Merge branch 'bug/JAL-2983negativeSliderMin' into releases/Release_2_11_1_Branch
[jalview.git] / src / jalview / gui / FeatureTypeSettings.java
index 73a22fa..512cf06 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.gui;
 
+import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureColourI;
 import jalview.bin.Cache;
@@ -48,6 +49,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 +65,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 +80,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 +145,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 +167,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 +348,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 +362,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 +638,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 +655,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();
         }
@@ -687,7 +672,7 @@ public class FeatureTypeSettings extends JalviewDialog
          */
         if (ap != null)
         {
-          ap.paintAlignment(true, true);
+          refreshDisplay(true);
         }
       }
     });
@@ -888,7 +873,7 @@ public class FeatureTypeSettings extends JalviewDialog
      * save the colour, and repaint stuff
      */
     fr.setColour(featureType, acg);
-    ap.paintAlignment(updateStructsAndOverview, updateStructsAndOverview);
+    refreshDisplay(updateStructsAndOverview);
 
     updateColoursTab();
   }
@@ -1027,7 +1012,7 @@ public class FeatureTypeSettings extends JalviewDialog
   {
     fr.setColour(featureType, originalColour);
     fr.setFeatureFilter(featureType, originalFilter);
-    ap.paintAlignment(true, true);
+    refreshDisplay(true);
   }
 
   /**
@@ -1045,8 +1030,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 +1044,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,
@@ -1751,45 +1748,26 @@ public class FeatureTypeSettings extends JalviewDialog
      * (note this might now be an empty filter with no conditions)
      */
     fr.setFeatureFilter(featureType, combined.isEmpty() ? null : combined);
-    ap.paintAlignment(true, true);
+    refreshDisplay(true);
 
     updateFiltersTab();
   }
 
   /**
-   * Answers the slider value, converted to the corresponding 'true' value by
-   * applying scaling
+   * Repaints alignment, structure and overview (if shown). If there is a
+   * complementary view which is showing this view's features, then also
+   * repaints that.
    * 
-   * @return
+   * @param updateStructsAndOverview
    */
-  float getSliderValue()
+  void refreshDisplay(boolean updateStructsAndOverview)
   {
-    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())
+    ap.paintAlignment(true, updateStructsAndOverview);
+    AlignViewportI complement = ap.getAlignViewport().getCodingComplement();
+    if (complement != null && complement.isShowComplementFeatures())
     {
-      f = min;
+      AlignFrame af2 = Desktop.getAlignFrameFor(complement);
+      af2.alignPanel.paintAlignment(true, updateStructsAndOverview);
     }
-    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);
   }
 }