001/* Monitor input values. 002 003 Copyright (c) 1998-2015 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.lib.gui; 029 030import java.util.HashSet; 031import java.util.Set; 032 033import ptolemy.actor.injection.ActorModuleInitializer; 034import ptolemy.actor.injection.PortableContainer; 035import ptolemy.actor.injection.PortablePlaceable; 036import ptolemy.actor.injection.PtolemyInjector; 037import ptolemy.actor.lib.Sink; 038import ptolemy.data.Token; 039import ptolemy.data.expr.Parameter; 040import ptolemy.data.type.BaseType; 041import ptolemy.data.type.TypeConstant; 042import ptolemy.graph.Inequality; 043import ptolemy.kernel.CompositeEntity; 044import ptolemy.kernel.util.IllegalActionException; 045import ptolemy.kernel.util.InternalErrorException; 046import ptolemy.kernel.util.NameDuplicationException; 047 048/////////////////////////////////////////////////////////////////// 049//// MonitorValue 050 051/** 052 Monitor inputs by setting the <i>value</i> parameter equal 053 to each arriving token. This actor can be used with 054 an icon that displays the value of a parameter to get 055 on-screen display of values in a diagram. The value is 056 updated only in postfire. 057 058 <p>Note that the icon for this actor is defined in 059 <code>ptolemy/actor/lib/genericsinks.xml</code>, which looks something 060 like 061 <pre> 062<entity name="MonitorValue" class="ptolemy.actor.lib.MonitorValue"> 063<doc>Monitor and display values</doc> 064 <property name="displayWidth" class="ptolemy.data.expr.Parameter" value="20"/> 065 <property name="_icon" class="ptolemy.vergil.icon.UpdatedValueIcon"> 066 <property name="attributeName" value="value"/> 067 <property name="displayWidth" value="displayWidth"/> 068 </property> 069</entity> 070 </pre> 071 072 @author Edward A. Lee 073 @version $Id$ 074 @since Ptolemy II 10.0 075 @Pt.ProposedRating Yellow (eal) 076 @Pt.AcceptedRating Red (bilung) 077 */ 078public class MonitorValue extends Sink implements PortablePlaceable { 079 /** Construct an actor. 080 * @param container The container. 081 * @param name The name of this actor. 082 * @exception IllegalActionException If the entity cannot be contained 083 * by the proposed container. 084 * @exception NameDuplicationException If the container already has an 085 * actor with this name. 086 */ 087 public MonitorValue(CompositeEntity container, String name) 088 throws NameDuplicationException, IllegalActionException { 089 super(container, name); 090 091 initial = new Parameter(this, "initial"); 092 093 value = new Parameter(this, "value"); 094 095 // The value parameter should not be persistent so that when 096 // we save and load 097 // doc/books/systems/types/test/auto/ObjectType.xml we avoid 098 // an error because ObjectTokens are not parseable. 099 value.setPersistent(false); 100 } 101 102 /////////////////////////////////////////////////////////////////// 103 //// ports and parameters //// 104 105 /** The most recently seen input value. This parameter has the same 106 * type as the input. 107 */ 108 public Parameter value; 109 110 /** The initial value to be displayed. 111 */ 112 public Parameter initial; 113 114 /////////////////////////////////////////////////////////////////// 115 //// public methods //// 116 117 /** Initialize the actor by clearing the display. */ 118 @Override 119 public void initialize() throws IllegalActionException { 120 super.initialize(); 121 value.setExpression(initial.getExpression()); 122 value.validate(); 123 } 124 125 /** Place the visual representation of the actor into the specified container. 126 * @param container The container in which to place the object, or 127 * null to specify that there is no current container. 128 */ 129 @Override 130 public void place(PortableContainer container) { 131 _getImplementation().place(container); 132 } 133 134 /** Read at most one token from the input and record its value. 135 * @exception IllegalActionException If there is no director. 136 * @return True. 137 */ 138 @Override 139 public boolean postfire() throws IllegalActionException { 140 if (input.hasToken(0)) { 141 Token oldToken = value.getToken(); 142 Token newToken = _getInputToken(0); 143 if (oldToken == null || !oldToken.equals(newToken)) { 144 value.setToken(newToken); 145 value.validate(); 146 _getImplementation().setValue(newToken); 147 } 148 } 149 150 return super.postfire(); 151 } 152 153 /////////////////////////////////////////////////////////////////// 154 //// protected methods //// 155 156 /** Set the input port greater than or equal to 157 * <code>BaseType.GENERAL</code> in case backward type inference is 158 * enabled and the input port has no type declared. 159 * 160 * @return A set of inequalities. 161 */ 162 @Override 163 protected Set<Inequality> _customTypeConstraints() { 164 HashSet<Inequality> result = new HashSet<Inequality>(); 165 if (isBackwardTypeInferenceEnabled() 166 && input.getTypeTerm().isSettable()) { 167 result.add(new Inequality(new TypeConstant(BaseType.GENERAL), 168 input.getTypeTerm())); 169 } 170 return result; 171 } 172 173 /** Return a token from the named input channel. 174 * This is a protected method to allow subclasses to override 175 * how inputs are observed. 176 * @param i The channel 177 * @return A token from the input channel or null if there is 178 * nothing to display. 179 * @exception IllegalActionException If reading the input fails. 180 */ 181 protected Token _getInputToken(int i) throws IllegalActionException { 182 if (input.hasToken(i)) { 183 Token token = input.get(i); 184 return token; 185 } 186 return null; 187 } 188 189 /////////////////////////////////////////////////////////////////// 190 //// private methods //// 191 192 /** Get the right instance of the implementation depending upon the 193 * of the dependency specified through dependency injection. 194 * If the instance has not been created, then it is created. 195 * If the instance already exists then return the same. 196 * 197 * <p>This code is used as part of the dependency injection needed for the 198 * HandSimDroid project, see $PTII/ptserver. This code uses dependency 199 * inject to determine what implementation to use at runtime. 200 * This method eventually reads ptolemy/actor/ActorModule.properties. 201 * {@link ptolemy.actor.injection.ActorModuleInitializer#initializeInjector()} 202 * should be called before this method is called. If it is not 203 * called, then a message is printed and initializeInjector() is called.</p> 204 * @return the implementation. 205 */ 206 private TextFieldContainerInterface _getImplementation() { 207 if (_implementation == null) { 208 if (PtolemyInjector.getInjector() == null) { 209 System.err.println("Warning: main() did not call " 210 + "ActorModuleInitializer.initializeInjector(), " 211 + "so Monitor is calling it for you."); 212 ActorModuleInitializer.initializeInjector(); 213 } 214 _implementation = PtolemyInjector.getInjector() 215 .getInstance(TextFieldContainerInterface.class); 216 } 217 218 try { 219 _implementation.init(this); 220 } catch (NameDuplicationException e) { 221 throw new InternalErrorException(this, e, 222 "Failed to initialize implementation"); 223 } catch (IllegalActionException e) { 224 throw new InternalErrorException(this, e, 225 "Failed to initialize implementation"); 226 } 227 228 return _implementation; 229 } 230 231 /////////////////////////////////////////////////////////////////// 232 //// private variables //// 233 234 /** Implementation of the MonitorValueInterface. */ 235 private TextFieldContainerInterface _implementation; 236}