diff options
author | Adam Wagner <wbadam@users.noreply.github.com> | 2017-03-16 20:35:46 +0200 |
---|---|---|
committer | Henri Sara <henri.sara@gmail.com> | 2017-04-12 14:58:11 +0300 |
commit | 1ac4f9724106fcf4abaab892210122231710c6be (patch) | |
tree | cd63d9a7d1e689b041ca05d25385d4b39929782d /client | |
parent | 2df1b373aae547275b566fef957322af0b61b427 (diff) | |
download | vaadin-framework-1ac4f9724106fcf4abaab892210122231710c6be.tar.gz vaadin-framework-1ac4f9724106fcf4abaab892210122231710c6be.zip |
Make it possible to drop things on top of Grid rows (#8747)
Fixes #8400
Diffstat (limited to 'client')
4 files changed, 193 insertions, 33 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 index eaeaffc1d9..b31a2578eb 100644 --- a/client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceExtensionConnector.java +++ b/client/src/main/java/com/vaadin/client/connectors/grid/GridDragSourceExtensionConnector.java @@ -29,6 +29,7 @@ import com.vaadin.client.widgets.Escalator; import com.vaadin.client.widgets.Grid; import com.vaadin.shared.Range; import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.dnd.DragSourceState; import com.vaadin.shared.ui.grid.GridDragSourceExtensionState; import com.vaadin.ui.GridDragSourceExtension; @@ -83,8 +84,7 @@ public class GridDragSourceExtensionConnector extends // Set drag data in DataTransfer object ((NativeEvent) event).getDataTransfer() - .setData(GridDragSourceExtensionState.DATA_TYPE_DRAG_DATA, - dragData.toJson()); + .setData(DragSourceState.DATA_TYPE_TEXT, dragData.toJson()); } } diff --git a/client/src/main/java/com/vaadin/client/connectors/grid/GridDropTargetExtensionConnector.java b/client/src/main/java/com/vaadin/client/connectors/grid/GridDropTargetExtensionConnector.java new file mode 100644 index 0000000000..9c25f5acb4 --- /dev/null +++ b/client/src/main/java/com/vaadin/client/connectors/grid/GridDropTargetExtensionConnector.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 java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.TableRowElement; +import com.vaadin.client.ServerConnector; +import com.vaadin.client.extensions.DropTargetExtensionConnector; +import com.vaadin.client.widget.escalator.RowContainer; +import com.vaadin.client.widgets.Escalator; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.grid.GridDropTargetExtensionRpc; +import com.vaadin.shared.ui.grid.GridDropTargetExtensionState; +import com.vaadin.shared.ui.grid.GridState; +import com.vaadin.ui.GridDropTargetExtension; + +import elemental.events.Event; +import elemental.json.JsonObject; + +/** + * Makes Grid an HTML5 drop target. This is the client side counterpart of + * {@link GridDropTargetExtension}. + * + * @author Vaadin Ltd + * @since + */ +@Connect(GridDropTargetExtension.class) +public class GridDropTargetExtensionConnector extends + DropTargetExtensionConnector { + + private GridConnector gridConnector; + + @Override + protected void extend(ServerConnector target) { + gridConnector = (GridConnector) target; + + super.extend(target); + } + + @Override + protected void sendDropEventToServer(String dataTransferText, + Event dropEvent) { + + String rowKey = null; + Optional<TableRowElement> targetRow = getTargetRow( + (Element) dropEvent.getTarget()); + if (targetRow.isPresent()) { + rowKey = getRowData(targetRow.get()) + .getString(GridState.JSONKEY_ROWKEY); + } + + getRpcProxy(GridDropTargetExtensionRpc.class) + .drop(dataTransferText, rowKey); + } + + private JsonObject getRowData(TableRowElement row) { + int rowIndex = ((Escalator.AbstractRowContainer) getGridBody()) + .getLogicalRowIndex(row); + return gridConnector.getDataSource().getRow(rowIndex); + } + + @Override + protected void addTargetIndicator(Event event) { + getTargetRow(((Element) event.getTarget())) + .ifPresent(e -> e.addClassName(CLASS_DRAG_OVER)); + } + + @Override + protected void removeTargetIndicator(Event event) { + getTargetRow(((Element) event.getTarget())) + .ifPresent(e -> e.removeClassName(CLASS_DRAG_OVER)); + } + + private Optional<TableRowElement> getTargetRow(Element source) { + while (!Objects.equals(source, getGridBody().getElement())) { + if (TableRowElement.is(source)) { + return Optional.of(source.cast()); + } + source = source.getParentElement(); + } + return Optional.empty(); + } + + @Override + protected Element getDropTargetElement() { + return getGridBody().getElement(); + } + + private Escalator getEscalator() { + return gridConnector.getWidget().getEscalator(); + } + + private RowContainer.BodyRowContainer getGridBody() { + return getEscalator().getBody(); + } + + @Override + public GridDropTargetExtensionState getState() { + return (GridDropTargetExtensionState) 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 23797ce886..52c70b362b 100644 --- a/client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java +++ b/client/src/main/java/com/vaadin/client/extensions/DragSourceExtensionConnector.java @@ -161,7 +161,7 @@ public class DragSourceExtensionConnector extends AbstractExtensionConnector { ((NativeEvent) event).getDataTransfer()); assert dropEffect != null : "Drop effect should never be null"; - + getRpcProxy(DragSourceRpc.class) .dragEnd(DropEffect.valueOf(dropEffect.toUpperCase())); } diff --git a/client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java b/client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java index 5f8ca243c7..473b72237e 100644 --- a/client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java +++ b/client/src/main/java/com/vaadin/client/extensions/DropTargetExtensionConnector.java @@ -15,7 +15,6 @@ */ package com.vaadin.client.extensions; -import com.google.gwt.dom.client.BrowserEvents; import com.google.gwt.dom.client.DataTransfer; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.NativeEvent; @@ -42,7 +41,7 @@ import elemental.events.EventTarget; @Connect(DropTargetExtension.class) public class DropTargetExtensionConnector extends AbstractExtensionConnector { - private static final String CLASS_DRAG_OVER = "v-drag-over"; + protected static final String CLASS_DRAG_OVER = "v-drag-over"; // Create event listeners private final EventListener dragEnterListener = this::onDragEnter; @@ -59,35 +58,46 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector { protected void extend(ServerConnector target) { dropTargetWidget = ((ComponentConnector) target).getWidget(); - EventTarget dropTarget = getDropTargetElement().cast(); + addDropListeners(getDropTargetElement()); + } - // dragenter event - dropTarget.addEventListener(BrowserEvents.DRAGENTER, dragEnterListener); + /** + * Adds dragenter, dragover, dragleave and drop event listeners to the given + * DOM element. + * + * @param element + * DOM element to attach event listeners to. + */ + protected void addDropListeners(Element element) { + EventTarget target = element.cast(); - // dragover event - dropTarget.addEventListener(BrowserEvents.DRAGOVER, dragOverListener); + target.addEventListener(Event.DRAGENTER, dragEnterListener); + target.addEventListener(Event.DRAGOVER, dragOverListener); + target.addEventListener(Event.DRAGLEAVE, dragLeaveListener); + target.addEventListener(Event.DROP, dropListener); + } - // dragleave event - dropTarget.addEventListener(BrowserEvents.DRAGLEAVE, dragLeaveListener); + /** + * Removes dragenter, dragover, dragleave and drop event listeners from the + * given DOM element. + * + * @param element + * DOM element to remove event listeners from. + */ + protected void removeDropListeners(Element element) { + EventTarget target = element.cast(); - // drop event - dropTarget.addEventListener(BrowserEvents.DROP, dropListener); + target.removeEventListener(Event.DRAGENTER, dragEnterListener); + target.removeEventListener(Event.DRAGOVER, dragOverListener); + target.removeEventListener(Event.DRAGLEAVE, dragLeaveListener); + target.removeEventListener(Event.DROP, dropListener); } @Override public void onUnregister() { super.onUnregister(); - EventTarget dropTarget = getDropTargetElement().cast(); - - // Remove listeners - dropTarget.removeEventListener(BrowserEvents.DRAGENTER, - dragEnterListener); - dropTarget.removeEventListener(BrowserEvents.DRAGOVER, - dragOverListener); - dropTarget.removeEventListener(BrowserEvents.DRAGLEAVE, - dragLeaveListener); - dropTarget.removeEventListener(BrowserEvents.DROP, dropListener); + removeDropListeners(getDropTargetElement()); } /** @@ -107,7 +117,7 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector { * browser event to be handled */ protected void onDragEnter(Event event) { - addTargetIndicator(getDropTargetElement()); + addTargetIndicator(event); } /** @@ -126,6 +136,9 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector { .valueOf(getState().dropEffect.name())); } + // Add drop target indicator in case the element doesn't have one + addTargetIndicator(event); + // Prevent default to allow drop nativeEvent.preventDefault(); nativeEvent.stopPropagation(); @@ -135,7 +148,7 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector { .setDropEffect(DataTransfer.DropEffect.NONE); // Remove drop target indicator - removeTargetIndicator(getDropTargetElement()); + removeTargetIndicator(event); } } @@ -164,7 +177,7 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector { * browser event to be handled */ protected void onDragLeave(Event event) { - removeTargetIndicator(getDropTargetElement()); + removeTargetIndicator(event); } /** @@ -182,10 +195,10 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector { String dataTransferText = nativeEvent.getDataTransfer().getData( DragSourceState.DATA_TYPE_TEXT); - getRpcProxy(DropTargetRpc.class).drop(dataTransferText); + sendDropEventToServer(dataTransferText, event); } - removeTargetIndicator(getDropTargetElement()); + removeTargetIndicator(event); } private boolean dropAllowed(NativeEvent event) { @@ -197,12 +210,40 @@ public class DropTargetExtensionConnector extends AbstractExtensionConnector { return true; } - private void addTargetIndicator(Element element) { - element.addClassName(CLASS_DRAG_OVER); + /** + * Initiates a server RPC for the drop event. + * + * @param dataTransferText + * Client side textual data that can be set for the drag source and + * is transferred to the drop target. + * @param dropEvent + * Client side drop event. + */ + protected void sendDropEventToServer(String dataTransferText, + Event dropEvent) { + getRpcProxy(DropTargetRpc.class).drop(dataTransferText); } - private void removeTargetIndicator(Element element) { - element.removeClassName(CLASS_DRAG_OVER); + /** + * Add class that indicates that the component is a target. + * + * @param event + * The drag enter or dragover event that triggered the indication. + */ + protected void addTargetIndicator(Event event) { + getDropTargetElement().addClassName(CLASS_DRAG_OVER); + } + + /** + * Remove the drag target indicator class name from the target element. + * <p> + * This is triggered on dragleave, drop and dragover events. + * + * @param event + * the event that triggered the removal of the indicator + */ + protected void removeTargetIndicator(Event event) { + getDropTargetElement().removeClassName(CLASS_DRAG_OVER); } private native boolean executeScript(NativeEvent event, String script)/*-{ |