diff options
author | Teemu Suo-Anttila <teemusa@vaadin.com> | 2015-05-25 15:14:39 +0300 |
---|---|---|
committer | Teppo Kurki <teppo.kurki@vaadin.com> | 2015-05-27 05:44:51 +0000 |
commit | a95f757546892a855def121ec5ce5e5bda927a29 (patch) | |
tree | f789ec0c399c5edbf3965bf932d1ec502a10dc9a | |
parent | 0a7b430d50dc8d82e2ca23296381939a7f444846 (diff) | |
download | vaadin-framework-a95f757546892a855def121ec5ce5e5bda927a29.tar.gz vaadin-framework-a95f757546892a855def121ec5ce5e5bda927a29.zip |
Fix Grid client-side event support (#17986)
Added a public API to get an EventCellReference for the most recent
fired event. Also EventCellReference now contains information on Grid
section and some related helpers.
Change-Id: Ia8a166da6f322084d65f9b1cb242e22b0e66e53b
5 files changed, 201 insertions, 6 deletions
diff --git a/client/src/com/vaadin/client/renderers/ClickableRenderer.java b/client/src/com/vaadin/client/renderers/ClickableRenderer.java index f5368d31c9..83059f8f01 100644 --- a/client/src/com/vaadin/client/renderers/ClickableRenderer.java +++ b/client/src/com/vaadin/client/renderers/ClickableRenderer.java @@ -33,6 +33,7 @@ import com.vaadin.client.widget.grid.CellReference; import com.vaadin.client.widget.grid.EventCellReference; import com.vaadin.client.widgets.Escalator; import com.vaadin.client.widgets.Grid; +import com.vaadin.client.widgets.Grid.Section; /** * An abstract superclass for renderers that render clickable widgets. Click @@ -152,7 +153,9 @@ public abstract class ClickableRenderer<T, W extends Widget> extends Cell cell = container.getCell(e); EventCellReference<T> cellReference = new EventCellReference<T>( grid); - cellReference.set(cell); + // FIXME: Section is currently always body. Might be useful for the + // future to have an actual check. + cellReference.set(cell, Section.BODY); return cellReference; } diff --git a/client/src/com/vaadin/client/widget/grid/EventCellReference.java b/client/src/com/vaadin/client/widget/grid/EventCellReference.java index 7ca1d5de75..98878339d1 100644 --- a/client/src/com/vaadin/client/widget/grid/EventCellReference.java +++ b/client/src/com/vaadin/client/widget/grid/EventCellReference.java @@ -19,6 +19,7 @@ import com.google.gwt.dom.client.TableCellElement; import com.vaadin.client.widget.escalator.Cell; import com.vaadin.client.widgets.Grid; import com.vaadin.client.widgets.Grid.Column; +import com.vaadin.client.widgets.Grid.Section; /** * A data class which contains information which identifies a cell being the @@ -33,12 +34,11 @@ import com.vaadin.client.widgets.Grid.Column; */ public class EventCellReference<T> extends CellReference<T> { - private Grid<T> grid; + private Section section; private TableCellElement element; public EventCellReference(Grid<T> grid) { super(new RowReference<T>(grid)); - this.grid = grid; } /** @@ -47,22 +47,76 @@ public class EventCellReference<T> extends CellReference<T> { * @param targetCell * cell to point to */ - public void set(Cell targetCell) { + public void set(Cell targetCell, Section section) { + Grid<T> grid = getGrid(); int row = targetCell.getRow(); int columnIndexDOM = targetCell.getColumn(); Column<?, T> column = grid.getVisibleColumns().get(columnIndexDOM); + // Row objects only make sense for body section of Grid. + T rowObject; + if (section == Section.BODY) { + rowObject = grid.getDataSource().getRow(row); + } else { + rowObject = null; + } + // At least for now we don't need to have the actual TableRowElement // available. - getRowReference().set(row, grid.getDataSource().getRow(row), null); + getRowReference().set(row, rowObject, null); + int columnIndex = grid.getColumns().indexOf(column); set(columnIndexDOM, columnIndex, column); this.element = targetCell.getElement(); + this.section = section; } @Override public TableCellElement getElement() { return element; } + + /** + * Is the cell reference for a cell in the header of the Grid. + * + * @since + * @return <code>true</true> if referenced cell is in the header, + * <code>false</code> if not + */ + public boolean isHeader() { + return section == Section.HEADER; + } + + /** + * Is the cell reference for a cell in the body of the Grid. + * + * @since + * @return <code>true</true> if referenced cell is in the body, + * <code>false</code> if not + */ + public boolean isBody() { + return section == Section.BODY; + } + + /** + * Is the cell reference for a cell in the footer of the Grid. + * + * @since + * @return <code>true</true> if referenced cell is in the footer, + * <code>false</code> if not + */ + public boolean isFooter() { + return section == Section.FOOTER; + } + + /** + * Gets the Grid section where the referenced cell is. + * + * @since + * @return grid section + */ + public Section getSection() { + return section; + } } diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index 50bc778736..f1edefc8ba 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -6202,7 +6202,7 @@ public class Grid<T> extends ResizeComposite implements assert cell != null : "received " + eventType + "-event with a null cell target"; - eventCell.set(cell); + eventCell.set(cell, getSectionFromContainer(container)); // Editor can steal focus from Grid and is still handled if (handleEditorEvent(event, container)) { @@ -6237,6 +6237,20 @@ public class Grid<T> extends ResizeComposite implements } } + private Section getSectionFromContainer(RowContainer container) { + assert container != null : "RowContainer should not be null"; + + if (container == escalator.getBody()) { + return Section.BODY; + } else if (container == escalator.getFooter()) { + return Section.FOOTER; + } else if (container == escalator.getHeader()) { + return Section.HEADER; + } + assert false : "RowContainer was not header, footer or body."; + return null; + } + private boolean isOrContainsInSpacer(Node node) { Node n = node; while (n != null && n != getElement()) { @@ -7780,4 +7794,17 @@ public class Grid<T> extends ResizeComposite implements sidebar.close(); } } + + /** + * Returns the {@link EventCellReference} for the latest event fired from + * this Grid. + * <p> + * Note: This cell reference will be updated when firing the next event. + * + * @since + * @return event cell reference + */ + public EventCellReference<T> getEventCell() { + return eventCell; + } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientContextMenuEventTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientContextMenuEventTest.java new file mode 100644 index 0000000000..b7242c87be --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientContextMenuEventTest.java @@ -0,0 +1,67 @@ +/* + * 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.client; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; + +public class GridClientContextMenuEventTest extends GridBasicClientFeaturesTest { + + @Override + public List<DesiredCapabilities> getBrowsersToTest() { + // PhantomJS doesn't support context click.. + return getBrowsersExcludingPhantomJS(); + } + + @Test + public void testContextMenuEventIsHandledCorrectly() { + setDebug(true); + openTestURL(); + + selectMenuPath("Component", "Internals", "Listeners", + "Add context menu listener"); + + openDebugLogTab(); + clearDebugMessages(); + + new Actions(getDriver()) + .moveToElement(getGridElement().getCell(0, 0), 5, 5) + .contextClick().perform(); + + assertTrue( + "Debug log was not visible", + isElementPresent(By + .xpath("//span[text() = 'Prevented opening a context menu in grid body']"))); + + new Actions(getDriver()) + .moveToElement(getGridElement().getHeaderCell(0, 0), 5, 5) + .contextClick().perform(); + + assertTrue( + "Debug log was not visible", + isElementPresent(By + .xpath("//span[text() = 'Prevented opening a context menu in grid header']"))); + + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java index 81f000c44e..12c2443c01 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java @@ -28,7 +28,10 @@ import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.ContextMenuEvent; +import com.google.gwt.event.dom.client.ContextMenuHandler; import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; @@ -52,6 +55,7 @@ import com.vaadin.client.widget.grid.CellReference; import com.vaadin.client.widget.grid.CellStyleGenerator; import com.vaadin.client.widget.grid.DetailsGenerator; import com.vaadin.client.widget.grid.EditorHandler; +import com.vaadin.client.widget.grid.EventCellReference; import com.vaadin.client.widget.grid.RendererCellReference; import com.vaadin.client.widget.grid.RowReference; import com.vaadin.client.widget.grid.RowStyleGenerator; @@ -521,6 +525,46 @@ public class GridBasicClientFeaturesWidget extends .addColumnVisibilityChangeHandler(handler); } }, listenersPath); + addMenuCommand("Add context menu listener", new ScheduledCommand() { + + HandlerRegistration handler = null; + ContextMenuHandler contextMenuHandler = new ContextMenuHandler() { + + @Override + public void onContextMenu(ContextMenuEvent event) { + event.preventDefault(); + final String location; + EventCellReference<?> cellRef = grid + .getEventCell(); + if (cellRef.isHeader()) { + location = "header"; + } else if (cellRef.isBody()) { + location = "body"; + } else if (cellRef.isFooter()) { + location = "footer"; + } else { + location = "somewhere"; + } + + getLogger().info( + "Prevented opening a context menu in grid " + + location); + } + }; + + @Override + public void execute() { + if (handler != null) { + grid.unsinkEvents(Event.ONCONTEXTMENU); + handler.removeHandler(); + } else { + grid.sinkEvents(Event.ONCONTEXTMENU); + handler = grid.addDomHandler(contextMenuHandler, + ContextMenuEvent.getType()); + } + } + + }, listenersPath); } private void createStateMenu() { |