2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
24 import java.awt.Component;
25 import java.awt.Container;
26 import java.awt.Dialog.ModalityType;
27 import java.awt.HeadlessException;
28 import java.awt.Window;
29 import java.awt.event.ActionEvent;
30 import java.awt.event.ActionListener;
31 import java.beans.PropertyChangeEvent;
32 import java.beans.PropertyChangeListener;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.HashMap;
36 import java.util.List;
38 import java.util.concurrent.Callable;
39 import java.util.concurrent.Executors;
41 import javax.swing.Icon;
42 import javax.swing.JButton;
43 import javax.swing.JDialog;
44 import javax.swing.JFrame;
45 import javax.swing.JInternalFrame;
46 import javax.swing.JOptionPane;
47 import javax.swing.JPanel;
48 import javax.swing.UIManager;
50 import jalview.util.Platform;
51 import jalview.util.dialogrunner.DialogRunnerI;
53 public class JvOptionPane extends JOptionPane
54 implements DialogRunnerI, PropertyChangeListener
56 private static final long serialVersionUID = -3019167117756785229L;
58 private static Object mockResponse = JOptionPane.CANCEL_OPTION;
60 private static boolean interactiveMode = true;
62 private Component parentComponent;
64 private Map<Object, Callable> callbacks = new HashMap<>();
67 * JalviewJS reports user choice in the dialog as the selected
68 * option (text); this list allows conversion to index (int)
70 List<Object> ourOptions;
72 public JvOptionPane(final Component parent)
74 this.parentComponent = Platform.isJS() ? this : parent;
77 public static int showConfirmDialog(Component parentComponent,
78 Object message) throws HeadlessException
80 // only called by test
81 return isInteractiveMode()
82 ? JOptionPane.showConfirmDialog(parentComponent, message)
83 : (int) getMockResponse();
87 * Message, title, optionType
89 * @param parentComponent
94 * @throws HeadlessException
96 public static int showConfirmDialog(Component parentComponent,
97 Object message, String title, int optionType)
98 throws HeadlessException
100 if (!isInteractiveMode())
102 return (int) getMockResponse();
106 case JOptionPane.YES_NO_CANCEL_OPTION:
107 // FeatureRenderer amendFeatures ?? TODO ??
112 case JOptionPane.YES_NO_OPTION:
113 // PromptUserConfig usage stats
114 // for now treated as "OK CANCEL"
116 case JOptionPane.OK_CANCEL_OPTION:
117 // will fall back to simple HTML
118 return JOptionPane.showConfirmDialog(parentComponent, message, title,
124 * Adds a message type. Fallback is to just add it in the beginning.
126 * @param parentComponent
132 * @throws HeadlessException
134 public static int showConfirmDialog(Component parentComponent,
135 Object message, String title, int optionType, int messageType)
136 throws HeadlessException
138 // JalviewServicesChanged
139 // PromptUserConfig raiseDialog
140 return isInteractiveMode()
141 ? JOptionPane.showConfirmDialog(parentComponent, message, title,
142 optionType, messageType)
143 : (int) getMockResponse();
149 * @param parentComponent
156 * @throws HeadlessException
158 public static int showConfirmDialog(Component parentComponent,
159 Object message, String title, int optionType, int messageType,
160 Icon icon) throws HeadlessException
162 // JvOptionPaneTest only
163 return isInteractiveMode()
164 ? JOptionPane.showConfirmDialog(parentComponent, message, title,
165 optionType, messageType, icon)
166 : (int) getMockResponse();
170 * Internal version "OK"
172 * @param parentComponent
176 public static int showInternalConfirmDialog(Component parentComponent,
179 // JvOptionPaneTest only;
180 return isInteractiveMode()
181 ? JOptionPane.showInternalConfirmDialog(parentComponent,
183 : (int) getMockResponse();
187 * Internal version -- changed to standard version for now
189 * @param parentComponent
195 public static int showInternalConfirmDialog(Component parentComponent,
196 String message, String title, int optionType)
198 if (!isInteractiveMode())
200 return (int) getMockResponse();
204 case JOptionPane.YES_NO_CANCEL_OPTION:
205 // ColourMenuHelper.addMenuItmers.offerRemoval TODO
206 case JOptionPane.YES_NO_OPTION:
207 // UserDefinedColoursSave -- relevant? TODO
210 case JOptionPane.OK_CANCEL_OPTION:
212 // EditNameDialog --- uses panel for messsage TODO
214 // Desktop.inputURLMenuItem
216 return JOptionPane.showConfirmDialog(parentComponent, message, title,
223 * @param parentComponent
230 public static int showInternalConfirmDialog(Component parentComponent,
231 Object message, String title, int optionType, int messageType)
233 if (!isInteractiveMode())
235 return (int) getMockResponse();
239 case JOptionPane.YES_NO_CANCEL_OPTION:
240 case JOptionPane.YES_NO_OPTION:
241 // UserQuestionanaireCheck
245 case JOptionPane.OK_CANCEL_OPTION:
246 // will fall back to simple HTML
247 return JOptionPane.showConfirmDialog(parentComponent, message, title,
248 optionType, messageType);
253 * adds icon; no longer internal
255 * @param parentComponent
263 public static int showInternalConfirmDialog(Component parentComponent,
264 Object message, String title, int optionType, int messageType,
267 if (!isInteractiveMode())
269 return (int) getMockResponse();
273 case JOptionPane.YES_NO_CANCEL_OPTION:
274 case JOptionPane.YES_NO_OPTION:
277 case JOptionPane.OK_CANCEL_OPTION:
278 // Preferences editLink/newLink
279 return JOptionPane.showConfirmDialog(parentComponent, message, title,
280 optionType, messageType, icon);
286 * custom options full-featured
288 * @param parentComponent
295 * @param initialValue
297 * @throws HeadlessException
299 public static int showOptionDialog(Component parentComponent,
300 String message, String title, int optionType, int messageType,
301 Icon icon, Object[] options, Object initialValue)
302 throws HeadlessException
304 if (!isInteractiveMode())
306 return (int) getMockResponse();
312 // 1) AlignViewport for openLinkedAlignment
314 // Show a dialog with the option to open and link (cDNA <-> protein) as a
316 // alignment, either as a standalone alignment or in a split frame. Returns
317 // true if the new alignment was opened, false if not, because the user
318 // declined the offer.
320 // 2) UserDefinedColors warning about saving over a name already defined
322 return JOptionPane.showOptionDialog(parentComponent, message, title,
323 optionType, messageType, icon, options, initialValue);
330 * @throws HeadlessException
332 public static void showMessageDialog(Component parentComponent,
333 String message) throws HeadlessException
335 if (!isInteractiveMode())
337 outputMessage(message);
343 JOptionPane.showMessageDialog(parentComponent, message);
347 * OK with message, title, and type
349 * @param parentComponent
353 * @throws HeadlessException
355 public static void showMessageDialog(Component parentComponent,
356 String message, String title, int messageType)
357 throws HeadlessException
359 // 30 implementations -- all just fine.
361 if (!isInteractiveMode())
363 outputMessage(message);
367 JOptionPane.showMessageDialog(parentComponent,
368 getPrefix(messageType) + message, title, messageType);
372 * adds title and icon
374 * @param parentComponent
379 * @throws HeadlessException
381 public static void showMessageDialog(Component parentComponent,
382 String message, String title, int messageType, Icon icon)
383 throws HeadlessException
388 if (!isInteractiveMode())
390 outputMessage(message);
394 JOptionPane.showMessageDialog(parentComponent, message, title,
402 public static void showInternalMessageDialog(Component parentComponent,
406 // WsPreferences only
408 if (!isInteractiveMode())
410 outputMessage(message);
414 JOptionPane.showMessageDialog(parentComponent, message);
418 * Adds title and messageType
420 * @param parentComponent
425 public static void showInternalMessageDialog(Component parentComponent,
426 String message, String title, int messageType)
431 if (!isInteractiveMode())
433 outputMessage(message);
437 JOptionPane.showMessageDialog(parentComponent,
438 getPrefix(messageType) + message, title, messageType);
443 * @param parentComponent
449 public static void showInternalMessageDialog(Component parentComponent,
450 Object message, String title, int messageType, Icon icon)
455 if (!isInteractiveMode())
457 outputMessage(message);
461 JOptionPane.showMessageDialog(parentComponent, message, title,
469 * @throws HeadlessException
471 public static String showInputDialog(Object message)
472 throws HeadlessException
476 if (!isInteractiveMode())
478 return getMockResponse().toString();
481 return JOptionPane.showInputDialog(message);
485 * adds inital selection value
488 * @param initialSelectionValue
491 public static String showInputDialog(String message,
492 String initialSelectionValue)
494 if (!isInteractiveMode())
496 return getMockResponse().toString();
499 // AnnotationPanel character option
501 return JOptionPane.showInputDialog(message, initialSelectionValue);
505 * adds inital selection value
508 * @param initialSelectionValue
511 public static String showInputDialog(Object message,
512 Object initialSelectionValue)
514 if (!isInteractiveMode())
516 return getMockResponse().toString();
519 // AnnotationPanel character option
521 return JOptionPane.showInputDialog(message, initialSelectionValue);
527 * @param parentComponent
530 * @throws HeadlessException
532 public static String showInputDialog(Component parentComponent,
533 String message) throws HeadlessException
537 return isInteractiveMode()
538 ? JOptionPane.showInputDialog(parentComponent, message)
539 : getMockResponse().toString();
543 * input with initial selection
545 * @param parentComponent
547 * @param initialSelectionValue
550 public static String showInputDialog(Component parentComponent,
551 String message, String initialSelectionValue)
556 return isInteractiveMode()
557 ? JOptionPane.showInputDialog(parentComponent, message,
558 initialSelectionValue)
559 : getMockResponse().toString();
563 * input with initial selection
565 * @param parentComponent
567 * @param initialSelectionValue
570 public static String showInputDialog(Component parentComponent,
571 Object message, Object initialSelectionValue)
576 return isInteractiveMode()
577 ? JOptionPane.showInputDialog(parentComponent, message,
578 initialSelectionValue)
579 : getMockResponse().toString();
584 * @param parentComponent
589 * @throws HeadlessException
591 public static String showInputDialog(Component parentComponent,
592 String message, String title, int messageType)
593 throws HeadlessException
598 return isInteractiveMode()
599 ? JOptionPane.showInputDialog(parentComponent, message, title,
601 : getMockResponse().toString();
605 * Customized input option
607 * @param parentComponent
612 * @param selectionValues
613 * @param initialSelectionValue
615 * @throws HeadlessException
617 public static Object showInputDialog(Component parentComponent,
618 Object message, String title, int messageType, Icon icon,
619 Object[] selectionValues, Object initialSelectionValue)
620 throws HeadlessException
625 return isInteractiveMode()
626 ? JOptionPane.showInputDialog(parentComponent, message, title,
627 messageType, icon, selectionValues,
628 initialSelectionValue)
629 : getMockResponse().toString();
635 * @param parentComponent
639 public static String showInternalInputDialog(Component parentComponent,
644 return isInteractiveMode()
645 ? JOptionPane.showInternalInputDialog(parentComponent, message)
646 : getMockResponse().toString();
650 * internal with title and messageType
652 * @param parentComponent
658 public static String showInternalInputDialog(Component parentComponent,
659 String message, String title, int messageType)
662 // AlignFrame tabbedPane_mousePressed
664 return isInteractiveMode()
665 ? JOptionPane.showInternalInputDialog(parentComponent,
666 getPrefix(messageType) + message, title, messageType)
667 : getMockResponse().toString();
671 * customized internal
673 * @param parentComponent
678 * @param selectionValues
679 * @param initialSelectionValue
682 public static Object showInternalInputDialog(Component parentComponent,
683 String message, String title, int messageType, Icon icon,
684 Object[] selectionValues, Object initialSelectionValue)
688 return isInteractiveMode()
689 ? JOptionPane.showInternalInputDialog(parentComponent, message,
690 title, messageType, icon, selectionValues,
691 initialSelectionValue)
692 : getMockResponse().toString();
695 ///////////// end of options ///////////////
697 private static void outputMessage(Object message)
699 System.out.println(">>> JOption Message : " + message.toString());
702 public static Object getMockResponse()
707 public static void setMockResponse(Object mockOption)
709 JvOptionPane.mockResponse = mockOption;
712 public static void resetMock()
714 setMockResponse(JOptionPane.CANCEL_OPTION);
715 setInteractiveMode(true);
718 public static boolean isInteractiveMode()
720 return interactiveMode;
723 public static void setInteractiveMode(boolean interactive)
725 JvOptionPane.interactiveMode = interactive;
728 private static String getPrefix(int messageType)
737 case JOptionPane.WARNING_MESSAGE:
738 prefix = "WARNING! ";
740 case JOptionPane.ERROR_MESSAGE:
751 * create a new option dialog that can be used to register responses - along
752 * lines of showOptionDialog
757 * @param defaultOption
758 * @param plainMessage
764 public static JvOptionPane newOptionDialog()
766 return new JvOptionPane(null);
769 public static JvOptionPane newOptionDialog(Component parentComponent)
771 return new JvOptionPane(parentComponent);
774 public void showDialog(String message, String title, int optionType,
775 int messageType, Icon icon, Object[] options, Object initialValue)
777 showDialog(message, title, optionType, messageType, icon, options,
781 public void showDialog(Object message, String title, int optionType,
782 int messageType, Icon icon, Object[] options, Object initialValue,
785 showDialog(message, title, optionType, messageType, icon, options,
786 initialValue, modal, null);
789 public void showDialog(Object message, String title, int optionType,
790 int messageType, Icon icon, Object[] options, Object initialValue,
791 boolean modal, JButton[] buttons)
793 if (!isInteractiveMode())
795 handleResponse(getMockResponse());
801 // 1) AlignViewport for openLinkedAlignment
803 // Show a dialog with the option to open and link (cDNA <-> protein) as a
805 // alignment, either as a standalone alignment or in a split frame. Returns
806 // true if the new alignment was opened, false if not, because the user
807 // declined the offer.
809 // 2) UserDefinedColors warning about saving over a name already defined
812 ourOptions = Arrays.asList(options);
816 boolean useButtons = false;
817 Object initialValueButton = null;
818 NOTNULL: if (buttons != null)
820 if (buttons.length != options.length)
822 jalview.bin.Console.error(
823 "Supplied buttons array not the same length as supplied options array.");
826 int[] buttonActions = { JOptionPane.YES_OPTION,
827 JOptionPane.NO_OPTION, JOptionPane.CANCEL_OPTION };
828 for (int i = 0; i < options.length; i++)
830 Object o = options[i];
831 jalview.bin.Console.debug(
832 "Setting button " + i + " to '" + o.toString() + "'");
833 JButton jb = buttons[i];
835 if (o.equals(initialValue))
836 initialValueButton = jb;
838 int buttonAction = buttonActions[i];
839 Callable action = callbacks.get(buttonAction);
840 jb.setText((String) o);
841 jb.addActionListener(new ActionListener()
844 public void actionPerformed(ActionEvent e)
847 Object obj = e.getSource();
848 Object joptionpaneObject = getAncestorClass(obj,
850 if (joptionpaneObject == null
851 || !(joptionpaneObject instanceof JOptionPane))
853 jalview.bin.Console.debug(
854 "Could not find JOptionPane ancestor of event object "
858 JOptionPane joptionpane = (JOptionPane) joptionpaneObject;
859 joptionpane.setValue(buttonAction);
861 Executors.newSingleThreadExecutor().submit(action);
862 // joptionpane.transferFocusBackward();
863 joptionpane.transferFocusBackward();
864 joptionpane.setVisible(false);
865 // put focus and raise parent window if possible, unless cancel
867 boolean raiseParent = (parentComponent != null);
868 if (buttonAction == JOptionPane.CANCEL_OPTION)
870 if (optionType == JOptionPane.YES_NO_OPTION
871 && buttonAction == JOptionPane.NO_OPTION)
875 parentComponent.requestFocus();
876 if (parentComponent instanceof JInternalFrame)
878 JInternalFrame jif = (JInternalFrame) parentComponent;
883 else if (parentComponent instanceof Window)
885 Window w = (Window) parentComponent;
890 joptionpane.setVisible(false);
897 // use a JOptionPane as usual
898 int response = JOptionPane.showOptionDialog(parentComponent, message,
899 title, optionType, messageType, icon,
900 useButtons ? buttons : options,
901 useButtons ? initialValueButton : initialValue);
904 * In Java, the response is returned to this thread and handled here;
905 * (for Javascript, see propertyChange)
907 if (!Platform.isJS())
914 handleResponse(response);
920 * This is java similar to the swingjs handling, with the callbacks
921 * attached to the button press of the dialog. This means we can use
922 * a non-modal JDialog for the confirmation without blocking the GUI.
925 JDialog dialog = createDialog(parentComponent, message, title,
926 optionType, messageType, icon, options, initialValue, modal,
928 jalview.bin.Console.debug("About to setVisible(true)");
929 dialog.setVisible(true);
930 jalview.bin.Console.debug("Just setVisible(true)");
934 public void showInternalDialog(JPanel mainPanel, String title,
935 int yesNoCancelOption, int questionMessage, Icon icon,
936 Object[] options, String initresponse)
938 if (!isInteractiveMode())
940 handleResponse(getMockResponse());
943 ourOptions = Arrays.asList(options);
945 if (parentComponent != this)
947 response = JOptionPane.showInternalOptionDialog(parentComponent,
948 mainPanel, title, yesNoCancelOption, questionMessage, icon,
949 options, initresponse);
953 response = JOptionPane.showOptionDialog(parentComponent, mainPanel,
954 title, yesNoCancelOption, questionMessage, icon, options,
957 if (!Platform.isJS())
964 handleResponse(response);
970 public JvOptionPane setResponseHandler(Object response, Runnable action)
972 callbacks.put(response, new Callable<Void>()
985 public JvOptionPane setResponseHandler(Object response, Callable action)
987 callbacks.put(response, action);
992 * showDialogOnTop will create a dialog that (attempts to) come to top of OS
995 public static int showDialogOnTop(String label, String actionString,
996 int JOPTIONPANE_OPTION, int JOPTIONPANE_MESSAGETYPE)
998 // Ensure Jalview window is brought to front (primarily for Quit
999 // confirmation window to be visible)
1001 // This method of raising the Jalview window is broken in java
1002 // jalviewDesktop.setVisible(true);
1003 // jalviewDesktop.toFront();
1005 // A better hack which works is to create a new JFrame parent with
1006 // setAlwaysOnTop(true)
1007 JFrame dialogParent = new JFrame();
1008 dialogParent.setAlwaysOnTop(true);
1010 int answer = JOptionPane.showConfirmDialog(dialogParent, label,
1011 actionString, JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE);
1013 dialogParent.setAlwaysOnTop(false);
1014 dialogParent.dispose();
1019 public void showDialogOnTopAsync(String label, String actionString,
1020 int JOPTIONPANE_OPTION, int JOPTIONPANE_MESSAGETYPE, Icon icon,
1021 Object[] options, Object initialValue, boolean modal)
1023 showDialogOnTopAsync(new JFrame(), label, actionString,
1024 JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE, icon, options,
1025 initialValue, modal);
1028 public void showDialogOnTopAsync(JFrame dialogParent, Object label,
1029 String actionString, int JOPTIONPANE_OPTION,
1030 int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options,
1031 Object initialValue, boolean modal)
1033 showDialogOnTopAsync(dialogParent, label, actionString,
1034 JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE, icon, options,
1035 initialValue, modal, null);
1038 public void showDialogOnTopAsync(JFrame dialogParent, Object label,
1039 String actionString, int JOPTIONPANE_OPTION,
1040 int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options,
1041 Object initialValue, boolean modal, JButton[] buttons)
1043 // Ensure Jalview window is brought to front (primarily for Quit
1044 // confirmation window to be visible)
1046 // This method of raising the Jalview window is broken in java
1047 // jalviewDesktop.setVisible(true);
1048 // jalviewDesktop.toFront();
1050 // A better hack which works is to create a new JFrame parent with
1051 // setAlwaysOnTop(true)
1052 dialogParent.setAlwaysOnTop(true);
1053 parentComponent = dialogParent;
1055 showDialog(label, actionString, JOPTIONPANE_OPTION,
1056 JOPTIONPANE_MESSAGETYPE, icon, options, initialValue, modal,
1059 dialogParent.setAlwaysOnTop(false);
1060 dialogParent.dispose();
1064 * JalviewJS signals option selection by a property change event for the
1065 * option e.g. "OK". This methods responds to that by running the response
1066 * action that corresponds to that option.
1071 public void propertyChange(PropertyChangeEvent evt)
1073 Object newValue = evt.getNewValue();
1074 int ourOption = ourOptions.indexOf(newValue);
1077 handleResponse(ourOption);
1082 handleResponse(newValue);
1087 public void handleResponse(Object response)
1090 * this test is for NaN in Chrome
1092 if (response != null && !response.equals(response))
1096 Callable<Void> action = callbacks.get(response);
1102 } catch (Exception e)
1104 e.printStackTrace();
1106 if (parentComponent != null)
1107 parentComponent.requestFocus();
1112 * Create a non-modal confirm dialog
1114 public JDialog createDialog(Component parentComponent, Object message,
1115 String title, int optionType, int messageType, Icon icon,
1116 Object[] options, Object initialValue, boolean modal)
1118 return createDialog(parentComponent, message, title, optionType,
1119 messageType, icon, options, initialValue, modal, null);
1122 public JDialog createDialog(Component parentComponent, Object message,
1123 String title, int optionType, int messageType, Icon icon,
1124 Object[] options, Object initialValue, boolean modal,
1127 JButton[] optionsButtons = null;
1128 Object initialValueButton = null;
1129 JOptionPane joptionpane = new JOptionPane();
1130 // Make button options
1131 int[] buttonActions = { JOptionPane.YES_OPTION, JOptionPane.NO_OPTION,
1132 JOptionPane.CANCEL_OPTION };
1134 // we need the strings to make the buttons with actionEventListener
1135 if (options == null)
1137 ArrayList<String> options_default = new ArrayList<>();
1138 options_default.add(UIManager.getString("OptionPane.yesButtonText"));
1139 if (optionType == JOptionPane.YES_NO_OPTION
1140 || optionType == JOptionPane.YES_NO_CANCEL_OPTION)
1142 options_default.add(UIManager.getString("OptionPane.noButtonText"));
1144 if (optionType == JOptionPane.YES_NO_CANCEL_OPTION)
1147 .add(UIManager.getString("OptionPane.cancelButtonText"));
1149 options = options_default.toArray();
1151 if (!Platform.isJS()) // JalviewJS already uses callback, don't need to
1154 if (((optionType == JOptionPane.YES_OPTION
1155 || optionType == JOptionPane.NO_OPTION
1156 || optionType == JOptionPane.CANCEL_OPTION
1157 || optionType == JOptionPane.OK_OPTION
1158 || optionType == JOptionPane.DEFAULT_OPTION)
1159 && options.length < 1)
1160 || ((optionType == JOptionPane.YES_NO_OPTION
1161 || optionType == JOptionPane.OK_CANCEL_OPTION)
1162 && options.length < 2)
1163 || (optionType == JOptionPane.YES_NO_CANCEL_OPTION
1164 && options.length < 3))
1167 .debug("JvOptionPane: not enough options for dialog type");
1169 optionsButtons = new JButton[options.length];
1170 for (int i = 0; i < options.length && i < 3; i++)
1172 Object o = options[i];
1173 int buttonAction = buttonActions[i];
1174 Callable action = callbacks.get(buttonAction);
1176 if (buttons != null && buttons.length > i && buttons[i] != null)
1184 jb.setText((String) o);
1185 jb.addActionListener(new ActionListener()
1188 public void actionPerformed(ActionEvent e)
1190 joptionpane.setValue(buttonAction);
1192 Executors.newSingleThreadExecutor().submit(action);
1193 // joptionpane.transferFocusBackward();
1194 joptionpane.transferFocusBackward();
1195 joptionpane.setVisible(false);
1196 // put focus and raise parent window if possible, unless cancel
1198 boolean raiseParent = (parentComponent != null);
1199 if (buttonAction == JOptionPane.CANCEL_OPTION)
1200 raiseParent = false;
1201 if (optionType == JOptionPane.YES_NO_OPTION
1202 && buttonAction == JOptionPane.NO_OPTION)
1203 raiseParent = false;
1206 parentComponent.requestFocus();
1207 if (parentComponent instanceof JInternalFrame)
1209 JInternalFrame jif = (JInternalFrame) parentComponent;
1214 else if (parentComponent instanceof Window)
1216 Window w = (Window) parentComponent;
1221 joptionpane.setVisible(false);
1224 optionsButtons[i] = jb;
1225 if (o.equals(initialValue))
1226 initialValueButton = jb;
1229 joptionpane.setMessage(message);
1230 joptionpane.setMessageType(messageType);
1231 joptionpane.setOptionType(optionType);
1232 joptionpane.setIcon(icon);
1233 joptionpane.setOptions(Platform.isJS() ? options : optionsButtons);
1234 joptionpane.setInitialValue(
1235 Platform.isJS() ? initialValue : initialValueButton);
1237 JDialog dialog = joptionpane.createDialog(parentComponent, title);
1238 dialog.setModalityType(
1239 modal ? ModalityType.APPLICATION_MODAL : ModalityType.MODELESS);
1240 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
1245 * Utility to programmatically click a button on a JOptionPane (as a JFrame)
1247 * returns true if button was found
1249 public static boolean clickButton(JFrame frame, int buttonType)
1256 * Get parent JOptionPane if there is one
1258 public static Container getAncestorClass(Object o, Class cl)
1261 if (o instanceof Container)
1265 Container p = c.getParent();
1268 if (p.getClass() == cl)
1272 else if (p instanceof Component)
1274 return getAncestorClass((Component) p, cl);