Merge branch 'develop' into feature_29/JAL-1372_referenceseq
authorJim Procter <jprocter@dundee.ac.uk>
Fri, 23 Jan 2015 14:06:11 +0000 (14:06 +0000)
committerJim Procter <jprocter@dundee.ac.uk>
Fri, 23 Jan 2015 14:06:11 +0000 (14:06 +0000)
finessing between two branches where bugs are patched twice
Conflicts:
src/jalview/appletgui/ScalePanel.java
src/jalview/appletgui/SeqCanvas.java
src/jalview/datamodel/ColumnSelection.java

1  2 
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/ScalePanel.java
src/jalview/appletgui/SeqCanvas.java
src/jalview/datamodel/ColumnSelection.java

Simple merge
@@@ -108,7 -108,7 +108,7 @@@ public class ScalePanel extends Panel i
          });
          pop.add(item);
  
-         if (av.getColumnSelection().hasHiddenColumns())
 -        if (av.getColumnSelection().getHiddenColumns().size() > 1)
++        if (av.getColumnSelection().hasManyHiddenColumns())
          {
            item = new MenuItem(MessageManager.getString("action.reveal_all"));
            item.addActionListener(new ActionListener()
--/*
-- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
-- * Copyright (C) 2014 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.AlignmentI;
--import jalview.datamodel.SearchResults;
--import jalview.datamodel.SequenceGroup;
--import jalview.datamodel.SequenceI;
--
--import java.awt.Color;
--import java.awt.FontMetrics;
--import java.awt.Graphics;
--import java.awt.Image;
--import java.awt.Panel;
--
--public class SeqCanvas extends Panel
--{
--  FeatureRenderer fr;
--
--  SequenceRenderer sr;
--
--  Image img;
--
--  Graphics gg;
--
--  int imgWidth;
--
--  int imgHeight;
--
--  AlignViewport av;
--
--  SearchResults searchResults = null;
--
--  boolean fastPaint = false;
--
--  int cursorX = 0;
--
--  int cursorY = 0;
--
--  public SeqCanvas(AlignViewport av)
--  {
--    this.av = av;
--    fr = new FeatureRenderer(av);
--    sr = new SequenceRenderer(av);
--    PaintRefresher.Register(this, av.getSequenceSetId());
--  }
--
--  public AlignViewport getViewport()
--  {
--    return av;
--  }
--
--  public FeatureRenderer getFeatureRenderer()
--  {
--    return fr;
--  }
--
--  public SequenceRenderer getSequenceRenderer()
--  {
--    return sr;
--  }
--
--  void drawNorthScale(Graphics g, int startx, int endx, int ypos)
--  {
--    int scalestartx = startx - startx % 10 + 10;
--
--    g.setColor(Color.black);
--
--    // NORTH SCALE
--    for (int i = scalestartx; i < endx; i += 10)
--    {
--      int value = i;
--      if (av.hasHiddenColumns())
--      {
--        value = av.getColumnSelection().adjustForHiddenColumns(value);
--      }
--
--      g.drawString(String.valueOf(value), (i - startx - 1) * av.charWidth,
--              ypos - (av.charHeight / 2));
--
--      g.drawLine(((i - startx - 1) * av.charWidth) + (av.charWidth / 2),
--              (ypos + 2) - (av.charHeight / 2),
--              ((i - startx - 1) * av.charWidth) + (av.charWidth / 2),
--              ypos - 2);
--    }
--  }
--
--  void drawWestScale(Graphics g, int startx, int endx, int ypos)
--  {
--    FontMetrics fm = getFontMetrics(av.getFont());
--    ypos += av.charHeight;
--    if (av.hasHiddenColumns())
--    {
--      startx = av.getColumnSelection().adjustForHiddenColumns(startx);
--      endx = av.getColumnSelection().adjustForHiddenColumns(endx);
--    }
--
--    int maxwidth = av.getAlignment().getWidth();
--    if (av.hasHiddenColumns())
--    {
--      maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
--    }
--
--    // WEST SCALE
--    for (int i = 0; i < av.getAlignment().getHeight(); i++)
--    {
--      SequenceI seq = av.getAlignment().getSequenceAt(i);
--      int index = startx;
--      int value = -1;
--
--      while (index < endx)
--      {
--        if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
--        {
--          index++;
--
--          continue;
--        }
--
--        value = av.getAlignment().getSequenceAt(i).findPosition(index);
--
--        break;
--      }
--
--      if (value != -1)
--      {
--        int x = LABEL_WEST - fm.stringWidth(String.valueOf(value))
--                - av.charWidth / 2;
--        g.drawString(value + "", x, (ypos + (i * av.charHeight))
--                - (av.charHeight / 5));
--      }
--    }
--  }
--
--  void drawEastScale(Graphics g, int startx, int endx, int ypos)
--  {
--    ypos += av.charHeight;
--
--    if (av.hasHiddenColumns())
--    {
--      endx = av.getColumnSelection().adjustForHiddenColumns(endx);
--    }
--
--    SequenceI seq;
--    // EAST SCALE
--    for (int i = 0; i < av.getAlignment().getHeight(); i++)
--    {
--      seq = av.getAlignment().getSequenceAt(i);
--      int index = endx;
--      int value = -1;
--
--      while (index > startx)
--      {
--        if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
--        {
--          index--;
--
--          continue;
--        }
--
--        value = seq.findPosition(index);
--
--        break;
--      }
--
--      if (value != -1)
--      {
--        g.drawString(String.valueOf(value), 0, (ypos + (i * av.charHeight))
--                - (av.charHeight / 5));
--      }
--    }
--  }
--
--  int lastsr = 0;
--
--  void fastPaint(int horizontal, int vertical)
--  {
--    if (fastPaint || gg == null)
--    {
--      return;
--    }
--
--    // Its possible on certain browsers that the call to fastpaint
--    // is faster than it can paint, so this check here catches
--    // this possibility
--    if (lastsr + horizontal != av.startRes)
--    {
--      horizontal = av.startRes - lastsr;
--    }
--
--    lastsr = av.startRes;
--
--    fastPaint = true;
--    gg.copyArea(horizontal * av.charWidth, vertical * av.charHeight,
--            imgWidth - horizontal * av.charWidth, imgHeight - vertical
--                    * av.charHeight, -horizontal * av.charWidth, -vertical
--                    * av.charHeight);
--
--    int sr = av.startRes, er = av.endRes, ss = av.startSeq, es = av.endSeq, transX = 0, transY = 0;
--
--    if (horizontal > 0) // scrollbar pulled right, image to the left
--    {
--      transX = (er - sr - horizontal) * av.charWidth;
--      sr = er - horizontal;
--    }
--    else if (horizontal < 0)
--    {
--      er = sr - horizontal;
--    }
--
--    else if (vertical > 0) // scroll down
--    {
--      ss = es - vertical;
--      if (ss < av.startSeq) // ie scrolling too fast, more than a page at a time
--      {
--        ss = av.startSeq;
--      }
--      else
--      {
--        transY = imgHeight - vertical * av.charHeight;
--      }
--    }
--    else if (vertical < 0)
--    {
--      es = ss - vertical;
--      if (es > av.endSeq)
--      {
--        es = av.endSeq;
--      }
--    }
--
--    gg.translate(transX, transY);
--
--    drawPanel(gg, sr, er, ss, es, 0);
--    gg.translate(-transX, -transY);
--
--    repaint();
--
--  }
--
--  /**
--   * Definitions of startx and endx (hopefully): SMJS This is what I'm working
--   * towards! startx is the first residue (starting at 0) to display. endx is
--   * the last residue to display (starting at 0). starty is the first sequence
--   * to display (starting at 0). endy is the last sequence to display (starting
--   * at 0). NOTE 1: The av limits are set in setFont in this class and in the
--   * adjustment listener in SeqPanel when the scrollbars move.
--   */
--  public void update(Graphics g)
--  {
--    paint(g);
--  }
--
--  public void paint(Graphics g)
--  {
--
--    if (img != null
--            && (fastPaint || (getSize().width != g.getClipBounds().width) || (getSize().height != g
--                    .getClipBounds().height)))
--    {
--      g.drawImage(img, 0, 0, this);
--      fastPaint = false;
--      return;
--    }
--
--    if (fastPaint)
--    {
--      g.drawImage(img, 0, 0, this);
--      fastPaint = false;
--      return;
--    }
--
--    // this draws the whole of the alignment
--    imgWidth = this.getSize().width;
--    imgHeight = this.getSize().height;
--
--    imgWidth -= imgWidth % av.charWidth;
--    imgHeight -= imgHeight % av.charHeight;
--
--    if (imgWidth < 1 || imgHeight < 1)
--    {
--      return;
--    }
--
--    if (img == null || imgWidth != img.getWidth(this)
--            || imgHeight != img.getHeight(this))
--    {
--      img = createImage(imgWidth, imgHeight);
--      gg = img.getGraphics();
--      gg.setFont(av.getFont());
--    }
--
--    gg.setColor(Color.white);
--    gg.fillRect(0, 0, imgWidth, imgHeight);
--
--    if (av.getWrapAlignment())
--    {
--      drawWrappedPanel(gg, imgWidth, imgHeight, av.startRes);
--    }
--    else
--    {
--      drawPanel(gg, av.startRes, av.endRes, av.startSeq, av.endSeq, 0);
--    }
--
--    g.drawImage(img, 0, 0, this);
--
--  }
--
--  int LABEL_WEST, LABEL_EAST;
--
--  public int getWrappedCanvasWidth(int cwidth)
--  {
--    cwidth -= cwidth % av.charWidth;
--
--    FontMetrics fm = getFontMetrics(av.getFont());
--
--    LABEL_EAST = 0;
--    LABEL_WEST = 0;
--
--    if (av.scaleRightWrapped)
--    {
--      LABEL_EAST = fm.stringWidth(getMask());
--    }
--
--    if (av.scaleLeftWrapped)
--    {
--      LABEL_WEST = fm.stringWidth(getMask());
--    }
--
--    return (cwidth - LABEL_EAST - LABEL_WEST) / av.charWidth;
--  }
--
--  /**
--   * Generates a string of zeroes.
--   * 
--   * @return String
--   */
--  String getMask()
--  {
--    String mask = "0";
--    int maxWidth = 0;
--    int tmp;
--    AlignmentI alignment = av.getAlignment();
--    for (int i = 0; i < alignment.getHeight(); i++)
--    {
--      tmp = alignment.getSequenceAt(i).getEnd();
--      if (tmp > maxWidth)
--      {
--        maxWidth = tmp;
--      }
--    }
--
--    for (int i = maxWidth; i > 0; i /= 10)
--    {
--      mask += "0";
--    }
--    return mask;
--  }
--
--  public void drawWrappedPanel(Graphics g, int canvasWidth,
--          int canvasHeight, int startRes)
--  {
--    AlignmentI al = av.getAlignment();
--
--    FontMetrics fm = getFontMetrics(av.getFont());
--
--    if (av.scaleRightWrapped)
--    {
--      LABEL_EAST = fm.stringWidth(getMask());
--    }
--
--    if (av.scaleLeftWrapped)
--    {
--      LABEL_WEST = fm.stringWidth(getMask());
--    }
--
--    int hgap = av.charHeight;
--    if (av.scaleAboveWrapped)
--    {
--      hgap += av.charHeight;
--    }
--
--    int cWidth = (canvasWidth - LABEL_EAST - LABEL_WEST) / av.charWidth;
--    int cHeight = av.getAlignment().getHeight() * av.charHeight;
--
--    av.setWrappedWidth(cWidth);
--
--    av.endRes = av.startRes + cWidth;
--
--    int endx;
--    int ypos = hgap;
--
--    int maxwidth = av.getAlignment().getWidth() - 1;
--
--    if (av.hasHiddenColumns())
--    {
--      maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
--    }
--
--    while ((ypos <= canvasHeight) && (startRes < maxwidth))
--    {
--      endx = startRes + cWidth - 1;
--
--      if (endx > maxwidth)
--      {
--        endx = maxwidth;
--      }
--
--      g.setColor(Color.black);
--
--      if (av.scaleLeftWrapped)
--      {
--        drawWestScale(g, startRes, endx, ypos);
--      }
--
--      if (av.scaleRightWrapped)
--      {
--        g.translate(canvasWidth - LABEL_EAST, 0);
--        drawEastScale(g, startRes, endx, ypos);
--        g.translate(-(canvasWidth - LABEL_EAST), 0);
--      }
--
--      g.translate(LABEL_WEST, 0);
--
--      if (av.scaleAboveWrapped)
--      {
--        drawNorthScale(g, startRes, endx, ypos);
--      }
--      if (av.hasHiddenColumns() && av.showHiddenMarkers)
--      {
--        g.setColor(Color.blue);
--        int res;
--        for (int i = 0; i < av.getColumnSelection().getHiddenColumns()
--                .size(); i++)
--        {
--          res = av.getColumnSelection().findHiddenRegionPosition(i)
--                  - startRes;
--
--          if (res < 0 || res > endx - startRes)
--          {
--            continue;
--          }
--
--          gg.fillPolygon(new int[]
--          { res * av.charWidth - av.charHeight / 4,
--              res * av.charWidth + av.charHeight / 4, res * av.charWidth },
--                  new int[]
--                  { ypos - (av.charHeight / 2), ypos - (av.charHeight / 2),
--                      ypos - (av.charHeight / 2) + 8 }, 3);
--
--        }
--      }
--
--      if (g.getClip() == null)
--      {
--        g.setClip(0, 0, cWidth * av.charWidth, canvasHeight);
--      }
--
--      drawPanel(g, startRes, endx, 0, al.getHeight(), ypos);
--      g.setClip(null);
--
--      if (av.showAnnotation)
--      {
--        g.translate(0, cHeight + ypos + 4);
--        if (annotations == null)
--        {
--          annotations = new AnnotationPanel(av);
--        }
--
--        annotations.drawComponent(g, startRes, endx + 1);
--        g.translate(0, -cHeight - ypos - 4);
--      }
--      g.translate(-LABEL_WEST, 0);
--
--      ypos += cHeight + getAnnotationHeight() + hgap;
--
--      startRes += cWidth;
--    }
--
--  }
--
--  AnnotationPanel annotations;
--
--  int getAnnotationHeight()
--  {
--    if (!av.showAnnotation)
--    {
--      return 0;
--    }
--
--    if (annotations == null)
--    {
--      annotations = new AnnotationPanel(av);
--    }
--
--    return annotations.adjustPanelHeight();
--  }
--
--  void drawPanel(Graphics g1, int startRes, int endRes, int startSeq,
--          int endSeq, int offset)
--  {
-     if (!av.hasHiddenColumns())
-     {
-       draw(g1, startRes, endRes, startSeq, endSeq, offset);
-     }
-     else
-     {
-       java.util.List<int[]> regions = av.getColumnSelection()
-               .getHiddenColumns();
--
-       int screenY = 0;
-       int blockStart = startRes;
-       int blockEnd = endRes;
--
-       for (int i = 0; i < regions.size(); i++)
-       {
-         int[] region = regions.get(i);
-         int hideStart = region[0];
-         int hideEnd = region[1];
-         if (hideStart <= blockStart)
-         {
-           blockStart += (hideEnd - hideStart) + 1;
-           continue;
-         }
-         blockEnd = hideStart - 1;
-         g1.translate(screenY * av.charWidth, 0);
-         draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
-         if (av.getShowHiddenMarkers())
-         {
-           g1.setColor(Color.blue);
-           g1.drawLine((blockEnd - blockStart + 1) * av.charWidth - 1,
-                   0 + offset, (blockEnd - blockStart + 1) * av.charWidth
-                           - 1, (endSeq - startSeq) * av.charHeight + offset);
-         }
-         g1.translate(-screenY * av.charWidth, 0);
-         screenY += blockEnd - blockStart + 1;
-         blockStart = hideEnd + 1;
-       }
-       if (screenY <= (endRes - startRes))
-       {
-         blockEnd = blockStart + (endRes - startRes) - screenY;
-         g1.translate(screenY * av.charWidth, 0);
-         draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
-         g1.translate(-screenY * av.charWidth, 0);
-       }
-     }
-   }
-   // int startRes, int endRes, int startSeq, int endSeq, int x, int y,
-   // int x1, int x2, int y1, int y2, int startx, int starty,
-   void draw(Graphics g, int startRes, int endRes, int startSeq, int endSeq,
-           int offset)
-   {
-     g.setFont(av.getFont());
-     sr.prepare(g, av.renderGaps);
-     SequenceI nextSeq;
-     // / First draw the sequences
-     // ///////////////////////////
-     for (int i = startSeq; i < endSeq; i++)
-     {
-       nextSeq = av.getAlignment().getSequenceAt(i);
-       if (nextSeq == null)
-       {
-         continue;
-       }
-       sr.drawSequence(nextSeq, av.getAlignment().findAllGroups(nextSeq),
-               startRes, endRes, offset + ((i - startSeq) * av.charHeight));
-       if (av.isShowSequenceFeatures())
-       {
-         fr.drawSequence(g, nextSeq, startRes, endRes, offset
-                 + ((i - startSeq) * av.charHeight));
-       }
-       // / Highlight search Results once all sequences have been drawn
-       // ////////////////////////////////////////////////////////
-       if (searchResults != null)
-       {
-         int[] visibleResults = searchResults.getResults(nextSeq, startRes,
-                 endRes);
-         if (visibleResults != null)
-         {
-           for (int r = 0; r < visibleResults.length; r += 2)
-           {
-             sr.drawHighlightedText(nextSeq, visibleResults[r],
-                     visibleResults[r + 1], (visibleResults[r] - startRes)
-                             * av.charWidth, offset
-                             + ((i - startSeq) * av.charHeight));
-           }
-         }
-       }
-       if (av.cursorMode && cursorY == i && cursorX >= startRes
-               && cursorX <= endRes)
-       {
-         sr.drawCursor(nextSeq, cursorX,
-                 (cursorX - startRes) * av.charWidth, offset
-                         + ((i - startSeq) * av.charHeight));
-       }
-     }
-     if (av.getSelectionGroup() != null
-             || av.getAlignment().getGroups().size() > 0)
-     {
-       drawGroupsBoundaries(g, startRes, endRes, startSeq, endSeq, offset);
-     }
-   }
-   void drawGroupsBoundaries(Graphics g, int startRes, int endRes,
-           int startSeq, int endSeq, int offset)
-   {
-     //
-     // ///////////////////////////////////
-     // Now outline any areas if necessary
-     // ///////////////////////////////////
-     SequenceGroup group = av.getSelectionGroup();
-     int sx = -1;
-     int sy = -1;
-     int ex = -1;
-     int groupIndex = -1;
-     if ((group == null) && (av.getAlignment().getGroups().size() > 0))
-     {
-       group = av.getAlignment().getGroups().get(0);
-       groupIndex = 0;
-     }
-     if (group != null)
-     {
-       do
-       {
-         int oldY = -1;
-         int i = 0;
-         boolean inGroup = false;
-         int top = -1;
-         int bottom = -1;
-         int alHeight = av.getAlignment().getHeight() - 1;
-         for (i = startSeq; i < endSeq; i++)
-         {
-           sx = (group.getStartRes() - startRes) * av.charWidth;
-           sy = offset + ((i - startSeq) * av.charHeight);
-           ex = (((group.getEndRes() + 1) - group.getStartRes()) * av.charWidth) - 1;
-           if (sx + ex < 0 || sx > imgWidth)
-           {
-             continue;
-           }
-           if ((sx <= (endRes - startRes) * av.charWidth)
-                   && group.getSequences(null).contains(
-                           av.getAlignment().getSequenceAt(i)))
-           {
-             if ((bottom == -1)
-                     && (i >= alHeight || !group.getSequences(null)
-                             .contains(
-                                     av.getAlignment().getSequenceAt(i + 1))))
-             {
-               bottom = sy + av.charHeight;
-             }
-             if (!inGroup)
-             {
-               if (((top == -1) && (i == 0))
-                       || !group.getSequences(null).contains(
-                               av.getAlignment().getSequenceAt(i - 1)))
-               {
-                 top = sy;
-               }
-               oldY = sy;
-               inGroup = true;
-               if (group == av.getSelectionGroup())
-               {
-                 g.setColor(Color.red);
-               }
-               else
-               {
-                 g.setColor(group.getOutlineColour());
-               }
-             }
-           }
-           else
-           {
-             if (inGroup)
-             {
-               if (sx >= 0 && sx < imgWidth)
-               {
-                 g.drawLine(sx, oldY, sx, sy);
-               }
-               if (sx + ex < imgWidth)
-               {
-                 g.drawLine(sx + ex, oldY, sx + ex, sy);
-               }
-               if (sx < 0)
-               {
-                 ex += sx;
-                 sx = 0;
-               }
-               if (sx + ex > imgWidth)
-               {
-                 ex = imgWidth;
-               }
-               else if (sx + ex >= (endRes - startRes + 1) * av.charWidth)
-               {
-                 ex = (endRes - startRes + 1) * av.charWidth;
-               }
-               if (top != -1)
-               {
-                 g.drawLine(sx, top, sx + ex, top);
-                 top = -1;
-               }
-               if (bottom != -1)
-               {
-                 g.drawLine(sx, bottom, sx + ex, bottom);
-                 bottom = -1;
-               }
-               inGroup = false;
-             }
-           }
-         }
-         if (inGroup)
-         {
-           sy = offset + ((i - startSeq) * av.charHeight);
-           if (sx >= 0 && sx < imgWidth)
-           {
-             g.drawLine(sx, oldY, sx, sy);
-           }
-           if (sx + ex < imgWidth)
-           {
-             g.drawLine(sx + ex, oldY, sx + ex, sy);
-           }
-           if (sx < 0)
-           {
-             ex += sx;
-             sx = 0;
-           }
-           if (sx + ex > imgWidth)
-           {
-             ex = imgWidth;
-           }
-           else if (sx + ex >= (endRes - startRes + 1) * av.charWidth)
-           {
-             ex = (endRes - startRes + 1) * av.charWidth;
-           }
-           if (top != -1)
-           {
-             g.drawLine(sx, top, sx + ex, top);
-             top = -1;
-           }
-           if (bottom != -1)
-           {
-             g.drawLine(sx, bottom - 1, sx + ex, bottom - 1);
-             bottom = -1;
-           }
-           inGroup = false;
-         }
-         groupIndex++;
-         if (groupIndex >= av.getAlignment().getGroups().size())
-         {
-           break;
-         }
-         group = av.getAlignment().getGroups()
-                 .get(groupIndex);
-       } while (groupIndex < av.getAlignment().getGroups().size());
-     }
-   }
-   public void highlightSearchResults(SearchResults results)
-   {
-     searchResults = results;
-     repaint();
-   }
- }
 -    if (!av.hasHiddenColumns())
 -    {
 -      draw(g1, startRes, endRes, startSeq, endSeq, offset);
 -    }
 -    else
 -    {
 -
 -
 -
 -      int screenY = 0;
 -      int blockStart = startRes;
 -      int blockEnd = endRes;
 -
 -      if (av.getColumnSelection() != null
 -              && av.getColumnSelection().getHiddenColumns() != null)
 -      {
 -        java.util.Vector regions = av.getColumnSelection()
 -                .getHiddenColumns();
 -
 -      for (int i = 0; i < regions.size(); i++)
 -      {
 -        int[] region = (int[]) regions.elementAt(i);
 -        int hideStart = region[0];
 -        int hideEnd = region[1];
 -
 -        if (hideStart <= blockStart)
 -        {
 -          blockStart += (hideEnd - hideStart) + 1;
 -          continue;
 -        }
 -
 -        blockEnd = hideStart - 1;
 -
 -        g1.translate(screenY * av.charWidth, 0);
 -
 -        draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
 -
 -        if (av.getShowHiddenMarkers())
 -        {
 -          g1.setColor(Color.blue);
 -          g1.drawLine((blockEnd - blockStart + 1) * av.charWidth - 1,
 -                  0 + offset, (blockEnd - blockStart + 1) * av.charWidth
 -                          - 1, (endSeq - startSeq) * av.charHeight + offset);
 -        }
 -
 -        g1.translate(-screenY * av.charWidth, 0);
 -        screenY += blockEnd - blockStart + 1;
 -        blockStart = hideEnd + 1;
 -      }
 -      }
 -      if (screenY <= (endRes - startRes))
 -      {
 -        blockEnd = blockStart + (endRes - startRes) - screenY;
 -        g1.translate(screenY * av.charWidth, 0);
 -        draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
 -
 -        g1.translate(-screenY * av.charWidth, 0);
 -      }
 -    }
 -
 -  }
 -
 -  // int startRes, int endRes, int startSeq, int endSeq, int x, int y,
 -  // int x1, int x2, int y1, int y2, int startx, int starty,
 -  void draw(Graphics g, int startRes, int endRes, int startSeq, int endSeq,
 -          int offset)
 -  {
 -    g.setFont(av.getFont());
 -    sr.prepare(g, av.renderGaps);
 -
 -    SequenceI nextSeq;
 -
 -    // / First draw the sequences
 -    // ///////////////////////////
 -    for (int i = startSeq; i < endSeq; i++)
 -    {
 -      nextSeq = av.getAlignment().getSequenceAt(i);
 -
 -      if (nextSeq == null)
 -      {
 -        continue;
 -      }
 -
 -      sr.drawSequence(nextSeq, av.getAlignment().findAllGroups(nextSeq),
 -              startRes, endRes, offset + ((i - startSeq) * av.charHeight));
 -
 -      if (av.isShowSequenceFeatures())
 -      {
 -        fr.drawSequence(g, nextSeq, startRes, endRes, offset
 -                + ((i - startSeq) * av.charHeight));
 -      }
 -
 -      // / Highlight search Results once all sequences have been drawn
 -      // ////////////////////////////////////////////////////////
 -      if (searchResults != null)
 -      {
 -        int[] visibleResults = searchResults.getResults(nextSeq, startRes,
 -                endRes);
 -        if (visibleResults != null)
 -        {
 -          for (int r = 0; r < visibleResults.length; r += 2)
 -          {
 -            sr.drawHighlightedText(nextSeq, visibleResults[r],
 -                    visibleResults[r + 1], (visibleResults[r] - startRes)
 -                            * av.charWidth, offset
 -                            + ((i - startSeq) * av.charHeight));
 -          }
 -        }
 -      }
 -
 -      if (av.cursorMode && cursorY == i && cursorX >= startRes
 -              && cursorX <= endRes)
 -      {
 -        sr.drawCursor(nextSeq, cursorX,
 -                (cursorX - startRes) * av.charWidth, offset
 -                        + ((i - startSeq) * av.charHeight));
 -      }
 -    }
 -
 -    if (av.getSelectionGroup() != null
 -            || av.getAlignment().getGroups().size() > 0)
 -    {
 -      drawGroupsBoundaries(g, startRes, endRes, startSeq, endSeq, offset);
 -    }
 -
 -  }
 -
 -  void drawGroupsBoundaries(Graphics g, int startRes, int endRes,
 -          int startSeq, int endSeq, int offset)
 -  {
 -    //
 -    // ///////////////////////////////////
 -    // Now outline any areas if necessary
 -    // ///////////////////////////////////
 -    SequenceGroup group = av.getSelectionGroup();
 -
 -    int sx = -1;
 -    int sy = -1;
 -    int ex = -1;
 -    int groupIndex = -1;
 -
 -    if ((group == null) && (av.getAlignment().getGroups().size() > 0))
 -    {
 -      group = av.getAlignment().getGroups().get(0);
 -      groupIndex = 0;
 -    }
 -
 -    if (group != null)
 -    {
 -      do
 -      {
 -        int oldY = -1;
 -        int i = 0;
 -        boolean inGroup = false;
 -        int top = -1;
 -        int bottom = -1;
 -        int alHeight = av.getAlignment().getHeight() - 1;
 -
 -        for (i = startSeq; i < endSeq; i++)
 -        {
 -          sx = (group.getStartRes() - startRes) * av.charWidth;
 -          sy = offset + ((i - startSeq) * av.charHeight);
 -          ex = (((group.getEndRes() + 1) - group.getStartRes()) * av.charWidth) - 1;
 -
 -          if (sx + ex < 0 || sx > imgWidth)
 -          {
 -            continue;
 -          }
 -
 -          if ((sx <= (endRes - startRes) * av.charWidth)
 -                  && group.getSequences(null).contains(
 -                          av.getAlignment().getSequenceAt(i)))
 -          {
 -            if ((bottom == -1)
 -                    && (i >= alHeight || !group.getSequences(null)
 -                            .contains(
 -                                    av.getAlignment().getSequenceAt(i + 1))))
 -            {
 -              bottom = sy + av.charHeight;
 -            }
 -
 -            if (!inGroup)
 -            {
 -              if (((top == -1) && (i == 0))
 -                      || !group.getSequences(null).contains(
 -                              av.getAlignment().getSequenceAt(i - 1)))
 -              {
 -                top = sy;
 -              }
 -
 -              oldY = sy;
 -              inGroup = true;
 -
 -              if (group == av.getSelectionGroup())
 -              {
 -                g.setColor(Color.red);
 -              }
 -              else
 -              {
 -                g.setColor(group.getOutlineColour());
 -              }
 -            }
 -          }
 -          else
 -          {
 -            if (inGroup)
 -            {
 -              if (sx >= 0 && sx < imgWidth)
 -              {
 -                g.drawLine(sx, oldY, sx, sy);
 -              }
 -
 -              if (sx + ex < imgWidth)
 -              {
 -                g.drawLine(sx + ex, oldY, sx + ex, sy);
 -              }
 -
 -              if (sx < 0)
 -              {
 -                ex += sx;
 -                sx = 0;
 -              }
 -
 -              if (sx + ex > imgWidth)
 -              {
 -                ex = imgWidth;
 -              }
 -
 -              else if (sx + ex >= (endRes - startRes + 1) * av.charWidth)
 -              {
 -                ex = (endRes - startRes + 1) * av.charWidth;
 -              }
 -
 -              if (top != -1)
 -              {
 -                g.drawLine(sx, top, sx + ex, top);
 -                top = -1;
 -              }
 -
 -              if (bottom != -1)
 -              {
 -                g.drawLine(sx, bottom, sx + ex, bottom);
 -                bottom = -1;
 -              }
 -
 -              inGroup = false;
 -            }
 -          }
 -        }
 -
 -        if (inGroup)
 -        {
 -          sy = offset + ((i - startSeq) * av.charHeight);
 -          if (sx >= 0 && sx < imgWidth)
 -          {
 -            g.drawLine(sx, oldY, sx, sy);
 -          }
 -
 -          if (sx + ex < imgWidth)
 -          {
 -            g.drawLine(sx + ex, oldY, sx + ex, sy);
 -          }
 -
 -          if (sx < 0)
 -          {
 -            ex += sx;
 -            sx = 0;
 -          }
 -
 -          if (sx + ex > imgWidth)
 -          {
 -            ex = imgWidth;
 -          }
 -          else if (sx + ex >= (endRes - startRes + 1) * av.charWidth)
 -          {
 -            ex = (endRes - startRes + 1) * av.charWidth;
 -          }
 -
 -          if (top != -1)
 -          {
 -            g.drawLine(sx, top, sx + ex, top);
 -            top = -1;
 -          }
 -
 -          if (bottom != -1)
 -          {
 -            g.drawLine(sx, bottom - 1, sx + ex, bottom - 1);
 -            bottom = -1;
 -          }
 -
 -          inGroup = false;
 -        }
 -
 -        groupIndex++;
 -
 -        if (groupIndex >= av.getAlignment().getGroups().size())
 -        {
 -          break;
 -        }
 -
 -        group = av.getAlignment().getGroups()
 -                .get(groupIndex);
 -      } while (groupIndex < av.getAlignment().getGroups().size());
 -
 -    }
 -  }
 -
 -  public void highlightSearchResults(SearchResults results)
 -  {
 -    searchResults = results;
 -
 -    repaint();
 -  }
 -
 -}
++/*\r
++ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)\r
++ * Copyright (C) 2014 The Jalview Authors\r
++ * \r
++ * This file is part of Jalview.\r
++ * \r
++ * Jalview is free software: you can redistribute it and/or\r
++ * modify it under the terms of the GNU General Public License \r
++ * as published by the Free Software Foundation, either version 3\r
++ * of the License, or (at your option) any later version.\r
++ *  \r
++ * Jalview is distributed in the hope that it will be useful, but \r
++ * WITHOUT ANY WARRANTY; without even the implied warranty \r
++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR \r
++ * PURPOSE.  See the GNU General Public License for more details.\r
++ * \r
++ * You should have received a copy of the GNU General Public License\r
++ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.\r
++ * The Jalview Authors are detailed in the 'AUTHORS' file.\r
++ */\r
++package jalview.appletgui;\r
++\r
++import jalview.datamodel.AlignmentI;\r
++import jalview.datamodel.SearchResults;\r
++import jalview.datamodel.SequenceGroup;\r
++import jalview.datamodel.SequenceI;\r
++\r
++import java.awt.Color;\r
++import java.awt.FontMetrics;\r
++import java.awt.Graphics;\r
++import java.awt.Image;\r
++import java.awt.Panel;\r
++\r
++public class SeqCanvas extends Panel\r
++{\r
++  FeatureRenderer fr;\r
++\r
++  SequenceRenderer sr;\r
++\r
++  Image img;\r
++\r
++  Graphics gg;\r
++\r
++  int imgWidth;\r
++\r
++  int imgHeight;\r
++\r
++  AlignViewport av;\r
++\r
++  SearchResults searchResults = null;\r
++\r
++  boolean fastPaint = false;\r
++\r
++  int cursorX = 0;\r
++\r
++  int cursorY = 0;\r
++\r
++  public SeqCanvas(AlignViewport av)\r
++  {\r
++    this.av = av;\r
++    fr = new FeatureRenderer(av);\r
++    sr = new SequenceRenderer(av);\r
++    PaintRefresher.Register(this, av.getSequenceSetId());\r
++  }\r
++\r
++  public AlignViewport getViewport()\r
++  {\r
++    return av;\r
++  }\r
++\r
++  public FeatureRenderer getFeatureRenderer()\r
++  {\r
++    return fr;\r
++  }\r
++\r
++  public SequenceRenderer getSequenceRenderer()\r
++  {\r
++    return sr;\r
++  }\r
++\r
++  void drawNorthScale(Graphics g, int startx, int endx, int ypos)\r
++  {\r
++    int scalestartx = startx - startx % 10 + 10;\r
++\r
++    g.setColor(Color.black);\r
++\r
++    // NORTH SCALE\r
++    for (int i = scalestartx; i < endx; i += 10)\r
++    {\r
++      int value = i;\r
++      if (av.hasHiddenColumns())\r
++      {\r
++        value = av.getColumnSelection().adjustForHiddenColumns(value);\r
++      }\r
++\r
++      g.drawString(String.valueOf(value), (i - startx - 1) * av.charWidth,\r
++              ypos - (av.charHeight / 2));\r
++\r
++      g.drawLine(((i - startx - 1) * av.charWidth) + (av.charWidth / 2),\r
++              (ypos + 2) - (av.charHeight / 2),\r
++              ((i - startx - 1) * av.charWidth) + (av.charWidth / 2),\r
++              ypos - 2);\r
++    }\r
++  }\r
++\r
++  void drawWestScale(Graphics g, int startx, int endx, int ypos)\r
++  {\r
++    FontMetrics fm = getFontMetrics(av.getFont());\r
++    ypos += av.charHeight;\r
++    if (av.hasHiddenColumns())\r
++    {\r
++      startx = av.getColumnSelection().adjustForHiddenColumns(startx);\r
++      endx = av.getColumnSelection().adjustForHiddenColumns(endx);\r
++    }\r
++\r
++    int maxwidth = av.getAlignment().getWidth();\r
++    if (av.hasHiddenColumns())\r
++    {\r
++      maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;\r
++    }\r
++\r
++    // WEST SCALE\r
++    for (int i = 0; i < av.getAlignment().getHeight(); i++)\r
++    {\r
++      SequenceI seq = av.getAlignment().getSequenceAt(i);\r
++      int index = startx;\r
++      int value = -1;\r
++\r
++      while (index < endx)\r
++      {\r
++        if (jalview.util.Comparison.isGap(seq.getCharAt(index)))\r
++        {\r
++          index++;\r
++\r
++          continue;\r
++        }\r
++\r
++        value = av.getAlignment().getSequenceAt(i).findPosition(index);\r
++\r
++        break;\r
++      }\r
++\r
++      if (value != -1)\r
++      {\r
++        int x = LABEL_WEST - fm.stringWidth(String.valueOf(value))\r
++                - av.charWidth / 2;\r
++        g.drawString(value + "", x, (ypos + (i * av.charHeight))\r
++                - (av.charHeight / 5));\r
++      }\r
++    }\r
++  }\r
++\r
++  void drawEastScale(Graphics g, int startx, int endx, int ypos)\r
++  {\r
++    ypos += av.charHeight;\r
++\r
++    if (av.hasHiddenColumns())\r
++    {\r
++      endx = av.getColumnSelection().adjustForHiddenColumns(endx);\r
++    }\r
++\r
++    SequenceI seq;\r
++    // EAST SCALE\r
++    for (int i = 0; i < av.getAlignment().getHeight(); i++)\r
++    {\r
++      seq = av.getAlignment().getSequenceAt(i);\r
++      int index = endx;\r
++      int value = -1;\r
++\r
++      while (index > startx)\r
++      {\r
++        if (jalview.util.Comparison.isGap(seq.getCharAt(index)))\r
++        {\r
++          index--;\r
++\r
++          continue;\r
++        }\r
++\r
++        value = seq.findPosition(index);\r
++\r
++        break;\r
++      }\r
++\r
++      if (value != -1)\r
++      {\r
++        g.drawString(String.valueOf(value), 0, (ypos + (i * av.charHeight))\r
++                - (av.charHeight / 5));\r
++      }\r
++    }\r
++  }\r
++\r
++  int lastsr = 0;\r
++\r
++  void fastPaint(int horizontal, int vertical)\r
++  {\r
++    if (fastPaint || gg == null)\r
++    {\r
++      return;\r
++    }\r
++\r
++    // Its possible on certain browsers that the call to fastpaint\r
++    // is faster than it can paint, so this check here catches\r
++    // this possibility\r
++    if (lastsr + horizontal != av.startRes)\r
++    {\r
++      horizontal = av.startRes - lastsr;\r
++    }\r
++\r
++    lastsr = av.startRes;\r
++\r
++    fastPaint = true;\r
++    gg.copyArea(horizontal * av.charWidth, vertical * av.charHeight,\r
++            imgWidth - horizontal * av.charWidth, imgHeight - vertical\r
++                    * av.charHeight, -horizontal * av.charWidth, -vertical\r
++                    * av.charHeight);\r
++\r
++    int sr = av.startRes, er = av.endRes, ss = av.startSeq, es = av.endSeq, transX = 0, transY = 0;\r
++\r
++    if (horizontal > 0) // scrollbar pulled right, image to the left\r
++    {\r
++      transX = (er - sr - horizontal) * av.charWidth;\r
++      sr = er - horizontal;\r
++    }\r
++    else if (horizontal < 0)\r
++    {\r
++      er = sr - horizontal;\r
++    }\r
++\r
++    else if (vertical > 0) // scroll down\r
++    {\r
++      ss = es - vertical;\r
++      if (ss < av.startSeq) // ie scrolling too fast, more than a page at a time\r
++      {\r
++        ss = av.startSeq;\r
++      }\r
++      else\r
++      {\r
++        transY = imgHeight - vertical * av.charHeight;\r
++      }\r
++    }\r
++    else if (vertical < 0)\r
++    {\r
++      es = ss - vertical;\r
++      if (es > av.endSeq)\r
++      {\r
++        es = av.endSeq;\r
++      }\r
++    }\r
++\r
++    gg.translate(transX, transY);\r
++\r
++    drawPanel(gg, sr, er, ss, es, 0);\r
++    gg.translate(-transX, -transY);\r
++\r
++    repaint();\r
++\r
++  }\r
++\r
++  /**\r
++   * Definitions of startx and endx (hopefully): SMJS This is what I'm working\r
++   * towards! startx is the first residue (starting at 0) to display. endx is\r
++   * the last residue to display (starting at 0). starty is the first sequence\r
++   * to display (starting at 0). endy is the last sequence to display (starting\r
++   * at 0). NOTE 1: The av limits are set in setFont in this class and in the\r
++   * adjustment listener in SeqPanel when the scrollbars move.\r
++   */\r
++  public void update(Graphics g)\r
++  {\r
++    paint(g);\r
++  }\r
++\r
++  public void paint(Graphics g)\r
++  {\r
++\r
++    if (img != null\r
++            && (fastPaint || (getSize().width != g.getClipBounds().width) || (getSize().height != g\r
++                    .getClipBounds().height)))\r
++    {\r
++      g.drawImage(img, 0, 0, this);\r
++      fastPaint = false;\r
++      return;\r
++    }\r
++\r
++    if (fastPaint)\r
++    {\r
++      g.drawImage(img, 0, 0, this);\r
++      fastPaint = false;\r
++      return;\r
++    }\r
++\r
++    // this draws the whole of the alignment\r
++    imgWidth = this.getSize().width;\r
++    imgHeight = this.getSize().height;\r
++\r
++    imgWidth -= imgWidth % av.charWidth;\r
++    imgHeight -= imgHeight % av.charHeight;\r
++\r
++    if (imgWidth < 1 || imgHeight < 1)\r
++    {\r
++      return;\r
++    }\r
++\r
++    if (img == null || imgWidth != img.getWidth(this)\r
++            || imgHeight != img.getHeight(this))\r
++    {\r
++      img = createImage(imgWidth, imgHeight);\r
++      gg = img.getGraphics();\r
++      gg.setFont(av.getFont());\r
++    }\r
++\r
++    gg.setColor(Color.white);\r
++    gg.fillRect(0, 0, imgWidth, imgHeight);\r
++\r
++    if (av.getWrapAlignment())\r
++    {\r
++      drawWrappedPanel(gg, imgWidth, imgHeight, av.startRes);\r
++    }\r
++    else\r
++    {\r
++      drawPanel(gg, av.startRes, av.endRes, av.startSeq, av.endSeq, 0);\r
++    }\r
++\r
++    g.drawImage(img, 0, 0, this);\r
++\r
++  }\r
++\r
++  int LABEL_WEST, LABEL_EAST;\r
++\r
++  public int getWrappedCanvasWidth(int cwidth)\r
++  {\r
++    cwidth -= cwidth % av.charWidth;\r
++\r
++    FontMetrics fm = getFontMetrics(av.getFont());\r
++\r
++    LABEL_EAST = 0;\r
++    LABEL_WEST = 0;\r
++\r
++    if (av.scaleRightWrapped)\r
++    {\r
++      LABEL_EAST = fm.stringWidth(getMask());\r
++    }\r
++\r
++    if (av.scaleLeftWrapped)\r
++    {\r
++      LABEL_WEST = fm.stringWidth(getMask());\r
++    }\r
++\r
++    return (cwidth - LABEL_EAST - LABEL_WEST) / av.charWidth;\r
++  }\r
++\r
++  /**\r
++   * Generates a string of zeroes.\r
++   * \r
++   * @return String\r
++   */\r
++  String getMask()\r
++  {\r
++    String mask = "0";\r
++    int maxWidth = 0;\r
++    int tmp;\r
++    AlignmentI alignment = av.getAlignment();\r
++    for (int i = 0; i < alignment.getHeight(); i++)\r
++    {\r
++      tmp = alignment.getSequenceAt(i).getEnd();\r
++      if (tmp > maxWidth)\r
++      {\r
++        maxWidth = tmp;\r
++      }\r
++    }\r
++\r
++    for (int i = maxWidth; i > 0; i /= 10)\r
++    {\r
++      mask += "0";\r
++    }\r
++    return mask;\r
++  }\r
++\r
++  public void drawWrappedPanel(Graphics g, int canvasWidth,\r
++          int canvasHeight, int startRes)\r
++  {\r
++    AlignmentI al = av.getAlignment();\r
++\r
++    FontMetrics fm = getFontMetrics(av.getFont());\r
++\r
++    if (av.scaleRightWrapped)\r
++    {\r
++      LABEL_EAST = fm.stringWidth(getMask());\r
++    }\r
++\r
++    if (av.scaleLeftWrapped)\r
++    {\r
++      LABEL_WEST = fm.stringWidth(getMask());\r
++    }\r
++\r
++    int hgap = av.charHeight;\r
++    if (av.scaleAboveWrapped)\r
++    {\r
++      hgap += av.charHeight;\r
++    }\r
++\r
++    int cWidth = (canvasWidth - LABEL_EAST - LABEL_WEST) / av.charWidth;\r
++    int cHeight = av.getAlignment().getHeight() * av.charHeight;\r
++\r
++    av.setWrappedWidth(cWidth);\r
++\r
++    av.endRes = av.startRes + cWidth;\r
++\r
++    int endx;\r
++    int ypos = hgap;\r
++\r
++    int maxwidth = av.getAlignment().getWidth() - 1;\r
++\r
++    if (av.hasHiddenColumns())\r
++    {\r
++      maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;\r
++    }\r
++\r
++    while ((ypos <= canvasHeight) && (startRes < maxwidth))\r
++    {\r
++      endx = startRes + cWidth - 1;\r
++\r
++      if (endx > maxwidth)\r
++      {\r
++        endx = maxwidth;\r
++      }\r
++\r
++      g.setColor(Color.black);\r
++\r
++      if (av.scaleLeftWrapped)\r
++      {\r
++        drawWestScale(g, startRes, endx, ypos);\r
++      }\r
++\r
++      if (av.scaleRightWrapped)\r
++      {\r
++        g.translate(canvasWidth - LABEL_EAST, 0);\r
++        drawEastScale(g, startRes, endx, ypos);\r
++        g.translate(-(canvasWidth - LABEL_EAST), 0);\r
++      }\r
++\r
++      g.translate(LABEL_WEST, 0);\r
++\r
++      if (av.scaleAboveWrapped)\r
++      {\r
++        drawNorthScale(g, startRes, endx, ypos);\r
++      }\r
++      if (av.hasHiddenColumns() && av.showHiddenMarkers)\r
++      {\r
++        g.setColor(Color.blue);\r
++        int res;\r
++        for (int i = 0; i < av.getColumnSelection().getHiddenColumns()\r
++                .size(); i++)\r
++        {\r
++          res = av.getColumnSelection().findHiddenRegionPosition(i)\r
++                  - startRes;\r
++\r
++          if (res < 0 || res > endx - startRes)\r
++          {\r
++            continue;\r
++          }\r
++\r
++          gg.fillPolygon(new int[]\r
++          { res * av.charWidth - av.charHeight / 4,\r
++              res * av.charWidth + av.charHeight / 4, res * av.charWidth },\r
++                  new int[]\r
++                  { ypos - (av.charHeight / 2), ypos - (av.charHeight / 2),\r
++                      ypos - (av.charHeight / 2) + 8 }, 3);\r
++\r
++        }\r
++      }\r
++\r
++      if (g.getClip() == null)\r
++      {\r
++        g.setClip(0, 0, cWidth * av.charWidth, canvasHeight);\r
++      }\r
++\r
++      drawPanel(g, startRes, endx, 0, al.getHeight(), ypos);\r
++      g.setClip(null);\r
++\r
++      if (av.showAnnotation)\r
++      {\r
++        g.translate(0, cHeight + ypos + 4);\r
++        if (annotations == null)\r
++        {\r
++          annotations = new AnnotationPanel(av);\r
++        }\r
++\r
++        annotations.drawComponent(g, startRes, endx + 1);\r
++        g.translate(0, -cHeight - ypos - 4);\r
++      }\r
++      g.translate(-LABEL_WEST, 0);\r
++\r
++      ypos += cHeight + getAnnotationHeight() + hgap;\r
++\r
++      startRes += cWidth;\r
++    }\r
++\r
++  }\r
++\r
++  AnnotationPanel annotations;\r
++\r
++  int getAnnotationHeight()\r
++  {\r
++    if (!av.showAnnotation)\r
++    {\r
++      return 0;\r
++    }\r
++\r
++    if (annotations == null)\r
++    {\r
++      annotations = new AnnotationPanel(av);\r
++    }\r
++\r
++    return annotations.adjustPanelHeight();\r
++  }\r
++\r
++  void drawPanel(Graphics g1, int startRes, int endRes, int startSeq,\r
++          int endSeq, int offset)\r
++  {\r
++\r
++\r
++    if (!av.hasHiddenColumns())\r
++    {\r
++      draw(g1, startRes, endRes, startSeq, endSeq, offset);\r
++    }\r
++    else\r
++    {\r
++\r
++      int screenY = 0;\r
++      int blockStart = startRes;\r
++      int blockEnd = endRes;\r
++\r
++      if (av.hasHiddenColumns())\r
++      {\r
++        for (int[] region : av.getColumnSelection().getHiddenColumns())\r
++        {\r
++          int hideStart = region[0];\r
++          int hideEnd = region[1];\r
++\r
++          if (hideStart <= blockStart)\r
++          {\r
++            blockStart += (hideEnd - hideStart) + 1;\r
++            continue;\r
++          }\r
++\r
++          blockEnd = hideStart - 1;\r
++\r
++          g1.translate(screenY * av.charWidth, 0);\r
++\r
++          draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);\r
++\r
++          if (av.getShowHiddenMarkers())\r
++          {\r
++            g1.setColor(Color.blue);\r
++            g1.drawLine((blockEnd - blockStart + 1) * av.charWidth - 1,\r
++                    0 + offset, (blockEnd - blockStart + 1) * av.charWidth\r
++                            - 1, (endSeq - startSeq) * av.charHeight\r
++                            + offset);\r
++          }\r
++\r
++          g1.translate(-screenY * av.charWidth, 0);\r
++          screenY += blockEnd - blockStart + 1;\r
++          blockStart = hideEnd + 1;\r
++        }\r
++      }\r
++      if (screenY <= (endRes - startRes))\r
++      {\r
++        blockEnd = blockStart + (endRes - startRes) - screenY;\r
++        g1.translate(screenY * av.charWidth, 0);\r
++        draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);\r
++\r
++        g1.translate(-screenY * av.charWidth, 0);\r
++      }\r
++    }\r
++\r
++  }\r
++\r
++  // int startRes, int endRes, int startSeq, int endSeq, int x, int y,\r
++  // int x1, int x2, int y1, int y2, int startx, int starty,\r
++  void draw(Graphics g, int startRes, int endRes, int startSeq, int endSeq,\r
++          int offset)\r
++  {\r
++    g.setFont(av.getFont());\r
++    sr.prepare(g, av.renderGaps);\r
++\r
++    SequenceI nextSeq;\r
++\r
++    // / First draw the sequences\r
++    // ///////////////////////////\r
++    for (int i = startSeq; i < endSeq; i++)\r
++    {\r
++      nextSeq = av.getAlignment().getSequenceAt(i);\r
++\r
++      if (nextSeq == null)\r
++      {\r
++        continue;\r
++      }\r
++\r
++      sr.drawSequence(nextSeq, av.getAlignment().findAllGroups(nextSeq),\r
++              startRes, endRes, offset + ((i - startSeq) * av.charHeight));\r
++\r
++      if (av.isShowSequenceFeatures())\r
++      {\r
++        fr.drawSequence(g, nextSeq, startRes, endRes, offset\r
++                + ((i - startSeq) * av.charHeight));\r
++      }\r
++\r
++      // / Highlight search Results once all sequences have been drawn\r
++      // ////////////////////////////////////////////////////////\r
++      if (searchResults != null)\r
++      {\r
++        int[] visibleResults = searchResults.getResults(nextSeq, startRes,\r
++                endRes);\r
++        if (visibleResults != null)\r
++        {\r
++          for (int r = 0; r < visibleResults.length; r += 2)\r
++          {\r
++            sr.drawHighlightedText(nextSeq, visibleResults[r],\r
++                    visibleResults[r + 1], (visibleResults[r] - startRes)\r
++                            * av.charWidth, offset\r
++                            + ((i - startSeq) * av.charHeight));\r
++          }\r
++        }\r
++      }\r
++\r
++      if (av.cursorMode && cursorY == i && cursorX >= startRes\r
++              && cursorX <= endRes)\r
++      {\r
++        sr.drawCursor(nextSeq, cursorX,\r
++                (cursorX - startRes) * av.charWidth, offset\r
++                        + ((i - startSeq) * av.charHeight));\r
++      }\r
++    }\r
++\r
++    if (av.getSelectionGroup() != null\r
++            || av.getAlignment().getGroups().size() > 0)\r
++    {\r
++      drawGroupsBoundaries(g, startRes, endRes, startSeq, endSeq, offset);\r
++    }\r
++\r
++  }\r
++\r
++  void drawGroupsBoundaries(Graphics g, int startRes, int endRes,\r
++          int startSeq, int endSeq, int offset)\r
++  {\r
++    //\r
++    // ///////////////////////////////////\r
++    // Now outline any areas if necessary\r
++    // ///////////////////////////////////\r
++    SequenceGroup group = av.getSelectionGroup();\r
++\r
++    int sx = -1;\r
++    int sy = -1;\r
++    int ex = -1;\r
++    int groupIndex = -1;\r
++\r
++    if ((group == null) && (av.getAlignment().getGroups().size() > 0))\r
++    {\r
++      group = av.getAlignment().getGroups().get(0);\r
++      groupIndex = 0;\r
++    }\r
++\r
++    if (group != null)\r
++    {\r
++      do\r
++      {\r
++        int oldY = -1;\r
++        int i = 0;\r
++        boolean inGroup = false;\r
++        int top = -1;\r
++        int bottom = -1;\r
++        int alHeight = av.getAlignment().getHeight() - 1;\r
++\r
++        for (i = startSeq; i < endSeq; i++)\r
++        {\r
++          sx = (group.getStartRes() - startRes) * av.charWidth;\r
++          sy = offset + ((i - startSeq) * av.charHeight);\r
++          ex = (((group.getEndRes() + 1) - group.getStartRes()) * av.charWidth) - 1;\r
++\r
++          if (sx + ex < 0 || sx > imgWidth)\r
++          {\r
++            continue;\r
++          }\r
++\r
++          if ((sx <= (endRes - startRes) * av.charWidth)\r
++                  && group.getSequences(null).contains(\r
++                          av.getAlignment().getSequenceAt(i)))\r
++          {\r
++            if ((bottom == -1)\r
++                    && (i >= alHeight || !group.getSequences(null)\r
++                            .contains(\r
++                                    av.getAlignment().getSequenceAt(i + 1))))\r
++            {\r
++              bottom = sy + av.charHeight;\r
++            }\r
++\r
++            if (!inGroup)\r
++            {\r
++              if (((top == -1) && (i == 0))\r
++                      || !group.getSequences(null).contains(\r
++                              av.getAlignment().getSequenceAt(i - 1)))\r
++              {\r
++                top = sy;\r
++              }\r
++\r
++              oldY = sy;\r
++              inGroup = true;\r
++\r
++              if (group == av.getSelectionGroup())\r
++              {\r
++                g.setColor(Color.red);\r
++              }\r
++              else\r
++              {\r
++                g.setColor(group.getOutlineColour());\r
++              }\r
++            }\r
++          }\r
++          else\r
++          {\r
++            if (inGroup)\r
++            {\r
++              if (sx >= 0 && sx < imgWidth)\r
++              {\r
++                g.drawLine(sx, oldY, sx, sy);\r
++              }\r
++\r
++              if (sx + ex < imgWidth)\r
++              {\r
++                g.drawLine(sx + ex, oldY, sx + ex, sy);\r
++              }\r
++\r
++              if (sx < 0)\r
++              {\r
++                ex += sx;\r
++                sx = 0;\r
++              }\r
++\r
++              if (sx + ex > imgWidth)\r
++              {\r
++                ex = imgWidth;\r
++              }\r
++\r
++              else if (sx + ex >= (endRes - startRes + 1) * av.charWidth)\r
++              {\r
++                ex = (endRes - startRes + 1) * av.charWidth;\r
++              }\r
++\r
++              if (top != -1)\r
++              {\r
++                g.drawLine(sx, top, sx + ex, top);\r
++                top = -1;\r
++              }\r
++\r
++              if (bottom != -1)\r
++              {\r
++                g.drawLine(sx, bottom, sx + ex, bottom);\r
++                bottom = -1;\r
++              }\r
++\r
++              inGroup = false;\r
++            }\r
++          }\r
++        }\r
++\r
++        if (inGroup)\r
++        {\r
++          sy = offset + ((i - startSeq) * av.charHeight);\r
++          if (sx >= 0 && sx < imgWidth)\r
++          {\r
++            g.drawLine(sx, oldY, sx, sy);\r
++          }\r
++\r
++          if (sx + ex < imgWidth)\r
++          {\r
++            g.drawLine(sx + ex, oldY, sx + ex, sy);\r
++          }\r
++\r
++          if (sx < 0)\r
++          {\r
++            ex += sx;\r
++            sx = 0;\r
++          }\r
++\r
++          if (sx + ex > imgWidth)\r
++          {\r
++            ex = imgWidth;\r
++          }\r
++          else if (sx + ex >= (endRes - startRes + 1) * av.charWidth)\r
++          {\r
++            ex = (endRes - startRes + 1) * av.charWidth;\r
++          }\r
++\r
++          if (top != -1)\r
++          {\r
++            g.drawLine(sx, top, sx + ex, top);\r
++            top = -1;\r
++          }\r
++\r
++          if (bottom != -1)\r
++          {\r
++            g.drawLine(sx, bottom - 1, sx + ex, bottom - 1);\r
++            bottom = -1;\r
++          }\r
++\r
++          inGroup = false;\r
++        }\r
++\r
++        groupIndex++;\r
++\r
++        if (groupIndex >= av.getAlignment().getGroups().size())\r
++        {\r
++          break;\r
++        }\r
++\r
++        group = av.getAlignment().getGroups()\r
++                .get(groupIndex);\r
++      } while (groupIndex < av.getAlignment().getGroups().size());\r
++\r
++    }\r
++  }\r
++\r
++  public void highlightSearchResults(SearchResults results)\r
++  {\r
++    searchResults = results;\r
++\r
++    repaint();\r
++  }\r
++\r
++}\r
  package jalview.datamodel;
  
  import jalview.util.ShiftList;
+ import jalview.viewmodel.annotationfilter.AnnotationFilterParameter;
+ import jalview.viewmodel.annotationfilter.AnnotationFilterParameter.SearchableAnnotationField;
  
  import java.util.ArrayList;
++import java.util.Arrays;
  import java.util.Enumeration;
  import java.util.List;
  import java.util.Vector;
@@@ -477,16 -479,16 +480,13 @@@ public class ColumnSelectio
    }
  
    /**
--   * This Method is used to return all the HiddenColumn regions less than the
--   * given index.
--   * 
--   * @param end
--   *          int
--   * @return Vector
++   * This Method is used to return all the HiddenColumn regions
++   * @return empty list or List of hidden column intervals
     */
 -  public Vector getHiddenColumns()
 +  public List<int[]> getHiddenColumns()
    {
--    return hiddenColumns;
++    return hiddenColumns == null ? Arrays.asList(new int[]
++    {}) : hiddenColumns;
    }
  
    /**
      }
    }
  
 +  /**
 +   * 
 +   * @return true if there are columns marked
 +   */
 +  public boolean hasSelectedColumns()
 +  {
 +    return (selected != null && selected.size() > 0);
 +  }
 +
 +  /**
 +   * 
 +   * @return true if there are columns hidden
 +   */
 +  public boolean hasHiddenColumns()
 +  {
 +    return hiddenColumns != null && hiddenColumns.size() > 0;
 +  }
++  
++  /**
++   * 
++   * @return true if there are more than one set of columns hidden
++   */
++  public boolean hasManyHiddenColumns()
++  {
++    return hiddenColumns != null && hiddenColumns.size() > 1;
++  }
 +
 +  /**
 +   * mark the columns corresponding to gap characters as hidden in the column
 +   * selection
 +   * 
 +   * @param sr
 +   */
 +  public void hideInsertionsFor(SequenceI sr)
 +  {
 +    List<int[]> inserts = sr.getInsertions();
 +    for (int[] r : inserts)
 +    {
 +      hideColumns(r[0], r[1]);
 +    }
 +  }
++  
+   public boolean filterAnnotations(Annotation[] annotations,
+           AnnotationFilterParameter filterParams)
+   {
+     this.revealAllHiddenColumns();
+     this.clear();
+     int count = 0;
+     do
+     {
+       if (annotations[count] != null)
+       {
+         boolean itemMatched = false;
+         if (filterParams.getThresholdType() == AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD
+                 && annotations[count].value >= filterParams
+                         .getThresholdValue())
+         {
+           itemMatched = true;
+         }
+         if (filterParams.getThresholdType() == AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD
+                 && annotations[count].value <= filterParams
+                         .getThresholdValue())
+         {
+           itemMatched = true;
+         }
+         if (filterParams.isFilterAlphaHelix()
+                 && annotations[count].secondaryStructure == 'H')
+         {
+           itemMatched = true;
+         }
+         if (filterParams.isFilterBetaSheet()
+                 && annotations[count].secondaryStructure == 'E')
+         {
+           itemMatched = true;
+         }
+         if (filterParams.isFilterTurn()
+                 && annotations[count].secondaryStructure == 'S')
+         {
+           itemMatched = true;
+         }
+         String regexSearchString = filterParams.getRegexString();
+         if (regexSearchString != null
+                 && !filterParams.getRegexSearchFields().isEmpty())
+         {
+           List<SearchableAnnotationField> fields = filterParams
+                   .getRegexSearchFields();
+           try
+           {
+             if (fields.contains(SearchableAnnotationField.DISPLAY_STRING)
+                     && annotations[count].displayCharacter
+                             .matches(regexSearchString))
+             {
+               itemMatched = true;
+             }
+           } catch (java.util.regex.PatternSyntaxException pse)
+           {
+             if (annotations[count].displayCharacter
+                     .equals(regexSearchString))
+             {
+               itemMatched = true;
+             }
+           }
+           if (fields.contains(SearchableAnnotationField.DESCRIPTION)
+                   && annotations[count].description != null
+                   && annotations[count].description
+                           .matches(regexSearchString))
+           {
+             itemMatched = true;
+           }
+         }
+         if (itemMatched)
+         {
+           this.addElement(count);
+         }
+       }
+       count++;
+     } while (count < annotations.length);
+     return false;
+   }
  }