From a9c8e66d14899796e786e643d434daf6f16cf062 Mon Sep 17 00:00:00 2001 From: Adam Wagner Date: Thu, 9 Feb 2017 07:52:15 +0100 Subject: HTML5 Drag and Drop Support (#8264) * Add DragSource Extension (#8169) * Add DropTarget Extension (#8170) * Add DragStart Event to DragSource Extension (#8171) * Make DataTransfer.dropEffect configurable (#8174) * Make DragSource.dataTransfer data configurable (#8172) * Add server-side Event for drop (#8177) * Added license headers * Extract handler methods, move DropEvent and DropListener to new file, move enums to top * Replaced LinkedHashMap with Map and added List to preserve order of data * Add API for adding a JS acceptance criteria for dragover and drop (#8178, #8179) * Make DragSource Extension extendable (#8175) * Make DropTarget Extension extendable (#8176) * Added javadoc to protected methods * Moved EffectAllowed to shared so that it could be used in shared state directly * Moved DropEffect to separate file, some review fixes and javadoc * Added list to DropTargetRpc to preserve order of data * Remove event listeners on unregister * Changed method names set/getData() to more descriptive set/getTransferData() * Add server side dragStart event (#8171) * Add style to prevent text selection to allow drag * Remove target indicator style on drop * Add client side dragend event listener for drag source * Add server side dragend listener. Attach client side listener only when server side listener added. * Add drag source information to server side dragstart and dragend events. * Fixed some issues addressed in review * Trigger server side dragstart only when there is a listener attached * Criteria script can be set as null to clear * Use Js Interop instead of JSNI for handling event listeners * Use elemental package instead of Js Interop for handling event listeners * Add missing javadoc for public methods * Add default value "uninitialized" to effectAllowed parameter * Simple test UI for HTML5 DnD functionality (#8395) * Add javadoc and other minor changes --- .../java/com/vaadin/event/dnd/DragEndEvent.java | 77 +++++++ .../java/com/vaadin/event/dnd/DragEndListener.java | 40 ++++ .../com/vaadin/event/dnd/DragSourceExtension.java | 226 +++++++++++++++++++++ .../java/com/vaadin/event/dnd/DragStartEvent.java | 77 +++++++ .../com/vaadin/event/dnd/DragStartListener.java | 40 ++++ .../main/java/com/vaadin/event/dnd/DropEvent.java | 77 +++++++ .../java/com/vaadin/event/dnd/DropListener.java | 38 ++++ .../com/vaadin/event/dnd/DropTargetExtension.java | 145 +++++++++++++ 8 files changed, 720 insertions(+) create mode 100644 server/src/main/java/com/vaadin/event/dnd/DragEndEvent.java create mode 100644 server/src/main/java/com/vaadin/event/dnd/DragEndListener.java create mode 100644 server/src/main/java/com/vaadin/event/dnd/DragSourceExtension.java create mode 100644 server/src/main/java/com/vaadin/event/dnd/DragStartEvent.java create mode 100644 server/src/main/java/com/vaadin/event/dnd/DragStartListener.java create mode 100644 server/src/main/java/com/vaadin/event/dnd/DropEvent.java create mode 100644 server/src/main/java/com/vaadin/event/dnd/DropListener.java create mode 100644 server/src/main/java/com/vaadin/event/dnd/DropTargetExtension.java (limited to 'server') diff --git a/server/src/main/java/com/vaadin/event/dnd/DragEndEvent.java b/server/src/main/java/com/vaadin/event/dnd/DragEndEvent.java new file mode 100644 index 0000000000..6f094ce9e2 --- /dev/null +++ b/server/src/main/java/com/vaadin/event/dnd/DragEndEvent.java @@ -0,0 +1,77 @@ +/* + * 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.event.dnd; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.vaadin.shared.ui.dnd.EffectAllowed; +import com.vaadin.ui.Component; + +/** + * Server side dragend event. Fired when an HTML5 dragend happens. + * + * @see DragSourceExtension#addDragEndListener(DragEndListener) + */ +public class DragEndEvent extends Component.Event { + private final Map data; + private final EffectAllowed effectAllowed; + + /** + * Creates a new server side dragend event. + * + * @param source + * Draggable component. + * @param types + * List of data types from {@code DataTransfer.types}. + * @param data + * Map of all data from {@code DataTransfer}. + * @param effectAllowed + * Parameter from {@code DataTransfer.effectAllowed}. + */ + public DragEndEvent(Component source, List types, + Map data, EffectAllowed effectAllowed) { + super(source); + + // Create a linked map that preserves the order of types + this.data = new LinkedHashMap<>(); + types.forEach(type -> this.data.put(type, data.get(type))); + + this.effectAllowed = effectAllowed; + } + + /** + * Get data from the client side {@code DataTransfer} object. + * + * @param format + * Data format, e.g. {@code text/plain} or {@code text/uri-list}. + * @return Data for the given format if exists in the client side {@code + * DataTransfer}, otherwise {@code null}. + */ + public String getTransferData(String format) { + return data != null ? data.get(format) : null; + } + + /** + * Returns the {@code effectAllowed} parameter of this event. + * + * @return This event's {@code effectAllowed} parameter. + */ + public EffectAllowed getEffectAllowed() { + return effectAllowed; + } +} diff --git a/server/src/main/java/com/vaadin/event/dnd/DragEndListener.java b/server/src/main/java/com/vaadin/event/dnd/DragEndListener.java new file mode 100644 index 0000000000..00a020353d --- /dev/null +++ b/server/src/main/java/com/vaadin/event/dnd/DragEndListener.java @@ -0,0 +1,40 @@ +/* + * 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.event.dnd; + +import java.lang.reflect.Method; + +import com.vaadin.event.ConnectorEventListener; + +/** + * Interface to be implemented when creating a dragend listener on a drag + * source for HTML5 drag and drop. + * + * @see DragSourceExtension#addDragEndListener(DragEndListener) + */ +@FunctionalInterface +public interface DragEndListener extends ConnectorEventListener { + static final Method DRAGEND_METHOD = DragEndListener.class + .getDeclaredMethods()[0]; + + /** + * Called when a server side dragend event is fired. + * + * @param event + * The dragend event that is fired. + */ + void dragEnd(DragEndEvent event); +} diff --git a/server/src/main/java/com/vaadin/event/dnd/DragSourceExtension.java b/server/src/main/java/com/vaadin/event/dnd/DragSourceExtension.java new file mode 100644 index 0000000000..d90e1bd8b8 --- /dev/null +++ b/server/src/main/java/com/vaadin/event/dnd/DragSourceExtension.java @@ -0,0 +1,226 @@ +/* + * 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.event.dnd; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +import com.vaadin.server.AbstractClientConnector; +import com.vaadin.server.AbstractExtension; +import com.vaadin.shared.Registration; +import com.vaadin.shared.ui.dnd.DragSourceRpc; +import com.vaadin.shared.ui.dnd.DragSourceState; +import com.vaadin.shared.ui.dnd.EffectAllowed; +import com.vaadin.ui.AbstractComponent; + +/** + * Extension to add drag source functionality to a component for using HTML5 + * drag and drop. + */ +public class DragSourceExtension extends AbstractExtension { + + /** + * Constructor for {@link DragSourceExtension} + */ + public DragSourceExtension() { + registerRpc(new DragSourceRpc() { + @Override + public void dragStart() { + DragStartEvent event = new DragStartEvent( + (AbstractComponent) getParent(), getState(false).types, + getState(false).data, getState(false).effectAllowed); + fireEvent(event); + } + + @Override + public void dragEnd() { + DragEndEvent event = new DragEndEvent( + (AbstractComponent) getParent(), getState(false).types, + getState(false).data, getState(false).effectAllowed); + fireEvent(event); + } + }); + } + + /** + * Makes {@code target} component a drag source. + * + * @param target + * Component to be extended. + */ + public void extend(AbstractComponent target) { + super.extend(target); + } + + /** + * Sets the allowed effects for the current drag source element. Used for + * setting client side {@code DataTransfer.effectAllowed} parameter for the + * drag event. + *

+ * By default the value is {@link EffectAllowed#UNINITIALIZED} which is + * equivalent to {@link EffectAllowed#ALL}. + * + * @param effect + * Effects to allow for this draggable element. Cannot be {@code + * null}. + */ + public void setEffectAllowed(EffectAllowed effect) { + if (effect == null) { + throw new IllegalArgumentException("Allowed effect cannot be null"); + } + if (!Objects.equals(getState(false).effectAllowed, effect)) { + getState().effectAllowed = effect; + } + } + + /** + * Returns the allowed effects for the current drag source element. Used to + * set client side {@code DataTransfer.effectAllowed} parameter for the drag + * event. + * + * @return Effects that are allowed for this draggable element. + */ + public EffectAllowed getEffectAllowed() { + return getState(false).effectAllowed; + } + + /** + * Sets the data for this drag source element. Used to set data for client + * side drag element using {@code DataTransfer.setData()}. To be used as a + * map, key-value pairs are stored. Order of entries are preserved. + *

+ * Note that by HTML specification, the browser will change data type + * "{@code text}" to "{@code text/plain}" and "{@code url}" to "{@code + * text/uri-list}" during client side drag event. + * + * @param format + * Data type to store, e.g. {@code text/plain} or {@code + * text/uri-list}. Cannot be {@code null}. + * @param data + * Data to store for the data type. Cannot be {@code null}. + */ + public void setTransferData(String format, String data) { + if (format == null) { + throw new IllegalArgumentException("Data type cannot be null"); + } + + if (data == null) { + throw new IllegalArgumentException("Data cannot be null"); + } + + if (!getState(false).types.contains(format)) { + getState().types.add(format); + } + getState().data.put(format, data); + } + + /** + * Returns the data stored for {@code format} type in this drag source + * element. + * + * @param format + * Data type of the requested data, e.g. {@code text/plain} or + * {@code text/uri-list}. + * @return Data that is stored for {@code format} data type. + */ + public String getTransferData(String format) { + return getState(false).data.get(format); + } + + /** + * Returns the map of data stored in this drag source element. The returned + * map preserves the order of storage and is unmodifiable. + * + * @return Unmodifiable copy of the map of data in the order the data was + * stored. + */ + public Map getTransferData() { + Map data = getState(false).data; + + // Create a map of data that preserves the order of types + LinkedHashMap orderedData = new LinkedHashMap<>( + data.size()); + getState(false).types + .forEach(type -> orderedData.put(type, data.get(type))); + + return Collections.unmodifiableMap(orderedData); + } + + /** + * Clears data with the given type for this drag source element when + * present. + * + * @param format + * Type of data to be cleared. Cannot be {@code null}. + */ + public void clearTransferData(String format) { + if (format == null) { + throw new IllegalArgumentException("Data type cannot be null"); + } + + getState().types.remove(format); + getState().data.remove(format); + } + + /** + * Clears all data for this drag source element. + */ + public void clearTransferData() { + getState().types.clear(); + getState().data.clear(); + } + + /** + * Attaches dragstart listener for the current drag source. {@link + * DragStartListener#dragStart(DragStartEvent)} is called when dragstart + * event happens on the client side. + * + * @param listener + * Listener to handle dragstart event. + * @return Handle to be used to remove this listener. + */ + public Registration addDragStartListener(DragStartListener listener) { + return addListener(DragSourceState.EVENT_DRAGSTART, + DragStartEvent.class, listener, + DragStartListener.DRAGSTART_METHOD); + } + + /** + * Attaches dragend listener for the current drag source. {@link + * DragEndListener#dragEnd(DragEndEvent)} is called when dragend + * event happens on the client side. + * + * @param listener + * Listener to handle dragend event. + * @return Handle to be used to remove this listener. + */ + public Registration addDragEndListener(DragEndListener listener) { + return addListener(DragSourceState.EVENT_DRAGEND, DragEndEvent.class, + listener, DragEndListener.DRAGEND_METHOD); + } + + @Override + protected DragSourceState getState() { + return (DragSourceState) super.getState(); + } + + @Override + protected DragSourceState getState(boolean markAsDirty) { + return (DragSourceState) super.getState(markAsDirty); + } +} diff --git a/server/src/main/java/com/vaadin/event/dnd/DragStartEvent.java b/server/src/main/java/com/vaadin/event/dnd/DragStartEvent.java new file mode 100644 index 0000000000..591a0e61a7 --- /dev/null +++ b/server/src/main/java/com/vaadin/event/dnd/DragStartEvent.java @@ -0,0 +1,77 @@ +/* + * 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.event.dnd; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.vaadin.shared.ui.dnd.EffectAllowed; +import com.vaadin.ui.Component; + +/** + * Server side dragstart event. Fired when an HTML5 dragstart happens. + * + * @see DragSourceExtension#addDragStartListener(DragStartListener) + */ +public class DragStartEvent extends Component.Event { + private final Map data; + private final EffectAllowed effectAllowed; + + /** + * Creates a new server side dragend event. + * + * @param source + * Draggable component. + * @param types + * List of data types from {@code DataTransfer.types}. + * @param data + * Map of all data from {@code DataTransfer}. + * @param effectAllowed + * Parameter from {@code DataTransfer.effectAllowed}. + */ + public DragStartEvent(Component source, List types, + Map data, EffectAllowed effectAllowed) { + super(source); + + // Create a linked map that preserves the order of types + this.data = new LinkedHashMap<>(); + types.forEach(type -> this.data.put(type, data.get(type))); + + this.effectAllowed = effectAllowed; + } + + /** + * Get data from the client side {@code DataTransfer} object. + * + * @param format + * Data format, e.g. {@code text/plain} or {@code text/uri-list}. + * @return Data for the given format if exists in the client side {@code + * DataTransfer}, otherwise {@code null}. + */ + public String getTransferData(String format) { + return data != null ? data.get(format) : null; + } + + /** + * Returns the {@code effectAllowed} parameter of this event. + * + * @return This event's {@code effectAllowed} parameter. + */ + public EffectAllowed getEffectAllowed() { + return effectAllowed; + } +} diff --git a/server/src/main/java/com/vaadin/event/dnd/DragStartListener.java b/server/src/main/java/com/vaadin/event/dnd/DragStartListener.java new file mode 100644 index 0000000000..8d691dee6b --- /dev/null +++ b/server/src/main/java/com/vaadin/event/dnd/DragStartListener.java @@ -0,0 +1,40 @@ +/* + * 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.event.dnd; + +import java.lang.reflect.Method; + +import com.vaadin.event.ConnectorEventListener; + +/** + * Interface to be implemented when creating a dragstart listener on a drag + * source for HTML5 drag and drop. + * + * @see DragSourceExtension#addDragStartListener(DragStartListener) + */ +@FunctionalInterface +public interface DragStartListener extends ConnectorEventListener { + static final Method DRAGSTART_METHOD = DragStartListener.class + .getDeclaredMethods()[0]; + + /** + * Called when a server side dragstart event is fired. + * + * @param event + * The dragstart event that is fired. + */ + void dragStart(DragStartEvent event); +} diff --git a/server/src/main/java/com/vaadin/event/dnd/DropEvent.java b/server/src/main/java/com/vaadin/event/dnd/DropEvent.java new file mode 100644 index 0000000000..382b93bc55 --- /dev/null +++ b/server/src/main/java/com/vaadin/event/dnd/DropEvent.java @@ -0,0 +1,77 @@ +/* + * 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.event.dnd; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.vaadin.shared.ui.dnd.DropEffect; +import com.vaadin.ui.Component; + +/** + * Server side drop event. Fired when an HTML5 drop happens. + * + * @see DropTargetExtension#addDropListener(DropListener) + */ +public class DropEvent extends Component.Event { + private final Map data; + private final DropEffect dropEffect; + + /** + * Creates a new server side drop event. + * + * @param source + * Drop target component. + * @param types + * List of data types from {@code DataTransfer.types}. + * @param data + * Map of all data from {@code DataTransfer}. + * @param dropEffect + * Parameter from {@code DataTransfer.dropEffect}. + */ + public DropEvent(Component source, List types, + Map data, DropEffect dropEffect) { + super(source); + + // Create a linked map that preserves the order of types + this.data = new LinkedHashMap<>(); + types.forEach(type -> this.data.put(type, data.get(type))); + + this.dropEffect = dropEffect; + } + + /** + * Get data from the client side {@code DataTransfer} object. + * + * @param format + * Data format, e.g. {@code text/plain} or {@code text/uri-list}. + * @return Data for the given format if exists in the client side {@code + * DataTransfer}, otherwise {@code null}. + */ + public String getTransferData(String format) { + return data != null ? data.get(format) : null; + } + + /** + * Get drop effect set for the current drop target. + * + * @return {@code dropEffect} parameter set for the current drop target. + */ + public DropEffect getDropEffect() { + return dropEffect; + } +} diff --git a/server/src/main/java/com/vaadin/event/dnd/DropListener.java b/server/src/main/java/com/vaadin/event/dnd/DropListener.java new file mode 100644 index 0000000000..8cb96d1852 --- /dev/null +++ b/server/src/main/java/com/vaadin/event/dnd/DropListener.java @@ -0,0 +1,38 @@ +/* + * 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.event.dnd; + +import java.lang.reflect.Method; + +import com.vaadin.event.ConnectorEventListener; + +/** + * Interface to be implemented when creating a drop listener on a drop target + * for HTML5 drag and drop. See {@link DropTargetExtension#addDropListener(DropListener)}. + */ +@FunctionalInterface +public interface DropListener extends ConnectorEventListener { + static final Method DROP_METHOD = DropListener.class + .getDeclaredMethods()[0]; + + /** + * Called when a server side drop event is fired. + * + * @param event + * The drop event that is fired. + */ + void drop(DropEvent event); +} diff --git a/server/src/main/java/com/vaadin/event/dnd/DropTargetExtension.java b/server/src/main/java/com/vaadin/event/dnd/DropTargetExtension.java new file mode 100644 index 0000000000..20819ec70f --- /dev/null +++ b/server/src/main/java/com/vaadin/event/dnd/DropTargetExtension.java @@ -0,0 +1,145 @@ +/* + * 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.event.dnd; + +import java.util.Objects; + +import com.vaadin.server.AbstractClientConnector; +import com.vaadin.server.AbstractExtension; +import com.vaadin.shared.Registration; +import com.vaadin.shared.ui.dnd.DropEffect; +import com.vaadin.shared.ui.dnd.DropTargetRpc; +import com.vaadin.shared.ui.dnd.DropTargetState; +import com.vaadin.ui.AbstractComponent; + +/** + * Extension to add drop target functionality to a widget for using HTML5 drag + * and drop. + */ +public class DropTargetExtension extends AbstractExtension { + + /** + * Constructor for {@link DropTargetExtension}. + */ + public DropTargetExtension() { + registerRpc((DropTargetRpc) (types, data, dropEffect) -> { + DropEvent event = new DropEvent((AbstractComponent) getParent(), + types, data, dropEffect); + + fireEvent(event); + }); + } + + /** + * Makes {@code target} component a drop target. + * + * @param target + * Component to be extended. + */ + public void extend(AbstractComponent target) { + super.extend(target); + } + + /** + * Sets the drop effect for the current drop target. Used for the client + * side {@code DataTransfer.dropEffect} parameter. + *

+ * Default value is browser dependent and can depend on e.g. modifier keys. + * + * @param dropEffect + * The drop effect to be set. Cannot be {@code null}. + */ + public void setDropEffect(DropEffect dropEffect) { + if (dropEffect == null) { + throw new IllegalArgumentException("Drop effect cannot be null."); + } + + if (!Objects.equals(getState(false).dropEffect, dropEffect)) { + getState().dropEffect = dropEffect; + } + } + + /** + * Returns the drop effect for the current drop target. + * + * @return The drop effect of this drop target. + */ + public DropEffect getDropEffect() { + return getState(false).dropEffect; + } + + /** + * Sets criteria to allow dragover event on the current drop target. The + * script executes when dragover event happens and stops the event in case + * the script returns {@code false}. + * + * @param criteriaScript + * JavaScript to be executed when dragover event happens or {@code + * null} to clear. + */ + public void setDragOverCriteria(String criteriaScript) { + if (!Objects.equals(getState(false).dragOverCriteria, criteriaScript)) { + getState().dragOverCriteria = criteriaScript; + } + } + + /** + * Sets criteria to allow drop event on the current drop target. The script + * executes when drop event happens and stops the event in case the script + * returns {@code false}. + * + * @param criteriaScript + * JavaScript to be executed when drop event happens or {@code null} + * to clear. + */ + public void setDropCriteria(String criteriaScript) { + if (!Objects.equals(getState(false).dropCriteria, criteriaScript)) { + getState().dropCriteria = criteriaScript; + } + } + + /** + * Returns the criteria for allowing drop event on the current drop target. + * + * @return JavaScript that executes when drop event happens. + */ + public String getDropCriteria() { + return getState(false).dropCriteria; + } + + /** + * Attaches drop listener for the current drop target. {@link + * DropListener#drop(DropEvent)} is called when drop event happens on the + * client side. + * + * @param listener + * Listener to handle drop event. + * @return Handle to be used to remove this listener. + */ + public Registration addDropListener(DropListener listener) { + return addListener(DropEvent.class, listener, DropListener.DROP_METHOD); + } + + @Override + protected DropTargetState getState() { + return (DropTargetState) super.getState(); + } + + @Override + protected DropTargetState getState(boolean markAsDirty) { + return (DropTargetState) super.getState(markAsDirty); + } +} -- cgit v1.2.3