summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorGuillermo Alvarez <guillermo@vaadin.com>2014-08-19 18:38:35 +0300
committerSauli Tähkäpää <sauli@vaadin.com>2014-09-12 16:16:10 +0300
commit6877a4d8802f9fae2b54e390e5171a1df705253d (patch)
tree01ae203b716290ab0e6f27f0dd94fefa3c4f1a4c /client
parent9126b9fc10b3fc5b3b71527073262c07dfc066a5 (diff)
downloadvaadin-framework-6877a4d8802f9fae2b54e390e5171a1df705253d.tar.gz
vaadin-framework-6877a4d8802f9fae2b54e390e5171a1df705253d.zip
Table handles both onMouseDown and onMouseUp events (#14347)
Now it has the same behaviour that the layout, and checks that the element under the mouse matches to complete the click action Change-Id: I9c61dac24479913c1bb1094edaf8878749984342
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/ui/VScrollTable.java287
1 files changed, 188 insertions, 99 deletions
diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java
index cb90823a7f..e7d760cc4e 100644
--- a/client/src/com/vaadin/client/ui/VScrollTable.java
+++ b/client/src/com/vaadin/client/ui/VScrollTable.java
@@ -25,6 +25,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.Scheduler;
@@ -66,6 +68,8 @@ import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Event.NativePreviewEvent;
+import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
@@ -763,6 +767,51 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
private HandlerRegistration addCloseHandler;
+ /**
+ * Changes to manage mouseDown and mouseUp
+ */
+ /**
+ * The element where the last mouse down event was registered.
+ */
+ private Element lastMouseDownTarget;
+
+ /**
+ * Set to true by {@link #mouseUpPreviewHandler} if it gets a mouseup at the
+ * same element as {@link #lastMouseDownTarget}.
+ */
+ private boolean mouseUpPreviewMatched = false;
+
+ private HandlerRegistration mouseUpEventPreviewRegistration;
+
+ /**
+ * Previews events after a mousedown to detect where the following mouseup
+ * hits.
+ */
+ private final NativePreviewHandler mouseUpPreviewHandler = new NativePreviewHandler() {
+
+ @Override
+ public void onPreviewNativeEvent(NativePreviewEvent event) {
+ if (event.getTypeInt() == Event.ONMOUSEUP) {
+ mouseUpEventPreviewRegistration.removeHandler();
+
+ // Event's reported target not always correct if event
+ // capture is in use
+ Element elementUnderMouse = Util.getElementUnderMouse(event
+ .getNativeEvent());
+ if (lastMouseDownTarget != null
+ && lastMouseDownTarget.isOrHasChild(elementUnderMouse)) {
+ mouseUpPreviewMatched = true;
+ } else {
+ getLogger().log(
+ Level.FINEST,
+ "Ignoring mouseup from " + elementUnderMouse
+ + " when mousedown was on "
+ + lastMouseDownTarget);
+ }
+ }
+ }
+ };
+
public VScrollTable() {
setMultiSelectMode(MULTISELECT_MODE_DEFAULT);
@@ -5922,114 +5971,134 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
break;
case Event.ONMOUSEUP:
- if (targetCellOrRowFound) {
- /*
- * Queue here, send at the same time as the
- * corresponding value change event - see #7127
- */
- boolean clickEventSent = handleClickEvent(event,
- targetTdOrTr, false);
-
- if (event.getButton() == Event.BUTTON_LEFT
- && isSelectable()) {
-
- // Ctrl+Shift click
- if ((event.getCtrlKey() || event.getMetaKey())
- && event.getShiftKey()
- && isMultiSelectModeDefault()) {
- toggleShiftSelection(false);
- setRowFocus(this);
-
- // Ctrl click
- } else if ((event.getCtrlKey() || event
- .getMetaKey())
- && isMultiSelectModeDefault()) {
- boolean wasSelected = isSelected();
- toggleSelection();
- setRowFocus(this);
- /*
- * next possible range select must start on
- * this row
- */
- selectionRangeStart = this;
- if (wasSelected) {
- removeRowFromUnsentSelectionRanges(this);
- }
+ /*
+ * Only fire a click if the mouseup hits the same
+ * element as the corresponding mousedown. This is first
+ * checked in the event preview but we can't fire the
+ * event there as the event might get canceled before it
+ * gets here.
+ */
+ if (mouseUpPreviewMatched
+ && lastMouseDownTarget != null
+ && lastMouseDownTarget == getElementTdOrTr(Util
+ .getElementUnderMouse(event))) {
+ // "Click" with left, right or middle button
+
+ if (targetCellOrRowFound) {
+ /*
+ * Queue here, send at the same time as the
+ * corresponding value change event - see #7127
+ */
+ boolean clickEventSent = handleClickEvent(
+ event, targetTdOrTr, false);
+
+ if (event.getButton() == Event.BUTTON_LEFT
+ && isSelectable()) {
+
+ // Ctrl+Shift click
+ if ((event.getCtrlKey() || event
+ .getMetaKey())
+ && event.getShiftKey()
+ && isMultiSelectModeDefault()) {
+ toggleShiftSelection(false);
+ setRowFocus(this);
- } else if ((event.getCtrlKey() || event
- .getMetaKey()) && isSingleSelectMode()) {
- // Ctrl (or meta) click (Single selection)
- if (!isSelected()
- || (isSelected() && nullSelectionAllowed)) {
+ // Ctrl click
+ } else if ((event.getCtrlKey() || event
+ .getMetaKey())
+ && isMultiSelectModeDefault()) {
+ boolean wasSelected = isSelected();
+ toggleSelection();
+ setRowFocus(this);
+ /*
+ * next possible range select must start
+ * on this row
+ */
+ selectionRangeStart = this;
+ if (wasSelected) {
+ removeRowFromUnsentSelectionRanges(this);
+ }
- if (!isSelected()) {
- deselectAll();
+ } else if ((event.getCtrlKey() || event
+ .getMetaKey())
+ && isSingleSelectMode()) {
+ // Ctrl (or meta) click (Single
+ // selection)
+ if (!isSelected()
+ || (isSelected() && nullSelectionAllowed)) {
+
+ if (!isSelected()) {
+ deselectAll();
+ }
+
+ toggleSelection();
+ setRowFocus(this);
}
- toggleSelection();
+ } else if (event.getShiftKey()
+ && isMultiSelectModeDefault()) {
+ // Shift click
+ toggleShiftSelection(true);
+
+ } else {
+ // click
+ boolean currentlyJustThisRowSelected = selectedRowKeys
+ .size() == 1
+ && selectedRowKeys
+ .contains(getKey());
+
+ if (!currentlyJustThisRowSelected) {
+ if (isSingleSelectMode()
+ || isMultiSelectModeDefault()) {
+ /*
+ * For default multi select mode
+ * (ctrl/shift) and for single
+ * select mode we need to clear
+ * the previous selection before
+ * selecting a new one when the
+ * user clicks on a row. Only in
+ * multiselect/simple mode the
+ * old selection should remain
+ * after a normal click.
+ */
+ deselectAll();
+ }
+ toggleSelection();
+ } else if ((isSingleSelectMode() || isMultiSelectModeSimple())
+ && nullSelectionAllowed) {
+ toggleSelection();
+ }/*
+ * else NOP to avoid excessive server
+ * visits (selection is removed with
+ * CTRL/META click)
+ */
+
+ selectionRangeStart = this;
setRowFocus(this);
}
- } else if (event.getShiftKey()
- && isMultiSelectModeDefault()) {
- // Shift click
- toggleShiftSelection(true);
-
- } else {
- // click
- boolean currentlyJustThisRowSelected = selectedRowKeys
- .size() == 1
- && selectedRowKeys
- .contains(getKey());
-
- if (!currentlyJustThisRowSelected) {
- if (isSingleSelectMode()
- || isMultiSelectModeDefault()) {
- /*
- * For default multi select mode
- * (ctrl/shift) and for single
- * select mode we need to clear the
- * previous selection before
- * selecting a new one when the user
- * clicks on a row. Only in
- * multiselect/simple mode the old
- * selection should remain after a
- * normal click.
- */
- deselectAll();
- }
- toggleSelection();
- } else if ((isSingleSelectMode() || isMultiSelectModeSimple())
- && nullSelectionAllowed) {
- toggleSelection();
- }/*
- * else NOP to avoid excessive server
- * visits (selection is removed with
- * CTRL/META click)
- */
-
- selectionRangeStart = this;
- setRowFocus(this);
+ // Remove IE text selection hack
+ if (BrowserInfo.get().isIE()) {
+ ((Element) event.getEventTarget()
+ .cast()).setPropertyJSO(
+ "onselectstart", null);
+ }
+ // Queue value change
+ sendSelectedRows(false);
}
-
- // Remove IE text selection hack
- if (BrowserInfo.get().isIE()) {
- ((Element) event.getEventTarget().cast())
- .setPropertyJSO("onselectstart",
- null);
+ /*
+ * Send queued click and value change events if
+ * any If a click event is sent, send value
+ * change with it regardless of the immediate
+ * flag, see #7127
+ */
+ if (immediate || clickEventSent) {
+ client.sendPendingVariableChanges();
}
- // Queue value change
- sendSelectedRows(false);
- }
- /*
- * Send queued click and value change events if any
- * If a click event is sent, send value change with
- * it regardless of the immediate flag, see #7127
- */
- if (immediate || clickEventSent) {
- client.sendPendingVariableChanges();
}
}
+ mouseUpPreviewMatched = false;
+ lastMouseDownTarget = null;
break;
case Event.ONTOUCHEND:
case Event.ONTOUCHCANCEL:
@@ -6135,6 +6204,17 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
}
break;
case Event.ONMOUSEDOWN:
+ /*
+ * When getting a mousedown event, we must detect where
+ * the corresponding mouseup event if it's on a
+ * different part of the page.
+ */
+ lastMouseDownTarget = getElementTdOrTr(Util
+ .getElementUnderMouse(event));
+ mouseUpPreviewMatched = false;
+ mouseUpEventPreviewRegistration = Event
+ .addNativePreviewHandler(mouseUpPreviewHandler);
+
if (targetCellOrRowFound) {
setRowFocus(this);
ensureFocus();
@@ -6269,7 +6349,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
*/
private Element getEventTargetTdOrTr(Event event) {
final Element eventTarget = event.getEventTarget().cast();
- Widget widget = Util.findWidget(eventTarget, null);
+ return getElementTdOrTr(eventTarget);
+ }
+
+ private Element getElementTdOrTr(Element element) {
+
+ Widget widget = Util.findWidget(element, null);
if (widget != this) {
/*
@@ -6289,7 +6374,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
return null;
}
}
- return getTdOrTr(eventTarget);
+ return getTdOrTr(element);
}
@Override
@@ -8133,4 +8218,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
public boolean isWorkPending() {
return lazyAdjustColumnWidths.isRunning();
}
+
+ private static Logger getLogger() {
+ return Logger.getLogger(VScrollTable.class.getName());
+ }
}