[cairo-commit] goocanvas/src Makefile.am, 1.10, 1.11 goocanvas.h, 1.2, 1.3 goocanvasatk.c, 1.6, 1.7 goocanvasatk.h, 1.1, 1.2 goocanvasellipse.c, 1.6, 1.7 goocanvasellipse.h, 1.2, 1.3 goocanvasgroup.c, 1.13, 1.14 goocanvasgroup.h, 1.8, 1.9 goocanvasimage.c, 1.7, 1.8 goocanvasimage.h, 1.2, 1.3 goocanvasimageview.c, 1.16, NONE goocanvasimageview.h, 1.4, NONE goocanvasitem.c, 1.10, 1.11 goocanvasitem.h, 1.7, 1.8 goocanvasitemsimple.c, 1.14, 1.15 goocanvasitemsimple.h, 1.10, 1.11 goocanvasitemview.c, 1.14, NONE goocanvasitemview.h, 1.12, NONE goocanvasitemviewsimple.c, 1.13, NONE goocanvasitemviewsimple.h, 1.5, NONE goocanvasmodel.c, 1.3, NONE goocanvasmodel.h, 1.2, NONE goocanvasmodelsimple.c, 1.5, NONE goocanvasmodelsimple.h, 1.2, NONE goocanvaspath.c, 1.7, 1.8 goocanvaspath.h, 1.5, 1.6 goocanvaspathview.c, 1.11, NONE goocanvaspathview.h, 1.4, NONE goocanvaspolyline.c, 1.6, 1.7 goocanvaspolyline.h, 1.4, 1.5 goocanvaspolylineview.c, 1.19, NONE goocanvaspolylineview.h, 1.5, NONE goocanvasrect.c, 1.6, 1.7 goocanvasrect.h, 1.2, 1.3 goocanvasrectview.c, 1.12, NONE goocanvasrectview.h, 1.4, NONE goocanvastext.c, 1.6, 1.7 goocanvastext.h, 1.3, 1.4 goocanvastextview.c, 1.19, NONE goocanvastextview.h, 1.5, NONE goocanvasview.c, 1.32, NONE goocanvasview.h, 1.11, NONE

Damon Chaplin commit at pdx.freedesktop.org
Wed Nov 29 10:40:57 PST 2006


Committed by: damon

Update of /cvs/cairo/goocanvas/src
In directory kemper:/tmp/cvs-serv14136/src

Modified Files:
	Makefile.am goocanvas.h goocanvasatk.c goocanvasatk.h 
	goocanvasellipse.c goocanvasellipse.h goocanvasgroup.c 
	goocanvasgroup.h goocanvasimage.c goocanvasimage.h 
	goocanvasitem.c goocanvasitem.h goocanvasitemsimple.c 
	goocanvasitemsimple.h goocanvaspath.c goocanvaspath.h 
	goocanvaspolyline.c goocanvaspolyline.h goocanvasrect.c 
	goocanvasrect.h goocanvastext.c goocanvastext.h 
Removed Files:
	goocanvasimageview.c goocanvasimageview.h goocanvasitemview.c 
	goocanvasitemview.h goocanvasitemviewsimple.c 
	goocanvasitemviewsimple.h goocanvasmodel.c goocanvasmodel.h 
	goocanvasmodelsimple.c goocanvasmodelsimple.h 
	goocanvaspathview.c goocanvaspathview.h 
	goocanvaspolylineview.c goocanvaspolylineview.h 
	goocanvasrectview.c goocanvasrectview.h goocanvastextview.c 
	goocanvastextview.h goocanvasview.c goocanvasview.h 
Log Message:
new optional model rewrite


Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/goocanvas/src/Makefile.am,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- Makefile.am	29 Nov 2006 16:35:38 -0000	1.10
+++ Makefile.am	29 Nov 2006 18:40:53 -0000	1.11
@@ -15,69 +15,52 @@
 
 libgoocanvasincludedir = $(includedir)/goocanvas-1.0
 
-libgoocanvas_public_headers =			\
-	goocanvasellipse.h			\
-	goocanvasellipseview.h			\
-	goocanvasgroup.h			\
-	goocanvasgroupview.h			\
-	goocanvasimage.h			\
-	goocanvasimageview.h			\
-	goocanvasitem.h				\
-	goocanvasitemsimple.h			\
-	goocanvasitemview.h			\
-	goocanvasitemviewsimple.h		\
-	goocanvasmodel.h			\
-	goocanvasmodelsimple.h			\
-	goocanvaspolyline.h			\
-	goocanvaspolylineview.h			\
-	goocanvaspath.h				\
-	goocanvaspathview.h			\
-	goocanvasrect.h				\
-	goocanvasrectview.h			\
-	goocanvastext.h				\
-	goocanvastextview.h			\
-	goocanvasutils.h			\
-	goocanvasview.h				\
+libgoocanvas_public_headers =		\
+	goocanvasellipse.h		\
+	goocanvasgroup.h		\
+	goocanvasimage.h		\
+	goocanvasitem.h			\
+	goocanvasitemmodel.h		\
+	goocanvasitemsimple.h		\
+	goocanvaspolyline.h		\
+	goocanvaspath.h			\
+	goocanvasrect.h			\
+	goocanvasstyle.h		\
+	goocanvastext.h			\
+	goocanvasutils.h		\
+	goocanvaswidget.h		\
 	goocanvas.h
 
-libgoocanvas_la_SOURCES =			\
-	goocanvasmarshal.list			\
-	goocanvasatk.h				\
-	goocanvasatk.c				\
-	goocanvasellipse.c			\
-	goocanvasellipseview.c			\
-	goocanvasenumtypes.c			\
-	goocanvasgroup.c			\
-	goocanvasgroupview.c			\
-	goocanvasimage.c			\
-	goocanvasimageview.c			\
-	goocanvasitem.c				\
-	goocanvasitemsimple.c			\
-	goocanvasitemview.c			\
-	goocanvasitemviewsimple.c		\
-	goocanvasmodel.c			\
-	goocanvasmodelsimple.c			\
-	goocanvaspolyline.c			\
-	goocanvaspolylineview.c			\
-	goocanvaspath.c				\
-	goocanvaspathview.c			\
-	goocanvasprivate.h			\
-	goocanvasrect.c				\
-	goocanvasrectview.c			\
-	goocanvastext.c				\
-	goocanvastextview.c			\
-	goocanvasutils.c			\
-	goocanvasview.c 
+libgoocanvas_la_SOURCES =		\
+	goocanvasmarshal.list		\
+	goocanvasatk.h			\
+	goocanvasatk.c			\
+	goocanvasellipse.c		\
+	goocanvasenumtypes.c		\
+	goocanvasgroup.c		\
+	goocanvasimage.c		\
+	goocanvasitem.c			\
+	goocanvasitemmodel.c		\
+	goocanvasitemsimple.c		\
+	goocanvaspolyline.c		\
+	goocanvaspath.c			\
+	goocanvasprivate.h		\
+	goocanvasrect.c			\
+	goocanvasstyle.c		\
+	goocanvastext.c			\
+	goocanvasutils.c		\
+	goocanvaswidget.c		\
+	goocanvas.c 
 
-libgoocanvas_built_headers =			\
-	goocanvasenumtypes.h			\
+libgoocanvas_built_headers =		\
+	goocanvasenumtypes.h		\
 	goocanvasmarshal.h
 
-libgoocanvas_built_sources =			\
+libgoocanvas_built_sources =		\
 	goocanvasenumtypes.c
 
-libgoocanvasinclude_HEADERS =			\
-	$(libgoocanvas_public_headers)		\
+libgoocanvasinclude_HEADERS =		\
+	$(libgoocanvas_public_headers)	\
 	$(libgoocanvas_built_headers)
 
 
@@ -118,3 +101,6 @@
 non-intermediate: goocanvasmarshal.c
 
 CLEANFILES = $(libgoocanvas_built_headers) $(libgoocanvas_built_sources)
+
+# Add this to the dist for use on Windows where glib-genmarshal may not work.
+EXTRA_DIST = goocanvasmarshal.c

Index: goocanvas.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvas.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- goocanvas.h	12 Oct 2006 12:53:47 -0000	1.2
+++ goocanvas.h	29 Nov 2006 18:40:53 -0000	1.3
@@ -1,33 +1,254 @@
 /*
- * GooCanvas. Copyright (C) 2005-6 Damon Chaplin.
+ * GooCanvas. Copyright (C) 2005 Damon Chaplin.
  * Released under the GNU LGPL license. See COPYING for details.
  *
- * goocanvas.h - includes all canvas header files.
+ * goocanvas.h - the main canvas widget.
  */
 #ifndef __GOO_CANVAS_H__
 #define __GOO_CANVAS_H__
 
-#include <goocanvasellipse.h>
-#include <goocanvasellipseview.h>
+#include <gtk/gtk.h>
 #include <goocanvasenumtypes.h>
+#include <goocanvasellipse.h>
 #include <goocanvasgroup.h>
-#include <goocanvasgroupview.h>
 #include <goocanvasimage.h>
-#include <goocanvasimageview.h>
-#include <goocanvasitem.h>
-#include <goocanvasitemsimple.h>
-#include <goocanvasitemview.h>
-#include <goocanvasmodel.h>
-#include <goocanvasmodelsimple.h>
-#include <goocanvaspolyline.h>
-#include <goocanvaspolylineview.h>
 #include <goocanvaspath.h>
-#include <goocanvaspathview.h>
+#include <goocanvaspolyline.h>
 #include <goocanvasrect.h>
-#include <goocanvasrectview.h>
 #include <goocanvastext.h>
-#include <goocanvastextview.h>
-#include <goocanvasutils.h>
-#include <goocanvasview.h>
+#include <goocanvaswidget.h>
+
+G_BEGIN_DECLS
+
+
+#define GOO_TYPE_CANVAS            (goo_canvas_get_type ())
+#define GOO_CANVAS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS, GooCanvas))
+#define GOO_CANVAS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS, GooCanvasClass))
+#define GOO_IS_CANVAS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS))
+#define GOO_IS_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS))
+#define GOO_CANVAS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS, GooCanvasClass))
+
+
+typedef struct _GooCanvasClass  GooCanvasClass;
+
+/**
+ * GooCanvas
+ *
+ * The #GooCanvas-struct struct contains private data only.
+ */
+struct _GooCanvas
+{
+  GtkContainer container;
+
+  /* The model for the root item, in model/view mode. */
+  GooCanvasItemModel *root_item_model;
+
+  /* The root canvas item. */
+  GooCanvasItem *root_item;
+
+  /* The bounds of the canvas, in canvas units (not pixels). */
+  GooCanvasBounds bounds;
+
+  /* The scale/zoom factor of the canvas, in pixels per device unit. */
+  gdouble scale;
+
+  /* Where the canvas is anchored (where it is displayed when it is smaller
+     than the entire window). */
+  GtkAnchorType anchor;
+
+  /* Idle handler ID, for processing updates. */
+  guint idle_id;
+
+  /* This is TRUE if some item in the canvas needs an update. */
+  guint need_update : 1;
+
+  /* The item that the mouse is over. */
+  GooCanvasItem *pointer_item;
+
+  /* The item that has the pointer grab, or NULL. */
+  GooCanvasItem *pointer_grab_item;
+
+  /* This is the item that the grab was started from. When the grab ends
+     we synthesize enter/leave notify events from this item. */
+  GooCanvasItem *pointer_grab_initial_item;
+
+  /* This is the mouse button that started an implicit pointer grab.
+     When the same button is released the implicit grab ends. */
+  guint pointer_grab_button;
+
+  /* The item that has the keyboard focus, or NULL. */
+  GooCanvasItem *focused_item;
+
+  /* The item that has the keyboard grab, or NULL. */
+  GooCanvasItem *keyboard_grab_item;
+
+  /* The synthesized event used for sending enter-notify and leave-notify
+     events to items. */
+  GdkEventCrossing crossing_event;
+
+  /* The main canvas window, which gets scrolled around. */
+  GdkWindow *canvas_window;
+
+  /* The offsets of the canvas within the canvas window, in pixels. These are
+     used when the canvas is smaller than the window size and the anchor is not
+     NORTH_WEST. */
+  gint canvas_x_offset;
+  gint canvas_y_offset;
+
+  /* The adjustments used for scrolling. */
+  GtkAdjustment *hadjustment;
+  GtkAdjustment *vadjustment;
+
+  /* Freezes any movement of the canvas window, until thawed. This is used
+     when we need to set both adjustments and don't want it to scroll twice. */
+  gint freeze_count;
+
+  /* A window temporarily mapped above the canvas to stop X from scrolling
+     the contents unnecessarily (i.e. when we zoom in/out). */
+  GdkWindow *tmp_window;
+
+  /* A hash table mapping canvas item models to canvas items. */
+  GHashTable *model_to_item;
+
+  /* The units of the canvas, which applies to all item coords. */
+  GtkUnit units;
+
+  /* The horizontal and vertical resolution of the display, in dots per inch.
+     This is only needed when units other than pixels are used. */
+  gdouble resolution_x, resolution_y;
+
+  /* The multiplers to convert from device units to pixels, taking into account
+     the canvas scale, the units setting and the display resolution. */
+  gdouble scale_x, scale_y;
+
+  /* The list of child widgets (using GooCanvasWidget items). */
+  GList *widget_items;
+};
+
+struct _GooCanvasClass
+{
+  GtkContainerClass parent_class;
+
+  void		 (* set_scroll_adjustments) (GooCanvas          *canvas,
+					     GtkAdjustment      *hadjustment,
+					     GtkAdjustment      *vadjustment);
+
+  /* Virtual methods. */
+  GooCanvasItem* (* create_item)	    (GooCanvas          *canvas,
+					     GooCanvasItemModel *model);
+
+  /* Signals. */
+  void           (* item_created)	    (GooCanvas          *canvas,
+					     GooCanvasItem      *item,
+					     GooCanvasItemModel *model);
+};
+
+
+GType           goo_canvas_get_type	    (void) G_GNUC_CONST;
+GtkWidget*      goo_canvas_new		    (void);
+
+GooCanvasItem*  goo_canvas_get_root_item    (GooCanvas		*canvas);
+void            goo_canvas_set_root_item    (GooCanvas		*canvas,
+					     GooCanvasItem      *item);
+
+GooCanvasItemModel* goo_canvas_get_root_item_model (GooCanvas	       *canvas);
+void                goo_canvas_set_root_item_model (GooCanvas	       *canvas,
+						    GooCanvasItemModel *model);
+
+GooCanvasItem*  goo_canvas_get_item	    (GooCanvas		*canvas,
+					     GooCanvasItemModel *model);
+GooCanvasItem*  goo_canvas_get_item_at	    (GooCanvas		*canvas,
+					     gdouble             x,
+					     gdouble             y,
+					     gboolean            is_pointer_event);
+
+gdouble         goo_canvas_get_scale	    (GooCanvas		*canvas);
+void            goo_canvas_set_scale	    (GooCanvas		*canvas,
+					     gdouble             pixels_per_unit);
+
+void            goo_canvas_get_bounds	    (GooCanvas		*canvas,
+					     gdouble            *left,
+					     gdouble            *top,
+					     gdouble            *right,
+					     gdouble            *bottom);
+void            goo_canvas_set_bounds	    (GooCanvas		*canvas,
+					     gdouble             left,
+					     gdouble             top,
+					     gdouble             right,
+					     gdouble             bottom);
+
+void            goo_canvas_scroll_to	    (GooCanvas		*canvas,
+					     gdouble             left,
+					     gdouble             top);
+
+void            goo_canvas_grab_focus	    (GooCanvas		*canvas,
+					     GooCanvasItem	*item);
+
+void            goo_canvas_render	    (GooCanvas		*canvas,
+					     cairo_t            *cr,
+					     GooCanvasBounds    *bounds,
+					     gdouble             scale);
+
+/*
+ * Coordinate conversion.
+ */
+void		goo_canvas_convert_to_pixels	   (GooCanvas       *canvas,
+						    gdouble         *x,
+						    gdouble         *y);
+void		goo_canvas_convert_from_pixels	   (GooCanvas       *canvas,
+						    gdouble         *x,
+						    gdouble         *y);
+
+void		goo_canvas_convert_to_item_space   (GooCanvas	    *canvas,
+						    GooCanvasItem   *item,
+						    gdouble         *x,
+						    gdouble         *y);
+void		goo_canvas_convert_from_item_space (GooCanvas       *canvas,
+						    GooCanvasItem   *item,
+						    gdouble         *x,
+						    gdouble         *y);
+
+
+/*
+ * Pointer/keyboard grabbing & ungrabbing.
+ */
+GdkGrabStatus	goo_canvas_pointer_grab	    (GooCanvas		*canvas,
+					     GooCanvasItem	*item,
+					     GdkEventMask        event_mask,
+					     GdkCursor		*cursor,
+					     guint32             time);
+void		goo_canvas_pointer_ungrab   (GooCanvas		*canvas,
+					     GooCanvasItem	*item,
+					     guint32             time);
+GdkGrabStatus	goo_canvas_keyboard_grab    (GooCanvas		*canvas,
+					     GooCanvasItem	*item,
+					     gboolean            owner_events,
+					     guint32             time);
+void		goo_canvas_keyboard_ungrab  (GooCanvas		*canvas,
+					     GooCanvasItem	*item,
+					     guint32             time);
+
+
+/*
+ * Internal functions, mainly for canvas subclasses and item implementations.
+ */
+GooCanvasItem*	goo_canvas_create_item	    (GooCanvas          *canvas,
+					     GooCanvasItemModel *model);
+void		goo_canvas_unregister_item  (GooCanvas		*canvas,
+					     GooCanvasItemModel *model);
+void		goo_canvas_update	    (GooCanvas		*canvas);
+void		goo_canvas_request_update   (GooCanvas		*canvas);
+void		goo_canvas_request_redraw   (GooCanvas		*canvas,
+					     GooCanvasBounds	*bounds);
+gdouble         goo_canvas_get_default_line_width (GooCanvas    *canvas);
+
+
+void            goo_canvas_register_widget_item   (GooCanvas          *canvas,
+						   GooCanvasWidget    *witem);
+void            goo_canvas_unregister_widget_item (GooCanvas          *canvas,
+						   GooCanvasWidget    *witem);
+
+
+G_END_DECLS
 
 #endif /* __GOO_CANVAS_H__ */

Index: goocanvasatk.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasatk.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- goocanvasatk.c	19 Jul 2006 15:49:47 -0000	1.6
+++ goocanvasatk.c	29 Nov 2006 18:40:53 -0000	1.7
@@ -14,51 +14,51 @@
 
 
 /*
- * GooCanvasItemViewAccessible.
+ * GooCanvasItemAccessible.
  */
 
-typedef AtkGObjectAccessible      GooCanvasItemViewAccessible;
-typedef AtkGObjectAccessibleClass GooCanvasItemViewAccessibleClass;
+typedef AtkGObjectAccessible      GooCanvasItemAccessible;
+typedef AtkGObjectAccessibleClass GooCanvasItemAccessibleClass;
 
-#define GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), goo_canvas_item_view_accessible_get_type ()))
+#define GOO_IS_CANVAS_ITEM_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), goo_canvas_item_accessible_get_type ()))
 
-static void goo_canvas_item_view_accessible_component_interface_init (AtkComponentIface *iface);
-static gint goo_canvas_item_view_accessible_get_index_in_parent (AtkObject *accessible);
+static void goo_canvas_item_accessible_component_interface_init (AtkComponentIface *iface);
+static gint goo_canvas_item_accessible_get_index_in_parent (AtkObject *accessible);
 
-G_DEFINE_TYPE_WITH_CODE (GooCanvasItemViewAccessible,
-			 goo_canvas_item_view_accessible,
+G_DEFINE_TYPE_WITH_CODE (GooCanvasItemAccessible,
+			 goo_canvas_item_accessible,
 			 ATK_TYPE_GOBJECT_ACCESSIBLE,
-			 G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, goo_canvas_item_view_accessible_component_interface_init))
+			 G_IMPLEMENT_INTERFACE (ATK_TYPE_COMPONENT, goo_canvas_item_accessible_component_interface_init))
 
 
-/* Returns the extents of the item view, in pixels relative to the main
+/* Returns the extents of the item, in pixels relative to the main
    canvas window. */
 static void
-goo_canvas_item_view_accessible_get_item_extents (GooCanvasItemView *view,
-						  GdkRectangle      *rect)
+goo_canvas_item_accessible_get_item_extents (GooCanvasItem *item,
+					     GdkRectangle  *rect)
 {
-  GooCanvasView *canvas_view;
+  GooCanvas *canvas;
   GooCanvasBounds bounds;
 
-  canvas_view = goo_canvas_item_view_get_canvas_view (view);
-  if (!canvas_view)
+  canvas = goo_canvas_item_get_canvas (item);
+  if (!canvas)
     {
       rect->x = rect->y = rect->width = rect->height = 0;
       return;
     }
 
   /* Get the bounds in device units. */
-  goo_canvas_item_view_get_bounds (view, &bounds);
+  goo_canvas_item_get_bounds (item, &bounds);
 
   /* Convert to pixels within the entire canvas. */
-  goo_canvas_view_convert_to_pixels (canvas_view, &bounds.x1, &bounds.y1);
-  goo_canvas_view_convert_to_pixels (canvas_view, &bounds.x2, &bounds.y2);
+  goo_canvas_convert_to_pixels (canvas, &bounds.x1, &bounds.y1);
+  goo_canvas_convert_to_pixels (canvas, &bounds.x2, &bounds.y2);
 
   /* Convert to pixels within the visible window. */
-  bounds.x1 -= canvas_view->hadjustment->value;
-  bounds.y1 -= canvas_view->vadjustment->value;
-  bounds.x2 -= canvas_view->hadjustment->value;
-  bounds.y2 -= canvas_view->vadjustment->value;
+  bounds.x1 -= canvas->hadjustment->value;
+  bounds.y1 -= canvas->vadjustment->value;
+  bounds.x2 -= canvas->hadjustment->value;
+  bounds.y2 -= canvas->vadjustment->value;
 
   /* Round up or down to integers. */
   rect->x = floor (bounds.x1);
@@ -71,12 +71,12 @@
 /* This returns TRUE if the given rectangle intersects the canvas window.
    The rectangle should be in pixels relative to the main canvas window. */
 static gboolean
-goo_canvas_item_view_accessible_is_item_in_window (GooCanvasItemView *view,
-						   GdkRectangle      *rect)
+goo_canvas_item_accessible_is_item_in_window (GooCanvasItem *item,
+					      GdkRectangle  *rect)
 {
   GtkWidget *widget;
 
-  widget = (GtkWidget*) goo_canvas_item_view_get_canvas_view (view);
+  widget = (GtkWidget*) goo_canvas_item_get_canvas (item);
   if (!widget)
     return FALSE;
 
@@ -89,33 +89,33 @@
 
 
 static gboolean
-goo_canvas_item_view_accessible_is_item_on_screen (GooCanvasItemView *view)
+goo_canvas_item_accessible_is_item_on_screen (GooCanvasItem *item)
 {
   GdkRectangle rect;
 
-  goo_canvas_item_view_accessible_get_item_extents (view, &rect);
-  return goo_canvas_item_view_accessible_is_item_in_window (view, &rect);
+  goo_canvas_item_accessible_get_item_extents (item, &rect);
+  return goo_canvas_item_accessible_is_item_in_window (item, &rect);
 }
 
 
 
 static void
-goo_canvas_item_view_accessible_get_extents (AtkComponent *component,
-					     gint         *x,
-					     gint         *y,
-					     gint         *width,
-					     gint         *height,
-					     AtkCoordType coord_type)
+goo_canvas_item_accessible_get_extents (AtkComponent *component,
+					gint         *x,
+					gint         *y,
+					gint         *width,
+					gint         *height,
+					AtkCoordType  coord_type)
 {
-  GooCanvasItemView *item_view;
-  GooCanvasView *canvas_view;
+  GooCanvasItem *item;
+  GooCanvas *canvas;
   GObject *object;
   gint window_x, window_y;
   gint toplevel_x, toplevel_y;
   GdkRectangle rect;
   GdkWindow *window;
 
-  g_return_if_fail (GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE (component));
+  g_return_if_fail (GOO_IS_CANVAS_ITEM_ACCESSIBLE (component));
 
   *x = *y = G_MININT;
 
@@ -123,27 +123,27 @@
   if (!object)
     return;
 
-  item_view = GOO_CANVAS_ITEM_VIEW (object);
+  item = GOO_CANVAS_ITEM (object);
 
-  canvas_view = goo_canvas_item_view_get_canvas_view (item_view);
-  if (!canvas_view || !GTK_WIDGET (canvas_view)->window)
+  canvas = goo_canvas_item_get_canvas (item);
+  if (!canvas || !GTK_WIDGET (canvas)->window)
     return;
 
-  goo_canvas_item_view_accessible_get_item_extents (item_view, &rect);
+  goo_canvas_item_accessible_get_item_extents (item, &rect);
   *width = rect.width;
   *height = rect.height;
 
-  if (!goo_canvas_item_view_accessible_is_item_in_window (item_view, &rect))
+  if (!goo_canvas_item_accessible_is_item_in_window (item, &rect))
     return;
 
-  gdk_window_get_origin (GTK_WIDGET (canvas_view)->window,
+  gdk_window_get_origin (GTK_WIDGET (canvas)->window,
 			 &window_x, &window_y);
   *x = rect.x + window_x;
   *y = rect.y + window_y;
 
   if (coord_type == ATK_XY_WINDOW)
     {
-      window = gdk_window_get_toplevel (GTK_WIDGET (canvas_view)->window);
+      window = gdk_window_get_toplevel (GTK_WIDGET (canvas)->window);
       gdk_window_get_origin (window, &toplevel_x, &toplevel_y);
       *x -= toplevel_x;
       *y -= toplevel_y;
@@ -152,23 +152,23 @@
 
 
 static gint
-goo_canvas_item_view_accessible_get_mdi_zorder (AtkComponent *component)
+goo_canvas_item_accessible_get_mdi_zorder (AtkComponent *component)
 {
-  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE (component), -1);
+  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_ACCESSIBLE (component), -1);
 
-  return goo_canvas_item_view_accessible_get_index_in_parent (ATK_OBJECT (component));
+  return goo_canvas_item_accessible_get_index_in_parent (ATK_OBJECT (component));
 }
 
 
 static guint
-goo_canvas_item_view_accessible_add_focus_handler (AtkComponent    *component,
-						   AtkFocusHandler  handler)
+goo_canvas_item_accessible_add_focus_handler (AtkComponent    *component,
+					      AtkFocusHandler  handler)
 {
   GSignalMatchType match_type;
   GClosure *closure;
   guint signal_id;
 
-  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE (component), 0);
+  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_ACCESSIBLE (component), 0);
 
   match_type = G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_FUNC;
   signal_id = g_signal_lookup ("focus-event", ATK_TYPE_OBJECT);
@@ -185,38 +185,38 @@
 
 
 static void
-goo_canvas_item_view_accessible_remove_focus_handler (AtkComponent *component,
-						      guint         handler_id)
+goo_canvas_item_accessible_remove_focus_handler (AtkComponent *component,
+						 guint         handler_id)
 {
-  g_return_if_fail (GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE (component));
+  g_return_if_fail (GOO_IS_CANVAS_ITEM_ACCESSIBLE (component));
 
   g_signal_handler_disconnect (ATK_OBJECT (component), handler_id);
 }
 
 
 static gboolean
-goo_canvas_item_view_accessible_grab_focus (AtkComponent    *component)
+goo_canvas_item_accessible_grab_focus (AtkComponent    *component)
 {
-  GooCanvasItemView *item_view;
-  GooCanvasView *canvas_view;
+  GooCanvasItem *item;
+  GooCanvas *canvas;
   GtkWidget *toplevel;
   GObject *object;
 
-  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE (component), FALSE);
+  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_ACCESSIBLE (component), FALSE);
 
   object = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (component));
   if (!object)
     return FALSE;
 
-  item_view = GOO_CANVAS_ITEM_VIEW (object);
+  item = GOO_CANVAS_ITEM (object);
 
-  canvas_view = goo_canvas_item_view_get_canvas_view (item_view);
-  if (!canvas_view)
+  canvas = goo_canvas_item_get_canvas (item);
+  if (!canvas)
     return FALSE;
 
-  goo_canvas_view_grab_focus (canvas_view, item_view);
+  goo_canvas_grab_focus (canvas, item);
 
-  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (canvas_view));
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (canvas));
   if (GTK_WIDGET_TOPLEVEL (toplevel))
     gtk_window_present (GTK_WINDOW (toplevel));
 
@@ -225,22 +225,24 @@
 
 
 static void
-goo_canvas_item_view_accessible_component_interface_init (AtkComponentIface *iface)
+goo_canvas_item_accessible_component_interface_init (AtkComponentIface *iface)
 {
-  iface->get_extents          = goo_canvas_item_view_accessible_get_extents;
-  iface->get_mdi_zorder       = goo_canvas_item_view_accessible_get_mdi_zorder;
-  iface->add_focus_handler    = goo_canvas_item_view_accessible_add_focus_handler;
-  iface->remove_focus_handler = goo_canvas_item_view_accessible_remove_focus_handler;
-  iface->grab_focus           = goo_canvas_item_view_accessible_grab_focus;
+  iface->get_extents          = goo_canvas_item_accessible_get_extents;
+  iface->get_mdi_zorder       = goo_canvas_item_accessible_get_mdi_zorder;
+  iface->add_focus_handler    = goo_canvas_item_accessible_add_focus_handler;
+  iface->remove_focus_handler = goo_canvas_item_accessible_remove_focus_handler;
+  iface->grab_focus           = goo_canvas_item_accessible_grab_focus;
 }
 
 
 static void
-goo_canvas_item_view_accessible_initialize (AtkObject *object,
-					    gpointer   data)
+goo_canvas_item_accessible_initialize (AtkObject *object,
+				       gpointer   data)
 {
-  if (ATK_OBJECT_CLASS (goo_canvas_item_view_accessible_parent_class)->initialize)
-    ATK_OBJECT_CLASS (goo_canvas_item_view_accessible_parent_class)->initialize (object, data);
+  if (ATK_OBJECT_CLASS (goo_canvas_item_accessible_parent_class)->initialize)
+    ATK_OBJECT_CLASS (goo_canvas_item_accessible_parent_class)->initialize (object, data);
+
+  object->role = ATK_ROLE_UNKNOWN;
 
   /* FIXME: Maybe this should be ATK_LAYER_CANVAS. */
   g_object_set_data (G_OBJECT (object), "atk-component-layer",
@@ -249,13 +251,13 @@
 
 
 static AtkObject*
-goo_canvas_item_view_accessible_get_parent (AtkObject *accessible)
+goo_canvas_item_accessible_get_parent (AtkObject *accessible)
 {
-  GooCanvasItemView *item_view, *parent_view;
-  GooCanvasView *canvas_view;
+  GooCanvasItem *item, *parent;
+  GooCanvas *canvas;
   GObject *object;
 
-  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE (accessible), NULL);
+  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_ACCESSIBLE (accessible), NULL);
 
   if (accessible->accessible_parent)
     return accessible->accessible_parent;
@@ -264,28 +266,28 @@
   if (object == NULL)
     return NULL;
 
-  item_view = GOO_CANVAS_ITEM_VIEW (object);
-  parent_view = goo_canvas_item_view_get_parent_view (item_view);
+  item = GOO_CANVAS_ITEM (object);
+  parent = goo_canvas_item_get_parent (item);
 
-  if (parent_view)
-    return atk_gobject_accessible_for_object (G_OBJECT (parent_view));
+  if (parent)
+    return atk_gobject_accessible_for_object (G_OBJECT (parent));
 
-  canvas_view = goo_canvas_item_view_get_canvas_view (item_view);
-  if (canvas_view)
-    return gtk_widget_get_accessible (GTK_WIDGET (canvas_view));
+  canvas = goo_canvas_item_get_canvas (item);
+  if (canvas)
+    return gtk_widget_get_accessible (GTK_WIDGET (canvas));
 
   return NULL;
 }
 
 
 static gint
-goo_canvas_item_view_accessible_get_index_in_parent (AtkObject *accessible)
+goo_canvas_item_accessible_get_index_in_parent (AtkObject *accessible)
 {
-  GooCanvasItemView *item_view, *parent_view;
-  GooCanvasView *canvas_view;
+  GooCanvasItem *item, *parent;
+  GooCanvas *canvas;
   GObject *object;
 
-  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE (accessible), -1);
+  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_ACCESSIBLE (accessible), -1);
 
   if (accessible->accessible_parent)
     {
@@ -312,14 +314,14 @@
   if (object == NULL)
     return -1;
 
-  item_view = GOO_CANVAS_ITEM_VIEW (object);
-  parent_view = goo_canvas_item_view_get_parent_view (item_view);
+  item = GOO_CANVAS_ITEM (object);
+  parent = goo_canvas_item_get_parent (item);
 
-  if (parent_view)
-    return goo_canvas_item_view_find_child (parent_view, item_view);
+  if (parent)
+    return goo_canvas_item_find_child (parent, item);
 
-  canvas_view = goo_canvas_item_view_get_canvas_view (item_view);
-  if (canvas_view)
+  canvas = goo_canvas_item_get_canvas (item);
+  if (canvas)
     return 0;
 
   return -1;
@@ -327,44 +329,44 @@
 
 
 static gint
-goo_canvas_item_view_accessible_get_n_children (AtkObject *accessible)
+goo_canvas_item_accessible_get_n_children (AtkObject *accessible)
 {
-  GooCanvasItemView *item_view;
+  GooCanvasItem *item;
   GObject *object;
 
-  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE (accessible), -1);
+  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_ACCESSIBLE (accessible), 0);
 
   object = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible));
   if (object == NULL)
-    return -1;
+    return 0;
 
-  item_view = GOO_CANVAS_ITEM_VIEW (object);
+  item = GOO_CANVAS_ITEM (object);
 
-  return goo_canvas_item_view_get_n_children (item_view);
+  return goo_canvas_item_get_n_children (item);
 }
 
 
 static AtkObject*
-goo_canvas_item_view_accessible_ref_child (AtkObject *accessible,
-					   gint       child_num)
+goo_canvas_item_accessible_ref_child (AtkObject *accessible,
+				      gint       child_num)
 {
-  GooCanvasItemView *item_view, *child_view;
+  GooCanvasItem *item, *child;
   AtkObject *atk_object;
   GObject *object;
 
-  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE (accessible), NULL);
+  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_ACCESSIBLE (accessible), NULL);
 
   object = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible));
   if (object == NULL)
     return NULL;
 
-  item_view = GOO_CANVAS_ITEM_VIEW (object);
+  item = GOO_CANVAS_ITEM (object);
 
-  child_view = goo_canvas_item_view_get_child (item_view, child_num);
-  if (!child_view)
+  child = goo_canvas_item_get_child (item, child_num);
+  if (!child)
     return NULL;
 
-  atk_object = atk_gobject_accessible_for_object (G_OBJECT (child_view));
+  atk_object = atk_gobject_accessible_for_object (G_OBJECT (child));
   g_object_ref (atk_object);
 
   return atk_object;
@@ -372,17 +374,17 @@
 
 
 static AtkStateSet*
-goo_canvas_item_view_accessible_ref_state_set (AtkObject *accessible)
+goo_canvas_item_accessible_ref_state_set (AtkObject *accessible)
 {
-  GooCanvasItemView *item_view;
-  GooCanvasView *canvas_view;
+  GooCanvasItem *item;
+  GooCanvas *canvas;
   AtkStateSet *state_set;
   GObject *object;
   gboolean can_focus = FALSE;
 
-  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_VIEW_ACCESSIBLE (accessible), NULL);
+  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_ACCESSIBLE (accessible), NULL);
 
-  state_set = ATK_OBJECT_CLASS (goo_canvas_item_view_accessible_parent_class)->ref_state_set (accessible);
+  state_set = ATK_OBJECT_CLASS (goo_canvas_item_accessible_parent_class)->ref_state_set (accessible);
 
   object = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible));
   if (!object)
@@ -391,28 +393,28 @@
       return state_set;
     }
 
-  item_view = GOO_CANVAS_ITEM_VIEW (object);
+  item = GOO_CANVAS_ITEM (object);
 
-  canvas_view = goo_canvas_item_view_get_canvas_view (item_view);
-  if (!canvas_view)
+  canvas = goo_canvas_item_get_canvas (item);
+  if (!canvas)
     return state_set;
 
-  if (goo_canvas_item_view_is_visible (item_view))
+  if (goo_canvas_item_is_visible (item))
     {
       atk_state_set_add_state (state_set, ATK_STATE_VISIBLE);
 
-      if (goo_canvas_item_view_accessible_is_item_on_screen (item_view))
+      if (goo_canvas_item_accessible_is_item_on_screen (item))
 	atk_state_set_add_state (state_set, ATK_STATE_SHOWING);
     }
 
-  g_object_get (item_view, "can-focus", &can_focus, NULL);
+  g_object_get (item, "can-focus", &can_focus, NULL);
 
-  if (GTK_WIDGET_CAN_FOCUS (GTK_WIDGET (canvas_view)) && can_focus)
+  if (GTK_WIDGET_CAN_FOCUS (GTK_WIDGET (canvas)) && can_focus)
     {
       atk_state_set_add_state (state_set, ATK_STATE_FOCUSABLE);
 
-      if (GTK_WIDGET_HAS_FOCUS (canvas_view)
-	  && canvas_view->focused_item_view == item_view)
+      if (GTK_WIDGET_HAS_FOCUS (canvas)
+	  && canvas->focused_item == item)
 	atk_state_set_add_state (state_set, ATK_STATE_FOCUSED);
     }
 
@@ -421,34 +423,33 @@
 
 
 static void
-goo_canvas_item_view_accessible_class_init (GooCanvasItemViewAccessibleClass *klass)
+goo_canvas_item_accessible_class_init (GooCanvasItemAccessibleClass *klass)
 {
   AtkObjectClass *aklass = (AtkObjectClass*) klass;
 
-  aklass->initialize          = goo_canvas_item_view_accessible_initialize;
-  aklass->get_parent          = goo_canvas_item_view_accessible_get_parent;
-  aklass->get_index_in_parent = goo_canvas_item_view_accessible_get_index_in_parent;
-  aklass->get_n_children      = goo_canvas_item_view_accessible_get_n_children;
-  aklass->ref_child           = goo_canvas_item_view_accessible_ref_child;
-  aklass->ref_state_set       = goo_canvas_item_view_accessible_ref_state_set;
+  aklass->initialize          = goo_canvas_item_accessible_initialize;
+  aklass->get_parent          = goo_canvas_item_accessible_get_parent;
+  aklass->get_index_in_parent = goo_canvas_item_accessible_get_index_in_parent;
+  aklass->get_n_children      = goo_canvas_item_accessible_get_n_children;
+  aklass->ref_child           = goo_canvas_item_accessible_ref_child;
+  aklass->ref_state_set       = goo_canvas_item_accessible_ref_state_set;
 }
 
 
 static void
-goo_canvas_item_view_accessible_init (GooCanvasItemViewAccessible *accessible)
+goo_canvas_item_accessible_init (GooCanvasItemAccessible *accessible)
 {
 }
 
 
 static AtkObject *
-goo_canvas_item_view_accessible_new (GObject *object)
+goo_canvas_item_accessible_new (GObject *object)
 {
   AtkObject *accessible;
 
-  g_return_val_if_fail (GOO_IS_CANVAS_ITEM_VIEW (object), NULL);
+  g_return_val_if_fail (GOO_IS_CANVAS_ITEM (object), NULL);
 
-  accessible = g_object_new (goo_canvas_item_view_accessible_get_type (),
-			     NULL);
+  accessible = g_object_new (goo_canvas_item_accessible_get_type (), NULL);
   atk_object_initialize (accessible, object);
 
   return accessible;
@@ -456,40 +457,167 @@
 
 
 /*
- * GooCanvasItemViewAccessibleFactory.
+ * GooCanvasItemAccessibleFactory.
  */
 
-typedef AtkObjectFactory      GooCanvasItemViewAccessibleFactory;
-typedef AtkObjectFactoryClass GooCanvasItemViewAccessibleFactoryClass;
+typedef AtkObjectFactory      GooCanvasItemAccessibleFactory;
+typedef AtkObjectFactoryClass GooCanvasItemAccessibleFactoryClass;
 
-G_DEFINE_TYPE (GooCanvasItemViewAccessibleFactory,
-	       goo_canvas_item_view_accessible_factory,
+G_DEFINE_TYPE (GooCanvasItemAccessibleFactory,
+	       goo_canvas_item_accessible_factory,
 	       ATK_TYPE_OBJECT_FACTORY)
 
 static void
-goo_canvas_item_view_accessible_factory_class_init (GooCanvasItemViewAccessibleFactoryClass *klass)
+goo_canvas_item_accessible_factory_class_init (GooCanvasItemAccessibleFactoryClass *klass)
 {
-  klass->create_accessible   = goo_canvas_item_view_accessible_new;
-  klass->get_accessible_type = goo_canvas_item_view_accessible_get_type;
+  klass->create_accessible   = goo_canvas_item_accessible_new;
+  klass->get_accessible_type = goo_canvas_item_accessible_get_type;
 }
 
 static void
-goo_canvas_item_view_accessible_factory_init (GooCanvasItemViewAccessibleFactory *factory)
+goo_canvas_item_accessible_factory_init (GooCanvasItemAccessibleFactory *factory)
 {
 }
 
 
 
 /*
- * GooCanvasViewAccessible.
+ * GooCanvasWidgetAccessible.
+ */
+
+typedef AtkGObjectAccessible      GooCanvasWidgetAccessible;
+typedef AtkGObjectAccessibleClass GooCanvasWidgetAccessibleClass;
+
+#define GOO_IS_CANVAS_WIDGET_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), goo_canvas_widget_accessible_get_type ()))
+
+G_DEFINE_TYPE (GooCanvasWidgetAccessible, goo_canvas_widget_accessible,
+	       GOO_TYPE_CANVAS_ITEM)
+
+
+static void
+goo_canvas_widget_accessible_initialize (AtkObject *object,
+					 gpointer   data)
+{
+  if (ATK_OBJECT_CLASS (goo_canvas_widget_accessible_parent_class)->initialize)
+    ATK_OBJECT_CLASS (goo_canvas_widget_accessible_parent_class)->initialize (object, data);
+
+  object->role = ATK_ROLE_PANEL;
+}
+
+
+static gint 
+goo_canvas_widget_accessible_get_n_children (AtkObject *accessible)
+{
+  GooCanvasWidget *witem;
+  GObject *object;
+
+  g_return_val_if_fail (GOO_IS_CANVAS_WIDGET_ACCESSIBLE (accessible), 0);
+
+  object = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible));
+  if (object == NULL)
+    return 0;
+
+  witem = GOO_CANVAS_WIDGET (object);
+
+  return witem->widget ? 1 : 0;
+}
+
+static AtkObject *
+goo_canvas_widget_accessible_ref_child (AtkObject *accessible,
+					gint       child_num)
+{
+  GooCanvasWidget *witem;
+  AtkObject *atk_object;
+  GObject *object;
+
+  g_return_val_if_fail (GOO_IS_CANVAS_WIDGET_ACCESSIBLE (accessible), NULL);
+
+  if (child_num != 0)
+    return NULL;
+
+  object = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible));
+  if (object == NULL)
+    return NULL;
+
+  g_return_val_if_fail (GOO_IS_CANVAS_WIDGET (object), NULL);
+
+  witem = GOO_CANVAS_WIDGET (object);
+
+  if (!witem->widget)
+    return NULL;
+
+  atk_object = gtk_widget_get_accessible (witem->widget);
+  g_object_ref (atk_object);
+
+  return atk_object;
+}
+
+
+static void
+goo_canvas_widget_accessible_class_init (GooCanvasWidgetAccessibleClass *klass)
+{
+  AtkObjectClass *aklass = (AtkObjectClass*) klass;
+
+  aklass->initialize     = goo_canvas_widget_accessible_initialize;
+  aklass->get_n_children = goo_canvas_widget_accessible_get_n_children;
+  aklass->ref_child      = goo_canvas_widget_accessible_ref_child;
+}
+
+
+static void
+goo_canvas_widget_accessible_init (GooCanvasWidgetAccessible *accessible)
+{
+}
+
+
+AtkObject*
+goo_canvas_widget_accessible_new (GObject *object)
+{
+  AtkObject *accessible;
+
+  g_return_val_if_fail (GOO_IS_CANVAS_WIDGET (object), NULL);
+
+  accessible = g_object_new (goo_canvas_widget_accessible_get_type (), NULL);
+  atk_object_initialize (accessible, object);
+
+  return accessible;
+}
+
+
+/*
+ * GooCanvasWidgetAccessibleFactory.
+ */
+
+typedef AtkObjectFactory      GooCanvasWidgetAccessibleFactory;
+typedef AtkObjectFactoryClass GooCanvasWidgetAccessibleFactoryClass;
+
+G_DEFINE_TYPE (GooCanvasWidgetAccessibleFactory,
+	       goo_canvas_widget_accessible_factory,
+	       ATK_TYPE_OBJECT_FACTORY)
+
+static void
+goo_canvas_widget_accessible_factory_class_init (GooCanvasWidgetAccessibleFactoryClass *klass)
+{
+  klass->create_accessible   = goo_canvas_widget_accessible_new;
+  klass->get_accessible_type = goo_canvas_widget_accessible_get_type;
+}
+
+static void
+goo_canvas_widget_accessible_factory_init (GooCanvasWidgetAccessibleFactory *factory)
+{
+}
+
+
+/*
+ * GooCanvasAccessible.
  */
 
 static gpointer accessible_parent_class = NULL;
 
 
 static void
-goo_canvas_view_accessible_initialize (AtkObject *object, 
-				       gpointer   data)
+goo_canvas_accessible_initialize (AtkObject *object, 
+				  gpointer   data)
 {
   if (ATK_OBJECT_CLASS (accessible_parent_class)->initialize) 
     ATK_OBJECT_CLASS (accessible_parent_class)->initialize (object, data);
@@ -500,13 +628,10 @@
 
 
 static gint
-goo_canvas_view_accessible_get_n_children (AtkObject *object)
+goo_canvas_accessible_get_n_children (AtkObject *object)
 {
   GtkAccessible *accessible;
   GtkWidget *widget;
-  GooCanvasView *canvas_view;
-  GooCanvasModel *model;
-  GooCanvasItem *root;
 
   accessible = GTK_ACCESSIBLE (object);
   widget = accessible->widget;
@@ -515,29 +640,20 @@
   if (widget == NULL)
     return 0;
 
-  g_return_val_if_fail (GOO_IS_CANVAS_VIEW (widget), 0);
-
-  canvas_view = GOO_CANVAS_VIEW (widget);
-
-  model = goo_canvas_view_get_model (canvas_view);
-  if (!model)
-    return 0;
+  g_return_val_if_fail (GOO_IS_CANVAS (widget), 0);
 
-  root = goo_canvas_model_get_root_item (model);
-  if (!root)
-    return 0;
+  if (goo_canvas_get_root_item (GOO_CANVAS (widget)))
+    return 1;
 
-  return 1;
+  return 0;
 }
 
 static AtkObject*
-goo_canvas_view_accessible_ref_child (AtkObject *object,
-				      gint       child_num)
+goo_canvas_accessible_ref_child (AtkObject *object,
+				 gint       child_num)
 {
   GtkAccessible *accessible;
   GtkWidget *widget;
-  GooCanvasView *canvas_view;
-  GooCanvasModel *model;
   GooCanvasItem *root;
   AtkObject *atk_object;
 
@@ -552,12 +668,7 @@
   if (widget == NULL)
     return NULL;
 
-  canvas_view = GOO_CANVAS_VIEW (widget);
-  model = goo_canvas_view_get_model (canvas_view);
-  if (!model)
-    return NULL;
-
-  root = goo_canvas_model_get_root_item (model);
+  root = goo_canvas_get_root_item (GOO_CANVAS (widget));
   if (!root)
     return NULL;
 
@@ -570,18 +681,18 @@
 
 
 static void
-goo_canvas_view_accessible_class_init (AtkObjectClass *klass)
+goo_canvas_accessible_class_init (AtkObjectClass *klass)
 {
   accessible_parent_class = g_type_class_peek_parent (klass);
 
-  klass->initialize     = goo_canvas_view_accessible_initialize;
-  klass->get_n_children = goo_canvas_view_accessible_get_n_children;
-  klass->ref_child      = goo_canvas_view_accessible_ref_child;
+  klass->initialize     = goo_canvas_accessible_initialize;
+  klass->get_n_children = goo_canvas_accessible_get_n_children;
+  klass->ref_child      = goo_canvas_accessible_ref_child;
 }
 
 
 static GType
-goo_canvas_view_accessible_get_type (void)
+goo_canvas_accessible_get_type (void)
 {
   static GType g_define_type_id = 0;
 
@@ -604,11 +715,11 @@
 	return G_TYPE_INVALID;
 
       g_type_query (parent_atk_type, &query);
-      tinfo.class_init = (GClassInitFunc) goo_canvas_view_accessible_class_init;
+      tinfo.class_init = (GClassInitFunc) goo_canvas_accessible_class_init;
       tinfo.class_size = query.class_size;
       tinfo.instance_size = query.instance_size;
       g_define_type_id = g_type_register_static (parent_atk_type,
-						 "GooCanvasViewAccessible",
+						 "GooCanvasAccessible",
 						 &tinfo, 0);
     }
 
@@ -617,13 +728,13 @@
 
 
 static AtkObject *
-goo_canvas_view_accessible_new (GObject *object)
+goo_canvas_accessible_new (GObject *object)
 {
   AtkObject *accessible;
 
-  g_return_val_if_fail (GOO_IS_CANVAS_VIEW (object), NULL);
+  g_return_val_if_fail (GOO_IS_CANVAS (object), NULL);
 
-  accessible = g_object_new (goo_canvas_view_accessible_get_type (), NULL);
+  accessible = g_object_new (goo_canvas_accessible_get_type (), NULL);
   atk_object_initialize (accessible, object);
 
   return accessible;
@@ -631,24 +742,24 @@
 
 
 /*
- * GooCanvasViewAccessibleFactory.
+ * GooCanvasAccessibleFactory.
  */
 
-typedef AtkObjectFactory      GooCanvasViewAccessibleFactory;
-typedef AtkObjectFactoryClass GooCanvasViewAccessibleFactoryClass;
+typedef AtkObjectFactory      GooCanvasAccessibleFactory;
+typedef AtkObjectFactoryClass GooCanvasAccessibleFactoryClass;
 
-G_DEFINE_TYPE (GooCanvasViewAccessibleFactory,
-	       goo_canvas_view_accessible_factory,
+G_DEFINE_TYPE (GooCanvasAccessibleFactory,
+	       goo_canvas_accessible_factory,
 	       ATK_TYPE_OBJECT_FACTORY)
 
 static void
-goo_canvas_view_accessible_factory_class_init (GooCanvasViewAccessibleFactoryClass *klass)
+goo_canvas_accessible_factory_class_init (GooCanvasAccessibleFactoryClass *klass)
 {
-  klass->create_accessible   = goo_canvas_view_accessible_new;
-  klass->get_accessible_type = goo_canvas_view_accessible_get_type;
+  klass->create_accessible   = goo_canvas_accessible_new;
+  klass->get_accessible_type = goo_canvas_accessible_get_type;
 }
 
 static void
-goo_canvas_view_accessible_factory_init (GooCanvasViewAccessibleFactory *factory)
+goo_canvas_accessible_factory_init (GooCanvasAccessibleFactory *factory)
 {
 }

Index: goocanvasatk.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasatk.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- goocanvasatk.h	18 Apr 2006 15:43:07 -0000	1.1
+++ goocanvasatk.h	29 Nov 2006 18:40:53 -0000	1.2
@@ -12,8 +12,9 @@
 
 G_BEGIN_DECLS
 
-GType    goo_canvas_view_accessible_factory_get_type  (void) G_GNUC_CONST;
-GType    goo_canvas_item_view_accessible_factory_get_type  (void) G_GNUC_CONST;
+GType    goo_canvas_accessible_factory_get_type  (void) G_GNUC_CONST;
+GType    goo_canvas_item_accessible_factory_get_type  (void) G_GNUC_CONST;
+GType    goo_canvas_widget_accessible_factory_get_type  (void) G_GNUC_CONST;
 
 
 G_END_DECLS

Index: goocanvasellipse.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasellipse.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- goocanvasellipse.c	24 Aug 2006 08:06:23 -0000	1.6
+++ goocanvasellipse.c	29 Nov 2006 18:40:53 -0000	1.7
@@ -25,15 +25,14 @@
  * g_object_get() and g_object_set().
  *
  * To respond to events such as mouse clicks on the ellipse you must connect
- * to the signal handlers of the corresponding #GooCanvasEllipseView objects.
- * (See goo_canvas_view_get_item_view() and #GooCanvasView::item-view-created.)
+ * to the signal handlers of the corresponding #GooCanvasEllipse objects.
+ * (See goo_canvas_get_item_view() and #GooCanvas::item-view-created.)
  */
 #include <config.h>
 #include <math.h>
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 #include "goocanvasellipse.h"
-#include "goocanvasellipseview.h"
 
 
 enum {
@@ -46,30 +45,28 @@
 };
 
 
-static void item_interface_init (GooCanvasItemIface *iface);
-static void goo_canvas_ellipse_get_property (GObject            *object,
-					     guint               param_id,
-					     GValue             *value,
-					     GParamSpec         *pspec);
-static void goo_canvas_ellipse_set_property (GObject            *object,
-					     guint               param_id,
-					     const GValue       *value,
-					     GParamSpec         *pspec);
+static void canvas_item_interface_init      (GooCanvasItemIface  *iface);
+static void goo_canvas_ellipse_finalize     (GObject             *object);
+static void goo_canvas_ellipse_get_property (GObject             *object,
+					     guint                param_id,
+					     GValue              *value,
+					     GParamSpec          *pspec);
+static void goo_canvas_ellipse_set_property (GObject             *object,
+					     guint                param_id,
+					     const GValue        *value,
+					     GParamSpec          *pspec);
+static void goo_canvas_ellipse_create_path  (GooCanvasItemSimple *simple,
+					     cairo_t             *cr);
 
 G_DEFINE_TYPE_WITH_CODE (GooCanvasEllipse, goo_canvas_ellipse,
 			 GOO_TYPE_CANVAS_ITEM_SIMPLE,
 			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
-						item_interface_init))
+						canvas_item_interface_init))
 
 
 static void
-goo_canvas_ellipse_class_init (GooCanvasEllipseClass *klass)
+goo_canvas_ellipse_install_common_properties (GObjectClass *gobject_class)
 {
-  GObjectClass *gobject_class = (GObjectClass*) klass;
-
-  gobject_class->get_property = goo_canvas_ellipse_get_property;
-  gobject_class->set_property = goo_canvas_ellipse_set_property;
-
   g_object_class_install_property (gobject_class, PROP_CENTER_X,
 				   g_param_spec_double ("center-x",
 							_("Center X"),
@@ -103,9 +100,26 @@
 
 
 static void
-goo_canvas_ellipse_init (GooCanvasEllipse *ellipse)
+goo_canvas_ellipse_class_init (GooCanvasEllipseClass *klass)
 {
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+  GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) klass;
+
+  gobject_class->finalize     = goo_canvas_ellipse_finalize;
+
+  gobject_class->get_property = goo_canvas_ellipse_get_property;
+  gobject_class->set_property = goo_canvas_ellipse_set_property;
+
+  simple_class->create_path = goo_canvas_ellipse_create_path;
 
+  goo_canvas_ellipse_install_common_properties (gobject_class);
+}
+
+
+static void
+goo_canvas_ellipse_init (GooCanvasEllipse *ellipse)
+{
+  ellipse->ellipse_data = g_slice_new0 (GooCanvasEllipseData);
 }
 
 
@@ -118,9 +132,7 @@
  * @center_y: the y coordinate of the center of the ellipse.
  * @radius_x: the horizontal radius of the ellipse.
  * @radius_y: the vertical radius of the ellipse.
- * @first_property: the name of the first property to set, or %NULL.
- * @...: the remaining property names and values to set, terminated with a
- *  %NULL.
+ * @...: optional pairs of property names and values, and a terminating %NULL.
  * 
  * Creates a new ellipse item.
  *
@@ -146,24 +158,28 @@
 			gdouble        center_y,
 			gdouble        radius_x,
 			gdouble        radius_y,
-			const gchar   *first_property,
 			...)
 {
   GooCanvasItem *item;
   GooCanvasEllipse *ellipse;
-  va_list args;
+  GooCanvasEllipseData *ellipse_data;
+  const char *first_property;
+  va_list var_args;
 
   item = g_object_new (GOO_TYPE_CANVAS_ELLIPSE, NULL);
-  ellipse = GOO_CANVAS_ELLIPSE (item);
+  ellipse = (GooCanvasEllipse*) item;
 
-  ellipse->center_x = center_x;
-  ellipse->center_y = center_y;
-  ellipse->radius_x = radius_x;
-  ellipse->radius_y = radius_y;
+  ellipse_data = ellipse->ellipse_data;
+  ellipse_data->center_x = center_x;
+  ellipse_data->center_y = center_y;
+  ellipse_data->radius_x = radius_x;
+  ellipse_data->radius_y = radius_y;
 
-  va_start (args, first_property);
-  g_object_set_valist (G_OBJECT (item), first_property, args);
-  va_end (args);
+  va_start (var_args, radius_y);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist ((GObject*) item, first_property, var_args);
+  va_end (var_args);
 
   if (parent)
     {
@@ -176,26 +192,39 @@
 
 
 static void
-goo_canvas_ellipse_get_property (GObject              *object,
-				 guint                 prop_id,
-				 GValue               *value,
-				 GParamSpec           *pspec)
+goo_canvas_ellipse_finalize (GObject *object)
 {
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
   GooCanvasEllipse *ellipse = (GooCanvasEllipse*) object;
 
+  if (!simple->model)
+    g_slice_free (GooCanvasEllipseData, ellipse->ellipse_data);
+  ellipse->ellipse_data = NULL;
+
+  G_OBJECT_CLASS (goo_canvas_ellipse_parent_class)->finalize (object);
+}
+
+
+static void
+goo_canvas_ellipse_get_common_property (GObject              *object,
+					GooCanvasEllipseData *ellipse_data,
+					guint                 prop_id,
+					GValue               *value,
+					GParamSpec           *pspec)
+{
   switch (prop_id)
     {
     case PROP_CENTER_X:
-      g_value_set_double (value, ellipse->center_x);
+      g_value_set_double (value, ellipse_data->center_x);
       break;
     case PROP_CENTER_Y:
-      g_value_set_double (value, ellipse->center_y);
+      g_value_set_double (value, ellipse_data->center_y);
       break;
     case PROP_RADIUS_X:
-      g_value_set_double (value, ellipse->radius_x);
+      g_value_set_double (value, ellipse_data->radius_x);
       break;
     case PROP_RADIUS_Y:
-      g_value_set_double (value, ellipse->radius_y);
+      g_value_set_double (value, ellipse_data->radius_y);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -205,50 +234,245 @@
 
 
 static void
-goo_canvas_ellipse_set_property (GObject              *object,
+goo_canvas_ellipse_get_property (GObject              *object,
 				 guint                 prop_id,
-				 const GValue         *value,
+				 GValue               *value,
 				 GParamSpec           *pspec)
 {
   GooCanvasEllipse *ellipse = (GooCanvasEllipse*) object;
 
+  goo_canvas_ellipse_get_common_property (object, ellipse->ellipse_data,
+					  prop_id, value, pspec);
+}
+
+
+static void
+goo_canvas_ellipse_set_common_property (GObject              *object,
+					GooCanvasEllipseData *ellipse_data,
+					guint                 prop_id,
+					const GValue         *value,
+					GParamSpec           *pspec)
+{
   switch (prop_id)
     {
     case PROP_CENTER_X:
-      ellipse->center_x = g_value_get_double (value);
+      ellipse_data->center_x = g_value_get_double (value);
       break;
     case PROP_CENTER_Y:
-      ellipse->center_y = g_value_get_double (value);
+      ellipse_data->center_y = g_value_get_double (value);
       break;
     case PROP_RADIUS_X:
-      ellipse->radius_x = g_value_get_double (value);
+      ellipse_data->radius_x = g_value_get_double (value);
       break;
     case PROP_RADIUS_Y:
-      ellipse->radius_y = g_value_get_double (value);
+      ellipse_data->radius_y = g_value_get_double (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
     }
+}
 
-  g_signal_emit_by_name (ellipse, "changed", TRUE);
+
+static void
+goo_canvas_ellipse_set_property (GObject              *object,
+				 guint                 prop_id,
+				 const GValue         *value,
+				 GParamSpec           *pspec)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasEllipse *ellipse = (GooCanvasEllipse*) object;
+
+  if (simple->model)
+    {
+      g_warning ("Can't set property of a canvas item with a model - set the model property instead");
+      return;
+    }
+
+  goo_canvas_ellipse_set_common_property (object, ellipse->ellipse_data,
+					  prop_id, value, pspec);
+  goo_canvas_item_simple_changed (simple, TRUE);
 }
 
 
-static GooCanvasItemView*
-goo_canvas_ellipse_create_view (GooCanvasItem     *item,
-				GooCanvasView     *canvas_view,
-				GooCanvasItemView *parent_view)
+static void
+goo_canvas_ellipse_create_path (GooCanvasItemSimple *simple,
+				cairo_t             *cr)
 {
-  return goo_canvas_ellipse_view_new (canvas_view, parent_view,
-				      (GooCanvasEllipse*) item);
+  GooCanvasEllipse *ellipse = (GooCanvasEllipse*) simple;
+  GooCanvasEllipseData *ellipse_data = ellipse->ellipse_data;
+
+  cairo_new_path (cr);
+  cairo_save (cr);
+  cairo_translate (cr, ellipse_data->center_x, ellipse_data->center_y);
+  cairo_scale (cr, ellipse_data->radius_x, ellipse_data->radius_y);
+  cairo_arc (cr, 0.0, 0.0, 1.0, 0.0, 2.0 * M_PI);
+  cairo_restore (cr);
 }
 
 
+
 static void
-item_interface_init (GooCanvasItemIface *iface)
+goo_canvas_ellipse_set_model    (GooCanvasItem      *item,
+				 GooCanvasItemModel *model)
 {
-  iface->create_view = goo_canvas_ellipse_create_view;
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+  GooCanvasItemIface *parent_iface = g_type_interface_peek_parent (iface);
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasEllipse *ellipse = (GooCanvasEllipse*) item;
+  GooCanvasEllipseModel *emodel = (GooCanvasEllipseModel*) model;
+
+  /* If our ellipse_data was allocated, free it. */
+  if (!simple->model)
+    g_slice_free (GooCanvasEllipseData, ellipse->ellipse_data);
+
+  /* Now use the new model's ellipse_data instead. */
+  ellipse->ellipse_data = &emodel->ellipse_data;
+
+  /* Let the parent GooCanvasItemSimple code do the rest. */
+  parent_iface->set_model (item, model);
+}
+
+
+static void
+canvas_item_interface_init (GooCanvasItemIface *iface)
+{
+  iface->set_model      = goo_canvas_ellipse_set_model;
+}
+
+
+/*
+ * GooCanvasEllipseModel.
+ */
+
+static void item_model_interface_init (GooCanvasItemModelIface *iface);
+static void goo_canvas_ellipse_model_finalize     (GObject            *object);
+static void goo_canvas_ellipse_model_get_property (GObject            *object,
+						   guint               param_id,
+						   GValue             *value,
+						   GParamSpec         *pspec);
+static void goo_canvas_ellipse_model_set_property (GObject            *object,
+						   guint               param_id,
+						   const GValue       *value,
+						   GParamSpec         *pspec);
+
+G_DEFINE_TYPE_WITH_CODE (GooCanvasEllipseModel, goo_canvas_ellipse_model,
+			 GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE,
+			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM_MODEL,
+						item_model_interface_init))
+
+
+static void
+goo_canvas_ellipse_model_class_init (GooCanvasEllipseModelClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+
+  gobject_class->finalize     = goo_canvas_ellipse_model_finalize;
+
+  gobject_class->get_property = goo_canvas_ellipse_model_get_property;
+  gobject_class->set_property = goo_canvas_ellipse_model_set_property;
+
+  goo_canvas_ellipse_install_common_properties (gobject_class);
+}
+
+
+static void
+goo_canvas_ellipse_model_init (GooCanvasEllipseModel *emodel)
+{
+
+}
+
+
+GooCanvasItemModel*
+goo_canvas_ellipse_model_new (GooCanvasItemModel *parent,
+			      gdouble             center_x,
+			      gdouble             center_y,
+			      gdouble             radius_x,
+			      gdouble             radius_y,
+			      ...)
+{
+  GooCanvasItemModel *model;
+  GooCanvasEllipseModel *emodel;
+  GooCanvasEllipseData *ellipse_data;
+  const char *first_property;
+  va_list var_args;
+
+  model = g_object_new (GOO_TYPE_CANVAS_ELLIPSE_MODEL, NULL);
+  emodel = (GooCanvasEllipseModel*) model;
+
+  ellipse_data = &emodel->ellipse_data;
+  ellipse_data->center_x = center_x;
+  ellipse_data->center_y = center_y;
+  ellipse_data->radius_x = radius_x;
+  ellipse_data->radius_y = radius_y;
+
+  va_start (var_args, radius_y);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist ((GObject*) model, first_property, var_args);
+  va_end (var_args);
+
+  if (parent)
+    {
+      goo_canvas_item_model_add_child (parent, model, -1);
+      g_object_unref (model);
+    }
+
+  return model;
+}
+
+
+static void
+goo_canvas_ellipse_model_finalize (GObject *object)
+{
+  /*GooCanvasEllipseModel *emodel = (GooCanvasEllipseModel*) object;*/
+
+  G_OBJECT_CLASS (goo_canvas_ellipse_model_parent_class)->finalize (object);
+}
+
+
+static void
+goo_canvas_ellipse_model_get_property (GObject              *object,
+				       guint                 prop_id,
+				       GValue               *value,
+				       GParamSpec           *pspec)
+{
+  GooCanvasEllipseModel *emodel = (GooCanvasEllipseModel*) object;
+
+  goo_canvas_ellipse_get_common_property (object, &emodel->ellipse_data,
+					  prop_id, value, pspec);
+}
+
+
+static void
+goo_canvas_ellipse_model_set_property (GObject              *object,
+				       guint                 prop_id,
+				       const GValue         *value,
+				       GParamSpec           *pspec)
+{
+  GooCanvasEllipseModel *emodel = (GooCanvasEllipseModel*) object;
+
+  goo_canvas_ellipse_set_common_property (object, &emodel->ellipse_data,
+					  prop_id, value, pspec);
+  g_signal_emit_by_name (emodel, "changed", TRUE);
 }
 
 
+static GooCanvasItem*
+goo_canvas_ellipse_model_create_item (GooCanvasItemModel *model,
+				      GooCanvas          *canvas)
+{
+  GooCanvasItem *item;
+
+  item = g_object_new (GOO_TYPE_CANVAS_ELLIPSE, NULL);
+  goo_canvas_item_set_model (item, model);
+
+  return item;
+}
+
+
+static void
+item_model_interface_init (GooCanvasItemModelIface *iface)
+{
+  iface->create_item    = goo_canvas_ellipse_model_create_item;
+}

Index: goocanvasellipse.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasellipse.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- goocanvasellipse.h	13 Apr 2006 16:06:04 -0000	1.2
+++ goocanvasellipse.h	29 Nov 2006 18:40:53 -0000	1.3
@@ -13,6 +13,14 @@
 G_BEGIN_DECLS
 
 
+/* This is the data used by both model and view classes. */
+typedef struct _GooCanvasEllipseData   GooCanvasEllipseData;
+struct _GooCanvasEllipseData
+{
+  gdouble center_x, center_y, radius_x, radius_y;
+};
+
+
 #define GOO_TYPE_CANVAS_ELLIPSE            (goo_canvas_ellipse_get_type ())
 #define GOO_CANVAS_ELLIPSE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_ELLIPSE, GooCanvasEllipse))
 #define GOO_CANVAS_ELLIPSE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_ELLIPSE, GooCanvasEllipseClass))
@@ -31,9 +39,9 @@
  */
 struct _GooCanvasEllipse
 {
-  GooCanvasItemSimple parent;
+  GooCanvasItemSimple parent_object;
 
-  gdouble center_x, center_y, radius_x, radius_y;
+  GooCanvasEllipseData *ellipse_data;
 };
 
 struct _GooCanvasEllipseClass
@@ -42,15 +50,54 @@
 };
 
 
-GType           goo_canvas_ellipse_get_type         (void) G_GNUC_CONST;
-GooCanvasItem*  goo_canvas_ellipse_new              (GooCanvasItem *parent,
-						     gdouble        center_x,
-						     gdouble        center_y,
-						     gdouble        radius_x,
-						     gdouble        radius_y,
-						     const gchar   *first_property,
-						     ...);
+GType               goo_canvas_ellipse_get_type  (void) G_GNUC_CONST;
 
+GooCanvasItem*      goo_canvas_ellipse_new	 (GooCanvasItem      *parent,
+						  gdouble             center_x,
+						  gdouble             center_y,
+						  gdouble             radius_x,
+						  gdouble             radius_y,
+						  ...);
+
+
+
+#define GOO_TYPE_CANVAS_ELLIPSE_MODEL            (goo_canvas_ellipse_model_get_type ())
+#define GOO_CANVAS_ELLIPSE_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_ELLIPSE_MODEL, GooCanvasEllipseModel))
+#define GOO_CANVAS_ELLIPSE_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_ELLIPSE_MODEL, GooCanvasEllipseModelClass))
+#define GOO_IS_CANVAS_ELLIPSE_MODEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_ELLIPSE_MODEL))
+#define GOO_IS_CANVAS_ELLIPSE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_ELLIPSE_MODEL))
+#define GOO_CANVAS_ELLIPSE_MODEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_ELLIPSE_MODEL, GooCanvasEllipseModelClass))
+
+
+typedef struct _GooCanvasEllipseModel       GooCanvasEllipseModel;
+typedef struct _GooCanvasEllipseModelClass  GooCanvasEllipseModelClass;
+
+/**
+ * GooCanvasEllipseModel
+ *
+ * The #GooCanvasEllipseModel-struct struct contains private data only.
+ */
+struct _GooCanvasEllipseModel
+{
+  GooCanvasItemModelSimple parent_object;
+
+  GooCanvasEllipseData ellipse_data;
+};
+
+struct _GooCanvasEllipseModelClass
+{
+  GooCanvasItemModelSimpleClass parent_class;
+};
+
+
+GType               goo_canvas_ellipse_model_get_type  (void) G_GNUC_CONST;
+
+GooCanvasItemModel* goo_canvas_ellipse_model_new (GooCanvasItemModel *parent,
+						  gdouble             center_x,
+						  gdouble             center_y,
+						  gdouble             radius_x,
+						  gdouble             radius_y,
+						  ...);
 
 G_END_DECLS
 

Index: goocanvasgroup.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasgroup.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- goocanvasgroup.c	24 Aug 2006 08:06:23 -0000	1.13
+++ goocanvasgroup.c	29 Nov 2006 18:40:53 -0000	1.14
@@ -26,42 +26,24 @@
  *
  * To respond to events such as mouse clicks on the group you must connect
  * to the signal handlers of the corresponding #GooCanvasGroupView objects.
- * (See goo_canvas_view_get_item_view() and #GooCanvasView::item-view-created.)
+ * (See goo_canvas_get_item_view() and #GooCanvas::item-created.)
  */
 #include <config.h>
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 #include "goocanvasprivate.h"
 #include "goocanvasgroup.h"
-#include "goocanvasgroupview.h"
+#include "goocanvasitemmodel.h"
+#include "goocanvas.h"
 #include "goocanvasmarshal.h"
+#include "goocanvasatk.h"
 
 
-enum {
-  PROP_0,
-
-  PROP_TRANSFORM,
-  PROP_VISIBILITY,
-  PROP_VISIBILITY_THRESHOLD,
-  PROP_POINTER_EVENTS,
-  PROP_TITLE,
-  PROP_DESCRIPTION
-};
-
-
-static void goo_canvas_group_finalize  (GObject *object);
-static void canvas_item_interface_init (GooCanvasItemIface *iface);
-static void goo_canvas_group_get_property (GObject            *object,
-					   guint               prop_id,
-					   GValue             *value,
-					   GParamSpec         *pspec);
-static void goo_canvas_group_set_property (GObject            *object,
-					   guint               prop_id,
-					   const GValue       *value,
-					   GParamSpec         *pspec);
+static void goo_canvas_group_finalize     (GObject            *object);
+static void canvas_item_interface_init    (GooCanvasItemIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (GooCanvasGroup, goo_canvas_group,
-			 G_TYPE_OBJECT,
+			 GOO_TYPE_CANVAS_ITEM_SIMPLE,
 			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
 						canvas_item_interface_init))
 
@@ -73,26 +55,13 @@
 
   gobject_class->finalize = goo_canvas_group_finalize;
 
-  gobject_class->get_property = goo_canvas_group_get_property;
-  gobject_class->set_property = goo_canvas_group_set_property;
-
-  g_object_class_override_property (gobject_class, PROP_VISIBILITY,
-				    "visibility");
-
-  g_object_class_override_property (gobject_class, PROP_VISIBILITY_THRESHOLD,
-				    "visibility-threshold");
-
-  g_object_class_override_property (gobject_class, PROP_TRANSFORM,
-				    "transform");
-
-  g_object_class_override_property (gobject_class, PROP_POINTER_EVENTS,
-				    "pointer-events");
-
-  g_object_class_override_property (gobject_class, PROP_TITLE,
-				    "title");
-
-  g_object_class_override_property (gobject_class, PROP_DESCRIPTION,
-				    "description");
+  /* Register our accessible factory, but only if accessibility is enabled. */
+  if (!ATK_IS_NO_OP_OBJECT_FACTORY (atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET)))
+    {
+      atk_registry_set_factory_type (atk_get_default_registry (),
+				     GOO_TYPE_CANVAS_GROUP,
+				     goo_canvas_item_accessible_factory_get_type ());
+    }
 }
 
 
@@ -100,8 +69,6 @@
 goo_canvas_group_init (GooCanvasGroup *group)
 {
   group->items = g_ptr_array_sized_new (8);
-  cairo_matrix_init_identity (&group->transform);
-  group->pointer_events = GOO_CANVAS_EVENTS_VISIBLE_PAINTED;
 }
 
 
@@ -110,51 +77,40 @@
  * @parent: the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
+ * @...: optional pairs of property names and values, and a terminating %NULL.
  * 
  * Creates a new group item.
  * 
  * Return value: a new group item.
  **/
 GooCanvasItem*
-goo_canvas_group_new (GooCanvasItem *parent)
+goo_canvas_group_new (GooCanvasItem *parent,
+		      ...)
 {
   GooCanvasItem *item;
   GooCanvasGroup *group;
+  va_list var_args;
+  const char *first_property;
 
   item = g_object_new (GOO_TYPE_CANVAS_GROUP, NULL);
-  group = GOO_CANVAS_GROUP (item);
+  group = (GooCanvasGroup*) item;
+
+  va_start (var_args, parent);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist (G_OBJECT (item), first_property, var_args);
+  va_end (var_args);
 
   if (parent)
     {
       goo_canvas_item_add_child (parent, item, -1);
       g_object_unref (item);
-
-      group->model = goo_canvas_item_get_model (parent);
     }
 
   return item;
 }
 
 
-/**
- * goo_canvas_group_set_model:
- * @group: a #GooCanvasGroup.
- * @model: the #GooCanvasModel of the group.
- * 
- * Sets the model of the group.
- *
- * This is only intended to be used by implementors of #GooCanvasModel, to set
- * the model of the root group.
- **/
-void
-goo_canvas_group_set_model   (GooCanvasGroup *group,
-			      GooCanvasModel *model)
-{
-  /* Note that we don't ref the model, to avoid reference cycles. */
-  group->model = model;
-}
-
-
 static void
 goo_canvas_group_finalize (GObject *object)
 {
@@ -165,6 +121,7 @@
   for (i = 0; i < group->items->len; i++)
     {
       GooCanvasItem *item = group->items->pdata[i];
+      goo_canvas_item_set_parent (item, NULL);
       g_object_unref (item);
     }
 
@@ -175,230 +132,587 @@
 
 
 static void
-goo_canvas_group_add_child     (GooCanvasItem  *group_item,
-				GooCanvasItem  *item,
+goo_canvas_group_add_child     (GooCanvasItem  *item,
+				GooCanvasItem  *child,
 				gint            position)
 {
-  GooCanvasGroup *group = GOO_CANVAS_GROUP (group_item);
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
 
-  g_object_ref (item);
+  g_object_ref (child);
 
   if (position >= 0)
     {
-      goo_canvas_util_ptr_array_insert (group->items, item, position);
+      goo_canvas_util_ptr_array_insert (group->items, child, position);
     }
   else
     {
       position = group->items->len;
-      g_ptr_array_add (group->items, item);
+      g_ptr_array_add (group->items, child);
     }
 
-  goo_canvas_item_set_parent (item, group_item);
+  goo_canvas_item_set_parent (child, item);
 
-  g_signal_emit_by_name (group, "child-added", position);
+  goo_canvas_item_request_update (item);
 }
 
 
 static void
-goo_canvas_group_move_child    (GooCanvasItem  *group_item,
+goo_canvas_group_move_child    (GooCanvasItem  *item,
 				gint	        old_position,
 				gint            new_position)
 {
-  GooCanvasGroup *group = GOO_CANVAS_GROUP (group_item);
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
+  GooCanvasItem *child;
+  GooCanvasBounds bounds;
+
+  /* Request a redraw of the item's bounds. */
+  child = group->items->pdata[old_position];
+  if (simple->canvas)
+    {
+      goo_canvas_item_get_bounds (child, &bounds);
+      goo_canvas_request_redraw (simple->canvas, &bounds);
+    }
 
   goo_canvas_util_ptr_array_move (group->items, old_position, new_position);
 
-  g_signal_emit_by_name (group, "child-moved", old_position, new_position);
+  goo_canvas_item_request_update (item);
 }
 
 
 static void
-goo_canvas_group_remove_child  (GooCanvasItem  *group_item,
+goo_canvas_group_remove_child  (GooCanvasItem  *item,
 				gint            child_num)
 {
-  GooCanvasGroup *group = GOO_CANVAS_GROUP (group_item);
-  GooCanvasItem *item;
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
+  GooCanvasItem *child;
+  GooCanvasBounds bounds;
 
-  item = group->items->pdata[child_num];
-  goo_canvas_item_set_parent (item, NULL);
-  g_object_unref (item);
+  /* Request a redraw of the item's bounds. */
+  child = group->items->pdata[child_num];
+  if (simple->canvas)
+    {
+      goo_canvas_item_get_bounds (child, &bounds);
+      goo_canvas_request_redraw (simple->canvas, &bounds);
+    }
+
+  goo_canvas_item_set_parent (child, NULL);
+  g_object_unref (child);
 
   g_ptr_array_remove_index (group->items, child_num);
 
-  g_signal_emit_by_name (group, "child-removed", child_num);
+  goo_canvas_item_request_update (item);
 }
 
 
 static gint
-goo_canvas_group_get_n_children (GooCanvasItem       *group_item)
+goo_canvas_group_get_n_children (GooCanvasItem  *item)
 {
-  GooCanvasGroup *group = GOO_CANVAS_GROUP (group_item);
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
 
   return group->items->len;
 }
 
 
 static GooCanvasItem*
-goo_canvas_group_get_child   (GooCanvasItem       *group_item,
+goo_canvas_group_get_child   (GooCanvasItem       *item,
 			      gint                 child_num)
 {
-  GooCanvasGroup *group = GOO_CANVAS_GROUP (group_item);
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
 
   return group->items->pdata[child_num];
 }
 
 
-static GooCanvasModel*
-goo_canvas_group_get_model (GooCanvasItem       *item)
+/* This is only used to set the canvas of the root group. It isn't normally
+   needed by apps. */
+static void
+goo_canvas_group_set_canvas  (GooCanvasItem *item,
+			      GooCanvas     *canvas)
 {
-  GooCanvasGroup *group = GOO_CANVAS_GROUP (item);
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
+  gint i;
 
-  if (!group->model && group->parent)
-    group->model = goo_canvas_item_get_model (group->parent);
+  simple->canvas = canvas;
 
-  return group->model;
+  /* 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_canvas (item, canvas);
+    }
 }
 
 
-static GooCanvasItem*
-goo_canvas_group_get_parent (GooCanvasItem       *item)
+static void
+on_model_child_added (GooCanvasGroupModel *model,
+		      gint                 position,
+		      GooCanvasGroup      *group)
 {
-  return GOO_CANVAS_GROUP (item)->parent;
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) group;
+  GooCanvasItem *item = (GooCanvasItem*) group;
+  GooCanvasItemModel *child_model;
+  GooCanvasItem *child;
+
+  /* Create a canvas item for the model. */
+  child_model = goo_canvas_item_model_get_child ((GooCanvasItemModel*) model,
+						 position);
+  child = goo_canvas_create_item (simple->canvas, child_model);
+  goo_canvas_group_add_child (item, child, position);
+  g_object_unref (child);
 }
 
 
 static void
-goo_canvas_group_set_parent (GooCanvasItem       *item,
-			     GooCanvasItem       *parent)
+on_model_child_moved (GooCanvasGroupModel *model,
+		      gint                 old_position,
+		      gint                 new_position,
+		      GooCanvasGroup      *group)
 {
-  GOO_CANVAS_GROUP (item)->parent = parent;
-  if (!parent)
-    GOO_CANVAS_GROUP (item)->model = NULL;
+  goo_canvas_group_move_child ((GooCanvasItem*) group, old_position,
+			       new_position);
 }
 
 
-static cairo_matrix_t*
-goo_canvas_group_get_transform (GooCanvasItem       *item)
+static void
+on_model_child_removed (GooCanvasGroupModel *model,
+			gint                 child_num,
+			GooCanvasGroup      *group)
 {
-  return &GOO_CANVAS_GROUP (item)->transform;
+  goo_canvas_group_remove_child ((GooCanvasItem*) group, child_num);
 }
 
 
 static void
-goo_canvas_group_set_transform (GooCanvasItem *item,
-				cairo_matrix_t *transform)
+goo_canvas_group_set_model (GooCanvasItem       *item,
+			    GooCanvasItemModel  *model)
 {
-  GooCanvasGroup *group = GOO_CANVAS_GROUP (item);
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+  GooCanvasItemIface *parent_iface = g_type_interface_peek_parent (iface);
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
+  gint n_children, i;
 
-  if (transform)
-    group->transform = *transform;
-  else
-    cairo_matrix_init_identity (&group->transform);
+  /* Do the default GooCanvasItemSimple code first. */
+  parent_iface->set_model (item, model);
 
-  g_signal_emit_by_name (group, "changed", TRUE);
+  /* Now add our own handlers. */
+  g_signal_connect (model, "child-added",
+		    G_CALLBACK (on_model_child_added), group);
+  g_signal_connect (model, "child-moved",
+		    G_CALLBACK (on_model_child_moved), group);
+  g_signal_connect (model, "child-removed",
+		    G_CALLBACK (on_model_child_removed), group);
+
+  /* Recursively create child items for any children. */
+  n_children = goo_canvas_item_model_get_n_children (model);
+  for (i = 0; i < n_children; i++)
+    on_model_child_added ((GooCanvasGroupModel*) simple->model, i, group);
 }
 
 
-static GooCanvasItemView*
-goo_canvas_group_create_view (GooCanvasItem     *group_item,
-			      GooCanvasView     *canvas_view,
-			      GooCanvasItemView *parent_view)
+static void
+goo_canvas_group_request_update  (GooCanvasItem *item)
 {
-  return goo_canvas_group_view_new (canvas_view, parent_view, group_item);
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+
+  if (!simple->need_update)
+    {
+      simple->need_update = TRUE;
+
+      if (simple->parent)
+	goo_canvas_item_request_update (simple->parent);
+      else if (simple->canvas)
+	goo_canvas_request_update (simple->canvas);
+    }
+}
+
+
+static void
+goo_canvas_group_update  (GooCanvasItem   *item,
+			  gboolean         entire_tree,
+			  cairo_t         *cr,
+			  GooCanvasBounds *bounds)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
+  GooCanvasBounds child_bounds;
+  gint i;
+
+  if (entire_tree || simple->need_update)
+    {
+      if (simple->need_entire_subtree_update)
+	entire_tree = TRUE;
+
+      simple->need_update = FALSE;
+      simple->need_entire_subtree_update = FALSE;
+
+      goo_canvas_item_simple_check_style (simple);
+
+      simple->bounds.x1 = simple->bounds.y1 = 0.0;
+      simple->bounds.x2 = simple->bounds.y2 = 0.0;
+
+      cairo_save (cr);
+      if (simple->simple_data->transform)
+	cairo_transform (cr, simple->simple_data->transform);
+
+      for (i = 0; i < group->items->len; i++)
+	{
+	  GooCanvasItem *child = group->items->pdata[i];
+
+	  goo_canvas_item_update (child, entire_tree, cr, &child_bounds);
+	  
+	  /* FIXME: Check for NULL bounds. Anywhere else? */
+	  if (i == 0)
+	    {
+	      simple->bounds.x1 = child_bounds.x1;
+	      simple->bounds.y1 = child_bounds.y1;
+	      simple->bounds.x2 = child_bounds.x2;
+	      simple->bounds.y2 = child_bounds.y2;
+	    }
+	  else
+	    {
+	      simple->bounds.x1 = MIN (simple->bounds.x1, child_bounds.x1);
+	      simple->bounds.y1 = MIN (simple->bounds.y1, child_bounds.y1);
+	      simple->bounds.x2 = MAX (simple->bounds.x2, child_bounds.x2);
+	      simple->bounds.y2 = MAX (simple->bounds.y2, child_bounds.y2);
+	    }
+	}
+      cairo_restore (cr);
+    }
+
+  *bounds = simple->bounds;
+}
+
+
+static GooCanvasItem*
+goo_canvas_group_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;
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
+  GooCanvasBounds child_bounds;
+  GooCanvasItem *found_item = NULL;
+  gboolean visible = parent_visible;
+  int i;
+
+  if (simple->need_update)
+    goo_canvas_item_ensure_updated (item);
+
+  if (simple_data->visibility == GOO_CANVAS_ITEM_INVISIBLE
+      || (simple_data->visibility == GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD
+	  && simple->canvas->scale < simple_data->visibility_threshold))
+    visible = FALSE;
+
+  /* Check if the group should receive events. */
+  if (is_pointer_event
+      && (simple_data->pointer_events == GOO_CANVAS_EVENTS_NONE
+	  || ((simple_data->pointer_events & GOO_CANVAS_EVENTS_VISIBLE_MASK)
+	      && !visible)))
+    return NULL;
+
+  /* Step down from the top item to the bottom in the stack/layer, and return
+     the first item found that contains the given point. */
+  cairo_save (cr);
+  if (simple_data->transform)
+    cairo_transform (cr, simple_data->transform);
+
+  for (i = group->items->len - 1; i >= 0; i--)
+    {
+      GooCanvasItem *child = group->items->pdata[i];
+      goo_canvas_item_get_bounds (child, &child_bounds);
+
+      /* Skip the item if the bounds don't contain the point. */
+      if (child_bounds.x1 > x || child_bounds.x2 < x
+	  || child_bounds.y1 > y || child_bounds.y2 < y)
+	continue;
+
+      found_item = goo_canvas_item_get_item_at (child, x, y, cr,
+						is_pointer_event, visible);
+      if (found_item)
+	break;
+    }
+  cairo_restore (cr);
+
+  return found_item;
+}
+
+
+static void
+goo_canvas_group_paint (GooCanvasItem     *item,
+			cairo_t           *cr,
+			GooCanvasBounds   *bounds,
+			gdouble            scale)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
+  GooCanvasBounds child_bounds;
+  gint i;
+
+  /* Check if the item should be visible. */
+  if (simple_data->visibility == GOO_CANVAS_ITEM_INVISIBLE
+      || (simple_data->visibility == GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD
+	  && simple->canvas->scale < simple_data->visibility_threshold))
+    return;
+
+  /* Paint all the items in the group. */
+  cairo_save (cr);
+  if (simple_data->transform)
+    cairo_transform (cr, simple_data->transform);
+
+  for (i = 0; i < group->items->len; i++)
+    {
+      GooCanvasItem *child = group->items->pdata[i];
+
+      goo_canvas_item_get_bounds (child, &child_bounds);
+
+      /* Skip the item if the bounds don't intersect the expose rectangle. */
+      if (child_bounds.x1 > bounds->x2 || child_bounds.x2 < bounds->x1
+	  || child_bounds.y1 > bounds->y2 || child_bounds.y2 < bounds->y1)
+	continue;
+
+      goo_canvas_item_paint (child, cr, bounds, scale);
+    }
+  cairo_restore (cr);
 }
 
 
 static void
 canvas_item_interface_init (GooCanvasItemIface *iface)
 {
+  iface->set_canvas     = goo_canvas_group_set_canvas;
+  iface->get_n_children = goo_canvas_group_get_n_children;
+  iface->get_child      = goo_canvas_group_get_child;
+  iface->request_update = goo_canvas_group_request_update;
+
   iface->add_child      = goo_canvas_group_add_child;
   iface->move_child     = goo_canvas_group_move_child;
   iface->remove_child   = goo_canvas_group_remove_child;
-  iface->get_n_children = goo_canvas_group_get_n_children;
-  iface->get_child      = goo_canvas_group_get_child;
 
-  iface->get_model      = goo_canvas_group_get_model;
-  iface->get_parent     = goo_canvas_group_get_parent;
-  iface->set_parent     = goo_canvas_group_set_parent;
-  iface->get_transform  = goo_canvas_group_get_transform;
-  iface->set_transform  = goo_canvas_group_set_transform;
-  iface->create_view    = goo_canvas_group_create_view;
+  iface->get_item_at	= goo_canvas_group_get_item_at;
+  iface->update         = goo_canvas_group_update;
+  iface->paint          = goo_canvas_group_paint;
+
+  iface->set_model      = goo_canvas_group_set_model;
 }
 
 
+/**
+ * SECTION:goocanvasgroupmodel
+ * @Title: GooCanvasGroupModelModel
+ * @Short_Description: model for a group of items.
+ *
+ * #GooCanvasGroupModel represents a group of items. Groups can be nested to any
+ * depth, to create a hierarchy of items. Items are ordered within each group,
+ * with later items being displayed above earlier items.
+ *
+ * #GooCanvasGroupModel implements the #GooCanvasItem interface, so you can use the
+ * #GooCanvasItem functions such as goo_canvas_item_raise() and
+ * goo_canvas_item_rotate(), and the properties such as "visibility" and
+ * "pointer-events".
+ *
+ * To create a #GooCanvasGroupModel use goo_canvas_group_model_new().
+ *
+ * To get or set the properties of an existing #GooCanvasGroupModel, use
+ * g_object_get() and g_object_set().
+ *
+ * To respond to events such as mouse clicks on the group you must connect
+ * to the signal handlers of the corresponding #GooCanvasGroupModelView objects.
+ * (See goo_canvas_view_get_item_view() and #GooCanvasView::item-view-created.)
+ */
+static void item_model_interface_init (GooCanvasItemModelIface *iface);
+static void goo_canvas_group_model_finalize     (GObject            *object);
+
+G_DEFINE_TYPE_WITH_CODE (GooCanvasGroupModel, goo_canvas_group_model,
+			 GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE,
+			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM_MODEL,
+						item_model_interface_init))
+
+
 static void
-goo_canvas_group_get_property (GObject              *object,
-			       guint                 prop_id,
-			       GValue               *value,
-			       GParamSpec           *pspec)
+goo_canvas_group_model_class_init (GooCanvasGroupModelClass *klass)
 {
-  GooCanvasGroup *group = (GooCanvasGroup*) object;
+  GObjectClass *gobject_class = (GObjectClass*) klass;
 
-  switch (prop_id)
-    {
-    case PROP_TRANSFORM:
-      g_value_set_boxed (value, &group->transform);
-      break;
-    case PROP_VISIBILITY:
-      g_value_set_enum (value, group->visibility);
-      break;
-    case PROP_VISIBILITY_THRESHOLD:
-      g_value_set_double (value, group->visibility_threshold);
-      break;
-    case PROP_POINTER_EVENTS:
-      g_value_set_flags (value, group->pointer_events);
-      break;
-    case PROP_TITLE:
-      g_value_set_string (value, group->title);
-      break;
-    case PROP_DESCRIPTION:
-      g_value_set_string (value, group->description);
-      break;
+  gobject_class->finalize = goo_canvas_group_model_finalize;
+}
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
+
+static void
+goo_canvas_group_model_init (GooCanvasGroupModel *gmodel)
+{
+  gmodel->children = g_ptr_array_sized_new (8);
+}
+
+
+/**
+ * goo_canvas_group_model_new:
+ * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ *  ownership of the item, and the item will automatically be freed when it is
+ *  removed from the parent. Otherwise call g_object_unref() to free it.
+ * @...: optional pairs of property names and values, and a terminating %NULL.
+ * 
+ * Creates a new group item.
+ * 
+ * Return value: a new group item.
+ **/
+GooCanvasItemModel*
+goo_canvas_group_model_new (GooCanvasItemModel *parent,
+			    ...)
+{
+  GooCanvasItemModel *item;
+  GooCanvasGroupModel *gmodel;
+  va_list var_args;
+  const char *first_property;
+
+  item = g_object_new (GOO_TYPE_CANVAS_GROUP_MODEL, NULL);
+  gmodel = (GooCanvasGroupModel*) item;
+
+  va_start (var_args, parent);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist (G_OBJECT (item), first_property, var_args);
+  va_end (var_args);
+
+  if (parent)
+    {
+      goo_canvas_item_model_add_child (parent, item, -1);
+      g_object_unref (item);
     }
+
+  return item;
 }
 
 
 static void
-goo_canvas_group_set_property (GObject              *object,
-			       guint                 prop_id,
-			       const GValue         *value,
-			       GParamSpec           *pspec)
+goo_canvas_group_model_finalize (GObject *object)
 {
-  GooCanvasGroup *group = (GooCanvasGroup*) object;
-  cairo_matrix_t *transform;
+  GooCanvasGroupModel *gmodel = (GooCanvasGroupModel*) object;
+  gint i;
 
-  switch (prop_id)
+  /* Unref all the items in the group. */
+  for (i = 0; i < gmodel->children->len; i++)
     {
-    case PROP_TRANSFORM:
-      transform = g_value_get_boxed (value);
-      group->transform = *transform;
-      break;
-    case PROP_VISIBILITY:
-      group->visibility = g_value_get_enum (value);
-      break;
-    case PROP_VISIBILITY_THRESHOLD:
-      group->visibility_threshold = g_value_get_double (value);
-      break;
-    case PROP_POINTER_EVENTS:
-      group->pointer_events = g_value_get_flags (value);
-      break;
-    case PROP_TITLE:
-      g_free (group->title);
-      group->title = g_value_dup_string (value);
-      break;
-    case PROP_DESCRIPTION:
-      g_free (group->description);
-      group->description = g_value_dup_string (value);
-      break;
+      GooCanvasItemModel *child = gmodel->children->pdata[i];
+      goo_canvas_item_model_set_parent (child, NULL);
+      g_object_unref (child);
+    }
 
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
+  g_ptr_array_free (gmodel->children, TRUE);
+
+  G_OBJECT_CLASS (goo_canvas_group_model_parent_class)->finalize (object);
+}
+
+
+static void
+goo_canvas_group_model_add_child     (GooCanvasItemModel *model,
+				      GooCanvasItemModel *child,
+				      gint                position)
+{
+  GooCanvasGroupModel *gmodel = (GooCanvasGroupModel*) model;
+
+  g_object_ref (child);
+
+  if (position >= 0)
+    {
+      goo_canvas_util_ptr_array_insert (gmodel->children, child, position);
+    }
+  else
+    {
+      position = gmodel->children->len;
+      g_ptr_array_add (gmodel->children, child);
     }
 
-  g_signal_emit_by_name (group, "changed", TRUE);
+  goo_canvas_item_model_set_parent (child, model);
+
+  g_signal_emit_by_name (gmodel, "child-added", position);
+}
+
+
+static void
+goo_canvas_group_model_move_child    (GooCanvasItemModel *model,
+				      gint	          old_position,
+				      gint                new_position)
+{
+  GooCanvasGroupModel *gmodel = (GooCanvasGroupModel*) model;
+
+  goo_canvas_util_ptr_array_move (gmodel->children, old_position,
+				  new_position);
+
+  g_signal_emit_by_name (gmodel, "child-moved", old_position, new_position);
+}
+
+
+static void
+goo_canvas_group_model_remove_child  (GooCanvasItemModel *model,
+				      gint                child_num)
+{
+  GooCanvasGroupModel *gmodel = (GooCanvasGroupModel*) model;
+  GooCanvasItemModel *child;
+
+  child = gmodel->children->pdata[child_num];
+  goo_canvas_item_model_set_parent (child, NULL);
+  g_object_unref (child);
+
+  g_ptr_array_remove_index (gmodel->children, child_num);
+
+  g_signal_emit_by_name (gmodel, "child-removed", child_num);
+}
+
+
+static gint
+goo_canvas_group_model_get_n_children (GooCanvasItemModel  *model)
+{
+  GooCanvasGroupModel *gmodel = (GooCanvasGroupModel*) model;
+
+  return gmodel->children->len;
+}
+
+
+static GooCanvasItemModel*
+goo_canvas_group_model_get_child   (GooCanvasItemModel  *model,
+				    gint                 child_num)
+{
+  GooCanvasGroupModel *gmodel = (GooCanvasGroupModel*) model;
+
+  return gmodel->children->pdata[child_num];
 }
+
+
+static GooCanvasItem*
+goo_canvas_group_model_create_item (GooCanvasItemModel *model,
+				    GooCanvas          *canvas)
+{
+  GooCanvasItem *item;
+
+  item = goo_canvas_group_new (NULL, NULL);
+  /* Note that we set the canvas before the model, since we may need the
+     canvas to create any child items. */
+  goo_canvas_item_set_canvas (item, canvas);
+  goo_canvas_item_set_model (item, model);
+
+  return item;
+}
+
+
+static void
+item_model_interface_init (GooCanvasItemModelIface *iface)
+{
+  iface->add_child      = goo_canvas_group_model_add_child;
+  iface->move_child     = goo_canvas_group_model_move_child;
+  iface->remove_child   = goo_canvas_group_model_remove_child;
+  iface->get_n_children = goo_canvas_group_model_get_n_children;
+  iface->get_child      = goo_canvas_group_model_get_child;
+
+  iface->create_item    = goo_canvas_group_model_create_item;
+}
+
+

Index: goocanvasgroup.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasgroup.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- goocanvasgroup.h	8 Aug 2006 21:58:13 -0000	1.8
+++ goocanvasgroup.h	29 Nov 2006 18:40:53 -0000	1.9
@@ -8,7 +8,7 @@
 #define __GOO_CANVAS_GROUP_H__
 
 #include <gtk/gtk.h>
-#include "goocanvasmodel.h"
+#include "goocanvasitemsimple.h"
 #include "goocanvasutils.h"
 
 G_BEGIN_DECLS
@@ -22,8 +22,11 @@
 #define GOO_CANVAS_GROUP_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_GROUP, GooCanvasGroupClass))
 
 
-typedef struct _GooCanvasGroup       GooCanvasGroup;
-typedef struct _GooCanvasGroupClass  GooCanvasGroupClass;
+typedef struct _GooCanvasGroup            GooCanvasGroup;
+typedef struct _GooCanvasGroupClass       GooCanvasGroupClass;
+
+typedef struct _GooCanvasGroupModel       GooCanvasGroupModel;
+typedef struct _GooCanvasGroupModelClass  GooCanvasGroupModelClass;
 
 /**
  * GooCanvasGroup
@@ -32,50 +35,58 @@
  */
 struct _GooCanvasGroup
 {
-  GObject object;
-
-  /* The canvas model. */
-  GooCanvasModel *model;
-
-  /* The parent item. */
-  GooCanvasItem *parent;
+  GooCanvasItemSimple parent_object;
 
   /* An array of pointers to GooCanvasItems. The first element is at the
      bottom of the display stack and the last element is at the top. */
   GPtrArray *items;
+};
 
-  /* The transformation matrix, or NULL. */
-  cairo_matrix_t transform;
+struct _GooCanvasGroupClass
+{
+  GooCanvasItemSimpleClass parent_class;
+};
 
-  /* If visibility is VISIBLE_ABOVE_THRESHOLD the item is visible if the canvas
-     scale setting is above this threshold (or equal to it). */
-  gdouble visibility_threshold;
 
-  /* The title and description of the item for accessibility. */
-  gchar *title;
-  gchar *description;
+GType          goo_canvas_group_get_type    (void) G_GNUC_CONST;
+GooCanvasItem* goo_canvas_group_new         (GooCanvasItem  *parent,
+					     ...);
 
-  /* Whether the item is visible, invisible, or visible above a given scale. */
-  GooCanvasItemVisibility visibility	: 2;
 
-  /* What events the group should receive. */
-  GooCanvasPointerEvents pointer_events : 4;
-};
 
-struct _GooCanvasGroupClass
+#define GOO_TYPE_CANVAS_GROUP_MODEL            (goo_canvas_group_model_get_type ())
+#define GOO_CANVAS_GROUP_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_GROUP_MODEL, GooCanvasGroupModel))
+#define GOO_CANVAS_GROUP_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_GROUP_MODEL, GooCanvasGroupModelClass))
+#define GOO_IS_CANVAS_GROUP_MODEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_GROUP_MODEL))
+#define GOO_IS_CANVAS_GROUP_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_GROUP_MODEL))
+#define GOO_CANVAS_GROUP_MODEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_GROUP_MODEL, GooCanvasGroupModelClass))
+
+
+
+/**
+ * GooCanvasGroupModel
+ *
+ * The #GooCanvasGroupModel-struct struct contains private data only.
+ */
+struct _GooCanvasGroupModel
 {
-  GObjectClass parent_class;
+  GooCanvasItemModelSimple parent_object;
+
+  /* An array of pointers to GooCanvasItemModels. The first element is at the
+     bottom of the display stack and the last element is at the top. */
+  GPtrArray *children;
 };
 
+struct _GooCanvasGroupModelClass
+{
+  GooCanvasItemModelSimpleClass parent_class;
+};
 
-GType          goo_canvas_group_get_type    (void) G_GNUC_CONST;
-GooCanvasItem* goo_canvas_group_new         (GooCanvasItem  *parent);
 
+GType               goo_canvas_group_model_get_type (void) G_GNUC_CONST;
+GooCanvasItemModel* goo_canvas_group_model_new      (GooCanvasItemModel  *parent,
+						     ...);
 
-/* This is only intended to be used by implementors of GooCanvasModel, to set
-   the model of the root group. */
-void           goo_canvas_group_set_model   (GooCanvasGroup *group,
-					     GooCanvasModel *model);
 
 G_END_DECLS
 

Index: goocanvasimage.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasimage.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- goocanvasimage.c	24 Aug 2006 08:06:23 -0000	1.7
+++ goocanvasimage.c	29 Nov 2006 18:40:53 -0000	1.8
@@ -26,14 +26,14 @@
  *
  * To respond to events such as mouse clicks on the image you must connect
  * to the signal handlers of the corresponding #GooCanvasImageView objects.
- * (See goo_canvas_view_get_item_view() and #GooCanvasView::item-view-created.)
+ * (See goo_canvas_get_item_view() and #GooCanvasView::item-view-created.)
  */
 #include <config.h>
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 #include "goocanvasprivate.h"
 #include "goocanvasimage.h"
-#include "goocanvasimageview.h"
+#include "goocanvas.h"
 #include "goocanvasutils.h"
 
 
@@ -50,8 +50,8 @@
   PROP_PIXBUF
 };
 
-static void goo_canvas_image_finalize (GObject *object);
-static void item_interface_init (GooCanvasItemIface *iface);
+static void goo_canvas_image_finalize     (GObject            *object);
+static void canvas_item_interface_init    (GooCanvasItemIface *iface);
 static void goo_canvas_image_get_property (GObject            *object,
 					   guint               param_id,
 					   GValue             *value,
@@ -64,19 +64,12 @@
 G_DEFINE_TYPE_WITH_CODE (GooCanvasImage, goo_canvas_image,
 			 GOO_TYPE_CANVAS_ITEM_SIMPLE,
 			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
-						item_interface_init))
+						canvas_item_interface_init))
 
 
 static void
-goo_canvas_image_class_init (GooCanvasImageClass *klass)
+goo_canvas_image_install_common_properties (GObjectClass *gobject_class)
 {
-  GObjectClass *gobject_class = (GObjectClass*) klass;
-
-  gobject_class->finalize = goo_canvas_image_finalize;
-
-  gobject_class->get_property = goo_canvas_image_get_property;
-  gobject_class->set_property = goo_canvas_image_set_property;
-
   g_object_class_install_property (gobject_class, PROP_PATTERN,
                                    g_param_spec_boxed ("pattern",
 						       _("Pattern"),
@@ -124,9 +117,23 @@
 
 
 static void
-goo_canvas_image_init (GooCanvasImage *canvas_image)
+goo_canvas_image_class_init (GooCanvasImageClass *klass)
 {
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+
+  gobject_class->finalize = goo_canvas_image_finalize;
 
+  gobject_class->get_property = goo_canvas_image_get_property;
+  gobject_class->set_property = goo_canvas_image_set_property;
+
+  goo_canvas_image_install_common_properties (gobject_class);
+}
+
+
+static void
+goo_canvas_image_init (GooCanvasImage *image)
+{
+  image->image_data = g_slice_new0 (GooCanvasImageData);
 }
 
 
@@ -138,9 +145,7 @@
  * @pixbuf: the #GdkPixbuf containing the image data, or %NULL.
  * @x: the x coordinate of the image.
  * @y: the y coordinate of the image.
- * @first_property: the name of the first property to set, or %NULL.
- * @...: the remaining property names and values to set, terminated with a
- *  %NULL.
+ * @...: optional pairs of property names and values, and a terminating %NULL.
  * 
  * Creates a new image item.
  * 
@@ -161,30 +166,34 @@
 		      GdkPixbuf     *pixbuf,
 		      gdouble        x,
 		      gdouble        y,
-		      const gchar   *first_property,
 		      ...)
 {
   GooCanvasItem *item;
   GooCanvasImage *image;
-  va_list args;
+  GooCanvasImageData *image_data;
+  const char *first_property;
+  va_list var_args;
 
   item = g_object_new (GOO_TYPE_CANVAS_IMAGE, NULL);
-  image = GOO_CANVAS_IMAGE (item);
-
-  image->x = x;
-  image->y = y;
+  image = (GooCanvasImage*) item;
 
-  va_start (args, first_property);
-  g_object_set_valist (G_OBJECT (item), first_property, args);
-  va_end (args);
+  image_data = image->image_data;
+  image_data->x = x;
+  image_data->y = y;
 
   if (pixbuf)
     {
-      image->pattern = goo_canvas_cairo_pattern_from_pixbuf (pixbuf);
-      image->width = gdk_pixbuf_get_width (pixbuf);
-      image->height = gdk_pixbuf_get_height (pixbuf);
+      image_data->pattern = goo_canvas_cairo_pattern_from_pixbuf (pixbuf);
+      image_data->width = gdk_pixbuf_get_width (pixbuf);
+      image_data->height = gdk_pixbuf_get_height (pixbuf);
     }
 
+  va_start (var_args, y);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist ((GObject*) item, first_property, var_args);
+  va_end (var_args);
+
   if (parent)
     {
       goo_canvas_item_add_child (parent, item, -1);
@@ -198,55 +207,43 @@
 static void
 goo_canvas_image_finalize (GObject *object)
 {
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
   GooCanvasImage *image = (GooCanvasImage*) object;
 
-  cairo_pattern_destroy (image->pattern);
+  if (!simple->model)
+    {
+      cairo_pattern_destroy (image->image_data->pattern);
+      g_slice_free (GooCanvasImageData, image->image_data);
+    }
+  image->image_data = NULL;
 
   G_OBJECT_CLASS (goo_canvas_image_parent_class)->finalize (object);
 }
 
 
-static GooCanvasItemView*
-goo_canvas_image_create_view (GooCanvasItem     *item,
-			      GooCanvasView     *canvas_view,
-			      GooCanvasItemView *parent_view)
-{
-  return goo_canvas_image_view_new (canvas_view, parent_view,
-				    (GooCanvasImage*) item);
-}
-
-
-static void
-item_interface_init (GooCanvasItemIface *iface)
-{
-  iface->create_view = goo_canvas_image_create_view;
-}
-
-
 static void
-goo_canvas_image_get_property (GObject              *object,
-			       guint                 prop_id,
-			       GValue               *value,
-			       GParamSpec           *pspec)
+goo_canvas_image_get_common_property (GObject              *object,
+				      GooCanvasImageData   *image_data,
+				      guint                 prop_id,
+				      GValue               *value,
+				      GParamSpec           *pspec)
 {
-  GooCanvasImage *image = (GooCanvasImage*) object;
-
   switch (prop_id)
     {
     case PROP_PATTERN:
-      g_value_set_boxed (value, image->pattern);
+      g_value_set_boxed (value, image_data->pattern);
       break;
     case PROP_X:
-      g_value_set_double (value, image->x);
+      g_value_set_double (value, image_data->x);
       break;
     case PROP_Y:
-      g_value_set_double (value, image->y);
+      g_value_set_double (value, image_data->y);
       break;
     case PROP_WIDTH:
-      g_value_set_double (value, image->width);
+      g_value_set_double (value, image_data->width);
       break;
     case PROP_HEIGHT:
-      g_value_set_double (value, image->height);
+      g_value_set_double (value, image_data->height);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -257,44 +254,388 @@
 
 
 static void
-goo_canvas_image_set_property (GObject              *object,
+goo_canvas_image_get_property (GObject              *object,
 			       guint                 prop_id,
-			       const GValue         *value,
+			       GValue               *value,
 			       GParamSpec           *pspec)
 {
   GooCanvasImage *image = (GooCanvasImage*) object;
+
+  goo_canvas_image_get_common_property (object, image->image_data, prop_id,
+					value, pspec);
+}
+
+
+static void
+goo_canvas_image_set_common_property (GObject              *object,
+				      GooCanvasImageData   *image_data,
+				      guint                 prop_id,
+				      const GValue         *value,
+				      GParamSpec           *pspec)
+{
   GdkPixbuf *pixbuf;
 
   switch (prop_id)
     {
     case PROP_PATTERN:
-      cairo_pattern_destroy (image->pattern);
-      image->pattern = g_value_get_boxed (value);
-      cairo_pattern_reference (image->pattern);
+      cairo_pattern_destroy (image_data->pattern);
+      image_data->pattern = g_value_get_boxed (value);
+      cairo_pattern_reference (image_data->pattern);
       break;
     case PROP_X:
-      image->x = g_value_get_double (value);
+      image_data->x = g_value_get_double (value);
       break;
     case PROP_Y:
-      image->y = g_value_get_double (value);
+      image_data->y = g_value_get_double (value);
       break;
     case PROP_WIDTH:
-      image->width = g_value_get_double (value);
+      image_data->width = g_value_get_double (value);
       break;
     case PROP_HEIGHT:
-      image->height = g_value_get_double (value);
+      image_data->height = g_value_get_double (value);
       break;
     case PROP_PIXBUF:
-      cairo_pattern_destroy (image->pattern);
+      cairo_pattern_destroy (image_data->pattern);
       pixbuf = g_value_get_object (value);
-      image->pattern = goo_canvas_cairo_pattern_from_pixbuf (pixbuf);
-      image->width = gdk_pixbuf_get_width (pixbuf);
-      image->height = gdk_pixbuf_get_height (pixbuf);
+      image_data->pattern = goo_canvas_cairo_pattern_from_pixbuf (pixbuf);
+      image_data->width = gdk_pixbuf_get_width (pixbuf);
+      image_data->height = gdk_pixbuf_get_height (pixbuf);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
+}
 
-  g_signal_emit_by_name (image, "changed", TRUE);
+
+static void
+goo_canvas_image_set_property (GObject              *object,
+			       guint                 prop_id,
+			       const GValue         *value,
+			       GParamSpec           *pspec)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasImage *image = (GooCanvasImage*) object;
+
+  if (simple->model)
+    {
+      g_warning ("Can't set property of a canvas item with a model - set the model property instead");
+      return;
+    }
+
+  goo_canvas_image_set_common_property (object, image->image_data, prop_id,
+					value, pspec);
+  goo_canvas_item_simple_changed (simple, TRUE);
 }
+
+
+static GooCanvasItem*
+goo_canvas_image_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;
+  GooCanvasImage *image = (GooCanvasImage*) simple;
+  GooCanvasImageData *image_data = image->image_data;
+  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. Note that we don't take
+     image transparency into account here at present. */
+  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);
+
+  if (user_x < image_data->x || (user_x > image_data->x + image_data->width)
+      || user_y < image_data->y || (user_y > image_data->y + image_data->height))
+    found_item = NULL;
+
+  cairo_restore (cr);
+
+  return found_item;
+}
+
+
+static void
+goo_canvas_image_update  (GooCanvasItem      *item,
+			  gboolean            entire_tree,
+			  cairo_t            *cr,
+			  GooCanvasBounds    *bounds)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasImage *image = (GooCanvasImage*) item;
+  GooCanvasImageData *image_data = image->image_data;
+
+  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);
+
+      /* Compute the new bounds. */
+      simple->bounds.x1 = image_data->x;
+      simple->bounds.y1 = image_data->y;
+      simple->bounds.x2 = image_data->x + image_data->width;
+      simple->bounds.y2 = image_data->y + image_data->height;
+
+      goo_canvas_item_simple_user_bounds_to_device (simple, cr,
+						    &simple->bounds);
+
+      /* Request a redraw of the new bounds. */
+      goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+
+      cairo_restore (cr);
+    }
+
+  *bounds = simple->bounds;
+}
+
+
+static void
+goo_canvas_image_paint (GooCanvasItem     *item,
+			cairo_t           *cr,
+			GooCanvasBounds   *bounds,
+			gdouble            scale)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasImage *image = (GooCanvasImage*) simple;
+  GooCanvasImageData *image_data = image->image_data;
+  cairo_matrix_t matrix;
+
+  if (!image_data->pattern)
+    return;
+
+  /* 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);
+
+  goo_canvas_style_set_fill_options (simple_data->style, cr);
+  cairo_set_source (cr, image_data->pattern);
+  cairo_matrix_init_translate (&matrix, -image_data->x, -image_data->y);
+  cairo_pattern_set_matrix (image_data->pattern, &matrix);
+  cairo_rectangle (cr, image_data->x, image_data->y,
+		   image_data->width, image_data->height);
+  cairo_fill (cr);
+
+  /* Using cairo_paint() is much slower, so I guess we shouldn't. */
+  /*cairo_paint (cr);*/
+
+  cairo_restore (cr);
+}
+
+
+static void
+goo_canvas_image_set_model    (GooCanvasItem      *item,
+			       GooCanvasItemModel *model)
+{
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+  GooCanvasItemIface *parent_iface = g_type_interface_peek_parent (iface);
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasImage *image = (GooCanvasImage*) item;
+  GooCanvasImageModel *emodel = (GooCanvasImageModel*) model;
+
+  /* If our data was allocated, free it. */
+  if (!simple->model)
+    {
+      cairo_pattern_destroy (image->image_data->pattern);
+      g_slice_free (GooCanvasImageData, image->image_data);
+    }
+
+  /* Now use the new model's data instead. */
+  image->image_data = &emodel->image_data;
+
+  /* Let the parent GooCanvasItemSimple code do the rest. */
+  parent_iface->set_model (item, model);
+}
+
+
+static void
+canvas_item_interface_init (GooCanvasItemIface *iface)
+{
+  iface->get_item_at = goo_canvas_image_get_item_at;
+  iface->update      = goo_canvas_image_update;
+  iface->paint       = goo_canvas_image_paint;
+  iface->set_model   = goo_canvas_image_set_model;
+}
+
+
+
+/*
+ * GooCanvasImageModel.
+ */
+
+static void item_model_interface_init (GooCanvasItemModelIface *iface);
+static void goo_canvas_image_model_finalize     (GObject            *object);
+static void goo_canvas_image_model_get_property (GObject            *object,
+						 guint               param_id,
+						 GValue             *value,
+						 GParamSpec         *pspec);
+static void goo_canvas_image_model_set_property (GObject            *object,
+						 guint               param_id,
+						 const GValue       *value,
+						 GParamSpec         *pspec);
+
+G_DEFINE_TYPE_WITH_CODE (GooCanvasImageModel, goo_canvas_image_model,
+			 GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE,
+			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM_MODEL,
+						item_model_interface_init))
+
+
+static void
+goo_canvas_image_model_class_init (GooCanvasImageModelClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+
+  gobject_class->finalize     = goo_canvas_image_model_finalize;
+
+  gobject_class->get_property = goo_canvas_image_model_get_property;
+  gobject_class->set_property = goo_canvas_image_model_set_property;
+
+  goo_canvas_image_install_common_properties (gobject_class);
+}
+
+
+static void
+goo_canvas_image_model_init (GooCanvasImageModel *emodel)
+{
+
+}
+
+
+GooCanvasItemModel*
+goo_canvas_image_model_new (GooCanvasItemModel *parent,
+			    GdkPixbuf          *pixbuf,
+			    gdouble             x,
+			    gdouble             y,
+			    ...)
+{
+  GooCanvasItemModel *model;
+  GooCanvasImageModel *imodel;
+  GooCanvasImageData *image_data;
+  const char *first_property;
+  va_list var_args;
+
+  model = g_object_new (GOO_TYPE_CANVAS_IMAGE_MODEL, NULL);
+  imodel = (GooCanvasImageModel*) model;
+
+  image_data = &imodel->image_data;
+  image_data->x = x;
+  image_data->y = y;
+
+  if (pixbuf)
+    {
+      image_data->pattern = goo_canvas_cairo_pattern_from_pixbuf (pixbuf);
+      image_data->width = gdk_pixbuf_get_width (pixbuf);
+      image_data->height = gdk_pixbuf_get_height (pixbuf);
+    }
+
+  va_start (var_args, y);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist ((GObject*) model, first_property, var_args);
+  va_end (var_args);
+
+  if (parent)
+    {
+      goo_canvas_item_model_add_child (parent, model, -1);
+      g_object_unref (model);
+    }
+
+  return model;
+}
+
+
+static void
+goo_canvas_image_model_finalize (GObject *object)
+{
+  GooCanvasImageModel *imodel = (GooCanvasImageModel*) object;
+
+  cairo_pattern_destroy (imodel->image_data.pattern);
+
+  G_OBJECT_CLASS (goo_canvas_image_model_parent_class)->finalize (object);
+}
+
+
+static void
+goo_canvas_image_model_get_property (GObject              *object,
+				     guint                 prop_id,
+				     GValue               *value,
+				     GParamSpec           *pspec)
+{
+  GooCanvasImageModel *imodel = (GooCanvasImageModel*) object;
+
+  goo_canvas_image_get_common_property (object, &imodel->image_data, prop_id,
+					value, pspec);
+}
+
+
+static void
+goo_canvas_image_model_set_property (GObject              *object,
+				     guint                 prop_id,
+				     const GValue         *value,
+				     GParamSpec           *pspec)
+{
+  GooCanvasImageModel *imodel = (GooCanvasImageModel*) object;
+
+  goo_canvas_image_set_common_property (object, &imodel->image_data, prop_id,
+					value, pspec);
+  g_signal_emit_by_name (imodel, "changed", TRUE);
+}
+
+
+static GooCanvasItem*
+goo_canvas_image_model_create_item (GooCanvasItemModel *model,
+				    GooCanvas          *canvas)
+{
+  GooCanvasItem *item;
+
+  item = g_object_new (GOO_TYPE_CANVAS_IMAGE, NULL);
+  goo_canvas_item_set_model (item, model);
+
+  return item;
+}
+
+
+static void
+item_model_interface_init (GooCanvasItemModelIface *iface)
+{
+  iface->create_item    = goo_canvas_image_model_create_item;
+}
+

Index: goocanvasimage.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasimage.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- goocanvasimage.h	13 Apr 2006 16:06:04 -0000	1.2
+++ goocanvasimage.h	29 Nov 2006 18:40:53 -0000	1.3
@@ -13,6 +13,16 @@
 G_BEGIN_DECLS
 
 
+/* This is the data used by both model and view classes. */
+typedef struct _GooCanvasImageData   GooCanvasImageData;
+struct _GooCanvasImageData
+{
+  cairo_pattern_t *pattern;
+
+  gdouble x, y, width, height;
+};
+
+
 #define GOO_TYPE_CANVAS_IMAGE            (goo_canvas_image_get_type ())
 #define GOO_CANVAS_IMAGE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_IMAGE, GooCanvasImage))
 #define GOO_CANVAS_IMAGE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_IMAGE, GooCanvasImageClass))
@@ -31,11 +41,9 @@
  */
 struct _GooCanvasImage
 {
-  GooCanvasItemSimple parent;
-
-  cairo_pattern_t *pattern;
+  GooCanvasItemSimple parent_object;
 
-  gdouble x, y, width, height;
+  GooCanvasImageData *image_data;
 };
 
 struct _GooCanvasImageClass
@@ -44,13 +52,52 @@
 };
 
 
-GType           goo_canvas_image_get_type          (void) G_GNUC_CONST;
-GooCanvasItem*  goo_canvas_image_new               (GooCanvasItem *parent,
-						    GdkPixbuf     *pixbuf,
-						    gdouble        x,
-						    gdouble        y,
-						    const gchar   *first_property,
-						    ...);
+GType               goo_canvas_image_get_type  (void) G_GNUC_CONST;
+
+GooCanvasItem*      goo_canvas_image_new       (GooCanvasItem      *parent,
+						GdkPixbuf          *pixbuf,
+						gdouble             x,
+						gdouble             y,
+						...);
+
+
+
+#define GOO_TYPE_CANVAS_IMAGE_MODEL            (goo_canvas_image_model_get_type ())
+#define GOO_CANVAS_IMAGE_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_IMAGE_MODEL, GooCanvasImageModel))
+#define GOO_CANVAS_IMAGE_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_IMAGE_MODEL, GooCanvasImageModelClass))
+#define GOO_IS_CANVAS_IMAGE_MODEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_IMAGE_MODEL))
+#define GOO_IS_CANVAS_IMAGE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_IMAGE_MODEL))
+#define GOO_CANVAS_IMAGE_MODEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_IMAGE_MODEL, GooCanvasImageModelClass))
+
+
+typedef struct _GooCanvasImageModel       GooCanvasImageModel;
+typedef struct _GooCanvasImageModelClass  GooCanvasImageModelClass;
+
+/**
+ * GooCanvasImageModel
+ *
+ * The #GooCanvasImageModel-struct struct contains private data only.
+ */
+struct _GooCanvasImageModel
+{
+  GooCanvasItemModelSimple parent_object;
+
+  GooCanvasImageData image_data;
+};
+
+struct _GooCanvasImageModelClass
+{
+  GooCanvasItemModelSimpleClass parent_class;
+};
+
+
+GType               goo_canvas_image_model_get_type  (void) G_GNUC_CONST;
+
+GooCanvasItemModel* goo_canvas_image_model_new (GooCanvasItemModel *parent,
+						GdkPixbuf          *pixbuf,
+						gdouble             x,
+						gdouble             y,
+						...);
 
 
 G_END_DECLS

--- goocanvasimageview.c DELETED ---

--- goocanvasimageview.h DELETED ---

Index: goocanvasitem.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasitem.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- goocanvasitem.c	12 Oct 2006 12:53:47 -0000	1.10
+++ goocanvasitem.c	29 Nov 2006 18:40:53 -0000	1.11
@@ -16,21 +16,37 @@
 #include <config.h>
 #include <math.h>
 #include <glib/gi18n-lib.h>
+#include <gobject/gobjectnotifyqueue.c>
+#include <gobject/gvaluecollector.h>
 #include <gtk/gtk.h>
 #include "goocanvasprivate.h"
-#include <goocanvasenumtypes.h>
 #include "goocanvasitem.h"
+#include "goocanvas.h"
 #include "goocanvasutils.h"
[...1157 lines suppressed...]
+ *           freed with g_free().
+ *
+ * Returns all child properties of a canvas item class.
+ */
+GParamSpec**
+goo_canvas_item_class_list_child_properties (GObjectClass *iclass,
+					     guint        *n_properties)
+{
+  GParamSpec **pspecs;
+  guint n;
+
+  g_return_val_if_fail (G_IS_OBJECT_CLASS (iclass), NULL);
+
+  pspecs = g_param_spec_pool_list (_goo_canvas_item_child_property_pool,
+				   G_OBJECT_CLASS_TYPE (iclass), &n);
+  if (n_properties)
+    *n_properties = n;
+
+  return pspecs;
+}

Index: goocanvasitem.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasitem.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- goocanvasitem.h	19 Jul 2006 13:52:33 -0000	1.7
+++ goocanvasitem.h	29 Nov 2006 18:40:53 -0000	1.8
@@ -8,6 +8,7 @@
 #define __GOO_CANVAS_ITEM_H__
 
 #include <gtk/gtk.h>
+#include "goocanvasstyle.h"
 
 G_BEGIN_DECLS
 
@@ -57,9 +58,8 @@
 
 
 /* Workaround for circular dependencies. Include this file first. */
-typedef struct _GooCanvasModel      GooCanvasModel;
-typedef struct _GooCanvasView       GooCanvasView;
-typedef struct _GooCanvasItemView   GooCanvasItemView;
+typedef struct _GooCanvas           GooCanvas;
+typedef struct _GooCanvasItemModel  GooCanvasItemModel;
 
 
 /**
@@ -89,117 +89,233 @@
 
   /*< public >*/
   /* Virtual methods that group items must implement. */
-  GooCanvasModel*      (* get_model)	   (GooCanvasItem       *item);
-  gint		       (* get_n_children)  (GooCanvasItem       *group);
-  GooCanvasItem*       (* get_child)	   (GooCanvasItem       *group,
+  GooCanvas*           (* get_canvas)	   (GooCanvasItem       *item);
+  void                 (* set_canvas)	   (GooCanvasItem       *item,
+					    GooCanvas           *canvas);
+  gint		       (* get_n_children)  (GooCanvasItem       *item);
+  GooCanvasItem*       (* get_child)	   (GooCanvasItem       *item,
 					    gint                 child_num);
+  void                 (* request_update)  (GooCanvasItem       *item);
 
   /* Virtual methods that group items may implement. */
-  void                 (* add_child)       (GooCanvasItem       *group,
+  void                 (* add_child)       (GooCanvasItem       *item,
 					    GooCanvasItem       *child,
 					    gint                 position);
-  void                 (* move_child)      (GooCanvasItem       *group,
+  void                 (* move_child)      (GooCanvasItem       *item,
 					    gint                 old_position,
 					    gint                 new_position);
-  void                 (* remove_child)    (GooCanvasItem       *group,
+  void                 (* remove_child)    (GooCanvasItem       *item,
 					    gint                 child_num);
+  void                 (*get_child_property) (GooCanvasItem     *item,
+					      GooCanvasItem     *child,
+					      guint              property_id,
+					      GValue            *value,
+					      GParamSpec        *pspec);
+  void                 (*set_child_property) (GooCanvasItem     *item,
+					      GooCanvasItem     *child,
+					      guint              property_id,
+					      const GValue      *value,
+					      GParamSpec        *pspec);
 
   /* Virtual methods that all canvas items must implement. */
-  GooCanvasItem*       (* get_parent)	  (GooCanvasItem       *item);
-  void                 (* set_parent)	  (GooCanvasItem       *item,
-					   GooCanvasItem       *parent);
+  GooCanvasItem*       (* get_parent)	   (GooCanvasItem       *item);
+  void                 (* set_parent)	   (GooCanvasItem       *item,
+					    GooCanvasItem       *parent);
+  void                 (* get_bounds)	   (GooCanvasItem	*item,
+					    GooCanvasBounds     *bounds);
+  GooCanvasItem*       (* get_item_at)	   (GooCanvasItem	*item,
+					    gdouble              x,
+					    gdouble              y,
+					    cairo_t             *cr,
+					    gboolean             is_pointer_event,
+					    gboolean             parent_is_visible);
+  void                 (* update)          (GooCanvasItem	*item,
+					    gboolean             entire_tree,
+					    cairo_t             *cr,
+					    GooCanvasBounds     *bounds);
+  void		       (* paint)	   (GooCanvasItem	*item,
+					    cairo_t             *cr,
+					    GooCanvasBounds     *bounds,
+					    gdouble              scale);
 
-  cairo_matrix_t*      (* get_transform)  (GooCanvasItem       *item);
-  void                 (* set_transform)  (GooCanvasItem       *item,
-					   cairo_matrix_t      *matrix);
+  /* Virtual methods that canvas items may implement. */
+  cairo_matrix_t*      (* get_transform)   (GooCanvasItem       *item);
+  void                 (* set_transform)   (GooCanvasItem       *item,
+					    cairo_matrix_t      *matrix);
+  GooCanvasStyle*      (* get_style)       (GooCanvasItem       *item);
+  void                 (* set_style)       (GooCanvasItem       *item,
+					    GooCanvasStyle      *style);
+  gboolean             (* is_visible)	   (GooCanvasItem	*item);
+
+  /* Virtual methods that model/view items must implement. */
+  GooCanvasItemModel*  (* get_model)	    (GooCanvasItem      *item);
+  void                 (* set_model)	    (GooCanvasItem      *item,
+					     GooCanvasItemModel *model);
 
-  GooCanvasItemView*   (* create_view)	  (GooCanvasItem       *item,
-					   GooCanvasView       *canvas_view,
-					   GooCanvasItemView   *parent_view);
 
   /* Signals. */
-  void                 (* child_added)	  (GooCanvasItem      *item,
-					   gint                child_num);
-  void                 (* child_moved)	  (GooCanvasItem      *item,
-					   gint                old_child_num,
-					   gint                new_child_num);
-  void                 (* child_removed)  (GooCanvasItem      *item,
-					   gint                child_num);
-  void                 (* changed)	  (GooCanvasItem      *item,
-					   gboolean            recompute_bounds);
+  gboolean	       (* enter_notify_event)	(GooCanvasItem       *item,
+						 GooCanvasItem       *target,
+						 GdkEventCrossing    *event);
+  gboolean	       (* leave_notify_event)	(GooCanvasItem       *item,
+						 GooCanvasItem       *target,
+						 GdkEventCrossing    *event);
+  gboolean	       (* motion_notify_event)	(GooCanvasItem       *item,
+						 GooCanvasItem       *target,
+						 GdkEventMotion      *event);
+  gboolean	       (* button_press_event)	(GooCanvasItem       *item,
+						 GooCanvasItem       *target,
+						 GdkEventButton      *event);
+  gboolean	       (* button_release_event)	(GooCanvasItem       *item,
+						 GooCanvasItem       *target,
+						 GdkEventButton      *event);
+  gboolean	       (* focus_in_event)	(GooCanvasItem       *item,
+						 GooCanvasItem       *target,
+						 GdkEventFocus       *event);
+  gboolean	       (* focus_out_event)	(GooCanvasItem       *item,
+						 GooCanvasItem       *target,
+						 GdkEventFocus       *event);
+  gboolean	       (* key_press_event)	(GooCanvasItem       *item,
+						 GooCanvasItem       *target,
+						 GdkEventKey         *event);
+  gboolean	       (* key_release_event)	(GooCanvasItem       *item,
+						 GooCanvasItem       *target,
+						 GdkEventKey         *event);
+  gboolean	       (* grab_broken_event)	(GooCanvasItem       *item,
+						 GooCanvasItem       *target,
+						 GdkEventGrabBroken  *event);
+  void                 (* child_notify)         (GooCanvasItem       *item,
+						 GParamSpec          *pspec);
 };
 
 
-GType                goo_canvas_item_get_type       (void) G_GNUC_CONST;
+GType              goo_canvas_item_get_type       (void) G_GNUC_CONST;
 
-GooCanvasItem *      goo_canvas_item_new	    (GooCanvasItem *parent,
-						     GType          type,
-						     const gchar   *first_property,
-						     ...);
 
 /*
  * Group functions - these should only be called on container items.
  */
-gint                 goo_canvas_item_get_n_children (GooCanvasItem *group);
-GooCanvasItem*       goo_canvas_item_get_child      (GooCanvasItem *group,
-						     gint           child_num);
-void                 goo_canvas_item_add_child      (GooCanvasItem *group,
-						     GooCanvasItem *item,
-						     gint           position);
-void                 goo_canvas_item_move_child     (GooCanvasItem *group,
-						     gint           old_position,
-						     gint           new_position);
-void                 goo_canvas_item_remove_child   (GooCanvasItem *group,
-						     gint           child_num);
-gint                 goo_canvas_item_find_child     (GooCanvasItem *group,
-						     GooCanvasItem *child);
+gint               goo_canvas_item_get_n_children (GooCanvasItem   *item);
+GooCanvasItem*     goo_canvas_item_get_child      (GooCanvasItem   *item,
+						   gint             child_num);
+gint               goo_canvas_item_find_child     (GooCanvasItem   *item,
+						   GooCanvasItem   *child);
+void               goo_canvas_item_add_child      (GooCanvasItem   *item,
+						   GooCanvasItem   *child,
+						   gint             position);
+void               goo_canvas_item_move_child     (GooCanvasItem   *item,
+						   gint             old_position,
+						   gint             new_position);
+void               goo_canvas_item_remove_child   (GooCanvasItem   *item,
+						   gint             child_num);
+
+void  goo_canvas_item_get_child_properties        (GooCanvasItem   *item,
+						   GooCanvasItem   *child,
+						   ...) G_GNUC_NULL_TERMINATED;
+void  goo_canvas_item_set_child_properties        (GooCanvasItem   *item,
+						   GooCanvasItem   *child,
+						   ...) G_GNUC_NULL_TERMINATED;
+void  goo_canvas_item_get_child_properties_valist (GooCanvasItem   *item,
+						   GooCanvasItem   *child,
+						   va_list	    var_args);
+void  goo_canvas_item_set_child_properties_valist (GooCanvasItem   *item,
+						   GooCanvasItem   *child,
+						   va_list	    var_args);
+
 
 /*
  * Item functions - these are safe to call on all items.
  */
-GooCanvasModel*      goo_canvas_item_get_model      (GooCanvasItem *item);
-GooCanvasItem*       goo_canvas_item_get_parent     (GooCanvasItem *item);
-void                 goo_canvas_item_set_parent	    (GooCanvasItem *item,
-						     GooCanvasItem *parent);
-gboolean             goo_canvas_item_is_container   (GooCanvasItem *item);
+GooCanvas*         goo_canvas_item_get_canvas     (GooCanvasItem   *item);
+void               goo_canvas_item_set_canvas     (GooCanvasItem   *item,
+						   GooCanvas       *canvas);
+GooCanvasItem*     goo_canvas_item_get_parent     (GooCanvasItem   *item);
+void               goo_canvas_item_set_parent	  (GooCanvasItem   *item,
+						   GooCanvasItem   *parent);
+gboolean           goo_canvas_item_is_container   (GooCanvasItem   *item);
 
-void                 goo_canvas_item_raise          (GooCanvasItem *item,
-						     GooCanvasItem *above);
-void                 goo_canvas_item_lower          (GooCanvasItem *item,
-						     GooCanvasItem *below);
+void               goo_canvas_item_raise          (GooCanvasItem   *item,
+						   GooCanvasItem   *above);
+void               goo_canvas_item_lower          (GooCanvasItem   *item,
+						   GooCanvasItem   *below);
 
-cairo_matrix_t*      goo_canvas_item_get_transform  (GooCanvasItem *item);
-void                 goo_canvas_item_set_transform  (GooCanvasItem *item,
-						     cairo_matrix_t *matrix);
+cairo_matrix_t*    goo_canvas_item_get_transform  (GooCanvasItem   *item);
+void               goo_canvas_item_set_transform  (GooCanvasItem   *item,
+						   cairo_matrix_t  *matrix);
+
+void               goo_canvas_item_translate      (GooCanvasItem   *item,
+						   double           tx,
+						   double           ty);
+void               goo_canvas_item_scale          (GooCanvasItem   *item,
+						   double           sx,
+						   double           sy);
+void               goo_canvas_item_rotate         (GooCanvasItem   *item,
+						   double           degrees,
+						   double           cx,
+						   double           cy);
+void               goo_canvas_item_skew_x         (GooCanvasItem   *item,
+						   double           degrees,
+						   double           cx,
+						   double           cy);
+void               goo_canvas_item_skew_y         (GooCanvasItem   *item,
+						   double           degrees,
+						   double           cx,
+						   double           cy);
+
+GooCanvasStyle*    goo_canvas_item_get_style      (GooCanvasItem   *item);
+void               goo_canvas_item_set_style      (GooCanvasItem   *item,
+						   GooCanvasStyle  *style);
+
+void               goo_canvas_item_animate        (GooCanvasItem   *item,
+						   double           x,
+						   double           y,
+						   double           scale,
+						   double           degrees,
+						   gint             duration,
+						   gint             step_time,
+						   GooCanvasAnimateType type);
+void               goo_canvas_item_stop_animation (GooCanvasItem   *item);
+
+
+
+void               goo_canvas_item_get_bounds	  (GooCanvasItem   *item,
+						   GooCanvasBounds *bounds);
+GooCanvasItem*	   goo_canvas_item_get_item_at    (GooCanvasItem   *item,
+						   gdouble          x,
+						   gdouble          y,
+						   cairo_t         *cr,
+						   gboolean         is_pointer_event,
+						   gboolean         parent_is_visible);
+gboolean           goo_canvas_item_is_visible     (GooCanvasItem   *item);
+
+GooCanvasItemModel* goo_canvas_item_get_model	  (GooCanvasItem      *item);
+void                goo_canvas_item_set_model	  (GooCanvasItem      *item,
+						   GooCanvasItemModel *model);
+
+void               goo_canvas_item_request_update (GooCanvasItem   *item);
+void		   goo_canvas_item_ensure_updated (GooCanvasItem   *item);
+void               goo_canvas_item_update         (GooCanvasItem   *item,
+						   gboolean         entire_tree,
+						   cairo_t         *cr,
+						   GooCanvasBounds *bounds);
+void               goo_canvas_item_paint          (GooCanvasItem   *item,
+						   cairo_t         *cr,
+						   GooCanvasBounds *bounds,
+						   gdouble          scale);
+
+
+/*
+ * Functions to support child properties when implementing new canvas items.
+ */
+void         goo_canvas_item_class_install_child_property (GObjectClass *iclass,
+							   guint	 property_id,
+							   GParamSpec	*pspec);
+GParamSpec*  goo_canvas_item_class_find_child_property	  (GObjectClass	*iclass,
+							   const gchar	*property_name);
+GParamSpec** goo_canvas_item_class_list_child_properties  (GObjectClass	*iclass,
+							   guint	*n_properties);
 
-void                 goo_canvas_item_translate      (GooCanvasItem *item,
-						     double         tx,
-						     double         ty);
-void                 goo_canvas_item_scale          (GooCanvasItem *item,
-						     double         sx,
-						     double         sy);
-void                 goo_canvas_item_rotate         (GooCanvasItem *item,
-						     double         degrees,
-						     double         cx,
-						     double         cy);
-void                 goo_canvas_item_skew_x         (GooCanvasItem *item,
-						     double         degrees,
-						     double         cx,
-						     double         cy);
-void                 goo_canvas_item_skew_y         (GooCanvasItem *item,
-						     double         degrees,
-						     double         cx,
-						     double         cy);
 
-void                 goo_canvas_item_animate        (GooCanvasItem *item,
-						     double         x,
-						     double         y,
-						     double         scale,
-						     double         degrees,
-						     gint           duration,
-						     gint           step_time,
-						     GooCanvasAnimateType type);
-void                 goo_canvas_item_stop_animation (GooCanvasItem *item);
 
 
 G_END_DECLS

Index: goocanvasitemsimple.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasitemsimple.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- goocanvasitemsimple.c	15 Aug 2006 10:08:25 -0000	1.14
+++ goocanvasitemsimple.c	29 Nov 2006 18:40:53 -0000	1.15
@@ -1,29 +1,30 @@
 /*
- * GooCanvas. Copyright (C) 2005 Damon Chaplin.
+ * GooCanvas. Copyright (C) 2005-6 Damon Chaplin.
  * Released under the GNU LGPL license. See COPYING for details.
  *
- * goocanvasitemsimple.c - abstract base class for simple items with styles.
+ * goocanvasitemsimple.c - abstract base class for simple item views.
  */
 
 /**
  * SECTION:goocanvasitemsimple
[...1690 lines suppressed...]
+  else
+    {
+      simple_data->style = NULL;
+      simple_data->own_style = FALSE;
+    }
+
+  g_signal_emit_by_name (smodel, "changed", TRUE);
+}
+
+
+static void
+item_model_interface_init  (GooCanvasItemModelIface *iface)
+{
+  iface->get_parent     = goo_canvas_item_model_simple_get_parent;
+  iface->set_parent     = goo_canvas_item_model_simple_set_parent;
+  iface->get_transform  = goo_canvas_item_model_simple_get_transform;
+  iface->set_transform  = goo_canvas_item_model_simple_set_transform;
+  iface->get_style      = goo_canvas_item_model_simple_get_style;
+  iface->set_style      = goo_canvas_item_model_simple_set_style;
+}

Index: goocanvasitemsimple.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasitemsimple.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- goocanvasitemsimple.h	8 Jun 2006 08:45:27 -0000	1.10
+++ goocanvasitemsimple.h	29 Nov 2006 18:40:53 -0000	1.11
@@ -1,105 +1,49 @@
 /*
- * GooCanvas. Copyright (C) 2005 Damon Chaplin.
+ * GooCanvas. Copyright (C) 2005-6 Damon Chaplin.
  * Released under the GNU LGPL license. See COPYING for details.
  *
- * goocanvasitemsimple.h - abstract base class for simple items with styles.
+ * goocanvasitemsimple.h - abstract base class for simple items.
  */
 #ifndef __GOO_CANVAS_ITEM_SIMPLE_H__
 #define __GOO_CANVAS_ITEM_SIMPLE_H__
 
 #include <gtk/gtk.h>
 #include "goocanvasitem.h"
+#include "goocanvasitemmodel.h"
+#include "goocanvasstyle.h"
 #include "goocanvasutils.h"
 
 G_BEGIN_DECLS
 
 
-/**
- * GooCanvasStyleValuesMask
- * @GOO_CANVAS_STYLE_STROKE_PATTERN: the stroke pattern has been set.
- * @GOO_CANVAS_STYLE_FILL_PATTERN: the fill pattern has been set.
- * @GOO_CANVAS_STYLE_FILL_RULE: the fill rule has been set.
- * @GOO_CANVAS_STYLE_OPERATOR: the operator has been set.
- * @GOO_CANVAS_STYLE_ANTIALIAS: the antialias setting has been set.
- * @GOO_CANVAS_STYLE_LINE_WIDTH: the line width has been set.
- * @GOO_CANVAS_STYLE_LINE_CAP: the line cap style has been set.
- * @GOO_CANVAS_STYLE_LINE_JOIN: the line join style has been set.
- * @GOO_CANVAS_STYLE_LINE_JOIN_MITER_LIMIT: the miter limit of line joins has
- *  been set.
- * @GOO_CANVAS_STYLE_LINE_DASH: the line dash pattern has been set.
- *
- * Specifies which fields of a #GooCanvasStyle object have been set.
- */
-typedef enum
+/* This is the data used by both model and view classes. */
+typedef struct _GooCanvasItemSimpleData   GooCanvasItemSimpleData;
+struct _GooCanvasItemSimpleData
 {
-  GOO_CANVAS_STYLE_STROKE_PATTERN	 = 1 << 0,
-  GOO_CANVAS_STYLE_FILL_PATTERN		 = 1 << 1,
-  GOO_CANVAS_STYLE_FILL_RULE		 = 1 << 2,
-  GOO_CANVAS_STYLE_OPERATOR		 = 1 << 3,
-  GOO_CANVAS_STYLE_ANTIALIAS		 = 1 << 4,
-
-  GOO_CANVAS_STYLE_LINE_WIDTH		 = 1 << 5,
-  GOO_CANVAS_STYLE_LINE_CAP		 = 1 << 6,
-  GOO_CANVAS_STYLE_LINE_JOIN		 = 1 << 7,
-  GOO_CANVAS_STYLE_LINE_JOIN_MITER_LIMIT = 1 << 8,
-  GOO_CANVAS_STYLE_LINE_DASH		 = 1 << 9
-} GooCanvasStyleValuesMask;
-
+  /* The style to draw with. */
+  GooCanvasStyle *style;
 
-/* These are the standard cairo drawing attributes. We allow the style to
-   be shared between multiple objects to avoid wasting memory. */
-/**
- * GooCanvasStyle
- * @ref_count: the reference count of the struct.
- * @mask: a mask specifying which fields of the #GooCanvasStyle have been set.
- * @stroke_pattern: the stroke pattern (or color).
- * @fill_pattern: the fill pattern (or color).
- * @line_width: the line width.
- * @line_join_miter_limit: the minimum angle in degrees at which the miter
- *  join style will be used. For smaller angles a bevel join is used instead.
- * @dash: the dash pattern.
- * @fill_rule: the fill rule.
- * @op: the drawing operator.
- * @antialias: the type of antialiasing to do.
- * @line_cap: the line cap style.
- * @line_join: the line join style.
- *
- * #GooCanvasStyle describes the style in which an item is to be drawn, e.g.
- * its stroke and fill colors or patterns, and its line width and style.
- */
-typedef struct _GooCanvasStyle GooCanvasStyle;
-struct _GooCanvasStyle
-{
-  int ref_count;
+  /* The transformation matrix of the item, or NULL. */
+  cairo_matrix_t *transform;
 
-  /* This specifies which fields are actually set. If the STROKE_PATTERN bit
-     is set, and stroke_pattern is NULL, no stroke will be drawn. */
-  GooCanvasStyleValuesMask mask;
+  /* If visibility is VISIBLE_ABOVE_THRESHOLD the item is visible if the canvas
+     scale setting is above this threshold (or equal to it). */
+  gdouble visibility_threshold;
 
-  cairo_pattern_t *stroke_pattern;
-  cairo_pattern_t *fill_pattern;
+  /* Whether the item is visible, invisible, or visible above a given scale. */
+  GooCanvasItemVisibility visibility	: 2;
 
-  double line_width, line_join_miter_limit;
+  /* What events the item should receive. */
+  GooCanvasPointerEvents pointer_events : 4;
 
-  GooCanvasLineDash *dash;
+  /* If the item can take the keyboard focus. */
+  guint can_focus                       : 1;
 
-  /* We use bitmasks here to cut down on memory use a bit. I've given each
-     field a few bits more than it needs to allow for new values. */
-  cairo_fill_rule_t fill_rule       : 3;
-  cairo_operator_t  op              : 6;
-  cairo_antialias_t antialias       : 4;
-  cairo_line_cap_t  line_cap        : 4;
-  cairo_line_join_t line_join       : 4;
+  /* If the item has its own style, rather than using its parents. */
+  guint own_style                       : 1;
 };
 
 
-#define GOO_TYPE_CANVAS_STYLE (goo_canvas_style_get_type ())
-GType           goo_canvas_style_get_type (void);
-GooCanvasStyle* goo_canvas_style_new	  (void);
-GooCanvasStyle* goo_canvas_style_ref	  (GooCanvasStyle *style);
-void            goo_canvas_style_unref	  (GooCanvasStyle *style);
-
-
 #define GOO_TYPE_CANVAS_ITEM_SIMPLE            (goo_canvas_item_simple_get_type ())
 #define GOO_CANVAS_ITEM_SIMPLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_ITEM_SIMPLE, GooCanvasItemSimple))
 #define GOO_CANVAS_ITEM_SIMPLE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_ITEM_SIMPLE, GooCanvasItemSimpleClass))
@@ -111,6 +55,8 @@
 typedef struct _GooCanvasItemSimple       GooCanvasItemSimple;
 typedef struct _GooCanvasItemSimpleClass  GooCanvasItemSimpleClass;
 
+typedef struct _GooCanvasItemModelSimple       GooCanvasItemModelSimple;
+
 /**
  * GooCanvasItemSimple
  *
@@ -120,59 +66,101 @@
 {
   GObject parent_object;
 
+  /* The canvas. */
+  GooCanvas *canvas;
+
   /* The parent item. */
   GooCanvasItem *parent;
 
-  /* The style to draw with. */
-  GooCanvasStyle *style;
-
-  /* The transformation matrix, or NULL. */
-  cairo_matrix_t *transform;
+  /* The model, if the canvas is in model/view mode, or NULL. */
+  GooCanvasItemModelSimple *model;
 
-  /* Whether the item is visible, invisible, or visible above a given scale. */
-  GooCanvasItemVisibility visibility;
+  /* The data shared between the model & view classes. */
+  GooCanvasItemSimpleData *simple_data;
 
-  /* If visibility is VISIBLE_ABOVE_THRESHOLD the item is visible if the canvas
-     scale setting is above this threshold (or equal to it). */
-  gdouble visibility_threshold;
+  /* The bounds of the item, relative to the entire canvas. */
+  GooCanvasBounds bounds;
 
-  /* What events the item should receive. */
-  GooCanvasPointerEvents pointer_events;
+  /* If the item needs to recompute its bounds and redraw. */
+  guint	need_update : 1;
 
-  /* The title and description of the item for accessibility. */
-  gchar *title;
-  gchar *description;
+  /* If all descendants need to be updated. */
+  guint need_entire_subtree_update      : 1;
 };
 
 struct _GooCanvasItemSimpleClass
 {
   GObjectClass parent_class;
+
+  /* Virtual methods. */
+  void		(* create_path)			   (GooCanvasItemSimple *item,
+						    cairo_t             *cr);
 };
 
 
-GType          goo_canvas_item_simple_get_type    (void) G_GNUC_CONST;
+GType    goo_canvas_item_simple_get_type	   (void) G_GNUC_CONST;
 
-void           goo_canvas_item_simple_set_style	  (GooCanvasItemSimple *item,
-						   GooCanvasStyle      *style);
 
+void     goo_canvas_item_simple_get_path_bounds	   (GooCanvasItemSimple *item,
+						    cairo_t             *cr,
+						    GooCanvasBounds     *bounds);
+void     goo_canvas_item_simple_user_bounds_to_device (GooCanvasItemSimple *item,
+						       cairo_t             *cr,
+						       GooCanvasBounds     *bounds);
+gboolean goo_canvas_item_simple_check_in_path	   (GooCanvasItemSimple *item,
+						    gdouble              x,
+						    gdouble              y,
+						    cairo_t             *cr,
+						    GooCanvasPointerEvents pointer_events);
+void     goo_canvas_item_simple_paint_path	   (GooCanvasItemSimple *item,
+						    cairo_t             *cr);
 
-void           goo_canvas_item_simple_set_fill_options   (GooCanvasItemSimple *item,
-							  cairo_t             *cr);
-void           goo_canvas_item_simple_set_stroke_options (GooCanvasItemSimple *item,
-							  cairo_t             *cr);
-void           goo_canvas_item_simple_get_path_bounds (GooCanvasItemSimple *item,
-						       cairo_t           *cr,
-						       GooCanvasBounds  *bounds);
-void           goo_canvas_item_simple_user_bounds_to_device (GooCanvasItemSimple *item,
-							     cairo_t             *cr,
-							     GooCanvasBounds     *bounds);
-gboolean       goo_canvas_item_simple_check_in_path (GooCanvasItemSimple *item,
-						     gdouble              x,
-						     gdouble              y,
-						     cairo_t             *cr,
-						     GooCanvasPointerEvents pointer_events);
-void           goo_canvas_item_simple_paint_path    (GooCanvasItemSimple *item,
-						     cairo_t             *cr);
+void     goo_canvas_item_simple_changed            (GooCanvasItemSimple *item,
+						    gboolean             recompute_bounds);
+void     goo_canvas_item_simple_check_style        (GooCanvasItemSimple *item);
+
+
+
+
+
+#define GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE            (goo_canvas_item_model_simple_get_type ())
+#define GOO_CANVAS_ITEM_MODEL_SIMPLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE, GooCanvasItemModelSimple))
+#define GOO_CANVAS_ITEM_MODEL_SIMPLE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE, GooCanvasItemModelSimpleClass))
+#define GOO_IS_CANVAS_ITEM_MODEL_SIMPLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE))
+#define GOO_IS_CANVAS_ITEM_MODEL_SIMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE))
+#define GOO_CANVAS_ITEM_MODEL_SIMPLE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE, GooCanvasItemModelSimpleClass))
+
+
+typedef struct _GooCanvasItemModelSimpleClass  GooCanvasItemModelSimpleClass;
+
+/**
+ * GooCanvasItemModelSimple
+ *
+ * The #GooCanvasItemModelSimple-struct struct contains private data only.
+ */
+struct _GooCanvasItemModelSimple
+{
+  GObject parent_object;
+
+  /* The parent model. */
+  GooCanvasItemModel *parent;
+
+  /* The data shared between the model & view classes. */
+  GooCanvasItemSimpleData simple_data;
+
+  /* The title and description of the item for accessibility. */
+  gchar *title;
+  gchar *description;
+};
+
+
+struct _GooCanvasItemModelSimpleClass
+{
+  GObjectClass parent_class;
+};
+
+
+GType    goo_canvas_item_model_simple_get_type  (void) G_GNUC_CONST;
 
 
 G_END_DECLS

--- goocanvasitemview.c DELETED ---

--- goocanvasitemview.h DELETED ---

--- goocanvasitemviewsimple.c DELETED ---

--- goocanvasitemviewsimple.h DELETED ---

--- goocanvasmodel.c DELETED ---

--- goocanvasmodel.h DELETED ---

--- goocanvasmodelsimple.c DELETED ---

--- goocanvasmodelsimple.h DELETED ---

Index: goocanvaspath.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvaspath.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- goocanvaspath.c	12 Oct 2006 10:33:27 -0000	1.7
+++ goocanvaspath.c	29 Nov 2006 18:40:53 -0000	1.8
@@ -31,13 +31,13 @@
  *
  * To respond to events such as mouse clicks on the path you must connect
  * to the signal handlers of the corresponding #GooCanvasPathView objects.
- * (See goo_canvas_view_get_item_view() and #GooCanvasView::item-view-created.)
+ * (See goo_canvas_get_item_view() and #GooCanvasView::item-view-created.)
  */
 #include <config.h>
+#include <math.h>
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 #include "goocanvaspath.h"
-#include "goocanvaspathview.h"
 
 
 enum {
@@ -46,33 +46,28 @@
   PROP_DATA,
 };
 
-static void goo_canvas_path_finalize (GObject *object);
-static void item_interface_init (GooCanvasItemIface *iface);
-static void goo_canvas_path_get_property (GObject            *object,
-					  guint               param_id,
-					  GValue             *value,
-					  GParamSpec         *pspec);
-static void goo_canvas_path_set_property (GObject            *object,
-					  guint               param_id,
-					  const GValue       *value,
-					  GParamSpec         *pspec);
+static void canvas_item_interface_init   (GooCanvasItemIface  *iface);
+static void goo_canvas_path_finalize     (GObject             *object);
+static void goo_canvas_path_get_property (GObject             *object,
+					  guint                param_id,
+					  GValue              *value,
+					  GParamSpec          *pspec);
+static void goo_canvas_path_set_property (GObject             *object,
+					  guint                param_id,
+					  const GValue        *value,
+					  GParamSpec          *pspec);
+static void goo_canvas_path_create_path  (GooCanvasItemSimple *simple,
+					  cairo_t             *cr);
 
 G_DEFINE_TYPE_WITH_CODE (GooCanvasPath, goo_canvas_path,
 			 GOO_TYPE_CANVAS_ITEM_SIMPLE,
 			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
-						item_interface_init))
+						canvas_item_interface_init))
 
 
 static void
-goo_canvas_path_class_init (GooCanvasPathClass *klass)
+goo_canvas_path_install_common_properties (GObjectClass *gobject_class)
 {
-  GObjectClass *gobject_class = (GObjectClass*) klass;
-
-  gobject_class->finalize = goo_canvas_path_finalize;
-
-  gobject_class->get_property = goo_canvas_path_get_property;
-  gobject_class->set_property = goo_canvas_path_set_property;
-
   /**
    * GooCanvasPath:data
    *
@@ -90,38 +85,26 @@
 
 
 static void
-goo_canvas_path_init (GooCanvasPath *path)
+goo_canvas_path_class_init (GooCanvasPathClass *klass)
 {
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+  GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) klass;
 
-}
-
+  gobject_class->finalize     = goo_canvas_path_finalize;
 
-static void
-goo_canvas_path_finalize (GObject *object)
-{
-  GooCanvasPath *path = (GooCanvasPath*) object;
+  gobject_class->get_property = goo_canvas_path_get_property;
+  gobject_class->set_property = goo_canvas_path_set_property;
 
-  if (path->commands)
-    g_array_free (path->commands, TRUE);
+  simple_class->create_path = goo_canvas_path_create_path;
 
-  G_OBJECT_CLASS (goo_canvas_path_parent_class)->finalize (object);
+  goo_canvas_path_install_common_properties (gobject_class);
 }
 
 
 static void
-goo_canvas_path_get_property (GObject              *object,
-			      guint                 prop_id,
-			      GValue               *value,
-			      GParamSpec           *pspec)
+goo_canvas_path_init (GooCanvasPath *path)
 {
-  /*GooCanvasPath *path = (GooCanvasPath*) object;*/
-
-  switch (prop_id)
-    {
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
+  path->path_commands = g_array_new (0, 0, sizeof (GooCanvasPathCommand));
 }
 
 
@@ -186,18 +169,18 @@
 
 
 static void
-goo_canvas_path_parse_data (GooCanvasPath *path,
-			    const gchar   *path_data)
+goo_canvas_path_parse_data (GArray            *path_commands,
+			    const gchar       *path_data)
 {
   GooCanvasPathCommand cmd;
   gchar *pos, command = 0, next_command;
   gboolean error = FALSE;
 
-  /* Free the current path data. */
-  if (path->commands)
-    g_array_free (path->commands, TRUE);
+  /* Clear any current commands. */
+  g_array_set_size (path_commands, 0);
 
-  path->commands = g_array_new (0, 0, sizeof (GooCanvasPathCommand));
+  if (!path_data)
+    return;
 
   pos = (gchar*) path_data;
   for (;;)
@@ -338,50 +321,11 @@
       if (error)
 	return;
 
-      g_array_append_val (path->commands, cmd);
+      g_array_append_val (path_commands, cmd);
     }
 }
 
 
-static void
-goo_canvas_path_set_property (GObject              *object,
-			      guint                 prop_id,
-			      const GValue         *value,
-			      GParamSpec           *pspec)
-{
-  GooCanvasPath *path = (GooCanvasPath*) object;
-
-  switch (prop_id)
-    {
-    case PROP_DATA:
-      goo_canvas_path_parse_data (path, g_value_get_string (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
-  }
-
-  g_signal_emit_by_name (path, "changed", TRUE);
-}
-
-
-static GooCanvasItemView*
-goo_canvas_path_create_view (GooCanvasItem     *item,
-			     GooCanvasView     *canvas_view,
-			     GooCanvasItemView *parent_view)
-{
-  return goo_canvas_path_view_new (canvas_view, parent_view,
-				   (GooCanvasPath*) item);
-}
-
-
-static void
-item_interface_init (GooCanvasItemIface *iface)
-{
-  iface->create_view = goo_canvas_path_create_view;
-}
-
-
 /**
  * goo_canvas_path_new:
  * @parent: the parent item, or %NULL. If a parent is specified, it will assume
@@ -436,19 +380,18 @@
 {
   GooCanvasItem *item;
   GooCanvasPath *path;
+  const char *first_property;
   va_list var_args;
-  const char *first_arg_name;
 
   item = g_object_new (GOO_TYPE_CANVAS_PATH, NULL);
-  path = GOO_CANVAS_PATH (item);
+  path = (GooCanvasPath*) item;
 
-  goo_canvas_path_parse_data (path, path_data);
+  goo_canvas_path_parse_data (path->path_commands, path_data);
 
   va_start (var_args, path_data);
-
-  first_arg_name = va_arg (var_args, char*);
-  g_object_set_valist (G_OBJECT (item), first_arg_name, var_args);
-
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist ((GObject*) item, first_property, var_args);
   va_end (var_args);
 
   if (parent)
@@ -461,3 +404,668 @@
 }
 
 
+static void
+goo_canvas_path_finalize (GObject *object)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasPath *path = (GooCanvasPath*) object;
+
+  if (!simple->model)
+    g_array_free (path->path_commands, TRUE);
+  path->path_commands = NULL;
+
+  G_OBJECT_CLASS (goo_canvas_path_parent_class)->finalize (object);
+}
+
+
+static void
+goo_canvas_path_get_common_property (GObject              *object,
+				     GArray               *path_commands,
+				     guint                 prop_id,
+				     GValue               *value,
+				     GParamSpec           *pspec)
+{
+  switch (prop_id)
+    {
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+
+static void
+goo_canvas_path_get_property (GObject              *object,
+			      guint                 prop_id,
+			      GValue               *value,
+			      GParamSpec           *pspec)
+{
+  GooCanvasPath *path = (GooCanvasPath*) object;
+
+  goo_canvas_path_get_common_property (object, path->path_commands, prop_id,
+				       value, pspec);
+}
+
+
+static void
+goo_canvas_path_set_common_property (GObject              *object,
+				     GArray               *path_commands,
+				     guint                 prop_id,
+				     const GValue         *value,
+				     GParamSpec           *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_DATA:
+      goo_canvas_path_parse_data (path_commands, g_value_get_string (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+static void
+goo_canvas_path_set_property (GObject              *object,
+			      guint                 prop_id,
+			      const GValue         *value,
+			      GParamSpec           *pspec)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasPath *path = (GooCanvasPath*) object;
+
+  if (simple->model)
+    {
+      g_warning ("Can't set property of a canvas item with a model - set the model property instead");
+      return;
+    }
+
+  goo_canvas_path_set_common_property (object, path->path_commands, prop_id,
+				       value, pspec);
+  goo_canvas_item_simple_changed (simple, TRUE);
+}
+
+
+static void
+do_curve_to (GooCanvasPathCommand *cmd,
+	     cairo_t              *cr,
+	     gdouble              *x,
+	     gdouble              *y,
+	     gdouble              *last_control_point_x,
+	     gdouble              *last_control_point_y)
+{
+  if (cmd->curve.relative)
+    {
+      cairo_curve_to (cr, *x + cmd->curve.x1, *y + cmd->curve.y1,
+		      *x + cmd->curve.x2, *y + cmd->curve.y2,
+		      *x + cmd->curve.x, *y + cmd->curve.y);
+      *last_control_point_x = *x + cmd->curve.x2;
+      *last_control_point_y = *y + cmd->curve.y2;
+      *x += cmd->curve.x;
+      *y += cmd->curve.y;
+    }
+  else
+    {
+      cairo_curve_to (cr, cmd->curve.x1, cmd->curve.y1,
+		      cmd->curve.x2, cmd->curve.y2,
+		      cmd->curve.x, cmd->curve.y);
+      *last_control_point_x = cmd->curve.x2;
+      *last_control_point_y = cmd->curve.y2;
+      *x = cmd->curve.x;
+      *y = cmd->curve.y;
+    }
+}
+
+
+static void
+do_smooth_curve_to (GooCanvasPathCommand    *cmd,
+		    GooCanvasPathCommandType prev_cmd_type,
+		    cairo_t                 *cr,
+		    gdouble                 *x,
+		    gdouble                 *y,
+		    gdouble                 *last_control_point_x,
+		    gdouble                 *last_control_point_y)
+{
+  gdouble x1, y1;
+
+  /* If the last command was a curveto or smooth curveto, we use the
+     reflection of the last control point about the current point as
+     the first control point of this curve. Otherwise we use the
+     current point as the first control point. */
+  if (prev_cmd_type == GOO_CANVAS_PATH_CURVE_TO
+      || prev_cmd_type == GOO_CANVAS_PATH_SMOOTH_CURVE_TO)
+    {
+      x1 = *x + (*x - *last_control_point_x);
+      y1 = *y + (*y - *last_control_point_y);
+    }
+  else
+    {
+      x1 = *x;
+      y1 = *y;
+    }
+
+  if (cmd->curve.relative)
+    {
+      cairo_curve_to (cr, x1, y1, *x + cmd->curve.x2, *y + cmd->curve.y2,
+		      *x + cmd->curve.x, *y + cmd->curve.y);
+      *last_control_point_x = *x + cmd->curve.x2;
+      *last_control_point_y = *y + cmd->curve.y2;
+      *x += cmd->curve.x;
+      *y += cmd->curve.y;
+    }
+  else
+    {
+      cairo_curve_to (cr, x1, y1, cmd->curve.x2, cmd->curve.y2,
+		      cmd->curve.x, cmd->curve.y);
+      *last_control_point_x = cmd->curve.x2;
+      *last_control_point_y = cmd->curve.y2;
+      *x = cmd->curve.x;
+      *y = cmd->curve.y;
+    }
+}
+
+
+static void
+do_quadratic_curve_to (GooCanvasPathCommand *cmd,
+		       cairo_t              *cr,
+		       gdouble              *x,
+		       gdouble              *y,
+		       gdouble              *last_control_point_x,
+		       gdouble              *last_control_point_y)
+{
+  gdouble qx1, qy1, qx2, qy2, x1, y1, x2, y2;
+
+  if (cmd->curve.relative)
+    {
+      qx1 = *x + cmd->curve.x1;
+      qy1 = *y + cmd->curve.y1;
+      qx2 = *x + cmd->curve.x;
+      qy2 = *y + cmd->curve.y;
+    }
+  else
+    {
+      qx1 = cmd->curve.x1;
+      qy1 = cmd->curve.y1;
+      qx2 = cmd->curve.x;
+      qy2 = cmd->curve.y;
+    }
+
+  /* We need to convert the quadratic into a cubic bezier. */
+  x1 = *x + (qx1 - *x) * 2.0 / 3.0;
+  y1 = *y + (qy1 - *y) * 2.0 / 3.0;
+
+  x2 = x1 + (qx2 - *x) / 3.0;
+  y2 = y1 + (qy2 - *y) / 3.0;
+
+  cairo_curve_to (cr, x1, y1, x2, y2, qx2, qy2);
+
+  *x = qx2;
+  *y = qy2;
+  *last_control_point_x = qx1;
+  *last_control_point_y = qy1;
+}
+
+
+static void
+do_smooth_quadratic_curve_to (GooCanvasPathCommand    *cmd,
+			      GooCanvasPathCommandType prev_cmd_type,
+			      cairo_t                 *cr,
+			      gdouble                 *x,
+			      gdouble                 *y,
+			      gdouble                 *last_control_point_x,
+			      gdouble                 *last_control_point_y)
+{
+  gdouble qx1, qy1, qx2, qy2, x1, y1, x2, y2;
+
+  /* If the last command was a quadratic or smooth quadratic, we use
+     the reflection of the last control point about the current point
+     as the first control point of this curve. Otherwise we use the
+     current point as the first control point. */
+  if (prev_cmd_type == GOO_CANVAS_PATH_QUADRATIC_CURVE_TO
+      || prev_cmd_type == GOO_CANVAS_PATH_SMOOTH_QUADRATIC_CURVE_TO)
+    {
+      qx1 = *x + (*x - *last_control_point_x);
+      qy1 = *y + (*y - *last_control_point_y);
+    }
+  else
+    {
+      qx1 = *x;
+      qy1 = *y;
+    }
+
+  if (cmd->curve.relative)
+    {
+      qx2 = *x + cmd->curve.x;
+      qy2 = *y + cmd->curve.y;
+    }
+  else
+    {
+      qx2 = cmd->curve.x;
+      qy2 = cmd->curve.y;
+    }
+
+  /* We need to convert the quadratic into a cubic bezier. */
+  x1 = *x + (qx1 - *x) * 2.0 / 3.0;
+  y1 = *y + (qy1 - *y) * 2.0 / 3.0;
+
+  x2 = x1 + (qx2 - *x) / 3.0;
+  y2 = y1 + (qy2 - *y) / 3.0;
+
+  cairo_curve_to (cr, x1, y1, x2, y2, qx2, qy2);
+
+  *x = qx2;
+  *y = qy2;
+  *last_control_point_x = qx1;
+  *last_control_point_y = qy1;
+}
+
+
+static gdouble
+calc_angle (gdouble ux, gdouble uy, gdouble vx, gdouble vy)
+{
+  gdouble top, u_magnitude, v_magnitude, angle_cos, angle;
+
+  top = ux * vx + uy * vy;
+  u_magnitude = sqrt (ux * ux + uy * uy);
+  v_magnitude = sqrt (vx * vx + vy * vy);
+  angle_cos = top / (u_magnitude * v_magnitude);
+
+  /* We check if the cosine is slightly out-of-bounds. */
+  if (angle_cos >= 1.0)
+    angle = 0.0;
+  if (angle_cos <= -1.0)
+    angle = M_PI;
+  else
+    angle = acos (angle_cos);
+
+  if (ux * vy - uy * vx < 0)
+    angle = - angle;
+
+  return angle;
+}
+
+
+/* FIXME: Maybe we should do these calculations once when the path data is
+   parsed, and keep the cairo parameters we need in the command instead. */
+static void
+do_elliptical_arc (GooCanvasPathCommand    *cmd,
+		   cairo_t                 *cr,
+		   gdouble                 *x,
+		   gdouble                 *y)
+{
+  gdouble x1 = *x, y1 = *y, x2, y2, rx, ry, lambda;
+  gdouble v1, v2, angle, angle_sin, angle_cos, x11, y11;
+  gdouble rx_squared, ry_squared, x11_squared, y11_squared, top, bottom;
+  gdouble c, cx1, cy1, cx, cy, start_angle, angle_delta;
+
+  /* Calculate the end point of the arc - x2,y2. */
+  if (cmd->arc.relative)
+    {
+      x2 = x1 + cmd->arc.x;
+      y2 = y1 + cmd->arc.y;
+    }
+  else
+    {
+      x2 = cmd->arc.x;
+      y2 = cmd->arc.y;
+    }
+
+  *x = x2;
+  *y = y2;
+
+  /* If the endpoints are exactly the same, just return (see SVG spec). */
+  if (x1 == x2 && y1 == y2)
+    return;
+
+  /* If either rx or ry is 0, do a simple lineto (see SVG spec). */
+  if (cmd->arc.rx == 0.0 || cmd->arc.ry == 0.0)
+    {
+      cairo_line_to (cr, x2, y2);
+      return;
+    }
+
+  /* Calculate x1' and y1' (as per SVG implementation notes). */
+  v1 = (x1 - x2) / 2.0;
+  v2 = (y1 - y2) / 2.0;
+
+  angle = cmd->arc.x_axis_rotation * (M_PI / 180.0);
+  angle_sin = sin (angle);
+  angle_cos = cos (angle);
+
+  x11 = (angle_cos * v1) + (angle_sin * v2);
+  y11 = - (angle_sin * v1) + (angle_cos * v2);
+
+  /* Ensure rx and ry are positive and large enough. */
+  rx = cmd->arc.rx > 0.0 ? cmd->arc.rx : - cmd->arc.rx;
+  ry = cmd->arc.ry > 0.0 ? cmd->arc.ry : - cmd->arc.ry;
+  lambda = (x11 * x11) / (rx * rx) + (y11 * y11) / (ry * ry);
+  if (lambda > 1.0)
+    {
+      gdouble square_root = sqrt (lambda);
+      rx *= square_root;
+      ry *= square_root;
+    }
+
+  /* Calculate cx' and cy'. */
+  rx_squared = rx * rx;
+  ry_squared = ry * ry;
+  x11_squared = x11 * x11;
+  y11_squared = y11 * y11;
+
+  top = (rx_squared * ry_squared) - (rx_squared * y11_squared)
+    - (ry_squared * x11_squared);
+  if (top < 0.0)
+    {
+      c = 0.0;
+    }
+  else
+    {
+      bottom = (rx_squared * y11_squared) + (ry_squared * x11_squared);
+      c = sqrt (top / bottom);
+    }
+
+  if (cmd->arc.large_arc_flag == cmd->arc.sweep_flag)
+    c = - c;
+
+  cx1 = c * ((rx * y11) / ry);
+  cy1 = c * (- (ry * x11) / rx);
+
+  /* Calculate cx and cy. */
+  cx = (angle_cos * cx1) - (angle_sin * cy1) + (x1 + x2) / 2;
+  cy = (angle_sin * cx1) + (angle_cos * cy1) + (y1 + y2) / 2;
+
+  /* Calculate the start and end angles. */
+  v1 = (x11 - cx1) / rx;
+  v2 = (y11 - cy1) / ry;
+
+  start_angle = calc_angle (1, 0, v1, v2);
+  angle_delta = calc_angle (v1, v2, (-x11 - cx1) / rx, (-y11 - cy1) / ry);
+
+  if (cmd->arc.sweep_flag == 0 && angle_delta > 0.0)
+    angle_delta -= 2 * M_PI;
+  else if (cmd->arc.sweep_flag == 1 && angle_delta < 0.0)
+    angle_delta += 2 * M_PI;
+
+  /* Now draw the arc. */
+  cairo_save (cr);
+  cairo_translate (cr, cx, cy);
+  cairo_rotate (cr, angle);
+  cairo_scale (cr, rx, ry);
+
+  if (angle_delta > 0.0)
+    cairo_arc (cr, 0.0, 0.0, 1.0,
+	       start_angle, start_angle + angle_delta);
+  else
+    cairo_arc_negative (cr, 0.0, 0.0, 1.0,
+			start_angle, start_angle + angle_delta);
+
+  cairo_restore (cr);
+}
+
+
+static void
+goo_canvas_path_create_path (GooCanvasItemSimple *simple,
+			     cairo_t             *cr)
+{
+  GooCanvasPath *path = (GooCanvasPath*) simple;
+  GooCanvasPathCommand *cmd;
+  GooCanvasPathCommandType prev_cmd_type = GOO_CANVAS_PATH_CLOSE_PATH;
+  gdouble x = 0, y = 0, path_start_x = 0, path_start_y = 0;
+  gdouble last_control_point_x = 0.0, last_control_point_y = 0.0;
+  gint i;
+
+  cairo_new_path (cr);
+
+  if (!path->path_commands || path->path_commands->len == 0)
+    return;
+
+  for (i = 0; i < path->path_commands->len; i++)
+    {
+      cmd = &g_array_index (path->path_commands, GooCanvasPathCommand, i);
+      switch (cmd->simple.type)
+	{
+	  /* Simple commands like moveto and lineto: MmZzLlHhVv. */
+	case GOO_CANVAS_PATH_MOVE_TO:
+	  if (cmd->simple.relative)
+	    {
+	      x += cmd->simple.x;
+	      y += cmd->simple.y;
+	    }
+	  else
+	    {
+	      x = cmd->simple.x;
+	      y = cmd->simple.y;
+	    }
+	  path_start_x = x;
+	  path_start_y = y;
+	  cairo_move_to (cr, x, y);
+	  break;
+
+	case GOO_CANVAS_PATH_CLOSE_PATH:
+	  x = path_start_x;
+	  y = path_start_y;
+	  cairo_close_path (cr);
+	  break;
+
+	case GOO_CANVAS_PATH_LINE_TO:
+	  if (cmd->simple.relative)
+	    {
+	      x += cmd->simple.x;
+	      y += cmd->simple.y;
+	    }
+	  else
+	    {
+	      x = cmd->simple.x;
+	      y = cmd->simple.y;
+	    }
+	  cairo_line_to (cr, x, y);
+	  break;
+
+	case GOO_CANVAS_PATH_HORIZONTAL_LINE_TO:
+	  if (cmd->simple.relative)
+	    x += cmd->simple.x;
+	  else
+	    x = cmd->simple.x;
+	  cairo_line_to (cr, x, y);
+	  break;
+
+	case GOO_CANVAS_PATH_VERTICAL_LINE_TO:
+	  if (cmd->simple.relative)
+	    y += cmd->simple.y;
+	  else
+	    y = cmd->simple.y;
+	  cairo_line_to (cr, x, y);
+	  break;
+
+	  /* Bezier curve commands: CcSsQqTt. */
+	case GOO_CANVAS_PATH_CURVE_TO:
+	  do_curve_to (cmd, cr, &x, &y,
+		       &last_control_point_x, &last_control_point_y);
+	  break;
+
+	case GOO_CANVAS_PATH_SMOOTH_CURVE_TO:
+	  do_smooth_curve_to (cmd, prev_cmd_type, cr, &x, &y,
+			      &last_control_point_x, &last_control_point_y);
+	  break;
+
+	case GOO_CANVAS_PATH_QUADRATIC_CURVE_TO:
+	  do_quadratic_curve_to (cmd, cr, &x, &y,
+				 &last_control_point_x, &last_control_point_y);
+	  break;
+
+	case GOO_CANVAS_PATH_SMOOTH_QUADRATIC_CURVE_TO:
+	  do_smooth_quadratic_curve_to (cmd, prev_cmd_type, cr, &x, &y,
+					&last_control_point_x,
+					&last_control_point_y);
+	  break;
+
+	  /* The elliptical arc commands: Aa. */
+	case GOO_CANVAS_PATH_ELLIPTICAL_ARC:
+	  do_elliptical_arc (cmd, cr, &x, &y);
+	  break;
+	}
+
+      prev_cmd_type = cmd->simple.type;
+    }
+}
+
+
+static void
+goo_canvas_path_set_model    (GooCanvasItem      *item,
+			      GooCanvasItemModel *model)
+{
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+  GooCanvasItemIface *parent_iface = g_type_interface_peek_parent (iface);
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasPath *path = (GooCanvasPath*) item;
+  GooCanvasPathModel *emodel = (GooCanvasPathModel*) model;
+
+  /* If our data was allocated, free it. */
+  if (!simple->model)
+    g_array_free (path->path_commands, TRUE);
+
+  /* Now use the new model's data instead. */
+  path->path_commands = emodel->path_commands;
+
+  /* Let the parent GooCanvasItemSimple code do the rest. */
+  parent_iface->set_model (item, model);
+}
+
+
+static void
+canvas_item_interface_init (GooCanvasItemIface *iface)
+{
+  iface->set_model      = goo_canvas_path_set_model;
+}
+
+
+/*
+ * GooCanvasPathModel.
+ */
+
+static void item_model_interface_init (GooCanvasItemModelIface *iface);
+static void goo_canvas_path_model_finalize     (GObject            *object);
+static void goo_canvas_path_model_get_property (GObject            *object,
+						   guint               param_id,
+						   GValue             *value,
+						   GParamSpec         *pspec);
+static void goo_canvas_path_model_set_property (GObject            *object,
+						   guint               param_id,
+						   const GValue       *value,
+						   GParamSpec         *pspec);
+
+G_DEFINE_TYPE_WITH_CODE (GooCanvasPathModel, goo_canvas_path_model,
+			 GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE,
+			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM_MODEL,
+						item_model_interface_init))
+
+
+static void
+goo_canvas_path_model_class_init (GooCanvasPathModelClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+
+  gobject_class->finalize     = goo_canvas_path_model_finalize;
+
+  gobject_class->get_property = goo_canvas_path_model_get_property;
+  gobject_class->set_property = goo_canvas_path_model_set_property;
+
+  goo_canvas_path_install_common_properties (gobject_class);
+}
+
+
+static void
+goo_canvas_path_model_init (GooCanvasPathModel *pmodel)
+{
+  pmodel->path_commands = g_array_new (0, 0, sizeof (GooCanvasPathCommand));
+}
+
+
+GooCanvasItemModel*
+goo_canvas_path_model_new (GooCanvasItemModel *parent,
+			   const gchar        *path_data,
+			   ...)
+{
+  GooCanvasItemModel *model;
+  GooCanvasPathModel *pmodel;
+  const char *first_property;
+  va_list var_args;
+
+  model = g_object_new (GOO_TYPE_CANVAS_PATH_MODEL, NULL);
+  pmodel = (GooCanvasPathModel*) model;
+
+  goo_canvas_path_parse_data (pmodel->path_commands, path_data);
+
+  va_start (var_args, path_data);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist ((GObject*) model, first_property, var_args);
+  va_end (var_args);
+
+  if (parent)
+    {
+      goo_canvas_item_model_add_child (parent, model, -1);
+      g_object_unref (model);
+    }
+
+  return model;
+}
+
+
+static void
+goo_canvas_path_model_finalize (GObject *object)
+{
+  GooCanvasPathModel *pmodel = (GooCanvasPathModel*) object;
+
+  g_array_free (pmodel->path_commands, TRUE);
+
+  G_OBJECT_CLASS (goo_canvas_path_model_parent_class)->finalize (object);
+}
+
+
+static void
+goo_canvas_path_model_get_property (GObject              *object,
+				       guint                 prop_id,
+				       GValue               *value,
+				       GParamSpec           *pspec)
+{
+  GooCanvasPathModel *pmodel = (GooCanvasPathModel*) object;
+
+  goo_canvas_path_get_common_property (object, pmodel->path_commands, prop_id,
+				       value, pspec);
+}
+
+
+static void
+goo_canvas_path_model_set_property (GObject              *object,
+				       guint                 prop_id,
+				       const GValue         *value,
+				       GParamSpec           *pspec)
+{
+  GooCanvasPathModel *pmodel = (GooCanvasPathModel*) object;
+
+  goo_canvas_path_set_common_property (object, pmodel->path_commands, prop_id,
+				       value, pspec);
+  g_signal_emit_by_name (pmodel, "changed", TRUE);
+}
+
+
+static GooCanvasItem*
+goo_canvas_path_model_create_item (GooCanvasItemModel *model,
+				   GooCanvas          *canvas)
+{
+  GooCanvasItem *item;
+
+  item = g_object_new (GOO_TYPE_CANVAS_PATH, NULL);
+  goo_canvas_item_set_model (item, model);
+
+  return item;
+}
+
+
+static void
+item_model_interface_init (GooCanvasItemModelIface *iface)
+{
+  iface->create_item    = goo_canvas_path_model_create_item;
+}

Index: goocanvaspath.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvaspath.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- goocanvaspath.h	12 Oct 2006 10:33:27 -0000	1.5
+++ goocanvaspath.h	29 Nov 2006 18:40:53 -0000	1.6
@@ -13,14 +13,6 @@
 G_BEGIN_DECLS
 
 
-#define GOO_TYPE_CANVAS_PATH            (goo_canvas_path_get_type ())
-#define GOO_CANVAS_PATH(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_PATH, GooCanvasPath))
-#define GOO_CANVAS_PATH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_PATH, GooCanvasPathClass))
-#define GOO_IS_CANVAS_PATH(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_PATH))
-#define GOO_IS_CANVAS_PATH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_PATH))
-#define GOO_CANVAS_PATH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_PATH, GooCanvasPathClass))
-
-
 /**
  * GooCanvasPathCommandType
  * @GOO_CANVAS_PATH_MOVE_TO: move to the given point.
@@ -110,24 +102,28 @@
 };
 
 
+#define GOO_TYPE_CANVAS_PATH            (goo_canvas_path_get_type ())
+#define GOO_CANVAS_PATH(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_PATH, GooCanvasPath))
+#define GOO_CANVAS_PATH_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_PATH, GooCanvasPathClass))
+#define GOO_IS_CANVAS_PATH(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_PATH))
+#define GOO_IS_CANVAS_PATH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_PATH))
+#define GOO_CANVAS_PATH_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_PATH, GooCanvasPathClass))
+
+
 typedef struct _GooCanvasPath       GooCanvasPath;
 typedef struct _GooCanvasPathClass  GooCanvasPathClass;
 
 /**
  * GooCanvasPath
- * @commands: an array of #GooCanvasPathCommand holding the specification of
- *  the path. Applications can modify this directly, but must call
- *  goo_canvas_item_simple_emit_changed() afterwards to notify the
- *  views that the #GooCanvasPath has changed.
  *
- * The #GooCanvasPath-struct contains the list of commands specifying the path.
+ * The #GooCanvasPath-struct struct contains private data only.
  */
 struct _GooCanvasPath
 {
   GooCanvasItemSimple parent;
 
-  /*< public >*/
-  GArray *commands;
+  /* An array of GooCanvasPathCommand. */
+  GArray *path_commands;
 };
 
 struct _GooCanvasPathClass
@@ -136,10 +132,49 @@
 };
 
 
-GType           goo_canvas_path_get_type          (void) G_GNUC_CONST;
-GooCanvasItem*  goo_canvas_path_new               (GooCanvasItem *parent,
-						   const gchar   *path_data,
-						   ...);
+GType               goo_canvas_path_get_type  (void) G_GNUC_CONST;
+
+GooCanvasItem*      goo_canvas_path_new       (GooCanvasItem      *parent,
+					       const gchar        *path_data,
+					       ...);
+
+
+
+#define GOO_TYPE_CANVAS_PATH_MODEL            (goo_canvas_path_model_get_type ())
+#define GOO_CANVAS_PATH_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_PATH_MODEL, GooCanvasPathModel))
+#define GOO_CANVAS_PATH_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_PATH_MODEL, GooCanvasPathModelClass))
+#define GOO_IS_CANVAS_PATH_MODEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_PATH_MODEL))
+#define GOO_IS_CANVAS_PATH_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_PATH_MODEL))
+#define GOO_CANVAS_PATH_MODEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_PATH_MODEL, GooCanvasPathModelClass))
+
+
+typedef struct _GooCanvasPathModel       GooCanvasPathModel;
+typedef struct _GooCanvasPathModelClass  GooCanvasPathModelClass;
+
+/**
+ * GooCanvasPathModel
+ *
+ * The #GooCanvasPathModel-struct struct contains private data only.
+ */
+struct _GooCanvasPathModel
+{
+  GooCanvasItemModelSimple parent_object;
+
+  /* An array of GooCanvasPathCommand. */
+  GArray *path_commands;
+};
+
+struct _GooCanvasPathModelClass
+{
+  GooCanvasItemModelSimpleClass parent_class;
+};
+
+
+GType               goo_canvas_path_model_get_type  (void) G_GNUC_CONST;
+
+GooCanvasItemModel* goo_canvas_path_model_new (GooCanvasItemModel *parent,
+					       const gchar        *path_data,
+					       ...);
 
 
 G_END_DECLS

--- goocanvaspathview.c DELETED ---

--- goocanvaspathview.h DELETED ---

Index: goocanvaspolyline.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvaspolyline.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- goocanvaspolyline.c	24 Aug 2006 08:06:23 -0000	1.6
+++ goocanvaspolyline.c	29 Nov 2006 18:40:53 -0000	1.7
@@ -27,7 +27,7 @@
  *
  * To respond to events such as mouse clicks on the polyline you must connect
  * to the signal handlers of the corresponding #GooCanvasPolylineView objects.
- * (See goo_canvas_view_get_item_view() and #GooCanvasView::item-view-created.)
+ * (See goo_canvas_get_item_view() and #GooCanvasView::item-view-created.)
  */
 #include <config.h>
 #include <math.h>
@@ -36,11 +36,8 @@
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
[...1116 lines suppressed...]
+
+
+static GooCanvasItem*
+goo_canvas_polyline_model_create_item (GooCanvasItemModel *model,
+				       GooCanvas          *canvas)
+{
+  GooCanvasItem *item;
+
+  item = g_object_new (GOO_TYPE_CANVAS_POLYLINE, NULL);
+  goo_canvas_item_set_model (item, model);
+
+  return item;
+}
+
+
+static void
+item_model_interface_init (GooCanvasItemModelIface *iface)
+{
+  iface->create_item    = goo_canvas_polyline_model_create_item;
+}

Index: goocanvaspolyline.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvaspolyline.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- goocanvaspolyline.h	12 Oct 2006 10:33:27 -0000	1.4
+++ goocanvaspolyline.h	29 Nov 2006 18:40:53 -0000	1.5
@@ -36,13 +36,6 @@
 void             goo_canvas_points_unref    (GooCanvasPoints *points);
 
 
-#define GOO_TYPE_CANVAS_POLYLINE            (goo_canvas_polyline_get_type ())
-#define GOO_CANVAS_POLYLINE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_POLYLINE, GooCanvasPolyline))
-#define GOO_CANVAS_POLYLINE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_POLYLINE, GooCanvasPolylineClass))
-#define GOO_IS_CANVAS_POLYLINE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_POLYLINE))
-#define GOO_IS_CANVAS_POLYLINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_POLYLINE))
-#define GOO_CANVAS_POLYLINE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_POLYLINE, GooCanvasPolylineClass))
-
 #define NUM_ARROW_POINTS     5		/* number of points in an arrowhead */
 
 typedef struct _GooCanvasPolylineArrowData GooCanvasPolylineArrowData;
@@ -58,6 +51,30 @@
 };
 
 
+/* This is the data used by both model and view classes. */
+typedef struct _GooCanvasPolylineData   GooCanvasPolylineData;
+struct _GooCanvasPolylineData
+{
+  gdouble *coords;
+
+  GooCanvasPolylineArrowData *arrow_data;
+
+  guint num_points	   : 16;
+  guint close_path	   : 1;
+  guint start_arrow	   : 1;
+  guint end_arrow          : 1;
+  guint reconfigure_arrows : 1;
+};
+
+
+#define GOO_TYPE_CANVAS_POLYLINE            (goo_canvas_polyline_get_type ())
+#define GOO_CANVAS_POLYLINE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_POLYLINE, GooCanvasPolyline))
+#define GOO_CANVAS_POLYLINE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_POLYLINE, GooCanvasPolylineClass))
+#define GOO_IS_CANVAS_POLYLINE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_POLYLINE))
+#define GOO_IS_CANVAS_POLYLINE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_POLYLINE))
+#define GOO_CANVAS_POLYLINE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_POLYLINE, GooCanvasPolylineClass))
+
+
 typedef struct _GooCanvasPolyline       GooCanvasPolyline;
 typedef struct _GooCanvasPolylineClass  GooCanvasPolylineClass;
 
@@ -70,15 +87,7 @@
 {
   GooCanvasItemSimple parent;
 
-  gdouble *coords;
-
-  GooCanvasPolylineArrowData *arrow_data;
-
-  guint num_points	   : 16;
-  guint close_path	   : 1;
-  guint start_arrow	   : 1;
-  guint end_arrow          : 1;
-  guint reconfigure_arrows : 1;
+  GooCanvasPolylineData *polyline_data;
 };
 
 struct _GooCanvasPolylineClass
@@ -87,20 +96,64 @@
 };
 
 
-GType           goo_canvas_polyline_get_type      (void) G_GNUC_CONST;
-GooCanvasItem*  goo_canvas_polyline_new           (GooCanvasItem *parent,
-						   gboolean       close_path,
-						   gint           num_points,
-						   ...);
+GType               goo_canvas_polyline_get_type       (void) G_GNUC_CONST;
+
+GooCanvasItem*      goo_canvas_polyline_new            (GooCanvasItem      *parent,
+							gboolean            close_path,
+							gint                num_points,
+							...);
+
+GooCanvasItem*      goo_canvas_polyline_new_line       (GooCanvasItem      *parent,
+							gdouble             x1,
+							gdouble             y1,
+							gdouble             x2,
+							gdouble             y2,
+							...);
+
+
+
+#define GOO_TYPE_CANVAS_POLYLINE_MODEL            (goo_canvas_polyline_model_get_type ())
+#define GOO_CANVAS_POLYLINE_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_POLYLINE_MODEL, GooCanvasPolylineModel))
+#define GOO_CANVAS_POLYLINE_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_POLYLINE_MODEL, GooCanvasPolylineModelClass))
+#define GOO_IS_CANVAS_POLYLINE_MODEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_POLYLINE_MODEL))
+#define GOO_IS_CANVAS_POLYLINE_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_POLYLINE_MODEL))
+#define GOO_CANVAS_POLYLINE_MODEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_POLYLINE_MODEL, GooCanvasPolylineModelClass))
+
+
+typedef struct _GooCanvasPolylineModel       GooCanvasPolylineModel;
+typedef struct _GooCanvasPolylineModelClass  GooCanvasPolylineModelClass;
+
+/**
+ * GooCanvasPolylineModel
+ *
+ * The #GooCanvasPolylineModel-struct struct contains private data only.
+ */
+struct _GooCanvasPolylineModel
+{
+  GooCanvasItemModelSimple parent_object;
+
+  GooCanvasPolylineData polyline_data;
+};
+
+struct _GooCanvasPolylineModelClass
+{
+  GooCanvasItemModelSimpleClass parent_class;
+};
 
-GooCanvasItem*  goo_canvas_polyline_new_line      (GooCanvasItem *parent,
-						   gdouble        x1,
-						   gdouble        y1,
-						   gdouble        x2,
-						   gdouble        y2,
-						   const gchar   *first_property,
-						   ...);
 
+GType               goo_canvas_polyline_model_get_type  (void) G_GNUC_CONST;
+
+GooCanvasItemModel* goo_canvas_polyline_model_new      (GooCanvasItemModel *parent,
+							gboolean            close_path,
+							gint                num_points,
+							...);
+
+GooCanvasItemModel* goo_canvas_polyline_model_new_line (GooCanvasItemModel *parent,
+							gdouble             x1,
+							gdouble             y1,
+							gdouble             x2,
+							gdouble             y2,
+							...);
 
 G_END_DECLS
 

--- goocanvaspolylineview.c DELETED ---

--- goocanvaspolylineview.h DELETED ---

Index: goocanvasrect.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasrect.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- goocanvasrect.c	24 Aug 2006 08:06:23 -0000	1.6
+++ goocanvasrect.c	29 Nov 2006 18:40:53 -0000	1.7
@@ -25,14 +25,14 @@
  * g_object_get() and g_object_set().
  *
  * To respond to events such as mouse clicks on the rect you must connect
- * to the signal handlers of the corresponding #GooCanvasRectView objects.
- * (See goo_canvas_view_get_item_view() and #GooCanvasView::item-view-created.)
+ * to the signal handlers of the corresponding #GooCanvasRect objects.
+ * (See goo_canvas_get_item_view() and #GooCanvas::item-view-created.)
  */
 #include <config.h>
+#include <math.h>
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 #include "goocanvasrect.h"
-#include "goocanvasrectview.h"
 
 
 enum {
@@ -47,7 +47,8 @@
 };
 
 
-static void item_interface_init (GooCanvasItemIface *iface);
+static void canvas_item_interface_init   (GooCanvasItemIface *iface);
+static void goo_canvas_rect_finalize     (GObject            *object);
 static void goo_canvas_rect_get_property (GObject            *object,
 					  guint               param_id,
 					  GValue             *value,
@@ -56,21 +57,18 @@
 					  guint               param_id,
 					  const GValue       *value,
 					  GParamSpec         *pspec);
+static void goo_canvas_rect_create_path (GooCanvasItemSimple *simple,
+					 cairo_t             *cr);
 
 G_DEFINE_TYPE_WITH_CODE (GooCanvasRect, goo_canvas_rect,
 			 GOO_TYPE_CANVAS_ITEM_SIMPLE,
 			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
-						item_interface_init))
+						canvas_item_interface_init))
 
 
 static void
-goo_canvas_rect_class_init (GooCanvasRectClass *klass)
+goo_canvas_rect_install_common_properties (GObjectClass *gobject_class)
 {
-  GObjectClass *gobject_class = (GObjectClass*) klass;
-
-  gobject_class->get_property = goo_canvas_rect_get_property;
-  gobject_class->set_property = goo_canvas_rect_set_property;
-
   g_object_class_install_property (gobject_class, PROP_X,
 				   g_param_spec_double ("x",
 							"X",
@@ -118,9 +116,26 @@
 
 
 static void
-goo_canvas_rect_init (GooCanvasRect *canvas_rect)
+goo_canvas_rect_class_init (GooCanvasRectClass *klass)
 {
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+  GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) klass;
 
+  gobject_class->finalize     = goo_canvas_rect_finalize;
+
+  gobject_class->get_property = goo_canvas_rect_get_property;
+  gobject_class->set_property = goo_canvas_rect_set_property;
+
+  simple_class->create_path = goo_canvas_rect_create_path;
+
+  goo_canvas_rect_install_common_properties (gobject_class);
+}
+
+
+static void
+goo_canvas_rect_init (GooCanvasRect *rect)
+{
+  rect->rect_data = g_slice_new0 (GooCanvasRectData);
 }
 
 
@@ -133,9 +148,7 @@
  * @y: the y coordinate of the top of the rectangle.
  * @width: the width of the rectangle.
  * @height: the height of the rectangle.
- * @first_property: the name of the first property to set, or %NULL.
- * @...: the remaining property names and values to set, terminated with a
- *  %NULL.
+ * @...: optional pairs of property names and values, and a terminating %NULL.
  * 
  * Creates a new rectangle item.
  * 
@@ -160,26 +173,30 @@
 		     gdouble        y,
 		     gdouble        width,
 		     gdouble        height,
-		     const gchar   *first_property,
 		     ...)
 {
   GooCanvasItem *item;
   GooCanvasRect *rect;
-  va_list args;
+  GooCanvasRectData *rect_data;
+  const char *first_property;
+  va_list var_args;
 
   item = g_object_new (GOO_TYPE_CANVAS_RECT, NULL);
-  rect = GOO_CANVAS_RECT (item);
+  rect = (GooCanvasRect*) item;
 
-  rect->x = x;
-  rect->y = y;
-  rect->width = width;
-  rect->height = height;
-  rect->radius_x = 0;
-  rect->radius_y = 0;
+  rect_data = rect->rect_data;
+  rect_data->x = x;
+  rect_data->y = y;
+  rect_data->width = width;
+  rect_data->height = height;
+  rect_data->radius_x = 0;
+  rect_data->radius_y = 0;
 
-  va_start (args, first_property);
-  g_object_set_valist (G_OBJECT (item), first_property, args);
-  va_end (args);
+  va_start (var_args, height);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist ((GObject*) item, first_property, var_args);
+  va_end (var_args);
 
   if (parent)
     {
@@ -191,50 +208,46 @@
 }
 
 
-static GooCanvasItemView*
-goo_canvas_rect_create_view (GooCanvasItem     *item,
-			     GooCanvasView     *canvas_view,
-			     GooCanvasItemView *parent_view)
+static void
+goo_canvas_rect_finalize (GObject *object)
 {
-  return goo_canvas_rect_view_new (canvas_view, parent_view,
-				   (GooCanvasRect*) item);
-}
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasRect *rect = (GooCanvasRect*) object;
 
+  if (!simple->model)
+    g_slice_free (GooCanvasRectData, rect->rect_data);
+  rect->rect_data = NULL;
 
-static void
-item_interface_init (GooCanvasItemIface *iface)
-{
-  iface->create_view = goo_canvas_rect_create_view;
+  G_OBJECT_CLASS (goo_canvas_rect_parent_class)->finalize (object);
 }
 
 
 static void
-goo_canvas_rect_get_property (GObject              *object,
-			      guint                 prop_id,
-			      GValue               *value,
-			      GParamSpec           *pspec)
+goo_canvas_rect_get_common_property (GObject              *object,
+				     GooCanvasRectData    *rect_data,
+				     guint                 prop_id,
+				     GValue               *value,
+				     GParamSpec           *pspec)
 {
-  GooCanvasRect *rect = (GooCanvasRect*) object;
-
   switch (prop_id)
     {
     case PROP_X:
-      g_value_set_double (value, rect->x);
+      g_value_set_double (value, rect_data->x);
       break;
     case PROP_Y:
-      g_value_set_double (value, rect->y);
+      g_value_set_double (value, rect_data->y);
       break;
     case PROP_WIDTH:
-      g_value_set_double (value, rect->width);
+      g_value_set_double (value, rect_data->width);
       break;
     case PROP_HEIGHT:
-      g_value_set_double (value, rect->height);
+      g_value_set_double (value, rect_data->height);
       break;
     case PROP_RADIUS_X:
-      g_value_set_double (value, rect->radius_x);
+      g_value_set_double (value, rect_data->radius_x);
       break;
     case PROP_RADIUS_Y:
-      g_value_set_double (value, rect->radius_y);
+      g_value_set_double (value, rect_data->radius_y);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -244,38 +257,298 @@
 
 
 static void
-goo_canvas_rect_set_property (GObject              *object,
+goo_canvas_rect_get_property (GObject              *object,
 			      guint                 prop_id,
-			      const GValue         *value,
+			      GValue               *value,
 			      GParamSpec           *pspec)
 {
   GooCanvasRect *rect = (GooCanvasRect*) object;
 
+  goo_canvas_rect_get_common_property (object, rect->rect_data, prop_id,
+				       value, pspec);
+}
+
+
+static void
+goo_canvas_rect_set_common_property (GObject              *object,
+				     GooCanvasRectData    *rect_data,
+				     guint                 prop_id,
+				     const GValue         *value,
+				     GParamSpec           *pspec)
+{
   switch (prop_id)
     {
     case PROP_X:
-      rect->x = g_value_get_double (value);
+      rect_data->x = g_value_get_double (value);
       break;
     case PROP_Y:
-      rect->y = g_value_get_double (value);
+      rect_data->y = g_value_get_double (value);
       break;
     case PROP_WIDTH:
-      rect->width = g_value_get_double (value);
+      rect_data->width = g_value_get_double (value);
       break;
     case PROP_HEIGHT:
-      rect->height = g_value_get_double (value);
+      rect_data->height = g_value_get_double (value);
       break;
     case PROP_RADIUS_X:
-      rect->radius_x = g_value_get_double (value);
+      rect_data->radius_x = g_value_get_double (value);
       break;
     case PROP_RADIUS_Y:
-      rect->radius_y = g_value_get_double (value);
+      rect_data->radius_y = g_value_get_double (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
+}
 
-  g_signal_emit_by_name (rect, "changed", TRUE);
+
+static void
+goo_canvas_rect_set_property (GObject              *object,
+			      guint                 prop_id,
+			      const GValue         *value,
+			      GParamSpec           *pspec)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasRect *rect = (GooCanvasRect*) object;
+
+  if (simple->model)
+    {
+      g_warning ("Can't set property of a canvas item with a model - set the model property instead");
+      return;
+    }
+
+  goo_canvas_rect_set_common_property (object, rect->rect_data, prop_id,
+				       value, pspec);
+  goo_canvas_item_simple_changed (simple, TRUE);
 }
 
+
+static void
+goo_canvas_rect_create_path (GooCanvasItemSimple *simple,
+			     cairo_t             *cr)
+{
+  GooCanvasRect *rect = (GooCanvasRect*) simple;
+  GooCanvasRectData *rect_data = rect->rect_data;
+
+  cairo_new_path (cr);
+
+  /* Check if we need to draw rounded corners. */
+  if (rect_data->radius_x > 0 && rect_data->radius_y > 0)
+    {
+      /* The radii can't be more than half the size of the rect. */
+      double rx = MIN (rect_data->radius_x, rect_data->width / 2);
+      double ry = MIN (rect_data->radius_y, rect_data->height / 2);
+
+      /* Draw the top-right arc. */
+      cairo_save (cr);
+      cairo_translate (cr, rect_data->x + rect_data->width - rx,
+		       rect_data->y + ry);
+      cairo_scale (cr, rx, ry);
+      cairo_arc (cr, 0.0, 0.0, 1.0, 1.5 * M_PI, 2.0 * M_PI);
+      cairo_restore (cr);
+
+      /* Draw the line down the right side. */
+      cairo_line_to (cr, rect_data->x + rect_data->width,
+		     rect_data->y + rect_data->height - ry);
+
+      /* Draw the bottom-right arc. */
+      cairo_save (cr);
+      cairo_translate (cr, rect_data->x + rect_data->width - rx,
+		       rect_data->y + rect_data->height - ry);
+      cairo_scale (cr, rx, ry);
+      cairo_arc (cr, 0.0, 0.0, 1.0, 0.0, 0.5 * M_PI);
+      cairo_restore (cr);
+
+      /* Draw the line left across the bottom. */
+      cairo_line_to (cr, rect_data->x + rx, rect_data->y + rect_data->height);
+
+      /* Draw the bottom-left arc. */
+      cairo_save (cr);
+      cairo_translate (cr, rect_data->x + rx,
+		       rect_data->y + rect_data->height - ry);
+      cairo_scale (cr, rx, ry);
+      cairo_arc (cr, 0.0, 0.0, 1.0, 0.5 * M_PI, M_PI);
+      cairo_restore (cr);
+
+      /* Draw the line up the left side. */
+      cairo_line_to (cr, rect_data->x, rect_data->y + ry);
+
+      /* Draw the top-left arc. */
+      cairo_save (cr);
+      cairo_translate (cr, rect_data->x + rx, rect_data->y + ry);
+      cairo_scale (cr, rx, ry);
+      cairo_arc (cr, 0.0, 0.0, 1.0, M_PI, 1.5 * M_PI);
+      cairo_restore (cr);
+
+      /* Close the path across the top. */
+      cairo_close_path (cr);
+    }
+  else
+    {
+      /* Draw the plain rectangle. */
+      cairo_move_to (cr, rect_data->x, rect_data->y);
+      cairo_line_to (cr, rect_data->x, rect_data->y + rect_data->height);
+      cairo_line_to (cr, rect_data->x + rect_data->width,
+		     rect_data->y + rect_data->height);
+      cairo_line_to (cr, rect_data->x + rect_data->width, rect_data->y);
+      cairo_close_path (cr);
+    }
+}
+
+
+
+static void
+goo_canvas_rect_set_model    (GooCanvasItem      *item,
+			      GooCanvasItemModel *model)
+{
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+  GooCanvasItemIface *parent_iface = g_type_interface_peek_parent (iface);
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasRect *rect = (GooCanvasRect*) item;
+  GooCanvasRectModel *emodel = (GooCanvasRectModel*) model;
+
+  /* If our rect_data was allocated, free it. */
+  if (!simple->model)
+    g_slice_free (GooCanvasRectData, rect->rect_data);
+
+  /* Now use the new model's rect_data instead. */
+  rect->rect_data = &emodel->rect_data;
+
+  /* Let the parent GooCanvasItemSimple code do the rest. */
+  parent_iface->set_model (item, model);
+}
+
+
+static void
+canvas_item_interface_init (GooCanvasItemIface *iface)
+{
+  iface->set_model      = goo_canvas_rect_set_model;
+}
+
+
+/*
+ * GooCanvasRectModel.
+ */
+
+static void item_model_interface_init (GooCanvasItemModelIface *iface);
+static void goo_canvas_rect_model_get_property (GObject            *object,
+						guint               param_id,
+						GValue             *value,
+						GParamSpec         *pspec);
+static void goo_canvas_rect_model_set_property (GObject            *object,
+						guint               param_id,
+						const GValue       *value,
+						GParamSpec         *pspec);
+
+G_DEFINE_TYPE_WITH_CODE (GooCanvasRectModel, goo_canvas_rect_model,
+			 GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE,
+			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM_MODEL,
+						item_model_interface_init))
+
+
+static void
+goo_canvas_rect_model_class_init (GooCanvasRectModelClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+
+  gobject_class->get_property = goo_canvas_rect_model_get_property;
+  gobject_class->set_property = goo_canvas_rect_model_set_property;
+
+  goo_canvas_rect_install_common_properties (gobject_class);
+}
+
+
+static void
+goo_canvas_rect_model_init (GooCanvasRectModel *rmodel)
+{
+
+}
+
+
+GooCanvasItemModel*
+goo_canvas_rect_model_new (GooCanvasItemModel *parent,
+			   gdouble             x,
+			   gdouble             y,
+			   gdouble             width,
+			   gdouble             height,
+			   ...)
+{
+  GooCanvasItemModel *model;
+  GooCanvasRectModel *rmodel;
+  GooCanvasRectData *rect_data;
+  const char *first_property;
+  va_list var_args;
+
+  model = g_object_new (GOO_TYPE_CANVAS_RECT_MODEL, NULL);
+  rmodel = (GooCanvasRectModel*) model;
+
+  rect_data = &rmodel->rect_data;
+  rect_data->x = x;
+  rect_data->y = y;
+  rect_data->width = width;
+  rect_data->height = height;
+  rect_data->radius_x = 0;
+  rect_data->radius_y = 0;
+
+  va_start (var_args, height);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist ((GObject*) model, first_property, var_args);
+  va_end (var_args);
+
+  if (parent)
+    {
+      goo_canvas_item_model_add_child (parent, model, -1);
+      g_object_unref (model);
+    }
+
+  return model;
+}
+
+
+static void
+goo_canvas_rect_model_get_property (GObject              *object,
+				    guint                 prop_id,
+				    GValue               *value,
+				    GParamSpec           *pspec)
+{
+  GooCanvasRectModel *rmodel = (GooCanvasRectModel*) object;
+
+  goo_canvas_rect_get_common_property (object, &rmodel->rect_data, prop_id,
+				       value, pspec);
+}
+
+
+static void
+goo_canvas_rect_model_set_property (GObject              *object,
+				    guint                 prop_id,
+				    const GValue         *value,
+				    GParamSpec           *pspec)
+{
+  GooCanvasRectModel *rmodel = (GooCanvasRectModel*) object;
+
+  goo_canvas_rect_set_common_property (object, &rmodel->rect_data, prop_id,
+				       value, pspec);
+  g_signal_emit_by_name (rmodel, "changed", TRUE);
+}
+
+
+static GooCanvasItem*
+goo_canvas_rect_model_create_item (GooCanvasItemModel *model,
+				   GooCanvas          *canvas)
+{
+  GooCanvasItem *item;
+
+  item = g_object_new (GOO_TYPE_CANVAS_RECT, NULL);
+  goo_canvas_item_set_model (item, model);
+
+  return item;
+}
+
+
+static void
+item_model_interface_init (GooCanvasItemModelIface *iface)
+{
+  iface->create_item    = goo_canvas_rect_model_create_item;
+}

Index: goocanvasrect.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvasrect.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- goocanvasrect.h	13 Apr 2006 16:06:04 -0000	1.2
+++ goocanvasrect.h	29 Nov 2006 18:40:53 -0000	1.3
@@ -13,6 +13,14 @@
 G_BEGIN_DECLS
 
 
+/* This is the data used by both model and view classes. */
+typedef struct _GooCanvasRectData   GooCanvasRectData;
+struct _GooCanvasRectData
+{
+  gdouble x, y, width, height, radius_x, radius_y;
+};
+
+
 #define GOO_TYPE_CANVAS_RECT            (goo_canvas_rect_get_type ())
 #define GOO_CANVAS_RECT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_RECT, GooCanvasRect))
 #define GOO_CANVAS_RECT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_RECT, GooCanvasRectClass))
@@ -33,7 +41,7 @@
 {
   GooCanvasItemSimple parent;
 
-  gdouble x, y, width, height, radius_x, radius_y;
+  GooCanvasRectData *rect_data;
 };
 
 struct _GooCanvasRectClass
@@ -42,14 +50,54 @@
 };
 
 
-GType          goo_canvas_rect_get_type        (void) G_GNUC_CONST;
-GooCanvasItem* goo_canvas_rect_new             (GooCanvasItem *parent,
-						gdouble        x,
-						gdouble        y,
-						gdouble        width,
-						gdouble        height,
-						const gchar   *first_property,
-						...);
+GType               goo_canvas_rect_get_type  (void) G_GNUC_CONST;
+
+GooCanvasItem*      goo_canvas_rect_new       (GooCanvasItem      *parent,
+					       gdouble             x,
+					       gdouble             y,
+					       gdouble             width,
+					       gdouble             height,
+					       ...);
+
+
+
+#define GOO_TYPE_CANVAS_RECT_MODEL            (goo_canvas_rect_model_get_type ())
+#define GOO_CANVAS_RECT_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_RECT_MODEL, GooCanvasRectModel))
+#define GOO_CANVAS_RECT_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_RECT_MODEL, GooCanvasRectModelClass))
+#define GOO_IS_CANVAS_RECT_MODEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_RECT_MODEL))
+#define GOO_IS_CANVAS_RECT_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_RECT_MODEL))
+#define GOO_CANVAS_RECT_MODEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_RECT_MODEL, GooCanvasRectModelClass))
+
+
+typedef struct _GooCanvasRectModel       GooCanvasRectModel;
+typedef struct _GooCanvasRectModelClass  GooCanvasRectModelClass;
+
+/**
+ * GooCanvasRectModel
+ *
+ * The #GooCanvasRectModel-struct struct contains private data only.
+ */
+struct _GooCanvasRectModel
+{
+  GooCanvasItemModelSimple parent_object;
+
+  GooCanvasRectData rect_data;
+};
+
+struct _GooCanvasRectModelClass
+{
+  GooCanvasItemModelSimpleClass parent_class;
+};
+
+
+GType               goo_canvas_rect_model_get_type  (void) G_GNUC_CONST;
+
+GooCanvasItemModel* goo_canvas_rect_model_new (GooCanvasItemModel *parent,
+					       gdouble             x,
+					       gdouble             y,
+					       gdouble             width,
+					       gdouble             height,
+					       ...);
 
 
 G_END_DECLS

--- goocanvasrectview.c DELETED ---

--- goocanvasrectview.h DELETED ---

Index: goocanvastext.c
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvastext.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- goocanvastext.c	24 Aug 2006 08:06:23 -0000	1.6
+++ goocanvastext.c	29 Nov 2006 18:40:53 -0000	1.7
@@ -26,13 +26,13 @@
  *
  * To respond to events such as mouse clicks on the text you must connect
  * to the signal handlers of the corresponding #GooCanvasTextView objects.
- * (See goo_canvas_view_get_item_view() and #GooCanvasView::item-view-created.)
+ * (See goo_canvas_get_item_view() and #GooCanvas::item-view-created.)
  */
 #include <config.h>
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 #include "goocanvastext.h"
-#include "goocanvastextview.h"
+#include "goocanvas.h"
 
 
 enum {
@@ -43,14 +43,12 @@
   PROP_WIDTH,
   PROP_TEXT,
   PROP_USE_MARKUP,
-  PROP_FONT,
-  PROP_FONT_DESC,
   PROP_ANCHOR,
   PROP_ALIGN
 };
 
-static void goo_canvas_text_finalize (GObject *object);
-static void item_interface_init (GooCanvasItemIface *iface);
+static void goo_canvas_text_finalize     (GObject            *object);
+static void canvas_item_interface_init   (GooCanvasItemIface *iface);
 static void goo_canvas_text_get_property (GObject            *object,
 					  guint               param_id,
 					  GValue             *value,
@@ -63,19 +61,12 @@
 G_DEFINE_TYPE_WITH_CODE (GooCanvasText, goo_canvas_text,
 			 GOO_TYPE_CANVAS_ITEM_SIMPLE,
 			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
-						item_interface_init))
+						canvas_item_interface_init))
 
 
 static void
-goo_canvas_text_class_init (GooCanvasTextClass *klass)
+goo_canvas_text_install_common_properties (GObjectClass *gobject_class)
 {
-  GObjectClass *gobject_class = (GObjectClass*) klass;
-
-  gobject_class->finalize = goo_canvas_text_finalize;
-
-  gobject_class->get_property = goo_canvas_text_get_property;
-  gobject_class->set_property = goo_canvas_text_set_property;
-
   /* Text */
   g_object_class_install_property (gobject_class, PROP_TEXT,
 				   g_param_spec_string ("text",
@@ -131,29 +122,36 @@
 						      PANGO_TYPE_ALIGNMENT,
 						      PANGO_ALIGN_LEFT,
 						      G_PARAM_READWRITE));
+}
 
-  /* Font */
-  g_object_class_install_property (gobject_class, PROP_FONT,
-				   g_param_spec_string ("font",
-							_("Font"),
-							_("The base font to use for the text"),
-							NULL,
-							G_PARAM_READWRITE));
 
-  g_object_class_install_property (gobject_class, PROP_FONT_DESC,
-				   g_param_spec_boxed ("font-desc",
-						       _("Font Description"),
-						       _("The attributes specifying which font to use"),
-						       PANGO_TYPE_FONT_DESCRIPTION,
-						       G_PARAM_READWRITE));
+static void
+goo_canvas_text_class_init (GooCanvasTextClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+
+  gobject_class->finalize = goo_canvas_text_finalize;
+
+  gobject_class->get_property = goo_canvas_text_get_property;
+  gobject_class->set_property = goo_canvas_text_set_property;
+
+  goo_canvas_text_install_common_properties (gobject_class);
+
+  /* Create the font options once and reuse it. */
+  klass->font_options = cairo_font_options_create ();
+  cairo_font_options_set_hint_metrics (klass->font_options,
+				       CAIRO_HINT_METRICS_OFF);
+  cairo_font_options_set_hint_style (klass->font_options,
+				     CAIRO_HINT_STYLE_NONE);
 }
 
 
 static void
 goo_canvas_text_init (GooCanvasText *text)
 {
-  text->width = -1.0;
-  text->anchor = GTK_ANCHOR_NW;
+  text->text_data = g_slice_new0 (GooCanvasTextData);
+  text->text_data->width = -1.0;
+  text->text_data->anchor = GTK_ANCHOR_NW;
 }
 
 
@@ -171,9 +169,7 @@
  *  top-left of the text being placed at the given @x and @y coordinates.
  *  An anchor of %GDK_ANCHOR_CENTER will result in the center of the text being
  *  placed at the @x and @y coordinates.
- * @first_property: the name of the first property to set, or %NULL.
- * @...: the remaining property names and values to set, terminated with a
- *  %NULL.
+ * @...: optional pairs of property names and values, and a terminating %NULL.
  * 
  * Creates a new text item.
  * 
@@ -197,25 +193,29 @@
 		     gdouble        y,
 		     gdouble        width,
 		     GtkAnchorType  anchor,
-		     const gchar   *first_property,
 		     ...)
 {
   GooCanvasItem *item;
   GooCanvasText *text;
-  va_list args;
+  GooCanvasTextData *text_data;
+  const char *first_property;
+  va_list var_args;
 
   item = g_object_new (GOO_TYPE_CANVAS_TEXT, NULL);
-  text = GOO_CANVAS_TEXT (item);
+  text = (GooCanvasText*) item;
 
-  text->text = g_strdup (string);
-  text->x = x;
-  text->y = y;
-  text->width = width;
-  text->anchor = anchor;
+  text_data = text->text_data;
+  text_data->text = g_strdup (string);
+  text_data->x = x;
+  text_data->y = y;
+  text_data->width = width;
+  text_data->anchor = anchor;
 
-  va_start (args, first_property);
-  g_object_set_valist (G_OBJECT (item), first_property, args);
-  va_end (args);
+  va_start (var_args, anchor);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist ((GObject*) item, first_property, var_args);
+  va_end (var_args);
 
   if (parent)
     {
@@ -230,76 +230,49 @@
 static void
 goo_canvas_text_finalize (GObject *object)
 {
-  GooCanvasText *item = (GooCanvasText*) object;
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasText *text = (GooCanvasText*) object;
 
-  g_free (item->text);
+  if (!simple->model)
+    {
+      g_free (text->text_data->text);
+      g_slice_free (GooCanvasTextData, text->text_data);
+    }
+  text->text_data = NULL;
 
   G_OBJECT_CLASS (goo_canvas_text_parent_class)->finalize (object);
 }
 
 
-static GooCanvasItemView*
-goo_canvas_text_create_view (GooCanvasItem     *item,
-			     GooCanvasView     *canvas_view,
-			     GooCanvasItemView *parent_view)
-{
-  return goo_canvas_text_view_new (canvas_view, parent_view,
-				   (GooCanvasText*) item);
-}
-
-
-static void
-item_interface_init (GooCanvasItemIface *iface)
-{
-  iface->create_view = goo_canvas_text_create_view;
-}
-
-
 static void
-goo_canvas_text_get_property (GObject              *object,
-			      guint                 prop_id,
-			      GValue               *value,
-			      GParamSpec           *pspec)
+goo_canvas_text_get_common_property (GObject                 *object,
+				     GooCanvasTextData       *text_data,
+				     guint                    prop_id,
+				     GValue                  *value,
+				     GParamSpec              *pspec)
 {
-  GooCanvasText *text = (GooCanvasText*) object;
-
   switch (prop_id)
     {
     case PROP_X:
-      g_value_set_double (value, text->x);
+      g_value_set_double (value, text_data->x);
       break;
     case PROP_Y:
-      g_value_set_double (value, text->y);
+      g_value_set_double (value, text_data->y);
       break;
     case PROP_WIDTH:
-      g_value_set_double (value, text->width);
+      g_value_set_double (value, text_data->width);
       break;
     case PROP_TEXT:
-      g_value_set_string (value, text->text);
+      g_value_set_string (value, text_data->text);
       break;
     case PROP_USE_MARKUP:
-      g_value_set_boolean (value, text->use_markup);
-      break;
-    case PROP_FONT:
-      if (text->font_desc)
-	{
-	  char *font = pango_font_description_to_string (text->font_desc);
-	  g_value_set_string (value, font);
-	  g_free (font);
-	}
-      else
-	{
-	  g_value_set_string (value, NULL);
-	}
-      break;
-    case PROP_FONT_DESC:
-      g_value_set_boxed (value, text->font_desc);
+      g_value_set_boolean (value, text_data->use_markup);
       break;
     case PROP_ANCHOR:
-      g_value_set_enum (value, text->anchor);
+      g_value_set_enum (value, text_data->anchor);
       break;
     case PROP_ALIGN:
-      g_value_set_enum (value, text->alignment);
+      g_value_set_enum (value, text_data->alignment);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -309,62 +282,543 @@
 
 
 static void
-goo_canvas_text_set_property (GObject              *object,
+goo_canvas_text_get_property (GObject              *object,
 			      guint                 prop_id,
-			      const GValue         *value,
+			      GValue               *value,
 			      GParamSpec           *pspec)
 {
   GooCanvasText *text = (GooCanvasText*) object;
-  const char *font_name;
-  PangoFontDescription *font_desc;
 
+  goo_canvas_text_get_common_property (object, text->text_data, prop_id,
+				       value, pspec);
+}
+
+
+static void
+goo_canvas_text_set_common_property (GObject                 *object,
+				     GooCanvasTextData       *text_data,
+				     guint                    prop_id,
+				     const GValue            *value,
+				     GParamSpec              *pspec)
+{
   switch (prop_id)
     {
     case PROP_X:
-      text->x = g_value_get_double (value);
+      text_data->x = g_value_get_double (value);
       break;
     case PROP_Y:
-      text->y = g_value_get_double (value);
+      text_data->y = g_value_get_double (value);
       break;
     case PROP_WIDTH:
-      text->width = g_value_get_double (value);
+      text_data->width = g_value_get_double (value);
       break;
     case PROP_TEXT:
-      g_free (text->text);
-      text->text = g_value_dup_string (value);
+      g_free (text_data->text);
+      text_data->text = g_value_dup_string (value);
       break;
     case PROP_USE_MARKUP:
-      text->use_markup = g_value_get_boolean (value);
-      break;
-    case PROP_FONT:
-      if (text->font_desc)
-	pango_font_description_free (text->font_desc);
-      font_name = g_value_get_string (value);
-      if (font_name)
-	text->font_desc = pango_font_description_from_string (font_name);
-      else
-	text->font_desc = NULL;
-      break;
-    case PROP_FONT_DESC:
-      if (text->font_desc)
-	pango_font_description_free (text->font_desc);
-      font_desc = g_value_peek_pointer (value);
-      if (font_desc)
-	text->font_desc = pango_font_description_copy (font_desc);
-      else
-	text->font_desc = NULL;
+      text_data->use_markup = g_value_get_boolean (value);
       break;
     case PROP_ANCHOR:
-      text->anchor = g_value_get_enum (value);
+      text_data->anchor = g_value_get_enum (value);
       break;
     case PROP_ALIGN:
-      text->alignment = g_value_get_enum (value);
+      text_data->alignment = g_value_get_enum (value);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
+}
 
-  g_signal_emit_by_name (text, "changed", TRUE);
+
+static void
+goo_canvas_text_set_property (GObject              *object,
+			      guint                 prop_id,
+			      const GValue         *value,
+			      GParamSpec           *pspec)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasText *text = (GooCanvasText*) object;
+
+  if (simple->model)
+    {
+      g_warning ("Can't set property of a canvas item with a model - set the model property instead");
+      return;
+    }
+
+  goo_canvas_text_set_common_property (object, text->text_data, prop_id,
+				       value, pspec);
+  goo_canvas_item_simple_changed (simple, TRUE);
+}
+
+
+static PangoLayout*
+goo_canvas_text_create_layout (GooCanvasText     *text,
+			       cairo_t           *cr,
+			       GooCanvasBounds   *bounds,
+			       gdouble	         *origin_x_return,
+			       gdouble	         *origin_y_return)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) text;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasTextData *text_data = text->text_data;
+  GooCanvasStyle *style = simple_data->style;
+  GValue *svalue;
+  PangoLayout *layout;
+  PangoContext *context;
+  PangoRectangle logical_rect;
+  double logical_width, logical_height, align_width, origin_x, origin_y;
+  gchar *string;
+
+  string = text_data->text ? text_data->text : "";
+
+  layout = pango_cairo_create_layout (cr);
+
+  /* Set the font options to ensure the text layout is the same whatever
+     the scale is. */
+  context = pango_layout_get_context (layout);
+  pango_cairo_context_set_font_options (context, GOO_CANVAS_TEXT_GET_CLASS (text)->font_options);
+
+  if (text_data->width > 0)
+    pango_layout_set_width (layout, (double) text_data->width * PANGO_SCALE);
+
+  if (text_data->use_markup)
+    pango_layout_set_markup (layout, string, -1);
+  else
+    pango_layout_set_text (layout, string, -1);
+
+  svalue = goo_canvas_style_get_property (style, goo_canvas_style_font_desc_id);
+  if (svalue)
+    pango_layout_set_font_description (layout, svalue->data[0].v_pointer);
+
+  if (text_data->alignment != PANGO_ALIGN_LEFT)
+    pango_layout_set_alignment (layout, text_data->alignment);
+
+  /* FIXME: Sometimes we should be using the ink_rect rather than the
+     logical rect, e.g. for the actual bounds of the item view. */
+  if (bounds)
+    {
+      /* Get size of the text, so we can position it according to anchor. */
+      pango_layout_get_extents (layout, NULL, &logical_rect);
+
+      logical_width = (double) logical_rect.width / PANGO_SCALE;
+      logical_height = (double) logical_rect.height / PANGO_SCALE;
+
+      /* If the text width has been set, that width is used to do the alignment
+	 positioning. Otherwise the actual width is used. */
+      if (text_data->width > 0)
+	align_width = text_data->width;
+      else
+	align_width = logical_width;
+
+      /* Now calculate the origin of the text, i.e. where we will tell Pango
+	 to draw it. */
+      origin_x = text_data->x;
+      origin_y = text_data->y;
+
+      switch (text_data->anchor)
+	{
+	case GTK_ANCHOR_N:
+	case GTK_ANCHOR_CENTER:
+	case GTK_ANCHOR_S:
+	  origin_x -= align_width / 2.0;
+	break;
+	case GTK_ANCHOR_NE:
+	case GTK_ANCHOR_E:
+	case GTK_ANCHOR_SE:
+	  origin_x -= align_width;
+	  break;
+	default:
+	  break;
+	}
+
+      switch (text_data->anchor)
+	{
+	case GTK_ANCHOR_W:
+	case GTK_ANCHOR_CENTER:
+	case GTK_ANCHOR_E:
+	  origin_y -= logical_height / 2.0;
+	  break;
+	case GTK_ANCHOR_SW:
+	case GTK_ANCHOR_S:
+	case GTK_ANCHOR_SE:
+	  origin_y -= logical_height;
+	  break;
+	default:
+	  break;
+	}
+
+      /* Return the origin of the text if required. */
+      if (origin_x_return)
+	*origin_x_return = origin_x;
+      if (origin_y_return)
+	*origin_y_return = origin_y;
+
+      /* Now calculate the bounds. */
+      bounds->x1 = origin_x;
+      bounds->y1 = origin_y;
+
+      if (text_data->width > 0)
+	{
+	  /* If the text width has been set, and the alignment isn't
+	     PANGO_ALIGN_LEFT, we need to adjust for the difference between
+	     the actual width of the text and the width that was used for
+	     alignment. */
+	  switch (text_data->alignment)
+	    {
+	    case PANGO_ALIGN_CENTER:
+	      bounds->x1 += (align_width - logical_width) / 2.0;
+	      break;
+	    case PANGO_ALIGN_RIGHT:
+	      bounds->x1 += align_width - logical_width;
+	      break;
+	    default:
+	      break;
+	    }
+	}
+
+      bounds->x2 = origin_x + logical_width;
+      bounds->y2 = origin_y + logical_height;
+    }
+
+  return layout;
+}
+
+
+static void
+goo_canvas_text_update  (GooCanvasItem      *item,
+			 gboolean            entire_tree,
+			 cairo_t            *cr,
+			 GooCanvasBounds    *bounds)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasText *text = (GooCanvasText*) item;
+  PangoLayout *layout;
+
+  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);
+
+      /* Compute the new bounds. */
+      layout = goo_canvas_text_create_layout (text, cr, &simple->bounds,
+					      NULL, NULL);
+      g_object_unref (layout);
+
+      goo_canvas_item_simple_user_bounds_to_device (simple, cr,
+						    &simple->bounds);
+
+      /* Request a redraw of the new bounds. */
+      goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+
+      cairo_restore (cr);
+    }
+
+  *bounds = simple->bounds;
 }
 
+
+static GooCanvasItem*
+goo_canvas_text_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;
+  GooCanvasText *text = (GooCanvasText*) item;
+  GooCanvasItem *found_item = NULL;
+  PangoLayout *layout;
+  GooCanvasBounds bounds;
+  PangoLayoutIter *iter;
+  PangoRectangle log_rect;
+  int px, py;
+  double user_x = x, user_y = y;
+  gdouble origin_x, origin_y;
+
+  /* If there is no text just return. */
+  if (!text->text_data->text || !text->text_data->text[0])
+    return NULL;
+
+  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;
+      if (simple_data->pointer_events & GOO_CANVAS_EVENTS_PAINTED_MASK)
+	{
+	  if (!goo_canvas_style_set_fill_options (simple_data->style, cr))
+	    return NULL;
+	}
+    }
+
+  cairo_save (cr);
+  if (simple_data->transform)
+    cairo_transform (cr, simple_data->transform);
+
+  cairo_device_to_user (cr, &user_x, &user_y);
+
+  layout = goo_canvas_text_create_layout (text, cr, &bounds,
+					  &origin_x, &origin_y);
+
+  /* Convert the coordinates into Pango units. */
+  px = (user_x - origin_x) * PANGO_SCALE;
+  py = (user_y - origin_y) * PANGO_SCALE;
+
+  /* We use line extents here. Note that SVG uses character cells to determine
+     hits so we have slightly different behavior. */
+  iter = pango_layout_get_iter (layout);
+  do
+    {
+      pango_layout_iter_get_line_extents (iter, NULL, &log_rect);
+
+      if (px >= log_rect.x && px < log_rect.x + log_rect.width 
+	  && py >= log_rect.y && py < log_rect.y + log_rect.height)
+	{
+	  found_item = item;
+	  break;
+	}
+
+    } while (pango_layout_iter_next_line (iter));
+
+  pango_layout_iter_free (iter);
+
+  g_object_unref (layout);
+
+  cairo_restore (cr);
+
+  return found_item;
+}
+
+
+static void
+goo_canvas_text_paint (GooCanvasItem     *item,
+		       cairo_t           *cr,
+		       GooCanvasBounds   *bounds,
+		       gdouble            scale)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasText *text = (GooCanvasText*) item;
+  PangoLayout *layout;
+  GooCanvasBounds layout_bounds;
+  gdouble origin_x, origin_y;
+
+  /* If there is no text just return. */
+  if (!text->text_data->text || !text->text_data->text[0])
+    return;
+
+  /* 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);
+
+  goo_canvas_style_set_fill_options (simple_data->style, cr);
+
+  cairo_new_path (cr);
+  layout = goo_canvas_text_create_layout (text, cr, &layout_bounds,
+					  &origin_x, &origin_y);
+  cairo_move_to (cr, origin_x, origin_y);
+  pango_cairo_show_layout (cr, layout);
+  g_object_unref (layout);
+
+  cairo_restore (cr);
+}
+
+
+static void
+goo_canvas_text_set_model    (GooCanvasItem      *item,
+			      GooCanvasItemModel *model)
+{
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+  GooCanvasItemIface *parent_iface = g_type_interface_peek_parent (iface);
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasText *text = (GooCanvasText*) item;
+  GooCanvasTextModel *emodel = (GooCanvasTextModel*) model;
+
+  /* If our text_data was allocated, free it. */
+  if (!simple->model)
+    g_slice_free (GooCanvasTextData, text->text_data);
+
+  /* Now use the new model's text_data instead. */
+  text->text_data = &emodel->text_data;
+
+  /* Let the parent GooCanvasItemSimple code do the rest. */
+  parent_iface->set_model (item, model);
+}
+
+
+static void
+canvas_item_interface_init (GooCanvasItemIface *iface)
+{
+  iface->get_item_at = goo_canvas_text_get_item_at;
+  iface->update      = goo_canvas_text_update;
+  iface->paint       = goo_canvas_text_paint;
+  iface->set_model   = goo_canvas_text_set_model;
+}
+
+
+
+/*
+ * GooCanvasTextModel.
+ */
+
+static void item_model_interface_init (GooCanvasItemModelIface *iface);
+static void goo_canvas_text_model_finalize     (GObject            *object);
+static void goo_canvas_text_model_get_property (GObject            *object,
+						guint               param_id,
+						GValue             *value,
+						GParamSpec         *pspec);
+static void goo_canvas_text_model_set_property (GObject            *object,
+						guint               param_id,
+						const GValue       *value,
+						GParamSpec         *pspec);
+
+G_DEFINE_TYPE_WITH_CODE (GooCanvasTextModel, goo_canvas_text_model,
+			 GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE,
+			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM_MODEL,
+						item_model_interface_init))
+
+
+static void
+goo_canvas_text_model_class_init (GooCanvasTextModelClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+
+  gobject_class->finalize     = goo_canvas_text_model_finalize;
+
+  gobject_class->get_property = goo_canvas_text_model_get_property;
+  gobject_class->set_property = goo_canvas_text_model_set_property;
+
+  goo_canvas_text_install_common_properties (gobject_class);
+}
+
+
+static void
+goo_canvas_text_model_init (GooCanvasTextModel *emodel)
+{
+
+}
+
+
+GooCanvasItemModel*
+goo_canvas_text_model_new (GooCanvasItemModel *parent,
+			   const char         *string,
+			   gdouble             x,
+			   gdouble             y,
+			   gdouble             width,
+			   GtkAnchorType       anchor,
+			   ...)
+{
+  GooCanvasItemModel *model;
+  GooCanvasTextModel *emodel;
+  GooCanvasTextData *text_data;
+  const char *first_property;
+  va_list var_args;
+
+  model = g_object_new (GOO_TYPE_CANVAS_TEXT_MODEL, NULL);
+  emodel = (GooCanvasTextModel*) model;
+
+  text_data = &emodel->text_data;
+  text_data->text = g_strdup (string);
+  text_data->x = x;
+  text_data->y = y;
+  text_data->width = width;
+  text_data->anchor = anchor;
+
+  va_start (var_args, anchor);
+  first_property = va_arg (var_args, char*);
+  if (first_property)
+    g_object_set_valist ((GObject*) model, first_property, var_args);
+  va_end (var_args);
+
+  if (parent)
+    {
+      goo_canvas_item_model_add_child (parent, model, -1);
+      g_object_unref (model);
+    }
+
+  return model;
+}
+
+
+static void
+goo_canvas_text_model_finalize (GObject *object)
+{
+  /*GooCanvasTextModel *emodel = (GooCanvasTextModel*) object;*/
+
+  G_OBJECT_CLASS (goo_canvas_text_model_parent_class)->finalize (object);
+}
+
+
+static void
+goo_canvas_text_model_get_property (GObject              *object,
+				    guint                 prop_id,
+				    GValue               *value,
+				    GParamSpec           *pspec)
+{
+  GooCanvasTextModel *emodel = (GooCanvasTextModel*) object;
+
+  goo_canvas_text_get_common_property (object, &emodel->text_data, prop_id,
+				       value, pspec);
+}
+
+
+static void
+goo_canvas_text_model_set_property (GObject              *object,
+				    guint                 prop_id,
+				    const GValue         *value,
+				    GParamSpec           *pspec)
+{
+  GooCanvasTextModel *emodel = (GooCanvasTextModel*) object;
+
+  goo_canvas_text_set_common_property (object, &emodel->text_data, prop_id,
+				       value, pspec);
+  g_signal_emit_by_name (emodel, "changed", TRUE);
+}
+
+
+static GooCanvasItem*
+goo_canvas_text_model_create_item (GooCanvasItemModel *model,
+				   GooCanvas          *canvas)
+{
+  GooCanvasItem *item;
+
+  item = g_object_new (GOO_TYPE_CANVAS_TEXT, NULL);
+  goo_canvas_item_set_model (item, model);
+
+  return item;
+}
+
+
+static void
+item_model_interface_init (GooCanvasItemModelIface *iface)
+{
+  iface->create_item    = goo_canvas_text_model_create_item;
+}

Index: goocanvastext.h
===================================================================
RCS file: /cvs/cairo/goocanvas/src/goocanvastext.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- goocanvastext.h	13 Apr 2006 16:06:04 -0000	1.3
+++ goocanvastext.h	29 Nov 2006 18:40:53 -0000	1.4
@@ -13,6 +13,19 @@
 G_BEGIN_DECLS
 
 
+/* This is the data used by both model and view classes. */
+typedef struct _GooCanvasTextData   GooCanvasTextData;
+struct _GooCanvasTextData
+{
+  gchar *text;
+  gboolean use_markup;
+
+  gdouble x, y, width;
+  GtkAnchorType anchor;
+  PangoAlignment alignment;
+};
+
+
 #define GOO_TYPE_CANVAS_TEXT            (goo_canvas_text_get_type ())
 #define GOO_CANVAS_TEXT(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_TEXT, GooCanvasText))
 #define GOO_CANVAS_TEXT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_TEXT, GooCanvasTextClass))
@@ -33,30 +46,68 @@
 {
   GooCanvasItemSimple parent;
 
-  gchar *text;
-  gboolean use_markup;
-  PangoFontDescription *font_desc;
-
-  gdouble x, y, width;
-  GtkAnchorType anchor;
-  PangoAlignment alignment;
+  GooCanvasTextData *text_data;
 };
 
 struct _GooCanvasTextClass
 {
   GooCanvasItemSimpleClass parent_class;
+
+  /* The font options we always use. */
+  cairo_font_options_t *font_options;
 };
 
 
-GType          goo_canvas_text_get_type        (void) G_GNUC_CONST;
-GooCanvasItem* goo_canvas_text_new             (GooCanvasItem *parent,
-						const char    *string,
-						gdouble        x,
-						gdouble        y,
-						gdouble        width,
-						GtkAnchorType  anchor,
-						const gchar   *first_property,
-						...);
+GType               goo_canvas_text_get_type  (void) G_GNUC_CONST;
+
+GooCanvasItem*      goo_canvas_text_new       (GooCanvasItem      *parent,
+					       const char         *string,
+					       gdouble             x,
+					       gdouble             y,
+					       gdouble             width,
+					       GtkAnchorType       anchor,
+					       ...);
+
+
+
+#define GOO_TYPE_CANVAS_TEXT_MODEL            (goo_canvas_text_model_get_type ())
+#define GOO_CANVAS_TEXT_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_TEXT_MODEL, GooCanvasTextModel))
+#define GOO_CANVAS_TEXT_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_TEXT_MODEL, GooCanvasTextModelClass))
+#define GOO_IS_CANVAS_TEXT_MODEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_TEXT_MODEL))
+#define GOO_IS_CANVAS_TEXT_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_TEXT_MODEL))
+#define GOO_CANVAS_TEXT_MODEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_TEXT_MODEL, GooCanvasTextModelClass))
+
+
+typedef struct _GooCanvasTextModel       GooCanvasTextModel;
+typedef struct _GooCanvasTextModelClass  GooCanvasTextModelClass;
+
+/**
+ * GooCanvasTextModel
+ *
+ * The #GooCanvasTextModel-struct struct contains private data only.
+ */
+struct _GooCanvasTextModel
+{
+  GooCanvasItemModelSimple parent_object;
+
+  GooCanvasTextData text_data;
+};
+
+struct _GooCanvasTextModelClass
+{
+  GooCanvasItemModelSimpleClass parent_class;
+};
+
+
+GType               goo_canvas_text_model_get_type  (void) G_GNUC_CONST;
+
+GooCanvasItemModel* goo_canvas_text_model_new (GooCanvasItemModel *parent,
+					       const char         *string,
+					       gdouble             x,
+					       gdouble             y,
+					       gdouble             width,
+					       GtkAnchorType       anchor,
+					       ...);
 
 
 G_END_DECLS

--- goocanvastextview.c DELETED ---

--- goocanvastextview.h DELETED ---

--- goocanvasview.c DELETED ---

--- goocanvasview.h DELETED ---



More information about the cairo-commit mailing list