001 /* 002 * The contents of this file are subject to the Mozilla Public License 003 * Version 1.1 (the "License"); you may not use this file except in 004 * compliance with the License. You may obtain a copy of the License at 005 * http://www.mozilla.org/MPL/ 006 * 007 * Software distributed under the License is distributed on an "AS IS" basis, 008 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for 009 * the specific language governing rights and limitations under the License. 010 * 011 * The Original Code is Protege-2000. 012 * 013 * The Initial Developer of the Original Code is Stanford University. Portions 014 * created by Stanford University are Copyright (C) 2006. All Rights Reserved. 015 * 016 * Protege was developed by Stanford Medical Informatics 017 * (http://www.smi.stanford.edu) at the Stanford University School of Medicine 018 * with support from the National Library of Medicine, the National Science 019 * Foundation, and the Defense Advanced Research Projects Agency. Current 020 * information about Protege can be obtained at http://protege.stanford.edu. 021 * 022 */ 023 024 package edu.uchsc.ccp.knowtator.ui; 025 026 import java.awt.BorderLayout; 027 import java.awt.Component; 028 import java.awt.Container; 029 import java.awt.Dialog; 030 import java.awt.FlowLayout; 031 import java.awt.Frame; 032 import java.awt.GridLayout; 033 import java.awt.Point; 034 import java.awt.Window; 035 import java.awt.event.ActionEvent; 036 import java.awt.event.KeyAdapter; 037 import java.awt.event.KeyEvent; 038 import java.awt.event.WindowAdapter; 039 import java.awt.event.WindowEvent; 040 041 import javax.swing.AbstractAction; 042 import javax.swing.Action; 043 import javax.swing.BorderFactory; 044 import javax.swing.JButton; 045 import javax.swing.JDialog; 046 import javax.swing.JPanel; 047 import javax.swing.SwingUtilities; 048 049 import edu.stanford.smi.protege.resource.LocalizedText; 050 import edu.stanford.smi.protege.resource.ResourceKey; 051 import edu.stanford.smi.protege.util.ComponentFactory; 052 import edu.stanford.smi.protege.util.ComponentUtilities; 053 import edu.stanford.smi.protege.util.Disposable; 054 import edu.stanford.smi.protege.util.MessagePanel; 055 import edu.stanford.smi.protege.util.StandardAction; 056 import edu.stanford.smi.protege.util.Validatable; 057 058 /** 059 * This code was copied directly from the Protege source code from 060 * edu.stanford.smi.protege.util.ModalDialog I copied the code so that I could 061 * modify it so that I could move the location of the where the dialog appears. 062 * 063 * A class to handle all modal dialog processing. This class just wraps the 064 * JDialog modal dialog implementation but adds some additional features such as 065 * a call back mechanism to stop an "OK". This class was originally written to 066 * work around the JDK 1.0 modal dialogs that didn't work at all. It also 067 * predates the JOptionPane stuff that is similar. 068 * 069 * @author Ray Fergerson <fergerson@smi.stanford.edu> 070 */ 071 public class ModalDialog extends JDialog implements Disposable { 072 073 static final long serialVersionUID = 0; 074 075 public static final int OPTION_OK = 1; 076 077 public static final int OPTION_YES = 2; 078 079 public static final int OPTION_NO = 3; 080 081 public static final int OPTION_CANCEL = 4; 082 083 public static final int OPTION_CLOSE = 5; 084 085 public static final int RESULT_ERROR = 6; 086 087 public static final int MODE_OK_CANCEL = 11; 088 089 public static final int MODE_YES_NO_CANCEL = 12; 090 091 public static final int MODE_YES_NO = 13; 092 093 public static final int MODE_CLOSE = 14; 094 095 private int _result; 096 097 private Component _panel; 098 099 private JPanel _buttonsPanel; 100 101 private CloseCallback _closeCallback; 102 103 private boolean _enableCloseButton; 104 105 private static ModalDialog _currentDialog; // used for testing 106 107 private static Point _location; 108 109 public static interface CloseCallback { 110 boolean canClose(int result); 111 } 112 113 private class WindowCloseListener extends WindowAdapter { 114 public void windowClosing(WindowEvent event) { 115 int option = OPTION_CANCEL; 116 if (!_enableCloseButton) { 117 int result = ModalDialog.showMessageDialog(ModalDialog.this, LocalizedText 118 .getText(ResourceKey.DIALOG_SAVE_CHANGES_TEXT), ModalDialog.MODE_YES_NO, null); 119 if (result == OPTION_YES) { 120 option = OPTION_OK; 121 } 122 } 123 attemptClose(option); 124 } 125 } 126 127 private ModalDialog(Dialog parent, Component panel, String title, int mode, CloseCallback callback, 128 boolean enableClose, Point location) { 129 super(parent, title, true); 130 init(panel, mode, callback, enableClose, location); 131 } 132 133 private ModalDialog(Frame parentFrame, Component panel, String title, int mode, CloseCallback callback, 134 boolean enableCloseButton, Point location) { 135 super(parentFrame, title, true); 136 init(panel, mode, callback, enableCloseButton, location); 137 } 138 139 public static void attemptDialogClose(int result) { 140 ModalDialog dialog = getCurrentDialog(); 141 if (dialog != null) { 142 dialog.attemptClose(result); 143 } 144 } 145 146 public void attemptClose(int result) { 147 _location = getLocation(); 148 boolean canClose; 149 if (_closeCallback == null) { 150 canClose = true; 151 } else { 152 canClose = _closeCallback.canClose(result); 153 } 154 if (canClose && result == OPTION_OK && _panel instanceof Validatable) { 155 Validatable validatable = (Validatable) _panel; 156 canClose = validatable.validateContents(); 157 if (canClose) { 158 validatable.saveContents(); 159 } 160 } 161 if (canClose) { 162 _result = result; 163 close(); 164 } 165 } 166 167 private void close() { 168 ComponentUtilities.dispose(this); 169 _currentDialog = null; 170 } 171 172 private JButton createButton(final int result, ResourceKey key) { 173 Action action = new StandardAction(key) { 174 public void actionPerformed(ActionEvent event) { 175 attemptClose(result); 176 } 177 }; 178 JButton button = ComponentFactory.createButton(action); 179 button.addKeyListener(new KeyAdapter() { 180 public void keyPressed(KeyEvent event) { 181 switch (event.getKeyCode()) { 182 case KeyEvent.VK_ENTER: 183 attemptClose(result); 184 break; 185 case KeyEvent.VK_ESCAPE: 186 attemptClose(OPTION_CANCEL); 187 break; 188 default: 189 // do nothing 190 break; 191 } 192 } 193 }); 194 return button; 195 } 196 197 private JPanel createButtonsPanel(int mode) { 198 JPanel buttonsGrid = ComponentFactory.createPanel(); 199 buttonsGrid.setLayout(new GridLayout(1, 3, 10, 10)); 200 switch (mode) { 201 case MODE_OK_CANCEL: 202 buttonsGrid.add(createButton(OPTION_OK, ResourceKey.OK_BUTTON_LABEL)); 203 buttonsGrid.add(createButton(OPTION_CANCEL, ResourceKey.CANCEL_BUTTON_LABEL)); 204 break; 205 case MODE_YES_NO: 206 buttonsGrid.add(createButton(OPTION_YES, ResourceKey.YES_BUTTON_LABEL)); 207 buttonsGrid.add(createButton(OPTION_NO, ResourceKey.NO_BUTTON_LABEL)); 208 break; 209 case MODE_YES_NO_CANCEL: 210 buttonsGrid.add(createButton(OPTION_YES, ResourceKey.YES_BUTTON_LABEL)); 211 buttonsGrid.add(createButton(OPTION_NO, ResourceKey.NO_BUTTON_LABEL)); 212 buttonsGrid.add(createButton(OPTION_CANCEL, ResourceKey.CANCEL_BUTTON_LABEL)); 213 break; 214 case MODE_CLOSE: 215 buttonsGrid.add(createButton(OPTION_CLOSE, ResourceKey.CLOSE_BUTTON_LABEL)); 216 break; 217 default: 218 // do nothing 219 break; 220 } 221 222 JPanel panel = ComponentFactory.createPanel(); 223 panel.setLayout(new FlowLayout()); 224 panel.add(buttonsGrid); 225 226 return panel; 227 } 228 229 public static ModalDialog getCurrentDialog() { 230 return _currentDialog; 231 } 232 233 // Doesn't work! 234 private void getFocus() { 235 SwingUtilities.invokeLater(new Runnable() { 236 public void run() { 237 JButton button = (JButton) ((Container) _buttonsPanel.getComponent(0)).getComponent(0); 238 button.requestFocus(); 239 } 240 }); 241 } 242 243 private void init(Component panel, int mode, CloseCallback callback, boolean enableCloseButton, Point location) { 244 _currentDialog = this; 245 _closeCallback = callback; 246 _enableCloseButton = enableCloseButton; 247 setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 248 addWindowListener(new WindowCloseListener()); 249 250 switch (mode) { 251 case MODE_OK_CANCEL: 252 _result = OPTION_CANCEL; 253 break; 254 case MODE_YES_NO_CANCEL: 255 _result = OPTION_CANCEL; 256 break; 257 case MODE_CLOSE: 258 _result = OPTION_CLOSE; 259 break; 260 default: 261 // do nothing 262 break; 263 } 264 265 _panel = panel; 266 _buttonsPanel = createButtonsPanel(mode); 267 268 layoutWidgets(); 269 270 pack(); 271 ComponentUtilities.center(this); 272 getFocus(); 273 if (location != null) { 274 _location = location; 275 setLocation(location); 276 } else if (_location != null) { 277 setLocation(_location); 278 } else { 279 _location = getLocation(); 280 } 281 setVisible(true); 282 } 283 284 private void layoutWidgets() { 285 JPanel borderedPanel = ComponentFactory.createPanel(); 286 borderedPanel.setLayout(new BorderLayout()); 287 borderedPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 288 borderedPanel.add(_panel); 289 290 getContentPane().setLayout(new BorderLayout()); 291 getContentPane().add(borderedPanel, BorderLayout.CENTER); 292 getContentPane().add(_buttonsPanel, BorderLayout.SOUTH); 293 } 294 295 public static int showDialog(Component parent, Component panel, String title, int mode, Point location) { 296 return showDialog(parent, panel, title, mode, null, location); 297 } 298 299 public static int showDialog(Component parent, Component panel, String title, int mode, CloseCallback callback, 300 Point location) { 301 return showDialog(parent, panel, title, mode, callback, true, location); 302 } 303 304 public static int showDialog(Component parent, Component panel, String title, int mode, CloseCallback callback, 305 boolean enableCloseButton, Point location) { 306 ModalDialog dialog; 307 Window window; 308 if (parent == null || parent instanceof Window) { 309 window = (Window) parent; 310 } else { 311 window = SwingUtilities.windowForComponent(parent); 312 } 313 if (window instanceof Frame || window == null) { 314 dialog = new ModalDialog((Frame) window, panel, title, mode, callback, enableCloseButton, location); 315 } else { 316 dialog = new ModalDialog((Dialog) window, panel, title, mode, callback, enableCloseButton, location); 317 } 318 int result; 319 if (dialog == null) { 320 result = RESULT_ERROR; 321 } else { 322 result = dialog._result; 323 } 324 return result; 325 } 326 327 public static void showMessageDialog(Component parent, String message, Point location) { 328 showMessageDialog(parent, message, ModalDialog.MODE_CLOSE, location); 329 } 330 331 public static void showMessageDialog(Component parent, String message, String title, Point location) { 332 showMessageDialog(parent, message, title, ModalDialog.MODE_CLOSE, location); 333 } 334 335 public static int showMessageDialog(Component parent, String message, int mode, Point location) { 336 return showDialog(parent, new MessagePanel(message), "", mode, location); 337 } 338 339 public static int showMessageDialog(Component parent, String message, String title, int mode, Point location) { 340 return showDialog(parent, new MessagePanel(message), title, mode, location); 341 } 342 343 public static Action getCloseAction(final Component c) { 344 return new AbstractAction() { 345 public void actionPerformed(ActionEvent event) { 346 Component root = SwingUtilities.getRoot(c); 347 if (root instanceof ModalDialog) { 348 ModalDialog dialog = (ModalDialog) root; 349 dialog.attemptClose(ModalDialog.OPTION_OK); 350 } 351 } 352 }; 353 } 354 355 } 356