JAL-3032 JvOptionPane summary of issues with boilerplate modal dialogs.
[jalview.git] / src / jalview / gui / JvOptionPane.java
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
22 package jalview.gui;
23
24 import java.awt.Component;
25 import java.awt.HeadlessException;
26
27 import javax.swing.Icon;
28 import javax.swing.JOptionPane;
29
30 public class JvOptionPane extends JOptionPane
31 {
32   // BH 2018 no changes needed here.
33
34   private static final long serialVersionUID = -3019167117756785229L;
35
36   private static Object mockResponse = JvOptionPane.CANCEL_OPTION;
37
38   private static boolean interactiveMode = true;
39
40   public static int showConfirmDialog(Component parentComponent,
41           Object message) throws HeadlessException
42   {
43     // only called by test
44     return isInteractiveMode()
45             ? JOptionPane.showConfirmDialog(parentComponent, message)
46             : (int) getMockResponse();
47   }
48
49   /**
50    * Message, title, optionType
51    * 
52    * @param parentComponent
53    * @param message
54    * @param title
55    * @param optionType
56    * @return
57    * @throws HeadlessException
58    */
59   public static int showConfirmDialog(Component parentComponent,
60           Object message, String title, int optionType)
61           throws HeadlessException
62   {
63     if (!isInteractiveMode())
64       return (int) getMockResponse();
65     switch (optionType)
66     {
67     case JvOptionPane.YES_NO_CANCEL_OPTION:
68       // FeatureRenderer amendFeatures  ?? TODO ??
69       // Chimera close
70       // PromptUserConfig
71       // $FALL-THROUGH$
72     default:
73     case JvOptionPane.YES_NO_OPTION:
74       // PromptUserConfig usage stats
75       // for now treated as "OK CANCEL"
76       // $FALL-THROUGH$
77     case JvOptionPane.OK_CANCEL_OPTION:
78       // will fall back to simple HTML
79       return JOptionPane.showConfirmDialog(parentComponent, message, title,
80               optionType);
81     }
82   }
83
84   /**
85    * Adds a message type. Fallback is to just add it in the beginning.
86    * 
87    * @param parentComponent
88    * @param message
89    * @param title
90    * @param optionType
91    * @param messageType
92    * @return
93    * @throws HeadlessException
94    */
95   public static int showConfirmDialog(Component parentComponent,
96           Object message, String title, int optionType, int messageType)
97           throws HeadlessException
98   {
99     // JalviewServicesChanged
100     // PromptUserConfig raiseDialog
101     return isInteractiveMode()
102             ? JOptionPane.showConfirmDialog(parentComponent, message, title,
103                     optionType, messageType)
104             : (int) getMockResponse();
105   }
106
107   /**
108    * Adds an icon
109    * 
110    * @param parentComponent
111    * @param message
112    * @param title
113    * @param optionType
114    * @param messageType
115    * @param icon
116    * @return
117    * @throws HeadlessException
118    */
119   public static int showConfirmDialog(Component parentComponent,
120           Object message, String title, int optionType, int messageType,
121           Icon icon) throws HeadlessException
122   {
123     // JvOptionPaneTest only
124     return isInteractiveMode()
125             ? JOptionPane.showConfirmDialog(parentComponent, message, title,
126                     optionType, messageType, icon)
127             : (int) getMockResponse();
128   }
129
130   /**
131    * Internal version "OK"
132    * 
133    * @param parentComponent
134    * @param message
135    * @return
136    */
137   public static int showInternalConfirmDialog(Component parentComponent,
138           Object message)
139   {
140     // JvOptionPaneTest only;
141     return isInteractiveMode() ? JOptionPane.showInternalConfirmDialog(
142             parentComponent, message) : (int) getMockResponse();
143   }
144
145   /**
146    * Internal version -- changed to standard version for now
147    * 
148    * @param parentComponent
149    * @param message
150    * @param title
151    * @param optionType
152    * @return
153    */
154   public static int showInternalConfirmDialog(Component parentComponent,
155           String message, String title, int optionType)
156   {
157     if (!isInteractiveMode())
158       return (int) getMockResponse();
159     switch (optionType)
160     {
161     case JvOptionPane.YES_NO_CANCEL_OPTION:
162       // ColourMenuHelper.addMenuItmers.offerRemoval TODO
163     case JvOptionPane.YES_NO_OPTION:
164       // UserDefinedColoursSave -- relevant? TODO
165       // $FALL-THROUGH$
166     default:
167     case JvOptionPane.OK_CANCEL_OPTION:
168
169       // EditNameDialog --- uses panel for messsage TODO
170
171       // Desktop.inputURLMenuItem
172       // WsPreferenses
173       return JOptionPane.showConfirmDialog(parentComponent, message, title,
174               optionType);
175     }
176   }
177
178   /**
179    * 
180    * @param parentComponent
181    * @param message
182    * @param title
183    * @param optionType
184    * @param messageType
185    * @return
186    */
187   public static int showInternalConfirmDialog(Component parentComponent,
188           Object message, String title, int optionType, int messageType)
189   {
190     if (!isInteractiveMode())
191       return (int) getMockResponse();
192     switch (optionType)
193     {
194     case JvOptionPane.YES_NO_CANCEL_OPTION:
195     case JvOptionPane.YES_NO_OPTION:
196       // UserQuestionanaireCheck
197       // VamsasApplication
198       // $FALL-THROUGH$
199     default:
200     case JvOptionPane.OK_CANCEL_OPTION:
201       // will fall back to simple HTML
202       return JOptionPane.showConfirmDialog(parentComponent, message, title,
203               optionType, messageType);
204     }
205   }
206
207   /**
208    * adds icon; no longer internal
209    * 
210    * @param parentComponent
211    * @param message
212    * @param title
213    * @param optionType
214    * @param messageType
215    * @param icon
216    * @return
217    */
218   public static int showInternalConfirmDialog(Component parentComponent,
219           Object message, String title, int optionType, int messageType,
220           Icon icon)
221   {
222     if (!isInteractiveMode())
223       return (int) getMockResponse();
224     switch (optionType)
225     {
226     case JvOptionPane.YES_NO_CANCEL_OPTION:
227     case JvOptionPane.YES_NO_OPTION:
228       //$FALL-THROUGH$
229     default:
230     case JvOptionPane.OK_CANCEL_OPTION:
231       // Preferences editLink/newLink
232       return JOptionPane.showConfirmDialog(parentComponent, message, title,
233               optionType, messageType, icon);
234     }
235
236   }
237
238   /**
239    * custom options full-featured
240    * 
241    * @param parentComponent
242    * @param message
243    * @param title
244    * @param optionType
245    * @param messageType
246    * @param icon
247    * @param options
248    * @param initialValue
249    * @return
250    * @throws HeadlessException
251    */
252   public static int showOptionDialog(Component parentComponent,
253           String message, String title, int optionType, int messageType,
254           Icon icon, Object[] options, Object initialValue)
255           throws HeadlessException
256   {
257     if (!isInteractiveMode())
258       return (int) getMockResponse();
259     // two uses:
260     //
261     // TODO
262     //
263     // 1) AlignViewport for openLinkedAlignment
264     //
265     // Show a dialog with the option to open and link (cDNA <-> protein) as a
266     // new
267     // alignment, either as a standalone alignment or in a split frame. Returns
268     // true if the new alignment was opened, false if not, because the user
269     // declined the offer.
270     //
271     // 2) UserDefinedColors warning about saving over a name already defined
272     //
273     return JOptionPane.showOptionDialog(parentComponent, message, title,
274             optionType, messageType, icon, options, initialValue);
275   }
276
277   /**
278    * Just an OK message
279    * 
280    * @param message
281    * @throws HeadlessException
282    */
283   public static void showMessageDialog(Component parentComponent,
284           String message) throws HeadlessException
285   {
286     if (!isInteractiveMode())
287     {
288       outputMessage(message);
289       return;
290     }
291
292     // test class only
293
294     JOptionPane.showMessageDialog(parentComponent, message);
295   }
296
297   /**
298    * OK with message, title, and type
299    * 
300    * @param parentComponent
301    * @param message
302    * @param title
303    * @param messageType
304    * @throws HeadlessException
305    */
306   public static void showMessageDialog(Component parentComponent,
307           String message, String title, int messageType)
308           throws HeadlessException
309   {
310     // 30 implementations -- all just fine.
311
312     if (!isInteractiveMode())
313     {
314       outputMessage(message);
315       return;
316     }
317
318     JOptionPane.showMessageDialog(parentComponent,
319             getPrefix(messageType) + message, title, messageType);
320   }
321
322   /**
323    * adds title and icon
324    * 
325    * @param parentComponent
326    * @param message
327    * @param title
328    * @param messageType
329    * @param icon
330    * @throws HeadlessException
331    */
332   public static void showMessageDialog(Component parentComponent,
333           String message, String title, int messageType, Icon icon)
334           throws HeadlessException
335   {
336
337     // test only
338
339     if (!isInteractiveMode())
340     {
341       outputMessage(message);
342       return;
343     }
344
345     JOptionPane.showMessageDialog(parentComponent, message, title,
346             messageType, icon);
347   }
348
349   /**
350    * was internal
351    * 
352    */
353   public static void showInternalMessageDialog(Component parentComponent,
354           Object message)
355   {
356
357     // WsPreferences only
358
359     if (!isInteractiveMode())
360     {
361       outputMessage(message);
362       return;
363     }
364
365     JOptionPane.showMessageDialog(parentComponent, message);
366   }
367
368
369   /**
370    * Adds title and messageType
371    * 
372    * @param parentComponent
373    * @param message
374    * @param title
375    * @param messageType
376    */
377   public static void showInternalMessageDialog(Component parentComponent,
378           String message, String title, int messageType)
379   {
380
381     // 41 references
382
383     if (!isInteractiveMode())
384     {
385       outputMessage(message);
386       return;
387     }
388
389     JOptionPane.showMessageDialog(parentComponent,
390             getPrefix(messageType) + message, title, messageType);
391   }
392
393   /**
394    * 
395    * @param parentComponent
396    * @param message
397    * @param title
398    * @param messageType
399    * @param icon
400    */
401   public static void showInternalMessageDialog(Component parentComponent,
402           Object message, String title, int messageType, Icon icon)
403   {
404
405     // test only
406
407     if (!isInteractiveMode())
408     {
409       outputMessage(message);
410       return;
411     }
412
413     JOptionPane.showMessageDialog(parentComponent, message, title,
414             messageType, icon);
415   }
416
417   /**
418    * 
419    * @param message
420    * @return
421    * @throws HeadlessException
422    */
423   public static String showInputDialog(Object message)
424           throws HeadlessException
425   {
426     // test only
427
428     if (!isInteractiveMode())
429     {
430       return getMockResponse().toString();
431     }
432
433     return JOptionPane.showInputDialog(message);
434   }
435
436   /**
437    * adds inital selection value
438    * 
439    * @param message
440    * @param initialSelectionValue
441    * @return
442    */
443   public static String showInputDialog(String message,
444           String initialSelectionValue)
445   {
446     if (!isInteractiveMode())
447     {
448       return getMockResponse().toString();
449     }
450
451     // AnnotationPanel character option
452
453     return JOptionPane.showInputDialog(message, initialSelectionValue);
454   }
455
456   /**
457    * centered on parent
458    * 
459    * @param parentComponent
460    * @param message
461    * @return
462    * @throws HeadlessException
463    */
464   public static String showInputDialog(Component parentComponent,
465           String message) throws HeadlessException
466   {
467     // test only
468
469     return isInteractiveMode()
470             ? JOptionPane.showInputDialog(parentComponent, message)
471             : getMockResponse().toString();
472   }
473
474   /**
475    * input with initial selection
476    * 
477    * @param parentComponent
478    * @param message
479    * @param initialSelectionValue
480    * @return
481    */
482   public static String showInputDialog(Component parentComponent,
483           String message, String initialSelectionValue)
484   {
485     
486     // AnnotationPanel
487     
488     return isInteractiveMode()
489             ? JOptionPane.showInputDialog(parentComponent, message,
490                     initialSelectionValue)
491             : getMockResponse().toString();
492   }
493
494   /**
495    * 
496    * @param parentComponent
497    * @param message
498    * @param title
499    * @param messageType
500    * @return
501    * @throws HeadlessException
502    */
503   public static String showInputDialog(Component parentComponent,
504           String message, String title, int messageType)
505           throws HeadlessException
506   {
507
508     // test only
509
510     return isInteractiveMode() ? JOptionPane
511             .showInputDialog(parentComponent, message, title, messageType)
512             : getMockResponse().toString();
513   }
514
515   /**
516    * Customized input option 
517    * 
518    * @param parentComponent
519    * @param message
520    * @param title
521    * @param messageType
522    * @param icon
523    * @param selectionValues
524    * @param initialSelectionValue
525    * @return
526    * @throws HeadlessException
527    */
528   public static Object showInputDialog(Component parentComponent,
529           Object message, String title, int messageType, Icon icon,
530           Object[] selectionValues, Object initialSelectionValue)
531           throws HeadlessException
532   {
533     
534     // test only
535     
536     return isInteractiveMode()
537             ? JOptionPane.showInputDialog(parentComponent, message, title,
538                     messageType, icon, selectionValues,
539                     initialSelectionValue)
540             : getMockResponse().toString();
541   }
542
543   
544   
545   /**
546    * internal version
547    * 
548    * @param parentComponent
549    * @param message
550    * @return
551    */
552   public static String showInternalInputDialog(Component parentComponent,
553           String message)
554   {
555     // test only
556     
557     return isInteractiveMode()
558             ? JOptionPane.showInternalInputDialog(parentComponent, message)
559             : getMockResponse().toString();
560   }
561
562   
563   /**
564    * internal with title and messageType
565    * 
566    * @param parentComponent
567    * @param message
568    * @param title
569    * @param messageType
570    * @return
571    */
572   public static String showInternalInputDialog(Component parentComponent,
573           String message, String title, int messageType)
574   {
575     
576     // AlignFrame tabbedPane_mousePressed
577     
578     return isInteractiveMode()
579             ? JOptionPane.showInternalInputDialog(parentComponent,
580                     getPrefix(messageType) + message, title, messageType)
581             : getMockResponse().toString();
582   }
583
584   /**
585    * customized internal
586    * 
587    * @param parentComponent
588    * @param message
589    * @param title
590    * @param messageType
591    * @param icon
592    * @param selectionValues
593    * @param initialSelectionValue
594    * @return
595    */
596   public static Object showInternalInputDialog(Component parentComponent,
597           String message, String title, int messageType, Icon icon,
598           Object[] selectionValues, Object initialSelectionValue)
599   {
600     // test only
601     
602     return isInteractiveMode()
603             ? JOptionPane.showInternalInputDialog(parentComponent, message,
604                     title, messageType, icon, selectionValues,
605                     initialSelectionValue)
606             : getMockResponse().toString();
607   }
608
609   
610   ///////////// end of options ///////////////
611   
612   
613   private static void outputMessage(Object message)
614   {
615     System.out.println(">>> JOption Message : " + message.toString());
616   }
617
618   public static Object getMockResponse()
619   {
620     return mockResponse;
621   }
622
623   public static void setMockResponse(Object mockOption)
624   {
625     JvOptionPane.mockResponse = mockOption;
626   }
627
628   public static void resetMock()
629   {
630     setMockResponse(JvOptionPane.CANCEL_OPTION);
631     setInteractiveMode(true);
632   }
633
634   public static boolean isInteractiveMode()
635   {
636     return interactiveMode;
637   }
638
639   public static void setInteractiveMode(boolean interactiveMode)
640   {
641     JvOptionPane.interactiveMode = interactiveMode;
642   }
643
644   @SuppressWarnings("unused")
645   private static String getPrefix(int messageType)
646   {
647     String prefix = ""; // JavaScript only
648
649     if (/** @j2sNative true || */
650     false)
651     {
652       switch (messageType)
653       {
654       default:
655       case JvOptionPane.INFORMATION_MESSAGE:
656         prefix = "Note: ";
657         break;
658       case JvOptionPane.WARNING_MESSAGE:
659         prefix = "WARNING! ";
660         break;
661       case JvOptionPane.ERROR_MESSAGE:
662         prefix = "ERRROR! ";
663         break;
664       }
665     }
666     return prefix;
667   }
668
669 }