ソースを参照

Initial support for multiple headers in new Grid

Change-Id: I7a3fa34749322451ab5cef4465d4d7c76029c097
tags/8.0.0.alpha3
Johannes Dahlström 7年前
コミット
680b7009d4

+ 46
- 5
client/src/main/java/com/vaadin/client/connectors/grid/GridConnector.java ファイルの表示

@@ -34,6 +34,7 @@ import com.vaadin.client.HasComponentsConnector;
import com.vaadin.client.MouseEventDetailsBuilder;
import com.vaadin.client.TooltipInfo;
import com.vaadin.client.WidgetUtil;
import com.vaadin.client.annotations.OnStateChange;
import com.vaadin.client.connectors.AbstractListingConnector;
import com.vaadin.client.data.DataSource;
import com.vaadin.client.ui.SimpleManagedLayout;
@@ -49,6 +50,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.HeaderRow;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.data.DataCommunicatorConstants;
import com.vaadin.shared.data.selection.SelectionModel;
@@ -59,6 +61,8 @@ import com.vaadin.shared.ui.grid.GridConstants;
import com.vaadin.shared.ui.grid.GridConstants.Section;
import com.vaadin.shared.ui.grid.GridServerRpc;
import com.vaadin.shared.ui.grid.GridState;
import com.vaadin.shared.ui.grid.SectionState;
import com.vaadin.shared.ui.grid.SectionState.RowState;

import elemental.json.JsonObject;

@@ -102,6 +106,8 @@ public class GridConnector

/* Map to keep track of all added columns */
private Map<Column<?, JsonObject>, String> columnToIdMap = new HashMap<>();
private Map<String, Column<?, JsonObject>> idToColumn = new HashMap<>();

/* Child component list for HasComponentsConnector */
private List<ComponentConnector> childComponents;
private SpaceSelectHandler<JsonObject> spaceSelectHandler;
@@ -109,16 +115,27 @@ public class GridConnector
private ItemClickHandler itemClickHandler = new ItemClickHandler();

/**
* Gets the string identifier of a {@link Column} in this grid.
* Gets the string identifier of the given column in this grid.
*
* @param column
* the column for which the identifier is to be retrieved for
* @return the string identifying the given column in this grid
* the column whose id to get
* @return the string id of the column
*/
public String getColumnId(Grid.Column<?, ?> column) {
public String getColumnId(Column<?, ?> column) {
return columnToIdMap.get(column);
}

/**
* Gets the column corresponding to the given string identifier.
*
* @param columnId
* the id of the column to get
* @return the column with the given id
*/
public Column<?, ?> getColumn(String columnId) {
return idToColumn.get(columnId);
}

@Override
@SuppressWarnings("unchecked")
public Grid<JsonObject> getWidget() {
@@ -202,6 +219,28 @@ public class GridConnector
layout();
}

@OnStateChange("header")
void updateHeader() {
final SectionState state = getState().header;
final Grid<JsonObject> grid = getWidget();

while (grid.getHeaderRowCount() > 0) {
grid.removeHeaderRow(0);
}

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));
}
}

@Override
public void setDataSource(DataSource<JsonObject> dataSource) {
super.setDataSource(dataSource);
@@ -228,6 +267,7 @@ public class GridConnector
.containsValue(id) : "Column with given id already exists.";
getWidget().addColumn(column);
columnToIdMap.put(column, id);
idToColumn.put(id, column);
}

/**
@@ -241,7 +281,8 @@ public class GridConnector
assert columnToIdMap
.containsKey(column) : "Given Column does not exist.";
getWidget().removeColumn(column);
columnToIdMap.remove(column);
String id = columnToIdMap.remove(column);
idToColumn.remove(id);
}

@Override

+ 206
- 5
server/src/main/java/com/vaadin/ui/Grid.java ファイルの表示

@@ -49,6 +49,8 @@ import com.vaadin.shared.ui.grid.GridConstants.Section;
import com.vaadin.shared.ui.grid.GridServerRpc;
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.renderers.AbstractRenderer;
import com.vaadin.ui.renderers.Renderer;
import com.vaadin.ui.renderers.TextRenderer;
@@ -512,7 +514,7 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents {
if (rowKey != null) {
item = getDataCommunicator().getKeyMapper().get(rowKey);
}
fireEvent(new GridContextClickEvent<T>(Grid.this, details, section,
fireEvent(new GridContextClickEvent<>(Grid.this, details, section,
rowIndex, item, getColumn(columnId)));
}

@@ -824,6 +826,15 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents {
super.extend(grid);
}

/**
* Returns the identifier used with this Column in communication.
*
* @return the identifier string
*/
public String getId() {
return getState(false).id;
}

/**
* Sets the identifier to use with this Column in communication.
*
@@ -1408,6 +1419,53 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents {
}
}

/**
* A header row in a Grid.
*/
public interface HeaderRow extends Serializable {

/**
* Returns the cell on this row corresponding to the given column id.
*
* @param columnId
* the id of the column whose header cell to get
* @return the header cell
*/
public HeaderCell getCell(String columnId);

/**
* Returns the cell on this row corresponding to the given column.
*
* @param column
* the column whose header cell to get
* @return the header cell
*/
public default HeaderCell getCell(Column<?, ?> column) {
return getCell(column.getId());
}
}

/**
* An individual cell on a Grid header row.
*/
public interface HeaderCell extends Serializable {

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

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

private KeyMapper<Column<T, ?>> columnKeys = new KeyMapper<>();
private Set<Column<T, ?>> columnSet = new LinkedHashSet<>();
private List<SortOrder<Column<T, ?>>> sortOrder = new ArrayList<>();
@@ -1416,15 +1474,26 @@ 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;
}
};

/**
* Constructor for the {@link Grid} component.
*/
public Grid() {
setSelectionModel(new SingleSelection());
registerRpc(new GridServerRpcImpl());

appendHeaderRow();

detailsManager = new DetailsManager<>();
addExtension(detailsManager);
addDataGenerator(detailsManager);

addDataGenerator((item, json) -> {
String styleName = styleGenerator.apply(item);
if (styleName != null && !styleName.isEmpty()) {
@@ -1455,8 +1524,6 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents {
* the value provider
* @param renderer
* the column value class
* @param <T>
* the type of this grid
* @param <V>
* the column value type
*
@@ -1467,13 +1534,23 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents {
public <V> Column<T, V> addColumn(String caption,
Function<T, ? extends V> valueProvider,
AbstractRenderer<? super T, V> renderer) {
Column<T, V> column = new Column<>(caption, valueProvider, renderer);
final Column<T, V> column = new Column<>(caption, valueProvider,
renderer);
final String columnId = columnKeys.key(column);

column.extend(this);
column.setId(columnKeys.key(column));
column.setId(columnId);
columnSet.add(column);
addDataGenerator(column);

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);
}

return column;
}

@@ -1762,6 +1839,130 @@ public class Grid<T> extends AbstractSingleSelect<T> implements HasComponents {
return descriptionGenerator;
}

//
// HEADER AND FOOTER
//

/**
* Returns the header row at the given index.
*
* @param rowIndex
* 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);
}

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

/**
* Inserts a new row at the given position to the header section. Shifts the
* row currently at that position and any subsequent rows down (adds one to
* their indices). Inserting at {@link #getHeaderRowCount()} appends the row
* at the bottom of the header.
*
* @param index
* the index at which to insert the row, where the topmost row
* has index zero
* @return the inserted header row
*
* @throws IndexOutOfBoundsException
* if {@code rowIndex < 0 || rowIndex > getHeaderRowCount()}
*
* @see #appendHeaderRow()
* @see #prependHeaderRow()
* @see #removeHeaderRow(HeaderRow)
* @see #removeHeaderRow(int)
*/
public HeaderRow addHeaderRowAt(int index) {
return getHeader().addRowAt(index);
}

/**
* Adds a new row at the bottom of the header section.
*
* @return the appended header row
*
* @see #prependHeaderRow()
* @see #addHeaderRowAt(int)
* @see #removeHeaderRow(HeaderRow)
* @see #removeHeaderRow(int)
*/
public HeaderRow appendHeaderRow() {
return addHeaderRowAt(getHeaderRowCount());
}

/**
* Adds a new row at the top of the header section.
*
* @return the prepended header row
*
* @see #appendHeaderRow()
* @see #addHeaderRowAt(int)
* @see #removeHeaderRow(HeaderRow)
* @see #removeHeaderRow(int)
*/
public HeaderRow prependHeaderRow() {
return addHeaderRowAt(0);
}

/**
* Removes the given row from the header section.
*
* @param row
* the header row to be removed, not null
*
* @throws IllegalArgumentException
* if the header does not contain the row
*
* @see #removeHeaderRow(int)
* @see #addHeaderRowAt(int)
* @see #appendHeaderRow()
* @see #prependHeaderRow()
*/
public void removeHeaderRow(HeaderRow row) {
getHeader().removeRow(row);
}

/**
* Removes the row at the given position from the header section.
*
* @param rowIndex
* the index of the row to remove, where the topmost row has
* index zero
*
* @throws IndexOutOfBoundsException
* if {@code rowIndex < 0 || rowIndex >= getHeaderRowCount()}
*
* @see #removeHeaderRow(HeaderRow)
* @see #addHeaderRowAt(int)
* @see #appendHeaderRow()
* @see #prependHeaderRow()
*/
public void removeHeaderRow(int rowIndex) {
getHeader().removeRow(rowIndex);
}

/**
* Returns the header section of this grid. The default header contains a
* single row displaying the column captions.
*
* @return the header section
*/
protected Header getHeader() {
return header;
}

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

+ 57
- 0
server/src/main/java/com/vaadin/ui/components/grid/Header.java ファイルの表示

@@ -0,0 +1,57 @@
/*
* 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 header section of a Grid.
*/
public abstract class Header extends StaticSection<Header.Row> {

public class Row extends StaticSection.StaticRow<Row.Cell>
implements Grid.HeaderRow {

public class Cell extends StaticSection.StaticCell implements
Grid.HeaderCell {
protected Cell() {
super(Row.this);
}
}

/**
* @param section
*/
protected Row() {
super(Header.this);
}

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

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

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

+ 307
- 0
server/src/main/java/com/vaadin/ui/components/grid/StaticSection.java ファイルの表示

@@ -0,0 +1,307 @@
/*
* 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 java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
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;

/**
* Represents the header or footer section of a Grid.
*
* @author Vaadin Ltd.
*
* @param <ROW>
* the type of the rows in the section
*
* @since 8.0
*/
public abstract class StaticSection<ROW extends StaticSection.StaticRow<?>>
implements Serializable {

/**
* Abstract base class for Grid header and footer rows.
*
* @param <CELL>
* the type of the cells in the row
*/
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<>();

/**
* Creates a new row belonging to the given section.
*
* @param section
* the section of the row
*/
protected StaticRow(StaticSection<?> section) {
this.section = section;
}

/**
* Creates and returns a new instance of the cell type.
*
* @return the created cell
*/
protected abstract CELL createCell();

/**
* Returns the declarative tag name used for the cells in this row.
*
* @return the cell tag name
*/
protected abstract String getCellTagName();

/**
* Adds a cell to this section, corresponding to the given column id.
*
* @param columnId
* the id of the column for which to add a cell
*/
protected void addCell(String columnId) {
CELL cell = createCell();
cell.setColumnId(columnId);
cells.put(columnId, cell);
rowState.cells.put(columnId, cell.getCellState());
}

/**
* Removes the cell from this section that corresponds to the given
* column id. If there is no such cell, does nothing.
*
* @param columnId
* the id of the column from which to remove the cell
*/
protected void removeCell(Object columnId) {
CELL cell = cells.remove(columnId);
if (cell != null) {
rowState.cells.remove(cell.getCellState());
}
}

/**
* Returns the shared state of this row.
*
* @return the row state
*/
protected RowState getRowState() {
return rowState;
}

/**
* Returns the cell in this section that corresponds to the given column
* id.
*
* @param columnId
* the id of the column
* @return the cell for the given column or null if not found
*/
public CELL getCell(String columnId) {
CELL cell = cells.get(columnId);
return cell;
}
}

/**
* A header or footer cell. Has a simple textual caption.
*/
abstract static class StaticCell implements Serializable {

private CellState cellState = new CellState();
private StaticRow<?> row;

protected StaticCell(StaticRow<?> row) {
this.row = row;
}

void setColumnId(String id) {
cellState.columnId = id;
}

String getColumnId() {
return cellState.columnId;
}

/**
* Gets the row where this cell is.
*
* @return row for this cell
*/
public StaticRow<?> getRow() {
return row;
}

/**
* Returns the shared state of this cell.
*
* @return the cell state
*/
protected CellState getCellState() {
return cellState;
}

/**
* Sets the textual caption of this cell.
*
* @param text
* a plain text caption, not null
*/
public void setText(String text) {
Objects.requireNonNull(text, "text cannot be null");
cellState.text = text;
row.section.markAsDirty();
}

/**
* Returns the textual caption of this cell.
*
* @return the plain text caption
*/
public String getText() {
return cellState.text;
}
}

private List<ROW> rows = new ArrayList<>();

/**
* Creates a new row instance.
*
* @return the new row
*/
protected abstract ROW createRow();

/**
* Returns the shared state of this section.
*
* @param markAsDirty
* {@code true} to mark the state as modified, {@code false}
* otherwise
* @return the section state
*/
protected abstract SectionState getState(boolean markAsDirty);

/**
* Marks the state of this section as modified.
*/
protected void markAsDirty() {
getState(true);
}

/**
* Adds a new row at the given index.
*
* @param index
* the index of the new row
* @return the added row
* @throws IndexOutOfBoundsException
* if {@code index < 0 || index > getRowCount()}
*/
public ROW addRowAt(int index) {
ROW row = createRow();
rows.add(index, row);
getState(true).rows.add(index, row.getRowState());
return row;
}

/**
* Removes the row at the given index.
*
* @param index
* the index of the row to remove
* @throws IndexOutOfBoundsException
* if {@code index < 0 || index >= getRowCount()}
*/
public void removeRow(int index) {
rows.remove(index);
getState(true).rows.remove(index);
}

/**
* Removes the given row from this section.
*
* @param row
* the row to remove, not null
* @throws IllegalArgumentException
* if this section does not contain the row
*/
public void removeRow(Object row) {
Objects.requireNonNull(row, "row cannot be null");
int index = rows.indexOf(row);
if (index < 0) {
throw new IllegalArgumentException(
"Section does not contain the given row");
}
removeRow(index);
}

/**
* Returns the row at the given index.
*
* @param index
* the index of the row
* @return the row at the index
* @throws IndexOutOfBoundsException
* if {@code index < 0 || index >= getRowCount()}
*/
public ROW getRow(int index) {
return rows.get(index);
}

/**
* Returns the number of rows in this section.
*
* @return the number of rows
*/
public int getRowCount() {
return rows.size();
}

/**
* Adds a cell corresponding to the given column id to this section.
*
* @param columnId
* the id of the column for which to add a cell
*/
public void addColumn(String columnId) {
for (ROW row : rows) {
row.addCell(columnId);
}
}

/**
* Removes the cell corresponding to the given column id.
*
* @param columnId
* the id of the column whose cell to remove
*/
public void removeColumn(String columnId) {
for (ROW row : rows) {
row.removeCell(columnId);
}
}
}

+ 155
- 0
server/src/test/java/com/vaadin/tests/server/component/grid/GridHeaderFooterTest.java ファイルの表示

@@ -0,0 +1,155 @@
/*
* 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.assertSame;
import static org.junit.Assert.fail;

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 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
public void appendHeaderRow_addedToBottom() {
HeaderRow defaultRow = grid.getHeaderRow(0);
HeaderRow addedRow = grid.appendHeaderRow();

assertSame(defaultRow, grid.getHeaderRow(0));
assertSame(addedRow, grid.getHeaderRow(1));
}

@Test
public void prependHeaderRow_addedToTop() {
HeaderRow defaultRow = grid.getHeaderRow(0);
HeaderRow addedRow = grid.prependHeaderRow();

assertSame(addedRow, grid.getHeaderRow(0));
assertSame(defaultRow, grid.getHeaderRow(1));
}

@Test
public void addHeaderRowAtZero_addedToTop() {
HeaderRow defaultRow = grid.getHeaderRow(0);
HeaderRow addedRow = grid.addHeaderRowAt(0);

assertSame(addedRow, grid.getHeaderRow(0));
assertSame(defaultRow, grid.getHeaderRow(1));
}

@Test
public void addHeaderRowAtRowCount_addedToBottom() {
HeaderRow defaultRow = grid.getHeaderRow(0);
HeaderRow addedRow = grid.addHeaderRowAt(grid.getHeaderRowCount());

assertSame(defaultRow, grid.getHeaderRow(0));
assertSame(addedRow, grid.getHeaderRow(1));
}

@Test
public void removeExistingHeaderRow_removed() {
HeaderRow defaultRow = grid.getHeaderRow(0);
HeaderRow addedRow = grid.appendHeaderRow();

grid.removeHeaderRow(addedRow);

assertEquals(1, grid.getHeaderRowCount());
assertSame(defaultRow, grid.getHeaderRow(0));
}

@Test
public void removeDefaultHeaderRow_removed() {
HeaderRow defaultRow = grid.getHeaderRow(0);
HeaderRow addedRow = grid.appendHeaderRow();

grid.removeHeaderRow(defaultRow);

assertEquals(1, grid.getHeaderRowCount());
assertSame(addedRow, grid.getHeaderRow(0));
}

@Test(expected = IndexOutOfBoundsException.class)
public void getHeaderRowNegativeIndex_throws() {
grid.getHeaderRow(-1);
}

@Test(expected = IndexOutOfBoundsException.class)
public void getHeaderRowIndexTooLarge_throws() {
grid.appendHeaderRow();
grid.getHeaderRow(2);
}

@Test(expected = IndexOutOfBoundsException.class)
public void addHeaderRowAtNegativeIndex_throws() {
grid.addHeaderRowAt(-1);
}

@Test(expected = IndexOutOfBoundsException.class)
public void addHeaderRowAtIndexTooLarge_throws() {
grid.addHeaderRowAt(2);
}

@Test(expected = IndexOutOfBoundsException.class)
public void removeHeaderRowNegativeIndex_throws() {
grid.removeHeaderRow(-1);
}

@Test(expected = IndexOutOfBoundsException.class)
public void removeHeaderRowIndexTooLarge_throws() {
grid.removeHeaderRow(1);
}

@Test(expected = IllegalArgumentException.class)
public void removeNonExistingHeaderRow_throws() {
HeaderRow row = grid.getHeaderRow(0);
try {
grid.removeHeaderRow(row);
} catch (Exception e) {
fail("unexpected exception: " + e);
}
grid.removeHeaderRow(row);
}
}

+ 3
- 0
shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java ファイルの表示

@@ -99,6 +99,9 @@ public class GridState extends AbstractSingleSelectState {
primaryStyleName = "v-grid";
}

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

/**
* Column order in grid.
*/

+ 57
- 0
shared/src/main/java/com/vaadin/shared/ui/grid/SectionState.java ファイルの表示

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

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Shared state for Grid headers and footers.
*
* @author Vaadin Ltd
* @since 7.4
*/
public class SectionState implements Serializable {

/** The state of a header or footer row. */
public static class RowState implements Serializable {

/** The map from column ids to the cells in this row. */
public Map<String, CellState> cells = new HashMap<>();

/**
* Whether this row is the default header row. Always false for footer
* rows.
*/
public boolean defaultHeader = false;
}

/** The state of a header or footer cell. */
public static class CellState implements Serializable {

/** The textual caption of this cell. */
public String text;

/** The id of the column that this cell belongs to. */
public String columnId;
}

/** The rows in this section. */
public List<RowState> rows = new ArrayList<>();
}

+ 2
- 0
uitest/src/main/java/com/vaadin/tests/components/grid/GridColumnResizing.java ファイルの表示

@@ -2,6 +2,7 @@ package com.vaadin.tests.components.grid;

import java.util.Arrays;

import com.vaadin.annotations.Widgetset;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractTestUI;
import com.vaadin.tests.data.bean.Person;
@@ -11,6 +12,7 @@ import com.vaadin.ui.Label;
import com.vaadin.ui.TextField;
import com.vaadin.ui.renderers.NumberRenderer;

@Widgetset("com.vaadin.DefaultWidgetSet")
public class GridColumnResizing extends AbstractTestUI {

@Override

+ 23
- 8
uitest/src/main/java/com/vaadin/tests/components/grid/basics/GridBasics.java ファイルの表示

@@ -33,6 +33,8 @@ 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";
@@ -128,21 +130,21 @@ public class GridBasics extends AbstractTestUIWithLog {
grid = new Grid<>();
grid.setItems(data);

grid.addColumn("Column 0",
grid.addColumn(COLUMN_CAPTIONS[0],
dataObj -> "(" + dataObj.getRowNumber() + ", 0)");
grid.addColumn("Column 1",
grid.addColumn(COLUMN_CAPTIONS[1],
dataObj -> "(" + dataObj.getRowNumber() + ", 1)");
grid.addColumn("Column 2",
grid.addColumn(COLUMN_CAPTIONS[2],
dataObj -> "(" + dataObj.getRowNumber() + ", 2)");

grid.addColumn("Row Number", DataObject::getRowNumber,
grid.addColumn(COLUMN_CAPTIONS[3], DataObject::getRowNumber,
new NumberRenderer());
grid.addColumn("Date", DataObject::getDate, new DateRenderer());
grid.addColumn("HTML String", DataObject::getHtmlString,
grid.addColumn(COLUMN_CAPTIONS[4], DataObject::getDate, new DateRenderer());
grid.addColumn(COLUMN_CAPTIONS[5], DataObject::getHtmlString,
new HtmlRenderer());
grid.addColumn("Big Random", DataObject::getBigRandom,
grid.addColumn(COLUMN_CAPTIONS[6], DataObject::getBigRandom,
new NumberRenderer());
grid.addColumn("Small Random", data -> data.getSmallRandom() / 5d,
grid.addColumn(COLUMN_CAPTIONS[7], data -> data.getSmallRandom() / 5d,
new ProgressBarRenderer());

grid.addSelectionListener(e -> log("Selected: " + e.getValue()));
@@ -159,6 +161,7 @@ public class GridBasics extends AbstractTestUIWithLog {
createSizeMenu(componentMenu.addItem("Size", null));
createDetailsMenu(componentMenu.addItem("Details", null));
createBodyMenu(componentMenu.addItem("Body rows", null));
createHeaderMenu(componentMenu.addItem("Header", null));
return menu;
}

@@ -293,6 +296,18 @@ public class GridBasics extends AbstractTestUIWithLog {
});
}

private void createHeaderMenu(MenuItem headerMenu) {
headerMenu.addItem("Append header row", menuItem -> {
grid.appendHeaderRow();
});
headerMenu.addItem("Prepend header row", menuItem -> {
grid.prependHeaderRow();
});
headerMenu.addItem("Remove first header row", menuItem -> {
grid.removeHeaderRow(0);
});
}

/* DetailsGenerator related things */

private void createDetailsMenu(MenuItem detailsMenu) {

+ 69
- 0
uitest/src/test/java/com/vaadin/tests/components/grid/basics/GridHeaderFooterTest.java ファイルの表示

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

import static org.junit.Assert.assertEquals;

import java.util.List;

import org.junit.Test;

import com.vaadin.testbench.By;
import com.vaadin.testbench.elements.GridElement.GridCellElement;

public class GridHeaderFooterTest extends GridBasicsTest {

@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));
}
}

@Test
public void appendHeaderRow_addedToBottom() {
selectMenuPath("Component", "Header", "Append header row");

assertEquals(2, getGridElement().getHeaderCount());
}

@Test
public void prependHeaderRow_addedToBottom() {
selectMenuPath("Component", "Header", "Prepend header row");

assertEquals(2, getGridElement().getHeaderCount());
}

@Test
public void removeDefaultHeaderRow_noHeaderRows() {
selectMenuPath("Component", "Header", "Remove first header row");

assertEquals(0, getGridElement().getHeaderCount());
}

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);
}
}

読み込み中…
キャンセル
保存