1. Project Clover database Fri Dec 6 2024 13:47:14 GMT
  2. Package jalview.gui

File JvOptionPane.java

 

Coverage histogram

../../img/srcFileCovDistChart3.png
52% of files have more coverage

Code metrics

238
459
69
1
1,754
1,145
240
0.52
6.65
69
3.48

Classes

Class
Line #
Actions
JvOptionPane 71 459 240
0.2428198524.3%
 

Contributing tests

This file is covered by 40 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
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.
11    *
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.
16    *
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.
20    */
21    package jalview.gui;
22   
23    import java.awt.AWTEvent;
24    import java.awt.ActiveEvent;
25    import java.awt.Component;
26    import java.awt.Container;
27    import java.awt.Dialog.ModalityType;
28    import java.awt.EventQueue;
29    import java.awt.HeadlessException;
30    import java.awt.MenuComponent;
31    import java.awt.Toolkit;
32    import java.awt.Window;
33    import java.awt.event.ActionEvent;
34    import java.awt.event.ActionListener;
35    import java.awt.event.KeyEvent;
36    import java.awt.event.MouseAdapter;
37    import java.awt.event.MouseMotionAdapter;
38    import java.beans.PropertyChangeEvent;
39    import java.beans.PropertyChangeListener;
40    import java.beans.PropertyVetoException;
41    import java.util.ArrayList;
42    import java.util.Arrays;
43    import java.util.HashMap;
44    import java.util.List;
45    import java.util.Map;
46    import java.util.concurrent.ExecutorService;
47    import java.util.concurrent.Executors;
48   
49    import javax.swing.Icon;
50    import javax.swing.JButton;
51    import javax.swing.JDialog;
52    import javax.swing.JFrame;
53    import javax.swing.JInternalFrame;
54    import javax.swing.JLayeredPane;
55    import javax.swing.JMenu;
56    import javax.swing.JMenuBar;
57    import javax.swing.JOptionPane;
58    import javax.swing.JPanel;
59    import javax.swing.JRootPane;
60    import javax.swing.SwingUtilities;
61    import javax.swing.UIManager;
62    import javax.swing.event.InternalFrameEvent;
63    import javax.swing.event.InternalFrameListener;
64   
65    import jalview.bin.Console;
66    import jalview.util.ChannelProperties;
67    import jalview.util.MessageManager;
68    import jalview.util.Platform;
69    import jalview.util.dialogrunner.DialogRunnerI;
70   
 
71    public class JvOptionPane extends JOptionPane
72    implements DialogRunnerI, PropertyChangeListener
73    {
74    private static final long serialVersionUID = -3019167117756785229L;
75   
76    private static Object mockResponse = JvOptionPane.CANCEL_OPTION;
77   
78    private static boolean interactiveMode = true;
79   
80    public static final Runnable NULLCALLABLE = () -> {
81    };
82   
83    private Component parentComponent;
84   
85    private ExecutorService executor = Executors.newCachedThreadPool();
86   
87    private JDialog dialog = null;
88   
89    private Map<Object, Runnable> callbacks = new HashMap<>();
90   
91    private int timeout = -1;
92   
 
93  1 toggle public void setTimeout(int i)
94    {
95  1 timeout = i;
96    }
97   
98    /*
99    * JalviewJS reports user choice in the dialog as the selected option (text);
100    * this list allows conversion to index (int)
101    */
102    List<Object> ourOptions;
103   
 
104  5 toggle public JvOptionPane(final Component parent)
105    {
106  5 this.parentComponent = Platform.isJS() ? this : parent;
107  5 this.setIcon(null);
108    }
109   
 
110  1 toggle public static int showConfirmDialog(Component parentComponent,
111    Object message) throws HeadlessException
112    {
113    // only called by test
114  1 return isInteractiveMode()
115    ? JOptionPane.showConfirmDialog(parentComponent, message)
116    : (int) getMockResponse();
117    }
118   
119    /**
120    * Message, title, optionType
121    *
122    * @param parentComponent
123    * @param message
124    * @param title
125    * @param optionType
126    * @return
127    * @throws HeadlessException
128    */
 
129  1 toggle public static int showConfirmDialog(Component parentComponent,
130    Object message, String title, int optionType)
131    throws HeadlessException
132    {
133  1 if (!isInteractiveMode())
134    {
135  1 return (int) getMockResponse();
136    }
137  0 switch (optionType)
138    {
139  0 case JvOptionPane.YES_NO_CANCEL_OPTION:
140    // FeatureRenderer amendFeatures ?? TODO ??
141    // Chimera close
142    // PromptUserConfig
143    // $FALL-THROUGH$
144  0 default:
145  0 case JvOptionPane.YES_NO_OPTION:
146    // PromptUserConfig usage stats
147    // for now treated as "OK CANCEL"
148    // $FALL-THROUGH$
149  0 case JvOptionPane.OK_CANCEL_OPTION:
150    // will fall back to simple HTML
151  0 return JOptionPane.showConfirmDialog(parentComponent, message, title,
152    optionType);
153    }
154    }
155   
156    /**
157    * Adds a message type. Fallback is to just add it in the beginning.
158    *
159    * @param parentComponent
160    * @param message
161    * @param title
162    * @param optionType
163    * @param messageType
164    * @return
165    * @throws HeadlessException
166    */
 
167  37 toggle public static int showConfirmDialog(Component parentComponent,
168    Object message, String title, int optionType, int messageType)
169    throws HeadlessException
170    {
171    // JalviewServicesChanged
172    // PromptUserConfig raiseDialog
173  37 return isInteractiveMode()
174    ? JOptionPane.showConfirmDialog(parentComponent, message, title,
175    optionType, messageType)
176    : (int) getMockResponse();
177    }
178   
179    /**
180    * Adds an icon
181    *
182    * @param parentComponent
183    * @param message
184    * @param title
185    * @param optionType
186    * @param messageType
187    * @param icon
188    * @return
189    * @throws HeadlessException
190    */
 
191  1 toggle public static int showConfirmDialog(Component parentComponent,
192    Object message, String title, int optionType, int messageType,
193    Icon icon) throws HeadlessException
194    {
195    // JvOptionPaneTest only
196  1 return isInteractiveMode()
197    ? JOptionPane.showConfirmDialog(parentComponent, message, title,
198    optionType, messageType, icon)
199    : (int) getMockResponse();
200    }
201   
202    /**
203    * Internal version "OK"
204    *
205    * @param parentComponent
206    * @param message
207    * @return
208    */
 
209  1 toggle public static int showInternalConfirmDialog(Component parentComponent,
210    Object message)
211    {
212    // JvOptionPaneTest only;
213  1 return isInteractiveMode()
214    ? JOptionPane.showInternalConfirmDialog(parentComponent,
215    message)
216    : (int) getMockResponse();
217    }
218   
219    /**
220    * Internal version -- changed to standard version for now
221    *
222    * @param parentComponent
223    * @param message
224    * @param title
225    * @param optionType
226    * @return
227    */
 
228  1 toggle public static int showInternalConfirmDialog(Component parentComponent,
229    String message, String title, int optionType)
230    {
231  1 if (!isInteractiveMode())
232    {
233  1 return (int) getMockResponse();
234    }
235  0 switch (optionType)
236    {
237  0 case JvOptionPane.YES_NO_CANCEL_OPTION:
238    // ColourMenuHelper.addMenuItmers.offerRemoval TODO
239  0 case JvOptionPane.YES_NO_OPTION:
240    // UserDefinedColoursSave -- relevant? TODO
241    // $FALL-THROUGH$
242  0 default:
243  0 case JvOptionPane.OK_CANCEL_OPTION:
244   
245    // EditNameDialog --- uses panel for messsage TODO
246   
247    // Desktop.inputURLMenuItem
248    // WsPreferenses
249  0 return JOptionPane.showConfirmDialog(parentComponent, message, title,
250    optionType);
251    }
252    }
253   
254    /**
255    *
256    * @param parentComponent
257    * @param message
258    * @param title
259    * @param optionType
260    * @param messageType
261    * @return
262    */
 
263  1 toggle public static int showInternalConfirmDialog(Component parentComponent,
264    Object message, String title, int optionType, int messageType)
265    {
266  1 if (!isInteractiveMode())
267    {
268  1 return (int) getMockResponse();
269    }
270  0 switch (optionType)
271    {
272  0 case JvOptionPane.YES_NO_CANCEL_OPTION:
273  0 case JvOptionPane.YES_NO_OPTION:
274    // UserQuestionanaireCheck
275    // VamsasApplication
276    // $FALL-THROUGH$
277  0 default:
278  0 case JvOptionPane.OK_CANCEL_OPTION:
279    // will fall back to simple HTML
280  0 return JOptionPane.showConfirmDialog(parentComponent, message, title,
281    optionType, messageType);
282    }
283    }
284   
285    /**
286    * adds icon; no longer internal
287    *
288    * @param parentComponent
289    * @param message
290    * @param title
291    * @param optionType
292    * @param messageType
293    * @param icon
294    * @return
295    */
 
296  1 toggle public static int showInternalConfirmDialog(Component parentComponent,
297    Object message, String title, int optionType, int messageType,
298    Icon icon)
299    {
300  1 if (!isInteractiveMode())
301    {
302  1 return (int) getMockResponse();
303    }
304  0 switch (optionType)
305    {
306  0 case JvOptionPane.YES_NO_CANCEL_OPTION:
307  0 case JvOptionPane.YES_NO_OPTION:
308    //$FALL-THROUGH$
309  0 default:
310  0 case JvOptionPane.OK_CANCEL_OPTION:
311    // Preferences editLink/newLink
312  0 return JOptionPane.showConfirmDialog(parentComponent, message, title,
313    optionType, messageType, icon);
314    }
315   
316    }
317   
318    /**
319    * custom options full-featured
320    *
321    * @param parentComponent
322    * @param message
323    * @param title
324    * @param optionType
325    * @param messageType
326    * @param icon
327    * @param options
328    * @param initialValue
329    * @return
330    * @throws HeadlessException
331    */
 
332  0 toggle public static int showOptionDialog(Component parentComponent,
333    String message, String title, int optionType, int messageType,
334    Icon icon, Object[] options, Object initialValue)
335    throws HeadlessException
336    {
337  0 if (!isInteractiveMode())
338    {
339  0 return (int) getMockResponse();
340    }
341    // two uses:
342    //
343    // TODO
344    //
345    // 1) AlignViewport for openLinkedAlignment
346    //
347    // Show a dialog with the option to open and link (cDNA <-> protein) as a
348    // new
349    // alignment, either as a standalone alignment or in a split frame. Returns
350    // true if the new alignment was opened, false if not, because the user
351    // declined the offer.
352    //
353    // 2) UserDefinedColors warning about saving over a name already defined
354    //
355  0 return JOptionPane.showOptionDialog(parentComponent, message, title,
356    optionType, messageType, icon, options, initialValue);
357    }
358   
359    /**
360    * Just an OK message
361    *
362    * @param message
363    * @throws HeadlessException
364    */
 
365  1 toggle public static void showMessageDialog(Component parentComponent,
366    String message) throws HeadlessException
367    {
368  1 if (!isInteractiveMode())
369    {
370  1 outputMessage(message);
371  1 return;
372    }
373   
374    // test class only
375   
376  0 JOptionPane.showMessageDialog(parentComponent, message);
377    }
378   
379    /**
380    * OK with message, title, and type
381    *
382    * @param parentComponent
383    * @param message
384    * @param title
385    * @param messageType
386    * @throws HeadlessException
387    */
 
388  3 toggle public static void showMessageDialog(Component parentComponent,
389    String message, String title, int messageType)
390    throws HeadlessException
391    {
392    // 30 implementations -- all just fine.
393   
394  3 if (!isInteractiveMode())
395    {
396  3 outputMessage(message);
397  3 return;
398    }
399   
400  0 JOptionPane.showMessageDialog(parentComponent,
401    getPrefix(messageType) + message, title, messageType);
402    }
403   
404    /**
405    * adds title and icon
406    *
407    * @param parentComponent
408    * @param message
409    * @param title
410    * @param messageType
411    * @param icon
412    * @throws HeadlessException
413    */
 
414  1 toggle public static void showMessageDialog(Component parentComponent,
415    String message, String title, int messageType, Icon icon)
416    throws HeadlessException
417    {
418   
419    // test only
420   
421  1 if (!isInteractiveMode())
422    {
423  1 outputMessage(message);
424  1 return;
425    }
426   
427  0 JOptionPane.showMessageDialog(parentComponent, message, title,
428    messageType, icon);
429    }
430   
431    /**
432    * was internal
433    *
434    */
 
435  1 toggle public static void showInternalMessageDialog(Component parentComponent,
436    Object message)
437    {
438   
439    // WsPreferences only
440   
441  1 if (!isInteractiveMode())
442    {
443  1 outputMessage(message);
444  1 return;
445    }
446   
447  0 JOptionPane.showMessageDialog(parentComponent, message);
448    }
449   
450    /**
451    * Adds title and messageType
452    *
453    * @param parentComponent
454    * @param message
455    * @param title
456    * @param messageType
457    */
 
458  2 toggle public static void showInternalMessageDialog(Component parentComponent,
459    String message, String title, int messageType)
460    {
461   
462    // 41 references
463   
464  2 if (!isInteractiveMode())
465    {
466  2 outputMessage(message);
467  2 return;
468    }
469   
470  0 JOptionPane.showMessageDialog(parentComponent,
471    getPrefix(messageType) + message, title, messageType);
472    }
473   
474    /**
475    *
476    * @param parentComponent
477    * @param message
478    * @param title
479    * @param messageType
480    * @param icon
481    */
 
482  1 toggle public static void showInternalMessageDialog(Component parentComponent,
483    Object message, String title, int messageType, Icon icon)
484    {
485   
486    // test only
487   
488  1 if (!isInteractiveMode())
489    {
490  1 outputMessage(message);
491  1 return;
492    }
493   
494  0 JOptionPane.showMessageDialog(parentComponent, message, title,
495    messageType, icon);
496    }
497   
498    /**
499    *
500    * @param message
501    * @return
502    * @throws HeadlessException
503    */
 
504  1 toggle public static String showInputDialog(Object message)
505    throws HeadlessException
506    {
507    // test only
508   
509  1 if (!isInteractiveMode())
510    {
511  1 return getMockResponse().toString();
512    }
513   
514  0 return JOptionPane.showInputDialog(message);
515    }
516   
517    /**
518    * adds inital selection value
519    *
520    * @param message
521    * @param initialSelectionValue
522    * @return
523    */
 
524  0 toggle public static String showInputDialog(String message,
525    String initialSelectionValue)
526    {
527  0 if (!isInteractiveMode())
528    {
529  0 return getMockResponse().toString();
530    }
531   
532    // AnnotationPanel character option
533   
534  0 return JOptionPane.showInputDialog(message, initialSelectionValue);
535    }
536   
537    /**
538    * adds inital selection value
539    *
540    * @param message
541    * @param initialSelectionValue
542    * @return
543    */
 
544  1 toggle public static String showInputDialog(Object message,
545    Object initialSelectionValue)
546    {
547  1 if (!isInteractiveMode())
548    {
549  1 return getMockResponse().toString();
550    }
551   
552    // AnnotationPanel character option
553   
554  0 return JOptionPane.showInputDialog(message, initialSelectionValue);
555    }
556   
557    /**
558    * centered on parent
559    *
560    * @param parentComponent
561    * @param message
562    * @return
563    * @throws HeadlessException
564    */
 
565  1 toggle public static String showInputDialog(Component parentComponent,
566    String message) throws HeadlessException
567    {
568    // test only
569   
570  1 return isInteractiveMode()
571    ? JOptionPane.showInputDialog(parentComponent, message)
572    : getMockResponse().toString();
573    }
574   
575    /**
576    * input with initial selection
577    *
578    * @param parentComponent
579    * @param message
580    * @param initialSelectionValue
581    * @return
582    */
 
583  0 toggle public static String showInputDialog(Component parentComponent,
584    String message, String initialSelectionValue)
585    {
586   
587    // AnnotationPanel
588   
589  0 return isInteractiveMode()
590    ? JOptionPane.showInputDialog(parentComponent, message,
591    initialSelectionValue)
592    : getMockResponse().toString();
593    }
594   
595    /**
596    * input with initial selection
597    *
598    * @param parentComponent
599    * @param message
600    * @param initialSelectionValue
601    * @return
602    */
 
603  1 toggle public static String showInputDialog(Component parentComponent,
604    Object message, Object initialSelectionValue)
605    {
606   
607    // AnnotationPanel
608   
609  1 return isInteractiveMode()
610    ? JOptionPane.showInputDialog(parentComponent, message,
611    initialSelectionValue)
612    : getMockResponse().toString();
613    }
614   
615    /**
616    *
617    * @param parentComponent
618    * @param message
619    * @param title
620    * @param messageType
621    * @return
622    * @throws HeadlessException
623    */
 
624  1 toggle public static String showInputDialog(Component parentComponent,
625    String message, String title, int messageType)
626    throws HeadlessException
627    {
628   
629    // test only
630   
631  1 return isInteractiveMode()
632    ? JOptionPane.showInputDialog(parentComponent, message, title,
633    messageType)
634    : getMockResponse().toString();
635    }
636   
637    /**
638    * Customized input option
639    *
640    * @param parentComponent
641    * @param message
642    * @param title
643    * @param messageType
644    * @param icon
645    * @param selectionValues
646    * @param initialSelectionValue
647    * @return
648    * @throws HeadlessException
649    */
 
650  1 toggle public static Object showInputDialog(Component parentComponent,
651    Object message, String title, int messageType, Icon icon,
652    Object[] selectionValues, Object initialSelectionValue)
653    throws HeadlessException
654    {
655   
656    // test only
657   
658  1 return isInteractiveMode()
659    ? JOptionPane.showInputDialog(parentComponent, message, title,
660    messageType, icon, selectionValues,
661    initialSelectionValue)
662    : getMockResponse().toString();
663    }
664   
665    /**
666    * internal version
667    *
668    * @param parentComponent
669    * @param message
670    * @return
671    */
 
672  1 toggle public static String showInternalInputDialog(Component parentComponent,
673    String message)
674    {
675    // test only
676   
677  1 return isInteractiveMode()
678    ? JOptionPane.showInternalInputDialog(parentComponent, message)
679    : getMockResponse().toString();
680    }
681   
682    /**
683    * internal with title and messageType
684    *
685    * @param parentComponent
686    * @param message
687    * @param title
688    * @param messageType
689    * @return
690    */
 
691  1 toggle public static String showInternalInputDialog(Component parentComponent,
692    String message, String title, int messageType)
693    {
694   
695    // AlignFrame tabbedPane_mousePressed
696   
697  1 return isInteractiveMode()
698    ? JOptionPane.showInternalInputDialog(parentComponent,
699    getPrefix(messageType) + message, title, messageType)
700    : getMockResponse().toString();
701    }
702   
703    /**
704    * customized internal
705    *
706    * @param parentComponent
707    * @param message
708    * @param title
709    * @param messageType
710    * @param icon
711    * @param selectionValues
712    * @param initialSelectionValue
713    * @return
714    */
 
715  1 toggle public static Object showInternalInputDialog(Component parentComponent,
716    String message, String title, int messageType, Icon icon,
717    Object[] selectionValues, Object initialSelectionValue)
718    {
719    // test only
720   
721  1 return isInteractiveMode()
722    ? JOptionPane.showInternalInputDialog(parentComponent, message,
723    title, messageType, icon, selectionValues,
724    initialSelectionValue)
725    : getMockResponse().toString();
726    }
727   
728    ///////////// end of options ///////////////
729   
 
730  9 toggle private static void outputMessage(Object message)
731    {
732  9 jalview.bin.Console
733    .outPrintln(">>> JOption Message : " + message.toString());
734    }
735   
 
736  57 toggle public static Object getMockResponse()
737    {
738  57 return mockResponse;
739    }
740   
 
741  177 toggle public static void setMockResponse(Object mockOption)
742    {
743  177 JvOptionPane.mockResponse = mockOption;
744    }
745   
 
746  0 toggle public static void resetMock()
747    {
748  0 setMockResponse(JvOptionPane.CANCEL_OPTION);
749  0 setInteractiveMode(true);
750    }
751   
 
752  68 toggle public static boolean isInteractiveMode()
753    {
754  68 return interactiveMode;
755    }
756   
 
757  164 toggle public static void setInteractiveMode(boolean interactive)
758    {
759  164 JvOptionPane.interactiveMode = interactive;
760    }
761   
 
762  0 toggle private static String getPrefix(int messageType)
763    {
764  0 String prefix = "";
765   
766    // JavaScript only
767  0 if (Platform.isJS())
768    {
769  0 switch (messageType)
770    {
771  0 case JvOptionPane.WARNING_MESSAGE:
772  0 prefix = "WARNING! ";
773  0 break;
774  0 case JvOptionPane.ERROR_MESSAGE:
775  0 prefix = "ERROR! ";
776  0 break;
777  0 default:
778  0 prefix = "Note: ";
779    }
780    }
781  0 return prefix;
782    }
783   
784    /**
785    * create a new option dialog that can be used to register responses - along
786    * lines of showOptionDialog
787    *
788    * @param desktop
789    * @param question
790    * @param string
791    * @param defaultOption
792    * @param plainMessage
793    * @param object
794    * @param options
795    * @param string2
796    * @return
797    */
 
798  4 toggle public static JvOptionPane newOptionDialog()
799    {
800  4 return new JvOptionPane(null);
801    }
802   
 
803  1 toggle public static JvOptionPane newOptionDialog(Component parentComponent)
804    {
805  1 return new JvOptionPane(parentComponent);
806    }
807   
 
808  0 toggle public void showDialog(String message, String title, int optionType,
809    int messageType, Icon icon, Object[] options, Object initialValue)
810    {
811  0 showDialog(message, title, optionType, messageType, icon, options,
812    initialValue, true);
813    }
814   
 
815  0 toggle public void showDialog(Object message, String title, int optionType,
816    int messageType, Icon icon, Object[] options, Object initialValue,
817    boolean modal)
818    {
819  0 showDialog(message, title, optionType, messageType, icon, options,
820    initialValue, modal, null);
821    }
822   
 
823  1 toggle public void showDialog(Object message, String title, int optionType,
824    int messageType, Icon icon, Object[] options, Object initialValue,
825    boolean modal, JButton[] buttons)
826    {
827  1 if (!isInteractiveMode())
828    {
829  0 handleResponse(getMockResponse());
830  0 return;
831    }
832    // two uses:
833    //
834    // TODO
835    //
836    // 1) AlignViewport for openLinkedAlignment
837    //
838    // Show a dialog with the option to open and link (cDNA <-> protein) as a
839    // new
840    // alignment, either as a standalone alignment or in a split frame. Returns
841    // true if the new alignment was opened, false if not, because the user
842    // declined the offer.
843    //
844    // 2) UserDefinedColors warning about saving over a name already defined
845    //
846   
847  1 ourOptions = Arrays.asList(options);
848   
849  1 if (modal)
850    {
851  1 boolean useButtons = false;
852  1 Object initialValueButton = null;
853  1 NOTNULL: if (buttons != null)
854    {
855  1 if (buttons.length != options.length)
856    {
857  0 jalview.bin.Console.error(
858    "Supplied buttons array not the same length as supplied options array.");
859  0 break NOTNULL;
860    }
861   
862    // run through buttons for initialValue first so we can set (and start)
863    // a final timeoutThreadF to include (and interrupt) in the button
864    // actions
865  1 Thread timeoutThread = null;
866  1 for (int i = 0; i < options.length; i++)
867    {
868  1 Object o = options[i];
869  1 JButton jb = buttons[i];
870  1 if (o.equals(initialValue))
871    {
872  1 if (timeout > 0 && jb != null && jb instanceof JButton)
873    {
874    // after timeout ms click the default button
875  1 timeoutThread = new Thread(() -> {
876  1 try
877    {
878  1 Thread.sleep(timeout);
879    } catch (InterruptedException e)
880    {
881  0 Console.debug(
882    "Dialog timeout interrupted. Probably a button pressed.");
883    }
884  0 jb.doClick();
885    });
886    }
887  1 initialValueButton = jb;
888  1 break;
889    }
890    }
891  1 final Thread timeoutThreadF = timeoutThread;
892  1 if (timeoutThreadF != null)
893    {
894  1 timeoutThreadF.start();
895    }
896   
897  1 int[] buttonActions = { JOptionPane.YES_OPTION,
898    JOptionPane.NO_OPTION, JOptionPane.CANCEL_OPTION };
899  2 for (int i = 0; i < options.length; i++)
900    {
901  1 Object o = options[i];
902  1 jalview.bin.Console.debug(
903    "Setting button " + i + " to '" + o.toString() + "'");
904  1 JButton jb = buttons[i];
905   
906  1 int buttonAction = buttonActions[i];
907  1 Runnable action = callbacks.get(buttonAction);
908  1 jb.setText((String) o);
909  1 jb.addActionListener(new ActionListener()
910    {
 
911  0 toggle @Override
912    public void actionPerformed(ActionEvent e)
913    {
914  0 if (timeoutThreadF != null)
915    {
916  0 timeoutThreadF.interrupt();
917    }
918   
919  0 Object obj = e.getSource();
920  0 if (obj == null || !(obj instanceof Component))
921    {
922  0 jalview.bin.Console.debug(
923    "Could not find Component source of event object "
924    + obj);
925  0 return;
926    }
927  0 Object joptionpaneObject = SwingUtilities.getAncestorOfClass(
928    JOptionPane.class, (Component) obj);
929  0 if (joptionpaneObject == null
930    || !(joptionpaneObject instanceof JOptionPane))
931    {
932  0 jalview.bin.Console.debug(
933    "Could not find JOptionPane ancestor of event object "
934    + obj);
935  0 return;
936    }
937  0 JOptionPane joptionpane = (JOptionPane) joptionpaneObject;
938  0 joptionpane.setValue(buttonAction);
939  0 if (action != null)
940  0 new Thread(action).start();
941  0 joptionpane.transferFocusBackward();
942  0 joptionpane.setVisible(false);
943    // put focus and raise parent window if possible, unless cancel or
944    // no button pressed
945  0 boolean raiseParent = (parentComponent != null);
946  0 if (buttonAction == JOptionPane.CANCEL_OPTION)
947  0 raiseParent = false;
948  0 if (optionType == JOptionPane.YES_NO_OPTION
949    && buttonAction == JOptionPane.NO_OPTION)
950  0 raiseParent = false;
951  0 if (raiseParent)
952    {
953  0 parentComponent.requestFocus();
954  0 if (parentComponent instanceof JInternalFrame)
955    {
956  0 JInternalFrame jif = (JInternalFrame) parentComponent;
957  0 jif.show();
958  0 jif.moveToFront();
959  0 jif.grabFocus();
960    }
961  0 else if (parentComponent instanceof Window)
962    {
963  0 Window w = (Window) parentComponent;
964  0 w.toFront();
965  0 w.requestFocus();
966    }
967    }
968  0 joptionpane.setVisible(false);
969    }
970    });
971   
972    }
973  1 useButtons = true;
974    }
975    // use a JOptionPane as usual
976  1 int response = JOptionPane.showOptionDialog(parentComponent, message,
977    title, optionType, messageType, icon,
978  1 useButtons ? buttons : options,
979  1 useButtons ? initialValueButton : initialValue);
980   
981    /*
982    * In Java, the response is returned to this thread and handled here; (for
983    * Javascript, see propertyChange)
984    */
985  0 if (!Platform.isJS())
986    /**
987    * Java only
988    *
989    * @j2sIgnore
990    */
991    {
992  0 handleResponse(response);
993    }
994    }
995    else
996    {
997    /*
998    * This is java similar to the swingjs handling, with the callbacks attached to
999    * the button press of the dialog. This means we can use a non-modal JDialog for
1000    * the confirmation without blocking the GUI.
1001    */
1002  0 JOptionPane joptionpane = new JOptionPane();
1003    // Make button options
1004  0 int[] buttonActions = { JvOptionPane.YES_OPTION,
1005    JvOptionPane.NO_OPTION, JvOptionPane.CANCEL_OPTION };
1006   
1007    // we need the strings to make the buttons with actionEventListener
1008  0 if (options == null)
1009    {
1010  0 ArrayList<String> options_default = new ArrayList<>();
1011  0 options_default
1012    .add(UIManager.getString("OptionPane.yesButtonText"));
1013  0 if (optionType == JvOptionPane.YES_NO_OPTION
1014    || optionType == JvOptionPane.YES_NO_CANCEL_OPTION)
1015    {
1016  0 options_default
1017    .add(UIManager.getString("OptionPane.noButtonText"));
1018    }
1019  0 if (optionType == JvOptionPane.YES_NO_CANCEL_OPTION)
1020    {
1021  0 options_default
1022    .add(UIManager.getString("OptionPane.cancelButtonText"));
1023    }
1024  0 options = options_default.toArray();
1025    }
1026   
1027  0 ArrayList<JButton> options_btns = new ArrayList<>();
1028  0 Object initialValue_btn = null;
1029  0 if (!Platform.isJS()) // JalviewJS already uses callback, don't need to
1030    // add them here
1031    {
1032  0 for (int i = 0; i < options.length && i < 3; i++)
1033    {
1034  0 Object o = options[i];
1035  0 int buttonAction = buttonActions[i];
1036  0 Runnable action = callbacks.get(buttonAction);
1037  0 JButton jb = new JButton();
1038  0 jb.setText((String) o);
1039  0 jb.addActionListener(new ActionListener()
1040    {
1041   
 
1042  0 toggle @Override
1043    public void actionPerformed(ActionEvent e)
1044    {
1045  0 joptionpane.setValue(buttonAction);
1046  0 if (action != null)
1047  0 new Thread(action).start();
1048    // joptionpane.transferFocusBackward();
1049  0 joptionpane.transferFocusBackward();
1050  0 joptionpane.setVisible(false);
1051    // put focus and raise parent window if possible, unless cancel
1052    // button pressed
1053  0 boolean raiseParent = (parentComponent != null);
1054  0 if (buttonAction == JvOptionPane.CANCEL_OPTION)
1055  0 raiseParent = false;
1056  0 if (optionType == JvOptionPane.YES_NO_OPTION
1057    && buttonAction == JvOptionPane.NO_OPTION)
1058  0 raiseParent = false;
1059  0 if (raiseParent)
1060    {
1061  0 parentComponent.requestFocus();
1062  0 if (parentComponent instanceof JInternalFrame)
1063    {
1064  0 JInternalFrame jif = (JInternalFrame) parentComponent;
1065  0 jif.show();
1066  0 jif.moveToFront();
1067  0 jif.grabFocus();
1068    }
1069  0 else if (parentComponent instanceof Window)
1070    {
1071  0 Window w = (Window) parentComponent;
1072  0 w.toFront();
1073  0 w.requestFocus();
1074    }
1075    }
1076  0 joptionpane.setVisible(false);
1077    }
1078    });
1079  0 options_btns.add(jb);
1080  0 if (o.equals(initialValue))
1081  0 initialValue_btn = jb;
1082    }
1083    }
1084  0 joptionpane.setMessage(message);
1085  0 joptionpane.setMessageType(messageType);
1086  0 joptionpane.setOptionType(optionType);
1087  0 joptionpane.setIcon(icon);
1088  0 joptionpane.setOptions(
1089  0 Platform.isJS() ? options : options_btns.toArray());
1090  0 joptionpane.setInitialValue(
1091  0 Platform.isJS() ? initialValue : initialValue_btn);
1092   
1093  0 JDialog dialog = joptionpane.createDialog(parentComponent, title);
1094  0 dialog.setIconImages(ChannelProperties.getIconList());
1095  0 dialog.setModalityType(modal ? ModalityType.APPLICATION_MODAL
1096    : ModalityType.MODELESS);
1097  0 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
1098  0 dialog.setVisible(true);
1099  0 setDialog(dialog);
1100    }
1101    }
1102   
 
1103  0 toggle public void showInternalDialog(Object mainPanel, String title,
1104    int yesNoCancelOption, int questionMessage, Icon icon,
1105    Object[] options, String initresponse)
1106    {
1107  0 if (!isInteractiveMode())
1108    {
1109  0 handleResponse(getMockResponse());
1110    }
1111   
1112    // need to set these separately so we can set the title bar icon later
1113  0 this.setOptionType(yesNoCancelOption);
1114  0 this.setMessageType(questionMessage);
1115  0 this.setIcon(icon);
1116  0 this.setInitialValue(initresponse);
1117  0 this.setOptions(options);
1118  0 this.setMessage(mainPanel);
1119   
1120  0 ourOptions = Arrays.asList(options);
1121  0 if (parentComponent != this
1122    && !(parentComponent == null && Desktop.instance == null))
1123    {
1124    // note the parent goes back to a JRootPane so is probably
1125    // Desktop.getDesktop()
1126  0 JInternalFrame jif = this.createInternalFrame(
1127  0 parentComponent != null ? parentComponent : Desktop.instance,
1128    title);
1129    // connect to the alignFrame using a map in Desktop
1130  0 if (parentComponent instanceof AlignFrame)
1131    {
1132  0 Desktop.addModal((AlignFrame) parentComponent, jif);
1133    }
1134  0 jif.setFrameIcon(null);
1135  0 jif.addInternalFrameListener(new InternalFrameListener()
1136    {
 
1137  0 toggle @Override
1138    public void internalFrameActivated(InternalFrameEvent arg0)
1139    {
1140    }
1141   
 
1142  0 toggle @Override
1143    public void internalFrameClosed(InternalFrameEvent arg0)
1144    {
1145  0 JvOptionPane.this.internalDialogHandleResponse();
1146    }
1147   
 
1148  0 toggle @Override
1149    public void internalFrameClosing(InternalFrameEvent arg0)
1150    {
1151    }
1152   
 
1153  0 toggle @Override
1154    public void internalFrameDeactivated(InternalFrameEvent arg0)
1155    {
1156    }
1157   
 
1158  0 toggle @Override
1159    public void internalFrameDeiconified(InternalFrameEvent arg0)
1160    {
1161    }
1162   
 
1163  0 toggle @Override
1164    public void internalFrameIconified(InternalFrameEvent arg0)
1165    {
1166    }
1167   
 
1168  0 toggle @Override
1169    public void internalFrameOpened(InternalFrameEvent arg0)
1170    {
1171    }
1172    });
1173  0 jif.setVisible(true);
1174  0 startModal(jif);
1175  0 return;
1176    }
1177    else
1178    {
1179  0 JDialog dialog = this.createDialog(parentComponent, title);
1180  0 dialog.setIconImages(ChannelProperties.getIconList());
1181  0 dialog.setVisible(true); // blocking
1182  0 this.internalDialogHandleResponse();
1183  0 return;
1184    }
1185    }
1186   
 
1187  0 toggle private void internalDialogHandleResponse()
1188    {
1189  0 Object value = this.getValue();
1190  0 if (value == null
1191    || (value instanceof Integer && (Integer) value == -1))
1192    {
1193  0 return;
1194    }
1195  0 String responseString = value.toString();
1196  0 int response = ourOptions.indexOf(responseString);
1197   
1198  0 if (!Platform.isJS())
1199    /**
1200    * Java only
1201    *
1202    * @j2sIgnore
1203    */
1204    {
1205  0 handleResponse(response);
1206    }
1207    }
1208   
1209    /*
1210    * @Override public JvOptionPane setResponseHandler(Object response, Runnable
1211    * action) { callbacks.put(response, new Callable<Void>() {
1212    *
1213    * @Override public Void call() { action.run(); return null; } }); return this;
1214    * }
1215    */
 
1216  9 toggle @Override
1217    public JvOptionPane setResponseHandler(Object response, Runnable action)
1218    {
1219  9 if (action == null)
1220    {
1221  0 action = NULLCALLABLE;
1222    }
1223  9 callbacks.put(response, action);
1224  9 return this;
1225    }
1226   
 
1227  0 toggle public void setDialog(JDialog d)
1228    {
1229  0 dialog = d;
1230    }
1231   
 
1232  0 toggle public JDialog getDialog()
1233    {
1234  0 return dialog;
1235    }
1236   
1237    /**
1238    * showDialogOnTop will create a dialog that (attempts to) come to top of OS
1239    * desktop windows
1240    */
 
1241  0 toggle public static int showDialogOnTop(String label, String actionString,
1242    int JOPTIONPANE_OPTION, int JOPTIONPANE_MESSAGETYPE)
1243    {
1244  0 return showDialogOnTop(null, label, actionString, JOPTIONPANE_OPTION,
1245    JOPTIONPANE_MESSAGETYPE);
1246    }
1247   
 
1248  0 toggle public static int showDialogOnTop(Component dialogParentComponent,
1249    String label, String actionString, int JOPTIONPANE_OPTION,
1250    int JOPTIONPANE_MESSAGETYPE)
1251    {
1252  0 if (!isInteractiveMode())
1253    {
1254  0 return (int) getMockResponse();
1255    }
1256    // Ensure Jalview window is brought to front (primarily for Quit
1257    // confirmation window to be visible)
1258   
1259    // This method of raising the Jalview window is broken in java
1260    // jalviewDesktop.setVisible(true);
1261    // jalviewDesktop.toFront();
1262   
1263    // A better hack which works is to create a new JFrame parent with
1264    // setAlwaysOnTop(true)
1265  0 JFrame dialogParent = new JFrame();
1266  0 if (dialogParentComponent == null)
1267    {
1268  0 dialogParent.setIconImages(ChannelProperties.getIconList());
1269  0 dialogParent.setAlwaysOnTop(true);
1270    }
1271   
1272  0 int answer = JOptionPane.showConfirmDialog(
1273  0 dialogParentComponent == null ? dialogParent
1274    : dialogParentComponent,
1275    label, actionString, JOPTIONPANE_OPTION,
1276    JOPTIONPANE_MESSAGETYPE);
1277   
1278  0 if (dialogParentComponent == null)
1279    {
1280  0 dialogParent.setAlwaysOnTop(false);
1281  0 dialogParent.dispose();
1282    }
1283   
1284  0 return answer;
1285    }
1286   
 
1287  1 toggle public void showDialogOnTopAsync(String label, String actionString,
1288    int JOPTIONPANE_OPTION, int JOPTIONPANE_MESSAGETYPE, Icon icon,
1289    Object[] options, Object initialValue, boolean modal)
1290    {
1291  1 JFrame frame = new JFrame();
1292  1 frame.setIconImages(ChannelProperties.getIconList());
1293  1 showDialogOnTopAsync(frame, label, actionString, JOPTIONPANE_OPTION,
1294    JOPTIONPANE_MESSAGETYPE, icon, options, initialValue, modal);
1295    }
1296   
 
1297  1 toggle public void showDialogOnTopAsync(JFrame dialogParent, Object label,
1298    String actionString, int JOPTIONPANE_OPTION,
1299    int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options,
1300    Object initialValue, boolean modal)
1301    {
1302  1 showDialogOnTopAsync(dialogParent, label, actionString,
1303    JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE, icon, options,
1304    initialValue, modal, null);
1305    }
1306   
 
1307  4 toggle public void showDialogOnTopAsync(JFrame dialogParent, Object label,
1308    String actionString, int JOPTIONPANE_OPTION,
1309    int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options,
1310    Object initialValue, boolean modal, JButton[] buttons)
1311    {
1312  4 showDialogOnTopAsync(dialogParent, label, actionString,
1313    JOPTIONPANE_OPTION, JOPTIONPANE_MESSAGETYPE, icon, options,
1314    initialValue, modal, buttons, true);
1315    }
1316   
 
1317  5 toggle public void showDialogOnTopAsync(JFrame dialogParent, Object label,
1318    String actionString, int JOPTIONPANE_OPTION,
1319    int JOPTIONPANE_MESSAGETYPE, Icon icon, Object[] options,
1320    Object initialValue, boolean modal, JButton[] buttons,
1321    boolean dispose)
1322    {
1323  5 if (!isInteractiveMode())
1324    {
1325  4 handleResponse(getMockResponse());
1326  4 return;
1327    }
1328    // Ensure Jalview window is brought to front (primarily for Quit
1329    // confirmation window to be visible)
1330   
1331    // This method of raising the Jalview window is broken in java
1332    // jalviewDesktop.setVisible(true);
1333    // jalviewDesktop.toFront();
1334   
1335    // A better hack which works is to create a new JFrame parent with
1336    // setAlwaysOnTop(true)
1337  1 boolean parentOnTop = dialogParent.isAlwaysOnTop();
1338  1 dialogParent.setAlwaysOnTop(true);
1339  1 parentComponent = dialogParent;
1340   
1341  1 showDialog(label, actionString, JOPTIONPANE_OPTION,
1342    JOPTIONPANE_MESSAGETYPE, icon, options, initialValue, modal,
1343    buttons);
1344   
1345  0 dialogParent.setAlwaysOnTop(parentOnTop);
1346   
1347  0 if (dispose)
1348    {
1349  0 dialogParent.setAlwaysOnTop(false);
1350  0 dialogParent.dispose();
1351    }
1352    }
1353   
1354    /**
1355    * JalviewJS signals option selection by a property change event for the
1356    * option e.g. "OK". This methods responds to that by running the response
1357    * action that corresponds to that option.
1358    *
1359    * @param evt
1360    */
 
1361  0 toggle @Override
1362    public void propertyChange(PropertyChangeEvent evt)
1363    {
1364  0 Object newValue = evt.getNewValue();
1365  0 int ourOption = ourOptions.indexOf(newValue);
1366  0 if (ourOption >= 0)
1367    {
1368  0 handleResponse(ourOption);
1369    }
1370    else
1371    {
1372    // try our luck..
1373  0 handleResponse(newValue);
1374    }
1375    }
1376   
 
1377  4 toggle @Override
1378    public void handleResponse(Object response)
1379    {
1380    /*
1381    * this test is for NaN in Chrome
1382    */
1383  4 if (response != null && !response.equals(response))
1384    {
1385  0 return;
1386    }
1387  4 Runnable action = callbacks.get(response);
1388  4 if (action != null)
1389    {
1390  2 try
1391    {
1392  2 new Thread(action).start();
1393    // action.call();
1394    } catch (Exception e)
1395    {
1396  0 e.printStackTrace();
1397    }
1398  2 if (parentComponent != null)
1399  0 parentComponent.requestFocus();
1400    }
1401    }
1402   
1403    /**
1404    * Create a non-modal confirm dialog
1405    */
 
1406  0 toggle public JDialog createDialog(Component parentComponent, Object message,
1407    String title, int optionType, int messageType, Icon icon,
1408    Object[] options, Object initialValue, boolean modal)
1409    {
1410  0 return createDialog(parentComponent, message, title, optionType,
1411    messageType, icon, options, initialValue, modal, null);
1412    }
1413   
 
1414  0 toggle public JDialog createDialog(Component parentComponent, Object message,
1415    String title, int optionType, int messageType, Icon icon,
1416    Object[] options, Object initialValue, boolean modal,
1417    JButton[] buttons)
1418    {
1419  0 if (!isInteractiveMode())
1420    {
1421  0 handleResponse(getMockResponse());
1422  0 return null;
1423    }
1424  0 JButton[] optionsButtons = null;
1425  0 Object initialValueButton = null;
1426  0 JOptionPane joptionpane = new JOptionPane();
1427    // Make button options
1428  0 int[] buttonActions = { JOptionPane.YES_OPTION, JOptionPane.NO_OPTION,
1429    JOptionPane.CANCEL_OPTION };
1430   
1431    // we need the strings to make the buttons with actionEventListener
1432  0 if (options == null)
1433    {
1434  0 ArrayList<String> options_default = new ArrayList<>();
1435  0 options_default.add(UIManager.getString("OptionPane.yesButtonText"));
1436  0 if (optionType == JOptionPane.YES_NO_OPTION
1437    || optionType == JOptionPane.YES_NO_CANCEL_OPTION)
1438    {
1439  0 options_default.add(UIManager.getString("OptionPane.noButtonText"));
1440    }
1441  0 if (optionType == JOptionPane.YES_NO_CANCEL_OPTION)
1442    {
1443  0 options_default
1444    .add(UIManager.getString("OptionPane.cancelButtonText"));
1445    }
1446  0 options = options_default.toArray();
1447    }
1448  0 if (!Platform.isJS()) // JalviewJS already uses callback, don't need to
1449    // add them here
1450    {
1451  0 if (((optionType == JOptionPane.YES_OPTION
1452    || optionType == JOptionPane.NO_OPTION
1453    || optionType == JOptionPane.CANCEL_OPTION
1454    || optionType == JOptionPane.OK_OPTION
1455    || optionType == JOptionPane.DEFAULT_OPTION)
1456    && options.length < 1)
1457    || ((optionType == JOptionPane.YES_NO_OPTION
1458    || optionType == JOptionPane.OK_CANCEL_OPTION)
1459    && options.length < 2)
1460    || (optionType == JOptionPane.YES_NO_CANCEL_OPTION
1461    && options.length < 3))
1462    {
1463  0 jalview.bin.Console
1464    .debug("JvOptionPane: not enough options for dialog type");
1465    }
1466  0 optionsButtons = new JButton[options.length];
1467  0 for (int i = 0; i < options.length && i < 3; i++)
1468    {
1469  0 Object o = options[i];
1470  0 int buttonAction = buttonActions[i];
1471  0 Runnable action = callbacks.get(buttonAction);
1472  0 JButton jb;
1473  0 if (buttons != null && buttons.length > i && buttons[i] != null)
1474    {
1475  0 jb = buttons[i];
1476    }
1477    else
1478    {
1479  0 jb = new JButton();
1480    }
1481  0 jb.setText((String) o);
1482  0 jb.addActionListener(new ActionListener()
1483    {
 
1484  0 toggle @Override
1485    public void actionPerformed(ActionEvent e)
1486    {
1487  0 joptionpane.setValue(buttonAction);
1488  0 if (action != null)
1489  0 new Thread(action).start();
1490    // joptionpane.transferFocusBackward();
1491  0 joptionpane.transferFocusBackward();
1492  0 joptionpane.setVisible(false);
1493    // put focus and raise parent window if possible, unless cancel
1494    // button pressed
1495  0 boolean raiseParent = (parentComponent != null);
1496  0 if (buttonAction == JOptionPane.CANCEL_OPTION)
1497  0 raiseParent = false;
1498  0 if (optionType == JOptionPane.YES_NO_OPTION
1499    && buttonAction == JOptionPane.NO_OPTION)
1500  0 raiseParent = false;
1501  0 if (raiseParent)
1502    {
1503  0 parentComponent.requestFocus();
1504  0 if (parentComponent instanceof JInternalFrame)
1505    {
1506  0 JInternalFrame jif = (JInternalFrame) parentComponent;
1507  0 jif.show();
1508  0 jif.moveToFront();
1509  0 jif.grabFocus();
1510    }
1511  0 else if (parentComponent instanceof Window)
1512    {
1513  0 Window w = (Window) parentComponent;
1514  0 w.toFront();
1515  0 w.requestFocus();
1516    }
1517    }
1518  0 joptionpane.setVisible(false);
1519    }
1520    });
1521  0 optionsButtons[i] = jb;
1522  0 if (o.equals(initialValue))
1523  0 initialValueButton = jb;
1524    }
1525    }
1526  0 joptionpane.setMessage(message);
1527  0 joptionpane.setMessageType(messageType);
1528  0 joptionpane.setOptionType(optionType);
1529  0 joptionpane.setIcon(icon);
1530  0 joptionpane.setOptions(Platform.isJS() ? options : optionsButtons);
1531  0 joptionpane.setInitialValue(
1532  0 Platform.isJS() ? initialValue : initialValueButton);
1533   
1534  0 JDialog dialog = joptionpane.createDialog(parentComponent, title);
1535  0 dialog.setIconImages(ChannelProperties.getIconList());
1536  0 dialog.setModalityType(
1537  0 modal ? ModalityType.APPLICATION_MODAL : ModalityType.MODELESS);
1538  0 dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
1539  0 setDialog(dialog);
1540  0 return dialog;
1541    }
1542   
1543    /**
1544    * Utility to programmatically click a button on a JOptionPane (as a JFrame)
1545    *
1546    * returns true if button was found
1547    */
 
1548  0 toggle public static boolean clickButton(JFrame frame, int buttonType)
1549    {
1550   
1551  0 return false;
1552    }
1553   
1554    /**
1555    * This helper method makes the JInternalFrame wait until it is notified by an
1556    * InternalFrameClosing event. This method also adds the given JOptionPane to
1557    * the JInternalFrame and sizes it according to the JInternalFrame's preferred
1558    * size.
1559    *
1560    * @param f
1561    * The JInternalFrame to make modal.
1562    */
 
1563  0 toggle private static void startModal(JInternalFrame f)
1564    {
1565    // We need to add an additional glasspane-like component directly
1566    // below the frame, which intercepts all mouse events that are not
1567    // directed at the frame itself.
1568  0 JPanel modalInterceptor = new JPanel();
1569  0 modalInterceptor.setOpaque(false);
1570  0 JLayeredPane lp = JLayeredPane.getLayeredPaneAbove(f);
1571  0 lp.setLayer(modalInterceptor, JLayeredPane.MODAL_LAYER.intValue());
1572  0 modalInterceptor.setBounds(0, 0, lp.getWidth(), lp.getHeight());
1573  0 modalInterceptor.addMouseListener(new MouseAdapter()
1574    {
1575    });
1576  0 modalInterceptor.addMouseMotionListener(new MouseMotionAdapter()
1577    {
1578    });
1579  0 lp.add(modalInterceptor);
1580  0 f.toFront();
1581   
1582    // disable the main menu bar if in Linux
1583  0 JMenuBar menubar = null;
1584  0 if (Platform.isLinux())
1585    {
1586  0 JRootPane rootpane = Desktop.getDesktop().getRootPane();
1587  0 menubar = rootpane.getJMenuBar();
1588    }
1589   
1590    // We need to explicitly dispatch events when we are blocking the event
1591    // dispatch thread.
1592  0 EventQueue queue = Toolkit.getDefaultToolkit().getSystemEventQueue();
1593  0 try
1594    {
1595  0 if (menubar != null)
1596    {
1597    // don't allow clicks on main menu on linux due to a hanging bug.
1598    // see JAL-4214.
1599  0 setMenusEnabled(menubar, false);
1600    }
1601   
1602  0 while (!f.isClosed())
1603    {
1604  0 if (EventQueue.isDispatchThread())
1605    {
1606    // The getNextEventMethod() issues wait() when no
1607    // event is available, so we don't need do explicitly wait().
1608  0 AWTEvent ev = queue.getNextEvent();
1609    // This mimics EventQueue.dispatchEvent(). We can't use
1610    // EventQueue.dispatchEvent() directly, because it is
1611    // protected, unfortunately.
1612  0 if (ev instanceof ActiveEvent)
1613    {
1614  0 ((ActiveEvent) ev).dispatch();
1615    }
1616  0 else if (ev instanceof KeyEvent && ((KeyEvent) ev).isControlDown()
1617    && menubar != null)
1618    {
1619    // temporarily enable menus to send Ctrl+? KeyEvents
1620  0 setMenusEnabled(menubar, true);
1621  0 ((Component) ev.getSource()).dispatchEvent(ev);
1622  0 setMenusEnabled(menubar, false);
1623    }
1624  0 else if (ev.getSource() instanceof MenuComponent)
1625    {
1626  0 ((MenuComponent) ev.getSource()).dispatchEvent(ev);
1627    }
1628  0 else if (ev.getSource() instanceof Component)
1629    {
1630  0 ((Component) ev.getSource()).dispatchEvent(ev);
1631    }
1632    // Other events are ignored as per spec in
1633    // EventQueue.dispatchEvent
1634    }
1635    else
1636    {
1637    // Give other threads a chance to become active.
1638  0 Thread.yield();
1639    }
1640    }
1641    } catch (InterruptedException ex)
1642    {
1643    // If we get interrupted, then leave the modal state.
1644    } finally
1645    {
1646    // re-enable the main menu bar
1647  0 if (menubar != null)
1648    {
1649  0 setMenusEnabled(menubar, true);
1650    }
1651   
1652    // Clean up the modal interceptor.
1653  0 lp.remove(modalInterceptor);
1654   
1655    // unpaint the frame
1656  0 f.setVisible(false);
1657   
1658    // close the frame
1659  0 try
1660    {
1661  0 f.setClosed(true);
1662    } catch (PropertyVetoException e)
1663    {
1664  0 f.doDefaultCloseAction();
1665    }
1666   
1667    // Remove the internal frame from its parent, so it is no longer
1668    // lurking around and clogging memory.
1669  0 Container parent = f.getParent();
1670  0 if (parent != null)
1671    {
1672  0 parent.remove(f);
1673    }
1674    }
1675    }
1676   
 
1677  0 toggle public static JvOptionPane frameDialog(Object message, String title,
1678    int messageType, String[] buttonsTextS, String defaultButtonS,
1679    List<Runnable> handlers, boolean modal)
1680    {
1681  0 JFrame parent = new JFrame();
1682  0 JvOptionPane jvop = JvOptionPane.newOptionDialog();
1683  0 final String[] buttonsText;
1684  0 final String defaultButton;
1685  0 if (buttonsTextS == null)
1686    {
1687  0 String ok = MessageManager.getString("action.ok");
1688  0 buttonsText = new String[] { ok };
1689  0 defaultButton = ok;
1690    }
1691    else
1692    {
1693  0 buttonsText = buttonsTextS;
1694  0 defaultButton = defaultButtonS;
1695    }
1696  0 JButton[] buttons = new JButton[buttonsText.length];
1697  0 for (int i = 0; i < buttonsText.length; i++)
1698    {
1699  0 buttons[i] = new JButton();
1700  0 buttons[i].setText(buttonsText[i]);
1701  0 Console.debug("DISABLING BUTTON " + buttons[i].getText());
1702  0 buttons[i].setEnabled(false);
1703  0 buttons[i].setVisible(false);
1704    }
1705   
1706  0 int dialogType = -1;
1707  0 if (buttonsText.length == 1)
1708    {
1709  0 dialogType = JOptionPane.OK_OPTION;
1710    }
1711  0 else if (buttonsText.length == 2)
1712    {
1713  0 dialogType = JOptionPane.YES_NO_OPTION;
1714    }
1715    else
1716    {
1717  0 dialogType = JOptionPane.YES_NO_CANCEL_OPTION;
1718    }
1719  0 jvop.setResponseHandler(JOptionPane.YES_OPTION,
1720  0 (handlers != null && handlers.size() > 0) ? handlers.get(0)
1721    : NULLCALLABLE);
1722  0 if (dialogType == JOptionPane.YES_NO_OPTION
1723    || dialogType == JOptionPane.YES_NO_CANCEL_OPTION)
1724    {
1725  0 jvop.setResponseHandler(JOptionPane.NO_OPTION,
1726  0 (handlers != null && handlers.size() > 1) ? handlers.get(1)
1727    : NULLCALLABLE);
1728    }
1729  0 if (dialogType == JOptionPane.YES_NO_CANCEL_OPTION)
1730    {
1731  0 jvop.setResponseHandler(JOptionPane.CANCEL_OPTION,
1732  0 (handlers != null && handlers.size() > 2) ? handlers.get(2)
1733    : NULLCALLABLE);
1734    }
1735   
1736  0 final int dt = dialogType;
1737  0 new Thread(() -> {
1738  0 jvop.showDialog(message, title, dt, messageType, null, buttonsText,
1739    defaultButton, modal, buttons);
1740    }).start();
1741   
1742  0 return jvop;
1743    }
1744   
 
1745  0 toggle private static void setMenusEnabled(JMenuBar menubar, boolean b)
1746    {
1747  0 for (int i = 0; i < menubar.getMenuCount(); i++)
1748    {
1749  0 JMenu menu = menubar.getMenu(i);
1750  0 menu.setEnabled(b);
1751    }
1752    }
1753   
1754    }