JAL-2055 prototype alternate feature colouring based on
[jalview.git] / src / jalview / gui / FeatureColourChooser.java
index 6b28937..d4e37f7 100644 (file)
@@ -1,36 +1,51 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.1)
- * Copyright (C) 2014 The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ 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.
+ * 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/>.
+ * 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 java.util.*;
-
-import java.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.border.LineBorder;
-import javax.swing.event.*;
-
-import jalview.datamodel.*;
-import jalview.schemes.*;
+import jalview.datamodel.GraphLine;
+import jalview.schemes.AnnotationColourGradient;
+import jalview.schemes.GraduatedColor;
 import jalview.util.MessageManager;
 
+import java.awt.BorderLayout;
+import java.awt.Color;
 import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Hashtable;
+
+import javax.swing.BorderFactory;
+import javax.swing.JCheckBox;
+import javax.swing.JColorChooser;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JTextField;
+import javax.swing.border.LineBorder;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
 
 public class FeatureColourChooser extends JalviewDialog
 {
@@ -61,12 +76,39 @@ public class FeatureColourChooser extends JalviewDialog
 
   boolean adjusting = false;
 
-  private float min;
+  final private float min;
+
+  final private float max;
 
-  private float max;
+  final private float scaleFactor;
 
   String type = null;
 
+  JPanel minColour = new JPanel();
+
+  JPanel maxColour = new JPanel();
+
+  JComboBox threshold = new JComboBox();
+
+  JSlider slider = new JSlider();
+
+  JTextField thresholdValue = new JTextField(20);
+
+  // TODO implement GUI for tolower flag
+  // JCheckBox toLower = new JCheckBox();
+
+  JCheckBox thresholdIsMin = new JCheckBox();
+
+  JCheckBox colourAlternately = new JCheckBox();
+
+  JCheckBox colourByLabel = new JCheckBox();
+
+  private GraphLine threshline;
+
+  private Color oldmaxColour;
+
+  private Color oldminColour;
+
   public FeatureColourChooser(FeatureRenderer frender, String type)
   {
     this(frender, false, type);
@@ -78,25 +120,28 @@ public class FeatureColourChooser extends JalviewDialog
     this.fr = frender;
     this.type = type;
     ap = fr.ap;
-    initDialogFrame(this, true, block, "Graduated Feature Colour for "
-            + type, 480, 185);
+    String title = MessageManager.formatMessage(
+            "label.graduated_color_for_params", new String[] { type });
+    initDialogFrame(this, true, block, title, 480, 185);
     // frame.setLayer(JLayeredPane.PALETTE_LAYER);
     // Desktop.addInternalFrame(frame, "Graduated Feature Colour for "+type,
     // 480, 145);
 
     slider.addChangeListener(new ChangeListener()
     {
+      @Override
       public void stateChanged(ChangeEvent evt)
       {
         if (!adjusting)
         {
-          thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
+          thresholdValue.setText((slider.getValue() / scaleFactor) + "");
           valueChanged();
         }
       }
     });
     slider.addMouseListener(new MouseAdapter()
     {
+      @Override
       public void mouseReleased(MouseEvent evt)
       {
         if (ap != null)
@@ -107,10 +152,18 @@ public class FeatureColourChooser extends JalviewDialog
       }
     });
 
-    float mm[] = ((float[][]) fr.minmax.get(type))[0];
+    float mm[] = fr.getMinMax().get(type)[0];
     min = mm[0];
     max = mm[1];
-    oldcs = fr.featureColours.get(type);
+
+    /*
+     * ensure scale factor allows a scaled range with
+     * 10 integer divisions ('ticks'); if we have got here,
+     * we should expect that max != min
+     */
+    scaleFactor = (max == min) ? 1f : 100f / (max - min);
+
+    oldcs = fr.getFeatureColours().get(type);
     if (oldcs instanceof GraduatedColor)
     {
       if (((GraduatedColor) oldcs).isAutoScale())
@@ -148,6 +201,7 @@ public class FeatureColourChooser extends JalviewDialog
     // update the gui from threshold state
     thresholdIsMin.setSelected(!cs.isAutoScale());
     colourByLabel.setSelected(cs.isColourByLabel());
+    colourAlternately.setSelected(cs.isColourAlternately());
     if (cs.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
     {
       // initialise threshold slider and selector
@@ -167,17 +221,6 @@ public class FeatureColourChooser extends JalviewDialog
     waitForInput();
   }
 
-  public FeatureColourChooser()
-  {
-    try
-    {
-      jbInit();
-    } catch (Exception ex)
-    {
-      ex.printStackTrace();
-    }
-  }
-
   private void jbInit() throws Exception
   {
 
@@ -187,6 +230,7 @@ public class FeatureColourChooser extends JalviewDialog
     minColour.setToolTipText(MessageManager.getString("label.min_colour"));
     minColour.addMouseListener(new MouseAdapter()
     {
+      @Override
       public void mousePressed(MouseEvent e)
       {
         if (minColour.isEnabled())
@@ -201,6 +245,7 @@ public class FeatureColourChooser extends JalviewDialog
     maxColour.setToolTipText(MessageManager.getString("label.max_colour"));
     maxColour.addMouseListener(new MouseAdapter()
     {
+      @Override
       public void mousePressed(MouseEvent e)
       {
         if (maxColour.isEnabled())
@@ -210,28 +255,39 @@ public class FeatureColourChooser extends JalviewDialog
       }
     });
     maxColour.setBorder(new LineBorder(Color.black));
+    JLabel minText = new JLabel();
     minText.setText(MessageManager.getString("label.min"));
     minText.setFont(JvSwingUtils.getLabelFont());
+    JLabel maxText = new JLabel();
     maxText.setText(MessageManager.getString("label.max"));
     maxText.setFont(JvSwingUtils.getLabelFont());
-    this.setLayout(borderLayout1);
-    jPanel2.setLayout(flowLayout1);
+    this.setLayout(new BorderLayout());
+    JPanel jPanel1 = new JPanel();
+    JPanel jPanel2 = new JPanel();
+    jPanel2.setLayout(new FlowLayout());
     jPanel1.setBackground(Color.white);
     jPanel2.setBackground(Color.white);
     threshold.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         threshold_actionPerformed(e);
       }
     });
-    threshold.setToolTipText(MessageManager.getString("label.threshold_feature_display_by_score"));
-    threshold.addItem(MessageManager.getString("label.threshold_feature_no_thereshold")); // index 0
-    threshold.addItem(MessageManager.getString("label.threshold_feature_above_thereshold")); // index 1
-    threshold.addItem(MessageManager.getString("label.threshold_feature_below_thereshold")); // index 2
-    jPanel3.setLayout(flowLayout2);
+    threshold.setToolTipText(MessageManager
+            .getString("label.threshold_feature_display_by_score"));
+    threshold.addItem(MessageManager
+            .getString("label.threshold_feature_no_thereshold")); // index 0
+    threshold.addItem(MessageManager
+            .getString("label.threshold_feature_above_thereshold")); // index 1
+    threshold.addItem(MessageManager
+            .getString("label.threshold_feature_below_thereshold")); // index 2
+    JPanel jPanel3 = new JPanel();
+    jPanel3.setLayout(new FlowLayout());
     thresholdValue.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         thresholdValue_actionPerformed(e);
@@ -243,36 +299,58 @@ public class FeatureColourChooser extends JalviewDialog
     slider.setEnabled(false);
     slider.setOpaque(false);
     slider.setPreferredSize(new Dimension(100, 32));
-    slider.setToolTipText(MessageManager.getString("label.adjust_thereshold"));
+    slider.setToolTipText(MessageManager
+            .getString("label.adjust_thereshold"));
     thresholdValue.setEnabled(false);
     thresholdValue.setColumns(7);
     jPanel3.setBackground(Color.white);
     thresholdIsMin.setBackground(Color.white);
-    thresholdIsMin.setText(MessageManager.getString("label.threshold_minmax"));
-    thresholdIsMin
-            .setToolTipText(MessageManager.getString("label.toggle_absolute_relative_display_threshold"));
+    thresholdIsMin.setText(MessageManager
+            .getString("label.threshold_minmax"));
+    thresholdIsMin.setToolTipText(MessageManager
+            .getString("label.toggle_absolute_relative_display_threshold"));
     thresholdIsMin.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent actionEvent)
       {
         thresholdIsMin_actionPerformed(actionEvent);
       }
     });
+    colourAlternately.setBackground(Color.white);
+    colourAlternately.setText(MessageManager
+            .getString("label.colour_alternately"));
+    colourAlternately.setToolTipText(MessageManager
+            .getString("label.colour_alternately_tip"));
+    colourAlternately.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent actionEvent)
+      {
+        colourAlternately_actionPerformed(actionEvent);
+      }
+    });
     colourByLabel.setBackground(Color.white);
-    colourByLabel.setText(MessageManager.getString("label.colour_by_label"));
     colourByLabel
-            .setToolTipText(MessageManager.getString("label.display_features_same_type_different_label_using_different_colour"));
+            .setText(MessageManager.getString("label.colour_by_label"));
+    colourByLabel
+            .setToolTipText(MessageManager
+                    .getString("label.display_features_same_type_different_label_using_different_colour"));
     colourByLabel.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent actionEvent)
       {
         colourByLabel_actionPerformed(actionEvent);
       }
     });
+
+    JPanel colourPanel = new JPanel();
     colourPanel.setBackground(Color.white);
     jPanel1.add(ok);
     jPanel1.add(cancel);
-    jPanel2.add(colourByLabel, java.awt.BorderLayout.WEST);
+    jPanel2.add(colourAlternately, java.awt.BorderLayout.WEST);
+    jPanel2.add(colourByLabel, java.awt.BorderLayout.CENTER);
     jPanel2.add(colourPanel, java.awt.BorderLayout.EAST);
     colourPanel.add(minText);
     colourPanel.add(minColour);
@@ -287,51 +365,16 @@ public class FeatureColourChooser extends JalviewDialog
     this.add(jPanel2, java.awt.BorderLayout.NORTH);
   }
 
-  JLabel minText = new JLabel();
-
-  JLabel maxText = new JLabel();
-
-  JPanel minColour = new JPanel();
-
-  JPanel maxColour = new JPanel();
-
-  JPanel colourPanel = new JPanel();
-
-  JPanel jPanel1 = new JPanel();
-
-  JPanel jPanel2 = new JPanel();
-
-  BorderLayout borderLayout1 = new BorderLayout();
-
-  JComboBox threshold = new JComboBox();
-
-  FlowLayout flowLayout1 = new FlowLayout();
-
-  JPanel jPanel3 = new JPanel();
-
-  FlowLayout flowLayout2 = new FlowLayout();
-
-  JSlider slider = new JSlider();
-
-  JTextField thresholdValue = new JTextField(20);
-
-  // TODO implement GUI for tolower flag
-  // JCheckBox toLower = new JCheckBox();
-
-  JCheckBox thresholdIsMin = new JCheckBox();
-
-  JCheckBox colourByLabel = new JCheckBox();
-
-  private GraphLine threshline;
-
-  private Color oldmaxColour;
-
-  private Color oldminColour;
+  protected void colourAlternately_actionPerformed(ActionEvent actionEvent)
+  {
+    changeColour();
+  }
 
   public void minColour_actionPerformed()
   {
     Color col = JColorChooser.showDialog(this,
-            MessageManager.getString("label.select_colour_minimum_value"), minColour.getBackground());
+            MessageManager.getString("label.select_colour_minimum_value"),
+            minColour.getBackground());
     if (col != null)
     {
       minColour.setBackground(col);
@@ -344,7 +387,8 @@ public class FeatureColourChooser extends JalviewDialog
   public void maxColour_actionPerformed()
   {
     Color col = JColorChooser.showDialog(this,
-            MessageManager.getString("label.select_colour_maximum_value"), maxColour.getBackground());
+            MessageManager.getString("label.select_colour_maximum_value"),
+            maxColour.getBackground());
     if (col != null)
     {
       maxColour.setBackground(col);
@@ -363,11 +407,11 @@ public class FeatureColourChooser extends JalviewDialog
     }
 
     int aboveThreshold = AnnotationColourGradient.NO_THRESHOLD;
-    if (threshold.getSelectedIndex()==1)
+    if (threshold.getSelectedIndex() == 1)
     {
       aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
     }
-    else if (threshold.getSelectedIndex()==2)
+    else if (threshold.getSelectedIndex() == 2)
     {
       aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
     }
@@ -407,11 +451,11 @@ public class FeatureColourChooser extends JalviewDialog
       adjusting = true;
       acg.setThresh(threshline.value);
 
-      float range = max * 1000f - min * 1000f;
+      float range = (max - min) * scaleFactor;
 
-      slider.setMinimum((int) (min * 1000));
-      slider.setMaximum((int) (max * 1000));
-      slider.setValue((int) (threshline.value * 1000));
+      slider.setMinimum((int) (min * scaleFactor));
+      slider.setMaximum((int) (max * scaleFactor));
+      slider.setValue((int) (threshline.value * scaleFactor));
       thresholdValue.setText(threshline.value + "");
       slider.setMajorTickSpacing((int) (range / 10f));
       slider.setEnabled(true);
@@ -439,6 +483,14 @@ public class FeatureColourChooser extends JalviewDialog
       acg.setAutoScaled(true);
     }
     acg.setColourByLabel(colourByLabel.isSelected());
+    acg.setColourAlternately(colourAlternately.isSelected());
+    colourByLabel.setEnabled(!colourAlternately.isSelected());
+    colourAlternately.setEnabled(!colourByLabel.isSelected());
+    if (!fr.isOrdinal(type))
+    {
+      // don't allow colour alternately if no feature numbering on features
+      colourAlternately.setEnabled(false);
+    }
     if (acg.isColourByLabel())
     {
       maxColour.setEnabled(false);
@@ -458,11 +510,12 @@ public class FeatureColourChooser extends JalviewDialog
       maxColour.setForeground(oldmaxColour);
       minColour.setForeground(oldminColour);
     }
-    fr.featureColours.put(type, acg);
+    fr.setColour(type, acg);
     cs = acg;
     ap.paintAlignment(false);
   }
 
+  @Override
   protected void raiseClosed()
   {
     if (this.colourEditor != null)
@@ -471,11 +524,13 @@ public class FeatureColourChooser extends JalviewDialog
     }
   }
 
+  @Override
   public void okPressed()
   {
     changeColour();
   }
 
+  @Override
   public void cancelPressed()
   {
     reset();
@@ -483,7 +538,7 @@ public class FeatureColourChooser extends JalviewDialog
 
   void reset()
   {
-    fr.featureColours.put(type, oldcs);
+    fr.setColour(type, oldcs);
     ap.paintAlignment(false);
     cs = null;
   }
@@ -508,7 +563,7 @@ public class FeatureColourChooser extends JalviewDialog
     try
     {
       float f = Float.parseFloat(thresholdValue.getText());
-      slider.setValue((int) (f * 1000));
+      slider.setValue((int) (f * scaleFactor));
       threshline.value = f;
     } catch (NumberFormatException ex)
     {
@@ -517,7 +572,7 @@ public class FeatureColourChooser extends JalviewDialog
 
   public void valueChanged()
   {
-    threshline.value = (float) slider.getValue() / 1000f;
+    threshline.value = slider.getValue() / scaleFactor;
     cs.setThresh(threshline.value);
     changeColour();
     ap.paintAlignment(false);