... 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

Reply via email to