aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Paul <henrik@vaadin.com>2014-10-16 14:04:25 +0300
committerVaadin Code Review <review@vaadin.com>2014-10-28 09:17:56 +0000
commit910f00d22208da68d3c327b35d93c4893df7e90d (patch)
tree4fedcfd2d2b5f2edc06c46cc84b6ead7d14ae63a
parent7540efb2c5f42ede2af51dadba2382c21e075203 (diff)
downloadvaadin-framework-910f00d22208da68d3c327b35d93c4893df7e90d.tar.gz
vaadin-framework-910f00d22208da68d3c327b35d93c4893df7e90d.zip
Drag selection now selects all rows in between two frames (#13334)
Change-Id: I0a25cd26a5190be744e6258e29b0560106425932
-rw-r--r--client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java130
1 files changed, 87 insertions, 43 deletions
diff --git a/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java b/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java
index b059beca54..f27c973db6 100644
--- a/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java
+++ b/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java
@@ -26,6 +26,7 @@ import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.TableElement;
+import com.google.gwt.dom.client.TableSectionElement;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
@@ -211,14 +212,14 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
/** The handle in which this instance is running. */
private AnimationHandle handle;
- /** The pointer's pageX coordinate. */
- private int pageX;
+ /** The pointer's pageX coordinate of the first click. */
+ private int initialPageX = -1;
/** The pointer's pageY coordinate. */
private int pageY;
/** The logical index of the row that was most recently modified. */
- private int logicalRow = -1;
+ private int lastModifiedLogicalRow = -1;
/** @see #doScrollAreaChecks(int) */
private int finalTopBound;
@@ -228,6 +229,9 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
private boolean scrollAreaShouldRebound = false;
+ private final int bodyAbsoluteTop;
+ private final int bodyAbsoluteBottom;
+
public AutoScrollerAndSelector(final int topBound,
final int bottomBound, final int gradientArea,
final boolean selectionPaint) {
@@ -235,6 +239,9 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
finalBottomBound = bottomBound;
this.gradientArea = gradientArea;
this.selectionPaint = selectionPaint;
+
+ bodyAbsoluteTop = getBodyClientTop();
+ bodyAbsoluteBottom = getBodyClientBottom();
}
@Override
@@ -252,11 +259,23 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
grid.setScrollTop(grid.getScrollTop() + intPixelsToScroll);
}
- int logicalRow = getLogicalRowIndex(Util.getElementFromPoint(pageX,
- pageY));
- if (logicalRow != -1 && logicalRow != this.logicalRow) {
- this.logicalRow = logicalRow;
- setSelected(logicalRow, selectionPaint);
+ int constrainedPageY = Math.max(bodyAbsoluteTop,
+ Math.min(bodyAbsoluteBottom, pageY));
+ int logicalRow = getLogicalRowIndex(Util.getElementFromPoint(
+ initialPageX, constrainedPageY));
+
+ int incrementOrDecrement = (logicalRow > lastModifiedLogicalRow) ? 1
+ : -1;
+
+ /*
+ * Both pageY and initialPageX have their initialized (and
+ * unupdated) values while the cursor hasn't moved since the first
+ * invocation. This will lead to logicalRow being -1, until the
+ * pointer has been moved.
+ */
+ while (logicalRow != -1 && lastModifiedLogicalRow != logicalRow) {
+ lastModifiedLogicalRow += incrementOrDecrement;
+ setSelected(lastModifiedLogicalRow, selectionPaint);
}
reschedule();
@@ -307,7 +326,7 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
public void start(int logicalRowIndex) {
running = true;
setSelected(logicalRowIndex, selectionPaint);
- logicalRow = logicalRowIndex;
+ lastModifiedLogicalRow = logicalRowIndex;
reschedule();
}
@@ -332,8 +351,11 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
public void updatePointerCoords(int pageX, int pageY) {
doScrollAreaChecks(pageY);
updateScrollSpeed(pageY);
- this.pageX = pageX;
this.pageY = pageY;
+
+ if (initialPageX == -1) {
+ initialPageX = pageX;
+ }
}
/**
@@ -469,25 +491,8 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
}
private void updateScrollBounds() {
- final Element root = Element.as(grid.getElement());
- final Element tableWrapper = Element.as(root.getChild(2));
- final TableElement table = TableElement.as(tableWrapper
- .getFirstChildElement());
- final Element thead = table.getTHead();
- final Element tfoot = table.getTFoot();
-
- /*
- * GWT _does_ have an "Element.getAbsoluteTop()" that takes both the
- * client top and scroll compensation into account, but they're
- * calculated wrong for our purposes, so this does something
- * similar, but only suitable for us.
- *
- * Also, this should be a bit faster, since the scroll compensation
- * is calculated only once and used in two places.
- */
-
- final int topBorder = getClientTop(root) + thead.getOffsetHeight();
- final int bottomBorder = getClientTop(tfoot);
+ final int topBorder = getBodyClientTop();
+ final int bottomBorder = getBodyClientBottom();
final int scrollCompensation = getScrollCompensation();
topBound = scrollCompensation + topBorder + SCROLL_AREA_GRADIENT_PX;
@@ -505,17 +510,6 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
}
}
- /** Get the "top" of an element in relation to "client" coordinates. */
- private int getClientTop(final Element e) {
- Element cursor = e;
- int top = 0;
- while (cursor != null) {
- top += cursor.getOffsetTop();
- cursor = cursor.getOffsetParent();
- }
- return top;
- }
-
private int getScrollCompensation() {
Element cursor = grid.getElement();
int scroll = 0;
@@ -679,6 +673,10 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
}
private int getLogicalRowIndex(final Element target) {
+ if (target == null) {
+ return -1;
+ }
+
/*
* We can't simply go backwards until we find a <tr> first element,
* because of the table-in-table scenario. We need to, unfortunately, go
@@ -701,18 +699,64 @@ public class MultiSelectionRenderer<T> extends ComplexRenderer<Boolean> {
return -1;
}
- private Element getTbodyElement() {
+ private TableElement getTableElement() {
final Element root = grid.getElement();
final Element tablewrapper = Element.as(root.getChild(2));
if (tablewrapper != null) {
- final TableElement table = TableElement.as(tablewrapper
- .getFirstChildElement());
+ return TableElement.as(tablewrapper.getFirstChildElement());
+ } else {
+ return null;
+ }
+ }
+
+ private TableSectionElement getTbodyElement() {
+ TableElement table = getTableElement();
+ if (table != null) {
return table.getTBodies().getItem(0);
} else {
return null;
}
}
+ private TableSectionElement getTheadElement() {
+ TableElement table = getTableElement();
+ if (table != null) {
+ return table.getTHead();
+ } else {
+ return null;
+ }
+ }
+
+ private TableSectionElement getTfootElement() {
+ TableElement table = getTableElement();
+ if (table != null) {
+ return table.getTFoot();
+ } else {
+ return null;
+ }
+ }
+
+ /** Get the "top" of an element in relation to "client" coordinates. */
+ @SuppressWarnings("static-method")
+ private int getClientTop(final Element e) {
+ Element cursor = e;
+ int top = 0;
+ while (cursor != null) {
+ top += cursor.getOffsetTop();
+ cursor = cursor.getOffsetParent();
+ }
+ return top;
+ }
+
+ private int getBodyClientBottom() {
+ return getClientTop(getTfootElement()) - 1;
+ }
+
+ private int getBodyClientTop() {
+ return getClientTop(grid.getElement())
+ + getTheadElement().getOffsetHeight();
+ }
+
protected boolean isSelected(final int logicalRow) {
return grid.isSelected(grid.getDataSource().getRow(logicalRow));
}