diff options
author | Mikael Grankvist <mgrankvi@vaadin.com> | 2015-03-20 08:07:51 +0200 |
---|---|---|
committer | Markus Koivisto <markus@vaadin.com> | 2015-04-15 11:53:35 +0300 |
commit | 0e1953be8f49c906c288416a3971519cea987713 (patch) | |
tree | a03fff30db4b0088a8f52b0591c959772889816a | |
parent | 583750936967e2eb2b35d48a8ea2519f351db1de (diff) | |
download | vaadin-framework-0e1953be8f49c906c288416a3971519cea987713.tar.gz vaadin-framework-0e1953be8f49c906c288416a3971519cea987713.zip |
Grid header should render "the same" after changes to header (#17131)
Change-Id: I2a16ffbd59bf4863eb6a7bea8d4b590a693af637
3 files changed, 403 insertions, 18 deletions
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index 4b27e17e37..3aaac14f10 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -2178,14 +2178,33 @@ public class Grid<T> extends ResizeComposite implements public final class SelectionColumn extends Column<Boolean, T> { private boolean initDone = false; + private boolean selected = false; SelectionColumn(final Renderer<Boolean> selectColumnRenderer) { super(selectColumnRenderer); } void initDone() { + addSelectAllToDefaultHeader(); + + setWidth(-1); + + setEditable(false); + + initDone = true; + } + + protected void addSelectAllToDefaultHeader() { if (getSelectionModel() instanceof SelectionModel.Multi && header.getDefaultRow() != null) { + // If selection cell already contains a widget do not + // create a new CheckBox + HeaderCell selectionCell = header.getDefaultRow().getCell(this); + if (selectionCell.getType() + .equals(GridStaticCellType.WIDGET) + && selectionCell.getWidget() instanceof CheckBox) { + return; + } /* * TODO: Currently the select all check box is shown when multi * selection is in use. This might result in malfunctions if no @@ -2202,19 +2221,18 @@ public class Grid<T> extends ResizeComposite implements public void onValueChange(ValueChangeEvent<Boolean> event) { if (event.getValue()) { fireEvent(new SelectAllEvent<T>(model)); + selected = true; } else { model.deselectAll(); + selected = false; } } }); - header.getDefaultRow().getCell(this).setWidget(checkBox); - } + checkBox.setValue(selected); - setWidth(-1); - - setEditable(false); + selectionCell.setWidget(checkBox); - initDone = true; + } } @Override @@ -3685,27 +3703,34 @@ public class Grid<T> extends ResizeComposite implements final StaticSection.StaticCell metadata = staticRow .getCell(columns.get(cell.getColumn())); + boolean updateCellData = true; // Decorate default row with sorting indicators if (staticRow instanceof HeaderRow) { addSortingIndicatorsToHeaderRow((HeaderRow) staticRow, cell); + + if (isHeaderSelectionColumn(row, cell)) { + updateCellData = false; + } } // Assign colspan to cell before rendering cell.setColSpan(metadata.getColspan()); TableCellElement element = cell.getElement(); - switch (metadata.getType()) { - case TEXT: - element.setInnerText(metadata.getText()); - break; - case HTML: - element.setInnerHTML(metadata.getHtml()); - break; - case WIDGET: - preDetach(row, Arrays.asList(cell)); - element.setInnerHTML(""); - postAttach(row, Arrays.asList(cell)); - break; + if (updateCellData) { + switch (metadata.getType()) { + case TEXT: + element.setInnerText(metadata.getText()); + break; + case HTML: + element.setInnerHTML(metadata.getHtml()); + break; + case WIDGET: + preDetach(row, Arrays.asList(cell)); + element.setInnerHTML(""); + postAttach(row, Arrays.asList(cell)); + break; + } } setCustomStyleName(element, metadata.getStyleName()); @@ -3765,6 +3790,27 @@ public class Grid<T> extends ResizeComposite implements @Override public void preAttach(Row row, Iterable<FlyweightCell> cellsToAttach) { + // Add select all checkbox if needed on rebuild. + for (FlyweightCell cell : cellsToAttach) { + if (isHeaderSelectionColumn(row, cell)) { + selectionColumn.addSelectAllToDefaultHeader(); + } + } + } + + /** + * Check if selectionColumn in the default header row + */ + private boolean isHeaderSelectionColumn(Row row, FlyweightCell cell) { + return selectionColumn != null && isDefaultHeaderRow(row) + && getColumn(cell.getColumn()).equals(selectionColumn); + } + + /** + * Row is the default header row. + */ + private boolean isDefaultHeaderRow(Row row) { + return section.getRow(row.getRow()).equals(header.getDefaultRow()); } @Override diff --git a/uitest/src/com/vaadin/tests/components/grid/GridHeaderFormatChange.java b/uitest/src/com/vaadin/tests/components/grid/GridHeaderFormatChange.java new file mode 100644 index 0000000000..fbd6a42a38 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridHeaderFormatChange.java @@ -0,0 +1,183 @@ +/* + * 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 java.io.Serializable; + +import com.vaadin.data.util.BeanItemContainer; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Grid; +import com.vaadin.ui.Grid.HeaderRow; +import com.vaadin.ui.Grid.SelectionMode; +import com.vaadin.ui.Grid.SelectionModel; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.renderers.NumberRenderer; + +public class GridHeaderFormatChange extends AbstractTestUI { + + private static final long serialVersionUID = -2787771187365766027L; + + private HeaderRow row; + + public class Person implements Serializable { + private static final long serialVersionUID = -7995927620756317000L; + + String firstName; + String lastName; + String streetAddress; + Integer zipCode; + String city; + + public Person(String firstName, String lastName, String streetAddress, + Integer zipCode, String city) { + this.firstName = firstName; + this.lastName = lastName; + this.streetAddress = streetAddress; + this.zipCode = zipCode; + this.city = city; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getStreetAddress() { + return streetAddress; + } + + public void setStreetAddress(String streetAddress) { + this.streetAddress = streetAddress; + } + + public Integer getZipCode() { + return zipCode; + } + + public void setZipCode(Integer zipCode) { + this.zipCode = zipCode; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + } + + @Override + protected void setup(VaadinRequest request) { + BeanItemContainer<Person> datasource = new BeanItemContainer<Person>( + Person.class); + final Grid grid; + + datasource.addItem(new Person("Rudolph", "Reindeer", "Ruukinkatu 2-4", + 20540, "Turku")); + + grid = new Grid(datasource); + grid.setWidth("600px"); + grid.getColumn("zipCode").setRenderer(new NumberRenderer()); + grid.setColumnOrder("firstName", "lastName", "streetAddress", + "zipCode", "city"); + grid.setSelectionMode(SelectionMode.SINGLE); + addComponent(grid); + + Button showHide = new Button("Hide firstName", + new Button.ClickListener() { + private static final long serialVersionUID = 8107530972693788705L; + + @Override + public void buttonClick(ClickEvent event) { + if (grid.getColumn("firstName") != null) { + grid.removeColumn("firstName"); + event.getButton().setCaption("Show firstName"); + } else { + grid.addColumn("firstName"); + grid.setColumnOrder("firstName", "lastName", + "streetAddress", "zipCode", "city"); + + event.getButton().setCaption("Hide firstName"); + } + } + }); + showHide.setId("show_hide"); + + Button selectionMode = new Button("Set multiselect", + new Button.ClickListener() { + private static final long serialVersionUID = 8107530972693788705L; + + @Override + public void buttonClick(ClickEvent event) { + if (grid.getSelectionModel() instanceof SelectionModel.Single) { + grid.setSelectionMode(SelectionMode.MULTI); + } else { + grid.setSelectionMode(SelectionMode.SINGLE); + } + } + }); + selectionMode.setId("selection_mode"); + + Button join = new Button("Add Join header column", + new Button.ClickListener() { + private static final long serialVersionUID = -5330801275551280623L; + + @Override + public void buttonClick(ClickEvent event) { + if (row == null) { + row = grid.prependHeaderRow(); + if (grid.getColumn("firstName") != null) { + row.join("firstName", "lastName").setText( + "Full Name"); + } + row.join("streetAddress", "zipCode", "city") + .setText("Address"); + } else { + grid.removeHeaderRow(row); + row = null; + } + } + }); + join.setId("join"); + addComponent(new HorizontalLayout(showHide, selectionMode, join)); + } + + @Override + protected String getTestDescription() { + return "Grid for testing header re-rendering."; + } + + @Override + protected Integer getTicketNumber() { + return 17131; + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/GridHeaderFormatChangeTest.java b/uitest/src/com/vaadin/tests/components/grid/GridHeaderFormatChangeTest.java new file mode 100644 index 0000000000..0e2a3d6ac6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridHeaderFormatChangeTest.java @@ -0,0 +1,156 @@ +/* + * 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 org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.GridElement; +import com.vaadin.testbench.parallel.TestCategory; +import com.vaadin.tests.tb3.MultiBrowserTest; + +@TestCategory("grid") +public class GridHeaderFormatChangeTest extends MultiBrowserTest { + + @Test + public void testHeaderRetainsSelectAllForColumnRemoval() { + openTestURL(); + GridElement grid = $(GridElement.class).first(); + + // Assert that we do not have the select all checkbox + Assert.assertTrue( + "Found input in header even though none should exist.", grid + .getHeader().findElements(By.tagName("input")) + .isEmpty()); + + // Set grid into multiselection mode + toggleSelectionMode(); + + // Assert that we now have a select all checkbox in the header + Assert.assertFalse("Expected one input field in header", grid + .getHeader().findElements(By.tagName("input")).isEmpty()); + + // Hide the firstName column from the grid. + toggleFirstName(); + + // Assert that we still have the select all checkbox in the header. + Assert.assertFalse("Header was missing checkbox after hiding column", + grid.getHeader().findElements(By.tagName("input")).isEmpty()); + + // Show the firstName column. + toggleFirstName(); + + // Assert that we still have the select all checkbox in the header. + Assert.assertFalse( + "Header was missing checkbox after bringing back column", grid + .getHeader().findElements(By.tagName("input")) + .isEmpty()); + } + + @Test + public void testHeaderRetainsSelectAllForJoinColumnAdd() { + openTestURL(); + GridElement grid = $(GridElement.class).first(); + + // Assert that we do not have the select all checkbox + Assert.assertTrue( + "Found input in header even though none should exist.", grid + .getHeader().findElements(By.tagName("input")) + .isEmpty()); + + // Set grid into multiselection mode + toggleSelectionMode(); + + // Assert that we now have a select all checkbox in the header + Assert.assertFalse("Expected one input field in header", grid + .getHeader().findElements(By.tagName("input")).isEmpty()); + + // Add Join columns header + toggleJoin(); + + // Assert that we still have the select all checkbox in the header. + Assert.assertFalse("Header was missing checkbox after hiding column", + grid.getHeader().findElements(By.tagName("input")).isEmpty()); + + // remove Join Columns header + toggleJoin(); + + // Assert that we still have the select all checkbox in the header. + Assert.assertFalse( + "Header was missing checkbox after bringing back column", grid + .getHeader().findElements(By.tagName("input")) + .isEmpty()); + } + + @Test + public void selectAllShouldKeepState() { + openTestURL(); + GridElement grid = $(GridElement.class).first(); + + // Assert that we do not have the select all checkbox + Assert.assertTrue( + "Found input in header even though none should exist.", grid + .getHeader().findElements(By.tagName("input")) + .isEmpty()); + + // Set grid into multiselection mode + toggleSelectionMode(); + + // Assert that we now have a select all checkbox in the header + Assert.assertFalse("Should not be selected after adding", grid + .getHeader().findElement(By.tagName("input")).isSelected()); + + grid.getHeader().findElement(By.tagName("input")).click(); + + // Assert that checkbox is checked + assertSelectAllChecked( + "Not selected even though we just clicked selection", grid); + + // Hide the firstName column from the grid. + toggleFirstName(); + + // Assert that checkbox is still checked + assertSelectAllChecked("Selection disappeared after removing column", + grid); + + // Show the firstName column. + toggleFirstName(); + + // Assert that checkbox is still checked + assertSelectAllChecked("Selection disappeared after adding column", + grid); + + } + + private void assertSelectAllChecked(String message, GridElement grid) { + Assert.assertTrue(message, + grid.getHeader().findElement(By.tagName("input")).isSelected()); + } + + private void toggleSelectionMode() { + $(ButtonElement.class).id("selection_mode").click(); + } + + private void toggleFirstName() { + $(ButtonElement.class).id("show_hide").click(); + } + + private void toggleJoin() { + $(ButtonElement.class).id("join").click(); + } +} |