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