package org.fhnw.aigs.TicTacToeSwing.client; import java.awt.Toolkit; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.JButton; import org.fhnw.aigs.swingClient.GUI.BaseBoard; import org.fhnw.aigs.swingClient.gameHandling.ClientGame; import org.fhnw.aigs.TicTacToeSwing.commons.TicTacToeFieldChangedMessage; import org.fhnw.aigs.TicTacToeSwing.commons.TicTacToeSymbol; import org.fhnw.aigs.commons.communication.FieldClickFeedbackMessage; import org.fhnw.aigs.commons.communication.FieldClickMessage; import org.fhnw.aigs.commons.communication.Message; /** * This is the class representing the TicTacToe board. * It contains 3 x 3 TicTacToePanes. * All event handlers and animations as well as the creation of the TicTacToePanes * occurs here.<br> * v1.0 Initial release<br> * v1.1 Changed Handling (integration of setFields() and SetEventHandler() into constructor) * @author Matthias Stöckli (v1.0) * @version v1.1 */ public class TicTacToeBoard extends BaseBoard{ public TicTacToeBoard(int x, int y, ClientGame clientGame){ super(x, y, clientGame); this.setFields(); this.setEventHandlers(); } /** * Sets the field appearance of the TicTacToeFields. * In this case it is sufficient to iterate through the x and y axis * and create a new TicTacToeField for every field. Then this new field * is added to the TicTacToeBoard. <br> */ @Override public void setFields(){ for(int i = 0; i < fieldsX; i++){ for(int j = 0; j < fieldsY; j++){ TicTacToePane ticTacToePane = new TicTacToePane(i, j); fieldPanes[i][j] = ticTacToePane; this.add(ticTacToePane, i, j); } } } /** * This method wires the TicTacToeFields to their respective actions. * Whenever one of the fields is clicked, a FieldClickedMessage will be sent * which is based upon the clicked field. The server will then react. */ @Override public void setEventHandlers(){ // Go through all fields for(int i = 0; i < this.getFieldsX(); i++){ for(int j = 0; j < this.getFieldsY(); j++){ // Event handler for the fields - reacts to the user's clicks. // Because we know that the children of all JPanels are JButtons // we can assume that ((TicTacToePane)this.getField(i, j)).getButton().addActionListener(new AbstractAction() { @Override public void actionPerformed(ActionEvent event) { TicTacToePane sourceField = (TicTacToePane)((JButton)event.getSource()).getParent(); // Get the source, i.e. which field was clicked int xPosition = sourceField.getXPosition(); // Get the column int yPosition = sourceField.getYPosition(); // Get the row // Create a field click message based on the coordinates FieldClickMessage fieldClickMessage = new FieldClickMessage(xPosition, yPosition); clientGame.sendMessageToServer(fieldClickMessage); } }); } } } /** * This method is responsible for any UI changes. * @param message */ @Override public void manipulateGUI(Message message){ // If one of the players changed the game situation, change the field if (message instanceof TicTacToeFieldChangedMessage) { changeField((TicTacToeFieldChangedMessage) message); } else // Provide the user with a feedback if the server sends a // FieldClickFeedbackMessage upon user interaction if(message instanceof FieldClickFeedbackMessage){ provideFeedback(); } } /** * Changes the field according to the TicTacToeFieldChangedMessage sent by the * server. * @param fieldChangedMessage The message sent by the server. */ private void changeField(TicTacToeFieldChangedMessage fieldChangedMessage) { int x = fieldChangedMessage.getXPosition(); int y = fieldChangedMessage.getYPosition(); TicTacToePane changedField = (TicTacToePane)this.getField(x, y); TicTacToeSymbol playerSymbol = fieldChangedMessage.getPlayerSymbol(); changedField.setPlayerSymbol(playerSymbol); } /** * Plays a "beep" sound when the user clicked on an invalid field. */ private void provideFeedback() { Toolkit.getDefaultToolkit().beep(); } }