diff options
author | Pekka Hyvönen <pekka@vaadin.com> | 2015-02-18 10:05:25 +0200 |
---|---|---|
committer | Pekka Hyvönen <pekka@vaadin.com> | 2015-02-18 12:23:23 +0200 |
commit | 9b2f51ca9ff48ad9484b8ee67770ab1a58352b35 (patch) | |
tree | 952a8f76a7e5003fd59daf0d1ebb17899ccd5f61 | |
parent | f537b9fdb2ba3993090d22011adfe247e4e2b6bd (diff) | |
download | vaadin-framework-9b2f51ca9ff48ad9484b8ee67770ab1a58352b35.tar.gz vaadin-framework-9b2f51ca9ff48ad9484b8ee67770ab1a58352b35.zip |
Update server side state when columns are reordered. (#16643)
Change-Id: I96c65dbb96614a5f5782b747fb8588647211cf4b
5 files changed, 194 insertions, 9 deletions
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java index f263b47642..2ae04b2be2 100644 --- a/client/src/com/vaadin/client/connectors/GridConnector.java +++ b/client/src/com/vaadin/client/connectors/GridConnector.java @@ -50,6 +50,8 @@ import com.vaadin.client.widget.grid.RowReference; import com.vaadin.client.widget.grid.RowStyleGenerator; import com.vaadin.client.widget.grid.events.BodyClickHandler; import com.vaadin.client.widget.grid.events.BodyDoubleClickHandler; +import com.vaadin.client.widget.grid.events.ColumnReorderEvent; +import com.vaadin.client.widget.grid.events.ColumnReorderHandler; import com.vaadin.client.widget.grid.events.GridClickEvent; import com.vaadin.client.widget.grid.events.GridDoubleClickEvent; import com.vaadin.client.widget.grid.events.SelectAllEvent; @@ -360,6 +362,24 @@ public class GridConnector extends AbstractHasComponentsConnector implements } } + private ColumnReorderHandler<JsonObject> columnReorderHandler = new ColumnReorderHandler<JsonObject>() { + + @Override + public void onColumnReorder(ColumnReorderEvent<JsonObject> event) { + if (!columnsUpdatedFromState) { + List<Column<?, JsonObject>> columns = getWidget().getColumns(); + final List<String> newColumnOrder = new ArrayList<String>(); + for (Column<?, JsonObject> column : columns) { + newColumnOrder.add(((CustomGridColumn) column).id); + } + getRpcProxy(GridServerRpc.class).columnsReordered( + newColumnOrder, columnOrder); + columnOrder = newColumnOrder; + getState().columnOrder = newColumnOrder; + } + } + }; + /** * Maps a generated column id to a grid column instance */ @@ -370,13 +390,22 @@ public class GridConnector extends AbstractHasComponentsConnector implements private List<String> columnOrder = new ArrayList<String>(); /** - * updateFromState is set to true when {@link #updateSelectionFromState()} - * makes changes to selection. This flag tells the - * {@code internalSelectionChangeHandler} to not send same data straight - * back to server. Said listener sets it back to false when handling that - * event. + * {@link #selectionUpdatedFromState} is set to true when + * {@link #updateSelectionFromState()} makes changes to selection. This flag + * tells the {@code internalSelectionChangeHandler} to not send same data + * straight back to server. Said listener sets it back to false when + * handling that event. + */ + private boolean selectionUpdatedFromState; + + /** + * {@link #columnsUpdatedFromState} is set to true when + * {@link #updateColumnOrderFromState(List)} is updating the column order + * for the widget. This flag tells the {@link #columnReorderHandler} to not + * send same data straight back to server. After updates, listener sets the + * value back to false. */ - private boolean updatedFromState = false; + private boolean columnsUpdatedFromState; private RpcDataSource dataSource; @@ -386,7 +415,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements if (event.isBatchedSelection()) { return; } - if (!updatedFromState) { + if (!selectionUpdatedFromState) { for (JsonObject row : event.getRemoved()) { selectedKeys.remove(dataSource.getRowKey(row)); } @@ -398,7 +427,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements getRpcProxy(GridServerRpc.class).select( new ArrayList<String>(selectedKeys)); } else { - updatedFromState = false; + selectionUpdatedFromState = false; } } }; @@ -496,6 +525,9 @@ public class GridConnector extends AbstractHasComponentsConnector implements }); getWidget().setEditorHandler(new CustomEditorHandler()); + + getWidget().addColumnReorderHandler(columnReorderHandler); + getLayoutManager().registerDependency(this, getWidget().getElement()); layout(); } @@ -589,7 +621,9 @@ public class GridConnector extends AbstractHasComponentsConnector implements columns[i] = columnIdToColumn.get(id); i++; } + columnsUpdatedFromState = true; getWidget().setColumnOrder(columns); + columnsUpdatedFromState = false; columnOrder = stateColumnOrder; } @@ -886,7 +920,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements if (changed) { // At least for now there's no way to send the selected and/or // deselected row data. Some data is only stored as keys - updatedFromState = true; + selectionUpdatedFromState = true; getWidget().fireEvent( new SelectionEvent<JsonObject>(getWidget(), (List<JsonObject>) null, null, false)); diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java index 764960606a..72a772713f 100644 --- a/server/src/com/vaadin/ui/Grid.java +++ b/server/src/com/vaadin/ui/Grid.java @@ -18,6 +18,7 @@ package com.vaadin.ui; import java.io.Serializable; import java.lang.reflect.Method; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -70,6 +71,7 @@ import com.vaadin.event.SortEvent.SortListener; import com.vaadin.event.SortEvent.SortNotifier; import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.AbstractExtension; +import com.vaadin.server.EncodeResult; import com.vaadin.server.ErrorMessage; import com.vaadin.server.JsonCodec; import com.vaadin.server.KeyMapper; @@ -3088,6 +3090,44 @@ public class Grid extends AbstractComponent implements SelectionNotifier, fireEvent(new ItemClickEvent(Grid.this, item, itemId, propertyId, details)); } + + @Override + public void columnsReordered(List<String> newColumnOrder, + List<String> oldColumnOrder) { + final String diffStateKey = "columnOrder"; + ConnectorTracker connectorTracker = getUI() + .getConnectorTracker(); + JsonObject diffState = connectorTracker.getDiffState(Grid.this); + // discard the change if the columns have been reordered from + // the server side, as the server side is always right + if (getState(false).columnOrder.equals(oldColumnOrder)) { + // Don't mark as dirty since client has the state already + getState(false).columnOrder = newColumnOrder; + // write changes to diffState so that possible reverting the + // column order is sent to client + assert diffState.hasKey(diffStateKey) : "Field name has changed"; + Type type = null; + try { + type = (getState(false).getClass().getDeclaredField( + diffStateKey).getGenericType()); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (SecurityException e) { + e.printStackTrace(); + } + EncodeResult encodeResult = JsonCodec.encode( + getState(false).columnOrder, diffState, type, + connectorTracker); + + diffState.put(diffStateKey, encodeResult.getEncodedValue()); + // TODO fire column reorder event + } else { + // make sure the client is reverted to the order that the + // server thinks it is + diffState.remove(diffStateKey); + markAsDirty(); + } + } }); registerRpc(new EditorServerRpc() { diff --git a/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java b/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java index c90a016383..4dec5530aa 100644 --- a/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java +++ b/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java @@ -47,4 +47,16 @@ public interface GridServerRpc extends ServerRpc { * mouse event details */ void itemClick(String rowKey, String columnId, MouseEventDetails details); + + /** + * Informs the server that the columns of the Grid have been reordered. + * + * @since + * @param newColumnOrder + * a list of column ids in the new order + * @param oldColumnOrder + * a list of column ids in order before the change + */ + void columnsReordered(List<String> newColumnOrder, + List<String> oldColumnOrder); } 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 3a6aca11f2..792ef89d42 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -248,10 +248,25 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> { addFilterActions(); + addInternalActions(); + this.grid = grid; return grid; } + private void addInternalActions() { + createClickAction("Update column order without updating client", + "Internals", new Command<Grid, Void>() { + @Override + public void execute(Grid grid, Void value, Object data) { + List<Column> columns = grid.getColumns(); + grid.setColumnOrder(columns.get(1).getPropertyId(), + columns.get(0).getPropertyId()); + grid.getUI().getConnectorTracker().markClean(grid); + } + }, null); + } + private void addFilterActions() { createClickAction("Column 1 starts with \"(23\"", "Filter", new Command<Grid, Void>() { @@ -658,6 +673,33 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> { } } }, null, c); + createClickAction("Move left", getColumnProperty(c), + new Command<Grid, String>() { + + @Override + public void execute(Grid grid, String value, Object data) { + final String columnProperty = getColumnProperty((Integer) data); + List<Column> cols = grid.getColumns(); + List<Object> reordered = new ArrayList<Object>(); + boolean addAsLast = false; + for (int i = 0; i < cols.size(); i++) { + Column col = cols.get(i); + if (col.getPropertyId().equals(columnProperty)) { + if (i == 0) { + addAsLast = true; + } else { + reordered.add(i - 1, columnProperty); + } + } else { + reordered.add(col.getPropertyId()); + } + } + if (addAsLast) { + reordered.add(columnProperty); + } + grid.setColumnOrder(reordered.toArray()); + } + }, null, c); createBooleanAction("Sortable", getColumnProperty(c), true, new Command<Grid, Boolean>() { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java index 7b62ff85f9..7f4e9bb7e9 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java @@ -71,6 +71,26 @@ public class GridColumnReorderTest extends GridBasicFeaturesTest { } @Test + public void testColumnReordering_reorderingTwiceBackForth_reordered() { + // given + openTestURL(); + assertColumnHeaderOrder(0, 1, 2); + toggleColumnReordering(); + + // when + dragDefaultColumnHeader(2, 0, 10); + + // then + assertColumnHeaderOrder(2, 0, 1, 3); + + // when + dragDefaultColumnHeader(1, 3, 110); + + // then + assertColumnHeaderOrder(2, 1, 3, 0); + } + + @Test public void testColumnReordering_notEnabled_noReordering() { // given openTestURL(); @@ -83,10 +103,47 @@ public class GridColumnReorderTest extends GridBasicFeaturesTest { assertColumnHeaderOrder(0, 1, 2); } + @Test + public void testColumnReordering_userChangesRevertedByServer_columnsAreUpdated() { + // given + openTestURL(); + assertColumnHeaderOrder(0, 1, 2); + toggleColumnReordering(); + + // when + dragDefaultColumnHeader(0, 2, 10); + assertColumnHeaderOrder(1, 0, 2); + moveColumnManuallyLeftByOne(0); + + // then + assertColumnHeaderOrder(0, 1, 2); + } + + @Test + public void testColumnReordering_concurrentUpdatesFromServer_columnOrderFromServerUsed() { + // given + openTestURL(); + assertColumnHeaderOrder(0, 1, 2); + toggleColumnReordering(); + + // when + selectMenuPath(new String[] { "Component", "Internals", + "Update column order without updating client" }); + dragDefaultColumnHeader(2, 0, 10); + + // then + assertColumnHeaderOrder(1, 0, 2); + } + private void toggleColumnReordering() { selectMenuPath(COLUMN_REORDERING_PATH); } + private void moveColumnManuallyLeftByOne(int index) { + selectMenuPath(new String[] { "Component", "Columns", + "Column " + index, "Move left" }); + } + private void assertColumnHeaderOrder(int... indices) { List<TestBenchElement> headers = getGridHeaderRowCells(); for (int i = 0; i < indices.length; i++) { |