package dev.kske.chess.ui; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Insets; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import javax.swing.DefaultListModel; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import dev.kske.chess.board.MoveNode; import dev.kske.chess.board.Piece.Color; import dev.kske.chess.event.Event; import dev.kske.chess.event.EventBus; import dev.kske.chess.event.MoveEvent; import dev.kske.chess.event.Subscribable; import dev.kske.chess.game.Game; import dev.kske.chess.game.NaturalPlayer; /** * Project: Chess
* File: GamePane.java
* Created: 23.08.2019
* Author: Kai S. K. Engelbart */ public class GamePane extends JComponent { private static final long serialVersionUID = 4349772338239617477L; private JButton btnRestart, btnSwapColors; private BoardPane boardPane; private Game game; private Color activeColor; private JPanel moveSelectionPanel; private JButton btnNext; private JButton btnFirst; private JButton btnLast; public GamePane() { activeColor = Color.WHITE; GridBagLayout gridBagLayout = new GridBagLayout(); gridBagLayout.columnWidths = new int[] { 450, 1, 0 }; gridBagLayout.rowHeights = new int[] { 33, 267, 1, 0 }; gridBagLayout.columnWeights = new double[] { 0.0, 1.0, 1.0 }; gridBagLayout.rowWeights = new double[] { 1.0, 1.0, 1.0, Double.MIN_VALUE }; setLayout(gridBagLayout); JPanel toolPanel = new JPanel(); btnRestart = new JButton("Restart"); btnRestart.addActionListener((evt) -> { if (game != null) game.reset(); game.start(); }); btnSwapColors = new JButton("Play as black"); btnSwapColors.addActionListener((evt) -> { game.swapColors(); btnSwapColors.setText("Play as " + activeColor.toString().toLowerCase()); activeColor = activeColor.opposite(); }); toolPanel.add(btnRestart); toolPanel.add(btnSwapColors); GridBagConstraints gbc_toolPanel = new GridBagConstraints(); gbc_toolPanel.insets = new Insets(0, 0, 5, 5); gbc_toolPanel.anchor = GridBagConstraints.NORTH; gbc_toolPanel.fill = GridBagConstraints.HORIZONTAL; gbc_toolPanel.gridx = 0; gbc_toolPanel.gridy = 0; gbc_toolPanel.gridwidth = 2; add(toolPanel, gbc_toolPanel); moveSelectionPanel = new JPanel(); GridBagConstraints gbc_moveSelectionPanel = new GridBagConstraints(); gbc_moveSelectionPanel.insets = new Insets(0, 0, 5, 0); gbc_moveSelectionPanel.fill = GridBagConstraints.BOTH; gbc_moveSelectionPanel.gridx = 2; gbc_moveSelectionPanel.gridy = 0; add(moveSelectionPanel, gbc_moveSelectionPanel); btnFirst = new JButton("First"); btnFirst.setEnabled(false); moveSelectionPanel.add(btnFirst); JButton btnPreviousMove = new JButton("Previous"); btnPreviousMove.setEnabled(false); moveSelectionPanel.add(btnPreviousMove); btnNext = new JButton("Next"); btnNext.setEnabled(false); moveSelectionPanel.add(btnNext); btnLast = new JButton("Last"); btnLast.setEnabled(false); moveSelectionPanel.add(btnLast); boardPane = new BoardPane(); GridBagConstraints gbc_boardPane = new GridBagConstraints(); gbc_boardPane.insets = new Insets(0, 0, 5, 5); gbc_boardPane.fill = GridBagConstraints.BOTH; gbc_boardPane.gridx = 0; gbc_boardPane.gridy = 1; add(boardPane, gbc_boardPane); JPanel numberPanel = new JPanel(new GridLayout(8, 1)); GridBagConstraints gbc_numberPanel = new GridBagConstraints(); gbc_numberPanel.insets = new Insets(0, 0, 5, 5); gbc_numberPanel.anchor = GridBagConstraints.WEST; gbc_numberPanel.fill = GridBagConstraints.VERTICAL; gbc_numberPanel.gridx = 1; gbc_numberPanel.gridy = 1; add(numberPanel, gbc_numberPanel); JPanel letterPanel = new JPanel(new GridLayout(1, 8)); GridBagConstraints gbc_letterPanel = new GridBagConstraints(); gbc_letterPanel.insets = new Insets(0, 0, 0, 5); gbc_letterPanel.anchor = GridBagConstraints.NORTH; gbc_letterPanel.fill = GridBagConstraints.HORIZONTAL; gbc_letterPanel.gridx = 0; gbc_letterPanel.gridy = 2; add(letterPanel, gbc_letterPanel); // Initialize board coordinates for (int i = 0; i < 8; i++) { numberPanel.add(new JLabel(String.valueOf(8 - i))); JLabel letterLabel = new JLabel(String.valueOf((char) (65 + i))); letterLabel.setHorizontalAlignment(JLabel.CENTER); letterPanel.add(letterLabel); } JScrollPane scrollPane = new JScrollPane(); GridBagConstraints gbc_scrollPane = new GridBagConstraints(); gbc_scrollPane.insets = new Insets(0, 0, 5, 0); gbc_scrollPane.fill = GridBagConstraints.BOTH; gbc_scrollPane.gridx = 2; gbc_scrollPane.gridy = 1; add(scrollPane, gbc_scrollPane); JList pgnList = new JList<>(); pgnList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); pgnList.setLayoutOrientation(JList.HORIZONTAL_WRAP); pgnList.setVisibleRowCount(0); pgnList.setCellRenderer(new MoveNodeRenderer()); scrollPane.setViewportView(pgnList); EventBus.getInstance().register(new Subscribable() { // TODO: Clean on restart @Override public void handle(Event event) { if (game.getBoard().getLog() == null || game.getBoard().getLog().isEmpty()) return; DefaultListModel model = new DefaultListModel<>(); game.getBoard().getLog().forEach(node -> model.addElement(node)); pgnList.setModel(model); } @Override public Set> supports() { return new HashSet<>(Arrays.asList(MoveEvent.class)); } }); } /** * @return The {@link BoardPane} instance associated with this game pane */ public BoardPane getBoardPane() { return boardPane; } /** * @return The {@link Game} instance associated with this game pane */ public Game getGame() { return game; } /** * Assigns a new {@link Game} instance to this game pane. If exactly one of the * players is natural, color swapping functionality is enabled. * * @param game The {@link Game} to assign to this game pane. */ public void setGame(Game game) { if (this.game != null) this.game.stop(); this.game = game; btnSwapColors.setEnabled(game.getPlayers().get(Color.WHITE) instanceof NaturalPlayer ^ game.getPlayers().get(Color.BLACK) instanceof NaturalPlayer); } }