From 839c37a6ccda1f4f2d88c1210372d76dc15ebc6e Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 31 Jan 2017 09:15:50 +0200 Subject: Refactor editor API to use Binding instead of a component generator (#8368) Fixes #8366 --- documentation/components/components-grid.asciidoc | 33 ++-- server/src/main/java/com/vaadin/ui/Grid.java | 195 +++++++++++++-------- .../components/grid/EditorComponentGenerator.java | 45 ----- .../com/vaadin/ui/components/grid/EditorImpl.java | 9 +- .../server/component/grid/GridDeclarativeTest.java | 3 +- .../tests/components/grid/GridCheckBoxDisplay.java | 15 +- .../grid/GridEditingWithNoScrollBars.java | 2 +- .../components/grid/GridEditorCustomField.java | 52 ++---- .../components/grid/GridEditorMultiselect.java | 14 +- .../vaadin/tests/components/grid/GridEditorUI.java | 14 +- .../tests/components/grid/basics/GridBasics.java | 21 ++- 11 files changed, 190 insertions(+), 213 deletions(-) delete mode 100644 server/src/main/java/com/vaadin/ui/components/grid/EditorComponentGenerator.java diff --git a/documentation/components/components-grid.asciidoc b/documentation/components/components-grid.asciidoc index 67923952e3..3ea0e578f3 100644 --- a/documentation/components/components-grid.asciidoc +++ b/documentation/components/components-grid.asciidoc @@ -692,11 +692,12 @@ editor. In the editor, the input fields can be edited, as well as navigated with kbd:[Tab] and kbd:[Shift+Tab] keys. If validation fails, an error is displayed and the user can correct the inputs. -The [classname]#Editor# is accessible via [methodname]#getEditor()#, and to enable editing, you need to call [methodname]#setEnabled(true) on it. +The [classname]#Editor# is accessible via [methodname]#getEditor()#, and to enable editing, you need to call [methodname]#setEnabled(true)# on it. -The editor is based on [classname]#Binder# which is used to bind the data -to the editor. See <> for more information on setting up field components and validation by using [classname]#Binder. -The [classname]#Binder# needs to be set with [methodname]#setBinder# in [classname]#Editor#. +The editor is based on [classname]#Binder# which is used to bind the data to the editor. +See <> for more information on setting up field components and validation by using [classname]#Binder#. +For each column that should be editable, a binding should be created in the editor binder and then the column is configured to use that binding. +For simple cases where no conversion or validation is needed, it is also possible to directly use `setEditorComponent` on a `Column` to only define the editor component and a setter that updates the row object when saving. [source, java] ---- @@ -707,26 +708,22 @@ Grid grid = new Grid<>(); TextField taskField = new TextField(); CheckBox doneField = new CheckBox(); -Binder binder = new Binder<>(); -binder.bind(taskField, Todo::getTask, Todo::setTask); -binder.bind(doneField, Todo::isDone, Todo::setDone); +Binder binder = grid.getEditor().getBinder(); -grid.getEditor().setBinder(binder); -grid.getEditor().setEnabled(true); +Binding doneBinding = binder.bind( + doneField, Todo::isDone, Todo::setDone); -Column column = grid - .addColumn(todo -> String.valueOf(todo.isDone())); +Column column = grid.addColumn( + todo -> String.valueOf(todo.isDone())); column.setWidth(75); -column.setEditorComponent(doneField); - -grid.addColumn(Todo::getTask).setEditorComponent(taskField); ----- +column.setEditorBinding(doneBinding); -It is possible to customize the used editor component for each column and row, -by using [methodname]#setEditorComponentGenerator(EditorComponentGenerator)# in -[classname]#Column#. +grid.addColumn(Todo::getTask).setEditorComponent( + taskField, Todo::setTask).setExpandRatio(1); +grid.getEditor().setEnabled(true); +---- [[components.grid.editing.buffered]] === Buffered / Unbuffered Mode diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java index 7aed70461e..4052282fdc 100644 --- a/server/src/main/java/com/vaadin/ui/Grid.java +++ b/server/src/main/java/com/vaadin/ui/Grid.java @@ -42,7 +42,9 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import com.vaadin.data.Binder; +import com.vaadin.data.Binder.Binding; import com.vaadin.data.HasDataProvider; +import com.vaadin.data.HasValue; import com.vaadin.data.ValueProvider; import com.vaadin.data.provider.DataCommunicator; import com.vaadin.data.provider.DataProvider; @@ -63,6 +65,7 @@ import com.vaadin.server.Extension; import com.vaadin.server.JsonCodec; import com.vaadin.server.SerializableComparator; import com.vaadin.server.SerializableFunction; +import com.vaadin.server.Setter; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.Registration; import com.vaadin.shared.data.DataCommunicatorConstants; @@ -84,7 +87,6 @@ import com.vaadin.ui.components.grid.ColumnVisibilityChangeListener; import com.vaadin.ui.components.grid.DescriptionGenerator; import com.vaadin.ui.components.grid.DetailsGenerator; import com.vaadin.ui.components.grid.Editor; -import com.vaadin.ui.components.grid.EditorComponentGenerator; import com.vaadin.ui.components.grid.EditorImpl; import com.vaadin.ui.components.grid.Footer; import com.vaadin.ui.components.grid.FooterCell; @@ -560,8 +562,7 @@ public class Grid extends AbstractListing implements HasComponents, assert columnInternalIds.length == directions.length : "Column and sort direction counts don't match."; - List> list = new ArrayList<>( - directions.length); + List> list = new ArrayList<>(directions.length); for (int i = 0; i < columnInternalIds.length; ++i) { Column column = columnKeys.get(columnInternalIds[i]); list.add(new GridSortOrder<>(column, directions[i])); @@ -784,7 +785,7 @@ public class Grid extends AbstractListing implements HasComponents, private StyleGenerator styleGenerator = item -> null; private DescriptionGenerator descriptionGenerator; - private EditorComponentGenerator componentGenerator; + private Binding editorBinding; private String userId; @@ -793,12 +794,13 @@ public class Grid extends AbstractListing implements HasComponents, * provider. * * @param valueProvider - * the function to get values from items + * the function to get values from items, not + * null * @param renderer - * the type of value + * the type of value, not null */ protected Column(ValueProvider valueProvider, - Renderer renderer) { + Renderer renderer) { Objects.requireNonNull(valueProvider, "Value provider can't be null"); Objects.requireNonNull(renderer, "Renderer can't be null"); @@ -819,7 +821,8 @@ public class Grid extends AbstractListing implements HasComponents, Class valueType = renderer.getPresentationType(); if (Comparable.class.isAssignableFrom(valueType)) { - comparator = (a, b) -> compareComparables(valueProvider.apply(a), valueProvider.apply(b)); + comparator = (a, b) -> compareComparables( + valueProvider.apply(a), valueProvider.apply(b)); state.sortable = true; } else if (Number.class.isAssignableFrom(valueType)) { /* @@ -827,7 +830,8 @@ public class Grid extends AbstractListing implements HasComponents, * Provide explicit comparison support in this case even though * Number itself isn't Comparable. */ - comparator = (a, b) -> compareNumbers((Number) valueProvider.apply(a), + comparator = (a, b) -> compareNumbers( + (Number) valueProvider.apply(a), (Number) valueProvider.apply(b)); state.sortable = true; } else { @@ -837,7 +841,8 @@ public class Grid extends AbstractListing implements HasComponents, @SuppressWarnings("unchecked") private static int compareComparables(Object a, Object b) { - return ((Comparator) Comparator.nullsLast(Comparator.naturalOrder())).compare(a, b); + return ((Comparator) Comparator + .nullsLast(Comparator.naturalOrder())).compare(a, b); } @SuppressWarnings("unchecked") @@ -845,17 +850,20 @@ public class Grid extends AbstractListing implements HasComponents, Number valueA = a != null ? a : Double.POSITIVE_INFINITY; Number valueB = b != null ? b : Double.POSITIVE_INFINITY; // Most Number implementations are Comparable - if (valueA instanceof Comparable && valueA.getClass().isInstance(valueB)) { + if (valueA instanceof Comparable + && valueA.getClass().isInstance(valueB)) { return ((Comparable) valueA).compareTo(valueB); } else if (valueA.equals(valueB)) { return 0; } else { // Fall back to comparing based on potentially truncated values - int compare = Long.compare(valueA.longValue(), valueB.longValue()); + int compare = Long.compare(valueA.longValue(), + valueB.longValue()); if (compare == 0) { // This might still produce 0 even though the values are not // equals, but there's nothing more we can do about that - compare = Double.compare(valueA.doubleValue(), valueB.doubleValue()); + compare = Double.compare(valueA.doubleValue(), + valueB.doubleValue()); } return compare; } @@ -979,7 +987,7 @@ public class Grid extends AbstractListing implements HasComponents, "Column identifier cannot be changed"); } this.userId = id; - getParent().setColumnId(id, this); + getGrid().setColumnId(id, this); return this; } @@ -1018,7 +1026,7 @@ public class Grid extends AbstractListing implements HasComponents, Objects.requireNonNull(caption, "Header caption can't be null"); getState().caption = caption; - HeaderRow row = getParent().getDefaultHeaderRow(); + HeaderRow row = getGrid().getDefaultHeaderRow(); if (row != null) { row.getCell(this).setText(caption); } @@ -1128,7 +1136,7 @@ public class Grid extends AbstractListing implements HasComponents, Objects.requireNonNull(cellStyleGenerator, "Cell style generator must not be null"); this.styleGenerator = cellStyleGenerator; - getParent().getDataCommunicator().reset(); + getGrid().getDataCommunicator().reset(); return this; } @@ -1154,7 +1162,7 @@ public class Grid extends AbstractListing implements HasComponents, public Column setDescriptionGenerator( DescriptionGenerator cellDescriptionGenerator) { this.descriptionGenerator = cellDescriptionGenerator; - getParent().getDataCommunicator().reset(); + getGrid().getDataCommunicator().reset(); return this; } @@ -1202,7 +1210,7 @@ public class Grid extends AbstractListing implements HasComponents, checkColumnIsAttached(); if (expandRatio != getExpandRatio()) { getState().expandRatio = expandRatio; - getParent().markAsDirty(); + getGrid().markAsDirty(); } return this; } @@ -1267,8 +1275,8 @@ public class Grid extends AbstractListing implements HasComponents, } if (pixelWidth != getWidth()) { getState().width = pixelWidth; - getParent().markAsDirty(); - getParent().fireColumnResizeEvent(this, false); + getGrid().markAsDirty(); + getGrid().fireColumnResizeEvent(this, false); } return this; } @@ -1297,8 +1305,8 @@ public class Grid extends AbstractListing implements HasComponents, checkColumnIsAttached(); if (!isWidthUndefined()) { getState().width = -1; - getParent().markAsDirty(); - getParent().fireColumnResizeEvent(this, false); + getGrid().markAsDirty(); + getGrid().fireColumnResizeEvent(this, false); } return this; } @@ -1324,7 +1332,7 @@ public class Grid extends AbstractListing implements HasComponents, + maxwidth + ")"); } getState().minWidth = pixels; - getParent().markAsDirty(); + getGrid().markAsDirty(); return this; } @@ -1361,7 +1369,7 @@ public class Grid extends AbstractListing implements HasComponents, } getState().maxWidth = pixels; - getParent().markAsDirty(); + getGrid().markAsDirty(); return this; } @@ -1389,7 +1397,7 @@ public class Grid extends AbstractListing implements HasComponents, checkColumnIsAttached(); if (resizable != isResizable()) { getState().resizable = resizable; - getParent().markAsDirty(); + getGrid().markAsDirty(); } return this; } @@ -1444,8 +1452,7 @@ public class Grid extends AbstractListing implements HasComponents, checkColumnIsAttached(); if (hidden != isHidden()) { getState().hidden = hidden; - getParent().fireColumnVisibilityChangeEvent(this, hidden, - false); + getGrid().fireColumnVisibilityChangeEvent(this, hidden, false); } return this; } @@ -1511,17 +1518,19 @@ public class Grid extends AbstractListing implements HasComponents, /** * Sets whether this Column has a component displayed in Editor or not. + * A column can only be editable if an editor component or binding has + * been set. * * @param editable * {@code true} if column is editable; {@code false} if not * @return this column * - * @see #setEditorComponent(Component) - * @see #setEditorComponentGenerator(EditorComponentGenerator) + * @see #setEditorComponent(HasValue, Setter) + * @see #setEditorBinding(Binding) */ public Column setEditable(boolean editable) { - Objects.requireNonNull(componentGenerator, - "Column has no editor component defined"); + Objects.requireNonNull(editorBinding, + "Column has no editor binding or component defined"); getState().editable = editable; return this; } @@ -1537,56 +1546,91 @@ public class Grid extends AbstractListing implements HasComponents, } /** - * Sets a static editor component for this column. + * Sets an editor binding for this column. The {@link Binding} is used + * when a row is in editor mode to define how to populate an editor + * component based on the edited row and how to update an item based on + * the value in the editor component. *

- * Note: The same component cannot be used for multiple - * columns. + * To create a binding to use with a column, define a binding for the + * editor binder (grid.getEditor().getBinder()) using e.g. + * {@link Binder#forField(HasValue)}. You can also use + * {@link #setEditorComponent(HasValue, Setter)} if no validator or + * converter is needed for the binding. + *

+ * The {@link HasValue} that the binding is defined to use must be a + * {@link Component}. * - * @param component - * the editor component + * @param binding + * the binding to use for this column * @return this column * + * @see #setEditorComponent(HasValue, Setter) + * @see Binding + * @see Grid#getEditor() * @see Editor#getBinder() - * @see Editor#setBinder(Binder) - * @see #setEditorComponentGenerator(EditorComponentGenerator) */ - public Column setEditorComponent(Component component) { - Objects.requireNonNull(component, - "null is not a valid editor field"); - return setEditorComponentGenerator(t -> component); + public Column setEditorBinding(Binding binding) { + Objects.requireNonNull(binding, "null is not a valid editor field"); + + if (!(binding.getField() instanceof Component)) { + throw new IllegalArgumentException( + "Binding target must be a component."); + } + + this.editorBinding = binding; + + return setEditable(true); } /** - * Sets a component generator to provide an editor component for this - * Column. This method can be used to generate any dynamic component to - * be displayed in the editor row. + * Gets the binder binding that is currently used for this column. + * + * @return the used binder binding, or null if no binding + * is configured + * + * @see #setEditorBinding(Binding) + */ + public Binding getEditorBinding() { + return editorBinding; + } + + /** + * Sets a component and setter to use for editing values of this column + * in the editor row. This is a shorthand for use in simple cases where + * no validator or converter is needed. Use + * {@link #setEditorBinding(Binding)} to support more complex cases. *

* Note: The same component cannot be used for multiple * columns. * - * @param componentGenerator - * the editor component generator + * @param editorComponent + * the editor component + * @param setter + * a setter that stores the component value in the row item * @return this column * - * @see EditorComponentGenerator - * @see #setEditorComponent(Component) + * @see Grid#getEditor() */ - public Column setEditorComponentGenerator( - EditorComponentGenerator componentGenerator) { - Objects.requireNonNull(componentGenerator); - this.componentGenerator = componentGenerator; - return setEditable(true); + public & Component> Column setEditorComponent( + C editorComponent, Setter setter) { + Objects.requireNonNull(editorComponent, + "Editor component cannot be null"); + Objects.requireNonNull(setter, "Setter cannot be null"); + + Binding binding = getGrid().getEditor().getBinder() + .bind(editorComponent, valueProvider::apply, setter); + + return setEditorBinding(binding); } /** - * Gets the editor component generator for this Column. - * - * @return editor component generator + * Gets the grid that this column belongs to. * - * @see EditorComponentGenerator + * @return the grid that this column belongs to, or null if + * this column has not yet been associated with any grid */ - public EditorComponentGenerator getEditorComponentGenerator() { - return componentGenerator; + protected Grid getGrid() { + return getParent(); } /** @@ -1597,7 +1641,7 @@ public class Grid extends AbstractListing implements HasComponents, * if the column is no longer attached to any grid */ protected void checkColumnIsAttached() throws IllegalStateException { - if (getParent() == null) { + if (getGrid() == null) { throw new IllegalStateException( "Column is no longer attached to a grid."); } @@ -1621,7 +1665,7 @@ public class Grid extends AbstractListing implements HasComponents, ColumnState defaultState = new ColumnState(); if (getId() == null) { - setId("column" + getParent().getColumns().indexOf(this)); + setId("column" + getGrid().getColumns().indexOf(this)); } DesignAttributeHandler.writeAttribute("column-id", attributes, @@ -1672,6 +1716,7 @@ public class Grid extends AbstractListing implements HasComponents, * @param designContext * the design context */ + @SuppressWarnings("unchecked") protected void readDesign(Element design, DesignContext designContext) { Attributes attributes = design.attributes(); @@ -1690,9 +1735,10 @@ public class Grid extends AbstractListing implements HasComponents, * inline data type. It will work incorrectly for other types * but we don't support them anyway. */ - setEditorComponentGenerator(item -> new TextField( - Optional.ofNullable(valueProvider.apply(item)) - .map(Object::toString).orElse(""))); + setEditorComponent((HasValue & Component) new TextField(), + (item, value) -> { + // Ignore user value since we don't know the setter + }); setEditable(DesignAttributeHandler.readAttribute("editable", attributes, boolean.class)); } @@ -1840,7 +1886,7 @@ public class Grid extends AbstractListing implements HasComponents, /** * Creates a new {@code Grid} using the given caption - * + * * @param caption * the caption of the grid */ @@ -1852,7 +1898,7 @@ public class Grid extends AbstractListing implements HasComponents, /** * Creates a new {@code Grid} using the given caption and * {@code DataProvider} - * + * * @param caption * the caption of the grid * @param dataProvider @@ -1865,7 +1911,7 @@ public class Grid extends AbstractListing implements HasComponents, /** * Creates a new {@code Grid} using the given {@code DataProvider} - * + * * @param dataProvider * the data provider, not {@code null} */ @@ -1877,7 +1923,7 @@ public class Grid extends AbstractListing implements HasComponents, /** * Creates a new {@code Grid} using the given caption and collection of * items - * + * * @param caption * the caption of the grid * @param items @@ -2833,9 +2879,8 @@ public class Grid extends AbstractListing implements HasComponents, * */ public void sort(Column column, SortDirection direction) { - setSortOrder( - Collections - .singletonList(new GridSortOrder<>(column, direction))); + setSortOrder(Collections + .singletonList(new GridSortOrder<>(column, direction))); } /** @@ -3287,9 +3332,9 @@ public class Grid extends AbstractListing implements HasComponents, protected SerializableComparator createSortingComparator() { BinaryOperator> operator = (comparator1, - comparator2) -> SerializableComparator - .asInstance((Comparator & Serializable) comparator1 - .thenComparing(comparator2)); + comparator2) -> SerializableComparator + .asInstance((Comparator & Serializable) comparator1 + .thenComparing(comparator2)); return sortOrder.stream().map( order -> order.getSorted().getComparator(order.getDirection())) .reduce((x, y) -> 0, operator); diff --git a/server/src/main/java/com/vaadin/ui/components/grid/EditorComponentGenerator.java b/server/src/main/java/com/vaadin/ui/components/grid/EditorComponentGenerator.java deleted file mode 100644 index b33c59a891..0000000000 --- a/server/src/main/java/com/vaadin/ui/components/grid/EditorComponentGenerator.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2016 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.ui.components.grid; - -import com.vaadin.server.SerializableFunction; -import com.vaadin.ui.Component; - -/** - * A callback interface for generating an editor component corresponding to an - * editable column of a grid. The generated component will be used in the grid - * editor to edit the value of the column for the selected grid row. - * - * @author Vaadin Ltd. - * @since 8.0 - * - * @param - * the bean type this generator is compatible with - */ -@FunctionalInterface -public interface EditorComponentGenerator - extends SerializableFunction { - - /** - * Gets a component for a given {@code bean}. - * - * @param bean - * the bean this component will be used to edit - * @return the generated component - */ - @Override - public Component apply(BEAN bean); -} diff --git a/server/src/main/java/com/vaadin/ui/components/grid/EditorImpl.java b/server/src/main/java/com/vaadin/ui/components/grid/EditorImpl.java index 56bf4d6414..a001a5026a 100644 --- a/server/src/main/java/com/vaadin/ui/components/grid/EditorImpl.java +++ b/server/src/main/java/com/vaadin/ui/components/grid/EditorImpl.java @@ -24,6 +24,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import com.vaadin.data.Binder; +import com.vaadin.data.Binder.Binding; import com.vaadin.data.BinderValidationStatus; import com.vaadin.data.BinderValidationStatusHandler; import com.vaadin.shared.ui.grid.editor.EditorClientRpc; @@ -216,8 +217,12 @@ public class EditorImpl extends AbstractGridExtension getParent().getColumns().stream().filter(Column::isEditable) .forEach(c -> { - Component component = c.getEditorComponentGenerator() - .apply(edited); + Binding binding = c.getEditorBinding(); + + assert binding + .getField() instanceof Component : "Grid should enforce that the binding field is a component"; + + Component component = (Component) binding.getField(); addComponentToGrid(component); columnFields.put(c, component); getState().columnFields.put(getInternalIdForColumn(c), diff --git a/server/src/test/java/com/vaadin/tests/server/component/grid/GridDeclarativeTest.java b/server/src/test/java/com/vaadin/tests/server/component/grid/GridDeclarativeTest.java index 5cbf5eb8b1..a24d4dac15 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/grid/GridDeclarativeTest.java +++ b/server/src/test/java/com/vaadin/tests/server/component/grid/GridDeclarativeTest.java @@ -37,6 +37,7 @@ import com.vaadin.ui.Grid; import com.vaadin.ui.Grid.Column; import com.vaadin.ui.Grid.SelectionMode; import com.vaadin.ui.Label; +import com.vaadin.ui.TextField; import com.vaadin.ui.components.grid.FooterCell; import com.vaadin.ui.components.grid.FooterRow; import com.vaadin.ui.components.grid.HeaderCell; @@ -175,7 +176,7 @@ public class GridDeclarativeTest extends AbstractListingDeclarativeTest { boolean sortable = false; column1.setSortable(sortable); boolean editable = true; - column1.setEditorComponentGenerator(component -> null); + column1.setEditorComponent(new TextField(), Person::setLastName); column1.setEditable(editable); boolean resizable = false; column1.setResizable(resizable); diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridCheckBoxDisplay.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridCheckBoxDisplay.java index a09aba038c..0459294fe5 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/grid/GridCheckBoxDisplay.java +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridCheckBoxDisplay.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.List; import com.vaadin.data.Binder; +import com.vaadin.data.Binder.Binding; import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractReindeerTestUI; import com.vaadin.ui.CheckBox; @@ -41,21 +42,21 @@ public class GridCheckBoxDisplay extends AbstractReindeerTestUI { TextField taskField = new TextField(); CheckBox doneField = new CheckBox(); - Binder binder = new Binder<>(); - binder.bind(taskField, Todo::getTask, Todo::setTask); - binder.bind(doneField, Todo::isDone, Todo::setDone); + Binder binder = grid.getEditor().getBinder(); - grid.getEditor().setBinder(binder); - grid.getEditor().setEnabled(true); + Binding doneBinding = binder.bind(doneField, + Todo::isDone, Todo::setDone); Column column = grid .addColumn(todo -> String.valueOf(todo.isDone())); column.setWidth(75); - column.setEditorComponent(doneField); + column.setEditorBinding(doneBinding); grid.addColumn(Todo::getTask).setExpandRatio(1) - .setEditorComponent(taskField); + .setEditorComponent(taskField, Todo::setTask); + + grid.getEditor().setEnabled(true); grid.setSelectionMode(Grid.SelectionMode.SINGLE); diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditingWithNoScrollBars.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditingWithNoScrollBars.java index 203a69b1f0..d637151986 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditingWithNoScrollBars.java +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditingWithNoScrollBars.java @@ -41,7 +41,7 @@ public class GridEditingWithNoScrollBars extends AbstractTestUI { stCombo.setEmptySelectionAllowed(false); stCombo.setSizeFull(); - column.setEditorComponent(stCombo); + column.setEditorComponent(stCombo, Person::setLastName); grid.setSelectionMode(SelectionMode.SINGLE); grid.getEditor().setEnabled(true); diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorCustomField.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorCustomField.java index 40f8695ece..e72280860c 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorCustomField.java +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorCustomField.java @@ -15,11 +15,7 @@ */ package com.vaadin.tests.components.grid; -import java.util.HashSet; -import java.util.Set; - import com.vaadin.annotations.Theme; -import com.vaadin.data.Binder; import com.vaadin.data.provider.ListDataProvider; import com.vaadin.data.provider.Query; import com.vaadin.server.VaadinRequest; @@ -42,52 +38,36 @@ public class GridEditorCustomField extends AbstractTestUIWithLog { @Override protected void setup(VaadinRequest request) { - Grid grid = createGrid(); - ListDataProvider dataProvider = ComplexPerson .createDataProvider(100); - grid.setDataProvider(dataProvider); - - Set cities = new HashSet<>(); - dataProvider.fetch(new Query<>()).forEach(person -> { - cities.add(person.getAddress().getCity()); - }); - CustomCitySelect cityEditor = new CustomCitySelect( - cities.toArray(new String[cities.size()])); + String[] cities = dataProvider.fetch(new Query<>()) + .map(person -> person.getAddress().getCity()).distinct() + .toArray(String[]::new); + CustomCitySelect cityEditor = new CustomCitySelect(cities); TextField firstNameField = new TextField(); TextField lastNameField = new TextField(); - Binder binder = new Binder<>(); - binder.bind(firstNameField, ComplexPerson::getFirstName, - ComplexPerson::setFirstName); - binder.bind(lastNameField, ComplexPerson::getLastName, - ComplexPerson::setLastName); - binder.bind(cityEditor, person -> person.getAddress().getCity(), - (person, city) -> person.getAddress().setCity(city)); - - grid.getEditor().setBinder(binder); - grid.getColumn(ADDRESS_CITY_IDENTIFIER).setEditorComponent(cityEditor); - grid.getColumn(FIRST_NAME_IDENTIFIER) - .setEditorComponent(firstNameField); - grid.getColumn(LAST_NAME_IDENTIFIER).setEditorComponent(lastNameField); - - addComponent(grid); - } - - private Grid createGrid() { Grid grid = new Grid<>(); grid.setWidth("800px"); grid.addColumn(person -> person.getFirstName()) - .setId(FIRST_NAME_IDENTIFIER).setCaption("First Name"); + .setId(FIRST_NAME_IDENTIFIER).setCaption("First Name") + .setEditorComponent(firstNameField, + ComplexPerson::setFirstName); grid.addColumn(person -> person.getLastName()) - .setId(LAST_NAME_IDENTIFIER).setCaption("Last Name"); + .setId(LAST_NAME_IDENTIFIER).setCaption("Last Name") + .setEditorComponent(lastNameField, ComplexPerson::setLastName); grid.addColumn(person -> person.getAddress().getCity()) - .setId(ADDRESS_CITY_IDENTIFIER).setCaption("City Name"); + .setId(ADDRESS_CITY_IDENTIFIER).setCaption("City Name") + .setEditorComponent(cityEditor, + (person, city) -> person.getAddress().setCity(city)); + grid.getEditor().setEnabled(true); - return grid; + grid.setDataProvider(dataProvider); + + addComponent(grid); } public static class CustomCitySelect extends CustomField { diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorMultiselect.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorMultiselect.java index dbeb1bbc8a..b216ef9fbf 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorMultiselect.java +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorMultiselect.java @@ -3,6 +3,7 @@ package com.vaadin.tests.components.grid; import java.util.stream.IntStream; import com.vaadin.data.Binder; +import com.vaadin.data.Binder.Binding; import com.vaadin.data.converter.StringToIntegerConverter; import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractTestUI; @@ -24,17 +25,14 @@ public class GridEditorMultiselect extends AbstractTestUI { .addColumn(Person::getAge, new NumberRenderer()) .setCaption("age"); - Binder binder = new Binder<>(); - grid.getEditor().setBinder(binder); + Binder binder = grid.getEditor().getBinder(); - TextField name = new TextField(); - nameColumn.setEditorComponent(name); - binder.bind(name, Person::getFirstName, Person::setFirstName); + nameColumn.setEditorComponent(new TextField(), Person::setFirstName); - TextField age = new TextField(); - ageColumn.setEditorComponent(age); - binder.forField(age).withConverter(new StringToIntegerConverter("")) + Binding ageBinding = binder.forField(new TextField()) + .withConverter(new StringToIntegerConverter("")) .bind(Person::getAge, Person::setAge); + ageColumn.setEditorBinding(ageBinding); grid.setItems(IntStream.range(0, 30).mapToObj(this::createPerson)); diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorUI.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorUI.java index bf8b997f80..d2d865498e 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorUI.java +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridEditorUI.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Random; -import com.vaadin.data.Binder; import com.vaadin.server.VaadinRequest; import com.vaadin.tests.components.AbstractTestUI; import com.vaadin.tests.util.Person; @@ -67,9 +66,6 @@ public class GridEditorUI extends AbstractTestUI { protected Grid createGrid() { Grid grid = new Grid<>(); - Binder binder = new Binder<>(); - grid.getEditor().setBinder(binder); - grid.addColumn(Person::getEmail).setCaption("Email"); Column fistNameColumn = grid .addColumn(Person::getFirstName).setCaption("First Name"); @@ -88,19 +84,15 @@ public class GridEditorUI extends AbstractTestUI { grid.getEditor().setEnabled(true); PasswordField passwordField = new PasswordField(); - fistNameColumn.setEditorComponent(passwordField); - binder.bind(passwordField, Person::getFirstName, Person::setFirstName); + fistNameColumn.setEditorComponent(passwordField, Person::setFirstName); TextField lastNameEditor = new TextField(); - lastNameColumn.setEditorComponent(lastNameEditor); + lastNameColumn.setEditorComponent(lastNameEditor, Person::setLastName); lastNameEditor.setMaxLength(50); - binder.bind(lastNameEditor, Person::getLastName, Person::setLastName); TextField phoneEditor = new TextField(); phoneEditor.setReadOnly(true); - phoneColumn.setEditorComponent(phoneEditor); - binder.bind(phoneEditor, Person::getPhoneNumber, - Person::setPhoneNumber); + phoneColumn.setEditorComponent(phoneEditor, Person::setPhoneNumber); return grid; } diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java b/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java index 208f91d71d..eabf281bbd 100644 --- a/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java +++ b/uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java @@ -16,6 +16,7 @@ import java.util.stream.Stream; import com.vaadin.annotations.Theme; import com.vaadin.annotations.Widgetset; import com.vaadin.data.Binder; +import com.vaadin.data.Binder.Binding; import com.vaadin.data.converter.StringToIntegerConverter; import com.vaadin.event.selection.MultiSelectionEvent; import com.vaadin.event.selection.SingleSelectionEvent; @@ -199,38 +200,40 @@ public class GridBasics extends AbstractTestUIWithLog { TextField coordinates = new TextField(); TextField rowNumber = new TextField(); - binder.bind(html, DataObject::getHtmlString, DataObject::setHtmlString); - binder.forField(smallRandom) + Binding smallRandomBinding = binder + .forField(smallRandom) .withConverter(new StringToIntegerConverter( "Could not convert value to Integer")) .withValidator(i -> i >= 0 && i < 5, "Small random needs to be in range [0..5)") .bind(DataObject::getSmallRandom, DataObject::setSmallRandom); - binder.bind(coordinates, DataObject::getCoordinates, - DataObject::setCoordinates); - binder.forField(rowNumber) + Binding rowNumberBinding = binder + .forField(rowNumber) .withConverter(new StringToIntegerConverter( "Could not convert value to Integer")) .bind(DataObject::getRowNumber, DataObject::setRowNumber); grid.addColumn(DataObject::getCoordinates) - .setCaption(COLUMN_CAPTIONS[0]).setEditorComponent(coordinates); + .setCaption(COLUMN_CAPTIONS[0]) + .setEditorComponent(coordinates, DataObject::setCoordinates); grid.addColumn(dataObj -> "(" + dataObj.getRowNumber() + ", 1)") .setCaption(COLUMN_CAPTIONS[1]); grid.addColumn(dataObj -> "(" + dataObj.getRowNumber() + ", 2)") .setCaption(COLUMN_CAPTIONS[2]); grid.addColumn(DataObject::getRowNumber, new NumberRenderer()) - .setCaption(COLUMN_CAPTIONS[3]).setEditorComponent(rowNumber); + .setCaption(COLUMN_CAPTIONS[3]) + .setEditorBinding(rowNumberBinding); grid.addColumn(DataObject::getDate, new DateRenderer()) .setCaption(COLUMN_CAPTIONS[4]); grid.addColumn(DataObject::getHtmlString, new HtmlRenderer()) - .setCaption(COLUMN_CAPTIONS[5]).setEditorComponent(html); + .setCaption(COLUMN_CAPTIONS[5]) + .setEditorComponent(html, DataObject::setHtmlString); grid.addColumn(DataObject::getBigRandom, new NumberRenderer()) .setCaption(COLUMN_CAPTIONS[6]); grid.addColumn(data -> data.getSmallRandom() / 5d, new ProgressBarRenderer()).setCaption(COLUMN_CAPTIONS[7]) - .setEditorComponent(smallRandom); + .setEditorBinding(smallRandomBinding); selectionListenerRegistration = ((SingleSelectionModelImpl) grid .getSelectionModel()) -- cgit v1.2.3