From 65001ada8adff987afc0cf4ce9797b6cfde26055 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 6 Jul 2017 17:39:37 +0100 Subject: [PATCH] JAL-1858 fast paint wrapped highlights unless view was scrolled --- src/jalview/gui/AlignmentPanel.java | 203 +++++++++++++++++----------------- src/jalview/gui/FeatureRenderer.java | 3 +- src/jalview/gui/SeqCanvas.java | 29 +++-- src/jalview/gui/SeqPanel.java | 11 +- 4 files changed, 131 insertions(+), 115 deletions(-) diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java index 3994c29..027dd0f 100644 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@ -343,19 +343,11 @@ public class AlignmentPanel extends GAlignmentPanel implements */ public void highlightSearchResults(SearchResultsI results) { - scrollToPosition(results); - getSeqPanel().seqCanvas.highlightSearchResults(results); - } + boolean scrolled = scrollToPosition(results, 0, true, false); - /** - * Scroll the view to show the position of the highlighted region in results - * (if any) and redraw the overview - * - * @param results - */ - public boolean scrollToPosition(SearchResultsI results) - { - return scrollToPosition(results, 0, true, false); + boolean noFastPaint = scrolled && av.getWrapAlignment(); + + getSeqPanel().seqCanvas.highlightSearchResults(results, noFastPaint); } /** @@ -373,8 +365,10 @@ public class AlignmentPanel extends GAlignmentPanel implements } /** - * Scroll the view to show the position of the highlighted region in results - * (if any) + * Scrolls the view (if necessary) to show the position of the first + * highlighted region in results (if any). Answers true if the view was + * scrolled, or false if no matched region was found, or it is already + * visible. * * @param results * @param verticalOffset @@ -384,116 +378,117 @@ public class AlignmentPanel extends GAlignmentPanel implements * - when set, the overview will be recalculated (takes longer) * @param centre * if true, try to centre the search results horizontally in the view - * @return false if results were not found + * @return */ - public boolean scrollToPosition(SearchResultsI results, + protected boolean scrollToPosition(SearchResultsI results, int verticalOffset, boolean redrawOverview, boolean centre) { int startv, endv, starts, ends; - // TODO: properly locate search results in view when large numbers of hidden - // columns exist before highlighted region - // do we need to scroll the panel? - // TODO: tons of nullpointerexceptions raised here. - if (results != null && results.getSize() > 0 && av != null - && av.getAlignment() != null) - { - int seqIndex = av.getAlignment().findIndex(results); - if (seqIndex == -1) - { - return false; - } - SequenceI seq = av.getAlignment().getSequenceAt(seqIndex); - int[] r = results.getResults(seq, 0, av.getAlignment().getWidth()); - if (r == null) - { - return false; - } - int start = r[0]; - int end = r[1]; + if (results == null || results.isEmpty() || av == null + || av.getAlignment() == null) + { + return false; + } + int seqIndex = av.getAlignment().findIndex(results); + if (seqIndex == -1) + { + return false; + } + SequenceI seq = av.getAlignment().getSequenceAt(seqIndex); - /* - * To centre results, scroll to positions half the visible width - * left/right of the start/end positions - */ - if (centre) - { - int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2 - - 1; - start = Math.max(start - offset, 0); - end = end + offset - 1; - } - if (start < 0) - { - return false; - } - if (end == seq.getEnd()) - { - return false; - } - if (av.hasHiddenColumns()) + int[] r = results.getResults(seq, 0, av.getAlignment().getWidth()); + if (r == null) + { + return false; + } + int start = r[0]; + int end = r[1]; + + /* + * To centre results, scroll to positions half the visible width + * left/right of the start/end positions + */ + if (centre) + { + int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2 - 1; + start = Math.max(start - offset, 0); + end = end + offset - 1; + } + if (start < 0) + { + return false; + } + if (end == seq.getEnd()) + { + return false; + } + + if (av.hasHiddenColumns()) + { + HiddenColumns hidden = av.getAlignment().getHiddenColumns(); + start = hidden.findColumnPosition(start); + end = hidden.findColumnPosition(end); + if (start == end) { - HiddenColumns hidden = av.getAlignment().getHiddenColumns(); - start = hidden.findColumnPosition(start); - end = hidden.findColumnPosition(end); - if (start == end) + if (!hidden.isVisible(r[0])) { - if (!hidden.isVisible(r[0])) - { - // don't scroll - position isn't visible - return false; - } + // don't scroll - position isn't visible + return false; } } + } - /* - * allow for offset of target sequence (actually scroll to one above it) - */ - seqIndex = Math.max(0, seqIndex - verticalOffset); + /* + * allow for offset of target sequence (actually scroll to one above it) + */ + seqIndex = Math.max(0, seqIndex - verticalOffset); + boolean scrollNeeded = true; - if (!av.getWrapAlignment()) + if (!av.getWrapAlignment()) + { + if ((startv = vpRanges.getStartRes()) >= start) { - if ((startv = vpRanges.getStartRes()) >= start) - { - /* - * Scroll left to make start of search results visible - */ - setScrollValues(start, seqIndex); - } - else if ((endv = vpRanges.getEndRes()) <= end) - { - /* - * Scroll right to make end of search results visible - */ - setScrollValues(startv + end - endv, seqIndex); - } - else if ((starts = vpRanges.getStartSeq()) > seqIndex) - { - /* - * Scroll up to make start of search results visible - */ - setScrollValues(vpRanges.getStartRes(), seqIndex); - } - else if ((ends = vpRanges.getEndSeq()) <= seqIndex) - { - /* - * Scroll down to make end of search results visible - */ - setScrollValues(vpRanges.getStartRes(), starts + seqIndex - ends - + 1); - } /* - * Else results are already visible - no need to scroll + * Scroll left to make start of search results visible */ + setScrollValues(start, seqIndex); } - else + else if ((endv = vpRanges.getEndRes()) <= end) { - vpRanges.scrollToWrappedVisible(start); + /* + * Scroll right to make end of search results visible + */ + setScrollValues(startv + end - endv, seqIndex); + } + else if ((starts = vpRanges.getStartSeq()) > seqIndex) + { + /* + * Scroll up to make start of search results visible + */ + setScrollValues(vpRanges.getStartRes(), seqIndex); } + else if ((ends = vpRanges.getEndSeq()) <= seqIndex) + { + /* + * Scroll down to make end of search results visible + */ + setScrollValues(vpRanges.getStartRes(), starts + seqIndex - ends + + 1); + } + /* + * Else results are already visible - no need to scroll + */ + scrollNeeded = false; + } + else + { + scrollNeeded = vpRanges.scrollToWrappedVisible(start); } paintAlignment(redrawOverview); - return true; + + return scrollNeeded; } /** @@ -1815,7 +1810,7 @@ public class AlignmentPanel extends GAlignmentPanel implements * @param verticalOffset * the number of visible sequences to show above the mapped region */ - public void scrollToCentre(SearchResultsI sr, int verticalOffset) + protected void scrollToCentre(SearchResultsI sr, int verticalOffset) { /* * To avoid jumpy vertical scrolling (if some sequences are gapped or not diff --git a/src/jalview/gui/FeatureRenderer.java b/src/jalview/gui/FeatureRenderer.java index 5c7bd4e..6f6bc02 100644 --- a/src/jalview/gui/FeatureRenderer.java +++ b/src/jalview/gui/FeatureRenderer.java @@ -271,7 +271,8 @@ public class FeatureRenderer extends highlight.addResult(sequences.get(0), sf.getBegin(), sf.getEnd()); - alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(highlight); + alignPanel.getSeqPanel().seqCanvas.highlightSearchResults( + highlight, false); } FeatureColourI col = getFeatureStyle(name.getText()); diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java index 6099897..47ef7cf 100755 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@ -1000,18 +1000,33 @@ public class SeqCanvas extends JComponent implements ViewportListenerI * on a black background. Any previous highlighting is removed. Answers true * if any highlight was left on the visible alignment (so status bar should be * set to match), else false. + *

+ * Currently fastPaint is not implemented for wrapped alignments. If a wrapped + * alignment had to be scrolled to show the highlighted region, then it should + * be fully redrawn, otherwise a fast paint can be performed. This argument + * could be removed if fast paint of scrolled wrapped alignment is coded in + * future (JAL-2609). * * @param results + * @param noFastPaint * @return */ - public boolean highlightSearchResults(SearchResultsI results) + public boolean highlightSearchResults(SearchResultsI results, + boolean noFastPaint) { - updateViewport(); - + if (fastpainting) + { + return false; + } boolean wrapped = av.getWrapAlignment(); try { + fastPaint = !noFastPaint; + fastpainting = fastPaint; + + updateViewport(); + /* * to avoid redrawing the whole visible region, we instead * redraw just the minimal regions to remove previous highlights @@ -1051,7 +1066,6 @@ public class SeqCanvas extends JComponent implements ViewportListenerI { fastpainting = false; } - } /** @@ -1214,8 +1228,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI ViewportRanges ranges = av.getRanges(); int canvasHeight = getHeight(); - int repeats = wrappedHeight / canvasHeight; - if (wrappedHeight % canvasHeight > 0) + int repeats = canvasHeight / wrappedHeight; + if (canvasHeight / wrappedHeight > 0) { repeats++; } @@ -1283,7 +1297,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI * transY: offset from top edge of canvas to residue position */ int transY = gapHeight; - transY += (displayColumn / wrappedWidth) * wrappedHeight; + transY += (displayColumn - ranges.getStartRes()) + / wrappedWidth * wrappedHeight; transY += (seqNo - ranges.getStartSeq()) * av.getCharHeight(); /* diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index 1a3081f..ca79c73 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -681,6 +681,8 @@ public class SeqPanel extends JPanel implements MouseListener, } lastSearchResults = results; + boolean wasScrolled = false; + if (av.isFollowHighlight()) { // don't allow highlight of protein/cDNA to also scroll a complementary @@ -688,13 +690,16 @@ public class SeqPanel extends JPanel implements MouseListener, // over residue to change abruptly, causing highlighted residue in panel 2 // to change, causing a scroll in panel 1 etc) ap.setToScrollComplementPanel(false); - if (ap.scrollToPosition(results, false)) + wasScrolled = ap.scrollToPosition(results, false); + if (wasScrolled) { seqCanvas.revalidate(); } ap.setToScrollComplementPanel(true); } - if (seqCanvas.highlightSearchResults(results)) + + boolean noFastPaint = wasScrolled && av.getWrapAlignment(); + if (seqCanvas.highlightSearchResults(results, noFastPaint)) { setStatusMessage(results); } @@ -1594,7 +1599,7 @@ public class SeqPanel extends JPanel implements MouseListener, SearchResultsI highlight = new SearchResults(); highlight.addResult(sequence, features.get(0).getBegin(), features .get(0).getEnd()); - seqCanvas.highlightSearchResults(highlight); + seqCanvas.highlightSearchResults(highlight, false); /* * open the Amend Features dialog; clear highlighting afterwards, -- 1.7.10.2