001/** A controller to do scheduled repaints at certain user specified moments. */ 002 003/* 004 Copyright (c) 2008-2014 The Regents of the University of California. 005 All rights reserved. 006 007 Permission is hereby granted, without written agreement and without 008 license or royalty fees, to use, copy, modify, and distribute this 009 software and its documentation for any purpose, provided that the above 010 copyright notice and the following two paragraphs appear in all copies 011 of this software. 012 013 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 014 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 015 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 016 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 017 SUCH DAMAGE. 018 019 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 020 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 022 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 023 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 024 ENHANCEMENTS, OR MODIFICATIONS. 025 */ 026 027package ptolemy.actor.gui; 028 029import ptolemy.actor.CompositeActor; 030import ptolemy.actor.Executable; 031import ptolemy.actor.Initializable; 032import ptolemy.data.BooleanToken; 033import ptolemy.data.expr.Parameter; 034import ptolemy.data.expr.SingletonParameter; 035import ptolemy.data.type.BaseType; 036import ptolemy.kernel.util.Attribute; 037import ptolemy.kernel.util.ChangeRequest; 038import ptolemy.kernel.util.IllegalActionException; 039import ptolemy.kernel.util.NameDuplicationException; 040import ptolemy.kernel.util.NamedObj; 041import ptolemy.kernel.util.Settable; 042import ptolemy.kernel.util.Workspace; 043 044/////////////////////////////////////////////////////////////////// 045//// ModelRepaintController 046 047/** 048 * A class to do scheduled repaints at certain user specified moments in 049 * the execution of the model. This component piggy-backs with the execution 050 * of its container, and allows you to define that repaints need to happen when 051 * certain functions of its container are executed. Currently only repaints at 052 * wrapup or post-fire can be scheduled. 053 * 054 * @author Bert Rodiers 055 * @version $Id$ 056 * @since Ptolemy II 8.0 057 * @Pt.ProposedRating Red (rodiers) 058 * @Pt.AcceptedRating Red (rodiers) 059 */ 060public class ModelRepaintController extends Attribute { 061 /** Construct an instance of the ModelRepaintController. 062 * @param container The container. 063 * @param name The name. 064 * @exception IllegalActionException If the attribute is not of an 065 * acceptable class for the container, or if the name contains a period. 066 * @exception NameDuplicationException If the name coincides with 067 * an attribute already in the container. 068 */ 069 public ModelRepaintController(NamedObj container, String name) 070 throws IllegalActionException, NameDuplicationException { 071 072 super(container, name); 073 074 _repaintOnWrapUp = new Parameter(this, "repaintOnWrapUp"); 075 _repaintOnWrapUp.setTypeEquals(BaseType.BOOLEAN); 076 _repaintOnWrapUp.setExpression("true"); 077 078 _repaintOnPostFire = new Parameter(this, "repaintOnPostFire"); 079 _repaintOnPostFire.setTypeEquals(BaseType.BOOLEAN); 080 _repaintOnPostFire.setExpression("false"); 081 082 // The icon. 083 _attachText("_iconDescription", "<svg>\n" + "<rect x=\"-60\" y=\"-10\" " 084 + "width=\"135\" height=\"20\" " + "style=\"fill:#00FFFF\"/>\n" 085 + "<text x=\"-55\" y=\"5\" " 086 + "style=\"font-size:14; font-family:SansSerif; fill:blue\">\n" 087 + "RepaintController\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 /** Clone the controller into the specified workspace. This calls the 099 * base class and then sets the attribute public members to refer 100 * to the attributes of the new controller 101 * @param workspace The workspace for the new controller 102 * @return A new controller 103 * @exception CloneNotSupportedException If a derived class contains 104 * an attribute that cannot be cloned. 105 */ 106 @Override 107 public Object clone(Workspace workspace) throws CloneNotSupportedException { 108 ModelRepaintController newObject = (ModelRepaintController) super.clone( 109 workspace); 110 newObject._executable = null; 111 newObject._repaintOnPostFire = (Parameter) newObject 112 .getAttribute("repaintOnPostFire"); 113 newObject._repaintOnWrapUp = (Parameter) newObject 114 .getAttribute("repaintOnWrapUp"); 115 return newObject; 116 } 117 118 /** Specify the container NamedObj, adding this attribute to the 119 * list of attributes in the container. If the container already 120 * contains an attribute with the same name, then throw an exception 121 * and do not make any changes. Similarly, if the container is 122 * not in the same workspace as this attribute, throw an exception. 123 * If this attribute is already contained by the NamedObj, do nothing. 124 * If the attribute already has a container, remove 125 * this attribute from its attribute list first. Otherwise, remove 126 * it from the directory of the workspace, if it is there. 127 * If the argument is null, then remove it from its container. 128 * It is not added to the workspace directory, so this could result in 129 * this object being garbage collected. 130 * Note that since an Attribute is a NamedObj, it can itself have 131 * attributes. However, recursive containment is not allowed, where 132 * an attribute is an attribute of itself, or indirectly of any attribute 133 * it contains. This method is write-synchronized on the 134 * workspace and increments its version number. 135 * 136 * @param container The container to attach this attribute to.. 137 * @exception IllegalActionException If this attribute is not of the 138 * expected class for the container, or it has no name, 139 * or the attribute and container are not in the same workspace, or 140 * the proposed container would result in recursive containment. 141 * @exception NameDuplicationException If the container already has 142 * an attribute with the name of this attribute. 143 * @see #getContainer() 144 */ 145 @Override 146 public void setContainer(NamedObj container) 147 throws IllegalActionException, NameDuplicationException { 148 if (_executable == null) { 149 // The inner class will be piggybacked as an executable for the container to 150 // execute change request at the appropriate times. These change request will 151 // lead to repaints of the GUI. 152 _executable = new Executable() { 153 @Override 154 public void fire() throws IllegalActionException { 155 } 156 157 @Override 158 public boolean isFireFunctional() { 159 return true; 160 } 161 162 @Override 163 public boolean isStrict() throws IllegalActionException { 164 return true; 165 } 166 167 @Override 168 public int iterate(int count) throws IllegalActionException { 169 return Executable.COMPLETED; 170 } 171 172 @Override 173 public boolean postfire() throws IllegalActionException { 174 _scheduleRepaint(_repaintOnPostFire); 175 return true; 176 } 177 178 @Override 179 public boolean prefire() throws IllegalActionException { 180 return true; 181 } 182 183 @Override 184 public void stop() { 185 } 186 187 @Override 188 public void stopFire() { 189 } 190 191 @Override 192 public void terminate() { 193 } 194 195 @Override 196 public void addInitializable(Initializable initializable) { 197 } 198 199 @Override 200 public void initialize() throws IllegalActionException { 201 } 202 203 @Override 204 public void preinitialize() throws IllegalActionException { 205 } 206 207 @Override 208 public void removeInitializable(Initializable initializable) { 209 } 210 211 @Override 212 public void wrapup() throws IllegalActionException { 213 _scheduleRepaint(_repaintOnWrapUp); 214 } 215 }; 216 } 217 218 // Don't piggy back on previous container anymore. 219 NamedObj previousContainer = getContainer(); 220 if (previousContainer instanceof CompositeActor) { 221 ((CompositeActor) previousContainer).removePiggyback(_executable); 222 } 223 super.setContainer(container); 224 225 if (container instanceof CompositeActor) { 226 ((CompositeActor) container).addPiggyback(_executable); 227 } 228 } 229 230 /////////////////////////////////////////////////////////////////// 231 //// private methods //// 232 233 /** Schedule a repaint in case the value parameter equals True. 234 * This is done by requesting a ChangeRequest. 235 * @param parameter The parameter. 236 */ 237 private void _scheduleRepaint(Parameter parameter) { 238 if (parameter.getExpression().equals("true")) { 239 // The ChangeRequest has false as third argument to avoid complete 240 // repaints of the model. 241 ChangeRequest request = new ChangeRequest(this, 242 "SetVariable change request", true) { 243 @Override 244 protected void _execute() throws IllegalActionException { 245 } 246 }; 247 248 // To prevent prompting for saving the model, mark this 249 // change as non-persistent. 250 request.setPersistent(false); 251 requestChange(request); 252 } 253 } 254 255 /////////////////////////////////////////////////////////////////// 256 //// private parameters //// 257 258 // An inner class that will be notified on certain events. 259 // The inner class will be piggybacked as an executable for the container to 260 // execute change request at the appropriate times. These change request will 261 // lead to repaints of the GUI. 262 private Executable _executable; 263 264 // A flag that specifies whether a repaint should happen on wrapup. 265 private Parameter _repaintOnWrapUp; 266 267 // A flag that specifies whether a repaint should happen on post-fire. 268 private Parameter _repaintOnPostFire; 269}