//
// @(#)BCSpinner.java 2/2003
//
// Copyright 2003 Zachary DelProposto. All rights reserved.
// Use is subject to license terms.
//
//
// This program 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.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
// Or from http://www.gnu.org/
//
package dip.gui.dialog.newgame;
import dip.misc.Utils;
import dip.world.Phase.YearType;
import javax.swing.AbstractSpinnerModel;
import javax.swing.JFormattedTextField;
import javax.swing.JSpinner;
/**
* Creates a Year spinner that (if enabled) correctly handles
* BC years ('negative' years), and uses YearType objects to
* increment/decrement.
* <p>
* To disable negative (BC) years, set the minimum value
* [setMinimum()] to 1.
*
*/
public class BCSpinner extends JSpinner
{
/** Create a BCSpinner */
public BCSpinner(int initialYear, int minimum, int maximum)
{
this(new YearType(initialYear), minimum, maximum);
}// BCSpinner()
/** Create a BCSpinner */
public BCSpinner(YearType initialYear, int minimum, int maximum)
{
super(new SpinnerYearTypeModel(initialYear, minimum, maximum));
setEditor(new YearTypeEditor(this));
}// BCSpinner()
/** Sets the current value */
public void setValue(int value)
{
setValue(new YearType(value));
}// setValue()
/** Sets the minimum value */
public void setMinimum(int value)
{
((SpinnerYearTypeModel) getModel()).setMinimum(value);
}// setMinimum()
/** Sets the maximum value */
public void setMaximum(int value)
{
((SpinnerYearTypeModel) getModel()).setMaximum(value);
}// setMaximum()
/** Type-Safe version of getValue() */
public YearType getYearTypeValue()
{
return (YearType) getValue();
}// getYearTypeValue()
private static class YearTypeEditor extends JSpinner.DefaultEditor
{
YearTypeEditor(JSpinner spinner)
{
super(spinner);
JFormattedTextField ftf = getTextField();
ftf.setEditable(true);
ftf.setColumns(4);
}// YearTypeEditor()
}// inner class YearTypeEditor
private static class SpinnerYearTypeModel extends AbstractSpinnerModel
{
private YearType value;
private int minimum, maximum;
/** Create a SpinnerYearTypeModel. 0 is not a valid min, max, or stepSize value. */
SpinnerYearTypeModel(YearType initialYear, int minimum, int maximum)
{
if(minimum > maximum || initialYear.getYear() > maximum || initialYear.getYear() < minimum)
{
throw new IllegalArgumentException("Bad min/max/initial values");
}
if(minimum == 0 || maximum == 0)
{
throw new IllegalArgumentException("Bad min/max values; cannot be 0");
}
this.value = initialYear;
this.minimum = minimum;
this.maximum = maximum;
}// SpinnerYearTypeModel()
/** Sets the minimum value. Note that 0 is not allowed. */
public void setMinimum(int min)
{
if(min == 0 || min > maximum)
{
throw new IllegalArgumentException("invalid min value");
}
this.minimum = min;
fireStateChanged();
}// setMinimum()
/** Sets the maximum value. Note that 0 is not allowed. */
public void setMaximum(int max)
{
if(max == 0 || max < minimum)
{
throw new IllegalArgumentException("invalid max value");
}
this.maximum = max;
fireStateChanged();
}// setMaximum()
/** Get the minimum value */
public int getMinimum() { return minimum; }
/** Get the maximum value */
public int getMaximum() { return maximum; }
/** Returns the next number in the sequence. Bounds-checks.*/
public Object getNextValue()
{
YearType incremented = value.getNext();
if(incremented.getYear() > maximum)
{
return null;
}
return incremented;
}// getNextValue()
/** Returns the previous number in the sequence. Bounds-checks.*/
public Object getPreviousValue()
{
YearType decremented = value.getPrevious();
if(decremented.getYear() < minimum)
{
return null;
}
return decremented;
}// getNextValue()
/** Returns the current value. */
public Object getValue()
{
return value;
}// getValue().
/**
* Sets the current value. If this is not a YearType, it
* is converted to a String and parsing is attempted.
* If the value is not valid, the current value is used.
*/
public void setValue(Object newValue)
{
// separate by type
YearType yt = null;
if(newValue instanceof YearType)
{
yt = (YearType) newValue;
}
else if(newValue != null)
{
// attempt String conversion (parsing)
// parse() will return null if year is invalid (includes '0')
yt = YearType.parse( newValue.toString().toLowerCase() );
}
// if legal, use it
if(yt != null && yt.getYear() >= minimum && yt.getYear() <= maximum)
{
this.value = yt;
}
// update
fireStateChanged();
}// setValue()
}// inner class SpinnerYearTypeModel
}// class BCSpinner