graduated feature color editing
authorjprocter <Jim Procter>
Fri, 16 Apr 2010 14:32:29 +0000 (14:32 +0000)
committerjprocter <Jim Procter>
Fri, 16 Apr 2010 14:32:29 +0000 (14:32 +0000)
src/jalview/appletgui/FeatureColourChooser.java
src/jalview/appletgui/FeatureRenderer.java
src/jalview/appletgui/FeatureSettings.java
src/jalview/appletgui/UserDefinedColours.java

index f4ad1d5..e3ab8eb 100644 (file)
@@ -30,11 +30,11 @@ import java.awt.Rectangle;
 public class FeatureColourChooser extends Panel implements
         ActionListener, AdjustmentListener, ItemListener, MouseListener
 {
-  Frame frame;
+  JVDialog frame;
 
   FeatureRenderer fr;
-  FeatureSettings fs;
-  AlignmentPanel ap;
+  FeatureSettings fs = null;
+  // AlignmentPanel ap;
 
   GraduatedColor cs;
   Object oldcs;
@@ -45,13 +45,22 @@ public class FeatureColourChooser extends Panel implements
   boolean adjusting = false;
   private float min,max;
   String type=null;
-  
+
+  private AlignFrame af=null;
+  public FeatureColourChooser(AlignFrame af, String type)
+  {
+    this.af = af;
+    init(af.getSeqcanvas().getFeatureRenderer(), type);
+  }
   public FeatureColourChooser(FeatureSettings fsettings, String type)
   {
     this.fs = fsettings;
+    init(fsettings.fr, type);
+    // this.ap = fsettings.ap;
+  }
+  private void init(FeatureRenderer frenderer,String type) {
     this.type = type;
-    fr = fsettings.fr;
-    ap = fsettings.ap;
+    fr = frenderer;
     float mm[] = ((float[][]) fr.minmax.get(type))[0];
     min = mm[0];
     max = mm[1];
@@ -71,6 +80,7 @@ public class FeatureColourChooser extends Panel implements
     }
     minColour.setBackground(cs.getMinColor());
     maxColour.setBackground(cs.getMaxColor());
+    colourFromLabel.setState(cs.isColourByLabel());
     adjusting = true;
 
     try
@@ -79,16 +89,26 @@ public class FeatureColourChooser extends Panel implements
     } catch (Exception ex)
     {
     }
-    // To HERE!
+    threshold.select(cs.getThreshType()==AnnotationColourGradient.NO_THRESHOLD ? 0 : cs.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD ? 1 : 2);
+    
     adjusting = false;
     changeColour();
+    colourFromLabel.addItemListener(this);
     slider.addAdjustmentListener(this);
     slider.addMouseListener(this);
-    frame = new Frame();
-    frame.add(this);
-    jalview.bin.JalviewLite.addFrame(frame, "Graduated Feature Colour for "+type, 480,
-            145);
+    Frame owner = (af!=null) ? af : fs.frame;
+    frame = new JVDialog(owner,"Graduated Feature Colour for "+type,true,480,248);
+    frame.setMainPanel(this);
     validate();
+    frame.setVisible(true);
+    if (frame.accept) {
+      changeColour();
+    } else {
+      // cancel
+        reset();
+        PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
+        frame.setVisible(false);
+    }
   }
 
   public FeatureColourChooser()
@@ -113,79 +133,72 @@ public class FeatureColourChooser extends Panel implements
     maxColour.addActionListener(this);
 
     thresholdIsMin.addItemListener(this);
-    ok.setLabel("OK");
-    ok.addActionListener(this);
-
-    cancel.setLabel("Cancel");
-    cancel.addActionListener(this);
-
-    this.setLayout(borderLayout1);
-    jPanel2.setLayout(flowLayout1);
 
+    this.setLayout(new GridLayout(4,1));
+    jPanel1.setLayout(new FlowLayout());
+    jPanel2.setLayout(new FlowLayout());
+    jPanel3.setLayout(new GridLayout(1,1));
+    jPanel4.setLayout(new FlowLayout());
     jPanel1.setBackground(Color.white);
     jPanel2.setBackground(Color.white);
+    jPanel4.setBackground(Color.white);
     threshold.addItemListener(this);
     threshold.addItem("No Threshold");
     threshold.addItem("Above Threshold");
     threshold.addItem("Below Threshold");
-    jPanel3.setLayout(null);
     thresholdValue.addActionListener(this);
-
     slider.setBackground(Color.white);
     slider.setEnabled(false);
-    slider.setBounds(new Rectangle(153, 3, 93, 21));
+    slider.setSize(new Dimension(93, 21));
     thresholdValue.setEnabled(false);
-    thresholdValue.setBounds(new Rectangle(248, 2, 79, 22));
+    thresholdValue.setSize(new Dimension(79,22)); //setBounds(new Rectangle(248, 2, 79, 22));
     thresholdValue.setColumns(5);
     jPanel3.setBackground(Color.white);
-    //currentColours.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
-    //currentColours.setLabel("Use Original Colours");
-    //currentColours.addItemListener(this);
-
-    threshold.setBounds(new Rectangle(11, 3, 139, 22));
+    
+    colourFromLabel.setFont(new java.awt.Font("Verdana", Font.PLAIN, 11));
+    colourFromLabel.setLabel("Colour by Label");
+    colourFromLabel.setSize(new Dimension(139,22));
+    //threshold.setBounds(new Rectangle(11, 3, 139, 22));
     thresholdIsMin.setBackground(Color.white);
     thresholdIsMin.setLabel("Threshold is min/max");
-    thresholdIsMin.setBounds(new Rectangle(328, 3, 135, 23));
-    jPanel1.add(ok);
-    jPanel1.add(cancel);
-    //jPanel2.add(currentColours);
-    jPanel2.add(minColour);
-    jPanel2.add(maxColour);
-    jPanel3.add(threshold);
+    thresholdIsMin.setSize(new Dimension(135,23));
+    //thresholdIsMin.setBounds(new Rectangle(328, 3, 135, 23));
+    jPanel1.add(minColour);
+    jPanel1.add(maxColour);
+    jPanel1.add(colourFromLabel);
+    jPanel2.add(threshold);
     jPanel3.add(slider);
-    jPanel3.add(thresholdValue);
-    jPanel3.add(thresholdIsMin);
-    this.add(jPanel2, java.awt.BorderLayout.NORTH);
-    this.add(jPanel3, java.awt.BorderLayout.CENTER);
-    this.add(jPanel1, java.awt.BorderLayout.SOUTH);
+    jPanel4.add(thresholdValue);
+    jPanel4.add(thresholdIsMin);
+    this.add(jPanel1);//, java.awt.BorderLayout.NORTH);
+    this.add(jPanel2);//, java.awt.BorderLayout.NORTH);
+    this.add(jPanel3);//, java.awt.BorderLayout.CENTER);
+    this.add(jPanel4);//, java.awt.BorderLayout.CENTER);
   }
 
   Button minColour = new Button();
 
   Button maxColour = new Button();
 
-  Button ok = new Button();
-
-  Button cancel = new Button();
-
+  
   Panel jPanel1 = new Panel();
 
   Panel jPanel2 = new Panel();
 
   Choice threshold = new Choice();
 
-  FlowLayout flowLayout1 = new FlowLayout();
-
   Panel jPanel3 = new Panel();
+  Panel jPanel4 = new Panel();
 
   Scrollbar slider = new Scrollbar(Scrollbar.HORIZONTAL);
 
   TextField thresholdValue = new TextField(20);
 
 
-  BorderLayout borderLayout1 = new BorderLayout();
+//  BorderLayout borderLayout1 = new BorderLayout();
 
   Checkbox thresholdIsMin = new Checkbox();
+  Checkbox colourFromLabel = new Checkbox();
 
   private GraphLine threshline;
 
@@ -210,19 +223,6 @@ public class FeatureColourChooser extends Panel implements
     {
       maxColour_actionPerformed(null);
     }
-
-    else if (evt.getSource() == ok)
-    {
-      changeColour();
-      frame.setVisible(false);
-    }
-    else if (evt.getSource() == cancel)
-    {
-      reset();
-      ap.paintAlignment(true);
-      frame.setVisible(false);
-    }
-
     else
     {
       changeColour();
@@ -231,7 +231,8 @@ public class FeatureColourChooser extends Panel implements
 
   public void itemStateChanged(ItemEvent evt)
   {
-
+    maxColour.setEnabled(!colourFromLabel.getState());
+    minColour.setEnabled(!colourFromLabel.getState());
     changeColour();
   }
 
@@ -244,37 +245,35 @@ public class FeatureColourChooser extends Panel implements
     }
   }
   protected void valueChanged() {
-    changeColour();
     threshline.value = (float) slider.getValue() / 1000f;
-    ap.paintAlignment(false);
+    cs.setThresh(threshline.value);
+    changeColour();
+    PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
+    // ap.paintAlignment(false);
   }
   public void minColour_actionPerformed(Color newCol)
   {
-    if (newCol != null)
+    if (newCol == null)
     {
+      UserDefinedColours udc = new UserDefinedColours(this,minColour.getBackground(), frame, "Select Colour for Minimum Value");
+    } else {
       minColour.setBackground(newCol);
       minColour.repaint();
       changeColour();
     }
-    else
-    {
-      new UserDefinedColours(this, "Select Colour for Minimum Value", minColour.getBackground());
-    }
-
+    
   }
 
   public void maxColour_actionPerformed(Color newCol)
   {
-    if (newCol != null)
+    if (newCol == null)
     {
+      UserDefinedColours udc = new UserDefinedColours(this,maxColour.getBackground(), frame, "Select Colour for Maximum Value");// this, "Select Colour for Maximum Value", maxColour.getBackground());
+    } else {
       maxColour.setBackground(newCol);
       maxColour.repaint();
       changeColour();
     }
-    else
-    {
-      new UserDefinedColours(this, "Select Colour for Maximum Value", maxColour.getBackground());
-    }
   }
 
   void changeColour()
@@ -299,6 +298,9 @@ public class FeatureColourChooser extends Panel implements
     thresholdValue.setEnabled(true);
     GraduatedColor acg = new GraduatedColor(minColour.getBackground(), maxColour.getBackground(), min, max);
 
+    acg.setColourByLabel(colourFromLabel.getState());
+    maxColour.setEnabled(!colourFromLabel.getState());
+    minColour.setEnabled(!colourFromLabel.getState());
     if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
     {
       slider.setEnabled(false);
@@ -345,13 +347,15 @@ public class FeatureColourChooser extends Panel implements
     
     fr.featureColours.put(type,acg);
     cs = acg;
-    ap.paintAlignment(false);
+    PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
+    // ap.paintAlignment(false);
   }
 
   void reset()
   {
     fr.featureColours.put(type, oldcs);
-    ap.paintAlignment(true);
+    PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
+    // ap.paintAlignment(true);
 
   }
 
@@ -365,7 +369,8 @@ public class FeatureColourChooser extends Panel implements
 
   public void mouseReleased(MouseEvent evt)
   {
-    ap.paintAlignment(true);
+    PaintRefresher.Refresh(this, fr.av.getSequenceSetId());
+    // ap.paintAlignment(true);
   }
 
   public void mouseEntered(MouseEvent evt)
index 08b0970..c2c2462 100755 (executable)
@@ -26,6 +26,7 @@ import java.awt.event.*;
 
 import jalview.appletgui.FeatureSettings.MyCheckbox;
 import jalview.datamodel.*;
+import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.GraduatedColor;
 
 /**
@@ -66,7 +67,7 @@ public class FeatureRenderer
    * Creates a new FeatureRenderer object.
    * 
    * @param av
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    */
   public FeatureRenderer(AlignViewport av)
   {
@@ -96,7 +97,86 @@ public class FeatureRenderer
 
   boolean deleteFeature = false;
 
-  Panel colourPanel;
+  FeatureColourPanel colourPanel;
+  class FeatureColourPanel extends Panel {
+    String label="";
+    
+    private Color maxCol;
+    private boolean isColourByLabel,isGcol;
+    /**
+     * render a feature style in the amend feature dialog box
+     */
+    public void updateColor(Object newcol)
+    {
+      
+      Color bg,col=null;
+      GraduatedColor gcol=null;
+      String vlabel = "";
+      if (newcol instanceof Color)
+      {
+        isGcol=false;
+        col = (Color) newcol;
+        gcol = null;
+      }
+      else if (newcol instanceof GraduatedColor)
+      {
+        isGcol=true;
+        gcol = (GraduatedColor) newcol;
+        col = null;
+      }
+      else
+      {
+        throw new Error("Invalid color for MyCheckBox");
+      }
+      if (col != null)
+      {
+        setBackground(bg=col);
+      }
+      else
+      {
+        if (gcol.getThreshType()!=AnnotationColourGradient.NO_THRESHOLD)
+        {
+          vlabel += " "+((gcol.getThreshType()==AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)" : "(<)");
+        }
+        if (isColourByLabel=gcol.isColourByLabel()) {
+          setBackground(bg=Color.white);
+          vlabel += " (by Label)";
+        } else {
+          setBackground(bg=gcol.getMinColor());
+          maxCol = gcol.getMaxColor();
+        }
+      }
+      label=vlabel;
+      setBackground(bg);
+      repaint();
+    }
+    FeatureColourPanel() {
+      super(null);
+    }
+    public void paint(Graphics g) 
+    {
+      int width=getWidth(),height=getHeight();
+      if (isGcol) {
+      if (isColourByLabel)
+      {
+        g.setColor(Color.white);
+        g.fillRect(width/2, 0,width/2, height);
+        g.setColor(Color.black); 
+        Font f=new Font("Verdana", Font.PLAIN,
+                10);
+        g.setFont(f);
+        g.drawString("Label", 0, 0);
+      }
+      else
+      {
+        g.setColor(maxCol);
+        g.fillRect(width/2, 0,width/2, height);
+        
+      }
+      }
+    }
+
+  }
 
   boolean amendFeatures(final SequenceI[] sequences,
           final SequenceFeature[] features, boolean newFeatures,
@@ -112,12 +192,13 @@ public class FeatureRenderer
     Button deleteButton = new Button("Delete");
     deleteFeature = false;
 
-    colourPanel = new Panel(null);
+    colourPanel = new FeatureColourPanel();
     colourPanel.setSize(110, 15);
     final FeatureRenderer fr = this;
 
     Panel panel = new Panel(new GridLayout(3, 1));
-
+    
+    featureIndex = 0; // feature to be amended.
     Panel tmp;
 
     // /////////////////////////////////////
@@ -169,7 +250,7 @@ public class FeatureRenderer
                     .createColourFromName(name.getText());
           }
 
-          colourPanel.setBackground(col);
+          colourPanel.updateColor(col);
         }
       });
 
@@ -271,26 +352,40 @@ public class FeatureRenderer
     start.setText(features[0].getBegin() + "");
     end.setText(features[0].getEnd() + "");
     description.setText(features[0].getDescription());
-
     Color col = getColour(name.getText());
     if (col == null)
     {
       col = new jalview.schemes.UserColourScheme()
               .createColourFromName(name.getText());
     }
-
-    colourPanel.setBackground(col);
-
+    Object fcol = getFeatureStyle(name.getText());
+    // simply display the feature color in a box
+    colourPanel.updateColor(fcol);
     dialog.setResizable(true);
-
-    colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
+    // TODO: render the graduated color in the box.
+    if (fcol instanceof Color)
     {
-      public void mousePressed(java.awt.event.MouseEvent evt)
+      colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
       {
-        new UserDefinedColours(fr, ap.alignFrame);
-      }
-    });
+        public void mousePressed(java.awt.event.MouseEvent evt)
+        {
+          new UserDefinedColours(fr, ap.alignFrame);
+        }
+      });
 
+    }
+    else
+    {
+      colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
+      {
+        public void mousePressed(java.awt.event.MouseEvent evt)
+        {
+          FeatureColourChooser fcc = new FeatureColourChooser(ap.alignFrame, name.getText());
+          fcc.setFocusable(true);
+          dialog.transferFocus();
+        }
+      });
+    }
     dialog.setVisible(true);
 
     jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
@@ -310,14 +405,17 @@ public class FeatureRenderer
 
     if (!newFeatures)
     {
-      SequenceFeature sf = features[featureIndex];
 
+      SequenceFeature sf = features[featureIndex];
       if (dialog.accept)
       {
         sf.type = lastFeatureAdded;
         sf.featureGroup = lastFeatureGroupAdded;
         sf.description = lastDescriptionAdded;
-        setColour(sf.type, colourPanel.getBackground());
+        if (fcol instanceof Color) {
+          // update colour - otherwise its already done.
+          setColour(sf.type, colourPanel.getBackground());
+        }
         try
         {
           sf.begin = Integer.parseInt(start.getText());
@@ -358,14 +456,18 @@ public class FeatureRenderer
         }
 
         col = colourPanel.getBackground();
-        setColour(lastFeatureAdded, col);
+        //setColour(lastFeatureAdded, fcol);
 
         if (lastFeatureGroupAdded != null)
         {
           featureGroups.put(lastFeatureGroupAdded, new Boolean(true));
-          av.featuresDisplayed.put(lastFeatureGroupAdded, new Integer(col
-                  .getRGB()));
         }
+        if (fcol instanceof Color) {
+          setColour(lastFeatureAdded, fcol);
+        }
+        av.featuresDisplayed.put(lastFeatureAdded,
+                getFeatureStyle(lastFeatureAdded));
+
         findAllFeatures();
 
         String[] tro = new String[renderOrder.length];
@@ -383,7 +485,7 @@ public class FeatureRenderer
       }
     }
 
-    findAllFeatures();
+    // findAllFeatures();
 
     ap.paintAlignment(true);
 
@@ -434,23 +536,23 @@ public class FeatureRenderer
    * DOCUMENT ME!
    * 
    * @param g
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    * @param seq
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    * @param sg
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    * @param start
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    * @param end
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    * @param x1
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    * @param y1
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    * @param width
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    * @param height
-   *                DOCUMENT ME!
+   *          DOCUMENT ME!
    */
   // String type;
   // SequenceFeature sf;
@@ -543,38 +645,39 @@ public class FeatureRenderer
           if (sequenceFeatures[sfindex].begin <= start
                   && sequenceFeatures[sfindex].end >= start)
           {
-            currentColour = new Integer(getColour(sequenceFeatures[sfindex]).getRGB());//av.featuresDisplayed
-                    //.get(sequenceFeatures[sfindex].type);
+            currentColour = new Integer(
+                    getColour(sequenceFeatures[sfindex]).getRGB());// av.featuresDisplayed
+            // .get(sequenceFeatures[sfindex].type);
           }
 
         }
         else if (sequenceFeatures[sfindex].type.equals("disulfide bond"))
         {
 
-          renderFeature(
-                  g,
-                  seq,
-                  seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                  seq.findIndex(sequenceFeatures[sfindex].begin) - 1,
-                  new Color(((Integer) av.featuresDisplayed
-                          .get(sequenceFeatures[sfindex].type)).intValue()),
-                  start, end, y1);
-          renderFeature(
-                  g,
-                  seq,
-                  seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                  seq.findIndex(sequenceFeatures[sfindex].end) - 1,
-                  new Color(((Integer) av.featuresDisplayed
-                          .get(sequenceFeatures[sfindex].type)).intValue()),
-                  start, end, y1);
+          renderFeature(g, seq, seq
+                  .findIndex(sequenceFeatures[sfindex].begin) - 1, seq
+                  .findIndex(sequenceFeatures[sfindex].begin) - 1,
+                  getColour(sequenceFeatures[sfindex])
+                  // new Color(((Integer) av.featuresDisplayed
+                  // .get(sequenceFeatures[sfindex].type)).intValue())
+                  , start, end, y1);
+          renderFeature(g, seq, seq
+                  .findIndex(sequenceFeatures[sfindex].end) - 1, seq
+                  .findIndex(sequenceFeatures[sfindex].end) - 1,
+                  getColour(sequenceFeatures[sfindex])
+                  // new Color(((Integer) av.featuresDisplayed
+                  // .get(sequenceFeatures[sfindex].type)).intValue())
+                  , start, end, y1);
 
         }
         else
         {
-          renderFeature(g, seq, seq
+          if (showFeature(sequenceFeatures[sfindex]))
+          {          renderFeature(g, seq, seq
                   .findIndex(sequenceFeatures[sfindex].begin) - 1, seq
                   .findIndex(sequenceFeatures[sfindex].end) - 1,
                   getColour(sequenceFeatures[sfindex]), start, end, y1);
+          }
         }
 
       }
@@ -634,7 +737,9 @@ public class FeatureRenderer
       }
     }
   }
-  Hashtable minmax=null;
+
+  Hashtable minmax = null;
+
   void findAllFeatures()
   {
     jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
@@ -642,7 +747,7 @@ public class FeatureRenderer
     av.featuresDisplayed = new Hashtable();
     Vector allfeatures = new Vector();
     minmax = new Hashtable();
-    
+
     for (int i = 0; i < av.alignment.getHeight(); i++)
     {
       SequenceFeature[] features = av.alignment.getSequenceAt(i)
@@ -656,7 +761,8 @@ public class FeatureRenderer
       int index = 0;
       while (index < features.length)
       {
-        if (features[index].begin==0 && features[index].end==0) {
+        if (features[index].begin == 0 && features[index].end == 0)
+        {
           index++;
           continue;
         }
@@ -672,19 +778,21 @@ public class FeatureRenderer
                   getColour(features[index].getType()).getRGB()));
           allfeatures.addElement(features[index].getType());
         }
-                if (features[index].score != Float.NaN)
+        if (features[index].score != Float.NaN)
         {
-          int nonpos= features[index].getBegin()>=1 ? 0 : 1;
+          int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
           float[][] mm = (float[][]) minmax.get(features[index].getType());
           if (mm == null)
           {
-            mm = new float[][] {null, null };
+            mm = new float[][]
+            { null, null };
             minmax.put(features[index].getType(), mm);
           }
-          if (mm[nonpos]==null)
-          { 
-            mm[nonpos] = new float[] { features[index].score, features[index].score };
-            
+          if (mm[nonpos] == null)
+          {
+            mm[nonpos] = new float[]
+            { features[index].score, features[index].score };
+
           }
           else
           {
@@ -698,7 +806,7 @@ public class FeatureRenderer
             }
           }
         }
-        
+
         index++;
       }
     }
@@ -713,17 +821,32 @@ public class FeatureRenderer
     }
   }
 
-  public Color getColour(String featureType)
+  /**
+   * get a feature style object for the given type string. Creates a
+   * java.awt.Color for a featureType with no existing colourscheme. TODO:
+   * replace return type with object implementing standard abstract colour/style
+   * interface
+   * 
+   * @param featureType
+   * @return java.awt.Color or GraduatedColor
+   */
+  public Object getFeatureStyle(String featureType)
   {
     Object fc = featureColours.get(featureType);
     if (fc == null)
     {
       jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
       Color col = ucs.createColourFromName(featureType);
-      featureColours.put(featureType, col);
-      return col;
+      featureColours.put(featureType, fc = col);
     }
-    else if (fc instanceof Color)
+    return fc;
+  }
+
+  public Color getColour(String featureType)
+  {
+    Object fc = getFeatureStyle(featureType);
+
+    if (fc instanceof Color)
     {
       return (Color) fc;
     }
@@ -733,10 +856,24 @@ public class FeatureRenderer
       {
         return ((GraduatedColor) fc).getMaxColor();
       }
-      // TODO: raise an implementation error here.
-      return null; // Color.white;
     }
+    throw new Error("Implementation Error: Unrecognised render object "
+            + fc.getClass() + " for features of type " + featureType);
+  }
+  /**
+   * 
+   * @param sequenceFeature
+   * @return true if feature is visible.
+   */
+  private boolean showFeature(SequenceFeature sequenceFeature)
+  {
+    Object fc = getFeatureStyle(sequenceFeature.type);
+    if (fc instanceof GraduatedColor)
+    {
+      return ((GraduatedColor) fc).isColored(sequenceFeature);
+    } else { return true; }
   }
+
   /**
    * implement graduated colouring for features with scores
    * 
@@ -745,15 +882,8 @@ public class FeatureRenderer
    */
   public Color getColour(SequenceFeature feature)
   {
-    Object fc = featureColours.get(feature.type);
-    if (fc == null)
-    {
-      jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
-      Color col = ucs.createColourFromName(feature.type);
-      featureColours.put(feature.type, col);
-      return col;
-    }
-    else if (fc instanceof Color)
+    Object fc = getFeatureStyle(feature.getType());
+    if (fc instanceof Color)
     {
       return (Color) fc;
     }
@@ -763,14 +893,22 @@ public class FeatureRenderer
       {
         return ((GraduatedColor) fc).findColor(feature);
       }
-      // TODO: raise an implementation error here.
-      return null; // Color.white;
     }
+    throw new Error("Implementation Error: Unrecognised render object "
+            + fc.getClass() + " for features of type " + feature.getType());
   }
 
-  public void setColour(String featureType, Color col)
+  public void setColour(String featureType, Object col)
   {
-    featureColours.put(featureType, col);
+    // overwrite
+    // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof
+    // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null;
+    // Object c = featureColours.get(featureType);
+    // if (c == null || c instanceof Color || (c instanceof GraduatedColor &&
+    // !((GraduatedColor)c).getMaxColor().equals(_col)))
+    {
+      featureColours.put(featureType, col);
+    }
   }
 
   public void setFeaturePriority(Object[][] data)
@@ -796,7 +934,7 @@ public class FeatureRenderer
       for (int i = 0; i < data.length; i++)
       {
         String type = data[i][0].toString();
-        setColour(type, (Color) data[i][1]);
+        setColour(type,  data[i][1]);
         if (((Boolean) data[i][2]).booleanValue())
         {
           av.featuresDisplayed.put(type, new Integer(getColour(type)
@@ -832,7 +970,7 @@ public class FeatureRenderer
    * get visible or invisible groups
    * 
    * @param visible
-   *                true to return visible groups, false to return hidden ones.
+   *          true to return visible groups, false to return hidden ones.
    * @return list of groups
    */
   public String[] getGroups(boolean visible)
@@ -869,9 +1007,9 @@ public class FeatureRenderer
    * set all feature groups in toset to be visible or invisible
    * 
    * @param toset
-   *                group names
+   *          group names
    * @param visible
-   *                the state of the named groups to set
+   *          the state of the named groups to set
    */
   public void setGroupState(String[] toset, boolean visible)
   {
@@ -1049,6 +1187,7 @@ public class FeatureRenderer
 
     return alignmentHasFeatures;
   }
+
   /**
    * 
    * @return the displayed feature type as an array of strings
@@ -1065,9 +1204,9 @@ public class FeatureRenderer
         if (av.featuresDisplayed.get(typ[i]) == null)
         {
           typ[i] = null;
-            }
-        }       
+        }
       }
+    }
     return typ;
   }
 }
index 2eb203c..80559bd 100755 (executable)
@@ -26,6 +26,8 @@ import java.awt.event.*;
 import jalview.analysis.AlignmentSorter;
 import jalview.commands.OrderCommand;
 import jalview.datamodel.*;
+import jalview.schemes.AnnotationColourGradient;
+import jalview.schemes.GraduatedColor;
 
 public class FeatureSettings extends Panel implements ItemListener,
         MouseListener, MouseMotionListener, ActionListener,
@@ -154,9 +156,11 @@ public class FeatureSettings extends Panel implements ItemListener,
     g.drawString("(Features can be added from searches or", 10, 40);
     g.drawString("from Jalview / GFF features files)", 10, 60);
   }
-  protected void popupSort(final String type, final Hashtable minmax,
+
+  protected void popupSort(final MyCheckbox check, final Hashtable minmax,
           int x, int y)
   {
+    final String type = check.type;
     java.awt.PopupMenu men = new PopupMenu("Settings for " + type);
     java.awt.MenuItem scr = new MenuItem("Sort by Score");
     men.add(scr);
@@ -186,31 +190,23 @@ public class FeatureSettings extends Panel implements ItemListener,
     if (minmax != null)
     {
       final Object typeMinMax = minmax.get(type);
-      final java.awt.CheckboxMenuItem chb = new java.awt.CheckboxMenuItem("Vary Height");
-      // this is broken at the moment
-      chb.setState(minmax.get(type) != null);
-      chb.addActionListener(new ActionListener()
-      {
-
-        public void actionPerformed(ActionEvent e)
-        {
-          chb.setState(chb.getState());
-          if (chb.getState())
-          {
-            minmax.put(type, null);
-          }
-          else
-          {
-            minmax.put(type, typeMinMax);
-          }
-        }
-
-      });
-      men.add(chb);
+      /*
+       * final java.awt.CheckboxMenuItem chb = new
+       * java.awt.CheckboxMenuItem("Vary Height"); // this is broken at the
+       * moment chb.setState(minmax.get(type) != null);
+       * chb.addActionListener(new ActionListener() {
+       * 
+       * public void actionPerformed(ActionEvent e) {
+       * chb.setState(chb.getState()); if (chb.getState()) { minmax.put(type,
+       * null); } else { minmax.put(type, typeMinMax); } }
+       * 
+       * }); men.add(chb);
+       */
       if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
       {
-        // graduated colourschemes for those where minmax exists for the positional features
-        MenuItem mxcol = new MenuItem("Min Max Colour");
+        // graduated colourschemes for those where minmax exists for the
+        // positional features
+        MenuItem mxcol = new MenuItem("Graduated Colour");
         men.add(mxcol);
         mxcol.addActionListener(new ActionListener()
         {
@@ -218,6 +214,8 @@ public class FeatureSettings extends Panel implements ItemListener,
           public void actionPerformed(ActionEvent e)
           {
             new FeatureColourChooser(me, type);
+            // write back the current colour object to update the table
+            check.updateColor(fr.getFeatureStyle(type));
           }
 
         });
@@ -309,14 +307,14 @@ public class FeatureSettings extends Panel implements ItemListener,
 
     Component[] comps;
     int cSize = featurePanel.getComponentCount();
-    Checkbox check;
+    MyCheckbox check;
     // This will remove any checkboxes which shouldn't be
     // visible
     for (int i = 0; i < cSize; i++)
     {
       comps = featurePanel.getComponents();
-      check = (Checkbox) comps[i];
-      if (!visibleChecks.contains(check.getLabel()))
+      check = (MyCheckbox) comps[i];
+      if (!visibleChecks.contains(check.type))
       {
         featurePanel.remove(i);
         cSize--;
@@ -368,21 +366,21 @@ public class FeatureSettings extends Panel implements ItemListener,
    * update the checklist of feature types with the given type
    * 
    * @param groupsChanged
-   *                true means if the type is not in the display list then it
-   *                will be added and displayed
+   *          true means if the type is not in the display list then it will be
+   *          added and displayed
    * @param type
-   *                feature type to be checked for in the list.
+   *          feature type to be checked for in the list.
    */
   void addCheck(boolean groupsChanged, String type)
   {
     boolean addCheck;
     Component[] comps = featurePanel.getComponents();
-    Checkbox check;
+    MyCheckbox check;
     addCheck = true;
     for (int i = 0; i < featurePanel.getComponentCount(); i++)
     {
-      check = (Checkbox) comps[i];
-      if (check.getLabel().equals(type))
+      check = (MyCheckbox) comps[i];
+      if (check.type.equals(type))
       {
         addCheck = false;
         break;
@@ -400,11 +398,11 @@ public class FeatureSettings extends Panel implements ItemListener,
       check = new MyCheckbox(
               type,
               selected,
-              (fr.featureLinks != null && fr.featureLinks.containsKey(type)));
+              (fr.featureLinks != null && fr.featureLinks.containsKey(type)),
+              fr.getFeatureStyle(type));
 
       check.addMouseListener(this);
       check.addMouseMotionListener(this);
-      check.setBackground(fr.getColour(type));
       check.addItemListener(this);
       if (groupsChanged)
       {
@@ -461,9 +459,9 @@ public class FeatureSettings extends Panel implements ItemListener,
     int tmpSize = 0;
     for (int i = 0; i < cSize; i++)
     {
-      Checkbox check = (Checkbox) comps[i];
-      tmp[tmpSize][0] = check.getLabel();
-      tmp[tmpSize][1] = fr.getColour(check.getLabel());
+      MyCheckbox check = (MyCheckbox) comps[i];
+      tmp[tmpSize][0] = check.type;
+      tmp[tmpSize][1] = fr.getFeatureStyle(check.type);
       tmp[tmpSize][2] = new Boolean(check.getState());
       tmpSize++;
     }
@@ -486,7 +484,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     selectedCheck = (MyCheckbox) evt.getSource();
 
     if (fr.featureLinks != null
-            && fr.featureLinks.containsKey(selectedCheck.getLabel()))
+            && fr.featureLinks.containsKey(selectedCheck.type))
     {
       if (evt.getX() > selectedCheck.stringWidth + 20)
       {
@@ -576,17 +574,17 @@ public class FeatureSettings extends Panel implements ItemListener,
   public void mouseClicked(MouseEvent evt)
   {
     MyCheckbox check = (MyCheckbox) evt.getSource();
-    if ((evt.getModifiers() & InputEvent.BUTTON3_MASK)!=0)
+    if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) != 0)
     {
-      this.popupSort(check.getLabel(), fr.minmax, evt.getX(), evt.getY());
+      this.popupSort(check, fr.minmax, evt.getX(), evt.getY());
     }
     if (fr.featureLinks != null
-            && fr.featureLinks.containsKey(check.getLabel()))
+            && fr.featureLinks.containsKey(check.type))
     {
       if (evt.getX() > check.stringWidth + 20)
       {
         evt.consume();
-        String link = fr.featureLinks.get(check.getLabel()).toString();
+        String link = fr.featureLinks.get(check.type).toString();
         ap.alignFrame.showURL(link.substring(link.indexOf("|") + 1), link
                 .substring(0, link.indexOf("|")));
       }
@@ -599,8 +597,15 @@ public class FeatureSettings extends Panel implements ItemListener,
 
     if (evt.getClickCount() > 1)
     {
-      new UserDefinedColours(this, check.getLabel(), fr.getColour(check
-              .getLabel()));
+      Object fcol = fr.getFeatureStyle(check.type);
+      if (fcol instanceof Color)
+      {
+        new UserDefinedColours(this, check.type, (Color) fcol);
+      } else {
+        new FeatureColourChooser(this, check.type);
+        // write back the current colour object to update the table
+        check.updateColor(fr.getFeatureStyle(check.type));
+      }
     }
   }
 
@@ -617,21 +622,98 @@ public class FeatureSettings extends Panel implements ItemListener,
 
   class MyCheckbox extends Checkbox
   {
+    public String type;
     public int stringWidth;
 
     boolean hasLink;
 
+    GraduatedColor gcol;
+
+    Color col;
+
+    public void updateColor(Object newcol)
+    {
+      if (newcol instanceof Color)
+      {
+        col = (Color) newcol;
+        gcol = null;
+      }
+      else if (newcol instanceof GraduatedColor)
+      {
+        gcol = (GraduatedColor) newcol;
+        col = null;
+      }
+      else
+      {
+        throw new Error("Invalid color for MyCheckBox");
+      }
+      if (col != null)
+      {
+        setBackground(col);
+      }
+      else
+      {
+        String vlabel = type;
+        if (gcol.getThreshType()!=AnnotationColourGradient.NO_THRESHOLD)
+        {
+          vlabel += " "+((gcol.getThreshType()==AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)" : "(<)");
+        }
+        if (gcol.isColourByLabel()) {
+          setBackground(Color.white);
+          vlabel += " (by Label)";
+        } else {
+          setBackground(gcol.getMinColor());
+        }
+        this.setLabel(vlabel);
+      }
+      repaint();
+    }
+
     public MyCheckbox(String label, boolean checked, boolean haslink)
     {
       super(label, checked);
-
+      type = label;
       FontMetrics fm = av.nullFrame.getFontMetrics(av.nullFrame.getFont());
       stringWidth = fm.stringWidth(label);
       this.hasLink = haslink;
     }
 
+    public MyCheckbox(String type, boolean selected, boolean b,
+            Object featureStyle)
+    {
+      this(type,selected,b);
+      updateColor(featureStyle);
+    }
+
     public void paint(Graphics g)
     {
+      int width = getWidth(), height = getHeight();
+      if (gcol != null)
+      {
+        if (gcol.isColourByLabel())
+        {
+          g.setColor(Color.white);
+          g.fillRect(width/2, 0,width/2, height);
+          /*g.setColor(Color.black); 
+          Font f=g.getFont().deriveFont(9);
+          g.setFont(f);
+
+          // g.setFont(g.getFont().deriveFont(
+          // AffineTransform.getScaleInstance(
+          // width/g.getFontMetrics().stringWidth("Label"),
+          // height/g.getFontMetrics().getHeight())));
+          g.drawString("Label", width/2, 0); */
+
+        }
+        else
+        {
+          Color maxCol = gcol.getMaxColor();
+          g.setColor(maxCol);
+          g.fillRect(width/2, 0,width/2, height);
+          
+        }
+      }
+
       if (hasLink)
       {
         g.drawImage(linkImage, stringWidth + 25,
@@ -639,10 +721,12 @@ public class FeatureSettings extends Panel implements ItemListener,
       }
     }
   }
+
   protected void sortByDens(String[] typ)
   {
     sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
   }
+
   private String[] getDisplayedFeatureTypes()
   {
     String[] typ = null;
@@ -664,7 +748,6 @@ public class FeatureSettings extends Panel implements ItemListener,
     return typ;
   }
 
-
   protected void sortBy(String[] typ, String methodText, final String method)
   {
     if (typ == null)
@@ -705,8 +788,8 @@ public class FeatureSettings extends Panel implements ItemListener,
     }
     SequenceI[] oldOrder = al.getSequencesArray();
     AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
-    this.ap.alignFrame.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av
-            .getAlignment()));
+    this.ap.alignFrame.addHistoryItem(new OrderCommand(methodText,
+            oldOrder, alignPanel.av.getAlignment()));
     alignPanel.paintAlignment(true);
 
   }
index 825cfd3..5da1fbf 100755 (executable)
@@ -100,13 +100,16 @@ public class UserDefinedColours extends Panel implements ActionListener,
     setTargetColour(fr.colourPanel.getBackground());
     dialog.setVisible(true);
   }
-
   public UserDefinedColours(Component caller, Color col1, Frame alignframe)
   {
+    this(caller, col1, alignframe, "Select Colour");
+  }
+  public UserDefinedColours(Component caller, Color col1, Container alignframe, String title)
+  {
     this.caller = caller;
     originalColour = col1;
-    originalLabel = "Select Colour";
-    setForDialog("Select Colour", alignframe);
+    originalLabel = title;
+    setForDialog(title, alignframe);
     setTargetColour(col1);
     dialog.setVisible(true);
   }
@@ -126,12 +129,21 @@ public class UserDefinedColours extends Panel implements ActionListener,
     frame.setSize(420, 200);
   }
 
-  void setForDialog(String title, Frame alignframe)
+  void setForDialog(String title, Container alignframe)
   {
     init();
     frame.setVisible(false);
     remove(buttonPanel);
-    dialog = new Dialog(alignframe, title, true);
+    if (alignframe instanceof Frame)
+    {
+      dialog = new Dialog((Frame)alignframe, title, true);
+    }
+    else 
+    if (alignframe instanceof JVDialog){
+      dialog = new Dialog(((JVDialog)alignframe), title, true);
+    } else {
+      throw new Error("Unsupported owner for User Colour scheme dialog.");
+    }
 
     dialog.add(this);
     this.setSize(400, 123);
@@ -320,14 +332,15 @@ public class UserDefinedColours extends Panel implements ActionListener,
   {
     final Button button = new Button();
     Color col = Color.white;
-
+    if (oldColourScheme!=null)
+    {
     try
     {
       col = oldColourScheme.findColour(aa.charAt(0), -1);
     } catch (Exception ex)
     {
     }
-
+    }
     button.setBackground(col);
     oldColours.addElement(col);
     button.setLabel(label);
@@ -381,7 +394,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
       }
       else if (caller instanceof FeatureRenderer)
       {
-        ((FeatureRenderer) caller).colourPanel.setBackground(getColor());
+        ((FeatureRenderer) caller).colourPanel.updateColor(getColor());
       }
       else if (caller instanceof FeatureColourChooser)
       {
@@ -456,11 +469,19 @@ public class UserDefinedColours extends Panel implements ActionListener,
       }
       else if (caller instanceof FeatureRenderer)
       {
-        ((FeatureRenderer) caller).colourPanel
-                .setBackground(originalColour);
+        ((FeatureRenderer) caller).colourPanel.updateColor(originalColour);
 
       }
 
+      else if (caller instanceof FeatureColourChooser)
+      {
+        if (originalLabel.indexOf("inimum")>-1)
+        {
+          ((FeatureColourChooser) caller).minColour_actionPerformed(originalColour);
+        } else {
+          ((FeatureColourChooser) caller).maxColour_actionPerformed(originalColour);
+        }
+      }
       if (dialog != null)
         dialog.setVisible(false);