001/* A Ptolemy application that instantiates class names given on the command 002 line. 003 004 Copyright (c) 1999-2014 The Regents of the University of California. 005 All rights reserved. 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 above 009 copyright notice and the following two paragraphs appear in all copies 010 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 028 */ 029package ptolemy.actor.gui; 030 031import java.awt.Color; 032import java.awt.event.WindowAdapter; 033import java.awt.event.WindowEvent; 034import java.util.Iterator; 035import java.util.LinkedList; 036import java.util.List; 037 038import ptolemy.actor.CompositeActor; 039import ptolemy.actor.Manager; 040import ptolemy.actor.injection.PortablePlaceable; 041import ptolemy.kernel.util.IllegalActionException; 042import ptolemy.util.StringUtilities; 043 044/////////////////////////////////////////////////////////////////// 045//// CompositeActorApplication 046 047/** 048 This application creates one or more Ptolemy II models given a 049 classname on the command line, and then executes those models, each in 050 its own thread. Each specified class should be derived from 051 CompositeActor, and should have a constructor that takes a single 052 argument, an instance of Workspace. If the model does not contain 053 a manager, then one will be created for it. The model is displayed using 054 an instance of ModelFrame, which provides controls for executing 055 the model and setting its top-level and director parameters. 056 <p> 057 The command-line arguments can also set parameter values for any 058 parameter in the models, with the name given relative to the top-level 059 entity. For example, to specify the iteration count in an SDF model, 060 you can invoke this on the command line as follows: 061 <pre> 062 java -classpath $PTII ptolemy.actor.gui.CompositeActorApplication \ 063 -director.iterations 1000 \ 064 -class ptolemy.domains.sdf.demo.Butterfly.Butterfly 065 </pre> 066 This assumes that the model given by the specified class name has a director 067 named "director" with a parameter named "iterations". If more than 068 one model is given on the command line, then the parameter values will 069 be set for all models that have such a parameter. 070 <p> 071 This class keeps count the number of open windows. The waitForFinish 072 method can then be used to determine when all of the windows opened by 073 this class have been closed. The main() method exits the application 074 when all windows have been closed. 075 076 @see ModelFrame 077 @author Edward A. Lee, Brian K. Vogel, and Steve Neuendorffer 078 @version $Id$ 079 @since Ptolemy II 0.4 080 @Pt.ProposedRating Yellow (cxh) 081 @Pt.AcceptedRating Red (vogel) 082 */ 083public class CompositeActorApplication extends CompositeActorSimpleApplication { 084 /////////////////////////////////////////////////////////////////// 085 //// public methods //// 086 087 /** Close any ModeFrames opened in processArgs(). 088 */ 089 public void close() { 090 // Mainly used for testing. 091 for (ModelFrame frame : _frames) { 092 if (frame != null) { 093 frame.close(); 094 } 095 } 096 } 097 098 /** Create a new application with the specified command-line arguments. 099 * @param args The command-line arguments. 100 */ 101 public static void main(String[] args) { 102 CompositeActorApplication application = new CompositeActorApplication(); 103 _run(application, args); 104 } 105 106 /** Parse the command-line arguments, creating models as specified. 107 * @param args The command-line arguments. 108 * @exception Exception If something goes wrong. 109 */ 110 @Override 111 public void processArgs(String[] args) throws Exception { 112 if (args != null) { 113 _parseArgs(args); 114 115 // start the models. 116 Iterator models = _models.iterator(); 117 118 while (models.hasNext()) { 119 _frames.add( 120 (ModelFrame) startRun((CompositeActor) models.next())); 121 } 122 } 123 } 124 125 /** If the specified model has a manager and is not already running, 126 * then execute the model in a new thread. Otherwise, do nothing. 127 * If the model contains an atomic entity that implements Placeable, 128 * we create create an instance of ModelFrame, if nothing implements 129 * Placeable, then we do not create an instance of ModelFrame. This 130 * allows us to run non-graphical models on systems that do not have 131 * a display. 132 * <p> 133 * We then start the model running. 134 * 135 * @param model The model to execute. 136 * @return The ModelFrame that for the model. 137 * @see ptolemy.actor.Manager#startRun() 138 */ 139 @Override 140 public synchronized Object startRun(CompositeActor model) { 141 // This method is synchronized so that it can atomically modify 142 // the count of executing processes. 143 // NOTE: If you modify this method, please be sure that it 144 // will work for non-graphical models in the nightly test suite. 145 // Iterate through the model, looking for something that is Placeable. 146 boolean hasPlaceable = false; 147 Iterator atomicEntities = model.allAtomicEntityList().iterator(); 148 149 while (atomicEntities.hasNext()) { 150 Object object = atomicEntities.next(); 151 152 if (object instanceof Placeable 153 || object instanceof PortablePlaceable) { 154 hasPlaceable = true; 155 break; 156 } 157 } 158 159 ModelFrame frame = null; 160 if (hasPlaceable) { 161 // The model has an entity that is Placeable, so create a frame. 162 try { 163 frame = new ModelFrame(model); 164 _openCount++; 165 frame.addWindowListener(new WindowAdapter() { 166 @Override 167 public void windowClosed(WindowEvent event) { 168 synchronized (CompositeActorApplication.this) { 169 _openCount--; 170 CompositeActorApplication.this.notifyAll(); 171 172 // FIXME: is this right? We need 173 // to exit if all the windows are closed? 174 if (_openCount == 0) { 175 StringUtilities.exit(0); 176 } 177 } 178 } 179 }); 180 frame.setBackground(new Color(0xe5e5e5)); 181 frame.pack(); 182 frame.centerOnScreen(); 183 frame.setVisible(true); 184 185 // FIXME: Use a JFrame listener to determine when all windows 186 // are closed. 187 } catch (Exception ex) { 188 System.out.println("startRun: " + ex); 189 } 190 } 191 192 Manager manager = model.getManager(); 193 194 if (manager != null) { 195 try { 196 manager.startRun(); 197 } catch (IllegalActionException ex) { 198 // Model is already running. Ignore. 199 } 200 } else { 201 report("Model " + model.getFullName() + " cannot be executed " 202 + "because it does not have a manager."); 203 } 204 return frame; 205 } 206 207 /////////////////////////////////////////////////////////////////// 208 //// private variables //// 209 210 // List of ModelFrames created processArgs(); 211 private List<ModelFrame> _frames = new LinkedList<ModelFrame>(); 212}