Code

Snap guides to (intersections of) guides (closes bug #331143)
authordvlierop2 <dvlierop2@users.sourceforge.net>
Wed, 25 Feb 2009 21:32:50 +0000 (21:32 +0000)
committerdvlierop2 <dvlierop2@users.sourceforge.net>
Wed, 25 Feb 2009 21:32:50 +0000 (21:32 +0000)
src/desktop-events.cpp
src/guide-snapper.cpp
src/snap.cpp
src/snap.h

index 73cd646650d0f66077bac56885ec4d54229c3846..7c3f0284738b5e74316190dd09d1c21ea47b8168 100644 (file)
@@ -88,6 +88,8 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
             if (event->button.button == 1) {
                 dragging = true;
                 sp_canvas_set_snap_delay_active(desktop->canvas, true);
+                // FIXME: The snap delay mechanism won't work here, because it has been implemented for the canvas. Dragging
+                // guides off the ruler will send event to the ruler and not to the canvas, which bypasses sp_canvas_motion
                 Geom::Point const event_w(sp_canvas_window_to_world(dtw->canvas, event_win));
                 Geom::Point const event_dt(desktop->w2d(event_w));
 
@@ -145,6 +147,8 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
 
                 SnapManager &m = desktop->namedview->snap_manager;
                 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);
 
                 sp_guideline_set_position(SP_GUIDELINE(guide), from_2geom(event_dt));
@@ -160,6 +164,8 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
 
                 SnapManager &m = desktop->namedview->snap_manager;
                 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);
 
                 dragging = false;
@@ -263,10 +269,10 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                                            event->motion.y);
                 Geom::Point motion_dt(desktop->w2d(motion_w));
 
-                // This is for snapping while dragging existing guidelines. New guidelines, 
+                // This is for snapping while dragging existing guidelines. New guidelines,
                 // which are dragged off the ruler, are being snapped in sp_dt_ruler_event
                 SnapManager &m = desktop->namedview->snap_manager;
-                m.setup(desktop);
+                m.setup(desktop, true, NULL, NULL, guide);
                 m.guideSnap(motion_dt, to_2geom(guide->normal_to_line));
 
                 switch (drag_type) {
@@ -313,8 +319,8 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
                     Geom::Point event_dt(desktop->w2d(event_w));
 
                     SnapManager &m = desktop->namedview->snap_manager;
-                    m.setup(desktop);
-                    m.guideSnap(event_dt, guide->normal_to_line);
+                    m.setup(desktop, true, NULL, NULL, guide);
+                                       m.guideSnap(event_dt, guide->normal_to_line);
 
                     if (sp_canvas_world_pt_inside_window(item->canvas, event_w)) {
                         switch (drag_type) {
index 6df066cbbf3d2ad7f65f9fd0b615a8f1f56c5665..989dec16b4662de1986aebd52a198c4a5c4b3fd9 100644 (file)
@@ -46,9 +46,13 @@ Inkscape::GuideSnapper::LineList Inkscape::GuideSnapper::_getSnapLines(Geom::Poi
         return s;
     }
 
+    SPGuide const *guide_to_ignore = _snapmanager->getGuideToIgnore();
+
     for (GSList const *l = _snapmanager->getNamedView()->guides; l != NULL; l = l->next) {
         SPGuide const *g = SP_GUIDE(l->data);
-        s.push_back(std::make_pair(g->normal_to_line, g->point_on_line));
+        if (g != guide_to_ignore) {
+               s.push_back(std::make_pair(g->normal_to_line, g->point_on_line));
+        }
     }
 
     return s;
@@ -63,7 +67,7 @@ bool Inkscape::GuideSnapper::ThisSnapperMightSnap() const
                return false;
        }
 
-       return (_snap_enabled && _snapmanager->snapprefs.getSnapToGuides() && _snapmanager->snapprefs.getSnapModeBBoxOrNodes() && _snapmanager->getNamedView()->showguides);
+       return (_snap_enabled && _snapmanager->snapprefs.getSnapToGuides() && _snapmanager->getNamedView()->showguides);
 }
 
 void Inkscape::GuideSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Point const normal_to_line, Geom::Point const point_on_line) const
index a170046c23c4a70232e82819e25f3d03d6e4affc..f6dceedba7e8fe6c46e759246c555445c5184f0c 100644 (file)
@@ -329,19 +329,33 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P
 
 void SnapManager::guideSnap(Geom::Point &p, Geom::Point const &guide_normal) const
 {
-    // This method is used to snap a guide to nodes, while dragging the guide around
+    // 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->canvas->context_snap_delay_active == false) {
                g_warning("context_snap_delay_active has not been set to true by the current context. Please report this!");
                // When the context goes into dragging-mode, then Inkscape should call this: sp_canvas_set_snap_delay_active(desktop->canvas, true);
        }
 
-    if ( !(object.GuidesMightSnap() && snapprefs.getSnapEnabledGlobally()) || snapprefs.getSnapPostponedGlobally() ) {
+    if (!snapprefs.getSnapEnabledGlobally() || snapprefs.getSnapPostponedGlobally()) {
+       return;
+    }
+
+    if (!(object.GuidesMightSnap() || snapprefs.getSnapToGuides())) {
         return;
     }
 
+    // Snap to nodes
     SnappedConstraints sc;
-    object.guideSnap(sc, p, guide_normal);
+    if (object.GuidesMightSnap()) {
+       object.guideSnap(sc, p, guide_normal);
+    }
+
+    // Snap to guides
+    if (snapprefs.getSnapToGuides()) {
+       guide.freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, Inkscape::SNAPSOURCE_GUIDE, true, Geom::OptRect(), NULL, 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);
@@ -874,7 +888,11 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, Inkscape:
     return bestSnappedPoint;
 }
 
-void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, SPItem const *item_to_ignore, std::vector<std::pair<Geom::Point, int> > *unselected_nodes)
+void SnapManager::setup(SPDesktop const *desktop,
+               bool snapindicator,
+               SPItem const *item_to_ignore,
+               std::vector<std::pair<Geom::Point, int> > *unselected_nodes,
+               SPGuide *guide_to_ignore)
 {
     g_assert(desktop != NULL);
     _item_to_ignore = item_to_ignore;
@@ -882,9 +900,14 @@ void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, SPItem con
     _desktop = desktop;
     _snapindicator = snapindicator;
     _unselected_nodes = unselected_nodes;
+    _guide_to_ignore = guide_to_ignore;
 }
 
-void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, std::vector<SPItem const *> &items_to_ignore, std::vector<std::pair<Geom::Point, int> > *unselected_nodes)
+void SnapManager::setup(SPDesktop const *desktop,
+               bool snapindicator,
+               std::vector<SPItem const *> &items_to_ignore,
+               std::vector<std::pair<Geom::Point, int> > *unselected_nodes,
+               SPGuide *guide_to_ignore)
 {
     g_assert(desktop != NULL);
     _item_to_ignore = NULL;
@@ -892,6 +915,7 @@ void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, std::vecto
     _desktop = desktop;
     _snapindicator = snapindicator;
     _unselected_nodes = unselected_nodes;
+    _guide_to_ignore = guide_to_ignore;
 }
 
 SPDocument *SnapManager::getDocument() const
index b6ec3a5d74d64629cb70a3a220bf55e848905e46..eba18f5deae5ce6e926672d85c76b43b860be3b4 100644 (file)
@@ -56,8 +56,17 @@ public:
     bool someSnapperMightSnap() const;
     bool gridSnapperMightSnap() const;
 
-    void setup(SPDesktop const *desktop, bool snapindicator = true, SPItem const *item_to_ignore = NULL, std::vector<std::pair<Geom::Point, int> > *unselected_nodes = NULL);
-    void setup(SPDesktop const *desktop, bool snapindicator, std::vector<SPItem const *> &items_to_ignore, std::vector<std::pair<Geom::Point, int> > *unselected_nodes = NULL);
+    void setup(SPDesktop const *desktop,
+                       bool snapindicator = true,
+                       SPItem const *item_to_ignore = NULL,
+                       std::vector<std::pair<Geom::Point, int> > *unselected_nodes = NULL,
+                       SPGuide *guide_to_ignore = NULL);
+
+    void setup(SPDesktop const *desktop,
+               bool snapindicator,
+               std::vector<SPItem const *> &items_to_ignore,
+               std::vector<std::pair<Geom::Point, int> > *unselected_nodes = NULL,
+               SPGuide *guide_to_ignore = NULL);
 
     // freeSnapReturnByRef() is preferred over freeSnap(), because it only returns a
     // point if snapping has occurred (by overwriting p); otherwise p is untouched
@@ -143,6 +152,7 @@ public:
     SPDesktop const *getDesktop() const {return _desktop;}
     SPNamedView const *getNamedView() const {return _named_view;}
     SPDocument *getDocument() const;
+    SPGuide const *getGuideToIgnore() const {return _guide_to_ignore;}
 
     bool getSnapIndicator() const {return _snapindicator;}
 
@@ -152,6 +162,7 @@ protected:
 private:
     std::vector<SPItem const *> *_items_to_ignore;
     SPItem const *_item_to_ignore;
+    SPGuide *_guide_to_ignore;
     SPDesktop const *_desktop;
     bool _snapindicator;
     std::vector<std::pair<Geom::Point, int> > *_unselected_nodes;