package ch.sahits.game.graphic.display.start;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.log4j.Logger;
import ch.sahits.game.event.ChangeRequest;
import ch.sahits.game.event.ENewGame;
import ch.sahits.game.event.EViewChangeEvent;
import ch.sahits.game.event.NewGameEvent;
import ch.sahits.game.event.ViewChangeRequestEvent;
import ch.sahits.game.graphic.display.IIndexChangeListener;
import ch.sahits.game.graphic.display.ISahitsComponent;
import ch.sahits.game.graphic.display.ISahitsContainer;
import ch.sahits.game.graphic.display.OpenPatricianBackgroundView;
import ch.sahits.game.graphic.layout.Button;
import ch.sahits.game.graphic.layout.ECellPosition;
import ch.sahits.game.graphic.layout.Label;
import ch.sahits.game.graphic.layout.MaximalGridLayoutConstraints;
import ch.sahits.game.graphic.layout.RadioButton;
import ch.sahits.game.graphic.layout.SahitsMaximalGridLayout;
import ch.sahits.game.graphic.layout.SelectableGroup;
import ch.sahits.game.graphic.layout.Slider;
import ch.sahits.game.graphic.layout.Spinner;
import ch.sahits.game.graphic.layout.TextInput;
import ch.sahits.game.openpatrician.model.Difficulty;
import ch.sahits.game.openpatrician.model.EGameSpeed;
import ch.sahits.game.openpatrician.model.EObjective;
import ch.sahits.game.openpatrician.model.GameFactory;
import ch.sahits.game.openpatrician.model.IGame;
import ch.sahits.game.openpatrician.model.IMap;
import ch.sahits.game.openpatrician.model.IPlayer;
import ch.sahits.game.openpatrician.model.city.CityFactory;
import ch.sahits.game.openpatrician.model.city.ECityName;
import ch.sahits.game.openpatrician.model.city.ICity;
import ch.sahits.game.openpatrician.model.ship.EShipUpgrade;
import ch.sahits.game.openpatrician.model.ship.IShip;
import ch.sahits.game.openpatrician.model.ship.ShipFactory;
import ch.sahits.game.openpatrician.util.PropertyLoader;
import ch.sahits.game.openpatrician.util.RandomNameLoader;
/**
* Rendering view to create a new single player game. This view encompasses the whole
* screen with a red brick background.
* @author Andi Hotz, (c) Sahits GmbH, 2011
* Created on Sep 18, 2011
*
*/
public class NewGameView extends OpenPatricianBackgroundView implements ISahitsContainer {
private final static Logger logger = Logger.getLogger(NewGameView.class);
private Font font=null;
private FontMetrics metic=null;
private Difficulty difficulity=Difficulty.CHANDLER;
private static RandomNameLoader firstNameLoader = new RandomNameLoader("firstnames.properties");
private static RandomNameLoader lastNameLoader = new RandomNameLoader("lastnames.properties");
private TextInput name;
private TextInput lastName;
private RadioButton male;
private RadioButton female;
@SuppressWarnings("unused")
private Spinner map;// TODO incorporate the map usage
private Spinner home;
private Spinner startYear;
private Slider difficulty;
private Spinner objective;
private Slider speed;
/**
* Construct the view with the specified dimensions and the font metrics
* @param rect
* @param metric
*/
public NewGameView(Rectangle rect, FontMetrics metric) {
super(rect,new SahitsMaximalGridLayout(4,7,5,ECellPosition.CENTER));
font =metric.getFont();
this.metic=metric;
createComponents();
}
/**
* Create the form element to specify the start settings of the new game
*/
private void createComponents() {
addLabel("Name");// TODO Externalize
name = addInput(getRandomFirstName());
addLabel("Last name");// TODO Externalize
lastName = addInput(getRandomLastName());
addLabel("Sex");// TODO Externalize
SelectableGroup gender = new SelectableGroup();
male = addRadioButton("male", true, gender);// TODO Externalize
female = addRadioButton("female", false, gender);// TODO Externalize
addLabel(null);
addLabel("Map");// TODO Externalize
map = addSpinner(getMapList());
addLabel("Hometown");// TODO Externalize
home = addSpinner(getHomeTowns4Map());
addLabel("Start year");// TODO Externalize
startYear =addSpinner(getStartYears());
addLabel(null);
addLabel(null);
addLabel("Difficulty");// TODO Externalize
difficulty = addSlider(getDificutlyList());
difficulty.addChangeListeners(new IIndexChangeListener() {
@Override
public void changeIndex(int newIndex) {
switch (newIndex){
case 0:
difficulity = Difficulty.CHANDLER;
break;
case 1:
difficulity = Difficulty.MERCHANT;
break;
case 2:
difficulity = Difficulty.TRADESMAN;
break;
case 3:
difficulity = Difficulty.COUNSILMAN;
break;
case 4:
difficulity = Difficulty.PATRICIAN;
break;
default:
throw new IllegalArgumentException("Illegal index");
}
}
});
addLabel("Game speed"); // TODO Externalize
speed = addSlider(getGameSpeedList());
//We do not need an listener as the data is extracted from the component when the game is started
addLabel("Objective"); // Open new site to define the Ob // TODO Externalize
objective = addSpinner(getObjectiveList());
addLabel(null);
addLabel(null);
addLabel(null);
Button start = addButton("Start Game"); // TODO Externalize
start.setAction(createStartButtonClickAction());
addLabel(null);
addLabel(null);
}
/**
* Action to be called when the start button is hit.
* @return
*/
private Runnable createStartButtonClickAction() {
return new Runnable() {
@Override
public void run() {
if (validInput()){
// Create a game model based on newGame
// Create NewGameEvent(SingePlayer) with notice of the gameModel
try {
int homeTownIndex = home.getSelectedIndex();
IMap gameMap = GameFactory.createMap(); // TODO consider custom maps
EObjective obj = EObjective.values()[objective.getSelectedIndex()];
Difficulty diff = difficulity;
EGameSpeed gameSpeed = EGameSpeed.values()[speed.getSelectedIndex()];
int startyear = Integer.parseInt(startYear.getSelected());
IGame game = GameFactory.createGame(gameMap, obj, diff, gameSpeed, startyear);
ICity homeCity = CityFactory.createCityByName(ECityName.values()[homeTownIndex]);
IPlayer player = GameFactory.createPlayer(name.getValue(), lastName.getValue(), homeCity, male.isSelected() && !female.isSelected(),difficulity.getStartingCapital());
RandomNameLoader shipLoader = new RandomNameLoader("shipnames.properties");
IShip ship = ShipFactory.createCrayer(shipLoader.getRandomName(), EShipUpgrade.LEVEL1,3000); // TODO check the value
player.addShip(ship);
// Initialize the player
new NewGameEvent(ENewGame.SINGELPLAYER).notify(player);
// Initialize the game/server
new NewGameEvent(ENewGame.SINGELPLAYER).notify(game);
// Request the view change
new ViewChangeRequestEvent(ChangeRequest.ALL).notify(EViewChangeEvent.START_GAME);
} catch (IOException e) { // property file for city creation not available
e.printStackTrace();
}
} // end if valid input
}
};
}
/**
* Create a list of objectives to select from
* @return
*/
private List<String> getObjectiveList() {
ArrayList<String> l = new ArrayList<String>();
// TODO translate
l.add("Endless game");
l.add("Mayor in 1 year");
l.add("Mayor in 2 year");
l.add("Mayor in 3 year");
l.add("Elderman in 2 year");
l.add("Elderman in 3 year");
l.add("Elderman in 5 year");
l.add("Businessvalue 1'000'000");
l.add("Businessvalue 10'000'000");
l.add("Businessvalue 100'000'000");
return l;
}
/**
* Compile a list of game speeds
* @return
*/
private List<String> getGameSpeedList() {
ArrayList<String> l = new ArrayList<String>();
// TODO translate
l.add("Slow motion"); // TODO utilize EGameSpeed
l.add("Slow");
l.add("Normal");
l.add("Fast");
return l;
}
/**
* Compile a list of the difficulty levels
* @return
*/
private List<String> getDificutlyList() {
// TODO translate
Properties props = PropertyLoader.loadProperties("DisplayMessages1");
ArrayList<String> l = new ArrayList<String>();
l.add(props.getProperty("CHANDLER")); // Utilize Difficulty
l.add(props.getProperty("MERCHANT"));
l.add(props.getProperty("TRADESMAN"));
l.add(props.getProperty("COUNSILMAN"));
l.add(props.getProperty("PATRICIAN"));
return l;
}
/**
* Initialize the list of start years from 1300 to 1400
* @return
*/
private List<String> getStartYears() {
ArrayList<String> l = new ArrayList<String>();
for (int year=1400;year>=1300;year--){
l.add(String.valueOf(year));
}
return l;
}
/**
* Create a list of town names that are available on the selected map as home towns.
* @return
*/
private List<String> getHomeTowns4Map() {
// TODO consider the selected map
ArrayList<String> l = new ArrayList<String>();
ECityName[] cityNames = ECityName.values();
for (int i=0;i<8;i++){
l.add(cityNames[i].getLocalizedName());
}
return l;
}
/**
* Add a {@link RadioButton} to the view.
* There should only on radio button be defined, that is selected in the same group
* @param label of the radio button
* @param selected flag indicating if the button is currently selected.
* @param group the button belongs to
* @return created RadioButton
*/
private RadioButton addRadioButton(String label, boolean selected, SelectableGroup group) {
RadioButton radio = new RadioButton(group, metic, font);
radio.setSelected(selected);
radio.setText(label);
group.add(radio);
add(radio,new MaximalGridLayoutConstraints(ECellPosition.TOP_LEFT));
return radio;
}
/**
* Create a {@link TextInput} field with an optional preset text
* @param value optional text of the input field
* @return {@link TextInput} field
*/
private TextInput addInput(String value) {
TextInput input = new TextInput(metic);
if (value !=null){
input.setValue(value);
}
setFont(input);
input.setSize(25);
add(input,new MaximalGridLayoutConstraints(ECellPosition.LEFT));
return input;
}
/**
* Creating a label. The name may be null identifying the label a place holder
* @param name
* @return
*/
private ISahitsComponent addLabel(String name) {
Label label = new Label(metic);
if (name!=null){
label.setText(name);
}
setFont(label);
add(label,new MaximalGridLayoutConstraints(ECellPosition.RIGHT));
return label;
}
/**
* Add a spinner control to the component. A spinner is similar to a drop down list
* in effect only that only the active element is displayed.
* @param elements List of elements in the spinner
* @return
*/
private Spinner addSpinner(List<String> elements){
Spinner spinner = new Spinner(metic);
setFont(spinner);
for (String s : elements) {
spinner.add(s);
}
add(spinner,new MaximalGridLayoutConstraints(ECellPosition.LEFT));
return spinner;
}
/**
* Add a slider control to the component. A slider uses a few values that
* are placed in a half circle above a steering wheel
* @param elements List of the selectable values. There should be only a few
* @return
*/
private Slider addSlider(List<String> elements) {
Slider slider = new Slider(metic);
setFont(slider);
for (String s : elements) {
slider.add(s);
}
slider.setSelected(0);
slider.setPaintLabels(true);
add(slider,new MaximalGridLayoutConstraints(ECellPosition.LEFT));
return slider;
}
/**
* Create a button with the text label. The action is not initialized
* @param text label of the button
* @return
*/
private Button addButton(final String text){
Button btn = new Button(metic);
setFont(btn);
btn.setText(text);
add(btn,new MaximalGridLayoutConstraints(ECellPosition.LEFT));
return btn;
}
/**
* Retrieve the list of the available maps
* @return
*/
private List<String> getMapList() {
ArrayList<String> l = new ArrayList<String>();
l.add("Standard"); // TODO translate
return l;
}
/**
* Set the font on the component
* @param comp
*/
private void setFont(ISahitsComponent comp) {
comp.setFont(font);
}
/**
* check if the input is valid and one may proceed.
* @return
*/
private boolean validInput(){
if (name.getValue()==null || name.getValue().trim().equals("")){
logger.warn("Name may not be null");
return false;
}
if (lastName.getValue()==null || lastName.getValue().trim().equals("")){
logger.warn("Last name may not be null");
return false;
}
return true;
}
/**
* Set the difficulty
* @param difficulity
*/
public void setDifficulity(Difficulty difficulity) {
this.difficulity = difficulity;
}
private static String getRandomFirstName(){
return firstNameLoader.getRandomName();
}
private static String getRandomLastName(){
return lastNameLoader.getRandomName();
}
}