[gcompris/gcomprixogoo] Updated with upstream goocanvas 0.15 and pygoocanvas 0.14.1.



commit 56b9c4f4c887c18d2be1a2dd752ab73ead65ba6d
Author: Bruno Coudoin <bruno coudoin free fr>
Date:   Sun Nov 8 16:16:26 2009 +0100

    Updated with upstream goocanvas 0.15 and pygoocanvas 0.14.1.
    (I patched pygoocanvas to make it compile with goocanvas 0.15).

 src/boards/goocanvas.c                  | 1777 +++++++++++++++++++------------
 src/boards/goocanvas.defs               |  160 +++-
 src/boards/goocanvas.override           |  440 ++++++++-
 src/boards/goocanvasmodule.c            |   10 +-
 src/goocanvas/src/goocanvas.c           |  665 +++++++++++-
 src/goocanvas/src/goocanvas.h           |   19 +
 src/goocanvas/src/goocanvasatk.c        |   27 +-
 src/goocanvas/src/goocanvasellipse.c    |   93 ++-
 src/goocanvas/src/goocanvasgrid.c       | 1170 ++++++++++++++++++++
 src/goocanvas/src/goocanvasgrid.h       |  153 +++
 src/goocanvas/src/goocanvasgroup.c      |  373 ++++++-
 src/goocanvas/src/goocanvasitem.c       |  277 ++++--
 src/goocanvas/src/goocanvasitem.h       |   29 +-
 src/goocanvas/src/goocanvasitemmodel.c  |  103 +-
 src/goocanvas/src/goocanvasitemmodel.h  |    2 -
 src/goocanvas/src/goocanvasitemsimple.c |  201 ++--
 src/goocanvas/src/goocanvasitemsimple.h |    8 +-
 src/goocanvas/src/goocanvasmarshal.c    |   45 +
 src/goocanvas/src/goocanvasmarshal.h    |    8 +
 src/goocanvas/src/goocanvaspath.c       |  359 ++++++-
 src/goocanvas/src/goocanvaspolyline.c   |  162 +++-
 src/goocanvas/src/goocanvasprivate.h    |   17 +
 src/goocanvas/src/goocanvasrect.c       |    1 -
 src/goocanvas/src/goocanvastable.c      |  199 +++--
 src/goocanvas/src/goocanvastext.c       |  132 ++-
 src/goocanvas/src/goocanvasutils.c      |  102 ++-
 src/goocanvas/src/goocanvasutils.h      |   88 ++-
 src/goocanvas/src/goocanvaswidget.c     |  120 ++-
 28 files changed, 5502 insertions(+), 1238 deletions(-)
---
diff --git a/src/boards/goocanvas.c b/src/boards/goocanvas.c
index f94b5be..7136d93 100644
--- a/src/boards/goocanvas.c
+++ b/src/boards/goocanvas.c
@@ -207,6 +207,8 @@ static PyTypeObject *_PyGtkContainer_Type;
 #define PyGtkContainer_Type (*_PyGtkContainer_Type)
 static PyTypeObject *_PyGtkAdjustment_Type;
 #define PyGtkAdjustment_Type (*_PyGtkAdjustment_Type)
+static PyTypeObject *_PyGdkCairoContext_Type;
+#define PyGdkCairoContext_Type (*_PyGdkCairoContext_Type)
 
 
 /* ---------- forward type declarations ---------- */
@@ -219,7 +221,6 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvasGroupModel_Type;
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasEllipseModel_Type;
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasItemSimple_Type;
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasImage_Type;
-PyTypeObject G_GNUC_INTERNAL PyGooCanvasSvg_Type;
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasGroup_Type;
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasEllipse_Type;
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasPath_Type;
@@ -238,7 +239,7 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvasItem_Type;
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasItemModel_Type;
 
 
-#line 664 "goocanvas.override"
+#line 667 "goocanvas.override"
 
 static PyObject *
 _py_canvas_style_get_property(GooCanvasStyle *style,
@@ -289,13 +290,13 @@ _py_goo_canvas_style_set_property(GooCanvasStyle *style,
 }
 
 
-#line 293 "goocanvas.c"
+#line 296 "goocanvas.c"
 
 
 
 /* ----------- GooCanvasPoints ----------- */
 
-#line 280 "goocanvas.override"
+#line 283 "goocanvas.override"
 static int
 _wrap_goo_canvas_points_new(PyGBoxed *self, PyObject *args, PyObject *kwargs)
 {
@@ -322,9 +323,52 @@ _wrap_goo_canvas_points_new(PyGBoxed *self, PyObject *args, PyObject *kwargs)
     self->gtype = GOO_TYPE_CANVAS_POINTS;
     return 0;
 }
-#line 326 "goocanvas.c"
+#line 329 "goocanvas.c"
 
 
+#line 1883 "goocanvas.override"
+
+static PyObject *
+_wrap_goo_canvas_points__get_coords(PyObject *self, void *closure)
+{
+    gdouble     *coords;
+    int         num_points, i;
+    PyObject    *ret = Py_None;
+
+    num_points = pyg_boxed_get(self, GooCanvasPoints)->num_points;
+    coords = pyg_boxed_get(self, GooCanvasPoints)->coords;
+
+    if (num_points > 0) {
+        ret = PyList_New(num_points);
+
+        for (i = 0; i < num_points; i ++) {
+            PyObject *py_temp = Py_BuildValue("dd", coords[2*i], coords[2*i + 1]);
+            PyList_SetItem(ret, i, py_temp);
+        }
+        return ret;
+    }
+    Py_INCREF(ret);
+    return ret;
+}
+
+#line 357 "goocanvas.c"
+
+
+static PyObject *
+_wrap_goo_canvas_points__get_num_points(PyObject *self, void *closure)
+{
+    int ret;
+
+    ret = pyg_boxed_get(self, GooCanvasPoints)->num_points;
+    return PyInt_FromLong(ret);
+}
+
+static const PyGetSetDef goo_canvas_points_getsets[] = {
+    { "coords", (getter)_wrap_goo_canvas_points__get_coords, (setter)0 },
+    { "num_points", (getter)_wrap_goo_canvas_points__get_num_points, (setter)0 },
+    { NULL, (getter)0, (setter)0 },
+};
+
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasPoints_Type = {
     PyObject_HEAD_INIT(NULL)
     0,                                 /* ob_size */
@@ -357,7 +401,7 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvasPoints_Type = {
     (iternextfunc)0,     /* tp_iternext */
     (struct PyMethodDef*)NULL, /* tp_methods */
     (struct PyMemberDef*)0,              /* tp_members */
-    (struct PyGetSetDef*)0,  /* tp_getset */
+    (struct PyGetSetDef*)goo_canvas_points_getsets,  /* tp_getset */
     NULL,                              /* tp_base */
     NULL,                              /* tp_dict */
     (descrgetfunc)0,    /* tp_descr_get */
@@ -374,7 +418,7 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvasPoints_Type = {
 
 /* ----------- GooCanvasLineDash ----------- */
 
-#line 445 "goocanvas.override"
+#line 448 "goocanvas.override"
 static int
 _wrap_goo_canvas_line_dash_newv(PyGBoxed *self, PyObject *args, PyObject *kwargs)
 {
@@ -411,7 +455,7 @@ _wrap_goo_canvas_line_dash_newv(PyGBoxed *self, PyObject *args, PyObject *kwargs
     self->free_on_dealloc = TRUE;
     return 0;
 }
-#line 415 "goocanvas.c"
+#line 461 "goocanvas.c"
 
 
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasLineDash_Type = {
@@ -463,34 +507,14 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvasLineDash_Type = {
 
 /* ----------- GooCanvas ----------- */
 
-static int
-_wrap_goo_canvas_new(PyGObject *self, PyObject *args, PyObject *kwargs)
-{
-    static char* kwlist[] = { NULL };
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
-                                     ":goocanvas.Canvas.__init__",
-                                     kwlist))
-        return -1;
-
-    pygobject_constructv(self, 0, NULL);
-    if (!self->obj) {
-        PyErr_SetString(
-            PyExc_RuntimeError, 
-            "could not create goocanvas.Canvas object");
-        return -1;
-    }
-    return 0;
-}
-
 static PyObject *
 _wrap_goo_canvas_get_root_item(PyGObject *self)
 {
     GooCanvasItem *ret;
 
-    
+
     ret = goo_canvas_get_root_item(GOO_CANVAS(self->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -503,9 +527,9 @@ _wrap_goo_canvas_set_root_item(PyGObject *self, PyObject *args, PyObject *kwargs
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.set_root_item", kwlist, &PyGooCanvasItem_Type, &item))
         return NULL;
-    
+
     goo_canvas_set_root_item(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM(item->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -515,9 +539,9 @@ _wrap_goo_canvas_get_root_item_model(PyGObject *self)
 {
     GooCanvasItemModel *ret;
 
-    
+
     ret = goo_canvas_get_root_item_model(GOO_CANVAS(self->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -530,9 +554,63 @@ _wrap_goo_canvas_set_root_item_model(PyGObject *self, PyObject *args, PyObject *
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.set_root_item_model", kwlist, &PyGooCanvasItemModel_Type, &model))
         return NULL;
-    
+
     goo_canvas_set_root_item_model(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM_MODEL(model->obj));
-    
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+_wrap_goo_canvas_get_static_root_item(PyGObject *self)
+{
+    GooCanvasItem *ret;
+
+
+    ret = goo_canvas_get_static_root_item(GOO_CANVAS(self->obj));
+
+    /* pygobject_new handles NULL checking */
+    return pygobject_new((GObject *)ret);
+}
+
+static PyObject *
+_wrap_goo_canvas_set_static_root_item(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "item", NULL };
+    PyGObject *item;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.set_static_root_item", kwlist, &PyGooCanvasItem_Type, &item))
+        return NULL;
+
+    goo_canvas_set_static_root_item(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM(item->obj));
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+_wrap_goo_canvas_get_static_root_item_model(PyGObject *self)
+{
+    GooCanvasItemModel *ret;
+
+
+    ret = goo_canvas_get_static_root_item_model(GOO_CANVAS(self->obj));
+
+    /* pygobject_new handles NULL checking */
+    return pygobject_new((GObject *)ret);
+}
+
+static PyObject *
+_wrap_goo_canvas_set_static_root_item_model(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "model", NULL };
+    PyGObject *model;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.set_static_root_item_model", kwlist, &PyGooCanvasItemModel_Type, &model))
+        return NULL;
+
+    goo_canvas_set_static_root_item_model(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM_MODEL(model->obj));
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -546,9 +624,9 @@ _wrap_goo_canvas_get_item(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.get_item", kwlist, &PyGooCanvasItemModel_Type, &model))
         return NULL;
-    
+
     ret = goo_canvas_get_item(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM_MODEL(model->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -563,14 +641,14 @@ _wrap_goo_canvas_get_item_at(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"ddi:GooCanvas.get_item_at", kwlist, &x, &y, &is_pointer_event))
         return NULL;
-    
+
     ret = goo_canvas_get_item_at(GOO_CANVAS(self->obj), x, y, is_pointer_event);
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
 
-#line 1437 "goocanvas.override"
+#line 1440 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_get_items_at(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -601,10 +679,10 @@ _wrap_goo_canvas_get_items_at(PyGObject *self, PyObject *args, PyObject *kwargs)
     return ret;
 }
 
-#line 605 "goocanvas.c"
+#line 685 "goocanvas.c"
 
 
-#line 1469 "goocanvas.override"
+#line 1472 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_get_items_in_area(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -642,7 +720,7 @@ _wrap_goo_canvas_get_items_in_area(PyGObject *self, PyObject *args, PyObject *kw
     return ret;
 }
 
-#line 646 "goocanvas.c"
+#line 726 "goocanvas.c"
 
 
 static PyObject *
@@ -650,9 +728,9 @@ _wrap_goo_canvas_get_scale(PyGObject *self)
 {
     double ret;
 
-    
+
     ret = goo_canvas_get_scale(GOO_CANVAS(self->obj));
-    
+
     return PyFloat_FromDouble(ret);
 }
 
@@ -664,14 +742,14 @@ _wrap_goo_canvas_set_scale(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"d:GooCanvas.set_scale", kwlist, &pixels_per_unit))
         return NULL;
-    
+
     goo_canvas_set_scale(GOO_CANVAS(self->obj), pixels_per_unit);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-#line 513 "goocanvas.override"
+#line 516 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_get_bounds(PyGObject *self)
 {
@@ -682,7 +760,7 @@ _wrap_goo_canvas_get_bounds(PyGObject *self)
     return Py_BuildValue("dddd", left, right, top, bottom);
 }
 
-#line 686 "goocanvas.c"
+#line 766 "goocanvas.c"
 
 
 static PyObject *
@@ -693,9 +771,9 @@ _wrap_goo_canvas_set_bounds(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"dddd:GooCanvas.set_bounds", kwlist, &left, &top, &right, &bottom))
         return NULL;
-    
+
     goo_canvas_set_bounds(GOO_CANVAS(self->obj), left, top, right, bottom);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -708,9 +786,9 @@ _wrap_goo_canvas_scroll_to(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"dd:GooCanvas.scroll_to", kwlist, &left, &top))
         return NULL;
-    
+
     goo_canvas_scroll_to(GOO_CANVAS(self->obj), left, top);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -723,9 +801,9 @@ _wrap_goo_canvas_grab_focus(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.grab_focus", kwlist, &PyGooCanvasItem_Type, &item))
         return NULL;
-    
+
     goo_canvas_grab_focus(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM(item->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -740,19 +818,19 @@ _wrap_goo_canvas_render(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!|Od:GooCanvas.render", kwlist, &PycairoContext_Type, &cr, &py_bounds, &scale))
         return NULL;
-    if (!(py_bounds == NULL || py_bounds == Py_None || 
+    if (!(py_bounds == NULL || py_bounds == Py_None ||
         PyObject_IsInstance(py_bounds, (PyObject *) &PyGooCanvasBounds_Type))) {
         PyErr_SetString(PyExc_TypeError, "parameter bounds must be goocanvas.Bounds or None");
         return NULL;
     }
-    
+
     goo_canvas_render(GOO_CANVAS(self->obj), cr->ctx, (py_bounds == NULL || py_bounds == Py_None)? NULL : &((PyGooCanvasBounds *) py_bounds)->bounds, scale);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-#line 540 "goocanvas.override"
+#line 543 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_convert_to_pixels(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -767,10 +845,10 @@ _wrap_goo_canvas_convert_to_pixels(PyGObject *self, PyObject *args, PyObject *kw
     return Py_BuildValue("dd", x, y);
 }
 
-#line 771 "goocanvas.c"
+#line 851 "goocanvas.c"
 
 
-#line 556 "goocanvas.override"
+#line 559 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_convert_from_pixels(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -785,10 +863,10 @@ _wrap_goo_canvas_convert_from_pixels(PyGObject *self, PyObject *args, PyObject *
     return Py_BuildValue("dd", x, y);
 }
 
-#line 789 "goocanvas.c"
+#line 869 "goocanvas.c"
 
 
-#line 572 "goocanvas.override"
+#line 575 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_convert_to_item_space(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -804,10 +882,10 @@ _wrap_goo_canvas_convert_to_item_space(PyGObject *self, PyObject *args, PyObject
 
     return Py_BuildValue("dd", x, y);
 }
-#line 808 "goocanvas.c"
+#line 888 "goocanvas.c"
 
 
-#line 589 "goocanvas.override"
+#line 592 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_convert_from_item_space(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -823,10 +901,26 @@ _wrap_goo_canvas_convert_from_item_space(PyGObject *self, PyObject *args, PyObje
 
     return Py_BuildValue("dd", x, y);
 }
-#line 827 "goocanvas.c"
+#line 907 "goocanvas.c"
 
 
 static PyObject *
+_wrap_goo_canvas_convert_bounds_to_item_space(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "item", "bounds", NULL };
+    PyGObject *item;
+    PyObject *py_bounds;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!O!:GooCanvas.convert_bounds_to_item_space", kwlist, &PyGooCanvasItem_Type, &item, &PyGooCanvasBounds_Type, &py_bounds))
+        return NULL;
+
+    goo_canvas_convert_bounds_to_item_space(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM(item->obj), (py_bounds == NULL)? NULL : &((PyGooCanvasBounds *) py_bounds)->bounds);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
 _wrap_goo_canvas_pointer_grab(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
     static char *kwlist[] = { "item", "event_mask", "cursor", "time", NULL };
@@ -847,9 +941,9 @@ _wrap_goo_canvas_pointer_grab(PyGObject *self, PyObject *args, PyObject *kwargs)
         PyErr_SetString(PyExc_TypeError, "cursor should be a GdkCursor or None");
         return NULL;
     }
-    
+
     ret = goo_canvas_pointer_grab(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM(item->obj), event_mask, cursor, time);
-    
+
     return pyg_enum_from_gtype(GDK_TYPE_GRAB_STATUS, ret);
 }
 
@@ -862,9 +956,9 @@ _wrap_goo_canvas_pointer_ungrab(PyGObject *self, PyObject *args, PyObject *kwarg
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!k:GooCanvas.pointer_ungrab", kwlist, &PyGooCanvasItem_Type, &item, &time))
         return NULL;
-    
+
     goo_canvas_pointer_ungrab(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM(item->obj), time);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -880,9 +974,9 @@ _wrap_goo_canvas_keyboard_grab(PyGObject *self, PyObject *args, PyObject *kwargs
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!ik:GooCanvas.keyboard_grab", kwlist, &PyGooCanvasItem_Type, &item, &owner_events, &time))
         return NULL;
-    
+
     ret = goo_canvas_keyboard_grab(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM(item->obj), owner_events, time);
-    
+
     return pyg_enum_from_gtype(GDK_TYPE_GRAB_STATUS, ret);
 }
 
@@ -895,24 +989,26 @@ _wrap_goo_canvas_keyboard_ungrab(PyGObject *self, PyObject *args, PyObject *kwar
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!k:GooCanvas.keyboard_ungrab", kwlist, &PyGooCanvasItem_Type, &item, &time))
         return NULL;
-    
+
     goo_canvas_keyboard_ungrab(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM(item->obj), time);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
+#line 2032 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_create_cairo_context(PyGObject *self)
 {
     cairo_t *ret;
 
-    
     ret = goo_canvas_create_cairo_context(GOO_CANVAS(self->obj));
-    
+
     cairo_reference(ret);
-    return PycairoContext_FromContext(ret, NULL, NULL);
+    return PycairoContext_FromContext(ret, &PyGdkCairoContext_Type, NULL);
 }
+#line 1013 "goocanvas.c"
+
 
 static PyObject *
 _wrap_goo_canvas_create_item(PyGObject *self, PyObject *args, PyObject *kwargs)
@@ -923,9 +1019,9 @@ _wrap_goo_canvas_create_item(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.create_item", kwlist, &PyGooCanvasItemModel_Type, &model))
         return NULL;
-    
+
     ret = goo_canvas_create_item(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM_MODEL(model->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -938,9 +1034,9 @@ _wrap_goo_canvas_unregister_item(PyGObject *self, PyObject *args, PyObject *kwar
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.unregister_item", kwlist, &PyGooCanvasItemModel_Type, &model))
         return NULL;
-    
+
     goo_canvas_unregister_item(GOO_CANVAS(self->obj), GOO_CANVAS_ITEM_MODEL(model->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -948,9 +1044,9 @@ _wrap_goo_canvas_unregister_item(PyGObject *self, PyObject *args, PyObject *kwar
 static PyObject *
 _wrap_goo_canvas_update(PyGObject *self)
 {
-    
+
     goo_canvas_update(GOO_CANVAS(self->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -958,9 +1054,9 @@ _wrap_goo_canvas_update(PyGObject *self)
 static PyObject *
 _wrap_goo_canvas_request_update(PyGObject *self)
 {
-    
+
     goo_canvas_request_update(GOO_CANVAS(self->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -973,9 +1069,25 @@ _wrap_goo_canvas_request_redraw(PyGObject *self, PyObject *args, PyObject *kwarg
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.request_redraw", kwlist, &PyGooCanvasBounds_Type, &py_bounds))
         return NULL;
-    
+
     goo_canvas_request_redraw(GOO_CANVAS(self->obj), (py_bounds == NULL)? NULL : &((PyGooCanvasBounds *) py_bounds)->bounds);
-    
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+_wrap_goo_canvas_request_item_redraw(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "bounds", "is_static", NULL };
+    PyObject *py_bounds;
+    int is_static;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!i:GooCanvas.request_item_redraw", kwlist, &PyGooCanvasBounds_Type, &py_bounds, &is_static))
+        return NULL;
+
+    goo_canvas_request_item_redraw(GOO_CANVAS(self->obj), (py_bounds == NULL)? NULL : &((PyGooCanvasBounds *) py_bounds)->bounds, is_static);
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -985,9 +1097,9 @@ _wrap_goo_canvas_get_default_line_width(PyGObject *self)
 {
     double ret;
 
-    
+
     ret = goo_canvas_get_default_line_width(GOO_CANVAS(self->obj));
-    
+
     return PyFloat_FromDouble(ret);
 }
 
@@ -999,9 +1111,9 @@ _wrap_goo_canvas_register_widget_item(PyGObject *self, PyObject *args, PyObject
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.register_widget_item", kwlist, &PyGooCanvasWidget_Type, &witem))
         return NULL;
-    
+
     goo_canvas_register_widget_item(GOO_CANVAS(self->obj), GOO_CANVAS_WIDGET(witem->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1014,9 +1126,9 @@ _wrap_goo_canvas_unregister_widget_item(PyGObject *self, PyObject *args, PyObjec
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvas.unregister_widget_item", kwlist, &PyGooCanvasWidget_Type, &witem))
         return NULL;
-    
+
     goo_canvas_unregister_widget_item(GOO_CANVAS(self->obj), GOO_CANVAS_WIDGET(witem->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1097,6 +1209,14 @@ static const PyMethodDef _PyGooCanvas_methods[] = {
       NULL },
     { "set_root_item_model", (PyCFunction)_wrap_goo_canvas_set_root_item_model, METH_VARARGS|METH_KEYWORDS,
       NULL },
+    { "get_static_root_item", (PyCFunction)_wrap_goo_canvas_get_static_root_item, METH_NOARGS,
+      NULL },
+    { "set_static_root_item", (PyCFunction)_wrap_goo_canvas_set_static_root_item, METH_VARARGS|METH_KEYWORDS,
+      NULL },
+    { "get_static_root_item_model", (PyCFunction)_wrap_goo_canvas_get_static_root_item_model, METH_NOARGS,
+      NULL },
+    { "set_static_root_item_model", (PyCFunction)_wrap_goo_canvas_set_static_root_item_model, METH_VARARGS|METH_KEYWORDS,
+      NULL },
     { "get_item", (PyCFunction)_wrap_goo_canvas_get_item, METH_VARARGS|METH_KEYWORDS,
       NULL },
     { "get_item_at", (PyCFunction)_wrap_goo_canvas_get_item_at, METH_VARARGS|METH_KEYWORDS,
@@ -1127,6 +1247,8 @@ static const PyMethodDef _PyGooCanvas_methods[] = {
       NULL },
     { "convert_from_item_space", (PyCFunction)_wrap_goo_canvas_convert_from_item_space, METH_VARARGS|METH_KEYWORDS,
       NULL },
+    { "convert_bounds_to_item_space", (PyCFunction)_wrap_goo_canvas_convert_bounds_to_item_space, METH_VARARGS|METH_KEYWORDS,
+      NULL },
     { "pointer_grab", (PyCFunction)_wrap_goo_canvas_pointer_grab, METH_VARARGS|METH_KEYWORDS,
       NULL },
     { "pointer_ungrab", (PyCFunction)_wrap_goo_canvas_pointer_ungrab, METH_VARARGS|METH_KEYWORDS,
@@ -1147,6 +1269,8 @@ static const PyMethodDef _PyGooCanvas_methods[] = {
       NULL },
     { "request_redraw", (PyCFunction)_wrap_goo_canvas_request_redraw, METH_VARARGS|METH_KEYWORDS,
       NULL },
+    { "request_item_redraw", (PyCFunction)_wrap_goo_canvas_request_item_redraw, METH_VARARGS|METH_KEYWORDS,
+      NULL },
     { "get_default_line_width", (PyCFunction)_wrap_goo_canvas_get_default_line_width, METH_NOARGS,
       NULL },
     { "register_widget_item", (PyCFunction)_wrap_goo_canvas_register_widget_item, METH_VARARGS|METH_KEYWORDS,
@@ -1200,7 +1324,7 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvas_Type = {
     (descrgetfunc)0,    /* tp_descr_get */
     (descrsetfunc)0,    /* tp_descr_set */
     offsetof(PyGObject, inst_dict),                 /* tp_dictoffset */
-    (initproc)_wrap_goo_canvas_new,             /* tp_init */
+    (initproc)0,             /* tp_init */
     (allocfunc)0,           /* tp_alloc */
     (newfunc)0,               /* tp_new */
     (freefunc)0,             /* tp_free */
@@ -1217,7 +1341,7 @@ _wrap_GooCanvas__proxy_do_set_scroll_adjustments(GooCanvas *self, GtkAdjustment*
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -1238,11 +1362,11 @@ _wrap_GooCanvas__proxy_do_set_scroll_adjustments(GooCanvas *self, GtkAdjustment*
         Py_INCREF(Py_None);
         py_vadjustment = Py_None;
     }
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_hadjustment);
     PyTuple_SET_ITEM(py_args, 1, py_vadjustment);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_set_scroll_adjustments");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -1273,8 +1397,8 @@ _wrap_GooCanvas__proxy_do_set_scroll_adjustments(GooCanvas *self, GtkAdjustment*
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -1291,7 +1415,7 @@ _wrap_GooCanvas__proxy_do_create_item(GooCanvas *self, GooCanvasItemModel*model)
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -1306,10 +1430,10 @@ _wrap_GooCanvas__proxy_do_create_item(GooCanvas *self, GooCanvasItemModel*model)
         Py_INCREF(Py_None);
         py_model = Py_None;
     }
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_model);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_create_item");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -1352,14 +1476,14 @@ _wrap_GooCanvas__proxy_do_create_item(GooCanvas *self, GooCanvasItemModel*model)
     }
     retval = (GooCanvasItem*) pygobject_get(py_retval);
     g_object_ref((GObject *) retval);
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -1372,7 +1496,7 @@ _wrap_GooCanvas__proxy_do_item_created(GooCanvas *self, GooCanvasItem*item, GooC
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -1393,11 +1517,11 @@ _wrap_GooCanvas__proxy_do_item_created(GooCanvas *self, GooCanvasItem*item, GooC
         Py_INCREF(Py_None);
         py_model = Py_None;
     }
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_item);
     PyTuple_SET_ITEM(py_args, 1, py_model);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_item_created");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -1428,8 +1552,8 @@ _wrap_GooCanvas__proxy_do_item_created(GooCanvas *self, GooCanvasItem*item, GooC
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -1525,7 +1649,6 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvasItemModelSimple_Type = {
 };
 
 
-
 /* ----------- GooCanvasImageModel ----------- */
 
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasImageModel_Type = {
@@ -1675,7 +1798,7 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvasEllipseModel_Type = {
 
 /* ----------- GooCanvasItemSimple ----------- */
 
-#line 257 "goocanvas.override"
+#line 260 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_simple_get_path_bounds(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -1697,7 +1820,7 @@ _wrap_goo_canvas_item_simple_get_path_bounds(PyGObject *self, PyObject *args, Py
     return py_bounds;
 }
 
-#line 1701 "goocanvas.c"
+#line 1876 "goocanvas.c"
 
 
 static PyObject *
@@ -1709,9 +1832,9 @@ _wrap_goo_canvas_item_simple_user_bounds_to_device(PyGObject *self, PyObject *ar
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!O!:GooCanvasItemSimple.user_bounds_to_device", kwlist, &PycairoContext_Type, &cr, &PyGooCanvasBounds_Type, &py_bounds))
         return NULL;
-    
+
     goo_canvas_item_simple_user_bounds_to_device(GOO_CANVAS_ITEM_SIMPLE(self->obj), cr->ctx, (py_bounds == NULL)? NULL : &((PyGooCanvasBounds *) py_bounds)->bounds);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1725,9 +1848,9 @@ _wrap_goo_canvas_item_simple_user_bounds_to_parent(PyGObject *self, PyObject *ar
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!O!:GooCanvasItemSimple.user_bounds_to_parent", kwlist, &PycairoContext_Type, &cr, &PyGooCanvasBounds_Type, &py_bounds))
         return NULL;
-    
+
     goo_canvas_item_simple_user_bounds_to_parent(GOO_CANVAS_ITEM_SIMPLE(self->obj), cr->ctx, (py_bounds == NULL)? NULL : &((PyGooCanvasBounds *) py_bounds)->bounds);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1746,9 +1869,9 @@ _wrap_goo_canvas_item_simple_check_in_path(PyGObject *self, PyObject *args, PyOb
         return NULL;
     if (pyg_flags_get_value(GOO_TYPE_CANVAS_POINTER_EVENTS, py_pointer_events, (gpointer)&pointer_events))
         return NULL;
-    
+
     ret = goo_canvas_item_simple_check_in_path(GOO_CANVAS_ITEM_SIMPLE(self->obj), x, y, cr->ctx, pointer_events);
-    
+
     return PyBool_FromLong(ret);
 
 }
@@ -1761,9 +1884,9 @@ _wrap_goo_canvas_item_simple_paint_path(PyGObject *self, PyObject *args, PyObjec
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItemSimple.paint_path", kwlist, &PycairoContext_Type, &cr))
         return NULL;
-    
+
     goo_canvas_item_simple_paint_path(GOO_CANVAS_ITEM_SIMPLE(self->obj), cr->ctx);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1776,9 +1899,9 @@ _wrap_goo_canvas_item_simple_changed(PyGObject *self, PyObject *args, PyObject *
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"i:GooCanvasItemSimple.changed", kwlist, &recompute_bounds))
         return NULL;
-    
+
     goo_canvas_item_simple_changed(GOO_CANVAS_ITEM_SIMPLE(self->obj), recompute_bounds);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1786,9 +1909,9 @@ _wrap_goo_canvas_item_simple_changed(PyGObject *self, PyObject *args, PyObject *
 static PyObject *
 _wrap_goo_canvas_item_simple_check_style(PyGObject *self)
 {
-    
+
     goo_canvas_item_simple_check_style(GOO_CANVAS_ITEM_SIMPLE(self->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1798,9 +1921,9 @@ _wrap_goo_canvas_item_simple_get_line_width(PyGObject *self)
 {
     double ret;
 
-    
+
     ret = goo_canvas_item_simple_get_line_width(GOO_CANVAS_ITEM_SIMPLE(self->obj));
-    
+
     return PyFloat_FromDouble(ret);
 }
 
@@ -1812,9 +1935,9 @@ _wrap_goo_canvas_item_simple_set_model(PyGObject *self, PyObject *args, PyObject
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItemSimple.set_model", kwlist, &PyGooCanvasItemModel_Type, &model))
         return NULL;
-    
+
     goo_canvas_item_simple_set_model(GOO_CANVAS_ITEM_SIMPLE(self->obj), GOO_CANVAS_ITEM_MODEL(model->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1944,7 +2067,7 @@ static const PyMethodDef _PyGooCanvasItemSimple_methods[] = {
     { NULL, NULL, 0, NULL }
 };
 
-#line 783 "goocanvas.override"
+#line 786 "goocanvas.override"
 
 static int
 _wrap_goo_canvas_item_simple__set_bounds_x1(PyGObject *self, PyObject *py_value, void *closure)
@@ -1957,7 +2080,7 @@ _wrap_goo_canvas_item_simple__set_bounds_x1(PyGObject *self, PyObject *py_value,
     return 0;
 }
 
-#line 1961 "goocanvas.c"
+#line 2136 "goocanvas.c"
 
 
 static PyObject *
@@ -1969,7 +2092,7 @@ _wrap_goo_canvas_item_simple__get_bounds_x1(PyObject *self, void *closure)
     return PyFloat_FromDouble(ret);
 }
 
-#line 797 "goocanvas.override"
+#line 800 "goocanvas.override"
 
 static int
 _wrap_goo_canvas_item_simple__set_bounds_x2(PyGObject *self, PyObject *py_value, void *closure)
@@ -1982,7 +2105,7 @@ _wrap_goo_canvas_item_simple__set_bounds_x2(PyGObject *self, PyObject *py_value,
     return 0;
 }
 
-#line 1986 "goocanvas.c"
+#line 2161 "goocanvas.c"
 
 
 static PyObject *
@@ -1994,7 +2117,7 @@ _wrap_goo_canvas_item_simple__get_bounds_x2(PyObject *self, void *closure)
     return PyFloat_FromDouble(ret);
 }
 
-#line 811 "goocanvas.override"
+#line 814 "goocanvas.override"
 
 static int
 _wrap_goo_canvas_item_simple__set_bounds_y1(PyGObject *self, PyObject *py_value, void *closure)
@@ -2007,7 +2130,7 @@ _wrap_goo_canvas_item_simple__set_bounds_y1(PyGObject *self, PyObject *py_value,
     return 0;
 }
 
-#line 2011 "goocanvas.c"
+#line 2186 "goocanvas.c"
 
 
 static PyObject *
@@ -2019,7 +2142,7 @@ _wrap_goo_canvas_item_simple__get_bounds_y1(PyObject *self, void *closure)
     return PyFloat_FromDouble(ret);
 }
 
-#line 825 "goocanvas.override"
+#line 828 "goocanvas.override"
 
 static int
 _wrap_goo_canvas_item_simple__set_bounds_y2(PyGObject *self, PyObject *py_value, void *closure)
@@ -2032,7 +2155,7 @@ _wrap_goo_canvas_item_simple__set_bounds_y2(PyGObject *self, PyObject *py_value,
     return 0;
 }
 
-#line 2036 "goocanvas.c"
+#line 2211 "goocanvas.c"
 
 
 static PyObject *
@@ -2044,7 +2167,7 @@ _wrap_goo_canvas_item_simple__get_bounds_y2(PyObject *self, void *closure)
     return PyFloat_FromDouble(ret);
 }
 
-#line 1587 "goocanvas.override"
+#line 1590 "goocanvas.override"
 
 static int
 _wrap_goo_canvas_item_simple__set_bounds(PyGObject *self, PyObject *py_value, void *closure)
@@ -2062,7 +2185,8 @@ _wrap_goo_canvas_item_simple__get_bounds(PyGObject *self, void *closure)
 {
     return pygoo_canvas_bounds_new(&GOO_CANVAS_ITEM_SIMPLE(pygobject_get(self))->bounds);
 }
-#line 2066 "goocanvas.c"
+
+#line 2242 "goocanvas.c"
 
 
 static const PyGetSetDef goo_canvas_item_simple_getsets[] = {
@@ -2128,7 +2252,7 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_create_path(GooCanvasItemSimple *self
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -2137,11 +2261,11 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_create_path(GooCanvasItemSimple *self
         pyg_gil_state_release(__py_state);
         return;
     }
-    py_cr = PycairoContext_FromContext(cairo_reference(cr), NULL, NULL);
-    
+    py_cr = PycairoContext_FromContext(cairo_reference(cr), &PyGdkCairoContext_Type, NULL);
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_cr);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_simple_create_path");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -2172,8 +2296,8 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_create_path(GooCanvasItemSimple *self
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -2189,7 +2313,7 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_update(GooCanvasItemSimple *self, cai
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -2198,11 +2322,11 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_update(GooCanvasItemSimple *self, cai
         pyg_gil_state_release(__py_state);
         return;
     }
-    py_cr = PycairoContext_FromContext(cairo_reference(cr), NULL, NULL);
-    
+    py_cr = PycairoContext_FromContext(cairo_reference(cr), &PyGdkCairoContext_Type, NULL);
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_cr);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_simple_update");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -2233,8 +2357,8 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_update(GooCanvasItemSimple *self, cai
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -2251,7 +2375,7 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_paint(GooCanvasItemSimple *self, cair
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -2260,13 +2384,13 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_paint(GooCanvasItemSimple *self, cair
         pyg_gil_state_release(__py_state);
         return;
     }
-    py_cr = PycairoContext_FromContext(cairo_reference(cr), NULL, NULL);
+    py_cr = PycairoContext_FromContext(cairo_reference(cr), &PyGdkCairoContext_Type, NULL);
     py_bounds = pygoo_canvas_bounds_new(bounds);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_cr);
     PyTuple_SET_ITEM(py_args, 1, py_bounds);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_simple_paint");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -2297,8 +2421,8 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_paint(GooCanvasItemSimple *self, cair
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -2319,7 +2443,7 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_is_item_at(GooCanvasItemSimple *self,
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -2330,16 +2454,16 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_is_item_at(GooCanvasItemSimple *self,
     }
     py_x = PyFloat_FromDouble(x);
     py_y = PyFloat_FromDouble(y);
-    py_cr = PycairoContext_FromContext(cairo_reference(cr), NULL, NULL);
+    py_cr = PycairoContext_FromContext(cairo_reference(cr), &PyGdkCairoContext_Type, NULL);
     py_is_pointer_event = is_pointer_event? Py_True : Py_False;
-    
+
     py_args = PyTuple_New(4);
     PyTuple_SET_ITEM(py_args, 0, py_x);
     PyTuple_SET_ITEM(py_args, 1, py_y);
     PyTuple_SET_ITEM(py_args, 2, py_cr);
     Py_INCREF(py_is_pointer_event);
     PyTuple_SET_ITEM(py_args, 3, py_is_pointer_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_simple_is_item_at");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -2371,15 +2495,15 @@ _wrap_GooCanvasItemSimple__proxy_do_simple_is_item_at(GooCanvasItemSimple *self,
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 
@@ -2482,55 +2606,6 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvasImage_Type = {
 
 
 
-/* ----------- GooCanvasSvg ----------- */
-
-PyTypeObject G_GNUC_INTERNAL PyGooCanvasSvg_Type = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                 /* ob_size */
-    "goocanvas.Svg",                   /* tp_name */
-    sizeof(PyGObject),          /* tp_basicsize */
-    0,                                 /* tp_itemsize */
-    /* methods */
-    (destructor)0,        /* tp_dealloc */
-    (printfunc)0,                      /* tp_print */
-    (getattrfunc)0,       /* tp_getattr */
-    (setattrfunc)0,       /* tp_setattr */
-    (cmpfunc)0,           /* tp_compare */
-    (reprfunc)0,             /* tp_repr */
-    (PyNumberMethods*)0,     /* tp_as_number */
-    (PySequenceMethods*)0, /* tp_as_sequence */
-    (PyMappingMethods*)0,   /* tp_as_mapping */
-    (hashfunc)0,             /* tp_hash */
-    (ternaryfunc)0,          /* tp_call */
-    (reprfunc)0,              /* tp_str */
-    (getattrofunc)0,     /* tp_getattro */
-    (setattrofunc)0,     /* tp_setattro */
-    (PyBufferProcs*)0,  /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,                      /* tp_flags */
-    NULL,                        /* Documentation string */
-    (traverseproc)0,     /* tp_traverse */
-    (inquiry)0,             /* tp_clear */
-    (richcmpfunc)0,   /* tp_richcompare */
-    offsetof(PyGObject, weakreflist),             /* tp_weaklistoffset */
-    (getiterfunc)0,          /* tp_iter */
-    (iternextfunc)0,     /* tp_iternext */
-    (struct PyMethodDef*)NULL, /* tp_methods */
-    (struct PyMemberDef*)0,              /* tp_members */
-    (struct PyGetSetDef*)0,  /* tp_getset */
-    NULL,                              /* tp_base */
-    NULL,                              /* tp_dict */
-    (descrgetfunc)0,    /* tp_descr_get */
-    (descrsetfunc)0,    /* tp_descr_set */
-    offsetof(PyGObject, inst_dict),                 /* tp_dictoffset */
-    (initproc)0,             /* tp_init */
-    (allocfunc)0,           /* tp_alloc */
-    (newfunc)0,               /* tp_new */
-    (freefunc)0,             /* tp_free */
-    (inquiry)0              /* tp_is_gc */
-};
-
-
-
 /* ----------- GooCanvasGroup ----------- */
 
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasGroup_Type = {
@@ -2930,9 +3005,9 @@ _wrap_goo_canvas_style_copy(PyGObject *self)
 {
     GooCanvasStyle *ret;
 
-    
+
     ret = goo_canvas_style_copy(GOO_CANVAS_STYLE(self->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -2942,9 +3017,9 @@ _wrap_goo_canvas_style_get_parent(PyGObject *self)
 {
     GooCanvasStyle *ret;
 
-    
+
     ret = goo_canvas_style_get_parent(GOO_CANVAS_STYLE(self->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -2957,14 +3032,14 @@ _wrap_goo_canvas_style_set_parent(PyGObject *self, PyObject *args, PyObject *kwa
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasStyle.set_parent", kwlist, &PyGooCanvasStyle_Type, &parent))
         return NULL;
-    
+
     goo_canvas_style_set_parent(GOO_CANVAS_STYLE(self->obj), GOO_CANVAS_STYLE(parent->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-#line 716 "goocanvas.override"
+#line 719 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_style_get_property(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -2977,10 +3052,10 @@ _wrap_goo_canvas_style_get_property(PyGObject *self, PyObject *args, PyObject *k
     return _py_canvas_style_get_property(GOO_CANVAS_STYLE(self->obj), name);
 }
 
-#line 2981 "goocanvas.c"
+#line 3157 "goocanvas.c"
 
 
-#line 730 "goocanvas.override"
+#line 733 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_style_set_property(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -2997,7 +3072,7 @@ _wrap_goo_canvas_style_set_property(PyGObject *self, PyObject *args, PyObject *k
     return Py_None;
 }
 
-#line 3001 "goocanvas.c"
+#line 3177 "goocanvas.c"
 
 
 static PyObject *
@@ -3009,9 +3084,9 @@ _wrap_goo_canvas_style_set_stroke_options(PyGObject *self, PyObject *args, PyObj
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasStyle.set_stroke_options", kwlist, &PycairoContext_Type, &cr))
         return NULL;
-    
+
     ret = goo_canvas_style_set_stroke_options(GOO_CANVAS_STYLE(self->obj), cr->ctx);
-    
+
     return PyBool_FromLong(ret);
 
 }
@@ -3025,9 +3100,9 @@ _wrap_goo_canvas_style_set_fill_options(PyGObject *self, PyObject *args, PyObjec
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasStyle.set_fill_options", kwlist, &PycairoContext_Type, &cr))
         return NULL;
-    
+
     ret = goo_canvas_style_set_fill_options(GOO_CANVAS_STYLE(self->obj), cr->ctx);
-    
+
     return PyBool_FromLong(ret);
 
 }
@@ -3050,7 +3125,7 @@ static const PyMethodDef _PyGooCanvasStyle_methods[] = {
     { NULL, NULL, 0, NULL }
 };
 
-#line 748 "goocanvas.override"
+#line 751 "goocanvas.override"
 
 static PyObject *
 goo_canvas_style_subscript(PyGObject *self, PyObject *arg)
@@ -3084,7 +3159,7 @@ static PyMappingMethods _wrap_goo_canvas_style_tp_as_mapping = {
     (objobjargproc) _wrap_goo_canvas_style_ass_subscript, /* objobjargproc mp_ass_subscript; */
 };
 
-#line 3088 "goocanvas.c"
+#line 3264 "goocanvas.c"
 
 
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasStyle_Type = {
@@ -3234,6 +3309,31 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvasTableModel_Type = {
 
 /* ----------- GooCanvasText ----------- */
 
+#line 1610 "goocanvas.override"
+static PyObject *
+_wrap_goo_canvas_text_get_natural_extents(PyGObject *self)
+{
+    PangoRectangle ink_rect, logical_rect;
+
+    goo_canvas_text_get_natural_extents(GOO_CANVAS_TEXT(self->obj), &ink_rect,
+                                        &logical_rect);
+
+    return Py_BuildValue("((iiii)(iiii))",
+			 ink_rect.x, ink_rect.y,
+			 ink_rect.width, ink_rect.height,
+			 logical_rect.x, logical_rect.y,
+			 logical_rect.width, logical_rect.height);
+}
+
+#line 3430 "goocanvas.c"
+
+
+static const PyMethodDef _PyGooCanvasText_methods[] = {
+    { "get_natural_extents", (PyCFunction)_wrap_goo_canvas_text_get_natural_extents, METH_NOARGS,
+      NULL },
+    { NULL, NULL, 0, NULL }
+};
+
 PyTypeObject G_GNUC_INTERNAL PyGooCanvasText_Type = {
     PyObject_HEAD_INIT(NULL)
     0,                                 /* ob_size */
@@ -3264,7 +3364,7 @@ PyTypeObject G_GNUC_INTERNAL PyGooCanvasText_Type = {
     offsetof(PyGObject, weakreflist),             /* tp_weaklistoffset */
     (getiterfunc)0,          /* tp_iter */
     (iternextfunc)0,     /* tp_iternext */
-    (struct PyMethodDef*)NULL, /* tp_methods */
+    (struct PyMethodDef*)_PyGooCanvasText_methods, /* tp_methods */
     (struct PyMemberDef*)0,              /* tp_members */
     (struct PyGetSetDef*)0,  /* tp_getset */
     NULL,                              /* tp_base */
@@ -3386,9 +3486,9 @@ _wrap_goo_canvas_item_get_n_children(PyGObject *self)
 {
     int ret;
 
-    
+
     ret = goo_canvas_item_get_n_children(GOO_CANVAS_ITEM(self->obj));
-    
+
     return PyInt_FromLong(ret);
 }
 
@@ -3401,9 +3501,9 @@ _wrap_goo_canvas_item_get_child(PyGObject *self, PyObject *args, PyObject *kwarg
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"i:GooCanvasItem.get_child", kwlist, &child_num))
         return NULL;
-    
+
     ret = goo_canvas_item_get_child(GOO_CANVAS_ITEM(self->obj), child_num);
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -3417,9 +3517,9 @@ _wrap_goo_canvas_item_find_child(PyGObject *self, PyObject *args, PyObject *kwar
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItem.find_child", kwlist, &PyGooCanvasItem_Type, &child))
         return NULL;
-    
+
     ret = goo_canvas_item_find_child(GOO_CANVAS_ITEM(self->obj), GOO_CANVAS_ITEM(child->obj));
-    
+
     return PyInt_FromLong(ret);
 }
 
@@ -3432,9 +3532,9 @@ _wrap_goo_canvas_item_add_child(PyGObject *self, PyObject *args, PyObject *kwarg
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!|i:GooCanvasItem.add_child", kwlist, &PyGooCanvasItem_Type, &child, &position))
         return NULL;
-    
+
     goo_canvas_item_add_child(GOO_CANVAS_ITEM(self->obj), GOO_CANVAS_ITEM(child->obj), position);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3447,14 +3547,14 @@ _wrap_goo_canvas_item_move_child(PyGObject *self, PyObject *args, PyObject *kwar
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"ii:GooCanvasItem.move_child", kwlist, &old_position, &new_position))
         return NULL;
-    
+
     goo_canvas_item_move_child(GOO_CANVAS_ITEM(self->obj), old_position, new_position);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-#line 483 "goocanvas.override"
+#line 486 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_remove_child(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -3483,10 +3583,129 @@ _wrap_goo_canvas_item_remove_child(PyGObject *self, PyObject *args, PyObject *kw
     Py_INCREF(Py_None);
     return Py_None;
 }
-#line 3487 "goocanvas.c"
+#line 3688 "goocanvas.c"
 
 
-#line 921 "goocanvas.override"
+#line 1711 "goocanvas.override"
+static PyObject *
+_wrap_goo_canvas_item_get_child_property(PyGObject *self,
+                                         PyObject *args,
+                                         PyObject *kwargs)
+{
+    static char    *kwlist[] = { "child", "property", NULL };
+    PyGObject *pychild;
+    gchar *property_name;
+    GooCanvasItem *item, *child;
+    GObjectClass *class;
+    GParamSpec *pspec;
+    GValue value = { 0, } ;
+    PyObject *ret;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O!s:GooCanvasItem.get_child_property",
+                                     kwlist, &PyGooCanvasItem_Type, &pychild,
+                                     &property_name)) {
+        return NULL;
+    }
+
+    item = GOO_CANVAS_ITEM(self->obj);
+    child = GOO_CANVAS_ITEM(pychild->obj);
+
+    if (goo_canvas_item_find_child(item, child) == -1) {
+        PyErr_SetString(PyExc_TypeError,
+                        "first argument must be a child");
+        return NULL;
+    }
+
+    class = G_OBJECT_GET_CLASS(item);
+    pspec = goo_canvas_item_class_find_child_property(class, property_name);
+    if (!pspec) {
+        gchar buf[512];
+        g_snprintf(buf, sizeof(buf),
+                   "item does not support property `%s'",
+                   property_name);
+
+        PyErr_SetString(PyExc_TypeError, buf);
+        return NULL;
+    }
+
+    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+
+    goo_canvas_item_get_child_property(item,
+                                       child,
+                                       property_name,
+                                       &value);
+
+    ret = pyg_value_as_pyobject(&value, TRUE);
+    g_value_unset(&value);
+
+    return ret;
+}
+
+#line 3747 "goocanvas.c"
+
+
+#line 1653 "goocanvas.override"
+static PyObject *
+_wrap_goo_canvas_item_set_child_property(PyGObject *self,
+                                         PyObject *args,
+                                         PyObject *kwargs)
+{
+    static char    *kwlist[] = { "child", "property", "value", NULL };
+    gchar *property_name;
+    PyGObject *pychild;
+    GooCanvasItem *item, *child;
+    PyGObject *pyvalue;
+    GObjectClass *class;
+    GParamSpec *pspec;
+    GValue value = { 0, } ;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O!sO:GooCanvasItem.set_child_property",
+                                     kwlist,
+                                    &PyGooCanvasItem_Type, &pychild,
+                                    &property_name, &pyvalue)) {
+        return NULL;
+    }
+
+    item = GOO_CANVAS_ITEM(self->obj);
+    child = GOO_CANVAS_ITEM(pychild->obj);
+
+    if (goo_canvas_item_find_child(item, child) == -1) {
+        PyErr_SetString(PyExc_TypeError,
+                        "first argument must be a child");
+        return NULL;
+    }
+
+    class = G_OBJECT_GET_CLASS(self->obj);
+    pspec = goo_canvas_item_class_find_child_property(class, property_name);
+    if (!pspec) {
+        gchar buf[512];
+        g_snprintf(buf, sizeof(buf),
+                   "item does not support property `%s'",
+                   property_name);
+        PyErr_SetString(PyExc_TypeError, buf);
+
+        return NULL;
+    }
+
+    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+
+    pyg_value_from_pyobject(&value, (PyObject*)pyvalue);
+
+    goo_canvas_item_set_child_property(item,
+                                       child,
+                                       property_name,
+                                       &value);
+    g_value_unset(&value);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+#line 3807 "goocanvas.c"
+
+
+#line 924 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_get_child_properties(PyGObject *self, PyObject *args)
 {
@@ -3567,10 +3786,10 @@ _wrap_goo_canvas_item_get_child_properties(PyGObject *self, PyObject *args)
     return tuple;
 }
 
-#line 3571 "goocanvas.c"
+#line 3891 "goocanvas.c"
 
 
-#line 839 "goocanvas.override"
+#line 842 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_set_child_properties(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -3651,36 +3870,47 @@ _wrap_goo_canvas_item_set_child_properties(PyGObject *self, PyObject *args, PyOb
     return Py_None;
 }
 
-#line 3655 "goocanvas.c"
+#line 3975 "goocanvas.c"
 
 
+#line 1953 "goocanvas.override"
 static PyObject *
-_wrap_goo_canvas_item_get_transform_for_child(PyGObject *self, PyObject *args, PyObject *kwargs)
+_wrap_goo_canvas_item_get_transform_for_child(PyGObject *self,
+                                              PyObject *args,
+                                              PyObject *kwargs)
 {
-    static char *kwlist[] = { "child", "transform", NULL };
+    static char *kwlist[] = { "child", NULL };
     PyGObject *child;
-    PyObject *py_transform;
     int ret;
-    cairo_matrix_t *transform;
+    cairo_matrix_t *transform = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!O:GooCanvasItem.get_transform_for_child", kwlist, &PyGooCanvasItem_Type, &child, &py_transform))
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O!:GooCanvasItem.get_transform_for_child",
+                                     kwlist, &PyGooCanvasItem_Type, &child))
         return NULL;
-    transform = &((PycairoMatrix*)(py_transform))->matrix;
-    
-    ret = goo_canvas_item_get_transform_for_child(GOO_CANVAS_ITEM(self->obj), GOO_CANVAS_ITEM(child->obj), transform);
-    
-    return PyBool_FromLong(ret);
 
+    ret = goo_canvas_item_get_transform_for_child(GOO_CANVAS_ITEM(self->obj),
+                                                  GOO_CANVAS_ITEM(child->obj),
+                                                  transform);
+
+    if (ret)
+        return PycairoMatrix_FromMatrix(transform);
+    else
+        Py_INCREF(Py_None);
+        return Py_None;
 }
 
+#line 4005 "goocanvas.c"
+
+
 static PyObject *
 _wrap_goo_canvas_item_get_canvas(PyGObject *self)
 {
     GooCanvas *ret;
 
-    
+
     ret = goo_canvas_item_get_canvas(GOO_CANVAS_ITEM(self->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -3693,9 +3923,9 @@ _wrap_goo_canvas_item_set_canvas(PyGObject *self, PyObject *args, PyObject *kwar
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItem.set_canvas", kwlist, &PyGooCanvas_Type, &canvas))
         return NULL;
-    
+
     goo_canvas_item_set_canvas(GOO_CANVAS_ITEM(self->obj), GOO_CANVAS(canvas->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3705,9 +3935,9 @@ _wrap_goo_canvas_item_get_parent(PyGObject *self)
 {
     GooCanvasItem *ret;
 
-    
+
     ret = goo_canvas_item_get_parent(GOO_CANVAS_ITEM(self->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -3720,9 +3950,9 @@ _wrap_goo_canvas_item_set_parent(PyGObject *self, PyObject *args, PyObject *kwar
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItem.set_parent", kwlist, &PyGooCanvasItem_Type, &parent))
         return NULL;
-    
+
     goo_canvas_item_set_parent(GOO_CANVAS_ITEM(self->obj), GOO_CANVAS_ITEM(parent->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3730,9 +3960,9 @@ _wrap_goo_canvas_item_set_parent(PyGObject *self, PyObject *args, PyObject *kwar
 static PyObject *
 _wrap_goo_canvas_item_remove(PyGObject *self)
 {
-    
+
     goo_canvas_item_remove(GOO_CANVAS_ITEM(self->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3742,9 +3972,9 @@ _wrap_goo_canvas_item_is_container(PyGObject *self)
 {
     int ret;
 
-    
+
     ret = goo_canvas_item_is_container(GOO_CANVAS_ITEM(self->obj));
-    
+
     return PyBool_FromLong(ret);
 
 }
@@ -3764,9 +3994,9 @@ _wrap_goo_canvas_item_raise(PyGObject *self, PyObject *args, PyObject *kwargs)
         PyErr_SetString(PyExc_TypeError, "above should be a GooCanvasItem or None");
         return NULL;
     }
-    
+
     goo_canvas_item_raise(GOO_CANVAS_ITEM(self->obj), (GooCanvasItem *) above);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3786,14 +4016,14 @@ _wrap_goo_canvas_item_lower(PyGObject *self, PyObject *args, PyObject *kwargs)
         PyErr_SetString(PyExc_TypeError, "below should be a GooCanvasItem or None");
         return NULL;
     }
-    
+
     goo_canvas_item_lower(GOO_CANVAS_ITEM(self->obj), (GooCanvasItem *) below);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-#line 1546 "goocanvas.override"
+#line 1549 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_get_transform(PyGObject *self)
 {
@@ -3812,26 +4042,51 @@ _wrap_goo_canvas_item_get_transform(PyGObject *self)
     return matrix;
 }
 
-#line 3816 "goocanvas.c"
+#line 4147 "goocanvas.c"
 
 
+#line 1981 "goocanvas.override"
 static PyObject *
-_wrap_goo_canvas_item_set_transform(PyGObject *self, PyObject *args, PyObject *kwargs)
+_wrap_goo_canvas_item_set_transform(PyGObject *self,
+                                    PyObject *args,
+                                    PyObject *kwargs)
 {
     static char *kwlist[] = { "matrix", NULL };
     PyObject *py_matrix;
-    cairo_matrix_t *matrix;
+    cairo_matrix_t *matrix = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O:GooCanvasItem.set_transform", kwlist, &py_matrix))
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O:GooCanvasItem.set_transform",
+                                     kwlist, &py_matrix))
         return NULL;
-    matrix = &((PycairoMatrix*)(py_matrix))->matrix;
-    
+
+    if (py_matrix && (py_matrix != Py_None))
+        matrix = &((PycairoMatrix*)(py_matrix))->matrix;
+
     goo_canvas_item_set_transform(GOO_CANVAS_ITEM(self->obj), matrix);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
+#line 4174 "goocanvas.c"
+
+
+#line 1627 "goocanvas.override"
+static PyObject *
+_wrap_goo_canvas_item_get_simple_transform(PyGObject *self)
+{
+    gdouble x, y, scale, rotation;
+
+    goo_canvas_item_get_simple_transform(GOO_CANVAS_ITEM(self->obj), &x, &y,
+                                         &scale, &rotation);
+
+    return Py_BuildValue("dddd", x, y, scale, rotation);
+}
+
+#line 4189 "goocanvas.c"
+
+
 static PyObject *
 _wrap_goo_canvas_item_set_simple_transform(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -3840,9 +4095,9 @@ _wrap_goo_canvas_item_set_simple_transform(PyGObject *self, PyObject *args, PyOb
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"dddd:GooCanvasItem.set_simple_transform", kwlist, &x, &y, &scale, &rotation))
         return NULL;
-    
+
     goo_canvas_item_set_simple_transform(GOO_CANVAS_ITEM(self->obj), x, y, scale, rotation);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3855,9 +4110,9 @@ _wrap_goo_canvas_item_translate(PyGObject *self, PyObject *args, PyObject *kwarg
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"dd:GooCanvasItem.translate", kwlist, &tx, &ty))
         return NULL;
-    
+
     goo_canvas_item_translate(GOO_CANVAS_ITEM(self->obj), tx, ty);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3870,9 +4125,9 @@ _wrap_goo_canvas_item_scale(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"dd:GooCanvasItem.scale", kwlist, &sx, &sy))
         return NULL;
-    
+
     goo_canvas_item_scale(GOO_CANVAS_ITEM(self->obj), sx, sy);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3885,9 +4140,9 @@ _wrap_goo_canvas_item_rotate(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"ddd:GooCanvasItem.rotate", kwlist, &degrees, &cx, &cy))
         return NULL;
-    
+
     goo_canvas_item_rotate(GOO_CANVAS_ITEM(self->obj), degrees, cx, cy);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3900,9 +4155,9 @@ _wrap_goo_canvas_item_skew_x(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"ddd:GooCanvasItem.skew_x", kwlist, &degrees, &cx, &cy))
         return NULL;
-    
+
     goo_canvas_item_skew_x(GOO_CANVAS_ITEM(self->obj), degrees, cx, cy);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3915,9 +4170,9 @@ _wrap_goo_canvas_item_skew_y(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"ddd:GooCanvasItem.skew_y", kwlist, &degrees, &cx, &cy))
         return NULL;
-    
+
     goo_canvas_item_skew_y(GOO_CANVAS_ITEM(self->obj), degrees, cx, cy);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3927,9 +4182,9 @@ _wrap_goo_canvas_item_get_style(PyGObject *self)
 {
     GooCanvasStyle *ret;
 
-    
+
     ret = goo_canvas_item_get_style(GOO_CANVAS_ITEM(self->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -3942,9 +4197,9 @@ _wrap_goo_canvas_item_set_style(PyGObject *self, PyObject *args, PyObject *kwarg
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItem.set_style", kwlist, &PyGooCanvasStyle_Type, &style))
         return NULL;
-    
+
     goo_canvas_item_set_style(GOO_CANVAS_ITEM(self->obj), GOO_CANVAS_STYLE(style->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3962,9 +4217,9 @@ _wrap_goo_canvas_item_animate(PyGObject *self, PyObject *args, PyObject *kwargs)
         return NULL;
     if (pyg_enum_get_value(GOO_TYPE_CANVAS_ANIMATE_TYPE, py_type, (gpointer)&type))
         return NULL;
-    
+
     goo_canvas_item_animate(GOO_CANVAS_ITEM(self->obj), x, y, scale, degrees, absolute, duration, step_time, type);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3972,14 +4227,14 @@ _wrap_goo_canvas_item_animate(PyGObject *self, PyObject *args, PyObject *kwargs)
 static PyObject *
 _wrap_goo_canvas_item_stop_animation(PyGObject *self)
 {
-    
+
     goo_canvas_item_stop_animation(GOO_CANVAS_ITEM(self->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-#line 525 "goocanvas.override"
+#line 528 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_get_bounds(PyGObject *self)
 {
@@ -3993,10 +4248,10 @@ _wrap_goo_canvas_item_get_bounds(PyGObject *self)
     return py_bounds;
 }
 
-#line 3997 "goocanvas.c"
+#line 4353 "goocanvas.c"
 
 
-#line 1508 "goocanvas.override"
+#line 1511 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_get_items_at(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -4033,7 +4288,7 @@ _wrap_goo_canvas_item_get_items_at(PyGObject *self, PyObject *args, PyObject *kw
     return ret;
 }
 
-#line 4037 "goocanvas.c"
+#line 4393 "goocanvas.c"
 
 
 static PyObject *
@@ -4041,9 +4296,9 @@ _wrap_goo_canvas_item_is_visible(PyGObject *self)
 {
     int ret;
 
-    
+
     ret = goo_canvas_item_is_visible(GOO_CANVAS_ITEM(self->obj));
-    
+
     return PyBool_FromLong(ret);
 
 }
@@ -4053,9 +4308,9 @@ _wrap_goo_canvas_item_get_model(PyGObject *self)
 {
     GooCanvasItemModel *ret;
 
-    
+
     ret = goo_canvas_item_get_model(GOO_CANVAS_ITEM(self->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -4068,9 +4323,9 @@ _wrap_goo_canvas_item_set_model(PyGObject *self, PyObject *args, PyObject *kwarg
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItem.set_model", kwlist, &PyGooCanvasItemModel_Type, &model))
         return NULL;
-    
+
     goo_canvas_item_set_model(GOO_CANVAS_ITEM(self->obj), GOO_CANVAS_ITEM_MODEL(model->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -4078,9 +4333,9 @@ _wrap_goo_canvas_item_set_model(PyGObject *self, PyObject *args, PyObject *kwarg
 static PyObject *
 _wrap_goo_canvas_item_request_update(PyGObject *self)
 {
-    
+
     goo_canvas_item_request_update(GOO_CANVAS_ITEM(self->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -4088,30 +4343,36 @@ _wrap_goo_canvas_item_request_update(PyGObject *self)
 static PyObject *
 _wrap_goo_canvas_item_ensure_updated(PyGObject *self)
 {
-    
+
     goo_canvas_item_ensure_updated(GOO_CANVAS_ITEM(self->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
+#line 1932 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_update(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
-    static char *kwlist[] = { "entire_tree", "cr", "bounds", NULL };
-    int entire_tree;
-    PyObject *py_bounds;
-    PycairoContext *cr;
+    static char *kwlist[] = { "entire_tree", "cr", NULL };
+    int             entire_tree;
+    PycairoContext  *cr;
+    GooCanvasBounds bounds;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"iO!O!:GooCanvasItem.update", kwlist, &entire_tree, &PycairoContext_Type, &cr, &PyGooCanvasBounds_Type, &py_bounds))
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"iO!:GooCanvasItem.update",
+                                     kwlist, &entire_tree,
+                                     &PycairoContext_Type, &cr))
         return NULL;
-    
-    goo_canvas_item_update(GOO_CANVAS_ITEM(self->obj), entire_tree, cr->ctx, (py_bounds == NULL)? NULL : &((PyGooCanvasBounds *) py_bounds)->bounds);
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    goo_canvas_item_update(GOO_CANVAS_ITEM(self->obj), entire_tree,
+                           cr->ctx, &bounds);
+
+    return pygoo_canvas_bounds_new(&bounds);
 }
 
+#line 4475 "goocanvas.c"
+
+
 static PyObject *
 _wrap_goo_canvas_item_paint(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -4122,35 +4383,43 @@ _wrap_goo_canvas_item_paint(PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!|Od:GooCanvasItem.paint", kwlist, &PycairoContext_Type, &cr, &py_bounds, &scale))
         return NULL;
-    if (!(py_bounds == NULL || py_bounds == Py_None || 
+    if (!(py_bounds == NULL || py_bounds == Py_None ||
         PyObject_IsInstance(py_bounds, (PyObject *) &PyGooCanvasBounds_Type))) {
         PyErr_SetString(PyExc_TypeError, "parameter bounds must be goocanvas.Bounds or None");
         return NULL;
     }
-    
+
     goo_canvas_item_paint(GOO_CANVAS_ITEM(self->obj), cr->ctx, (py_bounds == NULL || py_bounds == Py_None)? NULL : &((PyGooCanvasBounds *) py_bounds)->bounds, scale);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
+#line 1909 "goocanvas.override"
 static PyObject *
-_wrap_goo_canvas_item_get_requested_area(PyGObject *self, PyObject *args, PyObject *kwargs)
+_wrap_goo_canvas_item_get_requested_area(PyGObject *self,
+                                         PyObject *args,
+                                         PyObject *kwargs)
 {
-    static char *kwlist[] = { "cr", "requested_area", NULL };
-    PyObject *py_requested_area;
-    int ret;
-    PycairoContext *cr;
+    static char     *kwlist[] = { "cr", NULL };
+    int             ret;
+    GooCanvasBounds bounds;
+    PycairoContext  *cr;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!O!:GooCanvasItem.get_requested_area", kwlist, &PycairoContext_Type, &cr, &PyGooCanvasBounds_Type, &py_requested_area))
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O!:GooCanvasItem.get_requested_area",
+                                     kwlist, &PycairoContext_Type, &cr))
         return NULL;
-    
-    ret = goo_canvas_item_get_requested_area(GOO_CANVAS_ITEM(self->obj), cr->ctx, (py_requested_area == NULL)? NULL : &((PyGooCanvasBounds *) py_requested_area)->bounds);
-    
-    return PyBool_FromLong(ret);
 
+    ret = goo_canvas_item_get_requested_area(GOO_CANVAS_ITEM(self->obj),
+                                             cr->ctx, &bounds);
+
+    return pygoo_canvas_bounds_new(&bounds);
 }
 
+#line 4522 "goocanvas.c"
+
+
 static PyObject *
 _wrap_goo_canvas_item_get_requested_height(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -4160,9 +4429,9 @@ _wrap_goo_canvas_item_get_requested_height(PyGObject *self, PyObject *args, PyOb
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!d:GooCanvasItem.get_requested_height", kwlist, &PycairoContext_Type, &cr, &width))
         return NULL;
-    
+
     ret = goo_canvas_item_get_requested_height(GOO_CANVAS_ITEM(self->obj), cr->ctx, width);
-    
+
     return PyFloat_FromDouble(ret);
 }
 
@@ -4176,14 +4445,14 @@ _wrap_goo_canvas_item_allocate_area(PyGObject *self, PyObject *args, PyObject *k
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!O!O!dd:GooCanvasItem.allocate_area", kwlist, &PycairoContext_Type, &cr, &PyGooCanvasBounds_Type, &py_requested_area, &PyGooCanvasBounds_Type, &py_allocated_area, &x_offset, &y_offset))
         return NULL;
-    
+
     goo_canvas_item_allocate_area(GOO_CANVAS_ITEM(self->obj), cr->ctx, (py_requested_area == NULL)? NULL : &((PyGooCanvasBounds *) py_requested_area)->bounds, (py_allocated_area == NULL)? NULL : &((PyGooCanvasBounds *) py_allocated_area)->bounds, x_offset, y_offset);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-#line 1208 "goocanvas.override"
+#line 1211 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_find_child_property (PyObject *cls,
                                            PyObject *args,
@@ -4223,10 +4492,10 @@ _wrap_goo_canvas_item_find_child_property (PyObject *cls,
     return pyg_param_spec_new(pspec);
 }
 
-#line 4227 "goocanvas.c"
+#line 4597 "goocanvas.c"
 
 
-#line 1291 "goocanvas.override"
+#line 1294 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_list_child_properties (PyObject *cls,
                                              PyObject *args,
@@ -4267,10 +4536,10 @@ _wrap_goo_canvas_item_list_child_properties (PyObject *cls,
     return list;
 }
 
-#line 4271 "goocanvas.c"
+#line 4641 "goocanvas.c"
 
 
-#line 1385 "goocanvas.override"
+#line 1388 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_install_child_property (PyObject *cls,
                                               PyObject *args,
@@ -4321,7 +4590,7 @@ _wrap_goo_canvas_item_install_child_property (PyObject *cls,
     return Py_None;
 }
 
-#line 4325 "goocanvas.c"
+#line 4695 "goocanvas.c"
 
 
 static PyObject *
@@ -5142,6 +5411,10 @@ static const PyMethodDef _PyGooCanvasItem_methods[] = {
       NULL },
     { "remove_child", (PyCFunction)_wrap_goo_canvas_item_remove_child, METH_VARARGS|METH_KEYWORDS,
       NULL },
+    { "get_child_property", (PyCFunction)_wrap_goo_canvas_item_get_child_property, METH_VARARGS,
+      NULL },
+    { "set_child_property", (PyCFunction)_wrap_goo_canvas_item_set_child_property, METH_VARARGS|METH_KEYWORDS,
+      NULL },
     { "get_child_properties", (PyCFunction)_wrap_goo_canvas_item_get_child_properties, METH_VARARGS,
       NULL },
     { "set_child_properties", (PyCFunction)_wrap_goo_canvas_item_set_child_properties, METH_VARARGS|METH_KEYWORDS,
@@ -5168,6 +5441,8 @@ static const PyMethodDef _PyGooCanvasItem_methods[] = {
       NULL },
     { "set_transform", (PyCFunction)_wrap_goo_canvas_item_set_transform, METH_VARARGS|METH_KEYWORDS,
       NULL },
+    { "get_simple_transform", (PyCFunction)_wrap_goo_canvas_item_get_simple_transform, METH_NOARGS,
+      NULL },
     { "set_simple_transform", (PyCFunction)_wrap_goo_canvas_item_set_simple_transform, METH_VARARGS|METH_KEYWORDS,
       NULL },
     { "translate", (PyCFunction)_wrap_goo_canvas_item_translate, METH_VARARGS|METH_KEYWORDS,
@@ -5342,7 +5617,7 @@ _wrap_GooCanvasItem__proxy_do_get_canvas(GooCanvasItem *self)
     GooCanvas* retval;
     PyObject *py_retval;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -5351,8 +5626,8 @@ _wrap_GooCanvasItem__proxy_do_get_canvas(GooCanvasItem *self)
         pyg_gil_state_release(__py_state);
         return NULL;
     }
-    
-    
+
+
     py_method = PyObject_GetAttrString(py_self, "do_get_canvas");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -5391,13 +5666,13 @@ _wrap_GooCanvasItem__proxy_do_get_canvas(GooCanvasItem *self)
     }
     retval = (GooCanvas*) pygobject_get(py_retval);
     g_object_ref((GObject *) retval);
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -5409,7 +5684,7 @@ _wrap_GooCanvasItem__proxy_do_set_canvas(GooCanvasItem *self, GooCanvas*canvas)
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -5424,10 +5699,10 @@ _wrap_GooCanvasItem__proxy_do_set_canvas(GooCanvasItem *self, GooCanvas*canvas)
         Py_INCREF(Py_None);
         py_canvas = Py_None;
     }
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_canvas);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_set_canvas");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -5458,8 +5733,8 @@ _wrap_GooCanvasItem__proxy_do_set_canvas(GooCanvasItem *self, GooCanvas*canvas)
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -5474,7 +5749,7 @@ _wrap_GooCanvasItem__proxy_do_get_n_children(GooCanvasItem *self)
     gint retval;
     PyObject *py_retval;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -5483,8 +5758,8 @@ _wrap_GooCanvasItem__proxy_do_get_n_children(GooCanvasItem *self)
         pyg_gil_state_release(__py_state);
         return -G_MAXINT;
     }
-    
-    
+
+
     py_method = PyObject_GetAttrString(py_self, "do_get_n_children");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -5513,13 +5788,13 @@ _wrap_GooCanvasItem__proxy_do_get_n_children(GooCanvasItem *self)
         pyg_gil_state_release(__py_state);
         return -G_MAXINT;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static GooCanvasItem*
@@ -5532,7 +5807,7 @@ _wrap_GooCanvasItem__proxy_do_get_child(GooCanvasItem *self, gint child_num)
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -5542,10 +5817,10 @@ _wrap_GooCanvasItem__proxy_do_get_child(GooCanvasItem *self, gint child_num)
         return NULL;
     }
     py_child_num = PyInt_FromLong(child_num);
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_child_num);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_get_child");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -5588,14 +5863,14 @@ _wrap_GooCanvasItem__proxy_do_get_child(GooCanvasItem *self, gint child_num)
     }
     retval = (GooCanvasItem*) pygobject_get(py_retval);
     g_object_ref((GObject *) retval);
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -5605,7 +5880,7 @@ _wrap_GooCanvasItem__proxy_do_request_update(GooCanvasItem *self)
     PyObject *py_self;
     PyObject *py_retval;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -5614,8 +5889,8 @@ _wrap_GooCanvasItem__proxy_do_request_update(GooCanvasItem *self)
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     py_method = PyObject_GetAttrString(py_self, "do_request_update");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -5643,8 +5918,8 @@ _wrap_GooCanvasItem__proxy_do_request_update(GooCanvasItem *self)
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_self);
@@ -5660,7 +5935,7 @@ _wrap_GooCanvasItem__proxy_do_add_child(GooCanvasItem *self, GooCanvasItem*child
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -5676,11 +5951,11 @@ _wrap_GooCanvasItem__proxy_do_add_child(GooCanvasItem *self, GooCanvasItem*child
         py_child = Py_None;
     }
     py_position = PyInt_FromLong(position);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_child);
     PyTuple_SET_ITEM(py_args, 1, py_position);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_add_child");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -5711,8 +5986,8 @@ _wrap_GooCanvasItem__proxy_do_add_child(GooCanvasItem *self, GooCanvasItem*child
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -5729,7 +6004,7 @@ _wrap_GooCanvasItem__proxy_do_move_child(GooCanvasItem *self, gint old_position,
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -5740,11 +6015,11 @@ _wrap_GooCanvasItem__proxy_do_move_child(GooCanvasItem *self, gint old_position,
     }
     py_old_position = PyInt_FromLong(old_position);
     py_new_position = PyInt_FromLong(new_position);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_old_position);
     PyTuple_SET_ITEM(py_args, 1, py_new_position);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_move_child");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -5775,8 +6050,8 @@ _wrap_GooCanvasItem__proxy_do_move_child(GooCanvasItem *self, gint old_position,
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -5792,7 +6067,7 @@ _wrap_GooCanvasItem__proxy_do_remove_child(GooCanvasItem *self, gint child_num)
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -5802,10 +6077,10 @@ _wrap_GooCanvasItem__proxy_do_remove_child(GooCanvasItem *self, gint child_num)
         return;
     }
     py_child_num = PyInt_FromLong(child_num);
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_child_num);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_remove_child");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -5836,8 +6111,8 @@ _wrap_GooCanvasItem__proxy_do_remove_child(GooCanvasItem *self, gint child_num)
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -5852,7 +6127,7 @@ _wrap_GooCanvasItem__proxy_do_get_parent(GooCanvasItem *self)
     GooCanvasItem* retval;
     PyObject *py_retval;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -5861,8 +6136,8 @@ _wrap_GooCanvasItem__proxy_do_get_parent(GooCanvasItem *self)
         pyg_gil_state_release(__py_state);
         return NULL;
     }
-    
-    
+
+
     py_method = PyObject_GetAttrString(py_self, "do_get_parent");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -5901,13 +6176,13 @@ _wrap_GooCanvasItem__proxy_do_get_parent(GooCanvasItem *self)
     }
     retval = (GooCanvasItem*) pygobject_get(py_retval);
     g_object_ref((GObject *) retval);
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -5919,7 +6194,7 @@ _wrap_GooCanvasItem__proxy_do_set_parent(GooCanvasItem *self, GooCanvasItem*pare
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -5934,10 +6209,10 @@ _wrap_GooCanvasItem__proxy_do_set_parent(GooCanvasItem *self, GooCanvasItem*pare
         Py_INCREF(Py_None);
         py_parent = Py_None;
     }
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_parent);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_set_parent");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -5968,15 +6243,15 @@ _wrap_GooCanvasItem__proxy_do_set_parent(GooCanvasItem *self, GooCanvasItem*pare
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
 }
-#line 606 "goocanvas.override"
+#line 609 "goocanvas.override"
 static void
 _wrap_GooCanvasItem__proxy_do_get_bounds(GooCanvasItem *self, GooCanvasBounds *bounds)
 {
@@ -6002,10 +6277,10 @@ _wrap_GooCanvasItem__proxy_do_get_bounds(GooCanvasItem *self, GooCanvasBounds *b
     Py_XDECREF(py_bounds);
     pyg_gil_state_release(__py_state);
 }
-#line 6006 "goocanvas.c"
+#line 6382 "goocanvas.c"
 
 
-#line 633 "goocanvas.override"
+#line 636 "goocanvas.override"
 static void
 _wrap_GooCanvasItem__proxy_do_update(GooCanvasItem *self, gboolean entire_tree,
                                      cairo_t *cr, GooCanvasBounds *bounds)
@@ -6025,7 +6300,7 @@ _wrap_GooCanvasItem__proxy_do_update(GooCanvasItem *self, gboolean entire_tree,
 
     py_bounds = PyObject_CallMethod(py_self, "do_update", "iN",
                                     entire_tree,
-                                    PycairoContext_FromContext(cairo_reference(cr), NULL, NULL));
+                                    PycairoContext_FromContext(cairo_reference(cr), &PyGdkCairoContext_Type, NULL));
     if (py_bounds)
         *bounds = ((PyGooCanvasBounds *) py_bounds)->bounds;
     else
@@ -6035,7 +6310,7 @@ _wrap_GooCanvasItem__proxy_do_update(GooCanvasItem *self, gboolean entire_tree,
     pyg_gil_state_release(__py_state);
 }
 
-#line 6039 "goocanvas.c"
+#line 6415 "goocanvas.c"
 
 
 static void
@@ -6049,7 +6324,7 @@ _wrap_GooCanvasItem__proxy_do_paint(GooCanvasItem *self, cairo_t*cr, const GooCa
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6058,15 +6333,15 @@ _wrap_GooCanvasItem__proxy_do_paint(GooCanvasItem *self, cairo_t*cr, const GooCa
         pyg_gil_state_release(__py_state);
         return;
     }
-    py_cr = PycairoContext_FromContext(cairo_reference(cr), NULL, NULL);
+    py_cr = PycairoContext_FromContext(cairo_reference(cr), &PyGdkCairoContext_Type, NULL);
     py_bounds = pygoo_canvas_bounds_new(bounds);
     py_scale = PyFloat_FromDouble(scale);
-    
+
     py_args = PyTuple_New(3);
     PyTuple_SET_ITEM(py_args, 0, py_cr);
     PyTuple_SET_ITEM(py_args, 1, py_bounds);
     PyTuple_SET_ITEM(py_args, 2, py_scale);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_paint");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6097,8 +6372,8 @@ _wrap_GooCanvasItem__proxy_do_paint(GooCanvasItem *self, cairo_t*cr, const GooCa
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -6117,7 +6392,7 @@ _wrap_GooCanvasItem__proxy_do_get_requested_area(GooCanvasItem *self, cairo_t*cr
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6126,13 +6401,13 @@ _wrap_GooCanvasItem__proxy_do_get_requested_area(GooCanvasItem *self, cairo_t*cr
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    py_cr = PycairoContext_FromContext(cairo_reference(cr), NULL, NULL);
+    py_cr = PycairoContext_FromContext(cairo_reference(cr), &PyGdkCairoContext_Type, NULL);
     py_requested_area = pygoo_canvas_bounds_new(requested_area);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_cr);
     PyTuple_SET_ITEM(py_args, 1, py_requested_area);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_get_requested_area");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6164,15 +6439,15 @@ _wrap_GooCanvasItem__proxy_do_get_requested_area(GooCanvasItem *self, cairo_t*cr
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -6188,7 +6463,7 @@ _wrap_GooCanvasItem__proxy_do_allocate_area(GooCanvasItem *self, cairo_t*cr, con
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6197,19 +6472,19 @@ _wrap_GooCanvasItem__proxy_do_allocate_area(GooCanvasItem *self, cairo_t*cr, con
         pyg_gil_state_release(__py_state);
         return;
     }
-    py_cr = PycairoContext_FromContext(cairo_reference(cr), NULL, NULL);
+    py_cr = PycairoContext_FromContext(cairo_reference(cr), &PyGdkCairoContext_Type, NULL);
     py_requested_area = pygoo_canvas_bounds_new(requested_area);
     py_allocated_area = pygoo_canvas_bounds_new(allocated_area);
     py_x_offset = PyFloat_FromDouble(x_offset);
     py_y_offset = PyFloat_FromDouble(y_offset);
-    
+
     py_args = PyTuple_New(5);
     PyTuple_SET_ITEM(py_args, 0, py_cr);
     PyTuple_SET_ITEM(py_args, 1, py_requested_area);
     PyTuple_SET_ITEM(py_args, 2, py_allocated_area);
     PyTuple_SET_ITEM(py_args, 3, py_x_offset);
     PyTuple_SET_ITEM(py_args, 4, py_y_offset);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_allocate_area");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6240,8 +6515,8 @@ _wrap_GooCanvasItem__proxy_do_allocate_area(GooCanvasItem *self, cairo_t*cr, con
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -6256,7 +6531,7 @@ _wrap_GooCanvasItem__proxy_do_get_style(GooCanvasItem *self)
     GooCanvasStyle* retval;
     PyObject *py_retval;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6265,8 +6540,8 @@ _wrap_GooCanvasItem__proxy_do_get_style(GooCanvasItem *self)
         pyg_gil_state_release(__py_state);
         return NULL;
     }
-    
-    
+
+
     py_method = PyObject_GetAttrString(py_self, "do_get_style");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6305,13 +6580,13 @@ _wrap_GooCanvasItem__proxy_do_get_style(GooCanvasItem *self)
     }
     retval = (GooCanvasStyle*) pygobject_get(py_retval);
     g_object_ref((GObject *) retval);
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -6323,7 +6598,7 @@ _wrap_GooCanvasItem__proxy_do_set_style(GooCanvasItem *self, GooCanvasStyle*styl
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6338,10 +6613,10 @@ _wrap_GooCanvasItem__proxy_do_set_style(GooCanvasItem *self, GooCanvasStyle*styl
         Py_INCREF(Py_None);
         py_style = Py_None;
     }
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_style);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_set_style");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6372,8 +6647,8 @@ _wrap_GooCanvasItem__proxy_do_set_style(GooCanvasItem *self, GooCanvasStyle*styl
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -6389,7 +6664,7 @@ _wrap_GooCanvasItem__proxy_do_is_visible(GooCanvasItem *self)
     PyObject *py_main_retval;
     PyObject *py_retval;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6398,8 +6673,8 @@ _wrap_GooCanvasItem__proxy_do_is_visible(GooCanvasItem *self)
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
-    
+
+
     py_method = PyObject_GetAttrString(py_self, "do_is_visible");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6428,14 +6703,14 @@ _wrap_GooCanvasItem__proxy_do_is_visible(GooCanvasItem *self)
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static gdouble
@@ -6449,7 +6724,7 @@ _wrap_GooCanvasItem__proxy_do_get_requested_height(GooCanvasItem *self, cairo_t*
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6458,13 +6733,13 @@ _wrap_GooCanvasItem__proxy_do_get_requested_height(GooCanvasItem *self, cairo_t*
         pyg_gil_state_release(__py_state);
         return -G_MAXFLOAT;
     }
-    py_cr = PycairoContext_FromContext(cairo_reference(cr), NULL, NULL);
+    py_cr = PycairoContext_FromContext(cairo_reference(cr), &PyGdkCairoContext_Type, NULL);
     py_width = PyFloat_FromDouble(width);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_cr);
     PyTuple_SET_ITEM(py_args, 1, py_width);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_get_requested_height");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6496,14 +6771,14 @@ _wrap_GooCanvasItem__proxy_do_get_requested_height(GooCanvasItem *self, cairo_t*
         pyg_gil_state_release(__py_state);
         return -G_MAXFLOAT;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static GooCanvasItemModel*
@@ -6514,7 +6789,7 @@ _wrap_GooCanvasItem__proxy_do_get_model(GooCanvasItem *self)
     GooCanvasItemModel* retval;
     PyObject *py_retval;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6523,8 +6798,8 @@ _wrap_GooCanvasItem__proxy_do_get_model(GooCanvasItem *self)
         pyg_gil_state_release(__py_state);
         return NULL;
     }
-    
-    
+
+
     py_method = PyObject_GetAttrString(py_self, "do_get_model");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6563,13 +6838,13 @@ _wrap_GooCanvasItem__proxy_do_get_model(GooCanvasItem *self)
     }
     retval = (GooCanvasItemModel*) pygobject_get(py_retval);
     g_object_ref((GObject *) retval);
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -6581,7 +6856,7 @@ _wrap_GooCanvasItem__proxy_do_set_model(GooCanvasItem *self, GooCanvasItemModel*
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6596,10 +6871,10 @@ _wrap_GooCanvasItem__proxy_do_set_model(GooCanvasItem *self, GooCanvasItemModel*
         Py_INCREF(Py_None);
         py_model = Py_None;
     }
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_model);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_set_model");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6630,8 +6905,8 @@ _wrap_GooCanvasItem__proxy_do_set_model(GooCanvasItem *self, GooCanvasItemModel*
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -6650,7 +6925,7 @@ _wrap_GooCanvasItem__proxy_do_enter_notify_event(GooCanvasItem *self, GooCanvasI
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6666,11 +6941,11 @@ _wrap_GooCanvasItem__proxy_do_enter_notify_event(GooCanvasItem *self, GooCanvasI
         py_target = Py_None;
     }
     py_event = pyg_boxed_new(GDK_TYPE_EVENT, event, FALSE, FALSE);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_target);
     PyTuple_SET_ITEM(py_args, 1, py_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_enter_notify_event");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6702,15 +6977,15 @@ _wrap_GooCanvasItem__proxy_do_enter_notify_event(GooCanvasItem *self, GooCanvasI
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static gboolean
@@ -6725,7 +7000,7 @@ _wrap_GooCanvasItem__proxy_do_leave_notify_event(GooCanvasItem *self, GooCanvasI
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6741,11 +7016,11 @@ _wrap_GooCanvasItem__proxy_do_leave_notify_event(GooCanvasItem *self, GooCanvasI
         py_target = Py_None;
     }
     py_event = pyg_boxed_new(GDK_TYPE_EVENT, event, FALSE, FALSE);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_target);
     PyTuple_SET_ITEM(py_args, 1, py_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_leave_notify_event");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6777,15 +7052,15 @@ _wrap_GooCanvasItem__proxy_do_leave_notify_event(GooCanvasItem *self, GooCanvasI
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static gboolean
@@ -6800,7 +7075,7 @@ _wrap_GooCanvasItem__proxy_do_motion_notify_event(GooCanvasItem *self, GooCanvas
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6816,11 +7091,11 @@ _wrap_GooCanvasItem__proxy_do_motion_notify_event(GooCanvasItem *self, GooCanvas
         py_target = Py_None;
     }
     py_event = pyg_boxed_new(GDK_TYPE_EVENT, event, FALSE, FALSE);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_target);
     PyTuple_SET_ITEM(py_args, 1, py_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_motion_notify_event");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6852,15 +7127,15 @@ _wrap_GooCanvasItem__proxy_do_motion_notify_event(GooCanvasItem *self, GooCanvas
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static gboolean
@@ -6875,7 +7150,7 @@ _wrap_GooCanvasItem__proxy_do_button_press_event(GooCanvasItem *self, GooCanvasI
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6891,11 +7166,11 @@ _wrap_GooCanvasItem__proxy_do_button_press_event(GooCanvasItem *self, GooCanvasI
         py_target = Py_None;
     }
     py_event = pyg_boxed_new(GDK_TYPE_EVENT, event, FALSE, FALSE);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_target);
     PyTuple_SET_ITEM(py_args, 1, py_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_button_press_event");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -6927,15 +7202,15 @@ _wrap_GooCanvasItem__proxy_do_button_press_event(GooCanvasItem *self, GooCanvasI
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static gboolean
@@ -6950,7 +7225,7 @@ _wrap_GooCanvasItem__proxy_do_button_release_event(GooCanvasItem *self, GooCanva
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -6966,11 +7241,11 @@ _wrap_GooCanvasItem__proxy_do_button_release_event(GooCanvasItem *self, GooCanva
         py_target = Py_None;
     }
     py_event = pyg_boxed_new(GDK_TYPE_EVENT, event, FALSE, FALSE);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_target);
     PyTuple_SET_ITEM(py_args, 1, py_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_button_release_event");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -7002,15 +7277,15 @@ _wrap_GooCanvasItem__proxy_do_button_release_event(GooCanvasItem *self, GooCanva
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static gboolean
@@ -7025,7 +7300,7 @@ _wrap_GooCanvasItem__proxy_do_focus_in_event(GooCanvasItem *self, GooCanvasItem*
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -7041,11 +7316,11 @@ _wrap_GooCanvasItem__proxy_do_focus_in_event(GooCanvasItem *self, GooCanvasItem*
         py_target = Py_None;
     }
     py_event = pyg_boxed_new(GDK_TYPE_EVENT, event, FALSE, FALSE);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_target);
     PyTuple_SET_ITEM(py_args, 1, py_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_focus_in_event");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -7077,15 +7352,15 @@ _wrap_GooCanvasItem__proxy_do_focus_in_event(GooCanvasItem *self, GooCanvasItem*
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static gboolean
@@ -7100,7 +7375,7 @@ _wrap_GooCanvasItem__proxy_do_focus_out_event(GooCanvasItem *self, GooCanvasItem
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -7116,11 +7391,11 @@ _wrap_GooCanvasItem__proxy_do_focus_out_event(GooCanvasItem *self, GooCanvasItem
         py_target = Py_None;
     }
     py_event = pyg_boxed_new(GDK_TYPE_EVENT, event, FALSE, FALSE);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_target);
     PyTuple_SET_ITEM(py_args, 1, py_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_focus_out_event");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -7152,15 +7427,15 @@ _wrap_GooCanvasItem__proxy_do_focus_out_event(GooCanvasItem *self, GooCanvasItem
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static gboolean
@@ -7175,7 +7450,7 @@ _wrap_GooCanvasItem__proxy_do_key_press_event(GooCanvasItem *self, GooCanvasItem
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -7191,11 +7466,11 @@ _wrap_GooCanvasItem__proxy_do_key_press_event(GooCanvasItem *self, GooCanvasItem
         py_target = Py_None;
     }
     py_event = pyg_boxed_new(GDK_TYPE_EVENT, event, FALSE, FALSE);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_target);
     PyTuple_SET_ITEM(py_args, 1, py_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_key_press_event");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -7227,15 +7502,15 @@ _wrap_GooCanvasItem__proxy_do_key_press_event(GooCanvasItem *self, GooCanvasItem
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static gboolean
@@ -7250,7 +7525,7 @@ _wrap_GooCanvasItem__proxy_do_key_release_event(GooCanvasItem *self, GooCanvasIt
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -7266,11 +7541,11 @@ _wrap_GooCanvasItem__proxy_do_key_release_event(GooCanvasItem *self, GooCanvasIt
         py_target = Py_None;
     }
     py_event = pyg_boxed_new(GDK_TYPE_EVENT, event, FALSE, FALSE);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_target);
     PyTuple_SET_ITEM(py_args, 1, py_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_key_release_event");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -7302,15 +7577,15 @@ _wrap_GooCanvasItem__proxy_do_key_release_event(GooCanvasItem *self, GooCanvasIt
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static gboolean
@@ -7325,7 +7600,7 @@ _wrap_GooCanvasItem__proxy_do_grab_broken_event(GooCanvasItem *self, GooCanvasIt
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -7341,11 +7616,11 @@ _wrap_GooCanvasItem__proxy_do_grab_broken_event(GooCanvasItem *self, GooCanvasIt
         py_target = Py_None;
     }
     py_event = pyg_boxed_new(GDK_TYPE_EVENT, event, FALSE, FALSE);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_target);
     PyTuple_SET_ITEM(py_args, 1, py_event);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_grab_broken_event");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -7377,15 +7652,15 @@ _wrap_GooCanvasItem__proxy_do_grab_broken_event(GooCanvasItem *self, GooCanvasIt
         pyg_gil_state_release(__py_state);
         return FALSE;
     }
-    
+
     retval = PyObject_IsTrue(py_main_retval)? TRUE : FALSE;
-    
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 
@@ -7722,9 +7997,9 @@ _wrap_goo_canvas_item_model_get_n_children(PyGObject *self)
 {
     int ret;
 
-    
+
     ret = goo_canvas_item_model_get_n_children(GOO_CANVAS_ITEM_MODEL(self->obj));
-    
+
     return PyInt_FromLong(ret);
 }
 
@@ -7737,9 +8012,9 @@ _wrap_goo_canvas_item_model_get_child(PyGObject *self, PyObject *args, PyObject
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"i:GooCanvasItemModel.get_child", kwlist, &child_num))
         return NULL;
-    
+
     ret = goo_canvas_item_model_get_child(GOO_CANVAS_ITEM_MODEL(self->obj), child_num);
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -7753,9 +8028,9 @@ _wrap_goo_canvas_item_model_add_child(PyGObject *self, PyObject *args, PyObject
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!i:GooCanvasItemModel.add_child", kwlist, &PyGooCanvasItemModel_Type, &child, &position))
         return NULL;
-    
+
     goo_canvas_item_model_add_child(GOO_CANVAS_ITEM_MODEL(self->obj), GOO_CANVAS_ITEM_MODEL(child->obj), position);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -7768,9 +8043,9 @@ _wrap_goo_canvas_item_model_move_child(PyGObject *self, PyObject *args, PyObject
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"ii:GooCanvasItemModel.move_child", kwlist, &old_position, &new_position))
         return NULL;
-    
+
     goo_canvas_item_model_move_child(GOO_CANVAS_ITEM_MODEL(self->obj), old_position, new_position);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -7783,9 +8058,9 @@ _wrap_goo_canvas_item_model_remove_child(PyGObject *self, PyObject *args, PyObje
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"i:GooCanvasItemModel.remove_child", kwlist, &child_num))
         return NULL;
-    
+
     goo_canvas_item_model_remove_child(GOO_CANVAS_ITEM_MODEL(self->obj), child_num);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -7799,13 +8074,132 @@ _wrap_goo_canvas_item_model_find_child(PyGObject *self, PyObject *args, PyObject
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItemModel.find_child", kwlist, &PyGooCanvasItemModel_Type, &child))
         return NULL;
-    
+
     ret = goo_canvas_item_model_find_child(GOO_CANVAS_ITEM_MODEL(self->obj), GOO_CANVAS_ITEM_MODEL(child->obj));
-    
+
     return PyInt_FromLong(ret);
 }
 
-#line 1084 "goocanvas.override"
+#line 1826 "goocanvas.override"
+static PyObject *
+_wrap_goo_canvas_item_model_get_child_property(PyGObject *self,
+                                         PyObject *args,
+                                         PyObject *kwargs)
+{
+    static char    *kwlist[] = { "child", "property", NULL };
+    PyGObject *pychild;
+    gchar *property_name;
+    GooCanvasItemModel *item, *child;
+    GObjectClass *class;
+    GParamSpec *pspec;
+    GValue value = { 0, } ;
+    PyObject *ret;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                "O!s:GooCanvasItemModel.get_child_property",
+                                kwlist, &PyGooCanvasItemModel_Type, &pychild,
+                                &property_name)) {
+        return NULL;
+    }
+
+    item = GOO_CANVAS_ITEM_MODEL(self->obj);
+    child = GOO_CANVAS_ITEM_MODEL(pychild->obj);
+
+    if (goo_canvas_item_model_find_child(item, child) == -1) {
+        PyErr_SetString(PyExc_TypeError,
+                        "first argument must be a child");
+        return NULL;
+    }
+
+    class = G_OBJECT_GET_CLASS(item);
+    pspec = goo_canvas_item_model_class_find_child_property(class, property_name);
+    if (!pspec) {
+        gchar buf[512];
+        g_snprintf(buf, sizeof(buf),
+                   "item model does not support property `%s'",
+                   property_name);
+
+        PyErr_SetString(PyExc_TypeError, buf);
+        return NULL;
+    }
+
+    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+
+    goo_canvas_item_model_get_child_property(item,
+                                             child,
+                                             property_name,
+                                             &value);
+
+    ret = pyg_value_as_pyobject(&value, TRUE);
+    g_value_unset(&value);
+
+    return ret;
+}
+
+#line 8241 "goocanvas.c"
+
+
+#line 1768 "goocanvas.override"
+static PyObject *
+_wrap_goo_canvas_item_model_set_child_property(PyGObject *self,
+                                         PyObject *args,
+                                         PyObject *kwargs)
+{
+    static char    *kwlist[] = { "child", "property", "value", NULL };
+    gchar *property_name;
+    PyGObject *pychild;
+    GooCanvasItemModel *item, *child;
+    PyGObject *pyvalue;
+    GObjectClass *class;
+    GParamSpec *pspec;
+    GValue value = { 0, } ;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                "O!sO:GooCanvasItemModel.set_child_property",
+                                kwlist,
+                                &PyGooCanvasItemModel_Type, &pychild,
+                                &property_name, &pyvalue)) {
+        return NULL;
+    }
+
+    item = GOO_CANVAS_ITEM_MODEL(self->obj);
+    child = GOO_CANVAS_ITEM_MODEL(pychild->obj);
+
+    if (goo_canvas_item_model_find_child(item, child) == -1) {
+        PyErr_SetString(PyExc_TypeError,
+                        "first argument must be a child");
+        return NULL;
+    }
+
+    class = G_OBJECT_GET_CLASS(self->obj);
+    pspec = goo_canvas_item_model_class_find_child_property(class, property_name);
+    if (!pspec) {
+        gchar buf[512];
+        g_snprintf(buf, sizeof(buf),
+                   "item model does not support property `%s'",
+                   property_name);
+        PyErr_SetString(PyExc_TypeError, buf);
+
+        return NULL;
+    }
+
+    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+
+    pyg_value_from_pyobject(&value, (PyObject*)pyvalue);
+
+    goo_canvas_item_model_set_child_property(item,
+                                             child,
+                                             property_name,
+                                             &value);
+    g_value_unset(&value);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+#line 8301 "goocanvas.c"
+
+
+#line 1087 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_model_get_child_properties(PyGObject *self, PyObject *args)
 {
@@ -7887,10 +8281,10 @@ _wrap_goo_canvas_item_model_get_child_properties(PyGObject *self, PyObject *args
     return tuple;
 }
 
-#line 7891 "goocanvas.c"
+#line 8386 "goocanvas.c"
 
 
-#line 1003 "goocanvas.override"
+#line 1006 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_model_set_child_properties(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -7970,7 +8364,7 @@ _wrap_goo_canvas_item_model_set_child_properties(PyGObject *self, PyObject *args
     return Py_None;
 }
 
-#line 7974 "goocanvas.c"
+#line 8469 "goocanvas.c"
 
 
 static PyObject *
@@ -7978,9 +8372,9 @@ _wrap_goo_canvas_item_model_get_parent(PyGObject *self)
 {
     GooCanvasItemModel *ret;
 
-    
+
     ret = goo_canvas_item_model_get_parent(GOO_CANVAS_ITEM_MODEL(self->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -7993,9 +8387,9 @@ _wrap_goo_canvas_item_model_set_parent(PyGObject *self, PyObject *args, PyObject
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItemModel.set_parent", kwlist, &PyGooCanvasItemModel_Type, &parent))
         return NULL;
-    
+
     goo_canvas_item_model_set_parent(GOO_CANVAS_ITEM_MODEL(self->obj), GOO_CANVAS_ITEM_MODEL(parent->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8003,9 +8397,9 @@ _wrap_goo_canvas_item_model_set_parent(PyGObject *self, PyObject *args, PyObject
 static PyObject *
 _wrap_goo_canvas_item_model_remove(PyGObject *self)
 {
-    
+
     goo_canvas_item_model_remove(GOO_CANVAS_ITEM_MODEL(self->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8015,9 +8409,9 @@ _wrap_goo_canvas_item_model_is_container(PyGObject *self)
 {
     int ret;
 
-    
+
     ret = goo_canvas_item_model_is_container(GOO_CANVAS_ITEM_MODEL(self->obj));
-    
+
     return PyBool_FromLong(ret);
 
 }
@@ -8030,9 +8424,9 @@ _wrap_goo_canvas_item_model_raise(PyGObject *self, PyObject *args, PyObject *kwa
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItemModel.raise", kwlist, &PyGooCanvasItemModel_Type, &above))
         return NULL;
-    
+
     goo_canvas_item_model_raise(GOO_CANVAS_ITEM_MODEL(self->obj), GOO_CANVAS_ITEM_MODEL(above->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8045,14 +8439,14 @@ _wrap_goo_canvas_item_model_lower(PyGObject *self, PyObject *args, PyObject *kwa
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItemModel.lower", kwlist, &PyGooCanvasItemModel_Type, &below))
         return NULL;
-    
+
     goo_canvas_item_model_lower(GOO_CANVAS_ITEM_MODEL(self->obj), GOO_CANVAS_ITEM_MODEL(below->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-#line 1566 "goocanvas.override"
+#line 1569 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_model_get_transform(PyGObject *self)
 {
@@ -8072,26 +8466,52 @@ _wrap_goo_canvas_item_model_get_transform(PyGObject *self)
     return matrix;
 }
 
-#line 8076 "goocanvas.c"
+#line 8571 "goocanvas.c"
 
 
+#line 2006 "goocanvas.override"
 static PyObject *
-_wrap_goo_canvas_item_model_set_transform(PyGObject *self, PyObject *args, PyObject *kwargs)
+_wrap_goo_canvas_item_model_set_transform(PyGObject *self,
+                                          PyObject *args,
+                                          PyObject *kwargs)
 {
     static char *kwlist[] = { "matrix", NULL };
     PyObject *py_matrix;
-    cairo_matrix_t *matrix;
+    cairo_matrix_t *matrix = NULL;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O:GooCanvasItemModel.set_transform", kwlist, &py_matrix))
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O:GooCanvasItemModel.set_transform",
+                                     kwlist, &py_matrix))
         return NULL;
-    matrix = &((PycairoMatrix*)(py_matrix))->matrix;
-    
-    goo_canvas_item_model_set_transform(GOO_CANVAS_ITEM_MODEL(self->obj), matrix);
-    
+
+    if (py_matrix && (py_matrix != Py_None))
+        matrix = &((PycairoMatrix*)(py_matrix))->matrix;
+
+    goo_canvas_item_model_set_transform(GOO_CANVAS_ITEM_MODEL(self->obj),
+                                        matrix);
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
+#line 8599 "goocanvas.c"
+
+
+#line 1640 "goocanvas.override"
+static PyObject *
+_wrap_goo_canvas_item_model_get_simple_transform(PyGObject *self)
+{
+    gdouble x, y, scale, rotation;
+
+    goo_canvas_item_model_get_simple_transform(GOO_CANVAS_ITEM_MODEL(self->obj),
+                                               &x, &y, &scale, &rotation);
+
+    return Py_BuildValue("dddd", x, y, scale, rotation);
+}
+
+#line 8614 "goocanvas.c"
+
+
 static PyObject *
 _wrap_goo_canvas_item_model_set_simple_transform(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -8100,9 +8520,9 @@ _wrap_goo_canvas_item_model_set_simple_transform(PyGObject *self, PyObject *args
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"dddd:GooCanvasItemModel.set_simple_transform", kwlist, &x, &y, &scale, &rotation))
         return NULL;
-    
+
     goo_canvas_item_model_set_simple_transform(GOO_CANVAS_ITEM_MODEL(self->obj), x, y, scale, rotation);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8115,9 +8535,9 @@ _wrap_goo_canvas_item_model_translate(PyGObject *self, PyObject *args, PyObject
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"dd:GooCanvasItemModel.translate", kwlist, &tx, &ty))
         return NULL;
-    
+
     goo_canvas_item_model_translate(GOO_CANVAS_ITEM_MODEL(self->obj), tx, ty);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8130,9 +8550,9 @@ _wrap_goo_canvas_item_model_scale(PyGObject *self, PyObject *args, PyObject *kwa
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"dd:GooCanvasItemModel.scale", kwlist, &sx, &sy))
         return NULL;
-    
+
     goo_canvas_item_model_scale(GOO_CANVAS_ITEM_MODEL(self->obj), sx, sy);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8145,9 +8565,9 @@ _wrap_goo_canvas_item_model_rotate(PyGObject *self, PyObject *args, PyObject *kw
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"ddd:GooCanvasItemModel.rotate", kwlist, &degrees, &cx, &cy))
         return NULL;
-    
+
     goo_canvas_item_model_rotate(GOO_CANVAS_ITEM_MODEL(self->obj), degrees, cx, cy);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8160,9 +8580,9 @@ _wrap_goo_canvas_item_model_skew_x(PyGObject *self, PyObject *args, PyObject *kw
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"ddd:GooCanvasItemModel.skew_x", kwlist, &degrees, &cx, &cy))
         return NULL;
-    
+
     goo_canvas_item_model_skew_x(GOO_CANVAS_ITEM_MODEL(self->obj), degrees, cx, cy);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8175,9 +8595,9 @@ _wrap_goo_canvas_item_model_skew_y(PyGObject *self, PyObject *args, PyObject *kw
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"ddd:GooCanvasItemModel.skew_y", kwlist, &degrees, &cx, &cy))
         return NULL;
-    
+
     goo_canvas_item_model_skew_y(GOO_CANVAS_ITEM_MODEL(self->obj), degrees, cx, cy);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8187,9 +8607,9 @@ _wrap_goo_canvas_item_model_get_style(PyGObject *self)
 {
     GooCanvasStyle *ret;
 
-    
+
     ret = goo_canvas_item_model_get_style(GOO_CANVAS_ITEM_MODEL(self->obj));
-    
+
     /* pygobject_new handles NULL checking */
     return pygobject_new((GObject *)ret);
 }
@@ -8202,9 +8622,9 @@ _wrap_goo_canvas_item_model_set_style(PyGObject *self, PyObject *args, PyObject
 
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:GooCanvasItemModel.set_style", kwlist, &PyGooCanvasStyle_Type, &style))
         return NULL;
-    
+
     goo_canvas_item_model_set_style(GOO_CANVAS_ITEM_MODEL(self->obj), GOO_CANVAS_STYLE(style->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8222,9 +8642,9 @@ _wrap_goo_canvas_item_model_animate(PyGObject *self, PyObject *args, PyObject *k
         return NULL;
     if (pyg_enum_get_value(GOO_TYPE_CANVAS_ANIMATE_TYPE, py_type, (gpointer)&type))
         return NULL;
-    
+
     goo_canvas_item_model_animate(GOO_CANVAS_ITEM_MODEL(self->obj), x, y, scale, degrees, absolute, duration, step_time, type);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -8232,14 +8652,14 @@ _wrap_goo_canvas_item_model_animate(PyGObject *self, PyObject *args, PyObject *k
 static PyObject *
 _wrap_goo_canvas_item_model_stop_animation(PyGObject *self)
 {
-    
+
     goo_canvas_item_model_stop_animation(GOO_CANVAS_ITEM_MODEL(self->obj));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-#line 1208 "goocanvas.override"
+#line 1211 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_model_find_child_property (PyObject *cls,
                                                  PyObject *args,
@@ -8279,10 +8699,10 @@ _wrap_goo_canvas_item_model_find_child_property (PyObject *cls,
     return pyg_param_spec_new(pspec);
 }
 
-#line 8283 "goocanvas.c"
+#line 8804 "goocanvas.c"
 
 
-#line 1291 "goocanvas.override"
+#line 1294 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_model_list_child_properties (PyObject *cls,
                                                    PyObject *args,
@@ -8323,10 +8743,10 @@ _wrap_goo_canvas_item_model_list_child_properties (PyObject *cls,
     return list;
 }
 
-#line 8327 "goocanvas.c"
+#line 8848 "goocanvas.c"
 
 
-#line 1385 "goocanvas.override"
+#line 1388 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_item_model_install_child_property (PyObject *cls,
                                                     PyObject *args,
@@ -8377,7 +8797,7 @@ _wrap_goo_canvas_item_model_install_child_property (PyObject *cls,
     return Py_None;
 }
 
-#line 8381 "goocanvas.c"
+#line 8902 "goocanvas.c"
 
 
 static PyObject *
@@ -8732,6 +9152,10 @@ static const PyMethodDef _PyGooCanvasItemModel_methods[] = {
       NULL },
     { "find_child", (PyCFunction)_wrap_goo_canvas_item_model_find_child, METH_VARARGS|METH_KEYWORDS,
       NULL },
+    { "get_child_property", (PyCFunction)_wrap_goo_canvas_item_model_get_child_property, METH_VARARGS,
+      NULL },
+    { "set_child_property", (PyCFunction)_wrap_goo_canvas_item_model_set_child_property, METH_VARARGS|METH_KEYWORDS,
+      NULL },
     { "get_child_properties", (PyCFunction)_wrap_goo_canvas_item_model_get_child_properties, METH_VARARGS,
       NULL },
     { "set_child_properties", (PyCFunction)_wrap_goo_canvas_item_model_set_child_properties, METH_VARARGS|METH_KEYWORDS,
@@ -8752,6 +9176,8 @@ static const PyMethodDef _PyGooCanvasItemModel_methods[] = {
       NULL },
     { "set_transform", (PyCFunction)_wrap_goo_canvas_item_model_set_transform, METH_VARARGS|METH_KEYWORDS,
       NULL },
+    { "get_simple_transform", (PyCFunction)_wrap_goo_canvas_item_model_get_simple_transform, METH_NOARGS,
+      NULL },
     { "set_simple_transform", (PyCFunction)_wrap_goo_canvas_item_model_set_simple_transform, METH_VARARGS|METH_KEYWORDS,
       NULL },
     { "translate", (PyCFunction)_wrap_goo_canvas_item_model_translate, METH_VARARGS|METH_KEYWORDS,
@@ -8866,7 +9292,7 @@ _wrap_GooCanvasItemModel__proxy_do_get_n_children(GooCanvasItemModel *self)
     gint retval;
     PyObject *py_retval;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -8875,8 +9301,8 @@ _wrap_GooCanvasItemModel__proxy_do_get_n_children(GooCanvasItemModel *self)
         pyg_gil_state_release(__py_state);
         return -G_MAXINT;
     }
-    
-    
+
+
     py_method = PyObject_GetAttrString(py_self, "do_get_n_children");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -8905,13 +9331,13 @@ _wrap_GooCanvasItemModel__proxy_do_get_n_children(GooCanvasItemModel *self)
         pyg_gil_state_release(__py_state);
         return -G_MAXINT;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static GooCanvasItemModel*
@@ -8924,7 +9350,7 @@ _wrap_GooCanvasItemModel__proxy_do_get_child(GooCanvasItemModel *self, gint chil
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -8934,10 +9360,10 @@ _wrap_GooCanvasItemModel__proxy_do_get_child(GooCanvasItemModel *self, gint chil
         return NULL;
     }
     py_child_num = PyInt_FromLong(child_num);
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_child_num);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_get_child");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -8980,14 +9406,14 @@ _wrap_GooCanvasItemModel__proxy_do_get_child(GooCanvasItemModel *self, gint chil
     }
     retval = (GooCanvasItemModel*) pygobject_get(py_retval);
     g_object_ref((GObject *) retval);
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -9000,7 +9426,7 @@ _wrap_GooCanvasItemModel__proxy_do_add_child(GooCanvasItemModel *self, GooCanvas
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9016,11 +9442,11 @@ _wrap_GooCanvasItemModel__proxy_do_add_child(GooCanvasItemModel *self, GooCanvas
         py_child = Py_None;
     }
     py_position = PyInt_FromLong(position);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_child);
     PyTuple_SET_ITEM(py_args, 1, py_position);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_add_child");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9051,8 +9477,8 @@ _wrap_GooCanvasItemModel__proxy_do_add_child(GooCanvasItemModel *self, GooCanvas
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -9069,7 +9495,7 @@ _wrap_GooCanvasItemModel__proxy_do_move_child(GooCanvasItemModel *self, gint old
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9080,11 +9506,11 @@ _wrap_GooCanvasItemModel__proxy_do_move_child(GooCanvasItemModel *self, gint old
     }
     py_old_position = PyInt_FromLong(old_position);
     py_new_position = PyInt_FromLong(new_position);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_old_position);
     PyTuple_SET_ITEM(py_args, 1, py_new_position);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_move_child");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9115,8 +9541,8 @@ _wrap_GooCanvasItemModel__proxy_do_move_child(GooCanvasItemModel *self, gint old
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -9132,7 +9558,7 @@ _wrap_GooCanvasItemModel__proxy_do_remove_child(GooCanvasItemModel *self, gint c
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9142,10 +9568,10 @@ _wrap_GooCanvasItemModel__proxy_do_remove_child(GooCanvasItemModel *self, gint c
         return;
     }
     py_child_num = PyInt_FromLong(child_num);
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_child_num);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_remove_child");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9176,8 +9602,8 @@ _wrap_GooCanvasItemModel__proxy_do_remove_child(GooCanvasItemModel *self, gint c
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -9192,7 +9618,7 @@ _wrap_GooCanvasItemModel__proxy_do_get_parent(GooCanvasItemModel *self)
     GooCanvasItemModel* retval;
     PyObject *py_retval;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9201,8 +9627,8 @@ _wrap_GooCanvasItemModel__proxy_do_get_parent(GooCanvasItemModel *self)
         pyg_gil_state_release(__py_state);
         return NULL;
     }
-    
-    
+
+
     py_method = PyObject_GetAttrString(py_self, "do_get_parent");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9241,13 +9667,13 @@ _wrap_GooCanvasItemModel__proxy_do_get_parent(GooCanvasItemModel *self)
     }
     retval = (GooCanvasItemModel*) pygobject_get(py_retval);
     g_object_ref((GObject *) retval);
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -9259,7 +9685,7 @@ _wrap_GooCanvasItemModel__proxy_do_set_parent(GooCanvasItemModel *self, GooCanva
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9274,10 +9700,10 @@ _wrap_GooCanvasItemModel__proxy_do_set_parent(GooCanvasItemModel *self, GooCanva
         Py_INCREF(Py_None);
         py_parent = Py_None;
     }
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_parent);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_set_parent");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9308,8 +9734,8 @@ _wrap_GooCanvasItemModel__proxy_do_set_parent(GooCanvasItemModel *self, GooCanva
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -9324,7 +9750,7 @@ _wrap_GooCanvasItemModel__proxy_do_get_style(GooCanvasItemModel *self)
     GooCanvasStyle* retval;
     PyObject *py_retval;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9333,8 +9759,8 @@ _wrap_GooCanvasItemModel__proxy_do_get_style(GooCanvasItemModel *self)
         pyg_gil_state_release(__py_state);
         return NULL;
     }
-    
-    
+
+
     py_method = PyObject_GetAttrString(py_self, "do_get_style");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9373,13 +9799,13 @@ _wrap_GooCanvasItemModel__proxy_do_get_style(GooCanvasItemModel *self)
     }
     retval = (GooCanvasStyle*) pygobject_get(py_retval);
     g_object_ref((GObject *) retval);
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -9391,7 +9817,7 @@ _wrap_GooCanvasItemModel__proxy_do_set_style(GooCanvasItemModel *self, GooCanvas
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9406,10 +9832,10 @@ _wrap_GooCanvasItemModel__proxy_do_set_style(GooCanvasItemModel *self, GooCanvas
         Py_INCREF(Py_None);
         py_style = Py_None;
     }
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_style);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_set_style");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9440,8 +9866,8 @@ _wrap_GooCanvasItemModel__proxy_do_set_style(GooCanvasItemModel *self, GooCanvas
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -9458,7 +9884,7 @@ _wrap_GooCanvasItemModel__proxy_do_create_item(GooCanvasItemModel *self, GooCanv
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9473,10 +9899,10 @@ _wrap_GooCanvasItemModel__proxy_do_create_item(GooCanvasItemModel *self, GooCanv
         Py_INCREF(Py_None);
         py_canvas = Py_None;
     }
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_canvas);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_create_item");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9519,14 +9945,14 @@ _wrap_GooCanvasItemModel__proxy_do_create_item(GooCanvasItemModel *self, GooCanv
     }
     retval = (GooCanvasItem*) pygobject_get(py_retval);
     g_object_ref((GObject *) retval);
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_self);
     pyg_gil_state_release(__py_state);
-    
+
     return retval;
 }
 static void
@@ -9538,7 +9964,7 @@ _wrap_GooCanvasItemModel__proxy_do_child_added(GooCanvasItemModel *self, gint ch
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9548,10 +9974,10 @@ _wrap_GooCanvasItemModel__proxy_do_child_added(GooCanvasItemModel *self, gint ch
         return;
     }
     py_child_num = PyInt_FromLong(child_num);
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_child_num);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_child_added");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9582,8 +10008,8 @@ _wrap_GooCanvasItemModel__proxy_do_child_added(GooCanvasItemModel *self, gint ch
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -9600,7 +10026,7 @@ _wrap_GooCanvasItemModel__proxy_do_child_moved(GooCanvasItemModel *self, gint ol
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9611,11 +10037,11 @@ _wrap_GooCanvasItemModel__proxy_do_child_moved(GooCanvasItemModel *self, gint ol
     }
     py_old_child_num = PyInt_FromLong(old_child_num);
     py_new_child_num = PyInt_FromLong(new_child_num);
-    
+
     py_args = PyTuple_New(2);
     PyTuple_SET_ITEM(py_args, 0, py_old_child_num);
     PyTuple_SET_ITEM(py_args, 1, py_new_child_num);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_child_moved");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9646,8 +10072,8 @@ _wrap_GooCanvasItemModel__proxy_do_child_moved(GooCanvasItemModel *self, gint ol
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -9663,7 +10089,7 @@ _wrap_GooCanvasItemModel__proxy_do_child_removed(GooCanvasItemModel *self, gint
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9673,10 +10099,10 @@ _wrap_GooCanvasItemModel__proxy_do_child_removed(GooCanvasItemModel *self, gint
         return;
     }
     py_child_num = PyInt_FromLong(child_num);
-    
+
     py_args = PyTuple_New(1);
     PyTuple_SET_ITEM(py_args, 0, py_child_num);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_child_removed");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9707,8 +10133,8 @@ _wrap_GooCanvasItemModel__proxy_do_child_removed(GooCanvasItemModel *self, gint
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -9724,7 +10150,7 @@ _wrap_GooCanvasItemModel__proxy_do_changed(GooCanvasItemModel *self, gboolean re
     PyObject *py_retval;
     PyObject *py_args;
     PyObject *py_method;
-    
+
     __py_state = pyg_gil_state_ensure();
     py_self = pygobject_new((GObject *) self);
     if (!py_self) {
@@ -9734,11 +10160,11 @@ _wrap_GooCanvasItemModel__proxy_do_changed(GooCanvasItemModel *self, gboolean re
         return;
     }
     py_recompute_bounds = recompute_bounds? Py_True : Py_False;
-    
+
     py_args = PyTuple_New(1);
     Py_INCREF(py_recompute_bounds);
     PyTuple_SET_ITEM(py_args, 0, py_recompute_bounds);
-    
+
     py_method = PyObject_GetAttrString(py_self, "do_changed");
     if (!py_method) {
         if (PyErr_Occurred())
@@ -9769,8 +10195,8 @@ _wrap_GooCanvasItemModel__proxy_do_changed(GooCanvasItemModel *self, gboolean re
         pyg_gil_state_release(__py_state);
         return;
     }
-    
-    
+
+
     Py_XDECREF(py_retval);
     Py_DECREF(py_method);
     Py_DECREF(py_args);
@@ -9936,7 +10362,7 @@ static const GInterfaceInfo __GooCanvasItemModel__iinfo = {
 
 /* ----------- functions ----------- */
 
-#line 308 "goocanvas.override"
+#line 311 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_polyline_new_line(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -10003,10 +10429,10 @@ _wrap_goo_canvas_polyline_new_line(PyGObject *self, PyObject *args, PyObject *kw
 
     return pygobject_new((GObject *)ret);
 }
-#line 10007 "goocanvas.c"
+#line 10534 "goocanvas.c"
 
 
-#line 376 "goocanvas.override"
+#line 379 "goocanvas.override"
 static PyObject *
 _wrap_goo_canvas_polyline_model_new_line(PyGObject *self, PyObject *args, PyObject *kwargs)
 {
@@ -10074,7 +10500,7 @@ _wrap_goo_canvas_polyline_model_new_line(PyGObject *self, PyObject *args, PyObje
     return pygobject_new((GObject *)ret);
 }
 
-#line 10078 "goocanvas.c"
+#line 10605 "goocanvas.c"
 
 
 static PyObject *
@@ -10087,9 +10513,9 @@ _wrap_goo_cairo_matrix_copy(PyObject *self, PyObject *args, PyObject *kwargs)
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O:goo_cairo_matrix_copy", kwlist, &py_matrix))
         return NULL;
     matrix = &((PycairoMatrix*)(py_matrix))->matrix;
-    
+
     ret = goo_cairo_matrix_copy(matrix);
-    
+
     if (ret)
         return PycairoMatrix_FromMatrix(ret);
     else {
@@ -10108,9 +10534,9 @@ _wrap_goo_cairo_matrix_free(PyObject *self, PyObject *args, PyObject *kwargs)
     if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O:goo_cairo_matrix_free", kwlist, &py_matrix))
         return NULL;
     matrix = &((PycairoMatrix*)(py_matrix))->matrix;
-    
+
     goo_cairo_matrix_free(matrix);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -10190,6 +10616,18 @@ pygoocanvas_register_classes(PyObject *d)
             "could not import gtk");
         return ;
     }
+    if ((module = PyImport_ImportModule("gtk.gdk")) != NULL) {
+        _PyGdkCairoContext_Type = (PyTypeObject *)PyObject_GetAttrString(module, "CairoContext");
+        if (_PyGdkCairoContext_Type == NULL) {
+            PyErr_SetString(PyExc_ImportError,
+                "cannot import name CairoContext from gtk.gdk");
+            return ;
+        }
+    } else {
+        PyErr_SetString(PyExc_ImportError,
+            "could not import gtk.gdk");
+        return ;
+    }
 
 
 #line 198 "goocanvas.override"
@@ -10202,7 +10640,7 @@ pygoocanvas_register_classes(PyObject *d)
 
 
 
-#line 10206 "goocanvas.c"
+#line 10745 "goocanvas.c"
     pyg_register_boxed(d, "Points", GOO_TYPE_CANVAS_POINTS, &PyGooCanvasPoints_Type);
     pyg_register_boxed(d, "LineDash", GOO_TYPE_CANVAS_LINE_DASH, &PyGooCanvasLineDash_Type);
     pyg_register_interface(d, "Item", GOO_TYPE_CANVAS_ITEM, &PyGooCanvasItem_Type);
@@ -10210,7 +10648,6 @@ pygoocanvas_register_classes(PyObject *d)
     pyg_register_interface(d, "ItemModel", GOO_TYPE_CANVAS_ITEM_MODEL, &PyGooCanvasItemModel_Type);
     pyg_register_interface_info(GOO_TYPE_CANVAS_ITEM_MODEL, &__GooCanvasItemModel__iinfo);
     pygobject_register_class(d, "GooCanvas", GOO_TYPE_CANVAS, &PyGooCanvas_Type, Py_BuildValue("(O)", &PyGtkContainer_Type));
-    pyg_set_object_has_new_constructor(GOO_TYPE_CANVAS);
     pyg_register_class_init(GOO_TYPE_CANVAS, __GooCanvas_class_init);
     pygobject_register_class(d, "GooCanvasItemModelSimple", GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE, &PyGooCanvasItemModelSimple_Type, Py_BuildValue("(O)", &PyGObject_Type));
     pyg_set_object_has_new_constructor(GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE);
@@ -10225,8 +10662,6 @@ pygoocanvas_register_classes(PyObject *d)
     pyg_register_class_init(GOO_TYPE_CANVAS_ITEM_SIMPLE, __GooCanvasItemSimple_class_init);
     pygobject_register_class(d, "GooCanvasImage", GOO_TYPE_CANVAS_IMAGE, &PyGooCanvasImage_Type, Py_BuildValue("(O)", &PyGooCanvasItemSimple_Type));
     pyg_set_object_has_new_constructor(GOO_TYPE_CANVAS_IMAGE);
-    pygobject_register_class(d, "GooCanvasSvg", GOO_TYPE_CANVAS_SVG, &PyGooCanvasSvg_Type, Py_BuildValue("(O)", &PyGooCanvasItemSimple_Type));
-    pyg_set_object_has_new_constructor(GOO_TYPE_CANVAS_SVG);
     pygobject_register_class(d, "GooCanvasGroup", GOO_TYPE_CANVAS_GROUP, &PyGooCanvasGroup_Type, Py_BuildValue("(O)", &PyGooCanvasItemSimple_Type));
     pyg_set_object_has_new_constructor(GOO_TYPE_CANVAS_GROUP);
     pygobject_register_class(d, "GooCanvasEllipse", GOO_TYPE_CANVAS_ELLIPSE, &PyGooCanvasEllipse_Type, Py_BuildValue("(O)", &PyGooCanvasItemSimple_Type));
diff --git a/src/boards/goocanvas.defs b/src/boards/goocanvas.defs
index 863ce38..e534752 100644
--- a/src/boards/goocanvas.defs
+++ b/src/boards/goocanvas.defs
@@ -67,13 +67,6 @@
   (gtype-id "GOO_TYPE_CANVAS_IMAGE")
 )
 
-(define-object Svg
-  (in-module "Goo")
-  (parent "GooCanvasItemSimple")
-  (c-name "GooCanvasSvg")
-  (gtype-id "GOO_TYPE_CANVAS_SVG")
-)
-
 (define-object Group
   (in-module "Goo")
   (parent "GooCanvasItemSimple")
@@ -108,6 +101,9 @@
   (gtype-id "GOO_TYPE_CANVAS_POINTS")
   (copy-func "goo_canvas_points_ref")
   (release-func "goo_canvas_points_unref")
+  (fields
+   ("double*" "coords")
+   ("int" "num_points"))
 )
 
 (define-object Polyline
@@ -288,6 +284,36 @@
   )
 )
 
+(define-method get_static_root_item
+  (of-object "GooCanvas")
+  (c-name "goo_canvas_get_static_root_item")
+  (return-type "GooCanvasItem*")
+)
+
+(define-method set_static_root_item
+  (of-object "GooCanvas")
+  (c-name "goo_canvas_set_static_root_item")
+  (return-type "none")
+  (parameters
+    '("GooCanvasItem*" "item")
+  )
+)
+
+(define-method get_static_root_item_model
+  (of-object "GooCanvas")
+  (c-name "goo_canvas_get_static_root_item_model")
+  (return-type "GooCanvasItemModel*")
+)
+
+(define-method set_static_root_item_model
+  (of-object "GooCanvas")
+  (c-name "goo_canvas_set_static_root_item_model")
+  (return-type "none")
+  (parameters
+    '("GooCanvasItemModel*" "model")
+  )
+)
+
 (define-method get_item
   (of-object "GooCanvas")
   (c-name "goo_canvas_get_item")
@@ -442,6 +468,16 @@
   )
 )
 
+(define-method convert_bounds_to_item_space
+  (of-object "GooCanvas")
+  (c-name "goo_canvas_convert_bounds_to_item_space")
+  (return-type "none")
+  (parameters
+    '("GooCanvasItem*" "item")
+    '("GooCanvasBounds*" "bounds")
+  )
+)
+
 (define-method pointer_grab
   (of-object "GooCanvas")
   (c-name "goo_canvas_pointer_grab")
@@ -530,6 +566,16 @@
   )
 )
 
+(define-method request_item_redraw
+  (of-object "GooCanvas")
+  (c-name "goo_canvas_request_item_redraw")
+  (return-type "none")
+  (parameters
+    '("const-GooCanvasBounds*" "bounds")
+    '("gboolean" "is_static")
+  )
+)
+
 (define-method get_default_line_width
   (of-object "GooCanvas")
   (c-name "goo_canvas_get_default_line_width")
@@ -645,6 +691,7 @@
 
 
 
+
 ;; From goocanvasgroup.h
 
 (define-function goo_canvas_group_get_type
@@ -719,27 +766,6 @@
 
 
 
-;; From goocanvassvg.h
-
-(define-function goo_canvas_svg_get_type
-  (c-name "goo_canvas_svg_get_type")
-  (return-type "GType")
-)
-
-(define-function goo_canvas_svg_new
-  (c-name "goo_canvas_svg_new")
-  (is-constructor-of "GooCanvasSvg")
-  (return-type "GooCanvasItem*")
-  (parameters
-    '("GooCanvasItem*" "parent")
-    '("RsvgHandle*" "svg_handle")
-    '("const-gchar*" "svg_id")
-  )
-  (varargs #t)
-)
-
-
-
 ;; From goocanvasitem.h
 
 (define-function goo_canvas_item_get_type
@@ -800,6 +826,28 @@
   )
 )
 
+(define-method get_child_property
+  (of-object "GooCanvasItem")
+  (c-name "goo_canvas_item_get_child_property")
+  (return-type "none")
+  (parameters
+    '("GooCanvasItem*" "child")
+    '("const-gchar*" "property_name")
+    '("GValue*" "value")
+  )
+)
+
+(define-method set_child_property
+  (of-object "GooCanvasItem")
+  (c-name "goo_canvas_item_set_child_property")
+  (return-type "none")
+  (parameters
+    '("GooCanvasItem*" "child")
+    '("const-gchar*" "property_name")
+    '("const-GValue*" "value")
+  )
+)
+
 (define-method get_child_properties
   (of-object "GooCanvasItem")
   (c-name "goo_canvas_item_get_child_properties")
@@ -928,6 +976,18 @@
   )
 )
 
+(define-method get_simple_transform
+  (of-object "GooCanvasItem")
+  (c-name "goo_canvas_item_get_simple_transform")
+  (return-type "gboolean")
+  (parameters
+    '("gdouble*" "x")
+    '("gdouble*" "y")
+    '("gdouble*" "scale")
+    '("gdouble*" "rotation")
+  )
+)
+
 (define-method set_simple_transform
   (of-object "GooCanvasItem")
   (c-name "goo_canvas_item_set_simple_transform")
@@ -1510,6 +1570,28 @@
   )
 )
 
+(define-method get_child_property
+  (of-object "GooCanvasItemModel")
+  (c-name "goo_canvas_item_model_get_child_property")
+  (return-type "none")
+  (parameters
+    '("GooCanvasItemModel*" "child")
+    '("const-gchar*" "property_name")
+    '("GValue*" "value")
+  )
+)
+
+(define-method set_child_property
+  (of-object "GooCanvasItemModel")
+  (c-name "goo_canvas_item_model_set_child_property")
+  (return-type "none")
+  (parameters
+    '("GooCanvasItemModel*" "child")
+    '("const-gchar*" "property_name")
+    '("const-GValue*" "value")
+  )
+)
+
 (define-method get_child_properties
   (of-object "GooCanvasItemModel")
   (c-name "goo_canvas_item_model_get_child_properties")
@@ -1613,6 +1695,18 @@
   )
 )
 
+(define-method get_simple_transform
+  (of-object "GooCanvasItemModel")
+  (c-name "goo_canvas_item_model_get_simple_transform")
+  (return-type "gboolean")
+  (parameters
+    '("gdouble*" "x")
+    '("gdouble*" "y")
+    '("gdouble*" "scale")
+    '("gdouble*" "rotation")
+  )
+)
+
 (define-method set_simple_transform
   (of-object "GooCanvasItemModel")
   (c-name "goo_canvas_item_model_set_simple_transform")
@@ -2306,6 +2400,16 @@
   (varargs #t)
 )
 
+(define-method get_natural_extents
+  (of-object "GooCanvasText")
+  (c-name "goo_canvas_text_get_natural_extents")
+  (return-type "none")
+  (parameters
+    '("PangoRectangle*" "ink_rect")
+    '("PangoRectangle*" "logical_rect")
+  )
+)
+
 (define-function goo_canvas_text_model_get_type
   (c-name "goo_canvas_text_model_get_type")
   (return-type "GType")
diff --git a/src/boards/goocanvas.override b/src/boards/goocanvas.override
index e382c5c..334a5ba 100644
--- a/src/boards/goocanvas.override
+++ b/src/boards/goocanvas.override
@@ -210,14 +210,15 @@ modulename goocanvas
 import gobject.GObject as PyGObject_Type
 import gtk.Container as PyGtkContainer_Type
 import gtk.Adjustment as PyGtkAdjustment_Type
+import gtk.gdk.CairoContext as PyGdkCairoContext_Type
 
 %%
 ignore
+goo_canvas_new
 goo_canvas_ellipse_new
 goo_canvas_ellipse_model_new
 goo_canvas_group_new
 goo_canvas_group_model_new
-goo_canvas_svg_new
 goo_canvas_image_new
 goo_canvas_image_model_new
 goo_canvas_path_new
@@ -649,7 +650,7 @@ _wrap_GooCanvasItem__proxy_do_update(GooCanvasItem *self, gboolean entire_tree,
 
     py_bounds = PyObject_CallMethod(py_self, "do_update", "iN",
                                     entire_tree,
-                                    PycairoContext_FromContext(cairo_reference(cr), NULL, NULL));
+                                    PycairoContext_FromContext(cairo_reference(cr), &PyGdkCairoContext_Type, NULL));
     if (py_bounds)
         *bounds = ((PyGooCanvasBounds *) py_bounds)->bounds;
     else
@@ -1601,3 +1602,438 @@ _wrap_goo_canvas_item_simple__get_bounds(PyGObject *self, void *closure)
 {
     return pygoo_canvas_bounds_new(&GOO_CANVAS_ITEM_SIMPLE(pygobject_get(self))->bounds);
 }
+
+%%
+override goo_canvas_text_get_natural_extents noargs
+static PyObject *
+_wrap_goo_canvas_text_get_natural_extents(PyGObject *self)
+{
+    PangoRectangle ink_rect, logical_rect;
+
+    goo_canvas_text_get_natural_extents(GOO_CANVAS_TEXT(self->obj), &ink_rect,
+                                        &logical_rect);
+
+    return Py_BuildValue("((iiii)(iiii))",
+			 ink_rect.x, ink_rect.y,
+			 ink_rect.width, ink_rect.height,
+			 logical_rect.x, logical_rect.y,
+			 logical_rect.width, logical_rect.height);
+}
+
+%%
+override goo_canvas_item_get_simple_transform noargs
+static PyObject *
+_wrap_goo_canvas_item_get_simple_transform(PyGObject *self)
+{
+    gdouble x, y, scale, rotation;
+
+    goo_canvas_item_get_simple_transform(GOO_CANVAS_ITEM(self->obj), &x, &y,
+                                         &scale, &rotation);
+
+    return Py_BuildValue("dddd", x, y, scale, rotation);
+}
+
+%%
+override goo_canvas_item_model_get_simple_transform noargs
+static PyObject *
+_wrap_goo_canvas_item_model_get_simple_transform(PyGObject *self)
+{
+    gdouble x, y, scale, rotation;
+
+    goo_canvas_item_model_get_simple_transform(GOO_CANVAS_ITEM_MODEL(self->obj),
+                                               &x, &y, &scale, &rotation);
+
+    return Py_BuildValue("dddd", x, y, scale, rotation);
+}
+
+%%
+override goo_canvas_item_set_child_property kwargs
+static PyObject *
+_wrap_goo_canvas_item_set_child_property(PyGObject *self,
+                                         PyObject *args,
+                                         PyObject *kwargs)
+{
+    static char    *kwlist[] = { "child", "property", "value", NULL };
+    gchar *property_name;
+    PyGObject *pychild;
+    GooCanvasItem *item, *child;
+    PyGObject *pyvalue;
+    GObjectClass *class;
+    GParamSpec *pspec;
+    GValue value = { 0, } ;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O!sO:GooCanvasItem.set_child_property",
+                                     kwlist,
+                                    &PyGooCanvasItem_Type, &pychild,
+                                    &property_name, &pyvalue)) {
+        return NULL;
+    }
+
+    item = GOO_CANVAS_ITEM(self->obj);
+    child = GOO_CANVAS_ITEM(pychild->obj);
+
+    if (goo_canvas_item_find_child(item, child) == -1) {
+        PyErr_SetString(PyExc_TypeError,
+                        "first argument must be a child");
+        return NULL;
+    }
+
+    class = G_OBJECT_GET_CLASS(self->obj);
+    pspec = goo_canvas_item_class_find_child_property(class, property_name);
+    if (!pspec) {
+        gchar buf[512];
+        g_snprintf(buf, sizeof(buf),
+                   "item does not support property `%s'",
+                   property_name);
+        PyErr_SetString(PyExc_TypeError, buf);
+
+        return NULL;
+    }
+
+    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+
+    pyg_value_from_pyobject(&value, (PyObject*)pyvalue);
+
+    goo_canvas_item_set_child_property(item,
+                                       child,
+                                       property_name,
+                                       &value);
+    g_value_unset(&value);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+%%
+override goo_canvas_item_get_child_property
+static PyObject *
+_wrap_goo_canvas_item_get_child_property(PyGObject *self,
+                                         PyObject *args,
+                                         PyObject *kwargs)
+{
+    static char    *kwlist[] = { "child", "property", NULL };
+    PyGObject *pychild;
+    gchar *property_name;
+    GooCanvasItem *item, *child;
+    GObjectClass *class;
+    GParamSpec *pspec;
+    GValue value = { 0, } ;
+    PyObject *ret;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O!s:GooCanvasItem.get_child_property",
+                                     kwlist, &PyGooCanvasItem_Type, &pychild,
+                                     &property_name)) {
+        return NULL;
+    }
+
+    item = GOO_CANVAS_ITEM(self->obj);
+    child = GOO_CANVAS_ITEM(pychild->obj);
+
+    if (goo_canvas_item_find_child(item, child) == -1) {
+        PyErr_SetString(PyExc_TypeError,
+                        "first argument must be a child");
+        return NULL;
+    }
+
+    class = G_OBJECT_GET_CLASS(item);
+    pspec = goo_canvas_item_class_find_child_property(class, property_name);
+    if (!pspec) {
+        gchar buf[512];
+        g_snprintf(buf, sizeof(buf),
+                   "item does not support property `%s'",
+                   property_name);
+
+        PyErr_SetString(PyExc_TypeError, buf);
+        return NULL;
+    }
+
+    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+
+    goo_canvas_item_get_child_property(item,
+                                       child,
+                                       property_name,
+                                       &value);
+
+    ret = pyg_value_as_pyobject(&value, TRUE);
+    g_value_unset(&value);
+
+    return ret;
+}
+
+%%
+override goo_canvas_item_model_set_child_property kwargs
+static PyObject *
+_wrap_goo_canvas_item_model_set_child_property(PyGObject *self,
+                                         PyObject *args,
+                                         PyObject *kwargs)
+{
+    static char    *kwlist[] = { "child", "property", "value", NULL };
+    gchar *property_name;
+    PyGObject *pychild;
+    GooCanvasItemModel *item, *child;
+    PyGObject *pyvalue;
+    GObjectClass *class;
+    GParamSpec *pspec;
+    GValue value = { 0, } ;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                "O!sO:GooCanvasItemModel.set_child_property",
+                                kwlist,
+                                &PyGooCanvasItemModel_Type, &pychild,
+                                &property_name, &pyvalue)) {
+        return NULL;
+    }
+
+    item = GOO_CANVAS_ITEM_MODEL(self->obj);
+    child = GOO_CANVAS_ITEM_MODEL(pychild->obj);
+
+    if (goo_canvas_item_model_find_child(item, child) == -1) {
+        PyErr_SetString(PyExc_TypeError,
+                        "first argument must be a child");
+        return NULL;
+    }
+
+    class = G_OBJECT_GET_CLASS(self->obj);
+    pspec = goo_canvas_item_model_class_find_child_property(class, property_name);
+    if (!pspec) {
+        gchar buf[512];
+        g_snprintf(buf, sizeof(buf),
+                   "item model does not support property `%s'",
+                   property_name);
+        PyErr_SetString(PyExc_TypeError, buf);
+
+        return NULL;
+    }
+
+    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+
+    pyg_value_from_pyobject(&value, (PyObject*)pyvalue);
+
+    goo_canvas_item_model_set_child_property(item,
+                                             child,
+                                             property_name,
+                                             &value);
+    g_value_unset(&value);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+%%
+override goo_canvas_item_model_get_child_property
+static PyObject *
+_wrap_goo_canvas_item_model_get_child_property(PyGObject *self,
+                                         PyObject *args,
+                                         PyObject *kwargs)
+{
+    static char    *kwlist[] = { "child", "property", NULL };
+    PyGObject *pychild;
+    gchar *property_name;
+    GooCanvasItemModel *item, *child;
+    GObjectClass *class;
+    GParamSpec *pspec;
+    GValue value = { 0, } ;
+    PyObject *ret;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                "O!s:GooCanvasItemModel.get_child_property",
+                                kwlist, &PyGooCanvasItemModel_Type, &pychild,
+                                &property_name)) {
+        return NULL;
+    }
+
+    item = GOO_CANVAS_ITEM_MODEL(self->obj);
+    child = GOO_CANVAS_ITEM_MODEL(pychild->obj);
+
+    if (goo_canvas_item_model_find_child(item, child) == -1) {
+        PyErr_SetString(PyExc_TypeError,
+                        "first argument must be a child");
+        return NULL;
+    }
+
+    class = G_OBJECT_GET_CLASS(item);
+    pspec = goo_canvas_item_model_class_find_child_property(class, property_name);
+    if (!pspec) {
+        gchar buf[512];
+        g_snprintf(buf, sizeof(buf),
+                   "item model does not support property `%s'",
+                   property_name);
+
+        PyErr_SetString(PyExc_TypeError, buf);
+        return NULL;
+    }
+
+    g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
+
+    goo_canvas_item_model_get_child_property(item,
+                                             child,
+                                             property_name,
+                                             &value);
+
+    ret = pyg_value_as_pyobject(&value, TRUE);
+    g_value_unset(&value);
+
+    return ret;
+}
+
+%%
+override-attr GooCanvasPoints.coords
+
+static PyObject *
+_wrap_goo_canvas_points__get_coords(PyObject *self, void *closure)
+{
+    gdouble     *coords;
+    int         num_points, i;
+    PyObject    *ret = Py_None;
+
+    num_points = pyg_boxed_get(self, GooCanvasPoints)->num_points;
+    coords = pyg_boxed_get(self, GooCanvasPoints)->coords;
+
+    if (num_points > 0) {
+        ret = PyList_New(num_points);
+
+        for (i = 0; i < num_points; i ++) {
+            PyObject *py_temp = Py_BuildValue("dd", coords[2*i], coords[2*i + 1]);
+            PyList_SetItem(ret, i, py_temp);
+        }
+        return ret;
+    }
+    Py_INCREF(ret);
+    return ret;
+}
+
+%%
+override goo_canvas_item_get_requested_area kwargs
+static PyObject *
+_wrap_goo_canvas_item_get_requested_area(PyGObject *self,
+                                         PyObject *args,
+                                         PyObject *kwargs)
+{
+    static char     *kwlist[] = { "cr", NULL };
+    int             ret;
+    GooCanvasBounds bounds;
+    PycairoContext  *cr;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O!:GooCanvasItem.get_requested_area",
+                                     kwlist, &PycairoContext_Type, &cr))
+        return NULL;
+
+    ret = goo_canvas_item_get_requested_area(GOO_CANVAS_ITEM(self->obj),
+                                             cr->ctx, &bounds);
+
+    return pygoo_canvas_bounds_new(&bounds);
+}
+
+%%
+override goo_canvas_item_update kwargs
+static PyObject *
+_wrap_goo_canvas_item_update(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "entire_tree", "cr", NULL };
+    int             entire_tree;
+    PycairoContext  *cr;
+    GooCanvasBounds bounds;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,"iO!:GooCanvasItem.update",
+                                     kwlist, &entire_tree,
+                                     &PycairoContext_Type, &cr))
+        return NULL;
+
+    goo_canvas_item_update(GOO_CANVAS_ITEM(self->obj), entire_tree,
+                           cr->ctx, &bounds);
+
+    return pygoo_canvas_bounds_new(&bounds);
+}
+
+%%
+override goo_canvas_item_get_transform_for_child kwargs
+static PyObject *
+_wrap_goo_canvas_item_get_transform_for_child(PyGObject *self,
+                                              PyObject *args,
+                                              PyObject *kwargs)
+{
+    static char *kwlist[] = { "child", NULL };
+    PyGObject *child;
+    int ret;
+    cairo_matrix_t *transform = NULL;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O!:GooCanvasItem.get_transform_for_child",
+                                     kwlist, &PyGooCanvasItem_Type, &child))
+        return NULL;
+
+    ret = goo_canvas_item_get_transform_for_child(GOO_CANVAS_ITEM(self->obj),
+                                                  GOO_CANVAS_ITEM(child->obj),
+                                                  transform);
+
+    if (ret)
+        return PycairoMatrix_FromMatrix(transform);
+    else
+        Py_INCREF(Py_None);
+        return Py_None;
+}
+
+%%
+override goo_canvas_item_set_transform kwargs
+static PyObject *
+_wrap_goo_canvas_item_set_transform(PyGObject *self,
+                                    PyObject *args,
+                                    PyObject *kwargs)
+{
+    static char *kwlist[] = { "matrix", NULL };
+    PyObject *py_matrix;
+    cairo_matrix_t *matrix = NULL;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O:GooCanvasItem.set_transform",
+                                     kwlist, &py_matrix))
+        return NULL;
+
+    if (py_matrix && (py_matrix != Py_None))
+        matrix = &((PycairoMatrix*)(py_matrix))->matrix;
+
+    goo_canvas_item_set_transform(GOO_CANVAS_ITEM(self->obj), matrix);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+%%
+override goo_canvas_item_model_set_transform kwargs
+static PyObject *
+_wrap_goo_canvas_item_model_set_transform(PyGObject *self,
+                                          PyObject *args,
+                                          PyObject *kwargs)
+{
+    static char *kwlist[] = { "matrix", NULL };
+    PyObject *py_matrix;
+    cairo_matrix_t *matrix = NULL;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                                     "O:GooCanvasItemModel.set_transform",
+                                     kwlist, &py_matrix))
+        return NULL;
+
+    if (py_matrix && (py_matrix != Py_None))
+        matrix = &((PycairoMatrix*)(py_matrix))->matrix;
+
+    goo_canvas_item_model_set_transform(GOO_CANVAS_ITEM_MODEL(self->obj),
+                                        matrix);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+%%
+override goo_canvas_create_cairo_context noargs
+static PyObject *
+_wrap_goo_canvas_create_cairo_context(PyGObject *self)
+{
+    cairo_t *ret;
+
+    ret = goo_canvas_create_cairo_context(GOO_CANVAS(self->obj));
+
+    cairo_reference(ret);
+    return PycairoContext_FromContext(ret, &PyGdkCairoContext_Type, NULL);
+}
diff --git a/src/boards/goocanvasmodule.c b/src/boards/goocanvasmodule.c
index 95a75a8..bf19f2b 100644
--- a/src/boards/goocanvasmodule.c
+++ b/src/boards/goocanvasmodule.c
@@ -11,11 +11,11 @@
 Pycairo_CAPI_t *Pycairo_CAPI;
 
 
-void pygoocanvas_register_classes (PyObject *d);
+void pygoocanvas_register_classes (PyObject *d); 
 void pygoocanvas_add_constants(PyObject *module, const gchar *strip_prefix);
 
 extern PyMethodDef pygoocanvas_functions[];
-
+ 
 static PyObject *
 _cairo_matrix_from_gvalue(const GValue *value)
 {
@@ -65,9 +65,9 @@ initgoocanvas (void)
 
     m = Py_InitModule ("goocanvas", pygoocanvas_functions);
     d = PyModule_GetDict (m);
-
+    
     init_pygobject ();
-
+    
     pygoocanvas_register_classes (d);
     pygoocanvas_add_constants(m, "GOO_CANVAS_");
     PyModule_AddObject(m, "TYPE_CAIRO_MATRIX", pyg_type_wrapper_new(GOO_TYPE_CAIRO_MATRIX));
@@ -84,7 +84,7 @@ initgoocanvas (void)
                                      PYGOOCANVAS_MAJOR_VERSION,
                                      PYGOOCANVAS_MINOR_VERSION,
                                      PYGOOCANVAS_MICRO_VERSION));
-
+    
     if (PyErr_Occurred ())
         Py_FatalError ("can't initialise module goocanvas");
 }
diff --git a/src/goocanvas/src/goocanvas.c b/src/goocanvas/src/goocanvas.c
index 2eb41b3..f59bbdf 100644
--- a/src/goocanvas/src/goocanvas.c
+++ b/src/goocanvas/src/goocanvas.c
@@ -105,6 +105,17 @@
 #include "goocanvasmarshal.h"
 
 
+#define GOO_CANVAS_GET_PRIVATE(canvas)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((canvas), GOO_TYPE_CANVAS, GooCanvasPrivate))
+
+typedef struct _GooCanvasPrivate GooCanvasPrivate;
+struct _GooCanvasPrivate {
+  GooCanvasItem *static_root_item;
+  GooCanvasItemModel *static_root_item_model;
+  gint window_x, window_y;
+};
+
+
 enum {
   PROP_0,
 
@@ -125,7 +136,8 @@ enum {
   PROP_BACKGROUND_COLOR,
   PROP_BACKGROUND_COLOR_RGB,
   PROP_INTEGER_LAYOUT, 
-  PROP_CLEAR_BACKGROUND
+  PROP_CLEAR_BACKGROUND,
+  PROP_REDRAW_WHEN_SCROLLED
 };
 
 enum {
@@ -134,6 +146,7 @@ enum {
   LAST_SIGNAL
 };
 
+
 static guint canvas_signals[LAST_SIGNAL] = { 0 };
 
 static void     goo_canvas_dispose	   (GObject          *object);
@@ -188,6 +201,11 @@ static void     goo_canvas_forall          (GtkContainer     *container,
 					    gboolean          include_internals,
 					    GtkCallback       callback,
 					    gpointer          callback_data);
+static gboolean goo_canvas_query_tooltip   (GtkWidget	     *widget,
+					    gint              x,
+					    gint              y,
+					    gboolean          keyboard_tip,
+					    GtkTooltip       *tooltip);
 
 static void	goo_canvas_set_scale_internal (GooCanvas     *canvas,
 					       gdouble        scale_x,
@@ -201,6 +219,9 @@ static void     reconfigure_canvas	   (GooCanvas        *canvas,
 					    gboolean          redraw_if_needed);
 static void	goo_canvas_update_automatic_bounds (GooCanvas       *canvas);
 
+static void     goo_canvas_convert_to_static_item_space (GooCanvas     *canvas,
+							 gdouble       *x,
+							 gdouble       *y);
 
 G_DEFINE_TYPE (GooCanvas, goo_canvas, GTK_TYPE_CONTAINER)
 
@@ -217,6 +238,8 @@ goo_canvas_class_init (GooCanvasClass *klass)
   GtkWidgetClass *widget_class = (GtkWidgetClass*) klass;
   GtkContainerClass *container_class = (GtkContainerClass*) klass;
 
+  g_type_class_add_private (gobject_class, sizeof (GooCanvasPrivate));
+
   gobject_class->dispose	     = goo_canvas_dispose;
   gobject_class->finalize	     = goo_canvas_finalize;
   gobject_class->get_property	     = goo_canvas_get_property;
@@ -241,6 +264,7 @@ goo_canvas_class_init (GooCanvasClass *klass)
   widget_class->focus_in_event       = goo_canvas_focus_in;
   widget_class->focus_out_event      = goo_canvas_focus_out;
   widget_class->grab_broken_event    = goo_canvas_grab_broken;
+  widget_class->query_tooltip	     = goo_canvas_query_tooltip;
 
   container_class->remove	     = goo_canvas_remove;
   container_class->forall            = goo_canvas_forall;
@@ -393,6 +417,13 @@ goo_canvas_class_init (GooCanvasClass *klass)
 							 TRUE,
 							 G_PARAM_READWRITE));
 
+  g_object_class_install_property (gobject_class, PROP_REDRAW_WHEN_SCROLLED, 
+                                   g_param_spec_boolean ("redraw-when-scrolled",
+							 _("Redraw When Scrolled"),
+							 _("If the canvas is completely redrawn when scrolled, to reduce the flicker of static items"),
+							 FALSE,
+							 G_PARAM_READWRITE));
+
   /**
    * GooCanvas::set-scroll-adjustments
    * @canvas: the canvas.
@@ -443,6 +474,8 @@ goo_canvas_class_init (GooCanvasClass *klass)
 static void
 goo_canvas_init (GooCanvas *canvas)
 {
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+
   /* We set GTK_CAN_FOCUS by default, so it works as people expect.
      Though developers can turn this off if not needed for efficiency. */
   GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS);
@@ -455,6 +488,7 @@ goo_canvas_init (GooCanvas *canvas)
   canvas->crossing_event.type = GDK_LEAVE_NOTIFY;
   canvas->anchor = GTK_ANCHOR_NORTH_WEST;
   canvas->clear_background = TRUE;
+  canvas->redraw_when_scrolled = FALSE;
 
   /* Set the default bounds to a reasonable size. */
   canvas->bounds.x1 = 0.0;
@@ -485,6 +519,14 @@ goo_canvas_init (GooCanvas *canvas)
      time. Apps can set their own root item if required. */
   canvas->root_item = goo_canvas_group_new (NULL, NULL);
   goo_canvas_item_set_canvas (canvas->root_item, canvas);
+
+  priv->static_root_item = goo_canvas_group_new (NULL, NULL);
+  goo_canvas_item_set_canvas (priv->static_root_item, canvas);
+  goo_canvas_item_set_is_static (priv->static_root_item, TRUE);
+  priv->static_root_item_model = NULL;
+
+  priv->window_x = 0;
+  priv->window_y = 0;
 }
 
 
@@ -509,6 +551,7 @@ static void
 goo_canvas_dispose (GObject *object)
 {
   GooCanvas *canvas = (GooCanvas*) object;
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
 
   if (canvas->model_to_item)
     {
@@ -528,6 +571,18 @@ goo_canvas_dispose (GObject *object)
       canvas->root_item_model = NULL;
     }
 
+  if (priv->static_root_item)
+    {
+      g_object_unref (priv->static_root_item);
+      priv->static_root_item = NULL;
+    }
+
+  if (priv->static_root_item_model)
+    {
+      g_object_unref (priv->static_root_item_model);
+      priv->static_root_item_model = NULL;
+    }
+
   if (canvas->idle_id)
     {
       g_source_remove (canvas->idle_id);
@@ -703,6 +758,9 @@ goo_canvas_get_property    (GObject            *object,
     case PROP_CLEAR_BACKGROUND:
       g_value_set_boolean (value, canvas->clear_background);
       break;
+    case PROP_REDRAW_WHEN_SCROLLED:
+      g_value_set_boolean (value, canvas->redraw_when_scrolled);
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -806,6 +864,9 @@ goo_canvas_set_property    (GObject            *object,
     case PROP_CLEAR_BACKGROUND:
       canvas->clear_background = g_value_get_boolean (value);
       break;
+    case PROP_REDRAW_WHEN_SCROLLED:
+      canvas->redraw_when_scrolled = g_value_get_boolean (value);
+      break;
 
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -954,6 +1015,170 @@ goo_canvas_set_root_item    (GooCanvas		*canvas,
 
 
 /**
+ * goo_canvas_get_static_root_item:
+ * @canvas: a #GooCanvas.
+ *
+ * Gets the static root item of the canvas.
+ *
+ * Static items are exactly the same as ordinary canvas items, except that
+ * they do not move or change size when the canvas is scrolled or the scale
+ * changes.
+ *
+ * Static items are added to the static root item in exactly the same way that
+ * ordinary items are added to the root item.
+ *
+ * Returns: the static root item, or %NULL.
+ **/
+GooCanvasItem*
+goo_canvas_get_static_root_item    (GooCanvas		*canvas)
+{
+  g_return_val_if_fail (GOO_IS_CANVAS (canvas), NULL);
+
+  return GOO_CANVAS_GET_PRIVATE (canvas)->static_root_item;
+}
+
+
+/**
+ * goo_canvas_set_static_root_item:
+ * @canvas: a #GooCanvas.
+ * @item: the static root item.
+ *
+ * Sets the static root item. Any existing static items are removed.
+ *
+ * Static items are exactly the same as ordinary canvas items, except that
+ * they do not move or change size when the canvas is scrolled or the scale
+ * changes.
+ *
+ * Static items are added to the static root item in exactly the same way that
+ * ordinary items are added to the root item.
+ **/
+void
+goo_canvas_set_static_root_item    (GooCanvas		*canvas,
+				    GooCanvasItem       *item)
+{
+  GooCanvasPrivate *priv;
+
+  g_return_if_fail (GOO_IS_CANVAS (canvas));
+  g_return_if_fail (GOO_IS_CANVAS_ITEM (item));
+
+  priv = GOO_CANVAS_GET_PRIVATE (canvas);
+
+  if (priv->static_root_item == item)
+    return;
+
+  /* Remove any current model. */
+  if (priv->static_root_item_model)
+    {
+      g_object_unref (priv->static_root_item_model);
+      priv->static_root_item_model = NULL;
+    }
+
+  if (priv->static_root_item)
+    g_object_unref (priv->static_root_item);
+
+  priv->static_root_item = g_object_ref (item);
+  goo_canvas_item_set_canvas (priv->static_root_item, canvas);
+  goo_canvas_item_set_is_static (priv->static_root_item, TRUE);
+
+  canvas->need_update = TRUE;
+
+  if (GTK_WIDGET_REALIZED (canvas))
+    goo_canvas_update (canvas);
+
+  gtk_widget_queue_draw (GTK_WIDGET (canvas));
+}
+
+
+/**
+ * goo_canvas_get_static_root_item_model:
+ * @canvas: a #GooCanvas.
+ *
+ * Gets the static root item model of the canvas.
+ *
+ * Static item models are exactly the same as ordinary item models, except that
+ * the corresponding items do not move or change size when the canvas is
+ * scrolled or the scale changes.
+ *
+ * Static items models are added to the static root item model in exactly the
+ * same way that ordinary item models are added to the root item model.
+ *
+ * Returns: the static root item model, or %NULL.
+ **/
+GooCanvasItemModel*
+goo_canvas_get_static_root_item_model (GooCanvas	  *canvas)
+{
+  g_return_val_if_fail (GOO_IS_CANVAS (canvas), NULL);
+
+  return GOO_CANVAS_GET_PRIVATE (canvas)->static_root_item_model;
+}
+
+
+/**
+ * goo_canvas_set_static_root_item_model:
+ * @canvas: a #GooCanvas.
+ * @model: the static root item model.
+ *
+ * Sets the static root item model. Any existing static item models are
+ * removed.
+ *
+ * Static item models are exactly the same as ordinary item models, except that
+ * the corresponding items do not move or change size when the canvas is
+ * scrolled or the scale changes.
+ *
+ * Static items models are added to the static root item model in exactly the
+ * same way that ordinary item models are added to the root item model.
+ **/
+void
+goo_canvas_set_static_root_item_model (GooCanvas	  *canvas,
+				       GooCanvasItemModel *model)
+{
+  GooCanvasPrivate *priv;
+
+  g_return_if_fail (GOO_IS_CANVAS (canvas));
+  g_return_if_fail (GOO_IS_CANVAS_ITEM_MODEL (model));
+
+  priv = GOO_CANVAS_GET_PRIVATE (canvas);
+
+  if (priv->static_root_item_model == model)
+    return;
+
+  if (priv->static_root_item_model)
+    {
+      g_object_unref (priv->static_root_item_model);
+      priv->static_root_item_model = NULL;
+    }
+
+  if (priv->static_root_item)
+    {
+      g_object_unref (priv->static_root_item);
+      priv->static_root_item = NULL;
+    }
+
+  if (model)
+    {
+      priv->static_root_item_model = g_object_ref (model);
+
+      /* Create a hierarchy of canvas items for all the items in the model. */
+      priv->static_root_item = goo_canvas_create_item (canvas, model);
+    }
+  else
+    {
+      /* The model has been reset so we go back to a default root group. */
+      priv->static_root_item = goo_canvas_group_new (NULL, NULL);
+    }
+
+  goo_canvas_item_set_canvas (priv->static_root_item, canvas);
+  goo_canvas_item_set_is_static (priv->static_root_item, TRUE);
+  canvas->need_update = TRUE;
+
+  if (GTK_WIDGET_REALIZED (canvas))
+    goo_canvas_update (canvas);
+
+  gtk_widget_queue_draw (GTK_WIDGET (canvas));
+}
+
+
+/**
  * goo_canvas_get_item:
  * @canvas: a #GooCanvas.
  * @model: a #GooCanvasItemModel.
@@ -1014,19 +1239,30 @@ goo_canvas_get_item_at (GooCanvas     *canvas,
 			gdouble        y,
 			gboolean       is_pointer_event)
 {
+  GooCanvasPrivate *priv;
   cairo_t *cr;
   GooCanvasItem *result = NULL;
-  GList *list;
+  GList *list = NULL;
 
   g_return_val_if_fail (GOO_IS_CANVAS (canvas), NULL);
 
-  /* If no root item is set, just return NULL. */
-  if (!canvas->root_item)
-    return NULL;
-
+  priv = GOO_CANVAS_GET_PRIVATE (canvas);
   cr = goo_canvas_create_cairo_context (canvas);
-  list = goo_canvas_item_get_items_at (canvas->root_item, x, y, cr,
-				       is_pointer_event, TRUE, NULL);
+
+  if (canvas->root_item)
+    list = goo_canvas_item_get_items_at (canvas->root_item, x, y, cr,
+					 is_pointer_event, TRUE, NULL);
+
+  if (!list && priv->static_root_item)
+    {
+      gdouble static_x = x, static_y = y;
+
+      goo_canvas_convert_to_static_item_space (canvas, &static_x, &static_y);
+      list = goo_canvas_item_get_items_at (priv->static_root_item,
+					   static_x, static_y, cr,
+					   is_pointer_event, TRUE, NULL);
+    }
+
   cairo_destroy (cr);
 
   /* We just return the top item in the list. */
@@ -1059,18 +1295,29 @@ goo_canvas_get_items_at (GooCanvas     *canvas,
 			 gdouble        y,
 			 gboolean       is_pointer_event)
 {
+  GooCanvasPrivate *priv;
   cairo_t *cr;
-  GList *result;
+  GList *result = NULL;
 
   g_return_val_if_fail (GOO_IS_CANVAS (canvas), NULL);
 
-  /* If no root item is set, just return NULL. */
-  if (!canvas->root_item)
-    return NULL;
-
+  priv = GOO_CANVAS_GET_PRIVATE (canvas);
   cr = goo_canvas_create_cairo_context (canvas);
-  result = goo_canvas_item_get_items_at (canvas->root_item, x, y, cr,
-					 is_pointer_event, TRUE, NULL);
+
+  if (canvas->root_item)
+    result = goo_canvas_item_get_items_at (canvas->root_item, x, y, cr,
+					   is_pointer_event, TRUE, NULL);
+
+  if (priv->static_root_item)
+    {
+      gdouble static_x = x, static_y = y;
+
+      goo_canvas_convert_to_static_item_space (canvas, &static_x, &static_y);
+      result = goo_canvas_item_get_items_at (priv->static_root_item,
+					     static_x, static_y, cr,
+					     is_pointer_event, TRUE, result);
+    }
+
   cairo_destroy (cr);
 
   return result;
@@ -1181,6 +1428,7 @@ static void
 goo_canvas_realize (GtkWidget *widget)
 {
   GooCanvas *canvas;
+  GooCanvasPrivate *priv;
   GdkWindowAttr attributes;
   gint attributes_mask;
   gint width_pixels, height_pixels;
@@ -1189,6 +1437,7 @@ goo_canvas_realize (GtkWidget *widget)
   g_return_if_fail (GOO_IS_CANVAS (widget));
 
   canvas = GOO_CANVAS (widget);
+  priv = GOO_CANVAS_GET_PRIVATE (canvas);
   GTK_WIDGET_SET_FLAGS (canvas, GTK_REALIZED);
 
   attributes.window_type = GDK_WINDOW_CHILD;
@@ -1228,6 +1477,9 @@ goo_canvas_realize (GtkWidget *widget)
 			 | GDK_FOCUS_CHANGE_MASK
                          | gtk_widget_get_events (widget);
 
+  priv->window_x = attributes.x;
+  priv->window_y = attributes.y;
+
   canvas->canvas_window = gdk_window_new (widget->window,
 					  &attributes, attributes_mask);
   gdk_window_set_user_data (canvas->canvas_window, widget);
@@ -1440,6 +1692,74 @@ recalculate_scales (GooCanvas *canvas)
 }
 
 
+static void
+request_static_redraw (GooCanvas             *canvas,
+		       const GooCanvasBounds *bounds)
+{
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+  GdkRectangle rect;
+
+  if (!GTK_WIDGET_DRAWABLE (canvas) || (bounds->x1 == bounds->x2))
+    return;
+
+  /* We subtract one from the left & top edges, in case anti-aliasing makes
+     the drawing use an extra pixel. */
+  rect.x = (double) bounds->x1 - priv->window_x - 1;
+  rect.y = (double) bounds->y1 - priv->window_y - 1;
+
+  /* We add an extra one here for the same reason. (The other extra one is to
+     round up to the next pixel.) And one for luck! */
+  rect.width = (double) bounds->x2 - priv->window_x - rect.x + 2 + 1;
+  rect.height = (double) bounds->y2 - priv->window_y - rect.y + 2 + 1;
+
+  gdk_window_invalidate_rect (canvas->canvas_window, &rect, FALSE);
+}
+
+
+/* This requests a redraw of all the toplevel static items at their current
+   position, but redraws them at their given new position.
+   We redraw one item at a time to avoid GTK+ merging the rectangles into
+   one big one. */
+static void
+redraw_static_items_at_position (GooCanvas *canvas,
+				 gint       x,
+				 gint       y)
+{
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+  GooCanvasBounds bounds;
+  GooCanvasItem *item;
+  gint n_children, i, window_x_copy, window_y_copy;
+
+  if (!priv->static_root_item)
+    return;
+
+  window_x_copy = priv->window_x;
+  window_y_copy = priv->window_y;
+
+  n_children = goo_canvas_item_get_n_children (priv->static_root_item);
+  for (i = 0; i < n_children; i++)
+    {
+      item = goo_canvas_item_get_child (priv->static_root_item, i);
+
+      /* Get the bounds of all the static items, relative to the window. */
+      goo_canvas_item_get_bounds (item, &bounds);
+
+      /* Request a redraw of the old position. */
+      request_static_redraw (canvas, &bounds);
+
+      /* Redraw the item in its new position. */
+      priv->window_x = x;
+      priv->window_y = y;
+
+      gdk_window_process_updates (canvas->canvas_window, TRUE);
+
+      /* Now reset the window position. */
+      priv->window_x = window_x_copy;
+      priv->window_y = window_y_copy;
+    }
+}
+
+
 /* This makes sure the canvas is all set up correctly, i.e. the scrollbar
    adjustments are set, the canvas x & y offsets are calculated, and the
    canvas window is sized. */
@@ -1648,18 +1968,52 @@ static void
 goo_canvas_adjustment_value_changed (GtkAdjustment *adjustment,
 				     GooCanvas     *canvas)
 {
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
   AtkObject *accessible;
 
   if (!canvas->freeze_count && GTK_WIDGET_REALIZED (canvas))
     {
+      if (canvas->redraw_when_scrolled)
+	{
+	  /* Map the temporary window to stop the canvas window being scrolled.
+	     When it is unmapped the entire canvas will be redrawn. */
+	  if (GTK_WIDGET_MAPPED (canvas))
+	    gdk_window_show (canvas->tmp_window);
+	}
+      else
+	{
+	  /* Redraw the area currently occupied by the static items. But
+	     draw the static items in their new position. This stops them
+	     from being "dragged" when the window is scrolled. */
+	  redraw_static_items_at_position (canvas,
+					   -canvas->hadjustment->value,
+					   -canvas->hadjustment->value);
+
+	  /* Move the static items to the new position. */
+	  priv->window_x = -canvas->hadjustment->value;
+	  priv->window_y = -canvas->vadjustment->value;
+	}
+
       gdk_window_move (canvas->canvas_window,
 		       - canvas->hadjustment->value,
 		       - canvas->vadjustment->value);
-      
-      /* If this is callback from a signal for one of the scrollbars, process
-	 updates here for smoother scrolling. */
-      if (adjustment)
-	gdk_window_process_updates (canvas->canvas_window, TRUE);
+
+      if (canvas->redraw_when_scrolled)
+	{
+	  /* Unmap the temporary window, causing the entire canvas to be
+	     redrawn. */
+	  if (GTK_WIDGET_MAPPED (canvas))
+	    gdk_window_hide (canvas->tmp_window);
+	}
+      else
+	{
+	  /* Process updates here for smoother scrolling. */
+	  gdk_window_process_updates (canvas->canvas_window, TRUE);
+
+	  /* Now ensure the static items are redrawn in their new position. */
+	  redraw_static_items_at_position (canvas, priv->window_x,
+					   priv->window_y);
+	}
 
       /* Notify any accessibility modules that the view has changed. */
       accessible = gtk_widget_get_accessible (GTK_WIDGET (canvas));
@@ -1865,6 +2219,10 @@ goo_canvas_scroll_to_item (GooCanvas     *canvas,
   GooCanvasBounds bounds;
   gdouble hvalue, vvalue;
 
+  /* We can't scroll to static items. */
+  if (goo_canvas_item_get_is_static (item))
+    return;
+
   goo_canvas_item_get_bounds (item, &bounds);
 
   goo_canvas_convert_to_pixels (canvas, &bounds.x1, &bounds.y1);
@@ -2095,7 +2453,8 @@ static void
 goo_canvas_update_internal (GooCanvas *canvas,
 			    cairo_t   *cr)
 {
-  GooCanvasBounds bounds;
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+  GooCanvasBounds bounds, static_bounds;
 
   /* It is possible that processing the first set of updates causes other
      updates to be scheduled, so we loop round until all are done. Items
@@ -2108,6 +2467,10 @@ goo_canvas_update_internal (GooCanvas *canvas,
       canvas->need_entire_subtree_update = FALSE;
       if (canvas->root_item)
 	goo_canvas_item_update (canvas->root_item, entire_tree, cr, &bounds);
+
+      if (priv->static_root_item)
+	goo_canvas_item_update (priv->static_root_item, entire_tree, cr,
+				&static_bounds);
     }
 
   /* If the bounds are automatically-calculated, update them now. */
@@ -2189,12 +2552,13 @@ goo_canvas_request_update (GooCanvas   *canvas)
 /**
  * goo_canvas_request_redraw:
  * @canvas: a #GooCanvas.
- * @bounds: the bounds to redraw.
+ * @bounds: the bounds to redraw, in device space.
  * 
  * This function is only intended to be used by subclasses of #GooCanvas or
  * #GooCanvasItem implementations.
  *
- * Requests that the given bounds be redrawn.
+ * Requests that the given bounds be redrawn. The bounds must be in the canvas
+ * coordinate space.
  **/
 void
 goo_canvas_request_redraw (GooCanvas             *canvas,
@@ -2224,6 +2588,58 @@ goo_canvas_request_redraw (GooCanvas             *canvas,
 }
 
 
+/**
+ * goo_canvas_request_item_redraw:
+ * @canvas: a #GooCanvas.
+ * @bounds: the bounds of the item to redraw.
+ * @is_static: if the item is static.
+ * 
+ * This function is only intended to be used by subclasses of #GooCanvas or
+ * #GooCanvasItem implementations.
+ *
+ * Requests that the given bounds be redrawn. If @is_static is %TRUE the bounds
+ * are assumed to be in the static item coordinate space, otherwise they are
+ * assumed to be in the canvas coordinate space.
+ *
+ * If @is_static is %FALSE this function behaves the same as
+ * goo_canvas_request_redraw().
+ **/
+void
+goo_canvas_request_item_redraw (GooCanvas             *canvas,
+				const GooCanvasBounds *bounds,
+				gboolean               is_static)
+{
+  if (is_static)
+    request_static_redraw (canvas, bounds);
+  else
+    goo_canvas_request_redraw (canvas, bounds);
+}
+
+
+static void
+paint_static_items (GooCanvas      *canvas,
+		    GdkEventExpose *event,
+		    cairo_t        *cr)
+{
+  GooCanvasPrivate *priv = GOO_CANVAS_GET_PRIVATE (canvas);
+  GooCanvasBounds static_bounds;
+  double static_x_offset, static_y_offset;
+
+  cairo_save (cr);
+  cairo_identity_matrix (cr);
+  static_x_offset = floor (canvas->hadjustment->value);
+  static_y_offset = floor (canvas->vadjustment->value);
+  cairo_translate (cr, static_x_offset, static_y_offset);
+  /* FIXME: Uses pixels at present - use canvas units instead? */
+  static_bounds.x1 = event->area.x - static_x_offset;
+  static_bounds.y1 = event->area.y - static_y_offset;
+  static_bounds.x2 = event->area.width + static_bounds.x1;
+  static_bounds.y2 = event->area.height + static_bounds.y1;
+  goo_canvas_item_paint (priv->static_root_item, cr, &static_bounds, 1.0);
+  cairo_restore (cr);
+}
+
+
 static gboolean
 goo_canvas_expose_event (GtkWidget      *widget,
 			 GdkEventExpose *event)
@@ -2231,6 +2647,7 @@ goo_canvas_expose_event (GtkWidget      *widget,
   GooCanvas *canvas = GOO_CANVAS (widget);
   GooCanvasBounds bounds, root_item_bounds;
   cairo_t *cr;
+  double x1, y1, x2, y2;
 
   if (!canvas->root_item)
     return FALSE;
@@ -2282,17 +2699,26 @@ goo_canvas_expose_event (GtkWidget      *widget,
       || (root_item_bounds.y2 > canvas->bounds.y2
 	  && canvas->bounds.y2 < bounds.y2))
     {
+      /* Clip to the intersection of the canvas bounds and the expose
+	 bounds, to avoid cairo's 16-bit limits. */
+      x1 = MAX (canvas->bounds.x1, bounds.x1);
+      y1 = MAX (canvas->bounds.y1, bounds.y1);
+      x2 = MIN (canvas->bounds.x2, bounds.x2);
+      y2 = MIN (canvas->bounds.y2, bounds.y2);
+
       cairo_new_path (cr);
-      cairo_move_to (cr, canvas->bounds.x1, canvas->bounds.y1);
-      cairo_line_to (cr, canvas->bounds.x2, canvas->bounds.y1);
-      cairo_line_to (cr, canvas->bounds.x2, canvas->bounds.y2);
-      cairo_line_to (cr, canvas->bounds.x1, canvas->bounds.y2);
+      cairo_move_to (cr, x1, y1);
+      cairo_line_to (cr, x2, y1);
+      cairo_line_to (cr, x2, y2);
+      cairo_line_to (cr, x1, y2);
       cairo_close_path (cr);
       cairo_clip (cr);
     }
 
   goo_canvas_item_paint (canvas->root_item, cr, &bounds, canvas->scale);
 
+  paint_static_items (canvas, event, cr);
+
   cairo_destroy (cr);
 
   GTK_WIDGET_CLASS (goo_canvas_parent_class)->expose_event (widget, event);
@@ -2386,6 +2812,15 @@ initialize_crossing_event (GooCanvas *canvas,
       crossing_event->state  = event->crossing.state;
       break;
 
+    case GDK_SCROLL:
+      crossing_event->time   = event->scroll.time;
+      crossing_event->x      = event->scroll.x;
+      crossing_event->y      = event->scroll.y;
+      crossing_event->x_root = event->scroll.x_root;
+      crossing_event->y_root = event->scroll.y_root;
+      crossing_event->state  = event->scroll.state;
+      break;
+
     default:
       /* It must be a button press/release event. */
       crossing_event->time   = event->button.time;
@@ -2501,6 +2936,12 @@ emit_pointer_event (GooCanvas *canvas,
       x_root = &event.crossing.x_root;
       y_root = &event.crossing.y_root;
       break;
+    case GDK_SCROLL:
+      x = &event.scroll.x;
+      y = &event.scroll.y;
+      x_root = &event.scroll.x_root;
+      y_root = &event.scroll.y_root;
+      break;
     default:
       /* It must be a button press/release event. */
       x = &event.button.x;
@@ -2517,6 +2958,10 @@ emit_pointer_event (GooCanvas *canvas,
   /* Convert to the canvas coordinate space. */
   goo_canvas_convert_from_pixels (canvas, x, y);
 
+  /* Convert to static item space, if necessary. */
+  if (target_item && goo_canvas_item_get_is_static (target_item))
+    goo_canvas_convert_to_static_item_space (canvas, x, y);
+
   /* Copy to the x_root & y_root fields. */
   *x_root = *x;
   *y_root = *y;
@@ -2708,6 +3153,14 @@ goo_canvas_scroll	(GtkWidget      *widget,
   GtkAdjustment *adj;
   gdouble delta, new_value;
 
+  if (event->window == canvas->canvas_window)
+    {
+      /* See if the current item wants the scroll event. */
+      update_pointer_item (canvas, (GdkEvent*) event);
+      if (emit_pointer_event (canvas, "scroll_event", (GdkEvent*) event))
+        return TRUE;
+    }
+
   if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_DOWN)
     adj = canvas->vadjustment;
   else
@@ -3132,22 +3585,23 @@ goo_canvas_convert_from_window_pixels (GooCanvas     *canvas,
 }
 
 
-/**
- * goo_canvas_convert_to_item_space:
- * @canvas: a #GooCanvas.
- * @item: a #GooCanvasItem.
- * @x: a pointer to the x coordinate to convert.
- * @y: a pointer to the y coordinate to convert.
- * 
- * Converts a coordinate from the canvas coordinate space to the given
- * item's coordinate space, applying all transformation matrices including the
- * item's own transformation matrix, if it has one.
- **/
-void
-goo_canvas_convert_to_item_space (GooCanvas     *canvas,
-				  GooCanvasItem *item,
-				  gdouble       *x,
-				  gdouble       *y)
+/* Converts from the canvas coordinate space to the static item coordinate
+   space, i.e. in pixels from the top-left of the viewport window. */
+static void
+goo_canvas_convert_to_static_item_space (GooCanvas     *canvas,
+					 gdouble       *x,
+					 gdouble       *y)
+{
+  *x = ((*x - canvas->bounds.x1) * canvas->device_to_pixels_x)
+    + canvas->canvas_x_offset - canvas->hadjustment->value;
+  *y = ((*y - canvas->bounds.y1) * canvas->device_to_pixels_y)
+    + canvas->canvas_y_offset - canvas->vadjustment->value;
+}
+
+
+static void
+get_transform_to_item_space (GooCanvasItem  *item,
+			     cairo_matrix_t *transform)
 {
   GooCanvasItem *tmp = item, *parent, *child;
   GList *list = NULL, *l;
@@ -3176,8 +3630,31 @@ goo_canvas_convert_to_item_space (GooCanvas     *canvas,
     }
   g_list_free (list);
 
-  /* Now convert the coordinates. */
-  cairo_matrix_transform_point (&inverse, x, y);
+  *transform = inverse;
+}
+
+
+/**
+ * goo_canvas_convert_to_item_space:
+ * @canvas: a #GooCanvas.
+ * @item: a #GooCanvasItem.
+ * @x: a pointer to the x coordinate to convert.
+ * @y: a pointer to the y coordinate to convert.
+ * 
+ * Converts a coordinate from the canvas coordinate space to the given
+ * item's coordinate space, applying all transformation matrices including the
+ * item's own transformation matrix, if it has one.
+ **/
+void
+goo_canvas_convert_to_item_space (GooCanvas     *canvas,
+				  GooCanvasItem *item,
+				  gdouble       *x,
+				  gdouble       *y)
+{
+  cairo_matrix_t transform;
+
+  get_transform_to_item_space (item, &transform);
+  cairo_matrix_transform_point (&transform, x, y);
 }
 
 
@@ -3219,7 +3696,7 @@ goo_canvas_convert_from_item_space (GooCanvas     *canvas,
 							       &item_transform);
       if (has_transform)
 	{
-	  cairo_matrix_multiply (&transform, &transform, &item_transform);
+	  cairo_matrix_multiply (&transform, &item_transform, &transform);
 	}
     }
   g_list_free (list);
@@ -3229,6 +3706,56 @@ goo_canvas_convert_from_item_space (GooCanvas     *canvas,
 }
 
 
+/**
+ * goo_canvas_convert_bounds_to_item_space:
+ * @canvas: a #GooCanvas.
+ * @item: a #GooCanvasItem.
+ * @bounds: the bounds in canvas coordinate space, to be converted.
+ * 
+ * Converts the given bounds in the canvas coordinate space to a bounding box
+ * in item space. This is useful in the item paint() methods to convert the
+ * bounds to be painted to the item's coordinate space.
+ **/
+void
+goo_canvas_convert_bounds_to_item_space (GooCanvas           *canvas,
+					 GooCanvasItem       *item,
+					 GooCanvasBounds     *bounds)
+{
+  GooCanvasBounds tmp_bounds = *bounds, tmp_bounds2 = *bounds;
+  cairo_matrix_t transform;
+
+  get_transform_to_item_space (item, &transform);
+
+  /* Convert the top-left and bottom-right corners to device coords. */
+  cairo_matrix_transform_point (&transform, &tmp_bounds.x1, &tmp_bounds.y1);
+  cairo_matrix_transform_point (&transform, &tmp_bounds.x2, &tmp_bounds.y2);
+
+  /* Now convert the top-right and bottom-left corners. */
+  cairo_matrix_transform_point (&transform, &tmp_bounds2.x1, &tmp_bounds2.y2);
+  cairo_matrix_transform_point (&transform, &tmp_bounds2.x2, &tmp_bounds2.y1);
+
+  /* Calculate the minimum x coordinate seen and put in x1. */
+  bounds->x1 = MIN (tmp_bounds.x1, tmp_bounds.x2);
+  bounds->x1 = MIN (bounds->x1, tmp_bounds2.x1);
+  bounds->x1 = MIN (bounds->x1, tmp_bounds2.x2);
+
+  /* Calculate the maximum x coordinate seen and put in x2. */
+  bounds->x2 = MAX (tmp_bounds.x1, tmp_bounds.x2);
+  bounds->x2 = MAX (bounds->x2, tmp_bounds2.x1);
+  bounds->x2 = MAX (bounds->x2, tmp_bounds2.x2);
+
+  /* Calculate the minimum y coordinate seen and put in y1. */
+  bounds->y1 = MIN (tmp_bounds.y1, tmp_bounds.y2);
+  bounds->y1 = MIN (bounds->y1, tmp_bounds2.y1);
+  bounds->y1 = MIN (bounds->y1, tmp_bounds2.y2);
+
+  /* Calculate the maximum y coordinate seen and put in y2. */
+  bounds->y2 = MAX (tmp_bounds.y1, tmp_bounds.y2);
+  bounds->y2 = MAX (bounds->y2, tmp_bounds2.y1);
+  bounds->y2 = MAX (bounds->y2, tmp_bounds2.y2);
+}
+
+
 /*
  * Keyboard focus navigation.
  */
@@ -3796,3 +4323,49 @@ goo_canvas_remove (GtkContainer *container,
 	}
     }
 }
+
+
+static gboolean
+goo_canvas_query_tooltip (GtkWidget  *widget,
+			  gint        x,
+			  gint        y,
+			  gboolean    keyboard_tip,
+			  GtkTooltip *tooltip)
+{
+  GooCanvas *canvas = (GooCanvas*) widget;
+  GooCanvasItem *item = canvas->pointer_item, *parent;
+  gdouble item_x = x, item_y = y;
+  gboolean tip_set = FALSE, has_transform;
+  cairo_matrix_t transform;
+
+  if (!item)
+    return FALSE;
+
+  /* Convert from pixels to the item's coordinate space. */
+  goo_canvas_convert_from_pixels (canvas, &item_x, &item_y);
+  goo_canvas_convert_to_item_space (canvas, item, &item_x, &item_y);
+
+  for (;;)
+    {
+      g_signal_emit_by_name (item, "query-tooltip", item_x, item_y,
+			     keyboard_tip, tooltip, &tip_set);
+      if (tip_set)
+	return TRUE;
+
+      parent = goo_canvas_item_get_parent (item);
+      if (!parent)
+	break;
+
+      /* Convert x & y to the parent's coordinate space. */
+      has_transform = goo_canvas_item_get_transform_for_child (parent, item,
+							       &transform);
+      if (has_transform)
+	cairo_matrix_transform_point (&transform, &item_x, &item_y);
+
+      item = parent;
+    }
+
+  /* We call the parent method in case the canvas itself has a tooltip set. */
+  return GTK_WIDGET_CLASS (goo_canvas_parent_class)->query_tooltip (widget, x, y, keyboard_tip, tooltip);
+}
+
diff --git a/src/goocanvas/src/goocanvas.h b/src/goocanvas/src/goocanvas.h
index 56e38ff..c68b0c2 100644
--- a/src/goocanvas/src/goocanvas.h
+++ b/src/goocanvas/src/goocanvas.h
@@ -10,6 +10,7 @@
 #include <gtk/gtk.h>
 #include <goocanvasenumtypes.h>
 #include <goocanvasellipse.h>
+#include <goocanvasgrid.h>
 #include <goocanvasgroup.h>
 #include <goocanvasimage.h>
 #include <goocanvaspath.h>
@@ -84,6 +85,10 @@ struct _GooCanvas
   /* This is TRUE if the background is cleared before painting the canvas. */
   guint clear_background : 1;
 
+  /* This is TRUE if the canvas is completely redrawn when scrolled. It is
+     useful when there are sticky items to reduce flicker, but is slower. */
+  guint redraw_when_scrolled : 1;
+
   /* This is the padding around the automatic bounds. */
   gdouble bounds_padding;
 
@@ -204,6 +209,14 @@ GooCanvasItemModel* goo_canvas_get_root_item_model (GooCanvas	       *canvas);
 void                goo_canvas_set_root_item_model (GooCanvas	       *canvas,
 						    GooCanvasItemModel *model);
 
+GooCanvasItem*  goo_canvas_get_static_root_item    (GooCanvas		*canvas);
+void            goo_canvas_set_static_root_item    (GooCanvas		*canvas,
+						    GooCanvasItem      *item);
+
+GooCanvasItemModel* goo_canvas_get_static_root_item_model (GooCanvas	       *canvas);
+void                goo_canvas_set_static_root_item_model (GooCanvas	       *canvas,
+							   GooCanvasItemModel *model);
+
 GooCanvasItem*  goo_canvas_get_item	    (GooCanvas		*canvas,
 					     GooCanvasItemModel *model);
 GooCanvasItem*  goo_canvas_get_item_at	    (GooCanvas		*canvas,
@@ -265,6 +278,9 @@ void		goo_canvas_convert_from_item_space (GooCanvas       *canvas,
 						    GooCanvasItem   *item,
 						    gdouble         *x,
 						    gdouble         *y);
+void		goo_canvas_convert_bounds_to_item_space (GooCanvas           *canvas,
+							 GooCanvasItem       *item,
+							 GooCanvasBounds     *bounds);
 
 
 /*
@@ -299,6 +315,9 @@ void		goo_canvas_update	    (GooCanvas		*canvas);
 void		goo_canvas_request_update   (GooCanvas		*canvas);
 void		goo_canvas_request_redraw   (GooCanvas		*canvas,
 					     const GooCanvasBounds *bounds);
+void		goo_canvas_request_item_redraw   (GooCanvas		*canvas,
+						  const GooCanvasBounds *bounds,
+						  gboolean               is_static);
 gdouble         goo_canvas_get_default_line_width (GooCanvas    *canvas);
 
 
diff --git a/src/goocanvas/src/goocanvasatk.c b/src/goocanvas/src/goocanvasatk.c
index f32bb64..5c8c774 100644
--- a/src/goocanvas/src/goocanvasatk.c
+++ b/src/goocanvas/src/goocanvasatk.c
@@ -20,6 +20,7 @@
 typedef AtkGObjectAccessible      GooCanvasItemAccessible;
 typedef AtkGObjectAccessibleClass GooCanvasItemAccessibleClass;
 
+#define GOO_TYPE_CANVAS_ITEM_ACCESSIBLE    (goo_canvas_item_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_accessible_component_interface_init (AtkComponentIface *iface);
@@ -50,15 +51,19 @@ goo_canvas_item_accessible_get_item_extents (GooCanvasItem *item,
   /* Get the bounds in device units. */
   goo_canvas_item_get_bounds (item, &bounds);
 
-  /* Convert to pixels within the entire canvas. */
-  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->hadjustment->value;
-  bounds.y1 -= canvas->vadjustment->value;
-  bounds.x2 -= canvas->hadjustment->value;
-  bounds.y2 -= canvas->vadjustment->value;
+  /* Static items are in pixels so don't need converting. */
+  if (!goo_canvas_item_get_is_static (item))
+    {
+      /* Convert to pixels within the entire canvas. */
+      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->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);
@@ -491,7 +496,7 @@ 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)
+	       GOO_TYPE_CANVAS_ITEM_ACCESSIBLE)
 
 
 static void
@@ -570,7 +575,7 @@ goo_canvas_widget_accessible_init (GooCanvasWidgetAccessible *accessible)
 }
 
 
-AtkObject*
+static AtkObject*
 goo_canvas_widget_accessible_new (GObject *object)
 {
   AtkObject *accessible;
diff --git a/src/goocanvas/src/goocanvasellipse.c b/src/goocanvas/src/goocanvasellipse.c
index 7453a4c..6653f50 100644
--- a/src/goocanvas/src/goocanvasellipse.c
+++ b/src/goocanvas/src/goocanvasellipse.c
@@ -23,6 +23,10 @@
  *
  * To get or set the properties of an existing #GooCanvasEllipse, use
  * g_object_get() and g_object_set().
+ *
+ * The ellipse can be specified either with the "center-x", "center-y",
+ * "radius-x" and "radius-y" properties, or with the "x", "y", "width" and
+ * "height" properties.
  */
 #include <config.h>
 #include <math.h>
@@ -37,7 +41,12 @@ enum {
   PROP_CENTER_X,
   PROP_CENTER_Y,
   PROP_RADIUS_X,
-  PROP_RADIUS_Y
+  PROP_RADIUS_Y,
+
+  PROP_X,
+  PROP_Y,
+  PROP_WIDTH,
+  PROP_HEIGHT
 };
 
 
@@ -92,6 +101,36 @@ goo_canvas_ellipse_install_common_properties (GObjectClass *gobject_class)
 							_("The vertical radius of the ellipse"),
 							0.0, G_MAXDOUBLE, 0.0,
 							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_X,
+				   g_param_spec_double ("x",
+							"X",
+							_("The x coordinate of the left side of the ellipse"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_Y,
+				   g_param_spec_double ("y",
+							"Y",
+							_("The y coordinate of the top of the ellipse"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_WIDTH,
+				   g_param_spec_double ("width",
+							_("Width"),
+							_("The width of the ellipse"),
+							0.0, G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_HEIGHT,
+				   g_param_spec_double ("height",
+							_("Height"),
+							_("The height of the ellipse"),
+							0.0, G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
 }
 
 
@@ -224,6 +263,18 @@ goo_canvas_ellipse_get_common_property (GObject              *object,
     case PROP_RADIUS_Y:
       g_value_set_double (value, ellipse_data->radius_y);
       break;
+    case PROP_X:
+      g_value_set_double (value, ellipse_data->center_x - ellipse_data->radius_x);
+      break;
+    case PROP_Y:
+      g_value_set_double (value, ellipse_data->center_y - ellipse_data->radius_y);
+      break;
+    case PROP_WIDTH:
+      g_value_set_double (value, 2.0 * ellipse_data->radius_x);
+      break;
+    case PROP_HEIGHT:
+      g_value_set_double (value, 2.0 * ellipse_data->radius_y);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -251,19 +302,55 @@ goo_canvas_ellipse_set_common_property (GObject              *object,
 					const GValue         *value,
 					GParamSpec           *pspec)
 {
+  gdouble x, y;
+
   switch (prop_id)
     {
     case PROP_CENTER_X:
       ellipse_data->center_x = g_value_get_double (value);
+      g_object_notify (object, "x");
       break;
     case PROP_CENTER_Y:
       ellipse_data->center_y = g_value_get_double (value);
+      g_object_notify (object, "y");
       break;
     case PROP_RADIUS_X:
       ellipse_data->radius_x = g_value_get_double (value);
+      g_object_notify (object, "width");
       break;
     case PROP_RADIUS_Y:
       ellipse_data->radius_y = g_value_get_double (value);
+      g_object_notify (object, "height");
+      break;
+    case PROP_X:
+      ellipse_data->center_x = g_value_get_double (value) + ellipse_data->radius_x;
+      g_object_notify (object, "center-x");
+      break;
+    case PROP_Y:
+      ellipse_data->center_y = g_value_get_double (value) + ellipse_data->radius_y;
+      g_object_notify (object, "center-y");
+      break;
+    case PROP_WIDTH:
+      /* Calculate the current x coordinate. */
+      x = ellipse_data->center_x - ellipse_data->radius_x;
+      /* Calculate the new radius_x, which is half the width. */
+      ellipse_data->radius_x = g_value_get_double (value) / 2.0;
+      /* Now calculate the new center_x. */
+      ellipse_data->center_x = x + ellipse_data->radius_x;
+
+      g_object_notify (object, "center-x");
+      g_object_notify (object, "radius-x");
+      break;
+    case PROP_HEIGHT:
+      /* Calculate the current y coordinate. */
+      y = ellipse_data->center_y - ellipse_data->radius_y;
+      /* Calculate the new radius_y, which is half the height. */
+      ellipse_data->radius_y = g_value_get_double (value) / 2.0;
+      /* Now calculate the new center_y. */
+      ellipse_data->center_y = y + ellipse_data->radius_y;
+
+      g_object_notify (object, "center-y");
+      g_object_notify (object, "radius-y");
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -356,6 +443,10 @@ canvas_item_interface_init (GooCanvasItemIface *iface)
  * To get or set the properties of an existing #GooCanvasEllipseModel, use
  * g_object_get() and g_object_set().
  *
+ * The ellipse can be specified either with the "center-x", "center-y",
+ * "radius-x" and "radius-y" properties, or with the "x", "y", "width" and
+ * "height" properties.
+ *
  * To respond to events such as mouse clicks on the ellipse you must connect
  * to the signal handlers of the corresponding #GooCanvasEllipse objects.
  * (See goo_canvas_get_item() and #GooCanvas::item-created.)
diff --git a/src/goocanvas/src/goocanvasgrid.c b/src/goocanvas/src/goocanvasgrid.c
new file mode 100644
index 0000000..80190dd
--- /dev/null
+++ b/src/goocanvas/src/goocanvasgrid.c
@@ -0,0 +1,1170 @@
+/*
+ * GooCanvas. Copyright (C) 2005-8 Damon Chaplin.
+ * Released under the GNU LGPL license. See COPYING for details.
+ *
+ * goocanvasgrid.c - a grid item.
+ */
+
+/**
+ * SECTION:goocanvasgrid
+ * @Title: GooCanvasGrid
+ * @Short_Description: a grid item.
+ *
+ * GooCanvasGrid represents a grid item.
+ * A grid consists of a number of equally-spaced horizontal and vertical
+ * grid lines, plus an optional border.
+ *
+ * It is a subclass of #GooCanvasItemSimple and so inherits all of the style
+ * properties such as "stroke-color", "fill-color" and "line-width".
+ *
+ * It also implements the #GooCanvasItem interface, so you can use the
+ * #GooCanvasItem functions such as goo_canvas_item_raise() and
+ * goo_canvas_item_rotate().
+ *
+ * To create a #GooCanvasGrid use goo_canvas_grid_new().
+ *
+ * To get or set the properties of an existing #GooCanvasGrid, use
+ * g_object_get() and g_object_set().
+ *
+ * The grid's position and size is specified with the #GooCanvasGrid:x,
+ * #GooCanvasGrid:y, #GooCanvasGrid:width and #GooCanvasGrid:height properties.
+ *
+ * The #GooCanvasGrid:x-step and #GooCanvasGrid:y-step properties specify the 
+ * distance between grid lines. The  #GooCanvasGrid:x-offset and
+ * #GooCanvasGrid:y-offset properties specify the distance before the first
+ * grid lines.
+ *
+ * The horizontal or vertical grid lines can be hidden using the
+ * #GooCanvasGrid:show-horz-grid-lines and #GooCanvasGrid:show-vert-grid-lines
+ * properties.
+ *
+ * The width of the border can be set using the #GooCanvasGrid:border-width
+ * property. The border is drawn outside the area specified with the
+ * #GooCanvasGrid:x, #GooCanvasGrid:y, #GooCanvasGrid:width and
+ * #GooCanvasGrid:height properties.
+ *
+ * Other properties allow the colors and widths of the grid lines to be set.
+ * The grid line color and width properties override the standard
+ * #GooCanvasItemSimple:stroke-color and #GooCanvasItemSimple:line-width
+ * properties, enabling different styles for horizontal and vertical grid lines.
+ */
+#include <config.h>
+#include <math.h>
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include "goocanvasprivate.h"
+#include "goocanvas.h"
+
+
+enum {
+  PROP_0,
+
+  PROP_X,
+  PROP_Y,
+  PROP_WIDTH,
+  PROP_HEIGHT,
+  PROP_X_STEP,
+  PROP_Y_STEP,
+  PROP_X_OFFSET,
+  PROP_Y_OFFSET,
+  PROP_HORZ_GRID_LINE_WIDTH,
+  PROP_VERT_GRID_LINE_WIDTH,
+  PROP_HORZ_GRID_LINE_PATTERN,
+  PROP_VERT_GRID_LINE_PATTERN,
+  PROP_BORDER_WIDTH,
+  PROP_BORDER_PATTERN,
+  PROP_SHOW_HORZ_GRID_LINES,
+  PROP_SHOW_VERT_GRID_LINES,
+  PROP_VERT_GRID_LINES_ON_TOP,
+
+  /* Convenience properties. */
+  PROP_HORZ_GRID_LINE_COLOR,
+  PROP_HORZ_GRID_LINE_COLOR_RGBA,
+  PROP_HORZ_GRID_LINE_PIXBUF,
+  PROP_VERT_GRID_LINE_COLOR,
+  PROP_VERT_GRID_LINE_COLOR_RGBA,
+  PROP_VERT_GRID_LINE_PIXBUF,
+  PROP_BORDER_COLOR,
+  PROP_BORDER_COLOR_RGBA,
+  PROP_BORDER_PIXBUF
+};
+
+
+GooCanvasItemIface *goo_canvas_grid_parent_iface;
+
+static void canvas_item_interface_init      (GooCanvasItemIface  *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GooCanvasGrid, goo_canvas_grid,
+                         GOO_TYPE_CANVAS_ITEM_SIMPLE,
+			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
+						canvas_item_interface_init))
+
+
+static void
+goo_canvas_grid_install_common_properties (GObjectClass *gobject_class)
+{
+  g_object_class_install_property (gobject_class, PROP_X,
+				   g_param_spec_double ("x",
+							"X",
+							_("The x coordinate of the grid"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_Y,
+				   g_param_spec_double ("y",
+							"Y",
+							_("The y coordinate of the grid"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_WIDTH,
+				   g_param_spec_double ("width",
+							_("Width"),
+							_("The width of the grid"),
+							0.0, G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_HEIGHT,
+				   g_param_spec_double ("height",
+							_("Height"),
+							_("The height of the grid"),
+							0.0, G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_X_STEP,
+				   g_param_spec_double ("x-step",
+							"X Step",
+							_("The distance between the vertical grid lines"),
+							0.0, G_MAXDOUBLE, 10.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_Y_STEP,
+				   g_param_spec_double ("y-step",
+							"Y Step",
+							_("The distance between the horizontal grid lines"),
+							0.0, G_MAXDOUBLE, 10.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_X_OFFSET,
+				   g_param_spec_double ("x-offset",
+							"X Offset",
+							_("The distance before the first vertical grid line"),
+							0.0, G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_Y_OFFSET,
+				   g_param_spec_double ("y-offset",
+							"Y Offset",
+							_("The distance before the first horizontal grid line"),
+							0.0, G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_HORZ_GRID_LINE_WIDTH,
+                                   g_param_spec_double ("horz-grid-line-width",
+                                                        _("Horizontal Grid Line Width"),
+                                                        _("The width of the horizontal grid lines"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, -1.0,
+                                                        G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_VERT_GRID_LINE_WIDTH,
+                                   g_param_spec_double ("vert-grid-line-width",
+							_("Vertical Grid Line Width"),
+							_("The width of the vertical grid lines"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, -1.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_HORZ_GRID_LINE_PATTERN,
+                                   g_param_spec_boxed ("horz-grid-line-pattern",
+						       _("Horizontal Grid Line Pattern"),
+						       _("The cairo pattern to paint the horizontal grid lines with"),
+						       GOO_TYPE_CAIRO_PATTERN,
+						       G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_VERT_GRID_LINE_PATTERN,
+                                   g_param_spec_boxed ("vert-grid-line-pattern",
+						       _("Vertical Grid Line Pattern"),
+						       _("The cairo pattern to paint the vertical grid lines with"),
+						       GOO_TYPE_CAIRO_PATTERN,
+						       G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_BORDER_WIDTH,
+				   g_param_spec_double ("border-width",
+							_("Border Width"),
+							_("The width of the border around the grid"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, -1.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_BORDER_PATTERN,
+                                   g_param_spec_boxed ("border-pattern",
+						       _("Border Pattern"),
+						       _("The cairo pattern to paint the border with"),
+						       GOO_TYPE_CAIRO_PATTERN,
+						       G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_SHOW_HORZ_GRID_LINES,
+                                   g_param_spec_boolean ("show-horz-grid-lines",
+							 _("Show Horizontal Grid Lines"),
+							 _("If the horizontal grid lines are shown"),
+							 TRUE,
+							 G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_SHOW_VERT_GRID_LINES,
+                                   g_param_spec_boolean ("show-vert-grid-lines",
+							 _("Show Vertical Grid Lines"),
+							 _("If the vertical grid lines are shown"),
+							 TRUE,
+							 G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_VERT_GRID_LINES_ON_TOP,
+                                   g_param_spec_boolean ("vert-grid-lines-on-top",
+							 _("Vertical Grid Lines On Top"),
+							 _("If the vertical grid lines are painted above the horizontal grid lines"),
+							 FALSE,
+							 G_PARAM_READWRITE));
+
+
+  /* Convenience properties - some are writable only. */
+  g_object_class_install_property (gobject_class, PROP_HORZ_GRID_LINE_COLOR,
+				   g_param_spec_string ("horz-grid-line-color",
+							_("Horizontal Grid Line Color"),
+							_("The color to use for the horizontal grid lines"),
+							NULL,
+							G_PARAM_WRITABLE));
+
+  g_object_class_install_property (gobject_class, PROP_HORZ_GRID_LINE_COLOR_RGBA,
+				   g_param_spec_uint ("horz-grid-line-color-rgba",
+						      _("Horizontal Grid Line Color RGBA"),
+						      _("The color to use for the horizontal grid lines, specified as a 32-bit integer value"),
+						      0, G_MAXUINT, 0,
+						      G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_HORZ_GRID_LINE_PIXBUF,
+                                   g_param_spec_object ("horz-grid-line-pixbuf",
+							_("Horizontal Grid Line Pixbuf"),
+							_("The pixbuf to use to draw the horizontal grid lines"),
+                                                        GDK_TYPE_PIXBUF,
+                                                        G_PARAM_WRITABLE));
+
+  g_object_class_install_property (gobject_class, PROP_VERT_GRID_LINE_COLOR,
+				   g_param_spec_string ("vert-grid-line-color",
+							_("Vertical Grid Line Color"),
+							_("The color to use for the vertical grid lines"),
+							NULL,
+							G_PARAM_WRITABLE));
+
+  g_object_class_install_property (gobject_class, PROP_VERT_GRID_LINE_COLOR_RGBA,
+				   g_param_spec_uint ("vert-grid-line-color-rgba",
+						      _("Vertical Grid Line Color RGBA"),
+						      _("The color to use for the vertical grid lines, specified as a 32-bit integer value"),
+						      0, G_MAXUINT, 0,
+						      G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_VERT_GRID_LINE_PIXBUF,
+                                   g_param_spec_object ("vert-grid-line-pixbuf",
+							_("Vertical Grid Line Pixbuf"),
+							_("The pixbuf to use to draw the vertical grid lines"),
+                                                        GDK_TYPE_PIXBUF,
+                                                        G_PARAM_WRITABLE));
+
+  g_object_class_install_property (gobject_class, PROP_BORDER_COLOR,
+				   g_param_spec_string ("border-color",
+							_("Border Color"),
+							_("The color to use for the border"),
+							NULL,
+							G_PARAM_WRITABLE));
+
+  g_object_class_install_property (gobject_class, PROP_BORDER_COLOR_RGBA,
+				   g_param_spec_uint ("border-color-rgba",
+						      _("Border Color RGBA"),
+						      _("The color to use for the border, specified as a 32-bit integer value"),
+						      0, G_MAXUINT, 0,
+						      G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_BORDER_PIXBUF,
+                                   g_param_spec_object ("border-pixbuf",
+							_("Border Pixbuf"),
+							_("The pixbuf to use to draw the border"),
+                                                        GDK_TYPE_PIXBUF,
+                                                        G_PARAM_WRITABLE));
+}
+
+
+/* This initializes the common grid data. */
+static void
+goo_canvas_grid_init_data (GooCanvasGridData *grid_data)
+{
+  grid_data->x = 0.0;
+  grid_data->y = 0.0;
+  grid_data->width = 0.0;
+  grid_data->height = 0.0;
+  grid_data->x_step = 10.0;
+  grid_data->y_step = 10.0;
+  grid_data->x_offset = 0.0;
+  grid_data->y_offset = 0.0;
+  grid_data->horz_grid_line_width = -1.0;
+  grid_data->vert_grid_line_width = -1.0;
+  grid_data->horz_grid_line_pattern = NULL;
+  grid_data->vert_grid_line_pattern = NULL;
+  grid_data->border_width = -1.0;
+  grid_data->border_pattern = NULL;
+  grid_data->show_horz_grid_lines = TRUE;
+  grid_data->show_vert_grid_lines = TRUE;
+  grid_data->vert_grid_lines_on_top = FALSE;
+}
+
+
+/* This frees the contents of the grid data, but not the struct itself. */
+static void
+goo_canvas_grid_free_data (GooCanvasGridData *grid_data)
+{
+
+}
+
+
+static void
+goo_canvas_grid_init (GooCanvasGrid *grid)
+{
+  grid->grid_data = g_slice_new0 (GooCanvasGridData);
+  goo_canvas_grid_init_data (grid->grid_data);
+}
+
+
+/**
+ * goo_canvas_grid_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.
+ * @x: the x coordinate of the left of the grid.
+ * @y: the y coordinate of the top of the grid.
+ * @width: the width of the grid.
+ * @height: the height of the grid.
+ * @x_step: the distance between the vertical grid lines.
+ * @y_step: the distance between the horizontal grid lines.
+ * @x_offset: the distance before the first vertical grid line.
+ * @y_offset: the distance before the first horizontal grid line.
+ * @...: optional pairs of property names and values, and a terminating %NULL.
+ * 
+ * Creates a new grid item.
+ *
+ * <!--PARAMETERS-->
+ *
+ * Here's an example showing how to create a grid:
+ *
+ * <informalexample><programlisting>
+ *  GooCanvasItem *grid = goo_canvas_grid_new (mygroup, 100.0, 100.0, 400.0, 200.0,
+ *                                             20.0, 20.0, 10.0, 10.0,
+ *                                             "horz-grid-line-width", 4.0,
+ *                                             "horz-grid-line-color", "yellow",
+ *                                             "vert-grid-line-width", 2.0,
+ *                                             "vert-grid-line-color", "red",
+ *                                             "border-width", 3.0,
+ *                                             "border-color", "white",
+ *                                             "fill-color", "blue",
+ *                                             NULL);
+ * </programlisting></informalexample>
+ * 
+ * Returns: a new grid item.
+ **/
+GooCanvasItem*
+goo_canvas_grid_new (GooCanvasItem      *parent,
+		     gdouble             x,
+		     gdouble             y,
+		     gdouble             width,
+		     gdouble             height,
+		     gdouble             x_step,
+		     gdouble             y_step,
+		     gdouble             x_offset,
+		     gdouble             y_offset,
+		     ...)
+{
+  GooCanvasItem *item;
+  GooCanvasGrid *grid;
+  GooCanvasGridData *grid_data;
+  va_list var_args;
+  const char *first_property;
+
+  item = g_object_new (GOO_TYPE_CANVAS_GRID, NULL);
+  grid = (GooCanvasGrid*) item;
+
+  grid_data = grid->grid_data;
+  grid_data->x = x;
+  grid_data->y = y;
+  grid_data->width = width;
+  grid_data->height = height;
+  grid_data->x_step = x_step;
+  grid_data->y_step = y_step;
+  grid_data->x_offset = x_offset;
+  grid_data->y_offset = y_offset;
+
+  va_start (var_args, y_offset);
+  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);
+    }
+
+  return item;
+}
+
+
+static void
+goo_canvas_grid_finalize (GObject *object)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasGrid *grid = (GooCanvasGrid*) object;
+
+  /* Free our data if we didn't have a model. (If we had a model it would
+     have been reset in dispose() and simple_data will be NULL.) */
+  if (simple->simple_data)
+    {
+      goo_canvas_grid_free_data (grid->grid_data);
+      g_slice_free (GooCanvasGridData, grid->grid_data);
+    }
+  grid->grid_data = NULL;
+
+  G_OBJECT_CLASS (goo_canvas_grid_parent_class)->finalize (object);
+}
+
+
+static void
+goo_canvas_grid_get_common_property (GObject              *object,
+				     GooCanvasGridData    *grid_data,
+				     guint                 prop_id,
+				     GValue               *value,
+				     GParamSpec           *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_X:
+      g_value_set_double (value, grid_data->x);
+      break;
+    case PROP_Y:
+      g_value_set_double (value, grid_data->y);
+      break;
+    case PROP_WIDTH:
+      g_value_set_double (value, grid_data->width);
+      break;
+    case PROP_HEIGHT:
+      g_value_set_double (value, grid_data->height);
+      break;
+    case PROP_X_STEP:
+      g_value_set_double (value, grid_data->x_step);
+      break;
+    case PROP_Y_STEP:
+      g_value_set_double (value, grid_data->y_step);
+      break;
+    case PROP_X_OFFSET:
+      g_value_set_double (value, grid_data->x_offset);
+      break;
+    case PROP_Y_OFFSET:
+      g_value_set_double (value, grid_data->y_offset);
+      break;
+    case PROP_HORZ_GRID_LINE_WIDTH:
+      g_value_set_double (value, grid_data->horz_grid_line_width);
+      break;
+    case PROP_VERT_GRID_LINE_WIDTH:
+      g_value_set_double (value, grid_data->vert_grid_line_width);
+      break;
+    case PROP_HORZ_GRID_LINE_PATTERN:
+      g_value_set_boxed (value, grid_data->horz_grid_line_pattern);
+      break;
+    case PROP_VERT_GRID_LINE_PATTERN:
+      g_value_set_boxed (value, grid_data->vert_grid_line_pattern);
+      break;
+    case PROP_BORDER_WIDTH:
+      g_value_set_double (value, grid_data->border_width);
+      break;
+    case PROP_BORDER_PATTERN:
+      g_value_set_boxed (value, grid_data->border_pattern);
+      break;
+    case PROP_SHOW_HORZ_GRID_LINES:
+      g_value_set_boolean (value, grid_data->show_horz_grid_lines);
+      break;
+    case PROP_SHOW_VERT_GRID_LINES:
+      g_value_set_boolean (value, grid_data->show_vert_grid_lines);
+      break;
+    case PROP_VERT_GRID_LINES_ON_TOP:
+      g_value_set_boolean (value, grid_data->vert_grid_lines_on_top);
+      break;
+
+  /* Convenience properties. */
+    case PROP_HORZ_GRID_LINE_COLOR_RGBA:
+      goo_canvas_get_rgba_value_from_pattern (grid_data->horz_grid_line_pattern, value);
+      break;
+    case PROP_VERT_GRID_LINE_COLOR_RGBA:
+      goo_canvas_get_rgba_value_from_pattern (grid_data->vert_grid_line_pattern, value);
+      break;
+    case PROP_BORDER_COLOR_RGBA:
+      goo_canvas_get_rgba_value_from_pattern (grid_data->border_pattern, value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+static void
+goo_canvas_grid_get_property (GObject              *object,
+			      guint                 prop_id,
+			      GValue               *value,
+			      GParamSpec           *pspec)
+{
+  GooCanvasGrid *grid = (GooCanvasGrid*) object;
+
+  goo_canvas_grid_get_common_property (object, grid->grid_data,
+					  prop_id, value, pspec);
+}
+
+
+static void
+goo_canvas_grid_set_common_property (GObject              *object,
+				     GooCanvasGridData    *grid_data,
+				     guint                 prop_id,
+				     const GValue         *value,
+				     GParamSpec           *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_X:
+      grid_data->x = g_value_get_double (value);
+      break;
+    case PROP_Y:
+      grid_data->y = g_value_get_double (value);
+      break;
+    case PROP_WIDTH:
+      grid_data->width = g_value_get_double (value);
+      break;
+    case PROP_HEIGHT:
+      grid_data->height = g_value_get_double (value);
+      break;
+    case PROP_X_STEP:
+      grid_data->x_step = g_value_get_double (value);
+      break;
+    case PROP_Y_STEP:
+      grid_data->y_step = g_value_get_double (value);
+      break;
+    case PROP_X_OFFSET:
+      grid_data->x_offset = g_value_get_double (value);
+      break;
+    case PROP_Y_OFFSET:
+      grid_data->y_offset = g_value_get_double (value);
+      break;
+    case PROP_HORZ_GRID_LINE_WIDTH:
+      grid_data->horz_grid_line_width = g_value_get_double (value);
+      break;
+    case PROP_VERT_GRID_LINE_WIDTH:
+      grid_data->vert_grid_line_width = g_value_get_double (value);
+      break;
+    case PROP_HORZ_GRID_LINE_PATTERN:
+      cairo_pattern_destroy (grid_data->horz_grid_line_pattern);
+      grid_data->horz_grid_line_pattern = g_value_get_boxed (value);
+      cairo_pattern_reference (grid_data->horz_grid_line_pattern);
+      break;
+    case PROP_VERT_GRID_LINE_PATTERN:
+      cairo_pattern_destroy (grid_data->vert_grid_line_pattern);
+      grid_data->vert_grid_line_pattern = g_value_get_boxed (value);
+      cairo_pattern_reference (grid_data->vert_grid_line_pattern);
+      break;
+    case PROP_BORDER_WIDTH:
+      grid_data->border_width = g_value_get_double (value);
+      break;
+    case PROP_BORDER_PATTERN:
+      cairo_pattern_destroy (grid_data->border_pattern);
+      grid_data->border_pattern = g_value_get_boxed (value);
+      cairo_pattern_reference (grid_data->border_pattern);
+      break;
+    case PROP_SHOW_HORZ_GRID_LINES:
+      grid_data->show_horz_grid_lines = g_value_get_boolean (value);
+      break;
+    case PROP_SHOW_VERT_GRID_LINES:
+      grid_data->show_vert_grid_lines = g_value_get_boolean (value);
+      break;
+    case PROP_VERT_GRID_LINES_ON_TOP:
+      grid_data->vert_grid_lines_on_top = g_value_get_boolean (value);
+      break;
+
+  /* Convenience properties. */
+    case PROP_HORZ_GRID_LINE_COLOR:
+      cairo_pattern_destroy (grid_data->horz_grid_line_pattern);
+      grid_data->horz_grid_line_pattern = goo_canvas_create_pattern_from_color_value (value);
+      break;
+    case PROP_HORZ_GRID_LINE_COLOR_RGBA:
+      cairo_pattern_destroy (grid_data->horz_grid_line_pattern);
+      grid_data->horz_grid_line_pattern = goo_canvas_create_pattern_from_rgba_value (value);
+      break;
+    case PROP_HORZ_GRID_LINE_PIXBUF:
+      cairo_pattern_destroy (grid_data->horz_grid_line_pattern);
+      grid_data->horz_grid_line_pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
+      break;
+
+    case PROP_VERT_GRID_LINE_COLOR:
+      cairo_pattern_destroy (grid_data->vert_grid_line_pattern);
+      grid_data->vert_grid_line_pattern = goo_canvas_create_pattern_from_color_value (value);
+      break;
+    case PROP_VERT_GRID_LINE_COLOR_RGBA:
+      cairo_pattern_destroy (grid_data->vert_grid_line_pattern);
+      grid_data->vert_grid_line_pattern = goo_canvas_create_pattern_from_rgba_value (value);
+      break;
+    case PROP_VERT_GRID_LINE_PIXBUF:
+      cairo_pattern_destroy (grid_data->vert_grid_line_pattern);
+      grid_data->vert_grid_line_pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
+      break;
+
+    case PROP_BORDER_COLOR:
+      cairo_pattern_destroy (grid_data->border_pattern);
+      grid_data->border_pattern = goo_canvas_create_pattern_from_color_value (value);
+      break;
+    case PROP_BORDER_COLOR_RGBA:
+      cairo_pattern_destroy (grid_data->border_pattern);
+      grid_data->border_pattern = goo_canvas_create_pattern_from_rgba_value (value);
+      break;
+    case PROP_BORDER_PIXBUF:
+      cairo_pattern_destroy (grid_data->border_pattern);
+      grid_data->border_pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+
+static void
+goo_canvas_grid_set_property (GObject              *object,
+			      guint                 prop_id,
+			      const GValue         *value,
+			      GParamSpec           *pspec)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasGrid *grid = (GooCanvasGrid*) 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_grid_set_common_property (object, grid->grid_data,
+					  prop_id, value, pspec);
+  goo_canvas_item_simple_changed (simple, TRUE);
+}
+
+
+static void
+goo_canvas_grid_update  (GooCanvasItemSimple *simple,
+			 cairo_t             *cr)
+{
+  GooCanvasGrid *grid = (GooCanvasGrid*) simple;
+  GooCanvasGridData *grid_data = grid->grid_data;
+  gdouble border_width = 0.0;
+
+  /* We can quickly compute the bounds as being just the grid's size
+     plus the border width around each edge. */
+  if (grid_data->border_width > 0.0)
+    border_width = grid_data->border_width;
+
+  simple->bounds.x1 = grid_data->x - border_width;
+  simple->bounds.y1 = grid_data->y - border_width;
+  simple->bounds.x2 = grid_data->x + grid_data->width + border_width;
+  simple->bounds.y2 = grid_data->y + grid_data->height + border_width;
+}
+
+
+static gdouble
+calculate_start_position (gdouble start_pos,
+			  gdouble step,
+			  gdouble redraw_start_pos,
+			  gdouble line_width)
+{
+  gdouble n = 0.0, result;
+
+  /* We want the first position where pos + line_width/2 >= redraw_start_pos.
+     i.e. start_pos + (n * step) + (line_width / 2) >= redraw_start_pos,
+     or   (n * step) >= redraw_start_pos - start_pos - (line_width / 2),
+     or   n >= (redraw_start_pos - start_pos - (line_width / 2) / step). */
+  if (step > 0.0)
+    n = ceil (((redraw_start_pos - start_pos - (line_width / 2.0))) / step);
+
+  if (n <= 0.0)
+    result = start_pos;
+  else
+    result = start_pos + (n * step);
+
+  return result;
+}
+
+
+static void
+paint_vertical_lines (GooCanvasItemSimple   *simple,
+		      cairo_t               *cr,
+		      const GooCanvasBounds *bounds)
+{
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasGrid *grid = (GooCanvasGrid*) simple;
+  GooCanvasGridData *grid_data = grid->grid_data;
+  double x, max_x, max_y, max_bounds_x, line_width;
+  gboolean has_stroke;
+
+  if (!grid_data->show_vert_grid_lines)
+    return;
+
+  max_x = grid_data->x + grid_data->width;
+  max_y = grid_data->y + grid_data->height;
+
+  has_stroke = goo_canvas_style_set_stroke_options (simple_data->style, cr);
+  line_width = goo_canvas_item_simple_get_line_width (simple);
+
+  /* If the grid's vertical grid line pattern/color has been set, use that.
+     If not, and we don't have a stroke color just return. */
+  if (grid_data->vert_grid_line_pattern)
+    cairo_set_source (cr, grid_data->vert_grid_line_pattern);
+  else if (!has_stroke)
+    return;
+
+  /* If the grid's vertical grid line width has been set, use that. */
+  if (grid_data->vert_grid_line_width > 0.0)
+    {
+      line_width = grid_data->vert_grid_line_width;
+      cairo_set_line_width (cr, line_width);
+    }
+
+  cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+
+  /* Calculate the first grid line that intersects the bounds to redraw. */
+  x = calculate_start_position (grid_data->x + grid_data->x_offset,
+				grid_data->x_step, bounds->x1, line_width);
+
+  /* Calculate the last possible line position. */
+  max_bounds_x = bounds->x2 + (line_width / 2.0);
+  max_x = MIN (max_x, max_bounds_x);
+
+  /* Add on a tiny fraction of step to avoid any double comparison issues. */
+  max_x += grid_data->x_step * 0.00001;
+
+  while (x <= max_x)
+    {
+      cairo_move_to (cr, x, grid_data->y);
+      cairo_line_to (cr, x, max_y);
+      cairo_stroke (cr);
+
+      /* Avoid an infinite loop. */
+      if (grid_data->x_step <= 0.0)
+        break;
+
+      x += grid_data->x_step;
+    }
+}
+
+
+static void
+paint_horizontal_lines (GooCanvasItemSimple   *simple,
+			cairo_t               *cr,
+			const GooCanvasBounds *bounds)
+{
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasGrid *grid = (GooCanvasGrid*) simple;
+  GooCanvasGridData *grid_data = grid->grid_data;
+  double y, max_x, max_y, max_bounds_y, line_width;
+  gboolean has_stroke;
+
+  if (!grid_data->show_horz_grid_lines)
+    return;
+
+  max_x = grid_data->x + grid_data->width;
+  max_y = grid_data->y + grid_data->height;
+
+  has_stroke = goo_canvas_style_set_stroke_options (simple_data->style, cr);
+  line_width = goo_canvas_item_simple_get_line_width (simple);
+
+  /* If the grid's horizontal grid line pattern/color has been set, use that.
+     If not, and we don't have a stroke color just return. */
+  if (grid_data->horz_grid_line_pattern)
+    cairo_set_source (cr, grid_data->horz_grid_line_pattern);
+  else if (!has_stroke)
+    return;
+
+  /* If the grid's horizontal grid line width has been set, use that. */
+  if (grid_data->horz_grid_line_width > 0.0)
+    {
+      line_width = grid_data->horz_grid_line_width;
+      cairo_set_line_width (cr, grid_data->horz_grid_line_width);
+    }
+
+  cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+
+  /* Calculate the first grid line that intersects the bounds to redraw. */
+  y = calculate_start_position (grid_data->y + grid_data->y_offset,
+				grid_data->y_step, bounds->y1, line_width);
+
+  /* Calculate the last possible line position. */
+  max_bounds_y = bounds->y2 + (line_width / 2.0);
+  max_y = MIN (max_y, max_bounds_y);
+
+  /* Add on a tiny fraction of step to avoid any double comparison issues. */
+  max_y += grid_data->y_step * 0.00001;
+
+  while (y <= max_y)
+    {
+      cairo_move_to (cr, grid_data->x, y);
+      cairo_line_to (cr, max_x, y);
+      cairo_stroke (cr);
+
+      /* Avoid an infinite loop. */
+      if (grid_data->y_step <= 0.0)
+        break;
+
+      y += grid_data->y_step;
+    }
+}
+
+
+static void
+goo_canvas_grid_paint (GooCanvasItemSimple   *simple,
+		       cairo_t               *cr,
+		       const GooCanvasBounds *bounds)
+{
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasGrid *grid = (GooCanvasGrid*) simple;
+  GooCanvasGridData *grid_data = grid->grid_data;
+  GooCanvasBounds redraw_bounds = *bounds;
+  gdouble half_border_width;
+
+  /* Paint the background in the fill pattern/color, if one is set. */
+  if (goo_canvas_style_set_fill_options (simple_data->style, cr))
+    {
+      cairo_rectangle (cr, grid_data->x, grid_data->y,
+		       grid_data->width, grid_data->height);
+      cairo_fill (cr);
+    }
+
+  /* Clip to the grid's area while painting the grid lines. */
+  cairo_save (cr);
+  cairo_rectangle (cr, grid_data->x, grid_data->y,
+		   grid_data->width, grid_data->height);
+  cairo_clip (cr);
+
+  /* Convert the bounds to be redrawn from device space to item space. */
+  goo_canvas_convert_bounds_to_item_space (simple->canvas,
+					   (GooCanvasItem*) simple,
+					   &redraw_bounds);
+
+  /* Paint the grid lines, in the required order. */
+  if (grid_data->vert_grid_lines_on_top)
+    {
+      paint_horizontal_lines (simple, cr, &redraw_bounds);
+      paint_vertical_lines (simple, cr, &redraw_bounds);
+    }
+  else
+    {
+      paint_vertical_lines (simple, cr, &redraw_bounds);
+      paint_horizontal_lines (simple, cr, &redraw_bounds);
+    }
+
+  cairo_restore (cr);
+
+  /* Paint the border. */
+  if (grid_data->border_width > 0)
+    {
+      if (grid_data->border_pattern)
+	cairo_set_source (cr, grid_data->border_pattern);
+      else
+	goo_canvas_style_set_stroke_options (simple_data->style, cr);
+
+      cairo_set_line_width (cr, grid_data->border_width);
+      half_border_width = grid_data->border_width / 2.0;
+      cairo_rectangle (cr, grid_data->x - half_border_width,
+		       grid_data->y - half_border_width,
+		       grid_data->width + grid_data->border_width,
+		       grid_data->height + grid_data->border_width);
+      cairo_stroke (cr);
+    }
+}
+
+
+static void
+goo_canvas_grid_set_model    (GooCanvasItem      *item,
+			      GooCanvasItemModel *model)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasGrid *grid = (GooCanvasGrid*) item;
+  GooCanvasGridModel *gmodel = (GooCanvasGridModel*) model;
+
+  /* If our grid_data was allocated, free it. */
+  if (!simple->model)
+    {
+      goo_canvas_grid_free_data (grid->grid_data);
+      g_slice_free (GooCanvasGridData, grid->grid_data);
+    }
+
+  /* Now use the new model's grid_data instead. */
+  grid->grid_data = &gmodel->grid_data;
+
+  /* Let the parent class do the rest. */
+  goo_canvas_grid_parent_iface->set_model (item, model);
+}
+
+
+static void
+canvas_item_interface_init (GooCanvasItemIface *iface)
+{
+  iface->set_model      = goo_canvas_grid_set_model;
+}
+
+
+static void
+goo_canvas_grid_class_init (GooCanvasGridClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+  GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) klass;
+
+  goo_canvas_grid_parent_iface = g_type_interface_peek (goo_canvas_grid_parent_class, GOO_TYPE_CANVAS_ITEM);
+
+  gobject_class->finalize    = goo_canvas_grid_finalize;
+
+  gobject_class->get_property = goo_canvas_grid_get_property;
+  gobject_class->set_property = goo_canvas_grid_set_property;
+
+  simple_class->simple_update      = goo_canvas_grid_update;
+  simple_class->simple_paint       = goo_canvas_grid_paint;
+
+  goo_canvas_grid_install_common_properties (gobject_class);
+}
+
+
+
+/**
+ * SECTION:goocanvasgridmodel
+ * @Title: GooCanvasGridModel
+ * @Short_Description: a model for grid items.
+ *
+ * GooCanvasGridModel represents a model for grid items.
+ * A grid consists of a number of equally-spaced horizontal and vertical
+ * grid lines, plus an optional border.
+ *
+ * It is a subclass of #GooCanvasItemModelSimple and so inherits all of the
+ * style properties such as "stroke-color", "fill-color" and "line-width".
+ *
+ * It also implements the #GooCanvasItemModel interface, so you can use the
+ * #GooCanvasItemModel functions such as goo_canvas_item_model_raise() and
+ * goo_canvas_item_model_rotate().
+ *
+ * To create a #GooCanvasGridModel use goo_canvas_grid_model_new().
+ *
+ * To get or set the properties of an existing #GooCanvasGridModel, use
+ * g_object_get() and g_object_set().
+ *
+ * To respond to events such as mouse clicks on the grid you must connect
+ * to the signal handlers of the corresponding #GooCanvasGrid objects.
+ * (See goo_canvas_get_item() and #GooCanvas::item-created.)
+ *
+ * The grid's position and size is specified with the #GooCanvasGridModel:x,
+ * #GooCanvasGridModel:y, #GooCanvasGridModel:width and
+ * #GooCanvasGridModel:height properties.
+ *
+ * The #GooCanvasGridModel:x-step and #GooCanvasGridModel:y-step properties
+ * specify the distance between grid lines. The  #GooCanvasGridModel:x-offset
+ * and #GooCanvasGridModel:y-offset properties specify the distance before the
+ * first grid lines.
+ *
+ * The horizontal or vertical grid lines can be hidden using the
+ * #GooCanvasGridModel:show-horz-grid-lines and
+ * #GooCanvasGridModel:show-vert-grid-lines properties.
+ *
+ * The width of the border can be set using the #GooCanvasGridModel:border-width
+ * property. The border is drawn outside the area specified with the
+ * #GooCanvasGridModel:x, #GooCanvasGridModel:y, #GooCanvasGridModel:width and
+ * #GooCanvasGridModel:height properties.
+ *
+ * Other properties allow the colors and widths of the grid lines to be set.
+ * The grid line color and width properties override the standard
+ * #GooCanvasItemModelSimple:stroke-color and
+ * #GooCanvasItemModelSimple:line-width properties, enabling different styles
+ * for horizontal and vertical grid lines.
+ */
+
+GooCanvasItemModelIface *goo_canvas_grid_model_parent_iface;
+
+static void item_model_interface_init (GooCanvasItemModelIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GooCanvasGridModel, goo_canvas_grid_model,
+                         GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE,
+			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM_MODEL,
+						item_model_interface_init))
+
+
+static void
+goo_canvas_grid_model_init (GooCanvasGridModel *gmodel)
+{
+  goo_canvas_grid_init_data (&gmodel->grid_data);
+}
+
+
+/**
+ * goo_canvas_grid_model_new:
+ * @parent: the parent model, 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.
+ * @x: the x coordinate of the left of the grid.
+ * @y: the y coordinate of the top of the grid.
+ * @width: the width of the grid.
+ * @height: the height of the grid.
+ * @x_step: the distance between the vertical grid lines.
+ * @y_step: the distance between the horizontal grid lines.
+ * @x_offset: the distance before the first vertical grid line.
+ * @y_offset: the distance before the first horizontal grid line.
+ * @...: optional pairs of property names and values, and a terminating %NULL.
+ * 
+ * Creates a new grid model.
+ *
+ * <!--PARAMETERS-->
+ *
+ * Here's an example showing how to create a grid:
+ *
+ * <informalexample><programlisting>
+ *  GooCanvasItemModel *grid = goo_canvas_grid_model_new (mygroup, 100.0, 100.0, 400.0, 200.0,
+ *                                                        20.0, 20.0, 10.0, 10.0,
+ *                                                        "horz-grid-line-width", 4.0,
+ *                                                        "horz-grid-line-color", "yellow",
+ *                                                        "vert-grid-line-width", 2.0,
+ *                                                        "vert-grid-line-color", "red",
+ *                                                        "border-width", 3.0,
+ *                                                        "border-color", "white",
+ *                                                        "fill-color", "blue",
+ *                                                        NULL);
+ * </programlisting></informalexample>
+ * 
+ * Returns: a new grid model.
+ **/
+GooCanvasItemModel*
+goo_canvas_grid_model_new (GooCanvasItemModel *parent,
+			   gdouble             x,
+			   gdouble             y,
+			   gdouble             width,
+			   gdouble             height,
+			   gdouble             x_step,
+			   gdouble             y_step,
+			   gdouble             x_offset,
+			   gdouble             y_offset,
+			   ...)
+{
+  GooCanvasItemModel *model;
+  GooCanvasGridModel *gmodel;
+  GooCanvasGridData *grid_data;
+  const char *first_property;
+  va_list var_args;
+
+  model = g_object_new (GOO_TYPE_CANVAS_GRID_MODEL, NULL);
+  gmodel = (GooCanvasGridModel*) model;
+
+  grid_data = &gmodel->grid_data;
+  grid_data->x = x;
+  grid_data->y = y;
+  grid_data->width = width;
+  grid_data->height = height;
+  grid_data->x_step = x_step;
+  grid_data->y_step = y_step;
+  grid_data->x_offset = x_offset;
+  grid_data->y_offset = y_offset;
+
+  va_start (var_args, y_offset);
+  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_grid_model_finalize (GObject *object)
+{
+  GooCanvasGridModel *gmodel = (GooCanvasGridModel*) object;
+
+  goo_canvas_grid_free_data (&gmodel->grid_data);
+
+  G_OBJECT_CLASS (goo_canvas_grid_model_parent_class)->finalize (object);
+}
+
+
+static void
+goo_canvas_grid_model_get_property (GObject              *object,
+				    guint                 prop_id,
+				    GValue               *value,
+				    GParamSpec           *pspec)
+{
+  GooCanvasGridModel *gmodel = (GooCanvasGridModel*) object;
+
+  goo_canvas_grid_get_common_property (object, &gmodel->grid_data,
+					  prop_id, value, pspec);
+}
+
+
+static void
+goo_canvas_grid_model_set_property (GObject              *object,
+				    guint                 prop_id,
+				    const GValue         *value,
+				    GParamSpec           *pspec)
+{
+  GooCanvasGridModel *gmodel = (GooCanvasGridModel*) object;
+
+  goo_canvas_grid_set_common_property (object, &gmodel->grid_data,
+					  prop_id, value, pspec);
+  g_signal_emit_by_name (gmodel, "changed", TRUE);
+}
+
+
+static GooCanvasItem*
+goo_canvas_grid_model_create_item (GooCanvasItemModel *model,
+				   GooCanvas          *canvas)
+{
+  GooCanvasItem *item;
+
+  item = g_object_new (GOO_TYPE_CANVAS_GRID, NULL);
+  goo_canvas_item_set_model (item, model);
+
+  return item;
+}
+
+
+static void
+item_model_interface_init (GooCanvasItemModelIface *iface)
+{
+  iface->create_item    = goo_canvas_grid_model_create_item;
+}
+
+
+static void
+goo_canvas_grid_model_class_init (GooCanvasGridModelClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+
+  goo_canvas_grid_model_parent_iface = g_type_interface_peek (goo_canvas_grid_model_parent_class, GOO_TYPE_CANVAS_ITEM_MODEL);
+
+  gobject_class->finalize     = goo_canvas_grid_model_finalize;
+
+  gobject_class->get_property = goo_canvas_grid_model_get_property;
+  gobject_class->set_property = goo_canvas_grid_model_set_property;
+
+  goo_canvas_grid_install_common_properties (gobject_class);
+}
+
+
diff --git a/src/goocanvas/src/goocanvasgrid.h b/src/goocanvas/src/goocanvasgrid.h
new file mode 100644
index 0000000..fa70e2e
--- /dev/null
+++ b/src/goocanvas/src/goocanvasgrid.h
@@ -0,0 +1,153 @@
+/*
+ * GooCanvas. Copyright (C) 2005-8 Damon Chaplin.
+ * Released under the GNU LGPL license. See COPYING for details.
+ *
+ * goocanvasgrid.h - a grid item.
+ */
+#ifndef __GOO_CANVAS_GRID_H__
+#define __GOO_CANVAS_GRID_H__
+
+#include <gtk/gtk.h>
+#include "goocanvasitemsimple.h"
+
+G_BEGIN_DECLS
+
+
+/* This is the data used by both model and view classes. */
+typedef struct _GooCanvasGridData   GooCanvasGridData;
+struct _GooCanvasGridData
+{
+  /* The area that the grid covers. */
+  gdouble x, y, width, height;
+
+  /* The distance between grid lines. */
+  gdouble x_step, y_step;
+
+  /* The offset before the first grid line. */
+  gdouble x_offset, y_offset;
+
+  /* The widths of the grid lines, or -ve to use item's stroke width. */
+  gdouble horz_grid_line_width, vert_grid_line_width;
+
+  /* The color/pattern for the grid lines, or NULL to use the stroke color. */
+  cairo_pattern_t *horz_grid_line_pattern, *vert_grid_line_pattern;
+
+  /* The width of the border around the grid, or -1 for no border. */
+  gdouble border_width;
+
+  /* The color/pattern for the border, or NULL to use the stroke color. */
+  cairo_pattern_t *border_pattern;
+
+  /* If the horizontal and vertical grid lines should be shown. */
+  guint show_horz_grid_lines : 1;
+  guint show_vert_grid_lines : 1;
+
+  /* If vertical grid lines are drawn on top. */
+  guint vert_grid_lines_on_top : 1;
+};
+
+
+#define GOO_TYPE_CANVAS_GRID            (goo_canvas_grid_get_type ())
+#define GOO_CANVAS_GRID(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_GRID, GooCanvasGrid))
+#define GOO_CANVAS_GRID_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_GRID, GooCanvasGridClass))
+#define GOO_IS_CANVAS_GRID(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_GRID))
+#define GOO_IS_CANVAS_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_GRID))
+#define GOO_CANVAS_GRID_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_GRID, GooCanvasGridClass))
+
+
+typedef struct _GooCanvasGrid       GooCanvasGrid;
+typedef struct _GooCanvasGridClass  GooCanvasGridClass;
+
+/**
+ * GooCanvasGrid
+ *
+ * The #GooCanvasGrid-struct struct contains private data only.
+ */
+struct _GooCanvasGrid
+{
+  GooCanvasItemSimple parent_object;
+
+  GooCanvasGridData *grid_data;
+};
+
+struct _GooCanvasGridClass
+{
+  GooCanvasItemSimpleClass parent_class;
+
+  /*< private >*/
+
+  /* Padding for future expansion */
+  void (*_goo_canvas_reserved1) (void);
+  void (*_goo_canvas_reserved2) (void);
+  void (*_goo_canvas_reserved3) (void);
+  void (*_goo_canvas_reserved4) (void);
+};
+
+
+GType          goo_canvas_grid_get_type      (void) G_GNUC_CONST;
+GooCanvasItem* goo_canvas_grid_new           (GooCanvasItem      *parent,
+					      gdouble             x,
+					      gdouble             y,
+					      gdouble             width,
+					      gdouble             height,
+					      gdouble             x_step,
+					      gdouble             y_step,
+					      gdouble             x_offset,
+					      gdouble             y_offset,
+					      ...);
+
+
+
+#define GOO_TYPE_CANVAS_GRID_MODEL            (goo_canvas_grid_model_get_type ())
+#define GOO_CANVAS_GRID_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_GRID_MODEL, GooCanvasGridModel))
+#define GOO_CANVAS_GRID_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_GRID_MODEL, GooCanvasGridModelClass))
+#define GOO_IS_CANVAS_GRID_MODEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_GRID_MODEL))
+#define GOO_IS_CANVAS_GRID_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_CANVAS_GRID_MODEL))
+#define GOO_CANVAS_GRID_MODEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_CANVAS_GRID_MODEL, GooCanvasGridModelClass))
+
+
+typedef struct _GooCanvasGridModel       GooCanvasGridModel;
+typedef struct _GooCanvasGridModelClass  GooCanvasGridModelClass;
+
+/**
+ * GooCanvasGridModel
+ *
+ * The #GooCanvasGridModel-struct struct contains private data only.
+ */
+struct _GooCanvasGridModel
+{
+  GooCanvasItemModelSimple parent_object;
+
+  GooCanvasGridData grid_data;
+};
+
+struct _GooCanvasGridModelClass
+{
+  GooCanvasItemModelSimpleClass parent_class;
+
+  /*< private >*/
+
+  /* Padding for future expansion */
+  void (*_goo_canvas_reserved1) (void);
+  void (*_goo_canvas_reserved2) (void);
+  void (*_goo_canvas_reserved3) (void);
+  void (*_goo_canvas_reserved4) (void);
+};
+
+
+GType               goo_canvas_grid_model_get_type (void) G_GNUC_CONST;
+GooCanvasItemModel* goo_canvas_grid_model_new      (GooCanvasItemModel *parent,
+						    gdouble             x,
+						    gdouble             y,
+						    gdouble             width,
+						    gdouble             height,
+						    gdouble             x_step,
+						    gdouble             y_step,
+						    gdouble             x_offset,
+						    gdouble             y_offset,
+						    ...);
+
+
+G_END_DECLS
+
+#endif /* __GOO_CANVAS_GRID_H__ */
diff --git a/src/goocanvas/src/goocanvasgroup.c b/src/goocanvas/src/goocanvasgroup.c
index c668fb3..0f709ac 100644
--- a/src/goocanvas/src/goocanvasgroup.c
+++ b/src/goocanvas/src/goocanvasgroup.c
@@ -25,6 +25,9 @@
  * goo_canvas_item_rotate(), and the properties such as "visibility" and
  * "pointer-events".
  *
+ * If the #GooCanvasGroup:width and #GooCanvasGroup:height properties are
+ * set to positive values then the group is clipped to the given size.
+ *
  * To create a #GooCanvasGroup use goo_canvas_group_new().
  *
  * To get or set the properties of an existing #GooCanvasGroup, use
@@ -40,9 +43,38 @@
 #include "goocanvasmarshal.h"
 #include "goocanvasatk.h"
 
+typedef struct _GooCanvasGroupPrivate GooCanvasGroupPrivate;
+struct _GooCanvasGroupPrivate {
+  gdouble x;
+  gdouble y;
+  gdouble width;
+  gdouble height;
+};
+
+#define GOO_CANVAS_GROUP_GET_PRIVATE(group)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((group), GOO_TYPE_CANVAS_GROUP, GooCanvasGroupPrivate))
+#define GOO_CANVAS_GROUP_MODEL_GET_PRIVATE(group)  \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((group), GOO_TYPE_CANVAS_GROUP_MODEL, GooCanvasGroupPrivate))
+
+enum {
+  PROP_0,
+
+  PROP_X,
+  PROP_Y,
+  PROP_WIDTH,
+  PROP_HEIGHT
+};
 
 static void goo_canvas_group_dispose	  (GObject            *object);
 static void goo_canvas_group_finalize     (GObject            *object);
+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 canvas_item_interface_init    (GooCanvasItemIface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (GooCanvasGroup, goo_canvas_group,
@@ -50,14 +82,53 @@ G_DEFINE_TYPE_WITH_CODE (GooCanvasGroup, goo_canvas_group,
 			 G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
 						canvas_item_interface_init))
 
+static void
+goo_canvas_group_install_common_properties (GObjectClass *gobject_class)
+{
+  g_object_class_install_property (gobject_class, PROP_X,
+                                  g_param_spec_double ("x",
+                                                       "X",
+                                                       _("The x coordinate of the group"),
+                                                       -G_MAXDOUBLE,
+                                                       G_MAXDOUBLE, 0.0,
+                                                       G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_Y,
+                                  g_param_spec_double ("y",
+                                                       "Y",
+                                                       _("The y coordinate of the group"),
+                                                       -G_MAXDOUBLE,
+                                                       G_MAXDOUBLE, 0.0,
+                                                       G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_WIDTH,
+                                  g_param_spec_double ("width",
+                                                       _("Width"),
+                                                       _("The width of the group, or -1 to use the default width"),
+                                                       -G_MAXDOUBLE,
+                                                       G_MAXDOUBLE, -1.0,
+                                                       G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_HEIGHT,
+                                  g_param_spec_double ("height",
+                                                       _("Height"),
+                                                       _("The height of the group, or -1 to use the default height"),
+                                                       -G_MAXDOUBLE,
+                                                       G_MAXDOUBLE, -1.0,
+                                                       G_PARAM_READWRITE));
+}
 
 static void
 goo_canvas_group_class_init (GooCanvasGroupClass *klass)
 {
   GObjectClass *gobject_class = (GObjectClass*) klass;
 
+  g_type_class_add_private (gobject_class, sizeof (GooCanvasGroupPrivate));
+
   gobject_class->dispose  = goo_canvas_group_dispose;
   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;
 
   /* 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)))
@@ -66,13 +137,22 @@ goo_canvas_group_class_init (GooCanvasGroupClass *klass)
 				     GOO_TYPE_CANVAS_GROUP,
 				     goo_canvas_item_accessible_factory_get_type ());
     }
+
+  goo_canvas_group_install_common_properties (gobject_class);
 }
 
 
 static void
 goo_canvas_group_init (GooCanvasGroup *group)
 {
+  GooCanvasGroupPrivate* priv = GOO_CANVAS_GROUP_GET_PRIVATE (group);
+
   group->items = g_ptr_array_sized_new (8);
+
+  priv->x = 0.0;
+  priv->y = 0.0;
+  priv->width = -1.0;
+  priv->height = -1.0;
 }
 
 
@@ -146,12 +226,113 @@ goo_canvas_group_finalize (GObject *object)
 }
 
 
+/* Gets the private data to use, from the model or from the item itself. */
+static GooCanvasGroupPrivate*
+goo_canvas_group_get_private (GooCanvasGroup *group)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) group;
+
+  if (simple->model)
+    return GOO_CANVAS_GROUP_MODEL_GET_PRIVATE (simple->model);
+  else
+    return GOO_CANVAS_GROUP_GET_PRIVATE (group);
+}
+
+
+static void
+goo_canvas_group_get_common_property (GObject               *object,
+                                      GooCanvasGroupPrivate *priv,
+                                      guint                  prop_id,
+                                      GValue                *value,
+                                      GParamSpec            *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_X:
+      g_value_set_double (value, priv->x);
+      break;
+    case PROP_Y:
+      g_value_set_double (value, priv->y);
+      break;
+    case PROP_WIDTH:
+      g_value_set_double (value, priv->width);
+      break;
+    case PROP_HEIGHT:
+      g_value_set_double (value, priv->height);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+goo_canvas_group_get_property (GObject               *object,
+                               guint                  prop_id,
+                               GValue                *value,
+                               GParamSpec            *pspec)
+{
+  GooCanvasGroup *group = (GooCanvasGroup*) object;
+  GooCanvasGroupPrivate *priv = goo_canvas_group_get_private (group);
+
+  goo_canvas_group_get_common_property (object, priv, prop_id, value, pspec);
+}
+
+static void
+goo_canvas_group_set_common_property (GObject               *object,
+                                      GooCanvasGroupPrivate *priv,
+                                      guint                  prop_id,
+                                      const GValue          *value,
+                                      GParamSpec            *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_X:
+      priv->x = g_value_get_double (value);
+      break;
+    case PROP_Y:
+      priv->y = g_value_get_double (value);
+      break;
+    case PROP_WIDTH:
+      priv->width = g_value_get_double (value);
+      break;
+    case PROP_HEIGHT:
+      priv->height = g_value_get_double (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+goo_canvas_group_set_property (GObject                  *object,
+                               guint                     prop_id,
+                               const GValue             *value,
+                               GParamSpec               *pspec)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
+  GooCanvasGroup *group = (GooCanvasGroup*) object;
+  GooCanvasGroupPrivate *priv = goo_canvas_group_get_private (group);
+
+  if (simple->model)
+    {
+      g_warning ("Can't set property of a canvas item with a model - set the model property instead");
+      return;
+    }
+
+  goo_canvas_group_set_common_property (object, priv, prop_id, value, pspec);
+  goo_canvas_item_simple_changed (simple, TRUE);
+}
+
 static void
 goo_canvas_group_add_child     (GooCanvasItem  *item,
 				GooCanvasItem  *child,
 				gint            position)
 {
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
   GooCanvasGroup *group = (GooCanvasGroup*) item;
+  AtkObject *atk_obj, *child_atk_obj;
 
   g_object_ref (child);
 
@@ -166,6 +347,16 @@ goo_canvas_group_add_child     (GooCanvasItem  *item,
     }
 
   goo_canvas_item_set_parent (child, item);
+  goo_canvas_item_set_is_static (child, simple->simple_data->is_static);
+
+  /* Emit the "children_changed" ATK signal, if ATK is enabled. */
+  atk_obj = atk_gobject_accessible_for_object (G_OBJECT (item));
+  if (!ATK_IS_NO_OP_OBJECT (atk_obj))
+    {
+      child_atk_obj = atk_gobject_accessible_for_object (G_OBJECT (child));
+      g_signal_emit_by_name (atk_obj, "children_changed::add",
+			     position, child_atk_obj);
+    }
 
   goo_canvas_item_request_update (item);
 }
@@ -186,7 +377,8 @@ goo_canvas_group_move_child    (GooCanvasItem  *item,
   if (simple->canvas)
     {
       goo_canvas_item_get_bounds (child, &bounds);
-      goo_canvas_request_redraw (simple->canvas, &bounds);
+      goo_canvas_request_item_redraw (simple->canvas, &bounds,
+				      simple->simple_data->is_static);
     }
 
   goo_canvas_util_ptr_array_move (group->items, old_position, new_position);
@@ -203,6 +395,7 @@ goo_canvas_group_remove_child  (GooCanvasItem  *item,
   GooCanvasGroup *group = (GooCanvasGroup*) item;
   GooCanvasItem *child;
   GooCanvasBounds bounds;
+  AtkObject *atk_obj, *child_atk_obj;
 
   g_return_if_fail (child_num < group->items->len);
 
@@ -211,14 +404,24 @@ goo_canvas_group_remove_child  (GooCanvasItem  *item,
   if (simple->canvas)
     {
       goo_canvas_item_get_bounds (child, &bounds);
-      goo_canvas_request_redraw (simple->canvas, &bounds);
+      goo_canvas_request_item_redraw (simple->canvas, &bounds,
+				      simple->simple_data->is_static);
     }
 
-  goo_canvas_item_set_parent (child, NULL);
-  g_object_unref (child);
+  /* Emit the "children_changed" ATK signal, if ATK is enabled. */
+  atk_obj = atk_gobject_accessible_for_object (G_OBJECT (item));
+  if (!ATK_IS_NO_OP_OBJECT (atk_obj))
+    {
+      child_atk_obj = atk_gobject_accessible_for_object (G_OBJECT (child));
+      g_signal_emit_by_name (atk_obj, "children_changed::remove",
+			     child_num, child_atk_obj);
+    }
 
   g_ptr_array_remove_index (group->items, child_num);
 
+  goo_canvas_item_set_parent (child, NULL);
+  g_object_unref (child);
+
   goo_canvas_item_request_update (item);
 }
 
@@ -238,7 +441,9 @@ goo_canvas_group_get_child   (GooCanvasItem       *item,
 {
   GooCanvasGroup *group = (GooCanvasGroup*) item;
 
-  return group->items->pdata[child_num];
+  if (child_num < group->items->len)
+    return group->items->pdata[child_num];
+  return NULL;
 }
 
 
@@ -252,6 +457,9 @@ goo_canvas_group_set_canvas  (GooCanvasItem *item,
   GooCanvasGroup *group = (GooCanvasGroup*) item;
   gint i;
 
+  if (simple->canvas == canvas)
+    return;
+
   simple->canvas = canvas;
 
   /* Recursively set the canvas of all child items. */
@@ -264,6 +472,29 @@ goo_canvas_group_set_canvas  (GooCanvasItem *item,
 
 
 static void
+goo_canvas_group_set_is_static  (GooCanvasItem *item,
+				 gboolean       is_static)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasGroup *group = (GooCanvasGroup*) item;
+  gint i;
+
+  if (simple_data->is_static == is_static)
+    return;
+
+  simple_data->is_static = is_static;
+
+  /* Recursively set the canvas of all child items. */
+  for (i = 0; i < group->items->len; i++)
+    {
+      GooCanvasItem *item = group->items->pdata[i];
+      goo_canvas_item_set_is_static (item, is_static);
+    }
+}
+
+
+static void
 on_model_child_added (GooCanvasGroupModel *model,
 		      gint                 position,
 		      GooCanvasGroup      *group)
@@ -353,6 +584,7 @@ goo_canvas_group_update  (GooCanvasItem   *item,
 {
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
   GooCanvasGroup *group = (GooCanvasGroup*) item;
+  GooCanvasGroupPrivate *priv = goo_canvas_group_get_private (group);
   GooCanvasBounds child_bounds;
   gboolean initial_bounds = TRUE;
   gint i;
@@ -372,35 +604,38 @@ goo_canvas_group_update  (GooCanvasItem   *item,
 
       cairo_save (cr);
       if (simple->simple_data->transform)
-	cairo_transform (cr, simple->simple_data->transform);
+        cairo_transform (cr, simple->simple_data->transform);
+
+      cairo_translate (cr, priv->x, priv->y);
 
       for (i = 0; i < group->items->len; i++)
-	{
-	  GooCanvasItem *child = group->items->pdata[i];
-
-	  goo_canvas_item_update (child, entire_tree, cr, &child_bounds);
-	  
-	  /* If the child has non-empty bounds, compute the union. */
-	  if (child_bounds.x1 < child_bounds.x2
-	      && child_bounds.y1 < child_bounds.y2)
-	    {
-	      if (initial_bounds)
-		{
-		  simple->bounds.x1 = child_bounds.x1;
-		  simple->bounds.y1 = child_bounds.y1;
-		  simple->bounds.x2 = child_bounds.x2;
-		  simple->bounds.y2 = child_bounds.y2;
-		  initial_bounds = FALSE;
-		}
-	      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);
-		}
-	    }
-	}
+        {
+          GooCanvasItem *child = group->items->pdata[i];
+
+          goo_canvas_item_update (child, entire_tree, cr, &child_bounds);
+          
+          /* If the child has non-empty bounds, compute the union. */
+          if (child_bounds.x1 < child_bounds.x2
+              && child_bounds.y1 < child_bounds.y2)
+            {
+              if (initial_bounds)
+                {
+                  simple->bounds.x1 = child_bounds.x1;
+                  simple->bounds.y1 = child_bounds.y1;
+                  simple->bounds.x2 = child_bounds.x2;
+                  simple->bounds.y2 = child_bounds.y2;
+                  initial_bounds = FALSE;
+                }
+              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);
     }
 
@@ -420,6 +655,7 @@ goo_canvas_group_get_items_at (GooCanvasItem  *item,
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
   GooCanvasItemSimpleData *simple_data = simple->simple_data;
   GooCanvasGroup *group = (GooCanvasGroup*) item;
+  GooCanvasGroupPrivate *priv = goo_canvas_group_get_private (group);
   gboolean visible = parent_visible;
   int i;
 
@@ -447,6 +683,8 @@ goo_canvas_group_get_items_at (GooCanvasItem  *item,
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
 
+  cairo_translate (cr, priv->x, priv->y);
+
   /* If the group has a clip path, check if the point is inside it. */
   if (simple_data->clip_path_commands)
     {
@@ -462,6 +700,19 @@ goo_canvas_group_get_items_at (GooCanvasItem  *item,
 	}
     }
 
+  if (priv->width > 0.0 && priv->height > 0.0)
+    {
+      double user_x = x, user_y = y;
+
+      cairo_device_to_user (cr, &user_x, &user_y);
+      if (user_x < 0.0 || user_x >= priv->width
+	  || user_y < 0.0 || user_y >= priv->height)
+	{
+	  cairo_restore (cr);
+	  return found_items;
+	}
+    }
+
   /* Step up from the bottom of the children to the top, adding any items
      found to the start of the list. */
   for (i = 0; i < group->items->len; i++)
@@ -487,6 +738,7 @@ goo_canvas_group_paint (GooCanvasItem         *item,
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
   GooCanvasItemSimpleData *simple_data = simple->simple_data;
   GooCanvasGroup *group = (GooCanvasGroup*) item;
+  GooCanvasGroupPrivate *priv = goo_canvas_group_get_private (group);
   gint i;
 
   /* Skip the item if the bounds don't intersect the expose rectangle. */
@@ -505,6 +757,8 @@ goo_canvas_group_paint (GooCanvasItem         *item,
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
 
+  cairo_translate (cr, priv->x, priv->y);
+
   /* Clip with the group's clip path, if it is set. */
   if (simple_data->clip_path_commands)
     {
@@ -513,6 +767,12 @@ goo_canvas_group_paint (GooCanvasItem         *item,
       cairo_clip (cr);
     }
 
+  if (priv->width > 0.0 && priv->height > 0.0)
+    {
+      cairo_rectangle (cr, 0.0, 0.0, priv->width, priv->height);
+      cairo_clip (cr);
+    }
+
   for (i = 0; i < group->items->len; i++)
     {
       GooCanvasItem *child = group->items->pdata[i];
@@ -539,6 +799,7 @@ canvas_item_interface_init (GooCanvasItemIface *iface)
   iface->paint          = goo_canvas_group_paint;
 
   iface->set_model      = goo_canvas_group_set_model;
+  iface->set_is_static  = goo_canvas_group_set_is_static;
 }
 
 
@@ -574,6 +835,14 @@ canvas_item_interface_init (GooCanvasItemIface *iface)
 static void item_model_interface_init (GooCanvasItemModelIface *iface);
 static void goo_canvas_group_model_dispose      (GObject            *object);
 static void goo_canvas_group_model_finalize     (GObject            *object);
+static void goo_canvas_group_model_get_property (GObject            *object,
+                                                 guint               prop_id,
+                                                 GValue             *value,
+                                                 GParamSpec         *pspec);
+static void goo_canvas_group_model_set_property (GObject            *object,
+                                                 guint               prop_id,
+                                                 const GValue       *value,
+                                                 GParamSpec         *pspec);
 
 G_DEFINE_TYPE_WITH_CODE (GooCanvasGroupModel, goo_canvas_group_model,
 			 GOO_TYPE_CANVAS_ITEM_MODEL_SIMPLE,
@@ -585,16 +854,27 @@ static void
 goo_canvas_group_model_class_init (GooCanvasGroupModelClass *klass)
 {
   GObjectClass *gobject_class = (GObjectClass*) klass;
+  g_type_class_add_private (gobject_class, sizeof (GooCanvasGroupPrivate));
 
   gobject_class->dispose  = goo_canvas_group_model_dispose;
   gobject_class->finalize = goo_canvas_group_model_finalize;
+  gobject_class->get_property  = goo_canvas_group_model_get_property;
+  gobject_class->set_property = goo_canvas_group_model_set_property;
+
+  goo_canvas_group_install_common_properties (gobject_class);
 }
 
 
 static void
 goo_canvas_group_model_init (GooCanvasGroupModel *gmodel)
 {
+  GooCanvasGroupPrivate *priv = GOO_CANVAS_GROUP_MODEL_GET_PRIVATE (gmodel);
   gmodel->children = g_ptr_array_sized_new (8);
+
+  priv->x = 0.0;
+  priv->y = 0.0;
+  priv->width = -1.0;
+  priv->height = -1.0;
 }
 
 
@@ -667,6 +947,28 @@ goo_canvas_group_model_finalize (GObject *object)
   G_OBJECT_CLASS (goo_canvas_group_model_parent_class)->finalize (object);
 }
 
+static void goo_canvas_group_model_get_property (GObject            *object,
+                                                 guint               prop_id,
+                                                 GValue             *value,
+                                                 GParamSpec         *pspec)
+{
+  GooCanvasGroupModel *model = (GooCanvasGroupModel*) object;
+  GooCanvasGroupPrivate *priv = GOO_CANVAS_GROUP_MODEL_GET_PRIVATE (model);
+
+  goo_canvas_group_get_common_property (object, priv, prop_id, value, pspec);
+}
+
+static void goo_canvas_group_model_set_property (GObject            *object,
+                                                 guint               prop_id,
+                                                 const GValue       *value,
+                                                 GParamSpec         *pspec)
+{
+  GooCanvasGroupModel *model = (GooCanvasGroupModel*) object;
+  GooCanvasGroupPrivate *priv = GOO_CANVAS_GROUP_MODEL_GET_PRIVATE (model);
+
+  goo_canvas_group_set_common_property (object, priv, prop_id, value, pspec);
+  g_signal_emit_by_name (model, "changed", TRUE);
+}
 
 extern void _goo_canvas_item_model_emit_child_added (GooCanvasItemModel *model,
 						     gint                position);
@@ -719,11 +1021,12 @@ goo_canvas_group_model_remove_child  (GooCanvasItemModel *model,
 
   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);
+
+  g_object_unref (child);
 }
 
 
@@ -742,7 +1045,9 @@ goo_canvas_group_model_get_child   (GooCanvasItemModel  *model,
 {
   GooCanvasGroupModel *gmodel = (GooCanvasGroupModel*) model;
 
-  return gmodel->children->pdata[child_num];
+  if (child_num < gmodel->children->len)
+    return gmodel->children->pdata[child_num];
+  return NULL;
 }
 
 
diff --git a/src/goocanvas/src/goocanvasitem.c b/src/goocanvas/src/goocanvasitem.c
index 4e1e095..57db899 100644
--- a/src/goocanvas/src/goocanvasitem.c
+++ b/src/goocanvas/src/goocanvasitem.c
@@ -48,6 +48,8 @@ enum {
   GRAB_BROKEN_EVENT,
   CHILD_NOTIFY,
   ANIMATION_FINISHED,
+  SCROLL_EVENT,
+  QUERY_TOOLTIP,
 
   LAST_SIGNAL
 };
@@ -101,7 +103,7 @@ goo_canvas_item_base_init (gpointer g_iface)
 {
   static GObjectNotifyContext cpn_context = { 0, NULL, NULL };
   static gboolean initialized = FALSE;
-
+  
   if (!initialized)
     {
       GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
@@ -118,8 +120,9 @@ goo_canvas_item_base_init (gpointer g_iface)
        * GooCanvasItem::enter-notify-event
        * @item: the item that received the signal.
        * @target_item: the target of the event.
-       * @event: the event data, with coordinates translated to canvas
-       *  coordinates.
+       * @event: the event data. The x & y fields contain the mouse position
+       *  in the item's coordinate space. The x_root & y_root fields contain
+       *  the same coordinates converted to the canvas coordinate space.
        *
        * Emitted when the mouse enters an item.
        *
@@ -142,8 +145,9 @@ goo_canvas_item_base_init (gpointer g_iface)
        * GooCanvasItem::leave-notify-event
        * @item: the item that received the signal.
        * @target_item: the target of the event.
-       * @event: the event data, with coordinates translated to canvas
-       *  coordinates.
+       * @event: the event data. The x & y fields contain the mouse position
+       *  in the item's coordinate space. The x_root & y_root fields contain
+       *  the same coordinates converted to the canvas coordinate space.
        *
        * Emitted when the mouse leaves an item.
        *
@@ -166,8 +170,9 @@ goo_canvas_item_base_init (gpointer g_iface)
        * GooCanvasItem::motion-notify-event
        * @item: the item that received the signal.
        * @target_item: the target of the event.
-       * @event: the event data, with coordinates translated to canvas
-       *  coordinates.
+       * @event: the event data. The x & y fields contain the mouse position
+       *  in the item's coordinate space. The x_root & y_root fields contain
+       *  the same coordinates converted to the canvas coordinate space.
        *
        * Emitted when the mouse moves within an item.
        *
@@ -190,8 +195,9 @@ goo_canvas_item_base_init (gpointer g_iface)
        * GooCanvasItem::button-press-event
        * @item: the item that received the signal.
        * @target_item: the target of the event.
-       * @event: the event data, with coordinates translated to canvas
-       *  coordinates.
+       * @event: the event data. The x & y fields contain the mouse position
+       *  in the item's coordinate space. The x_root & y_root fields contain
+       *  the same coordinates converted to the canvas coordinate space.
        *
        * Emitted when a mouse button is pressed in an item.
        *
@@ -214,8 +220,9 @@ goo_canvas_item_base_init (gpointer g_iface)
        * GooCanvasItem::button-release-event
        * @item: the item that received the signal.
        * @target_item: the target of the event.
-       * @event: the event data, with coordinates translated to canvas
-       *  coordinates.
+       * @event: the event data. The x & y fields contain the mouse position
+       *  in the item's coordinate space. The x_root & y_root fields contain
+       *  the same coordinates converted to the canvas coordinate space.
        *
        * Emitted when a mouse button is released in an item.
        *
@@ -331,6 +338,37 @@ goo_canvas_item_base_init (gpointer g_iface)
 		      GOO_TYPE_CANVAS_ITEM,
 		      GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 
+      /**
+       * GooCanvasItem::query-tooltip:
+       * @item: the item which received the signal.
+       * @x: the x coordinate of the mouse.
+       * @y: the y coordinate of the mouse.
+       * @keyboard_mode: %TRUE if the tooltip was triggered using the keyboard.
+       * @tooltip: a #GtkTooltip.
+       *
+       * Emitted when the mouse has paused over the item for a certain amount
+       * of time, or the tooltip was requested via the keyboard.
+       *
+       * Note that if @keyboard_mode is %TRUE, the values of @x and @y are
+       * undefined and should not be used.
+       *
+       * If the item wants to display a tooltip it should update @tooltip
+       * and return %TRUE.
+       *
+       * Returns: %TRUE if the item has set a tooltip to show.
+       */
+      canvas_item_signals[QUERY_TOOLTIP] =
+	g_signal_new ("query-tooltip",
+		      iface_type,
+		      G_SIGNAL_RUN_LAST,
+		      G_STRUCT_OFFSET (GooCanvasItemIface, query_tooltip),
+		      goo_canvas_boolean_handled_accumulator, NULL,
+		      goo_canvas_marshal_BOOLEAN__DOUBLE_DOUBLE_BOOLEAN_OBJECT,
+		      G_TYPE_BOOLEAN, 4,
+		      G_TYPE_DOUBLE,
+		      G_TYPE_DOUBLE,
+		      G_TYPE_BOOLEAN,
+		      GTK_TYPE_TOOLTIP);
 
       /**
        * GooCanvasItem::grab-broken-event
@@ -362,7 +400,7 @@ goo_canvas_item_base_init (gpointer g_iface)
        * @pspec: the #GParamSpec of the changed child property.
        *
        * Emitted for each child property that has changed.
-       * The signal's detail holds the property name.
+       * The signal's detail holds the property name. 
        */
       canvas_item_signals[CHILD_NOTIFY] =
 	g_signal_new ("child_notify",
@@ -374,7 +412,6 @@ goo_canvas_item_base_init (gpointer g_iface)
 		      G_TYPE_NONE, 1,
 		      G_TYPE_PARAM);
 
-
       /**
        * GooCanvasItem::animation-finished
        * @item: the item that received the signal.
@@ -392,6 +429,33 @@ goo_canvas_item_base_init (gpointer g_iface)
 		      G_TYPE_NONE, 1,
 		      G_TYPE_BOOLEAN);
 
+      /**
+       * GooCanvasItem::scroll-event
+       * @item: the item that received the signal.
+       * @target_item: the target of the event.
+       * @event: the event data. The x & y fields contain the mouse position
+       *  in the item's coordinate space. The x_root & y_root fields contain
+       *  the same coordinates converted to the canvas coordinate space.
+       *
+       * Emitted when a button in the 4 to 7 range is pressed. Wheel mice are
+       * usually configured to generate button press events for buttons 4 and 5
+       * when the wheel is turned in an item.
+       *
+       * Returns: %TRUE to stop the signal emission, or %FALSE to let it
+       *  continue.
+       */
+      canvas_item_signals[SCROLL_EVENT] =
+	g_signal_new ("scroll_event",
+		      iface_type,
+		      G_SIGNAL_RUN_LAST,
+		      G_STRUCT_OFFSET (GooCanvasItemIface,
+				       scroll_event),
+		      goo_canvas_boolean_handled_accumulator, NULL,
+		      goo_canvas_marshal_BOOLEAN__OBJECT_BOXED,
+		      G_TYPE_BOOLEAN, 2,
+		      GOO_TYPE_CANVAS_ITEM,
+		      GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+
       g_object_interface_install_property (g_iface,
 					   g_param_spec_object ("parent",
 								_("Parent"),
@@ -452,6 +516,13 @@ goo_canvas_item_base_init (gpointer g_iface)
 								 FALSE,
 								 G_PARAM_READWRITE));
 
+      g_object_interface_install_property (g_iface,
+					   g_param_spec_string ("tooltip",
+								_("Tooltip"),
+								_("The tooltip to display for the item"),
+								NULL,
+								G_PARAM_READWRITE));
+
       _goo_canvas_style_init ();
 
       initialized = TRUE;
@@ -462,9 +533,9 @@ goo_canvas_item_base_init (gpointer g_iface)
 /**
  * goo_canvas_item_get_canvas:
  * @item: a #GooCanvasItem.
- *
+ * 
  * Returns the #GooCanvas containing the given #GooCanvasItem.
- *
+ * 
  * Returns: the #GooCanvas.
  **/
 GooCanvas*
@@ -491,7 +562,7 @@ goo_canvas_item_get_canvas (GooCanvasItem *item)
  * goo_canvas_item_set_canvas:
  * @item: a #GooCanvasItem.
  * @canvas: a #GooCanvas
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items, specifically container items such as #GooCanvasGroup.
  *
@@ -514,7 +585,7 @@ goo_canvas_item_set_canvas     (GooCanvasItem   *item,
  * @child: the item to add.
  * @position: the position of the item, or -1 to place it last (at the top of
  *  the stacking order).
- *
+ * 
  * Adds a child item to a container item at the given stack position.
  **/
 void
@@ -536,7 +607,7 @@ goo_canvas_item_add_child      (GooCanvasItem       *item,
  * @item: a container item.
  * @old_position: the current position of the child item.
  * @new_position: the new position of the child item.
- *
+ * 
  * Moves a child item to a new stack position within the container.
  **/
 void
@@ -556,7 +627,7 @@ goo_canvas_item_move_child     (GooCanvasItem       *item,
  * goo_canvas_item_remove_child:
  * @item: a container item.
  * @child_num: the position of the child item to remove.
- *
+ * 
  * Removes the child item at the given position.
  **/
 void
@@ -575,9 +646,9 @@ goo_canvas_item_remove_child   (GooCanvasItem       *item,
  * goo_canvas_item_find_child:
  * @item: a container item.
  * @child: the child item to find.
- *
+ * 
  * Attempts to find the given child item with the container's stack.
- *
+ * 
  * Returns: the position of the given @child item, or -1 if it isn't found.
  **/
 gint
@@ -602,9 +673,9 @@ goo_canvas_item_find_child     (GooCanvasItem *item,
 /**
  * goo_canvas_item_is_container:
  * @item: an item.
- *
+ * 
  * Tests to see if the given item is a container.
- *
+ * 
  * Returns: %TRUE if the item is a container.
  **/
 gboolean
@@ -619,9 +690,9 @@ goo_canvas_item_is_container (GooCanvasItem       *item)
 /**
  * goo_canvas_item_get_n_children:
  * @item: a container item.
- *
+ * 
  * Gets the number of children of the container.
- *
+ * 
  * Returns: the number of children.
  **/
 gint
@@ -637,10 +708,11 @@ goo_canvas_item_get_n_children (GooCanvasItem       *item)
  * goo_canvas_item_get_child:
  * @item: a container item.
  * @child_num: the position of a child in the container's stack.
- *
+ * 
  * Gets the child item at the given stack position.
- *
- * Returns: the child item at the given stack position.
+ * 
+ * Returns: the child item at the given stack position, or %NULL if @child_num
+ * is out of range.
  **/
 GooCanvasItem*
 goo_canvas_item_get_child (GooCanvasItem       *item,
@@ -655,9 +727,9 @@ goo_canvas_item_get_child (GooCanvasItem       *item,
 /**
  * goo_canvas_item_get_parent:
  * @item: an item.
- *
+ * 
  * Gets the parent of the given item.
- *
+ * 
  * Returns: the parent item, or %NULL if the item has no parent.
  **/
 GooCanvasItem*
@@ -673,7 +745,7 @@ goo_canvas_item_get_parent  (GooCanvasItem *item)
  * goo_canvas_item_set_parent:
  * @item: an item.
  * @parent: the new parent item.
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items (specifically container items such as #GooCanvasGroup).
  * It sets the parent of the child item.
@@ -693,9 +765,52 @@ goo_canvas_item_set_parent (GooCanvasItem *item,
 
 
 /**
- * goo_canvas_item_remove:
+ * goo_canvas_item_get_is_static:
  * @item: an item.
+ * 
+ * Returns %TRUE if the item is static. Static items do not move or change
+ * size when the canvas is scrolled or the scale changes.
  *
+ * Returns: %TRUE if the item is static.
+ **/
+gboolean
+goo_canvas_item_get_is_static	(GooCanvasItem		*item)
+{
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+
+  if (iface->get_is_static)
+    return iface->get_is_static (item);
+  return FALSE;
+}
+
+
+/**
+ * goo_canvas_item_set_is_static:
+ * @item: an item.
+ * @is_static: if the item is static.
+ * 
+ * Notifies the item that it is static. Static items do not move or change
+ * size when the canvas is scrolled or the scale changes.
+ *
+ * Container items such as #GooCanvasGroup should call this function when
+ * children are added, to notify children whether they are static or not.
+ * Containers should also pass on any changes in their own status to children.
+ **/
+void
+goo_canvas_item_set_is_static	(GooCanvasItem		*item,
+				 gboolean		 is_static)
+{
+  GooCanvasItemIface *iface = GOO_CANVAS_ITEM_GET_IFACE (item);
+
+  if (iface->set_is_static)
+    iface->set_is_static (item, is_static);
+}
+
+
+/**
+ * goo_canvas_item_remove:
+ * @item: an item.
+ * 
  * Removes an item from its parent. If the item is in a canvas it will be
  * removed.
  *
@@ -724,7 +839,7 @@ goo_canvas_item_remove (GooCanvasItem *item)
  * @item: an item.
  * @above: the item to raise @item above, or %NULL to raise @item to the top
  *  of the stack.
- *
+ * 
  * Raises an item in the stacking order.
  **/
 void
@@ -767,7 +882,7 @@ goo_canvas_item_raise          (GooCanvasItem *item,
  * @item: an item.
  * @below: the item to lower @item below, or %NULL to lower @item to the
  *  bottom of the stack.
- *
+ * 
  * Lowers an item in the stacking order.
  **/
 void
@@ -809,9 +924,9 @@ goo_canvas_item_lower          (GooCanvasItem *item,
  * goo_canvas_item_get_transform:
  * @item: an item.
  * @transform: the place to store the transform.
- *
+ * 
  * Gets the transformation matrix of an item.
- *
+ * 
  * Returns: %TRUE if a transform is set.
  **/
 gboolean
@@ -829,11 +944,11 @@ goo_canvas_item_get_transform  (GooCanvasItem   *item,
  * @item: an item.
  * @child: a child of @item.
  * @transform: the place to store the transform.
- *
+ * 
  * Gets the transformation matrix of an item combined with any special
  * transform needed for the given child. These special transforms are used
  * by layout items such as #GooCanvasTable.
- *
+ * 
  * Returns: %TRUE if a transform is set.
  **/
 gboolean
@@ -859,7 +974,7 @@ goo_canvas_item_get_transform_for_child  (GooCanvasItem  *item,
  * @item: an item.
  * @transform: the new transformation matrix, or %NULL to reset the
  *  transformation to the identity matrix.
- *
+ * 
  * Sets the transformation matrix of an item.
  **/
 void
@@ -877,13 +992,13 @@ goo_canvas_item_set_transform  (GooCanvasItem        *item,
  * @y: returns the y coordinate of the origin of the item's coordinate space.
  * @scale: returns the scale of the item.
  * @rotation: returns the clockwise rotation of the item, in degrees (0-360).
- *
+ * 
  * This function can be used to get the position, scale and rotation of an
  * item, providing that the item has a simple transformation matrix
  * (e.g. set with goo_canvas_item_set_simple_transform(), or using a
  * combination of simple translate, scale and rotate operations). If the item
  * has a complex transformation matrix the results will be incorrect.
- *
+ * 
  * Returns: %TRUE if a transform is set.
  **/
 gboolean
@@ -932,7 +1047,7 @@ goo_canvas_item_get_simple_transform (GooCanvasItem   *item,
  * @y: the y coordinate of the origin of the item's coordinate space.
  * @scale: the scale of the item.
  * @rotation: the clockwise rotation of the item, in degrees.
- *
+ * 
  * A convenience function to set the item's transformation matrix.
  **/
 void
@@ -957,7 +1072,7 @@ goo_canvas_item_set_simple_transform (GooCanvasItem   *item,
  * @item: an item.
  * @tx: the amount to move the origin in the horizontal direction.
  * @ty: the amount to move the origin in the vertical direction.
- *
+ * 
  * Translates the origin of the item's coordinate system by the given amounts.
  **/
 void
@@ -979,7 +1094,7 @@ goo_canvas_item_translate      (GooCanvasItem *item,
  * @item: an item.
  * @sx: the amount to scale the horizontal axis.
  * @sy: the amount to scale the vertical axis.
- *
+ * 
  * Scales the item's coordinate system by the given amounts.
  **/
 void
@@ -1002,7 +1117,7 @@ goo_canvas_item_scale          (GooCanvasItem *item,
  * @degrees: the clockwise angle of rotation.
  * @cx: the x coordinate of the origin of the rotation.
  * @cy: the y coordinate of the origin of the rotation.
- *
+ * 
  * Rotates the item's coordinate system by the given amount, about the given
  * origin.
  **/
@@ -1030,7 +1145,7 @@ goo_canvas_item_rotate         (GooCanvasItem *item,
  * @degrees: the skew angle.
  * @cx: the x coordinate of the origin of the skew transform.
  * @cy: the y coordinate of the origin of the skew transform.
- *
+ * 
  * Skews the item's coordinate system along the x axis by the given amount,
  * about the given origin.
  **/
@@ -1059,7 +1174,7 @@ goo_canvas_item_skew_x         (GooCanvasItem *item,
  * @degrees: the skew angle.
  * @cx: the x coordinate of the origin of the skew transform.
  * @cy: the y coordinate of the origin of the skew transform.
- *
+ * 
  * Skews the item's coordinate system along the y axis by the given amount,
  * about the given origin.
  **/
@@ -1085,10 +1200,10 @@ goo_canvas_item_skew_y         (GooCanvasItem *item,
 /**
  * goo_canvas_item_get_style:
  * @item: an item.
- *
+ * 
  * Gets the item's style. If the item doesn't have its own style it will return
  * its parent's style.
- *
+ * 
  * Returns: the item's style.
  **/
 GooCanvasStyle*
@@ -1104,7 +1219,7 @@ goo_canvas_item_get_style      (GooCanvasItem   *item)
  * goo_canvas_item_set_style:
  * @item: an item.
  * @style: a style.
- *
+ * 
  * Sets the item's style, by copying the properties from the given style.
  **/
 void
@@ -1342,7 +1457,7 @@ _goo_canvas_item_animate_internal (GooCanvasItem       *item,
  *  second).
  * @step_time: the time between each animation step, in milliseconds.
  * @type: specifies what happens when the animation finishes.
- *
+ * 
  * Animates an item from its current position to the given offsets, scale
  * and rotation.
  **/
@@ -1365,7 +1480,7 @@ goo_canvas_item_animate        (GooCanvasItem *item,
 /**
  * goo_canvas_item_stop_animation:
  * @item: an item.
- *
+ * 
  * Stops any current animation for the given item, leaving it at its current
  * position.
  **/
@@ -1384,7 +1499,7 @@ goo_canvas_item_stop_animation (GooCanvasItem *item)
 /**
  * goo_canvas_item_request_update:
  * @item: a #GooCanvasItem.
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items.
  *
@@ -1407,7 +1522,7 @@ goo_canvas_item_request_update  (GooCanvasItem *item)
  * goo_canvas_item_get_bounds:
  * @item: a #GooCanvasItem.
  * @bounds: a #GooCanvasBounds to return the bounds in.
- *
+ * 
  * Gets the bounds of the item.
  *
  * Note that the bounds includes the entire fill and stroke extents of the
@@ -1434,12 +1549,12 @@ goo_canvas_item_get_bounds  (GooCanvasItem   *item,
  * @parent_is_visible: %TRUE if the parent item is visible (which
  *  implies that all ancestors are also visible).
  * @found_items: the list of items found so far.
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items, specifically container items such as #GooCanvasGroup.
  *
  * It gets the items at the given point.
- *
+ * 
  * Returns: the @found_items list, with any more found items added onto
  *  the start of the list, leaving the top item first.
  **/
@@ -1465,7 +1580,7 @@ goo_canvas_item_get_items_at (GooCanvasItem  *item,
 /**
  * goo_canvas_item_is_visible:
  * @item: a #GooCanvasItem.
- *
+ * 
  * Checks if the item is visible.
  *
  * This entails checking the item's own visibility setting, as well as those
@@ -1473,7 +1588,7 @@ goo_canvas_item_get_items_at (GooCanvasItem  *item,
  *
  * Note that the item may be scrolled off the screen and so may not
  * be actually visible to the user.
- *
+ * 
  * Returns: %TRUE if the item is visible.
  **/
 gboolean
@@ -1498,9 +1613,9 @@ goo_canvas_item_is_visible  (GooCanvasItem   *item)
 /**
  * goo_canvas_item_get_model:
  * @item: a #GooCanvasItem.
- *
+ * 
  * Gets the model of the given canvas item.
- *
+ * 
  * Returns: the item's model, or %NULL if it has no model.
  **/
 GooCanvasItemModel*
@@ -1516,7 +1631,7 @@ goo_canvas_item_get_model	  (GooCanvasItem   *item)
  * goo_canvas_item_set_model:
  * @item: a #GooCanvasItem.
  * @model: a #GooCanvasItemModel.
- *
+ * 
  * Sets the model of the given canvas item.
  **/
 void
@@ -1533,7 +1648,7 @@ goo_canvas_item_set_model	  (GooCanvasItem      *item,
 /**
  * goo_canvas_item_ensure_updated:
  * @item: a #GooCanvasItem.
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items.
  *
@@ -1557,7 +1672,7 @@ goo_canvas_item_ensure_updated (GooCanvasItem *item)
  * @entire_tree: if the entire subtree should be updated.
  * @cr: a cairo context.
  * @bounds: a #GooCanvasBounds to return the new bounds in.
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items, specifically container items such as #GooCanvasGroup.
  *
@@ -1579,10 +1694,10 @@ goo_canvas_item_update      (GooCanvasItem   *item,
  * goo_canvas_item_paint:
  * @item: a #GooCanvasItem.
  * @cr: a cairo context.
- * @bounds: the bounds that need to be repainted.
+ * @bounds: the bounds that need to be repainted, in device space.
  * @scale: the scale to use to determine whether an item should be painted.
  *  See #GooCanvasItem:visibility-threshold.
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items, specifically container items such as #GooCanvasGroup.
  *
@@ -1609,12 +1724,12 @@ goo_canvas_item_paint (GooCanvasItem         *item,
  * @cr: a cairo context.
  * @requested_area: a #GooCanvasBounds to return the requested area in, in the
  *  parent's coordinate space.
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items, specifically layout items such as #GooCanvasTable.
  *
  * It gets the requested area of a child item.
- *
+ * 
  * Returns: %TRUE if the item should be allocated space.
  **/
 gboolean
@@ -1633,14 +1748,14 @@ goo_canvas_item_get_requested_area (GooCanvasItem    *item,
  * @item: a #GooCanvasItem.
  * @cr: a cairo context.
  * @width: the width that the item may be allocated.
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items, specifically layout items such as #GooCanvasTable.
  *
  * It gets the requested height of a child item, assuming it is allocated the
  * given width. This is useful for text items whose requested height may change
  * depending on the allocated width.
- *
+ * 
  * Returns: the requested height of the item, given the allocated width,
  *  or %-1 if the item doesn't support this method or its height doesn't
  *  change when allocated different widths.
@@ -1671,7 +1786,7 @@ goo_canvas_item_get_requested_height (GooCanvasItem       *item,
  *  the device coordinate space.
  * @y_offset: the y offset of the allocated area from the requested area in
  *  the device coordinate space.
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items, specifically layout items such as #GooCanvasTable.
  *
@@ -2014,7 +2129,7 @@ _goo_canvas_item_set_child_properties_internal (GObject              *object,
  * @child: a child #GooCanvasItem.
  * @property_name: the name of the child property to get.
  * @value: a location to return the value.
- *
+ * 
  * Gets a child property of @child.
  **/
 void
@@ -2038,7 +2153,7 @@ goo_canvas_item_get_child_property (GooCanvasItem *item,
  * @child: a child #GooCanvasItem.
  * @property_name: the name of the child property to set.
  * @value: the value to set the property to.
- *
+ * 
  * Sets a child property of @child.
  **/
 void
@@ -2062,7 +2177,7 @@ goo_canvas_item_set_child_property (GooCanvasItem   *item,
  * @child: a child #GooCanvasItem.
  * @var_args: pairs of property names and value pointers, and a terminating
  *  %NULL.
- *
+ * 
  * Gets the values of one or more child properties of @child.
  **/
 void
@@ -2082,7 +2197,7 @@ goo_canvas_item_get_child_properties_valist (GooCanvasItem   *item,
  * @item: a #GooCanvasItem.
  * @child: a child #GooCanvasItem.
  * @var_args: pairs of property names and values, and a terminating %NULL.
- *
+ * 
  * Sets the values of one or more child properties of @child.
  **/
 void
@@ -2102,7 +2217,7 @@ goo_canvas_item_set_child_properties_valist (GooCanvasItem   *item,
  * @item: a #GooCanvasItem.
  * @child: a child #GooCanvasItem.
  * @...: pairs of property names and value pointers, and a terminating %NULL.
- *
+ * 
  * Gets the values of one or more child properties of @child.
  **/
 void
@@ -2111,7 +2226,7 @@ goo_canvas_item_get_child_properties        (GooCanvasItem   *item,
 					     ...)
 {
   va_list var_args;
-
+  
   va_start (var_args, child);
   goo_canvas_item_get_child_properties_valist (item, child, var_args);
   va_end (var_args);
@@ -2123,7 +2238,7 @@ goo_canvas_item_get_child_properties        (GooCanvasItem   *item,
  * @item: a #GooCanvasItem.
  * @child: a child #GooCanvasItem.
  * @...: pairs of property names and values, and a terminating %NULL.
- *
+ * 
  * Sets the values of one or more child properties of @child.
  **/
 void
@@ -2132,7 +2247,7 @@ goo_canvas_item_set_child_properties        (GooCanvasItem   *item,
 					     ...)
 {
   va_list var_args;
-
+  
   va_start (var_args, child);
   goo_canvas_item_set_child_properties_valist (item, child, var_args);
   va_end (var_args);
@@ -2145,11 +2260,11 @@ goo_canvas_item_set_child_properties        (GooCanvasItem   *item,
  * @iclass: a #GObjectClass
  * @property_id: the id for the property
  * @pspec: the #GParamSpec for the property
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * items, specifically layout container items such as #GooCanvasTable.
  *
- * It installs a child property on a canvas item class.
+ * It installs a child property on a canvas item class. 
  **/
 void
 goo_canvas_item_class_install_child_property (GObjectClass *iclass,
@@ -2203,7 +2318,7 @@ goo_canvas_item_class_find_child_property (GObjectClass *iclass,
  * goo_canvas_item_class_list_child_properties:
  * @iclass: a #GObjectClass
  * @n_properties: location to return the number of child properties found
- * @returns: a newly allocated array of #GParamSpec*. The array must be
+ * @returns: a newly allocated array of #GParamSpec*. The array must be 
  *           freed with g_free().
  *
  * This function is only intended to be used when implementing new canvas
diff --git a/src/goocanvas/src/goocanvasitem.h b/src/goocanvas/src/goocanvasitem.h
index 5ac307c..76c61ec 100644
--- a/src/goocanvas/src/goocanvasitem.h
+++ b/src/goocanvas/src/goocanvasitem.h
@@ -55,7 +55,6 @@ GType goo_canvas_bounds_get_type (void) G_GNUC_CONST;
 
 #define GOO_TYPE_CANVAS_ITEM            (goo_canvas_item_get_type ())
 #define GOO_CANVAS_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_ITEM, GooCanvasItem))
-#define GOO_CANVAS_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_ITEM, GooCanvasItemClass))
 #define GOO_IS_CANVAS_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_ITEM))
 #define GOO_CANVAS_ITEM_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GOO_TYPE_CANVAS_ITEM, GooCanvasItemIface))
 
@@ -110,6 +109,8 @@ typedef struct _GooCanvasItem       GooCanvasItem;
  * @get_style: gets the item's style.
  * @set_style: sets the item's style.
  * @is_visible: returns %TRUE if the item is currently visible.
+ * @get_is_static: returns %TRUE if the item is static.
+ * @set_is_static: notifies the item whether it is static or not.
  * @get_requested_height: returns the requested height of the item,
  *  given a particular allocated width, using the parent's coordinate space.
  * @get_model: gets the model that the canvas item is viewing.
@@ -126,7 +127,10 @@ typedef struct _GooCanvasItem       GooCanvasItem;
  * @key_release_event: signal emitted when a key is released.
  * @grab_broken_event: signal emitted when a grab that the item has is lost.
  * @child_notify: signal emitted when a child property is changed.
+ * @query_tooltip: signal emitted to query the tooltip of an item.
  * @animation_finished: signal emitted when the item's animation has finished.
+ * @scroll_event: signal emitted when the mouse wheel is activated within
+ * the item.
  *
  * #GooCanvasItemIFace holds the virtual methods that make up the
  * #GooCanvasItem interface.
@@ -271,28 +275,30 @@ struct _GooCanvasItemIface
 							 GdkEventGrabBroken	*event);
   void			(* child_notify)		(GooCanvasItem		*item,
 							 GParamSpec		*pspec);
-
-  /*< private >*/
-
-  /* We might use this in future to support tooltips. */
   gboolean		(* query_tooltip)		(GooCanvasItem		*item,
 							 gdouble		 x,
 							 gdouble		 y,
 							 gboolean		 keyboard_tooltip,
-							 gpointer /*GtkTooltip*/		*tooltip);
+							 GtkTooltip		*tooltip);
+
+  gboolean		(* get_is_static)		(GooCanvasItem		*item);
+  void			(* set_is_static)		(GooCanvasItem		*item,
+							 gboolean		 is_static);
 
   void			(* animation_finished)		(GooCanvasItem           *item,
 							 gboolean                 stopped);
 
+  gboolean		(* scroll_event)		(GooCanvasItem		*item,
+							 GooCanvasItem		*target,
+							 GdkEventScroll		*event);
+
+  /*< private >*/
+
   /* Padding for future expansion */
   void (*_goo_canvas_reserved1) (void);
   void (*_goo_canvas_reserved2) (void);
   void (*_goo_canvas_reserved3) (void);
   void (*_goo_canvas_reserved4) (void);
-  void (*_goo_canvas_reserved5) (void);
-  void (*_goo_canvas_reserved6) (void);
-  void (*_goo_canvas_reserved7) (void);
-  void (*_goo_canvas_reserved8) (void);
 };
 
 
@@ -449,6 +455,9 @@ void		   goo_canvas_item_allocate_area      (GooCanvasItem	     *item,
 						       gdouble                x_offset,
 						       gdouble                y_offset);
 
+gboolean	   goo_canvas_item_get_is_static	(GooCanvasItem		*item);
+void		   goo_canvas_item_set_is_static	(GooCanvasItem		*item,
+							 gboolean		 is_static);
 
 
 /*
diff --git a/src/goocanvas/src/goocanvasitemmodel.c b/src/goocanvas/src/goocanvasitemmodel.c
index a2e559a..6f2de83 100644
--- a/src/goocanvas/src/goocanvasitemmodel.c
+++ b/src/goocanvas/src/goocanvasitemmodel.c
@@ -98,7 +98,7 @@ goo_canvas_item_model_base_init (gpointer g_iface)
 {
   static GObjectNotifyContext cpn_context = { 0, NULL, NULL };
   static gboolean initialized = FALSE;
-
+  
   if (!initialized)
     {
       GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
@@ -184,7 +184,7 @@ goo_canvas_item_model_base_init (gpointer g_iface)
        * @pspec: the #GParamSpec of the changed child property.
        *
        * Emitted for each child property that has changed.
-       * The signal's detail holds the property name.
+       * The signal's detail holds the property name. 
        */
       item_model_signals[CHILD_NOTIFY] =
 	g_signal_new ("child_notify",
@@ -213,6 +213,7 @@ goo_canvas_item_model_base_init (gpointer g_iface)
 		      G_TYPE_NONE, 1,
 		      G_TYPE_BOOLEAN);
 
+
       g_object_interface_install_property (g_iface,
 					   g_param_spec_object ("parent",
 								_("Parent"),
@@ -273,6 +274,13 @@ goo_canvas_item_model_base_init (gpointer g_iface)
 								 FALSE,
 								 G_PARAM_READWRITE));
 
+      g_object_interface_install_property (g_iface,
+					   g_param_spec_string ("tooltip",
+								_("Tooltip"),
+								_("The tooltip to display for the item"),
+								NULL,
+								G_PARAM_READWRITE));
+
       _goo_canvas_style_init ();
 
       initialized = TRUE;
@@ -286,7 +294,7 @@ goo_canvas_item_model_base_init (gpointer g_iface)
  * @child: the child to add.
  * @position: the position of the child, or -1 to place it last (at the top of
  *  the stacking order).
- *
+ * 
  * Adds a child at the given stack position.
  **/
 void
@@ -308,7 +316,7 @@ goo_canvas_item_model_add_child      (GooCanvasItemModel  *model,
  * @model: an item model.
  * @old_position: the current position of the child.
  * @new_position: the new position of the child.
- *
+ * 
  * Moves a child to a new stack position.
  **/
 void
@@ -328,7 +336,7 @@ goo_canvas_item_model_move_child     (GooCanvasItemModel  *model,
  * goo_canvas_item_model_remove_child:
  * @model: an item model.
  * @child_num: the position of the child to remove.
- *
+ * 
  * Removes the child at the given position.
  **/
 void
@@ -347,9 +355,9 @@ goo_canvas_item_model_remove_child   (GooCanvasItemModel  *model,
  * goo_canvas_item_model_find_child:
  * @model: an item model.
  * @child: the child to find.
- *
+ * 
  * Attempts to find the given child with the container's stack.
- *
+ * 
  * Returns: the position of the given @child, or -1 if it isn't found.
  **/
 gint
@@ -374,9 +382,9 @@ goo_canvas_item_model_find_child     (GooCanvasItemModel *model,
 /**
  * goo_canvas_item_model_is_container:
  * @model: an item model.
- *
+ * 
  * Tests to see if the given item model is a container.
- *
+ * 
  * Returns: %TRUE if the item model is a container.
  **/
 gboolean
@@ -391,9 +399,9 @@ goo_canvas_item_model_is_container (GooCanvasItemModel       *model)
 /**
  * goo_canvas_item_model_get_n_children:
  * @model: an item model.
- *
+ * 
  * Gets the number of children of the container.
- *
+ * 
  * Returns: the number of children.
  **/
 gint
@@ -409,10 +417,11 @@ goo_canvas_item_model_get_n_children (GooCanvasItemModel       *model)
  * goo_canvas_item_model_get_child:
  * @model: an item model.
  * @child_num: the position of a child in the container's stack.
- *
+ * 
  * Gets the child at the given stack position.
- *
- * Returns: the child at the given stack position.
+ * 
+ * Returns: the child at the given stack position, or %NULL if @child_num
+ * is out of range.
  **/
 GooCanvasItemModel*
 goo_canvas_item_model_get_child (GooCanvasItemModel  *model,
@@ -427,9 +436,9 @@ goo_canvas_item_model_get_child (GooCanvasItemModel  *model,
 /**
  * goo_canvas_item_model_get_parent:
  * @model: an item model.
- *
+ * 
  * Gets the parent of the given model.
- *
+ * 
  * Returns: the parent model, or %NULL if the model has no parent.
  **/
 GooCanvasItemModel*
@@ -443,7 +452,7 @@ goo_canvas_item_model_get_parent  (GooCanvasItemModel *model)
  * goo_canvas_item_model_set_parent:
  * @model: an item model.
  * @parent: the new parent item model.
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * item models (specifically container models such as #GooCanvasGroupModel).
  * It sets the parent of the child model.
@@ -465,7 +474,7 @@ goo_canvas_item_model_set_parent (GooCanvasItemModel *model,
 /**
  * goo_canvas_item_model_remove:
  * @model: an item model.
- *
+ * 
  * Removes a model from its parent. If the model is in a canvas it will be
  * removed.
  *
@@ -494,7 +503,7 @@ goo_canvas_item_model_remove         (GooCanvasItemModel *model)
  * @model: an item model.
  * @above: the item model to raise @model above, or %NULL to raise @model to the top
  *  of the stack.
- *
+ * 
  * Raises a model in the stacking order.
  **/
 void
@@ -537,7 +546,7 @@ goo_canvas_item_model_raise          (GooCanvasItemModel *model,
  * @model: an item model.
  * @below: the item model to lower @model below, or %NULL to lower @model to the
  *  bottom of the stack.
- *
+ * 
  * Lowers a model in the stacking order.
  **/
 void
@@ -579,9 +588,9 @@ goo_canvas_item_model_lower          (GooCanvasItemModel *model,
  * goo_canvas_item_model_get_transform:
  * @model: an item model.
  * @transform: the place to store the transform.
- *
+ * 
  * Gets the transformation matrix of an item model.
- *
+ * 
  * Returns: %TRUE if a transform is set.
  **/
 gboolean
@@ -599,7 +608,7 @@ goo_canvas_item_model_get_transform  (GooCanvasItemModel *model,
  * @model: an item model.
  * @transform: the new transformation matrix, or %NULL to reset the
  *  transformation to the identity matrix.
- *
+ * 
  * Sets the transformation matrix of an item model.
  **/
 void
@@ -617,13 +626,13 @@ goo_canvas_item_model_set_transform  (GooCanvasItemModel   *model,
  * @y: returns the y coordinate of the origin of the model's coordinate space.
  * @scale: returns the scale of the model.
  * @rotation: returns the clockwise rotation of the model, in degrees (0-360).
- *
+ * 
  * This function can be used to get the position, scale and rotation of an
  * item model, providing that the model has a simple transformation matrix
  * (e.g. set with goo_canvas_item_model_set_simple_transform(), or using a
  * combination of simple translate, scale and rotate operations). If the model
  * has a complex transformation matrix the results will be incorrect.
- *
+ * 
  * Returns: %TRUE if a transform is set.
  **/
 gboolean
@@ -672,7 +681,7 @@ goo_canvas_item_model_get_simple_transform (GooCanvasItemModel *model,
  * @y: the y coordinate of the origin of the model's coordinate space.
  * @scale: the scale of the model.
  * @rotation: the clockwise rotation of the model, in degrees.
- *
+ * 
  * A convenience function to set the item model's transformation matrix.
  **/
 void
@@ -697,7 +706,7 @@ goo_canvas_item_model_set_simple_transform (GooCanvasItemModel *model,
  * @model: an item model.
  * @tx: the amount to move the origin in the horizontal direction.
  * @ty: the amount to move the origin in the vertical direction.
- *
+ * 
  * Translates the origin of the model's coordinate system by the given amounts.
  **/
 void
@@ -719,7 +728,7 @@ goo_canvas_item_model_translate      (GooCanvasItemModel *model,
  * @model: an item model.
  * @sx: the amount to scale the horizontal axis.
  * @sy: the amount to scale the vertical axis.
- *
+ * 
  * Scales the model's coordinate system by the given amounts.
  **/
 void
@@ -742,7 +751,7 @@ goo_canvas_item_model_scale          (GooCanvasItemModel *model,
  * @degrees: the clockwise angle of rotation.
  * @cx: the x coordinate of the origin of the rotation.
  * @cy: the y coordinate of the origin of the rotation.
- *
+ * 
  * Rotates the model's coordinate system by the given amount, about the given
  * origin.
  **/
@@ -770,7 +779,7 @@ goo_canvas_item_model_rotate         (GooCanvasItemModel *model,
  * @degrees: the skew angle.
  * @cx: the x coordinate of the origin of the skew transform.
  * @cy: the y coordinate of the origin of the skew transform.
- *
+ * 
  * Skews the model's coordinate system along the x axis by the given amount,
  * about the given origin.
  **/
@@ -799,7 +808,7 @@ goo_canvas_item_model_skew_x         (GooCanvasItemModel *model,
  * @degrees: the skew angle.
  * @cx: the x coordinate of the origin of the skew transform.
  * @cy: the y coordinate of the origin of the skew transform.
- *
+ * 
  * Skews the model's coordinate system along the y axis by the given amount,
  * about the given origin.
  **/
@@ -825,10 +834,10 @@ goo_canvas_item_model_skew_y         (GooCanvasItemModel *model,
 /**
  * goo_canvas_item_model_get_style:
  * @model: an item model.
- *
+ * 
  * Gets the model's style. If the model doesn't have its own style it will
  * return its parent's style.
- *
+ * 
  * Returns: the model's style.
  **/
 GooCanvasStyle*
@@ -844,7 +853,7 @@ goo_canvas_item_model_get_style      (GooCanvasItemModel   *model)
  * goo_canvas_item_model_set_style:
  * @model: an item model.
  * @style: a style.
- *
+ * 
  * Sets the model's style, by copying the properties from the given style.
  **/
 void
@@ -885,7 +894,7 @@ extern void _goo_canvas_item_animate_internal (GooCanvasItem       *item,
  *  second).
  * @step_time: the time between each animation step, in milliseconds.
  * @type: specifies what happens when the animation finishes.
- *
+ * 
  * Animates a model from its current position to the given offsets, scale
  * and rotation.
  **/
@@ -908,7 +917,7 @@ goo_canvas_item_model_animate        (GooCanvasItemModel  *model,
 /**
  * goo_canvas_item_model_stop_animation:
  * @model: an item model.
- *
+ * 
  * Stops any current animation for the given model, leaving it at its current
  * position.
  **/
@@ -939,7 +948,7 @@ extern void _goo_canvas_item_set_child_properties_internal (GObject *object, GOb
  * @child: a child #GooCanvasItemModel.
  * @property_name: the name of the child property to get.
  * @value: a location to return the value.
- *
+ * 
  * Gets a child property of @child.
  **/
 void
@@ -963,7 +972,7 @@ goo_canvas_item_model_get_child_property (GooCanvasItemModel *model,
  * @child: a child #GooCanvasItemModel.
  * @property_name: the name of the child property to set.
  * @value: the value to set the property to.
- *
+ * 
  * Sets a child property of @child.
  **/
 void
@@ -987,7 +996,7 @@ goo_canvas_item_model_set_child_property (GooCanvasItemModel *model,
  * @child: a child #GooCanvasItemModel.
  * @var_args: pairs of property names and value pointers, and a terminating
  *  %NULL.
- *
+ * 
  * Gets the values of one or more child properties of @child.
  **/
 void
@@ -1007,7 +1016,7 @@ goo_canvas_item_model_get_child_properties_valist (GooCanvasItemModel *model,
  * @model: a #GooCanvasItemModel.
  * @child: a child #GooCanvasItemModel.
  * @var_args: pairs of property names and values, and a terminating %NULL.
- *
+ * 
  * Sets the values of one or more child properties of @child.
  **/
 void
@@ -1027,7 +1036,7 @@ goo_canvas_item_model_set_child_properties_valist (GooCanvasItemModel *model,
  * @model: a #GooCanvasItemModel.
  * @child: a child #GooCanvasItemModel.
  * @...: pairs of property names and value pointers, and a terminating %NULL.
- *
+ * 
  * Gets the values of one or more child properties of @child.
  **/
 void
@@ -1036,7 +1045,7 @@ goo_canvas_item_model_get_child_properties  (GooCanvasItemModel   *model,
 					     ...)
 {
   va_list var_args;
-
+  
   va_start (var_args, child);
   goo_canvas_item_model_get_child_properties_valist (model, child, var_args);
   va_end (var_args);
@@ -1048,7 +1057,7 @@ goo_canvas_item_model_get_child_properties  (GooCanvasItemModel   *model,
  * @model: a #GooCanvasItemModel.
  * @child: a child #GooCanvasItemModel.
  * @...: pairs of property names and values, and a terminating %NULL.
- *
+ * 
  * Sets the values of one or more child properties of @child.
  **/
 void
@@ -1057,7 +1066,7 @@ goo_canvas_item_model_set_child_properties  (GooCanvasItemModel   *model,
 					     ...)
 {
   va_list var_args;
-
+  
   va_start (var_args, child);
   goo_canvas_item_model_set_child_properties_valist (model, child, var_args);
   va_end (var_args);
@@ -1070,12 +1079,12 @@ goo_canvas_item_model_set_child_properties  (GooCanvasItemModel   *model,
  * @mclass: a #GObjectClass
  * @property_id: the id for the property
  * @pspec: the #GParamSpec for the property
- *
+ * 
  * This function is only intended to be used when implementing new canvas
  * item models, specifically layout container item models such as
  * #GooCanvasTableModel.
  *
- * It installs a child property on a canvas item class.
+ * It installs a child property on a canvas item class. 
  **/
 void
 goo_canvas_item_model_class_install_child_property (GObjectClass *mclass,
@@ -1130,7 +1139,7 @@ goo_canvas_item_model_class_find_child_property (GObjectClass *mclass,
  * goo_canvas_item_model_class_list_child_properties:
  * @mclass: a #GObjectClass
  * @n_properties: location to return the number of child properties found
- * @returns: a newly allocated array of #GParamSpec*. The array must be
+ * @returns: a newly allocated array of #GParamSpec*. The array must be 
  *           freed with g_free().
  *
  * This function is only intended to be used when implementing new canvas
diff --git a/src/goocanvas/src/goocanvasitemmodel.h b/src/goocanvas/src/goocanvasitemmodel.h
index ebdf179..c32f7ef 100644
--- a/src/goocanvas/src/goocanvasitemmodel.h
+++ b/src/goocanvas/src/goocanvasitemmodel.h
@@ -15,7 +15,6 @@ G_BEGIN_DECLS
 
 #define GOO_TYPE_CANVAS_ITEM_MODEL            (goo_canvas_item_model_get_type ())
 #define GOO_CANVAS_ITEM_MODEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_CANVAS_ITEM_MODEL, GooCanvasItemModel))
-#define GOO_CANVAS_ITEM_MODEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_CANVAS_ITEM_MODEL, GooCanvasItemModelClass))
 #define GOO_IS_CANVAS_ITEM_MODEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_CANVAS_ITEM_MODEL))
 #define GOO_CANVAS_ITEM_MODEL_GET_IFACE(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GOO_TYPE_CANVAS_ITEM_MODEL, GooCanvasItemModelIface))
 
@@ -149,7 +148,6 @@ struct _GooCanvasItemModelIface
   void (*_goo_canvas_reserved5) (void);
   void (*_goo_canvas_reserved6) (void);
   void (*_goo_canvas_reserved7) (void);
-  void (*_goo_canvas_reserved8) (void);
 };
 
 
diff --git a/src/goocanvas/src/goocanvasitemsimple.c b/src/goocanvas/src/goocanvasitemsimple.c
index ff5fbdb..46544ed 100644
--- a/src/goocanvas/src/goocanvasitemsimple.c
+++ b/src/goocanvas/src/goocanvasitemsimple.c
@@ -79,7 +79,8 @@ enum {
   PROP_DESCRIPTION,
   PROP_CAN_FOCUS,
   PROP_CLIP_PATH,
-  PROP_CLIP_FILL_RULE
+  PROP_CLIP_FILL_RULE,
+  PROP_TOOLTIP
 };
 
 static gboolean accessibility_enabled = FALSE;
@@ -287,6 +288,9 @@ goo_canvas_item_simple_install_common_properties (GObjectClass *gobject_class)
   g_object_class_override_property (gobject_class, PROP_CAN_FOCUS,
 				    "can-focus");
 
+  g_object_class_override_property (gobject_class, PROP_TOOLTIP,
+				    "tooltip");
+
   /**
    * GooCanvasItemSimple:clip-path
    *
@@ -432,27 +436,6 @@ goo_canvas_item_simple_finalize (GObject *object)
 }
 
 
-static guint
-convert_color (double red, double green, double blue, double alpha)
-{
-  guint red_byte, green_byte, blue_byte, alpha_byte;
-
-  red_byte = red * 256;
-  red_byte -= red_byte >> 8;
-
-  green_byte = green * 256;
-  green_byte -= green_byte >> 8;
-
-  blue_byte = blue * 256;
-  blue_byte -= blue_byte >> 8;
-
-  alpha_byte = alpha * 256;
-  alpha_byte -= alpha_byte >> 8;
-
-  return (red_byte << 24) + (green_byte << 16) + (blue_byte << 8) + alpha_byte;
-}
-
-
 static void
 goo_canvas_item_simple_get_common_property (GObject                 *object,
 					    GooCanvasItemSimpleData *simple_data,
@@ -465,9 +448,6 @@ goo_canvas_item_simple_get_common_property (GObject                 *object,
   GValue *svalue;
   gdouble line_width = 2.0;
   gchar *font = NULL;
-  cairo_pattern_t *pattern;
-  double red, green, blue, alpha;
-  guint rgba = 0;
 
   switch (prop_id)
     {
@@ -539,29 +519,15 @@ goo_canvas_item_simple_get_common_property (GObject                 *object,
       /* Convenience properties. */
     case PROP_STROKE_COLOR_RGBA:
       svalue = goo_canvas_style_get_property (style, goo_canvas_style_stroke_pattern_id);
-      if (svalue && svalue->data[0].v_pointer)
-	{
-	  pattern = svalue->data[0].v_pointer;
-	  if (cairo_pattern_get_type (pattern) == CAIRO_PATTERN_TYPE_SOLID)
-	    {
-	      cairo_pattern_get_rgba (pattern, &red, &green, &blue, &alpha);
-	      rgba = convert_color (red, green, blue, alpha);
-	    }
-	}
-      g_value_set_uint (value, rgba);
+      if (svalue)
+	goo_canvas_get_rgba_value_from_pattern (svalue->data[0].v_pointer,
+						value);
       break;
     case PROP_FILL_COLOR_RGBA:
       svalue = goo_canvas_style_get_property (style, goo_canvas_style_fill_pattern_id);
-      if (svalue && svalue->data[0].v_pointer)
-	{
-	  pattern = svalue->data[0].v_pointer;
-	  if (cairo_pattern_get_type (pattern) == CAIRO_PATTERN_TYPE_SOLID)
-	    {
-	      cairo_pattern_get_rgba (pattern, &red, &green, &blue, &alpha);
-	      rgba = convert_color (red, green, blue, alpha);
-	    }
-	}
-      g_value_set_uint (value, rgba);
+      if (svalue)
+	goo_canvas_get_rgba_value_from_pattern (svalue->data[0].v_pointer,
+						value);
       break;
 
       /* Other properties. */
@@ -583,6 +549,9 @@ goo_canvas_item_simple_get_common_property (GObject                 *object,
     case PROP_CLIP_FILL_RULE:
       g_value_set_enum (value, simple_data->clip_fill_rule);
       break;
+    case PROP_TOOLTIP:
+      g_value_set_string (value, simple_data->tooltip);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -630,10 +599,6 @@ goo_canvas_item_simple_set_common_property (GObject                 *object,
 					    GParamSpec              *pspec)
 {
   GooCanvasStyle *style;
-  GdkColor color = { 0, 0, 0, 0, };
-  guint rgba, red, green, blue, alpha;
-  GdkPixbuf *pixbuf;
-  cairo_surface_t *surface;
   cairo_pattern_t *pattern;
   gboolean recompute_bounds = FALSE;
   cairo_matrix_t *transform;
@@ -722,74 +687,29 @@ goo_canvas_item_simple_set_common_property (GObject                 *object,
 
       /* Convenience properties. */
     case PROP_STROKE_COLOR:
-      if (g_value_get_string (value))
-	gdk_color_parse (g_value_get_string (value), &color);
-      pattern = cairo_pattern_create_rgb (color.red / 65535.0,
-					  color.green / 65535.0,
-					  color.blue / 65535.0);
-      g_value_init (&tmpval, GOO_TYPE_CAIRO_PATTERN);
-      g_value_take_boxed (&tmpval, pattern);
-      goo_canvas_style_set_property (style, goo_canvas_style_stroke_pattern_id, &tmpval);
-      g_value_unset (&tmpval);
+      pattern = goo_canvas_create_pattern_from_color_value (value);
+      goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_stroke_pattern_id, pattern);
       break;
     case PROP_STROKE_COLOR_RGBA:
-      rgba = g_value_get_uint (value);
-      red   = (rgba >> 24) & 0xFF;
-      green = (rgba >> 16) & 0xFF;
-      blue  = (rgba >> 8)  & 0xFF;
-      alpha = (rgba)       & 0xFF;
-      pattern = cairo_pattern_create_rgba (red / 255.0, green / 255.0,
-					   blue / 255.0, alpha / 255.0);
-      g_value_init (&tmpval, GOO_TYPE_CAIRO_PATTERN);
-      g_value_take_boxed (&tmpval, pattern);
-      goo_canvas_style_set_property (style, goo_canvas_style_stroke_pattern_id, &tmpval);
-      g_value_unset (&tmpval);
+      pattern = goo_canvas_create_pattern_from_rgba_value (value);
+      goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_stroke_pattern_id, pattern);
       break;
     case PROP_STROKE_PIXBUF:
-      pixbuf = g_value_get_object (value);
-      surface = goo_canvas_cairo_surface_from_pixbuf (pixbuf);
-      pattern = cairo_pattern_create_for_surface (surface);
-      cairo_surface_destroy (surface);
-      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
-      g_value_init (&tmpval, GOO_TYPE_CAIRO_PATTERN);
-      g_value_take_boxed (&tmpval, pattern);
-      goo_canvas_style_set_property (style, goo_canvas_style_stroke_pattern_id, &tmpval);
-      g_value_unset (&tmpval);
+      pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
+      goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_stroke_pattern_id, pattern);
       break;
+
     case PROP_FILL_COLOR:
-      if (g_value_get_string (value))
-	gdk_color_parse (g_value_get_string (value), &color);
-      pattern = cairo_pattern_create_rgb (color.red / 65535.0,
-					  color.green / 65535.0,
-					  color.blue / 65535.0);
-      g_value_init (&tmpval, GOO_TYPE_CAIRO_PATTERN);
-      g_value_take_boxed (&tmpval, pattern);
-      goo_canvas_style_set_property (style, goo_canvas_style_fill_pattern_id, &tmpval);
-      g_value_unset (&tmpval);
+      pattern = goo_canvas_create_pattern_from_color_value (value);
+      goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_fill_pattern_id, pattern);
       break;
     case PROP_FILL_COLOR_RGBA:
-      rgba = g_value_get_uint (value);
-      red   = (rgba >> 24) & 0xFF;
-      green = (rgba >> 16) & 0xFF;
-      blue  = (rgba >> 8)  & 0xFF;
-      alpha = (rgba)       & 0xFF;
-      pattern = cairo_pattern_create_rgba (red / 255.0, green / 255.0,
-					   blue / 255.0, alpha / 255.0);
-      g_value_init (&tmpval, GOO_TYPE_CAIRO_PATTERN);
-      g_value_take_boxed (&tmpval, pattern);
-      goo_canvas_style_set_property (style, goo_canvas_style_fill_pattern_id, &tmpval);
-      g_value_unset (&tmpval);
+      pattern = goo_canvas_create_pattern_from_rgba_value (value);
+      goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_fill_pattern_id, pattern);
       break;
     case PROP_FILL_PIXBUF:
-      pixbuf = g_value_get_object (value);
-      surface = goo_canvas_cairo_surface_from_pixbuf (pixbuf);
-      pattern = cairo_pattern_create_for_surface (surface);
-      cairo_surface_destroy (surface);
-      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
-      g_value_init (&tmpval, GOO_TYPE_CAIRO_PATTERN);
-      g_value_take_boxed (&tmpval, pattern);
-      goo_canvas_style_set_property (style, goo_canvas_style_fill_pattern_id, &tmpval);
-      g_value_unset (&tmpval);
+      pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
+      goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_fill_pattern_id, pattern);
       break;
 
       /* Other properties. */
@@ -821,6 +741,9 @@ goo_canvas_item_simple_set_common_property (GObject                 *object,
       simple_data->clip_fill_rule = g_value_get_enum (value);
       recompute_bounds = TRUE;
       break;
+    case PROP_TOOLTIP:
+      simple_data->tooltip = g_value_dup_string (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -930,6 +853,9 @@ void
 goo_canvas_item_simple_changed    (GooCanvasItemSimple *item,
 				   gboolean             recompute_bounds)
 {
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+
   if (recompute_bounds)
     {
       item->need_entire_subtree_update = TRUE;
@@ -945,7 +871,7 @@ goo_canvas_item_simple_changed    (GooCanvasItemSimple *item,
   else
     {
       if (item->canvas)
-	goo_canvas_request_redraw (item->canvas, &item->bounds);
+	goo_canvas_request_item_redraw (item->canvas, &item->bounds, simple_data->is_static);
     }
 }
 
@@ -1151,6 +1077,27 @@ goo_canvas_item_simple_is_visible  (GooCanvasItem   *item)
 }
 
 
+static gboolean
+goo_canvas_item_simple_get_is_static  (GooCanvasItem   *item)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+
+  return simple_data->is_static;
+}
+
+
+static void
+goo_canvas_item_simple_set_is_static  (GooCanvasItem   *item,
+				       gboolean         is_static)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+
+  simple_data->is_static = is_static;
+}
+
+
 /**
  * goo_canvas_item_simple_check_style:
  * @item: a #GooCanvasItemSimple.
@@ -1258,7 +1205,7 @@ goo_canvas_item_simple_update  (GooCanvasItem   *item,
   if (entire_tree || simple->need_update)
     {
       /* Request a redraw of the existing bounds. */
-      goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+      goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
 
       cairo_save (cr);
       if (simple_data->transform)
@@ -1285,7 +1232,7 @@ goo_canvas_item_simple_update  (GooCanvasItem   *item,
       cairo_restore (cr);
 
       /* Request a redraw of the new bounds. */
-      goo_canvas_request_redraw (simple->canvas, &simple->bounds);
+      goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
     }
 
   *bounds = simple->bounds;
@@ -1302,6 +1249,9 @@ goo_canvas_item_simple_get_requested_area (GooCanvasItem    *item,
   cairo_matrix_t matrix;
   double x_offset, y_offset;
 
+  /* Request a redraw of the existing bounds. */
+  goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
+
   cairo_save (cr);
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
@@ -1370,6 +1320,7 @@ goo_canvas_item_simple_allocate_area      (GooCanvasItem         *item,
 					   gdouble                y_offset)
 {
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
 
   /* Simple items can't resize at all, so we just adjust the bounds x & y
      positions here, and let the item be clipped if necessary. */
@@ -1377,6 +1328,9 @@ goo_canvas_item_simple_allocate_area      (GooCanvasItem         *item,
   simple->bounds.y1 += y_offset;
   simple->bounds.x2 += x_offset;
   simple->bounds.y2 += y_offset;
+
+  /* Request a redraw of the new bounds. */
+  goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
 }
 
 
@@ -1542,6 +1496,26 @@ goo_canvas_item_simple_set_model_internal    (GooCanvasItem      *item,
 }
 
 
+static gboolean
+goo_canvas_item_simple_query_tooltip (GooCanvasItem  *item,
+				      gdouble         x,
+				      gdouble         y,
+				      gboolean        keyboard_tip,
+				      GtkTooltip     *tooltip)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+
+  if (simple_data->tooltip)
+    {
+      gtk_tooltip_set_markup (tooltip, simple_data->tooltip);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+
 static void
 canvas_item_interface_init (GooCanvasItemIface *iface)
 {
@@ -1562,9 +1536,13 @@ canvas_item_interface_init (GooCanvasItemIface *iface)
   iface->get_style          = goo_canvas_item_simple_get_style;
   iface->set_style          = goo_canvas_item_simple_set_style;
   iface->is_visible         = goo_canvas_item_simple_is_visible;
+  iface->get_is_static	    = goo_canvas_item_simple_get_is_static;
+  iface->set_is_static	    = goo_canvas_item_simple_set_is_static;
 
   iface->get_model          = goo_canvas_item_simple_get_model;
   iface->set_model          = goo_canvas_item_simple_set_model_internal;
+
+  iface->query_tooltip	    = goo_canvas_item_simple_query_tooltip;
 }
 
 
@@ -1692,7 +1670,8 @@ goo_canvas_item_simple_get_path_bounds (GooCanvasItemSimple *item,
  * This function is intended to be used by subclasses of #GooCanvasItemSimple,
  * typically in their update() or get_requested_area() methods.
  *
- * It converts the item's bounds to a bounding box in device space.
+ * It converts the item's bounds to a bounding box in the canvas (device)
+ * coordinate space.
  **/
 void
 goo_canvas_item_simple_user_bounds_to_device (GooCanvasItemSimple *item,
diff --git a/src/goocanvas/src/goocanvasitemsimple.h b/src/goocanvas/src/goocanvasitemsimple.h
index 73486c8..39ad00f 100644
--- a/src/goocanvas/src/goocanvasitemsimple.h
+++ b/src/goocanvas/src/goocanvasitemsimple.h
@@ -22,6 +22,7 @@ G_BEGIN_DECLS
  * @transform: the transformation matrix of the item, or %NULL.
  * @clip_path_commands: an array of #GooCanvasPathCommand specifying the clip
  *  path of the item, or %NULL.
+ * @tooltip: the item's tooltip.
  * @visibility_threshold: the threshold scale setting at which to show the item
  *  (if the @visibility setting is set to %VISIBLE_ABOVE_THRESHOLD).
  * @visibility: the #GooCanvasItemVisibility setting specifying whether the
@@ -32,6 +33,7 @@ G_BEGIN_DECLS
  * @own_style: if the item has its own style, rather than using its parent's.
  * @clip_fill_rule: the #cairo_fill_rule_t setting specifying the fill rule
  *  used for the clip path.
+ * @is_static: if the item is static.
  *
  * This is the data common to both the model and view classes.
  */
@@ -41,9 +43,6 @@ struct _GooCanvasItemSimpleData
   GooCanvasStyle *style;
   cairo_matrix_t *transform;
   GArray *clip_path_commands;
-
-  /*< private >*/
-  /* We will store tooltips here in future. */
   gchar *tooltip;
 
   /*< public >*/
@@ -53,10 +52,11 @@ struct _GooCanvasItemSimpleData
   guint can_focus                       : 1;
   guint own_style                       : 1;
   guint clip_fill_rule			: 4;
+  guint is_static			: 1;
 
   /*< private >*/
   /* We might use this in future for a cache setting - never/always/visible. */
-  guint cache_setting			: 3;
+  guint cache_setting			: 2;
   /* We might need this for tooltips in future. */
   guint has_tooltip			: 1;
 };
diff --git a/src/goocanvas/src/goocanvasmarshal.c b/src/goocanvas/src/goocanvasmarshal.c
index 18beee7..da2931f 100644
--- a/src/goocanvas/src/goocanvasmarshal.c
+++ b/src/goocanvas/src/goocanvasmarshal.c
@@ -208,3 +208,48 @@ goo_canvas_marshal_BOOLEAN__OBJECT_BOXED (GClosure     *closure,
   g_value_set_boolean (return_value, v_return);
 }
 
+/* BOOLEAN:DOUBLE,DOUBLE,BOOLEAN,OBJECT (./goocanvasmarshal.list:8) */
+void
+goo_canvas_marshal_BOOLEAN__DOUBLE_DOUBLE_BOOLEAN_OBJECT (GClosure     *closure,
+                                                          GValue       *return_value G_GNUC_UNUSED,
+                                                          guint         n_param_values,
+                                                          const GValue *param_values,
+                                                          gpointer      invocation_hint G_GNUC_UNUSED,
+                                                          gpointer      marshal_data)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__DOUBLE_DOUBLE_BOOLEAN_OBJECT) (gpointer     data1,
+                                                                          gdouble      arg_1,
+                                                                          gdouble      arg_2,
+                                                                          gboolean     arg_3,
+                                                                          gpointer     arg_4,
+                                                                          gpointer     data2);
+  register GMarshalFunc_BOOLEAN__DOUBLE_DOUBLE_BOOLEAN_OBJECT callback;
+  register GCClosure *cc = (GCClosure*) closure;
+  register gpointer data1, data2;
+  gboolean v_return;
+
+  g_return_if_fail (return_value != NULL);
+  g_return_if_fail (n_param_values == 5);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__DOUBLE_DOUBLE_BOOLEAN_OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_double (param_values + 1),
+                       g_marshal_value_peek_double (param_values + 2),
+                       g_marshal_value_peek_boolean (param_values + 3),
+                       g_marshal_value_peek_object (param_values + 4),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
diff --git a/src/goocanvas/src/goocanvasmarshal.h b/src/goocanvas/src/goocanvasmarshal.h
index 5a3a65d..fe94ec6 100644
--- a/src/goocanvas/src/goocanvasmarshal.h
+++ b/src/goocanvas/src/goocanvasmarshal.h
@@ -47,6 +47,14 @@ extern void goo_canvas_marshal_BOOLEAN__OBJECT_BOXED (GClosure     *closure,
                                                       gpointer      invocation_hint,
                                                       gpointer      marshal_data);
 
+/* BOOLEAN:DOUBLE,DOUBLE,BOOLEAN,OBJECT (./goocanvasmarshal.list:8) */
+extern void goo_canvas_marshal_BOOLEAN__DOUBLE_DOUBLE_BOOLEAN_OBJECT (GClosure     *closure,
+                                                                      GValue       *return_value,
+                                                                      guint         n_param_values,
+                                                                      const GValue *param_values,
+                                                                      gpointer      invocation_hint,
+                                                                      gpointer      marshal_data);
+
 G_END_DECLS
 
 #endif /* __goo_canvas_marshal_MARSHAL_H__ */
diff --git a/src/goocanvas/src/goocanvaspath.c b/src/goocanvas/src/goocanvaspath.c
index d6af970..0254a66 100644
--- a/src/goocanvas/src/goocanvaspath.c
+++ b/src/goocanvas/src/goocanvaspath.c
@@ -33,26 +33,21 @@
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
 #include "goocanvaspath.h"
+#include "goocanvas.h"
 
 
 enum {
   PROP_0,
 
   PROP_DATA,
+
+  PROP_X,
+  PROP_Y,
+  PROP_WIDTH,
+  PROP_HEIGHT
 };
 
 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,
@@ -76,23 +71,36 @@ goo_canvas_path_install_common_properties (GObjectClass *gobject_class)
 							_("The sequence of path commands"),
 							NULL,
 							G_PARAM_WRITABLE));
-}
-
-
-static void
-goo_canvas_path_class_init (GooCanvasPathClass *klass)
-{
-  GObjectClass *gobject_class = (GObjectClass*) klass;
-  GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) 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;
-
-  simple_class->simple_create_path = goo_canvas_path_create_path;
-
-  goo_canvas_path_install_common_properties (gobject_class);
+  g_object_class_install_property (gobject_class, PROP_X,
+				   g_param_spec_double ("x",
+							"X",
+							_("The x coordinate of the path"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_Y,
+				   g_param_spec_double ("y",
+							"Y",
+							_("The y coordinate of the path"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_WIDTH,
+				   g_param_spec_double ("width",
+							_("Width"),
+							_("The width of the path"),
+							0.0, G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_HEIGHT,
+				   g_param_spec_double ("height",
+							_("Height"),
+							_("The height of the path"),
+							0.0, G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
 }
 
 
@@ -200,16 +208,164 @@ goo_canvas_path_finalize (GObject *object)
   G_OBJECT_CLASS (goo_canvas_path_parent_class)->finalize (object);
 }
 
+static void
+goo_canvas_path_common_get_extent (GooCanvas            *canvas,
+                                   GooCanvasPathData    *path_data,
+                                   GooCanvasBounds      *bounds)
+{
+  cairo_t *cr;
+
+  cr = goo_canvas_create_cairo_context (canvas);
+  goo_canvas_create_path (path_data->path_commands, cr);
+  cairo_fill_extents (cr, &bounds->x1, &bounds->y1, &bounds->x2, &bounds->y2);
+  cairo_destroy (cr);
+}
+
+
+/* Moves all the absolute points in the command by the given amounts.
+   Relative points don't need to be moved. */
+static void
+goo_canvas_path_move_command (GooCanvasPathCommand *cmd,
+			      gdouble               x_offset,
+			      gdouble               y_offset)
+{
+  switch (cmd->simple.type)
+    {
+    case GOO_CANVAS_PATH_MOVE_TO:
+    case GOO_CANVAS_PATH_CLOSE_PATH:
+    case GOO_CANVAS_PATH_LINE_TO:
+    case GOO_CANVAS_PATH_HORIZONTAL_LINE_TO:
+    case GOO_CANVAS_PATH_VERTICAL_LINE_TO:
+      if (!cmd->simple.relative)
+        {
+          cmd->simple.x += x_offset;
+          cmd->simple.y += y_offset;
+        }
+      break;
+    case GOO_CANVAS_PATH_CURVE_TO:
+    case GOO_CANVAS_PATH_SMOOTH_CURVE_TO:
+    case GOO_CANVAS_PATH_QUADRATIC_CURVE_TO:
+    case GOO_CANVAS_PATH_SMOOTH_QUADRATIC_CURVE_TO:
+      if (!cmd->curve.relative)
+        {
+          cmd->curve.x += x_offset;
+          cmd->curve.y += y_offset;
+          cmd->curve.x1 += x_offset;
+          cmd->curve.y1 += y_offset;
+          cmd->curve.x2 += x_offset;
+          cmd->curve.y2 += y_offset;
+        }
+      break;
+    case GOO_CANVAS_PATH_ELLIPTICAL_ARC:
+      if (!cmd->arc.relative)
+        {
+          cmd->arc.x += x_offset;
+          cmd->arc.y += y_offset;
+        }
+      break;
+    default:
+      g_assert_not_reached();
+      break;
+    }
+}
+
+
+/* Scales all the points in the command by the given amounts. Absolute points
+   are scaled about the given origin. */
+static void
+goo_canvas_path_scale_command (GooCanvasPathCommand *cmd,
+			       gdouble               x_origin,
+			       gdouble               y_origin,
+			       gdouble               x_scale,
+			       gdouble               y_scale)
+{
+  switch (cmd->simple.type)
+    {
+    case GOO_CANVAS_PATH_MOVE_TO:
+    case GOO_CANVAS_PATH_CLOSE_PATH:
+    case GOO_CANVAS_PATH_LINE_TO:
+    case GOO_CANVAS_PATH_HORIZONTAL_LINE_TO:
+    case GOO_CANVAS_PATH_VERTICAL_LINE_TO:
+      if (cmd->simple.relative)
+        {
+          cmd->simple.x *= x_scale;
+          cmd->simple.y *= y_scale;
+        }
+      else
+        {
+          cmd->simple.x = x_origin + (cmd->simple.x - x_origin) * x_scale;
+          cmd->simple.y = y_origin + (cmd->simple.y - y_origin) * y_scale;
+        }
+      break;
+    case GOO_CANVAS_PATH_CURVE_TO:
+    case GOO_CANVAS_PATH_SMOOTH_CURVE_TO:
+    case GOO_CANVAS_PATH_QUADRATIC_CURVE_TO:
+    case GOO_CANVAS_PATH_SMOOTH_QUADRATIC_CURVE_TO:
+      if (cmd->curve.relative)
+        {
+          cmd->curve.x *= x_scale;
+          cmd->curve.y *= y_scale;
+          cmd->curve.x1 *= x_scale;
+          cmd->curve.y1 *= y_scale;
+          cmd->curve.x2 *= x_scale;
+          cmd->curve.y2 *= y_scale;
+        }
+      else
+        {
+          cmd->curve.x =  x_origin + (cmd->curve.x -  x_origin) * x_scale;
+          cmd->curve.y =  y_origin + (cmd->curve.y -  y_origin) * y_scale;
+          cmd->curve.x1 = x_origin + (cmd->curve.x1 - x_origin) * x_scale;
+          cmd->curve.y1 = y_origin + (cmd->curve.y1 - y_origin) * y_scale;
+          cmd->curve.x2 = x_origin + (cmd->curve.x2 - x_origin) * x_scale;
+          cmd->curve.y2 = y_origin + (cmd->curve.y2 - y_origin) * y_scale;
+        }
+      break;
+    case GOO_CANVAS_PATH_ELLIPTICAL_ARC:
+      if (cmd->arc.relative)
+        {
+          cmd->arc.x *= x_scale;
+          cmd->arc.y *= y_scale;
+        }
+      else
+        {
+          cmd->arc.x = x_origin + (cmd->arc.x - x_origin) * x_scale;
+          cmd->arc.y = y_origin + (cmd->arc.y - y_origin) * y_scale;
+        }
+      break;
+    default:
+      g_assert_not_reached();
+      break;
+  }
+}
 
 static void
 goo_canvas_path_get_common_property (GObject              *object,
+                                     GooCanvas            *canvas,
 				     GooCanvasPathData    *path_data,
 				     guint                 prop_id,
 				     GValue               *value,
 				     GParamSpec           *pspec)
 {
+  GooCanvasBounds extent;
+
   switch (prop_id)
     {
+    case PROP_X:
+      goo_canvas_path_common_get_extent (canvas, path_data, &extent);
+      g_value_set_double (value, extent.x1);
+      break;
+    case PROP_Y:
+      goo_canvas_path_common_get_extent (canvas, path_data, &extent);
+      g_value_set_double (value, extent.y1);
+      break;
+    case PROP_WIDTH:
+      goo_canvas_path_common_get_extent (canvas, path_data, &extent);
+      g_value_set_double (value, extent.x2 - extent.x1);
+      break;
+    case PROP_HEIGHT:
+      goo_canvas_path_common_get_extent (canvas, path_data, &extent);
+      g_value_set_double (value, extent.y2 - extent.y1);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -223,26 +379,113 @@ goo_canvas_path_get_property (GObject              *object,
 			      GValue               *value,
 			      GParamSpec           *pspec)
 {
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
   GooCanvasPath *path = (GooCanvasPath*) object;
 
-  goo_canvas_path_get_common_property (object, path->path_data, prop_id,
-				       value, pspec);
+  goo_canvas_path_get_common_property (object, simple->canvas,
+                                       path->path_data, prop_id, value, pspec);
 }
 
 
 static void
 goo_canvas_path_set_common_property (GObject              *object,
+                                     GooCanvas            *canvas,
 				     GooCanvasPathData    *path_data,
 				     guint                 prop_id,
 				     const GValue         *value,
 				     GParamSpec           *pspec)
 {
+  GooCanvasBounds extent;
+  GooCanvasPathCommand *cmd;
+  gdouble x_offset, y_offset, x_scale, y_scale;
+  guint i;
+
   switch (prop_id)
     {
     case PROP_DATA:
       if (path_data->path_commands)
 	g_array_free (path_data->path_commands, TRUE);
       path_data->path_commands = goo_canvas_parse_path_data (g_value_get_string (value));
+      g_object_notify (object, "x");
+      g_object_notify (object, "y");
+      g_object_notify (object, "width");
+      g_object_notify (object, "height");
+      break;
+    case PROP_X:
+      if (path_data->path_commands->len > 0)
+        {
+	  /* Calculate the x offset from the current position. */
+          goo_canvas_path_common_get_extent (canvas, path_data, &extent);
+          x_offset = g_value_get_double (value) - extent.x1;
+
+	  /* Add the offset to all the absolute x coordinates. */
+          for (i = 0; i < path_data->path_commands->len; i++)
+            {
+              cmd = &g_array_index (path_data->path_commands,
+				    GooCanvasPathCommand, i);
+              goo_canvas_path_move_command (cmd, x_offset, 0.0);
+            }
+          g_object_notify (object, "data");
+        }
+      break;
+    case PROP_Y:
+      if (path_data->path_commands->len > 0)
+        {
+	  /* Calculate the y offset from the current position. */
+          goo_canvas_path_common_get_extent (canvas, path_data, &extent);
+          y_offset = g_value_get_double (value) - extent.y1;
+
+	  /* Add the offset to all the absolute y coordinates. */
+          for (i = 0; i < path_data->path_commands->len; i++)
+            {
+              cmd = &g_array_index (path_data->path_commands,
+				    GooCanvasPathCommand, i);
+              goo_canvas_path_move_command (cmd, 0.0, y_offset);
+            }
+          g_object_notify (object, "data");
+        }
+      break;
+    case PROP_WIDTH:
+      if (path_data->path_commands->len >= 2)
+        {
+          goo_canvas_path_common_get_extent (canvas, path_data, &extent);
+          if (extent.x2 - extent.x1 != 0.0)
+            {
+	      /* Calculate the amount to scale the path. */
+              x_scale = g_value_get_double (value) / (extent.x2 - extent.x1);
+
+	      /* Scale the x coordinates, relative to the left-most point. */
+              for (i = 0; i < path_data->path_commands->len; i++)
+                {
+                  cmd = &g_array_index (path_data->path_commands,
+					GooCanvasPathCommand, i);
+                  goo_canvas_path_scale_command (cmd, extent.x1, 0.0,
+						 x_scale, 1.0);
+                }
+              g_object_notify (object, "data");
+            }
+        }
+      break;
+    case PROP_HEIGHT:
+      if (path_data->path_commands->len >= 2)
+        {
+          goo_canvas_path_common_get_extent (canvas, path_data, &extent);
+          if (extent.y2 - extent.y1 != 0.0)
+            {
+	      /* Calculate the amount to scale the polyline. */
+              y_scale = g_value_get_double (value) / (extent.y2 - extent.y1);
+
+	      /* Scale the y coordinates, relative to the top-most point. */
+              for (i = 0; i < path_data->path_commands->len; i++)
+                {
+                  cmd = &g_array_index (path_data->path_commands,
+					GooCanvasPathCommand, i);
+                  goo_canvas_path_scale_command (cmd, 0.0, extent.y1,
+						 1.0, y_scale);
+                }
+              g_object_notify (object, "data");
+            }
+        }
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -266,8 +509,8 @@ goo_canvas_path_set_property (GObject              *object,
       return;
     }
 
-  goo_canvas_path_set_common_property (object, path->path_data, prop_id,
-				       value, pspec);
+  goo_canvas_path_set_common_property (object, simple->canvas, path->path_data,
+                                       prop_id, value, pspec);
   goo_canvas_item_simple_changed (simple, TRUE);
 }
 
@@ -282,6 +525,34 @@ goo_canvas_path_create_path (GooCanvasItemSimple *simple,
 }
 
 
+static gboolean
+goo_canvas_path_is_item_at (GooCanvasItemSimple *simple,
+			    gdouble              x,
+			    gdouble              y,
+			    cairo_t             *cr,
+			    gboolean             is_pointer_event)
+{
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasPointerEvents pointer_events = GOO_CANVAS_EVENTS_ALL;
+  gboolean do_fill;
+
+  /* By default only check the fill if a fill color/pattern is specified. */
+  do_fill = goo_canvas_style_set_fill_options (simple_data->style, cr);
+  if (!do_fill)
+    pointer_events &= ~GOO_CANVAS_EVENTS_FILL_MASK;
+
+  /* If is_pointer_event is set use the pointer_events property instead. */
+  if (is_pointer_event)
+    pointer_events = simple_data->pointer_events;
+
+  goo_canvas_path_create_path (simple, cr);
+  if (goo_canvas_item_simple_check_in_path (simple, x, y, cr, pointer_events))
+    return TRUE;
+
+  return FALSE;
+}
+
+
 static void
 goo_canvas_path_set_model    (GooCanvasItem      *item,
 			      GooCanvasItemModel *model)
@@ -313,6 +584,24 @@ canvas_item_interface_init (GooCanvasItemIface *iface)
 }
 
 
+static void
+goo_canvas_path_class_init (GooCanvasPathClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass*) klass;
+  GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) 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;
+
+  simple_class->simple_create_path = goo_canvas_path_create_path;
+  simple_class->simple_is_item_at  = goo_canvas_path_is_item_at;
+
+  goo_canvas_path_install_common_properties (gobject_class);
+}
+
+
 /**
  * SECTION:goocanvaspathmodel
  * @Title: GooCanvasPathModel
@@ -478,8 +767,8 @@ goo_canvas_path_model_get_property (GObject              *object,
 {
   GooCanvasPathModel *pmodel = (GooCanvasPathModel*) object;
 
-  goo_canvas_path_get_common_property (object, &pmodel->path_data, prop_id,
-				       value, pspec);
+  goo_canvas_path_get_common_property (object, NULL, &pmodel->path_data,
+                                       prop_id, value, pspec);
 }
 
 
@@ -491,8 +780,8 @@ goo_canvas_path_model_set_property (GObject              *object,
 {
   GooCanvasPathModel *pmodel = (GooCanvasPathModel*) object;
 
-  goo_canvas_path_set_common_property (object, &pmodel->path_data, prop_id,
-				       value, pspec);
+  goo_canvas_path_set_common_property (object, NULL, &pmodel->path_data,
+                                       prop_id, value, pspec);
   g_signal_emit_by_name (pmodel, "changed", TRUE);
 }
 
diff --git a/src/goocanvas/src/goocanvaspolyline.c b/src/goocanvas/src/goocanvaspolyline.c
index c78a2b7..94fc8c4 100644
--- a/src/goocanvas/src/goocanvaspolyline.c
+++ b/src/goocanvas/src/goocanvaspolyline.c
@@ -117,20 +117,16 @@ enum {
   PROP_END_ARROW,
   PROP_ARROW_LENGTH,
   PROP_ARROW_WIDTH,
-  PROP_ARROW_TIP_LENGTH
+  PROP_ARROW_TIP_LENGTH,
+
+  PROP_X,
+  PROP_Y,
+  PROP_WIDTH,
+  PROP_HEIGHT
 };
 
 
-static void goo_canvas_polyline_finalize     (GObject            *object);
 static void canvas_item_interface_init       (GooCanvasItemIface *iface);
-static void goo_canvas_polyline_get_property (GObject            *object,
-					      guint               param_id,
-					      GValue             *value,
-					      GParamSpec         *pspec);
-static void goo_canvas_polyline_set_property (GObject            *object,
-					      guint               param_id,
-					      const GValue       *value,
-					      GParamSpec         *pspec);
 
 G_DEFINE_TYPE_WITH_CODE (GooCanvasPolyline, goo_canvas_polyline,
 			 GOO_TYPE_CANVAS_ITEM_SIMPLE,
@@ -189,6 +185,36 @@ goo_canvas_polyline_install_common_properties (GObjectClass *gobject_class)
 							_("The length of the arrow tip, as a multiple of the line width"),
 							0.0, G_MAXDOUBLE, 4.0,
 							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_X,
+				   g_param_spec_double ("x",
+							"X",
+							_("The x coordinate of the left-most point of the polyline"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_Y,
+				   g_param_spec_double ("y",
+							"Y",
+							_("The y coordinate of the top-most point of the polyline"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_WIDTH,
+				   g_param_spec_double ("width",
+							_("Width"),
+							_("The width of the polyline"),
+							0.0, G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_HEIGHT,
+				   g_param_spec_double ("height",
+							_("Height"),
+							_("The height of the polyline"),
+							0.0, G_MAXDOUBLE, 0.0,
+							G_PARAM_READWRITE));
 }
 
 
@@ -221,6 +247,32 @@ goo_canvas_polyline_finalize (GObject *object)
 
 
 static void
+goo_canvas_polyline_get_extent (GooCanvasPolylineData *polyline_data,
+                                GooCanvasBounds *bounds)
+{
+  guint i;
+
+  if (polyline_data->num_points == 0)
+    {
+      bounds->x1 = bounds->y1 = bounds->x2 = bounds->y2 = 0.0;
+    }
+  else
+    {
+      bounds->x1 = bounds->x2 = polyline_data->coords[0];
+      bounds->y1 = bounds->y2 = polyline_data->coords[1];
+
+      for (i = 1; i < polyline_data->num_points; i++)
+        {
+	  bounds->x1 = MIN (bounds->x1, polyline_data->coords[2 * i]);
+	  bounds->y1 = MIN (bounds->y1, polyline_data->coords[2 * i + 1]);
+	  bounds->x2 = MAX (bounds->x2, polyline_data->coords[2 * i]);
+	  bounds->y2 = MAX (bounds->y2, polyline_data->coords[2 * i + 1]);
+        }
+    }
+}
+
+
+static void
 goo_canvas_polyline_get_common_property (GObject              *object,
 					 GooCanvasPolylineData *polyline_data,
 					 guint                 prop_id,
@@ -228,6 +280,7 @@ goo_canvas_polyline_get_common_property (GObject              *object,
 					 GParamSpec           *pspec)
 {
   GooCanvasPoints *points;
+  GooCanvasBounds  extent;
 
   switch (prop_id)
     {
@@ -266,6 +319,22 @@ goo_canvas_polyline_get_common_property (GObject              *object,
       g_value_set_double (value, polyline_data->arrow_data
 			  ? polyline_data->arrow_data->arrow_tip_length : 4.0);
       break;
+    case PROP_X:
+      goo_canvas_polyline_get_extent (polyline_data, &extent);
+      g_value_set_double (value, extent.x1);
+      break;
+    case PROP_Y:
+      goo_canvas_polyline_get_extent (polyline_data, &extent);
+      g_value_set_double (value, extent.y1);
+      break;
+    case PROP_WIDTH:
+      goo_canvas_polyline_get_extent (polyline_data, &extent);
+      g_value_set_double (value, extent.x2 - extent.x1);
+      break;
+    case PROP_HEIGHT:
+      goo_canvas_polyline_get_extent (polyline_data, &extent);
+      g_value_set_double (value, extent.y2 - extent.y1);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -437,6 +506,9 @@ goo_canvas_polyline_set_common_property (GObject              *object,
 					 GParamSpec           *pspec)
 {
   GooCanvasPoints *points;
+  GooCanvasBounds  extent;
+  gdouble x_offset, y_offset, x_scale, y_scale;
+  guint i;
 
   switch (prop_id)
     {
@@ -461,6 +533,10 @@ goo_canvas_polyline_set_common_property (GObject              *object,
 		  polyline_data->num_points * 2 * sizeof (double));
 	}
       polyline_data->reconfigure_arrows = TRUE;
+      g_object_notify (object, "x");
+      g_object_notify (object, "y");
+      g_object_notify (object, "width");
+      g_object_notify (object, "height");
       break;
     case PROP_CLOSE_PATH:
       polyline_data->close_path = g_value_get_boolean (value);
@@ -489,6 +565,68 @@ goo_canvas_polyline_set_common_property (GObject              *object,
       polyline_data->arrow_data->arrow_tip_length = g_value_get_double (value);
       polyline_data->reconfigure_arrows = TRUE;
       break;
+    case PROP_X:
+      if (polyline_data->num_points > 0)
+        {
+	  /* Calculate the x offset from the current position. */
+          goo_canvas_polyline_get_extent (polyline_data, &extent);
+          x_offset = g_value_get_double (value) - extent.x1;
+
+	  /* Add the offset to all the x coordinates. */
+          for (i = 0; i < polyline_data->num_points; i++)
+            polyline_data->coords[2 * i] += x_offset;
+
+          g_object_notify (object, "points");
+        }
+      break;
+    case PROP_Y:
+      if (polyline_data->num_points > 0)
+        {
+	  /* Calculate the y offset from the current position. */
+          goo_canvas_polyline_get_extent (polyline_data, &extent);
+          y_offset = g_value_get_double (value) - extent.y1;
+
+	  /* Add the offset to all the y coordinates. */
+          for (i = 0; i < polyline_data->num_points; i++)
+            polyline_data->coords[2 * i + 1] += y_offset;
+
+          g_object_notify (object, "points");
+        }
+      break;
+    case PROP_WIDTH:
+      if (polyline_data->num_points >= 2)
+        {
+          goo_canvas_polyline_get_extent (polyline_data, &extent);
+          if (extent.x2 - extent.x1 != 0.0)
+            {
+	      /* Calculate the amount to scale the polyline. */
+              x_scale = g_value_get_double (value) / (extent.x2 - extent.x1);
+
+	      /* Scale the x coordinates, relative to the left-most point. */
+              for (i = 0; i < polyline_data->num_points; i++)
+                polyline_data->coords[2 * i] = extent.x1 + (polyline_data->coords[2 * i] - extent.x1) * x_scale;
+
+              g_object_notify (object, "points");
+            }
+        }
+      break;
+    case PROP_HEIGHT:
+      if (polyline_data->num_points >= 2)
+        {
+          goo_canvas_polyline_get_extent (polyline_data, &extent);
+          if (extent.y2 - extent.y1 != 0.0)
+            {
+	      /* Calculate the amount to scale the polyline. */
+              y_scale = g_value_get_double (value) / (extent.y2 - extent.y1);
+
+	      /* Scale the y coordinates, relative to the top-most point. */
+              for (i = 0; i < polyline_data->num_points; i++)
+                polyline_data->coords[2 * i + 1] = extent.y1 + (polyline_data->coords[2 * i + 1] - extent.y1) * y_scale;
+
+              g_object_notify (object, "points");
+            }
+        }
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -769,6 +907,10 @@ goo_canvas_polyline_is_item_at (GooCanvasItemSimple *simple,
   if (is_pointer_event)
     pointer_events = simple_data->pointer_events;
 
+  /* If the path isn't closed, we never check the fill. */
+  if (!(polyline_data->close_path && polyline_data->num_points > 2))
+    pointer_events &= ~GOO_CANVAS_EVENTS_FILL_MASK;
+
   goo_canvas_polyline_create_path (polyline, cr);
   if (goo_canvas_item_simple_check_in_path (simple, x, y, cr, pointer_events))
     return TRUE;
diff --git a/src/goocanvas/src/goocanvasprivate.h b/src/goocanvas/src/goocanvasprivate.h
index 3e58377..423f37e 100644
--- a/src/goocanvas/src/goocanvasprivate.h
+++ b/src/goocanvas/src/goocanvasprivate.h
@@ -8,6 +8,7 @@
 #define __GOO_CANVAS_PRIVATE_H__
 
 #include <gtk/gtk.h>
+#include "goocanvasstyle.h"
 
 G_BEGIN_DECLS
 
@@ -30,6 +31,22 @@ gint goo_canvas_util_ptr_array_find_index (GPtrArray *ptr_array,
 cairo_pattern_t* goo_canvas_cairo_pattern_from_pixbuf (GdkPixbuf *pixbuf);
 cairo_surface_t* goo_canvas_cairo_surface_from_pixbuf (GdkPixbuf *pixbuf);
 
+guint goo_canvas_convert_colors_to_rgba (double red,
+					 double green,
+					 double blue,
+					 double alpha);
+
+void goo_canvas_get_rgba_value_from_pattern (cairo_pattern_t *pattern,
+					     GValue          *value);
+
+void goo_canvas_set_style_property_from_pattern (GooCanvasStyle  *style,
+						 GQuark           property_id,
+						 cairo_pattern_t *pattern);
+
+cairo_pattern_t* goo_canvas_create_pattern_from_color_value  (const GValue *value);
+cairo_pattern_t* goo_canvas_create_pattern_from_rgba_value   (const GValue *value);
+cairo_pattern_t* goo_canvas_create_pattern_from_pixbuf_value (const GValue *value);
+
 
 gboolean goo_canvas_boolean_handled_accumulator (GSignalInvocationHint *ihint,
 						 GValue                *return_accu,
diff --git a/src/goocanvas/src/goocanvasrect.c b/src/goocanvas/src/goocanvasrect.c
index e899546..0af1021 100644
--- a/src/goocanvas/src/goocanvasrect.c
+++ b/src/goocanvas/src/goocanvasrect.c
@@ -360,7 +360,6 @@ goo_canvas_rect_create_path (GooCanvasItemSimple *simple,
       /* Draw the plain rectangle. */
       cairo_rectangle (cr, rect_data->x, rect_data->y,
 		       rect_data->width, rect_data->height);
-      cairo_close_path (cr);
     }
 }
 
diff --git a/src/goocanvas/src/goocanvastable.c b/src/goocanvas/src/goocanvastable.c
index 8ff2fe0..d20240b 100644
--- a/src/goocanvas/src/goocanvastable.c
+++ b/src/goocanvas/src/goocanvastable.c
@@ -51,6 +51,8 @@
 enum
 {
   PROP_0,
+  PROP_X,
+  PROP_Y,
   PROP_WIDTH,
   PROP_HEIGHT,
   PROP_ROW_SPACING,
@@ -164,6 +166,10 @@ struct _GooCanvasTableLayoutData
   GooCanvasTableDimensionLayoutData *dldata[2];
   GooCanvasTableChildLayoutData *children;
 
+  /* Position of the table */
+  gdouble x;
+  gdouble y;
+
   /* This is TRUE if we are rounding everything to the nearest integer. */
   gboolean integer_layout;
 
@@ -219,20 +225,11 @@ static void
 goo_canvas_table_install_common_properties (GObjectClass *gobject_class,
 					    InstallChildPropertyFunc install_child_property)
 {
-  g_object_class_install_property (gobject_class, PROP_WIDTH,
-                                   g_param_spec_double ("width",
-							_("Width"),
-							_("The requested width of the table, or -1 to use the default width"),
-							-G_MAXDOUBLE,
-							G_MAXDOUBLE, -1.0,
-							G_PARAM_READWRITE));
-  g_object_class_install_property (gobject_class, PROP_HEIGHT,
-                                   g_param_spec_double ("height",
-							_("Height"),
-							_("The requested height of the table, or -1 to use the default height"),
-							-G_MAXDOUBLE,
-							G_MAXDOUBLE, -1.0,
-							G_PARAM_READWRITE));
+  /* Override from GooCanvasGroup */
+  g_object_class_override_property (gobject_class, PROP_X, "x");
+  g_object_class_override_property (gobject_class, PROP_Y, "y");
+  g_object_class_override_property (gobject_class, PROP_WIDTH, "width");
+  g_object_class_override_property (gobject_class, PROP_HEIGHT, "height");
 
   /* FIXME: Support setting individual row/col spacing. */
   g_object_class_install_property (gobject_class, PROP_ROW_SPACING,
@@ -292,101 +289,101 @@ goo_canvas_table_install_common_properties (GObjectClass *gobject_class,
    * Child properties.
    */
   install_child_property (gobject_class, CHILD_PROP_LEFT_PADDING,
-			  g_param_spec_double ("left-padding", 
-					       _("Left Padding"), 
+			  g_param_spec_double ("left-padding",
+					       _("Left Padding"),
 					       _("Extra space to add to the left of the item"),
 					       0.0, G_MAXDOUBLE, 0.0,
 					       G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_RIGHT_PADDING,
-			  g_param_spec_double ("right-padding", 
-					       _("Right Padding"), 
+			  g_param_spec_double ("right-padding",
+					       _("Right Padding"),
 					       _("Extra space to add to the right of the item"),
 					       0.0, G_MAXDOUBLE, 0.0,
 					       G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_TOP_PADDING,
-			  g_param_spec_double ("top-padding", 
-					       _("Top Padding"), 
+			  g_param_spec_double ("top-padding",
+					       _("Top Padding"),
 					       _("Extra space to add above the item"),
 					       0.0, G_MAXDOUBLE, 0.0,
 					       G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_BOTTOM_PADDING,
-			  g_param_spec_double ("bottom-padding", 
-					       _("Bottom Padding"), 
+			  g_param_spec_double ("bottom-padding",
+					       _("Bottom Padding"),
 					       _("Extra space to add below the item"),
 					       0.0, G_MAXDOUBLE, 0.0,
 					       G_PARAM_READWRITE));
 
   install_child_property (gobject_class, CHILD_PROP_X_ALIGN,
-			  g_param_spec_double ("x-align", 
-					       _("X Align"), 
+			  g_param_spec_double ("x-align",
+					       _("X Align"),
 					       _("The horizontal position of the item within its allocated space. 0.0 is left-aligned, 1.0 is right-aligned"),
 					       0.0, 1.0, 0.5,
 					       G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_Y_ALIGN,
-			  g_param_spec_double ("y-align", 
-					       _("Y Align"), 
+			  g_param_spec_double ("y-align",
+					       _("Y Align"),
 					       _("The vertical position of the item within its allocated space. 0.0 is top-aligned, 1.0 is bottom-aligned"),
 					       0.0, 1.0, 0.5,
 					       G_PARAM_READWRITE));
 
   install_child_property (gobject_class, CHILD_PROP_ROW,
-			  g_param_spec_uint ("row", 
-					     _("Row"), 
+			  g_param_spec_uint ("row",
+					     _("Row"),
 					     _("The row to place the item in"),
 					     0, 65535, 0,
 					     G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_COLUMN,
-			  g_param_spec_uint ("column", 
-					     _("Column"), 
+			  g_param_spec_uint ("column",
+					     _("Column"),
 					     _("The column to place the item in"),
 					     0, 65535, 0,
 					     G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_ROWS,
-			  g_param_spec_uint ("rows", 
-					     _("Rows"), 
+			  g_param_spec_uint ("rows",
+					     _("Rows"),
 					     _("The number of rows that the item spans"),
 					     0, 65535, 1,
 					     G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_COLUMNS,
-			  g_param_spec_uint ("columns", 
-					     _("Columns"), 
+			  g_param_spec_uint ("columns",
+					     _("Columns"),
 					     _("The number of columns that the item spans"),
 					     0, 65535, 1,
 					     G_PARAM_READWRITE));
 
   install_child_property (gobject_class, CHILD_PROP_X_EXPAND,
-			  g_param_spec_boolean ("x-expand", 
-						_("X Expand"), 
+			  g_param_spec_boolean ("x-expand",
+						_("X Expand"),
 						_("If the item expands horizontally as the table expands"),
 						FALSE,
 						G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_X_FILL,
-			  g_param_spec_boolean ("x-fill", 
-						_("X Fill"), 
+			  g_param_spec_boolean ("x-fill",
+						_("X Fill"),
 						_("If the item fills all horizontal allocated space"),
 						FALSE,
 						G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_X_SHRINK,
-			  g_param_spec_boolean ("x-shrink", 
-						_("X Shrink"), 
+			  g_param_spec_boolean ("x-shrink",
+						_("X Shrink"),
 						_("If the item can shrink smaller than its requested size horizontally"),
 						FALSE,
 						G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_Y_EXPAND,
-			  g_param_spec_boolean ("y-expand", 
-						_("Y Expand"), 
+			  g_param_spec_boolean ("y-expand",
+						_("Y Expand"),
 						_("If the item expands vertically as the table expands"),
 						FALSE,
 						G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_Y_FILL,
-			  g_param_spec_boolean ("y-fill", 
-						_("Y Fill"), 
+			  g_param_spec_boolean ("y-fill",
+						_("Y Fill"),
 						_("If the item fills all vertical allocated space"),
 						FALSE,
 						G_PARAM_READWRITE));
   install_child_property (gobject_class, CHILD_PROP_Y_SHRINK,
-			  g_param_spec_boolean ("y-shrink", 
-						_("Y Shrink"), 
+			  g_param_spec_boolean ("y-shrink",
+						_("Y Shrink"),
 						_("If the item can shrink smaller than its requested size vertically"),
 						FALSE,
 						G_PARAM_READWRITE));
@@ -430,6 +427,9 @@ goo_canvas_table_init_data (GooCanvasTableData *table_data)
   table_data->children = g_array_new (0, 0, sizeof (GooCanvasTableChild));
 
   table_data->layout_data = g_slice_new (GooCanvasTableLayoutData);
+  table_data->layout_data->x = 0.0;
+  table_data->layout_data->y = 0.0;
+
   table_data->layout_data->children = NULL;
   for (d = 0; d < 2; d++)
     {
@@ -473,7 +473,7 @@ goo_canvas_table_init (GooCanvasTable *table)
  *  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 table item.
  *
  * <!--PARAMETERS-->
@@ -483,13 +483,13 @@ goo_canvas_table_init (GooCanvasTable *table)
  *
  * <informalexample><programlisting>
  *  GooCanvasItem *table, *square, *circle, *triangle;
- *  
+ *
  *  table = goo_canvas_table_new (root,
  *                                "row-spacing", 4.0,
  *                                "column-spacing", 4.0,
  *                                NULL);
  *  goo_canvas_item_translate (table, 400, 200);
- *  
+ *
  *  square = goo_canvas_rect_new (table, 0.0, 0.0, 50.0, 50.0,
  *                                "fill-color", "red",
  *                                NULL);
@@ -497,7 +497,7 @@ goo_canvas_table_init (GooCanvasTable *table)
  *                                        "row", 0,
  *                                        "column", 0,
  *                                        NULL);
- *  
+ *
  *  circle = goo_canvas_ellipse_new (table, 0.0, 0.0, 25.0, 25.0,
  *                                   "fill-color", "blue",
  *                                   NULL);
@@ -505,7 +505,7 @@ goo_canvas_table_init (GooCanvasTable *table)
  *                                        "row", 0,
  *                                        "column", 1,
  *                                        NULL);
- *  
+ *
  *  triangle = goo_canvas_polyline_new (table, TRUE, 3,
  *                                      25.0, 0.0, 0.0, 50.0, 50.0, 50.0,
  *                                      "fill-color", "yellow",
@@ -515,7 +515,7 @@ goo_canvas_table_init (GooCanvasTable *table)
  *                                        "column", 2,
  *                                        NULL);
  * </programlisting></informalexample>
- * 
+ *
  * Returns: a new table item.
  **/
 GooCanvasItem*
@@ -572,6 +572,12 @@ goo_canvas_table_get_common_property (GObject              *object,
 {
   switch (prop_id)
     {
+    case PROP_X:
+      g_value_set_double (value, table_data->layout_data->x);
+      break;
+    case PROP_Y:
+      g_value_set_double (value, table_data->layout_data->y);
+      break;
     case PROP_WIDTH:
       g_value_set_double (value, table_data->width);
       break;
@@ -618,7 +624,7 @@ goo_canvas_table_get_property (GObject              *object,
   GooCanvasTable *table = (GooCanvasTable*) object;
 
   goo_canvas_table_get_common_property (object, table->table_data,
-					prop_id, value, pspec);
+                                        prop_id, value, pspec);
 }
 
 
@@ -633,6 +639,12 @@ goo_canvas_table_set_common_property (GObject              *object,
 
   switch (prop_id)
     {
+    case PROP_X:
+      table_data->layout_data->x = g_value_get_double (value);
+      break;
+    case PROP_Y:
+      table_data->layout_data->y = g_value_get_double (value);
+      break;
     case PROP_WIDTH:
       table_data->width = g_value_get_double (value);
       break;
@@ -1438,7 +1450,7 @@ goo_canvas_table_size_request_pass2 (GooCanvasTable *table,
   GooCanvasTableDimensionLayoutData *dldata = layout_data->dldata[d];
   gdouble max_size = 0.0;
   gint i;
-  
+
   if (table_data->dimensions[d].homogeneous)
     {
       /* Calculate the maximum row or column size. */
@@ -1464,11 +1476,11 @@ goo_canvas_table_size_request_pass3 (GooCanvasTable *table,
   GooCanvasTableDimensionLayoutData *dldata;
   GooCanvasTableChild *child;
   gint i, j;
-  
+
   for (i = 0; i < table_data->children->len; i++)
     {
       child = &g_array_index (table_data->children, GooCanvasTableChild, i);
-      
+
       if (layout_data->children[i].requested_size[HORZ] <= 0.0)
 	continue;
 
@@ -1488,7 +1500,7 @@ goo_canvas_table_size_request_pass3 (GooCanvasTable *table,
 	      if (j < end)
 		total_space += dldata[j].spacing;
 	    }
-	      
+
 	  /* If we need to request more space for this child to fill
 	     its requisition, then divide up the needed space amongst the
 	     columns it spans, favoring expandable columns if any. */
@@ -1514,7 +1526,7 @@ goo_canvas_table_size_request_pass3 (GooCanvasTable *table,
 		  n_expand = child->size[d];
 		  force_expand = TRUE;
 		}
-		    
+
 	      if (layout_data->integer_layout)
 		{
 		  for (j = start; j <= end; j++)
@@ -1552,7 +1564,7 @@ goo_canvas_table_size_allocate_init (GooCanvasTable *table,
   GooCanvasTableDimension *dimension = &table_data->dimensions[d];
   GooCanvasTableDimensionLayoutData *dldata = layout_data->dldata[d];
   gint i;
-  
+
   /* Set the initial allocation, by copying over the requisition.
      Also set the final expand & shrink flags. */
   for (i = 0; i < dimension->size; i++)
@@ -1570,7 +1582,7 @@ goo_canvas_table_size_allocate_pass1 (GooCanvasTable *table,
   GooCanvasTableDimensionLayoutData *dldata;
   gdouble total_size, size_to_allocate, natural_size, extra, old_extra;
   gint i, nexpand, nshrink;
-  
+
   /* If we were allocated more space than we requested
    *  then we have to expand any expandable rows and columns
    *  to fill in the extra space.
@@ -1620,7 +1632,7 @@ goo_canvas_table_size_allocate_pass1 (GooCanvasTable *table,
 	  size_to_allocate = total_size;
 	  for (i = 0; i + 1 < dimension->size; i++)
 	    size_to_allocate -= dldata[i].spacing;
-	  
+
 	  if (layout_data->integer_layout)
 	    {
 	      gint n_elements = dimension->size;
@@ -1669,14 +1681,14 @@ goo_canvas_table_size_allocate_pass1 (GooCanvasTable *table,
 		}
 	    }
 	}
-	  
+
       /* Check to see if we were allocated less width than we requested,
        * then shrink until we fit the size give.
        */
       if (natural_size > total_size)
 	{
 	  gint total_nshrink = nshrink;
-	      
+
 	  extra = natural_size - total_size;
 	  while (total_nshrink > 0 && extra > 0)
 	    {
@@ -1778,7 +1790,7 @@ goo_canvas_table_size_allocate_pass3 (GooCanvasTable *table,
 
       if (requested_width <= 0.0)
 	continue;
-      
+
       start_column = child->start[HORZ];
       end_column = child->start[HORZ] + child->size[HORZ] - 1;
       x = columns[start_column].start + layout_data->children[i].start_pad[HORZ];
@@ -1800,7 +1812,7 @@ goo_canvas_table_size_allocate_pass3 (GooCanvasTable *table,
 	  if (layout_data->integer_layout)
 	    x = floor (x + 0.5);
 	}
-	  
+
       if (!(child->flags[VERT] & GOO_CANVAS_TABLE_CHILD_FILL))
 	{
 	  height = MIN (max_height, requested_height);
@@ -1929,11 +1941,14 @@ goo_canvas_table_get_requested_area (GooCanvasItem        *item,
   GooCanvasItemSimpleData *simple_data = simple->simple_data;
   GooCanvasTable *table = (GooCanvasTable*) item;
   GooCanvasTableData *table_data = table->table_data;
-  GooCanvasTableLayoutData *layout_data;
+  GooCanvasTableLayoutData *layout_data = table_data->layout_data;
   GooCanvasTableDimensionLayoutData *rows, *columns;
   gdouble width = 0.0, height = 0.0;
   gint row, column, end;
-  
+
+  /* Request a redraw of the existing bounds */
+  goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
+
   /* We reset the bounds to 0, just in case we are hidden or aren't allocated
      any area. */
   simple->bounds.x1 = simple->bounds.x2 = 0.0;
@@ -1950,6 +1965,8 @@ goo_canvas_table_get_requested_area (GooCanvasItem        *item,
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
 
+  cairo_translate (cr, layout_data->x, layout_data->y);
+
   /* Initialize the layout data, get the requested sizes of all children, and
      set the expand, shrink and empty flags. */
   goo_canvas_table_init_layout_data (table);
@@ -1961,7 +1978,6 @@ goo_canvas_table_get_requested_area (GooCanvasItem        *item,
   goo_canvas_table_size_request_pass3 (table, HORZ);
   goo_canvas_table_size_request_pass2 (table, HORZ);
 
-  layout_data = table_data->layout_data;
   rows = layout_data->dldata[VERT];
   columns = layout_data->dldata[HORZ];
 
@@ -1973,7 +1989,7 @@ goo_canvas_table_get_requested_area (GooCanvasItem        *item,
 	width += columns[column].spacing;
     }
   width += (layout_data->border_width + layout_data->border_spacing[HORZ] + layout_data->grid_line_width[VERT]) * 2.0;
-  
+
   /* Save the natural size, so we know if we have to clip children. */
   layout_data->natural_size[HORZ] = width;
 
@@ -2046,6 +2062,8 @@ goo_canvas_table_get_requested_height (GooCanvasItem    *item,
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
 
+  cairo_translate (cr, layout_data->x, layout_data->y);
+
   /* Convert the width from the parent's coordinate space. Note that we only
      need to support a simple scale operation here. */
   if (simple_data->transform)
@@ -2129,12 +2147,14 @@ goo_canvas_table_allocate_area (GooCanvasItem         *item,
 		   -(allocated_area->y1 - requested_area->y1));
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
+  cairo_translate (cr, layout_data->x, layout_data->y);
   goo_canvas_table_update_requested_heights (item, cr);
   cairo_restore (cr);
 
   cairo_save (cr);
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
+  cairo_translate (cr, layout_data->x, layout_data->y);
 
   /* Calculate the table's bounds. */
   simple->bounds.x1 = simple->bounds.y1 = 0.0;
@@ -2154,6 +2174,8 @@ goo_canvas_table_allocate_area (GooCanvasItem         *item,
   layout_data->children = NULL;
 
   cairo_restore (cr);
+
+  goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
 }
 
 
@@ -2193,6 +2215,7 @@ goo_canvas_table_paint (GooCanvasItem         *item,
 {
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
   GooCanvasItemSimpleData *simple_data = simple->simple_data;
+  GooCanvasStyle *style = simple_data->style;
   GooCanvasGroup *group = (GooCanvasGroup*) item;
   GooCanvasTable *table = (GooCanvasTable*) item;
   GooCanvasTableData *table_data = table->table_data;
@@ -2210,7 +2233,8 @@ goo_canvas_table_paint (GooCanvasItem         *item,
   gdouble frame_width, frame_height;
   gdouble line_start, line_end;
   gdouble spacing, half_spacing_before, half_spacing_after;
-  gboolean old_grid_line_visibility = FALSE, cur_grid_line_visibility;
+  gboolean old_grid_line_visibility = FALSE;
+  gboolean cur_grid_line_visibility;
 
   /* Skip the item if the bounds don't intersect the expose rectangle. */
   if (simple->bounds.x1 > bounds->x2 || simple->bounds.x2 < bounds->x1
@@ -2227,6 +2251,7 @@ goo_canvas_table_paint (GooCanvasItem         *item,
   cairo_save (cr);
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
+  cairo_translate (cr, layout_data->x, layout_data->y);
 
   /* Clip with the table's clip path, if it is set. */
   if (simple_data->clip_path_commands)
@@ -2249,10 +2274,6 @@ goo_canvas_table_paint (GooCanvasItem         *item,
   frame_width = MAX (layout_data->allocated_size[HORZ], layout_data->natural_size[HORZ]);
   frame_height = MAX (layout_data->allocated_size[VERT], layout_data->natural_size[VERT]);
 
-  /* Save current line width, line cap etc. for drawing items after having
-     drawn grid lines */
-  cairo_save (cr);
-
   /* Draw border and grid lines */
   if (check_clip)
     {
@@ -2264,7 +2285,26 @@ goo_canvas_table_paint (GooCanvasItem         *item,
       cairo_clip (cr);
     }
 
-  cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
+  /* Save current line width, line cap etc. for drawing items after having
+     drawn grid lines */
+  cairo_save (cr);
+
+  /* Fill the table, if desired. */
+  if (goo_canvas_style_set_fill_options (style, cr))
+    {
+      cairo_rectangle (cr,
+                       layout_data->border_width + vert_grid_line_width,
+                       layout_data->border_width + horz_grid_line_width,
+                       layout_data->allocated_size[HORZ] - 2 * (layout_data->border_width + vert_grid_line_width),
+                       layout_data->allocated_size[VERT] - 2 * (layout_data->border_width + horz_grid_line_width));
+      cairo_fill (cr);
+    }
+
+  /* We use the style for the stroke color, but the line cap style and line
+     width are overridden here. */
+  goo_canvas_style_set_stroke_options (style, cr);
+
+  cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
 
   /* Horizontal grid lines */
   if (horz_grid_line_width > 0.0)
@@ -2320,7 +2360,7 @@ goo_canvas_table_paint (GooCanvasItem         *item,
               old_grid_line_visibility = cur_grid_line_visibility;
             }
         }
-      
+
       cairo_stroke (cr);
     }
 
@@ -2444,7 +2484,7 @@ goo_canvas_table_paint (GooCanvasItem         *item,
 	  for (j = start_row; j <= end_row; j++)
 	    if (rows[j].shrink)
 	      clip = TRUE;
-			 
+
 	  /* Only clip the child if it may have been shrunk. */
 	  if (clip)
 	    {
@@ -2515,6 +2555,7 @@ goo_canvas_table_get_items_at (GooCanvasItem  *item,
   cairo_save (cr);
   if (simple_data->transform)
     cairo_transform (cr, simple_data->transform);
+  cairo_translate (cr, layout_data->x, layout_data->y);
 
   cairo_device_to_user (cr, &user_x, &user_y);
 
@@ -2730,7 +2771,7 @@ goo_canvas_table_model_init (GooCanvasTableModel *tmodel)
  *  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 table model.
  *
  * <!--PARAMETERS-->
@@ -2772,7 +2813,7 @@ goo_canvas_table_model_init (GooCanvasTableModel *tmodel)
  *                                              "column", 2,
  *                                              NULL);
  * </programlisting></informalexample>
- * 
+ *
  * Returns: a new table model.
  **/
 GooCanvasItemModel*
diff --git a/src/goocanvas/src/goocanvastext.c b/src/goocanvas/src/goocanvastext.c
index 9a245cd..5b100ae 100644
--- a/src/goocanvas/src/goocanvastext.c
+++ b/src/goocanvas/src/goocanvastext.c
@@ -19,6 +19,10 @@
  * #GooCanvasItem functions such as goo_canvas_item_raise() and
  * goo_canvas_item_rotate().
  *
+ * The #GooCanvasText:width and #GooCanvasText:height properties specify the
+ * area of the item. If it exceeds that area because there is too much text,
+ * it is clipped. The properties can be set to -1 to disable clipping.
+ *
  * To create a #GooCanvasText use goo_canvas_text_new().
  *
  * To get or set the properties of an existing #GooCanvasText, use
@@ -30,6 +34,15 @@
 #include "goocanvastext.h"
 #include "goocanvas.h"
 
+typedef struct _GooCanvasTextPrivate GooCanvasTextPrivate;
+struct _GooCanvasTextPrivate {
+  gdouble height;
+};
+
+#define GOO_CANVAS_TEXT_GET_PRIVATE(text) \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((text), GOO_TYPE_CANVAS_TEXT, GooCanvasTextPrivate))
+#define GOO_CANVAS_TEXT_MODEL_GET_PRIVATE(text) \
+   (G_TYPE_INSTANCE_GET_PRIVATE ((text), GOO_TYPE_CANVAS_TEXT_MODEL, GooCanvasTextPrivate))
 
 enum {
   PROP_0,
@@ -37,6 +50,7 @@ enum {
   PROP_X,
   PROP_Y,
   PROP_WIDTH,
+  PROP_HEIGHT,
   PROP_TEXT,
   PROP_USE_MARKUP,
   PROP_ANCHOR,
@@ -45,6 +59,15 @@ enum {
   PROP_WRAP
 };
 
+static PangoLayout*
+goo_canvas_text_create_layout (GooCanvasItemSimpleData *simple_data,
+			       GooCanvasTextData       *text_data,
+			       gdouble                  layout_width,
+			       cairo_t                 *cr,
+			       GooCanvasBounds         *bounds,
+			       gdouble	               *origin_x_return,
+			       gdouble	               *origin_y_return);
+
 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,
@@ -121,6 +144,15 @@ goo_canvas_text_install_common_properties (GObjectClass *gobject_class)
 							G_MAXDOUBLE, -1.0,
 							G_PARAM_READWRITE));
 
+  g_object_class_install_property (gobject_class, PROP_HEIGHT,
+				   g_param_spec_double ("height",
+							_("Height"),
+							_("The height to use to layout the text, or -1 to use the natural height"),
+							-G_MAXDOUBLE,
+							G_MAXDOUBLE, -1.0,
+							G_PARAM_READWRITE));
+
+
   g_object_class_install_property (gobject_class, PROP_ANCHOR,
 				   g_param_spec_enum ("anchor",
 						      _("Anchor"),
@@ -142,6 +174,8 @@ goo_canvas_text_install_common_properties (GObjectClass *gobject_class)
 static void
 goo_canvas_text_init (GooCanvasText *text)
 {
+  GooCanvasTextPrivate *priv = GOO_CANVAS_TEXT_GET_PRIVATE (text);
+
   text->text_data = g_slice_new0 (GooCanvasTextData);
   text->text_data->width = -1.0;
   text->text_data->anchor = GTK_ANCHOR_NW;
@@ -149,6 +183,8 @@ goo_canvas_text_init (GooCanvasText *text)
   text->text_data->wrap = PANGO_WRAP_WORD;
 
   text->layout_width = -1.0;
+
+  priv->height = -1.0;
 }
 
 
@@ -243,9 +279,23 @@ goo_canvas_text_finalize (GObject *object)
 }
 
 
+/* Gets the private data to use, from the model or from the item itself. */
+static GooCanvasTextPrivate*
+goo_canvas_text_get_private (GooCanvasText *text)
+{
+  GooCanvasItemSimple *simple = (GooCanvasItemSimple*) text;
+
+  if (simple->model)
+    return GOO_CANVAS_TEXT_MODEL_GET_PRIVATE (simple->model);
+  else
+    return GOO_CANVAS_TEXT_GET_PRIVATE (text);
+}
+
+
 static void
 goo_canvas_text_get_common_property (GObject                 *object,
 				     GooCanvasTextData       *text_data,
+				     GooCanvasTextPrivate    *priv,
 				     guint                    prop_id,
 				     GValue                  *value,
 				     GParamSpec              *pspec)
@@ -261,6 +311,9 @@ goo_canvas_text_get_common_property (GObject                 *object,
     case PROP_WIDTH:
       g_value_set_double (value, text_data->width);
       break;
+    case PROP_HEIGHT:
+      g_value_set_double (value, priv->height);
+      break;
     case PROP_TEXT:
       g_value_set_string (value, text_data->text);
       break;
@@ -293,15 +346,17 @@ goo_canvas_text_get_property (GObject              *object,
 			      GParamSpec           *pspec)
 {
   GooCanvasText *text = (GooCanvasText*) object;
+  GooCanvasTextPrivate *priv = goo_canvas_text_get_private (text);
 
-  goo_canvas_text_get_common_property (object, text->text_data, prop_id,
-				       value, pspec);
+  goo_canvas_text_get_common_property (object, text->text_data, priv,
+                                       prop_id, value, pspec);
 }
 
 
 static void
 goo_canvas_text_set_common_property (GObject                 *object,
 				     GooCanvasTextData       *text_data,
+				     GooCanvasTextPrivate    *priv,
 				     guint                    prop_id,
 				     const GValue            *value,
 				     GParamSpec              *pspec)
@@ -317,6 +372,9 @@ goo_canvas_text_set_common_property (GObject                 *object,
     case PROP_WIDTH:
       text_data->width = g_value_get_double (value);
       break;
+    case PROP_HEIGHT:
+      priv->height = g_value_get_double (value);
+      break;
     case PROP_TEXT:
       g_free (text_data->text);
       text_data->text = g_value_dup_string (value);
@@ -351,6 +409,7 @@ goo_canvas_text_set_property (GObject              *object,
 {
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
   GooCanvasText *text = (GooCanvasText*) object;
+  GooCanvasTextPrivate *priv = goo_canvas_text_get_private (text);
 
   if (simple->model)
     {
@@ -358,7 +417,7 @@ goo_canvas_text_set_property (GObject              *object,
       return;
     }
 
-  goo_canvas_text_set_common_property (object, text->text_data, prop_id,
+  goo_canvas_text_set_common_property (object, text->text_data, priv, prop_id,
 				       value, pspec);
   goo_canvas_item_simple_changed (simple, TRUE);
 }
@@ -409,7 +468,6 @@ goo_canvas_text_create_layout (GooCanvasItemSimpleData *simple_data,
 
   font_options = cairo_font_options_create ();
   cairo_font_options_set_hint_metrics (font_options, hint_metrics);
-  cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
   pango_cairo_context_set_font_options (context, font_options);
   cairo_font_options_destroy (font_options);
 
@@ -501,8 +559,8 @@ goo_canvas_text_create_layout (GooCanvasItemSimpleData *simple_data,
 	    }
 	}
 
-      bounds->x2 = origin_x + logical_width;
-      bounds->y2 = origin_y + logical_height;
+      bounds->x2 = bounds->x1 + logical_width;
+      bounds->y2 = bounds->y1 + logical_height;
 
       /* Now adjust it to take into account the ink bounds. Calculate how far
 	 the ink rect extends outside each edge of the logical rect and adjust
@@ -535,6 +593,7 @@ goo_canvas_text_update  (GooCanvasItemSimple *simple,
 			 cairo_t             *cr)
 {
   GooCanvasText *text = (GooCanvasText*) simple;
+  GooCanvasTextPrivate *priv = goo_canvas_text_get_private (text);
   PangoLayout *layout;
 
   /* Initialize the layout width to the text item's specified width property.
@@ -547,6 +606,10 @@ goo_canvas_text_update  (GooCanvasItemSimple *simple,
 					  text->layout_width, cr,
 					  &simple->bounds, NULL, NULL);
   g_object_unref (layout);
+
+  /* If the height is set, use that. */
+  if (priv->height > 0.0)
+    simple->bounds.y2 = simple->bounds.y1 + priv->height;
 }
 
 
@@ -574,6 +637,7 @@ goo_canvas_text_is_item_at (GooCanvasItemSimple *simple,
 {
   GooCanvasItemSimpleData *simple_data = simple->simple_data;
   GooCanvasText *text = (GooCanvasText*) simple;
+  GooCanvasTextPrivate *priv = goo_canvas_text_get_private (text);
   PangoLayout *layout;
   GooCanvasBounds bounds;
   PangoLayoutIter *iter;
@@ -592,6 +656,10 @@ goo_canvas_text_is_item_at (GooCanvasItemSimple *simple,
       && goo_canvas_text_is_unpainted (simple_data->style))
     return FALSE;
 
+  /* Check if the point is outside the clipped height. */
+  if (priv->height > 0.0 && y > priv->height)
+    return FALSE;
+
   layout = goo_canvas_text_create_layout (simple_data, text->text_data,
 					  text->layout_width, cr, &bounds,
 					  &origin_x, &origin_y);
@@ -644,6 +712,7 @@ goo_canvas_text_paint (GooCanvasItemSimple   *simple,
 		       const GooCanvasBounds *bounds)
 {
   GooCanvasText *text = (GooCanvasText*) simple;
+  GooCanvasTextPrivate *priv = goo_canvas_text_get_private (text);
   PangoLayout *layout;
   GooCanvasBounds layout_bounds;
   gdouble origin_x, origin_y;
@@ -659,8 +728,18 @@ goo_canvas_text_paint (GooCanvasItemSimple   *simple,
 					  text->layout_width, cr,
 					  &layout_bounds,
 					  &origin_x, &origin_y);
+  cairo_save (cr);
+
+  if (priv->height > 0.0)
+    {
+      cairo_rectangle (cr, origin_x, origin_y,
+		       text->layout_width, priv->height);
+      cairo_clip (cr);
+    }
   cairo_move_to (cr, origin_x, origin_y);
   pango_cairo_show_layout (cr, layout);
+
+  cairo_restore (cr);
   g_object_unref (layout);
 }
 
@@ -673,6 +752,7 @@ goo_canvas_text_get_requested_height (GooCanvasItem	*item,
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
   GooCanvasItemSimpleData *simple_data = simple->simple_data;
   GooCanvasText *text = (GooCanvasText*) item;
+  GooCanvasTextPrivate *priv = goo_canvas_text_get_private (text);
   PangoLayout *layout;
   gdouble height;
 
@@ -693,15 +773,23 @@ goo_canvas_text_get_requested_height (GooCanvasItem	*item,
   if (simple_data->transform)
     text->layout_width /= simple_data->transform->xx;
 
-  /* Create layout with given width. */
-  layout = goo_canvas_text_create_layout (simple_data, text->text_data,
-					  text->layout_width, cr,
-					  &simple->bounds, NULL, NULL);
-  g_object_unref (layout);
+  if (priv->height < 0.0)
+    {
+     /* Create layout with given width. */
+      layout = goo_canvas_text_create_layout (simple_data, text->text_data,
+					      text->layout_width, cr,
+					      &simple->bounds, NULL, NULL);
+      g_object_unref (layout);
+
+      height = simple->bounds.y2 - simple->bounds.y1;
+    }
+  else
+    {
+      height = priv->height;
+    }
 
-  /* Convert to the parent's coordinate space. As above,  we only need to
+  /* Convert to the parent's coordinate space. As above, we only need to
      support a simple scale operation here. */
-  height = simple->bounds.y2 - simple->bounds.y1;
   if (simple_data->transform)
     height *= simple_data->transform->yy;
 
@@ -783,6 +871,8 @@ goo_canvas_text_class_init (GooCanvasTextClass *klass)
   GObjectClass *gobject_class = (GObjectClass*) klass;
   GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) klass;
 
+  g_type_class_add_private (gobject_class, sizeof (GooCanvasTextPrivate));
+
   gobject_class->finalize = goo_canvas_text_finalize;
 
   gobject_class->get_property = goo_canvas_text_get_property;
@@ -843,6 +933,8 @@ goo_canvas_text_model_class_init (GooCanvasTextModelClass *klass)
 {
   GObjectClass *gobject_class = (GObjectClass*) klass;
 
+  g_type_class_add_private (gobject_class, sizeof (GooCanvasTextPrivate));
+
   gobject_class->finalize     = goo_canvas_text_model_finalize;
 
   gobject_class->get_property = goo_canvas_text_model_get_property;
@@ -855,10 +947,14 @@ goo_canvas_text_model_class_init (GooCanvasTextModelClass *klass)
 static void
 goo_canvas_text_model_init (GooCanvasTextModel *tmodel)
 {
+  GooCanvasTextPrivate *priv = GOO_CANVAS_TEXT_MODEL_GET_PRIVATE (tmodel);
+
   tmodel->text_data.width = -1.0;
   tmodel->text_data.anchor = GTK_ANCHOR_NW;
   tmodel->text_data.ellipsize = PANGO_ELLIPSIZE_NONE;
   tmodel->text_data.wrap = PANGO_WRAP_WORD;
+
+  priv->height = -1.0;
 }
 
 
@@ -952,9 +1048,10 @@ goo_canvas_text_model_get_property (GObject              *object,
 				    GParamSpec           *pspec)
 {
   GooCanvasTextModel *tmodel = (GooCanvasTextModel*) object;
+  GooCanvasTextPrivate *priv = GOO_CANVAS_TEXT_MODEL_GET_PRIVATE (tmodel);
 
-  goo_canvas_text_get_common_property (object, &tmodel->text_data, prop_id,
-				       value, pspec);
+  goo_canvas_text_get_common_property (object, &tmodel->text_data, priv,
+				       prop_id, value, pspec);
 }
 
 
@@ -965,9 +1062,10 @@ goo_canvas_text_model_set_property (GObject              *object,
 				    GParamSpec           *pspec)
 {
   GooCanvasTextModel *tmodel = (GooCanvasTextModel*) object;
+  GooCanvasTextPrivate *priv = GOO_CANVAS_TEXT_MODEL_GET_PRIVATE (tmodel);
 
-  goo_canvas_text_set_common_property (object, &tmodel->text_data, prop_id,
-				       value, pspec);
+  goo_canvas_text_set_common_property (object, &tmodel->text_data, priv,
+				       prop_id, value, pspec);
   g_signal_emit_by_name (tmodel, "changed", TRUE);
 }
 
diff --git a/src/goocanvas/src/goocanvasutils.c b/src/goocanvas/src/goocanvasutils.c
index 3b14387..ca07559 100644
--- a/src/goocanvas/src/goocanvasutils.c
+++ b/src/goocanvas/src/goocanvasutils.c
@@ -366,7 +366,7 @@ goo_canvas_line_dash_get_type (void)
   
   if (cairo_line_dash_type == 0)
     cairo_line_dash_type = g_boxed_type_register_static
-      ("GooCairoLineDash",
+      ("GooCanvasLineDash",
        (GBoxedCopyFunc) goo_canvas_line_dash_ref,
        (GBoxedFreeFunc) goo_canvas_line_dash_unref);
 
@@ -1192,3 +1192,103 @@ goo_canvas_bounds_get_type (void)
 }
 
 
+/* Converts red, green, blue and alpha doubles to an RGBA guint. */
+guint
+goo_canvas_convert_colors_to_rgba (double red,
+				   double green,
+				   double blue,
+				   double alpha)
+{
+  guint red_byte, green_byte, blue_byte, alpha_byte;
+
+  red_byte = red * 256;
+  red_byte -= red_byte >> 8;
+
+  green_byte = green * 256;
+  green_byte -= green_byte >> 8;
+
+  blue_byte = blue * 256;
+  blue_byte -= blue_byte >> 8;
+
+  alpha_byte = alpha * 256;
+  alpha_byte -= alpha_byte >> 8;
+
+  return (red_byte << 24) + (green_byte << 16) + (blue_byte << 8) + alpha_byte;
+}
+
+
+void
+goo_canvas_get_rgba_value_from_pattern (cairo_pattern_t *pattern,
+					GValue          *value)
+{
+  double red, green, blue, alpha;
+  guint rgba = 0;
+
+  if (pattern && cairo_pattern_get_type (pattern) == CAIRO_PATTERN_TYPE_SOLID)
+    {
+      cairo_pattern_get_rgba (pattern, &red, &green, &blue, &alpha);
+      rgba = goo_canvas_convert_colors_to_rgba (red, green, blue, alpha);
+    }
+  g_value_set_uint (value, rgba);
+}
+
+
+/* Sets a style property to the given pattern, taking ownership of it. */
+void
+goo_canvas_set_style_property_from_pattern (GooCanvasStyle  *style,
+					    GQuark           property_id,
+					    cairo_pattern_t *pattern)
+{
+  GValue tmpval = { 0 };
+
+  g_value_init (&tmpval, GOO_TYPE_CAIRO_PATTERN);
+  g_value_take_boxed (&tmpval, pattern);
+  goo_canvas_style_set_property (style, property_id, &tmpval);
+  g_value_unset (&tmpval);
+}
+
+
+cairo_pattern_t*
+goo_canvas_create_pattern_from_color_value (const GValue *value)
+{
+  GdkColor color = { 0, 0, 0, 0, };
+
+  if (g_value_get_string (value))
+    gdk_color_parse (g_value_get_string (value), &color);
+
+  return cairo_pattern_create_rgb (color.red / 65535.0,
+				   color.green / 65535.0,
+				   color.blue / 65535.0);
+}
+  
+
+cairo_pattern_t*
+goo_canvas_create_pattern_from_rgba_value (const GValue *value)
+{
+  guint rgba, red, green, blue, alpha;
+
+  rgba = g_value_get_uint (value);
+  red   = (rgba >> 24) & 0xFF;
+  green = (rgba >> 16) & 0xFF;
+  blue  = (rgba >> 8)  & 0xFF;
+  alpha = (rgba)       & 0xFF;
+
+  return cairo_pattern_create_rgba (red / 255.0, green / 255.0,
+				    blue / 255.0, alpha / 255.0);
+}
+
+
+cairo_pattern_t*
+goo_canvas_create_pattern_from_pixbuf_value (const GValue *value)
+{
+  GdkPixbuf *pixbuf;
+  cairo_surface_t *surface;
+  cairo_pattern_t *pattern;
+
+  pixbuf = g_value_get_object (value);
+  surface = goo_canvas_cairo_surface_from_pixbuf (pixbuf);
+  pattern = cairo_pattern_create_for_surface (surface);
+  cairo_surface_destroy (surface);
+  cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+  return pattern;
+}
diff --git a/src/goocanvas/src/goocanvasutils.h b/src/goocanvas/src/goocanvasutils.h
index fa1ce93..7f158d4 100644
--- a/src/goocanvas/src/goocanvasutils.h
+++ b/src/goocanvas/src/goocanvasutils.h
@@ -86,7 +86,7 @@ typedef enum
   GOO_CANVAS_ITEM_HIDDEN			= 0,
   GOO_CANVAS_ITEM_INVISIBLE			= 1,
   GOO_CANVAS_ITEM_VISIBLE			= 2,
-  GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD	= 3,
+  GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD	= 3
 } GooCanvasItemVisibility;
 
 
@@ -206,6 +206,92 @@ struct _GooCanvasLineDash
   double dash_offset;
 };
 
+
+/* These are here so we can document the cairo type wrappers - don't use. */
+#if 0
+typedef cairo_antialias_t	GooCairoAntialias;
+typedef cairo_fill_rule_t	GooCairoFillRule;
+typedef cairo_hint_metrics_t	GooCairoHintMetrics;
+typedef cairo_line_cap_t	GooCairoLineCap;
+typedef cairo_line_join_t	GooCairoLineJoin;
+typedef cairo_operator_t	GooCairoOperator;
+typedef cairo_matrix_t		GooCairoMatrix;
+typedef cairo_pattern_t		GooCairoPattern;
+#endif
+
+/**
+ * GooCairoAntialias
+ *
+ * #GooCairoAntialias is simply a wrapper for the #cairo_antialias_t type,
+ * allowing it to be used for #GObject properties.
+ *
+ * See the #cairo_antialias_t documentation.
+ */
+
+/**
+ * GooCairoFillRule
+ *
+ * #GooCairoFillRule is simply a wrapper for the #cairo_fill_rule_t type,
+ * allowing it to be used for #GObject properties.
+ *
+ * See the #cairo_fill_rule_t documentation.
+ */
+
+/**
+ * GooCairoHintMetrics
+ *
+ * #GooCairoHintMetrics is simply a wrapper for the #cairo_hint_metrics_t type,
+ * allowing it to be used for #GObject properties.
+ *
+ * See the #cairo_hint_metrics_t documentation.
+ */
+
+/**
+ * GooCairoLineCap
+ *
+ * #GooCairoLineCap is simply a wrapper for the #cairo_line_cap_t type,
+ * allowing it to be used for #GObject properties.
+ *
+ * See the #cairo_line_cap_t documentation.
+ */
+
+/**
+ * GooCairoLineJoin
+ *
+ * #GooCairoLineJoin is simply a wrapper for the #cairo_line_join_t type,
+ * allowing it to be used for #GObject properties.
+ *
+ * See the #cairo_line_join_t documentation.
+ */
+
+/**
+ * GooCairoOperator
+ *
+ * #GooCairoOperator is simply a wrapper for the #cairo_operator_t type,
+ * allowing it to be used for #GObject properties.
+ *
+ * See the #cairo_operator_t documentation.
+ */
+
+/**
+ * GooCairoMatrix
+ *
+ * #GooCairoMatrix is simply a wrapper for the #cairo_matrix_t type,
+ * allowing it to be used for #GObject properties.
+ *
+ * See the #cairo_matrix_t documentation.
+ */
+
+/**
+ * GooCairoPattern
+ *
+ * #GooCairoPattern is simply a wrapper for the #cairo_pattern_t type,
+ * allowing it to be used for #GObject properties.
+ *
+ * See the #cairo_pattern_t documentation.
+ */
+
+
 #define GOO_TYPE_CANVAS_LINE_DASH  (goo_canvas_line_dash_get_type ())
 GType              goo_canvas_line_dash_get_type (void) G_GNUC_CONST;
 GooCanvasLineDash* goo_canvas_line_dash_new   (gint               num_dashes,
diff --git a/src/goocanvas/src/goocanvaswidget.c b/src/goocanvas/src/goocanvaswidget.c
index 974892f..e8ddacc 100644
--- a/src/goocanvas/src/goocanvaswidget.c
+++ b/src/goocanvas/src/goocanvaswidget.c
@@ -12,6 +12,10 @@
  *
  * GooCanvasWidget provides support for placing any GtkWidget in the canvas.
  *
+ * The #GooCanvasWidget:width and #GooCanvasWidget:height properties specify
+ * the widget's size. If either of them is -1, then the requested size of the
+ * widget is used instead, which is the default for both width and height.
+ *
  * Note that there are a number of limitations in the use of #GooCanvasWidget:
  *
  * <itemizedlist><listitem><para>
@@ -26,6 +30,8 @@
  * </para></listitem><listitem><para>
  * It doesn't have a model/view variant like the other standard items,
  * so it can only be used in a simple canvas without a model.
+ * </para></listitem><listitem><para>
+ * It can't be made a static item.
  * </para></listitem></itemizedlist>
  */
 #include <config.h>
@@ -153,6 +159,73 @@ goo_canvas_widget_new               (GooCanvasItem    *parent,
 }
 
 
+/* Returns the anchor position, within the given width. */
+static gdouble
+goo_canvas_widget_anchor_horizontal_pos (GtkAnchorType anchor,
+					 gdouble       width)
+{
+  switch(anchor)
+    {
+    case GTK_ANCHOR_N:
+    case GTK_ANCHOR_CENTER:
+    case GTK_ANCHOR_S:
+      return width / 2.0;
+    case GTK_ANCHOR_NE:
+    case GTK_ANCHOR_E:
+    case GTK_ANCHOR_SE:
+      return width;
+    default:
+      return 0.0;
+    }
+}
+
+
+/* Returns the anchor position, within the given height. */
+static gdouble
+goo_canvas_widget_anchor_vertical_pos (GtkAnchorType anchor,
+				       gdouble       height)
+{
+  switch (anchor)
+    {
+    case GTK_ANCHOR_W:
+    case GTK_ANCHOR_CENTER:
+    case GTK_ANCHOR_E:
+      return height / 2.0;
+    case GTK_ANCHOR_SW:
+    case GTK_ANCHOR_S:
+    case GTK_ANCHOR_SE:
+      return height;
+    default:
+      return 0.0;
+    }
+}
+
+
+/* Returns the size to use for the widget, either the item's width & height
+   properties or the widget's own requested width & height. */
+static void
+goo_canvas_widget_get_widget_size (GooCanvasWidget *witem,
+				   gdouble         *width,
+				   gdouble         *height)
+{
+  GtkRequisition requisition;
+
+  if (witem->widget)
+    {
+      /* Get the widget's requested size, if we need it. */
+      if (witem->width < 0 || witem->height < 0)
+	gtk_widget_size_request (witem->widget, &requisition);
+
+      *width = witem->width < 0 ? requisition.width : witem->width;
+      *height = witem->height < 0 ? requisition.height : witem->height;
+    }
+  else
+    {
+      *width = *height = 0.0;
+    }
+}
+
+
 static void
 goo_canvas_widget_set_widget (GooCanvasWidget *witem,
 			      GtkWidget       *widget)
@@ -347,53 +420,19 @@ goo_canvas_widget_update  (GooCanvasItemSimple *simple,
 			   cairo_t             *cr)
 {
   GooCanvasWidget *witem = (GooCanvasWidget*) simple;
-  GtkRequisition requisition;
   gdouble width, height;
 
   if (witem->widget)
     {
-      /* Compute the new bounds. */
-      if (witem->width < 0 || witem->height < 0)
-	{
-	  gtk_widget_size_request (witem->widget, &requisition);
-	}
+      goo_canvas_widget_get_widget_size (witem, &width, &height);
 
       simple->bounds.x1 = witem->x;
       simple->bounds.y1 = witem->y;
-      width = witem->width < 0 ? requisition.width : witem->width;
-      height = witem->height < 0 ? requisition.height : witem->height;
-
-      switch (witem->anchor)
-	{
-	case GTK_ANCHOR_N:
-	case GTK_ANCHOR_CENTER:
-	case GTK_ANCHOR_S:
-	  simple->bounds.x1 -= width / 2.0;
-	  break;
-	case GTK_ANCHOR_NE:
-	case GTK_ANCHOR_E:
-	case GTK_ANCHOR_SE:
-	  simple->bounds.x1 -= width;
-	  break;
-	default:
-	  break;
-	}
 
-      switch (witem->anchor)
-	{
-	case GTK_ANCHOR_W:
-	case GTK_ANCHOR_CENTER:
-	case GTK_ANCHOR_E:
-	  simple->bounds.y1 -= height / 2.0;
-	  break;
-	case GTK_ANCHOR_SW:
-	case GTK_ANCHOR_S:
-	case GTK_ANCHOR_SE:
-	  simple->bounds.y1 -= height;
-	  break;
-	default:
-	  break;
-	}
+      simple->bounds.x1 -=
+        goo_canvas_widget_anchor_horizontal_pos (witem->anchor, width);
+      simple->bounds.y1 -=
+        goo_canvas_widget_anchor_vertical_pos (witem->anchor, height);
 
       simple->bounds.x2 = simple->bounds.x1 + width;
       simple->bounds.y2 = simple->bounds.y1 + height;
@@ -544,6 +583,7 @@ goo_canvas_widget_class_init (GooCanvasWidgetClass *klass)
 							G_MAXDOUBLE, -1.0,
 							G_PARAM_READWRITE));
 
+
   g_object_class_install_property (gobject_class, PROP_ANCHOR,
 				   g_param_spec_enum ("anchor",
 						      _("Anchor"),
@@ -555,5 +595,3 @@ goo_canvas_widget_class_init (GooCanvasWidgetClass *klass)
   g_object_class_override_property (gobject_class, PROP_VISIBILITY,
 				    "visibility");
 }
-
-



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