001/* Base class for the properties that can be used to configure a tableau. 002 003 Copyright (c) 2008-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.actor.gui.properties; 029 030import java.awt.Dimension; 031 032import javax.swing.JComponent; 033import javax.swing.JFrame; 034 035import ptolemy.actor.gui.Tableau; 036import ptolemy.data.IntMatrixToken; 037import ptolemy.data.expr.Parameter; 038import ptolemy.data.type.BaseType; 039import ptolemy.kernel.util.Attribute; 040import ptolemy.kernel.util.IllegalActionException; 041import ptolemy.kernel.util.NameDuplicationException; 042import ptolemy.kernel.util.NamedObj; 043import ptolemy.kernel.util.Workspace; 044 045////////////////////////////////////////////////////////////////////////// 046//// GUIProperty 047 048/** 049 Base class for the properties that can be used to configure a tableau. 050 051 @author Thomas Huining Feng 052 @version $Id$ 053 @since Ptolemy II 8.0 054 @Pt.ProposedRating Red (tfeng) 055 @Pt.AcceptedRating Red (tfeng) 056 */ 057public abstract class GUIProperty extends Attribute { 058 059 /** Construct a GUI property with the given name contained by the specified 060 * entity. The container argument must not be null, or a 061 * NullPointerException will be thrown. This attribute will use the 062 * workspace of the container for synchronization and version counts. 063 * If the name argument is null, then the name is set to the empty string. 064 * Increment the version of the workspace. 065 * @param container The container. 066 * @param name The name of this attribute. 067 * @exception IllegalActionException If the attribute is not of an 068 * acceptable class for the container, or if the name contains a period. 069 * @exception NameDuplicationException If the name coincides with 070 * an attribute already in the container. 071 */ 072 public GUIProperty(NamedObj container, String name) 073 throws IllegalActionException, NameDuplicationException { 074 this(container, name, null, null); 075 } 076 077 /** Construct a GUI property with the given name contained by the specified 078 * entity with the given Java Swing component. The container argument must 079 * not be null, or a NullPointerException will be thrown. This attribute 080 * will use the workspace of the container for synchronization and version 081 * counts. If the name argument is null, then the name is set to the empty 082 * string. Increment the version of the workspace. 083 * @param container The container. 084 * @param name The name of this attribute. 085 * @param component The Java Swing component. 086 * @exception IllegalActionException If the attribute is not of an 087 * acceptable class for the container, or if the name contains a period. 088 * @exception NameDuplicationException If the name coincides with 089 * an attribute already in the container. 090 */ 091 public GUIProperty(NamedObj container, String name, JComponent component) 092 throws IllegalActionException, NameDuplicationException { 093 this(container, name, component, null); 094 } 095 096 /** Construct a GUI property with the given name contained by the specified 097 * entity with the given Java Swing component and the given layout 098 * constraint. The container argument must not be null, or a 099 * NullPointerException will be thrown. This attribute 100 * will use the workspace of the container for synchronization and version 101 * counts. If the name argument is null, then the name is set to the empty 102 * string. Increment the version of the workspace. 103 * @param container The container. 104 * @param name The name of this attribute. 105 * @param component The Java Swing component. 106 * @param constraint The layout constraint. 107 * @exception IllegalActionException If the attribute is not of an 108 * acceptable class for the container, or if the name contains a period. 109 * @exception NameDuplicationException If the name coincides with 110 * an attribute already in the container. 111 */ 112 public GUIProperty(NamedObj container, String name, JComponent component, 113 Object constraint) 114 throws IllegalActionException, NameDuplicationException { 115 super(container, name); 116 117 preferredSize = new Parameter(this, "preferredSize"); 118 preferredSize.setTypeEquals(BaseType.INT_MATRIX); 119 preferredSize.setToken("[-1, -1]"); 120 121 _component = component == null ? _createComponent() : component; 122 _constraint = constraint; 123 _add(container); 124 } 125 126 /** Construct a GUI property with the given name contained by the specified 127 * entity with the given layout 128 * constraint. The container argument must not be null, or a 129 * NullPointerException will be thrown. This attribute 130 * will use the workspace of the container for synchronization and version 131 * counts. If the name argument is null, then the name is set to the empty 132 * string. Increment the version of the workspace. 133 * @param container The container. 134 * @param name The name of this attribute. 135 * @param constraint The layout constraint. 136 * @exception IllegalActionException If the attribute is not of an 137 * acceptable class for the container, or if the name contains a period. 138 * @exception NameDuplicationException If the name coincides with 139 * an attribute already in the container. 140 */ 141 public GUIProperty(NamedObj container, String name, Object constraint) 142 throws IllegalActionException, NameDuplicationException { 143 this(container, name, null, constraint); 144 } 145 146 /** React to a change in an attribute. This method is called by 147 * a contained attribute when its value changes. If the changed attribute 148 * is {@link #preferredSize}, then the preferred size of the Swing 149 * component in this GUI property is adjusted accordingly. 150 * @param attribute The attribute that changed. 151 * @exception IllegalActionException If the change is not acceptable 152 * to this container (not thrown in this base class). 153 */ 154 @Override 155 public void attributeChanged(Attribute attribute) 156 throws IllegalActionException { 157 if (attribute == preferredSize) { 158 JComponent component = getComponent(); 159 if (component != null) { 160 IntMatrixToken size = (IntMatrixToken) preferredSize.getToken(); 161 int width = size.getElementAt(0, 0); 162 int height = size.getElementAt(0, 1); 163 if (width >= 0 && height >= 0) { 164 component.setPreferredSize(new Dimension(width, height)); 165 } 166 } 167 } else { 168 super.attributeChanged(attribute); 169 } 170 } 171 172 /** Clone the property into the specified workspace. 173 * @param workspace The workspace in to which the object is cloned. 174 * @return A new property 175 * @exception CloneNotSupportedException If a derived class contains 176 * an attribute that cannot be cloned. 177 */ 178 @Override 179 public Object clone(Workspace workspace) throws CloneNotSupportedException { 180 GUIProperty newObject = (GUIProperty) super.clone(workspace); 181 newObject._component = null; 182 newObject._constraint = null; 183 184 return newObject; 185 } 186 187 /** Return the Swing component. 188 * @return The Swing component. 189 */ 190 public JComponent getComponent() { 191 return _component; 192 } 193 194 /** Specify the container NamedObj, adding this attribute to the 195 * list of attributes in the container. If the container already 196 * contains an attribute with the same name, then throw an exception 197 * and do not make any changes. Similarly, if the container is 198 * not in the same workspace as this attribute, throw an exception. 199 * If this attribute is already contained by the NamedObj, do nothing. 200 * If the attribute already has a container, remove 201 * this attribute from its attribute list first. Otherwise, remove 202 * it from the directory of the workspace, if it is there. 203 * If the argument is null, then remove it from its container. 204 * It is not added to the workspace directory, so this could result in 205 * this object being garbage collected. 206 * Note that since an Attribute is a NamedObj, it can itself have 207 * attributes. However, recursive containment is not allowed, where 208 * an attribute is an attribute of itself, or indirectly of any attribute 209 * it contains. This method is write-synchronized on the 210 * workspace and increments its version number. 211 * <p> 212 * Subclasses may constrain the type of container by overriding 213 * {@link #setContainer(NamedObj)}. 214 * @param container The container to attach this attribute to.. 215 * @exception IllegalActionException If this attribute is not of the 216 * expected class for the container, or it has no name, 217 * or the attribute and container are not in the same workspace, or 218 * the proposed container would result in recursive containment. 219 * @exception NameDuplicationException If the container already has 220 * an attribute with the name of this attribute. 221 * @see #getContainer() 222 */ 223 @Override 224 public void setContainer(NamedObj container) 225 throws IllegalActionException, NameDuplicationException { 226 if (getComponent() == null || _add(container)) { 227 super.setContainer(container); 228 } else { 229 throw new IllegalActionException(getName() 230 + " cannot be contained by " + container.getName()); 231 } 232 } 233 234 /** The preferred size of the Swing component. It would be a matrix of 2 235 * integers, such as [100, 20]. It is ignored if any integer is less than 236 * 0. 237 */ 238 public Parameter preferredSize; 239 240 /** Create a new Java Swing component. 241 * 242 * @return A Swing component that can be enclosed in this GUI property. 243 * @exception IllegalActionException Not thrown in this base class. 244 */ 245 protected abstract JComponent _createComponent() 246 throws IllegalActionException; 247 248 /** Add the Java Swing component to the tableau or GUI property that 249 * contains this GUI property. If this GUI property is already added to one 250 * such container, it will be removed from its old container first. 251 * 252 * @param container The new container. 253 * @return true if the container can be used; false if the adding is not 254 * successful. 255 */ 256 private boolean _add(NamedObj container) { 257 if (container == null) { 258 _remove(); 259 return true; 260 } else { 261 JComponent component = getComponent(); 262 if (component != null) { 263 if (container instanceof Tableau) { 264 _remove(); 265 JFrame frame = ((Tableau) container).getFrame(); 266 frame.getContentPane().add(component, _constraint); 267 return true; 268 } else if (container instanceof GUIProperty) { 269 _remove(); 270 ((GUIProperty) container).getComponent().add(component, 271 _constraint); 272 return true; 273 } 274 } 275 return false; 276 } 277 } 278 279 /** Remove the Java Swing component from the tableau or GUI property that 280 * contains this GUI property. 281 */ 282 private void _remove() { 283 NamedObj container = getContainer(); 284 if (container instanceof Tableau) { 285 JFrame frame = ((Tableau) container).getFrame(); 286 frame.getContentPane().remove(getComponent()); 287 } else if (container instanceof GUIProperty) { 288 JComponent component = ((GUIProperty) container).getComponent(); 289 component.remove(getComponent()); 290 } 291 } 292 293 /** The Java Swing component. 294 */ 295 private JComponent _component; 296 297 /** The layout constraint. 298 */ 299 private Object _constraint; 300}