/*
* Open Source Physics software is free software as described near the bottom of this code file.
*
* For additional information and documentation on Open Source Physics please see:
* <http://www.opensourcephysics.org/>
*/
package org.opensourcephysics.ejs.control;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;
import org.opensourcephysics.controls.XML;
import org.opensourcephysics.controls.XMLControl;
import org.opensourcephysics.ejs.Simulation;
import org.opensourcephysics.ejs.control.swing.ControlContainer;
import org.opensourcephysics.ejs.control.swing.ControlDialog;
import org.opensourcephysics.ejs.control.swing.ControlFrame;
import org.opensourcephysics.ejs.control.swing.ControlWindow;
import org.opensourcephysics.ejs.control.value.BooleanValue;
import org.opensourcephysics.ejs.control.value.DoubleValue;
import org.opensourcephysics.ejs.control.value.IntegerValue;
import org.opensourcephysics.ejs.control.value.ObjectValue;
import org.opensourcephysics.ejs.control.value.StringValue;
import org.opensourcephysics.ejs.control.value.Value;
/**
* A base class to group several ControlElements, connect them
* to one or more target objects in a unified form, and build a
* graphic interface with all of them.
*/
// Note for myself: This class is still very much dependent on the actual
// implementation of some of the particular subclasses of ControlElement,
// like ControlContainer, ControlFrame and ControlDialog.
public class GroupControl {
public static final int DEBUG_NONE = 0;
public static final int DEBUG_SET_AND_GET = 1;
public static final int DEBUG_ELEMENTS = 2;
public static final int DEBUG_CONTROL = 4;
public static final int DEBUG_CONTROL_VERBOSE = 8;
public static final int DEBUG_DRAWING = 16;
public static final int DEBUG_DRAWING_VERBOSE = 32;
public static final int DEBUG_SYSTEM = 64;
public static final int DEBUG_SYSTEM_VERBOSE = 128;
public static final int DEBUG_ALL = 255;
private int debugLevel = 0;
private String debugPrefix = ""; //$NON-NLS-1$
protected String replaceOwnerName = null;
private java.awt.Frame ownerFrame = null;
protected java.awt.Frame replaceOwnerFrame = null;
// private String defaultPrefix = null;
private Vector<String> prefixList = new Vector<String>();
private Simulation mySimulation = null;
private Hashtable<String, Object> targetTable = new Hashtable<String, Object>();
private Hashtable<String, ControlElement> elementTable = new Hashtable<String, ControlElement>();
Hashtable<String, GroupVariable> variableTable = new Hashtable<String, GroupVariable>();
private Vector<ControlElement> elementList = new Vector<ControlElement>();
private Vector<ControlElement> updateList = new Vector<ControlElement>();
GroupVariable methodTriggerVariable = null; // AMAVP (See Note in ControlElement)
/**
* The default constructor.
*/
public GroupControl() {
debugPrefix = this.getClass().getName();
int index = debugPrefix.lastIndexOf("."); //$NON-NLS-1$
if(index>=0) {
debugPrefix = debugPrefix.substring(index+1);
}
appendPrefixPath("org.opensourcephysics.ejs.control.swing.Control"); //$NON-NLS-1$
appendPrefixPath("org.opensourcephysics.ejs.control.drawables.Control"); //$NON-NLS-1$
appendPrefixPath("org.opensourcephysics.ejs.control.displayejs.Control"); //$NON-NLS-1$
setValue(ControlElement.METHOD_TRIGGER, new BooleanValue(false)); // AMAVP
methodTriggerVariable = variableTable.get(ControlElement.METHOD_TRIGGER); // AMAVP
}
/**
* The constructor.
* @param _target
*/
public GroupControl(Object _target) {
this();
addTarget("_default_", _target); //$NON-NLS-1$
if(_target instanceof Simulation) {
setSimulation((Simulation) _target);
}
}
/**
* A specialized constructor for Ejs use.
* This adds elements to it in the ususal way, but replaces a Frame element
* of a given name by the prescribed frame.
* @param _simulation
* @param _replaceName
* @param _replaceOwnerFrame
*/
public GroupControl(Object _simulation, String _replaceName, java.awt.Frame _replaceOwnerFrame) {
this(_simulation);
replaceOwnerFrame(_replaceName, _replaceOwnerFrame);
}
// ------------------------------------------------
// Preliminary things
// ------------------------------------------------
/**
* Sets the owner frame for all subsequent Dialogs
* @param Frame _frame The frame that should own next Dialogs
* (if there are Dialogs in this group)
*/
public void setOwnerFrame(java.awt.Frame _frame) {
ownerFrame = _frame;
}
/**
* Returns the owner frame for all subsequent Dialogs
*/
public java.awt.Frame getOwnerFrame() {
return ownerFrame;
}
public void replaceOwnerFrame(String _replaceName, java.awt.Frame _replaceOwnerFrame) {
replaceOwnerName = _replaceName;
replaceOwnerFrame = _replaceOwnerFrame;
}
/**
* Returns the name of the replacement for the owner frame for all subsequent Dialogs
*/
public String getReplaceOwnerName() {
return replaceOwnerName;
}
/**
* Returns the replacement for the owner frame for all subsequent Dialogs
*/
public java.awt.Frame getReplaceOwnerFrame() {
return replaceOwnerFrame;
}
/**
* Clears the list of default package name for unqualified elements
*/
public void clearPrefixPath() {
prefixList.clear();
}
/**
* Adds a prefix 'path' for unqualified elements. Hence "Frame"
* becomes _prefix + "Frame". The default list includes
* "org.opensourcephysics.ejs.control.swing.Control" and
* "org.opensourcephysics.ejs.control.drawables.Control"
* @param String _prefix The prefix to be added to list
*/
public void appendPrefixPath(String _prefix) {
prefixList.add(_prefix);
}
/**
* Returns the list (actually, a vector) of prefix
*/
public Vector<String> getDefaultPrefixList() {
return prefixList;
}
/**
* Sets the simulation under which the control is running
* This is used to up date the simulation whenever an Element changes a
* variable (See variableChanged in ControlElement)
* @param Simulation _sim The simulation
*/
public void setSimulation(Simulation _sim) {
mySimulation = _sim;
}
/**
* Returns the simulation under which the control is running
* This is used to up date the simulation whenever an Element changes a
* variable (See variableChanged in ControlElement
*/
public Simulation getSimulation() {
return mySimulation;
}
/**
* Sets the debug level
* @param int _level The minimim level that should
* produce debug mesagges. Must be one of
* DEBUG_NONE, DEBUG_SET_AND_GET, DEBUG_ELEMENTS,
* DEBUG_ALL=255
*/
public void setDebugLevel(int _level) {
debugLevel = _level;
}
/**
* Returns the current debug level
* @return The actual minimim level that produces debug messages
*/
public int getDebugLevel() {
return debugLevel;
}
// ------------------------------------------------
// Targets
// ------------------------------------------------
/**
* Returns one of the registered target objects
* @param String _name The name given to the target when it was added
*/
public Object getTarget(String _name) {
return targetTable.get(_name);
}
/**
* Adds an object to be controlled. Actions can then refer to methods of the
* form 'name.method:parameter'
* @param String _name A name to refer to the target
* @param Object _target A target object
*/
public void addTarget(String _name, Object _target) {
targetTable.put(_name, _target);
}
/**
* Removes a target object
*/
public void removeTarget(String _name) {
targetTable.remove(_name);
}
// --------------------------------------------------------
// Dealing with group variables
// --------------------------------------------------------
/**
* Sets the group value for a variable. This includes the value in all
* the elements of this group that are registered to this variable name.
* @param String _name The variable name
* @param Value _value The value as a <code>Value</code> object
*/
public void setValue(String _name, Value _value) {
// I have commented out the debug messages to improve performance (??).
// Uncomment them if you want further debug messages
// if ((debugLevel & DEBUG_SET_AND_GET)>0)
// System.out.print(debugPrefix+": Setting value of <"+_name+"> to <"+_value+"> ...");
// if (_name==null) return;
GroupVariable variable = variableTable.get(_name);
if(variable==null) {
variable = new GroupVariable(_name, _value);
variableTable.put(_name, variable);
// if ((debugLevel & DEBUG_SET_AND_GET)>0) System.out.println("Created <"+_name+"> with value <"+_value+">");
} else {
variable.setValue(_value);
variable.propagateValue(null);
// if ((debugLevel & DEBUG_SET_AND_GET)>0) System.out.println("<"+_name+"> set to <"+_value+">");
}
}
/**
* Returns the group value of a variable.
* @return the <code>Value</code> object of the variable. If the
* variable has never been set, it returns <b>null</b>.
* @param String _name The variable name
*/
public Value getValue(String _name) {
// I have commented the debug messages out to improve performance (??).
// Uncomment them if you want further debug messages
// if ((debugLevel & DEBUG_SET_AND_GET)>0)
// System.out.print(debugPrefix+": Getting value of <"+_name+ ">...");
GroupVariable variable = variableTable.get(_name);
if(variable==null) {
// if ((debugLevel & DEBUG_SET_AND_GET)>0) System.out.println("<"+_name+"> has not been set!");
return null;
}
// if ((debugLevel & DEBUG_SET_AND_GET)>0) System.out.println("<"+_name+"> found with value = <"+variable.value+">");
return variable.getValue();
}
/**
* Associates an element internal value with a variable name. Later on,
* when the user sets the value for this variable, either
* programmatically or by interaction with a given element,
* all registered elements will be informed of the change.
* Invoked by ControlElements when processing the 'variable'
* property. Not to be used directly by users.
* @param String _name The name of the variable
* @param ControlElement _element The element to be registered
* @param int _index An indentifier for the element internal value
* @param Value _value The initial value if the variable doesn't already exist
*/
public GroupVariable registerVariable(String _name, ControlElement _element, int _index, Value _value) {
// if ((debugLevel & DEBUG_SET_AND_GET)>0)
// System.out.print(debugPrefix+": Registering variable <"+_name
// + "> for element <"+_element+"> at index "+_index+" with value = "+_value);
if(_name==null) {
return null;
}
GroupVariable variable = variableTable.get(_name);
if(variable==null) {
variable = new GroupVariable(_name, _value);
variableTable.put(_name, variable);
if((debugLevel&DEBUG_SET_AND_GET)>0) {
System.out.print(" Created new variable <"+_name+"> with value = <"+_value+"> ..."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
// else variable.setValue(_value); // Commented means that the element takes
// the actual value, whatever it is
// System.out.println(" variable <"+_name+"> has value = <"+getValue(_name)+"> ...");
if((debugLevel&DEBUG_SET_AND_GET)>0) {
System.out.println(" Variable <"+_name+"> registered for element <"+_element+">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
variable.addElementListener(_element, _index);
variable.propagateValue(null); // null implies that the element takes the actual value
return variable;
}
/**
* Tells whether a variable is associated to any element.
* Invoked by EjsControl's method 'setValue/getValue'.
* Not to be used directly by users.
* @param ControlElement _element The element to be included
* @param String _variable The variable name
*/
public boolean isVariableRegistered(String _name) {
if(_name==null) {
return false;
}
return(variableTable.get(_name)!=null);
}
/**
* Invoked by ControlElements when their internal variables change.
* Not be used directly by users.
*/
public void variableChanged(GroupVariable _variable, ControlElement _element, Value _value) {
if(_variable==null) {
return;
}
_variable.setValue(_value);
_variable.propagateValue(_element);
_variable.invokeListeners(_element); // Call any registered listener
}
public void addListener(String _name, String _method) {
addListener(_name, _method, null);
}
/**
* Instructs the group to invoke a method (with an optional parameter) when a
* variable changes.
* @param String _name The name of the variable that may change
* @param String _method The method that should be called in the controlled
* @param Object _anObject the object to pass in the special case the method is method(#CONTROL#)
* object.
*/
public void addListener(String _name, String _method, Object _anObject) {
if((debugLevel&DEBUG_SET_AND_GET)>0) {
System.out.print(debugPrefix+": Adding listener for variable <"+_name+"> to <"+_method+"> ..."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
if(_name==null) {
return;
}
String[] parts = MethodWithOneParameter.splitMethodName(_method);
if(parts==null) {
System.err.println(getClass().getName()+" : Error! Listener <"+_method+"> not assigned"); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
if(parts[0]==null) {
parts[0] = "_default_"; //$NON-NLS-1$
}
Object target = getTarget(parts[0]);
if(target==null) {
System.err.println(getClass().getName()+" : Error! Target <"+parts[0]+"> not assigned"); //$NON-NLS-1$ //$NON-NLS-2$
return;
} else if((debugLevel&DEBUG_SET_AND_GET)>0) {
System.out.print(debugPrefix+": Target <"+parts[0]+"> found. Method is <"+_method+"> ..."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
GroupVariable variable = variableTable.get(_name);
if(variable==null) {
variable = new GroupVariable(_name, doubleValue);
variableTable.put(_name, variable);
if((debugLevel&DEBUG_SET_AND_GET)>0) {
System.out.print(" Created new variable <"+_name+"> for listener <"+_method+"> ..."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
if(parts[2]==null) {
variable.addListener(target, parts[1]+"()", _anObject); //$NON-NLS-1$
} else {
variable.addListener(target, parts[1]+"("+parts[2]+")", _anObject); //$NON-NLS-1$ //$NON-NLS-2$
}
}
// --------------------------------------------------------
// Adding and removing control elements
// --------------------------------------------------------
/**
* Renaming a ControlElement
* @param String _name The new name for the element.
*/
public void rename(ControlElement _element, String _name) {
String oldName = _element.getProperty("name"); //$NON-NLS-1$
if(oldName!=null) {
elementTable.remove(oldName);
}
if(_name!=null) {
elementTable.put(_name, _element);
}
}
/**
* Creates a new ControlElement with a given name
* This is a special feature that is used by LauncherApplet, so that
* if the name coincides with a given one, a Frame becomes a Panel,
* so that it can be captured!
* @param String _type The class name of the new element.
* @param String _name The name of the new element.
*/
final public ControlElement addNamed(String _type, String _name) {
String propertyList = "name="+_name; //$NON-NLS-1$
if((replaceOwnerName==null)||!replaceOwnerName.equals(_name)) {
return addObject(null, _type, propertyList);
}
if(_type.endsWith("ControlFrame")||_type.endsWith("ControlDrawingFrame")) { //$NON-NLS-1$ //$NON-NLS-2$
setOwnerFrame(replaceOwnerFrame);
return addObject(null, "org.opensourcephysics.ejs.control.swing.ControlPanel", propertyList); //$NON-NLS-1$
}
return addObject(null, _type, propertyList);
}
/**
* Creates a new ControlElement
* @param String _type The class name of the new element.
* If it is not qualified, then it is given the prefix (see above)
*/
final public ControlElement add(String _type) {
return addObject(null, _type, null);
}
/**
* Creates a new ControlElement and gives it a name
* @param String _type The class name of the new element.
* If it is not qualified, then it is given the default prefix (see above)
* @param String _propertyList A list of properties and Values
* to be set (see ControlElement.setProperties())
*/
final public ControlElement add(String _type, String _propertyList) {
return addObject(null, _type, _propertyList);
}
/**
* Creates a new ControlElement that wrapps an existing object
* If the object is not of the right class it will print a warning
* and ignore the object provided.
* @param Object _object The element to be wrapped
* @param String _type The class name of the new element.
* If it is not qualified, then it is given the prefix (see above)
*/
final public ControlElement addObject(Object _object, String _type) {
return addObject(_object, _type, null);
}
/**
* Creates a new ControlElement that wrapps an existing object
* If the object is not of the right class it will print a warning
* and ignore the object provided.
* @param Object _object The element to be wrapped
* @param String _type The class name of the new element.
* If it is not qualified, then it is given the prefix (see above)
* @param String _propertyList A list of properties and Values
* to be set (see ControlElement.setProperties())
*/
public ControlElement addObject(Object _object, String _type, String _propertyList) {
ControlElement element = null;
if((debugLevel&DEBUG_ELEMENTS)>0) {
System.err.println(this.getClass().getName()+" Adding element of type <"+_type+"> with properties <"+_propertyList+">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if(_object!=null) {
System.err.println(this.getClass().getName()+" using element "+_object); //$NON-NLS-1$
}
}
if(_type.indexOf(".")<0) { //$NON-NLS-1$
for(Enumeration<String> e = prefixList.elements(); e.hasMoreElements()&&(element==null); ) {
element = instantiateClass(_object, e.nextElement()+_type, false); // Silently
}
}
if(element==null) {
element = instantiateClass(_object, _type, true);
}
if(element==null) {
return null;
}
// Frames become automatically ownerFrames for subsequent Dialogs
if(element instanceof ControlFrame) {
setOwnerFrame((java.awt.Frame) ((ControlFrame) element).getComponent());
}
// Use ownerFrame for Dialogs, if there is any
if((element instanceof ControlDialog)&&(ownerFrame!=null)) {
((javax.swing.JDialog) ((ControlDialog) element).getComponent()).dispose();
((ControlDialog) element).replaceVisual(ownerFrame);
}
element.setGroup(this);
elementList.add(element);
if(element instanceof NeedsUpdate) {
updateList.add(element);
}
if((debugLevel&DEBUG_ELEMENTS)>0) {
System.err.println(this.getClass().getName()+" Setting properties to <"+_propertyList+">"); //$NON-NLS-1$ //$NON-NLS-2$
}
if(_propertyList!=null) {
element.setProperties(_propertyList);
}
if(element instanceof ControlWindow) { // Make windows visible by default
if(element.getProperty("visible")==null) { //$NON-NLS-1$
element.setProperty("visible", "true"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
return element;
}
private ControlElement instantiateClass(Object _object, String _classname, boolean _verbose) {
if((debugLevel&DEBUG_ELEMENTS)>0) {
System.err.println(this.getClass().getName()+": Trying to instantiate element of class "+_classname); //$NON-NLS-1$
if(_object!=null) {
System.err.println(this.getClass().getName()+" using element "+_object); //$NON-NLS-1$
}
}
// if (_object!=null) // Even if the object to wrapp is null!
try {
Class<?> aClass = Class.forName(_classname);
Class<?>[] c = {Object.class};
Object[] o = {_object};
java.lang.reflect.Constructor<?> constructor = aClass.getDeclaredConstructor(c);
return(ControlElement) constructor.newInstance(o);
} catch(Exception _exc) {
if(_verbose) {
_exc.printStackTrace();
return null;
} // Do not exit if in silent mode
}
// Try once more with the default constructor
try {
Class<?> aClass = Class.forName(_classname);
return(ControlElement) aClass.newInstance();
} catch(Exception _exc) {
if(_verbose) {
_exc.printStackTrace();
}
return null;
}
}
/**
* Returns a control element by name
* @return the ControlElement if found, null otherwise.
* @param String _name The name of the control element
*/
public ControlElement getElement(String _name) {
if(_name==null) {
return null;
}
ControlElement element = elementTable.get(_name);
if(element==null) {
// Commented out to improve performance
// if ((debugLevel & DEBUG_ELEMENTS)>0) {
// System.err.println(this.getClass().getName()+" Warning!: control element <"+_name+"> not found!");
// System.err.println(" List of named elements follows: ");
// for (Enumeration e = elementTable.elements() ; e.hasMoreElements() ;) {
// element = (ControlElement) e.nextElement();
// String name = element.getProperty("name");
// if (name!=null) System.err.println(" "+name+"(class is "+element.getClass().getName()+")");
// }
// }
return null;
}
return element;
}
// For backwards compatibility
public ControlElement getControl(String _name) {
return getElement(_name);
}
/**
* Returns the visual of a control element by name
* @return the java.awt.Component visual of the element if found, null otherwise.
* @param String _name The name of the control element
*/
public java.awt.Component getVisual(String _name) {
ControlElement element = getElement(_name);
if(element==null) {
return null;
}
return element.getVisual();
}
/**
* Returns the component of a control element by name
* @return the java.awt.Component component of the element if found, null otherwise.
* @param String _name The name of the control element
*/
public java.awt.Component getComponent(String _name) {
ControlElement element = getElement(_name);
if(element==null) {
return null;
}
return element.getComponent();
}
/**
* Returns the container of a control element by name
* @return the java.awt.Container visual of the element if found, and the
* element is a container, null otherwise.
* @param String _name The name of the control element
*/
public java.awt.Container getContainer(String _name) {
ControlElement element = getElement(_name);
if(element instanceof ControlContainer) {
return((ControlContainer) element).getContainer();
}
return null;
}
/**
* Completely destroy a ControlElement by name
* @param String _name The name of the ControlElement to be destroyed
*/
public void destroy(String _name) {
destroy(getElement(_name), true);
}
/**
* Completely destroy a ControlElement
* @param ControlElement _element The ControlElement to be destroyed
*/
public void destroy(ControlElement _element) {
destroy(_element, true);
}
/**
* Reset all elements
*/
public void reset() {
for(Enumeration<ControlElement> e = elementList.elements(); e.hasMoreElements(); ) {
// ControlElement ele = (ControlElement ) e.nextElement();
// System.out.println ("Resettimng element "+ele);
// ele.reset();
e.nextElement().reset();
}
}
/**
* Initialize all elements
*/
public void initialize() {
for(Enumeration<ControlElement> e = elementList.elements(); e.hasMoreElements(); ) {
e.nextElement().initialize();
}
}
/**
* Refresh all elements
*/
public void update() {
methodTriggerVariable.propagateValue(null); // AMAVP (See Note in ControlElement)
// setValue (ControlElement.METHOD_TRIGGER,true);
// for (Enumeration e=elementList.elements(); e.hasMoreElements(); ) ((ControlElement) e.nextElement()).update();
for(Enumeration<ControlElement> e = updateList.elements(); e.hasMoreElements(); ) {
((NeedsUpdate) e.nextElement()).update();
}
}
/**
* Set the active state of all elements
*/
public void setActive(boolean _active) {
for(Enumeration<ControlElement> e = elementList.elements(); e.hasMoreElements(); ) {
e.nextElement().setActive(_active);
}
}
/**
* Clears all variables
*/
public void clearVariables() {
variableTable.clear();
}
/**
* Destroy all elements
*/
public void clear() {
variableTable.clear();
setOwnerFrame(null);
for(Enumeration<ControlElement> e = elementList.elements(); e.hasMoreElements(); ) {
ControlElement element = e.nextElement();
String parent = element.getProperty("parent"); //$NON-NLS-1$
if(parent==null) {
destroy(element, false);
}
}
if((debugLevel&DEBUG_ELEMENTS)>0) {
System.err.println(this.getClass().getName()+" Warning!: All element were destroyed!"); //$NON-NLS-1$
System.err.println(" List of remaining elements follows: "); //$NON-NLS-1$
for(Enumeration<ControlElement> e = elementList.elements(); e.hasMoreElements(); ) {
ControlElement element = e.nextElement();
System.err.println(" "+element.toString()+"(class is "+element.getClass().getName()+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
}
private void destroy(ControlElement _element, boolean _informMyParent) {
if(_element==null) {
return;
}
if(_informMyParent) {
ControlElement parent = getElement(_element.getProperty("parent")); //$NON-NLS-1$
if(parent!=null) {
if(parent instanceof ControlContainer) {
((ControlContainer) parent).remove(_element);
}
} else { // It may have been added to a container programmatically
java.awt.Container cont = _element.getComponent().getParent();
if(cont!=null) {
cont.remove(_element.getComponent());
cont.validate();
cont.repaint();
}
}
}
_element.variablePropertiesClear();
String name = _element.getProperty("name"); //$NON-NLS-1$
if(name!=null) {
elementTable.remove(name);
}
elementList.remove(_element);
if(_element instanceof NeedsUpdate) {
updateList.remove(_element);
}
if(_element instanceof ControlContainer) {
for(Enumeration<ControlElement> e = ((ControlContainer) _element).getChildren().elements(); e.hasMoreElements(); ) {
ControlElement child = e.nextElement();
destroy(child, false);
}
}
if(_element instanceof ControlWindow) {
((ControlWindow) _element).dispose();
}
}
/**
* Returns the top-level ancestor of an element (either the
* containing Window or Applet), or null if the element has not
* been added to any container. If no element name is provided, the
* first control element whose component is a Window is returned.
* @return the Container if found, null otherwise.
* @param String _name The name of the control element
*/
public java.awt.Container getTopLevelAncestor(String _name) {
if(_name!=null) {
ControlElement element = getElement(_name);
java.awt.Component comp = element.getComponent();
if(comp instanceof javax.swing.JComponent) {
return((javax.swing.JComponent) comp).getTopLevelAncestor();
}
} else {
for(Enumeration<ControlElement> e = elementList.elements(); e.hasMoreElements(); ) {
ControlElement element = e.nextElement();
java.awt.Component comp = element.getComponent();
if(comp instanceof java.awt.Window) {
return(java.awt.Window) comp;
}
}
}
return null;
}
// -------------------------------------------------------
// Convenience methods
// Half way to org.opensourcephysics.controls.Control
// -------------------------------------------------------
// For the custom methods
private BooleanValue booleanValue = new BooleanValue(false);
private IntegerValue integerValue = new IntegerValue(0);
private DoubleValue doubleValue = new DoubleValue(0.0);
private StringValue stringValue = new StringValue(""); //$NON-NLS-1$
private ObjectValue objectValue = new ObjectValue(null);
// --------- Setting different types of values ------
/**
* A convenience method to set a value to a boolean
* @param _name
* @param _value
*/
public void setValue(String _name, boolean _value) {
booleanValue.value = _value;
setValue(_name, booleanValue);
}
/**
* A convenience method to set a value to an int
* @param _name
* @param _value
*/
public void setValue(String _name, int _value) {
integerValue.value = _value;
setValue(_name, integerValue);
}
/**
* A convenience method to set a value to a double
* @param _name
* @param _value
*/
public void setValue(String _name, double _value) {
doubleValue.value = _value;
setValue(_name, doubleValue);
}
/**
* A convenience method to set a value to a String
* @param _name
* @param _value
*/
public void setValue(String _name, String _value) {
stringValue.value = _value;
setValue(_name, stringValue);
}
/**
* A convenience method to set a value to any Object
* @param _name
* @param _value
*/
public void setValue(String _name, Object _value) {
if(_value instanceof String) {
setValue(_name, (String) _value);
} else {
objectValue.value = _value;
setValue(_name, objectValue);
}
}
// --------- Getting different types of values ------
/**
* A convenience method to get a value as a boolean
* @param _name
*/
public boolean getBoolean(String _name) {
Value value = getValue(_name);
if(value==null) {
return false;
}
return value.getBoolean();
}
/**
* A convenience method to get a value as an int
* @param _name
*/
public int getInt(String _name) {
Value value = getValue(_name);
if(value==null) {
return 0;
}
return value.getInteger();
}
/**
* A convenience method to get a value as a double
* @param _name
*/
public double getDouble(String _name) {
Value value = getValue(_name);
if(value==null) {
return 0.0;
}
return value.getDouble();
}
/**
* A convenience method to get a value as a String
* @param _name
*/
public String getString(String _name) {
Value value = getValue(_name);
if(value==null) {
return ""; //$NON-NLS-1$
}
return value.getString();
}
/**
* A convenience method to get a value as an Object
* @param _name
*/
public Object getObject(String _name) {
Value value = getValue(_name);
if(value==null) {
return null;
}
return value.getObject();
}
/**
* Returns an XML.ObjectLoader to save and load data for this object.
*
* @return the object loader
*/
public static XML.ObjectLoader getLoader() {
return new GroupControlLoader();
}
/**
* A class to save and load XML data for GroupControl.
*/
static class GroupControlLoader implements XML.ObjectLoader {
/**
* Saves object data to an XMLControl.
*
* @param control the control to save to
* @param obj the object to save
*/
public void saveObject(XMLControl control, Object obj) {
GroupControl groupcontrol = (GroupControl) obj;
Hashtable<String, GroupVariable> table = groupcontrol.variableTable;
Iterator<String> it = table.keySet().iterator();
while(it.hasNext()) {
String name = it.next();
if(!name.startsWith("_")) { // don't save ejs internal variables //$NON-NLS-1$
if(groupcontrol.getObject(name).getClass().isArray()) {
control.setValue(name, groupcontrol.getObject(name));
} else {
control.setValue(name, groupcontrol.getString(name));
}
}
}
}
/**
* Creates an object using data from an XMLControl.
*
* @param control the control
* @return the newly created object
*/
public Object createObject(XMLControl control) {
return new GroupControl(null);
}
/**
* Loads an object with data from an XMLControl.
*
* @param control the control
* @param obj the object
* @return the loaded object
*/
public Object loadObject(XMLControl control, Object obj) {
GroupControl groupcontrol = (GroupControl) obj;
Hashtable<String, GroupVariable> table = groupcontrol.variableTable;
Iterator<String> it = table.keySet().iterator();
while(it.hasNext()) {
String name = it.next();
if(control.getString(name)!=null) {
groupcontrol.setValue(name, control.getString(name));
} else if(control.getObject(name)!=null) {
Object namedObj = control.getObject(name);
if(namedObj instanceof java.awt.Color) {
groupcontrol.setValue(name, namedObj);
}
if(namedObj.getClass().isArray()) {
groupcontrol.setValue(name, namedObj);
} else {
groupcontrol.setValue(name, namedObj.toString());
}
}
}
return obj;
}
}
} // End of class
/*
* Open Source Physics software is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public License (GPL) as
* published by the Free Software Foundation; either version 2 of the License,
* or(at your option) any later version.
* Code that uses any portion of the code in the org.opensourcephysics package
* or any subpackage (subdirectory) of this package must must also be be released
* under the GNU GPL license.
*
* This software 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
* or view the license online at http://www.gnu.org/copyleft/gpl.html
*
* Copyright (c) 2007 The Open Source Physics project
* http://www.opensourcephysics.org
*/