summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeemu Suo-Anttila <teemusa@vaadin.com>2014-11-21 13:19:29 +0200
committerHenrik Paul <henrik@vaadin.com>2014-11-25 13:15:29 +0000
commit93436e79914c6d922c80efa387e8c539c68a68fc (patch)
treea9115e6e534dd2a2c628261ed05c87f53d1c6b03
parentab9aa7a27ac9dff880f3b0e0b2fa6868cd7dfe4a (diff)
downloadvaadin-framework-93436e79914c6d922c80efa387e8c539c68a68fc.tar.gz
vaadin-framework-93436e79914c6d922c80efa387e8c539c68a68fc.zip
Fix Grid server-side header merging and setup (#13334)
This implements simple error handling for broken headers and footers in client side. Change-Id: Ic1f1709720fa0b85e5c4c807462a9f9c7eb6f00e
-rw-r--r--client/src/com/vaadin/client/ui/grid/Grid.java8
-rw-r--r--client/src/com/vaadin/client/ui/grid/GridConnector.java19
-rw-r--r--client/src/com/vaadin/client/ui/grid/GridStaticSection.java106
-rw-r--r--server/src/com/vaadin/ui/components/grid/Grid.java26
-rw-r--r--server/src/com/vaadin/ui/components/grid/GridFooter.java4
-rw-r--r--server/src/com/vaadin/ui/components/grid/GridHeader.java17
-rw-r--r--server/src/com/vaadin/ui/components/grid/GridStaticSection.java118
-rw-r--r--server/tests/src/com/vaadin/tests/server/component/grid/GridStaticSection.java25
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java8
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColspans.java9
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java35
11 files changed, 253 insertions, 122 deletions
diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java
index 03e6c80d87..b9e0df3f72 100644
--- a/client/src/com/vaadin/client/ui/grid/Grid.java
+++ b/client/src/com/vaadin/client/ui/grid/Grid.java
@@ -3185,6 +3185,14 @@ public class Grid<T> extends ResizeComposite implements
column.reapplyWidth();
}
+ // Recalculate all the colspans
+ for (HeaderRow row : header.getRows()) {
+ row.calculateColspans();
+ }
+ for (FooterRow row : footer.getRows()) {
+ row.calculateColspans();
+ }
+
refreshHeader();
refreshBody();
refreshFooter();
diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java
index 24ea3ec433..d41d6e5ccb 100644
--- a/client/src/com/vaadin/client/ui/grid/GridConnector.java
+++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java
@@ -449,7 +449,8 @@ public class GridConnector extends AbstractHasComponentsConnector implements
.size()];
int i = 0;
for (String id : stateColumnOrder) {
- columns[i++] = columnIdToColumn.get(id);
+ columns[i] = columnIdToColumn.get(id);
+ i++;
}
getWidget().setColumnOrder(columns);
columnOrder = stateColumnOrder;
@@ -484,18 +485,14 @@ public class GridConnector extends AbstractHasComponentsConnector implements
updateStaticCellFromState(cell, cellState);
}
- for (List<String> group : rowState.cellGroups) {
+ for (Set<String> group : rowState.cellGroups.keySet()) {
GridColumn<?, ?>[] columns = new GridColumn<?, ?>[group.size()];
- String firstId = group.get(0);
- CellState cellState = null;
- for (CellState c : rowState.cells) {
- if (c.columnId.equals(firstId)) {
- cellState = c;
- }
- }
+ CellState cellState = rowState.cellGroups.get(group);
- for (int i = 0; i < group.size(); ++i) {
- columns[i] = columnIdToColumn.get(group.get(i));
+ int i = 0;
+ for (String columnId : group) {
+ columns[i] = columnIdToColumn.get(columnId);
+ i++;
}
// Set state to be the same as first in group.
diff --git a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java
index 52ea80c52b..3ffd37fcff 100644
--- a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java
+++ b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java
@@ -16,12 +16,11 @@
package com.vaadin.client.ui.grid;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.shared.ui.grid.GridStaticCellType;
@@ -191,16 +190,25 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
private GridStaticSection<?> section;
- private Collection<List<GridColumn<?, ?>>> cellGroups = new HashSet<List<GridColumn<?, ?>>>();
+ /**
+ * Map from set of spanned columns to cell meta data.
+ */
+ private Map<Set<GridColumn<?, ?>>, CELLTYPE> cellGroups = new HashMap<Set<GridColumn<?, ?>>, CELLTYPE>();
/**
- * Returns the cell on given GridColumn.
+ * Returns the cell on given GridColumn. If the column is merged
+ * returned cell is the cell for the whole group.
*
* @param column
* the column in grid
- * @return the cell on given column, null if not found
+ * @return the cell on given column, merged cell for merged columns,
+ * null if not found
*/
public CELLTYPE getCell(GridColumn<?, ?> column) {
+ Set<GridColumn<?, ?>> cellGroup = getCellGroupForColumn(column);
+ if (cellGroup != null) {
+ return cellGroups.get(cellGroup);
+ }
return cells.get(column);
}
@@ -218,9 +226,7 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
"You can't merge less than 2 columns together.");
}
- final List<?> columnList = section.grid.getColumns();
- int firstIndex = columnList.indexOf(columns[0]);
- int i = 0;
+ HashSet<GridColumn<?, ?>> columnGroup = new HashSet<GridColumn<?, ?>>();
for (GridColumn<?, ?> column : columns) {
if (!cells.containsKey(column)) {
throw new IllegalArgumentException(
@@ -228,22 +234,17 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
} else if (getCellGroupForColumn(column) != null) {
throw new IllegalStateException(
"Column is already in a group.");
- } else if (!column.equals(columnList.get(firstIndex + (i++)))) {
- throw new IllegalStateException(
- "Columns are in invalid order or not in a continuous range");
}
+ columnGroup.add(column);
}
- cellGroups.add(Arrays.asList(columns));
CELLTYPE joinedCell = createCell();
+ cellGroups.put(columnGroup, joinedCell);
joinedCell.setSection(getSection());
- for (GridColumn<?, ?> column : columns) {
- cells.put(column, joinedCell);
- }
calculateColspans();
- return getCell(columns[0]);
+ return joinedCell;
}
/**
@@ -273,18 +274,15 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
if (j == cells.length) {
break;
}
- } else if (j > 0) {
- throw new IllegalStateException(
- "Cells are in invalid order or not in a continuous range.");
}
}
return join(columns);
}
- private List<GridColumn<?, ?>> getCellGroupForColumn(
+ private Set<GridColumn<?, ?>> getCellGroupForColumn(
GridColumn<?, ?> column) {
- for (List<GridColumn<?, ?>> group : cellGroups) {
+ for (Set<GridColumn<?, ?>> group : cellGroups.keySet()) {
if (group.contains(column)) {
return group;
}
@@ -299,51 +297,45 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
cell.setColspan(1);
}
+ List<GridColumn<?, ?>> columnOrder = new ArrayList<GridColumn<?, ?>>(
+ section.grid.getColumns());
// Set colspan for grouped cells
- for (List<GridColumn<?, ?>> group : cellGroups) {
-
- int firstVisibleColumnInGroup = -1;
- int lastVisibleColumnInGroup = -1;
- int hiddenInsideGroup = 0;
-
- /*
- * To be able to calculate the colspan correctly we need to two
- * things; find the first visible cell in the group which will
- * get the colspan assigned to and find the amount of columns
- * which should be spanned.
- *
- * To do that we iterate through all cells, marking into memory
- * when we find the first visible cell, when we find the last
- * visible cell and how many cells are hidden in between.
- */
- for (int i = 0; i < group.size(); i++) {
- if (group.get(i).isVisible()) {
- lastVisibleColumnInGroup = i;
- if (firstVisibleColumnInGroup == -1) {
- firstVisibleColumnInGroup = i;
+ for (Set<GridColumn<?, ?>> group : cellGroups.keySet()) {
+ if (!checkCellGroupAndOrder(columnOrder, group)) {
+ cellGroups.get(group).setColspan(1);
+ } else {
+ int colSpan = group.size();
+ for (GridColumn<?, ?> column : group) {
+ if (!column.isVisible()) {
+ --colSpan;
}
- } else if (firstVisibleColumnInGroup != -1) {
- hiddenInsideGroup++;
}
+ cellGroups.get(group).setColspan(colSpan);
}
+ }
- if (firstVisibleColumnInGroup == -1
- || lastVisibleColumnInGroup == -1
- || firstVisibleColumnInGroup == lastVisibleColumnInGroup) {
- // No cells in group
+ }
+
+ private boolean checkCellGroupAndOrder(
+ List<GridColumn<?, ?>> columnOrder,
+ Set<GridColumn<?, ?>> cellGroup) {
+ if (!columnOrder.containsAll(cellGroup)) {
+ return false;
+ }
+
+ for (int i = 0; i < columnOrder.size(); ++i) {
+ if (!cellGroup.contains(columnOrder.get(i))) {
continue;
}
- /*
- * Assign colspan to first cell in group.
- */
- GridColumn<?, ?> firstVisibleColumn = group
- .get(firstVisibleColumnInGroup);
- CELLTYPE firstVisibleCell = getCell(firstVisibleColumn);
- firstVisibleCell.setColspan(lastVisibleColumnInGroup
- - firstVisibleColumnInGroup - hiddenInsideGroup + 1);
+ for (int j = 1; j < cellGroup.size(); ++j) {
+ if (!cellGroup.contains(columnOrder.get(i + j))) {
+ return false;
+ }
+ }
+ return true;
}
-
+ return false;
}
protected void addCell(GridColumn<?, ?> column) {
diff --git a/server/src/com/vaadin/ui/components/grid/Grid.java b/server/src/com/vaadin/ui/components/grid/Grid.java
index eaa5027a36..b5179dade1 100644
--- a/server/src/com/vaadin/ui/components/grid/Grid.java
+++ b/server/src/com/vaadin/ui/components/grid/Grid.java
@@ -40,6 +40,7 @@ import com.vaadin.data.RpcDataProviderExtension;
import com.vaadin.data.RpcDataProviderExtension.DataProviderKeyMapper;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.server.ErrorHandler;
+import com.vaadin.server.ErrorMessage;
import com.vaadin.server.KeyMapper;
import com.vaadin.shared.ui.grid.EditorRowClientRpc;
import com.vaadin.shared.ui.grid.EditorRowServerRpc;
@@ -472,6 +473,31 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier,
});
}
+ @Override
+ public void beforeClientResponse(boolean initial) {
+ try {
+ header.sanityCheck();
+ footer.sanityCheck();
+ } catch (Exception e) {
+ e.printStackTrace();
+ setComponentError(new ErrorMessage() {
+
+ @Override
+ public ErrorLevel getErrorLevel() {
+ return ErrorLevel.CRITICAL;
+ }
+
+ @Override
+ public String getFormattedHtmlMessage() {
+ return "Incorrectly merged cells";
+ }
+
+ });
+ }
+
+ super.beforeClientResponse(initial);
+ }
+
/**
* Sets the grid data source.
*
diff --git a/server/src/com/vaadin/ui/components/grid/GridFooter.java b/server/src/com/vaadin/ui/components/grid/GridFooter.java
index 2af991a39c..80bb26da72 100644
--- a/server/src/com/vaadin/ui/components/grid/GridFooter.java
+++ b/server/src/com/vaadin/ui/components/grid/GridFooter.java
@@ -62,4 +62,8 @@ public class GridFooter extends GridStaticSection<GridFooter.FooterRow> {
return new FooterRow(this);
}
+ @Override
+ protected void sanityCheck() throws IllegalStateException {
+ super.sanityCheck();
+ }
}
diff --git a/server/src/com/vaadin/ui/components/grid/GridHeader.java b/server/src/com/vaadin/ui/components/grid/GridHeader.java
index 9d7ec24a97..90abb4651c 100644
--- a/server/src/com/vaadin/ui/components/grid/GridHeader.java
+++ b/server/src/com/vaadin/ui/components/grid/GridHeader.java
@@ -121,4 +121,21 @@ public class GridHeader extends GridStaticSection<GridHeader.HeaderRow> {
}
return row;
}
+
+ @Override
+ protected void sanityCheck() throws IllegalStateException {
+ super.sanityCheck();
+
+ boolean hasDefaultRow = false;
+ for (HeaderRow row : rows) {
+ if (row.getRowState().defaultRow) {
+ if (!hasDefaultRow) {
+ hasDefaultRow = true;
+ } else {
+ throw new IllegalStateException(
+ "Multiple default rows in header");
+ }
+ }
+ }
+ }
}
diff --git a/server/src/com/vaadin/ui/components/grid/GridStaticSection.java b/server/src/com/vaadin/ui/components/grid/GridStaticSection.java
index 74acc2b781..a997c130a0 100644
--- a/server/src/com/vaadin/ui/components/grid/GridStaticSection.java
+++ b/server/src/com/vaadin/ui/components/grid/GridStaticSection.java
@@ -18,13 +18,12 @@ package com.vaadin.ui.components.grid;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
+import java.util.Set;
import com.vaadin.data.Container.Indexed;
import com.vaadin.shared.ui.grid.GridStaticCellType;
@@ -56,7 +55,7 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
private RowState rowState = new RowState();
protected GridStaticSection<?> section;
private Map<Object, CELLTYPE> cells = new LinkedHashMap<Object, CELLTYPE>();
- private Collection<List<CELLTYPE>> cellGroups = new HashSet<List<CELLTYPE>>();
+ private Map<Set<CELLTYPE>, CELLTYPE> cellGroups = new HashMap<Set<CELLTYPE>, CELLTYPE>();
protected StaticRow(GridStaticSection<?> section) {
this.section = section;
@@ -72,7 +71,7 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
protected void removeCell(Object propertyId) {
CELLTYPE cell = cells.remove(propertyId);
if (cell != null) {
- List<CELLTYPE> cellGroupForCell = getCellGroupForCell(cell);
+ Set<CELLTYPE> cellGroupForCell = getCellGroupForCell(cell);
if (cellGroupForCell != null) {
removeCellFromGroup(cell, cellGroupForCell);
}
@@ -80,9 +79,9 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
}
}
- private void removeCellFromGroup(CELLTYPE cell, List<CELLTYPE> cellGroup) {
+ private void removeCellFromGroup(CELLTYPE cell, Set<CELLTYPE> cellGroup) {
String columnId = cell.getColumnId();
- for (List<String> group : rowState.cellGroups) {
+ for (Set<String> group : rowState.cellGroups.keySet()) {
if (group.contains(columnId)) {
if (group.size() > 2) {
cellGroup.remove(cell);
@@ -108,14 +107,21 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
}
/**
- * Returns the cell for the given property id on this row.
+ * Returns the cell for the given property id on this row. If the column
+ * is merged returned cell is the cell for the whole group.
*
* @param propertyId
* the property id of the column
- * @return the cell for the given property or null if not found
+ * @return the cell for the given property, merged cell for merged
+ * properties, null if not found
*/
public CELLTYPE getCell(Object propertyId) {
- return cells.get(propertyId);
+ CELLTYPE cell = cells.get(propertyId);
+ Set<CELLTYPE> cellGroup = getCellGroupForCell(cell);
+ if (cellGroup != null) {
+ return cellGroups.get(cellGroup);
+ }
+ return cell;
}
/**
@@ -128,7 +134,7 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
public CELLTYPE join(Object... properties) {
assert properties.length > 1 : "You need to merge at least 2 properties";
- List<CELLTYPE> cells = new ArrayList<CELLTYPE>();
+ Set<CELLTYPE> cells = new HashSet<CELLTYPE>();
for (int i = 0; i < properties.length; ++i) {
cells.add(getCell(properties[i]));
}
@@ -146,10 +152,10 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
public CELLTYPE join(CELLTYPE... cells) {
assert cells.length > 1 : "You need to merge at least 2 cells";
- return join(Arrays.asList(cells));
+ return join(new HashSet<CELLTYPE>(Arrays.asList(cells)));
}
- protected CELLTYPE join(List<CELLTYPE> cells) {
+ protected CELLTYPE join(Set<CELLTYPE> cells) {
for (CELLTYPE cell : cells) {
if (getCellGroupForCell(cell) != null) {
throw new IllegalArgumentException("Cell already merged");
@@ -159,47 +165,20 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
}
}
- if (cellsInContinuousRange(cells)) {
- List<String> columnGroup = new ArrayList<String>();
- for (CELLTYPE cell : cells) {
- columnGroup.add(cell.getColumnId());
- }
- rowState.cellGroups.add(columnGroup);
- cellGroups.add(cells);
- return cells.get(0);
- } else {
- throw new IllegalArgumentException(
- "Cells are in invalid order or not in a contiunous range");
- }
- }
+ // Create new cell data for the group
+ CELLTYPE newCell = createCell();
- private boolean cellsInContinuousRange(List<CELLTYPE> mergeCells) {
- Iterator<CELLTYPE> mergeCellIterator = mergeCells.iterator();
- CELLTYPE mergeCell = mergeCellIterator.next();
- boolean firstFound = false;
- for (Entry<Object, CELLTYPE> entry : cells.entrySet()) {
- // Go through all the cells until first to be merged is found
- CELLTYPE currentCell = entry.getValue();
- if (currentCell == mergeCell) {
- if (!mergeCellIterator.hasNext()) {
- // All the cells to be merged are found and they
- // were in continuous range
- return true;
- }
- mergeCell = mergeCellIterator.next();
- firstFound = true;
- } else if (firstFound) {
- // We found the first cell already, but at least one cell
- // was not in a continuous range.
- return false;
- }
+ Set<String> columnGroup = new HashSet<String>();
+ for (CELLTYPE cell : cells) {
+ columnGroup.add(cell.getColumnId());
}
-
- return false;
+ rowState.cellGroups.put(columnGroup, newCell.getCellState());
+ cellGroups.put(cells, newCell);
+ return newCell;
}
- private List<CELLTYPE> getCellGroupForCell(CELLTYPE cell) {
- for (List<CELLTYPE> group : cellGroups) {
+ private Set<CELLTYPE> getCellGroupForCell(CELLTYPE cell) {
+ for (Set<CELLTYPE> group : cellGroups.keySet()) {
if (group.contains(cell)) {
return group;
}
@@ -498,4 +477,43 @@ abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
row.addCell(propertyId);
}
}
+
+ /**
+ * Performs a sanity check that section is in correct state.
+ *
+ * @throws IllegalStateException
+ * if merged cells are not i n continuous range
+ */
+ protected void sanityCheck() throws IllegalStateException {
+ List<String> columnOrder = grid.getState().columnOrder;
+ for (ROWTYPE row : rows) {
+ for (Set<String> cellGroup : row.getRowState().cellGroups.keySet()) {
+ if (!checkCellGroupAndOrder(columnOrder, cellGroup)) {
+ throw new IllegalStateException(
+ "Not all merged cells were in a continuous range.");
+ }
+ }
+ }
+ }
+
+ private boolean checkCellGroupAndOrder(List<String> columnOrder,
+ Set<String> cellGroup) {
+ if (!columnOrder.containsAll(cellGroup)) {
+ return false;
+ }
+
+ for (int i = 0; i < columnOrder.size(); ++i) {
+ if (!cellGroup.contains(columnOrder.get(i))) {
+ continue;
+ }
+
+ for (int j = 1; j < cellGroup.size(); ++j) {
+ if (!cellGroup.contains(columnOrder.get(i + j))) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
}
diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridStaticSection.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridStaticSection.java
index 3b00867257..10861ae72f 100644
--- a/server/tests/src/com/vaadin/tests/server/component/grid/GridStaticSection.java
+++ b/server/tests/src/com/vaadin/tests/server/component/grid/GridStaticSection.java
@@ -17,6 +17,8 @@ package com.vaadin.tests.server.component.grid;
import static org.junit.Assert.assertEquals;
+import java.lang.reflect.Method;
+
import org.junit.Before;
import org.junit.Test;
@@ -88,18 +90,35 @@ public class GridStaticSection {
mergeRow.getCell("zipCode"));
}
- @Test(expected = IllegalArgumentException.class)
- public void testJoinHeaderCellsIncorrectly() {
+ @Test(expected = IllegalStateException.class)
+ public void testJoinHeaderCellsIncorrectly() throws Throwable {
final GridHeader section = grid.getHeader();
HeaderRow mergeRow = section.prependRow();
mergeRow.join("firstName", "zipCode").setText("Name");
+ sanityCheck();
}
@Test
- public void testJoinAllFooterrCells() {
+ public void testJoinAllFooterCells() {
final GridFooter section = grid.getFooter();
FooterRow mergeRow = section.prependRow();
mergeRow.join(dataSource.getContainerPropertyIds().toArray()).setText(
"All the stuff.");
}
+
+ private void sanityCheck() throws Throwable {
+ Method sanityCheckHeader;
+ try {
+ sanityCheckHeader = GridHeader.class
+ .getDeclaredMethod("sanityCheck");
+ sanityCheckHeader.setAccessible(true);
+ Method sanityCheckFooter = GridFooter.class
+ .getDeclaredMethod("sanityCheck");
+ sanityCheckFooter.setAccessible(true);
+ sanityCheckHeader.invoke(grid.getHeader());
+ sanityCheckFooter.invoke(grid.getFooter());
+ } catch (Exception e) {
+ throw e.getCause();
+ }
+ }
}
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java b/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java
index 3dde4989b8..5a04bb2558 100644
--- a/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java
+++ b/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java
@@ -17,7 +17,10 @@ package com.vaadin.shared.ui.grid;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import com.vaadin.shared.Connector;
@@ -46,7 +49,10 @@ public class GridStaticSectionState implements Serializable {
public boolean defaultRow = false;
- public List<List<String>> cellGroups = new ArrayList<List<String>>();
+ /**
+ * Map from column id set to cell state for merged state.
+ */
+ public Map<Set<String>, CellState> cellGroups = new HashMap<Set<String>, CellState>();
}
public List<RowState> rows = new ArrayList<RowState>();
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColspans.java b/uitest/src/com/vaadin/tests/components/grid/GridColspans.java
index 3b3229a652..d1d98df06d 100644
--- a/uitest/src/com/vaadin/tests/components/grid/GridColspans.java
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColspans.java
@@ -77,6 +77,15 @@ public class GridColspans extends AbstractTestUI {
column.setVisible(!column.isVisible());
}
}));
+
+ addComponent(new Button("Change column order",
+ new Button.ClickListener() {
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ grid.setColumnOrder("zipCode", "firstName");
+ }
+ }));
}
@Override
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java b/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java
index 0191f1d625..3030592492 100644
--- a/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java
@@ -20,17 +20,25 @@ import static org.junit.Assert.assertEquals;
import java.io.IOException;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
+import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.interactions.Actions;
import com.vaadin.testbench.elements.ButtonElement;
import com.vaadin.tests.annotations.TestCategory;
+import com.vaadin.tests.components.grid.GridElement.GridCellElement;
import com.vaadin.tests.tb3.MultiBrowserTest;
@TestCategory("grid")
public class GridColspansTest extends MultiBrowserTest {
+ @Before
+ public void setUp() {
+ setDebug(true);
+ }
+
@Test
public void testHeaderColSpans() {
openTestURL();
@@ -88,4 +96,31 @@ public class GridColspansTest extends MultiBrowserTest {
Assert.assertEquals("Failed initial condition.", "lastName", grid
.getHeaderCell(2, 1).getText());
}
+
+ @Test
+ public void testSplittingMergedHeaders() {
+ openTestURL();
+
+ GridElement grid = $(GridElement.class).first();
+ GridCellElement headerCell = grid.getHeaderCell(1, 1);
+ Assert.assertEquals("Failed initial condition.", headerCell.getText(),
+ "Full Name");
+ Assert.assertEquals("Failed initial condition.",
+ grid.getHeaderCell(2, 1).getText(), "firstName");
+ $(ButtonElement.class).get(1).click();
+ headerCell = grid.getHeaderCell(1, 1);
+ Assert.assertEquals("Header text not changed on column reorder.",
+ headerCell.getText(), "Address");
+ Assert.assertEquals("Unexpected colspan", "1",
+ headerCell.getAttribute("colspan"));
+ headerCell = grid.getHeaderCell(1, 2);
+ Assert.assertEquals("Header text not changed on column reorder",
+ "Full Name", headerCell.getText());
+ Assert.assertEquals("Unexpected colspan", "2",
+ headerCell.getAttribute("colspan"));
+
+ Assert.assertTrue("Error indicator not present",
+ isElementPresent(By.className("v-errorindicator")));
+
+ }
}