JAL-2937 use preferences for presets, simplify some constructors
[jalview.git] / src / jalview / gui / OptsAndParamsPage.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 package jalview.gui;
22
23 import jalview.util.MessageManager;
24 import jalview.ws.params.ArgumentI;
25 import jalview.ws.params.OptionI;
26 import jalview.ws.params.ParameterI;
27 import jalview.ws.params.ValueConstrainI;
28 import jalview.ws.params.ValueConstrainI.ValueType;
29 import jalview.ws.params.simple.BooleanOption;
30 import jalview.ws.params.simple.LogarithmicParameter;
31
32 import java.awt.BorderLayout;
33 import java.awt.Component;
34 import java.awt.Dimension;
35 import java.awt.Font;
36 import java.awt.GridLayout;
37 import java.awt.Rectangle;
38 import java.awt.event.ActionEvent;
39 import java.awt.event.ActionListener;
40 import java.awt.event.KeyEvent;
41 import java.awt.event.KeyListener;
42 import java.awt.event.MouseEvent;
43 import java.awt.event.MouseListener;
44 import java.net.URL;
45 import java.util.ArrayList;
46 import java.util.List;
47 import java.util.Map;
48
49 import javax.swing.JButton;
50 import javax.swing.JCheckBox;
51 import javax.swing.JComboBox;
52 import javax.swing.JComponent;
53 import javax.swing.JLabel;
54 import javax.swing.JMenuItem;
55 import javax.swing.JPanel;
56 import javax.swing.JPopupMenu;
57 import javax.swing.JScrollPane;
58 import javax.swing.JSlider;
59 import javax.swing.JTextArea;
60 import javax.swing.JTextField;
61 import javax.swing.border.TitledBorder;
62 import javax.swing.event.ChangeEvent;
63 import javax.swing.event.ChangeListener;
64
65 import net.miginfocom.swing.MigLayout;
66
67 /**
68  * GUI generator/manager for options and parameters. Originally abstracted from
69  * the WsJobParameters dialog box.
70  * 
71  * @author jprocter
72  * 
73  */
74 public class OptsAndParamsPage
75 {
76   /**
77    * compact or verbose style parameters
78    */
79   boolean compact = false;
80
81   public class OptionBox extends JPanel
82           implements MouseListener, ActionListener
83   {
84     JCheckBox enabled = new JCheckBox();
85
86     final URL finfo;
87
88     boolean hasLink = false;
89
90     boolean initEnabled = false;
91
92     String initVal = null;
93
94     OptionI option;
95
96     JLabel optlabel = new JLabel();
97
98     JComboBox val = new JComboBox();
99
100     public OptionBox(OptionI opt)
101     {
102       option = opt;
103       setLayout(new BorderLayout());
104       enabled.setSelected(opt.isRequired()); // TODO: lock required options
105       enabled.setFont(new Font("Verdana", Font.PLAIN, 11));
106       enabled.setText("");
107       enabled.setText(opt.getName());
108       enabled.addActionListener(this);
109       finfo = option.getFurtherDetails();
110       String desc = opt.getDescription();
111       if (finfo != null)
112       {
113         hasLink = true;
114
115         enabled.setToolTipText(JvSwingUtils.wrapTooltip(true,
116                 ((desc == null || desc.trim().length() == 0)
117                         ? MessageManager.getString(
118                                 "label.opt_and_params_further_details")
119                         : desc) + "<br><img src=\"" + linkImageURL
120                         + "\"/>"));
121         enabled.addMouseListener(this);
122       }
123       else
124       {
125         if (desc != null && desc.trim().length() > 0)
126         {
127           enabled.setToolTipText(
128                   JvSwingUtils.wrapTooltip(true, opt.getDescription()));
129         }
130       }
131       add(enabled, BorderLayout.NORTH);
132       for (Object str : opt.getPossibleValues())
133       {
134         val.addItem(str);
135       }
136       val.setSelectedItem(opt.getValue());
137       if (opt.getPossibleValues().size() > 1)
138       {
139         setLayout(new GridLayout(1, 2));
140         val.addActionListener(this);
141         add(val, BorderLayout.SOUTH);
142       }
143       // TODO: add actionListeners for popup (to open further info),
144       // and to update list of parameters if an option is enabled
145       // that takes a value. JBPNote: is this TODO still valid ?
146       setInitialValue();
147     }
148
149     @Override
150     public void actionPerformed(ActionEvent e)
151     {
152       if (e.getSource() != enabled)
153       {
154         enabled.setSelected(true);
155       }
156       checkIfModified();
157     }
158
159     private void checkIfModified()
160     {
161       boolean notmod = (initEnabled == enabled.isSelected());
162       if (enabled.isSelected())
163       {
164         if (initVal != null)
165         {
166           notmod &= initVal.equals(val.getSelectedItem());
167         }
168         else
169         {
170           // compare against default service setting
171           notmod &= option.getValue() == null
172                   || option.getValue().equals(val.getSelectedItem());
173         }
174       }
175       else
176       {
177         notmod &= (initVal != null) ? initVal.equals(val.getSelectedItem())
178                 : val.getSelectedItem() != initVal;
179       }
180       poparent.argSetModified(this, !notmod);
181     }
182
183     public OptionI getOptionIfEnabled()
184     {
185       if (!enabled.isSelected())
186       {
187         return null;
188       }
189       OptionI opt = option.copy();
190       if (opt.getPossibleValues() != null
191               && opt.getPossibleValues().size() == 1)
192       {
193         // Hack to make sure the default value for an enabled option with only
194         // one value is actually returned
195         opt.setValue(opt.getPossibleValues().get(0));
196       }
197       if (val.getSelectedItem() != null)
198       {
199         opt.setValue((String) val.getSelectedItem());
200       }
201       else
202       {
203         if (option.getValue() != null)
204         {
205           opt.setValue(option.getValue());
206         }
207       }
208       return opt;
209     }
210
211     @Override
212     public void mouseClicked(MouseEvent e)
213     {
214       if (e.isPopupTrigger()) // for Windows
215       {
216         showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
217       }
218     }
219
220     @Override
221     public void mouseEntered(MouseEvent e)
222     {
223       // TODO Auto-generated method stub
224
225     }
226
227     @Override
228     public void mouseExited(MouseEvent e)
229     {
230       // TODO Auto-generated method stub
231
232     }
233
234     @Override
235     public void mousePressed(MouseEvent e)
236     {
237       if (e.isPopupTrigger()) // Mac
238       {
239         showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
240       }
241     }
242
243     @Override
244     public void mouseReleased(MouseEvent e)
245     {
246     }
247
248     public void resetToDefault(boolean setDefaultParams)
249     {
250       enabled.setSelected(false);
251       if (option.isRequired()
252               || (setDefaultParams && option.getValue() != null))
253       {
254         // Apply default value
255         selectOption(option, option.getValue());
256       }
257     }
258
259     public void setInitialValue()
260     {
261       initEnabled = enabled.isSelected();
262       if (option.getPossibleValues() != null
263               && option.getPossibleValues().size() > 1)
264       {
265         initVal = (String) val.getSelectedItem();
266       }
267       else
268       {
269         initVal = (initEnabled) ? (String) val.getSelectedItem() : null;
270       }
271     }
272
273   }
274
275   public class ParamBox extends JPanel
276           implements ChangeListener, ActionListener, MouseListener
277   {
278
279     boolean isLogarithmic;
280
281     boolean adjusting = false;
282
283     boolean choice = false;
284
285     JComboBox choicebox;
286
287     JPanel controlPanel = new JPanel();
288
289     boolean descisvisible = false;
290
291     JScrollPane descPanel = new JScrollPane();
292
293     final URL finfo;
294
295     boolean integ = false;
296
297     Object lastVal;
298
299     ParameterI parameter;
300
301     final OptsParametersContainerI pmdialogbox;
302
303     JPanel settingPanel = new JPanel();
304
305     JButton showDesc = new JButton();
306
307     JSlider slider = null;
308
309     JTextArea string = new JTextArea();
310
311     ValueConstrainI validator = null;
312
313     JTextField valueField = null;
314
315     public ParamBox(final OptsParametersContainerI pmlayout,
316             ParameterI parm)
317     {
318       pmdialogbox = pmlayout;
319       finfo = parm.getFurtherDetails();
320       validator = parm.getValidValue();
321       parameter = parm;
322       if (validator != null)
323       {
324         integ = validator.getType() == ValueType.Integer;
325       }
326       else
327       {
328         if (parameter.getPossibleValues() != null)
329         {
330           choice = true;
331         }
332       }
333       if (parm instanceof LogarithmicParameter)
334       {
335         isLogarithmic = true;
336       }
337
338       if (!compact)
339       {
340         makeExpanderParam(parm);
341       }
342       else
343       {
344         makeCompactParam(parm);
345
346       }
347     }
348
349     private void makeCompactParam(ParameterI parm)
350     {
351       setLayout(new MigLayout("", "[][grow]"));
352
353       String ttipText = null;
354
355       controlPanel.setLayout(new BorderLayout());
356
357       if (parm.getDescription() != null
358               && parm.getDescription().trim().length() > 0)
359       {
360         // Only create description boxes if there actually is a description.
361         ttipText = (JvSwingUtils.wrapTooltip(true,
362                 parm.getDescription() + (finfo != null ? "<br><img src=\""
363                         + linkImageURL + "\"/>"
364                         + MessageManager.getString(
365                                 "label.opt_and_params_further_details")
366                         : "")));
367       }
368
369       JvSwingUtils.mgAddtoLayout(this, ttipText, new JLabel(parm.getName()),
370               controlPanel, "");
371       updateControls(parm);
372       validate();
373     }
374
375     private void makeExpanderParam(ParameterI parm)
376     {
377       setPreferredSize(new Dimension(PARAM_WIDTH, PARAM_CLOSEDHEIGHT));
378       setBorder(new TitledBorder(parm.getName()));
379       setLayout(null);
380       showDesc.setFont(new Font("Verdana", Font.PLAIN, 6));
381       showDesc.setText("+");
382       string.setFont(new Font("Verdana", Font.PLAIN, 11));
383       string.setBackground(getBackground());
384
385       string.setEditable(false);
386       descPanel.getViewport().setView(string);
387
388       descPanel.setVisible(false);
389
390       JPanel firstrow = new JPanel();
391       firstrow.setLayout(null);
392       controlPanel.setLayout(new BorderLayout());
393       controlPanel.setBounds(new Rectangle(39, 10, PARAM_WIDTH - 70,
394               PARAM_CLOSEDHEIGHT - 50));
395       firstrow.add(controlPanel);
396       firstrow.setBounds(new Rectangle(10, 20, PARAM_WIDTH - 30,
397               PARAM_CLOSEDHEIGHT - 30));
398
399       final ParamBox me = this;
400
401       if (parm.getDescription() != null
402               && parm.getDescription().trim().length() > 0)
403       {
404         // Only create description boxes if there actually is a description.
405         if (finfo != null)
406         {
407           showDesc.setToolTipText(JvSwingUtils.wrapTooltip(true,
408                   MessageManager.formatMessage(
409                           "label.opt_and_params_show_brief_desc_image_link",
410                           new String[]
411                           { linkImageURL.toExternalForm() })));
412           showDesc.addMouseListener(this);
413         }
414         else
415         {
416           showDesc.setToolTipText(
417                   JvSwingUtils.wrapTooltip(true, MessageManager.getString(
418                           "label.opt_and_params_show_brief_desc")));
419         }
420         showDesc.addActionListener(new ActionListener()
421         {
422
423           @Override
424           public void actionPerformed(ActionEvent e)
425           {
426             descisvisible = !descisvisible;
427             descPanel.setVisible(descisvisible);
428             descPanel.getVerticalScrollBar().setValue(0);
429             me.setPreferredSize(new Dimension(PARAM_WIDTH,
430                     (descisvisible) ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT));
431             me.validate();
432             pmdialogbox.refreshParamLayout();
433           }
434         });
435         string.setWrapStyleWord(true);
436         string.setLineWrap(true);
437         string.setColumns(32);
438         string.setText(parm.getDescription());
439         showDesc.setBounds(new Rectangle(10, 10, 16, 16));
440         firstrow.add(showDesc);
441       }
442       add(firstrow);
443       validator = parm.getValidValue();
444       parameter = parm;
445       if (validator != null)
446       {
447         integ = validator.getType() == ValueType.Integer;
448       }
449       else
450       {
451         if (parameter.getPossibleValues() != null)
452         {
453           choice = true;
454         }
455       }
456       updateControls(parm);
457       descPanel.setBounds(new Rectangle(10, PARAM_CLOSEDHEIGHT,
458               PARAM_WIDTH - 20, PARAM_HEIGHT - PARAM_CLOSEDHEIGHT - 5));
459       add(descPanel);
460       validate();
461     }
462
463     @Override
464     public void actionPerformed(ActionEvent e)
465     {
466       if (adjusting)
467       {
468         return;
469       }
470       if (!choice)
471       {
472         updateSliderFromValueField();
473       }
474       checkIfModified();
475     }
476
477     private void checkIfModified()
478     {
479       Object cstate = updateSliderFromValueField();
480       boolean notmod = false;
481       if (cstate.getClass() == lastVal.getClass())
482       {
483         if (cstate instanceof int[])
484         {
485           notmod = (((int[]) cstate)[0] == ((int[]) lastVal)[0]);
486         }
487         else if (cstate instanceof float[])
488         {
489           notmod = (((float[]) cstate)[0] == ((float[]) lastVal)[0]);
490         }
491         else if (cstate instanceof String[])
492         {
493           notmod = (((String[]) cstate)[0].equals(((String[]) lastVal)[0]));
494         }
495       }
496       pmdialogbox.argSetModified(this, !notmod);
497     }
498
499     @Override
500     public int getBaseline(int width, int height)
501     {
502       return 0;
503     }
504
505     // from
506     // http://stackoverflow.com/questions/2743177/top-alignment-for-flowlayout
507     // helpful hint of using the Java 1.6 alignBaseLine property of FlowLayout
508     @Override
509     public Component.BaselineResizeBehavior getBaselineResizeBehavior()
510     {
511       return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
512     }
513
514     public int getBoxHeight()
515     {
516       return (descisvisible ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT);
517     }
518
519     public ParameterI getParameter()
520     {
521       ParameterI prm = parameter.copy();
522       if (choice)
523       {
524         prm.setValue((String) choicebox.getSelectedItem());
525       }
526       else
527       {
528         prm.setValue(valueField.getText());
529       }
530       return prm;
531     }
532
533     public void init()
534     {
535       // reset the widget's initial value.
536       lastVal = null;
537     }
538
539     @Override
540     public void mouseClicked(MouseEvent e)
541     {
542       if (e.isPopupTrigger()) // for Windows
543       {
544         showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
545       }
546     }
547
548     @Override
549     public void mouseEntered(MouseEvent e)
550     {
551       // TODO Auto-generated method stub
552
553     }
554
555     @Override
556     public void mouseExited(MouseEvent e)
557     {
558       // TODO Auto-generated method stub
559
560     }
561
562     @Override
563     public void mousePressed(MouseEvent e)
564     {
565       if (e.isPopupTrigger()) // for Mac
566       {
567         showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
568       }
569     }
570
571     @Override
572     public void mouseReleased(MouseEvent e)
573     {
574       // TODO Auto-generated method stub
575
576     }
577
578     @Override
579     public void stateChanged(ChangeEvent e)
580     {
581       if (!adjusting)
582       {
583         if (!isLogarithmic)
584         {
585           valueField.setText("" + ((integ) ? ("" + slider.getValue())
586                   : ("" + slider.getValue() / 1000f)));
587         }
588         else
589         {
590           Double base = ((LogarithmicParameter) parameter).getBase();
591           Double value = Math.pow(
592                   base,
593                   slider.getValue() / 1000000f);
594           valueField.setText(formatDouble(value));
595         }
596         checkIfModified();
597       }
598
599     }
600
601     public String formatDouble(Double value)
602     {
603       String string = String.format("%3.3f", value);
604       if (value < 0.001)
605       {
606         string = String.format("%3.3e", value);
607       }
608       return string;
609     }
610
611     public void updateControls(ParameterI parm)
612     {
613       adjusting = true;
614       boolean init = (choicebox == null && valueField == null);
615       if (init)
616       {
617         if (choice)
618         {
619           choicebox = new JComboBox();
620           choicebox.addActionListener(this);
621           controlPanel.add(choicebox, BorderLayout.CENTER);
622         }
623         else
624         {
625           slider = new JSlider();
626           slider.addChangeListener(this);
627           valueField = new JTextField();
628           valueField.addActionListener(this);
629           valueField.addKeyListener(new KeyListener()
630           {
631
632             @Override
633             public void keyTyped(KeyEvent e)
634             {
635             }
636
637             @Override
638             public void keyReleased(KeyEvent e)
639             {
640               if (e.isActionKey())
641               {
642                 if (valueField.getText().trim().length() > 0)
643                 {
644                   actionPerformed(null);
645                 }
646               }
647             }
648
649             @Override
650             public void keyPressed(KeyEvent e)
651             {
652             }
653           });
654           valueField.setPreferredSize(new Dimension(60, 25));
655           controlPanel.add(slider, BorderLayout.WEST);
656           controlPanel.add(valueField, BorderLayout.EAST);
657
658         }
659       }
660
661       if (parm != null)
662       {
663         if (choice)
664         {
665           if (init)
666           {
667             List vals = parm.getPossibleValues();
668             for (Object val : vals)
669             {
670               choicebox.addItem(val);
671             }
672           }
673
674           if (parm.getValue() != null)
675           {
676             choicebox.setSelectedItem(parm.getValue());
677           }
678         }
679         else
680         {
681           if (parm instanceof LogarithmicParameter)
682           {
683             Double base = ((LogarithmicParameter) parm).getBase();
684             Double value = Math.pow(base,
685                     Double.parseDouble(parm.getValue()) / 1000000);
686             valueField.setText(formatDouble(value));
687           }
688           else
689           {
690             valueField.setText(parm.getValue());
691           }
692         }
693       }
694       lastVal = updateSliderFromValueField();
695       adjusting = false;
696     }
697
698     public Object updateSliderFromValueField()
699     {
700       int iVal;
701       float fVal;
702       double dVal;
703       if (validator != null)
704       {
705         if (integ)
706         {
707           iVal = 0;
708           try
709           {
710             valueField.setText(valueField.getText().trim());
711             iVal = Integer.valueOf(valueField.getText());
712             if (validator.getMin() != null
713                     && validator.getMin().intValue() > iVal)
714             {
715               iVal = validator.getMin().intValue();
716               // TODO: provide visual indication that hard limit was reached for
717               // this parameter
718             }
719             if (validator.getMax() != null
720                     && validator.getMax().intValue() < iVal)
721             {
722               iVal = validator.getMax().intValue();
723               // TODO: provide visual indication that hard limit was reached for
724               // this parameter
725             }
726           } catch (Exception e)
727           {
728           }
729           ;
730           // update value field to reflect any bound checking we performed.
731           valueField.setText("" + iVal);
732           if (validator.getMin() != null && validator.getMax() != null)
733           {
734             slider.getModel().setRangeProperties(iVal, 1,
735                     validator.getMin().intValue(),
736                     validator.getMax().intValue() + 1, true);
737           }
738           else
739           {
740             slider.setVisible(false);
741           }
742           return new int[] { iVal };
743         }
744         else if (isLogarithmic)
745         {
746           double eValue;
747           dVal = 0d;
748           try
749           {
750             valueField.setText(valueField.getText().trim());
751             eValue = Double.valueOf(valueField.getText());
752
753             dVal = Math.log(eValue) / Math
754                     .log(((LogarithmicParameter) parameter).getBase())
755                     * 1000000;
756
757             if (validator.getMin() != null
758                     && validator.getMin().doubleValue() > dVal)
759             {
760               dVal = validator.getMin().doubleValue();
761               // TODO: provide visual indication that hard limit was reached for
762               // this parameter
763               // update value field to reflect any bound checking we performed.
764               valueField.setText("" + formatDouble(eValue));
765             }
766             if (validator.getMax() != null
767                     && validator.getMax().doubleValue() < dVal)
768             {
769               dVal = validator.getMax().doubleValue();
770               // TODO: provide visual indication that hard limit was reached for
771               // this parameter
772               // update value field to reflect any bound checking we performed.
773               valueField.setText("" + formatDouble(eValue));
774             }
775           } catch (Exception e)
776           {
777           }
778           ;
779           if (validator.getMin() != null && validator.getMax() != null)
780           {
781             slider.getModel().setRangeProperties((int) (dVal), 1,
782                     (int) (validator.getMin().doubleValue()),
783                     1 + (int) (validator.getMax().doubleValue()),
784                     true);
785           }
786           else
787           {
788             slider.setVisible(false);
789           }
790           return new double[] { dVal };
791         }
792         else
793         {
794           fVal = 0f;
795           try
796           {
797             valueField.setText(valueField.getText().trim());
798             fVal = Float.valueOf(valueField.getText());
799             if (validator.getMin() != null
800                     && validator.getMin().floatValue() > fVal)
801             {
802               fVal = validator.getMin().floatValue();
803               // TODO: provide visual indication that hard limit was reached for
804               // this parameter
805               // update value field to reflect any bound checking we performed.
806               valueField.setText("" + fVal);
807             }
808             if (validator.getMax() != null
809                     && validator.getMax().floatValue() < fVal)
810             {
811               fVal = validator.getMax().floatValue();
812               // TODO: provide visual indication that hard limit was reached for
813               // this parameter
814               // update value field to reflect any bound checking we performed.
815               valueField.setText("" + fVal);
816             }
817           } catch (Exception e)
818           {
819           }
820           ;
821           if (validator.getMin() != null && validator.getMax() != null)
822           {
823             slider.getModel().setRangeProperties((int) (fVal * 1000f), 1,
824                     (int) (validator.getMin().floatValue() * 1000f),
825                     1 + (int) (validator.getMax().floatValue() * 1000f),
826                     true);
827           }
828           else
829           {
830             slider.setVisible(false);
831           }
832           return new float[] { fVal };
833         }
834       }
835       else
836       {
837         if (!choice)
838         {
839           slider.setVisible(false);
840           return new String[] { valueField.getText().trim() };
841         }
842         else
843         {
844           return new String[] { (String) choicebox.getSelectedItem() };
845         }
846       }
847
848     }
849   }
850
851   public static final int PARAM_WIDTH = 340;
852
853   public static final int PARAM_HEIGHT = 150;
854
855   public static final int PARAM_CLOSEDHEIGHT = 80;
856
857   public OptsAndParamsPage(OptsParametersContainerI paramContainer)
858   {
859     this(paramContainer, false);
860   }
861
862   public OptsAndParamsPage(OptsParametersContainerI paramContainer,
863           boolean compact)
864   {
865     poparent = paramContainer;
866     this.compact = compact;
867   }
868
869   public static void showUrlPopUp(JComponent invoker, final String finfo,
870           int x, int y)
871   {
872
873     JPopupMenu mnu = new JPopupMenu();
874     JMenuItem mitem = new JMenuItem(
875             MessageManager.formatMessage("label.view_params", new String[]
876             { finfo }));
877     mitem.addActionListener(new ActionListener()
878     {
879
880       @Override
881       public void actionPerformed(ActionEvent e)
882       {
883         Desktop.showUrl(finfo);
884
885       }
886     });
887     mnu.add(mitem);
888     mnu.show(invoker, x, y);
889   }
890
891   URL linkImageURL = getClass().getResource("/images/link.gif");
892
893   Map<String, OptionBox> optSet = new java.util.LinkedHashMap<>();
894
895   Map<String, ParamBox> paramSet = new java.util.LinkedHashMap<>();
896
897   public Map<String, OptionBox> getOptSet()
898   {
899     return optSet;
900   }
901
902   public void setOptSet(Map<String, OptionBox> optSet)
903   {
904     this.optSet = optSet;
905   }
906
907   public Map<String, ParamBox> getParamSet()
908   {
909     return paramSet;
910   }
911
912   public void setParamSet(Map<String, ParamBox> paramSet)
913   {
914     this.paramSet = paramSet;
915   }
916
917   OptsParametersContainerI poparent;
918
919   OptionBox addOption(OptionI opt)
920   {
921     OptionBox cb = optSet.get(opt.getName());
922     if (cb == null)
923     {
924       cb = new OptionBox(opt);
925       optSet.put(opt.getName(), cb);
926       // jobOptions.add(cb, FlowLayout.LEFT);
927     }
928     return cb;
929   }
930
931   ParamBox addParameter(ParameterI arg)
932   {
933     ParamBox pb = paramSet.get(arg.getName());
934     if (pb == null)
935     {
936       pb = new ParamBox(poparent, arg);
937       paramSet.put(arg.getName(), pb);
938       // paramList.add(pb);
939     }
940     pb.init();
941     // take the defaults from the parameter
942     pb.updateControls(arg);
943     return pb;
944   }
945
946   void selectOption(OptionI option, String string)
947   {
948     OptionBox cb = optSet.get(option.getName());
949     if (cb == null)
950     {
951       cb = addOption(option);
952     }
953     cb.enabled.setSelected(string != null); // initial state for an option.
954     if (string != null)
955     {
956       if (option.getPossibleValues().contains(string))
957       {
958         cb.val.setSelectedItem(string);
959       }
960       else
961       {
962         throw new Error(String.format("Invalid value '%s' for option '%s'",
963                 string, option.getName()));
964       }
965     }
966     if (option.isRequired() && !cb.enabled.isSelected())
967     {
968       // TODO: indicate paramset is not valid.. option needs to be selected!
969     }
970     cb.setInitialValue();
971   }
972
973   void setParameter(ParameterI arg)
974   {
975     ParamBox pb = paramSet.get(arg.getName());
976     if (pb == null)
977     {
978       addParameter(arg);
979     }
980     else
981     {
982       pb.updateControls(arg);
983     }
984
985   }
986
987   /**
988    * recover options and parameters from GUI
989    * 
990    * @return
991    */
992   public List<ArgumentI> getCurrentSettings()
993   {
994     List<ArgumentI> argSet = new ArrayList<>();
995     for (OptionBox opts : getOptSet().values())
996     {
997       OptionI opt = opts.getOptionIfEnabled();
998       if (opt != null)
999       {
1000         argSet.add(opt);
1001       }
1002     }
1003     for (ParamBox parambox : getParamSet().values())
1004     {
1005       ParameterI parm = parambox.getParameter();
1006       if (parm != null)
1007       {
1008         argSet.add(parm);
1009       }
1010     }
1011
1012     return argSet;
1013   }
1014
1015 }