/* This file is part of the source code for 3D-XplorMath-J, Version 1.0 (January 2008). * Copyright (c) 2008 The 3D-XplorMath Consortium (http://3d-xplormath.org). * This source code is released under a BSD License, which allows redistribution * in source and binary form, with or without modification, provided copyright * and license information are included, and with no warranty or guarantee of * any kind. For details, see http://3d-xplormath.org/j/source/BSDLicense.txt */ package vmm.core; /** * Represents a settable numeric parameter associated with another object, such as a View * or Exhibit. A parameter is meant to be an attribute of a single object, which * is its "owner." The owner implements interface Parameterizable, which defines * a method {@link vmm.core.Parameterizable#parameterChanged(Parameter, Object, Object)}. * When a Parameter's value is changed, it calls this method in its owner. *
The value of a parameter can be set from a String that represents a constant expression.
* When the value is set in this way, the String is saved so that it can be returned when
* the parameter is converted to string form with the getValueAsString method.
* This allows parameters to have values such as "2*pi".
*
In addition to its value, a parameter has a "default value" that is used (in the VMM core) only * when the user clicks the "Defaults" button in a {@link vmm.core.ParameterDialog}. The default * value is set the first time the parameter's value is set, and it can be explicitely reset later. *
Parameters can be (at least) integers, real numbers, or complex numbers. These possibilities
* are repesented by different subclasses. Some parameters are "animated"; animated
* parameters implement the interface {@link vmm.core.Animateable}.
*/
abstract public class Parameter {
/**
* The value of this Parameter. The type of object will be different in different
* subclasses. A null value object is taken to represent the number zero.
*/
private Object value;
/**
* When the value of the parameter is set from a string, that string is stored
* here. When the value is set directly, valueString is set to null. If valueString
* is non-null, then it is the official string representations of the parameter's value.
*/
private String valueString;
/**
* The default value of this Parameter. This is set the first time that the
* value object is set to a non-null value. It can also be set by calling
* setDefaultValueObject() directly.
*/
private Object defaultValue;
/**
* The default value of this parameter as a String. This is saved when the default
* value is set from a string; otherwise, it is null.
*/
private String defaultValueString;
/**
* The object with which this Parameter is associated. A Parameter can have only
* one owner.
*/
private Parameterizable owner;
/**
* The name of this parameter. The name is for internal, programmatic use but
* might be mapped to a human-readable "title" in a proprties file.
*/
private String name;
/**
* Creates a parameter with a specified name and value object.
* The owner of the Parameter is initially
* set to null. Ordinarily, it will be set automatically when the parameter is
* associated with Parameterizable object. This is done, for example, in the
* View and Exhibit classes, so that most programmers don't have to think about the owner.
* @param name The name for the parameter. If null, the parameter has no name.
* @param value The initial value and default value for this parameter. This should be of
* the correct type for the particular kind of parameter that is being constructed. If
* this is null, the parameter is considered to have value zero.
*/
protected Parameter(String name, Object value) {
if (value != null)
setValueObject(value); // set value before owner to avoid calling parameterChanged.
this.name = name;
}
/**
* Create a parameter with a specified name and value, where the value is given as
* a string. The string will be run through the stringToValueObject method to convert
* the string to a numerical object; this can generate an error if the string does not
* represent a legal value. The owner of the Parameter is initially
* set to null. Ordinarily, the owner will be set automatically when the parameter is
* associated with Parameterizable object.
*
For "animated" parameters, this constructor should also set the animation start and * end values equal to the value. * @param name The name for the parameter. If null, the parameter has no name. * @param valueAsString The value of the parameter, as a string that will be parsed to get the * numeric value. This value also becomes the default value of the parameter. If null, the * parameter is considered to have value zero. */ public Parameter(String name, String valueAsString) { if (valueAsString != null) setValueFromString(valueAsString); this.name = name; } /** * Set both the value and the default value of the parameter to the specified value Object, * as if that object had been passed to the constructor. For animated parameters, this * should include setting the animation start and end values and default values to the * same value. */ protected void reset(Object value) { setDefaultValueObject(value); setValueObject(value); } /** * Set both the value and the default value of the parameter to the value encoded in the given string, * as if that string had been passed to the constructor. For animated parameters, this * should include setting the animation start and end values and default values to the * same value. This is primarily meant to be called in the constructor of an Exhibit when it wants to * change the value of a parameter that is inherited from a superclass. *
Note: In this class, this method simply calls setValueAndDefaultFromString(valueAsString).
* @see #reset(Object)
* @see #stringToValueObject(String)
*/
public void reset(String valueAsString) {
setValueAndDefaultFromString(valueAsString);
}
/**
* Returns a string representation of this Parameter's value. It shoudl be possible to pass the
* string that is returned by this method to the setValueFromString method to restore the value
* of the Parameter. In the top-level Parameter class, the return value is computed using the
* toString method of the value object, except that if the value object is null, then
* the return value is the string "0".
* This should be OK, but subclasses can override this method if necessary.
*
This method is called in the Parameter class to convert betweeen the object and the string
* representation of a parameter's value and default value.
* @param obj A parameter value represented as an object.
* @return A string representation of the value.
* @see #stringToValueObject(String)
*/
protected String valueObjectToString(Object obj) {
return (obj == null)? "0" : obj.toString();
}
/**
* Convert a string rerpesentation of a parameter value to a representation of that same value
* as an object. The object will be of the correct type for this parameter, presumably Integer,
* Double, or Complex, depending on the parameter type. The value should be obtained by
* parsing the string to allow for constant expressions such as "2*pi". This parsing might generate
* an error. If an error is generated, it should be of type NumberFormatException.
* @param str A string representation of a value for the parameter, possibly as a constant expression such as "2*pi"
* @return An object representing the value, presumably of type Integer, Double, or Complex.
*/
abstract protected Object stringToValueObject(String str);
/**
* Returns the owner of this parameter. The value will be null if this parameter has no owner.
*/
public Parameterizable getOwner() {
return owner;
}
/**
* Sets the owner of this parameter. The owner can be null, meaning that the parameter has no owner.
* This method is called automatically when the parameter is added to an Exhibit or View.
*/
public void setOwner(Parameterizable owner) {
this.owner = owner;
}
/**
* Returns the value of this object as an Object. The value can be null.
* It is not guaranteed that the value will be of the correct type, but subclasses
* might provide such a guarantee.
*/
public Object getValueObject() {
return value;
}
/**
* Sets a new value for this parameter and calls the parameterChanged method in the
* parameter's owner (if there is an owner). In this class, "owner.parameterChanged()" is called
* only if the value of the parameter actually does change; the equals() method is
* used to check for object equality. No other method is provided for setting the
* private value object, so all changes to the value object must go throught this method.
*
* @param value The new value of this parameter. The value is set without checking whether
* the value is of the correct type for this parameter. A type-cast error might result
* at some later time. Subclasses might override this method to guarantee that the
* object is of the correct type.
*/
public void setValueObject(Object value) {
Object oldValue = this.value;
this.value = value;
valueString = null;
if (value != null && defaultValue == null)
setDefaultValueObject(value);
if (owner != null) {
if (oldValue == null) {
if (value == null)
return;
}
else if (oldValue.equals(value))
return;
owner.parameterChanged(this,oldValue,value);
}
}
/**
* Explicitely set the default value object for this Parameter. The default
* value is also set, automatically, the first time that a non-null value object is
* specified, either in the constructor or in a call to setValueObject(). The
* value is set without checking whether the value of the correct type for this
* parameter. Note that only a pointer to the specified value is saved -- if the
* object is modified later, the default value of the parameter will change.
* The default value is used only in the getDefaultValueObject method.
*/
public void setDefaultValueObject(Object object) {
defaultValue = object;
defaultValueString = null;
}
/**
* Returns the default value of this parameter.
* @see #setDefaultValueObject(Object)
*/
public Object getDefaultValueObject() {
return defaultValue;
}
/**
* Sets the name of this object. The name is used internally in programs. It is not
* meant to be human-readable. In many cases, it will be in a format that can be used as a key in
* a properties file, which can map the name to a human-readable "title". The name can
* be null. A typical name might consist of the class name of the owner combined with
* a name for this particular parameter of the owner. In general, the name of a parameter
* should uniquely identify the parameters among all parameters associated with an Exhibit and
* with any View that displays that Exhibit.
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns the name of this parameter. The name can be null.
*/
public String getName() {
return name;
}
/**
* This method is meant to return a human-readable title or description for this parameter (one
* that could be used in a menu, for example). In this class, the title is obtained by calling
* the method I18n.tr(name) where "name" is the name of this parameter as returned by getName,
* or is "unnamed.parameter" if the name is null. Note that as a result of the definition of I18n.tr,
* if the name is non-null and is not mapped to a property, then the title will be the same as the name.
* @see #setName(String)
* @see I18n#tr(String)
*/
public String getTitle() {
String name = getName();
if (name == null)
return I18n.tr("unnamed.parameter");
else
return I18n.tr(name);
}
/**
* The text returned by this method, if any, is used as a ToolTip on the name of the parameter in
* parameter dialogs. If the return value in this class is null, no ToolTip is associated with the parameter name.
* The method in this class returns the value of I18n.trIfFound(getName() + ".hint"). If the name
* is null, the return value is null.
*/
public String getHint() {
String name = getName();
String hint = null;
if (name != null)
hint = I18n.trIfFound(name + ".hint");
return hint;
}
/**
* Returns a non-null string representation of this Parameter's value. It should be
* possible to use the returned value as a parameter to setValueFromString to restore
* the parameter to the same value. The value is obtained as follows: If this parameter's
* value was set most recently from a String, then that string is returned. Otherwise,
* if the parameter's value object is null, then the string "0" is returned. And if not,
* then the return value is obtained by applying the valueObjectToString method
* to the value object.
* @see #valueObjectToString(Object)
*/
final public String getValueAsString() {
if (valueString != null)
return valueString;
else if (value == null)
return "0";
else
return valueObjectToString(value);
}
/**
* Returns a non-null string representation of this Parameter's default value.
* If the Parameter's default value was set from a String, then that string is returned.
* Otherwise, if this Parameter's default value object is null, the return value is the string "0",
* and if not, then the return value is constructed by applying the valueObjectToString method
* to the default value object.
*/
public String getDefaultValueAsString() {
if (defaultValueString != null)
return defaultValueString;
else if (defaultValue == null)
return "0";
else
return valueObjectToString(defaultValue);
}
/**
* Sets the value of this parameter from a string representation of the value. The actual
* value is obtained from the stringToValueObject method.
* @param valueAsString A string representing the new value for this parameter. This string
* is passed to the stringToValueObject method to get the actual parameter value.
* This might result in a NumberFormatExcpetion or other error if the string does not represent
* a legal value for this parameter.
* @see #stringToValueObject(String)
*/
final public void setValueFromString(String valueAsString) {
boolean newDefaultVal = (defaultValue == null);
setValueObject(stringToValueObject(valueAsString));
valueString = valueAsString; // The previous line will have set valueString to null
if (newDefaultVal)
defaultValueString = valueAsString;
}
/**
* Sets the default value of this parameter from a string representation of the value. The actual
* value is obtained from the stringToValueObject method.
* @param valueAsString A string representing the new default value for this parameter. This string
* is passed to the stringToValueObject method to get the actual default value. This
* might result in an error if the string does not represent a legal value.
* @see #stringToValueObject(String)
*/
final public void setDefaultValueFromString(String valueAsString) {
setDefaultValueObject(stringToValueObject(valueAsString));
defaultValueString = valueAsString;
}
/**
* Sets both the value and the default value of this parameter from a string representation of the
* value.
* @param valueAsString string representing the value. This string
* is passed to the stringToValueObject method to get the actual value.
*/
final public void setValueAndDefaultFromString(String valueAsString) {
Object obj = stringToValueObject(valueAsString);
setValueObject(obj);
valueString = valueAsString;
setDefaultValueObject(obj);
defaultValueString = valueAsString;
}
/**
* Returns an input box for getting the value, animation start value, or animation
* end value from the user.
* @param inputType One of the constants {@link ParameterInput#VALUE},
* {@link ParameterInput#ANIMATION_START} or {@link ParameterInput#ANIMATION_END},
* indicating which type of value this method is meant to return.
* @return a ParameterInput consructed by calling new ParameterInput(this,inputType).
*/
public ParameterInput createParameterInput(int inputType) {
return new ParameterInput(this,inputType);
}
/**
* Returns a string including both the title and value of this Parameter.
* The string is constructed as: getTitle() + "(" + getValueAsString() + ")".
* @see #getValueAsString()
*/
public String toString() {
return getTitle() + "(" + getValueAsString() + ")";
}
}