From 9c8211611b3b49c877966e6b4248aecb5bf27c27 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Thu, 10 Jul 2014 16:54:22 +0300 Subject: Split GridBasicFeaturesTest to sub tests Change-Id: I17f2c9e289cd08f583fcccfbd2852d38afeda180 --- .../grid/basicfeatures/GridBasicFeatures.java | 544 +++++++++++++++++++++ .../grid/basicfeatures/GridBasicFeaturesTest.java | 79 +++ .../grid/basicfeatures/GridSelectionTest.java | 119 +++++ .../grid/basicfeatures/GridSortingTest.java | 159 ++++++ .../grid/basicfeatures/GridStructureTest.java | 347 +++++++++++++ 5 files changed, 1248 insertions(+) create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java new file mode 100644 index 0000000000..316d7116e3 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -0,0 +1,544 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Random; + +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.shared.ui.grid.HeightMode; +import com.vaadin.shared.ui.grid.SortDirection; +import com.vaadin.tests.components.AbstractComponentTest; +import com.vaadin.ui.components.grid.ColumnGroup; +import com.vaadin.ui.components.grid.ColumnGroupRow; +import com.vaadin.ui.components.grid.Grid; +import com.vaadin.ui.components.grid.Grid.SelectionMode; +import com.vaadin.ui.components.grid.GridColumn; +import com.vaadin.ui.components.grid.SortOrderChangeEvent; +import com.vaadin.ui.components.grid.SortOrderChangeListener; +import com.vaadin.ui.components.grid.renderers.DateRenderer; +import com.vaadin.ui.components.grid.renderers.HtmlRenderer; +import com.vaadin.ui.components.grid.renderers.NumberRenderer; +import com.vaadin.ui.components.grid.sort.Sort; +import com.vaadin.ui.components.grid.sort.SortOrder; + +/** + * Tests the basic features like columns, footers and headers + * + * @since + * @author Vaadin Ltd + */ +public class GridBasicFeatures extends AbstractComponentTest { + + private static final int MANUALLY_FORMATTED_COLUMNS = 4; + public static final int COLUMNS = 11; + public static final int ROWS = 1000; + + private int columnGroupRows = 0; + private IndexedContainer ds; + + @Override + @SuppressWarnings("unchecked") + protected Grid constructComponent() { + + // Build data source + ds = new IndexedContainer() { + @Override + public List getItemIds(int startIndex, int numberOfIds) { + log("Requested items " + startIndex + " - " + + (startIndex + numberOfIds)); + 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, ""); + + 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(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( + "" + row + ""); + + item.getItemProperty(getColumnProperty(col++)).setValue( + rand.nextInt()); + } + } + + // 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()); + } + + // Add footer values (header values are automatically created) + for (int col = 0; col < COLUMNS; col++) { + grid.getColumn(getColumnProperty(col)).setFooterCaption( + "Footer " + col); + } + + // Set varying column widths + for (int col = 0; col < COLUMNS; col++) { + grid.getColumn("Column" + col).setWidth(100 + col * 50); + } + + grid.addSortOrderChangeListener(new SortOrderChangeListener() { + @Override + public void sortOrderChange(SortOrderChangeEvent event) { + log("Sort order: " + event.getSortOrder()); + } + }); + + grid.setSelectionMode(SelectionMode.NONE); + + createGridActions(); + + createColumnActions(); + + createHeaderActions(); + + createFooterActions(); + + createColumnGroupActions(); + + createRowActions(); + + addHeightActions(); + + return grid; + } + + protected void createGridActions() { + LinkedHashMap 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() { + + @Override + public void execute(Grid grid, String value, Object data) { + grid.setPrimaryStyleName(value); + + } + }, primaryStyleNames.get("v-grid")); + + LinkedHashMap 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() { + @Override + public void execute(Grid grid, SelectionMode selectionMode, + Object data) { + grid.setSelectionMode(selectionMode); + } + }); + + LinkedHashMap> 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>() { + @Override + public void execute(Grid grid, List sortOrder, + Object data) { + grid.setSortOrder(sortOrder); + } + }); + } + + protected void createHeaderActions() { + createCategory("Headers", null); + + createBooleanAction("Visible", "Headers", true, + new Command() { + + @Override + public void execute(Grid grid, Boolean value, Object data) { + grid.setColumnHeadersVisible(value); + } + }); + } + + protected void createFooterActions() { + createCategory("Footers", null); + + createBooleanAction("Visible", "Footers", false, + new Command() { + + @Override + public void execute(Grid grid, Boolean value, Object data) { + grid.setColumnFootersVisible(value); + } + }); + } + + protected void createColumnActions() { + createCategory("Columns", null); + + for (int c = 0; c < COLUMNS; c++) { + createCategory(getColumnProperty(c), "Columns"); + + createBooleanAction("Visible", getColumnProperty(c), true, + new Command() { + + @Override + public void execute(Grid grid, Boolean value, + Object columnIndex) { + Object propertyId = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((Integer) columnIndex)); + GridColumn column = grid.getColumn(propertyId); + column.setVisible(!column.isVisible()); + } + }, c); + + createClickAction("Remove", getColumnProperty(c), + new Command() { + + @Override + public void execute(Grid grid, String value, Object data) { + grid.getContainerDatasource() + .removeContainerProperty("Column" + data); + } + }, null, c); + + createClickAction("Freeze", getColumnProperty(c), + new Command() { + + @Override + public void execute(Grid grid, String value, Object data) { + grid.setLastFrozenPropertyId("Column" + data); + } + }, null, c); + + createBooleanAction("Sortable", getColumnProperty(c), true, + new Command() { + + @Override + public void execute(Grid grid, Boolean value, + Object columnIndex) { + Object propertyId = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((Integer) columnIndex)); + GridColumn column = grid.getColumn(propertyId); + column.setSortable(value); + } + }, c); + + createCategory("Column" + c + " Width", getColumnProperty(c)); + + createClickAction("Auto", "Column" + c + " Width", + new Command() { + + @Override + public void execute(Grid grid, Integer value, + Object columnIndex) { + Object propertyId = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((Integer) columnIndex)); + GridColumn column = grid.getColumn(propertyId); + column.setWidthUndefined(); + } + }, -1, c); + + for (int w = 50; w < 300; w += 50) { + createClickAction(w + "px", "Column" + c + " Width", + new Command() { + + @Override + public void execute(Grid grid, Integer value, + Object columnIndex) { + Object propertyId = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((Integer) columnIndex)); + GridColumn column = grid.getColumn(propertyId); + column.setWidth(value); + } + }, w, c); + } + } + } + + private static String getColumnProperty(int c) { + return "Column" + c; + } + + protected void createColumnGroupActions() { + createCategory("Column groups", null); + + createClickAction("Add group row", "Column groups", + new Command() { + + @Override + public void execute(Grid grid, String value, Object data) { + final ColumnGroupRow row = grid.addColumnGroupRow(); + columnGroupRows++; + createCategory("Column group row " + columnGroupRows, + "Column groups"); + + createBooleanAction("Header Visible", + "Column group row " + columnGroupRows, true, + new Command() { + + @Override + public void execute(Grid grid, + Boolean value, Object columnIndex) { + row.setHeaderVisible(value); + } + }, row); + + createBooleanAction("Footer Visible", + "Column group row " + columnGroupRows, false, + new Command() { + + @Override + public void execute(Grid grid, + Boolean value, Object columnIndex) { + row.setFooterVisible(value); + } + }, row); + + for (int i = 0; i < COLUMNS; i++) { + final int columnIndex = i; + createClickAction("Group Column " + columnIndex + + " & " + (columnIndex + 1), + "Column group row " + columnGroupRows, + new Command() { + + @Override + public void execute(Grid c, + Integer value, Object data) { + final ColumnGroup group = row + .addGroup( + "Column" + value, + "Column" + + (value + 1)); + + group.setHeaderCaption("Column " + + value + " & " + + (value + 1)); + + group.setFooterCaption("Column " + + value + " & " + + (value + 1)); + } + }, i, row); + } + } + }, null, null); + + } + + protected void createRowActions() { + createCategory("Body rows", null); + + createClickAction("Add first row", "Body rows", + new Command() { + @Override + public void execute(Grid c, String value, Object data) { + Item item = ds.addItemAt(0, new Object()); + for (int i = 0; i < COLUMNS; i++) { + item.getItemProperty(getColumnProperty(i)) + .setValue("newcell: " + i); + } + } + }, null); + + createClickAction("Remove first row", "Body rows", + new Command() { + @Override + public void execute(Grid c, String value, Object data) { + Object firstItemId = ds.getIdByIndex(0); + ds.removeItem(firstItemId); + } + }, null); + + createClickAction("Modify first row (getItemProperty)", "Body rows", + new Command() { + @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) property) + .setValue("modified: " + i); + } + } + } + }, null); + + createClickAction("Modify first row (getContainerProperty)", + "Body rows", new Command() { + @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) property) + .setValue("modified: " + + containerPropertyId); + } + } + } + }, null); + + createBooleanAction("Select first row", "Body rows", false, + new Command() { + @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); + } + } + }); + } + + @SuppressWarnings("boxing") + protected void addHeightActions() { + createCategory("Height by Rows", "Size"); + + createBooleanAction("HeightMode Row", "Size", false, + new Command() { + @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 sizeCommand = new Command() { + @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() { + @Override + public void execute(Grid c, String value, Object data) { + c.setHeightByRows(i); + } + }, null); + } + + @Override + protected Integer getTicketNumber() { + return 12829; + } + + @Override + protected Class getTestClass() { + return Grid.class; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java new file mode 100644 index 0000000000..3651a0c919 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java @@ -0,0 +1,79 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.annotations.TestCategory; +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +@TestCategory("grid") +public abstract class GridBasicFeaturesTest extends MultiBrowserTest { + + @Override + protected Class getUIClass() { + return GridBasicFeatures.class; + } + + private void selectSubMenu(String menuCaption) { + selectMenu(menuCaption); + new Actions(getDriver()).moveByOffset(100, 0).build().perform(); + } + + private void selectMenu(String menuCaption) { + getDriver().findElement( + By.xpath("//span[text() = '" + menuCaption + "']")).click(); + } + + protected void selectMenuPath(String... menuCaptions) { + selectMenu(menuCaptions[0]); + for (int i = 1; i < menuCaptions.length; i++) { + selectSubMenu(menuCaptions[i]); + } + } + + protected GridElement getGridElement() { + return $(GridElement.class).id("testComponent"); + } + + protected void scrollGridVerticallyTo(double px) { + executeScript("arguments[0].scrollTop = " + px, + getGridVerticalScrollbar()); + } + + private Object executeScript(String script, WebElement element) { + final WebDriver driver = getDriver(); + if (driver instanceof JavascriptExecutor) { + final JavascriptExecutor je = (JavascriptExecutor) driver; + return je.executeScript(script, element); + } else { + throw new IllegalStateException("current driver " + + getDriver().getClass().getName() + " is not a " + + JavascriptExecutor.class.getSimpleName()); + } + } + + private WebElement getGridVerticalScrollbar() { + return getDriver() + .findElement( + By.xpath("//div[contains(@class, \"v-grid-scroller-vertical\")]")); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java new file mode 100644 index 0000000000..e18dc1faa4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java @@ -0,0 +1,119 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridSelectionTest extends GridBasicFeaturesTest { + + @Test + public void testSelectOnOff() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", + isSelected(getRow(0))); + toggleFirstRowSelection(); + assertTrue("row should become selected", isSelected(getRow(0))); + toggleFirstRowSelection(); + assertFalse("row shouldn't remain selected", isSelected(getRow(0))); + } + + @Test + public void testSelectOnScrollOffScroll() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", + isSelected(getRow(0))); + toggleFirstRowSelection(); + assertTrue("row should become selected", isSelected(getRow(0))); + + scrollGridVerticallyTo(10000); // make sure the row is out of cache + scrollGridVerticallyTo(0); // scroll it back into view + + assertTrue("row should still be selected when scrolling " + + "back into view", isSelected(getRow(0))); + } + + @Test + public void testSelectScrollOnScrollOff() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", + isSelected(getRow(0))); + + scrollGridVerticallyTo(10000); // make sure the row is out of cache + toggleFirstRowSelection(); + + scrollGridVerticallyTo(0); // scroll it back into view + assertTrue("row should still be selected when scrolling " + + "back into view", isSelected(getRow(0))); + + toggleFirstRowSelection(); + assertFalse("row shouldn't remain selected", isSelected(getRow(0))); + } + + @Test + public void testSelectScrollOnOffScroll() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", + isSelected(getRow(0))); + + scrollGridVerticallyTo(10000); // make sure the row is out of cache + toggleFirstRowSelection(); + toggleFirstRowSelection(); + + scrollGridVerticallyTo(0); // make sure the row is out of cache + assertFalse("row shouldn't be selected when scrolling " + + "back into view", isSelected(getRow(0))); + } + + private void setSelectionModelMulti() { + selectMenuPath("Component", "State", "Selection mode", "multi"); + } + + @SuppressWarnings("static-method") + private boolean isSelected(TestBenchElement row) { + /* + * FIXME We probably should get a GridRow instead of a plain + * TestBenchElement, that has an "isSelected" thing integrated. (henrik + * paul 26.6.2014) + */ + return row.getAttribute("class").contains("-row-selected"); + } + + private void toggleFirstRowSelection() { + selectMenuPath("Component", "Body rows", "Select first row"); + } + + private TestBenchElement getRow(int i) { + return getGridElement().getRow(i); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java new file mode 100644 index 0000000000..820070f933 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java @@ -0,0 +1,159 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.junit.Test; + +import com.vaadin.tests.components.grid.GridElement; + +public class GridSortingTest extends GridBasicFeaturesTest { + + @Test + public void testProgrammaticSorting() throws IOException { + openTestURL(); + + GridElement grid = getGridElement(); + + // Sorting by column 9 is sorting by row index that is represented as a + // String. + // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0) + sortBy("Column9, DESC"); + + assertTrue("Column 9 should have the sort-desc stylename", grid + .getHeaderCell(0, 9).getAttribute("class") + .contains("sort-desc")); + + String row = ""; + for (int i = 0; i < 3; ++i) { + row += "9"; + assertEquals( + "Grid is not sorted by Column9 using descending direction.", + "(" + row + ", 0)", grid.getCell(i, 0).getText()); + } + + // Column 10 is random numbers from Random with seed 13334 + sortBy("Column10, ASC"); + + assertFalse( + "Column 9 should no longer have the sort-desc stylename", + grid.getHeaderCell(0, 9).getAttribute("class") + .contains("sort-desc")); + assertTrue("Column 10 should have the sort-asc stylename", grid + .getHeaderCell(0, 10).getAttribute("class") + .contains("sort-asc")); + + // Not cleaning up correctly causes exceptions when scrolling. + grid.scrollToRow(50); + assertFalse("Scrolling caused and exception when shuffled.", + getLogRow(0).contains("Exception")); + + for (int i = 0; i < 5; ++i) { + assertGreater( + "Grid is not sorted by Column10 using ascending direction", + Integer.parseInt(grid.getCell(i + 1, 10).getText()), + Integer.parseInt(grid.getCell(i, 10).getText())); + + } + + // Column 7 is row index as a number. Last three row are original rows + // 2, 1 and 0. + sortBy("Column7, DESC"); + for (int i = 0; i < 3; ++i) { + assertEquals( + "Grid is not sorted by Column7 using descending direction", + "(" + i + ", 0)", + grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); + } + + assertFalse( + "Column 10 should no longer have the sort-asc stylename", + grid.getHeaderCell(0, 10).getAttribute("class") + .contains("sort-asc")); + assertTrue("Column 7 should have the sort-desc stylename", grid + .getHeaderCell(0, 7).getAttribute("class") + .contains("sort-desc")); + + } + + @Test + public void testUserSorting() throws InterruptedException { + openTestURL(); + + GridElement grid = getGridElement(); + + // Sorting by column 9 is sorting by row index that is represented as a + // String. + // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0) + + // Click header twice to sort descending + grid.getHeaderCell(0, 9).click(); + grid.getHeaderCell(0, 9).click(); + String row = ""; + for (int i = 0; i < 3; ++i) { + row += "9"; + assertEquals( + "Grid is not sorted by Column9 using descending direction.", + "(" + row + ", 0)", grid.getCell(i, 0).getText()); + } + + assertEquals("2. Sort order: [Column9 ASCENDING]", getLogRow(2)); + assertEquals("4. Sort order: [Column9 DESCENDING]", getLogRow(0)); + + // Column 10 is random numbers from Random with seed 13334 + // Click header to sort ascending + grid.getHeaderCell(0, 10).click(); + + assertEquals("6. Sort order: [Column10 ASCENDING]", getLogRow(0)); + + // Not cleaning up correctly causes exceptions when scrolling. + grid.scrollToRow(50); + assertFalse("Scrolling caused and exception when shuffled.", + getLogRow(0).contains("Exception")); + + for (int i = 0; i < 5; ++i) { + assertGreater( + "Grid is not sorted by Column10 using ascending direction", + Integer.parseInt(grid.getCell(i + 1, 10).getText()), + Integer.parseInt(grid.getCell(i, 10).getText())); + + } + + // Column 7 is row index as a number. Last three row are original rows + // 2, 1 and 0. + // Click header twice to sort descending + grid.getHeaderCell(0, 7).click(); + grid.getHeaderCell(0, 7).click(); + for (int i = 0; i < 3; ++i) { + assertEquals( + "Grid is not sorted by Column7 using descending direction", + "(" + i + ", 0)", + grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); + } + + assertEquals("9. Sort order: [Column7 ASCENDING]", getLogRow(3)); + assertEquals("11. Sort order: [Column7 DESCENDING]", getLogRow(1)); + } + + private void sortBy(String column) { + selectMenuPath("Component", "State", "Sort by column", column); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java new file mode 100644 index 0000000000..17438fd4bb --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java @@ -0,0 +1,347 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridStructureTest extends GridBasicFeaturesTest { + + @Test + public void testColumnHeaderCaptions() throws Exception { + openTestURL(); + + // Column headers should be visible + List cells = getGridHeaderRowCells(); + assertEquals(GridBasicFeatures.COLUMNS, cells.size()); + assertEquals("Column0", cells.get(0).getText()); + assertEquals("Column1", cells.get(1).getText()); + assertEquals("Column2", cells.get(2).getText()); + } + + @Test + public void testColumnFooterCaptions() throws Exception { + openTestURL(); + + // footer row should by default be hidden + List cells = getGridFooterRowCells(); + assertEquals(0, cells.size()); + + // Open footer row + selectMenuPath("Component", "Footers", "Visible"); + + // Footers should now be visible + cells = getGridFooterRowCells(); + assertEquals(GridBasicFeatures.COLUMNS, cells.size()); + assertEquals("Footer 0", cells.get(0).getText()); + assertEquals("Footer 1", cells.get(1).getText()); + assertEquals("Footer 2", cells.get(2).getText()); + } + + @Test + public void testColumnGroupHeaders() throws Exception { + openTestURL(); + + // Hide column headers for this test + selectMenuPath("Component", "Headers", "Visible"); + + List cells = getGridHeaderRowCells(); + + // header row should be empty + assertEquals(0, cells.size()); + + // add a group row + selectMenuPath("Component", "Column groups", "Add group row"); + + // Empty group row cells should be present + cells = getGridHeaderRowCells(); + assertEquals(GridBasicFeatures.COLUMNS, cells.size()); + + // Group columns 0 & 1 + selectMenuPath("Component", "Column groups", "Column group row 1", + "Group Column 0 & 1"); + + cells = getGridHeaderRowCells(); + assertEquals("Column 0 & 1", cells.get(0).getText()); + } + + @Test + public void testColumnGroupFooters() throws Exception { + openTestURL(); + + // add a group row + selectMenuPath("Component", "Column groups", "Add group row"); + + // Set footer visible + selectMenuPath("Component", "Column groups", "Column group row 1", + "Footer Visible"); + + // Group columns 0 & 1 + selectMenuPath("Component", "Column groups", "Column group row 1", + "Group Column 0 & 1"); + + List cells = getGridFooterRowCells(); + assertEquals("Column 0 & 1", cells.get(0).getText()); + } + + @Test + public void testGroupingSameColumnsOnRowThrowsException() throws Exception { + openTestURL(); + + // add a group row + selectMenuPath("Component", "Column groups", "Add group row"); + + // Group columns 0 & 1 + selectMenuPath("Component", "Column groups", "Column group row 1", + "Group Column 0 & 1"); + + // Group columns 1 & 2 shoud fail + selectMenuPath("Component", "Column groups", "Column group row 1", + "Group Column 1 & 2"); + + assertTrue(getLogRow(0) + .contains( + "Exception occured, java.lang.IllegalArgumentExceptionColumn Column1 already belongs to another group.")); + } + + @Test + public void testHidingColumn() throws Exception { + openTestURL(); + + // Column 0 should be visible + List cells = getGridHeaderRowCells(); + assertEquals("Column0", cells.get(0).getText()); + + // Hide column 0 + selectMenuPath("Component", "Columns", "Column0", "Visible"); + + // Column 1 should now be the first cell + cells = getGridHeaderRowCells(); + assertEquals("Column1", cells.get(0).getText()); + } + + @Test + public void testRemovingColumn() throws Exception { + openTestURL(); + + // Column 0 should be visible + List cells = getGridHeaderRowCells(); + assertEquals("Column0", cells.get(0).getText()); + + // Hide column 0 + selectMenuPath("Component", "Columns", "Column0", "Remove"); + + // Column 1 should now be the first cell + cells = getGridHeaderRowCells(); + assertEquals("Column1", cells.get(0).getText()); + } + + @Test + public void testDataLoadingAfterRowRemoval() throws Exception { + openTestURL(); + + // Remove columns 2,3,4 + selectMenuPath("Component", "Columns", "Column2", "Remove"); + selectMenuPath("Component", "Columns", "Column3", "Remove"); + selectMenuPath("Component", "Columns", "Column4", "Remove"); + + // Scroll so new data is lazy loaded + scrollGridVerticallyTo(1000); + + // Let lazy loading do its job + sleep(1000); + + // Check that row is loaded + assertThat(getBodyCellByRowAndColumn(11, 0).getText(), not("...")); + } + + @Test + public void testFreezingColumn() throws Exception { + openTestURL(); + + // Freeze column 2 + selectMenuPath("Component", "Columns", "Column2", "Freeze"); + + WebElement cell = getBodyCellByRowAndColumn(0, 0); + assertTrue(cell.getAttribute("class").contains("frozen")); + + cell = getBodyCellByRowAndColumn(0, 1); + assertTrue(cell.getAttribute("class").contains("frozen")); + } + + @Test + public void testInitialColumnWidths() throws Exception { + openTestURL(); + + WebElement cell = getBodyCellByRowAndColumn(0, 0); + assertEquals(100, cell.getSize().getWidth()); + + cell = getBodyCellByRowAndColumn(0, 1); + assertEquals(150, cell.getSize().getWidth()); + + cell = getBodyCellByRowAndColumn(0, 2); + assertEquals(200, cell.getSize().getWidth()); + } + + @Test + public void testColumnWidths() throws Exception { + openTestURL(); + + // Default column width is 100px + WebElement cell = getBodyCellByRowAndColumn(0, 0); + assertEquals(100, cell.getSize().getWidth()); + + // Set first column to be 200px wide + selectMenuPath("Component", "Columns", "Column0", "Column0 Width", + "200px"); + + cell = getBodyCellByRowAndColumn(0, 0); + assertEquals(200, cell.getSize().getWidth()); + + // Set second column to be 150px wide + selectMenuPath("Component", "Columns", "Column1", "Column1 Width", + "150px"); + cell = getBodyCellByRowAndColumn(0, 1); + assertEquals(150, cell.getSize().getWidth()); + + // Set first column to be auto sized (defaults to 100px currently) + selectMenuPath("Component", "Columns", "Column0", "Column0 Width", + "Auto"); + + cell = getBodyCellByRowAndColumn(0, 0); + assertEquals(100, cell.getSize().getWidth()); + } + + @Test + public void testPrimaryStyleNames() throws Exception { + openTestURL(); + + // v-grid is default primary style namea + assertPrimaryStylename("v-grid"); + + selectMenuPath("Component", "State", "Primary style name", + "v-escalator"); + assertPrimaryStylename("v-escalator"); + + selectMenuPath("Component", "State", "Primary style name", "my-grid"); + assertPrimaryStylename("my-grid"); + + selectMenuPath("Component", "State", "Primary style name", "v-grid"); + assertPrimaryStylename("v-grid"); + } + + /** + * Test that the current view is updated when a server-side container change + * occurs (without scrolling back and forth) + */ + @Test + public void testItemSetChangeEvent() throws Exception { + openTestURL(); + + final By newRow = By.xpath("//td[text()='newcell: 0']"); + + assertTrue("Unexpected initial state", !isElementPresent(newRow)); + + selectMenuPath("Component", "Body rows", "Add first row"); + assertTrue("Add row failed", isElementPresent(newRow)); + + selectMenuPath("Component", "Body rows", "Remove first row"); + assertTrue("Remove row failed", !isElementPresent(newRow)); + } + + /** + * Test that the current view is updated when a property's value is reflect + * to the client, when the value is modified server-side. + */ + @Test + public void testPropertyValueChangeEvent() throws Exception { + openTestURL(); + + assertEquals("Unexpected cell initial state", "(0, 0)", + getBodyCellByRowAndColumn(0, 0).getText()); + + selectMenuPath("Component", "Body rows", + "Modify first row (getItemProperty)"); + assertEquals("(First) modification with getItemProperty failed", + "modified: 0", getBodyCellByRowAndColumn(0, 0).getText()); + + selectMenuPath("Component", "Body rows", + "Modify first row (getContainerProperty)"); + assertEquals("(Second) modification with getItemProperty failed", + "modified: Column0", getBodyCellByRowAndColumn(0, 0).getText()); + } + + private void assertPrimaryStylename(String stylename) { + assertTrue(getGridElement().getAttribute("class").contains(stylename)); + + String tableWrapperStyleName = getTableWrapper().getAttribute("class"); + assertTrue(tableWrapperStyleName.contains(stylename + "-tablewrapper")); + + String hscrollStyleName = getHorizontalScroller().getAttribute("class"); + assertTrue(hscrollStyleName.contains(stylename + "-scroller")); + assertTrue(hscrollStyleName + .contains(stylename + "-scroller-horizontal")); + + String vscrollStyleName = getVerticalScroller().getAttribute("class"); + assertTrue(vscrollStyleName.contains(stylename + "-scroller")); + assertTrue(vscrollStyleName.contains(stylename + "-scroller-vertical")); + } + + private WebElement getBodyCellByRowAndColumn(int row, int column) { + return getGridElement().getCell(row, column); + } + + private WebElement getVerticalScroller() { + return getGridElement().findElement(By.xpath("./div[1]")); + } + + private WebElement getHorizontalScroller() { + return getGridElement().findElement(By.xpath("./div[2]")); + } + + private WebElement getTableWrapper() { + return getGridElement().findElement(By.xpath("./div[3]")); + } + + private List getGridHeaderRowCells() { + List headerCells = new ArrayList(); + for (int i = 0; i < getGridElement().getHeaderCount(); ++i) { + headerCells.addAll(getGridElement().getHeaderCells(i)); + } + return headerCells; + } + + private List getGridFooterRowCells() { + List footerCells = new ArrayList(); + for (int i = 0; i < getGridElement().getFooterCount(); ++i) { + footerCells.addAll(getGridElement().getFooterCells(i)); + } + return footerCells; + } +} -- cgit v1.2.3 From 44093bb40c6759e02bb7df3a27f649725e2f145d Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Tue, 15 Jul 2014 14:36:26 +0300 Subject: Refactor GridKeyboardNavigationTest GridKeyboardNavigationTest is now a subclass of GridBasicFeaturesTest. Change-Id: Ibb169526a035fb77a66024a5170996d9a0607b02 --- .../grid/GridKeyboardNavigationTest.java | 66 ---------------------- .../basicfeatures/GridKeyboardNavigationTest.java | 57 +++++++++++++++++++ 2 files changed, 57 insertions(+), 66 deletions(-) delete mode 100644 uitest/src/com/vaadin/tests/components/grid/GridKeyboardNavigationTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/uitest/src/com/vaadin/tests/components/grid/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/GridKeyboardNavigationTest.java deleted file mode 100644 index 927b941131..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/GridKeyboardNavigationTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2000-2014 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; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import com.vaadin.tests.tb3.MultiBrowserTest; - -public class GridKeyboardNavigationTest extends MultiBrowserTest { - - @Override - protected Class getUIClass() { - return GridBasicFeatures.class; - } - - @Test - public void testCellActiveOnClick() { - openTestURL(); - - GridElement grid = getGridElement(); - assertTrue("Body cell 0, 0 is not active on init.", - cellIsActive(grid, 0, 0)); - grid.getCell(5, 2).click(); - assertFalse("Body cell 0, 0 was still active after clicking", - cellIsActive(grid, 0, 0)); - assertTrue("Body cell 5, 2 is not active after clicking", - cellIsActive(grid, 5, 2)); - } - - @Test - public void testCellNotActiveWhenRendererHandlesEvent() { - openTestURL(); - - GridElement grid = getGridElement(); - assertTrue("Body cell 0, 0 is not active on init.", - cellIsActive(grid, 0, 0)); - grid.getHeaderCell(0, 3).click(); - assertTrue("Body cell 0, 0 is not active after click on header.", - cellIsActive(grid, 0, 0)); - } - - private boolean cellIsActive(GridElement grid, int row, int col) { - return grid.getCell(row, col).getAttribute("class") - .contains("-cell-active"); - } - - private GridElement getGridElement() { - return $(GridElement.class).first(); - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java new file mode 100644 index 0000000000..94a25aa321 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.tests.components.grid.GridElement; + +public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { + + @Test + public void testCellActiveOnClick() { + openTestURL(); + + GridElement grid = getGridElement(); + assertTrue("Body cell 0, 0 is not active on init.", + cellIsActive(grid, 0, 0)); + grid.getCell(5, 2).click(); + assertFalse("Body cell 0, 0 was still active after clicking", + cellIsActive(grid, 0, 0)); + assertTrue("Body cell 5, 2 is not active after clicking", + cellIsActive(grid, 5, 2)); + } + + @Test + public void testCellNotActiveWhenRendererHandlesEvent() { + openTestURL(); + + GridElement grid = getGridElement(); + assertTrue("Body cell 0, 0 is not active on init.", + cellIsActive(grid, 0, 0)); + grid.getHeaderCell(0, 3).click(); + assertTrue("Body cell 0, 0 is not active after click on header.", + cellIsActive(grid, 0, 0)); + } + + private boolean cellIsActive(GridElement grid, int row, int col) { + return grid.getCell(row, col).getAttribute("class") + .contains("-cell-active"); + } +} -- cgit v1.2.3 From 8c91be9e2fe478038aa1bf327c9e88d5a040fc77 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Mon, 14 Jul 2014 18:50:35 +0300 Subject: Add GridRowElement and GridCellElement (#13334) Change-Id: Ia0fbc8e0a54089f826659969fa281ec8a79b6d87 --- .../vaadin/tests/components/grid/GridElement.java | 65 +++++++++++++++++----- .../basicfeatures/GridKeyboardNavigationTest.java | 23 +++----- 2 files changed, 60 insertions(+), 28 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/uitest/src/com/vaadin/tests/components/grid/GridElement.java b/uitest/src/com/vaadin/tests/components/grid/GridElement.java index 091c9db1ce..5027c603d9 100644 --- a/uitest/src/com/vaadin/tests/components/grid/GridElement.java +++ b/uitest/src/com/vaadin/tests/components/grid/GridElement.java @@ -15,6 +15,7 @@ */ package com.vaadin.tests.components.grid; +import java.util.ArrayList; import java.util.List; import org.openqa.selenium.NoSuchElementException; @@ -22,6 +23,7 @@ import org.openqa.selenium.NoSuchElementException; import com.vaadin.testbench.By; import com.vaadin.testbench.TestBenchElement; import com.vaadin.testbench.elements.AbstractComponentElement; +import com.vaadin.testbench.elements.AbstractElement; import com.vaadin.testbench.elements.ServerClass; /** @@ -33,6 +35,30 @@ import com.vaadin.testbench.elements.ServerClass; @ServerClass("com.vaadin.ui.components.grid.Grid") public class GridElement extends AbstractComponentElement { + public static class GridCellElement extends AbstractElement { + + private String ACTIVE_CLASS_NAME = "-cell-active"; + + public boolean isActive() { + return getAttribute("class").contains(ACTIVE_CLASS_NAME); + } + } + + public static class GridRowElement extends AbstractElement { + + private String ACTIVE_CLASS_NAME = "-row-active"; + private String SELECTED_CLASS_NAME = "-row-selected"; + + public boolean isActive() { + return getAttribute("class").contains(ACTIVE_CLASS_NAME); + } + + @Override + public boolean isSelected() { + return getAttribute("class").contains(SELECTED_CLASS_NAME); + } + } + /** * Scrolls Grid element so that wanted row is displayed * @@ -56,9 +82,10 @@ public class GridElement extends AbstractComponentElement { * Column index * @return Cell element with given indices. */ - public TestBenchElement getCell(int rowIndex, int colIndex) { + public GridCellElement getCell(int rowIndex, int colIndex) { scrollToRow(rowIndex); - return getSubPart("#cell[" + rowIndex + "][" + colIndex + "]"); + return getSubPart("#cell[" + rowIndex + "][" + colIndex + "]").wrap( + GridCellElement.class); } /** @@ -68,9 +95,9 @@ public class GridElement extends AbstractComponentElement { * Row index * @return Row element with given index. */ - public TestBenchElement getRow(int index) { + public GridRowElement getRow(int index) { scrollToRow(index); - return getSubPart("#cell[" + index + "]"); + return getSubPart("#cell[" + index + "]").wrap(GridRowElement.class); } /** @@ -82,8 +109,9 @@ public class GridElement extends AbstractComponentElement { * Column index * @return Header cell element with given indices. */ - public TestBenchElement getHeaderCell(int rowIndex, int colIndex) { - return getSubPart("#header[" + rowIndex + "][" + colIndex + "]"); + public GridCellElement getHeaderCell(int rowIndex, int colIndex) { + return getSubPart("#header[" + rowIndex + "][" + colIndex + "]").wrap( + GridCellElement.class); } /** @@ -95,8 +123,9 @@ public class GridElement extends AbstractComponentElement { * Column index * @return Footer cell element with given indices. */ - public TestBenchElement getFooterCell(int rowIndex, int colIndex) { - return getSubPart("#footer[" + rowIndex + "][" + colIndex + "]"); + public GridCellElement getFooterCell(int rowIndex, int colIndex) { + return getSubPart("#footer[" + rowIndex + "][" + colIndex + "]").wrap( + GridCellElement.class); } /** @@ -106,10 +135,14 @@ public class GridElement extends AbstractComponentElement { * Row index * @return Header cell elements on given row. */ - public List getHeaderCells(int rowIndex) { - return TestBenchElement.wrapElements( + public List getHeaderCells(int rowIndex) { + List headers = new ArrayList(); + for (TestBenchElement e : TestBenchElement.wrapElements( getSubPart("#header[" + rowIndex + "]").findElements( - By.xpath("./th")), getTestBenchCommandExecutor()); + By.xpath("./th")), getCommandExecutor())) { + headers.add(e.wrap(GridCellElement.class)); + } + return headers; } /** @@ -119,10 +152,14 @@ public class GridElement extends AbstractComponentElement { * Row index * @return Header cell elements on given row. */ - public List getFooterCells(int rowIndex) { - return TestBenchElement.wrapElements( + public List getFooterCells(int rowIndex) { + List footers = new ArrayList(); + for (TestBenchElement e : TestBenchElement.wrapElements( getSubPart("#footer[" + rowIndex + "]").findElements( - By.xpath("./td")), getTestBenchCommandExecutor()); + By.xpath("./td")), getCommandExecutor())) { + footers.add(e.wrap(GridCellElement.class)); + } + return footers; } /** diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java index 94a25aa321..a297187b62 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java @@ -29,13 +29,13 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { openTestURL(); GridElement grid = getGridElement(); - assertTrue("Body cell 0, 0 is not active on init.", - cellIsActive(grid, 0, 0)); + assertTrue("Body cell 0, 0 is not active on init.", grid.getCell(0, 0) + .isActive()); grid.getCell(5, 2).click(); - assertFalse("Body cell 0, 0 was still active after clicking", - cellIsActive(grid, 0, 0)); + assertFalse("Body cell 0, 0 was still active after clicking", grid + .getCell(0, 0).isActive()); assertTrue("Body cell 5, 2 is not active after clicking", - cellIsActive(grid, 5, 2)); + grid.getCell(5, 2).isActive()); } @Test @@ -43,15 +43,10 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { openTestURL(); GridElement grid = getGridElement(); - assertTrue("Body cell 0, 0 is not active on init.", - cellIsActive(grid, 0, 0)); + assertTrue("Body cell 0, 0 is not active on init.", grid.getCell(0, 0) + .isActive()); grid.getHeaderCell(0, 3).click(); - assertTrue("Body cell 0, 0 is not active after click on header.", - cellIsActive(grid, 0, 0)); - } - - private boolean cellIsActive(GridElement grid, int row, int col) { - return grid.getCell(row, col).getAttribute("class") - .contains("-cell-active"); + assertTrue("Body cell 0, 0 is not active after click on header.", grid + .getCell(0, 0).isActive()); } } -- cgit v1.2.3 From 446c51e0f055aaf9d78020e9370e7d2dfbb451d1 Mon Sep 17 00:00:00 2001 From: Patrik Lindström Date: Wed, 16 Jul 2014 02:57:20 +0300 Subject: Add pure client-side test application for Grid (#13334) Change-Id: I853a91c20e80361ef5daeb31024597200acad1d9 --- .../basicfeatures/GridBasicClientFeaturesTest.java | 69 +++++ .../grid/basicfeatures/GridBasicFeaturesTest.java | 4 +- .../basicfeatures/GridClientSelectionTest.java | 35 +++ .../tests/widgetset/TestingWidgetSet.gwt.xml | 2 + .../client/grid/GridBasicClientFeatures.java | 254 +++++++++++++++++ .../grid/GridBasicClientFeaturesConnector.java | 36 +++ .../client/grid/PureGWTTestApplication.java | 308 +++++++++++++++++++++ .../server/grid/GridBasicClientFeatures.java | 41 +++ 8 files changed, 747 insertions(+), 2 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientSelectionTest.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/server/grid/GridBasicClientFeatures.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java new file mode 100644 index 0000000000..95b45b262e --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.widgetset.server.grid.GridBasicClientFeatures; + +/** + * Variant of GridBasicFeaturesTest to be used with GridBasicClientFeatures. + * + * @since + * @author Vaadin Ltd + */ +public abstract class GridBasicClientFeaturesTest extends GridBasicFeaturesTest { + + @Override + protected Class getUIClass() { + return GridBasicClientFeatures.class; + } + + @Override + protected GridElement getGridElement() { + return ((TestBenchElement) findElement(By.className("v-grid"))) + .wrap(GridElement.class); + } + + @Override + protected void selectMenu(String menuCaption) { + WebElement menuElement = getMenuElement(menuCaption); + new Actions(getDriver()).moveToElement(menuElement).perform(); + } + + private WebElement getMenuElement(String menuCaption) { + return getDriver().findElement( + By.xpath("//td[text() = '" + menuCaption + "']")); + } + + @Override + protected void selectMenuPath(String... menuCaptions) { + new Actions(getDriver()).moveToElement(getMenuElement(menuCaptions[0])) + .click().perform(); + for (int i = 1; i < menuCaptions.length - 1; ++i) { + selectMenu(menuCaptions[i]); + } + new Actions(getDriver()) + .moveToElement( + getMenuElement(menuCaptions[menuCaptions.length - 1])) + .click().perform(); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java index 3651a0c919..79501f50ac 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java @@ -33,12 +33,12 @@ public abstract class GridBasicFeaturesTest extends MultiBrowserTest { return GridBasicFeatures.class; } - private void selectSubMenu(String menuCaption) { + protected void selectSubMenu(String menuCaption) { selectMenu(menuCaption); new Actions(getDriver()).moveByOffset(100, 0).build().perform(); } - private void selectMenu(String menuCaption) { + protected void selectMenu(String menuCaption) { getDriver().findElement( By.xpath("//span[text() = '" + menuCaption + "']")).click(); } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientSelectionTest.java new file mode 100644 index 0000000000..cb70c28b7d --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientSelectionTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class GridClientSelectionTest extends GridBasicClientFeaturesTest { + + @Test + public void testChangeSelectionMode() { + openTestURL(); + + selectMenuPath("Component", "State", "Selection mode", "none"); + assertTrue("First column was selection column", getGridElement() + .getCell(0, 0).getText().equals("(0, 0)")); + selectMenuPath("Component", "State", "Selection mode", "multi"); + assertTrue("First column was not selection column", getGridElement() + .getCell(0, 1).getText().equals("(0, 0)")); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml index fd52e5cd0e..ac93efd7d4 100644 --- a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml +++ b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml @@ -4,6 +4,8 @@ + + diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java new file mode 100644 index 0000000000..857ff14528 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -0,0 +1,254 @@ +/* + * Copyright 2000-2014 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.widgetset.client.grid; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Random; + +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.vaadin.client.ui.grid.FlyweightCell; +import com.vaadin.client.ui.grid.Grid; +import com.vaadin.client.ui.grid.Grid.SelectionMode; +import com.vaadin.client.ui.grid.GridColumn; +import com.vaadin.client.ui.grid.Renderer; +import com.vaadin.client.ui.grid.datasources.ListDataSource; +import com.vaadin.client.ui.grid.renderers.DateRenderer; +import com.vaadin.client.ui.grid.renderers.HtmlRenderer; +import com.vaadin.client.ui.grid.renderers.NumberRenderer; +import com.vaadin.client.ui.grid.renderers.TextRenderer; +import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeatures.Data; + +/** + * Grid basic client features test application. + * + * @since + * @author Vaadin Ltd + */ +public class GridBasicClientFeatures extends + PureGWTTestApplication>> { + + public static enum Renderers { + TEXT_RENDERER, HTML_RENDERER, NUMBER_RENDERER, DATE_RENDERER; + } + + private static final int MANUALLY_FORMATTED_COLUMNS = 4; + public static final int COLUMNS = 11; + public static final int ROWS = 1000; + + private final Grid> grid; + private final List> data; + private final ListDataSource> ds; + + /** + * Our basic data object + */ + public final static class Data { + Object value; + } + + /** + * Convenience method for creating a list of Data objects to be used as a + * Row in the data source + * + * @param cols + * number of columns (items) to include in the row + * @return + */ + private List createDataRow(int cols) { + List list = new ArrayList(cols); + for (int i = 0; i < cols; ++i) { + list.add(new Data()); + } + data.add(list); + return list; + } + + @SuppressWarnings("unchecked") + public GridBasicClientFeatures() { + super(new Grid>()); + + // Initialize data source + data = new ArrayList>(); + { + Random rand = new Random(); + rand.setSeed(13334); + long timestamp = 0; + for (int row = 0; row < ROWS; row++) { + + List datarow = createDataRow(COLUMNS); + Data d; + + int col = 0; + for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) { + d = datarow.get(col); + d.value = "(" + row + ", " + col + ")"; + } + + d = datarow.get(col++); + d.value = Integer.valueOf(row); + + d = datarow.get(col++); + d.value = new Date(timestamp); + timestamp += 91250000; // a bit over a day, just to get + // variation + + d = datarow.get(col++); + d.value = "" + row + ""; + + d = datarow.get(col++); + d.value = Integer.valueOf(rand.nextInt()); + } + } + + ds = new ListDataSource>(data); + grid = getTestedWidget(); + grid.setDataSource(ds); + grid.setSelectionMode(SelectionMode.NONE); + + // Create a bunch of grid columns + + // Data source layout: + // text (String) * (COLUMNS - MANUALLY_FORMATTED_COLUMNS + 1) | + // rownumber (Integer) | some date (Date) | row number as HTML (String) + // | random value (Integer) + + int col = 0; + + // Text times COLUMNS - MANUALLY_FORMATTED_COLUMNS + for (col = 0; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) { + + final int c = col; + + grid.addColumn(new GridColumn>( + createRenderer(Renderers.TEXT_RENDERER)) { + @Override + public String getValue(List row) { + return (String) row.get(c).value; + } + }); + + } + + // Integer row number + { + final int c = col++; + grid.addColumn(new GridColumn>( + createRenderer(Renderers.NUMBER_RENDERER)) { + @Override + public Integer getValue(List row) { + return (Integer) row.get(c).value; + } + }); + } + + // Some date + { + final int c = col++; + grid.addColumn(new GridColumn>( + createRenderer(Renderers.DATE_RENDERER)) { + @Override + public Date getValue(List row) { + return (Date) row.get(c).value; + } + }); + } + + // Row number as a HTML string + { + final int c = col++; + grid.addColumn(new GridColumn>( + createRenderer(Renderers.HTML_RENDERER)) { + @Override + public String getValue(List row) { + return (String) row.get(c).value; + } + }); + } + + // Random integer value + { + final int c = col++; + grid.addColumn(new GridColumn>( + createRenderer(Renderers.NUMBER_RENDERER)) { + @Override + public Integer getValue(List row) { + return (Integer) row.get(c).value; + } + }); + } + + // + // Populate the menu + // + + addMenuCommand("multi", new ScheduledCommand() { + @Override + public void execute() { + grid.setSelectionMode(SelectionMode.MULTI); + } + }, "Component", "State", "Selection mode"); + + addMenuCommand("single", new ScheduledCommand() { + + @Override + public void execute() { + grid.setSelectionMode(SelectionMode.SINGLE); + } + }, "Component", "State", "Selection mode"); + + addMenuCommand("none", new ScheduledCommand() { + + @Override + public void execute() { + grid.setSelectionMode(SelectionMode.NONE); + } + }, "Component", "State", "Selection mode"); + + grid.getElement().getStyle().setZIndex(0); + add(grid); + } + + /** + * Creates a a renderer for a {@link Renderers} + */ + @SuppressWarnings("rawtypes") + private final Renderer createRenderer(Renderers renderer) { + switch (renderer) { + case TEXT_RENDERER: + return new TextRenderer(); + + case HTML_RENDERER: + return new HtmlRenderer() { + + @Override + public void render(FlyweightCell cell, String htmlString) { + super.render(cell, "" + htmlString + ""); + } + }; + + case NUMBER_RENDERER: + return new NumberRenderer(); + + case DATE_RENDERER: + return new DateRenderer(); + + default: + return new TextRenderer(); + } + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java new file mode 100644 index 0000000000..4b640e84e5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2014 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.widgetset.client.grid; + +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.shared.ui.Connect; + +/** + * Connector for the GridClientBasicFeatures ApplicationWidget + * + * @since + * @author Vaadin Ltd + */ +@Connect(com.vaadin.tests.widgetset.server.grid.GridBasicClientFeatures.GridTestComponent.class) +public class GridBasicClientFeaturesConnector extends + AbstractComponentConnector { + + @Override + public GridBasicClientFeatures getWidget() { + return (GridBasicClientFeatures) super.getWidget(); + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java new file mode 100644 index 0000000000..e9c126f232 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java @@ -0,0 +1,308 @@ +/* + * Copyright 2000-2014 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.widgetset.client.grid; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.DockLayoutPanel; +import com.google.gwt.user.client.ui.LayoutPanel; +import com.google.gwt.user.client.ui.MenuBar; +import com.google.gwt.user.client.ui.Panel; +import com.vaadin.client.ui.SubPartAware; + +/** + * Pure GWT Test Application base for testing features of a single widget; + * provides a menu system and convenience method for adding items to it. + * + * @since + * @author Vaadin Ltd + */ +public abstract class PureGWTTestApplication extends DockLayoutPanel + implements SubPartAware { + + /** + * Class describing a menu item with an associated action + */ + public static class Command { + private final String title; + private final ScheduledCommand command; + + /** + * Creates a Command object, which is used as an action entry in the + * Menu + * + * @param t + * a title string + * @param cmd + * a scheduled command that is executed when this item is + * selected + */ + public Command(String t, ScheduledCommand cmd) { + title = t; + command = cmd; + } + + /** + * Returns the title of this command item + * + * @return a title string + */ + public final String getTitle() { + return title; + } + + /** + * Returns the actual scheduled command of this command item + * + * @return a scheduled command + */ + public final ScheduledCommand getCommand() { + return command; + } + } + + /** + * A menu object, providing a complete system for building a hierarchical + * menu bar system. + */ + public static class Menu { + + private final String title; + private final MenuBar menubar; + private final List children; + private final List items; + + /** + * Create base-level menu, without a title. This is the root menu bar, + * which can be attached to a client application window. All other Menus + * should be added as child menus to this Menu, in order to maintain a + * nice hierarchy. + */ + private Menu() { + title = ""; + menubar = new MenuBar(); + children = new ArrayList(); + items = new ArrayList(); + } + + /** + * Create a sub-menu, with a title. + * + * @param title + */ + public Menu(String title) { + this.title = title; + menubar = new MenuBar(true); + children = new ArrayList(); + items = new ArrayList(); + } + + /** + * Return the GWT {@link MenuBar} object that provides the widget for + * this Menu + * + * @return a menubar object + */ + public MenuBar getMenuBar() { + return menubar; + } + + /** + * Returns the title of this menu entry + * + * @return a title string + */ + public String getTitle() { + return title; + } + + /** + * Adds a child menu entry to this menu. The title for this entry is + * taken from the Menu object argument. + * + * @param m + * another Menu object + */ + public void addChildMenu(Menu m) { + menubar.addItem(m.title, m.menubar); + children.add(m); + } + + /** + * Tests for the existence of a child menu by title at this level of the + * menu hierarchy + * + * @param title + * a title string + * @return true, if this menu has a direct child menu with the specified + * title, otherwise false + */ + public boolean hasChildMenu(String title) { + return getChildMenu(title) != null; + } + + /** + * Gets a reference to a child menu with a certain title, that is a + * direct child of this menu level. + * + * @param title + * a title string + * @return a Menu object with the specified title string, or null, if + * this menu doesn't have a direct child with the specified + * title. + */ + public Menu getChildMenu(String title) { + for (Menu m : children) { + if (m.title.equals(title)) { + return m; + } + } + return null; + } + + /** + * Adds a command item to the menu. When the entry is clicked, the + * command is executed. + * + * @param cmd + * a command object. + */ + public void addCommand(Command cmd) { + menubar.addItem(cmd.title, cmd.command); + items.add(cmd); + } + + /** + * Tests for the existence of a {@link Command} that is the direct child + * of this level of menu. + * + * @param title + * the command's title + * @return true, if this menu level includes a command item with the + * specified title. Otherwise false. + */ + public boolean hasCommand(String title) { + return getCommand(title) != null; + } + + /** + * Gets a reference to a {@link Command} item that is the direct child + * of this level of menu. + * + * @param title + * the command's title + * @return a command, if found in this menu level, otherwise null. + */ + public Command getCommand(String title) { + for (Command c : items) { + if (c.title.equals(title)) { + return c; + } + } + return null; + } + } + + /** + * Base level menu object, provides visible menu bar + */ + private final Menu menu; + private final T testedWidget; + + /** + * This constructor creates the basic menu bar and adds it to the top of the + * parent {@link DockLayoutPanel} + */ + protected PureGWTTestApplication(T widget) { + super(Unit.PX); + Panel menuPanel = new LayoutPanel(); + menu = new Menu(); + menuPanel.add(menu.getMenuBar()); + addNorth(menuPanel, 25); + testedWidget = widget; + } + + /** + * Connect an item to the menu structure + * + * @param cmd + * a scheduled command; see google's docs + * @param menupath + * path to the item + */ + public void addMenuCommand(String title, ScheduledCommand cmd, + String... menupath) { + Menu m = createMenuPath(menupath); + + m.addCommand(new Command(title, cmd)); + } + + /** + * Create a menu path, if one doesn't already exist, and return the last + * menu in the series. + * + * @param path + * a varargs list or array of strings describing a menu path, + * e.g. "File", "Recent", "User Files", which would result in the + * File menu having a submenu called "Recent" which would have a + * submenu called "User Files". + * @return the last Menu object specified by the path + */ + private Menu createMenuPath(String... path) { + Menu m = menu; + + for (String p : path) { + Menu sub = m.getChildMenu(p); + + if (sub == null) { + sub = new Menu(p); + m.addChildMenu(sub); + } + m = sub; + } + + return m; + } + + @Override + public Element getSubPartElement(String subPart) { + if (testedWidget instanceof SubPartAware) { + return ((SubPartAware) testedWidget).getSubPartElement(subPart); + } + return null; + } + + @Override + public String getSubPartName(Element subElement) { + if (testedWidget instanceof SubPartAware) { + return ((SubPartAware) testedWidget).getSubPartName(subElement); + } + return null; + } + + /** + * Gets the tested widget. + * + * @return tested widget + */ + public T getTestedWidget() { + return testedWidget; + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/server/grid/GridBasicClientFeatures.java new file mode 100644 index 0000000000..fb217dc232 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/grid/GridBasicClientFeatures.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2014 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.widgetset.server.grid; + +import com.vaadin.annotations.Widgetset; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.UI; + +/** + * Initializer shell for GridClientBasicFeatures test application + * + * @since + * @author Vaadin Ltd + */ +@Widgetset(TestingWidgetSet.NAME) +public class GridBasicClientFeatures extends UI { + + public class GridTestComponent extends AbstractComponent { + } + + @Override + protected void init(VaadinRequest request) { + setContent(new GridTestComponent()); + } + +} -- cgit v1.2.3 From 3626012f2ebf51c5433eb2671b5404e583a0f892 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Tue, 15 Jul 2014 14:36:01 +0300 Subject: Start rewrite of client-side Grid header/footer API (#13334) The old API is marked as deprecated and does not work anymore. Currently supported: * A single hard-coded header * Text captions TODO: * Footers * 0..n headers and footers * Column spanning * HTML content * Widget content * Component content * Sorting/Indicators * Server side API * Shared state handling Change-Id: I0448c36c8406807037b5e21e2db205a2ee24bc8a --- .../src/com/vaadin/client/ui/grid/ColumnGroup.java | 1 + .../com/vaadin/client/ui/grid/ColumnGroupRow.java | 1 + client/src/com/vaadin/client/ui/grid/Grid.java | 101 +++++++++-------- .../src/com/vaadin/client/ui/grid/GridHeader.java | 105 +++++++++++++++++ .../components/grid/GridSingleColumnTest.java | 5 + .../grid/basicfeatures/GridBasicFeaturesTest.java | 12 ++ .../grid/basicfeatures/GridHeaderTest.java | 36 ++++++ .../grid/basicfeatures/GridSortingTest.java | 5 + .../grid/basicfeatures/GridStructureTest.java | 125 ++------------------- 9 files changed, 228 insertions(+), 163 deletions(-) create mode 100644 client/src/com/vaadin/client/ui/grid/GridHeader.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/ColumnGroup.java b/client/src/com/vaadin/client/ui/grid/ColumnGroup.java index 13468a0d8e..af83730ceb 100644 --- a/client/src/com/vaadin/client/ui/grid/ColumnGroup.java +++ b/client/src/com/vaadin/client/ui/grid/ColumnGroup.java @@ -34,6 +34,7 @@ import com.vaadin.client.ui.grid.renderers.TextRenderer; * @author Vaadin Ltd * @see ColumnGroupRow#addGroup(ColumnGroup...) */ +@Deprecated public class ColumnGroup { /** diff --git a/client/src/com/vaadin/client/ui/grid/ColumnGroupRow.java b/client/src/com/vaadin/client/ui/grid/ColumnGroupRow.java index 3c621fdd15..bae6a732e6 100644 --- a/client/src/com/vaadin/client/ui/grid/ColumnGroupRow.java +++ b/client/src/com/vaadin/client/ui/grid/ColumnGroupRow.java @@ -33,6 +33,7 @@ import java.util.Set; * @since * @author Vaadin Ltd */ +@Deprecated public class ColumnGroupRow { /** diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 471f62cdeb..539c18f8c8 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -192,6 +192,8 @@ public class Grid extends Composite implements */ private Escalator escalator = GWT.create(Escalator.class); + private GridHeader header = GWT.create(GridHeader.class); + /** * List of columns in the grid. Order defines the visible order. */ @@ -206,16 +208,19 @@ public class Grid extends Composite implements /** * The column groups rows added to the grid */ + @Deprecated private final List> columnGroupRows = new ArrayList>(); /** * Are the headers for the columns visible */ + @Deprecated private boolean columnHeadersVisible = true; /** * Are the footers for the columns visible */ + @Deprecated private boolean columnFootersVisible = false; /** @@ -574,11 +579,13 @@ public class Grid extends Composite implements /** * The text displayed in the header of the column */ + @Deprecated private String header; /** * Text displayed in the column footer */ + @Deprecated private String footer; /** @@ -594,12 +601,14 @@ public class Grid extends Composite implements /** * Renderer for rendering the header cell value into the cell */ + @Deprecated private Renderer headerRenderer = new SortableColumnHeaderRenderer( new TextRenderer()); /** * Renderer for rendering the footer cell value into the cell */ + @Deprecated private Renderer footerRenderer = new TextRenderer(); private boolean sortable = false; @@ -661,6 +670,7 @@ public class Grid extends Composite implements * * @return the text displayed in the column caption */ + @Deprecated public String getHeaderCaption() { return header; } @@ -670,6 +680,7 @@ public class Grid extends Composite implements * * @return a renderer that renders header cells */ + @Deprecated public Renderer getHeaderRenderer() { return headerRenderer; } @@ -680,6 +691,7 @@ public class Grid extends Composite implements * @param renderer * The renderer to use for rendering header cells. */ + @Deprecated public void setHeaderRenderer(Renderer renderer) { if (renderer == null) { throw new IllegalArgumentException("Renderer cannot be null."); @@ -695,6 +707,7 @@ public class Grid extends Composite implements * * @return a renderer that renders footer cells */ + @Deprecated public Renderer getFooterRenderer() { return footerRenderer; } @@ -705,6 +718,7 @@ public class Grid extends Composite implements * @param renderer * The renderer to use for rendering footer cells. */ + @Deprecated public void setFooterRenderer(Renderer renderer) { if (renderer == null) { throw new IllegalArgumentException("Renderer cannot be null."); @@ -721,6 +735,7 @@ public class Grid extends Composite implements * @param caption * the text displayed in the column header */ + @Deprecated public void setHeaderCaption(String caption) { if (SharedUtil.equals(caption, header)) { return; @@ -739,6 +754,7 @@ public class Grid extends Composite implements * * @return The text displayed in the footer of the column */ + @Deprecated public String getFooterCaption() { return footer; } @@ -749,6 +765,7 @@ public class Grid extends Composite implements * @param caption * the text displayed in the footer of the column */ + @Deprecated public void setFooterCaption(String caption) { if (SharedUtil.equals(caption, footer)) { return; @@ -898,6 +915,7 @@ public class Grid extends Composite implements /** * Base class for header / footer escalator updater */ + @Deprecated protected abstract class HeaderFooterEscalatorUpdater implements EscalatorUpdater { @@ -1125,36 +1143,44 @@ public class Grid extends Composite implements * @return the updater that updates the data in the escalator. */ private EscalatorUpdater createHeaderUpdater() { - return new HeaderFooterEscalatorUpdater(escalator.getHeader(), true) { + return new EscalatorUpdater() { @Override - public boolean isRowVisible(ColumnGroupRow row) { - return row.isHeaderVisible(); - } + public void update(Row row, Iterable cellsToUpdate) { + GridHeader.HeaderRow headerRow = header.getRow(row.getRow()); - @Override - public String getGroupValue(ColumnGroup group) { - return group.getHeaderCaption(); + int colIndex = -1; + for (FlyweightCell cell : cellsToUpdate) { + if (colIndex == -1) { + colIndex = cell.getColumn(); + } + while (!columns.get(colIndex).isVisible()) { + colIndex++; + } + + headerRow.getRenderer().render(cell, + headerRow.getCell(colIndex).getText()); + + colIndex++; + } } @Override - public String getColumnValue(GridColumn column) { - return column.getHeaderCaption(); + public void preAttach(Row row, Iterable cellsToAttach) { } @Override - public boolean firstRowIsVisible() { - return isColumnHeadersVisible(); + public void postAttach(Row row, + Iterable attachedCells) { } @Override - public Renderer getRenderer(GridColumn column) { - return column.getHeaderRenderer(); + public void preDetach(Row row, Iterable cellsToDetach) { } @Override - public Renderer getGroupRenderer(ColumnGroup group) { - return group.getHeaderRenderer(); + public void postDetach(Row row, + Iterable detachedCells) { } }; } @@ -1306,38 +1332,7 @@ public class Grid extends Composite implements * @return the updater that updates the data in the escalator. */ private EscalatorUpdater createFooterUpdater() { - return new HeaderFooterEscalatorUpdater(escalator.getFooter(), false) { - - @Override - public boolean isRowVisible(ColumnGroupRow row) { - return row.isFooterVisible(); - } - - @Override - public String getGroupValue(ColumnGroup group) { - return group.getFooterCaption(); - } - - @Override - public String getColumnValue(GridColumn column) { - return column.getFooterCaption(); - } - - @Override - public boolean firstRowIsVisible() { - return isColumnFootersVisible(); - } - - @Override - public Renderer getRenderer(GridColumn column) { - return column.getFooterRenderer(); - } - - @Override - public Renderer getGroupRenderer(ColumnGroup group) { - return group.getFooterRenderer(); - } - }; + return EscalatorUpdater.NULL; } /** @@ -1437,6 +1432,8 @@ public class Grid extends Composite implements // Register column with grid columns.add(index, column); + header.addColumn(column, index); + // Register this grid instance with the column ((AbstractGridColumn) column).setGrid(this); @@ -1537,6 +1534,7 @@ public class Grid extends Composite implements int columnIndex = columns.indexOf(column); int visibleIndex = findVisibleColumnIndex(column); columns.remove(columnIndex); + header.removeColumn(columnIndex); // de-register column with grid ((AbstractGridColumn) column).setGrid(null); @@ -1618,6 +1616,7 @@ public class Grid extends Composite implements * @param visible * true if header rows should be visible */ + @Deprecated public void setColumnHeadersVisible(boolean visible) { if (visible == isColumnHeadersVisible()) { return; @@ -1631,6 +1630,7 @@ public class Grid extends Composite implements * * @return true if they are visible */ + @Deprecated public boolean isColumnHeadersVisible() { return columnHeadersVisible; } @@ -1664,6 +1664,7 @@ public class Grid extends Composite implements * @param visible * true if the footer row should be visible */ + @Deprecated public void setColumnFootersVisible(boolean visible) { if (visible == isColumnFootersVisible()) { return; @@ -1678,6 +1679,7 @@ public class Grid extends Composite implements * @return true if they are visible * */ + @Deprecated public boolean isColumnFootersVisible() { return columnFootersVisible; } @@ -1709,6 +1711,7 @@ public class Grid extends Composite implements * * @return a column group row instance you can use to add column groups */ + @Deprecated public ColumnGroupRow addColumnGroupRow() { ColumnGroupRow row = new ColumnGroupRow(this); columnGroupRows.add(row); @@ -1727,6 +1730,7 @@ public class Grid extends Composite implements * the index where the column group row should be added * @return a column group row instance you can use to add column groups */ + @Deprecated public ColumnGroupRow addColumnGroupRow(int rowIndex) { ColumnGroupRow row = new ColumnGroupRow(this); columnGroupRows.add(rowIndex, row); @@ -1741,6 +1745,7 @@ public class Grid extends Composite implements * @param row * The row to remove */ + @Deprecated public void removeColumnGroupRow(ColumnGroupRow row) { columnGroupRows.remove(row); refreshHeader(); @@ -1753,6 +1758,7 @@ public class Grid extends Composite implements * @return a unmodifiable list of column group rows * */ + @Deprecated public List> getColumnGroupRows() { return Collections.unmodifiableList(new ArrayList>( columnGroupRows)); @@ -1768,6 +1774,7 @@ public class Grid extends Composite implements * @return A column group for the row and column or null if not * found. */ + @Deprecated private ColumnGroup getGroupForColumn(ColumnGroupRow row, GridColumn column) { for (ColumnGroup group : row.getGroups()) { diff --git a/client/src/com/vaadin/client/ui/grid/GridHeader.java b/client/src/com/vaadin/client/ui/grid/GridHeader.java new file mode 100644 index 0000000000..023973c511 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/GridHeader.java @@ -0,0 +1,105 @@ +/* + * Copyright 2000-2014 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.client.ui.grid; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.vaadin.client.ui.grid.renderers.TextRenderer; + +/** + * Represents the header section of a Grid. A header consists of a single header + * row containing a header cell for each column. Each cell has a simple textual + * caption. + * + * TODO Arbitrary number of header rows (zero included) + * + * TODO Merging header cells + * + * TODO "Default" row with sorting + * + * TODO Widgets in cells + * + * TODO HTML in cells + * + * @since + * @author Vaadin Ltd + */ +public class GridHeader { + + /** + * A single row in a grid header section. + * + * @since + * @author Vaadin Ltd + */ + public static class HeaderRow { + + private List cells = new ArrayList(); + + private Renderer renderer = new TextRenderer(); + + public HeaderCell getCell(int index) { + return cells.get(index); + } + + protected void addCell(int index) { + cells.add(index, new HeaderCell()); + } + + protected void removeCell(int index) { + cells.remove(index); + } + + protected Renderer getRenderer() { + return renderer; + } + } + + /** + * A single cell in a grid header row. Has a textual caption. + * + * @since + * @author Vaadin Ltd + */ + public static class HeaderCell { + + private String text = ""; + + public void setText(String text) { + this.text = text; + } + + public String getText() { + return text; + } + } + + private List rows = Arrays.asList(new HeaderRow()); + + public HeaderRow getRow(int index) { + return rows.get(index); + } + + protected void addColumn(GridColumn column, int index) { + getRow(0).addCell(index); + } + + protected void removeColumn(int index) { + getRow(0).removeCell(index); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java index 10d2c8592a..2e062f36c6 100644 --- a/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java @@ -18,6 +18,7 @@ package com.vaadin.tests.components.grid; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; +import org.junit.Ignore; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; @@ -28,7 +29,11 @@ import com.vaadin.tests.tb3.MultiBrowserTest; @TestCategory("grid") public class GridSingleColumnTest extends MultiBrowserTest { + /* + * TODO unignore once column header captions are reimplemented + */ @Test + @Ignore public void headerIsVisible() { openTestURL(); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java index 79501f50ac..a3c62e0303 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java @@ -15,12 +15,16 @@ */ package com.vaadin.tests.components.grid.basicfeatures; +import java.util.ArrayList; +import java.util.List; + import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; +import com.vaadin.testbench.TestBenchElement; import com.vaadin.tests.annotations.TestCategory; import com.vaadin.tests.components.grid.GridElement; import com.vaadin.tests.tb3.MultiBrowserTest; @@ -59,6 +63,14 @@ public abstract class GridBasicFeaturesTest extends MultiBrowserTest { getGridVerticalScrollbar()); } + protected List getGridHeaderRowCells() { + List headerCells = new ArrayList(); + for (int i = 0; i < getGridElement().getHeaderCount(); ++i) { + headerCells.addAll(getGridElement().getHeaderCells(i)); + } + return headerCells; + } + private Object executeScript(String script, WebElement element) { final WebDriver driver = getDriver(); if (driver instanceof JavascriptExecutor) { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java new file mode 100644 index 0000000000..dfbb1679b0 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; + +import com.vaadin.testbench.TestBenchElement; + +public class GridHeaderTest extends GridBasicClientFeaturesTest { + + @Test + public void testHeaderVisible() throws Exception { + openTestURL(); + + // Column headers should be visible + List cells = getGridHeaderRowCells(); + assertEquals(GridBasicFeatures.COLUMNS, cells.size()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java index 820070f933..f706c1791d 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java @@ -21,13 +21,18 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; +import org.junit.Ignore; import org.junit.Test; import com.vaadin.tests.components.grid.GridElement; public class GridSortingTest extends GridBasicFeaturesTest { + /* + * TODO unignore once column header captions are reimplemented + */ @Test + @Ignore public void testProgrammaticSorting() throws IOException { openTestURL(); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java index 17438fd4bb..94f04e10a2 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java @@ -20,117 +20,22 @@ import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.util.ArrayList; import java.util.List; +import org.junit.Ignore; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import com.vaadin.testbench.TestBenchElement; -import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; -import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; public class GridStructureTest extends GridBasicFeaturesTest { + /* + * TODO unignore once column header captions are reimplemented + */ @Test - public void testColumnHeaderCaptions() throws Exception { - openTestURL(); - - // Column headers should be visible - List cells = getGridHeaderRowCells(); - assertEquals(GridBasicFeatures.COLUMNS, cells.size()); - assertEquals("Column0", cells.get(0).getText()); - assertEquals("Column1", cells.get(1).getText()); - assertEquals("Column2", cells.get(2).getText()); - } - - @Test - public void testColumnFooterCaptions() throws Exception { - openTestURL(); - - // footer row should by default be hidden - List cells = getGridFooterRowCells(); - assertEquals(0, cells.size()); - - // Open footer row - selectMenuPath("Component", "Footers", "Visible"); - - // Footers should now be visible - cells = getGridFooterRowCells(); - assertEquals(GridBasicFeatures.COLUMNS, cells.size()); - assertEquals("Footer 0", cells.get(0).getText()); - assertEquals("Footer 1", cells.get(1).getText()); - assertEquals("Footer 2", cells.get(2).getText()); - } - - @Test - public void testColumnGroupHeaders() throws Exception { - openTestURL(); - - // Hide column headers for this test - selectMenuPath("Component", "Headers", "Visible"); - - List cells = getGridHeaderRowCells(); - - // header row should be empty - assertEquals(0, cells.size()); - - // add a group row - selectMenuPath("Component", "Column groups", "Add group row"); - - // Empty group row cells should be present - cells = getGridHeaderRowCells(); - assertEquals(GridBasicFeatures.COLUMNS, cells.size()); - - // Group columns 0 & 1 - selectMenuPath("Component", "Column groups", "Column group row 1", - "Group Column 0 & 1"); - - cells = getGridHeaderRowCells(); - assertEquals("Column 0 & 1", cells.get(0).getText()); - } - - @Test - public void testColumnGroupFooters() throws Exception { - openTestURL(); - - // add a group row - selectMenuPath("Component", "Column groups", "Add group row"); - - // Set footer visible - selectMenuPath("Component", "Column groups", "Column group row 1", - "Footer Visible"); - - // Group columns 0 & 1 - selectMenuPath("Component", "Column groups", "Column group row 1", - "Group Column 0 & 1"); - - List cells = getGridFooterRowCells(); - assertEquals("Column 0 & 1", cells.get(0).getText()); - } - - @Test - public void testGroupingSameColumnsOnRowThrowsException() throws Exception { - openTestURL(); - - // add a group row - selectMenuPath("Component", "Column groups", "Add group row"); - - // Group columns 0 & 1 - selectMenuPath("Component", "Column groups", "Column group row 1", - "Group Column 0 & 1"); - - // Group columns 1 & 2 shoud fail - selectMenuPath("Component", "Column groups", "Column group row 1", - "Group Column 1 & 2"); - - assertTrue(getLogRow(0) - .contains( - "Exception occured, java.lang.IllegalArgumentExceptionColumn Column1 already belongs to another group.")); - } - - @Test + @Ignore public void testHidingColumn() throws Exception { openTestURL(); @@ -146,7 +51,11 @@ public class GridStructureTest extends GridBasicFeaturesTest { assertEquals("Column1", cells.get(0).getText()); } + /* + * TODO unignore once column header captions are reimplemented + */ @Test + @Ignore public void testRemovingColumn() throws Exception { openTestURL(); @@ -328,20 +237,4 @@ public class GridStructureTest extends GridBasicFeaturesTest { private WebElement getTableWrapper() { return getGridElement().findElement(By.xpath("./div[3]")); } - - private List getGridHeaderRowCells() { - List headerCells = new ArrayList(); - for (int i = 0; i < getGridElement().getHeaderCount(); ++i) { - headerCells.addAll(getGridElement().getHeaderCells(i)); - } - return headerCells; - } - - private List getGridFooterRowCells() { - List footerCells = new ArrayList(); - for (int i = 0; i < getGridElement().getFooterCount(); ++i) { - footerCells.addAll(getGridElement().getFooterCells(i)); - } - return footerCells; - } } -- cgit v1.2.3 From a9c124cc19b4e1bf1c8736e209b8e066a002da6f Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Wed, 16 Jul 2014 15:44:27 +0300 Subject: Implement active cell keyboard navigation for Grid (#13334) Change-Id: I38b759f24fa35432d5bc330b06a64caaa7ef3c9e --- client/src/com/vaadin/client/ui/grid/Grid.java | 297 ++++++++++++++++----- .../basicfeatures/GridKeyboardNavigationTest.java | 56 +++- 2 files changed, 292 insertions(+), 61 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 539c18f8c8..5ef94a296c 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -32,6 +32,7 @@ import com.google.gwt.dom.client.EventTarget; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.TableCellElement; import com.google.gwt.dom.client.Touch; +import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.touch.client.Point; import com.google.gwt.user.client.DOM; @@ -100,6 +101,222 @@ import com.vaadin.shared.util.SharedUtil; public class Grid extends Composite implements HasSelectionChangeHandlers, SubPartAware { + private class ActiveCellHandler { + + private RowContainer container = escalator.getBody(); + private int activeRow = 0; + private int activeColumn = 0; + private Element cellWithActiveStyle = null; + private Element rowWithActiveStyle = null; + + public ActiveCellHandler() { + sinkEvents(getNavigationEvents()); + } + + /** + * Sets style names for given cell when needed. + */ + public void updateActiveCellStyle(FlyweightCell cell) { + int cellRow = cell.getRow(); + int cellColumn = cell.getColumn(); + RowContainer cellContainer = escalator.findRowContainer(cell + .getElement()); + + if (cellContainer == container) { + // Cell is in the current container + if (cellRow == activeRow && cellColumn == activeColumn) { + if (cellWithActiveStyle != cell.getElement()) { + // Cell is correct but it does not have active style + if (cellWithActiveStyle != null) { + // Remove old active style + setStyleName(cellWithActiveStyle, + cellActiveStyleName, false); + } + cellWithActiveStyle = cell.getElement(); + // Add active style to correct cell. + setStyleName(cellWithActiveStyle, cellActiveStyleName, + true); + } + } else if (cellWithActiveStyle == cell.getElement()) { + // Due to escalator reusing cells, a new cell has the same + // element but is not the active cell. + setStyleName(cellWithActiveStyle, cellActiveStyleName, + false); + cellWithActiveStyle = null; + } + } + + if (cellContainer == escalator.getHeader() + || cellContainer == escalator.getFooter()) { + // Correct header and footer column also needs highlighting + setStyleName(cell.getElement(), headerFooterActiveStyleName, + cellColumn == activeColumn); + } + } + + /** + * Sets active row style name for given row if needed. + * + * @param row + * a row object + */ + public void updateActiveRowStyle(Row row) { + if (activeRow == row.getRow() && container == escalator.getBody()) { + if (row.getElement() != rowWithActiveStyle) { + // Row should have active style but does not have it. + if (rowWithActiveStyle != null) { + setStyleName(rowWithActiveStyle, rowActiveStyleName, + false); + } + rowWithActiveStyle = row.getElement(); + setStyleName(rowWithActiveStyle, rowActiveStyleName, true); + } + } else if (rowWithActiveStyle == row.getElement() + || (container != escalator.getBody() && rowWithActiveStyle != null)) { + // Remove active style. + setStyleName(rowWithActiveStyle, rowActiveStyleName, false); + rowWithActiveStyle = null; + } + } + + /** + * Sets currently active cell to a cell in given container with given + * indices. + * + * @param row + * new active row + * @param column + * new active column + * @param container + * new container + */ + private void setActiveCell(int row, int column, RowContainer container) { + if (row == activeRow && column == activeColumn + && container == this.container) { + return; + } + + int oldRow = activeRow; + int oldColumn = activeColumn; + activeRow = row; + activeColumn = column; + + if (container == escalator.getBody()) { + scrollToRow(activeRow); + } + escalator.scrollToColumn(activeColumn, ScrollDestination.ANY, 10); + + if (this.container == container) { + if (container != escalator.getBody()) { + if (oldColumn == activeColumn && oldRow != activeRow) { + refreshRow(oldRow); + } else if (oldColumn != activeColumn) { + refreshHeader(); + refreshFooter(); + } + } else { + if (oldRow != activeRow) { + refreshRow(oldRow); + } + + if (oldColumn != activeColumn) { + refreshHeader(); + refreshFooter(); + } + } + } else { + RowContainer oldContainer = this.container; + this.container = container; + + if (oldColumn != activeColumn) { + refreshHeader(); + refreshFooter(); + if (oldContainer == escalator.getBody()) { + oldContainer.refreshRows(oldRow, 1); + } + } else { + oldContainer.refreshRows(oldRow, 1); + } + } + refreshRow(activeRow); + } + + /** + * Sets currently active cell used for keyboard navigation. Note that + * active cell is not JavaScript {@code document.activeElement}. + * + * @param cell + * a cell object + */ + public void setActiveCell(Cell cell) { + setActiveCell(cell.getRow(), cell.getColumn(), + escalator.findRowContainer(cell.getElement())); + } + + /** + * Gets list of events that can be used for active cell navigation. + * + * @return list of navigation related event types + */ + public Collection getNavigationEvents() { + return Arrays.asList(BrowserEvents.KEYDOWN, BrowserEvents.CLICK); + } + + /** + * Handle events that can change the currently active cell. + */ + public void handleNavigationEvent(Event event, Cell cell) { + if (event.getType().equals(BrowserEvents.CLICK) + && event.getButton() == NativeEvent.BUTTON_LEFT + && cell != null) { + setActiveCell(cell); + getElement().focus(); + } else if (event.getType().equals(BrowserEvents.KEYDOWN)) { + int keyCode = event.getKeyCode(); + if (keyCode == 0) { + keyCode = event.getCharCode(); + } + int newRow = activeRow; + int newColumn = activeColumn; + RowContainer newContainer = container; + + switch (event.getKeyCode()) { + case KeyCodes.KEY_DOWN: + newRow += 1; + break; + case KeyCodes.KEY_UP: + newRow -= 1; + break; + case KeyCodes.KEY_RIGHT: + newColumn += 1; + break; + case KeyCodes.KEY_LEFT: + newColumn -= 1; + break; + } + + if (newRow < 0) { + newRow = 0; + } else if (newRow >= container.getRowCount()) { + newRow = container.getRowCount() - 1; + } + + if (newColumn < 0) { + newColumn = 0; + } else if (newColumn >= getColumnCount()) { + newColumn = getColumnCount() - 1; + } + + setActiveCell(newRow, newColumn, newContainer); + } + + } + + private void refreshRow(int row) { + container.refreshRows(row, 1); + } + } + private class SelectionColumn extends GridColumn { private boolean initDone = false; @@ -242,18 +459,14 @@ public class Grid extends Composite implements private String rowSelectedStyleName; private String cellActiveStyleName; private String rowActiveStyleName; - private String headerFooterFocusedStyleName; + private String headerFooterActiveStyleName; /** * Current selection model. */ private SelectionModel selectionModel; - /** - * Current active cell. - */ - private int activeRow = 0; - private int activeColumn = 0; + private final ActiveCellHandler activeCellHandler; /** * Enumeration for easy setting of selection mode. @@ -1017,9 +1230,7 @@ public class Grid extends Composite implements .render(cell, getColumnValue(column)); } - setStyleName(cell.getElement(), - headerFooterFocusedStyleName, - activeColumn == cell.getColumn()); + activeCellHandler.updateActiveCellStyle(cell); } } else if (columnGroupRows.size() > 0) { @@ -1058,9 +1269,7 @@ public class Grid extends Composite implements cellElement.setInnerHTML(null); cell.setColSpan(1); - setStyleName(cell.getElement(), - headerFooterFocusedStyleName, - activeColumn == cell.getColumn()); + activeCellHandler.updateActiveCellStyle(cell); } } } @@ -1088,6 +1297,8 @@ public class Grid extends Composite implements */ public Grid() { initWidget(escalator); + getElement().setTabIndex(0); + activeCellHandler = new ActiveCellHandler(); setStylePrimaryName("v-grid"); @@ -1098,7 +1309,6 @@ public class Grid extends Composite implements refreshHeader(); refreshFooter(); - sinkEvents(Event.ONMOUSEDOWN); setSelectionMode(SelectionMode.SINGLE); escalator @@ -1132,7 +1342,7 @@ public class Grid extends Composite implements rowHasDataStyleName = getStylePrimaryName() + "-row-has-data"; rowSelectedStyleName = getStylePrimaryName() + "-row-selected"; cellActiveStyleName = getStylePrimaryName() + "-cell-active"; - headerFooterFocusedStyleName = getStylePrimaryName() + "-header-active"; + headerFooterActiveStyleName = getStylePrimaryName() + "-header-active"; rowActiveStyleName = getStylePrimaryName() + "-row-active"; } @@ -1151,6 +1361,8 @@ public class Grid extends Composite implements int colIndex = -1; for (FlyweightCell cell : cellsToUpdate) { + activeCellHandler.updateActiveCellStyle(cell); + if (colIndex == -1) { colIndex = cell.getColumn(); } @@ -1244,8 +1456,7 @@ public class Grid extends Composite implements setStyleName(rowElement, rowSelectedStyleName, false); } - setStyleName(rowElement, rowActiveStyleName, - rowIndex == activeRow); + activeCellHandler.updateActiveRowStyle(row); for (FlyweightCell cell : cellsToUpdate) { GridColumn column = getColumnFromVisibleIndex(cell @@ -1254,8 +1465,7 @@ public class Grid extends Composite implements assert column != null : "Column was not found from cell (" + cell.getColumn() + "," + cell.getRow() + ")"; - setStyleName(cell.getElement(), cellActiveStyleName, - isActiveCell(cell)); + activeCellHandler.updateActiveCellStyle(cell); Renderer renderer = column.getRenderer(); @@ -1288,11 +1498,6 @@ public class Grid extends Composite implements } } - private boolean isActiveCell(FlyweightCell cell) { - return cell.getRow() == activeRow - && cell.getColumn() == activeColumn; - } - @Override public void preDetach(Row row, Iterable cellsToDetach) { for (FlyweightCell cell : cellsToDetach) { @@ -2122,8 +2327,9 @@ public class Grid extends Composite implements if (Element.is(target)) { Element e = Element.as(target); RowContainer container = escalator.findRowContainer(e); + Cell cell = null; if (container != null) { - Cell cell = container.getCell(e); + cell = container.getCell(e); if (cell != null) { GridColumn gridColumn = columns.get(cell.getColumn()); @@ -2145,14 +2351,13 @@ public class Grid extends Composite implements } } } - - // TODO: Support active cells in Headers and Footers, - // 14.07.2014, Teemu Suo-Anttila - if (event.getTypeInt() == Event.ONMOUSEDOWN) { - setActiveCell(cell); - } } } + + if (activeCellHandler.getNavigationEvents().contains( + event.getType())) { + activeCellHandler.handleNavigationEvent(event, cell); + } } } @@ -2255,13 +2460,13 @@ public class Grid extends Composite implements if (this.selectColumnRenderer != null) { removeColumnSkipSelectionColumnCheck(selectionColumn); - --activeColumn; + --activeCellHandler.activeColumn; } this.selectColumnRenderer = selectColumnRenderer; if (selectColumnRenderer != null) { - ++activeColumn; + ++activeCellHandler.activeColumn; selectionColumn = new SelectionColumn(selectColumnRenderer); // FIXME: this needs to be done elsewhere, requires design... @@ -2508,32 +2713,4 @@ public class Grid extends Composite implements fireEvent(new SortEvent(this, Collections.unmodifiableList(sortOrder))); } - - /** - * Set currently active cell used for keyboard navigation. Note that active - * cell is not {@code activeElement}. - * - * @param cell - * a cell object - */ - public void setActiveCell(Cell cell) { - int oldRow = activeRow; - int oldColumn = activeColumn; - - activeRow = cell.getRow(); - activeColumn = cell.getColumn(); - - if (oldRow != activeRow) { - escalator.getBody().refreshRows(oldRow, 1); - escalator.getBody().refreshRows(activeRow, 1); - } - - if (oldColumn != activeColumn) { - if (oldRow == activeRow) { - escalator.getBody().refreshRows(oldRow, 1); - } - refreshHeader(); - refreshFooter(); - } - } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java index a297187b62..465fdedad6 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java @@ -18,7 +18,13 @@ package com.vaadin.tests.components.grid.basicfeatures; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.io.IOException; + +import org.junit.Ignore; import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; import com.vaadin.tests.components.grid.GridElement; @@ -46,7 +52,55 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { assertTrue("Body cell 0, 0 is not active on init.", grid.getCell(0, 0) .isActive()); grid.getHeaderCell(0, 3).click(); - assertTrue("Body cell 0, 0 is not active after click on header.", grid + assertFalse("Body cell 0, 0 is active after click on header.", grid .getCell(0, 0).isActive()); + assertTrue("Header cell 0, 3 is not active after click on header.", + grid.getHeaderCell(0, 3).isActive()); + } + + @Test + public void testSimpleKeyboardNavigation() { + openTestURL(); + + GridElement grid = getGridElement(); + grid.getCell(0, 0).click(); + + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); + assertTrue("Body cell 1, 0 is not active after keyboard navigation.", + grid.getCell(1, 0).isActive()); + + new Actions(getDriver()).sendKeys(Keys.ARROW_RIGHT).perform(); + assertTrue("Body cell 1, 1 is not active after keyboard navigation.", + grid.getCell(1, 1).isActive()); + + Actions manyClicks = new Actions(getDriver()); + int i; + for (i = 1; i < 40; ++i) { + manyClicks.sendKeys(Keys.ARROW_DOWN); + } + manyClicks.perform(); + + assertFalse("Grid has not scrolled with active cell", + isElementPresent(By.xpath("//td[text() = '(0, 0)']"))); + assertTrue("Active cell is not visible", + isElementPresent(By.xpath("//td[text() = '(" + i + ", 0)']"))); + assertTrue("Body cell" + i + ", 1 is not active", grid.getCell(i, 1) + .isActive()); + } + + @Test + @Ignore("This feature is still on the TODO list") + public void testNavigateFromHeaderToBody() throws IOException { + openTestURL(); + + GridElement grid = getGridElement(); + grid.scrollToRow(300); + grid.getHeaderCell(0, 7).click(); + + assertTrue("Header cell is not active.", grid.getHeaderCell(0, 7) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); + assertTrue("Body cell 282, 7 is not active", grid.getCell(282, 7) + .isActive()); } } -- cgit v1.2.3 From f49e1227ae149833e50188fd21a0d6461af0c25a Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Tue, 15 Jul 2014 19:35:31 +0300 Subject: Client-side Grid header/footer rewrite: add simple footer support (#13334) Currently supported: * A single-row hard-coded header * A zero-row hard-coded footer * Text captions TODO: * 0..n headers and footers * Column spanning * HTML content * Widget content * Component content * Sorting/Indicators * Server side API * Shared state handling Change-Id: Ic85051b16ef77791f1fdae78fca47a0729e1c43d --- client/src/com/vaadin/client/ui/grid/Grid.java | 141 ++++++++++++--------- .../src/com/vaadin/client/ui/grid/GridFooter.java | 66 ++++++++++ .../src/com/vaadin/client/ui/grid/GridHeader.java | 63 ++------- .../vaadin/client/ui/grid/GridStaticSection.java | 141 +++++++++++++++++++++ .../grid/basicfeatures/GridBasicFeaturesTest.java | 8 ++ .../grid/basicfeatures/GridFooterTest.java | 36 ++++++ .../grid/basicfeatures/GridHeaderTest.java | 47 ++++++- .../client/grid/GridBasicClientFeatures.java | 41 +++++- 8 files changed, 427 insertions(+), 116 deletions(-) create mode 100644 client/src/com/vaadin/client/ui/grid/GridFooter.java create mode 100644 client/src/com/vaadin/client/ui/grid/GridStaticSection.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 5ef94a296c..1edd70daac 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -45,6 +45,7 @@ import com.vaadin.client.Util; import com.vaadin.client.data.DataChangeHandler; import com.vaadin.client.data.DataSource; import com.vaadin.client.ui.SubPartAware; +import com.vaadin.client.ui.grid.GridStaticSection.StaticRow; import com.vaadin.client.ui.grid.renderers.ComplexRenderer; import com.vaadin.client.ui.grid.renderers.TextRenderer; import com.vaadin.client.ui.grid.renderers.WidgetRenderer; @@ -409,7 +410,9 @@ public class Grid extends Composite implements */ private Escalator escalator = GWT.create(Escalator.class); - private GridHeader header = GWT.create(GridHeader.class); + private final GridHeader header = GWT.create(GridHeader.class); + + private final GridFooter footer = GWT.create(GridFooter.class); /** * List of columns in the grid. Order defines the visible order. @@ -1292,6 +1295,57 @@ public class Grid extends Composite implements } } + protected class StaticSectionUpdater implements EscalatorUpdater { + + private GridStaticSection section; + + public StaticSectionUpdater(GridStaticSection section) { + super(); + this.section = section; + } + + @Override + public void update(Row row, Iterable cellsToUpdate) { + StaticRow gridRow = section.getRow(row.getRow()); + + final List columnIndices = getVisibleColumnIndices(); + + for (FlyweightCell cell : cellsToUpdate) { + int index = columnIndices.get(cell.getColumn()); + gridRow.getRenderer().render(cell, + gridRow.getCell(index).getText()); + + activeCellHandler.updateActiveCellStyle(cell); + } + } + + @Override + public void preAttach(Row row, Iterable cellsToAttach) { + } + + @Override + public void postAttach(Row row, Iterable attachedCells) { + } + + @Override + public void preDetach(Row row, Iterable cellsToDetach) { + } + + @Override + public void postDetach(Row row, Iterable detachedCells) { + } + + private List getVisibleColumnIndices() { + List indices = new ArrayList(getColumnCount()); + for (int i = 0; i < getColumnCount(); i++) { + if (getColumn(i).isVisible()) { + indices.add(i); + } + } + return indices; + } + }; + /** * Creates a new instance. */ @@ -1353,48 +1407,7 @@ public class Grid extends Composite implements * @return the updater that updates the data in the escalator. */ private EscalatorUpdater createHeaderUpdater() { - return new EscalatorUpdater() { - - @Override - public void update(Row row, Iterable cellsToUpdate) { - GridHeader.HeaderRow headerRow = header.getRow(row.getRow()); - - int colIndex = -1; - for (FlyweightCell cell : cellsToUpdate) { - activeCellHandler.updateActiveCellStyle(cell); - - if (colIndex == -1) { - colIndex = cell.getColumn(); - } - while (!columns.get(colIndex).isVisible()) { - colIndex++; - } - - headerRow.getRenderer().render(cell, - headerRow.getCell(colIndex).getText()); - - colIndex++; - } - } - - @Override - public void preAttach(Row row, Iterable cellsToAttach) { - } - - @Override - public void postAttach(Row row, - Iterable attachedCells) { - } - - @Override - public void preDetach(Row row, Iterable cellsToDetach) { - } - - @Override - public void postDetach(Row row, - Iterable detachedCells) { - } - }; + return new StaticSectionUpdater(header); } private EscalatorUpdater createBodyUpdater() { @@ -1537,7 +1550,7 @@ public class Grid extends Composite implements * @return the updater that updates the data in the escalator. */ private EscalatorUpdater createFooterUpdater() { - return EscalatorUpdater.NULL; + return new StaticSectionUpdater(footer); } /** @@ -1552,18 +1565,10 @@ public class Grid extends Composite implements * the footer */ private void refreshRowContainer(RowContainer rows, - boolean firstRowIsVisible, boolean isHeader) { - - // Count needed rows - int totalRows = firstRowIsVisible ? 1 : 0; - for (ColumnGroupRow row : columnGroupRows) { - if (isHeader ? row.isHeaderVisible() : row.isFooterVisible()) { - totalRows++; - } - } + GridStaticSection section) { // Add or Remove rows on demand - int rowDiff = totalRows - rows.getRowCount(); + int rowDiff = section.getRows().size() - rows.getRowCount(); if (rowDiff > 0) { rows.insertRows(0, rowDiff); } else if (rowDiff < 0) { @@ -1580,8 +1585,7 @@ public class Grid extends Composite implements * Refreshes all header rows */ void refreshHeader() { - refreshRowContainer(escalator.getHeader(), isColumnHeadersVisible(), - true); + refreshRowContainer(escalator.getHeader(), header); } /** @@ -1595,8 +1599,7 @@ public class Grid extends Composite implements * Refreshes all footer rows */ void refreshFooter() { - refreshRowContainer(escalator.getFooter(), isColumnFootersVisible(), - false); + refreshRowContainer(escalator.getFooter(), footer); } /** @@ -1638,6 +1641,7 @@ public class Grid extends Composite implements columns.add(index, column); header.addColumn(column, index); + footer.addColumn(column, index); // Register this grid instance with the column ((AbstractGridColumn) column).setGrid(this); @@ -1739,7 +1743,9 @@ public class Grid extends Composite implements int columnIndex = columns.indexOf(column); int visibleIndex = findVisibleColumnIndex(column); columns.remove(columnIndex); + header.removeColumn(columnIndex); + footer.removeColumn(columnIndex); // de-register column with grid ((AbstractGridColumn) column).setGrid(null); @@ -1991,6 +1997,25 @@ public class Grid extends Composite implements return null; } + /** + * Returns the header section of this grid. The default header contains a + * single row displaying the column captions. + * + * @return the header + */ + public GridHeader getHeader() { + return header; + } + + /** + * Returns the footer section of this grid. The default footer is empty. + * + * @return the footer + */ + public GridFooter getFooter() { + return footer; + } + /** * {@inheritDoc} *

diff --git a/client/src/com/vaadin/client/ui/grid/GridFooter.java b/client/src/com/vaadin/client/ui/grid/GridFooter.java new file mode 100644 index 0000000000..dc0f0054a2 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/GridFooter.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2014 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.client.ui.grid; + +import java.util.Collections; +import java.util.List; + +/** + * Represents the footer section of a Grid. The footer is always empty. + * + * TODO Arbitrary number of footer rows (zero by default) + * + * TODO Merging footer cells + * + * TODO Widgets in cells + * + * TODO HTML in cells + * + * @since + * @author Vaadin Ltd + */ +public class GridFooter extends GridStaticSection { + + /** + * A single row in a grid Footer section. + * + */ + public static class FooterRow extends + GridStaticSection.StaticRow { + + @Override + protected FooterCell createCell() { + return new FooterCell(); + } + } + + /** + * A single cell in a grid Footer row. Has a textual caption. + * + */ + public static class FooterCell extends GridStaticSection.StaticCell { + } + + @Override + protected FooterRow createRow() { + return new FooterRow(); + } + + @Override + protected List createRowList() { + return Collections.emptyList(); + } +} diff --git a/client/src/com/vaadin/client/ui/grid/GridHeader.java b/client/src/com/vaadin/client/ui/grid/GridHeader.java index 023973c511..c23c848b8d 100644 --- a/client/src/com/vaadin/client/ui/grid/GridHeader.java +++ b/client/src/com/vaadin/client/ui/grid/GridHeader.java @@ -15,18 +15,15 @@ */ package com.vaadin.client.ui.grid; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import com.vaadin.client.ui.grid.renderers.TextRenderer; - /** * Represents the header section of a Grid. A header consists of a single header * row containing a header cell for each column. Each cell has a simple textual * caption. * - * TODO Arbitrary number of header rows (zero included) + * TODO Arbitrary number of header rows (zero included, one by default) * * TODO Merging header cells * @@ -39,67 +36,35 @@ import com.vaadin.client.ui.grid.renderers.TextRenderer; * @since * @author Vaadin Ltd */ -public class GridHeader { +public class GridHeader extends GridStaticSection { /** * A single row in a grid header section. * - * @since - * @author Vaadin Ltd */ - public static class HeaderRow { - - private List cells = new ArrayList(); - - private Renderer renderer = new TextRenderer(); - - public HeaderCell getCell(int index) { - return cells.get(index); - } - - protected void addCell(int index) { - cells.add(index, new HeaderCell()); - } - - protected void removeCell(int index) { - cells.remove(index); - } + public static class HeaderRow extends + GridStaticSection.StaticRow { - protected Renderer getRenderer() { - return renderer; + @Override + protected HeaderCell createCell() { + return new HeaderCell(); } } /** * A single cell in a grid header row. Has a textual caption. * - * @since - * @author Vaadin Ltd */ - public static class HeaderCell { - - private String text = ""; - - public void setText(String text) { - this.text = text; - } - - public String getText() { - return text; - } - } - - private List rows = Arrays.asList(new HeaderRow()); - - public HeaderRow getRow(int index) { - return rows.get(index); + public static class HeaderCell extends GridStaticSection.StaticCell { } - protected void addColumn(GridColumn column, int index) { - getRow(0).addCell(index); + @Override + protected HeaderRow createRow() { + return new HeaderRow(); } - protected void removeColumn(int index) { - getRow(0).removeCell(index); + @Override + protected List createRowList() { + return Arrays.asList(createRow()); } } diff --git a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java new file mode 100644 index 0000000000..3273c2dfa2 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java @@ -0,0 +1,141 @@ +/* + * Copyright 2000-2014 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.client.ui.grid; + +import java.util.ArrayList; +import java.util.List; + +import com.vaadin.client.ui.grid.GridStaticSection.StaticRow; +import com.vaadin.client.ui.grid.renderers.TextRenderer; + +/** + * Abstract base class for Grid header and footer sections. + * + * @since + * @author Vaadin Ltd + * @param + * the type of the rows in the section + */ +abstract class GridStaticSection> { + + /** + * A header or footer cell. Has a simple textual caption. + * + * TODO HTML content + * + * TODO Widget content + */ + static class StaticCell { + + private String text = ""; + + /** + * Sets the text displayed in this cell. + * + * @param text + * a plain text caption + */ + public void setText(String text) { + this.text = text; + } + + /** + * Returns the text displayed in this cell. + * + * @return the plain text caption + */ + public String getText() { + return text; + } + } + + /** + * Abstract base class for Grid header and footer rows. + * + * @param + * the type of the cells in the row + */ + abstract static class StaticRow { + + private List cells = new ArrayList(); + + private Renderer renderer = new TextRenderer(); + + /** + * Returns the cell at the given position in this row. + * + * @param index + * the position of the cell + * @return the cell at the index + * @throws IndexOutOfBoundsException + * if the index is out of bounds + */ + public CELLTYPE getCell(int index) { + return cells.get(index); + } + + protected void addCell(int index) { + cells.add(index, createCell()); + } + + protected void removeCell(int index) { + cells.remove(index); + } + + protected Renderer getRenderer() { + return renderer; + } + + protected abstract CELLTYPE createCell(); + } + + private List rows = createRowList(); + + /** + * Returns the row at the given position in this section. + * + * @param index + * the position of the row + * @return the row at the index + * @throws IndexOutOfBoundsException + * if the index is out of bounds + */ + public ROWTYPE getRow(int index) { + return rows.get(index); + } + + protected List getRows() { + return rows; + } + + protected void addColumn(GridColumn column, int index) { + for (ROWTYPE row : getRows()) { + row.addCell(index); + } + } + + protected void removeColumn(int index) { + for (ROWTYPE row : getRows()) { + row.removeCell(index); + } + } + + protected List createRowList() { + return new ArrayList(); + } + + protected abstract ROWTYPE createRow(); +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java index a3c62e0303..cc48f11c69 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java @@ -71,6 +71,14 @@ public abstract class GridBasicFeaturesTest extends MultiBrowserTest { return headerCells; } + protected List getGridFooterRowCells() { + List footerCells = new ArrayList(); + for (int i = 0; i < getGridElement().getFooterCount(); ++i) { + footerCells.addAll(getGridElement().getFooterCells(i)); + } + return footerCells; + } + private Object executeScript(String script, WebElement element) { final WebDriver driver = getDriver(); if (driver instanceof JavascriptExecutor) { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java new file mode 100644 index 0000000000..e126994f34 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; + +import com.vaadin.testbench.TestBenchElement; + +public class GridFooterTest extends GridBasicClientFeaturesTest { + + @Test + public void testFooterVisibility() throws Exception { + openTestURL(); + + // Footer should have zero rows by default + List cells = getGridFooterRowCells(); + assertEquals(0, cells.size()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java index dfbb1679b0..716e3b30fc 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java @@ -26,11 +26,54 @@ import com.vaadin.testbench.TestBenchElement; public class GridHeaderTest extends GridBasicClientFeaturesTest { @Test - public void testHeaderVisible() throws Exception { + public void testHeaderVisibility() throws Exception { openTestURL(); - // Column headers should be visible + // Column headers should be visible by default List cells = getGridHeaderRowCells(); assertEquals(GridBasicFeatures.COLUMNS, cells.size()); } + + @Test + public void testHeaderCaptions() throws Exception { + openTestURL(); + + List cells = getGridHeaderRowCells(); + + int i = 0; + for (TestBenchElement cell : cells) { + assertText("Column " + i, cell); + i++; + } + } + + @Test + public void testHeadersWithInvisibleColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 1", "Visible"); + selectMenuPath("Component", "Columns", "Column 3", "Visible"); + + List cells = getGridHeaderRowCells(); + assertEquals(GridBasicFeatures.COLUMNS - 2, cells.size()); + + assertText("Column 0", cells.get(0)); + assertText("Column 2", cells.get(1)); + assertText("Column 4", cells.get(2)); + + selectMenuPath("Component", "Columns", "Column 3", "Visible"); + + cells = getGridHeaderRowCells(); + assertEquals(GridBasicFeatures.COLUMNS - 1, cells.size()); + + assertText("Column 0", cells.get(0)); + assertText("Column 2", cells.get(1)); + assertText("Column 3", cells.get(2)); + assertText("Column 4", cells.get(3)); + } + + private static void assertText(String text, TestBenchElement e) { + // TBE.getText returns "" if the element is scrolled out of view + assertEquals(text, e.getAttribute("innerHTML")); + } } diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java index 857ff14528..182a5bfa29 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -25,6 +25,7 @@ import com.vaadin.client.ui.grid.FlyweightCell; import com.vaadin.client.ui.grid.Grid; import com.vaadin.client.ui.grid.Grid.SelectionMode; import com.vaadin.client.ui.grid.GridColumn; +import com.vaadin.client.ui.grid.GridHeader.HeaderCell; import com.vaadin.client.ui.grid.Renderer; import com.vaadin.client.ui.grid.datasources.ListDataSource; import com.vaadin.client.ui.grid.renderers.DateRenderer; @@ -192,35 +193,61 @@ public class GridBasicClientFeatures extends }); } + // Set captions to column headers + + for (int i = 0; i < COLUMNS; ++i) { + HeaderCell cell = grid.getHeader().getRow(0).getCell(i); + cell.setText("Column " + i); + } + // // Populate the menu // + createStateMenu(); + createColumnsMenu(); + + grid.getElement().getStyle().setZIndex(0); + add(grid); + } + + private void createStateMenu() { + String[] selectionModePath = { "Component", "State", "Selection mode" }; + addMenuCommand("multi", new ScheduledCommand() { @Override public void execute() { grid.setSelectionMode(SelectionMode.MULTI); } - }, "Component", "State", "Selection mode"); + }, selectionModePath); addMenuCommand("single", new ScheduledCommand() { - @Override public void execute() { grid.setSelectionMode(SelectionMode.SINGLE); } - }, "Component", "State", "Selection mode"); + }, selectionModePath); addMenuCommand("none", new ScheduledCommand() { - @Override public void execute() { grid.setSelectionMode(SelectionMode.NONE); } - }, "Component", "State", "Selection mode"); + }, selectionModePath); + } - grid.getElement().getStyle().setZIndex(0); - add(grid); + private void createColumnsMenu() { + + for (int i = 0; i < COLUMNS; i++) { + final int index = i; + addMenuCommand("Visible", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setVisible( + !grid.getColumn(index).isVisible()); + } + }, "Component", "Columns", "Column " + i); + } } /** -- cgit v1.2.3 From aca2902c9cafcb02db19a0cdd42b1488786c0f56 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Tue, 15 Jul 2014 20:44:59 +0300 Subject: Client-side Grid header/footer rewrite: add add/remove rows support (#13334) Currently supported: * Adding and removal of header and footer rows * Header is single-row by default * Footer is zero-row by default * Text captions TODO: * Column spanning * HTML content * Widget content * Component content * Sorting/Indicators * Server side API * Shared state handling Change-Id: I54b5062f31e38e872ca64394dfa02f866a1af202 --- client/src/com/vaadin/client/ui/grid/Grid.java | 12 +- .../src/com/vaadin/client/ui/grid/GridFooter.java | 12 +- .../src/com/vaadin/client/ui/grid/GridHeader.java | 12 +- .../vaadin/client/ui/grid/GridStaticSection.java | 143 +++++++++++++++++++-- .../grid/basicfeatures/GridFooterTest.java | 52 +++++++- .../grid/basicfeatures/GridHeaderTest.java | 76 ++++++++--- .../grid/basicfeatures/GridStaticSectionTest.java | 52 ++++++++ .../client/grid/GridBasicClientFeatures.java | 89 ++++++++++++- 8 files changed, 382 insertions(+), 66 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 4465cd0070..18c1cbae01 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -45,7 +45,6 @@ import com.vaadin.client.Util; import com.vaadin.client.data.DataChangeHandler; import com.vaadin.client.data.DataSource; import com.vaadin.client.ui.SubPartAware; -import com.vaadin.client.ui.grid.GridStaticSection.StaticRow; import com.vaadin.client.ui.grid.renderers.ComplexRenderer; import com.vaadin.client.ui.grid.renderers.TextRenderer; import com.vaadin.client.ui.grid.renderers.WidgetRenderer; @@ -1311,7 +1310,8 @@ public class Grid extends Composite implements @Override public void update(Row row, Iterable cellsToUpdate) { - StaticRow gridRow = section.getRow(row.getRow()); + GridStaticSection.StaticRow gridRow = section.getRow(row + .getRow()); final List columnIndices = getVisibleColumnIndices(); @@ -1365,8 +1365,10 @@ public class Grid extends Composite implements escalator.getBody().setEscalatorUpdater(createBodyUpdater()); escalator.getFooter().setEscalatorUpdater(createFooterUpdater()); - refreshHeader(); - refreshFooter(); + header.setGrid(this); + header.appendRow(); + + footer.setGrid(this); setSelectionMode(SelectionMode.SINGLE); @@ -1574,7 +1576,7 @@ public class Grid extends Composite implements GridStaticSection section) { // Add or Remove rows on demand - int rowDiff = section.getRows().size() - rows.getRowCount(); + int rowDiff = section.getRowCount() - rows.getRowCount(); if (rowDiff > 0) { rows.insertRows(0, rowDiff); } else if (rowDiff < 0) { diff --git a/client/src/com/vaadin/client/ui/grid/GridFooter.java b/client/src/com/vaadin/client/ui/grid/GridFooter.java index dc0f0054a2..7f478f7d29 100644 --- a/client/src/com/vaadin/client/ui/grid/GridFooter.java +++ b/client/src/com/vaadin/client/ui/grid/GridFooter.java @@ -15,9 +15,6 @@ */ package com.vaadin.client.ui.grid; -import java.util.Collections; -import java.util.List; - /** * Represents the footer section of a Grid. The footer is always empty. * @@ -38,8 +35,7 @@ public class GridFooter extends GridStaticSection { * A single row in a grid Footer section. * */ - public static class FooterRow extends - GridStaticSection.StaticRow { + public class FooterRow extends GridStaticSection.StaticRow { @Override protected FooterCell createCell() { @@ -51,7 +47,7 @@ public class GridFooter extends GridStaticSection { * A single cell in a grid Footer row. Has a textual caption. * */ - public static class FooterCell extends GridStaticSection.StaticCell { + public class FooterCell extends GridStaticSection.StaticCell { } @Override @@ -60,7 +56,7 @@ public class GridFooter extends GridStaticSection { } @Override - protected List createRowList() { - return Collections.emptyList(); + protected void refreshGrid() { + getGrid().refreshFooter(); } } diff --git a/client/src/com/vaadin/client/ui/grid/GridHeader.java b/client/src/com/vaadin/client/ui/grid/GridHeader.java index c23c848b8d..a2207c49c7 100644 --- a/client/src/com/vaadin/client/ui/grid/GridHeader.java +++ b/client/src/com/vaadin/client/ui/grid/GridHeader.java @@ -15,9 +15,6 @@ */ package com.vaadin.client.ui.grid; -import java.util.Arrays; -import java.util.List; - /** * Represents the header section of a Grid. A header consists of a single header * row containing a header cell for each column. Each cell has a simple textual @@ -42,8 +39,7 @@ public class GridHeader extends GridStaticSection { * A single row in a grid header section. * */ - public static class HeaderRow extends - GridStaticSection.StaticRow { + public class HeaderRow extends GridStaticSection.StaticRow { @Override protected HeaderCell createCell() { @@ -55,7 +51,7 @@ public class GridHeader extends GridStaticSection { * A single cell in a grid header row. Has a textual caption. * */ - public static class HeaderCell extends GridStaticSection.StaticCell { + public class HeaderCell extends GridStaticSection.StaticCell { } @Override @@ -64,7 +60,7 @@ public class GridHeader extends GridStaticSection { } @Override - protected List createRowList() { - return Arrays.asList(createRow()); + protected void refreshGrid() { + getGrid().refreshHeader(); } } diff --git a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java index 3273c2dfa2..5b4523ab76 100644 --- a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java +++ b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java @@ -18,7 +18,6 @@ package com.vaadin.client.ui.grid; import java.util.ArrayList; import java.util.List; -import com.vaadin.client.ui.grid.GridStaticSection.StaticRow; import com.vaadin.client.ui.grid.renderers.TextRenderer; /** @@ -29,7 +28,7 @@ import com.vaadin.client.ui.grid.renderers.TextRenderer; * @param * the type of the rows in the section */ -abstract class GridStaticSection> { +abstract class GridStaticSection> { /** * A header or footer cell. Has a simple textual caption. @@ -42,6 +41,8 @@ abstract class GridStaticSection> { private String text = ""; + private GridStaticSection section; + /** * Sets the text displayed in this cell. * @@ -50,6 +51,7 @@ abstract class GridStaticSection> { */ public void setText(String text) { this.text = text; + section.refreshGrid(); } /** @@ -60,6 +62,16 @@ abstract class GridStaticSection> { public String getText() { return text; } + + protected GridStaticSection getSection() { + assert section != null; + return section; + } + + protected void setSection(GridStaticSection section) { + this.section = section; + } + } /** @@ -74,6 +86,8 @@ abstract class GridStaticSection> { private Renderer renderer = new TextRenderer(); + private GridStaticSection section; + /** * Returns the cell at the given position in this row. * @@ -88,7 +102,9 @@ abstract class GridStaticSection> { } protected void addCell(int index) { - cells.add(index, createCell()); + CELLTYPE cell = createCell(); + cell.setSection(getSection()); + cells.add(index, cell); } protected void removeCell(int index) { @@ -100,16 +116,109 @@ abstract class GridStaticSection> { } protected abstract CELLTYPE createCell(); + + protected GridStaticSection getSection() { + return section; + } + + protected void setSection(GridStaticSection section) { + this.section = section; + } + } + + private Grid grid; + + private List rows = new ArrayList(); + + /** + * Creates and returns a new instance of the row type. + * + * @return the created row + */ + protected abstract ROWTYPE createRow(); + + /** + * Informs the grid that this section should be re-rendered. + */ + protected abstract void refreshGrid(); + + /** + * Inserts a new row at the given position. + * + * @param index + * the position at which to insert the row + * @return the new row + * + * @throws IndexOutOfBoundsException + * if the index is out of bounds + */ + public ROWTYPE addRow(int index) { + ROWTYPE row = createRow(); + row.setSection(this); + for (int i = 0; i < getGrid().getColumnCount(); ++i) { + row.addCell(i); + } + rows.add(index, row); + refreshGrid(); + return row; + } + + /** + * Adds a new row at the top of this section. + * + * @return the new row + */ + public ROWTYPE prependRow() { + return addRow(0); + } + + /** + * Adds a new row at the bottom of this section. + * + * @return the new row + */ + public ROWTYPE appendRow() { + return addRow(rows.size()); + } + + /** + * Removes the row at the given position. + * + * @param index + * the position of the row + * + * @throws IndexOutOfBoundsException + * if the index is out of bounds + */ + public void removeRow(int index) { + rows.remove(index); + refreshGrid(); } - private List rows = createRowList(); + /** + * Removes the given row from the section. + * + * @param row + * the row to be removed + * + * @throws IllegalArgumentException + * if the row does not exist in this section + */ + public void removeRow(ROWTYPE row) { + if (!rows.remove(row)) { + throw new IllegalArgumentException( + "Section does not contain the given row"); + } + refreshGrid(); + } /** - * Returns the row at the given position in this section. + * Returns the row at the given position. * * @param index * the position of the row - * @return the row at the index + * @return the row with the given index + * * @throws IndexOutOfBoundsException * if the index is out of bounds */ @@ -117,25 +226,37 @@ abstract class GridStaticSection> { return rows.get(index); } + /** + * Returns the number of rows in this section. + * + * @return the number of rows + */ + public int getRowCount() { + return rows.size(); + } + protected List getRows() { return rows; } protected void addColumn(GridColumn column, int index) { - for (ROWTYPE row : getRows()) { + for (ROWTYPE row : rows) { row.addCell(index); } } protected void removeColumn(int index) { - for (ROWTYPE row : getRows()) { + for (ROWTYPE row : rows) { row.removeCell(index); } } - protected List createRowList() { - return new ArrayList(); + protected void setGrid(Grid grid) { + this.grid = grid; } - protected abstract ROWTYPE createRow(); + protected Grid getGrid() { + assert grid != null; + return grid; + } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java index e126994f34..80110ddc81 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java @@ -17,20 +17,58 @@ package com.vaadin.tests.components.grid.basicfeatures; import static org.junit.Assert.assertEquals; -import java.util.List; - import org.junit.Test; -import com.vaadin.testbench.TestBenchElement; - -public class GridFooterTest extends GridBasicClientFeaturesTest { +public class GridFooterTest extends GridStaticSectionTest { @Test public void testFooterVisibility() throws Exception { openTestURL(); // Footer should have zero rows by default - List cells = getGridFooterRowCells(); - assertEquals(0, cells.size()); + assertEquals(0, getGridFooterRowCells().size()); + } + + @Test + public void testAddRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + assertFooterCount(1); + assertFooterTexts(0, 0); + + selectMenuPath("Component", "Footer", "Prepend row"); + + assertFooterCount(2); + assertFooterTexts(1, 0); + assertFooterTexts(0, 1); + + selectMenuPath("Component", "Footer", "Append row"); + + assertFooterCount(3); + assertFooterTexts(1, 0); + assertFooterTexts(0, 1); + assertFooterTexts(2, 2); + } + + @Test + public void testRemoveRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Prepend row"); + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Remove top row"); + + assertFooterCount(1); + assertFooterTexts(1, 0); + + selectMenuPath("Component", "Footer", "Remove bottom row"); + assertFooterCount(0); + } + + private void assertFooterCount(int count) { + assertEquals("footer count", count, getGridElement().getFooterCount()); } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java index 716e3b30fc..c1bc4cdd73 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java @@ -23,28 +23,21 @@ import org.junit.Test; import com.vaadin.testbench.TestBenchElement; -public class GridHeaderTest extends GridBasicClientFeaturesTest { +public class GridHeaderTest extends GridStaticSectionTest { @Test public void testHeaderVisibility() throws Exception { openTestURL(); // Column headers should be visible by default - List cells = getGridHeaderRowCells(); - assertEquals(GridBasicFeatures.COLUMNS, cells.size()); + assertEquals(GridBasicFeatures.COLUMNS, getGridHeaderRowCells().size()); } @Test public void testHeaderCaptions() throws Exception { openTestURL(); - List cells = getGridHeaderRowCells(); - - int i = 0; - for (TestBenchElement cell : cells) { - assertText("Column " + i, cell); - i++; - } + assertHeaderTexts(0, 0); } @Test @@ -57,23 +50,66 @@ public class GridHeaderTest extends GridBasicClientFeaturesTest { List cells = getGridHeaderRowCells(); assertEquals(GridBasicFeatures.COLUMNS - 2, cells.size()); - assertText("Column 0", cells.get(0)); - assertText("Column 2", cells.get(1)); - assertText("Column 4", cells.get(2)); + assertText("Header (0,0)", cells.get(0)); + assertText("Header (0,2)", cells.get(1)); + assertText("Header (0,4)", cells.get(2)); selectMenuPath("Component", "Columns", "Column 3", "Visible"); cells = getGridHeaderRowCells(); assertEquals(GridBasicFeatures.COLUMNS - 1, cells.size()); - assertText("Column 0", cells.get(0)); - assertText("Column 2", cells.get(1)); - assertText("Column 3", cells.get(2)); - assertText("Column 4", cells.get(3)); + assertText("Header (0,0)", cells.get(0)); + assertText("Header (0,2)", cells.get(1)); + assertText("Header (0,3)", cells.get(2)); + assertText("Header (0,4)", cells.get(3)); + } + + @Test + public void testAddRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + assertHeaderCount(2); + assertHeaderTexts(0, 0); + assertHeaderTexts(1, 1); + + selectMenuPath("Component", "Header", "Prepend row"); + + assertHeaderCount(3); + assertHeaderTexts(2, 0); + assertHeaderTexts(0, 1); + assertHeaderTexts(1, 2); + + selectMenuPath("Component", "Header", "Append row"); + + assertHeaderCount(4); + assertHeaderTexts(2, 0); + assertHeaderTexts(0, 1); + assertHeaderTexts(1, 2); + assertHeaderTexts(3, 3); + } + + @Test + public void testRemoveRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Prepend row"); + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Remove top row"); + + assertHeaderCount(2); + assertHeaderTexts(0, 0); + assertHeaderTexts(2, 1); + + selectMenuPath("Component", "Header", "Remove bottom row"); + assertHeaderCount(1); + assertHeaderTexts(0, 0); } - private static void assertText(String text, TestBenchElement e) { - // TBE.getText returns "" if the element is scrolled out of view - assertEquals(text, e.getAttribute("innerHTML")); + private void assertHeaderCount(int count) { + assertEquals("header count", count, getGridElement().getHeaderCount()); } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java new file mode 100644 index 0000000000..8f6739e16d --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.junit.Assert.assertEquals; + +import com.vaadin.testbench.TestBenchElement; + +/** + * Abstract base class for header and footer tests. + * + * @since + * @author Vaadin Ltd + */ +public abstract class GridStaticSectionTest extends GridBasicClientFeaturesTest { + + protected void assertHeaderTexts(int headerId, int rowIndex) { + int i = 0; + for (TestBenchElement cell : getGridElement().getHeaderCells(rowIndex)) { + assertText(String.format("Header (%d,%d)", headerId, i), cell); + i++; + } + assertEquals("number of header columns", GridBasicFeatures.COLUMNS, i); + } + + protected void assertFooterTexts(int footerId, int rowIndex) { + int i = 0; + for (TestBenchElement cell : getGridElement().getFooterCells(rowIndex)) { + assertText(String.format("Footer (%d,%d)", footerId, i), cell); + i++; + } + assertEquals("number of footer columns", GridBasicFeatures.COLUMNS, i); + } + + protected static void assertText(String text, TestBenchElement e) { + // TBE.getText returns "" if the element is scrolled out of view + assertEquals(text, e.getAttribute("innerHTML")); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java index 182a5bfa29..8564b149d8 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -25,7 +25,10 @@ import com.vaadin.client.ui.grid.FlyweightCell; import com.vaadin.client.ui.grid.Grid; import com.vaadin.client.ui.grid.Grid.SelectionMode; import com.vaadin.client.ui.grid.GridColumn; -import com.vaadin.client.ui.grid.GridHeader.HeaderCell; +import com.vaadin.client.ui.grid.GridFooter; +import com.vaadin.client.ui.grid.GridFooter.FooterRow; +import com.vaadin.client.ui.grid.GridHeader; +import com.vaadin.client.ui.grid.GridHeader.HeaderRow; import com.vaadin.client.ui.grid.Renderer; import com.vaadin.client.ui.grid.datasources.ListDataSource; import com.vaadin.client.ui.grid.renderers.DateRenderer; @@ -193,12 +196,7 @@ public class GridBasicClientFeatures extends }); } - // Set captions to column headers - - for (int i = 0; i < COLUMNS; ++i) { - HeaderCell cell = grid.getHeader().getRow(0).getCell(i); - cell.setText("Column " + i); - } + setHeaderTexts(grid.getHeader().getRow(0)); // // Populate the menu @@ -206,6 +204,8 @@ public class GridBasicClientFeatures extends createStateMenu(); createColumnsMenu(); + createHeaderMenu(); + createFooterMenu(); grid.getElement().getStyle().setZIndex(0); add(grid); @@ -250,6 +250,81 @@ public class GridBasicClientFeatures extends } } + private int headerCounter = 0; + private int footerCounter = 0; + + private void setHeaderTexts(HeaderRow row) { + for (int i = 0; i < COLUMNS; ++i) { + row.getCell(i).setText("Header (" + headerCounter + "," + i + ")"); + } + headerCounter++; + } + + private void setFooterTexts(FooterRow row) { + for (int i = 0; i < COLUMNS; ++i) { + row.getCell(i).setText("Footer (" + footerCounter + "," + i + ")"); + } + footerCounter++; + } + + private void createHeaderMenu() { + final GridHeader header = grid.getHeader(); + addMenuCommand("Prepend row", new ScheduledCommand() { + @Override + public void execute() { + setHeaderTexts(header.prependRow()); + } + }, "Component", "Header"); + addMenuCommand("Append row", new ScheduledCommand() { + @Override + public void execute() { + setHeaderTexts(header.appendRow()); + } + }, "Component", "Header"); + addMenuCommand("Remove top row", new ScheduledCommand() { + @Override + public void execute() { + header.removeRow(0); + } + }, "Component", "Header"); + addMenuCommand("Remove bottom row", new ScheduledCommand() { + @Override + public void execute() { + header.removeRow(header.getRowCount() - 1); + } + }, "Component", "Header"); + } + + private void createFooterMenu() { + + final GridFooter footer = grid.getFooter(); + + addMenuCommand("Prepend row", new ScheduledCommand() { + @Override + public void execute() { + setFooterTexts(footer.prependRow()); + } + }, "Component", "Footer"); + addMenuCommand("Append row", new ScheduledCommand() { + @Override + public void execute() { + setFooterTexts(footer.appendRow()); + } + }, "Component", "Footer"); + addMenuCommand("Remove top row", new ScheduledCommand() { + @Override + public void execute() { + footer.removeRow(0); + } + }, "Component", "Footer"); + addMenuCommand("Remove bottom row", new ScheduledCommand() { + @Override + public void execute() { + footer.removeRow(footer.getRowCount() - 1); + } + }, "Component", "Footer"); + } + /** * Creates a a renderer for a {@link Renderers} */ -- cgit v1.2.3 From a08d6a34fc7a89c1bad74047bfe2fd38a585e409 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Thu, 17 Jul 2014 16:43:25 +0300 Subject: Implement keyboard navigation between containers (#13334) Change-Id: I1592582eb20d46bac6ef6f5a6e995a6b3a73098b --- client/src/com/vaadin/client/ui/grid/Grid.java | 94 +++++++++++++++++++--- .../basicfeatures/GridKeyboardNavigationTest.java | 29 +++++-- 2 files changed, 107 insertions(+), 16 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 18c1cbae01..866ba611b3 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -265,16 +265,10 @@ public class Grid extends Composite implements * Handle events that can change the currently active cell. */ public void handleNavigationEvent(Event event, Cell cell) { - if (event.getType().equals(BrowserEvents.CLICK) - && event.getButton() == NativeEvent.BUTTON_LEFT - && cell != null) { + if (event.getType().equals(BrowserEvents.CLICK) && cell != null) { setActiveCell(cell); getElement().focus(); } else if (event.getType().equals(BrowserEvents.KEYDOWN)) { - int keyCode = event.getKeyCode(); - if (keyCode == 0) { - keyCode = event.getCharCode(); - } int newRow = activeRow; int newColumn = activeColumn; RowContainer newContainer = container; @@ -292,12 +286,36 @@ public class Grid extends Composite implements case KeyCodes.KEY_LEFT: newColumn -= 1; break; + default: + return; } if (newRow < 0) { - newRow = 0; + newContainer = getPreviousContainer(newContainer); + + if (newContainer == container) { + newRow = 0; + } else if (newContainer == escalator.getBody()) { + newRow = getLastVisibleRowIndex(); + } else { + newRow = newContainer.getRowCount() - 1; + } } else if (newRow >= container.getRowCount()) { - newRow = container.getRowCount() - 1; + newContainer = getNextContainer(newContainer); + + if (newContainer == container) { + newRow = container.getRowCount() - 1; + } else if (newContainer == escalator.getBody()) { + newRow = getFirstVisibleRowIndex(); + } else { + newRow = 0; + } + } + + if (newContainer.getRowCount() == 0) { + // There are no rows in the container. Can't change the + // active cell. + return; } if (newColumn < 0) { @@ -306,11 +324,69 @@ public class Grid extends Composite implements newColumn = getColumnCount() - 1; } + event.preventDefault(); + event.stopPropagation(); + setActiveCell(newRow, newColumn, newContainer); } } + private int getLastVisibleRowIndex() { + int lastRowIndex = escalator.getVisibleRowRange().getEnd(); + int footerTop = escalator.getFooter().getElement().getAbsoluteTop(); + Element lastRow; + + do { + lastRow = escalator.getBody().getRowElement(--lastRowIndex); + } while (lastRow.getAbsoluteBottom() > footerTop); + + return lastRowIndex; + } + + private int getFirstVisibleRowIndex() { + int firstRowIndex = escalator.getVisibleRowRange().getStart(); + int headerBottom = escalator.getHeader().getElement() + .getAbsoluteBottom(); + Element firstRow = escalator.getBody().getRowElement(firstRowIndex); + + while (firstRow.getAbsoluteTop() < headerBottom) { + firstRow = escalator.getBody().getRowElement(++firstRowIndex); + } + + return firstRowIndex; + } + + private RowContainer getPreviousContainer(RowContainer current) { + if (current == escalator.getFooter()) { + current = escalator.getBody(); + } else if (current == escalator.getBody()) { + current = escalator.getHeader(); + } else { + return current; + } + + if (current.getRowCount() == 0) { + return getPreviousContainer(current); + } + return current; + } + + private RowContainer getNextContainer(RowContainer current) { + if (current == escalator.getHeader()) { + current = escalator.getBody(); + } else if (current == escalator.getBody()) { + current = escalator.getFooter(); + } else { + return current; + } + + if (current.getRowCount() == 0) { + return getNextContainer(current); + } + return current; + } + private void refreshRow(int row) { container.refreshRows(row, 1); } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java index 465fdedad6..4c7e7c6365 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java @@ -18,9 +18,6 @@ package com.vaadin.tests.components.grid.basicfeatures; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import java.io.IOException; - -import org.junit.Ignore; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.Keys; @@ -89,18 +86,36 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { } @Test - @Ignore("This feature is still on the TODO list") - public void testNavigateFromHeaderToBody() throws IOException { + public void testNavigateFromHeaderToBody() { openTestURL(); GridElement grid = getGridElement(); grid.scrollToRow(300); - grid.getHeaderCell(0, 7).click(); + new Actions(driver).moveToElement(grid.getHeaderCell(0, 7)).click() + .perform(); + grid.scrollToRow(280); assertTrue("Header cell is not active.", grid.getHeaderCell(0, 7) .isActive()); new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); - assertTrue("Body cell 282, 7 is not active", grid.getCell(282, 7) + assertTrue("Body cell 280, 7 is not active", grid.getCell(280, 7) + .isActive()); + } + + @Test + public void testNavigationFromFooterToBody() { + openTestURL(); + + selectMenuPath("Component", "Footers", "Visible"); + + GridElement grid = getGridElement(); + grid.scrollToRow(300); + grid.getFooterCell(0, 2).click(); + + assertTrue("Footer cell is not active.", grid.getFooterCell(0, 2) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.ARROW_UP).perform(); + assertTrue("Body cell 300, 2 is not active", grid.getCell(300, 2) .isActive()); } } -- cgit v1.2.3 From 0bbd14486e3839c60e1e59f12dc959b133b6ed05 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Fri, 18 Jul 2014 11:18:58 +0300 Subject: Implement Tab navigation for Grid (#13334) Change-Id: If2c1f3db23247355439360def983dba714979a48 --- .../src/com/vaadin/client/ui/grid/Escalator.java | 2 + client/src/com/vaadin/client/ui/grid/Grid.java | 32 +++++++++++++- .../grid/basicfeatures/GridBasicFeaturesTest.java | 10 +++++ .../basicfeatures/GridKeyboardNavigationTest.java | 51 ++++++++++++++++++++++ 4 files changed, 94 insertions(+), 1 deletion(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Escalator.java b/client/src/com/vaadin/client/ui/grid/Escalator.java index 0a237f3fca..df564be937 100644 --- a/client/src/com/vaadin/client/ui/grid/Escalator.java +++ b/client/src/com/vaadin/client/ui/grid/Escalator.java @@ -3938,9 +3938,11 @@ public class Escalator extends Widget { setElement(root); root.appendChild(verticalScrollbar.getElement()); + verticalScrollbar.getElement().setTabIndex(-1); verticalScrollbar.setScrollbarThickness(Util.getNativeScrollbarSize()); root.appendChild(horizontalScrollbar.getElement()); + horizontalScrollbar.getElement().setTabIndex(-1); horizontalScrollbar .setScrollbarThickness(Util.getNativeScrollbarSize()); horizontalScrollbar diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 866ba611b3..833c59d08b 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -106,6 +106,9 @@ public class Grid extends Composite implements private RowContainer container = escalator.getBody(); private int activeRow = 0; private int activeColumn = 0; + private int lastActiveBodyRow = 0; + private int lastActiveHeaderRow = 0; + private int lastActiveFooterRow = 0; private Element cellWithActiveStyle = null; private Element rowWithActiveStyle = null; @@ -227,6 +230,14 @@ public class Grid extends Composite implements RowContainer oldContainer = this.container; this.container = container; + if (oldContainer == escalator.getBody()) { + lastActiveBodyRow = oldRow; + } else if (oldContainer == escalator.getHeader()) { + lastActiveHeaderRow = oldRow; + } else { + lastActiveFooterRow = oldRow; + } + if (oldColumn != activeColumn) { refreshHeader(); refreshFooter(); @@ -286,11 +297,30 @@ public class Grid extends Composite implements case KeyCodes.KEY_LEFT: newColumn -= 1; break; + case KeyCodes.KEY_TAB: + if (event.getShiftKey()) { + newContainer = getPreviousContainer(container); + } else { + newContainer = getNextContainer(container); + } + + if (newContainer == container) { + return; + } + break; default: return; } - if (newRow < 0) { + if (newContainer != container) { + if (newContainer == escalator.getBody()) { + newRow = lastActiveBodyRow; + } else if (newContainer == escalator.getHeader()) { + newRow = lastActiveHeaderRow; + } else { + newRow = lastActiveFooterRow; + } + } else if (newRow < 0) { newContainer = getPreviousContainer(newContainer); if (newContainer == container) { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java index cc48f11c69..94d9766f78 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java @@ -23,6 +23,7 @@ import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.DesiredCapabilities; import com.vaadin.testbench.TestBenchElement; import com.vaadin.tests.annotations.TestCategory; @@ -32,6 +33,15 @@ import com.vaadin.tests.tb3.MultiBrowserTest; @TestCategory("grid") public abstract class GridBasicFeaturesTest extends MultiBrowserTest { + @Override + protected DesiredCapabilities getDesiredCapabilities() { + DesiredCapabilities dCap = super.getDesiredCapabilities(); + if (BrowserUtil.isIE(dCap)) { + dCap.setCapability("requireWindowFocus", true); + } + return super.getDesiredCapabilities(); + } + @Override protected Class getUIClass() { return GridBasicFeatures.class; diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java index 4c7e7c6365..4c26124a51 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java @@ -118,4 +118,55 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { assertTrue("Body cell 300, 2 is not active", grid.getCell(300, 2) .isActive()); } + + @Test + public void testNavigateBetweenHeaderAndBodyWithTab() { + openTestURL(); + + GridElement grid = getGridElement(); + grid.getCell(10, 2).click(); + + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) + .keyUp(Keys.SHIFT).perform(); + assertTrue("Header cell 0, 2 is not active", grid.getHeaderCell(0, 2) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.TAB).perform(); + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + + // Navigate out of the Grid and try to navigate with arrow keys. + new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) + .sendKeys(Keys.TAB).keyUp(Keys.SHIFT).sendKeys(Keys.ARROW_DOWN) + .perform(); + assertTrue("Header cell 0, 2 is not active", grid.getHeaderCell(0, 2) + .isActive()); + } + + @Test + public void testNavigateBetweenFooterAndBodyWithTab() { + openTestURL(); + + selectMenuPath("Component", "Footers", "Visible"); + + GridElement grid = getGridElement(); + grid.getCell(10, 2).click(); + + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.TAB).perform(); + assertTrue("Footer cell 0, 2 is not active", grid.getFooterCell(0, 2) + .isActive()); + new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) + .keyUp(Keys.SHIFT).perform(); + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + + // Navigate out of the Grid and try to navigate with arrow keys. + new Actions(getDriver()).sendKeys(Keys.TAB).sendKeys(Keys.TAB) + .sendKeys(Keys.ARROW_UP).perform(); + assertTrue("Footer cell 0, 2 is not active", grid.getFooterCell(0, 2) + .isActive()); + } } -- cgit v1.2.3 From 1726ce75310c6341007b35ba5b93e25466e8531b Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Fri, 18 Jul 2014 15:33:55 +0300 Subject: Client-side Grid header/footer rewrite: add section setVisible (#13334) Currently supported: * Adding and removal of header and footer rows * Header is single-row by default * Footer is zero-row by default * Text captions * Showing and hiding the whole header or footer TODO: * Column spanning * HTML content * Widget content * Component content * Sorting/Indicators * Server side API * Shared state handling Change-Id: I9708f6f5dd7e9212e9ba5f1e462b55ca619c3df0 --- client/src/com/vaadin/client/ui/grid/Grid.java | 2 +- .../vaadin/client/ui/grid/GridStaticSection.java | 26 +++++++++++++++++ .../grid/basicfeatures/GridFooterTest.java | 21 +++++++++++-- .../grid/basicfeatures/GridHeaderTest.java | 21 +++++++++++-- .../client/grid/GridBasicClientFeatures.java | 34 ++++++++++++++++------ 5 files changed, 90 insertions(+), 14 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 833c59d08b..403b0d1e3f 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -1682,7 +1682,7 @@ public class Grid extends Composite implements GridStaticSection section) { // Add or Remove rows on demand - int rowDiff = section.getRowCount() - rows.getRowCount(); + int rowDiff = section.getVisibleRowCount() - rows.getRowCount(); if (rowDiff > 0) { rows.insertRows(0, rowDiff); } else if (rowDiff < 0) { diff --git a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java index 5b4523ab76..f455acc92e 100644 --- a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java +++ b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java @@ -130,6 +130,8 @@ abstract class GridStaticSection> private List rows = new ArrayList(); + private boolean visible = true; + /** * Creates and returns a new instance of the row type. * @@ -142,6 +144,26 @@ abstract class GridStaticSection> */ protected abstract void refreshGrid(); + /** + * Sets the visibility of the whole section. + * + * @param visible + * true to show this section, false to hide + */ + public void setVisible(boolean visible) { + this.visible = visible; + refreshGrid(); + } + + /** + * Returns the visibility of this section. + * + * @return true if visible, false otherwise. + */ + public boolean isVisible() { + return visible; + } + /** * Inserts a new row at the given position. * @@ -239,6 +261,10 @@ abstract class GridStaticSection> return rows; } + protected int getVisibleRowCount() { + return isVisible() ? getRowCount() : 0; + } + protected void addColumn(GridColumn column, int index) { for (ROWTYPE row : rows) { row.addCell(index); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java index 80110ddc81..f7dd85e3c3 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java @@ -22,11 +22,28 @@ import org.junit.Test; public class GridFooterTest extends GridStaticSectionTest { @Test - public void testFooterVisibility() throws Exception { + public void testDefaultFooter() { openTestURL(); // Footer should have zero rows by default - assertEquals(0, getGridFooterRowCells().size()); + assertFooterCount(0); + } + + @Test + public void testFooterVisibility() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Visible"); + + assertFooterCount(0); + + selectMenuPath("Component", "Footer", "Append row"); + + assertFooterCount(0); + + selectMenuPath("Component", "Footer", "Visible"); + + assertFooterCount(1); } @Test diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java index c1bc4cdd73..2ced9e16d4 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java @@ -25,12 +25,29 @@ import com.vaadin.testbench.TestBenchElement; public class GridHeaderTest extends GridStaticSectionTest { + @Test + public void testDefaultHeader() throws Exception { + openTestURL(); + + assertHeaderCount(1); + assertHeaderTexts(0, 0); + } + @Test public void testHeaderVisibility() throws Exception { openTestURL(); - // Column headers should be visible by default - assertEquals(GridBasicFeatures.COLUMNS, getGridHeaderRowCells().size()); + selectMenuPath("Component", "Header", "Visible"); + + assertHeaderCount(0); + + selectMenuPath("Component", "Header", "Append row"); + + assertHeaderCount(0); + + selectMenuPath("Component", "Header", "Visible"); + + assertHeaderCount(2); } @Test diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java index 8564b149d8..21d65d56ac 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -269,60 +269,76 @@ public class GridBasicClientFeatures extends private void createHeaderMenu() { final GridHeader header = grid.getHeader(); + final String[] menuPath = { "Component", "Header" }; + + addMenuCommand("Visible", new ScheduledCommand() { + @Override + public void execute() { + header.setVisible(!header.isVisible()); + } + }, menuPath); + addMenuCommand("Prepend row", new ScheduledCommand() { @Override public void execute() { setHeaderTexts(header.prependRow()); } - }, "Component", "Header"); + }, menuPath); addMenuCommand("Append row", new ScheduledCommand() { @Override public void execute() { setHeaderTexts(header.appendRow()); } - }, "Component", "Header"); + }, menuPath); addMenuCommand("Remove top row", new ScheduledCommand() { @Override public void execute() { header.removeRow(0); } - }, "Component", "Header"); + }, menuPath); addMenuCommand("Remove bottom row", new ScheduledCommand() { @Override public void execute() { header.removeRow(header.getRowCount() - 1); } - }, "Component", "Header"); + }, menuPath); } private void createFooterMenu() { - final GridFooter footer = grid.getFooter(); + final String[] menuPath = { "Component", "Footer" }; + + addMenuCommand("Visible", new ScheduledCommand() { + @Override + public void execute() { + footer.setVisible(!footer.isVisible()); + } + }, menuPath); addMenuCommand("Prepend row", new ScheduledCommand() { @Override public void execute() { setFooterTexts(footer.prependRow()); } - }, "Component", "Footer"); + }, menuPath); addMenuCommand("Append row", new ScheduledCommand() { @Override public void execute() { setFooterTexts(footer.appendRow()); } - }, "Component", "Footer"); + }, menuPath); addMenuCommand("Remove top row", new ScheduledCommand() { @Override public void execute() { footer.removeRow(0); } - }, "Component", "Footer"); + }, menuPath); addMenuCommand("Remove bottom row", new ScheduledCommand() { @Override public void execute() { footer.removeRow(footer.getRowCount() - 1); } - }, "Component", "Footer"); + }, menuPath); } /** -- cgit v1.2.3 From 6f5d9104a68641c143d11c5a1376ba728b8085cd Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Wed, 23 Jul 2014 11:27:38 +0300 Subject: Improve GridBasicClientFeaturesTest menu handling on some browsers Change-Id: Ie044d4872a6f3dbed11a7baad7c5e23e603103e5 --- .../components/grid/basicfeatures/GridBasicClientFeaturesTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java index 95b45b262e..559457ea1c 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java @@ -16,6 +16,7 @@ package com.vaadin.tests.components.grid.basicfeatures; import org.openqa.selenium.By; +import org.openqa.selenium.Dimension; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; @@ -45,7 +46,9 @@ public abstract class GridBasicClientFeaturesTest extends GridBasicFeaturesTest @Override protected void selectMenu(String menuCaption) { WebElement menuElement = getMenuElement(menuCaption); - new Actions(getDriver()).moveToElement(menuElement).perform(); + Dimension size = menuElement.getSize(); + new Actions(getDriver()).moveToElement(menuElement, size.width - 10, + size.height / 2).perform(); } private WebElement getMenuElement(String menuCaption) { @@ -59,6 +62,7 @@ public abstract class GridBasicClientFeaturesTest extends GridBasicFeaturesTest .click().perform(); for (int i = 1; i < menuCaptions.length - 1; ++i) { selectMenu(menuCaptions[i]); + new Actions(getDriver()).moveByOffset(20, 0).perform(); } new Actions(getDriver()) .moveToElement( -- cgit v1.2.3 From 7b749fb90f159ce285bc562a17293fbcd0d97400 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Wed, 23 Jul 2014 14:05:29 +0300 Subject: Add minimal Header/Footer visibility support to GridConnector (#13334) Change-Id: If1bc760d7237d77217fa40a6d91a43d6111e956a --- client/src/com/vaadin/client/ui/grid/GridConnector.java | 9 +++++---- .../grid/basicfeatures/GridKeyboardNavigationTest.java | 6 ++---- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java index ca66ccc3d5..a2563488d3 100644 --- a/client/src/com/vaadin/client/ui/grid/GridConnector.java +++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java @@ -262,6 +262,9 @@ public class GridConnector extends AbstractComponentConnector { getWidget().addSelectionChangeHandler(internalSelectionChangeHandler); + // TODO: Remove this workaround once we have header/footer communication + getWidget().getFooter().appendRow(); + getWidget().addSortHandler(new SortEventHandler() { @Override public void sort(SortEvent event) { @@ -320,14 +323,12 @@ public class GridConnector extends AbstractComponentConnector { // Header if (stateChangeEvent.hasPropertyChanged("columnHeadersVisible")) { - getWidget() - .setColumnHeadersVisible(getState().columnHeadersVisible); + getWidget().getHeader().setVisible(getState().columnHeadersVisible); } // Footer if (stateChangeEvent.hasPropertyChanged("columnFootersVisible")) { - getWidget() - .setColumnFootersVisible(getState().columnFootersVisible); + getWidget().getFooter().setVisible(getState().columnFootersVisible); } // Column row groups diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java index 4c26124a51..805213027e 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java @@ -70,18 +70,16 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { assertTrue("Body cell 1, 1 is not active after keyboard navigation.", grid.getCell(1, 1).isActive()); - Actions manyClicks = new Actions(getDriver()); int i; for (i = 1; i < 40; ++i) { - manyClicks.sendKeys(Keys.ARROW_DOWN); + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); } - manyClicks.perform(); assertFalse("Grid has not scrolled with active cell", isElementPresent(By.xpath("//td[text() = '(0, 0)']"))); assertTrue("Active cell is not visible", isElementPresent(By.xpath("//td[text() = '(" + i + ", 0)']"))); - assertTrue("Body cell" + i + ", 1 is not active", grid.getCell(i, 1) + assertTrue("Body cell " + i + ", 1 is not active", grid.getCell(i, 1) .isActive()); } -- cgit v1.2.3 From cfad6d54de44fead836ec9355bbc77c06fa26a40 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Wed, 16 Jul 2014 11:16:38 +0300 Subject: Client-side Grid header/footer rewrite: add default header support (#13334) Currently supported: * Adding and removal of header and footer rows * Header is single-row by default * Footer is zero-row by default * Text captions * Showing and hiding the whole header or footer * Default header rows for sorting UI TODO: * Column spanning * HTML content * Widget content * Component content * Server side API * Shared state handling Change-Id: I3d6a2b75fad87780f83238ab792bbbcfe99a48fd --- client/src/com/vaadin/client/ui/grid/Grid.java | 74 +++++++++++++--------- .../com/vaadin/client/ui/grid/GridConnector.java | 5 ++ .../src/com/vaadin/client/ui/grid/GridHeader.java | 73 +++++++++++++++++++++ .../vaadin/client/ui/grid/GridStaticSection.java | 9 ++- server/src/com/vaadin/ui/components/grid/Grid.java | 7 +- .../shared/ui/grid/GridStaticSectionState.java | 2 + .../grid/basicfeatures/GridHeaderTest.java | 38 +++++++++++ .../client/grid/GridBasicClientFeatures.java | 30 +++++++++ 8 files changed, 206 insertions(+), 32 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 403b0d1e3f..ff75417c12 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -45,6 +45,7 @@ import com.vaadin.client.Util; import com.vaadin.client.data.DataChangeHandler; import com.vaadin.client.data.DataSource; import com.vaadin.client.ui.SubPartAware; +import com.vaadin.client.ui.grid.GridHeader.HeaderRow; import com.vaadin.client.ui.grid.renderers.ComplexRenderer; import com.vaadin.client.ui.grid.renderers.TextRenderer; import com.vaadin.client.ui.grid.renderers.WidgetRenderer; @@ -616,6 +617,13 @@ public class Grid extends Composite implements protected abstract SelectionModel createModel(); } + class SortableColumnHeaderRenderer extends + AbstractGridColumn.SortableColumnHeaderRenderer { + SortableColumnHeaderRenderer(Renderer cellRenderer) { + super(Grid.this, cellRenderer); + } + } + /** * Base class for grid columns internally used by the Grid. The user should * use {@link GridColumn} when creating new columns. @@ -633,9 +641,11 @@ public class Grid extends Composite implements * * FIXME Currently assumes multisorting */ - private class SortableColumnHeaderRenderer extends + static class SortableColumnHeaderRenderer extends ComplexRenderer { + private Grid grid; + /** * Delay before a long tap action is triggered. Number in * milliseconds. @@ -658,7 +668,8 @@ public class Grid extends Composite implements @Override public void run() { - SortOrder sortingOrder = getSortingOrder(); + SortOrder sortingOrder = getSortingOrder(grid + .getColumnFromVisibleIndex(cell.getColumn())); if (sortingOrder == null) { /* * No previous sorting, sort Ascending @@ -697,7 +708,9 @@ public class Grid extends Composite implements * @param cellRenderer * The actual cell renderer */ - public SortableColumnHeaderRenderer(Renderer cellRenderer) { + public SortableColumnHeaderRenderer(Grid grid, + Renderer cellRenderer) { + this.grid = grid; this.cellRenderer = cellRenderer; } @@ -715,9 +728,11 @@ public class Grid extends Composite implements * this is fixed. */ if (grid != null) { - SortOrder sortingOrder = getSortingOrder(); + GridColumn column = grid + .getColumnFromVisibleIndex(cell.getColumn()); + SortOrder sortingOrder = getSortingOrder(column); Element cellElement = cell.getElement(); - if (grid.getColumn(cell.getColumn()).isSortable()) { + if (column.isSortable()) { if (sortingOrder != null) { if (SortDirection.ASCENDING == sortingOrder .getDirection()) { @@ -836,6 +851,18 @@ public class Grid extends Composite implements } + protected void removeFromRow(HeaderRow row) { + row.setRenderer(new Renderer() { + @Override + public void render(FlyweightCell cell, String data) { + cleanup(cell); + } + }); + grid.refreshHeader(); + row.setRenderer(cellRenderer); + grid.refreshHeader(); + } + /** * Sorts the column in a direction */ @@ -844,13 +871,14 @@ public class Grid extends Composite implements TableCellElement th = TableCellElement.as(cell.getElement()); // Apply primary sorting on clicked column - GridColumn columnInstance = getColumnInstance(); + GridColumn columnInstance = grid + .getColumnFromVisibleIndex(cell.getColumn()); Sort sorting = Sort.by(columnInstance, direction); // Re-apply old sorting to the sort order if (multisort) { for (SortOrder order : grid.getSortOrder()) { - if (order.getColumn() != AbstractGridColumn.this) { + if (order.getColumn() != columnInstance) { sorting = sorting.then(order.getColumn(), order.getDirection()); } @@ -861,24 +889,12 @@ public class Grid extends Composite implements grid.sort(sorting); } - /** - * Resolves a GridColumn out of a AbstractGridColumn - */ - private GridColumn getColumnInstance() { - for (GridColumn column : grid.getColumns()) { - if (column == AbstractGridColumn.this) { - return (GridColumn) column; - } - } - return null; - } - /** * Finds the sorting order for this column */ - private SortOrder getSortingOrder() { + private SortOrder getSortingOrder(GridColumn column) { for (SortOrder order : grid.getSortOrder()) { - if (order.getColumn() == AbstractGridColumn.this) { + if (order.getColumn() == column) { return order; } } @@ -922,8 +938,7 @@ public class Grid extends Composite implements * Renderer for rendering the header cell value into the cell */ @Deprecated - private Renderer headerRenderer = new SortableColumnHeaderRenderer( - new TextRenderer()); + private Renderer headerRenderer = new TextRenderer(); /** * Renderer for rendering the footer cell value into the cell @@ -964,8 +979,7 @@ public class Grid extends Composite implements throw new IllegalArgumentException("Renderer cannot be null."); } - this.headerRenderer = new SortableColumnHeaderRenderer( - headerRenderer); + this.headerRenderer = headerRenderer; this.footerRenderer = footerRenderer; } @@ -1016,7 +1030,7 @@ public class Grid extends Composite implements if (renderer == null) { throw new IllegalArgumentException("Renderer cannot be null."); } - headerRenderer = new SortableColumnHeaderRenderer(headerRenderer); + this.headerRenderer = headerRenderer; if (grid != null) { grid.refreshHeader(); } @@ -1472,7 +1486,8 @@ public class Grid extends Composite implements escalator.getFooter().setEscalatorUpdater(createFooterUpdater()); header.setGrid(this); - header.appendRow(); + HeaderRow defaultRow = header.appendRow(); + header.setDefaultRow(defaultRow); footer.setGrid(this); @@ -2470,13 +2485,14 @@ public class Grid extends Composite implements if (container != null) { cell = container.getCell(e); if (cell != null) { + // FIXME getFromVisibleIndex??? GridColumn gridColumn = columns.get(cell.getColumn()); Renderer renderer; if (container == escalator.getHeader()) { - renderer = gridColumn.getHeaderRenderer(); + renderer = header.getRow(cell.getRow()).getRenderer(); } else if (container == escalator.getFooter()) { - renderer = gridColumn.getFooterRenderer(); + renderer = footer.getRow(cell.getRow()).getRenderer(); } else { renderer = gridColumn.getRenderer(); } diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java index 67f4dc4045..3c7629a60d 100644 --- a/client/src/com/vaadin/client/ui/grid/GridConnector.java +++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java @@ -36,6 +36,7 @@ import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.data.DataSource.RowHandle; import com.vaadin.client.data.RpcDataSourceConnector.RpcDataSource; import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.client.ui.grid.GridHeader.HeaderRow; import com.vaadin.client.ui.grid.GridStaticSection.StaticRow; import com.vaadin.client.ui.grid.renderers.AbstractRendererConnector; import com.vaadin.client.ui.grid.selection.AbstractRowHandleSelectionModel; @@ -368,6 +369,10 @@ public class GridConnector extends AbstractComponentConnector { for (CellState cellState : rowState.cells) { row.getCell(i++).setText(cellState.text); } + + if (section instanceof GridHeader && rowState.defaultRow) { + ((GridHeader) section).setDefaultRow((HeaderRow) row); + } } section.setVisible(state.visible); diff --git a/client/src/com/vaadin/client/ui/grid/GridHeader.java b/client/src/com/vaadin/client/ui/grid/GridHeader.java index a2207c49c7..c5b0febeca 100644 --- a/client/src/com/vaadin/client/ui/grid/GridHeader.java +++ b/client/src/com/vaadin/client/ui/grid/GridHeader.java @@ -15,6 +15,8 @@ */ package com.vaadin.client.ui.grid; +import com.vaadin.client.ui.grid.Grid.AbstractGridColumn.SortableColumnHeaderRenderer; + /** * Represents the header section of a Grid. A header consists of a single header * row containing a header cell for each column. Each cell has a simple textual @@ -41,6 +43,16 @@ public class GridHeader extends GridStaticSection { */ public class HeaderRow extends GridStaticSection.StaticRow { + private boolean isDefault = false; + + protected void setDefault(boolean isDefault) { + this.isDefault = isDefault; + } + + public boolean isDefault() { + return isDefault; + } + @Override protected HeaderCell createCell() { return new HeaderCell(); @@ -54,6 +66,67 @@ public class GridHeader extends GridStaticSection { public class HeaderCell extends GridStaticSection.StaticCell { } + private HeaderRow defaultRow; + + @Override + public void removeRow(int index) { + HeaderRow removedRow = getRow(index); + super.removeRow(index); + if (removedRow == defaultRow) { + setDefaultRow(null); + } + } + + /** + * Sets the default row of this header. The default row is a special header + * row providing a user interface for sorting columns. + * + * @param row + * the new default row, or null for no default row + * + * @throws IllegalArgumentException + * this header does not contain the row + */ + public void setDefaultRow(HeaderRow row) { + if (row == defaultRow) { + return; + } + if (row != null && !getRows().contains(row)) { + throw new IllegalArgumentException( + "Cannot set a default row that does not exist in the container"); + } + if (defaultRow != null) { + assert defaultRow.getRenderer() instanceof SortableColumnHeaderRenderer; + + // Eclipse is wrong about this warning - javac does not accept the + // parameterized version + ((Grid.SortableColumnHeaderRenderer) defaultRow.getRenderer()) + .removeFromRow(defaultRow); + + defaultRow.setDefault(false); + } + if (row != null) { + assert !(row.getRenderer() instanceof SortableColumnHeaderRenderer); + + row.setRenderer(getGrid().new SortableColumnHeaderRenderer(row + .getRenderer())); + + row.setDefault(true); + } + defaultRow = row; + refreshGrid(); + } + + /** + * Returns the current default row of this header. The default row is a + * special header row providing a user interface for sorting columns. + * + * @return the default row or null if no default row set + */ + public HeaderRow getDefaultRow() { + return defaultRow; + } + @Override protected HeaderRow createRow() { return new HeaderRow(); diff --git a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java index f455acc92e..4318811ca2 100644 --- a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java +++ b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java @@ -111,6 +111,10 @@ abstract class GridStaticSection> cells.remove(index); } + protected void setRenderer(Renderer renderer) { + this.renderer = renderer; + } + protected Renderer getRenderer() { return renderer; } @@ -227,11 +231,12 @@ abstract class GridStaticSection> * if the row does not exist in this section */ public void removeRow(ROWTYPE row) { - if (!rows.remove(row)) { + try { + removeRow(rows.indexOf(row)); + } catch (IndexOutOfBoundsException e) { throw new IllegalArgumentException( "Section does not contain the given row"); } - refreshGrid(); } /** diff --git a/server/src/com/vaadin/ui/components/grid/Grid.java b/server/src/com/vaadin/ui/components/grid/Grid.java index e4e6dcf4be..67a97c74b7 100644 --- a/server/src/com/vaadin/ui/components/grid/Grid.java +++ b/server/src/com/vaadin/ui/components/grid/Grid.java @@ -225,8 +225,13 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { */ public Grid(final Container.Indexed datasource) { - getState().header.rows.add(new RowState()); + RowState headerDefaultRow = new RowState(); + headerDefaultRow.defaultRow = true; + getState().header.rows.add(headerDefaultRow); + + // FIXME By default there shouldn't be any footer row getState().footer.rows.add(new RowState()); + setColumnFootersVisible(false); setContainerDataSource(datasource); diff --git a/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java b/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java index 358c06d089..859e01f089 100644 --- a/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java +++ b/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java @@ -33,6 +33,8 @@ public class GridStaticSectionState implements Serializable { public static class RowState implements Serializable { public List cells = new ArrayList(); + + public boolean defaultRow = false; } public List rows = new ArrayList(); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java index 2ced9e16d4..1b27350f25 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java @@ -16,12 +16,16 @@ package com.vaadin.tests.components.grid.basicfeatures; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.util.Arrays; import java.util.List; import org.junit.Test; import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.GridElement.GridCellElement; public class GridHeaderTest extends GridStaticSectionTest { @@ -126,7 +130,41 @@ public class GridHeaderTest extends GridStaticSectionTest { assertHeaderTexts(0, 0); } + @Test + public void testDefaultRow() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Sortable"); + + GridCellElement headerCell = getGridElement().getHeaderCell(0, 0); + + headerCell.click(); + + assertTrue(hasClassName(headerCell, "sort-asc")); + + headerCell.click(); + + assertFalse(hasClassName(headerCell, "sort-asc")); + assertTrue(hasClassName(headerCell, "sort-desc")); + + selectMenuPath("Component", "Header", "Prepend row"); + selectMenuPath("Component", "Header", "Default row", "Top"); + + assertFalse(hasClassName(headerCell, "sort-desc")); + headerCell = getGridElement().getHeaderCell(0, 0); + assertTrue(hasClassName(headerCell, "sort-desc")); + + selectMenuPath("Component", "Header", "Default row", "Unset"); + + assertFalse(hasClassName(headerCell, "sort-desc")); + } + private void assertHeaderCount(int count) { assertEquals("header count", count, getGridElement().getHeaderCount()); } + + private boolean hasClassName(TestBenchElement element, String name) { + return Arrays.asList(element.getAttribute("class").split(" ")) + .contains(name); + } } diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java index 21d65d56ac..e013306dc0 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -31,6 +31,7 @@ import com.vaadin.client.ui.grid.GridHeader; import com.vaadin.client.ui.grid.GridHeader.HeaderRow; import com.vaadin.client.ui.grid.Renderer; import com.vaadin.client.ui.grid.datasources.ListDataSource; +import com.vaadin.client.ui.grid.datasources.ListSorter; import com.vaadin.client.ui.grid.renderers.DateRenderer; import com.vaadin.client.ui.grid.renderers.HtmlRenderer; import com.vaadin.client.ui.grid.renderers.NumberRenderer; @@ -57,6 +58,7 @@ public class GridBasicClientFeatures extends private final Grid> grid; private final List> data; private final ListDataSource> ds; + private final ListSorter> sorter; /** * Our basic data object @@ -124,6 +126,8 @@ public class GridBasicClientFeatures extends grid.setDataSource(ds); grid.setSelectionMode(SelectionMode.NONE); + sorter = new ListSorter>(grid); + // Create a bunch of grid columns // Data source layout: @@ -247,6 +251,13 @@ public class GridBasicClientFeatures extends !grid.getColumn(index).isVisible()); } }, "Component", "Columns", "Column " + i); + addMenuCommand("Sortable", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setSortable( + !grid.getColumn(index).isSortable()); + } + }, "Component", "Columns", "Column " + i); } } @@ -278,6 +289,25 @@ public class GridBasicClientFeatures extends } }, menuPath); + addMenuCommand("Top", new ScheduledCommand() { + @Override + public void execute() { + header.setDefaultRow(header.getRow(0)); + } + }, "Component", "Header", "Default row"); + addMenuCommand("Bottom", new ScheduledCommand() { + @Override + public void execute() { + header.setDefaultRow(header.getRow(header.getRowCount() - 1)); + } + }, "Component", "Header", "Default row"); + addMenuCommand("Unset", new ScheduledCommand() { + @Override + public void execute() { + header.setDefaultRow(null); + } + }, "Component", "Header", "Default row"); + addMenuCommand("Prepend row", new ScheduledCommand() { @Override public void execute() { -- cgit v1.2.3 From 64caee7afa90ac8b16ba48e768204aa36248ecbe Mon Sep 17 00:00:00 2001 From: John Ahlroos Date: Mon, 28 Jul 2014 16:26:01 +0300 Subject: Allow merging header and footer cells again #13334 This changeset adds the possibility to merge header and footer cells by using HeaderRow.join(). Note: Currently this does not support hidden columns, support for it should be added in a later changeset. Change-Id: I42e089ef2ac6eea304e355423b274159a79baa89 --- client/src/com/vaadin/client/ui/grid/Grid.java | 11 +- .../com/vaadin/client/ui/grid/GridConnector.java | 2 +- .../src/com/vaadin/client/ui/grid/GridFooter.java | 2 +- .../src/com/vaadin/client/ui/grid/GridHeader.java | 6 +- .../vaadin/client/ui/grid/GridStaticSection.java | 135 +++++++++++++++++++-- .../grid/basicfeatures/GridFooterTest.java | 55 +++++++++ .../grid/basicfeatures/GridHeaderTest.java | 51 ++++++++ .../client/grid/GridBasicClientFeatures.java | 79 +++++++++++- 8 files changed, 323 insertions(+), 18 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index ff75417c12..1e310e3ec4 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -46,6 +46,7 @@ import com.vaadin.client.data.DataChangeHandler; import com.vaadin.client.data.DataSource; import com.vaadin.client.ui.SubPartAware; import com.vaadin.client.ui.grid.GridHeader.HeaderRow; +import com.vaadin.client.ui.grid.GridStaticSection.StaticCell; import com.vaadin.client.ui.grid.renderers.ComplexRenderer; import com.vaadin.client.ui.grid.renderers.TextRenderer; import com.vaadin.client.ui.grid.renderers.WidgetRenderer; @@ -1436,9 +1437,15 @@ public class Grid extends Composite implements final List columnIndices = getVisibleColumnIndices(); for (FlyweightCell cell : cellsToUpdate) { + int index = columnIndices.get(cell.getColumn()); - gridRow.getRenderer().render(cell, - gridRow.getCell(index).getText()); + StaticCell metadata = gridRow.getCell(index); + + // Assign colspan to cell before rendering + cell.setColSpan(metadata.getColspan()); + + // Render + gridRow.getRenderer().render(cell, metadata.getText()); activeCellHandler.updateActiveCellStyle(cell, container); } diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java index 3c7629a60d..458dc7e1d2 100644 --- a/client/src/com/vaadin/client/ui/grid/GridConnector.java +++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java @@ -377,7 +377,7 @@ public class GridConnector extends AbstractComponentConnector { section.setVisible(state.visible); - section.refreshGrid(); + section.refreshSection(); } /** diff --git a/client/src/com/vaadin/client/ui/grid/GridFooter.java b/client/src/com/vaadin/client/ui/grid/GridFooter.java index 7f478f7d29..eba6ad81cb 100644 --- a/client/src/com/vaadin/client/ui/grid/GridFooter.java +++ b/client/src/com/vaadin/client/ui/grid/GridFooter.java @@ -56,7 +56,7 @@ public class GridFooter extends GridStaticSection { } @Override - protected void refreshGrid() { + protected void refreshSection() { getGrid().refreshFooter(); } } diff --git a/client/src/com/vaadin/client/ui/grid/GridHeader.java b/client/src/com/vaadin/client/ui/grid/GridHeader.java index c5b0febeca..4e046873f4 100644 --- a/client/src/com/vaadin/client/ui/grid/GridHeader.java +++ b/client/src/com/vaadin/client/ui/grid/GridHeader.java @@ -24,7 +24,7 @@ import com.vaadin.client.ui.grid.Grid.AbstractGridColumn.SortableColumnHeaderRen * * TODO Arbitrary number of header rows (zero included, one by default) * - * TODO Merging header cells + * TODO Account for hidden columns when merging header cells * * TODO "Default" row with sorting * @@ -114,7 +114,7 @@ public class GridHeader extends GridStaticSection { row.setDefault(true); } defaultRow = row; - refreshGrid(); + refreshSection(); } /** @@ -133,7 +133,7 @@ public class GridHeader extends GridStaticSection { } @Override - protected void refreshGrid() { + protected void refreshSection() { getGrid().refreshHeader(); } } diff --git a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java index 4318811ca2..fa4f3e5ea0 100644 --- a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java +++ b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java @@ -16,6 +16,9 @@ package com.vaadin.client.ui.grid; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import com.vaadin.client.ui.grid.renderers.TextRenderer; @@ -41,17 +44,19 @@ abstract class GridStaticSection> private String text = ""; + private int colspan = 1; + private GridStaticSection section; /** * Sets the text displayed in this cell. - * + * * @param text * a plain text caption */ public void setText(String text) { this.text = text; - section.refreshGrid(); + section.refreshSection(); } /** @@ -72,6 +77,21 @@ abstract class GridStaticSection> this.section = section; } + /** + * @return the colspan + */ + public int getColspan() { + return colspan; + } + + /** + * @param colspan + * the colspan to set + */ + public void setColspan(int colspan) { + this.colspan = colspan; + } + } /** @@ -88,6 +108,8 @@ abstract class GridStaticSection> private GridStaticSection section; + private Collection> cellGroups = new HashSet>(); + /** * Returns the cell at the given position in this row. * @@ -101,6 +123,105 @@ abstract class GridStaticSection> return cells.get(index); } + /** + * Merges cells in a row + * + * @param cells + * The cells to be merged + * @return The first cell of the merged cells + */ + protected CELLTYPE join(List cells) { + assert cells.size() > 1 : "You cannot merge less than 2 cells together"; + + // Ensure no cell is already grouped + for (CELLTYPE cell : cells) { + if (getCellGroupForCell(cell) != null) { + throw new IllegalStateException("Cell " + cell.getText() + + " is already grouped."); + } + } + + // Ensure continuous range + int firstCellIndex = this.cells.indexOf(cells.get(0)); + for (int i = 0; i < cells.size(); i++) { + if (this.cells.get(firstCellIndex + i) != cells.get(i)) { + throw new IllegalStateException( + "Cell range must be a continous range"); + } + } + + // Create a new group + cellGroups.add(new ArrayList(cells)); + + calculateColspans(); + + getSection().refreshSection(); + + // Returns first cell of group + return cells.get(0); + } + + /** + * Merges columns cells in a row + * + * @param columns + * The columns which header should be merged + * @return The remaining visible cell after the merge + */ + public CELLTYPE join(GridColumn... columns) { + assert columns.length > 1 : "You cannot merge less than 2 columns together"; + + // Convert columns to cells + List cells = new ArrayList(); + for (GridColumn c : columns) { + int index = getSection().getGrid().getColumns().indexOf(c); + cells.add(this.cells.get(index)); + } + + return join(cells); + } + + /** + * Merges columns cells in a row + * + * @param cells + * The cells to merge. Must be from the same row. + * @return The remaining visible cell after the merge + */ + public CELLTYPE join(CELLTYPE... cells) { + return join(Arrays.asList(cells)); + } + + private List getCellGroupForCell(CELLTYPE cell) { + for (List group : cellGroups) { + if (group.contains(cell)) { + return group; + } + } + return null; + } + + private void calculateColspans() { + // Reset all cells + for (CELLTYPE cell : cells) { + cell.setColspan(1); + } + + // Set colspan for grouped cells + for (List group : cellGroups) { + for (int i = 0; i < group.size(); i++) { + CELLTYPE cell = group.get(i); + if (i == 0) { + // Assign full colspan to first cell + cell.setColspan(group.size()); + } else { + // Hide other cells + cell.setColspan(0); + } + } + } + } + protected void addCell(int index) { CELLTYPE cell = createCell(); cell.setSection(getSection()); @@ -146,7 +267,7 @@ abstract class GridStaticSection> /** * Informs the grid that this section should be re-rendered. */ - protected abstract void refreshGrid(); + protected abstract void refreshSection(); /** * Sets the visibility of the whole section. @@ -156,7 +277,7 @@ abstract class GridStaticSection> */ public void setVisible(boolean visible) { this.visible = visible; - refreshGrid(); + refreshSection(); } /** @@ -185,7 +306,7 @@ abstract class GridStaticSection> row.addCell(i); } rows.add(index, row); - refreshGrid(); + refreshSection(); return row; } @@ -218,12 +339,12 @@ abstract class GridStaticSection> */ public void removeRow(int index) { rows.remove(index); - refreshGrid(); + refreshSection(); } /** * Removes the given row from the section. - * + * * @param row * the row to be removed * diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java index f7dd85e3c3..e117ed5fbb 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java @@ -16,9 +16,13 @@ package com.vaadin.tests.components.grid.basicfeatures; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import org.junit.Test; +import com.vaadin.tests.components.grid.GridElement.GridCellElement; + public class GridFooterTest extends GridStaticSectionTest { @Test @@ -85,6 +89,57 @@ public class GridFooterTest extends GridStaticSectionTest { assertFooterCount(0); } + @Test + public void joinColumnsByCells() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Row 1", "Join column cells 0, 1"); + + GridCellElement spannedCell = getGridElement().getFooterCell(0, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getFooterCell(0, 1); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinColumnsByColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Row 1", "Join columns 1, 2"); + + GridCellElement spannedCell = getGridElement().getFooterCell(0, 1); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getFooterCell(0, 2); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinAllColumnsInRow() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Row 1", "Join all columns"); + + GridCellElement spannedCell = getGridElement().getFooterCell(0, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("11", spannedCell.getAttribute("colspan")); + + for (int columnIndex = 1; columnIndex < 11; columnIndex++) { + GridCellElement hiddenCell = getGridElement().getFooterCell(0, + columnIndex); + assertFalse(hiddenCell.isDisplayed()); + } + } + private void assertFooterCount(int count) { assertEquals("footer count", count, getGridElement().getFooterCount()); } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java index 1b27350f25..771c0da810 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java @@ -159,6 +159,57 @@ public class GridHeaderTest extends GridStaticSectionTest { assertFalse(hasClassName(headerCell, "sort-desc")); } + @Test + public void joinHeaderColumnsByCells() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join column cells 0, 1"); + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getHeaderCell(1, 1); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinHeaderColumnsByColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2"); + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 1); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getHeaderCell(1, 2); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinAllColumnsInHeaderRow() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join all columns"); + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("11", spannedCell.getAttribute("colspan")); + + for (int columnIndex = 1; columnIndex < 11; columnIndex++) { + GridCellElement hiddenCell = getGridElement().getHeaderCell(1, + columnIndex); + assertFalse(hiddenCell.isDisplayed()); + } + } + private void assertHeaderCount(int count) { assertEquals("header count", count, getGridElement().getHeaderCount()); } diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java index e013306dc0..b6dfdc8635 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -311,13 +311,13 @@ public class GridBasicClientFeatures extends addMenuCommand("Prepend row", new ScheduledCommand() { @Override public void execute() { - setHeaderTexts(header.prependRow()); + configureHeaderRow(header.prependRow()); } }, menuPath); addMenuCommand("Append row", new ScheduledCommand() { @Override public void execute() { - setHeaderTexts(header.appendRow()); + configureHeaderRow(header.appendRow()); } }, menuPath); addMenuCommand("Remove top row", new ScheduledCommand() { @@ -332,6 +332,42 @@ public class GridBasicClientFeatures extends header.removeRow(header.getRowCount() - 1); } }, menuPath); + + } + + private void configureHeaderRow(final HeaderRow row) { + final GridHeader header = grid.getHeader(); + setHeaderTexts(row); + String rowTitle = "Row " + header.getRowCount(); + final String[] menuPath = { "Component", "Header", rowTitle }; + + addMenuCommand("Join column cells 0, 1", new ScheduledCommand() { + + @Override + public void execute() { + row.join(row.getCell(0), row.getCell(1)); + + } + }, menuPath); + + addMenuCommand("Join columns 1, 2", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumn(1), grid.getColumn(2)); + + } + }, menuPath); + + addMenuCommand("Join all columns", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumns().toArray( + new GridColumn[grid.getColumnCount()])); + + } + }, menuPath); } private void createFooterMenu() { @@ -348,13 +384,13 @@ public class GridBasicClientFeatures extends addMenuCommand("Prepend row", new ScheduledCommand() { @Override public void execute() { - setFooterTexts(footer.prependRow()); + configureFooterRow(footer.prependRow()); } }, menuPath); addMenuCommand("Append row", new ScheduledCommand() { @Override public void execute() { - setFooterTexts(footer.appendRow()); + configureFooterRow(footer.appendRow()); } }, menuPath); addMenuCommand("Remove top row", new ScheduledCommand() { @@ -371,6 +407,41 @@ public class GridBasicClientFeatures extends }, menuPath); } + private void configureFooterRow(final FooterRow row) { + final GridFooter footer = grid.getFooter(); + setFooterTexts(row); + String rowTitle = "Row " + footer.getRowCount(); + final String[] menuPath = { "Component", "Footer", rowTitle }; + + addMenuCommand("Join column cells 0, 1", new ScheduledCommand() { + + @Override + public void execute() { + row.join(row.getCell(0), row.getCell(1)); + + } + }, menuPath); + + addMenuCommand("Join columns 1, 2", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumn(1), grid.getColumn(2)); + + } + }, menuPath); + + addMenuCommand("Join all columns", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumns().toArray( + new GridColumn[grid.getColumnCount()])); + + } + }, menuPath); + } + /** * Creates a a renderer for a {@link Renderers} */ -- cgit v1.2.3 From 18308551b69b113368360e59c722d1dd4a314895 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Mon, 28 Jul 2014 14:16:41 +0300 Subject: Add multi column sorting test for Grid Change-Id: I3ff10c66fd4133ec794cc23c259e3fb6dc6ebec0 --- .../grid/basicfeatures/GridBasicFeatures.java | 12 ++++++++-- .../grid/basicfeatures/GridSortingTest.java | 26 ++++++++++++++++++++++ .../client/grid/GridBasicClientFeatures.java | 19 ++++++++++++++-- 3 files changed, 53 insertions(+), 4 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java index 316d7116e3..cfe3646295 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -52,8 +52,8 @@ import com.vaadin.ui.components.grid.sort.SortOrder; */ public class GridBasicFeatures extends AbstractComponentTest { - private static final int MANUALLY_FORMATTED_COLUMNS = 4; - public static final int COLUMNS = 11; + private static final int MANUALLY_FORMATTED_COLUMNS = 5; + public static final int COLUMNS = 12; public static final int ROWS = 1000; private int columnGroupRows = 0; @@ -86,6 +86,8 @@ public class GridBasicFeatures extends AbstractComponentTest { new Date()); ds.addContainerProperty(getColumnProperty(col++), String.class, ""); + // Random numbers + ds.addContainerProperty(getColumnProperty(col++), Integer.class, 0); ds.addContainerProperty(getColumnProperty(col++), Integer.class, 0); } @@ -110,8 +112,12 @@ public class GridBasicFeatures extends AbstractComponentTest { item.getItemProperty(getColumnProperty(col++)).setValue( "" + row + ""); + // Random numbers item.getItemProperty(getColumnProperty(col++)).setValue( rand.nextInt()); + // Random between 0 - 5 to test multisorting + item.getItemProperty(getColumnProperty(col++)).setValue( + rand.nextInt(5)); } } @@ -132,6 +138,8 @@ public class GridBasicFeatures extends AbstractComponentTest { new HtmlRenderer()); grid.getColumn(getColumnProperty(col++)).setRenderer( new NumberRenderer()); + grid.getColumn(getColumnProperty(col++)).setRenderer( + new NumberRenderer()); } // Add footer values (header values are automatically created) diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java index f706c1791d..4a1d7b7be1 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java @@ -23,6 +23,8 @@ import java.io.IOException; import org.junit.Ignore; import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; import com.vaadin.tests.components.grid.GridElement; @@ -158,6 +160,30 @@ public class GridSortingTest extends GridBasicFeaturesTest { assertEquals("11. Sort order: [Column7 DESCENDING]", getLogRow(1)); } + @Test + public void testUserMultiColumnSorting() { + openTestURL(); + + getGridElement().getHeaderCell(0, 0).click(); + new Actions(driver).keyDown(Keys.SHIFT).perform(); + getGridElement().getHeaderCell(0, 11).click(); + new Actions(driver).keyUp(Keys.SHIFT).perform(); + + String prev = getGridElement().getCell(0, 11).getAttribute("innerHTML"); + for (int i = 1; i <= 6; ++i) { + assertEquals("Column 11 should contain same values.", prev, + getGridElement().getCell(i, 11).getAttribute("innerHTML")); + } + + prev = getGridElement().getCell(0, 0).getText(); + for (int i = 1; i <= 6; ++i) { + assertTrue( + "Grid is not sorted by column 0.", + prev.compareTo(getGridElement().getCell(i, 0).getText()) < 0); + } + + } + private void sortBy(String column) { selectMenuPath("Component", "State", "Sort by column", column); } diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java index b6dfdc8635..7d4b29ba5d 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -51,8 +51,8 @@ public class GridBasicClientFeatures extends TEXT_RENDERER, HTML_RENDERER, NUMBER_RENDERER, DATE_RENDERER; } - private static final int MANUALLY_FORMATTED_COLUMNS = 4; - public static final int COLUMNS = 11; + private static final int MANUALLY_FORMATTED_COLUMNS = 5; + public static final int COLUMNS = 12; public static final int ROWS = 1000; private final Grid> grid; @@ -118,6 +118,9 @@ public class GridBasicClientFeatures extends d = datarow.get(col++); d.value = Integer.valueOf(rand.nextInt()); + + d = datarow.get(col++); + d.value = Integer.valueOf(rand.nextInt(5)); } } @@ -200,6 +203,18 @@ public class GridBasicClientFeatures extends }); } + // Random integer value between 0 and 5 + { + final int c = col++; + grid.addColumn(new GridColumn>( + createRenderer(Renderers.NUMBER_RENDERER)) { + @Override + public Integer getValue(List row) { + return (Integer) row.get(c).value; + } + }); + } + setHeaderTexts(grid.getHeader().getRow(0)); // -- cgit v1.2.3 From f0cab759eeb61f0f5e5a5f33a0e7ae1168bf8d96 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Wed, 30 Jul 2014 10:19:48 +0300 Subject: Use GridBasicFeatures variable COLUMNS instead of hardcoded value Change-Id: Ide8c50c98ac86653cbc5ab7614465b7d26c10c81 --- .../vaadin/tests/components/grid/basicfeatures/GridFooterTest.java | 5 +++-- .../vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java index e117ed5fbb..c4e86369f9 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java @@ -131,9 +131,10 @@ public class GridFooterTest extends GridStaticSectionTest { GridCellElement spannedCell = getGridElement().getFooterCell(0, 0); assertTrue(spannedCell.isDisplayed()); - assertEquals("11", spannedCell.getAttribute("colspan")); + assertEquals("" + GridBasicFeatures.COLUMNS, + spannedCell.getAttribute("colspan")); - for (int columnIndex = 1; columnIndex < 11; columnIndex++) { + for (int columnIndex = 1; columnIndex < GridBasicFeatures.COLUMNS; columnIndex++) { GridCellElement hiddenCell = getGridElement().getFooterCell(0, columnIndex); assertFalse(hiddenCell.isDisplayed()); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java index 771c0da810..43d5aa47df 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java @@ -201,9 +201,10 @@ public class GridHeaderTest extends GridStaticSectionTest { GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); assertTrue(spannedCell.isDisplayed()); - assertEquals("11", spannedCell.getAttribute("colspan")); + assertEquals("" + GridBasicFeatures.COLUMNS, + spannedCell.getAttribute("colspan")); - for (int columnIndex = 1; columnIndex < 11; columnIndex++) { + for (int columnIndex = 1; columnIndex < GridBasicFeatures.COLUMNS; columnIndex++) { GridCellElement hiddenCell = getGridElement().getHeaderCell(1, columnIndex); assertFalse(hiddenCell.isDisplayed()); -- cgit v1.2.3 From 91f14489833ccad2f3c5aeaabfd4d5c4a5a60728 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Mon, 28 Jul 2014 12:25:32 +0300 Subject: Fix SelectionModelSingle when updating from server (#13334) Change-Id: I4ae1411b3833387e83c8951f9b08528cf1ba97b9 --- .../ui/grid/selection/SelectionModelSingle.java | 36 +++++------- .../grid/basicfeatures/GridSelectionTest.java | 65 ++++++++++++++++------ 2 files changed, 62 insertions(+), 39 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/selection/SelectionModelSingle.java b/client/src/com/vaadin/client/ui/grid/selection/SelectionModelSingle.java index 2647ae9c56..2942538d81 100644 --- a/client/src/com/vaadin/client/ui/grid/selection/SelectionModelSingle.java +++ b/client/src/com/vaadin/client/ui/grid/selection/SelectionModelSingle.java @@ -68,20 +68,13 @@ public class SelectionModelSingle extends AbstractRowHandleSelectionModel throw new IllegalArgumentException("Row cannot be null"); } - if (isSelected(row)) { - return false; - } - T removed = getSelectedRow(); - if (selectedRow != null) { - selectedRow.unpin(); - } - selectedRow = grid.getDataSource().getHandle(row); - selectedRow.pin(); + if (selectByHandle(grid.getDataSource().getHandle(row))) { + grid.fireEvent(new SelectionChangeEvent(grid, row, removed)); - grid.fireEvent(new SelectionChangeEvent(grid, row, removed)); - - return true; + return true; + } + return false; } @Override @@ -92,10 +85,8 @@ public class SelectionModelSingle extends AbstractRowHandleSelectionModel } if (isSelected(row)) { - T removed = selectedRow.getRow(); - selectedRow.unpin(); - selectedRow = null; - grid.fireEvent(new SelectionChangeEvent(grid, null, removed)); + deselectByHandle(selectedRow); + grid.fireEvent(new SelectionChangeEvent(grid, null, row)); return true; } @@ -109,10 +100,8 @@ public class SelectionModelSingle extends AbstractRowHandleSelectionModel @Override public void reset() { - T removed = getSelectedRow(); - - if (removed != null) { - deselect(removed); + if (selectedRow != null) { + deselect(getSelectedRow()); } } @@ -126,8 +115,10 @@ public class SelectionModelSingle extends AbstractRowHandleSelectionModel @Override protected boolean selectByHandle(RowHandle handle) { - if (!handle.equals(selectedRow)) { + if (handle != null && !handle.equals(selectedRow)) { + deselectByHandle(selectedRow); selectedRow = handle; + selectedRow.pin(); return true; } else { return false; @@ -136,7 +127,8 @@ public class SelectionModelSingle extends AbstractRowHandleSelectionModel @Override protected boolean deselectByHandle(RowHandle handle) { - if (handle.equals(selectedRow)) { + if (handle != null && handle.equals(selectedRow)) { + selectedRow.unpin(); selectedRow = null; return true; } else { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java index e18dc1faa4..873c222f80 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java @@ -21,7 +21,8 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; import com.vaadin.testbench.TestBenchElement; -import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.components.grid.GridElement.GridRowElement; public class GridSelectionTest extends GridBasicFeaturesTest { @@ -31,12 +32,12 @@ public class GridSelectionTest extends GridBasicFeaturesTest { setSelectionModelMulti(); - assertFalse("row shouldn't start out as selected", - isSelected(getRow(0))); + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); toggleFirstRowSelection(); - assertTrue("row should become selected", isSelected(getRow(0))); + assertTrue("row should become selected", getRow(0).isSelected()); toggleFirstRowSelection(); - assertFalse("row shouldn't remain selected", isSelected(getRow(0))); + assertFalse("row shouldn't remain selected", getRow(0).isSelected()); } @Test @@ -45,16 +46,16 @@ public class GridSelectionTest extends GridBasicFeaturesTest { setSelectionModelMulti(); - assertFalse("row shouldn't start out as selected", - isSelected(getRow(0))); + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); toggleFirstRowSelection(); - assertTrue("row should become selected", isSelected(getRow(0))); + assertTrue("row should become selected", getRow(0).isSelected()); scrollGridVerticallyTo(10000); // make sure the row is out of cache scrollGridVerticallyTo(0); // scroll it back into view assertTrue("row should still be selected when scrolling " - + "back into view", isSelected(getRow(0))); + + "back into view", getRow(0).isSelected()); } @Test @@ -63,18 +64,18 @@ public class GridSelectionTest extends GridBasicFeaturesTest { setSelectionModelMulti(); - assertFalse("row shouldn't start out as selected", - isSelected(getRow(0))); + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); scrollGridVerticallyTo(10000); // make sure the row is out of cache toggleFirstRowSelection(); scrollGridVerticallyTo(0); // scroll it back into view assertTrue("row should still be selected when scrolling " - + "back into view", isSelected(getRow(0))); + + "back into view", getRow(0).isSelected()); toggleFirstRowSelection(); - assertFalse("row shouldn't remain selected", isSelected(getRow(0))); + assertFalse("row shouldn't remain selected", getRow(0).isSelected()); } @Test @@ -83,8 +84,8 @@ public class GridSelectionTest extends GridBasicFeaturesTest { setSelectionModelMulti(); - assertFalse("row shouldn't start out as selected", - isSelected(getRow(0))); + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); scrollGridVerticallyTo(10000); // make sure the row is out of cache toggleFirstRowSelection(); @@ -92,13 +93,43 @@ public class GridSelectionTest extends GridBasicFeaturesTest { scrollGridVerticallyTo(0); // make sure the row is out of cache assertFalse("row shouldn't be selected when scrolling " - + "back into view", isSelected(getRow(0))); + + "back into view", getRow(0).isSelected()); + } + + @Test + public void testSingleSelectionUpdatesFromServer() { + openTestURL(); + setSelectionModelSingle(); + + GridElement grid = getGridElement(); + assertFalse("First row was selected from start", grid.getRow(0) + .isSelected()); + toggleFirstRowSelection(); + assertTrue("First row was not selected.", getRow(0).isSelected()); + grid.getCell(5, 0).click(); + assertTrue("Fifth row was not selected.", getRow(5).isSelected()); + assertFalse("First row was still selected.", getRow(0).isSelected()); + grid.getCell(0, 0).click(); + toggleFirstRowSelection(); + assertFalse("First row was still selected.", getRow(0).isSelected()); + assertFalse("Fifth row was still selected.", getRow(5).isSelected()); + + grid.scrollToRow(600); + grid.getCell(595, 0).click(); + assertTrue("Row 595 was not selected.", getRow(595).isSelected()); + toggleFirstRowSelection(); + assertFalse("Row 595 was still selected.", getRow(595).isSelected()); + assertTrue("First row was not selected.", getRow(0).isSelected()); } private void setSelectionModelMulti() { selectMenuPath("Component", "State", "Selection mode", "multi"); } + private void setSelectionModelSingle() { + selectMenuPath("Component", "State", "Selection mode", "single"); + } + @SuppressWarnings("static-method") private boolean isSelected(TestBenchElement row) { /* @@ -113,7 +144,7 @@ public class GridSelectionTest extends GridBasicFeaturesTest { selectMenuPath("Component", "Body rows", "Select first row"); } - private TestBenchElement getRow(int i) { + private GridRowElement getRow(int i) { return getGridElement().getRow(i); } } -- cgit v1.2.3 From 5d0aa11b2c83e7f5abfa4c6d9ef71871b810a016 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Tue, 29 Jul 2014 17:19:28 +0300 Subject: Add server side API for Headers and Footers (#13334) Change-Id: I52f282089cc55b1f281b9aeb934886442b0c34f3 --- server/src/com/vaadin/ui/components/grid/Grid.java | 66 +++-- .../com/vaadin/ui/components/grid/GridColumn.java | 17 +- .../com/vaadin/ui/components/grid/GridFooter.java | 66 +++++ .../com/vaadin/ui/components/grid/GridHeader.java | 124 ++++++++++ .../ui/components/grid/GridStaticSection.java | 273 +++++++++++++++++++++ .../tests/server/component/grid/GridColumns.java | 32 ++- .../grid/basicfeatures/GridBasicFeatures.java | 135 ++++++++-- .../basicfeatures/GridKeyboardNavigationTest.java | 4 +- .../grid/basicfeatures/GridSortingTest.java | 33 ++- .../grid/basicfeatures/GridStructureTest.java | 37 ++- 10 files changed, 679 insertions(+), 108 deletions(-) create mode 100644 server/src/com/vaadin/ui/components/grid/GridFooter.java create mode 100644 server/src/com/vaadin/ui/components/grid/GridHeader.java create mode 100644 server/src/com/vaadin/ui/components/grid/GridStaticSection.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/server/src/com/vaadin/ui/components/grid/Grid.java b/server/src/com/vaadin/ui/components/grid/Grid.java index 67a97c74b7..f5846c0148 100644 --- a/server/src/com/vaadin/ui/components/grid/Grid.java +++ b/server/src/com/vaadin/ui/components/grid/Grid.java @@ -46,12 +46,11 @@ import com.vaadin.shared.ui.grid.GridColumnState; import com.vaadin.shared.ui.grid.GridServerRpc; import com.vaadin.shared.ui.grid.GridState; import com.vaadin.shared.ui.grid.GridState.SharedSelectionMode; -import com.vaadin.shared.ui.grid.GridStaticSectionState.CellState; -import com.vaadin.shared.ui.grid.GridStaticSectionState.RowState; import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.shared.ui.grid.ScrollDestination; import com.vaadin.shared.ui.grid.SortDirection; import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.components.grid.GridHeader.HeaderRow; import com.vaadin.ui.components.grid.selection.MultiSelectionModel; import com.vaadin.ui.components.grid.selection.NoSelectionModel; import com.vaadin.ui.components.grid.selection.SelectionChangeEvent; @@ -209,6 +208,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { */ private int ignoreSelectionClientSync = 0; + private final GridHeader header = new GridHeader(this); + private final GridFooter footer = new GridFooter(this); + private static final Method SELECTION_CHANGE_METHOD = ReflectTools .findMethod(SelectionChangeListener.class, "selectionChange", SelectionChangeEvent.class); @@ -224,17 +226,8 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { * the data source for the grid */ public Grid(final Container.Indexed datasource) { - - RowState headerDefaultRow = new RowState(); - headerDefaultRow.defaultRow = true; - getState().header.rows.add(headerDefaultRow); - - // FIXME By default there shouldn't be any footer row - getState().footer.rows.add(new RowState()); - - setColumnFootersVisible(false); - setContainerDataSource(datasource); + setSelectionMode(SelectionMode.MULTI); addSelectionChangeListener(new SelectionChangeListener() { @Override @@ -433,6 +426,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { setLastFrozenPropertyId(null); // Add columns + HeaderRow row = getHeader().getDefaultRow(); for (Object propertyId : datasource.getContainerPropertyIds()) { if (!columns.containsKey(propertyId)) { GridColumn column = appendColumn(propertyId); @@ -445,7 +439,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { } // Add by default property id as column header - column.setHeaderCaption(String.valueOf(propertyId)); + row.getCell(propertyId).setText(String.valueOf(propertyId)); } } } @@ -476,8 +470,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { * @param visible * true if the header rows should be visible */ + @Deprecated public void setColumnHeadersVisible(boolean visible) { - getState().header.visible = visible; + getHeader().setVisible(visible); } /** @@ -485,8 +480,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { * * @return true if the headers of the columns are visible */ + @Deprecated public boolean isColumnHeadersVisible() { - return getState(false).header.visible; + return getHeader().isVisible(); } /** @@ -495,8 +491,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { * @param visible * true if the footer rows should be visible */ + @Deprecated public void setColumnFootersVisible(boolean visible) { - getState().footer.visible = visible; + getFooter().setVisible(visible); } /** @@ -504,8 +501,9 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { * * @return true if the footer rows should be visible */ + @Deprecated public boolean isColumnFootersVisible() { - return getState(false).footer.visible; + return getFooter().isVisible(); } /** @@ -537,6 +535,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { * * @return a column group instance you can use to add column groups */ + @Deprecated public ColumnGroupRow addColumnGroupRow() { ColumnGroupRowState state = new ColumnGroupRowState(); ColumnGroupRow row = new ColumnGroupRow(this, state, columnKeys); @@ -552,6 +551,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { * the index of the row * @return a column group instance you can use to add column groups */ + @Deprecated public ColumnGroupRow addColumnGroupRow(int rowIndex) { ColumnGroupRowState state = new ColumnGroupRowState(); ColumnGroupRow row = new ColumnGroupRow(this, state, columnKeys); @@ -566,6 +566,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { * @param row * the row to remove */ + @Deprecated public void removeColumnGroupRow(ColumnGroupRow row) { columnGroupRows.remove(row); getState().columnGroupRows.remove(row.getState()); @@ -576,6 +577,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { * * @return an unmodifiable list of column group rows */ + @Deprecated public List getColumnGroupRows() { return Collections.unmodifiableList(new ArrayList( columnGroupRows)); @@ -635,11 +637,13 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { GridColumnState columnState = new GridColumnState(); columnState.id = columnKeys.key(datasourcePropertyId); getState().columns.add(columnState); - for (RowState row : getState().header.rows) { - row.cells.add(new CellState()); + + for (int i = 0; i < getHeader().getRowCount(); ++i) { + getHeader().getRow(i).addCell(datasourcePropertyId); } - for (RowState row : getState().footer.rows) { - row.cells.add(new CellState()); + + for (int i = 0; i < getFooter().getRowCount(); ++i) { + getFooter().getRow(i).addCell(datasourcePropertyId); } GridColumn column = new GridColumn(this, columnState); @@ -1316,4 +1320,24 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { removeListener(SortOrderChangeEvent.class, listener, SORT_ORDER_CHANGE_METHOD); } + + /** + * Returns the header section of this grid. The default header contains a + * single row displaying the column captions. + * + * @return the header + */ + public GridHeader getHeader() { + return header; + } + + /** + * Returns the footer section of this grid. The default header contains a + * single row displaying the column captions. + * + * @return the footer + */ + public GridFooter getFooter() { + return footer; + } } diff --git a/server/src/com/vaadin/ui/components/grid/GridColumn.java b/server/src/com/vaadin/ui/components/grid/GridColumn.java index 667b4f86db..0ef805eb2e 100644 --- a/server/src/com/vaadin/ui/components/grid/GridColumn.java +++ b/server/src/com/vaadin/ui/components/grid/GridColumn.java @@ -82,14 +82,15 @@ public class GridColumn implements Serializable { * Returns the caption of the header. By default the header caption is the * property id of the column. * - * @return the text in the header + * @return the text in the default row of header, null if no default row * * @throws IllegalStateException * if the column no longer is attached to the grid */ + @Deprecated public String getHeaderCaption() throws IllegalStateException { checkColumnIsAttached(); - return getHeaderCellState().text; + return state.header; } /** @@ -101,11 +102,10 @@ public class GridColumn implements Serializable { * @throws IllegalStateException * if the column is no longer attached to any grid */ + @Deprecated public void setHeaderCaption(String caption) throws IllegalStateException { checkColumnIsAttached(); - getHeaderCellState().text = caption; state.header = caption; - grid.markAsDirty(); } /** @@ -116,6 +116,7 @@ public class GridColumn implements Serializable { * @throws IllegalStateException * if the column is no longer attached to any grid */ + @Deprecated public String getFooterCaption() throws IllegalStateException { checkColumnIsAttached(); return getFooterCellState().text; @@ -130,6 +131,7 @@ public class GridColumn implements Serializable { * @throws IllegalStateException * if the column is no longer attached to any grid */ + @Deprecated public void setFooterCaption(String caption) throws IllegalStateException { checkColumnIsAttached(); getFooterCellState().text = caption; @@ -137,11 +139,6 @@ public class GridColumn implements Serializable { grid.markAsDirty(); } - private CellState getHeaderCellState() { - int index = grid.getState().columns.indexOf(state); - return grid.getState().header.rows.get(0).cells.get(index); - } - private CellState getFooterCellState() { int index = grid.getState().columns.indexOf(state); return grid.getState().footer.rows.get(0).cells.get(index); @@ -252,7 +249,7 @@ public class GridColumn implements Serializable { * the renderer to use * @throws IllegalArgumentException * if no compatible converter could be found - * + * * @see VaadinSession#getConverterFactory() * @see ConverterUtil#getConverter(Class, Class, VaadinSession) * @see #setConverter(Converter) diff --git a/server/src/com/vaadin/ui/components/grid/GridFooter.java b/server/src/com/vaadin/ui/components/grid/GridFooter.java new file mode 100644 index 0000000000..e4a7eab5d1 --- /dev/null +++ b/server/src/com/vaadin/ui/components/grid/GridFooter.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2014 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.shared.ui.grid.GridStaticSectionState; + +/** + * Represents the footer section of a Grid. By default Footer is not visible. + * + * @since + * @author Vaadin Ltd + */ +public class GridFooter extends GridStaticSection { + + public class FooterRow extends GridStaticSection.StaticRow { + + protected FooterRow(GridStaticSection section) { + super(section); + } + + @Override + protected FooterCell createCell() { + return new FooterCell(this); + } + + } + + public class FooterCell extends GridStaticSection.StaticCell { + + protected FooterCell(FooterRow row) { + super(row); + } + } + + private final GridStaticSectionState footerState = new GridStaticSectionState(); + + protected GridFooter(Grid grid) { + this.grid = grid; + grid.getState(true).footer = footerState; + setVisible(false); + } + + @Override + protected GridStaticSectionState getState() { + return footerState; + } + + @Override + protected FooterRow createRow() { + return new FooterRow(this); + } + +} diff --git a/server/src/com/vaadin/ui/components/grid/GridHeader.java b/server/src/com/vaadin/ui/components/grid/GridHeader.java new file mode 100644 index 0000000000..f8bd3c6642 --- /dev/null +++ b/server/src/com/vaadin/ui/components/grid/GridHeader.java @@ -0,0 +1,124 @@ +/* + * Copyright 2000-2014 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.shared.ui.grid.GridStaticSectionState; + +/** + * Represents the header section of a Grid. + * + * @since + * @author Vaadin Ltd + */ +public class GridHeader extends GridStaticSection { + + public class HeaderRow extends GridStaticSection.StaticRow { + + protected HeaderRow(GridStaticSection section) { + super(section); + } + + private void setDefaultRow(boolean value) { + getRowState().defaultRow = value; + } + + @Override + protected HeaderCell createCell() { + return new HeaderCell(this); + } + } + + public class HeaderCell extends GridStaticSection.StaticCell { + + protected HeaderCell(HeaderRow row) { + super(row); + } + } + + private HeaderRow defaultRow = null; + private final GridStaticSectionState headerState = new GridStaticSectionState(); + + protected GridHeader(Grid grid) { + this.grid = grid; + grid.getState(true).header = headerState; + HeaderRow row = createRow(); + rows.add(row); + setDefaultRow(row); + getState().rows.add(row.getRowState()); + } + + /** + * Sets the default row of this header. The default row is a special header + * row providing a user interface for sorting columns. + * + * @param row + * the new default row, or null for no default row + * + * @throws IllegalArgumentException + * this header does not contain the row + */ + public void setDefaultRow(HeaderRow row) { + if (row == defaultRow) { + return; + } + + if (row != null && !rows.contains(row)) { + throw new IllegalArgumentException( + "Cannot set a default row that does not exist in the section"); + } + + if (defaultRow != null) { + defaultRow.setDefaultRow(false); + } + + if (row != null) { + row.setDefaultRow(true); + } + + defaultRow = row; + markAsDirty(); + } + + /** + * Returns the current default row of this header. The default row is a + * special header row providing a user interface for sorting columns. + * + * @return the default row or null if no default row set + */ + public HeaderRow getDefaultRow() { + return defaultRow; + } + + @Override + protected GridStaticSectionState getState() { + return headerState; + } + + @Override + protected HeaderRow createRow() { + return new HeaderRow(this); + } + + @Override + public HeaderRow removeRow(int rowIndex) { + HeaderRow row = super.removeRow(rowIndex); + if (row == defaultRow) { + // Default Header Row was just removed. + setDefaultRow(null); + } + return row; + } +} diff --git a/server/src/com/vaadin/ui/components/grid/GridStaticSection.java b/server/src/com/vaadin/ui/components/grid/GridStaticSection.java new file mode 100644 index 0000000000..80d822e7bc --- /dev/null +++ b/server/src/com/vaadin/ui/components/grid/GridStaticSection.java @@ -0,0 +1,273 @@ +/* + * Copyright 2000-2014 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 com.vaadin.data.Container.Indexed; +import com.vaadin.shared.ui.grid.GridStaticSectionState; +import com.vaadin.shared.ui.grid.GridStaticSectionState.CellState; +import com.vaadin.shared.ui.grid.GridStaticSectionState.RowState; + +/** + * Abstract base class for Grid header and footer sections. + * + * @since + * @author Vaadin Ltd + * @param + * the type of the rows in the section + */ +abstract class GridStaticSection> + implements Serializable { + + /** + * Abstract base class for Grid header and footer rows. + * + * @param + * the type of the cells in the row + */ + abstract static class StaticRow> implements + Serializable { + + private RowState rowState = new RowState(); + protected GridStaticSection section; + private Map cells = new LinkedHashMap(); + + protected StaticRow(GridStaticSection section) { + this.section = section; + } + + protected void addCell(Object propertyId) { + CELLTYPE cell = createCell(); + cells.put(propertyId, cell); + rowState.cells.add(cell.getCellState()); + } + + /** + * Creates and returns a new instance of the cell type. + * + * @return the created cell + */ + protected abstract CELLTYPE createCell(); + + protected RowState getRowState() { + return rowState; + } + + /** + * Returns the cell at the given position in this row. + * + * @param propertyId + * the itemId of column + * @return the cell on given column + * @throws IndexOutOfBoundsException + * if the index is out of bounds + */ + public CELLTYPE getCell(Object propertyId) { + return cells.get(propertyId); + } + } + + /** + * A header or footer cell. Has a simple textual caption. + * + * @param + * the type of row this cells is in + */ + abstract static class StaticCell> implements + Serializable { + + private CellState cellState = new CellState(); + private ROWTYPE row; + + protected StaticCell(ROWTYPE row) { + this.row = row; + } + + /** + * Gets the row where this cell is. + * + * @return row for this cell + */ + public ROWTYPE getRow() { + return row; + } + + protected CellState getCellState() { + return cellState; + } + + /** + * Gets the current text content of this cell. Text is null if HTML or + * Component content is used. + * + * @return text content or null + */ + public String getText() { + return cellState.text; + } + + /** + * Sets the current text content of this cell. + * + * @param text + * new text content + */ + public void setText(String text) { + if (text != null && !text.equals(getCellState().text)) { + getCellState().text = text; + row.section.markAsDirty(); + } + } + } + + protected Grid grid; + protected List rows = new ArrayList(); + + /** + * Sets the visibility of the whole section. + * + * @param visible + * true to show this section, false to hide + */ + public void setVisible(boolean visible) { + if (getState().visible != visible) { + getState().visible = visible; + markAsDirty(); + } + } + + /** + * Returns the visibility of this section. + * + * @return true if visible, false otherwise. + */ + public boolean isVisible() { + return getState().visible; + } + + /** + * Removes the row at the given position. + * + * @param index + * the position of the row + * + * @throws IndexOutOfBoundsException + * if the index is out of bounds + */ + public ROWTYPE removeRow(int rowIndex) { + ROWTYPE row = rows.remove(rowIndex); + getState().rows.remove(rowIndex); + + markAsDirty(); + return row; + } + + /** + * Removes the given row from the section. + * + * @param row + * the row to be removed + * + * @throws IllegalArgumentException + * if the row does not exist in this section + */ + public void removeRow(ROWTYPE row) { + try { + removeRow(rows.indexOf(row)); + } catch (IndexOutOfBoundsException e) { + throw new IllegalArgumentException( + "Section does not contain the given row"); + } + } + + /** + * Gets row at given index. + * + * @param rowIndex + * 0 based index for row. Counted from top to bottom + * @return row at given index + */ + public ROWTYPE getRow(int rowIndex) { + return rows.get(rowIndex); + } + + /** + * Adds a new row at the top of this section. + * + * @return the new row + */ + public ROWTYPE prependRow() { + return addRowAt(0); + } + + /** + * Adds a new row at the bottom of this section. + * + * @return the new row + */ + public ROWTYPE appendRow() { + return addRowAt(rows.size()); + } + + /** + * Inserts a new row at the given position. + * + * @param index + * the position at which to insert the row + * @return the new row + * + * @throws IndexOutOfBoundsException + * if the index is out of bounds + */ + public ROWTYPE addRowAt(int index) { + ROWTYPE row = createRow(); + rows.add(index, row); + getState().rows.add(index, row.getRowState()); + + Indexed dataSource = grid.getContainerDatasource(); + for (Object id : dataSource.getContainerPropertyIds()) { + row.addCell(id); + } + + markAsDirty(); + return row; + } + + /** + * Gets the amount of rows in this section. + * + * @return row count + */ + public int getRowCount() { + return rows.size(); + } + + protected abstract GridStaticSectionState getState(); + + protected abstract ROWTYPE createRow(); + + /** + * Informs the grid that state has changed and it should be redrawn. + */ + protected void markAsDirty() { + grid.markAsDirty(); + } +} diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java index 9d71d21d59..d1c821cc54 100644 --- a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java +++ b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java @@ -77,7 +77,8 @@ public class GridColumns { assertNotNull(column); // Property id should be the column header by default - assertEquals(propertyId.toString(), column.getHeaderCaption()); + assertEquals(propertyId.toString(), grid.getHeader() + .getDefaultRow().getCell(propertyId).getText()); } } @@ -88,11 +89,6 @@ public class GridColumns { GridColumn column = grid.getColumn("column1"); assertNotNull(column); - column.setFooterCaption("CustomFooter"); - assertEquals("CustomFooter", column.getFooterCaption()); - assertEquals(column.getFooterCaption(), - getColumnState("column1").footer); - column.setHeaderCaption("CustomHeader"); assertEquals("CustomHeader", column.getHeaderCaption()); assertEquals(column.getHeaderCaption(), @@ -174,31 +170,31 @@ public class GridColumns { @Test public void testHeaderVisiblility() throws Exception { - assertTrue(grid.isColumnHeadersVisible()); + assertTrue(grid.getHeader().isVisible()); assertTrue(state.header.visible); - grid.setColumnHeadersVisible(false); - assertFalse(grid.isColumnHeadersVisible()); + grid.getHeader().setVisible(false); + assertFalse(grid.getHeader().isVisible()); assertFalse(state.header.visible); - grid.setColumnHeadersVisible(true); - assertTrue(grid.isColumnHeadersVisible()); + grid.getHeader().setVisible(true); + assertTrue(grid.getHeader().isVisible()); assertTrue(state.header.visible); } @Test public void testFooterVisibility() throws Exception { - assertFalse(grid.isColumnFootersVisible()); - assertFalse(state.footer.visible); - - grid.setColumnFootersVisible(false); - assertFalse(grid.isColumnFootersVisible()); + assertFalse(grid.getFooter().isVisible()); assertFalse(state.footer.visible); - grid.setColumnFootersVisible(true); - assertTrue(grid.isColumnFootersVisible()); + grid.getFooter().setVisible(true); + assertTrue(grid.getFooter().isVisible()); assertTrue(state.footer.visible); + + grid.getFooter().setVisible(false); + assertFalse(grid.getFooter().isVisible()); + assertFalse(state.footer.visible); } @Test diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java index cfe3646295..bff16d8db7 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -36,6 +36,9 @@ import com.vaadin.ui.components.grid.ColumnGroupRow; import com.vaadin.ui.components.grid.Grid; import com.vaadin.ui.components.grid.Grid.SelectionMode; import com.vaadin.ui.components.grid.GridColumn; +import com.vaadin.ui.components.grid.GridFooter; +import com.vaadin.ui.components.grid.GridHeader; +import com.vaadin.ui.components.grid.GridHeader.HeaderRow; import com.vaadin.ui.components.grid.SortOrderChangeEvent; import com.vaadin.ui.components.grid.SortOrderChangeListener; import com.vaadin.ui.components.grid.renderers.DateRenderer; @@ -142,15 +145,20 @@ public class GridBasicFeatures extends AbstractComponentTest { new NumberRenderer()); } + // Create footer + GridFooter footer = grid.getFooter(); + footer.appendRow(); + footer.setVisible(false); + // Add footer values (header values are automatically created) for (int col = 0; col < COLUMNS; col++) { - grid.getColumn(getColumnProperty(col)).setFooterCaption( - "Footer " + col); + footer.getRow(0).getCell(getColumnProperty(col)) + .setText("Footer " + col); } // Set varying column widths for (int col = 0; col < COLUMNS; col++) { - grid.getColumn("Column" + col).setWidth(100 + col * 50); + grid.getColumn(getColumnProperty(col)).setWidth(100 + col * 50); } grid.addSortOrderChangeListener(new SortOrderChangeListener() { @@ -226,29 +234,125 @@ public class GridBasicFeatures extends AbstractComponentTest { } protected void createHeaderActions() { - createCategory("Headers", null); + createCategory("Header", null); - createBooleanAction("Visible", "Headers", true, + createBooleanAction("Visible", "Header", true, new Command() { @Override public void execute(Grid grid, Boolean value, Object data) { - grid.setColumnHeadersVisible(value); + grid.getHeader().setVisible(value); } }); + + LinkedHashMap defaultRows = new LinkedHashMap(); + defaultRows.put("Top", "Top"); + defaultRows.put("Bottom", "Bottom"); + defaultRows.put("Unset", "Unset"); + + createMultiClickAction("Default row", "Header", defaultRows, + new Command() { + + @Override + public void execute(Grid grid, String value, Object data) { + HeaderRow defaultRow = null; + GridHeader header = grid.getHeader(); + if (value.equals("Top")) { + defaultRow = header.getRow(0); + } else if (value.equals("Bottom")) { + defaultRow = header.getRow(header.getRowCount() - 1); + } + header.setDefaultRow(defaultRow); + } + + }, defaultRows.get("Top")); + + createClickAction("Prepend row", "Header", new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getHeader().prependRow(); + } + + }, null); + createClickAction("Append row", "Header", new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getHeader().appendRow(); + } + + }, null); + + createClickAction("Remove top row", "Header", + new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getHeader().removeRow(0); + } + + }, null); + createClickAction("Remove bottom row", "Header", + new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getHeader().removeRow( + grid.getHeader().getRowCount() - 1); + } + + }, null); } protected void createFooterActions() { - createCategory("Footers", null); + createCategory("Footer", null); - createBooleanAction("Visible", "Footers", false, + createBooleanAction("Visible", "Footer", false, new Command() { @Override public void execute(Grid grid, Boolean value, Object data) { - grid.setColumnFootersVisible(value); + grid.getFooter().setVisible(value); } }); + + createClickAction("Prepend row", "Footer", new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getFooter().prependRow(); + } + + }, null); + createClickAction("Append row", "Footer", new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getFooter().appendRow(); + } + + }, null); + + createClickAction("Remove top row", "Footer", + new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getFooter().removeRow(0); + } + + }, null); + createClickAction("Remove bottom row", "Footer", + new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getFooter().removeRow( + grid.getFooter().getRowCount() - 1); + } + + }, null); } protected void createColumnActions() { @@ -278,7 +382,8 @@ public class GridBasicFeatures extends AbstractComponentTest { @Override public void execute(Grid grid, String value, Object data) { grid.getContainerDatasource() - .removeContainerProperty("Column" + data); + .removeContainerProperty( + getColumnProperty((Integer) data)); } }, null, c); @@ -287,7 +392,7 @@ public class GridBasicFeatures extends AbstractComponentTest { @Override public void execute(Grid grid, String value, Object data) { - grid.setLastFrozenPropertyId("Column" + data); + grid.setLastFrozenPropertyId(getColumnProperty((Integer) data)); } }, null, c); @@ -306,9 +411,9 @@ public class GridBasicFeatures extends AbstractComponentTest { } }, c); - createCategory("Column" + c + " Width", getColumnProperty(c)); + createCategory("Column " + c + " Width", getColumnProperty(c)); - createClickAction("Auto", "Column" + c + " Width", + createClickAction("Auto", "Column " + c + " Width", new Command() { @Override @@ -324,7 +429,7 @@ public class GridBasicFeatures extends AbstractComponentTest { }, -1, c); for (int w = 50; w < 300; w += 50) { - createClickAction(w + "px", "Column" + c + " Width", + createClickAction(w + "px", "Column " + c + " Width", new Command() { @Override @@ -343,7 +448,7 @@ public class GridBasicFeatures extends AbstractComponentTest { } private static String getColumnProperty(int c) { - return "Column" + c; + return "Column " + c; } protected void createColumnGroupActions() { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java index 805213027e..e20b45bd1d 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java @@ -104,7 +104,7 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { public void testNavigationFromFooterToBody() { openTestURL(); - selectMenuPath("Component", "Footers", "Visible"); + selectMenuPath("Component", "Footer", "Visible"); GridElement grid = getGridElement(); grid.scrollToRow(300); @@ -146,7 +146,7 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { public void testNavigateBetweenFooterAndBodyWithTab() { openTestURL(); - selectMenuPath("Component", "Footers", "Visible"); + selectMenuPath("Component", "Footer", "Visible"); GridElement grid = getGridElement(); grid.getCell(10, 2).click(); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java index 4a1d7b7be1..ee3f2a632b 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; -import org.junit.Ignore; import org.junit.Test; import org.openqa.selenium.Keys; import org.openqa.selenium.interactions.Actions; @@ -30,11 +29,7 @@ import com.vaadin.tests.components.grid.GridElement; public class GridSortingTest extends GridBasicFeaturesTest { - /* - * TODO unignore once column header captions are reimplemented - */ @Test - @Ignore public void testProgrammaticSorting() throws IOException { openTestURL(); @@ -43,7 +38,7 @@ public class GridSortingTest extends GridBasicFeaturesTest { // Sorting by column 9 is sorting by row index that is represented as a // String. // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0) - sortBy("Column9, DESC"); + sortBy("Column 9, DESC"); assertTrue("Column 9 should have the sort-desc stylename", grid .getHeaderCell(0, 9).getAttribute("class") @@ -53,12 +48,12 @@ public class GridSortingTest extends GridBasicFeaturesTest { for (int i = 0; i < 3; ++i) { row += "9"; assertEquals( - "Grid is not sorted by Column9 using descending direction.", + "Grid is not sorted by Column 9 using descending direction.", "(" + row + ", 0)", grid.getCell(i, 0).getText()); } // Column 10 is random numbers from Random with seed 13334 - sortBy("Column10, ASC"); + sortBy("Column 10, ASC"); assertFalse( "Column 9 should no longer have the sort-desc stylename", @@ -75,7 +70,7 @@ public class GridSortingTest extends GridBasicFeaturesTest { for (int i = 0; i < 5; ++i) { assertGreater( - "Grid is not sorted by Column10 using ascending direction", + "Grid is not sorted by Column 10 using ascending direction", Integer.parseInt(grid.getCell(i + 1, 10).getText()), Integer.parseInt(grid.getCell(i, 10).getText())); @@ -83,10 +78,10 @@ public class GridSortingTest extends GridBasicFeaturesTest { // Column 7 is row index as a number. Last three row are original rows // 2, 1 and 0. - sortBy("Column7, DESC"); + sortBy("Column 7, DESC"); for (int i = 0; i < 3; ++i) { assertEquals( - "Grid is not sorted by Column7 using descending direction", + "Grid is not sorted by Column 7 using descending direction", "(" + i + ", 0)", grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); } @@ -118,18 +113,18 @@ public class GridSortingTest extends GridBasicFeaturesTest { for (int i = 0; i < 3; ++i) { row += "9"; assertEquals( - "Grid is not sorted by Column9 using descending direction.", + "Grid is not sorted by Column 9 using descending direction.", "(" + row + ", 0)", grid.getCell(i, 0).getText()); } - assertEquals("2. Sort order: [Column9 ASCENDING]", getLogRow(2)); - assertEquals("4. Sort order: [Column9 DESCENDING]", getLogRow(0)); + assertEquals("2. Sort order: [Column 9 ASCENDING]", getLogRow(2)); + assertEquals("4. Sort order: [Column 9 DESCENDING]", getLogRow(0)); // Column 10 is random numbers from Random with seed 13334 // Click header to sort ascending grid.getHeaderCell(0, 10).click(); - assertEquals("6. Sort order: [Column10 ASCENDING]", getLogRow(0)); + assertEquals("6. Sort order: [Column 10 ASCENDING]", getLogRow(0)); // Not cleaning up correctly causes exceptions when scrolling. grid.scrollToRow(50); @@ -138,7 +133,7 @@ public class GridSortingTest extends GridBasicFeaturesTest { for (int i = 0; i < 5; ++i) { assertGreater( - "Grid is not sorted by Column10 using ascending direction", + "Grid is not sorted by Column 10 using ascending direction", Integer.parseInt(grid.getCell(i + 1, 10).getText()), Integer.parseInt(grid.getCell(i, 10).getText())); @@ -151,13 +146,13 @@ public class GridSortingTest extends GridBasicFeaturesTest { grid.getHeaderCell(0, 7).click(); for (int i = 0; i < 3; ++i) { assertEquals( - "Grid is not sorted by Column7 using descending direction", + "Grid is not sorted by Column 7 using descending direction", "(" + i + ", 0)", grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); } - assertEquals("9. Sort order: [Column7 ASCENDING]", getLogRow(3)); - assertEquals("11. Sort order: [Column7 DESCENDING]", getLogRow(1)); + assertEquals("9. Sort order: [Column 7 ASCENDING]", getLogRow(3)); + assertEquals("11. Sort order: [Column 7 DESCENDING]", getLogRow(1)); } @Test diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java index 94f04e10a2..ced6963c32 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java @@ -22,7 +22,6 @@ import static org.junit.Assert.assertTrue; import java.util.List; -import org.junit.Ignore; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; @@ -31,44 +30,36 @@ import com.vaadin.testbench.TestBenchElement; public class GridStructureTest extends GridBasicFeaturesTest { - /* - * TODO unignore once column header captions are reimplemented - */ @Test - @Ignore public void testHidingColumn() throws Exception { openTestURL(); // Column 0 should be visible List cells = getGridHeaderRowCells(); - assertEquals("Column0", cells.get(0).getText()); + assertEquals("Column 0", cells.get(0).getText()); // Hide column 0 - selectMenuPath("Component", "Columns", "Column0", "Visible"); + selectMenuPath("Component", "Columns", "Column 0", "Visible"); // Column 1 should now be the first cell cells = getGridHeaderRowCells(); - assertEquals("Column1", cells.get(0).getText()); + assertEquals("Column 1", cells.get(0).getText()); } - /* - * TODO unignore once column header captions are reimplemented - */ @Test - @Ignore public void testRemovingColumn() throws Exception { openTestURL(); // Column 0 should be visible List cells = getGridHeaderRowCells(); - assertEquals("Column0", cells.get(0).getText()); + assertEquals("Column 0", cells.get(0).getText()); // Hide column 0 - selectMenuPath("Component", "Columns", "Column0", "Remove"); + selectMenuPath("Component", "Columns", "Column 0", "Remove"); // Column 1 should now be the first cell cells = getGridHeaderRowCells(); - assertEquals("Column1", cells.get(0).getText()); + assertEquals("Column 1", cells.get(0).getText()); } @Test @@ -76,9 +67,9 @@ public class GridStructureTest extends GridBasicFeaturesTest { openTestURL(); // Remove columns 2,3,4 - selectMenuPath("Component", "Columns", "Column2", "Remove"); - selectMenuPath("Component", "Columns", "Column3", "Remove"); - selectMenuPath("Component", "Columns", "Column4", "Remove"); + selectMenuPath("Component", "Columns", "Column 2", "Remove"); + selectMenuPath("Component", "Columns", "Column 3", "Remove"); + selectMenuPath("Component", "Columns", "Column 4", "Remove"); // Scroll so new data is lazy loaded scrollGridVerticallyTo(1000); @@ -95,7 +86,7 @@ public class GridStructureTest extends GridBasicFeaturesTest { openTestURL(); // Freeze column 2 - selectMenuPath("Component", "Columns", "Column2", "Freeze"); + selectMenuPath("Component", "Columns", "Column 2", "Freeze"); WebElement cell = getBodyCellByRowAndColumn(0, 0); assertTrue(cell.getAttribute("class").contains("frozen")); @@ -127,20 +118,20 @@ public class GridStructureTest extends GridBasicFeaturesTest { assertEquals(100, cell.getSize().getWidth()); // Set first column to be 200px wide - selectMenuPath("Component", "Columns", "Column0", "Column0 Width", + selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", "200px"); cell = getBodyCellByRowAndColumn(0, 0); assertEquals(200, cell.getSize().getWidth()); // Set second column to be 150px wide - selectMenuPath("Component", "Columns", "Column1", "Column1 Width", + selectMenuPath("Component", "Columns", "Column 1", "Column 1 Width", "150px"); cell = getBodyCellByRowAndColumn(0, 1); assertEquals(150, cell.getSize().getWidth()); // Set first column to be auto sized (defaults to 100px currently) - selectMenuPath("Component", "Columns", "Column0", "Column0 Width", + selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", "Auto"); cell = getBodyCellByRowAndColumn(0, 0); @@ -203,7 +194,7 @@ public class GridStructureTest extends GridBasicFeaturesTest { selectMenuPath("Component", "Body rows", "Modify first row (getContainerProperty)"); assertEquals("(Second) modification with getItemProperty failed", - "modified: Column0", getBodyCellByRowAndColumn(0, 0).getText()); + "modified: Column 0", getBodyCellByRowAndColumn(0, 0).getText()); } private void assertPrimaryStylename(String stylename) { -- cgit v1.2.3 From b51f6ebc0d0e60d20f40f4492e865d990b80ceb2 Mon Sep 17 00:00:00 2001 From: John Ahlroos Date: Thu, 31 Jul 2014 15:34:58 +0300 Subject: Fixes setting width before adding column to grid #13334 Change-Id: Iddc16a9b84b2d52b39d44280b3d73a656c971fd0 --- client/src/com/vaadin/client/ui/grid/Grid.java | 9 +--- .../GridClientColumnPropertiesTest.java | 58 ++++++++++++++++++++++ .../client/grid/GridBasicClientFeatures.java | 26 +++++++++- 3 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientColumnPropertiesTest.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index d946be3d9e..dbfaf15813 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -1193,14 +1193,7 @@ public class Grid extends Composite implements * @return pixel width of the column */ public int getWidth() { - if (grid == null) { - return width; - } else { - int index = findIndexOfColumn(); - ColumnConfiguration conf = grid.escalator - .getColumnConfiguration(); - return conf.getColumnWidth(index); - } + return width; } /** diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientColumnPropertiesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientColumnPropertiesTest.java new file mode 100644 index 0000000000..c9e048cc7f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientColumnPropertiesTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeatures; + +public class GridClientColumnPropertiesTest extends GridBasicClientFeaturesTest { + + @Test + public void initialColumnWidths() { + openTestURL(); + + for (int col = 0; col < GridBasicClientFeatures.COLUMNS; col++) { + int width = getGridElement().getCell(0, col).getSize().getWidth(); + if (col <= 6) { + // Growing column widths + assertEquals(50 + col * 25, width); + } else { + assertEquals(100, width); + } + } + } + + @Test + public void testChangingColumnWidth() { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Width", "50px"); + int width = getGridElement().getCell(0, 0).getSize().getWidth(); + assertEquals(50, width); + + selectMenuPath("Component", "Columns", "Column 0", "Width", "200px"); + width = getGridElement().getCell(0, 0).getSize().getWidth(); + assertEquals(200, width); + + selectMenuPath("Component", "Columns", "Column 0", "Width", "auto"); + width = getGridElement().getCell(0, 0).getSize().getWidth(); + assertEquals(100, width); + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java index 7d4b29ba5d..1c9758b669 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -145,13 +145,17 @@ public class GridBasicClientFeatures extends final int c = col; - grid.addColumn(new GridColumn>( + GridColumn> column = new GridColumn>( createRenderer(Renderers.TEXT_RENDERER)) { @Override public String getValue(List row) { return (String) row.get(c).value; } - }); + }; + + column.setWidth(50 + c * 25); + + grid.addColumn(column); } @@ -273,6 +277,24 @@ public class GridBasicClientFeatures extends !grid.getColumn(index).isSortable()); } }, "Component", "Columns", "Column " + i); + addMenuCommand("auto", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setWidth(-1); + } + }, "Component", "Columns", "Column " + i, "Width"); + addMenuCommand("50px", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setWidth(50); + } + }, "Component", "Columns", "Column " + i, "Width"); + addMenuCommand("200px", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setWidth(200); + } + }, "Component", "Columns", "Column " + i, "Width"); } } -- cgit v1.2.3 From e16a0fb28ec04266ab01b6b9ff001b19cf32944b Mon Sep 17 00:00:00 2001 From: Henrik Paul Date: Mon, 4 Aug 2014 12:51:37 +0300 Subject: Remove deprecated header/footer API (#13334) Change-Id: I9bddef300a817fd31054515e97bc6924370d3475 --- .../com/vaadin/ui/components/grid/ColumnGroup.java | 165 ----------- .../vaadin/ui/components/grid/ColumnGroupRow.java | 303 --------------------- server/src/com/vaadin/ui/components/grid/Grid.java | 125 --------- .../server/component/grid/GridColumnGroups.java | 260 ------------------ .../vaadin/shared/ui/grid/ColumnGroupRowState.java | 46 ---- .../src/com/vaadin/shared/ui/grid/GridState.java | 5 - .../tests/components/grid/GridColumnGroups.java | 106 ------- .../grid/basicfeatures/GridBasicFeatures.java | 70 ----- 8 files changed, 1080 deletions(-) delete mode 100644 server/src/com/vaadin/ui/components/grid/ColumnGroup.java delete mode 100644 server/src/com/vaadin/ui/components/grid/ColumnGroupRow.java delete mode 100644 server/tests/src/com/vaadin/tests/server/component/grid/GridColumnGroups.java delete mode 100644 shared/src/com/vaadin/shared/ui/grid/ColumnGroupRowState.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/GridColumnGroups.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/server/src/com/vaadin/ui/components/grid/ColumnGroup.java b/server/src/com/vaadin/ui/components/grid/ColumnGroup.java deleted file mode 100644 index ec676dfb87..0000000000 --- a/server/src/com/vaadin/ui/components/grid/ColumnGroup.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2000-2014 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.Collections; -import java.util.List; - -import com.vaadin.shared.ui.grid.ColumnGroupState; - -/** - * Column groups are used to group columns together for adding common auxiliary - * headers and footers. Columns groups are added to {@link ColumnGroupRow}'s. - * - * @since - * @author Vaadin Ltd - */ -public class ColumnGroup implements Serializable { - - /** - * List of property ids belonging to this group - */ - private List columns; - - /** - * The grid the column group is associated with - */ - private final Grid grid; - - /** - * The column group row the column group is attached to - */ - private final ColumnGroupRow row; - - /** - * The common state between the server and the client - */ - private final ColumnGroupState state; - - /** - * Constructs a new column group - * - * @param grid - * the grid the column group is associated with - * @param state - * the state representing the data of the grid. Sent to the - * client - * @param propertyIds - * the property ids of the columns that belongs to the group - * @param groups - * the sub groups who should be included in this group - * - */ - ColumnGroup(Grid grid, ColumnGroupRow row, ColumnGroupState state, - List propertyIds) { - if (propertyIds == null) { - throw new IllegalArgumentException( - "propertyIds cannot be null. Use empty list instead."); - } - - this.state = state; - this.row = row; - columns = Collections.unmodifiableList(new ArrayList( - propertyIds)); - this.grid = grid; - } - - /** - * Sets the text displayed in the header of the column group. - * - * @param header - * the text displayed in the header of the column - */ - public void setHeaderCaption(String header) { - checkGroupIsAttached(); - state.header = header; - grid.markAsDirty(); - } - - /** - * Sets the text displayed in the header of the column group. - * - * @return the text displayed in the header of the column - */ - public String getHeaderCaption() { - checkGroupIsAttached(); - return state.header; - } - - /** - * Sets the text displayed in the footer of the column group. - * - * @param footer - * the text displayed in the footer of the column - */ - public void setFooterCaption(String footer) { - checkGroupIsAttached(); - state.footer = footer; - grid.markAsDirty(); - } - - /** - * The text displayed in the footer of the column group. - * - * @return the text displayed in the footer of the column - */ - public String getFooterCaption() { - checkGroupIsAttached(); - return state.footer; - } - - /** - * Is a property id in this group or in some sub group of this group. - * - * @param propertyId - * the property id to check for - * @return true if the property id is included in this group. - */ - public boolean isColumnInGroup(Object propertyId) { - if (columns.contains(propertyId)) { - return true; - } - return false; - } - - /** - * Returns a list of property ids where all also the child groups property - * ids are included. - * - * @return a unmodifiable list with all the columns in the group. Includes - * any subgroup columns as well. - */ - public List getColumns() { - return columns; - } - - /** - * Checks if column group is attached to a row and throws an - * {@link IllegalStateException} if it is not. - * - * @throws IllegalStateException - * if the column is no longer attached to any grid - */ - protected void checkGroupIsAttached() throws IllegalStateException { - if (!row.getState().groups.contains(state)) { - throw new IllegalStateException( - "Column Group has been removed from the row."); - } - } -} diff --git a/server/src/com/vaadin/ui/components/grid/ColumnGroupRow.java b/server/src/com/vaadin/ui/components/grid/ColumnGroupRow.java deleted file mode 100644 index a497b5a8a8..0000000000 --- a/server/src/com/vaadin/ui/components/grid/ColumnGroupRow.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2000-2014 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.Arrays; -import java.util.Collections; -import java.util.List; - -import com.vaadin.server.KeyMapper; -import com.vaadin.shared.ui.grid.ColumnGroupRowState; -import com.vaadin.shared.ui.grid.ColumnGroupState; - -/** - * A column group row represents an auxiliary header or footer row added to the - * grid. A column group row includes column groups that group columns together. - * - * @since - * @author Vaadin Ltd - */ -public class ColumnGroupRow implements Serializable { - - /** - * The common state shared between the client and server - */ - private final ColumnGroupRowState state; - - /** - * The column groups in this row - */ - private List groups = new ArrayList(); - - /** - * Grid that the group row belongs to - */ - private final Grid grid; - - /** - * The column keys used to identify the column on the client side - */ - private final KeyMapper columnKeys; - - /** - * Constructs a new column group - * - * @param grid - * The grid that the column group is associated to - * @param state - * The shared state which contains the data shared between server - * and client - * @param columnKeys - * The column key mapper for converting property ids to client - * side column identifiers - */ - ColumnGroupRow(Grid grid, ColumnGroupRowState state, - KeyMapper columnKeys) { - this.grid = grid; - this.columnKeys = columnKeys; - this.state = state; - } - - /** - * Gets the shared state for the column group row. Used internally to send - * the group row to the client. - * - * @return The current state of the row - */ - ColumnGroupRowState getState() { - return state; - } - - /** - * Add a new group to the row by using property ids for the columns. - * - * @param propertyIds - * The property ids of the columns that should be included in the - * group. A column can only belong in group on a row at a time. - * @return a column group representing the collection of columns added to - * the group - */ - public ColumnGroup addGroup(Object... propertyIds) - throws IllegalArgumentException { - assert propertyIds != null : "propertyIds cannot be null."; - - for (Object propertyId : propertyIds) { - if (hasColumnBeenGrouped(propertyId)) { - throw new IllegalArgumentException("Column " - + String.valueOf(propertyId) - + " already belongs to another group."); - } - } - - validateNewGroupProperties(Arrays.asList(propertyIds)); - - ColumnGroupState state = new ColumnGroupState(); - for (Object propertyId : propertyIds) { - assert propertyId != null : "null items in columns array not supported."; - state.columns.add(columnKeys.key(propertyId)); - } - this.state.groups.add(state); - - ColumnGroup group = new ColumnGroup(grid, this, state, - Arrays.asList(propertyIds)); - groups.add(group); - - grid.markAsDirty(); - return group; - } - - private void validateNewGroupProperties(List propertyIds) - throws IllegalArgumentException { - - /* - * Validate parent grouping - */ - int rowIndex = grid.getColumnGroupRows().indexOf(this); - int parentRowIndex = rowIndex - 1; - - // Get the parent row of this row. - ColumnGroupRow parentRow = null; - if (parentRowIndex > -1) { - parentRow = grid.getColumnGroupRows().get(parentRowIndex); - } - - if (parentRow == null) { - // A parentless row is always valid and is usually the first row - // added to the grid - return; - } - - for (Object id : propertyIds) { - if (parentRow.hasColumnBeenGrouped(id)) { - /* - * If a property has been grouped in the parent row then all of - * the properties in the parent group also needs to be included - * in the child group for the groups to be valid - */ - ColumnGroup parentGroup = parentRow.getGroupForProperty(id); - if (!propertyIds.containsAll(parentGroup.getColumns())) { - throw new IllegalArgumentException( - "Grouped properties overlaps previous grouping bounderies"); - } - } - } - } - - /** - * Add a new group to the row by using column instances. - * - * @param columns - * the columns that should belong to the group - * @return a column group representing the collection of columns added to - * the group - */ - public ColumnGroup addGroup(GridColumn... columns) - throws IllegalArgumentException { - assert columns != null : "columns cannot be null"; - - List propertyIds = new ArrayList(); - for (GridColumn column : columns) { - assert column != null : "null items in columns array not supported."; - - String columnId = column.getState().id; - Object propertyId = grid.getPropertyIdByColumnId(columnId); - propertyIds.add(propertyId); - } - return addGroup(propertyIds.toArray()); - } - - /** - * Add a new group to the row by using other already greated groups - * - * @param groups - * the subgroups of the group - * @return a column group representing the collection of columns added to - * the group - * - */ - public ColumnGroup addGroup(ColumnGroup... groups) - throws IllegalArgumentException { - assert groups != null : "groups cannot be null"; - - // Gather all groups columns into one list - List propertyIds = new ArrayList(); - for (ColumnGroup group : groups) { - propertyIds.addAll(group.getColumns()); - } - - validateNewGroupProperties(propertyIds); - - ColumnGroupState state = new ColumnGroupState(); - ColumnGroup group = new ColumnGroup(grid, this, state, propertyIds); - this.groups.add(group); - - // Update state - for (Object propertyId : group.getColumns()) { - state.columns.add(columnKeys.key(propertyId)); - } - this.state.groups.add(state); - - grid.markAsDirty(); - return group; - } - - /** - * Removes a group from the row. Does not remove the group from subgroups, - * to remove it from the subgroup invoke removeGroup on the subgroup. - * - * @param group - * the group to remove - */ - public void removeGroup(ColumnGroup group) { - int index = groups.indexOf(group); - groups.remove(index); - state.groups.remove(index); - grid.markAsDirty(); - } - - /** - * Get the groups in the row. - * - * @return unmodifiable list of groups in this row - */ - public List getGroups() { - return Collections.unmodifiableList(groups); - } - - /** - * Checks if a property id has been added to a group in this row. - * - * @param propertyId - * the property id to check for - * @return true if the column is included in a group - */ - private boolean hasColumnBeenGrouped(Object propertyId) { - return getGroupForProperty(propertyId) != null; - } - - private ColumnGroup getGroupForProperty(Object propertyId) { - for (ColumnGroup group : groups) { - if (group.isColumnInGroup(propertyId)) { - return group; - } - } - return null; - } - - /** - * Is the header visible for the row. - * - * @return true if header is visible - */ - public boolean isHeaderVisible() { - return state.headerVisible; - } - - /** - * Sets the header visible for the row. - * - * @param visible - * should the header be shown - */ - public void setHeaderVisible(boolean visible) { - state.headerVisible = visible; - grid.markAsDirty(); - } - - /** - * Is the footer visible for the row. - * - * @return true if footer is visible - */ - public boolean isFooterVisible() { - return state.footerVisible; - } - - /** - * Sets the footer visible for the row. - * - * @param visible - * should the footer be shown - */ - public void setFooterVisible(boolean visible) { - state.footerVisible = visible; - grid.markAsDirty(); - } - -} diff --git a/server/src/com/vaadin/ui/components/grid/Grid.java b/server/src/com/vaadin/ui/components/grid/Grid.java index 514a0496e2..5e21c7b70a 100644 --- a/server/src/com/vaadin/ui/components/grid/Grid.java +++ b/server/src/com/vaadin/ui/components/grid/Grid.java @@ -40,7 +40,6 @@ import com.vaadin.data.Container.Sortable; import com.vaadin.data.RpcDataProviderExtension; import com.vaadin.data.RpcDataProviderExtension.DataProviderKeyMapper; import com.vaadin.server.KeyMapper; -import com.vaadin.shared.ui.grid.ColumnGroupRowState; import com.vaadin.shared.ui.grid.GridClientRpc; import com.vaadin.shared.ui.grid.GridColumnState; import com.vaadin.shared.ui.grid.GridServerRpc; @@ -138,11 +137,6 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { */ private final KeyMapper columnKeys = new KeyMapper(); - /** - * The column groups added to the grid - */ - private final List columnGroupRows = new ArrayList(); - /** * The current sort order */ @@ -464,125 +458,6 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { return columns.get(propertyId); } - /** - * Sets the header rows visible. - * - * @param visible - * true if the header rows should be visible - */ - @Deprecated - public void setColumnHeadersVisible(boolean visible) { - getHeader().setVisible(visible); - } - - /** - * Are the header rows visible? - * - * @return true if the headers of the columns are visible - */ - @Deprecated - public boolean isColumnHeadersVisible() { - return getHeader().isVisible(); - } - - /** - * Sets the footer rows visible. - * - * @param visible - * true if the footer rows should be visible - */ - @Deprecated - public void setColumnFootersVisible(boolean visible) { - getFooter().setVisible(visible); - } - - /** - * Are the footer rows visible. - * - * @return true if the footer rows should be visible - */ - @Deprecated - public boolean isColumnFootersVisible() { - return getFooter().isVisible(); - } - - /** - *

- * Adds a new column group to the grid. - * - *

- * Column group rows are rendered in the header and footer of the grid. - * Column group rows are made up of column groups which groups together - * columns for adding a common auxiliary header or footer for the columns. - *

- *

- * - *

- * Example usage: - * - *

-     * // Add a new column group row to the grid
-     * ColumnGroupRow row = grid.addColumnGroupRow();
-     * 
-     * // Group "Column1" and "Column2" together to form a header in the row
-     * ColumnGroup column12 = row.addGroup("Column1", "Column2");
-     * 
-     * // Set a common header for "Column1" and "Column2"
-     * column12.setHeader("Column 1&2");
-     * 
- * - *

- * - * @return a column group instance you can use to add column groups - */ - @Deprecated - public ColumnGroupRow addColumnGroupRow() { - ColumnGroupRowState state = new ColumnGroupRowState(); - ColumnGroupRow row = new ColumnGroupRow(this, state, columnKeys); - columnGroupRows.add(row); - getState().columnGroupRows.add(state); - return row; - } - - /** - * Adds a new column group to the grid at a specific index - * - * @param rowIndex - * the index of the row - * @return a column group instance you can use to add column groups - */ - @Deprecated - public ColumnGroupRow addColumnGroupRow(int rowIndex) { - ColumnGroupRowState state = new ColumnGroupRowState(); - ColumnGroupRow row = new ColumnGroupRow(this, state, columnKeys); - columnGroupRows.add(rowIndex, row); - getState().columnGroupRows.add(rowIndex, state); - return row; - } - - /** - * Removes a column group. - * - * @param row - * the row to remove - */ - @Deprecated - public void removeColumnGroupRow(ColumnGroupRow row) { - columnGroupRows.remove(row); - getState().columnGroupRows.remove(row.getState()); - } - - /** - * Gets the column group rows. - * - * @return an unmodifiable list of column group rows - */ - @Deprecated - public List getColumnGroupRows() { - return Collections.unmodifiableList(new ArrayList( - columnGroupRows)); - } - /** * Used internally by the {@link Grid} to get a {@link GridColumn} by * referencing its generated state id. Also used by {@link GridColumn} to diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumnGroups.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumnGroups.java deleted file mode 100644 index 21bfbbb37e..0000000000 --- a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumnGroups.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2000-2014 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.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import com.vaadin.data.util.IndexedContainer; -import com.vaadin.server.KeyMapper; -import com.vaadin.shared.ui.grid.GridState; -import com.vaadin.ui.components.grid.ColumnGroup; -import com.vaadin.ui.components.grid.ColumnGroupRow; -import com.vaadin.ui.components.grid.Grid; - -public class GridColumnGroups { - - private Grid grid; - - private GridState state; - - private Method getStateMethod; - - private Field columnIdGeneratorField; - - private KeyMapper columnIdMapper; - - @Before - public void setup() throws Exception { - IndexedContainer ds = new IndexedContainer(); - for (int c = 0; c < 10; c++) { - ds.addContainerProperty("column" + c, String.class, ""); - } - grid = new Grid(ds); - - getStateMethod = Grid.class.getDeclaredMethod("getState"); - getStateMethod.setAccessible(true); - - state = (GridState) getStateMethod.invoke(grid); - - columnIdGeneratorField = Grid.class.getDeclaredField("columnKeys"); - columnIdGeneratorField.setAccessible(true); - - columnIdMapper = (KeyMapper) columnIdGeneratorField.get(grid); - } - - @Test - public void testColumnGroupRows() throws Exception { - - // No column group rows by default - List rows = grid.getColumnGroupRows(); - assertEquals(0, rows.size()); - - // Add some rows - ColumnGroupRow row1 = grid.addColumnGroupRow(); - ColumnGroupRow row3 = grid.addColumnGroupRow(); - ColumnGroupRow row2 = grid.addColumnGroupRow(1); - - rows = grid.getColumnGroupRows(); - assertEquals(3, rows.size()); - assertEquals(row1, rows.get(0)); - assertEquals(row2, rows.get(1)); - assertEquals(row3, rows.get(2)); - - // Header should be visible by default, footer should not - assertTrue(row1.isHeaderVisible()); - assertFalse(row1.isFooterVisible()); - - row1.setHeaderVisible(false); - assertFalse(row1.isHeaderVisible()); - row1.setHeaderVisible(true); - assertTrue(row1.isHeaderVisible()); - - row1.setFooterVisible(true); - assertTrue(row1.isFooterVisible()); - row1.setFooterVisible(false); - assertFalse(row1.isFooterVisible()); - - row1.setHeaderVisible(true); - row1.setFooterVisible(true); - assertTrue(row1.isHeaderVisible()); - assertTrue(row1.isFooterVisible()); - - row1.setHeaderVisible(false); - row1.setFooterVisible(false); - assertFalse(row1.isHeaderVisible()); - assertFalse(row1.isFooterVisible()); - } - - @Test - public void testColumnGroupsInState() throws Exception { - - // Add a new row - ColumnGroupRow row = grid.addColumnGroupRow(); - assertTrue(state.columnGroupRows.size() == 1); - - // Add a group by property id - ColumnGroup columns12 = row.addGroup("column1", "column2"); - assertTrue(state.columnGroupRows.get(0).groups.size() == 1); - - // Set header of column - columns12.setHeaderCaption("Column12"); - assertEquals("Column12", - state.columnGroupRows.get(0).groups.get(0).header); - - // Set footer of column - columns12.setFooterCaption("Footer12"); - assertEquals("Footer12", - state.columnGroupRows.get(0).groups.get(0).footer); - - // Add another group by column instance - ColumnGroup columns34 = row.addGroup(grid.getColumn("column3"), - grid.getColumn("column4")); - assertTrue(state.columnGroupRows.get(0).groups.size() == 2); - - // add another group row - ColumnGroupRow row2 = grid.addColumnGroupRow(); - assertTrue(state.columnGroupRows.size() == 2); - - // add a group by combining the two previous groups - ColumnGroup columns1234 = row2.addGroup(columns12, columns34); - assertTrue(columns1234.getColumns().size() == 4); - - // Insert a group as the second group - ColumnGroupRow newRow2 = grid.addColumnGroupRow(1); - assertTrue(state.columnGroupRows.size() == 3); - } - - @Test - public void testAddingColumnGroups() throws Exception { - - ColumnGroupRow row = grid.addColumnGroupRow(); - - // By property id - ColumnGroup columns01 = row.addGroup("column0", "column1"); - assertEquals(2, columns01.getColumns().size()); - assertEquals("column0", columns01.getColumns().get(0)); - assertTrue(columns01.isColumnInGroup("column0")); - assertEquals("column1", columns01.getColumns().get(1)); - assertTrue(columns01.isColumnInGroup("column1")); - - // By grid column - ColumnGroup columns23 = row.addGroup(grid.getColumn("column2"), - grid.getColumn("column3")); - assertEquals(2, columns23.getColumns().size()); - assertEquals("column2", columns23.getColumns().get(0)); - assertTrue(columns23.isColumnInGroup("column2")); - assertEquals("column3", columns23.getColumns().get(1)); - assertTrue(columns23.isColumnInGroup("column3")); - - // Combine groups - ColumnGroupRow row2 = grid.addColumnGroupRow(); - ColumnGroup columns0123 = row2.addGroup(columns01, columns23); - assertEquals(4, columns0123.getColumns().size()); - assertEquals("column0", columns0123.getColumns().get(0)); - assertTrue(columns0123.isColumnInGroup("column0")); - assertEquals("column1", columns0123.getColumns().get(1)); - assertTrue(columns0123.isColumnInGroup("column1")); - assertEquals("column2", columns0123.getColumns().get(2)); - assertTrue(columns0123.isColumnInGroup("column2")); - assertEquals("column3", columns0123.getColumns().get(3)); - assertTrue(columns0123.isColumnInGroup("column3")); - } - - @Test - public void testColumnGroupHeadersAndFooters() throws Exception { - - ColumnGroupRow row = grid.addColumnGroupRow(); - ColumnGroup group = row.addGroup("column1", "column2"); - - // Header - assertNull(group.getHeaderCaption()); - group.setHeaderCaption("My header"); - assertEquals("My header", group.getHeaderCaption()); - group.setHeaderCaption(null); - assertNull(group.getHeaderCaption()); - - // Footer - assertNull(group.getFooterCaption()); - group.setFooterCaption("My footer"); - assertEquals("My footer", group.getFooterCaption()); - group.setFooterCaption(null); - assertNull(group.getFooterCaption()); - } - - @Test - public void testColumnGroupDetachment() throws Exception { - - ColumnGroupRow row = grid.addColumnGroupRow(); - ColumnGroup group = row.addGroup("column1", "column2"); - - // Remove group - row.removeGroup(group); - - try { - group.setHeaderCaption("Header"); - fail("Should throw exception for setting header caption on detached group"); - } catch (IllegalStateException ise) { - - } - - try { - group.setFooterCaption("Footer"); - fail("Should throw exception for setting footer caption on detached group"); - } catch (IllegalStateException ise) { - - } - } - - @Test - public void testColumnGroupLimits() throws Exception { - - ColumnGroupRow row = grid.addColumnGroupRow(); - row.addGroup("column1", "column2"); - row.addGroup("column3", "column4"); - - try { - row.addGroup("column2", "column3"); - fail("Adding a group with already grouped properties should throw exception"); - } catch (IllegalArgumentException iae) { - - } - - ColumnGroupRow row2 = grid.addColumnGroupRow(); - - try { - row2.addGroup("column2", "column3"); - fail("Adding a group that breaks previous grouping boundaries should throw exception"); - } catch (IllegalArgumentException iae) { - - } - - // This however should not throw an exception as it spans completely - // over the parent rows groups - row2.addGroup("column1", "column2", "column3", "column4"); - - } -} diff --git a/shared/src/com/vaadin/shared/ui/grid/ColumnGroupRowState.java b/shared/src/com/vaadin/shared/ui/grid/ColumnGroupRowState.java deleted file mode 100644 index d3d5ea2495..0000000000 --- a/shared/src/com/vaadin/shared/ui/grid/ColumnGroupRowState.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2000-2013 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.List; - -/** - * The column group row data shared between the server and client - * - * @since - * @author Vaadin Ltd - */ -public class ColumnGroupRowState implements Serializable { - - /** - * The groups that has been added to the row - */ - public List groups = new ArrayList(); - - /** - * Is the header shown - */ - public boolean headerVisible = true; - - /** - * Is the footer shown - */ - public boolean footerVisible = false; - -} diff --git a/shared/src/com/vaadin/shared/ui/grid/GridState.java b/shared/src/com/vaadin/shared/ui/grid/GridState.java index 68ee64dfe4..54acc80127 100644 --- a/shared/src/com/vaadin/shared/ui/grid/GridState.java +++ b/shared/src/com/vaadin/shared/ui/grid/GridState.java @@ -102,11 +102,6 @@ public class GridState extends AbstractComponentState { public GridStaticSectionState footer = new GridStaticSectionState(); - /** - * The column groups added to the grid - */ - public List columnGroupRows = new ArrayList(); - /** * The id for the last frozen column. * diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColumnGroups.java b/uitest/src/com/vaadin/tests/components/grid/GridColumnGroups.java deleted file mode 100644 index f1199301d9..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/GridColumnGroups.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2000-2014 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; - -import com.vaadin.data.util.IndexedContainer; -import com.vaadin.server.VaadinRequest; -import com.vaadin.tests.components.AbstractTestUI; -import com.vaadin.ui.components.grid.ColumnGroup; -import com.vaadin.ui.components.grid.ColumnGroupRow; -import com.vaadin.ui.components.grid.Grid; -import com.vaadin.ui.components.grid.GridColumn; - -public class GridColumnGroups extends AbstractTestUI { - - private final int COLUMNS = 4; - - @Override - protected void setup(VaadinRequest request) { - - // Setup grid - IndexedContainer ds = new IndexedContainer(); - for (int col = 0; col < COLUMNS; col++) { - ds.addContainerProperty("Column" + col, String.class, ""); - } - Grid grid = new Grid(ds); - addComponent(grid); - - /*- - * --------------------------------------------- - * | Header 1 | <- Auxiliary row 2 - * |-------------------------------------------| - * | Header 2 | Header 3 | <- Auxiliary row 1 - * |-------------------------------------------| - * | Column 1 | Column 2 | Column 3 | Column 4 | <- Column headers - * --------------------------------------------| - * | ... | ... | ... | ... | - * | ... | ... | ... | ... | - * --------------------------------------------| - * | Column 1 | Column 2 | Column 3 | Column 4 | <- Column footers - * --------------------------------------------| - * | Footer 2 | Footer 3 | <- Auxiliary row 1 - * --------------------------------------------| - * | Footer 1 | <- Auxiliary row 2 - * --------------------------------------------- - -*/ - - // Set column footers (headers are generated automatically) - grid.setColumnFootersVisible(true); - for (Object propertyId : ds.getContainerPropertyIds()) { - GridColumn column = grid.getColumn(propertyId); - column.setFooterCaption(String.valueOf(propertyId)); - } - - // First auxiliary row - ColumnGroupRow auxRow1 = grid.addColumnGroupRow(); - - // Using property id to create a column group - ColumnGroup columns12 = auxRow1.addGroup("Column0", "Column1"); - columns12.setHeaderCaption("Header 2"); - columns12.setFooterCaption("Footer 2"); - - // Using grid columns to create a column group - GridColumn column3 = grid.getColumn("Column2"); - GridColumn column4 = grid.getColumn("Column3"); - ColumnGroup columns34 = auxRow1.addGroup(column3, column4); - columns34.setHeaderCaption("Header 3"); - columns34.setFooterCaption("Footer 3"); - - // Second auxiliary row - ColumnGroupRow auxRow2 = grid.addColumnGroupRow(); - - // Using previous groups to create a column group - ColumnGroup columns1234 = auxRow2.addGroup(columns12, columns34); - columns1234.setHeaderCaption("Header 1"); - columns1234.setFooterCaption("Footer 1"); - - } - - @Override - protected String getTestDescription() { - return "Grid should support headers and footer groups"; - } - - @Override - protected Integer getTicketNumber() { - return 12894; - } - -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java index bff16d8db7..9ab2c98bdb 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -31,8 +31,6 @@ import com.vaadin.data.util.IndexedContainer; import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.shared.ui.grid.SortDirection; import com.vaadin.tests.components.AbstractComponentTest; -import com.vaadin.ui.components.grid.ColumnGroup; -import com.vaadin.ui.components.grid.ColumnGroupRow; import com.vaadin.ui.components.grid.Grid; import com.vaadin.ui.components.grid.Grid.SelectionMode; import com.vaadin.ui.components.grid.GridColumn; @@ -178,8 +176,6 @@ public class GridBasicFeatures extends AbstractComponentTest { createFooterActions(); - createColumnGroupActions(); - createRowActions(); addHeightActions(); @@ -451,72 +447,6 @@ public class GridBasicFeatures extends AbstractComponentTest { return "Column " + c; } - protected void createColumnGroupActions() { - createCategory("Column groups", null); - - createClickAction("Add group row", "Column groups", - new Command() { - - @Override - public void execute(Grid grid, String value, Object data) { - final ColumnGroupRow row = grid.addColumnGroupRow(); - columnGroupRows++; - createCategory("Column group row " + columnGroupRows, - "Column groups"); - - createBooleanAction("Header Visible", - "Column group row " + columnGroupRows, true, - new Command() { - - @Override - public void execute(Grid grid, - Boolean value, Object columnIndex) { - row.setHeaderVisible(value); - } - }, row); - - createBooleanAction("Footer Visible", - "Column group row " + columnGroupRows, false, - new Command() { - - @Override - public void execute(Grid grid, - Boolean value, Object columnIndex) { - row.setFooterVisible(value); - } - }, row); - - for (int i = 0; i < COLUMNS; i++) { - final int columnIndex = i; - createClickAction("Group Column " + columnIndex - + " & " + (columnIndex + 1), - "Column group row " + columnGroupRows, - new Command() { - - @Override - public void execute(Grid c, - Integer value, Object data) { - final ColumnGroup group = row - .addGroup( - "Column" + value, - "Column" - + (value + 1)); - - group.setHeaderCaption("Column " - + value + " & " - + (value + 1)); - - group.setFooterCaption("Column " - + value + " & " - + (value + 1)); - } - }, i, row); - } - } - }, null, null); - - } - protected void createRowActions() { createCategory("Body rows", null); -- cgit v1.2.3 From a9fc5d5be75c8ca33231909d1a44f471b5dcaaf9 Mon Sep 17 00:00:00 2001 From: John Ahlroos Date: Thu, 7 Aug 2014 11:11:03 +0300 Subject: Fixes removing all rows causing javascript error #13334 Change-Id: If3850d2248c6731bf3ee55d73c4cba2999ff9882 --- shared/src/com/vaadin/shared/ui/grid/Range.java | 6 ++++++ .../tests/components/grid/basicfeatures/GridBasicFeatures.java | 9 +++++++++ .../tests/components/grid/basicfeatures/GridStructureTest.java | 10 ++++++++++ 3 files changed, 25 insertions(+) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/shared/src/com/vaadin/shared/ui/grid/Range.java b/shared/src/com/vaadin/shared/ui/grid/Range.java index a1d4d86103..38b2ff2a60 100644 --- a/shared/src/com/vaadin/shared/ui/grid/Range.java +++ b/shared/src/com/vaadin/shared/ui/grid/Range.java @@ -369,6 +369,12 @@ public final class Range implements Serializable { * if the two ranges aren't connected */ public Range combineWith(Range other) throws IllegalArgumentException { + if (other.isEmpty()) { + return this; + } else if (isEmpty()) { + return other; + } + if (getStart() > other.getEnd() || other.getStart() > getEnd()) { throw new IllegalArgumentException("There is a gap between " + this + " and " + other); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java index 9ab2c98bdb..8b3391253b 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -521,6 +521,15 @@ public class GridBasicFeatures extends AbstractComponentTest { } } }); + + createClickAction("Remove all rows", "Body rows", + new Command() { + @SuppressWarnings("unchecked") + @Override + public void execute(Grid c, String value, Object data) { + ds.removeAllItems(); + } + }, null); } @SuppressWarnings("boxing") diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java index ced6963c32..d52f512b4f 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java @@ -197,6 +197,16 @@ public class GridStructureTest extends GridBasicFeaturesTest { "modified: Column 0", getBodyCellByRowAndColumn(0, 0).getText()); } + @Test + public void testRemovingAllItems() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Body rows", "Remove all rows"); + + assertEquals(0, getGridElement().findElement(By.tagName("tbody")) + .findElements(By.tagName("tr")).size()); + } + private void assertPrimaryStylename(String stylename) { assertTrue(getGridElement().getAttribute("class").contains(stylename)); -- cgit v1.2.3 From a479a22f20d683b794350a7098abe78835c495b5 Mon Sep 17 00:00:00 2001 From: John Ahlroos Date: Mon, 4 Aug 2014 14:38:12 +0300 Subject: Take hidden columns into account when calculating colspan #13334 Change-Id: Ibaf5950408dfbd832efcca6882db94258f2e9b3a --- .../com/vaadin/client/ui/grid/FlyweightCell.java | 5 ++ client/src/com/vaadin/client/ui/grid/Grid.java | 11 +++- .../src/com/vaadin/client/ui/grid/GridFooter.java | 22 +++++++- .../src/com/vaadin/client/ui/grid/GridHeader.java | 21 ++++++- .../vaadin/client/ui/grid/GridStaticSection.java | 57 ++++++++++++++++--- .../grid/basicfeatures/GridHeaderTest.java | 65 ++++++++++++++++++++++ .../client/grid/GridBasicClientFeatures.java | 10 ++++ 7 files changed, 180 insertions(+), 11 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/FlyweightCell.java b/client/src/com/vaadin/client/ui/grid/FlyweightCell.java index de003f865c..b82fccfbe0 100644 --- a/client/src/com/vaadin/client/ui/grid/FlyweightCell.java +++ b/client/src/com/vaadin/client/ui/grid/FlyweightCell.java @@ -144,6 +144,11 @@ public class FlyweightCell { } public void setColSpan(final int numberOfCells) { + if (numberOfCells < 1) { + throw new IllegalArgumentException( + "Number of cells should be more than 0"); + } + /*- * This will default to 1 if unset, as per DOM specifications: * http://www.w3.org/TR/html5/tabular-data.html#attributes-common-to-td-and-th-elements diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index cff9f68454..580cf41165 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -45,6 +45,7 @@ import com.vaadin.client.Util; import com.vaadin.client.data.DataChangeHandler; import com.vaadin.client.data.DataSource; import com.vaadin.client.ui.SubPartAware; +import com.vaadin.client.ui.grid.GridFooter.FooterRow; import com.vaadin.client.ui.grid.GridHeader.HeaderRow; import com.vaadin.client.ui.grid.GridStaticSection.StaticCell; import com.vaadin.client.ui.grid.renderers.ComplexRenderer; @@ -923,7 +924,6 @@ public class Grid extends Composite implements this.visible = visible; - // Remove column if (grid != null) { int index = findIndexOfColumn(); ColumnConfiguration conf = grid.escalator @@ -934,8 +934,15 @@ public class Grid extends Composite implements } else { conf.removeColumns(index, 1); } - } + for (HeaderRow row : grid.getHeader().getRows()) { + row.calculateColspans(); + } + + for (FooterRow row : grid.getFooter().getRows()) { + row.calculateColspans(); + } + } } /** diff --git a/client/src/com/vaadin/client/ui/grid/GridFooter.java b/client/src/com/vaadin/client/ui/grid/GridFooter.java index eba6ad81cb..4470bbf6b9 100644 --- a/client/src/com/vaadin/client/ui/grid/GridFooter.java +++ b/client/src/com/vaadin/client/ui/grid/GridFooter.java @@ -15,6 +15,8 @@ */ package com.vaadin.client.ui.grid; +import com.google.gwt.core.client.Scheduler; + /** * Represents the footer section of a Grid. The footer is always empty. * @@ -50,6 +52,8 @@ public class GridFooter extends GridStaticSection { public class FooterCell extends GridStaticSection.StaticCell { } + private boolean markAsDirty = false; + @Override protected FooterRow createRow() { return new FooterRow(); @@ -57,6 +61,22 @@ public class GridFooter extends GridStaticSection { @Override protected void refreshSection() { - getGrid().refreshFooter(); + markAsDirty = true; + + /* + * Defer the refresh so if we multiple times call refreshSection() (for + * example when updating cell values) we only get one actual refresh in + * the end. + */ + Scheduler.get().scheduleFinally(new Scheduler.ScheduledCommand() { + + @Override + public void execute() { + if (markAsDirty) { + markAsDirty = false; + getGrid().refreshFooter(); + } + } + }); } } diff --git a/client/src/com/vaadin/client/ui/grid/GridHeader.java b/client/src/com/vaadin/client/ui/grid/GridHeader.java index 4e046873f4..e139d7b946 100644 --- a/client/src/com/vaadin/client/ui/grid/GridHeader.java +++ b/client/src/com/vaadin/client/ui/grid/GridHeader.java @@ -15,6 +15,7 @@ */ package com.vaadin.client.ui.grid; +import com.google.gwt.core.client.Scheduler; import com.vaadin.client.ui.grid.Grid.AbstractGridColumn.SortableColumnHeaderRenderer; /** @@ -68,6 +69,8 @@ public class GridHeader extends GridStaticSection { private HeaderRow defaultRow; + private boolean markAsDirty = false; + @Override public void removeRow(int index) { HeaderRow removedRow = getRow(index); @@ -134,6 +137,22 @@ public class GridHeader extends GridStaticSection { @Override protected void refreshSection() { - getGrid().refreshHeader(); + markAsDirty = true; + + /* + * Defer the refresh so if we multiple times call refreshSection() (for + * example when updating cell values) we only get one actual refresh in + * the end. + */ + Scheduler.get().scheduleFinally(new Scheduler.ScheduledCommand() { + + @Override + public void execute() { + if (markAsDirty) { + markAsDirty = false; + getGrid().refreshHeader(); + } + } + }); } } diff --git a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java index fa4f3e5ea0..c40c41594c 100644 --- a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java +++ b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java @@ -85,11 +85,18 @@ abstract class GridStaticSection> } /** + * Sets the colspan for the cell + * * @param colspan * the colspan to set */ public void setColspan(int colspan) { + if (colspan < 1) { + throw new IllegalArgumentException( + "Colspan cannot be less than 1"); + } this.colspan = colspan; + section.refreshSection(); } } @@ -201,7 +208,8 @@ abstract class GridStaticSection> return null; } - private void calculateColspans() { + void calculateColspans() { + // Reset all cells for (CELLTYPE cell : cells) { cell.setColspan(1); @@ -209,17 +217,52 @@ abstract class GridStaticSection> // Set colspan for grouped cells for (List group : cellGroups) { + + int firstVisibleColumnInGroup = -1; + int lastVisibleColumnInGroup = -1; + int hiddenInsideGroup = 0; + + /* + * To be able to calculate the colspan correctly we need to two + * things; find the first visible cell in the group which will + * get the colspan assigned to and find the amount of columns + * which should be spanned. + * + * To do that we iterate through all cells, marking into memory + * when we find the first visible cell, when we find the last + * visible cell and how many cells are hidden in between. + */ for (int i = 0; i < group.size(); i++) { CELLTYPE cell = group.get(i); - if (i == 0) { - // Assign full colspan to first cell - cell.setColspan(group.size()); - } else { - // Hide other cells - cell.setColspan(0); + int cellIndex = this.cells.indexOf(cell); + boolean columnVisible = getSection().getGrid() + .getColumn(cellIndex).isVisible(); + if (columnVisible) { + lastVisibleColumnInGroup = i; + if (firstVisibleColumnInGroup == -1) { + firstVisibleColumnInGroup = i; + } + } else if (firstVisibleColumnInGroup != -1) { + hiddenInsideGroup++; } } + + if (firstVisibleColumnInGroup == -1 + || lastVisibleColumnInGroup == -1 + || firstVisibleColumnInGroup == lastVisibleColumnInGroup) { + // No cells in group + continue; + } + + /* + * Assign colspan to first cell in group. + */ + CELLTYPE firstVisibleCell = group + .get(firstVisibleColumnInGroup); + firstVisibleCell.setColspan(lastVisibleColumnInGroup + - firstVisibleColumnInGroup - hiddenInsideGroup + 1); } + } protected void addCell(int index) { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java index 43d5aa47df..2665d5c669 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java @@ -211,6 +211,71 @@ public class GridHeaderTest extends GridStaticSectionTest { } } + @Test + public void hideFirstColumnInColspan() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join all columns"); + + int visibleColumns = GridBasicFeatures.COLUMNS; + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("" + visibleColumns, spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Columns", "Column 0", "Visible"); + visibleColumns--; + + spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("" + visibleColumns, spannedCell.getAttribute("colspan")); + } + + @Test + public void multipleColspanAndMultipleHiddenColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + // Join columns [1,2] and [3,4,5] + selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2"); + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("2", spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5"); + spannedCell = getGridElement().getHeaderCell(1, 3); + assertEquals("3", spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Columns", "Column 2", "Visible"); + spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("1", spannedCell.getAttribute("colspan")); + + // Ensure the second colspan is preserved (shifts one index to the left) + spannedCell = getGridElement().getHeaderCell(1, 2); + assertEquals("3", spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Columns", "Column 4", "Visible"); + + // First reduced colspan is reduced + spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("1", spannedCell.getAttribute("colspan")); + + // Second colspan is also now reduced + spannedCell = getGridElement().getHeaderCell(1, 2); + assertEquals("2", spannedCell.getAttribute("colspan")); + + // Show columns again + selectMenuPath("Component", "Columns", "Column 2", "Visible"); + selectMenuPath("Component", "Columns", "Column 4", "Visible"); + + spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("2", spannedCell.getAttribute("colspan")); + spannedCell = getGridElement().getHeaderCell(1, 3); + assertEquals("3", spannedCell.getAttribute("colspan")); + } + private void assertHeaderCount(int count) { assertEquals("header count", count, getGridElement().getHeaderCount()); } diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java index 1c9758b669..24cfe49239 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -396,6 +396,16 @@ public class GridBasicClientFeatures extends } }, menuPath); + addMenuCommand("Join columns 3, 4, 5", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumn(3), grid.getColumn(4), + grid.getColumn(5)); + + } + }, menuPath); + addMenuCommand("Join all columns", new ScheduledCommand() { @Override -- cgit v1.2.3 From 94dfb5d68dd6c1e3542edc80488fe53a9da2d0e5 Mon Sep 17 00:00:00 2001 From: John Ahlroos Date: Wed, 30 Jul 2014 13:27:51 +0300 Subject: Support HTML and Widgets in header/footer cells #13334 Change-Id: I1f9a4388b9b2e9e3892b31977eaf674ed4e0959b --- .../src/com/vaadin/client/ui/grid/Escalator.java | 8 +- client/src/com/vaadin/client/ui/grid/Grid.java | 82 +++++++++++-- .../com/vaadin/client/ui/grid/GridConnector.java | 2 +- .../src/com/vaadin/client/ui/grid/GridFooter.java | 10 +- .../src/com/vaadin/client/ui/grid/GridHeader.java | 14 +-- .../vaadin/client/ui/grid/GridStaticSection.java | 135 ++++++++++++++++++--- .../grid/basicfeatures/GridFooterTest.java | 59 +++++++++ .../grid/basicfeatures/GridHeaderTest.java | 79 +++++++++++- .../grid/basicfeatures/GridStaticSectionTest.java | 40 +++++- .../client/grid/GridBasicClientFeatures.java | 88 +++++++++++++- 10 files changed, 460 insertions(+), 57 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Escalator.java b/client/src/com/vaadin/client/ui/grid/Escalator.java index df564be937..7263313356 100644 --- a/client/src/com/vaadin/client/ui/grid/Escalator.java +++ b/client/src/com/vaadin/client/ui/grid/Escalator.java @@ -4405,7 +4405,13 @@ public class Escalator extends Widget { @SuppressWarnings("deprecation") com.google.gwt.user.client.Element castElement = (com.google.gwt.user.client.Element) possibleWidgetNode .cast(); - return Util.findWidget(castElement, null); + Widget w = Util.findWidget(castElement, null); + + // Ensure findWidget did not traverse past the cell element in the + // DOM hierarchy + if (cellNode.isOrHasChild(w.getElement())) { + return w; + } } return null; } diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 580cf41165..cf0606a38c 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -710,7 +710,7 @@ public class Grid extends Composite implements public Collection getConsumedEvents() { return Arrays.asList(BrowserEvents.TOUCHSTART, BrowserEvents.TOUCHMOVE, BrowserEvents.TOUCHEND, - BrowserEvents.TOUCHCANCEL, BrowserEvents.MOUSEDOWN); + BrowserEvents.TOUCHCANCEL, BrowserEvents.CLICK); } @Override @@ -774,11 +774,14 @@ public class Grid extends Composite implements lazySorter.cancel(); - } else if (BrowserEvents.MOUSEDOWN.equals(event.getType())) { - event.preventDefault(); + } else if (BrowserEvents.CLICK.equals(event.getType())) { lazySorter.setCurrentCell(cell); lazySorter.setMultisort(event.getShiftKey()); lazySorter.run(); + + // Active cell handling is also monitoring the click + // event so we allow event to propagate for it + return false; } return true; } @@ -1046,7 +1049,7 @@ public class Grid extends Composite implements @Override public void update(Row row, Iterable cellsToUpdate) { - GridStaticSection.StaticRow gridRow = section.getRow(row + GridStaticSection.StaticRow staticRow = section.getRow(row .getRow()); final List columnIndices = getVisibleColumnIndices(); @@ -1054,13 +1057,28 @@ public class Grid extends Composite implements for (FlyweightCell cell : cellsToUpdate) { int index = columnIndices.get(cell.getColumn()); - StaticCell metadata = gridRow.getCell(index); + final StaticCell metadata = staticRow.getCell(index); // Assign colspan to cell before rendering cell.setColSpan(metadata.getColspan()); - // Render - gridRow.getRenderer().render(cell, metadata.getText()); + // Decorates cell with possible indicators onto the cell. + // Actual content is rendered below. + staticRow.getRenderer().render(cell, null); + + switch (metadata.getType()) { + case TEXT: + cell.getElement().setInnerText(metadata.getText()); + break; + case HTML: + cell.getElement().setInnerHTML(metadata.getHtml()); + break; + case WIDGET: + preDetach(row, Arrays.asList(cell)); + cell.getElement().setInnerHTML(""); + postAttach(row, Arrays.asList(cell)); + break; + } activeCellHandler.updateActiveCellStyle(cell, container); } @@ -1072,10 +1090,60 @@ public class Grid extends Composite implements @Override public void postAttach(Row row, Iterable attachedCells) { + GridStaticSection.StaticRow gridRow = section.getRow(row + .getRow()); + List columnIndices = getVisibleColumnIndices(); + + for (FlyweightCell cell : attachedCells) { + int index = columnIndices.get(cell.getColumn()); + StaticCell metadata = gridRow.getCell(index); + /* + * If the cell contains widgets that are not currently attach + * then attach them now. + */ + if (StaticCell.Type.WIDGET.equals(metadata.getType())) { + final Widget widget = metadata.getWidget(); + final Element cellElement = cell.getElement(); + + if (!widget.isAttached()) { + + // Physical attach + cellElement.appendChild(widget.getElement()); + + // Logical attach + setParent(widget, Grid.this); + + getLogger().info("Attached widget " + widget); + } + } + } } @Override public void preDetach(Row row, Iterable cellsToDetach) { + if (section.getRowCount() > row.getRow()) { + GridStaticSection.StaticRow gridRow = section.getRow(row + .getRow()); + List columnIndices = getVisibleColumnIndices(); + for (FlyweightCell cell : cellsToDetach) { + int index = columnIndices.get(cell.getColumn()); + StaticCell metadata = gridRow.getCell(index); + + if (StaticCell.Type.WIDGET.equals(metadata.getType()) + && metadata.getWidget().isAttached()) { + + Widget widget = metadata.getWidget(); + + // Logical detach + setParent(widget, null); + + // Physical detach + widget.getElement().removeFromParent(); + + getLogger().info("Detached widget " + widget); + } + } + } } @Override diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java index 039e3b1074..56affc75d1 100644 --- a/client/src/com/vaadin/client/ui/grid/GridConnector.java +++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java @@ -317,7 +317,7 @@ public class GridConnector extends AbstractComponentConnector { section.setVisible(state.visible); - section.refreshSection(); + section.requestSectionRefresh(); } /** diff --git a/client/src/com/vaadin/client/ui/grid/GridFooter.java b/client/src/com/vaadin/client/ui/grid/GridFooter.java index 4470bbf6b9..e798139b9a 100644 --- a/client/src/com/vaadin/client/ui/grid/GridFooter.java +++ b/client/src/com/vaadin/client/ui/grid/GridFooter.java @@ -20,14 +20,6 @@ import com.google.gwt.core.client.Scheduler; /** * Represents the footer section of a Grid. The footer is always empty. * - * TODO Arbitrary number of footer rows (zero by default) - * - * TODO Merging footer cells - * - * TODO Widgets in cells - * - * TODO HTML in cells - * * @since * @author Vaadin Ltd */ @@ -60,7 +52,7 @@ public class GridFooter extends GridStaticSection { } @Override - protected void refreshSection() { + protected void requestSectionRefresh() { markAsDirty = true; /* diff --git a/client/src/com/vaadin/client/ui/grid/GridHeader.java b/client/src/com/vaadin/client/ui/grid/GridHeader.java index e139d7b946..f714848618 100644 --- a/client/src/com/vaadin/client/ui/grid/GridHeader.java +++ b/client/src/com/vaadin/client/ui/grid/GridHeader.java @@ -23,16 +23,6 @@ import com.vaadin.client.ui.grid.Grid.AbstractGridColumn.SortableColumnHeaderRen * row containing a header cell for each column. Each cell has a simple textual * caption. * - * TODO Arbitrary number of header rows (zero included, one by default) - * - * TODO Account for hidden columns when merging header cells - * - * TODO "Default" row with sorting - * - * TODO Widgets in cells - * - * TODO HTML in cells - * * @since * @author Vaadin Ltd */ @@ -117,7 +107,7 @@ public class GridHeader extends GridStaticSection { row.setDefault(true); } defaultRow = row; - refreshSection(); + requestSectionRefresh(); } /** @@ -136,7 +126,7 @@ public class GridHeader extends GridStaticSection { } @Override - protected void refreshSection() { + protected void requestSectionRefresh() { markAsDirty = true; /* diff --git a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java index c40c41594c..14e4d6de9c 100644 --- a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java +++ b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java @@ -21,7 +21,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; -import com.vaadin.client.ui.grid.renderers.TextRenderer; +import com.google.gwt.user.client.ui.Widget; /** * Abstract base class for Grid header and footer sections. @@ -36,18 +36,21 @@ abstract class GridStaticSection> /** * A header or footer cell. Has a simple textual caption. * - * TODO HTML content - * - * TODO Widget content */ static class StaticCell { - private String text = ""; + public enum Type { + TEXT, HTML, WIDGET; + } + + private Object content = null; private int colspan = 1; private GridStaticSection section; + private Type type = Type.TEXT; + /** * Sets the text displayed in this cell. * @@ -55,8 +58,9 @@ abstract class GridStaticSection> * a plain text caption */ public void setText(String text) { - this.text = text; - section.refreshSection(); + this.content = text; + this.type = Type.TEXT; + section.requestSectionRefresh(); } /** @@ -65,7 +69,11 @@ abstract class GridStaticSection> * @return the plain text caption */ public String getText() { - return text; + if (type != Type.TEXT) { + throw new IllegalStateException( + "Cannot fetch Text from a cell with type " + type); + } + return (String) content; } protected GridStaticSection getSection() { @@ -78,14 +86,17 @@ abstract class GridStaticSection> } /** - * @return the colspan + * Returns the amount of columns the cell spans. By default is 1. + * + * @return The amount of columns the cell spans. */ public int getColspan() { return colspan; } /** - * Sets the colspan for the cell + * Sets the amount of columns the cell spans. Must be more or equal to + * 1. By default is 1. * * @param colspan * the colspan to set @@ -95,10 +106,78 @@ abstract class GridStaticSection> throw new IllegalArgumentException( "Colspan cannot be less than 1"); } + this.colspan = colspan; - section.refreshSection(); + section.requestSectionRefresh(); + } + + /** + * Returns the html inside the cell. + * + * @throws IllegalStateException + * if trying to retrive HTML from a cell with a type other + * than {@link Type#HTML}. + * @return the html content of the cell. + */ + public String getHtml() { + if (type != Type.HTML) { + throw new IllegalStateException( + "Cannot fetch HTML from a cell with type " + type); + } + return (String) content; } + /** + * Sets the content of the cell to the provided html. All previous + * content is discarded and the cell type is set to {@link Type#HTML}. + * + * @param html + * The html content of the cell + */ + public void setHtml(String html) { + this.content = html; + this.type = Type.HTML; + section.requestSectionRefresh(); + } + + /** + * Returns the widget in the cell. + * + * @throws IllegalStateException + * if the cell is not {@link Type#WIDGET} + * + * @return the widget in the cell + */ + public Widget getWidget() { + if (type != Type.WIDGET) { + throw new IllegalStateException( + "Cannot fetch Widget from a cell with type " + type); + } + return (Widget) content; + } + + /** + * Set widget as the content of the cell. The type of the cell becomes + * {@link Type#WIDGET}. All previous content is discarded. + * + * @param widget + * The widget to add to the cell. Should not be previously + * attached anywhere (widget.getParent == null). + */ + public void setWidget(Widget widget) { + this.content = widget; + this.type = Type.WIDGET; + section.requestSectionRefresh(); + } + + /** + * Returns the type of the cell. + * + * @return the type of content the cell contains. + */ + public Type getType() { + return type; + } } /** @@ -111,7 +190,16 @@ abstract class GridStaticSection> private List cells = new ArrayList(); - private Renderer renderer = new TextRenderer(); + private Renderer renderer = new Renderer() { + + @Override + public void render(FlyweightCell cell, String data) { + /* + * The rendering into the cell is done directly from the updater + * since it needs to handle multiple types of data. + */ + } + }; private GridStaticSection section; @@ -160,10 +248,9 @@ abstract class GridStaticSection> // Create a new group cellGroups.add(new ArrayList(cells)); + // Calculates colspans, triggers refresh on section implicitly calculateColspans(); - getSection().refreshSection(); - // Returns first cell of group return cells.get(0); } @@ -309,8 +396,12 @@ abstract class GridStaticSection> /** * Informs the grid that this section should be re-rendered. + *

+ * Note that re-render means calling update() on each cell, + * preAttach()/postAttach()/preDetach()/postDetach() is not called as the + * cells are not removed from the DOM. */ - protected abstract void refreshSection(); + protected abstract void requestSectionRefresh(); /** * Sets the visibility of the whole section. @@ -320,7 +411,7 @@ abstract class GridStaticSection> */ public void setVisible(boolean visible) { this.visible = visible; - refreshSection(); + requestSectionRefresh(); } /** @@ -349,7 +440,8 @@ abstract class GridStaticSection> row.addCell(i); } rows.add(index, row); - refreshSection(); + + requestSectionRefresh(); return row; } @@ -382,7 +474,7 @@ abstract class GridStaticSection> */ public void removeRow(int index) { rows.remove(index); - refreshSection(); + requestSectionRefresh(); } /** @@ -414,7 +506,12 @@ abstract class GridStaticSection> * if the index is out of bounds */ public ROWTYPE getRow(int index) { - return rows.get(index); + try { + return rows.get(index); + } catch (IndexOutOfBoundsException e) { + throw new IllegalArgumentException("Row with index " + index + + " does not exist"); + } } /** diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java index c4e86369f9..d6a865ee29 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java @@ -17,9 +17,12 @@ package com.vaadin.tests.components.grid.basicfeatures; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; import com.vaadin.tests.components.grid.GridElement.GridCellElement; @@ -141,6 +144,62 @@ public class GridFooterTest extends GridStaticSectionTest { } } + @Test + public void testInitialCellTypes() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + GridCellElement textCell = getGridElement().getFooterCell(0, 0); + assertEquals("Footer (0,0)", textCell.getText()); + + GridCellElement widgetCell = getGridElement().getFooterCell(0, 1); + assertTrue(widgetCell.isElementPresent(By.className("gwt-HTML"))); + + GridCellElement htmlCell = getGridElement().getFooterCell(0, 2); + assertHTML("Footer (0,2)", htmlCell); + } + + @Test + public void testDynamicallyChangingCellType() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Columns", "Column 0", "Footer Type", + "Widget Footer"); + GridCellElement widgetCell = getGridElement().getFooterCell(0, 0); + assertTrue(widgetCell.isElementPresent(By.className("gwt-Button"))); + + selectMenuPath("Component", "Columns", "Column 1", "Footer Type", + "HTML Footer"); + GridCellElement htmlCell = getGridElement().getFooterCell(0, 1); + assertHTML("HTML Footer", htmlCell); + + selectMenuPath("Component", "Columns", "Column 2", "Footer Type", + "Text Footer"); + GridCellElement textCell = getGridElement().getFooterCell(0, 2); + assertEquals("Text Footer", textCell.getText()); + } + + @Test + public void testCellWidgetInteraction() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Columns", "Column 0", "Footer Type", + "Widget Footer"); + GridCellElement widgetCell = getGridElement().getFooterCell(0, 0); + WebElement button = widgetCell.findElement(By.className("gwt-Button")); + + assertNotEquals("Clicked", button.getText()); + + button.click(); + + assertEquals("Clicked", button.getText()); + } + private void assertFooterCount(int count) { assertEquals("footer count", count, getGridElement().getFooterCount()); } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java index 2665d5c669..ccffee854a 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java @@ -17,12 +17,15 @@ package com.vaadin.tests.components.grid.basicfeatures; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.List; import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; import com.vaadin.testbench.TestBenchElement; import com.vaadin.tests.components.grid.GridElement.GridCellElement; @@ -72,8 +75,8 @@ public class GridHeaderTest extends GridStaticSectionTest { assertEquals(GridBasicFeatures.COLUMNS - 2, cells.size()); assertText("Header (0,0)", cells.get(0)); - assertText("Header (0,2)", cells.get(1)); - assertText("Header (0,4)", cells.get(2)); + assertHTML("Header (0,2)", cells.get(1)); + assertHTML("Header (0,4)", cells.get(2)); selectMenuPath("Component", "Columns", "Column 3", "Visible"); @@ -81,9 +84,9 @@ public class GridHeaderTest extends GridStaticSectionTest { assertEquals(GridBasicFeatures.COLUMNS - 1, cells.size()); assertText("Header (0,0)", cells.get(0)); - assertText("Header (0,2)", cells.get(1)); + assertHTML("Header (0,2)", cells.get(1)); assertText("Header (0,3)", cells.get(2)); - assertText("Header (0,4)", cells.get(3)); + assertHTML("Header (0,4)", cells.get(3)); } @Test @@ -274,6 +277,74 @@ public class GridHeaderTest extends GridStaticSectionTest { assertEquals("2", spannedCell.getAttribute("colspan")); spannedCell = getGridElement().getHeaderCell(1, 3); assertEquals("3", spannedCell.getAttribute("colspan")); + + } + + @Test + public void testInitialCellTypes() throws Exception { + openTestURL(); + + GridCellElement textCell = getGridElement().getHeaderCell(0, 0); + assertEquals("Header (0,0)", textCell.getText()); + + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 1); + assertTrue(widgetCell.isElementPresent(By.className("gwt-HTML"))); + + GridCellElement htmlCell = getGridElement().getHeaderCell(0, 2); + assertHTML("Header (0,2)", htmlCell); + } + + @Test + public void testDynamicallyChangingCellType() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Header Type", + "Widget Header"); + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); + assertTrue(widgetCell.isElementPresent(By.className("gwt-Button"))); + + selectMenuPath("Component", "Columns", "Column 1", "Header Type", + "HTML Header"); + GridCellElement htmlCell = getGridElement().getHeaderCell(0, 1); + assertHTML("HTML Header", htmlCell); + + selectMenuPath("Component", "Columns", "Column 2", "Header Type", + "Text Header"); + GridCellElement textCell = getGridElement().getHeaderCell(0, 2); + assertEquals("Text Header", textCell.getText()); + } + + @Test + public void testCellWidgetInteraction() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Header Type", + "Widget Header"); + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); + WebElement button = widgetCell.findElement(By.className("gwt-Button")); + + button.click(); + + assertEquals("Clicked", button.getText()); + } + + @Test + public void widgetInSortableCellInteraction() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Header Type", + "Widget Header"); + + selectMenuPath("Component", "Columns", "Column 0", "Sortable"); + + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); + WebElement button = widgetCell.findElement(By.className("gwt-Button")); + + assertNotEquals("Clicked", button.getText()); + + button.click(); + + assertEquals("Clicked", button.getText()); } private void assertHeaderCount(int count) { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java index 8f6739e16d..5fac9cf860 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java @@ -30,7 +30,18 @@ public abstract class GridStaticSectionTest extends GridBasicClientFeaturesTest protected void assertHeaderTexts(int headerId, int rowIndex) { int i = 0; for (TestBenchElement cell : getGridElement().getHeaderCells(rowIndex)) { - assertText(String.format("Header (%d,%d)", headerId, i), cell); + + if (i % 3 == 0) { + assertText(String.format("Header (%d,%d)", headerId, i), cell); + } else if (i % 2 == 0) { + assertHTML(String.format("Header (%d,%d)", headerId, i), + cell); + } else { + assertHTML(String.format( + "

Header (%d,%d)
", + headerId, i), cell); + } + i++; } assertEquals("number of header columns", GridBasicFeatures.COLUMNS, i); @@ -39,7 +50,16 @@ public abstract class GridStaticSectionTest extends GridBasicClientFeaturesTest protected void assertFooterTexts(int footerId, int rowIndex) { int i = 0; for (TestBenchElement cell : getGridElement().getFooterCells(rowIndex)) { - assertText(String.format("Footer (%d,%d)", footerId, i), cell); + if (i % 3 == 0) { + assertText(String.format("Footer (%d,%d)", footerId, i), cell); + } else if (i % 2 == 0) { + assertHTML(String.format("Footer (%d,%d)", footerId, i), + cell); + } else { + assertHTML(String.format( + "
Footer (%d,%d)
", + footerId, i), cell); + } i++; } assertEquals("number of footer columns", GridBasicFeatures.COLUMNS, i); @@ -49,4 +69,20 @@ public abstract class GridStaticSectionTest extends GridBasicClientFeaturesTest // TBE.getText returns "" if the element is scrolled out of view assertEquals(text, e.getAttribute("innerHTML")); } + + protected static void assertHTML(String text, TestBenchElement e) { + String html = e.getAttribute("innerHTML"); + + // IE 8 returns tags as upper case while other browsers do not, make the + // comparison non-casesensive + html = html.toLowerCase(); + text = text.toLowerCase(); + + // IE 8 returns attributes without quotes, make the comparison without + // quotes + html = html.replaceAll("\"", ""); + text = html.replaceAll("\"", ""); + + assertEquals(text, html); + } } diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java index 24cfe49239..50f60f9847 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -21,6 +21,10 @@ import java.util.List; import java.util.Random; import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.HTML; import com.vaadin.client.ui.grid.FlyweightCell; import com.vaadin.client.ui.grid.Grid; import com.vaadin.client.ui.grid.Grid.SelectionMode; @@ -277,6 +281,7 @@ public class GridBasicClientFeatures extends !grid.getColumn(index).isSortable()); } }, "Component", "Columns", "Column " + i); + addMenuCommand("auto", new ScheduledCommand() { @Override public void execute() { @@ -295,6 +300,66 @@ public class GridBasicClientFeatures extends grid.getColumn(index).setWidth(200); } }, "Component", "Columns", "Column " + i, "Width"); + + // Header types + addMenuCommand("Text Header", new ScheduledCommand() { + @Override + public void execute() { + grid.getHeader().getRow(0).getCell(index) + .setText("Text Header"); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + addMenuCommand("HTML Header", new ScheduledCommand() { + @Override + public void execute() { + grid.getHeader().getRow(0).getCell(index) + .setHtml("HTML Header"); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + addMenuCommand("Widget Header", new ScheduledCommand() { + @Override + public void execute() { + final Button button = new Button("Button Header"); + button.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + button.setText("Clicked"); + } + }); + grid.getHeader().getRow(0).getCell(index).setWidget(button); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + + // Footer types + addMenuCommand("Text Footer", new ScheduledCommand() { + @Override + public void execute() { + grid.getFooter().getRow(0).getCell(index) + .setText("Text Footer"); + } + }, "Component", "Columns", "Column " + i, "Footer Type"); + addMenuCommand("HTML Footer", new ScheduledCommand() { + @Override + public void execute() { + grid.getFooter().getRow(0).getCell(index) + .setHtml("HTML Footer"); + } + }, "Component", "Columns", "Column " + i, "Footer Type"); + addMenuCommand("Widget Footer", new ScheduledCommand() { + @Override + public void execute() { + final Button button = new Button("Button Footer"); + button.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + button.setText("Clicked"); + } + }); + grid.getFooter().getRow(0).getCell(index).setWidget(button); + } + }, "Component", "Columns", "Column " + i, "Footer Type"); } } @@ -303,14 +368,32 @@ public class GridBasicClientFeatures extends private void setHeaderTexts(HeaderRow row) { for (int i = 0; i < COLUMNS; ++i) { - row.getCell(i).setText("Header (" + headerCounter + "," + i + ")"); + String caption = "Header (" + headerCounter + "," + i + ")"; + + // Lets use some different cell types + if (i % 3 == 0) { + row.getCell(i).setText(caption); + } else if (i % 2 == 0) { + row.getCell(i).setHtml("" + caption + ""); + } else { + row.getCell(i).setWidget(new HTML(caption)); + } } headerCounter++; } private void setFooterTexts(FooterRow row) { for (int i = 0; i < COLUMNS; ++i) { - row.getCell(i).setText("Footer (" + footerCounter + "," + i + ")"); + String caption = "Footer (" + footerCounter + "," + i + ")"; + + // Lets use some different cell types + if (i % 3 == 0) { + row.getCell(i).setText(caption); + } else if (i % 2 == 0) { + row.getCell(i).setHtml("" + caption + ""); + } else { + row.getCell(i).setWidget(new HTML(caption)); + } } footerCounter++; } @@ -449,6 +532,7 @@ public class GridBasicClientFeatures extends addMenuCommand("Remove bottom row", new ScheduledCommand() { @Override public void execute() { + assert footer.getRowCount() > 0; footer.removeRow(footer.getRowCount() - 1); } }, menuPath); -- cgit v1.2.3 From c8e0335ccd4e2af54efe752fc98b20c52fafabcf Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Fri, 1 Aug 2014 15:07:30 +0300 Subject: Add server side support for Components in Headers and Footers (#13334) Change-Id: Ic5a6b4c68bc2d09840cbd7faffebae8991a5fff4 --- client/src/com/vaadin/client/ui/grid/Grid.java | 5 +- .../com/vaadin/client/ui/grid/GridConnector.java | 42 +++++++++- .../vaadin/client/ui/grid/GridStaticSection.java | 21 +++-- server/src/com/vaadin/ui/components/grid/Grid.java | 38 ++++++++- .../com/vaadin/ui/components/grid/GridFooter.java | 2 +- .../com/vaadin/ui/components/grid/GridHeader.java | 2 +- .../ui/components/grid/GridStaticSection.java | 93 +++++++++++++++++----- .../vaadin/shared/ui/grid/GridStaticCellType.java | 39 +++++++++ .../shared/ui/grid/GridStaticSectionState.java | 8 ++ .../grid/basicfeatures/GridBasicFeatures.java | 88 ++++++++++++++++++++ .../GridStaticSectionComponentTest.java | 56 +++++++++++++ 11 files changed, 354 insertions(+), 40 deletions(-) create mode 100644 shared/src/com/vaadin/shared/ui/grid/GridStaticCellType.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index cf0606a38c..d1858a8f3f 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -62,6 +62,7 @@ import com.vaadin.client.ui.grid.sort.SortEvent; import com.vaadin.client.ui.grid.sort.SortEventHandler; import com.vaadin.client.ui.grid.sort.SortOrder; import com.vaadin.shared.ui.grid.GridConstants; +import com.vaadin.shared.ui.grid.GridStaticCellType; import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.shared.ui.grid.Range; import com.vaadin.shared.ui.grid.ScrollDestination; @@ -1101,7 +1102,7 @@ public class Grid extends Composite implements * If the cell contains widgets that are not currently attach * then attach them now. */ - if (StaticCell.Type.WIDGET.equals(metadata.getType())) { + if (GridStaticCellType.WIDGET.equals(metadata.getType())) { final Widget widget = metadata.getWidget(); final Element cellElement = cell.getElement(); @@ -1129,7 +1130,7 @@ public class Grid extends Composite implements int index = columnIndices.get(cell.getColumn()); StaticCell metadata = gridRow.getCell(index); - if (StaticCell.Type.WIDGET.equals(metadata.getType()) + if (GridStaticCellType.WIDGET.equals(metadata.getType()) && metadata.getWidget().isAttached()) { Widget widget = metadata.getWidget(); diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java index 56affc75d1..12952c7db8 100644 --- a/client/src/com/vaadin/client/ui/grid/GridConnector.java +++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java @@ -30,11 +30,13 @@ import java.util.logging.Logger; import com.google.gwt.json.client.JSONArray; import com.google.gwt.json.client.JSONObject; import com.google.gwt.json.client.JSONValue; +import com.vaadin.client.ComponentConnector; +import com.vaadin.client.ConnectorHierarchyChangeEvent; import com.vaadin.client.annotations.OnStateChange; import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.data.DataSource.RowHandle; import com.vaadin.client.data.RpcDataSourceConnector.RpcDataSource; -import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.client.ui.AbstractHasComponentsConnector; import com.vaadin.client.ui.grid.GridHeader.HeaderRow; import com.vaadin.client.ui.grid.GridStaticSection.StaticCell; import com.vaadin.client.ui.grid.GridStaticSection.StaticRow; @@ -73,7 +75,7 @@ import com.vaadin.shared.ui.grid.SortDirection; * @author Vaadin Ltd */ @Connect(com.vaadin.ui.components.grid.Grid.class) -public class GridConnector extends AbstractComponentConnector { +public class GridConnector extends AbstractHasComponentsConnector { /** * Custom implementation of the custom grid column using a JSONObject to @@ -297,8 +299,22 @@ public class GridConnector extends AbstractComponentConnector { int i = 0; for (CellState cellState : rowState.cells) { - StaticCell cell = row.getCell(diff + (i++)); - cell.setText(cellState.text); + StaticCell cell = row.getCell(i++); + switch (cellState.type) { + case TEXT: + cell.setText(cellState.text); + break; + case HTML: + cell.setHtml(cellState.text); + break; + case WIDGET: + ComponentConnector connector = (ComponentConnector) cellState.connector; + cell.setWidget(connector.getWidget()); + break; + default: + throw new IllegalStateException("unexpected cell type: " + + cellState.type); + } } for (List group : rowState.cellGroups) { @@ -570,4 +586,22 @@ public class GridConnector extends AbstractComponentConnector { + key.getClass().getSimpleName() + " (" + key + ")"; return (String) key; } + + /* + * (non-Javadoc) + * + * @see + * com.vaadin.client.HasComponentsConnector#updateCaption(com.vaadin.client + * .ComponentConnector) + */ + @Override + public void updateCaption(ComponentConnector connector) { + // TODO Auto-generated method stub + + } + + @Override + public void onConnectorHierarchyChange( + ConnectorHierarchyChangeEvent connectorHierarchyChangeEvent) { + } } diff --git a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java index 14e4d6de9c..1be0a92b8f 100644 --- a/client/src/com/vaadin/client/ui/grid/GridStaticSection.java +++ b/client/src/com/vaadin/client/ui/grid/GridStaticSection.java @@ -22,6 +22,7 @@ import java.util.HashSet; import java.util.List; import com.google.gwt.user.client.ui.Widget; +import com.vaadin.shared.ui.grid.GridStaticCellType; /** * Abstract base class for Grid header and footer sections. @@ -39,17 +40,13 @@ abstract class GridStaticSection> */ static class StaticCell { - public enum Type { - TEXT, HTML, WIDGET; - } - private Object content = null; private int colspan = 1; private GridStaticSection section; - private Type type = Type.TEXT; + private GridStaticCellType type = GridStaticCellType.TEXT; /** * Sets the text displayed in this cell. @@ -59,7 +56,7 @@ abstract class GridStaticSection> */ public void setText(String text) { this.content = text; - this.type = Type.TEXT; + this.type = GridStaticCellType.TEXT; section.requestSectionRefresh(); } @@ -69,7 +66,7 @@ abstract class GridStaticSection> * @return the plain text caption */ public String getText() { - if (type != Type.TEXT) { + if (type != GridStaticCellType.TEXT) { throw new IllegalStateException( "Cannot fetch Text from a cell with type " + type); } @@ -120,7 +117,7 @@ abstract class GridStaticSection> * @return the html content of the cell. */ public String getHtml() { - if (type != Type.HTML) { + if (type != GridStaticCellType.HTML) { throw new IllegalStateException( "Cannot fetch HTML from a cell with type " + type); } @@ -136,7 +133,7 @@ abstract class GridStaticSection> */ public void setHtml(String html) { this.content = html; - this.type = Type.HTML; + this.type = GridStaticCellType.HTML; section.requestSectionRefresh(); } @@ -149,7 +146,7 @@ abstract class GridStaticSection> * @return the widget in the cell */ public Widget getWidget() { - if (type != Type.WIDGET) { + if (type != GridStaticCellType.WIDGET) { throw new IllegalStateException( "Cannot fetch Widget from a cell with type " + type); } @@ -166,7 +163,7 @@ abstract class GridStaticSection> */ public void setWidget(Widget widget) { this.content = widget; - this.type = Type.WIDGET; + this.type = GridStaticCellType.WIDGET; section.requestSectionRefresh(); } @@ -175,7 +172,7 @@ abstract class GridStaticSection> * * @return the type of content the cell contains. */ - public Type getType() { + public GridStaticCellType getType() { return type; } } diff --git a/server/src/com/vaadin/ui/components/grid/Grid.java b/server/src/com/vaadin/ui/components/grid/Grid.java index 2e0ac6bb31..d365d3e0cc 100644 --- a/server/src/com/vaadin/ui/components/grid/Grid.java +++ b/server/src/com/vaadin/ui/components/grid/Grid.java @@ -45,10 +45,16 @@ import com.vaadin.shared.ui.grid.GridColumnState; import com.vaadin.shared.ui.grid.GridServerRpc; import com.vaadin.shared.ui.grid.GridState; import com.vaadin.shared.ui.grid.GridState.SharedSelectionMode; +import com.vaadin.shared.ui.grid.GridStaticCellType; import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.shared.ui.grid.ScrollDestination; import com.vaadin.shared.ui.grid.SortDirection; import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.Component; +import com.vaadin.ui.HasComponents; +import com.vaadin.ui.components.grid.GridFooter.FooterCell; +import com.vaadin.ui.components.grid.GridFooter.FooterRow; +import com.vaadin.ui.components.grid.GridHeader.HeaderCell; import com.vaadin.ui.components.grid.GridHeader.HeaderRow; import com.vaadin.ui.components.grid.selection.MultiSelectionModel; import com.vaadin.ui.components.grid.selection.NoSelectionModel; @@ -123,7 +129,8 @@ import com.vaadin.util.ReflectTools; * @since * @author Vaadin Ltd */ -public class Grid extends AbstractComponent implements SelectionChangeNotifier { +public class Grid extends AbstractComponent implements SelectionChangeNotifier, + HasComponents { /** * Selection modes representing built-in {@link SelectionModel @@ -1259,4 +1266,33 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier { public GridFooter getFooter() { return footer; } + + @Override + public Iterator iterator() { + List componentList = new ArrayList(); + + GridHeader header = getHeader(); + for (int i = 0; i < header.getRowCount(); ++i) { + HeaderRow row = header.getRow(i); + for (Object propId : datasource.getContainerPropertyIds()) { + HeaderCell cell = row.getCell(propId); + if (cell.getCellState().type == GridStaticCellType.WIDGET) { + componentList.add(cell.getComponent()); + } + } + } + + GridFooter footer = getFooter(); + for (int i = 0; i < footer.getRowCount(); ++i) { + FooterRow row = footer.getRow(i); + for (Object propId : datasource.getContainerPropertyIds()) { + FooterCell cell = row.getCell(propId); + if (cell.getCellState().type == GridStaticCellType.WIDGET) { + componentList.add(cell.getComponent()); + } + } + } + + return componentList.iterator(); + } } diff --git a/server/src/com/vaadin/ui/components/grid/GridFooter.java b/server/src/com/vaadin/ui/components/grid/GridFooter.java index 84b2b70090..0a28a481cf 100644 --- a/server/src/com/vaadin/ui/components/grid/GridFooter.java +++ b/server/src/com/vaadin/ui/components/grid/GridFooter.java @@ -38,7 +38,7 @@ public class GridFooter extends GridStaticSection { } - public class FooterCell extends GridStaticSection.StaticCell { + public class FooterCell extends GridStaticSection.StaticCell { protected FooterCell(FooterRow row) { super(row); diff --git a/server/src/com/vaadin/ui/components/grid/GridHeader.java b/server/src/com/vaadin/ui/components/grid/GridHeader.java index 67f7bfdf69..9d7ec24a97 100644 --- a/server/src/com/vaadin/ui/components/grid/GridHeader.java +++ b/server/src/com/vaadin/ui/components/grid/GridHeader.java @@ -41,7 +41,7 @@ public class GridHeader extends GridStaticSection { } } - public class HeaderCell extends GridStaticSection.StaticCell { + public class HeaderCell extends GridStaticSection.StaticCell { protected HeaderCell(HeaderRow row) { super(row); diff --git a/server/src/com/vaadin/ui/components/grid/GridStaticSection.java b/server/src/com/vaadin/ui/components/grid/GridStaticSection.java index 8c983052ea..eb098d0d4e 100644 --- a/server/src/com/vaadin/ui/components/grid/GridStaticSection.java +++ b/server/src/com/vaadin/ui/components/grid/GridStaticSection.java @@ -26,9 +26,11 @@ import java.util.List; import java.util.Map; import com.vaadin.data.Container.Indexed; +import com.vaadin.shared.ui.grid.GridStaticCellType; import com.vaadin.shared.ui.grid.GridStaticSectionState; import com.vaadin.shared.ui.grid.GridStaticSectionState.CellState; import com.vaadin.shared.ui.grid.GridStaticSectionState.RowState; +import com.vaadin.ui.Component; /** * Abstract base class for Grid header and footer sections. @@ -47,7 +49,7 @@ abstract class GridStaticSection> * @param * the type of the cells in the row */ - abstract static class StaticRow> implements + abstract static class StaticRow implements Serializable { private RowState rowState = new RowState(); @@ -184,17 +186,13 @@ abstract class GridStaticSection> /** * A header or footer cell. Has a simple textual caption. - * - * @param - * the type of row this cells is in */ - abstract static class StaticCell> implements - Serializable { + abstract static class StaticCell implements Serializable { private CellState cellState = new CellState(); - private ROWTYPE row; + private StaticRow row; - protected StaticCell(ROWTYPE row) { + protected StaticCell(StaticRow row) { this.row = row; } @@ -203,7 +201,7 @@ abstract class GridStaticSection> * * @return row for this cell */ - public ROWTYPE getRow() { + public StaticRow getRow() { return row; } @@ -212,26 +210,83 @@ abstract class GridStaticSection> } /** - * Gets the current text content of this cell. Text is null if HTML or - * Component content is used. + * Sets the text displayed in this cell. * - * @return text content or null + * @param text + * a plain text caption + */ + public void setText(String text) { + cellState.text = text; + cellState.type = GridStaticCellType.TEXT; + row.section.markAsDirty(); + } + + /** + * Returns the text displayed in this cell. + * + * @return the plain text caption */ public String getText() { + if (cellState.type != GridStaticCellType.TEXT) { + throw new IllegalStateException( + "Cannot fetch Text from a cell with type " + + cellState.type); + } return cellState.text; } /** - * Sets the current text content of this cell. + * Returns the HTML content displayed in this cell. + * + * @return the html * - * @param text - * new text content */ - public void setText(String text) { - if (text != null && !text.equals(getCellState().text)) { - getCellState().text = text; - row.section.markAsDirty(); + public String getHtml() { + if (cellState.type != GridStaticCellType.HTML) { + throw new IllegalStateException( + "Cannot fetch HTML from a cell with type " + + cellState.type); } + return cellState.html; + } + + /** + * Sets the HTML content displayed in this cell. + * + * @param html + * the html to set + */ + public void setHtml(String html) { + cellState.html = html; + cellState.type = GridStaticCellType.HTML; + row.section.markAsDirty(); + } + + /** + * Returns the component displayed in this cell. + * + * @return the component + */ + public Component getComponent() { + if (cellState.type != GridStaticCellType.WIDGET) { + throw new IllegalStateException( + "Cannot fetch Component from a cell with type " + + cellState.type); + } + return (Component) cellState.connector; + } + + /** + * Sets the component displayed in this cell. + * + * @param component + * the component to set + */ + public void setComponent(Component component) { + component.setParent(row.section.grid); + cellState.connector = component; + cellState.type = GridStaticCellType.WIDGET; + row.section.markAsDirty(); } } diff --git a/shared/src/com/vaadin/shared/ui/grid/GridStaticCellType.java b/shared/src/com/vaadin/shared/ui/grid/GridStaticCellType.java new file mode 100644 index 0000000000..eae4bc8da4 --- /dev/null +++ b/shared/src/com/vaadin/shared/ui/grid/GridStaticCellType.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2014 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; + +/** + * Enumeration, specifying the content type of a Cell in a GridStaticSection. + * + * @since + * @author Vaadin Ltd + */ +public enum GridStaticCellType { + /** + * Text content + */ + TEXT, + + /** + * HTML content + */ + HTML, + + /** + * Widget content + */ + WIDGET; +} \ No newline at end of file diff --git a/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java b/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java index 41f56199da..c3c373b5af 100644 --- a/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java +++ b/shared/src/com/vaadin/shared/ui/grid/GridStaticSectionState.java @@ -19,6 +19,8 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import com.vaadin.shared.Connector; + /** * Shared state for Grid headers and footers. * @@ -29,6 +31,12 @@ public class GridStaticSectionState implements Serializable { public static class CellState implements Serializable { public String text = ""; + + public String html = ""; + + public Connector connector = null; + + public GridStaticCellType type = GridStaticCellType.TEXT; } public static class RowState implements Serializable { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java index 8b3391253b..031ebf7fa5 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -28,14 +28,20 @@ import java.util.Random; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.util.IndexedContainer; +import com.vaadin.shared.ui.grid.GridStaticCellType; import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.shared.ui.grid.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.components.grid.Grid; import com.vaadin.ui.components.grid.Grid.SelectionMode; import com.vaadin.ui.components.grid.GridColumn; import com.vaadin.ui.components.grid.GridFooter; +import com.vaadin.ui.components.grid.GridFooter.FooterCell; import com.vaadin.ui.components.grid.GridHeader; +import com.vaadin.ui.components.grid.GridHeader.HeaderCell; import com.vaadin.ui.components.grid.GridHeader.HeaderRow; import com.vaadin.ui.components.grid.SortOrderChangeEvent; import com.vaadin.ui.components.grid.SortOrderChangeListener; @@ -440,6 +446,88 @@ public class GridBasicFeatures extends AbstractComponentTest { } }, w, c); } + + LinkedHashMap 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() { + + @Override + public void execute(Grid grid, + GridStaticCellType value, Object columnIndex) { + final Object propertyId = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((Integer) columnIndex)); + final HeaderCell cell = grid.getHeader() + .getDefaultRow().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() { + + @Override + public void execute(Grid grid, + GridStaticCellType value, Object columnIndex) { + final Object propertyId = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((Integer) columnIndex)); + final FooterCell cell = grid.getFooter().getRow(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); } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java new file mode 100644 index 0000000000..fe32825d75 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.junit.Test; + +import com.vaadin.testbench.elements.ButtonElement; + +public class GridStaticSectionComponentTest extends GridBasicFeaturesTest { + + @Test + public void testNativeButtonInHeader() throws IOException { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 1", "Header Type", + "Widget Header"); + + getGridElement().$(ButtonElement.class).first().click(); + + // Clicking also triggers sorting + assertEquals("2. Button clicked!", getLogRow(2)); + + compareScreen("button"); + } + + @Test + public void testNativeButtonInFooter() throws IOException { + openTestURL(); + + selectMenuPath("Component", "Footer", "Visible"); + selectMenuPath("Component", "Footer", "Append row"); + selectMenuPath("Component", "Columns", "Column 1", "Footer Type", + "Widget Footer"); + + getGridElement().$(ButtonElement.class).first().click(); + + assertEquals("4. Button clicked!", getLogRow(0)); + } +} -- cgit v1.2.3 From e5230e6a2433f5c8a74c66b73e96d0454866d316 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Thu, 7 Aug 2014 15:47:54 +0300 Subject: Remove unnecessary compareScreen from GridStaticSectionComponentTest Change-Id: I60d30508ba9a57a704b11032d970121bfb640793 --- .../components/grid/basicfeatures/GridStaticSectionComponentTest.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java index fe32825d75..d19d870548 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java @@ -36,8 +36,6 @@ public class GridStaticSectionComponentTest extends GridBasicFeaturesTest { // Clicking also triggers sorting assertEquals("2. Button clicked!", getLogRow(2)); - - compareScreen("button"); } @Test -- cgit v1.2.3 From 2ae0ff76032d5160c9bc9a7549a1c05c1434d800 Mon Sep 17 00:00:00 2001 From: John Ahlroos Date: Wed, 6 Aug 2014 14:38:11 +0300 Subject: Ensure primary stylenames are correct #13334 Change-Id: If8c220d70a1537006a042be25b36bf880209268d --- client/src/com/vaadin/client/ui/grid/Grid.java | 6 ++ .../vaadin/tests/components/grid/GridElement.java | 81 ++++++++++++++ .../basicfeatures/GridBasicClientFeaturesTest.java | 8 -- .../grid/basicfeatures/GridBasicFeaturesTest.java | 3 +- .../grid/basicfeatures/GridStructureTest.java | 51 ++++----- .../grid/basicfeatures/GridStylingTest.java | 118 +++++++++++++++++++++ .../client/grid/GridBasicClientFeatures.java | 28 +++++ 7 files changed, 254 insertions(+), 41 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStylingTest.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index d5582e0202..395d510ec4 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -1217,6 +1217,12 @@ public class Grid extends Composite implements cellActiveStyleName = getStylePrimaryName() + "-cell-active"; headerFooterActiveStyleName = getStylePrimaryName() + "-header-active"; rowActiveStyleName = getStylePrimaryName() + "-row-active"; + + if (isAttached()) { + refreshHeader(); + refreshBody(); + refreshFooter(); + } } /** diff --git a/uitest/src/com/vaadin/tests/components/grid/GridElement.java b/uitest/src/com/vaadin/tests/components/grid/GridElement.java index 3b28c4eaa2..bd8cad45c6 100644 --- a/uitest/src/com/vaadin/tests/components/grid/GridElement.java +++ b/uitest/src/com/vaadin/tests/components/grid/GridElement.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; import com.vaadin.testbench.By; import com.vaadin.testbench.TestBenchElement; @@ -185,6 +186,85 @@ public class GridElement extends AbstractComponentElement { return getSubPart("#footer").findElements(By.xpath("./tr")).size(); } + /** + * Get a header row by index + * + * @param rowIndex + * Row index + * @return The th element of the row + */ + public WebElement getHeaderRow(int rowIndex) { + return getSubPart("#header[" + rowIndex + "]"); + } + + /** + * Get a footer row by index + * + * @param rowIndex + * Row index + * @return The tr element of the row + */ + public WebElement getFooterRow(int rowIndex) { + return getSubPart("#footer[" + rowIndex + "]"); + } + + /** + * Get the vertical scroll element + * + * @return The element representing the vertical scrollbar + */ + public WebElement getVerticalScroller() { + List rootElements = findElements(By.xpath("./div")); + return rootElements.get(0); + } + + /** + * Get the horizontal scroll element + * + * @return The element representing the horizontal scrollbar + */ + public WebElement getHorizontalScroller() { + List rootElements = findElements(By.xpath("./div")); + return rootElements.get(1); + } + + /** + * Get the header element + * + * @return The thead element + */ + public WebElement getHeader() { + return getSubPart("#header"); + } + + /** + * Get the body element + * + * @return the tbody element + */ + public WebElement getBody() { + return getSubPart("#cell"); + } + + /** + * Get the footer element + * + * @return the tfoot element + */ + public WebElement getFooter() { + return getSubPart("#footer"); + } + + /** + * Get the element wrapping the table element + * + * @return The element that wraps the table element + */ + public WebElement getTableWrapper() { + List rootElements = findElements(By.xpath("./div")); + return rootElements.get(2); + } + /** * Helper function to get Grid subparts wrapped correctly * @@ -195,4 +275,5 @@ public class GridElement extends AbstractComponentElement { private TestBenchElement getSubPart(String subPartSelector) { return (TestBenchElement) findElement(By.vaadin(subPartSelector)); } + } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java index 559457ea1c..a8a2d4f12e 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java @@ -20,8 +20,6 @@ import org.openqa.selenium.Dimension; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; -import com.vaadin.testbench.TestBenchElement; -import com.vaadin.tests.components.grid.GridElement; import com.vaadin.tests.widgetset.server.grid.GridBasicClientFeatures; /** @@ -37,12 +35,6 @@ public abstract class GridBasicClientFeaturesTest extends GridBasicFeaturesTest return GridBasicClientFeatures.class; } - @Override - protected GridElement getGridElement() { - return ((TestBenchElement) findElement(By.className("v-grid"))) - .wrap(GridElement.class); - } - @Override protected void selectMenu(String menuCaption) { WebElement menuElement = getMenuElement(menuCaption); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java index 94d9766f78..6ef0ab5006 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java @@ -65,7 +65,8 @@ public abstract class GridBasicFeaturesTest extends MultiBrowserTest { } protected GridElement getGridElement() { - return $(GridElement.class).id("testComponent"); + return ((TestBenchElement) findElement(By.id("testComponent"))) + .wrap(GridElement.class); } protected void scrollGridVerticallyTo(double px) { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java index d52f512b4f..9adc4fa8a4 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java @@ -78,7 +78,7 @@ public class GridStructureTest extends GridBasicFeaturesTest { sleep(1000); // Check that row is loaded - assertThat(getBodyCellByRowAndColumn(11, 0).getText(), not("...")); + assertThat(getGridElement().getCell(11, 0).getText(), not("...")); } @Test @@ -88,10 +88,10 @@ public class GridStructureTest extends GridBasicFeaturesTest { // Freeze column 2 selectMenuPath("Component", "Columns", "Column 2", "Freeze"); - WebElement cell = getBodyCellByRowAndColumn(0, 0); + WebElement cell = getGridElement().getCell(0, 0); assertTrue(cell.getAttribute("class").contains("frozen")); - cell = getBodyCellByRowAndColumn(0, 1); + cell = getGridElement().getCell(0, 1); assertTrue(cell.getAttribute("class").contains("frozen")); } @@ -99,13 +99,13 @@ public class GridStructureTest extends GridBasicFeaturesTest { public void testInitialColumnWidths() throws Exception { openTestURL(); - WebElement cell = getBodyCellByRowAndColumn(0, 0); + WebElement cell = getGridElement().getCell(0, 0); assertEquals(100, cell.getSize().getWidth()); - cell = getBodyCellByRowAndColumn(0, 1); + cell = getGridElement().getCell(0, 1); assertEquals(150, cell.getSize().getWidth()); - cell = getBodyCellByRowAndColumn(0, 2); + cell = getGridElement().getCell(0, 2); assertEquals(200, cell.getSize().getWidth()); } @@ -114,27 +114,27 @@ public class GridStructureTest extends GridBasicFeaturesTest { openTestURL(); // Default column width is 100px - WebElement cell = getBodyCellByRowAndColumn(0, 0); + WebElement cell = getGridElement().getCell(0, 0); assertEquals(100, cell.getSize().getWidth()); // Set first column to be 200px wide selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", "200px"); - cell = getBodyCellByRowAndColumn(0, 0); + cell = getGridElement().getCell(0, 0); assertEquals(200, cell.getSize().getWidth()); // Set second column to be 150px wide selectMenuPath("Component", "Columns", "Column 1", "Column 1 Width", "150px"); - cell = getBodyCellByRowAndColumn(0, 1); + cell = getGridElement().getCell(0, 1); assertEquals(150, cell.getSize().getWidth()); // Set first column to be auto sized (defaults to 100px currently) selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", "Auto"); - cell = getBodyCellByRowAndColumn(0, 0); + cell = getGridElement().getCell(0, 0); assertEquals(100, cell.getSize().getWidth()); } @@ -184,17 +184,17 @@ public class GridStructureTest extends GridBasicFeaturesTest { openTestURL(); assertEquals("Unexpected cell initial state", "(0, 0)", - getBodyCellByRowAndColumn(0, 0).getText()); + getGridElement().getCell(0, 0).getText()); selectMenuPath("Component", "Body rows", "Modify first row (getItemProperty)"); assertEquals("(First) modification with getItemProperty failed", - "modified: 0", getBodyCellByRowAndColumn(0, 0).getText()); + "modified: 0", getGridElement().getCell(0, 0).getText()); selectMenuPath("Component", "Body rows", "Modify first row (getContainerProperty)"); assertEquals("(Second) modification with getItemProperty failed", - "modified: Column 0", getBodyCellByRowAndColumn(0, 0).getText()); + "modified: Column 0", getGridElement().getCell(0, 0).getText()); } @Test @@ -210,32 +210,19 @@ public class GridStructureTest extends GridBasicFeaturesTest { private void assertPrimaryStylename(String stylename) { assertTrue(getGridElement().getAttribute("class").contains(stylename)); - String tableWrapperStyleName = getTableWrapper().getAttribute("class"); + String tableWrapperStyleName = getGridElement().getTableWrapper() + .getAttribute("class"); assertTrue(tableWrapperStyleName.contains(stylename + "-tablewrapper")); - String hscrollStyleName = getHorizontalScroller().getAttribute("class"); + String hscrollStyleName = getGridElement().getHorizontalScroller() + .getAttribute("class"); assertTrue(hscrollStyleName.contains(stylename + "-scroller")); assertTrue(hscrollStyleName .contains(stylename + "-scroller-horizontal")); - String vscrollStyleName = getVerticalScroller().getAttribute("class"); + String vscrollStyleName = getGridElement().getVerticalScroller() + .getAttribute("class"); assertTrue(vscrollStyleName.contains(stylename + "-scroller")); assertTrue(vscrollStyleName.contains(stylename + "-scroller-vertical")); } - - private WebElement getBodyCellByRowAndColumn(int row, int column) { - return getGridElement().getCell(row, column); - } - - private WebElement getVerticalScroller() { - return getGridElement().findElement(By.xpath("./div[1]")); - } - - private WebElement getHorizontalScroller() { - return getGridElement().findElement(By.xpath("./div[2]")); - } - - private WebElement getTableWrapper() { - return getGridElement().findElement(By.xpath("./div[3]")); - } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStylingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStylingTest.java new file mode 100644 index 0000000000..e6c37ebf9d --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStylingTest.java @@ -0,0 +1,118 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.testbench.By; + +public class GridStylingTest extends GridStaticSectionTest { + + @Test + public void testGridPrimaryStyle() throws Exception { + openTestURL(); + + validateStylenames("v-grid"); + } + + @Test + public void testChangingPrimaryStyleName() throws Exception { + openTestURL(); + + selectMenuPath("Component", "State", "Primary Stylename", + "v-custom-style"); + + validateStylenames("v-custom-style"); + } + + private void validateStylenames(String stylename) { + + String classNames = getGridElement().getAttribute("class"); + assertEquals(stylename, classNames); + + classNames = getGridElement().getVerticalScroller().getAttribute( + "class"); + assertTrue(classNames.contains(stylename + "-scroller")); + assertTrue(classNames.contains(stylename + "-scroller-vertical")); + + classNames = getGridElement().getHorizontalScroller().getAttribute( + "class"); + assertTrue(classNames.contains(stylename + "-scroller")); + assertTrue(classNames.contains(stylename + "-scroller-horizontal")); + + classNames = getGridElement().getTableWrapper().getAttribute("class"); + assertEquals(stylename + "-tablewrapper", classNames); + + classNames = getGridElement().getHeader().getAttribute("class"); + assertEquals(stylename + "-header", classNames); + + for (int row = 0; row < getGridElement().getHeaderCount(); row++) { + classNames = getGridElement().getHeaderRow(row).getAttribute( + "class"); + assertEquals(stylename + "-row", classNames); + + for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { + classNames = getGridElement().getHeaderCell(row, col) + .getAttribute("class"); + assertTrue(classNames.contains(stylename + "-cell")); + + if (row == 0 && col == 0) { + assertTrue(classNames, + classNames.contains(stylename + "-header-active")); + } + } + } + + classNames = getGridElement().getBody().getAttribute("class"); + assertEquals(stylename + "-body", classNames); + + int rowsInBody = getGridElement().getBody() + .findElements(By.tagName("tr")).size(); + for (int row = 0; row < rowsInBody; row++) { + classNames = getGridElement().getRow(row).getAttribute("class"); + assertTrue(classNames.contains(stylename + "-row")); + assertTrue(classNames.contains(stylename + "-row-has-data")); + + for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { + classNames = getGridElement().getCell(row, col).getAttribute( + "class"); + assertTrue(classNames.contains(stylename + "-cell")); + + if (row == 0 && col == 0) { + assertTrue(classNames.contains(stylename + "-cell-active")); + } + } + } + + classNames = getGridElement().getFooter().getAttribute("class"); + assertEquals(stylename + "-footer", classNames); + + for (int row = 0; row < getGridElement().getFooterCount(); row++) { + classNames = getGridElement().getFooterRow(row).getAttribute( + "class"); + assertEquals(stylename + "-row", classNames); + + for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { + classNames = getGridElement().getFooterCell(row, col) + .getAttribute("class"); + assertTrue(classNames.contains(stylename + "-cell")); + } + } + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java index 50f60f9847..6eac275a9a 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java @@ -130,6 +130,7 @@ public class GridBasicClientFeatures extends ds = new ListDataSource>(data); grid = getTestedWidget(); + grid.getElement().setId("testComponent"); grid.setDataSource(ds); grid.setSelectionMode(SelectionMode.NONE); @@ -240,6 +241,8 @@ public class GridBasicClientFeatures extends private void createStateMenu() { String[] selectionModePath = { "Component", "State", "Selection mode" }; + String[] primaryStyleNamePath = { "Component", "State", + "Primary Stylename" }; addMenuCommand("multi", new ScheduledCommand() { @Override @@ -261,6 +264,31 @@ public class GridBasicClientFeatures extends grid.setSelectionMode(SelectionMode.NONE); } }, selectionModePath); + + addMenuCommand("v-grid", new ScheduledCommand() { + @Override + public void execute() { + grid.setStylePrimaryName("v-grid"); + + } + }, primaryStyleNamePath); + + addMenuCommand("v-escalator", new ScheduledCommand() { + @Override + public void execute() { + grid.setStylePrimaryName("v-escalator"); + + } + }, primaryStyleNamePath); + + addMenuCommand("v-custom-style", new ScheduledCommand() { + @Override + public void execute() { + grid.setStylePrimaryName("v-custom-style"); + + } + }, primaryStyleNamePath); + } private void createColumnsMenu() { -- cgit v1.2.3 From e944e870b7d417450579c8ec5520e9d00890d515 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Thu, 7 Aug 2014 10:54:42 +0300 Subject: Separate GridBasicFeature tests into client and server subpackages Also move GridBasicClientFeatures to more reasonable place and rename the client side UI so it won't collide in jetty path search. Change-Id: I9475e2fd28a00ec83eeb03ebc122c12eb840ac0b --- .../basicfeatures/GridBasicClientFeatures.java | 41 ++ .../basicfeatures/GridBasicClientFeaturesTest.java | 2 - .../GridClientColumnPropertiesTest.java | 58 -- .../basicfeatures/GridClientSelectionTest.java | 35 -- .../grid/basicfeatures/GridFooterTest.java | 206 ------- .../grid/basicfeatures/GridHeaderTest.java | 358 ------------ .../basicfeatures/GridKeyboardNavigationTest.java | 170 ------ .../grid/basicfeatures/GridSelectionTest.java | 150 ----- .../grid/basicfeatures/GridSortingTest.java | 185 ------ .../GridStaticSectionComponentTest.java | 54 -- .../grid/basicfeatures/GridStaticSectionTest.java | 88 --- .../grid/basicfeatures/GridStructureTest.java | 228 -------- .../grid/basicfeatures/GridStylingTest.java | 118 ---- .../client/GridClientColumnPropertiesTest.java | 59 ++ .../client/GridClientSelectionTest.java | 37 ++ .../grid/basicfeatures/client/GridFooterTest.java | 207 +++++++ .../grid/basicfeatures/client/GridHeaderTest.java | 359 ++++++++++++ .../client/GridStaticSectionTest.java | 90 +++ .../grid/basicfeatures/client/GridStylingTest.java | 119 ++++ .../server/GridKeyboardNavigationTest.java | 172 ++++++ .../basicfeatures/server/GridSelectionTest.java | 151 +++++ .../grid/basicfeatures/server/GridSortingTest.java | 187 ++++++ .../server/GridStaticSectionComponentTest.java | 55 ++ .../basicfeatures/server/GridStructureTest.java | 229 ++++++++ .../client/grid/GridBasicClientFeatures.java | 632 --------------------- .../grid/GridBasicClientFeaturesConnector.java | 9 +- .../client/grid/GridBasicClientFeaturesWidget.java | 632 +++++++++++++++++++++ .../server/grid/GridBasicClientFeatures.java | 41 -- 28 files changed, 2343 insertions(+), 2329 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientColumnPropertiesTest.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientSelectionTest.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java delete mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStylingTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java delete mode 100644 uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java delete mode 100644 uitest/src/com/vaadin/tests/widgetset/server/grid/GridBasicClientFeatures.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java new file mode 100644 index 0000000000..4c5e703b82 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2014 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.basicfeatures; + +import com.vaadin.annotations.Widgetset; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.UI; + +/** + * Initializer shell for GridClientBasicFeatures test application + * + * @since + * @author Vaadin Ltd + */ +@Widgetset(TestingWidgetSet.NAME) +public class GridBasicClientFeatures extends UI { + + public class GridTestComponent extends AbstractComponent { + } + + @Override + protected void init(VaadinRequest request) { + setContent(new GridTestComponent()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java index a8a2d4f12e..e3318fe650 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java @@ -20,8 +20,6 @@ import org.openqa.selenium.Dimension; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; -import com.vaadin.tests.widgetset.server.grid.GridBasicClientFeatures; - /** * Variant of GridBasicFeaturesTest to be used with GridBasicClientFeatures. * diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientColumnPropertiesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientColumnPropertiesTest.java deleted file mode 100644 index c9e048cc7f..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientColumnPropertiesTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeatures; - -public class GridClientColumnPropertiesTest extends GridBasicClientFeaturesTest { - - @Test - public void initialColumnWidths() { - openTestURL(); - - for (int col = 0; col < GridBasicClientFeatures.COLUMNS; col++) { - int width = getGridElement().getCell(0, col).getSize().getWidth(); - if (col <= 6) { - // Growing column widths - assertEquals(50 + col * 25, width); - } else { - assertEquals(100, width); - } - } - } - - @Test - public void testChangingColumnWidth() { - openTestURL(); - - selectMenuPath("Component", "Columns", "Column 0", "Width", "50px"); - int width = getGridElement().getCell(0, 0).getSize().getWidth(); - assertEquals(50, width); - - selectMenuPath("Component", "Columns", "Column 0", "Width", "200px"); - width = getGridElement().getCell(0, 0).getSize().getWidth(); - assertEquals(200, width); - - selectMenuPath("Component", "Columns", "Column 0", "Width", "auto"); - width = getGridElement().getCell(0, 0).getSize().getWidth(); - assertEquals(100, width); - } - -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientSelectionTest.java deleted file mode 100644 index cb70c28b7d..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridClientSelectionTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class GridClientSelectionTest extends GridBasicClientFeaturesTest { - - @Test - public void testChangeSelectionMode() { - openTestURL(); - - selectMenuPath("Component", "State", "Selection mode", "none"); - assertTrue("First column was selection column", getGridElement() - .getCell(0, 0).getText().equals("(0, 0)")); - selectMenuPath("Component", "State", "Selection mode", "multi"); - assertTrue("First column was not selection column", getGridElement() - .getCell(0, 1).getText().equals("(0, 0)")); - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java deleted file mode 100644 index d6a865ee29..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridFooterTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.WebElement; - -import com.vaadin.tests.components.grid.GridElement.GridCellElement; - -public class GridFooterTest extends GridStaticSectionTest { - - @Test - public void testDefaultFooter() { - openTestURL(); - - // Footer should have zero rows by default - assertFooterCount(0); - } - - @Test - public void testFooterVisibility() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Footer", "Visible"); - - assertFooterCount(0); - - selectMenuPath("Component", "Footer", "Append row"); - - assertFooterCount(0); - - selectMenuPath("Component", "Footer", "Visible"); - - assertFooterCount(1); - } - - @Test - public void testAddRows() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Footer", "Append row"); - - assertFooterCount(1); - assertFooterTexts(0, 0); - - selectMenuPath("Component", "Footer", "Prepend row"); - - assertFooterCount(2); - assertFooterTexts(1, 0); - assertFooterTexts(0, 1); - - selectMenuPath("Component", "Footer", "Append row"); - - assertFooterCount(3); - assertFooterTexts(1, 0); - assertFooterTexts(0, 1); - assertFooterTexts(2, 2); - } - - @Test - public void testRemoveRows() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Footer", "Prepend row"); - selectMenuPath("Component", "Footer", "Append row"); - - selectMenuPath("Component", "Footer", "Remove top row"); - - assertFooterCount(1); - assertFooterTexts(1, 0); - - selectMenuPath("Component", "Footer", "Remove bottom row"); - assertFooterCount(0); - } - - @Test - public void joinColumnsByCells() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Footer", "Append row"); - - selectMenuPath("Component", "Footer", "Row 1", "Join column cells 0, 1"); - - GridCellElement spannedCell = getGridElement().getFooterCell(0, 0); - assertTrue(spannedCell.isDisplayed()); - assertEquals("2", spannedCell.getAttribute("colspan")); - - GridCellElement hiddenCell = getGridElement().getFooterCell(0, 1); - assertFalse(hiddenCell.isDisplayed()); - } - - @Test - public void joinColumnsByColumns() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Footer", "Append row"); - - selectMenuPath("Component", "Footer", "Row 1", "Join columns 1, 2"); - - GridCellElement spannedCell = getGridElement().getFooterCell(0, 1); - assertTrue(spannedCell.isDisplayed()); - assertEquals("2", spannedCell.getAttribute("colspan")); - - GridCellElement hiddenCell = getGridElement().getFooterCell(0, 2); - assertFalse(hiddenCell.isDisplayed()); - } - - @Test - public void joinAllColumnsInRow() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Footer", "Append row"); - - selectMenuPath("Component", "Footer", "Row 1", "Join all columns"); - - GridCellElement spannedCell = getGridElement().getFooterCell(0, 0); - assertTrue(spannedCell.isDisplayed()); - assertEquals("" + GridBasicFeatures.COLUMNS, - spannedCell.getAttribute("colspan")); - - for (int columnIndex = 1; columnIndex < GridBasicFeatures.COLUMNS; columnIndex++) { - GridCellElement hiddenCell = getGridElement().getFooterCell(0, - columnIndex); - assertFalse(hiddenCell.isDisplayed()); - } - } - - @Test - public void testInitialCellTypes() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Footer", "Append row"); - - GridCellElement textCell = getGridElement().getFooterCell(0, 0); - assertEquals("Footer (0,0)", textCell.getText()); - - GridCellElement widgetCell = getGridElement().getFooterCell(0, 1); - assertTrue(widgetCell.isElementPresent(By.className("gwt-HTML"))); - - GridCellElement htmlCell = getGridElement().getFooterCell(0, 2); - assertHTML("Footer (0,2)", htmlCell); - } - - @Test - public void testDynamicallyChangingCellType() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Footer", "Append row"); - - selectMenuPath("Component", "Columns", "Column 0", "Footer Type", - "Widget Footer"); - GridCellElement widgetCell = getGridElement().getFooterCell(0, 0); - assertTrue(widgetCell.isElementPresent(By.className("gwt-Button"))); - - selectMenuPath("Component", "Columns", "Column 1", "Footer Type", - "HTML Footer"); - GridCellElement htmlCell = getGridElement().getFooterCell(0, 1); - assertHTML("HTML Footer", htmlCell); - - selectMenuPath("Component", "Columns", "Column 2", "Footer Type", - "Text Footer"); - GridCellElement textCell = getGridElement().getFooterCell(0, 2); - assertEquals("Text Footer", textCell.getText()); - } - - @Test - public void testCellWidgetInteraction() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Footer", "Append row"); - - selectMenuPath("Component", "Columns", "Column 0", "Footer Type", - "Widget Footer"); - GridCellElement widgetCell = getGridElement().getFooterCell(0, 0); - WebElement button = widgetCell.findElement(By.className("gwt-Button")); - - assertNotEquals("Clicked", button.getText()); - - button.click(); - - assertEquals("Clicked", button.getText()); - } - - private void assertFooterCount(int count) { - assertEquals("footer count", count, getGridElement().getFooterCount()); - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java deleted file mode 100644 index ccffee854a..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridHeaderTest.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.List; - -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.WebElement; - -import com.vaadin.testbench.TestBenchElement; -import com.vaadin.tests.components.grid.GridElement.GridCellElement; - -public class GridHeaderTest extends GridStaticSectionTest { - - @Test - public void testDefaultHeader() throws Exception { - openTestURL(); - - assertHeaderCount(1); - assertHeaderTexts(0, 0); - } - - @Test - public void testHeaderVisibility() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Header", "Visible"); - - assertHeaderCount(0); - - selectMenuPath("Component", "Header", "Append row"); - - assertHeaderCount(0); - - selectMenuPath("Component", "Header", "Visible"); - - assertHeaderCount(2); - } - - @Test - public void testHeaderCaptions() throws Exception { - openTestURL(); - - assertHeaderTexts(0, 0); - } - - @Test - public void testHeadersWithInvisibleColumns() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Columns", "Column 1", "Visible"); - selectMenuPath("Component", "Columns", "Column 3", "Visible"); - - List cells = getGridHeaderRowCells(); - assertEquals(GridBasicFeatures.COLUMNS - 2, cells.size()); - - assertText("Header (0,0)", cells.get(0)); - assertHTML("Header (0,2)", cells.get(1)); - assertHTML("Header (0,4)", cells.get(2)); - - selectMenuPath("Component", "Columns", "Column 3", "Visible"); - - cells = getGridHeaderRowCells(); - assertEquals(GridBasicFeatures.COLUMNS - 1, cells.size()); - - assertText("Header (0,0)", cells.get(0)); - assertHTML("Header (0,2)", cells.get(1)); - assertText("Header (0,3)", cells.get(2)); - assertHTML("Header (0,4)", cells.get(3)); - } - - @Test - public void testAddRows() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Header", "Append row"); - - assertHeaderCount(2); - assertHeaderTexts(0, 0); - assertHeaderTexts(1, 1); - - selectMenuPath("Component", "Header", "Prepend row"); - - assertHeaderCount(3); - assertHeaderTexts(2, 0); - assertHeaderTexts(0, 1); - assertHeaderTexts(1, 2); - - selectMenuPath("Component", "Header", "Append row"); - - assertHeaderCount(4); - assertHeaderTexts(2, 0); - assertHeaderTexts(0, 1); - assertHeaderTexts(1, 2); - assertHeaderTexts(3, 3); - } - - @Test - public void testRemoveRows() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Header", "Prepend row"); - selectMenuPath("Component", "Header", "Append row"); - - selectMenuPath("Component", "Header", "Remove top row"); - - assertHeaderCount(2); - assertHeaderTexts(0, 0); - assertHeaderTexts(2, 1); - - selectMenuPath("Component", "Header", "Remove bottom row"); - assertHeaderCount(1); - assertHeaderTexts(0, 0); - } - - @Test - public void testDefaultRow() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Columns", "Column 0", "Sortable"); - - GridCellElement headerCell = getGridElement().getHeaderCell(0, 0); - - headerCell.click(); - - assertTrue(hasClassName(headerCell, "sort-asc")); - - headerCell.click(); - - assertFalse(hasClassName(headerCell, "sort-asc")); - assertTrue(hasClassName(headerCell, "sort-desc")); - - selectMenuPath("Component", "Header", "Prepend row"); - selectMenuPath("Component", "Header", "Default row", "Top"); - - assertFalse(hasClassName(headerCell, "sort-desc")); - headerCell = getGridElement().getHeaderCell(0, 0); - assertTrue(hasClassName(headerCell, "sort-desc")); - - selectMenuPath("Component", "Header", "Default row", "Unset"); - - assertFalse(hasClassName(headerCell, "sort-desc")); - } - - @Test - public void joinHeaderColumnsByCells() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Header", "Append row"); - - selectMenuPath("Component", "Header", "Row 2", "Join column cells 0, 1"); - - GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); - assertTrue(spannedCell.isDisplayed()); - assertEquals("2", spannedCell.getAttribute("colspan")); - - GridCellElement hiddenCell = getGridElement().getHeaderCell(1, 1); - assertFalse(hiddenCell.isDisplayed()); - } - - @Test - public void joinHeaderColumnsByColumns() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Header", "Append row"); - - selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2"); - - GridCellElement spannedCell = getGridElement().getHeaderCell(1, 1); - assertTrue(spannedCell.isDisplayed()); - assertEquals("2", spannedCell.getAttribute("colspan")); - - GridCellElement hiddenCell = getGridElement().getHeaderCell(1, 2); - assertFalse(hiddenCell.isDisplayed()); - } - - @Test - public void joinAllColumnsInHeaderRow() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Header", "Append row"); - - selectMenuPath("Component", "Header", "Row 2", "Join all columns"); - - GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); - assertTrue(spannedCell.isDisplayed()); - assertEquals("" + GridBasicFeatures.COLUMNS, - spannedCell.getAttribute("colspan")); - - for (int columnIndex = 1; columnIndex < GridBasicFeatures.COLUMNS; columnIndex++) { - GridCellElement hiddenCell = getGridElement().getHeaderCell(1, - columnIndex); - assertFalse(hiddenCell.isDisplayed()); - } - } - - @Test - public void hideFirstColumnInColspan() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Header", "Append row"); - - selectMenuPath("Component", "Header", "Row 2", "Join all columns"); - - int visibleColumns = GridBasicFeatures.COLUMNS; - - GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); - assertTrue(spannedCell.isDisplayed()); - assertEquals("" + visibleColumns, spannedCell.getAttribute("colspan")); - - selectMenuPath("Component", "Columns", "Column 0", "Visible"); - visibleColumns--; - - spannedCell = getGridElement().getHeaderCell(1, 0); - assertTrue(spannedCell.isDisplayed()); - assertEquals("" + visibleColumns, spannedCell.getAttribute("colspan")); - } - - @Test - public void multipleColspanAndMultipleHiddenColumns() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Header", "Append row"); - - // Join columns [1,2] and [3,4,5] - selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2"); - GridCellElement spannedCell = getGridElement().getHeaderCell(1, 1); - assertEquals("2", spannedCell.getAttribute("colspan")); - - selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5"); - spannedCell = getGridElement().getHeaderCell(1, 3); - assertEquals("3", spannedCell.getAttribute("colspan")); - - selectMenuPath("Component", "Columns", "Column 2", "Visible"); - spannedCell = getGridElement().getHeaderCell(1, 1); - assertEquals("1", spannedCell.getAttribute("colspan")); - - // Ensure the second colspan is preserved (shifts one index to the left) - spannedCell = getGridElement().getHeaderCell(1, 2); - assertEquals("3", spannedCell.getAttribute("colspan")); - - selectMenuPath("Component", "Columns", "Column 4", "Visible"); - - // First reduced colspan is reduced - spannedCell = getGridElement().getHeaderCell(1, 1); - assertEquals("1", spannedCell.getAttribute("colspan")); - - // Second colspan is also now reduced - spannedCell = getGridElement().getHeaderCell(1, 2); - assertEquals("2", spannedCell.getAttribute("colspan")); - - // Show columns again - selectMenuPath("Component", "Columns", "Column 2", "Visible"); - selectMenuPath("Component", "Columns", "Column 4", "Visible"); - - spannedCell = getGridElement().getHeaderCell(1, 1); - assertEquals("2", spannedCell.getAttribute("colspan")); - spannedCell = getGridElement().getHeaderCell(1, 3); - assertEquals("3", spannedCell.getAttribute("colspan")); - - } - - @Test - public void testInitialCellTypes() throws Exception { - openTestURL(); - - GridCellElement textCell = getGridElement().getHeaderCell(0, 0); - assertEquals("Header (0,0)", textCell.getText()); - - GridCellElement widgetCell = getGridElement().getHeaderCell(0, 1); - assertTrue(widgetCell.isElementPresent(By.className("gwt-HTML"))); - - GridCellElement htmlCell = getGridElement().getHeaderCell(0, 2); - assertHTML("Header (0,2)", htmlCell); - } - - @Test - public void testDynamicallyChangingCellType() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Columns", "Column 0", "Header Type", - "Widget Header"); - GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); - assertTrue(widgetCell.isElementPresent(By.className("gwt-Button"))); - - selectMenuPath("Component", "Columns", "Column 1", "Header Type", - "HTML Header"); - GridCellElement htmlCell = getGridElement().getHeaderCell(0, 1); - assertHTML("HTML Header", htmlCell); - - selectMenuPath("Component", "Columns", "Column 2", "Header Type", - "Text Header"); - GridCellElement textCell = getGridElement().getHeaderCell(0, 2); - assertEquals("Text Header", textCell.getText()); - } - - @Test - public void testCellWidgetInteraction() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Columns", "Column 0", "Header Type", - "Widget Header"); - GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); - WebElement button = widgetCell.findElement(By.className("gwt-Button")); - - button.click(); - - assertEquals("Clicked", button.getText()); - } - - @Test - public void widgetInSortableCellInteraction() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Columns", "Column 0", "Header Type", - "Widget Header"); - - selectMenuPath("Component", "Columns", "Column 0", "Sortable"); - - GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); - WebElement button = widgetCell.findElement(By.className("gwt-Button")); - - assertNotEquals("Clicked", button.getText()); - - button.click(); - - assertEquals("Clicked", button.getText()); - } - - private void assertHeaderCount(int count) { - assertEquals("header count", count, getGridElement().getHeaderCount()); - } - - private boolean hasClassName(TestBenchElement element, String name) { - return Arrays.asList(element.getAttribute("class").split(" ")) - .contains(name); - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java deleted file mode 100644 index e20b45bd1d..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridKeyboardNavigationTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Keys; -import org.openqa.selenium.interactions.Actions; - -import com.vaadin.tests.components.grid.GridElement; - -public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { - - @Test - public void testCellActiveOnClick() { - openTestURL(); - - GridElement grid = getGridElement(); - assertTrue("Body cell 0, 0 is not active on init.", grid.getCell(0, 0) - .isActive()); - grid.getCell(5, 2).click(); - assertFalse("Body cell 0, 0 was still active after clicking", grid - .getCell(0, 0).isActive()); - assertTrue("Body cell 5, 2 is not active after clicking", - grid.getCell(5, 2).isActive()); - } - - @Test - public void testCellNotActiveWhenRendererHandlesEvent() { - openTestURL(); - - GridElement grid = getGridElement(); - assertTrue("Body cell 0, 0 is not active on init.", grid.getCell(0, 0) - .isActive()); - grid.getHeaderCell(0, 3).click(); - assertFalse("Body cell 0, 0 is active after click on header.", grid - .getCell(0, 0).isActive()); - assertTrue("Header cell 0, 3 is not active after click on header.", - grid.getHeaderCell(0, 3).isActive()); - } - - @Test - public void testSimpleKeyboardNavigation() { - openTestURL(); - - GridElement grid = getGridElement(); - grid.getCell(0, 0).click(); - - new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); - assertTrue("Body cell 1, 0 is not active after keyboard navigation.", - grid.getCell(1, 0).isActive()); - - new Actions(getDriver()).sendKeys(Keys.ARROW_RIGHT).perform(); - assertTrue("Body cell 1, 1 is not active after keyboard navigation.", - grid.getCell(1, 1).isActive()); - - int i; - for (i = 1; i < 40; ++i) { - new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); - } - - assertFalse("Grid has not scrolled with active cell", - isElementPresent(By.xpath("//td[text() = '(0, 0)']"))); - assertTrue("Active cell is not visible", - isElementPresent(By.xpath("//td[text() = '(" + i + ", 0)']"))); - assertTrue("Body cell " + i + ", 1 is not active", grid.getCell(i, 1) - .isActive()); - } - - @Test - public void testNavigateFromHeaderToBody() { - openTestURL(); - - GridElement grid = getGridElement(); - grid.scrollToRow(300); - new Actions(driver).moveToElement(grid.getHeaderCell(0, 7)).click() - .perform(); - grid.scrollToRow(280); - - assertTrue("Header cell is not active.", grid.getHeaderCell(0, 7) - .isActive()); - new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); - assertTrue("Body cell 280, 7 is not active", grid.getCell(280, 7) - .isActive()); - } - - @Test - public void testNavigationFromFooterToBody() { - openTestURL(); - - selectMenuPath("Component", "Footer", "Visible"); - - GridElement grid = getGridElement(); - grid.scrollToRow(300); - grid.getFooterCell(0, 2).click(); - - assertTrue("Footer cell is not active.", grid.getFooterCell(0, 2) - .isActive()); - new Actions(getDriver()).sendKeys(Keys.ARROW_UP).perform(); - assertTrue("Body cell 300, 2 is not active", grid.getCell(300, 2) - .isActive()); - } - - @Test - public void testNavigateBetweenHeaderAndBodyWithTab() { - openTestURL(); - - GridElement grid = getGridElement(); - grid.getCell(10, 2).click(); - - assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) - .isActive()); - new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) - .keyUp(Keys.SHIFT).perform(); - assertTrue("Header cell 0, 2 is not active", grid.getHeaderCell(0, 2) - .isActive()); - new Actions(getDriver()).sendKeys(Keys.TAB).perform(); - assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) - .isActive()); - - // Navigate out of the Grid and try to navigate with arrow keys. - new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) - .sendKeys(Keys.TAB).keyUp(Keys.SHIFT).sendKeys(Keys.ARROW_DOWN) - .perform(); - assertTrue("Header cell 0, 2 is not active", grid.getHeaderCell(0, 2) - .isActive()); - } - - @Test - public void testNavigateBetweenFooterAndBodyWithTab() { - openTestURL(); - - selectMenuPath("Component", "Footer", "Visible"); - - GridElement grid = getGridElement(); - grid.getCell(10, 2).click(); - - assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) - .isActive()); - new Actions(getDriver()).sendKeys(Keys.TAB).perform(); - assertTrue("Footer cell 0, 2 is not active", grid.getFooterCell(0, 2) - .isActive()); - new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) - .keyUp(Keys.SHIFT).perform(); - assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) - .isActive()); - - // Navigate out of the Grid and try to navigate with arrow keys. - new Actions(getDriver()).sendKeys(Keys.TAB).sendKeys(Keys.TAB) - .sendKeys(Keys.ARROW_UP).perform(); - assertTrue("Footer cell 0, 2 is not active", grid.getFooterCell(0, 2) - .isActive()); - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java deleted file mode 100644 index 873c222f80..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSelectionTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import com.vaadin.testbench.TestBenchElement; -import com.vaadin.tests.components.grid.GridElement; -import com.vaadin.tests.components.grid.GridElement.GridRowElement; - -public class GridSelectionTest extends GridBasicFeaturesTest { - - @Test - public void testSelectOnOff() throws Exception { - openTestURL(); - - setSelectionModelMulti(); - - assertFalse("row shouldn't start out as selected", getRow(0) - .isSelected()); - toggleFirstRowSelection(); - assertTrue("row should become selected", getRow(0).isSelected()); - toggleFirstRowSelection(); - assertFalse("row shouldn't remain selected", getRow(0).isSelected()); - } - - @Test - public void testSelectOnScrollOffScroll() throws Exception { - openTestURL(); - - setSelectionModelMulti(); - - assertFalse("row shouldn't start out as selected", getRow(0) - .isSelected()); - toggleFirstRowSelection(); - assertTrue("row should become selected", getRow(0).isSelected()); - - scrollGridVerticallyTo(10000); // make sure the row is out of cache - scrollGridVerticallyTo(0); // scroll it back into view - - assertTrue("row should still be selected when scrolling " - + "back into view", getRow(0).isSelected()); - } - - @Test - public void testSelectScrollOnScrollOff() throws Exception { - openTestURL(); - - setSelectionModelMulti(); - - assertFalse("row shouldn't start out as selected", getRow(0) - .isSelected()); - - scrollGridVerticallyTo(10000); // make sure the row is out of cache - toggleFirstRowSelection(); - - scrollGridVerticallyTo(0); // scroll it back into view - assertTrue("row should still be selected when scrolling " - + "back into view", getRow(0).isSelected()); - - toggleFirstRowSelection(); - assertFalse("row shouldn't remain selected", getRow(0).isSelected()); - } - - @Test - public void testSelectScrollOnOffScroll() throws Exception { - openTestURL(); - - setSelectionModelMulti(); - - assertFalse("row shouldn't start out as selected", getRow(0) - .isSelected()); - - scrollGridVerticallyTo(10000); // make sure the row is out of cache - toggleFirstRowSelection(); - toggleFirstRowSelection(); - - scrollGridVerticallyTo(0); // make sure the row is out of cache - assertFalse("row shouldn't be selected when scrolling " - + "back into view", getRow(0).isSelected()); - } - - @Test - public void testSingleSelectionUpdatesFromServer() { - openTestURL(); - setSelectionModelSingle(); - - GridElement grid = getGridElement(); - assertFalse("First row was selected from start", grid.getRow(0) - .isSelected()); - toggleFirstRowSelection(); - assertTrue("First row was not selected.", getRow(0).isSelected()); - grid.getCell(5, 0).click(); - assertTrue("Fifth row was not selected.", getRow(5).isSelected()); - assertFalse("First row was still selected.", getRow(0).isSelected()); - grid.getCell(0, 0).click(); - toggleFirstRowSelection(); - assertFalse("First row was still selected.", getRow(0).isSelected()); - assertFalse("Fifth row was still selected.", getRow(5).isSelected()); - - grid.scrollToRow(600); - grid.getCell(595, 0).click(); - assertTrue("Row 595 was not selected.", getRow(595).isSelected()); - toggleFirstRowSelection(); - assertFalse("Row 595 was still selected.", getRow(595).isSelected()); - assertTrue("First row was not selected.", getRow(0).isSelected()); - } - - private void setSelectionModelMulti() { - selectMenuPath("Component", "State", "Selection mode", "multi"); - } - - private void setSelectionModelSingle() { - selectMenuPath("Component", "State", "Selection mode", "single"); - } - - @SuppressWarnings("static-method") - private boolean isSelected(TestBenchElement row) { - /* - * FIXME We probably should get a GridRow instead of a plain - * TestBenchElement, that has an "isSelected" thing integrated. (henrik - * paul 26.6.2014) - */ - return row.getAttribute("class").contains("-row-selected"); - } - - private void toggleFirstRowSelection() { - selectMenuPath("Component", "Body rows", "Select first row"); - } - - private GridRowElement getRow(int i) { - return getGridElement().getRow(i); - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java deleted file mode 100644 index ee3f2a632b..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSortingTest.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; - -import org.junit.Test; -import org.openqa.selenium.Keys; -import org.openqa.selenium.interactions.Actions; - -import com.vaadin.tests.components.grid.GridElement; - -public class GridSortingTest extends GridBasicFeaturesTest { - - @Test - public void testProgrammaticSorting() throws IOException { - openTestURL(); - - GridElement grid = getGridElement(); - - // Sorting by column 9 is sorting by row index that is represented as a - // String. - // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0) - sortBy("Column 9, DESC"); - - assertTrue("Column 9 should have the sort-desc stylename", grid - .getHeaderCell(0, 9).getAttribute("class") - .contains("sort-desc")); - - String row = ""; - for (int i = 0; i < 3; ++i) { - row += "9"; - assertEquals( - "Grid is not sorted by Column 9 using descending direction.", - "(" + row + ", 0)", grid.getCell(i, 0).getText()); - } - - // Column 10 is random numbers from Random with seed 13334 - sortBy("Column 10, ASC"); - - assertFalse( - "Column 9 should no longer have the sort-desc stylename", - grid.getHeaderCell(0, 9).getAttribute("class") - .contains("sort-desc")); - assertTrue("Column 10 should have the sort-asc stylename", grid - .getHeaderCell(0, 10).getAttribute("class") - .contains("sort-asc")); - - // Not cleaning up correctly causes exceptions when scrolling. - grid.scrollToRow(50); - assertFalse("Scrolling caused and exception when shuffled.", - getLogRow(0).contains("Exception")); - - for (int i = 0; i < 5; ++i) { - assertGreater( - "Grid is not sorted by Column 10 using ascending direction", - Integer.parseInt(grid.getCell(i + 1, 10).getText()), - Integer.parseInt(grid.getCell(i, 10).getText())); - - } - - // Column 7 is row index as a number. Last three row are original rows - // 2, 1 and 0. - sortBy("Column 7, DESC"); - for (int i = 0; i < 3; ++i) { - assertEquals( - "Grid is not sorted by Column 7 using descending direction", - "(" + i + ", 0)", - grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); - } - - assertFalse( - "Column 10 should no longer have the sort-asc stylename", - grid.getHeaderCell(0, 10).getAttribute("class") - .contains("sort-asc")); - assertTrue("Column 7 should have the sort-desc stylename", grid - .getHeaderCell(0, 7).getAttribute("class") - .contains("sort-desc")); - - } - - @Test - public void testUserSorting() throws InterruptedException { - openTestURL(); - - GridElement grid = getGridElement(); - - // Sorting by column 9 is sorting by row index that is represented as a - // String. - // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0) - - // Click header twice to sort descending - grid.getHeaderCell(0, 9).click(); - grid.getHeaderCell(0, 9).click(); - String row = ""; - for (int i = 0; i < 3; ++i) { - row += "9"; - assertEquals( - "Grid is not sorted by Column 9 using descending direction.", - "(" + row + ", 0)", grid.getCell(i, 0).getText()); - } - - assertEquals("2. Sort order: [Column 9 ASCENDING]", getLogRow(2)); - assertEquals("4. Sort order: [Column 9 DESCENDING]", getLogRow(0)); - - // Column 10 is random numbers from Random with seed 13334 - // Click header to sort ascending - grid.getHeaderCell(0, 10).click(); - - assertEquals("6. Sort order: [Column 10 ASCENDING]", getLogRow(0)); - - // Not cleaning up correctly causes exceptions when scrolling. - grid.scrollToRow(50); - assertFalse("Scrolling caused and exception when shuffled.", - getLogRow(0).contains("Exception")); - - for (int i = 0; i < 5; ++i) { - assertGreater( - "Grid is not sorted by Column 10 using ascending direction", - Integer.parseInt(grid.getCell(i + 1, 10).getText()), - Integer.parseInt(grid.getCell(i, 10).getText())); - - } - - // Column 7 is row index as a number. Last three row are original rows - // 2, 1 and 0. - // Click header twice to sort descending - grid.getHeaderCell(0, 7).click(); - grid.getHeaderCell(0, 7).click(); - for (int i = 0; i < 3; ++i) { - assertEquals( - "Grid is not sorted by Column 7 using descending direction", - "(" + i + ", 0)", - grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); - } - - assertEquals("9. Sort order: [Column 7 ASCENDING]", getLogRow(3)); - assertEquals("11. Sort order: [Column 7 DESCENDING]", getLogRow(1)); - } - - @Test - public void testUserMultiColumnSorting() { - openTestURL(); - - getGridElement().getHeaderCell(0, 0).click(); - new Actions(driver).keyDown(Keys.SHIFT).perform(); - getGridElement().getHeaderCell(0, 11).click(); - new Actions(driver).keyUp(Keys.SHIFT).perform(); - - String prev = getGridElement().getCell(0, 11).getAttribute("innerHTML"); - for (int i = 1; i <= 6; ++i) { - assertEquals("Column 11 should contain same values.", prev, - getGridElement().getCell(i, 11).getAttribute("innerHTML")); - } - - prev = getGridElement().getCell(0, 0).getText(); - for (int i = 1; i <= 6; ++i) { - assertTrue( - "Grid is not sorted by column 0.", - prev.compareTo(getGridElement().getCell(i, 0).getText()) < 0); - } - - } - - private void sortBy(String column) { - selectMenuPath("Component", "State", "Sort by column", column); - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java deleted file mode 100644 index d19d870548..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionComponentTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.junit.Assert.assertEquals; - -import java.io.IOException; - -import org.junit.Test; - -import com.vaadin.testbench.elements.ButtonElement; - -public class GridStaticSectionComponentTest extends GridBasicFeaturesTest { - - @Test - public void testNativeButtonInHeader() throws IOException { - openTestURL(); - - selectMenuPath("Component", "Columns", "Column 1", "Header Type", - "Widget Header"); - - getGridElement().$(ButtonElement.class).first().click(); - - // Clicking also triggers sorting - assertEquals("2. Button clicked!", getLogRow(2)); - } - - @Test - public void testNativeButtonInFooter() throws IOException { - openTestURL(); - - selectMenuPath("Component", "Footer", "Visible"); - selectMenuPath("Component", "Footer", "Append row"); - selectMenuPath("Component", "Columns", "Column 1", "Footer Type", - "Widget Footer"); - - getGridElement().$(ButtonElement.class).first().click(); - - assertEquals("4. Button clicked!", getLogRow(0)); - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java deleted file mode 100644 index 5fac9cf860..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStaticSectionTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.junit.Assert.assertEquals; - -import com.vaadin.testbench.TestBenchElement; - -/** - * Abstract base class for header and footer tests. - * - * @since - * @author Vaadin Ltd - */ -public abstract class GridStaticSectionTest extends GridBasicClientFeaturesTest { - - protected void assertHeaderTexts(int headerId, int rowIndex) { - int i = 0; - for (TestBenchElement cell : getGridElement().getHeaderCells(rowIndex)) { - - if (i % 3 == 0) { - assertText(String.format("Header (%d,%d)", headerId, i), cell); - } else if (i % 2 == 0) { - assertHTML(String.format("Header (%d,%d)", headerId, i), - cell); - } else { - assertHTML(String.format( - "
Header (%d,%d)
", - headerId, i), cell); - } - - i++; - } - assertEquals("number of header columns", GridBasicFeatures.COLUMNS, i); - } - - protected void assertFooterTexts(int footerId, int rowIndex) { - int i = 0; - for (TestBenchElement cell : getGridElement().getFooterCells(rowIndex)) { - if (i % 3 == 0) { - assertText(String.format("Footer (%d,%d)", footerId, i), cell); - } else if (i % 2 == 0) { - assertHTML(String.format("Footer (%d,%d)", footerId, i), - cell); - } else { - assertHTML(String.format( - "
Footer (%d,%d)
", - footerId, i), cell); - } - i++; - } - assertEquals("number of footer columns", GridBasicFeatures.COLUMNS, i); - } - - protected static void assertText(String text, TestBenchElement e) { - // TBE.getText returns "" if the element is scrolled out of view - assertEquals(text, e.getAttribute("innerHTML")); - } - - protected static void assertHTML(String text, TestBenchElement e) { - String html = e.getAttribute("innerHTML"); - - // IE 8 returns tags as upper case while other browsers do not, make the - // comparison non-casesensive - html = html.toLowerCase(); - text = text.toLowerCase(); - - // IE 8 returns attributes without quotes, make the comparison without - // quotes - html = html.replaceAll("\"", ""); - text = html.replaceAll("\"", ""); - - assertEquals(text, html); - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java deleted file mode 100644 index 9adc4fa8a4..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStructureTest.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.IsNot.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.List; - -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.WebElement; - -import com.vaadin.testbench.TestBenchElement; - -public class GridStructureTest extends GridBasicFeaturesTest { - - @Test - public void testHidingColumn() throws Exception { - openTestURL(); - - // Column 0 should be visible - List cells = getGridHeaderRowCells(); - assertEquals("Column 0", cells.get(0).getText()); - - // Hide column 0 - selectMenuPath("Component", "Columns", "Column 0", "Visible"); - - // Column 1 should now be the first cell - cells = getGridHeaderRowCells(); - assertEquals("Column 1", cells.get(0).getText()); - } - - @Test - public void testRemovingColumn() throws Exception { - openTestURL(); - - // Column 0 should be visible - List cells = getGridHeaderRowCells(); - assertEquals("Column 0", cells.get(0).getText()); - - // Hide column 0 - selectMenuPath("Component", "Columns", "Column 0", "Remove"); - - // Column 1 should now be the first cell - cells = getGridHeaderRowCells(); - assertEquals("Column 1", cells.get(0).getText()); - } - - @Test - public void testDataLoadingAfterRowRemoval() throws Exception { - openTestURL(); - - // Remove columns 2,3,4 - selectMenuPath("Component", "Columns", "Column 2", "Remove"); - selectMenuPath("Component", "Columns", "Column 3", "Remove"); - selectMenuPath("Component", "Columns", "Column 4", "Remove"); - - // Scroll so new data is lazy loaded - scrollGridVerticallyTo(1000); - - // Let lazy loading do its job - sleep(1000); - - // Check that row is loaded - assertThat(getGridElement().getCell(11, 0).getText(), not("...")); - } - - @Test - public void testFreezingColumn() throws Exception { - openTestURL(); - - // Freeze column 2 - selectMenuPath("Component", "Columns", "Column 2", "Freeze"); - - WebElement cell = getGridElement().getCell(0, 0); - assertTrue(cell.getAttribute("class").contains("frozen")); - - cell = getGridElement().getCell(0, 1); - assertTrue(cell.getAttribute("class").contains("frozen")); - } - - @Test - public void testInitialColumnWidths() throws Exception { - openTestURL(); - - WebElement cell = getGridElement().getCell(0, 0); - assertEquals(100, cell.getSize().getWidth()); - - cell = getGridElement().getCell(0, 1); - assertEquals(150, cell.getSize().getWidth()); - - cell = getGridElement().getCell(0, 2); - assertEquals(200, cell.getSize().getWidth()); - } - - @Test - public void testColumnWidths() throws Exception { - openTestURL(); - - // Default column width is 100px - WebElement cell = getGridElement().getCell(0, 0); - assertEquals(100, cell.getSize().getWidth()); - - // Set first column to be 200px wide - selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", - "200px"); - - cell = getGridElement().getCell(0, 0); - assertEquals(200, cell.getSize().getWidth()); - - // Set second column to be 150px wide - selectMenuPath("Component", "Columns", "Column 1", "Column 1 Width", - "150px"); - cell = getGridElement().getCell(0, 1); - assertEquals(150, cell.getSize().getWidth()); - - // Set first column to be auto sized (defaults to 100px currently) - selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", - "Auto"); - - cell = getGridElement().getCell(0, 0); - assertEquals(100, cell.getSize().getWidth()); - } - - @Test - public void testPrimaryStyleNames() throws Exception { - openTestURL(); - - // v-grid is default primary style namea - assertPrimaryStylename("v-grid"); - - selectMenuPath("Component", "State", "Primary style name", - "v-escalator"); - assertPrimaryStylename("v-escalator"); - - selectMenuPath("Component", "State", "Primary style name", "my-grid"); - assertPrimaryStylename("my-grid"); - - selectMenuPath("Component", "State", "Primary style name", "v-grid"); - assertPrimaryStylename("v-grid"); - } - - /** - * Test that the current view is updated when a server-side container change - * occurs (without scrolling back and forth) - */ - @Test - public void testItemSetChangeEvent() throws Exception { - openTestURL(); - - final By newRow = By.xpath("//td[text()='newcell: 0']"); - - assertTrue("Unexpected initial state", !isElementPresent(newRow)); - - selectMenuPath("Component", "Body rows", "Add first row"); - assertTrue("Add row failed", isElementPresent(newRow)); - - selectMenuPath("Component", "Body rows", "Remove first row"); - assertTrue("Remove row failed", !isElementPresent(newRow)); - } - - /** - * Test that the current view is updated when a property's value is reflect - * to the client, when the value is modified server-side. - */ - @Test - public void testPropertyValueChangeEvent() throws Exception { - openTestURL(); - - assertEquals("Unexpected cell initial state", "(0, 0)", - getGridElement().getCell(0, 0).getText()); - - selectMenuPath("Component", "Body rows", - "Modify first row (getItemProperty)"); - assertEquals("(First) modification with getItemProperty failed", - "modified: 0", getGridElement().getCell(0, 0).getText()); - - selectMenuPath("Component", "Body rows", - "Modify first row (getContainerProperty)"); - assertEquals("(Second) modification with getItemProperty failed", - "modified: Column 0", getGridElement().getCell(0, 0).getText()); - } - - @Test - public void testRemovingAllItems() throws Exception { - openTestURL(); - - selectMenuPath("Component", "Body rows", "Remove all rows"); - - assertEquals(0, getGridElement().findElement(By.tagName("tbody")) - .findElements(By.tagName("tr")).size()); - } - - private void assertPrimaryStylename(String stylename) { - assertTrue(getGridElement().getAttribute("class").contains(stylename)); - - String tableWrapperStyleName = getGridElement().getTableWrapper() - .getAttribute("class"); - assertTrue(tableWrapperStyleName.contains(stylename + "-tablewrapper")); - - String hscrollStyleName = getGridElement().getHorizontalScroller() - .getAttribute("class"); - assertTrue(hscrollStyleName.contains(stylename + "-scroller")); - assertTrue(hscrollStyleName - .contains(stylename + "-scroller-horizontal")); - - String vscrollStyleName = getGridElement().getVerticalScroller() - .getAttribute("class"); - assertTrue(vscrollStyleName.contains(stylename + "-scroller")); - assertTrue(vscrollStyleName.contains(stylename + "-scroller-vertical")); - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStylingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStylingTest.java deleted file mode 100644 index e6c37ebf9d..0000000000 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridStylingTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2000-2014 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.basicfeatures; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import com.vaadin.testbench.By; - -public class GridStylingTest extends GridStaticSectionTest { - - @Test - public void testGridPrimaryStyle() throws Exception { - openTestURL(); - - validateStylenames("v-grid"); - } - - @Test - public void testChangingPrimaryStyleName() throws Exception { - openTestURL(); - - selectMenuPath("Component", "State", "Primary Stylename", - "v-custom-style"); - - validateStylenames("v-custom-style"); - } - - private void validateStylenames(String stylename) { - - String classNames = getGridElement().getAttribute("class"); - assertEquals(stylename, classNames); - - classNames = getGridElement().getVerticalScroller().getAttribute( - "class"); - assertTrue(classNames.contains(stylename + "-scroller")); - assertTrue(classNames.contains(stylename + "-scroller-vertical")); - - classNames = getGridElement().getHorizontalScroller().getAttribute( - "class"); - assertTrue(classNames.contains(stylename + "-scroller")); - assertTrue(classNames.contains(stylename + "-scroller-horizontal")); - - classNames = getGridElement().getTableWrapper().getAttribute("class"); - assertEquals(stylename + "-tablewrapper", classNames); - - classNames = getGridElement().getHeader().getAttribute("class"); - assertEquals(stylename + "-header", classNames); - - for (int row = 0; row < getGridElement().getHeaderCount(); row++) { - classNames = getGridElement().getHeaderRow(row).getAttribute( - "class"); - assertEquals(stylename + "-row", classNames); - - for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { - classNames = getGridElement().getHeaderCell(row, col) - .getAttribute("class"); - assertTrue(classNames.contains(stylename + "-cell")); - - if (row == 0 && col == 0) { - assertTrue(classNames, - classNames.contains(stylename + "-header-active")); - } - } - } - - classNames = getGridElement().getBody().getAttribute("class"); - assertEquals(stylename + "-body", classNames); - - int rowsInBody = getGridElement().getBody() - .findElements(By.tagName("tr")).size(); - for (int row = 0; row < rowsInBody; row++) { - classNames = getGridElement().getRow(row).getAttribute("class"); - assertTrue(classNames.contains(stylename + "-row")); - assertTrue(classNames.contains(stylename + "-row-has-data")); - - for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { - classNames = getGridElement().getCell(row, col).getAttribute( - "class"); - assertTrue(classNames.contains(stylename + "-cell")); - - if (row == 0 && col == 0) { - assertTrue(classNames.contains(stylename + "-cell-active")); - } - } - } - - classNames = getGridElement().getFooter().getAttribute("class"); - assertEquals(stylename + "-footer", classNames); - - for (int row = 0; row < getGridElement().getFooterCount(); row++) { - classNames = getGridElement().getFooterRow(row).getAttribute( - "class"); - assertEquals(stylename + "-row", classNames); - - for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { - classNames = getGridElement().getFooterCell(row, col) - .getAttribute("class"); - assertTrue(classNames.contains(stylename + "-cell")); - } - } - } -} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java new file mode 100644 index 0000000000..ece9fdf7d7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2014 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.basicfeatures.client; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; +import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeaturesWidget; + +public class GridClientColumnPropertiesTest extends GridBasicClientFeaturesTest { + + @Test + public void initialColumnWidths() { + openTestURL(); + + for (int col = 0; col < GridBasicClientFeaturesWidget.COLUMNS; col++) { + int width = getGridElement().getCell(0, col).getSize().getWidth(); + if (col <= 6) { + // Growing column widths + assertEquals(50 + col * 25, width); + } else { + assertEquals(100, width); + } + } + } + + @Test + public void testChangingColumnWidth() { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Width", "50px"); + int width = getGridElement().getCell(0, 0).getSize().getWidth(); + assertEquals(50, width); + + selectMenuPath("Component", "Columns", "Column 0", "Width", "200px"); + width = getGridElement().getCell(0, 0).getSize().getWidth(); + assertEquals(200, width); + + selectMenuPath("Component", "Columns", "Column 0", "Width", "auto"); + width = getGridElement().getCell(0, 0).getSize().getWidth(); + assertEquals(100, width); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java new file mode 100644 index 0000000000..4b47837887 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2014 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.basicfeatures.client; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; + +public class GridClientSelectionTest extends GridBasicClientFeaturesTest { + + @Test + public void testChangeSelectionMode() { + openTestURL(); + + selectMenuPath("Component", "State", "Selection mode", "none"); + assertTrue("First column was selection column", getGridElement() + .getCell(0, 0).getText().equals("(0, 0)")); + selectMenuPath("Component", "State", "Selection mode", "multi"); + assertTrue("First column was not selection column", getGridElement() + .getCell(0, 1).getText().equals("(0, 0)")); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java new file mode 100644 index 0000000000..8124e5361f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java @@ -0,0 +1,207 @@ +/* + * Copyright 2000-2014 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.basicfeatures.client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.components.grid.GridElement.GridCellElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; + +public class GridFooterTest extends GridStaticSectionTest { + + @Test + public void testDefaultFooter() { + openTestURL(); + + // Footer should have zero rows by default + assertFooterCount(0); + } + + @Test + public void testFooterVisibility() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Visible"); + + assertFooterCount(0); + + selectMenuPath("Component", "Footer", "Append row"); + + assertFooterCount(0); + + selectMenuPath("Component", "Footer", "Visible"); + + assertFooterCount(1); + } + + @Test + public void testAddRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + assertFooterCount(1); + assertFooterTexts(0, 0); + + selectMenuPath("Component", "Footer", "Prepend row"); + + assertFooterCount(2); + assertFooterTexts(1, 0); + assertFooterTexts(0, 1); + + selectMenuPath("Component", "Footer", "Append row"); + + assertFooterCount(3); + assertFooterTexts(1, 0); + assertFooterTexts(0, 1); + assertFooterTexts(2, 2); + } + + @Test + public void testRemoveRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Prepend row"); + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Remove top row"); + + assertFooterCount(1); + assertFooterTexts(1, 0); + + selectMenuPath("Component", "Footer", "Remove bottom row"); + assertFooterCount(0); + } + + @Test + public void joinColumnsByCells() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Row 1", "Join column cells 0, 1"); + + GridCellElement spannedCell = getGridElement().getFooterCell(0, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getFooterCell(0, 1); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinColumnsByColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Row 1", "Join columns 1, 2"); + + GridCellElement spannedCell = getGridElement().getFooterCell(0, 1); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getFooterCell(0, 2); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinAllColumnsInRow() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Row 1", "Join all columns"); + + GridCellElement spannedCell = getGridElement().getFooterCell(0, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("" + GridBasicFeatures.COLUMNS, + spannedCell.getAttribute("colspan")); + + for (int columnIndex = 1; columnIndex < GridBasicFeatures.COLUMNS; columnIndex++) { + GridCellElement hiddenCell = getGridElement().getFooterCell(0, + columnIndex); + assertFalse(hiddenCell.isDisplayed()); + } + } + + @Test + public void testInitialCellTypes() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + GridCellElement textCell = getGridElement().getFooterCell(0, 0); + assertEquals("Footer (0,0)", textCell.getText()); + + GridCellElement widgetCell = getGridElement().getFooterCell(0, 1); + assertTrue(widgetCell.isElementPresent(By.className("gwt-HTML"))); + + GridCellElement htmlCell = getGridElement().getFooterCell(0, 2); + assertHTML("Footer (0,2)", htmlCell); + } + + @Test + public void testDynamicallyChangingCellType() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Columns", "Column 0", "Footer Type", + "Widget Footer"); + GridCellElement widgetCell = getGridElement().getFooterCell(0, 0); + assertTrue(widgetCell.isElementPresent(By.className("gwt-Button"))); + + selectMenuPath("Component", "Columns", "Column 1", "Footer Type", + "HTML Footer"); + GridCellElement htmlCell = getGridElement().getFooterCell(0, 1); + assertHTML("HTML Footer", htmlCell); + + selectMenuPath("Component", "Columns", "Column 2", "Footer Type", + "Text Footer"); + GridCellElement textCell = getGridElement().getFooterCell(0, 2); + assertEquals("Text Footer", textCell.getText()); + } + + @Test + public void testCellWidgetInteraction() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Columns", "Column 0", "Footer Type", + "Widget Footer"); + GridCellElement widgetCell = getGridElement().getFooterCell(0, 0); + WebElement button = widgetCell.findElement(By.className("gwt-Button")); + + assertNotEquals("Clicked", button.getText()); + + button.click(); + + assertEquals("Clicked", button.getText()); + } + + private void assertFooterCount(int count) { + assertEquals("footer count", count, getGridElement().getFooterCount()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java new file mode 100644 index 0000000000..c528571a2e --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java @@ -0,0 +1,359 @@ +/* + * Copyright 2000-2014 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.basicfeatures.client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.GridElement.GridCellElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; + +public class GridHeaderTest extends GridStaticSectionTest { + + @Test + public void testDefaultHeader() throws Exception { + openTestURL(); + + assertHeaderCount(1); + assertHeaderTexts(0, 0); + } + + @Test + public void testHeaderVisibility() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Visible"); + + assertHeaderCount(0); + + selectMenuPath("Component", "Header", "Append row"); + + assertHeaderCount(0); + + selectMenuPath("Component", "Header", "Visible"); + + assertHeaderCount(2); + } + + @Test + public void testHeaderCaptions() throws Exception { + openTestURL(); + + assertHeaderTexts(0, 0); + } + + @Test + public void testHeadersWithInvisibleColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 1", "Visible"); + selectMenuPath("Component", "Columns", "Column 3", "Visible"); + + List cells = getGridHeaderRowCells(); + assertEquals(GridBasicFeatures.COLUMNS - 2, cells.size()); + + assertText("Header (0,0)", cells.get(0)); + assertHTML("Header (0,2)", cells.get(1)); + assertHTML("Header (0,4)", cells.get(2)); + + selectMenuPath("Component", "Columns", "Column 3", "Visible"); + + cells = getGridHeaderRowCells(); + assertEquals(GridBasicFeatures.COLUMNS - 1, cells.size()); + + assertText("Header (0,0)", cells.get(0)); + assertHTML("Header (0,2)", cells.get(1)); + assertText("Header (0,3)", cells.get(2)); + assertHTML("Header (0,4)", cells.get(3)); + } + + @Test + public void testAddRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + assertHeaderCount(2); + assertHeaderTexts(0, 0); + assertHeaderTexts(1, 1); + + selectMenuPath("Component", "Header", "Prepend row"); + + assertHeaderCount(3); + assertHeaderTexts(2, 0); + assertHeaderTexts(0, 1); + assertHeaderTexts(1, 2); + + selectMenuPath("Component", "Header", "Append row"); + + assertHeaderCount(4); + assertHeaderTexts(2, 0); + assertHeaderTexts(0, 1); + assertHeaderTexts(1, 2); + assertHeaderTexts(3, 3); + } + + @Test + public void testRemoveRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Prepend row"); + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Remove top row"); + + assertHeaderCount(2); + assertHeaderTexts(0, 0); + assertHeaderTexts(2, 1); + + selectMenuPath("Component", "Header", "Remove bottom row"); + assertHeaderCount(1); + assertHeaderTexts(0, 0); + } + + @Test + public void testDefaultRow() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Sortable"); + + GridCellElement headerCell = getGridElement().getHeaderCell(0, 0); + + headerCell.click(); + + assertTrue(hasClassName(headerCell, "sort-asc")); + + headerCell.click(); + + assertFalse(hasClassName(headerCell, "sort-asc")); + assertTrue(hasClassName(headerCell, "sort-desc")); + + selectMenuPath("Component", "Header", "Prepend row"); + selectMenuPath("Component", "Header", "Default row", "Top"); + + assertFalse(hasClassName(headerCell, "sort-desc")); + headerCell = getGridElement().getHeaderCell(0, 0); + assertTrue(hasClassName(headerCell, "sort-desc")); + + selectMenuPath("Component", "Header", "Default row", "Unset"); + + assertFalse(hasClassName(headerCell, "sort-desc")); + } + + @Test + public void joinHeaderColumnsByCells() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join column cells 0, 1"); + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getHeaderCell(1, 1); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinHeaderColumnsByColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2"); + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 1); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getHeaderCell(1, 2); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinAllColumnsInHeaderRow() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join all columns"); + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("" + GridBasicFeatures.COLUMNS, + spannedCell.getAttribute("colspan")); + + for (int columnIndex = 1; columnIndex < GridBasicFeatures.COLUMNS; columnIndex++) { + GridCellElement hiddenCell = getGridElement().getHeaderCell(1, + columnIndex); + assertFalse(hiddenCell.isDisplayed()); + } + } + + @Test + public void hideFirstColumnInColspan() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join all columns"); + + int visibleColumns = GridBasicFeatures.COLUMNS; + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("" + visibleColumns, spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Columns", "Column 0", "Visible"); + visibleColumns--; + + spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("" + visibleColumns, spannedCell.getAttribute("colspan")); + } + + @Test + public void multipleColspanAndMultipleHiddenColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + // Join columns [1,2] and [3,4,5] + selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2"); + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("2", spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5"); + spannedCell = getGridElement().getHeaderCell(1, 3); + assertEquals("3", spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Columns", "Column 2", "Visible"); + spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("1", spannedCell.getAttribute("colspan")); + + // Ensure the second colspan is preserved (shifts one index to the left) + spannedCell = getGridElement().getHeaderCell(1, 2); + assertEquals("3", spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Columns", "Column 4", "Visible"); + + // First reduced colspan is reduced + spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("1", spannedCell.getAttribute("colspan")); + + // Second colspan is also now reduced + spannedCell = getGridElement().getHeaderCell(1, 2); + assertEquals("2", spannedCell.getAttribute("colspan")); + + // Show columns again + selectMenuPath("Component", "Columns", "Column 2", "Visible"); + selectMenuPath("Component", "Columns", "Column 4", "Visible"); + + spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("2", spannedCell.getAttribute("colspan")); + spannedCell = getGridElement().getHeaderCell(1, 3); + assertEquals("3", spannedCell.getAttribute("colspan")); + + } + + @Test + public void testInitialCellTypes() throws Exception { + openTestURL(); + + GridCellElement textCell = getGridElement().getHeaderCell(0, 0); + assertEquals("Header (0,0)", textCell.getText()); + + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 1); + assertTrue(widgetCell.isElementPresent(By.className("gwt-HTML"))); + + GridCellElement htmlCell = getGridElement().getHeaderCell(0, 2); + assertHTML("Header (0,2)", htmlCell); + } + + @Test + public void testDynamicallyChangingCellType() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Header Type", + "Widget Header"); + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); + assertTrue(widgetCell.isElementPresent(By.className("gwt-Button"))); + + selectMenuPath("Component", "Columns", "Column 1", "Header Type", + "HTML Header"); + GridCellElement htmlCell = getGridElement().getHeaderCell(0, 1); + assertHTML("HTML Header", htmlCell); + + selectMenuPath("Component", "Columns", "Column 2", "Header Type", + "Text Header"); + GridCellElement textCell = getGridElement().getHeaderCell(0, 2); + assertEquals("Text Header", textCell.getText()); + } + + @Test + public void testCellWidgetInteraction() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Header Type", + "Widget Header"); + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); + WebElement button = widgetCell.findElement(By.className("gwt-Button")); + + button.click(); + + assertEquals("Clicked", button.getText()); + } + + @Test + public void widgetInSortableCellInteraction() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Header Type", + "Widget Header"); + + selectMenuPath("Component", "Columns", "Column 0", "Sortable"); + + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); + WebElement button = widgetCell.findElement(By.className("gwt-Button")); + + assertNotEquals("Clicked", button.getText()); + + button.click(); + + assertEquals("Clicked", button.getText()); + } + + private void assertHeaderCount(int count) { + assertEquals("header count", count, getGridElement().getHeaderCount()); + } + + private boolean hasClassName(TestBenchElement element, String name) { + return Arrays.asList(element.getAttribute("class").split(" ")) + .contains(name); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java new file mode 100644 index 0000000000..cc801bf870 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2014 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.basicfeatures.client; + +import static org.junit.Assert.assertEquals; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; + +/** + * Abstract base class for header and footer tests. + * + * @since + * @author Vaadin Ltd + */ +public abstract class GridStaticSectionTest extends GridBasicClientFeaturesTest { + + protected void assertHeaderTexts(int headerId, int rowIndex) { + int i = 0; + for (TestBenchElement cell : getGridElement().getHeaderCells(rowIndex)) { + + if (i % 3 == 0) { + assertText(String.format("Header (%d,%d)", headerId, i), cell); + } else if (i % 2 == 0) { + assertHTML(String.format("Header (%d,%d)", headerId, i), + cell); + } else { + assertHTML(String.format( + "
Header (%d,%d)
", + headerId, i), cell); + } + + i++; + } + assertEquals("number of header columns", GridBasicFeatures.COLUMNS, i); + } + + protected void assertFooterTexts(int footerId, int rowIndex) { + int i = 0; + for (TestBenchElement cell : getGridElement().getFooterCells(rowIndex)) { + if (i % 3 == 0) { + assertText(String.format("Footer (%d,%d)", footerId, i), cell); + } else if (i % 2 == 0) { + assertHTML(String.format("Footer (%d,%d)", footerId, i), + cell); + } else { + assertHTML(String.format( + "
Footer (%d,%d)
", + footerId, i), cell); + } + i++; + } + assertEquals("number of footer columns", GridBasicFeatures.COLUMNS, i); + } + + protected static void assertText(String text, TestBenchElement e) { + // TBE.getText returns "" if the element is scrolled out of view + assertEquals(text, e.getAttribute("innerHTML")); + } + + protected static void assertHTML(String text, TestBenchElement e) { + String html = e.getAttribute("innerHTML"); + + // IE 8 returns tags as upper case while other browsers do not, make the + // comparison non-casesensive + html = html.toLowerCase(); + text = text.toLowerCase(); + + // IE 8 returns attributes without quotes, make the comparison without + // quotes + html = html.replaceAll("\"", ""); + text = html.replaceAll("\"", ""); + + assertEquals(text, html); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java new file mode 100644 index 0000000000..67e974bd0a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java @@ -0,0 +1,119 @@ +/* + * Copyright 2000-2014 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.basicfeatures.client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.testbench.By; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; + +public class GridStylingTest extends GridStaticSectionTest { + + @Test + public void testGridPrimaryStyle() throws Exception { + openTestURL(); + + validateStylenames("v-grid"); + } + + @Test + public void testChangingPrimaryStyleName() throws Exception { + openTestURL(); + + selectMenuPath("Component", "State", "Primary Stylename", + "v-custom-style"); + + validateStylenames("v-custom-style"); + } + + private void validateStylenames(String stylename) { + + String classNames = getGridElement().getAttribute("class"); + assertEquals(stylename, classNames); + + classNames = getGridElement().getVerticalScroller().getAttribute( + "class"); + assertTrue(classNames.contains(stylename + "-scroller")); + assertTrue(classNames.contains(stylename + "-scroller-vertical")); + + classNames = getGridElement().getHorizontalScroller().getAttribute( + "class"); + assertTrue(classNames.contains(stylename + "-scroller")); + assertTrue(classNames.contains(stylename + "-scroller-horizontal")); + + classNames = getGridElement().getTableWrapper().getAttribute("class"); + assertEquals(stylename + "-tablewrapper", classNames); + + classNames = getGridElement().getHeader().getAttribute("class"); + assertEquals(stylename + "-header", classNames); + + for (int row = 0; row < getGridElement().getHeaderCount(); row++) { + classNames = getGridElement().getHeaderRow(row).getAttribute( + "class"); + assertEquals(stylename + "-row", classNames); + + for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { + classNames = getGridElement().getHeaderCell(row, col) + .getAttribute("class"); + assertTrue(classNames.contains(stylename + "-cell")); + + if (row == 0 && col == 0) { + assertTrue(classNames, + classNames.contains(stylename + "-header-active")); + } + } + } + + classNames = getGridElement().getBody().getAttribute("class"); + assertEquals(stylename + "-body", classNames); + + int rowsInBody = getGridElement().getBody() + .findElements(By.tagName("tr")).size(); + for (int row = 0; row < rowsInBody; row++) { + classNames = getGridElement().getRow(row).getAttribute("class"); + assertTrue(classNames.contains(stylename + "-row")); + assertTrue(classNames.contains(stylename + "-row-has-data")); + + for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { + classNames = getGridElement().getCell(row, col).getAttribute( + "class"); + assertTrue(classNames.contains(stylename + "-cell")); + + if (row == 0 && col == 0) { + assertTrue(classNames.contains(stylename + "-cell-active")); + } + } + } + + classNames = getGridElement().getFooter().getAttribute("class"); + assertEquals(stylename + "-footer", classNames); + + for (int row = 0; row < getGridElement().getFooterCount(); row++) { + classNames = getGridElement().getFooterRow(row).getAttribute( + "class"); + assertEquals(stylename + "-row", classNames); + + for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { + classNames = getGridElement().getFooterCell(row, col) + .getAttribute("class"); + assertTrue(classNames.contains(stylename + "-cell")); + } + } + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java new file mode 100644 index 0000000000..948c753fec --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java @@ -0,0 +1,172 @@ +/* + * Copyright 2000-2014 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.basicfeatures.server; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { + + @Test + public void testCellActiveOnClick() { + openTestURL(); + + GridElement grid = getGridElement(); + assertTrue("Body cell 0, 0 is not active on init.", grid.getCell(0, 0) + .isActive()); + grid.getCell(5, 2).click(); + assertFalse("Body cell 0, 0 was still active after clicking", grid + .getCell(0, 0).isActive()); + assertTrue("Body cell 5, 2 is not active after clicking", + grid.getCell(5, 2).isActive()); + } + + @Test + public void testCellNotActiveWhenRendererHandlesEvent() { + openTestURL(); + + GridElement grid = getGridElement(); + assertTrue("Body cell 0, 0 is not active on init.", grid.getCell(0, 0) + .isActive()); + grid.getHeaderCell(0, 3).click(); + assertFalse("Body cell 0, 0 is active after click on header.", grid + .getCell(0, 0).isActive()); + assertTrue("Header cell 0, 3 is not active after click on header.", + grid.getHeaderCell(0, 3).isActive()); + } + + @Test + public void testSimpleKeyboardNavigation() { + openTestURL(); + + GridElement grid = getGridElement(); + grid.getCell(0, 0).click(); + + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); + assertTrue("Body cell 1, 0 is not active after keyboard navigation.", + grid.getCell(1, 0).isActive()); + + new Actions(getDriver()).sendKeys(Keys.ARROW_RIGHT).perform(); + assertTrue("Body cell 1, 1 is not active after keyboard navigation.", + grid.getCell(1, 1).isActive()); + + int i; + for (i = 1; i < 40; ++i) { + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); + } + + assertFalse("Grid has not scrolled with active cell", + isElementPresent(By.xpath("//td[text() = '(0, 0)']"))); + assertTrue("Active cell is not visible", + isElementPresent(By.xpath("//td[text() = '(" + i + ", 0)']"))); + assertTrue("Body cell " + i + ", 1 is not active", grid.getCell(i, 1) + .isActive()); + } + + @Test + public void testNavigateFromHeaderToBody() { + openTestURL(); + + GridElement grid = getGridElement(); + grid.scrollToRow(300); + new Actions(driver).moveToElement(grid.getHeaderCell(0, 7)).click() + .perform(); + grid.scrollToRow(280); + + assertTrue("Header cell is not active.", grid.getHeaderCell(0, 7) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); + assertTrue("Body cell 280, 7 is not active", grid.getCell(280, 7) + .isActive()); + } + + @Test + public void testNavigationFromFooterToBody() { + openTestURL(); + + selectMenuPath("Component", "Footer", "Visible"); + + GridElement grid = getGridElement(); + grid.scrollToRow(300); + grid.getFooterCell(0, 2).click(); + + assertTrue("Footer cell is not active.", grid.getFooterCell(0, 2) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.ARROW_UP).perform(); + assertTrue("Body cell 300, 2 is not active", grid.getCell(300, 2) + .isActive()); + } + + @Test + public void testNavigateBetweenHeaderAndBodyWithTab() { + openTestURL(); + + GridElement grid = getGridElement(); + grid.getCell(10, 2).click(); + + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) + .keyUp(Keys.SHIFT).perform(); + assertTrue("Header cell 0, 2 is not active", grid.getHeaderCell(0, 2) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.TAB).perform(); + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + + // Navigate out of the Grid and try to navigate with arrow keys. + new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) + .sendKeys(Keys.TAB).keyUp(Keys.SHIFT).sendKeys(Keys.ARROW_DOWN) + .perform(); + assertTrue("Header cell 0, 2 is not active", grid.getHeaderCell(0, 2) + .isActive()); + } + + @Test + public void testNavigateBetweenFooterAndBodyWithTab() { + openTestURL(); + + selectMenuPath("Component", "Footer", "Visible"); + + GridElement grid = getGridElement(); + grid.getCell(10, 2).click(); + + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.TAB).perform(); + assertTrue("Footer cell 0, 2 is not active", grid.getFooterCell(0, 2) + .isActive()); + new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) + .keyUp(Keys.SHIFT).perform(); + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + + // Navigate out of the Grid and try to navigate with arrow keys. + new Actions(getDriver()).sendKeys(Keys.TAB).sendKeys(Keys.TAB) + .sendKeys(Keys.ARROW_UP).perform(); + assertTrue("Footer cell 0, 2 is not active", grid.getFooterCell(0, 2) + .isActive()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java new file mode 100644 index 0000000000..c190f7d0ec --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java @@ -0,0 +1,151 @@ +/* + * Copyright 2000-2014 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.basicfeatures.server; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.components.grid.GridElement.GridRowElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridSelectionTest extends GridBasicFeaturesTest { + + @Test + public void testSelectOnOff() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); + toggleFirstRowSelection(); + assertTrue("row should become selected", getRow(0).isSelected()); + toggleFirstRowSelection(); + assertFalse("row shouldn't remain selected", getRow(0).isSelected()); + } + + @Test + public void testSelectOnScrollOffScroll() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); + toggleFirstRowSelection(); + assertTrue("row should become selected", getRow(0).isSelected()); + + scrollGridVerticallyTo(10000); // make sure the row is out of cache + scrollGridVerticallyTo(0); // scroll it back into view + + assertTrue("row should still be selected when scrolling " + + "back into view", getRow(0).isSelected()); + } + + @Test + public void testSelectScrollOnScrollOff() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); + + scrollGridVerticallyTo(10000); // make sure the row is out of cache + toggleFirstRowSelection(); + + scrollGridVerticallyTo(0); // scroll it back into view + assertTrue("row should still be selected when scrolling " + + "back into view", getRow(0).isSelected()); + + toggleFirstRowSelection(); + assertFalse("row shouldn't remain selected", getRow(0).isSelected()); + } + + @Test + public void testSelectScrollOnOffScroll() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); + + scrollGridVerticallyTo(10000); // make sure the row is out of cache + toggleFirstRowSelection(); + toggleFirstRowSelection(); + + scrollGridVerticallyTo(0); // make sure the row is out of cache + assertFalse("row shouldn't be selected when scrolling " + + "back into view", getRow(0).isSelected()); + } + + @Test + public void testSingleSelectionUpdatesFromServer() { + openTestURL(); + setSelectionModelSingle(); + + GridElement grid = getGridElement(); + assertFalse("First row was selected from start", grid.getRow(0) + .isSelected()); + toggleFirstRowSelection(); + assertTrue("First row was not selected.", getRow(0).isSelected()); + grid.getCell(5, 0).click(); + assertTrue("Fifth row was not selected.", getRow(5).isSelected()); + assertFalse("First row was still selected.", getRow(0).isSelected()); + grid.getCell(0, 0).click(); + toggleFirstRowSelection(); + assertFalse("First row was still selected.", getRow(0).isSelected()); + assertFalse("Fifth row was still selected.", getRow(5).isSelected()); + + grid.scrollToRow(600); + grid.getCell(595, 0).click(); + assertTrue("Row 595 was not selected.", getRow(595).isSelected()); + toggleFirstRowSelection(); + assertFalse("Row 595 was still selected.", getRow(595).isSelected()); + assertTrue("First row was not selected.", getRow(0).isSelected()); + } + + private void setSelectionModelMulti() { + selectMenuPath("Component", "State", "Selection mode", "multi"); + } + + private void setSelectionModelSingle() { + selectMenuPath("Component", "State", "Selection mode", "single"); + } + + @SuppressWarnings("static-method") + private boolean isSelected(TestBenchElement row) { + /* + * FIXME We probably should get a GridRow instead of a plain + * TestBenchElement, that has an "isSelected" thing integrated. (henrik + * paul 26.6.2014) + */ + return row.getAttribute("class").contains("-row-selected"); + } + + private void toggleFirstRowSelection() { + selectMenuPath("Component", "Body rows", "Select first row"); + } + + private GridRowElement getRow(int i) { + return getGridElement().getRow(i); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java new file mode 100644 index 0000000000..a5a83c156e --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java @@ -0,0 +1,187 @@ +/* + * Copyright 2000-2014 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.basicfeatures.server; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; + +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridSortingTest extends GridBasicFeaturesTest { + + @Test + public void testProgrammaticSorting() throws IOException { + openTestURL(); + + GridElement grid = getGridElement(); + + // Sorting by column 9 is sorting by row index that is represented as a + // String. + // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0) + sortBy("Column 9, DESC"); + + assertTrue("Column 9 should have the sort-desc stylename", grid + .getHeaderCell(0, 9).getAttribute("class") + .contains("sort-desc")); + + String row = ""; + for (int i = 0; i < 3; ++i) { + row += "9"; + assertEquals( + "Grid is not sorted by Column 9 using descending direction.", + "(" + row + ", 0)", grid.getCell(i, 0).getText()); + } + + // Column 10 is random numbers from Random with seed 13334 + sortBy("Column 10, ASC"); + + assertFalse( + "Column 9 should no longer have the sort-desc stylename", + grid.getHeaderCell(0, 9).getAttribute("class") + .contains("sort-desc")); + assertTrue("Column 10 should have the sort-asc stylename", grid + .getHeaderCell(0, 10).getAttribute("class") + .contains("sort-asc")); + + // Not cleaning up correctly causes exceptions when scrolling. + grid.scrollToRow(50); + assertFalse("Scrolling caused and exception when shuffled.", + getLogRow(0).contains("Exception")); + + for (int i = 0; i < 5; ++i) { + assertGreater( + "Grid is not sorted by Column 10 using ascending direction", + Integer.parseInt(grid.getCell(i + 1, 10).getText()), + Integer.parseInt(grid.getCell(i, 10).getText())); + + } + + // Column 7 is row index as a number. Last three row are original rows + // 2, 1 and 0. + sortBy("Column 7, DESC"); + for (int i = 0; i < 3; ++i) { + assertEquals( + "Grid is not sorted by Column 7 using descending direction", + "(" + i + ", 0)", + grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); + } + + assertFalse( + "Column 10 should no longer have the sort-asc stylename", + grid.getHeaderCell(0, 10).getAttribute("class") + .contains("sort-asc")); + assertTrue("Column 7 should have the sort-desc stylename", grid + .getHeaderCell(0, 7).getAttribute("class") + .contains("sort-desc")); + + } + + @Test + public void testUserSorting() throws InterruptedException { + openTestURL(); + + GridElement grid = getGridElement(); + + // Sorting by column 9 is sorting by row index that is represented as a + // String. + // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0) + + // Click header twice to sort descending + grid.getHeaderCell(0, 9).click(); + grid.getHeaderCell(0, 9).click(); + String row = ""; + for (int i = 0; i < 3; ++i) { + row += "9"; + assertEquals( + "Grid is not sorted by Column 9 using descending direction.", + "(" + row + ", 0)", grid.getCell(i, 0).getText()); + } + + assertEquals("2. Sort order: [Column 9 ASCENDING]", getLogRow(2)); + assertEquals("4. Sort order: [Column 9 DESCENDING]", getLogRow(0)); + + // Column 10 is random numbers from Random with seed 13334 + // Click header to sort ascending + grid.getHeaderCell(0, 10).click(); + + assertEquals("6. Sort order: [Column 10 ASCENDING]", getLogRow(0)); + + // Not cleaning up correctly causes exceptions when scrolling. + grid.scrollToRow(50); + assertFalse("Scrolling caused and exception when shuffled.", + getLogRow(0).contains("Exception")); + + for (int i = 0; i < 5; ++i) { + assertGreater( + "Grid is not sorted by Column 10 using ascending direction", + Integer.parseInt(grid.getCell(i + 1, 10).getText()), + Integer.parseInt(grid.getCell(i, 10).getText())); + + } + + // Column 7 is row index as a number. Last three row are original rows + // 2, 1 and 0. + // Click header twice to sort descending + grid.getHeaderCell(0, 7).click(); + grid.getHeaderCell(0, 7).click(); + for (int i = 0; i < 3; ++i) { + assertEquals( + "Grid is not sorted by Column 7 using descending direction", + "(" + i + ", 0)", + grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); + } + + assertEquals("9. Sort order: [Column 7 ASCENDING]", getLogRow(3)); + assertEquals("11. Sort order: [Column 7 DESCENDING]", getLogRow(1)); + } + + @Test + public void testUserMultiColumnSorting() { + openTestURL(); + + getGridElement().getHeaderCell(0, 0).click(); + new Actions(driver).keyDown(Keys.SHIFT).perform(); + getGridElement().getHeaderCell(0, 11).click(); + new Actions(driver).keyUp(Keys.SHIFT).perform(); + + String prev = getGridElement().getCell(0, 11).getAttribute("innerHTML"); + for (int i = 1; i <= 6; ++i) { + assertEquals("Column 11 should contain same values.", prev, + getGridElement().getCell(i, 11).getAttribute("innerHTML")); + } + + prev = getGridElement().getCell(0, 0).getText(); + for (int i = 1; i <= 6; ++i) { + assertTrue( + "Grid is not sorted by column 0.", + prev.compareTo(getGridElement().getCell(i, 0).getText()) < 0); + } + + } + + private void sortBy(String column) { + selectMenuPath("Component", "State", "Sort by column", column); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java new file mode 100644 index 0000000000..19a68a87f4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2014 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.basicfeatures.server; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.junit.Test; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridStaticSectionComponentTest extends GridBasicFeaturesTest { + + @Test + public void testNativeButtonInHeader() throws IOException { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 1", "Header Type", + "Widget Header"); + + getGridElement().$(ButtonElement.class).first().click(); + + // Clicking also triggers sorting + assertEquals("2. Button clicked!", getLogRow(2)); + } + + @Test + public void testNativeButtonInFooter() throws IOException { + openTestURL(); + + selectMenuPath("Component", "Footer", "Visible"); + selectMenuPath("Component", "Footer", "Append row"); + selectMenuPath("Component", "Columns", "Column 1", "Footer Type", + "Widget Footer"); + + getGridElement().$(ButtonElement.class).first().click(); + + assertEquals("4. Button clicked!", getLogRow(0)); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java new file mode 100644 index 0000000000..7c5607d4e6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java @@ -0,0 +1,229 @@ +/* + * Copyright 2000-2014 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.basicfeatures.server; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridStructureTest extends GridBasicFeaturesTest { + + @Test + public void testHidingColumn() throws Exception { + openTestURL(); + + // Column 0 should be visible + List cells = getGridHeaderRowCells(); + assertEquals("Column 0", cells.get(0).getText()); + + // Hide column 0 + selectMenuPath("Component", "Columns", "Column 0", "Visible"); + + // Column 1 should now be the first cell + cells = getGridHeaderRowCells(); + assertEquals("Column 1", cells.get(0).getText()); + } + + @Test + public void testRemovingColumn() throws Exception { + openTestURL(); + + // Column 0 should be visible + List cells = getGridHeaderRowCells(); + assertEquals("Column 0", cells.get(0).getText()); + + // Hide column 0 + selectMenuPath("Component", "Columns", "Column 0", "Remove"); + + // Column 1 should now be the first cell + cells = getGridHeaderRowCells(); + assertEquals("Column 1", cells.get(0).getText()); + } + + @Test + public void testDataLoadingAfterRowRemoval() throws Exception { + openTestURL(); + + // Remove columns 2,3,4 + selectMenuPath("Component", "Columns", "Column 2", "Remove"); + selectMenuPath("Component", "Columns", "Column 3", "Remove"); + selectMenuPath("Component", "Columns", "Column 4", "Remove"); + + // Scroll so new data is lazy loaded + scrollGridVerticallyTo(1000); + + // Let lazy loading do its job + sleep(1000); + + // Check that row is loaded + assertThat(getGridElement().getCell(11, 0).getText(), not("...")); + } + + @Test + public void testFreezingColumn() throws Exception { + openTestURL(); + + // Freeze column 2 + selectMenuPath("Component", "Columns", "Column 2", "Freeze"); + + WebElement cell = getGridElement().getCell(0, 0); + assertTrue(cell.getAttribute("class").contains("frozen")); + + cell = getGridElement().getCell(0, 1); + assertTrue(cell.getAttribute("class").contains("frozen")); + } + + @Test + public void testInitialColumnWidths() throws Exception { + openTestURL(); + + WebElement cell = getGridElement().getCell(0, 0); + assertEquals(100, cell.getSize().getWidth()); + + cell = getGridElement().getCell(0, 1); + assertEquals(150, cell.getSize().getWidth()); + + cell = getGridElement().getCell(0, 2); + assertEquals(200, cell.getSize().getWidth()); + } + + @Test + public void testColumnWidths() throws Exception { + openTestURL(); + + // Default column width is 100px + WebElement cell = getGridElement().getCell(0, 0); + assertEquals(100, cell.getSize().getWidth()); + + // Set first column to be 200px wide + selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", + "200px"); + + cell = getGridElement().getCell(0, 0); + assertEquals(200, cell.getSize().getWidth()); + + // Set second column to be 150px wide + selectMenuPath("Component", "Columns", "Column 1", "Column 1 Width", + "150px"); + cell = getGridElement().getCell(0, 1); + assertEquals(150, cell.getSize().getWidth()); + + // Set first column to be auto sized (defaults to 100px currently) + selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", + "Auto"); + + cell = getGridElement().getCell(0, 0); + assertEquals(100, cell.getSize().getWidth()); + } + + @Test + public void testPrimaryStyleNames() throws Exception { + openTestURL(); + + // v-grid is default primary style namea + assertPrimaryStylename("v-grid"); + + selectMenuPath("Component", "State", "Primary style name", + "v-escalator"); + assertPrimaryStylename("v-escalator"); + + selectMenuPath("Component", "State", "Primary style name", "my-grid"); + assertPrimaryStylename("my-grid"); + + selectMenuPath("Component", "State", "Primary style name", "v-grid"); + assertPrimaryStylename("v-grid"); + } + + /** + * Test that the current view is updated when a server-side container change + * occurs (without scrolling back and forth) + */ + @Test + public void testItemSetChangeEvent() throws Exception { + openTestURL(); + + final By newRow = By.xpath("//td[text()='newcell: 0']"); + + assertTrue("Unexpected initial state", !isElementPresent(newRow)); + + selectMenuPath("Component", "Body rows", "Add first row"); + assertTrue("Add row failed", isElementPresent(newRow)); + + selectMenuPath("Component", "Body rows", "Remove first row"); + assertTrue("Remove row failed", !isElementPresent(newRow)); + } + + /** + * Test that the current view is updated when a property's value is reflect + * to the client, when the value is modified server-side. + */ + @Test + public void testPropertyValueChangeEvent() throws Exception { + openTestURL(); + + assertEquals("Unexpected cell initial state", "(0, 0)", + getGridElement().getCell(0, 0).getText()); + + selectMenuPath("Component", "Body rows", + "Modify first row (getItemProperty)"); + assertEquals("(First) modification with getItemProperty failed", + "modified: 0", getGridElement().getCell(0, 0).getText()); + + selectMenuPath("Component", "Body rows", + "Modify first row (getContainerProperty)"); + assertEquals("(Second) modification with getItemProperty failed", + "modified: Column 0", getGridElement().getCell(0, 0).getText()); + } + + @Test + public void testRemovingAllItems() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Body rows", "Remove all rows"); + + assertEquals(0, getGridElement().findElement(By.tagName("tbody")) + .findElements(By.tagName("tr")).size()); + } + + private void assertPrimaryStylename(String stylename) { + assertTrue(getGridElement().getAttribute("class").contains(stylename)); + + String tableWrapperStyleName = getGridElement().getTableWrapper() + .getAttribute("class"); + assertTrue(tableWrapperStyleName.contains(stylename + "-tablewrapper")); + + String hscrollStyleName = getGridElement().getHorizontalScroller() + .getAttribute("class"); + assertTrue(hscrollStyleName.contains(stylename + "-scroller")); + assertTrue(hscrollStyleName + .contains(stylename + "-scroller-horizontal")); + + String vscrollStyleName = getGridElement().getVerticalScroller() + .getAttribute("class"); + assertTrue(vscrollStyleName.contains(stylename + "-scroller")); + assertTrue(vscrollStyleName.contains(stylename + "-scroller-vertical")); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java deleted file mode 100644 index 6eac275a9a..0000000000 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeatures.java +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright 2000-2014 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.widgetset.client.grid; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Random; - -import com.google.gwt.core.client.Scheduler.ScheduledCommand; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.HTML; -import com.vaadin.client.ui.grid.FlyweightCell; -import com.vaadin.client.ui.grid.Grid; -import com.vaadin.client.ui.grid.Grid.SelectionMode; -import com.vaadin.client.ui.grid.GridColumn; -import com.vaadin.client.ui.grid.GridFooter; -import com.vaadin.client.ui.grid.GridFooter.FooterRow; -import com.vaadin.client.ui.grid.GridHeader; -import com.vaadin.client.ui.grid.GridHeader.HeaderRow; -import com.vaadin.client.ui.grid.Renderer; -import com.vaadin.client.ui.grid.datasources.ListDataSource; -import com.vaadin.client.ui.grid.datasources.ListSorter; -import com.vaadin.client.ui.grid.renderers.DateRenderer; -import com.vaadin.client.ui.grid.renderers.HtmlRenderer; -import com.vaadin.client.ui.grid.renderers.NumberRenderer; -import com.vaadin.client.ui.grid.renderers.TextRenderer; -import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeatures.Data; - -/** - * Grid basic client features test application. - * - * @since - * @author Vaadin Ltd - */ -public class GridBasicClientFeatures extends - PureGWTTestApplication>> { - - public static enum Renderers { - TEXT_RENDERER, HTML_RENDERER, NUMBER_RENDERER, DATE_RENDERER; - } - - private static final int MANUALLY_FORMATTED_COLUMNS = 5; - public static final int COLUMNS = 12; - public static final int ROWS = 1000; - - private final Grid> grid; - private final List> data; - private final ListDataSource> ds; - private final ListSorter> sorter; - - /** - * Our basic data object - */ - public final static class Data { - Object value; - } - - /** - * Convenience method for creating a list of Data objects to be used as a - * Row in the data source - * - * @param cols - * number of columns (items) to include in the row - * @return - */ - private List createDataRow(int cols) { - List list = new ArrayList(cols); - for (int i = 0; i < cols; ++i) { - list.add(new Data()); - } - data.add(list); - return list; - } - - @SuppressWarnings("unchecked") - public GridBasicClientFeatures() { - super(new Grid>()); - - // Initialize data source - data = new ArrayList>(); - { - Random rand = new Random(); - rand.setSeed(13334); - long timestamp = 0; - for (int row = 0; row < ROWS; row++) { - - List datarow = createDataRow(COLUMNS); - Data d; - - int col = 0; - for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) { - d = datarow.get(col); - d.value = "(" + row + ", " + col + ")"; - } - - d = datarow.get(col++); - d.value = Integer.valueOf(row); - - d = datarow.get(col++); - d.value = new Date(timestamp); - timestamp += 91250000; // a bit over a day, just to get - // variation - - d = datarow.get(col++); - d.value = "" + row + ""; - - d = datarow.get(col++); - d.value = Integer.valueOf(rand.nextInt()); - - d = datarow.get(col++); - d.value = Integer.valueOf(rand.nextInt(5)); - } - } - - ds = new ListDataSource>(data); - grid = getTestedWidget(); - grid.getElement().setId("testComponent"); - grid.setDataSource(ds); - grid.setSelectionMode(SelectionMode.NONE); - - sorter = new ListSorter>(grid); - - // Create a bunch of grid columns - - // Data source layout: - // text (String) * (COLUMNS - MANUALLY_FORMATTED_COLUMNS + 1) | - // rownumber (Integer) | some date (Date) | row number as HTML (String) - // | random value (Integer) - - int col = 0; - - // Text times COLUMNS - MANUALLY_FORMATTED_COLUMNS - for (col = 0; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) { - - final int c = col; - - GridColumn> column = new GridColumn>( - createRenderer(Renderers.TEXT_RENDERER)) { - @Override - public String getValue(List row) { - return (String) row.get(c).value; - } - }; - - column.setWidth(50 + c * 25); - - grid.addColumn(column); - - } - - // Integer row number - { - final int c = col++; - grid.addColumn(new GridColumn>( - createRenderer(Renderers.NUMBER_RENDERER)) { - @Override - public Integer getValue(List row) { - return (Integer) row.get(c).value; - } - }); - } - - // Some date - { - final int c = col++; - grid.addColumn(new GridColumn>( - createRenderer(Renderers.DATE_RENDERER)) { - @Override - public Date getValue(List row) { - return (Date) row.get(c).value; - } - }); - } - - // Row number as a HTML string - { - final int c = col++; - grid.addColumn(new GridColumn>( - createRenderer(Renderers.HTML_RENDERER)) { - @Override - public String getValue(List row) { - return (String) row.get(c).value; - } - }); - } - - // Random integer value - { - final int c = col++; - grid.addColumn(new GridColumn>( - createRenderer(Renderers.NUMBER_RENDERER)) { - @Override - public Integer getValue(List row) { - return (Integer) row.get(c).value; - } - }); - } - - // Random integer value between 0 and 5 - { - final int c = col++; - grid.addColumn(new GridColumn>( - createRenderer(Renderers.NUMBER_RENDERER)) { - @Override - public Integer getValue(List row) { - return (Integer) row.get(c).value; - } - }); - } - - setHeaderTexts(grid.getHeader().getRow(0)); - - // - // Populate the menu - // - - createStateMenu(); - createColumnsMenu(); - createHeaderMenu(); - createFooterMenu(); - - grid.getElement().getStyle().setZIndex(0); - add(grid); - } - - private void createStateMenu() { - String[] selectionModePath = { "Component", "State", "Selection mode" }; - String[] primaryStyleNamePath = { "Component", "State", - "Primary Stylename" }; - - addMenuCommand("multi", new ScheduledCommand() { - @Override - public void execute() { - grid.setSelectionMode(SelectionMode.MULTI); - } - }, selectionModePath); - - addMenuCommand("single", new ScheduledCommand() { - @Override - public void execute() { - grid.setSelectionMode(SelectionMode.SINGLE); - } - }, selectionModePath); - - addMenuCommand("none", new ScheduledCommand() { - @Override - public void execute() { - grid.setSelectionMode(SelectionMode.NONE); - } - }, selectionModePath); - - addMenuCommand("v-grid", new ScheduledCommand() { - @Override - public void execute() { - grid.setStylePrimaryName("v-grid"); - - } - }, primaryStyleNamePath); - - addMenuCommand("v-escalator", new ScheduledCommand() { - @Override - public void execute() { - grid.setStylePrimaryName("v-escalator"); - - } - }, primaryStyleNamePath); - - addMenuCommand("v-custom-style", new ScheduledCommand() { - @Override - public void execute() { - grid.setStylePrimaryName("v-custom-style"); - - } - }, primaryStyleNamePath); - - } - - private void createColumnsMenu() { - - for (int i = 0; i < COLUMNS; i++) { - final int index = i; - addMenuCommand("Visible", new ScheduledCommand() { - @Override - public void execute() { - grid.getColumn(index).setVisible( - !grid.getColumn(index).isVisible()); - } - }, "Component", "Columns", "Column " + i); - addMenuCommand("Sortable", new ScheduledCommand() { - @Override - public void execute() { - grid.getColumn(index).setSortable( - !grid.getColumn(index).isSortable()); - } - }, "Component", "Columns", "Column " + i); - - addMenuCommand("auto", new ScheduledCommand() { - @Override - public void execute() { - grid.getColumn(index).setWidth(-1); - } - }, "Component", "Columns", "Column " + i, "Width"); - addMenuCommand("50px", new ScheduledCommand() { - @Override - public void execute() { - grid.getColumn(index).setWidth(50); - } - }, "Component", "Columns", "Column " + i, "Width"); - addMenuCommand("200px", new ScheduledCommand() { - @Override - public void execute() { - grid.getColumn(index).setWidth(200); - } - }, "Component", "Columns", "Column " + i, "Width"); - - // Header types - addMenuCommand("Text Header", new ScheduledCommand() { - @Override - public void execute() { - grid.getHeader().getRow(0).getCell(index) - .setText("Text Header"); - } - }, "Component", "Columns", "Column " + i, "Header Type"); - addMenuCommand("HTML Header", new ScheduledCommand() { - @Override - public void execute() { - grid.getHeader().getRow(0).getCell(index) - .setHtml("HTML Header"); - } - }, "Component", "Columns", "Column " + i, "Header Type"); - addMenuCommand("Widget Header", new ScheduledCommand() { - @Override - public void execute() { - final Button button = new Button("Button Header"); - button.addClickHandler(new ClickHandler() { - - @Override - public void onClick(ClickEvent event) { - button.setText("Clicked"); - } - }); - grid.getHeader().getRow(0).getCell(index).setWidget(button); - } - }, "Component", "Columns", "Column " + i, "Header Type"); - - // Footer types - addMenuCommand("Text Footer", new ScheduledCommand() { - @Override - public void execute() { - grid.getFooter().getRow(0).getCell(index) - .setText("Text Footer"); - } - }, "Component", "Columns", "Column " + i, "Footer Type"); - addMenuCommand("HTML Footer", new ScheduledCommand() { - @Override - public void execute() { - grid.getFooter().getRow(0).getCell(index) - .setHtml("HTML Footer"); - } - }, "Component", "Columns", "Column " + i, "Footer Type"); - addMenuCommand("Widget Footer", new ScheduledCommand() { - @Override - public void execute() { - final Button button = new Button("Button Footer"); - button.addClickHandler(new ClickHandler() { - - @Override - public void onClick(ClickEvent event) { - button.setText("Clicked"); - } - }); - grid.getFooter().getRow(0).getCell(index).setWidget(button); - } - }, "Component", "Columns", "Column " + i, "Footer Type"); - } - } - - private int headerCounter = 0; - private int footerCounter = 0; - - private void setHeaderTexts(HeaderRow row) { - for (int i = 0; i < COLUMNS; ++i) { - String caption = "Header (" + headerCounter + "," + i + ")"; - - // Lets use some different cell types - if (i % 3 == 0) { - row.getCell(i).setText(caption); - } else if (i % 2 == 0) { - row.getCell(i).setHtml("" + caption + ""); - } else { - row.getCell(i).setWidget(new HTML(caption)); - } - } - headerCounter++; - } - - private void setFooterTexts(FooterRow row) { - for (int i = 0; i < COLUMNS; ++i) { - String caption = "Footer (" + footerCounter + "," + i + ")"; - - // Lets use some different cell types - if (i % 3 == 0) { - row.getCell(i).setText(caption); - } else if (i % 2 == 0) { - row.getCell(i).setHtml("" + caption + ""); - } else { - row.getCell(i).setWidget(new HTML(caption)); - } - } - footerCounter++; - } - - private void createHeaderMenu() { - final GridHeader header = grid.getHeader(); - final String[] menuPath = { "Component", "Header" }; - - addMenuCommand("Visible", new ScheduledCommand() { - @Override - public void execute() { - header.setVisible(!header.isVisible()); - } - }, menuPath); - - addMenuCommand("Top", new ScheduledCommand() { - @Override - public void execute() { - header.setDefaultRow(header.getRow(0)); - } - }, "Component", "Header", "Default row"); - addMenuCommand("Bottom", new ScheduledCommand() { - @Override - public void execute() { - header.setDefaultRow(header.getRow(header.getRowCount() - 1)); - } - }, "Component", "Header", "Default row"); - addMenuCommand("Unset", new ScheduledCommand() { - @Override - public void execute() { - header.setDefaultRow(null); - } - }, "Component", "Header", "Default row"); - - addMenuCommand("Prepend row", new ScheduledCommand() { - @Override - public void execute() { - configureHeaderRow(header.prependRow()); - } - }, menuPath); - addMenuCommand("Append row", new ScheduledCommand() { - @Override - public void execute() { - configureHeaderRow(header.appendRow()); - } - }, menuPath); - addMenuCommand("Remove top row", new ScheduledCommand() { - @Override - public void execute() { - header.removeRow(0); - } - }, menuPath); - addMenuCommand("Remove bottom row", new ScheduledCommand() { - @Override - public void execute() { - header.removeRow(header.getRowCount() - 1); - } - }, menuPath); - - } - - private void configureHeaderRow(final HeaderRow row) { - final GridHeader header = grid.getHeader(); - setHeaderTexts(row); - String rowTitle = "Row " + header.getRowCount(); - final String[] menuPath = { "Component", "Header", rowTitle }; - - addMenuCommand("Join column cells 0, 1", new ScheduledCommand() { - - @Override - public void execute() { - row.join(row.getCell(0), row.getCell(1)); - - } - }, menuPath); - - addMenuCommand("Join columns 1, 2", new ScheduledCommand() { - - @Override - public void execute() { - row.join(grid.getColumn(1), grid.getColumn(2)); - - } - }, menuPath); - - addMenuCommand("Join columns 3, 4, 5", new ScheduledCommand() { - - @Override - public void execute() { - row.join(grid.getColumn(3), grid.getColumn(4), - grid.getColumn(5)); - - } - }, menuPath); - - addMenuCommand("Join all columns", new ScheduledCommand() { - - @Override - public void execute() { - row.join(grid.getColumns().toArray( - new GridColumn[grid.getColumnCount()])); - - } - }, menuPath); - } - - private void createFooterMenu() { - final GridFooter footer = grid.getFooter(); - final String[] menuPath = { "Component", "Footer" }; - - addMenuCommand("Visible", new ScheduledCommand() { - @Override - public void execute() { - footer.setVisible(!footer.isVisible()); - } - }, menuPath); - - addMenuCommand("Prepend row", new ScheduledCommand() { - @Override - public void execute() { - configureFooterRow(footer.prependRow()); - } - }, menuPath); - addMenuCommand("Append row", new ScheduledCommand() { - @Override - public void execute() { - configureFooterRow(footer.appendRow()); - } - }, menuPath); - addMenuCommand("Remove top row", new ScheduledCommand() { - @Override - public void execute() { - footer.removeRow(0); - } - }, menuPath); - addMenuCommand("Remove bottom row", new ScheduledCommand() { - @Override - public void execute() { - assert footer.getRowCount() > 0; - footer.removeRow(footer.getRowCount() - 1); - } - }, menuPath); - } - - private void configureFooterRow(final FooterRow row) { - final GridFooter footer = grid.getFooter(); - setFooterTexts(row); - String rowTitle = "Row " + footer.getRowCount(); - final String[] menuPath = { "Component", "Footer", rowTitle }; - - addMenuCommand("Join column cells 0, 1", new ScheduledCommand() { - - @Override - public void execute() { - row.join(row.getCell(0), row.getCell(1)); - - } - }, menuPath); - - addMenuCommand("Join columns 1, 2", new ScheduledCommand() { - - @Override - public void execute() { - row.join(grid.getColumn(1), grid.getColumn(2)); - - } - }, menuPath); - - addMenuCommand("Join all columns", new ScheduledCommand() { - - @Override - public void execute() { - row.join(grid.getColumns().toArray( - new GridColumn[grid.getColumnCount()])); - - } - }, menuPath); - } - - /** - * Creates a a renderer for a {@link Renderers} - */ - @SuppressWarnings("rawtypes") - private final Renderer createRenderer(Renderers renderer) { - switch (renderer) { - case TEXT_RENDERER: - return new TextRenderer(); - - case HTML_RENDERER: - return new HtmlRenderer() { - - @Override - public void render(FlyweightCell cell, String htmlString) { - super.render(cell, "" + htmlString + ""); - } - }; - - case NUMBER_RENDERER: - return new NumberRenderer(); - - case DATE_RENDERER: - return new DateRenderer(); - - default: - return new TextRenderer(); - } - } -} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java index 4b640e84e5..b0841b69fb 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java @@ -17,20 +17,21 @@ package com.vaadin.tests.widgetset.client.grid; import com.vaadin.client.ui.AbstractComponentConnector; import com.vaadin.shared.ui.Connect; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeatures.GridTestComponent; /** * Connector for the GridClientBasicFeatures ApplicationWidget - * + * * @since * @author Vaadin Ltd */ -@Connect(com.vaadin.tests.widgetset.server.grid.GridBasicClientFeatures.GridTestComponent.class) +@Connect(GridTestComponent.class) public class GridBasicClientFeaturesConnector extends AbstractComponentConnector { @Override - public GridBasicClientFeatures getWidget() { - return (GridBasicClientFeatures) super.getWidget(); + public GridBasicClientFeaturesWidget getWidget() { + return (GridBasicClientFeaturesWidget) super.getWidget(); } } diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java new file mode 100644 index 0000000000..8a5a75da38 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java @@ -0,0 +1,632 @@ +/* + * Copyright 2000-2014 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.widgetset.client.grid; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Random; + +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.HTML; +import com.vaadin.client.ui.grid.FlyweightCell; +import com.vaadin.client.ui.grid.Grid; +import com.vaadin.client.ui.grid.Grid.SelectionMode; +import com.vaadin.client.ui.grid.GridColumn; +import com.vaadin.client.ui.grid.GridFooter; +import com.vaadin.client.ui.grid.GridFooter.FooterRow; +import com.vaadin.client.ui.grid.GridHeader; +import com.vaadin.client.ui.grid.GridHeader.HeaderRow; +import com.vaadin.client.ui.grid.Renderer; +import com.vaadin.client.ui.grid.datasources.ListDataSource; +import com.vaadin.client.ui.grid.datasources.ListSorter; +import com.vaadin.client.ui.grid.renderers.DateRenderer; +import com.vaadin.client.ui.grid.renderers.HtmlRenderer; +import com.vaadin.client.ui.grid.renderers.NumberRenderer; +import com.vaadin.client.ui.grid.renderers.TextRenderer; +import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeaturesWidget.Data; + +/** + * Grid basic client features test application. + * + * @since + * @author Vaadin Ltd + */ +public class GridBasicClientFeaturesWidget extends + PureGWTTestApplication>> { + + public static enum Renderers { + TEXT_RENDERER, HTML_RENDERER, NUMBER_RENDERER, DATE_RENDERER; + } + + private static final int MANUALLY_FORMATTED_COLUMNS = 5; + public static final int COLUMNS = 12; + public static final int ROWS = 1000; + + private final Grid> grid; + private final List> data; + private final ListDataSource> ds; + private final ListSorter> sorter; + + /** + * Our basic data object + */ + public final static class Data { + Object value; + } + + /** + * Convenience method for creating a list of Data objects to be used as a + * Row in the data source + * + * @param cols + * number of columns (items) to include in the row + * @return + */ + private List createDataRow(int cols) { + List list = new ArrayList(cols); + for (int i = 0; i < cols; ++i) { + list.add(new Data()); + } + data.add(list); + return list; + } + + @SuppressWarnings("unchecked") + public GridBasicClientFeaturesWidget() { + super(new Grid>()); + + // Initialize data source + data = new ArrayList>(); + { + Random rand = new Random(); + rand.setSeed(13334); + long timestamp = 0; + for (int row = 0; row < ROWS; row++) { + + List datarow = createDataRow(COLUMNS); + Data d; + + int col = 0; + for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) { + d = datarow.get(col); + d.value = "(" + row + ", " + col + ")"; + } + + d = datarow.get(col++); + d.value = Integer.valueOf(row); + + d = datarow.get(col++); + d.value = new Date(timestamp); + timestamp += 91250000; // a bit over a day, just to get + // variation + + d = datarow.get(col++); + d.value = "" + row + ""; + + d = datarow.get(col++); + d.value = Integer.valueOf(rand.nextInt()); + + d = datarow.get(col++); + d.value = Integer.valueOf(rand.nextInt(5)); + } + } + + ds = new ListDataSource>(data); + grid = getTestedWidget(); + grid.getElement().setId("testComponent"); + grid.setDataSource(ds); + grid.setSelectionMode(SelectionMode.NONE); + + sorter = new ListSorter>(grid); + + // Create a bunch of grid columns + + // Data source layout: + // text (String) * (COLUMNS - MANUALLY_FORMATTED_COLUMNS + 1) | + // rownumber (Integer) | some date (Date) | row number as HTML (String) + // | random value (Integer) + + int col = 0; + + // Text times COLUMNS - MANUALLY_FORMATTED_COLUMNS + for (col = 0; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) { + + final int c = col; + + GridColumn> column = new GridColumn>( + createRenderer(Renderers.TEXT_RENDERER)) { + @Override + public String getValue(List row) { + return (String) row.get(c).value; + } + }; + + column.setWidth(50 + c * 25); + + grid.addColumn(column); + + } + + // Integer row number + { + final int c = col++; + grid.addColumn(new GridColumn>( + createRenderer(Renderers.NUMBER_RENDERER)) { + @Override + public Integer getValue(List row) { + return (Integer) row.get(c).value; + } + }); + } + + // Some date + { + final int c = col++; + grid.addColumn(new GridColumn>( + createRenderer(Renderers.DATE_RENDERER)) { + @Override + public Date getValue(List row) { + return (Date) row.get(c).value; + } + }); + } + + // Row number as a HTML string + { + final int c = col++; + grid.addColumn(new GridColumn>( + createRenderer(Renderers.HTML_RENDERER)) { + @Override + public String getValue(List row) { + return (String) row.get(c).value; + } + }); + } + + // Random integer value + { + final int c = col++; + grid.addColumn(new GridColumn>( + createRenderer(Renderers.NUMBER_RENDERER)) { + @Override + public Integer getValue(List row) { + return (Integer) row.get(c).value; + } + }); + } + + // Random integer value between 0 and 5 + { + final int c = col++; + grid.addColumn(new GridColumn>( + createRenderer(Renderers.NUMBER_RENDERER)) { + @Override + public Integer getValue(List row) { + return (Integer) row.get(c).value; + } + }); + } + + setHeaderTexts(grid.getHeader().getRow(0)); + + // + // Populate the menu + // + + createStateMenu(); + createColumnsMenu(); + createHeaderMenu(); + createFooterMenu(); + + grid.getElement().getStyle().setZIndex(0); + add(grid); + } + + private void createStateMenu() { + String[] selectionModePath = { "Component", "State", "Selection mode" }; + String[] primaryStyleNamePath = { "Component", "State", + "Primary Stylename" }; + + addMenuCommand("multi", new ScheduledCommand() { + @Override + public void execute() { + grid.setSelectionMode(SelectionMode.MULTI); + } + }, selectionModePath); + + addMenuCommand("single", new ScheduledCommand() { + @Override + public void execute() { + grid.setSelectionMode(SelectionMode.SINGLE); + } + }, selectionModePath); + + addMenuCommand("none", new ScheduledCommand() { + @Override + public void execute() { + grid.setSelectionMode(SelectionMode.NONE); + } + }, selectionModePath); + + addMenuCommand("v-grid", new ScheduledCommand() { + @Override + public void execute() { + grid.setStylePrimaryName("v-grid"); + + } + }, primaryStyleNamePath); + + addMenuCommand("v-escalator", new ScheduledCommand() { + @Override + public void execute() { + grid.setStylePrimaryName("v-escalator"); + + } + }, primaryStyleNamePath); + + addMenuCommand("v-custom-style", new ScheduledCommand() { + @Override + public void execute() { + grid.setStylePrimaryName("v-custom-style"); + + } + }, primaryStyleNamePath); + + } + + private void createColumnsMenu() { + + for (int i = 0; i < COLUMNS; i++) { + final int index = i; + addMenuCommand("Visible", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setVisible( + !grid.getColumn(index).isVisible()); + } + }, "Component", "Columns", "Column " + i); + addMenuCommand("Sortable", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setSortable( + !grid.getColumn(index).isSortable()); + } + }, "Component", "Columns", "Column " + i); + + addMenuCommand("auto", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setWidth(-1); + } + }, "Component", "Columns", "Column " + i, "Width"); + addMenuCommand("50px", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setWidth(50); + } + }, "Component", "Columns", "Column " + i, "Width"); + addMenuCommand("200px", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setWidth(200); + } + }, "Component", "Columns", "Column " + i, "Width"); + + // Header types + addMenuCommand("Text Header", new ScheduledCommand() { + @Override + public void execute() { + grid.getHeader().getRow(0).getCell(index) + .setText("Text Header"); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + addMenuCommand("HTML Header", new ScheduledCommand() { + @Override + public void execute() { + grid.getHeader().getRow(0).getCell(index) + .setHtml("HTML Header"); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + addMenuCommand("Widget Header", new ScheduledCommand() { + @Override + public void execute() { + final Button button = new Button("Button Header"); + button.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + button.setText("Clicked"); + } + }); + grid.getHeader().getRow(0).getCell(index).setWidget(button); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + + // Footer types + addMenuCommand("Text Footer", new ScheduledCommand() { + @Override + public void execute() { + grid.getFooter().getRow(0).getCell(index) + .setText("Text Footer"); + } + }, "Component", "Columns", "Column " + i, "Footer Type"); + addMenuCommand("HTML Footer", new ScheduledCommand() { + @Override + public void execute() { + grid.getFooter().getRow(0).getCell(index) + .setHtml("HTML Footer"); + } + }, "Component", "Columns", "Column " + i, "Footer Type"); + addMenuCommand("Widget Footer", new ScheduledCommand() { + @Override + public void execute() { + final Button button = new Button("Button Footer"); + button.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + button.setText("Clicked"); + } + }); + grid.getFooter().getRow(0).getCell(index).setWidget(button); + } + }, "Component", "Columns", "Column " + i, "Footer Type"); + } + } + + private int headerCounter = 0; + private int footerCounter = 0; + + private void setHeaderTexts(HeaderRow row) { + for (int i = 0; i < COLUMNS; ++i) { + String caption = "Header (" + headerCounter + "," + i + ")"; + + // Lets use some different cell types + if (i % 3 == 0) { + row.getCell(i).setText(caption); + } else if (i % 2 == 0) { + row.getCell(i).setHtml("" + caption + ""); + } else { + row.getCell(i).setWidget(new HTML(caption)); + } + } + headerCounter++; + } + + private void setFooterTexts(FooterRow row) { + for (int i = 0; i < COLUMNS; ++i) { + String caption = "Footer (" + footerCounter + "," + i + ")"; + + // Lets use some different cell types + if (i % 3 == 0) { + row.getCell(i).setText(caption); + } else if (i % 2 == 0) { + row.getCell(i).setHtml("" + caption + ""); + } else { + row.getCell(i).setWidget(new HTML(caption)); + } + } + footerCounter++; + } + + private void createHeaderMenu() { + final GridHeader header = grid.getHeader(); + final String[] menuPath = { "Component", "Header" }; + + addMenuCommand("Visible", new ScheduledCommand() { + @Override + public void execute() { + header.setVisible(!header.isVisible()); + } + }, menuPath); + + addMenuCommand("Top", new ScheduledCommand() { + @Override + public void execute() { + header.setDefaultRow(header.getRow(0)); + } + }, "Component", "Header", "Default row"); + addMenuCommand("Bottom", new ScheduledCommand() { + @Override + public void execute() { + header.setDefaultRow(header.getRow(header.getRowCount() - 1)); + } + }, "Component", "Header", "Default row"); + addMenuCommand("Unset", new ScheduledCommand() { + @Override + public void execute() { + header.setDefaultRow(null); + } + }, "Component", "Header", "Default row"); + + addMenuCommand("Prepend row", new ScheduledCommand() { + @Override + public void execute() { + configureHeaderRow(header.prependRow()); + } + }, menuPath); + addMenuCommand("Append row", new ScheduledCommand() { + @Override + public void execute() { + configureHeaderRow(header.appendRow()); + } + }, menuPath); + addMenuCommand("Remove top row", new ScheduledCommand() { + @Override + public void execute() { + header.removeRow(0); + } + }, menuPath); + addMenuCommand("Remove bottom row", new ScheduledCommand() { + @Override + public void execute() { + header.removeRow(header.getRowCount() - 1); + } + }, menuPath); + + } + + private void configureHeaderRow(final HeaderRow row) { + final GridHeader header = grid.getHeader(); + setHeaderTexts(row); + String rowTitle = "Row " + header.getRowCount(); + final String[] menuPath = { "Component", "Header", rowTitle }; + + addMenuCommand("Join column cells 0, 1", new ScheduledCommand() { + + @Override + public void execute() { + row.join(row.getCell(0), row.getCell(1)); + + } + }, menuPath); + + addMenuCommand("Join columns 1, 2", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumn(1), grid.getColumn(2)); + + } + }, menuPath); + + addMenuCommand("Join columns 3, 4, 5", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumn(3), grid.getColumn(4), + grid.getColumn(5)); + + } + }, menuPath); + + addMenuCommand("Join all columns", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumns().toArray( + new GridColumn[grid.getColumnCount()])); + + } + }, menuPath); + } + + private void createFooterMenu() { + final GridFooter footer = grid.getFooter(); + final String[] menuPath = { "Component", "Footer" }; + + addMenuCommand("Visible", new ScheduledCommand() { + @Override + public void execute() { + footer.setVisible(!footer.isVisible()); + } + }, menuPath); + + addMenuCommand("Prepend row", new ScheduledCommand() { + @Override + public void execute() { + configureFooterRow(footer.prependRow()); + } + }, menuPath); + addMenuCommand("Append row", new ScheduledCommand() { + @Override + public void execute() { + configureFooterRow(footer.appendRow()); + } + }, menuPath); + addMenuCommand("Remove top row", new ScheduledCommand() { + @Override + public void execute() { + footer.removeRow(0); + } + }, menuPath); + addMenuCommand("Remove bottom row", new ScheduledCommand() { + @Override + public void execute() { + assert footer.getRowCount() > 0; + footer.removeRow(footer.getRowCount() - 1); + } + }, menuPath); + } + + private void configureFooterRow(final FooterRow row) { + final GridFooter footer = grid.getFooter(); + setFooterTexts(row); + String rowTitle = "Row " + footer.getRowCount(); + final String[] menuPath = { "Component", "Footer", rowTitle }; + + addMenuCommand("Join column cells 0, 1", new ScheduledCommand() { + + @Override + public void execute() { + row.join(row.getCell(0), row.getCell(1)); + + } + }, menuPath); + + addMenuCommand("Join columns 1, 2", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumn(1), grid.getColumn(2)); + + } + }, menuPath); + + addMenuCommand("Join all columns", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumns().toArray( + new GridColumn[grid.getColumnCount()])); + + } + }, menuPath); + } + + /** + * Creates a a renderer for a {@link Renderers} + */ + @SuppressWarnings("rawtypes") + private final Renderer createRenderer(Renderers renderer) { + switch (renderer) { + case TEXT_RENDERER: + return new TextRenderer(); + + case HTML_RENDERER: + return new HtmlRenderer() { + + @Override + public void render(FlyweightCell cell, String htmlString) { + super.render(cell, "" + htmlString + ""); + } + }; + + case NUMBER_RENDERER: + return new NumberRenderer(); + + case DATE_RENDERER: + return new DateRenderer(); + + default: + return new TextRenderer(); + } + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/grid/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/widgetset/server/grid/GridBasicClientFeatures.java deleted file mode 100644 index fb217dc232..0000000000 --- a/uitest/src/com/vaadin/tests/widgetset/server/grid/GridBasicClientFeatures.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2000-2014 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.widgetset.server.grid; - -import com.vaadin.annotations.Widgetset; -import com.vaadin.server.VaadinRequest; -import com.vaadin.tests.widgetset.TestingWidgetSet; -import com.vaadin.ui.AbstractComponent; -import com.vaadin.ui.UI; - -/** - * Initializer shell for GridClientBasicFeatures test application - * - * @since - * @author Vaadin Ltd - */ -@Widgetset(TestingWidgetSet.NAME) -public class GridBasicClientFeatures extends UI { - - public class GridTestComponent extends AbstractComponent { - } - - @Override - protected void init(VaadinRequest request) { - setContent(new GridTestComponent()); - } - -} -- cgit v1.2.3 From c532e42ec703079eb024ca8e1f03442d493a40e7 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Wed, 13 Aug 2014 16:39:40 +0300 Subject: Implement KeyEvents for Grid (#13334) Change-Id: Ida7a358aa23a4c96232a01bed0b4810fb91dd832 --- .../com/vaadin/client/ui/grid/FlyweightCell.java | 3 +- client/src/com/vaadin/client/ui/grid/Grid.java | 154 ++++++++++++++++++++- client/src/com/vaadin/client/ui/grid/Row.java | 4 +- .../keyevents/AbstractGridKeyEventHandler.java | 43 ++++++ .../ui/grid/keyevents/BodyKeyDownHandler.java | 28 ++++ .../ui/grid/keyevents/BodyKeyPressHandler.java | 28 ++++ .../client/ui/grid/keyevents/BodyKeyUpHandler.java | 28 ++++ .../ui/grid/keyevents/FooterKeyDownHandler.java | 28 ++++ .../ui/grid/keyevents/FooterKeyPressHandler.java | 28 ++++ .../ui/grid/keyevents/FooterKeyUpHandler.java | 28 ++++ .../client/ui/grid/keyevents/GridKeyDownEvent.java | 51 +++++++ .../ui/grid/keyevents/GridKeyPressEvent.java | 51 +++++++ .../client/ui/grid/keyevents/GridKeyUpEvent.java | 51 +++++++ .../ui/grid/keyevents/HeaderKeyDownHandler.java | 28 ++++ .../ui/grid/keyevents/HeaderKeyPressHandler.java | 28 ++++ .../ui/grid/keyevents/HeaderKeyUpHandler.java | 28 ++++ .../client/GridClientKeyEventsTest.java | 108 +++++++++++++++ .../client/grid/GridBasicClientFeaturesWidget.java | 127 ++++++++++++++++- 18 files changed, 834 insertions(+), 10 deletions(-) create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/AbstractGridKeyEventHandler.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyDownHandler.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyPressHandler.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyUpHandler.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyDownHandler.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyPressHandler.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyUpHandler.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/GridKeyDownEvent.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/GridKeyPressEvent.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/GridKeyUpEvent.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyDownHandler.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyPressHandler.java create mode 100644 client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyUpHandler.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/FlyweightCell.java b/client/src/com/vaadin/client/ui/grid/FlyweightCell.java index dcc543de9c..30cc4fc79e 100644 --- a/client/src/com/vaadin/client/ui/grid/FlyweightCell.java +++ b/client/src/com/vaadin/client/ui/grid/FlyweightCell.java @@ -17,7 +17,6 @@ package com.vaadin.client.ui.grid; import java.util.List; -import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.TableCellElement; @@ -70,7 +69,7 @@ public class FlyweightCell { * Returns the element of the cell. Can be either a TD element * or a TH element. */ - public Element getElement() { + public TableCellElement getElement() { assertSetup(); return element; } diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 531e27098c..a2bb0d3f09 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -33,7 +33,9 @@ import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.EventTarget; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.TableCellElement; +import com.google.gwt.dom.client.TableRowElement; import com.google.gwt.dom.client.Touch; +import com.google.gwt.event.dom.client.KeyCodeEvent; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.touch.client.Point; @@ -50,6 +52,22 @@ import com.vaadin.client.ui.SubPartAware; import com.vaadin.client.ui.grid.GridFooter.FooterRow; import com.vaadin.client.ui.grid.GridHeader.HeaderRow; import com.vaadin.client.ui.grid.GridStaticSection.StaticCell; +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler; +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyPressHandler; +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyUpHandler; +import com.vaadin.client.ui.grid.keyevents.BodyKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.BodyKeyPressHandler; +import com.vaadin.client.ui.grid.keyevents.BodyKeyUpHandler; +import com.vaadin.client.ui.grid.keyevents.FooterKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.FooterKeyPressHandler; +import com.vaadin.client.ui.grid.keyevents.FooterKeyUpHandler; +import com.vaadin.client.ui.grid.keyevents.GridKeyDownEvent; +import com.vaadin.client.ui.grid.keyevents.GridKeyPressEvent; +import com.vaadin.client.ui.grid.keyevents.GridKeyUpEvent; +import com.vaadin.client.ui.grid.keyevents.HeaderKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.HeaderKeyPressHandler; +import com.vaadin.client.ui.grid.keyevents.HeaderKeyUpHandler; import com.vaadin.client.ui.grid.renderers.ComplexRenderer; import com.vaadin.client.ui.grid.renderers.WidgetRenderer; import com.vaadin.client.ui.grid.selection.HasSelectionChangeHandlers; @@ -105,6 +123,68 @@ import com.vaadin.shared.ui.grid.SortDirection; public class Grid extends Composite implements HasSelectionChangeHandlers, SubPartAware { + public static abstract class AbstractGridKeyEvent + extends KeyCodeEvent { + + /** + * Enum describing different section of Grid. + */ + public enum GridSection { + HEADER, BODY, FOOTER + } + + private Grid grid; + protected Cell activeCell; + protected GridSection activeSection; + private final Type associatedType = new Type( + getBrowserEventType(), this); + + public AbstractGridKeyEvent(Grid grid) { + this.grid = grid; + } + + protected abstract String getBrowserEventType(); + + /** + * Gets the Grid instance for this event. + * + * @return grid + */ + public Grid getGrid() { + return grid; + } + + /** + * Gets the active cell for this event. + * + * @return active cell + */ + public Cell getActiveCell() { + return activeCell; + } + + @Override + protected void dispatch(HANDLER handler) { + activeCell = grid.activeCellHandler.getActiveCell(); + activeSection = GridSection.FOOTER; + final RowContainer container = grid.activeCellHandler.container; + if (container == grid.escalator.getHeader()) { + activeSection = GridSection.HEADER; + } else if (container == grid.escalator.getBody()) { + activeSection = GridSection.BODY; + } + } + + @Override + public Type getAssociatedType() { + return associatedType; + } + } + + private GridKeyDownEvent keyDown = new GridKeyDownEvent(this); + private GridKeyUpEvent keyUp = new GridKeyUpEvent(this); + private GridKeyPressEvent keyPress = new GridKeyPressEvent(this); + private class ActiveCellHandler { private RowContainer container = escalator.getBody(); @@ -113,13 +193,17 @@ public class Grid extends Composite implements private int lastActiveBodyRow = 0; private int lastActiveHeaderRow = 0; private int lastActiveFooterRow = 0; - private Element cellWithActiveStyle = null; - private Element rowWithActiveStyle = null; + private TableCellElement cellWithActiveStyle = null; + private TableRowElement rowWithActiveStyle = null; public ActiveCellHandler() { sinkEvents(getNavigationEvents()); } + private Cell getActiveCell() { + return new Cell(activeRow, activeColumn, cellWithActiveStyle); + } + /** * Sets style names for given cell when needed. */ @@ -594,7 +678,7 @@ public class Grid extends Composite implements */ private SelectionModel selectionModel; - private final ActiveCellHandler activeCellHandler; + protected final ActiveCellHandler activeCellHandler; private final LazySorter lazySorter = new LazySorter(); @@ -1199,8 +1283,10 @@ public class Grid extends Composite implements } }); - // Sink header events + // Sink header events and key events sinkEvents(getHeader().getConsumedEvents()); + sinkEvents(Arrays.asList(BrowserEvents.KEYDOWN, BrowserEvents.KEYUP, + BrowserEvents.KEYPRESS)); } @Override @@ -2356,6 +2442,66 @@ public class Grid extends Composite implements return addHandler(handler, DataAvailableEvent.TYPE); } + /** + * Register a KeyDown handler to this Grid. If the handler is a + * HeaderKeyDownHandler, it will be fired only when a header cell is active. + * The same goes for body and footer with their respective handlers. + * + * @param handler + * the key handler to register + * @return the registration for the event + */ + public > HandlerRegistration addKeyDownHandler( + HANDLER handler) { + if (handler instanceof BodyKeyDownHandler + || handler instanceof HeaderKeyDownHandler + || handler instanceof FooterKeyDownHandler) { + return addHandler(handler, keyDown.getAssociatedType()); + } + throw new IllegalArgumentException( + "Handler not a valid extension of GridKeyDownHandler"); + } + + /** + * Register a KeyUp handler to this Grid. If the handler is a + * HeaderKeyUpHandler, it will be fired only when a header cell is active. + * The same goes for body and footer with their respective handlers. + * + * @param handler + * the key handler to register + * @return the registration for the event + */ + public > HandlerRegistration addKeyUpHandler( + HANDLER handler) { + if (handler instanceof BodyKeyUpHandler + || handler instanceof HeaderKeyUpHandler + || handler instanceof FooterKeyUpHandler) { + return addHandler(handler, keyUp.getAssociatedType()); + } + throw new IllegalArgumentException( + "Handler not a valid extension of GridKeyUpHandler"); + } + + /** + * Register a KeyPress handler to this Grid. If the handler is a + * HeaderKeyPressHandler, it will be fired only when a header cell is + * active. The same goes for body and footer with their respective handlers. + * + * @param handler + * the key handler to register + * @return the registration for the event + */ + public > HandlerRegistration addKeyPressHandler( + HANDLER handler) { + if (handler instanceof BodyKeyPressHandler + || handler instanceof HeaderKeyPressHandler + || handler instanceof FooterKeyPressHandler) { + return addHandler(handler, keyPress.getAssociatedType()); + } + throw new IllegalArgumentException( + "Handler not a valid extension of GridKeyPressHandler"); + } + /** * Apply sorting to data source. */ diff --git a/client/src/com/vaadin/client/ui/grid/Row.java b/client/src/com/vaadin/client/ui/grid/Row.java index a5317e52c4..6419a98574 100644 --- a/client/src/com/vaadin/client/ui/grid/Row.java +++ b/client/src/com/vaadin/client/ui/grid/Row.java @@ -16,7 +16,7 @@ package com.vaadin.client.ui.grid; -import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.TableRowElement; /** * A representation of a row in an {@link Escalator}. @@ -44,5 +44,5 @@ public interface Row { * * @return the root element of the row */ - public Element getElement(); + public TableRowElement getElement(); } \ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/AbstractGridKeyEventHandler.java b/client/src/com/vaadin/client/ui/grid/keyevents/AbstractGridKeyEventHandler.java new file mode 100644 index 0000000000..28a85924fa --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/AbstractGridKeyEventHandler.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.google.gwt.event.shared.EventHandler; + +/** + * Base interface of all handlers for {@link AbstractGridKeyEvent}s. + * + * @since + * @author Vaadin Ltd + */ +public abstract interface AbstractGridKeyEventHandler extends EventHandler { + + public abstract interface GridKeyDownHandler extends + AbstractGridKeyEventHandler { + public void onKeyDown(GridKeyDownEvent event); + } + + public abstract interface GridKeyUpHandler extends + AbstractGridKeyEventHandler { + public void onKeyUp(GridKeyUpEvent event); + } + + public abstract interface GridKeyPressHandler extends + AbstractGridKeyEventHandler { + public void onKeyPress(GridKeyPressEvent event); + } + +} diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyDownHandler.java b/client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyDownHandler.java new file mode 100644 index 0000000000..a3b76ea5d7 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyDownHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyDownHandler; + +/** + * Handler for {@link GridKeyDownEvent}s that happen when active cell is in the + * body of the Grid. + * + * @since + * @author Vaadin Ltd + */ +public interface BodyKeyDownHandler extends GridKeyDownHandler { +} diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyPressHandler.java b/client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyPressHandler.java new file mode 100644 index 0000000000..5548994cf9 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyPressHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyPressHandler; + +/** + * Handler for {@link GridKeyPressEvent}s that happen when active cell is in the + * body of the Grid. + * + * @since + * @author Vaadin Ltd + */ +public interface BodyKeyPressHandler extends GridKeyPressHandler { +} \ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyUpHandler.java b/client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyUpHandler.java new file mode 100644 index 0000000000..33b4fc81fe --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/BodyKeyUpHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyUpHandler; + +/** + * Handler for {@link GridKeyUpEvent}s that happen when active cell is in the + * body of the Grid. + * + * @since + * @author Vaadin Ltd + */ +public interface BodyKeyUpHandler extends GridKeyUpHandler { +} \ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyDownHandler.java b/client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyDownHandler.java new file mode 100644 index 0000000000..e90f52e736 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyDownHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyDownHandler; + +/** + * Handler for {@link GridKeyDownEvent}s that happen when active cell is in the + * footer of the Grid. + * + * @since + * @author Vaadin Ltd + */ +public interface FooterKeyDownHandler extends GridKeyDownHandler { +} diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyPressHandler.java b/client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyPressHandler.java new file mode 100644 index 0000000000..58f48f36f5 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyPressHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyPressHandler; + +/** + * Handler for {@link GridKeyPressEvent}s that happen when active cell is in the + * footer of the Grid. + * + * @since + * @author Vaadin Ltd + */ +public interface FooterKeyPressHandler extends GridKeyPressHandler { +} \ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyUpHandler.java b/client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyUpHandler.java new file mode 100644 index 0000000000..d6bcddf710 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/FooterKeyUpHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyUpHandler; + +/** + * Handler for {@link GridKeyUpEvent}s that happen when active cell is in the + * footer of the Grid. + * + * @since + * @author Vaadin Ltd + */ +public interface FooterKeyUpHandler extends GridKeyUpHandler { +} \ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/GridKeyDownEvent.java b/client/src/com/vaadin/client/ui/grid/keyevents/GridKeyDownEvent.java new file mode 100644 index 0000000000..8af65dbf49 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/GridKeyDownEvent.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.google.gwt.dom.client.BrowserEvents; +import com.vaadin.client.ui.grid.Grid; +import com.vaadin.client.ui.grid.Grid.AbstractGridKeyEvent; +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyDownHandler; + +/** + * Represents native key down event in Grid. + * + * @since + * @author Vaadin Ltd + */ +public class GridKeyDownEvent extends + AbstractGridKeyEvent> { + + public GridKeyDownEvent(Grid grid) { + super(grid); + } + + @Override + protected void dispatch(GridKeyDownHandler handler) { + super.dispatch(handler); + if ((activeSection == GridSection.BODY && handler instanceof BodyKeyDownHandler) + || (activeSection == GridSection.HEADER && handler instanceof HeaderKeyDownHandler) + || (activeSection == GridSection.FOOTER && handler instanceof FooterKeyDownHandler)) { + handler.onKeyDown(this); + } + } + + @Override + protected String getBrowserEventType() { + return BrowserEvents.KEYDOWN; + } + +} diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/GridKeyPressEvent.java b/client/src/com/vaadin/client/ui/grid/keyevents/GridKeyPressEvent.java new file mode 100644 index 0000000000..6f06bc6674 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/GridKeyPressEvent.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.google.gwt.dom.client.BrowserEvents; +import com.vaadin.client.ui.grid.Grid; +import com.vaadin.client.ui.grid.Grid.AbstractGridKeyEvent; +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyPressHandler; + +/** + * Represents native key press event in Grid. + * + * @since + * @author Vaadin Ltd + */ +public class GridKeyPressEvent extends + AbstractGridKeyEvent> { + + public GridKeyPressEvent(Grid grid) { + super(grid); + } + + @Override + protected void dispatch(GridKeyPressHandler handler) { + super.dispatch(handler); + if ((activeSection == GridSection.BODY && handler instanceof BodyKeyPressHandler) + || (activeSection == GridSection.HEADER && handler instanceof HeaderKeyPressHandler) + || (activeSection == GridSection.FOOTER && handler instanceof FooterKeyPressHandler)) { + handler.onKeyPress(this); + } + } + + @Override + protected String getBrowserEventType() { + return BrowserEvents.KEYPRESS; + } + +} \ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/GridKeyUpEvent.java b/client/src/com/vaadin/client/ui/grid/keyevents/GridKeyUpEvent.java new file mode 100644 index 0000000000..d289dbae98 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/GridKeyUpEvent.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.google.gwt.dom.client.BrowserEvents; +import com.vaadin.client.ui.grid.Grid; +import com.vaadin.client.ui.grid.Grid.AbstractGridKeyEvent; +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyUpHandler; + +/** + * Represents native key up event in Grid. + * + * @since + * @author Vaadin Ltd + */ +public class GridKeyUpEvent extends + AbstractGridKeyEvent> { + + public GridKeyUpEvent(Grid grid) { + super(grid); + } + + @Override + protected void dispatch(GridKeyUpHandler handler) { + super.dispatch(handler); + if ((activeSection == GridSection.BODY && handler instanceof BodyKeyUpHandler) + || (activeSection == GridSection.HEADER && handler instanceof HeaderKeyUpHandler) + || (activeSection == GridSection.FOOTER && handler instanceof FooterKeyUpHandler)) { + handler.onKeyUp(this); + } + } + + @Override + protected String getBrowserEventType() { + return BrowserEvents.KEYUP; + } + +} diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyDownHandler.java b/client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyDownHandler.java new file mode 100644 index 0000000000..28c9a8e056 --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyDownHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyDownHandler; + +/** + * Handler for {@link GridKeyDownEvent}s that happen when active cell is in the + * header of the Grid. + * + * @since + * @author Vaadin Ltd + */ +public interface HeaderKeyDownHandler extends GridKeyDownHandler { +} diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyPressHandler.java b/client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyPressHandler.java new file mode 100644 index 0000000000..607c30493d --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyPressHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyPressHandler; + +/** + * Handler for {@link GridKeyPressEvent}s that happen when active cell is in the + * header of the Grid. + * + * @since + * @author Vaadin Ltd + */ +public interface HeaderKeyPressHandler extends GridKeyPressHandler { +} \ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyUpHandler.java b/client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyUpHandler.java new file mode 100644 index 0000000000..bfa3dde79b --- /dev/null +++ b/client/src/com/vaadin/client/ui/grid/keyevents/HeaderKeyUpHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 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.client.ui.grid.keyevents; + +import com.vaadin.client.ui.grid.keyevents.AbstractGridKeyEventHandler.GridKeyUpHandler; + +/** + * Handler for {@link GridKeyUpEvent}s that happen when active cell is in the + * header of the Grid. + * + * @since + * @author Vaadin Ltd + */ +public interface HeaderKeyUpHandler extends GridKeyUpHandler { +} \ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java new file mode 100644 index 0000000000..fe81380296 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java @@ -0,0 +1,108 @@ +/* + * Copyright 2000-2014 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.basicfeatures.client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.testbench.By; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; + +public class GridClientKeyEventsTest extends GridBasicClientFeaturesTest { + + private List eventOrder = Arrays.asList("keydown", "keyup", + "keypress"); + + @Test + public void testBodyKeyEvents() throws IOException { + openTestURL(); + + getGridElement().getCell(2, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + for (int i = 0; i < 3; ++i) { + assertEquals("Body key event handler was not called.", "(2, 2) " + + eventOrder.get(i) + " 13", + findElements(By.className("v-label")).get(i * 3).getText()); + + assertTrue("Header key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3 + 1) + .getText().isEmpty()); + assertTrue("Footer key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3 + 2) + .getText().isEmpty()); + } + + } + + @Test + public void testHeaderKeyEvents() throws IOException { + openTestURL(); + + getGridElement().getHeaderCell(0, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + for (int i = 0; i < 3; ++i) { + assertEquals("Header key event handler was not called.", "(0, 2) " + + eventOrder.get(i) + " 13", + findElements(By.className("v-label")).get(i * 3 + 1) + .getText()); + + assertTrue("Body key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3).getText() + .isEmpty()); + assertTrue("Footer key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3 + 2) + .getText().isEmpty()); + } + } + + @Test + public void testFooterKeyEvents() throws IOException { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + getGridElement().getFooterCell(0, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + for (int i = 0; i < 3; ++i) { + assertEquals("Footer key event handler was not called.", "(0, 2) " + + eventOrder.get(i) + " 13", + findElements(By.className("v-label")).get(i * 3 + 2) + .getText()); + + assertTrue("Body key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3).getText() + .isEmpty()); + assertTrue("Header key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3 + 1) + .getText().isEmpty()); + + } + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java index 8a5a75da38..a7210236d4 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java @@ -25,8 +25,11 @@ import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.HTML; +import com.vaadin.client.ui.VLabel; +import com.vaadin.client.ui.grid.Cell; import com.vaadin.client.ui.grid.FlyweightCell; import com.vaadin.client.ui.grid.Grid; +import com.vaadin.client.ui.grid.Grid.AbstractGridKeyEvent; import com.vaadin.client.ui.grid.Grid.SelectionMode; import com.vaadin.client.ui.grid.GridColumn; import com.vaadin.client.ui.grid.GridFooter; @@ -36,6 +39,18 @@ import com.vaadin.client.ui.grid.GridHeader.HeaderRow; import com.vaadin.client.ui.grid.Renderer; import com.vaadin.client.ui.grid.datasources.ListDataSource; import com.vaadin.client.ui.grid.datasources.ListSorter; +import com.vaadin.client.ui.grid.keyevents.BodyKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.BodyKeyPressHandler; +import com.vaadin.client.ui.grid.keyevents.BodyKeyUpHandler; +import com.vaadin.client.ui.grid.keyevents.FooterKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.FooterKeyPressHandler; +import com.vaadin.client.ui.grid.keyevents.FooterKeyUpHandler; +import com.vaadin.client.ui.grid.keyevents.GridKeyDownEvent; +import com.vaadin.client.ui.grid.keyevents.GridKeyPressEvent; +import com.vaadin.client.ui.grid.keyevents.GridKeyUpEvent; +import com.vaadin.client.ui.grid.keyevents.HeaderKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.HeaderKeyPressHandler; +import com.vaadin.client.ui.grid.keyevents.HeaderKeyUpHandler; import com.vaadin.client.ui.grid.renderers.DateRenderer; import com.vaadin.client.ui.grid.renderers.HtmlRenderer; import com.vaadin.client.ui.grid.renderers.NumberRenderer; @@ -236,7 +251,9 @@ public class GridBasicClientFeaturesWidget extends createFooterMenu(); grid.getElement().getStyle().setZIndex(0); - add(grid); + addNorth(grid, 400); + + createKeyHandlers(); } private void createStateMenu() { @@ -602,7 +619,7 @@ public class GridBasicClientFeaturesWidget extends } /** - * Creates a a renderer for a {@link Renderers} + * Creates a renderer for a {@link Renderers} */ @SuppressWarnings("rawtypes") private final Renderer createRenderer(Renderers renderer) { @@ -629,4 +646,110 @@ public class GridBasicClientFeaturesWidget extends return new TextRenderer(); } } + + /** + * Creates a collection of handlers for all the grid key events + */ + private void createKeyHandlers() { + final List labels = new ArrayList(); + for (int i = 0; i < 9; ++i) { + VLabel tmp = new VLabel(); + addNorth(tmp, 20); + labels.add(tmp); + } + + // Key Down Events + grid.addKeyDownHandler(new BodyKeyDownHandler>() { + private final VLabel label = labels.get(0); + + @Override + public void onKeyDown(GridKeyDownEvent> event) { + updateLabel(label, event); + } + }); + + grid.addKeyDownHandler(new HeaderKeyDownHandler>() { + private final VLabel label = labels.get(1); + + @Override + public void onKeyDown(GridKeyDownEvent> event) { + updateLabel(label, event); + } + }); + + grid.addKeyDownHandler(new FooterKeyDownHandler>() { + private final VLabel label = labels.get(2); + + @Override + public void onKeyDown(GridKeyDownEvent> event) { + updateLabel(label, event); + } + }); + + // Key Up Events + grid.addKeyUpHandler(new BodyKeyUpHandler>() { + private final VLabel label = labels.get(3); + + @Override + public void onKeyUp(GridKeyUpEvent> event) { + updateLabel(label, event); + } + }); + + grid.addKeyUpHandler(new HeaderKeyUpHandler>() { + private final VLabel label = labels.get(4); + + @Override + public void onKeyUp(GridKeyUpEvent> event) { + updateLabel(label, event); + } + }); + + grid.addKeyUpHandler(new FooterKeyUpHandler>() { + private final VLabel label = labels.get(5); + + @Override + public void onKeyUp(GridKeyUpEvent> event) { + updateLabel(label, event); + } + }); + + // Key Press Events + grid.addKeyPressHandler(new BodyKeyPressHandler>() { + private final VLabel label = labels.get(6); + + @Override + public void onKeyPress(GridKeyPressEvent> event) { + updateLabel(label, event); + } + }); + + grid.addKeyPressHandler(new HeaderKeyPressHandler>() { + private final VLabel label = labels.get(7); + + @Override + public void onKeyPress(GridKeyPressEvent> event) { + updateLabel(label, event); + } + }); + + grid.addKeyPressHandler(new FooterKeyPressHandler>() { + private final VLabel label = labels.get(8); + + @Override + public void onKeyPress(GridKeyPressEvent> event) { + updateLabel(label, event); + } + }); + + } + + private void updateLabel(VLabel label, + AbstractGridKeyEvent, ?> event) { + String type = event.getNativeEvent().getType(); + Cell active = event.getActiveCell(); + String coords = "(" + active.getRow() + ", " + active.getColumn() + ")"; + String keyCode = "" + event.getNativeKeyCode(); + label.setText(coords + " " + type + " " + keyCode); + } } -- cgit v1.2.3 From 32842a06a64d4351018ffb720d12aa8cd6011743 Mon Sep 17 00:00:00 2001 From: Patrik Lindström Date: Mon, 18 Aug 2014 16:04:28 +0300 Subject: Add event originator information to Sort Events (#13334) Change-Id: I9f8a295d6944807ccf89ea535d5500fac013e127 --- client/src/com/vaadin/client/ui/grid/Grid.java | 16 ++++++--- .../com/vaadin/client/ui/grid/GridConnector.java | 4 +-- .../com/vaadin/client/ui/grid/sort/SortEvent.java | 22 ++++++++++-- server/src/com/vaadin/ui/components/grid/Grid.java | 21 +++++++---- .../ui/components/grid/SortOrderChangeEvent.java | 21 ++++++++++- .../com/vaadin/shared/ui/grid/GridServerRpc.java | 3 +- .../vaadin/shared/ui/grid/SortEventOriginator.java | 41 ++++++++++++++++++++++ .../grid/basicfeatures/GridBasicFeatures.java | 19 +++++++++- .../grid/basicfeatures/server/GridSortingTest.java | 20 ++++++++--- 9 files changed, 142 insertions(+), 25 deletions(-) create mode 100644 shared/src/com/vaadin/shared/ui/grid/SortEventOriginator.java (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index a2bb0d3f09..22c3604bf8 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -87,6 +87,7 @@ import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.shared.ui.grid.Range; import com.vaadin.shared.ui.grid.ScrollDestination; import com.vaadin.shared.ui.grid.SortDirection; +import com.vaadin.shared.ui.grid.SortEventOriginator; /** * A data grid view that supports columns and lazy loading of data rows from a @@ -622,8 +623,8 @@ public class Grid extends Composite implements } } - // Perform sorting - Grid.this.sort(sorting); + // Perform sorting; indicate originator as user + Grid.this.setSortOrder(sorting.build(), SortEventOriginator.USER); } } @@ -2376,11 +2377,16 @@ public class Grid extends Composite implements * a sort order list. If set to null, the sort order is cleared. */ public void setSortOrder(List order) { + setSortOrder(order, SortEventOriginator.API); + } + + private void setSortOrder(List order, + SortEventOriginator originator) { sortOrder.clear(); if (order != null) { sortOrder.addAll(order); } - sort(); + sort(originator); } /** @@ -2505,9 +2511,9 @@ public class Grid extends Composite implements /** * Apply sorting to data source. */ - private void sort() { + private void sort(SortEventOriginator originator) { refreshHeader(); fireEvent(new SortEvent(this, - Collections.unmodifiableList(sortOrder))); + Collections.unmodifiableList(sortOrder), originator)); } } diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java index 9d93c81d82..73440232b1 100644 --- a/client/src/com/vaadin/client/ui/grid/GridConnector.java +++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java @@ -224,8 +224,8 @@ public class GridConnector extends AbstractHasComponentsConnector { if (!Arrays.equals(columnIds, getState().sortColumns) || !Arrays.equals(directions, getState().sortDirs)) { // Report back to server if changed - getRpcProxy(GridServerRpc.class) - .sort(columnIds, directions); + getRpcProxy(GridServerRpc.class).sort(columnIds, + directions, event.getOriginator()); } } }); diff --git a/client/src/com/vaadin/client/ui/grid/sort/SortEvent.java b/client/src/com/vaadin/client/ui/grid/sort/SortEvent.java index baa12ae224..edbd84c4a5 100644 --- a/client/src/com/vaadin/client/ui/grid/sort/SortEvent.java +++ b/client/src/com/vaadin/client/ui/grid/sort/SortEvent.java @@ -20,6 +20,7 @@ import java.util.List; import com.google.gwt.event.shared.GwtEvent; import com.vaadin.client.data.DataSource; import com.vaadin.client.ui.grid.Grid; +import com.vaadin.shared.ui.grid.SortEventOriginator; /** * A sort event, fired by the Grid when it needs its data source to provide data @@ -34,6 +35,7 @@ public class SortEvent extends GwtEvent> { private final Grid grid; private final List order; + private final SortEventOriginator originator; /** * Creates a new Sort Event. All provided parameters are final, and passed @@ -41,14 +43,16 @@ public class SortEvent extends GwtEvent> { * * @param grid * a grid reference - * @param datasource - * a reference to the grid's data source * @param order * an array dictating the desired sort order of the data source + * @param originator + * a value indicating where this event originated from */ - public SortEvent(Grid grid, List order) { + public SortEvent(Grid grid, List order, + SortEventOriginator originator) { this.grid = grid; this.order = order; + this.originator = originator; } @Override @@ -103,6 +107,18 @@ public class SortEvent extends GwtEvent> { return order; } + /** + * Gets a value describing the originator of this event, i.e. what actions + * resulted in this event being fired. + * + * @return a sort event originator value + * + * @see SortEventOriginator + */ + public SortEventOriginator getOriginator() { + return originator; + } + @SuppressWarnings("unchecked") @Override protected void dispatch(SortEventHandler handler) { diff --git a/server/src/com/vaadin/ui/components/grid/Grid.java b/server/src/com/vaadin/ui/components/grid/Grid.java index fba6eed462..3c115f9241 100644 --- a/server/src/com/vaadin/ui/components/grid/Grid.java +++ b/server/src/com/vaadin/ui/components/grid/Grid.java @@ -49,6 +49,7 @@ import com.vaadin.shared.ui.grid.GridStaticCellType; import com.vaadin.shared.ui.grid.HeightMode; import com.vaadin.shared.ui.grid.ScrollDestination; import com.vaadin.shared.ui.grid.SortDirection; +import com.vaadin.shared.ui.grid.SortEventOriginator; import com.vaadin.ui.AbstractComponent; import com.vaadin.ui.Component; import com.vaadin.ui.HasComponents; @@ -373,7 +374,8 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, } @Override - public void sort(String[] columnIds, SortDirection[] directions) { + public void sort(String[] columnIds, SortDirection[] directions, + SortEventOriginator originator) { assert columnIds.length == directions.length; List order = new ArrayList( @@ -383,7 +385,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, order.add(new SortOrder(propertyId, directions[i])); } - setSortOrder(order); + setSortOrder(order, originator); } }); } @@ -439,7 +441,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, } } - sort(); + sort(SortEventOriginator.INTERNAL); } else { // If the new container is not sortable, we'll just re-set the sort @@ -1126,7 +1128,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, */ public void clearSortOrder() { sortOrder.clear(); - sort(); + sort(false); } /** @@ -1140,6 +1142,11 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, * a sort order list. */ public void setSortOrder(List order) { + setSortOrder(order, SortEventOriginator.API); + } + + private void setSortOrder(List order, + SortEventOriginator originator) { if (!(getContainerDatasource() instanceof Container.Sortable)) { throw new IllegalStateException( "Attached container is not sortable (does not implement Container.Sortable)"); @@ -1164,7 +1171,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, } sortOrder.addAll(order); - sort(); + sort(originator); } /** @@ -1179,7 +1186,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, /** * Apply sorting to data source. */ - private void sort() { + private void sort(SortEventOriginator originator) { Container c = getContainerDatasource(); if (c instanceof Container.Sortable) { @@ -1215,7 +1222,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, cs.sort(propertyIds, directions); fireEvent(new SortOrderChangeEvent(this, new ArrayList( - sortOrder))); + sortOrder), originator)); getState().sortColumns = columnKeys; getState(false).sortDirs = stateDirs; diff --git a/server/src/com/vaadin/ui/components/grid/SortOrderChangeEvent.java b/server/src/com/vaadin/ui/components/grid/SortOrderChangeEvent.java index 71afa10a9b..690fcdf1c4 100644 --- a/server/src/com/vaadin/ui/components/grid/SortOrderChangeEvent.java +++ b/server/src/com/vaadin/ui/components/grid/SortOrderChangeEvent.java @@ -17,6 +17,7 @@ package com.vaadin.ui.components.grid; import java.util.List; +import com.vaadin.shared.ui.grid.SortEventOriginator; import com.vaadin.ui.Component; import com.vaadin.ui.components.grid.sort.SortOrder; @@ -31,6 +32,7 @@ import com.vaadin.ui.components.grid.sort.SortOrder; public class SortOrderChangeEvent extends Component.Event { private final List sortOrder; + private final SortEventOriginator originator; /** * Creates a new sort order change event for a grid and a sort order list. @@ -39,10 +41,15 @@ public class SortOrderChangeEvent extends Component.Event { * the grid from which the event originates * @param sortOrder * the new sort order list + * @param wasInitiatedByUser + * should be set to true if this event results from end-user + * interaction instead of an API call or side effect */ - public SortOrderChangeEvent(Grid grid, List sortOrder) { + public SortOrderChangeEvent(Grid grid, List sortOrder, + SortEventOriginator originator) { super(grid); this.sortOrder = sortOrder; + this.originator = originator; } /** @@ -54,4 +61,16 @@ public class SortOrderChangeEvent extends Component.Event { return sortOrder; } + /** + * Gets a value describing the originator of this event, i.e. what actions + * resulted in this event being fired. + * + * @return a sort event originator value + * + * @see SortEventOriginator + */ + public SortEventOriginator getOriginator() { + return originator; + } + } diff --git a/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java b/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java index 9ce094b092..fd671e30a7 100644 --- a/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java +++ b/shared/src/com/vaadin/shared/ui/grid/GridServerRpc.java @@ -28,5 +28,6 @@ import com.vaadin.shared.communication.ServerRpc; public interface GridServerRpc extends ServerRpc { void selectionChange(List newSelection); - void sort(String[] columnIds, SortDirection[] directions); + void sort(String[] columnIds, SortDirection[] directions, + SortEventOriginator originator); } diff --git a/shared/src/com/vaadin/shared/ui/grid/SortEventOriginator.java b/shared/src/com/vaadin/shared/ui/grid/SortEventOriginator.java new file mode 100644 index 0000000000..acdd46ea5b --- /dev/null +++ b/shared/src/com/vaadin/shared/ui/grid/SortEventOriginator.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2014 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; + +/** + * Identifier for the originator of a sort event or sort order change event. + * + * @since + * @author Vaadin Ltd + */ +public enum SortEventOriginator { + + /** + * This event was the result of an API call. + */ + API, + + /** + * This event was the result of a user interacting with the UI. + */ + USER, + + /** + * This event resulted as a side-effect of an internal event. + */ + INTERNAL + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java index 031ebf7fa5..d54b1838ea 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -168,7 +168,24 @@ public class GridBasicFeatures extends AbstractComponentTest { grid.addSortOrderChangeListener(new SortOrderChangeListener() { @Override public void sortOrderChange(SortOrderChangeEvent event) { - log("Sort order: " + event.getSortOrder()); + + String origin; + switch (event.getOriginator()) { + case API: + origin = "API"; + break; + case INTERNAL: + origin = "INTERNAL"; + break; + case USER: + origin = "USER"; + break; + default: + origin = "!!! ERROR !!!"; + break; + } + + log("Sort order: " + event.getSortOrder() + " by " + origin); } }); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java index a5a83c156e..024be65e83 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java @@ -42,6 +42,11 @@ public class GridSortingTest extends GridBasicFeaturesTest { // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0) sortBy("Column 9, DESC"); + // Verify that programmatic sorting calls are identified as originating + // from API + assertEquals("3. Sort order: [Column 9 DESCENDING] by API", + getLogRow(0)); + assertTrue("Column 9 should have the sort-desc stylename", grid .getHeaderCell(0, 9).getAttribute("class") .contains("sort-desc")); @@ -119,14 +124,17 @@ public class GridSortingTest extends GridBasicFeaturesTest { "(" + row + ", 0)", grid.getCell(i, 0).getText()); } - assertEquals("2. Sort order: [Column 9 ASCENDING]", getLogRow(2)); - assertEquals("4. Sort order: [Column 9 DESCENDING]", getLogRow(0)); + assertEquals("2. Sort order: [Column 9 ASCENDING] by USER", + getLogRow(2)); + assertEquals("4. Sort order: [Column 9 DESCENDING] by USER", + getLogRow(0)); // Column 10 is random numbers from Random with seed 13334 // Click header to sort ascending grid.getHeaderCell(0, 10).click(); - assertEquals("6. Sort order: [Column 10 ASCENDING]", getLogRow(0)); + assertEquals("6. Sort order: [Column 10 ASCENDING] by USER", + getLogRow(0)); // Not cleaning up correctly causes exceptions when scrolling. grid.scrollToRow(50); @@ -153,8 +161,10 @@ public class GridSortingTest extends GridBasicFeaturesTest { grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); } - assertEquals("9. Sort order: [Column 7 ASCENDING]", getLogRow(3)); - assertEquals("11. Sort order: [Column 7 DESCENDING]", getLogRow(1)); + assertEquals("9. Sort order: [Column 7 ASCENDING] by USER", + getLogRow(3)); + assertEquals("11. Sort order: [Column 7 DESCENDING] by USER", + getLogRow(1)); } @Test -- cgit v1.2.3 From 204b16013ccc129dc4ce78cab73a51a65f5bf4c8 Mon Sep 17 00:00:00 2001 From: John Ahlroos Date: Wed, 13 Aug 2014 14:02:42 +0300 Subject: Added PAGEUP/PAGEDOWN/HOME/END keyboard navigation #13334 Change-Id: Ib415d4b3abcefc11983f2daa8cb11a2bdd99b95a --- client/src/com/vaadin/client/ui/grid/Grid.java | 100 +++++++++++++++------ .../server/GridKeyboardNavigationTest.java | 55 +++++++++++- 2 files changed, 129 insertions(+), 26 deletions(-) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index 22c3604bf8..0e077f4867 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -454,31 +454,6 @@ public class Grid extends Composite implements } - private int getLastVisibleRowIndex() { - int lastRowIndex = escalator.getVisibleRowRange().getEnd(); - int footerTop = escalator.getFooter().getElement().getAbsoluteTop(); - Element lastRow; - - do { - lastRow = escalator.getBody().getRowElement(--lastRowIndex); - } while (lastRow.getAbsoluteBottom() > footerTop); - - return lastRowIndex; - } - - private int getFirstVisibleRowIndex() { - int firstRowIndex = escalator.getVisibleRowRange().getStart(); - int headerBottom = escalator.getHeader().getElement() - .getAbsoluteBottom(); - Element firstRow = escalator.getBody().getRowElement(firstRowIndex); - - while (firstRow.getAbsoluteTop() < headerBottom) { - firstRow = escalator.getBody().getRowElement(++firstRowIndex); - } - - return firstRowIndex; - } - private RowContainer getPreviousContainer(RowContainer current) { if (current == escalator.getFooter()) { current = escalator.getBody(); @@ -1984,9 +1959,59 @@ public class Grid extends Composite implements && (Util.getFocusedElement() == getElement() || cell != null)) { activeCellHandler.handleNavigationEvent(event, cell); } + + handleGridNavigation(event, cell); } } + private void handleGridNavigation(Event event, Cell cell) { + if (!event.getType().equals(BrowserEvents.KEYDOWN)) { + // Only handle key downs + return; + } + + int newRow = -1; + RowContainer container = escalator.getBody(); + switch (event.getKeyCode()) { + case KeyCodes.KEY_HOME: + if (container.getRowCount() > 0) { + newRow = 0; + } + break; + case KeyCodes.KEY_END: + if (container.getRowCount() > 0) { + newRow = container.getRowCount() - 1; + } + break; + case KeyCodes.KEY_PAGEUP: { + Range range = escalator.getVisibleRowRange(); + if (!range.isEmpty()) { + int firstIndex = getFirstVisibleRowIndex(); + newRow = firstIndex - range.length(); + if (newRow < 0) { + newRow = 0; + } + } + break; + } + case KeyCodes.KEY_PAGEDOWN: { + Range range = escalator.getVisibleRowRange(); + if (!range.isEmpty()) { + int lastIndex = getLastVisibleRowIndex(); + newRow = lastIndex + range.length(); + if (newRow >= container.getRowCount()) { + newRow = container.getRowCount() - 1; + } + } + break; + } + default: + return; + } + + scrollToRow(newRow); + } + private Point rowEventTouchStartingPoint; private boolean handleDefaultRowEvent(final Cell cell, NativeEvent event) { @@ -2516,4 +2541,29 @@ public class Grid extends Composite implements fireEvent(new SortEvent(this, Collections.unmodifiableList(sortOrder), originator)); } + + private int getLastVisibleRowIndex() { + int lastRowIndex = escalator.getVisibleRowRange().getEnd(); + int footerTop = escalator.getFooter().getElement().getAbsoluteTop(); + Element lastRow; + + do { + lastRow = escalator.getBody().getRowElement(--lastRowIndex); + } while (lastRow.getAbsoluteBottom() > footerTop); + + return lastRowIndex; + } + + private int getFirstVisibleRowIndex() { + int firstRowIndex = escalator.getVisibleRowRange().getStart(); + int headerBottom = escalator.getHeader().getElement() + .getAbsoluteBottom(); + Element firstRow = escalator.getBody().getRowElement(firstRowIndex); + + while (firstRow.getAbsoluteTop() < headerBottom) { + firstRow = escalator.getBody().getRowElement(++firstRowIndex); + } + + return firstRowIndex; + } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java index 948c753fec..0f9fd875d8 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java @@ -24,7 +24,7 @@ import org.openqa.selenium.Keys; import org.openqa.selenium.interactions.Actions; import com.vaadin.tests.components.grid.GridElement; -import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { @@ -169,4 +169,57 @@ public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { assertTrue("Footer cell 0, 2 is not active", grid.getFooterCell(0, 2) .isActive()); } + + @Test + public void testHomeEnd() throws Exception { + openTestURL(); + + getGridElement().getCell(100, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.HOME).perform(); + assertTrue("First row is not visible", getGridElement().getCell(0, 2) + .isDisplayed()); + + new Actions(getDriver()).sendKeys(Keys.END).perform(); + assertTrue("Last row cell not visible", + getGridElement().getCell(GridBasicFeatures.ROWS - 1, 2) + .isDisplayed()); + } + + @Test + public void testPageUpPageDown() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Size", "HeightMode Row"); + + getGridElement().getCell(5, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.PAGE_DOWN).perform(); + assertTrue("Row 5 did not remain active", getGridElement() + .getCell(5, 2).isActive()); + assertTrue("Row 20 did not become visible", + getGridElement().getCell(20, 2).isDisplayed()); + + new Actions(getDriver()).sendKeys(Keys.PAGE_DOWN).perform(); + assertTrue("Row 5 did not remain active", getGridElement() + .getCell(5, 2).isActive()); + assertTrue("Row 40 did not become visible", + getGridElement().getCell(40, 2).isDisplayed()); + + getGridElement().getCell(50, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.PAGE_UP).perform(); + assertTrue("Row 50 did not remain active", + getGridElement().getCell(50, 2).isActive()); + assertTrue("Row 20 did not become visible", + getGridElement().getCell(20, 2).isDisplayed()); + + new Actions(getDriver()).sendKeys(Keys.PAGE_UP).perform(); + assertTrue("Row 50 did not remain active", + getGridElement().getCell(50, 2).isActive()); + assertTrue("Row 0 did not become visible", + getGridElement().getCell(0, 2).isDisplayed()); + + } + } -- cgit v1.2.3 From d9ff10864bc17bfd6e83725a293065b91d234904 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Tue, 19 Aug 2014 11:36:41 +0300 Subject: Implement selection with keyboard (#13334) Change-Id: I29a2ac38dfd613e952fd2f939ee8670271255aa3 --- client/src/com/vaadin/client/ui/grid/Grid.java | 5 ++ .../client/ui/grid/renderers/ComplexRenderer.java | 8 +++ .../ui/grid/selection/MultiSelectionRenderer.java | 67 ++++++++++++++++++++++ .../basicfeatures/server/GridSelectionTest.java | 28 +++++++++ 4 files changed, 108 insertions(+) (limited to 'uitest/src/com/vaadin/tests/components/grid/basicfeatures') diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index cf802b5d48..70d8286c90 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -2222,6 +2222,11 @@ public class Grid extends Composite implements throw new IllegalArgumentException("Selection model can't be null"); } + if (selectColumnRenderer != null + && selectColumnRenderer instanceof ComplexRenderer) { + ((ComplexRenderer) selectColumnRenderer).destroy(); + } + this.selectionModel = selectionModel; selectionModel.setGrid(this); setSelectColumnRenderer(this.selectionModel diff --git a/client/src/com/vaadin/client/ui/grid/renderers/ComplexRenderer.java b/client/src/com/vaadin/client/ui/grid/renderers/ComplexRenderer.java index d5dd845e92..f0c95e2ddf 100644 --- a/client/src/com/vaadin/client/ui/grid/renderers/ComplexRenderer.java +++ b/client/src/com/vaadin/client/ui/grid/renderers/ComplexRenderer.java @@ -142,4 +142,12 @@ public abstract class ComplexRenderer implements Renderer { public boolean onActivate() { return false; } + + /** + * Called when the renderer is deemed to be destroyed and no longer used by + * the Grid. + */ + public void destroy() { + // Implement if needed + } } diff --git a/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java b/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java index 1033b00623..a3030e3a1f 100644 --- a/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java +++ b/client/src/com/vaadin/client/ui/grid/selection/MultiSelectionRenderer.java @@ -27,6 +27,7 @@ import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.InputElement; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.TableElement; +import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; @@ -36,10 +37,17 @@ import com.vaadin.client.Util; import com.vaadin.client.data.AbstractRemoteDataSource; import com.vaadin.client.data.DataSource; import com.vaadin.client.ui.grid.Cell; +import com.vaadin.client.ui.grid.DataAvailableEvent; +import com.vaadin.client.ui.grid.DataAvailableHandler; import com.vaadin.client.ui.grid.FlyweightCell; import com.vaadin.client.ui.grid.Grid; +import com.vaadin.client.ui.grid.keyevents.BodyKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.BodyKeyUpHandler; +import com.vaadin.client.ui.grid.keyevents.GridKeyDownEvent; +import com.vaadin.client.ui.grid.keyevents.GridKeyUpEvent; import com.vaadin.client.ui.grid.renderers.ComplexRenderer; import com.vaadin.client.ui.grid.selection.SelectionModel.Multi.Batched; +import com.vaadin.shared.ui.grid.ScrollDestination; /* This class will probably not survive the final merge of all selection functionality. */ public class MultiSelectionRenderer extends ComplexRenderer { @@ -576,15 +584,74 @@ public class MultiSelectionRenderer extends ComplexRenderer { } } + private class SpaceKeyDownSelectHandler implements BodyKeyDownHandler { + + private HandlerRegistration scrollHandler = null; + private boolean spaceDown = false; + + @Override + public void onKeyDown(GridKeyDownEvent event) { + if (event.getNativeKeyCode() != KeyCodes.KEY_SPACE || spaceDown) { + return; + } + + spaceDown = true; + Cell active = event.getActiveCell(); + final int rowIndex = active.getRow(); + + if (scrollHandler != null) { + scrollHandler.removeHandler(); + scrollHandler = null; + } + + scrollHandler = grid + .addDataAvailableHandler(new DataAvailableHandler() { + + @Override + public void onDataAvailable(DataAvailableEvent event) { + if (event.getAvailableRows().contains(rowIndex)) { + setSelected(rowIndex, !isSelected(rowIndex)); + scrollHandler.removeHandler(); + scrollHandler = null; + } + } + }); + grid.scrollToRow(rowIndex, ScrollDestination.ANY); + } + + } + private static final String LOGICAL_ROW_PROPERTY_INT = "vEscalatorLogicalRow"; private final Grid grid; private HandlerRegistration nativePreviewHandlerRegistration; + private final SpaceKeyDownSelectHandler handler = new SpaceKeyDownSelectHandler(); + private HandlerRegistration spaceDown; + private HandlerRegistration spaceUp; private final AutoScrollHandler autoScrollHandler = new AutoScrollHandler(); public MultiSelectionRenderer(final Grid grid) { this.grid = grid; + spaceDown = grid.addKeyDownHandler(handler); + spaceUp = grid.addKeyUpHandler(new BodyKeyUpHandler() { + + @Override + public void onKeyUp(GridKeyUpEvent event) { + if (event.getNativeKeyCode() == KeyCodes.KEY_SPACE) { + handler.spaceDown = false; + } + } + }); + } + + @Override + public void destroy() { + spaceDown.removeHandler(); + spaceUp.removeHandler(); + if (nativePreviewHandlerRegistration != null) { + removeNativeHandler(); + } } @Override diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java index c190f7d0ec..6e2ac91df2 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java @@ -19,6 +19,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; import com.vaadin.testbench.TestBenchElement; import com.vaadin.tests.components.grid.GridElement; @@ -123,6 +125,32 @@ public class GridSelectionTest extends GridBasicFeaturesTest { assertTrue("First row was not selected.", getRow(0).isSelected()); } + @Test + public void testKeyboardSelection() { + openTestURL(); + setSelectionModelMulti(); + + GridElement grid = getGridElement(); + grid.getCell(3, 1).click(); + new Actions(getDriver()).sendKeys(Keys.SPACE).perform(); + + assertTrue("Grid row 3 was not selected with space key.", grid + .getRow(3).isSelected()); + + new Actions(getDriver()).sendKeys(Keys.SPACE).perform(); + + assertTrue("Grid row 3 was not deselected with space key.", !grid + .getRow(3).isSelected()); + + grid.scrollToRow(500); + + new Actions(getDriver()).sendKeys(Keys.SPACE).perform(); + + assertTrue("Grid row 3 was not selected with space key.", grid + .getRow(3).isSelected()); + + } + private void setSelectionModelMulti() { selectMenuPath("Component", "State", "Selection mode", "multi"); } -- cgit v1.2.3