Someone posted a link to the minutes of the gtk+ meeting at GUADEC which reminded me that I promised to write up some of the ideas I had for a canvas-type widget.
The reason model/view is a useful model is that it allows applications to keep a data structure (the model) containing all the business logic (what the application *does*) in one place and then have separate modules displaying views of this data structure. Whenever something changes about the model the view is signalled to change itself as appropriate. In an application based on GnomeCanvas or similar there will often be a correspondence between objects in the data model and canvas items and changes to the model will cause changes to the canvas items. Essentially the application is forced to keep two distinct copies of the model up to date. Not only does this use lots of memory, it also requires lots of code to be written. A much simpler approach is often to simply walk the model and draw on a drawing area on every expose event. This gets hard for two reasons: - you need to handle input on distinct areas corresponding to objects in the model. - you need to handle scrolling Both of these are solved by a canvas widget which I'd argue is its main attraction. For the old GnomeCanvas you also had the attraction of antialiasing/translucency and bezier curves, but not cairo provides this. So FooScrollArea is an attempt at implementing input and scrolling without retaining a hierarchy of canvas items, ie, and "immeddiate mode" canvas. Demo code here: http://www.daimi.au.dk/~sandmann/canvas-demo.tar.gz The main thing to note is the small amount of code in testarea2 actually needed to implement the features demonstrated. How applications would use it: Applications keep a datastructure containing the application model. Whenever something changes in this datastructure the corresponding area is invalidated. The scroll area will then emit an expose signal and the application will repaint the invalid area. Ie basically like the gtk+ drawing model. The difference is in how input is handled. During the expose handling, the application is not only drawing stuff, it is also setting input regions. These input regions are remembered by the canvas, but *get invalidated along with the pixels*. Ie., you are required to "repaint" all the input regions on every expose. If you paint two input regions on top of each other, the top one will get the event first (and can optionally pass it along to lower layers). This way, all information about stacking and overlapping input regions is *implicit* in the application model rather than explicit in the canvas hierarchy. So even input handling is immediate mode rather than retained mode. Example of why this is useful: Suppose you are writing an illustration program like Inkscape. Your data model might be a tree of groups containing shapes and curves. One of these shapes might be selected which means it has little handles you can use to change the shape. In the FooScrollArea model all you need to write is expose code for the shape: expose_shape (Shape *shape, ScrollArea *area, Region *region) { draw_shape (area); draw_input_region (area, shape); if (shape->selected) { for (points in shape) { draw_drag_handle(); set_drag_handle_input (handle_shape_input); } } } When a shape is clicked, the old selected shape gets its "selected" bit cleared and the new one gets it set in the application model. Then both areas are invalidad. When a drag handle is dragged, the corresponding point needs to be moved and the item invalidated. So there is only one copy of the state pertaining to the shape. In the retained model, this will need to happen: When a shape is clicked, the old selected shape needs to be unslected, which means deleting a canvas item for each point on the shape. Then new canvas items must be created for each of the handle points in the new shape. When a drag handle is clicked, three different objects must be updated: the application model object, the canvas item for the shape, and the drag handle for the clicked point. And this is just for editing a simple shape. I believe this 'immediate' mode canvas is a simpler and more efficient model than retained mode canvases, at least for most non-trivial applications. Soren _______________________________________________ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list