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