From 461d9cd18036c268ae890fcf2418e9ac181b3c61 Mon Sep 17 00:00:00 2001 From: BobHanson Date: Tue, 2 Jun 2020 18:23:42 -0500 Subject: [PATCH] JAL-3446 JAL-3401 from JAL-3253 HoldRepaint and SeqCanvas sizing issues. - integrated changes from 0b573ed (gmungoc) --- src/jalview/gui/AlignmentPanel.java | 21 +- src/jalview/gui/IdCanvas.java | 81 +++- src/jalview/gui/PaintRefresher.java | 4 +- src/jalview/gui/SeqCanvas.java | 466 ++++++++++++-------- src/jalview/gui/SeqPanel.java | 3 +- test/jalview/gui/SeqCanvasTest.java | 83 ++-- test/jalview/ws/PDBSequenceFetcherTest.java | 2 +- test/jalview/ws/jabaws/JalviewJabawsTestUtils.java | 4 +- 8 files changed, 414 insertions(+), 250 deletions(-) diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java index 2b6d5a0..91b773e 100644 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@ -1068,8 +1068,7 @@ public class AlignmentPanel extends GAlignmentPanel implements public int printWrappedAlignment(int pageWidth, int pageHeight, int pageNumber, Graphics g) throws PrinterException { - getSeqPanel().seqCanvas.calculateWrappedGeometry(getWidth(), - getHeight()); + getSeqPanel().seqCanvas.calculateWrappedGeometry(); int annotationHeight = 0; if (av.isShowAnnotation()) { @@ -1856,19 +1855,29 @@ public class AlignmentPanel extends GAlignmentPanel implements private boolean holdRepaint = false; + /** + * Called by IdCanvas and SeqPanel to defer painting until after JVP loading. + * + * @return true if holding + */ public boolean getHoldRepaint() { return holdRepaint; } - public void setHoldRepaint(boolean b) + /** + * Called by Jalview2xml while loading + * + * @param tf + */ + public void setHoldRepaint(boolean tf) { - if (holdRepaint == b) + if (holdRepaint == tf) { return; } - holdRepaint = b; - if (!b) + holdRepaint = tf; + if (!tf) { repaint(); } diff --git a/src/jalview/gui/IdCanvas.java b/src/jalview/gui/IdCanvas.java index 10c0787..14ae033 100755 --- a/src/jalview/gui/IdCanvas.java +++ b/src/jalview/gui/IdCanvas.java @@ -20,6 +20,10 @@ */ package jalview.gui; +import jalview.datamodel.SequenceI; +import jalview.viewmodel.ViewportListenerI; +import jalview.viewmodel.ViewportRanges; + import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; @@ -33,10 +37,6 @@ import java.util.List; import javax.swing.JPanel; -import jalview.datamodel.SequenceI; -import jalview.viewmodel.ViewportListenerI; -import jalview.viewmodel.ViewportRanges; - /** * DOCUMENT ME! * @@ -59,7 +59,7 @@ public class IdCanvas extends JPanel implements ViewportListenerI int imgHeight = 0; - boolean fastPaint = false; + private boolean fastPaint = false; List searchResults; @@ -137,6 +137,7 @@ public class IdCanvas extends JPanel implements ViewportListenerI g.drawString(s.getDisplayId(av.getShowJVSuffix()), xPos, (((i - starty + 1) * charHeight) + ypos) - (charHeight / 5)); + // JAL-3253-applet was just hiddenRows here. ccfc48e (gmungoc) added getShowHiddenMarkers test if (hiddenRows && av.getShowHiddenMarkers()) { drawMarker(g, av, i, starty, ypos); @@ -221,6 +222,11 @@ public class IdCanvas extends JPanel implements ViewportListenerI @Override public void paintComponent(Graphics g) { + if (av.getAlignPanel().getHoldRepaint()) + { + return; + } + g.setColor(Color.white); g.fillRect(0, 0, getWidth(), getHeight()); @@ -244,7 +250,7 @@ public class IdCanvas extends JPanel implements ViewportListenerI if (oldHeight != imgHeight || image.getWidth(this) != getWidth()) { - image = new BufferedImage(getWidth(), imgHeight, + image = new BufferedImage(getWidth(), imgHeight, BufferedImage.TYPE_INT_RGB); } @@ -384,20 +390,49 @@ public class IdCanvas extends JPanel implements ViewportListenerI int alignmentWidth = alignViewport.getAlignment().getWidth(); final int alheight = alignViewport.getAlignment().getHeight(); - /* + +// int annotationHeight = 0; + + /* (former) * assumption: SeqCanvas.calculateWrappedGeometry has been called + * + * was based on the fact that SeqCanvas was added as a child prior to IdCanvas, + * and children are processed in order of addition. + * + * It's probably fine. But... + * */ SeqCanvas seqCanvas = alignViewport.getAlignPanel() .getSeqPanel().seqCanvas; + // ...better: let's call it now + seqCanvas.calculateWrappedGeometry(); final int charHeight = alignViewport.getCharHeight(); AnnotationLabels labels = null; if (alignViewport.isShowAnnotation()) { + // BH when was ap == null? + if (ap == null) + { + ap = new AnnotationPanel(alignViewport); + } +// annotationHeight = ap.adjustPanelHeight(); labels = new AnnotationLabels(alignViewport); } +// int hgap = charHeight; +// if (alignViewport.getScaleAboveWrapped()) +// { +// hgap += charHeight; +// } +// +// /* +// * height of alignment + gap + annotations (if shown) +// */ +// int cHeight = alheight * charHeight + hgap +// + annotationHeight; +// ViewportRanges ranges = alignViewport.getRanges(); int rowSize = ranges.getViewportWidth(); @@ -568,20 +603,34 @@ public class IdCanvas extends JPanel implements ViewportListenerI public void propertyChange(PropertyChangeEvent evt) { String propertyName = evt.getPropertyName(); - if (propertyName.equals(ViewportRanges.STARTSEQ) - || (av.getWrapAlignment() - && propertyName.equals(ViewportRanges.STARTRES))) + switch (propertyName) { + case ViewportRanges.STARTSEQ: fastPaint((int) evt.getNewValue() - (int) evt.getOldValue()); - } - else if (propertyName.equals(ViewportRanges.STARTRESANDSEQ)) - { + break; + case ViewportRanges.STARTRES: + if (av.getWrapAlignment()) + { + fastPaint((int) evt.getNewValue() - (int) evt.getOldValue()); + } + break; + case ViewportRanges.STARTRESANDSEQ: fastPaint(((int[]) evt.getNewValue())[1] - ((int[]) evt.getOldValue())[1]); - } - else if (propertyName.equals(ViewportRanges.MOVE_VIEWPORT)) - { + break; + case ViewportRanges.MOVE_VIEWPORT: repaint(); + break; + default: } } + + /** + * Clears the flag that allows a 'fast paint' on the next repaint, so + * requiring a full repaint + */ + public void setNoFastPaint() + { + fastPaint = false; + } } diff --git a/src/jalview/gui/PaintRefresher.java b/src/jalview/gui/PaintRefresher.java index 953fdc5..326bac0 100755 --- a/src/jalview/gui/PaintRefresher.java +++ b/src/jalview/gui/PaintRefresher.java @@ -128,13 +128,13 @@ public class PaintRefresher { // BH 2019.04.22 fixes JS problem of repaint() consolidation // that occurs in JavaScript but not Java [JAL-3226] - ((IdCanvas) comp).fastPaint = false; + ((IdCanvas) comp).setNoFastPaint(); } else if (comp instanceof SeqCanvas) { // BH 2019.04.22 fixes JS problem of repaint() consolidation // that occurs in JavaScript but not Java [JAL-3226] - ((SeqCanvas) comp).fastPaint = false; + ((SeqCanvas) comp).setNoFastPaint(); } comp.repaint(); } diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java index b27208a..f62507a 100755 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@ -57,7 +57,8 @@ import javax.swing.JPanel; public class SeqCanvas extends JPanel implements ViewportListenerI { /** - * vertical gap in pixels between sequences and annotations when in wrapped mode + * vertical gap in pixels between sequences and annotations when in wrapped + * mode */ static final int SEQS_ANNOTATION_GAP = 3; @@ -75,7 +76,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI private final SequenceRenderer seqRdr; - boolean fastPaint = false; + private boolean fastPaint = false; private boolean fastpainting = false; @@ -94,8 +95,12 @@ public class SeqCanvas extends JPanel implements ViewportListenerI private int wrappedVisibleWidths; // number of wrapped widths displayed + private int availWidth; + + private int availHeight; + // Don't do this! Graphics handles are supposed to be transient - //private Graphics2D gg; + // private Graphics2D gg; /** * Creates a new SeqCanvas object. @@ -116,7 +121,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI public SequenceRenderer getSequenceRenderer() { - return seqRdr; + return seqRdr; } public FeatureRenderer getFeatureRenderer() @@ -202,7 +207,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI int yPos = ypos + charHeight; int startX = startx; int endX = endx; - + if (av.hasHiddenColumns()) { HiddenColumns hiddenColumns = av.getAlignment().getHiddenColumns(); @@ -238,7 +243,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI } } - /* * white fill the space for the scale */ @@ -343,7 +347,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI } } - // System.err.println(">>> FastPaint to " + transX + " " + transY + " " // + horizontal + " " + vertical + " " + startRes + " " + endRes // + " " + startSeq + " " + endSeq); @@ -352,9 +355,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI gg.copyArea(horizontal * charWidth, vertical * charHeight, img.getWidth(), img.getHeight(), -horizontal * charWidth, -vertical * charHeight); - - /** @j2sNative xxi = this.img */ - gg.translate(transX, transY); drawPanel(gg, startRes, endRes, startSeq, endSeq, 0); gg.translate(-transX, -transY); @@ -374,19 +374,14 @@ public class SeqCanvas extends JPanel implements ViewportListenerI @Override public void paintComponent(Graphics g) { + if (av.getAlignPanel().getHoldRepaint()) + { + return; + } - int charHeight = av.getCharHeight(); - int charWidth = av.getCharWidth(); - - int width = getWidth(); - int height = getHeight(); - - width -= (width % charWidth); - height -= (height % charHeight); - - // BH 2019 can't possibly fastPaint if either width or height is 0 + getAvailSizes(); - if (width == 0 || height == 0) + if (availWidth == 0 || availHeight == 0) { return; } @@ -436,10 +431,11 @@ public class SeqCanvas extends JPanel implements ViewportListenerI // img is a cached version of the last view we drew. // If we have no img or the size has changed, make a new one. // - if (img == null || width != img.getWidth() - || height != img.getHeight()) + if (img == null || availWidth != img.getWidth() + || availHeight != img.getHeight()) { - img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + img = new BufferedImage(availWidth, availHeight, + BufferedImage.TYPE_INT_RGB); } Graphics2D gg = (Graphics2D) img.getGraphics(); @@ -452,11 +448,11 @@ public class SeqCanvas extends JPanel implements ViewportListenerI } gg.setColor(Color.white); - gg.fillRect(0, 0, img.getWidth(), img.getHeight()); + gg.fillRect(0, 0, availWidth, availHeight); if (av.getWrapAlignment()) { - drawWrappedPanel(gg, width, height, ranges.getStartRes()); + drawWrappedPanel(gg, availWidth, availHeight, ranges.getStartRes()); } else { @@ -474,7 +470,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI drawCursor(g, startRes, endRes, startSeq, endSeq); } } - + /** * Draw an alignment panel for printing * @@ -494,8 +490,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI { drawPanel(g1, startRes, endRes, startSeq, endSeq, 0); - drawSelectionGroup((Graphics2D) g1, startRes, endRes, - startSeq, endSeq); + drawSelectionGroup((Graphics2D) g1, startRes, endRes, startSeq, endSeq); } /** @@ -519,37 +514,36 @@ public class SeqCanvas extends JPanel implements ViewportListenerI if (group != null) { drawWrappedSelection((Graphics2D) g, group, canvasWidth, canvasHeight, - startRes); + startRes); } } /** - * Returns the visible width of the canvas in residues, after allowing for - * East or West scales (if shown) + * Using the current font, determine fields labelWidthEast and labelWidthWest, + * and return the number of residues that can fill the remaining width * - * @param canvasWidth + * @param w * the width in pixels (possibly including scales) * - * @return + * @return the visible width in residues, after allowing for East or West + * scales (if shown) + * */ - public int getWrappedCanvasWidth(int canvasWidth) + public int getWrappedCanvasWidth(int w) { int charWidth = av.getCharWidth(); FontMetrics fm = getFontMetrics(av.getFont()); - int labelWidth = 0; - - if (av.getScaleRightWrapped() || av.getScaleLeftWrapped()) - { - labelWidth = getLabelWidth(fm); - } + int labelWidth = (av.getScaleRightWrapped() || av.getScaleLeftWrapped() + ? getLabelWidth(fm) + : 0); labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0; labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0; - return (canvasWidth - labelWidthEast - labelWidthWest) / charWidth; + return (w - labelWidthEast - labelWidthWest) / charWidth; } /** @@ -575,6 +569,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI maxWidth = Math.max(maxWidth, alignment.getSequenceAt(i).getEnd()); } + // quick int log10 int length = 0; for (int i = maxWidth; i > 0; i /= 10) { @@ -589,28 +584,25 @@ public class SeqCanvas extends JPanel implements ViewportListenerI * window * * @param g - * @param canvasWidth + * @param availWidth * available width in pixels - * @param canvasHeight + * @param availHeight * available height in pixels * @param startColumn * the first column (0...) of the alignment to draw */ - public void drawWrappedPanel(Graphics g, int canvasWidth, - int canvasHeight, final int startColumn) + public void drawWrappedPanel(Graphics g, int availWidth, int availHeight, + final int startColumn) { - int wrappedWidthInResidues = calculateWrappedGeometry(canvasWidth, - canvasHeight); - + int wrappedWidthInResidues = calculateWrappedGeometry(); av.setWrappedWidth(wrappedWidthInResidues); - ViewportRanges ranges = av.getRanges(); ranges.setViewportStartAndWidth(startColumn, wrappedWidthInResidues); // we need to call this again to make sure the startColumn + // wrappedWidthInResidues values are used to calculate wrappedVisibleWidths // correctly. - calculateWrappedGeometry(canvasWidth, canvasHeight); + calculateWrappedGeometry(); /* * draw one width at a time (excluding any scales shown), @@ -623,9 +615,9 @@ public class SeqCanvas extends JPanel implements ViewportListenerI int currentWidth = 0; while ((currentWidth < wrappedVisibleWidths) && (start < maxWidth)) { - int endColumn = Math - .min(maxWidth, start + wrappedWidthInResidues - 1); - drawWrappedWidth(g, ypos, start, endColumn, canvasHeight); + int endColumn = Math.min(maxWidth, + start + wrappedWidthInResidues - 1); + drawWrappedWidth(g, ypos, start, endColumn, availHeight); ypos += wrappedRepeatHeightPx; start += wrappedWidthInResidues; currentWidth++; @@ -634,6 +626,16 @@ public class SeqCanvas extends JPanel implements ViewportListenerI drawWrappedDecorators(g, startColumn); } + private void getAvailSizes() + { + int charHeight = av.getCharHeight(); + int charWidth = av.getCharWidth(); + availWidth = getWidth(); + availHeight = getHeight(); + availWidth -= (availWidth % charWidth); + availHeight -= (availHeight % charHeight); + } + /** * Calculates and saves values needed when rendering a wrapped alignment. * These depend on many factors, including @@ -644,12 +646,26 @@ public class SeqCanvas extends JPanel implements ViewportListenerI *
  • whether scales are shown left, right or above the alignment
  • * * + * @param availWidth + * @param availHeight + * @return the number of residue columns in each width + */ + protected int calculateWrappedGeometry() + { + getAvailSizes(); + return calculateWrappedGeometry(availWidth, availHeight); + + } + + /** + * for test only * @param canvasWidth * @param canvasHeight - * @return the number of residue columns in each width + * @return */ - protected int calculateWrappedGeometry(int canvasWidth, int canvasHeight) + public int calculateWrappedGeometry(int canvasWidth, int canvasHeight) { + int charHeight = av.getCharHeight(); /* @@ -663,9 +679,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI * compute height in pixels of the wrapped widths * - start with space above plus sequences */ - wrappedRepeatHeightPx = wrappedSpaceAboveAlignment; - wrappedRepeatHeightPx += av.getAlignment().getHeight() - * charHeight; + wrappedRepeatHeightPx = wrappedSpaceAboveAlignment + + av.getAlignment().getHeight() * charHeight; /* * add annotations panel height if shown @@ -736,7 +751,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI int charWidth = av.getCharWidth(); int xOffset = labelWidthWest + ((startColumn - ranges.getStartRes()) % viewportWidth) - * charWidth; + * charWidth; g.translate(xOffset, 0); @@ -803,7 +818,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI if (av.getScaleRightWrapped()) { int x = labelWidthWest + viewportWidth * charWidth; - + g.translate(x, 0); drawVerticalScale(g, startCol, endColumn, ypos, false); g.translate(-x, 0); @@ -815,8 +830,9 @@ public class SeqCanvas extends JPanel implements ViewportListenerI */ g.translate(labelWidthWest, 0); g.setColor(Color.white); - g.fillRect(0, ypos - wrappedSpaceAboveAlignment, viewportWidth - * charWidth + labelWidthWest, wrappedSpaceAboveAlignment); + g.fillRect(0, ypos - wrappedSpaceAboveAlignment, + viewportWidth * charWidth + labelWidthWest, + wrappedSpaceAboveAlignment); g.setColor(Color.black); g.translate(-labelWidthWest, 0); @@ -883,18 +899,21 @@ public class SeqCanvas extends JPanel implements ViewportListenerI } } + private final static BasicStroke dottedStroke = new BasicStroke(1, + BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 3f, new float[] + { 5f, 3f }, 0f); + + private final static BasicStroke basicStroke = new BasicStroke(); + /* * Draw a selection group over a wrapped alignment */ private void drawWrappedSelection(Graphics2D g, SequenceGroup group, - int canvasWidth, - int canvasHeight, int startRes) + int canvasWidth, int canvasHeight, int startRes) { // chop the wrapped alignment extent up into panel-sized blocks and treat // each block as if it were a block from an unwrapped alignment - g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_ROUND, 3f, new float[] - { 5f, 3f }, 0f)); + g.setStroke(dottedStroke); g.setColor(Color.RED); int charWidth = av.getCharWidth(); @@ -902,6 +921,21 @@ public class SeqCanvas extends JPanel implements ViewportListenerI / charWidth; int startx = startRes; int maxwidth = av.getAlignment().getVisibleWidth(); + + // JAL-3253-applet had this: + // // height gap above each panel + // int charHeight = av.getCharHeight(); + // int hgap = charHeight; + // if (av.getScaleAboveWrapped()) + // { + // hgap += charHeight; + // } + // int dy = getAnnotationHeight() + hgap + // + av.getAlignment().getHeight() * charHeight; + // int ypos = hgap; // vertical offset + + // this is from 0b573ed (gmungoc) + int dy = wrappedRepeatHeightPx; int ypos = wrappedSpaceAboveAlignment; while ((ypos <= canvasHeight) && (startx < maxwidth)) @@ -915,21 +949,24 @@ public class SeqCanvas extends JPanel implements ViewportListenerI } g.translate(labelWidthWest, 0); + drawUnwrappedSelection(g, group, startx, endx, 0, - av.getAlignment().getHeight() - 1, - ypos); + av.getAlignment().getHeight() - 1, ypos); + g.translate(-labelWidthWest, 0); - ypos += wrappedRepeatHeightPx; + // update vertical offset + ypos += dy; + // update horizontal offset startx += cWidth; } - g.setStroke(new BasicStroke()); + g.setStroke(basicStroke); } /** - * Answers zero if annotations are not shown, otherwise recalculates and answers - * the total height of all annotation rows in pixels + * Answers zero if annotations are not shown, otherwise recalculates and + * answers the total height of all annotation rows in pixels * * @return */ @@ -1190,8 +1227,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI * the cursor drawn on it, if any */ private void drawCursor(Graphics g, int startRes, int endRes, - int startSeq, - int endSeq) + int startSeq, int endSeq) { // convert the cursorY into a position on the visible alignment int cursor_ypos = cursorY; @@ -1262,7 +1298,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI } } - /** * Draw a selection group over an unwrapped alignment * @@ -1285,7 +1320,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI int startRes, int endRes, int startSeq, int endSeq, int offset) { int charWidth = av.getCharWidth(); - + if (!av.hasHiddenColumns()) { drawPartialGroupOutline(g, group, startRes, endRes, startSeq, endSeq, @@ -1308,8 +1343,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI blockStart = region[0]; g.translate(screenY * charWidth, 0); - drawPartialGroupOutline(g, group, - blockStart, blockEnd, startSeq, endSeq, offset); + drawPartialGroupOutline(g, group, blockStart, blockEnd, startSeq, + endSeq, offset); g.translate(-screenY * charWidth, 0); screenY += blockEnd - blockStart + 1; @@ -1478,7 +1513,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI g.drawLine(sx + xwidth, oldY, sx + xwidth, sy); } } - + /** * Highlights search results in the visible region by rendering as white text * on a black background. Any previous highlighting is removed. Answers true @@ -1494,7 +1529,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI return highlightSearchResults(results, false); } - + /** * Highlights search results in the visible region by rendering as white text * on a black background. Any previous highlighting is removed. Answers true @@ -1652,7 +1687,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI { firstCol = alignment.getHiddenColumns() .absoluteToVisibleColumn(firstCol); - lastCol = alignment.getHiddenColumns().absoluteToVisibleColumn(lastCol); + lastCol = alignment.getHiddenColumns() + .absoluteToVisibleColumn(lastCol); } int transX = (firstCol - ranges.getStartRes()) * av.getCharWidth(); int transY = (firstSeq - ranges.getStartSeq()) * av.getCharHeight(); @@ -1670,92 +1706,161 @@ public class SeqCanvas extends JPanel implements ViewportListenerI public void propertyChange(PropertyChangeEvent evt) { String eventName = evt.getPropertyName(); - // System.err.println(">>SeqCanvas propertyChange " + eventName); - if (eventName.equals(SequenceGroup.SEQ_GROUP_CHANGED)) - { - fastPaint = true; - repaint(); - return; - } - else if (eventName.equals(ViewportRanges.MOVE_VIEWPORT)) - { - fastPaint = false; - // System.err.println("!!!! fastPaint false from MOVE_VIEWPORT"); - repaint(); - return; - } - int scrollX = 0; - if (eventName.equals(ViewportRanges.STARTRES) - || eventName.equals(ViewportRanges.STARTRESANDSEQ)) - { - // Make sure we're not trying to draw a panel - // larger than the visible window - if (eventName.equals(ViewportRanges.STARTRES)) - { - scrollX = (int) evt.getNewValue() - (int) evt.getOldValue(); - } - else - { - scrollX = ((int[]) evt.getNewValue())[0] - - ((int[]) evt.getOldValue())[0]; - } - ViewportRanges vpRanges = av.getRanges(); + // BH 2019.07.27 removes dead code introduced in aad3650 and simplifies + // logic, emphasizing no check for ENDRES or ENDSEQ - int range = vpRanges.getEndRes() - vpRanges.getStartRes() + 1; - if (scrollX > range) - { - scrollX = range; - } - else if (scrollX < -range) - { - scrollX = -range; - } - } // Both scrolling and resizing change viewport ranges: scrolling changes // both start and end points, but resize only changes end values. // Here we only want to fastpaint on a scroll, with resize using a normal // paint, so scroll events are identified as changes to the horizontal or // vertical start value. - if (eventName.equals(ViewportRanges.STARTRES)) - { - if (av.getWrapAlignment()) - { - fastPaintWrapped(scrollX); - } - else - { - fastPaint(scrollX, 0); - } - } - else if (eventName.equals(ViewportRanges.STARTSEQ)) + + // Make sure we're not trying to draw a panel + // larger than the visible window + int scrollX = 0; + int scrollY = 0; + switch (eventName) { - // scroll + case SequenceGroup.SEQ_GROUP_CHANGED: + fastPaint = true; + repaint(); + return; + case ViewportRanges.MOVE_VIEWPORT: + fastPaint = false; + repaint(); + return; + case ViewportRanges.STARTSEQ: + // meaning STARTOREND + // typically scroll, but possibly just the end changed fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue()); - } - else if (eventName.equals(ViewportRanges.STARTRESANDSEQ)) - { - if (av.getWrapAlignment()) - { - fastPaintWrapped(scrollX); - } - else + return; + case ViewportRanges.STARTRES: + // meaning STARTOREND + scrollX = (int) evt.getNewValue() - (int) evt.getOldValue(); + break; + case ViewportRanges.STARTRESANDSEQ: + scrollX = ((int[]) evt.getNewValue())[0] + - ((int[]) evt.getOldValue())[0]; + scrollY = ((int[]) evt.getNewValue())[1] + - ((int[]) evt.getOldValue())[1]; + + // System.out.println("SC dx dy " + scrollX + " " + scrollY); + + if (scrollX != 0 && scrollY != 0) { - fastPaint(scrollX, 0); + // all sorts of problems in JavaScript if this is commented out. + repaint(); + return; + } + break; + default: + return; } - else if (eventName.equals(ViewportRanges.STARTSEQ)) + + ViewportRanges vpRanges = av.getRanges(); + int range = vpRanges.getEndRes() - vpRanges.getStartRes() + 1; + scrollX = Math.max(Math.min(scrollX, range), -range); + // only STARTRES or STARTRESANDSEQ: + if (av.getWrapAlignment()) { - // scroll - fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue()); + fastPaintWrapped(scrollX); } - else if (eventName.equals(ViewportRanges.STARTRESANDSEQ)) + else { - if (av.getWrapAlignment()) - { - fastPaintWrapped(scrollX); - } + fastPaint(scrollX, scrollY); } + + // BH 2019.07.27 was: + // if (eventName.equals(SequenceGroup.SEQ_GROUP_CHANGED)) + // { + // fastPaint = true; + // repaint(); + // return; + // } + // else if (eventName.equals(ViewportRanges.MOVE_VIEWPORT)) + // { + // fastPaint = false; + // // System.err.println("!!!! fastPaint false from MOVE_VIEWPORT"); + // repaint(); + // return; + // } + // + // if (eventName.equals(ViewportRanges.STARTRES) + // || eventName.equals(ViewportRanges.STARTRESANDSEQ)) + // { + // // Make sure we're not trying to draw a panel + // // larger than the visible window + // if (eventName.equals(ViewportRanges.STARTRES)) + // { + // scrollX = (int) evt.getNewValue() - (int) evt.getOldValue(); + // } + // else + // { + // scrollX = ((int[]) evt.getNewValue())[0] + // - ((int[]) evt.getOldValue())[0]; + // } + // ViewportRanges vpRanges = av.getRanges(); + // + // int range = vpRanges.getEndRes() - vpRanges.getStartRes() + 1; + // if (scrollX > range) + // { + // scrollX = range; + // } + // else if (scrollX < -range) + // { + // scrollX = -range; + // } + // } + // Both scrolling and resizing change viewport ranges: scrolling changes + // both start and end points, but resize only changes end values. + // Here we only want to fastpaint on a scroll, with resize using a normal + // paint, so scroll events are identified as changes to the horizontal or + // vertical start value. + // BH 2019.07.27 was: + // if (eventName.equals(ViewportRanges.STARTRES)) + // { + // if (av.getWrapAlignment()) + // { + // fastPaintWrapped(scrollX); + // } + // else + // { + // fastPaint(scrollX, 0); + // } + // } + // else if (eventName.equals(ViewportRanges.STARTSEQ)) + // { + // // scroll + // fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue()); + // } + // else if (eventName.equals(ViewportRanges.STARTRESANDSEQ)) + // { + // if (av.getWrapAlignment()) + // { + // fastPaintWrapped(scrollX); + // } + // else + // { + // fastPaint(scrollX, 0); + // } + // } + // + // BH oops! + // + // else if (eventName.equals(ViewportRanges.STARTSEQ)) + // { + // // scroll + // fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue()); + // } + // else if (eventName.equals(ViewportRanges.STARTRESANDSEQ)) + // { + // if (av.getWrapAlignment()) + // { + // fastPaintWrapped(scrollX); + // } + // } } /** @@ -1792,10 +1897,10 @@ public class SeqCanvas extends JPanel implements ViewportListenerI try { - + Graphics gg = img.getGraphics(); - - calculateWrappedGeometry(getWidth(), getHeight()); + + calculateWrappedGeometry(); /* * relocate the regions of the alignment that are still visible @@ -1810,8 +1915,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI if (scrollX < 0) { int startRes = ranges.getStartRes(); - drawWrappedWidth(gg, wrappedSpaceAboveAlignment, startRes, startRes - - scrollX - 1, getHeight()); + drawWrappedWidth(gg, wrappedSpaceAboveAlignment, startRes, + startRes - scrollX - 1, getHeight()); } else { @@ -1824,7 +1929,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI drawWrappedDecorators(gg, ranges.getStartRes()); gg.dispose(); - + repaint(); } finally { @@ -1849,7 +1954,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI } Graphics gg = img.getGraphics(); - + ViewportRanges ranges = av.getRanges(); int viewportWidth = ranges.getViewportWidth(); int charWidth = av.getCharWidth(); @@ -1860,7 +1965,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI */ int visibleWidths = wrappedVisibleWidths; int canvasHeight = getHeight(); - boolean lastWidthPartHeight = (wrappedVisibleWidths * wrappedRepeatHeightPx) > canvasHeight; + boolean lastWidthPartHeight = (wrappedVisibleWidths + * wrappedRepeatHeightPx) > canvasHeight; if (lastWidthPartHeight) { @@ -1876,16 +1982,15 @@ public class SeqCanvas extends JPanel implements ViewportListenerI /* * white fill first to erase annotations */ - - + gg.translate(xOffset, 0); gg.setColor(Color.white); - gg.fillRect(labelWidthWest, ypos, - (endRes - startRes + 1) * charWidth, wrappedRepeatHeightPx); + gg.fillRect(labelWidthWest, ypos, (endRes - startRes + 1) * charWidth, + wrappedRepeatHeightPx); gg.translate(-xOffset, 0); drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight); - + } /* @@ -1930,7 +2035,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI gg.fillRect(0, canvasHeight - heightBelow, getWidth(), heightBelow); } gg.dispose(); - } + } /** * Shifts the visible alignment by the specified number of columns - left if @@ -2018,8 +2123,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI if (y + wrappedRepeatHeightPx < canvasHeight - wrappedRepeatHeightPx && (xpos + viewportWidth <= xMax)) { - gg.copyArea(labelWidthWest, y + wrappedRepeatHeightPx, -positions - * charWidth, heightToCopy, widthToCopy, + gg.copyArea(labelWidthWest, y + wrappedRepeatHeightPx, + -positions * charWidth, heightToCopy, widthToCopy, -wrappedRepeatHeightPx); } y += wrappedRepeatHeightPx; @@ -2029,7 +2134,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI gg.dispose(); } - /** * Redraws any positions in the search results in the visible region of a * wrapped alignment. Any highlights are drawn depending on the search results @@ -2050,7 +2154,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI boolean matchFound = false; - calculateWrappedGeometry(getWidth(), getHeight()); + calculateWrappedGeometry(); int wrappedWidth = av.getWrappedWidth(); int wrappedHeight = wrappedRepeatHeightPx; @@ -2063,8 +2167,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI } int firstVisibleColumn = ranges.getStartRes(); - int lastVisibleColumn = ranges.getStartRes() + repeats - * ranges.getViewportWidth() - 1; + int lastVisibleColumn = ranges.getStartRes() + + repeats * ranges.getViewportWidth() - 1; AlignmentI alignment = av.getAlignment(); if (av.hasHiddenColumns()) @@ -2077,7 +2181,6 @@ public class SeqCanvas extends JPanel implements ViewportListenerI int gapHeight = charHeight * (av.getScaleAboveWrapped() ? 2 : 1); - Graphics gg = img.getGraphics(); for (int seqNo = ranges.getStartSeq(); seqNo <= ranges @@ -2121,8 +2224,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI * transX: offset from left edge of canvas to residue position */ int transX = labelWidthWest - + ((displayColumn - ranges.getStartRes()) % wrappedWidth) - * av.getCharWidth(); + + ((displayColumn - ranges.getStartRes()) + % wrappedWidth) * av.getCharWidth(); /* * transY: offset from top edge of canvas to residue position @@ -2149,7 +2252,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI } } } - + gg.dispose(); return matchFound; @@ -2165,4 +2268,13 @@ public class SeqCanvas extends JPanel implements ViewportListenerI return labelWidthWest; } + /** + * Clears the flag that allows a 'fast paint' on the next repaint, so + * requiring a full repaint + */ + public void setNoFastPaint() + { + fastPaint = false; + } + } diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index b2149df..4e789b9 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -291,8 +291,7 @@ public class SeqPanel extends JPanel int alignmentHeight = av.getAlignment().getHeight(); if (av.getWrapAlignment()) { - seqCanvas.calculateWrappedGeometry(seqCanvas.getWidth(), - seqCanvas.getHeight()); + seqCanvas.calculateWrappedGeometry(); /* * yPos modulo height of repeating width diff --git a/test/jalview/gui/SeqCanvasTest.java b/test/jalview/gui/SeqCanvasTest.java index e3b1191..78f6cd3 100644 --- a/test/jalview/gui/SeqCanvasTest.java +++ b/test/jalview/gui/SeqCanvasTest.java @@ -22,21 +22,27 @@ package jalview.gui; import static org.testng.Assert.assertEquals; +import jalview.bin.Cache; +import jalview.datamodel.AlignmentI; +import jalview.io.DataSourceType; +import jalview.io.FileLoader; +import jalview.util.Platform; + import java.awt.Font; import java.awt.FontMetrics; -import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import jalview.bin.Cache; -import jalview.datamodel.AlignmentI; -import jalview.io.DataSourceType; -import jalview.io.FileLoader; import junit.extensions.PA; public class SeqCanvasTest { - private AlignFrame af; + @BeforeClass(alwaysRun = true) + public void setUp() + { + Cache.initLogger(); + } /** * Test the method that computes wrapped width in residues, height of wrapped @@ -45,6 +51,8 @@ public class SeqCanvasTest @Test(groups = "Functional") public void testCalculateWrappedGeometry_noAnnotations() { + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded( + "examples/uniref50.fa", DataSourceType.FILE); AlignViewport av = af.getViewport(); AlignmentI al = av.getAlignment(); assertEquals(al.getWidth(), 157); @@ -57,8 +65,8 @@ public class SeqCanvasTest av.setFont(new Font("SansSerif", Font.PLAIN, 14), true); int charHeight = av.getCharHeight(); int charWidth = av.getCharWidth(); - assertEquals(charHeight, 17); - assertEquals(charWidth, 12); + assertEquals(charHeight, Platform.isMac() ? 17 : 19); + assertEquals(charWidth, Platform.isMac() ? 12 : 11); /* * first with scales above, left, right @@ -69,7 +77,8 @@ public class SeqCanvasTest av.setScaleRightWrapped(true); FontMetrics fm = testee.getFontMetrics(av.getFont()); int labelWidth = fm.stringWidth("000") + charWidth; - assertEquals(labelWidth, 39); // 3 x 9 + charWidth + assertEquals(labelWidth, + Platform.isMac() ? 3 * 9 + charWidth : 3 * 8 + charWidth); /* * width 400 pixels leaves (400 - 2*labelWidth) for residue columns @@ -191,7 +200,7 @@ public class SeqCanvasTest canvasWidth += 2; wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight); - assertEquals(wrappedWidth, 24); // 2px not enough + assertEquals(wrappedWidth, Platform.isMac() ? 24 : 25); // 2px not enough canvasWidth += 1; wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight); @@ -213,6 +222,8 @@ public class SeqCanvasTest @Test(groups = "Functional") public void testCalculateWrappedGeometry_withAnnotations() { + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded( + "examples/uniref50.fa", DataSourceType.FILE); AlignViewport av = af.getViewport(); AlignmentI al = av.getAlignment(); assertEquals(al.getWidth(), 157); @@ -223,9 +234,10 @@ public class SeqCanvasTest av.setFont(new Font("SansSerif", Font.PLAIN, 14), true); int charHeight = av.getCharHeight(); int charWidth = av.getCharWidth(); - assertEquals(charHeight, 17); - assertEquals(charWidth, 12); - + + assertEquals(charHeight, Platform.isMac() ? 17 : 19); + assertEquals(charWidth, Platform.isMac() ? 12 : 11); + SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas; /* @@ -235,9 +247,12 @@ public class SeqCanvasTest av.setScaleAboveWrapped(true); av.setScaleLeftWrapped(true); av.setScaleRightWrapped(true); + FontMetrics fm = testee.getFontMetrics(av.getFont()); int labelWidth = fm.stringWidth("000") + charWidth; - assertEquals(labelWidth, 39); // 3 x 9 + charWidth + assertEquals(labelWidth, + Platform.isMac() ? 3 * 9 + charWidth : 3 * 8 + charWidth); + int annotationHeight = testee.getAnnotationHeight(); /* @@ -306,25 +321,27 @@ public class SeqCanvasTest * endSeq should be unchanged, but the vertical repeat height should include * all sequences. */ - @Test(groups = "Functional_Failing") + @Test(groups = "Functional") public void testCalculateWrappedGeometry_fromScrolled() { + AlignFrame af = new FileLoader().LoadFileWaitTillLoaded( + "examples/uniref50.fa", DataSourceType.FILE); AlignViewport av = af.getViewport(); AlignmentI al = av.getAlignment(); assertEquals(al.getWidth(), 157); assertEquals(al.getHeight(), 15); av.getRanges().setStartEndSeq(0, 3); - av.setFont(new Font("SansSerif", Font.PLAIN, 14), true); - av.setWrapAlignment(true); av.setShowAnnotation(false); av.setScaleAboveWrapped(true); SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas; - + av.setWrapAlignment(true); + av.setFont(new Font("SansSerif", Font.PLAIN, 14), true); int charHeight = av.getCharHeight(); int charWidth = av.getCharWidth(); - assertEquals(charHeight, 17); - assertEquals(charWidth, 12); + // Windows h=19, w=11. + assertEquals(charHeight, Platform.isMac() ? 17 : 19); + assertEquals(charWidth, Platform.isMac() ? 12 : 11); int canvasWidth = 400; int canvasHeight = 300; @@ -333,29 +350,7 @@ public class SeqCanvasTest assertEquals(av.getRanges().getEndSeq(), 3); // unchanged int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx"); - assertEquals(repeatingHeight, charHeight * (2 + al.getHeight())); - } - - @BeforeMethod(alwaysRun = true) - public void setUp() - { - Cache.loadProperties("test/jalview/io/testProps.jvprops"); - Cache.setPropertyNoSave("SHOW_IDENTITY", - Boolean.TRUE.toString()); - af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa", - DataSourceType.FILE); - - /* - * wait for Consensus thread to complete - */ - do - { - try - { - Thread.sleep(50); - } catch (InterruptedException x) - { - } - } while (af.getViewport().getCalcManager().isWorking()); + int h = charHeight * (2 + al.getHeight()); + assertEquals(repeatingHeight, h); } } diff --git a/test/jalview/ws/PDBSequenceFetcherTest.java b/test/jalview/ws/PDBSequenceFetcherTest.java index 9992137..b14b3b5 100644 --- a/test/jalview/ws/PDBSequenceFetcherTest.java +++ b/test/jalview/ws/PDBSequenceFetcherTest.java @@ -149,7 +149,7 @@ public class PDBSequenceFetcherTest // chains in structure have a mapping to data in the structure List prev = null; int lastp = -1; - for (int col = 1; col <= sq.getLength(); col++) + for (int col = 1, ns = sq.getLength(); col <= ns; col++) { List sf = sq.findFeatures(col, col, "RESNUM"); if (sf.size() != 1) diff --git a/test/jalview/ws/jabaws/JalviewJabawsTestUtils.java b/test/jalview/ws/jabaws/JalviewJabawsTestUtils.java index 12f5e1b..9c291c3 100644 --- a/test/jalview/ws/jabaws/JalviewJabawsTestUtils.java +++ b/test/jalview/ws/jabaws/JalviewJabawsTestUtils.java @@ -85,7 +85,7 @@ public class JalviewJabawsTestUtils public static Jws2Discoverer getJabawsDiscoverer(boolean localhost) { jalview.ws.jws2.Jws2Discoverer disc = jalview.ws.jws2.Jws2Discoverer - .getDiscoverer(); + .getInstance(); String svcurls = ""; if (localhost) { @@ -97,7 +97,7 @@ public class JalviewJabawsTestUtils services.add(url); } ; - Jws2Discoverer.getDiscoverer().setServiceUrls(services); + Jws2Discoverer.getInstance().setServiceUrls(services); } try { -- 1.7.10.2