summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDiederik van Lierop <mail@diedenrezi.nl>2009-06-02 04:36:17 +0000
committerdvlierop2 <dvlierop2@users.sourceforge.net>2009-06-02 04:36:17 +0000
commit9d1365da9d6ed6312e4f034df40aa64dec35c9e0 (patch)
treeb5d6de8cc2a3293d1b8db11dfd8fd17f7d8cfa06 /src
parentMoved whiteboard related file to POTFILES.ignore (diff)
downloadinkscape-9d1365da9d6ed6312e4f034df40aa64dec35c9e0.tar.gz
inkscape-9d1365da9d6ed6312e4f034df40aa64dec35c9e0.zip
When dragging the origin of a guide along that guide, we should use constrained snapping instead of free snapping. Also make sure that we snap to paths too, not just to guides
(bzr r7973)
Diffstat (limited to 'src')
-rw-r--r--src/desktop-events.cpp50
-rw-r--r--src/display/snap-indicator.cpp5
-rw-r--r--src/object-snapper.cpp37
-rw-r--r--src/object-snapper.h8
-rw-r--r--src/snap.cpp40
-rw-r--r--src/snap.h4
-rw-r--r--src/snapped-point.h1
7 files changed, 110 insertions, 35 deletions
diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp
index 3d8e88fba..17b077890 100644
--- a/src/desktop-events.cpp
+++ b/src/desktop-events.cpp
@@ -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();
diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp
index e73eef796..081496fd0 100644
--- a/src/display/snap-indicator.cpp
+++ b/src/display/snap-indicator.cpp
@@ -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;
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp
index 70377cb66..5dd9350dc 100644
--- a/src/object-snapper.cpp
+++ b/src/object-snapper.cpp
@@ -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);
diff --git a/src/object-snapper.h b/src/object-snapper.h
index f220106e3..baa60a096 100644
--- a/src/object-snapper.h
+++ b/src/object-snapper.h
@@ -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;
diff --git a/src/snap.cpp b/src/snap.cpp
index 9ca9b7838..aa0e4af5c 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -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
diff --git a/src/snap.h b/src/snap.h
index 5290ef081..ba920510f 100644
--- a/src/snap.h
+++ b/src/snap.h
@@ -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,
diff --git a/src/snapped-point.h b/src/snapped-point.h
index ee7c12aa7..d071afddc 100644
--- a/src/snapped-point.h
+++ b/src/snapped-point.h
@@ -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