JAL-3949 Complete new abstracted logging framework in jalview.log. Updated log calls...
[jalview.git] / src / jalview / gui / FeatureTypeSettings.java
index 9ff51a8..aaf81ac 100644 (file)
  */
 package jalview.gui;
 
+import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureColourI;
+import jalview.bin.Cache;
 import jalview.datamodel.GraphLine;
 import jalview.datamodel.features.FeatureAttributes;
 import jalview.datamodel.features.FeatureAttributes.Datatype;
@@ -48,6 +50,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;
@@ -61,8 +65,8 @@ 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;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
@@ -76,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");
 
@@ -139,11 +145,6 @@ public class FeatureTypeSettings extends JalviewDialog
   private float max;
 
   /*
-   * scale factor for conversion between absolute min-max and slider
-   */
-  float scaleFactor;
-
-  /*
    * radio button group, to select what to colour by:
    * simple colour, by category (text), or graduated
    */
@@ -163,9 +164,9 @@ public class FeatureTypeSettings extends JalviewDialog
 
   JPanel maxColour = new JPanel();
 
-  private JComboBox<String> threshold = new JComboBox<>();
+  private JComboBox<Object> threshold = new JComboBox<>();
 
-  JSlider slider = new JSlider();
+  private Slider slider;
 
   JTextField thresholdValue = new JTextField(20);
 
@@ -180,17 +181,17 @@ public class FeatureTypeSettings extends JalviewDialog
   /*
    * choice of option for 'colour for no value'
    */
-  private JComboBox<String> noValueCombo;
+  private JComboBox<Object> noValueCombo;
 
   /*
    * choice of what to colour by text (Label or attribute)
    */
-  private JComboBox<String> colourByTextCombo;
+  private JComboBox<Object> colourByTextCombo;
 
   /*
    * choice of what to colour by range (Score or attribute)
    */
-  private JComboBox<String> colourByRangeCombo;
+  private JComboBox<Object> colourByRangeCombo;
 
   private JRadioButton andFilters;
 
@@ -344,12 +345,11 @@ public class FeatureTypeSettings extends JalviewDialog
        * update min-max scaling if there is a range to work with,
        * else disable the widgets (this shouldn't happen if only 
        * valid options are offered in the combo box)
+       * offset slider to have only non-negative values if necessary (JAL-2983)
        */
-      scaleFactor = (max == min) ? 1f : 100f / (max - min);
-      float range = (max - min) * scaleFactor;
-      slider.setMinimum((int) (min * scaleFactor));
-      slider.setMaximum((int) (max * scaleFactor));
-      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);
@@ -361,8 +361,8 @@ public class FeatureTypeSettings extends JalviewDialog
                 fc.isAboveThreshold() ? ABOVE_THRESHOLD_OPTION
                         : BELOW_THRESHOLD_OPTION);
         slider.setEnabled(true);
-        slider.setValue((int) (fc.getThreshold() * scaleFactor));
-        thresholdValue.setText(String.valueOf(fc.getThreshold()));
+        slider.setSliderValue(fc.getThreshold());
+        setThresholdValueText(fc.getThreshold());
         thresholdValue.setEnabled(true);
         thresholdIsMin.setEnabled(true);
       }
@@ -640,6 +640,7 @@ public class FeatureTypeSettings extends JalviewDialog
         thresholdValue_actionPerformed();
       }
     });
+    slider = new Slider(0f, 100f, 50f);
     slider.setPaintLabels(false);
     slider.setPaintTicks(true);
     slider.setBackground(Color.white);
@@ -656,8 +657,7 @@ public class FeatureTypeSettings extends JalviewDialog
       {
         if (!adjusting)
         {
-          thresholdValue
-                  .setText(String.valueOf(slider.getValue() / scaleFactor));
+          setThresholdValueText(slider.getSliderValue());
           thresholdValue.setBackground(Color.white); // to reset red for invalid
           sliderValueChanged();
         }
@@ -674,7 +674,7 @@ public class FeatureTypeSettings extends JalviewDialog
          */
         if (ap != null)
         {
-          ap.paintAlignment(true, true);
+          refreshDisplay(true);
         }
       }
     });
@@ -890,7 +890,7 @@ public class FeatureTypeSettings extends JalviewDialog
      * save the colour, and repaint stuff
      */
     fr.setColour(featureType, acg);
-    ap.paintAlignment(updateStructsAndOverview, updateStructsAndOverview);
+    refreshDisplay(updateStructsAndOverview);
 
     updateColoursPanel();
   }
@@ -1029,7 +1029,7 @@ public class FeatureTypeSettings extends JalviewDialog
   {
     fr.setColour(featureType, originalColour);
     fr.setFeatureFilter(featureType, originalFilter);
-    ap.paintAlignment(true, true);
+    refreshDisplay(true);
   }
 
   /**
@@ -1047,8 +1047,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));
-      slider.setValue((int) (f * scaleFactor));
+      setThresholdValueText(f);
+      slider.setSliderValue(f);
       threshline.value = f;
       thresholdValue.setBackground(Color.white); // ok
       adjusting = false;
@@ -1061,13 +1061,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 = getRoundedSliderValue();
+    threshline.value = slider.getSliderValue();
 
     /*
      * repaint alignment, but not Overview or structure,
@@ -1076,21 +1088,6 @@ public class FeatureTypeSettings extends JalviewDialog
     colourChanged(false);
   }
 
-  /**
-   * Converts the slider value to its absolute value by dividing by the
-   * scaleFactor. Rounding errors are squashed by forcing min/max of slider
-   * range to the actual min/max of feature score range
-   * 
-   * @return
-   */
-  private float getRoundedSliderValue()
-  {
-    int value = slider.getValue();
-    float f = value == slider.getMaximum() ? max
-            : (value == slider.getMinimum() ? min : value / scaleFactor);
-    return f;
-  }
-
   void addActionListener(ActionListener listener)
   {
     if (featureSettings != null)
@@ -1120,7 +1117,7 @@ public class FeatureTypeSettings extends JalviewDialog
    * @param withRange
    * @param withText
    */
-  protected JComboBox<String> populateAttributesDropdown(
+  protected JComboBox<Object> populateAttributesDropdown(
           List<String[]> attNames, boolean withRange, boolean withText)
   {
     List<String> displayAtts = new ArrayList<>();
@@ -1159,9 +1156,11 @@ public class FeatureTypeSettings extends JalviewDialog
       tooltips.add(desc == null ? "" : desc);
     }
 
-    JComboBox<String> attCombo = JvSwingUtils
-            .buildComboWithTooltips(displayAtts, tooltips);
-
+    // now convert String List to Object List for buildComboWithTooltips
+    List<Object> displayAttsObjects = new ArrayList<>(displayAtts);
+    JComboBox<Object> attCombo = JvSwingUtils
+            .buildComboWithTooltips(displayAttsObjects, tooltips);
+    
     return attCombo;
   }
 
@@ -1339,8 +1338,8 @@ public class FeatureTypeSettings extends JalviewDialog
      * drop-down choice of attribute, with description as a tooltip 
      * if we can obtain it
      */
-    JComboBox<String> attCombo = populateAttributesDropdown(attNames, true,
-            true);
+    final JComboBox<Object> attCombo = populateAttributesDropdown(attNames,
+            true, true);
     String filterBy = setSelectedAttribute(attCombo, filter);
 
     JComboBox<Condition> condCombo = new JComboBox<>();
@@ -1441,10 +1440,13 @@ public class FeatureTypeSettings extends JalviewDialog
     if (!patternField.isEnabled()
             || (pattern != null && pattern.trim().length() > 0))
     {
-      JButton removeCondition = new JButton("\u2717"); // Dingbats cursive x
+      JButton removeCondition = new JButton("\u2717");
+      // Dingbats cursive x
+      removeCondition.setBorder(new EmptyBorder(0, 0, 0, 0));
+      removeCondition.setBackground(Color.WHITE);
       removeCondition.setPreferredSize(new Dimension(23, 17));
-      removeCondition
-              .setToolTipText(MessageManager.getString("label.delete_row"));
+      removeCondition.setToolTipText(
+              MessageManager.getString("label.delete_condition"));
       removeCondition.addActionListener(new ActionListener()
       {
         @Override
@@ -1467,7 +1469,7 @@ public class FeatureTypeSettings extends JalviewDialog
    * @param attCombo
    * @param filter
    */
-  private String setSelectedAttribute(JComboBox<String> attCombo,
+  private String setSelectedAttribute(JComboBox<Object> attCombo,
           FeatureMatcherI filter)
   {
     String item = null;
@@ -1684,11 +1686,19 @@ public class FeatureTypeSettings extends JalviewDialog
    * @param valueField
    * @param filterIndex
    */
-  protected boolean updateFilter(JComboBox<String> attCombo,
+  protected boolean updateFilter(JComboBox<Object> attCombo,
           JComboBox<Condition> condCombo, JTextField valueField,
           int filterIndex)
   {
-    String attName = (String) attCombo.getSelectedItem();
+    String attName;
+    try
+    {
+      attName = (String) attCombo.getSelectedItem();
+    } catch (Exception e)
+    {
+      Cache.error("Problem casting Combo box entry to String");
+      attName = attCombo.getSelectedItem().toString();
+    }
     Condition cond = (Condition) condCombo.getSelectedItem();
     String pattern = valueField.getText().trim();
 
@@ -1765,8 +1775,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);
 
     updateFiltersPanel();
   }
+
+  /**
+   * Repaints alignment, structure and overview (if shown). If there is a
+   * complementary view which is showing this view's features, then also
+   * repaints that.
+   * 
+   * @param updateStructsAndOverview
+   */
+  void refreshDisplay(boolean updateStructsAndOverview)
+  {
+    ap.paintAlignment(true, updateStructsAndOverview);
+    AlignViewportI complement = ap.getAlignViewport().getCodingComplement();
+    if (complement != null && complement.isShowComplementFeatures())
+    {
+      AlignFrame af2 = Desktop.getAlignFrameFor(complement);
+      af2.alignPanel.paintAlignment(true, updateStructsAndOverview);
+    }
+  }
 }