Code

Split SPCanvasItem and SPCanvasGroup to individual .h files. Removed forward header.
[inkscape.git] / src / display / sp-canvas.cpp
index e640911d66ce9cba1d5292fdbfbd5fb4958e8e1a..fc68bcfc00a3c6ac304033832b183ab925738eab 100644 (file)
@@ -1,5 +1,3 @@
-#define __SP_CANVAS_C__
-
 /** \file
  * Port of GnomeCanvas for Inkscape needs
  *
 
 #include "helper/sp-marshal.h"
 #include <helper/recthull.h>
-#include <display/sp-canvas.h>
-#include "display-forward.h"
+#include "display/sp-canvas.h"
+#include "display/sp-canvas-group.h"
 #include <2geom/matrix.h>
-#include <libnr/nr-convex-hull.h>
+#include "libnr/nr-convex-hull.h"
 #include "preferences.h"
 #include "inkscape.h"
 #include "sodipodi-ctrlrect.h"
@@ -103,6 +101,7 @@ static void group_remove (SPCanvasGroup *group, SPCanvasItem *item);
 /* SPCanvasItem */
 
 enum {ITEM_EVENT, ITEM_LAST_SIGNAL};
+enum {PROP_0, PROP_VISIBLE};
 
 
 static void sp_canvas_request_update (SPCanvas *canvas);
@@ -114,11 +113,10 @@ static void sp_canvas_item_dispose (GObject *object);
 static void sp_canvas_item_construct (SPCanvasItem *item, SPCanvasGroup *parent, gchar const *first_arg_name, va_list args);
 
 static int emit_event (SPCanvas *canvas, GdkEvent *event);
+static int pick_current_item (SPCanvas *canvas, GdkEvent *event);
 
 static guint item_signals[ITEM_LAST_SIGNAL] = { 0 };
 
-static GtkObjectClass *item_parent_class;
-
 /**
  * Registers the SPCanvasItem class with Glib and returns its type number.
  */
@@ -151,9 +149,6 @@ sp_canvas_item_class_init (SPCanvasItemClass *klass)
 {
     GObjectClass *object_class = (GObjectClass *) klass;
 
-    /* fixme: Derive from GObject */
-    item_parent_class = (GtkObjectClass*)gtk_type_class (GTK_TYPE_OBJECT);
-
     item_signals[ITEM_EVENT] = g_signal_new ("event",
                                              G_TYPE_FROM_CLASS (klass),
                                              G_SIGNAL_RUN_LAST,
@@ -172,6 +167,9 @@ sp_canvas_item_class_init (SPCanvasItemClass *klass)
 static void
 sp_canvas_item_init (SPCanvasItem *item)
 {
+    // TODO items should not be visible on creation - this causes kludges with items
+    // that should be initially invisible; examples of such items: node handles, the CtrlRect
+    // used for rubberbanding, path outline, etc.
     item->flags |= SP_CANVAS_ITEM_VISIBLE;
     item->xform = Geom::Matrix(Geom::identity());
 }
@@ -277,7 +275,7 @@ sp_canvas_item_dispose (GObject *object)
         group_remove (SP_CANVAS_GROUP (item->parent), item);
     }
 
-    G_OBJECT_CLASS (item_parent_class)->dispose (object);
+    G_OBJECT_CLASS (g_type_class_peek(g_type_parent(sp_canvas_item_get_type())))->dispose (object);
 }
 
 /**
@@ -477,6 +475,13 @@ sp_canvas_item_lower (SPCanvasItem *item, int positions)
     item->canvas->need_repick = TRUE;
 }
 
+bool
+sp_canvas_item_is_visible (SPCanvasItem *item)
+{
+    return item->flags & SP_CANVAS_ITEM_VISIBLE;
+}
+
+
 /**
  * Sets visible flag on item and requests a redraw.
  */
@@ -542,8 +547,13 @@ sp_canvas_item_grab (SPCanvasItem *item, guint event_mask, GdkCursor *cursor, gu
     if (item->canvas->grabbed_item)
         return -1;
 
-    if (!(item->flags & SP_CANVAS_ITEM_VISIBLE))
-        return -1;
+    // This test disallows grabbing events by an invisible item, which may be useful
+    // sometimes. An example is the hidden control point used for the selector component,
+    // where it is used for object selection and rubberbanding. There seems to be nothing
+    // preventing this except this test, so I removed it.
+    // -- Krzysztof KosiƄski, 2009.08.12
+    //if (!(item->flags & SP_CANVAS_ITEM_VISIBLE))
+    //    return -1;
 
     if (HAS_BROKEN_MOTION_HINTS) {
         event_mask &= ~GDK_POINTER_MOTION_HINT_MASK;
@@ -1316,6 +1326,20 @@ emit_event (SPCanvas *canvas, GdkEvent *event)
     if (canvas->grabbed_item && !is_descendant (canvas->current_item, canvas->grabbed_item)) {
         item = canvas->grabbed_item;
     } else {
+        // Make sure that current_item is up-to-date. If a snap indicator was just deleted, then
+        // sp_canvas_item_dispose has been called and there is no current_item specified. We need
+        // that though because otherwise we don't know where to send this event to, leading to a
+        // lost event. We can't wait for idle events to have current_item updated, we need it now!
+        // Otherwise, scrolling when hovering above a pre-snap indicator won't work (for example)
+        // See this bug report: https://bugs.launchpad.net/inkscape/+bug/522335/comments/8
+        if (canvas->need_repick && !canvas->in_repick && event->type == GDK_SCROLL) {
+            // To avoid side effects, we'll only do this for scroll events, because this is the
+            // only thing we want to fix here. An example of a reported side effect is that
+            // otherwise selection of nodes in the node editor by dragging a rectangle using a
+            // tablet will break
+            canvas->need_repick = FALSE;
+            pick_current_item (canvas, (GdkEvent *) event);
+        }
         item = canvas->current_item;
     }
 
@@ -1481,6 +1505,8 @@ pick_current_item (SPCanvas *canvas, GdkEvent *event)
         retval = emit_event (canvas, &new_event);
     }
 
+
+
     return retval;
 }
 
@@ -1578,7 +1604,7 @@ static inline void request_motions(GdkWindow *w, GdkEventMotion *event) {
 static int
 sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
 {
-       int status;
+    int status;
     SPCanvas *canvas = SP_CANVAS (widget);
 
     track_latency((GdkEvent *)event);
@@ -1590,11 +1616,11 @@ sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
         return FALSE;
 
     canvas->state = event->state;
-       pick_current_item (canvas, (GdkEvent *) event);
-       status = emit_event (canvas, (GdkEvent *) event);
-       if (event->is_hint) {
-               request_motions(widget->window, event);
-       }
+    pick_current_item (canvas, (GdkEvent *) event);
+    status = emit_event (canvas, (GdkEvent *) event);
+    if (event->is_hint) {
+        request_motions(widget->window, event);
+    }
 
     return status;
 }
@@ -2085,7 +2111,7 @@ paint (SPCanvas *canvas)
 static int
 do_update (SPCanvas *canvas)
 {
-    if (!canvas->root || !canvas->pixmap_gc) // canvas may have already be destroyed by closing desktop durring interrupted display!
+    if (!canvas->root || !canvas->pixmap_gc) // canvas may have already be destroyed by closing desktop during interrupted display!
         return TRUE;
         
     if (canvas->drawing_disabled)
@@ -2189,6 +2215,7 @@ sp_canvas_scroll_to (SPCanvas *canvas, double cx, double cy, unsigned int clear,
     } else {
         // scrolling as part of zoom; do nothing here - the next do_update will perform full redraw
     }
+
 }
 
 /**
@@ -2423,4 +2450,4 @@ void sp_canvas_mark_rect(SPCanvas* canvas, int nl, int nt, int nr, int nb, uint8
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :