X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fshape-editor.cpp;h=91909d8505fdae651ef80a5a552d3d7c4c972889;hb=8d358698ecbf192ba7c6dc05d4f7de7592753d9f;hp=d9a500e3c463cb2dd03a70c56cd181077010fec8;hpb=2f99f08590b9e75d4c4f33cc4374db3e8f97f15d;p=inkscape.git diff --git a/src/shape-editor.cpp b/src/shape-editor.cpp index d9a500e3c..91909d850 100644 --- a/src/shape-editor.cpp +++ b/src/shape-editor.cpp @@ -12,14 +12,17 @@ #include "config.h" #endif +#include #include #include "sp-object.h" #include "sp-item.h" +#include "live_effects/lpeobject.h" #include "selection.h" #include "desktop.h" #include "desktop-handles.h" #include "knotholder.h" +#include "live_effects/parameter/pointparam-knotholder.h" #include "node-context.h" #include "xml/node-event-vector.h" #include "prefs-utils.h" @@ -30,7 +33,7 @@ #include "shape-editor.h" -ShapeEditorsCollective::ShapeEditorsCollective(SPDesktop *dt) { +ShapeEditorsCollective::ShapeEditorsCollective(SPDesktop */*dt*/) { } ShapeEditorsCollective::~ShapeEditorsCollective() { @@ -79,7 +82,7 @@ void ShapeEditor::unset_item() { } if (this->knotholder) { - sp_knot_holder_destroy(this->knotholder); + delete this->knotholder; this->knotholder = NULL; } } @@ -93,18 +96,13 @@ bool ShapeEditor::has_knotholder () { } bool ShapeEditor::has_local_change () { - if (this->nodepath) - return (this->nodepath->local_change != 0); - else if (this->knotholder) - return (this->knotholder->local_change != 0); - else - return false; + return ((this->nodepath && this->nodepath->local_change) || + (this->knotholder && this->knotholder->local_change != 0)); } void ShapeEditor::decrement_local_change () { - if (this->nodepath) { - if (this->nodepath->local_change > 0) - this->nodepath->local_change--; + if (this->nodepath && this->nodepath->local_change > 0) { + this->nodepath->local_change--; } else if (this->knotholder) { this->knotholder->local_change = FALSE; } @@ -113,7 +111,7 @@ void ShapeEditor::decrement_local_change () { SPItem *ShapeEditor::get_item () { SPItem *item = NULL; if (this->has_nodepath()) { - item = SP_ITEM(this->nodepath->object); + item = this->nodepath->item; } else if (this->has_knotholder()) { item = SP_ITEM(this->knotholder->item); } @@ -131,23 +129,26 @@ void ShapeEditor::restore_nodepath_selection (GList *saved) { ::restore_nodepath_selection (this->nodepath, saved); } +bool ShapeEditor::nodepath_edits_repr_key(gchar const *name) { + if (nodepath && name) { + return ( !strcmp(name, nodepath->repr_key) || !strcmp(name, nodepath->repr_nodetypes_key) ); + } + + return false; +} -static void shapeeditor_event_attr_changed(Inkscape::XML::Node *repr, gchar const *name, - gchar const *old_value, gchar const *new_value, - bool is_interactive, gpointer data) +static void shapeeditor_event_attr_changed(Inkscape::XML::Node */*repr*/, gchar const *name, + gchar const */*old_value*/, gchar const */*new_value*/, + bool /*is_interactive*/, gpointer data) { - SPItem *item = NULL; gboolean changed = FALSE; g_assert(data); ShapeEditor *sh = ((ShapeEditor *) data); - item = sh->get_item(); - - if ( - ((sh->has_nodepath()) && (!strcmp(name, "d") || !strcmp(name, "sodipodi:nodetypes"))) // With paths, we only need to act if one of the path-affecting attributes has changed. - || sh->has_knotholder()) { - changed = !sh->has_local_change(); + if ( sh->has_knotholder() || ( sh->has_nodepath() && sh->nodepath_edits_repr_key(name) ) ) + { + changed = !sh->has_local_change(); sh->decrement_local_change(); } @@ -157,7 +158,7 @@ static void shapeeditor_event_attr_changed(Inkscape::XML::Node *repr, gchar cons saved = sh->save_nodepath_selection(); } - sh->set_item (item); + sh->reset_item (); if (sh->has_nodepath() && saved) { sh->restore_nodepath_selection(saved); @@ -184,9 +185,21 @@ void ShapeEditor::set_item(SPItem *item) { this->grab_node = -1; if (item) { - this->nodepath = sp_nodepath_new(desktop, item, (prefs_get_int_attribute("tools.nodes", "show_handles", 1) != 0)); + if (SP_IS_LPE_ITEM(item)) { + SPLPEItem *lpeitem = SP_LPE_ITEM(item); + Inkscape::LivePathEffect::Effect *lpe = sp_lpe_item_get_current_lpe(lpeitem); + if (!(lpe && lpe->isVisible() && lpe->providesKnotholder())) { + // only create nodepath if the item either doesn't have an LPE + // or the LPE is invisible or it doesn't provide a knotholder itself + this->nodepath = sp_nodepath_new(desktop, item, + (prefs_get_int_attribute("tools.nodes", "show_handles", 1) != 0)); + } else if (lpe && lpe->isVisible()) { + sp_lpe_item_add_temporary_canvasitems(lpeitem, desktop); + } + } + if (this->nodepath) { - this->nodepath->shape_editor = this; + this->nodepath->shape_editor = this; } this->knotholder = sp_item_knot_holder(item, desktop); @@ -205,29 +218,24 @@ void ShapeEditor::set_item(SPItem *item) { } } -void ShapeEditor::set_livepatheffect_parameter(SPObject *lpeobject, const char * key) { - +/** Please note that this function only works for path parameters. +* All other parameters probably will crash Inkscape! +*/ +void ShapeEditor::set_item_lpe_path_parameter(SPItem *item, SPObject *lpeobject, const char * key) +{ unset_item(); this->grab_node = -1; if (lpeobject) { - this->nodepath = sp_nodepath_new( desktop, lpeobject, + this->nodepath = sp_nodepath_new( desktop, lpeobject, (prefs_get_int_attribute("tools.nodes", "show_handles", 1) != 0), - key); + key, item); if (this->nodepath) { - this->nodepath->shape_editor = this; - } - //this->knotholder = sp_item_knot_holder(item, desktop); - g_message("create knotholder?"); + this->nodepath->shape_editor = this; - if (this->nodepath || this->knotholder) { // setting new listener - Inkscape::XML::Node *repr; - if (this->knotholder) - repr = this->knotholder->repr; - else - repr = SP_OBJECT_REPR(lpeobject); + Inkscape::XML::Node *repr = SP_OBJECT_REPR(lpeobject); if (repr) { Inkscape::GC::anchor(repr); sp_repr_add_listener(repr, &shapeeditor_repr_events, this); @@ -236,6 +244,38 @@ void ShapeEditor::set_livepatheffect_parameter(SPObject *lpeobject, const char * } } +/** +* pass a new knotholder to ShapeEditor to manage (and delete) +*/ +void +ShapeEditor::set_knotholder(KnotHolder * knot_holder) +{ + unset_item(); + + this->grab_node = -1; + + if (knot_holder) { + this->knotholder = knot_holder; + } +} + + +/** FIXME: think about this. Is this thing only called when the item needs to be updated? + Why not make a reload function in NodePath and in KnotHolder? */ +void ShapeEditor::reset_item () +{ + if ( (this->nodepath) && (IS_LIVEPATHEFFECT(this->nodepath->object)) ) { + SPItem * item = this->nodepath->item; + SPObject *obj = this->nodepath->object; + char * key = g_strdup(this->nodepath->repr_key); + set_item_lpe_path_parameter(item, obj, key); // the above checks for nodepath, so it is indeed a path that we are editing + g_free(key); + } else { + SPItem * item = get_item(); + set_item(item); + } +} + void ShapeEditor::nodepath_destroyed () { this->nodepath = NULL; } @@ -247,14 +287,14 @@ void ShapeEditor::update_statusbar () { bool ShapeEditor::is_over_stroke (NR::Point event_p, bool remember) { - if (!this->nodepath) + if (!this->nodepath) return false; // no stroke in knotholder SPItem *item = get_item(); //Translate click point into proper coord system this->curvepoint_doc = desktop->w2d(event_p); - this->curvepoint_doc *= sp_item_dt2i_affine(item); + this->curvepoint_doc *= from_2geom(sp_item_dt2i_affine(item)); sp_nodepath_ensure_livarot_path(this->nodepath); @@ -269,13 +309,12 @@ bool ShapeEditor::is_over_stroke (NR::Point event_p, bool remember) { delta = desktop->d2w(delta); double stroke_tolerance = - ( !SP_OBJECT_STYLE(item)->stroke.isNone() ? - desktop->current_zoom() * - SP_OBJECT_STYLE (item)->stroke_width.computed * - sp_item_i2d_affine (item).expansion() * 0.5 + (( !SP_OBJECT_STYLE(item)->stroke.isNone() ? + desktop->current_zoom() * + SP_OBJECT_STYLE (item)->stroke_width.computed * 0.5 * + NR::expansion(from_2geom(sp_item_i2d_affine(item))) : 0.0) - + prefs_get_int_attribute_limited("options.dragtolerance", "value", 0, 0, 100); //(double) SP_EVENT_CONTEXT(nc)->tolerance; - + + prefs_get_int_attribute_limited("options.dragtolerance", "value", 0, 0, 100)) /NR::expansion(from_2geom(sp_item_i2d_affine(item))); bool close = (NR::L2 (delta) < stroke_tolerance); if (remember && close) { @@ -434,39 +473,51 @@ void ShapeEditor::scale_nodes_screen(gdouble const grow, int const which) { } void ShapeEditor::select_all (bool invert) { - if (this->nodepath) + if (this->nodepath) sp_nodepath_select_all (this->nodepath, invert); } void ShapeEditor::select_all_from_subpath (bool invert) { - if (this->nodepath) + if (this->nodepath) sp_nodepath_select_all_from_subpath (this->nodepath, invert); } void ShapeEditor::select_next () { - if (this->nodepath) + if (this->nodepath) { sp_nodepath_select_next (this->nodepath); + if (this->nodepath->numSelected() >= 1) { + this->desktop->scroll_to_point(&(this->nodepath->singleSelectedCoords()), 1.0); + } + } } void ShapeEditor::select_prev () { - if (this->nodepath) + if (this->nodepath) { sp_nodepath_select_prev (this->nodepath); + if (this->nodepath->numSelected() >= 1) { + this->desktop->scroll_to_point(&(this->nodepath->singleSelectedCoords()), 1.0); + } + } } void ShapeEditor::show_handles (bool show) { - if (this->nodepath) + if (this->nodepath && !this->nodepath->straight_path) sp_nodepath_show_handles (this->nodepath, show); } +void ShapeEditor::show_helperpath (bool show) { + if (this->nodepath) + sp_nodepath_show_helperpath (this->nodepath, show); +} void ShapeEditor::flip (NR::Dim2 axis, NR::Maybe center) { - if (this->nodepath) + if (this->nodepath) sp_nodepath_flip (this->nodepath, axis, center); } void ShapeEditor::distribute (NR::Dim2 axis) { - if (this->nodepath) + if (this->nodepath) sp_nodepath_selected_distribute (this->nodepath, axis); } void ShapeEditor::align (NR::Dim2 axis) { - if (this->nodepath) + if (this->nodepath) sp_nodepath_selected_align (this->nodepath, axis); }