001/* The node controller for ChicInvoker visible attributes. 002 003 Copyright (c) 1998-2016 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 027 */ 028package ptolemy.chic; 029 030import java.awt.Event; 031import java.awt.event.ActionEvent; 032import java.awt.event.KeyEvent; 033import java.net.URL; 034 035import javax.swing.KeyStroke; 036 037import diva.graph.GraphController; 038import diva.gui.GUIUtilities; 039import ptolemy.actor.gui.Configuration; 040import ptolemy.kernel.util.IllegalActionException; 041import ptolemy.kernel.util.NameDuplicationException; 042import ptolemy.kernel.util.NamedObj; 043import ptolemy.util.MessageHandler; 044import ptolemy.vergil.kernel.AttributeController; 045import ptolemy.vergil.toolbox.FigureAction; 046import ptolemy.vergil.toolbox.MenuActionFactory; 047 048/////////////////////////////////////////////////////////////////// 049//// ChicController 050 051/** 052 This class provides interaction with nodes that represent ChicInvoker 053 visible attributes. It provides a double click binding and context menu 054 entry to edit the parameters of the node ("Configure"), a command to get 055 documentation ("Get Documentation"), a command to look inside ("Look 056 Inside") and commands for invoking Chic. It can have one of two access 057 levels, FULL or PARTIAL. If the access level is FULL, then the context 058 menu also contains a command to rename the node ("Customize Name") and 059 a command to set the icon of the node ("Set Icon"). 060 061 @author Eleftherios Matsikoudis 062 @version $Id$ 063 @since Ptolemy II 3.0 064 @Pt.ProposedRating Red (cxh) 065 @Pt.AcceptedRating Red (cxh) 066 */ 067public class ChicController extends AttributeController { 068 /** Create a Chic controller associated with the specified graph 069 * controller with full access. 070 * @param controller The associated graph controller. 071 */ 072 public ChicController(GraphController controller) { 073 this(controller, FULL); 074 } 075 076 /** Create a Chic controller associated with the specified graph 077 * controller. 078 * @param controller The associated graph controller. 079 * @param access The access level. 080 */ 081 public ChicController(GraphController controller, Access access) { 082 super(controller, access); 083 084 // Add commands to invoke Chic 085 _menuFactory.addMenuItemFactory( 086 new MenuActionFactory(new AsynchronousIOAction())); 087 _menuFactory.addMenuItemFactory( 088 new MenuActionFactory(new SynchronousAGAction())); 089 090 // _menuFactory.addMenuItemFactory( 091 // new MenuActionFactory(new BidirectionalSynAction())); 092 // _menuFactory.addMenuItemFactory( 093 // new MenuActionFactory(new StatelessSoftwareAction())); 094 // _menuFactory.addMenuItemFactory( 095 // new MenuActionFactory(new StatefulSoftwareAction())); 096 // Add a command to look inside 097 if (_configuration != null) { 098 // NOTE: The following requires that the configuration be 099 // non-null, or it will report an error. 100 _menuFactory.addMenuItemFactory( 101 new MenuActionFactory(_lookInsideAction)); 102 } 103 } 104 105 /////////////////////////////////////////////////////////////////// 106 //// public methods //// 107 108 /** Set the configuration. This is used to open documentation files. 109 * @param configuration The configuration. 110 */ 111 @Override 112 public void setConfiguration(Configuration configuration) { 113 super.setConfiguration(configuration); 114 115 if (_configuration != null) { 116 // NOTE: The following requires that the configuration be 117 // non-null, or it will report an error. 118 _menuFactory.addMenuItemFactory( 119 new MenuActionFactory(_lookInsideAction)); 120 } 121 } 122 123 /////////////////////////////////////////////////////////////////// 124 //// protected variables //// 125 126 /** The action that handles look inside. This is accessed by 127 * by ActorViewerController to create a hot key for the editor. 128 */ 129 protected LookInsideAction _lookInsideAction = new LookInsideAction(); 130 131 /////////////////////////////////////////////////////////////////// 132 //// private variables //// 133 134 // Error message used when we can't find the inside definition. 135 private static String _CANNOT_FIND_MESSAGE = "Cannot find inside definition. " 136 + "Perhaps source code is not installed? " 137 + "You can obtain source code for Berkeley actors at: " 138 + "http://ptolemy.eecs.berkeley.edu/ptolemyII"; 139 140 /////////////////////////////////////////////////////////////////// 141 //// inner classes //// 142 143 /** An action to invoke CHIC: Asynchronous I/O 144 */ 145 @SuppressWarnings("serial") 146 private static class AsynchronousIOAction extends FigureAction { 147 public AsynchronousIOAction() { 148 super("CHIC: Asynchronous I/O"); 149 } 150 151 @Override 152 public void actionPerformed(ActionEvent e) { 153 // Determine which entity was selected for the look inside action. 154 super.actionPerformed(e); 155 156 NamedObj object = getTarget(); 157 158 try { 159 ((ChicInvoker) object).checkInterfaceCompatibility( 160 ChicInvoker.ASYNCHRONOUS_IO, false); 161 } catch (IllegalActionException ex) { 162 MessageHandler.error(ex.getMessage()); 163 } catch (NameDuplicationException ex) { 164 MessageHandler.error(ex.getMessage()); 165 } 166 167 return; 168 } 169 } 170 171 // /** An action to invoke CHIC: Bidirectional Syn A/G 172 // */ 173 // private class BidirectionalSynAction extends FigureAction { 174 // 175 // public BidirectionalSynAction() { 176 // super("CHIC: Bidirectional Syn A/G"); 177 // } 178 // 179 // public void actionPerformed(ActionEvent e) { 180 // 181 // // Determine which entity was selected for the look inside action. 182 // super.actionPerformed(e); 183 // NamedObj object = getTarget(); 184 // try { 185 // ((ChicInvoker)object).checkInterfaceCompatibility( 186 // ChicInvoker.BIDIRECTIONAL_SYN_AG, 187 // false); 188 // } catch (IllegalActionException ex) { 189 // MessageHandler.error(ex.getMessage()); 190 // } catch (NameDuplicationException ex) { 191 // MessageHandler.error(ex.getMessage()); 192 // } 193 // return; 194 // } 195 // } 196 197 /** An action to look inside the Chic visible attribute. 198 */ 199 @SuppressWarnings("serial") 200 private class LookInsideAction extends FigureAction { 201 public LookInsideAction() { 202 super("Look Inside (Ctrl+L)"); 203 204 // For some inexplicable reason, the I key doesn't work here. 205 // Use L, which used to be used for layout. 206 putValue(GUIUtilities.ACCELERATOR_KEY, 207 KeyStroke.getKeyStroke(KeyEvent.VK_L, Event.CTRL_MASK)); 208 } 209 210 @Override 211 public void actionPerformed(ActionEvent e) { 212 if (_configuration == null) { 213 MessageHandler 214 .error("Cannot look inside without a configuration."); 215 return; 216 } 217 218 // Determine which entity was selected for the look inside action. 219 super.actionPerformed(e); 220 221 NamedObj object = getTarget(); 222 223 // Open the source code, if possible. 224 String filename = object.getClass().getName().replace('.', '/') 225 + ".java"; 226 227 try { 228 URL toRead = getClass().getClassLoader().getResource(filename); 229 230 if (toRead != null) { 231 _configuration.openModel(null, toRead, 232 toRead.toExternalForm()); 233 } else { 234 MessageHandler.error(_CANNOT_FIND_MESSAGE); 235 } 236 } catch (Exception ex) { 237 MessageHandler.error(_CANNOT_FIND_MESSAGE, ex); 238 } 239 240 return; 241 } 242 } 243 244 // /** An action to invoke CHIC: Stateful Software 245 // */ 246 // private class StatefulSoftwareAction extends FigureAction { 247 // 248 // public StatefulSoftwareAction() { 249 // super("CHIC: Stateful Software"); 250 // } 251 // 252 // public void actionPerformed(ActionEvent e) { 253 // 254 // // Determine which entity was selected for the look inside action. 255 // super.actionPerformed(e); 256 // NamedObj object = getTarget(); 257 // try { 258 // ((ChicInvoker)object).checkInterfaceCompatibility( 259 // ChicInvoker.STATEFUL_SOFTWARE, 260 // false); 261 // } catch (IllegalActionException ex) { 262 // MessageHandler.error(ex.getMessage()); 263 // } catch (NameDuplicationException ex) { 264 // MessageHandler.error(ex.getMessage()); 265 // } 266 // return; 267 // } 268 // } 269 // /** An action to invoke CHIC: Stateless Software 270 // */ 271 // private class StatelessSoftwareAction extends FigureAction { 272 // 273 // public StatelessSoftwareAction() { 274 // super("CHIC: Stateless Software"); 275 // } 276 // 277 // public void actionPerformed(ActionEvent e) { 278 // 279 // // Determine which entity was selected for the look inside action. 280 // super.actionPerformed(e); 281 // NamedObj object = getTarget(); 282 // try { 283 // ((ChicInvoker)object).checkInterfaceCompatibility( 284 // ChicInvoker.STATELESS_SOFTWARE, 285 // false); 286 // } catch (IllegalActionException ex) { 287 // MessageHandler.error(ex.getMessage()); 288 // } catch (NameDuplicationException ex) { 289 // MessageHandler.error(ex.getMessage()); 290 // } 291 // return; 292 // } 293 // } 294 295 /** An action to invoke CHIC: Synchronous A/G 296 */ 297 @SuppressWarnings("serial") 298 private static class SynchronousAGAction extends FigureAction { 299 // FindBugs suggests making this class static so as to decrease 300 // the size of instances and avoid dangling references. 301 302 public SynchronousAGAction() { 303 super("CHIC: Synchronous A/G"); 304 } 305 306 @Override 307 public void actionPerformed(ActionEvent e) { 308 // Determine which entity was selected for the look inside action. 309 super.actionPerformed(e); 310 311 NamedObj object = getTarget(); 312 313 try { 314 ((ChicInvoker) object).checkInterfaceCompatibility( 315 ChicInvoker.SYNCHRONOUS_AG, false); 316 } catch (IllegalActionException ex) { 317 MessageHandler.error(ex.getMessage()); 318 } catch (NameDuplicationException ex) { 319 MessageHandler.error(ex.getMessage()); 320 } 321 322 return; 323 } 324 } 325}