package chess.view.simplerender; import java.awt.Color; import java.awt.Graphics; import java.awt.GridLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.util.List; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.SwingUtilities; import chess.controller.CommandExecutor; import chess.controller.CommandSender; import chess.controller.commands.PromoteCommand.PromoteType; import chess.controller.event.GameListener; import chess.model.Coordinate; import chess.model.Move; public class Window extends JFrame implements GameListener, CommandSender { private final CommandExecutor commandExecutor; private Coordinate lastClick = null; private final JLabel cells[][]; private final JLabel displayText; private final JButton castlingButton = new JButton("Roque"); private final JButton bigCastlingButton = new JButton("Grand Roque"); private final JButton undoButton = new JButton("Annuler le coup précédent"); private final boolean showPopups; public Window(final CommandExecutor commandExecutor, boolean showPopups) { this.cells = new JLabel[8][8]; this.displayText = new JLabel(); this.commandExecutor = commandExecutor; this.showPopups = showPopups; setSize(800, 910); setVisible(true); setLocationRelativeTo(null); setDefaultCloseOperation(DISPOSE_ON_CLOSE); addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { commandExecutor.close(); } }); } private Color getCellColor(int x, int y) { return ((x + y) % 2 == 1) ? Color.DARK_GRAY : Color.LIGHT_GRAY; } @SuppressWarnings("unused") private void buildButtons(JPanel bottom) { castlingButton.addActionListener((event) -> { sendCastling(); }); bigCastlingButton.addActionListener((event) -> { sendBigCastling(); }); undoButton.addActionListener((event) -> { sendUndo(); }); bottom.add(castlingButton); bottom.add(bigCastlingButton); bottom.add(undoButton); } private void buildBoard() { JPanel content = new JPanel(); JPanel grid = new JPanel(new GridLayout(8, 8)); JPanel bottom = new JPanel(); buildButtons(bottom); content.add(this.displayText); content.add(grid); content.add(bottom); setContentPane(content); for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { JLabel label = new JLabel(); label.setOpaque(true); label.setBackground(getCellColor(x, y)); this.cells[x][y] = label; final int xx = x; final int yy = y; label.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { onCellClicked(xx, yy); } }); grid.add(label); } } updateBoard(); } private void updateBoard() { PieceIcon pieceIcon = new PieceIcon(); for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { JLabel cell = this.cells[x][y]; try { cell.setIcon(pieceIcon.getIcon(getPieceAt(x, y))); } catch (IOException e) { e.printStackTrace(); } } } } private boolean previewMoves(int x, int y) { List allowedMoves = getPieceAllowedMoves(new Coordinate(x, y)); if (allowedMoves.isEmpty()) return false; for (Coordinate destCoord : allowedMoves) { JLabel cell = this.cells[destCoord.getX()][destCoord.getY()]; Graphics g = cell.getGraphics(); g.setColor(new Color(128, 128, 128, 128)); g.fillOval(25, 25, 50, 50); } return true; } private void drawInvalid(Move move) { JLabel from = this.cells[move.getStart().getX()][move.getStart().getY()]; JLabel to = this.cells[move.getFinish().getX()][move.getFinish().getY()]; from.setBackground(Color.RED); to.setBackground(Color.RED); } private void clearMoves() { for (int y = 0; y < 8; y++) { for (int x = 0; x < 8; x++) { JLabel cell = this.cells[x][y]; cell.setBackground(getCellColor(x, y)); cell.paint(cell.getGraphics()); } } } private void onCellClicked(int x, int y) { clearMoves(); if (this.lastClick == null) { if (isCellEmpty(x, y)) return; if (!previewMoves(x, y)) return; this.lastClick = new Coordinate(x, y); return; } if (!this.lastClick.equals(new Coordinate(x, y))) { Move move = new Move(lastClick, new Coordinate(x, y)); sendMove(move); } this.lastClick = null; } private void updateButtons() { this.castlingButton.setEnabled(canDoCastling()); this.bigCastlingButton.setEnabled(canDoBigCastling()); } @Override public void onPlayerTurn(chess.model.Color color, boolean undone) { this.displayText.setText("Current turn: " + color); updateButtons(); } @Override public void onWin(chess.model.Color color) { JOptionPane.showMessageDialog(this, "Victory of " + color); } @Override public void onKingInCheck() { if (!showPopups) return; SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(this, "Check!"); }); } @Override public void onKingInMat() { SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(this, "Checkmate!"); }); } @Override public void onPatSituation() { JOptionPane.showMessageDialog(this, "Pat. It's a draw!"); } @Override public void onSurrender(chess.model.Color color) { JOptionPane.showMessageDialog(this, color + " has surrendered."); } @Override public void onGameEnd() { JOptionPane.showMessageDialog(this, "End of the game"); this.dispose(); this.commandExecutor.close(); } @Override public void onGameStart() { buildBoard(); } @Override public void onPromotePawn(Coordinate pieceCoords) { if (!showPopups) return; SwingUtilities.invokeLater(() -> { String result = null; Object[] possibilities = new Object[PromoteType.values().length]; int i = 0; for (PromoteType type : PromoteType.values()) { possibilities[i] = type.name(); i++; } while (result == null || result.isEmpty()) { result = (String) JOptionPane.showInputDialog( this, "Choose the type of piece to upgrade the pawn", "Promote Dialog", JOptionPane.PLAIN_MESSAGE, null, possibilities, possibilities[0]); } PromoteType choosedType = null; for (PromoteType type : PromoteType.values()) { if (type.name().equals(result)) { choosedType = type; break; } } if (choosedType != null) sendPawnPromotion(choosedType); }); } @Override public void onBoardUpdate() { updateBoard(); } @Override public void onMove(Move move, boolean captured) {} @Override public void onMoveNotAllowed(Move move) { drawInvalid(move); } @Override public void onDraw() { JOptionPane.showMessageDialog(this, "Same position was repeated three times. It's a draw!"); } @Override public void onCastling(boolean bigCastling, Move kingMove, Move rookMove) {} @Override public void onPawnPromoted(PromoteType promotion) {} @Override public CommandExecutor getCommandExecutor() { return this.commandExecutor; } }