Browse Source

Table / TreeTable multiselect disabling of touch detection (#12014)

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
tags/8.12.0.alpha1
Anna Koskinen 3 years ago
parent
commit
0645a86e5b
No account linked to committer's email address

+ 9
- 2
compatibility-client/src/main/java/com/vaadin/v7/client/ui/VScrollTable.java View 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;

+ 35
- 1
compatibility-server/src/main/java/com/vaadin/v7/ui/Table.java View 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

+ 2
- 1
uitest/src/main/java/com/vaadin/tests/components/table/CtrlShiftMultiselect.java View 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);

+ 41
- 0
uitest/src/main/java/com/vaadin/tests/components/table/CtrlShiftMultiselectTouchDetectionDisabled.java View File

@@ -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;
}

}

+ 64
- 0
uitest/src/main/java/com/vaadin/tests/components/treetable/TreeTableMultiselect.java View File

@@ -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;
}

}

+ 40
- 0
uitest/src/test/java/com/vaadin/tests/components/table/CtrlShiftMultiselectTouchDetectionDisabledTest.java View File

@@ -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();
}

}

+ 38
- 0
uitest/src/test/java/com/vaadin/tests/components/treetable/TreeTableMultiselectTest.java View File

@@ -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();
}

}

Loading…
Cancel
Save