diff options
author | Johannes Dahlström <johannesd@vaadin.com> | 2015-02-04 18:33:30 +0200 |
---|---|---|
committer | Johannes Dahlström <johannesd@vaadin.com> | 2015-02-05 15:47:46 +0000 |
commit | a15f2847950126bc87751c54d977d2f4edd45c04 (patch) | |
tree | 200d9866abb2c9334ca9c38ef58639954c562d27 | |
parent | 50724f2d0d1e225b5c24d097d3c4b8529b7a8f3f (diff) | |
download | vaadin-framework-a15f2847950126bc87751c54d977d2f4edd45c04.tar.gz vaadin-framework-a15f2847950126bc87751c54d977d2f4edd45c04.zip |
Grid columns can now be marked as non-editable (#16538)
Non-editable columns are not assigned editor fields. When the editor is active,
any non-editable content is not displayed (this should changein the future).
This is separate from setting the property or editor field read-only - in those
cases the field is still used to display the data which may not be desired and
will fail if there is no converter.
Also add Column.setEditorField(Field<?>) and the corresponding getter.
Change-Id: Ice17c357895cb63a8e1bfd6abaffc1d803399e98
10 files changed, 255 insertions, 37 deletions
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java index 827e366de0..8d383ab0ae 100644 --- a/client/src/com/vaadin/client/connectors/GridConnector.java +++ b/client/src/com/vaadin/client/connectors/GridConnector.java @@ -756,6 +756,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements column.setExpandRatio(state.expandRatio); column.setSortable(state.sortable); + column.setEditable(state.editable); column.setEditorConnector((AbstractFieldConnector) state.editorConnector); } diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index a870a732b5..303b94763d 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -1254,11 +1254,13 @@ public class Grid<T> extends ResizeComposite implements /** * Returns the editor widget associated with the given column. If the - * editor is not active, returns null. + * editor is not active or the column is not + * {@link Grid.Column#isEditable() editable}, returns null. * * @param column * the column - * @return the widget if the editor is open, null otherwise + * @return the widget if the editor is open and the column is editable, + * null otherwise */ protected Widget getWidget(Column<?, T> column) { return columnToWidget.get(column); @@ -1305,14 +1307,12 @@ public class Grid<T> extends ResizeComposite implements editorOverlay.appendChild(cell); Column<?, T> column = grid.getColumn(i); - if (column == grid.selectionColumn) { - continue; - } - - Widget editor = getHandler().getWidget(column); - if (editor != null) { - columnToWidget.put(column, editor); - attachWidget(editor, cell); + if (column.isEditable()) { + Widget editor = getHandler().getWidget(column); + if (editor != null) { + columnToWidget.put(column, editor); + attachWidget(editor, cell); + } } } @@ -1987,6 +1987,7 @@ public class Grid<T> extends ResizeComposite implements } public final class SelectionColumn extends Column<Boolean, T> { + private boolean initDone = false; SelectionColumn(final Renderer<Boolean> selectColumnRenderer) { @@ -2022,6 +2023,8 @@ public class Grid<T> extends ResizeComposite implements setWidth(-1); + setEditable(false); + initDone = true; } @@ -2074,6 +2077,17 @@ public class Grid<T> extends ResizeComposite implements public double getMinimumWidth() { return -1; } + + @Override + public Column<Boolean, T> setEditable(boolean editable) { + if (initDone) { + throw new UnsupportedOperationException( + "can't set the selection column editable"); + } + super.setEditable(editable); + return this; + } + } /** @@ -2738,6 +2752,8 @@ public class Grid<T> extends ResizeComposite implements private boolean sortable = false; + private boolean editable = true; + private String headerCaption = ""; private double minimumWidthPx = GridConstants.DEFAULT_MIN_WIDTH; @@ -3159,6 +3175,43 @@ public class Grid<T> extends ResizeComposite implements return expandRatio; } + /** + * Sets whether the values in this column should be editable by the user + * when the row editor is active. By default columns are editable. + * + * @param editable + * {@code true} to set this column editable, {@code false} + * otherwise + * @return this column + * + * @throws IllegalStateException + * if the editor is currently active + * + * @see Grid#editRow(int) + * @see Grid#isEditorActive() + */ + public Column<C, T> setEditable(boolean editable) { + if (editable != this.editable && grid.isEditorActive()) { + throw new IllegalStateException( + "Cannot change column editable status while the editor is active"); + } + this.editable = editable; + return this; + } + + /** + * Returns whether the values in this column are editable by the user + * when the row editor is active. + * + * @return {@code true} if this column is editable, {@code false} + * otherwise + * + * @see #setEditable(boolean) + */ + public boolean isEditable() { + return editable; + } + private void scheduleColumnWidthRecalculator() { if (grid != null) { grid.autoColumnWidthsRecalculator.schedule(); @@ -5782,6 +5835,15 @@ public class Grid<T> extends ResizeComposite implements } /** + * Returns whether the editor is currently open on some row. + * + * @return {@code true} if the editor is active, {@code false} otherwise. + */ + public boolean isEditorActive() { + return editor.getState() != State.INACTIVE; + } + + /** * Saves any unsaved changes in the editor to the data source. * * @throws IllegalStateException diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java index 125cc5a05a..69e23ecd92 100644 --- a/server/src/com/vaadin/ui/Grid.java +++ b/server/src/com/vaadin/ui/Grid.java @@ -1982,7 +1982,7 @@ public class Grid extends AbstractComponent implements SelectionNotifier, } /** - * Return the property id for the backing property of this Column + * Returns the property id for the backing property of this Column * * @return property id */ @@ -2302,11 +2302,14 @@ public class Grid extends AbstractComponent implements SelectionNotifier, } /** - * Should sorting controls be available for the column + * Sets whether the column should be sortable by the user. The grid can + * be sorted by a sortable column by clicking or tapping the column's + * default header. Programmatic sorting using the Grid.sort methods is + * not affected by this setting. * * @param sortable - * <code>true</code> if the sorting controls should be - * visible. + * <code>true</code> if the user should be able to sort the + * column, false otherwise * @return the column itself */ public Column setSortable(boolean sortable) { @@ -2334,7 +2337,9 @@ public class Grid extends AbstractComponent implements SelectionNotifier, } /** - * Are the sorting controls visible in the column header + * Returns whether the user is able to sort the grid by this column. + * + * @return true if the column is sortable by the user, false otherwise */ public boolean isSortable() { return state.sortable; @@ -2361,8 +2366,8 @@ public class Grid extends AbstractComponent implements SelectionNotifier, * and 2, respectively. The column with a <strong>ratio of 0 is exactly * as wide as its contents requires</strong>. The column with a ratio of * 1 is as wide as it needs, <strong>plus a third of any excess - * space</strong>, bceause we have 3 parts total, and this column - * reservs only one of those. The column with a ratio of 2, is as wide + * space</strong>, because we have 3 parts total, and this column + * reserves only one of those. The column with a ratio of 2, is as wide * as it needs to be, <strong>plus two thirds</strong> of the excess * width. * @@ -2384,7 +2389,7 @@ public class Grid extends AbstractComponent implements SelectionNotifier, } /** - * Gets the column's expand ratio. + * Returns the column's expand ratio. * * @return the column's expand ratio * @see #setExpandRatio(int) @@ -2431,7 +2436,7 @@ public class Grid extends AbstractComponent implements SelectionNotifier, } /** - * Gets the minimum width for this column. + * Return the minimum width for this column. * * @return the minimum width for this column * @see #setMinimumWidth(double) @@ -2468,7 +2473,7 @@ public class Grid extends AbstractComponent implements SelectionNotifier, } /** - * Gets the maximum width for this column. + * Returns the maximum width for this column. * * @return the maximum width for this column * @see #setMaximumWidth(double) @@ -2476,6 +2481,79 @@ public class Grid extends AbstractComponent implements SelectionNotifier, public double getMaximumWidth() { return getState().maxWidth; } + + /** + * Sets whether the properties corresponding to this column should be + * editable when the item editor is active. By default columns are + * editable. + * <p> + * Values in non-editable columns are currently not displayed when the + * editor is active, but this will probably change in the future. They + * are not automatically assigned an editor field and, if one is + * manually assigned, it is not used. Columns that cannot (or should + * not) be edited even in principle should be set non-editable. + * + * @param editable + * {@code true} if this column should be editable, + * {@code false} otherwise + * @return this column + * + * @throws IllegalStateException + * if the editor is currently active + * + * @see Grid#editItem(Object) + * @see Grid#isEditorActive() + */ + public Column setEditable(boolean editable) { + checkColumnIsAttached(); + if (grid.isEditorActive()) { + throw new IllegalStateException( + "Cannot change column editable status while the editor is active"); + } + getState().editable = editable; + grid.markAsDirty(); + return this; + } + + /** + * Returns whether the properties corresponding to this column should be + * editable when the item editor is active. + * + * @return {@code true} if this column is editable, {@code false} + * otherwise + * + * @see Grid#editItem(Object) + * @see #setEditable(boolean) + */ + + public boolean isEditable() { + return getState().editable; + } + + /** + * Sets the field component used to edit the properties in this column + * when the item editor is active. Please refer to + * {@link Grid#setEditorField(Object, Field)} for more information. + * + * @param editor + * the editor field, cannot be null + * @return this column + */ + public Column setEditorField(Field<?> editor) { + grid.setEditorField(getPropertyId(), editor); + return this; + } + + /** + * Returns the editor field used to edit the properties in this column + * when the item editor is active. Please refer to + * {@link Grid#getEditorField(Object)} for more information. + * + * @return the editor field or null if this column is not editable + */ + public Field<?> getEditorField() { + return grid.getEditorField(getPropertyId()); + } } /** @@ -4616,6 +4694,8 @@ public class Grid extends AbstractComponent implements SelectionNotifier, /** * Gets the field component that represents a property in the item editor. + * Returns null if the corresponding column is not + * {@link Column#isEditable() editable}. * <p> * When {@link #editItem(Object) editItem} is called, fields are * automatically created and bound for any unbound properties. @@ -4627,7 +4707,7 @@ public class Grid extends AbstractComponent implements SelectionNotifier, * * @param propertyId * the property id of the property for which to find the field - * @return the bound field, never null + * @return the bound field or null if the respective column is not editable * * @throws IllegalArgumentException * if there is no column for the provided property id @@ -4638,6 +4718,10 @@ public class Grid extends AbstractComponent implements SelectionNotifier, public Field<?> getEditorField(Object propertyId) { checkColumnExists(propertyId); + if (!getColumn(propertyId).isEditable()) { + return null; + } + Field<?> editor = editorFieldGroup.getField(propertyId); if (editor == null) { editor = editorFieldGroup.buildAndBind(propertyId); @@ -4651,7 +4735,8 @@ public class Grid extends AbstractComponent implements SelectionNotifier, } /** - * Opens the editor interface for the provided item. + * Opens the editor interface for the provided item. Scrolls the Grid to + * bring the item to view if it is not already visible. * * @param itemId * the id of the item to edit @@ -4683,11 +4768,8 @@ public class Grid extends AbstractComponent implements SelectionNotifier, editorFieldGroup.setItemDataSource(item); for (Column column : getColumns()) { - Object propertyId = column.getPropertyId(); - - Field<?> editor = getEditorField(propertyId); - - getColumn(propertyId).getState().editorConnector = editor; + column.getState().editorConnector = getEditorField(column + .getPropertyId()); } } diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java index 5e96f4eeae..ab17e47393 100644 --- a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java +++ b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java @@ -19,6 +19,7 @@ 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.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -37,6 +38,7 @@ import com.vaadin.shared.ui.grid.GridState; import com.vaadin.shared.util.SharedUtil; import com.vaadin.ui.Grid; import com.vaadin.ui.Grid.Column; +import com.vaadin.ui.TextField; public class GridColumns { @@ -242,6 +244,35 @@ public class GridColumns { noSortColumn.setSortable(true); } + @Test + public void testColumnsEditableByDefault() { + for (Column c : grid.getColumns()) { + assertTrue(c + " should be editable", c.isEditable()); + } + } + + @Test + public void testPropertyAndColumnEditorFieldsMatch() { + grid.setEditorField("column1", new TextField()); + assertSame(grid.getEditorField("column1"), grid.getColumn("column1") + .getEditorField()); + + grid.getColumn("column2").setEditorField(new TextField()); + assertSame(grid.getEditorField("column2"), grid.getColumn("column2") + .getEditorField()); + } + + @Test + public void testUneditableColumnHasNoField() { + Column col = grid.getColumn("column1"); + + col.setEditable(false); + + assertFalse("Column should be uneditable", col.isEditable()); + assertNull("Uneditable column should not be auto-assigned a Field", + col.getEditorField()); + } + private GridColumnState getColumnState(Object propertyId) { String columnId = columnIdMapper.key(propertyId); for (GridColumnState columnState : state.columns) { diff --git a/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java b/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java index 070d146736..4c5b2c3a02 100644 --- a/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java +++ b/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java @@ -46,6 +46,12 @@ public class GridColumnState implements Serializable { public Connector rendererConnector; /** + * Whether the values in this column are editable when the editor interface + * is active. + */ + public boolean editable = true; + + /** * The connector for the field used to edit cells in this column when the * editor interface is active. */ diff --git a/uitest/src/com/vaadin/testbench/elements/GridElement.java b/uitest/src/com/vaadin/testbench/elements/GridElement.java index 784e67d8c2..5a27bc1444 100644 --- a/uitest/src/com/vaadin/testbench/elements/GridElement.java +++ b/uitest/src/com/vaadin/testbench/elements/GridElement.java @@ -75,14 +75,31 @@ public class GridElement extends AbstractComponentElement { * Gets the editor field for column in given index. * * @param colIndex - * column index + * the column index * @return the editor field for given location + * + * @throws NoSuchElementException + * if {@code isEditable(colIndex) == false} */ public TestBenchElement getField(int colIndex) { return grid.getSubPart("#editor[" + colIndex + "]"); } /** + * Gets whether the column with the given index is editable, that is, + * has an associated editor field. + * + * @param colIndex + * the column index + * @return {@code true} if the column has an editor field, {@code false} + * otherwise + */ + public boolean isEditable(int colIndex) { + return grid + .isElementPresent(By.vaadin("#editor[" + colIndex + "]")); + } + + /** * Saves the fields of this editor. * <p> * <em>Note:</em> that this closes the editor making this element diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java index 89fff6871b..fe4a31d9e7 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -77,6 +77,7 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> { public static final String CELL_STYLE_GENERATOR_SPECIAL = "Special for 1/4 Column 1"; private static final int MANUALLY_FORMATTED_COLUMNS = 5; public static final int COLUMNS = 12; + public static final int EDITABLE_COLUMNS = COLUMNS - 1; public static final int ROWS = 1000; private int containerDelay = 0; @@ -223,7 +224,8 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> { grid.setSelectionMode(SelectionMode.NONE); - grid.getEditorField(getColumnProperty(3)).setReadOnly(true); + grid.getEditorField(getColumnProperty(2)).setReadOnly(true); + grid.getColumn(getColumnProperty(3)).setEditable(false); createGridActions(); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java index a81d374167..f6f2fac074 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java @@ -102,14 +102,14 @@ public class GridEditorClientTest extends GridBasicClientFeaturesTest { List<WebElement> widgets = editor.findElements(By .className("gwt-TextBox")); - assertEquals(GridBasicFeatures.COLUMNS, widgets.size()); + assertEquals(GridBasicFeatures.EDITABLE_COLUMNS, widgets.size()); assertEquals("(100, 0)", widgets.get(0).getAttribute("value")); assertEquals("(100, 1)", widgets.get(1).getAttribute("value")); assertEquals("(100, 2)", widgets.get(2).getAttribute("value")); - assertEquals("100", widgets.get(7).getAttribute("value")); - assertEquals("<b>100</b>", widgets.get(9).getAttribute("value")); + assertEquals("100", widgets.get(6).getAttribute("value")); + assertEquals("<b>100</b>", widgets.get(8).getAttribute("value")); } @Test @@ -186,6 +186,13 @@ public class GridEditorClientTest extends GridBasicClientFeaturesTest { .getText()); } + public void testUneditableColumn() { + selectMenuPath("Component", "Editor", "Edit row 5"); + + assertFalse("Uneditable column should not have an editor widget", + getGridElement().getEditor().isEditable(3)); + } + protected WebElement getSaveButton() { return getEditor().findElement(By.className("v-grid-editor-save")); } @@ -193,5 +200,4 @@ public class GridEditorClientTest extends GridBasicClientFeaturesTest { protected WebElement getCancelButton() { return getEditor().findElement(By.className("v-grid-editor-cancel")); } - } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java index 566946a7ea..5e11af1ca5 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java @@ -119,13 +119,13 @@ public class GridEditorTest extends GridBasicFeaturesTest { selectMenuPath(EDIT_ITEM_100); List<WebElement> widgets = getEditorWidgets(); - assertEquals("Number of widgets", GridBasicFeatures.COLUMNS, + assertEquals("Number of widgets", GridBasicFeatures.EDITABLE_COLUMNS, widgets.size()); assertEquals("(100, 0)", widgets.get(0).getAttribute("value")); assertEquals("(100, 1)", widgets.get(1).getAttribute("value")); assertEquals("(100, 2)", widgets.get(2).getAttribute("value")); - assertEquals("<b>100</b>", widgets.get(9).getAttribute("value")); + assertEquals("<b>100</b>", widgets.get(8).getAttribute("value")); } @Test @@ -191,8 +191,8 @@ public class GridEditorTest extends GridBasicFeaturesTest { private void assertEditorOpen() { assertNotNull("Editor is supposed to be open", getEditor()); - assertEquals("Unexpected number of widgets", GridBasicFeatures.COLUMNS, - getEditorWidgets().size()); + assertEquals("Unexpected number of widgets", + GridBasicFeatures.EDITABLE_COLUMNS, getEditorWidgets().size()); } private void assertEditorClosed() { @@ -287,6 +287,15 @@ public class GridEditorTest extends GridBasicFeaturesTest { originalScrollPos, getGridVerticalScrollPos()); } + @Test + public void testUneditableColumn() { + selectMenuPath(EDIT_ITEM_5); + assertEditorOpen(); + + assertFalse("Uneditable column should not have an editor widget", + getGridElement().getEditor().isEditable(3)); + } + private WebElement getSaveButton() { return getDriver().findElement(By.className("v-grid-editor-save")); } 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 7a635ad420..41d74a11a2 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java @@ -359,6 +359,8 @@ public class GridBasicClientFeaturesWidget extends column.setHeaderCaption("Header (0," + c + ")"); } + grid.getColumn(3).setEditable(false); + HeaderRow row = grid.getDefaultHeaderRow(); for (int i = 0; i < col; ++i) { String caption = "Header (0," + i + ")"; |