private SelectMode selectMode = SelectMode.NONE;
+ private boolean multiSelectTouchDetectionEnabled = true;
+
public final HashSet<String> selectedRowKeys = new HashSet<String>();
/*
} else {
selectMode = SelectMode.NONE;
}
+ if (uidl.hasAttribute("touchdetection")) {
+ multiSelectTouchDetectionEnabled = uidl
+ .getBooleanAttribute("touchdetection");
+ }
}
}
}
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;
private MultiSelectMode multiSelectMode = MultiSelectMode.DEFAULT;
+ private boolean multiSelectTouchDetectionEnabled = true;
+
private boolean rowCacheInvalidated;
private RowGenerator rowGenerator = null;
if (isSelectable()) {
target.addAttribute("selectmode",
(isMultiSelect() ? "multi" : "single"));
+ if (isMultiSelect()) {
+ target.addAttribute("touchdetection",
+ isMultiSelectTouchDetectionEnabled());
+ }
} else {
target.addAttribute("selectmode", "none");
}
* <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
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
@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);
--- /dev/null
+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
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+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();
+ }
+
+}
--- /dev/null
+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();
+ }
+
+}