Code

When dragging the origin of a guide along that guide, we should use constrained snapp...
authordvlierop2 <dvlierop2@users.sourceforge.net>
Tue, 2 Jun 2009 04:36:17 +0000 (04:36 +0000)
committerdvlierop2 <dvlierop2@users.sourceforge.net>
Tue, 2 Jun 2009 04:36:17 +0000 (04:36 +0000)
src/desktop-events.cpp
src/display/snap-indicator.cpp
src/object-snapper.cpp
src/object-snapper.h
src/snap.cpp
src/snap.h
src/snapped-point.h

index 3d8e88fba7ea1c3422bfac0d51c7808732fb4d6a..17b0778909e2ed34679a6f819a014a61619696d6 100644 (file)
@@ -161,7 +161,7 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
                 m.setup(desktop);
                 // We only have a temporary guide which is not stored in our document yet. Because the guide snapper only looks
                 // in the document for guides to snap to, we don't have to worry about a guide snapping to itself here
-                m.guideSnap(event_dt, normal);
+                m.guideFreeSnap(event_dt, normal);
 
                 sp_guideline_set_position(SP_GUIDELINE(guide), from_2geom(event_dt));
                 desktop->set_coordinate_status(to_2geom(event_dt));
@@ -178,7 +178,7 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
                 m.setup(desktop);
                 // We only have a temporary guide which is not stored in our document yet. Because the guide snapper only looks
                                // in the document for guides to snap to, we don't have to worry about a guide snapping to itself here
-                m.guideSnap(event_dt, normal);
+                m.guideFreeSnap(event_dt, normal);
 
                 dragging = false;
 
@@ -226,17 +226,15 @@ int sp_dt_vruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw)
 }
 
 /* Guides */
-
-static Geom::Point drag_origin;
-
 enum SPGuideDragType {
     SP_DRAG_TRANSLATE,
-    SP_DRAG_TRANSLATE_CONSTRAINED,
+    SP_DRAG_TRANSLATE_CONSTRAINED, // Is not being used currently!
     SP_DRAG_ROTATE,
     SP_DRAG_MOVE_ORIGIN,
     SP_DRAG_NONE
 };
 
+static Geom::Point drag_origin;
 static SPGuideDragType drag_type = SP_DRAG_NONE;
 
 gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
@@ -304,7 +302,17 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                 // which are dragged off the ruler, are being snapped in sp_dt_ruler_event
                 SnapManager &m = desktop->namedview->snap_manager;
                 m.setup(desktop, true, NULL, NULL, guide);
-                m.guideSnap(motion_dt, to_2geom(guide->normal_to_line));
+                if (drag_type == SP_DRAG_MOVE_ORIGIN) {
+                       // If we snap in guideConstrainedSnap() below, then motion_dt will be forced to be on the guide
+                                       // If we don't snap however, then it the origin should still be constrained to the guide
+                                       // So let's do that explicitly first:
+                       Geom::Line line(guide->point_on_line, guide->angle());
+                                       Geom::Coord t = line.nearestPoint(motion_dt);
+                                       motion_dt = line.pointAt(t);
+                       m.guideConstrainedSnap(motion_dt, *guide);
+                } else {
+                                       m.guideFreeSnap(motion_dt, guide->normal_to_line);
+                }
 
                 switch (drag_type) {
                     case SP_DRAG_TRANSLATE:
@@ -312,7 +320,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                         sp_guide_moveto(*guide, guide->point_on_line + motion_dt - drag_origin, false);
                         break;
                     }
-                    case SP_DRAG_TRANSLATE_CONSTRAINED:
+                    case SP_DRAG_TRANSLATE_CONSTRAINED: // Is not being used currently!
                     {
                         Geom::Point pt_constr = Geom::constrain_angle(guide->point_on_line, motion_dt);
                         sp_guide_moveto(*guide, pt_constr, false);
@@ -326,10 +334,8 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     }
                     case SP_DRAG_MOVE_ORIGIN:
                     {
-                        Geom::Line line(guide->point_on_line, guide->angle());
-                        Geom::Coord t = line.nearestPoint(motion_dt);
-                        sp_guide_moveto(*guide, line.pointAt(t), false);
-                        break;
+                        sp_guide_moveto(*guide, motion_dt, false);
+                       break;
                     }
                     case SP_DRAG_NONE:
                         g_assert_not_reached();
@@ -351,7 +357,17 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
 
                     SnapManager &m = desktop->namedview->snap_manager;
                     m.setup(desktop, true, NULL, NULL, guide);
-                                       m.guideSnap(event_dt, guide->normal_to_line);
+                    if (drag_type == SP_DRAG_MOVE_ORIGIN) {
+                       // If we snap in guideConstrainedSnap() below, then motion_dt will be forced to be on the guide
+                       // If we don't snap however, then it the origin should still be constrained to the guide
+                       // So let's do that explicitly first:
+                       Geom::Line line(guide->point_on_line, guide->angle());
+                                               Geom::Coord t = line.nearestPoint(event_dt);
+                                               event_dt = line.pointAt(t);
+                       m.guideConstrainedSnap(event_dt, *guide);
+                                       } else {
+                                               m.guideFreeSnap(event_dt, guide->normal_to_line);
+                                       }
 
                     if (sp_canvas_world_pt_inside_window(item->canvas, event_w)) {
                         switch (drag_type) {
@@ -360,7 +376,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                                 sp_guide_moveto(*guide, guide->point_on_line + event_dt - drag_origin, true);
                                 break;
                             }
-                            case SP_DRAG_TRANSLATE_CONSTRAINED:
+                            case SP_DRAG_TRANSLATE_CONSTRAINED: // Is not being used currently!
                             {
                                 Geom::Point pt_constr = Geom::constrain_angle(guide->point_on_line, event_dt);
                                 sp_guide_moveto(*guide, pt_constr, true);
@@ -374,10 +390,8 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                             }
                             case SP_DRAG_MOVE_ORIGIN:
                             {
-                                Geom::Line line(guide->point_on_line, guide->angle());
-                                Geom::Coord t = line.nearestPoint(event_dt);
-                                sp_guide_moveto(*guide, line.pointAt(t), true);
-                                break;
+                               sp_guide_moveto(*guide, event_dt, true);
+                               break;
                             }
                             case SP_DRAG_NONE:
                                 g_assert_not_reached();
index e73eef79675c607ec5caf8b1b614115078aacdec..081496fd0943bb2f03d7eba737ebc24fbabb79aa 100644 (file)
@@ -56,7 +56,7 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const p)
     bool value = prefs->getBool("/options/snapindicator/value", true);
 
     if (value) {
-        // TRANSLATORS: undefined target for snapping 
+        // TRANSLATORS: undefined target for snapping
         gchar *target_name = _("UNDEFINED");
         switch (p.getTarget()) {
                        case SNAPTARGET_UNDEFINED:
@@ -180,6 +180,9 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const p)
                        case SNAPSOURCE_GUIDE:
                                source_name = _("Guide");
                                break;
+                       case SNAPSOURCE_GUIDE_ORIGIN:
+                               source_name = _("Guide origin");
+                               break;
                        case SNAPSOURCE_CONVEX_HULL_CORNER:
                                source_name = _("Convex hull corner");
                                break;
index 70377cb661fe77f22dafc401387a90b72e359216..5dd9350dcf11b3d8cc110ea13c6cae0f5a12744d 100644 (file)
@@ -330,6 +330,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapPreferences::PointType
         SPItem::BBoxType bbox_type = SPItem::GEOMETRIC_BBOX;
 
         bool p_is_a_node = t & Inkscape::SnapPreferences::SNAPPOINT_NODE;
+        bool p_is_a_guide = t & Inkscape::SnapPreferences::SNAPPOINT_GUIDE;
 
         if (_snapmanager->snapprefs.getSnapToBBoxPath()) {
             Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -365,7 +366,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapPreferences::PointType
 
             //Add the item's path to snap to
             if (_snapmanager->snapprefs.getSnapToItemPath()) {
-                if (!(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_node)) {
+                if (p_is_a_guide || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_node)) {
                     // Snapping to the path of characters is very cool, but for a large
                     // chunk of text this will take ages! So limit snapping to text paths
                     // containing max. 240 characters. Snapping the bbox will not be affected
@@ -399,7 +400,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapPreferences::PointType
 
             //Add the item's bounding box to snap to
             if (_snapmanager->snapprefs.getSnapToBBoxPath()) {
-                if (!(_snapmanager->snapprefs.getStrictSnapping() && p_is_a_node)) {
+                if (p_is_a_guide || !(_snapmanager->snapprefs.getStrictSnapping() && p_is_a_node)) {
                     // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox
                     // of the item AND the bbox of the clipping path at the same time
                     if (!(*i).clip_or_mask) {
@@ -663,7 +664,7 @@ void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc,
 
 
 // This method is used to snap a guide to nodes, while dragging the guide around
-void Inkscape::ObjectSnapper::guideSnap(SnappedConstraints &sc,
+void Inkscape::ObjectSnapper::guideFreeSnap(SnappedConstraints &sc,
                                         Geom::Point const &p,
                                         Geom::Point const &guide_normal) const
 {
@@ -680,15 +681,29 @@ void Inkscape::ObjectSnapper::guideSnap(SnappedConstraints &sc,
         snap_dim = ANGLED_GUIDE_TRANSL_SNAP;
     }
 
-    // We don't support ANGLED_GUIDE_ROT_SNAP yet.
+    _findCandidates(sp_document_root(_snapmanager->getDocument()), &it, true, Geom::Rect(p, p), snap_dim, false, Geom::identity());
+    _snapTranslatingGuideToNodes(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, guide_normal);
+    // _snapRotatingGuideToNodes has not been implemented yet.
+}
 
-    // It would be cool to allow the user to rotate a guide by dragging it, instead of
-    // only translating it. (For example when CTRL is pressed). We will need an UI part
-    // for that first; and some important usability choices need to be made:
-    // E.g. which point should be used for pivoting? A previously snapped point,
-    // or a transformation center (which can be moved after clicking for the
-    // second time on an object; but should this point then be constrained to the
-    // line, or can it be located anywhere?)
+// This method is used to snap the origin of a guide to nodes/paths, while dragging the origin along the guide
+void Inkscape::ObjectSnapper::guideConstrainedSnap(SnappedConstraints &sc,
+                                        Geom::Point const &p,
+                                        Geom::Point const &guide_normal,
+                                        ConstraintLine const &c) const
+{
+    /* Get a list of all the SPItems that we will try to snap to */
+    std::vector<SPItem*> cand;
+    std::vector<SPItem const *> const it; //just an empty list
+
+    DimensionToSnap snap_dim;
+    if (guide_normal == to_2geom(component_vectors[Geom::Y])) {
+        snap_dim = GUIDE_TRANSL_SNAP_Y;
+    } else if (guide_normal == to_2geom(component_vectors[Geom::X])) {
+        snap_dim = GUIDE_TRANSL_SNAP_X;
+    } else {
+        snap_dim = ANGLED_GUIDE_TRANSL_SNAP;
+    }
 
     _findCandidates(sp_document_root(_snapmanager->getDocument()), &it, true, Geom::Rect(p, p), snap_dim, false, Geom::identity());
     _snapTranslatingGuideToNodes(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, guide_normal);
index f220106e389a73fc97a409322db5aaf6c834e908..baa60a096fdc392049dfb48664aad4bb3563c8cb 100644 (file)
@@ -53,13 +53,17 @@ public:
                GUIDE_TRANSL_SNAP_X, // For snapping a vertical guide (normal in the X-direction) to objects,
                GUIDE_TRANSL_SNAP_Y, // For snapping a horizontal guide (normal in the Y-direction) to objects
                ANGLED_GUIDE_TRANSL_SNAP, // For snapping an angled guide, while translating it accross the desktop
-               ANGLED_GUIDE_ROT_SNAP, // For snapping an angled guide, while rotating it around some pivot point
                TRANSL_SNAP_XY}; // All other cases; for snapping to objects, other than guides
 
-       void guideSnap(SnappedConstraints &sc,
+       void guideFreeSnap(SnappedConstraints &sc,
                                   Geom::Point const &p,
                                   Geom::Point const &guide_normal) const;
 
+       void guideConstrainedSnap(SnappedConstraints &sc,
+                                          Geom::Point const &p,
+                                          Geom::Point const &guide_normal,
+                                          ConstraintLine const &c) const;
+
        bool ThisSnapperMightSnap() const;
        bool GuidesMightSnap() const;
 
index 9ca9b78382ec5b68d8fc9bcdc325c3a2c16d11e1..aa0e4af5c511fa90c9fb2d735ceb651ff5ff6440 100644 (file)
@@ -330,7 +330,8 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P
     return findBestSnap(p, source_type, sc, true);
 }
 
-void SnapManager::guideSnap(Geom::Point &p, Geom::Point const &guide_normal) const
+// guideFreeSnap is used when dragging or rotating the guide
+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!
 
@@ -350,7 +351,7 @@ void SnapManager::guideSnap(Geom::Point &p, Geom::Point const &guide_normal) con
     // Snap to nodes
     SnappedConstraints sc;
     if (object.GuidesMightSnap()) {
-        object.guideSnap(sc, p, guide_normal);
+        object.guideFreeSnap(sc, p, guide_normal);
     }
 
     // Snap to guides
@@ -364,6 +365,41 @@ void SnapManager::guideSnap(Geom::Point &p, Geom::Point const &guide_normal) con
     s.getPoint(p);
 }
 
+// guideConstrainedSnap is used when dragging the origin of the guide along the guide itself
+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);
+       }
+
+    if (!snapprefs.getSnapEnabledGlobally() || snapprefs.getSnapPostponedGlobally()) {
+        return;
+    }
+
+    if (!(object.ThisSnapperMightSnap() || snapprefs.getSnapToGuides())) {
+        return;
+    }
+
+    // Snap to nodes or paths
+    SnappedConstraints sc;
+    Inkscape::Snapper::ConstraintLine cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line));
+    if (object.ThisSnapperMightSnap()) {
+        object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, Inkscape::SNAPSOURCE_GUIDE_ORIGIN, true, Geom::OptRect(), cl, NULL);
+    }
+
+    // Snap to guides
+    if (snapprefs.getSnapToGuides()) {
+        guide.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, Inkscape::SNAPSOURCE_GUIDE_ORIGIN, true, Geom::OptRect(), cl, NULL);
+    }
+
+    // We won't snap to grids, what's the use?
+
+    Inkscape::SnappedPoint const s = findBestSnap(p, Inkscape::SNAPSOURCE_GUIDE, sc, false);
+    s.getPoint(p);
+}
 
 /**
  *  Main internal snapping method, which is called by the other, friendlier, public
index 5290ef081ed3f90a98012439900b2981911cf573..ba920510f1b61d669ac880c3ecd4791f468d14d0 100644 (file)
@@ -23,6 +23,7 @@
 #include "guide-snapper.h"
 #include "object-snapper.h"
 #include "snap-preferences.h"
+//#include "sp-guide.h"
 
 class SPNamedView;
 
@@ -98,7 +99,8 @@ public:
                                            bool first_point = true,
                                            Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const;
 
-    void guideSnap(Geom::Point &p, Geom::Point const &guide_normal) const;
+    void guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal) const;
+    void guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const;
 
     Inkscape::SnappedPoint freeSnapTranslation(Inkscape::SnapPreferences::PointType point_type,
                                                std::vector<std::pair<Geom::Point, int> > const &p,
index ee7c12aa7e9687d785401a7fad2a51de18ca5f0b..d071afddc7c9f29120fbe869940380a5b2436892 100644 (file)
@@ -62,6 +62,7 @@ enum SnapSourceType {
     SNAPSOURCE_HANDLE,
     SNAPSOURCE_PATH_INTERSECTION,
     SNAPSOURCE_GUIDE,
+    SNAPSOURCE_GUIDE_ORIGIN,
     SNAPSOURCE_CONVEX_HULL_CORNER,
     SNAPSOURCE_ELLIPSE_QUADRANT_POINT,
     SNAPSOURCE_CENTER, // of ellipse