diff --git a/src/dev/kske/chess/ui/DialogUtil.java b/src/dev/kske/chess/ui/DialogUtil.java index e69f3d7..f591881 100644 --- a/src/dev/kske/chess/ui/DialogUtil.java +++ b/src/dev/kske/chess/ui/DialogUtil.java @@ -15,6 +15,7 @@ import javax.swing.JFileChooser; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.filechooser.FileFilter; import dev.kske.chess.io.EngineUtil; @@ -28,11 +29,25 @@ public class DialogUtil { private DialogUtil() {} - public static void showFileSelectionDialog(Component parent, Consumer action) { + public static void showFileSelectionDialog(Component parent, Consumer> action) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setCurrentDirectory(new File(System.getProperty("user.home"))); - if (fileChooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) - action.accept(fileChooser.getSelectedFile()); + fileChooser.setAcceptAllFileFilterUsed(false); + fileChooser.addChoosableFileFilter(new FileFilter() { + + @Override + public boolean accept(File f) { + int dotIndex = f.getName().lastIndexOf('.'); + if (dotIndex >= 0) { + String extension = f.getName().substring(dotIndex).toLowerCase(); + return extension.equals(".fen") || extension.equals(".pgn"); + } else return f.isDirectory(); + } + + @Override + public String getDescription() { return "FEN and PGN files"; } + }); + if (fileChooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) action.accept(Arrays.asList(fileChooser.getSelectedFile())); } public static void showGameConfigurationDialog(Component parent, BiConsumer action) { diff --git a/src/dev/kske/chess/ui/FENDropTarget.java b/src/dev/kske/chess/ui/FENDropTarget.java deleted file mode 100644 index aea43b3..0000000 --- a/src/dev/kske/chess/ui/FENDropTarget.java +++ /dev/null @@ -1,66 +0,0 @@ -package dev.kske.chess.ui; - -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.awt.dnd.DnDConstants; -import java.awt.dnd.DropTargetAdapter; -import java.awt.dnd.DropTargetDropEvent; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.List; - -import javax.swing.JOptionPane; - -import dev.kske.chess.board.FENString; -import dev.kske.chess.exception.ChessException; -import dev.kske.chess.game.Game; - -/** - * Project: Chess
- * File: FENDropTarget.java
- * Created: 13 Aug 2019
- * Author: Kai S. K. Engelbart - */ -public class FENDropTarget extends DropTargetAdapter { - - private MainWindow mainWindow; - - public FENDropTarget(MainWindow mainWindow) { this.mainWindow = mainWindow; } - - @SuppressWarnings("unchecked") - @Override - public void drop(DropTargetDropEvent evt) { - try { - evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); - ((List) evt.getTransferable().getTransferData(DataFlavor.javaFileListFlavor)).forEach(file -> { - try (BufferedReader br = new BufferedReader(new FileReader(file))) { - final GamePane gamePane = mainWindow.addGamePane(); - final String fen = br.readLine(); - DialogUtil.showGameConfigurationDialog(null, (whiteName, blackName) -> { - Game game; - try { - game = new Game(gamePane.getBoardPane(), whiteName, blackName, new FENString(fen).getBoard()); - gamePane.setGame(game); - game.start(); - } catch (ChessException e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(mainWindow, - "Failed to load FEN string: " + e.toString(), - "FEN loading error", - JOptionPane.ERROR_MESSAGE); - } - }); - evt.dropComplete(true); - } catch (IOException e) { - e.printStackTrace(); - evt.rejectDrop(); - } - }); - } catch (UnsupportedFlavorException | IOException ex) { - ex.printStackTrace(); - evt.rejectDrop(); - } - } -} diff --git a/src/dev/kske/chess/ui/GameDropTarget.java b/src/dev/kske/chess/ui/GameDropTarget.java new file mode 100644 index 0000000..c6da82b --- /dev/null +++ b/src/dev/kske/chess/ui/GameDropTarget.java @@ -0,0 +1,35 @@ +package dev.kske.chess.ui; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DropTargetAdapter; +import java.awt.dnd.DropTargetDropEvent; +import java.io.File; +import java.io.IOException; +import java.util.List; + +/** + * Project: Chess
+ * File: GameDropTarget.java
+ * Created: 13 Aug 2019
+ * Author: Kai S. K. Engelbart + */ +public class GameDropTarget extends DropTargetAdapter { + + private MainWindow mainWindow; + + public GameDropTarget(MainWindow mainWindow) { this.mainWindow = mainWindow; } + + @SuppressWarnings("unchecked") + @Override + public void drop(DropTargetDropEvent evt) { + try { + evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); + mainWindow.loadFiles((List) evt.getTransferable().getTransferData(DataFlavor.javaFileListFlavor)); + } catch (UnsupportedFlavorException | IOException ex) { + ex.printStackTrace(); + evt.rejectDrop(); + } + } +} diff --git a/src/dev/kske/chess/ui/MainWindow.java b/src/dev/kske/chess/ui/MainWindow.java index edaa113..cb6271f 100644 --- a/src/dev/kske/chess/ui/MainWindow.java +++ b/src/dev/kske/chess/ui/MainWindow.java @@ -3,10 +3,23 @@ package dev.kske.chess.ui; import java.awt.EventQueue; import java.awt.Toolkit; import java.awt.dnd.DropTarget; +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.List; +import javax.swing.JComboBox; import javax.swing.JFrame; +import javax.swing.JOptionPane; import javax.swing.JTabbedPane; +import dev.kske.chess.board.Board; +import dev.kske.chess.board.FENString; +import dev.kske.chess.exception.ChessException; +import dev.kske.chess.game.Game; +import dev.kske.chess.pgn.PGNDatabase; +import dev.kske.chess.pgn.PGNGame; + /** * Project: Chess
* File: MainWindow.java
@@ -55,7 +68,7 @@ public class MainWindow extends JFrame { getContentPane().add(tabbedPane); setJMenuBar(new MenuBar(this)); - new DropTarget(this, new FENDropTarget(this)); + new DropTarget(this, new GameDropTarget(this)); // Update position and dimensions pack(); @@ -74,9 +87,7 @@ public class MainWindow extends JFrame { * * @return The new {@link GamePane} */ - public GamePane addGamePane() { - return addGamePane("Game " + (tabbedPane.getComponentCount() + 1)); - } + public GamePane addGamePane() { return addGamePane("Game " + (tabbedPane.getComponentCount() + 1)); } /** * Creates a new {@link GamePane}, adds it to the tabbed pane and opens it. @@ -91,12 +102,64 @@ public class MainWindow extends JFrame { return gamePane; } + public GamePane addGamePane(String title, Board board) { + GamePane gamePane = addGamePane(title); + DialogUtil.showGameConfigurationDialog(this, + (whiteName, blackName) -> { + Game game = new Game(gamePane.getBoardPane(), whiteName, blackName, board); + gamePane.setGame(game); + game.start(); + }); + return gamePane; + } + /** * Removes a {@link GamePane} form the tabbed pane. * * @param index The index of the {@link GamePane} to remove */ - public void removeGamePane(int index) { - tabbedPane.remove(index); + public void removeGamePane(int index) { tabbedPane.remove(index); } + + /** + * Loads a game file (FEN or PGN) and adds it to a new {@link GamePane}. + * + * @param files the files to load the game from + */ + public void loadFiles(List files) { + files.forEach(file -> { + final String name = file.getName().substring(0, file.getName().lastIndexOf('.')); + final String extension = file.getName().substring(file.getName().lastIndexOf('.')).toLowerCase(); + try { + Board board; + switch (extension) { + case ".fen": + board = new FENString(new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8)).getBoard(); + break; + case ".pgn": + PGNDatabase pgnDB = new PGNDatabase(); + pgnDB.load(file); + if (pgnDB.getGames().size() > 0) { + String[] gameNames = new String[pgnDB.getGames().size()]; + for (int i = 0; i < gameNames.length; i++) { + final PGNGame game = pgnDB.getGames().get(i); + gameNames[i] = String.format("%s vs %s: %s", game.getTag("White"), game.getTag("Black"), game.getTag("Result")); + } + JComboBox comboBox = new JComboBox<>(gameNames); + JOptionPane.showInputDialog(this, comboBox, "Select a game", JOptionPane.QUESTION_MESSAGE); + board = pgnDB.getGames().get(comboBox.getSelectedIndex()).getBoard(); + } else throw new ChessException("The PGN database '" + name + "' is empty!"); + break; + default: + throw new ChessException("The file extension '" + extension + "' is not supported!"); + } + addGamePane(name, board); + } catch (Exception e) { + e.printStackTrace(); + JOptionPane.showMessageDialog(this, + "Failed to load the file " + file.getName() + ": " + e.toString(), + "File loading error", + JOptionPane.ERROR_MESSAGE); + } + }); } } diff --git a/src/dev/kske/chess/ui/MenuBar.java b/src/dev/kske/chess/ui/MenuBar.java index 8e796db..a224268 100644 --- a/src/dev/kske/chess/ui/MenuBar.java +++ b/src/dev/kske/chess/ui/MenuBar.java @@ -2,11 +2,7 @@ package dev.kske.chess.ui; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import javax.swing.JComboBox; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; @@ -16,8 +12,6 @@ import dev.kske.chess.board.FENString; import dev.kske.chess.exception.ChessException; import dev.kske.chess.game.Game; import dev.kske.chess.io.EngineUtil; -import dev.kske.chess.pgn.PGNDatabase; -import dev.kske.chess.pgn.PGNGame; /** * Project: Chess
@@ -52,7 +46,7 @@ public class MenuBar extends JMenuBar { gameMenu.add(newGameMenuItem); JMenuItem loadFileMenu = new JMenuItem("Load game file"); - loadFileMenu.addActionListener((evt) -> DialogUtil.showFileSelectionDialog(mainWindow, this::loadFile)); + loadFileMenu.addActionListener((evt) -> DialogUtil.showFileSelectionDialog(mainWindow, mainWindow::loadFiles)); gameMenu.add(loadFileMenu); add(gameMenu); @@ -108,73 +102,4 @@ public class MenuBar extends JMenuBar { add(toolsMenu); } - - private void loadFile(File file) { - final String name = file.getName().substring(0, file.getName().lastIndexOf('.')); - final String extension = file.getName().substring(file.getName().lastIndexOf('.')).toLowerCase(); - switch (extension) { - case ".fen": - try { - final GamePane gamePane = mainWindow.addGamePane(name); - final String fen = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); - DialogUtil.showGameConfigurationDialog(mainWindow, (whiteName, blackName) -> { - Game game; - try { - game = new Game(gamePane.getBoardPane(), whiteName, blackName, new FENString(fen).getBoard()); - gamePane.setGame(game); - game.start(); - } catch (ChessException e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(mainWindow, - "Failed to load FEN string: " + e.toString(), - "FEN loading error", - JOptionPane.ERROR_MESSAGE); - } - }); - } catch (Exception e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(mainWindow, - "Failed to load the file " + file.getName() + ": " + e.toString(), - "File loading error", - JOptionPane.ERROR_MESSAGE); - } - break; - case ".pgn": - try { - final GamePane gamePane = mainWindow.addGamePane(name); - PGNDatabase pgnDB = new PGNDatabase(); - pgnDB.load(file); - if (pgnDB.getGames().size() > 0) { - String[] gameNames = new String[pgnDB.getGames().size()]; - for (int i = 0; i < gameNames.length; i++) { - final PGNGame game = pgnDB.getGames().get(i); - gameNames[i] = String.format("%s vs %s: %s", game.getTag("White"), game.getTag("Black"), game.getTag("Result")); - } - JComboBox comboBox = new JComboBox<>(gameNames); - JOptionPane.showInputDialog(mainWindow, comboBox, "Select a game", JOptionPane.QUESTION_MESSAGE); - DialogUtil.showGameConfigurationDialog(mainWindow, (whiteName, blackName) -> { - final Game game = new Game(gamePane.getBoardPane(), whiteName, blackName, - pgnDB.getGames().get(comboBox.getSelectedIndex()).getBoard()); - game.start(); - }); - } - } catch (Exception e) { - e.printStackTrace(); - JOptionPane.showMessageDialog(mainWindow, - "Failed to load the file " + file.getName() + ": " + e.toString(), - "File loading error", - JOptionPane.ERROR_MESSAGE); - } - break; - default: - JOptionPane.showMessageDialog(mainWindow, - "The file extension '" + extension + "' is not supported!", - "File loading error", - JOptionPane.ERROR_MESSAGE); - } - } - - public void loadFENFile(File file) { - - } }