Преглед изворни кода

Implement basic footer support for Grid

Change-Id: I3db51521320767a28bc3acd9586b1453764a15bc
tags/8.0.0.alpha5
Teemu Suo-Anttila пре 7 година
родитељ
комит
5bc6d1802e

+ 22
- 0
client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java Прегледај датотеку

@@ -53,6 +53,7 @@ import com.vaadin.client.widget.grid.sort.SortEvent;
import com.vaadin.client.widget.grid.sort.SortOrder;
import com.vaadin.client.widgets.Grid;
import com.vaadin.client.widgets.Grid.Column;
import com.vaadin.client.widgets.Grid.FooterRow;
import com.vaadin.client.widgets.Grid.HeaderRow;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.data.DataCommunicatorConstants;
@@ -264,6 +265,27 @@ public class GridConnector
}
}

/**
* Updates the grid footer section on state change.
*/
@OnStateChange("footer")
void updateFooter() {
final Grid<JsonObject> grid = getWidget();
final SectionState state = getState().footer;

while (grid.getFooterRowCount() > 0) {
grid.removeFooterRow(0);
}

for (RowState rowState : state.rows) {
FooterRow row = grid.appendFooterRow();

rowState.cells.forEach((columnId, cellState) -> {
row.getCell(getColumn(columnId)).setText(cellState.text);
});
}
}

@Override
public void setDataSource(DataSource<JsonObject> dataSource) {
super.setDataSource(dataSource);

+ 189
- 0
server/src/main/java/com/vaadin/ui/Grid.java Прегледај датотеку

@@ -54,6 +54,8 @@ import com.vaadin.shared.ui.grid.GridState;
import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.shared.ui.grid.SectionState;
import com.vaadin.shared.util.SharedUtil;
import com.vaadin.ui.Grid.FooterRow;
import com.vaadin.ui.components.grid.Footer;
import com.vaadin.ui.components.grid.Header;
import com.vaadin.ui.components.grid.Header.Row;
import com.vaadin.ui.renderers.AbstractRenderer;
@@ -1562,6 +1564,57 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents {
public void setText(String text);
}

/**
* A footer row in a Grid.
*/
public interface FooterRow extends Serializable {

/**
* Returns the cell on this row corresponding to the given column id.
*
* @param columnId
* the id of the column whose footer cell to get, not null
* @return the footer cell
* @throws IllegalArgumentException
* if there is no such column in the grid
*/
public FooterCell getCell(String columnId);

/**
* Returns the cell on this row corresponding to the given column.
*
* @param column
* the column whose footer cell to get, not null
* @return the footer cell
* @throws IllegalArgumentException
* if there is no such column in the grid
*/
public default FooterCell getCell(Column<?, ?> column) {
return getCell(column.getId());
}
}

/**
* An individual cell on a Grid footer row.
*/
public interface FooterCell extends Serializable {

/**
* Returns the textual caption of this cell.
*
* @return the footer caption
*/
public String getText();

/**
* Sets the textual caption of this cell.
*
* @param text
* the footer caption to set, not null
*/
public void setText(String text);
}

private class HeaderImpl extends Header {

@Override
@@ -1575,6 +1628,19 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents {
}
};

private class FooterImpl extends Footer {

@Override
protected SectionState getState(boolean markAsDirty) {
return Grid.this.getState(markAsDirty).footer;
}

@Override
protected Collection<Column<T, ?>> getColumns() {
return Grid.this.getColumns();
}
};

private Set<Column<T, ?>> columnSet = new LinkedHashSet<>();
private Map<String, Column<T, ?>> columnKeys = new HashMap<>();

@@ -1585,6 +1651,7 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents {
private DescriptionGenerator<T> descriptionGenerator;

private Header header = new HeaderImpl();
private Footer footer = new FooterImpl();

private int counter = 0;

@@ -2155,6 +2222,128 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents {
return header;
}

/**
* Returns the footer row at the given index.
*
* @param index
* the index of the row, where the topmost row has index zero
* @return the footer row at the index
* @throws IndexOutOfBoundsException
* if {@code rowIndex < 0 || rowIndex >= getFooterRowCount()}
*/
public FooterRow getFooterRow(int index) {
return getFooter().getRow(index);
}

/**
* Gets the number of rows in the footer section.
*
* @return the number of footer rows
*/
public int getFooterRowCount() {
return getFooter().getRowCount();
}

/**
* Inserts a new row at the given position to the footer section. Shifts the
* row currently at that position and any subsequent rows down (adds one to
* their indices). Inserting at {@link #getFooterRowCount()} appends the row
* at the bottom of the footer.
*
* @param index
* the index at which to insert the row, where the topmost row
* has index zero
* @return the inserted footer row
*
* @throws IndexOutOfBoundsException
* if {@code rowIndex < 0 || rowIndex > getFooterRowCount()}
*
* @see #appendFooterRow()
* @see #prependFooterRow()
* @see #removeFooterRow(FooterRow)
* @see #removeFooterRow(int)
*/
public FooterRow addFooterRowAt(int index) {
return getFooter().addRowAt(index);
}

/**
* Adds a new row at the bottom of the footer section.
*
* @return the appended footer row
*
* @see #prependFooterRow()
* @see #addFooterRowAt(int)
* @see #removeFooterRow(FooterRow)
* @see #removeFooterRow(int)
*/
public FooterRow appendFooterRow() {
return addFooterRowAt(getFooterRowCount());
}

/**
* Adds a new row at the top of the footer section.
*
* @return the prepended footer row
*
* @see #appendFooterRow()
* @see #addFooterRowAt(int)
* @see #removeFooterRow(FooterRow)
* @see #removeFooterRow(int)
*/
public FooterRow prependFooterRow() {
return addFooterRowAt(0);
}

/**
* Removes the given row from the footer section. Removing a default row
* sets the Grid to have no default row.
*
* @param row
* the footer row to be removed, not null
*
* @throws IllegalArgumentException
* if the footer does not contain the row
*
* @see #removeFooterRow(int)
* @see #addFooterRowAt(int)
* @see #appendFooterRow()
* @see #prependFooterRow()
*/
public void removeFooterRow(FooterRow row) {
getFooter().removeRow(row);
}

/**
* Removes the row at the given position from the footer section.
*
* @param index
* the index of the row to remove, where the topmost row has
* index zero
*
* @throws IndexOutOfBoundsException
* if {@code index < 0 || index >= getFooterRowCount()}
*
* @see #removeFooterRow(FooterRow)
* @see #addFooterRowAt(int)
* @see #appendFooterRow()
* @see #prependFooterRow()
*/
public void removeFooterRow(int index) {
getFooter().removeRow(index);
}

/**
* Returns the footer section of this grid. The default footer contains a
* single row, set as the {@linkplain #setDefaultFooterRow(FooterRow)
* default row}.
*
* @return the footer section
*/
protected Footer getFooter() {
return footer;
}

/**
* Registers a new column reorder listener.
*

+ 70
- 0
server/src/main/java/com/vaadin/ui/components/grid/Footer.java Прегледај датотеку

@@ -0,0 +1,70 @@
/*
* 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.ui.components.grid;

import com.vaadin.ui.Grid;

/**
* Represents the footer section of a Grid.
*
* @author Vaadin Ltd.
*
* @since 8.0
*/
public abstract class Footer extends StaticSection<Footer.Row> {

/**
* A row in a Grid Footer.
*/
public class Row extends StaticSection.StaticRow<Row.Cell>
implements Grid.FooterRow {

/**
* A cell in a Grid footer row.
*/
public class Cell extends StaticSection.StaticCell
implements Grid.FooterCell {
/**
* Creates a new footer cell.
*/
protected Cell() {
super(Row.this);
}
}

/**
* Creates a new footer row.
*/
protected Row() {
super(Footer.this);
}

@Override
protected Cell createCell() {
return new Cell();
}

@Override
protected String getCellTagName() {
return "td";
}
}

@Override
public Row createRow() {
return new Row();
}
}

+ 3
- 0
shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java Прегледај датотеку

@@ -102,6 +102,9 @@ public class GridState extends AbstractSingleSelectState {
/** The state of the header section. */
public SectionState header = new SectionState();

/** The state of the footer section. */
public SectionState footer = new SectionState();

/**
* Column order in grid.
*/

+ 31
- 0
uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java Прегледај датотеку

@@ -20,6 +20,7 @@ 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.FooterRow;
import com.vaadin.ui.Grid.HeaderRow;
import com.vaadin.ui.Label;
import com.vaadin.ui.MenuBar;
@@ -199,6 +200,7 @@ public class GridBasics extends AbstractReindeerTestUIWithLog {
createDetailsMenu(componentMenu.addItem("Details", null));
createBodyMenu(componentMenu.addItem("Body rows", null));
createHeaderMenu(componentMenu.addItem("Header", null));
createFooterMenu(componentMenu.addItem("Footer", null));
createColumnsMenu(componentMenu.addItem("Columns", null));
return menu;
}
@@ -409,6 +411,35 @@ public class GridBasics extends AbstractReindeerTestUIWithLog {
});
}

private void createFooterMenu(MenuItem footerMenu) {
footerMenu.addItem("Add default footer row", menuItem -> {
FooterRow defaultFooter = grid.appendFooterRow();
grid.getColumns().forEach(
column -> defaultFooter.getCell(column).setText(grid
.getDefaultHeaderRow().getCell(column).getText()));
footerMenu.removeChild(menuItem);
});
footerMenu.addItem("Append footer row", menuItem -> {
FooterRow row = grid.appendFooterRow();

int i = 0;
for (Column<?, ?> column : grid.getColumns()) {
row.getCell(column).setText("Footer cell " + i++);
}
});
footerMenu.addItem("Prepend footer row", menuItem -> {
FooterRow row = grid.prependFooterRow();

int i = 0;
for (Column<?, ?> column : grid.getColumns()) {
row.getCell(column).setText("Footer cell " + i++);
}
});
footerMenu.addItem("Remove first footer row", menuItem -> {
grid.removeFooterRow(0);
});
}

/* DetailsGenerator related things */

private void createDetailsMenu(MenuItem detailsMenu) {

+ 52
- 8
uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridHeaderFooterTest.java Прегледај датотеку

@@ -31,8 +31,18 @@ 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);
.mapToObj(i -> "Header cell " + i).toArray(String[]::new);

protected static final String[] FOOTER_TEXTS = IntStream
.range(0, GridBasics.COLUMN_CAPTIONS.length)
.mapToObj(i -> "Footer cell " + i).toArray(String[]::new);

@Override
public void setUp() {
super.setUp();

selectMenuPath("Component", "Footer", "Add default footer row");
}

@Test
public void initialState_defaultHeaderPresent() {
@@ -103,16 +113,40 @@ public class GridHeaderFooterTest extends GridBasicsTest {
assertNoSortIndicator(headerCell, "sort-desc");
}

@Test
public void initialState_defaultFooterPresent() {
assertEquals(1, getGridElement().getFooterCount());
assertFooterTexts(0, GridBasics.COLUMN_CAPTIONS);
}

@Test
public void appendFooterRow_addedToBottom() {
selectMenuPath("Component", "Footer", "Append footer row");

assertEquals(2, getGridElement().getFooterCount());
assertFooterTexts(0, GridBasics.COLUMN_CAPTIONS);
assertFooterTexts(1, FOOTER_TEXTS);
}

@Test
public void prependFooterRow_addedToTop() {
selectMenuPath("Component", "Footer", "Prepend footer row");

assertEquals(2, getGridElement().getFooterCount());
assertFooterTexts(0, FOOTER_TEXTS);
assertFooterTexts(1, GridBasics.COLUMN_CAPTIONS);
}

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");
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);
List<GridCellElement> headerCells = getGridElement()
.getHeaderCells(rowIndex);

assertEquals(texts.length, headerCells.size());
for (int i = 0; i < headerCells.size(); i++) {
@@ -120,9 +154,19 @@ public class GridHeaderFooterTest extends GridBasicsTest {
}
}

protected void assertFooterTexts(int rowIndex, String[] texts) {
List<GridCellElement> footerCells = getGridElement()
.getFooterCells(rowIndex);

assertEquals(texts.length, footerCells.size());
for (int i = 0; i < footerCells.size(); i++) {
assertText(texts[i], footerCells.get(i));
}
}

protected void assertSortIndicator(GridCellElement cell, String classname) {
assertTrue("Header cell should have sort indicator " + classname, cell
.getAttribute("class").contains(classname));
assertTrue("Header cell should have sort indicator " + classname,
cell.getAttribute("class").contains(classname));
}

protected void assertNoSortIndicator(GridCellElement cell,

Loading…
Откажи
Сачувај