package vooga.rts.networking.client.clientgui;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Collection;
import java.util.List;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import vooga.rts.networking.NetworkBundle;
import vooga.rts.networking.communications.PlayerInfo;
/**
* Represents the view of the lobby.
*
* @author David Winegar
* @author Sean Wareham
*
*/
public class LobbyView extends JPanel {
private static final long serialVersionUID = -3777313562807648414L;
private static final String NO_PLAYER = "";
private static final int COLUMN_1 = 0;
private static final int COLUMN_2 = 1;
private static final int COLUMN_3 = 2;
private static final int ROW_1 = 0;
private int myMaxPlayers;
private JLabel[] myUsernameLabels;
private JComboBox[] myFactionBoxes;
private JComboBox[] myTeamBoxes;
private PlayerInfo[] myPlayers;
private IModel myModel;
private Collection<PlayerInfo> myUserControlledPlayers;
private ItemListener myFactionListener;
private ItemListener myTeamListener;
/**
* Create the panel.
*
* @param model model to communicate with
* @param factions list of factions
* @param maxPlayers max players of this lobby
*/
public LobbyView (IModel model, List<String> factions, int maxPlayers) {
initializeGridBagLayout();
// initialize state
myModel = model;
myMaxPlayers = maxPlayers;
myUsernameLabels = new JLabel[myMaxPlayers];
myTeamBoxes = new JComboBox[myMaxPlayers];
myFactionBoxes = new JComboBox[myMaxPlayers];
Integer[] teamNumList = new Integer[myMaxPlayers];
for (int i = 0; i < myMaxPlayers; i++) {
teamNumList[i] = i + 1;
}
initializeListeners();
initializeLabelsAndBoxes(factions, teamNumList);
}
/**
* Initializes the title labels and the labels and boxes used in the GridBagLayout for the lobby
* chooser.
*
* @param factions factions
* @param teamNumList list of team numbers
*/
private void initializeLabelsAndBoxes (List<String> factions, Integer[] teamNumList) {
// initialize labels and buttons for player slots
for (int i = 0; i < myMaxPlayers; i++) {
myUsernameLabels[i] = createLabel(NO_PLAYER, COLUMN_1, i + 1);
myTeamBoxes[i] = createComboBox(teamNumList, COLUMN_2, i + 1, myTeamListener);
myFactionBoxes[i] =
createComboBox(factions.toArray(), COLUMN_3, i + 1, myFactionListener);
}
// initialize title labels
createLabel(NetworkBundle.getString("PlayerName"), COLUMN_1, ROW_1);
createLabel(NetworkBundle.getString("Team"), COLUMN_2, ROW_1);
createLabel(NetworkBundle.getString("Faction"), COLUMN_3, ROW_1);
}
/**
* Initializes the layout. This particular method was created by the WindowBuilder and thus is
* not the most readable. Also has significant conflicts between checkstyle and the formatter.
*/
private void initializeGridBagLayout () {
GridBagLayout gridBagLayout = new GridBagLayout();
gridBagLayout.columnWidths = new int[] { 0, 0, 0, 0 };
gridBagLayout.rowHeights =
new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
gridBagLayout.columnWeights = new double[] { 1.0, 1.0, 1.0, Double.MIN_VALUE };
gridBagLayout.rowWeights =
new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE };
setLayout(gridBagLayout);
}
/**
* Initializes the listeners into state. myFactionListener listens for changes in factions, and
* myTeamListener listens for changes in teams, and they update the IModel appropriately.
*/
private void initializeListeners () {
myFactionListener = new ItemListener() {
@Override
public void itemStateChanged (ItemEvent e) {
JComboBox box = (JComboBox) e.getSource();
String faction = (String) box.getSelectedItem();
for (int i = 0; i < myFactionBoxes.length; i++) {
if (box == myFactionBoxes[i]) {
myModel.updateFaction(faction, i);
}
}
}
};
myTeamListener = new ItemListener() {
@Override
public void itemStateChanged (ItemEvent e) {
JComboBox box = (JComboBox) e.getSource();
Integer team = (Integer) box.getSelectedItem();
for (int i = 0; i < myTeamBoxes.length; i++) {
if (box == myTeamBoxes[i]) {
myModel.updateTeam(team, i);
}
}
}
};
}
/**
* Creates a label and adds it to grid. Utility method to avoid repeated code.
*/
private JLabel createLabel (String name, int xposition, int yposition) {
JLabel label = new JLabel(name);
label.setOpaque(true);
GridBagConstraints labelConstraints = new GridBagConstraints();
addComponentToGrid(xposition, yposition, label, labelConstraints);
return label;
}
/**
* Creates a combobox and adds it to grid. Utility method to avoid repeated code.
*/
private JComboBox createComboBox (Object[] objectArray,
int xposition,
int yposition,
ItemListener listener) {
JComboBox box = new JComboBox(objectArray);
GridBagConstraints boxConstraints = new GridBagConstraints();
boxConstraints.fill = GridBagConstraints.HORIZONTAL;
addComponentToGrid(xposition, yposition, box, boxConstraints);
box.setEnabled(false);
box.addItemListener(listener);
return box;
}
/**
* adds component to grid at specified place. Utility method to avoid repeated code.
* Method created through WindowBuilder.
*/
private void addComponentToGrid (int xposition,
int yposition,
JComponent component,
GridBagConstraints labelConstraints) {
labelConstraints.insets = new Insets(0, 5, 5, 5);
labelConstraints.gridx = xposition;
labelConstraints.gridy = yposition;
add(component, labelConstraints);
}
/**
* Updates all labels and buttons
*/
private void updateLabelsAndButtons () {
// for each player
for (int i = 0; i < myPlayers.length; i++) {
// set boxes not enabled
myFactionBoxes[i].setEnabled(false);
myTeamBoxes[i].setEnabled(false);
PlayerInfo player = myPlayers[i];
// if player exists
if (player != null) {
// set player name
myUsernameLabels[i].setText(player.getName());
// remove item listeners, because when calling setSelectedItem() it will create an
// infinite loop with the listener
myFactionBoxes[i].removeItemListener(myFactionListener);
myTeamBoxes[i].removeItemListener(myTeamListener);
// change to reflect current state
myFactionBoxes[i].setSelectedItem(player.getFaction());
myTeamBoxes[i].setSelectedItem(player.getTeam());
// add back item listeners
myFactionBoxes[i].addItemListener(myFactionListener);
myTeamBoxes[i].addItemListener(myTeamListener);
// if slot is user-controllable, set boxes as enabled
if (myUserControlledPlayers.contains(player)) {
myFactionBoxes[i].setEnabled(true);
myTeamBoxes[i].setEnabled(true);
}
}
else {
// set empty label
myUsernameLabels[i].setText(NO_PLAYER);
}
}
validate();
repaint();
}
/**
* Update the current LobbyView to reflectt the state passed in.
*
* @param userControlledPlayers new user controlled players
* @param allPlayers all players
*/
public void update (Collection<PlayerInfo> userControlledPlayers, PlayerInfo[] allPlayers) {
myPlayers = allPlayers;
myUserControlledPlayers = userControlledPlayers;
updateLabelsAndButtons();
}
}