private boolean selectionHasChanged = false;
+ /*
+ * to fix #14388. The cause of defect #14388: event 'clickEvent' is sent to
+ * server before updating of "selected" variable, but should be send after
+ * it
+ */
+ private boolean sendClickEventNow = false;
+
/** For internal use only. May be removed or replaced in the future. */
public String[] bodyActionKeys;
Command command = new Command() {
@Override
public void execute() {
+ /*
+ * we should send selection to server immediately in 2 cases: 1)
+ * 'immediate' property of Tree is true 2) sendClickEventNow is
+ * true
+ */
client.updateVariable(paintableId, "selected",
selectedIds.toArray(new String[selectedIds.size()]),
- immediate);
+ sendClickEventNow || immediate);
+ sendClickEventNow = false;
selectionHasChanged = false;
}
};
// server. We do not want to send the event if there is a
// selection event happening after this. In all other cases
// we want to send it immediately.
- boolean sendClickEventNow = true;
-
- if (details.getButton() == MouseButton.LEFT && immediate
- && selectable) {
- // Probably a selection that will cause a value change
- // event to be sent
- sendClickEventNow = false;
-
- // The exception is that user clicked on the
- // currently selected row and null selection is not
- // allowed == no selection event
- if (isSelected() && selectedIds.size() == 1
- && !isNullSelectionAllowed) {
- sendClickEventNow = true;
+ sendClickEventNow = true;
+
+ if (details.getButton() == MouseButton.LEFT && selectable) {
+ if (immediate) {
+ // event to be sent
+ sendClickEventNow = false;
+
+ // The exception is that user clicked on the
+ // currently selected row and null selection is not
+ // allowed == no selection event
+ if (isSelected() && selectedIds.size() == 1
+ && !isNullSelectionAllowed) {
+ sendClickEventNow = true;
+ }
}
- }
- client.updateVariable(paintableId, "clickedKey", key, false);
- client.updateVariable(paintableId, "clickEvent",
- details.toString(), sendClickEventNow);
+ client.updateVariable(paintableId, "clickedKey", key,
+ false);
+
+ /*
+ * in any case event should not be send immediately here
+ * - send after updating of "selected" variable
+ */
+ client.updateVariable(paintableId, "clickEvent",
+ details.toString(), false);
+
+ } else { // for all another mouse buttons (RIGHT, MIDDLE) or
+ // if not selectable
+ client.updateVariable(paintableId, "clickedKey", key,
+ false);
+
+ client.updateVariable(paintableId, "clickEvent",
+ details.toString(), sendClickEventNow);
+ sendClickEventNow = false; // reset it
+ }
}
});
}
--- /dev/null
+package com.vaadin.tests.components.tree;
+
+import com.vaadin.event.ItemClickEvent;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.ui.Tree;
+
+@SuppressWarnings("serial")
+public class TreeItemSelectionWithoutImmediate extends AbstractTestUIWithLog {
+
+ protected static final String TREE_ID = "TreeId";
+
+ protected static final String MENU_ITEM_TEMPLATE = "Menu Item %d";
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Tree tree = new Tree("With ItemClickListener not Immediate");
+ tree.setId(TREE_ID);
+ tree.setImmediate(false);
+
+ for (int i = 1; i <= 4; i++) {
+ tree.addItem(String.format(MENU_ITEM_TEMPLATE, i));
+ }
+
+ tree.addItemClickListener(new ItemClickEvent.ItemClickListener() {
+
+ @Override
+ public void itemClick(ItemClickEvent event) {
+ log("ItemClickEvent = " + event.getItemId());
+ }
+ });
+
+ addComponent(tree);
+ }
+
+ @Override
+ protected String getTestDescription() {
+ return "Test for ensuring that selection of tree items works correctly if immediate == false "
+ + "and ItemClickListener is added to Tree";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 14388;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.tree;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.By;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class TreeItemSelectionWithoutImmediateTest extends MultiBrowserTest {
+
+ private static final long serialVersionUID = 1L;
+
+ @Test
+ public void testSelectTreeWithItemClickListenerNotImmediate()
+ throws InterruptedException {
+ openTestURL();
+
+ // click on item i (in circle we select next item and check if it is
+ // selected in tree)
+ for (int i = 1; i <= 4; i++) {
+ WebElement treeItem = getTreeNode(String.format(
+ TreeItemSelectionWithoutImmediate.MENU_ITEM_TEMPLATE, i));
+
+ new Actions(getDriver()).moveToElement(treeItem).click().perform();
+ Thread.sleep(100);
+
+ WebElement selectedElement = driver.findElement(By
+ .className("v-tree-node-selected"));
+
+ treeItem = getTreeNode(String.format(
+ TreeItemSelectionWithoutImmediate.MENU_ITEM_TEMPLATE, i));
+
+ assertThat("Clicked element should be selected", selectedElement
+ .getText().equals(treeItem.getText()), is(true));
+ }
+ }
+
+ private WebElement getTreeNode(String caption) {
+ return getDriver().findElement(
+ By.xpath("//span[text() = '" + caption + "']"));
+ }
+}