Code

New widget helperclass for Gtk:Entry
[inkscape.git] / src / nodepath.cpp
index 3f76a6548e1a603db04ecdb15f8f917fe5344d53..e58a8b31da3056c9494ff62163559b3d6bc2f186 100644 (file)
@@ -94,9 +94,9 @@ static gchar *create_typestr(Inkscape::NodePath::Path *np);
 
 static void sp_node_update_handles(Inkscape::NodePath::Node *node, bool fire_move_signals = true);
 
-static void sp_nodepath_node_select(Inkscape::NodePath::Node *node, bool incremental, bool override);
+static void sp_nodepath_node_select(Inkscape::NodePath::Node *node, gboolean incremental, gboolean override);
 
-static void sp_node_set_selected(Inkscape::NodePath::Node *node, bool selected);
+static void sp_node_set_selected(Inkscape::NodePath::Node *node, gboolean selected);
 
 /* Adjust handle placement, if the node or the other handle is moved */
 static void sp_node_adjust_handle(Inkscape::NodePath::Node *node, gint which_adjust);
@@ -106,15 +106,15 @@ static void sp_node_adjust_handles(Inkscape::NodePath::Node *node);
 static void node_clicked(SPKnot *knot, guint state, gpointer data);
 static void node_grabbed(SPKnot *knot, guint state, gpointer data);
 static void node_ungrabbed(SPKnot *knot, guint state, gpointer data);
-static bool node_request(SPKnot *knot, NR::Point *p, guint state, gpointer data);
+static gboolean node_request(SPKnot *knot, NR::Point *p, guint state, gpointer data);
 
 /* Handle event callbacks */
 static void node_handle_clicked(SPKnot *knot, guint state, gpointer data);
 static void node_handle_grabbed(SPKnot *knot, guint state, gpointer data);
 static void node_handle_ungrabbed(SPKnot *knot, guint state, gpointer data);
-static bool node_handle_request(SPKnot *knot, NR::Point *p, guint state, gpointer data);
+static gboolean node_handle_request(SPKnot *knot, NR::Point *p, guint state, gpointer data);
 static void node_handle_moved(SPKnot *knot, NR::Point *p, guint state, gpointer data);
-static bool node_handle_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::Node *n);
+static gboolean node_handle_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::Node *n);
 
 /* Constructors and destructors */
 
@@ -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);
     }
 
@@ -1286,7 +1283,7 @@ static void sp_node_ensure_knot_exists (SPDesktop *desktop, Inkscape::NodePath::
 /**
  * Ensure the given handle of the node is visible/invisible, update its screen position
  */
-static void sp_node_update_handle(Inkscape::NodePath::Node *node, gint which, bool show_handle, bool fire_move_signals)
+static void sp_node_update_handle(Inkscape::NodePath::Node *node, gint which, gboolean show_handle, bool fire_move_signals)
 {
     g_assert(node != NULL);
 
@@ -1351,7 +1348,7 @@ static void sp_node_update_handles(Inkscape::NodePath::Node *node, bool fire_mov
             sp_knot_moveto(node->knot, &node->pos);
     }
 
-    bool show_handles = node->selected;
+    gboolean show_handles = node->selected;
     if (node->p.other != NULL) {
         if (node->p.other->selected) show_handles = TRUE;
     }
@@ -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
@@ -1558,11 +1556,11 @@ sp_nodepath_select_segment_near_point(Inkscape::NodePath::Path *nodepath, NR::Po
     //fixme: this can return NULL, so check before proceeding.
     g_return_if_fail(e != NULL);
     
-    bool force = FALSE;
+    gboolean force = FALSE;
     if (!(e->selected && (!e->p.other || e->p.other->selected))) {
         force = TRUE;
     }
-    sp_nodepath_node_select(e, (bool) toggle, force);
+    sp_nodepath_node_select(e, (gboolean) toggle, force);
     if (e->p.other)
         sp_nodepath_node_select(e->p.other, TRUE, force);
 
@@ -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
@@ -2120,7 +2119,7 @@ sp_node_selected_delete_segment(void)
     if (a->subpath->closed) {
 
 
-        bool reversed = FALSE;
+        gboolean reversed = FALSE;
 
         //Since we can go in a circle, we need to find the shorter distance.
         //  a->b or b->a
@@ -2276,7 +2275,7 @@ sp_node_selected_set_type(Inkscape::NodePath::NodeType type)
 /**
  * Change select status of node, update its own and neighbour handles.
  */
-static void sp_node_set_selected(Inkscape::NodePath::Node *node, bool selected)
+static void sp_node_set_selected(Inkscape::NodePath::Node *node, gboolean selected)
 {
     node->selected = selected;
 
@@ -2303,7 +2302,7 @@ static void sp_node_set_selected(Inkscape::NodePath::Node *node, bool selected)
 \param incremental   If true, add to selection, otherwise deselect others
 \param override   If true, always select this node, otherwise toggle selected status
 */
-static void sp_nodepath_node_select(Inkscape::NodePath::Node *node, bool incremental, bool override)
+static void sp_nodepath_node_select(Inkscape::NodePath::Node *node, gboolean incremental, gboolean override)
 {
     Inkscape::NodePath::Path *nodepath = node->subpath->nodepath;
 
@@ -2520,7 +2519,7 @@ void sp_nodepath_select_prev(Inkscape::NodePath::Path *nodepath)
 /**
  * \brief Select all nodes that are within the rectangle.
  */
-void sp_nodepath_select_rect(Inkscape::NodePath::Path *nodepath, NR::Rect const &b, bool incremental)
+void sp_nodepath_select_rect(Inkscape::NodePath::Path *nodepath, NR::Rect const &b, gboolean incremental)
 {
     if (!incremental) {
         sp_nodepath_deselect(nodepath);
@@ -2855,9 +2854,9 @@ static void sp_node_adjust_handles(Inkscape::NodePath::Node *node)
 /**
  * Node event callback.
  */
-static bool node_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::Node *n)
+static gboolean node_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::Node *n)
 {
-    bool ret = FALSE;
+    gboolean ret = FALSE;
     switch (event->type) {
         case GDK_ENTER_NOTIFY:
             active_node = n;
@@ -2865,6 +2864,33 @@ static bool node_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::Node *
         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 +2902,16 @@ static bool node_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::Node *
                     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:
@@ -2902,7 +2928,7 @@ static bool node_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::Node *
 /**
  * Handle keypress on node; directly called.
  */
-bool node_key(GdkEvent *event)
+gboolean node_key(GdkEvent *event)
 {
     Inkscape::NodePath::Path *np;
 
@@ -2985,6 +3011,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 +3025,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"));
 }
@@ -3033,13 +3064,13 @@ static double point_line_distance(NR::Point *p, double a)
  * Callback for node "request" signal.
  * \todo fixme: This goes to "moved" event? (lauris)
  */
-static bool
+static gboolean
 node_request(SPKnot *knot, NR::Point *p, guint state, gpointer data)
 {
     double yn, xn, yp, xp;
     double an, ap, na, pa;
     double d_an, d_ap, d_na, d_pa;
-    bool collinear = FALSE;
+    gboolean collinear = FALSE;
     NR::Point c;
     NR::Point pr;
 
@@ -3198,14 +3229,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 +3289,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);
 }
 
 /**
@@ -3277,12 +3311,13 @@ static void node_handle_ungrabbed(SPKnot *knot, guint state, gpointer data)
     }
 
     sp_nodepath_update_repr(n->subpath->nodepath, _("Move node handle"));
+    sp_canvas_end_forced_full_redraws(n->subpath->nodepath->desktop->canvas);
 }
 
 /**
  * Node handle "request" signal callback.
  */
-static bool node_handle_request(SPKnot *knot, NR::Point *p, guint state, gpointer data)
+static gboolean node_handle_request(SPKnot *knot, NR::Point *p, guint state, gpointer data)
 {
     Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) data;
 
@@ -3424,9 +3459,9 @@ static void node_handle_moved(SPKnot *knot, NR::Point *p, guint state, gpointer
 /**
  * Node handle event callback.
  */
-static bool node_handle_event(SPKnot *knot, GdkEvent *event,Inkscape::NodePath::Node *n)
+static gboolean node_handle_event(SPKnot *knot, GdkEvent *event,Inkscape::NodePath::Node *n)
 {
-    bool ret = FALSE;
+    gboolean ret = FALSE;
     switch (event->type) {
         case GDK_KEY_PRESS:
             switch (get_group0_keyval (&event->key)) {
@@ -3449,7 +3484,7 @@ static bool node_handle_event(SPKnot *knot, GdkEvent *event,Inkscape::NodePath::
 }
 
 static void node_rotate_one_internal(Inkscape::NodePath::Node const &n, gdouble const angle,
-                                 Radial &rme, Radial &rother, bool const both)
+                                 Radial &rme, Radial &rother, gboolean const both)
 {
     rme.a += angle;
     if ( both
@@ -3461,7 +3496,7 @@ static void node_rotate_one_internal(Inkscape::NodePath::Node const &n, gdouble
 }
 
 static void node_rotate_one_internal_screen(Inkscape::NodePath::Node const &n, gdouble const angle,
-                                        Radial &rme, Radial &rother, bool const both)
+                                        Radial &rme, Radial &rother, gboolean const both)
 {
     gdouble const norm_angle = angle / n.subpath->nodepath->desktop->current_zoom();
 
@@ -3492,7 +3527,7 @@ static void node_rotate_one_internal_screen(Inkscape::NodePath::Node const &n, g
 /**
  * Rotate one node.
  */
-static void node_rotate_one (Inkscape::NodePath::Node *n, gdouble angle, int which, bool screen)
+static void node_rotate_one (Inkscape::NodePath::Node *n, gdouble angle, int which, gboolean screen)
 {
     Inkscape::NodePath::NodeSide *me, *other;
     bool both = false;