]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add ItemClickEvents to Grid (#15449)
authorTeemu Suo-Anttila <teemusa@vaadin.com>
Fri, 9 Jan 2015 12:55:13 +0000 (14:55 +0200)
committerVaadin Code Review <review@vaadin.com>
Wed, 14 Jan 2015 10:25:13 +0000 (10:25 +0000)
Change-Id: I743f4de9fd11c5d81b11a3b8f2e0957293c5587c

12 files changed:
client/src/com/vaadin/client/connectors/GridConnector.java
client/src/com/vaadin/client/widget/grid/events/AbstractGridMouseEventHandler.java
client/src/com/vaadin/client/widget/grid/events/BodyDoubleClickHandler.java [new file with mode: 0644]
client/src/com/vaadin/client/widget/grid/events/FooterDoubleClickHandler.java [new file with mode: 0644]
client/src/com/vaadin/client/widget/grid/events/GridDoubleClickEvent.java [new file with mode: 0644]
client/src/com/vaadin/client/widget/grid/events/HeaderDoubleClickHandler.java [new file with mode: 0644]
client/src/com/vaadin/client/widgets/Grid.java
server/src/com/vaadin/ui/Grid.java
shared/src/com/vaadin/shared/ui/grid/GridConstants.java
shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridItemClickTest.java [new file with mode: 0644]

index a2e63fc397c6c461b892f305d97106bd1c3a4856..98562a871e0b35e253442e17a3128e411a2327df 100644 (file)
@@ -29,9 +29,11 @@ import java.util.logging.Logger;
 
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.NativeEvent;
 import com.google.gwt.user.client.ui.Widget;
 import com.vaadin.client.ComponentConnector;
 import com.vaadin.client.ConnectorHierarchyChangeEvent;
+import com.vaadin.client.MouseEventDetailsBuilder;
 import com.vaadin.client.annotations.OnStateChange;
 import com.vaadin.client.communication.StateChangeEvent;
 import com.vaadin.client.connectors.RpcDataSourceConnector.RpcDataSource;
@@ -45,6 +47,10 @@ import com.vaadin.client.widget.grid.CellStyleGenerator;
 import com.vaadin.client.widget.grid.EditorHandler;
 import com.vaadin.client.widget.grid.RowReference;
 import com.vaadin.client.widget.grid.RowStyleGenerator;
+import com.vaadin.client.widget.grid.events.BodyClickHandler;
+import com.vaadin.client.widget.grid.events.BodyDoubleClickHandler;
+import com.vaadin.client.widget.grid.events.GridClickEvent;
+import com.vaadin.client.widget.grid.events.GridDoubleClickEvent;
 import com.vaadin.client.widget.grid.events.SelectAllEvent;
 import com.vaadin.client.widget.grid.events.SelectAllHandler;
 import com.vaadin.client.widget.grid.selection.AbstractRowHandleSelectionModel;
@@ -68,6 +74,7 @@ import com.vaadin.shared.ui.grid.EditorClientRpc;
 import com.vaadin.shared.ui.grid.EditorServerRpc;
 import com.vaadin.shared.ui.grid.GridClientRpc;
 import com.vaadin.shared.ui.grid.GridColumnState;
+import com.vaadin.shared.ui.grid.GridConstants;
 import com.vaadin.shared.ui.grid.GridServerRpc;
 import com.vaadin.shared.ui.grid.GridState;
 import com.vaadin.shared.ui.grid.GridState.SharedSelectionMode;
@@ -304,6 +311,35 @@ public class GridConnector extends AbstractHasComponentsConnector implements
         }
     }
 
+    private class ItemClickHandler implements BodyClickHandler,
+            BodyDoubleClickHandler {
+
+        @Override
+        public void onClick(GridClickEvent event) {
+            if (hasEventListener(GridConstants.ITEM_CLICK_EVENT_ID)) {
+                fireItemClick(event.getTargetCell(), event.getNativeEvent());
+            }
+        }
+
+        @Override
+        public void onDoubleClick(GridDoubleClickEvent event) {
+            if (hasEventListener(GridConstants.ITEM_CLICK_EVENT_ID)) {
+                fireItemClick(event.getTargetCell(), event.getNativeEvent());
+            }
+        }
+
+        private void fireItemClick(CellReference<?> cell, NativeEvent mouseEvent) {
+            String rowKey = getRowKey((JsonObject) cell.getRow());
+            String columnId = getColumnId(cell.getColumn());
+            getRpcProxy(GridServerRpc.class)
+                    .itemClick(
+                            rowKey,
+                            columnId,
+                            MouseEventDetailsBuilder
+                                    .buildMouseEventDetails(mouseEvent));
+        }
+    }
+
     /**
      * Maps a generated column id to a grid column instance
      */
@@ -347,6 +383,8 @@ public class GridConnector extends AbstractHasComponentsConnector implements
         }
     };
 
+    private ItemClickHandler itemClickHandler = new ItemClickHandler();
+
     @Override
     @SuppressWarnings("unchecked")
     public Grid<JsonObject> getWidget() {
@@ -397,6 +435,10 @@ public class GridConnector extends AbstractHasComponentsConnector implements
 
         getWidget().addSelectionHandler(internalSelectionChangeHandler);
 
+        /* Item click events */
+        getWidget().addBodyClickHandler(itemClickHandler);
+        getWidget().addBodyDoubleClickHandler(itemClickHandler);
+
         getWidget().addSortHandler(new SortHandler<JsonObject>() {
             @Override
             public void sort(SortEvent<JsonObject> event) {
@@ -881,7 +923,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements
             ConnectorHierarchyChangeEvent connectorHierarchyChangeEvent) {
     }
 
-    public String getColumnId(Grid.Column<?, JsonObject> column) {
+    public String getColumnId(Grid.Column<?, ?> column) {
         if (column instanceof CustomGridColumn) {
             return ((CustomGridColumn) column).id;
         }
index f72dcc37d2b7042cdf5e10c09bd5efa767413714..15e22a6d57c85752952d2fb999a9968ffa0e3719 100644 (file)
@@ -31,4 +31,9 @@ public abstract interface AbstractGridMouseEventHandler extends EventHandler {
         public void onClick(GridClickEvent event);
     }
 
+    public abstract interface GridDoubleClickHandler extends
+            AbstractGridMouseEventHandler {
+        public void onDoubleClick(GridDoubleClickEvent event);
+    }
+
 }
\ No newline at end of file
diff --git a/client/src/com/vaadin/client/widget/grid/events/BodyDoubleClickHandler.java b/client/src/com/vaadin/client/widget/grid/events/BodyDoubleClickHandler.java
new file mode 100644 (file)
index 0000000..a7be5ba
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.client.widget.grid.events;
+
+import com.vaadin.client.widget.grid.events.AbstractGridMouseEventHandler.GridDoubleClickHandler;
+
+/**
+ * Handler for {@link GridDoubleClickEvent}s that happen in the body of the
+ * Grid.
+ * 
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface BodyDoubleClickHandler extends GridDoubleClickHandler {
+
+}
diff --git a/client/src/com/vaadin/client/widget/grid/events/FooterDoubleClickHandler.java b/client/src/com/vaadin/client/widget/grid/events/FooterDoubleClickHandler.java
new file mode 100644 (file)
index 0000000..3bb9c9e
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.client.widget.grid.events;
+
+import com.vaadin.client.widget.grid.events.AbstractGridMouseEventHandler.GridDoubleClickHandler;
+
+/**
+ * Handler for {@link GridDoubleClickEvent}s that happen in the footer of the
+ * Grid.
+ * 
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface FooterDoubleClickHandler extends GridDoubleClickHandler {
+
+}
diff --git a/client/src/com/vaadin/client/widget/grid/events/GridDoubleClickEvent.java b/client/src/com/vaadin/client/widget/grid/events/GridDoubleClickEvent.java
new file mode 100644 (file)
index 0000000..20e432a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.client.widget.grid.events;
+
+import com.google.gwt.dom.client.BrowserEvents;
+import com.vaadin.client.widget.grid.CellReference;
+import com.vaadin.client.widget.grid.events.AbstractGridMouseEventHandler.GridDoubleClickHandler;
+import com.vaadin.client.widgets.Grid;
+import com.vaadin.client.widgets.Grid.AbstractGridMouseEvent;
+import com.vaadin.client.widgets.Grid.Section;
+
+/**
+ * Represents native mouse double click event in Grid.
+ * 
+ * @since
+ * @author Vaadin Ltd
+ */
+public class GridDoubleClickEvent extends
+        AbstractGridMouseEvent<GridDoubleClickHandler> {
+
+    public GridDoubleClickEvent(Grid<?> grid, CellReference<?> targetCell) {
+        super(grid, targetCell);
+    }
+
+    @Override
+    protected String getBrowserEventType() {
+        return BrowserEvents.DBLCLICK;
+    }
+
+    @Override
+    protected void doDispatch(GridDoubleClickHandler handler, Section section) {
+        if ((section == Section.BODY && handler instanceof BodyDoubleClickHandler)
+                || (section == Section.HEADER && handler instanceof HeaderDoubleClickHandler)
+                || (section == Section.FOOTER && handler instanceof FooterDoubleClickHandler)) {
+            handler.onDoubleClick(this);
+        }
+    }
+
+}
diff --git a/client/src/com/vaadin/client/widget/grid/events/HeaderDoubleClickHandler.java b/client/src/com/vaadin/client/widget/grid/events/HeaderDoubleClickHandler.java
new file mode 100644 (file)
index 0000000..7ebb0c1
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.client.widget.grid.events;
+
+import com.vaadin.client.widget.grid.events.AbstractGridMouseEventHandler.GridDoubleClickHandler;
+
+/**
+ * Handler for {@link GridDoubleClickEvent}s that happen in the header of the
+ * Grid.
+ * 
+ * @since
+ * @author Vaadin Ltd
+ */
+public interface HeaderDoubleClickHandler extends GridDoubleClickHandler {
+
+}
index d401b4da78d17df8de93684775a0055d0294f895..18115b2a3bc7de385d9bd908992825821800d1cd 100644 (file)
@@ -89,18 +89,22 @@ import com.vaadin.client.widget.grid.RowStyleGenerator;
 import com.vaadin.client.widget.grid.events.AbstractGridKeyEventHandler;
 import com.vaadin.client.widget.grid.events.AbstractGridMouseEventHandler;
 import com.vaadin.client.widget.grid.events.BodyClickHandler;
+import com.vaadin.client.widget.grid.events.BodyDoubleClickHandler;
 import com.vaadin.client.widget.grid.events.BodyKeyDownHandler;
 import com.vaadin.client.widget.grid.events.BodyKeyPressHandler;
 import com.vaadin.client.widget.grid.events.BodyKeyUpHandler;
 import com.vaadin.client.widget.grid.events.FooterClickHandler;
+import com.vaadin.client.widget.grid.events.FooterDoubleClickHandler;
 import com.vaadin.client.widget.grid.events.FooterKeyDownHandler;
 import com.vaadin.client.widget.grid.events.FooterKeyPressHandler;
 import com.vaadin.client.widget.grid.events.FooterKeyUpHandler;
 import com.vaadin.client.widget.grid.events.GridClickEvent;
+import com.vaadin.client.widget.grid.events.GridDoubleClickEvent;
 import com.vaadin.client.widget.grid.events.GridKeyDownEvent;
 import com.vaadin.client.widget.grid.events.GridKeyPressEvent;
 import com.vaadin.client.widget.grid.events.GridKeyUpEvent;
 import com.vaadin.client.widget.grid.events.HeaderClickHandler;
+import com.vaadin.client.widget.grid.events.HeaderDoubleClickHandler;
 import com.vaadin.client.widget.grid.events.HeaderKeyDownHandler;
 import com.vaadin.client.widget.grid.events.HeaderKeyPressHandler;
 import com.vaadin.client.widget.grid.events.HeaderKeyUpHandler;
@@ -1450,6 +1454,8 @@ public class Grid<T> extends ResizeComposite implements
     private GridKeyUpEvent keyUp = new GridKeyUpEvent(this, eventCell);
     private GridKeyPressEvent keyPress = new GridKeyPressEvent(this, eventCell);
     private GridClickEvent clickEvent = new GridClickEvent(this, eventCell);
+    private GridDoubleClickEvent doubleClickEvent = new GridDoubleClickEvent(
+            this, eventCell);
 
     private class CellFocusHandler {
 
@@ -5357,6 +5363,48 @@ public class Grid<T> extends ResizeComposite implements
         return addHandler(handler, clickEvent.getAssociatedType());
     }
 
+    /**
+     * Register a BodyDoubleClickHandler to this Grid. The event for this
+     * handler is fired when a double click event occurs in the Body of this
+     * Grid.
+     * 
+     * @param handler
+     *            the double click handler to register
+     * @return the registration for the event
+     */
+    public HandlerRegistration addBodyDoubleClickHandler(
+            BodyDoubleClickHandler handler) {
+        return addHandler(handler, doubleClickEvent.getAssociatedType());
+    }
+
+    /**
+     * Register a HeaderDoubleClickHandler to this Grid. The event for this
+     * handler is fired when a double click event occurs in the Header of this
+     * Grid.
+     * 
+     * @param handler
+     *            the double click handler to register
+     * @return the registration for the event
+     */
+    public HandlerRegistration addHeaderDoubleClickHandler(
+            HeaderDoubleClickHandler handler) {
+        return addHandler(handler, doubleClickEvent.getAssociatedType());
+    }
+
+    /**
+     * Register a FooterDoubleClickHandler to this Grid. The event for this
+     * handler is fired when a double click event occurs in the Footer of this
+     * Grid.
+     * 
+     * @param handler
+     *            the double click handler to register
+     * @return the registration for the event
+     */
+    public HandlerRegistration addFooterDoubleClickHandler(
+            FooterDoubleClickHandler handler) {
+        return addHandler(handler, doubleClickEvent.getAssociatedType());
+    }
+
     /**
      * Apply sorting to data source.
      */
index 0843fb6ec18e3d441587c3606f7bda4f6c686d5e..443e51fba3a85369b91b389f045c1cc15def3f49 100644 (file)
@@ -56,6 +56,9 @@ import com.vaadin.data.sort.SortOrder;
 import com.vaadin.data.util.IndexedContainer;
 import com.vaadin.data.util.converter.Converter;
 import com.vaadin.data.util.converter.ConverterUtil;
+import com.vaadin.event.ItemClickEvent;
+import com.vaadin.event.ItemClickEvent.ItemClickListener;
+import com.vaadin.event.ItemClickEvent.ItemClickNotifier;
 import com.vaadin.event.SelectionEvent;
 import com.vaadin.event.SelectionEvent.SelectionListener;
 import com.vaadin.event.SelectionEvent.SelectionNotifier;
@@ -68,11 +71,13 @@ import com.vaadin.server.ErrorMessage;
 import com.vaadin.server.JsonCodec;
 import com.vaadin.server.KeyMapper;
 import com.vaadin.server.VaadinSession;
+import com.vaadin.shared.MouseEventDetails;
 import com.vaadin.shared.data.sort.SortDirection;
 import com.vaadin.shared.ui.grid.EditorClientRpc;
 import com.vaadin.shared.ui.grid.EditorServerRpc;
 import com.vaadin.shared.ui.grid.GridClientRpc;
 import com.vaadin.shared.ui.grid.GridColumnState;
+import com.vaadin.shared.ui.grid.GridConstants;
 import com.vaadin.shared.ui.grid.GridServerRpc;
 import com.vaadin.shared.ui.grid.GridState;
 import com.vaadin.shared.ui.grid.GridState.SharedSelectionMode;
@@ -155,7 +160,7 @@ import elemental.json.JsonValue;
  * @author Vaadin Ltd
  */
 public class Grid extends AbstractComponent implements SelectionNotifier,
-        SortNotifier, SelectiveRenderer {
+        SortNotifier, SelectiveRenderer, ItemClickNotifier {
 
     /**
      * Custom field group that allows finding property types before an item has
@@ -2712,6 +2717,16 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
 
                 ((SelectionModel.Multi) getSelectionModel()).selectAll();
             }
+
+            @Override
+            public void itemClick(String rowKey, String columnId,
+                    MouseEventDetails details) {
+                Object itemId = getKeyMapper().getItemId(rowKey);
+                Item item = datasource.getItem(itemId);
+                Object propertyId = getPropertyIdByColumnId(columnId);
+                fireEvent(new ItemClickEvent(Grid.this, item, itemId,
+                        propertyId, details));
+            }
         });
 
         registerRpc(new EditorServerRpc() {
@@ -4524,4 +4539,28 @@ public class Grid extends AbstractComponent implements SelectionNotifier,
     public void setEditorFieldFactory(FieldGroupFieldFactory fieldFactory) {
         editorFieldGroup.setFieldFactory(fieldFactory);
     }
+
+    @Override
+    public void addItemClickListener(ItemClickListener listener) {
+        addListener(GridConstants.ITEM_CLICK_EVENT_ID, ItemClickEvent.class,
+                listener, ItemClickEvent.ITEM_CLICK_METHOD);
+    }
+
+    @Override
+    @Deprecated
+    public void addListener(ItemClickListener listener) {
+        addItemClickListener(listener);
+    }
+
+    @Override
+    public void removeItemClickListener(ItemClickListener listener) {
+        removeListener(GridConstants.ITEM_CLICK_EVENT_ID, ItemClickEvent.class,
+                listener);
+    }
+
+    @Override
+    @Deprecated
+    public void removeListener(ItemClickListener listener) {
+        removeItemClickListener(listener);
+    }
 }
index 994b109204f2ca412c9267bbcb0b6cf3906a4a3a..b36a1624760ed63aafdd594ee35d09d62f97f2cb 100644 (file)
@@ -63,4 +63,9 @@ public final class GridConstants implements Serializable {
      * Default width for columns.
      */
     public static final double DEFAULT_COLUMN_WIDTH_PX = -1;
+
+    /**
+     * Event ID for item click events
+     */
+    public static final String ITEM_CLICK_EVENT_ID = "itemClick";
 }
index 77eda7a2f61c0824344dcdaa2a7a1b19ec01ba65..c90a01638391dc46a43244af4603bcfc0fd0dab7 100644 (file)
@@ -17,6 +17,7 @@ package com.vaadin.shared.ui.grid;
 
 import java.util.List;
 
+import com.vaadin.shared.MouseEventDetails;
 import com.vaadin.shared.communication.ServerRpc;
 import com.vaadin.shared.data.sort.SortDirection;
 
@@ -34,4 +35,16 @@ public interface GridServerRpc extends ServerRpc {
 
     void sort(String[] columnIds, SortDirection[] directions,
             boolean userOriginated);
+
+    /**
+     * Informs the server that an item has been clicked in Grid.
+     * 
+     * @param rowKey
+     *            a key identifying the clicked item
+     * @param columnId
+     *            column id identifying the clicked property
+     * @param details
+     *            mouse event details
+     */
+    void itemClick(String rowKey, String columnId, MouseEventDetails details);
 }
index 5912f2b5a505db6d1b8e8062c7d296512749d488..7a625e2f25476e75649882a52641dff6a82191ac 100644 (file)
@@ -33,6 +33,8 @@ import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
 import com.vaadin.data.sort.Sort;
 import com.vaadin.data.sort.SortOrder;
 import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.event.ItemClickEvent;
+import com.vaadin.event.ItemClickEvent.ItemClickListener;
 import com.vaadin.event.SelectionEvent;
 import com.vaadin.event.SelectionEvent.SelectionListener;
 import com.vaadin.event.SortEvent;
@@ -93,6 +95,16 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
         }
     };
 
+    private ItemClickListener itemClickListener = new ItemClickListener() {
+
+        @Override
+        public void itemClick(ItemClickEvent event) {
+            log("Item " + (event.isDoubleClick() ? "double " : "")
+                    + "click on " + event.getPropertyId() + ", item "
+                    + event.getItemId());
+        }
+    };
+
     @Override
     @SuppressWarnings("unchecked")
     protected Grid constructComponent() {
@@ -452,6 +464,7 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
             containerDelayValues.put(String.valueOf(delay),
                     Integer.valueOf(delay));
         }
+
         createSelectAction("Container delay", "State", containerDelayValues,
                 "0", new Command<Grid, Integer>() {
                     @Override
@@ -459,6 +472,20 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
                         containerDelay = delay.intValue();
                     }
                 });
+
+        createBooleanAction("ItemClickListener", "State", false,
+                new Command<Grid, Boolean>() {
+
+                    @Override
+                    public void execute(Grid c, Boolean value, Object data) {
+                        if (!value) {
+                            c.removeItemClickListener(itemClickListener);
+                        } else {
+                            c.addItemClickListener(itemClickListener);
+                        }
+                    }
+
+                });
     }
 
     protected void createHeaderActions() {
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridItemClickTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridItemClickTest.java
new file mode 100644 (file)
index 0000000..57fc56c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridItemClickTest extends GridBasicFeaturesTest {
+
+    @Test
+    public void testItemClick() {
+        openTestURL();
+
+        selectMenuPath("Component", "State", "ItemClickListener");
+
+        GridCellElement cell = getGridElement().getCell(3, 2);
+        new Actions(getDriver()).moveToElement(cell).click().perform();
+
+        assertTrue("No click in log", logContainsText(itemClickOn(3, 2, false)));
+    }
+
+    @Test
+    public void testItemDoubleClick() {
+        openTestURL();
+
+        selectMenuPath("Component", "State", "ItemClickListener");
+
+        GridCellElement cell = getGridElement().getCell(3, 2);
+        new Actions(getDriver()).moveToElement(cell).doubleClick().perform();
+
+        assertTrue("No double click in log",
+                logContainsText(itemClickOn(3, 2, true)));
+    }
+
+    private String itemClickOn(int row, int column, boolean dblClick) {
+        return "Item " + (dblClick ? "double " : "") + "click on Column "
+                + column + ", item " + row;
+    }
+}