X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fviewmodel%2FViewportRanges.java;h=24ff57f46861e3ffed3004250946f89b97892260;hb=f8b17a9e7363b8a9e7cd12d61bc6d611c7c97d7d;hp=56c1d39e789a7eb02e63252dfbdd5ca9b0bd1b38;hpb=2b2c9e1a88930585de0b5c205e4ae6f0174440d2;p=jalview.git diff --git a/src/jalview/viewmodel/ViewportRanges.java b/src/jalview/viewmodel/ViewportRanges.java index 56c1d39..24ff57f 100644 --- a/src/jalview/viewmodel/ViewportRanges.java +++ b/src/jalview/viewmodel/ViewportRanges.java @@ -32,6 +32,16 @@ import jalview.datamodel.HiddenColumns; */ public class ViewportRanges extends ViewportProperties { + public static final String STARTRES = "startres"; + + public static final String ENDRES = "endres"; + + public static final String STARTSEQ = "startseq"; + + public static final String ENDSEQ = "endseq"; + + private boolean wrappedMode = false; + // start residue of viewport private int startRes; @@ -121,9 +131,14 @@ public class ViewportRanges extends ViewportProperties public void setStartEndRes(int start, int end) { int oldstartres = this.startRes; - if (start > getVisibleAlignmentWidth() - 1) + + /* + * if not wrapped, don't leave white space at the right margin + */ + int lastColumn = getVisibleAlignmentWidth() - 1; + if (!wrappedMode && (start > lastColumn)) { - startRes = getVisibleAlignmentWidth() - 1; + startRes = Math.max(lastColumn, 0); } else if (start < 0) { @@ -139,38 +154,25 @@ public class ViewportRanges extends ViewportProperties { endRes = 0; } + else if (!wrappedMode && (end > lastColumn)) + { + endRes = Math.max(lastColumn, 0); + } else { endRes = end; } - changeSupport.firePropertyChange("startres", oldstartres, startRes); + changeSupport.firePropertyChange(STARTRES, oldstartres, startRes); if (oldstartres == startRes) { // event won't be fired if start positions are same // fire an event for the end positions in case they changed - changeSupport.firePropertyChange("endres", oldendres, endRes); + changeSupport.firePropertyChange(ENDRES, oldendres, endRes); } } /** - * Set last residue visible in the viewport. Fires a property change event. - * - * @param res - * residue position - */ - public void setEndRes(int res) - { - int startres = res; - int width = getViewportWidth(); - if (startres + width - 1 > getVisibleAlignmentWidth() - 1) - { - startres = getVisibleAlignmentWidth() - width; - } - setStartEndRes(startres - width + 1, startres); - } - - /** * Set the first sequence visible in the viewport, maintaining the height. If * the viewport would extend past the last sequence, sets the viewport so it * sits at the bottom of the alignment. Fires a property change event. @@ -202,9 +204,10 @@ public class ViewportRanges extends ViewportProperties public void setStartEndSeq(int start, int end) { int oldstartseq = this.startSeq; - if (start > getVisibleAlignmentHeight() - 1) + int visibleHeight = getVisibleAlignmentHeight(); + if (start > visibleHeight - 1) { - startSeq = getVisibleAlignmentHeight() - 1; + startSeq = Math.max(visibleHeight - 1, 0); } else if (start < 0) { @@ -216,9 +219,9 @@ public class ViewportRanges extends ViewportProperties } int oldendseq = this.endSeq; - if (end >= getVisibleAlignmentHeight()) + if (end >= visibleHeight) { - endSeq = getVisibleAlignmentHeight() - 1; + endSeq = Math.max(visibleHeight - 1, 0); } else if (end < 0) { @@ -229,12 +232,12 @@ public class ViewportRanges extends ViewportProperties endSeq = end; } - changeSupport.firePropertyChange("startseq", oldstartseq, startSeq); + changeSupport.firePropertyChange(STARTSEQ, oldstartseq, startSeq); if (oldstartseq == startSeq) { // event won't be fired if start positions are the same // fire in case the end positions changed - changeSupport.firePropertyChange("endseq", oldendseq, endSeq); + changeSupport.firePropertyChange(ENDSEQ, oldendseq, endSeq); } } @@ -326,9 +329,18 @@ public class ViewportRanges extends ViewportProperties { vpstart = 0; } - else if (vpstart + w - 1 > getVisibleAlignmentWidth() - 1) + + /* + * if not wrapped, don't leave white space at the right margin + */ + if (!wrappedMode) { - vpstart = getVisibleAlignmentWidth() - 1; + if ((w <= getVisibleAlignmentWidth()) + && (vpstart + w - 1 > getVisibleAlignmentWidth() - 1)) + { + vpstart = getVisibleAlignmentWidth() - w; + } + } setStartEndRes(vpstart, vpstart + w - 1); } @@ -350,7 +362,10 @@ public class ViewportRanges extends ViewportProperties { vpstart = 0; } - else if (vpstart + h - 1 > getVisibleAlignmentHeight() - 1) + else if ((h <= getVisibleAlignmentHeight()) + && (vpstart + h - 1 > getVisibleAlignmentHeight() - 1)) + // viewport height is less than the full alignment and we are running off + // the bottom { vpstart = getVisibleAlignmentHeight() - h; } @@ -387,23 +402,39 @@ public class ViewportRanges extends ViewportProperties */ public boolean scrollUp(boolean up) { + /* + * if in unwrapped mode, scroll up or down one sequence row; + * if in wrapped mode, scroll by one visible width of columns + */ if (up) { - if (startSeq < 1) + if (wrappedMode) { - return false; + pageUp(); + } + else + { + if (startSeq < 1) + { + return false; + } + setStartSeq(startSeq - 1); } - - setStartSeq(startSeq - 1); } else { - if (endSeq >= getVisibleAlignmentHeight() - 1) + if (wrappedMode) { - return false; + pageDown(); + } + else + { + if (endSeq >= getVisibleAlignmentHeight() - 1) + { + return false; + } + setStartSeq(startSeq + 1); } - - setStartSeq(startSeq + 1); } return true; } @@ -429,7 +460,7 @@ public class ViewportRanges extends ViewportProperties } else { - if (endRes > getVisibleAlignmentWidth() - 1) + if (endRes >= getVisibleAlignmentWidth() - 1) { return false; } @@ -441,18 +472,42 @@ public class ViewportRanges extends ViewportProperties } /** - * Scroll a wrapped alignment so that the specified residue is visible. Fires - * a property change event. + * Scroll a wrapped alignment so that the specified residue is in the first + * repeat of the wrapped view. Fires a property change event. Answers true if + * the startRes changed, else false. * * @param res * residue position to scroll to + * @return */ - public void scrollToWrappedVisible(int res) + public boolean scrollToWrappedVisible(int res) { - // get the start residue of the wrapped row which res is in - // and set that as our start residue + int oldStartRes = startRes; int width = getViewportWidth(); - setStartRes((res / width) * width); + + if (res >= oldStartRes && res < oldStartRes + width) + { + return false; + } + + boolean up = res < oldStartRes; + int widthsToScroll = Math.abs((res - oldStartRes) / width); + if (up) + { + widthsToScroll++; + } + + int residuesToScroll = width * widthsToScroll; + int newStartRes = up ? oldStartRes - residuesToScroll : oldStartRes + + residuesToScroll; + if (newStartRes < 0) + { + newStartRes = 0; + } + + setStartRes(newStartRes); + + return true; } /** @@ -490,20 +545,116 @@ public class ViewportRanges extends ViewportProperties } } } - + /** * Adjust sequence position for page up. Fires a property change event. */ public void pageUp() { - setViewportStartAndHeight(2 * startSeq - endSeq, getViewportHeight()); + if (wrappedMode) + { + setStartRes(Math.max(0, getStartRes() - getViewportWidth())); + } + else + { + setViewportStartAndHeight(startSeq - (endSeq - startSeq), + getViewportHeight()); + } } - + /** * Adjust sequence position for page down. Fires a property change event. */ public void pageDown() { - setViewportStartAndHeight(endSeq, getViewportHeight()); + if (wrappedMode) + { + /* + * if height is more than width (i.e. not all sequences fit on screen), + * increase page down to height + */ + int newStart = getStartRes() + + Math.max(getViewportHeight(), getViewportWidth()); + + /* + * don't page down beyond end of alignment, or if not all + * sequences fit in the visible height + */ + if (newStart < getVisibleAlignmentWidth()) + { + setStartRes(newStart); + } + } + else + { + setViewportStartAndHeight(endSeq, getViewportHeight()); + } + } + + public void setWrappedMode(boolean wrapped) + { + wrappedMode = wrapped; + } + + public boolean isWrappedMode() + { + return wrappedMode; + } + + /** + * Answers the vertical scroll position (0..) to set, given the visible column + * that is at top left. + * + *
+   * Example:
+   *    viewport width 40 columns (0-39, 40-79, 80-119...)
+   *    column 0 returns scroll position 0
+   *    columns 1-40 return scroll position 1
+   *    columns 41-80 return scroll position 2
+   *    etc
+   * 
+ * + * @param topLeftColumn + * (0..) + * @return + */ + public int getWrappedScrollPosition(final int topLeftColumn) + { + int w = getViewportWidth(); + + /* + * visible whole widths + */ + int scroll = topLeftColumn / w; + + /* + * add 1 for a part width if there is one + */ + scroll += topLeftColumn % w > 0 ? 1 : 0; + + return scroll; + } + + /** + * Answers the maximum wrapped vertical scroll value, given the column + * position (0..) to show at top left of the visible region. + * + * @param topLeftColumn + * @return + */ + public int getWrappedMaxScroll(int topLeftColumn) + { + int scrollPosition = getWrappedScrollPosition(topLeftColumn); + + /* + * how many more widths could be drawn after this one? + */ + int columnsRemaining = getVisibleAlignmentWidth() - topLeftColumn; + int width = getViewportWidth(); + int widthsRemaining = columnsRemaining / width + + (columnsRemaining % width > 0 ? 1 : 0) - 1; + int maxScroll = scrollPosition + widthsRemaining; + + return maxScroll; } }