diff --git a/game-app/game-core/src/main/java/games/strategy/engine/history/History.java b/game-app/game-core/src/main/java/games/strategy/engine/history/History.java index 6d146233c87..36a6751d00e 100644 --- a/game-app/game-core/src/main/java/games/strategy/engine/history/History.java +++ b/game-app/game-core/src/main/java/games/strategy/engine/history/History.java @@ -9,6 +9,7 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.List; +import java.util.Optional; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; @@ -131,12 +132,15 @@ public synchronized void gotoNode(final HistoryNode node) { * removes all changes that occurred after this node. */ public synchronized void removeAllHistoryAfterNode(final HistoryNode removeAfterNode) { - gotoNode(removeAfterNode); assertCorrectThread(); + if (!seekingEnabled) { + nextChangeIndex = changes.size(); + seekingEnabled = true; + } + gotoNode(getNearestLeafAtOrBefore(removeAfterNode).orElse((HistoryNode) getRoot())); try (GameData.Unlocker ignored = gameData.acquireWriteLock()) { - final int lastChange = getLastChange(removeAfterNode) + 1; - while (changes.size() > lastChange) { - changes.remove(lastChange); + if (changes.size() > nextChangeIndex) { + changes.subList(nextChangeIndex, changes.size()).clear(); } final Enumeration enumeration = ((DefaultMutableTreeNode) this.getRoot()).preorderEnumeration(); @@ -147,7 +151,7 @@ public synchronized void removeAllHistoryAfterNode(final HistoryNode removeAfter final HistoryNode node = (HistoryNode) enumeration.nextElement(); if (node instanceof IndexedHistoryNode) { final int index = ((IndexedHistoryNode) node).getChangeStartIndex(); - if (index >= lastChange) { + if (index >= nextChangeIndex) { startRemoving = true; } if (startRemoving) { @@ -155,12 +159,19 @@ public synchronized void removeAllHistoryAfterNode(final HistoryNode removeAfter } } } - while (!nodesToRemove.isEmpty()) { - removeNodeFromParent(nodesToRemove.remove(0)); + for (HistoryNode node : nodesToRemove) { + removeNodeFromParent(node); } } } + public Optional getNearestLeafAtOrBefore(HistoryNode node) { + if (node.isLeaf()) { + return Optional.of(node); + } + return Optional.ofNullable((HistoryNode) node.getPreviousLeaf()); + } + synchronized void changeAdded(final Change change) { changes.add(change); if (seekingEnabled && nextChangeIndex == changes.size()) { diff --git a/game-app/game-core/src/main/java/games/strategy/triplea/ui/TripleAFrame.java b/game-app/game-core/src/main/java/games/strategy/triplea/ui/TripleAFrame.java index 825dc6ec839..ddae5db8437 100644 --- a/game-app/game-core/src/main/java/games/strategy/triplea/ui/TripleAFrame.java +++ b/game-app/game-core/src/main/java/games/strategy/triplea/ui/TripleAFrame.java @@ -1881,7 +1881,6 @@ public void actionPerformed(final ActionEvent ae) { Injections.getInstance().getEngineVersion()) .orElse(null); if (datacopy != null) { - datacopy.getHistory().gotoNode(historyPanel.getCurrentPopupNode()); datacopy .getHistory() .removeAllHistoryAfterNode(historyPanel.getCurrentPopupNode()); @@ -1901,14 +1900,11 @@ public void actionPerformed(final ActionEvent ae) { datacopy.getSequence().getStep(0).getDisplayName(); GamePlayer currentPlayer = datacopy.getSequence().getStep(0).getPlayerId(); + int roundOffset = datacopy.getSequence().getRoundOffset(); while (enumeration.hasMoreElements()) { final HistoryNode node = (HistoryNode) enumeration.nextElement(); if (node instanceof Round) { - round = - Math.max( - 0, - ((Round) node).getRoundNo() - - datacopy.getSequence().getRoundOffset()); + round = Math.max(0, ((Round) node).getRoundNo() - roundOffset); currentPlayer = null; stepDisplayName = node.getTitle(); } else if (node instanceof Step) { diff --git a/game-app/game-core/src/main/java/games/strategy/triplea/ui/history/HistoryPanel.java b/game-app/game-core/src/main/java/games/strategy/triplea/ui/history/HistoryPanel.java index f51c36f3755..27ccde8f932 100644 --- a/game-app/game-core/src/main/java/games/strategy/triplea/ui/history/HistoryPanel.java +++ b/game-app/game-core/src/main/java/games/strategy/triplea/ui/history/HistoryPanel.java @@ -275,13 +275,8 @@ private void gotoNode(final HistoryNode node) { // If this is not a leaf node, set the game state to the last leaf node before it. This way, // selecting something like "Round 3" shows the state at the start of the round, which ensures // chronological order when moving up/down the nodes using arrow keys even if some are expanded. - if (!node.isLeaf()) { - final TreeNode leaf = node.getPreviousLeaf(); - // If no previous leaf, select the root node. - data.getHistory().gotoNode((HistoryNode) Optional.ofNullable(leaf).orElse(node.getRoot())); - } else { - data.getHistory().gotoNode(node); - } + Optional target = data.getHistory().getNearestLeafAtOrBefore(node); + data.getHistory().gotoNode(target.orElse((HistoryNode) node.getRoot())); } public HistoryNode getCurrentNode() {