Creating New Items

Creating New Items — how to create new canvas items.

How to Create New Canvas Items

Here's an example of how to create a new simple canvas item. (Note that this item doesn't have a model-view split.)

Here's the header file - a fairly standard GObject header file. Our item derives from GooCanvasItemSimple and just has its own x, y, width and height variables:

  /*
   * GooCanvas Demo. Copyright (C) 2006 Damon Chaplin.
   * Released under the GNU LGPL license. See COPYING for details.
   *
   * demo-item.c - a simple demo item.
   */
  #ifndef __GOO_DEMO_ITEM_H__
  #define __GOO_DEMO_ITEM_H__
  
  #include <gtk/gtk.h>
  #include "goocanvasitemsimple.h"
  
  G_BEGIN_DECLS
  
  
  #define GOO_TYPE_DEMO_ITEM            (goo_demo_item_get_type ())
  #define GOO_DEMO_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GOO_TYPE_DEMO_ITEM, GooDemoItem))
  #define GOO_DEMO_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GOO_TYPE_DEMO_ITEM, GooDemoItemClass))
  #define GOO_IS_DEMO_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GOO_TYPE_DEMO_ITEM))
  #define GOO_IS_DEMO_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GOO_TYPE_DEMO_ITEM))
  #define GOO_DEMO_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GOO_TYPE_DEMO_ITEM, GooDemoItemClass))
  
  
  typedef struct _GooDemoItem       GooDemoItem;
  typedef struct _GooDemoItemClass  GooDemoItemClass;
  
  struct _GooDemoItem
  {
    GooCanvasItemSimple parent_object;
  
    gdouble x, y, width, height;
  };
  
  struct _GooDemoItemClass
  {
    GooCanvasItemSimpleClass parent_class;
  };
  
  
  GType               goo_demo_item_get_type  (void) G_GNUC_CONST;
  
  GooCanvasItem*      goo_demo_item_new       (GooCanvasItem      *parent,
                                               gdouble             x,
                                               gdouble             y,
                                               gdouble             width,
                                               gdouble             height,
                                               ...);
  
  
  G_END_DECLS
  
  #endif /* __GOO_DEMO_ITEM_H__ */
 

And here's the source file:

  /*
   * GooCanvas Demo. Copyright (C) 2006 Damon Chaplin.
   * Released under the GNU LGPL license. See COPYING for details.
   *
   * demo-item.c - a simple demo item.
   */
  #include <config.h>
  #include "goocanvas.h"
  #include "demo-item.h"
  
  
  /* Use the GLib convenience macro to define the type. GooDemoItem is the
     class struct, goo_demo_item is the function prefix, and our class is a
     subclass of GOO_TYPE_CANVAS_ITEM_SIMPLE. */
  G_DEFINE_TYPE (GooDemoItem, goo_demo_item, GOO_TYPE_CANVAS_ITEM_SIMPLE)
  
  
  /* The standard object initialization function. */
  static void
  goo_demo_item_init (GooDemoItem *demo_item)
  {
    demo_item->x = 0.0;
    demo_item->y = 0.0;
    demo_item->width = 0.0;
    demo_item->height = 0.0;
  }
  
  
  /* 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             width,
                     gdouble             height,
                     ...)
  {
    GooCanvasItem *item;
    GooDemoItem *demo_item;
    const char *first_property;
    va_list var_args;
  
    item = g_object_new (GOO_TYPE_DEMO_ITEM, NULL);
  
    demo_item = (GooDemoItem*) item;
    demo_item->x = x;
    demo_item->y = y;
    demo_item->width = width;
    demo_item->height = height;
  
    va_start (var_args, height);
    first_property = va_arg (var_args, char*);
    if (first_property)
      g_object_set_valist ((GObject*) item, first_property, var_args);
    va_end (var_args);
  
    if (parent)
      {
        goo_canvas_item_add_child (parent, item, -1);
        g_object_unref (item);
      }
  
    return item;
  }
  
  
  /* The update method. This is called when the canvas is initially shown and
     also whenever the object is updated and needs to change its size and/or
     shape. It should calculate its new bounds in its own coordinate space,
     storing them in simple->bounds. */
  static void
  goo_demo_item_update  (GooCanvasItemSimple *simple,
                         cairo_t             *cr)
  {
    GooDemoItem *demo_item = (GooDemoItem*) simple;
  
    /* Compute the new bounds. */
    simple->bounds.x1 = demo_item->x;
    simple->bounds.y1 = demo_item->y;
    simple->bounds.x2 = demo_item->x + demo_item->width;
    simple->bounds.y2 = demo_item->y + demo_item->height;
  }
  
  
  /* The paint method. This should draw the item on the given cairo_t, using
     the item's own coordinate space. */
  static void
  goo_demo_item_paint (GooCanvasItemSimple *simple,
                       cairo_t             *cr,
                       GooCanvasBounds     *bounds)
  {
    GooDemoItem *demo_item = (GooDemoItem*) simple;
  
    cairo_move_to (cr, demo_item->x, demo_item->y);
    cairo_line_to (cr, demo_item->x, demo_item->y + demo_item->height);
    cairo_line_to (cr, demo_item->x + demo_item->width,
                   demo_item->y + demo_item->height);
    cairo_line_to (cr, demo_item->x + demo_item->width, demo_item->y);
    cairo_close_path (cr);
    goo_canvas_style_set_fill_options (simple->simple_data->style, cr);
    cairo_fill (cr);
  }
  
  
  /* Hit detection. This should check if the given coordinate (in the item's
     coordinate space) is within the item. If it is it should return the item,
     otherwise it should return NULL. */
  static GooCanvasItem*
  goo_demo_item_get_item_at (GooCanvasItemSimple *simple,
                             gdouble              x,
                             gdouble              y,
                             cairo_t             *cr,
                             gboolean             is_pointer_event)
  {
    GooDemoItem *demo_item = (GooDemoItem*) simple;
  
    if (x < demo_item->x || (x > demo_item->x + demo_item->width)
        || y < demo_item->y || (y > demo_item->y + demo_item->height))
      return NULL;
  
    return (GooCanvasItem*) simple;
  }
  
  
  /* The class initialization function. Here we set the class' update(), paint()
     and get_item_at() methods. */
  static void
  goo_demo_item_class_init (GooDemoItemClass *klass)
  {
    GooCanvasItemSimpleClass *simple_class = (GooCanvasItemSimpleClass*) klass;
  
    simple_class->update        = goo_demo_item_update;
    simple_class->paint         = goo_demo_item_paint;
    simple_class->get_item_at   = goo_demo_item_get_item_at;
  }