From 2be1e43d7081f0bc2c5f905d6b007fe597934ae3 Mon Sep 17 00:00:00 2001 From: Henrik Paul Date: Wed, 18 Mar 2015 10:05:47 +0200 Subject: [PATCH] Adds server side column hiding API to Grid (#17023) Change-Id: Ic00e873176f499dfc45976439e09d712932775da --- .../client/connectors/GridConnector.java | 4 + server/src/com/vaadin/ui/Grid.java | 159 ++++++++++++++++++ .../shared/ui/grid/GridColumnState.java | 6 + .../grid/basicfeatures/GridBasicFeatures.java | 43 ++++- .../server/GridColumnVisibilityTest.java | 89 ++++++++++ 5 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java index 495bcd0411..d3045ee13b 100644 --- a/client/src/com/vaadin/client/connectors/GridConnector.java +++ b/client/src/com/vaadin/client/connectors/GridConnector.java @@ -824,6 +824,10 @@ public class GridConnector extends AbstractHasComponentsConnector implements column.setExpandRatio(state.expandRatio); column.setSortable(state.sortable); + + column.setHidden(state.hidden); + column.setHideable(state.hidable); + column.setEditable(state.editable); column.setEditorConnector((AbstractFieldConnector) state.editorConnector); } diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java index 12722b2596..31a25d8f8f 100644 --- a/server/src/com/vaadin/ui/Grid.java +++ b/server/src/com/vaadin/ui/Grid.java @@ -166,6 +166,67 @@ import elemental.json.JsonValue; public class Grid extends AbstractComponent implements SelectionNotifier, SortNotifier, SelectiveRenderer, ItemClickNotifier { + /** + * An event listener for column visibility change events in the Grid. + * + * @since + */ + 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 becomes hidden or unhidden. + * + * @since + */ + public static class ColumnVisibilityChangeEvent extends Component.Event { + + private final Column column; + private final boolean userOriginated; + + /** + * Constructor for a column visibility change event. + * + * @param column + * the column that changed its visibility + * @param isUserOriginated + * true iff the event was triggered by an UI + * interaction + */ + public ColumnVisibilityChangeEvent(Component source, Column column, + boolean isUserOriginated) { + super(source); + this.column = column; + userOriginated = isUserOriginated; + } + + /** + * Gets the column that became hidden or unhidden. + * + * @return the column that became hidden or unhidden. + * @see Column#isHidden() + */ + public Column getColumn() { + return column; + } + + /** + * Returns true if the column reorder was done by the user, + * false if not and it was triggered by server side code. + * + * @return true if event is a result of user interaction + */ + public boolean isUserOriginated() { + return userOriginated; + } + } + /** * Custom field group that allows finding property types before an item has * been bound. @@ -2715,6 +2776,66 @@ public class Grid extends AbstractComponent implements SelectionNotifier, public Field getEditorField() { return grid.getEditorField(getPropertyId()); } + + /** + * Hides or shows the column. By default columns are visible before + * explicitly hiding them. + * + * @since + * @param hidden + * true to hide the column, false + * to show + */ + public void setHidden(boolean hidden) { + if (hidden != getState().hidden) { + getState().hidden = hidden; + grid.markAsDirty(); + grid.fireColumnVisibilityChangeEvent(this, false); + } + } + + /** + * Is this column hidden. Default is {@code false}. + * + * @since + * @return true if the column is currently hidden, + * false otherwise + */ + public boolean isHidden() { + return getState().hidden; + } + + /** + * Set whether it is possible for the user to hide this column or not. + * Default is {@code false}. + *

+ * Note: it is still possible to hide the column + * programmatically using {@link #setHidden(boolean)} + * + * @since + * @param hidable + * true iff the column may be hidable by the + * user via UI interaction + */ + public void setHidable(boolean hidable) { + getState().hidable = hidable; + grid.markAsDirty(); + } + + /** + * Is it possible for the the user to hide this column. Default is + * {@code false}. + *

+ * Note: the column can be programmatically hidden using + * {@link #setHidden(boolean)} regardless of the returned value. + * + * @since + * @return true if the user can hide the column, + * false if not + */ + public boolean isHidable() { + return getState().hidable; + } } /** @@ -2952,6 +3073,11 @@ public class Grid extends AbstractComponent implements SelectionNotifier, .findMethod(ColumnReorderListener.class, "columnReorder", ColumnReorderEvent.class); + private static final Method COLUMN_VISIBILITY_METHOD = ReflectTools + .findMethod(ColumnVisibilityChangeListener.class, + "columnVisibilityChanged", + ColumnVisibilityChangeEvent.class); + /** * Creates a new Grid with a new {@link IndexedContainer} as the data * source. @@ -5242,4 +5368,37 @@ public class Grid extends AbstractComponent implements SelectionNotifier, public void recalculateColumnWidths() { getRpcProxy(GridClientRpc.class).recalculateColumnWidths(); } + + /** + * Registers a new column visibility change listener + * + * @since + * @param listener + * the listener to register + */ + public void addColumnVisibilityChangeListener( + ColumnVisibilityChangeListener listener) { + addListener(ColumnVisibilityChangeEvent.class, listener, + COLUMN_VISIBILITY_METHOD); + } + + /** + * Removes a previously registered column visibility change listener + * + * @since + * @param listener + * the listener to remove + */ + public void removeColumnVisibilityChangeListener( + ColumnVisibilityChangeListener listener) { + removeListener(ColumnVisibilityChangeEvent.class, listener, + COLUMN_VISIBILITY_METHOD); + } + + private void fireColumnVisibilityChangeEvent(Column column, + boolean isUserOriginated) { + fireEvent(new ColumnVisibilityChangeEvent(this, column, + isUserOriginated)); + } + } diff --git a/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java b/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java index 4c5b2c3a02..b966c53352 100644 --- a/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java +++ b/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java @@ -76,4 +76,10 @@ public class GridColumnState implements Serializable { * minWidth is less than the calculated width, minWidth will win. */ public double minWidth = GridConstants.DEFAULT_MIN_WIDTH; + + /** Is the column currently hidden. */ + public boolean hidden = false; + + /** Can the column be hidden by the UI. */ + public boolean hidable = false; } 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 e9f6bfdbb9..aeeaa25ac3 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -52,6 +52,8 @@ import com.vaadin.ui.Grid.CellStyleGenerator; import com.vaadin.ui.Grid.Column; import com.vaadin.ui.Grid.ColumnReorderEvent; import com.vaadin.ui.Grid.ColumnReorderListener; +import com.vaadin.ui.Grid.ColumnVisibilityChangeEvent; +import com.vaadin.ui.Grid.ColumnVisibilityChangeListener; import com.vaadin.ui.Grid.FooterCell; import com.vaadin.ui.Grid.HeaderCell; import com.vaadin.ui.Grid.HeaderRow; @@ -120,6 +122,16 @@ public class GridBasicFeatures extends AbstractComponentTest { } }; + private ColumnVisibilityChangeListener columnVisibilityListener = new ColumnVisibilityChangeListener() { + @Override + public void columnVisibilityChanged(ColumnVisibilityChangeEvent event) { + log("Visibility changed: "// + + "propertyId: " + event.getColumn().getPropertyId() // + + ", isHidden: " + event.getColumn().isHidden() // + + ", userOriginated: " + event.isUserOriginated()); + } + }; + @Override @SuppressWarnings("unchecked") protected Grid constructComponent() { @@ -532,6 +544,17 @@ public class GridBasicFeatures extends AbstractComponentTest { } } }); + createBooleanAction("ColumnVisibilityChangeListener", "State", false, + new Command() { + @Override + public void execute(Grid grid, Boolean value, Object data) { + if (value) { + grid.addColumnVisibilityChangeListener(columnVisibilityListener); + } else { + grid.removeColumnVisibilityChangeListener(columnVisibilityListener); + } + } + }); createBooleanAction("Single select allow deselect", "State", singleSelectAllowDeselect, new Command() { @@ -676,6 +699,7 @@ public class GridBasicFeatures extends AbstractComponentTest { }, null); } + @SuppressWarnings("boxing") protected void createColumnActions() { createCategory("Columns", null); @@ -736,6 +760,24 @@ public class GridBasicFeatures extends AbstractComponentTest { } }, c); + createBooleanAction("Hidable", getColumnProperty(c), false, + new Command() { + @Override + public void execute(Grid c, Boolean hidable, + Object propertyId) { + grid.getColumn(propertyId).setHidable(hidable); + } + }, getColumnProperty(c)); + + createBooleanAction("Hidden", getColumnProperty(c), false, + new Command() { + @Override + public void execute(Grid c, Boolean hidden, + Object propertyId) { + grid.getColumn(propertyId).setHidden(hidden); + } + }, getColumnProperty(c)); + createCategory("Column " + c + " Width", getColumnProperty(c)); createClickAction("Auto", "Column " + c + " Width", @@ -753,7 +795,6 @@ public class GridBasicFeatures extends AbstractComponentTest { createClickAction("25.5px", "Column " + c + " Width", new Command() { @Override - @SuppressWarnings("boxing") public void execute(Grid grid, Void value, Object columnIndex) { grid.getColumns().get((Integer) columnIndex) diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java new file mode 100644 index 0000000000..8fb733dfa0 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java @@ -0,0 +1,89 @@ +/* + * 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 org.junit.Before; +import org.junit.Test; + +import com.vaadin.testbench.annotations.RunLocally; +import com.vaadin.testbench.parallel.Browser; +import com.vaadin.testbench.parallel.TestCategory; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +@TestCategory("grid") +@RunLocally(Browser.PHANTOMJS) +public class GridColumnVisibilityTest extends GridBasicFeaturesTest { + + private static final String[] TOGGLE_LISTENER = new String[] { "Component", + "State", "ColumnVisibilityChangeListener" }; + private static final String[] TOGGLE_HIDE_COLUMN_0 = new String[] { + "Component", "Columns", "Column 0", "Hidden" }; + + private static final String COLUMN_0_BECAME_HIDDEN_MSG = "Visibility " + + "changed: propertyId: Column 0, isHidden: true"; + private static final String COLUMN_0_BECAME_UNHIDDEN_MSG = "Visibility " + + "changed: propertyId: Column 0, isHidden: false"; + + @Before + public void setUp() { + openTestURL(); + } + + @Test + public void columnIsNotShownWhenHidden() { + assertEquals("column 0", getGridElement().getHeaderCell(0, 0).getText() + .toLowerCase()); + + selectMenuPath(TOGGLE_HIDE_COLUMN_0); + assertEquals("column 1", getGridElement().getHeaderCell(0, 0).getText() + .toLowerCase()); + } + + @Test + public void columnIsShownWhenUnhidden() { + selectMenuPath(TOGGLE_HIDE_COLUMN_0); + selectMenuPath(TOGGLE_HIDE_COLUMN_0); + assertEquals("column 0", getGridElement().getHeaderCell(0, 0).getText() + .toLowerCase()); + } + + @Test + public void registeringListener() { + assertFalse(logContainsText(COLUMN_0_BECAME_HIDDEN_MSG)); + selectMenuPath(TOGGLE_LISTENER); + assertFalse(logContainsText(COLUMN_0_BECAME_HIDDEN_MSG)); + + selectMenuPath(TOGGLE_HIDE_COLUMN_0); + assertTrue(logContainsText(COLUMN_0_BECAME_HIDDEN_MSG)); + + selectMenuPath(TOGGLE_HIDE_COLUMN_0); + assertTrue(logContainsText(COLUMN_0_BECAME_UNHIDDEN_MSG)); + } + + @Test + public void deregisteringListener() { + selectMenuPath(TOGGLE_LISTENER); + selectMenuPath(TOGGLE_HIDE_COLUMN_0); + + selectMenuPath(TOGGLE_LISTENER); + selectMenuPath(TOGGLE_HIDE_COLUMN_0); + assertFalse(logContainsText(COLUMN_0_BECAME_UNHIDDEN_MSG)); + } +} -- 2.39.5