JAL-969 refactor columnselection operation (during JAL-2001)
[jalview.git] / src / jalview / viewmodel / AlignmentViewport.java
index 899e8a7..b70e92b 100644 (file)
@@ -49,6 +49,7 @@ import jalview.structure.CommandListener;
 import jalview.structure.StructureSelectionManager;
 import jalview.structure.VamsasSource;
 import jalview.util.Comparison;
+import jalview.util.MapList;
 import jalview.util.MappingUtils;
 import jalview.viewmodel.styles.ViewStyle;
 import jalview.workers.AlignCalcManager;
@@ -65,7 +66,6 @@ import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * base class holding visualization and analysis attributes and common logic for
@@ -95,6 +95,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param name
    * @see jalview.api.ViewStyleI#setFontName(java.lang.String)
    */
+  @Override
   public void setFontName(String name)
   {
     viewStyle.setFontName(name);
@@ -104,6 +105,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param style
    * @see jalview.api.ViewStyleI#setFontStyle(int)
    */
+  @Override
   public void setFontStyle(int style)
   {
     viewStyle.setFontStyle(style);
@@ -113,6 +115,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param size
    * @see jalview.api.ViewStyleI#setFontSize(int)
    */
+  @Override
   public void setFontSize(int size)
   {
     viewStyle.setFontSize(size);
@@ -122,6 +125,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getFontStyle()
    */
+  @Override
   public int getFontStyle()
   {
     return viewStyle.getFontStyle();
@@ -131,6 +135,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getFontName()
    */
+  @Override
   public String getFontName()
   {
     return viewStyle.getFontName();
@@ -140,6 +145,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getFontSize()
    */
+  @Override
   public int getFontSize()
   {
     return viewStyle.getFontSize();
@@ -149,6 +155,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param upperCasebold
    * @see jalview.api.ViewStyleI#setUpperCasebold(boolean)
    */
+  @Override
   public void setUpperCasebold(boolean upperCasebold)
   {
     viewStyle.setUpperCasebold(upperCasebold);
@@ -158,6 +165,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#isUpperCasebold()
    */
+  @Override
   public boolean isUpperCasebold()
   {
     return viewStyle.isUpperCasebold();
@@ -167,6 +175,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#isSeqNameItalics()
    */
+  @Override
   public boolean isSeqNameItalics()
   {
     return viewStyle.isSeqNameItalics();
@@ -176,6 +185,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param colourByReferenceSeq
    * @see jalview.api.ViewStyleI#setColourByReferenceSeq(boolean)
    */
+  @Override
   public void setColourByReferenceSeq(boolean colourByReferenceSeq)
   {
     viewStyle.setColourByReferenceSeq(colourByReferenceSeq);
@@ -185,6 +195,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param b
    * @see jalview.api.ViewStyleI#setColourAppliesToAllGroups(boolean)
    */
+  @Override
   public void setColourAppliesToAllGroups(boolean b)
   {
     viewStyle.setColourAppliesToAllGroups(b);
@@ -194,6 +205,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getColourAppliesToAllGroups()
    */
+  @Override
   public boolean getColourAppliesToAllGroups()
   {
     return viewStyle.getColourAppliesToAllGroups();
@@ -203,6 +215,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getAbovePIDThreshold()
    */
+  @Override
   public boolean getAbovePIDThreshold()
   {
     return viewStyle.getAbovePIDThreshold();
@@ -212,6 +225,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param inc
    * @see jalview.api.ViewStyleI#setIncrement(int)
    */
+  @Override
   public void setIncrement(int inc)
   {
     viewStyle.setIncrement(inc);
@@ -221,6 +235,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getIncrement()
    */
+  @Override
   public int getIncrement()
   {
     return viewStyle.getIncrement();
@@ -230,6 +245,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param b
    * @see jalview.api.ViewStyleI#setConservationSelected(boolean)
    */
+  @Override
   public void setConservationSelected(boolean b)
   {
     viewStyle.setConservationSelected(b);
@@ -239,6 +255,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param show
    * @see jalview.api.ViewStyleI#setShowHiddenMarkers(boolean)
    */
+  @Override
   public void setShowHiddenMarkers(boolean show)
   {
     viewStyle.setShowHiddenMarkers(show);
@@ -248,6 +265,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getShowHiddenMarkers()
    */
+  @Override
   public boolean getShowHiddenMarkers()
   {
     return viewStyle.getShowHiddenMarkers();
@@ -257,6 +275,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param b
    * @see jalview.api.ViewStyleI#setScaleRightWrapped(boolean)
    */
+  @Override
   public void setScaleRightWrapped(boolean b)
   {
     viewStyle.setScaleRightWrapped(b);
@@ -266,6 +285,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param b
    * @see jalview.api.ViewStyleI#setScaleLeftWrapped(boolean)
    */
+  @Override
   public void setScaleLeftWrapped(boolean b)
   {
     viewStyle.setScaleLeftWrapped(b);
@@ -275,6 +295,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param b
    * @see jalview.api.ViewStyleI#setScaleAboveWrapped(boolean)
    */
+  @Override
   public void setScaleAboveWrapped(boolean b)
   {
     viewStyle.setScaleAboveWrapped(b);
@@ -284,6 +305,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getScaleLeftWrapped()
    */
+  @Override
   public boolean getScaleLeftWrapped()
   {
     return viewStyle.getScaleLeftWrapped();
@@ -293,6 +315,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getScaleAboveWrapped()
    */
+  @Override
   public boolean getScaleAboveWrapped()
   {
     return viewStyle.getScaleAboveWrapped();
@@ -302,6 +325,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getScaleRightWrapped()
    */
+  @Override
   public boolean getScaleRightWrapped()
   {
     return viewStyle.getScaleRightWrapped();
@@ -311,6 +335,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param b
    * @see jalview.api.ViewStyleI#setAbovePIDThreshold(boolean)
    */
+  @Override
   public void setAbovePIDThreshold(boolean b)
   {
     viewStyle.setAbovePIDThreshold(b);
@@ -320,6 +345,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param thresh
    * @see jalview.api.ViewStyleI#setThreshold(int)
    */
+  @Override
   public void setThreshold(int thresh)
   {
     viewStyle.setThreshold(thresh);
@@ -329,6 +355,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getThreshold()
    */
+  @Override
   public int getThreshold()
   {
     return viewStyle.getThreshold();
@@ -338,6 +365,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getShowJVSuffix()
    */
+  @Override
   public boolean getShowJVSuffix()
   {
     return viewStyle.getShowJVSuffix();
@@ -347,6 +375,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param b
    * @see jalview.api.ViewStyleI#setShowJVSuffix(boolean)
    */
+  @Override
   public void setShowJVSuffix(boolean b)
   {
     viewStyle.setShowJVSuffix(b);
@@ -356,6 +385,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param state
    * @see jalview.api.ViewStyleI#setWrapAlignment(boolean)
    */
+  @Override
   public void setWrapAlignment(boolean state)
   {
     viewStyle.setWrapAlignment(state);
@@ -365,6 +395,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param state
    * @see jalview.api.ViewStyleI#setShowText(boolean)
    */
+  @Override
   public void setShowText(boolean state)
   {
     viewStyle.setShowText(state);
@@ -374,6 +405,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param state
    * @see jalview.api.ViewStyleI#setRenderGaps(boolean)
    */
+  @Override
   public void setRenderGaps(boolean state)
   {
     viewStyle.setRenderGaps(state);
@@ -383,6 +415,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getColourText()
    */
+  @Override
   public boolean getColourText()
   {
     return viewStyle.getColourText();
@@ -392,6 +425,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param state
    * @see jalview.api.ViewStyleI#setColourText(boolean)
    */
+  @Override
   public void setColourText(boolean state)
   {
     viewStyle.setColourText(state);
@@ -401,6 +435,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getWrapAlignment()
    */
+  @Override
   public boolean getWrapAlignment()
   {
     return viewStyle.getWrapAlignment();
@@ -410,6 +445,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getShowText()
    */
+  @Override
   public boolean getShowText()
   {
     return viewStyle.getShowText();
@@ -419,6 +455,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getWrappedWidth()
    */
+  @Override
   public int getWrappedWidth()
   {
     return viewStyle.getWrappedWidth();
@@ -428,6 +465,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param w
    * @see jalview.api.ViewStyleI#setWrappedWidth(int)
    */
+  @Override
   public void setWrappedWidth(int w)
   {
     viewStyle.setWrappedWidth(w);
@@ -437,6 +475,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getCharHeight()
    */
+  @Override
   public int getCharHeight()
   {
     return viewStyle.getCharHeight();
@@ -446,6 +485,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param h
    * @see jalview.api.ViewStyleI#setCharHeight(int)
    */
+  @Override
   public void setCharHeight(int h)
   {
     viewStyle.setCharHeight(h);
@@ -455,6 +495,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getCharWidth()
    */
+  @Override
   public int getCharWidth()
   {
     return viewStyle.getCharWidth();
@@ -464,6 +505,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param w
    * @see jalview.api.ViewStyleI#setCharWidth(int)
    */
+  @Override
   public void setCharWidth(int w)
   {
     viewStyle.setCharWidth(w);
@@ -473,6 +515,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getShowBoxes()
    */
+  @Override
   public boolean getShowBoxes()
   {
     return viewStyle.getShowBoxes();
@@ -482,6 +525,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getShowUnconserved()
    */
+  @Override
   public boolean getShowUnconserved()
   {
     return viewStyle.getShowUnconserved();
@@ -491,6 +535,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param showunconserved
    * @see jalview.api.ViewStyleI#setShowUnconserved(boolean)
    */
+  @Override
   public void setShowUnconserved(boolean showunconserved)
   {
     viewStyle.setShowUnconserved(showunconserved);
@@ -500,6 +545,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param default1
    * @see jalview.api.ViewStyleI#setSeqNameItalics(boolean)
    */
+  @Override
   public void setSeqNameItalics(boolean default1)
   {
     viewStyle.setSeqNameItalics(default1);
@@ -540,7 +586,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return isDataset;
   }
 
-
   private Map<SequenceI, SequenceCollectionI> hiddenRepSequences;
 
   protected ColumnSelection colSel = new ColumnSelection();
@@ -553,12 +598,11 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   protected ColourSchemeI globalColourScheme = null;
 
-
   @Override
   public void setGlobalColourScheme(ColourSchemeI cs)
   {
     // TODO: logic refactored from AlignFrame changeColour -
-    // autorecalc stuff should be changed to rely on the worker system
+    // TODO: autorecalc stuff should be changed to rely on the worker system
     // check to see if we should implement a changeColour(cs) method rather than
     // put th logic in here
     // - means that caller decides if they want to just modify state and defer
@@ -630,7 +674,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
         }
       }
     }
-
   }
 
   @Override
@@ -794,15 +837,28 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
     /*
      * A separate thread to compute cDNA consensus for a protein alignment
+     * which has mapping to cDNA
      */
     final AlignmentI al = this.getAlignment();
     if (!al.isNucleotide() && al.getCodonFrames() != null
             && !al.getCodonFrames().isEmpty())
     {
-      if (calculator
-              .getRegisteredWorkersOfClass(ComplementConsensusThread.class) == null)
+      /*
+       * fudge - check first mapping is protein-to-nucleotide
+       * (we don't want to do this for protein-to-protein)
+       */
+      AlignedCodonFrame mapping = al.getCodonFrames().iterator().next();
+      // TODO hold mapping type e.g. dna-to-protein in AlignedCodonFrame?
+      MapList[] mapLists = mapping.getdnaToProt();
+      // mapLists can be empty if project load has not finished resolving seqs
+      if (mapLists.length > 0 && mapLists[0].getFromRatio() == 3)
       {
-        calculator.registerWorker(new ComplementConsensusThread(this, ap));
+        if (calculator
+                .getRegisteredWorkersOfClass(ComplementConsensusThread.class) == null)
+        {
+          calculator
+                  .registerWorker(new ComplementConsensusThread(this, ap));
+        }
       }
     }
   }
@@ -979,7 +1035,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
    */
   public boolean sortByTree = false;
 
-
   /**
    * 
    * 
@@ -1061,7 +1116,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return alignment.getHiddenSequences().getSize() > 0;
   }
 
-
   protected SequenceGroup selectionGroup;
 
   public void setSequenceSetId(String newid)
@@ -1152,7 +1206,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    */
   public boolean isColSelChanged(boolean b)
   {
-    int hc = (colSel == null || colSel.size() == 0) ? -1 : colSel
+    int hc = (colSel == null || colSel.isEmpty()) ? -1 : colSel
             .hashCode();
     if (hc != -1 && hc != colselhash)
     {
@@ -1247,7 +1301,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   public void hideSelectedColumns()
   {
-    if (colSel.size() < 1)
+    if (colSel.isEmpty())
     {
       return;
     }
@@ -1310,8 +1364,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
   public void showSequence(int index)
   {
     List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(
-            index,
-            hiddenRepSequences);
+            index, hiddenRepSequences);
     if (tmp.size() > 0)
     {
       if (selectionGroup == null)
@@ -1384,7 +1437,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
     if (hiddenRepSequences == null)
     {
-      hiddenRepSequences = new Hashtable();
+      hiddenRepSequences = new Hashtable<SequenceI, SequenceCollectionI>();
     }
 
     hiddenRepSequences.put(repSequence, sg);
@@ -1412,8 +1465,9 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   public boolean isHiddenRepSequence(SequenceI seq)
   {
-    return alignment.getSeqrep()==seq || (hiddenRepSequences != null
-            && hiddenRepSequences.containsKey(seq));
+    return alignment.getSeqrep() == seq
+            || (hiddenRepSequences != null && hiddenRepSequences
+                    .containsKey(seq));
   }
 
   public SequenceGroup getRepresentedSequences(SequenceI seq)
@@ -1435,7 +1489,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     colSel.invertColumnSelection(0, alignment.getWidth());
   }
 
-
   @Override
   public SequenceI[] getSelectionAsNewSequence()
   {
@@ -1463,7 +1516,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return sequences;
   }
 
-
   @Override
   public SequenceI[] getSequenceSelection()
   {
@@ -1479,16 +1531,13 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return sequences;
   }
 
-
   @Override
-  public CigarArray getViewAsCigars(
-          boolean selectedRegionOnly)
+  public CigarArray getViewAsCigars(boolean selectedRegionOnly)
   {
     return new CigarArray(alignment, colSel,
             (selectedRegionOnly ? selectionGroup : null));
   }
 
-
   @Override
   public jalview.datamodel.AlignmentView getAlignmentView(
           boolean selectedOnly)
@@ -1496,7 +1545,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return getAlignmentView(selectedOnly, false);
   }
 
-
   @Override
   public jalview.datamodel.AlignmentView getAlignmentView(
           boolean selectedOnly, boolean markGroups)
@@ -1506,7 +1554,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
             markGroups);
   }
 
-
   @Override
   public String[] getViewAsString(boolean selectedRegionOnly)
   {
@@ -1523,9 +1570,20 @@ public abstract class AlignmentViewport implements AlignViewportI,
     }
     else
     {
-      iSize = alignment.getHeight();
-      seqs = alignment.getSequencesArray();
-      end = alignment.getWidth();
+      if (hasHiddenRows())
+      {
+        iSize = alignment.getHiddenSequences().getFullAlignment()
+                .getHeight();
+        seqs = alignment.getHiddenSequences().getFullAlignment()
+                .getSequencesArray();
+        end = alignment.getHiddenSequences().getFullAlignment().getWidth();
+      }
+      else
+      {
+        iSize = alignment.getHeight();
+        seqs = alignment.getSequencesArray();
+        end = alignment.getWidth();
+      }
     }
 
     selection = new String[iSize];
@@ -1544,7 +1602,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return selection;
   }
 
-
   @Override
   public List<int[]> getVisibleRegionBoundaries(int min, int max)
   {
@@ -1572,8 +1629,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
         }
       }
 
-      regions.add(new int[]
-      { start, end });
+      regions.add(new int[] { start, end });
 
       if (colSel != null && colSel.hasHiddenColumns())
       {
@@ -1588,19 +1644,23 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   @Override
-  public List<AlignmentAnnotation> getVisibleAlignmentAnnotation(boolean selectedOnly)
+  public List<AlignmentAnnotation> getVisibleAlignmentAnnotation(
+          boolean selectedOnly)
   {
     ArrayList<AlignmentAnnotation> ala = new ArrayList<AlignmentAnnotation>();
     AlignmentAnnotation[] aa;
-    if ((aa=alignment.getAlignmentAnnotation())!=null)
+    if ((aa = alignment.getAlignmentAnnotation()) != null)
     {
-      for (AlignmentAnnotation annot:aa)
+      for (AlignmentAnnotation annot : aa)
       {
         AlignmentAnnotation clone = new AlignmentAnnotation(annot);
-        if (selectedOnly && selectionGroup!=null)
+        if (selectedOnly && selectionGroup != null)
+        {
+          colSel.makeVisibleAnnotation(selectionGroup.getStartRes(),
+                  selectionGroup.getEndRes(), clone);
+        }
+        else
         {
-          colSel.makeVisibleAnnotation(selectionGroup.getStartRes(), selectionGroup.getEndRes(),clone);
-        } else {
           colSel.makeVisibleAnnotation(clone);
         }
         ala.add(clone);
@@ -1609,14 +1669,12 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return ala;
   }
 
-
   @Override
   public boolean isPadGaps()
   {
     return padGaps;
   }
 
-
   @Override
   public void setPadGaps(boolean padGaps)
   {
@@ -1735,14 +1793,22 @@ public abstract class AlignmentViewport implements AlignViewportI,
   {
     if (!alignment.isNucleotide())
     {
-      final Set<AlignedCodonFrame> codonMappings = alignment
+      final List<AlignedCodonFrame> codonMappings = alignment
               .getCodonFrames();
       if (codonMappings != null && !codonMappings.isEmpty())
       {
-        complementConsensus = new AlignmentAnnotation("cDNA Consensus",
-                "PID for cDNA", new Annotation[1], 0f, 100f,
-                AlignmentAnnotation.BAR_GRAPH);
-        initConsensus(complementConsensus);
+        // fudge: check mappings are not protein-to-protein
+        // TODO: nicer
+        AlignedCodonFrame mapping = codonMappings.iterator().next();
+        MapList[] mapLists = mapping.getdnaToProt();
+        // mapLists can be empty if project load has not finished resolving seqs
+        if (mapLists.length > 0 && mapLists[0].getFromRatio() == 3)
+        {
+          complementConsensus = new AlignmentAnnotation("cDNA Consensus",
+                  "PID for cDNA", new Annotation[1], 0f, 100f,
+                  AlignmentAnnotation.BAR_GRAPH);
+          initConsensus(complementConsensus);
+        }
       }
     }
   }
@@ -1944,6 +2010,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
     }
     oldrfs.clear();
   }
+
   @Override
   public boolean isDisplayReferenceSeq()
   {
@@ -2052,7 +2119,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
   @Override
   public boolean areFeaturesDisplayed()
   {
-    return featuresDisplayed != null && featuresDisplayed.getRegisterdFeaturesCount()>0;
+    return featuresDisplayed != null
+            && featuresDisplayed.getRegisteredFeaturesCount() > 0;
   }
 
   /**
@@ -2066,6 +2134,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
   {
     viewStyle.setShowSequenceFeatures(b);
   }
+
   @Override
   public boolean isShowSequenceFeatures()
   {
@@ -2084,8 +2153,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return viewStyle.isShowSequenceFeaturesHeight();
   }
 
-
-
   @Override
   public void setShowAnnotation(boolean b)
   {
@@ -2126,6 +2193,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getTextColour()
    */
+  @Override
   public Color getTextColour()
   {
     return viewStyle.getTextColour();
@@ -2135,6 +2203,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getTextColour2()
    */
+  @Override
   public Color getTextColour2()
   {
     return viewStyle.getTextColour2();
@@ -2144,6 +2213,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getThresholdTextColour()
    */
+  @Override
   public int getThresholdTextColour()
   {
     return viewStyle.getThresholdTextColour();
@@ -2153,6 +2223,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#isConservationColourSelected()
    */
+  @Override
   public boolean isConservationColourSelected()
   {
     return viewStyle.isConservationColourSelected();
@@ -2162,6 +2233,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#isRenderGaps()
    */
+  @Override
   public boolean isRenderGaps()
   {
     return viewStyle.isRenderGaps();
@@ -2171,6 +2243,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#isShowColourText()
    */
+  @Override
   public boolean isShowColourText()
   {
     return viewStyle.isShowColourText();
@@ -2180,6 +2253,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param conservationColourSelected
    * @see jalview.api.ViewStyleI#setConservationColourSelected(boolean)
    */
+  @Override
   public void setConservationColourSelected(
           boolean conservationColourSelected)
   {
@@ -2190,6 +2264,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param showColourText
    * @see jalview.api.ViewStyleI#setShowColourText(boolean)
    */
+  @Override
   public void setShowColourText(boolean showColourText)
   {
     viewStyle.setShowColourText(showColourText);
@@ -2199,6 +2274,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param textColour
    * @see jalview.api.ViewStyleI#setTextColour(java.awt.Color)
    */
+  @Override
   public void setTextColour(Color textColour)
   {
     viewStyle.setTextColour(textColour);
@@ -2208,6 +2284,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param thresholdTextColour
    * @see jalview.api.ViewStyleI#setThresholdTextColour(int)
    */
+  @Override
   public void setThresholdTextColour(int thresholdTextColour)
   {
     viewStyle.setThresholdTextColour(thresholdTextColour);
@@ -2217,6 +2294,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param textColour2
    * @see jalview.api.ViewStyleI#setTextColour2(java.awt.Color)
    */
+  @Override
   public void setTextColour2(Color textColour2)
   {
     viewStyle.setTextColour2(textColour2);
@@ -2244,6 +2322,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#getIdWidth()
    */
+  @Override
   public int getIdWidth()
   {
     return viewStyle.getIdWidth();
@@ -2253,6 +2332,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param i
    * @see jalview.api.ViewStyleI#setIdWidth(int)
    */
+  @Override
   public void setIdWidth(int i)
   {
     viewStyle.setIdWidth(i);
@@ -2262,6 +2342,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#isCentreColumnLabels()
    */
+  @Override
   public boolean isCentreColumnLabels()
   {
     return viewStyle.isCentreColumnLabels();
@@ -2271,6 +2352,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param centreColumnLabels
    * @see jalview.api.ViewStyleI#setCentreColumnLabels(boolean)
    */
+  @Override
   public void setCentreColumnLabels(boolean centreColumnLabels)
   {
     viewStyle.setCentreColumnLabels(centreColumnLabels);
@@ -2280,6 +2362,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param showdbrefs
    * @see jalview.api.ViewStyleI#setShowDBRefs(boolean)
    */
+  @Override
   public void setShowDBRefs(boolean showdbrefs)
   {
     viewStyle.setShowDBRefs(showdbrefs);
@@ -2289,6 +2372,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#isShowDBRefs()
    */
+  @Override
   public boolean isShowDBRefs()
   {
     return viewStyle.isShowDBRefs();
@@ -2298,6 +2382,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @return
    * @see jalview.api.ViewStyleI#isShowNPFeats()
    */
+  @Override
   public boolean isShowNPFeats()
   {
     return viewStyle.isShowNPFeats();
@@ -2307,6 +2392,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
    * @param shownpfeats
    * @see jalview.api.ViewStyleI#setShowNPFeats(boolean)
    */
+  @Override
   public void setShowNPFeats(boolean shownpfeats)
   {
     viewStyle.setShowNPFeats(shownpfeats);
@@ -2330,7 +2416,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   protected void broadcastCommand(CommandI command, boolean undo)
   {
-    getStructureSelectionManager().commandPerformed(command, undo, getVamsasSource());
+    getStructureSelectionManager().commandPerformed(command, undo,
+            getVamsasSource());
   }
 
   /**
@@ -2438,6 +2525,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return startRes;
   }
 
+  @Override
   public int getEndRes()
   {
     return endRes;
@@ -2507,15 +2595,15 @@ public abstract class AlignmentViewport implements AlignViewportI,
       return 0;
     }
     boolean iAmProtein = !getAlignment().isNucleotide();
-    AlignmentI proteinAlignment = iAmProtein ? getAlignment()
-            : complement.getAlignment();
+    AlignmentI proteinAlignment = iAmProtein ? getAlignment() : complement
+            .getAlignment();
     if (proteinAlignment == null)
     {
       return 0;
     }
-    final Set<AlignedCodonFrame> mappings = proteinAlignment
+    final List<AlignedCodonFrame> mappings = proteinAlignment
             .getCodonFrames();
-  
+
     /*
      * Heuristic: find the first mapped sequence (if any) with a non-gapped
      * residue in the middle column of the visible region. Scroll the
@@ -2531,7 +2619,13 @@ public abstract class AlignmentViewport implements AlignViewportI,
     int middleColumn = getStartRes() + (getEndRes() - getStartRes()) / 2;
     final HiddenSequences hiddenSequences = getAlignment()
             .getHiddenSequences();
-    for (int seqNo = getStartSeq(); seqNo < getEndSeq(); seqNo++, seqOffset++)
+
+    /*
+     * searching to the bottom of the alignment gives smoother scrolling across
+     * all gapped visible regions
+     */
+    int lastSeq = alignment.getHeight() - 1;
+    for (int seqNo = getStartSeq(); seqNo < lastSeq; seqNo++, seqOffset++)
     {
       sequence = getAlignment().getSequenceAt(seqNo);
       if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
@@ -2546,10 +2640,10 @@ public abstract class AlignmentViewport implements AlignViewportI,
               .findMappingsForSequence(sequence, mappings);
       if (!seqMappings.isEmpty())
       {
-          break;
+        break;
       }
     }
-  
+
     if (sequence == null)
     {
       /*
@@ -2561,4 +2655,37 @@ public abstract class AlignmentViewport implements AlignViewportI,
             sequence.findPosition(middleColumn), mappings);
     return seqOffset;
   }
+
+  /**
+   * synthesize a column selection if none exists so it covers the given
+   * selection group. if wholewidth is false, no column selection is made if the
+   * selection group covers the whole alignment width.
+   * 
+   * @param sg
+   * @param wholewidth
+   */
+  public void expandColSelection(SequenceGroup sg, boolean wholewidth)
+  {
+    int sgs, sge;
+    if (sg != null
+            && (sgs = sg.getStartRes()) >= 0
+            && sg.getStartRes() <= (sge = sg.getEndRes())
+            && (colSel == null || colSel.getSelected() == null || colSel
+                    .getSelected().size() == 0))
+    {
+      if (!wholewidth && alignment.getWidth() == (1 + sge - sgs))
+      {
+        // do nothing
+        return;
+      }
+      if (colSel == null)
+      {
+        colSel = new ColumnSelection();
+      }
+      for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++)
+      {
+        colSel.addElement(cspos);
+      }
+    }
+  }
 }