diff --git a/src/org/openstreetmap/josm/command/Command.java b/src/org/openstreetmap/josm/command/Command.java
index 945967a..a865bea 100644
a
|
b
|
public abstract class Command extends PseudoCommand {
|
147 | 147 | /** |
148 | 148 | * Executes the command on the dataset. This implementation will remember all |
149 | 149 | * primitives returned by fillModifiedData for restoring them on undo. |
| 150 | * <p> |
| 151 | * The layer is invalidated after execution so that it can be re-painted. |
150 | 152 | * @return true |
151 | 153 | */ |
152 | 154 | public boolean executeCommand() { |
… |
… |
public abstract class Command extends PseudoCommand {
|
299 | 301 | return Objects.equals(cloneMap, command.cloneMap) && |
300 | 302 | Objects.equals(layer, command.layer); |
301 | 303 | } |
| 304 | |
| 305 | /** |
| 306 | * Invalidate all layers that were affected by this command. |
| 307 | * @see Layer#invalidate() |
| 308 | */ |
| 309 | public void invalidateAffectedLayers() { |
| 310 | OsmDataLayer layer = getLayer(); |
| 311 | if (layer != null) { |
| 312 | layer.invalidate(); |
| 313 | } |
| 314 | } |
302 | 315 | } |
diff --git a/src/org/openstreetmap/josm/command/SequenceCommand.java b/src/org/openstreetmap/josm/command/SequenceCommand.java
index 22428c8..eb74259 100644
a
|
b
|
public class SequenceCommand extends Command {
|
125 | 125 | } |
126 | 126 | |
127 | 127 | @Override |
| 128 | public void invalidateAffectedLayers() { |
| 129 | super.invalidateAffectedLayers(); |
| 130 | for (Command c : sequence) { |
| 131 | c.invalidateAffectedLayers(); |
| 132 | } |
| 133 | } |
| 134 | |
| 135 | @Override |
128 | 136 | public int hashCode() { |
129 | 137 | return Objects.hash(super.hashCode(), Arrays.hashCode(sequence), sequenceComplete, name, continueOnError); |
130 | 138 | } |
diff --git a/src/org/openstreetmap/josm/data/UndoRedoHandler.java b/src/org/openstreetmap/josm/data/UndoRedoHandler.java
index 7118052..bb39aae 100644
a
|
b
|
import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
|
14 | 14 | import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener; |
15 | 15 | import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent; |
16 | 16 | import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent; |
| 17 | import org.openstreetmap.josm.gui.layer.OsmDataLayer; |
17 | 18 | import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener; |
18 | 19 | import org.openstreetmap.josm.tools.CheckParameterUtil; |
19 | 20 | |
| 21 | /** |
| 22 | * This is the global undo/redo handler for all {@link OsmDataLayer}s. |
| 23 | * <p> |
| 24 | * If you want to change a data layer, you can use {@link #add(Command)} to execute a command on it and make that command undoable. |
| 25 | */ |
20 | 26 | public class UndoRedoHandler implements LayerChangeListener { |
21 | 27 | |
22 | 28 | /** |
… |
… |
public class UndoRedoHandler implements LayerChangeListener {
|
44 | 50 | public void addNoRedraw(final Command c) { |
45 | 51 | CheckParameterUtil.ensureParameterNotNull(c, "c"); |
46 | 52 | c.executeCommand(); |
| 53 | c.invalidateAffectedLayers(); |
47 | 54 | commands.add(c); |
48 | 55 | // Limit the number of commands in the undo list. |
49 | 56 | // Currently you have to undo the commands one by one. If |
… |
… |
public class UndoRedoHandler implements LayerChangeListener {
|
54 | 61 | redoCommands.clear(); |
55 | 62 | } |
56 | 63 | |
| 64 | /** |
| 65 | * Fires a commands change event after adding a command. |
| 66 | */ |
57 | 67 | public void afterAdd() { |
58 | 68 | fireCommandsChanged(); |
59 | | |
60 | | // the command may have changed the selection so tell the listeners about the current situation |
61 | | DataSet ds = Main.getLayerManager().getEditDataSet(); |
62 | | if (ds != null) { |
63 | | ds.fireSelectionChanged(); |
64 | | } |
65 | 69 | } |
66 | 70 | |
67 | 71 | /** |
… |
… |
public class UndoRedoHandler implements LayerChangeListener {
|
69 | 73 | * @param c The command to execute. Must not be {@code null}. |
70 | 74 | */ |
71 | 75 | public synchronized void add(final Command c) { |
| 76 | DataSet ds = Main.getLayerManager().getEditDataSet(); |
| 77 | Collection<? extends OsmPrimitive> oldSelection = ds.getSelected(); |
72 | 78 | addNoRedraw(c); |
73 | 79 | afterAdd(); |
| 80 | |
| 81 | // the command may have changed the selection so tell the listeners about the current situation |
| 82 | fireIfSelectionChanged(ds, oldSelection); |
74 | 83 | } |
75 | 84 | |
76 | 85 | /** |
… |
… |
public class UndoRedoHandler implements LayerChangeListener {
|
87 | 96 | public synchronized void undo(int num) { |
88 | 97 | if (commands.isEmpty()) |
89 | 98 | return; |
90 | | Collection<? extends OsmPrimitive> oldSelection = Main.getLayerManager().getEditDataSet().getSelected(); |
91 | | Main.getLayerManager().getEditDataSet().beginUpdate(); |
| 99 | DataSet ds = Main.getLayerManager().getEditDataSet(); |
| 100 | Collection<? extends OsmPrimitive> oldSelection = ds.getSelected(); |
| 101 | ds.beginUpdate(); |
92 | 102 | try { |
93 | 103 | for (int i = 1; i <= num; ++i) { |
94 | 104 | final Command c = commands.removeLast(); |
95 | 105 | c.undoCommand(); |
| 106 | c.invalidateAffectedLayers(); |
96 | 107 | redoCommands.addFirst(c); |
97 | 108 | if (commands.isEmpty()) { |
98 | 109 | break; |
99 | 110 | } |
100 | 111 | } |
101 | 112 | } finally { |
102 | | Main.getLayerManager().getEditDataSet().endUpdate(); |
| 113 | ds.endUpdate(); |
103 | 114 | } |
104 | 115 | fireCommandsChanged(); |
105 | | Collection<? extends OsmPrimitive> newSelection = Main.getLayerManager().getEditDataSet().getSelected(); |
106 | | if (!oldSelection.equals(newSelection)) { |
107 | | Main.getLayerManager().getEditDataSet().fireSelectionChanged(); |
108 | | } |
| 116 | fireIfSelectionChanged(ds, oldSelection); |
109 | 117 | } |
110 | 118 | |
111 | 119 | /** |
… |
… |
public class UndoRedoHandler implements LayerChangeListener {
|
122 | 130 | public void redo(int num) { |
123 | 131 | if (redoCommands.isEmpty()) |
124 | 132 | return; |
125 | | Collection<? extends OsmPrimitive> oldSelection = Main.getLayerManager().getEditDataSet().getSelected(); |
| 133 | DataSet ds = Main.getLayerManager().getEditDataSet(); |
| 134 | Collection<? extends OsmPrimitive> oldSelection = ds.getSelected(); |
126 | 135 | for (int i = 0; i < num; ++i) { |
127 | 136 | final Command c = redoCommands.removeFirst(); |
128 | 137 | c.executeCommand(); |
| 138 | c.invalidateAffectedLayers(); |
129 | 139 | commands.add(c); |
130 | 140 | if (redoCommands.isEmpty()) { |
131 | 141 | break; |
132 | 142 | } |
133 | 143 | } |
134 | 144 | fireCommandsChanged(); |
135 | | Collection<? extends OsmPrimitive> newSelection = Main.getLayerManager().getEditDataSet().getSelected(); |
| 145 | fireIfSelectionChanged(ds, oldSelection); |
| 146 | } |
| 147 | |
| 148 | private static void fireIfSelectionChanged(DataSet ds, Collection<? extends OsmPrimitive> oldSelection) { |
| 149 | Collection<? extends OsmPrimitive> newSelection = ds.getSelected(); |
136 | 150 | if (!oldSelection.equals(newSelection)) { |
137 | | Main.getLayerManager().getEditDataSet().fireSelectionChanged(); |
| 151 | ds.fireSelectionChanged(); |
138 | 152 | } |
139 | 153 | } |
140 | 154 | |
141 | | public void fireCommandsChanged() { |
| 155 | /** |
| 156 | * Fires a command change to all listeners. |
| 157 | */ |
| 158 | private void fireCommandsChanged() { |
142 | 159 | for (final CommandQueueListener l : listenerCommands) { |
143 | 160 | l.commandChanged(commands.size(), redoCommands.size()); |
144 | 161 | } |
145 | 162 | } |
146 | 163 | |
| 164 | /** |
| 165 | * Resets the undo/redo list. |
| 166 | */ |
147 | 167 | public void clean() { |
148 | 168 | redoCommands.clear(); |
149 | 169 | commands.clear(); |
150 | 170 | fireCommandsChanged(); |
151 | 171 | } |
152 | 172 | |
| 173 | /** |
| 174 | * Resets all commands that affect the given layer. |
| 175 | * @param layer The layer that was affected. |
| 176 | */ |
153 | 177 | public void clean(Layer layer) { |
154 | 178 | if (layer == null) |
155 | 179 | return; |
diff --git a/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java b/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
index 1b37a88..28febcc 100644
a
|
b
|
public class ValidatorDialog extends ToggleDialog implements SelectionChangedLis
|
607 | 607 | } |
608 | 608 | |
609 | 609 | @Override |
610 | | protected void realRun() throws SAXException, IOException, |
611 | | OsmTransferException { |
| 610 | protected void realRun() throws SAXException, IOException, OsmTransferException { |
612 | 611 | ProgressMonitor monitor = getProgressMonitor(); |
613 | 612 | try { |
614 | 613 | monitor.setTicksCount(testErrors.size()); |
| 614 | final DataSet ds = Main.getLayerManager().getEditDataSet(); |
615 | 615 | int i = 0; |
616 | 616 | SwingUtilities.invokeAndWait(new Runnable() { |
617 | 617 | @Override |
618 | 618 | public void run() { |
619 | | Main.getLayerManager().getEditDataSet().beginUpdate(); |
| 619 | ds.beginUpdate(); |
620 | 620 | } |
621 | 621 | }); |
622 | 622 | try { |
… |
… |
public class ValidatorDialog extends ToggleDialog implements SelectionChangedLis
|
632 | 632 | SwingUtilities.invokeAndWait(new Runnable() { |
633 | 633 | @Override |
634 | 634 | public void run() { |
635 | | Main.getLayerManager().getEditDataSet().endUpdate(); |
| 635 | ds.endUpdate(); |
636 | 636 | } |
637 | 637 | }); |
638 | 638 | } |
… |
… |
public class ValidatorDialog extends ToggleDialog implements SelectionChangedLis
|
643 | 643 | Main.main.undoRedo.afterAdd(); |
644 | 644 | Main.map.repaint(); |
645 | 645 | tree.resetErrors(); |
646 | | Main.getLayerManager().getEditDataSet().fireSelectionChanged(); |
| 646 | ds.fireSelectionChanged(); |
647 | 647 | } |
648 | 648 | }); |
649 | 649 | } catch (InterruptedException | InvocationTargetException e) { |
diff --git a/test/unit/org/openstreetmap/josm/actions/mapmode/DrawActionTest.java b/test/unit/org/openstreetmap/josm/actions/mapmode/DrawActionTest.java
index e7ac1b4..1bd00dc 100644
a
|
b
|
public class DrawActionTest {
|
52 | 52 | public void testTicket12011() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { |
53 | 53 | DataSet dataSet = new DataSet(); |
54 | 54 | OsmDataLayer layer = new OsmDataLayer(dataSet, OsmDataLayer.createNewName(), null); |
| 55 | Main.getLayerManager().addLayer(layer); |
55 | 56 | |
56 | 57 | Field mapView = MapFrame.class.getDeclaredField("mapView"); |
57 | 58 | Utils.setObjectsAccessible(mapView); |
… |
… |
public class DrawActionTest {
|
67 | 68 | w.setNodes(Arrays.asList(new Node[] {n1, n2})); |
68 | 69 | dataSet.addPrimitive(w); |
69 | 70 | |
70 | | Main.getLayerManager().addLayer(layer); |
71 | 71 | try { |
72 | 72 | assertTrue(Main.map.selectDrawTool(false)); |
73 | 73 | |