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