JAL-3048 response() renamed addResponse(); checkstyle warning fixes
[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 jalview.util.dialogrunner.DialogRunner;
25 import jalview.util.dialogrunner.DialogRunnerI;
26 import jalview.util.dialogrunner.RunResponse;
27
28 import java.awt.Component;
29 import java.awt.HeadlessException;
30 import java.beans.PropertyChangeEvent;
31 import java.beans.PropertyChangeListener;
32 import java.util.Arrays;
33 import java.util.List;
34
35 import javax.swing.Icon;
36 import javax.swing.JOptionPane;
37 import javax.swing.JPanel;
38
39 public class JvOptionPane extends JOptionPane
40         implements DialogRunnerI, PropertyChangeListener
41 {
42   // BH 2018 no changes needed here.
43
44   private static final long serialVersionUID = -3019167117756785229L;
45
46   private static Object mockResponse = JvOptionPane.CANCEL_OPTION;
47
48   private static boolean interactiveMode = true;
49
50   private Component parentComponent;
51
52   public JvOptionPane(final Component parentComponent)
53   {
54     
55     this.parentComponent = parentComponent;
56   }
57
58   public static int showConfirmDialog(Component parentComponent,
59           Object message) throws HeadlessException
60   {
61     // only called by test
62     return isInteractiveMode()
63             ? JOptionPane.showConfirmDialog(parentComponent, message)
64             : (int) getMockResponse();
65   }
66
67   /**
68    * Message, title, optionType
69    * 
70    * @param parentComponent
71    * @param message
72    * @param title
73    * @param optionType
74    * @return
75    * @throws HeadlessException
76    */
77   public static int showConfirmDialog(Component parentComponent,
78           Object message, String title, int optionType)
79           throws HeadlessException
80   {
81     if (!isInteractiveMode())
82     {
83       return (int) getMockResponse();
84     }
85     switch (optionType)
86     {
87     case JvOptionPane.YES_NO_CANCEL_OPTION:
88       // FeatureRenderer amendFeatures  ?? TODO ??
89       // Chimera close
90       // PromptUserConfig
91       // $FALL-THROUGH$
92     default:
93     case JvOptionPane.YES_NO_OPTION:
94       // PromptUserConfig usage stats
95       // for now treated as "OK CANCEL"
96       // $FALL-THROUGH$
97     case JvOptionPane.OK_CANCEL_OPTION:
98       // will fall back to simple HTML
99       return JOptionPane.showConfirmDialog(parentComponent, message, title,
100               optionType);
101     }
102   }
103
104   /**
105    * Adds a message type. Fallback is to just add it in the beginning.
106    * 
107    * @param parentComponent
108    * @param message
109    * @param title
110    * @param optionType
111    * @param messageType
112    * @return
113    * @throws HeadlessException
114    */
115   public static int showConfirmDialog(Component parentComponent,
116           Object message, String title, int optionType, int messageType)
117           throws HeadlessException
118   {
119     // JalviewServicesChanged
120     // PromptUserConfig raiseDialog
121     return isInteractiveMode()
122             ? JOptionPane.showConfirmDialog(parentComponent, message, title,
123                     optionType, messageType)
124             : (int) getMockResponse();
125   }
126
127   /**
128    * Adds an icon
129    * 
130    * @param parentComponent
131    * @param message
132    * @param title
133    * @param optionType
134    * @param messageType
135    * @param icon
136    * @return
137    * @throws HeadlessException
138    */
139   public static int showConfirmDialog(Component parentComponent,
140           Object message, String title, int optionType, int messageType,
141           Icon icon) throws HeadlessException
142   {
143     // JvOptionPaneTest only
144     return isInteractiveMode()
145             ? JOptionPane.showConfirmDialog(parentComponent, message, title,
146                     optionType, messageType, icon)
147             : (int) getMockResponse();
148   }
149
150   /**
151    * Internal version "OK"
152    * 
153    * @param parentComponent
154    * @param message
155    * @return
156    */
157   public static int showInternalConfirmDialog(Component parentComponent,
158           Object message)
159   {
160     // JvOptionPaneTest only;
161     return isInteractiveMode() ? JOptionPane.showInternalConfirmDialog(
162             parentComponent, message) : (int) getMockResponse();
163   }
164
165   /**
166    * Internal version -- changed to standard version for now
167    * 
168    * @param parentComponent
169    * @param message
170    * @param title
171    * @param optionType
172    * @return
173    */
174   public static int showInternalConfirmDialog(Component parentComponent,
175           String message, String title, int optionType)
176   {
177     if (!isInteractiveMode())
178     {
179       return (int) getMockResponse();
180     }
181     switch (optionType)
182     {
183     case JvOptionPane.YES_NO_CANCEL_OPTION:
184       // ColourMenuHelper.addMenuItmers.offerRemoval TODO
185     case JvOptionPane.YES_NO_OPTION:
186       // UserDefinedColoursSave -- relevant? TODO
187       // $FALL-THROUGH$
188     default:
189     case JvOptionPane.OK_CANCEL_OPTION:
190
191       // EditNameDialog --- uses panel for messsage TODO
192
193       // Desktop.inputURLMenuItem
194       // WsPreferenses
195       return JOptionPane.showConfirmDialog(parentComponent, message, title,
196               optionType);
197     }
198   }
199
200   /**
201    * 
202    * @param parentComponent
203    * @param message
204    * @param title
205    * @param optionType
206    * @param messageType
207    * @return
208    */
209   public static int showInternalConfirmDialog(Component parentComponent,
210           Object message, String title, int optionType, int messageType)
211   {
212     if (!isInteractiveMode())
213     {
214       return (int) getMockResponse();
215     }
216     switch (optionType)
217     {
218     case JvOptionPane.YES_NO_CANCEL_OPTION:
219     case JvOptionPane.YES_NO_OPTION:
220       // UserQuestionanaireCheck
221       // VamsasApplication
222       // $FALL-THROUGH$
223     default:
224     case JvOptionPane.OK_CANCEL_OPTION:
225       // will fall back to simple HTML
226       return JOptionPane.showConfirmDialog(parentComponent, message, title,
227               optionType, messageType);
228     }
229   }
230
231   /**
232    * adds icon; no longer internal
233    * 
234    * @param parentComponent
235    * @param message
236    * @param title
237    * @param optionType
238    * @param messageType
239    * @param icon
240    * @return
241    */
242   public static int showInternalConfirmDialog(Component parentComponent,
243           Object message, String title, int optionType, int messageType,
244           Icon icon)
245   {
246     if (!isInteractiveMode())
247     {
248       return (int) getMockResponse();
249     }
250     switch (optionType)
251     {
252     case JvOptionPane.YES_NO_CANCEL_OPTION:
253     case JvOptionPane.YES_NO_OPTION:
254       //$FALL-THROUGH$
255     default:
256     case JvOptionPane.OK_CANCEL_OPTION:
257       // Preferences editLink/newLink
258       return JOptionPane.showConfirmDialog(parentComponent, message, title,
259               optionType, messageType, icon);
260     }
261
262   }
263
264   /**
265    * custom options full-featured
266    * 
267    * @param parentComponent
268    * @param message
269    * @param title
270    * @param optionType
271    * @param messageType
272    * @param icon
273    * @param options
274    * @param initialValue
275    * @return
276    * @throws HeadlessException
277    */
278   public static int showOptionDialog(Component parentComponent,
279           String message, String title, int optionType, int messageType,
280           Icon icon, Object[] options, Object initialValue)
281           throws HeadlessException
282   {
283     if (!isInteractiveMode())
284     {
285       return (int) getMockResponse();
286     }
287     // two uses:
288     //
289     // TODO
290     //
291     // 1) AlignViewport for openLinkedAlignment
292     //
293     // Show a dialog with the option to open and link (cDNA <-> protein) as a
294     // new
295     // alignment, either as a standalone alignment or in a split frame. Returns
296     // true if the new alignment was opened, false if not, because the user
297     // declined the offer.
298     //
299     // 2) UserDefinedColors warning about saving over a name already defined
300     //
301     return JOptionPane.showOptionDialog(parentComponent, message, title,
302             optionType, messageType, icon, options, initialValue);
303   }
304
305   /**
306    * Just an OK message
307    * 
308    * @param message
309    * @throws HeadlessException
310    */
311   public static void showMessageDialog(Component parentComponent,
312           String message) throws HeadlessException
313   {
314     if (!isInteractiveMode())
315     {
316       outputMessage(message);
317       return;
318     }
319
320     // test class only
321
322     JOptionPane.showMessageDialog(parentComponent, message);
323   }
324
325   /**
326    * OK with message, title, and type
327    * 
328    * @param parentComponent
329    * @param message
330    * @param title
331    * @param messageType
332    * @throws HeadlessException
333    */
334   public static void showMessageDialog(Component parentComponent,
335           String message, String title, int messageType)
336           throws HeadlessException
337   {
338     // 30 implementations -- all just fine.
339
340     if (!isInteractiveMode())
341     {
342       outputMessage(message);
343       return;
344     }
345
346     JOptionPane.showMessageDialog(parentComponent,
347             getPrefix(messageType) + message, title, messageType);
348   }
349
350   /**
351    * adds title and icon
352    * 
353    * @param parentComponent
354    * @param message
355    * @param title
356    * @param messageType
357    * @param icon
358    * @throws HeadlessException
359    */
360   public static void showMessageDialog(Component parentComponent,
361           String message, String title, int messageType, Icon icon)
362           throws HeadlessException
363   {
364
365     // test only
366
367     if (!isInteractiveMode())
368     {
369       outputMessage(message);
370       return;
371     }
372
373     JOptionPane.showMessageDialog(parentComponent, message, title,
374             messageType, icon);
375   }
376
377   /**
378    * was internal
379    * 
380    */
381   public static void showInternalMessageDialog(Component parentComponent,
382           Object message)
383   {
384
385     // WsPreferences only
386
387     if (!isInteractiveMode())
388     {
389       outputMessage(message);
390       return;
391     }
392
393     JOptionPane.showMessageDialog(parentComponent, message);
394   }
395
396
397   /**
398    * Adds title and messageType
399    * 
400    * @param parentComponent
401    * @param message
402    * @param title
403    * @param messageType
404    */
405   public static void showInternalMessageDialog(Component parentComponent,
406           String message, String title, int messageType)
407   {
408
409     // 41 references
410
411     if (!isInteractiveMode())
412     {
413       outputMessage(message);
414       return;
415     }
416
417     JOptionPane.showMessageDialog(parentComponent,
418             getPrefix(messageType) + message, title, messageType);
419   }
420
421   /**
422    * 
423    * @param parentComponent
424    * @param message
425    * @param title
426    * @param messageType
427    * @param icon
428    */
429   public static void showInternalMessageDialog(Component parentComponent,
430           Object message, String title, int messageType, Icon icon)
431   {
432
433     // test only
434
435     if (!isInteractiveMode())
436     {
437       outputMessage(message);
438       return;
439     }
440
441     JOptionPane.showMessageDialog(parentComponent, message, title,
442             messageType, icon);
443   }
444
445   /**
446    * 
447    * @param message
448    * @return
449    * @throws HeadlessException
450    */
451   public static String showInputDialog(Object message)
452           throws HeadlessException
453   {
454     // test only
455
456     if (!isInteractiveMode())
457     {
458       return getMockResponse().toString();
459     }
460
461     return JOptionPane.showInputDialog(message);
462   }
463
464   /**
465    * adds inital selection value
466    * 
467    * @param message
468    * @param initialSelectionValue
469    * @return
470    */
471   public static String showInputDialog(String message,
472           String initialSelectionValue)
473   {
474     if (!isInteractiveMode())
475     {
476       return getMockResponse().toString();
477     }
478
479     // AnnotationPanel character option
480
481     return JOptionPane.showInputDialog(message, initialSelectionValue);
482   }
483
484   /**
485    * adds inital selection value
486    * 
487    * @param message
488    * @param initialSelectionValue
489    * @return
490    */
491   public static String showInputDialog(Object message,
492           Object initialSelectionValue)
493   {
494     if (!isInteractiveMode())
495     {
496       return getMockResponse().toString();
497     }
498
499     // AnnotationPanel character option
500
501     return JOptionPane.showInputDialog(message, initialSelectionValue);
502   }
503   /**
504    * centered on parent
505    * 
506    * @param parentComponent
507    * @param message
508    * @return
509    * @throws HeadlessException
510    */
511   public static String showInputDialog(Component parentComponent,
512           String message) throws HeadlessException
513   {
514     // test only
515
516     return isInteractiveMode()
517             ? JOptionPane.showInputDialog(parentComponent, message)
518             : getMockResponse().toString();
519   }
520
521   /**
522    * input with initial selection
523    * 
524    * @param parentComponent
525    * @param message
526    * @param initialSelectionValue
527    * @return
528    */
529   public static String showInputDialog(Component parentComponent,
530           String message, String initialSelectionValue)
531   {
532     
533     // AnnotationPanel
534     
535     return isInteractiveMode()
536             ? JOptionPane.showInputDialog(parentComponent, message,
537                     initialSelectionValue)
538             : getMockResponse().toString();
539   }
540   
541
542   /**
543    * input with initial selection
544    * 
545    * @param parentComponent
546    * @param message
547    * @param initialSelectionValue
548    * @return
549    */
550   public static String showInputDialog(Component parentComponent,
551           Object message, Object initialSelectionValue)
552   {
553     
554     // AnnotationPanel
555     
556     return isInteractiveMode()
557             ? JOptionPane.showInputDialog(parentComponent, message,
558                     initialSelectionValue)
559             : getMockResponse().toString();
560   }
561
562   /**
563    * 
564    * @param parentComponent
565    * @param message
566    * @param title
567    * @param messageType
568    * @return
569    * @throws HeadlessException
570    */
571   public static String showInputDialog(Component parentComponent,
572           String message, String title, int messageType)
573           throws HeadlessException
574   {
575
576     // test only
577
578     return isInteractiveMode() ? JOptionPane
579             .showInputDialog(parentComponent, message, title, messageType)
580             : getMockResponse().toString();
581   }
582
583   /**
584    * Customized input option 
585    * 
586    * @param parentComponent
587    * @param message
588    * @param title
589    * @param messageType
590    * @param icon
591    * @param selectionValues
592    * @param initialSelectionValue
593    * @return
594    * @throws HeadlessException
595    */
596   public static Object showInputDialog(Component parentComponent,
597           Object message, String title, int messageType, Icon icon,
598           Object[] selectionValues, Object initialSelectionValue)
599           throws HeadlessException
600   {
601     
602     // test only
603     
604     return isInteractiveMode()
605             ? JOptionPane.showInputDialog(parentComponent, message, title,
606                     messageType, icon, selectionValues,
607                     initialSelectionValue)
608             : getMockResponse().toString();
609   }
610
611   
612   
613   /**
614    * internal version
615    * 
616    * @param parentComponent
617    * @param message
618    * @return
619    */
620   public static String showInternalInputDialog(Component parentComponent,
621           String message)
622   {
623     // test only
624     
625     return isInteractiveMode()
626             ? JOptionPane.showInternalInputDialog(parentComponent, message)
627             : getMockResponse().toString();
628   }
629
630   
631   /**
632    * internal with title and messageType
633    * 
634    * @param parentComponent
635    * @param message
636    * @param title
637    * @param messageType
638    * @return
639    */
640   public static String showInternalInputDialog(Component parentComponent,
641           String message, String title, int messageType)
642   {
643     
644     // AlignFrame tabbedPane_mousePressed
645     
646     return isInteractiveMode()
647             ? JOptionPane.showInternalInputDialog(parentComponent,
648                     getPrefix(messageType) + message, title, messageType)
649             : getMockResponse().toString();
650   }
651
652   /**
653    * customized internal
654    * 
655    * @param parentComponent
656    * @param message
657    * @param title
658    * @param messageType
659    * @param icon
660    * @param selectionValues
661    * @param initialSelectionValue
662    * @return
663    */
664   public static Object showInternalInputDialog(Component parentComponent,
665           String message, String title, int messageType, Icon icon,
666           Object[] selectionValues, Object initialSelectionValue)
667   {
668     // test only
669     
670     return isInteractiveMode()
671             ? JOptionPane.showInternalInputDialog(parentComponent, message,
672                     title, messageType, icon, selectionValues,
673                     initialSelectionValue)
674             : getMockResponse().toString();
675   }
676
677   
678   ///////////// end of options ///////////////
679   
680   
681   private static void outputMessage(Object message)
682   {
683     System.out.println(">>> JOption Message : " + message.toString());
684   }
685
686   public static Object getMockResponse()
687   {
688     return mockResponse;
689   }
690
691   public static void setMockResponse(Object mockOption)
692   {
693     JvOptionPane.mockResponse = mockOption;
694   }
695
696   public static void resetMock()
697   {
698     setMockResponse(JvOptionPane.CANCEL_OPTION);
699     setInteractiveMode(true);
700   }
701
702   public static boolean isInteractiveMode()
703   {
704     return interactiveMode;
705   }
706
707   public static void setInteractiveMode(boolean interactiveMode)
708   {
709     JvOptionPane.interactiveMode = interactiveMode;
710   }
711
712   @SuppressWarnings("unused")
713   private static String getPrefix(int messageType)
714   {
715     String prefix = ""; // JavaScript only
716
717     if (/** @j2sNative true || */
718     false)
719     {
720       switch (messageType)
721       {
722       case JvOptionPane.WARNING_MESSAGE:
723         prefix = "WARNING! ";
724         break;
725       case JvOptionPane.ERROR_MESSAGE:
726         prefix = "ERROR! ";
727         break;
728       default:
729         prefix = "Note: ";
730       }
731     }
732     return prefix;
733   }
734
735   DialogRunner<JvOptionPane> runner = new DialogRunner(this);
736
737   private List<Object> ourOptions;
738   /**
739    * create a new option dialog that can be used to register responses - along
740    * lines of showOptionDialog
741    * 
742    * @param desktop
743    * @param question
744    * @param string
745    * @param defaultOption
746    * @param plainMessage
747    * @param object
748    * @param options
749    * @param string2
750    * @return
751    */
752   public static JvOptionPane newOptionDialog(Component parentComponent)
753   {
754     return new JvOptionPane(parentComponent);
755   }
756
757   public void showDialog(
758           String message, String title, int optionType, int messageType,
759           Icon icon, Object[] options, Object initialValue)
760   {
761
762     if (!isInteractiveMode())
763     {
764       runner.firstRun((int) getMockResponse());
765     }
766     // two uses:
767     //
768     // TODO
769     //
770     // 1) AlignViewport for openLinkedAlignment
771     //
772     // Show a dialog with the option to open and link (cDNA <-> protein) as a
773     // new
774     // alignment, either as a standalone alignment or in a split frame. Returns
775     // true if the new alignment was opened, false if not, because the user
776     // declined the offer.
777     //
778     // 2) UserDefinedColors warning about saving over a name already defined
779     //
780     Component parent;
781     /**
782      * @j2sNative
783      * parent = this;
784      */
785     {
786       parent = parentComponent;
787     }
788     ;
789     ourOptions = Arrays.asList(options);
790     int response = JOptionPane.showOptionDialog(parent, message, title,
791             optionType, messageType, icon, options, initialValue);
792     /**
793      * @j2sNative
794      */
795     {
796       runner.firstRun(response);
797     }
798
799   }
800
801   public void showInternalDialog(JPanel mainPanel, String title,
802           int yesNoCancelOption, int questionMessage, Icon icon,
803           Object[] options, String initresponse)
804   {
805     if (!isInteractiveMode())
806     {
807       runner.firstRun((int) getMockResponse());
808     }
809     Component parent;
810     /**
811      * @j2sNative parent = this;
812      */
813     {
814       parent = parentComponent;
815     }
816     ourOptions = Arrays.asList(options);
817     
818     int response;
819     if (parent!=this) {
820
821       response = JOptionPane.showInternalOptionDialog(parent, mainPanel,
822               title, yesNoCancelOption, questionMessage, icon, options,
823               initresponse);
824     }
825     else
826     {
827       response = JOptionPane.showOptionDialog(parent, mainPanel, title,
828               yesNoCancelOption, questionMessage, icon, options,
829               initresponse);
830     }
831     /**
832      * @j2sNative
833      */
834     {
835       runner.firstRun(response);
836     }
837     
838   }
839   @Override
840   public JvOptionPane addResponse(RunResponse action)
841   {
842
843     runner.addResponse(action);
844     return this;
845   }
846
847   public JvOptionPane defaultResponse(Runnable runnable)
848   {
849     runner.setDefaultResponse(runnable);
850     return this;
851   }
852
853   @Override
854   public void propertyChange(PropertyChangeEvent evt)
855   {
856     int ourOption = ourOptions.indexOf(evt.getNewValue());
857     if (ourOption == -1)
858     {
859       // try our luck..
860       runner.run(evt.getNewValue());
861     }
862     else
863     {
864       runner.run(ourOption);
865     }
866   }
867
868
869 }