24a60eaf0ce152c6b85dfcbd87cc083d7171de26
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 TRANSLATION,
71 SCALE,
72 STRETCH,
73 SKEW
74 };
76 SnapManager(SPNamedView const *v);
78 typedef std::list<const Inkscape::Snapper*> SnapperList;
80 bool someSnapperMightSnap() const;
81 bool gridSnapperMightSnap() const;
83 void setup(SPDesktop const *desktop,
84 bool snapindicator = true,
85 SPItem const *item_to_ignore = NULL,
86 std::vector<Inkscape::SnapCandidatePoint> *unselected_nodes = NULL,
87 SPGuide *guide_to_ignore = NULL);
89 void setup(SPDesktop const *desktop,
90 bool snapindicator,
91 std::vector<SPItem const *> &items_to_ignore,
92 std::vector<Inkscape::SnapCandidatePoint> *unselected_nodes = NULL,
93 SPGuide *guide_to_ignore = NULL);
94 void setupIgnoreSelection(SPDesktop const *desktop,
95 bool snapindicator = true,
96 std::vector<Inkscape::SnapCandidatePoint> *unselected_nodes = NULL,
97 SPGuide *guide_to_ignore = NULL);
99 // freeSnapReturnByRef() is preferred over freeSnap(), because it only returns a
100 // point if snapping has occurred (by overwriting p); otherwise p is untouched
101 void freeSnapReturnByRef(Geom::Point &p,
102 Inkscape::SnapSourceType const source_type,
103 Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const;
105 Inkscape::SnappedPoint freeSnap(Inkscape::SnapCandidatePoint const &p,
106 Geom::OptRect const &bbox_to_snap = Geom::OptRect() ) const;
108 Geom::Point multipleOfGridPitch(Geom::Point const &t) const;
110 // constrainedSnapReturnByRef() is preferred over constrainedSnap(), because it only returns a
111 // point, by overwriting p, if snapping has occurred; otherwise p is untouched
112 void constrainedSnapReturnByRef(Geom::Point &p,
113 Inkscape::SnapSourceType const source_type,
114 Inkscape::Snapper::ConstraintLine const &constraint,
115 Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const;
117 Inkscape::SnappedPoint constrainedSnap(Inkscape::SnapCandidatePoint const &p,
118 Inkscape::Snapper::ConstraintLine const &constraint,
119 Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const;
121 void guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SPGuideDragType drag_type) const;
122 void guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const;
124 Inkscape::SnappedPoint freeSnapTranslation(std::vector<Inkscape::SnapCandidatePoint> const &p,
125 Geom::Point const &pointer,
126 Geom::Point const &tr) const;
128 Inkscape::SnappedPoint constrainedSnapTranslation(std::vector<Inkscape::SnapCandidatePoint> const &p,
129 Geom::Point const &pointer,
130 Inkscape::Snapper::ConstraintLine const &constraint,
131 Geom::Point const &tr) const;
133 Inkscape::SnappedPoint freeSnapScale(std::vector<Inkscape::SnapCandidatePoint> const &p,
134 Geom::Point const &pointer,
135 Geom::Scale const &s,
136 Geom::Point const &o) const;
138 Inkscape::SnappedPoint constrainedSnapScale(std::vector<Inkscape::SnapCandidatePoint> const &p,
139 Geom::Point const &pointer,
140 Geom::Scale const &s,
141 Geom::Point const &o) const;
143 Inkscape::SnappedPoint constrainedSnapStretch(std::vector<Inkscape::SnapCandidatePoint> const &p,
144 Geom::Point const &pointer,
145 Geom::Coord const &s,
146 Geom::Point const &o,
147 Geom::Dim2 d,
148 bool uniform) const;
150 Inkscape::SnappedPoint constrainedSnapSkew(std::vector<Inkscape::SnapCandidatePoint> const &p,
151 Geom::Point const &pointer,
152 Inkscape::Snapper::ConstraintLine const &constraint,
153 Geom::Point const &s, // s[0] = skew factor, s[1] = scale factor
154 Geom::Point const &o,
155 Geom::Dim2 d) const;
157 Inkscape::GuideSnapper guide; ///< guide snapper
158 Inkscape::ObjectSnapper object; ///< snapper to other objects
159 Inkscape::SnapPreferences snapprefs;
161 SnapperList getSnappers() const;
162 SnapperList getGridSnappers() const;
164 SPDesktop const *getDesktop() const {return _desktop;}
165 SPNamedView const *getNamedView() const {return _named_view;}
166 SPDocument *getDocument() const;
167 SPGuide const *getGuideToIgnore() const {return _guide_to_ignore;}
169 bool getSnapIndicator() const {return _snapindicator;}
171 Inkscape::SnappedPoint findBestSnap(Inkscape::SnapCandidatePoint const &p, SnappedConstraints const &sc, bool constrained, bool noCurves = false) const;
173 protected:
174 SPNamedView const *_named_view;
176 private:
177 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
178 SPGuide *_guide_to_ignore; ///< A guide that should not be snapped to, e.g. the guide that is currently being dragged
179 SPDesktop const *_desktop;
180 bool _snapindicator; ///< When true, an indicator will be drawn at the position that was being snapped to
181 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
182 //TODO: Make _unselected_nodes type safe; in the line above int is used for Inkscape::SnapTargetType, but if I remember
183 //correctly then in other cases the int is being used for Inkscape::SnapSourceType, or for both. How to make
184 //this type safe?
186 Inkscape::SnappedPoint _snapTransformed(std::vector<Inkscape::SnapCandidatePoint> const &points,
187 Geom::Point const &pointer,
188 bool constrained,
189 Inkscape::Snapper::ConstraintLine const &constraint,
190 Transformation transformation_type,
191 Geom::Point const &transformation,
192 Geom::Point const &origin,
193 Geom::Dim2 dim,
194 bool uniform) const;
196 Geom::Point _transformPoint(Inkscape::SnapCandidatePoint const &p,
197 Transformation const transformation_type,
198 Geom::Point const &transformation,
199 Geom::Point const &origin,
200 Geom::Dim2 const dim,
201 bool const uniform) const;
203 void _displaySnapsource(Inkscape::SnapCandidatePoint const &p) const;
204 };
206 #endif /* !SEEN_SNAP_H */
208 /*
209 Local Variables:
210 mode:c++
211 c-file-style:"stroustrup"
212 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
213 indent-tabs-mode:nil
214 fill-column:99
215 End:
216 */
217 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :