/* * 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.util.HashSet; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import org.jsoup.nodes.Element; import com.vaadin.ui.Grid; import com.vaadin.ui.Grid.Column; import com.vaadin.ui.declarative.DesignAttributeHandler; import com.vaadin.ui.declarative.DesignContext; /** * Represents the header section of a Grid. * * @author Vaadin Ltd. * * @since 8.0 */ public abstract class Header extends StaticSection<Header.Row> { /** * A row in a Grid header. */ public class Row extends StaticSection.StaticRow<Row.Cell> implements HeaderRow { /** * A cell in a Grid header row. */ public class Cell extends StaticSection.StaticCell implements HeaderCell { /** * Creates a new header cell. */ protected Cell() { super(Row.this); } @Override public void setText(String text) { super.setText(text); if (isDefault()) { Column<?, ?> col = getColumnByInternalId(getColumnId()); if (col != null) { col.setCaption(text); } } } } /** * Creates a new header row. */ protected Row() { super(Header.this); } @Override protected Cell createCell() { return new Cell(); } @Override protected String getCellTagName() { return "th"; } /** * Returns whether this row is the default header row. * * @return {@code true} if this row is the default row, {@code false} * otherwise. */ protected boolean isDefault() { return getRowState().defaultHeader; } /** * Sets whether this row is the default header row. * * @param defaultHeader * {@code true} to set to default, {@code false} otherwise. */ protected void setDefault(boolean defaultHeader) { getRowState().defaultHeader = defaultHeader; } /** * Merges column cells in the row. Original cells are hidden, and new * merged cell is shown instead. The cell has a width of all merged * cells together, inherits styles of the first merged cell but has * empty caption. * * @param cellsToMerge * the cells which should be merged. The cells should not be * merged to any other cell set. * @return the remaining visible cell after the merge * * @see #join(HeaderCell...) * @see com.vaadin.ui.AbstractComponent#setCaption(String) setCaption */ @Override public HeaderCell join(Set<HeaderCell> cellsToMerge) { for (HeaderCell cell : cellsToMerge) { checkIfAlreadyMerged(cell.getColumnId()); } // Create new cell data for the group Cell newCell = createCell(); Set<String> columnGroup = new HashSet<>(); for (HeaderCell cell : cellsToMerge) { columnGroup.add(cell.getColumnId()); } addMergedCell(newCell, columnGroup); markAsDirty(); return newCell; } /** * Merges column cells in the row. Original cells are hidden, and new * merged cell is shown instead. The cell has a width of all merged * cells together, inherits styles of the first merged cell but has * empty caption. * * @param cellsToMerge * the cells which should be merged. The cells should not be * merged to any other cell set. * @return the remaining visible cell after the merge * * @see #join(Set) * @see com.vaadin.ui.AbstractComponent#setCaption(String) setCaption */ @Override public HeaderCell join(HeaderCell... cellsToMerge) { return join(Stream.of(cellsToMerge)); } private HeaderCell join(Stream<HeaderCell> cellStream) { return join(cellStream.collect(Collectors.toSet())); } @Override public HeaderCell join(Column<?, ?>... columnsToMerge) { return join(Stream.of(columnsToMerge).map(this::getCell)); } @Override public HeaderCell join(String... columnIdsToMerge) { Grid<?> grid = getGrid(); return join(Stream.of(columnIdsToMerge).map(columnId -> { Column<?, ?> column = grid.getColumn(columnId); if (column == null) { throw new IllegalStateException( "There is no column with the id " + columnId); } return getCell(column); })); } @Override protected void readDesign(Element trElement, DesignContext designContext) { super.readDesign(trElement, designContext); boolean defaultRow = DesignAttributeHandler.readAttribute("default", trElement.attributes(), false, boolean.class); if (defaultRow) { setDefault(true); } } @Override protected void writeDesign(Element trElement, DesignContext designContext) { super.writeDesign(trElement, designContext); if (isDefault()) { DesignAttributeHandler.writeAttribute("default", trElement.attributes(), true, null, boolean.class, designContext); } } } @Override public Row createRow() { return new Row(); } @Override public void removeRow(int index) { if (getRow(index).isDefault()) { setDefaultRow(null); } super.removeRow(index); } /** * Returns the default row of this header. The default row displays column * captions and sort indicators. * * @return the default row, or {@code null} if there is no default row */ public Row getDefaultRow() { return getRows().stream().filter(Row::isDefault).findAny().orElse(null); } /** * Sets the default row of this header. The default row displays column * captions and sort indicators. * * @param defaultRow * the new default row, or null for no default row * * @throws IllegalArgumentException * if the header does not contain the row */ public void setDefaultRow(Row defaultRow) { if (defaultRow != null) { if (!getRows().contains(defaultRow)) { throw new IllegalArgumentException( "The section does not contain the row"); } if (defaultRow.isDefault()) { return; } } getRows().forEach(row -> row.setDefault(row == defaultRow)); markAsDirty(); } }