Code

Reduce libsigc++ usage to partially fix performance regressions
authorKrzysztof Kosiński <tweenk.pl@gmail.com>
Thu, 4 Feb 2010 02:14:09 +0000 (03:14 +0100)
committerKrzysztof Kosiński <tweenk.pl@gmail.com>
Thu, 4 Feb 2010 02:14:09 +0000 (03:14 +0100)
in the new node tool.

15 files changed:
src/ui/tool/control-point-selection.cpp
src/ui/tool/control-point-selection.h
src/ui/tool/control-point.cpp
src/ui/tool/control-point.h
src/ui/tool/curve-drag-point.cpp
src/ui/tool/curve-drag-point.h
src/ui/tool/multi-path-manipulator.cpp
src/ui/tool/node.cpp
src/ui/tool/node.h
src/ui/tool/path-manipulator.cpp
src/ui/tool/path-manipulator.h
src/ui/tool/selectable-control-point.cpp
src/ui/tool/selectable-control-point.h
src/ui/tool/selector.cpp
src/ui/tool/transform-handle-set.cpp

index 615968fef2a68a205863bd95b37787f177ba1b9b..de19fef8d0268d47b37aa05f4603f8f3c6f1f260 100644 (file)
@@ -78,29 +78,7 @@ std::pair<ControlPointSelection::iterator, bool> ControlPointSelection::insert(c
         return std::pair<iterator, bool>(found, false);
     }
 
-    boost::shared_ptr<connlist_type> clist(new connlist_type());
-
-    // hide event param and always return false
-    clist->push_back(
-        x->signal_grabbed.connect(
-            sigc::bind_return(
-                sigc::hide(
-                    sigc::mem_fun(*this, &ControlPointSelection::_pointGrabbed)),
-                false)));
-    clist->push_back(
-        x->signal_dragged.connect(
-                sigc::mem_fun(*this, &ControlPointSelection::_pointDragged)));
-    clist->push_back(
-        x->signal_ungrabbed.connect(
-            sigc::hide(
-                sigc::mem_fun(*this, &ControlPointSelection::_pointUngrabbed))));
-    clist->push_back(
-        x->signal_clicked.connect(
-            sigc::bind<0>(
-                sigc::mem_fun(*this, &ControlPointSelection::_pointClicked),
-                x)));
-
-    found = _points.insert(std::make_pair(x, clist)).first;
+    found = _points.insert(x).first;
 
     x->updateState();
     _rot_radius.reset();
@@ -112,11 +90,7 @@ std::pair<ControlPointSelection::iterator, bool> ControlPointSelection::insert(c
 /** Remove a point from the selection. */
 void ControlPointSelection::erase(iterator pos)
 {
-    SelectableControlPoint *erased = pos->first;
-    boost::shared_ptr<connlist_type> clist = pos->second;
-    for (connlist_type::iterator i = clist->begin(); i != clist->end(); ++i) {
-        i->disconnect();
-    }
+    SelectableControlPoint *erased = *pos;
     _points.erase(pos);
     erased->updateState();
     _rot_radius.reset();
@@ -198,7 +172,7 @@ void ControlPointSelection::spatialGrow(SelectableControlPoint *origin, int dir)
 void ControlPointSelection::transform(Geom::Matrix const &m)
 {
     for (iterator i = _points.begin(); i != _points.end(); ++i) {
-        SelectableControlPoint *cur = i->first;
+        SelectableControlPoint *cur = *i;
         cur->transform(m);
     }
     // TODO preserving the rotation radius needs some rethinking...
@@ -214,14 +188,14 @@ void ControlPointSelection::align(Geom::Dim2 axis)
 
     Geom::OptInterval bound;
     for (iterator i = _points.begin(); i != _points.end(); ++i) {
-        bound.unionWith(Geom::OptInterval(i->first->position()[d]));
+        bound.unionWith(Geom::OptInterval((*i)->position()[d]));
     }
 
     double new_coord = bound->middle();
     for (iterator i = _points.begin(); i != _points.end(); ++i) {
-        Geom::Point pos = i->first->position();
+        Geom::Point pos = (*i)->position();
         pos[d] = new_coord;
-        i->first->move(pos);
+        (*i)->move(pos);
     }
 }
 
@@ -238,8 +212,8 @@ void ControlPointSelection::distribute(Geom::Dim2 d)
     // first we insert all points into a multimap keyed by the aligned coord to sort them
     // simultaneously we compute the extent of selection
     for (iterator i = _points.begin(); i != _points.end(); ++i) {
-        Geom::Point pos = i->first->position();
-        sm.insert(std::make_pair(pos[d], i->first));
+        Geom::Point pos = (*i)->position();
+        sm.insert(std::make_pair(pos[d], (*i)));
         bound.unionWith(Geom::OptInterval(pos[d]));
     }
 
@@ -261,7 +235,7 @@ Geom::OptRect ControlPointSelection::pointwiseBounds()
 {
     Geom::OptRect bound;
     for (iterator i = _points.begin(); i != _points.end(); ++i) {
-        SelectableControlPoint *cur = i->first;
+        SelectableControlPoint *cur = (*i);
         Geom::Point p = cur->position();
         if (!bound) {
             bound = Geom::Rect(p, p);
@@ -276,7 +250,7 @@ Geom::OptRect ControlPointSelection::bounds()
 {
     Geom::OptRect bound;
     for (iterator i = _points.begin(); i != _points.end(); ++i) {
-        SelectableControlPoint *cur = i->first;
+        SelectableControlPoint *cur = (*i);
         Geom::OptRect r = cur->bounds();
         bound.unionWith(r);
     }
@@ -320,7 +294,7 @@ void ControlPointSelection::_pointDragged(Geom::Point const &old_pos, Geom::Poin
 {
     Geom::Point delta = new_pos - old_pos;
     for (iterator i = _points.begin(); i != _points.end(); ++i) {
-        SelectableControlPoint *cur = i->first;
+        SelectableControlPoint *cur = (*i);
         cur->move(cur->position() + delta);
     }
     _handles->rotationCenter().move(_handles->rotationCenter().position() + delta);
@@ -355,7 +329,7 @@ void ControlPointSelection::_updateTransformHandles(bool preserve_center)
         _handles->setBounds(*b, preserve_center);
         _handles->setVisible(true);
     } else if (_one_node_handles && size() == 1) { // only one control point in selection
-        SelectableControlPoint *p = begin()->first;
+        SelectableControlPoint *p = *begin();
         _handles->setBounds(p->bounds());
         _handles->rotationCenter().move(p->position());
         _handles->rotationCenter().setVisible(false);
index 54d724f00062a74ff727f32c64457103a6ff090c..025f9bb618be83927473a0e942c4f1396969ec9d 100644 (file)
@@ -44,14 +44,12 @@ public:
     ControlPointSelection(SPDesktop *d, SPCanvasGroup *th_group);
     ~ControlPointSelection();
     typedef std::list<sigc::connection> connlist_type;
-    typedef std::tr1::unordered_map< SelectableControlPoint *,
-        boost::shared_ptr<connlist_type> > map_type;
     typedef std::tr1::unordered_set< SelectableControlPoint * > set_type;
     typedef set_type Set; // convenience alias
 
-    typedef map_type::iterator iterator;
-    typedef map_type::const_iterator const_iterator;
-    typedef map_type::size_type size_type;
+    typedef set_type::iterator iterator;
+    typedef set_type::const_iterator const_iterator;
+    typedef set_type::size_type size_type;
     typedef SelectableControlPoint *value_type;
     typedef SelectableControlPoint *key_type;
 
@@ -127,7 +125,7 @@ private:
     bool _keyboardFlip(Geom::Dim2);
     void _keyboardTransform(Geom::Matrix const &);
     void _commitTransform(CommitEvent ce);
-    map_type _points;
+    set_type _points;
     set_type _all_points;
     boost::optional<double> _rot_radius;
     TransformHandleSet *_handles;
index 941924e0a73041324021e5712df03d1170d397c7..2eaddc6b4f57a4afcc671df372c8f1c7dc9b3c2f 100644 (file)
@@ -34,46 +34,24 @@ namespace UI {
  * point in the drawing. The drawing can be changed by dragging the point and the things that are
  * attached to it with the mouse. Example things that could be edited with draggable points
  * are gradient stops, the place where text is attached to a path, text kerns, nodes and handles
- * in a path, and many more. Control points use signals heavily - <b>read the libsigc++
- * tutorial on the wiki</b> before using this class.</b>
+ * in a path, and many more.
  *
- * @par Control point signals
+ * @par Control point event handlers
  * @par
- * The control point has several signals which allow you to react to things that happen to it.
- * The most important singals are the grabbed, dragged, ungrabbed and moved signals.
- * When a drag happens, the order of emission is as follows:
- * - <tt>signal_grabbed</tt>
- * - <tt>signal_dragged</tt>
- * - <tt>signal_dragged</tt>
- * - <tt>signal_dragged</tt>
+ * The control point has several virtual methods which allow you to react to things that
+ * happen to it. The most important ones are the grabbed, dragged, ungrabbed and moved functions.
+ * When a drag happens, the order of calls is as follows:
+ * - <tt>grabbed()</tt>
+ * - <tt>dragged()</tt>
+ * - <tt>dragged()</tt>
+ * - <tt>dragged()</tt>
  * - ...
- * - <tt>signal_dragged</tt>
- * - <tt>signal_ungrabbed</tt>
+ * - <tt>dragged()</tt>
+ * - <tt>ungrabbed()</tt>
  *
  * The control point can also respond to clicks and double clicks. On a double click,
- * <tt>signal_clicked</tt> is emitted, followed by <tt>signal_doubleclicked</tt>.
- *
- * A few signal usage hints if you can't be bothered to read the tutorial:
- * - If you want some other object or a global function to react to signals of a control point
- *   from some other object, and you want to access the control point that emitted the signal
- *   in the handler, use <tt>sigc::bind</tt> like this:
- *   @code
- *   void handle_clicked_signal(ControlPoint *point, int button);
- *   point->signal_clicked.connect(
- *       sigc::bind<0>( sigc::ptr_fun(handle_clicked_signal),
- *                      point ));
- *   @endcode
- * - You can ignore unneeded parameters using sigc::hide.
- * - If you want to get rid of the handlers added by constructors in superclasses,
- *   use the <tt>clear()</tt> method: @code signal_clicked.clear(); @endcode
- * - To connect at the front of the slot list instead of at the end, use:
- *   @code
- *   signal_clicked.slots().push_front(
- *       sigc::mem_fun(*this, &FunkyPoint::_clickedHandler));
- *   @endcode
- * - Note that calling <tt>slots()</tt> does not copy anything. You can disconnect
- *   and reorder slots by manipulating the elements of the slot list. The returned object is
- *   of type @verbatim (signal type)::slot_list @endverbatim.
+ * clicked() is called, followed by doubleclicked(). When deriving from SelectableControlPoint,
+ * you need to manually call the superclass version at the appropriate point in your handler.
  *
  * @par Which method to override?
  * @par
@@ -87,46 +65,6 @@ namespace UI {
  *   the setPosition() method.
  */
 
-/**
- * @var ControlPoint::signal_dragged
- * Emitted while dragging, but before moving the knot to new position.
- * Old position will always be the same as position() - there are two parameters
- * only for convenience.
- * - First parameter: old position, always equal to position()
- * - Second parameter: new position (after drag). This is passed as a non-const reference,
- *   so you can change it from the handler - that's how constrained dragging is implemented.
- * - Third parameter: motion event
- */
-
-/**
- * @var ControlPoint::signal_clicked
- * Emitted when the control point is clicked, at mouse button release. The parameter contains
- * the event that caused the signal to be emitted. Your signal handler should return true
- * if the click had some effect. If it did nothing, return false. Improperly handling this signal
- * can cause the context menu not to appear when a control point is right-clicked.
- */
-
-/**
- * @var ControlPoint::signal_doubleclicked
- * Emitted when the control point is doubleclicked, at mouse button release. The parameter
- * contains the event that caused the signal to be emitted. Your signal handler should return true
- * if the double click had some effect. If it did nothing, return false.
- */
-
-/**
- * @var ControlPoint::signal_grabbed
- * Emitted when the control point is grabbed and a drag starts. The parameter contains
- * the causing event. Return true to prevent further processing. Because all control points
- * handle drag tolerance, <tt>signal_dragged</tt> will be emitted immediately after this signal
- * to move the point to its new position.
- */
-
-/**
- * @var ControlPoint::signal_ungrabbed
- * Emitted when the control point finishes a drag. The parameter contains the event which
- * caused the signal, but it can be NULL if the grab was broken.
- */
-
 /**
  * @enum ControlPoint::State
  * Enumeration representing the possible states of the control point, used to determine
@@ -247,9 +185,9 @@ ControlPoint::~ControlPoint()
 
 void ControlPoint::_commonInit()
 {
+    SP_CTRL(_canvas_item)->moveto(_position);
     _event_handler_connection = g_signal_connect(G_OBJECT(_canvas_item), "event",
                                                  G_CALLBACK(_event_handler), this);
-    SP_CTRL(_canvas_item)->moveto(_position);
 }
 
 /** Relocate the control point without side effects.
@@ -408,8 +346,8 @@ bool ControlPoint::_eventHandler(GdkEvent *event)
                 // if we are here, it means the tolerance was just exceeded.
                 next_release_doubleclick = 0;
                 _drag_origin = _position;
-                transferred = signal_grabbed.emit(&event->motion);
-                // _drag_initiated might change during the above signal emission
+                transferred = grabbed(&event->motion);
+                // _drag_initiated might change during the above virtual call
                 if (!_drag_initiated) {
                     // this guarantees smooth redraws while dragging
                     sp_canvas_force_full_redraw_after_interruptions(_desktop->canvas, 5);
@@ -421,7 +359,7 @@ bool ControlPoint::_eventHandler(GdkEvent *event)
                 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);
+                dragged(new_pos, &event->motion);
                 move(new_pos);
                 _updateDragTip(&event->motion); // update dragging tip after moving to new position
                 
@@ -453,17 +391,17 @@ bool ControlPoint::_eventHandler(GdkEvent *event)
 
         if (event->button.button == next_release_doubleclick) {
             _drag_initiated = false;
-            return signal_doubleclicked.emit(&event->button);
+            return doubleclicked(&event->button);
         }
         if (event->button.button == 1) {
             if (_drag_initiated) {
                 // it is the end of a drag
-                signal_ungrabbed.emit(&event->button);
+                ungrabbed(&event->button);
                 _drag_initiated = false;
                 return true;
             } else {
                 // it is the end of a click
-                return signal_clicked.emit(&event->button);
+                return clicked(&event->button);
             }
         }
         _drag_initiated = false;
@@ -479,7 +417,7 @@ bool ControlPoint::_eventHandler(GdkEvent *event)
     case GDK_GRAB_BROKEN:
         if (!event->grab_broken.keyboard && _event_grab) {
             {
-                signal_ungrabbed.emit(0);
+                ungrabbed(NULL);
                 if (_drag_initiated)
                     sp_canvas_end_forced_full_redraws(_desktop->canvas);
             }
@@ -578,7 +516,7 @@ void ControlPoint::transferGrab(ControlPoint *prev_point, GdkEventMotion *event)
 {
     if (!_event_grab) return;
 
-    signal_grabbed.emit(event);
+    grabbed(event);
     sp_canvas_item_ungrab(prev_point->_canvas_item, event->time);
     sp_canvas_item_grab(_canvas_item, _grab_event_mask, NULL, event->time);
 
@@ -615,6 +553,14 @@ void ControlPoint::_setColors(ColorEntry colors)
     g_object_set(_canvas_item, "fill_color", colors.fill, "stroke_color", colors.stroke, NULL);
 }
 
+// dummy implementations for handlers
+// they are here to avoid unused param warnings
+bool ControlPoint::grabbed(GdkEventMotion *) { return false; }
+void ControlPoint::dragged(Geom::Point &, GdkEventMotion *) {}
+void ControlPoint::ungrabbed(GdkEventButton *) {}
+bool ControlPoint::clicked(GdkEventButton *) { return false; }
+bool ControlPoint::doubleclicked(GdkEventButton *) { return false; }
+
 } // namespace UI
 } // namespace Inkscape
 
index e59d6d5cfff64f9e09d9c21880a7b27c406973d1..48c70748b0f465f997089381f8e22feab7d1719d 100644 (file)
@@ -73,11 +73,11 @@ public:
 
     /// @name Receive notifications about control point events
     /// @{
-    sigc::signal<void, Geom::Point const &, Geom::Point &, GdkEventMotion*> signal_dragged;
+    /*sigc::signal<void, Geom::Point const &, Geom::Point &, GdkEventMotion*> signal_dragged;
     sigc::signal<bool, GdkEventButton*>::accumulated<RInt> signal_clicked;
     sigc::signal<bool, GdkEventButton*>::accumulated<RInt> signal_doubleclicked;
     sigc::signal<bool, GdkEventMotion*>::accumulated<Int> signal_grabbed;
-    sigc::signal<void, GdkEventButton*> signal_ungrabbed;
+    sigc::signal<void, GdkEventButton*> signal_ungrabbed;*/
     /// @}
 
     /// @name Inspect the state of the control point
@@ -90,7 +90,7 @@ 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
+    // temporarily public, until snap delay is refactored a little
     virtual bool _eventHandler(GdkEvent *event);
 
 protected:
@@ -99,6 +99,39 @@ protected:
     ControlPoint(SPDesktop *d, Geom::Point const &initial_pos, Gtk::AnchorType anchor,
         Glib::RefPtr<Gdk::Pixbuf> pixbuf, ColorSet *cset = 0, SPCanvasGroup *group = 0);
 
+    /// @name Handle control point events in subclasses
+    /// @{
+    /**
+     * Called when the user moves the point beyond the drag tolerance with the first button held
+     * down. Return true if you called transferGrab() during this method.
+     * @param event Motion event when drag tolerance was exceeded */
+    virtual bool grabbed(GdkEventMotion *event);
+    /**
+     * Called while dragging, but before moving the knot to new position.
+     * @param pos Old position, always equal to position()
+     * @param new_pos New position (after drag). This is passed as a non-const reference,
+     *   so you can change it from the handler - that's how constrained dragging is implemented.
+     * @param event Motion event */
+    virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event);
+    /**
+     * @var ControlPoint::signal_ungrabbed
+     * Emitted when the control point finishes a drag.
+     * @param event Button release event
+     */
+    virtual void ungrabbed(GdkEventButton *event);
+    /**
+     * Called when the control point is clicked, at mouse button release. Your override should
+     * return true if the click had some effect. If it did nothing, return false. Improperly
+     * implementing this method can cause the default context menu not to appear when a control
+     * point is right-clicked.
+     * @param event Button release event */
+    virtual bool clicked(GdkEventButton *event);
+    /**
+     * Called when the control point is doubleclicked, at mouse button release.
+     * @param event Button release event */
+    virtual bool doubleclicked(GdkEventButton *);
+    /// @}
+
     /// @name Manipulate the control point's appearance in subclasses
     /// @{
     virtual void _setState(State state);
index 0e02761736cff695d269f13afbc9e78d5b1bd308..88cb72ed5698d8a952e0b1fac165ce71cea0054c 100644 (file)
@@ -42,23 +42,9 @@ CurveDragPoint::CurveDragPoint(PathManipulator &pm)
     , _pm(pm)
 {
     setVisible(false);
-    signal_grabbed.connect(
-        sigc::bind_return(
-            sigc::mem_fun(*this, &CurveDragPoint::_grabbedHandler),
-            false));
-    signal_dragged.connect(
-            sigc::hide(
-                sigc::mem_fun(*this, &CurveDragPoint::_draggedHandler)));
-    signal_ungrabbed.connect(
-        sigc::hide(
-            sigc::mem_fun(*this, &CurveDragPoint::_ungrabbedHandler)));
-    signal_clicked.connect(
-        sigc::mem_fun(*this, &CurveDragPoint::_clickedHandler));
-    signal_doubleclicked.connect(
-        sigc::mem_fun(*this, &CurveDragPoint::_doubleclickedHandler));
 }
 
-void CurveDragPoint::_grabbedHandler(GdkEventMotion */*event*/)
+bool CurveDragPoint::grabbed(GdkEventMotion */*event*/)
 {
     _pm._selection.hideTransformHandles();
     NodeList::iterator second = first.next();
@@ -71,44 +57,41 @@ void CurveDragPoint::_grabbedHandler(GdkEventMotion */*event*/)
         first->front()->move(first->front()->position() + delta);
         second->back()->move(second->back()->position() - delta);
 
-        signal_update.emit();
+        _pm.update();
     }
+    return false;
 }
 
-void CurveDragPoint::_draggedHandler(Geom::Point const &old_pos, Geom::Point const &new_pos)
+void CurveDragPoint::dragged(Geom::Point &new_pos, GdkEventMotion *)
 {
-    if (_drags_stroke) {
-        // TODO
-    } else {
-        NodeList::iterator second = first.next();
-        // Magic Bezier Drag Equations follow!
-        // "weight" describes how the influence of the drag should be distributed
-        // among the handles; 0 = front handle only, 1 = back handle only.
-        double weight, t = _t;
-        if (t <= 1.0 / 6.0) weight = 0;
-        else if (t <= 0.5) weight = (pow((6 * t - 1) / 2.0, 3)) / 2;
-        else if (t <= 5.0 / 6.0) weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5;
-        else weight = 1;
-
-        Geom::Point delta = new_pos - old_pos;
-        Geom::Point offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta;
-        Geom::Point offset1 = (weight/(3*t*t*(1-t))) * delta;
-
-        first->front()->move(first->front()->position() + offset0);
-        second->back()->move(second->back()->position() + offset1);
-    }
-
-    signal_update.emit();
+    NodeList::iterator second = first.next();
+    // Magic Bezier Drag Equations follow!
+    // "weight" describes how the influence of the drag should be distributed
+    // among the handles; 0 = front handle only, 1 = back handle only.
+    double weight, t = _t;
+    if (t <= 1.0 / 6.0) weight = 0;
+    else if (t <= 0.5) weight = (pow((6 * t - 1) / 2.0, 3)) / 2;
+    else if (t <= 5.0 / 6.0) weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5;
+    else weight = 1;
+
+    Geom::Point delta = new_pos - position();
+    Geom::Point offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta;
+    Geom::Point offset1 = (weight/(3*t*t*(1-t))) * delta;
+
+    first->front()->move(first->front()->position() + offset0);
+    second->back()->move(second->back()->position() + offset1);
+
+    _pm.update();
 }
 
-void CurveDragPoint::_ungrabbedHandler()
+void CurveDragPoint::ungrabbed(GdkEventButton *)
 {
     _pm._updateDragPoint(_desktop->d2w(position()));
     _pm._commit(_("Drag curve"));
     _pm._selection.restoreTransformHandles();
 }
 
-bool CurveDragPoint::_clickedHandler(GdkEventButton *event)
+bool CurveDragPoint::clicked(GdkEventButton *event)
 {
     // This check is probably redundant
     if (!first || event->button != 1) return false;
@@ -141,7 +124,7 @@ bool CurveDragPoint::_clickedHandler(GdkEventButton *event)
     return true;
 }
 
-bool CurveDragPoint::_doubleclickedHandler(GdkEventButton *event)
+bool CurveDragPoint::doubleclicked(GdkEventButton *event)
 {
     if (event->button != 1 || !first || !first.next()) return false;
     _insertNode(true);
@@ -160,7 +143,7 @@ void CurveDragPoint::_insertNode(bool take_selection)
     }
     _pm._selection.insert(inserted.ptr());
 
-    signal_update.emit();
+    _pm.update();
     _pm._commit(_("Add node"));
 }
 
index 51382615e74848291edcbd0bd206dc3cecc6ff17..147a918371c480dfe8f2153fdbc8c41bb38c5153 100644 (file)
@@ -27,15 +27,15 @@ public:
     void setSize(double sz) { _setSize(sz); }
     void setTimeValue(double t) { _t = t; }
     void setIterator(NodeList::iterator i) { first = i; }
-    sigc::signal<void> signal_update;
 protected:
     virtual Glib::ustring _getTip(unsigned state);
 private:
-    void _grabbedHandler(GdkEventMotion *);
-    void _draggedHandler(Geom::Point const &, Geom::Point const &);
-    bool _clickedHandler(GdkEventButton *);
-    bool _doubleclickedHandler(GdkEventButton *);
-    void _ungrabbedHandler();
+    virtual void dragged(Geom::Point &, GdkEventMotion *);
+    virtual bool grabbed(GdkEventMotion *);
+    virtual void ungrabbed(GdkEventButton *);
+    virtual bool clicked(GdkEventButton *);
+    virtual bool doubleclicked(GdkEventButton *);
+
     void _insertNode(bool take_selection);
     double _t;
     PathManipulator &_pm;
index d133fcf25fa05dc792cc77342ab1bb662402dfee..c34ef066e48d448a88ce52b642e1830e9315715e 100644 (file)
@@ -45,7 +45,7 @@ void find_join_iterators(ControlPointSelection &sel, IterPairList &pairs)
 
     // find all endnodes in selection
     for (ControlPointSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
-        Node *node = dynamic_cast<Node*>(i->first);
+        Node *node = dynamic_cast<Node*>(*i);
         if (!node) continue;
         NodeList::iterator iter = NodeList::get_iterator(node);
         if (!iter.next() || !iter.prev()) join_iters.insert(iter);
@@ -203,7 +203,7 @@ void MultiPathManipulator::setNodeType(NodeType type)
 {
     if (_selection.empty()) return;
     for (ControlPointSelection::iterator i = _selection.begin(); i != _selection.end(); ++i) {
-        Node *node = dynamic_cast<Node*>(i->first);
+        Node *node = dynamic_cast<Node*>(*i);
         if (node) node->setType(type);
     }
     _done(_("Change node type"));
index 2675b4045f796a82c2d38429fafbc88c9a207cec..6419acf6d32e12bc842a43a9a14584035e7f7c1b 100644 (file)
@@ -89,20 +89,10 @@ Handle::Handle(NodeSharedData const &data, Geom::Point const &initial_pos, Node
     _cset = &handle_colors;
     _handle_line = sp_canvas_item_new(data.handle_line_group, SP_TYPE_CTRLLINE, NULL);
     setVisible(false);
-    signal_grabbed.connect(
-        sigc::bind_return(
-            sigc::hide(
-                sigc::mem_fun(*this, &Handle::_grabbedHandler)),
-            false));
-    signal_dragged.connect(
-        sigc::hide<0>(
-            sigc::mem_fun(*this, &Handle::_draggedHandler)));
-    signal_ungrabbed.connect(
-        sigc::hide(sigc::mem_fun(*this, &Handle::_ungrabbedHandler)));
 }
 Handle::~Handle()
 {
-    sp_canvas_item_hide(_handle_line);
+    //sp_canvas_item_hide(_handle_line);
     gtk_object_destroy(GTK_OBJECT(_handle_line));
 }
 
@@ -232,12 +222,14 @@ char const *Handle::handle_type_to_localized_string(NodeType type)
     }
 }
 
-void Handle::_grabbedHandler()
+bool Handle::grabbed(GdkEventMotion *)
 {
     _saved_length = _drag_out ? 0 : length();
+    _pm()._handleGrabbed();
+    return false;
 }
 
-void Handle::_draggedHandler(Geom::Point &new_pos, GdkEventMotion *event)
+void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
 {
     Geom::Point parent_pos = _parent->position();
     // with Alt, preserve length
@@ -253,12 +245,13 @@ void Handle::_draggedHandler(Geom::Point &new_pos, GdkEventMotion *event)
         new_pos = parent_pos + Geom::constrain_angle(Geom::Point(0,0), new_pos - parent_pos, snaps,
             _drag_out ? Geom::Point(1,0) : Geom::unit_vector(rel_origin));
     }
-    signal_update.emit();
+    _pm().update();
 }
 
-void Handle::_ungrabbedHandler()
+void Handle::ungrabbed(GdkEventButton *)
 {
     // hide the handle if it's less than dragtolerance away from the node
+    // TODO is this actually desired?
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
     int drag_tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
 
@@ -267,6 +260,14 @@ void Handle::_ungrabbedHandler()
         move(_parent->position());
     }
     _drag_out = false;
+
+    _pm()._handleUngrabbed();
+}
+
+bool Handle::clicked(GdkEventButton *event)
+{
+    _pm()._handleClicked(this, event);
+    return true;
 }
 
 static double snap_increment_degrees() {
@@ -337,11 +338,6 @@ Node::Node(NodeSharedData const &data, Geom::Point const &initial_pos)
     , _handles_shown(false)
 {
     // NOTE we do not set type here, because the handles are still degenerate
-    // connect to own grabbed signal - dragging out handles
-    signal_grabbed.connect(
-        sigc::mem_fun(*this, &Node::_grabbedHandler));
-    signal_dragged.connect( sigc::hide<0>(
-        sigc::mem_fun(*this, &Node::_draggedHandler)));
 }
 
 // NOTE: not using iterators won't make this much quicker because iterators can be 100% inlined.
@@ -807,8 +803,11 @@ void Node::_setState(State state)
     SelectableControlPoint::_setState(state);
 }
 
-bool Node::_grabbedHandler(GdkEventMotion *event)
+bool Node::grabbed(GdkEventMotion *event)
 {
+    if (SelectableControlPoint::grabbed(event))
+        return true;
+
     // Dragging out handles with Shift + drag on a node.
     if (!held_shift(*event)) return false;
 
@@ -843,7 +842,7 @@ bool Node::_grabbedHandler(GdkEventMotion *event)
     return true;
 }
 
-void Node::_draggedHandler(Geom::Point &new_pos, GdkEventMotion *event)
+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;
@@ -923,6 +922,15 @@ void Node::_draggedHandler(Geom::Point &new_pos, GdkEventMotion *event)
     } else if (snap) {
         sm.freeSnapReturnByRef(new_pos, _snapSourceType());
     }
+
+    SelectableControlPoint::dragged(new_pos, event);
+}
+
+bool Node::clicked(GdkEventButton *event)
+{
+    if(_pm()._nodeClicked(this, event))
+        return true;
+    return SelectableControlPoint::clicked(event);
 }
 
 Inkscape::SnapSourceType Node::_snapSourceType()
@@ -1080,7 +1088,6 @@ NodeList::iterator NodeList::insert(iterator i, Node *x)
     ins->prev->next = x;
     ins->prev = x;
     x->ListNode::list = this;
-    _list.signal_insert_node.emit(x);
     return iterator(x);
 }
 
@@ -1100,9 +1107,7 @@ void NodeList::splice(iterator pos, NodeList &list, iterator first, iterator las
 {
     ListNode *ins_beg = first._node, *ins_end = last._node, *at = pos._node;
     for (ListNode *ln = ins_beg; ln != ins_end; ln = ln->next) {
-        list._list.signal_remove_node.emit(static_cast<Node*>(ln));
         ln->list = this;
-        _list.signal_insert_node.emit(static_cast<Node*>(ln));
     }
     ins_beg->prev->next = ins_end;
     ins_end->prev->next = at;
@@ -1157,7 +1162,6 @@ NodeList::iterator NodeList::erase(iterator i)
     Node *rm = static_cast<Node*>(i._node);
     ListNode *rmnext = rm->next, *rmprev = rm->prev;
     ++i;
-    _list.signal_remove_node.emit(rm);
     delete rm;
     rmprev->next = rmnext;
     rmnext->prev = rmprev;
index d822d854f100971a1eda0d697e527bf54a9d7e17..581cc9b6fe9e41dab25fcd61d3aa2f5da6ea8b98 100644 (file)
@@ -11,6 +11,7 @@
 #ifndef SEEN_UI_TOOL_NODE_H
 #define SEEN_UI_TOOL_NODE_H
 
+#include <glib.h>
 #include <iterator>
 #include <iosfwd>
 #include <stdexcept>
@@ -97,16 +98,19 @@ public:
     Node *parent() { return _parent; }
 
     static char const *handle_type_to_localized_string(NodeType type);
-    sigc::signal<void> signal_update;
 protected:
     Handle(NodeSharedData const &data, Geom::Point const &initial_pos, Node *parent);
+
+    virtual void dragged(Geom::Point &, GdkEventMotion *);
+    virtual bool grabbed(GdkEventMotion *);
+    virtual void ungrabbed(GdkEventButton *);
+    virtual bool clicked(GdkEventButton *);
+
     virtual Glib::ustring _getTip(unsigned state);
     virtual Glib::ustring _getDragTip(GdkEventMotion *event);
     virtual bool _hasDragTips() { return true; }
 private:
-    void _grabbedHandler();
-    void _draggedHandler(Geom::Point &, GdkEventMotion *);
-    void _ungrabbedHandler();
+    inline PathManipulator &_pm();
     Node *_parent; // the handle's lifetime does not extend beyond that of the parent node,
     // so a naked pointer is OK and allows setting it during Node's construction
     SPCanvasItem *_handle_line;
@@ -140,14 +144,16 @@ public:
     // temporarily public
     virtual bool _eventHandler(GdkEvent *event);
 protected:
+    virtual void dragged(Geom::Point &, GdkEventMotion *);
+    virtual bool grabbed(GdkEventMotion *);
+    virtual bool clicked(GdkEventButton *);
+
     virtual void _setState(State state);
     virtual Glib::ustring _getTip(unsigned state);
     virtual Glib::ustring _getDragTip(GdkEventMotion *event);
     virtual bool _hasDragTips() { return true; }
 private:
     Node(Node const &);
-    bool _grabbedHandler(GdkEventMotion *);
-    void _draggedHandler(Geom::Point &, GdkEventMotion *);
     void _fixNeighbors(Geom::Point const &old_pos, Geom::Point const &new_pos);
     void _updateAutoHandles();
     void _linearGrow(int dir);
@@ -155,6 +161,7 @@ private:
     Node *_prev();
     Inkscape::SnapSourceType _snapSourceType();
     Inkscape::SnapTargetType _snapTargetType();
+    inline PathManipulator &_pm();
     static SPCtrlShapeType _node_type_to_shape(NodeType type);
     static bool _is_line_segment(Node *first, Node *second);
 
@@ -327,8 +334,6 @@ public:
 
     SubpathList(PathManipulator &pm) : _path_manipulator(pm) {}
 
-    sigc::signal<void, Node *> signal_insert_node;
-    sigc::signal<void, Node *> signal_remove_node;
 private:
     list_type _nodelists;
     PathManipulator &_path_manipulator;
@@ -349,6 +354,12 @@ inline void Handle::setRelativePos(Geom::Point const &p) {
 inline double Handle::length() {
     return relativePos().length();
 }
+inline PathManipulator &Handle::_pm() {
+    return _parent->_pm();
+}
+inline PathManipulator &Node::_pm() {
+    return list()->_list._path_manipulator;
+}
 
 // definitions for node iterator
 template <typename N>
@@ -359,14 +370,14 @@ template <typename N>
 NodeIterator<N> NodeIterator<N>::next() const {
     NodeIterator<N> ret(*this);
     ++ret;
-    if (!ret && _node->list->closed()) ++ret;
+    if (G_UNLIKELY(!ret) && _node->list->closed()) ++ret;
     return ret;
 }
 template <typename N>
 NodeIterator<N> NodeIterator<N>::prev() const {
     NodeIterator<N> ret(*this);
     --ret;
-    if (!ret && _node->list->closed()) --ret;
+    if (G_UNLIKELY(!ret) && _node->list->closed()) --ret;
     return ret;
 }
 
index 0ce02aa95e504ca048af83b52f15393693d39a95..43955edbfa9303fd15180d78d9e7d75a918b1f80 100644 (file)
@@ -119,19 +119,10 @@ PathManipulator::PathManipulator(MultiPathManipulator &mpm, SPPath *path,
         SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
     sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(_outline), 0, SP_WIND_RULE_NONZERO);
 
-    _subpaths.signal_insert_node.connect(
-        sigc::mem_fun(*this, &PathManipulator::_attachNodeHandlers));
-    // NOTE: signal_remove_node is called just before destruction. Nodes are trackable,
-    // so removing the signals manually is not necessary.
-    /*_subpaths.signal_remove_node.connect(
-        sigc::mem_fun(*this, &PathManipulator::_removeNodeHandlers));*/
-
     _selection.signal_update.connect(
         sigc::mem_fun(*this, &PathManipulator::update));
     _selection.signal_point_changed.connect(
         sigc::mem_fun(*this, &PathManipulator::_selectionChanged));
-    _dragpoint->signal_update.connect(
-        sigc::mem_fun(*this, &PathManipulator::update));
     _desktop->signal_zoom_changed.connect(
         sigc::hide( sigc::mem_fun(*this, &PathManipulator::_updateOutlineOnZoomChange)));
 
@@ -1174,34 +1165,8 @@ Inkscape::XML::Node *PathManipulator::_getXMLNode()
     return LIVEPATHEFFECT(_path)->repr;
 }
 
-void PathManipulator::_attachNodeHandlers(Node *node)
-{
-    Handle *handles[2] = { node->front(), node->back() };
-    for (int i = 0; i < 2; ++i) {
-        handles[i]->signal_update.connect(
-            sigc::mem_fun(*this, &PathManipulator::update));
-        handles[i]->signal_ungrabbed.connect(
-            sigc::hide(
-                sigc::mem_fun(*this, &PathManipulator::_handleUngrabbed)));
-        handles[i]->signal_grabbed.connect(
-            sigc::bind_return(
-                sigc::hide(
-                    sigc::mem_fun(*this, &PathManipulator::_handleGrabbed)),
-                false));
-        handles[i]->signal_clicked.connect(
-            sigc::bind<0>(
-                sigc::mem_fun(*this, &PathManipulator::_handleClicked),
-                handles[i]));
-    }
-    node->signal_clicked.connect(
-        sigc::bind<0>(
-            sigc::mem_fun(*this, &PathManipulator::_nodeClicked),
-            node));
-}
-
 bool PathManipulator::_nodeClicked(Node *n, GdkEventButton *event)
 {
-    // cycle between node types on ctrl+click
     if (event->button != 1) return false;
     if (held_alt(*event) && held_control(*event)) {
         // Ctrl+Alt+click: delete nodes
index 6b69e226a7665effc6a0e4d5548f8e8a2351af07..1e9e5057547952cfd0a56b4dbc385aa23a20d5d6 100644 (file)
@@ -104,7 +104,6 @@ private:
     Glib::ustring _nodetypesKey();
     Inkscape::XML::Node *_getXMLNode();
 
-    void _attachNodeHandlers(Node *n);
     void _selectionChanged(SelectableControlPoint *p, bool selected);
     bool _nodeClicked(Node *, GdkEventButton *);
     void _handleGrabbed();
@@ -139,6 +138,7 @@ private:
     friend class PathManipulatorObserver;
     friend class CurveDragPoint;
     friend class Node;
+    friend class Handle;
 };
 
 } // namespace UI
index 9039bd53320f81c4a699673ac0c9533d94ba085e..1835f0008594cb9e4615ea662c8d9d10f68e14a0 100644 (file)
@@ -34,7 +34,7 @@ SelectableControlPoint::SelectableControlPoint(SPDesktop *d, Geom::Point const &
         : reinterpret_cast<ControlPoint::ColorSet*>(&default_scp_color_set), group)
     , _selection (sel)
 {
-    _connectHandlers();
+    _selection.allPoints().insert(this);
 }
 SelectableControlPoint::SelectableControlPoint(SPDesktop *d, Geom::Point const &initial_pos,
         Gtk::AnchorType anchor, Glib::RefPtr<Gdk::Pixbuf> pixbuf,
@@ -44,7 +44,7 @@ SelectableControlPoint::SelectableControlPoint(SPDesktop *d, Geom::Point const &
         : reinterpret_cast<ControlPoint::ColorSet*>(&default_scp_color_set), group)
     , _selection (sel)
 {
-    _connectHandlers();
+    _selection.allPoints().insert(this);
 }
 
 SelectableControlPoint::~SelectableControlPoint()
@@ -53,28 +53,31 @@ SelectableControlPoint::~SelectableControlPoint()
     _selection.allPoints().erase(this);
 }
 
-void SelectableControlPoint::_connectHandlers()
-{
-    _selection.allPoints().insert(this);
-    signal_grabbed.connect(
-        sigc::bind_return(
-            sigc::hide(
-                sigc::mem_fun(*this, &SelectableControlPoint::_grabbedHandler)),
-            false));
-    signal_clicked.connect(
-        sigc::mem_fun(*this, &SelectableControlPoint::_clickedHandler));
-}
-
-void SelectableControlPoint::_grabbedHandler()
+bool SelectableControlPoint::grabbed(GdkEventMotion *)
 {
     // if a point is dragged while not selected, it should select itself
     if (!selected()) {
         _takeSelection();
     }
+    _selection._pointGrabbed();
+    return false;
 }
 
-bool SelectableControlPoint::_clickedHandler(GdkEventButton *event)
+void SelectableControlPoint::dragged(Geom::Point &new_pos, GdkEventMotion *event)
 {
+    _selection._pointDragged(position(), new_pos, event);
+}
+
+void SelectableControlPoint::ungrabbed(GdkEventButton *)
+{
+    _selection._pointUngrabbed();
+}
+
+bool SelectableControlPoint::clicked(GdkEventButton *event)
+{
+    if (_selection._pointClicked(this, event))
+        return true;
+
     if (event->button != 1) return false;
     if (held_shift(*event)) {
         if (selected()) {
index f5e9541c30661f580f1789c28231d716eaf90b88..2fde16ea94dfd596e58a74e53c2f6859c73961d5 100644 (file)
@@ -45,13 +45,14 @@ protected:
 
     virtual void _setState(State state);
 
+    virtual void dragged(Geom::Point &, GdkEventMotion *);
+    virtual bool grabbed(GdkEventMotion *);
+    virtual void ungrabbed(GdkEventButton *);
+    virtual bool clicked(GdkEventButton *);
+
     ControlPointSelection &_selection;
 private:
-    void _connectHandlers();
     void _takeSelection();
-    
-    void _grabbedHandler();
-    bool _clickedHandler(GdkEventButton *);
 };
 
 } // namespace UI
index bf3ea67144016c221237b0329e9e2361b2140261..8d3cf565059b21a0c746d0cfd46a72d29a06def3 100644 (file)
@@ -36,17 +36,6 @@ public:
         _rubber = static_cast<CtrlRect*>(sp_canvas_item_new(sp_desktop_controls(_desktop),
         SP_TYPE_CTRLRECT, NULL));
         sp_canvas_item_hide(_rubber);
-
-        signal_clicked.connect(sigc::mem_fun(*this, &SelectorPoint::_clicked));
-        signal_grabbed.connect(
-            sigc::bind_return(
-                sigc::hide(
-                    sigc::mem_fun(*this, &SelectorPoint::_grabbed)),
-                false));
-        signal_dragged.connect(
-                sigc::hide<0>( sigc::hide(
-                    sigc::mem_fun(*this, &SelectorPoint::_dragged))));
-        signal_ungrabbed.connect(sigc::mem_fun(*this, &SelectorPoint::_ungrabbed));
     }
     ~SelectorPoint() {
         gtk_object_destroy(_rubber);
@@ -69,27 +58,28 @@ protected:
     }
 
 private:
-    bool _clicked(GdkEventButton *event) {
-        if (event->button != 1) return false;
-        _selector->signal_point.emit(position(), event);
-        return true;
-    }
-    void _grabbed() {
+    virtual bool grabbed(GdkEventMotion *) {
         _cancel = false;
         _start = position();
         sp_canvas_item_show(_rubber);
+        return false;
     }
-    void _dragged(Geom::Point &new_pos) {
+    virtual void dragged(Geom::Point &new_pos, GdkEventMotion *) {
         if (_cancel) return;
         Geom::Rect sel(_start, new_pos);
         _rubber->setRectangle(sel);
     }
-    void _ungrabbed(GdkEventButton *event) {
+    virtual void ungrabbed(GdkEventButton *event) {
         if (_cancel) return;
         sp_canvas_item_hide(_rubber);
         Geom::Rect sel(_start, position());
         _selector->signal_area.emit(sel, event);
     }
+    virtual bool clicked(GdkEventButton *event) {
+        if (event->button != 1) return false;
+        _selector->signal_point.emit(position(), event);
+        return true;
+    }
     CtrlRect *_rubber;
     Selector *_selector;
     Geom::Point _start;
index f9086950dc3011c06ae3494a8df2684cd75dd729..1af848b964d0a0930d6088df5365ef150dfcc55b 100644 (file)
@@ -84,17 +84,6 @@ public:
         , _th(th)
     {
         setVisible(false);
-        signal_grabbed.connect(
-            sigc::bind_return(
-                sigc::hide(
-                    sigc::mem_fun(*this, &TransformHandle::_grabbedHandler)),
-                false));
-        signal_dragged.connect(
-            sigc::hide<0>(
-                sigc::mem_fun(*this, &TransformHandle::_draggedHandler)));
-        signal_ungrabbed.connect(
-            sigc::hide(
-                sigc::mem_fun(*this, &TransformHandle::_ungrabbedHandler)));
     }
 protected:
     virtual void startTransform() {}
@@ -106,7 +95,7 @@ protected:
     Geom::Point _origin;
     TransformHandleSet &_th;
 private:
-    void _grabbedHandler() {
+    virtual bool grabbed(GdkEventMotion *) {
         _origin = position();
         _last_transform.setIdentity();
         startTransform();
@@ -114,8 +103,9 @@ private:
         _th._setActiveHandle(this);
         _cset = &invisible_cset;
         _setState(_state);
+        return false;
     }
-    void _draggedHandler(Geom::Point &new_pos, GdkEventMotion *event)
+    virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event)
     {
         Geom::Matrix t = computeTransform(new_pos, event);
         // protect against degeneracies
@@ -125,7 +115,7 @@ private:
         _th.signal_transform.emit(incr);
         _last_transform = t;
     }
-    void _ungrabbedHandler() {
+    virtual void ungrabbed(GdkEventButton *) {
         _th._clearActiveHandle();
         _cset = &thandle_cset;
         _setState(_state);