Hi Paul, thanks for your remarks!
On Di, 29.12.2009 21:48, Paul Davis wrote: >It was designed after looking at undo models in various other >applications, and finding them all to have various problems for what >we really needed (this included the GIMP). This seems to be a common scenario. Let's work on fixing this in the toolkit! :-) >1) you need to be able to group individual actions into transactions Absolutely. >2) serialization/deserialization is good, and hard That's a very interesting point that I've been thinking about too. Though this seems like another topic to me - many widgets in GTK+ could benefit from serialization support (e.g. state serialization of TreeView's), so this should really be a more general interface and not an undo-stack-isle-solution, so I left it out for now. >3) its very hard to use only a Memento pattern without running into >efficiency problems Efficiency is a good point, too. For an undo stack, the most common operation is to put stuff onto the stack, so this should be most efficient. Pushing something onto the stack should be cheap, and keeping a large stack around should be cheap (memory-wise). That's why I chose elements of the stack just be be minimal structs, just holding a (optional) human readable description, a pointer to a struct of the callback functions, and a pointer to the user-data. That's about as efficient as it can get. An alternative implementation would be to have a base class, and each element that can be pushed onto the stack needs to be derived from that base class, overriding the callback functions as needed (that's btw how Qt does it with the QUndoCommand class, and I believe also how you did it). I also tried that in a previous attempt, but found it too expensive (and hard to use from C) for little gain. >5) deciding whether or not to support nested transactions can be important True. Actually, my first attempt didn't allow nesting of transactions (or groups, how I called it), and I found it insufficient. And this limitation is not really needed anyways, if one doesn't distinguish between individual command entries and transactions, but instead treats a transaction as a special case of a command entry. In my suggested implementation, the stack is a list of trees. In your nomenclature, all leaves in the tree would be individual command entries, and all non-leaves would be transactions. An undo operation undoes the complete tree. I find this nesting possibility essential for programs that don't e.g. follow the command pattern from the start anyways. >battle-tested implementation that avoids pre-registration >of actions that can be undone Actually, it would be very easy to avoid the registering of undo action sets with a name, and just pass a pointer to the set whenever registering an action. It could probably even be offered in parallel as an alternative. However, there's one important reason why the registering should at least be possible: To make it possible to hook into the stack from dynamically loaded modules (aka plugins). If they just registered function pointers, and got unloaded, the pointers would point to garbage, and undo operations would crash. By allowing them to register, a "unregister" operation could be provided which removed everything concerning that set from the stack (or, it it wants to be conservative, cleared the stack if an entry corresponding to the unregistered item was in it). Holger _______________________________________________ gtk-devel-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/gtk-devel-list
