Code

Node tool: snap while scaling a selection of nodes. Consider this as experimental...
[inkscape.git] / src / ui / tool / control-point-selection.h
index 0f0daffaa4cdb0143d8e546d03c80a9c86cd7209..0e5acf6c5cc84e05151f5f8de19915117a02f20a 100644 (file)
@@ -1,5 +1,5 @@
 /** @file
- * Node selection - stores a set of nodes and applies transformations
+ * Control point selection - stores a set of control points and applies transformations
  * to them
  */
 /* Authors:
@@ -9,46 +9,44 @@
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
-#ifndef SEEN_UI_TOOL_NODE_SELECTION_H
-#define SEEN_UI_TOOL_NODE_SELECTION_H
+#ifndef SEEN_UI_TOOL_CONTROL_POINT_SELECTION_H
+#define SEEN_UI_TOOL_CONTROL_POINT_SELECTION_H
 
 #include <memory>
-#include <tr1/unordered_map>
-#include <boost/shared_ptr.hpp>
-#include <boost/weak_ptr.hpp>
 #include <boost/optional.hpp>
 #include <sigc++/sigc++.h>
 #include <2geom/forward.h>
 #include <2geom/point.h>
-#include "display/display-forward.h"
+#include <2geom/rect.h>
 #include "util/accumulators.h"
-#include "util/hash.h"
+#include "util/unordered-containers.h"
 #include "ui/tool/commit-events.h"
 #include "ui/tool/manipulator.h"
-
-namespace std { using namespace tr1; }
+#include "snap-candidate.h"
 
 class SPDesktop;
+struct SPCanvasGroup;
 
 namespace Inkscape {
 namespace UI {
-
 class TransformHandleSet;
 class SelectableControlPoint;
+}
+}
 
-class ControlPointSelection : public Manipulator {
+namespace Inkscape {
+namespace UI {
+
+class ControlPointSelection : public Manipulator, public sigc::trackable {
 public:
     ControlPointSelection(SPDesktop *d, SPCanvasGroup *th_group);
     ~ControlPointSelection();
-    typedef std::list<sigc::connection> connlist_type;
-    typedef std::unordered_map< SelectableControlPoint *,
-        boost::shared_ptr<connlist_type> > map_type;
-
-    // boilerplate typedefs
-    typedef map_type::iterator iterator;
-    typedef map_type::const_iterator const_iterator;
-    typedef map_type::size_type size_type;
+    typedef INK_UNORDERED_SET<SelectableControlPoint *> set_type;
+    typedef set_type Set; // convenience alias
 
+    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;
 
@@ -78,7 +76,18 @@ public:
     void erase(iterator first, iterator last);
 
     // find
-    iterator find(const key_type &k) { return _points.find(k); }
+    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 *);
 
@@ -89,38 +98,56 @@ public:
     Geom::OptRect pointwiseBounds();
     Geom::OptRect bounds();
 
+    bool transformHandlesEnabled() { return _handles_visible; }
     void showTransformHandles(bool v, bool one_node);
     // the two methods below do not modify the state; they are for use in manipulators
-    // that need to temporarily hide the handles
+    // that need to temporarily hide the handles, for example when moving a node
     void hideTransformHandles();
     void restoreTransformHandles();
-    
-    // TODO this is really only applicable to nodes... maybe derive a NodeSelection?
-    void setSculpting(bool v) { _sculpt_enabled = v; }
+    void toggleTransformHandlesMode();
 
     sigc::signal<void> signal_update;
     sigc::signal<void, SelectableControlPoint *, bool> signal_point_changed;
     sigc::signal<void, CommitEvent> signal_commit;
+
+    std::vector<Inkscape::SnapCandidatePoint> getOriginalPoints();
+    void setOriginalPoints();
+
 private:
-    void _selectionGrabbed(SelectableControlPoint *, GdkEventMotion *);
-    void _selectionDragged(Geom::Point const &, Geom::Point &, GdkEventMotion *);
-    void _selectionUngrabbed();
+    // The functions below are invoked from SelectableControlPoint.
+    // Previously they were connected to handlers when selecting, but this
+    // creates problems when dragging a point that was not selected.
+    void _pointGrabbed(SelectableControlPoint *);
+    void _pointDragged(Geom::Point &, GdkEventMotion *);
+    void _pointUngrabbed();
+    bool _pointClicked(SelectableControlPoint *, GdkEventButton *);
+    void _pointChanged(SelectableControlPoint *, bool);
+    void _mouseoverChanged();
+
     void _updateTransformHandles(bool preserve_center);
+    void _updateBounds();
     bool _keyboardMove(GdkEventKey const &, Geom::Point const &);
     bool _keyboardRotate(GdkEventKey const &, int);
     bool _keyboardScale(GdkEventKey const &, int);
     bool _keyboardFlip(Geom::Dim2);
     void _keyboardTransform(Geom::Matrix const &);
-    void _commitTransform(CommitEvent ce);
-    map_type _points;
+    void _commitHandlesTransform(CommitEvent ce);
+    double _rotationRadius(Geom::Point const &);
+
+    set_type _points;
+    set_type _all_points;
+    INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Point> _original_positions;
+    INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Matrix> _last_trans;
     boost::optional<double> _rot_radius;
+    boost::optional<double> _mouseover_rot_radius;
+    Geom::OptRect _bounds;
     TransformHandleSet *_handles;
-    SelectableControlPoint *_grabbed_point;
+    SelectableControlPoint *_grabbed_point, *_farthest_point;
     unsigned _dragging         : 1;
     unsigned _handles_visible  : 1;
     unsigned _one_node_handles : 1;
-    unsigned _sculpt_enabled   : 1;
-    unsigned _sculpting        : 1;
+
+    friend class SelectableControlPoint;
 };
 
 } // namespace UI
@@ -137,4 +164,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 :