summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPekka Hyvönen <pekka@vaadin.com>2015-02-18 10:05:25 +0200
committerPekka Hyvönen <pekka@vaadin.com>2015-02-18 12:23:23 +0200
commit9b2f51ca9ff48ad9484b8ee67770ab1a58352b35 (patch)
tree952a8f76a7e5003fd59daf0d1ebb17899ccd5f61
parentf537b9fdb2ba3993090d22011adfe247e4e2b6bd (diff)
downloadvaadin-framework-9b2f51ca9ff48ad9484b8ee67770ab1a58352b35.tar.gz
vaadin-framework-9b2f51ca9ff48ad9484b8ee67770ab1a58352b35.zip
Update server side state when columns are reordered. (#16643)
Change-Id: I96c65dbb96614a5f5782b747fb8588647211cf4b
-rw-r--r--client/src/com/vaadin/client/connectors/GridConnector.java52
-rw-r--r--server/src/com/vaadin/ui/Grid.java40
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java12
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java42
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java57
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++) {