graduated feature schemes (with visual indication of thresholding)
[jalview.git] / src / jalview / gui / FeatureColourChooser.java
index 993cd2e..1898113 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
- * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
+ * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -23,23 +23,35 @@ 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 java.awt.Dimension;
 
-public class FeatureColourChooser extends JPanel
+public class FeatureColourChooser extends JPanel 
 {
-  JInternalFrame frame;
+  JDialog frame;
   
-  FeatureRenderer fr;
-
-  FeatureSettings fs;
-
-  GraduatedColor cs;
-  Object oldcs;
 
+//  FeatureSettings fs;
+  FeatureRenderer fr;
+  
+  
+  private GraduatedColor cs;
+  private Object oldcs;
+  /**
+   * 
+   * @return the last colour setting selected by user - either oldcs (which may be a java.awt.Color) or the new GraduatedColor
+   */
+  public Object getLastColour() {
+    if (cs==null)
+    {
+      return oldcs;
+    }
+    return cs;
+  }
   Hashtable oldgroupColours;
   
   AlignmentPanel ap;
@@ -51,16 +63,22 @@ public class FeatureColourChooser extends JPanel
 
   private float max;
   String type = null;
-  public FeatureColourChooser(FeatureSettings fsettings, String type)
+  public FeatureColourChooser(FeatureRenderer frender, String type)
   {
-    this.fs = fsettings;
+    this(frender,false,type);
+  }
+    public FeatureColourChooser(FeatureRenderer frender, boolean block, String type)
+    {
+    this.fr = frender;
     this.type = type;
-    fr = fsettings.fr;
     ap = fr.ap;
-    frame = new JInternalFrame();
+    frame = new JDialog(Desktop.instance,true);
+    frame.setTitle("Graduated Feature Colour for "+type);
+    Rectangle deskr = Desktop.instance.getBounds();
+    frame.setBounds(new Rectangle((int) (deskr.getCenterX()-240),(int) (deskr.getCenterY()-92),480,185));
     frame.setContentPane(this);
-    frame.setLayer(JLayeredPane.PALETTE_LAYER);
-    Desktop.addInternalFrame(frame, "Graduated Feature Colour for "+type, 480, 145);
+    //frame.setLayer(JLayeredPane.PALETTE_LAYER);
+    //Desktop.addInternalFrame(frame, "Graduated Feature Colour for "+type, 480, 145);
 
     slider.addChangeListener(new ChangeListener()
     {
@@ -77,7 +95,7 @@ public class FeatureColourChooser extends JPanel
     {
       public void mouseReleased(MouseEvent evt)
       {
-        if (fr.ap!=null) { fr.ap.paintAlignment(true); };
+        if (ap!=null) { ap.paintAlignment(true); };
       }
     });
 
@@ -87,7 +105,13 @@ public class FeatureColourChooser extends JPanel
     oldcs = fr.featureColours.get(type);
     if (oldcs instanceof GraduatedColor)
     {
-      cs = new GraduatedColor((GraduatedColor) oldcs, min, max);
+      if (((GraduatedColor)oldcs).isAutoScale())
+      {
+        // update the scale
+        cs = new GraduatedColor((GraduatedColor) oldcs, min, max);
+      } else {
+        cs = new GraduatedColor((GraduatedColor) oldcs);
+      }
     } else {
       // promote original color to a graduated color
       Color bl = Color.black;
@@ -97,9 +121,10 @@ public class FeatureColourChooser extends JPanel
       }
       // original colour becomes the maximum colour
       cs = new GraduatedColor(Color.white,bl,mm[0],mm[1]);
+      cs.setColourByLabel(false);
     }
-    minColour.setBackground(cs.getMinColor());
-    maxColour.setBackground(cs.getMaxColor());
+    minColour.setBackground(oldminColour=cs.getMinColor());
+    maxColour.setBackground(oldmaxColour=cs.getMaxColor());
     adjusting = true;
     
     try
@@ -108,11 +133,37 @@ public class FeatureColourChooser extends JPanel
     } catch (Exception ex)
     {
     }
+    // update the gui from threshold state
+    thresholdIsMin.setSelected(!cs.isAutoScale());
+    colourByLabel.setSelected(cs.isColourByLabel());
+    if (cs.getThreshType()!=AnnotationColourGradient.NO_THRESHOLD)
+    {
+      // initialise threshold slider and selector
+      threshold.setSelectedIndex(cs.getThreshType()==AnnotationColourGradient.ABOVE_THRESHOLD ? 1 : 2);
+            slider.setEnabled(true);
+      thresholdValue.setEnabled(true);
+      threshline = new jalview.datamodel.GraphLine(
+                        (max - min) / 2f,
+                        "Threshold", Color.black);
+      
+    } 
 
     adjusting = false;
 
     changeColour();
+    if (!block)
+    {
+      new Thread(new Runnable() {
 
+      public void run()
+      {
+        frame.show();
+      }
+      
+    }).start();
+    } else {
+      frame.show();
+    }
   }
 
   public FeatureColourChooser()
@@ -128,8 +179,9 @@ public class FeatureColourChooser extends JPanel
 
   private void jbInit() throws Exception
   {
+    
     minColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
-    minColour.setBorder(BorderFactory.createEtchedBorder());
+    minColour.setBorder(BorderFactory.createLineBorder(Color.black));
     minColour.setPreferredSize(new Dimension(40, 20));
     minColour.setToolTipText("Minimum Colour");
     minColour.addMouseListener(new MouseAdapter()
@@ -143,7 +195,7 @@ public class FeatureColourChooser extends JPanel
       }
     });
     maxColour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
-    maxColour.setBorder(BorderFactory.createEtchedBorder());
+    maxColour.setBorder(BorderFactory.createLineBorder(Color.black));
     maxColour.setPreferredSize(new Dimension(40, 20));
     maxColour.setToolTipText("Maximum Colour");
     maxColour.addMouseListener(new MouseAdapter()
@@ -156,6 +208,11 @@ public class FeatureColourChooser extends JPanel
         }
       }
     });
+    maxColour.setBorder(new LineBorder(Color.black));
+    minText.setText("Min:");
+    minText.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
+    maxText.setText("Max:");
+    maxText.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
     ok.setOpaque(false);
     ok.setText("OK");
     ok.addActionListener(new ActionListener()
@@ -185,9 +242,10 @@ public class FeatureColourChooser extends JPanel
         threshold_actionPerformed(e);
       }
     });
-    threshold.addItem("No Threshold");
-    threshold.addItem("Above Threshold");
-    threshold.addItem("Below Threshold");
+    threshold.setToolTipText("Threshold the feature display by score.");
+    threshold.addItem("No Threshold"); // index 0
+    threshold.addItem("Above Threshold"); // index 1
+    threshold.addItem("Below Threshold"); // index 2
     jPanel3.setLayout(flowLayout2);
     thresholdValue.addActionListener(new ActionListener()
     {
@@ -202,21 +260,13 @@ public class FeatureColourChooser extends JPanel
     slider.setEnabled(false);
     slider.setOpaque(false);
     slider.setPreferredSize(new Dimension(100, 32));
+    slider.setToolTipText("Adjust threshold");
     thresholdValue.setEnabled(false);
     thresholdValue.setColumns(7);
     jPanel3.setBackground(Color.white);
-    currentColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
-    currentColours.setOpaque(false);
-    currentColours.setText("Use Original Colours");
-    currentColours.addActionListener(new ActionListener()
-    {
-      public void actionPerformed(ActionEvent e)
-      {
-        currentColours_actionPerformed(e);
-      }
-    });
     thresholdIsMin.setBackground(Color.white);
     thresholdIsMin.setText("Threshold is Min/Max");
+    thresholdIsMin.setToolTipText("Toggle between absolute and relative display threshold.");
     thresholdIsMin.addActionListener(new ActionListener()
     {
       public void actionPerformed(ActionEvent actionEvent)
@@ -224,11 +274,25 @@ public class FeatureColourChooser extends JPanel
         thresholdIsMin_actionPerformed(actionEvent);
       }
     });
+    colourByLabel.setBackground(Color.white);
+    colourByLabel.setText("Colour by Label");
+    colourByLabel.setToolTipText("Display features of the same type with a different label using a different colour. (e.g. domain features)");
+    colourByLabel.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent actionEvent)
+      {
+        colourByLabel_actionPerformed(actionEvent);
+      }
+    });
+    colourPanel.setBackground(Color.white);
     jPanel1.add(ok);
     jPanel1.add(cancel);
-    // jPanel2.add(currentColours);
-    jPanel2.add(minColour);
-    jPanel2.add(maxColour);
+    jPanel2.add(colourByLabel,java.awt.BorderLayout.WEST);
+    jPanel2.add(colourPanel,java.awt.BorderLayout.EAST);
+    colourPanel.add(minText);
+    colourPanel.add(minColour);
+    colourPanel.add(maxText);
+    colourPanel.add(maxColour);
     this.add(jPanel3, java.awt.BorderLayout.CENTER);
     jPanel3.add(threshold);
     jPanel3.add(slider);
@@ -239,6 +303,8 @@ public class FeatureColourChooser extends JPanel
   }
 
 
+  JLabel minText = new JLabel();
+  JLabel maxText = new JLabel();
   JPanel minColour = new JPanel();
 
   JPanel maxColour = new JPanel();
@@ -246,7 +312,7 @@ public class FeatureColourChooser extends JPanel
   JButton ok = new JButton();
 
   JButton cancel = new JButton();
-
+  JPanel colourPanel = new JPanel();
   JPanel jPanel1 = new JPanel();
 
   JPanel jPanel2 = new JPanel();
@@ -264,13 +330,20 @@ public class FeatureColourChooser extends JPanel
   JSlider slider = new JSlider();
 
   JTextField thresholdValue = new JTextField(20);
-  // TODO refactor to tolower flag
-  JCheckBox currentColours = new JCheckBox();
+  // 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;
+
   public void minColour_actionPerformed()
   {
     Color col = JColorChooser.showDialog(this,
@@ -316,13 +389,22 @@ public class FeatureColourChooser extends JPanel
 
     slider.setEnabled(true);
     thresholdValue.setEnabled(true);
-    GraduatedColor acg = new GraduatedColor(minColour.getBackground(), maxColour.getBackground(), min, max);
+    
+    GraduatedColor acg;
+    if (cs.isColourByLabel())
+      {
+        acg = new GraduatedColor(oldminColour, oldmaxColour, min, max);
+      } else {
+        acg = new GraduatedColor(oldminColour=minColour.getBackground(), oldmaxColour=maxColour.getBackground(), min, max);
+        
+      }
 
     if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
     {
       slider.setEnabled(false);
       thresholdValue.setEnabled(false);
       thresholdValue.setText("");
+      thresholdIsMin.setEnabled(false);
     }
     else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
             && threshline == null)
@@ -348,31 +430,53 @@ public class FeatureColourChooser extends JPanel
       slider.setMajorTickSpacing((int) (range / 10f));
       slider.setEnabled(true);
       thresholdValue.setEnabled(true);
+      thresholdIsMin.setEnabled(!colourByLabel.isSelected());
       adjusting = false;
     }
 
     acg.setThreshType(aboveThreshold);
     if (thresholdIsMin.isSelected() && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
     {
+      acg.setAutoScaled(false);
       if (aboveThreshold==AnnotationColourGradient.ABOVE_THRESHOLD)
       { 
         acg = new GraduatedColor(acg, threshline.value, max);
       } else { 
         acg = new GraduatedColor(acg, min,threshline.value);
       }
+    } else {
+      acg.setAutoScaled(true);
+    }
+    acg.setColourByLabel(colourByLabel.isSelected());
+    if (acg.isColourByLabel())
+    {
+      maxColour.setEnabled(false);
+      minColour.setEnabled(false);
+      maxColour.setBackground(this.getBackground());
+      minColour.setBackground(this.getBackground());
+    } else {
+      maxColour.setEnabled(true);
+      minColour.setEnabled(true);
+      maxColour.setBackground(oldmaxColour);
+      minColour.setBackground(oldminColour);
     }
-    
     fr.featureColours.put(type,acg);
     cs = acg;
     ap.paintAlignment(false);
   }
-
+  private void raiseClosed() {
+    if (this.colourEditor!=null)
+    {
+      colourEditor.actionPerformed(new ActionEvent(this, 0, "CLOSED"));
+    }
+  }
   public void ok_actionPerformed(ActionEvent e)
   {
     changeColour();
     try
     {
-      frame.setClosed(true);
+      frame.dispose();
+      raiseClosed();
     } catch (Exception ex)
     {
     }
@@ -383,7 +487,9 @@ public class FeatureColourChooser extends JPanel
     reset();
     try
     {
-      frame.setClosed(true);
+      frame.dispose();
+//      frame.setClosed(true);
+      raiseClosed();
     } catch (Exception ex)
     {
     }
@@ -392,6 +498,8 @@ public class FeatureColourChooser extends JPanel
   void reset()
   {
     fr.featureColours.put(type, oldcs);
+    ap.paintAlignment(false);
+    cs = null;
   }
 
   public void thresholdCheck_actionPerformed(ActionEvent e)
@@ -429,22 +537,22 @@ public class FeatureColourChooser extends JPanel
     ap.paintAlignment(false);
   }
 
-  public void currentColours_actionPerformed(ActionEvent e)
+  public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)
   {
-    if (currentColours.isSelected())
-    {
-      reset();
-    }
-
-    maxColour.setEnabled(!currentColours.isSelected());
-    minColour.setEnabled(!currentColours.isSelected());
-
     changeColour();
   }
-
-  public void thresholdIsMin_actionPerformed(ActionEvent actionEvent)
+  public void colourByLabel_actionPerformed(ActionEvent actionEvent)
   {
     changeColour();
   }
+  ActionListener colourEditor=null;
+  public void addActionListener(ActionListener graduatedColorEditor)
+  {
+    if (colourEditor!=null)
+    {
+      System.err.println("IMPLEMENTATION ISSUE: overwriting action listener for FeatureColourChooser");
+    }
+    colourEditor = graduatedColorEditor;
+  }
 
 }