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

Last change on this file since 3143 was 3143, checked in by bastiK, 14 years ago

limit the size of the undo stack

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