~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

Viewing changes to src/sp-item-group.cpp

  • Committer: knutux
  • Date: 2006-04-20 16:06:59 UTC
  • Revision ID: knutux@users.sourceforge.net-20060420160659-vyt0xz1up0dcl9yb
SVG 1.1 Conditional Processing Module rendering support (<switch> element, requiredReatures/requiredExtensions/systemLanguage attributes).
Two more W3C SVG Test Suite testes pass after this change.

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
static void sp_group_init (SPGroup *group);
39
39
static void sp_group_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
40
40
static void sp_group_release(SPObject *object);
41
 
static void sp_group_dispose (GObject *object);
 
41
static void sp_group_dispose(GObject *object);
42
42
 
43
43
static void sp_group_child_added (SPObject * object, Inkscape::XML::Node * child, Inkscape::XML::Node * ref);
44
44
static void sp_group_remove_child (SPObject * object, Inkscape::XML::Node * child);
116
116
sp_group_init (SPGroup *group)
117
117
{
118
118
        group->_layer_mode = SPGroup::GROUP;
 
119
    group->group = new CGroup(group);
119
120
        new (&group->_display_modes) std::map<unsigned int, SPGroup::LayerMode>();
120
121
}
121
122
 
141
142
sp_group_dispose(GObject *object)
142
143
{
143
144
        SP_GROUP(object)->_display_modes.~map();
 
145
    delete SP_GROUP(object)->group;
144
146
}
145
147
 
146
148
static void
153
155
        if (((SPObjectClass *) (parent_class))->child_added)
154
156
                (* ((SPObjectClass *) (parent_class))->child_added) (object, child, ref);
155
157
 
156
 
    SPObject *last_child = object->lastChild();
157
 
    if (last_child && SP_OBJECT_REPR(last_child) == child) {
158
 
        // optimization for the common special case where the child is being added at the end
159
 
            SPObject *ochild = last_child;
160
 
            if ( SP_IS_ITEM(ochild) ) {
161
 
                    /* TODO: this should be moved into SPItem somehow */
162
 
                    SPItemView *v;
163
 
                    NRArenaItem *ac;
164
 
 
165
 
                    for (v = item->display; v != NULL; v = v->next) {
166
 
                            ac = sp_item_invoke_show (SP_ITEM (ochild), NR_ARENA_ITEM_ARENA (v->arenaitem), v->key, v->flags);
167
 
 
168
 
                            if (ac) {
169
 
                                    nr_arena_item_append_child (v->arenaitem, ac);
170
 
                                    nr_arena_item_unref (ac);
171
 
                            }
172
 
                    }
173
 
            }
174
 
    } else {    // general case
175
 
            SPObject *ochild = sp_object_get_child_by_repr(object, child);
176
 
            if ( ochild && SP_IS_ITEM(ochild) ) {
177
 
                    /* TODO: this should be moved into SPItem somehow */
178
 
                    SPItemView *v;
179
 
                    NRArenaItem *ac;
180
 
 
181
 
                    unsigned position = sp_item_pos_in_parent(SP_ITEM(ochild));
182
 
 
183
 
                    for (v = item->display; v != NULL; v = v->next) {
184
 
                            ac = sp_item_invoke_show (SP_ITEM (ochild), NR_ARENA_ITEM_ARENA (v->arenaitem), v->key, v->flags);
185
 
 
186
 
                            if (ac) {
187
 
                                    nr_arena_item_add_child (v->arenaitem, ac, NULL);
188
 
                                    nr_arena_item_set_order (ac, position);
189
 
                                    nr_arena_item_unref (ac);
190
 
                            }
191
 
                    }
192
 
            }
193
 
    }
194
 
 
195
 
        object->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
158
    SP_GROUP(object)->group->onChildAdded(child);
196
159
}
197
160
 
198
161
/* fixme: hide (Lauris) */
203
166
        if (((SPObjectClass *) (parent_class))->remove_child)
204
167
                (* ((SPObjectClass *) (parent_class))->remove_child) (object, child);
205
168
 
206
 
        object->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
169
    SP_GROUP(object)->group->onChildRemoved(child);
207
170
}
208
171
 
209
172
static void
212
175
        if (((SPObjectClass *) (parent_class))->order_changed)
213
176
                (* ((SPObjectClass *) (parent_class))->order_changed) (object, child, old_ref, new_ref);
214
177
 
215
 
        SPObject *ochild = sp_object_get_child_by_repr(object, child);
216
 
        if ( ochild && SP_IS_ITEM(ochild) ) {
217
 
                /* TODO: this should be moved into SPItem somehow */
218
 
                SPItemView *v;
219
 
                unsigned position = sp_item_pos_in_parent(SP_ITEM(ochild));
220
 
                for ( v = SP_ITEM (ochild)->display ; v != NULL ; v = v->next ) {
221
 
                        nr_arena_item_set_order (v->arenaitem, position);
222
 
                }
223
 
        }
224
 
 
225
 
        object->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
178
    SP_GROUP(object)->group->onOrderChanged(child, old_ref, new_ref);
226
179
}
227
180
 
228
181
static void
229
182
sp_group_update (SPObject *object, SPCtx *ctx, unsigned int flags)
230
183
{
231
 
        SPGroup *group;
232
 
        SPObject *child;
233
 
        SPItemCtx *ictx, cctx;
234
 
        GSList *l;
235
 
 
236
 
        group = SP_GROUP (object);
237
 
        ictx = (SPItemCtx *) ctx;
238
 
        cctx = *ictx;
239
 
 
240
 
        if (((SPObjectClass *) (parent_class))->update)
241
 
                ((SPObjectClass *) (parent_class))->update (object, ctx, flags);
242
 
 
243
 
        if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
244
 
        flags &= SP_OBJECT_MODIFIED_CASCADE;
245
 
 
246
 
        l = NULL;
247
 
        for (child = sp_object_first_child(object) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) {
248
 
                g_object_ref (G_OBJECT (child));
249
 
                l = g_slist_prepend (l, child);
250
 
        }
251
 
        l = g_slist_reverse (l);
252
 
        while (l) {
253
 
                child = SP_OBJECT (l->data);
254
 
                l = g_slist_remove (l, child);
255
 
                if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
256
 
                        if (SP_IS_ITEM (child)) {
257
 
                                SPItem const &chi = *SP_ITEM(child);
258
 
                                cctx.i2doc = chi.transform * ictx->i2doc;
259
 
                                cctx.i2vp = chi.transform * ictx->i2vp;
260
 
                                child->updateDisplay((SPCtx *)&cctx, flags);
261
 
                        } else {
262
 
                                child->updateDisplay(ctx, flags);
263
 
                        }
264
 
                }
265
 
                g_object_unref (G_OBJECT (child));
266
 
        }
 
184
    if (((SPObjectClass *) (parent_class))->update)
 
185
        ((SPObjectClass *) (parent_class))->update (object, ctx, flags);
 
186
 
 
187
    SP_GROUP(object)->group->onUpdate(ctx, flags);
267
188
}
268
189
 
269
190
static void
270
191
sp_group_modified (SPObject *object, guint flags)
271
192
{
272
 
        SPGroup *group;
273
 
        SPObject *child;
274
 
        GSList *l;
275
 
 
276
 
        group = SP_GROUP (object);
277
 
 
278
 
        if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
279
 
        flags &= SP_OBJECT_MODIFIED_CASCADE;
280
 
 
281
 
        l = NULL;
282
 
        for (child = sp_object_first_child(object) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) {
283
 
                g_object_ref (G_OBJECT (child));
284
 
                l = g_slist_prepend (l, child);
285
 
        }
286
 
        l = g_slist_reverse (l);
287
 
        while (l) {
288
 
                child = SP_OBJECT (l->data);
289
 
                l = g_slist_remove (l, child);
290
 
                if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
291
 
                        child->emitModified(flags);
292
 
                }
293
 
                g_object_unref (G_OBJECT (child));
294
 
        }
 
193
    SP_GROUP(object)->group->onModified(flags);
295
194
}
296
195
 
297
196
static Inkscape::XML::Node *
343
242
static void
344
243
sp_group_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const flags)
345
244
{
346
 
        for (SPObject *o = sp_object_first_child(SP_OBJECT(item)); o != NULL; o = SP_OBJECT_NEXT(o)) {
347
 
                if (SP_IS_ITEM(o)) {
348
 
                        SPItem *child = SP_ITEM(o);
349
 
                        NR::Matrix const ct(child->transform * transform);
350
 
                        sp_item_invoke_bbox_full(child, bbox, ct, flags, FALSE);
351
 
                }
352
 
        }
 
245
    SP_GROUP(item)->group->calculateBBox(bbox, transform, flags);
353
246
}
354
247
 
355
248
static void
356
249
sp_group_print (SPItem * item, SPPrintContext *ctx)
357
250
{
358
 
        SPGroup * group;
359
 
        SPItem * child;
360
 
        SPObject * o;
361
 
 
362
 
        group = SP_GROUP (item);
363
 
 
364
 
        for (o = sp_object_first_child(SP_OBJECT(item)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) {
365
 
                if (SP_IS_ITEM (o)) {
366
 
                        child = SP_ITEM (o);
367
 
                        sp_item_invoke_print (SP_ITEM (o), ctx);
368
 
                }
369
 
        }
 
251
    SP_GROUP(item)->group->onPrint(ctx);
370
252
}
371
253
 
372
254
static gchar * sp_group_description (SPItem * item)
373
255
{
374
 
        SPGroup * group;
375
 
        SPObject * o;
376
 
        gint len;
377
 
 
378
 
        group = SP_GROUP (item);
379
 
 
380
 
        len = 0;
381
 
        for ( o = sp_object_first_child(SP_OBJECT(item)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) {
382
 
                if (SP_IS_ITEM(o)) {
383
 
                        len += 1;
384
 
                }
385
 
        }
386
 
 
387
 
        return g_strdup_printf(
388
 
                        ngettext("<b>Group</b> of <b>%d</b> object",
389
 
                                 "<b>Group</b> of <b>%d</b> objects",
390
 
                                 len), len);
 
256
    return SP_GROUP(item)->group->getDescription();
391
257
}
392
258
 
393
259
static void sp_group_set(SPObject *object, unsigned key, char const *value) {
412
278
static NRArenaItem *
413
279
sp_group_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags)
414
280
{
415
 
        SPGroup *group;
416
 
        NRArenaItem *ai, *ac, *ar;
417
 
        SPItem * child;
418
 
        SPObject * o;
419
 
 
420
 
        group = (SPGroup *) item;
421
 
 
422
 
        ai = NRArenaGroup::create(arena);
423
 
        nr_arena_group_set_transparent(NR_ARENA_GROUP (ai),
424
 
                                       group->effectiveLayerMode(key) ==
425
 
                                         SPGroup::LAYER);
426
 
 
427
 
        ar = NULL;
428
 
 
429
 
        for (o = sp_object_first_child(SP_OBJECT(item)) ; o != NULL; o = SP_OBJECT_NEXT(o) ) {
430
 
                if (SP_IS_ITEM (o)) {
431
 
                        child = SP_ITEM (o);
432
 
                        ac = sp_item_invoke_show (child, arena, key, flags);
433
 
                        if (ac) {
434
 
                                nr_arena_item_add_child (ai, ac, ar);
435
 
                                ar = ac;
436
 
                                nr_arena_item_unref (ac);
437
 
                        }
438
 
                }
439
 
        }
440
 
 
441
 
        return ai;
 
281
    return SP_GROUP(item)->group->show(arena, key, flags);
442
282
}
443
283
 
444
284
static void
445
285
sp_group_hide (SPItem *item, unsigned int key)
446
286
{
447
 
        SPGroup * group;
448
 
        SPItem * child;
449
 
        SPObject * o;
450
 
 
451
 
        group = (SPGroup *) item;
452
 
 
453
 
        for (o = sp_object_first_child(SP_OBJECT(item)) ; o != NULL; o = SP_OBJECT_NEXT(o) ) {
454
 
                if (SP_IS_ITEM (o)) {
455
 
                        child = SP_ITEM (o);
456
 
                        sp_item_invoke_hide (child, key);
457
 
                }
458
 
        }
459
 
 
460
 
        if (((SPItemClass *) parent_class)->hide)
461
 
                ((SPItemClass *) parent_class)->hide (item, key);
 
287
    SP_GROUP(item)->group->hide(key);
462
288
}
463
289
 
464
290
static void sp_group_snappoints (SPItem const *item, SnapPointsIter p)
697
523
                }
698
524
        }
699
525
}
 
526
 
 
527
CGroup::CGroup(SPGroup *group) {
 
528
    _group = group;
 
529
}
 
530
 
 
531
CGroup::~CGroup() {
 
532
}
 
533
 
 
534
void CGroup::onChildAdded(Inkscape::XML::Node *child) {
 
535
    SPObject *last_child = _group->lastChild();
 
536
    if (last_child && SP_OBJECT_REPR(last_child) == child) {
 
537
        // optimization for the common special case where the child is being added at the end
 
538
        SPObject *ochild = last_child;
 
539
        if ( SP_IS_ITEM(ochild) ) {
 
540
            /* TODO: this should be moved into SPItem somehow */
 
541
            SPItemView *v;
 
542
            NRArenaItem *ac;
 
543
 
 
544
            for (v = _group->display; v != NULL; v = v->next) {
 
545
                ac = sp_item_invoke_show (SP_ITEM (ochild), NR_ARENA_ITEM_ARENA (v->arenaitem), v->key, v->flags);
 
546
 
 
547
                if (ac) {
 
548
                    nr_arena_item_append_child (v->arenaitem, ac);
 
549
                    nr_arena_item_unref (ac);
 
550
                }
 
551
            }
 
552
        }
 
553
    } else {    // general case
 
554
        SPObject *ochild = sp_object_get_child_by_repr(_group, child);
 
555
        if ( ochild && SP_IS_ITEM(ochild) ) {
 
556
            /* TODO: this should be moved into SPItem somehow */
 
557
            SPItemView *v;
 
558
            NRArenaItem *ac;
 
559
 
 
560
            unsigned position = sp_item_pos_in_parent(SP_ITEM(ochild));
 
561
 
 
562
            for (v = _group->display; v != NULL; v = v->next) {
 
563
                ac = sp_item_invoke_show (SP_ITEM (ochild), NR_ARENA_ITEM_ARENA (v->arenaitem), v->key, v->flags);
 
564
 
 
565
                if (ac) {
 
566
                    nr_arena_item_add_child (v->arenaitem, ac, NULL);
 
567
                    nr_arena_item_set_order (ac, position);
 
568
                    nr_arena_item_unref (ac);
 
569
                }
 
570
            }
 
571
        }
 
572
    }
 
573
 
 
574
    _group->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
575
}
 
576
 
 
577
void CGroup::onChildRemoved(Inkscape::XML::Node */*child*/) {
 
578
    _group->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
579
}
 
580
 
 
581
void CGroup::onUpdate(SPCtx *ctx, unsigned int flags) {    
 
582
    SPObject *child;
 
583
    SPItemCtx *ictx, cctx;
 
584
 
 
585
    ictx = (SPItemCtx *) ctx;
 
586
    cctx = *ictx;
 
587
 
 
588
    if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
 
589
    flags &= SP_OBJECT_MODIFIED_CASCADE;
 
590
 
 
591
    GSList *l = g_slist_reverse(_childList(true, ActionUpdate));
 
592
    while (l) {
 
593
        child = SP_OBJECT (l->data);
 
594
        l = g_slist_remove (l, child);
 
595
        if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
 
596
            if (SP_IS_ITEM (child)) {
 
597
                SPItem const &chi = *SP_ITEM(child);
 
598
                cctx.i2doc = chi.transform * ictx->i2doc;
 
599
                cctx.i2vp = chi.transform * ictx->i2vp;
 
600
                child->updateDisplay((SPCtx *)&cctx, flags);
 
601
            } else {
 
602
                child->updateDisplay(ctx, flags);
 
603
            }
 
604
        }
 
605
        g_object_unref (G_OBJECT (child));
 
606
    }
 
607
}
 
608
 
 
609
GSList *CGroup::_childList(bool add_ref, Action) {
 
610
    GSList *l = NULL;
 
611
    for (SPObject *child = sp_object_first_child(_group) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) {
 
612
        if (add_ref)
 
613
            g_object_ref (G_OBJECT (child));
 
614
 
 
615
        l = g_slist_prepend (l, child);
 
616
    }
 
617
    return l;
 
618
}
 
619
 
 
620
void CGroup::onModified(guint flags) {
 
621
    SPObject *child;
 
622
 
 
623
    if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
 
624
    flags &= SP_OBJECT_MODIFIED_CASCADE;
 
625
 
 
626
    GSList *l = g_slist_reverse(_childList(true));
 
627
    while (l) {
 
628
        child = SP_OBJECT (l->data);
 
629
        l = g_slist_remove (l, child);
 
630
        if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
 
631
            child->emitModified(flags);
 
632
        }
 
633
        g_object_unref (G_OBJECT (child));
 
634
    }
 
635
}
 
636
 
 
637
void CGroup::calculateBBox(NRRect *bbox, NR::Matrix const &transform, unsigned const flags) {
 
638
    GSList *l = _childList(false, ActionBBox);
 
639
    while (l) {
 
640
        SPObject *o = SP_OBJECT (l->data);
 
641
        if (SP_IS_ITEM(o)) {
 
642
            SPItem *child = SP_ITEM(o);
 
643
            NR::Matrix const ct(child->transform * transform);
 
644
            sp_item_invoke_bbox_full(child, bbox, ct, flags, FALSE);
 
645
        }        
 
646
        l = g_slist_remove (l, o);
 
647
    }
 
648
}
 
649
 
 
650
void CGroup::onPrint(SPPrintContext *ctx) {
 
651
    GSList *l = _childList(false);
 
652
    while (l) {
 
653
        SPObject *o = SP_OBJECT (l->data);
 
654
        if (SP_IS_ITEM(o)) {
 
655
            sp_item_invoke_print (SP_ITEM (o), ctx);
 
656
        }        
 
657
        l = g_slist_remove (l, o);
 
658
    }
 
659
}
 
660
 
 
661
gint CGroup::getItemCount() {
 
662
    gint len = 0;
 
663
    for (SPObject *o = sp_object_first_child(SP_OBJECT(_group)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) {
 
664
        if (SP_IS_ITEM(o)) {
 
665
            len++;
 
666
        }
 
667
    }
 
668
    
 
669
    return len;
 
670
}
 
671
 
 
672
gchar *CGroup::getDescription() {
 
673
    gint len = getItemCount();
 
674
    return g_strdup_printf(
 
675
            ngettext("<b>Group</b> of <b>%d</b> object",
 
676
                 "<b>Group</b> of <b>%d</b> objects",
 
677
                 len), len);
 
678
}
 
679
 
 
680
NRArenaItem *CGroup::show (NRArena *arena, unsigned int key, unsigned int flags) {
 
681
    NRArenaItem *ai;
 
682
 
 
683
    ai = NRArenaGroup::create(arena);
 
684
    nr_arena_group_set_transparent(NR_ARENA_GROUP (ai),
 
685
                                   _group->effectiveLayerMode(key) ==
 
686
                         SPGroup::LAYER);
 
687
 
 
688
    _showChildren(arena, ai, key, flags);
 
689
    return ai;
 
690
}
 
691
 
 
692
void CGroup::_showChildren (NRArena *arena, NRArenaItem *ai, unsigned int key, unsigned int flags) {
 
693
    NRArenaItem *ac = NULL;
 
694
    NRArenaItem *ar = NULL;
 
695
    SPItem * child = NULL;
 
696
    GSList *l = _childList(false, ActionShow);
 
697
    while (l) {
 
698
        SPObject *o = SP_OBJECT (l->data);
 
699
        if (SP_IS_ITEM (o)) {
 
700
            child = SP_ITEM (o);
 
701
            ac = sp_item_invoke_show (child, arena, key, flags);
 
702
            if (ac) {
 
703
                nr_arena_item_add_child (ai, ac, ar);
 
704
                ar = ac;
 
705
                nr_arena_item_unref (ac);
 
706
            }
 
707
        }
 
708
        l = g_slist_remove (l, o);
 
709
    }
 
710
}
 
711
 
 
712
void CGroup::hide (unsigned int key) {
 
713
    SPItem * child;
 
714
 
 
715
    GSList *l = _childList(false, ActionShow);
 
716
    while (l) {
 
717
        SPObject *o = SP_OBJECT (l->data);
 
718
        if (SP_IS_ITEM (o)) {
 
719
            child = SP_ITEM (o);
 
720
            sp_item_invoke_hide (child, key);
 
721
        }
 
722
        l = g_slist_remove (l, o);
 
723
    }
 
724
 
 
725
    if (((SPItemClass *) parent_class)->hide)
 
726
        ((SPItemClass *) parent_class)->hide (_group, key);
 
727
}
 
728
 
 
729
void CGroup::onOrderChanged (Inkscape::XML::Node *child, Inkscape::XML::Node *, Inkscape::XML::Node *)
 
730
{
 
731
    SPObject *ochild = sp_object_get_child_by_repr(_group, child);
 
732
    if ( ochild && SP_IS_ITEM(ochild) ) {
 
733
        /* TODO: this should be moved into SPItem somehow */
 
734
        SPItemView *v;
 
735
        unsigned position = sp_item_pos_in_parent(SP_ITEM(ochild));
 
736
        for ( v = SP_ITEM (ochild)->display ; v != NULL ; v = v->next ) {
 
737
            nr_arena_item_set_order (v->arenaitem, position);
 
738
        }
 
739
    }
 
740
 
 
741
    _group->requestModified(SP_OBJECT_MODIFIED_FLAG);
 
742
}