Added game tab support

+ GamePane component with the game displaying functionality from
MainWindow
- Simplified MainWindow, added JTabbedPane with GamePane elements
- Adjusted FENDropTarget and MenuBar
This commit is contained in:
Kai S. K. Engelbart 2019-08-23 22:00:30 +02:00
parent 7271f7b3a3
commit 961100f74c
4 changed files with 151 additions and 105 deletions

View File

@ -19,26 +19,27 @@ import java.util.List;
*/ */
public class FENDropTarget extends DropTargetAdapter { public class FENDropTarget extends DropTargetAdapter {
private MainWindow mainWindow; private GamePane gamePane;
public FENDropTarget(MainWindow mainWindow) { public FENDropTarget(GamePane gamePane) {
this.mainWindow = mainWindow; this.gamePane = gamePane;
} }
@Override @Override
public void drop(DropTargetDropEvent evt) { public void drop(DropTargetDropEvent evt) {
try { try {
evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
@SuppressWarnings("unchecked") @SuppressWarnings(
List<File> droppedFiles = (List<File>) evt.getTransferable() "unchecked"
.getTransferData(DataFlavor.javaFileListFlavor); )
List<File> droppedFiles = (List<File>) evt.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
try (BufferedReader br = new BufferedReader(new FileReader(droppedFiles.get(0)))) { try (BufferedReader br = new BufferedReader(new FileReader(droppedFiles.get(0)))) {
mainWindow.getGame().reset(); gamePane.getGame().reset();
mainWindow.getGame().getBoard().initFromFEN(br.readLine()); gamePane.getGame().getBoard().initFromFEN(br.readLine());
mainWindow.getBoardPane().getBoardComponent().repaint(); gamePane.getBoardPane().getBoardComponent().repaint();
mainWindow.getGame() gamePane.getGame()
.getPlayers() .getPlayers()
.get(mainWindow.getGame().getBoard().getLog().getActiveColor()) .get(gamePane.getGame().getBoard().getLog().getActiveColor())
.requestMove(); .requestMove();
evt.dropComplete(true); evt.dropComplete(true);
} }

View File

@ -0,0 +1,93 @@
package dev.kske.chess.ui;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.dnd.DropTarget;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import dev.kske.chess.board.Piece.Color;
import dev.kske.chess.game.Game;
import dev.kske.chess.game.NaturalPlayer;
/**
* Project: <strong>Chess</strong><br>
* File: <strong>GamePane.java</strong><br>
* Created: <strong>23.08.2019</strong><br>
* Author: <strong>Kai S. K. Engelbart</strong>
*/
public class GamePane extends JComponent {
private static final long serialVersionUID = 4349772338239617477L;
private JButton btnRestart, btnSwapColors;
private BoardPane boardPane;
private Game game;
private Color activeColor;
@SuppressWarnings(
"unused"
)
public GamePane() {
setLayout(new BorderLayout());
boardPane = new BoardPane();
add(boardPane, BorderLayout.CENTER);
JPanel toolPanel = new JPanel();
btnRestart = new JButton("Restart");
btnRestart.addActionListener((evt) -> {
if (game != null) game.reset();
game.start();
});
activeColor = Color.WHITE;
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);
add(toolPanel, BorderLayout.NORTH);
JPanel letterPanel = new JPanel(new GridLayout(1, 8));
for (int i = 0; i < 8; i++) {
JLabel letterLabel = new JLabel(String.valueOf((char) (65 + i)));
letterLabel.setHorizontalAlignment(JLabel.CENTER);
letterPanel.add(letterLabel);
}
add(letterPanel, BorderLayout.SOUTH);
JPanel numberPanel = new JPanel(new GridLayout(8, 1));
for (int i = 0; i < 8; i++)
numberPanel.add(new JLabel(String.valueOf(8 - i)));
add(numberPanel, BorderLayout.EAST);
new DropTarget(this, new FENDropTarget(this));
}
public BoardPane getBoardPane() { return boardPane; }
/**
* @return The {@link Game} instance associated with this board 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.disconnect();
this.game = game;
btnSwapColors.setEnabled(game.getPlayers().get(Color.WHITE) instanceof NaturalPlayer
^ game.getPlayers().get(Color.BLACK) instanceof NaturalPlayer);
}
}

View File

@ -1,19 +1,10 @@
package dev.kske.chess.ui; package dev.kske.chess.ui;
import java.awt.BorderLayout;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.dnd.DropTarget;
import javax.swing.JButton;
import javax.swing.JFrame; import javax.swing.JFrame;
import javax.swing.JLabel; import javax.swing.JTabbedPane;
import javax.swing.JPanel;
import dev.kske.chess.board.Piece.Color;
import dev.kske.chess.game.Game;
import dev.kske.chess.game.NaturalPlayer;
/** /**
* Project: <strong>Chess</strong><br> * Project: <strong>Chess</strong><br>
@ -23,22 +14,21 @@ import dev.kske.chess.game.NaturalPlayer;
*/ */
public class MainWindow { public class MainWindow {
private JFrame mframe; private JFrame frame;
private JButton btnRestart, btnSwapColors; private JTabbedPane tabbedPane;
private BoardPane boardPane;
private Game game;
private Color activeColor;
/** /**
* Launch the application. * Launch the application.
*/ */
@SuppressWarnings(
"unused"
)
public static void main(String[] args) { public static void main(String[] args) {
EventQueue.invokeLater(() -> { EventQueue.invokeLater(() -> {
try { try {
MainWindow window = new MainWindow(); new MainWindow();
window.mframe.setVisible(true); } catch (Exception ex) {
} catch (Exception e) { ex.printStackTrace();
e.printStackTrace();
} }
}); });
} }
@ -53,67 +43,29 @@ public class MainWindow {
/** /**
* Initialize the contents of the frame. * Initialize the contents of the frame.
*/ */
@SuppressWarnings(
"unused"
)
private void initialize() { private void initialize() {
mframe = new JFrame("Chess by Kai S. K. Engelbart"); // Configure frame
mframe.setResizable(false); frame = new JFrame("Chess by Kai S. K. Engelbart");
mframe.setBounds(100, 100, 494, 565); frame.setResizable(false);
mframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setBounds(100, 100, 494, 565);
mframe.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/pieces/queen_white.png"))); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("/pieces/queen_white.png")));
boardPane = new BoardPane(); // Add frame content
mframe.getContentPane().add(boardPane, BorderLayout.CENTER); tabbedPane = new JTabbedPane();
tabbedPane.add("Game 1", new GamePane());
frame.getContentPane().add(tabbedPane);
JPanel toolPanel = new JPanel(); frame.setJMenuBar(new MenuBar(this));
btnRestart = new JButton("Restart");
btnRestart.addActionListener((evt) -> {
if (game != null) game.reset();
game.start();
});
activeColor = Color.WHITE; // Update position and dimensions
btnSwapColors = new JButton("Play as black"); frame.pack();
btnSwapColors.addActionListener((evt) -> { frame.setLocationRelativeTo(null);
game.swapColors(); frame.setVisible(true);
btnSwapColors.setText("Play as " + activeColor.toString().toLowerCase());
activeColor = activeColor.opposite();
});
toolPanel.add(btnRestart);
toolPanel.add(btnSwapColors);
mframe.getContentPane().add(toolPanel, BorderLayout.NORTH);
JPanel letterPanel = new JPanel(new GridLayout(1, 8));
for (int i = 0; i < 8; i++) {
JLabel letterLabel = new JLabel(String.valueOf((char) (65 + i)));
letterLabel.setHorizontalAlignment(JLabel.CENTER);
letterPanel.add(letterLabel);
}
mframe.add(letterPanel, BorderLayout.SOUTH);
JPanel numberPanel = new JPanel(new GridLayout(8, 1));
for (int i = 0; i < 8; i++)
numberPanel.add(new JLabel(String.valueOf(8 - i)));
mframe.add(numberPanel, BorderLayout.EAST);
mframe.setJMenuBar(new MenuBar(this));
new DropTarget(mframe, new FENDropTarget(this));
mframe.pack();
mframe.setLocationRelativeTo(null);
} }
public BoardPane getBoardPane() { return boardPane; } /**
* @return The currently selected {@link GamePane} component
public Game getGame() { return game; } */
public GamePane getSelectedGamePane() { return (GamePane) tabbedPane.getSelectedComponent(); }
public void setGame(Game game) {
if (this.game != null) this.game.disconnect();
this.game = game;
btnSwapColors.setEnabled(game.getPlayers().get(Color.WHITE) instanceof NaturalPlayer
^ game.getPlayers().get(Color.BLACK) instanceof NaturalPlayer);
}
} }

View File

@ -21,11 +21,9 @@ public class MenuBar extends JMenuBar {
private static final long serialVersionUID = -7221583703531248228L; private static final long serialVersionUID = -7221583703531248228L;
private final MainWindow mainWindow; private final MainWindow mainWindow;
private final BoardPane boardPane;
public MenuBar(MainWindow mainWindow) { public MenuBar(MainWindow mainWindow) {
this.mainWindow = mainWindow; this.mainWindow = mainWindow;
boardPane = mainWindow.getBoardPane();
initGameMenu(); initGameMenu();
initEngineMenu(); initEngineMenu();
@ -38,14 +36,15 @@ public class MenuBar extends JMenuBar {
newGameMenuItem.addActionListener((evt) -> { newGameMenuItem.addActionListener((evt) -> {
GameConfigurationDialog dialog = new GameConfigurationDialog(); GameConfigurationDialog dialog = new GameConfigurationDialog();
dialog.setVisible(true); dialog.setVisible(true);
if (dialog.isStartGame()) startGame(new Game(boardPane, dialog.getWhiteName(), dialog.getBlackName())); if (dialog.isStartGame()) startGame(new Game(mainWindow.getSelectedGamePane().getBoardPane(),
dialog.getWhiteName(), dialog.getBlackName()));
}); });
gameMenu.add(newGameMenuItem); gameMenu.add(newGameMenuItem);
add(gameMenu); add(gameMenu);
// Start a game // Start a game
startGame(new Game(boardPane, "Natural Player", "Natural Player")); startGame(new Game(mainWindow.getSelectedGamePane().getBoardPane(), "Natural Player", "Natural Player"));
} }
private void initEngineMenu() { private void initEngineMenu() {
@ -54,8 +53,7 @@ public class MenuBar extends JMenuBar {
JMenuItem addEngineMenuItem = new JMenuItem("Add engine"); JMenuItem addEngineMenuItem = new JMenuItem("Add engine");
addEngineMenuItem.addActionListener((evt) -> { addEngineMenuItem.addActionListener((evt) -> {
String enginePath = JOptionPane.showInputDialog(getParent(), String enginePath = JOptionPane.showInputDialog(getParent(),
"Enter the path to a UCI-compatible chess engine:", "Enter the path to a UCI-compatible chess engine:", "Engine selection",
"Engine selection",
JOptionPane.QUESTION_MESSAGE); JOptionPane.QUESTION_MESSAGE);
if (enginePath != null) EngineUtil.addEngine(enginePath); if (enginePath != null) EngineUtil.addEngine(enginePath);
}); });
@ -72,27 +70,29 @@ public class MenuBar extends JMenuBar {
// TODO: prevent multiple initializations // TODO: prevent multiple initializations
JMenuItem showLogMenuItem = new JMenuItem("Show move log"); JMenuItem showLogMenuItem = new JMenuItem("Show move log");
showLogMenuItem showLogMenuItem.addActionListener(
.addActionListener((evt) -> new LogFrame(mainWindow.getGame().getBoard().getLog()).setVisible(true)); (evt) -> new LogFrame(mainWindow.getSelectedGamePane().getGame().getBoard().getLog()).setVisible(true));
toolsMenu.add(showLogMenuItem); toolsMenu.add(showLogMenuItem);
JMenuItem exportFENMenuItem = new JMenuItem("Export board to FEN"); JMenuItem exportFENMenuItem = new JMenuItem("Export board to FEN");
exportFENMenuItem.addActionListener((evt) -> Toolkit.getDefaultToolkit() exportFENMenuItem.addActionListener((evt) -> Toolkit.getDefaultToolkit()
.getSystemClipboard() .getSystemClipboard()
.setContents(new StringSelection(mainWindow.getGame().getBoard().toFEN()), null)); .setContents(new StringSelection(mainWindow.getSelectedGamePane().getGame().getBoard().toFEN()), null));
toolsMenu.add(exportFENMenuItem); toolsMenu.add(exportFENMenuItem);
// TODO: Synchronize with game // TODO: Synchronize with game
JMenuItem loadFromFENMenuItem = new JMenuItem("Load board from FEN"); JMenuItem loadFromFENMenuItem = new JMenuItem("Load board from FEN");
loadFromFENMenuItem.addActionListener((evt) -> { loadFromFENMenuItem.addActionListener((evt) -> {
mainWindow.getGame().reset(); mainWindow.getSelectedGamePane().getGame().reset();
mainWindow.getGame() mainWindow.getSelectedGamePane()
.getGame()
.getBoard() .getBoard()
.initFromFEN(JOptionPane.showInputDialog("Enter a FEN string: ")); .initFromFEN(JOptionPane.showInputDialog("Enter a FEN string: "));
mainWindow.getBoardPane().getBoardComponent().repaint(); mainWindow.getSelectedGamePane().getBoardPane().getBoardComponent().repaint();
mainWindow.getGame() mainWindow.getSelectedGamePane()
.getGame()
.getPlayers() .getPlayers()
.get(mainWindow.getGame().getBoard().getLog().getActiveColor()) .get(mainWindow.getSelectedGamePane().getGame().getBoard().getLog().getActiveColor())
.requestMove(); .requestMove();
}); });
toolsMenu.add(loadFromFENMenuItem); toolsMenu.add(loadFromFENMenuItem);
@ -101,7 +101,7 @@ public class MenuBar extends JMenuBar {
} }
private void startGame(Game game) { private void startGame(Game game) {
mainWindow.setGame(game); mainWindow.getSelectedGamePane().setGame(game);
// Update board and board component // Update board and board component
game.reset(); game.reset();