JAL-1925 update source version in license
[jalview.git] / src / jalview / gui / OptsAndParamsPage.java
index eb04d08..a74fd25 100644 (file)
@@ -1,23 +1,46 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b2)
+ * Copyright (C) 2015 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.Hashtable;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -37,15 +60,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 +105,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 + "\"/>")
-                + "</html>");
+
+        enabled.setToolTipText(JvSwingUtils
+                .wrapTooltip(
+                        true,
+                        ((desc == null || desc.trim().length() == 0) ? MessageManager
+                                .getString("label.opt_and_params_further_details ")
+                                : desc)
+                                + "<br><img src=\"" + linkImageURL + "\"/>"));
         enabled.addMouseListener(this);
       }
       else
       {
-        enabled.setToolTipText("<html>"
-                + JvSwingUtils.wrapTooltip(opt.getDescription())
-                + "</html>");
+        if (desc != null && desc.trim().length() > 0)
+        {
+          enabled.setToolTipText(JvSwingUtils.wrapTooltip(true,
+                  opt.getDescription()));
+        }
       }
       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 +166,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 +185,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 +238,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,7 +259,7 @@ public class OptsAndParamsPage
       }
       else
       {
-        initVal = (initEnabled) ? option.getDefaultValue() : null;
+        initVal = (initEnabled) ? (String) val.getSelectedItem() : null;
       }
     }
 
@@ -253,6 +305,64 @@ 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 = (JvSwingUtils
+                .wrapTooltip(
+                        true,
+                        parm.getDescription()
+                                + (finfo != null ? "<br><img src=\""
+                                        + linkImageURL
+                                        + "\"/>"
+                                        + MessageManager
+                                                .getString("label.opt_and_params_further_detail")
+                                        : "")));
+      }
+
+      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 +373,69 @@ 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(JvSwingUtils.wrapTooltip(
+                  true,
+                  MessageManager
+                          .formatMessage(
+                                  "label.opt_and_params_show_brief_desc_image_link",
+                                  new String[] { linkImageURL
+                                          .toExternalForm() })));
+          showDesc.addMouseListener(this);
+        }
+        else
+        {
+          showDesc.setToolTipText(JvSwingUtils.wrapTooltip(
+                  true,
+                  MessageManager
+                          .getString("label.opt_and_params_show_brief_desc")));
+        }
+        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 +487,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 +511,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 +569,7 @@ public class OptsAndParamsPage
       }
 
     }
+
     public void updateControls(ParameterI parm)
     {
       adjusting = true;
@@ -467,6 +588,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 +633,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,24 +678,26 @@ 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
           {
             slider.setVisible(false);
           }
-          return new int[]
-          { iVal };
+          return new int[] { iVal };
         }
         else
         {
           fVal = 0f;
           try
           {
+            valueField.setText(valueField.getText().trim());
             fVal = Float.valueOf(valueField.getText());
             if (validator.getMin() != null
                     && validator.getMin().floatValue() > fVal)
@@ -557,6 +705,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 +714,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,16 +723,16 @@ 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
           {
             slider.setVisible(false);
           }
-          return new float[]
-          { fVal };
+          return new float[] { fVal };
         }
       }
       else
@@ -588,27 +740,33 @@ public class OptsAndParamsPage
         if (!choice)
         {
           slider.setVisible(false);
-          return new String[]
-          { valueField.getText().trim() };
+          return new String[] { valueField.getText().trim() };
         }
         else
         {
-          return new String[]
-          { (String) choicebox.getSelectedItem() };
+          return new String[] { (String) choicebox.getSelectedItem() };
         }
       }
 
     }
   }
 
-  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;
 
-  static final int PARAM_CLOSEDHEIGHT = 80;
-  public OptsAndParamsPage(WsJobParameters wsJobParameters)
+  public static final int PARAM_CLOSEDHEIGHT = 80;
+
+  public OptsAndParamsPage(OptsParametersContainerI paramContainer)
   {
-    poparent = wsJobParameters;
+    this(paramContainer, false);
+  }
+
+  public OptsAndParamsPage(OptsParametersContainerI paramContainer,
+          boolean compact)
+  {
+    poparent = paramContainer;
+    this.compact = compact;
   }
 
   public static void showUrlPopUp(JComponent invoker, final String finfo,
@@ -616,7 +774,8 @@ 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 +790,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 +816,6 @@ public class OptsAndParamsPage
     this.paramSet = paramSet;
   }
 
-
   OptsParametersContainerI poparent;
 
   OptionBox addOption(OptionI opt)
@@ -680,7 +837,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
@@ -704,7 +861,9 @@ public class OptsAndParamsPage
       }
       else
       {
-        throw new Error("Invalid value " + string + " for option " + option);
+        throw new Error(MessageManager.formatMessage(
+                "error.invalid_value_for_option", new String[] { string,
+                    option.getName() }));
       }
 
     }
@@ -729,5 +888,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;
+  }
 
 }