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

Last change on this file since 2541 was 2541, checked in by stoecker, 14 years ago

fixed #2539 - redone last fix a bit

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