Skip to content

Commit

Permalink
Initial support for multiple headers in new Grid
Browse files Browse the repository at this point in the history
Change-Id: I7a3fa34749322451ab5cef4465d4d7c76029c097
  • Loading branch information
jdahlstrom authored and Vaadin Code Review committed Sep 27, 2016
1 parent 211dd53 commit 680b700
Show file tree
Hide file tree
Showing 10 changed files with 925 additions and 18 deletions.
Expand Up @@ -34,6 +34,7 @@
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;
Expand All @@ -49,6 +50,7 @@
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;
Expand All @@ -59,6 +61,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.SectionState;
import com.vaadin.shared.ui.grid.SectionState.RowState;

import elemental.json.JsonObject;

Expand Down Expand Up @@ -102,23 +106,36 @@ private void fireItemClick(CellReference<?> cell,

/* 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;
private ClickSelectHandler<JsonObject> clickSelectHandler;
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() {
Expand Down Expand Up @@ -202,6 +219,28 @@ public boolean isSelected(JsonObject item) {
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);
Expand All @@ -228,6 +267,7 @@ public void addColumn(Column<?, JsonObject> column, String id) {
.containsValue(id) : "Column with given id already exists.";
getWidget().addColumn(column);
columnToIdMap.put(column, id);
idToColumn.put(id, column);
}

/**
Expand All @@ -241,7 +281,8 @@ public void removeColumn(Column<?, JsonObject> column) {
assert columnToIdMap
.containsKey(column) : "Given Column does not exist.";
getWidget().removeColumn(column);
columnToIdMap.remove(column);
String id = columnToIdMap.remove(column);
idToColumn.remove(id);
}

@Override
Expand Down
211 changes: 206 additions & 5 deletions server/src/main/java/com/vaadin/ui/Grid.java
Expand Up @@ -49,6 +49,8 @@
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;
Expand Down Expand Up @@ -512,7 +514,7 @@ public void contextClick(int rowIndex, String rowKey, String columnId,
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)));
}

Expand Down Expand Up @@ -824,6 +826,15 @@ private void extend(Grid<T> grid) {
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.
*
Expand Down Expand Up @@ -1408,6 +1419,53 @@ protected void doSetSelectedKey(String key) {
}
}

/**
* 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<>();
Expand All @@ -1416,15 +1474,26 @@ protected void doSetSelectedKey(String key) {
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()) {
Expand Down Expand Up @@ -1455,8 +1524,6 @@ public <V> void fireColumnVisibilityChangeEvent(Column<T, V> column,
* the value provider
* @param renderer
* the column value class
* @param <T>
* the type of this grid
* @param <V>
* the column value type
*
Expand All @@ -1467,13 +1534,23 @@ public <V> void fireColumnVisibilityChangeEvent(Column<T, V> column,
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;
}

Expand Down Expand Up @@ -1762,6 +1839,130 @@ public DescriptionGenerator<T> getDescriptionGenerator() {
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.
*
Expand Down

0 comments on commit 680b700

Please sign in to comment.