JAL-3187 'on top' optional for complementary features
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 13 Feb 2019 14:36:54 +0000 (14:36 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Mon, 18 Feb 2019 09:08:39 +0000 (09:08 +0000)
Conflicts:
src/jalview/gui/FeatureSettings.java

src/jalview/api/ViewStyleI.java
src/jalview/gui/FeatureSettings.java
src/jalview/renderer/seqfeatures/FeatureRenderer.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/viewmodel/styles/ViewStyle.java

index 978ce61..a348300 100644 (file)
@@ -28,6 +28,10 @@ public interface ViewStyleI
 
   boolean isShowComplementFeatures();
 
+  void setShowComplementFeaturesOnTop(boolean b);
+
+  boolean isShowComplementFeaturesOnTop();
+
   void setColourAppliesToAllGroups(boolean b);
 
   boolean getColourAppliesToAllGroups();
index 7b8eae4..9dbeb8a 100644 (file)
@@ -44,6 +44,7 @@ import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.Dimension;
+import java.awt.FlowLayout;
 import java.awt.Font;
 import java.awt.Graphics;
 import java.awt.GridLayout;
@@ -153,6 +154,8 @@ public class FeatureSettings extends JPanel
 
   JCheckBox showComplement;
 
+  JCheckBox showComplementOnTop;
+
   /*
    * when true, constructor is still executing - so ignore UI events
    */
@@ -1278,8 +1281,22 @@ public class FeatureSettings extends JPanel
       }
     });
 
-    JPanel transPanel = new JPanel(new GridLayout(1, 2));
-    bigPanel.add(transPanel, BorderLayout.SOUTH);
+    showComplementOnTop = new JCheckBox("on top");
+    showComplementOnTop
+            .setSelected(af.getViewport().isShowComplementFeaturesOnTop());
+    showComplementOnTop.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        af.getViewport().setShowComplementFeaturesOnTop(
+                showComplementOnTop.isSelected());
+        refreshDisplay();
+      }
+    });
+
+    JPanel lowerPanel = new JPanel(new GridLayout(1, 2));
+    bigPanel.add(lowerPanel, BorderLayout.SOUTH);
 
     JPanel transbuttons = new JPanel(new GridLayout(5, 1));
     transbuttons.add(optimizeOrder);
@@ -1290,14 +1307,18 @@ public class FeatureSettings extends JPanel
 
     boolean hasComplement = af.getViewport().getCodingComplement() != null;
     JPanel transPanelLeft = new JPanel(
-            new GridLayout(hasComplement ? 2 : 1, 1));
+            new GridLayout(hasComplement ? 3 : 2, 1));
+    transPanelLeft.add(new JLabel(" Colour transparency" + ":"));
     transPanelLeft.add(transparency);
     if (hasComplement)
     {
-      transPanelLeft.add(showComplement);
+      JPanel cp = new JPanel(new FlowLayout(FlowLayout.LEFT));
+      cp.add(showComplement);
+      cp.add(showComplementOnTop);
+      transPanelLeft.add(cp);
     }
-    transPanel.add(transPanelLeft);
-    transPanel.add(transbuttons);
+    lowerPanel.add(transPanelLeft);
+    lowerPanel.add(transbuttons);
 
     JPanel buttonPanel = new JPanel();
     buttonPanel.add(ok);
index 4e81e69..78f4989 100644 (file)
@@ -294,6 +294,16 @@ public class FeatureRenderer extends FeatureRendererModel
     Color drawnColour = null;
 
     /*
+     * draw 'complement' features below ours if configured to do so
+     */
+    if (av.isShowComplementFeatures()
+            && !av.isShowComplementFeaturesOnTop())
+    {
+      drawnColour = drawComplementFeatures(g, seq, start, end, y1,
+              colourOnly, visiblePositions, drawnColour);
+    }
+
+    /*
      * iterate over features in ordering of their rendering (last is on top)
      */
     for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
@@ -399,27 +409,12 @@ public class FeatureRenderer extends FeatureRendererModel
     }
 
     /*
-     * if configured to do so, find and show complement's features
+     * draw 'complement' features above ours if configured to do so
      */
-    if (av.isShowComplementFeatures())
+    if (av.isShowComplementFeatures() && av.isShowComplementFeaturesOnTop())
     {
-      AlignViewportI comp = av.getCodingComplement();
-      FeatureRenderer fr2 = Desktop.getAlignFrameFor(comp)
-              .getFeatureRenderer();
-      for (int pos = visiblePositions.start; pos <= visiblePositions.end; pos++)
-      {
-        int column = seq.findIndex(pos);
-        List<SequenceFeature> features = fr2
-                .findComplementFeaturesAtResidue(seq, pos);
-        for (SequenceFeature sf : features)
-        {
-          FeatureColourI fc = fr2.getFeatureStyle(sf.getType());
-          Color featureColour = fr2.getColor(sf, fc);
-          renderFeature(g, seq, column - 1, column - 1, featureColour,
-                  start, end, y1, colourOnly);
-          drawnColour = featureColour;
-        }
-      }
+      drawnColour = drawComplementFeatures(g, seq, start, end, y1,
+              colourOnly, visiblePositions, drawnColour);
     }
 
     if (transparency != 1.0f && g != null)
@@ -435,6 +430,45 @@ public class FeatureRenderer extends FeatureRendererModel
   }
 
   /**
+   * Find any features on the CDS/protein complement of the sequence region and
+   * draw them, with visibility and colouring as configured in the complementary
+   * viewport
+   * 
+   * @param g
+   * @param seq
+   * @param start
+   * @param end
+   * @param y1
+   * @param colourOnly
+   * @param visiblePositions
+   * @param drawnColour
+   * @return
+   */
+  Color drawComplementFeatures(final Graphics g, final SequenceI seq,
+          int start, int end, int y1, boolean colourOnly,
+          Range visiblePositions, Color drawnColour)
+  {
+    AlignViewportI comp = av.getCodingComplement();
+    FeatureRenderer fr2 = Desktop.getAlignFrameFor(comp)
+            .getFeatureRenderer();
+    for (int pos = visiblePositions.start; pos <= visiblePositions.end; pos++)
+    {
+      int column = seq.findIndex(pos);
+      List<SequenceFeature> features = fr2
+              .findComplementFeaturesAtResidue(seq, pos);
+      for (SequenceFeature sf : features)
+      {
+        FeatureColourI fc = fr2.getFeatureStyle(sf.getType());
+        Color featureColour = fr2.getColor(sf, fc);
+        renderFeature(g, seq, column - 1, column - 1, featureColour,
+                start, end, y1, colourOnly);
+        drawnColour = featureColour;
+      }
+    }
+    return drawnColour;
+  }
+
+  /**
    * Called when alignment in associated view has new/modified features to
    * discover and display.
    * 
@@ -471,27 +505,12 @@ public class FeatureRenderer extends FeatureRendererModel
     /*
      * show complement features on top (if configured to show them)
      */
-    if (av.isShowComplementFeatures())
+    if (av.isShowComplementFeatures() && av.isShowComplementFeaturesOnTop())
     {
-      AlignViewportI complement = av.getCodingComplement();
-      AlignFrame af = Desktop.getAlignFrameFor(complement);
-      FeatureRendererModel fr2 = af.getFeatureRenderer();
-      List<SequenceFeature> features = fr2.findComplementFeaturesAtResidue(
-              seq, seq.findPosition(column - 1));
-
-      ReverseListIterator<SequenceFeature> it = new ReverseListIterator<>(
-              features);
-      while (it.hasNext())
+      Color col = findComplementFeatureColour(seq, column);
+      if (col != null)
       {
-        SequenceFeature sf = it.next();
-        if (!fr2.featureGroupNotShown(sf))
-        {
-          Color col = fr2.getColour(sf);
-          if (col != null)
-          {
-            return col;
-          }
-        }
+        return col;
       }
     }
 
@@ -524,8 +543,40 @@ public class FeatureRenderer extends FeatureRendererModel
     }
 
     /*
-     * no displayed feature found at position
+     * show complement features underneath (if configured to show them)
      */
+    Color col = null;
+    if (av.isShowComplementFeatures()
+            && !av.isShowComplementFeaturesOnTop())
+    {
+      col = findComplementFeatureColour(seq, column);
+    }
+
+    return col;
+  }
+
+  Color findComplementFeatureColour(SequenceI seq, int column)
+  {
+    AlignViewportI complement = av.getCodingComplement();
+    AlignFrame af = Desktop.getAlignFrameFor(complement);
+    FeatureRendererModel fr2 = af.getFeatureRenderer();
+    List<SequenceFeature> features = fr2.findComplementFeaturesAtResidue(
+            seq, seq.findPosition(column - 1));
+
+    ReverseListIterator<SequenceFeature> it = new ReverseListIterator<>(
+            features);
+    while (it.hasNext())
+    {
+      SequenceFeature sf = it.next();
+      if (!fr2.featureGroupNotShown(sf))
+      {
+        Color col = fr2.getColour(sf);
+        if (col != null)
+        {
+          return col;
+        }
+      }
+    }
     return null;
   }
 }
index ec3f12e..1ae879b 100644 (file)
@@ -2726,6 +2726,18 @@ public abstract class AlignmentViewport
     return viewStyle.isShowComplementFeatures();
   }
 
+  @Override
+  public void setShowComplementFeaturesOnTop(boolean b)
+  {
+    viewStyle.setShowComplementFeaturesOnTop(b);
+  }
+
+  @Override
+  public boolean isShowComplementFeaturesOnTop()
+  {
+    return viewStyle.isShowComplementFeaturesOnTop();
+  }
+
   /**
    * @return true if view should scroll to show the highlighted region of a
    *         sequence
index d68227b..7fa1e39 100644 (file)
@@ -369,6 +369,8 @@ public class ViewStyle implements ViewStyleI
 
   private boolean showComplementFeatures;
 
+  private boolean showComplementFeaturesOnTop;
+
   /**
    * GUI state
    * 
@@ -1127,4 +1129,16 @@ public class ViewStyle implements ViewStyleI
   {
     return showComplementFeatures;
   }
+
+  @Override
+  public void setShowComplementFeaturesOnTop(boolean b)
+  {
+    showComplementFeaturesOnTop = b;
+  }
+
+  @Override
+  public boolean isShowComplementFeaturesOnTop()
+  {
+    return showComplementFeaturesOnTop;
+  }
 }