JAL-2015 JAL-1956 rollout of FeatureColourI in place of JAL-1956_featureStyles
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 24 Feb 2016 16:51:31 +0000 (16:51 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 24 Feb 2016 16:51:31 +0000 (16:51 +0000)
Color/GraduatedColour

24 files changed:
src/jalview/api/FeatureColourI.java
src/jalview/api/FeatureRenderer.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/FeatureColourChooser.java
src/jalview/appletgui/FeatureRenderer.java
src/jalview/appletgui/FeatureSettings.java
src/jalview/appletgui/UserDefinedColours.java
src/jalview/gui/AnnotationExporter.java
src/jalview/gui/FeatureColourChooser.java
src/jalview/gui/FeatureRenderer.java
src/jalview/gui/FeatureSettings.java
src/jalview/gui/Jalview2XML.java
src/jalview/io/FeaturesFile.java
src/jalview/io/SequenceAnnotationReport.java
src/jalview/renderer/seqfeatures/FeatureRenderer.java
src/jalview/schemes/FeatureColour.java [new file with mode: 0644]
src/jalview/schemes/FeatureColourAdapter.java [deleted file]
src/jalview/schemes/FeatureColourScheme.java
src/jalview/schemes/UserColourScheme.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java
src/jalview/ws/jws2/AADisorderClient.java
test/jalview/io/FeaturesFileTest.java
test/jalview/schemes/FeatureColourTest.java [new file with mode: 0644]

index d8363f4..0a333ca 100644 (file)
@@ -1,18 +1,21 @@
 package jalview.api;
 
+import jalview.datamodel.SequenceFeature;
+
 import java.awt.Color;
 
 public interface FeatureColourI
 {
 
   /**
-   * Answers true when either isColourByLabel, isAboveThreshold or
-   * isBelowThreshold answers true
+   * Answers true when the feature colour varies across the score range
    * 
    * @return
    */
   boolean isGraduatedColour();
 
+  void setGraduatedColour(boolean b);
+
   /**
    * Returns the feature colour (when isGraduatedColour answers false)
    * 
@@ -35,13 +38,22 @@ public interface FeatureColourI
   Color getMaxColour();
 
   /**
-   * Answers true if the feature is coloured by label (description); only
-   * applicable when isGraduatedColour answers true
+   * Answers true if the feature has a single colour, i.e. if isColourByLabel()
+   * and isGraduatedColour() both answer false
+   * 
+   * @return
+   */
+  boolean isSimpleColour();
+
+  /**
+   * Answers true if the feature is coloured by label (description)
    * 
    * @return
    */
   boolean isColourByLabel();
 
+  void setColourByLabel(boolean b);
+
   /**
    * Answers true if the feature is coloured below a threshold value; only
    * applicable when isGraduatedColour answers true
@@ -50,6 +62,8 @@ public interface FeatureColourI
    */
   boolean isBelowThreshold();
 
+  void setBelowThreshold(boolean b);
+
   /**
    * Answers true if the feature is coloured above a threshold value; only
    * applicable when isGraduatedColour answers true
@@ -58,14 +72,20 @@ public interface FeatureColourI
    */
   boolean isAboveThreshold();
 
+  void setAboveThreshold(boolean b);
+
   /**
-   * Answers true if the threshold is the min (or max) of the colour range; only
-   * applicable when isGraduatedColour answers true
+   * Answers true if the threshold is the minimum value (when
+   * isAboveThreshold()) or maximum value (when isBelowThreshold()) of the
+   * colour range; only applicable when isGraduatedColour and either
+   * isAboveThreshold() or isBelowThreshold() answers true
    * 
    * @return
    */
   boolean isThresholdMinMax();
 
+  void setThresholdMinMax(boolean b);
+
   /**
    * Returns the threshold value (if any), else zero
    * 
@@ -73,10 +93,57 @@ public interface FeatureColourI
    */
   float getThreshold();
 
+  void setThreshold(float f);
+
+  boolean isAutoScaled();
+
+  void setAutoScaled(boolean b);
+
+  /**
+   * Returns the maximum score of the graduated colour range
+   * 
+   * @return
+   */
+  float getMax();
+
+  /**
+   * Returns the minimum score of the graduated colour range
+   * 
+   * @return
+   */
+  float getMin();
+
+  /**
+   * Answers true if either isAboveThreshold or isBelowThreshold answers true
+   * 
+   * @return
+   */
+  boolean hasThreshold();
+
+  /**
+   * Returns the computed colour for the given sequence feature
+   * 
+   * @param feature
+   * @return
+   */
+  Color getColor(SequenceFeature feature);
+
   /**
-   * Answers true if ?
+   * Answers true if the feature has a simple colour, or is coloured by label,
+   * or has a graduated colour and the score of this feature instance is within
+   * the range to render (if any), i.e. does not lie below or above any
+   * threshold set.
    * 
+   * @param feature
    * @return
    */
-  boolean isLowToHigh();
+  boolean isColored(SequenceFeature feature);
+
+  /**
+   * Update the min-max range for a graduated colour scheme
+   * 
+   * @param min
+   * @param max
+   */
+  void updateBounds(float min, float max);
 }
index 0d0adaa..21319fd 100644 (file)
@@ -60,17 +60,15 @@ public interface FeatureRenderer
    * @param ft
    * @return display style for a feature
    */
-  Object getFeatureStyle(String ft);
+  FeatureColourI getFeatureStyle(String ft);
 
   /**
    * update the feature style for a particular feature
    * 
    * @param ft
    * @param ggc
-   *          - currently allows java.awt.Color and
-   *          jalview.schemes.GraduatedColor
    */
-  void setColour(String ft, Object ggc);
+  void setColour(String ft, FeatureColourI ggc);
 
   AlignViewportI getViewport();
 
@@ -85,7 +83,7 @@ public interface FeatureRenderer
    * 
    * @return
    */
-  Map<String, Object> getFeatureColours();
+  Map<String, FeatureColourI> getFeatureColours();
 
   /**
    * query the alignment view to find all features
@@ -100,7 +98,7 @@ public interface FeatureRenderer
    * 
    * @return
    */
-  Map<String, Object> getDisplayedFeatureCols();
+  Map<String, FeatureColourI> getDisplayedFeatureCols();
 
   /**
    * get all registered groups
index b7e7899..40fbd6d 100644 (file)
@@ -25,6 +25,7 @@ import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
 import jalview.api.AlignViewControllerGuiI;
 import jalview.api.AlignViewControllerI;
 import jalview.api.AlignViewportI;
+import jalview.api.FeatureColourI;
 import jalview.api.FeatureRenderer;
 import jalview.api.FeatureSettingsControllerI;
 import jalview.api.SequenceStructureBinding;
@@ -1406,7 +1407,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     return annotation;
   }
 
-  private Map<String, Object> getDisplayedFeatureCols()
+  private Map<String, FeatureColourI> getDisplayedFeatureCols()
   {
     if (alignPanel.getFeatureRenderer() != null
             && viewport.getFeaturesDisplayed() != null)
index 46a67c4..3c04ccd 100644 (file)
  */
 package jalview.appletgui;
 
+import jalview.api.FeatureColourI;
 import jalview.datamodel.GraphLine;
 import jalview.schemes.AnnotationColourGradient;
-import jalview.schemes.GraduatedColor;
+import jalview.schemes.FeatureColour;
 import jalview.util.MessageManager;
 
 import java.awt.Checkbox;
@@ -60,9 +61,9 @@ public class FeatureColourChooser extends Panel implements ActionListener,
 
   // AlignmentPanel ap;
 
-  GraduatedColor cs;
+  FeatureColourI cs;
 
-  Object oldcs;
+  FeatureColourI oldcs;
 
   Hashtable oldgroupColours;
 
@@ -91,29 +92,29 @@ public class FeatureColourChooser extends Panel implements ActionListener,
   {
     this.type = type;
     fr = frenderer;
-    float mm[] = ((float[][]) fr.getMinMax().get(type))[0];
+    float mm[] = fr.getMinMax().get(type)[0];
     min = mm[0];
     max = mm[1];
     oldcs = fr.getFeatureColours().get(type);
-    if (oldcs instanceof GraduatedColor)
+    if (oldcs.isGraduatedColour())
     {
-      cs = new GraduatedColor((GraduatedColor) oldcs, min, max);
+      cs = new FeatureColour((FeatureColour) oldcs, min, max);
     }
     else
     {
       // promote original color to a graduated color
       Color bl = Color.black;
-      if (oldcs instanceof Color)
+      if (oldcs.isSimpleColour())
       {
-        bl = (Color) oldcs;
+        bl = oldcs.getColour();
       }
       // original colour becomes the maximum colour
-      cs = new GraduatedColor(Color.white, bl, mm[0], mm[1]);
+      cs = new FeatureColour(Color.white, bl, mm[0], mm[1]);
     }
-    minColour.setBackground(cs.getMinColor());
-    maxColour.setBackground(cs.getMaxColor());
-    minColour.setForeground(cs.getMinColor());
-    maxColour.setForeground(cs.getMaxColor());
+    minColour.setBackground(cs.getMinColour());
+    maxColour.setBackground(cs.getMaxColour());
+    minColour.setForeground(cs.getMinColour());
+    maxColour.setForeground(cs.getMaxColour());
     colourFromLabel.setState(cs.isColourByLabel());
     adjusting = true;
 
@@ -123,10 +124,8 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     } catch (Exception ex)
     {
     }
-    threshold
-            .select(cs.getThreshType() == AnnotationColourGradient.NO_THRESHOLD ? 0
-                    : cs.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD ? 1
-                            : 2);
+    threshold.select(cs.isAboveThreshold() ? 1 : (cs.isBelowThreshold() ? 2
+            : 0));
 
     adjusting = false;
     changeColour();
@@ -259,6 +258,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
 
   private GraphLine threshline;
 
+  @Override
   public void actionPerformed(ActionEvent evt)
   {
     if (evt.getSource() == thresholdValue)
@@ -286,6 +286,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     }
   }
 
+  @Override
   public void itemStateChanged(ItemEvent evt)
   {
     maxColour.setEnabled(!colourFromLabel.getState());
@@ -293,19 +294,20 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     changeColour();
   }
 
+  @Override
   public void adjustmentValueChanged(AdjustmentEvent evt)
   {
     if (!adjusting)
     {
-      thresholdValue.setText(((float) slider.getValue() / 1000f) + "");
+      thresholdValue.setText((slider.getValue() / 1000f) + "");
       valueChanged();
     }
   }
 
   protected void valueChanged()
   {
-    threshline.value = (float) slider.getValue() / 1000f;
-    cs.setThresh(threshline.value);
+    threshline.value = slider.getValue() / 1000f;
+    cs.setThreshold(threshline.value);
     changeColour();
     PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId());
     // ap.paintAlignment(false);
@@ -369,7 +371,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
 
     slider.setEnabled(true);
     thresholdValue.setEnabled(true);
-    GraduatedColor acg = new GraduatedColor(minColour.getBackground(),
+    FeatureColour acg = new FeatureColour(minColour.getBackground(),
             maxColour.getBackground(), min, max);
 
     acg.setColourByLabel(colourFromLabel.getState());
@@ -393,7 +395,7 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
     {
       adjusting = true;
-      acg.setThresh(threshline.value);
+      acg.setThreshold(threshline.value);
 
       float range = max * 1000f - min * 1000f;
 
@@ -406,17 +408,17 @@ public class FeatureColourChooser extends Panel implements ActionListener,
       adjusting = false;
     }
 
-    acg.setThreshType(aboveThreshold);
+    acg.setAboveThreshold(true);
     if (thresholdIsMin.getState()
             && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
     {
       if (aboveThreshold == AnnotationColourGradient.ABOVE_THRESHOLD)
       {
-        acg = new GraduatedColor(acg, threshline.value, max);
+        acg = new FeatureColour(acg, threshline.value, max);
       }
       else
       {
-        acg = new GraduatedColor(acg, min, threshline.value);
+        acg = new FeatureColour(acg, min, threshline.value);
       }
     }
 
@@ -434,14 +436,17 @@ public class FeatureColourChooser extends Panel implements ActionListener,
 
   }
 
+  @Override
   public void mouseClicked(MouseEvent evt)
   {
   }
 
+  @Override
   public void mousePressed(MouseEvent evt)
   {
   }
 
+  @Override
   public void mouseReleased(MouseEvent evt)
   {
     if (evt.getSource() == minColour || evt.getSource() == maxColour)
@@ -456,10 +461,12 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     // ap.paintAlignment(true);
   }
 
+  @Override
   public void mouseEntered(MouseEvent evt)
   {
   }
 
+  @Override
   public void mouseExited(MouseEvent evt)
   {
   }
index 4655ba5..b90b8d3 100644 (file)
  */
 package jalview.appletgui;
 
+import jalview.api.FeatureColourI;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
-import jalview.schemes.AnnotationColourGradient;
-import jalview.schemes.GraduatedColor;
+import jalview.io.FeaturesFile;
+import jalview.schemes.FeatureColour;
+import jalview.schemes.UserColourScheme;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 
@@ -43,6 +45,8 @@ import java.awt.TextArea;
 import java.awt.TextField;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 import java.util.Hashtable;
 
 /**
@@ -63,7 +67,6 @@ public class FeatureRenderer extends
    * Creates a new FeatureRenderer object.
    * 
    * @param av
-   *          DOCUMENT ME!
    */
   public FeatureRenderer(AlignmentViewport av)
   {
@@ -97,51 +100,35 @@ public class FeatureRenderer extends
     /**
      * render a feature style in the amend feature dialog box
      */
-    public void updateColor(Object newcol)
+    public void updateColor(FeatureColourI newcol)
     {
-
-      Color bg, col = null;
-      GraduatedColor gcol = null;
+      Color bg = null;
       String vlabel = "";
-      if (newcol instanceof Color)
-      {
-        isGcol = false;
-        col = (Color) newcol;
-        gcol = null;
-      }
-      else if (newcol instanceof GraduatedColor)
+      if (newcol.isSimpleColour())
       {
-        isGcol = true;
-        gcol = (GraduatedColor) newcol;
-        col = null;
+        bg = newcol.getColour();
+        setBackground(bg);
       }
       else
       {
-        throw new Error(
-                MessageManager
-                        .getString("error.invalid_colour_for_mycheckbox"));
-      }
-      if (col != null)
-      {
-        setBackground(bg = col);
-      }
-      else
-      {
-        if (gcol.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
+        if (newcol.isAboveThreshold())
+        {
+          vlabel += " (>)";
+        }
+        else if (newcol.isBelowThreshold())
         {
-          vlabel += " "
-                  + ((gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)"
-                          : "(<)");
+          vlabel += " (<)";
         }
-        if (isColourByLabel = gcol.isColourByLabel())
+
+        if (isColourByLabel = newcol.isColourByLabel())
         {
           setBackground(bg = Color.white);
           vlabel += " (by Label)";
         }
         else
         {
-          setBackground(bg = gcol.getMinColor());
-          maxCol = gcol.getMaxColor();
+          setBackground(bg = newcol.getMinColour());
+          maxCol = newcol.getMaxColour();
         }
       }
       label = vlabel;
@@ -154,6 +141,7 @@ public class FeatureRenderer extends
       super(null);
     }
 
+    @Override
     public void paint(Graphics g)
     {
       Dimension d = getSize();
@@ -227,6 +215,7 @@ public class FeatureRenderer extends
 
       overlaps.addItemListener(new java.awt.event.ItemListener()
       {
+        @Override
         public void itemStateChanged(java.awt.event.ItemEvent e)
         {
           int index = overlaps.getSelectedIndex();
@@ -246,11 +235,12 @@ public class FeatureRenderer extends
             ap.seqPanel.seqCanvas.highlightSearchResults(highlight);
 
           }
-          Object col = getFeatureStyle(name.getText());
+          FeatureColourI col = getFeatureStyle(name.getText());
           if (col == null)
           {
-            col = new jalview.schemes.UserColourScheme()
+            Color generatedColour = UserColourScheme
                     .createColourFromName(name.getText());
+            col = new FeatureColour(generatedColour);
           }
 
           colourPanel.updateColor(col);
@@ -344,6 +334,7 @@ public class FeatureRenderer extends
       dialog.buttonPanel.add(deleteButton, 1);
       deleteButton.addActionListener(new ActionListener()
       {
+        @Override
         public void actionPerformed(ActionEvent evt)
         {
           deleteFeature = true;
@@ -357,20 +348,16 @@ public class FeatureRenderer extends
     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());
-    }
-    Object fcol = getFeatureStyle(name.getText());
+    // lookup (or generate) the feature colour
+    FeatureColourI fcol = getFeatureStyle(name.getText());
     // simply display the feature color in a box
     colourPanel.updateColor(fcol);
     dialog.setResizable(true);
     // TODO: render the graduated color in the box.
-    colourPanel.addMouseListener(new java.awt.event.MouseAdapter()
+    colourPanel.addMouseListener(new MouseAdapter()
     {
-      public void mousePressed(java.awt.event.MouseEvent evt)
+      @Override
+      public void mousePressed(MouseEvent evt)
       {
         if (!colourPanel.isGcol)
         {
@@ -378,15 +365,14 @@ public class FeatureRenderer extends
         }
         else
         {
-          FeatureColourChooser fcc = new FeatureColourChooser(
-                  ap.alignFrame, name.getText());
+          new FeatureColourChooser(ap.alignFrame, name.getText());
           dialog.transferFocus();
         }
       }
     });
     dialog.setVisible(true);
 
-    jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
+    FeaturesFile ffile = new FeaturesFile();
 
     if (dialog.accept)
     {
@@ -415,7 +401,7 @@ public class FeatureRenderer extends
         if (!colourPanel.isGcol)
         {
           // update colour - otherwise its already done.
-          setColour(sf.type, colourPanel.getBackground());
+          setColour(sf.type, new FeatureColour(colourPanel.getBackground()));
         }
         try
         {
@@ -455,7 +441,7 @@ public class FeatureRenderer extends
         {
           setGroupVisibility(lastFeatureGroupAdded, true);
         }
-        setColour(lastFeatureAdded, newColour); // was fcol
+        setColour(lastFeatureAdded, new FeatureColour(newColour)); // was fcol
         setVisible(lastFeatureAdded);
         findAllFeatures(false); // different to original applet behaviour ?
         // findAllFeatures();
index 1c156dc..203605b 100755 (executable)
  */
 package jalview.appletgui;
 
+import jalview.api.FeatureColourI;
 import jalview.api.FeatureSettingsControllerI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceFeature;
-import jalview.schemes.AnnotationColourGradient;
-import jalview.schemes.GraduatedColor;
 import jalview.util.MessageManager;
 
 import java.awt.BorderLayout;
@@ -58,8 +57,8 @@ import java.awt.event.MouseMotionListener;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.util.Enumeration;
-import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
 import java.util.Vector;
 
 public class FeatureSettings extends Panel implements ItemListener,
@@ -165,6 +164,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     final FeatureSettings me = this;
     frame.addWindowListener(new WindowAdapter()
     {
+      @Override
       public void windowClosing(WindowEvent e)
       {
         if (me.av.featureSettings == me)
@@ -185,6 +185,7 @@ public class FeatureSettings extends Panel implements ItemListener,
             width, height);
   }
 
+  @Override
   public void paint(Graphics g)
   {
     g.setColor(Color.black);
@@ -198,20 +199,22 @@ public class FeatureSettings extends Panel implements ItemListener,
             60);
   }
 
-  protected void popupSort(final MyCheckbox check, final Hashtable minmax,
+  protected void popupSort(final MyCheckbox check,
+          final Map<String, float[][]> minmax,
           int x, int y)
   {
     final String type = check.type;
-    final Object typeCol = fr.getFeatureStyle(type);
-    java.awt.PopupMenu men = new PopupMenu(MessageManager.formatMessage(
+    final FeatureColourI typeCol = fr.getFeatureStyle(type);
+    PopupMenu men = new PopupMenu(MessageManager.formatMessage(
             "label.settings_for_type", new String[] { type }));
-    java.awt.MenuItem scr = new MenuItem(
+    MenuItem scr = new MenuItem(
             MessageManager.getString("label.sort_by_score"));
     men.add(scr);
     final FeatureSettings me = this;
     scr.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         me.ap.alignFrame.avc
@@ -224,6 +227,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     dens.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         me.ap.alignFrame.avc
@@ -234,7 +238,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     men.add(dens);
     if (minmax != null)
     {
-      final Object typeMinMax = minmax.get(type);
+      final float[][] typeMinMax = minmax.get(type);
       /*
        * final java.awt.CheckboxMenuItem chb = new
        * java.awt.CheckboxMenuItem("Vary Height"); // this is broken at the
@@ -247,20 +251,21 @@ public class FeatureSettings extends Panel implements ItemListener,
        * 
        * }); men.add(chb);
        */
-      if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
+      if (typeMinMax != null && typeMinMax[0] != null)
       {
         // graduated colourschemes for those where minmax exists for the
         // positional features
         MenuItem mxcol = new MenuItem(
-                (typeCol instanceof Color) ? "Graduated Colour"
+                (typeCol.isSimpleColour()) ? "Graduated Colour"
                         : "Single Colour");
         men.add(mxcol);
         mxcol.addActionListener(new ActionListener()
         {
 
+          @Override
           public void actionPerformed(ActionEvent e)
           {
-            if (typeCol instanceof Color)
+            if (typeCol.isSimpleColour())
             {
               new FeatureColourChooser(me, type);
               // write back the current colour object to update the table
@@ -268,8 +273,7 @@ public class FeatureSettings extends Panel implements ItemListener,
             }
             else
             {
-              new UserDefinedColours(me, check.type,
-                      ((GraduatedColor) typeCol));
+              new UserDefinedColours(me, check.type, typeCol);
             }
           }
 
@@ -334,7 +338,7 @@ public class FeatureSettings extends Panel implements ItemListener,
   {
     SequenceFeature[] tmpfeatures;
     String group = null, type;
-    Vector visibleChecks = new Vector();
+    Vector<String> visibleChecks = new Vector<String>();
     AlignmentI alignment = av.getAlignment();
     for (int i = 0; i < alignment.getHeight(); i++)
     {
@@ -400,7 +404,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
     // now add checkboxes which should be visible,
     // if they have not already been added
-    Enumeration en = visibleChecks.elements();
+    Enumeration<String> en = visibleChecks.elements();
 
     while (en.hasMoreElements())
     {
@@ -474,6 +478,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     }
   }
 
+  @Override
   public void actionPerformed(ActionEvent evt)
   {
     for (int i = 0; i < featurePanel.getComponentCount(); i++)
@@ -486,6 +491,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
   private ItemListener groupItemListener = new ItemListener()
   {
+    @Override
     public void itemStateChanged(ItemEvent evt)
     {
       Checkbox source = (Checkbox) evt.getSource();
@@ -500,6 +506,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     };
   };
 
+  @Override
   public void itemStateChanged(ItemEvent evt)
   {
     selectionChanged();
@@ -533,6 +540,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
   boolean dragging = false;
 
+  @Override
   public void mousePressed(MouseEvent evt)
   {
 
@@ -549,6 +557,7 @@ public class FeatureSettings extends Panel implements ItemListener,
 
   }
 
+  @Override
   public void mouseDragged(MouseEvent evt)
   {
     if (((Component) evt.getSource()).getParent() != featurePanel)
@@ -558,6 +567,7 @@ public class FeatureSettings extends Panel implements ItemListener,
     dragging = true;
   }
 
+  @Override
   public void mouseReleased(MouseEvent evt)
   {
     if (((Component) evt.getSource()).getParent() != featurePanel)
@@ -610,19 +620,9 @@ public class FeatureSettings extends Panel implements ItemListener,
     }
   }
 
-  public void setUserColour(String feature, Object originalColour)
+  public void setUserColour(String feature, FeatureColourI originalColour)
   {
-    if (originalColour instanceof Color
-            || originalColour instanceof GraduatedColor)
-    {
-      fr.setColour(feature, originalColour);
-    }
-    else
-    {
-      throw new Error(
-              MessageManager
-                      .getString("error.implementation_error_unsupported_feature_colour_object"));
-    }
+    fr.setColour(feature, originalColour);
     refreshTable();
   }
 
@@ -633,14 +633,17 @@ public class FeatureSettings extends Panel implements ItemListener,
     ap.paintAlignment(true);
   }
 
+  @Override
   public void mouseEntered(MouseEvent evt)
   {
   }
 
+  @Override
   public void mouseExited(MouseEvent evt)
   {
   }
 
+  @Override
   public void mouseClicked(MouseEvent evt)
   {
     MyCheckbox check = (MyCheckbox) evt.getSource();
@@ -666,10 +669,10 @@ public class FeatureSettings extends Panel implements ItemListener,
 
     if (evt.getClickCount() > 1)
     {
-      Object fcol = fr.getFeatureStyle(check.type);
-      if (fcol instanceof Color)
+      FeatureColourI fcol = fr.getFeatureStyle(check.type);
+      if (fcol.isSimpleColour())
       {
-        new UserDefinedColours(this, check.type, (Color) fcol);
+        new UserDefinedColours(this, check.type, fcol.getColour());
       }
       else
       {
@@ -680,10 +683,12 @@ public class FeatureSettings extends Panel implements ItemListener,
     }
   }
 
+  @Override
   public void mouseMoved(MouseEvent evt)
   {
   }
 
+  @Override
   public void adjustmentValueChanged(AdjustmentEvent evt)
   {
     fr.setTransparency((100 - transparency.getValue()) / 100f);
@@ -699,49 +704,34 @@ public class FeatureSettings extends Panel implements ItemListener,
 
     boolean hasLink;
 
-    GraduatedColor gcol;
-
-    Color col;
+    FeatureColourI col;
 
-    public void updateColor(Object newcol)
+    public void updateColor(FeatureColourI newcol)
     {
-      if (newcol instanceof Color)
+      col = newcol;
+      if (col.isSimpleColour())
       {
-        col = (Color) newcol;
-        gcol = null;
-      }
-      else if (newcol instanceof GraduatedColor)
-      {
-        gcol = (GraduatedColor) newcol;
-        col = null;
-      }
-      else
-      {
-        throw new Error(
-                MessageManager
-                        .getString("error.invalid_colour_for_mycheckbox"));
-      }
-      if (col != null)
-      {
-        setBackground(col);
+        setBackground(col.getColour());
       }
       else
       {
         String vlabel = type;
-        if (gcol.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
+        if (col.isAboveThreshold())
+        {
+          vlabel += " (>)";
+        }
+        else if (col.isBelowThreshold())
         {
-          vlabel += " "
-                  + ((gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD) ? "(>)"
-                          : "(<)");
+          vlabel += " (<)";
         }
-        if (gcol.isColourByLabel())
+        if (col.isColourByLabel())
         {
           setBackground(Color.white);
           vlabel += " (by Label)";
         }
         else
         {
-          setBackground(gcol.getMinColor());
+          setBackground(col.getMinColour());
         }
         this.setLabel(vlabel);
       }
@@ -758,40 +748,38 @@ public class FeatureSettings extends Panel implements ItemListener,
     }
 
     public MyCheckbox(String type, boolean selected, boolean b,
-            Object featureStyle)
+            FeatureColourI featureStyle)
     {
       this(type, selected, b);
       updateColor(featureStyle);
     }
 
+    @Override
     public void paint(Graphics g)
     {
       Dimension d = getSize();
-      if (gcol != null)
+      if (col.isColourByLabel())
       {
-        if (gcol.isColourByLabel())
-        {
-          g.setColor(Color.white);
-          g.fillRect(d.width / 2, 0, d.width / 2, d.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);
-           */
+        g.setColor(Color.white);
+        g.fillRect(d.width / 2, 0, d.width / 2, d.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(d.width / 2, 0, d.width / 2, d.height);
+      }
+      else if (col.isGraduatedColour())
+      {
+        Color maxCol = col.getMaxColour();
+        g.setColor(maxCol);
+        g.fillRect(d.width / 2, 0, d.width / 2, d.height);
 
-        }
       }
 
       if (hasLink)
index 57cf669..88098a9 100644 (file)
  */
 package jalview.appletgui;
 
+import jalview.api.FeatureColourI;
 import jalview.datamodel.SequenceGroup;
 import jalview.schemes.ColourSchemeI;
-import jalview.schemes.GraduatedColor;
+import jalview.schemes.FeatureColour;
 import jalview.schemes.ResidueProperties;
 import jalview.schemes.UserColourScheme;
 import jalview.util.MessageManager;
@@ -59,7 +60,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
 
   Button selectedButton;
 
-  Vector oldColours = new Vector();
+  Vector<Color> oldColours = new Vector<Color>();
 
   ColourSchemeI oldColourScheme;
 
@@ -75,7 +76,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
 
   String originalLabel;
 
-  Object originalColour;
+  FeatureColourI originalColour;
 
   int R = 0, G = 0, B = 0;
 
@@ -117,7 +118,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
   public UserDefinedColours(FeatureRenderer fr, Frame alignframe)
   {
     caller = fr;
-    originalColour = fr.colourPanel.getBackground();
+    originalColour = new FeatureColour(fr.colourPanel.getBackground());
     originalLabel = "Feature Colour";
     setForDialog("Select Feature Colour", alignframe);
     setTargetColour(fr.colourPanel.getBackground());
@@ -134,21 +135,21 @@ public class UserDefinedColours extends Panel implements ActionListener,
    * 
    * @param caller
    *          - handles events
-   * @param col1
+   * @param col
    *          - original colour
    * @param alignframe
    *          - the parent Frame for the dialog
    * @param title
    *          - window title
    */
-  public UserDefinedColours(Component caller, Color col1, Frame alignframe,
+  public UserDefinedColours(Component caller, Color col, Frame alignframe,
           String title)
   {
     this.caller = caller;
-    originalColour = col1;
+    originalColour = new FeatureColour(col);
     originalLabel = title;
     setForDialog(title, alignframe);
-    setTargetColour(col1);
+    setTargetColour(col);
     dialog.setVisible(true);
   }
 
@@ -161,7 +162,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
    */
   public UserDefinedColours(Object caller, String label, Color colour)
   {
-    this(caller, label, colour, colour);
+    this(caller, label, new FeatureColour(colour), colour);
   }
 
   /**
@@ -172,13 +173,13 @@ public class UserDefinedColours extends Panel implements ActionListener,
    * @param graduatedColor
    */
   public UserDefinedColours(FeatureSettings me, String type,
-          GraduatedColor graduatedColor)
+          FeatureColourI graduatedColor)
   {
-    this(me, type, graduatedColor, graduatedColor.getMaxColor());
+    this(me, type, graduatedColor, graduatedColor.getMaxColour());
   }
 
-  private UserDefinedColours(Object caller, String label, Object ocolour,
-          Color colour)
+  private UserDefinedColours(Object caller, String label,
+          FeatureColourI ocolour, Color colour)
   {
     this.caller = caller;
     originalColour = ocolour;
@@ -228,6 +229,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
 
   }
 
+  @Override
   public void actionPerformed(ActionEvent evt)
   {
     final Object source = evt.getSource();
@@ -257,6 +259,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
     }
   }
 
+  @Override
   public void adjustmentValueChanged(AdjustmentEvent evt)
   {
     if (evt.getSource() == rScroller)
@@ -420,6 +423,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
     button.setFont(new java.awt.Font("Verdana", 1, 10));
     button.addMouseListener(new java.awt.event.MouseAdapter()
     {
+      @Override
       public void mousePressed(MouseEvent e)
       {
         colourButtonPressed(e);
@@ -451,7 +455,8 @@ public class UserDefinedColours extends Panel implements ActionListener,
     {
       if (caller instanceof FeatureSettings)
       {
-        ((FeatureSettings) caller).setUserColour(originalLabel, getColor());
+        ((FeatureSettings) caller).setUserColour(originalLabel,
+                new FeatureColour(getColor()));
       }
       else if (caller instanceof AnnotationColourChooser)
       {
@@ -468,7 +473,8 @@ public class UserDefinedColours extends Panel implements ActionListener,
       }
       else if (caller instanceof FeatureRenderer)
       {
-        ((FeatureRenderer) caller).colourPanel.updateColor(getColor());
+        ((FeatureRenderer) caller).colourPanel
+                .updateColor(new FeatureColour(getColor()));
       }
       else if (caller instanceof FeatureColourChooser)
       {
@@ -537,12 +543,12 @@ public class UserDefinedColours extends Panel implements ActionListener,
         if (originalLabel.equals("Min Colour"))
         {
           ((AnnotationColourChooser) caller)
-                  .minColour_actionPerformed((Color) originalColour);
+                  .minColour_actionPerformed(originalColour.getColour());
         }
         else
         {
           ((AnnotationColourChooser) caller)
-                  .maxColour_actionPerformed((Color) originalColour);
+                  .maxColour_actionPerformed(originalColour.getColour());
         }
       }
       else if (caller instanceof FeatureRenderer)
@@ -556,12 +562,12 @@ public class UserDefinedColours extends Panel implements ActionListener,
         if (originalLabel.indexOf("inimum") > -1)
         {
           ((FeatureColourChooser) caller)
-                  .minColour_actionPerformed((Color) originalColour);
+                  .minColour_actionPerformed(originalColour.getColour());
         }
         else
         {
           ((FeatureColourChooser) caller)
-                  .maxColour_actionPerformed((Color) originalColour);
+                  .maxColour_actionPerformed(originalColour.getColour());
         }
       }
       if (dialog != null)
@@ -576,7 +582,7 @@ public class UserDefinedColours extends Panel implements ActionListener,
     Color[] newColours = new Color[24];
     for (int i = 0; i < 24; i++)
     {
-      newColours[i] = (Color) oldColours.elementAt(i);
+      newColours[i] = oldColours.elementAt(i);
       buttonPanel.getComponent(i).setBackground(newColours[i]);
     }
 
index 643d8a0..383dd1b 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.gui;
 
+import jalview.api.FeatureColourI;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.io.AnnotationFile;
 import jalview.io.FeaturesFile;
@@ -32,6 +33,7 @@ import java.awt.Color;
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.Map;
 
 import javax.swing.BorderFactory;
 import javax.swing.ButtonGroup;
@@ -153,17 +155,17 @@ public class AnnotationExporter extends JPanel
             .getString("label.no_features_on_alignment");
     if (features)
     {
+      Map<String, FeatureColourI> displayedFeatureColours = ap
+              .getFeatureRenderer().getDisplayedFeatureCols();
       if (GFFFormat.isSelected())
       {
         text = new FeaturesFile().printGFFFormat(ap.av.getAlignment()
-                .getDataset().getSequencesArray(), ap.getFeatureRenderer()
-                .getDisplayedFeatureCols(), true, ap.av.isShowNPFeats());// ap.av.featuresDisplayed//);
+                .getDataset().getSequencesArray(), displayedFeatureColours, true, ap.av.isShowNPFeats());// ap.av.featuresDisplayed//);
       }
       else
       {
         text = new FeaturesFile().printJalviewFormat(ap.av.getAlignment()
-                .getDataset().getSequencesArray(), ap.getFeatureRenderer()
-                .getDisplayedFeatureCols(), true, ap.av.isShowNPFeats()); // ap.av.featuresDisplayed);
+                .getDataset().getSequencesArray(), displayedFeatureColours, true, ap.av.isShowNPFeats()); // ap.av.featuresDisplayed);
       }
     }
     else
@@ -236,6 +238,7 @@ public class AnnotationExporter extends JPanel
     toFile.setText(MessageManager.getString("label.to_file"));
     toFile.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         toFile_actionPerformed(e);
@@ -244,6 +247,7 @@ public class AnnotationExporter extends JPanel
     toTextbox.setText(MessageManager.getString("label.to_textbox"));
     toTextbox.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         toTextbox_actionPerformed(e);
@@ -252,6 +256,7 @@ public class AnnotationExporter extends JPanel
     close.setText(MessageManager.getString("action.close"));
     close.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         close_actionPerformed(e);
index 064d58b..79217ea 100644 (file)
@@ -20,9 +20,9 @@
  */
 package jalview.gui;
 
+import jalview.api.FeatureColourI;
 import jalview.datamodel.GraphLine;
-import jalview.schemes.AnnotationColourGradient;
-import jalview.schemes.GraduatedColor;
+import jalview.schemes.FeatureColour;
 import jalview.util.MessageManager;
 
 import java.awt.BorderLayout;
@@ -33,7 +33,6 @@ 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;
@@ -52,16 +51,16 @@ public class FeatureColourChooser extends JalviewDialog
   // FeatureSettings fs;
   FeatureRenderer fr;
 
-  private GraduatedColor cs;
+  private FeatureColourI cs;
 
-  private Object oldcs;
+  private FeatureColourI 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()
+  public FeatureColourI getLastColour()
   {
     if (cs == null)
     {
@@ -70,8 +69,6 @@ public class FeatureColourChooser extends JalviewDialog
     return cs;
   }
 
-  Hashtable oldgroupColours;
-
   AlignmentPanel ap;
 
   boolean adjusting = false;
@@ -127,7 +124,7 @@ public class FeatureColourChooser extends JalviewDialog
       }
     });
 
-    float mm[] = ((float[][]) fr.getMinMax().get(type))[0];
+    float mm[] = fr.getMinMax().get(type)[0];
     min = mm[0];
     max = mm[1];
 
@@ -139,32 +136,32 @@ public class FeatureColourChooser extends JalviewDialog
     scaleFactor = (max == min) ? 1f : 100f / (max - min);
 
     oldcs = fr.getFeatureColours().get(type);
-    if (oldcs instanceof GraduatedColor)
+    if (!oldcs.isSimpleColour())
     {
-      if (((GraduatedColor) oldcs).isAutoScale())
+      if (oldcs.isAutoScaled())
       {
         // update the scale
-        cs = new GraduatedColor((GraduatedColor) oldcs, min, max);
+        cs = new FeatureColour((FeatureColour) oldcs, min, max);
       }
       else
       {
-        cs = new GraduatedColor((GraduatedColor) oldcs);
+        cs = new FeatureColour((FeatureColour) oldcs);
       }
     }
     else
     {
       // promote original color to a graduated color
-      Color bl = Color.black;
-      if (oldcs instanceof Color)
+      Color bl = oldcs.getColour();
+      if (bl == null)
       {
-        bl = (Color) oldcs;
+        bl = Color.BLACK;
       }
       // original colour becomes the maximum colour
-      cs = new GraduatedColor(Color.white, bl, mm[0], mm[1]);
+      cs = new FeatureColour(Color.white, bl, mm[0], mm[1]);
       cs.setColourByLabel(false);
     }
-    minColour.setBackground(oldminColour = cs.getMinColor());
-    maxColour.setBackground(oldmaxColour = cs.getMaxColor());
+    minColour.setBackground(oldminColour = cs.getMinColour());
+    maxColour.setBackground(oldmaxColour = cs.getMaxColour());
     adjusting = true;
 
     try
@@ -174,18 +171,15 @@ public class FeatureColourChooser extends JalviewDialog
     {
     }
     // update the gui from threshold state
-    thresholdIsMin.setSelected(!cs.isAutoScale());
+    thresholdIsMin.setSelected(!cs.isAutoScaled());
     colourByLabel.setSelected(cs.isColourByLabel());
-    if (cs.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
+    if (cs.hasThreshold())
     {
       // initialise threshold slider and selector
-      threshold
-              .setSelectedIndex(cs.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD ? 1
-                      : 2);
+      threshold.setSelectedIndex(cs.isAboveThreshold() ? 1 : 2);
       slider.setEnabled(true);
       thresholdValue.setEnabled(true);
-      threshline = new jalview.datamodel.GraphLine((max - min) / 2f,
-              "Threshold", Color.black);
+      threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
 
     }
 
@@ -395,50 +389,50 @@ public class FeatureColourChooser extends JalviewDialog
       return;
     }
 
-    int aboveThreshold = AnnotationColourGradient.NO_THRESHOLD;
+    boolean aboveThreshold = false;
+    boolean belowThreshold = false;
     if (threshold.getSelectedIndex() == 1)
     {
-      aboveThreshold = AnnotationColourGradient.ABOVE_THRESHOLD;
+      aboveThreshold = true;
     }
     else if (threshold.getSelectedIndex() == 2)
     {
-      aboveThreshold = AnnotationColourGradient.BELOW_THRESHOLD;
+      belowThreshold = true;
     }
+    boolean hasThreshold = aboveThreshold || belowThreshold;
 
     slider.setEnabled(true);
     thresholdValue.setEnabled(true);
 
-    GraduatedColor acg;
+    FeatureColourI acg;
     if (cs.isColourByLabel())
     {
-      acg = new GraduatedColor(oldminColour, oldmaxColour, min, max);
+      acg = new FeatureColour(oldminColour, oldmaxColour, min, max);
     }
     else
     {
-      acg = new GraduatedColor(oldminColour = minColour.getBackground(),
+      acg = new FeatureColour(oldminColour = minColour.getBackground(),
               oldmaxColour = maxColour.getBackground(), min, max);
 
     }
 
-    if (aboveThreshold == AnnotationColourGradient.NO_THRESHOLD)
+    if (!hasThreshold)
     {
       slider.setEnabled(false);
       thresholdValue.setEnabled(false);
       thresholdValue.setText("");
       thresholdIsMin.setEnabled(false);
     }
-    else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
-            && threshline == null)
+    else if (threshline == null)
     {
       // todo visual indication of feature threshold
-      threshline = new jalview.datamodel.GraphLine((max - min) / 2f,
-              "Threshold", Color.black);
+      threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
     }
 
-    if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
+    if (hasThreshold)
     {
       adjusting = true;
-      acg.setThresh(threshline.value);
+      acg.setThreshold(threshline.value);
 
       float range = (max - min) * scaleFactor;
 
@@ -453,18 +447,18 @@ public class FeatureColourChooser extends JalviewDialog
       adjusting = false;
     }
 
-    acg.setThreshType(aboveThreshold);
-    if (thresholdIsMin.isSelected()
-            && aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
+    acg.setAboveThreshold(aboveThreshold);
+    acg.setBelowThreshold(belowThreshold);
+    if (thresholdIsMin.isSelected() && hasThreshold)
     {
       acg.setAutoScaled(false);
-      if (aboveThreshold == AnnotationColourGradient.ABOVE_THRESHOLD)
+      if (aboveThreshold)
       {
-        acg = new GraduatedColor(acg, threshline.value, max);
+        acg = new FeatureColour((FeatureColour) acg, threshline.value, max);
       }
       else
       {
-        acg = new GraduatedColor(acg, min, threshline.value);
+        acg = new FeatureColour((FeatureColour) acg, min, threshline.value);
       }
     }
     else
@@ -554,7 +548,7 @@ public class FeatureColourChooser extends JalviewDialog
   public void valueChanged()
   {
     threshline.value = slider.getValue() / scaleFactor;
-    cs.setThresh(threshline.value);
+    cs.setThreshold(threshline.value);
     changeColour();
     ap.paintAlignment(false);
   }
index a0f1b80..46bcdab 100644 (file)
  */
 package jalview.gui;
 
+import jalview.api.FeatureColourI;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
-import jalview.schemes.GraduatedColor;
+import jalview.schemes.FeatureColour;
+import jalview.schemes.UserColourScheme;
 import jalview.util.MessageManager;
 
 import java.awt.BorderLayout;
@@ -92,7 +94,7 @@ public class FeatureRenderer extends
 
   static String lastDescriptionAdded;
 
-  Object oldcol, fcol;
+  FeatureColourI oldcol, fcol;
 
   int featureIndex = 0;
 
@@ -121,22 +123,22 @@ public class FeatureRenderer extends
     {
       FeatureColourChooser fcc = null;
 
+      @Override
       public void mousePressed(MouseEvent evt)
       {
-        if (fcol instanceof Color)
+        if (fcol.isSimpleColour())
         {
           Color col = JColorChooser.showDialog(Desktop.desktop,
                   MessageManager.getString("label.select_feature_colour"),
-                  ((Color) fcol));
+                  fcol.getColour());
           if (col != null)
           {
-            fcol = col;
-            updateColourButton(bigPanel, colour, col);
+            fcol = new FeatureColour(col);
+            updateColourButton(bigPanel, colour, new FeatureColour(col));
           }
         }
         else
         {
-
           if (fcc == null)
           {
             final String type = features[featureIndex].getType();
@@ -147,6 +149,7 @@ public class FeatureRenderer extends
             fcc.addActionListener(new ActionListener()
             {
 
+              @Override
               public void actionPerformed(ActionEvent e)
               {
                 fcol = fcc.getLastColour();
@@ -182,6 +185,7 @@ public class FeatureRenderer extends
 
       overlaps.addItemListener(new ItemListener()
       {
+        @Override
         public void itemStateChanged(ItemEvent e)
         {
           int index = overlaps.getSelectedIndex();
@@ -201,11 +205,11 @@ public class FeatureRenderer extends
             ap.getSeqPanel().seqCanvas.highlightSearchResults(highlight);
 
           }
-          Object col = getFeatureStyle(name.getText());
+          FeatureColourI col = getFeatureStyle(name.getText());
           if (col == null)
           {
-            col = new jalview.schemes.UserColourScheme()
-                    .createColourFromName(name.getText());
+            col = new FeatureColour(UserColourScheme
+                    .createColourFromName(name.getText()));
           }
           oldcol = fcol = col;
           updateColourButton(bigPanel, colour, col);
@@ -416,26 +420,25 @@ public class FeatureRenderer extends
    * 
    * @param bigPanel
    * @param col
-   * @param col2
+   * @param col
    */
   protected void updateColourButton(JPanel bigPanel, JLabel colour,
-          Object col2)
+          FeatureColourI col)
   {
     colour.removeAll();
     colour.setIcon(null);
     colour.setToolTipText(null);
     colour.setText("");
 
-    if (col2 instanceof Color)
+    if (col.isSimpleColour())
     {
-      colour.setBackground((Color) col2);
+      colour.setBackground(col.getColour());
     }
     else
     {
       colour.setBackground(bigPanel.getBackground());
       colour.setForeground(Color.black);
-      FeatureSettings.renderGraduatedColor(colour, (GraduatedColor) col2);
-      // colour.setForeground(colour.getBackground());
+      FeatureSettings.renderGraduatedColor(colour, col);
     }
   }
 }
index 6b58b51..cf7bdb3 100644 (file)
  */
 package jalview.gui;
 
+import jalview.api.FeatureColourI;
 import jalview.api.FeatureSettingsControllerI;
 import jalview.bin.Cache;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.Help.HelpId;
 import jalview.io.JalviewFileChooser;
-import jalview.schemes.AnnotationColourGradient;
-import jalview.schemes.GraduatedColor;
+import jalview.schemabinding.version2.JalviewUserColours;
+import jalview.schemes.FeatureColour;
+import jalview.util.Format;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.util.QuickSort;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.ws.dbsources.das.api.jalviewSourceI;
 
@@ -57,6 +61,7 @@ import java.io.PrintWriter;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.Vector;
 
@@ -158,12 +163,13 @@ public class FeatureSettings extends JPanel implements
 
     table.setDefaultEditor(Color.class, new ColorEditor(this));
 
-    table.setDefaultEditor(GraduatedColor.class, new ColorEditor(this));
-    table.setDefaultRenderer(GraduatedColor.class, new ColorRenderer());
+    table.setDefaultEditor(FeatureColour.class, new ColorEditor(this));
+    table.setDefaultRenderer(FeatureColour.class, new ColorRenderer());
     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 
     table.addMouseListener(new MouseAdapter()
     {
+      @Override
       public void mousePressed(MouseEvent evt)
       {
         selectedRow = table.rowAtPoint(evt.getPoint());
@@ -198,6 +204,7 @@ public class FeatureSettings extends JPanel implements
 
     table.addMouseMotionListener(new MouseMotionAdapter()
     {
+      @Override
       public void mouseDragged(MouseEvent evt)
       {
         int newRow = table.rowAtPoint(evt.getPoint());
@@ -237,6 +244,7 @@ public class FeatureSettings extends JPanel implements
     final FeatureSettings fs = this;
     fr.addPropertyChangeListener(change = new PropertyChangeListener()
     {
+      @Override
       public void propertyChange(PropertyChangeEvent evt)
       {
         if (!fs.resettingTable && !fs.handlingUpdate)
@@ -252,7 +260,7 @@ public class FeatureSettings extends JPanel implements
 
     frame = new JInternalFrame();
     frame.setContentPane(this);
-    if (new jalview.util.Platform().isAMac())
+    if (Platform.isAMac())
     {
       Desktop.addInternalFrame(frame,
               MessageManager.getString("label.sequence_feature_settings"),
@@ -267,6 +275,7 @@ public class FeatureSettings extends JPanel implements
 
     frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
     {
+      @Override
       public void internalFrameClosed(
               javax.swing.event.InternalFrameEvent evt)
       {
@@ -277,9 +286,12 @@ public class FeatureSettings extends JPanel implements
     frame.setLayer(JLayeredPane.PALETTE_LAYER);
   }
 
-  protected void popupSort(final int selectedRow, final String type,
-          final Object typeCol, final Hashtable minmax, int x, int y)
+  protected void popupSort(final int row, final String type,
+          final Object typeCol, final Map<String, float[][]> minmax, int x,
+          int y)
   {
+    final FeatureColourI featureColour = (FeatureColourI) typeCol;
+
     JPopupMenu men = new JPopupMenu(MessageManager.formatMessage(
             "label.settings_for_param", new String[] { type }));
     JMenuItem scr = new JMenuItem(
@@ -289,6 +301,7 @@ public class FeatureSettings extends JPanel implements
     scr.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         me.af.avc.sortAlignmentByFeatureScore(new String[] { type });
@@ -300,6 +313,7 @@ public class FeatureSettings extends JPanel implements
     dens.addActionListener(new ActionListener()
     {
 
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         me.af.avc.sortAlignmentByFeatureDensity(new String[] { type });
@@ -309,7 +323,7 @@ public class FeatureSettings extends JPanel implements
     men.add(dens);
     if (minmax != null)
     {
-      final Object typeMinMax = minmax.get(type);
+      final float[][] typeMinMax = minmax.get(type);
       /*
        * final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
        * this is broken at the moment and isn't that useful anyway!
@@ -324,24 +338,25 @@ public class FeatureSettings extends JPanel implements
        * 
        * men.add(chb);
        */
-      if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
+      if (typeMinMax != null && typeMinMax[0] != null)
       {
         // if (table.getValueAt(row, column));
         // graduated colourschemes for those where minmax exists for the
         // positional features
         final JCheckBoxMenuItem mxcol = new JCheckBoxMenuItem(
                 "Graduated Colour");
-        mxcol.setSelected(!(typeCol instanceof Color));
+        mxcol.setSelected(!featureColour.isSimpleColour());
         men.add(mxcol);
         mxcol.addActionListener(new ActionListener()
         {
           JColorChooser colorChooser;
 
+          @Override
           public void actionPerformed(ActionEvent e)
           {
             if (e.getSource() == mxcol)
             {
-              if (typeCol instanceof Color)
+              if (featureColour.isSimpleColour())
               {
                 FeatureColourChooser fc = new FeatureColourChooser(me.fr,
                         type);
@@ -355,8 +370,7 @@ public class FeatureSettings extends JPanel implements
                         "Select new Colour", true, // modal
                         colorChooser, this, // OK button handler
                         null); // no CANCEL button handler
-                colorChooser.setColor(((GraduatedColor) typeCol)
-                        .getMaxColor());
+                colorChooser.setColor(featureColour.getMaxColour());
                 dialog.setVisible(true);
               }
             }
@@ -366,13 +380,13 @@ public class FeatureSettings extends JPanel implements
               {
                 FeatureColourChooser fc = (FeatureColourChooser) e
                         .getSource();
-                table.setValueAt(fc.getLastColour(), selectedRow, 1);
+                table.setValueAt(fc.getLastColour(), row, 1);
                 table.validate();
               }
               else
               {
                 // probably the color chooser!
-                table.setValueAt(colorChooser.getColor(), selectedRow, 1);
+                table.setValueAt(colorChooser.getColor(), row, 1);
                 table.validate();
                 me.updateFeatureRenderer(
                         ((FeatureTableModel) table.getModel()).getData(),
@@ -421,13 +435,13 @@ public class FeatureSettings extends JPanel implements
   /**
    * contains a float[3] for each feature type string. created by setTableData
    */
-  Hashtable typeWidth = null;
+  Map<String, float[]> typeWidth = null;
 
   @Override
   synchronized public void discoverAllFeatureData()
   {
-    Vector allFeatures = new Vector();
-    Vector allGroups = new Vector();
+    Vector<String> allFeatures = new Vector<String>();
+    Vector<String> allGroups = new Vector<String>();
     SequenceFeature[] tmpfeatures;
     String group;
     for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
@@ -507,6 +521,7 @@ public class FeatureSettings extends JPanel implements
     check.setFont(new Font("Serif", Font.BOLD, 12));
     check.addItemListener(new ItemListener()
     {
+      @Override
       public void itemStateChanged(ItemEvent evt)
       {
         fr.setGroupVisibility(check.getText(), check.isSelected());
@@ -532,13 +547,13 @@ public class FeatureSettings extends JPanel implements
       return;
     }
     resettingTable = true;
-    typeWidth = new Hashtable();
+    typeWidth = new Hashtable<String, float[]>();
     // TODO: change avWidth calculation to 'per-sequence' average and use long
     // rather than float
     float[] avWidth = null;
     SequenceFeature[] tmpfeatures;
     String group = null, type;
-    Vector visibleChecks = new Vector();
+    Vector<String> visibleChecks = new Vector<String>();
 
     // Find out which features should be visible depending on which groups
     // are selected / deselected
@@ -579,7 +594,7 @@ public class FeatureSettings extends JPanel implements
         }
         else
         {
-          avWidth = (float[]) typeWidth.get(tmpfeatures[index].getType());
+          avWidth = typeWidth.get(tmpfeatures[index].getType());
         }
         avWidth[0]++;
         if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
@@ -724,8 +739,7 @@ public class FeatureSettings extends JPanel implements
         InputStreamReader in = new InputStreamReader(new FileInputStream(
                 file), "UTF-8");
 
-        jalview.schemabinding.version2.JalviewUserColours jucs = new jalview.schemabinding.version2.JalviewUserColours();
-        jucs = jucs.unmarshal(in);
+        JalviewUserColours jucs = JalviewUserColours.unmarshal(in);
 
         for (int i = jucs.getColourCount() - 1; i >= 0; i--)
         {
@@ -744,7 +758,7 @@ public class FeatureSettings extends JPanel implements
               Cache.log.warn("Couldn't parse out graduated feature color.",
                       e);
             }
-            GraduatedColor gcol = new GraduatedColor(mincol, maxcol,
+            FeatureColourI gcol = new FeatureColour(mincol, maxcol,
                     newcol.getMin(), newcol.getMax());
             if (newcol.hasAutoScale())
             {
@@ -756,31 +770,28 @@ public class FeatureSettings extends JPanel implements
             }
             if (newcol.hasThreshold())
             {
-              gcol.setThresh(newcol.getThreshold());
-              gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD); // default
+              gcol.setThreshold(newcol.getThreshold());
             }
             if (newcol.getThreshType().length() > 0)
             {
               String ttyp = newcol.getThreshType();
-              if (ttyp.equalsIgnoreCase("NONE"))
-              {
-                gcol.setThreshType(AnnotationColourGradient.NO_THRESHOLD);
-              }
               if (ttyp.equalsIgnoreCase("ABOVE"))
               {
-                gcol.setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
+                gcol.setAboveThreshold(true);
               }
               if (ttyp.equalsIgnoreCase("BELOW"))
               {
-                gcol.setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
+                gcol.setBelowThreshold(true);
               }
             }
             fr.setColour(name = newcol.getName(), gcol);
           }
           else
           {
-            fr.setColour(name = jucs.getColour(i).getName(), new Color(
-                    Integer.parseInt(jucs.getColour(i).getRGB(), 16)));
+            Color color = new Color(
+                    Integer.parseInt(jucs.getColour(i).getRGB(), 16));
+            fr.setColour(name = jucs.getColour(i).getName(),
+                    new FeatureColour(color));
           }
           fr.setOrder(name, (i == 0) ? 0 : i / jucs.getColourCount());
         }
@@ -824,50 +835,40 @@ public class FeatureSettings extends JPanel implements
         PrintWriter out = new PrintWriter(new OutputStreamWriter(
                 new FileOutputStream(choice), "UTF-8"));
 
-        Set fr_colours = fr.getAllFeatureColours();
-        Iterator e = fr_colours.iterator();
+        Set<String> fr_colours = fr.getAllFeatureColours();
+        Iterator<String> e = fr_colours.iterator();
         float[] sortOrder = new float[fr_colours.size()];
         String[] sortTypes = new String[fr_colours.size()];
         int i = 0;
         while (e.hasNext())
         {
-          sortTypes[i] = e.next().toString();
+          sortTypes[i] = e.next();
           sortOrder[i] = fr.getOrder(sortTypes[i]);
           i++;
         }
-        jalview.util.QuickSort.sort(sortOrder, sortTypes);
+        QuickSort.sort(sortOrder, sortTypes);
         sortOrder = null;
-        Object fcol;
-        GraduatedColor gcol;
         for (i = 0; i < sortTypes.length; i++)
         {
           jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
           col.setName(sortTypes[i]);
-          col.setRGB(jalview.util.Format.getHexString(fr.getColour(col
-                  .getName())));
-          fcol = fr.getFeatureStyle(sortTypes[i]);
-          if (fcol instanceof GraduatedColor)
+          FeatureColourI fcol = fr.getFeatureStyle(sortTypes[i]);
+          if (fcol.isSimpleColour())
           {
-            gcol = (GraduatedColor) fcol;
-            col.setMin(gcol.getMin());
-            col.setMax(gcol.getMax());
-            col.setMinRGB(jalview.util.Format.getHexString(gcol
-                    .getMinColor()));
-            col.setAutoScale(gcol.isAutoScale());
-            col.setThreshold(gcol.getThresh());
-            col.setColourByLabel(gcol.isColourByLabel());
-            switch (gcol.getThreshType())
-            {
-            case AnnotationColourGradient.NO_THRESHOLD:
-              col.setThreshType("NONE");
-              break;
-            case AnnotationColourGradient.ABOVE_THRESHOLD:
-              col.setThreshType("ABOVE");
-              break;
-            case AnnotationColourGradient.BELOW_THRESHOLD:
-              col.setThreshType("BELOW");
-              break;
-            }
+            col.setRGB(Format.getHexString(fcol.getColour()));
+          }
+          else
+          {
+            col.setRGB(Format.getHexString(fcol.getMaxColour()));
+            col.setMin(fcol.getMin());
+            col.setMax(fcol.getMax());
+            col.setMinRGB(jalview.util.Format.getHexString(fcol
+                    .getMinColour()));
+            col.setAutoScale(fcol.isAutoScaled());
+            col.setThreshold(fcol.getThreshold());
+            col.setColourByLabel(fcol.isColourByLabel());
+            col.setThreshType(fcol.isAboveThreshold() ? "ABOVE" : (fcol
+                    .isBelowThreshold() ? "BELOW" : "NONE"));
           }
           ucs.addColour(col);
         }
@@ -903,7 +904,7 @@ public class FeatureSettings extends JPanel implements
     int num = 0;
     for (int i = 0; i < data.length; i++)
     {
-      awidth = (float[]) typeWidth.get(data[i][0]);
+      awidth = typeWidth.get(data[i][0]);
       if (awidth[0] > 0)
       {
         width[i] = awidth[1] / awidth[0];// *awidth[0]*awidth[2]; - better
@@ -1029,6 +1030,7 @@ public class FeatureSettings extends JPanel implements
     invert.setText(MessageManager.getString("label.invert_selection"));
     invert.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         invertSelection();
@@ -1038,6 +1040,7 @@ public class FeatureSettings extends JPanel implements
     optimizeOrder.setText(MessageManager.getString("label.optimise_order"));
     optimizeOrder.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         orderByAvWidth();
@@ -1048,6 +1051,7 @@ public class FeatureSettings extends JPanel implements
             .setText(MessageManager.getString("label.seq_sort_by_score"));
     sortByScore.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         af.avc.sortAlignmentByFeatureScore(null);
@@ -1058,6 +1062,7 @@ public class FeatureSettings extends JPanel implements
             .getString("label.sequence_sort_by_density"));
     sortByDens.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         af.avc.sortAlignmentByFeatureDensity(null);
@@ -1067,6 +1072,7 @@ public class FeatureSettings extends JPanel implements
     help.setText(MessageManager.getString("action.help"));
     help.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         try
@@ -1082,6 +1088,7 @@ public class FeatureSettings extends JPanel implements
     help.setText(MessageManager.getString("action.help"));
     help.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         try
@@ -1097,6 +1104,7 @@ public class FeatureSettings extends JPanel implements
     cancel.setText(MessageManager.getString("action.cancel"));
     cancel.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         fr.setTransparency(originalTransparency);
@@ -1108,6 +1116,7 @@ public class FeatureSettings extends JPanel implements
     ok.setText(MessageManager.getString("action.ok"));
     ok.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         close();
@@ -1117,6 +1126,7 @@ public class FeatureSettings extends JPanel implements
     loadColours.setText(MessageManager.getString("label.load_colours"));
     loadColours.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         load();
@@ -1126,6 +1136,7 @@ public class FeatureSettings extends JPanel implements
     saveColours.setText(MessageManager.getString("label.save_colours"));
     saveColours.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         save();
@@ -1133,6 +1144,7 @@ public class FeatureSettings extends JPanel implements
     });
     transparency.addChangeListener(new ChangeListener()
     {
+      @Override
       public void stateChanged(ChangeEvent evt)
       {
         fr.setTransparency((100 - transparency.getValue()) / 100f);
@@ -1146,6 +1158,7 @@ public class FeatureSettings extends JPanel implements
     fetchDAS.setText(MessageManager.getString("label.fetch_das_features"));
     fetchDAS.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         fetchDAS_actionPerformed(e);
@@ -1154,6 +1167,7 @@ public class FeatureSettings extends JPanel implements
     saveDAS.setText(MessageManager.getString("action.save_as_default"));
     saveDAS.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         saveDAS_actionPerformed(e);
@@ -1165,6 +1179,7 @@ public class FeatureSettings extends JPanel implements
     cancelDAS.setText(MessageManager.getString("action.cancel_fetch"));
     cancelDAS.addActionListener(new ActionListener()
     {
+      @Override
       public void actionPerformed(ActionEvent e)
       {
         cancelDAS_actionPerformed(e);
@@ -1203,7 +1218,8 @@ public class FeatureSettings extends JPanel implements
     fetchDAS.setEnabled(false);
     cancelDAS.setEnabled(true);
     dassourceBrowser.setGuiEnabled(false);
-    Vector selectedSources = dassourceBrowser.getSelectedSources();
+    Vector<jalviewSourceI> selectedSources = dassourceBrowser
+            .getSelectedSources();
     doDasFeatureFetch(selectedSources, true, true);
   }
 
@@ -1262,7 +1278,7 @@ public class FeatureSettings extends JPanel implements
    *          Vector of Strings to resolve to DAS source nicknames.
    * @return sources that are present in source list.
    */
-  public List<jalviewSourceI> resolveSourceNicknames(Vector sources)
+  public List<jalviewSourceI> resolveSourceNicknames(Vector<String> sources)
   {
     return dassourceBrowser.sourceRegistry.resolveSourceNicknames(sources);
   }
@@ -1273,7 +1289,7 @@ public class FeatureSettings extends JPanel implements
    * 
    * @return vector of selected das source nicknames
    */
-  public Vector getSelectedSources()
+  public Vector<jalviewSourceI> getSelectedSources()
   {
     return dassourceBrowser.getSelectedSources();
   }
@@ -1287,7 +1303,7 @@ public class FeatureSettings extends JPanel implements
    *          if true then runs in same thread, otherwise passes to the Swing
    *          executor
    */
-  public void fetchDasFeatures(Vector sources, boolean block)
+  public void fetchDasFeatures(Vector<String> sources, boolean block)
   {
     initDasSources();
     List<jalviewSourceI> resolved = dassourceBrowser.sourceRegistry
@@ -1304,6 +1320,7 @@ public class FeatureSettings extends JPanel implements
       Runnable fetcher = new Runnable()
       {
 
+        @Override
         public void run()
         {
           doDasFeatureFetch(dassources, true, false);
@@ -1385,6 +1402,7 @@ public class FeatureSettings extends JPanel implements
       this.data = data;
     }
 
+    @Override
     public int getColumnCount()
     {
       return columnNames.length;
@@ -1395,31 +1413,37 @@ public class FeatureSettings extends JPanel implements
       return data[row];
     }
 
+    @Override
     public int getRowCount()
     {
       return data.length;
     }
 
+    @Override
     public String getColumnName(int col)
     {
       return columnNames[col];
     }
 
+    @Override
     public Object getValueAt(int row, int col)
     {
       return data[row][col];
     }
 
+    @Override
     public Class getColumnClass(int c)
     {
       return getValueAt(0, c).getClass();
     }
 
+    @Override
     public boolean isCellEditable(int row, int col)
     {
       return col == 0 ? false : true;
     }
 
+    @Override
     public void setValueAt(Object value, int row, int col)
     {
       data[row][col] = value;
@@ -1444,10 +1468,12 @@ public class FeatureSettings extends JPanel implements
       setVerticalTextPosition(SwingConstants.CENTER);
     }
 
-    public Component getTableCellRendererComponent(JTable table,
+    @Override
+    public Component getTableCellRendererComponent(JTable tbl,
             Object color, boolean isSelected, boolean hasFocus, int row,
             int column)
     {
+      FeatureColourI cellColour = (FeatureColourI) color;
       // JLabel comp = new JLabel();
       // comp.
       setOpaque(true);
@@ -1455,11 +1481,11 @@ public class FeatureSettings extends JPanel implements
       // setBounds(getBounds());
       Color newColor;
       setToolTipText(baseTT);
-      setBackground(table.getBackground());
-      if (color instanceof GraduatedColor)
+      setBackground(tbl.getBackground());
+      if (!cellColour.isSimpleColour())
       {
-        Rectangle cr = table.getCellRect(row, column, false);
-        FeatureSettings.renderGraduatedColor(this, (GraduatedColor) color,
+        Rectangle cr = tbl.getCellRect(row, column, false);
+        FeatureSettings.renderGraduatedColor(this, cellColour,
                 (int) cr.getWidth(), (int) cr.getHeight());
 
       }
@@ -1467,20 +1493,16 @@ public class FeatureSettings extends JPanel implements
       {
         this.setText("");
         this.setIcon(null);
-        newColor = (Color) color;
-        // comp.
+        newColor = cellColour.getColour();
         setBackground(newColor);
-        // comp.setToolTipText("RGB value: " + newColor.getRed() + ", "
-        // + newColor.getGreen() + ", " + newColor.getBlue());
       }
       if (isSelected)
       {
         if (selectedBorder == null)
         {
           selectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
-                  table.getSelectionBackground());
+                  tbl.getSelectionBackground());
         }
-        // comp.
         setBorder(selectedBorder);
       }
       else
@@ -1488,9 +1510,8 @@ public class FeatureSettings extends JPanel implements
         if (unselectedBorder == null)
         {
           unselectedBorder = BorderFactory.createMatteBorder(2, 5, 2, 5,
-                  table.getBackground());
+                  tbl.getBackground());
         }
-        // comp.
         setBorder(unselectedBorder);
       }
 
@@ -1504,7 +1525,7 @@ public class FeatureSettings extends JPanel implements
    * @param comp
    * @param gcol
    */
-  public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol)
+  public static void renderGraduatedColor(JLabel comp, FeatureColourI gcol)
   {
     int w = comp.getWidth(), h = comp.getHeight();
     if (w < 20)
@@ -1520,23 +1541,23 @@ public class FeatureSettings extends JPanel implements
     renderGraduatedColor(comp, gcol, w, h);
   }
 
-  public static void renderGraduatedColor(JLabel comp, GraduatedColor gcol,
+  public static void renderGraduatedColor(JLabel comp, FeatureColourI gcol,
           int w, int h)
   {
     boolean thr = false;
     String tt = "";
     String tx = "";
-    if (gcol.getThreshType() == AnnotationColourGradient.ABOVE_THRESHOLD)
+    if (gcol.isAboveThreshold())
     {
       thr = true;
       tx += ">";
-      tt += "Thresholded (Above " + gcol.getThresh() + ") ";
+      tt += "Thresholded (Above " + gcol.getThreshold() + ") ";
     }
-    if (gcol.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
+    if (gcol.isBelowThreshold())
     {
       thr = true;
       tx += "<";
-      tt += "Thresholded (Below " + gcol.getThresh() + ") ";
+      tt += "Thresholded (Below " + gcol.getThreshold() + ") ";
     }
     if (gcol.isColourByLabel())
     {
@@ -1550,7 +1571,7 @@ public class FeatureSettings extends JPanel implements
     }
     else
     {
-      Color newColor = gcol.getMaxColor();
+      Color newColor = gcol.getMaxColour();
       comp.setBackground(newColor);
       // System.err.println("Width is " + w / 2);
       Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
@@ -1578,7 +1599,7 @@ public class FeatureSettings extends JPanel implements
 
 class FeatureIcon implements Icon
 {
-  GraduatedColor gcol;
+  FeatureColourI gcol;
 
   Color backg;
 
@@ -1590,7 +1611,7 @@ class FeatureIcon implements Icon
 
   Color mpcolour = Color.white;
 
-  FeatureIcon(GraduatedColor gfc, Color bg, int w, int h, boolean mspace)
+  FeatureIcon(FeatureColourI gfc, Color bg, int w, int h, boolean mspace)
   {
     gcol = gfc;
     backg = bg;
@@ -1609,16 +1630,19 @@ class FeatureIcon implements Icon
     }
   }
 
+  @Override
   public int getIconWidth()
   {
     return width;
   }
 
+  @Override
   public int getIconHeight()
   {
     return height;
   }
 
+  @Override
   public void paintIcon(Component c, Graphics g, int x, int y)
   {
 
@@ -1627,7 +1651,7 @@ class FeatureIcon implements Icon
       g.setColor(backg);
       g.fillRect(0, 0, width, height);
       // need an icon here.
-      g.setColor(gcol.getMaxColor());
+      g.setColor(gcol.getMaxColour());
 
       g.setFont(new Font("Verdana", Font.PLAIN, 9));
 
@@ -1641,7 +1665,7 @@ class FeatureIcon implements Icon
     }
     else
     {
-      Color minCol = gcol.getMinColor();
+      Color minCol = gcol.getMinColour();
       g.setColor(minCol);
       g.fillRect(0, 0, s1, height);
       if (midspace)
@@ -1649,7 +1673,7 @@ class FeatureIcon implements Icon
         g.setColor(Color.white);
         g.fillRect(s1, 0, e1 - s1, height);
       }
-      g.setColor(gcol.getMaxColor());
+      g.setColor(gcol.getMaxColour());
       g.fillRect(0, e1, width - e1, height);
     }
   }
@@ -1660,14 +1684,12 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor,
 {
   FeatureSettings me;
 
-  GraduatedColor currentGColor;
+  FeatureColourI currentColor;
 
   FeatureColourChooser chooser;
 
   String type;
 
-  Color currentColor;
-
   JButton button;
 
   JColorChooser colorChooser;
@@ -1699,6 +1721,7 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor,
   /**
    * Handles events from the editor button and from the dialog's OK button.
    */
+  @Override
   public void actionPerformed(ActionEvent e)
   {
 
@@ -1706,11 +1729,11 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor,
     {
       // The user has clicked the cell, so
       // bring up the dialog.
-      if (currentColor != null)
+      if (currentColor.isSimpleColour())
       {
         // bring up simple color chooser
-        button.setBackground(currentColor);
-        colorChooser.setColor(currentColor);
+        button.setBackground(currentColor.getColour());
+        colorChooser.setColor(currentColor.getColour());
         dialog.setVisible(true);
       }
       else
@@ -1727,15 +1750,13 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor,
     }
     else
     { // User pressed dialog's "OK" button.
-      if (currentColor != null)
+      if (currentColor.isSimpleColour())
       {
-        currentColor = colorChooser.getColor();
+        currentColor = new FeatureColour(colorChooser.getColor());
       }
       else
       {
-        // class cast exceptions may be raised if the chooser created on a
-        // non-graduated color
-        currentGColor = (GraduatedColor) chooser.getLastColour();
+        currentColor = chooser.getLastColour();
       }
       me.table.setValueAt(getCellEditorValue(), selectedRow, 1);
       fireEditingStopped();
@@ -1744,31 +1765,27 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor,
   }
 
   // Implement the one CellEditor method that AbstractCellEditor doesn't.
+  @Override
   public Object getCellEditorValue()
   {
-    if (currentColor == null)
-    {
-      return currentGColor;
-    }
     return currentColor;
   }
 
   // Implement the one method defined by TableCellEditor.
+  @Override
   public Component getTableCellEditorComponent(JTable table, Object value,
           boolean isSelected, int row, int column)
   {
-    currentGColor = null;
-    currentColor = null;
+    currentColor = (FeatureColourI) value;
     this.selectedRow = row;
     type = me.table.getValueAt(row, 0).toString();
     button.setOpaque(true);
     button.setBackground(me.getBackground());
-    if (value instanceof GraduatedColor)
+    if (!currentColor.isSimpleColour())
     {
-      currentGColor = (GraduatedColor) value;
       JLabel btn = new JLabel();
       btn.setSize(button.getSize());
-      FeatureSettings.renderGraduatedColor(btn, currentGColor);
+      FeatureSettings.renderGraduatedColor(btn, currentColor);
       button.setBackground(btn.getBackground());
       button.setIcon(btn.getIcon());
       button.setText(btn.getText());
@@ -1777,8 +1794,7 @@ class ColorEditor extends AbstractCellEditor implements TableCellEditor,
     {
       button.setText("");
       button.setIcon(null);
-      currentColor = (Color) value;
-      button.setBackground(currentColor);
+      button.setBackground(currentColor.getColour());
     }
     return button;
   }
index fc96edc..9a9c7b3 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.gui;
 
+import jalview.api.FeatureColourI;
 import jalview.api.ViewStyleI;
 import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
@@ -71,7 +72,7 @@ import jalview.schemabinding.version2.Viewport;
 import jalview.schemes.AnnotationColourGradient;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.ColourSchemeProperty;
-import jalview.schemes.GraduatedColor;
+import jalview.schemes.FeatureColour;
 import jalview.schemes.ResidueColourScheme;
 import jalview.schemes.ResidueProperties;
 import jalview.schemes.UserColourScheme;
@@ -90,6 +91,7 @@ import jalview.ws.params.ArgumentI;
 import jalview.ws.params.AutoCalcSetting;
 import jalview.ws.params.WsParamSetI;
 
+import java.awt.Color;
 import java.awt.Rectangle;
 import java.io.BufferedReader;
 import java.io.DataInputStream;
@@ -1193,34 +1195,32 @@ public class Jalview2XML
                 .getFeatureRenderer().getRenderOrder()
                 .toArray(new String[0]);
 
-        Vector settingsAdded = new Vector();
-        Object gstyle = null;
-        GraduatedColor gcol = null;
+        Vector<String> settingsAdded = new Vector<String>();
         if (renderOrder != null)
         {
           for (int ro = 0; ro < renderOrder.length; ro++)
           {
-            gstyle = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
+            FeatureColourI gstyle = ap.getSeqPanel().seqCanvas
+                    .getFeatureRenderer()
                     .getFeatureStyle(renderOrder[ro]);
             Setting setting = new Setting();
             setting.setType(renderOrder[ro]);
-            if (gstyle instanceof GraduatedColor)
+            if (!gstyle.isSimpleColour())
             {
-              gcol = (GraduatedColor) gstyle;
-              setting.setColour(gcol.getMaxColor().getRGB());
-              setting.setMincolour(gcol.getMinColor().getRGB());
-              setting.setMin(gcol.getMin());
-              setting.setMax(gcol.getMax());
-              setting.setColourByLabel(gcol.isColourByLabel());
-              setting.setAutoScale(gcol.isAutoScale());
-              setting.setThreshold(gcol.getThresh());
-              setting.setThreshstate(gcol.getThreshType());
+              setting.setColour(gstyle.getMaxColour().getRGB());
+              setting.setMincolour(gstyle.getMinColour().getRGB());
+              setting.setMin(gstyle.getMin());
+              setting.setMax(gstyle.getMax());
+              setting.setColourByLabel(gstyle.isColourByLabel());
+              setting.setAutoScale(gstyle.isAutoScaled());
+              setting.setThreshold(gstyle.getThreshold());
+              // -1 = No threshold, 0 = Below, 1 = Above
+              setting.setThreshstate(gstyle.isAboveThreshold() ? 1
+                      : (gstyle.isBelowThreshold() ? 0 : -1));
             }
             else
             {
-              setting.setColour(ap.getSeqPanel().seqCanvas
-                      .getFeatureRenderer().getColour(renderOrder[ro])
-                      .getRGB());
+              setting.setColour(gstyle.getColour().getRGB());
             }
 
             setting.setDisplay(av.getFeaturesDisplayed().isVisible(
@@ -1236,36 +1236,11 @@ public class Jalview2XML
           }
         }
 
-        // Make sure we save none displayed feature settings
-        Iterator en = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
-                .getFeatureColours().keySet().iterator();
-        while (en.hasNext())
-        {
-          String key = en.next().toString();
-          if (settingsAdded.contains(key))
-          {
-            continue;
-          }
-
-          Setting setting = new Setting();
-          setting.setType(key);
-          setting.setColour(ap.getSeqPanel().seqCanvas.getFeatureRenderer()
-                  .getColour(key).getRGB());
-
-          setting.setDisplay(false);
-          float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
-                  .getOrder(key);
-          if (rorder > -1)
-          {
-            setting.setOrder(rorder);
-          }
-          fs.addSetting(setting);
-          settingsAdded.addElement(key);
-        }
         // is groups actually supposed to be a map here ?
-        en = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
+        Iterator<String> en = ap.getSeqPanel().seqCanvas
+                .getFeatureRenderer()
                 .getFeatureGroups().iterator();
-        Vector groupsAdded = new Vector();
+        Vector<String> groupsAdded = new Vector<String>();
         while (en.hasNext())
         {
           String grp = en.next().toString();
@@ -1282,7 +1257,6 @@ public class Jalview2XML
           groupsAdded.addElement(grp);
         }
         jms.setFeatureSettings(fs);
-
       }
 
       if (av.hasHiddenColumns())
@@ -2178,6 +2152,7 @@ public class Jalview2XML
       {
         SwingUtilities.invokeAndWait(new Runnable()
         {
+          @Override
           public void run()
           {
             setLoadingFinishedForNewStructureViewers();
@@ -4352,25 +4327,33 @@ public class Jalview2XML
       af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
       String[] renderOrder = new String[jms.getFeatureSettings()
               .getSettingCount()];
-      Hashtable featureGroups = new Hashtable();
-      Hashtable featureColours = new Hashtable();
-      Hashtable featureOrder = new Hashtable();
+      Map<String, FeatureColourI> featureColours = new Hashtable<String, FeatureColourI>();
+      Map<String, Float> featureOrder = new Hashtable<String, Float>();
 
       for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++)
       {
         Setting setting = jms.getFeatureSettings().getSetting(fs);
         if (setting.hasMincolour())
         {
-          GraduatedColor gc = setting.hasMin() ? new GraduatedColor(
-                  new java.awt.Color(setting.getMincolour()),
-                  new java.awt.Color(setting.getColour()),
-                  setting.getMin(), setting.getMax()) : new GraduatedColor(
-                  new java.awt.Color(setting.getMincolour()),
-                  new java.awt.Color(setting.getColour()), 0, 1);
+          FeatureColourI gc = setting.hasMin() ? new FeatureColour(
+                  new Color(setting.getMincolour()), new Color(
+                          setting.getColour()), setting.getMin(),
+                  setting.getMax()) : new FeatureColour(new Color(
+                  setting.getMincolour()), new Color(setting.getColour()),
+                  0, 1);
           if (setting.hasThreshold())
           {
-            gc.setThresh(setting.getThreshold());
-            gc.setThreshType(setting.getThreshstate());
+            gc.setThreshold(setting.getThreshold());
+            int threshstate = setting.getThreshstate();
+            // -1 = None, 0 = Below, 1 = Above threshold
+            if (threshstate == 0)
+            {
+              gc.setBelowThreshold(true);
+            }
+            else if (threshstate == 1)
+            {
+              gc.setAboveThreshold(true);
+            }
           }
           gc.setAutoScaled(true); // default
           if (setting.hasAutoScale())
@@ -4386,8 +4369,8 @@ public class Jalview2XML
         }
         else
         {
-          featureColours.put(setting.getType(),
-                  new java.awt.Color(setting.getColour()));
+          featureColours.put(setting.getType(), new FeatureColour(
+                  new Color(setting.getColour())));
         }
         renderOrder[fs] = setting.getType();
         if (setting.hasOrder())
@@ -4404,7 +4387,7 @@ public class Jalview2XML
           fdi.setVisible(setting.getType());
         }
       }
-      Hashtable fgtable = new Hashtable();
+      Map<String, Boolean> fgtable = new Hashtable<String, Boolean>();
       for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++)
       {
         Group grp = jms.getFeatureSettings().getGroup(gs);
index aa5583c..6bc0374 100755 (executable)
 package jalview.io;
 
 import jalview.analysis.SequenceIdMatcher;
+import jalview.api.FeatureColourI;
 import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceDummy;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.schemes.AnnotationColourGradient;
-import jalview.schemes.GraduatedColor;
+import jalview.schemes.FeatureColour;
 import jalview.schemes.UserColourScheme;
 import jalview.util.Format;
 import jalview.util.MapList;
@@ -277,7 +278,7 @@ public class FeaturesFile extends AlignFile
           }
           else
           {
-            Object colour = null;
+            FeatureColourI colour = null;
             String colscheme = st.nextToken();
             if (colscheme.indexOf("|") > -1
                     || colscheme.trim().equalsIgnoreCase("label"))
@@ -393,7 +394,7 @@ public class FeaturesFile extends AlignFile
               }
               try
               {
-                colour = new jalview.schemes.GraduatedColor(
+                colour = new FeatureColour(
                         new UserColourScheme(mincol).findColour('A'),
                         new UserColourScheme(maxcol).findColour('A'), min,
                         max);
@@ -406,10 +407,8 @@ public class FeaturesFile extends AlignFile
               }
               if (colour != null)
               {
-                ((jalview.schemes.GraduatedColor) colour)
-                        .setColourByLabel(labelCol);
-                ((jalview.schemes.GraduatedColor) colour)
-                        .setAutoScaled(abso == null);
+                colour.setColourByLabel(labelCol);
+                colour.setAutoScaled(abso == null);
                 // add in any additional parameters
                 String ttype = null, tval = null;
                 if (gcol.hasMoreTokens())
@@ -418,18 +417,14 @@ public class FeaturesFile extends AlignFile
                   ttype = gcol.nextToken();
                   if (ttype.toLowerCase().startsWith("below"))
                   {
-                    ((jalview.schemes.GraduatedColor) colour)
-                            .setThreshType(AnnotationColourGradient.BELOW_THRESHOLD);
+                    colour.setBelowThreshold(true);
                   }
                   else if (ttype.toLowerCase().startsWith("above"))
                   {
-                    ((jalview.schemes.GraduatedColor) colour)
-                            .setThreshType(AnnotationColourGradient.ABOVE_THRESHOLD);
+                    colour.setAboveThreshold(true);
                   }
                   else
                   {
-                    ((jalview.schemes.GraduatedColor) colour)
-                            .setThreshType(AnnotationColourGradient.NO_THRESHOLD);
                     if (!ttype.toLowerCase().startsWith("no"))
                     {
                       System.err
@@ -438,14 +433,13 @@ public class FeaturesFile extends AlignFile
                     }
                   }
                 }
-                if (((GraduatedColor) colour).getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
+                if (colour.hasThreshold())
                 {
                   try
                   {
                     gcol.nextToken();
                     tval = gcol.nextToken();
-                    ((jalview.schemes.GraduatedColor) colour)
-                            .setThresh(new Float(tval).floatValue());
+                    colour.setThreshold(new Float(tval).floatValue());
                   } catch (Exception e)
                   {
                     System.err
@@ -470,7 +464,7 @@ public class FeaturesFile extends AlignFile
             else
             {
               UserColourScheme ucs = new UserColourScheme(colscheme);
-              colour = ucs.findColour('A');
+              colour = new FeatureColour(ucs.findColour('A'));
             }
             if (colour != null)
             {
@@ -1176,20 +1170,20 @@ public class FeaturesFile extends AlignFile
    * 
    * @param seqs
    *          source of sequence features
-   * @param visible
+   * @param map
    *          hash of feature types and colours
    * @return features file contents
    */
   public String printJalviewFormat(SequenceI[] seqs,
-          Map<String, Object> visible)
+          Map<String, FeatureColourI> map)
   {
-    return printJalviewFormat(seqs, visible, true, true);
+    return printJalviewFormat(seqs, map, true, true);
   }
 
   /**
    * generate a features file for seqs with colours from visible (if any)
    * 
-   * @param seqs
+   * @param sequences
    *          source of features
    * @param visible
    *          hash of Colours for each feature type
@@ -1200,7 +1194,8 @@ public class FeaturesFile extends AlignFile
    *          of group or type)
    * @return features file contents
    */
-  public String printJalviewFormat(SequenceI[] seqs, Map visible,
+  public String printJalviewFormat(SequenceI[] sequences,
+          Map<String, FeatureColourI> visible,
           boolean visOnly, boolean nonpos)
   {
     StringBuffer out = new StringBuffer();
@@ -1217,54 +1212,46 @@ public class FeaturesFile extends AlignFile
       // write feature colours only if we're given them and we are generating
       // viewed features
       // TODO: decide if feature links should also be written here ?
-      Iterator en = visible.keySet().iterator();
-      String type, color;
+      Iterator<String> en = visible.keySet().iterator();
+      String feature, color;
       while (en.hasNext())
       {
-        type = en.next().toString();
+        feature = en.next();
 
-        if (visible.get(type) instanceof GraduatedColor)
+        FeatureColourI gc = visible.get(feature);
+        if (!gc.isSimpleColour())
         {
-          GraduatedColor gc = (GraduatedColor) visible.get(type);
           color = (gc.isColourByLabel() ? "label|" : "")
-                  + Format.getHexString(gc.getMinColor()) + "|"
-                  + Format.getHexString(gc.getMaxColor())
-                  + (gc.isAutoScale() ? "|" : "|abso|") + gc.getMin() + "|"
+                  + Format.getHexString(gc.getMinColour()) + "|"
+                  + Format.getHexString(gc.getMaxColour())
+                  + (gc.isAutoScaled() ? "|" : "|abso|") + gc.getMin()
+                  + "|"
                   + gc.getMax() + "|";
-          if (gc.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
+          if (gc.isBelowThreshold())
           {
-            if (gc.getThreshType() == AnnotationColourGradient.BELOW_THRESHOLD)
-            {
-              color += "below";
-            }
-            else
-            {
-              if (gc.getThreshType() != AnnotationColourGradient.ABOVE_THRESHOLD)
-              {
-                System.err.println("WARNING: Unsupported threshold type ("
-                        + gc.getThreshType() + ") : Assuming 'above'");
-              }
-              color += "above";
-            }
-            // add the value
-            color += "|" + gc.getThresh();
+            color += "below|" + gc.getThreshold();
+          }
+          else if (gc.isAboveThreshold())
+          {
+            color += "above|" + gc.getThreshold();
           }
           else
           {
             color += "none";
           }
         }
-        else if (visible.get(type) instanceof java.awt.Color)
-        {
-          color = Format.getHexString((java.awt.Color) visible.get(type));
-        }
         else
         {
-          // legacy support for integer objects containing colour triplet values
-          color = Format.getHexString(new java.awt.Color(Integer
-                  .parseInt(visible.get(type).toString())));
+          color = Format.getHexString(gc.getColour());
         }
-        out.append(type);
+        // else
+        // {
+        // // legacy support for integer objects containing colour triplet
+        // values
+        // color = Format.getHexString(new java.awt.Color(Integer
+        // .parseInt(visible.get(type).toString())));
+        // }
+        out.append(feature);
         out.append("\t");
         out.append(color);
         out.append(newline);
@@ -1275,9 +1262,9 @@ public class FeaturesFile extends AlignFile
     int groupIndex = 0;
     boolean isnonpos = false;
 
-    for (int i = 0; i < seqs.length; i++)
+    for (int i = 0; i < sequences.length; i++)
     {
-      next = seqs[i].getSequenceFeatures();
+      next = sequences[i].getSequenceFeatures();
       if (next != null)
       {
         for (int j = 0; j < next.length; j++)
@@ -1316,9 +1303,9 @@ public class FeaturesFile extends AlignFile
         group = null;
       }
 
-      for (int i = 0; i < seqs.length; i++)
+      for (int i = 0; i < sequences.length; i++)
       {
-        next = seqs[i].getSequenceFeatures();
+        next = sequences[i].getSequenceFeatures();
         if (next != null)
         {
           for (int j = 0; j < next.length; j++)
@@ -1382,7 +1369,7 @@ public class FeaturesFile extends AlignFile
 
               out.append("\t");
             }
-            out.append(seqs[i].getName());
+            out.append(sequences[i].getName());
             out.append("\t-1\t");
             out.append(next[j].begin);
             out.append("\t");
@@ -1426,16 +1413,17 @@ public class FeaturesFile extends AlignFile
    * default.
    * 
    * @param seqs
-   * @param visible
+   * @param map
    * @return
    */
-  public String printGFFFormat(SequenceI[] seqs, Map<String, Object> visible)
+  public String printGFFFormat(SequenceI[] seqs,
+          Map<String, FeatureColourI> map)
   {
-    return printGFFFormat(seqs, visible, true, true);
+    return printGFFFormat(seqs, map, true, true);
   }
 
   public String printGFFFormat(SequenceI[] seqs,
-          Map<String, Object> visible, boolean visOnly, boolean nonpos)
+          Map<String, FeatureColourI> map, boolean visOnly, boolean nonpos)
   {
     StringBuffer out = new StringBuffer();
     SequenceFeature[] next;
@@ -1450,7 +1438,7 @@ public class FeaturesFile extends AlignFile
         {
           isnonpos = next[j].begin == 0 && next[j].end == 0;
           if ((!nonpos && isnonpos)
-                  || (!isnonpos && visOnly && !visible
+                  || (!isnonpos && visOnly && !map
                           .containsKey(next[j].type)))
           {
             continue;
@@ -1513,6 +1501,7 @@ public class FeaturesFile extends AlignFile
   /**
    * this is only for the benefit of object polymorphism - method does nothing.
    */
+  @Override
   public void parse()
   {
     // IGNORED
@@ -1523,6 +1512,7 @@ public class FeaturesFile extends AlignFile
    * 
    * @return error message
    */
+  @Override
   public String print()
   {
     return "USE printGFFFormat() or printJalviewFormat()";
index d3a1d09..6573a7f 100644 (file)
@@ -26,8 +26,8 @@ import jalview.datamodel.SequenceI;
 import jalview.util.UrlLink;
 
 import java.util.ArrayList;
-import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
 
 /**
  * generate HTML reports for a sequence
@@ -60,7 +60,7 @@ public class SequenceAnnotationReport
   }
 
   public void appendFeatures(final StringBuffer tooltipText2, int rpos,
-          List<SequenceFeature> features, Hashtable minmax)
+          List<SequenceFeature> features, Map<String, float[][]> map)
   {
     String tmpString;
     if (features != null)
@@ -150,8 +150,8 @@ public class SequenceAnnotationReport
             // check score should be shown
             if (!Float.isNaN(feature.getScore()))
             {
-              float[][] rng = (minmax == null) ? null : ((float[][]) minmax
-                      .get(feature.getType()));
+              float[][] rng = (map == null) ? null : (map.get(feature
+                      .getType()));
               if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
               {
                 tooltipText2.append(" Score=" + feature.getScore());
@@ -321,7 +321,7 @@ public class SequenceAnnotationReport
 
   public void createSequenceAnnotationReport(final StringBuffer tip,
           SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
-          Hashtable minmax)
+          Map<String, float[][]> minmax)
   {
     createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats,
             true, minmax);
@@ -329,7 +329,7 @@ public class SequenceAnnotationReport
 
   public void createSequenceAnnotationReport(final StringBuffer tip,
           SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
-          boolean tableWrap, Hashtable minmax)
+          boolean tableWrap, Map<String, float[][]> map)
   {
     String tmp;
     tip.append("<i>");
@@ -369,7 +369,7 @@ public class SequenceAnnotationReport
           int sz = -tip.length();
           List<SequenceFeature> tfeat = new ArrayList<SequenceFeature>();
           tfeat.add(features[i]);
-          appendFeatures(tip, 0, tfeat, minmax);
+          appendFeatures(tip, 0, tfeat, map);
           sz += tip.length();
           maxWidth = Math.max(maxWidth, sz);
         }
index 26bc895..bc00cc4 100644 (file)
@@ -50,6 +50,8 @@ public class FeatureRenderer extends
 
   boolean av_validCharWidth, av_isShowSeqFeatureHeight;
 
+  private Integer currentColour;
+
   protected void updateAvConfig()
   {
     av_charHeight = av.getCharHeight();
@@ -168,14 +170,15 @@ public class FeatureRenderer extends
 
   BufferedImage offscreenImage;
 
+  @Override
   public Color findFeatureColour(Color initialCol, SequenceI seq, int res)
   {
     return new Color(findFeatureColour(initialCol.getRGB(), seq, res));
   }
 
   /**
-   * This is used by the Molecule Viewer and Overview to get the accurate
-   * colourof the rendered sequence
+   * This is used by the Molecule Viewer and Overview to get the accurate colour
+   * of the rendered sequence
    */
   public synchronized int findFeatureColour(int initialCol,
           final SequenceI seq, int column)
@@ -245,7 +248,7 @@ public class FeatureRenderer extends
       }
       else
       {
-        return ((Integer) currentColour).intValue();
+        return currentColour.intValue();
       }
     }
 
@@ -415,6 +418,7 @@ public class FeatureRenderer extends
    * discover and display.
    * 
    */
+  @Override
   public void featuresAdded()
   {
     lastSeq = null;
diff --git a/src/jalview/schemes/FeatureColour.java b/src/jalview/schemes/FeatureColour.java
new file mode 100644 (file)
index 0000000..ce382c3
--- /dev/null
@@ -0,0 +1,421 @@
+package jalview.schemes;
+
+import jalview.api.FeatureColourI;
+import jalview.datamodel.SequenceFeature;
+
+import java.awt.Color;
+
+/**
+ * A class that wraps either a simple colour or a graduated colour
+ */
+public class FeatureColour implements FeatureColourI
+{
+  final private Color colour;
+
+  final private Color minColour;
+
+  final private Color maxColour;
+
+  private boolean graduatedColour;
+
+  private boolean colourByLabel;
+
+  private float threshold;
+
+  private float base;
+
+  private float range;
+
+  private boolean belowThreshold;
+
+  private boolean aboveThreshold;
+
+  private boolean thresholdIsMinOrMax;
+
+  private boolean isHighToLow;
+
+  private boolean autoScaled;
+
+  final private float minRed;
+
+  final private float minGreen;
+
+  final private float minBlue;
+
+  final private float deltaRed;
+
+  final private float deltaGreen;
+
+  final private float deltaBlue;
+
+  /**
+   * Default constructor
+   */
+  public FeatureColour()
+  {
+    this((Color) null);
+  }
+
+  /**
+   * Constructor given a simple colour
+   * 
+   * @param c
+   */
+  public FeatureColour(Color c)
+  {
+    minColour = null;
+    maxColour = null;
+    minRed = 0f;
+    minGreen = 0f;
+    minBlue = 0f;
+    deltaRed = 0f;
+    deltaGreen = 0f;
+    deltaBlue = 0f;
+    colour = c;
+  }
+
+  /**
+   * Constructor given a colour range and a score range
+   * 
+   * @param low
+   * @param high
+   * @param min
+   * @param max
+   */
+  public FeatureColour(Color low, Color high, float min, float max)
+  {
+    graduatedColour = true;
+    colour = null;
+    minColour = low;
+    maxColour = high;
+    threshold = Float.NaN;
+    isHighToLow = min >= max;
+    minRed = low.getRed() / 255f;
+    minGreen = low.getGreen() / 255f;
+    minBlue = low.getBlue() / 255f;
+    deltaRed = (high.getRed() / 255f) - minRed;
+    deltaGreen = (high.getGreen() / 255f) - minGreen;
+    deltaBlue = (high.getBlue() / 255f) - minBlue;
+    if (isHighToLow)
+    {
+      base = max;
+      range = min - max;
+    }
+    else
+    {
+      base = min;
+      range = max - min;
+    }
+  }
+
+  /**
+   * Copy constructor
+   * 
+   * @param fc
+   */
+  public FeatureColour(FeatureColour fc)
+  {
+    colour = fc.colour;
+    minColour = fc.minColour;
+    maxColour = fc.maxColour;
+    minRed = fc.minRed;
+    minGreen = fc.minGreen;
+    minBlue = fc.minBlue;
+    deltaRed = fc.deltaRed;
+    deltaGreen = fc.deltaGreen;
+    deltaBlue = fc.deltaBlue;
+    base = fc.base;
+    range = fc.range;
+    isHighToLow = fc.isHighToLow;
+    setAboveThreshold(fc.isAboveThreshold());
+    setBelowThreshold(fc.isBelowThreshold());
+    setThreshold(fc.getThreshold());
+    setAutoScaled(fc.isAutoScaled());
+    setColourByLabel(fc.isColourByLabel());
+  }
+  
+  /**
+   * Copy constructor with new min/max ranges
+   * @param fc
+   * @param min
+   * @param max
+   */
+  public FeatureColour(FeatureColour fc, float min, float max)
+  {
+    this(fc);
+    graduatedColour = true;
+    updateBounds(min, max);
+  }
+
+  @Override
+  public boolean isGraduatedColour()
+  {
+    return graduatedColour;
+  }
+
+  /**
+   * Sets the 'graduated colour' flag. If true, also sets 'colour by label' to
+   * false.
+   */
+  @Override
+  public void setGraduatedColour(boolean b)
+  {
+    graduatedColour = b;
+    if (b)
+    {
+      setColourByLabel(false);
+    }
+  }
+
+  @Override
+  public Color getColour()
+  {
+    return colour;
+  }
+
+  @Override
+  public Color getMinColour()
+  {
+    return minColour;
+  }
+
+  @Override
+  public Color getMaxColour()
+  {
+    return maxColour;
+  }
+
+  @Override
+  public boolean isColourByLabel()
+  {
+    return colourByLabel;
+  }
+
+  /**
+   * Sets the 'colour by label' flag. If true, also sets 'graduated colour' to
+   * false.
+   */
+  @Override
+  public void setColourByLabel(boolean b)
+  {
+    colourByLabel = b;
+    if (b)
+    {
+      setGraduatedColour(false);
+    }
+  }
+  @Override
+  public boolean isBelowThreshold()
+  {
+    return belowThreshold;
+  }
+
+  @Override
+  public void setBelowThreshold(boolean b)
+  {
+    belowThreshold = b;
+    if (b)
+    {
+      setAboveThreshold(false);
+    }
+  }
+
+  @Override
+  public boolean isAboveThreshold()
+  {
+    return aboveThreshold;
+  }
+
+  @Override
+  public void setAboveThreshold(boolean b)
+  {
+    aboveThreshold = b;
+    if (b)
+    {
+      setBelowThreshold(false);
+    }
+  }
+
+  @Override
+  public boolean isThresholdMinMax()
+  {
+    return thresholdIsMinOrMax;
+  }
+
+  @Override
+  public void setThresholdMinMax(boolean b)
+  {
+    thresholdIsMinOrMax = b;
+  }
+
+  @Override
+  public float getThreshold()
+  {
+    return threshold;
+  }
+
+  @Override
+  public void setThreshold(float f)
+  {
+    threshold = f;
+  }
+
+  @Override
+  public boolean isAutoScaled()
+  {
+    return autoScaled;
+  }
+
+  @Override
+  public void setAutoScaled(boolean b)
+  {
+    this.autoScaled = b;
+  }
+
+  /**
+   * Updates the base and range appropriately for the given minmax range
+   * 
+   * @param min
+   * @param max
+   */
+  @Override
+  public void updateBounds(float min, float max)
+  {
+    if (max < min)
+    {
+      base = max;
+      range = min - max;
+      isHighToLow = true;
+    }
+    else
+    {
+      base = min;
+      range = max - min;
+      isHighToLow = false;
+    }
+  }
+
+  /**
+   * Returns the colour for the given instance of the feature. This may be a
+   * simple colour, a colour generated from the feature description (if
+   * isColourByLabel()), or a colour derived from the feature score (if
+   * isGraduatedColour()).
+   * 
+   * @param feature
+   * @return
+   */
+  @Override
+  public Color getColor(SequenceFeature feature)
+  {
+    if (isColourByLabel())
+    {
+      return UserColourScheme
+              .createColourFromName(feature.getDescription());
+    }
+
+    if (!isGraduatedColour())
+    {
+      return getColour();
+    }
+
+    // todo should we check for above/below threshold here?
+    if (range == 0.0)
+    {
+      return getMaxColour();
+    }
+    float scr = feature.getScore();
+    if (Float.isNaN(scr))
+    {
+      return getMinColour();
+    }
+    float scl = (scr - base) / range;
+    if (isHighToLow)
+    {
+      scl = -scl;
+    }
+    if (scl < 0f)
+    {
+      scl = 0f;
+    }
+    if (scl > 1f)
+    {
+      scl = 1f;
+    }
+    return new Color(minRed + scl * deltaRed, minGreen + scl * deltaGreen, minBlue + scl * deltaBlue);
+  }
+
+  /**
+   * Returns the maximum score of the graduated colour range
+   * 
+   * @return
+   */
+  @Override
+  public float getMax()
+  {
+    // regenerate the original values passed in to the constructor
+    return (isHighToLow) ? base : (base + range);
+  }
+
+  /**
+   * Returns the minimum score of the graduated colour range
+   * 
+   * @return
+   */
+  @Override
+  public float getMin()
+  {
+    // regenerate the original value passed in to the constructor
+    return (isHighToLow) ? (base + range) : base;
+  }
+
+  /**
+   * Answers true if the feature has a simple colour, or is coloured by label,
+   * or has a graduated colour and the score of this feature instance is within
+   * the range to render (if any), i.e. does not lie below or above any
+   * threshold set.
+   * 
+   * @param feature
+   * @return
+   */
+  @Override
+  public boolean isColored(SequenceFeature feature)
+  {
+    if (isColourByLabel() || !isGraduatedColour())
+    {
+      return true;
+    }
+
+    float val = feature.getScore();
+    if (Float.isNaN(val))
+    {
+      return true;
+    }
+    if (Float.isNaN(this.threshold))
+    {
+      return true;
+    }
+
+    if (isAboveThreshold() && val <= threshold)
+    {
+      return false;
+    }
+    if (isBelowThreshold() && val >= threshold)
+    {
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public boolean isSimpleColour()
+  {
+    return (!isColourByLabel() && !isGraduatedColour());
+  }
+
+  @Override
+  public boolean hasThreshold()
+  {
+    return isAboveThreshold() || isBelowThreshold();
+  }
+
+}
diff --git a/src/jalview/schemes/FeatureColourAdapter.java b/src/jalview/schemes/FeatureColourAdapter.java
deleted file mode 100644 (file)
index a86bee4..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-package jalview.schemes;
-
-import jalview.api.FeatureColourI;
-
-import java.awt.Color;
-
-/**
- * A convenience class with implementations of FeatureColourI methods. Override
- * methods as required in subclasses.
- */
-public class FeatureColourAdapter implements FeatureColourI
-{
-  @Override
-  public boolean isGraduatedColour()
-  {
-    return isColourByLabel() || isAboveThreshold() || isBelowThreshold();
-  }
-
-  @Override
-  public Color getColour()
-  {
-    return Color.BLACK;
-  }
-
-  @Override
-  public Color getMinColour()
-  {
-    return Color.WHITE;
-  }
-
-  @Override
-  public Color getMaxColour()
-  {
-    return Color.BLACK;
-  }
-
-  @Override
-  public boolean isColourByLabel()
-  {
-    return false;
-  }
-
-  @Override
-  public boolean isBelowThreshold()
-  {
-    return false;
-  }
-
-  @Override
-  public boolean isAboveThreshold()
-  {
-    return false;
-  }
-
-  @Override
-  public boolean isThresholdMinMax()
-  {
-    return false;
-  }
-
-  @Override
-  public float getThreshold()
-  {
-    return 0f;
-  }
-
-  @Override
-  public boolean isLowToHigh()
-  {
-    return true;
-  }
-
-}
index 4a90b84..628b514 100644 (file)
@@ -38,7 +38,7 @@ public enum FeatureColourScheme implements FeatureSettingsI
     {
       if (EXON.equals(type))
       {
-        return new FeatureColourAdapter()
+        return new FeatureColour()
         {
           @Override
           public boolean isColourByLabel()
@@ -49,15 +49,7 @@ public enum FeatureColourScheme implements FeatureSettingsI
       }
       if (SEQUENCE_VARIANT.equals(type))
       {
-        return new FeatureColourAdapter()
-        {
-
-          @Override
-          public Color getColour()
-          {
-            return Color.RED;
-          }
-        };
+        return new FeatureColour(Color.RED);
       }
       return null;
     }
index 7aff05a..2498208 100755 (executable)
@@ -136,7 +136,7 @@ public class UserColourScheme extends ResidueColourScheme
 
   }
 
-  public Color createColourFromName(String name)
+  public static Color createColourFromName(String name)
   {
     int r, g, b;
 
index 8db907c..b299624 100644 (file)
 package jalview.viewmodel.seqfeatures;
 
 import jalview.api.AlignViewportI;
+import jalview.api.FeatureColourI;
 import jalview.api.FeaturesDisplayedI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.seqfeatures.FeatureRenderer;
-import jalview.schemes.GraduatedColor;
+import jalview.schemes.FeatureColour;
+import jalview.schemes.UserColourScheme;
 import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.Color;
@@ -50,19 +52,20 @@ public abstract class FeatureRendererModel implements
    */
   protected float transparency = 1.0f;
 
-  protected Map<String, Object> featureColours = new ConcurrentHashMap<String, Object>();
+  protected Map<String, FeatureColourI> featureColours = new ConcurrentHashMap<String, FeatureColourI>();
 
   protected Map<String, Boolean> featureGroups = new ConcurrentHashMap<String, Boolean>();
 
-  protected Object currentColour;
-
   protected String[] renderOrder;
 
+  Map<String, Float> featureOrder = null;
+
   protected PropertyChangeSupport changeSupport = new PropertyChangeSupport(
           this);
 
   protected AlignmentViewport av;
 
+  @Override
   public AlignViewportI getViewport()
   {
     return av;
@@ -188,9 +191,9 @@ public abstract class FeatureRendererModel implements
     renderOrder = neworder;
   }
 
-  protected Hashtable minmax = new Hashtable();
+  protected Map<String, float[][]> minmax = new Hashtable<String, float[][]>();
 
-  public Hashtable getMinMax()
+  public Map<String, float[][]> getMinMax()
   {
     return minmax;
   }
@@ -204,7 +207,7 @@ public abstract class FeatureRendererModel implements
    */
   protected final byte[] normaliseScore(SequenceFeature sequenceFeature)
   {
-    float[] mm = ((float[][]) minmax.get(sequenceFeature.type))[0];
+    float[] mm = minmax.get(sequenceFeature.type)[0];
     final byte[] r = new byte[] { 0, (byte) 255 };
     if (mm != null)
     {
@@ -335,7 +338,7 @@ public abstract class FeatureRendererModel implements
     }
     if (minmax == null)
     {
-      minmax = new Hashtable();
+      minmax = new Hashtable<String, float[][]>();
     }
     AlignmentI alignment = av.getAlignment();
     for (int i = 0; i < alignment.getHeight(); i++)
@@ -390,7 +393,7 @@ public abstract class FeatureRendererModel implements
         if (!Float.isNaN(features[index].score))
         {
           int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
-          float[][] mm = (float[][]) minmax.get(features[index].getType());
+          float[][] mm = minmax.get(features[index].getType());
           if (mm == null)
           {
             mm = new float[][] { null, null };
@@ -439,7 +442,6 @@ public abstract class FeatureRendererModel implements
     List<String> allfeatures = new ArrayList<String>(allFeatures);
     String[] oldRender = renderOrder;
     renderOrder = new String[allfeatures.size()];
-    Object mmrange, fc = null;
     boolean initOrders = (featureOrder == null);
     int opos = 0;
     if (oldRender != null && oldRender.length > 0)
@@ -459,16 +461,13 @@ public abstract class FeatureRendererModel implements
             allfeatures.remove(oldRender[j]);
             if (minmax != null)
             {
-              mmrange = minmax.get(oldRender[j]);
+              float[][] mmrange = minmax.get(oldRender[j]);
               if (mmrange != null)
               {
-                fc = featureColours.get(oldRender[j]);
-                if (fc != null && fc instanceof GraduatedColor
-                        && ((GraduatedColor) fc).isAutoScale())
+                FeatureColourI fc = featureColours.get(oldRender[j]);
+                if (fc != null && !fc.isSimpleColour() && fc.isAutoScaled())
                 {
-                  ((GraduatedColor) fc).updateBounds(
-                          ((float[][]) mmrange)[0][0],
-                          ((float[][]) mmrange)[0][1]);
+                  fc.updateBounds(mmrange[0][0], mmrange[0][1]);
                 }
               }
             }
@@ -492,15 +491,13 @@ public abstract class FeatureRendererModel implements
       if (minmax != null)
       {
         // update from new features minmax if necessary
-        mmrange = minmax.get(newf[i]);
+        float[][] mmrange = minmax.get(newf[i]);
         if (mmrange != null)
         {
-          fc = featureColours.get(newf[i]);
-          if (fc != null && fc instanceof GraduatedColor
-                  && ((GraduatedColor) fc).isAutoScale())
+          FeatureColourI fc = featureColours.get(newf[i]);
+          if (fc != null && !fc.isSimpleColour() && fc.isAutoScaled())
           {
-            ((GraduatedColor) fc).updateBounds(((float[][]) mmrange)[0][0],
-                    ((float[][]) mmrange)[0][1]);
+            fc.updateBounds(mmrange[0][0], mmrange[0][1]);
           }
         }
       }
@@ -512,7 +509,7 @@ public abstract class FeatureRendererModel implements
         setOrder(newf[i], i / (float) denom);
       }
       // set order from newly found feature from persisted ordering.
-      sortOrder[i] = 2 - ((Float) featureOrder.get(newf[i])).floatValue();
+      sortOrder[i] = 2 - featureOrder.get(newf[i]).floatValue();
       if (i < iSize)
       {
         // only sort if we need to
@@ -530,51 +527,25 @@ public abstract class FeatureRendererModel implements
 
   /**
    * 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
+   * java.awt.Color for a featureType with no existing colourscheme.
    * 
    * @param featureType
-   * @return java.awt.Color or GraduatedColor
+   * @return
    */
-  public Object getFeatureStyle(String featureType)
+  @Override
+  public FeatureColourI getFeatureStyle(String featureType)
   {
-    Object fc = featureColours.get(featureType);
+    FeatureColourI fc = featureColours.get(featureType);
     if (fc == null)
     {
-      jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
-      Color col = ucs.createColourFromName(featureType);
-      featureColours.put(featureType, fc = col);
+      Color col = UserColourScheme.createColourFromName(featureType);
+      fc = new FeatureColour(col);
+      featureColours.put(featureType, fc);
     }
     return fc;
   }
 
   /**
-   * return a nominal colour for this feature
-   * 
-   * @param featureType
-   * @return standard color, or maximum colour for graduated colourscheme
-   */
-  public Color getColour(String featureType)
-  {
-    Object fc = getFeatureStyle(featureType);
-
-    if (fc instanceof Color)
-    {
-      return (Color) fc;
-    }
-    else
-    {
-      if (fc instanceof GraduatedColor)
-      {
-        return ((GraduatedColor) fc).getMaxColor();
-      }
-    }
-    throw new Error("Implementation Error: Unrecognised render object "
-            + fc.getClass() + " for features of type " + featureType);
-  }
-
-  /**
    * calculate the render colour for a specific feature using current feature
    * settings.
    * 
@@ -583,33 +554,14 @@ public abstract class FeatureRendererModel implements
    */
   public Color getColour(SequenceFeature feature)
   {
-    Object fc = getFeatureStyle(feature.getType());
-    if (fc instanceof Color)
-    {
-      return (Color) fc;
-    }
-    else
-    {
-      if (fc instanceof GraduatedColor)
-      {
-        return ((GraduatedColor) fc).findColor(feature);
-      }
-    }
-    throw new Error("Implementation Error: Unrecognised render object "
-            + fc.getClass() + " for features of type " + feature.getType());
+    FeatureColourI fc = getFeatureStyle(feature.getType());
+    return fc.getColor(feature);
   }
 
   protected boolean showFeature(SequenceFeature sequenceFeature)
   {
-    Object fc = getFeatureStyle(sequenceFeature.type);
-    if (fc instanceof GraduatedColor)
-    {
-      return ((GraduatedColor) fc).isColored(sequenceFeature);
-    }
-    else
-    {
-      return true;
-    }
+    FeatureColourI fc = getFeatureStyle(sequenceFeature.type);
+    return fc.isColored(sequenceFeature);
   }
 
   protected boolean showFeatureOfType(String type)
@@ -617,14 +569,9 @@ public abstract class FeatureRendererModel implements
     return av.getFeaturesDisplayed().isVisible(type);
   }
 
-  public void setColour(String featureType, Object col)
+  @Override
+  public void setColour(String featureType, FeatureColourI 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);
     }
@@ -640,8 +587,6 @@ public abstract class FeatureRendererModel implements
     return transparency;
   }
 
-  Map featureOrder = null;
-
   /**
    * analogous to colour - store a normalized ordering for all feature types in
    * this rendering context.
@@ -656,7 +601,7 @@ public abstract class FeatureRendererModel implements
   {
     if (featureOrder == null)
     {
-      featureOrder = new Hashtable();
+      featureOrder = new Hashtable<String, Float>();
     }
     featureOrder.put(type, new Float(position));
     return position;
@@ -674,14 +619,14 @@ public abstract class FeatureRendererModel implements
     {
       if (featureOrder.containsKey(type))
       {
-        return ((Float) featureOrder.get(type)).floatValue();
+        return featureOrder.get(type).floatValue();
       }
     }
     return -1;
   }
 
   @Override
-  public Map<String, Object> getFeatureColours()
+  public Map<String, FeatureColourI> getFeatureColours()
   {
     return featureColours;
   }
@@ -736,8 +681,7 @@ public abstract class FeatureRendererModel implements
       for (int i = 0; i < data.length; i++)
       {
         String type = data[i][0].toString();
-        setColour(type, data[i][1]); // todo : typesafety - feature color
-        // interface object
+        setColour(type, (FeatureColourI) data[i][1]);
         if (((Boolean) data[i][2]).booleanValue())
         {
           av_featuresdisplayed.setVisible(type);
@@ -767,7 +711,7 @@ public abstract class FeatureRendererModel implements
     changeSupport.removePropertyChangeListener(listener);
   }
 
-  public Set getAllFeatureColours()
+  public Set<String> getAllFeatureColours()
   {
     return featureColours.keySet();
   }
@@ -831,13 +775,13 @@ public abstract class FeatureRendererModel implements
    * @return list of groups
    */
   @Override
-  public List getGroups(boolean visible)
+  public List<String> getGroups(boolean visible)
   {
     if (featureGroups != null)
     {
-      ArrayList gp = new ArrayList();
+      List<String> gp = new ArrayList<String>();
 
-      for (Object grp : featureGroups.keySet())
+      for (String grp : featureGroups.keySet())
       {
         Boolean state = featureGroups.get(grp);
         if (state.booleanValue() == visible)
@@ -879,19 +823,19 @@ public abstract class FeatureRendererModel implements
   }
 
   @Override
-  public Hashtable getDisplayedFeatureCols()
+  public Map<String, FeatureColourI> getDisplayedFeatureCols()
   {
-    Hashtable fcols = new Hashtable();
+    Map<String, FeatureColourI> fcols = new Hashtable<String, FeatureColourI>();
     if (getViewport().getFeaturesDisplayed() == null)
     {
       return fcols;
     }
-    Iterator<String> en = getViewport().getFeaturesDisplayed()
+    Iterator<String> features = getViewport().getFeaturesDisplayed()
             .getVisibleFeatures();
-    while (en.hasNext())
+    while (features.hasNext())
     {
-      String col = en.next();
-      fcols.put(col, getColour(col));
+      String feature = features.next();
+      fcols.put(feature, getFeatureStyle(feature));
     }
     return fcols;
   }
index 1985b6d..dc2ae11 100644 (file)
  */
 package jalview.viewmodel.seqfeatures;
 
-import jalview.schemes.GraduatedColor;
+import jalview.api.FeatureColourI;
+import jalview.schemes.FeatureColour;
 
 import java.util.Arrays;
-import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -32,24 +32,33 @@ public class FeatureRendererSettings implements Cloneable
 {
   String[] renderOrder;
 
-  Map featureGroups;
+  /*
+   * map of {groupName, isDisplayed}
+   */
+  Map<String, Boolean> featureGroups;
 
-  Map featureColours;
+  /*
+   * map of {featureType, colourScheme}
+   */
+  Map<String, FeatureColourI> featureColours;
 
   float transparency;
 
-  Map featureOrder;
+  Map<String, Float> featureOrder;
 
   public FeatureRendererSettings(String[] renderOrder,
-          Hashtable featureGroups, Hashtable featureColours,
-          float transparency, Hashtable featureOrder)
+          Map<String, Boolean> featureGroups,
+          Map<String, FeatureColourI> featureColours, float transparency,
+          Map<String, Float> featureOrder)
   {
     super();
     this.renderOrder = Arrays.copyOf(renderOrder, renderOrder.length);
-    this.featureGroups = new ConcurrentHashMap(featureGroups);
-    this.featureColours = new ConcurrentHashMap(featureColours);
+    this.featureGroups = new ConcurrentHashMap<String, Boolean>(
+            featureGroups);
+    this.featureColours = new ConcurrentHashMap<String, FeatureColourI>(
+            featureColours);
     this.transparency = transparency;
-    this.featureOrder = new ConcurrentHashMap(featureOrder);
+    this.featureOrder = new ConcurrentHashMap<String, Float>(featureOrder);
   }
 
   /**
@@ -61,9 +70,9 @@ public class FeatureRendererSettings implements Cloneable
           jalview.viewmodel.seqfeatures.FeatureRendererModel fr)
   {
     renderOrder = null;
-    featureGroups = new ConcurrentHashMap();
-    featureColours = new ConcurrentHashMap();
-    featureOrder = new ConcurrentHashMap();
+    featureGroups = new ConcurrentHashMap<String, Boolean>();
+    featureColours = new ConcurrentHashMap<String, FeatureColourI>();
+    featureOrder = new ConcurrentHashMap<String, Float>();
     if (fr.renderOrder != null)
     {
       this.renderOrder = new String[fr.renderOrder.length];
@@ -72,26 +81,30 @@ public class FeatureRendererSettings implements Cloneable
     }
     if (fr.featureGroups != null)
     {
-      this.featureGroups = new ConcurrentHashMap(fr.featureGroups);
+      this.featureGroups = new ConcurrentHashMap<String, Boolean>(
+              fr.featureGroups);
     }
     if (fr.featureColours != null)
     {
-      this.featureColours = new ConcurrentHashMap(fr.featureColours);
+      this.featureColours = new ConcurrentHashMap<String, FeatureColourI>(
+              fr.featureColours);
     }
-    Iterator en = fr.featureColours.keySet().iterator();
+    Iterator<String> en = fr.featureColours.keySet().iterator();
     while (en.hasNext())
     {
-      Object next = en.next();
-      Object val = featureColours.get(next);
-      if (val instanceof GraduatedColor)
+      String next = en.next();
+      FeatureColourI val = featureColours.get(next);
+      // if (val instanceof GraduatedColor)
+      if (val.isGraduatedColour() || val.isColourByLabel()) // why this test?
       {
-        featureColours.put(next, new GraduatedColor((GraduatedColor) val));
+        featureColours.put(next, new FeatureColour((FeatureColour) val));
       }
     }
     this.transparency = fr.transparency;
     if (fr.featureOrder != null)
     {
-      this.featureOrder = new ConcurrentHashMap(fr.featureOrder);
+      this.featureOrder = new ConcurrentHashMap<String, Float>(
+              fr.featureOrder);
     }
   }
 }
index f929b1e..71b6c91 100644 (file)
 package jalview.ws.jws2;
 
 import jalview.api.AlignCalcWorkerI;
+import jalview.api.FeatureColourI;
 import jalview.bin.Cache;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.GraphLine;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
-import jalview.schemes.GraduatedColor;
+import jalview.schemes.FeatureColour;
 import jalview.schemes.UserColourScheme;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.params.WsParamSetI;
@@ -308,8 +309,8 @@ public class AADisorderClient extends JabawsCalcWorker implements
                 annot.description += "<br/>" + threshNote;
               }
               annot.description += "</html>";
-              Color col = new UserColourScheme(typeName)
-                      .createColourFromName(typeName + scr.getMethod());
+              Color col = UserColourScheme.createColourFromName(typeName
+                      + scr.getMethod());
               for (int p = 0, ps = annot.annotations.length; p < ps; p++)
               {
                 if (annot.annotations[p] != null)
@@ -337,13 +338,13 @@ public class AADisorderClient extends JabawsCalcWorker implements
                   .cloneFeatureRenderer();
           for (String ft : fc.keySet())
           {
-            Object gc = fr.getFeatureStyle(ft);
-            if (gc instanceof Color)
+            FeatureColourI gc = fr.getFeatureStyle(ft);
+            if (gc.isSimpleColour())
             {
               // set graduated color as fading to white for minimum, and
               // autoscaling to values on alignment
-              GraduatedColor ggc = new GraduatedColor(Color.white,
-                      (Color) gc, Float.MIN_VALUE, Float.MAX_VALUE);
+              FeatureColourI ggc = new FeatureColour(Color.white,
+                      gc.getColour(), Float.MIN_VALUE, Float.MAX_VALUE);
               ggc.setAutoScaled(true);
               fr.setColour(ft, ggc);
             }
index 520d1bb..d65f9df 100644 (file)
@@ -24,6 +24,7 @@ import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertNotNull;
 import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.api.FeatureColourI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceFeature;
 import jalview.gui.AlignFrame;
@@ -76,7 +77,7 @@ public class FeaturesFileTest
     File f = new File("examples/uniref50.fa");
     AlignmentI al = readAlignmentFile(f);
     AlignFrame af = new AlignFrame(al, 500, 500);
-    Map<String, Object> colours = af.getFeatureRenderer()
+    Map<String, FeatureColourI> colours = af.getFeatureRenderer()
             .getFeatureColours();
     FeaturesFile featuresFile = new FeaturesFile(
             "examples/exampleFeatures.txt", FormatAdapter.FILE);
@@ -89,8 +90,8 @@ public class FeaturesFileTest
      */
     colours = af.getFeatureRenderer().getFeatureColours();
     assertEquals("26 feature group colours not found", 26, colours.size());
-    assertEquals(colours.get("Cath"), new Color(0x93b1d1));
-    assertEquals(colours.get("ASX-MOTIF"), new Color(0x6addbb));
+    assertEquals(colours.get("Cath").getColour(), new Color(0x93b1d1));
+    assertEquals(colours.get("ASX-MOTIF").getColour(), new Color(0x6addbb));
 
     /*
      * verify (some) features on sequences
diff --git a/test/jalview/schemes/FeatureColourTest.java b/test/jalview/schemes/FeatureColourTest.java
new file mode 100644 (file)
index 0000000..81357fa
--- /dev/null
@@ -0,0 +1,115 @@
+package jalview.schemes;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
+import jalview.datamodel.SequenceFeature;
+
+import java.awt.Color;
+
+import org.testng.annotations.Test;
+
+public class FeatureColourTest
+{
+  @Test(groups = { "Functional" })
+  public void testIsColored_simpleColour()
+  {
+    FeatureColour fc = new FeatureColour(Color.RED);
+    assertTrue(fc.isColored(new SequenceFeature()));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testIsColored_colourByLabel()
+  {
+    FeatureColour fc = new FeatureColour();
+    fc.setColourByLabel(true);
+    assertTrue(fc.isColored(new SequenceFeature()));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testIsColored_aboveThreshold()
+  {
+    // graduated colour range from score 20 to 100
+    FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 20f,
+            100f);
+
+    // score 0 is adjusted to bottom of range
+    SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 0f,
+            null);
+    assertTrue(fc.isColored(sf));
+    assertEquals(Color.WHITE, fc.getColor(sf));
+
+    // score 120 is adjusted to top of range
+    sf.setScore(120f);
+    assertEquals(Color.BLACK, fc.getColor(sf));
+
+    // value below threshold is still rendered
+    // setting threshold has no effect yet...
+    fc.setThreshold(60f);
+    sf.setScore(36f);
+    assertTrue(fc.isColored(sf));
+    assertEquals(new Color(204, 204, 204), fc.getColor(sf));
+
+    // now apply threshold:
+    fc.setAboveThreshold(true);
+    assertFalse(fc.isColored(sf));
+    // colour is still returned though ?!?
+    assertEquals(new Color(204, 204, 204), fc.getColor(sf));
+
+    sf.setScore(84); // above threshold now
+    assertTrue(fc.isColored(sf));
+    assertEquals(new Color(51, 51, 51), fc.getColor(sf));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetColor_simpleColour()
+  {
+    FeatureColour fc = new FeatureColour(Color.RED);
+    assertEquals(Color.RED, fc.getColor(new SequenceFeature()));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetColor_colourByLabel()
+  {
+    FeatureColour fc = new FeatureColour();
+    fc.setColourByLabel(true);
+    SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 1f,
+            null);
+    Color expected = UserColourScheme.createColourFromName("desc");
+    assertEquals(expected, fc.getColor(sf));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetColor_Graduated()
+  {
+    // graduated colour from score 0 to 100, gray(128, 128, 128) to red(255, 0, 0)
+    FeatureColour fc = new FeatureColour(Color.GRAY, Color.RED, 0f, 100f);
+    // feature score is 75 which is 3/4 of the way from GRAY to RED
+    SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 75f,
+            null);
+    // the colour gradient is computed in float values from 0-1 (where 1 == 255)
+    float red = 128 / 255f + 3 / 4f * (255 - 128) / 255f;
+    float green = 128 / 255f + 3 / 4f * (0 - 128) / 255f;
+    float blue = 128 / 255f + 3 / 4f * (0 - 128) / 255f;
+    Color expected = new Color(red, green, blue);
+    assertEquals(expected, fc.getColor(sf));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetColor_belowThreshold()
+  {
+    // gradient from [50, 150] from WHITE(255, 255, 255) to BLACK(0, 0, 0)
+    FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 50f,
+            150f);
+    SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 70f,
+            null);
+    fc.setThreshold(100f); // ignore for now
+    assertTrue(fc.isColored(sf));
+    assertEquals(new Color(204, 204, 204), fc.getColor(sf));
+
+    fc.setAboveThreshold(true); // feature lies below threshold
+    assertFalse(fc.isColored(sf));
+    assertEquals(new Color(204, 204, 204), fc.getColor(sf));
+  }
+}