]> source.dussan.org Git - vaadin-framework.git/commitdiff
Table / TreeTable multiselect disabling of touch detection (#12014) pr12027/r10
authorAnna Koskinen <Ansku@users.noreply.github.com>
Tue, 19 May 2020 10:13:25 +0000 (13:13 +0300)
committerGitHub <noreply@github.com>
Tue, 19 May 2020 10:13:25 +0000 (13:13 +0300)
Added a toggle in Table (and thus TreeTable) where you can explicitly
disable multiselect touch screen detection. This allows you to work
around issues on hybrid devices that have both a touch screen and a
keyboard where you don't want automatic simple multiselection applied.

Fixes #11601, slightly modified cherry-pick of #11641

compatibility-client/src/main/java/com/vaadin/v7/client/ui/VScrollTable.java
compatibility-server/src/main/java/com/vaadin/v7/ui/Table.java
uitest/src/main/java/com/vaadin/tests/components/table/CtrlShiftMultiselect.java
uitest/src/main/java/com/vaadin/tests/components/table/CtrlShiftMultiselectTouchDetectionDisabled.java [new file with mode: 0644]
uitest/src/main/java/com/vaadin/tests/components/treetable/TreeTableMultiselect.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/table/CtrlShiftMultiselectTouchDetectionDisabledTest.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/treetable/TreeTableMultiselectTest.java [new file with mode: 0644]

index 4b0a52c1bdbb7fb3cd21b12578f4ffa86d090a11..c4294009d27befc0cf9ed4962ce4f39d3fe06c63 100644 (file)
@@ -349,6 +349,8 @@ public class VScrollTable extends FlowPanel
 
     private SelectMode selectMode = SelectMode.NONE;
 
+    private boolean multiSelectTouchDetectionEnabled = true;
+
     public final HashSet<String> selectedRowKeys = new HashSet<String>();
 
     /*
@@ -1502,6 +1504,10 @@ public class VScrollTable extends FlowPanel
             } else {
                 selectMode = SelectMode.NONE;
             }
+            if (uidl.hasAttribute("touchdetection")) {
+                multiSelectTouchDetectionEnabled = uidl
+                        .getBooleanAttribute("touchdetection");
+            }
         }
     }
 
@@ -1951,9 +1957,10 @@ public class VScrollTable extends FlowPanel
     }
 
     private void setMultiSelectMode(int multiselectmode) {
-        if (BrowserInfo.get().isTouchDevice()) {
+        if (BrowserInfo.get().isTouchDevice()
+                && multiSelectTouchDetectionEnabled) {
             // Always use the simple mode for touch devices that do not have
-            // shift/ctrl keys
+            // shift/ctrl keys (unless this feature is explicitly disabled)
             this.multiselectmode = MULTISELECT_MODE_SIMPLE;
         } else {
             this.multiselectmode = multiselectmode;
index 433254aa67cd8b168293ba8e9205a6d0c7ab07d9..0519e20f75e866f09a8f509c6b93e1df0cc27191 100644 (file)
@@ -588,6 +588,8 @@ public class Table extends AbstractSelect implements Action.Container,
 
     private MultiSelectMode multiSelectMode = MultiSelectMode.DEFAULT;
 
+    private boolean multiSelectTouchDetectionEnabled = true;
+
     private boolean rowCacheInvalidated;
 
     private RowGenerator rowGenerator = null;
@@ -3775,6 +3777,10 @@ public class Table extends AbstractSelect implements Action.Container,
         if (isSelectable()) {
             target.addAttribute("selectmode",
                     (isMultiSelect() ? "multi" : "single"));
+            if (isMultiSelect()) {
+                target.addAttribute("touchdetection",
+                        isMultiSelectTouchDetectionEnabled());
+            }
         } else {
             target.addAttribute("selectmode", "none");
         }
@@ -5188,7 +5194,10 @@ public class Table extends AbstractSelect implements Action.Container,
      * <p>
      * Note, that on some clients the mode may not be respected. E.g. on touch
      * based devices CTRL/SHIFT base selection method is invalid, so touch based
-     * browsers always use the {@link MultiSelectMode#SIMPLE}.
+     * browsers always use the {@link MultiSelectMode#SIMPLE} unless touch multi
+     * select is explicitly disabled.
+     *
+     * @see #setMultiSelectTouchDetectionEnabled(boolean)
      *
      * @param mode
      *            The select mode of the table
@@ -5207,6 +5216,31 @@ public class Table extends AbstractSelect implements Action.Container,
         return multiSelectMode;
     }
 
+    /**
+     * Default behavior on touch-reporting devices is to switch from CTRL/SHIFT
+     * based multi-selection to simple mode, but you can use this method to
+     * explicitly disable the touch device detection. Thus you can keep using
+     * keyboard-based multi selection on hybrid devices that have both a touch
+     * screen and a keyboard.
+     *
+     * @param multiSelectTouchDetectionEnabled
+     *            Whether to enable or disable touch screen detection
+     */
+    public void setMultiSelectTouchDetectionEnabled(
+            boolean multiSelectTouchDetectionEnabled) {
+        this.multiSelectTouchDetectionEnabled = multiSelectTouchDetectionEnabled;
+        markAsDirty();
+    }
+
+    /**
+     * Returns if touch screen detection is used to toggle multi select mode.
+     *
+     * @return If touch screen detection for multi select is enabled
+     */
+    public boolean isMultiSelectTouchDetectionEnabled() {
+        return multiSelectTouchDetectionEnabled;
+    }
+
     /**
      * Lazy loading accept criterion for Table. Accepted target rows are loaded
      * from server once per drag and drop operation. Developer must override one
index 1713dddde51173e679b97a0fecc5a1cfc69c55da..0a1a1ab560315e78cd6bdbee77a423fb4910ea05 100644 (file)
@@ -10,9 +10,10 @@ import com.vaadin.v7.ui.Table.TableDragMode;
 @SuppressWarnings("serial")
 public class CtrlShiftMultiselect extends TestBase {
 
+    protected final Table table = new Table("Multiselectable table");
+
     @Override
     protected void setup() {
-        final Table table = new Table("Multiselectable table");
 
         table.setContainerDataSource(createContainer());
         table.setImmediate(true);
diff --git a/uitest/src/main/java/com/vaadin/tests/components/table/CtrlShiftMultiselectTouchDetectionDisabled.java b/uitest/src/main/java/com/vaadin/tests/components/table/CtrlShiftMultiselectTouchDetectionDisabled.java
new file mode 100644 (file)
index 0000000..318b595
--- /dev/null
@@ -0,0 +1,41 @@
+package com.vaadin.tests.components.table;
+
+import java.util.Set;
+
+import com.vaadin.v7.data.Property;
+import com.vaadin.v7.ui.Label;
+
+public class CtrlShiftMultiselectTouchDetectionDisabled
+        extends CtrlShiftMultiselect {
+
+    protected Label label;
+
+    @Override
+    protected void setup() {
+        super.setup();
+        label = new Label("0");
+        label.setId("count");
+        label.setCaption("Amount of selected items");
+        table.setMultiSelectTouchDetectionEnabled(false);
+        table.addValueChangeListener(new Property.ValueChangeListener() {
+            @Override
+            public void valueChange(Property.ValueChangeEvent event) {
+                Property property = event.getProperty();
+                Set set = (Set) property.getValue();
+                label.setValue("" + set.size());
+            }
+        });
+        addComponent(label);
+    }
+
+    @Override
+    protected String getDescription() {
+        return "Allow disabling multi selection's touch screen detection for hybrid devices";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 11601;
+    }
+
+}
\ No newline at end of file
diff --git a/uitest/src/main/java/com/vaadin/tests/components/treetable/TreeTableMultiselect.java b/uitest/src/main/java/com/vaadin/tests/components/treetable/TreeTableMultiselect.java
new file mode 100644 (file)
index 0000000..2ceae92
--- /dev/null
@@ -0,0 +1,64 @@
+package com.vaadin.tests.components.treetable;
+
+import static com.vaadin.server.Sizeable.Unit.PIXELS;
+
+import java.util.Set;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.v7.data.Property;
+import com.vaadin.v7.ui.Label;
+import com.vaadin.v7.ui.TreeTable;
+
+public class TreeTableMultiselect extends AbstractTestUI {
+
+    protected final TreeTable tt = new TreeTable("Multiselectable treetable");
+    protected Label label;
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        label = new Label("0");
+        label.setCaption("Amount of selected items");
+        label.setId("count");
+
+        tt.setImmediate(true);
+        tt.addContainerProperty("Foo", String.class, "");
+        tt.setColumnWidth("Foo", 100);
+        tt.addContainerProperty("Bar", String.class, "");
+        tt.setColumnWidth("Bar", 100);
+        tt.setHeight(400, PIXELS);
+        Object item1 = tt.addItem(new Object[] { "Foo", "Bar" }, null);
+        Object item2 = tt.addItem(new Object[] { "Foo2", "Bar2" }, null);
+        Object item3 = tt.addItem(new Object[] { "Foo3", "Bar3" }, null);
+        tt.setParent(item2, item1);
+        tt.setParent(item3, item1);
+        tt.setCollapsed(item1, false);
+        tt.setSelectable(true);
+        tt.setMultiSelect(true);
+        tt.setMultiSelectTouchDetectionEnabled(false);
+        tt.setWidth("400px");
+        tt.setHeight("400px");
+        tt.addValueChangeListener(new Property.ValueChangeListener() {
+            @Override
+            public void valueChange(Property.ValueChangeEvent event) {
+                Property property = event.getProperty();
+                Set set = (Set) property.getValue();
+                label.setValue("" + set.size());
+            }
+        });
+
+        addComponent(tt);
+        addComponent(label);
+    }
+
+    @Override
+    public String getTestDescription() {
+        return "Allow disabling multi selection's touch screen detection for hybrid devices";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 11601;
+    }
+
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/table/CtrlShiftMultiselectTouchDetectionDisabledTest.java b/uitest/src/test/java/com/vaadin/tests/components/table/CtrlShiftMultiselectTouchDetectionDisabledTest.java
new file mode 100644 (file)
index 0000000..7066b01
--- /dev/null
@@ -0,0 +1,40 @@
+package com.vaadin.tests.components.table;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.testbench.elements.TableElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class CtrlShiftMultiselectTouchDetectionDisabledTest
+        extends SingleBrowserTest {
+
+    @Override
+    protected boolean requireWindowFocusForIE() {
+        return true;
+    }
+
+    @Test
+    public void testSelectedCount() {
+        openTestURL();
+        clickRow(3);
+        new Actions(driver).keyDown(Keys.SHIFT).perform();
+        clickRow(8);
+        new Actions(driver).keyUp(Keys.SHIFT).perform();
+        new Actions(driver).release().perform();
+        LabelElement labelElement = $(LabelElement.class).id("count");
+        assertEquals("Unexpected amount of selected rows", "6",
+                labelElement.getText());
+
+    }
+
+    private void clickRow(int index) {
+        TableElement tableElement = $(TableElement.class).first();
+        tableElement.getRow(index).click();
+    }
+
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/treetable/TreeTableMultiselectTest.java b/uitest/src/test/java/com/vaadin/tests/components/treetable/TreeTableMultiselectTest.java
new file mode 100644 (file)
index 0000000..36107f1
--- /dev/null
@@ -0,0 +1,38 @@
+package com.vaadin.tests.components.treetable;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.testbench.elements.TreeTableElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class TreeTableMultiselectTest extends SingleBrowserTest {
+
+    @Override
+    protected boolean requireWindowFocusForIE() {
+        return true;
+    }
+
+    @Test
+    public void testSelectedCount() {
+        openTestURL();
+        clickRow(0);
+        new Actions(driver).keyDown(Keys.SHIFT).perform();
+        clickRow(2);
+        new Actions(driver).keyUp(Keys.SHIFT).perform();
+        new Actions(driver).release().perform();
+        LabelElement labelElement = $(LabelElement.class).id("count");
+        assertEquals("Unexpected amount of selected rows", "3",
+                labelElement.getText());
+    }
+
+    private void clickRow(int index) {
+        TreeTableElement treeTable = $(TreeTableElement.class).first();
+        treeTable.getRow(index).click();
+    }
+
+}