Merge branch 'documentation/JAL-2418_release2102' into develop
[jalview.git] / src / jalview / viewmodel / seqfeatures / FeatureRendererModel.java
index 4ac4804..40f38b6 100644 (file)
@@ -28,7 +28,7 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.seqfeatures.FeatureRenderer;
 import jalview.schemes.FeatureColour;
-import jalview.schemes.UserColourScheme;
+import jalview.util.ColorUtils;
 
 import java.awt.Color;
 import java.beans.PropertyChangeListener;
@@ -36,6 +36,7 @@ import java.beans.PropertyChangeSupport;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
@@ -288,8 +289,12 @@ public abstract class FeatureRendererModel implements
           continue;
         }
 
-        if ((features[i].getBegin() <= res)
-                && (features[i].getEnd() >= res))
+        // check if start/end are at res, and if not a contact feature, that res
+        // lies between start and end
+        if ((features[i].getBegin() == res || features[i].getEnd() == res)
+                || (!features[i].isContactFeature()
+                        && (features[i].getBegin() < res) && (features[i]
+                        .getEnd() >= res)))
         {
           tmp.add(features[i]);
         }
@@ -340,6 +345,8 @@ public abstract class FeatureRendererModel implements
     {
       minmax = new Hashtable<String, float[][]>();
     }
+
+    Set<String> oldGroups = new HashSet<String>(featureGroups.keySet());
     AlignmentI alignment = av.getAlignment();
     for (int i = 0; i < alignment.getHeight(); i++)
     {
@@ -354,9 +361,10 @@ public abstract class FeatureRendererModel implements
       int index = 0;
       while (index < features.length)
       {
+        String fgrp = features[index].getFeatureGroup();
+        oldGroups.remove(fgrp);
         if (!featuresDisplayed.isRegistered(features[index].getType()))
         {
-          String fgrp = features[index].getFeatureGroup();
           if (fgrp != null)
           {
             Boolean groupDisplayed = featureGroups.get(fgrp);
@@ -420,6 +428,16 @@ public abstract class FeatureRendererModel implements
         index++;
       }
     }
+
+    /*
+     * oldGroups now consists of groups that no longer 
+     * have any feature in them - remove these
+     */
+    for (String grp : oldGroups)
+    {
+      featureGroups.remove(grp);
+    }
+
     updateRenderOrder(allfeatures);
     findingFeatures = false;
   }
@@ -538,7 +556,7 @@ public abstract class FeatureRendererModel implements
     FeatureColourI fc = featureColours.get(featureType);
     if (fc == null)
     {
-      Color col = UserColourScheme.createColourFromName(featureType);
+      Color col = ColorUtils.createColourFromName(featureType);
       fc = new FeatureColour(col);
       featureColours.put(featureType, fc);
     }
@@ -546,27 +564,44 @@ public abstract class FeatureRendererModel implements
   }
 
   /**
-   * calculate the render colour for a specific feature using current feature
-   * settings.
+   * Returns the configured colour for a particular feature instance. This
+   * includes calculation of 'colour by label', or of a graduated score colour,
+   * if applicable. It does not take into account feature visibility or colour
+   * transparency.
    * 
    * @param feature
-   * @return render colour for the given feature
+   * @return
    */
   public Color getColour(SequenceFeature feature)
   {
     FeatureColourI fc = getFeatureStyle(feature.getType());
-    return fc.getColor(feature);
+    return fc.isColored(feature) ? fc.getColor(feature) : null;
   }
 
+  /**
+   * Answers true unless the feature has a score value which lies outside a
+   * minimum or maximum threshold configured for colouring. This method does not
+   * check feature type or group visibility.
+   * 
+   * @param sequenceFeature
+   * @return
+   */
   protected boolean showFeature(SequenceFeature sequenceFeature)
   {
     FeatureColourI fc = getFeatureStyle(sequenceFeature.type);
     return fc.isColored(sequenceFeature);
   }
 
+  /**
+   * Answers true if the feature type is currently selected to be displayed,
+   * else false
+   * 
+   * @param type
+   * @return
+   */
   protected boolean showFeatureOfType(String type)
   {
-    return av.getFeaturesDisplayed().isVisible(type);
+    return type == null ? false : av.getFeaturesDisplayed().isVisible(type);
   }
 
   @Override
@@ -575,11 +610,13 @@ public abstract class FeatureRendererModel implements
     featureColours.put(featureType, col);
   }
 
+  @Override
   public void setTransparency(float value)
   {
     transparency = value;
   }
 
+  @Override
   public float getTransparency()
   {
     return transparency;
@@ -811,7 +848,7 @@ public abstract class FeatureRendererModel implements
    * @return list of groups
    */
   @Override
-  public List getGroups(boolean visible)
+  public List<String> getGroups(boolean visible)
   {
     if (featureGroups != null)
     {