JAL-3371 JAL-2983 add gui.Slider to handle negative, float or % values
[jalview.git] / src / jalview / gui / FeatureTypeSettings.java
index 73a22fa..92918d4 100644 (file)
@@ -48,6 +48,8 @@ import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
+import java.math.BigDecimal;
+import java.math.MathContext;
 import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.List;
@@ -62,7 +64,6 @@ import javax.swing.JComboBox;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JRadioButton;
-import javax.swing.JSlider;
 import javax.swing.JTextField;
 import javax.swing.border.EmptyBorder;
 import javax.swing.border.LineBorder;
@@ -78,6 +79,8 @@ import javax.swing.event.ChangeListener;
  */
 public class FeatureTypeSettings extends JalviewDialog
 {
+  private final static MathContext FOUR_SIG_FIG = new MathContext(4);
+
   private final static String LABEL_18N = MessageManager
           .getString("label.label");
 
@@ -141,20 +144,6 @@ public class FeatureTypeSettings extends JalviewDialog
   private float max;
 
   /*
-   * scale factor for conversion between absolute min-max and slider
-   * slider value is true value * scale factor
-   */
-  private float sliderScaleFactor;
-
-  /*
-   *  value to subtract from slider value before conversion;
-   *  normally zero, but >0 if min is negative
-   *  true value = (slider value - offset) / scale factor
-   *  slider value = true value * scale factor + offset 
-   */
-  private int sliderOffset;
-
-  /*
    * radio button group, to select what to colour by:
    * simple colour, by category (text), or graduated
    */
@@ -177,7 +166,7 @@ public class FeatureTypeSettings extends JalviewDialog
 
   private JComboBox<Object> threshold = new JComboBox<>();
 
-  private JSlider slider = new JSlider();
+  private Slider slider;
 
   private JTextField thresholdValue = new JTextField(20);
 
@@ -358,14 +347,9 @@ public class FeatureTypeSettings extends JalviewDialog
        * valid options are offered in the combo box)
        * offset slider to have only non-negative values if necessary (JAL-2983)
        */
-      sliderScaleFactor = (max == min) ? 1f : 100f / (max - min);
-      float range = (max - min) * sliderScaleFactor;
-      int minimum = (int) (min * sliderScaleFactor);
-      int maximum = (int) (max * sliderScaleFactor);
-      sliderOffset = minimum < 0f ? -minimum : 0;
-      slider.setMinimum(minimum + sliderOffset);
-      slider.setMaximum(maximum + sliderOffset);
-      slider.setMajorTickSpacing((int) (range / 10f));
+      slider.setSliderModel(min, max, min);
+      slider.setMajorTickSpacing(
+              (int) ((slider.getMaximum() - slider.getMinimum()) / 10f));
 
       threshline = new GraphLine((max - min) / 2f, "Threshold",
               Color.black);
@@ -377,8 +361,8 @@ public class FeatureTypeSettings extends JalviewDialog
                 fc.isAboveThreshold() ? ABOVE_THRESHOLD_OPTION
                         : BELOW_THRESHOLD_OPTION);
         slider.setEnabled(true);
-        setSliderValue(fc.getThreshold());
-        thresholdValue.setText(String.valueOf(fc.getThreshold()));
+        slider.setSliderValue(fc.getThreshold());
+        setThresholdValueText(fc.getThreshold());
         thresholdValue.setEnabled(true);
         thresholdIsMin.setEnabled(true);
       }
@@ -653,6 +637,7 @@ public class FeatureTypeSettings extends JalviewDialog
         thresholdValue_actionPerformed();
       }
     });
+    slider = new Slider(0f, 100f, 50f);
     slider.setPaintLabels(false);
     slider.setPaintTicks(true);
     slider.setBackground(Color.white);
@@ -669,8 +654,7 @@ public class FeatureTypeSettings extends JalviewDialog
       {
         if (!adjusting)
         {
-          thresholdValue
-                  .setText(String.format("%.3f", getSliderValue()));
+          setThresholdValueText(slider.getSliderValue());
           thresholdValue.setBackground(Color.white); // to reset red for invalid
           sliderValueChanged();
         }
@@ -1045,8 +1029,8 @@ public class FeatureTypeSettings extends JalviewDialog
       float f = Float.parseFloat(thresholdValue.getText());
       f = Float.max(f,  this.min);
       f = Float.min(f, this.max);
-      thresholdValue.setText(String.valueOf(f));
-      setSliderValue(f * sliderScaleFactor);
+      setThresholdValueText(f);
+      slider.setSliderValue(f);
       threshline.value = f;
       thresholdValue.setBackground(Color.white); // ok
       adjusting = false;
@@ -1059,13 +1043,25 @@ public class FeatureTypeSettings extends JalviewDialog
   }
 
   /**
+   * Sets the text field for threshold value, rounded to four significant figures
+   * 
+   * @param f
+   */
+  void setThresholdValueText(float f)
+  {
+    BigDecimal formatted = new BigDecimal(f).round(FOUR_SIG_FIG)
+            .stripTrailingZeros();
+    thresholdValue.setText(formatted.toPlainString());
+  }
+
+  /**
    * Action on change of threshold slider value. This may be done interactively
    * (by moving the slider), or programmatically (to update the slider after
    * manual input of a threshold value).
    */
   protected void sliderValueChanged()
   {
-    threshline.value = getSliderValue();
+    threshline.value = slider.getSliderValue();
 
     /*
      * repaint alignment, but not Overview or structure,
@@ -1755,41 +1751,4 @@ public class FeatureTypeSettings extends JalviewDialog
 
     updateFiltersTab();
   }
-
-  /**
-   * Answers the slider value, converted to the corresponding 'true' value by
-   * applying scaling
-   * 
-   * @return
-   */
-  float getSliderValue()
-  {
-    int value = slider.getValue();
-    float f = (value - sliderOffset) / sliderScaleFactor;
-
-    /*
-     * avoid rounding errors at min/max of range
-     */
-    if (value == slider.getMaximum())
-    {
-      f = max;
-    }
-    else if (value == slider.getMinimum())
-    {
-      f = min;
-    }
-    return f;
-  }
-
-  /**
-   * Sets the slider value, converted from the corresponding 'true' value by
-   * applying scaling
-   * 
-   * @param f
-   */
-  void setSliderValue(float f)
-  {
-    float v = f * sliderScaleFactor + sliderOffset;
-    slider.setValue((int) v);
-  }
 }