I am currently working to implement Undo / Redo within my application, and am having some issues, particularly with chains of Undo / Redo events.
I have a factory class which builds custom ShapeNodes (a main node with many sub-nodes as labels etc. and a custom anchor pattern), based on a data class which models the unterlying data each node represents.
In order to support undo / redo for creating / deleting these nodes I have sub-classed Command and implemented Execute, Undo and Redo. When a node is created, I instantiate a new NodeCreatedCmd class, which stores refernces to my custom shapeNode and the data class which supports it.
To undo the add I call diagram.Nodes.Remove().
In order to redo the node creation, I had hoped to simply be able to call diagram.Nodes.Add(shapeNode); to re-add it to the diagram. However, the call to diagram.Nodes.Remove() sets the read-only SubordinateGroup property to null, and so all the label nodes are not ressurected.
To get around this I have to call my factory class again to create a new shapeNode with the same properties as the old ShapeNode.
The problem is that any other Commands in the undo history which referenced the original ShapeNode (such as link creations etc.) now reference the OLD ShapeNode object which is no longer on the diagram, leading to incorrect behaviour.
From within my own Commands I can get round this by searching the Nodes collection and finding the Node I require, rather than using the reference to the old one, but the automatic commands I am relying on, such as node movement, still reference the incorrect object.
Has this issue been addressed before, or do I need to write my own version of any event which I need in this case?
Cheers,
xan
Edit:
An additional problem I have found I encounter while trying to work around the problem listed above.
I have special rules, based on the ptoperties of the data class which backs each node, which control whether a link between two nodes / anchor points is allowed. Thus I have another Command subclass, LinkDeletedCmd, which I create when a link is deleted by the user, which allows the underlying data structures to be kept properly updated when undoing / redoing a link delete.
However, due to the problem above I wish to disable the recording of the built-in link deletion command and have complete control. The problem is that I create my command in the LinkDeleted handler I have, and concequently my LinkDeletedCmd is grouped as a subcommand along with the built in link delete command and there is no way of seperating the two - either both are executed, or neither.
As always, any help or suggestions are hugely appreciated,
Cheers,
xan
|