... is limited. Well, I have declared I have little time for the baby (have real babies to look after ;-) among other things), but I manage to make a commit from time to time.
For now I concentrate on the very basics of the design, as the initial implementation was made in the mode of "do the minimum necessary to validate the concept". I'll try to summarize the architecture over the weekend but for the last two evenings, I have at least managed to put more thoughts into the undo system, updated the code to implement the idea well, and even cover it with few tests. Here is how is it meant to work. Please look at it and try to find weak points where the scheme would broke. 1) No commands. User actions perform DataSet modifications directly (through the API of DataSet and individual primitives). 2) DataSet exports UndoableEdits to a registered UndoManager (there is one per editable layer), after slight processing inside a special UndoableEditSupport. 3) Each DS/Primitive modification metod first creates an UndoableEdit of proper kind. The edit samples current value of the field to be modified and keeps it. 4) undo/redo of given edit just switches the current and saved value. The infrastructure enforces that you can't do an out-of-order undo/redo, so switch is safe. 5) To support grouping of edits, DataSet exports runAtomic(Runnable) method. Anything running inside it's run will be posted to the UndoManager as single (Compound)UndoableEdit, so you can undo/redo it atomically. 6) To support incremental edits (like if you're dragging around the selection - that modifies the DataSet on every mouse move event), runAtomic takes a token that can be compared. If you perform two (or more) consecutive runAtomic()s with the same token, all the UndoableEdits generated during the second (subsequent) round are discarded. This works thanks to 3 and 4: user action: [change x from 1 to 2| save x was 1] user action: [change x from 2 to 3|discard] user undo: [undo change - set x to 1, save x was 3] user redo: [redo change - set x to 3, save x was 1] The only thing that needs to be taken care of in such case is that you use the same token only for relevant groups of edits. The use case for this is to generate new token on mouse down, use the token throughout the whole drag (thus the complete drag operation of the node selection/way/whatever ends up being single undoable edit) and then discard the token on mouse-up. That's all the magic in there. It should cover complicated edits, composition of edits and simple undo. Is there a hole in it? -- Petr "Nenik" Nejedly, NetBeans/Sun Microsystems, http://www.netbeans.org 355/113 -- Not the famous irrational number PI, but an incredible simulation! _______________________________________________ josm-dev mailing list [email protected] http://lists.openstreetmap.org/cgi-bin/mailman/listinfo/josm-dev
