From 69798ea10a289afe384617def233992eb80c9fda Mon Sep 17 00:00:00 2001 From: =?utf8?q?Johannes=20Dahlstr=C3=B6m?= Date: Mon, 25 Aug 2014 11:02:09 +0300 Subject: [PATCH] Implement client-side editor row widget binding (#13334) Change-Id: I898d89cecc2d1c552a3cc32461d612d55d1babd7 --- .../com/vaadin/client/ui/grid/EditorRow.java | 62 ++++++++++++++++++- .../client/ui/grid/EditorRowHandler.java | 38 ++++++++++++ .../src/com/vaadin/client/ui/grid/Grid.java | 6 +- .../vaadin/client/ui/grid/GridConnector.java | 32 +++++++++- .../shared/ui/grid/GridColumnState.java | 9 +++ .../client/GridEditorRowClientTest.java | 21 +++++++ .../grid/GridBasicClientFeaturesWidget.java | 11 ++++ 7 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 client/src/com/vaadin/client/ui/grid/EditorRowHandler.java diff --git a/client/src/com/vaadin/client/ui/grid/EditorRow.java b/client/src/com/vaadin/client/ui/grid/EditorRow.java index c57ae26ff3..9399898473 100644 --- a/client/src/com/vaadin/client/ui/grid/EditorRow.java +++ b/client/src/com/vaadin/client/ui/grid/EditorRow.java @@ -15,6 +15,9 @@ */ package com.vaadin.client.ui.grid; +import java.util.ArrayList; +import java.util.List; + import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style; @@ -23,6 +26,7 @@ import com.google.gwt.dom.client.TableCellElement; import com.google.gwt.dom.client.TableRowElement; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ui.grid.Escalator.AbstractRowContainer; import com.vaadin.client.ui.grid.ScrollbarBundle.Direction; import com.vaadin.shared.ui.grid.ScrollDestination; @@ -43,9 +47,13 @@ public class EditorRow { INACTIVE, ACTIVATING, ACTIVE, COMMITTING } + private Grid grid; + + private EditorRowHandler handler; + private DivElement editorOverlay = DivElement.as(DOM.createDiv()); - private Grid grid; + private List editorWidgets = new ArrayList(); private boolean enabled = false; private State state = State.INACTIVE; @@ -110,6 +118,34 @@ public class EditorRow { state = State.INACTIVE; } + /** + * Returns the handler responsible for binding data and editor widgets to + * this editor row. + * + * @return the editor row handler or null if not set + */ + public EditorRowHandler getHandler() { + return handler; + } + + /** + * Sets the handler responsible for binding data and editor widgets to this + * editor row. + * + * @param rowHandler + * the new editor row handler + * + * @throws IllegalStateException + * if this editor row is currently in edit mode + */ + public void setHandler(EditorRowHandler rowHandler) { + if (state != State.INACTIVE) { + throw new IllegalStateException( + "Cannot set EditorRowHandler: EditorRow is currently in edit mode"); + } + this.handler = rowHandler; + } + public boolean isEnabled() { return enabled; } @@ -122,11 +158,16 @@ public class EditorRow { * * @throws IllegalStateException * if in edit mode and trying to disable + * @throws IllegalStateException + * if the editor row handler is not set */ public void setEnabled(boolean enabled) { if (enabled == false && state != State.INACTIVE) { throw new IllegalStateException( "Cannot disable: EditorRow is in edit mode"); + } else if (enabled == true && getHandler() == null) { + throw new IllegalStateException( + "Cannot enable: EditorRowHandler not set"); } this.enabled = enabled; } @@ -184,15 +225,30 @@ public class EditorRow { setBounds(editorOverlay, tr.getOffsetLeft(), rowTop + bodyTop - wrapperTop, tr.getOffsetWidth(), tr.getOffsetHeight()); + tableWrapper.appendChild(editorOverlay); + for (int i = 0; i < tr.getCells().getLength(); i++) { Element cell = createCell(tr.getCells().getItem(i)); + editorOverlay.appendChild(cell); - } - tableWrapper.appendChild(editorOverlay); + Widget editor = getHandler().getWidget( + grid.getColumnFromVisibleIndex(i)); + if (editor != null) { + editorWidgets.add(editor); + cell.appendChild(editor.getElement()); + Grid.setParent(editor, grid); + } + } } protected void hideOverlay() { + for (Widget w : editorWidgets) { + Grid.setParent(w, null); + } + editorWidgets.clear(); + + editorOverlay.removeAllChildren(); editorOverlay.removeFromParent(); } diff --git a/client/src/com/vaadin/client/ui/grid/EditorRowHandler.java b/client/src/com/vaadin/client/ui/grid/EditorRowHandler.java new file mode 100644 index 0000000000..43c43c67f6 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/EditorRowHandler.java @@ -0,0 +1,38 @@ +/* + * 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.ui.grid; + +import com.google.gwt.user.client.ui.Widget; + +/** + * An interface for binding widgets and data to the editor row. + * + * @since + * @author Vaadin Ltd + */ +public interface EditorRowHandler { + + /** + * Returns the widget instance that is used to edit the values in the given + * column. A null return value means the column is not editable. + * + * @param column + * the column whose values should be edited + * @return the editor widget for the column or null if the column is not + * editable + */ + public Widget getWidget(GridColumn column); +} diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 2b0bbc9f05..a667bfa8dd 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -1571,7 +1571,7 @@ public class Grid extends Composite implements } } - private int findVisibleColumnIndex(GridColumn column) { + protected int findVisibleColumnIndex(GridColumn column) { int idx = 0; for (GridColumn c : columns) { if (c == column) { @@ -1583,7 +1583,7 @@ public class Grid extends Composite implements return -1; } - private GridColumn getColumnFromVisibleIndex(int index) { + protected GridColumn getColumnFromVisibleIndex(int index) { int idx = -1; for (GridColumn c : columns) { if (c.isVisible()) { @@ -2436,7 +2436,7 @@ public class Grid extends Composite implements * @param parent * The parent to set */ - private static native final void setParent(Widget widget, Widget parent) + static native final void setParent(Widget widget, Widget parent) /*-{ widget.@com.google.gwt.user.client.ui.Widget::setParent(Lcom/google/gwt/user/client/ui/Widget;)(parent); }-*/; diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java index a06e1df802..8ff467cfd5 100644 --- a/client/src/com/vaadin/client/ui/grid/GridConnector.java +++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java @@ -30,12 +30,14 @@ import java.util.logging.Logger; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONValue; +import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ComponentConnector; import com.vaadin.client.ConnectorHierarchyChangeEvent; import com.vaadin.client.annotations.OnStateChange; import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.data.DataSource.RowHandle; import com.vaadin.client.data.RpcDataSourceConnector.RpcDataSource; +import com.vaadin.client.ui.AbstractFieldConnector; import com.vaadin.client.ui.AbstractHasComponentsConnector; import com.vaadin.client.ui.grid.GridHeader.HeaderRow; import com.vaadin.client.ui.grid.GridStaticSection.StaticCell; @@ -87,6 +89,8 @@ public class GridConnector extends AbstractHasComponentsConnector { private AbstractRendererConnector rendererConnector; + private AbstractFieldConnector editorConnector; + public CustomGridColumn(String id, AbstractRendererConnector rendererConnector) { super(rendererConnector.getRenderer()); @@ -116,6 +120,14 @@ public class GridConnector extends AbstractHasComponentsConnector { return rendererConnector; } + private AbstractFieldConnector getEditorConnector() { + return editorConnector; + } + + private void setEditorConnector(AbstractFieldConnector editorConnector) { + this.editorConnector = editorConnector; + } + private int resolveCurrentIndexFromState() { List columns = getState().columns; int numColumns = columns.size(); @@ -128,6 +140,18 @@ public class GridConnector extends AbstractHasComponentsConnector { } } + private class CustomEditorRowHandler implements + EditorRowHandler { + + @Override + public Widget getWidget(GridColumn column) { + assert column != null; + AbstractFieldConnector c = ((CustomGridColumn) column) + .getEditorConnector(); + return c != null ? c.getWidget() : null; + } + } + /** * Maps a generated column id to a grid column instance */ @@ -229,6 +253,8 @@ public class GridConnector extends AbstractHasComponentsConnector { } } }); + + getWidget().getEditorRow().setHandler(new CustomEditorRowHandler()); } @Override @@ -362,13 +388,14 @@ public class GridConnector extends AbstractHasComponentsConnector { getWidgetColumnIndex(columnIndex)); GridColumnState columnState = getState().columns.get(columnIndex); - updateColumnFromState(column, columnState); assert column instanceof CustomGridColumn : "column at index " + columnIndex + " is not a " + CustomGridColumn.class.getSimpleName() + ", but a " + column.getClass().getSimpleName(); + updateColumnFromState((CustomGridColumn) column, columnState); + if (columnState.rendererConnector != ((CustomGridColumn) column) .getRendererConnector()) { throw new UnsupportedOperationException( @@ -432,11 +459,12 @@ public class GridConnector extends AbstractHasComponentsConnector { * @param state * The state to get the data from */ - private static void updateColumnFromState(GridColumn column, + private static void updateColumnFromState(CustomGridColumn column, GridColumnState state) { column.setVisible(state.visible); column.setWidth(state.width); column.setSortable(state.sortable); + column.setEditorConnector((AbstractFieldConnector) state.editorConnector); } /** diff --git a/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java b/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java index b73e7cffd5..d9c72d5ebd 100644 --- a/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java +++ b/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java @@ -56,8 +56,17 @@ public class GridColumnState implements Serializable { */ public int width = 100; + /** + * The connector for the renderer used to render the cells in this column. + */ public Connector rendererConnector; + /** + * The connector for the field used to edit cells in this column when the + * editor row is active. + */ + public Connector editorConnector; + /** * Are sorting indicators shown for a column. Default is false. */ diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowClientTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowClientTest.java index 5a4568259d..5c19e29f17 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowClientTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowClientTest.java @@ -15,16 +15,22 @@ */ package com.vaadin.tests.components.grid.basicfeatures.client; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import java.util.List; + import org.junit.Before; import org.junit.Test; +import org.openqa.selenium.By; import org.openqa.selenium.Keys; import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; public class GridEditorRowClientTest extends GridBasicClientFeaturesTest { @@ -71,4 +77,19 @@ public class GridEditorRowClientTest extends GridBasicClientFeaturesTest { new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); assertNull(getEditorRow()); } + + @Test + public void testWidgetBinding() throws Exception { + selectMenuPath("Component", "State", "Editor row", "Edit row 100"); + WebElement editorRow = getEditorRow(); + + List widgets = editorRow.findElements(By + .className("gwt-TextBox")); + + assertEquals(GridBasicFeatures.COLUMNS, widgets.size()); + + for (int i = 0; i < GridBasicFeatures.COLUMNS; ++i) { + assertEquals("Column " + i, widgets.get(i).getAttribute("value")); + } + } } 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 9cf56439d8..8055508f71 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java @@ -27,8 +27,11 @@ import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ui.VLabel; import com.vaadin.client.ui.grid.Cell; +import com.vaadin.client.ui.grid.EditorRowHandler; import com.vaadin.client.ui.grid.FlyweightCell; import com.vaadin.client.ui.grid.Grid; import com.vaadin.client.ui.grid.Grid.AbstractGridKeyEvent; @@ -152,6 +155,14 @@ public class GridBasicClientFeaturesWidget extends grid.getElement().setId("testComponent"); grid.setDataSource(ds); grid.setSelectionMode(SelectionMode.NONE); + grid.getEditorRow().setHandler(new EditorRowHandler>() { + @Override + public Widget getWidget(GridColumn> column) { + TextBox tb = new TextBox(); + tb.setText("Column " + grid.getColumns().indexOf(column)); + return tb; + } + }); sorter = new ListSorter>(grid); -- 2.39.5