Revampled MainFrame layout to improve appearance/usability when the number of tiles is very large or small.
Fixed instantiation where a new MouseListener was used to each tile - now only one is used for all Tiles. Fixed issue where the MouseListener was being added to each tile twice.
This commit is contained in:
@@ -7,18 +7,17 @@ import java.awt.event.MouseWheelListener;
|
|||||||
|
|
||||||
import model.HumanPlayer;
|
import model.HumanPlayer;
|
||||||
|
|
||||||
import view.BoardPanel;
|
|
||||||
import view.Tile;
|
import view.Tile;
|
||||||
import view.TileSelectionPanel;
|
import view.TileSelectionPanel;
|
||||||
|
|
||||||
public class BoardPanelMouseListener implements MouseListener, MouseWheelListener {
|
public class BoardPanelMouseListener implements MouseListener, MouseWheelListener {
|
||||||
private final BoardPanel boardPanel;
|
private static int clickNum = 0;
|
||||||
|
|
||||||
private final HumanPlayer humanPlayer;
|
private final HumanPlayer humanPlayer;
|
||||||
private final TileSelectionPanel tsp;
|
private final TileSelectionPanel tsp;
|
||||||
|
|
||||||
public BoardPanelMouseListener(BoardPanel boardPanel, TileSelectionPanel tsp, HumanPlayer humanPlayer) {
|
public BoardPanelMouseListener(TileSelectionPanel tsp, HumanPlayer humanPlayer) {
|
||||||
this.humanPlayer = humanPlayer;
|
this.humanPlayer = humanPlayer;
|
||||||
this.boardPanel = boardPanel;
|
|
||||||
this.tsp = tsp;
|
this.tsp = tsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ public class BoardPanelMouseListener implements MouseListener, MouseWheelListene
|
|||||||
public void mouseClicked(MouseEvent e) {
|
public void mouseClicked(MouseEvent e) {
|
||||||
Tile tile = (Tile) e.getComponent();
|
Tile tile = (Tile) e.getComponent();
|
||||||
humanPlayer.setCell(tile.getRow(), tile.getCol());
|
humanPlayer.setCell(tile.getRow(), tile.getCol());
|
||||||
boardPanel.updateIcons();
|
System.out.println("mouseClicked() " + (clickNum++));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ public class Board {
|
|||||||
BLUE, GREEN, NONE, RED, YELLOW
|
BLUE, GREEN, NONE, RED, YELLOW
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int NUM_COLS = 6;
|
public static final int NUM_COLS = 5;
|
||||||
public static final int NUM_ROWS = 6;
|
public static final int NUM_ROWS = 5;
|
||||||
public static final int ROW_REMOVAL_SIZE = 3;
|
public static final int ROW_REMOVAL_SIZE = 3;
|
||||||
|
|
||||||
private final TileColor[][] board;
|
private final TileColor[][] board;
|
||||||
|
|||||||
@@ -1,42 +1,23 @@
|
|||||||
package model;
|
package model;
|
||||||
|
|
||||||
|
import view.BoardPanel;
|
||||||
|
import view.MessagePanel;
|
||||||
import model.Board.TileColor;
|
import model.Board.TileColor;
|
||||||
|
|
||||||
public class Referee {
|
public class Referee implements Runnable {
|
||||||
|
|
||||||
public enum Message {
|
public static final String COM_TURN = "Waiting for the computer's move.";
|
||||||
COM_TURN {
|
public static final String GAME_OVER = "Game over!";
|
||||||
@Override
|
public static final String PLAYER_TURN = "Waiting for the player's move.";
|
||||||
public String toString() {
|
|
||||||
return "Waiting for the computer's move.";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
GAME_OVER {
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Game over!";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
NONE {
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
},
|
|
||||||
PLAYER_TURN {
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Waiting for the player's move.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Board board;
|
private final Board board;
|
||||||
private final HumanPlayer humanPlayer = new HumanPlayer();
|
private final HumanPlayer humanPlayer = new HumanPlayer();
|
||||||
private final Player cc;
|
private final Player cc;
|
||||||
|
|
||||||
private boolean playerTurn;
|
private boolean playerTurn;
|
||||||
|
private BoardPanel boardPanel;
|
||||||
private int score = 0;
|
private int score = 0;
|
||||||
|
private MessagePanel messagePanel;
|
||||||
|
|
||||||
public Referee() {
|
public Referee() {
|
||||||
board = new Board();
|
board = new Board();
|
||||||
@@ -44,50 +25,63 @@ public class Referee {
|
|||||||
playerTurn = true;
|
playerTurn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doSomething() {
|
@Override
|
||||||
if (playerTurn && humanPlayer.isReady()) {
|
public void run() {
|
||||||
Move mv = humanPlayer.getMove(board);
|
int plies = 0;
|
||||||
if (board.getTile(mv.getCell().r, mv.getCell().c) == TileColor.NONE) {
|
while (!isOver()) {
|
||||||
playToken(humanPlayer.getMove(board));
|
if (playerTurn) {
|
||||||
|
boolean wasInterrupted = false;
|
||||||
|
while (!humanPlayer.isReady()) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(250L);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
wasInterrupted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wasInterrupted) {
|
||||||
|
System.out.println("Interrupted while waiting for human to move!");
|
||||||
|
} else {
|
||||||
|
Move mv = humanPlayer.getMove(board);
|
||||||
|
if (board.getTile(mv.getCell().r, mv.getCell().c) == TileColor.NONE) {
|
||||||
|
playToken(humanPlayer.getMove(board));
|
||||||
|
} else {
|
||||||
|
humanPlayer.denyMove();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
humanPlayer.denyMove();
|
Move mv = cc.getMove(board);
|
||||||
|
playToken(mv);
|
||||||
|
}
|
||||||
|
|
||||||
|
messagePanel.updateMessage(getMessage());
|
||||||
|
boardPanel.updateIcons();
|
||||||
|
System.out.println("plies: " + plies++);
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000L);
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
System.out.println("Interrupted while waiting for human view ply!");
|
||||||
}
|
}
|
||||||
} else if (!playerTurn) {
|
|
||||||
Move mv = cc.getMove(board);
|
|
||||||
playToken(mv);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player getCom() {
|
public Player getComputerPlayer() {
|
||||||
return cc;
|
return cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMessage() {
|
|
||||||
if (isOver()) {
|
|
||||||
return Message.GAME_OVER.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (isPlayersTurn()) {
|
|
||||||
return Message.PLAYER_TURN.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
return Message.COM_TURN.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public HumanPlayer getHumanPlayer() {
|
public HumanPlayer getHumanPlayer() {
|
||||||
return humanPlayer;
|
return humanPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getScore() {
|
public String getMessage() {
|
||||||
return score;
|
if (isOver()) {
|
||||||
|
return GAME_OVER;
|
||||||
|
} else if (isPlayersTurn()) {
|
||||||
|
return PLAYER_TURN;
|
||||||
|
} else {
|
||||||
|
return COM_TURN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TileColor getTile(int r, int c) {
|
|
||||||
return board.getTile(r, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOver() {
|
public boolean isOver() {
|
||||||
for (int r = 0; r < Board.NUM_ROWS; r++) {
|
for (int r = 0; r < Board.NUM_ROWS; r++) {
|
||||||
for (int c = 0; c < Board.NUM_COLS; c++) {
|
for (int c = 0; c < Board.NUM_COLS; c++) {
|
||||||
@@ -99,27 +93,35 @@ public class Referee {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPlayersTurn() {
|
||||||
|
return playerTurn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getScore() {
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TileColor getTile(int r, int c) {
|
||||||
|
return board.getTile(r, c);
|
||||||
|
}
|
||||||
|
|
||||||
public void playToken(Move move) {
|
public void playToken(Move move) {
|
||||||
|
|
||||||
board.setTile(move.getCell(), move.getColor());
|
board.setTile(move.getCell(), move.getColor());
|
||||||
|
|
||||||
if (playerTurn) {
|
if (playerTurn) {
|
||||||
incrementScore();
|
score++;
|
||||||
}
|
}
|
||||||
|
|
||||||
incrementTurn();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void incrementScore() {
|
|
||||||
score++;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void incrementTurn() {
|
|
||||||
playerTurn = !playerTurn;
|
playerTurn = !playerTurn;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPlayersTurn() {
|
public void setBoardPanel(BoardPanel boardPanel) {
|
||||||
return playerTurn;
|
this.boardPanel = boardPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessagePanel(MessagePanel messagePanel) {
|
||||||
|
this.messagePanel = messagePanel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,17 +35,15 @@ public class BoardPanel extends JPanel {
|
|||||||
referee = ref;
|
referee = ref;
|
||||||
setLayout(new GridLayout(Board.NUM_ROWS, Board.NUM_COLS));
|
setLayout(new GridLayout(Board.NUM_ROWS, Board.NUM_COLS));
|
||||||
|
|
||||||
BoardPanelMouseListener bpml = new BoardPanelMouseListener(this, tsp, referee.getHumanPlayer());
|
BoardPanelMouseListener bpml = new BoardPanelMouseListener(tsp,
|
||||||
|
referee.getHumanPlayer());
|
||||||
ImageIcon noneIcon = new ImageIcon(NONE_ICON);
|
ImageIcon noneIcon = new ImageIcon(NONE_ICON);
|
||||||
for (int r = 0; r < Board.NUM_ROWS; r++) {
|
for (int r = 0; r < Board.NUM_ROWS; r++) {
|
||||||
for (int c = 0; c < Board.NUM_COLS; c++) {
|
for (int c = 0; c < Board.NUM_COLS; c++) {
|
||||||
Tile tile = new Tile(noneIcon,r,c);
|
Tile tile = new Tile(noneIcon, r, c);
|
||||||
board[r][c] = tile;
|
board[r][c] = tile;
|
||||||
tile.addMouseListener(bpml);
|
|
||||||
|
|
||||||
board[r][c].addMouseListener(bpml);
|
board[r][c].addMouseListener(bpml);
|
||||||
board[r][c].addMouseWheelListener(bpml);
|
board[r][c].addMouseWheelListener(bpml);
|
||||||
|
|
||||||
add(board[r][c]);
|
add(board[r][c]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package view;
|
package view;
|
||||||
|
|
||||||
import java.awt.GridBagConstraints;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.GridBagLayout;
|
|
||||||
import java.awt.Insets;
|
|
||||||
|
|
||||||
|
import javax.swing.Box;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
import model.Referee;
|
import model.Referee;
|
||||||
|
|
||||||
@@ -12,90 +13,85 @@ public class MainFrame extends JFrame {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Referee referee;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new MainFrame();
|
MainFrame mainFrame = new MainFrame();
|
||||||
|
mainFrame.playGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Referee game;
|
|
||||||
|
|
||||||
public MainFrame() {
|
public MainFrame() {
|
||||||
super("Project 4");
|
super("CS8803 Project 4");
|
||||||
game = new Referee();
|
referee = new Referee();
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
// Set up window.
|
|
||||||
setDefaultCloseOperation(MainFrame.EXIT_ON_CLOSE);
|
setDefaultCloseOperation(MainFrame.EXIT_ON_CLOSE);
|
||||||
setResizable(false);
|
|
||||||
|
|
||||||
pack();
|
|
||||||
setLocationRelativeTo(null);
|
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
|
pack();
|
||||||
run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void init() {
|
private void init() {
|
||||||
// Create objects.
|
ScorePanel sp = new ScorePanel(referee);
|
||||||
ScorePanel sp = new ScorePanel(game);
|
TileSelectionPanel tp = new TileSelectionPanel(referee.getHumanPlayer());
|
||||||
TileSelectionPanel tp = new TileSelectionPanel(game.getHumanPlayer());
|
|
||||||
BoardPanel bp = new BoardPanel(game,tp);
|
|
||||||
MessagePanel mp = new MessagePanel(game);
|
|
||||||
|
|
||||||
// Add stuff to panel.
|
BoardPanel bp = new BoardPanel(referee,tp);
|
||||||
GridBagLayout layout = new GridBagLayout();
|
referee.setBoardPanel(bp);
|
||||||
GridBagConstraints con;
|
|
||||||
|
MessagePanel mp = new MessagePanel(referee);
|
||||||
con = new GridBagConstraints();
|
referee.setMessagePanel(mp);
|
||||||
con.anchor = GridBagConstraints.WEST;
|
|
||||||
con.fill = GridBagConstraints.BOTH;
|
//The outer wrapper allows the game board to be resized vertically.
|
||||||
con.gridheight = 1;
|
JPanel vWrapper = new JPanel();
|
||||||
con.gridwidth = 1;
|
vWrapper.setLayout(new BoxLayout(vWrapper,BoxLayout.Y_AXIS));
|
||||||
con.gridx = 0;
|
|
||||||
con.gridy = 0;
|
//The inner wrappers allow each sub-panel to be independently resized horizontally.
|
||||||
con.weightx = 1;
|
JPanel hWrapperTop = new JPanel();
|
||||||
layout.setConstraints(sp, con);
|
hWrapperTop.setLayout(new BoxLayout(hWrapperTop,BoxLayout.X_AXIS));
|
||||||
|
JPanel hWrapperMid = new JPanel();
|
||||||
con = new GridBagConstraints();
|
hWrapperMid.setLayout(new BoxLayout(hWrapperMid,BoxLayout.X_AXIS));
|
||||||
con.anchor = GridBagConstraints.EAST;
|
JPanel hWrapperBottom = new JPanel();
|
||||||
con.fill = GridBagConstraints.BOTH;
|
hWrapperBottom.setLayout(new BorderLayout());
|
||||||
con.gridheight = 1;
|
|
||||||
con.gridwidth = 1;
|
//Top horizontal-box wrapper contains message panel, score panel
|
||||||
con.gridx = 1;
|
hWrapperTop.add(Box.createHorizontalGlue());
|
||||||
con.gridy = 0;
|
hWrapperTop.add(mp);
|
||||||
con.weightx = 1;
|
hWrapperTop.add(sp);
|
||||||
layout.setConstraints(mp, con);
|
hWrapperTop.add(Box.createHorizontalGlue());
|
||||||
|
|
||||||
con = new GridBagConstraints();
|
//Mid horizontal box wrapper contains board panel
|
||||||
con.anchor = GridBagConstraints.NORTH;
|
hWrapperMid.add(Box.createHorizontalGlue());
|
||||||
con.fill = GridBagConstraints.BOTH;
|
|
||||||
con.gridwidth = 2;
|
JPanel bpContainer = new JPanel();
|
||||||
con.gridx = 0;
|
bpContainer.add(bp);
|
||||||
con.gridy = 1;
|
hWrapperMid.add(bpContainer);
|
||||||
layout.setConstraints(bp, con);
|
hWrapperMid.add(Box.createHorizontalGlue());
|
||||||
|
|
||||||
con = new GridBagConstraints();
|
//Bottom horizontal box wrapper contains tile panel
|
||||||
con.anchor = GridBagConstraints.NORTH;
|
hWrapperBottom.add(tp,BorderLayout.NORTH);
|
||||||
con.fill = GridBagConstraints.BOTH;
|
|
||||||
con.gridwidth = 2;
|
//the outter wrapper contains the 3 inner wrappers: top, mid, bottom
|
||||||
con.gridx = 0;
|
vWrapper.add(hWrapperTop);
|
||||||
con.gridy = 2;
|
vWrapper.add(hWrapperMid);
|
||||||
con.insets = new Insets(10, 0, 10, 0);
|
vWrapper.add(hWrapperBottom);
|
||||||
layout.setConstraints(tp, con);
|
|
||||||
|
//The main JFrame contains a the outer (vertical) wrapper, in the center of a BorderLayout.
|
||||||
setLayout(layout);
|
setLayout(new BorderLayout());
|
||||||
add(sp);
|
add(vWrapper,BorderLayout.CENTER);
|
||||||
add(mp);
|
|
||||||
add(bp);
|
//To ensure correct size, pre-populate the score and message panels with text.
|
||||||
add(tp);
|
sp.updateScore();
|
||||||
|
mp.updateMessage("Loading new game...");
|
||||||
|
|
||||||
pack();
|
pack();
|
||||||
|
|
||||||
|
//Finally, update the border to show the initially selected tile color.
|
||||||
tp.updateBorders();
|
tp.updateBorders();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void run() {
|
private void playGame() {
|
||||||
while (!game.isOver()) {
|
new Thread(referee).start();
|
||||||
game.doSomething();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,18 +10,16 @@ public class MessagePanel extends JPanel {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final JLabel message = new JLabel();
|
private final JLabel label = new JLabel(" ");
|
||||||
private final Referee referee;
|
|
||||||
|
|
||||||
public MessagePanel(Referee ref) {
|
public MessagePanel(Referee ref) {
|
||||||
referee = ref;
|
add(label);
|
||||||
add(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateMessage() {
|
public void updateMessage(final String message) {
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
message.setText(referee.getMessage());
|
label.setText(message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package view;
|
package view;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.GridBagConstraints;
|
import java.awt.FlowLayout;
|
||||||
import java.awt.GridBagLayout;
|
|
||||||
import java.awt.Insets;
|
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
@@ -73,69 +71,10 @@ public class TileSelectionPanel extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initLayout() {
|
private void initLayout() {
|
||||||
GridBagLayout layout = new GridBagLayout();
|
setLayout(new FlowLayout());
|
||||||
GridBagConstraints con;
|
|
||||||
JLabel spacer1 = new JLabel();
|
|
||||||
JLabel spacer2 = new JLabel();
|
|
||||||
|
|
||||||
con = new GridBagConstraints();
|
|
||||||
con.gridheight = 1;
|
|
||||||
con.gridwidth = 1;
|
|
||||||
con.gridx = 0;
|
|
||||||
con.gridy = 0;
|
|
||||||
con.weightx = 1;
|
|
||||||
layout.setConstraints(spacer1, con);
|
|
||||||
|
|
||||||
con = new GridBagConstraints();
|
|
||||||
con.gridheight = 1;
|
|
||||||
con.gridwidth = 1;
|
|
||||||
con.gridx = 1;
|
|
||||||
con.gridy = 0;
|
|
||||||
con.insets = new Insets(5, 5, 5, 5);
|
|
||||||
con.weightx = 0;
|
|
||||||
layout.setConstraints(blue, con);
|
|
||||||
|
|
||||||
con = new GridBagConstraints();
|
|
||||||
con.gridheight = 1;
|
|
||||||
con.gridwidth = 1;
|
|
||||||
con.gridx = 2;
|
|
||||||
con.gridy = 0;
|
|
||||||
con.insets = new Insets(5, 5, 5, 5);
|
|
||||||
con.weightx = 0;
|
|
||||||
layout.setConstraints(green, con);
|
|
||||||
|
|
||||||
con = new GridBagConstraints();
|
|
||||||
con.gridheight = 1;
|
|
||||||
con.gridwidth = 1;
|
|
||||||
con.gridx = 3;
|
|
||||||
con.gridy = 0;
|
|
||||||
con.insets = new Insets(5, 5, 5, 5);
|
|
||||||
con.weightx = 0;
|
|
||||||
layout.setConstraints(red, con);
|
|
||||||
|
|
||||||
con = new GridBagConstraints();
|
|
||||||
con.gridheight = 1;
|
|
||||||
con.gridwidth = 1;
|
|
||||||
con.gridx = 4;
|
|
||||||
con.gridy = 0;
|
|
||||||
con.insets = new Insets(5, 5, 5, 5);
|
|
||||||
con.weightx = 0;
|
|
||||||
layout.setConstraints(yellow, con);
|
|
||||||
|
|
||||||
con = new GridBagConstraints();
|
|
||||||
con.gridheight = 1;
|
|
||||||
con.gridwidth = 1;
|
|
||||||
con.gridx = 5;
|
|
||||||
con.gridy = 0;
|
|
||||||
con.weightx = 1;
|
|
||||||
layout.setConstraints(spacer2, con);
|
|
||||||
|
|
||||||
setLayout(layout);
|
|
||||||
add(spacer1);
|
|
||||||
add(blue);
|
add(blue);
|
||||||
add(green);
|
add(green);
|
||||||
add(red);
|
add(red);
|
||||||
add(yellow);
|
add(yellow);
|
||||||
add(spacer2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user