goocanvas r21 - in trunk: . demo docs src



Author: damon
Date: Fri Oct 31 16:50:17 2008
New Revision: 21
URL: http://svn.gnome.org/viewvc/goocanvas?rev=21&view=rev

Log:

2008-10-31  Damon Chaplin  <damon gnome org>

	    * src/goocanvas.h: 
	    (goo_canvas_get_static_root_item): new function to get static root item.
	    (goo_canvas_set_static_root_item): new function to set static root item.
	    (goo_canvas_get_static_root_item_model): new function to get static
	    root item model.
	    (goo_canvas_set_static_root_item_model): new function to set static
	    root item model.
	    (goo_canvas_request_item_redraw): new function to request a redraw of
	    an item either in device space or in the static item space.

	    * src/goocanvasitem.h (struct _GooCanvasItemIface): added
	    get_is_static() and set_is_static() interface methods.

	    * src/goocanvasitemsimple.h (struct _GooCanvasItemSimpleData): removed
	    one bit from cache_setting and used it for is_static. Hopefully that
	    won't break binary compatibility.

	    * src/goocanvas.c (struct _GooCanvasPrivate): added new private struct
	    with static root item & model and current window position.
	    (goo_canvas_init): init private struct and create static root item.
	    (goo_canvas_dispose): free static root item & model.
	    (goo_canvas_update_internal): update static items.
	    (goo_canvas_get_item_at): check static items as well.
	    (goo_canvas_get_items_at): check static items as well.
	    (goo_canvas_realize): store original window position in private struct.
	    (request_static_redraw): new function to request a redraw in static
	    coordinate space.
	    (request_all_static_redraws): new function to request a redraw of all
	    static items.
	    (paint_static_items): new function to paint the static items.
	    (goo_canvas_expose_event): call paint_static_items().
	    (goo_canvas_convert_to_static_item_space): new function to convert
	    coords to static space.
	    (goo_canvas_adjustment_value_changed): redraw the static items before
	    the window is scrolled, but in their new position. We do this so we
	    don't see them being dragged along when scrolling.
	    Redraw them again after the window has been moved. Hopefully we can
	    optimize this a bit in future to avoid the flickering.

	    * src/goocanvasitem.c (goo_canvas_item_get_is_static)
	    (goo_canvas_item_set_is_static): new functions to call the interface
	    methods if they		     are implemented. The default behavior allows old code
	    to work without crashing (but old items can't be static).

	    * src/goocanvasitemsimple.c (goo_canvas_item_simple_get_is_static)
	    (goo_canvas_item_simple_set_is_static): implemented new interface
	    functions - just get/set the bit-flag.

	    * src/goocanvasgroup.c (goo_canvas_group_add_child): call
	    set_is_static() on new child.

	    * src/goocanvasgroup.c (goo_canvas_group_set_is_static): implement new
	    interface method, calling set_is_static() for all children if changed.

	    * src/goocanvasitemsimple.c:
	    * src/goocanvasgroup.c:
	    * src/goocanvastable.c: use new goo_canvas_request_item_redraw()
	    function so static items are redrawn correctly.

	    * demo/mv-demo.c (create_static_model): 
	    * demo/demo.c (setup_static_items): added some static items to test.
	    Note that dragging around when scale != 1.0 is weird as the coord
	    spaces are different, but is expected.



Modified:
   trunk/ChangeLog
   trunk/demo/demo.c
   trunk/demo/mv-demo.c
   trunk/docs/goocanvas-sections.txt
   trunk/src/goocanvas.c
   trunk/src/goocanvas.h
   trunk/src/goocanvasgroup.c
   trunk/src/goocanvasitem.c
   trunk/src/goocanvasitem.h
   trunk/src/goocanvasitemsimple.c
   trunk/src/goocanvasitemsimple.h
   trunk/src/goocanvastable.c

Modified: trunk/demo/demo.c
==============================================================================
--- trunk/demo/demo.c	(original)
+++ trunk/demo/demo.c	Fri Oct 31 16:50:17 2008
@@ -1326,6 +1326,40 @@
 }
 
 
+static void
+setup_static_items (GooCanvas *canvas)
+{
+  GooCanvasItem *static_root, *item;
+
+  static_root = goo_canvas_get_static_root_item (canvas);
+
+  item = goo_canvas_polyline_new_line (static_root,
+				       40.0, 410.0,
+				       40.0, 330.0,
+				       "stroke-color", "midnightblue",
+				       "line-width", 3.0,
+				       "end-arrow", TRUE,
+				       "arrow-tip-length", 3.0,
+				       "arrow-length", 4.0,
+				       "arrow-width", 3.5,
+				       NULL);
+  setup_item_signals (item);
+
+  item = goo_canvas_polyline_new_line (static_root,
+				       32.0, 370.0,
+				       48.0, 370.0,
+				       "stroke-color", "midnightblue",
+				       "line-width", 3.0,
+				       NULL);
+  setup_item_signals (item);
+
+  item = goo_canvas_text_new (static_root, "N", 40, 320, -1, GTK_ANCHOR_S,
+			      "font", "Sans 12",
+			      NULL);
+  setup_item_signals (item);
+}
+
+
 /* This checks that the rgba color properties work properly, i.e. the value
    written to them is the same when read back out. */
 static void
@@ -1423,6 +1457,7 @@
   setup_texts (root); 
   setup_images (root);
   setup_invisible_texts (root);
+  setup_static_items (canvas);
 #endif
 
   test_color_properties (root);

Modified: trunk/demo/mv-demo.c
==============================================================================
--- trunk/demo/mv-demo.c	(original)
+++ trunk/demo/mv-demo.c	Fri Oct 31 16:50:17 2008
@@ -385,7 +385,8 @@
 
 
 GtkWidget *
-create_canvas_primitives (GooCanvasItemModel *model)
+create_canvas_primitives (GooCanvasItemModel *model,
+			  GooCanvasItemModel *static_model)
 {
 	GtkWidget *vbox;
 	GtkWidget *hbox;
@@ -631,6 +632,8 @@
 	   item views to render each of the items. */
 	goo_canvas_set_root_item_model (GOO_CANVAS (canvas), model);
 
+	goo_canvas_set_static_root_item_model (GOO_CANVAS (canvas), static_model);
+
 #if 0
 	g_signal_connect_after (canvas, "key_press_event",
 				G_CALLBACK (key_press),
@@ -1211,6 +1214,39 @@
 }
 
 
+static GooCanvasItemModel*
+create_static_model ()
+{
+  GooCanvasItemModel *static_root, *item;
+
+  static_root = goo_canvas_group_model_new (NULL, NULL);
+
+  item = goo_canvas_polyline_model_new_line (static_root,
+					     40.0, 410.0,
+					     40.0, 330.0,
+					     "stroke-color", "midnightblue",
+					     "line-width", 3.0,
+					     "end-arrow", TRUE,
+					     "arrow-tip-length", 3.0,
+					     "arrow-length", 4.0,
+					     "arrow-width", 3.5,
+					     NULL);
+
+  item = goo_canvas_polyline_model_new_line (static_root,
+					     32.0, 370.0,
+					     48.0, 370.0,
+					     "stroke-color", "midnightblue",
+					     "line-width", 3.0,
+					     NULL);
+
+  item = goo_canvas_text_model_new (static_root, "N", 40, 320, -1, GTK_ANCHOR_S,
+				    "font", "Sans 12",
+				    NULL);
+
+  return static_root;
+}
+
+
 static void
 test_simple_transforms (GooCanvasItemModel *root)
 {
@@ -1295,7 +1331,8 @@
 
 
 static GtkWidget*
-create_window (GooCanvasItemModel *model)
+create_window (GooCanvasItemModel *model,
+	       GooCanvasItemModel *static_model)
 {
   GtkWidget *window, *notebook;
 
@@ -1310,7 +1347,7 @@
   gtk_container_add (GTK_CONTAINER (window), notebook);
 
   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
-			    create_canvas_primitives (model),
+			    create_canvas_primitives (model, static_model),
 			    gtk_label_new ("Primitives"));
 #if 1
   gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
@@ -1375,21 +1412,23 @@
 int
 main (int argc, char *argv[])
 {
-  GooCanvasItemModel *model;
+  GooCanvasItemModel *model, *static_model;
   GtkWidget *window;
 
   gtk_set_locale ();
   gtk_init (&argc, &argv);
 
   model = create_model ();
+  static_model = create_static_model ();
 
   /* Create 2 windows to show off multiple views. */
-  window = create_window (model);
+  window = create_window (model, static_model);
 #if 1
-  window = create_window (model);
+  window = create_window (model, static_model);
 #endif
 
   g_object_unref (model);
+  g_object_unref (static_model);
 
   gtk_main ();
   return 0;

Modified: trunk/docs/goocanvas-sections.txt
==============================================================================
--- trunk/docs/goocanvas-sections.txt	(original)
+++ trunk/docs/goocanvas-sections.txt	Fri Oct 31 16:50:17 2008
@@ -95,6 +95,8 @@
 goo_canvas_item_set_simple_transform
 goo_canvas_item_get_bounds
 goo_canvas_item_is_visible
+goo_canvas_item_get_is_static
+goo_canvas_item_set_is_static
 
 <SUBSECTION>
 goo_canvas_item_animate
@@ -351,10 +353,20 @@
 
 <SUBSECTION>
 goo_canvas_new
+
+<SUBSECTION>
 goo_canvas_get_root_item
 goo_canvas_set_root_item
 goo_canvas_get_root_item_model
 goo_canvas_set_root_item_model
+
+<SUBSECTION>
+goo_canvas_get_static_root_item
+goo_canvas_set_static_root_item
+goo_canvas_get_static_root_item_model
+goo_canvas_set_static_root_item_model
+
+<SUBSECTION>
 goo_canvas_get_bounds
 goo_canvas_set_bounds
 goo_canvas_get_scale
@@ -394,6 +406,7 @@
 goo_canvas_update
 goo_canvas_request_update
 goo_canvas_request_redraw
+goo_canvas_request_item_redraw
 goo_canvas_get_default_line_width
 
 <SUBSECTION Standard>

Modified: trunk/src/goocanvas.c
==============================================================================
--- trunk/src/goocanvas.c	(original)
+++ trunk/src/goocanvas.c	Fri Oct 31 16:50:17 2008
@@ -105,6 +105,17 @@
 #include "goocanvasmarshal.h"
 
 
+#define GOO_CANVAS_GET_PRIVATE(canvas)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((canvas), GOO_TYPE_CANVAS, GooCanvasPrivate))
+
+typedef struct _GooCanvasPrivate GooCanvasPrivate;
+struct _GooCanvasPrivate {
+  GooCanvasItem *static_root_item;
+  GooCanvasItemModel *static_root_item_model;
+  gint window_x, window_y;
+};
+
+
 enum {
   PROP_0,
 
@@ -134,6 +145,7 @@
   LAST_SIGNAL
 };
 
+
 static guint canvas_signals[LAST_SIGNAL] = { 0 };
 
 static void     goo_canvas_dispose	   (GObject          *object);
@@ -201,6 +213,9 @@
 					    gboolean          redraw_if_needed);
 static void	goo_canvas_update_automatic_bounds (GooCanvas       *canvas);
 
+static void     goo_canvas_convert_to_static_item_space (GooCanvas     *canvas,
+							 gdouble       *x,
+							 gdouble       *y);
 
 G_DEFINE_TYPE (GooCanvas, goo_canvas, GTK_TYPE_CONTAINER)
 
@@ -217,6 +232,8 @@
   GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
   GtkContainerClass *container_class = (GtkContainerClass*) klass;
 
+  g_type_class_add_private (gobject_class, sizeof (GooCanvasPrivate));
+
   gobject_class->dispose	     = goo_canvas_dispose;
   gobject_class->finalize	     = goo_canvas_finalize;
   gobject_class->get_property	     = goo_canvas_get_property;
@@ -443,6 +460,8 @@
 static void
 goo_canvas_init (GooCanvas *canvas)
 {
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+
   /* We set GTK_CAN_FOCUS by default, so it works as people expect.
      Though developers can turn this off if not needed for efficiency. */
   GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS);
@@ -485,6 +504,14 @@
      time. Apps can set their own root item if required. */
   canvas->root_item = goo_canvas_group_new (NULL, NULL);
   goo_canvas_item_set_canvas (canvas->root_item, canvas);
+
+  priv->static_root_item = goo_canvas_group_new (NULL, NULL);
+  goo_canvas_item_set_canvas (priv->static_root_item, canvas);
+  goo_canvas_item_set_is_static (priv->static_root_item, TRUE);
+  priv->static_root_item_model = NULL;
+
+  priv->window_x = 0;
+  priv->window_y = 0;
 }
 
 
@@ -509,6 +536,7 @@
 goo_canvas_dispose (GObject *object)
 {
   GooCanvas *canvas = (GooCanvas*) object;
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
 
   if (canvas->model_to_item)
     {
@@ -528,6 +556,18 @@
       canvas->root_item_model = NULL;
     }
 
+  if (priv->static_root_item)
+    {
+      g_object_unref (priv->static_root_item);
+      priv->static_root_item = NULL;
+    }
+
+  if (priv->static_root_item_model)
+    {
+      g_object_unref (priv->static_root_item_model);
+      priv->static_root_item_model = NULL;
+    }
+
   if (canvas->idle_id)
     {
       g_source_remove (canvas->idle_id);
@@ -954,6 +994,142 @@
 
 
 /**
+ * goo_canvas_get_static_root_item:
+ * @canvas: a #GooCanvas.
+ *
+ * Gets the static root item of the canvas.
+ *
+ * Returns: the static root item, or %NULL.
+ **/
+GooCanvasItem*
+goo_canvas_get_static_root_item    (GooCanvas		*canvas)
+{
+  g_return_val_if_fail (GOO_IS_CANVAS (canvas), NULL);
+
+  return GOO_CANVAS_GET_PRIVATE (canvas)->static_root_item;
+}
+
+
+/**
+ * goo_canvas_set_static_root_item:
+ * @canvas: a #GooCanvas.
+ * @item: the static root item.
+ *
+ * Sets the static root item. Any existing static items are removed.
+ **/
+void
+goo_canvas_set_static_root_item    (GooCanvas		*canvas,
+				    GooCanvasItem       *item)
+{
+  GooCanvasPrivate *priv;
+
+  g_return_if_fail (GOO_IS_CANVAS (canvas));
+  g_return_if_fail (GOO_IS_CANVAS_ITEM (item));
+
+  priv = GOO_CANVAS_GET_PRIVATE (canvas);
+
+  if (priv->static_root_item == item)
+    return;
+
+  /* Remove any current model. */
+  if (priv->static_root_item_model)
+    {
+      g_object_unref (priv->static_root_item_model);
+      priv->static_root_item_model = NULL;
+    }
+
+  if (priv->static_root_item)
+    g_object_unref (priv->static_root_item);
+
+  priv->static_root_item = g_object_ref (item);
+  goo_canvas_item_set_canvas (priv->static_root_item, canvas);
+  goo_canvas_item_set_is_static (priv->static_root_item, TRUE);
+
+  canvas->need_update = TRUE;
+
+  if (GTK_WIDGET_REALIZED (canvas))
+    goo_canvas_update (canvas);
+
+  gtk_widget_queue_draw (GTK_WIDGET (canvas));
+}
+
+
+/**
+ * goo_canvas_get_static_root_item_model:
+ * @canvas: a #GooCanvas.
+ *
+ * Gets the static root item model of the canvas.
+ *
+ * Returns: the static root item model, or %NULL.
+ **/
+GooCanvasItemModel*
+goo_canvas_get_static_root_item_model (GooCanvas	  *canvas)
+{
+  g_return_val_if_fail (GOO_IS_CANVAS (canvas), NULL);
+
+  return GOO_CANVAS_GET_PRIVATE (canvas)->static_root_item_model;
+}
+
+
+/**
+ * goo_canvas_set_static_root_item_model:
+ * @canvas: a #GooCanvas.
+ * @model: the static root item model.
+ *
+ * Sets the static root item model. Any existing static item models are
+ * removed.
+ **/
+void
+goo_canvas_set_static_root_item_model (GooCanvas	  *canvas,
+				       GooCanvasItemModel *model)
+{
+  GooCanvasPrivate *priv;
+
+  g_return_if_fail (GOO_IS_CANVAS (canvas));
+  g_return_if_fail (GOO_IS_CANVAS_ITEM_MODEL (model));
+
+  priv = GOO_CANVAS_GET_PRIVATE (canvas);
+
+  if (priv->static_root_item_model == model)
+    return;
+
+  if (priv->static_root_item_model)
+    {
+      g_object_unref (priv->static_root_item_model);
+      priv->static_root_item_model = NULL;
+    }
+
+  if (priv->static_root_item)
+    {
+      g_object_unref (priv->static_root_item);
+      priv->static_root_item = NULL;
+    }
+
+  if (model)
+    {
+      priv->static_root_item_model = g_object_ref (model);
+
+      /* Create a hierarchy of canvas items for all the items in the model. */
+      priv->static_root_item = goo_canvas_create_item (canvas, model);
+    }
+  else
+    {
+      /* The model has been reset so we go back to a default root group. */
+      priv->static_root_item = goo_canvas_group_new (NULL, NULL);
+    }
+
+  goo_canvas_item_set_canvas (priv->static_root_item, canvas);
+  goo_canvas_item_set_is_static (priv->static_root_item, TRUE);
+  canvas->need_update = TRUE;
+
+  if (GTK_WIDGET_REALIZED (canvas))
+    goo_canvas_update (canvas);
+
+  gtk_widget_queue_draw (GTK_WIDGET (canvas));
+}
+
+
+/**
  * goo_canvas_get_item:
  * @canvas: a #GooCanvas.
  * @model: a #GooCanvasItemModel.
@@ -1014,19 +1190,30 @@
 			gdouble        y,
 			gboolean       is_pointer_event)
 {
+  GooCanvasPrivate *priv;
   cairo_t *cr;
   GooCanvasItem *result = NULL;
-  GList *list;
+  GList *list = NULL;
 
   g_return_val_if_fail (GOO_IS_CANVAS (canvas), NULL);
 
-  /* If no root item is set, just return NULL. */
-  if (!canvas->root_item)
-    return NULL;
-
+  priv = GOO_CANVAS_GET_PRIVATE (canvas);
   cr = goo_canvas_create_cairo_context (canvas);
-  list = goo_canvas_item_get_items_at (canvas->root_item, x, y, cr,
-				       is_pointer_event, TRUE, NULL);
+
+  if (canvas->root_item)
+    list = goo_canvas_item_get_items_at (canvas->root_item, x, y, cr,
+					 is_pointer_event, TRUE, NULL);
+
+  if (!list && priv->static_root_item)
+    {
+      gdouble static_x = x, static_y = y;
+
+      goo_canvas_convert_to_static_item_space (canvas, &static_x, &static_y);
+      list = goo_canvas_item_get_items_at (priv->static_root_item,
+					   static_x, static_y, cr,
+					   is_pointer_event, TRUE, NULL);
+    }
+
   cairo_destroy (cr);
 
   /* We just return the top item in the list. */
@@ -1059,18 +1246,29 @@
 			 gdouble        y,
 			 gboolean       is_pointer_event)
 {
+  GooCanvasPrivate *priv;
   cairo_t *cr;
-  GList *result;
+  GList *result = NULL;
 
   g_return_val_if_fail (GOO_IS_CANVAS (canvas), NULL);
 
-  /* If no root item is set, just return NULL. */
-  if (!canvas->root_item)
-    return NULL;
-
+  priv = GOO_CANVAS_GET_PRIVATE (canvas);
   cr = goo_canvas_create_cairo_context (canvas);
-  result = goo_canvas_item_get_items_at (canvas->root_item, x, y, cr,
-					 is_pointer_event, TRUE, NULL);
+
+  if (canvas->root_item)
+    result = goo_canvas_item_get_items_at (canvas->root_item, x, y, cr,
+					   is_pointer_event, TRUE, NULL);
+
+  if (priv->static_root_item)
+    {
+      gdouble static_x = x, static_y = y;
+
+      goo_canvas_convert_to_static_item_space (canvas, &static_x, &static_y);
+      result = goo_canvas_item_get_items_at (priv->static_root_item,
+					     static_x, static_y, cr,
+					     is_pointer_event, TRUE, result);
+    }
+
   cairo_destroy (cr);
 
   return result;
@@ -1181,6 +1379,7 @@
 goo_canvas_realize (GtkWidget *widget)
 {
   GooCanvas *canvas;
+  GooCanvasPrivate *priv;
   GdkWindowAttr attributes;
   gint attributes_mask;
   gint width_pixels, height_pixels;
@@ -1189,6 +1388,7 @@
   g_return_if_fail (GOO_IS_CANVAS (widget));
 
   canvas = GOO_CANVAS (widget);
+  priv = GOO_CANVAS_GET_PRIVATE (canvas);
   GTK_WIDGET_SET_FLAGS (canvas, GTK_REALIZED);
 
   attributes.window_type = GDK_WINDOW_CHILD;
@@ -1228,6 +1428,9 @@
 			 | GDK_FOCUS_CHANGE_MASK
                          | gtk_widget_get_events (widget);
 
+  priv->window_x = attributes.x;
+  priv->window_y = attributes.y;
+
   canvas->canvas_window = gdk_window_new (widget->window,
 					  &attributes, attributes_mask);
   gdk_window_set_user_data (canvas->canvas_window, widget);
@@ -1440,6 +1643,47 @@
 }
 
 
+static void
+request_static_redraw (GooCanvas             *canvas,
+		       const GooCanvasBounds *bounds)
+{
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+  GdkRectangle rect;
+
+  if (!GTK_WIDGET_DRAWABLE (canvas) || (bounds->x1 == bounds->x2))
+    return;
+
+  /* We subtract one from the left & top edges, in case anti-aliasing makes
+     the drawing use an extra pixel. */
+  rect.x = (double) bounds->x1 - priv->window_x - 1;
+  rect.y = (double) bounds->y1 - priv->window_y - 1;
+
+  /* We add an extra one here for the same reason. (The other extra one is to
+     round up to the next pixel.) And one for luck! */
+  rect.width = (double) bounds->x2 - priv->window_x - rect.x + 2 + 1;
+  rect.height = (double) bounds->y2 - priv->window_y - rect.y + 2 + 1;
+
+  gdk_window_invalidate_rect (canvas->canvas_window, &rect, FALSE);
+}
+
+
+static void
+request_all_static_redraws (GooCanvas *canvas)
+{
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+  GooCanvasBounds bounds;
+
+  if (!priv->static_root_item)
+    return;
+
+  /* Get the bounds of all the static items, relative to the window. */
+  goo_canvas_item_get_bounds (priv->static_root_item, &bounds);
+
+  /* Request a redraw of the old position. */
+  request_static_redraw (canvas, &bounds);
+}
+
+
 /* This makes sure the canvas is all set up correctly, i.e. the scrollbar
    adjustments are set, the canvas x & y offsets are calculated, and the
    canvas window is sized. */
@@ -1648,19 +1892,52 @@
 goo_canvas_adjustment_value_changed (GtkAdjustment *adjustment,
 				     GooCanvas     *canvas)
 {
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
   AtkObject *accessible;
 
   if (!canvas->freeze_count && GTK_WIDGET_REALIZED (canvas))
     {
+      /* Request a redraw of the bounds of the static items. */
+      request_all_static_redraws (canvas);
+
+      /* Move the static items to the new position. */
+      priv->window_x = -canvas->hadjustment->value;
+      priv->window_y = -canvas->vadjustment->value;
+
+      /* Now do the redraw. This makes sure the static items don't get dragged when the rest
+	 of the window is scrolled. */
+      if (adjustment)
+	gdk_window_process_updates (canvas->canvas_window, TRUE);
+
+      /* To avoid flicker of static items completely we could redraw the entire canvas whenever
+	 it is scrolled, by mapping the temporary window as we do when zooming. Though of course
+	 it is a lot slower. We could make this an option. (If this code is used we don't need
+	 to redraw the static items and process updates afterwards.) */
+#if 0
+      if (GTK_WIDGET_MAPPED (canvas))
+	gdk_window_show (canvas->tmp_window);
+#endif
+
       gdk_window_move (canvas->canvas_window,
 		       - canvas->hadjustment->value,
 		       - canvas->vadjustment->value);
-      
+
       /* If this is callback from a signal for one of the scrollbars, process
 	 updates here for smoother scrolling. */
       if (adjustment)
 	gdk_window_process_updates (canvas->canvas_window, TRUE);
 
+      /* Now make sure the static items are redrawn in their new position. */
+      request_all_static_redraws (canvas);
+
+      if (adjustment)
+	gdk_window_process_updates (canvas->canvas_window, TRUE);
+
+#if 0
+      if (GTK_WIDGET_MAPPED (canvas))
+	gdk_window_hide (canvas->tmp_window);
+#endif
+
       /* Notify any accessibility modules that the view has changed. */
       accessible = gtk_widget_get_accessible (GTK_WIDGET (canvas));
       g_signal_emit_by_name (accessible, "visible_data_changed");
@@ -2095,7 +2372,8 @@
 goo_canvas_update_internal (GooCanvas *canvas,
 			    cairo_t   *cr)
 {
-  GooCanvasBounds bounds;
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+  GooCanvasBounds bounds, static_bounds;
 
   /* It is possible that processing the first set of updates causes other
      updates to be scheduled, so we loop round until all are done. Items
@@ -2108,6 +2386,10 @@
       canvas->need_entire_subtree_update = FALSE;
       if (canvas->root_item)
 	goo_canvas_item_update (canvas->root_item, entire_tree, cr, &bounds);
+
+      if (priv->static_root_item)
+	goo_canvas_item_update (priv->static_root_item, entire_tree, cr,
+				&static_bounds);
     }
 
   /* If the bounds are automatically-calculated, update them now. */
@@ -2189,7 +2471,7 @@
 /**
  * goo_canvas_request_redraw:
  * @canvas: a #GooCanvas.
- * @bounds: the bounds to redraw.
+ * @bounds: the bounds to redraw, in device space.
  * 
  * This function is only intended to be used by subclasses of #GooCanvas or
  * #GooCanvasItem implementations.
@@ -2224,6 +2506,54 @@
 }
 
 
+/**
+ * goo_canvas_request_item_redraw:
+ * @canvas: a #GooCanvas.
+ * @bounds: the bounds of the item to redraw.
+ * @is_static: if the item is static.
+ * 
+ * This function is only intended to be used by subclasses of #GooCanvas or
+ * #GooCanvasItem implementations.
+ *
+ * Requests that the given bounds be redrawn. If the item is static the bounds are assumed to
+ * be in the static item coordinate space, otherwise they are assumed to be in device space.
+ **/
+void
+goo_canvas_request_item_redraw (GooCanvas             *canvas,
+				const GooCanvasBounds *bounds,
+				gboolean               is_static)
+{
+  if (is_static)
+    request_static_redraw (canvas, bounds);
+  else
+    goo_canvas_request_redraw (canvas, bounds);
+}
+
+
+static void
+paint_static_items (GooCanvas      *canvas,
+		    GdkEventExpose *event,
+		    cairo_t        *cr)
+{
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+  GooCanvasBounds static_bounds;
+  double static_x_offset, static_y_offset;
+
+  cairo_save (cr);
+  cairo_identity_matrix (cr);
+  static_x_offset = floor (canvas->hadjustment->value);
+  static_y_offset = floor (canvas->vadjustment->value);
+  cairo_translate (cr, static_x_offset, static_y_offset);
+  /* FIXME: Uses pixels at present - use canvas units instead? */
+  static_bounds.x1 = event->area.x - static_x_offset;
+  static_bounds.y1 = event->area.y - static_y_offset;
+  static_bounds.x2 = event->area.width + static_bounds.x1;
+  static_bounds.y2 = event->area.height + static_bounds.y1;
+  goo_canvas_item_paint (priv->static_root_item, cr, &static_bounds, 1.0);
+  cairo_restore (cr);
+}
+
+
 static gboolean
 goo_canvas_expose_event (GtkWidget      *widget,
 			 GdkEventExpose *event)
@@ -2301,6 +2631,8 @@
 
   goo_canvas_item_paint (canvas->root_item, cr, &bounds, canvas->scale);
 
+  paint_static_items (canvas, event, cr);
+
   cairo_destroy (cr);
 
   GTK_WIDGET_CLASS (goo_canvas_parent_class)->expose_event (widget, event);
@@ -3140,6 +3472,20 @@
 }
 
 
+/* Converts from device space to the coordinate space the static items are in, i.e. in pixels
+   from the top-left of the viewport window. */
+static void
+goo_canvas_convert_to_static_item_space (GooCanvas     *canvas,
+					 gdouble       *x,
+					 gdouble       *y)
+{
+  *x = ((*x - canvas->bounds.x1) * canvas->device_to_pixels_x)
+    + canvas->canvas_x_offset - canvas->hadjustment->value;
+  *y = ((*y - canvas->bounds.y1) * canvas->device_to_pixels_y)
+    + canvas->canvas_y_offset - canvas->vadjustment->value;
+}
+
+
 /**
  * goo_canvas_convert_to_item_space:
  * @canvas: a #GooCanvas.

Modified: trunk/src/goocanvas.h
==============================================================================
--- trunk/src/goocanvas.h	(original)
+++ trunk/src/goocanvas.h	Fri Oct 31 16:50:17 2008
@@ -203,6 +203,14 @@
 void                goo_canvas_set_root_item_model (GooCanvas	       *canvas,
 						    GooCanvasItemModel *model);
 
+GooCanvasItem*  goo_canvas_get_static_root_item    (GooCanvas		*canvas);
+void            goo_canvas_set_static_root_item    (GooCanvas		*canvas,
+						    GooCanvasItem      *item);
+
+GooCanvasItemModel* goo_canvas_get_static_root_item_model (GooCanvas	       *canvas);
+void                goo_canvas_set_static_root_item_model (GooCanvas	       *canvas,
+							   GooCanvasItemModel *model);
+
 GooCanvasItem*  goo_canvas_get_item	    (GooCanvas		*canvas,
 					     GooCanvasItemModel *model);
 GooCanvasItem*  goo_canvas_get_item_at	    (GooCanvas		*canvas,
@@ -298,6 +306,9 @@
 void		goo_canvas_request_update   (GooCanvas		*canvas);
 void		goo_canvas_request_redraw   (GooCanvas		*canvas,
 					     const GooCanvasBounds *bounds);
+void		goo_canvas_request_item_redraw   (GooCanvas		*canvas,
+						  const GooCanvasBounds *bounds,
+						  gboolean               is_static);
 gdouble         goo_canvas_get_default_line_width (GooCanvas    *canvas);
 
 

Modified: trunk/src/goocanvasgroup.c
==============================================================================
--- trunk/src/goocanvasgroup.c	(original)
+++ trunk/src/goocanvasgroup.c	Fri Oct 31 16:50:17 2008
@@ -151,6 +151,7 @@
 				GooCanvasItem  *child,
 				gint            position)
 {
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
   GooCanvasGroup *group = (GooCanvasGroup*) item;
   AtkObject *atk_obj, *child_atk_obj;
 
@@ -167,6 +168,7 @@
     }
 
   goo_canvas_item_set_parent (child, item);
+  goo_canvas_item_set_is_static (child, simple->simple_data->is_static);
 
   /* Emit the "children_changed" ATK signal, if ATK is enabled. */
   atk_obj = atk_gobject_accessible_for_object (G_OBJECT (item));
@@ -196,7 +198,8 @@
   if (simple->canvas)
     {
       goo_canvas_item_get_bounds (child, &bounds);
-      goo_canvas_request_redraw (simple->canvas, &bounds);
+      goo_canvas_request_item_redraw (simple->canvas, &bounds,
+				      simple->simple_data->is_static);
     }
 
   goo_canvas_util_ptr_array_move (group->items, old_position, new_position);
@@ -222,7 +225,8 @@
   if (simple->canvas)
     {
       goo_canvas_item_get_bounds (child, &bounds);
-      goo_canvas_request_redraw (simple->canvas, &bounds);
+      goo_canvas_request_item_redraw (simple->canvas, &bounds,
+				      simple->simple_data->is_static);
     }
 
   /* Emit the "children_changed" ATK signal, if ATK is enabled. */
@@ -274,6 +278,9 @@
   GooCanvasGroup *group = (GooCanvasGroup*) item;
   gint i;
 
+  if (simple->canvas == canvas)
+    return;
+
   simple->canvas = canvas;
 
   /* Recursively set the canvas of all child items. */
@@ -286,6 +293,29 @@
 
 
 static void
+goo_canvas_group_set_is_static  (GooCanvasItem *item,
+				 gboolean       is_static)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
+  gint i;
+
+  if (simple_data->is_static == is_static)
+    return;
+
+  simple_data->is_static = is_static;
+
+  /* Recursively set the canvas of all child items. */
+  for (i = 0; i < group->items->len; i++)
+    {
+      GooCanvasItem *item = group->items->pdata[i];
+      goo_canvas_item_set_is_static (item, is_static);
+    }
+}
+
+
+static void
 on_model_child_added (GooCanvasGroupModel *model,
 		      gint                 position,
 		      GooCanvasGroup      *group)
@@ -561,6 +591,7 @@
   iface->paint          = goo_canvas_group_paint;
 
   iface->set_model      = goo_canvas_group_set_model;
+  iface->set_is_static  = goo_canvas_group_set_is_static;
 }
 
 

Modified: trunk/src/goocanvasitem.c
==============================================================================
--- trunk/src/goocanvasitem.c	(original)
+++ trunk/src/goocanvasitem.c	Fri Oct 31 16:50:17 2008
@@ -676,6 +676,49 @@
 
 
 /**
+ * goo_canvas_item_get_is_static:
+ * @item: an item.
+ * 
+ * Returns %TRUE if the item is static. Static items do not move or change
+ * size when the canvas is scrolled or the scale changes.
+ *
+ * Returns: %TRUE if the item is static.
+ **/
+gboolean
+goo_canvas_item_get_is_static	(GooCanvasItem		*item)
+{
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+
+  if (iface->get_is_static)
+    return iface->get_is_static (item);
+  return FALSE;
+}
+
+
+/**
+ * goo_canvas_item_set_is_static:
+ * @item: an item.
+ * @is_static: if the item is static.
+ * 
+ * Notifies the item that it is static. Static items do not move or change
+ * size when the canvas is scrolled or the scale changes.
+ *
+ * Container items such as #GooCanvasGroup should call this function when
+ * children are added, to notify children whether they are static or not.
+ * Containers should also pass on any changes in their own status to children.
+ **/
+void
+goo_canvas_item_set_is_static	(GooCanvasItem		*item,
+				 gboolean		 is_static)
+{
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+
+  if (iface->set_is_static)
+    iface->set_is_static (item, is_static);
+}
+
+
+/**
  * goo_canvas_item_remove:
  * @item: an item.
  * 
@@ -1554,7 +1597,7 @@
  * goo_canvas_item_paint:
  * @item: a #GooCanvasItem.
  * @cr: a cairo context.
- * @bounds: the bounds that need to be repainted.
+ * @bounds: the bounds that need to be repainted, in device space.
  * @scale: the scale to use to determine whether an item should be painted.
  *  See #GooCanvasItem:visibility-threshold.
  * 

Modified: trunk/src/goocanvasitem.h
==============================================================================
--- trunk/src/goocanvasitem.h	(original)
+++ trunk/src/goocanvasitem.h	Fri Oct 31 16:50:17 2008
@@ -109,6 +109,8 @@
  * @get_style: gets the item's style.
  * @set_style: sets the item's style.
  * @is_visible: returns %TRUE if the item is currently visible.
+ * @get_is_static: returns %TRUE if the item is static.
+ * @set_is_static: notifies the item whether it is static or not.
  * @get_requested_height: returns the requested height of the item,
  *  given a particular allocated width, using the parent's coordinate space.
  * @get_model: gets the model that the canvas item is viewing.
@@ -280,6 +282,14 @@
 							 gpointer /*GtkTooltip*/		*tooltip);
 
 
+  /*< public >*/
+
+  gboolean		(* get_is_static)		(GooCanvasItem		*item);
+  void			(* set_is_static)		(GooCanvasItem		*item,
+							 gboolean		 is_static);
+
+  /*< private >*/
+
   /* Padding for future expansion */
   void (*_goo_canvas_reserved1) (void);
   void (*_goo_canvas_reserved2) (void);
@@ -287,8 +297,6 @@
   void (*_goo_canvas_reserved4) (void);
   void (*_goo_canvas_reserved5) (void);
   void (*_goo_canvas_reserved6) (void);
-  void (*_goo_canvas_reserved7) (void);
-  void (*_goo_canvas_reserved8) (void);
 };
 
 
@@ -445,6 +453,9 @@
 						       gdouble                x_offset,
 						       gdouble                y_offset);
 
+gboolean	   goo_canvas_item_get_is_static	(GooCanvasItem		*item);
+void		   goo_canvas_item_set_is_static	(GooCanvasItem		*item,
+							 gboolean		 is_static);
 
 
 /*

Modified: trunk/src/goocanvasitemsimple.c
==============================================================================
--- trunk/src/goocanvasitemsimple.c	(original)
+++ trunk/src/goocanvasitemsimple.c	Fri Oct 31 16:50:17 2008
@@ -930,6 +930,9 @@
 goo_canvas_item_simple_changed    (GooCanvasItemSimple *item,
 				   gboolean             recompute_bounds)
 {
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+
   if (recompute_bounds)
     {
       item->need_entire_subtree_update = TRUE;
@@ -945,7 +948,7 @@
   else
     {
       if (item->canvas)
-	goo_canvas_request_redraw (item->canvas, &item->bounds);
+	goo_canvas_request_item_redraw (item->canvas, &item->bounds, simple_data->is_static);
     }
 }
 
@@ -1151,6 +1154,27 @@
 }
 
 
+static gboolean
+goo_canvas_item_simple_get_is_static  (GooCanvasItem   *item)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+
+  return simple_data->is_static;
+}
+
+
+static void
+goo_canvas_item_simple_set_is_static  (GooCanvasItem   *item,
+				       gboolean         is_static)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+
+  simple_data->is_static = is_static;
+}
+
+
 /**
  * goo_canvas_item_simple_check_style:
  * @item: a #GooCanvasItemSimple.
@@ -1258,7 +1282,7 @@
   if (entire_tree || simple->need_update)
     {
       /* Request a redraw of the existing bounds. */
-      goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+      goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
 
       cairo_save (cr);
       if (simple_data->transform)
@@ -1285,7 +1309,7 @@
       cairo_restore (cr);
 
       /* Request a redraw of the new bounds. */
-      goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+      goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
     }
 
   *bounds = simple->bounds;
@@ -1303,7 +1327,7 @@
   double x_offset, y_offset;
 
   /* Request a redraw of the existing bounds. */
-  goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+  goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
 
   cairo_save (cr);
   if (simple_data->transform)
@@ -1373,6 +1397,7 @@
 					   gdouble                y_offset)
 {
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
 
   /* Simple items can't resize at all, so we just adjust the bounds x & y
      positions here, and let the item be clipped if necessary. */
@@ -1382,7 +1407,7 @@
   simple->bounds.y2 += y_offset;
 
   /* Request a redraw of the new bounds. */
-  goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+  goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
 }
 
 
@@ -1568,6 +1593,8 @@
   iface->get_style          = goo_canvas_item_simple_get_style;
   iface->set_style          = goo_canvas_item_simple_set_style;
   iface->is_visible         = goo_canvas_item_simple_is_visible;
+  iface->get_is_static	    = goo_canvas_item_simple_get_is_static;
+  iface->set_is_static	    = goo_canvas_item_simple_set_is_static;
 
   iface->get_model          = goo_canvas_item_simple_get_model;
   iface->set_model          = goo_canvas_item_simple_set_model_internal;

Modified: trunk/src/goocanvasitemsimple.h
==============================================================================
--- trunk/src/goocanvasitemsimple.h	(original)
+++ trunk/src/goocanvasitemsimple.h	Fri Oct 31 16:50:17 2008
@@ -32,6 +32,7 @@
  * @own_style: if the item has its own style, rather than using its parent's.
  * @clip_fill_rule: the #cairo_fill_rule_t setting specifying the fill rule
  *  used for the clip path.
+ * @is_static: if the item is static.
  *
  * This is the data common to both the model and view classes.
  */
@@ -53,10 +54,11 @@
   guint can_focus                       : 1;
   guint own_style                       : 1;
   guint clip_fill_rule			: 4;
+  guint is_static			: 1;
 
   /*< private >*/
   /* We might use this in future for a cache setting - never/always/visible. */
-  guint cache_setting			: 3;
+  guint cache_setting			: 2;
   /* We might need this for tooltips in future. */
   guint has_tooltip			: 1;
 };

Modified: trunk/src/goocanvastable.c
==============================================================================
--- trunk/src/goocanvastable.c	(original)
+++ trunk/src/goocanvastable.c	Fri Oct 31 16:50:17 2008
@@ -1935,7 +1935,7 @@
   gint row, column, end;
 
   /* Request a redraw of the existing bounds */
-  goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+  goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
   
   /* We reset the bounds to 0, just in case we are hidden or aren't allocated
      any area. */
@@ -2158,7 +2158,7 @@
 
   cairo_restore (cr);
 
-  goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+  goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
 }
 
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]