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