From 590c77b8456655aa615f68dbb6c5560a9917ca79 Mon Sep 17 00:00:00 2001 From: dvlierop2 Date: Thu, 18 Jun 2009 20:34:59 +0000 Subject: [PATCH] Documenting of the snapping API --- src/snap.cpp | 387 +++++++++++++++++++++++++++++++++++++-------------- src/snap.h | 23 ++- 2 files changed, 295 insertions(+), 115 deletions(-) diff --git a/src/snap.cpp b/src/snap.cpp index aa0e4af5c..dcd4e85f7 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -50,6 +50,15 @@ SnapManager::SnapManager(SPNamedView const *v) : } /** + * \brief Return a list of snappers + * + * Inkscape snaps to objects, grids, and guides. For each of these snap targets a + * separate class is used, which has been derived from the base Snapper class. The + * getSnappers() method returns a list of pointers to instances of this class. This + * list contains exactly one instance of the guide snapper and of the object snapper + * class, but any number of grid snappers (because each grid has its own snapper + * instance) + * * \return List of snappers that we use. */ SnapManager::SnapperList @@ -66,6 +75,13 @@ SnapManager::getSnappers() const } /** + * \brief Return a list of gridsnappers + * + * Each grid has its own instance of the snapper class. This way snapping can + * be enabled per grid individually. A list will be returned containing the + * pointers to these instances, but only for grids that are being displayed + * and for which snapping is enabled. + * * \return List of gridsnappers that we use. */ SnapManager::SnapperList @@ -73,7 +89,6 @@ SnapManager::getGridSnappers() const { SnapperList s; - //FIXME: this code should actually do this: add new grid snappers that are active for this desktop. now it just adds all gridsnappers if (_desktop && _desktop->gridsEnabled() && snapprefs.getSnapToGrids()) { for ( GSList const *l = _named_view->grids; l != NULL; l = l->next) { Inkscape::CanvasGrid *grid = (Inkscape::CanvasGrid*) l->data; @@ -85,7 +100,14 @@ SnapManager::getGridSnappers() const } /** - * \return true if one of the snappers will try to snap something. + * \brief Return true if any snapping might occur, whether its to grids, guides or objects + * + * Each snapper instance handles its own snapping target, e.g. grids, guides or + * objects. This method iterates through all these snapper instances and returns + * true if any of the snappers might possible snap, considering only the relevant + * snapping preferences. + * + * \return true if one of the snappers will try to snap to something. */ bool SnapManager::someSnapperMightSnap() const @@ -104,7 +126,7 @@ bool SnapManager::someSnapperMightSnap() const } /** - * \return true if one of the snappers will try to snap something. + * \return true if one of the grids might be snapped to. */ bool SnapManager::gridSnapperMightSnap() const @@ -123,14 +145,27 @@ bool SnapManager::gridSnapperMightSnap() const } /** - * Try to snap a point to any of the specified snappers. + * \brief Try to snap a point to grids, guides or objects. + * + * Try to snap a point to grids, guides or objects, in two degrees-of-freedom, + * i.e. snap in any direction on the two dimensional canvas to the nearest + * snap target. freeSnapReturnByRef() is equal in snapping behavior to + * freeSnap(), but the former returns the snapped point trough the referenced + * parameter p. This parameter p initially contains the position of the snap + * source and will we overwritten by the target position if snapping has occurred. + * This makes snapping transparent to the calling code. If this is not desired + * because either the calling code must know whether snapping has occurred, or + * because the original position should not be touched, then freeSnap() should be + * called instead. * - * \param point_type Type of point. - * \param p Point. - * \param first_point If true then this point is the first one from a whole bunch of points - * \param points_to_snap The whole bunch of points, all from the same selection and having the same transformation - * \param snappers List of snappers to try to snap to - * \return Snapped point. + * PS: SnapManager::setup() must have been called before calling this method, + * but only once for a set of points + * + * \param point_type Category of points to which the source point belongs: node, guide or bounding box + * \param p Current position of the snap source; will be overwritten by the position of the snap target if snapping has occurred + * \param source_type Detailed description of the source type, will be used by the snap indicator + * \param first_point If true then this point is the first one from a set of points, all from the same selection and having the same transformation + * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, @@ -139,22 +174,32 @@ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point bool first_point, Geom::OptRect const &bbox_to_snap) const { + //TODO: PointType and source_type are somewhat redundant; can't we get rid of the point_type parameter? Inkscape::SnappedPoint const s = freeSnap(point_type, p, source_type, first_point, bbox_to_snap); s.getPoint(p); } /** - * Try to snap a point to any of the specified snappers. + * \brief Try to snap a point to grids, guides or objects. + * + * Try to snap a point to grids, guides or objects, in two degrees-of-freedom, + * i.e. snap in any direction on the two dimensional canvas to the nearest + * snap target. freeSnap() is equal in snapping behavior to + * freeSnapReturnByRef(). Please read the comments of the latter for more details * - * \param point_type Type of point. - * \param p Point. - * \param first_point If true then this point is the first one from a whole bunch of points - * \param points_to_snap The whole bunch of points, all from the same selection and having the same transformation - * \param snappers List of snappers to try to snap to - * \return Snapped point. + * PS: SnapManager::setup() must have been called before calling this method, + * but only once for a set of points + * + * \param point_type Category of points to which the source point belongs: node, guide or bounding box + * \param p Current position of the snap source + * \param source_type Detailed description of the source type, will be used by the snap indicator + * \param first_point If true then this point is the first one from a set of points, all from the same selection and having the same transformation + * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation + * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics */ + Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointType point_type, Geom::Point const &p, Inkscape::SnapSourceType const &source_type, @@ -196,19 +241,30 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointTyp return findBestSnap(p, source_type, sc, false); } -// When pasting, we would like to snap to the grid. Problem is that we don't know which nodes were -// aligned to the grid at the time of copying, so we don't know which nodes to snap. If we'd snap an -// unaligned node to the grid, previously aligned nodes would become unaligned. That's undesirable. -// Instead we will make sure that the offset between the source and the copy is a multiple of the grid -// pitch. If the source was aligned, then the copy will therefore also be aligned -// PS: Whether we really find a multiple also depends on the snapping range! +/** + * \brief Snap to the closest multiple of a grid pitch + * + * When pasting, we would like to snap to the grid. Problem is that we don't know which + * nodes were aligned to the grid at the time of copying, so we don't know which nodes + * to snap. If we'd snap an unaligned node to the grid, previously aligned nodes would + * become unaligned. That's undesirable. Instead we will make sure that the offset + * between the source and its pasted copy is a multiple of the grid pitch. If the source + * was aligned, then the copy will therefore also be aligned. + * + * PS: Whether we really find a multiple also depends on the snapping range! Most users + * will have "always snap" enabled though, in which case a multiple will always be found. + * PS2: When multiple grids are present then the result will become ambiguous. There is no + * way to control to which grid this method will snap. + * + * \param t Vector that represents the offset of the pasted copy with respect to the original + * \return Offset vector after snapping to the closest multiple of a grid pitch + */ + Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const { if (!snapprefs.getSnapEnabledGlobally()) // No need to check for snapprefs.getSnapPostponedGlobally() here return t; - //FIXME: this code should actually do this: add new grid snappers that are active for this desktop. now it just adds all gridsnappers - if (_desktop && _desktop->gridsEnabled()) { bool success = false; Geom::Point nearest_multiple; @@ -252,15 +308,31 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const } /** - * Try to snap a point to any interested snappers. A snap will only occur along - * a line described by a Inkscape::Snapper::ConstraintLine. + * \brief Try to snap a point along a constraint line to grids, guides or objects. + * + * Try to snap a point to grids, guides or objects, in only one degree-of-freedom, + * i.e. snap in a specific direction on the two dimensional canvas to the nearest + * snap target. + * + * constrainedSnapReturnByRef() is equal in snapping behavior to + * constrainedSnap(), but the former returns the snapped point trough the referenced + * parameter p. This parameter p initially contains the position of the snap + * source and will we overwritten by the target position if snapping has occurred. + * This makes snapping transparent to the calling code. If this is not desired + * because either the calling code must know whether snapping has occurred, or + * because the original position should not be touched, then constrainedSnap() should + * be called instead. * - * \param point_type Type of point. - * \param p Point. - * \param first_point If true then this point is the first one from a whole bunch of points - * \param points_to_snap The whole bunch of points, all from the same selection and having the same transformation - * \param constraint Constraint line. - * \return Snapped point. + * PS: SnapManager::setup() must have been called before calling this method, + * but only once for a set of points + * + * \param point_type Category of points to which the source point belongs: node, guide or bounding box + * \param p Current position of the snap source; will be overwritten by the position of the snap target if snapping has occurred + * \param source_type Detailed description of the source type, will be used by the snap indicator + * \param constraint The direction or line along which snapping must occur + * \param snap_projection Currently unused + * \param first_point If true then this point is the first one from a set of points, all from the same selection and having the same transformation + * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, @@ -275,17 +347,24 @@ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointTyp s.getPoint(p); } - /** - * Try to snap a point to any interested snappers. A snap will only occur along - * a line described by a Inkscape::Snapper::ConstraintLine. + * \brief Try to snap a point along a constraint line to grids, guides or objects. * - * \param point_type Type of point. - * \param p Point. - * \param first_point If true then this point is the first one from a whole bunch of points - * \param points_to_snap The whole bunch of points, all from the same selection and having the same transformation - * \param constraint Constraint line. - * \return Snapped point. + * Try to snap a point to grids, guides or objects, in only one degree-of-freedom, + * i.e. snap in a specific direction on the two dimensional canvas to the nearest + * snap target. constrainedSnap is equal in snapping behavior to + * constrainedSnapReturnByRef(). Please read the comments of the latter for more details. + * + * PS: SnapManager::setup() must have been called before calling this method, + * but only once for a set of points + * + * \param point_type Category of points to which the source point belongs: node, guide or bounding box + * \param p Current position of the snap source + * \param source_type Detailed description of the source type, will be used by the snap indicator + * \param constraint The direction or line along which snapping must occur + * \param snap_projection Currently unused + * \param first_point If true then this point is the first one from a set of points, all from the same selection and having the same transformation + * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::PointType point_type, @@ -296,7 +375,9 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P bool first_point, Geom::OptRect const &bbox_to_snap) const { - if (_desktop->event_context && _desktop->event_context->_snap_window_open == false) { + //TODO: Get rid of the snap_projection parameter (if it is really not used) + + if (_desktop->event_context && _desktop->event_context->_snap_window_open == false) { g_warning("The current tool tries to snap, but it hasn't yet opened the snap window. Please report this!"); // When the context goes into dragging-mode, then Inkscape should call this: sp_event_context_snap_window_open(event_context); } @@ -330,12 +411,21 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P return findBestSnap(p, source_type, sc, true); } -// guideFreeSnap is used when dragging or rotating the guide +/** + * \brief Try to snap a point of a guide to another guide or to a node + * + * Try to snap a point of a guide to another guide or to a node in two degrees- + * of-freedom, i.e. snap in any direction on the two dimensional canvas to the + * nearest snap target. This method is used when dragging or rotating a guide + * + * PS: SnapManager::setup() must have been called before calling this method, + * + * \param p Current position of the point on the guide that is to be snapped; will be overwritten by the position of the snap target if snapping has occurred + * \param guide_normal Vector normal to the guide line + */ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal) const { - // This method is used to snap a guide to nodes or to other guides, while dragging the guide around. Will not snap to grids! - - if (_desktop->event_context && _desktop->event_context->_snap_window_open == false) { + if (_desktop->event_context && _desktop->event_context->_snap_window_open == false) { g_warning("The current tool tries to snap, but it hasn't yet opened the snap window. Please report this!"); // When the context goes into dragging-mode, then Inkscape should call this: sp_event_context_snap_window_open(event_context); } @@ -365,11 +455,22 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal) s.getPoint(p); } -// guideConstrainedSnap is used when dragging the origin of the guide along the guide itself +/** + * \brief Try to snap a point on a guide to the intersection with another guide or a path + * + * Try to snap a point on a guide to the intersection of that guide with another + * guide or with a path. The snapped point will lie somewhere on the guide-line, + * making this is a constrained snap, i.e. in only one degree-of-freedom. + * This method is used when dragging the origin of the guide along the guide itself. + * + * PS: SnapManager::setup() must have been called before calling this method, + * + * \param p Current position of the point on the guide that is to be snapped; will be overwritten by the position of the snap target if snapping has occurred + * \param guide_normal Vector normal to the guide line + */ + void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const { - // This method is used to snap a guide to paths or to other guides, while dragging the origin of the guide around. Will not snap to grids! - if (_desktop->event_context && _desktop->event_context->_snap_window_open == false) { g_warning("The current tool tries to snap, but it hasn't yet opened the snap window. Please report this!"); // When the context goes into dragging-mode, then Inkscape should call this: sp_event_context_snap_window_open(event_context); @@ -402,20 +503,29 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) } /** - * Main internal snapping method, which is called by the other, friendlier, public - * methods. It's a bit hairy as it has lots of parameters, but it saves on a lot - * of duplicated code. + * \brief Method for snapping sets of points while they are being transformed + * + * Method for snapping sets of points while they are being transformed, when using + * for example the selector tool. This method is for internal use only, and should + * not have to be called directly. Use freeSnapTransalation(), constrainedSnapScale(), + * etc. instead. * - * \param type Type of points being snapped. - * \param points List of points to snap (i.e. untransformed). - * \param pointer Location of the mouse pointer, at the time when dragging started (i.e. "untransformed") - * \param constrained true if the snap is constrained. - * \param constraint Constraint line to use, if `constrained' is true, otherwise undefined. + * This is what is being done in this method: transform each point, find out whether + * a free snap or constrained snap is more appropriate, do the snapping, calculate + * some metrics to quantify the snap "distance", and see if it's better than the + * previous snap. Finally, the best ("nearest") snap from all these points is returned. + * + * \param type Category of points to which the source point belongs: node or bounding box. + * \param points Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. + * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). + * \param constrained true if the snap is constrained, e.g. for stretching or for purely horizontal translation. + * \param constraint The direction or line along which snapping must occur, if 'constrained' is true; otherwise undefined. * \param transformation_type Type of transformation to apply to points before trying to snap them. * \param transformation Description of the transformation; details depend on the type. * \param origin Origin of the transformation, if applicable. - * \param dim Dimension of the transformation, if applicable. + * \param dim Dimension to which the transformation applies, if applicable. * \param uniform true if the transformation should be uniform; only applicable for stretching and scaling. + * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ Inkscape::SnappedPoint SnapManager::_snapTransformed( @@ -649,13 +759,13 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( /** - * Try to snap a list of points to any interested snappers after they have undergone - * a translation. + * \brief Apply a translation to a set of points and try to snap freely in 2 degrees-of-freedom * - * \param point_type Type of points. - * \param p Points. - * \param tr Proposed translation. - * \return Snapped translation, if a snap occurred, and a flag indicating whether a snap occurred. + * \param point_type Category of points to which the source point belongs: node or bounding box. + * \param p Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. + * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). + * \param tr Proposed translation; the final translation can only be calculated after snapping has occurred + * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ Inkscape::SnappedPoint SnapManager::freeSnapTranslation(Inkscape::SnapPreferences::PointType point_type, @@ -670,17 +780,15 @@ Inkscape::SnappedPoint SnapManager::freeSnapTranslation(Inkscape::SnapPreference return _snapTransformed(point_type, p, pointer, false, Geom::Point(0,0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); } - /** - * Try to snap a list of points to any interested snappers after they have undergone a - * translation. A snap will only occur along a line described by a - * Inkscape::Snapper::ConstraintLine. + * \brief Apply a translation to a set of points and try to snap along a constraint * - * \param point_type Type of points. - * \param p Points. - * \param constraint Constraint line. - * \param tr Proposed translation. - * \return Snapped translation, if a snap occurred, and a flag indicating whether a snap occurred. + * \param point_type Category of points to which the source point belongs: node or bounding box. + * \param p Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. + * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). + * \param constraint The direction or line along which snapping must occur. + * \param tr Proposed translation; the final translation can only be calculated after snapping has occurred. + * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(Inkscape::SnapPreferences::PointType point_type, @@ -698,14 +806,14 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(Inkscape::SnapPre /** - * Try to snap a list of points to any interested snappers after they have undergone - * a scale. + * \brief Apply a scaling to a set of points and try to snap freely in 2 degrees-of-freedom * - * \param point_type Type of points. - * \param p Points. - * \param s Proposed scale. - * \param o Origin of proposed scale. - * \return Snapped scale, if a snap occurred, and a flag indicating whether a snap occurred. + * \param point_type Category of points to which the source point belongs: node or bounding box. + * \param p Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. + * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). + * \param s Proposed scaling; the final scaling can only be calculated after snapping has occurred + * \param o Origin of the scaling + * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ Inkscape::SnappedPoint SnapManager::freeSnapScale(Inkscape::SnapPreferences::PointType point_type, @@ -723,15 +831,14 @@ Inkscape::SnappedPoint SnapManager::freeSnapScale(Inkscape::SnapPreferences::Poi /** - * Try to snap a list of points to any interested snappers after they have undergone - * a scale. A snap will only occur along a line described by a - * Inkscape::Snapper::ConstraintLine. + * \brief Apply a scaling to a set of points and snap such that the aspect ratio of the selection is preserved * - * \param point_type Type of points. - * \param p Points. - * \param s Proposed scale. - * \param o Origin of proposed scale. - * \return Snapped scale, if a snap occurred, and a flag indicating whether a snap occurred. + * \param point_type Category of points to which the source point belongs: node or bounding box. + * \param p Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. + * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). + * \param s Proposed scaling; the final scaling can only be calculated after snapping has occurred + * \param o Origin of the scaling + * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::SnapPreferences::PointType point_type, @@ -748,18 +855,17 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::SnapPreferenc return _snapTransformed(point_type, p, pointer, true, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); } - /** - * Try to snap a list of points to any interested snappers after they have undergone - * a stretch. + * \brief Apply a stretch to a set of points and snap such that the direction of the stretch is preserved * - * \param point_type Type of points. - * \param p Points. - * \param s Proposed stretch. - * \param o Origin of proposed stretch. + * \param point_type Category of points to which the source point belongs: node or bounding box. + * \param p Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. + * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). + * \param s Proposed stretch; the final stretch can only be calculated after snapping has occurred + * \param o Origin of the stretching * \param d Dimension in which to apply proposed stretch. - * \param u true if the stretch should be uniform (ie to be applied equally in both dimensions) - * \return Snapped stretch, if a snap occurred, and a flag indicating whether a snap occurred. + * \param u true if the stretch should be uniform (i.e. to be applied equally in both dimensions) + * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPreferences::PointType point_type, @@ -777,17 +883,17 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPrefere return _snapTransformed(point_type, p, pointer, true, Geom::Point(0,0), STRETCH, Geom::Point(s, s), o, d, u); } - /** - * Try to snap a list of points to any interested snappers after they have undergone - * a skew. + * \brief Apply a skew to a set of points and snap such that the direction of the skew is preserved * - * \param point_type Type of points. - * \param p Points. - * \param s Proposed skew. - * \param o Origin of proposed skew. + * \param point_type Category of points to which the source point belongs: node or bounding box. + * \param p Collection of points to snap (snap sources), at their untransformed position, all points undergoing the same transformation. Paired with an identifier of the type of the snap source. + * \param pointer Location of the mouse pointer at the time dragging started (i.e. when the selection was still untransformed). + * \param constraint The direction or line along which snapping must occur. + * \param s Proposed skew; the final skew can only be calculated after snapping has occurred + * \param o Origin of the proposed skew * \param d Dimension in which to apply proposed skew. - * \return Snapped skew, if a snap occurred, and a flag indicating whether a snap occurred. + * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics. */ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreferences::PointType point_type, @@ -800,7 +906,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreference { // "s" contains skew factor in s[0], and scale factor in s[1] - // Snapping the nodes of the boundingbox of a selection that is being transformed, will only work if + // Snapping the nodes of the bounding box of a selection that is being transformed, will only work if // the transformation of the bounding box is equal to the transformation of the individual nodes. This is // NOT the case for example when rotating or skewing. The bounding box itself cannot possibly rotate or skew, // so it's corners have a different transformation. The snappers cannot handle this, therefore snapping @@ -814,7 +920,21 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreference return _snapTransformed(point_type, p, pointer, true, constraint, SKEW, s, o, d, false); } -Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, Inkscape::SnapSourceType const source_type, SnappedConstraints &sc, bool constrained) const +/** + * \brief Given a set of possible snap targets, find the best target (which is not necessarily + * also the nearest target), and show the snap indicator if requested + * + * \param p Current position of the snap source + * \param source_type Detailed description of the source type, will be used by the snap indicator + * \param sc A structure holding all snap targets that have been found so far + * \param constrained True if the snap is constrained, e.g. for stretching or for purely horizontal translation. + * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics + */ + +Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, + Inkscape::SnapSourceType const source_type, + SnappedConstraints &sc, + bool constrained) const { /* @@ -925,6 +1045,22 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, Inkscape: return bestSnappedPoint; } +/** + * \brief Prepare the snap manager for the actual snapping, which includes building a list of snap targets + * to ignore and toggling the snap indicator + * + * There are two overloaded setup() methods, of which this one only allows for a single item to be ignored + * whereas the other one will take a list of items to ignore + * + * \param desktop Reference to the desktop to which this snap manager is attached + * \param snapindicator If true then a snap indicator will be displayed automatically (when enabled in the preferences) + * \param item_to_ignore This item will not be snapped to, e.g. the item that is currently being dragged. This avoids "self-snapping" + * \param unselected_nodes Stationary nodes of the path that is currently being edited in the node tool and + * that can be snapped too. Nodes not in this list will not be snapped to, to avoid "self-snapping". Of each + * unselected node both the position (Geom::Point) and the type (Inkscape::SnapTargetType) will be stored + * \param guide_to_ignore Guide that is currently being dragged and should not be snapped to + */ + void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, SPItem const *item_to_ignore, @@ -940,6 +1076,22 @@ void SnapManager::setup(SPDesktop const *desktop, _guide_to_ignore = guide_to_ignore; } +/** + * \brief Prepare the snap manager for the actual snapping, which includes building a list of snap targets + * to ignore and toggling the snap indicator + * + * There are two overloaded setup() methods, of which the other one only allows for a single item to be ignored + * whereas this one will take a list of items to ignore + * + * \param desktop Reference to the desktop to which this snap manager is attached + * \param snapindicator If true then a snap indicator will be displayed automatically (when enabled in the preferences) + * \param items_to_ignore These items will not be snapped to, e.g. the items that are currently being dragged. This avoids "self-snapping" + * \param unselected_nodes Stationary nodes of the path that is currently being edited in the node tool and + * that can be snapped too. Nodes not in this list will not be snapped to, to avoid "self-snapping". Of each + * unselected node both the position (Geom::Point) and the type (Inkscape::SnapTargetType) will be stored + * \param guide_to_ignore Guide that is currently being dragged and should not be snapped to + */ + void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, std::vector &items_to_ignore, @@ -960,6 +1112,18 @@ SPDocument *SnapManager::getDocument() const return _named_view->document; } +/** + * \brief Takes an untransformed point, applies the given transformation, and returns the transformed point. Eliminates lots of duplicated code + * + * \param p The untransformed position of the point, paired with an identifier of the type of the snap source. + * \param transformation_type Type of transformation to apply. + * \param transformation Mathematical description of the transformation; details depend on the type. + * \param origin Origin of the transformation, if applicable. + * \param dim Dimension to which the transformation applies, if applicable. + * \param uniform true if the transformation should be uniform; only applicable for stretching and scaling. + * \return The position of the point after transformation + */ + Geom::Point SnapManager::_transformPoint(std::pair const &p, Transformation const transformation_type, Geom::Point const &transformation, @@ -1002,6 +1166,13 @@ Geom::Point SnapManager::_transformPoint(std::pair const &p, return transformed; } +/** + * \brief Mark the location of the snap source (not the snap target!) on the canvas by drawing a symbol + * + * \param point_type Category of points to which the source point belongs: node, guide or bounding box + * \param p The transformed position of the source point, paired with an identifier of the type of the snap source. + */ + void SnapManager::_displaySnapsource(Inkscape::SnapPreferences::PointType point_type, std::pair const &p) const { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); diff --git a/src/snap.h b/src/snap.h index ba920510f..10a85de75 100644 --- a/src/snap.h +++ b/src/snap.h @@ -5,6 +5,13 @@ * \file snap.h * \brief SnapManager class. * + * The SnapManager class handles most (if not all) of the interfacing of the snapping mechanisms with the + * other parts of the code base. It stores the references to the various types of snappers for grid, guides + * and objects, and it stores most of the snapping preferences. Besides that it provides methods to setup + * the snapping environment (e.g. keeps a list of the items to ignore when looking for snap target candidates, + * and toggling of the snap indicator), and it provides many different methods for the snapping itself (free + * snapping vs. constrained snapping, returning the result by reference or through a return statement, etc.) + * * Authors: * Lauris Kaplinski * Frank Felfe @@ -13,7 +20,7 @@ * * Copyright (C) 2006-2007 Johan Engelen * Copyright (C) 2000-2002 Lauris Kaplinski - * Copyright (C) 2000-2008 Authors + * Copyright (C) 2000-2009 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -23,7 +30,6 @@ #include "guide-snapper.h" #include "object-snapper.h" #include "snap-preferences.h" -//#include "sp-guide.h" class SPNamedView; @@ -159,12 +165,15 @@ protected: SPNamedView const *_named_view; private: - std::vector *_items_to_ignore; - SPItem const *_item_to_ignore; - SPGuide *_guide_to_ignore; + std::vector *_items_to_ignore; ///< Items that should not be snapped to, for example the items that are currently being dragged. Set using the setup() method + SPItem const *_item_to_ignore; ///< Single item that should not be snapped to. If not NULL then this takes precedence over _items_to_ignore. Set using the setup() method + SPGuide *_guide_to_ignore; ///< A guide that should not be snapped to, e.g. the guide that is currently being dragged SPDesktop const *_desktop; - bool _snapindicator; - std::vector > *_unselected_nodes; + bool _snapindicator; ///< When true, an indicator will be drawn at the position that was being snapped to + std::vector > *_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 + //TODO: Make _unselected_nodes type safe; in the line above int is used for Inkscape::SnapTargetType, but if I remember + //correctly then in other cases the int is being used for Inkscape::SnapSourceType, or for both. How to make + //this type safe? Inkscape::SnappedPoint _snapTransformed(Inkscape::SnapPreferences::PointType type, std::vector > const &points, -- 2.30.2