Merge branch 'task/JAL-3763_newDatasetForCds' into merge/develop_task/JAL-3763_newDat...
[jalview.git] / src / jalview / viewmodel / seqfeatures / FeatureRendererModel.java
index 9e707f3..eb1030c 100644 (file)
  */
 package jalview.viewmodel.seqfeatures;
 
+import java.awt.Color;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
 import jalview.api.AlignViewportI;
 import jalview.api.FeatureColourI;
 import jalview.api.FeaturesDisplayedI;
 import jalview.datamodel.AlignedCodonFrame;
+import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.MappedFeatures;
-import jalview.datamodel.Mapping;
 import jalview.datamodel.SearchResultMatchI;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SearchResultsI;
@@ -37,21 +52,7 @@ import jalview.datamodel.features.SequenceFeatures;
 import jalview.renderer.seqfeatures.FeatureRenderer;
 import jalview.schemes.FeatureColour;
 import jalview.util.ColorUtils;
-
-import java.awt.Color;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
+import jalview.util.Platform;
 
 public abstract class FeatureRendererModel
         implements jalview.api.FeatureRenderer
@@ -103,11 +104,11 @@ public abstract class FeatureRendererModel
 
   Map<String, Float> featureOrder = null;
 
-  protected PropertyChangeSupport changeSupport = new PropertyChangeSupport(
-          this);
-
   protected AlignViewportI av;
 
+  private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
+          this);
+
   @Override
   public AlignViewportI getViewport()
   {
@@ -300,13 +301,19 @@ public abstract class FeatureRendererModel
       {
         firing = Boolean.TRUE;
         findAllFeatures(true); // add all new features as visible
-        changeSupport.firePropertyChange("changeSupport", null, null);
+        notifyFeaturesChanged();
         firing = Boolean.FALSE;
       }
     }
   }
 
   @Override
+  public void notifyFeaturesChanged()
+  {
+    changeSupport.firePropertyChange("changeSupport", null, null);
+  }
+
+  @Override
   public List<SequenceFeature> findFeaturesAtColumn(SequenceI sequence, int column)
   {
     /*
@@ -1046,6 +1053,14 @@ public abstract class FeatureRendererModel
   public void filterFeaturesForDisplay(List<SequenceFeature> features)
   {
     /*
+     * fudge: JalviewJS's IntervalStore lacks the sort method called :-(
+     */
+    if (Platform.isJS())
+    {
+      return;
+    }
+
+    /*
      * don't remove 'redundant' features if 
      * - transparency is applied (feature count affects depth of feature colour)
      * - filters are applied (not all features may be displayable)
@@ -1121,7 +1136,7 @@ public abstract class FeatureRendererModel
   /**
    * Answers the colour for the feature, or null if the feature is excluded by
    * feature group visibility, by filters, or by colour threshold settings. This
-   * method does not take feature visibility into account.
+   * method does not take feature type visibility into account.
    * 
    * @param sf
    * @param fc
@@ -1190,8 +1205,8 @@ public abstract class FeatureRendererModel
   }
 
   @Override
-  public MappedFeatures findComplementFeaturesAtResidue(SequenceI sequence,
-          int pos)
+  public MappedFeatures findComplementFeaturesAtResidue(
+          final SequenceI sequence, final int pos)
   {
     SequenceI ds = sequence.getDatasetSequence();
     if (ds == null)
@@ -1218,18 +1233,18 @@ public abstract class FeatureRendererModel
      * todo: direct lookup of CDS for peptide and vice-versa; for now,
      * have to search through an unordered list of mappings for a candidate
      */
-    Mapping mapping = null;
+    SequenceToSequenceMapping mapping = null;
     SequenceI mapFrom = null;
 
     for (AlignedCodonFrame acf : mappings)
     {
-      mapping = acf.getMappingForSequence(sequence);
-      if (mapping == null || !mapping.getMap().isTripletMap())
+      mapping = acf.getCoveringCodonMapping(ds);
+      if (mapping == null)
       {
-        continue; // we are only looking for 3:1 or 1:3 mappings
+        continue;
       }
       SearchResultsI sr = new SearchResults();
-      acf.markMappedRegion(ds, pos, sr);
+      mapping.markMappedRegion(ds, pos, sr);
       for (SearchResultMatchI match : sr.getResults())
       {
         int fromRes = match.getStart();
@@ -1260,9 +1275,12 @@ public abstract class FeatureRendererModel
     }
 
     /*
-     * sort by renderorder, inefficiently
+     * sort by renderorder (inefficiently but ok for small scale);
+     * NB this sorts 'on top' feature to end, for rendering
      */
     List<SequenceFeature> result = new ArrayList<>();
+    final int toAdd = found.size();
+    int added = 0;
     for (String type : renderOrder)
     {
       for (SequenceFeature sf : found)
@@ -1270,16 +1288,16 @@ public abstract class FeatureRendererModel
         if (type.equals(sf.getType()))
         {
           result.add(sf);
-          if (result.size() == found.size())
-          {
-            return new MappedFeatures(mapping, mapFrom, pos, residue,
-                    result);
-          }
+          added++;
+        }
+        if (added == toAdd)
+        {
+          break;
         }
       }
     }
     
-    return new MappedFeatures(mapping, mapFrom, pos, residue, result);
+    return new MappedFeatures(mapping.getMapping(), mapFrom, pos, residue, result);
   }
 
   @Override