From f4768b7ac32a9493841ab459e53ca86407b10224 Mon Sep 17 00:00:00 2001 From: kske Date: Mon, 6 Jan 2020 15:03:20 +0200 Subject: [PATCH] Working on move history navigation * Enabled "next" and "previous" buttons * Added corresponding methods to Board * Added Move#invert() * Rendering variation count in MoveNodeRenderer The added functionality does not work correctly at the moment. This is probably caused due to missing synchronization between the state of the board, the game and the user interface. --- src/dev/kske/chess/board/Board.java | 28 +++++++++++++++++++++ src/dev/kske/chess/board/Move.java | 4 +++ src/dev/kske/chess/game/Game.java | 2 +- src/dev/kske/chess/ui/GamePane.java | 23 +++++++++++++++-- src/dev/kske/chess/ui/MoveNodeRenderer.java | 5 +++- 5 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/dev/kske/chess/board/Board.java b/src/dev/kske/chess/board/Board.java index 28d6cca..c634dff 100644 --- a/src/dev/kske/chess/board/Board.java +++ b/src/dev/kske/chess/board/Board.java @@ -8,6 +8,8 @@ import java.util.Map; import java.util.Objects; import dev.kske.chess.board.Piece.Color; +import dev.kske.chess.event.EventBus; +import dev.kske.chess.event.MoveEvent; /** * Project: Chess
@@ -120,6 +122,32 @@ public class Board { log.removeLast(); } + public void selectPreviousNode() { + MoveNode moveNode = log.getLast(); + Move move = moveNode.move; + + // Revert the move + move.revert(this, moveNode.capturedPiece); + + // Select previous move node + log.selectPreviousNode(); + + // Dispatch move event + EventBus.getInstance().dispatch(new MoveEvent(move.invert(), getGameEventType(log.getActiveColor().opposite()))); + } + + public void selectNextNode(int index) { + log.selectNextNode(index); + MoveNode moveNode = log.getLast(); + Move move = moveNode.move; + + // Execute the next move + move.execute(this); + + // Dispatch move event + EventBus.getInstance().dispatch(new MoveEvent(move, getGameEventType(log.getActiveColor().opposite()))); + } + /** * Generated every legal move for one color * diff --git a/src/dev/kske/chess/board/Move.java b/src/dev/kske/chess/board/Move.java index 2ff63e2..267f53e 100644 --- a/src/dev/kske/chess/board/Move.java +++ b/src/dev/kske/chess/board/Move.java @@ -43,6 +43,10 @@ public class Move { board.set(pos, board.get(dest)); board.set(dest, capturedPiece); } + + public Move invert() { + return new Move(dest, pos); + } public static Move fromLAN(String move) { Position pos = Position.fromLAN(move.substring(0, 2)); diff --git a/src/dev/kske/chess/game/Game.java b/src/dev/kske/chess/game/Game.java index 2005cd0..b3f5171 100644 --- a/src/dev/kske/chess/game/Game.java +++ b/src/dev/kske/chess/game/Game.java @@ -29,7 +29,7 @@ import dev.kske.chess.ui.OverlayComponent; */ public class Game { - private Map players = new HashMap<>(); + private Map players = new HashMap<>(2); private Board board; private OverlayComponent overlayComponent; private BoardComponent boardComponent; diff --git a/src/dev/kske/chess/ui/GamePane.java b/src/dev/kske/chess/ui/GamePane.java index b8bf02d..2b542eb 100644 --- a/src/dev/kske/chess/ui/GamePane.java +++ b/src/dev/kske/chess/ui/GamePane.java @@ -12,6 +12,7 @@ import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; @@ -95,11 +96,29 @@ public class GamePane extends JComponent { moveSelectionPanel.add(btnFirst); btnPrevious = new JButton("Previous"); - btnPrevious.setEnabled(false); + btnPrevious.addActionListener((evt) -> { + if (game != null) { + game.getBoard().selectPreviousNode(); + getBoardPane().getOverlayComponent().clearArrow(); + repaint(); + } + }); moveSelectionPanel.add(btnPrevious); btnNext = new JButton("Next"); - btnNext.setEnabled(false); + btnNext.addActionListener((evt) -> { + if(game != null) { + int numVariations = game.getBoard().getLog().getLast().getVariations().size(); + int index; + if(numVariations == 1) + index = 1; + else + index = Integer.parseInt(JOptionPane.showInputDialog("Enter the variation index.")); + game.getBoard().selectNextNode(index); + getBoardPane().getOverlayComponent().clearArrow(); + repaint(); + } + }); moveSelectionPanel.add(btnNext); btnLast = new JButton("Last"); diff --git a/src/dev/kske/chess/ui/MoveNodeRenderer.java b/src/dev/kske/chess/ui/MoveNodeRenderer.java index f78bea5..7553052 100644 --- a/src/dev/kske/chess/ui/MoveNodeRenderer.java +++ b/src/dev/kske/chess/ui/MoveNodeRenderer.java @@ -26,7 +26,10 @@ public class MoveNodeRenderer extends JLabel implements ListCellRenderer list, MoveNode node, int index, boolean isSelected, boolean cellHasFocus) { setBorder(new EmptyBorder(5, 5, 5, 5)); - setText(node.move.toLAN()); + + int numVariations = node.hasVariations() ? node.getVariations().size() : 0; + setText(String.format("%s (%d)", node.move.toLAN(), numVariations)); + setBackground(isSelected ? Color.red : Color.white); setOpaque(true); return this;