[cairo-commit] goocanvas/demo demo-item.c,1.1,1.2

Damon Chaplin commit at pdx.freedesktop.org
Thu Nov 30 06:35:09 PST 2006


Committed by: damon

Update of /cvs/cairo/goocanvas/demo
In directory kemper:/tmp/cvs-serv20167/demo

Modified Files:
	demo-item.c 
Log Message:
2006-11-30  Damon Chaplin  <damon at gnome.org>

	* src/goocanvasitemsimple.h (struct _GooCanvasItemSimpleClass): added
	new update/paint/get_item_at methods that subclasses can override.
	If items use these methods GooCanvasItemSimple will perform all the
	standard stuff before passing control to them. This makes it much
	easier to create simple canvas items.

	* demo/demo-item.c: 
	* src/goocanvaspolyline.c: 
	* src/goocanvastext.c: 
	* src/goocanvasimage.c: use the above methods, so we can get rid of
	all the boilerplate code.



Index: demo-item.c
===================================================================
RCS file: /cvs/cairo/goocanvas/demo/demo-item.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- demo-item.c	29 Nov 2006 20:44:58 -0000	1.1
+++ demo-item.c	30 Nov 2006 14:35:05 -0000	1.2
@@ -8,26 +8,17 @@
 #include "goocanvas.h"
 #include "demo-item.h"
 
-static void canvas_item_interface_init    (GooCanvasItemIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (GooDemoItem, goo_demo_item,
-			 GOO_TYPE_CANVAS_ITEM_SIMPLE,
-			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
-						canvas_item_interface_init))
-
 
-static void
-goo_demo_item_class_init (GooDemoItemClass *klass)
-{
-  /* You would normally setup a few class functions here, and install any
-     object properties and signals. */
-}
+/* Use the GLib convenience macro to define the type. GooDemoItem is the
+   class struct, goo_demo_item is the function prefix, and our class is a
+   subclass of GOO_TYPE_CANVAS_ITEM_SIMPLE. */
+G_DEFINE_TYPE (GooDemoItem, goo_demo_item, GOO_TYPE_CANVAS_ITEM_SIMPLE)
 
 
+/* The standard object initialization function. */
 static void
 goo_demo_item_init (GooDemoItem *demo_item)
 {
-  /* Here's where you initialize the object. */
   demo_item->x = 0.0;
   demo_item->y = 0.0;
   demo_item->width = 0.0;
@@ -35,11 +26,9 @@
 }
 
 
-/*
- * NOTE: Quite a bit of the code below is the same in all the subclasses
- * of GooCanvasItemSimple, so I've marked the item-specific code.
- */
-
+/* The convenience function to create new items. This should start with a 
+   parent argument and end with a variable list of object properties to fit
+   in with the standard canvas items. */
 GooCanvasItem*
 goo_demo_item_new (GooCanvasItem      *parent,
 		   gdouble             x,
@@ -53,8 +42,6 @@
   const char *first_property;
   va_list var_args;
 
-  /* ===== START OF ITEM-SPECIFIC CODE ===== */
-
   item = g_object_new (GOO_TYPE_DEMO_ITEM, NULL);
 
   demo_item = (GooDemoItem*) item;
@@ -64,9 +51,6 @@
   demo_item->height = height;
 
   va_start (var_args, height);
-
-  /* ===== END OF ITEM-SPECIFIC CODE ===== */
-
   first_property = va_arg (var_args, char*);
   if (first_property)
     g_object_set_valist ((GObject*) item, first_property, var_args);
@@ -82,146 +66,77 @@
 }
 
 
-static GooCanvasItem*
-goo_demo_item_get_item_at (GooCanvasItem  *item,
-			   gdouble         x,
-			   gdouble         y,
-			   cairo_t        *cr,
-			   gboolean        is_pointer_event,
-			   gboolean        parent_visible)
-{
-  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
-  GooCanvasItemSimpleData *simple_data = simple->simple_data;
-  GooDemoItem *demo_item = (GooDemoItem*) item;
-  GooCanvasItem *found_item = item;
-  double user_x = x, user_y = y;
-
-  if (simple->need_update)
-    goo_canvas_item_ensure_updated (item);
-
-  /* Check if the item should receive events. */
-  if (is_pointer_event)
-    {
-      if (simple_data->pointer_events == GOO_CANVAS_EVENTS_NONE)
-	return NULL;
-      if (simple_data->pointer_events & GOO_CANVAS_EVENTS_VISIBLE_MASK
-	  && (!parent_visible
-	      || simple_data->visibility == GOO_CANVAS_ITEM_INVISIBLE
-	      || (simple_data->visibility == GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD
-		  && simple->canvas->scale < simple_data->visibility_threshold)))
-	return NULL;
-    }
-
-  cairo_save (cr);
-
-  if (simple_data->transform)
-    cairo_transform (cr, simple_data->transform);
-
-  cairo_device_to_user (cr, &user_x, &user_y);
-
-  /* ===== START OF ITEM-SPECIFIC CODE ===== */
-
-  /* Check if the given point is in the item. */
-  if (user_x < demo_item->x || (user_x > demo_item->x + demo_item->width)
-      || user_y < demo_item->y || (user_y > demo_item->y + demo_item->height))
-    found_item = NULL;
-
-  /* ===== END OF ITEM-SPECIFIC CODE ===== */
-
-  cairo_restore (cr);
-
-  return found_item;
-}
-
-
+/* The update method. This is called when the canvas is initially shown and
+   also whenever the object is updated and needs to change its size and/or
+   shape. It should calculate its new bounds, storing them in simple->bounds,
+   and it should convert these to device coordinates. */
 static void
-goo_demo_item_update  (GooCanvasItem      *item,
-		       gboolean            entire_tree,
-		       cairo_t            *cr,
-		       GooCanvasBounds    *bounds)
+goo_demo_item_update  (GooCanvasItemSimple *simple,
+		       cairo_t             *cr)
 {
-  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
-  GooCanvasItemSimpleData *simple_data = simple->simple_data;
-  GooDemoItem *demo_item = (GooDemoItem*) item;
-
-  if (entire_tree || simple->need_update)
-    {
-      simple->need_update = FALSE;
-
-      goo_canvas_item_simple_check_style (simple);
-
-      cairo_save (cr);
-      if (simple_data->transform)
-	cairo_transform (cr, simple_data->transform);
-
-      /* Request a redraw of the existing bounds. */
-      goo_canvas_request_redraw (simple->canvas, &simple->bounds);
-
-      /* ===== START OF ITEM-SPECIFIC CODE ===== */
-
-      /* Compute the new bounds, converting to device coordinates. */
-      simple->bounds.x1 = demo_item->x;
-      simple->bounds.y1 = demo_item->y;
-      simple->bounds.x2 = demo_item->x + demo_item->width;
-      simple->bounds.y2 = demo_item->y + demo_item->height;
-
-      goo_canvas_item_simple_user_bounds_to_device (simple, cr,
-						    &simple->bounds);
-
-      /* ===== END OF ITEM-SPECIFIC CODE ===== */
-
-      /* Request a redraw of the new bounds. */
-      goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+  GooDemoItem *demo_item = (GooDemoItem*) simple;
 
-      cairo_restore (cr);
-    }
+  /* Compute the new bounds. */
+  simple->bounds.x1 = demo_item->x;
+  simple->bounds.y1 = demo_item->y;
+  simple->bounds.x2 = demo_item->x + demo_item->width;
+  simple->bounds.y2 = demo_item->y + demo_item->height;
 
-  *bounds = simple->bounds;
+  /* Convert to device coordinates. */
+  goo_canvas_item_simple_user_bounds_to_device (simple, cr, &simple->bounds);
 }
 
 
+/* The paint method. This should draw the item on the given cairo_t, using
+   the item's own coordinate space. */
 static void
-goo_demo_item_paint (GooCanvasItem     *item,
-		     cairo_t           *cr,
-		     GooCanvasBounds   *bounds,
-		     gdouble            scale)
+goo_demo_item_paint (GooCanvasItemSimple *simple,
+		     cairo_t             *cr,
+		     GooCanvasBounds     *bounds)
 {
-  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
-  GooCanvasItemSimpleData *simple_data = simple->simple_data;
-  GooDemoItem *demo_item = (GooDemoItem*) item;
-
-  /* Check if the item should be visible. */
-  if (simple_data->visibility == GOO_CANVAS_ITEM_INVISIBLE
-      || (simple_data->visibility == GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD
-	  && scale < simple_data->visibility_threshold))
-    return;
-
-  cairo_save (cr);
-  if (simple_data->transform)
-    cairo_transform (cr, simple_data->transform);
-
-  /* ===== START OF ITEM-SPECIFIC CODE ===== */
+  GooDemoItem *demo_item = (GooDemoItem*) simple;
 
-  /* Draw the item here. */
   cairo_move_to (cr, demo_item->x, demo_item->y);
   cairo_line_to (cr, demo_item->x, demo_item->y + demo_item->height);
   cairo_line_to (cr, demo_item->x + demo_item->width,
 		 demo_item->y + demo_item->height);
   cairo_line_to (cr, demo_item->x + demo_item->width, demo_item->y);
   cairo_close_path (cr);
-  goo_canvas_style_set_fill_options (simple_data->style, cr);
+  goo_canvas_style_set_fill_options (simple->simple_data->style, cr);
   cairo_fill (cr);
+}
 
-  /* ===== END OF ITEM-SPECIFIC CODE ===== */
 
-  cairo_restore (cr);
+/* Hit detection. This should check if the given coordinate (in the item's
+   coordinate space) is within the item. If it is it should return the item,
+   otherwise it should return NULL. */
+static GooCanvasItem*
+goo_demo_item_get_item_at (GooCanvasItemSimple *simple,
+			   gdouble              x,
+			   gdouble              y,
+			   cairo_t             *cr,
+			   gboolean             is_pointer_event)
+{
+  GooDemoItem *demo_item = (GooDemoItem*) simple;
+
+  if (x < demo_item->x || (x > demo_item->x + demo_item->width)
+      || y < demo_item->y || (y > demo_item->y + demo_item->height))
+    return NULL;
+
+  return (GooCanvasItem*) simple;
 }
 
 
+/* The class initialization function. Here we set the class' update(), paint()
+   and get_item_at() methods. */
 static void
-canvas_item_interface_init (GooCanvasItemIface *iface)
+goo_demo_item_class_init (GooDemoItemClass *klass)
 {
-  iface->get_item_at = goo_demo_item_get_item_at;
-  iface->update      = goo_demo_item_update;
-  iface->paint       = goo_demo_item_paint;
+  GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) klass;
+
+  simple_class->update        = goo_demo_item_update;
+  simple_class->paint         = goo_demo_item_paint;
+  simple_class->get_item_at   = goo_demo_item_get_item_at;
 }
+
+



More information about the cairo-commit mailing list