diff options
author | Johannes Dahlström <johannesd@vaadin.com> | 2016-09-26 18:45:28 +0300 |
---|---|---|
committer | Johannes Dahlström <johannesd@vaadin.com> | 2016-09-28 00:44:10 +0300 |
commit | 96119ab0224421d69393d9d41ed02900121a683e (patch) | |
tree | adc27cf326fdf007c24db9a742f2f41f2637fc94 /server | |
parent | 680b7009d4f453dc8eec42975192094b2e0e8e2f (diff) | |
download | vaadin-framework-96119ab0224421d69393d9d41ed02900121a683e.tar.gz vaadin-framework-96119ab0224421d69393d9d41ed02900121a683e.zip |
Implement default header row in new Grid
Change-Id: Id26a98caca022ed2a4dbe0128a79721a54f5b267
Diffstat (limited to 'server')
5 files changed, 287 insertions, 49 deletions
diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java index 3777decbe9..b1a2c64ec8 100644 --- a/server/src/main/java/com/vaadin/ui/Grid.java +++ b/server/src/main/java/com/vaadin/ui/Grid.java @@ -51,6 +51,7 @@ import com.vaadin.shared.ui.grid.GridState; import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.shared.ui.grid.SectionState; import com.vaadin.ui.components.grid.Header; +import com.vaadin.ui.components.grid.Header.Row; import com.vaadin.ui.renderers.AbstractRenderer; import com.vaadin.ui.renderers.Renderer; import com.vaadin.ui.renderers.TextRenderer; @@ -873,13 +874,19 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { * Sets the header caption for this column. * * @param caption - * the header caption + * the header caption, not null * * @return this column */ public Column<T, V> setCaption(String caption) { Objects.requireNonNull(caption, "Header caption can't be null"); getState().caption = caption; + + HeaderRow row = getParent().getDefaultHeaderRow(); + if (row != null) { + row.getCell(getId()).setText(caption); + } + return this; } @@ -1428,8 +1435,10 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { * Returns the cell on this row corresponding to the given column id. * * @param columnId - * the id of the column whose header cell to get + * the id of the column whose header cell to get, not null * @return the header cell + * @throws IllegalArgumentException + * if there is no such column in the grid */ public HeaderCell getCell(String columnId); @@ -1437,8 +1446,10 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { * Returns the cell on this row corresponding to the given column. * * @param column - * the column whose header cell to get + * the column whose header cell to get, not null * @return the header cell + * @throws IllegalArgumentException + * if there is no such column in the grid */ public default HeaderCell getCell(Column<?, ?> column) { return getCell(column.getId()); @@ -1461,11 +1472,24 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { * Sets the textual caption of this cell. * * @param text - * the header caption to set + * the header caption to set, not null */ public void setText(String text); } + private class HeaderImpl extends Header { + + @Override + protected SectionState getState(boolean markAsDirty) { + return Grid.this.getState(markAsDirty).header; + } + + @Override + protected Collection<Column<T, ?>> getColumns() { + return Grid.this.getColumns(); + } + }; + private KeyMapper<Column<T, ?>> columnKeys = new KeyMapper<>(); private Set<Column<T, ?>> columnSet = new LinkedHashSet<>(); private List<SortOrder<Column<T, ?>>> sortOrder = new ArrayList<>(); @@ -1474,12 +1498,7 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { private StyleGenerator<T> styleGenerator = item -> null; private DescriptionGenerator<T> descriptionGenerator; - private Header header = new Header() { - @Override - protected SectionState getState(boolean markAsDirty) { - return Grid.this.getState(markAsDirty).header; - } - }; + private Header header = new HeaderImpl(); /** * Constructor for the {@link Grid} component. @@ -1488,7 +1507,7 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { setSelectionModel(new SingleSelection()); registerRpc(new GridServerRpcImpl()); - appendHeaderRow(); + setDefaultHeaderRow(appendHeaderRow()); detailsManager = new DetailsManager<>(); addExtension(detailsManager); @@ -1545,10 +1564,8 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { getHeader().addColumn(columnId); - if (getHeaderRowCount() > 0) { - // TODO Default header API to be added in a later patch - HeaderRow defaultHeader = getHeaderRow(0); - defaultHeader.getCell(columnId).setText(caption); + if (getDefaultHeaderRow() != null) { + getDefaultHeaderRow().getCell(columnId).setText(caption); } return column; @@ -1580,7 +1597,9 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { if (columnSet.remove(column)) { columnKeys.remove(column); removeDataGenerator(column); + getHeader().removeColumn(column.getId()); column.remove(); + } } @@ -1846,14 +1865,14 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { /** * Returns the header row at the given index. * - * @param rowIndex + * @param index * the index of the row, where the topmost row has index zero * @return the header row at the index * @throws IndexOutOfBoundsException * if {@code rowIndex < 0 || rowIndex >= getHeaderRowCount()} */ - public HeaderRow getHeaderRow(int rowIndex) { - return getHeader().getRow(rowIndex); + public HeaderRow getHeaderRow(int index) { + return getHeader().getRow(index); } /** @@ -1917,7 +1936,8 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { } /** - * Removes the given row from the header section. + * Removes the given row from the header section. Removing a default row + * sets the Grid to have no default row. * * @param row * the header row to be removed, not null @@ -1937,25 +1957,54 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { /** * Removes the row at the given position from the header section. * - * @param rowIndex + * @param index * the index of the row to remove, where the topmost row has * index zero * * @throws IndexOutOfBoundsException - * if {@code rowIndex < 0 || rowIndex >= getHeaderRowCount()} + * if {@code index < 0 || index >= getHeaderRowCount()} * * @see #removeHeaderRow(HeaderRow) * @see #addHeaderRowAt(int) * @see #appendHeaderRow() * @see #prependHeaderRow() */ - public void removeHeaderRow(int rowIndex) { - getHeader().removeRow(rowIndex); + public void removeHeaderRow(int index) { + getHeader().removeRow(index); + } + + /** + * Returns the current default row of the header. + * + * @return the default row or null if no default row set + * + * @see #setDefaultHeaderRow(HeaderRow) + */ + public HeaderRow getDefaultHeaderRow() { + return header.getDefaultRow(); + } + + /** + * Sets the default row of the header. The default row is a special header + * row that displays column captions and sort indicators. By default Grid + * has a single row which is also the default row. When a header row is set + * as the default row, any existing cell content is replaced by the column + * captions. + * + * @param row + * the new default row, or null for no default row + * + * @throws IllegalArgumentException + * if the header does not contain the row + */ + public void setDefaultHeaderRow(HeaderRow row) { + header.setDefaultRow((Row) row); } /** * Returns the header section of this grid. The default header contains a - * single row displaying the column captions. + * single row, set as the {@linkplain #setDefaultHeaderRow(HeaderRow) + * default row}. * * @return the header section */ @@ -1994,7 +2043,7 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents { } /** - * Registers a new column visibility change listener + * Registers a new column visibility change listener. * * @param listener * the listener to register, not null diff --git a/server/src/main/java/com/vaadin/ui/components/grid/Header.java b/server/src/main/java/com/vaadin/ui/components/grid/Header.java index 8348795c10..31f80a9add 100644 --- a/server/src/main/java/com/vaadin/ui/components/grid/Header.java +++ b/server/src/main/java/com/vaadin/ui/components/grid/Header.java @@ -19,21 +19,34 @@ import com.vaadin.ui.Grid; /** * Represents the header section of a Grid. + * + * @author Vaadin Ltd. + * + * @since 8.0 */ public abstract class Header extends StaticSection<Header.Row> { + /** + * A row in a Grid header. + */ public class Row extends StaticSection.StaticRow<Row.Cell> implements Grid.HeaderRow { + /** + * A cell in a Grid header row. + */ public class Cell extends StaticSection.StaticCell implements Grid.HeaderCell { + /** + * Creates a new header cell. + */ protected Cell() { super(Row.this); } } /** - * @param section + * Creates a new header row. */ protected Row() { super(Header.this); @@ -48,10 +61,75 @@ public abstract class Header extends StaticSection<Header.Row> { protected String getCellTagName() { return "th"; } + + /** + * Returns whether this row is the default header row. + * + * @return {@code true} if this row is the default row, {@code false} + * otherwise. + */ + protected boolean isDefault() { + return getRowState().defaultHeader; + } + + /** + * Sets whether this row is the default header row. + * + * @param defaultHeader + * {@code true} to set to default, {@code false} otherwise. + */ + protected void setDefault(boolean defaultHeader) { + getRowState().defaultHeader = defaultHeader; + } } @Override public Row createRow() { return new Row(); } + + @Override + public void removeRow(int index) { + if (getRow(index).isDefault()) { + setDefaultRow(null); + } + super.removeRow(index); + } + + /** + * Returns the default row of this header. The default row displays column + * captions and sort indicators. + * + * @return the default row, or {@code null} if there is no default row + */ + public Row getDefaultRow() { + return getRows().stream() + .filter(Row::isDefault) + .findAny().orElse(null); + } + + /** + * Sets the default row of this header. The default row displays column + * captions and sort indicators. + * + * @param defaultRow + * the new default row, or null for no default row + * + * @throws IllegalArgumentException + * if the header does not contain the row + */ + public void setDefaultRow(Row defaultRow) { + if (defaultRow != null) { + if (!getRows().contains(defaultRow)) { + throw new IllegalArgumentException( + "The section does not contain the row"); + } + if (defaultRow.isDefault()) { + return; + } + } + getRows().forEach(row -> row.setDefault(row == defaultRow)); + + markAsDirty(); + } } diff --git a/server/src/main/java/com/vaadin/ui/components/grid/StaticSection.java b/server/src/main/java/com/vaadin/ui/components/grid/StaticSection.java index dbd5749bd0..e1c64f31e6 100644 --- a/server/src/main/java/com/vaadin/ui/components/grid/StaticSection.java +++ b/server/src/main/java/com/vaadin/ui/components/grid/StaticSection.java @@ -17,6 +17,8 @@ package com.vaadin.ui.components.grid; import java.io.Serializable; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -25,6 +27,7 @@ import java.util.Objects; import com.vaadin.shared.ui.grid.SectionState; import com.vaadin.shared.ui.grid.SectionState.CellState; import com.vaadin.shared.ui.grid.SectionState.RowState; +import com.vaadin.ui.Grid.Column; /** * Represents the header or footer section of a Grid. @@ -48,9 +51,9 @@ public abstract class StaticSection<ROW extends StaticSection.StaticRow<?>> public abstract static class StaticRow<CELL extends StaticCell> implements Serializable { - private RowState rowState = new RowState(); - private StaticSection<?> section; - private Map<Object, CELL> cells = new LinkedHashMap<>(); + private final RowState rowState = new RowState(); + private final StaticSection<?> section; + private final Map<Object, CELL> cells = new LinkedHashMap<>(); /** * Creates a new row belonging to the given section. @@ -118,10 +121,17 @@ public abstract class StaticSection<ROW extends StaticSection.StaticRow<?>> * * @param columnId * the id of the column - * @return the cell for the given column or null if not found + * @return the cell for the given column + * + * @throws IllegalArgumentException + * if no cell was found for the column id */ public CELL getCell(String columnId) { CELL cell = cells.get(columnId); + if (cell == null) { + throw new IllegalArgumentException( + "No cell found for column id " + columnId); + } return cell; } } @@ -186,7 +196,7 @@ public abstract class StaticSection<ROW extends StaticSection.StaticRow<?>> } } - private List<ROW> rows = new ArrayList<>(); + private final List<ROW> rows = new ArrayList<>(); /** * Creates a new row instance. @@ -205,6 +215,8 @@ public abstract class StaticSection<ROW extends StaticSection.StaticRow<?>> */ protected abstract SectionState getState(boolean markAsDirty); + protected abstract Collection<? extends Column<?, ?>> getColumns(); + /** * Marks the state of this section as modified. */ @@ -225,6 +237,9 @@ public abstract class StaticSection<ROW extends StaticSection.StaticRow<?>> ROW row = createRow(); rows.add(index, row); getState(true).rows.add(index, row.getRowState()); + + getColumns().stream().forEach(column -> row.addCell(column.getId())); + return row; } @@ -304,4 +319,13 @@ public abstract class StaticSection<ROW extends StaticSection.StaticRow<?>> row.removeCell(columnId); } } + + /** + * Returns an unmodifiable list of the rows in this section. + * + * @return the rows in this section + */ + protected List<ROW> getRows() { + return Collections.unmodifiableList(rows); + } } diff --git a/server/src/test/java/com/vaadin/tests/server/component/grid/GridDefaultHeaderTest.java b/server/src/test/java/com/vaadin/tests/server/component/grid/GridDefaultHeaderTest.java new file mode 100644 index 0000000000..80984cc647 --- /dev/null +++ b/server/src/test/java/com/vaadin/tests/server/component/grid/GridDefaultHeaderTest.java @@ -0,0 +1,87 @@ +/* + * 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.tests.server.component.grid; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import java.util.function.Function; + +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.ui.Grid; +import com.vaadin.ui.Grid.Column; +import com.vaadin.ui.Grid.HeaderRow; + +public class GridDefaultHeaderTest { + private Grid<String> grid; + private Column<?, ?> column1, column2; + + @Before + public void setUp() { + grid = new Grid<>(); + + column1 = grid.addColumn("First", Function.identity()); + column2 = grid.addColumn("Second", Function.identity()); + } + + @Test + public void initialState_hasDefaultHeader() { + HeaderRow defaultHeader = grid.getDefaultHeaderRow(); + + assertEquals(1, grid.getHeaderRowCount()); + assertSame(grid.getHeaderRow(0), defaultHeader); + assertEquals("First", defaultHeader.getCell(column1).getText()); + assertEquals("Second", defaultHeader.getCell(column2).getText()); + } + + @Test + public void initialState_defaultHeaderRemovable() { + grid.removeHeaderRow(0); + + assertEquals(0, grid.getHeaderRowCount()); + assertNull(grid.getDefaultHeaderRow()); + } + + @Test + public void initialState_updateColumnCaption_defaultHeaderUpdated() { + column1.setCaption("1st"); + + assertEquals("1st", grid.getDefaultHeaderRow().getCell(column1) + .getText()); + } + + @Test + public void customDefaultHeader_updateColumnCaption_defaultHeaderUpdated() { + grid.setDefaultHeaderRow(grid.appendHeaderRow()); + column1.setCaption("1st"); + + assertEquals("1st", grid.getDefaultHeaderRow().getCell(column1) + .getText()); + assertEquals("First", grid.getHeaderRow(0).getCell(column1).getText()); + } + + @Test + public void noDefaultRow_updateColumnCaption_headerNotUpdated() { + grid.setDefaultHeaderRow(null); + column1.setCaption("1st"); + + assertEquals("First", grid.getHeaderRow(0).getCell(column1) + .getText()); + } +} diff --git a/server/src/test/java/com/vaadin/tests/server/component/grid/GridHeaderFooterTest.java b/server/src/test/java/com/vaadin/tests/server/component/grid/GridHeaderFooterTest.java index 87c2632b40..a566ae3685 100644 --- a/server/src/test/java/com/vaadin/tests/server/component/grid/GridHeaderFooterTest.java +++ b/server/src/test/java/com/vaadin/tests/server/component/grid/GridHeaderFooterTest.java @@ -16,9 +16,12 @@ package com.vaadin.tests.server.component.grid; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; +import java.util.function.Function; + import org.junit.Before; import org.junit.Test; @@ -29,28 +32,10 @@ import com.vaadin.ui.Grid.HeaderRow; public class GridHeaderFooterTest { private Grid<String> grid; - private Column<?, ?> column1, column2; @Before public void setUp() { grid = new Grid<>(); - - column1 = grid.addColumn("First", s -> s.substring(0, 1)); - column2 = grid.addColumn("Rest", s -> s.substring(1)); - } - - @Test - public void initialState_hasDefaultHeader() { - assertEquals(1, grid.getHeaderRowCount()); - HeaderRow defaultHeader = grid.getHeaderRow(0); - assertEquals("First", defaultHeader.getCell(column1).getText()); - assertEquals("Rest", defaultHeader.getCell(column2).getText()); - } - - @Test - public void initialState_defaultHeaderRemovable() { - grid.removeHeaderRow(0); - assertEquals(0, grid.getHeaderRowCount()); } @Test @@ -152,4 +137,19 @@ public class GridHeaderFooterTest { } grid.removeHeaderRow(row); } + + @Test + public void addColumn_headerCellAdded() { + Column<?, ?> column = grid.addColumn("Col", Function.identity()); + + assertNotNull(grid.getHeaderRow(0).getCell(column)); + } + + @Test(expected = IllegalArgumentException.class) + public void removeColumn_headerCellRemoved() { + Column<String, ?> column = grid.addColumn("Col", Function.identity()); + grid.removeColumn(column); + + grid.getHeaderRow(0).getCell(column); + } } |