JAL-3949 Complete new abstracted logging framework in jalview.log. Updated log calls...
[jalview.git] / src / jalview / gui / WsJobParameters.java
index 7c4391e..1c86fec 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
 package jalview.gui;
 
 import java.awt.BorderLayout;
@@ -5,41 +25,36 @@ import java.awt.Component;
 import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
 import java.awt.GridLayout;
+import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.awt.event.ComponentEvent;
-import java.awt.event.ComponentListener;
-import java.awt.event.ContainerEvent;
-import java.awt.event.ContainerListener;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
+import java.awt.event.HierarchyBoundsListener;
+import java.awt.event.HierarchyEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
 import java.awt.event.WindowEvent;
 import java.awt.event.WindowListener;
-import java.awt.event.WindowStateListener;
-import java.util.ArrayList;
-import java.util.EventObject;
-import java.util.HashSet;
+import java.net.URL;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.Vector;
 
 import javax.swing.JButton;
-import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
+import javax.swing.JDialog;
 import javax.swing.JFrame;
 import javax.swing.JLabel;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
-import javax.swing.JTable;
+import javax.swing.JSplitPane;
 import javax.swing.JTextArea;
-import javax.swing.ListSelectionModel;
-import javax.swing.SwingUtilities;
 import javax.swing.border.TitledBorder;
-import javax.swing.event.CellEditorListener;
-import javax.swing.table.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
 
 import compbio.metadata.Argument;
 import compbio.metadata.Option;
@@ -47,58 +62,105 @@ import compbio.metadata.Parameter;
 import compbio.metadata.Preset;
 import compbio.metadata.PresetManager;
 import compbio.metadata.RunnerConfig;
-import compbio.metadata.ValueConstrain;
-import compbio.metadata.ValueConstrain.Type;
-
+import jalview.bin.Cache;
+import jalview.gui.OptsAndParamsPage.OptionBox;
+import jalview.gui.OptsAndParamsPage.ParamBox;
+import jalview.util.MessageManager;
+import jalview.ws.jws2.JabaParamStore;
+import jalview.ws.jws2.JabaPreset;
 import jalview.ws.jws2.Jws2Discoverer;
-import jalview.ws.jws2.Jws2Discoverer.Jws2Instance;
-
-public class WsJobParameters extends JPanel
+import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.OptionI;
+import jalview.ws.params.ParamDatastoreI;
+import jalview.ws.params.ParameterI;
+import jalview.ws.params.WsParamSetI;
+import net.miginfocom.swing.MigLayout;
+
+/**
+ * job parameter editing/browsing dialog box. User can browse existing settings
+ * (user + presets + Defaults), and any changes to parameters creates a modified
+ * user parameter set. LOGIC: If the parameter set is modified, and its name is
+ * a valid, non-existant user parameter set, then a save button is shown. If the
+ * parameter set is modified and its name is a valid, extant user parameter set,
+ * then an update button is shown. If user parameter set's name is edited, and
+ * old name exists as a writable user parameter set, then rename button is
+ * shown. If current parameter set is associated with a user defined parameter
+ * set, then : if set is modifed, a 'revert' button is shown. if set is not
+ * modified, a 'delete' button is shown.
+ * 
+ * @author JimP
+ * 
+ */
+public class WsJobParameters extends JPanel implements ItemListener,
+        ActionListener, DocumentListener, OptsParametersContainerI
 {
-  JPanel setDetails = new JPanel();
+  URL linkImageURL = getClass().getResource("/images/link.gif");
+
+  private static final String SVC_DEF = "Defaults"; // this is the null
+                                                    // parameter set as shown to
+                                                    // user
 
-  JPanel settingsPanel = new JPanel();
+  /**
+   * manager for options and parameters.
+   */
+  OptsAndParamsPage opanp = new OptsAndParamsPage(this);
 
+  /**
+   * panel containing job options
+   */
   JPanel jobOptions = new JPanel();
 
-  JPanel jobParameters = new JPanel();
+  /**
+   * panel containing job parameters
+   */
+  JPanel paramList = new JPanel();
 
-  JPanel paramButtons = new JPanel();
+  JPanel SetNamePanel = new JPanel();
 
-  JButton exportParams = new JButton();
+  JPanel setDetails = new JPanel();
 
-  JButton importParams = new JButton();
+  JSplitPane settingsPanel = new JSplitPane();
 
-  JButton resetParams = new JButton();
+  JPanel jobPanel = new JPanel();
 
-  JButton addParam = new JButton();
+  JScrollPane jobOptionsPane = new JScrollPane();
 
-  JButton removeParam = new JButton();
+  JButton createpref = new JButton();
 
-  JButton editParam = new JButton();
+  JButton deletepref = new JButton();
 
-  JLabel setName = new JLabel();
+  JButton revertpref = new JButton();
 
-  JTextArea setDescr = new JTextArea();
+  JButton updatepref = new JButton();
 
-  JTable paramTable = new JTable();
+  JButton startjob = new JButton();
+
+  JButton canceljob = new JButton();
+
+  JComboBox setName = new JComboBox();
+
+  JTextArea setDescr = new JTextArea();
 
   JScrollPane paramPane = new JScrollPane();
 
+  // ScrollablePanel optsAndparams = new ScrollablePanel();
+  JPanel optsAndparams = new JPanel();
+
   RunnerConfig serviceOptions;
 
-  List<Parameter> availableParameters;
+  ParamDatastoreI paramStore;
 
-  private BorderLayout jparamLayout;
+  private int MAX_OPTWIDTH = 200;
 
   WsJobParameters(Jws2Instance service)
   {
     this(service, null);
   }
 
-  public WsJobParameters(Jws2Instance service, Preset p)
+  public WsJobParameters(Jws2Instance service, WsParamSetI preset)
   {
-    this(null, service, p);
+    this(null, service, preset, null);
   }
 
   /**
@@ -106,782 +168,1366 @@ public class WsJobParameters extends JPanel
    * @param desktop
    *          - if null, create new JFrame outside of desktop
    * @param service
-   * @param p
+   * @param preset
+   */
+  public WsJobParameters(JFrame parent, Jws2Instance service,
+          WsParamSetI preset, List<Argument> jobArgset)
+  {
+    this(parent, null, service, preset, jobArgset);
+  }
+
+  /**
+   * 
+   * @param parent
+   * @param paramStorei
+   * @param service
+   * @param preset
+   * @param jobArgset
    */
-  public WsJobParameters(JFrame parent, Jws2Instance service, Preset p)
+  public WsJobParameters(JFrame parent, ParamDatastoreI paramStorei,
+          Jws2Instance service, WsParamSetI preset,
+          List<Argument> jobArgset)
   {
     super();
     jbInit();
-    initTableUI();
+    this.paramStore = paramStorei;
+    if (paramStore == null)
+    {
+      paramStore = service.getParamStore();
+    }
+    this.service = service;
+    // argSetModified(false);
     // populate parameter table
-    initForService(service, p);
+    initForService(service, preset, jobArgset);
     // display in new JFrame attached to parent.
     validate();
   }
 
-  private void jbInit()
-  {
-    exportParams.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    exportParams.setText("Export");
-    exportParams.setToolTipText("Export parameters to a file");
-    exportParams.addActionListener(new ActionListener()
-    {
-      public void actionPerformed(ActionEvent e)
-      {
-        exportParams_actionPerformed(e);
-      }
-    });
-    importParams.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    importParams.setText("Import");
-    importParams.setToolTipText("Import parameters from a file");
-    importParams.addActionListener(new ActionListener()
-    {
-      public void actionPerformed(ActionEvent e)
-      {
-        importParams_actionPerformed(e);
-      }
-    });
-    resetParams.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    resetParams.setText("Defaults");
-    resetParams.setToolTipText("Reset to defaults");
-    resetParams.addActionListener(new ActionListener()
-    {
-      public void actionPerformed(ActionEvent e)
-      {
-        resetParams_actionPerformed(e);
-      }
-    });
-    addParam.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    addParam.setText("Add");
-    addParam.setToolTipText("Add new parameter");
-    addParam.addActionListener(new ActionListener()
-    {
-      public void actionPerformed(ActionEvent e)
-      {
-        addParam_actionPerformed(e);
-      }
-    });
-    removeParam.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    removeParam.setText("Remove");
-    removeParam.setToolTipText("Remove selected parameter");
-    removeParam.addActionListener(new ActionListener()
-    {
-      public void actionPerformed(ActionEvent e)
-      {
-        removeParam_actionPerformed(e);
-      }
-    });
-    editParam.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
-    editParam.setText("Edit");
-    editParam.setToolTipText("Edit selected parameter");
-    editParam.addActionListener(new ActionListener()
-    {
-      public void actionPerformed(ActionEvent e)
-      {
-        editParam_actionPerformed(e);
-      }
-    });
+  int response = -1;
 
-    setDetails.setBorder(new TitledBorder("Details"));
-    setDetails.setLayout(new GridLayout(2, 1));
-    setDescr.setColumns(40);
-    setDescr.setWrapStyleWord(true);
-    setDescr.setPreferredSize(new Dimension(350, 100));
-    setDetails.add(setName);
-    setDetails.add(setDescr);
-    setDetails.setPreferredSize(new Dimension(360, 150));
-    settingsPanel.setLayout(new BorderLayout());
-    jobOptions.setBorder(new TitledBorder("Options"));
-    jobParameters.setBorder(new TitledBorder("Parameters"));
-    jobParameters.setLayout(jparamLayout = new BorderLayout());
-    paramPane.setPreferredSize(new Dimension(360, 300));
-    paramButtons.setLayout(new GridLayout(2, 3));
-    paramButtons.add(addParam);
-    paramButtons.add(editParam);
-    paramButtons.add(removeParam);
-    // TODO: relayout buttons nicely
-    paramButtons.add(exportParams);
-    paramButtons.add(importParams);
-    paramButtons.add(resetParams);
-    jobParameters.add(paramPane, BorderLayout.NORTH);
-    jobParameters.add(paramButtons, BorderLayout.SOUTH);
-    settingsPanel.add(jobOptions, BorderLayout.NORTH);
-    settingsPanel.add(jobParameters, BorderLayout.SOUTH);
-    setLayout(new BorderLayout());
-    setPreferredSize(new Dimension(400, 600));
-    setSize(new Dimension(400, 600));
-    add(setDetails, BorderLayout.NORTH);
-    add(settingsPanel, BorderLayout.CENTER);
-  }
+  JDialog frame = null;
 
   /**
-   * need to populate table and validate after calling this to set up table and
-   * add it to pane
+   * shows a modal dialog containing the parameters.
+   * 
+   * @return
    */
-  public void initTableUI()
+  public boolean showRunDialog()
   {
-    paramTable = new JTable();
-    paramTable.getTableHeader()
-            .setFont(new Font("Verdana", Font.PLAIN, 12));
-    paramTable.setFont(new Font("Verdana", Font.PLAIN, 12));
 
-    paramPane.getViewport().removeAll();
-    paramPane.getViewport().add(paramTable);
-    paramTable.setDefaultRenderer(Argument.class, new ArgumentRenderer());
-    paramTable.setDefaultRenderer(Parameter.class, new ArgumentRenderer());
-    paramTable.setDefaultRenderer(Option.class, new ArgumentRenderer());
-    paramTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-    paramTable.addMouseListener(new MouseListener()
-    {
+    frame = new JDialog(Desktop.instance, true);
 
-      @Override
-      public void mouseClicked(MouseEvent e)
-      {
-        if (e.getClickCount() > 1)
-        {
-          editParam_actionPerformed(null);
-        }
-      }
+    frame.setTitle(MessageManager.formatMessage("label.edit_params_for",
+            new String[]
+            { service.getActionText() }));
+    Rectangle deskr = Desktop.instance.getBounds();
+    Dimension pref = this.getPreferredSize();
+    frame.setBounds(
+            new Rectangle((int) (deskr.getCenterX() - pref.width / 2),
+                    (int) (deskr.getCenterY() - pref.height / 2),
+                    pref.width, pref.height));
+    frame.setContentPane(this);
 
+    // should perhaps recover defaults from user prefs.
+
+    frame.validate();
+    javax.swing.SwingUtilities.invokeLater(new Runnable()
+    {
       @Override
-      public void mouseEntered(MouseEvent e)
+      public void run()
       {
-        // tooltips
-        // TODO Auto-generated method stub
+        // jobPanel.setDividerLocation(0.25);
 
       }
+    });
+    frame.setVisible(true);
 
-      @Override
-      public void mouseExited(MouseEvent e)
-      {
-        // tooltips
-        // TODO Auto-generated method stub
+    if (response > 0)
+    {
+      return true;
+    }
+    return false;
+  }
 
-      }
+  private void jbInit()
+  {
+    this.addHierarchyBoundsListener(new HierarchyBoundsListener()
+    {
 
       @Override
-      public void mousePressed(MouseEvent e)
+      public void ancestorResized(HierarchyEvent arg0)
       {
-        // TODO Auto-generated method stub
-
+        refreshParamLayout();
       }
 
       @Override
-      public void mouseReleased(MouseEvent e)
+      public void ancestorMoved(HierarchyEvent arg0)
       {
         // TODO Auto-generated method stub
 
       }
-
     });
-    // paramTable.setDefaultEditor(Argument.class, new WsArgumentEditor(this));
-  }
-
-  public class WsArgumentEditor implements TableCellEditor
-  {
-
-    int p;
-
-    Argument arg;
-
-    WsJobParameters wsparm;
-
-    public WsArgumentEditor(WsJobParameters wsJobParameters)
-    {
-      wsparm = wsJobParameters;
-      p = wsparm.paramTable.getSelectedRow();
-      arg = (Argument) wsparm.paramTable.getValueAt(p, wsparm.paramTable
-              .getSelectedColumn());
-      /*
-       * if (arg instanceof Option) { if
-       * (JOptionPane.showInternalConfirmDialog(Desktop.desktop,
-       * "Remove option "+arg.getName(),
-       * "Delete option ?",JOptionPane.YES_NO_OPTION,
-       * JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
-       * 
-       * } }
-       */
-    }
+    updatepref = JvSwingUtils.makeButton(
+            MessageManager.getString("action.update"),
+            MessageManager.getString("label.update_user_parameter_set"),
+            new ActionListener()
+            {
 
-    @Override
-    public Component getTableCellEditorComponent(JTable table,
-            Object value, boolean isSelected, int row, int column)
-    {
-      // TODO Auto-generated method stub
-      return null;
-    }
+              @Override
+              public void actionPerformed(ActionEvent e)
+              {
+                update_actionPerformed(e);
+              }
+            });
+    deletepref = JvSwingUtils.makeButton(
+            MessageManager.getString("action.delete"),
+            MessageManager.getString("label.delete_user_parameter_set"),
+            new ActionListener()
+            {
 
-    @Override
-    public void addCellEditorListener(CellEditorListener l)
-    {
-      // TODO Auto-generated method stub
+              @Override
+              public void actionPerformed(ActionEvent e)
+              {
+                delete_actionPerformed(e);
+              }
+            });
+    createpref = JvSwingUtils.makeButton(
+            MessageManager.getString("action.create"),
+            MessageManager.getString("label.create_user_parameter_set"),
+            new ActionListener()
+            {
 
-    }
+              @Override
+              public void actionPerformed(ActionEvent e)
+              {
+                create_actionPerformed(e);
+              }
+            });
+    revertpref = JvSwingUtils.makeButton(
+            MessageManager.getString("action.revert"),
+            MessageManager
+                    .getString("label.revert_changes_user_parameter_set"),
+            new ActionListener()
+            {
 
-    @Override
-    public void cancelCellEditing()
-    {
-      // TODO Auto-generated method stub
+              @Override
+              public void actionPerformed(ActionEvent e)
+              {
+                revert_actionPerformed(e);
+              }
+            });
+    startjob = JvSwingUtils.makeButton(
+            MessageManager.getString("action.start_job"),
+            MessageManager.getString("label.start_job_current_settings"),
+            new ActionListener()
+            {
+              @Override
+              public void actionPerformed(ActionEvent e)
+              {
+                startjob_actionPerformed(e);
+              }
+            });
+    canceljob = JvSwingUtils.makeButton(
+            MessageManager.getString("action.cancel_job"),
+            MessageManager.getString("label.cancel_job_close_dialog"),
+            new ActionListener()
+            {
+              @Override
+              public void actionPerformed(ActionEvent e)
+              {
+                canceljob_actionPerformed(e);
+              }
+            });
+
+    setDetails.setBorder(
+            new TitledBorder(MessageManager.getString("label.details")));
+    setDetails.setLayout(new BorderLayout());
+    setDescr.setColumns(40);
+    setDescr.setWrapStyleWord(true);
+    setDescr.setLineWrap(true);
+    setDescr.setBackground(getBackground());
+    setDescr.setEditable(true);
+    setDescr.getDocument().addDocumentListener(this);
+    setDescr.setToolTipText(
+            MessageManager.getString("label.edit_notes_parameter_set"));
+    JScrollPane setDescrView = new JScrollPane();
+    setDescrView.getViewport().setView(setDescr);
+    setName.setEditable(true);
+    setName.addItemListener(this);
+    setName.getEditor().addActionListener(this);
+    JPanel setNameInfo = new JPanel(new FlowLayout(FlowLayout.LEFT));
+    GridBagLayout gbl = new GridBagLayout();
+    SetNamePanel.setLayout(gbl);
+
+    JLabel setNameLabel = new JLabel(
+            MessageManager.getString("label.current_parameter_set_name"));
+    setNameLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
+
+    setNameInfo.add(setNameLabel);
+    setNameInfo.add(setName);
+
+    // initial button visibility
+    updatepref.setVisible(false);
+    deletepref.setVisible(false);
+    revertpref.setVisible(false);
+    createpref.setVisible(false);
+    JPanel setsavebuts = new JPanel();
+    setsavebuts.setLayout(new FlowLayout(FlowLayout.LEFT)); // GridLayout(1,2));
+    ((FlowLayout) setsavebuts.getLayout()).setHgap(10);
+    ((FlowLayout) setsavebuts.getLayout()).setVgap(0);
+    JPanel spacer = new JPanel();
+    spacer.setPreferredSize(new Dimension(2, 30));
+    setsavebuts.add(spacer);
+    setsavebuts.add(deletepref);
+    setsavebuts.add(revertpref);
+    setsavebuts.add(createpref);
+    setsavebuts.add(updatepref);
+    // setsavebuts.setSize(new Dimension(150, 30));
+    JPanel buttonArea = new JPanel(new GridLayout(1, 1));
+    buttonArea.add(setsavebuts);
+    SetNamePanel.add(setNameInfo);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.gridheight = 2;
+    gbl.setConstraints(setNameInfo, gbc);
+    SetNamePanel.add(buttonArea);
+    gbc = new GridBagConstraints();
+    gbc.gridx = 0;
+    gbc.gridy = 2;
+    gbc.gridheight = 1;
+    gbl.setConstraints(buttonArea, gbc);
+    setDetails.add(setDescrView, BorderLayout.CENTER);
+
+    // paramPane.setPreferredSize(new Dimension(360, 400));
+    // paramPane.setPreferredSize(null);
+    jobOptions.setBorder(
+            new TitledBorder(MessageManager.getString("label.options")));
+    jobOptions.setOpaque(true);
+    paramList.setBorder(
+            new TitledBorder(MessageManager.getString("label.parameters")));
+    paramList.setOpaque(true);
+    JPanel bjo = new JPanel(new BorderLayout()),
+            bjp = new JPanel(new BorderLayout());
+    bjo.add(jobOptions, BorderLayout.CENTER);
+    bjp.add(paramList, BorderLayout.CENTER);
+    bjp.setOpaque(true);
+    bjo.setOpaque(true);
+    // optsAndparams.setScrollableWidth(ScrollableSizeHint.FIT);
+    // optsAndparams.setScrollableHeight(ScrollableSizeHint.NONE);
+    // optsAndparams.setLayout(new BorderLayout());
+    optsAndparams.setLayout(new BorderLayout());
+    optsAndparams.add(jobOptions, BorderLayout.NORTH);
+    optsAndparams.add(paramList, BorderLayout.CENTER);
+    JPanel jp = new JPanel(new BorderLayout());
+    jp.add(optsAndparams, BorderLayout.CENTER);
+    paramPane.getViewport().setView(jp);
+    paramPane.setBorder(null);
+    setLayout(new BorderLayout());
+    jobPanel.setPreferredSize(null);
+    jobPanel.setLayout(new BorderLayout());
+    jobPanel.add(setDetails, BorderLayout.NORTH);
+    jobPanel.add(paramPane, BorderLayout.CENTER);
+    // jobPanel.setOrientation(JSplitPane.VERTICAL_SPLIT);
+
+    add(SetNamePanel, BorderLayout.NORTH);
+    add(jobPanel, BorderLayout.CENTER);
+
+    JPanel dialogpanel = new JPanel();
+    dialogpanel.add(startjob);
+    dialogpanel.add(canceljob);
+    // JAL-1580: setMaximumSize() doesn't work, so just size for the worst case:
+    // check for null is for JUnit usage
+    final int windowHeight = Desktop.instance == null ? 540
+            : Desktop.instance.getHeight();
+    setPreferredSize(new Dimension(540, windowHeight));
+    add(dialogpanel, BorderLayout.SOUTH);
+    validate();
+  }
 
-    }
+  protected void revert_actionPerformed(ActionEvent e)
+  {
+    reInitDialog(lastParmSet);
+    updateWebServiceMenus();
+  }
 
-    @Override
-    public Object getCellEditorValue()
+  protected void update_actionPerformed(ActionEvent e)
+  {
+    if (isUserPreset)
     {
-      // TODO Auto-generated method stub
-      return null;
+      String curname = ((String) setName.getSelectedItem()).trim();
+      _updatePreset(lastParmSet, curname);
+      lastParmSet = curname;
+      isUserPreset = true;
+      initArgSetModified();
+      syncSetNamesWithStore();
     }
+  }
 
-    @Override
-    public boolean isCellEditable(EventObject anEvent)
-    {
-      // TODO Auto-generated method stub
-      return false;
-    }
+  private void _deleteUserPreset(String lastParmSet2)
+  {
+    paramStore.deletePreset(lastParmSet2);
+  }
 
-    @Override
-    public void removeCellEditorListener(CellEditorListener l)
+  protected void delete_actionPerformed(ActionEvent e)
+  {
+    if (isUserPreset)
     {
-      // TODO Auto-generated method stub
-
+      // delete current preset's saved entry
+      _deleteUserPreset(lastParmSet);
     }
+    reInitDialog(null); // service default
+    updateWebServiceMenus();
+  }
 
-    @Override
-    public boolean shouldSelectCell(EventObject anEvent)
+  protected void create_actionPerformed(ActionEvent e)
+  {
+    String curname = ((String) setName.getSelectedItem()).trim();
+    if (curname.length() > 0)
     {
-      // TODO Auto-generated method stub
-      return false;
+      _storeCurrentPreset(curname);
+      lastParmSet = curname;
+      isUserPreset = true;
+      reInitDialog(curname);
+      initArgSetModified();
+      updateWebServiceMenus();
     }
-
-    @Override
-    public boolean stopCellEditing()
+    else
     {
-      // TODO Auto-generated method stub
-      return false;
+      // TODO: show warning
+      System.err.println("Invalid name. Not saved.");
     }
-
-  }
-
-  protected void editParam_actionPerformed(ActionEvent e)
-  {
-    // TODO Auto-generated method stub
-
   }
 
-  protected void removeParam_actionPerformed(ActionEvent e)
+  protected void canceljob_actionPerformed(ActionEvent e)
   {
-    // TODO Auto-generated method stub
-
+    response = 0;
+    if (frame != null)
+    {
+      frame.setVisible(false);
+    }
   }
 
-  protected void addParam_actionPerformed(ActionEvent e)
+  protected void startjob_actionPerformed(ActionEvent e)
   {
-    // TODO Auto-generated method stub
-
+    response = 1;
+    if (frame != null)
+    {
+      frame.setVisible(false);
+    }
   }
 
-  protected void resetParams_actionPerformed(ActionEvent e)
-  {
-    // TODO Auto-generated method stub
+  Jws2Instance service;
 
-  }
-
-  protected void importParams_actionPerformed(ActionEvent e)
-  {
-    // TODO Auto-generated method stub
+  /**
+   * list of service presets in the gui
+   */
+  Hashtable servicePresets = null;
 
-  }
+  /**
+   * set if dialog is being set - so handlers will avoid spurious events
+   */
+  boolean settingDialog = false;
 
-  protected void exportParams_actionPerformed(ActionEvent e)
+  void initForService(Jws2Instance service, WsParamSetI jabap,
+          List<Argument> jabajobArgset)
   {
-    // TODO Auto-generated method stub
+    WsParamSetI p = null;
+    List<ArgumentI> jobArgset = null;
+    settingDialog = true;
+    { // instantiate the abstract proxy for Jaba objects
+      jobArgset = jabajobArgset == null ? null
+              : JabaParamStore.getJwsArgsfromJaba(jabajobArgset);
+      p = jabap; // (jabap != null) ? paramStore.getPreset(jabap.getName()) :
+                 // null;
+    }
 
-  }
+    Hashtable exnames = new Hashtable();
+    for (int i = 0, iSize = setName.getItemCount(); i < iSize; i++)
+    {
+      exnames.put(setName.getItemAt(i), setName.getItemAt(i));
+    }
+    servicePresets = new Hashtable();
+    // Add the default entry - if not present already.
+    if (!exnames.contains(SVC_DEF))
+    {
+      setName.addItem(SVC_DEF);
+      exnames.put(SVC_DEF, SVC_DEF);
+      servicePresets.put(SVC_DEF, SVC_DEF);
+    }
+    String curname = (p == null ? "" : p.getName());
+    for (WsParamSetI pr : paramStore.getPresets())
+    {
+      if (!pr.isModifiable())
+      {
+        servicePresets.put(pr.getName(), "preset");
+      }
+      else
+      {
+      }
+      if (!exnames.contains(pr.getName()))
+      {
+        setName.addItem(pr.getName());
+      }
+    }
+    // TODO: if initial jobArgset matches a given user setting or preset then
+    // should recover setting accordingly
+    // updateTable(p, jobArgset);
+    if (p != null)
+    {
+      reInitDialog(p.getName());
+      initArgSetModified();
+    }
+    else
+    {
+      if (jobArgset != null && jobArgset.size() > 0)
+      {
+        curSetName = "Supplied Settings";
+        isUserPreset = false;
+        updateTable(p, jobArgset);
+        setName.setSelectedItem(curSetName);
+        updateButtonDisplay();
+      }
+      else
+      {
+        curSetName = null;
+        reInitDialog(null);
+      }
+    }
+    settingDialog = false;
 
-  void initForService(Jws2Instance service, Preset p)
-  {
-    serviceOptions = service.getRunnerConfig();
-    updateTable(p);
   }
 
   @SuppressWarnings("unchecked")
-  private void updateTable(Preset p)
+  private void updateTable(WsParamSetI p, List<ArgumentI> jobArgset)
   {
-    WsParameterTableModel mdl = null;
-    TableModel tmdl = paramTable.getModel();
-    if (tmdl instanceof WsParameterTableModel)
+    boolean setDefaultParams = false;
+    if (lastParmSet == null)
     {
-      mdl = (WsParameterTableModel) tmdl;
+      isUserPreset = false;
+      // First call - so provide Service default settings
+      setName.setSelectedItem(lastSetName = SVC_DEF);
     }
-    if (mdl == null)
+    if (p == null && SVC_DEF.equals("" + setName.getSelectedItem()))
     {
-      paramTable.setModel(mdl = new WsParameterTableModel());
+      // indicate that service defaults should be set if available
+      setDefaultParams = true;
     }
-    availableParameters = new ArrayList<Parameter>();
-    List<Parameter> setargs = new ArrayList<Parameter>();
     // populate table from default parameter set.
-    List<Argument> args = serviceOptions.getArguments();
-    
+    List<ArgumentI> args = paramStore.getServiceParameters();
+
     // split to params and required arguments
     {
-      for (Argument arg : args)
+      int cw = 0;
+      boolean optset = false;
+      for (ArgumentI myarg : args)
       {
-        Argument myarg = (Argument) arg;
         // Ideally, Argument would implement isRequired !
-        if (myarg instanceof Parameter)
+        if (myarg instanceof ParameterI)
         {
-          Parameter parm = (Parameter) myarg;
-          if (parm.isRequired())
-          {
-            setargs.add(parm);
-          }
-          else
-          {
-            availableParameters.add(parm);
-          }
+          ParameterI parm = (ParameterI) myarg;
+          opanp.addParameter(parm).validate();
         }
         else
         {
-          if (myarg instanceof Option)
+          if (myarg instanceof OptionI)
           {
-            Option opt = (Option) myarg;
-            addOption(opt);
-            if (opt.isRequired())
+            OptionI opt = (OptionI) myarg;
+            OptionBox ob = opanp.addOption(opt);
+            ob.resetToDefault(setDefaultParams);
+            if (MAX_OPTWIDTH < ob.getPreferredSize().width)
             {
-              selectOption(opt, opt.getDefaultValue());
+              MAX_OPTWIDTH = ob.getPreferredSize().width;
             }
+            ob.validate();
+            cw += ob.getPreferredSize().width + 5;
           }
           else
           {
             System.err.println("Ignoring unknown service argument type "
-                    + arg.getClass().getName());
+                    + myarg.getClass().getName());
           }
         }
       }
+      args = null; // no more args to process.
     }
-
     if (p != null)
     {
-      setDescr.setText(p.getDescription());
-      setName.setText(p.getName());
+      isUserPreset = false;
+      // initialise setname
+      setName.setSelectedItem(lastSetName = p.getName());
+      setDescr.setText(lastDescrText = p.getDescription());
       // TODO - URL link
       try
       {
-        args = p.getArguments(serviceOptions);
+        args = p.getArguments();
       } catch (Exception e)
       {
         e.printStackTrace();
       }
-      setargs.clear();
-      // get setargs from current object
-      if (args != null)
+      // TODO: check if args should be unselected prior to resetting using the
+      // preset
+    }
+
+    if (jobArgset != null)
+    {
+      argSetModified(jobArgset, true);
+      args = jobArgset;
+    }
+    // get setargs from current object
+    if (args != null)
+    {
+      for (ArgumentI arg : args)
       {
-        for (Argument arg : args)
+        if (arg instanceof ParameterI)
+        {
+          opanp.setParameter((ParameterI) arg);
+        }
+        else
         {
-          if (arg instanceof Parameter)
+          if (arg instanceof OptionI)
           {
-            setargs.add((Parameter) arg);
+            // System.out.println("Setting option "
+            // + System.identityHashCode(arg) + ":" + arg.getName()
+            // + " with " + arg.getDefaultValue());
+            opanp.selectOption((OptionI) arg, arg.getValue());
           }
-          else
-          {
-            if (arg instanceof Option)
-            {
-              selectOption((Option) arg, arg.getDefaultValue());
-            }
-          }
-
         }
+
       }
     }
 
-    mdl.setData(setargs);
-    paramTable.setModel(mdl);
-    // paramTable.validate();
-    jobOptions.setLayout(new GridLayout(optSet.size() / 2 + 1, 2));
-    jobOptions.validate();
+    refreshParamLayout();
+    revalidate();
   }
 
-  private void selectOption(Option opt, String string)
+  private boolean isModified()
   {
-    OptionBox cb = optSet.get(opt.getName());
-    if (cb == null)
-    {
-      cb = addOption(opt);
-    }
-    if (string == null)
+    return modifiedElements.size() > 0;
+  }
+
+  private Hashtable modifiedElements = new Hashtable();
+
+  /**
+   * reset gui and modification state settings
+   */
+  private void initArgSetModified()
+  {
+    curSetName = null;
+    modifiedElements.clear();
+    updateButtonDisplay();
+  }
+
+  private void updateButtonDisplay()
+  {
+    boolean _update = false, _create = false, _delete = false,
+            _revert = false;
+    if (modifiedElements.size() > 0)
     {
-      // no value specified.
-      if (opt.isRequired())
+      // set modified
+      _revert = true;
+      _update = isUserPreset; // can only update user presets
+      if (!isUserPreset || modifiedElements.containsKey(setName))
       {
-        // indicate option needs to be selected!
-      }
-      else
-      {
-        cb.enabled.setSelected(false);
+        // name modified - can create new preset
+        _create = true;
       }
     }
     else
     {
-      cb.enabled.setSelected(true);
+      // set unmodified
+    }
+    // can still delete a user preset
+    _delete = isUserPreset;
 
-      if (opt.getPossibleValues().contains(string))
-      {
-        cb.val.setSelectedItem(string);
-      }
-      else
+    createpref.setVisible(_create);
+    updatepref.setVisible(_update);
+    deletepref.setVisible(_delete);
+    revertpref.setVisible(_revert);
+    validate();
+  }
+
+  @Override
+  public void argSetModified(Object modifiedElement, boolean b)
+  {
+    if (settingDialog)
+    {
+      return;
+    }
+    if (!b)
+    {
+      modifiedElements.remove(modifiedElement);
+    }
+    else
+    {
+      if (b && modifiedElement == setName
+              && modifiedElements.contains(modifiedElement))
       {
-        throw new Error("Invalid value " + string + " for option " + opt);
+        // HACK! prevents iteration on makeSetNameValid
+        b = false;
       }
-
+      modifiedElements.put(modifiedElement, modifiedElement);
     }
+    // set mod status based on presence of elements in table
+    if (b && modifiedElements.size() > 0)
+    {
+      makeSetNameValid(!isUserPreset);
+      SetNamePanel.revalidate();
+    }
+    updateButtonDisplay();
   }
 
-  Map<String, OptionBox> optSet = new Hashtable<String, OptionBox>();
-
-  public class OptionBox extends JPanel
+  private boolean isServicePreset(String selectedItem)
   {
-    JComboBox val = new JComboBox();
-
-    JCheckBox enabled = new JCheckBox();
+    return selectedItem.equals(SVC_DEF)
+            || servicePresets.containsKey(selectedItem);
+  }
 
-    public OptionBox(Option opt)
+  /**
+   * check if the current set name is a valid set name for saving, if not, then
+   * fix it.
+   */
+  private void makeSetNameValid(boolean newuserset)
+  {
+    boolean stn = settingDialog;
+    boolean renamed = false;
+    settingDialog = true;
+    String nm = (curSetName != null ? curSetName
+            : (String) setName.getSelectedItem());
+    // check if the name is reserved - if it is, rename it.
+    if (isServicePreset(nm))
+    {
+      nm = "User " + nm;
+      renamed = true;
+    }
+    String tnm = nm;
+    if (newuserset)
     {
-      setLayout(new BorderLayout());
-      enabled.setSelected(opt.isRequired());
-      enabled.setFont(new Font("Verdana", Font.PLAIN, 11));
-      enabled.setText(opt.getName());
-      enabled.setToolTipText(opt.getDescription());
-      add(enabled, BorderLayout.NORTH);
-      if (opt.getPossibleValues().size() > 1)
+      int i = 0;
+      while (paramStore.getPreset(tnm) != null)
       {
-        setLayout(new GridLayout(1,2));
-        for (Object str : opt.getPossibleValues())
-        {
-          val.addItem((String) str);
-        }
-        val.setSelectedItem((String) opt.getDefaultValue());
-        add(val, BorderLayout.SOUTH);
+        tnm = nm + " (" + (++i) + ")";
+        renamed = true;
+      }
+      if (i > 0)
+      {
+        nm = tnm;
       }
-      // TODO: add actionListeners for popup (to open further info), 
-      // and to update list of parameters if an option is enabled
-      // that takes a value.
     }
-  }
 
-  private OptionBox addOption(Option opt)
-  {
-    OptionBox cb = optSet.get(opt.getName());
-    if (cb == null)
+    boolean makeupdate = false;
+    // sync the gui with the preset database
+    for (int i = 0, iS = setName.getItemCount(); i < iS; i++)
+    {
+      String snm = (String) setName.getItemAt(i);
+      if (snm.equals(nm))
+      {
+        makeupdate = true;
+        // setName.setSelectedIndex(i);
+      }
+    }
+    if (!makeupdate)
+    {
+      setName.addItem(curSetName = nm);
+      setName.setSelectedItem(curSetName);
+    }
+    if (renamed)
     {
-      cb = new OptionBox(opt);
-      optSet.put(opt.getName(), cb);
-      jobOptions.add(cb);
+      settingDialog = false; // we need this name change to be registered.
+      argSetModified(setName, renamed);
     }
-    return cb;
+    settingDialog = stn;
   }
 
-  class WsParameterTableModel extends AbstractTableModel
+  @Override
+  public void refreshParamLayout()
   {
-    // arg list - vector for thread safety
-    public Vector<Parameter> data = new Vector<Parameter>();
+    // optsAndparams.setPreferredSize(null);
+    FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
+    int sep = fl.getVgap();
+    boolean fh = true;
+    int os = 0,
+            s = jobOptions.getBorder().getBorderInsets(jobOptions).bottom
+                    + jobOptions.getBorder().getBorderInsets(jobOptions).top
+                    + 2 * sep;
+    /**
+     * final height for viewport
+     */
+    int finalh = s;
+    int panewidth = paramPane.getViewport().getSize().width - 120
+            - jobOptions.getBorder().getBorderInsets(jobOptions).left
+            + jobOptions.getBorder().getBorderInsets(jobOptions).right;
 
-    private String[] colNames =
-    { "Parameter", "Value" };
+    int w = 2 * fl.getHgap()
+            + (MAX_OPTWIDTH > OptsAndParamsPage.PARAM_WIDTH ? MAX_OPTWIDTH
+                    : OptsAndParamsPage.PARAM_WIDTH);
+    int hgap = fl.getHgap(), cw = hgap;
 
-    @Override
-    public int getColumnCount()
+    if (opanp.getOptSet().size() > 0)
     {
-      return 2;
-    }
 
-    @Override
-    public int findColumn(String columnName)
+      jobOptions.setLayout(new MigLayout("", "", ""));
+      jobOptions.removeAll();
+
+      for (OptionBox pbox : opanp.getOptSet().values())
+      {
+        pbox.validate();
+        cw += pbox.getSize().width + hgap;
+        if (cw + 120 > panewidth)
+        {
+          jobOptions.add(pbox, "wrap");
+          // System.out.println("Wrap on "+pbox.option.getName());
+          cw = hgap + pbox.getSize().width;
+          fh = true;
+        }
+        else
+        {
+          jobOptions.add(pbox);
+        }
+        if (fh)
+        {
+          finalh += pbox.getSize().height + fl.getVgap();
+          fh = false;
+        }
+      }
+      jobOptions.revalidate();
+    }
+    else
     {
-      // TODO Auto-generated method stub
-      return super.findColumn(columnName);
+      jobOptions.setVisible(false);
     }
 
-    public void setData(List<Parameter> setargs)
+    // Now layout the parameters assuming they occupy one column - to calculate
+    // total height of options+parameters
+    fl = new FlowLayout(FlowLayout.LEFT);
+    // helpful hint from
+    // http://stackoverflow.com/questions/2743177/top-alignment-for-flowlayout
+    fl.setAlignOnBaseline(true);
+    if (opanp.getParamSet().size() > 0)
     {
-      if (setargs != null)
+      paramList.removeAll();
+      paramList.setLayout(new MigLayout("", "", ""));
+      fh = true;
+      for (ParamBox pbox : opanp.getParamSet().values())
       {
-        data = new Vector<Parameter>(setargs);
+        pbox.validate();
+        cw += pbox.getSize().width + hgap;
+        if (cw + 160 > panewidth)
+        {
+          paramList.add(pbox, "wrap");
+          cw = pbox.getSize().width + hgap;
+          fh = true;
+        }
+        else
+        {
+          paramList.add(pbox);
+        }
+        if (fh)
+        {
+          finalh += pbox.getSize().height + fl.getVgap();
+          fh = false;
+        }
 
       }
-      else
-      {
-        data = new Vector<Parameter>();
-      }
+      /*
+       * s = 2 * sep; for (ParamBox pbox : opanp.getParamSet().values()) {
+       * pbox.validate(); s += sep +
+       * pbox.getPreferredSize().height+pbox.getBorder
+       * ().getBorderInsets(pbox).bottom; }
+       * 
+       * // paramList.setPreferredSize(new Dimension(w, s));
+       * os+=s+2*sep+paramList
+       * .getBorder().getBorderInsets(paramList).bottom+paramList
+       * .getBorder().getBorderInsets(paramList).top;
+       */
+      paramList.revalidate();
     }
-
-    public List<Parameter> getData()
+    else
     {
-      return new ArrayList<Parameter>(data);
+      paramList.setVisible(false);
     }
+    // TODO: waste some time trying to eliminate any unnecessary .validate calls
+    // here
+    // System.out.println("Size will be : "+w+","+os);
+    // optsAndparams.setPreferredSize(null);
+    // paramPane.getViewport().setView(optsAndparams);
+    paramPane.getViewport().setAutoscrolls(true);
+    paramPane.revalidate();
+    revalidate();
+  }
 
-    @Override
-    public int getRowCount()
+  /**
+   * testing method - grab a service and parameter set and show the window
+   * 
+   * @param args
+   * @j2sIgnore
+   */
+  public static void main(String[] args)
+  {
+    jalview.ws.jws2.Jws2Discoverer disc = jalview.ws.jws2.Jws2Discoverer
+            .getDiscoverer();
+    int p = 0;
+    if (args.length > 0)
     {
-      return data.size();
+      Vector<String> services = new Vector<>();
+      services.addElement(args[p++]);
+      Jws2Discoverer.getDiscoverer().setServiceUrls(services);
     }
-
-    @Override
-    public Object getValueAt(int rowIndex, int columnIndex)
+    try
+    {
+      disc.run();
+    } catch (Exception e)
     {
-      if (rowIndex >= 0 && rowIndex < data.size())
+      System.err.println("Aborting. Problem discovering services.");
+      e.printStackTrace();
+      return;
+    }
+    Jws2Instance lastserv = null;
+    for (Jws2Instance service : disc.getServices())
+    {
+      lastserv = service;
+      if (p >= args.length || service.serviceType.equalsIgnoreCase(args[p]))
       {
-        Parameter prm = data.elementAt(rowIndex);
-        switch (columnIndex)
+        if (lastserv != null)
         {
-        case 0:
-          return prm.getName();
-        case 1:
-          Object exc = null;
-          // the accessor name for the parameter value is possibly confusing
-          String val = prm.getDefaultValue();
-          try
+          List<Preset> prl = null;
+          Preset pr = null;
+          if (++p < args.length)
           {
-            if (prm.getValidValue().getType().equals(Type.Float))
+            PresetManager prman = lastserv.getPresets();
+            if (prman != null)
             {
-              exc = new Float(0);
-              return Float.parseFloat(val);
+              pr = prman.getPresetByName(args[p]);
+              if (pr == null)
+              {
+                // just grab the last preset.
+                prl = prman.getPresets();
+              }
             }
-            if (prm.getValidValue().getType().equals(Type.Integer))
+          }
+          else
+          {
+            PresetManager prman = lastserv.getPresets();
+            if (prman != null)
             {
-              exc = new Integer(0);
-              return Integer.parseInt(val);
+              prl = prman.getPresets();
             }
-          } catch (NumberFormatException e)
-          {
-            return exc;
           }
-          // must be a string
-          return val;
+          Iterator<Preset> en = (prl == null) ? null : prl.iterator();
+          while (en != null && en.hasNext())
+          {
+            if (en != null)
+            {
+              if (!en.hasNext())
+              {
+                en = prl.iterator();
+              }
+              pr = en.next();
+            }
+            {
+              System.out.println("Testing opts dupes for "
+                      + lastserv.getUri() + " : " + lastserv.getActionText()
+                      + ":" + pr.getName());
+              List<Option> rg = lastserv.getRunnerConfig().getOptions();
+              for (Option o : rg)
+              {
+                try
+                {
+                  Option cpy = jalview.ws.jws2.ParameterUtils.copyOption(o);
+                } catch (Exception e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                } catch (Error e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                }
+              }
+            }
+            {
+              System.out.println("Testing param dupes:");
+              List<Parameter> rg = lastserv.getRunnerConfig()
+                      .getParameters();
+              for (Parameter o : rg)
+              {
+                try
+                {
+                  Parameter cpy = jalview.ws.jws2.ParameterUtils
+                          .copyParameter(o);
+                } catch (Exception e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                } catch (Error e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                }
+              }
+            }
+            {
+              System.out.println("Testing param write:");
+              List<String> writeparam = null, readparam = null;
+              try
+              {
+                writeparam = jalview.ws.jws2.ParameterUtils
+                        .writeParameterSet(
+                                pr.getArguments(lastserv.getRunnerConfig()),
+                                " ");
+                System.out.println("Testing param read :");
+                List<Option> pset = jalview.ws.jws2.ParameterUtils
+                        .processParameters(writeparam,
+                                lastserv.getRunnerConfig(), " ");
+                readparam = jalview.ws.jws2.ParameterUtils
+                        .writeParameterSet(pset, " ");
+                Iterator<String> o = pr.getOptions().iterator(),
+                        s = writeparam.iterator(), t = readparam.iterator();
+                boolean failed = false;
+                while (s.hasNext() && t.hasNext())
+                {
+                  String on = o.next(), sn = s.next(), st = t.next();
+                  if (!sn.equals(st))
+                  {
+                    System.out.println(
+                            "Original was " + on + " Phase 1 wrote " + sn
+                                    + "\tPhase 2 wrote " + st);
+                    failed = true;
+                  }
+                }
+                if (failed)
+                {
+                  System.out.println(
+                          "Original parameters:\n" + pr.getOptions());
+                  System.out.println(
+                          "Wrote parameters in first set:\n" + writeparam);
+                  System.out.println(
+                          "Wrote parameters in second set:\n" + readparam);
+
+                }
+              } catch (Exception e)
+              {
+                e.printStackTrace();
+              }
+            }
+            WsJobParameters pgui = new WsJobParameters(lastserv,
+                    new JabaPreset(lastserv, pr));
+            JFrame jf = new JFrame(MessageManager
+                    .formatMessage("label.ws_parameters_for", new String[]
+                    { lastserv.getActionText() }));
+            JPanel cont = new JPanel(new BorderLayout());
+            pgui.validate();
+            cont.setPreferredSize(pgui.getPreferredSize());
+            cont.add(pgui, BorderLayout.CENTER);
+            jf.setLayout(new BorderLayout());
+            jf.add(cont, BorderLayout.CENTER);
+            jf.validate();
+            final Thread thr = Thread.currentThread();
+            jf.addWindowListener(new WindowListener()
+            {
+
+              @Override
+              public void windowActivated(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowClosed(WindowEvent e)
+              {
+              }
+
+              @Override
+              public void windowClosing(WindowEvent e)
+              {
+                thr.interrupt();
+
+              }
+
+              @Override
+              public void windowDeactivated(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
 
-        default:
+              }
+
+              @Override
+              public void windowDeiconified(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowIconified(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowOpened(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+            });
+            jf.setVisible(true);
+            boolean inter = false;
+            while (!inter)
+            {
+              try
+              {
+                Thread.sleep(10000);
+              } catch (Exception e)
+              {
+                inter = true;
+              }
+            }
+            jf.dispose();
+          }
         }
       }
-      return null;
     }
+  }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
-     */
-    @Override
-    public Class<?> getColumnClass(int columnIndex)
+  public boolean isServiceDefaults()
+  {
+    return (!isModified()
+            && (lastParmSet != null && lastParmSet.equals(SVC_DEF)));
+  }
+
+  public List<ArgumentI> getJobParams()
+  {
+    return opanp.getCurrentSettings();
+  }
+
+  String lastParmSet = null;
+
+  /*
+   * Hashtable<String, Object[]> editedParams = new Hashtable<String,
+   * Object[]>();
+   * 
+   * store the given parameters in the user parameter set database.
+   * 
+   * @param storeSetName - lastParmSet
+   * 
+   * @param descr - setDescr.getText()
+   * 
+   * @param jobParams - getJobParams()
+   * 
+   * private void _storeUserPreset(String storeSetName, String descr,
+   * List<ArgumentI> jobParams) { // this is a simple hash store. Object[] pset;
+   * editedParams.put(storeSetName, pset = new Object[3]); pset[0] =
+   * storeSetName; pset[1] = descr; pset[2] = jobParams; // writeParam("Saving "
+   * + storeSetName + ": ", jobParams); }
+   * 
+   * private void writeParam(String nm, List<ArgumentI> params) { for (ArgumentI
+   * p : params) { System.out.println(nm + ":" + System.identityHashCode(p) +
+   * " Name: " + p.getName() + " Value: " + p.getDefaultValue()); } }
+   * 
+   * private Object[] _getUserPreset(String setName) { Object[] pset =
+   * editedParams.get(setName); // if (pset != null) // writeParam("Retrieving "
+   * + setName + ": ", (List<Argument>) pset[2]); return pset; }
+   * 
+   * * remove the given user preset from the preset stash
+   * 
+   * @param setName
+   * 
+   * private void _deleteUserPreset(String setName) {
+   * editedParams.remove(setName); }
+   */
+
+  private void syncSetNamesWithStore()
+  {
+    int n = 0;
+    // remove any set names in the drop down menu that aren't either a reserved
+    // setting, or a user defined or service preset.
+    Vector items = new Vector();
+    while (n < setName.getItemCount())
     {
-      switch (columnIndex)
+      String item = (String) setName.getItemAt(n);
+      if (!item.equals(SVC_DEF) && !paramStore.presetExists(item))
+      {
+        setName.removeItemAt(n);
+      }
+      else
       {
-      case 0:
-        return String.class;
-      case 1:
-        return Parameter.class;
+        items.addElement(item);
+        n++;
       }
-      return super.getColumnClass(columnIndex);
     }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see javax.swing.table.AbstractTableModel#getColumnName(int)
-     */
-    @Override
-    public String getColumnName(int column)
+    if (!items.contains(SVC_DEF))
     {
-      return colNames[column];
+      setName.addItem(SVC_DEF);
     }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see javax.swing.table.AbstractTableModel#isCellEditable(int, int)
-     */
-    @Override
-    public boolean isCellEditable(int rowIndex, int columnIndex)
+    for (WsParamSetI upn : paramStore.getPresets())
     {
-      if (columnIndex == 1)
+      if (!items.contains(upn.getName()))
       {
-        return true;
+        setName.addItem(upn.getName());
       }
-      return false;
     }
   }
 
-  class ArgumentRenderer implements TableCellRenderer
-  {
+  /**
+   * true if lastParmSet is a user preset
+   */
+  boolean isUserPreset = false;
 
-    @Override
-    public Component getTableCellRendererComponent(JTable table,
-            Object value, boolean isSelected, boolean hasFocus, int row,
-            int column)
+  private void reInitDialog(String nextPreset)
+  {
+    settingDialog = true;
+    // updateTable(null,null); // first reset to defaults
+    WsParamSetI pset = null;
+    if (nextPreset != null && nextPreset.length() > 0)
     {
-      if (value instanceof Option)
-      {
-        JCheckBox cb = new JCheckBox();
-        cb.setSelected(true);
-        return cb;
-      }
-      if (value instanceof Boolean)
+      pset = paramStore.getPreset(nextPreset);
+    }
+    if (pset != null)
+    {
+      if (pset.isModifiable())
       {
-        JCheckBox cb = new JCheckBox();
-        cb.setSelected(((Boolean) value).booleanValue());
-        return cb;
+        isUserPreset = true;
+        setDescr.setText(pset.getDescription());
+        updateTable(null, pset.getArguments());
+        lastParmSet = nextPreset;
       }
-      if (value instanceof String)
+      else
       {
-        JLabel lbl = new JLabel();
-        lbl.setFont(new Font("Verdana", Font.PLAIN, 11));
-        lbl.setText((String) value);
-        return lbl;
+        isUserPreset = false;
+        setDescr.setText("");
+        // must be a default preset from service
+        updateTable(pset, null);
+        lastParmSet = nextPreset;
       }
-      if (value instanceof Parameter)
-      {
-        String val = ((Parameter) value).getDefaultValue();
-        ValueConstrain constr = ((Parameter) value).getValidValue();
-        JLabel lbl = new JLabel();
-        lbl.setFont(new Font("Verdana", Font.PLAIN, 11));
-        lbl.setText(val);
-        return lbl;
-        /*
-         * type dependent return value if
-         * (constr.getType().equals(Type.Integer))
-         * 
-         * { lbl.setText(val); } if (constr.getType().equals(Type.Float)) { }
-         * return lbl;
-         */
-      }
-      return null;
     }
+    else
+    {
+      isUserPreset = false;
+      // Service defaults
+      setDescr.setText("");
+      updateTable(null, null);
+      lastParmSet = SVC_DEF;
+    }
+
+    initArgSetModified();
+    syncSetNamesWithStore();
+    setName.setSelectedItem(lastParmSet);
+    SetNamePanel.validate();
+    validate();
+    settingDialog = false;
   }
 
   /**
-   * testing method - grab a service and parameter set and show the window
-   * 
-   * @param args
+   * Rebuild the AlignFrame web service menus (after add/delete of a preset
+   * option).
    */
-  public static void main(String[] args)
+  protected void updateWebServiceMenus()
   {
-    jalview.ws.jws2.Jws2Discoverer disc = jalview.ws.jws2.Jws2Discoverer
-            .getDiscoverer();
-    int p = 0;
-    if (args.length > 3)
+    for (AlignFrame alignFrame : Desktop.getAlignFrames())
     {
-      Vector<String> services = new Vector<String>();
-      services.addElement(args[p++]);
-      Jws2Discoverer.setServiceUrls(services);
+      alignFrame.BuildWebServiceMenu();
     }
-    try
-    {
-      disc.run();
-    } catch (Exception e)
-    {
-      System.err.println("Aborting. Problem discovering services.");
-      e.printStackTrace();
-      return;
-    }
-    Jws2Discoverer.Jws2Instance lastserv = null;
-    for (Jws2Discoverer.Jws2Instance service : disc.getServices())
+  }
+
+  String curSetName = null;
+
+  @Override
+  public void itemStateChanged(ItemEvent e)
+  {
+    if (e.getSource() == setName && e.getStateChange() == e.SELECTED)
     {
-      lastserv = service;
-      if (p < args.length && service.serviceType.equalsIgnoreCase(args[p]))
+      final String setname = (String) setName.getSelectedItem();
+      if (Cache.isDebugEnabled())
       {
-        break;
+        Cache.debug("Item state changed for " + setname
+                + " (handling ? " + !settingDialog + ")");
       }
-    }
-    if (lastserv != null)
-    {
-      Preset pr = null;
-      if (++p < args.length)
+      if (settingDialog)
+      {
+        // ignore event
+        return;
+      }
+      if (setname == null)
+      {
+        return;
+      }
+      javax.swing.SwingUtilities.invokeLater(new Runnable()
       {
-        PresetManager prman = lastserv.getPresets();
-        if (prman != null)
+        @Override
+        public void run()
         {
-          pr = prman.getPresetByName(args[p]);
-          if (pr == null)
-          {
-            // just grab the last preset.
-            List<Preset> prl = prman.getPresets();
-            pr = prl.get(prl.size() - 1);
-          }
+          doPreferenceComboStateChange(setname);
         }
+      });
+    }
+  }
+
+  private void doPreferenceComboStateChange(String setname)
+  {
+    // user has selected a different item from combo-box
+    if (isModified())
+    {
+      String lsetname = (curSetName != null) ? curSetName : lastParmSet;
+      if (lsetname.equals(setname))
+      {
+        // setname was just edited - so ignore this event.
+        return;
       }
-      while (true)
-      {
-        WsJobParameters pgui = new WsJobParameters(lastserv, pr);
-        JFrame jf = new JFrame("Parameters for " + lastserv.getActionText());
-        JPanel cont = new JPanel();
-        cont.setSize(new Dimension(600, 800));
-        cont.add(pgui);
-        jf.add(cont);
-        final Thread thr = Thread.currentThread();
-        jf.addWindowListener(new WindowListener()
-        {
+      settingDialog = true;
+      System.out.println("Prompting to save " + lsetname);
+      if (JvOptionPane.showConfirmDialog(this, "Parameter set '" + lsetname
+              + "' is modifed, and your changes will be lost.\nReally change preset ?",
+              "Warning: Unsaved Changes",
+              JvOptionPane.OK_CANCEL_OPTION) != JvOptionPane.OK_OPTION)
+      {
+        // revert the combobox to the current item
+        settingDialog = true;
+        setName.setSelectedItem(lsetname);
+        settingDialog = false;
+        // and leave.
+        return;
+        // System.out.println("Saving for " + lsetname);
+        // _storeCurrentPreset(lsetname);
 
-          @Override
-          public void windowActivated(WindowEvent e)
-          {
-            // TODO Auto-generated method stub
+      }
+    }
+    settingDialog = true;
+    reInitDialog(setname);
+    settingDialog = false;
 
-          }
+  }
 
-          @Override
-          public void windowClosed(WindowEvent e)
-          {
-          }
+  private void _renameExistingPreset(String oldName, String curSetName2)
+  {
+    paramStore.updatePreset(oldName, curSetName2, setDescr.getText(),
+            getJobParams());
+  }
 
-          @Override
-          public void windowClosing(WindowEvent e)
-          {
-            thr.interrupt();
+  /**
+   * store current settings as given name. You should then reset gui.
+   * 
+   * @param curSetName2
+   */
+  private void _storeCurrentPreset(String curSetName2)
+  {
+    paramStore.storePreset(curSetName2, setDescr.getText(), getJobParams());
+  }
 
-          }
+  private void _updatePreset(String lastParmSet2, String curname)
+  {
+    paramStore.updatePreset(lastParmSet2, curname, setDescr.getText(),
+            getJobParams());
 
-          @Override
-          public void windowDeactivated(WindowEvent e)
-          {
-            // TODO Auto-generated method stub
+  }
 
-          }
+  /**
+   * last saved name for this user preset
+   */
+  String lastSetName = null;
 
-          @Override
-          public void windowDeiconified(WindowEvent e)
+  /**
+   * last saved value of the description text for this user preset
+   */
+  String lastDescrText = null;
+
+  @Override
+  public void actionPerformed(ActionEvent e)
+  {
+    if (e.getSource() instanceof Component)
+    {
+      Component src = (Component) e.getSource();
+      if (src.getParent() == setName)
+      {
+        // rename any existing records we know about for this set.
+        String newname = e.getActionCommand().trim();
+        String msg = null;
+        if (isServicePreset(newname))
+        {
+          final String oldname = curSetName != null ? curSetName
+                  : lastParmSet;
+          final Component ourframe = this;
+          settingDialog = true;
+          setName.getEditor().setItem(oldname);
+          settingDialog = false;
+          javax.swing.SwingUtilities.invokeLater(new Runnable()
           {
-            // TODO Auto-generated method stub
+            @Override
+            public void run()
+            {
+              JvOptionPane.showMessageDialog(ourframe,
+                      MessageManager.getString(
+                              "label.invalid_name_preset_exists"),
+                      MessageManager.getString("label.invalid_name"),
+                      JvOptionPane.WARNING_MESSAGE);
+            }
+          });
 
-          }
+          return;
+        }
+        curSetName = newname;
+        System.err.println("New name for user setting " + curSetName
+                + " (was " + setName.getSelectedItem() + ")");
+        if (curSetName.equals(setName.getSelectedItem()))
+        {
+          curSetName = null;
+        }
+        if (curSetName != null)
+        {
+          argSetModified(setName, true);
+          return;
+        }
 
-          @Override
-          public void windowIconified(WindowEvent e)
-          {
-            // TODO Auto-generated method stub
+      }
+    }
+  }
 
-          }
+  private void checkDescrModified()
+  {
+    if (!settingDialog)
+    {
 
-          @Override
-          public void windowOpened(WindowEvent e)
-          {
-            // TODO Auto-generated method stub
+      argSetModified(setDescr,
+              (lastDescrText == null
+                      ? setDescr.getText().trim().length() > 0
+                      : !setDescr.getText().equals(lastDescrText)));
 
-          }
+    }
+  }
 
-        });
-        jf.setVisible(true);
-        boolean inter = false;
-        while (!inter)
-        {
-          try
-          {
-            Thread.sleep(10000);
-          } catch (Exception e)
-          {
-            inter = true;
-          }
-          ;
-        }
-        jf.dispose();
-      }
+  @Override
+  public void insertUpdate(DocumentEvent e)
+  {
+    checkDescrModified();
+  }
+
+  @Override
+  public void removeUpdate(DocumentEvent e)
+  {
+    checkDescrModified();
+  }
+
+  @Override
+  public void changedUpdate(DocumentEvent e)
+  {
+    checkDescrModified();
+  }
+
+  /**
+   * 
+   * @return null or the service preset selected by the user
+   */
+  public WsParamSetI getPreset()
+  {
+    if (isUserPreset || isModified()
+            || (lastParmSet != null && lastParmSet.equals(SVC_DEF)))
+    {
+      return null;
+    }
+    else
+    {
+      return paramStore.getPreset(lastParmSet);
     }
   }
 }