Code

Filter effects dialog:
[inkscape.git] / src / nodepath.cpp
index 32e302e330ad1fd7b3b7321f84f49c9f6f4ca5ca..4131c8ccaaeca8e439804d672c92a12c2b738f8a 100644 (file)
@@ -136,7 +136,7 @@ static Inkscape::NodePath::NodeSide *sp_node_opposite_side(Inkscape::NodePath::N
 static NRPathcode sp_node_path_code_from_side(Inkscape::NodePath::Node *node,Inkscape::NodePath::NodeSide *me);
 
 // active_node indicates mouseover node
-static Inkscape::NodePath::Node *active_node = NULL;
+Inkscape::NodePath::Node * Inkscape::NodePath::Path::active_node = NULL;
 
 /**
  * \brief Creates new nodepath from item
@@ -1228,9 +1228,8 @@ sp_nodepath_selected_nodes_sculpt(Inkscape::NodePath::Path *nodepath, Inkscape::
  * handle possible snapping, and commit the change with possible undo.
  */
 void
-sp_node_selected_move(gdouble dx, gdouble dy)
+sp_node_selected_move(Inkscape::NodePath::Path *nodepath, gdouble dx, gdouble dy)
 {
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (!nodepath) return;
 
     sp_nodepath_selected_nodes_move(nodepath, dx, dy, false);
@@ -1248,7 +1247,7 @@ sp_node_selected_move(gdouble dx, gdouble dy)
  * Move node selection off screen and commit the change.
  */
 void
-sp_node_selected_move_screen(gdouble dx, gdouble dy)
+sp_node_selected_move_screen(Inkscape::NodePath::Path *nodepath, gdouble dx, gdouble dy)
 {
     // borrowed from sp_selection_move_screen in selection-chemistry.c
     // we find out the current zoom factor and divide deltas by it
@@ -1258,7 +1257,6 @@ sp_node_selected_move_screen(gdouble dx, gdouble dy)
     gdouble zdx = dx / zoom;
     gdouble zdy = dy / zoom;
 
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (!nodepath) return;
 
     sp_nodepath_selected_nodes_move(nodepath, zdx, zdy, false);
@@ -1407,9 +1405,8 @@ static void sp_nodepath_update_handles(Inkscape::NodePath::Path *nodepath)
 }
 
 void
-sp_nodepath_show_handles(bool show)
+sp_nodepath_show_handles(Inkscape::NodePath::Path *nodepath, bool show)
 {
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (nodepath == NULL) return;
 
     nodepath->show_handles = show;
@@ -1517,9 +1514,8 @@ void sp_nodepath_selected_distribute(Inkscape::NodePath::Path *nodepath, NR::Dim
  * Call sp_nodepath_line_add_node() for all selected segments.
  */
 void
-sp_node_selected_add_node(void)
+sp_node_selected_add_node(Inkscape::NodePath::Path *nodepath)
 {
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (!nodepath) {
         return;
     }
@@ -1682,9 +1678,8 @@ sp_nodepath_curve_drag(int node, double t, NR::Point delta)
 /**
  * Call sp_nodepath_break() for all selected segments.
  */
-void sp_node_selected_break()
+void sp_node_selected_break(Inkscape::NodePath::Path *nodepath)
 {
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (!nodepath) return;
 
     GList *temp = NULL;
@@ -1710,9 +1705,8 @@ void sp_node_selected_break()
 /**
  * Duplicate the selected node(s).
  */
-void sp_node_selected_duplicate()
+void sp_node_selected_duplicate(Inkscape::NodePath::Path *nodepath)
 {
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (!nodepath) {
         return;
     }
@@ -1740,9 +1734,8 @@ void sp_node_selected_duplicate()
 /**
  *  Join two nodes by merging them into one.
  */
-void sp_node_selected_join()
+void sp_node_selected_join(Inkscape::NodePath::Path *nodepath)
 {
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (!nodepath) return; // there's no nodepath when editing rects, stars, spirals or ellipses
 
     if (g_list_length(nodepath->selected) != 2) {
@@ -1842,9 +1835,8 @@ void sp_node_selected_join()
 /**
  *  Join two nodes by adding a segment between them.
  */
-void sp_node_selected_join_segment()
+void sp_node_selected_join_segment(Inkscape::NodePath::Path *nodepath)
 {
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (!nodepath) return; // there's no nodepath when editing rects, stars, spirals or ellipses
 
     if (g_list_length(nodepath->selected) != 2) {
@@ -2079,9 +2071,8 @@ void sp_node_delete_preserve(GList *nodes_to_delete)
 /**
  * Delete one or more selected nodes.
  */
-void sp_node_selected_delete()
+void sp_node_selected_delete(Inkscape::NodePath::Path *nodepath)
 {
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (!nodepath) return;
     if (!nodepath->selected) return;
 
@@ -2117,12 +2108,11 @@ void sp_node_selected_delete()
  * This is the code for 'split'.
  */
 void
-sp_node_selected_delete_segment(void)
+sp_node_selected_delete_segment(Inkscape::NodePath::Path *nodepath)
 {
    Inkscape::NodePath::Node *start, *end;     //Start , end nodes.  not inclusive
    Inkscape::NodePath::Node *curr, *next;     //Iterators
 
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (!nodepath) return; // there's no nodepath when editing rects, stars, spirals or ellipses
 
     if (g_list_length(nodepath->selected) != 2) {
@@ -2278,9 +2268,8 @@ sp_node_selected_delete_segment(void)
  * Call sp_nodepath_set_line() for all selected segments.
  */
 void
-sp_node_selected_set_line_type(NRPathcode code)
+sp_node_selected_set_line_type(Inkscape::NodePath::Path *nodepath, NRPathcode code)
 {
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (nodepath == NULL) return;
 
     for (GList *l = nodepath->selected; l != NULL; l = l->next) {
@@ -2298,9 +2287,8 @@ sp_node_selected_set_line_type(NRPathcode code)
  * Call sp_nodepath_convert_node_type() for all selected nodes.
  */
 void
-sp_node_selected_set_type(Inkscape::NodePath::NodeType type)
+sp_node_selected_set_type(Inkscape::NodePath::Path *nodepath, Inkscape::NodePath::NodeType type)
 {
-    Inkscape::NodePath::Path *nodepath = sp_nodepath_current();
     if (nodepath == NULL) return;
 
     for (GList *l = nodepath->selected; l != NULL; l = l->next) {
@@ -2897,10 +2885,10 @@ static gboolean node_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::No
     gboolean ret = FALSE;
     switch (event->type) {
         case GDK_ENTER_NOTIFY:
-            active_node = n;
+            Inkscape::NodePath::Path::active_node = n;
             break;
         case GDK_LEAVE_NOTIFY:
-            active_node = NULL;
+            Inkscape::NodePath::Path::active_node = NULL;
             break;
         case GDK_SCROLL:
             if ((event->scroll.state & GDK_CONTROL_MASK) && !(event->scroll.state & GDK_SHIFT_MASK)) { // linearly
@@ -2971,33 +2959,33 @@ gboolean node_key(GdkEvent *event)
     Inkscape::NodePath::Path *np;
 
     // there is no way to verify nodes so set active_node to nil when deleting!!
-    if (active_node == NULL) return FALSE;
+    if (Inkscape::NodePath::Path::active_node == NULL) return FALSE;
 
     if ((event->type == GDK_KEY_PRESS) && !(event->key.state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))) {
         gint ret = FALSE;
         switch (get_group0_keyval (&event->key)) {
             /// \todo FIXME: this does not seem to work, the keys are stolen by tool contexts!
             case GDK_BackSpace:
-                np = active_node->subpath->nodepath;
-                sp_nodepath_node_destroy(active_node);
+                np = Inkscape::NodePath::Path::active_node->subpath->nodepath;
+                sp_nodepath_node_destroy(Inkscape::NodePath::Path::active_node);
                 sp_nodepath_update_repr(np, _("Delete node"));
-                active_node = NULL;
+                Inkscape::NodePath::Path::active_node = NULL;
                 ret = TRUE;
                 break;
             case GDK_c:
-                sp_nodepath_set_node_type(active_node,Inkscape::NodePath::NODE_CUSP);
+                sp_nodepath_set_node_type(Inkscape::NodePath::Path::active_node,Inkscape::NodePath::NODE_CUSP);
                 ret = TRUE;
                 break;
             case GDK_s:
-                sp_nodepath_set_node_type(active_node,Inkscape::NodePath::NODE_SMOOTH);
+                sp_nodepath_set_node_type(Inkscape::NodePath::Path::active_node,Inkscape::NodePath::NODE_SMOOTH);
                 ret = TRUE;
                 break;
             case GDK_y:
-                sp_nodepath_set_node_type(active_node,Inkscape::NodePath::NODE_SYMM);
+                sp_nodepath_set_node_type(Inkscape::NodePath::Path::active_node,Inkscape::NodePath::NODE_SYMM);
                 ret = TRUE;
                 break;
             case GDK_b:
-                sp_nodepath_node_break(active_node);
+                sp_nodepath_node_break(Inkscape::NodePath::Path::active_node);
                 ret = TRUE;
                 break;
         }
@@ -3513,6 +3501,16 @@ static gboolean node_handle_event(SPKnot *knot, GdkEvent *event,Inkscape::NodePa
                     break;
             }
             break;
+        case GDK_ENTER_NOTIFY:
+            // we use an experimentally determined threshold that seems to work fine
+            if (NR::L2(n->pos - knot->pos) < 0.75)
+                Inkscape::NodePath::Path::active_node = n;
+            break;
+        case GDK_LEAVE_NOTIFY:
+            // we use an experimentally determined threshold that seems to work fine
+            if (NR::L2(n->pos - knot->pos) < 0.75)
+                Inkscape::NodePath::Path::active_node = NULL;
+            break;
         default:
             break;
     }
@@ -3652,10 +3650,16 @@ void sp_nodepath_selected_nodes_rotate(Inkscape::NodePath::Path *nodepath, gdoub
             rot = angle;
         }
 
+        NR::Point rot_center;
+        if (Inkscape::NodePath::Path::active_node == NULL)
+            rot_center = box.midpoint();
+        else
+            rot_center = Inkscape::NodePath::Path::active_node->pos;
+
         NR::Matrix t =
-            NR::Matrix (NR::translate(-box.midpoint())) *
+            NR::Matrix (NR::translate(-rot_center)) *
             NR::Matrix (NR::rotate(rot)) *
-            NR::Matrix (NR::translate(box.midpoint()));
+            NR::Matrix (NR::translate(rot_center));
 
         for (GList *l = nodepath->selected; l != NULL; l = l->next) {
             Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
@@ -3777,10 +3781,16 @@ void sp_nodepath_selected_nodes_scale(Inkscape::NodePath::Path *nodepath, gdoubl
 
         double scale = (box.maxExtent() + grow)/box.maxExtent();
 
+        NR::Point scale_center;
+        if (Inkscape::NodePath::Path::active_node == NULL)
+            scale_center = box.midpoint();
+        else
+            scale_center = Inkscape::NodePath::Path::active_node->pos;
+
         NR::Matrix t =
-            NR::Matrix (NR::translate(-box.midpoint())) *
+            NR::Matrix (NR::translate(-scale_center)) *
             NR::Matrix (NR::scale(scale, scale)) *
-            NR::Matrix (NR::translate(box.midpoint()));
+            NR::Matrix (NR::translate(scale_center));
 
         for (GList *l = nodepath->selected; l != NULL; l = l->next) {
             Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
@@ -3803,11 +3813,11 @@ void sp_nodepath_selected_nodes_scale_screen(Inkscape::NodePath::Path *nodepath,
 /**
  * Flip selected nodes horizontally/vertically.
  */
-void sp_nodepath_flip (Inkscape::NodePath::Path *nodepath, NR::Dim2 axis)
+void sp_nodepath_flip (Inkscape::NodePath::Path *nodepath, NR::Dim2 axis, NR::Maybe<NR::Point> center)
 {
     if (!nodepath || !nodepath->selected) return;
 
-    if (g_list_length(nodepath->selected) == 1) {
+    if (g_list_length(nodepath->selected) == 1 && !center) {
         // flip handles of the single selected node
         Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) nodepath->selected->data;
         double temp = n->p.pos[axis];
@@ -3824,10 +3834,13 @@ void sp_nodepath_flip (Inkscape::NodePath::Path *nodepath, NR::Dim2 axis)
             box.expandTo (n->pos); // contain all selected nodes
         }
 
+        if (!center) {
+            center = box.midpoint();
+        }
         NR::Matrix t =
-            NR::Matrix (NR::translate(-box.midpoint())) *
+            NR::Matrix (NR::translate(- *center)) *
             NR::Matrix ((axis == NR::X)? NR::scale(-1, 1) : NR::scale(1, -1)) *
-            NR::Matrix (NR::translate(box.midpoint()));
+            NR::Matrix (NR::translate(*center));
 
         for (GList *l = nodepath->selected; l != NULL; l = l->next) {
             Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;