Code

Remove ca.new form ALL_LINGUAS.
[inkscape.git] / src / nodepath.cpp
index 3398ac1a1267bfd78eae70754fb2e71195ffa5e6..69827bd848552cf30a67afce908b5d2fad9f871a 100644 (file)
@@ -211,9 +211,7 @@ Inkscape::NodePath::Path *sp_nodepath_new(SPDesktop *desktop, SPItem *item, bool
     sp_curve_unref(curve);
 
     // create the livarot representation from the same item
-    np->livarot_path = Path_for_item(item, true, true);
-    if (np->livarot_path)
-        np->livarot_path->ConvertWithBackData(0.01);
+    sp_nodepath_ensure_livarot_path(np);
 
     return np;
 }
@@ -247,6 +245,16 @@ void sp_nodepath_destroy(Inkscape::NodePath::Path *np) {
 }
 
 
+void sp_nodepath_ensure_livarot_path(Inkscape::NodePath::Path *np)
+{
+    if (np && np->livarot_path == NULL && np->path && SP_IS_ITEM(np->path)) {
+        np->livarot_path = Path_for_item (np->path, true, true);
+        if (np->livarot_path)
+            np->livarot_path->ConvertWithBackData(0.01);
+    }
+}
+
+
 /**
  *  Return the node count of a given NodeSubPath.
  */
@@ -482,21 +490,16 @@ void sp_nodepath_update_repr(Inkscape::NodePath::Path *np, const gchar *annotati
     //fixme: np can be NULL, so check before proceeding
     g_return_if_fail(np != NULL);
 
-    update_repr_internal(np);
-    sp_document_done(sp_desktop_document(np->desktop), SP_VERB_CONTEXT_NODE, 
-                     annotation);
-
     if (np->livarot_path) {
         delete np->livarot_path;
         np->livarot_path = NULL;
     }
 
-    if (np->path && SP_IS_ITEM(np->path)) {
-        np->livarot_path = Path_for_item (np->path, true, true);
-        if (np->livarot_path)
-            np->livarot_path->ConvertWithBackData(0.01);
-    }
-
+    update_repr_internal(np);
+    sp_canvas_end_forced_full_redraws(np->desktop->canvas);
+    
+    sp_document_done(sp_desktop_document(np->desktop), SP_VERB_CONTEXT_NODE, 
+                     annotation);
 }
 
 /**
@@ -504,20 +507,14 @@ void sp_nodepath_update_repr(Inkscape::NodePath::Path *np, const gchar *annotati
  */
 static void sp_nodepath_update_repr_keyed(Inkscape::NodePath::Path *np, gchar const *key, const gchar *annotation)
 {
-    update_repr_internal(np);
-    sp_document_maybe_done(sp_desktop_document(np->desktop), key, SP_VERB_CONTEXT_NODE, 
-                           annotation);
-
     if (np->livarot_path) {
         delete np->livarot_path;
         np->livarot_path = NULL;
     }
 
-    if (np->path && SP_IS_ITEM(np->path)) {
-        np->livarot_path = Path_for_item (np->path, true, true);
-        if (np->livarot_path)
-            np->livarot_path->ConvertWithBackData(0.01);
-    }
+    update_repr_internal(np);
+    sp_document_maybe_done(sp_desktop_document(np->desktop), key, SP_VERB_CONTEXT_NODE, 
+                           annotation);
 }
 
 /**
@@ -992,7 +989,7 @@ static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath,
     }
 
     for (GList *l = nodepath->selected; l != NULL; l = l->next) {
-       Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
+        Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
         sp_node_moveto(n, n->pos + best_pt);
     }
 
@@ -1550,6 +1547,7 @@ sp_nodepath_select_segment_near_point(Inkscape::NodePath::Path *nodepath, NR::Po
         return;
     }
 
+    sp_nodepath_ensure_livarot_path(nodepath);
     Path::cut_position position = get_nearest_position_on_Path(nodepath->livarot_path, p);
 
     //find segment to segment
@@ -1581,6 +1579,7 @@ sp_nodepath_add_node_near_point(Inkscape::NodePath::Path *nodepath, NR::Point p)
         return;
     }
 
+    sp_nodepath_ensure_livarot_path(nodepath);
     Path::cut_position position = get_nearest_position_on_Path(nodepath->livarot_path, p);
 
     //find segment to split
@@ -1609,8 +1608,10 @@ sp_nodepath_add_node_near_point(Inkscape::NodePath::Path *nodepath, NR::Point p)
  * cf. app/vectors/gimpbezierstroke.c, gimp_bezier_stroke_point_move_relative()
  */
 void
-sp_nodepath_curve_drag(Inkscape::NodePath::Node * e, double t, NR::Point delta)
+sp_nodepath_curve_drag(int node, double t, NR::Point delta)
 {
+    Inkscape::NodePath::Node *e = sp_nodepath_get_node_by_index(node);
+
     //fixme: e and e->p can be NULL, so check for those before proceeding
     g_return_if_fail(e != NULL);
     g_return_if_fail(&e->p != NULL);
@@ -1726,8 +1727,11 @@ void sp_node_selected_join()
    Inkscape::NodePath::Node *b = (Inkscape::NodePath::Node *) nodepath->selected->next->data;
 
     g_assert(a != b);
-    g_assert(a->p.other || a->n.other);
-    g_assert(b->p.other || b->n.other);
+    if (!(a->p.other || a->n.other) || !(b->p.other || b->n.other)) { 
+        // someone tried to join an orphan node (i.e. a single-node subpath).
+        // this is not worth an error message, just fail silently.
+        return;
+    }
 
     if (((a->subpath->closed) || (b->subpath->closed)) || (a->p.other && a->n.other) || (b->p.other && b->n.other)) {
         nodepath->desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("To join, you must have <b>two endnodes</b> selected."));
@@ -1825,8 +1829,11 @@ void sp_node_selected_join_segment()
    Inkscape::NodePath::Node *b = (Inkscape::NodePath::Node *) nodepath->selected->next->data;
 
     g_assert(a != b);
-    g_assert(a->p.other || a->n.other);
-    g_assert(b->p.other || b->n.other);
+    if (!(a->p.other || a->n.other) || !(b->p.other || b->n.other)) { 
+        // someone tried to join an orphan node (i.e. a single-node subpath).
+        // this is not worth an error message, just fail silently.
+        return;
+    }
 
     if (((a->subpath->closed) || (b->subpath->closed)) || (a->p.other && a->n.other) || (b->p.other && b->n.other)) {
         nodepath->desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("To join, you must have <b>two endnodes</b> selected."));
@@ -2212,7 +2219,10 @@ sp_node_selected_delete_segment(void)
         //Copy everything after 'end' to a new subpath
        Inkscape::NodePath::SubPath *t = sp_nodepath_subpath_new(nodepath);
         for (curr=end ; curr ; curr=curr->n.other) {
-            sp_nodepath_node_new(t, NULL, (Inkscape::NodePath::NodeType)curr->type, (NRPathcode)curr->code,
+            NRPathcode code = (NRPathcode) curr->code;
+            if (curr == end)
+                code = NR_MOVETO;
+            sp_nodepath_node_new(t, NULL, (Inkscape::NodePath::NodeType)curr->type, code,
                                  &curr->p.pos, &curr->pos, &curr->n.pos);
         }
 
@@ -2865,6 +2875,33 @@ static gboolean node_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::No
         case GDK_LEAVE_NOTIFY:
             active_node = NULL;
             break;
+        case GDK_SCROLL:
+            if ((event->scroll.state & GDK_CONTROL_MASK) && !(event->scroll.state & GDK_SHIFT_MASK)) { // linearly
+                switch (event->scroll.direction) {
+                    case GDK_SCROLL_UP:
+                        nodepath_grow_selection_linearly (n->subpath->nodepath, n, +1);
+                        break;
+                    case GDK_SCROLL_DOWN:
+                        nodepath_grow_selection_linearly (n->subpath->nodepath, n, -1);
+                        break;
+                    default:
+                        break;
+                }
+                ret = TRUE;
+            } else if (!(event->scroll.state & GDK_SHIFT_MASK)) { // spatially
+                switch (event->scroll.direction) {
+                    case GDK_SCROLL_UP:
+                        nodepath_grow_selection_spatially (n->subpath->nodepath, n, +1);
+                        break;
+                    case GDK_SCROLL_DOWN:
+                        nodepath_grow_selection_spatially (n->subpath->nodepath, n, -1);
+                        break;
+                    default:
+                        break;
+                }
+                ret = TRUE;
+            }
+            break;
         case GDK_KEY_PRESS:
             switch (get_group0_keyval (&event->key)) {
                 case GDK_space:
@@ -2876,16 +2913,16 @@ static gboolean node_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::No
                     break;
                 case GDK_Page_Up:
                     if (event->key.state & GDK_CONTROL_MASK) {
-                        nodepath_grow_selection_spatially (n->subpath->nodepath, n, +1);
-                    } else {
                         nodepath_grow_selection_linearly (n->subpath->nodepath, n, +1);
+                    } else {
+                        nodepath_grow_selection_spatially (n->subpath->nodepath, n, +1);
                     }
                     break;
                 case GDK_Page_Down:
                     if (event->key.state & GDK_CONTROL_MASK) {
-                        nodepath_grow_selection_spatially (n->subpath->nodepath, n, -1);
-                    } else {
                         nodepath_grow_selection_linearly (n->subpath->nodepath, n, -1);
+                    } else {
+                        nodepath_grow_selection_spatially (n->subpath->nodepath, n, -1);
                     }
                     break;
                 default:
@@ -2985,6 +3022,9 @@ static void node_grabbed(SPKnot *knot, guint state, gpointer data)
         sp_nodepath_node_select(n, (state & GDK_SHIFT_MASK), FALSE);
     }
 
+    n->is_dragging = true;
+    sp_canvas_force_full_redraw_after_interruptions(n->subpath->nodepath->desktop->canvas, 5);
+
     sp_nodepath_remember_origins (n->subpath->nodepath);
 }
 
@@ -2996,6 +3036,8 @@ static void node_ungrabbed(SPKnot *knot, guint state, gpointer data)
    Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) data;
 
    n->dragging_out = NULL;
+   n->is_dragging = false;
+   sp_canvas_end_forced_full_redraws(n->subpath->nodepath->desktop->canvas);
 
    sp_nodepath_update_repr(n->subpath->nodepath, _("Move nodes"));
 }
@@ -3198,14 +3240,16 @@ node_request(SPKnot *knot, NR::Point *p, guint state, gpointer data)
             }
         }
     } else { // move freely
-        if (state & GDK_MOD1_MASK) { // sculpt
-            sp_nodepath_selected_nodes_sculpt(n->subpath->nodepath, n, (*p) - n->origin);
-        } else {
-            sp_nodepath_selected_nodes_move(n->subpath->nodepath,
-                                        (*p)[NR::X] - n->pos[NR::X],
-                                        (*p)[NR::Y] - n->pos[NR::Y],
-                                        (state & GDK_SHIFT_MASK) == 0);
-       }
+        if (n->is_dragging) {
+            if (state & GDK_MOD1_MASK) { // sculpt
+                sp_nodepath_selected_nodes_sculpt(n->subpath->nodepath, n, (*p) - n->origin);
+            } else {
+                sp_nodepath_selected_nodes_move(n->subpath->nodepath,
+                                            (*p)[NR::X] - n->pos[NR::X],
+                                            (*p)[NR::Y] - n->pos[NR::Y],
+                                            (state & GDK_SHIFT_MASK) == 0);
+            }
+        }
     }
 
     n->subpath->nodepath->desktop->scroll_to_point(p);
@@ -3256,6 +3300,7 @@ static void node_handle_grabbed(SPKnot *knot, guint state, gpointer data)
         g_assert_not_reached();
     }
 
+    sp_canvas_force_full_redraw_after_interruptions(n->subpath->nodepath->desktop->canvas, 5);
 }
 
 /**
@@ -3992,6 +4037,7 @@ static void sp_nodepath_node_destroy(Inkscape::NodePath::Node *node)
         g_signal_handlers_disconnect_by_func(G_OBJECT(node->p.knot), (gpointer) G_CALLBACK(node_handle_moved), node);
         g_signal_handlers_disconnect_by_func(G_OBJECT(node->p.knot), (gpointer) G_CALLBACK(node_handle_event), node);
         g_object_unref(G_OBJECT(node->p.knot));
+        node->p.knot = NULL;
     }
 
     if (node->n.knot) {
@@ -4002,6 +4048,7 @@ static void sp_nodepath_node_destroy(Inkscape::NodePath::Node *node)
         g_signal_handlers_disconnect_by_func(G_OBJECT(node->n.knot), (gpointer) G_CALLBACK(node_handle_moved), node);
         g_signal_handlers_disconnect_by_func(G_OBJECT(node->n.knot), (gpointer) G_CALLBACK(node_handle_event), node);
         g_object_unref(G_OBJECT(node->n.knot));
+        node->n.knot = NULL;
     }
 
     if (node->p.line)