From 67f498031a89aa97926db7be629e94ef031c10e4 Mon Sep 17 00:00:00 2001 From: kiramt Date: Tue, 3 Oct 2017 07:45:06 +0100 Subject: [PATCH] JAL-2674 2nd attempt to refactor seqcanvas drawing to iterator --- src/jalview/appletgui/SeqCanvas.java | 9 +- src/jalview/datamodel/HiddenColumns.java | 137 ++++++++++++++++++++++++++++++ src/jalview/gui/SeqCanvas.java | 37 +++++--- 3 files changed, 164 insertions(+), 19 deletions(-) diff --git a/src/jalview/appletgui/SeqCanvas.java b/src/jalview/appletgui/SeqCanvas.java index 74a9f7f..67b21bc 100755 --- a/src/jalview/appletgui/SeqCanvas.java +++ b/src/jalview/appletgui/SeqCanvas.java @@ -562,7 +562,7 @@ public class SeqCanvas extends Panel implements ViewportListenerI int screenY = 0; final int screenYMax = endRes - startRes; int blockStart = startRes; - int blockEnd = endRes; + int blockEnd = endRes; // equals blockStart + screenYMax - screenY; HiddenColumns hidden = av.getAlignment().getHiddenColumns(); Iterator regions = hidden.iterator(); @@ -575,6 +575,7 @@ public class SeqCanvas extends Panel implements ViewportListenerI if (hideStart <= blockStart) { blockStart += (hideEnd - hideStart) + 1; + blockEnd += (hideEnd - hideStart) + 1; continue; } @@ -582,8 +583,7 @@ public class SeqCanvas extends Panel implements ViewportListenerI * draw up to just before the next hidden region, or the end of * the visible region, whichever comes first */ - blockEnd = Math.min(hideStart - 1, - blockStart + screenYMax - screenY); + blockEnd = Math.min(blockEnd, hideStart - 1); g1.translate(screenY * avcharWidth, 0); draw(g1, blockStart, blockEnd, startSeq, endSeq, offset); @@ -603,6 +603,7 @@ public class SeqCanvas extends Panel implements ViewportListenerI g1.translate(-screenY * avcharWidth, 0); screenY += blockEnd - blockStart + 1; blockStart = hideEnd + 1; + blockEnd = blockStart + screenYMax - screenY; if (screenY > screenYMax) { @@ -614,10 +615,8 @@ public class SeqCanvas extends Panel implements ViewportListenerI if (screenY <= screenYMax) { // remaining visible region to render - blockEnd = blockStart + screenYMax - screenY; g1.translate(screenY * avcharWidth, 0); draw(g1, blockStart, blockEnd, startSeq, endSeq, offset); - g1.translate(-screenY * avcharWidth, 0); } } diff --git a/src/jalview/datamodel/HiddenColumns.java b/src/jalview/datamodel/HiddenColumns.java index b6e6ce3..2088aba 100644 --- a/src/jalview/datamodel/HiddenColumns.java +++ b/src/jalview/datamodel/HiddenColumns.java @@ -1393,6 +1393,37 @@ public class HiddenColumns } /** + * return an iterator over visible segments between the given start and end + * boundaries + * + * @param start + * (first column - inclusive from 0) + * @param end + * (last column - inclusive) + * @param useVisibleCoords + * if true, start and end are visible column positions, not absolute + * positions + */ + public Iterator getVisibleBlocksIterator(int start, int end, + boolean useVisibleCoords) + { + if (useVisibleCoords) + { + // TODO + // we should really just convert start and end here with + // adjustForHiddenColumns + // and then create a VisibleBlocksIterator + // but without a cursor this will be horribly slow in some situations + // ... so until then... + return new VisibleBlocksVisBoundsIterator(start, end, true); + } + else + { + return new VisibleBlocksIterator(start, end, true); + } + } + + /** * An iterator which iterates over hidden column regions in a range. */ private class BoundedHiddenColsIterator implements Iterator @@ -1891,4 +1922,110 @@ public class HiddenColumns } } + /** + * An iterator which iterates over visible regions in a range as visible + * column positions. + */ + public class VisibleBlocksVisBoundsIterator implements Iterator + { + private List vcontigs = new ArrayList<>(); + + private int currentPosition = 0; + + private boolean endsAtHidden = true; + + VisibleBlocksVisBoundsIterator(int start, int end, boolean usecopy) + { + try + { + if (usecopy) + { + LOCK.readLock().lock(); + } + + if (hiddenColumns != null && hiddenColumns.size() > 0) + { + int blockStart = start; + int blockEnd = end; + int hiddenSoFar = 0; + int visSoFar = 0; + int maxVisible = end - start; + + // iterate until a region begins within (start,end] + int i = 0; + while ((i < hiddenColumns.size()) + && (hiddenColumns.get(i)[0] <= blockStart + hiddenSoFar)) + { + hiddenSoFar += hiddenColumns.get(i)[1] - hiddenColumns.get(i)[0] + + 1; + i++; + } + + blockStart += hiddenSoFar; // convert start to absolute position + blockEnd += hiddenSoFar; // convert end too in + + // iterate from start to end, adding each hidden region. Positions are + // absolute, and all regions which *overlap* [start,end] are used. + while (i < hiddenColumns.size() + && (hiddenColumns.get(i)[0] <= blockEnd)) + { + int[] region = hiddenColumns.get(i); + + blockEnd = Math.min(blockEnd, region[0] - 1); + + int[] contig = new int[] { blockStart, blockEnd }; + vcontigs.add(contig); + + visSoFar += blockEnd - blockStart + 1; + blockStart = region[1] + 1; + blockEnd = end + hiddenSoFar; + hiddenSoFar += region[1] - region[0] + 1; + + i++; + } + if (visSoFar < maxVisible) + { + blockEnd = blockStart + maxVisible - visSoFar; + int[] contig = new int[] { blockStart, + blockEnd }; + vcontigs.add(contig); + + endsAtHidden = false; + } + } + else + { + int[] contig = new int[] { start, end }; + vcontigs.add(contig); + endsAtHidden = false; + } + } finally + { + if (usecopy) + { + LOCK.readLock().unlock(); + } + } + } + + @Override + public boolean hasNext() + { + return (currentPosition < vcontigs.size()); + } + + @Override + public int[] next() + { + int[] result = vcontigs.get(currentPosition); + currentPosition++; + return result; + } + + public boolean endsAtHidden() + { + return endsAtHidden; + } + } + } diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java index f61c7c6..2c8a5df 100755 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@ -22,6 +22,7 @@ package jalview.gui; import jalview.datamodel.AlignmentI; import jalview.datamodel.HiddenColumns; +import jalview.datamodel.HiddenColumns.VisibleBlocksVisBoundsIterator; import jalview.datamodel.SearchResultsI; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; @@ -853,28 +854,33 @@ public class SeqCanvas extends JComponent implements ViewportListenerI int screenY = 0; final int screenYMax = endRes - startRes; int blockStart = startRes; - int blockEnd = endRes; + int blockEnd = endRes; // equals blockStart + screenYMax - screenY; HiddenColumns hidden = av.getAlignment().getHiddenColumns(); - Iterator regions = hidden.iterator(); + VisibleBlocksVisBoundsIterator regions = (VisibleBlocksVisBoundsIterator) hidden + .getVisibleBlocksIterator(startRes, endRes, true);// hidden.iterator(); while (regions.hasNext()) { int[] region = regions.next(); - int hideStart = region[0]; + blockEnd = region[1]; + blockStart = region[0]; +/* int hideStart = region[0]; int hideEnd = region[1]; if (hideStart <= blockStart) { - blockStart += (hideEnd - hideStart) + 1; + blockStart += (hideEnd - hideStart) + 1; // convert startRes to an + // absolute value + blockEnd += (hideEnd - hideStart) + 1; continue; } - +*/ /* * draw up to just before the next hidden region, or the end of * the visible region, whichever comes first */ - blockEnd = Math.min(hideStart - 1, - blockStart + screenYMax - screenY); +// blockEnd = Math.min(hideStart - 1, +// blockEnd); g1.translate(screenY * charWidth, 0); draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset); @@ -883,7 +889,9 @@ public class SeqCanvas extends JComponent implements ViewportListenerI * draw the downline of the hidden column marker (ScalePanel draws the * triangle on top) if we reached it */ - if (av.getShowHiddenMarkers() && blockEnd == hideStart - 1) + if (av.getShowHiddenMarkers() + && (regions.hasNext() || regions.endsAtHidden()))// blockEnd == + // hideStart - 1) { g1.setColor(Color.blue); @@ -894,24 +902,25 @@ public class SeqCanvas extends JComponent implements ViewportListenerI g1.translate(-screenY * charWidth, 0); screenY += blockEnd - blockStart + 1; - blockStart = hideEnd + 1; - + /* blockStart = hideEnd + 1; + blockEnd = blockStart + screenYMax - screenY; + if (screenY > screenYMax) { // already rendered last block return; - } + }*/ } - if (screenY <= screenYMax) + /* if (screenY <= screenYMax) { // remaining visible region to render blockEnd = blockStart + screenYMax - screenY; g1.translate(screenY * charWidth, 0); draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset); - + g1.translate(-screenY * charWidth, 0); - } + }*/ } } -- 1.7.10.2