JAL-2438 FeatureColourFinder refactored from FeatureRenderer, fr not
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 13 Mar 2017 16:42:23 +0000 (16:42 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 13 Mar 2017 16:42:23 +0000 (16:42 +0000)
cloned for structure viewers

29 files changed:
src/MCview/AppletPDBCanvas.java
src/MCview/PDBCanvas.java
src/jalview/api/FeatureRenderer.java
src/jalview/api/SequenceRenderer.java
src/jalview/appletgui/AppletJmolBinding.java
src/jalview/appletgui/ExtJmol.java
src/jalview/appletgui/OverviewPanel.java
src/jalview/appletgui/SeqCanvas.java
src/jalview/appletgui/SequenceRenderer.java
src/jalview/ext/jmol/JalviewJmolBinding.java
src/jalview/ext/jmol/JmolCommands.java
src/jalview/ext/rbvi/chimera/ChimeraCommands.java
src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java
src/jalview/ext/varna/VarnaCommands.java
src/jalview/gui/AppJmolBinding.java
src/jalview/gui/FeatureRenderer.java
src/jalview/gui/JalviewChimeraBindingModel.java
src/jalview/gui/OverviewPanel.java
src/jalview/gui/SeqCanvas.java
src/jalview/gui/SequenceRenderer.java
src/jalview/io/JSONFile.java
src/jalview/javascript/MouseOverStructureListener.java
src/jalview/renderer/seqfeatures/FeatureColourFinder.java [new file with mode: 0644]
src/jalview/renderer/seqfeatures/FeatureRenderer.java
src/jalview/structures/models/AAStructureBindingModel.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
test/jalview/ext/jmol/JmolCommandsTest.java
test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java
test/jalview/structures/models/AAStructureBindingModelTest.java

index aac796c..1602cb4 100644 (file)
@@ -28,6 +28,7 @@ import jalview.datamodel.PDBEntry;
 import jalview.datamodel.SequenceI;
 import jalview.io.DataSourceType;
 import jalview.io.StructureFile;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 import jalview.structure.AtomSpec;
 import jalview.structure.StructureListener;
 import jalview.structure.StructureMapping;
@@ -577,6 +578,8 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
       showFeatures = true;
     }
 
+    FeatureColourFinder finder = new FeatureColourFinder(fr);
+
     PDBChain chain;
     if (bysequence && pdb != null)
     {
@@ -607,7 +610,7 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
                   tmp.startCol = sr.getResidueBoxColour(sequence[s], pos);
                   if (showFeatures)
                   {
-                    tmp.startCol = fr.findFeatureColour(tmp.startCol,
+                    tmp.startCol = finder.findFeatureColour(tmp.startCol,
                             sequence[s], pos);
                   }
                 }
@@ -618,11 +621,10 @@ public class AppletPDBCanvas extends Panel implements MouseListener,
                   tmp.endCol = sr.getResidueBoxColour(sequence[s], pos);
                   if (showFeatures)
                   {
-                    tmp.endCol = fr.findFeatureColour(tmp.endCol,
+                    tmp.endCol = finder.findFeatureColour(tmp.endCol,
                             sequence[s], pos);
                   }
                 }
-
               }
             }
           }
index 292de91..ae58758 100644 (file)
@@ -28,6 +28,7 @@ import jalview.gui.FeatureRenderer;
 import jalview.gui.SequenceRenderer;
 import jalview.io.DataSourceType;
 import jalview.io.StructureFile;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 import jalview.structure.AtomSpec;
 import jalview.structure.StructureListener;
 import jalview.structure.StructureMapping;
@@ -546,6 +547,7 @@ public class PDBCanvas extends JPanel implements MouseListener,
       showFeatures = true;
     }
 
+    FeatureColourFinder finder = new FeatureColourFinder(fr);
     PDBChain chain;
     if (bysequence && pdb != null)
     {
@@ -576,7 +578,7 @@ public class PDBCanvas extends JPanel implements MouseListener,
                   tmp.startCol = sr.getResidueBoxColour(sequence[s], pos);
                   if (showFeatures)
                   {
-                    tmp.startCol = fr.findFeatureColour(tmp.startCol,
+                    tmp.startCol = finder.findFeatureColour(tmp.startCol,
                             sequence[s], pos);
                   }
                 }
@@ -587,7 +589,7 @@ public class PDBCanvas extends JPanel implements MouseListener,
                   tmp.endCol = sr.getResidueBoxColour(sequence[s], pos);
                   if (showFeatures)
                   {
-                    tmp.endCol = fr.findFeatureColour(tmp.endCol,
+                    tmp.endCol = finder.findFeatureColour(tmp.endCol,
                             sequence[s], pos);
                   }
                 }
index f54231e..b1813a6 100644 (file)
@@ -24,6 +24,7 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 
 import java.awt.Color;
+import java.awt.Graphics;
 import java.util.List;
 import java.util.Map;
 
@@ -46,9 +47,10 @@ public interface FeatureRenderer
    *          - sequence providing features
    * @param r
    *          - column position
+   * @param g
    * @return
    */
-  Color findFeatureColour(Color col, SequenceI sequenceI, int r);
+  Color findFeatureColour(Color col, SequenceI sequenceI, int r, Graphics g);
 
   /**
    * trigger the feature discovery process for a newly created feature renderer.
@@ -170,4 +172,19 @@ public interface FeatureRenderer
    */
   void setVisible(String featureType);
 
+  /**
+   * Sets the transparency value, between 0 (full transparency) and 1 (no
+   * transparency)
+   * 
+   * @param value
+   */
+  void setTransparency(float value);
+
+  /**
+   * Returns the transparency value, between 0 (full transparency) and 1 (no
+   * transparency)
+   * 
+   * @return
+   */
+  float getTransparency();
 }
index d708902..5e772a4 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.api;
 
 import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 
 import java.awt.Color;
 
@@ -29,6 +30,7 @@ public interface SequenceRenderer
 
   Color getResidueBoxColour(SequenceI sequenceI, int r);
 
-  Color getResidueColour(SequenceI seq, int position, FeatureRenderer fr);
+  Color getResidueColour(SequenceI seq, int position,
+          FeatureColourFinder finder);
 
 }
index f938cad..8ddff52 100644 (file)
@@ -54,21 +54,15 @@ class AppletJmolBinding extends JalviewJmolBinding
   public jalview.api.FeatureRenderer getFeatureRenderer(
           AlignmentViewPanel alignment)
   {
-    AlignmentPanel ap = (AlignmentPanel) alignment;
-    if (appletJmolBinding.ap.av.isShowSequenceFeatures())
+    AlignmentPanel alignPanel = (AlignmentPanel) alignment;
+    if (alignPanel.av.isShowSequenceFeatures())
     {
-      if (appletJmolBinding.fr == null)
-      {
-        appletJmolBinding.fr = new jalview.appletgui.FeatureRenderer(
-                appletJmolBinding.ap.av);
-      }
-
-      appletJmolBinding.fr
-              .transferSettings(appletJmolBinding.ap.seqPanel.seqCanvas
-                      .getFeatureRenderer());
+      return alignPanel.getFeatureRenderer();
+    }
+    else
+    {
+      return null;
     }
-
-    return appletJmolBinding.fr;
   }
 
   @Override
index 189fe88..b369318 100644 (file)
@@ -82,10 +82,10 @@ public class ExtJmol extends JalviewJmolBinding
   @Override
   public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
   {
-    AlignmentPanel ap = (AlignmentPanel) alignment;
-    if (ap.av.isShowSequenceFeatures())
+    AlignmentPanel alignPanel = (AlignmentPanel) alignment;
+    if (alignPanel.av.isShowSequenceFeatures())
     {
-      return ap.getFeatureRenderer();
+      return alignPanel.getFeatureRenderer();
     }
     else
     {
index 9b2be4c..8427c77 100755 (executable)
@@ -21,6 +21,7 @@
 package jalview.appletgui;
 
 import jalview.datamodel.AlignmentI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 
 import java.awt.Color;
 import java.awt.Dimension;
@@ -303,6 +304,8 @@ public class OverviewPanel extends Panel implements Runnable,
             .hasHiddenColumns();
     boolean hiddenRow = false;
     AlignmentI alignment = av.getAlignment();
+
+    FeatureColourFinder finder = new FeatureColourFinder(fr);
     for (row = 0; row <= sequencesHeight; row++)
     {
       if (resizeAgain)
@@ -353,7 +356,7 @@ public class OverviewPanel extends Panel implements Runnable,
 
           if (av.isShowSequenceFeatures())
           {
-            color = fr.findFeatureColour(color, seq, lastcol);
+            color = finder.findFeatureColour(color, seq, lastcol);
           }
         }
         else
index 5d6bb07..5ab3459 100755 (executable)
@@ -625,7 +625,7 @@ public class SeqCanvas extends Panel
       if (av.isShowSequenceFeatures())
       {
         fr.drawSequence(g, nextSeq, startRes, endRes, offset
-                + ((i - startSeq) * avcharHeight));
+                + ((i - startSeq) * avcharHeight), false);
       }
 
       // / Highlight search Results once all sequences have been drawn
index 86d1f98..b5586c9 100755 (executable)
  */
 package jalview.appletgui;
 
-import jalview.api.FeatureRenderer;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.ResidueShaderI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 
 import java.awt.Color;
 import java.awt.Font;
@@ -96,20 +96,20 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
    * 
    * @param seq
    * @param position
-   * @param fr
+   * @param finder
    * @return
    */
   @Override
   public Color getResidueColour(final SequenceI seq, int position,
-          FeatureRenderer fr)
+          FeatureColourFinder finder)
   {
     // TODO replace 8 or so code duplications with calls to this method
     // (refactored as needed)
     Color col = getResidueBoxColour(seq, position);
 
-    if (fr != null)
+    if (finder != null)
     {
-      col = fr.findFeatureColour(col, seq, position);
+      col = finder.findFeatureColour(col, seq, position);
     }
     return col;
   }
index 82e188f..19e8b67 100644 (file)
@@ -20,7 +20,7 @@
  */
 package jalview.ext.jmol;
 
-import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureRenderer;
 import jalview.api.SequenceRenderer;
 import jalview.datamodel.AlignmentI;
@@ -499,17 +499,15 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
   /**
    * @param files
    * @param sr
-   * @param fr
-   * @param viewport
+   * @param viewPanel
    * @return
    */
   @Override
   protected StructureMappingcommandSet[] getColourBySequenceCommands(
-          String[] files, SequenceRenderer sr, FeatureRenderer fr,
-          AlignViewportI viewport)
+          String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel)
   {
     return JmolCommands.getColourBySequenceCommand(getSsm(), files,
-            getSequence(), sr, fr, viewport);
+            getSequence(), sr, viewPanel);
   }
 
   /**
@@ -1184,10 +1182,7 @@ public abstract class JalviewJmolBinding extends AAStructureBindingModel
     if (notifyLoaded)
     {
       FeatureRenderer fr = getFeatureRenderer(null);
-      if (fr != null)
-      {
-        fr.featuresAdded();
-      }
+      fr.featuresAdded();
       refreshGUI();
       loadNotifiesHandled++;
     }
index a809cae..a1ff3c5 100644 (file)
 package jalview.ext.jmol;
 
 import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureRenderer;
 import jalview.api.SequenceRenderer;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 import jalview.structure.StructureMapping;
 import jalview.structure.StructureMappingcommandSet;
 import jalview.structure.StructureSelectionManager;
@@ -53,9 +55,12 @@ public class JmolCommands
    */
   public static StructureMappingcommandSet[] getColourBySequenceCommand(
           StructureSelectionManager ssm, String[] files,
-          SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
-          AlignViewportI viewport)
+          SequenceI[][] sequence, SequenceRenderer sr,
+          AlignmentViewPanel viewPanel)
   {
+    FeatureRenderer fr = viewPanel.getFeatureRenderer();
+    FeatureColourFinder finder = new FeatureColourFinder(fr);
+    AlignViewportI viewport = viewPanel.getAlignViewport();
     ColumnSelection cs = viewport.getColumnSelection();
     AlignmentI al = viewport.getAlignment();
     List<StructureMappingcommandSet> cset = new ArrayList<StructureMappingcommandSet>();
@@ -101,7 +106,8 @@ public class JmolCommands
 
               if (fr != null)
               {
-                col = fr.findFeatureColour(col, sequence[pdbfnum][s], r);
+                col = finder
+                        .findFeatureColour(col, sequence[pdbfnum][s], r);
               }
 
               /*
index e665982..1d8b944 100644 (file)
 package jalview.ext.rbvi.chimera;
 
 import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureRenderer;
 import jalview.api.SequenceRenderer;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 import jalview.structure.StructureMapping;
 import jalview.structure.StructureMappingcommandSet;
 import jalview.structure.StructureSelectionManager;
@@ -59,16 +61,16 @@ public class ChimeraCommands
    * @param sequence
    * @param sr
    * @param fr
-   * @param viewport
+   * @param viewPanel
    * @return
    */
   public static StructureMappingcommandSet[] getColourBySequenceCommand(
           StructureSelectionManager ssm, String[] files,
-          SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
-          AlignViewportI viewport)
+          SequenceI[][] sequence, SequenceRenderer sr,
+          AlignmentViewPanel viewPanel)
   {
     Map<Object, AtomSpecModel> colourMap = buildColoursMap(ssm, files,
-            sequence, sr, fr, viewport);
+            sequence, sr, viewPanel);
 
     List<String> colourCommands = buildColourCommands(colourMap);
 
@@ -186,9 +188,12 @@ public class ChimeraCommands
    */
   protected static Map<Object, AtomSpecModel> buildColoursMap(
           StructureSelectionManager ssm, String[] files,
-          SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
-          AlignViewportI viewport)
+          SequenceI[][] sequence, SequenceRenderer sr,
+          AlignmentViewPanel viewPanel)
   {
+    FeatureRenderer fr = viewPanel.getFeatureRenderer();
+    FeatureColourFinder finder = new FeatureColourFinder(fr);
+    AlignViewportI viewport = viewPanel.getAlignViewport();
     ColumnSelection cs = viewport.getColumnSelection();
     AlignmentI al = viewport.getAlignment();
     Map<Object, AtomSpecModel> colourMap = new LinkedHashMap<Object, AtomSpecModel>();
@@ -228,7 +233,7 @@ public class ChimeraCommands
                 continue;
               }
 
-              Color colour = sr.getResidueColour(seq, r, fr);
+              Color colour = sr.getResidueColour(seq, r, finder);
 
               /*
                * darker colour for hidden regions
@@ -310,16 +315,15 @@ public class ChimeraCommands
    * @param ssm
    * @param files
    * @param seqs
-   * @param fr
-   * @param alignment
+   * @param viewPanel
    * @return
    */
   public static StructureMappingcommandSet getSetAttributeCommandsForFeatures(
           StructureSelectionManager ssm, String[] files,
-          SequenceI[][] seqs, FeatureRenderer fr, AlignmentI alignment)
+          SequenceI[][] seqs, AlignmentViewPanel viewPanel)
   {
     Map<String, Map<Object, AtomSpecModel>> featureMap = buildFeaturesMap(
-            ssm, files, seqs, fr, alignment);
+            ssm, files, seqs, viewPanel);
 
     List<String> commands = buildSetAttributeCommands(featureMap);
 
@@ -339,22 +343,28 @@ public class ChimeraCommands
    * @param ssm
    * @param files
    * @param seqs
-   * @param fr
-   * @param alignment
+   * @param viewPanel
    * @return
    */
   protected static Map<String, Map<Object, AtomSpecModel>> buildFeaturesMap(
           StructureSelectionManager ssm, String[] files,
-          SequenceI[][] seqs, FeatureRenderer fr, AlignmentI alignment)
+          SequenceI[][] seqs, AlignmentViewPanel viewPanel)
   {
     Map<String, Map<Object, AtomSpecModel>> theMap = new LinkedHashMap<String, Map<Object, AtomSpecModel>>();
 
+    FeatureRenderer fr = viewPanel.getFeatureRenderer();
+    if (fr == null)
+    {
+      return theMap;
+    }
+
     List<String> visibleFeatures = fr.getDisplayedFeatureTypes();
     if (visibleFeatures.isEmpty())
     {
       return theMap;
     }
 
+    AlignmentI alignment = viewPanel.getAlignment();
     for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
     {
       StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
index 9a570fc..fad3137 100644 (file)
@@ -20,9 +20,7 @@
  */
 package jalview.ext.rbvi.chimera;
 
-import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
-import jalview.api.FeatureRenderer;
 import jalview.api.SequenceRenderer;
 import jalview.api.structures.JalviewStructureDisplayI;
 import jalview.bin.Cache;
@@ -175,11 +173,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       {
         getSsm().addStructureViewerListener(this);
         // ssm.addSelectionListener(this);
-        FeatureRenderer fr = getFeatureRenderer(null);
-        if (fr != null)
-        {
-          fr.featuresAdded();
-        }
         refreshGUI();
       }
       return true;
@@ -699,17 +692,15 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   /**
    * @param files
    * @param sr
-   * @param fr
-   * @param viewport
+   * @param viewPanel
    * @return
    */
   @Override
   protected StructureMappingcommandSet[] getColourBySequenceCommands(
-          String[] files, SequenceRenderer sr, FeatureRenderer fr,
-          AlignViewportI viewport)
+          String[] files, SequenceRenderer sr, AlignmentViewPanel viewPanel)
   {
     return ChimeraCommands.getColourBySequenceCommand(getSsm(), files,
-            getSequence(), sr, fr, viewport);
+            getSequence(), sr, viewPanel);
   }
 
   /**
@@ -1110,15 +1101,6 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   {
     // TODO refactor as required to pull up to an interface
     AlignmentI alignment = avp.getAlignment();
-    FeatureRenderer fr = getFeatureRenderer(avp);
-
-    /*
-     * fr is null if feature display is turned off
-     */
-    if (fr == null)
-    {
-      return 0;
-    }
 
     String[] files = getPdbFile();
     if (files == null)
@@ -1128,7 +1110,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
 
     StructureMappingcommandSet commandSet = ChimeraCommands
             .getSetAttributeCommandsForFeatures(getSsm(), files,
-                    getSequence(), fr, alignment);
+                    getSequence(), avp);
     String[] commands = commandSet.commands;
     if (commands.length > 10)
     {
index a41e10e..617dc8f 100644 (file)
  */
 package jalview.ext.varna;
 
-import jalview.api.FeatureRenderer;
 import jalview.api.SequenceRenderer;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 import jalview.structure.StructureMapping;
 import jalview.structure.StructureSelectionManager;
 
@@ -47,7 +47,8 @@ public class VarnaCommands
    */
   public static String[] getColourBySequenceCommand(
           StructureSelectionManager ssm, String[] files,
-          SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr,
+          SequenceI[][] sequence, SequenceRenderer sr,
+          FeatureColourFinder fr,
           AlignmentI alignment)
   {
     ArrayList<String> str = new ArrayList<String>();
@@ -58,7 +59,9 @@ public class VarnaCommands
       StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
 
       if (mapping == null || mapping.length < 1)
+      {
         continue;
+      }
 
       int lastPos = -1;
       for (int s = 0; s < sequence[pdbfnum].length; s++)
@@ -79,14 +82,18 @@ public class VarnaCommands
               int pos = mapping[m].getPDBResNum(asp.findPosition(r));
 
               if (pos < 1 || pos == lastPos)
+              {
                 continue;
+              }
 
               lastPos = pos;
 
               Color col = sr.getResidueBoxColour(sequence[pdbfnum][s], r);
 
               if (fr != null)
+              {
                 col = fr.findFeatureColour(col, sequence[pdbfnum][s], r);
+              }
               String newSelcom = (mapping[m].getChain() != " " ? ":"
                       + mapping[m].getChain() : "")
                       + "/"
index 75e0c5e..f822358 100644 (file)
@@ -40,8 +40,6 @@ public class AppJmolBinding extends JalviewJmolBinding
 {
   private AppJmol appJmolWindow;
 
-  private FeatureRenderer fr = null;
-
   public AppJmolBinding(AppJmol appJmol, StructureSelectionManager sSm,
           PDBEntry[] pdbentry, SequenceI[][] sequenceIs, DataSourceType protocol)
   {
@@ -50,26 +48,6 @@ public class AppJmolBinding extends JalviewJmolBinding
   }
 
   @Override
-  public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
-  {
-    AlignmentPanel ap = (alignment == null) ? appJmolWindow
-            .getAlignmentPanel() : (AlignmentPanel) alignment;
-    if (ap.av.isShowSequenceFeatures())
-    {
-      if (fr == null)
-      {
-        fr = (jalview.gui.FeatureRenderer) ap.cloneFeatureRenderer();
-      }
-      else
-      {
-        ap.updateFeatureRenderer(fr);
-      }
-    }
-
-    return fr;
-  }
-
-  @Override
   public SequenceRenderer getSequenceRenderer(AlignmentViewPanel alignment)
   {
     return new SequenceRenderer(((AlignmentPanel) alignment).av);
@@ -215,4 +193,18 @@ public class AppJmolBinding extends JalviewJmolBinding
   {
     return appJmolWindow;
   }
+
+  @Override
+  public jalview.api.FeatureRenderer getFeatureRenderer(
+          AlignmentViewPanel alignment)
+  {
+    AlignmentPanel ap = (alignment == null) ? appJmolWindow
+            .getAlignmentPanel() : (AlignmentPanel) alignment;
+    if (ap.av.isShowSequenceFeatures())
+    {
+      return ap.av.getAlignPanel().getSeqPanel().seqCanvas.fr;
+    }
+
+    return null;
+  }
 }
index ed6a3c5..86b8eba 100644 (file)
@@ -46,7 +46,6 @@ import java.util.Comparator;
 import javax.swing.JColorChooser;
 import javax.swing.JComboBox;
 import javax.swing.JLabel;
-import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.JSpinner;
@@ -61,8 +60,7 @@ import javax.swing.SwingConstants;
  * @version $Revision$
  */
 public class FeatureRenderer extends
-        jalview.renderer.seqfeatures.FeatureRenderer implements
-        jalview.api.FeatureRenderer
+        jalview.renderer.seqfeatures.FeatureRenderer
 {
   Color resBoxColour;
 
index a1f05bd..c9b35d8 100644 (file)
@@ -34,9 +34,6 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
 {
   private ChimeraViewFrame cvf;
 
-  private FeatureRenderer fr = null;
-
-
   public JalviewChimeraBindingModel(ChimeraViewFrame chimeraViewFrame,
           StructureSelectionManager ssm, PDBEntry[] pdbentry,
           SequenceI[][] sequenceIs, DataSourceType protocol)
@@ -52,17 +49,10 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding
             : (AlignmentPanel) alignment;
     if (ap.av.isShowSequenceFeatures())
     {
-      if (fr == null)
-      {
-        fr = (jalview.gui.FeatureRenderer) ap.cloneFeatureRenderer();
-      }
-      else
-      {
-        ap.updateFeatureRenderer(fr);
-      }
+      return ap.getSeqPanel().seqCanvas.fr;
     }
 
-    return fr;
+    return null;
   }
 
   @Override
index 1c48690..7fdb610 100755 (executable)
@@ -21,6 +21,7 @@
 package jalview.gui;
 
 import jalview.renderer.AnnotationRenderer;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 
 import java.awt.Color;
 import java.awt.Dimension;
@@ -289,7 +290,7 @@ public class OverviewPanel extends JPanel implements Runnable
     float sampleRow = (float) alheight / (float) sequencesHeight;
 
     int lastcol = -1, lastrow = -1;
-    int color = Color.white.getRGB();
+    Color color = Color.white;
     int row, col;
     jalview.datamodel.SequenceI seq;
     final boolean hasHiddenRows = av.hasHiddenRows(), hasHiddenCols = av
@@ -298,6 +299,9 @@ public class OverviewPanel extends JPanel implements Runnable
     // get hidden row and hidden column map once at beginning.
     // clone featureRenderer settings to avoid race conditions... if state is
     // updated just need to refresh again
+
+    FeatureColourFinder finder = new FeatureColourFinder(fr);
+
     for (row = 0; row < sequencesHeight; row++)
     {
       if (resizeAgain)
@@ -358,7 +362,7 @@ public class OverviewPanel extends JPanel implements Runnable
         if ((int) (col * sampleCol) == lastcol
                 && (int) (row * sampleRow) == lastrow)
         {
-          miniMe.setRGB(col, row, color);
+          miniMe.setRGB(col, row, color.getRGB());
           continue;
         }
 
@@ -366,26 +370,26 @@ public class OverviewPanel extends JPanel implements Runnable
 
         if (seq.getLength() > lastcol)
         {
-          color = sr.getResidueBoxColour(seq, lastcol).getRGB();
+          color = sr.getResidueBoxColour(seq, lastcol);
 
           if (av.isShowSequenceFeatures())
           {
-            color = fr.findFeatureColour(color, seq, lastcol);
+            color = finder.findFeatureColour(color, seq, lastcol);
           }
         }
         else
         {
-          color = -1; // White
+          color = Color.WHITE;
         }
 
         if (hiddenRow
                 || (hasHiddenCols && !av.getColumnSelection().isVisible(
                         lastcol)))
         {
-          color = new Color(color).darker().darker().getRGB();
+          color = color.darker().darker();
         }
 
-        miniMe.setRGB(col, row, color);
+        miniMe.setRGB(col, row, color.getRGB());
 
       }
     }
index d015292..97889af 100755 (executable)
@@ -733,7 +733,7 @@ public class SeqCanvas extends JComponent
       if (av.isShowSequenceFeatures())
       {
         fr.drawSequence(g, nextSeq, startRes, endRes, offset
-                + ((i - startSeq) * charHeight));
+                + ((i - startSeq) * charHeight), false);
       }
 
       // / Highlight search Results once all sequences have been drawn
index 95c3261..764ef3f 100755 (executable)
  */
 package jalview.gui;
 
-import jalview.api.FeatureRenderer;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.ResidueShaderI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 import jalview.util.Comparison;
 
 import java.awt.Color;
@@ -111,20 +111,20 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer
    * 
    * @param seq
    * @param position
-   * @param fr
+   * @param finder
    * @return
    */
   @Override
   public Color getResidueColour(final SequenceI seq, int position,
-          FeatureRenderer fr)
+          FeatureColourFinder finder)
   {
     // TODO replace 8 or so code duplications with calls to this method
     // (refactored as needed)
     Color col = getResidueBoxColour(seq, position);
 
-    if (fr != null)
+    if (finder != null)
     {
-      col = fr.findFeatureColour(col, seq, position);
+      col = finder.findFeatureColour(col, seq, position);
     }
     return col;
   }
index 27ebe5a..053a65e 100644 (file)
@@ -46,6 +46,7 @@ import jalview.json.binding.biojson.v1.ColourSchemeMapper;
 import jalview.json.binding.biojson.v1.SequenceFeaturesPojo;
 import jalview.json.binding.biojson.v1.SequenceGrpPojo;
 import jalview.json.binding.biojson.v1.SequencePojo;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
 import jalview.schemes.JalviewColourScheme;
 import jalview.schemes.ResidueColourScheme;
 import jalview.util.ColorUtils;
@@ -328,6 +329,8 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
       return sequenceFeaturesPojo;
     }
 
+    FeatureColourFinder finder = new FeatureColourFinder(fr);
+
     for (SequenceI seq : sqs)
     {
       SequenceI dataSetSequence = seq.getDatasetSequence();
@@ -350,7 +353,7 @@ public class JSONFile extends AlignFile implements ComplexAlignFile
                   String.valueOf(seq.hashCode()));
 
           String featureColour = (fr == null) ? null : jalview.util.Format
-                  .getHexString(fr.findFeatureColour(Color.white, seq,
+                  .getHexString(finder.findFeatureColour(Color.white, seq,
                           seq.findIndex(sf.getBegin())));
           jsonFeature.setXstart(seq.findIndex(sf.getBegin()) - 1);
           jsonFeature.setXend(seq.findIndex(sf.getEnd()));
index 6d366d0..7580222 100644 (file)
@@ -221,8 +221,8 @@ public class MouseOverStructureListener extends JSFunctionExec implements
       ArrayList<String[]> ccomands = new ArrayList<String[]>();
       ArrayList<String> pdbfn = new ArrayList<String>();
       StructureMappingcommandSet[] colcommands = JmolCommands
-              .getColourBySequenceCommand(ssm, modelSet, sequence, sr, fr,
-                      ((AlignmentViewPanel) source).getAlignViewport());
+              .getColourBySequenceCommand(ssm, modelSet, sequence, sr,
+                      (AlignmentViewPanel) source);
       if (colcommands == null)
       {
         return;
diff --git a/src/jalview/renderer/seqfeatures/FeatureColourFinder.java b/src/jalview/renderer/seqfeatures/FeatureColourFinder.java
new file mode 100644 (file)
index 0000000..5055ed5
--- /dev/null
@@ -0,0 +1,79 @@
+package jalview.renderer.seqfeatures;
+
+import jalview.api.FeaturesDisplayedI;
+import jalview.datamodel.SequenceI;
+import jalview.viewmodel.seqfeatures.FeatureRendererModel;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+
+/**
+ * A helper class to find feature colour using an associated FeatureRenderer
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class FeatureColourFinder
+{
+  /*
+   * the class we delegate feature finding to
+   */
+  private jalview.api.FeatureRenderer featureRenderer;
+
+  /*
+   * a 1-pixel image on which features can be drawn, for the case where
+   * transparency allows 'see-through' of multiple feature colours
+   */
+  private BufferedImage offscreenImage;
+
+  /**
+   * Constructor
+   * 
+   * @param fr
+   */
+  public FeatureColourFinder(jalview.api.FeatureRenderer fr)
+  {
+    featureRenderer = fr;
+    offscreenImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
+  }
+
+  /**
+   * Answers the feature colour to show for the given sequence and column
+   * position. This delegates to the FeatureRenderer to find the colour, which
+   * will depend on feature location, visibility, ordering, and whether or not
+   * transparency is applied. For feature rendering with transparency, this
+   * class provides a dummy 'offscreen' graphics context where multiple feature
+   * colours can be overlaid and the combined colour read back.
+   * 
+   * @param defaultColour
+   * @param seq
+   * @param column
+   * @return
+   */
+  public Color findFeatureColour(Color defaultColour, SequenceI seq,
+          int column)
+  {
+    if (!((FeatureRendererModel) featureRenderer).hasRenderOrder())
+    {
+      return defaultColour;
+    }
+
+    FeaturesDisplayedI displayed = featureRenderer.getFeaturesDisplayed();
+    if (displayed == null || displayed.getVisibleFeatureCount() == 0)
+    {
+      return defaultColour; // nothing to see here folks
+    }
+
+    Graphics g = featureRenderer.getTransparency() == 1f ? null
+            : offscreenImage.getGraphics();
+
+    Color c = featureRenderer.findFeatureColour(defaultColour, seq, column,
+            g);
+    if (c != null && g != null)
+    {
+      c = new Color(offscreenImage.getRGB(0, 0));
+    }
+    return c == null ? defaultColour : c;
+  }
+}
index 9e0089f..de3b201 100644 (file)
@@ -23,6 +23,7 @@ package jalview.renderer.seqfeatures;
 import jalview.api.AlignViewportI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.util.Comparison;
 import jalview.viewmodel.seqfeatures.FeatureRendererModel;
 
 import java.awt.AlphaComposite;
@@ -34,24 +35,16 @@ import java.awt.image.BufferedImage;
 
 public class FeatureRenderer extends FeatureRendererModel
 {
-
-  FontMetrics fm;
-
-  int charOffset;
-
-  boolean offscreenRender = false;
+  private static final AlphaComposite NO_TRANSPARENCY = AlphaComposite
+          .getInstance(AlphaComposite.SRC_OVER, 1.0f);
 
   protected SequenceI lastSeq;
 
-  char s;
-
-  int i;
-
-  int av_charHeight, av_charWidth;
+  BufferedImage offscreenImage;
 
-  boolean av_validCharWidth, av_isShowSeqFeatureHeight;
+  private volatile SequenceFeature[] lastSequenceFeatures;
 
-  private Integer currentColour;
+  int sfSize;
 
   /**
    * Constructor given a viewport
@@ -63,141 +56,174 @@ public class FeatureRenderer extends FeatureRendererModel
     this.av = viewport;
   }
 
-  protected void updateAvConfig()
+  /**
+   * Renders the sequence using the given feature colour between the given start
+   * and end columns. Returns true if at least one column is drawn, else false
+   * (the feature range does not overlap the start and end positions).
+   * 
+   * @param g
+   * @param seq
+   * @param featureStart
+   * @param featureEnd
+   * @param featureColour
+   * @param start
+   * @param end
+   * @param y1
+   * @param colourOnly
+   * @return
+   */
+  boolean renderFeature(Graphics g, SequenceI seq, int featureStart,
+          int featureEnd, Color featureColour, int start, int end, int y1,
+          boolean colourOnly)
   {
-    av_charHeight = av.getCharHeight();
-    av_charWidth = av.getCharWidth();
-    av_validCharWidth = av.isValidCharWidth();
-    av_isShowSeqFeatureHeight = av.isShowSequenceFeaturesHeight();
-  }
+    int charHeight = av.getCharHeight();
+    int charWidth = av.getCharWidth();
+    boolean validCharWidth = av.isValidCharWidth();
 
-  void renderFeature(Graphics g, SequenceI seq, int fstart, int fend,
-          Color featureColour, int start, int end, int y1)
-  {
-    updateAvConfig();
-    if (((fstart <= end) && (fend >= start)))
+    if (featureStart > end || featureEnd < start)
     {
-      if (fstart < start)
-      { // fix for if the feature we have starts before the sequence start,
-        fstart = start; // but the feature end is still valid!!
-      }
-
-      if (fend >= end)
-      {
-        fend = end;
-      }
-      int pady = (y1 + av_charHeight) - av_charHeight / 5;
-      for (i = fstart; i <= fend; i++)
-      {
-        s = seq.getCharAt(i);
+      return false;
+    }
 
-        if (jalview.util.Comparison.isGap(s))
-        {
-          continue;
-        }
+    if (featureStart < start)
+    {
+      featureStart = start;
+    }
+    if (featureEnd >= end)
+    {
+      featureEnd = end;
+    }
+    int pady = (y1 + charHeight) - charHeight / 5;
 
-        g.setColor(featureColour);
+    FontMetrics fm = g.getFontMetrics();
+    for (int i = featureStart; i <= featureEnd; i++)
+    {
+      char s = seq.getCharAt(i);
 
-        g.fillRect((i - start) * av_charWidth, y1, av_charWidth,
-                av_charHeight);
+      if (Comparison.isGap(s))
+      {
+        continue;
+      }
 
-        if (offscreenRender || !av_validCharWidth)
-        {
-          continue;
-        }
+      g.setColor(featureColour);
 
-        g.setColor(Color.white);
-        charOffset = (av_charWidth - fm.charWidth(s)) / 2;
-        g.drawString(String.valueOf(s), charOffset
-                + (av_charWidth * (i - start)), pady);
+      g.fillRect((i - start) * charWidth, y1, charWidth,
+              charHeight);
 
+      if (colourOnly || !validCharWidth)
+      {
+        continue;
       }
+
+      g.setColor(Color.white);
+      int charOffset = (charWidth - fm.charWidth(s)) / 2;
+      g.drawString(String.valueOf(s), charOffset
+              + (charWidth * (i - start)), pady);
     }
+    return true;
   }
 
-  void renderScoreFeature(Graphics g, SequenceI seq, int fstart, int fend,
-          Color featureColour, int start, int end, int y1, byte[] bs)
+  /**
+   * Renders the sequence using the given SCORE feature colour between the given
+   * start and end columns. Returns true if at least one column is drawn, else
+   * false (the feature range does not overlap the start and end positions).
+   * 
+   * @param g
+   * @param seq
+   * @param fstart
+   * @param fend
+   * @param featureColour
+   * @param start
+   * @param end
+   * @param y1
+   * @param bs
+   * @param colourOnly
+   * @return
+   */
+  boolean renderScoreFeature(Graphics g, SequenceI seq, int fstart,
+          int fend, Color featureColour, int start, int end, int y1,
+          byte[] bs, boolean colourOnly)
   {
-    updateAvConfig();
-    if (((fstart <= end) && (fend >= start)))
+    if (fstart > end || fend < start)
     {
-      if (fstart < start)
-      { // fix for if the feature we have starts before the sequence start,
-        fstart = start; // but the feature end is still valid!!
-      }
+      return false;
+    }
 
-      if (fend >= end)
+    if (fstart < start)
+    { // fix for if the feature we have starts before the sequence start,
+      fstart = start; // but the feature end is still valid!!
+    }
+
+    if (fend >= end)
+    {
+      fend = end;
+    }
+    int charHeight = av.getCharHeight();
+    int pady = (y1 + charHeight) - charHeight / 5;
+    int ystrt = 0, yend = charHeight;
+    if (bs[0] != 0)
+    {
+      // signed - zero is always middle of residue line.
+      if (bs[1] < 128)
       {
-        fend = end;
-      }
-      int pady = (y1 + av_charHeight) - av_charHeight / 5;
-      int ystrt = 0, yend = av_charHeight;
-      if (bs[0] != 0)
-      {
-        // signed - zero is always middle of residue line.
-        if (bs[1] < 128)
-        {
-          yend = av_charHeight * (128 - bs[1]) / 512;
-          ystrt = av_charHeight - yend / 2;
-        }
-        else
-        {
-          ystrt = av_charHeight / 2;
-          yend = av_charHeight * (bs[1] - 128) / 512;
-        }
+        yend = charHeight * (128 - bs[1]) / 512;
+        ystrt = charHeight - yend / 2;
       }
       else
       {
-        yend = av_charHeight * bs[1] / 255;
-        ystrt = av_charHeight - yend;
-
+        ystrt = charHeight / 2;
+        yend = charHeight * (bs[1] - 128) / 512;
       }
-      for (i = fstart; i <= fend; i++)
-      {
-        s = seq.getCharAt(i);
+    }
+    else
+    {
+      yend = charHeight * bs[1] / 255;
+      ystrt = charHeight - yend;
 
-        if (jalview.util.Comparison.isGap(s))
-        {
-          continue;
-        }
+    }
 
-        g.setColor(featureColour);
-        int x = (i - start) * av_charWidth;
-        g.drawRect(x, y1, av_charWidth, av_charHeight);
-        g.fillRect(x, y1 + ystrt, av_charWidth, yend);
+    FontMetrics fm = g.getFontMetrics();
+    int charWidth = av.getCharWidth();
 
-        if (offscreenRender || !av_validCharWidth)
-        {
-          continue;
-        }
+    for (int i = fstart; i <= fend; i++)
+    {
+      char s = seq.getCharAt(i);
 
-        g.setColor(Color.black);
-        charOffset = (av_charWidth - fm.charWidth(s)) / 2;
-        g.drawString(String.valueOf(s), charOffset
-                + (av_charWidth * (i - start)), pady);
+      if (Comparison.isGap(s))
+      {
+        continue;
       }
-    }
-  }
 
-  BufferedImage offscreenImage;
+      g.setColor(featureColour);
+      int x = (i - start) * charWidth;
+      g.drawRect(x, y1, charWidth, charHeight);
+      g.fillRect(x, y1 + ystrt, charWidth, yend);
 
-  @Override
-  public Color findFeatureColour(Color initialCol, SequenceI seq, int res)
-  {
-    return new Color(findFeatureColour(initialCol.getRGB(), seq, res));
+      if (colourOnly || !av.isValidCharWidth())
+      {
+        continue;
+      }
+
+      g.setColor(Color.black);
+      int charOffset = (charWidth - fm.charWidth(s)) / 2;
+      g.drawString(String.valueOf(s), charOffset
+              + (charWidth * (i - start)), pady);
+    }
+    return true;
   }
 
   /**
    * This is used by Structure Viewers and the Overview Window to get the
-   * feature colour of the rendered sequence, returned as an RGB value
+   * feature colour of the rendered sequence
    * 
    * @param defaultColour
    * @param seq
    * @param column
    * @return
    */
-  public synchronized int findFeatureColour(int defaultColour,
-          final SequenceI seq, int column)
+  @Override
+  public Color findFeatureColour(Color defaultColour, SequenceI seq,
+          int column, Graphics g)
   {
     if (!av.isShowSequenceFeatures())
     {
@@ -231,60 +257,29 @@ public class FeatureRenderer extends FeatureRendererModel
       return defaultColour;
     }
 
-    if (jalview.util.Comparison.isGap(lastSeq.getCharAt(column)))
+    if (Comparison.isGap(lastSeq.getCharAt(column)))
     {
-      return Color.white.getRGB();
+      return Color.white;
     }
 
-    // Only bother making an offscreen image if transparency is applied
-    if (transparency != 1.0f && offscreenImage == null)
+    Color renderedColour = null;
+    if (transparency == 1.0f)
     {
-      offscreenImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
-    }
-
-    currentColour = null;
-    // TODO: non-threadsafe - each rendering thread needs its own instance of
-    // the feature renderer - or this should be synchronized.
-    offscreenRender = true;
-
-    if (offscreenImage != null)
-    {
-      offscreenImage.setRGB(0, 0, defaultColour);
-      drawSequence(offscreenImage.getGraphics(), lastSeq, column, column, 0);
-
-      return offscreenImage.getRGB(0, 0);
+      renderedColour = findFeatureColour(seq, seq.findPosition(column));
     }
     else
     {
-      drawSequence(null, lastSeq, lastSeq.findPosition(column), -1, -1);
-
-      if (currentColour == null)
-      {
-        return defaultColour;
-      }
-      else
-      {
-        return currentColour.intValue();
-      }
+      renderedColour = drawSequence(g, lastSeq, column, column, 0, true);
     }
-
+    return renderedColour == null ? defaultColour : renderedColour;
   }
 
-  private volatile SequenceFeature[] lastSequenceFeatures;
-
-  int sfSize;
-
-  int sfindex;
-
-  int spos;
-
-  int epos;
-
   /**
-   * Draws the sequence on the graphics context, or just determines the colour
-   * that would be drawn (if flag offscreenrender is true).
+   * Draws the sequence features on the graphics context, or just determines the
+   * colour that would be drawn (if flag offscreenrender is true).
    * 
    * @param g
+   *          the graphics context to draw on (may be null if colourOnly==true)
    * @param seq
    * @param start
    *          start column (or sequence position in offscreenrender mode)
@@ -292,19 +287,19 @@ public class FeatureRenderer extends FeatureRendererModel
    *          end column (not used in offscreenrender mode)
    * @param y1
    *          vertical offset at which to draw on the graphics
+   * @param colourOnly
+   *          if true, only do enough to determine the colour for the position,
+   *          do not draw the character
+   * @return
    */
-  public synchronized void drawSequence(Graphics g, final SequenceI seq,
-          int start, int end, int y1)
+  public synchronized Color drawSequence(final Graphics g,
+          final SequenceI seq, int start, int end, int y1,
+          boolean colourOnly)
   {
     SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
     if (sequenceFeatures == null || sequenceFeatures.length == 0)
     {
-      return;
-    }
-
-    if (g != null)
-    {
-      fm = g.getFontMetrics();
+      return null;
     }
 
     updateFeatures();
@@ -316,20 +311,25 @@ public class FeatureRenderer extends FeatureRendererModel
       lastSequenceFeatures = sequenceFeatures;
     }
 
-    if (transparency != 1 && g != null)
+    if (transparency != 1f && g != null)
     {
       Graphics2D g2 = (Graphics2D) g;
       g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
               transparency));
     }
 
-    if (!offscreenRender)
-    {
-      spos = lastSeq.findPosition(start);
-      epos = lastSeq.findPosition(end);
-    }
+    int startPos = lastSeq.findPosition(start);
+    int endPos = lastSeq.findPosition(end);
 
     sfSize = lastSequenceFeatures.length;
+    Color drawnColour = null;
+
+    /*
+     * iterate over features in ordering of their rendering;
+     * if drawing a range of columns, use render order to ensure last is on top
+     * if drawing a single column (as in findFeatureColour), with no 
+     * transparency, work backwards to find the topmost rendered feature colour
+     */
     for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
     {
       String type = renderOrder[renderIndex];
@@ -340,7 +340,7 @@ public class FeatureRenderer extends FeatureRendererModel
 
       // loop through all features in sequence to find
       // current feature to render
-      for (sfindex = 0; sfindex < sfSize; sfindex++)
+      for (int sfindex = 0; sfindex < sfSize; sfindex++)
       {
         final SequenceFeature sequenceFeature = lastSequenceFeatures[sfindex];
         if (!sequenceFeature.type.equals(type))
@@ -358,9 +358,8 @@ public class FeatureRenderer extends FeatureRendererModel
          * unless doing offscreenRender (to the Overview window or a 
          * structure viewer) which is not limited 
          */
-        if (!offscreenRender
-                && (sequenceFeature.getBegin() > epos || sequenceFeature
-                        .getEnd() < spos))
+        if (sequenceFeature.getBegin() > endPos
+                || sequenceFeature.getEnd() < startPos)
         {
           continue;
         }
@@ -368,58 +367,46 @@ public class FeatureRenderer extends FeatureRendererModel
         Color featureColour = getColour(sequenceFeature);
         boolean isContactFeature = sequenceFeature.isContactFeature();
 
-        if (offscreenRender && offscreenImage == null)
+        if (isContactFeature)
         {
-          /*
-           * offscreen mode with no image (image is only needed if transparency 
-           * is applied to feature colours) - just check feature is rendered at 
-           * the requested position (start == sequence position in this mode)
-           */
-          boolean featureIsAtPosition = sequenceFeature.begin <= start
-                  && sequenceFeature.end >= start;
-          if (isContactFeature)
-          {
-            featureIsAtPosition = sequenceFeature.begin == start
-                    || sequenceFeature.end == start;
-          }
-          if (featureIsAtPosition)
-          {
-            // this is passed out to the overview and other sequence renderers
-            // (e.g. molecule viewer) to get displayed colour for rendered
-            // sequence
-            currentColour = new Integer(featureColour.getRGB());
-            // used to be retreived from av.featuresDisplayed
-            // currentColour = av.featuresDisplayed
-            // .get(sequenceFeatures[sfindex].type);
-
-          }
-        }
-        else if (isContactFeature)
-        {
-          renderFeature(g, seq, seq.findIndex(sequenceFeature.begin) - 1,
+          boolean drawn = renderFeature(g, seq,
+                  seq.findIndex(sequenceFeature.begin) - 1,
                   seq.findIndex(sequenceFeature.begin) - 1, featureColour,
-                  start, end, y1);
-          renderFeature(g, seq, seq.findIndex(sequenceFeature.end) - 1,
+                  start, end, y1, colourOnly);
+          drawn |= renderFeature(g, seq,
+                  seq.findIndex(sequenceFeature.end) - 1,
                   seq.findIndex(sequenceFeature.end) - 1, featureColour,
-                  start, end, y1);
-
+                  start, end, y1, colourOnly);
+          if (drawn)
+          {
+            drawnColour = featureColour;
+          }
         }
         else if (showFeature(sequenceFeature))
         {
-          if (av_isShowSeqFeatureHeight
+          if (av.isShowSequenceFeaturesHeight()
                   && !Float.isNaN(sequenceFeature.score))
           {
-            renderScoreFeature(g, seq,
+            boolean drawn = renderScoreFeature(g, seq,
                     seq.findIndex(sequenceFeature.begin) - 1,
-                    seq.findIndex(sequenceFeature.end) - 1,
-                    featureColour, start, end, y1,
-                    normaliseScore(sequenceFeature));
+                    seq.findIndex(sequenceFeature.end) - 1, featureColour,
+                    start, end, y1, normaliseScore(sequenceFeature),
+                    colourOnly);
+            if (drawn)
+            {
+              drawnColour = featureColour;
+            }
           }
           else
           {
-            renderFeature(g, seq, seq.findIndex(sequenceFeature.begin) - 1,
-                    seq.findIndex(sequenceFeature.end) - 1,
-                    featureColour, start, end, y1);
+            boolean drawn = renderFeature(g, seq,
+                    seq.findIndex(sequenceFeature.begin) - 1,
+                    seq.findIndex(sequenceFeature.end) - 1, featureColour,
+                    start, end, y1, colourOnly);
+            if (drawn)
+            {
+              drawnColour = featureColour;
+            }
           }
         }
       }
@@ -427,10 +414,19 @@ public class FeatureRenderer extends FeatureRendererModel
 
     if (transparency != 1.0f && g != null)
     {
+      /*
+       * get colour as rendered including transparency
+       * and reset transparency
+       */
+      if (offscreenImage != null && drawnColour != null)
+      {
+        drawnColour = new Color(offscreenImage.getRGB(0, 0));
+      }
       Graphics2D g2 = (Graphics2D) g;
-      g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
-              1.0f));
+      g2.setComposite(NO_TRANSPARENCY);
     }
+
+    return drawnColour;
   }
 
   /**
@@ -462,4 +458,69 @@ public class FeatureRenderer extends FeatureRendererModel
     lastSeq = null;
     findAllFeatures();
   }
+
+  /**
+   * Returns the sequence feature colour rendered at the given sequence
+   * position, or null if none found. The feature of highest render order (i.e.
+   * on top) is found, subject to both feature type and feature group being
+   * visible, and its colour returned.
+   * 
+   * @param seq
+   * @param pos
+   * @return
+   */
+  Color findFeatureColour(SequenceI seq, int pos)
+  {
+    SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
+    if (sequenceFeatures == null || sequenceFeatures.length == 0)
+    {
+      return null;
+    }
+  
+    // updateFeatures();
+
+    /*
+     * inspect features in reverse renderOrder (the last in the array is 
+     * displayed on top) until we find one that is rendered at the position
+     */
+    for (int renderIndex = renderOrder.length - 1; renderIndex >= 0; renderIndex--)
+    {
+      String type = renderOrder[renderIndex];
+      if (!showFeatureOfType(type))
+      {
+        continue;
+      }
+
+      for (int sfindex = 0; sfindex < sequenceFeatures.length; sfindex++)
+      {
+        SequenceFeature sequenceFeature = sequenceFeatures[sfindex];
+        if (!sequenceFeature.type.equals(type))
+        {
+          continue;
+        }
+
+        if (featureGroupNotShown(sequenceFeature))
+        {
+          continue;
+        }
+
+        boolean featureIsAtPosition = sequenceFeature.begin <= pos
+                && sequenceFeature.end >= pos;
+        if (sequenceFeature.isContactFeature())
+        {
+          featureIsAtPosition = sequenceFeature.begin == pos
+                  || sequenceFeature.end == pos;
+        }
+        if (featureIsAtPosition)
+        {
+          return getColour(sequenceFeature);
+        }
+      }
+    }
+  
+    /*
+     * no displayed feature found at position
+     */
+    return null;
+  }
 }
index 7d57886..82ba2d7 100644 (file)
@@ -20,9 +20,7 @@
  */
 package jalview.structures.models;
 
-import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
-import jalview.api.FeatureRenderer;
 import jalview.api.SequenceRenderer;
 import jalview.api.StructureSelectionManagerProvider;
 import jalview.api.structures.JalviewStructureDisplayI;
@@ -724,18 +722,7 @@ public abstract class AAStructureBindingModel extends
   public abstract void setBackgroundColour(Color col);
 
   protected abstract StructureMappingcommandSet[] getColourBySequenceCommands(
-          String[] files, SequenceRenderer sr, FeatureRenderer fr,
-          AlignViewportI alignViewportI);
-
-  /**
-   * returns the current featureRenderer that should be used to colour the
-   * structures
-   * 
-   * @param alignment
-   * 
-   * @return
-   */
-  public abstract FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment);
+          String[] files, SequenceRenderer sr, AlignmentViewPanel avp);
 
   /**
    * returns the current sequenceRenderer that should be used to colour the
@@ -773,16 +760,8 @@ public abstract class AAStructureBindingModel extends
   
     SequenceRenderer sr = getSequenceRenderer(alignmentv);
   
-    FeatureRenderer fr = null;
-    boolean showFeatures = alignmentv.getAlignViewport()
-            .isShowSequenceFeatures();
-    if (showFeatures)
-    {
-      fr = getFeatureRenderer(alignmentv);
-    }
-  
     StructureMappingcommandSet[] colourBySequenceCommands = getColourBySequenceCommands(
-            files, sr, fr, alignmentv.getAlignViewport());
+            files, sr, alignmentv);
     colourBySequence(colourBySequenceCommands);
   }
 
@@ -790,4 +769,7 @@ public abstract class AAStructureBindingModel extends
   {
     return fileLoadingError != null && fileLoadingError.length() > 0;
   }
+
+  protected abstract jalview.api.FeatureRenderer getFeatureRenderer(
+          AlignmentViewPanel alignment);
 }
index 8468329..085743f 100644 (file)
@@ -822,7 +822,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)
     {
index 89da196..2c23311 100644 (file)
@@ -58,7 +58,6 @@ public class JmolCommandsTest
     // need some mappings!
 
     StructureMappingcommandSet[] commands = JmolCommands
-            .getColourBySequenceCommand(ssm, files, seqs, sr, null,
-                    af.getViewport());
+            .getColourBySequenceCommand(ssm, files, seqs, sr, af.alignPanel);
   }
 }
index d351171..49a951e 100644 (file)
@@ -202,8 +202,7 @@ public class ChimeraCommandsTest
     ssm.addStructureMapping(sm2);
 
     StructureMappingcommandSet[] commands = ChimeraCommands
-            .getColourBySequenceCommand(ssm, files, seqs, sr, null,
-                    af.getViewport());
+            .getColourBySequenceCommand(ssm, files, seqs, sr, af.alignPanel);
     assertEquals(1, commands.length);
     assertEquals(1, commands[0].commands.length);
     String theCommand = commands[0].commands[0];
index c92daea..30f9e68 100644 (file)
@@ -24,7 +24,6 @@ import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
 import static org.testng.AssertJUnit.assertTrue;
 
-import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.api.FeatureRenderer;
 import jalview.api.SequenceRenderer;
@@ -184,14 +183,7 @@ public class AAStructureBindingModelTest
 
       @Override
       protected StructureMappingcommandSet[] getColourBySequenceCommands(
-              String[] files, SequenceRenderer sr, FeatureRenderer fr,
-              AlignViewportI viewport)
-      {
-        return null;
-      }
-
-      @Override
-      public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment)
+              String[] files, SequenceRenderer sr, AlignmentViewPanel avp)
       {
         return null;
       }
@@ -218,6 +210,13 @@ public class AAStructureBindingModelTest
       public void colourByCharge()
       {
       }
+
+      @Override
+      protected FeatureRenderer getFeatureRenderer(
+              AlignmentViewPanel alignment)
+      {
+        return null;
+      }
     };
   }