*/
package com.vaadin.client.extensions;
-import java.util.List;
-import java.util.Map;
-
import com.google.gwt.dom.client.DataTransfer;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
private static final String CLASS_DRAGGABLE = "v-draggable";
- /**
- * Data type for storing drag source extension connector's ID
- */
- static final String DATA_TYPE_DRAG_SOURCE_ID = "drag-source-id";
-
// Create event listeners
private final EventListener dragStartListener = this::onDragStart;
private final EventListener dragEndListener = this::onDragEnd;
getState().effectAllowed.getValue());
}
- // Set data parameter
- List<String> types = getState().types;
- Map<String, String> data = getState().data;
- for (String format : types) {
- nativeEvent.getDataTransfer().setData(format, data.get(format));
- }
-
- // Store the extension's connector ID in DataTransfer.data
- nativeEvent.getDataTransfer()
- .setData(DATA_TYPE_DRAG_SOURCE_ID, getConnectorId());
+ // Set text data parameter
+ nativeEvent.getDataTransfer().setData(DragSourceState.DATA_TYPE_TEXT,
+ getState().dataTransferText);
// Initiate firing server side dragstart event when there is a
// DragStartListener attached on the server side
*/
package com.vaadin.client.extensions;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.DataTransfer;
import com.google.gwt.dom.client.Element;
import com.vaadin.client.ServerConnector;
import com.vaadin.event.dnd.DropTargetExtension;
import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.dnd.DragSourceState;
import com.vaadin.shared.ui.dnd.DropTargetRpc;
import com.vaadin.shared.ui.dnd.DropTargetState;
nativeEvent.preventDefault();
nativeEvent.stopPropagation();
- // Initiate firing server side drop event
- JsArrayString typesJsArray = getTypes(
- nativeEvent.getDataTransfer());
- List<String> types = new ArrayList<>();
- Map<String, String> data = new HashMap<>();
- for (int i = 0; i < typesJsArray.length(); i++) {
- types.add(typesJsArray.get(i));
- data.put(typesJsArray.get(i), nativeEvent.getDataTransfer()
- .getData(typesJsArray.get(i)));
- }
+ String dataTransferText = nativeEvent.getDataTransfer().getData(
+ DragSourceState.DATA_TYPE_TEXT);
getRpcProxy(DropTargetRpc.class)
- .drop(types, data, getState().dropEffect, data.get(
- DragSourceExtensionConnector.DATA_TYPE_DRAG_SOURCE_ID));
+ .drop(dataTransferText, getState().dropEffect);
}
removeTargetIndicator(getDropTargetElement());
return new Function('event', script)(event);
}-*/;
- private native JsArrayString getTypes(DataTransfer dataTransfer)/*-{
- return dataTransfer.types;
- }-*/;
-
@Override
public DropTargetState getState() {
return (DropTargetState) super.getState();
== Drag Source
-Any component can be made a drag source that has a set of data that is transferred when it is dragged and dropped.
+Any component can be made a drag source that has textual data that is transferred when it is dragged and dropped.
-To make a component a drag source, you apply the [classname]#DragSourceExtension# to it. Then you can define the data to transfer, and the allowed drag effect.
+To make a component a drag source, you apply the [classname]#DragSourceExtension# to it. Then you can define the text to transfer, and the allowed drag effect.
[source, java]
----
// set the allowed effect
dragSource.setEffectAllowed(EffectAllowed.MOVE);
-// set the data to transfer
-dragSource.setTransferData("text/plain", "hello receiver");
+// set the text to transfer
+dragSource.setDataTransferText("hello receiver");
----
The __effect allowed__ specifies the allowed effects that must match the __drop effect__ of the drop target. If these don't match, the drop event is never fired on the target. If multiple effects are allowed, the user can use the modifier keys to switch between the desired effects. The default effect and the modifier keys are system and browser dependent.
-The __transfer data__ is a set of data, that the drop target will receive in the __drop event__. The first parameter given is the type of the data, and the second parameter is the actual data as string. The type parameter thus acts as a key for the actual data. For more information about the
-type parameter, see https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types[MDN recommendations].
+The __data transfer text__ is textual data, that the drop target will receive in the __drop event__.
The [classname]#DragStartEvent# is fired when the drag has started, and the [classname]#DragEndEvent# event when the drag has ended, either in a drop or a cancel.
dropTargetLayout.addComponent(dragSource.get());
// get possible transfer data
- // NOTE that "text" is same as "text/plain" from drag source data,
- // see the HTML5 standard for more info
- String message = event.getTransferData("text");
+ String message = event.getDataTransferText();
Notification.show("DropEvent with data transfer: "+ message);
}
});
*/
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.AbstractComponent;
import com.vaadin.ui.Component;
* @since 8.1
*/
public class DragEndEvent<T extends AbstractComponent> extends Component.Event {
- private final Map<String, String> data;
+ private final String dataTransferText;
private final EffectAllowed effectAllowed;
/**
*
* @param source
* Component that was dragged.
- * @param types
- * List of data types from {@code DataTransfer.types} object.
- * @param data
- * Map containing all types and corresponding data from the {@code
- * DataTransfer} object.
+ * @param dataTransferText
+ * Data of type {@code "text"} from the {@code DataTransfer}
+ * object.
* @param effectAllowed
* Allowed effects from {@code DataTransfer.effectAllowed} object.
*/
- public DragEndEvent(T source, List<String> types, Map<String, String> data,
+ public DragEndEvent(T source, String dataTransferText,
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.dataTransferText = dataTransferText;
this.effectAllowed = effectAllowed;
}
/**
- * Get data from the client side {@code DataTransfer} object.
+ * Get data of type {@code "text"} 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}.
+ * @return Data of type {@code "text"} if exists in the client side {@code
+ * DataTransfer} object, otherwise {@literal null}.
*/
- public String getTransferData(String format) {
- return data != null ? data.get(format) : null;
+ public String getDataTransferText() {
+ return dataTransferText;
}
/**
*/
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.AbstractExtension;
public class DragSourceExtension<T extends AbstractComponent> extends
AbstractExtension {
+ private Registration dragStartListenerHandle;
+ private Registration dragEndListenerHandle;
+
/**
* Extends {@code target} component and makes it a drag source.
*
@Override
public void dragStart() {
DragStartEvent<T> event = new DragStartEvent<>(target,
- getState(false).types, getState(false).data,
+ getState(false).dataTransferText,
getState(false).effectAllowed);
fireEvent(event);
}
@Override
public void dragEnd() {
DragEndEvent<T> event = new DragEndEvent<>(target,
- getState(false).types, getState(false).data,
+ getState(false).dataTransferText,
getState(false).effectAllowed);
fireEvent(event);
}
});
super.extend(target);
+
+ // Set current extension as active drag source in the UI
+ dragStartListenerHandle = addDragStartListener(
+ event -> getUI().setActiveDragSource(this));
+
+ // Remove current extension as active drag source from the UI
+ dragEndListenerHandle = addDragEndListener(
+ event -> getUI().setActiveDragSource(null));
+ }
+
+ @Override
+ public void remove() {
+ super.remove();
+
+ // Remove listeners attached on construction
+ dragStartListenerHandle.remove();
+ dragEndListenerHandle.remove();
}
/**
}
/**
- * 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.
- * <p>
- * 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.
+ * Sets data for this drag source element. The data is set for the client
+ * side draggable element using the {@code DataTransfer.setData("text",
+ * data)} method.
*
- * @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}.
+ * Data to be set for the client side draggable element.
*/
- 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);
+ public void setDataTransferText(String data) {
+ getState().dataTransferText = data;
}
/**
- * Returns the data stored for {@code format} type in this drag source
+ * Returns the data stored with type {@code "text"} 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.
+ * @return Data of type {@code "text"} stored in this drag source element.
*/
- 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<String, String> getTransferData() {
- Map<String, String> data = getState(false).data;
-
- // Create a map of data that preserves the order of types
- LinkedHashMap<String, String> 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);
+ public String getDataTransferText() {
+ return getState(false).dataTransferText;
}
/**
- * Clears all data for this drag source element.
+ * Clears data of type {@code "text"} in this drag source element.
*/
- public void clearTransferData() {
- getState().types.clear();
- getState().data.clear();
+ public void clearDataTransferText() {
+ getState().dataTransferText = null;
}
/**
*/
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.AbstractComponent;
import com.vaadin.ui.Component;
*/
public class DragStartEvent<T extends AbstractComponent> extends
Component.Event {
- private final Map<String, String> data;
+ private final String dataTransferText;
private final EffectAllowed effectAllowed;
/**
*
* @param source
* Component that is dragged.
- * @param types
- * List of data types from {@code DataTransfer.types} object.
- * @param data
- * Map containing all types and corresponding data from the {@code
- * DataTransfer} object.
+ * @param dataTransferText
+ * Data of type {@code "text"} from the {@code DataTransfer}
+ * object.
* @param effectAllowed
* Allowed effects from {@code DataTransfer.effectAllowed} object.
*/
- public DragStartEvent(T source, List<String> types,
- Map<String, String> data, EffectAllowed effectAllowed) {
+ public DragStartEvent(T source, String dataTransferText,
+ 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.dataTransferText = dataTransferText;
this.effectAllowed = effectAllowed;
}
/**
- * Get data from the client side {@code DataTransfer} object.
+ * Get data of type {@code "text"} 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}.
+ * @return Data of type {@code "text"} if exists in the client side {@code
+ * DataTransfer} object, otherwise {@literal null}.
*/
- public String getTransferData(String format) {
- return data != null ? data.get(format) : null;
+ public String getDataTransferText() {
+ return dataTransferText;
}
/**
*/
package com.vaadin.event.dnd;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
import java.util.Optional;
import com.vaadin.shared.ui.dnd.DropEffect;
* @since 8.1
*/
public class DropEvent<T extends AbstractComponent> extends Component.Event {
- private final Map<String, String> data;
+ private final String dataTransferText;
private final DropEffect dropEffect;
- private final DragSourceExtension<AbstractComponent> dragSourceExtension;
+ private final DragSourceExtension<? extends AbstractComponent> dragSourceExtension;
private final AbstractComponent dragSource;
/**
*
* @param target
* Component that received the drop.
- * @param types
- * List of data types from {@code DataTransfer.types} object.
- * @param data
- * Map containing all types and corresponding data from the {@code
- * DataTransfer} object.
+ * @param dataTransferText
+ * Data of type {@code "text"} from the {@code DataTransfer}
+ * object.
* @param dropEffect
* Drop effect from {@code DataTransfer.dropEffect} object.
* @param dragSourceExtension
* Drag source extension of the component that initiated the drop
* event.
*/
- public DropEvent(T target, List<String> types, Map<String, String> data,
- DropEffect dropEffect,
- DragSourceExtension<AbstractComponent> dragSourceExtension) {
+ public DropEvent(T target, String dataTransferText, DropEffect dropEffect,
+ DragSourceExtension<? extends AbstractComponent> dragSourceExtension) {
super(target);
- // 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.dataTransferText = dataTransferText;
this.dropEffect = dropEffect;
}
/**
- * Get data from the client side {@code DataTransfer} object.
+ * Get data of type {@code "text"} 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}.
+ * @return Data of type {@code "text"} if exists in the client side {@code
+ * DataTransfer} object, otherwise {@literal null}.
*/
- public String getTransferData(String format) {
- return data != null ? data.get(format) : null;
+ public String getDataTransferText() {
+ return dataTransferText;
}
/**
*
* @return Drag source extension or an empty optional
*/
- public Optional<DragSourceExtension<AbstractComponent>> getDragSourceExtension() {
+ public Optional<DragSourceExtension<? extends AbstractComponent>> getDragSourceExtension() {
return Optional.ofNullable(dragSourceExtension);
}
import java.util.Objects;
import com.vaadin.server.AbstractExtension;
-import com.vaadin.server.ClientConnector;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.dnd.DropEffect;
import com.vaadin.shared.ui.dnd.DropTargetRpc;
* Component to be extended.
*/
public DropTargetExtension(T target) {
- registerRpc((DropTargetRpc) (types, data, dropEffect, dataSourceId) -> {
- DragSourceExtension dragSource = null;
-
- ClientConnector connector = getUI().getConnectorTracker()
- .getConnector(dataSourceId);
- if (connector != null && connector instanceof DragSourceExtension) {
- dragSource = (DragSourceExtension) connector;
- }
-
- DropEvent<T> event = new DropEvent<>(target, types, data,
- dropEffect, dragSource);
+ registerRpc((DropTargetRpc) (dataTransferText, dropEffect) -> {
+ DropEvent<T> event = new DropEvent<>(target, dataTransferText,
+ dropEffect, getUI().getActiveDragSource());
fireEvent(event);
});
import com.vaadin.event.UIEvents.PollEvent;
import com.vaadin.event.UIEvents.PollListener;
import com.vaadin.event.UIEvents.PollNotifier;
+import com.vaadin.event.dnd.DragSourceExtension;
import com.vaadin.navigator.Navigator;
import com.vaadin.server.ClientConnector;
import com.vaadin.server.ComponentSizeValidator;
*/
private int lastProcessedClientToServerId = -1;
+ /**
+ * Stores the extension of the active drag source component
+ */
+ private DragSourceExtension<? extends AbstractComponent> activeDragSource;
+
/**
* Creates a new empty UI without a caption. The content of the UI must be
* set by calling {@link #setContent(Component)} before using the UI.
WindowOrderUpdateEvent.class, listener);
}
+ /**
+ * Sets the drag source of an active HTML5 drag event.
+ *
+ * @param extension
+ * Extension of the drag source component.
+ * @see DragSourceExtension
+ * @since
+ */
+ public void setActiveDragSource(
+ DragSourceExtension<? extends AbstractComponent> extension) {
+ this.activeDragSource = extension;
+ }
+
+ /**
+ * Gets the drag source of an active HTML5 drag event.
+ *
+ * @return Extension of the drag source component if the drag event is
+ * active and originated from this UI, {@literal null} otherwise.
+ * @see DragSourceExtension
+ * @since
+ */
+ public DragSourceExtension<? extends AbstractComponent> getActiveDragSource() {
+ return this.activeDragSource;
+ }
+
/**
* Event which is fired when the ordering of the windows is updated.
* <p>
// set the allowed effect
dragSource.setEffectAllowed(EffectAllowed.MOVE);
// set the data to transfer
- dragSource.setTransferData("text/plain", "hello receiver");
+ dragSource.setDataTransferText("hello receiver");
dragSource.addDragStartListener(
event -> event.getComponent().addStyleName("dragged"));
dragSource.addDragEndListener(
dropTargetLayout.addComponent(dragSource.get());
// get possible transfer data
- // NOTE that "text" is same as "text/plain" from drag source
- // data
- String message = event.getTransferData("text");
+ String message = event.getDataTransferText();
Notification.show("DropEvent with data transfer: " + message);
}
});
*/
package com.vaadin.shared.ui.dnd;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
import com.vaadin.shared.communication.SharedState;
/**
public static final String EVENT_DRAGSTART = "dragstart";
/**
- * {@code DataTransfer.effectAllowed} parameter for the drag event.
+ * Data type {@code "text"} for storing data in {@code DataTransfer} object.
*/
- public EffectAllowed effectAllowed = EffectAllowed.UNINITIALIZED;
+ public static final String DATA_TYPE_TEXT = "text";
/**
- * {@code DataTransfer.types} parameter. Used to keep track of data formats
- * set for the drag event.
+ * {@code DataTransfer.effectAllowed} parameter for the drag event.
*/
- public List<String> types = new ArrayList<>();
+ public EffectAllowed effectAllowed = EffectAllowed.UNINITIALIZED;
/**
- * Used to store data in the {@code DataTransfer} object for the drag event.
+ * Used to store text data in {@code DataTransfer} object for the drag
+ * event.
*/
- public Map<String, String> data = new HashMap<>();
+ public String dataTransferText;
}
*/
package com.vaadin.shared.ui.dnd;
-import java.util.List;
-import java.util.Map;
-
import com.vaadin.shared.communication.ServerRpc;
/**
/**
* Called when drop event happens on client side.
*
- * @param types
- * Data types that are present in {@code data} map in the same order
- * as found in {@code DataTransfer.types}.
- * @param data
- * Contains data from {@code DataTransfer} object.
+ * @param dataTransferText
+ * Data of type {@code "text"} from the {@code DataTransfer}
+ * object.
* @param dropEffect
* Drop effect set for the drop target where drop happened.
- * @param dragSourceId
- * Drag source component connector's ID.
*/
- public void drop(List<String> types, Map<String, String> data,
- DropEffect dropEffect, String dragSourceId);
+ public void drop(String dataTransferText, DropEffect dropEffect);
}