001/* A frame for presenting a dialog 002 003 Copyright (c) 2003-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.actor.gui; 029 030import java.awt.BorderLayout; 031import java.awt.Dimension; 032import java.awt.Frame; 033import java.awt.GraphicsConfiguration; 034import java.awt.GraphicsDevice; 035import java.awt.GraphicsEnvironment; 036import java.awt.Point; 037import java.awt.Rectangle; 038import java.awt.event.ActionEvent; 039import java.awt.event.ActionListener; 040import java.awt.event.WindowAdapter; 041import java.awt.event.WindowEvent; 042import java.net.URL; 043 044import javax.swing.JButton; 045import javax.swing.JComponent; 046import javax.swing.JFrame; 047import javax.swing.JPanel; 048import javax.swing.JScrollPane; 049 050import ptolemy.kernel.Entity; 051import ptolemy.util.MessageHandler; 052 053/////////////////////////////////////////////////////////////////// 054//// PtolemyDialog 055 056/** 057 Ptolemy specific dialog. 058 059 @author Rowland R Johnson 060 @version $Id$ 061 @since Ptolemy II 4.0 062 @Pt.ProposedRating Red (rowland) 063 @Pt.AcceptedRating Red (rowland) 064 */ 065@SuppressWarnings("serial") 066public abstract class PtolemyDialog extends JFrame implements ActionListener { 067 /** 068 * Construct a PtolemyDialog. 069 * 070 * @param title The title of the PtolemyDialog. 071 * @param dialogTableau The dialogTableau, used to set the title. 072 * @param owner The frame. 073 * @param target The model 074 * @param configuration a Configuration object 075 */ 076 public PtolemyDialog(String title, DialogTableau dialogTableau, Frame owner, 077 Entity target, Configuration configuration) { 078 super(title); 079 _owner = owner; 080 _dialogTableau = dialogTableau; 081 _target = target; 082 _configuration = configuration; 083 _dialogTableau.setTitle(title); 084 085 // This JDialog consists of two components. On top is a JComponent 086 // inside of a JScrolPane that displays the ports and their attributes. 087 // On bottom is a JPanel that contains buttons that cause various 088 // actions. 089 JPanel _buttons = _createButtonsPanel(); 090 getContentPane().add(_buttons, BorderLayout.SOUTH); 091 addWindowListener(new WindowAdapter() { 092 @Override 093 public void windowClosing(WindowEvent e) { 094 _cancel(); 095 } 096 }); 097 098 _owner.addWindowListener(new WindowAdapter() { 099 @Override 100 public void windowIconified(WindowEvent e) { 101 _iconify(); 102 } 103 104 @Override 105 public void windowDeiconified(WindowEvent e) { 106 _deiconify(); 107 } 108 }); 109 110 GraphicsEnvironment ge = GraphicsEnvironment 111 .getLocalGraphicsEnvironment(); 112 GraphicsDevice[] SCREENS = ge.getScreenDevices(); 113 Point ownerLoc = owner.getLocation(); 114 Rectangle screenBounds = null; 115 116 for (GraphicsDevice element : SCREENS) { 117 GraphicsConfiguration gc = element.getDefaultConfiguration(); 118 Rectangle bounds = gc.getBounds(); 119 120 if (bounds.contains(ownerLoc)) { 121 screenBounds = bounds; 122 break; 123 } 124 } 125 126 if (screenBounds != null) { 127 Dimension size = getPreferredSize(); 128 int x = screenBounds.x + screenBounds.width / 2 - size.width / 2; 129 int y = screenBounds.y + screenBounds.height / 2 - size.height / 2; 130 setLocation(x, y); 131 } else { 132 setLocationRelativeTo(_owner); 133 } 134 } 135 136 /////////////////////////////////////////////////////////////////// 137 //// public methods //// 138 139 /** If the action event is a JButton, process the button press. 140 * @param aEvent The event. 141 */ 142 @Override 143 public void actionPerformed(ActionEvent aEvent) { 144 String command = aEvent.getActionCommand(); 145 146 if (aEvent.getSource() instanceof JButton) { 147 _processButtonPress(command); 148 } 149 } 150 151 /** Return the target. 152 * @return The target. 153 * @see #setTarget(Entity) 154 */ 155 public Entity getTarget() { 156 return _target; 157 } 158 159 /** If necessary save any state. 160 * In this base class, do nothing. Derived classes should extend 161 * this method so that the {@link #_cancel()} method save state 162 * if necessary. 163 */ 164 public void saveIfRequired() { 165 } 166 167 /** Set the contents of this dialog. 168 * @param contents The contents. 169 */ 170 public void setContents(JComponent contents) { 171 _contents = contents; 172 getContentPane().add(_contents, BorderLayout.CENTER); 173 } 174 175 /** Set the contents of this dialog. 176 * @param contents The contents. 177 */ 178 public void setScrollableContents(JComponent contents) { 179 _contents = contents; 180 181 JScrollPane scrollPane = new JScrollPane(_contents); 182 getContentPane().add(scrollPane, BorderLayout.CENTER); 183 } 184 185 /** Set the target of this dialog. 186 * @param entity Target of this dialog. 187 * @see #getTarget() 188 */ 189 public void setTarget(Entity entity) { 190 _target = entity; 191 } 192 193 /////////////////////////////////////////////////////////////////// 194 //// protected methods //// 195 196 /** Cancel this dialog, saving if necessary. 197 */ 198 protected void _cancel() { 199 saveIfRequired(); 200 dispose(); 201 } 202 203 /** Created extended buttons. 204 * @param _buttons The buttons to be created. 205 */ 206 protected abstract void _createExtendedButtons(JPanel _buttons); 207 208 /** Get the URL that is the help for this dialog. 209 * @return URL that is the help for this dialog. 210 */ 211 protected abstract URL _getHelpURL(); 212 213 /** Return true if any of the values have been changed, but the state 214 * has not yet been saved. 215 * @return True if values have been changed but not saved. 216 */ 217 protected boolean _isDirty() { 218 return _dirty; 219 } 220 221 /** Process button presses. 222 * The button semantics are 223 * <br>Commit - Apply and then cancel the dialog. 224 * <br>Apply - make the changes that have been expressed thus far. 225 * <br>Help - Show the associated help. 226 * <br>Cancel - Remove the dialog without making any pending changes. 227 * @param button The name of the button to process. 228 */ 229 protected void _processButtonPress(String button) { 230 if (button.equals("Cancel")) { 231 _cancel(); 232 } else if (button.equals("Help")) { 233 _showHelp(); 234 } else { 235 //TODO throw an exception here 236 } 237 } 238 239 /** Set the boolean that determines if the GUI has a change that has not 240 * applied to the system. 241 * @param dirty True if the GUI has a change that has not been applied. 242 */ 243 protected void _setDirty(boolean dirty) { 244 _dirty = dirty; 245 } 246 247 /** Display the help URL. 248 * @see #_getHelpURL() 249 */ 250 protected void _showHelp() { 251 URL toRead = _getHelpURL(); 252 253 if (toRead != null && _configuration != null) { 254 try { 255 _configuration.openModel(null, toRead, toRead.toExternalForm()); 256 } catch (Exception ex) { 257 MessageHandler.error("Help screen failure", ex); 258 } 259 } else { 260 MessageHandler.error("No help available."); 261 } 262 } 263 264 /////////////////////////////////////////////////////////////////// 265 //// protected members //// 266 267 /** The configuration that corresponds with this dialog. 268 * The configuration is used to properly display the help text. 269 */ 270 protected Configuration _configuration; 271 272 /** The help button. */ 273 protected JButton _helpButton; 274 275 /** The cancel button. */ 276 protected JButton _cancelButton; 277 278 /////////////////////////////////////////////////////////////////// 279 //// private methods //// 280 281 /** Create the buttons panel. */ 282 private JPanel _createButtonsPanel() { 283 JPanel _buttons = new JPanel(); 284 285 _createExtendedButtons(_buttons); 286 _helpButton = new JButton("Help"); 287 _buttons.add(_helpButton); 288 _cancelButton = new JButton("Cancel"); 289 _buttons.add(_cancelButton); 290 291 for (int i = 0; i < _buttons.getComponentCount(); i++) { 292 ((JButton) _buttons.getComponent(i)).addActionListener(this); 293 } 294 295 return _buttons; 296 } 297 298 private void _deiconify() { 299 setExtendedState(Frame.NORMAL); 300 } 301 302 private void _iconify() { 303 setExtendedState(Frame.ICONIFIED); 304 } 305 306 /////////////////////////////////////////////////////////////////// 307 //// private members //// 308 private JComponent _contents; 309 310 /** The following is true if any of the values have been changed but not 311 * applied. 312 */ 313 private boolean _dirty = false; 314 315 private DialogTableau _dialogTableau; 316 317 private Frame _owner; 318 319 private Entity _target; 320}