diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2010-11-25 20:51:17 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2010-11-25 20:51:17 +0000 |
| commit | 0bd9f7e209d522dbcebe0449a91397fdd9e38977 (patch) | |
| tree | 834c7d02456658b57625ab68cc28f7854a5a85dc /src/ui/tool | |
| parent | Fix handling of x and y attributes of patterns (diff) | |
| parent | Fix ruler redraw issue on GTK 2.22 (diff) | |
| download | inkscape-0bd9f7e209d522dbcebe0449a91397fdd9e38977.tar.gz inkscape-0bd9f7e209d522dbcebe0449a91397fdd9e38977.zip | |
Merge from trunk
(bzr r9508.1.70)
Diffstat (limited to 'src/ui/tool')
29 files changed, 197 insertions, 78 deletions
diff --git a/src/ui/tool/commit-events.h b/src/ui/tool/commit-events.h index d99872766..110564ba3 100644 --- a/src/ui/tool/commit-events.h +++ b/src/ui/tool/commit-events.h @@ -48,4 +48,4 @@ enum CommitEvent { fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index 615587eeb..91e0bc2c2 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -654,4 +654,4 @@ bool ControlPointSelection::event(GdkEvent *event) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h index 8023c3e28..3aed6ae93 100644 --- a/src/ui/tool/control-point-selection.h +++ b/src/ui/tool/control-point-selection.h @@ -159,4 +159,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/control-point.cpp b/src/ui/tool/control-point.cpp index b74e3bc9c..d5e5b7dfe 100644 --- a/src/ui/tool/control-point.cpp +++ b/src/ui/tool/control-point.cpp @@ -329,7 +329,7 @@ bool ControlPoint::_eventHandler(GdkEvent *event) _setState(STATE_CLICKED); return true; } - return false; + return _event_grab; case GDK_2BUTTON_PRESS: // store the button number for next release @@ -452,8 +452,9 @@ bool ControlPoint::_eventHandler(GdkEvent *event) default: break; } - - return false; + + // do not propagate events during grab - it might cause problems + return _event_grab; } void ControlPoint::_setMouseover(ControlPoint *p, unsigned state) @@ -578,4 +579,4 @@ bool ControlPoint::doubleclicked(GdkEventButton *) { return false; } fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/control-point.h b/src/ui/tool/control-point.h index 48c70748b..4de5e5847 100644 --- a/src/ui/tool/control-point.h +++ b/src/ui/tool/control-point.h @@ -199,4 +199,4 @@ extern ControlPoint::ColorSet invisible_cset; fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/curve-drag-point.cpp b/src/ui/tool/curve-drag-point.cpp index 0e5805dda..a3fb5aa6e 100644 --- a/src/ui/tool/curve-drag-point.cpp +++ b/src/ui/tool/curve-drag-point.cpp @@ -193,4 +193,4 @@ Glib::ustring CurveDragPoint::_getTip(unsigned state) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/curve-drag-point.h b/src/ui/tool/curve-drag-point.h index 288ae6a8e..42a4930c8 100644 --- a/src/ui/tool/curve-drag-point.h +++ b/src/ui/tool/curve-drag-point.h @@ -59,4 +59,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/event-utils.cpp b/src/ui/tool/event-utils.cpp index 91b2cdb04..ef2d27653 100644 --- a/src/ui/tool/event-utils.cpp +++ b/src/ui/tool/event-utils.cpp @@ -153,4 +153,4 @@ unsigned state_after_event(GdkEvent *event) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/event-utils.h b/src/ui/tool/event-utils.h index 784855f56..de29c3dda 100644 --- a/src/ui/tool/event-utils.h +++ b/src/ui/tool/event-utils.h @@ -129,4 +129,4 @@ unsigned state_after_event(GdkEvent *event); fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/manipulator.cpp b/src/ui/tool/manipulator.cpp index b532fcab4..49e601797 100644 --- a/src/ui/tool/manipulator.cpp +++ b/src/ui/tool/manipulator.cpp @@ -86,4 +86,4 @@ bool ManipulatorGroup::event(GdkEvent *event) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/manipulator.h b/src/ui/tool/manipulator.h index 799dad0d3..fd24e7b61 100644 --- a/src/ui/tool/manipulator.h +++ b/src/ui/tool/manipulator.h @@ -162,4 +162,4 @@ protected: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/modifier-tracker.cpp b/src/ui/tool/modifier-tracker.cpp index 8c6033bc7..bbef0d469 100644 --- a/src/ui/tool/modifier-tracker.cpp +++ b/src/ui/tool/modifier-tracker.cpp @@ -90,4 +90,4 @@ bool ModifierTracker::event(GdkEvent *event) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/modifier-tracker.h b/src/ui/tool/modifier-tracker.h index 55538ead6..8c8787e87 100644 --- a/src/ui/tool/modifier-tracker.h +++ b/src/ui/tool/modifier-tracker.h @@ -51,4 +51,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp index 2025a12d7..82446b7b4 100644 --- a/src/ui/tool/multi-path-manipulator.cpp +++ b/src/ui/tool/multi-path-manipulator.cpp @@ -220,11 +220,29 @@ void MultiPathManipulator::invertSelectionInSubpaths() void MultiPathManipulator::setNodeType(NodeType type) { if (_selection.empty()) return; + + // When all selected nodes are already cusp, retract their handles + bool retract_handles = (type == NODE_CUSP); + for (ControlPointSelection::iterator i = _selection.begin(); i != _selection.end(); ++i) { Node *node = dynamic_cast<Node*>(*i); - if (node) node->setType(type); + if (node) { + retract_handles &= (node->type() == NODE_CUSP); + node->setType(type); + } + } + + if (retract_handles) { + for (ControlPointSelection::iterator i = _selection.begin(); i != _selection.end(); ++i) { + Node *node = dynamic_cast<Node*>(*i); + if (node) { + node->front()->retract(); + node->back()->retract(); + } + } } - _done(_("Change node type")); + + _done(retract_handles ? _("Retract handles") : _("Change node type")); } void MultiPathManipulator::setSegmentType(SegmentType type) @@ -244,6 +262,12 @@ void MultiPathManipulator::insertNodes() _done(_("Add nodes")); } +void MultiPathManipulator::duplicateNodes() +{ + invokeForAll(&PathManipulator::duplicateNodes); + _done(_("Duplicate nodes")); +} + void MultiPathManipulator::joinNodes() { invokeForAll(&PathManipulator::hideDragPoint); @@ -513,6 +537,12 @@ bool MultiPathManipulator::event(GdkEvent *event) return true; } break; + case GDK_d: + case GDK_D: + if (held_only_shift(event->key)) { + duplicateNodes(); + return true; + } case GDK_j: case GDK_J: if (held_only_shift(event->key)) { @@ -591,6 +621,20 @@ bool MultiPathManipulator::event(GdkEvent *event) return true; } break; + case GDK_l: + case GDK_L: + if (held_only_shift(event->key)) { + // Shift+L - make segments linear + setSegmentType(SEGMENT_STRAIGHT); + return true; + } + case GDK_u: + case GDK_U: + if (held_only_shift(event->key)) { + // Shift+L - make segments curves + setSegmentType(SEGMENT_CUBIC_BEZIER); + return true; + } default: break; } @@ -714,4 +758,4 @@ guint32 MultiPathManipulator::_getOutlineColor(ShapeRole role) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/multi-path-manipulator.h b/src/ui/tool/multi-path-manipulator.h index 181ae6d1d..ddb74c1bc 100644 --- a/src/ui/tool/multi-path-manipulator.h +++ b/src/ui/tool/multi-path-manipulator.h @@ -53,6 +53,7 @@ public: void setSegmentType(SegmentType t); void insertNodes(); + void duplicateNodes(); void joinNodes(); void breakNodes(); void deleteNodes(bool keep_shape = true); @@ -135,4 +136,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/node-tool.cpp b/src/ui/tool/node-tool.cpp index 450ca96f0..8008d79eb 100644 --- a/src/ui/tool/node-tool.cpp +++ b/src/ui/tool/node-tool.cpp @@ -25,6 +25,7 @@ #include "sp-mask.h" #include "sp-object-group.h" #include "sp-path.h" +#include "sp-text.h" #include "ui/tool/node-tool.h" #include "ui/tool/control-point-selection.h" #include "ui/tool/curve-drag-point.h" @@ -164,6 +165,7 @@ void ink_node_tool_init(InkNodeTool *nt) new (&nt->_multipath) MultiPathPtr(); new (&nt->_selector) SelectorPtr(); new (&nt->_path_data) PathSharedDataPtr(); + new (&nt->_shape_editors) ShapeEditors(); } void ink_node_tool_dispose(GObject *object) @@ -178,6 +180,7 @@ void ink_node_tool_dispose(GObject *object) nt->_multipath.~MultiPathPtr(); nt->_selected_nodes.~CSelPtr(); nt->_selector.~SelectorPtr(); + nt->_shape_editors.~ShapeEditors(); Inkscape::UI::PathSharedData &data = *nt->_path_data; destroy_group(data.node_data.node_group); @@ -195,10 +198,6 @@ void ink_node_tool_dispose(GObject *object) if (nt->_node_message_context) { delete nt->_node_message_context; } - if (nt->shape_editor) { - nt->shape_editor->unset_item(SH_KNOTHOLDER); - delete nt->shape_editor; - } G_OBJECT_CLASS(g_type_class_peek(g_type_parent(INK_TYPE_NODE_TOOL)))->dispose(object); } @@ -281,9 +280,6 @@ void ink_node_tool_setup(SPEventContext *ec) nt->flash_tempitem = NULL; nt->flashed_item = NULL; nt->_last_over = NULL; - // TODO long term, fold ShapeEditor into MultiPathManipulator and rename MPM - // to something better - nt->shape_editor = new ShapeEditor(nt->desktop); // read prefs before adding items to selection to prevent momentarily showing the outline sp_event_context_read(nt, "show_handles"); @@ -403,22 +399,30 @@ void ink_node_tool_selection_changed(InkNodeTool *nt, Inkscape::Selection *sel) } } - // ugly hack: set the first editable non-path item for knotholder - // maybe use multiple ShapeEditors for now, to allow editing many shapes at once? - bool something_set = false; + // use multiple ShapeEditors for now, to allow editing many shapes at once + // needs to be rethought + for (ShapeEditors::iterator i = nt->_shape_editors.begin(); + i != nt->_shape_editors.end(); ) + { + ShapeRecord s; + s.item = i->first; + if (shapes.find(s) == shapes.end()) { + nt->_shape_editors.erase(i++); + } else { + ++i; + } + } + for (std::set<ShapeRecord>::iterator i = shapes.begin(); i != shapes.end(); ++i) { ShapeRecord const &r = *i; - if (SP_IS_SHAPE(r.item) || - (SP_IS_PATH(r.item) && r.item->repr->attribute("inkscape:original-d") != NULL)) + if ((SP_IS_SHAPE(r.item) || SP_IS_TEXT(r.item)) && + nt->_shape_editors.find(r.item) == nt->_shape_editors.end()) { - nt->shape_editor->set_item(r.item, SH_KNOTHOLDER); - something_set = true; - break; + ShapeEditor *si = new ShapeEditor(nt->desktop); + si->set_item(r.item, SH_KNOTHOLDER); + nt->_shape_editors.insert(const_cast<SPItem*&>(r.item), si); } } - if (!something_set) { - nt->shape_editor->unset_item(SH_KNOTHOLDER); - } nt->_multipath->setItems(shapes); ink_node_tool_update_tip(nt, NULL); @@ -615,8 +619,14 @@ void ink_node_tool_select_point(InkNodeTool *nt, Geom::Point const &/*sel*/, Gdk if (item_clicked == NULL) { // nothing under cursor // if no Shift, deselect - if (!(event->state & GDK_SHIFT_MASK)) { - selection->clear(); + // if there are nodes selected, the first click should deselect the nodes + // and the second should deselect the items + if (!state_held_shift(event->state)) { + if (nt->_selected_nodes->empty()) { + selection->clear(); + } else { + nt->_selected_nodes->clear(); + } } } else { if (held_shift(*event)) { @@ -658,4 +668,4 @@ void ink_node_tool_mouseover_changed(InkNodeTool *nt, Inkscape::UI::ControlPoint fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/node-tool.h b/src/ui/tool/node-tool.h index 641d064c1..4d38e69e2 100644 --- a/src/ui/tool/node-tool.h +++ b/src/ui/tool/node-tool.h @@ -12,6 +12,7 @@ #define SEEN_UI_TOOL_NODE_TOOL_H #include <memory> +#include <boost/ptr_container/ptr_map.hpp> #include <glib.h> #include <sigc++/sigc++.h> #include "event-context.h" @@ -41,6 +42,7 @@ typedef std::auto_ptr<Inkscape::UI::MultiPathManipulator> MultiPathPtr; typedef std::auto_ptr<Inkscape::UI::ControlPointSelection> CSelPtr; typedef std::auto_ptr<Inkscape::UI::Selector> SelectorPtr; typedef std::auto_ptr<Inkscape::UI::PathSharedData> PathSharedDataPtr; +typedef boost::ptr_map<SPItem*, ShapeEditor> ShapeEditors; struct InkNodeTool : public SPEventContext { @@ -56,6 +58,7 @@ struct InkNodeTool : public SPEventContext PathSharedDataPtr _path_data; SPCanvasGroup *_transform_handle_group; SPItem *_last_over; + ShapeEditors _shape_editors; unsigned cursor_drag : 1; unsigned show_handles : 1; @@ -86,4 +89,4 @@ GType ink_node_tool_get_type (void); fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/node-types.h b/src/ui/tool/node-types.h index 80eaf4fa7..e4921fa8d 100644 --- a/src/ui/tool/node-types.h +++ b/src/ui/tool/node-types.h @@ -45,4 +45,4 @@ enum SegmentType { fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index a8582ccc5..12d04dd2b 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -274,8 +274,10 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event) } else { sm.freeSnapReturnByRef(new_pos, SNAPSOURCE_NODE_HANDLE); } + sm.unSetup(); } + // with Shift, if the node is cusp, rotate the other handle as well if (_parent->type() == NODE_CUSP && !_drag_out) { if (held_shift(*event)) { @@ -566,11 +568,7 @@ void Node::setType(NodeType type, bool update_handles) if (update_handles) { switch (type) { case NODE_CUSP: - // if the existing type is also NODE_CUSP, retract handles - if (_type == NODE_CUSP) { - _front.retract(); - _back.retract(); - } + // nothing to do break; case NODE_AUTO: // auto handles make no sense for endnodes @@ -578,13 +576,15 @@ void Node::setType(NodeType type, bool update_handles) _updateAutoHandles(); break; case NODE_SMOOTH: { + // ignore attempts to make smooth endnodes. + if (isEndNode()) return; // rotate handles to be colinear // for degenerate nodes set positions like auto handles bool prev_line = _is_line_segment(_prev(), this); bool next_line = _is_line_segment(this, _next()); if (_type == NODE_SMOOTH) { - // for a node that is already smooth and has a degenerate handle, - // drag out the second handle to 1/3 the length of the linear segment + // For a node that is already smooth and has a degenerate handle, + // drag out the second handle without changing the direction of the first one. if (_front.isDegenerate()) { double dist = Geom::distance(_next()->position(), position()); _front.setRelativePos(Geom::unit_vector(-_back.relativePos()) * dist / 3); @@ -728,8 +728,7 @@ NodeType Node::parse_nodetype(char x) /** Customized event handler to catch scroll events needed for selection grow/shrink. */ bool Node::_eventHandler(GdkEvent *event) { - static NodeList::iterator origin; - static int dir; + int dir = 0; switch (event->type) { @@ -740,14 +739,34 @@ bool Node::_eventHandler(GdkEvent *event) dir = -1; } else break; if (held_control(event->scroll)) { - _selection.spatialGrow(this, dir); + _linearGrow(dir); } else { + _selection.spatialGrow(this, dir); + } + return true; + case GDK_KEY_PRESS: + switch (shortcut_key(event->key)) + { + case GDK_Page_Up: + dir = 1; + break; + case GDK_Page_Down: + dir = -1; + break; + default: goto bail_out; + } + + if (held_control(event->key)) { _linearGrow(dir); + } else { + _selection.spatialGrow(this, dir); } return true; default: break; } + + bail_out: return ControlPoint::_eventHandler(event); } @@ -942,8 +961,16 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) { // For a note on how snapping is implemented in Inkscape, see snap.h. SnapManager &sm = _desktop->namedview->snap_manager; - bool snap = sm.someSnapperMightSnap(); + // even if we won't really snap, we might still call the one of the + // constrainedSnap() methods to enforce the constraints, so we need + // to setup the snapmanager anyway; this is also required for someSnapperMightSnap() + sm.setup(_desktop); + + // do not snap when Shift is pressed + bool snap = !held_shift(*event) && sm.someSnapperMightSnap(); + Inkscape::SnappedPoint sp; + std::vector<Inkscape::SnapCandidatePoint> unselected; if (snap) { /* setup * TODO We are doing this every time a snap happens. It should once be done only once @@ -953,7 +980,6 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) * TODO Snapping to unselected segments of selected paths doesn't work yet. */ // Build the list of unselected nodes. - std::vector<Inkscape::SnapCandidatePoint> unselected; typedef ControlPointSelection::Set Set; Set &nodes = _selection.allPoints(); for (Set::iterator i = nodes.begin(); i != nodes.end(); ++i) { @@ -963,6 +989,7 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) unselected.push_back(p); } } + sm.unSetup(); sm.setupIgnoreSelection(_desktop, true, &unselected); } @@ -1014,12 +1041,12 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *bperp_point)); } - sp = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), constraints); + sp = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), constraints, held_shift(*event)); } else { // with Ctrl, constrain to axes constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(1, 0))); constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(0, 1))); - sp = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), constraints); + sp = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), constraints, held_shift(*event)); } new_pos = sp.getPoint(); } else if (snap) { @@ -1027,6 +1054,8 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event) new_pos = sp.getPoint(); } + sm.unSetup(); + SelectableControlPoint::dragged(new_pos, event); } @@ -1374,4 +1403,4 @@ NodeList &NodeList::get(iterator const &i) { fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h index af4cd7e3a..0194f5053 100644 --- a/src/ui/tool/node.h +++ b/src/ui/tool/node.h @@ -408,4 +408,4 @@ NodeIterator<N> &NodeIterator<N>::retreat() { fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 66f72f379..956f48a7d 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -319,6 +319,39 @@ void PathManipulator::insertNodes() } } +/** Insert new nodes exactly at the positions of selected nodes while preserving shape. + * This is equivalent to breaking, except that it doesn't split into subpaths. */ +void PathManipulator::duplicateNodes() +{ + if (_num_selected == 0) return; + + for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) { + for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) { + if (j->selected()) { + NodeList::iterator k = j.next(); + Node *n = new Node(_multi_path_manipulator._path_data.node_data, *j); + + // Move the new node to the bottom of the Z-order. This way you can drag all + // nodes that were selected before this operation without deselecting + // everything because there is a new node above. + n->sink(); + + n->front()->setPosition(*j->front()); + j->front()->retract(); + j->setType(NODE_CUSP, false); + (*i)->insert(k, n); + + // We need to manually call the selection change callback to refresh + // the handle display correctly. + // This call changes num_selected, but we call this once for a selected node + // and once for an unselected node, so in the end the number stays correct. + _selectionChanged(j.ptr(), true); + _selectionChanged(n, false); + } + } + } +} + /** Replace contiguous selections of nodes in each subpath with one node. */ void PathManipulator::weldNodes(NodeList::iterator preserve_pos) { @@ -1292,17 +1325,11 @@ bool PathManipulator::_nodeClicked(Node *n, GdkEventButton *event) return true; } else if (held_control(*event)) { // Ctrl+click: cycle between node types - if (n->isEndNode()) { - if (n->type() == NODE_CUSP) { - n->setType(NODE_SMOOTH); - } else { - n->setType(NODE_CUSP); - } - } else { + if (!n->isEndNode()) { n->setType(static_cast<NodeType>((n->type() + 1) % NODE_LAST_REAL_TYPE)); + update(); + _commit(_("Cycle node type")); } - update(); - _commit(_("Cycle node type")); return true; } return false; @@ -1414,7 +1441,10 @@ void PathManipulator::_updateDragPoint(Geom::Point const &evp) NodeList::iterator first = (*spi)->before(pvp->t, &fracpart); double stroke_tolerance = _getStrokeTolerance(); - if (Geom::distance(evp, nearest_point) < stroke_tolerance) { + if (first && first.next() && + fracpart != 0.0 && + Geom::distance(evp, nearest_point) < stroke_tolerance) + { _dragpoint->setVisible(true); _dragpoint->setPosition(_desktop->w2d(nearest_point)); _dragpoint->setSize(2 * stroke_tolerance); @@ -1459,4 +1489,4 @@ double PathManipulator::_getStrokeTolerance() fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h index a8f1c957e..87b88fc77 100644 --- a/src/ui/tool/path-manipulator.h +++ b/src/ui/tool/path-manipulator.h @@ -69,6 +69,7 @@ public: void invertSelectionInSubpaths(); void insertNodes(); + void duplicateNodes(); void weldNodes(NodeList::iterator preserve_pos = NodeList::iterator()); void weldSegments(); void breakNodes(); @@ -162,4 +163,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/selectable-control-point.cpp b/src/ui/tool/selectable-control-point.cpp index 76028dd82..e9a8bcbd6 100644 --- a/src/ui/tool/selectable-control-point.cpp +++ b/src/ui/tool/selectable-control-point.cpp @@ -136,4 +136,4 @@ void SelectableControlPoint::_setState(State state) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/selectable-control-point.h b/src/ui/tool/selectable-control-point.h index 2fde16ea9..1b8bd46cc 100644 --- a/src/ui/tool/selectable-control-point.h +++ b/src/ui/tool/selectable-control-point.h @@ -69,4 +69,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/selector.cpp b/src/ui/tool/selector.cpp index d766d5be3..fdd0fc51f 100644 --- a/src/ui/tool/selector.cpp +++ b/src/ui/tool/selector.cpp @@ -130,4 +130,4 @@ bool Selector::event(GdkEvent *event) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/selector.h b/src/ui/tool/selector.h index f7c00ea71..e61668d9e 100644 --- a/src/ui/tool/selector.h +++ b/src/ui/tool/selector.h @@ -56,4 +56,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/shape-record.h b/src/ui/tool/shape-record.h index edfad1401..893231404 100644 --- a/src/ui/tool/shape-record.h +++ b/src/ui/tool/shape-record.h @@ -58,4 +58,4 @@ struct ShapeRecord : fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp index 6b8fb4c11..ef93a3767 100644 --- a/src/ui/tool/transform-handle-set.cpp +++ b/src/ui/tool/transform-handle-set.cpp @@ -654,4 +654,4 @@ void TransformHandleSet::_updateVisibility(bool v) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/tool/transform-handle-set.h b/src/ui/tool/transform-handle-set.h index 48ad3af51..2a4df8751 100644 --- a/src/ui/tool/transform-handle-set.h +++ b/src/ui/tool/transform-handle-set.h @@ -93,4 +93,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |
