goocanvas experiences

I’ve got to know goocanvas (API documentation, browse CVS) better over the last week. I achieved what I needed, but it could have been easier.

No generic positioning of items

You can’t set the position of goocanvas items. Well, you can set the x,y position of a GooCanvasRect, and you can set the points in a GooCanvasPolyline, but there is no generic position API in the base GooCanvasItem interface.

This makes it very difficult to write generic code for dragging, loading, and saving. All the items could support a generic API – it wouldn’t matter if the x,y is some arbitrary point in the item. I have implemented this in derived classes in C++, with some multiple inheritance awkwardness, but life would be far easier if it was in the GooCanvasItem base class itself. Erik Osheim did this in Python too. You wouldn’t want to do it in C. It seems to be a regression compared to libgnomecanvas, which has gnome_canvas_item_move().

Note that you can “translate” generic GooCanvasItem items, but

  • Two APIs for the same thing, to be used at different times, is annoying.
  • You can’t easily discover the actual position after translating. For instance, the GooCanvasRect x,y properties are not changed by goo_canvas_item_translate(). That function just changes a translation matrix which is applied to the x,y, rather than changing x,y.

I guess this is the cairo drawing system, but the canvas API shouldn’t force that on me. This is a major problem in the API for me, so I hope I can persuade Damon to let us add this.

Update: We created a GooCanvas generic positioning patch for this.

No high-level funtionality

You have to implement too much yourself. Not every application needs the ability to drag and resize items, but many do, and it would be nice if this was easy and consistent. I implemented drag-to-move, snap to grid, snap to rules, ctrl-to-restrict-drag-to-one-axis, resizing via corners and edges with appropriate arrow cursors, and signalling for a context menu on right-click. I still need to do selection highlighting and moving of multiple selections. I did that with a CanvasGroupResizable class that can take a child to be manipulated, though it currently only works with a rectangle child. It uses the generically-movable rectangles and lines that I mentioned above.

The next person to reimplement this will probably make it behave subtly differently.

Now that I finally have a canvas with the basic functionality that I need, I was able to reimplement and improve Glom’s Relationships Overview. I’ll now start using it to implement print layouts showing field data.

Printing is easy

goo_canvas_render() makes printing really easy with GtkPrintOperation.

Minor issues

  • Instead of having a GooCanvasContainer type, there’s a goo_canvas_item_is_container() function that tells you whether goo_canvas_item_get_child() and friends are useful.
    Damon seems to like the idea of correcting this. Update: We created a GooCanvas Container-type patch for this.
  • The root item idea doesn’t seem useful. You always have to use goo_canvas_get_root_item() to actually add or remove items to the canvas. I’d like to make the GooCanvas widget implement the GooCanvasContainer interface instead.
  • The model/view separation doesn’t seem useful, though I might be persuaded by a real life example. I don’t see a big need to display the same canvas twice in the same UI. In GtkTreeView the model/view separation allows you to show two views with differently sorted or filtered models, but I don’t see an equivalent in goocanvas. I can imagine using different zoom levels or different visibility (at different zooms) levels, but I don’t see a way to specify that for a canvas “view”.
  • The *_new() functions need to be fixed to just use g_object_new(), for language bindings. Bug filed.
  • The *_new() functions, such as goo_canvas_rect_new() correctly return an initial reference if you pass NULL for the parent parameter, but do not return a reference if you specify a parent. That’s maybe convenient if you can remember, but its’ an invitation to make mistakes.

At first glance, libccc has many of the same problems. Note that I was dissuaded from trying libccc first because it was started after goocanvas, without any stated reason, and due to the lack of documentation on the functions that I looked at.

I should look at HippoCanvas too.

6 thoughts on “goocanvas experiences

  1. Hey Murray, I’m getting hit with similar issues. Like not being able to resize the RectangleItem using pixel size, will it is constructed that way. etc.

    I wonder if we couldn’t add that directly to goocanvasmm.

  2. Hub, do you mean the “No generic positioning of items”? I think we need to do this in a branch of goocanvas and then try really hard to get it used by goocanvas itself. If not then we’ll have a useful fork.

    For now, I have a parallel hierarchy of canvas items in Glom that makes this possible. You might find it useful.

Leave a Reply

Your email address will not be published. Required fields are marked *