001/* An icon that renders the value of an attribute of the container. 002 003 Copyright (c) 1999-2016 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.icon; 029 030import java.awt.Color; 031import java.awt.geom.Rectangle2D; 032import java.util.Iterator; 033 034import javax.swing.SwingConstants; 035import javax.swing.SwingUtilities; 036 037import diva.canvas.Figure; 038import diva.canvas.toolbox.BasicRectangle; 039import diva.canvas.toolbox.LabelFigure; 040import ptolemy.data.IntToken; 041import ptolemy.kernel.util.Attribute; 042import ptolemy.kernel.util.IllegalActionException; 043import ptolemy.kernel.util.InternalErrorException; 044import ptolemy.kernel.util.NameDuplicationException; 045import ptolemy.kernel.util.NamedObj; 046import ptolemy.kernel.util.Settable; 047import ptolemy.kernel.util.Workspace; 048 049/////////////////////////////////////////////////////////////////// 050//// UpdatedValueIcon 051 052/** 053 An icon that displays the value of an attribute of the container, 054 updating it as the value of the value of the attribute is updated. 055 The attribute is assumed to be an instance of Settable, and its name 056 is given by the parameter <i>attributeName</i>. The width of the 057 display is fixed, and is given by the attribute <i>displayWidth</i>, 058 which is in "n" characters. 059 060 @author Edward A. Lee 061 @version $Id$ 062 @since Ptolemy II 2.0 063 @Pt.ProposedRating Yellow (eal) 064 @Pt.AcceptedRating Red (johnr) 065 */ 066public class UpdatedValueIcon extends AttributeValueIcon { 067 /** Create a new icon with the given name in the given container. 068 * The container is required to implement Settable, or an exception 069 * will be thrown. 070 * @param container The container for this attribute. 071 * @param name The name of this attribute. 072 * @exception IllegalActionException If thrown by the parent 073 * class or while setting an attribute. 074 * @exception NameDuplicationException If the name coincides with 075 * an attribute already in the container. 076 */ 077 public UpdatedValueIcon(NamedObj container, String name) 078 throws NameDuplicationException, IllegalActionException { 079 super(container, name); 080 } 081 082 /////////////////////////////////////////////////////////////////// 083 //// public methods //// 084 085 /** Override the base class to identify the named attribute in the 086 * container and to attach a listener to it. 087 * @param attribute The attribute that changed. 088 * @exception IllegalActionException Not thrown in this class. 089 */ 090 @Override 091 public void attributeChanged(Attribute attribute) 092 throws IllegalActionException { 093 if (attribute == attributeName) { 094 // If we were previously associated with an attribute, 095 // remove the listener. 096 if (_associatedAttribute != null) { 097 _associatedAttribute.removeValueListener(this); 098 _associatedAttribute = null; 099 } 100 101 NamedObj container = getContainer(); 102 103 if (container != null) { 104 Attribute candidateAttribute = container 105 .getAttribute(attributeName.getExpression()); 106 107 if (candidateAttribute instanceof Settable) { 108 _associatedAttribute = (Settable) candidateAttribute; 109 _associatedAttribute.addValueListener(this); 110 } 111 } 112 113 _updateFigures(); 114 } else { 115 super.attributeChanged(attribute); 116 } 117 } 118 119 /** Clone the object into the specified workspace. The new object is 120 * <i>not</i> added to the directory of that workspace (you must do this 121 * yourself if you want it there). 122 * The result is an object with no container. 123 * @param workspace The workspace for the cloned object. 124 * @exception CloneNotSupportedException Not thrown in this base class 125 * @return The new Attribute. 126 */ 127 @Override 128 public Object clone(Workspace workspace) throws CloneNotSupportedException { 129 UpdatedValueIcon newObject = (UpdatedValueIcon) super.clone(workspace); 130 newObject._associatedAttribute = null; 131 132 // Find the new associated attribute for the clone. 133 try { 134 newObject.attributeChanged(newObject.attributeName); 135 } catch (IllegalActionException e) { 136 throw new InternalErrorException(e); 137 } 138 139 return newObject; 140 } 141 142 /** Create a new background figure. This overrides the base class 143 * to draw a fixed-width box. 144 * @return A new figure. 145 */ 146 @Override 147 public Figure createBackgroundFigure() { 148 // Measure width of a character. Unfortunately, this 149 // requires generating a label figure that we will not use. 150 // Note that pessimistic choice of character would be "m", 151 // but this results in way too much padding normally. 152 // Thus, we use "n" and correct if necessary. 153 LabelFigure label = new LabelFigure("N", _labelFont, 1.0, 154 SwingConstants.CENTER); 155 Rectangle2D stringBounds = label.getBounds(); 156 157 try { 158 int numberOfCharacters = ((IntToken) displayWidth.getToken()) 159 .intValue(); 160 161 // NOTE: Padding of 10. 162 int width = (int) (stringBounds.getWidth() * numberOfCharacters 163 + 10); 164 165 _displayString(); 166 label = new LabelFigure("N", _labelFont, 1.0, 167 SwingConstants.CENTER); 168 stringBounds = label.getBounds(); 169 if (width < stringBounds.getWidth()) { 170 width = (int) stringBounds.getWidth() + 10; 171 } 172 173 return new BasicRectangle(0, 0, width, 30, Color.white, 1); 174 } catch (IllegalActionException ex) { 175 // Should not be thrown. 176 throw new InternalErrorException(ex); 177 } 178 } 179 180 /** React to the specified Settable changing by requesting a 181 * repaint of the most recently constructed figures. 182 * @param settable The object that has changed value. 183 */ 184 @Override 185 public void valueChanged(Settable settable) { 186 if (settable == _associatedAttribute) { 187 _updateFigures(); 188 } else { 189 super.valueChanged(settable); 190 } 191 } 192 193 /////////////////////////////////////////////////////////////////// 194 //// protected methods //// 195 196 /** Update the figures that were created by this icon to reflect the 197 * new attribute value. This method is called by this class in response 198 * to notification that attributes have changed. 199 */ 200 protected void _updateFigures() { 201 // Invoke in the swing thread. 202 // NOTE: These requests could be consolidated, so that 203 // if there is a string of them pending, only one gets 204 // executed. However, this results in jerky updates, with 205 // some values being skipped, so it seems like it's not 206 // a good idea. 207 SwingUtilities.invokeLater(new Runnable() { 208 @Override 209 public void run() { 210 String string = _displayString(); 211 synchronized (_figures) { 212 Iterator figures = _liveFigureIterator(); 213 214 while (figures.hasNext()) { 215 LabelFigure figure = (LabelFigure) figures.next(); 216 figure.setString(string); 217 } 218 } 219 } 220 }); 221 } 222 223 /////////////////////////////////////////////////////////////////// 224 //// protected members //// 225 226 /** The attribute whose value is being represented. */ 227 protected Settable _associatedAttribute; 228}