diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2010-01-10 00:46:28 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2010-01-10 00:46:28 +0000 |
| commit | b52865a71a9f83da9719a3ec5f50a4a2cd7cdace (patch) | |
| tree | 6d8def69ad0aa28aa4414dc9d501707444a5419b /src/ui | |
| parent | Implement selection linear grow (diff) | |
| download | inkscape-b52865a71a9f83da9719a3ec5f50a4a2cd7cdace.tar.gz inkscape-b52865a71a9f83da9719a3ec5f50a4a2cd7cdace.zip | |
* Implement node snapping.
* Fix minor bug in linear grow.
* Add --fixes.
* Move some node selection-related functions to ControlPointSelection.
Fixed bugs:
- https://launchpad.net/bugs/170561
- https://launchpad.net/bugs/171893
- https://launchpad.net/bugs/182585
- https://launchpad.net/bugs/446773
(bzr r8846.2.9)
Diffstat (limited to 'src/ui')
| -rw-r--r-- | src/ui/tool/control-point-selection.cpp | 55 | ||||
| -rw-r--r-- | src/ui/tool/control-point-selection.h | 15 | ||||
| -rw-r--r-- | src/ui/tool/control-point.cpp | 81 | ||||
| -rw-r--r-- | src/ui/tool/control-point.h | 6 | ||||
| -rw-r--r-- | src/ui/tool/multi-path-manipulator.cpp | 52 | ||||
| -rw-r--r-- | src/ui/tool/multi-path-manipulator.h | 5 | ||||
| -rw-r--r-- | src/ui/tool/node-tool.cpp | 12 | ||||
| -rw-r--r-- | src/ui/tool/node.cpp | 124 | ||||
| -rw-r--r-- | src/ui/tool/node.h | 6 | ||||
| -rw-r--r-- | src/ui/tool/path-manipulator.cpp | 48 | ||||
| -rw-r--r-- | src/ui/tool/path-manipulator.h | 3 | ||||
| -rw-r--r-- | src/ui/tool/selectable-control-point.cpp | 2 |
12 files changed, 232 insertions, 177 deletions
diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index d10045c62..5a84592b6 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -140,7 +140,60 @@ void ControlPointSelection::clear() erase(i++); } -/** Transform all selected control points by the supplied affine transformation. */ +/** Select all points that this selection can contain. */ +void ControlPointSelection::selectAll() +{ + for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) { + insert(*i); + } +} +/** Select all points inside the given rectangle (in desktop coordinates). */ +void ControlPointSelection::selectArea(Geom::Rect const &r) +{ + for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) { + if (r.contains(**i)) + insert(*i); + } +} +/** Unselect all selected points and select all unselected points. */ +void ControlPointSelection::invertSelection() +{ + for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) { + if ((*i)->selected()) erase(*i); + else insert(*i); + } +} +void ControlPointSelection::spatialGrow(SelectableControlPoint *origin, int dir) +{ + bool grow = (dir > 0); + Geom::Point p = origin->position(); + double best_dist = grow ? HUGE_VAL : 0; + SelectableControlPoint *match = NULL; + for (set_type::iterator i = _all_points.begin(); i != _all_points.end(); ++i) { + bool selected = (*i)->selected(); + if (grow && !selected) { + double dist = Geom::distance((*i)->position(), p); + if (dist < best_dist) { + best_dist = dist; + match = *i; + } + } + if (!grow && selected) { + double dist = Geom::distance((*i)->position(), p); + // use >= to also deselect the origin node when it's the last one selected + if (dist >= best_dist) { + best_dist = dist; + match = *i; + } + } + } + if (match) { + if (grow) insert(match); + else erase(match); + } +} + +/** Transform all selected control points by the given affine transformation. */ void ControlPointSelection::transform(Geom::Matrix const &m) { for (iterator i = _points.begin(); i != _points.end(); ++i) { diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h index 0f0daffaa..38df5c7e5 100644 --- a/src/ui/tool/control-point-selection.h +++ b/src/ui/tool/control-point-selection.h @@ -14,6 +14,7 @@ #include <memory> #include <tr1/unordered_map> +#include <tr1/unordered_set> #include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp> #include <boost/optional.hpp> @@ -43,12 +44,12 @@ public: typedef std::list<sigc::connection> connlist_type; typedef std::unordered_map< SelectableControlPoint *, boost::shared_ptr<connlist_type> > map_type; + typedef std::unordered_set< SelectableControlPoint * > set_type; + typedef set_type Set; // convenience alias - // boilerplate typedefs typedef map_type::iterator iterator; typedef map_type::const_iterator const_iterator; typedef map_type::size_type size_type; - typedef SelectableControlPoint *value_type; typedef SelectableControlPoint *key_type; @@ -80,6 +81,15 @@ public: // find iterator find(const key_type &k) { return _points.find(k); } + // Sometimes it is very useful to keep a list of all selectable points. + set_type const &allPoints() const { return _all_points; } + set_type &allPoints() { return _all_points; } + // ...for example in these methods. Another useful case is snapping. + void selectAll(); + void selectArea(Geom::Rect const &); + void invertSelection(); + void spatialGrow(SelectableControlPoint *origin, int dir); + virtual bool event(GdkEvent *); void transform(Geom::Matrix const &m); @@ -113,6 +123,7 @@ private: void _keyboardTransform(Geom::Matrix const &); void _commitTransform(CommitEvent ce); map_type _points; + set_type _all_points; boost::optional<double> _rot_radius; TransformHandleSet *_handles; SelectableControlPoint *_grabbed_point; diff --git a/src/ui/tool/control-point.cpp b/src/ui/tool/control-point.cpp index 74dd6e31c..0d076a5ab 100644 --- a/src/ui/tool/control-point.cpp +++ b/src/ui/tool/control-point.cpp @@ -12,13 +12,14 @@ #include <gdkmm.h> #include <gtkmm.h> #include <2geom/point.h> -#include "ui/tool/control-point.h" -#include "ui/tool/event-utils.h" -#include "preferences.h" #include "desktop.h" #include "desktop-handles.h" +#include "display/snap-indicator.h" #include "event-context.h" #include "message-context.h" +#include "preferences.h" +#include "ui/tool/control-point.h" +#include "ui/tool/event-utils.h" namespace Inkscape { namespace UI { @@ -397,6 +398,7 @@ bool ControlPoint::_eventHandler(GdkEvent *event) case GDK_MOTION_NOTIFY: if (held_button<1>(event->motion) && !_desktop->event_context->space_panning) { + _desktop->snapindicator->remove_snaptarget(); bool transferred = false; if (!_drag_initiated) { bool t = fabs(event->motion.x - _drag_event_origin[Geom::X]) <= drag_tolerance && @@ -414,48 +416,57 @@ bool ControlPoint::_eventHandler(GdkEvent *event) _drag_initiated = true; } } - if (transferred) return true; - // the point was moved beyond the drag tolerance - Geom::Point new_pos = _desktop->w2d(event_point(event->motion)) + pointer_offset; - - // the new position is passed by reference and can be changed in the handlers. - signal_dragged.emit(_position, new_pos, &event->motion); - move(new_pos); - _updateDragTip(&event->motion); // update dragging tip after moving to new position - - _desktop->scroll_to_point(new_pos); - _desktop->set_coordinate_status(_position); + if (!transferred) { + // dragging in progress + Geom::Point new_pos = _desktop->w2d(event_point(event->motion)) + pointer_offset; + + // the new position is passed by reference and can be changed in the handlers. + signal_dragged.emit(_position, new_pos, &event->motion); + move(new_pos); + _updateDragTip(&event->motion); // update dragging tip after moving to new position + + _desktop->scroll_to_point(new_pos); + _desktop->set_coordinate_status(_position); + sp_event_context_snap_delay_handler(_desktop->event_context, NULL, + reinterpret_cast<SPKnot*>(this), &event->motion, + DelayedSnapEvent::CONTROL_POINT_HANDLER); + } return true; } break; case GDK_BUTTON_RELEASE: - if (_event_grab) { - sp_canvas_item_ungrab(_canvas_item, event->button.time); - _setMouseover(this, event->button.state); - _event_grab = false; + if (!_event_grab) break; - if (_drag_initiated) { - sp_canvas_end_forced_full_redraws(_desktop->canvas); - } + // TODO I think this "feature" is wrong. + // sp_event_context_snap_watchdog_callback(_desktop->event_context->_delayed_snap_event); + sp_event_context_discard_delayed_snap_event(_desktop->event_context); + _desktop->snapindicator->remove_snaptarget(); + + sp_canvas_item_ungrab(_canvas_item, event->button.time); + _setMouseover(this, event->button.state); + _event_grab = false; - if (event->button.button == next_release_doubleclick) { + if (_drag_initiated) { + sp_canvas_end_forced_full_redraws(_desktop->canvas); + } + + if (event->button.button == next_release_doubleclick) { + _drag_initiated = false; + return signal_doubleclicked.emit(&event->button); + } + if (event->button.button == 1) { + if (_drag_initiated) { + // it is the end of a drag + signal_ungrabbed.emit(&event->button); _drag_initiated = false; - return signal_doubleclicked.emit(&event->button); + return true; + } else { + // it is the end of a click + return signal_clicked.emit(&event->button); } - if (event->button.button == 1) { - if (_drag_initiated) { - // it is the end of a drag - signal_ungrabbed.emit(&event->button); - _drag_initiated = false; - return true; - } else { - // it is the end of a click - return signal_clicked.emit(&event->button); - } - } - _drag_initiated = false; } + _drag_initiated = false; break; case GDK_ENTER_NOTIFY: diff --git a/src/ui/tool/control-point.h b/src/ui/tool/control-point.h index c4b0a42be..4997c5ef4 100644 --- a/src/ui/tool/control-point.h +++ b/src/ui/tool/control-point.h @@ -90,6 +90,9 @@ public: static sigc::signal<void, ControlPoint*> signal_mouseover_change; static Glib::ustring format_tip(char const *format, ...) G_GNUC_PRINTF(1,2); + // temporarily public, until snapping is refactored a little + virtual bool _eventHandler(GdkEvent *event); + protected: ControlPoint(SPDesktop *d, Geom::Point const &initial_pos, Gtk::AnchorType anchor, SPCtrlShapeType shape, unsigned int size, ColorSet *cset = 0, SPCanvasGroup *group = 0); @@ -112,14 +115,13 @@ protected: void _setPixbuf(Glib::RefPtr<Gdk::Pixbuf>); /// @} - virtual bool _eventHandler(GdkEvent *event); virtual Glib::ustring _getTip(unsigned state) { return ""; } virtual Glib::ustring _getDragTip(GdkEventMotion *event) { return ""; } virtual bool _hasDragTips() { return false; } SPDesktop *const _desktop; ///< The desktop this control point resides on. SPCanvasItem * _canvas_item; ///< Visual representation of the control point. - ColorSet *_cset; ///< Describes the colors used to represent the point + ColorSet *_cset; ///< Colors used to represent the point State _state; static int const _grab_event_mask; diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp index ac0165e1a..33d96c706 100644 --- a/src/ui/tool/multi-path-manipulator.cpp +++ b/src/ui/tool/multi-path-manipulator.cpp @@ -181,71 +181,21 @@ void MultiPathManipulator::setItems(std::set<ShapeRecord> const &s) void MultiPathManipulator::selectSubpaths() { if (_selection.empty()) { - invokeForAll(&PathManipulator::selectAll); + _selection.selectAll(); } else { invokeForAll(&PathManipulator::selectSubpaths); } } -void MultiPathManipulator::selectAll() -{ - invokeForAll(&PathManipulator::selectAll); -} - -void MultiPathManipulator::selectArea(Geom::Rect const &area, bool take) -{ - if (take) _selection.clear(); - invokeForAll(&PathManipulator::selectArea, area); -} void MultiPathManipulator::shiftSelection(int dir) { invokeForAll(&PathManipulator::shiftSelection, dir); } -void MultiPathManipulator::spatialGrow(NodeList::iterator origin, int dir) -{ - double extr_dist = dir > 0 ? HUGE_VAL : -HUGE_VAL; - NodeList::iterator target; - do { // this substitutes for goto - if ((dir > 0 && !origin->selected())) { - target = origin; - break; - } - - bool closest = dir > 0; // when growing, find closest node - bool selected = dir < 0; // when growing, consider only unselected nodes - - for (MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) { - NodeList::iterator t = i->second->extremeNode(origin, selected, !selected, closest); - if (!t) continue; - double dist = Geom::distance(*t, *origin); - bool cond = closest ? (dist < extr_dist) : (dist > extr_dist); - if (cond) { - extr_dist = dist; - target = t; - } - } - } while (0); - - if (!target) return; - if (dir > 0) { - _selection.insert(target.ptr()); - } else { - _selection.erase(target.ptr()); - } -} -void MultiPathManipulator::invertSelection() -{ - invokeForAll(&PathManipulator::invertSelection); -} void MultiPathManipulator::invertSelectionInSubpaths() { invokeForAll(&PathManipulator::invertSelectionInSubpaths); } -void MultiPathManipulator::deselect() -{ - _selection.clear(); -} void MultiPathManipulator::setNodeType(NodeType type) { diff --git a/src/ui/tool/multi-path-manipulator.h b/src/ui/tool/multi-path-manipulator.h index 4fbbf1b05..46ad3a8d2 100644 --- a/src/ui/tool/multi-path-manipulator.h +++ b/src/ui/tool/multi-path-manipulator.h @@ -45,13 +45,8 @@ public: void cleanup(); void selectSubpaths(); - void selectAll(); - void selectArea(Geom::Rect const &area, bool take); void shiftSelection(int dir); - void spatialGrow(NodeList::iterator center, int dir); - void invertSelection(); void invertSelectionInSubpaths(); - void deselect(); void setNodeType(NodeType t); void setSegmentType(SegmentType t); diff --git a/src/ui/tool/node-tool.cpp b/src/ui/tool/node-tool.cpp index 735ddf87e..c1ba3394e 100644 --- a/src/ui/tool/node-tool.cpp +++ b/src/ui/tool/node-tool.cpp @@ -62,12 +62,15 @@ * it might handle all shapes. Handles XML commit of actions that affect all paths or * the node selection and removes PathManipulators that have no nodes left after e.g. node * deletes. - * - ControlPointSelection: keeps track of node selection. Performs actions that require no + * - ControlPointSelection: keeps track of node selection and a set of nodes that can potentially + * be selected. There can be more than one selection. Performs actions that require no * knowledge about the path, only about the nodes, like dragging and transforms. It is not * specific to nodes and can accomodate any control point derived from SelectableControlPoint. * Transforms nodes in response to transform handle events. * - TransformHandleSet: displays nodeset transform handles and emits transform events. The aim * is to eventually use a common class for object and control point transforms. + * - SelectableControlPoint: base for any type of selectable point. It can belong to only one + * selection. * * @par Plans for the future * @par @@ -384,9 +387,6 @@ void ink_node_tool_selection_changed(InkNodeTool *nt, Inkscape::Selection *sel) std::set<ShapeRecord> shapes; - // TODO this is ugly!!! - //typedef std::map<SPItem*, std::pair<Geom::Matrix, guint32> > TransMap; - //typedef std::map<SPPath*, std::pair<Geom::Matrix, guint32> > PathMap; GSList const *ilist = sel->itemList(); for (GSList *i = const_cast<GSList*>(ilist); i; i = i->next) { @@ -477,7 +477,7 @@ gint ink_node_tool_root_handler(SPEventContext *event_context, GdkEvent *event) case GDK_a: if (held_control(event->key)) { if (held_alt(event->key)) { - nt->_multipath->selectAll(); + nt->_selected_nodes->selectAll(); } else { // select all nodes in subpaths that have something selected // if nothing is selected, select everything @@ -554,7 +554,7 @@ void ink_node_tool_select_area(InkNodeTool *nt, Geom::Rect const &sel, GdkEventB selection->setList(items); g_slist_free(items); } else { - nt->_multipath->selectArea(sel, !held_shift(*event)); + nt->_selected_nodes->selectArea(sel); } } void ink_node_tool_select_point(InkNodeTool *nt, Geom::Point const &sel, GdkEventButton *event) diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index 22d4ddc47..adef8e5a7 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -22,6 +22,8 @@ #include "desktop.h" #include "desktop-handles.h" #include "preferences.h" +#include "snap.h" +#include "snap-preferences.h" #include "sp-metrics.h" #include "sp-namedview.h" #include "ui/tool/control-point-selection.h" @@ -638,10 +640,8 @@ bool Node::_eventHandler(GdkEvent *event) } else if (event->scroll.direction == GDK_SCROLL_DOWN) { dir = -1; } else break; - origin = NodeList::get_iterator(this); - if (held_control(event->scroll)) { - list()->_list._path_manipulator._multi_path_manipulator.spatialGrow(origin, dir); + _selection.spatialGrow(this, dir); } else { _linearGrow(dir); } @@ -658,7 +658,6 @@ static double bezier_length (Geom::Point a0, Geom::Point a1, Geom::Point a2, Geo double lower = Geom::distance(a0, a3); double upper = Geom::distance(a0, a1) + Geom::distance(a1, a2) + Geom::distance(a2, a3); - // TODO maybe EPSILON is this is too big in this case? if (upper - lower < Geom::EPSILON) return (lower + upper)/2; Geom::Point // Casteljau subdivision @@ -732,7 +731,7 @@ void Node::_linearGrow(int dir) } else { // both iterators that store last selected nodes are initially empty NodeList::iterator last_fwd, last_rev; - double last_distance_back, last_distance_front; + double last_distance_back = 0, last_distance_front = 0; while (rev || fwd) { if (fwd && (!rev || distance_front <= distance_back)) { @@ -741,7 +740,7 @@ void Node::_linearGrow(int dir) last_distance_front = distance_front; } NodeList::iterator n = fwd.next(); - distance_front += bezier_length(*fwd, fwd->_front, n->_back, *n); + if (n) distance_front += bezier_length(*fwd, fwd->_front, n->_back, *n); fwd = n; } else if (rev && (!fwd || distance_front > distance_back)) { if (rev->selected()) { @@ -749,13 +748,27 @@ void Node::_linearGrow(int dir) last_distance_back = distance_back; } NodeList::iterator p = rev.prev(); - distance_back += bezier_length(*rev, rev->_back, p->_front, *p); + if (p) distance_back += bezier_length(*rev, rev->_back, p->_front, *p); rev = p; } // Check whether we walked the entire cyclic subpath. // This is initially true because both iterators start from this node, // so this check cannot go in the while condition. - if (fwd == rev) break; + // When this happens, we need to check the last node, pointed to by the iterators. + if (fwd && fwd == rev) { + if (!fwd->selected()) break; + NodeList::iterator fwdp = fwd.prev(), revn = rev.next(); + double df = distance_front + bezier_length(*fwdp, fwdp->_front, fwd->_back, *fwd); + double db = distance_back + bezier_length(*revn, revn->_back, rev->_front, *rev); + if (df > db) { + last_fwd = fwd; + last_distance_front = df; + } else { + last_rev = rev; + last_distance_back = db; + } + break; + } } NodeList::iterator t; @@ -825,34 +838,97 @@ bool Node::_grabbedHandler(GdkEventMotion *event) void Node::_draggedHandler(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; + Inkscape::SnapPreferences::PointType t = Inkscape::SnapPreferences::SNAPPOINT_NODE; + bool snap = sm.someSnapperMightSnap(); + std::vector< std::pair<Geom::Point, int> > unselected; + if (snap) { + // setup + // TODO we are doing this every time a snap happens. It should once be done only once + // per drag - maybe in the grabbed handler? + // TODO "unselected" must be valid during the snap run, because it is not copied. + // Fix this in snap.h and snap.cpp, then the above. + + // Build the list of unselected nodes. + typedef ControlPointSelection::Set Set; + Set nodes = _selection.allPoints(); + for (Set::iterator i = nodes.begin(); i != nodes.end(); ++i) { + if (!(*i)->selected()) { + Node *n = static_cast<Node*>(*i); + unselected.push_back(std::make_pair((*i)->position(), (int) n->_snapTargetType())); + } + } + sm.setupIgnoreSelection(_desktop, true, &unselected); + } + if (held_control(*event)) { + Geom::Point origin = _last_drag_origin(); if (held_alt(*event)) { // with Ctrl+Alt, constrain to handle lines // project the new position onto a handle line that is closer - Geom::Point origin = _last_drag_origin(); - Geom::Line line_front(origin, origin + _front.relativePos()); - Geom::Line line_back(origin, origin + _back.relativePos()); - double dist_front, dist_back; - dist_front = Geom::distance(new_pos, line_front); - dist_back = Geom::distance(new_pos, line_back); - if (dist_front < dist_back) { - new_pos = Geom::projection(new_pos, line_front); + Inkscape::Snapper::ConstraintLine line_front(origin, _front.relativePos()); + Inkscape::Snapper::ConstraintLine line_back(origin, _back.relativePos()); + + // TODO: combine these two branches by modifying snap.h / snap.cpp + if (snap) { + Inkscape::SnappedPoint fp, bp; + fp = sm.constrainedSnap(t, position(), _snapSourceType(), line_front); + bp = sm.constrainedSnap(t, position(), _snapSourceType(), line_back); + + if (fp.isOtherSnapBetter(bp, false)) { + bp.getPoint(new_pos); + } else { + fp.getPoint(new_pos); + } } else { - new_pos = Geom::projection(new_pos, line_back); + Geom::Point p_front = line_front.projection(new_pos); + Geom::Point p_back = line_back.projection(new_pos); + if (Geom::distance(new_pos, p_front) < Geom::distance(new_pos, p_back)) { + new_pos = p_front; + } else { + new_pos = p_back; + } } } else { // with Ctrl, constrain to axes - // TODO maybe add diagonals when the distance from origin is large enough? - Geom::Point origin = _last_drag_origin(); - Geom::Point delta = new_pos - origin; - Geom::Dim2 d = (fabs(delta[Geom::X]) < fabs(delta[Geom::Y])) ? Geom::X : Geom::Y; - new_pos[d] = origin[d]; + // TODO combine the two branches + if (snap) { + Inkscape::SnappedPoint fp, bp; + Inkscape::Snapper::ConstraintLine line_x(origin, Geom::Point(1, 0)); + Inkscape::Snapper::ConstraintLine line_y(origin, Geom::Point(0, 1)); + fp = sm.constrainedSnap(t, position(), _snapSourceType(), line_x); + bp = sm.constrainedSnap(t, position(), _snapSourceType(), line_y); + + if (fp.isOtherSnapBetter(bp, false)) { + fp = bp; + } + fp.getPoint(new_pos); + } else { + Geom::Point origin = _last_drag_origin(); + Geom::Point delta = new_pos - origin; + Geom::Dim2 d = (fabs(delta[Geom::X]) < fabs(delta[Geom::Y])) ? Geom::X : Geom::Y; + new_pos[d] = origin[d]; + } } - } else { - // TODO snapping? + } else if (snap) { + sm.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, new_pos, _snapSourceType()); } } +Inkscape::SnapSourceType Node::_snapSourceType() +{ + if (_type == NODE_SMOOTH || _type == NODE_AUTO) + return SNAPSOURCE_NODE_SMOOTH; + return SNAPSOURCE_NODE_CUSP; +} +Inkscape::SnapTargetType Node::_snapTargetType() +{ + if (_type == NODE_SMOOTH || _type == NODE_AUTO) + return SNAPTARGET_NODE_SMOOTH; + return SNAPTARGET_NODE_CUSP; +} + Glib::ustring Node::_getTip(unsigned state) { if (state_held_shift(state)) { diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h index 167cf90b8..a85877d5c 100644 --- a/src/ui/tool/node.h +++ b/src/ui/tool/node.h @@ -19,6 +19,7 @@ #include <boost/shared_ptr.hpp> #include <boost/optional.hpp> #include <boost/operators.hpp> +#include "snapped-point.h" #include "ui/tool/selectable-control-point.h" #include "ui/tool/node-types.h" @@ -136,8 +137,9 @@ public: void sink(); static char const *node_type_to_localized_string(NodeType type); -protected: + // temporarily public virtual bool _eventHandler(GdkEvent *event); +protected: virtual void _setState(State state); virtual Glib::ustring _getTip(unsigned state); virtual Glib::ustring _getDragTip(GdkEventMotion *event); @@ -151,6 +153,8 @@ private: void _linearGrow(int dir); Node *_next(); Node *_prev(); + Inkscape::SnapSourceType _snapSourceType(); + Inkscape::SnapTargetType _snapTargetType(); static SPCtrlShapeType _node_type_to_shape(NodeType type); static bool _is_line_segment(Node *first, Node *second); diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 2755d6fb3..cfa3846f8 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -214,42 +214,6 @@ void PathManipulator::selectSubpaths() } } -/** Select all nodes in the path. */ -void PathManipulator::selectAll() -{ - for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) { - for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) { - _selection.insert(j.ptr()); - } - } -} - -/** Select points inside the given rectangle. If all points inside it are already selected, - * they will be deselected. - * @param area Area to select - */ -void PathManipulator::selectArea(Geom::Rect const &area) -{ - bool nothing_selected = true; - std::vector<Node*> in_area; - for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) { - for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) { - if (area.contains(j->position())) { - in_area.push_back(j.ptr()); - if (!j->selected()) { - _selection.insert(j.ptr()); - nothing_selected = false; - } - } - } - } - if (nothing_selected) { - for (std::vector<Node*>::iterator i = in_area.begin(); i != in_area.end(); ++i) { - _selection.erase(*i); - } - } -} - /** Move the selection forward or backward by one node in each subpath, based on the sign * of the parameter. */ void PathManipulator::shiftSelection(int dir) @@ -298,17 +262,6 @@ void PathManipulator::shiftSelection(int dir) } } -/** Invert selection in the entire path. */ -void PathManipulator::invertSelection() -{ - for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) { - for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) { - if (j->selected()) _selection.erase(j.ptr()); - else _selection.insert(j.ptr()); - } - } -} - /** Invert selection in the selected subpaths. */ void PathManipulator::invertSelectionInSubpaths() { @@ -724,6 +677,7 @@ void PathManipulator::setControlsTransform(Geom::Matrix const &tnew) _createGeometryFromControlPoints(); } +/** Hide the curve drag point until the next motion event. */ void PathManipulator::hideDragPoint() { _dragpoint->setVisible(false); diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h index 38f66dee0..99e183b45 100644 --- a/src/ui/tool/path-manipulator.h +++ b/src/ui/tool/path-manipulator.h @@ -64,10 +64,7 @@ public: SPPath *item() { return _path; } void selectSubpaths(); - void selectAll(); - void selectArea(Geom::Rect const &); void shiftSelection(int dir); - void invertSelection(); void invertSelectionInSubpaths(); void insertNodes(); diff --git a/src/ui/tool/selectable-control-point.cpp b/src/ui/tool/selectable-control-point.cpp index b189a713f..5b9aa4fc8 100644 --- a/src/ui/tool/selectable-control-point.cpp +++ b/src/ui/tool/selectable-control-point.cpp @@ -50,10 +50,12 @@ SelectableControlPoint::SelectableControlPoint(SPDesktop *d, Geom::Point const & SelectableControlPoint::~SelectableControlPoint() { _selection.erase(this); + _selection.allPoints().erase(this); } void SelectableControlPoint::_connectHandlers() { + _selection.allPoints().insert(this); signal_clicked.connect( sigc::mem_fun(*this, &SelectableControlPoint::_clickedHandler)); signal_grabbed.connect( |
