source: josm/trunk/src/org/openstreetmap/josm/data/UndoRedoHandler.java @ 4920

Revision 4908, 5.2 KB checked in by simon04, 4 days ago (diff)

fix #7327 - show hint in undo-menu which action will be undone (from event stack)

  • Property svn:eol-style set to native
Line 
1//License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.data;
3
4import java.util.Collection;
5import java.util.Iterator;
6import java.util.LinkedList;
7
8import org.openstreetmap.josm.Main;
9import org.openstreetmap.josm.command.Command;
10import org.openstreetmap.josm.data.osm.OsmPrimitive;
11import org.openstreetmap.josm.gui.MapView;
12import org.openstreetmap.josm.gui.layer.Layer;
13import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener;
14
15public class UndoRedoHandler implements MapView.LayerChangeListener {
16
17    /**
18     * All commands that were made on the dataset. Don't write from outside!
19     */
20    public final LinkedList<Command> commands = new LinkedList<Command>();
21    /**
22     * The stack for redoing commands
23     */
24    public final LinkedList<Command> redoCommands = new LinkedList<Command>();
25
26    private final LinkedList<CommandQueueListener> listenerCommands = new LinkedList<CommandQueueListener>();
27
28    public UndoRedoHandler() {
29        MapView.addLayerChangeListener(this);
30    }
31
32    /**
33     * Execute the command and add it to the intern command queue.
34     */
35    public void addNoRedraw(final Command c) {
36        c.executeCommand();
37        commands.add(c);
38        // Limit the number of commands in the undo list.
39        // Currently you have to undo the commands one by one. If
40        // this changes, a higher default value may be reasonable.
41        if (commands.size() > Main.pref.getInteger("undo.max", 1000)) {
42            commands.removeFirst();
43        }
44        redoCommands.clear();
45    }
46
47    public void afterAdd() {
48        fireCommandsChanged();
49
50        // the command may have changed the selection so tell the listeners about the current situation
51        Main.main.getCurrentDataSet().fireSelectionChanged();
52    }
53
54    /**
55     * Execute the command and add it to the intern command queue.
56     */
57    synchronized public void add(final Command c) {
58        addNoRedraw(c);
59        afterAdd();
60    }
61
62    /**
63     * Undoes the last added command.
64     */
65    public void undo() {
66        undo(1);
67    }
68
69    /**
70     * Undoes multiple commands.
71     */
72    synchronized public void undo(int num) {
73        if (commands.isEmpty())
74            return;
75        Collection<? extends OsmPrimitive> oldSelection = Main.main.getCurrentDataSet().getSelected();
76        Main.main.getCurrentDataSet().beginUpdate();
77        try {
78            for (int i=1; i<=num; ++i) {
79                final Command c = commands.removeLast();
80                c.undoCommand();
81                redoCommands.addFirst(c);
82                if (commands.isEmpty()) {
83                    break;
84                }
85            }
86        }
87        finally {
88            Main.main.getCurrentDataSet().endUpdate();
89        }
90        fireCommandsChanged();
91        Collection<? extends OsmPrimitive> newSelection = Main.main.getCurrentDataSet().getSelected();
92        if (!oldSelection.equals(newSelection)) {
93            Main.main.getCurrentDataSet().fireSelectionChanged();
94        }
95    }
96
97    /**
98     * Redoes the last undoed command.
99     */
100    public void redo() {
101        redo(1);
102    }
103
104    /**
105     * Redoes multiple commands.
106     */
107    public void redo(int num) {
108        if (redoCommands.isEmpty())
109            return;
110        Collection<? extends OsmPrimitive> oldSelection = Main.main.getCurrentDataSet().getSelected();
111        for (int i=0; i<num; ++i) {
112            final Command c = redoCommands.removeFirst();
113            c.executeCommand();
114            commands.add(c);
115            if (redoCommands.isEmpty()) {
116                break;
117            }
118        }
119        fireCommandsChanged();
120        Collection<? extends OsmPrimitive> newSelection = Main.main.getCurrentDataSet().getSelected();
121        if (!oldSelection.equals(newSelection)) {
122            Main.main.getCurrentDataSet().fireSelectionChanged();
123        }
124    }
125
126    public void fireCommandsChanged() {
127        for (final CommandQueueListener l : listenerCommands) {
128            l.commandChanged(commands.size(), redoCommands.size());
129        }
130    }
131
132    public void clean() {
133        redoCommands.clear();
134        commands.clear();
135        fireCommandsChanged();
136    }
137
138    public void clean(Layer layer) {
139        if (layer == null)
140            return;
141        boolean changed = false;
142        for (Iterator<Command> it = commands.iterator(); it.hasNext();) {
143            if (it.next().invalidBecauselayerRemoved(layer)) {
144                it.remove();
145                changed = true;
146            }
147        }
148        for (Iterator<Command> it = redoCommands.iterator(); it.hasNext();) {
149            if (it.next().invalidBecauselayerRemoved(layer)) {
150                it.remove();
151                changed = true;
152            }
153        }
154        if (changed) {
155            fireCommandsChanged();
156        }
157    }
158
159    public void layerRemoved(Layer oldLayer) {
160        clean(oldLayer);
161    }
162
163    public void layerAdded(Layer newLayer) {}
164    public void activeLayerChange(Layer oldLayer, Layer newLayer) {}
165
166    public void removeCommandQueueListener(CommandQueueListener l) {
167        listenerCommands.remove(l);
168    }
169
170    public boolean addCommandQueueListener(CommandQueueListener l) {
171        return listenerCommands.add(l);
172    }
173}
Note: See TracBrowser for help on using the repository browser.