001/* An attribute with a reference to a filled two-dimensional shape. 002 003 Copyright (c) 2003-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.vergil.kernel.attributes; 029 030import java.awt.Color; 031import java.awt.Shape; 032 033import ptolemy.actor.gui.ColorAttribute; 034import ptolemy.data.BooleanToken; 035import ptolemy.data.DoubleToken; 036import ptolemy.data.expr.Parameter; 037import ptolemy.data.type.BaseType; 038import ptolemy.kernel.util.Attribute; 039import ptolemy.kernel.util.IllegalActionException; 040import ptolemy.kernel.util.NameDuplicationException; 041import ptolemy.kernel.util.NamedObj; 042import ptolemy.kernel.util.Workspace; 043import ptolemy.vergil.icon.ResizableAttributeControllerFactory; 044 045/////////////////////////////////////////////////////////////////// 046//// FilledShapeAttribute 047 048/** 049 This is an abstract attribute that is rendered as a filled shape. 050 Concrete subclasses produce particular shapes, such as rectangles 051 and circles. Derived classes need to react to changes in the 052 <i>width</i> and <i>height</i> parameters in the attributeChanged() 053 method by calling setShape() on the protected member _icon. 054 <p> 055 @author Edward A. Lee 056 @version $Id$ 057 @since Ptolemy II 4.0 058 @Pt.ProposedRating Yellow (eal) 059 @Pt.AcceptedRating Red (cxh) 060 */ 061public abstract class FilledShapeAttribute extends ShapeAttribute { 062 /** Construct an attribute with the given name contained by the 063 * specified container. The container argument must not be null, or a 064 * NullPointerException will be thrown. This attribute will use the 065 * workspace of the container for synchronization and version counts. 066 * If the name argument is null, then the name is set to the empty 067 * string. Increment the version of the workspace. 068 * @param container The container. 069 * @param name The name of this attribute. 070 * @exception IllegalActionException If the attribute is not of an 071 * acceptable class for the container, or if the name contains a period. 072 * @exception NameDuplicationException If the name coincides with 073 * an attribute already in the container. 074 */ 075 public FilledShapeAttribute(NamedObj container, String name) 076 throws IllegalActionException, NameDuplicationException { 077 super(container, name); 078 079 width = new Parameter(this, "width"); 080 width.setTypeEquals(BaseType.DOUBLE); 081 width.setExpression("100.0"); 082 083 height = new Parameter(this, "height"); 084 height.setTypeEquals(BaseType.DOUBLE); 085 height.setExpression("100.0"); 086 087 centered = new Parameter(this, "centered"); 088 centered.setTypeEquals(BaseType.BOOLEAN); 089 centered.setExpression("false"); 090 091 fillColor = new ColorAttribute(this, "fillColor"); 092 fillColor.setExpression("none"); 093 094 // Create a custom controller. 095 new ResizableAttributeControllerFactory(this, "_controllerFactory"); 096 } 097 098 /////////////////////////////////////////////////////////////////// 099 //// parameters //// 100 101 /** Indicator of whether the shape should be centered on the location. 102 * This is a boolean that defaults to false, which means that the 103 * location is the upper left corner. 104 */ 105 public Parameter centered; 106 107 /** The line color. This is a string representing an array with 108 * four elements, red, green, blue, and alpha, where alpha is 109 * transparency. The default is "{0.0, 0.0, 0.0, 1.0}", which 110 * represents an opaque black. 111 */ 112 public ColorAttribute fillColor; 113 114 /** The vertical extent. 115 * This is a double that defaults to 100.0. 116 */ 117 public Parameter height; 118 119 /** The horizontal extent. 120 * This is a double that defaults to 100.0. 121 */ 122 public Parameter width; 123 124 /////////////////////////////////////////////////////////////////// 125 //// public methods //// 126 127 /** React to a changes in the attributes by changing 128 * the icon. 129 * @param attribute The attribute that changed. 130 * @exception IllegalActionException If the change is not acceptable 131 * to this container (should not be thrown). 132 */ 133 @Override 134 public void attributeChanged(Attribute attribute) 135 throws IllegalActionException { 136 if ((attribute == width || attribute == height) 137 && !_inAttributeChanged) { 138 try { 139 // Prevent redundant actions here... When we evaluate the 140 // _other_ attribute here (whichever one did _not_ trigger 141 // this call, it will likely trigger another call to 142 // attributeChanged(), which will result in this action 143 // being performed twice. 144 _inAttributeChanged = true; 145 146 double widthValue = ((DoubleToken) width.getToken()) 147 .doubleValue(); 148 double heightValue = ((DoubleToken) height.getToken()) 149 .doubleValue(); 150 151 if (widthValue != _widthValue || heightValue != _heightValue) { 152 _widthValue = widthValue; 153 _heightValue = heightValue; 154 _icon.setShape(_newShape()); 155 } 156 } finally { 157 _inAttributeChanged = false; 158 } 159 } else if (attribute == centered) { 160 boolean centeredValue = ((BooleanToken) centered.getToken()) 161 .booleanValue(); 162 163 if (centeredValue != _centeredValue) { 164 _centeredValue = centeredValue; 165 _icon.setCentered(_centeredValue); 166 } 167 } else if (attribute == fillColor) { 168 Color fillColorValue = fillColor.asColor(); 169 170 if (fillColorValue.getAlpha() == 0f) { 171 _icon.setFillColor(null); 172 } else { 173 _icon.setFillColor(fillColorValue); 174 } 175 } else { 176 super.attributeChanged(attribute); 177 } 178 } 179 180 /** Clone the object into the specified workspace. The new object is 181 * <i>not</i> added to the directory of that workspace (you must do this 182 * yourself if you want it there). 183 * The result is an object with no container. 184 * @param workspace The workspace for the cloned object. 185 * @exception CloneNotSupportedException Not thrown in this base class 186 * @return The new Attribute. 187 */ 188 @Override 189 public Object clone(Workspace workspace) throws CloneNotSupportedException { 190 FilledShapeAttribute newObject = (FilledShapeAttribute) super.clone( 191 workspace); 192 newObject._inAttributeChanged = false; 193 194 newObject._icon.setCentered(newObject._centeredValue); 195 196 return newObject; 197 } 198 199 /////////////////////////////////////////////////////////////////// 200 //// protected methods //// 201 202 /** Return the a new shape given a new width and height. This class 203 * guarantees that the protected variables _centeredValue, _widthValue, 204 * and _heightValue are up to date when this method is called. 205 * Derived classes should override this to return an appropriate shape. 206 * @return A new shape. 207 */ 208 protected abstract Shape _newShape(); 209 210 /////////////////////////////////////////////////////////////////// 211 //// protected variables //// 212 213 /** Most recently set value of the centered parameter. */ 214 protected boolean _centeredValue = false; 215 216 /** Most recently set value of the height parameter. */ 217 protected double _heightValue; 218 219 /** Variable used to prevent re-entry into attributeChanged(). */ 220 protected transient boolean _inAttributeChanged = false; 221 222 /** Most recently set value of the width parameter. */ 223 protected double _widthValue; 224}