Code

Node tool: snap while scaling a selection of nodes. Consider this as experimental...
[inkscape.git] / src / snap.h
1 /**
2  * \file snap.h
3  * \brief Per-desktop object that handles snapping queries
4  *//*
5  * Authors:
6  *   Lauris Kaplinski <lauris@kaplinski.com>
7  *   Frank Felfe <innerspace@iname.com>
8  *   Carl Hetherington <inkscape@carlh.net>
9  *   Diederik van Lierop <mail@diedenrezi.nl>
10  *
11  * Copyright (C) 2006-2007 Johan Engelen <johan@shouraizou.nl>
12  * Copyright (C) 2000-2002 Lauris Kaplinski
13  * Copyright (C) 2000-2010 Authors
14  *
15  * Released under GNU GPL, read the file 'COPYING' for more information
16  */
18 #ifndef SEEN_SNAP_H
19 #define SEEN_SNAP_H
21 #include <vector>
22 #include "guide-snapper.h"
23 #include "object-snapper.h"
24 #include "snap-preferences.h"
26 /* Guides */
27 enum SPGuideDragType { // used both here and in desktop-events.cpp
28     SP_DRAG_TRANSLATE,
29     SP_DRAG_ROTATE,
30     SP_DRAG_MOVE_ORIGIN,
31     SP_DRAG_NONE
32 };
34 class SPNamedView;
36 /// Class to coordinate snapping operations
37 /**
38  * The SnapManager class handles most (if not all) of the interfacing of the snapping mechanisms
39  * with the other parts of the code base. It stores the references to the various types of snappers
40  * for grid, guides and objects, and it stores most of the snapping preferences. Besides that
41  * it provides methods to setup the snapping environment (e.g. keeps a list of the items to ignore
42  * when looking for snap target candidates, and toggling of the snap indicator), and it provides
43  * many different methods for snapping queries (free snapping vs. constrained snapping,
44  * returning the result by reference or through a return statement, etc.)
45  * 
46  * Each SPNamedView has one of these.  It offers methods to snap points to whatever
47  * snappers are defined (e.g. grid, guides etc.).  It also allows callers to snap
48  * points which have undergone some transformation (e.g. translation, scaling etc.)
49  *
50  * \par How snapping is implemented in Inkscape
51  * \par
52  * The snapping system consists of two key elements. The first one is the snap manager
53  * (this class), which keeps some data about objects in the document and answers queries
54  * of the type "given this point and type of transformation, what is the best place
55  * to snap to?".
56  * 
57  * The second is in event-context.cpp and implements the snapping timeout. Whenever a motion
58  * events happens over the canvas, it stores it for later use and initiates a timeout.
59  * This timeout is discarded whenever a new motion event occurs. When the timeout expires,
60  * a global flag in SnapManager, accessed via getSnapPostponedGlobally(), is set to true
61  * and the stored event is replayed, but this time with snapping enabled. This way you can
62  * write snapping code directly in your control point's dragged handler as if there was
63  * no timeout.
64  */
66 class SnapManager
67 {
68 public:
69     enum Transformation {
70         TRANSLATE,
71         SCALE,
72         STRETCH,
73         SKEW,
74         ROTATE
75     };
77     SnapManager(SPNamedView const *v);
79     typedef std::list<const Inkscape::Snapper*> SnapperList;
81     bool someSnapperMightSnap() const;
82     bool gridSnapperMightSnap() const;
84     void setup(SPDesktop const *desktop,
85             bool snapindicator = true,
86             SPItem const *item_to_ignore = NULL,
87             std::vector<Inkscape::SnapCandidatePoint> *unselected_nodes = NULL,
88             SPGuide *guide_to_ignore = NULL);
90     void setup(SPDesktop const *desktop,
91                bool snapindicator,
92                std::vector<SPItem const *> &items_to_ignore,
93                std::vector<Inkscape::SnapCandidatePoint> *unselected_nodes = NULL,
94                SPGuide *guide_to_ignore = NULL);
96     void setupIgnoreSelection(SPDesktop const *desktop,
97                               bool snapindicator = true,
98                               std::vector<Inkscape::SnapCandidatePoint> *unselected_nodes = NULL,
99                               SPGuide *guide_to_ignore = NULL);
101     void unSetup() {_rotation_center_source_items = NULL;
102                     _guide_to_ignore = NULL;
103                     _desktop = NULL;
104                     _unselected_nodes = NULL;}
106     // If we're dragging a rotation center, then setRotationCenterSource() stores the parent item
107     // of this rotation center; this reference is used to make sure that we do not snap a rotation
108     // center to itself
109     // NOTE: Must be called after calling setup(), not before!
110     void setRotationCenterSource(GSList *items) {_rotation_center_source_items = items;}
111     GSList const *getRotationCenterSource() {return _rotation_center_source_items;}
113     // freeSnapReturnByRef() is preferred over freeSnap(), because it only returns a
114     // point if snapping has occurred (by overwriting p); otherwise p is untouched
115     void freeSnapReturnByRef(Geom::Point &p,
116                                 Inkscape::SnapSourceType const source_type,
117                                 Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const;
119     Inkscape::SnappedPoint freeSnap(Inkscape::SnapCandidatePoint const &p,
120                                     Geom::OptRect const &bbox_to_snap = Geom::OptRect() ) const;
122     void preSnap(Inkscape::SnapCandidatePoint const &p);
124     Geom::Point multipleOfGridPitch(Geom::Point const &t, Geom::Point const &origin);
126     // constrainedSnapReturnByRef() is preferred over constrainedSnap(), because it only returns a
127     // point, by overwriting p, if snapping has occurred; otherwise p is untouched
128     void constrainedSnapReturnByRef(Geom::Point &p,
129                                     Inkscape::SnapSourceType const source_type,
130                                     Inkscape::Snapper::SnapConstraint const &constraint,
131                                     Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const;
133     Inkscape::SnappedPoint constrainedSnap(Inkscape::SnapCandidatePoint const &p,
134                                            Inkscape::Snapper::SnapConstraint const &constraint,
135                                            Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const;
137     Inkscape::SnappedPoint multipleConstrainedSnaps(Inkscape::SnapCandidatePoint const &p,
138                                                     std::vector<Inkscape::Snapper::SnapConstraint> const &constraints,
139                                                     bool dont_snap = false,
140                                                     Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const;
142     Inkscape::SnappedPoint constrainedAngularSnap(Inkscape::SnapCandidatePoint const &p,
143                                                     boost::optional<Geom::Point> const &p_ref,
144                                                     Geom::Point const &o,
145                                                     unsigned const snaps) const;
147     void guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SPGuideDragType drag_type) const;
148     void guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const;
150     Inkscape::SnappedPoint freeSnapTranslate(std::vector<Inkscape::SnapCandidatePoint> const &p,
151                                                Geom::Point const &pointer,
152                                                Geom::Point const &tr);
154     Inkscape::SnappedPoint constrainedSnapTranslate(std::vector<Inkscape::SnapCandidatePoint> const &p,
155                                                       Geom::Point const &pointer,
156                                                       Inkscape::Snapper::SnapConstraint const &constraint,
157                                                       Geom::Point const &tr);
159     Inkscape::SnappedPoint freeSnapScale(std::vector<Inkscape::SnapCandidatePoint> const &p,
160                                          Geom::Point const &pointer,
161                                          Geom::Scale const &s,
162                                          Geom::Point const &o);
164     Inkscape::SnappedPoint constrainedSnapScale(std::vector<Inkscape::SnapCandidatePoint> const &p,
165                                                 Geom::Point const &pointer,
166                                                 Geom::Scale const &s,
167                                                 Geom::Point const &o);
169     Inkscape::SnappedPoint constrainedSnapStretch(std::vector<Inkscape::SnapCandidatePoint> const &p,
170                                                   Geom::Point const &pointer,
171                                                   Geom::Coord const &s,
172                                                   Geom::Point const &o,
173                                                   Geom::Dim2 d,
174                                                   bool uniform);
176     Inkscape::SnappedPoint constrainedSnapSkew(std::vector<Inkscape::SnapCandidatePoint> const &p,
177                                                Geom::Point const &pointer,
178                                                Inkscape::Snapper::SnapConstraint const &constraint,
179                                                Geom::Point const &s, // s[0] = skew factor, s[1] = scale factor
180                                                Geom::Point const &o,
181                                                Geom::Dim2 d);
183     Inkscape::SnappedPoint constrainedSnapRotate(std::vector<Inkscape::SnapCandidatePoint> const &p,
184                                                     Geom::Point const &pointer,
185                                                     Geom::Coord const &angle,
186                                                     Geom::Point const &o);
188     Inkscape::GuideSnapper guide;      ///< guide snapper
189     Inkscape::ObjectSnapper object;    ///< snapper to other objects
190     Inkscape::SnapPreferences snapprefs;
192     SnapperList getSnappers() const;
193     SnapperList getGridSnappers() const;
195     SPDesktop const *getDesktop() const {return _desktop;}
196     SPNamedView const *getNamedView() const {return _named_view;}
197     SPDocument *getDocument() const;
198     SPGuide const *getGuideToIgnore() const {return _guide_to_ignore;}
200     bool getSnapIndicator() const {return _snapindicator;}
202     Inkscape::SnappedPoint findBestSnap(Inkscape::SnapCandidatePoint const &p, SnappedConstraints const &sc, bool constrained, bool noCurves = false, bool allowOffScreen = false) const;
203     void keepClosestPointOnly(std::vector<Inkscape::SnapCandidatePoint> &points, const Geom::Point &reference) const;
205 protected:
206     SPNamedView const *_named_view;
208 private:
209     std::vector<SPItem const *> _items_to_ignore; ///< Items that should not be snapped to, for example the items that are currently being dragged. Set using the setup() method
210     GSList *_rotation_center_source_items; // to avoid snapping a rotation center to itself
211     SPGuide *_guide_to_ignore; ///< A guide that should not be snapped to, e.g. the guide that is currently being dragged
212     SPDesktop const *_desktop;
213     bool _snapindicator; ///< When true, an indicator will be drawn at the position that was being snapped to
214     std::vector<Inkscape::SnapCandidatePoint> *_unselected_nodes; ///< Nodes of the path that is currently being edited and which have not been selected and which will therefore be stationary. Only these nodes will be considered for snapping to. Of each unselected node both the position (Geom::Point) and the type (Inkscape::SnapTargetType) will be stored
216     Inkscape::SnappedPoint _snapTransformed(std::vector<Inkscape::SnapCandidatePoint> const &points,
217                                             Geom::Point const &pointer,
218                                             bool constrained,
219                                             Inkscape::Snapper::SnapConstraint const &constraint,
220                                             Transformation transformation_type,
221                                             Geom::Point const &transformation,
222                                             Geom::Point const &origin,
223                                             Geom::Dim2 dim,
224                                             bool uniform);
226     Geom::Point _transformPoint(Inkscape::SnapCandidatePoint const &p,
227                                             Transformation const transformation_type,
228                                             Geom::Point const &transformation,
229                                             Geom::Point const &origin,
230                                             Geom::Dim2 const dim,
231                                             bool const uniform) const;
233     void _displaySnapsource(Inkscape::SnapCandidatePoint const &p) const;
234 };
236 #endif /* !SEEN_SNAP_H */
238 /*
239   Local Variables:
240   mode:c++
241   c-file-style:"stroustrup"
242   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
243   indent-tabs-mode:nil
244   fill-column:99
245   End:
246 */
247 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :