/**
* Copyright (C) 2002-2012 The FreeCol Team
*
* This file is part of FreeCol.
*
* FreeCol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* FreeCol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FreeCol. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.freecol.client.gui.panel;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Map.Entry;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import net.miginfocom.swing.MigLayout;
import net.sf.freecol.client.FreeColClient;
import net.sf.freecol.client.gui.GUI;
import net.sf.freecol.client.gui.i18n.Messages;
import net.sf.freecol.common.model.GameOptions;
import net.sf.freecol.common.model.Nation;
import net.sf.freecol.common.model.NationOptions;
import net.sf.freecol.common.model.NationOptions.NationState;
import net.sf.freecol.common.model.Specification;
import net.sf.freecol.common.option.FileOption;
import net.sf.freecol.common.option.MapGeneratorOptions;
import net.sf.freecol.common.option.OptionGroup;
/**
* The panel where you choose your nation and color and connected players are
* shown.
*/
public final class StartGamePanel extends FreeColPanel implements ActionListener {
private static final Logger logger = Logger.getLogger(StartGamePanel.class.getName());
private static final int START = 0, CANCEL = 1,
READY = 3, CHAT = 4, GAME_OPTIONS = 5, MAP_GENERATOR_OPTIONS = 6;
private boolean singlePlayerGame;
private JCheckBox readyBox;
private JTextField chat;
private JTextArea chatArea;
private JButton start;
private JButton gameOptions;
private JButton mapGeneratorOptions;
private PlayersTable table;
/**
* Create the panel from which to start a game.
*
* @param freeColClient The <code>FreeColClient</code> for the game.
* @param gui The <code>GUI</code> to display on.
*/
public StartGamePanel(FreeColClient freeColClient, GUI gui) {
super(freeColClient, gui);
}
public void initialize(boolean singlePlayer) {
removeAll();
this.singlePlayerGame = singlePlayer;
NationOptions nationOptions = getGame().getNationOptions();
JButton cancel = new JButton(Messages.message("cancel"));
JScrollPane chatScroll = null, tableScroll;
setCancelComponent(cancel);
table = new PlayersTable(getFreeColClient(), getGUI(), nationOptions, getMyPlayer());
start = new JButton(Messages.message("startGame"));
gameOptions = new JButton(Messages.message("gameOptions"));
mapGeneratorOptions = new JButton(Messages.message("mapGeneratorOptions"));
readyBox = new JCheckBox(Messages.message("iAmReady"));
if (singlePlayerGame) {
// If we set the ready flag to false then the player will
// be able to change the settings as he likes.
getMyPlayer().setReady(false);
// Pretend as if the player is ready.
readyBox.setSelected(true);
} else {
readyBox.setSelected(getMyPlayer().isReady());
chat = new JTextField();
chatArea = new JTextArea();
chatScroll = new JScrollPane(chatArea, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
}
refreshPlayersTable();
tableScroll = new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
tableScroll.getViewport().setOpaque(false);
setLayout(new MigLayout("fill, wrap 2"));
add(tableScroll, "width 600:, grow");
if (!singlePlayerGame) {
add(chatScroll, "width 250:, grow");
}
add(mapGeneratorOptions, "newline, split 2, growx, top, sg");
add(gameOptions, "growx, top, sg");
if (!singlePlayerGame) {
add(chat, "grow, top");
}
add(readyBox, "newline");
add(start, "newline, span, split 2, tag ok");
add(cancel, "tag cancel");
start.setActionCommand(String.valueOf(START));
cancel.setActionCommand(String.valueOf(CANCEL));
readyBox.setActionCommand(String.valueOf(READY));
gameOptions.setActionCommand(String.valueOf(GAME_OPTIONS));
mapGeneratorOptions.setActionCommand(String.valueOf(MAP_GENERATOR_OPTIONS));
if (!singlePlayerGame) {
chat.setActionCommand(String.valueOf(CHAT));
chat.addActionListener(this);
chatArea.setEditable(false);
chatArea.setLineWrap(true);
chatArea.setWrapStyleWord(true);
chatArea.setText("");
}
enterPressesWhenFocused(start);
enterPressesWhenFocused(cancel);
start.addActionListener(this);
cancel.addActionListener(this);
readyBox.addActionListener(this);
gameOptions.addActionListener(this);
mapGeneratorOptions.addActionListener(this);
setEnabled(true);
}
@Override
public void requestFocus() {
start.requestFocus();
}
/**
* Updates the map generator options displayed on this panel.
*/
public void updateMapGeneratorOptions() {
getFreeColClient().getGame().getMapGeneratorOptions()
.getOption("model.option.mapWidth");
getFreeColClient().getGame().getMapGeneratorOptions()
.getOption("model.option.mapHeight");
}
/**
* Updates the game options displayed on this panel.
*/
public void updateGameOptions() {
// Nothing yet.
}
/**
* Sets whether or not this component is enabled. It also does this for its
* children.
*
* @param enabled 'true' if this component and its children should be
* enabled, 'false' otherwise.
*/
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
Component[] components = getComponents();
for (int i = 0; i < components.length; i++) {
components[i].setEnabled(enabled);
}
if (singlePlayerGame && enabled) {
readyBox.setEnabled(false);
}
if (enabled) {
start.setEnabled(getFreeColClient().isAdmin());
}
gameOptions.setEnabled(enabled);
}
/**
* Check that the user has not specified degenerate victory conditions
* that are automatically true.
*
* @return True if the victory conditions are sensible.
*/
private boolean checkVictoryConditions() {
Specification spec = getSpecification();
if (singlePlayerGame
&& spec.getBoolean(GameOptions.VICTORY_DEFEAT_EUROPEANS)
&& !spec.getBoolean(GameOptions.VICTORY_DEFEAT_REF)) {
int n = 0;
for (Entry<Nation, NationState> e
: getGame().getNationOptions().getNations().entrySet()) {
if (e.getKey().getType().isEuropean()
&& e.getValue() != NationState.NOT_AVAILABLE) n++;
}
if (n == 0) {
getGUI().errorMessage("victory.noEuropeans");
return false;
}
}
return true;
}
/**
* This function analyses an event and calls the right methods to take care
* of the user's requests.
*
* @param event The incoming ActionEvent.
*/
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
try {
switch (Integer.valueOf(command).intValue()) {
case START:
int row = table.getSelectedRow();
int col = table.getSelectedColumn();
if (row > -1 && col > -1){
table.getCellEditor(row, col).stopCellEditing();
}
if (!checkVictoryConditions()) break;
// The ready flag was set to false for single player
// mode in order to allow the player to change
// whatever he wants.
if (singlePlayerGame) {
getMyPlayer().setReady(true);
}
getFreeColClient().getPreGameController().requestLaunch();
break;
case CANCEL:
getFreeColClient().getConnectController().quitGame(true);
getGUI().removeFromCanvas(this);
getGUI().showNewPanel();
break;
case READY:
getFreeColClient().getPreGameController()
.setReady(readyBox.isSelected());
refreshPlayersTable();
break;
case CHAT:
if (chat.getText().trim().length() > 0) {
getFreeColClient().getPreGameController()
.chat(chat.getText());
displayChat(getMyPlayer().getName(), chat.getText(), false);
chat.setText("");
}
break;
case GAME_OPTIONS:
getGUI().showGameOptionsDialog(getFreeColClient().isAdmin(), true);
break;
case MAP_GENERATOR_OPTIONS:
OptionGroup mgo = getFreeColClient().getGame()
.getMapGeneratorOptions();
FileOption importFile = (FileOption) mgo.getOption(MapGeneratorOptions.IMPORT_FILE);
boolean loadCustomOptions = (importFile.getValue() == null);
getGUI().showMapGeneratorOptionsDialog(mgo, getFreeColClient().isAdmin(),
loadCustomOptions);
break;
default:
logger.warning("Invalid Actioncommand: invalid number.");
}
} catch (NumberFormatException e) {
logger.warning("Invalid Actioncommand: not a number.");
}
}
/**
* Displays a chat message to the user.
*
* @param senderName The name of the player who sent the chat message to the
* server.
* @param message The chat message.
* @param privateChat 'true' if the message is a private one, 'false'
* otherwise.
*/
public void displayChat(String senderName, String message, boolean privateChat) {
if (privateChat) {
chatArea.append(senderName + " (private): " + message + '\n');
} else {
chatArea.append(senderName + ": " + message + '\n');
}
}
/**
* Refreshes the table that displays the players and the choices that
* they've made.
*/
public void refreshPlayersTable() {
table.update();
}
}