5c1218717d98095e60a4576cd7e46699feaeda61
[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.net.URL;
27 import java.util.ArrayList;
28 import java.util.EventObject;
29 import java.util.HashSet;
30 import java.util.Hashtable;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Vector;
35
36 import javax.swing.InputVerifier;
37 import javax.swing.JButton;
38 import javax.swing.JCheckBox;
39 import javax.swing.JComboBox;
40 import javax.swing.JComponent;
41 import javax.swing.JDialog;
42 import javax.swing.JFrame;
43 import javax.swing.JLabel;
44 import javax.swing.JList;
45 import javax.swing.JMenuItem;
46 import javax.swing.JOptionPane;
47 import javax.swing.JPanel;
48 import javax.swing.JPopupMenu;
49 import javax.swing.JScrollPane;
50 import javax.swing.JSlider;
51 import javax.swing.JSplitPane;
52 import javax.swing.JTabbedPane;
53 import javax.swing.JTable;
54 import javax.swing.JTextArea;
55 import javax.swing.JTextField;
56 import javax.swing.ListSelectionModel;
57 import javax.swing.SwingConstants;
58 import javax.swing.SwingUtilities;
59 import javax.swing.border.TitledBorder;
60 import javax.swing.event.CellEditorListener;
61 import javax.swing.event.ChangeEvent;
62 import javax.swing.event.ChangeListener;
63 import javax.swing.event.DocumentEvent;
64 import javax.swing.event.DocumentListener;
65 import javax.swing.table.*;
66
67 import compbio.metadata.Argument;
68 import compbio.metadata.Option;
69 import compbio.metadata.Parameter;
70 import compbio.metadata.Preset;
71 import compbio.metadata.PresetManager;
72 import compbio.metadata.RunnerConfig;
73 import compbio.metadata.ValueConstrain;
74 import compbio.metadata.WrongParameterException;
75 import compbio.metadata.ValueConstrain.Type;
76
77 import jalview.util.jarInputStreamProvider;
78 import jalview.ws.jws2.JabaParamStore;
79 import jalview.ws.jws2.JabaPreset;
80 import jalview.ws.jws2.Jws2Discoverer;
81 import jalview.ws.jws2.ParameterUtils;
82 import jalview.ws.jws2.Jws2Discoverer.Jws2Instance;
83 import jalview.ws.jws2.dm.JabaOption;
84 import jalview.ws.jws2.dm.JabaParameter;
85 import jalview.ws.params.ArgumentI;
86 import jalview.ws.params.OptionI;
87 import jalview.ws.params.ParamDatastoreI;
88 import jalview.ws.params.ParameterI;
89 import jalview.ws.params.ValueConstrainI;
90 import jalview.ws.params.WsParamSetI;
91
92 /**
93  * job parameter editing/browsing dialog box. User can browse existing settings
94  * (user + presets + Defaults), and any changes to parameters creates a modified
95  * user parameter set. LOGIC: If the parameter set is modified, and its name is
96  * a valid, non-existant user parameter set, then a save button is shown. If the
97  * parameter set is modified and its name is a valid, extant user parameter set,
98  * then an update button is shown. If user parameter set's name is edited, and
99  * old name exists as a writable user parameter set, then rename button is
100  * shown. If current parameter set is associated with a user defined parameter
101  * set, then : if set is modifed, a 'revert' button is shown. if set is not
102  * modified, a 'delete' button is shown.
103  * 
104  * @author JimP
105  * 
106  */
107 public class WsJobParameters extends JPanel implements ItemListener,
108         ActionListener, DocumentListener
109 {
110   URL linkImageURL = getClass().getResource("/images/link.gif");
111   private static final String SVC_DEF = "Defaults"; // this is the null
112                                                     // parameter set as shown to
113                                                     // user
114
115   private static final int PARAM_WIDTH = 340, PARAM_HEIGHT = 150,
116           PARAM_CLOSEDHEIGHT = 80;
117
118   private static final int OPTSET_HEIGHT = 30;
119
120   JPanel SetNamePanel = new JPanel();
121
122   JPanel setDetails = new JPanel();
123
124   JSplitPane settingsPanel = new JSplitPane();
125
126   JSplitPane jobPanel = new JSplitPane();
127   JTabbedPane tabpanels=new JTabbedPane();
128   JPanel jobOptions = new JPanel();
129
130   JScrollPane jobOptionsPane = new JScrollPane();
131
132   JPanel jobParameters = new JPanel();
133
134   JButton createpref = new JButton();
135
136   JButton deletepref = new JButton();
137
138   JButton revertpref = new JButton();
139
140   JButton updatepref = new JButton();
141
142   JButton startjob = new JButton();
143
144   JButton canceljob = new JButton();
145
146   JComboBox setName = new JComboBox();
147
148   JTextArea setDescr = new JTextArea();
149
150   JScrollPane paramPane = new JScrollPane();
151
152   JPanel paramList = new JPanel();
153
154   RunnerConfig serviceOptions;
155
156   ParamDatastoreI paramStore;
157
158   WsJobParameters(Jws2Instance service)
159   {
160     this(service, null);
161   }
162
163   public WsJobParameters(Jws2Instance service, WsParamSetI preset)
164   {
165     this(null, service, preset, null);
166   }
167
168   /**
169    * 
170    * @param desktop
171    *          - if null, create new JFrame outside of desktop
172    * @param service
173    * @param preset
174    */
175   public WsJobParameters(JFrame parent, Jws2Instance service,
176           WsParamSetI preset, List<Argument> jobArgset)
177   {
178     this(parent, null, service, preset, jobArgset);
179   }
180
181   /**
182    * 
183    * @param parent
184    * @param paramStorei
185    * @param service
186    * @param preset
187    * @param jobArgset
188    */
189   public WsJobParameters(JFrame parent, ParamDatastoreI paramStorei,
190           Jws2Instance service, WsParamSetI preset, List<Argument> jobArgset)
191   {
192     super();
193     jbInit();
194     this.paramStore = paramStorei;
195     if (paramStore == null)
196     {
197       paramStore = service.getParamStore();
198     }
199     this.service = service;
200     // argSetModified(false);
201     // populate parameter table
202     initForService(service, preset, jobArgset);
203     // display in new JFrame attached to parent.
204     validate();
205   }
206
207   int response = -1;
208
209   JDialog frame = null;
210
211   /**
212    * shows a modal dialog containing the parameters.
213    * 
214    * @return
215    */
216   public boolean showRunDialog()
217   {
218
219     frame = new JDialog(Desktop.instance, true);
220
221     frame.setTitle("Edit parameters for " + service.getActionText());
222     Rectangle deskr = Desktop.instance.getBounds();
223     frame.setBounds(new Rectangle((int) (deskr.getCenterX() - 240),
224             (int) (deskr.getCenterY() - 250), 480, 500));
225     frame.setContentPane(this);
226     // should recover defaults from user prefs.
227     //settingsPanel.setDividerLocation(0.4);
228     //jobPanel.setDividerLocation(0.5);
229     tabpanels.setSelectedComponent(jobOptionsPane);
230     frame.validate();
231     frame.setVisible(true);
232
233     if (response > 0)
234     {
235       return true;
236     }
237     return false;
238   }
239
240   protected JButton makeButton(String label, String tooltip,
241           ActionListener action)
242   {
243     JButton button = new JButton();
244     button.setText(label);
245     button.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
246     button.setForeground(Color.black);
247     button.setHorizontalAlignment(SwingConstants.CENTER);
248     button.setToolTipText(tooltip);
249     button.addActionListener(action);
250     return button;
251   }
252
253   private void jbInit()
254   {
255     updatepref = makeButton("Update", "Update the stored user preference",
256             new ActionListener()
257             {
258
259               public void actionPerformed(ActionEvent e)
260               {
261                 update_actionPerformed(e);
262               }
263             });
264     deletepref = makeButton("Delete", "Delete the user preference",
265             new ActionListener()
266             {
267
268               public void actionPerformed(ActionEvent e)
269               {
270                 delete_actionPerformed(e);
271               }
272             });
273     createpref = makeButton("Create", "Create a new preference",
274             new ActionListener()
275             {
276
277               public void actionPerformed(ActionEvent e)
278               {
279                 create_actionPerformed(e);
280               }
281             });
282     revertpref = makeButton("Revert",
283             "Undo all changes to the current set", new ActionListener()
284             {
285
286               public void actionPerformed(ActionEvent e)
287               {
288                 revert_actionPerformed(e);
289               }
290             });
291     startjob.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
292     startjob.setText("Start");
293     startjob.setToolTipText("Start Job");
294     startjob.addActionListener(new ActionListener()
295     {
296       public void actionPerformed(ActionEvent e)
297       {
298         startjob_actionPerformed(e);
299       }
300     });
301     canceljob.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
302     canceljob.setText("Cancel");
303     canceljob.setToolTipText("Cancel Job");
304     canceljob.addActionListener(new ActionListener()
305     {
306       public void actionPerformed(ActionEvent e)
307       {
308         canceljob_actionPerformed(e);
309       }
310     });
311
312     setDetails.setBorder(new TitledBorder("Details"));
313     setDetails.setLayout(new BorderLayout());
314     setDescr.setColumns(40);
315     setDescr.setWrapStyleWord(true);
316     setDescr.setLineWrap(true);
317     setDescr.setBackground(getBackground());
318     setDescr.setEditable(true);
319     setDescr.getDocument().addDocumentListener(this);
320     JScrollPane setDescrView = new JScrollPane();
321     // setDescrView.setPreferredSize(new Dimension(350, 200));
322     setDescrView.getViewport().setView(setDescr);
323     setName.setEditable(true);
324     setName.addItemListener(this);
325     setName.getEditor().addActionListener(this);
326     JPanel setNameInfo = new JPanel(new FlowLayout(FlowLayout.LEFT));
327     SetNamePanel.setLayout(new GridLayout(2, 1));
328     SetNamePanel.setMinimumSize(new Dimension(300, 40));
329     JLabel setNameLabel = new JLabel("Parameter set: ");
330     setNameLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
331     // setNameLabel.setHorizontalAlignment(FlowLayout.LEFT);
332     setNameInfo.add(setNameLabel);
333     setNameInfo.add(setName);
334     // initial button visibility
335     updatepref.setVisible(false);
336     deletepref.setVisible(false);
337     revertpref.setVisible(false);
338     createpref.setVisible(false);
339     JPanel setsavebuts = new JPanel();
340     setsavebuts.setLayout(new FlowLayout(FlowLayout.LEFT)); // GridLayout(1,2));
341     ((FlowLayout) setsavebuts.getLayout()).setHgap(10);
342     ((FlowLayout) setsavebuts.getLayout()).setVgap(0);
343     setsavebuts.add(deletepref);
344     setsavebuts.add(revertpref);
345     setsavebuts.add(createpref);
346     setsavebuts.add(updatepref);
347     setsavebuts.setSize(new Dimension(150, 20));
348     JPanel buttonArea = new JPanel(new GridLayout(1, 1));
349     buttonArea.add(setsavebuts);
350     SetNamePanel.add(setNameInfo);
351     SetNamePanel.add(buttonArea);
352     setDetails.add(setDescrView, BorderLayout.CENTER);
353     //setDetails.setPreferredSize(new Dimension(360, 100));
354     jobParameters.setBorder(new TitledBorder("Parameters"));
355     jobParameters.setLayout(new BorderLayout());
356     paramPane.setPreferredSize(new Dimension(360, 300));
357     paramPane.getVerticalScrollBar().setUnitIncrement(20);
358     // paramPanel.setPreferredSize(new Dimension(360, 300));
359     // TODO: relayout buttons nicely
360     paramPane.getViewport().setView(paramList);
361     jobParameters.add(paramPane, BorderLayout.CENTER);
362     JPanel jobOptionsPanel = new JPanel();
363     jobOptionsPanel.setLayout(new BorderLayout());
364     jobOptionsPanel.setBorder(new TitledBorder("Options"));
365     jobOptionsPane.getViewport().setView(jobOptions);
366     jobOptionsPanel.add(jobOptionsPane, BorderLayout.CENTER);
367     //settingsPanel.setLeftComponent(jobOptionsPanel);
368     //settingsPanel.setRightComponent(jobParameters);
369     //settingsPanel.setOrientation(JSplitPane.VERTICAL_SPLIT);
370
371     setLayout(new BorderLayout());
372     jobPanel.setLeftComponent(setDetails);
373     jobPanel.setRightComponent(tabpanels);
374     jobPanel.setOrientation(JSplitPane.VERTICAL_SPLIT);
375     add(SetNamePanel, BorderLayout.NORTH);
376     //add(jobPanel, BorderLayout.CENTER);
377     //setDescrView.setName("Description");
378     //tabpanels.add(setDescrView);
379     jobOptionsPane.setName("Options");
380     tabpanels.add(jobOptionsPane);
381     paramPane.setName("Parameters");
382     tabpanels.add(paramPane);
383     add(jobPanel, BorderLayout.CENTER);
384     JPanel dialogpanel = new JPanel();
385     dialogpanel.add(startjob);
386     dialogpanel.add(canceljob);
387     add(dialogpanel, BorderLayout.SOUTH);
388   }
389
390   protected void revert_actionPerformed(ActionEvent e)
391   {
392     reInitDialog(lastParmSet);
393
394   }
395
396   protected void update_actionPerformed(ActionEvent e)
397   {
398     if (isUserPreset)
399     {
400       String curname = ((String) setName.getSelectedItem()).trim();
401       _updatePreset(lastParmSet, curname);
402       lastParmSet = curname;
403       isUserPreset = true;
404       initArgSetModified();
405       syncSetNamesWithStore();
406     }
407   }
408
409   private void _deleteUserPreset(String lastParmSet2)
410   {
411     paramStore.deletePreset(lastParmSet2);
412   }
413
414   protected void delete_actionPerformed(ActionEvent e)
415   {
416     if (isUserPreset)
417     {
418       // delete current preset's saved entry
419       _deleteUserPreset(lastParmSet);
420     }
421     reInitDialog(null); // service default
422   }
423
424   protected void create_actionPerformed(ActionEvent e)
425   {
426     String curname = ((String) setName.getSelectedItem()).trim();
427     if (curname.length() > 0)
428     {
429       _storeCurrentPreset(curname);
430       lastParmSet = curname;
431       isUserPreset = true;
432       initArgSetModified();
433     }
434     else
435     {
436       // TODO: show warning
437       System.err.println("Invalid name. Not saved.");
438     }
439   }
440
441   protected void canceljob_actionPerformed(ActionEvent e)
442   {
443     response = 0;
444     if (frame != null)
445     {
446       frame.setVisible(false);
447     }
448   }
449
450   protected void startjob_actionPerformed(ActionEvent e)
451   {
452     response = 1;
453     if (frame != null)
454     {
455       frame.setVisible(false);
456     }
457   }
458
459   Jws2Instance service;
460
461   /**
462    * list of service presets in the gui
463    */
464   Hashtable servicePresets = null;
465
466   /**
467    * set if dialog is being set - so handlers will avoid spurious events
468    */
469   boolean settingDialog = false;
470
471   void initForService(Jws2Instance service, WsParamSetI jabap,
472           List<Argument> jabajobArgset)
473   {
474     WsParamSetI p = null;
475     List<ArgumentI> jobArgset = null;
476     settingDialog = true;
477     { // instantiate the abstract proxy for Jaba objects
478       jobArgset = jabajobArgset == null ? null : JabaParamStore
479               .getJwsArgsfromJaba(jabajobArgset);
480       p = jabap; // (jabap != null) ? paramStore.getPreset(jabap.getName()) :
481                  // null;
482     }
483     // TODO: Recover window geometry prefs for this service
484     // jobPanel.setDividerLocation(proportionalLocation)
485     // settingsPanel.setDividerLocation(proportionalLocation)
486     Hashtable exnames = new Hashtable();
487     for (int i = 0, iSize = setName.getItemCount(); i < iSize; i++)
488     {
489       exnames.put((String) setName.getItemAt(i), setName.getItemAt(i));
490     }
491     servicePresets = new Hashtable();
492     // Add the default entry - if not present already.
493     if (!exnames.contains(SVC_DEF))
494     {
495       setName.addItem(SVC_DEF);
496       exnames.put(SVC_DEF, SVC_DEF);
497       servicePresets.put(SVC_DEF, SVC_DEF);
498     }
499     String curname = (p == null ? "" : p.getName());
500     for (WsParamSetI pr : paramStore.getPresets())
501     {
502       if (!pr.isModifiable())
503       {
504         servicePresets.put(pr.getName(), "preset");
505       }
506       else
507       {
508       }
509       if (!exnames.contains(pr.getName()))
510       {
511         setName.addItem(pr.getName());
512       }
513     }
514     // TODO: if initial jobArgset matches a given user setting or preset then
515     // should recover setting accordingly
516     // updateTable(p, jobArgset);
517     if (p != null)
518     {
519       reInitDialog(p.getName());
520       initArgSetModified();
521     }
522     else
523     {
524       if (jobArgset != null && jobArgset.size() > 0)
525       {
526         curSetName = "Supplied Settings";
527         updateTable(p, jobArgset);
528       }
529       else
530       {
531         curSetName = null;
532         reInitDialog(null);
533       }
534     }
535     settingDialog = false;
536
537   }
538
539   @SuppressWarnings("unchecked")
540   private void updateTable(WsParamSetI p, List<ArgumentI> jobArgset)
541   {
542     // populate table from default parameter set.
543     List<ArgumentI> args = paramStore.getServiceParameters();
544
545     // split to params and required arguments
546     {
547       for (ArgumentI myarg : args)
548       {
549         // Ideally, Argument would implement isRequired !
550         if (myarg instanceof ParameterI)
551         {
552           ParameterI parm = (ParameterI) myarg;
553           addParameter(parm);
554         }
555         else
556         {
557           if (myarg instanceof OptionI)
558           {
559             OptionI opt = (OptionI) myarg;
560             addOption(opt).resetToDefault();
561           }
562           else
563           {
564             System.err.println("Ignoring unknown service argument type "
565                     + myarg.getClass().getName());
566           }
567         }
568       }
569       args = null; // no more args to process.
570     }
571     if (p != null)
572     {
573       isUserPreset = false;
574       // initialise setname
575       setName.setSelectedItem(lastSetName = p.getName());
576       setDescr.setText(lastDescrText = p.getDescription());
577       // TODO - URL link
578       try
579       {
580         args = p.getArguments();
581       } catch (Exception e)
582       {
583         e.printStackTrace();
584       }
585       // TODO: check if args should be unselected prior to resetting using the
586       // preset
587     }
588     else
589     {
590       if (lastParmSet == null)
591       {
592         isUserPreset = false;
593         // first call - so create a dummy name
594
595         setName.setSelectedItem(lastSetName = SVC_DEF);
596       }
597     }
598
599     if (jobArgset != null)
600     {
601       argSetModified(jobArgset, true);
602       args = jobArgset;
603     }
604     // get setargs from current object
605     if (args != null)
606     {
607       for (ArgumentI arg : args)
608       {
609         if (arg instanceof ParameterI)
610         {
611           setParameter((ParameterI) arg);
612         }
613         else
614         {
615           if (arg instanceof OptionI)
616           {
617             // System.out.println("Setting option "
618             // + System.identityHashCode(arg) + ":" + arg.getName()
619             // + " with " + arg.getDefaultValue());
620             selectOption((OptionI) arg, arg.getDefaultValue());
621           }
622         }
623
624       }
625     }
626
627     jobOptions.setPreferredSize(new Dimension(PARAM_WIDTH, optSet.size()
628             * OPTSET_HEIGHT));
629     jobOptions.setLayout(new GridLayout(optSet.size(), 1));
630     refreshParamLayout();
631     paramPane.validate();
632     revalidate();
633   }
634
635   private boolean isModified()
636   {
637     return modifiedElements.size() > 0;
638   }
639
640   private Hashtable modifiedElements = new Hashtable();
641
642   /**
643    * reset gui and modification state settings
644    */
645   private void initArgSetModified()
646   {
647     curSetName = null;
648     modifiedElements.clear();
649     updateButtonDisplay();
650   }
651
652   private void updateButtonDisplay()
653   {
654     boolean _update = false, _create = false, _delete = false, _revert = false;
655     if (modifiedElements.size() > 0)
656     {
657       // set modified
658       _revert = true;
659       _update = isUserPreset; // can only update user presets
660       if (!isUserPreset || modifiedElements.containsKey(setName))
661       {
662         // name modified - can create new preset
663         _create = true;
664       }
665     }
666     else
667     {
668       // set unmodified
669     }
670     // can still delete a user preset
671     _delete = isUserPreset;
672
673     createpref.setVisible(_create);
674     updatepref.setVisible(_update);
675     deletepref.setVisible(_delete);
676     revertpref.setVisible(_revert);
677     validate();
678   }
679
680   private void argSetModified(Object modifiedElement, boolean b)
681   {
682     if (settingDialog)
683     {
684       return;
685     }
686     if (!b)
687     {
688       modifiedElements.remove(modifiedElement);
689     }
690     else
691     {
692       if (b && modifiedElement == setName
693               && modifiedElements.contains(modifiedElement))
694       {
695         // HACK! prevents iteration on makeSetNameValid
696         b = false;
697       }
698       modifiedElements.put(modifiedElement, modifiedElement);
699     }
700     // set mod status based on presence of elements in table
701     if (b && modifiedElements.size() > 0)
702     {
703       makeSetNameValid(!isUserPreset);
704       SetNamePanel.revalidate();
705     }
706     updateButtonDisplay();
707   }
708
709   private boolean isServicePreset(String selectedItem)
710   {
711     return selectedItem.equals(SVC_DEF)
712             || servicePresets.containsKey(selectedItem);
713   }
714
715   /**
716    * check if the current set name is a valid set name for saving, if not, then
717    * fix it.
718    */
719   private void makeSetNameValid(boolean newuserset)
720   {
721     boolean stn = settingDialog;
722     boolean renamed = false;
723     settingDialog = true;
724     String nm = (curSetName != null ? curSetName : (String) setName
725             .getSelectedItem());
726     // check if the name is reserved - if it is, rename it.
727     if (isServicePreset(nm))
728     {
729       nm = "User " + nm;
730       renamed = true;
731     }
732     String tnm = nm;
733     if (newuserset)
734     {
735       int i = 0;
736       while (paramStore.getPreset(tnm) != null)
737       {
738         tnm = nm + " (" + (++i) + ")";
739         renamed = true;
740       }
741       if (i > 0)
742       {
743         nm = tnm;
744       }
745     }
746
747     boolean makeupdate = false;
748     // sync the gui with the preset database
749     for (int i = 0, iS = setName.getItemCount(); i < iS; i++)
750     {
751       String snm = (String) setName.getItemAt(i);
752       if (snm.equals(nm))
753       {
754         makeupdate = true;
755         // setName.setSelectedIndex(i);
756       }
757     }
758     if (!makeupdate)
759     {
760       setName.addItem(curSetName = nm);
761       setName.setSelectedItem(curSetName);
762     }
763     if (renamed)
764     {
765       settingDialog = false; // we need this name change to be registered.
766       argSetModified(setName, renamed);
767     }
768     settingDialog = stn;
769   }
770
771   private void addParameter(ParameterI arg)
772   {
773     ParamBox pb = paramSet.get(arg.getName());
774     if (pb == null)
775     {
776       pb = new ParamBox(this, arg);
777       paramSet.put(arg.getName(), pb);
778       paramList.add(pb);
779     }
780     pb.init();
781     // take the defaults from the parameter
782     pb.updateControls(arg);
783   }
784
785   private void setParameter(ParameterI arg)
786   {
787     ParamBox pb = paramSet.get(arg.getName());
788     if (pb == null)
789     {
790       addParameter(arg);
791     }
792     else
793     {
794       pb.updateControls(arg);
795     }
796
797   }
798
799   private void selectOption(OptionI option, String string)
800   {
801     OptionBox cb = optSet.get(option.getName());
802     if (cb == null)
803     {
804       cb = addOption(option);
805     }
806     cb.enabled.setSelected(string != null); // initial state for an option.
807     if (string != null)
808     {
809       if (option.getPossibleValues().contains(string))
810       {
811         cb.val.setSelectedItem(string);
812       }
813       else
814       {
815         throw new Error("Invalid value " + string + " for option " + option);
816       }
817
818     }
819     if (option.isRequired() && !cb.enabled.isSelected())
820     {
821       // TODO: indicate paramset is not valid.. option needs to be selected!
822     }
823     cb.setInitialValue();
824   }
825
826   Map<String, ParamBox> paramSet = new Hashtable<String, ParamBox>();
827
828   public class ParamBox extends JPanel implements ChangeListener,
829           ActionListener, MouseListener
830   {
831     JButton showDesc = new JButton();
832
833     JTextArea string = new JTextArea();
834
835     JScrollPane descPanel = new JScrollPane();
836
837     JSlider slider = null;
838
839     JTextField valueField = null;
840
841     ValueConstrainI validator = null;
842
843     JPanel settingPanel = new JPanel();
844
845     JPanel controlPanel = new JPanel();
846
847     boolean integ = false;
848
849     boolean choice = false;
850
851     boolean descisvisible = false;
852
853     final WsJobParameters pmdialogbox;
854
855     final URL finfo;
856
857     public ParamBox(final WsJobParameters pmlayout, ParameterI parm)
858     {
859       pmdialogbox = pmlayout;
860       setPreferredSize(new Dimension(PARAM_WIDTH, PARAM_CLOSEDHEIGHT));
861       setBorder(new TitledBorder(parm.getName()));
862       setLayout(null);
863       showDesc.setFont(new Font("Verdana", Font.PLAIN, 6));
864       showDesc.setText("+");
865       string.setFont(new Font("Verdana", Font.PLAIN, 11));
866       string.setBackground(getBackground());
867       // string.setSize(new Dimension(PARAM_WIDTH, 80));
868       string.setEditable(false);
869       descPanel.getViewport().setView(string);
870       // descPanel.setLocation(2,17);
871       descPanel.setVisible(false);
872       // string.setMinimumSize(new Dimension(140,80));
873       // string.setMaximumSize(new Dimension(280,80));
874       final ParamBox me = this;
875       finfo = parm.getFurtherDetails();
876       if (finfo != null)
877       {
878         showDesc.setToolTipText("<html><p>Click to show brief description<br><img src=\"" + linkImageURL + "\"/> Right click for further information.</p></html>");
879         showDesc.addMouseListener(this);
880       }
881       else
882       {
883         showDesc.setToolTipText("<html><p>Click to show brief description.</p></html>");
884       }
885       showDesc.addActionListener(new ActionListener()
886       {
887
888         public void actionPerformed(ActionEvent e)
889         {
890           descisvisible = !descisvisible;
891           descPanel.setVisible(descisvisible);
892           me.setPreferredSize(new Dimension(PARAM_WIDTH,
893                   (descisvisible) ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT));
894           me.validate();
895           pmlayout.refreshParamLayout();
896         }
897       });
898       string.setWrapStyleWord(true);
899       string.setLineWrap(true);
900       string.setColumns(32);
901       string.setText(parm.getDescription());
902       JPanel firstrow = new JPanel();
903       firstrow.setLayout(null);
904       controlPanel.setLayout(new BorderLayout());
905       controlPanel.setBounds(new Rectangle(39, 10, PARAM_WIDTH - 70,
906               PARAM_CLOSEDHEIGHT - 50));
907       showDesc.setBounds(new Rectangle(10, 10, 16, 16));
908       firstrow.add(showDesc);
909       firstrow.add(controlPanel);
910       firstrow.setBounds(new Rectangle(10, 20, PARAM_WIDTH - 30,
911               PARAM_CLOSEDHEIGHT - 30));
912       add(firstrow);
913       validator = parm.getValidValue();
914       parameter = parm;
915       if (validator != null)
916       {
917         integ = validator.getType() == Type.Integer;
918       }
919       else
920       {
921         if (parameter.getPossibleValues() != null)
922         {
923           choice = true;
924         }
925       }
926       updateControls(parm);
927       descPanel.setBounds(new Rectangle(10, PARAM_CLOSEDHEIGHT,
928               PARAM_WIDTH - 20, PARAM_HEIGHT - PARAM_CLOSEDHEIGHT - 5));
929       add(descPanel);
930       validate();
931     }
932
933     public void init()
934     {
935       // reset the widget's initial value.
936       lastVal = null;
937     }
938
939     boolean adjusting = false;
940
941     ParameterI parameter;
942
943     JComboBox choicebox;
944
945     public int getBoxHeight()
946     {
947       return (descisvisible ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT);
948     }
949
950     public void updateControls(ParameterI parm)
951     {
952       adjusting = true;
953       boolean init = (choicebox == null && valueField == null);
954       float fVal = 0f;
955       int iVal = 0;
956       if (init)
957       {
958         if (choice)
959         {
960           choicebox = new JComboBox();
961           choicebox.addActionListener(this);
962           controlPanel.add(choicebox, BorderLayout.CENTER);
963         }
964         else
965         {
966           slider = new JSlider();
967           slider.addChangeListener(this);
968           valueField = new JTextField();
969           valueField.addActionListener(this);
970           valueField.setPreferredSize(new Dimension(60, 25));
971           controlPanel.add(slider, BorderLayout.WEST);
972           controlPanel.add(valueField, BorderLayout.EAST);
973
974         }
975       }
976
977       if (parm != null)
978       {
979         if (choice)
980         {
981           if (init)
982           {
983             List vals = parm.getPossibleValues();
984             for (Object val : vals)
985             {
986               choicebox.addItem(val);
987             }
988           }
989
990           if (parm.getDefaultValue() != null)
991           {
992             choicebox.setSelectedItem(parm.getDefaultValue());
993           }
994         }
995         else
996         {
997           valueField.setText(parm.getDefaultValue());
998         }
999       }
1000       lastVal = updateSliderFromValueField();
1001       adjusting = false;
1002     }
1003
1004     Object lastVal;
1005
1006     public ParameterI getParameter()
1007     {
1008       ParameterI prm = parameter.copy();
1009       if (choice)
1010       {
1011         prm.setDefaultValue((String) choicebox.getSelectedItem());
1012       }
1013       else
1014       {
1015         prm.setDefaultValue(valueField.getText());
1016       }
1017       return prm;
1018     }
1019
1020     public Object updateSliderFromValueField()
1021     {
1022       int iVal;
1023       float fVal;
1024       if (validator != null)
1025       {
1026         if (integ)
1027         {
1028           iVal = 0;
1029           try
1030           {
1031             valueField.setText(valueField.getText().trim());
1032             iVal = Integer.valueOf(valueField.getText());
1033             if (validator.getMin() != null
1034                     && validator.getMin().intValue() > iVal)
1035             {
1036               iVal = validator.getMin().intValue();
1037               // TODO: provide visual indication that hard limit was reached for
1038               // this parameter
1039             }
1040             if (validator.getMax() != null
1041                     && validator.getMax().intValue() < iVal)
1042             {
1043               iVal = validator.getMax().intValue();
1044               // TODO: provide visual indication that hard limit was reached for
1045               // this parameter
1046             }
1047           } catch (Exception e)
1048           {
1049           }
1050           ;
1051           if (validator.getMin() != null && validator.getMax() != null)
1052           {
1053             slider.getModel().setRangeProperties(iVal, 1,
1054                     validator.getMin().intValue(),
1055                     validator.getMax().intValue(), true);
1056           }
1057           else
1058           {
1059             slider.setVisible(false);
1060           }
1061           return new int[]
1062           { iVal };
1063         }
1064         else
1065         {
1066           fVal = 0f;
1067           try
1068           {
1069             fVal = Float.valueOf(valueField.getText());
1070             if (validator.getMin() != null
1071                     && validator.getMin().floatValue() > fVal)
1072             {
1073               fVal = validator.getMin().floatValue();
1074               // TODO: provide visual indication that hard limit was reached for
1075               // this parameter
1076             }
1077             if (validator.getMax() != null
1078                     && validator.getMax().floatValue() < fVal)
1079             {
1080               fVal = validator.getMax().floatValue();
1081               // TODO: provide visual indication that hard limit was reached for
1082               // this parameter
1083             }
1084           } catch (Exception e)
1085           {
1086           }
1087           ;
1088           if (validator.getMin() != null && validator.getMax() != null)
1089           {
1090             slider.getModel().setRangeProperties((int) fVal * 1000, 1,
1091                     (int) validator.getMin().floatValue() * 1000,
1092                     (int) validator.getMax().floatValue() * 1000, true);
1093           }
1094           else
1095           {
1096             slider.setVisible(false);
1097           }
1098           return new float[]
1099           { fVal };
1100         }
1101       }
1102       else
1103       {
1104         if (!choice)
1105         {
1106           slider.setVisible(false);
1107           return new String[]
1108           { valueField.getText().trim() };
1109         }
1110         else
1111         {
1112           return new String[]
1113           { (String) choicebox.getSelectedItem() };
1114         }
1115       }
1116
1117     }
1118
1119     public void stateChanged(ChangeEvent e)
1120     {
1121       if (!adjusting)
1122       {
1123         valueField.setText(""
1124                 + ((integ) ? ("" + (int) slider.getValue())
1125                         : ("" + (float) (slider.getValue() / 1000f))));
1126         checkIfModified();
1127       }
1128
1129     }
1130
1131     public void actionPerformed(ActionEvent e)
1132     {
1133       if (adjusting)
1134       {
1135         return;
1136       }
1137       if (!choice)
1138       {
1139         updateSliderFromValueField();
1140       }
1141       checkIfModified();
1142     }
1143
1144     private void checkIfModified()
1145     {
1146       Object cstate = updateSliderFromValueField();
1147       boolean notmod = false;
1148       if (cstate.getClass() == lastVal.getClass())
1149       {
1150         if (cstate instanceof int[])
1151         {
1152           notmod = (((int[]) cstate)[0] == ((int[]) lastVal)[0]);
1153         }
1154         else if (cstate instanceof float[])
1155         {
1156           notmod = (((float[]) cstate)[0] == ((float[]) lastVal)[0]);
1157         }
1158         else if (cstate instanceof String[])
1159         {
1160           notmod = (((String[]) cstate)[0].equals(((String[]) lastVal)[0]));
1161         }
1162       }
1163       pmdialogbox.argSetModified(this, !notmod);
1164     }
1165
1166     public void mouseClicked(MouseEvent e)
1167     {
1168       if (javax.swing.SwingUtilities.isRightMouseButton(e))
1169       {
1170         showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
1171       }
1172     }
1173
1174     public void mousePressed(MouseEvent e)
1175     {
1176       // TODO Auto-generated method stub
1177
1178     }
1179
1180     public void mouseReleased(MouseEvent e)
1181     {
1182       // TODO Auto-generated method stub
1183
1184     }
1185
1186     public void mouseEntered(MouseEvent e)
1187     {
1188       // TODO Auto-generated method stub
1189
1190     }
1191
1192     public void mouseExited(MouseEvent e)
1193     {
1194       // TODO Auto-generated method stub
1195
1196     }
1197
1198   }
1199
1200   Map<String, OptionBox> optSet = new Hashtable<String, OptionBox>();
1201
1202   public class OptionBox extends JPanel implements MouseListener,
1203           ActionListener
1204   {
1205     JComboBox val = new JComboBox();
1206
1207     JCheckBox enabled = new JCheckBox();
1208
1209     JLabel optlabel = new JLabel();
1210
1211     final URL finfo;
1212
1213     boolean hasLink = false;
1214
1215     OptionI option;
1216
1217     public OptionBox(OptionI opt)
1218     {
1219       option = opt;
1220       setLayout(new BorderLayout());
1221       enabled.setSelected(opt.isRequired()); // TODO: lock required options
1222       enabled.setFont(new Font("Verdana", Font.PLAIN, 11));
1223       enabled.setText("");
1224       enabled.setText(opt.getName());
1225       enabled.addActionListener(this);
1226       finfo = option.getFurtherDetails();
1227       if (finfo != null)
1228       {
1229         hasLink = true;
1230         // optlabel.setToolTipText("<html><p>"+opt.getDescription()+"</p><img src=\""+linkImageURL+"\"/></html>");
1231         enabled.setToolTipText("<html><p>" + opt.getDescription()
1232                 + "</p><img src=\"" + linkImageURL + "\"/></html>");
1233         // optlabel.addMouseListener(this);
1234         enabled.addMouseListener(this);
1235       }
1236       else
1237       {
1238         // optlabel.setToolTipText(opt.getDescription());
1239         enabled.setToolTipText(opt.getDescription());
1240       }
1241       add(enabled, BorderLayout.NORTH);
1242       if (opt.getPossibleValues().size() > 1)
1243       {
1244         setLayout(new GridLayout(1, 2));
1245         for (Object str : opt.getPossibleValues())
1246         {
1247           val.addItem((String) str);
1248         }
1249         val.setSelectedItem((String) opt.getDefaultValue());
1250         val.addActionListener(this);
1251         add(val, BorderLayout.SOUTH);
1252       }
1253       // TODO: add actionListeners for popup (to open further info),
1254       // and to update list of parameters if an option is enabled
1255       // that takes a value.
1256       setInitialValue();
1257     }
1258
1259     public void resetToDefault()
1260     {
1261       enabled.setSelected(false);
1262       if (option.isRequired())
1263       {
1264         // Apply default value
1265         selectOption(option, option.getDefaultValue());
1266       }
1267     }
1268
1269     boolean initEnabled = false;
1270
1271     String initVal = null;
1272
1273     public void setInitialValue()
1274     {
1275       initEnabled = enabled.isSelected();
1276       if (option.getPossibleValues() != null
1277               && option.getPossibleValues().size() > 1)
1278       {
1279         initVal = (String) val.getSelectedItem();
1280       }
1281       else
1282       {
1283         initVal = (initEnabled) ? option.getDefaultValue() : null;
1284       }
1285     }
1286
1287     public OptionI getOptionIfEnabled()
1288     {
1289       if (!enabled.isSelected())
1290       {
1291         return null;
1292       }
1293       OptionI opt = option.copy();
1294
1295       if (val.getSelectedItem() != null)
1296       {
1297         opt.setDefaultValue((String) val.getSelectedItem());
1298       }
1299       return opt;
1300     }
1301
1302     public void actionPerformed(ActionEvent e)
1303     {
1304       if (e.getSource() != enabled)
1305       {
1306         enabled.setSelected(true);
1307       }
1308       checkIfModified();
1309     }
1310
1311     private void checkIfModified()
1312     {
1313       boolean notmod = (initEnabled == enabled.isSelected());
1314       if (enabled.isSelected())
1315       {
1316         if (initVal != null)
1317         {
1318           notmod &= initVal.equals(val.getSelectedItem());
1319         }
1320         else
1321         {
1322           // compare against default service setting
1323           notmod &= option.getDefaultValue() == null
1324                   || option.getDefaultValue().equals(val.getSelectedItem());
1325         }
1326       }
1327       else
1328       {
1329         notmod &= initVal == null;
1330       }
1331       argSetModified(this, !notmod);
1332     }
1333
1334     public void mouseClicked(MouseEvent e)
1335     {
1336       if (javax.swing.SwingUtilities.isRightMouseButton(e))
1337       {
1338         showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
1339       }
1340     }
1341
1342     public void mousePressed(MouseEvent e)
1343     {
1344       // TODO Auto-generated method stub
1345
1346     }
1347
1348     public void mouseReleased(MouseEvent e)
1349     {
1350       // TODO Auto-generated method stub
1351
1352     }
1353
1354     public void mouseEntered(MouseEvent e)
1355     {
1356       // TODO Auto-generated method stub
1357
1358     }
1359
1360     public void mouseExited(MouseEvent e)
1361     {
1362       // TODO Auto-generated method stub
1363
1364     }
1365
1366   }
1367
1368   private OptionBox addOption(OptionI opt)
1369   {
1370     OptionBox cb = optSet.get(opt.getName());
1371     if (cb == null)
1372     {
1373       cb = new OptionBox(opt);
1374       optSet.put(opt.getName(), cb);
1375       jobOptions.add(cb);
1376     }
1377     return cb;
1378   }
1379
1380   public static void showUrlPopUp(JComponent invoker, final String finfo,
1381           int x, int y)
1382   {
1383
1384     JPopupMenu mnu = new JPopupMenu();
1385     JMenuItem mitem = new JMenuItem("View " + finfo);
1386     mitem.addActionListener(new ActionListener()
1387     {
1388
1389       @Override
1390       public void actionPerformed(ActionEvent e)
1391       {
1392         Desktop.showUrl(finfo);
1393
1394       }
1395     });
1396     mnu.add(mitem);
1397     mnu.show(invoker, x, y);
1398   }
1399
1400   protected void refreshParamLayout()
1401   {
1402     FlowLayout fl = new FlowLayout();
1403     paramList.setLayout(fl);
1404     int s = 2 * fl.getVgap();
1405     for (ParamBox pbox : paramSet.values())
1406     {
1407       s += fl.getVgap() + pbox.getBoxHeight(); // getBoxHeight();
1408     }
1409     paramList.setPreferredSize(new Dimension(PARAM_WIDTH, s));
1410     validate();
1411   }
1412
1413   /**
1414    * testing method - grab a service and parameter set and show the window
1415    * 
1416    * @param args
1417    */
1418   public static void main(String[] args)
1419   {
1420     jalview.ws.jws2.Jws2Discoverer disc = jalview.ws.jws2.Jws2Discoverer
1421             .getDiscoverer();
1422     int p = 0;
1423     if (args.length > 3)
1424     {
1425       Vector<String> services = new Vector<String>();
1426       services.addElement(args[p++]);
1427       Jws2Discoverer.setServiceUrls(services);
1428     }
1429     try
1430     {
1431       disc.run();
1432     } catch (Exception e)
1433     {
1434       System.err.println("Aborting. Problem discovering services.");
1435       e.printStackTrace();
1436       return;
1437     }
1438     Jws2Discoverer.Jws2Instance lastserv = null;
1439     for (Jws2Discoverer.Jws2Instance service : disc.getServices())
1440     {
1441       lastserv = service;
1442       if (p >= args.length || service.serviceType.equalsIgnoreCase(args[p]))
1443       {
1444         if (lastserv != null)
1445         {
1446           List<Preset> prl = null;
1447           Preset pr = null;
1448           if (++p < args.length)
1449           {
1450             PresetManager prman = lastserv.getPresets();
1451             if (prman != null)
1452             {
1453               pr = prman.getPresetByName(args[p]);
1454               if (pr == null)
1455               {
1456                 // just grab the last preset.
1457                 prl = prman.getPresets();
1458               }
1459             }
1460           }
1461           else
1462           {
1463             PresetManager prman = lastserv.getPresets();
1464             if (prman != null)
1465             {
1466               prl = prman.getPresets();
1467             }
1468           }
1469           Iterator<Preset> en = (prl == null) ? null : prl.iterator();
1470           while (en != null && en.hasNext())
1471           {
1472             if (en != null)
1473             {
1474               if (!en.hasNext())
1475               {
1476                 en = prl.iterator();
1477               }
1478               pr = en.next();
1479             }
1480             {
1481               System.out.println("Testing opts dupes for "
1482                       + lastserv.getUri() + " : "
1483                       + lastserv.getActionText() + ":" + pr.getName());
1484               List<Option> rg = lastserv.getRunnerConfig().getOptions();
1485               for (Option o : rg)
1486               {
1487                 try
1488                 {
1489                   Option cpy = jalview.ws.jws2.ParameterUtils.copyOption(o);
1490                 } catch (Exception e)
1491                 {
1492                   System.err.println("Failed to copy " + o.getName());
1493                   e.printStackTrace();
1494                 } catch (Error e)
1495                 {
1496                   System.err.println("Failed to copy " + o.getName());
1497                   e.printStackTrace();
1498                 }
1499               }
1500             }
1501             {
1502               System.out.println("Testing param dupes:");
1503               List<Parameter> rg = lastserv.getRunnerConfig()
1504                       .getParameters();
1505               for (Parameter o : rg)
1506               {
1507                 try
1508                 {
1509                   Parameter cpy = jalview.ws.jws2.ParameterUtils
1510                           .copyParameter(o);
1511                 } catch (Exception e)
1512                 {
1513                   System.err.println("Failed to copy " + o.getName());
1514                   e.printStackTrace();
1515                 } catch (Error e)
1516                 {
1517                   System.err.println("Failed to copy " + o.getName());
1518                   e.printStackTrace();
1519                 }
1520               }
1521             }
1522             {
1523               System.out.println("Testing param write:");
1524               List<String> writeparam = null, readparam = null;
1525               try
1526               {
1527                 writeparam = jalview.ws.jws2.ParameterUtils
1528                         .writeParameterSet(
1529                                 pr.getArguments(lastserv.getRunnerConfig()),
1530                                 " ");
1531                 System.out.println("Testing param read :");
1532                 List<Option> pset = jalview.ws.jws2.ParameterUtils
1533                         .processParameters(writeparam,
1534                                 lastserv.getRunnerConfig(), " ");
1535                 readparam = jalview.ws.jws2.ParameterUtils
1536                         .writeParameterSet(pset, " ");
1537                 Iterator<String> o = pr.getOptions().iterator(), s = writeparam
1538                         .iterator(), t = readparam.iterator();
1539                 boolean failed = false;
1540                 while (s.hasNext() && t.hasNext())
1541                 {
1542                   String on = o.next(), sn = s.next(), st = t.next();
1543                   if (!sn.equals(st))
1544                   {
1545                     System.out.println("Original was " + on
1546                             + " Phase 1 wrote " + sn + "\tPhase 2 wrote "
1547                             + st);
1548                     failed = true;
1549                   }
1550                 }
1551                 if (failed)
1552                 {
1553                   System.out.println("Original parameters:\n"
1554                           + pr.getOptions());
1555                   System.out.println("Wrote parameters in first set:\n"
1556                           + writeparam);
1557                   System.out.println("Wrote parameters in second set:\n"
1558                           + readparam);
1559
1560                 }
1561               } catch (Exception e)
1562               {
1563                 e.printStackTrace();
1564               }
1565             }
1566             WsJobParameters pgui = new WsJobParameters(lastserv,
1567                     new JabaPreset(lastserv, pr));
1568             JFrame jf = new JFrame("Parameters for "
1569                     + lastserv.getActionText());
1570             JPanel cont = new JPanel();
1571             // jf.setPreferredSize(new Dimension(600, 800));
1572             cont.add(pgui);
1573             jf.add(cont);
1574             final Thread thr = Thread.currentThread();
1575             jf.addWindowListener(new WindowListener()
1576             {
1577
1578               public void windowActivated(WindowEvent e)
1579               {
1580                 // TODO Auto-generated method stub
1581
1582               }
1583
1584               public void windowClosed(WindowEvent e)
1585               {
1586               }
1587
1588               public void windowClosing(WindowEvent e)
1589               {
1590                 thr.interrupt();
1591
1592               }
1593
1594               public void windowDeactivated(WindowEvent e)
1595               {
1596                 // TODO Auto-generated method stub
1597
1598               }
1599
1600               public void windowDeiconified(WindowEvent e)
1601               {
1602                 // TODO Auto-generated method stub
1603
1604               }
1605
1606               public void windowIconified(WindowEvent e)
1607               {
1608                 // TODO Auto-generated method stub
1609
1610               }
1611
1612               public void windowOpened(WindowEvent e)
1613               {
1614                 // TODO Auto-generated method stub
1615
1616               }
1617
1618             });
1619             jf.setVisible(true);
1620             boolean inter = false;
1621             while (!inter)
1622             {
1623               try
1624               {
1625                 Thread.sleep(10000);
1626               } catch (Exception e)
1627               {
1628                 inter = true;
1629               }
1630               ;
1631             }
1632             jf.dispose();
1633           }
1634         }
1635       }
1636     }
1637   }
1638
1639   public List<ArgumentI> getJobParams()
1640   {
1641     List<ArgumentI> argSet = new ArrayList<ArgumentI>();
1642     // recover options and parameters from GUI
1643     for (OptionBox opts : optSet.values())
1644     {
1645       OptionI opt = opts.getOptionIfEnabled();
1646       if (opt != null)
1647       {
1648         argSet.add(opt);
1649       }
1650     }
1651     for (ParamBox parambox : paramSet.values())
1652     {
1653       ParameterI parm = parambox.getParameter();
1654       if (parm != null)
1655       {
1656         argSet.add(parm);
1657       }
1658     }
1659
1660     return argSet;
1661   }
1662
1663   String lastParmSet = null;
1664
1665   /*
1666    * Hashtable<String, Object[]> editedParams = new Hashtable<String,
1667    * Object[]>();
1668    * 
1669    * store the given parameters in the user parameter set database.
1670    * 
1671    * @param storeSetName - lastParmSet
1672    * 
1673    * @param descr - setDescr.getText()
1674    * 
1675    * @param jobParams - getJobParams()
1676    * 
1677    * private void _storeUserPreset(String storeSetName, String descr,
1678    * List<ArgumentI> jobParams) { // this is a simple hash store. Object[] pset;
1679    * editedParams.put(storeSetName, pset = new Object[3]); pset[0] =
1680    * storeSetName; pset[1] = descr; pset[2] = jobParams; // writeParam("Saving "
1681    * + storeSetName + ": ", jobParams); }
1682    * 
1683    * private void writeParam(String nm, List<ArgumentI> params) { for (ArgumentI
1684    * p : params) { System.out.println(nm + ":" + System.identityHashCode(p) +
1685    * " Name: " + p.getName() + " Value: " + p.getDefaultValue()); } }
1686    * 
1687    * private Object[] _getUserPreset(String setName) { Object[] pset =
1688    * editedParams.get(setName); // if (pset != null) // writeParam("Retrieving "
1689    * + setName + ": ", (List<Argument>) pset[2]); return pset; }
1690    * 
1691    * * remove the given user preset from the preset stash
1692    * 
1693    * @param setName
1694    * 
1695    * private void _deleteUserPreset(String setName) {
1696    * editedParams.remove(setName); }
1697    */
1698
1699   private void syncSetNamesWithStore()
1700   {
1701     int n = 0;
1702     // remove any set names in the drop down menu that aren't either a reserved
1703     // setting, or a user defined or service preset.
1704     Vector items = new Vector();
1705     while (n < setName.getItemCount())
1706     {
1707       String item = (String) setName.getItemAt(n);
1708       if (!item.equals(SVC_DEF) && !paramStore.presetExists(item))
1709       {
1710         setName.removeItemAt(n);
1711       }
1712       else
1713       {
1714         items.addElement(item);
1715         n++;
1716       }
1717     }
1718     if (!items.contains(SVC_DEF))
1719     {
1720       setName.addItem(SVC_DEF);
1721     }
1722     for (WsParamSetI upn : paramStore.getPresets())
1723     {
1724       if (!items.contains(upn.getName()))
1725       {
1726         setName.addItem(upn.getName());
1727       }
1728     }
1729   }
1730
1731   /**
1732    * true if lastParmSet is a user preset
1733    */
1734   boolean isUserPreset = false;
1735
1736   private void reInitDialog(String nextPreset)
1737   {
1738     settingDialog = true;
1739     // updateTable(null,null); // first reset to defaults
1740     WsParamSetI pset = null;
1741     if (nextPreset != null && nextPreset.length() > 0)
1742     {
1743       pset = paramStore.getPreset(nextPreset);
1744     }
1745     if (pset != null)
1746     {
1747       if (pset.isModifiable())
1748       {
1749         isUserPreset = true;
1750         setDescr.setText(pset.getDescription());
1751         updateTable(null, pset.getArguments());
1752         lastParmSet = nextPreset;
1753       }
1754       else
1755       {
1756         isUserPreset = false;
1757         setDescr.setText("");
1758         // must be a default preset from service
1759         updateTable(pset, null);
1760         lastParmSet = nextPreset;
1761       }
1762     }
1763     else
1764     {
1765       isUserPreset = false;
1766       // Service defaults
1767       updateTable(null, null);
1768       lastParmSet = SVC_DEF;
1769     }
1770
1771     initArgSetModified();
1772     syncSetNamesWithStore();
1773     setName.setSelectedItem(lastParmSet);
1774     validate();
1775     settingDialog = false;
1776
1777   }
1778
1779   String curSetName = null;
1780
1781   public void itemStateChanged(ItemEvent e)
1782   {
1783     if (e.getSource() == setName && e.getStateChange() == e.SELECTED)
1784     {
1785       final String setname = (String) setName.getSelectedItem();
1786       System.out.println("Item state changed for " + setname
1787               + " (handling ? " + !settingDialog + ")");
1788       if (settingDialog)
1789       {
1790         // ignore event
1791         return;
1792       }
1793       if (setname == null)
1794       {
1795         return;
1796       }
1797       javax.swing.SwingUtilities.invokeLater(new Runnable()
1798       {
1799         public void run()
1800         {
1801           doPreferenceComboStateChange(setname);
1802         }
1803       });
1804     }
1805   }
1806
1807   private void doPreferenceComboStateChange(String setname)
1808   {
1809     // user has selected a different item from combo-box
1810     if (isModified())
1811     {
1812       String lsetname = (curSetName != null) ? curSetName : lastParmSet;
1813       if (lsetname.equals(setname))
1814       {
1815         // setname was just edited - so ignore this event.
1816         return;
1817       }
1818       settingDialog = true;
1819       System.out.println("Prompting to save " + lsetname);
1820       if (javax.swing.JOptionPane
1821               .showConfirmDialog(
1822                       this,
1823                       "Parameter set '"
1824                               + lsetname
1825                               + "' is modifed, and your changes will be lost.\nReally change preset ?",
1826                       "Warning: Unsaved Changes",
1827                       javax.swing.JOptionPane.OK_CANCEL_OPTION) != JOptionPane.OK_OPTION)
1828       {
1829         // revert the combobox to the current item
1830         settingDialog = true;
1831         setName.setSelectedItem(lsetname);
1832         settingDialog = false;
1833         // and leave.
1834         return;
1835         // System.out.println("Saving for " + lsetname);
1836         // _storeCurrentPreset(lsetname);
1837
1838       }
1839     }
1840     settingDialog = true;
1841     reInitDialog(setname);
1842     settingDialog = false;
1843
1844   }
1845
1846   private void _renameExistingPreset(String oldName, String curSetName2)
1847   {
1848     paramStore.updatePreset(oldName, curSetName2, setDescr.getText(),
1849             getJobParams());
1850   }
1851
1852   /**
1853    * store current settings as given name. You should then reset gui.
1854    * 
1855    * @param curSetName2
1856    */
1857   private void _storeCurrentPreset(String curSetName2)
1858   {
1859     paramStore.storePreset(curSetName2, setDescr.getText(), getJobParams());
1860   }
1861
1862   private void _updatePreset(String lastParmSet2, String curname)
1863   {
1864     paramStore.updatePreset(lastParmSet2, curname, setDescr.getText(),
1865             getJobParams());
1866
1867   }
1868
1869   /**
1870    * last saved name for this user preset
1871    */
1872   String lastSetName = null;
1873
1874   /**
1875    * last saved value of the description text for this user preset
1876    */
1877   String lastDescrText = null;
1878
1879   public void actionPerformed(ActionEvent e)
1880   {
1881     if (e.getSource() instanceof Component)
1882     {
1883       Component src = (Component) e.getSource();
1884       if (src.getParent() == setName)
1885       {
1886         // rename any existing records we know about for this set.
1887         String newname = (String) e.getActionCommand().trim();
1888         String msg = null;
1889         if (isServicePreset(newname))
1890         {
1891           final String oldname = curSetName!=null ? curSetName : lastParmSet;
1892           final Component ourframe=this;
1893           settingDialog=true;
1894           setName.getEditor().setItem(oldname);
1895           settingDialog=false;
1896           javax.swing.SwingUtilities.invokeLater(new Runnable() {public void run() {
1897             JOptionPane.showMessageDialog(ourframe, 
1898                     "Invalid name - preset already exists.", "Invalid name",
1899                     JOptionPane.WARNING_MESSAGE);
1900             }});
1901           
1902           return;
1903         }
1904         curSetName = newname;
1905         System.err.println("New name for user setting " + curSetName
1906                 + " (was " + setName.getSelectedItem() + ")");
1907         if (curSetName.equals(setName.getSelectedItem()))
1908         {
1909           curSetName = null;
1910         }
1911         if (curSetName != null)
1912         {
1913           argSetModified(setName, true);
1914           return;
1915         }
1916
1917       }
1918     }
1919   }
1920
1921   private void checkDescrModified()
1922   {
1923     if (!settingDialog)
1924     {
1925
1926       argSetModified(
1927               setDescr,
1928               (lastDescrText == null ? setDescr.getText().trim().length() > 0
1929                       : !setDescr.getText().equals(lastDescrText)));
1930
1931     }
1932   }
1933
1934   public void insertUpdate(DocumentEvent e)
1935   {
1936     checkDescrModified();
1937   }
1938
1939   public void removeUpdate(DocumentEvent e)
1940   {
1941     checkDescrModified();
1942   }
1943
1944   public void changedUpdate(DocumentEvent e)
1945   {
1946     checkDescrModified();
1947   }
1948
1949   /**
1950    * 
1951    * @return null or the service preset selected by the user
1952    */
1953   public WsParamSetI getPreset()
1954   {
1955     if (isUserPreset || isModified()
1956             || (lastParmSet != null && lastParmSet.equals(SVC_DEF)))
1957     {
1958       return null;
1959     }
1960     else
1961     {
1962       return paramStore.getPreset(lastParmSet);
1963     }
1964   }
1965 }