36f416cff8433506c20e14a5c8fc7cf1159564f1
[jalview.git] / src / jalview / gui / WsJobParameters.java
1 package jalview.gui;
2
3 import java.awt.BorderLayout;
4 import java.awt.Color;
5 import java.awt.Component;
6 import java.awt.Dimension;
7 import java.awt.FlowLayout;
8 import java.awt.Font;
9 import java.awt.GridLayout;
10 import java.awt.Rectangle;
11 import java.awt.event.ActionEvent;
12 import java.awt.event.ActionListener;
13 import java.awt.event.ComponentEvent;
14 import java.awt.event.ComponentListener;
15 import java.awt.event.ContainerEvent;
16 import java.awt.event.ContainerListener;
17 import java.awt.event.ItemEvent;
18 import java.awt.event.ItemListener;
19 import java.awt.event.KeyEvent;
20 import java.awt.event.KeyListener;
21 import java.awt.event.MouseEvent;
22 import java.awt.event.MouseListener;
23 import java.awt.event.WindowEvent;
24 import java.awt.event.WindowListener;
25 import java.awt.event.WindowStateListener;
26 import java.util.ArrayList;
27 import java.util.EventObject;
28 import java.util.HashSet;
29 import java.util.Hashtable;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Vector;
34
35 import javax.swing.JButton;
36 import javax.swing.JCheckBox;
37 import javax.swing.JComboBox;
38 import javax.swing.JDialog;
39 import javax.swing.JFrame;
40 import javax.swing.JLabel;
41 import javax.swing.JList;
42 import javax.swing.JOptionPane;
43 import javax.swing.JPanel;
44 import javax.swing.JScrollPane;
45 import javax.swing.JSlider;
46 import javax.swing.JTable;
47 import javax.swing.JTextArea;
48 import javax.swing.JTextField;
49 import javax.swing.ListSelectionModel;
50 import javax.swing.SwingConstants;
51 import javax.swing.SwingUtilities;
52 import javax.swing.border.TitledBorder;
53 import javax.swing.event.CellEditorListener;
54 import javax.swing.event.ChangeEvent;
55 import javax.swing.event.ChangeListener;
56 import javax.swing.table.*;
57
58 import compbio.metadata.Argument;
59 import compbio.metadata.Option;
60 import compbio.metadata.Parameter;
61 import compbio.metadata.Preset;
62 import compbio.metadata.PresetManager;
63 import compbio.metadata.RunnerConfig;
64 import compbio.metadata.ValueConstrain;
65 import compbio.metadata.WrongParameterException;
66 import compbio.metadata.ValueConstrain.Type;
67
68 import jalview.ws.jws2.Jws2Discoverer;
69 import jalview.ws.jws2.Jws2Discoverer.Jws2Instance;
70
71 public class WsJobParameters extends JPanel implements ItemListener,
72         ActionListener
73 {
74   private static final int PARAM_WIDTH = 340, PARAM_HEIGHT = 150,PARAM_CLOSEDHEIGHT=80;
75
76   private static final int OPTSET_HEIGHT = 30;
77
78   JPanel setDetails = new JPanel();
79
80   JPanel settingsPanel = new JPanel();
81
82   JPanel jobOptions = new JPanel();
83
84   JScrollPane jobOptionsPane = new JScrollPane();
85
86   JPanel jobParameters = new JPanel();
87
88   JPanel paramButtons = new JPanel();
89
90   JPanel paramPanel = new JPanel();
91
92   JLabel modified = new JLabel();
93
94   JButton startjob = new JButton();
95
96   JButton canceljob = new JButton();
97
98   JButton exportParams = new JButton();
99
100   JButton importParams = new JButton();
101
102   JButton resetParams = new JButton();
103
104   JButton addParam = new JButton();
105
106   JButton removeParam = new JButton();
107
108   JButton editParam = new JButton();
109
110   JComboBox setName = new JComboBox();
111
112   JTextArea setDescr = new JTextArea();
113
114   JScrollPane paramPane = new JScrollPane();
115
116   // JList paramList = new JList();
117   JPanel paramList = new JPanel();
118
119   RunnerConfig serviceOptions;
120
121   List<Parameter> availableParameters;
122
123   private BorderLayout jparamLayout;
124
125   WsJobParameters(Jws2Instance service)
126   {
127     this(service, null);
128   }
129
130   public WsJobParameters(Jws2Instance service, Preset p)
131   {
132     this(null, service, p, null);
133   }
134
135   /**
136    * 
137    * @param desktop
138    *          - if null, create new JFrame outside of desktop
139    * @param service
140    * @param p
141    */
142   public WsJobParameters(JFrame parent, Jws2Instance service, Preset p,
143           List<Argument> jobArgset)
144   {
145     super();
146     jbInit();
147     argSetModified(false);
148     // populate parameter table
149     initForService(service, p, jobArgset);
150     // display in new JFrame attached to parent.
151     validate();
152   }
153
154   int response = -1;
155
156   JDialog frame = null;
157
158   public boolean showRunDialog()
159   {
160
161     frame = new JDialog(Desktop.instance, true);
162
163     frame.setTitle("Edit parameters for " + service.getActionText());
164     Rectangle deskr = Desktop.instance.getBounds();
165     frame.setBounds(new Rectangle((int) (deskr.getCenterX() - 240),
166             (int) (deskr.getCenterY() - 92), 380, 385));
167     frame.setContentPane(this);
168
169     frame.setVisible(true);
170
171     if (response > 0)
172     {
173       return true;
174     }
175     return false;
176   }
177
178   private void jbInit()
179   {
180     modified.setText("*");
181     modified.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
182     modified.setForeground(Color.red);
183     modified.setHorizontalAlignment(SwingConstants.RIGHT);
184
185     exportParams.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
186     exportParams.setText("Export");
187     exportParams.setToolTipText("Export parameters to a file");
188     exportParams.addActionListener(new ActionListener()
189     {
190       public void actionPerformed(ActionEvent e)
191       {
192         exportParams_actionPerformed(e);
193       }
194     });
195     importParams.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
196     importParams.setText("Import");
197     importParams.setToolTipText("Import parameters from a file");
198     importParams.addActionListener(new ActionListener()
199     {
200       public void actionPerformed(ActionEvent e)
201       {
202         importParams_actionPerformed(e);
203       }
204     });
205     resetParams.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
206     resetParams.setText("Defaults");
207     resetParams.setToolTipText("Reset to defaults");
208     resetParams.addActionListener(new ActionListener()
209     {
210       public void actionPerformed(ActionEvent e)
211       {
212         resetParams_actionPerformed(e);
213       }
214     });
215     addParam.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
216     addParam.setText("Add");
217     addParam.setToolTipText("Add new parameter");
218     addParam.addActionListener(new ActionListener()
219     {
220       public void actionPerformed(ActionEvent e)
221       {
222         addParam_actionPerformed(e);
223       }
224     });
225     removeParam.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
226     removeParam.setText("Remove");
227     removeParam.setToolTipText("Remove selected parameter");
228     removeParam.addActionListener(new ActionListener()
229     {
230       public void actionPerformed(ActionEvent e)
231       {
232         removeParam_actionPerformed(e);
233       }
234     });
235     editParam.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
236     editParam.setText("Edit");
237     editParam.setToolTipText("Edit selected parameter");
238     editParam.addActionListener(new ActionListener()
239     {
240       public void actionPerformed(ActionEvent e)
241       {
242         editParam_actionPerformed(e);
243       }
244     });
245     startjob.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
246     startjob.setText("Start");
247     startjob.setToolTipText("Start Job");
248     startjob.addActionListener(new ActionListener()
249     {
250       public void actionPerformed(ActionEvent e)
251       {
252         startjob_actionPerformed(e);
253       }
254     });
255     canceljob.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
256     canceljob.setText("Cancel");
257     canceljob.setToolTipText("Cancel Job");
258     canceljob.addActionListener(new ActionListener()
259     {
260       public void actionPerformed(ActionEvent e)
261       {
262         canceljob_actionPerformed(e);
263       }
264     });
265
266     setDetails.setBorder(new TitledBorder("Details"));
267     setDetails.setLayout(new BorderLayout());
268     setDescr.setColumns(40);
269     setDescr.setWrapStyleWord(true);
270     setDescr.setLineWrap(true);
271     setDescr.setBackground(getBackground());
272     setDescr.setEditable(false);
273     JScrollPane setDescrView = new JScrollPane();
274     // setDescrView.setPreferredSize(new Dimension(350, 200));
275     setDescrView.getViewport().setView(setDescr);
276     setName.setEditable(true);
277     setName.addItemListener(this);
278     setName.getEditor().addActionListener(this);
279     modified.setPreferredSize(new Dimension(15, 15));
280     JPanel SetNamePanel = new JPanel();
281     SetNamePanel.setLayout(new BorderLayout());
282     SetNamePanel.add(setName, BorderLayout.WEST);
283     SetNamePanel.add(modified, BorderLayout.EAST);
284     setDetails.add(SetNamePanel, BorderLayout.NORTH);
285     setDetails.add(setDescrView, BorderLayout.CENTER);
286     // setDetails.setPreferredSize(new Dimension(360, 100));
287     jobParameters.setBorder(new TitledBorder("Parameters"));
288     jobParameters.setLayout(jparamLayout = new BorderLayout());
289     paramPane.setPreferredSize(new Dimension(360, 300));
290     paramPane.getVerticalScrollBar().setUnitIncrement(20);
291     // paramPanel.setPreferredSize(new Dimension(360, 300));
292     paramButtons.setLayout(new GridLayout(2, 3));
293     paramButtons.add(addParam);
294     paramButtons.add(editParam);
295     paramButtons.add(removeParam);
296     // TODO: relayout buttons nicely
297     paramButtons.add(exportParams);
298     paramButtons.add(importParams);
299     paramButtons.add(resetParams);
300     paramPane.getViewport().setView(paramList);
301     jobParameters.add(paramPane, BorderLayout.NORTH);
302     // jobParameters.add(paramButtons, BorderLayout.SOUTH);
303     settingsPanel.setLayout(new GridLayout(2,1));
304     // settingsPanel.add(modified, BorderLayout.NORTH);
305     JPanel jobOptionsPanel = new JPanel();
306     jobOptionsPanel.setLayout(new BorderLayout());
307     jobOptionsPanel.setBorder(new TitledBorder("Options"));
308     jobOptionsPane.getViewport().setView(jobOptions);
309     jobOptionsPanel.add(jobOptionsPane, BorderLayout.CENTER);
310     settingsPanel.add(jobOptionsPanel);
311     settingsPanel.add(jobParameters);
312
313     setLayout(new BorderLayout());
314     // setPreferredSize(new Dimension(400, 600));
315     // setSize(new Dimension(400, 600));
316     add(setDetails, BorderLayout.NORTH);
317     add(settingsPanel, BorderLayout.CENTER);
318     JPanel dialogpanel = new JPanel();
319     dialogpanel.add(startjob);
320     dialogpanel.add(canceljob);
321     add(dialogpanel, BorderLayout.SOUTH);
322   }
323
324   protected void canceljob_actionPerformed(ActionEvent e)
325   {
326     response = 0;
327     if (frame != null)
328     {
329       frame.setVisible(false);
330     }
331   }
332
333   protected void startjob_actionPerformed(ActionEvent e)
334   {
335     response = 1;
336     if (frame != null)
337     {
338       frame.setVisible(false);
339     }
340   }
341
342   protected void editParam_actionPerformed(ActionEvent e)
343   {
344     // TODO Auto-generated method stub
345
346   }
347
348   protected void removeParam_actionPerformed(ActionEvent e)
349   {
350     // TODO Auto-generated method stub
351
352   }
353
354   protected void addParam_actionPerformed(ActionEvent e)
355   {
356     // TODO Auto-generated method stub
357
358   }
359
360   protected void resetParams_actionPerformed(ActionEvent e)
361   {
362     // TODO Auto-generated method stub
363
364   }
365
366   protected void importParams_actionPerformed(ActionEvent e)
367   {
368     // TODO Auto-generated method stub
369
370   }
371
372   protected void exportParams_actionPerformed(ActionEvent e)
373   {
374     // TODO Auto-generated method stub
375
376   }
377
378   Jws2Instance service;
379
380   void initForService(Jws2Instance service, Preset p,
381           List<Argument> jobArgset)
382   {
383     this.service = service;
384     serviceOptions = service.getRunnerConfig();
385     // add any presets not already added.
386     String curname = (p == null ? "" : p.getName());
387     PresetManager prman = service.getPresets();
388     if (prman != null)
389     {
390       List prList = service.getPresets().getPresets();
391       if (prList != null)
392       {
393         for (Object pr : prList)
394         {
395           if (p == null || !curname.equals(((Preset) pr).getName()))
396           {
397             setName.addItem(((Preset) pr).getName());
398           }
399         }
400       }
401     }
402     updateTable(p, jobArgset);
403   }
404
405   @SuppressWarnings("unchecked")
406   private void updateTable(Preset p, List<Argument> jobArgset)
407   {
408     availableParameters = new ArrayList<Parameter>();
409     List<Parameter> setargs = new ArrayList<Parameter>();
410     // populate table from default parameter set.
411     List<Argument> args = serviceOptions.getArguments();
412
413     // split to params and required arguments
414     {
415       for (Argument arg : args)
416       {
417         Argument myarg = (Argument) arg;
418         // Ideally, Argument would implement isRequired !
419         if (myarg instanceof Parameter)
420         {
421           Parameter parm = (Parameter) myarg;
422           if (true) // parm.isRequired())
423           {
424             addParameter(parm);
425           }
426           else
427           {
428             availableParameters.add(parm);
429           }
430         }
431         else
432         {
433           if (myarg instanceof Option)
434           {
435             Option opt = (Option) myarg;
436             addOption(opt);
437             if (opt.isRequired())
438             {
439               selectOption(opt, opt.getDefaultValue());
440             }
441           }
442           else
443           {
444             System.err.println("Ignoring unknown service argument type "
445                     + arg.getClass().getName());
446           }
447         }
448       }
449       args = null; // no more args to process.
450     }
451     if (p != null)
452     {
453       if (lastParmSet == null)
454       {
455         // initialise setname
456         setName.addItem(p.getName());
457       }
458       setDescr.setText(p.getDescription());
459       // TODO - URL link
460       try
461       {
462         args = p.getArguments(serviceOptions);
463       } catch (Exception e)
464       {
465         e.printStackTrace();
466       }
467       // TODO: check if args should be unselected prior to resetting using the
468       // preset
469       setargs.clear();
470     }
471     else
472     {
473       if (lastParmSet == null)
474       {
475         // first call - so create a dummy name
476         setName.addItem("Defaults *");
477       }
478     }
479     if (jobArgset != null)
480     {
481       argSetModified(true);
482       args = jobArgset;
483     }
484     // get setargs from current object
485     if (args != null)
486     {
487       for (Argument arg : args)
488       {
489         if (arg instanceof Parameter)
490         {
491           setargs.add((Parameter) arg);
492         }
493         else
494         {
495           if (arg instanceof Option)
496           {
497             selectOption((Option) arg, arg.getDefaultValue());
498           }
499         }
500
501       }
502     }
503
504     // mdl.setData(setargs);
505     // jobOptions.setLayout(new GridLayout(optSet.size() / 2 + 1, 2));
506     jobOptions.setPreferredSize(new Dimension(PARAM_WIDTH, optSet.size()
507             * OPTSET_HEIGHT));
508     jobOptions.setLayout(new GridLayout(optSet.size(), 1));
509     refreshParamLayout();
510     // paramPanel.setLayout(new GridLayout(paramSet.size(), 1));
511     // paramList.va
512     // paramPane.getViewport().validate();
513     paramPane.validate();
514     validate();
515   }
516
517   private boolean isModified()
518   {
519     return modified.isVisible();
520   }
521
522   private void argSetModified(boolean b)
523   {
524     modified.setVisible(b);
525     /*
526      * String setn = (String)setName.getSelectedItem(); if (setn==null) return;
527      * int p = setName.getSelectedIndex(); if (b) { if (setn.length()<2 ||
528      * setn.lastIndexOf(" *")!=setn.length()-2) { setn = setn+" *"; } } else {
529      * if (setn.lastIndexOf(" *")==setn.length()-2) { setn =
530      * setn.substring(0,setn.length()-2); } } // edit the list
531      * 
532      * Object[] objects = new Object[setName.getItemCount()]; for (int
533      * i=0;i<objects.length; i++) { objects[i] = setName.getItemAt(i); }
534      * objects[p] = setn; setName.removeAllItems(); for (int
535      * i=0;i<objects.length; i++) { setName.addItem(objects[i]); }
536      * setName.setSelectedIndex(p);
537      */
538     validate();
539   }
540
541   private void addParameter(Parameter parm)
542   {
543     ParamBox pb = paramSet.get(parm.getName());
544     if (pb == null)
545     {
546       pb = new ParamBox(this, parm);
547       paramSet.put(parm.getName(), pb);
548       paramList.add(pb);
549     }
550   }
551
552   private void selectOption(Option opt, String string)
553   {
554     OptionBox cb = optSet.get(opt.getName());
555     if (cb == null)
556     {
557       cb = addOption(opt);
558     }
559     if (string == null)
560     {
561       // no value specified.
562       if (opt.isRequired())
563       {
564         // indicate option needs to be selected!
565       }
566       else
567       {
568         cb.enabled.setSelected(false);
569       }
570     }
571     else
572     {
573       cb.enabled.setSelected(true);
574
575       if (opt.getPossibleValues().contains(string))
576       {
577         cb.val.setSelectedItem(string);
578       }
579       else
580       {
581         throw new Error("Invalid value " + string + " for option " + opt);
582       }
583
584     }
585   }
586
587   Map<String, ParamBox> paramSet = new Hashtable<String, ParamBox>();
588
589   public class ParamBox extends JPanel implements ChangeListener,
590           ActionListener
591   {
592     JButton showDesc = new JButton();
593
594     JTextArea string = new JTextArea();
595     JScrollPane descPanel = new JScrollPane();
596
597     JSlider slider = null;
598
599     JTextField valueField = null;
600
601     ValueConstrain validator = null;
602     JPanel settingPanel = new JPanel();
603     JPanel controlPanel=new JPanel();
604
605     boolean integ = false;
606
607     boolean choice = false;
608     boolean descisvisible=false;
609     public ParamBox(final WsJobParameters pmlayout, Parameter parm)
610     {
611       setPreferredSize(new Dimension(PARAM_WIDTH, PARAM_CLOSEDHEIGHT));
612       setBorder(new TitledBorder(parm.getName()));
613       setLayout(null);
614       showDesc.setFont(new Font("Verdana", Font.PLAIN, 11));
615       showDesc.setText("?");
616       string.setFont(new Font("Verdana", Font.PLAIN, 11));
617       string.setBackground(getBackground());
618       // string.setSize(new Dimension(PARAM_WIDTH, 80));
619       string.setEditable(false);
620       descPanel.getViewport().setView(string);
621       //descPanel.setLocation(2,17);
622       descPanel.setVisible(false);
623       // string.setMinimumSize(new Dimension(140,80));
624       // string.setMaximumSize(new Dimension(280,80));
625       final ParamBox me=this;
626       showDesc.addActionListener(new ActionListener() {
627
628         @Override
629         public void actionPerformed(ActionEvent e)
630         {
631           descisvisible=!descisvisible;
632           descPanel.setVisible(descisvisible);
633           me.setPreferredSize(new Dimension(PARAM_WIDTH, (descisvisible) ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT));
634           me.validate();
635           pmlayout.refreshParamLayout();
636         }
637       });
638       string.setWrapStyleWord(true);
639       string.setLineWrap(true);
640       string.setColumns(32);
641       string.setText(parm.getDescription());
642       // name.setToolTipText(parm.getDescription());
643       JPanel firstrow = new JPanel();
644       firstrow.setLayout(null);
645       controlPanel.setLayout(new BorderLayout());
646       controlPanel.setBounds(new Rectangle(39, 10, PARAM_WIDTH-70,PARAM_CLOSEDHEIGHT-50));
647       showDesc.setBounds(new Rectangle(10,10,16,16));
648       firstrow.add(showDesc);
649       firstrow.add(controlPanel);
650       firstrow.setBounds(new Rectangle(10,20,PARAM_WIDTH-30, PARAM_CLOSEDHEIGHT-30));
651       add(firstrow);
652       validator = parm.getValidValue();
653       parameter = parm;
654       if (validator != null)
655       {
656         integ = validator.getType() == Type.Integer;
657       }
658       else
659       {
660         if (parameter.getPossibleValues() != null)
661         {
662           choice = true;
663         }
664       }
665       updateControls(parm);
666       descPanel.setBounds(new Rectangle(10,PARAM_CLOSEDHEIGHT+10, PARAM_WIDTH-20, PARAM_HEIGHT-PARAM_CLOSEDHEIGHT-30));
667       add(descPanel);
668       validate();
669     }
670
671
672     boolean adjusting = false;
673
674     Parameter parameter;
675
676     JComboBox choicebox;
677     public int getBoxHeight()
678     {
679       return (descisvisible ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT);
680     }
681     public void updateControls(Parameter parm)
682     {
683       adjusting = true;
684       boolean init = valueField == null;
685       float fVal = 0f;
686       int iVal = 0;
687       if (init)
688       {
689         if (choice)
690         {
691           choicebox = new JComboBox();
692           choicebox.addActionListener(this);
693           controlPanel.add(choicebox,BorderLayout.CENTER);
694         }
695         else
696         {
697           slider = new JSlider();
698           slider.addChangeListener(this);
699           valueField = new JTextField();
700           valueField.addActionListener(this);
701           valueField.setPreferredSize(new Dimension(60, 25));
702           controlPanel.add(slider,BorderLayout.WEST);
703           controlPanel.add(valueField, BorderLayout.EAST);
704
705         }
706       }
707
708       if (parm != null)
709       {
710         if (choice)
711         {
712           List vals = parm.getPossibleValues();
713           for (Object val : vals)
714           {
715             choicebox.addItem(val);
716           }
717           if (parm.getDefaultValue() != null)
718           {
719             choicebox.setSelectedItem(parm.getDefaultValue());
720           }
721         }
722         else
723         {
724           valueField.setText(parm.getDefaultValue());
725         }
726       }
727       updateSliderFromValueField();
728       adjusting = false;
729     }
730
731     public Parameter getParameter()
732     {
733       try
734       {
735         if (choice)
736         {
737           parameter.setDefaultValue((String) choicebox.getSelectedItem());
738         }
739         else
740         {
741           parameter.setDefaultValue(valueField.getText());
742         }
743       } catch (WrongParameterException e)
744       {
745         e.printStackTrace();
746         return null;
747       }
748       return parameter;
749     }
750
751     public Object updateSliderFromValueField()
752     {
753       int iVal;
754       float fVal;
755       if (validator != null)
756       {
757         if (integ)
758         {
759           iVal = 0;
760           try
761           {
762             valueField.setText(valueField.getText().trim());
763             iVal = Integer.valueOf(valueField.getText());
764           } catch (Exception e)
765           {
766           }
767           ;
768           if (validator.getMin() != null && validator.getMax() != null)
769           {
770             slider.getModel().setRangeProperties(iVal, 1,
771                     validator.getMin().intValue(),
772                     validator.getMax().intValue(), true);
773           }
774           else
775           {
776             slider.setVisible(false);
777           }
778           return new int[]
779           { iVal };
780         }
781         else
782         {
783           fVal = 0f;
784           try
785           {
786             fVal = Float.valueOf(valueField.getText());
787           } catch (Exception e)
788           {
789           }
790           ;
791           if (validator.getMin() != null && validator.getMax() != null)
792           {
793             slider.getModel().setRangeProperties((int) fVal * 1000, 1,
794                     (int) validator.getMin().floatValue() * 1000,
795                     (int) validator.getMax().floatValue() * 1000, true);
796           }
797           else
798           {
799             slider.setVisible(false);
800           }
801           return new float[]
802           { fVal };
803         }
804       }
805       else
806       {
807         if (!choice)
808         {
809           slider.setVisible(false);
810           return new String[]
811           { valueField.getText().trim() };
812         }
813         else
814         {
815           return new String[]
816           { (String) choicebox.getSelectedItem() };
817         }
818       }
819
820     }
821
822     @Override
823     public void stateChanged(ChangeEvent e)
824     {
825       if (!adjusting)
826       {
827         valueField.setText(""
828                 + ((integ) ? ("" + (int) slider.getValue())
829                         : ("" + (float) (slider.getValue() / 1000f))));
830       }
831     }
832
833     @Override
834     public void actionPerformed(ActionEvent e)
835     {
836       if (choice)
837       {
838       }
839       else if (!adjusting)
840       {
841         updateSliderFromValueField();
842       }
843       argSetModified(true);
844     }
845
846   }
847
848   Map<String, OptionBox> optSet = new Hashtable<String, OptionBox>();
849
850   public class OptionBox extends JPanel implements ActionListener
851   {
852     JComboBox val = new JComboBox();
853
854     JCheckBox enabled = new JCheckBox();
855
856     Option option;
857
858     public OptionBox(Option opt)
859     {
860       option = opt;
861       setLayout(new BorderLayout());
862       enabled.setSelected(opt.isRequired());
863       enabled.setFont(new Font("Verdana", Font.PLAIN, 11));
864       enabled.setText(opt.getName());
865       enabled.setToolTipText(opt.getDescription());
866       add(enabled, BorderLayout.NORTH);
867       if (opt.getPossibleValues().size() > 1)
868       {
869         setLayout(new GridLayout(1, 2));
870         for (Object str : opt.getPossibleValues())
871         {
872           val.addItem((String) str);
873         }
874         val.setSelectedItem((String) opt.getDefaultValue());
875         val.addActionListener(this);
876         add(val, BorderLayout.SOUTH);
877       }
878       // TODO: add actionListeners for popup (to open further info),
879       // and to update list of parameters if an option is enabled
880       // that takes a value.
881     }
882
883     public Option getOptionIfEnabled()
884     {
885       if (!enabled.isSelected())
886       {
887         return null;
888       }
889       try
890       {
891         if (val.getSelectedItem() != null)
892         {
893           option.setDefaultValue((String) val.getSelectedItem());
894         }
895       } catch (WrongParameterException e)
896       {
897         e.printStackTrace();
898         return null;
899       }
900       return option;
901     }
902
903     @Override
904     public void actionPerformed(ActionEvent e)
905     {
906       argSetModified(true);
907       enabled.setSelected(true);
908     }
909   }
910
911   private OptionBox addOption(Option opt)
912   {
913     OptionBox cb = optSet.get(opt.getName());
914     if (cb == null)
915     {
916       cb = new OptionBox(opt);
917       optSet.put(opt.getName(), cb);
918       jobOptions.add(cb);
919     }
920     return cb;
921   }
922
923   protected void refreshParamLayout()
924   {
925     int s=100;
926     for (ParamBox pbox : paramSet.values()){
927       s+=pbox.getBoxHeight();
928     }
929     paramList.setPreferredSize(new Dimension(PARAM_WIDTH, s));
930     paramList.setLayout(new FlowLayout());
931     validate();
932   }
933
934   /**
935    * testing method - grab a service and parameter set and show the window
936    * 
937    * @param args
938    */
939   public static void main(String[] args)
940   {
941     jalview.ws.jws2.Jws2Discoverer disc = jalview.ws.jws2.Jws2Discoverer
942             .getDiscoverer();
943     int p = 0;
944     if (args.length > 3)
945     {
946       Vector<String> services = new Vector<String>();
947       services.addElement(args[p++]);
948       Jws2Discoverer.setServiceUrls(services);
949     }
950     try
951     {
952       disc.run();
953     } catch (Exception e)
954     {
955       System.err.println("Aborting. Problem discovering services.");
956       e.printStackTrace();
957       return;
958     }
959     Jws2Discoverer.Jws2Instance lastserv = null;
960     for (Jws2Discoverer.Jws2Instance service : disc.getServices())
961     {
962       lastserv = service;
963       if (p < args.length && service.serviceType.equalsIgnoreCase(args[p]))
964       {
965         break;
966       }
967     }
968     if (lastserv != null)
969     {
970       List<Preset> prl = null;
971       Preset pr = null;
972       if (++p < args.length)
973       {
974         PresetManager prman = lastserv.getPresets();
975         if (prman != null)
976         {
977           pr = prman.getPresetByName(args[p]);
978           if (pr == null)
979           {
980             // just grab the last preset.
981             prl = prman.getPresets();
982           }
983         }
984       }
985       Iterator<Preset> en = (prl == null) ? null : prl.iterator();
986       while (true)
987       {
988         if (en != null)
989         {
990           if (!en.hasNext())
991           {
992             en = prl.iterator();
993           }
994           pr = en.next();
995         }
996         WsJobParameters pgui = new WsJobParameters(lastserv, pr);
997         JFrame jf = new JFrame("Parameters for " + lastserv.getActionText());
998         JPanel cont = new JPanel();
999         jf.setPreferredSize(new Dimension(600, 800));
1000         cont.add(pgui);
1001         jf.add(cont);
1002         final Thread thr = Thread.currentThread();
1003         jf.addWindowListener(new WindowListener()
1004         {
1005
1006           @Override
1007           public void windowActivated(WindowEvent e)
1008           {
1009             // TODO Auto-generated method stub
1010
1011           }
1012
1013           @Override
1014           public void windowClosed(WindowEvent e)
1015           {
1016           }
1017
1018           @Override
1019           public void windowClosing(WindowEvent e)
1020           {
1021             thr.interrupt();
1022
1023           }
1024
1025           @Override
1026           public void windowDeactivated(WindowEvent e)
1027           {
1028             // TODO Auto-generated method stub
1029
1030           }
1031
1032           @Override
1033           public void windowDeiconified(WindowEvent e)
1034           {
1035             // TODO Auto-generated method stub
1036
1037           }
1038
1039           @Override
1040           public void windowIconified(WindowEvent e)
1041           {
1042             // TODO Auto-generated method stub
1043
1044           }
1045
1046           @Override
1047           public void windowOpened(WindowEvent e)
1048           {
1049             // TODO Auto-generated method stub
1050
1051           }
1052
1053         });
1054         jf.setVisible(true);
1055         boolean inter = false;
1056         while (!inter)
1057         {
1058           try
1059           {
1060             Thread.sleep(10000);
1061           } catch (Exception e)
1062           {
1063             inter = true;
1064           }
1065           ;
1066         }
1067         jf.dispose();
1068       }
1069     }
1070   }
1071
1072   public List<Argument> getJobParams()
1073   {
1074     List<Argument> argSet = new ArrayList<Argument>();
1075     // recover options and parameters from GUI
1076     for (OptionBox opts : optSet.values())
1077     {
1078       Option opt = opts.getOptionIfEnabled();
1079       if (opt != null)
1080       {
1081         argSet.add(opt);
1082       }
1083     }
1084     for (ParamBox parambox : paramSet.values())
1085     {
1086       Parameter parm = parambox.getParameter();
1087       if (parm != null)
1088       {
1089         argSet.add(parm);
1090       }
1091     }
1092
1093     return argSet;
1094   }
1095
1096   String lastParmSet = null;
1097
1098   Hashtable<String, Object[]> editedParams = new Hashtable<String, Object[]>();
1099
1100   @Override
1101   public void itemStateChanged(ItemEvent e)
1102   {
1103     if (e.getSource() == setName)
1104     {
1105       String setname = (String) setName.getSelectedItem();
1106       if (setname == null)
1107       {
1108         return;
1109       }
1110       // if modified - warn user - or at least save current edited set.
1111       if (lastParmSet != null)
1112       {
1113         // save current state
1114         Object[] pset;
1115         editedParams.put(lastParmSet, pset = new Object[3]);
1116         pset[0] = lastParmSet;
1117         pset[1] = setDescr.getText();
1118         pset[2] = getJobParams();
1119       }
1120       Object[] pset = editedParams.get(setname);
1121       if (pset != null)
1122       {
1123         setDescr.setText((String) pset[1]);
1124         updateTable(null, (List<Argument>) pset[2]);
1125         lastParmSet = setname;
1126         validate();
1127       }
1128       else
1129       {
1130         // must be a default preset from service
1131         Preset p = null;
1132         try
1133         {
1134           PresetManager prman = service.getPresets();
1135           if (prman!=null)
1136           {
1137             p = prman.getPresetByName(setname);
1138           }
1139         } catch (Exception ex)
1140         {
1141           ex.printStackTrace();
1142         }
1143         if (p != null)
1144         {
1145           updateTable(p, null);
1146           validate();
1147           lastParmSet = setname;
1148         }
1149       }
1150
1151     }
1152   }
1153
1154   @Override
1155   public void actionPerformed(ActionEvent e)
1156   {
1157     if (e.getSource() == setName)
1158     {
1159       // rename any existing records we know about for this set.
1160       String newname = (String) setName.getSelectedItem();
1161       System.err.println("Command " + newname + " : "
1162               + e.getActionCommand());
1163     }
1164   }
1165 }