Code

Refactoring the snapping API (making it easier to maintain and understand for the...
[inkscape.git] / src / gradient-drag.cpp
index 1394cd7581d8e602a44a17db2ba1b6230e1be7c2..726f4d78add1f7fdd6e655a9db05bf49d081bcd2 100644 (file)
@@ -298,7 +298,7 @@ GrDrag::addStopNearPoint (SPItem *item, Geom::Point mouse_p, double tolerance)
             Geom::Point end     = sp_item_gradient_get_coords(item, POINT_LG_END, 0, fill_or_stroke);
 
             Geom::Point nearest = snap_vector_midpoint (mouse_p, begin, end, 0);
-            double dist_screen = NR::L2 (mouse_p - nearest);
+            double dist_screen = Geom::L2 (mouse_p - nearest);
             if ( dist_screen < tolerance ) {
                 // add the knot
                 offset = get_offset_between_points(nearest, begin, end);
@@ -309,7 +309,7 @@ GrDrag::addStopNearPoint (SPItem *item, Geom::Point mouse_p, double tolerance)
             Geom::Point begin = sp_item_gradient_get_coords(item, POINT_RG_CENTER, 0, fill_or_stroke);
             Geom::Point end   = sp_item_gradient_get_coords(item, POINT_RG_R1, 0, fill_or_stroke);
             Geom::Point nearest = snap_vector_midpoint (mouse_p, begin, end, 0);
-            double dist_screen = NR::L2 (mouse_p - nearest);
+            double dist_screen = Geom::L2 (mouse_p - nearest);
             if ( dist_screen < tolerance ) {
                 offset = get_offset_between_points(nearest, begin, end);
                 addknot = true;
@@ -319,7 +319,7 @@ GrDrag::addStopNearPoint (SPItem *item, Geom::Point mouse_p, double tolerance)
 
             end    = sp_item_gradient_get_coords(item, POINT_RG_R2, 0, fill_or_stroke);
             nearest = snap_vector_midpoint (mouse_p, begin, end, 0);
-            dist_screen = NR::L2 (mouse_p - nearest);
+            dist_screen = Geom::L2 (mouse_p - nearest);
             if ( dist_screen < tolerance ) {
                 offset = get_offset_between_points(nearest, begin, end);
                 addknot = true;
@@ -358,13 +358,13 @@ GrDrag::addStopNearPoint (SPItem *item, Geom::Point mouse_p, double tolerance)
 
 
 bool
-GrDrag::dropColor(SPItem */*item*/, gchar *c, Geom::Point p)
+GrDrag::dropColor(SPItem */*item*/, gchar const *c, Geom::Point p)
 {
     // first, see if we can drop onto one of the existing draggers
     for (GList *i = draggers; i != NULL; i = i->next) { // for all draggables of dragger
         GrDragger *d = (GrDragger *) i->data;
 
-        if (NR::L2(p - d->point)*desktop->current_zoom() < 5) {
+        if (Geom::L2(p - d->point)*desktop->current_zoom() < 5) {
            SPCSSAttr *stop = sp_repr_css_attr_new ();
            sp_repr_css_set_property (stop, "stop-color", c);
            sp_repr_css_set_property (stop, "stop-opacity", "1");
@@ -385,7 +385,7 @@ GrDrag::dropColor(SPItem */*item*/, gchar *c, Geom::Point p)
         for (GSList *l = lines; (l != NULL) && (!over_line); l = l->next) {
             line = (SPCtrlLine*) l->data;
             Geom::Point nearest = snap_vector_midpoint (p, line->s, line->e, 0);
-            double dist_screen = NR::L2 (p - nearest) * desktop->current_zoom();
+            double dist_screen = Geom::L2 (p - nearest) * desktop->current_zoom();
             if (line->item && dist_screen < 5) {
                 SPStop *stop = addStopNearPoint (line->item, p, 5/desktop->current_zoom());
                 if (stop) {
@@ -541,8 +541,9 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp
 
     Geom::Point p = ppointer;
 
-    // FIXME: take from prefs
-    double snap_dist = SNAP_DIST / dragger->parent->desktop->current_zoom();
+    SPDesktop *desktop = dragger->parent->desktop;
+       SnapManager &m = desktop->namedview->snap_manager;
+       double snap_dist = m.snapprefs.getObjectTolerance() / dragger->parent->desktop->current_zoom();
 
     if (state & GDK_SHIFT_MASK) {
         // with Shift; unsnap if we carry more than one draggable
@@ -565,7 +566,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp
         // without Shift or Ctrl; see if we need to snap to another dragger
         for (GList *di = dragger->parent->draggers; di != NULL; di = di->next) {
             GrDragger *d_new = (GrDragger *) di->data;
-            if (dragger->mayMerge(d_new) && NR::L2 (d_new->point - p) < snap_dist) {
+            if (dragger->mayMerge(d_new) && Geom::L2 (d_new->point - p) < snap_dist) {
 
                 // Merge draggers:
                 for (GSList const* i = dragger->draggables; i != NULL; i = i->next) { // for all draggables of dragger
@@ -593,51 +594,19 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp
         }
     }
 
-    if (!((state & GDK_SHIFT_MASK) || ((state & GDK_CONTROL_MASK) && (state & GDK_MOD1_MASK)))) {
-        // Try snapping to the grid or guides
-        SPDesktop *desktop = dragger->parent->desktop;
-        SnapManager &m = desktop->namedview->snap_manager;
-        m.setup(desktop);
-        Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p));
+    m.setup(desktop);
+    if (!((state & GDK_SHIFT_MASK) || (state & GDK_CONTROL_MASK))) {
+        Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_OTHER, Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_HANDLE));
         if (s.getSnapped()) {
             p = s.getPoint();
             sp_knot_moveto (knot, p);
-        } else {
-            bool was_snapped = false;
-            double dist = NR_HUGE;
-            // No snapping so far, let's see if we need to snap to any of the levels
-            for (guint i = 0; i < dragger->parent->hor_levels.size(); i++) {
-                dist = fabs(p[Geom::Y] - dragger->parent->hor_levels[i]);
-                if (dist < snap_dist) {
-                    p[Geom::Y] = dragger->parent->hor_levels[i];
-                    s = Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_GRADIENT, dist, snap_dist, false, false);
-                    was_snapped = true;
-                    sp_knot_moveto (knot, p);
-                }
-            }
-            for (guint i = 0; i < dragger->parent->vert_levels.size(); i++) {
-                dist = fabs(p[Geom::X] - dragger->parent->vert_levels[i]);
-                if (dist < snap_dist) {
-                    p[Geom::X] = dragger->parent->vert_levels[i];
-                    s = Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_GRADIENT, dist, snap_dist, false, false);
-                    was_snapped = true;
-                    sp_knot_moveto (knot, p);
-                }
-            }
-            if (was_snapped) {
-                desktop->snapindicator->set_new_snappoint(s);
-            }
         }
-    }
-
-    if (state & GDK_CONTROL_MASK) {
+    } else if (state & GDK_CONTROL_MASK) {
+        SnappedConstraints sc;
         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
         unsigned snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12));
         /* 0 means no snapping. */
 
-        // This list will store snap vectors from all draggables of dragger
-        GSList *snap_vectors = NULL;
-
         for (GSList const* i = dragger->draggables; i != NULL; i = i->next) {
             GrDraggable *draggable = (GrDraggable *) i->data;
 
@@ -683,30 +652,32 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp
             if (dr_snap.isFinite()) {
                 if (state & GDK_MOD1_MASK) {
                     // with Alt, snap to the original angle and its perpendiculars
-                    snap_vector = get_snap_vector (p, dr_snap, M_PI/2, NR::atan2 (dragger->point_original - dr_snap));
+                    snap_vector = get_snap_vector (p, dr_snap, M_PI/2, Geom::atan2 (dragger->point_original - dr_snap));
                 } else {
                     // with Ctrl, snap to M_PI/snaps
                     snap_vector = get_snap_vector (p, dr_snap, M_PI/snaps, 0);
                 }
-            }
-            if (snap_vector) {
-                snap_vectors = g_slist_prepend (snap_vectors, &(*snap_vector));
+                if (snap_vector) {
+                    Inkscape::Snapper::ConstraintLine cl(dr_snap, p + *snap_vector - dr_snap);
+                    Inkscape::SnappedPoint s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_OTHER, Inkscape::SnapCandidatePoint(p + *snap_vector, Inkscape::SNAPSOURCE_HANDLE), cl);
+                    if (s.getSnapped()) {
+                        s.setTransformation(s.getPoint() - p);
+                        sc.points.push_back(s);
+                    } else {
+                        Inkscape::SnappedPoint dummy(p + *snap_vector, Inkscape::SNAPSOURCE_HANDLE, 0, Inkscape::SNAPTARGET_CONSTRAINED_ANGLE, Geom::L2(*snap_vector), 10000, true, false);
+                        dummy.setTransformation(*snap_vector);
+                        sc.points.push_back(dummy);
+                    }
+                }
             }
         }
 
-        // Move by the smallest of snap vectors:
-        Geom::Point move(9999, 9999);
-        for (GSList const *i = snap_vectors; i != NULL; i = i->next) {
-            Geom::Point *snap_vector = (Geom::Point *) i->data;
-            if (NR::L2(*snap_vector) < NR::L2(move))
-                move = *snap_vector;
-        }
-        if (move[Geom::X] < 9999) {
-            p += move;
+        Inkscape::SnappedPoint bsp = m.findBestSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_HANDLE), sc, true); // snap indicator will be displayed if needed
+
+        if (bsp.getSnapped()) {
+            p += bsp.getTransformation();
             sp_knot_moveto (knot, p);
         }
-
-        g_slist_free(snap_vectors);
     }
 
     drag->keep_selection = (bool) g_list_find(drag->selected, dragger);
@@ -846,11 +817,11 @@ gr_knot_moved_midpoint_handler(SPKnot */*knot*/, Geom::Point const &ppointer, gu
         if (state & GDK_MOD1_MASK) {
             // FIXME: unify all these profiles (here, in nodepath, in tweak) in one place
             double alpha = 1.0;
-            if (NR::L2(drg->point - dragger->point) + NR::L2(drg->point - begin) - 1e-3 > NR::L2(dragger->point - begin)) { // drg is on the end side from dragger
-                double x = NR::L2(drg->point - dragger->point)/NR::L2(end - dragger->point);
+            if (Geom::L2(drg->point - dragger->point) + Geom::L2(drg->point - begin) - 1e-3 > Geom::L2(dragger->point - begin)) { // drg is on the end side from dragger
+                double x = Geom::L2(drg->point - dragger->point)/Geom::L2(end - dragger->point);
                 this_move = (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5) * this_move;
             } else { // drg is on the begin side from dragger
-                double x = NR::L2(drg->point - dragger->point)/NR::L2(begin - dragger->point);
+                double x = Geom::L2(drg->point - dragger->point)/Geom::L2(begin - dragger->point);
                 this_move = (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5) * this_move;
             }
         }
@@ -1452,7 +1423,7 @@ GrDrag::selectByCoords(std::vector<Geom::Point> coords)
     for (GList *l = this->draggers; l != NULL; l = l->next) {
         GrDragger *d = ((GrDragger *) l->data);
         for (guint k = 0; k < coords.size(); k++) {
-            if (NR::L2 (d->point - coords[k]) < 1e-4) {
+            if (Geom::L2 (d->point - coords[k]) < 1e-4) {
                 setSelected (d, true, true);
             }
         }
@@ -1563,7 +1534,7 @@ GrDrag::addDragger (GrDraggable *draggable)
 
     for (GList *i = this->draggers; i != NULL; i = i->next) {
         GrDragger *dragger = (GrDragger *) i->data;
-        if (dragger->mayMerge (draggable) && NR::L2 (dragger->point - p) < MERGE_DIST) {
+        if (dragger->mayMerge (draggable) && Geom::L2 (dragger->point - p) < MERGE_DIST) {
             // distance is small, merge this draggable into dragger, no need to create new dragger
             dragger->addDraggable (draggable);
             dragger->updateKnotShape();