demo_item->size = 0.0;
 }
 
-void
-goo_demo_item_move_to (GooCanvasItem   *item,
-                      gdouble           x,
-                      gdouble           y)
-{
-    cairo_matrix_t matrix;
-
-    cairo_matrix_init_translate (&matrix, x, y);
-    goo_canvas_item_set_transform (item, &matrix);
-}
-
-void
-goo_demo_item_glide_to (GooCanvasItem  *item,
-                       gdouble          x,
-                       gdouble          y)
-{
-    goo_canvas_item_animate (item, x, y,
-                            1.0, 0,
-                            500, 40,
-                            GOO_CANVAS_ANIMATE_FREEZE);
-}
-
 /* The convenience function to create new items. This should start with a 
    parent argument and end with a variable list of object properties to fit
    in with the standard canvas items. */
 GooCanvasItem*
-goo_demo_item_new (GooCanvasItem      *parent,
-                  gdouble             x,
-                  gdouble             y,
-                  gdouble             size,
-                  char                letter,
+goo_demo_item_new (GooCanvasItem       *parent,
+                  gdouble               size,
+                  GooDemoItemPaintFunc  paint,
+                  void                 *closure,
                   ...)
 {
     GooCanvasItem *item;
 
     demo_item = (GooDemoItem*) item;
     demo_item->size = size;
-    demo_item->letter = letter;
+    demo_item->paint = paint;
+    demo_item->closure = closure;
 
-    va_start (var_args, letter);
+    va_start (var_args, closure);
     first_property = va_arg (var_args, char*);
     if (first_property)
        g_object_set_valist ((GObject*) item, first_property, var_args);
        g_object_unref (item);
     }
 
-    goo_demo_item_move_to (item, x, y);
-
     return item;
 }
 
                     GooCanvasBounds     *bounds)
 {
     GooDemoItem *item = (GooDemoItem*) simple;
-    cairo_pattern_t *gradient;
-    cairo_text_extents_t extents;
-    int rad = (int) (item->size / 2);
-    int cx = item->size / 2;
-    int cy = cx;
-    int tx, ty;
-    double spot_angle = M_PI / 4.0;
-    double spot_rad = rad / 2.0;
-    char string[2];
-
-    cairo_save (cr);
-
-    gradient = cairo_pattern_create_radial (cx - spot_rad * cos (spot_angle),
-                                           cy - spot_rad * sin (spot_angle),
-                                           0.0,
-                                           cx - spot_rad * cos (spot_angle),
-                                           cy - spot_rad * sin (spot_angle),
-                                           rad + spot_rad);
-    cairo_pattern_add_color_stop_rgb (gradient, 0.0, 1.0, 1.0, 1.0);
-    cairo_pattern_add_color_stop_rgb (gradient, 1.0, 0.33, 0.33, 0.33);
-
-    cairo_set_source (cr, gradient);
-
-    cairo_arc (cr,
-              cx, cy,
-              rad, 0, 2 * M_PI);
-
-    cairo_fill (cr);
-
-    cairo_select_font_face (cr, "mono",
-                           CAIRO_FONT_SLANT_NORMAL,
-                           CAIRO_FONT_WEIGHT_BOLD);
-    cairo_set_font_size (cr, 1.8 * rad);
-
-    string[0] = item->letter;
-    string[1] = '\0';
-    cairo_text_extents (cr, string, &extents);
-    tx = cx - extents.width / 2 - extents.x_bearing;
-    ty = cy - extents.height / 2 - extents.y_bearing;
-
-    cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
-    cairo_move_to (cr, tx + 1, ty + 1);
-    cairo_show_text (cr, string);
-               
-    cairo_set_source_rgb (cr, 0.33, 0.33, 0.33);
-    cairo_move_to (cr, tx - 1, ty - 1);
-    cairo_show_text (cr, string);
-
-    cairo_set_source_rgb (cr, 0.2, 0.3, 0.8);
-    cairo_move_to (cr, tx, ty);
-    cairo_show_text (cr, string);
-
-    cairo_restore (cr);
+
+    item->paint (cr, item->closure);
 }
 
 /* Hit detection. This should check if the given coordinate (in the item's
 
 typedef struct _GooDemoItem       GooDemoItem;
 typedef struct _GooDemoItemClass  GooDemoItemClass;
 
+typedef void (*GooDemoItemPaintFunc) (cairo_t *cr, void *);
+
 struct _GooDemoItem
 {
     GooCanvasItemSimple parent_object;
-
     double size;
-    char letter;
+    GooDemoItemPaintFunc paint;
+    void *closure;
 };
 
 struct _GooDemoItemClass
 
 GType               goo_demo_item_get_type  (void) G_GNUC_CONST;
 
-GooCanvasItem*      goo_demo_item_new       (GooCanvasItem      *parent,
-                                            gdouble             x,
-                                            gdouble             y,
-                                            gdouble             size,
-                                            char                letter,
+GooCanvasItem*      goo_demo_item_new       (GooCanvasItem             *parent,
+                                            gdouble                     size,
+                                            GooDemoItemPaintFunc        paint,
+                                            void                       *closure,
                                             ...);
 
-void
-goo_demo_item_move_to (GooCanvasItem   *item,
-                      gdouble           x,
-                      gdouble           y);
-
-void
-goo_demo_item_glide_to (GooCanvasItem  *item,
-                       gdouble          x,
-                       gdouble          y);
-
 G_END_DECLS
 
 #endif /* __GOO_DEMO_ITEM_H__ */
 
     char letter;
     int rack_index;
     int x, y;
+    int size;
     GooCanvasItem *item;
     gboolean guessed;
 } tile_t;
     *y -= (LETTER_SIZE + LETTER_PAD);
 }
 
+static void
+tile_paint (cairo_t *cr, void *closure)
+{
+    tile_t *tile = closure;
+
+    cairo_pattern_t *gradient;
+    cairo_text_extents_t extents;
+    int rad = (int) (tile->size / 2);
+    int cx = tile->size / 2;
+    int cy = cx;
+    int tx, ty;
+    double spot_angle = M_PI / 4.0;
+    double spot_rad = rad / 2.0;
+    char string[2];
+
+    cairo_save (cr);
+
+    gradient = cairo_pattern_create_radial (cx - spot_rad * cos (spot_angle),
+                                           cy - spot_rad * sin (spot_angle),
+                                           0.0,
+                                           cx - spot_rad * cos (spot_angle),
+                                           cy - spot_rad * sin (spot_angle),
+                                           rad + spot_rad);
+    cairo_pattern_add_color_stop_rgb (gradient, 0.0, 1.0, 1.0, 1.0);
+    cairo_pattern_add_color_stop_rgb (gradient, 1.0, 0.33, 0.33, 0.33);
+
+    cairo_set_source (cr, gradient);
+
+    cairo_arc (cr,
+              cx, cy,
+              rad, 0, 2 * M_PI);
+
+    cairo_fill (cr);
+
+    cairo_select_font_face (cr, "mono",
+                           CAIRO_FONT_SLANT_NORMAL,
+                           CAIRO_FONT_WEIGHT_BOLD);
+    cairo_set_font_size (cr, 1.8 * rad);
+
+    string[0] = tile->letter;
+    string[1] = '\0';
+    cairo_text_extents (cr, string, &extents);
+    tx = cx - extents.width / 2 - extents.x_bearing;
+    ty = cy - extents.height / 2 - extents.y_bearing;
+
+    cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
+    cairo_move_to (cr, tx + 1, ty + 1);
+    cairo_show_text (cr, string);
+               
+    cairo_set_source_rgb (cr, 0.33, 0.33, 0.33);
+    cairo_move_to (cr, tx - 1, ty - 1);
+    cairo_show_text (cr, string);
+
+    cairo_set_source_rgb (cr, 0.2, 0.3, 0.8);
+    cairo_move_to (cr, tx, ty);
+    cairo_show_text (cr, string);
+
+    cairo_restore (cr);
+}
+
+static void
+tile_move_to (tile_t *tile, int x, int y)
+{
+    cairo_matrix_t matrix;
+
+    cairo_matrix_init_translate (&matrix, x, y);
+    goo_canvas_item_set_transform (tile->item, &matrix);
+}
+
+static void
+tile_glide_to (tile_t *tile, int x, int y)
+{
+    goo_canvas_item_animate (tile->item, x, y,
+                            1.0, 0,
+                            500, 40,
+                            GOO_CANVAS_ANIMATE_FREEZE);
+    tile->x = x;
+    tile->y = y;
+}
+
 static tile_t *
 tile_create (GooCanvasItem *parent,
             char letter, int rack_index)
     tile->letter = tolower (letter);
     tile->rack_index = rack_index;
     rack_tile_position (rack_index, &tile->x, &tile->y);
+    tile->size = LETTER_SIZE;
     tile->item = goo_demo_item_new (parent,
-                                   tile->x, tile->y,
-                                   LETTER_SIZE,
-                                   toupper (letter),
-                                   NULL);
+                                   tile->size,
+                                   tile_paint,
+                                   tile);
+
+    tile_move_to (tile, tile->x, tile->y);
+
     tile->guessed = FALSE;
 
     return tile;
 }
 
-static void
-tile_glide_to (tile_t *tile, int x, int y)
-{
-    goo_demo_item_glide_to (tile->item, x, y);
-    tile->x = x;
-    tile->y = y;
-}
-
 static gboolean
 on_delete_event (GtkWidget *window,
                 GdkEvent  *event,