/*
* $Id$
*
* Copyright (c) 2005-2012 by Rodney Kinney, Brent Easton
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Library General Public License (LGPL) as published by
* the Free Software Foundation.
*
* This library 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 Library General Public License for more
* details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; if not, copies are available at
* http://www.opensource.org.
*/
package VASSAL.build.module.turn;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JMenu;
import javax.swing.JPanel;
import VASSAL.build.AutoConfigurable;
import VASSAL.build.Buildable;
import VASSAL.build.GameModule;
import VASSAL.build.module.properties.MutableProperty;
import VASSAL.configure.Configurer;
import VASSAL.configure.FormattedStringConfigurer;
import VASSAL.configure.StringEnumConfigurer;
import VASSAL.i18n.ComponentI18nData;
import VASSAL.i18n.TranslatableConfigurerFactory;
import VASSAL.tools.FormattedString;
public abstract class TurnLevel extends TurnComponent {
protected static final String NAME = "name"; //$NON-NLS-1$
protected static final String PROP = "property"; //$NON-NLS-1$
protected static final String TURN_FORMAT = "turnFormat"; //$NON-NLS-1$
protected static final String LEVEL_VALUE = "value"; //$NON-NLS-1$
protected TurnTracker turn;
protected JDialog setDialog;
protected JPanel levelSetControls = null;
protected Component childSetControls = null;
protected TurnComponent parent = null;
protected String propertyName;
protected int start = 1; // Counter Start value
protected int current = 1; // Current counter pointer
protected int currentSubLevel = 0; // sub-level pointer
protected boolean subLevelRolledOver = false;
protected boolean rolledOver = false;
protected MutableProperty.Impl myValue = new MutableProperty.Impl("",this); //$NON-NLS-1$
protected FormattedString turnFormat;
protected abstract String getState();
protected abstract void setState(String code);
protected abstract String getValueString();
protected abstract String getLongestValueName();
protected abstract Component getSetControl();
public TurnLevel() {
super();
turnFormat = new FormattedString("$" + LEVEL_VALUE + "$"); //$NON-NLS-1$ //$NON-NLS-2$
}
public void findMaximumStrings(List<String> levels, int currentLevel) {
String s = getLongestFormattedValue();
if (levels.size() < (currentLevel+1) || levels.get(currentLevel) == null || levels.get(currentLevel).length() < s.length()) {
levels.add(currentLevel, s);
}
for (Buildable b : getBuildables()) {
if (b instanceof TurnLevel) {
((TurnLevel) b).findMaximumStrings(levels, currentLevel+1);
}
}
}
protected String getLongestFormattedValue() {
turnFormat.setProperty(LEVEL_VALUE, getLongestValueName());
return turnFormat.getText();
}
protected boolean hasSubLevelRolledOver() {
return subLevelRolledOver;
}
protected boolean isActive() {
return true;
}
protected void reset() {
for (int i = 0; i < getTurnLevelCount(); i++) {
getTurnLevel(i).reset();
}
currentSubLevel = 0;
}
protected void advance() {
rolledOver = false;
subLevelRolledOver = false;
if (getTurnLevelCount() > 0) {
TurnLevel subLevel = getTurnLevel(currentSubLevel);
subLevel.advance();
if (subLevel.hasRolledOver()) {
currentSubLevel++;
if (currentSubLevel >= getTurnLevelCount()) {
currentSubLevel = 0;
subLevelRolledOver = true;
}
getTurnLevel(currentSubLevel).setLow();
}
}
}
protected void retreat() {
rolledOver = false;
subLevelRolledOver = false;
if (getTurnLevelCount() > 0) {
TurnLevel subLevel = getTurnLevel(currentSubLevel);
subLevel.retreat();
if (subLevel.hasRolledOver()) {
currentSubLevel--;
if (currentSubLevel < 0) {
currentSubLevel = getTurnLevelCount() - 1;
subLevelRolledOver = true;
}
getTurnLevel(currentSubLevel).setHigh();
}
}
}
// Return the description of this turn
public String getTurnString() {
turnFormat.setProperty(LEVEL_VALUE, getValueString());
return turnFormat.getText();
}
public List<TurnLevel> getActiveChildLevels() {
ArrayList<TurnLevel> children = new ArrayList<TurnLevel>();
if (getTurnLevelCount() > 0) {
TurnLevel activeChild = getTurnLevel(currentSubLevel);
children.add(activeChild);
children.addAll(activeChild.getActiveChildLevels());
}
return children;
}
protected void buildConfigMenu(JMenu menu) {
JMenu m = getConfigMenu();
if (m != null) {
menu.add(m);
}
}
protected JMenu getConfigMenu() {
JMenu menu = new JMenu(getConfigureName());
for (int i = 0; i < getTurnLevelCount(); i++) {
getTurnLevel(i).buildConfigMenu(menu);
}
return menu.getItemCount() == 0 ? null : menu;
}
public boolean isConfigurable() {
for (int i = 0; i < getTurnLevelCount(); i++) {
if (getTurnLevel(i).isConfigurable()) {
return true;
}
}
return false;
}
private static final Dimension FILLER = new Dimension(0, 3);
protected Component getSetControls(JDialog dialog, TurnTracker turn) {
this.turn = turn;
this.setDialog = dialog;
levelSetControls = new JPanel();
levelSetControls.setLayout(new BoxLayout(levelSetControls, BoxLayout.Y_AXIS));
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
p.setBorder(BorderFactory.createLineBorder(Color.black));
p.add(Box.createRigidArea(FILLER));
p.add(getSetControl());
p.add(Box.createRigidArea(FILLER));
if (getTurnLevelCount() > 1) {
String s[] = new String[getTurnLevelCount()];
for (int i = 0; i < s.length; i++) {
s[i] = getTurnLevel(i).getConfigureName();
}
StringEnumConfigurer e = new StringEnumConfigurer(null, " Select: ", s);
e.setValue(getTurnLevel(currentSubLevel).getConfigureName());
e.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
String option = ((StringEnumConfigurer) e.getSource()).getValueString();
for (int i = 0; i < getTurnLevelCount(); i++) {
if (option.equals(getTurnLevel(i).getConfigureName())) {
currentSubLevel = i;
addChildControls();
}
}
}
});
p.add(e.getControls());
p.add(Box.createRigidArea(FILLER));
}
levelSetControls.add(p);
levelSetControls.add(Box.createRigidArea(FILLER));
addChildControls();
return levelSetControls;
}
protected void addChildControls() {
if (childSetControls != null) {
levelSetControls.remove(childSetControls);
}
if (getTurnLevelCount() > 0) {
childSetControls = getTurnLevel(currentSubLevel).getSetControls(setDialog, turn);
levelSetControls.add(childSetControls);
setDialog.pack();
}
}
protected TurnTracker getTurn() {
return turn;
}
protected void setRolledOver(boolean b) {
rolledOver = b;
}
protected boolean hasRolledOver() {
return rolledOver;
}
protected void setLow() {
if (getTurnLevelCount() > 0) {
currentSubLevel = 0;
getTurnLevel(currentSubLevel).setLow();
}
myValue.setPropertyValue(getValueString());
}
protected void setHigh() {
if (getTurnLevelCount() > 0) {
currentSubLevel = getTurnLevelCount() - 1;
getTurnLevel(currentSubLevel).setHigh();
}
myValue.setPropertyValue(getValueString());
}
public String[] getAttributeDescriptions() {
return new String[] {
"Description: ",
"Property Name: ",
"Turn Level Format ($levelx$): "
};
}
public Class<?>[] getAttributeTypes() {
return new Class<?>[] {
String.class,
String.class,
TurnFormatConfig.class
};
}
public String[] getAttributeNames() {
return new String[] {
NAME,
PROP,
TURN_FORMAT
};
}
public void setAttribute(String key, Object value) {
if (NAME.equals(key)) {
setConfigureName((String) value);
myValue.setPropertyName(getConfigureName());
}
else if (PROP.equals(key)) {
propertyName = (String) value;
myValue.setPropertyName(propertyName);
}
else if (TURN_FORMAT.equals(key)) {
turnFormat.setFormat((String) value);
}
}
public String getAttributeValueString(String key) {
if (NAME.equals(key)) {
return getConfigureName();
}
else if (TURN_FORMAT.equals(key)) {
return turnFormat.getFormat();
}
else if (PROP.equals(key)) {
return propertyName;
}
else {
return ""; //$NON-NLS-1$
}
}
/*
* Allow TurnLevels to share global property with other TurnLevel's. Check to
* see if a property already exists with the same name
*/
public void addTo(Buildable parent) {
this.parent = (TurnComponent) parent;
((TurnComponent) parent).addLevel(this);
MutableProperty.Impl existingValue = (MutableProperty.Impl) GameModule.getGameModule().getMutableProperty(propertyName);
if (existingValue == null) {
myValue.addTo(GameModule.getGameModule());
}
else {
myValue = existingValue;
}
}
public void removeFrom(Buildable parent) {
((TurnComponent) parent).removeLevel(this);
myValue.removeFromContainer();
}
public Class<?>[] getAllowableConfigureComponents() {
return new Class<?>[] { CounterTurnLevel.class, ListTurnLevel.class };
}
public static class TurnFormatConfig implements TranslatableConfigurerFactory {
public Configurer getConfigurer(AutoConfigurable c, String key, String name) {
return new FormattedStringConfigurer(key, name, new String[] { LEVEL_VALUE });
}
}
public ComponentI18nData getI18nData() {
ComponentI18nData myI18nData = super.getI18nData();
myI18nData.setAttributeTranslatable(PROP, false);
return myI18nData;
}
/**
* Implement PropertyNameSource - Expose the name of this level property
*/
public List<String> getPropertyNames() {
final ArrayList<String> l = new ArrayList<String>();
if (propertyName != null && propertyName.length() > 0) {
l.add(propertyName);
}
return l;
}
}