summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrik Lindström <patrik@vaadin.com>2016-11-02 11:54:49 +0200
committerPekka Hyvönen <pekka@vaadin.com>2016-11-17 10:05:47 +0000
commit9a0b4e9827cdcdb4084fb6b61ab7cd8953ee94fb (patch)
tree4dd3d79b60919eca46eff6fa37de9bb23ce30e53
parent9696c66041d9852a97aa553485afcca354d684d3 (diff)
downloadvaadin-framework-9a0b4e9827cdcdb4084fb6b61ab7cd8953ee94fb.tar.gz
vaadin-framework-9a0b4e9827cdcdb4084fb6b61ab7cd8953ee94fb.zip
Add lazy/simple resize mode to Grid (#20108)
Change-Id: I47427efc28c350382dba8c1f50fd332a3f4585e4
-rw-r--r--client/src/main/java/com/vaadin/client/connectors/GridConnector.java5
-rw-r--r--client/src/main/java/com/vaadin/client/ui/dd/DragHandle.java57
-rw-r--r--client/src/main/java/com/vaadin/client/widgets/Grid.java199
-rw-r--r--server/src/main/java/com/vaadin/ui/Grid.java21
-rw-r--r--shared/src/main/java/com/vaadin/shared/ui/grid/ColumnResizeMode.java36
-rw-r--r--shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java5
-rw-r--r--themes/src/main/themes/VAADIN/themes/base/grid/grid.scss16
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java8
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/grid/basicfeatures/GridColumnResizeModeTest.java74
9 files changed, 359 insertions, 62 deletions
diff --git a/client/src/main/java/com/vaadin/client/connectors/GridConnector.java b/client/src/main/java/com/vaadin/client/connectors/GridConnector.java
index ddde546da9..e329d4a4c8 100644
--- a/client/src/main/java/com/vaadin/client/connectors/GridConnector.java
+++ b/client/src/main/java/com/vaadin/client/connectors/GridConnector.java
@@ -839,6 +839,11 @@ public class GridConnector extends AbstractHasComponentsConnector
}
}
+ // Column resize mode
+ if (stateChangeEvent.hasPropertyChanged("columnResizeMode")) {
+ getWidget().setColumnResizeMode(getState().columnResizeMode);
+ }
+
// Header and footer
if (stateChangeEvent.hasPropertyChanged("header")) {
updateHeaderFromState(getState().header);
diff --git a/client/src/main/java/com/vaadin/client/ui/dd/DragHandle.java b/client/src/main/java/com/vaadin/client/ui/dd/DragHandle.java
index a983337c22..5aec3b3fe9 100644
--- a/client/src/main/java/com/vaadin/client/ui/dd/DragHandle.java
+++ b/client/src/main/java/com/vaadin/client/ui/dd/DragHandle.java
@@ -44,7 +44,7 @@ public class DragHandle {
/**
* Called when dragging starts
*/
- public void onStart();
+ void onStart();
/**
* Called when the drag handle has moved.
@@ -54,18 +54,18 @@ public class DragHandle {
* @param deltaY
* change in Y direction since start
*/
- public void onUpdate(double deltaX, double deltaY);
+ void onUpdate(double deltaX, double deltaY);
/**
* Called when the drag operation has been cancelled (usually by
* pressing ESC)
*/
- public void onCancel();
+ void onCancel();
/**
* Called when the drag operation completes successfully
*/
- public void onComplete();
+ void onComplete();
}
@@ -87,6 +87,20 @@ public class DragHandle {
* later) both to provide the "-dragged" style and to make sure
* that the drag handle can be properly styled (it's otherwise
* invisible)
+ */
+ public DragHandle(String baseName) {
+ this(baseName,null);
+ }
+
+ /**
+ * Creates a new DragHandle.
+ *
+ * @param baseName
+ * CSS style name to use for this DragHandle element. This
+ * parameter is supplied to the constructor (rather than added
+ * later) both to provide the "-dragged" style and to make sure
+ * that the drag handle can be properly styled (it's otherwise
+ * invisible)
* @param callback
* Callback object allows hooking up the drag handle to the rest
* of the program logic
@@ -106,22 +120,28 @@ public class DragHandle {
@Override
public void onDrop() {
removeDraggingStyle();
- userCallback.onComplete();
+ if(userCallback != null) {
+ userCallback.onComplete();
+ }
}
@Override
public void onDragUpdate(Event e) {
- double dx = WidgetUtil.getTouchOrMouseClientX(e) - startX;
- double dy = WidgetUtil.getTouchOrMouseClientY(e) - startY;
- userCallback.onUpdate(dx, dy);
+ if(userCallback != null) {
+ double dx = WidgetUtil.getTouchOrMouseClientX(e) - startX;
+ double dy = WidgetUtil.getTouchOrMouseClientY(e) - startY;
+ userCallback.onUpdate(dx, dy);
+ }
}
@Override
public boolean onDragStart(Event e) {
addDraggingStyle();
- startX = WidgetUtil.getTouchOrMouseClientX(e);
- startY = WidgetUtil.getTouchOrMouseClientY(e);
- userCallback.onStart();
+ if(userCallback != null) {
+ startX = WidgetUtil.getTouchOrMouseClientX(e);
+ startY = WidgetUtil.getTouchOrMouseClientY(e);
+ userCallback.onStart();
+ }
return true;
}
@@ -133,7 +153,9 @@ public class DragHandle {
@Override
public void onDragCancel() {
removeDraggingStyle();
- userCallback.onCancel();
+ if(userCallback != null) {
+ userCallback.onCancel();
+ }
}
private void addDraggingStyle() {
@@ -157,6 +179,17 @@ public class DragHandle {
}
/**
+ * Sets the user-facing drag handle callback method. This allows
+ * code using the DragHandle to react to the situations where a
+ * drag handle first touched, when it's moved and when it's released.
+ *
+ * @param dragHandleCallback the callback object to use (can be null)
+ */
+ public void setCallback(DragHandleCallback dragHandleCallback) {
+ userCallback = dragHandleCallback;
+ }
+
+ /**
* Returns the current parent element for this drag handle. May be null.
*
* @return an Element or null
diff --git a/client/src/main/java/com/vaadin/client/widgets/Grid.java b/client/src/main/java/com/vaadin/client/widgets/Grid.java
index 2b193a55db..3290aa8a48 100644
--- a/client/src/main/java/com/vaadin/client/widgets/Grid.java
+++ b/client/src/main/java/com/vaadin/client/widgets/Grid.java
@@ -77,6 +77,7 @@ import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.ResizeComposite;
import com.google.gwt.user.client.ui.Widget;
+
import com.vaadin.client.BrowserInfo;
import com.vaadin.client.DeferredWorker;
import com.vaadin.client.Focusable;
@@ -176,6 +177,7 @@ import com.vaadin.client.widgets.Grid.Editor.State;
import com.vaadin.client.widgets.Grid.StaticSection.StaticCell;
import com.vaadin.client.widgets.Grid.StaticSection.StaticRow;
import com.vaadin.shared.data.sort.SortDirection;
+import com.vaadin.shared.ui.grid.ColumnResizeMode;
import com.vaadin.shared.ui.grid.GridConstants;
import com.vaadin.shared.ui.grid.GridConstants.Section;
import com.vaadin.shared.ui.grid.GridStaticCellType;
@@ -5711,63 +5713,142 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
&& staticRow instanceof HeaderRow
&& ((HeaderRow) staticRow).isDefault()) {
+ final DivElement resizeElement = Document.get().createDivElement();
+ resizeElement.addClassName(getStylePrimaryName() + "-column-resize-simple-indicator");
+
final int column = cell.getColumn();
- DragHandle dragger = new DragHandle(
- getStylePrimaryName() + "-column-resize-handle",
- new DragHandleCallback() {
-
- private Column<?, T> col = getVisibleColumn(
- column);
- private double initialWidth = 0;
- private double minCellWidth;
-
- @Override
- public void onUpdate(double deltaX,
- double deltaY) {
- col.setWidth(Math.max(minCellWidth,
- initialWidth + deltaX));
- }
+ final DragHandle dragger = new DragHandle(getStylePrimaryName() + "-column-resize-handle");
+ dragger.addTo(td);
- @Override
- public void onStart() {
- initialWidth = col.getWidthActual();
-
- minCellWidth = escalator.getMinCellWidth(
- getVisibleColumns().indexOf(col));
- for (Column<?, T> c : getVisibleColumns()) {
- if (selectionColumn == c) {
- // Don't modify selection column.
- continue;
- }
-
- if (c.getWidth() < 0) {
- c.setWidth(c.getWidthActual());
- fireEvent(new ColumnResizeEvent<T>(
- c));
- }
- }
+ // Common functionality for drag handle callback implementations
+ abstract class AbstractDHCallback implements DragHandleCallback {
+ protected Column<?, T> col = getVisibleColumn(column);
+ protected double initialWidth = 0;
+ protected double minCellWidth;
+ protected double width;
+
+ protected void dragStarted() {
+ initialWidth = col.getWidthActual();
+ width = initialWidth;
+
+ minCellWidth = escalator.getMinCellWidth(getVisibleColumns().indexOf(col));
+ for (Column<?, T> c : getVisibleColumns()) {
+ if (selectionColumn == c) {
+ // Don't modify selection column.
+ continue;
+ }
- WidgetUtil.setTextSelectionEnabled(
- getElement(), false);
+ if (c.getWidth() < 0) {
+ c.setWidth(c.getWidthActual());
+ fireEvent(new ColumnResizeEvent<T>(c));
}
+ }
- @Override
- public void onComplete() {
- fireEvent(new ColumnResizeEvent<T>(col));
+ WidgetUtil.setTextSelectionEnabled(getElement(), false);
+ }
- WidgetUtil.setTextSelectionEnabled(
- getElement(), true);
- }
+ protected void dragEnded() {
+ WidgetUtil.setTextSelectionEnabled(getElement(), true);
+ }
+ }
- @Override
- public void onCancel() {
- col.setWidth(initialWidth);
+ final DragHandleCallback simpleResizeMode = new AbstractDHCallback() {
+ protected void dragEnded() {
+ super.dragEnded();
+ dragger.getElement().removeChild(resizeElement);
+ }
- WidgetUtil.setTextSelectionEnabled(
- getElement(), true);
- }
- });
- dragger.addTo(td);
+ @Override
+ public void onStart() {
+ dragStarted();
+ dragger.getElement().appendChild(resizeElement);
+ resizeElement.getStyle().setLeft((dragger.getElement().getOffsetWidth() - resizeElement.getOffsetWidth()) * .5, Unit.PX);
+ resizeElement.getStyle().setHeight(col.grid.getOffsetHeight(), Unit.PX);
+ }
+
+ @Override
+ public void onUpdate(double deltaX, double deltaY) {
+ width = Math.max(minCellWidth, initialWidth + deltaX);
+ resizeElement.getStyle().setLeft((dragger.getElement().getOffsetWidth() - resizeElement.getOffsetWidth()) * .5 + (width - initialWidth), Unit.PX);
+ }
+
+ @Override
+ public void onCancel() {
+ dragEnded();
+ }
+
+ @Override
+ public void onComplete() {
+ dragEnded();
+
+ col.setWidth(width);
+ fireEvent(new ColumnResizeEvent<T>(col));
+ }
+ };
+
+ final DragHandleCallback animatedResizeMode = new AbstractDHCallback() {
+ @Override
+ public void onStart() {
+ dragStarted();
+ }
+
+ @Override
+ public void onUpdate(double deltaX, double deltaY) {
+ width = Math.max(minCellWidth, initialWidth + deltaX);
+ col.setWidth(width);
+ }
+
+ @Override
+ public void onCancel() {
+ dragEnded();
+ col.setWidth(initialWidth);
+ }
+
+ @Override
+ public void onComplete() {
+ dragEnded();
+ col.setWidth(width);
+ fireEvent(new ColumnResizeEvent<T>(col));
+ }
+ };
+
+ // DragHandle gets assigned a 'master callback' that delegates
+ // functionality to the correct case-specific implementation
+ dragger.setCallback(new DragHandleCallback() {
+
+ private DragHandleCallback currentCallback;
+
+ @Override
+ public void onStart() {
+ switch(getColumnResizeMode()) {
+ case SIMPLE:
+ currentCallback = simpleResizeMode;
+ break;
+ case ANIMATED:
+ currentCallback = animatedResizeMode;
+ break;
+ default:
+ throw new UnsupportedOperationException("Support for current column resize mode is not yet implemented");
+ }
+
+ currentCallback.onStart();
+ }
+
+ @Override
+ public void onUpdate(double deltaX, double deltaY) {
+ currentCallback.onUpdate(deltaX,deltaY);
+ }
+
+ @Override
+ public void onCancel() {
+ currentCallback.onCancel();
+ }
+
+ @Override
+ public void onComplete() {
+ currentCallback.onComplete();
+ }
+ });
}
cellFocusHandler.updateFocusedCellStyle(cell, container);
@@ -6023,6 +6104,26 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
fireEvent(new GridEnabledEvent(enabled));
}
+ private ColumnResizeMode columnResizeMode = ColumnResizeMode.ANIMATED;
+
+ /**
+ * Sets the column resize mode to use. The default mode is {@link ColumnResizeMode.ANIMATED}.
+ *
+ * @param mode a ColumnResizeMode value
+ */
+ public void setColumnResizeMode(ColumnResizeMode mode) {
+ columnResizeMode = mode;
+ }
+
+ /**
+ * Returns the current column resize mode. The default mode is {@link ColumnResizeMode.ANIMATED}.
+ *
+ * @return a ColumnResizeMode value
+ */
+ public ColumnResizeMode getColumnResizeMode() {
+ return columnResizeMode;
+ }
+
@Override
public void setStylePrimaryName(String style) {
super.setStylePrimaryName(style);
diff --git a/server/src/main/java/com/vaadin/ui/Grid.java b/server/src/main/java/com/vaadin/ui/Grid.java
index b8becd1c33..6bdcd1377b 100644
--- a/server/src/main/java/com/vaadin/ui/Grid.java
+++ b/server/src/main/java/com/vaadin/ui/Grid.java
@@ -85,6 +85,7 @@ import com.vaadin.server.communication.data.DataGenerator;
import com.vaadin.server.communication.data.RpcDataProviderExtension;
import com.vaadin.shared.MouseEventDetails;
import com.vaadin.shared.data.sort.SortDirection;
+import com.vaadin.shared.ui.grid.ColumnResizeMode;
import com.vaadin.shared.ui.grid.EditorClientRpc;
import com.vaadin.shared.ui.grid.EditorServerRpc;
import com.vaadin.shared.ui.grid.GridClientRpc;
@@ -4544,6 +4545,7 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
private Object editedItemId = null;
private boolean editorActive = false;
+
/**
* True while the editor is storing the field values, i.e. commiting the
* field group.
@@ -4789,7 +4791,6 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
if (column != null && column.isResizable()) {
column.getState().width = pixels;
fireColumnResizeEvent(column, true);
- markAsDirty();
}
}
});
@@ -5261,6 +5262,24 @@ public class Grid extends AbstractFocusable implements SelectionNotifier,
}
/**
+ * Sets the column resize mode to use. The default mode is {@link ColumnResizeMode#ANIMATED}.
+ *
+ * @param mode a ColumnResizeMode value
+ */
+ public void setColumnResizeMode(ColumnResizeMode mode) {
+ getState().columnResizeMode = mode;
+ }
+
+ /**
+ * Returns the current column resize mode. The default mode is {@link ColumnResizeMode#ANIMATED}.
+ *
+ * @return a ColumnResizeMode value
+ */
+ public ColumnResizeMode getColumnResizeMode() {
+ return getState(false).columnResizeMode;
+ }
+
+ /**
* Creates a new column based on a property id and appends it as the last
* column.
*
diff --git a/shared/src/main/java/com/vaadin/shared/ui/grid/ColumnResizeMode.java b/shared/src/main/java/com/vaadin/shared/ui/grid/ColumnResizeMode.java
new file mode 100644
index 0000000000..a19a2bb9eb
--- /dev/null
+++ b/shared/src/main/java/com/vaadin/shared/ui/grid/ColumnResizeMode.java
@@ -0,0 +1,36 @@
+/*
+ * 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.shared.ui.grid;
+
+/**
+ * Collection of modes used for resizing columns in the Grid.
+ */
+public enum ColumnResizeMode {
+
+ /**
+ * When column resize mode is set to Animated, columns
+ * are resized as they are dragged.
+ */
+ ANIMATED,
+
+ /**
+ * When column resize mode is set to Simple, dragging to resize
+ * a column will show a marker, and the column will resize only
+ * after the mouse button or touch is released.
+ */
+ SIMPLE
+
+}
diff --git a/shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java b/shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java
index f20f519439..7786b7e0f3 100644
--- a/shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java
+++ b/shared/src/main/java/com/vaadin/shared/ui/grid/GridState.java
@@ -142,6 +142,11 @@ public class GridState extends TabIndexState {
}
/**
+ * Column resize mode in grid.
+ */
+ public ColumnResizeMode columnResizeMode = ColumnResizeMode.ANIMATED;
+
+ /**
* Columns in grid.
*/
public List<GridColumnState> columns = new ArrayList<GridColumnState>();
diff --git a/themes/src/main/themes/VAADIN/themes/base/grid/grid.scss b/themes/src/main/themes/VAADIN/themes/base/grid/grid.scss
index 983463381b..1a55cc2595 100644
--- a/themes/src/main/themes/VAADIN/themes/base/grid/grid.scss
+++ b/themes/src/main/themes/VAADIN/themes/base/grid/grid.scss
@@ -283,6 +283,22 @@ $v-grid-details-border-bottom-stripe: 1px solid darken($v-grid-row-background-co
user-select: none;
}
+ .#{$primaryStyleName}-column-resize-simple-indicator {
+ position: absolute;
+ width: 3px;
+ top: 0px;
+ left: $v-grid-cell-padding-horizontal;
+ z-index: 9001;
+ background: #fff;
+ box-shadow: 0px 0px 5px #000;
+
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ }
+
// Footer
.#{$primaryStyleName}-footer {
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
index 18cfb56660..e3fdd68ed6 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
@@ -44,6 +44,7 @@ import com.vaadin.event.SelectionEvent.SelectionListener;
import com.vaadin.event.SortEvent;
import com.vaadin.event.SortEvent.SortListener;
import com.vaadin.shared.data.sort.SortDirection;
+import com.vaadin.shared.ui.grid.ColumnResizeMode;
import com.vaadin.shared.ui.grid.GridStaticCellType;
import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.tests.components.AbstractComponentTest;
@@ -1266,6 +1267,13 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
grid.getColumns().get(0).setMaximumWidth(30);
}
}, null);
+
+ createBooleanAction("Simple resize mode", "Columns", false, new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid g, Boolean value, Object data) {
+ g.setColumnResizeMode(value ? ColumnResizeMode.SIMPLE : ColumnResizeMode.ANIMATED);
+ }
+ });
}
private static String getColumnProperty(int c) {
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/basicfeatures/GridColumnResizeModeTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/basicfeatures/GridColumnResizeModeTest.java
new file mode 100644
index 0000000000..8e767eb033
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/tests/components/grid/basicfeatures/GridColumnResizeModeTest.java
@@ -0,0 +1,74 @@
+package com.vaadin.tests.components.grid.basicfeatures;/*
+ * 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.
+ */
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.parallel.TestCategory;
+import com.vaadin.tests.components.grid.basicfeatures.element.CustomGridElement;
+
+@TestCategory("grid")
+public class GridColumnResizeModeTest extends GridBasicFeaturesTest {
+
+ @Before
+ public void before() {
+ openTestURL();
+ }
+
+ @Test
+ public void testSimpleResizeModeToggle() throws Exception {
+
+ CustomGridElement grid = getGridElement();
+
+ List<WebElement> handles = grid.findElements(By.className("v-grid-column-resize-handle"));
+ WebElement handle = handles.get(1);
+
+ Actions drag1 = new Actions(getDriver()).moveToElement(handle).clickAndHold();
+ Actions drag2 = new Actions(getDriver()).moveByOffset(-50, 0);
+ Actions drag3 = new Actions(getDriver()).moveByOffset(100, 0);
+ Actions dragEndAction = new Actions(getDriver()).release().moveToElement(grid);
+
+ selectMenuPath("Component", "Columns", "Simple resize mode");
+ sleep(250);
+
+ drag1.perform();
+ sleep(500);
+ drag2.perform();
+ sleep(500);
+ drag3.perform();
+ sleep(500);
+
+ // Make sure we find at least one simple resize mode splitter
+ assertElementPresent(By.className("v-grid-column-resize-simple-indicator"));
+
+ dragEndAction.perform();
+
+ // Make sure it went away
+ assertElementNotPresent(By.className("v-grid-column-resize-simple-indicator"));
+
+ // See that we got a resize event
+ sleep(500);
+ Assert.assertEquals("Log shows resize event", getLogRow(0), "3. ColumnResizeEvent: isUserOriginated? true");
+
+ }
+
+}