001    /**
002     * BoardPanel is a GUI component for displaying a chessboard.
003     */
004    
005    package ui;
006    
007    import java.awt.Color;
008    import java.awt.ComponentOrientation;
009    import java.awt.GridLayout;
010    import java.util.Collection;
011    import java.util.HashMap;
012    import java.util.Map;
013    
014    import javax.swing.JPanel;
015    
016    import rules.GameState;
017    import core.Move;
018    import core.Piece;
019    import core.Position;
020    
021    
022    public class BoardPanel extends JPanel {
023            private static final long serialVersionUID = 144;
024            
025            private Map<Position, SquarePanel> map;
026            private Collection<Move> moves;
027            
028            // One square of the board may be selected at a given time
029            private SquarePanel selectedPanel = null;
030            
031            /**
032             * Constructor
033             */
034            public BoardPanel() {
035                    this.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
036                    this.setLayout(new GridLayout(8, 8));
037                    
038                    map = new HashMap<Position, SquarePanel>();
039                    
040                    // For each square on the board
041                    for (int i = 63; i >= 0; i--) {
042                            int x = i % 8;
043                            int y = i / 8;
044                            Position pos = Position.get(x, y);
045                            Color color;
046                            if ((x + y) % 2 == 0) {
047                                    color = Color.BLACK;
048                            }
049                            else {
050                                    color = Color.WHITE;
051                            }
052                            SquarePanel panel = new SquarePanel(color);
053                            this.add(panel);
054                            map.put(pos, panel);
055                    }
056            }
057            
058            /**
059             * Updates this component to reflect the board in the argument
060             */
061            public void updateBoard(GameState state) {
062                    
063                    // For each position/piece pair
064                for (Map.Entry<Position, ? extends Piece> e : state.getPieceMap().entrySet()) {
065                            // Set the piece field of the appropriate SquarePanel
066                    SquarePanel s = map.get(e.getKey());
067                    s.setPiece(e.getValue());
068                    s.setCanMove(false);
069                    s.setCanBeTaken(false);
070                }
071    
072                moves = state.legalMoves();
073                for(Move m : moves) {
074                    if (!m.isPass()) {
075                        map.get(m.getFrom()).setCanMove(true);
076                    }
077                }
078                reselectCapture();
079            }
080        /**
081         * Corrects the canBeTaken flag for all SquarePanels in the map
082         */
083        private void reselectCapture(){
084            for(Move m: moves) {
085                if (!m.isPass()) {
086                    map.get(m.getTo()).setCanBeTaken(false);
087                }
088            }
089            for(Move m: moves) {
090                if (!m.isPass() && 
091                    selectedPanel != null &&
092                    selectedPanel == map.get(m.getFrom())) {
093                    map.get(m.getTo()).setCanBeTaken(true);
094                } 
095            }
096        }
097            
098            /**
099             * Sets the selected panel to the one at the position in the argument.
100             * If the argument is null, or if the suggested square cannot move,
101             * then no panel is selected.
102             * Returns whether a panel has been selected.
103             */
104            public boolean setSelectedPanel(Position p) {
105                    // Deselect the old panel
106                    if (selectedPanel != null) {
107                            selectedPanel.setSelected(false);
108                            this.update(this.getGraphics());
109                    }
110                    
111                    // Select the new panel and change the state variable
112                    if (p != null) {
113                            SquarePanel panel = map.get(p);
114                            if (!panel.getCanMove()) {
115                                return false;
116                            }
117                            panel.setSelected(true);
118                            selectedPanel = panel;
119                            
120                            this.update(this.getGraphics());
121                            reselectCapture();
122                            return true;
123                    } else {
124                        selectedPanel = null;
125                    }
126                    reselectCapture();
127                    return false;
128            }
129    }