]> source.dussan.org Git - vaadin-framework.git/commitdiff
Implement default header row in new Grid
authorJohannes Dahlström <johannesd@vaadin.com>
Mon, 26 Sep 2016 15:45:28 +0000 (18:45 +0300)
committerJohannes Dahlström <johannesd@vaadin.com>
Tue, 27 Sep 2016 21:44:10 +0000 (00:44 +0300)
Change-Id: Id26a98caca022ed2a4dbe0128a79721a54f5b267

client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java
server/src/main/java/com/vaadin/ui/Grid.java
server/src/main/java/com/vaadin/ui/components/grid/Header.java
server/src/main/java/com/vaadin/ui/components/grid/StaticSection.java
server/src/test/java/com/vaadin/tests/server/component/grid/GridDefaultHeaderTest.java [new file with mode: 0644]
server/src/test/java/com/vaadin/tests/server/component/grid/GridHeaderFooterTest.java
uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java
uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridHeaderFooterTest.java

index 0da4ec3bcced42dc6486ea4394e38efab4ef5bb6..6596137d9d9dbdb6832eb613f375866993a71032 100644 (file)
@@ -219,10 +219,13 @@ public class GridConnector
         layout();
     }
 
+    /**
+     * Updates the grid header section on state change.
+     */
     @OnStateChange("header")
     void updateHeader() {
-        final SectionState state = getState().header;
         final Grid<JsonObject> grid = getWidget();
+        final SectionState state = getState().header;
 
         while (grid.getHeaderRowCount() > 0) {
             grid.removeHeaderRow(0);
@@ -230,14 +233,14 @@ public class GridConnector
 
         for (RowState rowState : state.rows) {
             HeaderRow row = grid.appendHeaderRow();
+
             rowState.cells.forEach((columnId, cellState) -> {
                 row.getCell(getColumn(columnId)).setText(cellState.text);
             });
-        }
 
-        if (grid.getHeaderRowCount() > 0) {
-            // TODO Default header handling to be added in a later patch
-            grid.setDefaultHeaderRow(grid.getHeaderRow(0));
+            if (rowState.defaultHeader) {
+                grid.setDefaultHeaderRow(row);
+            }
         }
     }
 
index 3777decbe983228da3475caa5677e4a7f86e3dcf..b1a2c64ec8de254a96da843e97430e1cb3501d62 100644 (file)
@@ -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
index 8348795c1011de6ff2b62646eef86d7e1f0e1ec1..31f80a9adda919f295dde7e6d4a9cfc455c78bda 100644 (file)
@@ -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();
+    }
 }
index dbd5749bd0ed30eec6d3edfd5ed03fc8053c5ae8..e1c64f31e66b2de1d5e67d14c2e21e3e26f17f70 100644 (file)
@@ -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 (file)
index 0000000..80984cc
--- /dev/null
@@ -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());
+    }
+}
index 87c2632b40ac9ab0388b86aaebee59183cb804ab..a566ae3685c8cb6f280fb8847ec12a791f8e8bca 100644 (file)
 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);
+    }
 }
index bf0aa3ea5634645ff0604db9478d2c41ca211467..f75dbd27cc3fb076435a47e0908bce649c76648d 100644 (file)
@@ -16,7 +16,9 @@ import com.vaadin.tests.components.AbstractTestUIWithLog;
 import com.vaadin.ui.Button;
 import com.vaadin.ui.Component;
 import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.Column;
 import com.vaadin.ui.Grid.DetailsGenerator;
+import com.vaadin.ui.Grid.HeaderRow;
 import com.vaadin.ui.Label;
 import com.vaadin.ui.MenuBar;
 import com.vaadin.ui.MenuBar.Command;
@@ -33,8 +35,6 @@ import com.vaadin.ui.renderers.ProgressBarRenderer;
 @Widgetset("com.vaadin.DefaultWidgetSet")
 public class GridBasics extends AbstractTestUIWithLog {
 
-    public static final String[] COLUMN_CAPTIONS  = { "Column 0", "Column 1", "Column 2", "Row Number", "Date", "HTML String", "Big Random", "Small Random" };
-
     public static final String ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4 = "Row numbers for 3/4";
     public static final String ROW_STYLE_GENERATOR_NONE = "None";
     public static final String ROW_STYLE_GENERATOR_ROW_NUMBERS = "Row numbers";
@@ -46,6 +46,10 @@ public class GridBasics extends AbstractTestUIWithLog {
     public static final String CELL_STYLE_GENERATOR_EMPTY = "Empty string";
     public static final String CELL_STYLE_GENERATOR_NULL = "Null";
 
+    public static final String[] COLUMN_CAPTIONS = { "Column 0", "Column 1",
+            "Column 2", "Row Number", "Date", "HTML String", "Big Random",
+            "Small Random" };
+
     private static class DetailedDetailsGenerator
             implements DetailsGenerator<DataObject> {
 
@@ -139,7 +143,8 @@ public class GridBasics extends AbstractTestUIWithLog {
 
         grid.addColumn(COLUMN_CAPTIONS[3], DataObject::getRowNumber,
                 new NumberRenderer());
-        grid.addColumn(COLUMN_CAPTIONS[4], DataObject::getDate, new DateRenderer());
+        grid.addColumn(COLUMN_CAPTIONS[4], DataObject::getDate,
+                new DateRenderer());
         grid.addColumn(COLUMN_CAPTIONS[5], DataObject::getHtmlString,
                 new HtmlRenderer());
         grid.addColumn(COLUMN_CAPTIONS[6], DataObject::getBigRandom,
@@ -298,14 +303,30 @@ public class GridBasics extends AbstractTestUIWithLog {
 
     private void createHeaderMenu(MenuItem headerMenu) {
         headerMenu.addItem("Append header row", menuItem -> {
-            grid.appendHeaderRow();
+            HeaderRow row = grid.appendHeaderRow();
+
+            int i = 0;
+            for (Column<?, ?> column : grid.getColumns()) {
+                row.getCell(column).setText("Header cell " + i++);
+            }
         });
         headerMenu.addItem("Prepend header row", menuItem -> {
-            grid.prependHeaderRow();
+            HeaderRow row = grid.prependHeaderRow();
+
+            int i = 0;
+            for (Column<?, ?> column : grid.getColumns()) {
+                row.getCell(column).setText("Header cell " + i++);
+            }
         });
         headerMenu.addItem("Remove first header row", menuItem -> {
             grid.removeHeaderRow(0);
         });
+        headerMenu.addItem("Set first row as default", menuItem -> {
+            grid.setDefaultHeaderRow(grid.getHeaderRow(0));
+        });
+        headerMenu.addItem("Set no default row", menuItem -> {
+            grid.setDefaultHeaderRow(null);
+        });
     }
 
     /* DetailsGenerator related things */
index c1a4cfc2b07e3718cc9d40f0b64d15373c87c461..5b594a980d1393be476ed96000c640ae77869f45 100644 (file)
 package com.vaadin.tests.components.grid.basics;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import java.util.List;
+import java.util.stream.IntStream;
 
 import org.junit.Test;
 
@@ -26,17 +29,15 @@ import com.vaadin.testbench.elements.GridElement.GridCellElement;
 
 public class GridHeaderFooterTest extends GridBasicsTest {
 
+    protected static final String[] HEADER_TEXTS = IntStream
+            .range(0, GridBasics.COLUMN_CAPTIONS.length)
+            .mapToObj(i -> "Header cell " + i)
+            .toArray(String[]::new);
+
     @Test
     public void initialState_defaultHeaderPresent() {
         assertEquals(1, getGridElement().getHeaderCount());
-
-        final String[] captions = GridBasics.COLUMN_CAPTIONS;
-        List<GridCellElement> headerCells = getGridElement().getHeaderCells(0);
-
-        assertEquals(captions.length, headerCells.size());
-        for (int i = 0; i < headerCells.size(); i++) {
-            assertText(captions[i], headerCells.get(i));
-        }
+        assertHeaderTexts(0, GridBasics.COLUMN_CAPTIONS);
     }
 
     @Test
@@ -44,13 +45,17 @@ public class GridHeaderFooterTest extends GridBasicsTest {
         selectMenuPath("Component", "Header", "Append header row");
 
         assertEquals(2, getGridElement().getHeaderCount());
+        assertHeaderTexts(0, GridBasics.COLUMN_CAPTIONS);
+        assertHeaderTexts(1, HEADER_TEXTS);
     }
 
     @Test
-    public void prependHeaderRow_addedToBottom() {
+    public void prependHeaderRow_addedToTop() {
         selectMenuPath("Component", "Header", "Prepend header row");
 
         assertEquals(2, getGridElement().getHeaderCount());
+        assertHeaderTexts(0, HEADER_TEXTS);
+        assertHeaderTexts(1, GridBasics.COLUMN_CAPTIONS);
     }
 
     @Test
@@ -60,10 +65,69 @@ public class GridHeaderFooterTest extends GridBasicsTest {
         assertEquals(0, getGridElement().getHeaderCount());
     }
 
+    @Test
+    public void setDefaultRow_headerCaptionsUpdated() {
+        selectMenuPath("Component", "Header", "Prepend header row");
+        selectMenuPath("Component", "Header", "Set first row as default");
+
+        assertHeaderTexts(0, GridBasics.COLUMN_CAPTIONS);
+    }
+
+    @Test
+    public void clickDefaultHeaderCell_sortIndicatorPresent() {
+        GridCellElement headerCell = getGridElement().getHeaderCell(0, 2);
+        headerCell.click();
+
+        assertSortIndicator(headerCell, "sort-asc");
+
+        headerCell.click();
+        assertNoSortIndicator(headerCell, "sort-asc");
+        assertSortIndicator(headerCell, "sort-desc");
+
+        GridCellElement anotherCell = getGridElement().getHeaderCell(0, 3);
+        anotherCell.click();
+
+        assertNoSortIndicator(headerCell, "sort-asc");
+        assertNoSortIndicator(headerCell, "sort-desc");
+        assertSortIndicator(anotherCell, "sort-asc");
+    }
+
+    @Test
+    public void noDefaultRow_clickHeaderCell_sortIndicatorsNotPresent() {
+        selectMenuPath("Component", "Header", "Set no default row");
+
+        GridCellElement headerCell = getGridElement().getHeaderCell(0, 2);
+        headerCell.click();
+
+        assertNoSortIndicator(headerCell, "sort-asc");
+        assertNoSortIndicator(headerCell, "sort-desc");
+    }
+
     protected static void assertText(String expected, GridCellElement e) {
         // TBE.getText returns "" if the element is scrolled out of view
         String actual = e.findElement(By.tagName("div")).getAttribute(
                 "innerHTML");
         assertEquals(expected, actual);
     }
+
+    protected void assertHeaderTexts(int rowIndex, String[] texts) {
+        List<GridCellElement> headerCells = getGridElement().getHeaderCells(
+                rowIndex);
+
+        assertEquals(texts.length, headerCells.size());
+        for (int i = 0; i < headerCells.size(); i++) {
+            assertText(texts[i], headerCells.get(i));
+        }
+    }
+
+    protected void assertSortIndicator(GridCellElement cell, String classname) {
+        assertTrue("Header cell should have sort indicator " + classname, cell
+                .getAttribute("class").contains(classname));
+    }
+
+    protected void assertNoSortIndicator(GridCellElement cell,
+            String classname) {
+        assertFalse("Header cell should not have sort indicator " + classname,
+                cell.getAttribute("class").contains(classname));
+    }
 }