diff options
author | Adam Wagner <wbadam@users.noreply.github.com> | 2017-02-28 09:41:04 +0200 |
---|---|---|
committer | Henri Sara <henri.sara@gmail.com> | 2017-04-12 14:58:11 +0300 |
commit | c4f8524ea881e6a946ac9e9e1911fd2873f484e9 (patch) | |
tree | 05a175054cd7e3728b8ce6d80a2d6954a6494cc8 /client | |
parent | 8b94b1aeca0e8d7cdd2d13d2f9ba32264b310ac2 (diff) | |
download | vaadin-framework-c4f8524ea881e6a946ac9e9e1911fd2873f484e9.tar.gz vaadin-framework-c4f8524ea881e6a946ac9e9e1911fd2873f484e9.zip |
Make Grid rows draggable (#8690)
It is possible to customize the drag data for each row. (#8706)
Fixes #8396
Diffstat (limited to 'client')
4 files changed, 200 insertions, 12 deletions
diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceExtensionConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceExtensionConnector.java new file mode 100644 index 0000000000..f402f2396d --- /dev/null +++ b/client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceExtensionConnector.java @@ -0,0 +1,119 @@ +/* + * 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.client.connectors.grid; + +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.dom.client.TableRowElement; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.extensions.DragSourceExtensionConnector; +import com.vaadin.client.widget.escalator.RowContainer; +import com.vaadin.client.widgets.Escalator; +import com.vaadin.shared.Range; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.grid.GridDragSourceExtensionState; +import com.vaadin.ui.GridDragSourceExtension; + +import elemental.events.Event; +import elemental.json.JsonObject; + +/** + * Adds HTML5 drag and drop functionality to a {@link com.vaadin.client.widgets.Grid + * Grid}'s rows. This is the client side counterpart of {@link + * GridDragSourceExtension}. + * + * @author Vaadin Ltd + * @since + */ +@Connect(GridDragSourceExtension.class) +public class GridDragSourceExtensionConnector extends + DragSourceExtensionConnector { + + private GridConnector gridConnector; + + @Override + protected void extend(ServerConnector target) { + this.gridConnector = (GridConnector) target; + + // Set newly added rows draggable + getGridBody().setNewEscalatorRowCallback( + rows -> rows.forEach(this::setDraggable)); + + // Add drag listeners to body element + addDragListeners(getGridBody().getElement()); + } + + @Override + protected void onDragStart(Event event) { + super.onDragStart(event); + + if (event.getTarget() instanceof TableRowElement) { + TableRowElement row = (TableRowElement) event.getTarget(); + int rowIndex = ((Escalator.AbstractRowContainer) getGridBody()) + .getLogicalRowIndex(row); + + JsonObject rowData = gridConnector.getDataSource().getRow(rowIndex); + + // Set drag data in DataTransfer object + ((NativeEvent) event).getDataTransfer() + .setData(GridDragSourceExtensionState.DATA_TYPE_DRAG_DATA, + getDragData(rowData).toJson()); + } + } + + /** + * Gets drag data from the row data if exists or returns complete row data + * otherwise. + * + * @param row + * Row data. + * @return Drag data if present or row data otherwise. + */ + private JsonObject getDragData(JsonObject row) { + return row.hasKey(GridDragSourceExtensionState.JSONKEY_DRAG_DATA) + ? row.getObject(GridDragSourceExtensionState.JSONKEY_DRAG_DATA) + : row; + } + + @Override + public void onUnregister() { + super.onUnregister(); + + // Remove draggable from all row elements in the escalator + Range visibleRange = getEscalator().getVisibleRowRange(); + for (int i = visibleRange.getStart(); i < visibleRange.getEnd(); i++) { + removeDraggable(getGridBody().getRowElement(i)); + } + + // Remove drag listeners from body element + removeDragListeners(getGridBody().getElement()); + + // Remove callback for newly added rows + getGridBody().setNewEscalatorRowCallback(null); + } + + private Escalator getEscalator() { + return gridConnector.getWidget().getEscalator(); + } + + private RowContainer.BodyRowContainer getGridBody() { + return getEscalator().getBody(); + } + + @Override + public GridDragSourceExtensionState getState() { + return (GridDragSourceExtensionState) super.getState(); + } +} diff --git a/client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java b/client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java index 3094042826..23797ce886 100644 --- a/client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java +++ b/client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java @@ -56,29 +56,66 @@ public class DragSourceExtensionConnector extends AbstractExtensionConnector { protected void extend(ServerConnector target) { dragSourceWidget = ((ComponentConnector) target).getWidget(); - Element dragSourceElement = getDraggableElement(); + setDraggable(getDraggableElement()); + addDragListeners(getDraggableElement()); + } + + /** + * Sets the given element draggable and adds class name. + * + * @param element + * Element to be set draggable. + */ + protected void setDraggable(Element element) { + element.setDraggable(Element.DRAGGABLE_TRUE); + element.addClassName(CLASS_DRAGGABLE); + } + + /** + * Removes draggable and class name from the given element. + * + * @param element + * Element to remove draggable from. + */ + protected void removeDraggable(Element element) { + element.setDraggable(Element.DRAGGABLE_FALSE); + element.removeClassName(CLASS_DRAGGABLE); + } - dragSourceElement.setDraggable(Element.DRAGGABLE_TRUE); - dragSourceElement.addClassName(CLASS_DRAGGABLE); + /** + * Adds dragstart and dragend event listeners to the given DOM element. + * + * @param element + * DOM element to attach event listeners to. + */ + protected void addDragListeners(Element element) { + EventTarget target = element.cast(); - EventTarget dragSource = dragSourceElement.cast(); + target.addEventListener(Event.DRAGSTART, dragStartListener); + target.addEventListener(Event.DRAGEND, dragEndListener); + } - // dragstart - dragSource.addEventListener(Event.DRAGSTART, dragStartListener); + /** + * Removes dragstart and dragend event listeners from the given DOM element. + * + * @param element + * DOM element to remove event listeners from. + */ + protected void removeDragListeners(Element element) { + EventTarget target = element.cast(); - // dragend - dragSource.addEventListener(Event.DRAGEND, dragEndListener); + target.removeEventListener(Event.DRAGSTART, dragStartListener); + target.removeEventListener(Event.DRAGEND, dragEndListener); } @Override public void onUnregister() { super.onUnregister(); - EventTarget dragSource = (EventTarget) getDraggableElement(); + Element dragSource = getDraggableElement(); - // Remove listeners - dragSource.removeEventListener(Event.DRAGSTART, dragStartListener); - dragSource.removeEventListener(Event.DRAGEND, dragEndListener); + removeDraggable(dragSource); + removeDragListeners(dragSource); } /** diff --git a/client/src/main/java/com/vaadin/client/widget/escalator/RowContainer.java b/client/src/main/java/com/vaadin/client/widget/escalator/RowContainer.java index 0105aa687c..ca00ca9b63 100644 --- a/client/src/main/java/com/vaadin/client/widget/escalator/RowContainer.java +++ b/client/src/main/java/com/vaadin/client/widget/escalator/RowContainer.java @@ -16,6 +16,9 @@ package com.vaadin.client.widget.escalator; +import java.util.List; +import java.util.function.Consumer; + import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.TableRowElement; import com.google.gwt.dom.client.TableSectionElement; @@ -116,6 +119,17 @@ public interface RowContainer { @Override public void removeRows(int index, int numberOfRows) throws IndexOutOfBoundsException, IllegalArgumentException; + + /** + * Sets a callback function that is executed when new rows are added to + * the escalator. + * + * @param consumer + * A Consumer function that receives the newly added table row + * elements. + */ + public void setNewEscalatorRowCallback( + Consumer<List<TableRowElement>> consumer); } /** diff --git a/client/src/main/java/com/vaadin/client/widgets/Escalator.java b/client/src/main/java/com/vaadin/client/widgets/Escalator.java index 7bb078a94a..1f223c1d85 100644 --- a/client/src/main/java/com/vaadin/client/widgets/Escalator.java +++ b/client/src/main/java/com/vaadin/client/widgets/Escalator.java @@ -25,7 +25,9 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.TreeMap; +import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; @@ -2401,6 +2403,12 @@ public class Escalator extends Widget @Deprecated private int topRowLogicalIndex = 0; + /** + * A callback function to be executed after new rows are added to the + * escalator. + */ + private Consumer<List<TableRowElement>> newEscalatorRowCallback; + private void setTopRowLogicalIndex(int topRowLogicalIndex) { if (LogConfiguration.loggingIsEnabled(Level.INFO)) { Logger.getLogger("Escalator.BodyRowContainer") @@ -2992,6 +3000,10 @@ public class Escalator extends Widget y += spacerContainer.getSpacerHeight(i); } + // Execute the registered callback function for newly created rows + Optional.ofNullable(newEscalatorRowCallback) + .ifPresent(callback -> callback.accept(addedRows)); + return addedRows; } else { return Collections.emptyList(); @@ -3982,6 +3994,12 @@ public class Escalator extends Widget int padding) { spacerContainer.scrollToSpacer(spacerIndex, destination, padding); } + + @Override + public void setNewEscalatorRowCallback( + Consumer<List<TableRowElement>> callback) { + this.newEscalatorRowCallback = callback; + } } private class ColumnConfigurationImpl implements ColumnConfiguration { |