column.setSortable(getState().sortable);
}
+ @OnStateChange("hidingToggleCaption")
+ void updateHidingToggleCaption() {
+ column.setHidingToggleCaption(getState().hidingToggleCaption);
+ }
+
+ @OnStateChange("hidden")
+ void updateHidden() {
+ column.setHidden(getState().hidden);
+ }
+
+ @OnStateChange("hidable")
+ void updateHidable() {
+ column.setHidable(getState().hidable);
+ }
+
@Override
public void onUnregister() {
super.onUnregister();
return null;
});
+ getWidget().addColumnVisibilityChangeHandler(event -> {
+ if (event.isUserOriginated()) {
+ getRpcProxy(GridServerRpc.class).columnVisibilityChanged(
+ getColumnId(event.getColumn()), event.isHidden());
+ }
+ });
+
/* Item click events */
getWidget().addBodyClickHandler(itemClickHandler);
getWidget().addBodyDoubleClickHandler(itemClickHandler);
private static final Method ITEM_CLICK_METHOD = ReflectTools
.findMethod(ItemClickListener.class, "accept", ItemClick.class);
+ @Deprecated
+ private static final Method COLUMN_VISIBILITY_METHOD = ReflectTools
+ .findMethod(ColumnVisibilityChangeListener.class,
+ "columnVisibilityChanged",
+ ColumnVisibilityChangeEvent.class);
+
/**
* An event fired when an item in the Grid has been clicked.
*
}
}
+ /**
+ * An event listener for column visibility change events in the Grid.
+ *
+ * @since 7.5.0
+ */
+ public interface ColumnVisibilityChangeListener extends Serializable {
+
+ /**
+ * Called when a column has become hidden or unhidden.
+ *
+ * @param event
+ */
+ void columnVisibilityChanged(ColumnVisibilityChangeEvent event);
+ }
+
+ /**
+ * An event that is fired when a column's visibility changes.
+ *
+ * @since 7.5.0
+ */
+ public static class ColumnVisibilityChangeEvent extends Component.Event {
+
+ private final Column<?, ?> column;
+ private final boolean userOriginated;
+ private final boolean hidden;
+
+ /**
+ * Constructor for a column visibility change event.
+ *
+ * @param source
+ * the grid from which this event originates
+ * @param column
+ * the column that changed its visibility
+ * @param hidden
+ * <code>true</code> if the column was hidden,
+ * <code>false</code> if it became visible
+ * @param isUserOriginated
+ * <code>true</code> iff the event was triggered by an UI
+ * interaction
+ */
+ public ColumnVisibilityChangeEvent(Grid<?> source, Column<?, ?> column,
+ boolean hidden, boolean isUserOriginated) {
+ super(source);
+ this.column = column;
+ this.hidden = hidden;
+ userOriginated = isUserOriginated;
+ }
+
+ /**
+ * Gets the column that became hidden or visible.
+ *
+ * @return the column that became hidden or visible.
+ * @see Column#isHidden()
+ */
+ public Column<?, ?> getColumn() {
+ return column;
+ }
+
+ /**
+ * Was the column set hidden or visible.
+ *
+ * @return <code>true</code> if the column was hidden <code>false</code>
+ * if it was set visible
+ */
+ public boolean isHidden() {
+ return hidden;
+ }
+
+ /**
+ * Returns <code>true</code> if the column reorder was done by the user,
+ * <code>false</code> if not and it was triggered by server side code.
+ *
+ * @return <code>true</code> if event is a result of user interaction
+ */
+ public boolean isUserOriginated() {
+ return userOriginated;
+ }
+ }
+
/**
* A callback interface for generating description texts for an item.
*
}
@Override
- public void columnVisibilityChanged(String id, boolean hidden,
- boolean userOriginated) {
- // TODO Auto-generated method stub
+ public void columnVisibilityChanged(String id, boolean hidden) {
+ Column<T, ?> column = getColumn(id);
+ ColumnState columnState = column.getState(false);
+ if (columnState.hidden != hidden) {
+ columnState.hidden = hidden;
+ fireColumnVisibilityChangeEvent(column, hidden, true);
+ }
}
@Override
public DescriptionGenerator<T> getDescriptionGenerator() {
return descriptionGenerator;
}
+
+ /**
+ * Sets the caption of the hiding toggle for this column. Shown in the
+ * toggle for this column in the grid's sidebar when the column is
+ * {@link #isHidable() hidable}.
+ * <p>
+ * The default value is <code>null</code>, and in that case the column's
+ * {@link #getHeaderCaption() header caption} is used.
+ * <p>
+ * <em>NOTE:</em> setting this to empty string might cause the hiding
+ * toggle to not render correctly.
+ *
+ * @since 7.5.0
+ * @param hidingToggleCaption
+ * the text to show in the column hiding toggle
+ * @return the column itself
+ */
+ public Column<T, V> setHidingToggleCaption(String hidingToggleCaption) {
+ if (hidingToggleCaption != getHidingToggleCaption()) {
+ getState().hidingToggleCaption = hidingToggleCaption;
+ }
+ return this;
+ }
+
+ /**
+ * Gets the caption of the hiding toggle for this column.
+ *
+ * @since 7.5.0
+ * @see #setHidingToggleCaption(String)
+ * @return the caption for the hiding toggle for this column
+ */
+ public String getHidingToggleCaption() {
+ return getState(false).hidingToggleCaption;
+ }
+
+ /**
+ * Hides or shows the column. By default columns are visible before
+ * explicitly hiding them.
+ *
+ * @since 7.5.0
+ * @param hidden
+ * <code>true</code> to hide the column, <code>false</code>
+ * to show
+ * @return this column
+ * @throws IllegalStateException
+ * if the column is no longer attached to any grid
+ */
+ public Column<T, V> setHidden(boolean hidden) {
+ checkColumnIsAttached();
+ if (hidden != isHidden()) {
+ getState().hidden = hidden;
+ getParent().fireColumnVisibilityChangeEvent(this, hidden,
+ false);
+ }
+ return this;
+ }
+
+ /**
+ * Returns whether this column is hidden. Default is {@code false}.
+ *
+ * @since 7.5.0
+ * @return <code>true</code> if the column is currently hidden,
+ * <code>false</code> otherwise
+ */
+ public boolean isHidden() {
+ return getState(false).hidden;
+ }
+
+ /**
+ * Sets whether this column can be hidden by the user. Hidable columns
+ * can be hidden and shown via the sidebar menu.
+ *
+ * @since 7.5.0
+ * @param hidable
+ * <code>true</code> iff the column may be hidable by the
+ * user via UI interaction
+ * @return this column
+ */
+ public Column<T, V> setHidable(boolean hidable) {
+ if (hidable != isHidable()) {
+ getState().hidable = hidable;
+ }
+ return this;
+ }
+
+ /**
+ * Returns whether this column can be hidden by the user. Default is
+ * {@code false}.
+ * <p>
+ * <em>Note:</em> the column can be programmatically hidden using
+ * {@link #setHidden(boolean)} regardless of the returned value.
+ *
+ * @since 7.5.0
+ * @return <code>true</code> if the user can hide the column,
+ * <code>false</code> if not
+ */
+ public boolean isHidable() {
+ return getState(false).hidable;
+ }
+
+ /**
+ * Checks whether this column is attached and throws an
+ * {@link IllegalStateException} if it is not.
+ *
+ * @throws IllegalStateException
+ * if the column is no longer attached to any grid
+ */
+ protected void checkColumnIsAttached() throws IllegalStateException {
+ if (getParent() == null) {
+ throw new IllegalStateException(
+ "Column is no longer attached to a grid.");
+ }
+ }
}
private final class SingleSelection extends AbstractSingleSelection {
});
}
+ public <V> void fireColumnVisibilityChangeEvent(Column<T, V> column,
+ boolean hidden, boolean userOriginated) {
+ fireEvent(new ColumnVisibilityChangeEvent(this, column, hidden,
+ userOriginated));
+ }
+
/**
* Adds a new column to this {@link Grid} with given header caption, typed
* renderer and value provider.
return () -> removeListener(ItemClick.class, listener);
}
+ /**
+ * Registers a new column visibility change listener
+ *
+ * @param listener
+ * the listener to register, not null
+ * @return a registration for the listener
+ */
+ public Registration addColumnVisibilityChangeListener(
+ ColumnVisibilityChangeListener listener) {
+ Objects.requireNonNull(listener, "listener cannot be null");
+ addListener(ColumnVisibilityChangeEvent.class, listener,
+ COLUMN_VISIBILITY_METHOD);
+ return () -> removeListener(ColumnVisibilityChangeEvent.class, listener,
+ COLUMN_VISIBILITY_METHOD);
+ }
+
@Override
protected GridState getState() {
return getState(true);
public String id;
public boolean sortable;
+ /** The caption for the column hiding toggle. */
+ public String hidingToggleCaption;
+
+ /** Whether this column is currently hidden. */
+ public boolean hidden = false;
+
+ /** Whether the column can be hidden by the user. */
+ public boolean hidable = false;
+
public Connector renderer;
}
* the id of the column
* @param hidden
* <code>true</code> if hidden, <code>false</code> if unhidden
- * @param userOriginated
- * <code>true</code> if triggered by user, <code>false</code> if
- * by code
*/
- void columnVisibilityChanged(String id, boolean hidden,
- boolean userOriginated);
+ void columnVisibilityChanged(String id, boolean hidden);
/**
* Informs the server that a column has been resized by the user.
--- /dev/null
+package com.vaadin.tests.components.grid;
+
+import java.util.Arrays;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.renderers.NumberRenderer;
+import com.vaadin.v7.ui.Label;
+
+public class GridColumnHiding extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ Grid<Person> grid = new Grid<>();
+ Column<Person, String> nameColumn = grid
+ .addColumn("Name", Person::getFirstName).setHidable(true);
+ Column<Person, Number> ageColumn = grid
+ .addColumn("Age", Person::getAge, new NumberRenderer())
+ .setHidable(true)
+ .setHidingToggleCaption("custom age column caption");
+ Column<Person, String> emailColumn = grid.addColumn("Email",
+ Person::getEmail);
+
+ Button toggleNameColumn = new Button("server side toggle name column");
+ Button toggleAgeColumn = new Button("server side toggle age column");
+ Button toggleEmailColumn = new Button(
+ "server side toggle email column");
+
+ toggleNameColumn.addClickListener(
+ event -> nameColumn.setHidden(!nameColumn.isHidden()));
+ toggleAgeColumn.addClickListener(
+ event -> ageColumn.setHidden(!ageColumn.isHidden()));
+ toggleEmailColumn.addClickListener(
+ event -> emailColumn.setHidden(!emailColumn.isHidden()));
+
+ Label visibilityChangeLabel = new Label("visibility change label");
+ grid.addColumnVisibilityChangeListener(event -> visibilityChangeLabel
+ .setValue(event.getColumn().isHidden() + ""));
+
+ grid.setItems(Arrays.asList(Person.createTestPerson1(),
+ Person.createTestPerson2()));
+
+ addComponents(grid, toggleNameColumn, toggleAgeColumn,
+ toggleEmailColumn, visibilityChangeLabel);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2000-2016 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.customelements.GridElement;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.LabelElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class GridColumnHidingTest extends MultiBrowserTest {
+
+ @Test
+ public void serverHideColumns() {
+ openTestURL();
+ GridElement grid = $(GridElement.class).first();
+ ButtonElement toggleNameColumn = $(ButtonElement.class).get(0);
+ ButtonElement toggleAgeColumn = $(ButtonElement.class).get(1);
+ ButtonElement toggleEmailColumn = $(ButtonElement.class).get(2);
+
+ Assert.assertEquals("Foo", grid.getCell(0, 0).getText());
+ Assert.assertEquals("Maya", grid.getCell(1, 0).getText());
+ Assert.assertEquals("46", grid.getCell(0, 1).getText());
+ Assert.assertEquals("yeah@cool.com", grid.getCell(0, 2).getText());
+
+ toggleAgeColumn.click();
+ Assert.assertEquals("Foo", grid.getCell(0, 0).getText());
+ Assert.assertEquals("Maya", grid.getCell(1, 0).getText());
+ Assert.assertEquals("yeah@cool.com", grid.getCell(0, 1).getText());
+
+ toggleNameColumn.click();
+ Assert.assertEquals("yeah@cool.com", grid.getCell(0, 0).getText());
+
+ toggleEmailColumn.click();
+ Assert.assertFalse(isElementPresent(By.className("v-grid-cell")));
+
+ toggleAgeColumn.click();
+ toggleNameColumn.click();
+ toggleEmailColumn.click();
+ Assert.assertEquals("Foo", grid.getCell(0, 0).getText());
+ Assert.assertEquals("46", grid.getCell(0, 1).getText());
+ Assert.assertEquals("yeah@cool.com", grid.getCell(0, 2).getText());
+ }
+
+ @Test
+ public void clientHideColumns() {
+ openTestURL();
+ GridElement grid = $(GridElement.class).first();
+
+ getSidebarOpenButton(grid).click();
+ getColumnHidingToggle(grid, "custom age column caption").click();
+ Assert.assertEquals("Foo", grid.getCell(0, 0).getText());
+ Assert.assertEquals("Maya", grid.getCell(1, 0).getText());
+ Assert.assertEquals("yeah@cool.com", grid.getCell(0, 1).getText());
+ Assert.assertEquals("maya@foo.bar", grid.getCell(1, 1).getText());
+
+ getColumnHidingToggle(grid, "Name").click();
+ Assert.assertEquals("yeah@cool.com", grid.getCell(0, 0).getText());
+
+ getColumnHidingToggle(grid, "custom age column caption").click();
+ Assert.assertEquals("46", grid.getCell(0, 0).getText());
+ Assert.assertEquals("18", grid.getCell(1, 0).getText());
+ Assert.assertEquals("yeah@cool.com", grid.getCell(0, 1).getText());
+ Assert.assertEquals("maya@foo.bar", grid.getCell(1, 1).getText());
+ }
+
+ @Test
+ public void columnVisibilityChangeListener() {
+ openTestURL();
+ GridElement grid = $(GridElement.class).first();
+ LabelElement isHiddenLabel = $(LabelElement.class).get(1);
+ ButtonElement toggleNameColumn = $(ButtonElement.class).get(0);
+ ButtonElement toggleAgeColumn = $(ButtonElement.class).get(1);
+
+ Assert.assertEquals("visibility change label", isHiddenLabel.getText());
+ toggleNameColumn.click();
+ Assert.assertEquals("true", isHiddenLabel.getText());
+ toggleAgeColumn.click();
+ Assert.assertEquals("true", isHiddenLabel.getText());
+ toggleAgeColumn.click();
+ Assert.assertEquals("false", isHiddenLabel.getText());
+
+ getSidebarOpenButton(grid).click();
+ getColumnHidingToggle(grid, "Name").click();
+ Assert.assertEquals("false", isHiddenLabel.getText());
+ getColumnHidingToggle(grid, "custom age column caption").click();
+ Assert.assertEquals("true", isHiddenLabel.getText());
+ getSidebarOpenButton(grid).click();
+ }
+
+ @Test
+ public void columnTogglesVisibility() {
+ openTestURL();
+ GridElement grid = $(GridElement.class).first();
+ getSidebarOpenButton(grid).click();
+ List<WebElement> elements = getColumnHidingToggles(grid);
+ Assert.assertEquals(2, elements.size());
+ Assert.assertTrue("Name".equals(elements.get(0).getText()));
+ Assert.assertTrue(
+ "custom age column caption".equals(elements.get(1).getText()));
+ }
+
+ protected WebElement getSidebarOpenButton(GridElement grid) {
+ List<WebElement> elements = grid
+ .findElements(By.className("v-grid-sidebar-button"));
+ return elements.isEmpty() ? null : elements.get(0);
+ }
+
+ protected List<WebElement> getColumnHidingToggles(GridElement grid) {
+ WebElement sidebar = getSidebar(grid);
+ return sidebar.findElements(By.className("column-hiding-toggle"));
+ }
+
+ protected WebElement getColumnHidingToggle(GridElement grid,
+ String caption) {
+ List<WebElement> elements = getColumnHidingToggles(grid);
+ for (WebElement e : elements) {
+ if (caption.equalsIgnoreCase(e.getText())) {
+ return e;
+ }
+ }
+ return null;
+ }
+
+ protected WebElement getSidebar(GridElement grid) {
+ List<WebElement> elements = findElements(
+ By.className("v-grid-sidebar-popup"));
+ return elements.isEmpty() ? null : elements.get(0);
+ }
+}