JAL-1503 update version in GPL header
[jalview.git] / src / jalview / gui / OptsAndParamsPage.java
index f0fd3a7..5df0174 100644 (file)
@@ -1,22 +1,44 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.1)
+ * Copyright (C) 2014 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 jalview.util.MessageManager;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.OptionI;
 import jalview.ws.params.ParameterI;
 import jalview.ws.params.ValueConstrainI;
+import jalview.ws.params.ValueConstrainI.ValueType;
 
 import java.awt.BorderLayout;
 import java.awt.Component;
-import java.awt.Container;
 import java.awt.Dimension;
-import java.awt.FlowLayout;
 import java.awt.Font;
 import java.awt.GridLayout;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.net.URL;
+import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
@@ -37,15 +59,22 @@ import javax.swing.border.TitledBorder;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
 
-import compbio.metadata.ValueConstrain.Type;
+import net.miginfocom.swing.MigLayout;
 
 /**
- * GUI generator/manager for options and parameters. Originally abstracted from the WsJobParameters dialog box.
- * @author jprocter 
- *
+ * GUI generator/manager for options and parameters. Originally abstracted from
+ * the WsJobParameters dialog box.
+ * 
+ * @author jprocter
+ * 
  */
 public class OptsAndParamsPage
 {
+  /**
+   * compact or verbose style parameters
+   */
+  boolean compact = false;
+
   public class OptionBox extends JPanel implements MouseListener,
           ActionListener
   {
@@ -75,30 +104,37 @@ public class OptsAndParamsPage
       enabled.setText(opt.getName());
       enabled.addActionListener(this);
       finfo = option.getFurtherDetails();
+      String desc = opt.getDescription();
       if (finfo != null)
       {
         hasLink = true;
+
         enabled.setToolTipText("<html>"
-                + JvSwingUtils.wrapTooltip(opt.getDescription()
-                        + "<br><img src=\"" + linkImageURL + "\"/>")
+                + JvSwingUtils
+                        .wrapTooltip(((desc == null || desc.trim().length()==0) ? "see further details by right-clicking"
+                                : desc)
+                                + "<br><img src=\"" + linkImageURL + "\"/>")
                 + "</html>");
         enabled.addMouseListener(this);
       }
       else
       {
-        enabled.setToolTipText("<html>"
-                + JvSwingUtils.wrapTooltip(opt.getDescription())
-                + "</html>");
+        if (desc != null && desc.trim().length()>0)
+        {
+          enabled.setToolTipText("<html>"
+                  + JvSwingUtils.wrapTooltip(opt.getDescription())
+                  + "</html>");
+        }
       }
       add(enabled, BorderLayout.NORTH);
+      for (Object str : opt.getPossibleValues())
+      {
+        val.addItem((String) str);
+      }
+      val.setSelectedItem((String) opt.getValue());
       if (opt.getPossibleValues().size() > 1)
       {
         setLayout(new GridLayout(1, 2));
-        for (Object str : opt.getPossibleValues())
-        {
-          val.addItem((String) str);
-        }
-        val.setSelectedItem((String) opt.getDefaultValue());
         val.addActionListener(this);
         add(val, BorderLayout.SOUTH);
       }
@@ -129,13 +165,14 @@ public class OptsAndParamsPage
         else
         {
           // compare against default service setting
-          notmod &= option.getDefaultValue() == null
-                  || option.getDefaultValue().equals(val.getSelectedItem());
+          notmod &= option.getValue() == null
+                  || option.getValue().equals(val.getSelectedItem());
         }
       }
       else
       {
-        notmod &= initVal == null;
+        notmod &= (initVal != null) ? initVal.equals(val.getSelectedItem())
+                : val.getSelectedItem() != initVal;
       }
       poparent.argSetModified(this, !notmod);
     }
@@ -147,10 +184,23 @@ public class OptsAndParamsPage
         return null;
       }
       OptionI opt = option.copy();
-
+      if (opt.getPossibleValues() != null
+              && opt.getPossibleValues().size() == 1)
+      {
+        // Hack to make sure the default value for an enabled option with only
+        // one value is actually returned
+        opt.setValue(opt.getPossibleValues().get(0));
+      }
       if (val.getSelectedItem() != null)
       {
-        opt.setDefaultValue((String) val.getSelectedItem());
+        opt.setValue((String) val.getSelectedItem());
+      }
+      else
+      {
+        if (option.getValue() != null)
+        {
+          opt.setValue(option.getValue());
+        }
       }
       return opt;
     }
@@ -187,13 +237,14 @@ public class OptsAndParamsPage
 
     }
 
-    public void resetToDefault()
+
+    public void resetToDefault(boolean setDefaultParams)
     {
       enabled.setSelected(false);
-      if (option.isRequired())
+      if (option.isRequired() || (setDefaultParams && option.getValue()!=null))
       {
         // Apply default value
-        selectOption(option, option.getDefaultValue());
+        selectOption(option, option.getValue());
       }
     }
 
@@ -207,10 +258,10 @@ public class OptsAndParamsPage
       }
       else
       {
-        initVal = (initEnabled) ? option.getDefaultValue() : null;
+        initVal = (initEnabled) ? (String) val.getSelectedItem() : null;
       }
     }
-
+    
   }
 
   public class ParamBox extends JPanel implements ChangeListener,
@@ -253,6 +304,61 @@ public class OptsAndParamsPage
     public ParamBox(final OptsParametersContainerI pmlayout, ParameterI parm)
     {
       pmdialogbox = pmlayout;
+      finfo = parm.getFurtherDetails();
+      validator = parm.getValidValue();
+      parameter = parm;
+      if (validator != null)
+      {
+        integ = validator.getType() == ValueType.Integer;
+      }
+      else
+      {
+        if (parameter.getPossibleValues() != null)
+        {
+          choice = true;
+        }
+      }
+
+      if (!compact)
+      {
+        makeExpanderParam(parm);
+      }
+      else
+      {
+        makeCompactParam(parm);
+
+      }
+    }
+
+    private void makeCompactParam(ParameterI parm)
+    {
+      setLayout(new MigLayout("", "[][grow]"));
+
+      String ttipText = null;
+
+      controlPanel.setLayout(new BorderLayout());
+
+      if (parm.getDescription() != null
+              && parm.getDescription().trim().length() > 0)
+      {
+        // Only create description boxes if there actually is a description.
+        ttipText = ("<html>"
+                + JvSwingUtils
+                        .wrapTooltip(parm.getDescription()
+                                + (finfo != null ? "<br><img src=\""
+                                        + linkImageURL
+                                        + "\"/> Right click for further information."
+                                        : "")) + "</html>");
+      }
+
+      JvSwingUtils.mgAddtoLayout(this, ttipText,
+              new JLabel(parm.getName()), controlPanel, "");
+      updateControls(parm);
+      validate();
+    }
+
+    private void makeExpanderParam(ParameterI parm)
+    {
       setPreferredSize(new Dimension(PARAM_WIDTH, PARAM_CLOSEDHEIGHT));
       setBorder(new TitledBorder(parm.getName()));
       setLayout(null);
@@ -263,62 +369,68 @@ public class OptsAndParamsPage
 
       string.setEditable(false);
       descPanel.getViewport().setView(string);
-      
+
       descPanel.setVisible(false);
-      
-      final ParamBox me = this;
-      finfo = parm.getFurtherDetails();
-      if (finfo != null)
-      {
-        showDesc.setToolTipText("<html>"
-                + JvSwingUtils
-                        .wrapTooltip("Click to show brief description<br><img src=\""
-                                + linkImageURL
-                                + "\"/> Right click for further information.")
-                + "</html>");
-        showDesc.addMouseListener(this);
-      }
-      else
-      {
-        showDesc.setToolTipText("<html>"
-                + JvSwingUtils
-                        .wrapTooltip("Click to show brief description.")
-                + "</html>");
-      }
-      showDesc.addActionListener(new ActionListener()
-      {
 
-        public void actionPerformed(ActionEvent e)
-        {
-          descisvisible = !descisvisible;
-          descPanel.setVisible(descisvisible);
-          descPanel.getVerticalScrollBar().setValue(0);
-          me.setPreferredSize(new Dimension(PARAM_WIDTH,
-                  (descisvisible) ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT));
-          me.validate();
-          pmlayout.refreshParamLayout();
-        }
-      });
-      string.setWrapStyleWord(true);
-      string.setLineWrap(true);
-      string.setColumns(32);
-      string.setText(parm.getDescription());
       JPanel firstrow = new JPanel();
       firstrow.setLayout(null);
       controlPanel.setLayout(new BorderLayout());
       controlPanel.setBounds(new Rectangle(39, 10, PARAM_WIDTH - 70,
               PARAM_CLOSEDHEIGHT - 50));
-      showDesc.setBounds(new Rectangle(10, 10, 16, 16));
-      firstrow.add(showDesc);
       firstrow.add(controlPanel);
       firstrow.setBounds(new Rectangle(10, 20, PARAM_WIDTH - 30,
               PARAM_CLOSEDHEIGHT - 30));
+
+      final ParamBox me = this;
+
+      if (parm.getDescription() != null
+              && parm.getDescription().trim().length() > 0)
+      {
+        // Only create description boxes if there actually is a description.
+        if (finfo != null)
+        {
+          showDesc.setToolTipText("<html>"
+                  + JvSwingUtils
+                          .wrapTooltip("Click to show brief description<br><img src=\""
+                                  + linkImageURL
+                                  + "\"/> Right click for further information.")
+                  + "</html>");
+          showDesc.addMouseListener(this);
+        }
+        else
+        {
+          showDesc.setToolTipText("<html>"
+                  + JvSwingUtils
+                          .wrapTooltip("Click to show brief description.")
+                  + "</html>");
+        }
+        showDesc.addActionListener(new ActionListener()
+        {
+
+          public void actionPerformed(ActionEvent e)
+          {
+            descisvisible = !descisvisible;
+            descPanel.setVisible(descisvisible);
+            descPanel.getVerticalScrollBar().setValue(0);
+            me.setPreferredSize(new Dimension(PARAM_WIDTH,
+                    (descisvisible) ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT));
+            me.validate();
+            pmdialogbox.refreshParamLayout();
+          }
+        });
+        string.setWrapStyleWord(true);
+        string.setLineWrap(true);
+        string.setColumns(32);
+        string.setText(parm.getDescription());
+        showDesc.setBounds(new Rectangle(10, 10, 16, 16));
+        firstrow.add(showDesc);
+      }
       add(firstrow);
       validator = parm.getValidValue();
       parameter = parm;
       if (validator != null)
       {
-        integ = validator.getType() == Type.Integer;
+        integ = validator.getType() == ValueType.Integer;
       }
       else
       {
@@ -370,15 +482,18 @@ public class OptsAndParamsPage
     }
 
     @Override
-    public int getBaseline(int width, int height) {
-        return 0;
+    public int getBaseline(int width, int height)
+    {
+      return 0;
     }
 
-    // from http://stackoverflow.com/questions/2743177/top-alignment-for-flowlayout
+    // from
+    // http://stackoverflow.com/questions/2743177/top-alignment-for-flowlayout
     // helpful hint of using the Java 1.6 alignBaseLine property of FlowLayout
     @Override
-    public Component.BaselineResizeBehavior getBaselineResizeBehavior() {
-        return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
+    public Component.BaselineResizeBehavior getBaselineResizeBehavior()
+    {
+      return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
     }
 
     public int getBoxHeight()
@@ -391,11 +506,11 @@ public class OptsAndParamsPage
       ParameterI prm = parameter.copy();
       if (choice)
       {
-        prm.setDefaultValue((String) choicebox.getSelectedItem());
+        prm.setValue((String) choicebox.getSelectedItem());
       }
       else
       {
-        prm.setDefaultValue(valueField.getText());
+        prm.setValue(valueField.getText());
       }
       return prm;
     }
@@ -449,6 +564,7 @@ public class OptsAndParamsPage
       }
 
     }
+
     public void updateControls(ParameterI parm)
     {
       adjusting = true;
@@ -467,6 +583,31 @@ public class OptsAndParamsPage
           slider.addChangeListener(this);
           valueField = new JTextField();
           valueField.addActionListener(this);
+          valueField.addKeyListener(new KeyListener()
+          {
+
+            @Override
+            public void keyTyped(KeyEvent e)
+            {
+            }
+
+            @Override
+            public void keyReleased(KeyEvent e)
+            {
+              if (e.isActionKey())
+              {
+                if (valueField.getText().trim().length() > 0)
+                {
+                  actionPerformed(null);
+                }
+              }
+            }
+
+            @Override
+            public void keyPressed(KeyEvent e)
+            {
+            }
+          });
           valueField.setPreferredSize(new Dimension(60, 25));
           controlPanel.add(slider, BorderLayout.WEST);
           controlPanel.add(valueField, BorderLayout.EAST);
@@ -487,14 +628,14 @@ public class OptsAndParamsPage
             }
           }
 
-          if (parm.getDefaultValue() != null)
+          if (parm.getValue() != null)
           {
-            choicebox.setSelectedItem(parm.getDefaultValue());
+            choicebox.setSelectedItem(parm.getValue());
           }
         }
         else
         {
-          valueField.setText(parm.getDefaultValue());
+          valueField.setText(parm.getValue());
         }
       }
       lastVal = updateSliderFromValueField();
@@ -532,11 +673,13 @@ public class OptsAndParamsPage
           {
           }
           ;
+          // update value field to reflect any bound checking we performed.
+          valueField.setText("" + iVal);
           if (validator.getMin() != null && validator.getMax() != null)
           {
             slider.getModel().setRangeProperties(iVal, 1,
                     validator.getMin().intValue(),
-                    validator.getMax().intValue(), true);
+                    validator.getMax().intValue()+1, true);
           }
           else
           {
@@ -550,6 +693,7 @@ public class OptsAndParamsPage
           fVal = 0f;
           try
           {
+            valueField.setText(valueField.getText().trim());
             fVal = Float.valueOf(valueField.getText());
             if (validator.getMin() != null
                     && validator.getMin().floatValue() > fVal)
@@ -557,6 +701,8 @@ public class OptsAndParamsPage
               fVal = validator.getMin().floatValue();
               // TODO: provide visual indication that hard limit was reached for
               // this parameter
+              // update value field to reflect any bound checking we performed.
+              valueField.setText("" + fVal);
             }
             if (validator.getMax() != null
                     && validator.getMax().floatValue() < fVal)
@@ -564,6 +710,8 @@ public class OptsAndParamsPage
               fVal = validator.getMax().floatValue();
               // TODO: provide visual indication that hard limit was reached for
               // this parameter
+              // update value field to reflect any bound checking we performed.
+              valueField.setText("" + fVal);
             }
           } catch (Exception e)
           {
@@ -571,9 +719,9 @@ public class OptsAndParamsPage
           ;
           if (validator.getMin() != null && validator.getMax() != null)
           {
-            slider.getModel().setRangeProperties((int) fVal * 1000, 1,
-                    (int) validator.getMin().floatValue() * 1000,
-                    (int) validator.getMax().floatValue() * 1000, true);
+            slider.getModel().setRangeProperties((int) (fVal * 1000f), 1,
+                    (int) (validator.getMin().floatValue() * 1000f),
+                    1+(int) (validator.getMax().floatValue() * 1000f), true);
           }
           else
           {
@@ -601,14 +749,22 @@ public class OptsAndParamsPage
     }
   }
 
-  static final int PARAM_WIDTH = 340;
+  public static final int PARAM_WIDTH = 340;
 
-  private static final int PARAM_HEIGHT = 150;
+  public static final int PARAM_HEIGHT = 150;
+
+  public static final int PARAM_CLOSEDHEIGHT = 80;
+
+  public OptsAndParamsPage(OptsParametersContainerI paramContainer)
+  {
+    this(paramContainer, false);
+  }
 
-  static final int PARAM_CLOSEDHEIGHT = 80;
-  public OptsAndParamsPage(OptsParametersContainerI wsJobParameters)
+  public OptsAndParamsPage(OptsParametersContainerI paramContainer,
+          boolean compact)
   {
-    poparent = wsJobParameters;
+    poparent = paramContainer;
+    this.compact = compact;
   }
 
   public static void showUrlPopUp(JComponent invoker, final String finfo,
@@ -616,7 +772,7 @@ public class OptsAndParamsPage
   {
 
     JPopupMenu mnu = new JPopupMenu();
-    JMenuItem mitem = new JMenuItem("View " + finfo);
+    JMenuItem mitem = new JMenuItem(MessageManager.formatMessage("label.view_params", new String[]{finfo}));
     mitem.addActionListener(new ActionListener()
     {
 
@@ -631,12 +787,11 @@ public class OptsAndParamsPage
     mnu.show(invoker, x, y);
   }
 
-
   URL linkImageURL = getClass().getResource("/images/link.gif");
 
-  Map<String, OptionBox> optSet = new Hashtable<String, OptionBox>();
+  Map<String, OptionBox> optSet = new java.util.LinkedHashMap<String, OptionBox>();
 
-  Map<String, ParamBox> paramSet = new Hashtable<String, ParamBox>();
+  Map<String, ParamBox> paramSet = new java.util.LinkedHashMap<String, ParamBox>();
 
   public Map<String, OptionBox> getOptSet()
   {
@@ -658,7 +813,6 @@ public class OptsAndParamsPage
     this.paramSet = paramSet;
   }
 
-
   OptsParametersContainerI poparent;
 
   OptionBox addOption(OptionI opt)
@@ -680,7 +834,7 @@ public class OptsAndParamsPage
     {
       pb = new ParamBox(poparent, arg);
       paramSet.put(arg.getName(), pb);
-//      paramList.add(pb);
+      // paramList.add(pb);
     }
     pb.init();
     // take the defaults from the parameter
@@ -729,5 +883,32 @@ public class OptsAndParamsPage
 
   }
 
+  /**
+   * recover options and parameters from GUI
+   * 
+   * @return
+   */
+  public List<ArgumentI> getCurrentSettings()
+  {
+    List<ArgumentI> argSet = new ArrayList<ArgumentI>();
+    for (OptionBox opts : getOptSet().values())
+    {
+      OptionI opt = opts.getOptionIfEnabled();
+      if (opt != null)
+      {
+        argSet.add(opt);
+      }
+    }
+    for (ParamBox parambox : getParamSet().values())
+    {
+      ParameterI parm = parambox.getParameter();
+      if (parm != null)
+      {
+        argSet.add(parm);
+      }
+    }
+
+    return argSet;
+  }
 
 }