-
Notifications
You must be signed in to change notification settings - Fork 0
/
BoardPanel.java
188 lines (164 loc) · 4.84 KB
/
BoardPanel.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.JLabel;
/**
* Represents a Swing displayer for a chess board.
* Implements Observer for visually updating the
* board when game state changes.
*/
public class BoardPanel extends JPanel implements Observer {
/** Represents a chess board. */
private final Board board;
/** Represents event handler. */
private final Controller controller;
/** Represents board index. */
private final int index;
/**
* Initializes a Swing displayer for a chess board.
*
* @param board is a chess board.
* @param controller is a handler for click events.
*/
public BoardPanel(Board board, Controller controller) {
this.board = board;
this.controller = controller;
this.index = 0; // First board is index 0
}
/**
* Initializes a Swing displayer for a chess board.
*
* @param board is a chess board.
* @param controller is a handler for click events.
*/
public BoardPanel(Board board, Controller controller, int index) {
this.board = board;
this.controller = controller;
this.index = index;
}
/**
* Initializer to set up the Swing displayer.
*/
public void init() {
setLayout(new GridLayout(board.getHeight(), board.getWidth()));
update();
}
/**
* Implements abstract method to repaint the board
* when game state changes.
*/
@Override
public void update() {
// Clear the board
removeAll();
// Repaint the board
for (int tile = 0; tile < board.getSize(); tile++) {
Position position = board.getTile(tile);
if (position.getZ() != index) continue; // Essential for proper display. Try unchecking it.
TilePanel tilePanel = new TilePanel(position, controller);
Piece piece = board.getPiece(position); // Check for piece at tile
if (piece != null) {
tilePanel.setPieceLabel(piece); // Label tile with piece name
} else {
tilePanel.removePieceLabel(); // Unoccupied tile is blank.
}
tilePanel.setPreferredSize(new Dimension(60, 60));
add(tilePanel);
}
// Refresh state
revalidate();
repaint();
}
/**
* Inner class represents each tile of the board.
* A tile cannot exist without the board.
*/
public class TilePanel extends JPanel {
/** Represents tile coordinates. */
private final Position position;
/** Represents event handler. */
private final Controller controller;
/** Represents tile color. */
private Color color;
/** Represents piece name. */
private JLabel label;
/**
* Constructor for a TilePanel to handle click events.
*
* @param board is a chess board.
* @param controller is a handler for click events.
*/
public TilePanel(Position position, Controller controller) {
this.position = position;
this.controller = controller;
int x = position.getX();
int y = position.getY();
color = ((x + y) % 2 == 0) ? Color.WHITE : Color.BLACK;
setBackground(color);
// Attach an event listener for tile click events.
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (board.hasPiece(position)) System.out.println("Piece selected.");
else System.out.println("Tile selected.");
controller.selectTile(position); // Update the controller
}
});
setOpaque(true);
}
/**
* Assigns an occupied tile with the piece name.
*
* @param piece represents a chess piece.
*/
public void setPieceLabel(Piece piece) {
// Center the label. Use Comic Sans.
if (label == null) {
label = new JLabel();
label.setHorizontalAlignment(JLabel.CENTER);
label.setVerticalAlignment(JLabel.CENTER);
label.setFont(new Font("Comic Sans MS", Font.BOLD, 14));
label.setPreferredSize(new Dimension(60, 60));
this.add(label);
}
if (piece != null) {
// If image does not load, fall back to alt-text.
try {
ImageIcon icon = piece.getIcon();
Image original = icon.getImage();
Image scaled = original.getScaledInstance(60, 60, Image.SCALE_SMOOTH);
label.setIcon(new ImageIcon(scaled));
} catch (Exception e) {
label.setText(piece.getName().name()); // Update label of occupied tile
label.setForeground((piece.getColor() == Color.BLACK) ? Color.BLUE : Color.RED); // Update font color
}
} else {
// If image does not load, fall back to alt-text.
try {
label.setIcon(null);
} catch (Exception e) {
label.setText(""); // Unoccupied tile
}
}
this.revalidate();
this.repaint();
}
/**
* Removes label from a tile.
*/
public void removePieceLabel() {
if (label != null) {
this.remove(label);
label = null;
this.revalidate();
this.repaint();
}
}
}
}