From 06908fe3837e7ca910c393a746298970a2126890 Mon Sep 17 00:00:00 2001 From: dvlierop2 Date: Wed, 25 Feb 2009 21:32:50 +0000 Subject: [PATCH] Snap guides to (intersections of) guides (closes bug #331143) --- src/desktop-events.cpp | 14 ++++++++++---- src/guide-snapper.cpp | 8 ++++++-- src/snap.cpp | 34 +++++++++++++++++++++++++++++----- src/snap.h | 15 +++++++++++++-- 4 files changed, 58 insertions(+), 13 deletions(-) diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp index 73cd64665..7c3f02847 100644 --- a/src/desktop-events.cpp +++ b/src/desktop-events.cpp @@ -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) { diff --git a/src/guide-snapper.cpp b/src/guide-snapper.cpp index 6df066cbb..989dec16b 100644 --- a/src/guide-snapper.cpp +++ b/src/guide-snapper.cpp @@ -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 diff --git a/src/snap.cpp b/src/snap.cpp index a170046c2..f6dceedba 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -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 > *unselected_nodes) +void SnapManager::setup(SPDesktop const *desktop, + bool snapindicator, + SPItem const *item_to_ignore, + std::vector > *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 &items_to_ignore, std::vector > *unselected_nodes) +void SnapManager::setup(SPDesktop const *desktop, + bool snapindicator, + std::vector &items_to_ignore, + std::vector > *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 diff --git a/src/snap.h b/src/snap.h index b6ec3a5d7..eba18f5de 100644 --- a/src/snap.h +++ b/src/snap.h @@ -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 > *unselected_nodes = NULL); - void setup(SPDesktop const *desktop, bool snapindicator, std::vector &items_to_ignore, std::vector > *unselected_nodes = NULL); + void setup(SPDesktop const *desktop, + bool snapindicator = true, + SPItem const *item_to_ignore = NULL, + std::vector > *unselected_nodes = NULL, + SPGuide *guide_to_ignore = NULL); + + void setup(SPDesktop const *desktop, + bool snapindicator, + std::vector &items_to_ignore, + std::vector > *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 *_items_to_ignore; SPItem const *_item_to_ignore; + SPGuide *_guide_to_ignore; SPDesktop const *_desktop; bool _snapindicator; std::vector > *_unselected_nodes; -- 2.30.2