X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fknotholder.cpp;h=55a171414e58ee59144961b62c4cfd3e1f0734e9;hb=78e23de1b966743b030c38b1c654768736bae72b;hp=f78198275ee83bf6bdf5075d2818306b4a427f88;hpb=97a20864afec63a0b7bb757b628ee2ae596cf648;p=inkscape.git diff --git a/src/knotholder.cpp b/src/knotholder.cpp index f78198275..55a171414 100644 --- a/src/knotholder.cpp +++ b/src/knotholder.cpp @@ -30,10 +30,11 @@ #include "sp-pattern.h" #include "style.h" #include "live_effects/lpeobject.h" +#include "desktop.h" +#include "display/sp-canvas.h" #include "xml/repr.h" // for debugging only -#include #include class SPDesktop; @@ -54,23 +55,24 @@ KnotHolder::KnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFun this->repr = repr; this->local_change = FALSE; + + this->dragging = false; } KnotHolder::~KnotHolder() { g_object_unref(G_OBJECT(item)); for(std::list::iterator i = entity.begin(); i != entity.end(); ++i) { KnotHolderEntity* e = (*i); - if (!e->isLPEParam()) { - // knotholder entity may be deleted + if (e->isDeletable()) { delete (*i); } else { - // we must not delete the entity since it's an LPE parameter, + // we must not delete the entity (since it's attached to an LPE parameter), // but the handle should be destroyed g_object_unref(e->knot); } (*i) = NULL; } - entity.clear(); // this shouldn't be necessary, though + entity.clear(); // is this necessary? } /** @@ -80,7 +82,7 @@ KnotHolder::~KnotHolder() { void KnotHolder::update_knots() { - NR::Matrix const i2d(sp_item_i2d_affine(item)); + Geom::Matrix const i2d(sp_item_i2d_affine(item)); for(std::list::iterator i = entity.begin(); i != entity.end(); ++i) { KnotHolderEntity *e = *i; @@ -91,7 +93,7 @@ KnotHolder::update_knots() void KnotHolder::knot_clicked_handler(SPKnot *knot, guint state) { - KnotHolder *knot_holder = this; + KnotHolder *knot_holder = this; for(std::list::iterator i = knot_holder->entity.begin(); i != knot_holder->entity.end(); ++i) { KnotHolderEntity *e = *i; @@ -128,21 +130,25 @@ KnotHolder::knot_clicked_handler(SPKnot *knot, guint state) } // for drag, this is done by ungrabbed_handler, but for click we must do it here - sp_document_done(SP_OBJECT_DOCUMENT(item), object_verb, + sp_document_done(SP_OBJECT_DOCUMENT(item), object_verb, _("Change handle")); } void -KnotHolder::knot_moved_handler(SPKnot *knot, NR::Point const *p, guint state) +KnotHolder::knot_moved_handler(SPKnot *knot, Geom::Point const &p, guint state) { - // this was a local change and the knotholder does not need to be recreated: + if (this->dragging == false) { + this->dragging = true; + } + + // this was a local change and the knotholder does not need to be recreated: this->local_change = TRUE; for(std::list::iterator i = this->entity.begin(); i != this->entity.end(); ++i) { KnotHolderEntity *e = *i; if (e->knot == knot) { - NR::Point const q = *p / sp_item_i2d_affine(item); - e->knot_set(q, e->knot->drag_origin / sp_item_i2d_affine(item), state); + Geom::Point const q = p * sp_item_i2d_affine(item).inverse(); + e->knot_set(q, e->knot->drag_origin * sp_item_i2d_affine(item).inverse(), state); break; } } @@ -155,34 +161,34 @@ KnotHolder::knot_moved_handler(SPKnot *knot, NR::Point const *p, guint state) } void -KnotHolder::knot_ungrabbed_handler(SPKnot *knot) +KnotHolder::knot_ungrabbed_handler(SPKnot */*knot*/) { - if (this->released) { + this->dragging = false; + + if (this->released) { this->released(this->item); } else { SPObject *object = (SPObject *) this->item; - object->updateRepr(object->repr, SP_OBJECT_WRITE_EXT); + + // Caution: this call involves a screen update, which may process events, and as a + // result the knotholder may be destructed. So, after the updateRepr, we cannot use any + // fields of this knotholder (such as this->item), but only values we have saved beforehand + // (such as object). + object->updateRepr(); /* do cleanup tasks (e.g., for LPE items write the parameter values * that were changed by dragging the handle to SVG) */ - if (SP_IS_LPE_ITEM(item)) { - // This writes all parameters to SVG. Is this sufficiently efficient or should we only write - // the ones that were changed (e.g., via the individual handles' onKnotUngrabbed() method? - Inkscape::LivePathEffect::Effect *lpe = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)); + if (SP_IS_LPE_ITEM(object)) { + // This writes all parameters to SVG. Is this sufficiently efficient or should we only + // write the ones that were changed? + + Inkscape::LivePathEffect::Effect *lpe = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(object)); if (lpe) { LivePathEffectObject *lpeobj = lpe->getLPEObj(); SP_OBJECT(lpeobj)->updateRepr(); } } - // this was once used to write individual parameter values to SVG but this is now done globally above; - // we leave the calls to onKnotUngrabbed, anyway, in case any other cleanup tasks need to be done - for(std::list::iterator i = this->entity.begin(); i != this->entity.end(); ++i) { - KnotHolderEntity *e = *i; - if (e->knot == knot) { - e->onKnotUngrabbed(); // for most KnotHolderEntitys this does nothing - } - } unsigned int object_verb = SP_VERB_NONE; @@ -202,7 +208,7 @@ KnotHolder::knot_ungrabbed_handler(SPKnot *knot) else object_verb = SP_VERB_SELECTION_DYNAMIC_OFFSET; } - + sp_document_done(SP_OBJECT_DOCUMENT (object), object_verb, _("Move handle")); } @@ -227,10 +233,10 @@ KnotHolder::add_pattern_knotholder() // TRANSLATORS: This refers to the pattern that's inside the object _("Move the pattern fill inside the object"), SP_KNOT_SHAPE_CROSS); - entity_angle->create(desktop, item, this, + entity_scale->create(desktop, item, this, _("Scale the pattern fill uniformly"), SP_KNOT_SHAPE_SQUARE, SP_KNOT_MODE_XOR); - entity_scale->create(desktop, item, this, + entity_angle->create(desktop, item, this, _("Rotate the pattern fill; with Ctrl to snap angle"), SP_KNOT_SHAPE_CIRCLE, SP_KNOT_MODE_XOR); entity.push_back(entity_xy);