/**
* Callback that notifies when the cursor is on top of a new row or column
* because of the automatic scrolling.
- *
- * @since
*/
public interface AutoScrollerCallback {
/**
- * Triggered when doing automatic horizontal scrolling.
+ * Triggered when doing automatic scrolling.
+ * <p>
+ * Because the auto scroller currently only supports scrolling in one
+ * axis, this method is used for both vertical and horizontal scrolling.
*
* @param scrollDiff
* the amount of pixels that have been auto scrolled since
* last call
*/
- void onHorizontalAutoScroll(int scrollDiff);
+ void onAutoScroll(int scrollDiff);
/**
- * Triggered when doing automatic vertical scrolling.
- *
- * @param scrollDiff
- * the amount of pixels that have been auto scrolled since
- * last call
+ * Triggered when the grid scroll has reached the minimum scroll
+ * position. Depending on the scroll axis, either scrollLeft or
+ * scrollTop is 0.
*/
- void onVerticalAutoScroll(int scrollDiff);
+ void onAutoScrollReachedMin();
+
+ /**
+ * Triggered when the grid scroll has reached the max scroll position.
+ * Depending on the scroll axis, either scrollLeft or scrollTop is at
+ * its maximum value.
+ */
+ void onAutoScrollReachedMax();
}
public enum ScrollAxis {
pixelsToScroll -= intPixelsToScroll;
if (intPixelsToScroll != 0) {
+ double scrollPos;
+ double maxScrollPos;
+ double newScrollPos;
if (scrollDirection == ScrollAxis.VERTICAL) {
- grid.setScrollTop(grid.getScrollTop() + intPixelsToScroll);
- callback.onVerticalAutoScroll(intPixelsToScroll);
+ scrollPos = grid.getScrollTop();
+ maxScrollPos = getMaxScrollTop();
} else {
- grid.setScrollLeft(grid.getScrollLeft() + intPixelsToScroll);
- callback.onHorizontalAutoScroll(intPixelsToScroll);
+ scrollPos = grid.getScrollLeft();
+ maxScrollPos = getMaxScrollLeft();
+ }
+ if (intPixelsToScroll > 0 && scrollPos < maxScrollPos
+ || intPixelsToScroll < 0 && scrollPos > 0) {
+ newScrollPos = scrollPos + intPixelsToScroll;
+ if (scrollDirection == ScrollAxis.VERTICAL) {
+ grid.setScrollTop(newScrollPos);
+ } else {
+ grid.setScrollLeft(newScrollPos);
+ }
+ callback.onAutoScroll(intPixelsToScroll);
+ if (newScrollPos <= 0) {
+ callback.onAutoScrollReachedMin();
+ } else if (newScrollPos >= maxScrollPos) {
+ callback.onAutoScrollReachedMax();
+ }
}
}
private void updateScrollBounds() {
double startBorder = getBodyClientStart();
final int endBorder = getBodyClientEnd();
-
- for (int i = 0; i < grid.getFrozenColumnCount(); i++) {
- startBorder += grid.getColumn(i).getWidthActual();
- }
+ startBorder += getFrozenColumnsWidth();
final int scrollCompensation = getScrollCompensation();
startingBound = scrollCompensation + startBorder + scrollAreaPX;
return getClientLeft(getTbodyElement());
}
}
+
+ private double getFrozenColumnsWidth() {
+ double value = 0;
+ for (int i = 0; i < grid.getFrozenColumnCount(); i++) {
+ value += grid.getColumn(i).getWidthActual();
+ }
+ return value;
+ }
+
+ private double getMaxScrollLeft() {
+ return grid.getScrollWidth()
+ - (getTableElement().getParentElement().getOffsetWidth() - getFrozenColumnsWidth());
+ }
+
+ private double getMaxScrollTop() {
+ return grid.getScrollHeight() - getTfootElement().getOffsetHeight()
+ - getTheadElement().getOffsetHeight();
+ }
}
horizontalScrollbar.setScrollPos(scrollLeft);
}
+ /**
+ * Returns the scroll width for the escalator. Note that this is not
+ * necessary the same as {@code Element.scrollWidth} in the DOM.
+ *
+ * @since
+ * @return the scroll width in pixels
+ */
+ public double getScrollWidth() {
+ return horizontalScrollbar.getScrollSize();
+ }
+
+ /**
+ * Returns the scroll height for the escalator. Note that this is not
+ * necessary the same as {@code Element.scrollHeight} in the DOM.
+ *
+ * @since
+ * @return the scroll height in pixels
+ */
+ public double getScrollHeight() {
+ return verticalScrollbar.getScrollSize();
+ }
+
/**
* Scrolls the body horizontally so that the column at the given index is
* visible and there is at least {@code padding} pixels in the direction of
private final AutoScrollerCallback autoScrollerCallback = new AutoScrollerCallback() {
@Override
- public void onVerticalAutoScroll(int scrollDiff) {
- // NOP
+ public void onAutoScroll(int scrollDiff) {
+ autoScrollX = scrollDiff;
+ onDragUpdate(null);
}
@Override
- public void onHorizontalAutoScroll(int scrollDiff) {
- onDragUpdate(null);
+ public void onAutoScrollReachedMin() {
+ // make sure the drop marker is visible on the left
+ autoScrollX = 0;
+ updateDragDropMarker(clientX);
+ }
+
+ @Override
+ public void onAutoScrollReachedMax() {
+ // make sure the drop marker is visible on the right
+ autoScrollX = 0;
+ updateDragDropMarker(clientX);
}
};
/**
private int clientX;
+ /** How much the grid is being auto scrolled while dragging. */
+ private int autoScrollX;
+
private void initHeaderDragElementDOM() {
if (table == null) {
tableHeader = DOM.createTHead();
if (event != null) {
clientX = WidgetUtil.getTouchOrMouseClientX(event
.getNativeEvent());
+ autoScrollX = 0;
}
resolveDragElementHorizontalPosition(clientX);
updateDragDropMarker(clientX);
dropMarkerLeft += cellWidth;
}
}
+ dropMarkerLeft += autoScrollX;
if (dropMarkerLeft > header.getElement().getOffsetWidth()
|| dropMarkerLeft < 0) {
dropMarkerLeft = -10000000;
final int focusedRowIndex = focusedCell.getRow();
final int draggedColumnIndex = eventCell.getColumnIndex();
// transfer focus if it was effected by the new column order
- // FIXME if the dragged column is partly outside of the view
- // port and the focused cell is +-1 of the dragged column, the
- // grid scrolls to the right end. maybe fixed when the automatic
- // scroll handling is implemented?
final RowContainer rowContainer = escalator
.findRowContainer(focusedCell.getElement());
if (focusedCellColumnIndex == draggedColumnIndex) {
&& draggedColumnIndex < focusedCellColumnIndex) {
cellFocusHandler.setCellFocus(focusedRowIndex,
focusedCellColumnIndex - 1, rowContainer);
- } else {
- cellFocusHandler.setCellFocus(focusedRowIndex,
- focusedCellColumnIndex, rowContainer);
}
}
}
return escalator.getScrollLeft();
}
+ /**
+ * Returns the height of the scrollable area in pixels.
+ *
+ * @since
+ * @return the height of the scrollable area in pixels
+ */
+ public double getScrollHeight() {
+ return escalator.getScrollHeight();
+ }
+
+ /**
+ * Returns the width of the scrollable area in pixels.
+ *
+ * @since
+ * @return the width of the scrollable area in pixels.
+ */
+ public double getScrollWidth() {
+ return escalator.getScrollWidth();
+ }
+
private static final Logger getLogger() {
return Logger.getLogger(Grid.class.getName());
}