Merge remote-tracking branch
authorkiramt <k.mourao@dundee.ac.uk>
Mon, 24 Apr 2017 13:13:18 +0000 (14:13 +0100)
committerkiramt <k.mourao@dundee.ac.uk>
Mon, 24 Apr 2017 13:13:18 +0000 (14:13 +0100)
'origin/features/JAL-2388hiddencolumnschanges' into
features/JAL-2388OverviewWindow

Conflicts:
src/jalview/appletgui/OverviewPanel.java
src/jalview/gui/OverviewPanel.java
src/jalview/viewmodel/OverviewDimensions.java

17 files changed:
1  2 
src/jalview/appletgui/AlignViewport.java
src/jalview/appletgui/OverviewCanvas.java
src/jalview/appletgui/OverviewPanel.java
src/jalview/datamodel/AllColsCollection.java
src/jalview/datamodel/AllColsIterator.java
src/jalview/datamodel/VisibleColsCollection.java
src/jalview/datamodel/VisibleColsIterator.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/OverviewCanvas.java
src/jalview/gui/OverviewPanel.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/viewmodel/OverviewDimensions.java
src/jalview/viewmodel/OverviewDimensionsAllVisible.java
src/jalview/viewmodel/OverviewDimensionsWithHidden.java
test/jalview/datamodel/AllColsIteratorTest.java
test/jalview/datamodel/VisibleColsIteratorTest.java
test/jalview/viewmodel/OverviewDimensionsTest.java

index 51819cd,0000000..2fbdeab
mode 100644,000000..100644
--- /dev/null
@@@ -1,254 -1,0 +1,254 @@@
 +/*
 + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 + * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * 
 + * This file is part of Jalview.
 + * 
 + * Jalview is free software: you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License 
 + * as published by the Free Software Foundation, either version 3
 + * of the License, or (at your option) any later version.
 + *  
 + * Jalview is distributed in the hope that it will be useful, but 
 + * WITHOUT ANY WARRANTY; without even the implied warranty 
 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 + * PURPOSE.  See the GNU General Public License for more details.
 + * 
 + * You should have received a copy of the GNU General Public License
 + * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
 + * The Jalview Authors are detailed in the 'AUTHORS' file.
 + */
 +package jalview.appletgui;
 +
 +import jalview.datamodel.SequenceI;
 +import jalview.renderer.seqfeatures.FeatureColourFinder;
 +import jalview.viewmodel.OverviewDimensions;
 +
 +import java.awt.Color;
 +import java.awt.Dimension;
 +import java.awt.Frame;
 +import java.awt.Graphics;
 +import java.awt.Image;
 +
 +import javax.swing.JComponent;
 +
 +public class OverviewCanvas extends JComponent
 +{
 +  // This is set true if the alignment view changes whilst
 +  // the overview is being calculated
 +  private volatile boolean restart = false;
 +
 +  private volatile boolean updaterunning = false;
 +
 +  private OverviewDimensions od;
 +
 +  private Image miniMe;
 +
 +  private Image offscreen;
 +
 +  private AlignViewport av;
 +
 +  // Can set different properties in this seqCanvas than
 +  // main visible SeqCanvas
 +  private SequenceRenderer sr;
 +
 +  private FeatureRenderer fr;
 +
 +  private Frame nullFrame;
 +
 +  public OverviewCanvas(OverviewDimensions overviewDims,
 +          AlignViewport alignvp)
 +  {
 +    od = overviewDims;
 +    av = alignvp;
 +
 +    nullFrame = new Frame();
 +    nullFrame.addNotify();
 +
 +    sr = new SequenceRenderer(av);
 +    sr.graphics = nullFrame.getGraphics();
 +    sr.renderGaps = false;
 +    sr.forOverview = true;
 +    fr = new FeatureRenderer(av);
 +  }
 +
 +  /*
 +   * Signals to drawing code that the associated alignment viewport
 +   * has changed and a redraw will be required
 +   */
 +  public boolean restartDraw()
 +  {
 +    synchronized (this)
 +    {
 +      if (updaterunning)
 +      {
 +        restart = true;
 +      }
 +      else
 +      {
 +        updaterunning = true;
 +      }
 +      return restart;
 +    }
 +  }
 +
 +  public void draw(boolean showSequenceFeatures, boolean showAnnotation,
 +          AlignmentPanel ap)
 +  {
 +    miniMe = null;
 +
 +    if (av.isShowSequenceFeatures())
 +    {
 +      fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer());
 +    }
 +
 +    setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
 +
 +    miniMe = nullFrame.createImage(od.getWidth(), od.getHeight());
 +    offscreen = nullFrame.createImage(od.getWidth(), od.getHeight());
 +
 +    Graphics mg = miniMe.getGraphics();
 +
 +    int alwidth = av.getAlignment().getWidth();
 +    int alheight = av.getAlignment().getAbsoluteHeight();
 +    float sampleCol = alwidth / (float) od.getWidth();
 +    float sampleRow = alheight / (float) od.getSequencesHeight();
 +
 +    buildImage(sampleRow, sampleCol, mg);
 +
 +    // check for conservation annotation to make sure overview works for DNA too
 +    if (showAnnotation)
 +    {
 +      for (int col = 0; col < od.getWidth() && !restart; col++)
 +      {
 +        mg.translate(col, od.getSequencesHeight());
 +        ap.annotationPanel.renderer.drawGraph(mg,
 +                av.getAlignmentConservationAnnotation(),
 +                av.getAlignmentConservationAnnotation().annotations,
 +                (int) (sampleCol) + 1, od.getGraphHeight(),
 +                (int) (col * sampleCol), (int) (col * sampleCol) + 1);
 +        mg.translate(-col, -od.getSequencesHeight());
 +      }
 +    }
 +    System.gc();
 +
 +    if (restart)
 +    {
 +      restart = false;
 +      draw(showSequenceFeatures, showAnnotation, ap);
 +    }
 +    else
 +    {
 +      updaterunning = false;
 +    }
 +  }
 +
 +  /*
 +   * Build the overview panel image
 +   */
 +  private void buildImage(float sampleRow, float sampleCol, Graphics mg)
 +  {
 +    int lastcol = 0;
 +    int lastrow = 0;
 +    int xstart = 0;
 +    int ystart = 0;
 +    Color color = Color.yellow;
 +    int sameRow = 0;
 +    int sameCol = 0;
 +
 +    SequenceI seq = null;
 +    FeatureColourFinder finder = new FeatureColourFinder(fr);
 +
 +    final boolean hasHiddenCols = av.hasHiddenColumns();
 +    boolean hiddenRow = false;
 +
 +    for (int row = 0; row < od.getSequencesHeight() && !restart; row++)
 +    {
 +      if ((int) (row * sampleRow) == lastrow)
 +      {
 +        sameRow++;
 +      }
 +      else
 +      {
 +        // get the sequence which would be at alignment index 'lastrow' if no
 +        // rows were hidden, and determine whether it is hidden or not
 +        hiddenRow = av.getAlignment().isHidden(lastrow);
 +        seq = av.getAlignment().getSequenceAtAbsoluteIndex(lastrow);
 +
 +        for (int col = 0; col < od.getWidth(); col++)
 +        {
 +          if ((int) (col * sampleCol) == lastcol
 +                  && (int) (row * sampleRow) == lastrow)
 +          {
 +            sameCol++;
 +          }
 +          else
 +          {
 +            lastcol = (int) (col * sampleCol);
 +
 +            color = getColumnColourFromSequence(seq, hiddenRow,
 +                    hasHiddenCols, lastcol, finder);
 +
 +            mg.setColor(color);
 +            if (sameCol == 1 && sameRow == 1)
 +            {
 +              mg.drawLine(xstart, ystart, xstart, ystart);
 +            }
 +            else
 +            {
 +              mg.fillRect(xstart, ystart, sameCol, sameRow);
 +            }
 +
 +            xstart = col;
 +            sameCol = 1;
 +          }
 +        }
 +        lastrow = (int) (row * sampleRow);
 +        ystart = row;
 +        sameRow = 1;
 +      }
 +    }
 +  }
 +
 +  /*
 +   * Find the colour of a sequence at a specified column position
 +   */
 +  private Color getColumnColourFromSequence(
 +          jalview.datamodel.SequenceI seq, boolean hiddenRow,
 +          boolean hasHiddenCols, int lastcol, FeatureColourFinder finder)
 +  {
 +    Color color = Color.white;
 +    if (seq.getLength() > lastcol)
 +    {
 +      color = sr.getResidueColour(seq, lastcol, finder);
 +    }
 +
 +    if (hiddenRow
-             || (hasHiddenCols && !av.getColumnSelection()
++            || (hasHiddenCols && !av.getAlignment().getHiddenColumns()
 +                    .isVisible(lastcol)))
 +    {
 +      color = color.darker().darker();
 +    }
 +    return color;
 +  }
 +
 +  @Override
 +  public void update(Graphics g)
 +  {
 +    paint(g);
 +  }
 +
 +  @Override
 +  public void paint(Graphics g)
 +  {
 +    Graphics og = offscreen.getGraphics();
 +    if (miniMe != null)
 +    {
 +      og.drawImage(miniMe, 0, 0, this);
 +      og.setColor(Color.red);
 +      od.drawBox(og);
 +      g.drawImage(offscreen, 0, 0, this);
 +    }
 +  }
 +
 +}
@@@ -169,7 -335,28 +169,8 @@@ public class OverviewPanel extends Pane
    public void setBoxPosition()
    {
      od.setBoxPosition(av.getAlignment()
-             .getHiddenSequences(), av.getColumnSelection(), av.getRanges());
+ .getHiddenSequences(), av
+             .getAlignment().getHiddenColumns(), av.getRanges());
      repaint();
    }
 -
 -  @Override
 -  public void update(Graphics g)
 -  {
 -    paint(g);
 -  }
 -
 -  @Override
 -  public void paint(Graphics g)
 -  {
 -    Graphics og = offscreen.getGraphics();
 -    if (miniMe != null)
 -    {
 -      og.drawImage(miniMe, 0, 0, this);
 -      og.setColor(Color.red);
 -      od.drawBox(og);
 -      g.drawImage(offscreen, 0, 0, this);
 -    }
 -  }
 -
  }
index 1b1a5dd,0000000..03f2fea
mode 100644,000000..100644
--- /dev/null
@@@ -1,51 -1,0 +1,52 @@@
 +/*
 + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 + * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * 
 + * This file is part of Jalview.
 + * 
 + * Jalview is free software: you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License 
 + * as published by the Free Software Foundation, either version 3
 + * of the License, or (at your option) any later version.
 + *  
 + * Jalview is distributed in the hope that it will be useful, but 
 + * WITHOUT ANY WARRANTY; without even the implied warranty 
 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 + * PURPOSE.  See the GNU General Public License for more details.
 + * 
 + * You should have received a copy of the GNU General Public License
 + * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
 + * The Jalview Authors are detailed in the 'AUTHORS' file.
 + */
 +package jalview.datamodel;
 +
 +import jalview.api.AlignmentColsCollectionI;
 +
 +import java.util.Iterator;
 +
 +public class AllColsCollection implements AlignmentColsCollectionI
 +{
 +  int start;
 +  int end;
-   ColumnSelection hidden;
++
++  HiddenColumns hidden;
 +  
-   public AllColsCollection(int s, int e, ColumnSelection colsel)
++  public AllColsCollection(int s, int e, HiddenColumns hiddenCols)
 +  {
 +    start = s;
 +    end = e;
-     hidden = colsel;
++    hidden = hiddenCols;
 +  }
 +  
 +  @Override
 +  public Iterator<Integer> iterator()
 +  {
 +    return new AllColsIterator(start,end,hidden);
 +  }
 +
 +  @Override
 +  public boolean isHidden(int c)
 +  {
 +    return !hidden.isVisible(c);
 +  }
 +}
index 67d7ba5,0000000..c7a0bb1
mode 100644,000000..100644
--- /dev/null
@@@ -1,74 -1,0 +1,73 @@@
 +/*
 + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 + * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * 
 + * This file is part of Jalview.
 + * 
 + * Jalview is free software: you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License 
 + * as published by the Free Software Foundation, either version 3
 + * of the License, or (at your option) any later version.
 + *  
 + * Jalview is distributed in the hope that it will be useful, but 
 + * WITHOUT ANY WARRANTY; without even the implied warranty 
 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 + * PURPOSE.  See the GNU General Public License for more details.
 + * 
 + * You should have received a copy of the GNU General Public License
 + * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
 + * The Jalview Authors are detailed in the 'AUTHORS' file.
 + */
 +package jalview.datamodel;
 +
 +import java.util.Iterator;
 +import java.util.NoSuchElementException;
 +
 +/**
 + * An iterator which iterates over all columns or rows in an alignment, whether
 + * hidden or visible.
 + * 
 + * @author kmourao
 + *
 + */
 +public class AllColsIterator implements Iterator<Integer>
 +{
 +  private int last;
 +
 +  private int next;
 +
 +  private int current;
 +
-   public AllColsIterator(int firstcol, int lastcol,
-           ColumnSelection hiddenCols)
++  public AllColsIterator(int firstcol, int lastcol, HiddenColumns hiddenCols)
 +  {
 +    last = lastcol;
 +    next = firstcol;
 +    current = firstcol;
 +  }
 +
 +  @Override
 +  public boolean hasNext()
 +  {
 +    return current + 1 <= last;
 +  }
 +
 +  @Override
 +  public Integer next()
 +  {
 +    if (current + 1 > last)
 +    {
 +      throw new NoSuchElementException();
 +    }
 +    current = next;
 +    next++;
 +
 +    return current;
 +  }
 +
 +  @Override
 +  public void remove()
 +  {
 +    throw new UnsupportedOperationException();
 +  }
 +}
 +
index aabd603,0000000..8b6c2a4
mode 100644,000000..100644
--- /dev/null
@@@ -1,53 -1,0 +1,53 @@@
 +/*
 + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 + * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * 
 + * This file is part of Jalview.
 + * 
 + * Jalview is free software: you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License 
 + * as published by the Free Software Foundation, either version 3
 + * of the License, or (at your option) any later version.
 + *  
 + * Jalview is distributed in the hope that it will be useful, but 
 + * WITHOUT ANY WARRANTY; without even the implied warranty 
 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 + * PURPOSE.  See the GNU General Public License for more details.
 + * 
 + * You should have received a copy of the GNU General Public License
 + * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
 + * The Jalview Authors are detailed in the 'AUTHORS' file.
 + */
 +package jalview.datamodel;
 +
 +import jalview.api.AlignmentColsCollectionI;
 +
 +import java.util.Iterator;
 +
 +public class VisibleColsCollection implements AlignmentColsCollectionI
 +{
 +  int start;
 +  int end;
 +
-   ColumnSelection hidden;
++  HiddenColumns hidden;
 +
-   public VisibleColsCollection(int s, int e, ColumnSelection colsel)
++  public VisibleColsCollection(int s, int e, HiddenColumns hiddenCols)
 +  {
 +    start = s;
 +    end = e;
-     hidden = colsel;
++    hidden = hiddenCols;
 +  }
 +
 +  @Override
 +  public Iterator<Integer> iterator()
 +  {
 +    return new VisibleColsIterator(start, end, hidden);
 +  }
 +
 +  @Override
 +  public boolean isHidden(int c)
 +  {
 +    return false;
 +  }
 +
 +}
index 2a69a82,0000000..2ab61ff
mode 100644,000000..100644
--- /dev/null
@@@ -1,131 -1,0 +1,131 @@@
 +/*
 + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 + * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * 
 + * This file is part of Jalview.
 + * 
 + * Jalview is free software: you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License 
 + * as published by the Free Software Foundation, either version 3
 + * of the License, or (at your option) any later version.
 + *  
 + * Jalview is distributed in the hope that it will be useful, but 
 + * WITHOUT ANY WARRANTY; without even the implied warranty 
 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 + * PURPOSE.  See the GNU General Public License for more details.
 + * 
 + * You should have received a copy of the GNU General Public License
 + * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
 + * The Jalview Authors are detailed in the 'AUTHORS' file.
 + */
 +package jalview.datamodel;
 +
 +import java.util.Iterator;
 +import java.util.List;
 +import java.util.NoSuchElementException;
 +
 +/**
 + * An iterator which iterates over all visible columns in an alignment
 + * 
 + * @author kmourao
 + *
 + */
 +public class VisibleColsIterator implements Iterator<Integer>
 +{
 +  private int last;
 +
 +  private int current;
 +
 +  private int next;
 +
 +  private List<int[]> hidden;
 +
 +  private int lasthiddenregion;
 +
 +  public VisibleColsIterator(int firstcol, int lastcol,
-           ColumnSelection hiddenCols)
++          HiddenColumns hiddenCols)
 +  {
 +    last = lastcol;
 +    current = firstcol;
 +    next = firstcol;
-     hidden = hiddenCols.getHiddenColumns();
++    hidden = hiddenCols.getListOfCols();
 +    lasthiddenregion = -1;
 +
 +    if (hidden != null)
 +    {
 +      int i = 0;
 +      for (i = 0; i < hidden.size(); ++i)
 +      {
 +        if (current >= hidden.get(i)[0] && current <= hidden.get(i)[1])
 +        {
 +          // current is hidden, move to right
 +          current = hidden.get(i)[1] + 1;
 +          next = current;
 +        }
 +        if (current < hidden.get(i)[0])
 +        {
 +          break;
 +        }
 +      }
 +      lasthiddenregion = i - 1;
 +
 +      for (i = hidden.size() - 1; i >= 0; --i)
 +      {
 +        if (last >= hidden.get(i)[0] && last <= hidden.get(i)[1])
 +        {
 +          // last is hidden, move to left
 +          last = hidden.get(i)[0] - 1;
 +        }
 +        if (last > hidden.get(i)[1])
 +        {
 +          break;
 +        }
 +      }
 +    }
 +  }
 +
 +  @Override
 +  public boolean hasNext()
 +  {
 +    return next <= last;
 +  }
 +
 +  @Override
 +  public Integer next()
 +  {
 +    if (next > last)
 +    {
 +      throw new NoSuchElementException();
 +    }
 +    current = next;
 +    if ((hidden != null) && (lasthiddenregion + 1 < hidden.size()))
 +    {
 +      // still some more hidden regions
 +      if (next + 1 < hidden.get(lasthiddenregion + 1)[0])
 +      {
 +        // next+1 is still before the next hidden region
 +        next++;
 +      }
 +      else if ((next + 1 >= hidden.get(lasthiddenregion + 1)[0])
 +              && (next + 1 <= hidden.get(lasthiddenregion + 1)[1]))
 +      {
 +        // next + 1 is in the next hidden region
 +        next = hidden.get(lasthiddenregion + 1)[1] + 1;
 +        lasthiddenregion++;
 +      }
 +    }
 +    else
 +    {
 +      // finished with hidden regions, just increment normally
 +      next++;
 +    }
 +    return current;
 +  }
 +
 +  @Override
 +  public void remove()
 +  {
 +    throw new UnsupportedOperationException();
 +  }
 +}
 +
@@@ -147,12 -148,12 +148,12 @@@ public class AlignViewport extends Alig
     * @param hiddenColumns
     *          ColumnSelection
     */
-   public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns)
+   public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns)
    {
 -    setAlignment(al);
 +    super(al);
      if (hiddenColumns != null)
      {
-       colSel = hiddenColumns;
+       al.setHiddenColumns(hiddenColumns);
      }
      init();
    }
     * @param viewid
     *          (may be null)
     */
-   public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns,
+   public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns,
            String seqsetid, String viewid)
    {
 +    super(al);
      sequenceSetID = seqsetid;
      viewId = viewid;
      // TODO remove these once 2.4.VAMSAS release finished
      {
        Cache.log.debug("Setting viewport's view id : " + viewId);
      }
 -    setAlignment(al);
 +
      if (hiddenColumns != null)
      {
-       colSel = hiddenColumns;
+       al.setHiddenColumns(hiddenColumns);
      }
      init();
    }
index 5005f4e,0000000..e475c2c
mode 100644,000000..100644
--- /dev/null
@@@ -1,185 -1,0 +1,188 @@@
 +/*
 + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 + * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * 
 + * This file is part of Jalview.
 + * 
 + * Jalview is free software: you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License 
 + * as published by the Free Software Foundation, either version 3
 + * of the License, or (at your option) any later version.
 + *  
 + * Jalview is distributed in the hope that it will be useful, but 
 + * WITHOUT ANY WARRANTY; without even the implied warranty 
 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 + * PURPOSE.  See the GNU General Public License for more details.
 + * 
 + * You should have received a copy of the GNU General Public License
 + * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
 + * The Jalview Authors are detailed in the 'AUTHORS' file.
 + */
 +package jalview.gui;
 +
 +import jalview.api.AlignViewportI;
 +import jalview.renderer.seqfeatures.FeatureColourFinder;
 +import jalview.viewmodel.OverviewDimensions;
 +
 +import java.awt.Color;
 +import java.awt.Dimension;
 +import java.awt.Graphics;
 +import java.awt.image.BufferedImage;
 +
 +import javax.swing.JComponent;
 +
 +public class OverviewCanvas extends JComponent
 +{
 +  private static final Color TRANS_GREY = new Color(100, 100, 100, 25);
 +
 +  // This is set true if the alignment view changes whilst
 +  // the overview is being calculated
 +  private volatile boolean restart = false;
 +
 +  private volatile boolean updaterunning = false;
 +
 +  private BufferedImage miniMe;
 +
 +  private BufferedImage lastMiniMe = null;
 +
 +  // Can set different properties in this seqCanvas than
 +  // main visible SeqCanvas
 +  private SequenceRenderer sr;
 +
 +  private jalview.renderer.seqfeatures.FeatureRenderer fr;
 +
 +  private OverviewDimensions od;
 +
 +  private AlignViewportI av;
 +
 +  public OverviewCanvas(OverviewDimensions overviewDims,
 +          AlignViewportI alignvp)
 +  {
 +    od = overviewDims;
 +    av = alignvp;
 +
 +    sr = new SequenceRenderer(av);
 +    sr.renderGaps = false;
 +    sr.forOverview = true;
 +    fr = new jalview.renderer.seqfeatures.FeatureRenderer(av);
 +  }
 +
 +  /**
 +   * Update the overview dimensions object used by the canvas (e.g. if we change
 +   * from showing hidden columns to hiding them or vice versa)
 +   * 
 +   * @param overviewDims
 +   */
 +  public void resetOviewDims(OverviewDimensions overviewDims)
 +  {
 +    od = overviewDims;
 +  }
 +
 +  /**
 +   * Signals to drawing code that the associated alignment viewport has changed
 +   * and a redraw will be required
 +   */
 +  public boolean restartDraw()
 +  {
 +    synchronized (this)
 +    {
 +      if (updaterunning)
 +      {
 +        restart = true;
 +      }
 +      else
 +      {
 +        updaterunning = true;
 +      }
 +      return restart;
 +    }
 +  }
 +
 +  /**
 +   * Draw the overview sequences
 +   * 
 +   * @param showSequenceFeatures
 +   *          true if sequence features are to be shown
 +   * @param showAnnotation
 +   *          true if the annotation is to be shown
 +   * @param transferRenderer
 +   *          the renderer to transfer feature colouring from
 +   */
 +  public void draw(boolean showSequenceFeatures, boolean showAnnotation,
 +          FeatureRenderer transferRenderer)
 +  {
 +    miniMe = null;
 +
 +    if (showSequenceFeatures)
 +    {
 +      fr.transferSettings(transferRenderer);
 +    }
 +    FeatureColourFinder finder = new FeatureColourFinder(fr);
 +
 +    // why do we need to set preferred size again? was set in
 +    // updateOverviewImage
 +    setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
 +
 +    OverviewRenderer or = new OverviewRenderer(sr, finder, od);
 +    miniMe = or.draw(od.getRows(av.getRanges(), av.getAlignment()),
-             od.getColumns(av.getRanges(), av.getColumnSelection()));
++ od
++            .getColumns(av.getRanges(), av.getAlignment()
++                    .getHiddenColumns()));
 +
 +    Graphics mg = miniMe.getGraphics();
 +
 +    if (showAnnotation)
 +    {
 +      mg.translate(0, od.getSequencesHeight());
 +      or.drawGraph(mg, av.getAlignmentConservationAnnotation(),
 +              av.getCharWidth(), od.getGraphHeight(),
-               od.getColumns(av.getRanges(), av.getColumnSelection()));
++ od.getColumns(
++              av.getRanges(), av.getAlignment().getHiddenColumns()));
 +      mg.translate(0, -od.getSequencesHeight());
 +    }
 +    System.gc();
 +
 +    if (restart)
 +    {
 +      restart = false;
 +      draw(showSequenceFeatures, showAnnotation, transferRenderer);
 +    }
 +    else
 +    {
 +      updaterunning = false;
 +      lastMiniMe = miniMe;
 +    }
 +  }
 +
 +  @Override
 +  public void paintComponent(Graphics g)
 +  {
 +    if (restart)
 +    {
 +      if (lastMiniMe == null)
 +      {
 +        g.setColor(Color.white);
 +        g.fillRect(0, 0, getWidth(), getHeight());
 +      }
 +      else
 +      {
 +        g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
 +      }
 +      g.setColor(TRANS_GREY);
 +      g.fillRect(0, 0, getWidth(), getHeight());
 +    }
 +    else if (lastMiniMe != null)
 +    {
 +      g.drawImage(lastMiniMe, 0, 0, this);
 +      if (lastMiniMe != miniMe)
 +      {
 +        g.setColor(TRANS_GREY);
 +        g.fillRect(0, 0, getWidth(), getHeight());
 +      }
 +    }
 +
 +    g.setColor(Color.red);
 +    od.drawBox(g);
 +  }
 +
 +}
@@@ -97,12 -112,11 +97,12 @@@ public class OverviewPanel extends JPan
        @Override
        public void mouseDragged(MouseEvent evt)
        {
 -        if (!av.getWrapAlignment())
 +        if (!SwingUtilities.isRightMouseButton(evt)
 +                && !av.getWrapAlignment())
          {
            od.updateViewportFromMouse(evt.getX(), evt.getY(), av
-                   .getAlignment().getHiddenSequences(), av
-                   .getColumnSelection(), av.getRanges());
+                   .getAlignment().getHiddenSequences(), av.getAlignment()
+                   .getHiddenColumns(), av.getRanges());
            ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
          }
        }
        @Override
        public void mousePressed(MouseEvent evt)
        {
 -        if (!av.getWrapAlignment())
 +        if (SwingUtilities.isRightMouseButton(evt))
 +        {
 +          if (!Platform.isAMac())
 +          {
 +            showPopupMenu(evt);
 +          }
 +        }
 +        else if (!av.getWrapAlignment())
          {
            od.updateViewportFromMouse(evt.getX(), evt.getY(), av
-                   .getAlignment().getHiddenSequences(), av
-                   .getColumnSelection(), av.getRanges());
+                   .getAlignment().getHiddenSequences(), av.getAlignment()
+                   .getHiddenColumns(), av.getRanges());
            ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
          }
        }
    public void setBoxPosition()
    {
      od.setBoxPosition(av.getAlignment()
-             .getHiddenSequences(), av.getColumnSelection(), av.getRanges());
+ .getHiddenSequences(), av
+             .getAlignment().getHiddenColumns(), av.getRanges());
      repaint();
    }
 -
 -
 -  @Override
 -  public void paintComponent(Graphics g)
 -  {
 -    if (resizing || resizeAgain)
 -    {
 -      if (lastMiniMe == null)
 -      {
 -        g.setColor(Color.white);
 -        g.fillRect(0, 0, getWidth(), getHeight());
 -      }
 -      else
 -      {
 -        g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
 -      }
 -      g.setColor(TRANS_GREY);
 -      g.fillRect(0, 0, getWidth(), getHeight());
 -    }
 -    else if (lastMiniMe != null)
 -    {
 -      g.drawImage(lastMiniMe, 0, 0, this);
 -      if (lastMiniMe != miniMe)
 -      {
 -        g.setColor(TRANS_GREY);
 -        g.fillRect(0, 0, getWidth(), getHeight());
 -      }
 -    }
 -
 -    g.setColor(Color.red);
 -    od.drawBox(g);
 -  }
  }
   */
  package jalview.viewmodel;
  
 +import jalview.api.AlignmentColsCollectionI;
 +import jalview.api.AlignmentRowsCollectionI;
 +import jalview.datamodel.AlignmentI;
- import jalview.datamodel.ColumnSelection;
+ import jalview.datamodel.HiddenColumns;
  import jalview.datamodel.HiddenSequences;
  
  import java.awt.Graphics;
@@@ -146,79 -340,4 +146,79 @@@ public abstract class OverviewDimension
    {
      return graphHeight;
    }
 -}
 +
 +  public float getPixelsPerCol()
 +  {
 +    return (float) width / alwidth;
 +  }
 +
 +  public float getPixelsPerSeq()
 +  {
 +    return (float) sequencesHeight / alheight;
 +  }
 +
 +  public void setWidth(int w)
 +  {
 +    width = w;
 +  }
 +
 +  public void setHeight(int h)
 +  {
 +    sequencesHeight = h - graphHeight;
 +  }
 +
 +  /**
 +   * Update the viewport location from a mouse click in the overview panel
 +   * 
 +   * @param mousex
 +   *          x location of mouse
 +   * @param mousey
 +   *          y location of mouse
 +   * @param hiddenSeqs
 +   *          the alignment's hidden sequences
 +   * @param hiddenCols
 +   *          the alignment's hidden columns
 +   * @param ranges
 +   *          the alignment's width and height ranges
 +   */
 +  public abstract void updateViewportFromMouse(int mousex, int mousey,
-           HiddenSequences hiddenSeqs, ColumnSelection hiddenCols,
++          HiddenSequences hiddenSeqs, HiddenColumns hiddenCols,
 +          ViewportRanges ranges);
 +
 +  /**
 +   * Set the overview panel's box position to match the viewport
 +   * 
 +   * @param hiddenSeqs
 +   *          the alignment's hidden sequences
 +   * @param hiddenCols
 +   *          the alignment's hidden columns
 +   * @param ranges
 +   *          the alignment's width and height ranges
 +   */
 +  public abstract void setBoxPosition(HiddenSequences hiddenSeqs,
-           ColumnSelection hiddenCols, ViewportRanges ranges);
++          HiddenColumns hiddenCols, ViewportRanges ranges);
 +
 +  /**
 +   * Get the collection of columns used by this overview dimensions object
 +   * 
 +   * @param ranges
 +   *          the alignment's width and height ranges
 +   * @param hiddenCols
 +   *          the alignment's hidden columns
 +   * @return a column collection
 +   */
 +  public abstract AlignmentColsCollectionI getColumns(
-           ViewportRanges ranges, ColumnSelection hiddenCols);
++          ViewportRanges ranges, HiddenColumns hiddenCols);
 +
 +  /**
 +   * Get the collection of rows used by this overview dimensions object
 +   * 
 +   * @param ranges
 +   *          the alignment's width and height ranges
 +   * @param al
 +   *          the alignment
 +   * @return a row collection
 +   */
 +  public abstract AlignmentRowsCollectionI getRows(
 +          ViewportRanges ranges, AlignmentI al);
 +}
index b30cc78,0000000..94d2899
mode 100644,000000..100644
--- /dev/null
@@@ -1,148 -1,0 +1,148 @@@
 +package jalview.viewmodel;
 +
 +import jalview.api.AlignmentColsCollectionI;
 +import jalview.api.AlignmentRowsCollectionI;
 +import jalview.datamodel.AlignmentI;
- import jalview.datamodel.ColumnSelection;
++import jalview.datamodel.HiddenColumns;
 +import jalview.datamodel.HiddenSequences;
 +import jalview.datamodel.VisibleColsCollection;
 +import jalview.datamodel.VisibleRowsCollection;
 +
 +public class OverviewDimensionsAllVisible extends OverviewDimensions
 +{
 +  public OverviewDimensionsAllVisible(ViewportRanges ranges,
 +          boolean showAnnotationPanel)
 +  {
 +    super(ranges, showAnnotationPanel);
 +
 +    alwidth = ranges.getVisibleAlignmentWidth();
 +    alheight = ranges.getVisibleAlignmentHeight();
 +  }
 +
 +  @Override
 +  public void updateViewportFromMouse(int mousex, int mousey,
-           HiddenSequences hiddenSeqs, ColumnSelection hiddenCols,
++          HiddenSequences hiddenSeqs, HiddenColumns hiddenCols,
 +          ViewportRanges ranges)
 +  {
 +    int x = mousex;
 +    int y = mousey;
 +
 +    alwidth = ranges.getVisibleAlignmentWidth();
 +    alheight = ranges.getVisibleAlignmentHeight();
 +
 +    if (x < 0)
 +    {
 +      x = 0;
 +    }
 +
 +    if (y < 0)
 +    {
 +      y = 0;
 +    }
 +
 +    //
 +    // Convert x value to residue position
 +    //
 +
 +    // need to determine where scrollCol should be, given x
 +    // to do this also need to know width of viewport, and some hidden column
 +    // correction
 +
 +    // convert x to residues - this is an absolute position
 +    int xAsRes = Math.round((float) x * alwidth / width);
 +
 +    // get viewport width in residues
 +    int vpwidth = ranges.getEndRes() - ranges.getStartRes() + 1;
 +
 +    if (xAsRes + vpwidth > alwidth)
 +    {
 +      // went past the end of the alignment, adjust backwards
 +
 +      // if last position was before the end of the alignment, need to update
 +      if ((scrollCol + vpwidth - 1) < alwidth)
 +      {
 +        xAsRes = alwidth - vpwidth;
 +      }
 +      else
 +      {
 +        xAsRes = scrollCol;
 +      }
 +    }
 +
 +
 +    //
 +    // Convert y value to sequence position
 +    //
 +
 +    // convert y to residues
 +    int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
 +
 +    // get viewport height in sequences
 +    // add 1 because height includes both endSeq and startSeq
 +    int vpheight = ranges.getEndSeq() - ranges.getStartSeq() + 1;
 +
 +    if (yAsSeq + vpheight > alheight)
 +    {
 +      // went past the end of the alignment, adjust backwards
 +      if ((scrollRow + vpheight - 1) < alheight)
 +      {
 +        yAsSeq = alheight - vpheight;
 +      }
 +      else
 +      {
 +        yAsSeq = scrollRow;
 +      }
 +    }
 +
 +    // update scroll values
 +    scrollCol = xAsRes;
 +    scrollRow = yAsSeq;
 +
 +  }
 +
 +  @Override
 +  public void setBoxPosition(HiddenSequences hiddenSeqs,
-           ColumnSelection hiddenCols, ViewportRanges ranges)
++          HiddenColumns hiddenCols, ViewportRanges ranges)
 +  {
 +    alwidth = ranges.getVisibleAlignmentWidth();
 +    alheight = ranges.getVisibleAlignmentHeight();
 +
 +    // work with visible values of startRes and endRes
 +    int startRes = ranges.getStartRes();
 +    int endRes = ranges.getEndRes();
 +
 +    // work with visible values of startSeq and endSeq
 +    int startSeq = ranges.getStartSeq();
 +    int endSeq = ranges.getEndSeq();
 +
 +    // boxX, boxY is the x,y location equivalent to startRes, startSeq
 +    boxX = Math.round((float) startRes * width / alwidth);
 +    boxY = Math.round((float) startSeq * sequencesHeight / alheight);
 +
 +    // boxWidth is the width in residues translated to pixels
 +    // since the box includes both the start and end residues, add 1 to the
 +    // difference
 +    boxWidth = Math
 +            .round((float) (endRes - startRes + 1) * width / alwidth);
 +    // boxHeight is the height in sequences translated to pixels
 +    boxHeight = Math.round((float) (endSeq - startSeq + 1)
 +            * sequencesHeight / alheight);
 +
 +  }
 +
 +  @Override
 +  public AlignmentColsCollectionI getColumns(ViewportRanges ranges,
-           ColumnSelection hiddenCols)
++          HiddenColumns hiddenCols)
 +  {
 +    return new VisibleColsCollection(0,
 +            ranges.getVisibleAlignmentWidth() - 1, hiddenCols);
 +  }
 +
 +  @Override
 +  public AlignmentRowsCollectionI getRows(ViewportRanges ranges,
 +          AlignmentI al)
 +  {
 +    return new VisibleRowsCollection(0,
 +            ranges.getVisibleAlignmentHeight() - 1, al);
 +  }
 +}
index eff27dd,0000000..6043755
mode 100644,000000..100644
--- /dev/null
@@@ -1,222 -1,0 +1,222 @@@
 +/*
 + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 + * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * 
 + * This file is part of Jalview.
 + * 
 + * Jalview is free software: you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License 
 + * as published by the Free Software Foundation, either version 3
 + * of the License, or (at your option) any later version.
 + *  
 + * Jalview is distributed in the hope that it will be useful, but 
 + * WITHOUT ANY WARRANTY; without even the implied warranty 
 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 + * PURPOSE.  See the GNU General Public License for more details.
 + * 
 + * You should have received a copy of the GNU General Public License
 + * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
 + * The Jalview Authors are detailed in the 'AUTHORS' file.
 + */
 +package jalview.viewmodel;
 +
 +import jalview.api.AlignmentColsCollectionI;
 +import jalview.api.AlignmentRowsCollectionI;
 +import jalview.datamodel.AlignmentI;
 +import jalview.datamodel.AllColsCollection;
 +import jalview.datamodel.AllRowsCollection;
- import jalview.datamodel.ColumnSelection;
++import jalview.datamodel.HiddenColumns;
 +import jalview.datamodel.HiddenSequences;
 +
 +public class OverviewDimensionsWithHidden extends OverviewDimensions
 +{
 +  /**
 +   * Create an OverviewDimensions object
 +   * 
 +   * @param ranges
 +   *          positional properties of the viewport
 +   * @param showAnnotationPanel
 +   *          true if the annotation panel is to be shown, false otherwise
 +   */
 +  public OverviewDimensionsWithHidden(ViewportRanges ranges,
 +          boolean showAnnotationPanel)
 +  {
 +    super(ranges, showAnnotationPanel);
 +
 +    alwidth = ranges.getAbsoluteAlignmentWidth();
 +    alheight = ranges.getAbsoluteAlignmentHeight();
 +  }
 +
 +  /**
 +   * Check box dimensions and scroll positions and correct if necessary
 +   * 
 +   * @param mousex
 +   *          x position in overview panel
 +   * @param mousey
 +   *          y position in overview panel
 +   * @param hiddenSeqs
 +   *          hidden sequences
 +   * @param hiddenCols
 +   *          hidden columns
 +   * @param ranges
 +   *          viewport position properties
 +   */
 +  @Override
 +  public void updateViewportFromMouse(int mousex, int mousey,
-           HiddenSequences hiddenSeqs, ColumnSelection hiddenCols,
++          HiddenSequences hiddenSeqs, HiddenColumns hiddenCols,
 +          ViewportRanges ranges)
 +  {
 +    int x = mousex;
 +    int y = mousey;
 +
 +    alwidth = ranges.getAbsoluteAlignmentWidth();
 +    alheight = ranges.getAbsoluteAlignmentHeight();
 +
 +    if (x < 0)
 +    {
 +      x = 0;
 +    }
 +
 +    if (y < 0)
 +    {
 +      y = 0;
 +    }
 +
 +    //
 +    // Convert x value to residue position
 +    //
 +
 +    // need to determine where scrollCol should be, given x
 +    // to do this also need to know width of viewport, and some hidden column
 +    // correction
 +
 +    // convert x to residues - this is an absolute position
 +    int xAsRes = Math.round((float) x * alwidth / width);
 +
 +    // get viewport width in residues
 +    int vpwidth = ranges.getEndRes() - ranges.getStartRes() + 1;
 +
 +    // get where x should be when accounting for hidden cols
 +    // if x is in a hidden col region, shift to left - but we still need
 +    // absolute position
 +    // so convert back after getting visible region position
 +    int visXAsRes = hiddenCols.findColumnPosition(xAsRes);
 +
 +    // check in case we went off the edge of the alignment
 +    int visAlignWidth = hiddenCols.findColumnPosition(alwidth - 1);
 +    if (visXAsRes + vpwidth - 1 > visAlignWidth)
 +    {
 +      // went past the end of the alignment, adjust backwards
 +
 +      // if last position was before the end of the alignment, need to update
 +      if ((scrollCol + vpwidth - 1) < visAlignWidth)
 +      {
 +        visXAsRes = hiddenCols.findColumnPosition(hiddenCols
 +                .subtractVisibleColumns(vpwidth - 1, alwidth - 1));
 +      }
 +      else
 +      {
 +        visXAsRes = scrollCol;
 +      }
 +    }
 +
 +    //
 +    // Convert y value to sequence position
 +    //
 +
 +    // convert y to residues
 +    int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
 +
 +    // get viewport height in sequences
 +    // add 1 because height includes both endSeq and startSeq
 +    int vpheight = ranges.getEndSeq() - ranges.getStartSeq() + 1;
 +
 +    // get where y should be when accounting for hidden rows
 +    // if y is in a hidden row region, shift up - but we still need absolute
 +    // position,
 +    // so convert back after getting visible region position
 +    yAsSeq = hiddenSeqs.adjustForHiddenSeqs(hiddenSeqs
 +            .findIndexWithoutHiddenSeqs(yAsSeq));
 +
 +    // check in case we went off the edge of the alignment
 +    int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight);
 +    int visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
 +    if (visYAsSeq + vpheight - 1 > visAlignHeight)
 +    {
 +      // went past the end of the alignment, adjust backwards
 +      if ((scrollRow + vpheight - 1) < visAlignHeight)
 +      {
 +        visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(hiddenSeqs
 +                .subtractVisibleRows(vpheight - 1, alheight - 1));
 +      }
 +      else
 +      {
 +        visYAsSeq = scrollRow;
 +      }
 +    }
 +
 +    // update scroll values
 +    scrollCol = visXAsRes;
 +    scrollRow = visYAsSeq;
 +
 +  }
 +
 +  /**
 +   * Update the overview panel box when the associated alignment panel is
 +   * changed
 +   * 
 +   * @param hiddenSeqs
 +   *          hidden sequences
 +   * @param hiddenCols
 +   *          hidden columns
 +   * @param ranges
 +   *          viewport position properties
 +   */
 +  @Override
 +  public void setBoxPosition(HiddenSequences hiddenSeqs,
-           ColumnSelection hiddenCols, ViewportRanges ranges)
++          HiddenColumns hiddenCols, ViewportRanges ranges)
 +  {
 +    alwidth = ranges.getAbsoluteAlignmentWidth();
 +    alheight = ranges.getAbsoluteAlignmentHeight();
 +
 +    // work with absolute values of startRes and endRes
 +    int startRes = hiddenCols.adjustForHiddenColumns(ranges.getStartRes());
 +    int endRes = hiddenCols.adjustForHiddenColumns(ranges.getEndRes());
 +
 +    // work with absolute values of startSeq and endSeq
 +    int startSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getStartSeq());
 +    int endSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getEndSeq());
 +
 +    // boxX, boxY is the x,y location equivalent to startRes, startSeq
 +    boxX = Math.round((float) startRes * width / alwidth);
 +    boxY = Math.round((float) startSeq * sequencesHeight / alheight);
 +
 +    // boxWidth is the width in residues translated to pixels
 +    // since the box includes both the start and end residues, add 1 to the
 +    // difference
 +    boxWidth = Math
 +            .round((float) (endRes - startRes + 1) * width / alwidth);
 +    // boxHeight is the height in sequences translated to pixels
 +    boxHeight = Math.round((float) (endSeq - startSeq + 1)
 +            * sequencesHeight
 +            / alheight);
 +  }
 +
 +  @Override
 +  public AlignmentColsCollectionI getColumns(ViewportRanges ranges,
-           ColumnSelection hiddenCols)
++          HiddenColumns hiddenCols)
 +  {
 +    return new AllColsCollection(0,
 +            ranges.getAbsoluteAlignmentWidth() - 1,
 +            hiddenCols);
 +  }
 +
 +  @Override
 +  public AlignmentRowsCollectionI getRows(ViewportRanges ranges,
 +          AlignmentI al)
 +  {
 +    return new AllRowsCollection(0,
 +            ranges.getAbsoluteAlignmentHeight() - 1,
 +            al);
 +  }
 +}
index ee82340,0000000..fbb20be
mode 100644,000000..100644
--- /dev/null
@@@ -1,85 -1,0 +1,85 @@@
 +/*
 + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 + * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * 
 + * This file is part of Jalview.
 + * 
 + * Jalview is free software: you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License 
 + * as published by the Free Software Foundation, either version 3
 + * of the License, or (at your option) any later version.
 + *  
 + * Jalview is distributed in the hope that it will be useful, but 
 + * WITHOUT ANY WARRANTY; without even the implied warranty 
 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 + * PURPOSE.  See the GNU General Public License for more details.
 + * 
 + * You should have received a copy of the GNU General Public License
 + * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
 + * The Jalview Authors are detailed in the 'AUTHORS' file.
 + */
 +package jalview.datamodel;
 +
 +import static org.testng.Assert.assertTrue;
 +
 +import java.util.NoSuchElementException;
 +
 +import org.testng.annotations.BeforeClass;
 +import org.testng.annotations.Test;
 +
 +public class AllColsIteratorTest
 +{
-   ColumnSelection hiddenCols;
++  HiddenColumns hiddenCols;
 +  
 +  @BeforeClass
 +  public void setup()
 +  {
-    hiddenCols = new ColumnSelection();
++    hiddenCols = new HiddenColumns();
 +   hiddenCols.hideColumns(2,4);
 +  }
 +  
 +
 +  /*
 +   * Test iterator iterates through collection correctly
 +   */
 +  @Test(groups = { "Functional" })
 +  public void testHasNextAndNext()
 +  {
 +    AllColsIterator it = new AllColsIterator(0, 3, hiddenCols);
 +    int count = 0;
 +    while (it.hasNext())
 +    {
 +      it.next();
 +      count++;
 +    }
 +    assertTrue(count == 4, "hasNext() is false after 4 iterations");
 +  }
 +
 +  /*
 +   * Test iterator throws NoSuchElementException at end of iteration
 +   */
 +  @Test(
 +    groups = { "Functional" },
 +    expectedExceptions = { NoSuchElementException.class })
 +  public void testLastNext() throws NoSuchElementException
 +  {
 +    AllColsIterator it = new AllColsIterator(0, 3, hiddenCols);
 +    while (it.hasNext())
 +    {
 +      it.next();
 +    }
 +    it.next();
 +  }
 +
 +  /*
 +   * Test iterator throws UnsupportedOperationException on call to remove
 +   */
 +  @Test(
 +    groups = { "Functional" },
 +    expectedExceptions = { UnsupportedOperationException.class })
 +  public void testRemove() throws UnsupportedOperationException
 +  {
 +    AllColsIterator it = new AllColsIterator(0, 3, hiddenCols);
 +    it.remove();
 +  }
 +}
index d908b78,0000000..b2d747b
mode 100644,000000..100644
--- /dev/null
@@@ -1,198 -1,0 +1,198 @@@
 +/*
 + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
 + * Copyright (C) $$Year-Rel$$ The Jalview Authors
 + * 
 + * This file is part of Jalview.
 + * 
 + * Jalview is free software: you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License 
 + * as published by the Free Software Foundation, either version 3
 + * of the License, or (at your option) any later version.
 + *  
 + * Jalview is distributed in the hope that it will be useful, but 
 + * WITHOUT ANY WARRANTY; without even the implied warranty 
 + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 + * PURPOSE.  See the GNU General Public License for more details.
 + * 
 + * You should have received a copy of the GNU General Public License
 + * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
 + * The Jalview Authors are detailed in the 'AUTHORS' file.
 + */
 +package jalview.datamodel;
 +
 +import static org.testng.Assert.assertTrue;
 +
 +import java.util.NoSuchElementException;
 +
 +import org.testng.annotations.BeforeClass;
 +import org.testng.annotations.Test;
 +
 +public class VisibleColsIteratorTest
 +{
-   ColumnSelection hiddenCols;
++  HiddenColumns hiddenCols;
 +
-   ColumnSelection hiddenColsAtStart;
++  HiddenColumns hiddenColsAtStart;
 +
 +  @BeforeClass(groups = { "Functional" })
 +  public void setup()
 +  {
-     hiddenCols = new ColumnSelection();
++    hiddenCols = new HiddenColumns();
 +    hiddenCols.hideColumns(2, 4);
 +
-     hiddenColsAtStart = new ColumnSelection();
++    hiddenColsAtStart = new HiddenColumns();
 +    hiddenColsAtStart.hideColumns(0, 2);
 +  }
 +
 +  /*
 +   * Test iterator iterates correctly through the columns
 +   * when alignment has hidden cols
 +   */
 +  @Test(groups = { "Functional" })
 +  public void testHasNextAndNextWithHidden()
 +  {
 +    VisibleColsIterator it = new VisibleColsIterator(0, 6, hiddenCols);
 +    int count = 0;
 +    while (it.hasNext())
 +    {
 +      it.next();
 +      count++;
 +    }
 +    assertTrue(count == 4, "hasNext() is false after 4 iterations");
 +  }
 +
 +  /*
 +   * Test iterator iterates correctly through the columns
 +   * when alignment has no hidden cols
 +   */
 +  @Test(groups = { "Functional" })
 +  public void testHasNextAndNextNoHidden()
 +  {
 +    VisibleColsIterator it2 = new VisibleColsIterator(0, 3,
-             new ColumnSelection());
++            new HiddenColumns());
 +    int count = 0;
 +    while (it2.hasNext())
 +    {
 +      it2.next();
 +      count++;
 +    }
 +    assertTrue(count == 4, "hasNext() is false after 4 iterations");
 +  }
 +
 +  /*
 +   * Test iterator iterates correctly through the columns
 +   * when alignment has hidden cols at start
 +   */
 +  @Test(groups = { "Functional" })
 +  public void testHasNextAndNextStartHidden()
 +  {
 +    VisibleColsIterator it3 = new VisibleColsIterator(0, 6,
 +            hiddenColsAtStart);
 +    int count = 0;
 +    while (it3.hasNext())
 +    {
 +      it3.next();
 +      count++;
 +    }
 +    assertTrue(count == 4, "hasNext() is false after 4 iterations");
 +  }
 +
 +  /*
 +   * Test iterator iterates correctly through the columns
 +   * when alignment has hidden cols at end
 +   */
 +  @Test(groups = { "Functional" })
 +  public void testHasNextAndNextEndHidden()
 +  {
 +    VisibleColsIterator it4 = new VisibleColsIterator(0, 4, hiddenCols);
 +    int count = 0;
 +    while (it4.hasNext())
 +    {
 +      it4.next();
 +      count++;
 +    }
 +    assertTrue(count == 2, "hasNext() is false after 2 iterations");
 +
 +  }
 +
 +  /*
 +   * Test iterator always throws NoSuchElementException at end of iteration
 +   * when alignment has hidden cols
 +   */
 +  @Test(
 +    groups = { "Functional" },
 +    expectedExceptions = { NoSuchElementException.class })
 +  public void testLastNextWithHidden() throws NoSuchElementException
 +  {
 +    VisibleColsIterator it = new VisibleColsIterator(0, 3, hiddenCols);
 +    while (it.hasNext())
 +    {
 +      it.next();
 +    }
 +    it.next();
 +  }
 +
 +  /*
 +   * Test iterator always throws NoSuchElementException at end of iteration
 +   * when alignment has no hidden cols
 +   */
 +  @Test(
 +    groups = { "Functional" },
 +    expectedExceptions = { NoSuchElementException.class })
 +  public void testLastNextNoHidden() throws NoSuchElementException
 +  {
 +    VisibleColsIterator it2 = new VisibleColsIterator(0, 3,
-             new ColumnSelection());
++            new HiddenColumns());
 +    while (it2.hasNext())
 +    {
 +      it2.next();
 +    }
 +    it2.next();
 +  }
 +
 +  /*
 +   * Test iterator always throws NoSuchElementException at end of iteration
 +   * when alignment has hidden cols at start
 +   */
 +  @Test(
 +    groups = { "Functional" },
 +    expectedExceptions = { NoSuchElementException.class })
 +  public void testLastNextStartHidden() throws NoSuchElementException
 +  {
 +    VisibleColsIterator it3 = new VisibleColsIterator(0, 6,
 +            hiddenColsAtStart);
 +    while (it3.hasNext())
 +    {
 +      it3.next();
 +    }
 +    it3.next();
 +  }
 +
 +  /*
 +   * Test iterator always throws NoSuchElementException at end of iteration
 +   * when alignment has hidden cols at end
 +   */
 +  @Test(
 +    groups = { "Functional" },
 +    expectedExceptions = { NoSuchElementException.class })
 +  public void testLastNextEndHidden() throws NoSuchElementException
 +  {
 +    VisibleColsIterator it4 = new VisibleColsIterator(0, 4, hiddenCols);
 +    while (it4.hasNext())
 +    {
 +      it4.next();
 +    }
 +    it4.next();
 +  }
 +
 +  /*
 +   * Test calls to remove throw UnsupportedOperationException
 +   */
 +  @Test(
 +    groups = { "Functional" },
 +    expectedExceptions = { UnsupportedOperationException.class })
 +  public void testRemove() throws UnsupportedOperationException
 +  {
 +    VisibleColsIterator it = new VisibleColsIterator(0, 3, hiddenCols);
 +    it.remove();
 +  }
 +}
@@@ -84,9 -86,9 +86,9 @@@ public class OverviewDimensionsTes
      viewHeight = vpranges.getEndSeq() - vpranges.getStartSeq() + 1;
      viewWidth = vpranges.getEndRes() - vpranges.getStartRes() + 1;
  
-     ColumnSelection hiddenCols = new ColumnSelection();
+     HiddenColumns hiddenCols = new HiddenColumns();
  
 -    od = new OverviewDimensions(vpranges, true);
 +    od = new OverviewDimensionsWithHidden(vpranges, true);
      // Initial box sizing - default path through code
      od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);