X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsp-item-group.cpp;h=f73bc26002874e08e37e9874e300d21d0e78e5d1;hb=5e8a08857af3a55929109a0e6eaf5a149b4b6e1c;hp=a2be6daf427e8f05d9b81a00435f5ce9cfc41def;hpb=1391834bee278d740c12201a5f258cd1eda044c1;p=inkscape.git diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index a2be6daf4..f73bc2600 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -6,8 +6,9 @@ * Authors: * Lauris Kaplinski * bulia byak + * Johan Engelen * - * Copyright (C) 1999-2005 authors + * Copyright (C) 1999-2006 authors * Copyright (C) 2000-2001 Ximian, Inc. * * Released under GNU GPL, read the file 'COPYING' for more information @@ -17,9 +18,7 @@ # include "config.h" #endif -#if defined(WIN32) || defined(__APPLE__) -# include -#endif +#include #include "display/nr-arena-group.h" #include "libnr/nr-matrix-ops.h" @@ -29,16 +28,18 @@ #include "document.h" #include "style.h" #include "attributes.h" - +#include "sp-item-transform.h" #include "sp-root.h" #include "sp-use.h" #include "prefs-utils.h" +#include "sp-clippath.h" +#include "sp-mask.h" static void sp_group_class_init (SPGroupClass *klass); static void sp_group_init (SPGroup *group); static void sp_group_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); static void sp_group_release(SPObject *object); -static void sp_group_dispose (GObject *object); +static void sp_group_dispose(GObject *object); static void sp_group_child_added (SPObject * object, Inkscape::XML::Node * child, Inkscape::XML::Node * ref); static void sp_group_remove_child (SPObject * object, Inkscape::XML::Node * child); @@ -116,6 +117,7 @@ static void sp_group_init (SPGroup *group) { group->_layer_mode = SPGroup::GROUP; + group->group = new CGroup(group); new (&group->_display_modes) std::map(); } @@ -141,6 +143,7 @@ static void sp_group_dispose(GObject *object) { SP_GROUP(object)->_display_modes.~map(); + delete SP_GROUP(object)->group; } static void @@ -153,46 +156,7 @@ sp_group_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XM if (((SPObjectClass *) (parent_class))->child_added) (* ((SPObjectClass *) (parent_class))->child_added) (object, child, ref); - SPObject *last_child = object->lastChild(); - if (last_child && SP_OBJECT_REPR(last_child) == child) { - // optimization for the common special case where the child is being added at the end - SPObject *ochild = last_child; - if ( SP_IS_ITEM(ochild) ) { - /* TODO: this should be moved into SPItem somehow */ - SPItemView *v; - NRArenaItem *ac; - - for (v = item->display; v != NULL; v = v->next) { - ac = sp_item_invoke_show (SP_ITEM (ochild), NR_ARENA_ITEM_ARENA (v->arenaitem), v->key, v->flags); - - if (ac) { - nr_arena_item_append_child (v->arenaitem, ac); - nr_arena_item_unref (ac); - } - } - } - } else { // general case - SPObject *ochild = sp_object_get_child_by_repr(object, child); - if ( ochild && SP_IS_ITEM(ochild) ) { - /* TODO: this should be moved into SPItem somehow */ - SPItemView *v; - NRArenaItem *ac; - - unsigned position = sp_item_pos_in_parent(SP_ITEM(ochild)); - - for (v = item->display; v != NULL; v = v->next) { - ac = sp_item_invoke_show (SP_ITEM (ochild), NR_ARENA_ITEM_ARENA (v->arenaitem), v->key, v->flags); - - if (ac) { - nr_arena_item_add_child (v->arenaitem, ac, NULL); - nr_arena_item_set_order (ac, position); - nr_arena_item_unref (ac); - } - } - } - } - - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + SP_GROUP(object)->group->onChildAdded(child); } /* fixme: hide (Lauris) */ @@ -203,7 +167,7 @@ sp_group_remove_child (SPObject * object, Inkscape::XML::Node * child) if (((SPObjectClass *) (parent_class))->remove_child) (* ((SPObjectClass *) (parent_class))->remove_child) (object, child); - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + SP_GROUP(object)->group->onChildRemoved(child); } static void @@ -212,86 +176,22 @@ sp_group_order_changed (SPObject *object, Inkscape::XML::Node *child, Inkscape:: if (((SPObjectClass *) (parent_class))->order_changed) (* ((SPObjectClass *) (parent_class))->order_changed) (object, child, old_ref, new_ref); - SPObject *ochild = sp_object_get_child_by_repr(object, child); - if ( ochild && SP_IS_ITEM(ochild) ) { - /* TODO: this should be moved into SPItem somehow */ - SPItemView *v; - unsigned position = sp_item_pos_in_parent(SP_ITEM(ochild)); - for ( v = SP_ITEM (ochild)->display ; v != NULL ; v = v->next ) { - nr_arena_item_set_order (v->arenaitem, position); - } - } - - object->requestModified(SP_OBJECT_MODIFIED_FLAG); + SP_GROUP(object)->group->onOrderChanged(child, old_ref, new_ref); } static void sp_group_update (SPObject *object, SPCtx *ctx, unsigned int flags) { - SPGroup *group; - SPObject *child; - SPItemCtx *ictx, cctx; - GSList *l; - - group = SP_GROUP (object); - ictx = (SPItemCtx *) ctx; - cctx = *ictx; - - if (((SPObjectClass *) (parent_class))->update) - ((SPObjectClass *) (parent_class))->update (object, ctx, flags); + if (((SPObjectClass *) (parent_class))->update) + ((SPObjectClass *) (parent_class))->update (object, ctx, flags); - if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; - flags &= SP_OBJECT_MODIFIED_CASCADE; - - l = NULL; - for (child = sp_object_first_child(object) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) { - g_object_ref (G_OBJECT (child)); - l = g_slist_prepend (l, child); - } - l = g_slist_reverse (l); - while (l) { - child = SP_OBJECT (l->data); - l = g_slist_remove (l, child); - if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - if (SP_IS_ITEM (child)) { - SPItem const &chi = *SP_ITEM(child); - cctx.i2doc = chi.transform * ictx->i2doc; - cctx.i2vp = chi.transform * ictx->i2vp; - child->updateDisplay((SPCtx *)&cctx, flags); - } else { - child->updateDisplay(ctx, flags); - } - } - g_object_unref (G_OBJECT (child)); - } + SP_GROUP(object)->group->onUpdate(ctx, flags); } static void sp_group_modified (SPObject *object, guint flags) { - SPGroup *group; - SPObject *child; - GSList *l; - - group = SP_GROUP (object); - - if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; - flags &= SP_OBJECT_MODIFIED_CASCADE; - - l = NULL; - for (child = sp_object_first_child(object) ; child != NULL ; child = SP_OBJECT_NEXT(child) ) { - g_object_ref (G_OBJECT (child)); - l = g_slist_prepend (l, child); - } - l = g_slist_reverse (l); - while (l) { - child = SP_OBJECT (l->data); - l = g_slist_remove (l, child); - if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { - child->emitModified(flags); - } - g_object_unref (G_OBJECT (child)); - } + SP_GROUP(object)->group->onModified(flags); } static Inkscape::XML::Node * @@ -305,7 +205,10 @@ sp_group_write (SPObject *object, Inkscape::XML::Node *repr, guint flags) if (flags & SP_OBJECT_WRITE_BUILD) { GSList *l; - if (!repr) repr = sp_repr_new ("svg:g"); + if (!repr) { + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object)); + repr = xml_doc->createElement("svg:g"); + } l = NULL; for (child = sp_object_first_child(object); child != NULL; child = SP_OBJECT_NEXT(child) ) { crepr = child->updateRepr(NULL, flags); @@ -343,51 +246,18 @@ sp_group_write (SPObject *object, Inkscape::XML::Node *repr, guint flags) static void sp_group_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const flags) { - for (SPObject *o = sp_object_first_child(SP_OBJECT(item)); o != NULL; o = SP_OBJECT_NEXT(o)) { - if (SP_IS_ITEM(o)) { - SPItem *child = SP_ITEM(o); - NR::Matrix const ct(child->transform * transform); - sp_item_invoke_bbox_full(child, bbox, ct, flags, FALSE); - } - } + SP_GROUP(item)->group->calculateBBox(bbox, transform, flags); } static void sp_group_print (SPItem * item, SPPrintContext *ctx) { - SPGroup * group; - SPItem * child; - SPObject * o; - - group = SP_GROUP (item); - - for (o = sp_object_first_child(SP_OBJECT(item)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) { - if (SP_IS_ITEM (o)) { - child = SP_ITEM (o); - sp_item_invoke_print (SP_ITEM (o), ctx); - } - } + SP_GROUP(item)->group->onPrint(ctx); } static gchar * sp_group_description (SPItem * item) { - SPGroup * group; - SPObject * o; - gint len; - - group = SP_GROUP (item); - - len = 0; - for ( o = sp_object_first_child(SP_OBJECT(item)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) { - if (SP_IS_ITEM(o)) { - len += 1; - } - } - - return g_strdup_printf( - ngettext("Group of %d object", - "Group of %d objects", - len), len); + return SP_GROUP(item)->group->getDescription(); } static void sp_group_set(SPObject *object, unsigned key, char const *value) { @@ -412,53 +282,13 @@ static void sp_group_set(SPObject *object, unsigned key, char const *value) { static NRArenaItem * sp_group_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags) { - SPGroup *group; - NRArenaItem *ai, *ac, *ar; - SPItem * child; - SPObject * o; - - group = (SPGroup *) item; - - ai = NRArenaGroup::create(arena); - nr_arena_group_set_transparent(NR_ARENA_GROUP (ai), - group->effectiveLayerMode(key) == - SPGroup::LAYER); - - ar = NULL; - - for (o = sp_object_first_child(SP_OBJECT(item)) ; o != NULL; o = SP_OBJECT_NEXT(o) ) { - if (SP_IS_ITEM (o)) { - child = SP_ITEM (o); - ac = sp_item_invoke_show (child, arena, key, flags); - if (ac) { - nr_arena_item_add_child (ai, ac, ar); - ar = ac; - nr_arena_item_unref (ac); - } - } - } - - return ai; + return SP_GROUP(item)->group->show(arena, key, flags); } static void sp_group_hide (SPItem *item, unsigned int key) { - SPGroup * group; - SPItem * child; - SPObject * o; - - group = (SPGroup *) item; - - for (o = sp_object_first_child(SP_OBJECT(item)) ; o != NULL; o = SP_OBJECT_NEXT(o) ) { - if (SP_IS_ITEM (o)) { - child = SP_ITEM (o); - sp_item_invoke_hide (child, key); - } - } - - if (((SPItemClass *) parent_class)->hide) - ((SPItemClass *) parent_class)->hide (item, key); + SP_GROUP(item)->group->hide(key); } static void sp_group_snappoints (SPItem const *item, SnapPointsIter p) @@ -557,12 +387,9 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) // This is just a way to temporarily remember the transform in repr. When repr is // reattached outside of the group, the transform will be written more properly // (i.e. optimized into the object if the corresponding preference is set) - gchar affinestr[80]; - if (sp_svg_transform_write(affinestr, 79, ctrans)) { - nrepr->setAttribute("transform", affinestr); - } else { - nrepr->setAttribute("transform", NULL); - } + gchar *affinestr=sp_svg_transform_write(ctrans); + nrepr->setAttribute("transform", affinestr); + g_free(affinestr); items = g_slist_prepend (items, nrepr); @@ -590,7 +417,6 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) } /* Step 4 - add items */ - gint const preserve = prefs_get_int_attribute("options.preservetransform", "value", 0); while (items) { Inkscape::XML::Node *repr = (Inkscape::XML::Node *) items->data; // add item @@ -600,26 +426,19 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) repr->setPosition(pos > 0 ? pos : 0); // fill in the children list if non-null - SPItem *nitem = (SPItem *) doc->getObjectByRepr(repr); - - /* Optimize the transform matrix if requested. */ - // No compensations are required because this is supposed to be a non-transformation visually. - if (!preserve) { - NR::Matrix (*set_transform)(SPItem *, NR::Matrix const &) = ((SPItemClass *) G_OBJECT_GET_CLASS(nitem))->set_transform; - if (set_transform) { - sp_item_set_item_transform(nitem, set_transform(nitem, nitem->transform)); - nitem->updateRepr(); - } - } + SPItem *item = (SPItem *) doc->getObjectByRepr(repr); + sp_item_write_transform(item, repr, item->transform, NULL, false); + Inkscape::GC::release(repr); - if (children && SP_IS_ITEM (nitem)) - *children = g_slist_prepend (*children, nitem); + if (children && SP_IS_ITEM (item)) + *children = g_slist_prepend (*children, item); items = g_slist_remove (items, items->data); } - if (do_done) sp_document_done (doc); + if (do_done) + sp_document_done (doc, SP_VERB_NONE, _("Ungroup")); } /* @@ -697,3 +516,252 @@ void SPGroup::_updateLayerMode(unsigned int display_key) { } } } + +void SPGroup::translateChildItems(NR::translate const &tr) +{ + if (this->hasChildren()) + { + SPObject *o = NULL; + for (o = sp_object_first_child(SP_OBJECT(this)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) { + if (SP_IS_ITEM (o)) { + sp_item_move_rel(static_cast(o), tr); + } + } + } +} + +CGroup::CGroup(SPGroup *group) { + _group = group; +} + +CGroup::~CGroup() { +} + +void CGroup::onChildAdded(Inkscape::XML::Node *child) { + SPObject *last_child = _group->lastChild(); + if (last_child && SP_OBJECT_REPR(last_child) == child) { + // optimization for the common special case where the child is being added at the end + SPObject *ochild = last_child; + if ( SP_IS_ITEM(ochild) ) { + /* TODO: this should be moved into SPItem somehow */ + SPItemView *v; + NRArenaItem *ac; + + for (v = _group->display; v != NULL; v = v->next) { + ac = sp_item_invoke_show (SP_ITEM (ochild), NR_ARENA_ITEM_ARENA (v->arenaitem), v->key, v->flags); + + if (ac) { + nr_arena_item_append_child (v->arenaitem, ac); + nr_arena_item_unref (ac); + } + } + } + } else { // general case + SPObject *ochild = sp_object_get_child_by_repr(_group, child); + if ( ochild && SP_IS_ITEM(ochild) ) { + /* TODO: this should be moved into SPItem somehow */ + SPItemView *v; + NRArenaItem *ac; + + unsigned position = sp_item_pos_in_parent(SP_ITEM(ochild)); + + for (v = _group->display; v != NULL; v = v->next) { + ac = sp_item_invoke_show (SP_ITEM (ochild), NR_ARENA_ITEM_ARENA (v->arenaitem), v->key, v->flags); + + if (ac) { + nr_arena_item_add_child (v->arenaitem, ac, NULL); + nr_arena_item_set_order (ac, position); + nr_arena_item_unref (ac); + } + } + } + } + + _group->requestModified(SP_OBJECT_MODIFIED_FLAG); +} + +void CGroup::onChildRemoved(Inkscape::XML::Node */*child*/) { + _group->requestModified(SP_OBJECT_MODIFIED_FLAG); +} + +void CGroup::onUpdate(SPCtx *ctx, unsigned int flags) { + SPItemCtx *ictx, cctx; + + ictx = (SPItemCtx *) ctx; + cctx = *ictx; + + if (flags & SP_OBJECT_MODIFIED_FLAG) { + flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + } + + flags &= SP_OBJECT_MODIFIED_CASCADE; + + if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { + SPObject *object = SP_OBJECT(_group); + for (SPItemView *v = SP_ITEM(_group)->display; v != NULL; v = v->next) { + nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); + } + } + + GSList *l = g_slist_reverse(_group->childList(true, SPObject::ActionUpdate)); + while (l) { + SPObject *child = SP_OBJECT (l->data); + l = g_slist_remove (l, child); + if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + if (SP_IS_ITEM (child)) { + SPItem const &chi = *SP_ITEM(child); + cctx.i2doc = chi.transform * ictx->i2doc; + cctx.i2vp = chi.transform * ictx->i2vp; + child->updateDisplay((SPCtx *)&cctx, flags); + } else { + child->updateDisplay(ctx, flags); + } + } + g_object_unref (G_OBJECT (child)); + } +} + +void CGroup::onModified(guint flags) { + SPObject *child; + + if (flags & SP_OBJECT_MODIFIED_FLAG) flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; + flags &= SP_OBJECT_MODIFIED_CASCADE; + + if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { + SPObject *object = SP_OBJECT(_group); + for (SPItemView *v = SP_ITEM(_group)->display; v != NULL; v = v->next) { + nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); + } + } + + GSList *l = g_slist_reverse(_group->childList(true)); + while (l) { + child = SP_OBJECT (l->data); + l = g_slist_remove (l, child); + if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + child->emitModified(flags); + } + g_object_unref (G_OBJECT (child)); + } +} + +void CGroup::calculateBBox(NRRect *bbox, NR::Matrix const &transform, unsigned const flags) { + GSList *l = _group->childList(false, SPObject::ActionBBox); + while (l) { + SPObject *o = SP_OBJECT (l->data); + if (SP_IS_ITEM(o)) { + SPItem *child = SP_ITEM(o); + NR::Matrix const ct(child->transform * transform); + sp_item_invoke_bbox_full(child, bbox, ct, flags, FALSE); + } + l = g_slist_remove (l, o); + } +} + +void CGroup::onPrint(SPPrintContext *ctx) { + GSList *l = g_slist_reverse(_group->childList(false)); + while (l) { + SPObject *o = SP_OBJECT (l->data); + if (SP_IS_ITEM(o)) { + sp_item_invoke_print (SP_ITEM (o), ctx); + } + l = g_slist_remove (l, o); + } +} + +gint CGroup::getItemCount() { + gint len = 0; + for (SPObject *o = sp_object_first_child(SP_OBJECT(_group)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) { + if (SP_IS_ITEM(o)) { + len++; + } + } + + return len; +} + +gchar *CGroup::getDescription() { + gint len = getItemCount(); + return g_strdup_printf( + ngettext("Group of %d object", + "Group of %d objects", + len), len); +} + +NRArenaItem *CGroup::show (NRArena *arena, unsigned int key, unsigned int flags) { + NRArenaItem *ai; + SPObject *object = SP_OBJECT(_group); + + ai = NRArenaGroup::create(arena); + + nr_arena_group_set_transparent(NR_ARENA_GROUP (ai), + _group->effectiveLayerMode(key) == + SPGroup::LAYER); + nr_arena_group_set_style(NR_ARENA_GROUP(ai), SP_OBJECT_STYLE(object)); + + _showChildren(arena, ai, key, flags); + return ai; +} + +void CGroup::_showChildren (NRArena *arena, NRArenaItem *ai, unsigned int key, unsigned int flags) { + NRArenaItem *ac = NULL; + NRArenaItem *ar = NULL; + SPItem * child = NULL; + GSList *l = g_slist_reverse(_group->childList(false, SPObject::ActionShow)); + while (l) { + SPObject *o = SP_OBJECT (l->data); + if (SP_IS_ITEM (o)) { + child = SP_ITEM (o); + ac = sp_item_invoke_show (child, arena, key, flags); + if (ac) { + nr_arena_item_add_child (ai, ac, ar); + ar = ac; + nr_arena_item_unref (ac); + } + } + l = g_slist_remove (l, o); + } +} + +void CGroup::hide (unsigned int key) { + SPItem * child; + + GSList *l = g_slist_reverse(_group->childList(false, SPObject::ActionShow)); + while (l) { + SPObject *o = SP_OBJECT (l->data); + if (SP_IS_ITEM (o)) { + child = SP_ITEM (o); + sp_item_invoke_hide (child, key); + } + l = g_slist_remove (l, o); + } + + if (((SPItemClass *) parent_class)->hide) + ((SPItemClass *) parent_class)->hide (_group, key); +} + +void CGroup::onOrderChanged (Inkscape::XML::Node *child, Inkscape::XML::Node *, Inkscape::XML::Node *) +{ + SPObject *ochild = sp_object_get_child_by_repr(_group, child); + if ( ochild && SP_IS_ITEM(ochild) ) { + /* TODO: this should be moved into SPItem somehow */ + SPItemView *v; + unsigned position = sp_item_pos_in_parent(SP_ITEM(ochild)); + for ( v = SP_ITEM (ochild)->display ; v != NULL ; v = v->next ) { + nr_arena_item_set_order (v->arenaitem, position); + } + } + + _group->requestModified(SP_OBJECT_MODIFIED_FLAG); +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :