diff options
author | Johannes Dahlström <johannesd@vaadin.com> | 2015-10-05 17:46:28 +0300 |
---|---|---|
committer | Markus Koivisto <markus@vaadin.com> | 2015-10-09 12:33:21 +0000 |
commit | 2732b77278001c11fd5059fb89f19587302cb033 (patch) | |
tree | 2ecb166c2b0cbd1391f0f1bcd31cc58cdbec0a46 | |
parent | 9ee97bbf72551ba650e7ea910dddaae64f6c7ef0 (diff) | |
download | vaadin-framework-2732b77278001c11fd5059fb89f19587302cb033.tar.gz vaadin-framework-2732b77278001c11fd5059fb89f19587302cb033.zip |
Add Grid column resize event API (#16838)
Change-Id: I1cdecb54b3df45b16ddf2c7b06261198be086274
9 files changed, 421 insertions, 28 deletions
diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java index 60a9aacb88..0a6ba1642e 100644 --- a/client/src/com/vaadin/client/connectors/GridConnector.java +++ b/client/src/com/vaadin/client/connectors/GridConnector.java @@ -62,6 +62,8 @@ import com.vaadin.client.widget.grid.events.BodyClickHandler; import com.vaadin.client.widget.grid.events.BodyDoubleClickHandler; import com.vaadin.client.widget.grid.events.ColumnReorderEvent; import com.vaadin.client.widget.grid.events.ColumnReorderHandler; +import com.vaadin.client.widget.grid.events.ColumnResizeEvent; +import com.vaadin.client.widget.grid.events.ColumnResizeHandler; import com.vaadin.client.widget.grid.events.ColumnVisibilityChangeEvent; import com.vaadin.client.widget.grid.events.ColumnVisibilityChangeHandler; import com.vaadin.client.widget.grid.events.GridClickEvent; @@ -193,14 +195,6 @@ public class GridConnector extends AbstractHasComponentsConnector implements return null; } - @Override - protected void setWidth(double pixels, boolean userOriginated) { - super.setWidth(pixels, userOriginated); - if (userOriginated) { - getRpcProxy(GridServerRpc.class).columnResized(id, pixels); - } - } - private AbstractFieldConnector getEditorConnector() { return editorConnector; } @@ -479,6 +473,21 @@ public class GridConnector extends AbstractHasComponentsConnector implements } }; + private ColumnResizeHandler<JsonObject> columnResizeHandler = new ColumnResizeHandler<JsonObject>() { + + @Override + public void onColumnResize(ColumnResizeEvent<JsonObject> event) { + if (!columnsUpdatedFromState) { + Column<?, JsonObject> column = event.getColumn(); + if (column instanceof CustomGridColumn) { + getRpcProxy(GridServerRpc.class).columnResized( + ((CustomGridColumn) column).id, + column.getWidthActual()); + } + } + } + }; + private class CustomDetailsGenerator implements DetailsGenerator { private final Map<String, ComponentConnector> idToDetailsMap = new HashMap<String, ComponentConnector>(); @@ -750,6 +759,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements getWidget().addColumnReorderHandler(columnReorderHandler); getWidget().addColumnVisibilityChangeHandler( columnVisibilityChangeHandler); + getWidget().addColumnResizeHandler(columnResizeHandler); ConnectorFocusAndBlurHandler.addHandlers(this); diff --git a/client/src/com/vaadin/client/widget/grid/events/ColumnResizeEvent.java b/client/src/com/vaadin/client/widget/grid/events/ColumnResizeEvent.java new file mode 100644 index 0000000000..bb61ec021d --- /dev/null +++ b/client/src/com/vaadin/client/widget/grid/events/ColumnResizeEvent.java @@ -0,0 +1,67 @@ +/* + * 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.widget.grid.events; + +import com.google.gwt.event.shared.GwtEvent; +import com.vaadin.client.widgets.Grid.Column; + +/** + * An event for notifying that the columns in the Grid have been resized. + * + * @param <T> + * The row type of the grid. The row type is the POJO type from where + * the data is retrieved into the column cells. + * @since + * @author Vaadin Ltd + */ +public class ColumnResizeEvent<T> extends GwtEvent<ColumnResizeHandler<T>> { + + /** + * Handler type. + */ + private final static Type<ColumnResizeHandler<?>> TYPE = new Type<ColumnResizeHandler<?>>(); + + private Column<?, T> column; + + /** + * @param column + */ + public ColumnResizeEvent(Column<?, T> column) { + this.column = column; + } + + public static final Type<ColumnResizeHandler<?>> getType() { + return TYPE; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public Type<ColumnResizeHandler<T>> getAssociatedType() { + return (Type) TYPE; + } + + @Override + protected void dispatch(ColumnResizeHandler<T> handler) { + handler.onColumnResize(this); + } + + /** + * @return the column + */ + public Column<?, T> getColumn() { + return column; + } +} diff --git a/client/src/com/vaadin/client/widget/grid/events/ColumnResizeHandler.java b/client/src/com/vaadin/client/widget/grid/events/ColumnResizeHandler.java new file mode 100644 index 0000000000..a1bbef4dab --- /dev/null +++ b/client/src/com/vaadin/client/widget/grid/events/ColumnResizeHandler.java @@ -0,0 +1,40 @@ +/* + * 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.widget.grid.events; + +import com.google.gwt.event.shared.EventHandler; + +/** + * Handler for a Grid column resize event, called when the Grid's columns has + * been resized. + * + * @param <T> + * The row type of the grid. The row type is the POJO type from where + * the data is retrieved into the column cells. + * @since + * @author Vaadin Ltd + */ +public interface ColumnResizeHandler<T> extends EventHandler { + + /** + * A column resize event, fired by Grid when the columns of the Grid have + * been resized. + * + * @param event + * column resize event + */ + public void onColumnResize(ColumnResizeEvent<T> event); +} diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index db7b25720e..d31548eabd 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -124,6 +124,8 @@ import com.vaadin.client.widget.grid.events.BodyKeyPressHandler; import com.vaadin.client.widget.grid.events.BodyKeyUpHandler; import com.vaadin.client.widget.grid.events.ColumnReorderEvent; import com.vaadin.client.widget.grid.events.ColumnReorderHandler; +import com.vaadin.client.widget.grid.events.ColumnResizeEvent; +import com.vaadin.client.widget.grid.events.ColumnResizeHandler; import com.vaadin.client.widget.grid.events.ColumnVisibilityChangeEvent; import com.vaadin.client.widget.grid.events.ColumnVisibilityChangeHandler; import com.vaadin.client.widget.grid.events.FooterClickHandler; @@ -4761,17 +4763,13 @@ public class Grid<T> extends ResizeComposite implements * the width in pixels or negative for auto sizing */ public Column<C, T> setWidth(double pixels) { - setWidth(pixels, false); - return this; - } - - protected void setWidth(double pixels, boolean userOriginated) { if (!WidgetUtil.pixelValuesEqual(widthUser, pixels)) { widthUser = pixels; if (!isHidden()) { scheduleColumnWidthRecalculator(); } } + return this; } void doSetWidth(double pixels) { @@ -5578,7 +5576,7 @@ public class Grid<T> extends ResizeComposite implements @Override public void onUpdate(double deltaX, double deltaY) { - col.setWidth(initialWidth + deltaX, false); + col.setWidth(initialWidth + deltaX); } @Override @@ -5588,12 +5586,12 @@ public class Grid<T> extends ResizeComposite implements @Override public void onComplete() { - col.setWidth(col.getWidthActual(), true); + fireEvent(new ColumnResizeEvent<T>(col)); } @Override public void onCancel() { - col.setWidth(initialWidth, false); + col.setWidth(initialWidth); } }); dragger.addTo(td); @@ -7930,6 +7928,20 @@ public class Grid<T> extends ResizeComposite implements } /** + * Register a column resize handler to this Grid. The event for this handler + * is fired when the Grid's columns are resized. + * + * @since + * @param handler + * the handler for the event + * @return the registration for the event + */ + public HandlerRegistration addColumnResizeHandler( + ColumnResizeHandler<T> handler) { + return addHandler(handler, ColumnResizeEvent.getType()); + } + + /** * Apply sorting to data source. */ private void sort(boolean userOriginated) { diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java index c26e6d6705..4e0dadb47c 100644 --- a/server/src/com/vaadin/ui/Grid.java +++ b/server/src/com/vaadin/ui/Grid.java @@ -541,6 +541,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, * @since 7.5.0 */ public interface ColumnReorderListener extends Serializable { + /** * Called when the columns of the grid have been reordered. * @@ -557,9 +558,6 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, */ public static class ColumnReorderEvent extends Component.Event { - /** - * Is the column reorder related to this event initiated by the user - */ private final boolean userOriginated; /** @@ -588,6 +586,163 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, } /** + * An event listener for column resize events in the Grid. + * + * @since + */ + public interface ColumnResizeListener extends Serializable { + + /** + * Called when the columns of the grid have been resized. + * + * @param event + * An event providing more information + */ + void columnResize(ColumnResizeEvent event); + } + + /** + * An event that is fired when a column is resized, either programmatically + * or by the user. + * + * @since + */ + public static class ColumnResizeEvent extends Component.Event { + + private final Column column; + private final boolean userOriginated; + + /** + * + * @param source + * the grid where the event originated from + * @param userOriginated + * <code>true</code> if event is a result of user + * interaction, <code>false</code> if from API call + */ + public ColumnResizeEvent(Grid source, Column column, + boolean userOriginated) { + super(source); + this.column = column; + this.userOriginated = userOriginated; + } + + /** + * Returns the column that was resized. + * + * @return the resized column. + */ + public Column getColumn() { + return column; + } + + /** + * Returns <code>true</code> if the column resize 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; + } + + } + + /** + * Interface for an editor event listener + */ + public interface EditorListener extends Serializable { + + public static final Method EDITOR_OPEN_METHOD = ReflectTools + .findMethod(EditorListener.class, "editorOpened", + EditorOpenEvent.class); + public static final Method EDITOR_MOVE_METHOD = ReflectTools + .findMethod(EditorListener.class, "editorMoved", + EditorMoveEvent.class); + public static final Method EDITOR_CLOSE_METHOD = ReflectTools + .findMethod(EditorListener.class, "editorClosed", + EditorCloseEvent.class); + + /** + * Called when an editor is opened + * + * @param e + * an editor open event object + */ + public void editorOpened(EditorOpenEvent e); + + /** + * Called when an editor is reopened without closing it first + * + * @param e + * an editor move event object + */ + public void editorMoved(EditorMoveEvent e); + + /** + * Called when an editor is closed + * + * @param e + * an editor close event object + */ + public void editorClosed(EditorCloseEvent e); + + } + + /** + * Base class for editor related events + */ + public static abstract class EditorEvent extends Component.Event { + + private Object itemID; + + protected EditorEvent(Grid source, Object itemID) { + super(source); + this.itemID = itemID; + } + + /** + * Get the item (row) for which this editor was opened + */ + public Object getItem() { + return itemID; + } + + } + + /** + * This event gets fired when an editor is opened + */ + public static class EditorOpenEvent extends EditorEvent { + + public EditorOpenEvent(Grid source, Object itemID) { + super(source, itemID); + } + } + + /** + * This event gets fired when an editor is opened while another row is being + * edited (i.e. editor focus moves elsewhere) + */ + public static class EditorMoveEvent extends EditorEvent { + + public EditorMoveEvent(Grid source, Object itemID) { + super(source, itemID); + } + } + + /** + * This event gets fired when an editor is dismissed or closed by other + * means. + */ + public static class EditorCloseEvent extends EditorEvent { + + public EditorCloseEvent(Grid source, Object itemID) { + super(source, itemID); + } + } + + /** * Default error handler for the editor * */ @@ -2955,22 +3110,41 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, "Pixel width should be greated than 0 (in " + toString() + ")"); } - state.width = pixelWidth; - grid.markAsDirty(); + if (state.width != pixelWidth) { + state.width = pixelWidth; + grid.markAsDirty(); + grid.fireColumnResizeEvent(this, false); + } return this; } /** - * Marks the column width as undefined meaning that the grid is free to - * resize the column based on the cell contents and available space in - * the grid. + * Returns whether this column has an undefined width. + * + * @since + * @return whether the width is undefined + * @throws IllegalStateException + * if the column is no longer attached to any grid + */ + public boolean isWidthUndefined() { + checkColumnIsAttached(); + return state.width < 0; + } + + /** + * Marks the column width as undefined. An undefined width means the + * grid is free to resize the column based on the cell contents and + * available space in the grid. * * @return the column itself */ public Column setWidthUndefined() { checkColumnIsAttached(); - state.width = -1; - grid.markAsDirty(); + if (!isWidthUndefined()) { + state.width = -1; + grid.markAsDirty(); + grid.fireColumnResizeEvent(this, false); + } return this; } @@ -4086,6 +4260,10 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, .findMethod(ColumnReorderListener.class, "columnReorder", ColumnReorderEvent.class); + private static final Method COLUMN_RESIZE_METHOD = ReflectTools + .findMethod(ColumnResizeListener.class, "columnResize", + ColumnResizeEvent.class); + private static final Method COLUMN_VISIBILITY_METHOD = ReflectTools .findMethod(ColumnVisibilityChangeListener.class, "columnVisibilityChanged", @@ -4276,6 +4454,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, final Column column = getColumnByColumnId(id); if (column != null && column.isResizable()) { column.getState().width = pixels; + fireColumnResizeEvent(column, true); } } }); @@ -5374,6 +5553,30 @@ public class Grid extends AbstractFocusable implements SelectionNotifier, COLUMN_REORDER_METHOD); } + private void fireColumnResizeEvent(Column column, boolean userOriginated) { + fireEvent(new ColumnResizeEvent(this, column, userOriginated)); + } + + /** + * Registers a new column resize listener. + * + * @param listener + * the listener to register + */ + public void addColumnResizeListener(ColumnResizeListener listener) { + addListener(ColumnResizeEvent.class, listener, COLUMN_RESIZE_METHOD); + } + + /** + * Removes a previously registered column resize listener. + * + * @param listener + * the listener to remove + */ + public void removeColumnResizeListener(ColumnResizeListener listener) { + removeListener(ColumnResizeEvent.class, listener, COLUMN_RESIZE_METHOD); + } + /** * Gets the * {@link com.vaadin.data.RpcDataProviderExtension.DataProviderKeyMapper 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 2b960d26a0..da230e86c7 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 @@ -15,6 +15,9 @@ */ package com.vaadin.tests.server.component.grid; +import static org.easymock.EasyMock.and; +import static org.easymock.EasyMock.capture; +import static org.easymock.EasyMock.isA; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -29,6 +32,8 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; +import org.easymock.Capture; +import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; @@ -39,6 +44,8 @@ import com.vaadin.shared.ui.grid.GridState; import com.vaadin.shared.util.SharedUtil; import com.vaadin.ui.Grid; import com.vaadin.ui.Grid.Column; +import com.vaadin.ui.Grid.ColumnResizeEvent; +import com.vaadin.ui.Grid.ColumnResizeListener; import com.vaadin.ui.TextField; public class GridColumns { @@ -354,4 +361,34 @@ public class GridColumns { assertEquals("hidingToggleCaption", firstColumn.getHidingToggleCaption()); } + + @Test + public void testColumnSetWidthFiresResizeEvent() { + final Column firstColumn = grid.getColumns().get(0); + + // prepare a listener mock that captures the argument + ColumnResizeListener mock = EasyMock + .createMock(ColumnResizeListener.class); + Capture<ColumnResizeEvent> capturedEvent = new Capture<ColumnResizeEvent>(); + mock.columnResize(and(capture(capturedEvent), + isA(ColumnResizeEvent.class))); + EasyMock.expectLastCall().once(); + + // Tell it to wait for the call + EasyMock.replay(mock); + + // Cause a resize event + grid.addColumnResizeListener(mock); + firstColumn.setWidth(firstColumn.getWidth() + 10); + + // Verify the method was called + EasyMock.verify(mock); + + // Asserts on the captured event + ColumnResizeEvent event = capturedEvent.getValue(); + assertEquals("Event column was not first column.", firstColumn, + event.getColumn()); + assertFalse("Event should not be userOriginated", + event.isUserOriginated()); + } } 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 30cc8a2b13..a3160ba2c6 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -60,6 +60,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.ColumnResizeEvent; +import com.vaadin.ui.Grid.ColumnResizeListener; import com.vaadin.ui.Grid.ColumnVisibilityChangeEvent; import com.vaadin.ui.Grid.ColumnVisibilityChangeListener; import com.vaadin.ui.Grid.DetailsGenerator; @@ -354,8 +356,15 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> { grid.addSortListener(new SortListener() { @Override public void sort(SortEvent event) { + log("SortEvent: isUserOriginated? " + event.isUserOriginated()); + } + }); - log("SortOrderChangeEvent: isUserOriginated? " + grid.addColumnResizeListener(new ColumnResizeListener() { + + @Override + public void columnResize(ColumnResizeEvent event) { + log("ColumnResizeEvent : isUserOriginated? " + event.isUserOriginated()); } }); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnResizeTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnResizeTest.java index 827a132eb9..7c62571cb1 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnResizeTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnResizeTest.java @@ -16,10 +16,13 @@ package com.vaadin.tests.components.grid.basicfeatures.server; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; import org.openqa.selenium.By; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.interactions.Actions; import com.vaadin.testbench.elements.GridElement.GridCellElement; import com.vaadin.testbench.parallel.TestCategory; @@ -84,4 +87,16 @@ public class GridColumnResizeTest extends GridBasicFeaturesTest { cell.isElementPresent(By .cssSelector("div.v-grid-column-resize-handle"))); } + + @Test + public void testResizeFirstColumn() { + GridCellElement headerCell = getGridElement().getHeaderCell(0, 0); + Dimension size = headerCell.getSize(); + new Actions(getDriver()) + .moveToElement(headerCell, size.getWidth() - 1, + size.getHeight() / 2).clickAndHold() + .moveByOffset(-10, 0).release().perform(); + assertTrue("Log did not contain a resize event.", + logContainsText("ColumnResizeEvent : isUserOriginated? true")); + } } 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 cbd0857bd1..b471612798 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 @@ -379,7 +379,7 @@ public class GridSortingTest extends GridBasicFeaturesTest { // Find a message in the log List<WebElement> userOriginatedMessages = getDriver() .findElements( - By.xpath("//div[@id='Log']//*[contains(text(),'SortOrderChangeEvent: isUserOriginated')]")); + By.xpath("//div[@id='Log']//*[contains(text(),'SortEvent: isUserOriginated')]")); Collections.sort(userOriginatedMessages, new Comparator<WebElement>() { @Override |