001/* This actor implements a communication aspect Monitor. 002 003@Copyright (c) 2010-2014 The Regents of the University of California. 004All rights reserved. 005 006Permission is hereby granted, without written agreement and without 007license or royalty fees, to use, copy, modify, and distribute this 008software and its documentation for any purpose, provided that the 009above copyright notice and the following two paragraphs appear in all 010copies of this software. 011 012IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 013FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 014ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 015THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 016SUCH DAMAGE. 017 018THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 019INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 020MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 021PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 022CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 023ENHANCEMENTS, OR MODIFICATIONS. 024 025 PT_COPYRIGHT_VERSION_2 026 COPYRIGHTENDKEY 027 028 029 */ 030 031package ptolemy.actor.gui; 032 033import java.awt.Color; 034import java.awt.Frame; 035import java.util.ArrayList; 036import java.util.List; 037 038import ptolemy.actor.Actor; 039import ptolemy.actor.CommunicationAspect; 040import ptolemy.actor.CommunicationAspectListener; 041import ptolemy.actor.CompositeActor; 042import ptolemy.actor.Director; 043import ptolemy.actor.TypedAtomicActor; 044import ptolemy.data.BooleanToken; 045import ptolemy.data.expr.SingletonParameter; 046import ptolemy.kernel.CompositeEntity; 047import ptolemy.kernel.util.IllegalActionException; 048import ptolemy.kernel.util.InternalErrorException; 049import ptolemy.kernel.util.NameDuplicationException; 050import ptolemy.kernel.util.NamedObj; 051import ptolemy.kernel.util.Settable; 052import ptolemy.plot.Plot; 053 054/** This actor implements a Communication aspect Monitor. 055 * This monitor shows when communication aspects in the model receive messages 056 * and send messages in a 2D plot. The x-Axis is the time, the y-Axis shows how 057 * many messages are currently processed by the communication aspect. 058 * 059 * @author Patricia Derler 060 * @version $Id$ 061 * @since Ptolemy II 10.0 062 * @Pt.ProposedRating Yellow (derler) 063 * @Pt.AcceptedRating Red (derler) 064 */ 065public class CommunicationAspectMonitor extends TypedAtomicActor 066 implements CommunicationAspectListener { 067 068 /** Construct a factory with the specified container and name. 069 * @param container The container. 070 * @param name The name of the factory. 071 * @exception IllegalActionException 072 * If the factory is not of an acceptable attribute for 073 * the container. 074 * @exception NameDuplicationException 075 * If the name coincides with an attribute already in the 076 * container. 077 */ 078 public CommunicationAspectMonitor(CompositeEntity container, String name) 079 throws IllegalActionException, NameDuplicationException { 080 super(container, name); 081 082 _attachText("_iconDescription", "<svg>\n" 083 + "<rect x=\"-50\" y=\"-20\" width=\"130\" height=\"40\" " 084 + "style=\"fill:blue\"/>" + "<text x=\"-40\" y=\"-5\" " 085 + "style=\"font-size:12; font-family:SansSerif; fill:white\">" 086 + "Double click to\nplot the schedule.</text></svg>"); 087 088 new CommunicationAspectMonitorEditorFactory(this, "_editorFactory"); 089 090 SingletonParameter hide = new SingletonParameter(this, "_hideName"); 091 hide.setToken(BooleanToken.TRUE); 092 hide.setVisibility(Settable.EXPERT); 093 094 } 095 096 /////////////////////////////////////////////////////////////////// 097 // public variables // 098 099 /** The plotter. */ 100 public Plot plot; 101 102 /////////////////////////////////////////////////////////////////// 103 // public methods // 104 105 /** The event is displayed. 106 * @param qm The communication aspect that sent the event. 107 * @param source The source actor that caused the event in the 108 * communication aspect. 109 * @param messageId The ID of the message that caused the event in 110 * the communication aspect. 111 * @param messageCnt The amount of messages currently being processed 112 * by the communication aspect. 113 * @param time The time when the event happened. 114 * @param event The type of the event. e.g. message received, message sent, ... 115 */ 116 @Override 117 public void event(final CommunicationAspect qm, Actor source, int messageId, 118 int messageCnt, double time, EventType event) { 119 120 if (plot == null) { 121 return; 122 } 123 124 double x = time; 125 double y = 0; 126 int actorDataset = _communicationAspects.indexOf(qm); 127 if (event == null) { 128 plot.addPoint(actorDataset, x, y, false); 129 } else if (event == EventType.RECEIVED) { 130 plot.addPoint(actorDataset, x, y + 0.1 * messageCnt, true); 131 } else if (event == EventType.SENT) { 132 plot.addPoint(actorDataset, x, y + 0.1 * messageCnt, true); 133 } 134 plot.fillPlot(); 135 plot.repaint(); 136 } 137 138 Color[] colors; 139 140 /** Initialize the plot and the legend with the list of communication aspects used 141 * in this model. 142 * @exception IllegalActionException If thrown by the parent class. 143 */ 144 @Override 145 public void initialize() throws IllegalActionException { 146 super.initialize(); 147 _communicationAspects = new ArrayList<CommunicationAspect>(); 148 if (getContainer() instanceof CompositeActor) { 149 Director director = ((CompositeActor) getContainer()).getDirector(); 150 List<Actor> list = ((CompositeActor) director.getContainer()) 151 .entityList(); 152 for (Actor actor : list) { 153 if (actor instanceof CommunicationAspect) { 154 _communicationAspects.add((CommunicationAspect) actor); 155 ((CommunicationAspect) actor).registerListener(this); 156 } 157 } 158 } 159 160 if (plot != null) { 161 plot.clear(false); 162 plot.clearLegends(); 163 colors = new Color[_communicationAspects.size()]; 164 for (CommunicationAspect aspect : _communicationAspects) { 165 int idx = _communicationAspects.indexOf(aspect); 166 plot.addLegend(idx, ((NamedObj) aspect).getName()); 167 plot.addPoint(idx, 0.0, /*idx*/0, false); 168 colors[idx] = ((ColorAttribute) ((NamedObj) aspect) 169 .getAttribute( 170 CommunicationAspect.decoratorHighlightColorName)) 171 .asColor(); 172 } 173 174 plot.doLayout(); 175 } 176 // FIXME: This affects all plots in the model: 177 // plot.setColors(colors); 178 } 179 180 /////////////////////////////////////////////////////////////////// 181 // private variables // 182 183 /** List of communication aspects used in the model. */ 184 private List<CommunicationAspect> _communicationAspects; 185 186 /////////////////////////////////////////////////////////////////// 187 // inner classes // 188 189 /** Factory that creates the schedule plotter. */ 190 public class CommunicationAspectMonitorEditorFactory extends EditorFactory { 191 // This class needs to be public for shallow code generation. 192 /** 193 * Constructs a SchedulePlotter$SchedulePlotterEditorFactory object. 194 * 195 * @param container 196 * The container. 197 * @param name 198 * The name of the factory. 199 * @exception IllegalActionException 200 * If the factory is not of an acceptable attribute 201 * for the container. 202 * @exception NameDuplicationException 203 * If the name coincides with an attribute already in 204 * the container. 205 */ 206 public CommunicationAspectMonitorEditorFactory(NamedObj container, 207 String name) 208 throws IllegalActionException, NameDuplicationException { 209 super(container, name); 210 } 211 212 /** 213 * Create an editor for configuring the specified object with the 214 * specified parent window. 215 * 216 * @param object 217 * The object to configure. 218 * @param parent 219 * The parent window, or null if there is none. 220 */ 221 @Override 222 public void createEditor(NamedObj object, Frame parent) { 223 try { 224 Configuration configuration = ((TableauFrame) parent) 225 .getConfiguration(); 226 227 NamedObj container = object.getContainer(); 228 229 plot = new Plot(); 230 plot.setTitle("communication aspect Monitor"); 231 plot.setButtons(true); 232 plot.setMarksStyle("dots"); 233 234 // We put the plotter as a sub-effigy of the toplevel effigy, 235 // so that it closes when the model is closed. 236 Effigy effigy = Configuration.findEffigy(toplevel()); 237 PlotEffigy schedulePlotterEffigy = new PlotEffigy(effigy, 238 container.uniqueName("schedulePlotterEffigy")); 239 schedulePlotterEffigy.setPlot(plot); 240 schedulePlotterEffigy.setModel(this.getContainer()); 241 schedulePlotterEffigy.identifier.setExpression("Monitor"); 242 243 configuration.createPrimaryTableau(schedulePlotterEffigy); 244 245 plot.setVisible(true); 246 } catch (Throwable throwable) { 247 throw new InternalErrorException(object, throwable, 248 "Cannot create Plotter"); 249 } 250 } 251 } 252 253}