]> source.dussan.org Git - vaadin-framework.git/commitdiff
Implement client-side editor row widget binding (#13334)
authorJohannes Dahlström <johannesd@vaadin.com>
Mon, 25 Aug 2014 08:02:09 +0000 (11:02 +0300)
committerTeemu Suo-Anttila <teemusa@vaadin.com>
Tue, 9 Sep 2014 11:44:01 +0000 (11:44 +0000)
Change-Id: I898d89cecc2d1c552a3cc32461d612d55d1babd7

client/src/com/vaadin/client/ui/grid/EditorRow.java
client/src/com/vaadin/client/ui/grid/EditorRowHandler.java [new file with mode: 0644]
client/src/com/vaadin/client/ui/grid/Grid.java
client/src/com/vaadin/client/ui/grid/GridConnector.java
shared/src/com/vaadin/shared/ui/grid/GridColumnState.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowClientTest.java
uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java

index c57ae26ff31a8b00efdd223763d4b508077bf9a7..9399898473e99e37f88a3efa1497ce8b01c3ce48 100644 (file)
@@ -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<T> {
         INACTIVE, ACTIVATING, ACTIVE, COMMITTING
     }
 
+    private Grid<T> grid;
+
+    private EditorRowHandler<T> handler;
+
     private DivElement editorOverlay = DivElement.as(DOM.createDiv());
 
-    private Grid<T> grid;
+    private List<Widget> editorWidgets = new ArrayList<Widget>();
 
     private boolean enabled = false;
     private State state = State.INACTIVE;
@@ -110,6 +118,34 @@ public class EditorRow<T> {
         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<T> 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<T> 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<T> {
      * 
      * @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<T> {
         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 (file)
index 0000000..43c43c6
--- /dev/null
@@ -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<T> {
+
+    /**
+     * 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<?, T> column);
+}
index 2b0bbc9f05ccea6cb2217fe1281df88fbc494a17..a667bfa8dd97fbe968ede53ae5b3dde4baa2ba51 100644 (file)
@@ -1571,7 +1571,7 @@ public class Grid<T> extends Composite implements
         }
     }
 
-    private int findVisibleColumnIndex(GridColumn<?, T> column) {
+    protected int findVisibleColumnIndex(GridColumn<?, T> column) {
         int idx = 0;
         for (GridColumn<?, T> c : columns) {
             if (c == column) {
@@ -1583,7 +1583,7 @@ public class Grid<T> extends Composite implements
         return -1;
     }
 
-    private GridColumn<?, T> getColumnFromVisibleIndex(int index) {
+    protected GridColumn<?, T> getColumnFromVisibleIndex(int index) {
         int idx = -1;
         for (GridColumn<?, T> c : columns) {
             if (c.isVisible()) {
@@ -2436,7 +2436,7 @@ public class Grid<T> 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);
     }-*/;
index a06e1df802ce023b4b729e687d63d88bbf4df9d5..8ff467cfd5f5d7e1166d9c7afddd5757d6a78e16 100644 (file)
@@ -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<Object> rendererConnector;
 
+        private AbstractFieldConnector editorConnector;
+
         public CustomGridColumn(String id,
                 AbstractRendererConnector<Object> 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<GridColumnState> columns = getState().columns;
             int numColumns = columns.size();
@@ -128,6 +140,18 @@ public class GridConnector extends AbstractHasComponentsConnector {
         }
     }
 
+    private class CustomEditorRowHandler implements
+            EditorRowHandler<JSONObject> {
+
+        @Override
+        public Widget getWidget(GridColumn<?, JSONObject> 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<?, JSONObject> 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);
     }
 
     /**
index b73e7cffd54fd3de99f044b03971cea8be60743b..d9c72d5ebde59e8ae8e9576275085dc0a4f72ea6 100644 (file)
@@ -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.
      */
index 5a4568259dfd6651b8fd73269172e834fa0dadb5..5c19e29f179e2faca35c26eb61d398e5080fcbcc 100644 (file)
  */
 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<WebElement> 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"));
+        }
+    }
 }
index 9cf56439d88df9672dd62d29f428da0df95a0592..8055508f7158f1ff801d7445fff8efcbb157300a 100644 (file)
@@ -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<List<Data>>() {
+            @Override
+            public Widget getWidget(GridColumn<?, List<Data>> column) {
+                TextBox tb = new TextBox();
+                tb.setText("Column " + grid.getColumns().indexOf(column));
+                return tb;
+            }
+        });
 
         sorter = new ListSorter<List<Data>>(grid);