2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.datamodel.AlignmentI;
24 import jalview.datamodel.HiddenColumns;
25 import jalview.datamodel.SearchResultsI;
26 import jalview.datamodel.SequenceGroup;
27 import jalview.datamodel.SequenceI;
28 import jalview.renderer.ScaleRenderer;
29 import jalview.renderer.ScaleRenderer.ScaleMark;
30 import jalview.viewmodel.ViewportListenerI;
31 import jalview.viewmodel.ViewportRanges;
33 import java.awt.AlphaComposite;
34 import java.awt.BasicStroke;
35 import java.awt.BorderLayout;
36 import java.awt.Color;
37 import java.awt.FontMetrics;
38 import java.awt.Graphics;
39 import java.awt.Graphics2D;
40 import java.awt.RenderingHints;
41 import java.awt.Shape;
42 import java.awt.image.BufferedImage;
43 import java.beans.PropertyChangeEvent;
44 import java.util.List;
46 import javax.swing.JComponent;
54 public class SeqCanvas extends JComponent implements ViewportListenerI
56 final FeatureRenderer fr;
58 final SequenceRenderer seqRdr;
66 boolean fastPaint = false;
80 boolean fastpainting = false;
82 AnnotationPanel annotations;
85 * Creates a new SeqCanvas object.
90 public SeqCanvas(AlignmentPanel ap)
94 fr = new FeatureRenderer(ap);
95 seqRdr = new SequenceRenderer(av);
96 setLayout(new BorderLayout());
97 PaintRefresher.Register(this, av.getSequenceSetId());
98 setBackground(Color.white);
100 av.getRanges().addPropertyChangeListener(this);
103 public SequenceRenderer getSequenceRenderer()
108 public FeatureRenderer getFeatureRenderer()
113 private void updateViewport()
115 charHeight = av.getCharHeight();
116 charWidth = av.getCharWidth();
131 private void drawNorthScale(Graphics g, int startx, int endx, int ypos)
134 for (ScaleMark mark : new ScaleRenderer().calculateMarks(av, startx,
137 int mpos = mark.column; // (i - startx - 1)
142 String mstring = mark.text;
148 g.drawString(mstring, mpos * charWidth, ypos - (charHeight / 2));
150 g.drawLine((mpos * charWidth) + (charWidth / 2), (ypos + 2)
151 - (charHeight / 2), (mpos * charWidth) + (charWidth / 2),
169 void drawWestScale(Graphics g, int startx, int endx, int ypos)
171 FontMetrics fm = getFontMetrics(av.getFont());
174 if (av.hasHiddenColumns())
176 startx = av.getAlignment().getHiddenColumns()
177 .adjustForHiddenColumns(startx);
178 endx = av.getAlignment().getHiddenColumns()
179 .adjustForHiddenColumns(endx);
182 int maxwidth = av.getAlignment().getWidth();
183 if (av.hasHiddenColumns())
185 maxwidth = av.getAlignment().getHiddenColumns()
186 .findColumnPosition(maxwidth) - 1;
190 for (int i = 0; i < av.getAlignment().getHeight(); i++)
192 SequenceI seq = av.getAlignment().getSequenceAt(i);
198 if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
205 value = av.getAlignment().getSequenceAt(i).findPosition(index);
212 int x = LABEL_WEST - fm.stringWidth(String.valueOf(value))
214 g.drawString(value + "", x, (ypos + (i * charHeight))
232 void drawEastScale(Graphics g, int startx, int endx, int ypos)
236 if (av.hasHiddenColumns())
238 endx = av.getAlignment().getHiddenColumns()
239 .adjustForHiddenColumns(endx);
244 for (int i = 0; i < av.getAlignment().getHeight(); i++)
246 seq = av.getAlignment().getSequenceAt(i);
250 while (index > startx)
252 if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
259 value = seq.findPosition(index);
266 g.drawString(String.valueOf(value), 0, (ypos + (i * charHeight))
274 * need to make this thread safe move alignment rendering in response to
280 * shift up or down in repaint
282 public void fastPaint(int horizontal, int vertical)
284 if (fastpainting || gg == null)
292 ViewportRanges ranges = av.getRanges();
293 int sr = ranges.getStartRes();
294 int er = ranges.getEndRes();
295 int ss = ranges.getStartSeq();
296 int es = ranges.getEndSeq();
300 gg.copyArea(horizontal * charWidth, vertical * charHeight,
301 img.getWidth(), img.getHeight(), -horizontal * charWidth,
302 -vertical * charHeight);
304 if (horizontal > 0) // scrollbar pulled right, image to the left
306 transX = (er - sr - horizontal) * charWidth;
307 sr = er - horizontal;
309 else if (horizontal < 0)
311 er = sr - horizontal;
313 else if (vertical > 0) // scroll down
317 if (ss < ranges.getStartSeq())
318 { // ie scrolling too fast, more than a page at a time
319 ss = ranges.getStartSeq();
323 transY = img.getHeight() - ((vertical + 1) * charHeight);
326 else if (vertical < 0)
330 if (es > ranges.getEndSeq())
332 es = ranges.getEndSeq();
336 gg.translate(transX, transY);
337 drawPanel(gg, sr, er, ss, es, 0);
338 gg.translate(-transX, -transY);
341 fastpainting = false;
345 * Definitions of startx and endx (hopefully): SMJS This is what I'm working
346 * towards! startx is the first residue (starting at 0) to display. endx is
347 * the last residue to display (starting at 0). starty is the first sequence
348 * to display (starting at 0). endy is the last sequence to display (starting
349 * at 0). NOTE 1: The av limits are set in setFont in this class and in the
350 * adjustment listener in SeqPanel when the scrollbars move.
353 // Set this to false to force a full panel paint
355 public void paintComponent(Graphics g)
357 super.paintComponent(g);
361 ViewportRanges ranges = av.getRanges();
363 int width = getWidth();
364 int height = getHeight();
366 width -= (width % charWidth);
367 height -= (height % charHeight);
369 // selectImage is the selection group outline image
370 BufferedImage selectImage = drawSelectionGroup(
371 ranges.getStartRes(), ranges.getEndRes(),
372 ranges.getStartSeq(), ranges.getEndSeq());
374 if (fastPaint || (getVisibleRect().width != g.getClipBounds().width)
375 || (getVisibleRect().height != g.getClipBounds().height))
377 BufferedImage lcimg = buildLocalImage(selectImage);
378 g.drawImage(lcimg, 0, 0, this);
381 else if ((width > 0) && (height > 0))
383 // img is a cached version of the last view we drew, if any
384 // if we have no img or the size has changed, make a new one
385 if (img == null || width != img.getWidth()
386 || height != img.getHeight())
393 gg = (Graphics2D) img.getGraphics();
394 gg.setFont(av.getFont());
399 gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
400 RenderingHints.VALUE_ANTIALIAS_ON);
403 gg.setColor(Color.white);
404 gg.fillRect(0, 0, img.getWidth(), img.getHeight());
406 if (av.getWrapAlignment())
408 drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes());
412 drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(),
413 ranges.getStartSeq(), ranges.getEndSeq(), 0);
416 // lcimg is a local *copy* of img which we'll draw selectImage on top of
417 BufferedImage lcimg = buildLocalImage(selectImage);
418 g.drawImage(lcimg, 0, 0, this);
423 * Make a local image by combining the cached image img
426 private BufferedImage buildLocalImage(BufferedImage selectImage)
428 // clone the cached image
429 BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
431 Graphics2D g2d = lcimg.createGraphics();
432 g2d.drawImage(img, 0, 0, null);
434 // overlay selection group on lcimg
435 if (selectImage != null)
438 AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
439 g2d.drawImage(selectImage, 0, 0, this);
446 private void paintSeqGroup()
452 private BufferedImage setupImage()
454 BufferedImage lcimg = null;
456 int width = getWidth();
457 int height = getHeight();
459 width -= (width % charWidth);
460 height -= (height % charHeight);
462 if ((width < 1) || (height < 1))
469 lcimg = new BufferedImage(width, height,
470 BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
471 } catch (OutOfMemoryError er)
475 "Selection Group image OutOfMemory Redraw Error.\n" + er);
476 new OOMWarning("Creating alignment image for display", er);
490 * @return DOCUMENT ME!
492 public int getWrappedCanvasWidth(int cwidth)
494 FontMetrics fm = getFontMetrics(av.getFont());
499 if (av.getScaleRightWrapped())
501 LABEL_EAST = fm.stringWidth(getMask());
504 if (av.getScaleLeftWrapped())
506 LABEL_WEST = fm.stringWidth(getMask());
509 return (cwidth - LABEL_EAST - LABEL_WEST) / charWidth;
513 * Generates a string of zeroes.
522 for (int i = 0; i < av.getAlignment().getHeight(); i++)
524 tmp = av.getAlignment().getSequenceAt(i).getEnd();
531 for (int i = maxWidth; i > 0; i /= 10)
545 * @param canvasHeight
550 public void drawWrappedPanel(Graphics g, int canvasWidth,
551 int canvasHeight, int startRes)
554 AlignmentI al = av.getAlignment();
556 FontMetrics fm = getFontMetrics(av.getFont());
561 if (av.getScaleRightWrapped())
563 LABEL_EAST = fm.stringWidth(getMask());
566 if (av.getScaleLeftWrapped())
568 LABEL_WEST = fm.stringWidth(getMask());
571 int hgap = charHeight;
572 if (av.getScaleAboveWrapped())
577 int cWidth = (canvasWidth - LABEL_EAST - LABEL_WEST) / charWidth;
578 int cHeight = av.getAlignment().getHeight() * charHeight;
580 av.setWrappedWidth(cWidth);
582 av.getRanges().setViewportStartAndWidth(startRes, cWidth);
586 int maxwidth = av.getAlignment().getWidth();
588 if (av.hasHiddenColumns())
590 maxwidth = av.getAlignment().getHiddenColumns()
591 .findColumnPosition(maxwidth);
594 while ((ypos <= canvasHeight) && (startRes < maxwidth))
596 endx = startRes + cWidth - 1;
603 g.setFont(av.getFont());
604 g.setColor(Color.black);
606 if (av.getScaleLeftWrapped())
608 drawWestScale(g, startRes, endx, ypos);
611 if (av.getScaleRightWrapped())
613 g.translate(canvasWidth - LABEL_EAST, 0);
614 drawEastScale(g, startRes, endx, ypos);
615 g.translate(-(canvasWidth - LABEL_EAST), 0);
618 g.translate(LABEL_WEST, 0);
620 if (av.getScaleAboveWrapped())
622 drawNorthScale(g, startRes, endx, ypos);
625 if (av.hasHiddenColumns() && av.getShowHiddenMarkers())
627 g.setColor(Color.blue);
629 HiddenColumns hidden = av.getAlignment().getHiddenColumns();
630 List<Integer> positions = hidden.findHiddenRegionPositions();
631 for (int pos : positions)
633 res = pos - startRes;
635 if (res < 0 || res > endx - startRes)
641 new int[] { res * charWidth - charHeight / 4,
642 res * charWidth + charHeight / 4, res * charWidth },
643 new int[] { ypos - (charHeight / 2),
644 ypos - (charHeight / 2), ypos - (charHeight / 2) + 8 },
650 // When printing we have an extra clipped region,
651 // the Printable page which we need to account for here
652 Shape clip = g.getClip();
656 g.setClip(0, 0, cWidth * charWidth, canvasHeight);
660 g.setClip(0, (int) clip.getBounds().getY(), cWidth * charWidth,
661 (int) clip.getBounds().getHeight());
664 drawPanel(g, startRes, endx, 0, al.getHeight() - 1, ypos);
666 if (av.isShowAnnotation())
668 g.translate(0, cHeight + ypos + 3);
669 if (annotations == null)
671 annotations = new AnnotationPanel(av);
674 annotations.renderer.drawComponent(annotations, av, g, -1,
676 g.translate(0, -cHeight - ypos - 3);
679 g.translate(-LABEL_WEST, 0);
681 ypos += cHeight + getAnnotationHeight() + hgap;
688 * Draw a selection group over a wrapped alignment
690 private void drawWrappedSelection(Graphics2D g, SequenceGroup group,
692 int canvasHeight, int startRes)
694 // height gap above each panel
695 int hgap = charHeight;
696 if (av.getScaleAboveWrapped())
701 int cWidth = (canvasWidth - LABEL_EAST - LABEL_WEST) / charWidth;
702 int cHeight = av.getAlignment().getHeight() * charHeight;
704 int startx = startRes;
706 int ypos = hgap; // vertical offset
707 int maxwidth = av.getAlignment().getWidth();
709 if (av.hasHiddenColumns())
711 maxwidth = av.getAlignment().getHiddenColumns()
712 .findColumnPosition(maxwidth);
715 // chop the wrapped alignment extent up into panel-sized blocks and treat
716 // each block as if it were a block from an unwrapped alignment
717 while ((ypos <= canvasHeight) && (startx < maxwidth))
719 // set end value to be start + width, or maxwidth, whichever is smaller
720 endx = startx + cWidth - 1;
727 g.translate(LABEL_WEST, 0);
729 drawUnwrappedSelection(g, group, startx, endx, 0,
730 av.getAlignment().getHeight() - 1,
733 g.translate(-LABEL_WEST, 0);
735 // update vertical offset
736 ypos += cHeight + getAnnotationHeight() + hgap;
738 // update horizontal offset
743 int getAnnotationHeight()
745 if (!av.isShowAnnotation())
750 if (annotations == null)
752 annotations = new AnnotationPanel(av);
755 return annotations.adjustPanelHeight();
774 public void drawPanel(Graphics g1, int startRes, int endRes,
775 int startSeq, int endSeq, int offset)
778 if (!av.hasHiddenColumns())
780 draw(g1, startRes, endRes, startSeq, endSeq, offset);
785 int blockStart = startRes;
786 int blockEnd = endRes;
788 for (int[] region : av.getAlignment().getHiddenColumns()
789 .getHiddenColumnsCopy())
791 int hideStart = region[0];
792 int hideEnd = region[1];
794 if (hideStart <= blockStart)
796 blockStart += (hideEnd - hideStart) + 1;
800 blockEnd = hideStart - 1;
802 g1.translate(screenY * charWidth, 0);
804 draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
806 if (av.getShowHiddenMarkers())
808 g1.setColor(Color.blue);
810 g1.drawLine((blockEnd - blockStart + 1) * charWidth - 1,
811 0 + offset, (blockEnd - blockStart + 1) * charWidth - 1,
812 (endSeq - startSeq + 1) * charHeight + offset);
815 g1.translate(-screenY * charWidth, 0);
816 screenY += blockEnd - blockStart + 1;
817 blockStart = hideEnd + 1;
819 if (screenY > (endRes - startRes))
821 // already rendered last block
826 if (screenY <= (endRes - startRes))
828 // remaining visible region to render
829 blockEnd = blockStart + (endRes - startRes) - screenY;
830 g1.translate(screenY * charWidth, 0);
831 draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
833 g1.translate(-screenY * charWidth, 0);
839 private void draw(Graphics g, int startRes, int endRes, int startSeq,
840 int endSeq, int offset)
842 g.setFont(av.getFont());
843 seqRdr.prepare(g, av.isRenderGaps());
847 // / First draw the sequences
848 // ///////////////////////////
849 for (int i = startSeq; i <= endSeq; i++)
851 nextSeq = av.getAlignment().getSequenceAt(i);
854 // occasionally, a race condition occurs such that the alignment row is
858 seqRdr.drawSequence(nextSeq, av.getAlignment().findAllGroups(nextSeq),
859 startRes, endRes, offset + ((i - startSeq) * charHeight));
861 if (av.isShowSequenceFeatures())
863 fr.drawSequence(g, nextSeq, startRes, endRes, offset
864 + ((i - startSeq) * charHeight), false);
867 // / Highlight search Results once all sequences have been drawn
868 // ////////////////////////////////////////////////////////
869 if (av.hasSearchResults())
871 int[] visibleResults = av.getSearchResults().getResults(nextSeq,
873 if (visibleResults != null)
875 for (int r = 0; r < visibleResults.length; r += 2)
877 seqRdr.drawHighlightedText(nextSeq, visibleResults[r],
878 visibleResults[r + 1], (visibleResults[r] - startRes)
880 + ((i - startSeq) * charHeight));
885 if (av.cursorMode && cursorY == i && cursorX >= startRes
886 && cursorX <= endRes)
888 seqRdr.drawCursor(nextSeq, cursorX, (cursorX - startRes) * charWidth,
889 offset + ((i - startSeq) * charHeight));
893 if (av.getSelectionGroup() != null
894 || av.getAlignment().getGroups().size() > 0)
896 drawGroupsBoundaries(g, startRes, endRes, startSeq, endSeq, offset);
901 void drawGroupsBoundaries(Graphics g1, int startRes, int endRes,
902 int startSeq, int endSeq, int offset)
904 Graphics2D g = (Graphics2D) g1;
906 // ///////////////////////////////////
907 // Now outline any areas if necessary
908 // ///////////////////////////////////
910 SequenceGroup group = null;
913 if (av.getAlignment().getGroups().size() > 0)
915 group = av.getAlignment().getGroups().get(0);
921 g.setStroke(new BasicStroke());
922 g.setColor(group.getOutlineColour());
926 drawPartialGroupOutline(g, group, startRes, endRes, startSeq,
931 g.setStroke(new BasicStroke());
933 if (groupIndex >= av.getAlignment().getGroups().size())
938 group = av.getAlignment().getGroups().get(groupIndex);
940 } while (groupIndex < av.getAlignment().getGroups().size());
948 * Draw the selection group as a separate image and overlay
950 private BufferedImage drawSelectionGroup(int startRes, int endRes,
951 int startSeq, int endSeq)
953 // get a new image of the correct size
954 BufferedImage selectionImage = setupImage();
956 if (selectionImage == null)
961 SequenceGroup group = av.getSelectionGroup();
968 // set up drawing colour
969 Graphics2D g = (Graphics2D) selectionImage.getGraphics();
971 // set background to transparent
972 g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
973 g.fillRect(0, 0, selectionImage.getWidth(), selectionImage.getHeight());
975 // set up foreground to draw red dashed line
976 g.setComposite(AlphaComposite.Src);
977 g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
978 BasicStroke.JOIN_ROUND, 3f, new float[]
980 g.setColor(Color.RED);
982 if (!av.getWrapAlignment())
984 drawUnwrappedSelection(g, group, startRes, endRes, startSeq, endSeq,
989 drawWrappedSelection(g, group, getWidth(), getHeight(),
990 av.getRanges().getStartRes());
994 return selectionImage;
998 * Draw a selection group over an unwrapped alignment
999 * @param g graphics object to draw with
1000 * @param group selection group
1001 * @param startRes start residue of area to draw
1002 * @param endRes end residue of area to draw
1003 * @param startSeq start sequence of area to draw
1004 * @param endSeq end sequence of area to draw
1005 * @param offset vertical offset (used when called from wrapped alignment code)
1007 private void drawUnwrappedSelection(Graphics2D g, SequenceGroup group,
1008 int startRes, int endRes, int startSeq, int endSeq, int offset)
1010 if (!av.hasHiddenColumns())
1012 drawPartialGroupOutline(g, group, startRes, endRes, startSeq, endSeq,
1017 // package into blocks of visible columns
1019 int blockStart = startRes;
1020 int blockEnd = endRes;
1022 for (int[] region : av.getAlignment().getHiddenColumns()
1023 .getHiddenColumnsCopy())
1025 int hideStart = region[0];
1026 int hideEnd = region[1];
1028 if (hideStart <= blockStart)
1030 blockStart += (hideEnd - hideStart) + 1;
1034 blockEnd = hideStart - 1;
1036 g.translate(screenY * charWidth, 0);
1037 drawPartialGroupOutline(g, group,
1038 blockStart, blockEnd, startSeq, endSeq, offset);
1040 g.translate(-screenY * charWidth, 0);
1041 screenY += blockEnd - blockStart + 1;
1042 blockStart = hideEnd + 1;
1044 if (screenY > (endRes - startRes))
1046 // already rendered last block
1051 if (screenY <= (endRes - startRes))
1053 // remaining visible region to render
1054 blockEnd = blockStart + (endRes - startRes) - screenY;
1055 g.translate(screenY * charWidth, 0);
1056 drawPartialGroupOutline(g, group,
1057 blockStart, blockEnd, startSeq, endSeq, offset);
1059 g.translate(-screenY * charWidth, 0);
1065 * Draw the selection group as a separate image and overlay
1067 private void drawPartialGroupOutline(Graphics2D g, SequenceGroup group,
1068 int startRes, int endRes, int startSeq, int endSeq,
1071 int visWidth = (endRes - startRes + 1) * charWidth;
1075 boolean inGroup = false;
1083 for (i = startSeq; i <= endSeq; i++)
1085 // position of start residue of group relative to startRes, in pixels
1086 sx = (group.getStartRes() - startRes) * charWidth;
1088 // width of group in pixels
1089 xwidth = (((group.getEndRes() + 1) - group.getStartRes()) * charWidth)
1092 sy = verticalOffset + (i - startSeq) * charHeight;
1094 if (sx + xwidth < 0 || sx > visWidth)
1099 if ((sx <= (endRes - startRes) * charWidth)
1100 && group.getSequences(null)
1101 .contains(av.getAlignment().getSequenceAt(i)))
1103 if ((bottom == -1) && !group.getSequences(null)
1104 .contains(av.getAlignment().getSequenceAt(i + 1)))
1106 bottom = sy + charHeight;
1111 if (((top == -1) && (i == 0)) || !group.getSequences(null)
1112 .contains(av.getAlignment().getSequenceAt(i - 1)))
1125 // if start position is visible, draw vertical line to left of
1127 if (sx >= 0 && sx < visWidth)
1129 g.drawLine(sx, oldY, sx, sy);
1132 // if end position is visible, draw vertical line to right of
1134 if (sx + xwidth < visWidth)
1136 g.drawLine(sx + xwidth, oldY, sx + xwidth, sy);
1145 if (sx + xwidth >= (endRes - startRes + 1) * charWidth)
1147 xwidth = (endRes - startRes + 1) * charWidth - sx;
1150 // draw horizontal line at top of group
1153 g.drawLine(sx, top, sx + xwidth, top);
1157 // draw horizontal line at bottom of group
1160 g.drawLine(sx, bottom, sx + xwidth, bottom);
1171 sy = verticalOffset + ((i - startSeq) * charHeight);
1172 if (sx >= 0 && sx < visWidth)
1174 g.drawLine(sx, oldY, sx, sy);
1177 if (sx + xwidth < visWidth)
1179 g.drawLine(sx + xwidth, oldY, sx + xwidth, sy);
1188 if (sx + xwidth > visWidth)
1192 else if (sx + xwidth >= (endRes - startRes + 1) * charWidth)
1194 xwidth = (endRes - startRes + 1) * charWidth;
1199 g.drawLine(sx, top, sx + xwidth, top);
1205 g.drawLine(sx, bottom - 1, sx + xwidth, bottom - 1);
1219 public void highlightSearchResults(SearchResultsI results)
1223 av.setSearchResults(results);
1229 public void propertyChange(PropertyChangeEvent evt)
1231 String eventName = evt.getPropertyName();
1233 if (eventName.equals(SequenceGroup.SEQ_GROUP_CHANGED))
1237 else if (av.getWrapAlignment())
1239 if (eventName.equals(ViewportRanges.STARTRES))
1247 if (eventName.equals(ViewportRanges.STARTRES))
1249 // Make sure we're not trying to draw a panel
1250 // larger than the visible window
1251 ViewportRanges vpRanges = av.getRanges();
1252 scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
1253 int range = vpRanges.getEndRes() - vpRanges.getStartRes();
1254 if (scrollX > range)
1258 else if (scrollX < -range)
1264 // Both scrolling and resizing change viewport ranges: scrolling changes
1265 // both start and end points, but resize only changes end values.
1266 // Here we only want to fastpaint on a scroll, with resize using a normal
1267 // paint, so scroll events are identified as changes to the horizontal or
1268 // vertical start value.
1269 if (eventName.equals(ViewportRanges.STARTRES))
1271 // scroll - startres and endres both change
1272 fastPaint(scrollX, 0);
1274 else if (eventName.equals(ViewportRanges.STARTSEQ))
1277 fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());