Fix scrolling in NavigationTable

On Mac Chrome using the native scrollIntoView() method causes the
browser to scroll the page to make the top of the selected row the top
of the window.  Clicking on a row in My Changes for example scrolls
the window to make the row at the immediate top of the window, hiding
all content above it.

This algorithm is optimal if the position being moved to is a section
header of a long chunk of text, it minimizes the number of jumps of
the view.  It doesn't work as well for tables.

Rewrite the scroll logic to center the selected row into the middle of
the vertical height, but only adjust the scroll bars if the element is
currently obsecured from view.  This causes very tall tables to jump
every half screen, but the prior half is still visible above the new
position.  I think this works better for navigating large tables of
changes and files.

Change-Id: I5b1aeaf2d2a6a5a2ee962e29b6332732273fecbc
This commit is contained in:
Shawn Pearce
2013-07-19 17:55:04 -07:00
parent ce6c264029
commit e8edbcc1cd

View File

@@ -22,6 +22,7 @@ import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ScrollPanel;
@@ -231,13 +232,41 @@ public abstract class NavigationTable<RowItem> extends FancyFlexTable<RowItem> {
}
});
} else {
scrollIntoView0(tr);
int rt = tr.getAbsoluteTop();
int rl = tr.getAbsoluteLeft();
int rb = tr.getAbsoluteBottom();
int wt = Window.getScrollTop();
int wl = Window.getScrollLeft();
int wh = Window.getClientHeight();
int ww = Window.getClientWidth();
int wb = wt + wh;
// If the row is partially or fully obscured, scroll:
//
// rl < wl: Row left edge is off screen to left.
// rt < wt: Row top is above top of window.
// wb < rt: Row top is below bottom of window.
// wb < rb: Row bottom is below bottom of window.
if (rl < wl || rt < wt || wb < rt || wb < rb) {
if (rl < wl) {
// Left edge needs to move to make it visible.
// If the row fully fits in the window, set 0.
if (tr.getAbsoluteRight() < ww) {
wl = 0;
} else {
wl = Math.max(tr.getAbsoluteLeft() - 5, 0);
}
}
// Vertically center the row in the window.
int h = (wh - (rb - rt)) / 2;
Window.scrollTo(wl, Math.max(rt - h, 0));
}
}
}
private static final native void scrollIntoView0(Element e)
/*-{ if (e.scrollIntoView) e.scrollIntoView() }-*/;
protected void movePointerTo(final Object oldId) {
final int row = findRow(oldId);
if (0 <= row) {