/* * 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.v7.tests.components.grid.basicfeatures; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Random; import com.vaadin.annotations.Theme; import com.vaadin.shared.data.sort.SortDirection; import com.vaadin.tests.components.AbstractComponentTest; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.Component; import com.vaadin.ui.CssLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Notification; import com.vaadin.ui.Panel; import com.vaadin.v7.data.Container.Filter; import com.vaadin.v7.data.Item; import com.vaadin.v7.data.Property; import com.vaadin.v7.data.Property.ValueChangeEvent; import com.vaadin.v7.data.Property.ValueChangeListener; import com.vaadin.v7.data.fieldgroup.FieldGroup.CommitException; import com.vaadin.v7.data.sort.Sort; import com.vaadin.v7.data.sort.SortOrder; import com.vaadin.v7.data.util.IndexedContainer; import com.vaadin.v7.event.ItemClickEvent; import com.vaadin.v7.event.ItemClickEvent.ItemClickListener; import com.vaadin.v7.event.SelectionEvent; import com.vaadin.v7.event.SelectionEvent.SelectionListener; import com.vaadin.v7.event.SortEvent; import com.vaadin.v7.shared.ui.grid.ColumnResizeMode; import com.vaadin.v7.shared.ui.grid.GridStaticCellType; import com.vaadin.v7.shared.ui.grid.HeightMode; import com.vaadin.v7.ui.Field; import com.vaadin.v7.ui.Grid; import com.vaadin.v7.ui.Grid.CellDescriptionGenerator; import com.vaadin.v7.ui.Grid.CellReference; import com.vaadin.v7.ui.Grid.CellStyleGenerator; import com.vaadin.v7.ui.Grid.Column; import com.vaadin.v7.ui.Grid.ColumnReorderEvent; import com.vaadin.v7.ui.Grid.ColumnReorderListener; import com.vaadin.v7.ui.Grid.ColumnResizeEvent; import com.vaadin.v7.ui.Grid.ColumnResizeListener; import com.vaadin.v7.ui.Grid.ColumnVisibilityChangeEvent; import com.vaadin.v7.ui.Grid.ColumnVisibilityChangeListener; import com.vaadin.v7.ui.Grid.DetailsGenerator; import com.vaadin.v7.ui.Grid.FooterCell; import com.vaadin.v7.ui.Grid.HeaderCell; import com.vaadin.v7.ui.Grid.HeaderRow; import com.vaadin.v7.ui.Grid.MultiSelectionModel; import com.vaadin.v7.ui.Grid.RowDescriptionGenerator; import com.vaadin.v7.ui.Grid.RowReference; import com.vaadin.v7.ui.Grid.RowStyleGenerator; import com.vaadin.v7.ui.Grid.SelectionMode; import com.vaadin.v7.ui.Grid.SelectionModel; import com.vaadin.v7.ui.renderers.DateRenderer; import com.vaadin.v7.ui.renderers.HtmlRenderer; import com.vaadin.v7.ui.renderers.NumberRenderer; /** * Tests the basic features like columns, footers and headers * * @since * @author Vaadin Ltd */ @Theme("valo") public class GridBasicFeatures extends AbstractComponentTest<Grid> { 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"; public static final String ROW_STYLE_GENERATOR_EMPTY = "Empty string"; public static final String ROW_STYLE_GENERATOR_NULL = "Null"; public static final String CELL_STYLE_GENERATOR_NONE = "None"; public static final String CELL_STYLE_GENERATOR_PROPERTY_TO_STRING = "Property to string"; public static final String CELL_STYLE_GENERATOR_SPECIAL = "Special for 1/4 Column 1"; public static final String CELL_STYLE_GENERATOR_EMPTY = "Empty string"; public static final String CELL_STYLE_GENERATOR_NULL = "Null"; private static final int MANUALLY_FORMATTED_COLUMNS = 5; public static final int COLUMNS = 12; public static final int EDITABLE_COLUMNS = COLUMNS - 1; public static final int ROWS = 1000; private int containerDelay = 0; private boolean singleSelectAllowDeselect = true; private IndexedContainer ds; private Grid grid; private SelectionListener selectionListener = new SelectionListener() { @Override public void select(SelectionEvent event) { Iterator<Object> iter = event.getAdded().iterator(); Object addedRow = iter.hasNext() ? iter.next() : "none"; iter = event.getRemoved().iterator(); Object removedRow = iter.hasNext() ? iter.next() : "none"; log("SelectionEvent: Added " + addedRow + ", Removed " + removedRow); } }; private ItemClickListener itemClickListener = new ItemClickListener() { @Override public void itemClick(ItemClickEvent event) { log("Item " + (event.isDoubleClick() ? "double " : "") + "click on " + event.getPropertyId() + ", item " + event.getItemId()); } }; private RowDescriptionGenerator rowDescriptionGenerator = new RowDescriptionGenerator() { @Override public String getDescription(RowReference row) { return "Row tooltip for row " + row.getItemId(); } }; private CellDescriptionGenerator cellDescriptionGenerator = new CellDescriptionGenerator() { @Override public String getDescription(CellReference cell) { if ("Column 0".equals(cell.getPropertyId())) { return "Cell tooltip for row " + cell.getItemId() + ", column 0"; } else { return null; } } }; private ItemClickListener editorOpeningItemClickListener = new ItemClickListener() { @Override public void itemClick(ItemClickEvent event) { grid.editItem(event.getItemId()); } }; private ValueChangeListener reactiveValueChanger = new ValueChangeListener() { @Override @SuppressWarnings("unchecked") public void valueChange(ValueChangeEvent event) { Object id = grid.getEditedItemId(); grid.getContainerDataSource().getContainerProperty(id, "Column 2") .setValue("Modified"); } }; private ColumnReorderListener columnReorderListener = new ColumnReorderListener() { @Override public void columnReorder(ColumnReorderEvent event) { log("Columns reordered, userOriginated: " + event.isUserOriginated()); } }; private ColumnVisibilityChangeListener columnVisibilityListener = new ColumnVisibilityChangeListener() { @Override public void columnVisibilityChanged(ColumnVisibilityChangeEvent event) { log("Visibility changed: "// + "propertyId: " + event.getColumn().getPropertyId() // + ", isHidden: " + event.getColumn().isHidden() // + ", userOriginated: " + event.isUserOriginated()); } }; private final DetailsGenerator detailedDetailsGenerator = new DetailsGenerator() { @Override public Component getDetails(final RowReference rowReference) { CssLayout cssLayout = new CssLayout(); cssLayout.setHeight("200px"); cssLayout.setWidth("100%"); Item item = rowReference.getItem(); for (Object propertyId : item.getItemPropertyIds()) { Property<?> prop = item.getItemProperty(propertyId); String string = prop.getValue().toString(); cssLayout.addComponent(new Label(string)); } final int rowIndex = grid.getContainerDataSource() .indexOfId(rowReference.getItemId()); ClickListener clickListener = new ClickListener() { @Override public void buttonClick(ClickEvent event) { Notification.show("You clicked on the " + "button in the details for " + "row " + rowIndex); } }; cssLayout.addComponent(new Button("Press me", clickListener)); return cssLayout; } }; private final DetailsGenerator watchingDetailsGenerator = new DetailsGenerator() { private int id = 0; @Override public Component getDetails(RowReference rowReference) { return new Label("You are watching item id " + rowReference.getItemId() + " (" + id++ + ")"); } }; private Map<Object, Panel> detailsMap = new HashMap<>(); private final DetailsGenerator persistingDetailsGenerator = new DetailsGenerator() { @Override public Component getDetails(RowReference rowReference) { Object itemId = rowReference.getItemId(); if (!detailsMap.containsKey(itemId)) { Panel panel = new Panel(); panel.setContent(new Label("One")); detailsMap.put(itemId, panel); } return detailsMap.get(itemId); } }; @Override @SuppressWarnings("unchecked") protected Grid constructComponent() { // Build data source ds = new IndexedContainer() { @Override public List<Object> getItemIds(int startIndex, int numberOfIds) { log("Requested items " + startIndex + " - " + (startIndex + numberOfIds)); if (containerDelay > 0) { try { Thread.sleep(containerDelay); } catch (InterruptedException e) { e.printStackTrace(); } } return super.getItemIds(startIndex, numberOfIds); } }; { int col = 0; for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; col++) { ds.addContainerProperty(getColumnProperty(col), String.class, ""); } ds.addContainerProperty(getColumnProperty(col++), Integer.class, Integer.valueOf(0)); ds.addContainerProperty(getColumnProperty(col++), Date.class, new Date()); ds.addContainerProperty(getColumnProperty(col++), String.class, ""); // Random numbers ds.addContainerProperty(getColumnProperty(col++), Integer.class, 0); ds.addContainerProperty(getColumnProperty(col++), Integer.class, 0); } { Random rand = new Random(); rand.setSeed(13334); long timestamp = 0; for (int row = 0; row < ROWS; row++) { Item item = ds.addItem(Integer.valueOf(row)); int col = 0; for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; col++) { item.getItemProperty(getColumnProperty(col)) .setValue("(" + row + ", " + col + ")"); } item.getItemProperty(getColumnProperty(1)).setReadOnly(true); item.getItemProperty(getColumnProperty(col++)) .setValue(Integer.valueOf(row)); item.getItemProperty(getColumnProperty(col++)) .setValue(new Date(timestamp)); timestamp += 91250000; // a bit over a day, just to get // variation item.getItemProperty(getColumnProperty(col++)) .setValue("<b>" + row + "</b>"); // Random numbers item.getItemProperty(getColumnProperty(col++)) .setValue(rand.nextInt()); // Random between 0 - 5 to test multisorting item.getItemProperty(getColumnProperty(col++)) .setValue(rand.nextInt(5)); } } // Create grid Grid grid = new Grid(ds); { int col = grid.getContainerDataSource().getContainerPropertyIds() .size() - MANUALLY_FORMATTED_COLUMNS; grid.getColumn(getColumnProperty(col++)) .setRenderer(new NumberRenderer( new DecimalFormat("0,000.00", DecimalFormatSymbols .getInstance(new Locale("fi", "FI"))))); grid.getColumn(getColumnProperty(col++)).setRenderer( new DateRenderer(new SimpleDateFormat("dd.MM.yy HH:mm"))); grid.getColumn(getColumnProperty(col++)) .setRenderer(new HtmlRenderer()); grid.getColumn(getColumnProperty(col++)) .setRenderer(new NumberRenderer()); grid.getColumn(getColumnProperty(col++)) .setRenderer(new NumberRenderer()); } // Create footer grid.appendFooterRow(); grid.setFooterVisible(false); // Add footer values (header values are automatically created) for (int col = 0; col < COLUMNS; col++) { grid.getFooterRow(0).getCell(getColumnProperty(col)) .setText("Footer " + col); } // Set varying column widths for (int col = 0; col < COLUMNS; col++) { Column column = grid.getColumn(getColumnProperty(col)); column.setWidth(100 + col * 50); column.setHidable(isColumnHidableByDefault(col)); } grid.addSortListener(new SortEvent.SortListener() { @Override public void sort(SortEvent event) { log("SortEvent: isUserOriginated? " + event.isUserOriginated()); } }); grid.addColumnResizeListener(new ColumnResizeListener() { @Override public void columnResize(ColumnResizeEvent event) { log("ColumnResizeEvent: isUserOriginated? " + event.isUserOriginated()); } }); grid.setSelectionMode(SelectionMode.NONE); grid.getColumn(getColumnProperty(2)).getEditorField().setReadOnly(true); grid.getColumn(getColumnProperty(3)).setEditable(false); createGridActions(); createColumnActions(); createPropertyActions(); createHeaderActions(); createFooterActions(); createRowActions(); createEditorActions(); addHeightActions(); addFilterActions(); addInternalActions(); createDetailsActions(); this.grid = grid; return grid; } protected boolean isColumnHidableByDefault(int col) { return false; } protected boolean isColumnHiddenByDefault(int col) { return false; } private void addInternalActions() { createClickAction("Update column order without updating client", "Internals", new Command<Grid, Void>() { @Override public void execute(Grid grid, Void value, Object data) { List<Column> columns = grid.getColumns(); grid.setColumnOrder(columns.get(1).getPropertyId(), columns.get(0).getPropertyId()); grid.getUI().getConnectorTracker().markClean(grid); } }, null); } private void addFilterActions() { createBooleanAction("Column 1 starts with \"(23\"", "Filter", false, new Command<Grid, Boolean>() { Filter filter = new Filter() { @Override public boolean passesFilter(Object itemId, Item item) { return item.getItemProperty("Column 1").getValue() .toString().startsWith("(23"); } @Override public boolean appliesToProperty(Object propertyId) { return propertyId.equals("Column 1"); } }; @Override public void execute(Grid grid, Boolean value, Object data) { if (value) { ds.addContainerFilter(filter); } else { ds.removeContainerFilter(filter); } } }); createBooleanAction("Impassable filter", "Filter", false, new Command<Grid, Boolean>() { Filter filter = new Filter() { @Override public boolean passesFilter(Object itemId, Item item) { return false; } @Override public boolean appliesToProperty(Object propertyId) { return true; } }; @Override public void execute(Grid c, Boolean value, Object data) { if (value) { ds.addContainerFilter(filter); } else { ds.removeContainerFilter(filter); } } }); } protected void createGridActions() { LinkedHashMap<String, String> primaryStyleNames = new LinkedHashMap<>(); primaryStyleNames.put("v-grid", "v-grid"); primaryStyleNames.put("v-escalator", "v-escalator"); primaryStyleNames.put("my-grid", "my-grid"); createMultiClickAction("Primary style name", "State", primaryStyleNames, new Command<Grid, String>() { @Override public void execute(Grid grid, String value, Object data) { grid.setPrimaryStyleName(value); } }, primaryStyleNames.get("v-grid")); LinkedHashMap<String, SelectionMode> selectionModes = new LinkedHashMap<>(); selectionModes.put("single", SelectionMode.SINGLE); selectionModes.put("multi", SelectionMode.MULTI); selectionModes.put("none", SelectionMode.NONE); createSelectAction("Selection mode", "State", selectionModes, "none", new Command<Grid, Grid.SelectionMode>() { @Override public void execute(Grid grid, SelectionMode selectionMode, Object data) { grid.setSelectionMode(selectionMode); if (selectionMode == SelectionMode.SINGLE) { grid.addSelectionListener(selectionListener); ((SelectionModel.Single) grid.getSelectionModel()) .setDeselectAllowed( singleSelectAllowDeselect); } else { grid.removeSelectionListener(selectionListener); } } }); LinkedHashMap<String, Integer> selectionLimits = new LinkedHashMap<>(); selectionLimits.put("2", Integer.valueOf(2)); selectionLimits.put("1000", Integer.valueOf(1000)); selectionLimits.put("Integer.MAX_VALUE", Integer.valueOf(Integer.MAX_VALUE)); createSelectAction("Selection limit", "State", selectionLimits, "1000", new Command<Grid, Integer>() { @Override public void execute(Grid grid, Integer limit, Object data) { if (!(grid .getSelectionModel() instanceof MultiSelectionModel)) { grid.setSelectionMode(SelectionMode.MULTI); } ((MultiSelectionModel) grid.getSelectionModel()) .setSelectionLimit(limit.intValue()); } }); LinkedHashMap<String, List<SortOrder>> sortableProperties = new LinkedHashMap<>(); for (Object propertyId : ds.getSortableContainerPropertyIds()) { sortableProperties.put(propertyId + ", ASC", Sort.by(propertyId).build()); sortableProperties.put(propertyId + ", DESC", Sort.by(propertyId, SortDirection.DESCENDING).build()); } createSelectAction("Sort by column", "State", sortableProperties, "Column 9, ascending", new Command<Grid, List<SortOrder>>() { @Override public void execute(Grid grid, List<SortOrder> sortOrder, Object data) { grid.setSortOrder(sortOrder); } }); createBooleanAction("Reverse Grid Columns", "State", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { List<Object> ids = new ArrayList<>(); ids.addAll(ds.getContainerPropertyIds()); if (!value) { c.setColumnOrder(ids.toArray()); } else { Object[] idsArray = new Object[ids.size()]; for (int i = 0; i < ids.size(); ++i) { idsArray[i] = ids.get(ids.size() - 1 - i); } c.setColumnOrder(idsArray); } } }); LinkedHashMap<String, CellStyleGenerator> cellStyleGenerators = new LinkedHashMap<>(); LinkedHashMap<String, RowStyleGenerator> rowStyleGenerators = new LinkedHashMap<>(); rowStyleGenerators.put(ROW_STYLE_GENERATOR_NONE, null); rowStyleGenerators.put(ROW_STYLE_GENERATOR_ROW_NUMBERS, new RowStyleGenerator() { @Override public String getStyle(RowReference rowReference) { return "row" + rowReference.getItemId(); } }); rowStyleGenerators.put(ROW_STYLE_GENERATOR_ROW_NUMBERS_FOR_3_OF_4, new RowStyleGenerator() { @Override public String getStyle(RowReference rowReference) { int rowIndex = ((Integer) rowReference.getItemId()) .intValue(); if (rowIndex % 4 == 0) { return null; } else { return "row" + rowReference.getItemId(); } } }); rowStyleGenerators.put(ROW_STYLE_GENERATOR_EMPTY, new RowStyleGenerator() { @Override public String getStyle(RowReference rowReference) { return ""; } }); rowStyleGenerators.put(ROW_STYLE_GENERATOR_NULL, new RowStyleGenerator() { @Override public String getStyle(RowReference rowReference) { return null; } }); cellStyleGenerators.put(CELL_STYLE_GENERATOR_NONE, null); cellStyleGenerators.put(CELL_STYLE_GENERATOR_PROPERTY_TO_STRING, new CellStyleGenerator() { @Override public String getStyle(CellReference cellReference) { return cellReference.getPropertyId().toString() .replace(' ', '-'); } }); cellStyleGenerators.put(CELL_STYLE_GENERATOR_SPECIAL, new CellStyleGenerator() { @Override public String getStyle(CellReference cellReference) { int rowIndex = ((Integer) cellReference.getItemId()) .intValue(); Object propertyId = cellReference.getPropertyId(); if (rowIndex % 4 == 1) { return null; } else if (rowIndex % 4 == 3 && "Column 1".equals(propertyId)) { return null; } return propertyId.toString().replace(' ', '_'); } }); cellStyleGenerators.put(CELL_STYLE_GENERATOR_EMPTY, new CellStyleGenerator() { @Override public String getStyle(CellReference cellReference) { return ""; } }); cellStyleGenerators.put(CELL_STYLE_GENERATOR_NULL, new CellStyleGenerator() { @Override public String getStyle(CellReference cellReference) { return null; } }); createSelectAction("Row style generator", "State", rowStyleGenerators, CELL_STYLE_GENERATOR_NONE, new Command<Grid, RowStyleGenerator>() { @Override public void execute(Grid grid, RowStyleGenerator generator, Object data) { grid.setRowStyleGenerator(generator); } }); createSelectAction("Cell style generator", "State", cellStyleGenerators, CELL_STYLE_GENERATOR_NONE, new Command<Grid, CellStyleGenerator>() { @Override public void execute(Grid grid, CellStyleGenerator generator, Object data) { grid.setCellStyleGenerator(generator); } }); createBooleanAction("Row description generator", "State", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { c.setRowDescriptionGenerator( value ? rowDescriptionGenerator : null); } }); createBooleanAction("Cell description generator", "State", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { c.setCellDescriptionGenerator( value ? cellDescriptionGenerator : null); } }); LinkedHashMap<String, Integer> frozenOptions = new LinkedHashMap<>(); for (int i = -1; i <= COLUMNS; i++) { frozenOptions.put(String.valueOf(i), Integer.valueOf(i)); } /* * This line below is a workaround for a FF24 bug regarding submenu * handling - it makes the sub menu wider. */ frozenOptions.put("-1 for unfreezing selection column", -1); createSelectAction("Frozen column count", "State", frozenOptions, "0", new Command<Grid, Integer>() { @Override public void execute(Grid c, Integer value, Object data) { c.setFrozenColumnCount(value.intValue()); } }); LinkedHashMap<String, Integer> containerDelayValues = new LinkedHashMap<>(); for (int delay : new int[] { 0, 500, 2000, 10000 }) { containerDelayValues.put(String.valueOf(delay), Integer.valueOf(delay)); } createSelectAction("Container delay", "State", containerDelayValues, "0", new Command<Grid, Integer>() { @Override public void execute(Grid grid, Integer delay, Object data) { containerDelay = delay.intValue(); } }); createBooleanAction("ItemClickListener", "State", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { if (!value) { c.removeItemClickListener(itemClickListener); } else { c.addItemClickListener(itemClickListener); } } }); createBooleanAction("EditorOpeningItemClickListener", "State", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { if (!value) { c.removeItemClickListener( editorOpeningItemClickListener); } else { c.addItemClickListener( editorOpeningItemClickListener); } } }); createBooleanAction("ReactiveValueChanger", "State", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { Field<?> targetField = grid.getEditorFieldGroup() .getField("Column 0"); if (targetField != null) { if (!value) { targetField.removeValueChangeListener( reactiveValueChanger); } else { targetField.addValueChangeListener( reactiveValueChanger); } } } }); createBooleanAction("ColumnReorderListener", "State", false, new Command<Grid, Boolean>() { @Override public void execute(Grid grid, Boolean value, Object data) { if (value) { grid.addColumnReorderListener( columnReorderListener); } else { grid.removeColumnReorderListener( columnReorderListener); } } }); createBooleanAction("ColumnVisibilityChangeListener", "State", false, new Command<Grid, Boolean>() { @Override public void execute(Grid grid, Boolean value, Object data) { if (value) { grid.addColumnVisibilityChangeListener( columnVisibilityListener); } else { grid.removeColumnVisibilityChangeListener( columnVisibilityListener); } } }); createBooleanAction("Single select allow deselect", "State", singleSelectAllowDeselect, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { singleSelectAllowDeselect = value.booleanValue(); SelectionModel model = c.getSelectionModel(); if (model instanceof SelectionModel.Single) { ((SelectionModel.Single) model).setDeselectAllowed( singleSelectAllowDeselect); } } }); createBooleanAction("Column Reordering Allowed", "State", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { c.setColumnReorderingAllowed(value); } }); createClickAction("Select all", "State", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { SelectionModel selectionModel = c.getSelectionModel(); if (selectionModel instanceof SelectionModel.Multi) { ((SelectionModel.Multi) selectionModel).selectAll(); } } }, null); createClickAction("Select none", "State", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { SelectionModel selectionModel = c.getSelectionModel(); if (selectionModel instanceof SelectionModel.Multi) { ((SelectionModel.Multi) selectionModel).deselectAll(); } } }, null); } protected void createHeaderActions() { createCategory("Header", null); createBooleanAction("Visible", "Header", true, new Command<Grid, Boolean>() { @Override public void execute(Grid grid, Boolean value, Object data) { grid.setHeaderVisible(value); } }); LinkedHashMap<String, String> defaultRows = new LinkedHashMap<>(); 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; if (value.equals("Top")) { defaultRow = grid.getHeaderRow(0); } else if (value.equals("Bottom")) { defaultRow = grid .getHeaderRow(grid.getHeaderRowCount() - 1); } grid.setDefaultHeaderRow(defaultRow); } }, defaultRows.get("Top")); createClickAction("Prepend row", "Header", new Command<Grid, Object>() { @Override public void execute(Grid grid, Object value, Object data) { grid.prependHeaderRow(); } }, null); createClickAction("Append row", "Header", new Command<Grid, Object>() { @Override public void execute(Grid grid, Object value, Object data) { grid.appendHeaderRow(); } }, null); createClickAction("Remove top row", "Header", new Command<Grid, Object>() { @Override public void execute(Grid grid, Object value, Object data) { grid.removeHeaderRow(0); } }, null); createClickAction("Remove bottom row", "Header", new Command<Grid, Object>() { @Override public void execute(Grid grid, Object value, Object data) { grid.removeHeaderRow(grid.getHeaderRowCount() - 1); } }, null); } protected void createFooterActions() { createCategory("Footer", null); createBooleanAction("Visible", "Footer", false, new Command<Grid, Boolean>() { @Override public void execute(Grid grid, Boolean value, Object data) { grid.setFooterVisible(value); } }); createClickAction("Prepend row", "Footer", new Command<Grid, Object>() { @Override public void execute(Grid grid, Object value, Object data) { grid.prependFooterRow(); } }, null); createClickAction("Append row", "Footer", new Command<Grid, Object>() { @Override public void execute(Grid grid, Object value, Object data) { grid.appendFooterRow(); } }, null); createClickAction("Remove top row", "Footer", new Command<Grid, Object>() { @Override public void execute(Grid grid, Object value, Object data) { grid.removeFooterRow(0); } }, null); createClickAction("Remove bottom row", "Footer", new Command<Grid, Object>() { @Override public void execute(Grid grid, Object value, Object data) { grid.removeFooterRow(grid.getFooterRowCount() - 1); } }, null); } @SuppressWarnings("boxing") protected void createColumnActions() { createCategory("Columns", null); for (int c = 0; c < COLUMNS; c++) { final int index = c; createCategory(getColumnProperty(c), "Columns"); createClickAction("Add / Remove", getColumnProperty(c), new Command<Grid, String>() { boolean wasHidable; boolean wasHidden; String wasColumnHidingToggleCaption; @Override public void execute(Grid grid, String value, Object data) { String columnProperty = getColumnProperty( (Integer) data); Column column = grid.getColumn(columnProperty); if (column == null) { column = grid.addColumn(columnProperty); column.setHidable(wasHidable); column.setHidden(wasHidden); column.setHidingToggleCaption( wasColumnHidingToggleCaption); } else { wasHidable = column.isHidable(); wasHidden = column.isHidden(); wasColumnHidingToggleCaption = column .getHidingToggleCaption(); grid.removeColumn(columnProperty); } } }, null, c); createClickAction("Move left", getColumnProperty(c), new Command<Grid, String>() { @Override public void execute(Grid grid, String value, Object data) { final String columnProperty = getColumnProperty( (Integer) data); List<Column> cols = grid.getColumns(); List<Object> reordered = new ArrayList<>(); boolean addAsLast = false; for (int i = 0; i < cols.size(); i++) { Column col = cols.get(i); if (col.getPropertyId() .equals(columnProperty)) { if (i == 0) { addAsLast = true; } else { reordered.add(i - 1, columnProperty); } } else { reordered.add(col.getPropertyId()); } } if (addAsLast) { reordered.add(columnProperty); } grid.setColumnOrder(reordered.toArray()); } }, null, c); createBooleanAction("Sortable", getColumnProperty(c), true, new Command<Grid, Boolean>() { @Override public void execute(Grid grid, Boolean value, Object columnIndex) { Object propertyId = getColumnProperty( (Integer) columnIndex); Column column = grid.getColumn(propertyId); column.setSortable(value); } }, c); createBooleanAction("Resizable", getColumnProperty(c), true, new Command<Grid, Boolean>() { @Override public void execute(Grid grid, Boolean value, Object columnIndex) { Object propertyId = getColumnProperty( (Integer) columnIndex); Column column = grid.getColumn(propertyId); column.setResizable(value); } }, c); createBooleanAction("Hidable", getColumnProperty(c), isColumnHidableByDefault(c), new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean hidable, Object propertyId) { grid.getColumn(propertyId).setHidable(hidable); } }, getColumnProperty(c)); createBooleanAction("Hidden", getColumnProperty(c), isColumnHiddenByDefault(c), new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean hidden, Object propertyId) { grid.getColumn(propertyId).setHidden(hidden); } }, getColumnProperty(c)); createClickAction("Change hiding toggle caption", getColumnProperty(c), new Command<Grid, String>() { int count = 0; @Override public void execute(Grid grid, String value, Object data) { final String columnProperty = getColumnProperty( (Integer) data); grid.getColumn(columnProperty) .setHidingToggleCaption(columnProperty + " caption " + count++); } }, null, c); createClickAction("Change header caption", getColumnProperty(c), new Command<Grid, String>() { int count = 0; @Override public void execute(Grid grid, String value, Object data) { final String columnProperty = getColumnProperty( (Integer) data); grid.getColumn(columnProperty).setHeaderCaption( columnProperty + " header " + count++); } }, null, c); createCategory("Column " + c + " Width", getColumnProperty(c)); createClickAction("Auto", "Column " + c + " Width", new Command<Grid, Integer>() { @Override public void execute(Grid grid, Integer value, Object columnIndex) { Object propertyId = getColumnProperty( (Integer) columnIndex); Column column = grid.getColumn(propertyId); column.setWidthUndefined(); } }, -1, c); createClickAction("25.5px", "Column " + c + " Width", new Command<Grid, Void>() { @Override public void execute(Grid grid, Void value, Object columnIndex) { grid.getColumns().get((Integer) columnIndex) .setWidth(25.5); } }, null, c); for (int w = 50; w < 300; w += 50) { createClickAction(w + "px", "Column " + c + " Width", new Command<Grid, Integer>() { @Override public void execute(Grid grid, Integer value, Object columnIndex) { Object propertyId = getColumnProperty( (Integer) columnIndex); Column column = grid.getColumn(propertyId); column.setWidth(value); } }, w, c); } LinkedHashMap<String, GridStaticCellType> defaultRows = new LinkedHashMap<>(); defaultRows.put("Text Header", GridStaticCellType.TEXT); defaultRows.put("Html Header ", GridStaticCellType.HTML); defaultRows.put("Widget Header", GridStaticCellType.WIDGET); createMultiClickAction("Header Type", getColumnProperty(c), defaultRows, new Command<Grid, GridStaticCellType>() { @Override public void execute(Grid grid, GridStaticCellType value, Object columnIndex) { final Object propertyId = getColumnProperty( (Integer) columnIndex); final HeaderCell cell = grid.getDefaultHeaderRow() .getCell(propertyId); switch (value) { case TEXT: cell.setText("Text Header"); break; case HTML: cell.setHtml("HTML Header"); break; case WIDGET: cell.setComponent(new Button("Button Header", new ClickListener() { @Override public void buttonClick( ClickEvent event) { log("Button clicked!"); } })); default: break; } } }, c); defaultRows = new LinkedHashMap<>(); defaultRows.put("Text Footer", GridStaticCellType.TEXT); defaultRows.put("Html Footer", GridStaticCellType.HTML); defaultRows.put("Widget Footer", GridStaticCellType.WIDGET); createMultiClickAction("Footer Type", getColumnProperty(c), defaultRows, new Command<Grid, GridStaticCellType>() { @Override public void execute(Grid grid, GridStaticCellType value, Object columnIndex) { final Object propertyId = getColumnProperty( (Integer) columnIndex); final FooterCell cell = grid.getFooterRow(0) .getCell(propertyId); switch (value) { case TEXT: cell.setText("Text Footer"); break; case HTML: cell.setHtml("HTML Footer"); break; case WIDGET: cell.setComponent(new Button("Button Footer", new ClickListener() { @Override public void buttonClick( ClickEvent event) { log("Button clicked!"); } })); default: break; } } }, c); } createClickAction("All columns auto width", "Columns", new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { for (Column col : grid.getColumns()) { col.setWidthUndefined(); } } }, null); createBooleanAction("All columns hidable", "Columns", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { for (Column col : grid.getColumns()) { col.setHidable(value); } } }); createBooleanAction("Toggle all column hidden state", "Columns", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { for (Column col : grid.getColumns()) { col.setHidden(!col.isHidden()); } } }); createBooleanAction("All columns resizable", "Columns", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { for (Column col : grid.getColumns()) { col.setResizable(value); } } }); createClickAction("All columns expanding, Col 0 has max width of 30px", "Columns", new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { for (Column col : grid.getColumns()) { col.setWidthUndefined(); } grid.getColumns().get(0).setMaximumWidth(30); } }, null); createBooleanAction("Simple resize mode", "Columns", false, new Command<Grid, Boolean>() { @Override public void execute(Grid g, Boolean value, Object data) { g.setColumnResizeMode(value ? ColumnResizeMode.SIMPLE : ColumnResizeMode.ANIMATED); } }); } private static String getColumnProperty(int c) { return "Column " + c; } protected void createPropertyActions() { createCategory("Properties", null); createBooleanAction("Prepend property", "Properties", false, new Command<Grid, Boolean>() { private final Object propertyId = new Object(); @Override public void execute(Grid c, Boolean enable, Object data) { if (enable.booleanValue()) { ds.addContainerProperty(propertyId, String.class, "property value"); grid.getColumn(propertyId) .setHeaderCaption("new property"); grid.setColumnOrder(propertyId); } else { ds.removeContainerProperty(propertyId); } } }, null); } protected void createRowActions() { createCategory("Body rows", null); class NewRowCommand implements Command<Grid, String> { private final int index; public NewRowCommand() { this(0); } public NewRowCommand(int index) { this.index = index; } @Override public void execute(Grid c, String value, Object data) { Item item = ds.addItemAt(index, new Object()); for (int i = 0; i < COLUMNS; i++) { Class<?> type = ds.getType(getColumnProperty(i)); if (String.class.isAssignableFrom(type)) { Property<String> itemProperty = getProperty(item, i); itemProperty.setValue("newcell: " + i); } else if (Integer.class.isAssignableFrom(type)) { Property<Integer> itemProperty = getProperty(item, i); itemProperty.setValue(Integer.valueOf(i)); } else { // let the default value be taken implicitly. } } } private <T extends Object> Property<T> getProperty(Item item, int i) { @SuppressWarnings("unchecked") Property<T> itemProperty = item .getItemProperty(getColumnProperty(i)); return itemProperty; } } final NewRowCommand newRowCommand = new NewRowCommand(); createClickAction("Add 18 rows", "Body rows", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { for (int i = 0; i < 18; i++) { newRowCommand.execute(c, value, data); } } }, null); createClickAction("Add first row", "Body rows", newRowCommand, null); createClickAction("Add third row", "Body rows", new NewRowCommand(2), null); createClickAction("Remove first row", "Body rows", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { Object firstItemId = ds.getIdByIndex(0); ds.removeItem(firstItemId); } }, null); createClickAction("Remove 18 first rows", "Body rows", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { for (int i = 0; i < 18; i++) { Object firstItemId = ds.getIdByIndex(0); ds.removeItem(firstItemId); } } }, null); createClickAction("Modify first row (getItemProperty)", "Body rows", new Command<Grid, String>() { @SuppressWarnings("unchecked") @Override public void execute(Grid c, String value, Object data) { Object firstItemId = ds.getIdByIndex(0); Item item = ds.getItem(firstItemId); for (int i = 0; i < COLUMNS; i++) { Property<?> property = item .getItemProperty(getColumnProperty(i)); if (property.getType().equals(String.class)) { ((Property<String>) property) .setValue("modified: " + i); } } } }, null); createClickAction("Modify first row (getContainerProperty)", "Body rows", new Command<Grid, String>() { @SuppressWarnings("unchecked") @Override public void execute(Grid c, String value, Object data) { Object firstItemId = ds.getIdByIndex(0); for (Object containerPropertyId : ds .getContainerPropertyIds()) { Property<?> property = ds.getContainerProperty( firstItemId, containerPropertyId); if (property.getType().equals(String.class)) { ((Property<String>) property).setValue( "modified: " + containerPropertyId); } } } }, null); createBooleanAction("Select first row", "Body rows", false, new Command<Grid, Boolean>() { @Override public void execute(Grid grid, Boolean select, Object data) { final Object firstItemId = grid.getContainerDataSource() .firstItemId(); if (select.booleanValue()) { grid.select(firstItemId); } else { grid.deselect(firstItemId); } } }); createClickAction("Remove all rows", "Body rows", new Command<Grid, String>() { @SuppressWarnings("unchecked") @Override public void execute(Grid c, String value, Object data) { ds.removeAllItems(); } }, null); createClickAction("Remove selected rows", "Body rows", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { // Usually you'd deselect all the rows before removing // them. It is done this way to test for #19152 for (Object itemId : c.getSelectedRows()) { ds.removeItem(itemId); } c.select(null); } }, null); } protected void createEditorActions() { createBooleanAction("Enabled", "Editor", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { c.setEditorEnabled(value); } }); createBooleanAction("Buffered mode", "Editor", true, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean value, Object data) { c.setEditorBuffered(value); } }); createClickAction("Edit item 5", "Editor", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { c.editItem(5); } }, null); createClickAction("Edit item 100", "Editor", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { c.editItem(100); } }, null); createClickAction("Save", "Editor", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { try { c.saveEditor(); } catch (CommitException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, null); createClickAction("Cancel edit", "Editor", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { c.cancelEditor(); } }, null); createClickAction("Change save caption", "Editor", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { c.setEditorSaveCaption("ǝʌɐS"); } }, null); createClickAction("Change cancel caption", "Editor", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { c.setEditorCancelCaption("ʃǝɔuɐↃ"); } }, null); } @SuppressWarnings("boxing") protected void addHeightActions() { createCategory("Height by Rows", "Size"); createBooleanAction("HeightMode Row", "Size", false, new Command<Grid, Boolean>() { @Override public void execute(Grid c, Boolean heightModeByRows, Object data) { c.setHeightMode(heightModeByRows ? HeightMode.ROW : HeightMode.CSS); } }, null); addActionForHeightByRows(1d / 3d); addActionForHeightByRows(2d / 3d); for (double i = 1; i < 5; i++) { addActionForHeightByRows(i); addActionForHeightByRows(i + 1d / 3d); addActionForHeightByRows(i + 2d / 3d); } Command<Grid, String> sizeCommand = new Command<Grid, String>() { @Override public void execute(Grid grid, String height, Object data) { grid.setHeight(height); } }; createCategory("Height", "Size"); // header 20px + scrollbar 16px = 36px baseline createClickAction("86px (no drag scroll select)", "Height", sizeCommand, "86px"); createClickAction("96px (drag scroll select limit)", "Height", sizeCommand, "96px"); createClickAction("106px (drag scroll select enabled)", "Height", sizeCommand, "106px"); } private void addActionForHeightByRows(final Double i) { DecimalFormat df = new DecimalFormat("0.00"); createClickAction(df.format(i) + " rows", "Height by Rows", new Command<Grid, String>() { @Override public void execute(Grid c, String value, Object data) { c.setHeightByRows(i); } }, null); } private void createDetailsActions() { Command<Grid, DetailsGenerator> swapDetailsGenerator = new Command<Grid, DetailsGenerator>() { @Override public void execute(Grid c, DetailsGenerator generator, Object data) { grid.setDetailsGenerator(generator); } }; Command<Grid, Boolean> openOrCloseItemId = new Command<Grid, Boolean>() { @Override @SuppressWarnings("boxing") public void execute(Grid g, Boolean visible, Object itemId) { g.setDetailsVisible(itemId, visible); } }; createCategory("Generators", "Details"); createClickAction("NULL", "Generators", swapDetailsGenerator, DetailsGenerator.NULL); createClickAction("\"Watching\"", "Generators", swapDetailsGenerator, watchingDetailsGenerator); createClickAction("Detailed", "Generators", swapDetailsGenerator, detailedDetailsGenerator); createClickAction("Persisting", "Generators", swapDetailsGenerator, persistingDetailsGenerator); createClickAction("- Change Component", "Generators", new Command<Grid, Void>() { @Override public void execute(Grid c, Void value, Object data) { for (Object id : detailsMap.keySet()) { Panel panel = detailsMap.get(id); Label label = (Label) panel.getContent(); if (label.getValue().equals("One")) { panel.setContent(new Label("Two")); } else { panel.setContent(new Label("One")); } } } }, null); createClickAction("Toggle firstItemId", "Details", new Command<Grid, Void>() { @Override public void execute(Grid g, Void value, Object data) { Object firstItemId = g.getContainerDataSource() .firstItemId(); boolean toggle = g.isDetailsVisible(firstItemId); g.setDetailsVisible(firstItemId, !toggle); g.setDetailsVisible(firstItemId, toggle); } }, null); createBooleanAction("Open firstItemId", "Details", false, openOrCloseItemId, ds.firstItemId()); createBooleanAction("Open 1", "Details", false, openOrCloseItemId, ds.getIdByIndex(1)); createBooleanAction("Open 995", "Details", false, openOrCloseItemId, ds.getIdByIndex(995)); } @Override protected Integer getTicketNumber() { return 12829; } @Override protected Class<Grid> getTestClass() { return Grid.class; } }