001/* An applet that shows resolved types in a vergil graph. 002 003 Copyright (c) 1999-2014 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 */ 027package ptolemy.vergil; 028 029import java.util.Iterator; 030 031import ptolemy.actor.Manager; 032import ptolemy.actor.TypeEvent; 033import ptolemy.actor.TypeListener; 034import ptolemy.actor.TypedIOPort; 035import ptolemy.kernel.CompositeEntity; 036import ptolemy.kernel.Entity; 037import ptolemy.kernel.util.Attribute; 038import ptolemy.kernel.util.Configurable; 039import ptolemy.kernel.util.NamedObj; 040import ptolemy.kernel.util.Workspace; 041import ptolemy.moml.MoMLChangeRequest; 042 043/////////////////////////////////////////////////////////////////// 044//// TypeAnimatorApplet 045 046/** 047 An applet that demonstrates the Ptolemy II type system. 048 This applet identifies attributes whose names match entity names, 049 followed by an underscore, followed by a port name. 050 If that attribute has an icon (i.e. it is a visible attribute), 051 then the icon is set to a text string that gives the type of 052 the port. 053 <p> 054 To use this applet, create an MoML file with the model that you 055 want to animate, and insert visible attributes in it. Rename 056 these so that the name has the form "entityname_portname", 057 to illustrate the port of the specified entity. 058 059 @author Edward A. Lee and Yuhong Xiong 060 @version $Id$ 061 @since Ptolemy II 1.0 062 @Pt.ProposedRating Yellow (eal) 063 @Pt.AcceptedRating Red (cxh) 064 */ 065@SuppressWarnings("serial") 066public class TypeAnimatorApplet extends MoMLViewerApplet { 067 /////////////////////////////////////////////////////////////////// 068 //// public methods //// 069 070 /** React to the fact that the manager state has changed. This is 071 * called by the manager. In this class, we detect the start of 072 * execution of the model to initialize the type displays with 073 * the initial types. 074 * @param manager The manager that changed. 075 */ 076 @Override 077 public void managerStateChanged(Manager manager) { 078 super.managerStateChanged(manager); 079 080 // FIXME this is a workaround for a bug in the type system where 081 // type listeners are not properly notified when the type is 082 // a structured type. 083 if (manager.getState() == Manager.INITIALIZING) { 084 _updateAllTypeDisplays(); 085 } 086 } 087 088 /** Override the base class to avoid executing the model automatically 089 * when the applet starts, and instead to update type displays 090 * to the initial types of the ports. 091 */ 092 @Override 093 public void start() { 094 _updateAllTypeDisplays(); 095 } 096 097 /////////////////////////////////////////////////////////////////// 098 //// protected methods //// 099 100 /** Create the model. This overrides the base class to attach 101 * type listeners to all the ports contained by top-level entities. 102 * @param workspace The workspace in which to create the model. 103 * @exception Exception If there was a problem creating the model. 104 * @return The model that was created 105 */ 106 @Override 107 protected NamedObj _createModel(Workspace workspace) throws Exception { 108 _toplevel = super._createModel(workspace); 109 110 if (_toplevel instanceof CompositeEntity) { 111 CompositeEntity toplevel = (CompositeEntity) _toplevel; 112 TypeListener typeListener = new PortTypeListener(); 113 Iterator entities = toplevel.entityList().iterator(); 114 115 while (entities.hasNext()) { 116 Entity entity = (Entity) entities.next(); 117 Iterator ports = entity.portList().iterator(); 118 119 while (ports.hasNext()) { 120 TypedIOPort port = (TypedIOPort) ports.next(); 121 port.addTypeListener(typeListener); 122 } 123 } 124 } 125 126 return _toplevel; 127 } 128 129 /////////////////////////////////////////////////////////////////// 130 //// private methods //// 131 // Update the type designator for all ports contained by 132 // entities contained by the toplevel. 133 private void _updateAllTypeDisplays() { 134 if (_toplevel instanceof CompositeEntity) { 135 CompositeEntity toplevel = (CompositeEntity) _toplevel; 136 Iterator entities = toplevel.entityList().iterator(); 137 138 while (entities.hasNext()) { 139 Entity entity = (Entity) entities.next(); 140 Iterator ports = entity.portList().iterator(); 141 142 while (ports.hasNext()) { 143 TypedIOPort port = (TypedIOPort) ports.next(); 144 _updateTypeDisplay(port); 145 } 146 } 147 } 148 } 149 150 // Update the type designator for the specified port. 151 private void _updateTypeDisplay(TypedIOPort port) { 152 // Construct the name of the type label from the name 153 // of the port relative to the top level. 154 String portName = port.getName(_toplevel); 155 String labelName = portName.replace('.', '_'); 156 Attribute label = _toplevel.getAttribute(labelName); 157 158 if (label != null) { 159 Configurable config = (Configurable) label 160 .getAttribute("_iconDescription"); 161 162 if (config != null) { 163 String moml = "<property name=" + "\"_iconDescription\" " 164 + "class=\"ptolemy.kernel.util" 165 + ".SingletonConfigurableAttribute\">" 166 + "<configure><svg><text x=\"20\" " 167 + "style=\"font-size:14; font-family:sanserif; " 168 + "fill:red\" y=\"20\">" + port.getType() 169 + "</text></svg></configure></property>"; 170 label.requestChange(new MoMLChangeRequest(this, label, moml)); 171 } 172 } 173 } 174 175 /////////////////////////////////////////////////////////////////// 176 //// inner classes //// 177 // The local listener class 178 private class PortTypeListener implements TypeListener { 179 // Called to indicate that a type has changed. 180 @Override 181 public void typeChanged(final TypeEvent event) { 182 TypedIOPort port = (TypedIOPort) event.getSource(); 183 _updateTypeDisplay(port); 184 } 185 } 186}