]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add server side API for Headers and Footers (#13334)
authorTeemu Suo-Anttila <teemusa@vaadin.com>
Tue, 29 Jul 2014 14:19:28 +0000 (17:19 +0300)
committerVaadin Code Review <review@vaadin.com>
Thu, 31 Jul 2014 10:56:25 +0000 (10:56 +0000)
Change-Id: I52f282089cc55b1f281b9aeb934886442b0c34f3

server/src/com/vaadin/ui/components/grid/Grid.java
server/src/com/vaadin/ui/components/grid/GridColumn.java
server/src/com/vaadin/ui/components/grid/GridFooter.java [new file with mode: 0644]
server/src/com/vaadin/ui/components/grid/GridHeader.java [new file with mode: 0644]
server/src/com/vaadin/ui/components/grid/GridStaticSection.java [new file with mode: 0644]
server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java

index 67a97c74b7b8930a14077f5bc7d03803f6e3036e..f5846c014837c9f591ead278d91c4c1f5edb1ab6 100644 (file)
@@ -46,12 +46,11 @@ import com.vaadin.shared.ui.grid.GridColumnState;
 import com.vaadin.shared.ui.grid.GridServerRpc;
 import com.vaadin.shared.ui.grid.GridState;
 import com.vaadin.shared.ui.grid.GridState.SharedSelectionMode;
-import com.vaadin.shared.ui.grid.GridStaticSectionState.CellState;
-import com.vaadin.shared.ui.grid.GridStaticSectionState.RowState;
 import com.vaadin.shared.ui.grid.HeightMode;
 import com.vaadin.shared.ui.grid.ScrollDestination;
 import com.vaadin.shared.ui.grid.SortDirection;
 import com.vaadin.ui.AbstractComponent;
+import com.vaadin.ui.components.grid.GridHeader.HeaderRow;
 import com.vaadin.ui.components.grid.selection.MultiSelectionModel;
 import com.vaadin.ui.components.grid.selection.NoSelectionModel;
 import com.vaadin.ui.components.grid.selection.SelectionChangeEvent;
@@ -209,6 +208,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
      */
     private int ignoreSelectionClientSync = 0;
 
+    private final GridHeader header = new GridHeader(this);
+    private final GridFooter footer = new GridFooter(this);
+
     private static final Method SELECTION_CHANGE_METHOD = ReflectTools
             .findMethod(SelectionChangeListener.class, "selectionChange",
                     SelectionChangeEvent.class);
@@ -224,17 +226,8 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
      *            the data source for the grid
      */
     public Grid(final Container.Indexed datasource) {
-
-        RowState headerDefaultRow = new RowState();
-        headerDefaultRow.defaultRow = true;
-        getState().header.rows.add(headerDefaultRow);
-
-        // FIXME By default there shouldn't be any footer row
-        getState().footer.rows.add(new RowState());
-
-        setColumnFootersVisible(false);
-
         setContainerDataSource(datasource);
+
         setSelectionMode(SelectionMode.MULTI);
         addSelectionChangeListener(new SelectionChangeListener() {
             @Override
@@ -433,6 +426,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
         setLastFrozenPropertyId(null);
 
         // Add columns
+        HeaderRow row = getHeader().getDefaultRow();
         for (Object propertyId : datasource.getContainerPropertyIds()) {
             if (!columns.containsKey(propertyId)) {
                 GridColumn column = appendColumn(propertyId);
@@ -445,7 +439,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
                 }
 
                 // Add by default property id as column header
-                column.setHeaderCaption(String.valueOf(propertyId));
+                row.getCell(propertyId).setText(String.valueOf(propertyId));
             }
         }
     }
@@ -476,8 +470,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
      * @param visible
      *            <code>true</code> if the header rows should be visible
      */
+    @Deprecated
     public void setColumnHeadersVisible(boolean visible) {
-        getState().header.visible = visible;
+        getHeader().setVisible(visible);
     }
 
     /**
@@ -485,8 +480,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
      * 
      * @return <code>true</code> if the headers of the columns are visible
      */
+    @Deprecated
     public boolean isColumnHeadersVisible() {
-        return getState(false).header.visible;
+        return getHeader().isVisible();
     }
 
     /**
@@ -495,8 +491,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
      * @param visible
      *            <code>true</code> if the footer rows should be visible
      */
+    @Deprecated
     public void setColumnFootersVisible(boolean visible) {
-        getState().footer.visible = visible;
+        getFooter().setVisible(visible);
     }
 
     /**
@@ -504,8 +501,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
      * 
      * @return <code>true</code> if the footer rows should be visible
      */
+    @Deprecated
     public boolean isColumnFootersVisible() {
-        return getState(false).footer.visible;
+        return getFooter().isVisible();
     }
 
     /**
@@ -537,6 +535,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
      * 
      * @return a column group instance you can use to add column groups
      */
+    @Deprecated
     public ColumnGroupRow addColumnGroupRow() {
         ColumnGroupRowState state = new ColumnGroupRowState();
         ColumnGroupRow row = new ColumnGroupRow(this, state, columnKeys);
@@ -552,6 +551,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
      *            the index of the row
      * @return a column group instance you can use to add column groups
      */
+    @Deprecated
     public ColumnGroupRow addColumnGroupRow(int rowIndex) {
         ColumnGroupRowState state = new ColumnGroupRowState();
         ColumnGroupRow row = new ColumnGroupRow(this, state, columnKeys);
@@ -566,6 +566,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
      * @param row
      *            the row to remove
      */
+    @Deprecated
     public void removeColumnGroupRow(ColumnGroupRow row) {
         columnGroupRows.remove(row);
         getState().columnGroupRows.remove(row.getState());
@@ -576,6 +577,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
      * 
      * @return an unmodifiable list of column group rows
      */
+    @Deprecated
     public List<ColumnGroupRow> getColumnGroupRows() {
         return Collections.unmodifiableList(new ArrayList<ColumnGroupRow>(
                 columnGroupRows));
@@ -635,11 +637,13 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
         GridColumnState columnState = new GridColumnState();
         columnState.id = columnKeys.key(datasourcePropertyId);
         getState().columns.add(columnState);
-        for (RowState row : getState().header.rows) {
-            row.cells.add(new CellState());
+
+        for (int i = 0; i < getHeader().getRowCount(); ++i) {
+            getHeader().getRow(i).addCell(datasourcePropertyId);
         }
-        for (RowState row : getState().footer.rows) {
-            row.cells.add(new CellState());
+
+        for (int i = 0; i < getFooter().getRowCount(); ++i) {
+            getFooter().getRow(i).addCell(datasourcePropertyId);
         }
 
         GridColumn column = new GridColumn(this, columnState);
@@ -1316,4 +1320,24 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier {
         removeListener(SortOrderChangeEvent.class, listener,
                 SORT_ORDER_CHANGE_METHOD);
     }
+
+    /**
+     * Returns the header section of this grid. The default header contains a
+     * single row displaying the column captions.
+     * 
+     * @return the header
+     */
+    public GridHeader getHeader() {
+        return header;
+    }
+
+    /**
+     * Returns the footer section of this grid. The default header contains a
+     * single row displaying the column captions.
+     * 
+     * @return the footer
+     */
+    public GridFooter getFooter() {
+        return footer;
+    }
 }
index 667b4f86dbaa520c93cb3f49cefa9d4ca4821f80..0ef805eb2ed6fd8f8c985a3a74e6ddeba041ee48 100644 (file)
@@ -82,14 +82,15 @@ public class GridColumn implements Serializable {
      * Returns the caption of the header. By default the header caption is the
      * property id of the column.
      * 
-     * @return the text in the header
+     * @return the text in the default row of header, null if no default row
      * 
      * @throws IllegalStateException
      *             if the column no longer is attached to the grid
      */
+    @Deprecated
     public String getHeaderCaption() throws IllegalStateException {
         checkColumnIsAttached();
-        return getHeaderCellState().text;
+        return state.header;
     }
 
     /**
@@ -101,11 +102,10 @@ public class GridColumn implements Serializable {
      * @throws IllegalStateException
      *             if the column is no longer attached to any grid
      */
+    @Deprecated
     public void setHeaderCaption(String caption) throws IllegalStateException {
         checkColumnIsAttached();
-        getHeaderCellState().text = caption;
         state.header = caption;
-        grid.markAsDirty();
     }
 
     /**
@@ -116,6 +116,7 @@ public class GridColumn implements Serializable {
      * @throws IllegalStateException
      *             if the column is no longer attached to any grid
      */
+    @Deprecated
     public String getFooterCaption() throws IllegalStateException {
         checkColumnIsAttached();
         return getFooterCellState().text;
@@ -130,6 +131,7 @@ public class GridColumn implements Serializable {
      * @throws IllegalStateException
      *             if the column is no longer attached to any grid
      */
+    @Deprecated
     public void setFooterCaption(String caption) throws IllegalStateException {
         checkColumnIsAttached();
         getFooterCellState().text = caption;
@@ -137,11 +139,6 @@ public class GridColumn implements Serializable {
         grid.markAsDirty();
     }
 
-    private CellState getHeaderCellState() {
-        int index = grid.getState().columns.indexOf(state);
-        return grid.getState().header.rows.get(0).cells.get(index);
-    }
-
     private CellState getFooterCellState() {
         int index = grid.getState().columns.indexOf(state);
         return grid.getState().footer.rows.get(0).cells.get(index);
@@ -252,7 +249,7 @@ public class GridColumn implements Serializable {
      *            the renderer to use
      * @throws IllegalArgumentException
      *             if no compatible converter could be found
-     *
+     * 
      * @see VaadinSession#getConverterFactory()
      * @see ConverterUtil#getConverter(Class, Class, VaadinSession)
      * @see #setConverter(Converter)
diff --git a/server/src/com/vaadin/ui/components/grid/GridFooter.java b/server/src/com/vaadin/ui/components/grid/GridFooter.java
new file mode 100644 (file)
index 0000000..e4a7eab
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2014 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.ui.components.grid;
+
+import com.vaadin.shared.ui.grid.GridStaticSectionState;
+
+/**
+ * Represents the footer section of a Grid. By default Footer is not visible.
+ * 
+ * @since
+ * @author Vaadin Ltd
+ */
+public class GridFooter extends GridStaticSection<GridFooter.FooterRow> {
+
+    public class FooterRow extends GridStaticSection.StaticRow<FooterCell> {
+
+        protected FooterRow(GridStaticSection<?> section) {
+            super(section);
+        }
+
+        @Override
+        protected FooterCell createCell() {
+            return new FooterCell(this);
+        }
+
+    }
+
+    public class FooterCell extends GridStaticSection.StaticCell<FooterRow> {
+
+        protected FooterCell(FooterRow row) {
+            super(row);
+        }
+    }
+
+    private final GridStaticSectionState footerState = new GridStaticSectionState();
+
+    protected GridFooter(Grid grid) {
+        this.grid = grid;
+        grid.getState(true).footer = footerState;
+        setVisible(false);
+    }
+
+    @Override
+    protected GridStaticSectionState getState() {
+        return footerState;
+    }
+
+    @Override
+    protected FooterRow createRow() {
+        return new FooterRow(this);
+    }
+
+}
diff --git a/server/src/com/vaadin/ui/components/grid/GridHeader.java b/server/src/com/vaadin/ui/components/grid/GridHeader.java
new file mode 100644 (file)
index 0000000..f8bd3c6
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000-2014 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.ui.components.grid;
+
+import com.vaadin.shared.ui.grid.GridStaticSectionState;
+
+/**
+ * Represents the header section of a Grid.
+ * 
+ * @since
+ * @author Vaadin Ltd
+ */
+public class GridHeader extends GridStaticSection<GridHeader.HeaderRow> {
+
+    public class HeaderRow extends GridStaticSection.StaticRow<HeaderCell> {
+
+        protected HeaderRow(GridStaticSection<?> section) {
+            super(section);
+        }
+
+        private void setDefaultRow(boolean value) {
+            getRowState().defaultRow = value;
+        }
+
+        @Override
+        protected HeaderCell createCell() {
+            return new HeaderCell(this);
+        }
+    }
+
+    public class HeaderCell extends GridStaticSection.StaticCell<HeaderRow> {
+
+        protected HeaderCell(HeaderRow row) {
+            super(row);
+        }
+    }
+
+    private HeaderRow defaultRow = null;
+    private final GridStaticSectionState headerState = new GridStaticSectionState();
+
+    protected GridHeader(Grid grid) {
+        this.grid = grid;
+        grid.getState(true).header = headerState;
+        HeaderRow row = createRow();
+        rows.add(row);
+        setDefaultRow(row);
+        getState().rows.add(row.getRowState());
+    }
+
+    /**
+     * Sets the default row of this header. The default row is a special header
+     * row providing a user interface for sorting columns.
+     * 
+     * @param row
+     *            the new default row, or null for no default row
+     * 
+     * @throws IllegalArgumentException
+     *             this header does not contain the row
+     */
+    public void setDefaultRow(HeaderRow row) {
+        if (row == defaultRow) {
+            return;
+        }
+
+        if (row != null && !rows.contains(row)) {
+            throw new IllegalArgumentException(
+                    "Cannot set a default row that does not exist in the section");
+        }
+
+        if (defaultRow != null) {
+            defaultRow.setDefaultRow(false);
+        }
+
+        if (row != null) {
+            row.setDefaultRow(true);
+        }
+
+        defaultRow = row;
+        markAsDirty();
+    }
+
+    /**
+     * Returns the current default row of this header. The default row is a
+     * special header row providing a user interface for sorting columns.
+     * 
+     * @return the default row or null if no default row set
+     */
+    public HeaderRow getDefaultRow() {
+        return defaultRow;
+    }
+
+    @Override
+    protected GridStaticSectionState getState() {
+        return headerState;
+    }
+
+    @Override
+    protected HeaderRow createRow() {
+        return new HeaderRow(this);
+    }
+
+    @Override
+    public HeaderRow removeRow(int rowIndex) {
+        HeaderRow row = super.removeRow(rowIndex);
+        if (row == defaultRow) {
+            // Default Header Row was just removed.
+            setDefaultRow(null);
+        }
+        return row;
+    }
+}
diff --git a/server/src/com/vaadin/ui/components/grid/GridStaticSection.java b/server/src/com/vaadin/ui/components/grid/GridStaticSection.java
new file mode 100644 (file)
index 0000000..80d822e
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2000-2014 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.ui.components.grid;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.vaadin.data.Container.Indexed;
+import com.vaadin.shared.ui.grid.GridStaticSectionState;
+import com.vaadin.shared.ui.grid.GridStaticSectionState.CellState;
+import com.vaadin.shared.ui.grid.GridStaticSectionState.RowState;
+
+/**
+ * Abstract base class for Grid header and footer sections.
+ * 
+ * @since
+ * @author Vaadin Ltd
+ * @param <ROWTYPE>
+ *            the type of the rows in the section
+ */
+abstract class GridStaticSection<ROWTYPE extends GridStaticSection.StaticRow<?>>
+        implements Serializable {
+
+    /**
+     * Abstract base class for Grid header and footer rows.
+     * 
+     * @param <CELLTYPE>
+     *            the type of the cells in the row
+     */
+    abstract static class StaticRow<CELLTYPE extends StaticCell<?>> implements
+            Serializable {
+
+        private RowState rowState = new RowState();
+        protected GridStaticSection<?> section;
+        private Map<Object, CELLTYPE> cells = new LinkedHashMap<Object, CELLTYPE>();
+
+        protected StaticRow(GridStaticSection<?> section) {
+            this.section = section;
+        }
+
+        protected void addCell(Object propertyId) {
+            CELLTYPE cell = createCell();
+            cells.put(propertyId, cell);
+            rowState.cells.add(cell.getCellState());
+        }
+
+        /**
+         * Creates and returns a new instance of the cell type.
+         * 
+         * @return the created cell
+         */
+        protected abstract CELLTYPE createCell();
+
+        protected RowState getRowState() {
+            return rowState;
+        }
+
+        /**
+         * Returns the cell at the given position in this row.
+         * 
+         * @param propertyId
+         *            the itemId of column
+         * @return the cell on given column
+         * @throws IndexOutOfBoundsException
+         *             if the index is out of bounds
+         */
+        public CELLTYPE getCell(Object propertyId) {
+            return cells.get(propertyId);
+        }
+    }
+
+    /**
+     * A header or footer cell. Has a simple textual caption.
+     * 
+     * @param <ROWTYPE>
+     *            the type of row this cells is in
+     */
+    abstract static class StaticCell<ROWTYPE extends StaticRow<?>> implements
+            Serializable {
+
+        private CellState cellState = new CellState();
+        private ROWTYPE row;
+
+        protected StaticCell(ROWTYPE row) {
+            this.row = row;
+        }
+
+        /**
+         * Gets the row where this cell is.
+         * 
+         * @return row for this cell
+         */
+        public ROWTYPE getRow() {
+            return row;
+        }
+
+        protected CellState getCellState() {
+            return cellState;
+        }
+
+        /**
+         * Gets the current text content of this cell. Text is null if HTML or
+         * Component content is used.
+         * 
+         * @return text content or null
+         */
+        public String getText() {
+            return cellState.text;
+        }
+
+        /**
+         * Sets the current text content of this cell.
+         * 
+         * @param text
+         *            new text content
+         */
+        public void setText(String text) {
+            if (text != null && !text.equals(getCellState().text)) {
+                getCellState().text = text;
+                row.section.markAsDirty();
+            }
+        }
+    }
+
+    protected Grid grid;
+    protected List<ROWTYPE> rows = new ArrayList<ROWTYPE>();
+
+    /**
+     * Sets the visibility of the whole section.
+     * 
+     * @param visible
+     *            true to show this section, false to hide
+     */
+    public void setVisible(boolean visible) {
+        if (getState().visible != visible) {
+            getState().visible = visible;
+            markAsDirty();
+        }
+    }
+
+    /**
+     * Returns the visibility of this section.
+     * 
+     * @return true if visible, false otherwise.
+     */
+    public boolean isVisible() {
+        return getState().visible;
+    }
+
+    /**
+     * Removes the row at the given position.
+     * 
+     * @param index
+     *            the position of the row
+     * 
+     * @throws IndexOutOfBoundsException
+     *             if the index is out of bounds
+     */
+    public ROWTYPE removeRow(int rowIndex) {
+        ROWTYPE row = rows.remove(rowIndex);
+        getState().rows.remove(rowIndex);
+
+        markAsDirty();
+        return row;
+    }
+
+    /**
+     * Removes the given row from the section.
+     * 
+     * @param row
+     *            the row to be removed
+     * 
+     * @throws IllegalArgumentException
+     *             if the row does not exist in this section
+     */
+    public void removeRow(ROWTYPE row) {
+        try {
+            removeRow(rows.indexOf(row));
+        } catch (IndexOutOfBoundsException e) {
+            throw new IllegalArgumentException(
+                    "Section does not contain the given row");
+        }
+    }
+
+    /**
+     * Gets row at given index.
+     * 
+     * @param rowIndex
+     *            0 based index for row. Counted from top to bottom
+     * @return row at given index
+     */
+    public ROWTYPE getRow(int rowIndex) {
+        return rows.get(rowIndex);
+    }
+
+    /**
+     * Adds a new row at the top of this section.
+     * 
+     * @return the new row
+     */
+    public ROWTYPE prependRow() {
+        return addRowAt(0);
+    }
+
+    /**
+     * Adds a new row at the bottom of this section.
+     * 
+     * @return the new row
+     */
+    public ROWTYPE appendRow() {
+        return addRowAt(rows.size());
+    }
+
+    /**
+     * Inserts a new row at the given position.
+     * 
+     * @param index
+     *            the position at which to insert the row
+     * @return the new row
+     * 
+     * @throws IndexOutOfBoundsException
+     *             if the index is out of bounds
+     */
+    public ROWTYPE addRowAt(int index) {
+        ROWTYPE row = createRow();
+        rows.add(index, row);
+        getState().rows.add(index, row.getRowState());
+
+        Indexed dataSource = grid.getContainerDatasource();
+        for (Object id : dataSource.getContainerPropertyIds()) {
+            row.addCell(id);
+        }
+
+        markAsDirty();
+        return row;
+    }
+
+    /**
+     * Gets the amount of rows in this section.
+     * 
+     * @return row count
+     */
+    public int getRowCount() {
+        return rows.size();
+    }
+
+    protected abstract GridStaticSectionState getState();
+
+    protected abstract ROWTYPE createRow();
+
+    /**
+     * Informs the grid that state has changed and it should be redrawn.
+     */
+    protected void markAsDirty() {
+        grid.markAsDirty();
+    }
+}
index 9d71d21d59762b444f877157a0b705a885bdd783..d1c821cc549be8f29ae81d21afc215fb21893368 100644 (file)
@@ -77,7 +77,8 @@ public class GridColumns {
             assertNotNull(column);
 
             // Property id should be the column header by default
-            assertEquals(propertyId.toString(), column.getHeaderCaption());
+            assertEquals(propertyId.toString(), grid.getHeader()
+                    .getDefaultRow().getCell(propertyId).getText());
         }
     }
 
@@ -88,11 +89,6 @@ public class GridColumns {
         GridColumn column = grid.getColumn("column1");
         assertNotNull(column);
 
-        column.setFooterCaption("CustomFooter");
-        assertEquals("CustomFooter", column.getFooterCaption());
-        assertEquals(column.getFooterCaption(),
-                getColumnState("column1").footer);
-
         column.setHeaderCaption("CustomHeader");
         assertEquals("CustomHeader", column.getHeaderCaption());
         assertEquals(column.getHeaderCaption(),
@@ -174,31 +170,31 @@ public class GridColumns {
     @Test
     public void testHeaderVisiblility() throws Exception {
 
-        assertTrue(grid.isColumnHeadersVisible());
+        assertTrue(grid.getHeader().isVisible());
         assertTrue(state.header.visible);
 
-        grid.setColumnHeadersVisible(false);
-        assertFalse(grid.isColumnHeadersVisible());
+        grid.getHeader().setVisible(false);
+        assertFalse(grid.getHeader().isVisible());
         assertFalse(state.header.visible);
 
-        grid.setColumnHeadersVisible(true);
-        assertTrue(grid.isColumnHeadersVisible());
+        grid.getHeader().setVisible(true);
+        assertTrue(grid.getHeader().isVisible());
         assertTrue(state.header.visible);
     }
 
     @Test
     public void testFooterVisibility() throws Exception {
 
-        assertFalse(grid.isColumnFootersVisible());
-        assertFalse(state.footer.visible);
-
-        grid.setColumnFootersVisible(false);
-        assertFalse(grid.isColumnFootersVisible());
+        assertFalse(grid.getFooter().isVisible());
         assertFalse(state.footer.visible);
 
-        grid.setColumnFootersVisible(true);
-        assertTrue(grid.isColumnFootersVisible());
+        grid.getFooter().setVisible(true);
+        assertTrue(grid.getFooter().isVisible());
         assertTrue(state.footer.visible);
+
+        grid.getFooter().setVisible(false);
+        assertFalse(grid.getFooter().isVisible());
+        assertFalse(state.footer.visible);
     }
 
     @Test
index cfe36462959b5a6caff6aa58803ef0d449471569..bff16d8db7989272534df19eca9957da2618ee51 100644 (file)
@@ -36,6 +36,9 @@ import com.vaadin.ui.components.grid.ColumnGroupRow;
 import com.vaadin.ui.components.grid.Grid;
 import com.vaadin.ui.components.grid.Grid.SelectionMode;
 import com.vaadin.ui.components.grid.GridColumn;
+import com.vaadin.ui.components.grid.GridFooter;
+import com.vaadin.ui.components.grid.GridHeader;
+import com.vaadin.ui.components.grid.GridHeader.HeaderRow;
 import com.vaadin.ui.components.grid.SortOrderChangeEvent;
 import com.vaadin.ui.components.grid.SortOrderChangeListener;
 import com.vaadin.ui.components.grid.renderers.DateRenderer;
@@ -142,15 +145,20 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
                     new NumberRenderer());
         }
 
+        // Create footer
+        GridFooter footer = grid.getFooter();
+        footer.appendRow();
+        footer.setVisible(false);
+
         // Add footer values (header values are automatically created)
         for (int col = 0; col < COLUMNS; col++) {
-            grid.getColumn(getColumnProperty(col)).setFooterCaption(
-                    "Footer " + col);
+            footer.getRow(0).getCell(getColumnProperty(col))
+                    .setText("Footer " + col);
         }
 
         // Set varying column widths
         for (int col = 0; col < COLUMNS; col++) {
-            grid.getColumn("Column" + col).setWidth(100 + col * 50);
+            grid.getColumn(getColumnProperty(col)).setWidth(100 + col * 50);
         }
 
         grid.addSortOrderChangeListener(new SortOrderChangeListener() {
@@ -226,29 +234,125 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
     }
 
     protected void createHeaderActions() {
-        createCategory("Headers", null);
+        createCategory("Header", null);
 
-        createBooleanAction("Visible", "Headers", true,
+        createBooleanAction("Visible", "Header", true,
                 new Command<Grid, Boolean>() {
 
                     @Override
                     public void execute(Grid grid, Boolean value, Object data) {
-                        grid.setColumnHeadersVisible(value);
+                        grid.getHeader().setVisible(value);
                     }
                 });
+
+        LinkedHashMap<String, String> defaultRows = new LinkedHashMap<String, String>();
+        defaultRows.put("Top", "Top");
+        defaultRows.put("Bottom", "Bottom");
+        defaultRows.put("Unset", "Unset");
+
+        createMultiClickAction("Default row", "Header", defaultRows,
+                new Command<Grid, String>() {
+
+                    @Override
+                    public void execute(Grid grid, String value, Object data) {
+                        HeaderRow defaultRow = null;
+                        GridHeader header = grid.getHeader();
+                        if (value.equals("Top")) {
+                            defaultRow = header.getRow(0);
+                        } else if (value.equals("Bottom")) {
+                            defaultRow = header.getRow(header.getRowCount() - 1);
+                        }
+                        header.setDefaultRow(defaultRow);
+                    }
+
+                }, defaultRows.get("Top"));
+
+        createClickAction("Prepend row", "Header", new Command<Grid, Object>() {
+
+            @Override
+            public void execute(Grid grid, Object value, Object data) {
+                grid.getHeader().prependRow();
+            }
+
+        }, null);
+        createClickAction("Append row", "Header", new Command<Grid, Object>() {
+
+            @Override
+            public void execute(Grid grid, Object value, Object data) {
+                grid.getHeader().appendRow();
+            }
+
+        }, null);
+
+        createClickAction("Remove top row", "Header",
+                new Command<Grid, Object>() {
+
+                    @Override
+                    public void execute(Grid grid, Object value, Object data) {
+                        grid.getHeader().removeRow(0);
+                    }
+
+                }, null);
+        createClickAction("Remove bottom row", "Header",
+                new Command<Grid, Object>() {
+
+                    @Override
+                    public void execute(Grid grid, Object value, Object data) {
+                        grid.getHeader().removeRow(
+                                grid.getHeader().getRowCount() - 1);
+                    }
+
+                }, null);
     }
 
     protected void createFooterActions() {
-        createCategory("Footers", null);
+        createCategory("Footer", null);
 
-        createBooleanAction("Visible", "Footers", false,
+        createBooleanAction("Visible", "Footer", false,
                 new Command<Grid, Boolean>() {
 
                     @Override
                     public void execute(Grid grid, Boolean value, Object data) {
-                        grid.setColumnFootersVisible(value);
+                        grid.getFooter().setVisible(value);
                     }
                 });
+
+        createClickAction("Prepend row", "Footer", new Command<Grid, Object>() {
+
+            @Override
+            public void execute(Grid grid, Object value, Object data) {
+                grid.getFooter().prependRow();
+            }
+
+        }, null);
+        createClickAction("Append row", "Footer", new Command<Grid, Object>() {
+
+            @Override
+            public void execute(Grid grid, Object value, Object data) {
+                grid.getFooter().appendRow();
+            }
+
+        }, null);
+
+        createClickAction("Remove top row", "Footer",
+                new Command<Grid, Object>() {
+
+                    @Override
+                    public void execute(Grid grid, Object value, Object data) {
+                        grid.getFooter().removeRow(0);
+                    }
+
+                }, null);
+        createClickAction("Remove bottom row", "Footer",
+                new Command<Grid, Object>() {
+
+                    @Override
+                    public void execute(Grid grid, Object value, Object data) {
+                        grid.getFooter().removeRow(
+                                grid.getFooter().getRowCount() - 1);
+                    }
+
+                }, null);
     }
 
     protected void createColumnActions() {
@@ -278,7 +382,8 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
                         @Override
                         public void execute(Grid grid, String value, Object data) {
                             grid.getContainerDatasource()
-                                    .removeContainerProperty("Column" + data);
+                                    .removeContainerProperty(
+                                            getColumnProperty((Integer) data));
                         }
                     }, null, c);
 
@@ -287,7 +392,7 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
 
                         @Override
                         public void execute(Grid grid, String value, Object data) {
-                            grid.setLastFrozenPropertyId("Column" + data);
+                            grid.setLastFrozenPropertyId(getColumnProperty((Integer) data));
                         }
                     }, null, c);
 
@@ -306,9 +411,9 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
                         }
                     }, c);
 
-            createCategory("Column" + c + " Width", getColumnProperty(c));
+            createCategory("Column " + c + " Width", getColumnProperty(c));
 
-            createClickAction("Auto", "Column" + c + " Width",
+            createClickAction("Auto", "Column " + c + " Width",
                     new Command<Grid, Integer>() {
 
                         @Override
@@ -324,7 +429,7 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
                     }, -1, c);
 
             for (int w = 50; w < 300; w += 50) {
-                createClickAction(w + "px", "Column" + c + " Width",
+                createClickAction(w + "px", "Column " + c + " Width",
                         new Command<Grid, Integer>() {
 
                             @Override
@@ -343,7 +448,7 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
     }
 
     private static String getColumnProperty(int c) {
-        return "Column" + c;
+        return "Column " + c;
     }
 
     protected void createColumnGroupActions() {
index 805213027e3d289dce05be1aaa2f6acbd0287726..e20b45bd1d8d6d8a2a72d247f75f7896134fc41d 100644 (file)
@@ -104,7 +104,7 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest {
     public void testNavigationFromFooterToBody() {
         openTestURL();
 
-        selectMenuPath("Component", "Footers", "Visible");
+        selectMenuPath("Component", "Footer", "Visible");
 
         GridElement grid = getGridElement();
         grid.scrollToRow(300);
@@ -146,7 +146,7 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest {
     public void testNavigateBetweenFooterAndBodyWithTab() {
         openTestURL();
 
-        selectMenuPath("Component", "Footers", "Visible");
+        selectMenuPath("Component", "Footer", "Visible");
 
         GridElement grid = getGridElement();
         grid.getCell(10, 2).click();
index 4a1d7b7be1d945c1825e2232c844d06ab4ea5d99..ee3f2a632be83b871ec20ca672f387504663e2fd 100644 (file)
@@ -21,7 +21,6 @@ import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
 
-import org.junit.Ignore;
 import org.junit.Test;
 import org.openqa.selenium.Keys;
 import org.openqa.selenium.interactions.Actions;
@@ -30,11 +29,7 @@ import com.vaadin.tests.components.grid.GridElement;
 
 public class GridSortingTest extends GridBasicFeaturesTest {
 
-    /*
-     * TODO unignore once column header captions are reimplemented
-     */
     @Test
-    @Ignore
     public void testProgrammaticSorting() throws IOException {
         openTestURL();
 
@@ -43,7 +38,7 @@ public class GridSortingTest extends GridBasicFeaturesTest {
         // Sorting by column 9 is sorting by row index that is represented as a
         // String.
         // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0)
-        sortBy("Column9, DESC");
+        sortBy("Column 9, DESC");
 
         assertTrue("Column 9 should have the sort-desc stylename", grid
                 .getHeaderCell(0, 9).getAttribute("class")
@@ -53,12 +48,12 @@ public class GridSortingTest extends GridBasicFeaturesTest {
         for (int i = 0; i < 3; ++i) {
             row += "9";
             assertEquals(
-                    "Grid is not sorted by Column9 using descending direction.",
+                    "Grid is not sorted by Column 9 using descending direction.",
                     "(" + row + ", 0)", grid.getCell(i, 0).getText());
         }
 
         // Column 10 is random numbers from Random with seed 13334
-        sortBy("Column10, ASC");
+        sortBy("Column 10, ASC");
 
         assertFalse(
                 "Column 9 should no longer have the sort-desc stylename",
@@ -75,7 +70,7 @@ public class GridSortingTest extends GridBasicFeaturesTest {
 
         for (int i = 0; i < 5; ++i) {
             assertGreater(
-                    "Grid is not sorted by Column10 using ascending direction",
+                    "Grid is not sorted by Column 10 using ascending direction",
                     Integer.parseInt(grid.getCell(i + 1, 10).getText()),
                     Integer.parseInt(grid.getCell(i, 10).getText()));
 
@@ -83,10 +78,10 @@ public class GridSortingTest extends GridBasicFeaturesTest {
 
         // Column 7 is row index as a number. Last three row are original rows
         // 2, 1 and 0.
-        sortBy("Column7, DESC");
+        sortBy("Column 7, DESC");
         for (int i = 0; i < 3; ++i) {
             assertEquals(
-                    "Grid is not sorted by Column7 using descending direction",
+                    "Grid is not sorted by Column 7 using descending direction",
                     "(" + i + ", 0)",
                     grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText());
         }
@@ -118,18 +113,18 @@ public class GridSortingTest extends GridBasicFeaturesTest {
         for (int i = 0; i < 3; ++i) {
             row += "9";
             assertEquals(
-                    "Grid is not sorted by Column9 using descending direction.",
+                    "Grid is not sorted by Column 9 using descending direction.",
                     "(" + row + ", 0)", grid.getCell(i, 0).getText());
         }
 
-        assertEquals("2. Sort order: [Column9 ASCENDING]", getLogRow(2));
-        assertEquals("4. Sort order: [Column9 DESCENDING]", getLogRow(0));
+        assertEquals("2. Sort order: [Column 9 ASCENDING]", getLogRow(2));
+        assertEquals("4. Sort order: [Column 9 DESCENDING]", getLogRow(0));
 
         // Column 10 is random numbers from Random with seed 13334
         // Click header to sort ascending
         grid.getHeaderCell(0, 10).click();
 
-        assertEquals("6. Sort order: [Column10 ASCENDING]", getLogRow(0));
+        assertEquals("6. Sort order: [Column 10 ASCENDING]", getLogRow(0));
 
         // Not cleaning up correctly causes exceptions when scrolling.
         grid.scrollToRow(50);
@@ -138,7 +133,7 @@ public class GridSortingTest extends GridBasicFeaturesTest {
 
         for (int i = 0; i < 5; ++i) {
             assertGreater(
-                    "Grid is not sorted by Column10 using ascending direction",
+                    "Grid is not sorted by Column 10 using ascending direction",
                     Integer.parseInt(grid.getCell(i + 1, 10).getText()),
                     Integer.parseInt(grid.getCell(i, 10).getText()));
 
@@ -151,13 +146,13 @@ public class GridSortingTest extends GridBasicFeaturesTest {
         grid.getHeaderCell(0, 7).click();
         for (int i = 0; i < 3; ++i) {
             assertEquals(
-                    "Grid is not sorted by Column7 using descending direction",
+                    "Grid is not sorted by Column 7 using descending direction",
                     "(" + i + ", 0)",
                     grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText());
         }
 
-        assertEquals("9. Sort order: [Column7 ASCENDING]", getLogRow(3));
-        assertEquals("11. Sort order: [Column7 DESCENDING]", getLogRow(1));
+        assertEquals("9. Sort order: [Column 7 ASCENDING]", getLogRow(3));
+        assertEquals("11. Sort order: [Column 7 DESCENDING]", getLogRow(1));
     }
 
     @Test
index 94f04e10a2fbf6282621d3ed674cb461f2a963b7..ced6963c32595392fe4e1e3136fc7e1d8c17932c 100644 (file)
@@ -22,7 +22,6 @@ import static org.junit.Assert.assertTrue;
 
 import java.util.List;
 
-import org.junit.Ignore;
 import org.junit.Test;
 import org.openqa.selenium.By;
 import org.openqa.selenium.WebElement;
@@ -31,44 +30,36 @@ import com.vaadin.testbench.TestBenchElement;
 
 public class GridStructureTest extends GridBasicFeaturesTest {
 
-    /*
-     * TODO unignore once column header captions are reimplemented
-     */
     @Test
-    @Ignore
     public void testHidingColumn() throws Exception {
         openTestURL();
 
         // Column 0 should be visible
         List<TestBenchElement> cells = getGridHeaderRowCells();
-        assertEquals("Column0", cells.get(0).getText());
+        assertEquals("Column 0", cells.get(0).getText());
 
         // Hide column 0
-        selectMenuPath("Component", "Columns", "Column0", "Visible");
+        selectMenuPath("Component", "Columns", "Column 0", "Visible");
 
         // Column 1 should now be the first cell
         cells = getGridHeaderRowCells();
-        assertEquals("Column1", cells.get(0).getText());
+        assertEquals("Column 1", cells.get(0).getText());
     }
 
-    /*
-     * TODO unignore once column header captions are reimplemented
-     */
     @Test
-    @Ignore
     public void testRemovingColumn() throws Exception {
         openTestURL();
 
         // Column 0 should be visible
         List<TestBenchElement> cells = getGridHeaderRowCells();
-        assertEquals("Column0", cells.get(0).getText());
+        assertEquals("Column 0", cells.get(0).getText());
 
         // Hide column 0
-        selectMenuPath("Component", "Columns", "Column0", "Remove");
+        selectMenuPath("Component", "Columns", "Column 0", "Remove");
 
         // Column 1 should now be the first cell
         cells = getGridHeaderRowCells();
-        assertEquals("Column1", cells.get(0).getText());
+        assertEquals("Column 1", cells.get(0).getText());
     }
 
     @Test
@@ -76,9 +67,9 @@ public class GridStructureTest extends GridBasicFeaturesTest {
         openTestURL();
 
         // Remove columns 2,3,4
-        selectMenuPath("Component", "Columns", "Column2", "Remove");
-        selectMenuPath("Component", "Columns", "Column3", "Remove");
-        selectMenuPath("Component", "Columns", "Column4", "Remove");
+        selectMenuPath("Component", "Columns", "Column 2", "Remove");
+        selectMenuPath("Component", "Columns", "Column 3", "Remove");
+        selectMenuPath("Component", "Columns", "Column 4", "Remove");
 
         // Scroll so new data is lazy loaded
         scrollGridVerticallyTo(1000);
@@ -95,7 +86,7 @@ public class GridStructureTest extends GridBasicFeaturesTest {
         openTestURL();
 
         // Freeze column 2
-        selectMenuPath("Component", "Columns", "Column2", "Freeze");
+        selectMenuPath("Component", "Columns", "Column 2", "Freeze");
 
         WebElement cell = getBodyCellByRowAndColumn(0, 0);
         assertTrue(cell.getAttribute("class").contains("frozen"));
@@ -127,20 +118,20 @@ public class GridStructureTest extends GridBasicFeaturesTest {
         assertEquals(100, cell.getSize().getWidth());
 
         // Set first column to be 200px wide
-        selectMenuPath("Component", "Columns", "Column0", "Column0 Width",
+        selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width",
                 "200px");
 
         cell = getBodyCellByRowAndColumn(0, 0);
         assertEquals(200, cell.getSize().getWidth());
 
         // Set second column to be 150px wide
-        selectMenuPath("Component", "Columns", "Column1", "Column1 Width",
+        selectMenuPath("Component", "Columns", "Column 1", "Column 1 Width",
                 "150px");
         cell = getBodyCellByRowAndColumn(0, 1);
         assertEquals(150, cell.getSize().getWidth());
 
         // Set first column to be auto sized (defaults to 100px currently)
-        selectMenuPath("Component", "Columns", "Column0", "Column0 Width",
+        selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width",
                 "Auto");
 
         cell = getBodyCellByRowAndColumn(0, 0);
@@ -203,7 +194,7 @@ public class GridStructureTest extends GridBasicFeaturesTest {
         selectMenuPath("Component", "Body rows",
                 "Modify first row (getContainerProperty)");
         assertEquals("(Second) modification with getItemProperty failed",
-                "modified: Column0", getBodyCellByRowAndColumn(0, 0).getText());
+                "modified: Column 0", getBodyCellByRowAndColumn(0, 0).getText());
     }
 
     private void assertPrimaryStylename(String stylename) {