001/* The graph controller for interface automata models.
002
003 Copyright (c) 1998-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
027 */
028package ptolemy.vergil.modal.ia;
029
030import java.awt.Color;
031import java.awt.event.ActionEvent;
032import java.awt.event.KeyEvent;
033import java.io.File;
034import java.net.URL;
035
036import javax.swing.AbstractAction;
037import javax.swing.JFileChooser;
038import javax.swing.JMenu;
039import javax.swing.JToolBar;
040
041import ptolemy.actor.gui.Configuration;
042import ptolemy.actor.gui.Tableau;
043import ptolemy.domains.modal.kernel.ia.InterfaceAutomaton;
044import ptolemy.gui.JFileChooserBugFix;
045import ptolemy.util.StringUtilities;
046import ptolemy.vergil.modal.FSMGraphController;
047
048///////////////////////////////////////////////////////////////////
049//// InterfaceAutomatonGraphController
050
051/**
052 A Graph Controller for interface automata models.  This controller adds
053 the "Compose With" menu item to the Graph menu.
054
055 @author Steve Neuendorffer, Yuhong Xiong, Contributor: Edward A. Lee
056 @version $Id$
057 @since Ptolemy II 8.0
058 @Pt.ProposedRating Red (yuhong)
059 @Pt.AcceptedRating Red (johnr)
060 */
061public class InterfaceAutomatonGraphController extends FSMGraphController {
062    /** Create a new controller with the specified directory of the current
063     *  model. The directory is for setting the current directory of
064     *  the file chooser invoked by the "Compose With" menu item.
065     *  @param directory An instance of File that specifies the directory
066     *   of the current model.
067     */
068    public InterfaceAutomatonGraphController(File directory) {
069        super();
070        _directory = directory;
071    }
072
073    ///////////////////////////////////////////////////////////////////
074    ////                         public methods                    ////
075
076    /** Add commands to the specified menu and toolbar, as appropriate
077     *  for this controller.  In this class, commands are added to create
078     *  ports and relations.
079     *  @param menu The menu to add to, or null if none.
080     *  @param toolbar The toolbar to add to, or null if none.
081     */
082    @Override
083    public void addToMenuAndToolbar(JMenu menu, JToolBar toolbar) {
084        super.addToMenuAndToolbar(menu, toolbar);
085
086        // Add an item that does composition.
087        // menu.addSeparator();
088        diva.gui.GUIUtilities.addMenuItem(menu, _composeWithAction);
089
090        // diva.gui.GUIUtilities.addToolBarButton(toolbar, _newStateAction);
091    }
092
093    ///////////////////////////////////////////////////////////////////
094    ////                         private variables                 ////
095    // The action for composing with another interface automaton.
096    private ComposeWithAction _composeWithAction = new ComposeWithAction();
097
098    // The directory of the current model.
099    private File _directory;
100
101    ///////////////////////////////////////////////////////////////////
102    ////                         inner classes                     ////
103    ///////////////////////////////////////////////////////////////////
104    //// ComposeWithAction
105
106    /** An action to perform composition. */
107    @SuppressWarnings("serial")
108    public class ComposeWithAction extends AbstractAction {
109        /** Create a new action to perform composition. */
110        public ComposeWithAction() {
111            super("Compose With");
112            putValue("tooltip", "Compose with another interface automaton");
113            putValue(diva.gui.GUIUtilities.MNEMONIC_KEY,
114                    Integer.valueOf(KeyEvent.VK_C));
115        }
116
117        /** Compose with another interface automaton by first opening a file
118         *  chooser dialog and then composing with the specified model.
119         *  The specified model and the composition result are shown in
120         *  two new interface automaton graph frames.
121         */
122        @Override
123        public void actionPerformed(ActionEvent e) {
124            // NOTE: This code is mostly copied from Top.
125
126            // Avoid white boxes in file chooser, see
127            // http://bugzilla.ecoinformatics.org/show_bug.cgi?id=3801
128            JFileChooserBugFix jFileChooserBugFix = new JFileChooserBugFix();
129            Color background = null;
130            try {
131                background = jFileChooserBugFix.saveBackground();
132                JFileChooser fileDialog = new JFileChooser();
133                fileDialog.setDialogTitle(
134                        "Select an interface automaton to compose with.");
135
136                if (_directory != null) {
137                    fileDialog.setCurrentDirectory(_directory);
138                } else {
139                    // The default on Windows is to open at user.home, which is
140                    // typically an absurd directory inside the O/S installation.
141                    // So we use the current directory instead.
142                    // FIXME: Could this throw a security exception in an applet?
143                    String cwd = StringUtilities.getProperty("user.dir");
144
145                    if (cwd != null) {
146                        fileDialog.setCurrentDirectory(new File(cwd));
147                    }
148                }
149
150                int returnValue = fileDialog.showOpenDialog(getFrame());
151
152                if (returnValue == JFileChooser.APPROVE_OPTION) {
153                    _directory = fileDialog.getCurrentDirectory();
154
155                    try {
156                        // NOTE: It would be nice if it were possible to enter
157                        // a URL in the file chooser, but Java's file chooser does
158                        // not permit this, regrettably.  So we have a separate
159                        // menu item for this.
160                        File file = fileDialog.getSelectedFile()
161                                .getCanonicalFile();
162                        URL url = file.toURI().toURL();
163
164                        // NOTE: Used to use for the first argument the following,
165                        // but it seems to not work for relative file references:
166                        // new URL("file", null, _directory.getAbsolutePath()
167                        Configuration configuration = getConfiguration();
168                        Tableau newAutomatonTableau = configuration
169                                .openModel(url, url, url.toExternalForm());
170
171                        // compose the two interface automata and show result
172                        InterfaceAutomaton model1 = (InterfaceAutomaton) getFrame()
173                                .getModel();
174                        InterfaceAutomatonGraphFrame graphFrame2 = (InterfaceAutomatonGraphFrame) newAutomatonTableau
175                                .getFrame();
176                        InterfaceAutomaton model2 = (InterfaceAutomaton) graphFrame2
177                                .getModel();
178
179                        InterfaceAutomaton composition = model1.compose(model2);
180                        configuration.openModel(composition);
181                    } catch (Exception ex) {
182                        getFrame().report("Error reading input", ex);
183                    }
184                }
185            } finally {
186                jFileChooserBugFix.restoreBackground(background);
187            }
188        }
189    }
190}