summaryrefslogtreecommitdiffstats
path: root/compatibility-server
diff options
context:
space:
mode:
Diffstat (limited to 'compatibility-server')
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/fieldgroup/FieldGroup.java45
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java80
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/GridEditorMissingPropertyTest.java334
3 files changed, 441 insertions, 18 deletions
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/fieldgroup/FieldGroup.java b/compatibility-server/src/main/java/com/vaadin/v7/data/fieldgroup/FieldGroup.java
index 1055d1921d..553bbc753c 100644
--- a/compatibility-server/src/main/java/com/vaadin/v7/data/fieldgroup/FieldGroup.java
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/fieldgroup/FieldGroup.java
@@ -99,6 +99,13 @@ public class FieldGroup implements Serializable {
public void setItemDataSource(Item itemDataSource) {
this.itemDataSource = itemDataSource;
+ bindFields();
+ }
+
+ /**
+ * Binds all fields to the properties in the item in use.
+ */
+ protected void bindFields() {
for (Field<?> f : fieldToPropertyId.keySet()) {
bind(f, fieldToPropertyId.get(f));
}
@@ -254,20 +261,7 @@ public class FieldGroup implements Serializable {
fieldToPropertyId.put(field, propertyId);
propertyIdToField.put(propertyId, field);
if (itemDataSource == null) {
- // Clear any possible existing binding to clear the field
- field.setPropertyDataSource(null);
- boolean fieldReadOnly = field.isReadOnly();
- if (!fieldReadOnly) {
- field.clear();
- } else {
- // Temporarily make the field read-write so we can clear the
- // value. Needed because setPropertyDataSource(null) does not
- // currently clear the field
- // (https://dev.vaadin.com/ticket/14733)
- field.setReadOnly(false);
- field.clear();
- field.setReadOnly(true);
- }
+ clearField(field);
// Will be bound when data source is set
return;
@@ -279,6 +273,29 @@ public class FieldGroup implements Serializable {
}
/**
+ * Clears field and any possible existing binding.
+ *
+ * @param field
+ * The field to be cleared
+ */
+ protected void clearField(Field<?> field) {
+ // Clear any possible existing binding to clear the field
+ field.setPropertyDataSource(null);
+ boolean fieldReadOnly = field.isReadOnly();
+ if (!fieldReadOnly) {
+ field.clear();
+ } else {
+ // Temporarily make the field read-write so we can clear the
+ // value. Needed because setPropertyDataSource(null) does not
+ // currently clear the field
+ // (https://dev.vaadin.com/ticket/14733)
+ field.setReadOnly(false);
+ field.clear();
+ field.setReadOnly(true);
+ }
+ }
+
+ /**
* Wrap property to transactional property.
*/
protected <T> Property.Transactional<T> wrapInTransactionalProperty(
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java b/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java
index f5399f60ce..e48e58824f 100644
--- a/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java
+++ b/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java
@@ -104,6 +104,7 @@ import com.vaadin.v7.event.SelectionEvent.SelectionListener;
import com.vaadin.v7.event.SelectionEvent.SelectionNotifier;
import com.vaadin.v7.server.communication.data.DataGenerator;
import com.vaadin.v7.server.communication.data.RpcDataProviderExtension;
+import com.vaadin.v7.shared.ui.grid.ColumnResizeMode;
import com.vaadin.v7.shared.ui.grid.EditorClientRpc;
import com.vaadin.v7.shared.ui.grid.EditorServerRpc;
import com.vaadin.v7.shared.ui.grid.GridClientRpc;
@@ -566,6 +567,35 @@ public class Grid extends AbstractComponent
}
return field;
}
+
+ @Override
+ protected void bindFields() {
+ List<Field<?>> fields = new ArrayList<>(getFields());
+ Item itemDataSource = getItemDataSource();
+
+ if (itemDataSource == null) {
+ unbindFields(fields);
+ } else {
+ bindFields(fields, itemDataSource);
+ }
+ }
+
+ private void unbindFields(List<Field<?>> fields) {
+ for (Field<?> field : fields) {
+ clearField(field);
+ unbind(field);
+ field.setParent(null);
+ }
+ }
+
+ private void bindFields(List<Field<?>> fields, Item itemDataSource) {
+ for (Field<?> field : fields) {
+ if (itemDataSource
+ .getItemProperty(getPropertyId(field)) != null) {
+ bind(field, getPropertyId(field));
+ }
+ }
+ }
}
/**
@@ -2242,8 +2272,9 @@ public class Grid extends AbstractComponent
Renderer<?> renderer = column.getRenderer();
Item item = cell.getItem();
- Object modelValue = item.getItemProperty(cell.getPropertyId())
- .getValue();
+ Property itemProperty = item.getItemProperty(cell.getPropertyId());
+ Object modelValue = itemProperty == null ? null
+ : itemProperty.getValue();
data.put(columnKeys.key(cell.getPropertyId()), AbstractRenderer
.encodeValue(modelValue, renderer, converter, getLocale()));
@@ -4583,6 +4614,12 @@ public class Grid extends AbstractComponent
private boolean editorSaving = false;
private FieldGroup editorFieldGroup = new CustomFieldGroup();
+ /**
+ * Poperty ID to Field mapping that stores editor fields set by
+ * {@link #setEditorField(Object, Field)}.
+ */
+ private Map<Object, Field<?>> editorFields = new HashMap<>();
+
private CellStyleGenerator cellStyleGenerator;
private RowStyleGenerator rowStyleGenerator;
@@ -5286,6 +5323,27 @@ public class Grid extends AbstractComponent
}
/**
+ * Sets the column resize mode to use. The default mode is
+ * {@link ColumnResizeMode#ANIMATED}.
+ *
+ * @param mode
+ * a ColumnResizeMode value
+ */
+ public void setColumnResizeMode(ColumnResizeMode mode) {
+ getState().columnResizeMode = mode;
+ }
+
+ /**
+ * Returns the current column resize mode. The default mode is
+ * {@link ColumnResizeMode#ANIMATED}.
+ *
+ * @return a ColumnResizeMode value
+ */
+ public ColumnResizeMode getColumnResizeMode() {
+ return getState(false).columnResizeMode;
+ }
+
+ /**
* Creates a new column based on a property id and appends it as the last
* column.
*
@@ -6868,6 +6926,16 @@ public class Grid extends AbstractComponent
Field<?> editor = editorFieldGroup.getField(propertyId);
+ // If field group has no field for this property, see if we have it
+ // stored
+ if (editor == null) {
+ editor = editorFields.get(propertyId);
+ if (editor != null) {
+ editorFieldGroup.bind(editor, propertyId);
+ }
+ }
+
+ // Otherwise try to build one
try {
if (editor == null) {
editor = editorFieldGroup.buildAndBind(propertyId);
@@ -6923,8 +6991,9 @@ public class Grid extends AbstractComponent
editorFieldGroup.setItemDataSource(item);
for (Column column : getColumns()) {
- column.getState().editorConnector = getEditorField(
- column.getPropertyId());
+ column.getState().editorConnector = item
+ .getItemProperty(column.getPropertyId()) == null ? null
+ : getEditorField(column.getPropertyId());
}
editorActive = true;
@@ -6953,6 +7022,9 @@ public class Grid extends AbstractComponent
field.setParent(this);
editorFieldGroup.bind(field, propertyId);
}
+
+ // Store field for this property for future reference
+ editorFields.put(propertyId, field);
}
/**
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/GridEditorMissingPropertyTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/GridEditorMissingPropertyTest.java
new file mode 100644
index 0000000000..be6334f8cc
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/GridEditorMissingPropertyTest.java
@@ -0,0 +1,334 @@
+/*
+ * 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.v7.tests.server.component.grid;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.v7.data.Item;
+import com.vaadin.v7.data.Property;
+import com.vaadin.v7.data.fieldgroup.FieldGroup;
+import com.vaadin.v7.data.util.AbstractInMemoryContainer;
+import com.vaadin.v7.data.util.BeanItem;
+import com.vaadin.v7.ui.Field;
+import com.vaadin.v7.ui.PasswordField;
+import com.vaadin.v7.ui.TextField;
+
+public class GridEditorMissingPropertyTest {
+
+ private static final String PROPERTY_NAME = "name";
+ private static final String PROPERTY_SIZE = "size";
+
+ private static final String FOLDER_NAME_BEFORE = "Folder name";
+ private static final String FOLDER_NAME_AFTER = "Modified folder name";
+ private static final String FILE_NAME_BEFORE = "File name";
+ private static final String FILE_NAME_AFTER = "Modified file name";
+ private static final String FILE_SIZE_BEFORE = "10kB";
+ private static final String FILE_SIZE_AFTER = "20MB";
+
+ private final Grid grid = new Grid();
+
+ // Test items
+ private final Folder folder = new Folder(FOLDER_NAME_BEFORE);
+ private final File file = new File(FILE_NAME_BEFORE, FILE_SIZE_BEFORE);
+
+ @Before
+ public void setup() throws SecurityException, NoSuchMethodException {
+ final BeanItem<Entry> folderItem = new BeanItem<>(folder);
+ final BeanItem<Entry> childItem = new BeanItem<>(file);
+
+ @SuppressWarnings("unchecked")
+ TestContainer container = new TestContainer(
+ Arrays.asList(folderItem, childItem),
+ Arrays.asList(PROPERTY_NAME, PROPERTY_SIZE));
+
+ grid.setContainerDataSource(container);
+ grid.setSelectionMode(Grid.SelectionMode.SINGLE);
+ grid.setEditorEnabled(true);
+ }
+
+ @Test
+ public void testBindFields() {
+ FieldGroup fieldGroup = grid.getEditorFieldGroup();
+
+ // Item with incomplete property set
+ fieldGroup.setItemDataSource(
+ grid.getContainerDataSource().getItem(folder));
+ grid.getColumn(PROPERTY_NAME).getEditorField(); // called in
+ // grid.doEditItem
+ assertTrue("Properties in item should be bound",
+ fieldGroup.getBoundPropertyIds().contains(PROPERTY_NAME));
+ assertFalse("Properties not present in item should not be bound",
+ fieldGroup.getBoundPropertyIds().contains(PROPERTY_SIZE));
+ assertTrue("All of item's properties should be bound",
+ fieldGroup.getUnboundPropertyIds().isEmpty());
+
+ // Unbind all fields
+ fieldGroup.setItemDataSource(null);
+ assertTrue("No properties should be bound",
+ fieldGroup.getBoundPropertyIds().isEmpty());
+ assertTrue("No unbound properties should exist",
+ fieldGroup.getUnboundPropertyIds().isEmpty());
+
+ // Item with complete property set
+ fieldGroup
+ .setItemDataSource(grid.getContainerDataSource().getItem(file));
+ grid.getColumn(PROPERTY_NAME).getEditorField();
+ grid.getColumn(PROPERTY_SIZE).getEditorField();
+ assertTrue("Properties in item should be bound",
+ fieldGroup.getBoundPropertyIds().contains(PROPERTY_NAME));
+ assertTrue("Properties in item should be bound",
+ fieldGroup.getBoundPropertyIds().contains(PROPERTY_SIZE));
+ assertTrue("All of item's properties should be bound",
+ fieldGroup.getUnboundPropertyIds().isEmpty());
+
+ // Unbind all fields
+ fieldGroup.setItemDataSource(null);
+ assertTrue("No properties should be bound",
+ fieldGroup.getBoundPropertyIds().isEmpty());
+ assertTrue("No unbound properties should exist",
+ fieldGroup.getUnboundPropertyIds().isEmpty());
+ }
+
+ @Test
+ public void testSetEditorField() {
+ FieldGroup fieldGroup = grid.getEditorFieldGroup();
+ Field editorField = new PasswordField();
+
+ // Explicitly set editor field
+ fieldGroup.setItemDataSource(
+ grid.getContainerDataSource().getItem(folder));
+ grid.getColumn(PROPERTY_NAME).setEditorField(editorField);
+ assertTrue("Editor field should be the one that was previously set",
+ grid.getColumn(PROPERTY_NAME).getEditorField() == editorField);
+
+ // Reset item
+ fieldGroup.setItemDataSource(null);
+ fieldGroup
+ .setItemDataSource(grid.getContainerDataSource().getItem(file));
+ assertTrue("Editor field should be the one that was previously set",
+ grid.getColumn(PROPERTY_NAME).getEditorField() == editorField);
+ }
+
+ @Test
+ public void testEditCell() {
+ // Row with missing property
+ startEdit(folder);
+ assertEquals(folder, grid.getEditedItemId());
+ assertEquals(getEditedItem(),
+ grid.getEditorFieldGroup().getItemDataSource());
+
+ assertEquals(FOLDER_NAME_BEFORE,
+ grid.getColumn(PROPERTY_NAME).getEditorField().getValue());
+ try {
+ grid.getColumn(PROPERTY_SIZE).getEditorField();
+ fail("Grid.editorFieldGroup should throw BindException by default");
+ } catch (FieldGroup.BindException e) {
+ // BindException is thrown using the default FieldGroup
+ }
+ grid.cancelEditor();
+
+ // Row with all properties
+ startEdit(file);
+ assertEquals(file, grid.getEditedItemId());
+ assertEquals(getEditedItem(),
+ grid.getEditorFieldGroup().getItemDataSource());
+
+ assertEquals(FILE_NAME_BEFORE,
+ grid.getColumn(PROPERTY_NAME).getEditorField().getValue());
+ assertEquals(FILE_SIZE_BEFORE,
+ grid.getColumn(PROPERTY_SIZE).getEditorField().getValue());
+ grid.cancelEditor();
+ }
+
+ @Test
+ public void testCancelEditor() {
+ // Row with all properties
+ testCancel(file, PROPERTY_NAME, FILE_NAME_BEFORE, FILE_NAME_AFTER);
+ testCancel(file, PROPERTY_SIZE, FILE_SIZE_BEFORE, FILE_SIZE_AFTER);
+
+ // Row with missing property
+ testCancel(folder, PROPERTY_NAME, FOLDER_NAME_BEFORE,
+ FOLDER_NAME_AFTER);
+ }
+
+ private void testCancel(Object itemId, String propertyId,
+ String valueBefore, String valueAfter) {
+ startEdit(itemId);
+
+ TextField field = (TextField) grid.getColumn(propertyId)
+ .getEditorField();
+ field.setValue(valueAfter);
+
+ Property<?> datasource = field.getPropertyDataSource();
+
+ grid.cancelEditor();
+ assertFalse(grid.isEditorActive());
+ assertNull(grid.getEditedItemId());
+ assertFalse(field.isModified());
+ assertEquals("", field.getValue());
+ assertEquals(valueBefore, datasource.getValue());
+ assertNull(field.getPropertyDataSource());
+ assertNull(grid.getEditorFieldGroup().getItemDataSource());
+ }
+
+ @Test
+ public void testSaveEditor() throws Exception {
+ // Row with all properties
+ testSave(file, PROPERTY_SIZE, FILE_SIZE_BEFORE, FILE_SIZE_AFTER);
+
+ // Row with missing property
+ testSave(folder, PROPERTY_NAME, FOLDER_NAME_BEFORE, FOLDER_NAME_AFTER);
+ }
+
+ private void testSave(Object itemId, String propertyId, String valueBefore,
+ String valueAfter) throws Exception {
+ startEdit(itemId);
+ TextField field = (TextField) grid.getColumn(propertyId)
+ .getEditorField();
+
+ field.setValue(valueAfter);
+ assertEquals(valueBefore, field.getPropertyDataSource().getValue());
+
+ grid.saveEditor();
+ assertTrue(grid.isEditorActive());
+ assertFalse(field.isModified());
+ assertEquals(valueAfter, field.getValue());
+ assertEquals(valueAfter, getEditedProperty(propertyId).getValue());
+ grid.cancelEditor();
+ }
+
+ private Item getEditedItem() {
+ assertNotNull(grid.getEditedItemId());
+ return grid.getContainerDataSource().getItem(grid.getEditedItemId());
+ }
+
+ private Property<?> getEditedProperty(Object propertyId) {
+ return getEditedItem().getItemProperty(propertyId);
+ }
+
+ private void startEdit(Object itemId) {
+ grid.setEditorEnabled(true);
+ grid.editItem(itemId);
+ // Simulate succesful client response to actually start the editing.
+ grid.doEditItem();
+ }
+
+ private class TestContainer
+ extends AbstractInMemoryContainer<Object, String, BeanItem> {
+
+ private final List<BeanItem<Entry>> items;
+ private final List<String> pids;
+
+ public TestContainer(List<BeanItem<Entry>> items, List<String> pids) {
+ this.items = items;
+ this.pids = pids;
+ }
+
+ @Override
+ protected List<Object> getAllItemIds() {
+ List<Object> ids = new ArrayList<>();
+ for (BeanItem<Entry> item : items) {
+ ids.add(item.getBean());
+ }
+ return ids;
+ }
+
+ @Override
+ protected BeanItem<Entry> getUnfilteredItem(Object itemId) {
+ for (BeanItem<Entry> item : items) {
+ if (item.getBean().equals(itemId)) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Collection<?> getContainerPropertyIds() {
+ return pids;
+ }
+
+ @Override
+ public Property getContainerProperty(Object itemId, Object propertyId) {
+ return getItem(itemId).getItemProperty(propertyId);
+ }
+
+ @Override
+ public Class<?> getType(Object propertyId) {
+ return String.class;
+ }
+ }
+
+ public class Entry {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Entry(String name) {
+ this.name = name;
+ }
+ }
+
+ public class Folder extends Entry {
+
+ public Folder(String name) {
+ super(name);
+ }
+ }
+
+ public class File extends Entry {
+ private String size;
+
+ public File(String name, String size) {
+ super(name);
+ this.size = size;
+ }
+
+ public String getSize() {
+ return size;
+ }
+
+ public void setSize(String size) {
+ this.size = size;
+ }
+ }
+
+ private class Grid extends com.vaadin.v7.ui.Grid {
+ @Override
+ protected void doEditItem() {
+ super.doEditItem();
+ }
+ }
+}