/* * 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.swing; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.util.ArrayList; import javax.swing.JComponent; import org.opensourcephysics.ejs.control.ControlElement; import org.opensourcephysics.ejs.control.Utils; import org.opensourcephysics.ejs.control.value.Value; /** * <code>ControlSwingElement</code> is a base class for an object that * displays a visual java.awt.Component. * <p> * @see java.awt.Component * @see org.opensourcephysics.ejs.control.ControlElement */ public abstract class ControlSwingElement extends ControlElement { // Important: if you change the order of the properties you must up date // these constants accordingly!!! // These constants are her for use of any subclass that overrides the // setValue() method for any of these properties static public final int NAME = 0; // The name of the element // shadows superclass field static public final int POSITION = 1; // The position in its parent static public final int PARENT = 2; // Its parent static public final int ENABLED = 3; // Whetehr it is responsive or not static public final int VISIBLE = 4; // The visibility static public final int SIZE = 5; // The size static public final int FOREGROUND = 6; // The foreground color static public final int BACKGROUND = 7; // The background color static public final int FONT = 8; // The font static public final int TOOLTIP = 9; // The tooltip // Particular types of actions static public final int ACTION_PRESS = 10; static public final int ACTION_ON = 20; static public final int ACTION_OFF = 21; static private ArrayList<String> myInfoList = null; // The list of registered properties protected Component myVisual; // The visual element to display private Color myDefaultBkgd = null, myDefaultFrgd = null; private Font myDefaultFont = null; private Dimension mySize = null; // ------------------------------------------------ // Static constants and constructor // ------------------------------------------------ // public ControlSwingElement() { this(null); } /** * Instantiates an object that wrapps a Swing JComponent of this type. * If an object of an appropriate class is provided, it is used as * the visual. * @param _visual The javax.swing.JComponent to be wrapped */ public ControlSwingElement(Object _visual) { super(_visual); myVisual = createVisual(_visual); super.myObject = myVisual; myDefaultFrgd = myVisual.getForeground(); myDefaultBkgd = myVisual.getBackground(); myDefaultFont = myVisual.getFont(); if(myVisual instanceof JComponent) { mySize = ((JComponent) myVisual).getPreferredSize(); } } // ------------------------------------------------ // Visual components // ------------------------------------------------ /** * Creates the visual component of this <code>ControlElement</code>, * the one you can configure graphically. * If an object of an appropriate class is provided, it is used as * the visual. * @param _visual The javax.swing.JComponent to be wrapped */ abstract protected Component createVisual(Object _visual); /** * Returns the visual component of this <code>ControlElement</code>, * the one you can configure graphically. */ final public Component getVisual() { return myVisual; } /** * Returns the component of this <code>ControlElement</code>, * the one that is added to a container. */ public Component getComponent() { return myVisual; } // This one is not final becuase, although this is the usual behaviour, // there are exceptions. F. i., when embedding the visual into a JScrollPane // ------------------------------------------------ // Definition of Properties // ------------------------------------------------ /** * Returns the list of all properties that can be set for this * ControlElement. * Subclasses that add properties should extend this table. * Order is crucial here: Both for the presentation in an editor (f.i. ViewElement) * and for the setValue() method. */ // Important: Order is crucial!!! if you change the order of the properties // you must up date the constants at the beginning of this file accordingly!!! public ArrayList<String> getPropertyList() { if(myInfoList==null) { myInfoList = new ArrayList<String>(); myInfoList.add("name"); //$NON-NLS-1$ myInfoList.add("position"); //$NON-NLS-1$ myInfoList.add("parent"); //$NON-NLS-1$ myInfoList.add("enabled"); //$NON-NLS-1$ myInfoList.add("visible"); //$NON-NLS-1$ myInfoList.add("size"); //$NON-NLS-1$ myInfoList.add("foreground"); //$NON-NLS-1$ myInfoList.add("background"); //$NON-NLS-1$ myInfoList.add("font"); //$NON-NLS-1$ myInfoList.add("tooltip"); //$NON-NLS-1$ } return myInfoList; } /** * Returns information about a given property. * Subclasses that add properties should extend this table. * <ll> * <li> The first keyword is ALWAYS the type. * <li> The keyword <b>CONSTANT</b> applies to properties that can not be * changed using the setValue() methods * <li> The keyword <b>BASIC</b> is used by Ejs to group properties to the left * hand side of the property editor * <li> The keyword <b>HIDDEN</b> is used by Ejs so that it does not display * an entry in the editor field * </ll> */ // Order in the implementation is irrelevant. public String getPropertyInfo(String _property) { if(_property.equals("name")) { //$NON-NLS-1$ return "String CONSTANT HIDDEN"; //$NON-NLS-1$ } if(_property.equals("position")) { //$NON-NLS-1$ return "Position CONSTANT PREVIOUS HIDDEN "; //$NON-NLS-1$ } if(_property.equals("parent")) { //$NON-NLS-1$ return "ControlElement CONSTANT HIDDEN"; //$NON-NLS-1$ } if(_property.equals("enabled")) { //$NON-NLS-1$ return "boolean BASIC HIDDEN"; //$NON-NLS-1$ } if(_property.equals("visible")) { //$NON-NLS-1$ return "boolean BASIC HIDDEN"; //$NON-NLS-1$ } if(_property.equals("size")) { //$NON-NLS-1$ return "Dimension|Object BASIC"; //$NON-NLS-1$ } if(_property.equals("foreground")) { //$NON-NLS-1$ return "Color|Object BASIC"; //$NON-NLS-1$ } if(_property.equals("background")) { //$NON-NLS-1$ return "Color|Object BASIC"; //$NON-NLS-1$ } if(_property.equals("font")) { //$NON-NLS-1$ return "Font|Object BASIC"; //$NON-NLS-1$ } if(_property.equals("tooltip")) { //$NON-NLS-1$ return "String BASIC TRANSLATABLE"; //$NON-NLS-1$ } return null; } /** * Checks if a value can be considered a valid constant value for a property * If not, it returns null, meaning the value can be considered to be * a GroupVariable or a primitive constant. * This method implements more cases than really needed for the base class. * This is in order to save repetitions in swing subclasses. * @param String _property The property name * @param String _value The proposed value for the property */ public Value parseConstant(String _propertyType, String _value) { if(_value==null) { return null; } Value constantValue; if(_propertyType.indexOf("Alignment")>=0) { //$NON-NLS-1$ constantValue = ConstantParser.alignmentConstant(_value); if(constantValue!=null) { return constantValue; } } if(_propertyType.indexOf("Dimension")>=0) { //$NON-NLS-1$ constantValue = ConstantParser.dimensionConstant(_value); if(constantValue!=null) { return constantValue; } } if(_propertyType.indexOf("Layout")>=0) { //$NON-NLS-1$ constantValue = ConstantParser.layoutConstant(((ControlContainer) this).getContainer(), _value); if(constantValue!=null) { return constantValue; } } if(_propertyType.indexOf("Orientation")>=0) { //$NON-NLS-1$ constantValue = ConstantParser.orientationConstant(_value); if(constantValue!=null) { return constantValue; } } if(_propertyType.indexOf("Placement")>=0) { //$NON-NLS-1$ constantValue = ConstantParser.placementConstant(_value); if(constantValue!=null) { return constantValue; } } if(_propertyType.indexOf("Point")>=0) { //$NON-NLS-1$ constantValue = ConstantParser.pointConstant(_value); if(constantValue!=null) { return constantValue; } } return super.parseConstant(_propertyType, _value); } // ------------------------------------------------ // Set and Get the values of the properties // ------------------------------------------------ /** * Sets the value of the registered variables. * Subclasses with internal values should extend this * @param _index A keyword index that distinguishes among variables * @param _value The object holding the value for the variable. */ public void setValue(int _index, Value _value) { // System.out.println ("Setting property #"+_index+" to "+_value.toString()); switch(_index) { case NAME : super.setValue(ControlElement.NAME, _value); getComponent().setName(_value.toString()); // Added for WC on 051209 break; case POSITION : { ControlElement parent = myGroup.getElement(getProperty("parent")); //$NON-NLS-1$ if((parent!=null)&&(parent instanceof ControlContainer)) { ((ControlContainer) parent).remove(this); } myPropertiesTable.put("position", _value.toString()); //$NON-NLS-1$ if((parent!=null)&&(parent instanceof ControlContainer)) { ((ControlContainer) parent).add(this); } } break; case PARENT : { ControlElement parent = myGroup.getElement(getProperty("parent")); //$NON-NLS-1$ if((parent!=null)&&(parent instanceof ControlContainer)) { ((ControlContainer) parent).remove(this); } parent = myGroup.getElement(_value.toString()); if(parent==null) { if(!(this instanceof ControlWindow)) { System.err.println(getClass().getName()+" : Error! Parent <"+_value+"> not found for "+toString()); //$NON-NLS-1$ //$NON-NLS-2$ } } else { if(parent instanceof ControlContainer) { ((ControlContainer) parent).add(this); } else { System.err.println(getClass().getName()+" : Error! Parent <"+_value+"> is not a ControlContainer"); //$NON-NLS-1$ //$NON-NLS-2$ } } } break; case ENABLED : getVisual().setEnabled(_value.getBoolean()); break; // enabled case VISIBLE : getVisual().setVisible(_value.getBoolean()); break; // visible case SIZE : // Size (myVisual is necessarily a JComponent) if(getComponent() instanceof JComponent) { Dimension size = (Dimension) _value.getObject(); if((size.width==mySize.width)&&(size.height==mySize.height)) { return; // Do not waste time } ((JComponent) getComponent()).setPreferredSize(mySize = size); if(this instanceof ControlContainer) { ((ControlContainer) this).getContainer().validate(); } ControlElement parentElement = myGroup.getElement(getProperty("parent")); //$NON-NLS-1$ if(parentElement!=null) { ((ControlContainer) parentElement).adjustSize(); } } break; case FOREGROUND : // Foreground (not much time is wasted if the color is the same) if(_value.getObject() instanceof Color) { getVisual().setForeground((Color) _value.getObject()); } break; case BACKGROUND : // Background if(_value.getObject() instanceof Color) { getVisual().setBackground((Color) _value.getObject()); } break; case FONT : // Font if(_value.getObject() instanceof Font) { getVisual().setFont((Font) _value.getObject()); } break; case TOOLTIP : // Tooltip if(getVisual() instanceof JComponent) { ((JComponent) getVisual()).setToolTipText(_value.toString()); } break; default : // Do nothing. No inherited properties } } public void setDefaultValue(int _index) { // System.out.println ("Setting default value for property #"+_index); switch(_index) { case NAME : super.setDefaultValue(ControlElement.NAME); break; case POSITION : { ControlElement parent = myGroup.getElement(getProperty("parent")); //$NON-NLS-1$ if((parent!=null)&&(parent instanceof ControlContainer)) { ((ControlContainer) parent).remove(this); } myPropertiesTable.remove("position"); //$NON-NLS-1$ if((parent!=null)&&(parent instanceof ControlContainer)) { ((ControlContainer) parent).add(this); } } break; case PARENT : { ControlElement parent = myGroup.getElement(getProperty("parent")); //$NON-NLS-1$ if((parent!=null)&&(parent instanceof ControlContainer)) { ((ControlContainer) parent).remove(this); } } break; case ENABLED : getVisual().setEnabled(true); break; case VISIBLE : getVisual().setVisible(true); break; case SIZE : // Size (getComponent() is necessarily a JComponent) if(getComponent() instanceof JComponent) { ((JComponent) getComponent()).setPreferredSize(null); // ask the UI for the default if(this instanceof ControlContainer) { ((ControlContainer) this).getContainer().validate(); } ControlElement parentElement = myGroup.getElement(getProperty("parent")); //$NON-NLS-1$ if(parentElement!=null) { ((ControlContainer) parentElement).adjustSize(); } } break; case FOREGROUND : getVisual().setForeground(myDefaultFrgd); break; case BACKGROUND : getVisual().setBackground(myDefaultBkgd); break; case FONT : getVisual().setFont(myDefaultFont); break; case TOOLTIP : if(getComponent() instanceof JComponent) { ((JComponent) getVisual()).setToolTipText(null); } break; default : break; } } /** * Gets the value of any internal variable. * Subclasses with internal values should extend this * @param _index A keyword index that distinguishes among variables * @return Value _value The object holding the value for the variable. */ public Value getValue(int _index) { return null; // Any of these properties can be modified by the element } // ------------------------------------------------ // A utility for subclasses that require an icon // ------------------------------------------------ protected javax.swing.ImageIcon getIcon(String _iconFile) { javax.swing.ImageIcon icon; if(getProperty("_ejs_codebase")!=null) { //$NON-NLS-1$ icon = Utils.icon(getProperty("_ejs_codebase"), _iconFile); //$NON-NLS-1$ } else if((getSimulation()!=null)&&(getSimulation().getCodebase()!=null)) { icon = Utils.icon(getSimulation().getCodebase().toString(), _iconFile); } else { icon = Utils.icon(null, _iconFile); } return icon; } } // 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 */