001/* This parameter, when inserted into a model, causes the ports in the model to display their unconsumed inputs. 002 003 @Copyright (c) 2007-2014 The Regents of the University of California. 004 All rights reserved. 005 006 Permission is hereby granted, without written agreement and without 007 license or royalty fees, to use, copy, modify, and distribute this 008 software and its documentation for any purpose, provided that the 009 above copyright notice and the following two paragraphs appear in all 010 copies of this software. 011 012 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016 SUCH DAMAGE. 017 018 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023 ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION 2 026 COPYRIGHTENDKEY 027 */ 028package ptolemy.vergil.actor.lib; 029 030import java.util.List; 031 032import ptolemy.actor.Actor; 033import ptolemy.actor.CompositeActor; 034import ptolemy.actor.Executable; 035import ptolemy.actor.IOPort; 036import ptolemy.actor.Initializable; 037import ptolemy.data.BooleanToken; 038import ptolemy.data.expr.SingletonParameter; 039import ptolemy.kernel.util.ChangeRequest; 040import ptolemy.kernel.util.IllegalActionException; 041import ptolemy.kernel.util.InternalErrorException; 042import ptolemy.kernel.util.NameDuplicationException; 043import ptolemy.kernel.util.NamedObj; 044import ptolemy.kernel.util.Settable; 045import ptolemy.kernel.util.SingletonAttribute; 046 047/////////////////////////////////////////////////////////////////// 048//// MonitorReceiverContents 049 050/** 051 This parameter, when inserted into a model or an opaque composite actor, 052 causes all input ports to acquire an attribute that makes them display 053 their contents on the screen. This works by piggybacking on the 054 initialize() method of the container to insert the relevant parameters 055 into the ports. It also piggybacks on postfire() and wrapup() to issue 056 a ChangeRequest, which causes a repaint of the screen in Vergil. 057 To stop monitoring the queue contents, simply delete 058 this attribute from the model. 059 To use this one option is to instantiate an attribute of type 060 ptolemy.vergil.actor.lib.MonitorReceiverContents 061 062 @author Edward A. Lee, Contributor: Bert Rodiers 063 @version $Id$ 064 @since Ptolemy II 8.0 065 @Pt.ProposedRating Yellow (eal) 066 @Pt.AcceptedRating Red (cxh) 067 */ 068public class MonitorReceiverContents extends SingletonAttribute { 069 070 /** Construct an actor with the specified container and name. 071 * @param container The container. 072 * @param name The name of this actor. 073 * @exception IllegalActionException If the entity cannot be contained 074 * by the proposed container. 075 * @exception NameDuplicationException If the container already has an 076 * actor with this name. 077 */ 078 public MonitorReceiverContents(NamedObj container, String name) 079 throws IllegalActionException, NameDuplicationException { 080 super(container, name); 081 082 // The icon. 083 _attachText("_iconDescription", "<svg>\n" + "<rect x=\"-60\" y=\"-10\" " 084 + "width=\"180\" height=\"20\" " + "style=\"fill:#00FFFF\"/>\n" 085 + "<text x=\"-55\" y=\"5\" " 086 + "style=\"font-size:14; font-family:SansSerif; fill:blue\">\n" 087 + "MonitorReceiverContents\n" + "</text>\n" + "</svg>\n"); 088 089 // Hide the name. 090 SingletonParameter hideName = new SingletonParameter(this, "_hideName"); 091 hideName.setToken(BooleanToken.TRUE); 092 hideName.setVisibility(Settable.EXPERT); 093 } 094 095 /////////////////////////////////////////////////////////////////// 096 //// public methods //// 097 098 /** Specify the container. If the container is not the same as the 099 * previous container, then stop monitoring queue contents in the 100 * previous container, and start monitoring them in the new one. 101 * @param container The container to attach this attribute to.. 102 * @exception IllegalActionException If this attribute is not of the 103 * expected class for the container, or it has no name, 104 * or the attribute and container are not in the same workspace, or 105 * the proposed container would result in recursive containment. 106 * @exception NameDuplicationException If the container already has 107 * an attribute with the name of this attribute. 108 * @see #getContainer() 109 */ 110 @Override 111 public void setContainer(final NamedObj container) 112 throws IllegalActionException, NameDuplicationException { 113 NamedObj previousContainer = getContainer(); 114 if (previousContainer == container) { 115 return; 116 } 117 if (previousContainer != null 118 && previousContainer instanceof CompositeActor) { 119 // _piggybackContainer should be non-null, but we check anyway. 120 if (_piggybackContainer != null) { 121 _piggybackContainer.removePiggyback(_executable); 122 } 123 _executable = null; 124 // Also, remove all _showInfo attributes in the ports of the previous container. 125 List<Actor> entities = ((CompositeActor) previousContainer) 126 .deepEntityList(); 127 for (Actor entity : entities) { 128 List<IOPort> ports = entity.inputPortList(); 129 for (IOPort port : ports) { 130 List<MonitorReceiverAttribute> attributes = port 131 .attributeList(MonitorReceiverAttribute.class); 132 for (MonitorReceiverAttribute attribute : attributes) { 133 attribute.setContainer(null); 134 } 135 } 136 } 137 } 138 super.setContainer(container); 139 140 if (container != null && container instanceof CompositeActor) { 141 if (_executable == null) { 142 // The inner class will be piggybacked as an executable for the container to 143 // execute change request at the appropriate times. These change request will 144 // lead to repaints of the GUI. 145 _executable = new Executable() { 146 147 @Override 148 public void initialize() throws IllegalActionException { 149 // Add _showInfo attributes to any input port that does not already have one. 150 try { 151 workspace().getWriteAccess(); 152 List<Actor> entities = ((CompositeActor) container) 153 .deepEntityList(); 154 for (Actor entity : entities) { 155 List<IOPort> ports = entity.inputPortList(); 156 for (IOPort port : ports) { 157 if (port.getAttribute( 158 "_showInfo") == null) { 159 MonitorReceiverAttribute attribute = new MonitorReceiverAttribute( 160 port, "_showInfo"); 161 attribute.setPersistent(false); 162 } 163 } 164 } 165 } catch (NameDuplicationException ex) { 166 throw new InternalErrorException(ex); 167 } finally { 168 workspace().doneTemporaryWriting(); 169 } 170 } 171 172 // Request repaint on postfire() and wrapup(). 173 @Override 174 public boolean postfire() { 175 ChangeRequest request = new ChangeRequest(this, 176 "SetVariable change request", 177 true /*Although this not a structural change in my point of view 178 , we however for some reason need to specify it is, otherwise the GUI won't update.*/ 179 ) { 180 @Override 181 protected void _execute() 182 throws IllegalActionException { 183 } 184 }; 185 // To prevent prompting for saving the model, mark this 186 // change as non-persistent. 187 request.setPersistent(false); 188 requestChange(request); 189 return true; 190 } 191 192 @Override 193 public void wrapup() { 194 ChangeRequest request = new ChangeRequest(this, 195 "SetVariable change request", true) { 196 @Override 197 protected void _execute() 198 throws IllegalActionException { 199 } 200 }; 201 // To prevent prompting for saving the model, mark this 202 // change as non-persistent. 203 request.setPersistent(false); 204 requestChange(request); 205 } 206 207 // All other methods are empty. 208 @Override 209 public void fire() throws IllegalActionException { 210 } 211 212 @Override 213 public boolean isFireFunctional() { 214 return true; 215 } 216 217 @Override 218 public boolean isStrict() { 219 return true; 220 } 221 222 @Override 223 public int iterate(int count) { 224 return Executable.COMPLETED; 225 } 226 227 @Override 228 public boolean prefire() throws IllegalActionException { 229 return true; 230 } 231 232 @Override 233 public void stop() { 234 } 235 236 @Override 237 public void stopFire() { 238 } 239 240 @Override 241 public void terminate() { 242 } 243 244 @Override 245 public void addInitializable(Initializable initializable) { 246 } 247 248 @Override 249 public void preinitialize() throws IllegalActionException { 250 } 251 252 @Override 253 public void removeInitializable( 254 Initializable initializable) { 255 } 256 }; 257 } 258 259 _piggybackContainer = (CompositeActor) container; 260 _piggybackContainer.addPiggyback(_executable); 261 } 262 } 263 264 /////////////////////////////////////////////////////////////////// 265 //// private variables //// 266 267 /** The executable that creates the monitor attributes in initialize(). */ 268 private Executable _executable; 269 270 /** The last container on which we piggybacked. */ 271 private CompositeActor _piggybackContainer; 272}