* 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 changestags/8.1.0.alpha1
@@ -0,0 +1,139 @@ | |||
/* | |||
* 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.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; | |||
import com.vaadin.client.ComponentConnector; | |||
import com.vaadin.client.ServerConnector; | |||
import com.vaadin.event.dnd.DragSourceExtension; | |||
import com.vaadin.shared.ui.Connect; | |||
import com.vaadin.shared.ui.dnd.DragSourceRpc; | |||
import com.vaadin.shared.ui.dnd.DragSourceState; | |||
import elemental.events.Event; | |||
import elemental.events.EventListener; | |||
import elemental.events.EventTarget; | |||
/** | |||
* Extension to add drag source functionality to a widget for using HTML5 drag | |||
* and drop. Client side counterpart of {@link DragSourceExtension}. | |||
*/ | |||
@Connect(DragSourceExtension.class) | |||
public class DragSourceExtensionConnector extends AbstractExtensionConnector { | |||
private static final String CLASS_DRAGGABLE = "v-draggable"; | |||
// Create event listeners | |||
private final EventListener dragStartListener = this::onDragStart; | |||
private final EventListener dragEndListener = this::onDragEnd; | |||
@Override | |||
protected void extend(ServerConnector target) { | |||
Element dragSourceElement = getDraggableElement(); | |||
dragSourceElement.setDraggable(Element.DRAGGABLE_TRUE); | |||
dragSourceElement.addClassName(CLASS_DRAGGABLE); | |||
EventTarget dragSource = dragSourceElement.cast(); | |||
// dragstart | |||
dragSource.addEventListener(Event.DRAGSTART, dragStartListener); | |||
// dragend | |||
dragSource.addEventListener(Event.DRAGEND, dragEndListener); | |||
} | |||
@Override | |||
public void onUnregister() { | |||
super.onUnregister(); | |||
EventTarget dragSource = (EventTarget) getDraggableElement(); | |||
// Remove listeners | |||
dragSource.removeEventListener(Event.DRAGSTART, dragStartListener); | |||
dragSource.removeEventListener(Event.DRAGEND, dragEndListener); | |||
} | |||
/** | |||
* Event handler for the {@code dragstart} event. Called when {@code | |||
* dragstart} event occurs. | |||
* | |||
* @param event | |||
* browser event to be handled | |||
*/ | |||
protected void onDragStart(Event event) { | |||
// Convert elemental event to have access to dataTransfer | |||
NativeEvent nativeEvent = (NativeEvent) event; | |||
// Set effectAllowed parameter | |||
if (getState().effectAllowed != null) { | |||
setEffectAllowed(nativeEvent.getDataTransfer(), | |||
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)); | |||
} | |||
// Initiate firing server side dragstart event when there is a | |||
// DragStartListener attached on the server side | |||
if (hasEventListener(DragSourceState.EVENT_DRAGSTART)) { | |||
getRpcProxy(DragSourceRpc.class).dragStart(); | |||
} | |||
} | |||
/** | |||
* Event handler for the {@code dragend} event. Called when {@code dragend} | |||
* event occurs. | |||
* | |||
* @param event | |||
*/ | |||
protected void onDragEnd(Event event) { | |||
// Initiate server start dragend event when there is a DragEndListener | |||
// attached on the server side | |||
if (hasEventListener(DragSourceState.EVENT_DRAGEND)) { | |||
getRpcProxy(DragSourceRpc.class).dragEnd(); | |||
} | |||
} | |||
/** | |||
* Finds the draggable element within the widget. By default, returns the | |||
* topmost element. | |||
* | |||
* @return the draggable element in the parent widget. | |||
*/ | |||
protected Element getDraggableElement() { | |||
return ((ComponentConnector) getParent()).getWidget().getElement(); | |||
} | |||
private native void setEffectAllowed(DataTransfer dataTransfer, | |||
String effectAllowed)/*-{ | |||
dataTransfer.effectAllowed = effectAllowed; | |||
}-*/; | |||
@Override | |||
public DragSourceState getState() { | |||
return (DragSourceState) super.getState(); | |||
} | |||
} |
@@ -0,0 +1,223 @@ | |||
/* | |||
* 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.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.google.gwt.dom.client.NativeEvent; | |||
import com.vaadin.client.ComponentConnector; | |||
import com.vaadin.client.ServerConnector; | |||
import com.vaadin.event.dnd.DropTargetExtension; | |||
import com.vaadin.shared.ui.Connect; | |||
import com.vaadin.shared.ui.dnd.DropTargetRpc; | |||
import com.vaadin.shared.ui.dnd.DropTargetState; | |||
import elemental.events.Event; | |||
import elemental.events.EventListener; | |||
import elemental.events.EventTarget; | |||
/** | |||
* Extension to add drop target functionality to a widget for using HTML5 drag | |||
* and drop. Client side counterpart of {@link DropTargetExtension}. | |||
*/ | |||
@Connect(DropTargetExtension.class) | |||
public class DropTargetExtensionConnector extends AbstractExtensionConnector { | |||
private static final String CLASS_DRAG_OVER = "v-drag-over"; | |||
// Create event listeners | |||
private final EventListener dragEnterListener = this::onDragEnter; | |||
private final EventListener dragOverListener = this::onDragOver; | |||
private final EventListener dragLeaveListener = this::onDragLeave; | |||
private final EventListener dropListener = this::onDrop; | |||
@Override | |||
protected void extend(ServerConnector target) { | |||
EventTarget dropTarget = getDropTargetElement().cast(); | |||
// dragenter event | |||
dropTarget.addEventListener(BrowserEvents.DRAGENTER, dragEnterListener); | |||
// dragover event | |||
dropTarget.addEventListener(BrowserEvents.DRAGOVER, dragOverListener); | |||
// dragleave event | |||
dropTarget.addEventListener(BrowserEvents.DRAGLEAVE, dragLeaveListener); | |||
// drop event | |||
dropTarget.addEventListener(BrowserEvents.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); | |||
} | |||
/** | |||
* Finds the drop target element within the widget. By default, returns the | |||
* topmost element. | |||
* | |||
* @return the drop target element in the parent widget. | |||
*/ | |||
protected Element getDropTargetElement() { | |||
return ((ComponentConnector) getParent()).getWidget().getElement(); | |||
} | |||
/** | |||
* Event handler for the {@code dragenter} event. | |||
* | |||
* @param event | |||
* browser event to be handled | |||
*/ | |||
protected void onDragEnter(Event event) { | |||
addTargetIndicator(getDropTargetElement()); | |||
} | |||
/** | |||
* Event handler for the {@code dragover} event. | |||
* | |||
* @param event | |||
* browser event to be handled | |||
*/ | |||
protected void onDragOver(Event event) { | |||
NativeEvent nativeEvent = (NativeEvent) event; | |||
if (isDragOverAllowed(nativeEvent)) { | |||
// Set dropEffect parameter | |||
if (getState().dropEffect != null) { | |||
nativeEvent.getDataTransfer().setDropEffect( | |||
DataTransfer.DropEffect | |||
.valueOf(getState().dropEffect.name())); | |||
} | |||
// Prevent default to allow drop | |||
nativeEvent.preventDefault(); | |||
nativeEvent.stopPropagation(); | |||
} else { | |||
// Remove drop effect | |||
nativeEvent.getDataTransfer() | |||
.setDropEffect(DataTransfer.DropEffect.NONE); | |||
// Remove drop target indicator | |||
removeTargetIndicator(getDropTargetElement()); | |||
} | |||
} | |||
/** | |||
* Determines if dragover event is allowed on this drop target according to | |||
* the dragover criteria. | |||
* | |||
* @param event | |||
* Native dragover event. | |||
* @return {@code true} if dragover is allowed, {@code false} otherwise. | |||
* @see DropTargetExtension#setDragOverCriteria(String) | |||
*/ | |||
protected boolean isDragOverAllowed(NativeEvent event) { | |||
if (getState().dragOverCriteria != null) { | |||
return executeScript(event, getState().dragOverCriteria); | |||
} | |||
// Allow when criteria not set | |||
return true; | |||
} | |||
/** | |||
* Event handler for the {@code dragleave} event. | |||
* | |||
* @param event | |||
* browser event to be handled | |||
*/ | |||
protected void onDragLeave(Event event) { | |||
removeTargetIndicator(getDropTargetElement()); | |||
} | |||
/** | |||
* Event handler for the {@code drop} event. | |||
* | |||
* @param event | |||
* browser event to be handled | |||
*/ | |||
protected void onDrop(Event event) { | |||
NativeEvent nativeEvent = (NativeEvent) event; | |||
if (dropAllowed(nativeEvent)) { | |||
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))); | |||
} | |||
getRpcProxy(DropTargetRpc.class) | |||
.drop(types, data, getState().dropEffect); | |||
} | |||
removeTargetIndicator(getDropTargetElement()); | |||
} | |||
private boolean dropAllowed(NativeEvent event) { | |||
if (getState().dropCriteria != null) { | |||
return executeScript(event, getState().dropCriteria); | |||
} | |||
// Allow when criteria not set | |||
return true; | |||
} | |||
private void addTargetIndicator(Element element) { | |||
element.addClassName(CLASS_DRAG_OVER); | |||
} | |||
private void removeTargetIndicator(Element element) { | |||
element.removeClassName(CLASS_DRAG_OVER); | |||
} | |||
private native boolean executeScript(NativeEvent event, String script)/*-{ | |||
return new Function('event', script)(event); | |||
}-*/; | |||
private native JsArrayString getTypes(DataTransfer dataTransfer)/*-{ | |||
return dataTransfer.types; | |||
}-*/; | |||
@Override | |||
public DropTargetState getState() { | |||
return (DropTargetState) super.getState(); | |||
} | |||
} |
@@ -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<String, String> 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<String> types, | |||
Map<String, String> 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; | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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. | |||
* <p> | |||
* 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. | |||
* <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. | |||
* | |||
* @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<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); | |||
} | |||
/** | |||
* 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); | |||
} | |||
} |
@@ -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<String, String> 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<String> types, | |||
Map<String, String> 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; | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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<String, String> 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<String> types, | |||
Map<String, String> 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; | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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. | |||
* <p> | |||
* 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); | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
/* | |||
* 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.dnd; | |||
import com.vaadin.shared.communication.ServerRpc; | |||
/** | |||
* RPC for firing server side event when client side dragstart event happens on | |||
* drag source. | |||
*/ | |||
public interface DragSourceRpc extends ServerRpc { | |||
/** | |||
* Called when dragsource event happens on client side. | |||
*/ | |||
public void dragStart(); | |||
/** | |||
* Called when dragend event happens on client side. | |||
*/ | |||
public void dragEnd(); | |||
} |
@@ -0,0 +1,55 @@ | |||
/* | |||
* 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.dnd; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import com.vaadin.shared.communication.SharedState; | |||
/** | |||
* State class containing parameters for DragSourceExtension. | |||
*/ | |||
public class DragSourceState extends SharedState { | |||
/** | |||
* Event identifier for dragend event. | |||
*/ | |||
public static final String EVENT_DRAGEND = "dragend"; | |||
/** | |||
* Event identifier for dragstart event. | |||
*/ | |||
public static final String EVENT_DRAGSTART = "dragstart"; | |||
/** | |||
* {@code DataTransfer.effectAllowed} parameter for the drag event. | |||
*/ | |||
public EffectAllowed effectAllowed = EffectAllowed.UNINITIALIZED; | |||
/** | |||
* {@code DataTransfer.types} parameter. Used to keep track of data formats | |||
* set for the drag event. | |||
*/ | |||
public List<String> types = new ArrayList<>(); | |||
/** | |||
* Used to store data in the {@code DataTransfer} object for the drag event. | |||
*/ | |||
public Map<String, String> data = new HashMap<>(); | |||
} |
@@ -0,0 +1,41 @@ | |||
/* | |||
* 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.dnd; | |||
/** | |||
* Used to specify the drop effect to use on dragenter or dragover events. | |||
*/ | |||
public enum DropEffect { | |||
/** | |||
* A copy of the source item is made at the new location. | |||
*/ | |||
COPY, | |||
/** | |||
* An item is moved to a new location. | |||
*/ | |||
MOVE, | |||
/** | |||
* A link is established to the source at the new location. | |||
*/ | |||
LINK, | |||
/** | |||
* The item may not be dropped. | |||
*/ | |||
NONE | |||
} |
@@ -0,0 +1,42 @@ | |||
/* | |||
* 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.dnd; | |||
import java.util.List; | |||
import java.util.Map; | |||
import com.vaadin.shared.communication.ServerRpc; | |||
/** | |||
* RPC for firing server side drop event when client side drop event happens on | |||
* drop target. | |||
*/ | |||
public interface DropTargetRpc extends 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 dropEffect | |||
* Drop effect set for the drop target where drop happened. | |||
*/ | |||
public void drop(List<String> types, Map<String, String> data, | |||
DropEffect dropEffect); | |||
} |
@@ -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.shared.ui.dnd; | |||
import com.vaadin.shared.communication.SharedState; | |||
/** | |||
* State class containing parameters for DropTargetExtension. | |||
*/ | |||
public class DropTargetState extends SharedState { | |||
/** | |||
* {@code DataTransfer.dropEffect} parameter for the drag event | |||
*/ | |||
public DropEffect dropEffect; | |||
/** | |||
* Criteria script to allow dragOver event on the element | |||
*/ | |||
public String dragOverCriteria; | |||
/** | |||
* Criteria script to allow drop event on the element | |||
*/ | |||
public String dropCriteria; | |||
} |
@@ -0,0 +1,81 @@ | |||
/* | |||
* 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.dnd; | |||
/** | |||
* Used to specify the effect that is allowed for a drag operation. | |||
*/ | |||
public enum EffectAllowed { | |||
/** | |||
* The item may not be dropped. | |||
*/ | |||
NONE("none"), | |||
/** | |||
* A copy of the source item may be made at the new location. | |||
*/ | |||
COPY("copy"), | |||
/** | |||
* An item may be moved to a new location. | |||
*/ | |||
MOVE("move"), | |||
/** | |||
* A link may be established to the source at the new location. | |||
*/ | |||
LINK("link"), | |||
/** | |||
* A copy or move operation is permitted. | |||
*/ | |||
COPY_MOVE("copyMove"), | |||
/** | |||
* A copy or link operation is permitted. | |||
*/ | |||
COPY_LINK("copyLink"), | |||
/** | |||
* A link or move operation is permitted. | |||
*/ | |||
LINK_MOVE("linkMove"), | |||
/** | |||
* All operations are permitted. | |||
*/ | |||
ALL("all"), | |||
/** | |||
* Default state, equivalent to ALL | |||
*/ | |||
UNINITIALIZED("uninitialized"); | |||
private final String value; | |||
EffectAllowed(String value) { | |||
this.value = value; | |||
} | |||
/** | |||
* Get the string value that is accepted by the client side drag event. | |||
* | |||
* @return String value accepted by the client side drag event. | |||
*/ | |||
public String getValue() { | |||
return value; | |||
} | |||
} |
@@ -345,6 +345,8 @@ $valo-shared-pathPrefix: null; | |||
@include valo-drag-element; | |||
@include valo-draggable; | |||
@include valo-tooltip; | |||
@include valo-contextmenu; |
@@ -275,6 +275,12 @@ $v-selection-item-selection-color: $v-selection-color !default; | |||
} | |||
} | |||
@mixin valo-draggable { | |||
.v-draggable { | |||
user-select: none !important; | |||
} | |||
} | |||
/** | |||
* Outputs the styles for generic dragging ghost elements. | |||
* |
@@ -0,0 +1,153 @@ | |||
/* | |||
* 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.tests.dnd; | |||
import java.util.Optional; | |||
import com.vaadin.event.dnd.DragSourceExtension; | |||
import com.vaadin.event.dnd.DropTargetExtension; | |||
import com.vaadin.server.Extension; | |||
import com.vaadin.server.Page; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUIWithLog; | |||
import com.vaadin.ui.Component; | |||
import com.vaadin.ui.HorizontalLayout; | |||
import com.vaadin.ui.Label; | |||
public class DragAndDropCardShuffle extends AbstractTestUIWithLog { | |||
// Data type for storing card position | |||
private static final String DATA_INDEX = "index"; | |||
// Create cards | |||
private final Label ace = new Label("A"); | |||
private final Label jack = new Label("J"); | |||
private final Label queen = new Label("Q"); | |||
private final Label king = new Label("K"); | |||
// Create desk | |||
private final HorizontalLayout desk = new HorizontalLayout(); | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
// Create UI and add extensions | |||
desk.addComponents(ace, jack, queen, king); | |||
ace.setStyleName("card"); | |||
addDragSourceExtension(ace); | |||
addDropTargetExtension(ace); | |||
jack.setStyleName("card"); | |||
addDragSourceExtension(jack); | |||
addDropTargetExtension(jack); | |||
queen.setStyleName("card"); | |||
addDragSourceExtension(queen); | |||
addDropTargetExtension(queen); | |||
king.setStyleName("card"); | |||
addDragSourceExtension(king); | |||
addDropTargetExtension(king); | |||
addComponent(desk); | |||
// Add styling | |||
setStyle(); | |||
} | |||
private void addDragSourceExtension(Label source) { | |||
// Create and attach extension | |||
DragSourceExtension dragSource = new DragSourceExtension(); | |||
dragSource.extend(source); | |||
// Set component position as transfer data | |||
dragSource.setTransferData(DATA_INDEX, | |||
String.valueOf(desk.getComponentIndex(source))); | |||
// Add listeners | |||
dragSource.addDragStartListener(event -> { | |||
event.getComponent().addStyleName("dragged"); | |||
log(((Label) event.getComponent()).getValue() + " dragstart"); | |||
}); | |||
dragSource.addDragEndListener(event -> { | |||
event.getComponent().removeStyleName("dragged"); | |||
log(((Label) event.getComponent()).getValue() + " dragend"); | |||
}); | |||
} | |||
private void addDropTargetExtension(Label target) { | |||
// Create and attach extension | |||
DropTargetExtension dropTarget = new DropTargetExtension(); | |||
dropTarget.extend(target); | |||
// Add listener | |||
dropTarget.addDropListener(event -> { | |||
// Retrieve the source's position | |||
int sourceIndex = Integer | |||
.valueOf(event.getTransferData(DATA_INDEX)); | |||
// Find source component | |||
Component source = desk.getComponent(sourceIndex); | |||
// Swap source and target components | |||
desk.replaceComponent(target, source); | |||
// Get DragSource extension for target component and set position data | |||
Optional<Extension> targetExt = target.getExtensions().stream() | |||
.filter(e -> e instanceof DragSourceExtension).findFirst(); | |||
targetExt.ifPresent(extension -> { | |||
((DragSourceExtension) extension).setTransferData(DATA_INDEX, | |||
String.valueOf(desk.getComponentIndex(target))); | |||
}); | |||
// Get DragSource extension for source component and set position data | |||
Optional<Extension> sourceExt = source.getExtensions().stream() | |||
.filter(e -> e instanceof DragSourceExtension).findFirst(); | |||
sourceExt.ifPresent(extension -> { | |||
((DragSourceExtension) extension).setTransferData(DATA_INDEX, | |||
String.valueOf(desk.getComponentIndex(source))); | |||
}); | |||
log(((Label) source).getValue() + " dropped onto " + ((Label) event | |||
.getComponent()).getValue()); | |||
}); | |||
} | |||
private void setStyle() { | |||
Page.Styles styles = Page.getCurrent().getStyles(); | |||
styles.add(".card {" | |||
+ "width: 150px;" | |||
+ "height: 200px;" | |||
+ "border: 1px solid black;" | |||
+ "border-radius: 7px;" | |||
+ "padding-left: 10px;" | |||
+ "color: red;" | |||
+ "font-weight: bolder;" | |||
+ "font-size: 25px;" | |||
+ "background-color: gainsboro;" | |||
+ "}"); | |||
styles.add(".v-drag-over {border-style: dashed;}"); | |||
styles.add(".dragged {opacity: .4;}"); | |||
} | |||
@Override | |||
protected String getTestDescription() { | |||
return "Shuffle cards with pure HTML5 drag and drop"; | |||
} | |||
} |