001/* An extended simple graph view for Ptolemy models 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.vergil.basic; 029 030import java.awt.BorderLayout; 031import java.awt.Component; 032import java.awt.Toolkit; 033import java.awt.event.ActionEvent; 034import java.awt.event.KeyEvent; 035import java.awt.event.KeyListener; 036 037import javax.swing.AbstractAction; 038import javax.swing.Action; 039import javax.swing.ActionMap; 040import javax.swing.InputMap; 041import javax.swing.JDialog; 042import javax.swing.KeyStroke; 043 044import diva.gui.GUIUtilities; 045import ptolemy.actor.gui.Tableau; 046import ptolemy.gui.UndeferredGraphicalMessageHandler; 047import ptolemy.kernel.CompositeEntity; 048import ptolemy.moml.LibraryAttribute; 049 050/////////////////////////////////////////////////////////////////// 051//// ExtendedGraphFrame 052 053/** 054 An graph view for ptolemy models extended with the capability 055 to display the model in full-screen mode. 056 057 @author Edward A. Lee 058 @version $Id$ 059 @since Ptolemy II 2.0 060 @Pt.ProposedRating Red (neuendor) 061 @Pt.AcceptedRating Red (johnr) 062 */ 063@SuppressWarnings("serial") 064public abstract class ExtendedGraphFrame extends BasicGraphFrame { 065 /** Construct a frame associated with the specified Ptolemy II model. 066 * After constructing this, it is necessary 067 * to call setVisible(true) to make the frame appear. 068 * This is typically done by calling show() on the controlling tableau. 069 * This constructor results in a graph frame that obtains its library 070 * either from the model (if it has one) or the default library defined 071 * in the configuration. 072 * @see Tableau#show() 073 * @param entity The model to put in this frame. 074 * @param tableau The tableau responsible for this frame. 075 */ 076 public ExtendedGraphFrame(CompositeEntity entity, Tableau tableau) { 077 this(entity, tableau, null); 078 } 079 080 /** Construct a frame associated with the specified Ptolemy II model. 081 * After constructing this, it is necessary 082 * to call setVisible(true) to make the frame appear. 083 * This is typically done by calling show() on the controlling tableau. 084 * This constructor results in a graph frame that obtains its library 085 * either from the model (if it has one), or the <i>defaultLibrary</i> 086 * argument (if it is non-null), or the default library defined 087 * in the configuration. 088 * @see Tableau#show() 089 * @param entity The model to put in this frame. 090 * @param tableau The tableau responsible for this frame. 091 * @param defaultLibrary An attribute specifying the default library 092 * to use if the model does not have a library. 093 */ 094 public ExtendedGraphFrame(CompositeEntity entity, Tableau tableau, 095 LibraryAttribute defaultLibrary) { 096 super(entity, tableau, defaultLibrary); 097 _initExtendedGraphFrame(); 098 } 099 100 /////////////////////////////////////////////////////////////////// 101 //// public methods //// 102 103 /** Cancel full screen mode. Note that this should be called 104 * in the swing event thread. 105 */ 106 public void cancelFullScreen() { 107 if (_screen == null) { 108 // Already canceled. 109 return; 110 } 111 112 _screen.dispose(); 113 _screen = null; 114 115 // Only include the palettePane and panner if there is an actor library. 116 // The ptinyViewer configuration uses this. 117 if ((CompositeEntity) getConfiguration() 118 .getEntity("actor library") != null) { 119 // Put the component back into the original window. 120 _splitPane.setRightComponent(_getRightComponent()); 121 122 // Restore association with the graph panner. 123 _graphPanner.setCanvas(getJGraph()); 124 } else { 125 getContentPane().add(_getRightComponent()); 126 } 127 pack(); 128 show(); 129 UndeferredGraphicalMessageHandler.setContext(_previousDefaultContext); 130 toFront(); 131 _getRightComponent().requestFocus(); 132 } 133 134 /** Go to full screen. 135 */ 136 public void fullScreen() { 137 if (_screen != null) { 138 // Already in full screen mode. 139 _screen.toFront(); 140 return; 141 } 142 143 // NOTE: Do not make the original graph frame the owner, 144 // because we are going to hide it, and if it is the owner, 145 // then the new frame will be hidden also. 146 _screen = new JDialog(); 147 _screen.getContentPane().setLayout(new BorderLayout()); 148 149 // Set to full-screen size. 150 Toolkit toolkit = _screen.getToolkit(); 151 int width = toolkit.getScreenSize().width; 152 int height = toolkit.getScreenSize().height; 153 _screen.setSize(width, height); 154 155 _screen.setUndecorated(true); 156 _screen.getContentPane().add(getJGraph(), BorderLayout.CENTER); 157 158 // NOTE: Have to avoid the following, which forces the 159 // dialog to resize the preferred size of _jgraph, which 160 // nullifies the call to setSize() above. 161 // _screen.pack(); 162 _screen.setVisible(true); 163 164 // Make the new screen the default context for modal messages. 165 _previousDefaultContext = UndeferredGraphicalMessageHandler 166 .getContext(); 167 UndeferredGraphicalMessageHandler.setContext(_screen); 168 169 // NOTE: As usual with swing, what the UI does is pretty 170 // random, and doesn't correlate much with the documentation. 171 // The following two lines do not work if _screen is a 172 // JWindow instead of a JDialog. There is no apparent 173 // reason for this, but this is why we use JDialog. 174 // Unfortunately, apparently the JDialog does not appear 175 // in the Windows task bar. 176 _screen.toFront(); 177 getJGraph().requestFocus(); 178 179 _screen.setResizable(false); 180 181 // Bind escape key to remove full-screen mode. 182 ActionMap actionMap = getJGraph().getActionMap(); 183 184 // Use the action as both a key and the action. 185 actionMap.put(_fullScreenAction, _fullScreenAction); 186 187 InputMap inputMap = getJGraph().getInputMap(); 188 inputMap.put(KeyStroke.getKeyStroke("ESCAPE"), _fullScreenAction); 189 190 // The ptinyViewer configuration will have a null _graphPanner. 191 if (_graphPanner != null) { 192 // Remove association with the graph panner. 193 _graphPanner.setCanvas(null); 194 } 195 196 setVisible(false); 197 } 198 199 /** Dispose of this frame. 200 * Override this dispose() method to unattach any listeners that may keep 201 * this model from getting garbage collected. This method invokes the 202 * dispose() method of the superclass, 203 * {@link ptolemy.vergil.basic.BasicGraphFrame}. 204 */ 205 @Override 206 public void dispose() { 207 if (_debugClosing) { 208 System.out.println( 209 "ExtendedGraphFrame.dispose() : " + this.getName()); 210 } 211 212 _fullScreenAction = null; 213 super.dispose(); 214 } 215 216 /////////////////////////////////////////////////////////////////// 217 //// protected methods //// 218 219 /** 220 * Initialize this class. 221 * In this base class, a button for the full screen action 222 * is added to the toolbar. 223 */ 224 protected void _initExtendedGraphFrame() { 225 GUIUtilities.addToolBarButton(_toolbar, _fullScreenAction); 226 } 227 228 /** Create the menus that are used by this frame. 229 */ 230 @Override 231 protected void _addMenus() { 232 super._addMenus(); 233 234 _viewMenu.addSeparator(); 235 GUIUtilities.addHotKey(_getRightComponent(), _fullScreenAction); 236 GUIUtilities.addMenuItem(_viewMenu, _fullScreenAction); 237 } 238 239 /** Invoke the close() method of the superclass and optionally 240 * print a debugging message. 241 * If {@link ptolemy.actor.gui.Tableau#_debugClosing} is 242 * true, then a message is printed to standard out. 243 * This method is used for debugging memory leaks. 244 * @return True if the close completes, and false otherwise. 245 */ 246 @Override 247 protected boolean _close() { 248 if (_debugClosing) { 249 System.out 250 .println("ExtendedGraphFrame._close() : " + this.getName()); 251 } 252 253 return super._close(); 254 } 255 256 /////////////////////////////////////////////////////////////////// 257 //// private variables //// 258 259 /** Action for displaying in full-screen mode. */ 260 private Action _fullScreenAction = new FullScreenAction("Full Screen"); 261 262 /** Default context for dialogs before going to full-screen mode. */ 263 private Component _previousDefaultContext; 264 265 /** If we are in full-screen mode, this will be non-null. */ 266 private JDialog _screen; 267 268 /////////////////////////////////////////////////////////////////// 269 //// inner classes //// 270 271 /////////////////////////////////////////////////////////////////// 272 //// FullScreenAction 273 /** An action to display in full-screen mode. */ 274 public class FullScreenAction extends AbstractAction 275 implements KeyListener { 276 /** Construct a full screen action. 277 * @param description A string that describes the action. Spaces are 278 * permitted, each word is usually capitalized. 279 */ 280 public FullScreenAction(String description) { 281 super(description); 282 283 // Load the image by using the absolute path to the gif. 284 // Using a relative location should work, but it does not. 285 // Use the resource locator of the class. 286 // For more information, see 287 // jdk1.3/docs/guide/resources/resources.html 288 GUIUtilities.addIcons(this, 289 new String[][] { 290 { "/ptolemy/vergil/basic/img/fullscreen.gif", 291 GUIUtilities.LARGE_ICON }, 292 { "/ptolemy/vergil/basic/img/fullscreen_o.gif", 293 GUIUtilities.ROLLOVER_ICON }, 294 { "/ptolemy/vergil/basic/img/fullscreen_ov.gif", 295 GUIUtilities.ROLLOVER_SELECTED_ICON }, 296 { "/ptolemy/vergil/basic/img/fullscreen_on.gif", 297 GUIUtilities.SELECTED_ICON } }); 298 299 putValue("tooltip", description); 300 301 putValue(GUIUtilities.MNEMONIC_KEY, Integer.valueOf(KeyEvent.VK_S)); 302 } 303 304 /** If we are in full-screen mode, then revert; otherwise, go 305 * to full-screen mode. 306 * @param e The action event, ignored by this method. 307 */ 308 @Override 309 public void actionPerformed(ActionEvent e) { 310 if (_screen == null) { 311 fullScreen(); 312 } else { 313 cancelFullScreen(); 314 } 315 } 316 317 /** React to a key press by removing full-screen mode. 318 * @param e The key event, ignored by this method. 319 */ 320 @Override 321 public void keyPressed(KeyEvent e) { 322 if (_screen != null) { 323 cancelFullScreen(); 324 } 325 } 326 327 /** React to a key press by removing full-screen mode. 328 * @param e The key event, ignored by this method. 329 */ 330 @Override 331 public void keyReleased(KeyEvent e) { 332 if (_screen != null) { 333 cancelFullScreen(); 334 } 335 } 336 337 /** React to a key press by removing full-screen mode. 338 * @param e The key event, ignored by this method. 339 */ 340 @Override 341 public void keyTyped(KeyEvent e) { 342 if (_screen != null) { 343 cancelFullScreen(); 344 } 345 } 346 } 347}