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}