import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.ui.dd.AbstractDropHandler;
-import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager;
-import com.vaadin.terminal.gwt.client.ui.dd.DragEvent;
-import com.vaadin.terminal.gwt.client.ui.dd.HasDropHandler;
-import com.vaadin.terminal.gwt.client.ui.dd.Html5DragEvent;
-import com.vaadin.terminal.gwt.client.ui.dd.Transferable;
+import com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragEvent;
+import com.vaadin.terminal.gwt.client.ui.dd.VHasDropHandler;
+import com.vaadin.terminal.gwt.client.ui.dd.VHtml5DragEvent;
+import com.vaadin.terminal.gwt.client.ui.dd.VTransferable;
public class VDragDropPane extends VAbsoluteLayout implements Container,
- HasDropHandler {
+ VHasDropHandler {
private String paintableId;
/**
* DragEvent is stored here in case of HTML5 drag event.
*/
- private DragEvent vaadinDragEvent;
+ private VDragEvent vaadinDragEvent;
public VDragDropPane() {
super();
.getEventTarget();
Paintable paintable = client.getPaintable((Element) eventTarget
.cast());
- Transferable transferable = new Transferable();
+ VTransferable transferable = new VTransferable();
transferable.setComponent(paintable);
- DragEvent drag = DragAndDropManager.get().startDrag(
+ VDragEvent drag = VDragAndDropManager.get().startDrag(
transferable, event.getNativeEvent(), true);
Element cloneNode = (Element) ((Widget) paintable).getElement()
.cloneNode(true);
}-*/;
- public boolean html5DragEnter(Html5DragEvent event) {
+ public boolean html5DragEnter(VHtml5DragEvent event) {
ApplicationConnection.getConsole().log("HTML 5 Drag Enter");
- Transferable transferable = new Transferable();
+ VTransferable transferable = new VTransferable();
// TODO refine api somehow so that we will now not use the event preview
// method provided by manager
- vaadinDragEvent = DragAndDropManager.get().startDrag(transferable,
+ vaadinDragEvent = VDragAndDropManager.get().startDrag(transferable,
event, false);
event.preventDefault();
event.stopPropagation();
return false;
}
- public boolean html5DragLeave(Html5DragEvent event) {
+ public boolean html5DragLeave(VHtml5DragEvent event) {
ApplicationConnection.getConsole().log("HTML 5 Drag Leave posponed...");
DeferredCommand.addCommand(new Command() {
public void execute() {
return false;
}
- public boolean html5DragOver(Html5DragEvent event) {
+ public boolean html5DragOver(VHtml5DragEvent event) {
ApplicationConnection.getConsole().log("HTML 5 Drag Over");
getDropHandler().dragOver(vaadinDragEvent);
// needed to be set for Safari, otherwise drop will not happen
return false;
}
- public boolean html5DragDrop(Html5DragEvent event) {
+ public boolean html5DragDrop(VHtml5DragEvent event) {
ApplicationConnection.getConsole().log("HTML 5 Drag Drop");
- Transferable transferable = vaadinDragEvent.getTransferrable();
+ VTransferable transferable = vaadinDragEvent.getTransferrable();
JsArrayString types = event.getTypes();
for (int i = 0; i < types.length(); i++) {
transferable.setData("fileContents", fileAsString);
}
- DragAndDropManager.get().endDrag();
+ VDragAndDropManager.get().endDrag();
vaadinDragEvent = null;
event.preventDefault();
event.stopPropagation();
}
}
- private AbstractDropHandler dropHandler;
+ private VAbstractDropHandler dropHandler;
- public AbstractDropHandler getDropHandler() {
+ public VAbstractDropHandler getDropHandler() {
if (dropHandler == null) {
- dropHandler = new AbstractDropHandler() {
+ dropHandler = new VAbstractDropHandler() {
@Override
public Paintable getPaintable() {
}
@Override
- public void dragLeave(DragEvent drag) {
+ public void dragLeave(VDragEvent drag) {
ApplicationConnection.getConsole().log("DragLeave");
getStyleElement().getStyle().setBackgroundColor("yellow");
}
@Override
- public boolean drop(DragEvent drag) {
+ public boolean drop(VDragEvent drag) {
ApplicationConnection.getConsole().log(
"Drop" + drag.sinceStart());
}
@Override
- protected void dragAccepted(DragEvent drag) {
+ protected void dragAccepted(VDragEvent drag) {
getStyleElement().getStyle().setBackgroundColor("green");
}
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.ui.VScrollTable.VScrollTableBody.VScrollTableRow;
-import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager;
-import com.vaadin.terminal.gwt.client.ui.dd.DragEvent;
-import com.vaadin.terminal.gwt.client.ui.dd.Transferable;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragEvent;
+import com.vaadin.terminal.gwt.client.ui.dd.VTransferable;
/**
* VScrollTable
break;
case Event.ONMOUSEMOVE:
if (mDown && dragmode != 0) {
- Transferable transferable = new Transferable();
+ VTransferable transferable = new VTransferable();
transferable.setComponent(VScrollTable.this);
transferable.setItemId("" + rowKey);
// TODO propertyId
- DragEvent ev = DragAndDropManager.get()
+ VDragEvent ev = VDragAndDropManager.get()
.startDrag(transferable, event, true);
Element cloneNode = (Element) getElement()
.cloneNode(true);
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.ValueMap;
-import com.vaadin.terminal.gwt.client.ui.dd.AbstractDropHandler;
-import com.vaadin.terminal.gwt.client.ui.dd.AcceptCallback;
-import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager;
-import com.vaadin.terminal.gwt.client.ui.dd.DragEvent;
-import com.vaadin.terminal.gwt.client.ui.dd.DropHandler;
-import com.vaadin.terminal.gwt.client.ui.dd.HasDropHandler;
-import com.vaadin.terminal.gwt.client.ui.dd.Transferable;
-import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager.DragEventType;
+import com.vaadin.terminal.gwt.client.ui.dd.VAbstractDropHandler;
+import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCallback;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragEvent;
+import com.vaadin.terminal.gwt.client.ui.dd.VDropHandler;
+import com.vaadin.terminal.gwt.client.ui.dd.VHasDropHandler;
+import com.vaadin.terminal.gwt.client.ui.dd.VTransferable;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager.DragEventType;
/**
*
*/
-public class VTree extends FlowPanel implements Paintable, HasDropHandler {
+public class VTree extends FlowPanel implements Paintable, VHasDropHandler {
public static final String CLASSNAME = "v-tree";
private int dragModes;
- private AbstractDropHandler dropHandler;
+ private VAbstractDropHandler dropHandler;
public VTree() {
super();
}
- private void updateTreeRelatedTransferData(DragEvent drag) {
+ private void updateTreeRelatedTransferData(VDragEvent drag) {
drag.getEventDetails().put("itemIdOver", currentMouseOverKey);
if (currentMouseOverKey != null) {
private void updateDropHandler(UIDL childUidl) {
if (dropHandler == null) {
- dropHandler = new AbstractDropHandler() {
+ dropHandler = new VAbstractDropHandler() {
@Override
- public void dragEnter(DragEvent drag) {
+ public void dragEnter(VDragEvent drag) {
updateTreeRelatedTransferData(drag);
super.dragEnter(drag);
}
@Override
- protected void dragAccepted(final DragEvent drag) {
+ protected void dragAccepted(final VDragEvent drag) {
}
@Override
- public void dragOver(final DragEvent currentDrag) {
+ public void dragOver(final VDragEvent currentDrag) {
final Object oldIdOver = currentDrag.getEventDetails().get(
"itemIdOver");
final String oldDetail = (String) currentDrag
+ detail);
updateTreeRelatedTransferData(currentDrag);
- AcceptCallback accpectedCb = new AcceptCallback() {
+ VAcceptCallback accpectedCb = new VAcceptCallback() {
public void handleResponse(
ValueMap responseData) {
if (responseData == null // via client
}
};
if (validateOnServer()) {
- DragAndDropManager.get().visitServer(
+ VDragAndDropManager.get().visitServer(
DragEventType.OVER, accpectedCb);
} else {
}
@Override
- public void dragLeave(DragEvent drag) {
+ public void dragLeave(VDragEvent drag) {
cleanUp();
}
}
@Override
- public boolean drop(DragEvent drag) {
+ public boolean drop(VDragEvent drag) {
cleanUp();
return super.drop(drag);
}
ApplicationConnection.getConsole().log(
"TreeNode drag start " + event.getType());
// start actual drag on slight move when mouse is down
- Transferable t = new Transferable();
+ VTransferable t = new VTransferable();
t.setComponent(VTree.this);
t.setItemId(key);
- DragEvent drag = DragAndDropManager.get().startDrag(t,
+ VDragEvent drag = VDragAndDropManager.get().startDrag(t,
mouseDownEvent, true);
Element node = (Element) nodeCaptionDiv.cloneNode(true);
node.getStyle().setOpacity(0.4);
}
}
- public DropHandler getDropHandler() {
+ public VDropHandler getDropHandler() {
return dropHandler;
}
}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import com.vaadin.terminal.gwt.client.Paintable;
-import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.ValueMap;
-import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager.DragEventType;
-
-public abstract class AbstractDropHandler implements DropHandler {
-
- private boolean serverValidate;
- private UIDL criterioUIDL;
-
- public void updateRules(UIDL uidl) {
- serverValidate = uidl.getBooleanAttribute("serverValidate");
- int childCount = uidl.getChildCount();
- for (int i = 0; i < childCount; i++) {
- UIDL childUIDL = uidl.getChildUIDL(i);
- if (childUIDL.getTag().equals("acceptCriterion")) {
- criterioUIDL = childUIDL;
- // TODO consider parsing the criteria tree here instead of
- // translating uidl during validates()
-
- }
- }
- }
-
- public boolean validateOnServer() {
- return serverValidate;
- }
-
- /**
- * Default implementation does nothing.
- */
- public void dragOver(DragEvent currentDrag) {
-
- }
-
- /**
- * Default implementation does nothing.
- */
- public void dragLeave(DragEvent drag) {
- // TODO Auto-generated method stub
-
- }
-
- /**
- * If transferrable is accepted (either via server visit or client side
- * rules) the default implementation calls {@link #dragAccepted(DragEvent)}
- * method.
- */
- public void dragEnter(final DragEvent drag) {
- if (serverValidate) {
- DragAndDropManager.get().visitServer(DragEventType.ENTER,
- new AcceptCallback() {
- public void handleResponse(ValueMap responseData) {
- if (responseData.containsKey("accepted")) {
- dragAccepted(drag);
- }
- }
- });
- } else if (validates(drag)) {
- dragAccepted(drag);
- }
- }
-
- abstract protected void dragAccepted(DragEvent drag);
-
- /**
- * Returns true if client side rules are met.
- *
- * @param drag
- * @return
- */
- protected boolean validates(DragEvent drag) {
- if (criterioUIDL != null) {
- String criteriaName = criterioUIDL.getStringAttribute("name");
- AcceptCriteria acceptCriteria = AcceptCriterion.get(criteriaName);
- if (acceptCriteria != null) {
- // ApplicationConnection.getConsole().log(
- // "Criteria : " + acceptCriteria.getClass().getName());
- return acceptCriteria.accept(drag, criterioUIDL);
- }
- }
- return false;
- }
-
- public boolean drop(DragEvent drag) {
- if (serverValidate) {
- return true;
- } else {
- return validates(drag);
- }
- }
-
- public abstract Paintable getPaintable();
-
-}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import com.vaadin.terminal.gwt.client.ValueMap;
-
-public interface AcceptCallback {
-
- /**
- * This method is called by {@link DragAndDropManager} if the
- * {@link DragEvent} is still active. Developer can update for example drag
- * icon or target emphasis based on the information returned from server
- * side. If the drag and drop operation ends or the
- * {@link AbstractDropHandler} has changed before response arrives, the
- * method is never called.
- *
- * @param responseData
- */
- public void handleResponse(ValueMap responseData);
-
-}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import com.vaadin.terminal.gwt.client.UIDL;
-
-public interface AcceptCriteria {
-
- public boolean accept(DragEvent drag, UIDL configuration);
-
-}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.google.gwt.core.client.GWT;
-
-public class AcceptCriterion {
- protected static Map<String, AcceptCriteria> criterion = new HashMap<String, AcceptCriteria>();
- private static AcceptCriterionImpl impl;
-
- static {
- impl = GWT.create(AcceptCriterionImpl.class);
- impl.populateCriterionMap(criterion);
- }
-
- public static AcceptCriteria get(String name) {
- return criterion.get(name);
- }
-
-}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import java.util.Map;
-
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.Paintable;
-import com.vaadin.terminal.gwt.client.UIDL;
-
-public class AcceptCriterionImpl {
-
- private final class OverTreeNode implements AcceptCriteria {
- public boolean accept(DragEvent drag, UIDL configuration) {
- Boolean containsKey = (Boolean) drag.getEventDetails().get(
- "itemIdOverIsNode");
- if (containsKey != null && containsKey.booleanValue()) {
- return true;
- }
- return false;
- }
- }
-
- private final class ComponentCriteria implements AcceptCriteria {
- public boolean accept(DragEvent drag, UIDL configuration) {
- try {
- Paintable component = drag.getTransferrable().getComponent();
- String requiredPid = configuration
- .getStringAttribute("component");
- String pid = ((Widget) component).getElement()
- .getPropertyString("tkPid");
- return pid.equals(requiredPid);
- } catch (Exception e) {
- }
- return false;
- }
- }
-
- private final class And implements AcceptCriteria {
- public boolean accept(DragEvent drag, UIDL configuration) {
- UIDL childUIDL = configuration.getChildUIDL(0);
- UIDL childUIDL2 = configuration.getChildUIDL(1);
- AcceptCriteria acceptCriteria = AcceptCriterion.get(childUIDL
- .getStringAttribute("name"));
- AcceptCriteria acceptCriteria2 = AcceptCriterion.get(childUIDL2
- .getStringAttribute("name"));
- if (acceptCriteria == null || acceptCriteria2 == null) {
- ApplicationConnection.getConsole().log(
- "And criteria didn't found a chidl criteria");
- return false;
- }
- boolean accept = acceptCriteria.accept(drag, childUIDL);
- boolean accept2 = acceptCriteria2.accept(drag, childUIDL2);
- return accept && accept2;
- }
- }
-
- private final class AcceptAll implements AcceptCriteria {
- public boolean accept(DragEvent drag, UIDL configuration) {
- return true;
- }
- }
-
- private final class HasItemId implements AcceptCriteria {
- public boolean accept(DragEvent drag, UIDL configuration) {
- return drag.getTransferrable().getItemId() != null;
- }
- }
-
- /**
- * TODO this method could be written by generator
- *
- * TODO consider moving implementations to top level classes
- *
- * TODO use fully qualified names of server side counterparts as keys
- */
- public void populateCriterionMap(Map<String, AcceptCriteria> map) {
- AcceptCriteria crit;
-
- crit = new HasItemId();
- map.put("needsItemId", crit);
-
- crit = new AcceptAll();
- map.put("acceptAll", crit);
-
- crit = new And();
- map.put("and", crit);
-
- crit = new OverTreeNode();
- map.put("overTreeNode", crit);
-
- crit = new ComponentCriteria();
- map.put("component", crit);
-
- }
-}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import com.google.gwt.dom.client.Element;
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.dom.client.Style;
-import com.google.gwt.dom.client.Style.Position;
-import com.google.gwt.dom.client.Style.Unit;
-import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.EventListener;
-import com.google.gwt.user.client.Event.NativePreviewEvent;
-import com.google.gwt.user.client.Event.NativePreviewHandler;
-import com.google.gwt.user.client.ui.RootPanel;
-import com.google.gwt.user.client.ui.Widget;
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.MouseEventDetails;
-import com.vaadin.terminal.gwt.client.Paintable;
-import com.vaadin.terminal.gwt.client.ValueMap;
-
-/**
- * Helper class to manage the state of drag and drop event on Vaadin client
- * side. Can be used to implement most of the drag and drop operation
- * automatically via cross-browser event preview method or just as a helper when
- * implementing own low level drag and drop operation (like with HTML5 api).
- * <p>
- * Singleton. Only one drag and drop operation can be active anyways. Use
- * {@link #get()} to get instance.
- *
- */
-public class DragAndDropManager {
-
- public enum DragEventType {
- ENTER, LEAVE, OVER, DROP
- }
-
- private static final String DD_SERVICE = "DD";
-
- private static DragAndDropManager instance;
- private HandlerRegistration handlerRegistration;
- private DragEvent currentDrag;
-
- /**
- * If dragging is currently on a drophandler, this field has reference to it
- */
- private DropHandler currentDropHandler;
-
- public DropHandler getCurrentDropHandler() {
- return currentDropHandler;
- }
-
- /**
- * If drag and drop operation is not handled by {@link DragAndDropManager}s
- * internal handler, this can be used to update current {@link DropHandler}.
- *
- * @param currentDropHandler
- */
- public void setCurrentDropHandler(DropHandler currentDropHandler) {
- this.currentDropHandler = currentDropHandler;
- }
-
- private AcceptCallback acceptCallback;
-
- public static DragAndDropManager get() {
- if (instance == null) {
- instance = new DragAndDropManager();
- }
- return instance;
- }
-
- /* Singleton */
- private DragAndDropManager() {
- }
-
- /**
- * This method is used to start Vaadin client side drag and drop operation.
- * Operation may be started by virtually any Widget.
- * <p>
- * Cancels possible existing drag. TODO figure out if this is always a bug
- * if one is active. Maybe a good and cheap lifesaver thought.
- * <p>
- * If possible, method automatically detects current {@link DropHandler} and
- * fires {@link DropHandler#dragEnter(DragEvent)} event on it.
- * <p>
- * May also be used to control the drag and drop operation. If this option
- * is used, {@link DropHandler} is searched on mouse events and appropriate
- * methods on it called automatically.
- *
- * @param transferable
- * @param nativeEvent
- * @param handleDragEvents
- * if true, {@link DragAndDropManager} handles the drag and drop
- * operation GWT event preview.
- * @return
- */
- public DragEvent startDrag(Transferable transferable,
- NativeEvent startEvent, boolean handleDragEvents) {
- interruptDrag();
-
- currentDrag = new DragEvent(transferable, startEvent);
- DropHandler dh = null;
- if (startEvent != null) {
- dh = findDragTarget((Element) startEvent.getEventTarget().cast());
- }
- if (dh != null) {
- // drag has started on a DropHandler, kind of drag over happens
- currentDropHandler = dh;
- updateCurrentEvent(startEvent);
- dh.dragEnter(currentDrag);
- }
-
- if (handleDragEvents) {
-
- handlerRegistration = Event
- .addNativePreviewHandler(new NativePreviewHandler() {
-
- public void onPreviewNativeEvent(
- NativePreviewEvent event) {
- updateCurrentEvent(event.getNativeEvent());
- updateDragImagePosition();
-
- NativeEvent nativeEvent = event.getNativeEvent();
- Element targetElement = (Element) nativeEvent
- .getEventTarget().cast();
- if (dragElement != null
- && targetElement.isOrHasChild(dragElement)) {
- ApplicationConnection.getConsole().log(
- "Event on dragImage, ignored");
- event.cancel();
- nativeEvent.stopPropagation();
- return;
- }
-
- int typeInt = event.getTypeInt();
- switch (typeInt) {
- case Event.ONMOUSEOVER:
- ApplicationConnection.getConsole().log(
- event.getNativeEvent().getType());
- DropHandler target = findDragTarget(targetElement);
- if (target != null && target != currentDrag) {
- currentDropHandler = target;
- target.dragEnter(currentDrag);
- } else if (target == null
- && currentDropHandler != null) {
- ApplicationConnection.getConsole().log(
- "Invalid state!?");
- currentDropHandler = null;
- }
- break;
- case Event.ONMOUSEOUT:
- ApplicationConnection.getConsole().log(
- event.getNativeEvent().getType());
-
- Element relatedTarget = (Element) nativeEvent
- .getRelatedEventTarget().cast();
- DropHandler newDragHanler = findDragTarget(relatedTarget);
- if (dragElement != null
- && dragElement
- .isOrHasChild(relatedTarget)) {
- ApplicationConnection.getConsole().log(
- "Mouse out of dragImage, ignored");
- return;
- }
-
- if (currentDropHandler != null
- && currentDropHandler != newDragHanler) {
- currentDropHandler.dragLeave(currentDrag);
- currentDropHandler = null;
- acceptCallback = null;
- }
- break;
- case Event.ONMOUSEMOVE:
- if (currentDropHandler != null) {
- currentDropHandler.dragOver(currentDrag);
- }
- nativeEvent.preventDefault();
-
- break;
-
- case Event.ONMOUSEUP:
- endDrag();
- break;
-
- default:
- break;
- }
-
- }
-
- });
- }
- return currentDrag;
- }
-
- private void interruptDrag() {
- if (currentDrag != null) {
- ApplicationConnection.getConsole()
- .log("Drag operation interrupted");
- if (currentDropHandler != null) {
- currentDrag.currentGwtEvent = null;
- currentDropHandler.dragLeave(currentDrag);
- currentDropHandler = null;
- }
- currentDrag = null;
- }
- }
-
- private void updateDragImagePosition() {
- if (currentDrag.currentGwtEvent != null && dragElement != null) {
- Style style = dragElement.getStyle();
- int clientY = currentDrag.currentGwtEvent.getClientY() + 6;
- int clientX = currentDrag.currentGwtEvent.getClientX() + 6;
- style.setTop(clientY, Unit.PX);
- style.setLeft(clientX, Unit.PX);
- }
- }
-
- /**
- * First seeks the widget from this element, then iterates widgets until one
- * implement HasDropHandler. Returns DropHandler from that.
- *
- * @param element
- * @return
- */
- private DropHandler findDragTarget(Element element) {
-
- EventListener eventListener = Event.getEventListener(element);
- while (eventListener == null) {
- element = element.getParentElement();
- if (element == null) {
- break;
- }
- eventListener = Event.getEventListener(element);
- }
- if (eventListener == null) {
- ApplicationConnection.getConsole().log(
- "No suitable DropHandler found");
- return null;
- } else {
- Widget w = (Widget) eventListener;
- while (!(w instanceof HasDropHandler)) {
- w = w.getParent();
- if (w == null) {
- break;
- }
- }
- if (w == null) {
- ApplicationConnection.getConsole().log(
- "No suitable DropHandler found2");
- return null;
- } else {
- DropHandler dh = ((HasDropHandler) w).getDropHandler();
- if (dh == null) {
- ApplicationConnection.getConsole().log(
- "No suitable DropHandler found3");
- }
- return dh;
- }
- }
- }
-
- private void updateCurrentEvent(NativeEvent event) {
- currentDrag.currentGwtEvent = event;
- }
-
- public void endDrag() {
- if (handlerRegistration != null) {
- handlerRegistration.removeHandler();
- handlerRegistration = null;
- }
- if (currentDropHandler != null) {
- // we have dropped on a drop target
- boolean sendTransferrableToServer = currentDropHandler
- .drop(currentDrag);
- if (sendTransferrableToServer) {
- doRequest(DragEventType.DROP);
- }
- currentDropHandler = null;
- acceptCallback = null;
-
- }
-
- currentDrag = null;
-
- if (dragElement != null) {
- RootPanel.getBodyElement().removeChild(dragElement);
- dragElement = null;
- }
- }
-
- private int visitId = 0;
- private Element dragElement;
-
- /**
- * Visits server during drag and drop procedure. Transferable and event type
- * is given to server side counterpart of DropHandler.
- *
- * If another server visit is started before the current is received, the
- * current is just dropped. TODO consider if callback should have
- * interrupted() method for cleanup.
- *
- * @param acceptCallback
- */
- public void visitServer(DragEventType type, AcceptCallback acceptCallback) {
- doRequest(type);
- this.acceptCallback = acceptCallback;
- }
-
- private void doRequest(DragEventType drop) {
- Paintable paintable = currentDropHandler.getPaintable();
- ApplicationConnection client = currentDropHandler
- .getApplicationConnection();
- /*
- * For drag events we are using special id that are routed to
- * "drag service" which then again finds the corresponding DropHandler
- * on server side.
- *
- * TODO add rest of the data in Transferable
- *
- * TODO implement partial updates to Transferable (currently the whole
- * Transferable is sent on each request)
- */
- visitId++;
- client.updateVariable(DD_SERVICE, "visitId", visitId, false);
- client.updateVariable(DD_SERVICE, "eventId", currentDrag.getEventId(),
- false);
- client.updateVariable(DD_SERVICE, "dhowner", paintable, false);
-
- Transferable transferable = currentDrag.getTransferrable();
-
- if (transferable.getItemId() != null) {
- client.updateVariable(DD_SERVICE, "itemId", transferable
- .getItemId(), false);
- }
- if (transferable.getPropertyId() != null) {
- client.updateVariable(DD_SERVICE, "propertyId", transferable
- .getPropertyId(), false);
- }
-
- client.updateVariable(DD_SERVICE, "component", transferable
- .getComponent(), false);
-
- client.updateVariable(DD_SERVICE, "type", drop.ordinal(), false);
-
- if (currentDrag.currentGwtEvent != null) {
- try {
- MouseEventDetails mouseEventDetails = new MouseEventDetails(
- currentDrag.currentGwtEvent);
- currentDrag.getEventDetails().put("mouseEvent",
- mouseEventDetails.serialize());
- } catch (Exception e) {
- // NOP, (at least oophm on Safari) can't serialize html dd event
- // to
- // mouseevent
- }
- } else {
- currentDrag.getEventDetails().put("mouseEvent", null);
- }
- client.updateVariable(DD_SERVICE, "evt", currentDrag.getEventDetails(),
- false);
-
- client.updateVariable(DD_SERVICE, "tra", transferable.getVariableMap(),
- true);
-
- }
-
- public void handleServerResponse(ValueMap valueMap) {
- if (acceptCallback == null) {
- return;
- }
- int visitId = valueMap.getInt("visitId");
- if (this.visitId == visitId) {
- acceptCallback.handleResponse(valueMap);
- acceptCallback = null;
- }
- }
-
- void setDragElement(Element node) {
- if (currentDrag != null) {
- if (dragElement != null && dragElement != node) {
- RootPanel.getBodyElement().removeChild(dragElement);
- } else if (node == dragElement) {
- return;
- }
-
- dragElement = node;
- Style style = node.getStyle();
- style.setPosition(Position.ABSOLUTE);
- style.setZIndex(600000);
- RootPanel.getBodyElement().appendChild(node);
- }
- }
-
-}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.user.client.Element;
-
-/**
- * DragEvent used by Vaadin client side engine. Supports components, items,
- * properties and custom payload (HTML5 style).
- *
- *
- */
-public class DragEvent {
-
- private static int eventId = 0;
-
- private Transferable transferable;
-
- NativeEvent currentGwtEvent;
-
- private NativeEvent startEvent;
-
- private int id;
-
- private Date start;
-
- private HashMap<String, Object> dropDetails = new HashMap<String, Object>();
-
- DragEvent(Transferable t, NativeEvent startEvent) {
- transferable = t;
- this.startEvent = startEvent;
- id = eventId++;
- start = new Date();
- }
-
- public Transferable getTransferrable() {
- return transferable;
- }
-
- public NativeEvent getCurrentGwtEvent() {
- return currentGwtEvent;
- }
-
- public int getEventId() {
- return id;
- }
-
- public long sinceStart() {
- return new Date().getTime() - start.getTime();
- }
-
- /**
- * Sets the element that will be used as "drag icon".
- *
- * TODO decide if this method should be here or in {@link Transferable} (in
- * HTML5 it is in DataTransfer) or {@link DragAndDropManager}
- *
- * TODO should be possible to override behaviour an set to HTML5
- * DataTransfer
- *
- * @param node
- */
- public void setDragImage(Element node) {
- DragAndDropManager.get().setDragElement(node);
- }
-
- /**
- * TODO consider using similar smaller (than map) api as in Transferable
- *
- * TODO clean up when drop handler changes
- *
- * @return
- */
- public Map<String, Object> getEventDetails() {
- return dropDetails;
- }
-
-}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import com.vaadin.terminal.gwt.client.ApplicationConnection;
-import com.vaadin.terminal.gwt.client.Paintable;
-
-/**
- * Vaadin Widgets (TODO or Paintables, see {@link HasDropHandler}) that want to
- * receive something via drag and drop implement this interface.
- */
-public interface DropHandler {
-
- /**
- * Called by D'D' manager when drag gets over this drop handler.
- *
- * @param drag
- */
- public void dragEnter(DragEvent drag);
-
- /**
- * Called by D'D' manager when drag gets out this drop handler.
- *
- * @param drag
- */
- public void dragLeave(DragEvent drag);
-
- /**
- * The actual drop happened on this drop handler.
- *
- * @param drag
- * @return true if Tranferrable of this drag event needs to be sent to
- * server, false if drop was finally canceled or no server visit is
- * needed
- */
- public boolean drop(DragEvent drag);
-
- /**
- * When drag is over current drag handler.
- *
- * With drag implementation by {@link DragAndDropManager} will be called
- * when mouse is moved. HTML5 implementations call this continuously even
- * though mouse is not moved.
- *
- * @param currentDrag
- */
- public void dragOver(DragEvent currentDrag);
-
- /**
- * Returns the Paintable into which this DragHandler is assosiated
- */
- public Paintable getPaintable();
-
- /**
- * Returns the application connection to which this {@link DropHandler}
- * belongs to. DragAndDropManager uses this fucction to send Transferable to
- * server side.
- */
- public ApplicationConnection getApplicationConnection();
-
-}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import com.vaadin.terminal.gwt.client.Paintable;
-
-/**
- * Used to detect Widget from widget tree that has {@link #getDropHandler()}
- *
- * Decide whether to get rid of this class. If so, {@link AbstractDropHandler} must
- * extend {@link Paintable}.
- *
- */
-public interface HasDropHandler {
- public DropHandler getDropHandler();
-}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import com.google.gwt.core.client.JsArrayString;
-import com.google.gwt.dom.client.NativeEvent;
-
-public class Html5DragEvent extends NativeEvent {
- protected Html5DragEvent() {
- }
-
- public final native JsArrayString getTypes()
- /*-{
- return this.dataTransfer.types;
- }-*/;
-
- public final native String getDataAsText(String type)
- /*-{
- var v = this.dataTransfer.getData(type);
- return v;
- }-*/;
-
- /**
- * Works on FF 3.6 and possibly with gears.
- *
- * @param index
- * @return
- */
- public final native String getFileAsString(int index)
- /*-{
- if(this.dataTransfer.files.length > 0 && this.dataTransfer.files[0].getAsText) {
- return this.dataTransfer.files[index].getAsText("UTF-8");
- }
- return null;
- }-*/;
-
- public final native void setDragEffect(String effect)
- /*-{
- try {
- this.dataTransfer.dropEffect = effect;
- } catch (e){}
- }-*/;
-
- public final native String getEffectAllowed()
- /*-{
- return this.dataTransfer.effectAllowed;
- }-*/;
-}
+++ /dev/null
-package com.vaadin.terminal.gwt.client.ui.dd;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.vaadin.terminal.DragSource;
-import com.vaadin.terminal.gwt.client.Paintable;
-
-/**
- * Client side counterpart for Transferable in com.vaadin.event.Transferable
- *
- */
-public class Transferable {
-
- /**
- * @return the component
- */
- public Paintable getComponent() {
- return component;
- }
-
- /**
- * @param component
- * the component to set
- */
- public void setComponent(Paintable component) {
- this.component = component;
- }
-
- /**
- * This is commonly actually a key to property id on client side than the
- * actual propertyId.
- *
- * Translated by terminal and {@link DragSource}
- *
- * @return the propertyId
- */
- public String getPropertyId() {
- return (String) variables.get("propertyId");
- }
-
- /**
- * This is commonly actually a key to property id on client side than the
- * actual propertyId.
- *
- * Translated by terminal and {@link DragSource}
- *
- * @param propertyId
- * the propertyId to set
- */
- public void setPropertyId(String propertyId) {
- variables.put("propertyId", propertyId);
- }
-
- /**
- * @return the itemId
- */
- public String getItemId() {
- return (String) variables.get("itemId");
- }
-
- /**
- * This is commonly actually a key to item id on client side than the actual
- * itemId.
- *
- * Translated by terminal and {@link DragSource}
- *
- * @param itemId
- * the itemId to set
- */
- public void setItemId(String itemId) {
- variables.put("itemId", itemId);
- }
-
- private Paintable component;
-
- public Object getData(String dataFlawor) {
- return variables.get(dataFlawor);
- }
-
- public void setData(String dataFlawor, Object value) {
- variables.put(dataFlawor, value);
- }
-
- public Collection<String> getDataFlawors() {
- return variables.keySet();
- }
-
- private final Map<String, Object> variables = new HashMap<String, Object>();
-
- /**
- * This method should only be called by {@link DragAndDropManager}.
- *
- * @return data in this Transferable that needs to be moved to server.
- */
- public Map<String, Object> getVariableMap() {
- return variables;
- }
-
-}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import com.vaadin.terminal.gwt.client.Paintable;
+import com.vaadin.terminal.gwt.client.UIDL;
+import com.vaadin.terminal.gwt.client.ValueMap;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager.DragEventType;
+
+public abstract class VAbstractDropHandler implements VDropHandler {
+
+ private boolean serverValidate;
+ private UIDL criterioUIDL;
+
+ public void updateRules(UIDL uidl) {
+ serverValidate = uidl.getBooleanAttribute("serverValidate");
+ int childCount = uidl.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ UIDL childUIDL = uidl.getChildUIDL(i);
+ if (childUIDL.getTag().equals("acceptCriterion")) {
+ criterioUIDL = childUIDL;
+ // TODO consider parsing the criteria tree here instead of
+ // translating uidl during validates()
+
+ }
+ }
+ }
+
+ public boolean validateOnServer() {
+ return serverValidate;
+ }
+
+ /**
+ * Default implementation does nothing.
+ */
+ public void dragOver(VDragEvent currentDrag) {
+
+ }
+
+ /**
+ * Default implementation does nothing.
+ */
+ public void dragLeave(VDragEvent drag) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * If transferrable is accepted (either via server visit or client side
+ * rules) the default implementation calls {@link #dragAccepted(VDragEvent)}
+ * method.
+ */
+ public void dragEnter(final VDragEvent drag) {
+ if (serverValidate) {
+ VDragAndDropManager.get().visitServer(DragEventType.ENTER,
+ new VAcceptCallback() {
+ public void handleResponse(ValueMap responseData) {
+ if (responseData.containsKey("accepted")) {
+ dragAccepted(drag);
+ }
+ }
+ });
+ } else if (validates(drag)) {
+ dragAccepted(drag);
+ }
+ }
+
+ abstract protected void dragAccepted(VDragEvent drag);
+
+ /**
+ * Returns true if client side rules are met.
+ *
+ * @param drag
+ * @return
+ */
+ protected boolean validates(VDragEvent drag) {
+ if (criterioUIDL != null) {
+ String criteriaName = criterioUIDL.getStringAttribute("name");
+ VAcceptCriteria acceptCriteria = VAcceptCriterion.get(criteriaName);
+ if (acceptCriteria != null) {
+ // ApplicationConnection.getConsole().log(
+ // "Criteria : " + acceptCriteria.getClass().getName());
+ return acceptCriteria.accept(drag, criterioUIDL);
+ }
+ }
+ return false;
+ }
+
+ public boolean drop(VDragEvent drag) {
+ if (serverValidate) {
+ return true;
+ } else {
+ return validates(drag);
+ }
+ }
+
+ public abstract Paintable getPaintable();
+
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import com.vaadin.terminal.gwt.client.ValueMap;
+
+public interface VAcceptCallback {
+
+ /**
+ * This method is called by {@link VDragAndDropManager} if the
+ * {@link VDragEvent} is still active. Developer can update for example drag
+ * icon or target emphasis based on the information returned from server
+ * side. If the drag and drop operation ends or the
+ * {@link VAbstractDropHandler} has changed before response arrives, the
+ * method is never called.
+ *
+ * @param responseData
+ */
+ public void handleResponse(ValueMap responseData);
+
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import com.vaadin.terminal.gwt.client.UIDL;
+
+public interface VAcceptCriteria {
+
+ public boolean accept(VDragEvent drag, UIDL configuration);
+
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gwt.core.client.GWT;
+
+public class VAcceptCriterion {
+ protected static Map<String, VAcceptCriteria> criterion = new HashMap<String, VAcceptCriteria>();
+ private static VAcceptCriterionImpl impl;
+
+ static {
+ impl = GWT.create(VAcceptCriterionImpl.class);
+ impl.populateCriterionMap(criterion);
+ }
+
+ public static VAcceptCriteria get(String name) {
+ return criterion.get(name);
+ }
+
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import java.util.Map;
+
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.Paintable;
+import com.vaadin.terminal.gwt.client.UIDL;
+
+public class VAcceptCriterionImpl {
+
+ private final class OverTreeNode implements VAcceptCriteria {
+ public boolean accept(VDragEvent drag, UIDL configuration) {
+ Boolean containsKey = (Boolean) drag.getEventDetails().get(
+ "itemIdOverIsNode");
+ if (containsKey != null && containsKey.booleanValue()) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ private final class ComponentCriteria implements VAcceptCriteria {
+ public boolean accept(VDragEvent drag, UIDL configuration) {
+ try {
+ Paintable component = drag.getTransferrable().getComponent();
+ String requiredPid = configuration
+ .getStringAttribute("component");
+ String pid = ((Widget) component).getElement()
+ .getPropertyString("tkPid");
+ return pid.equals(requiredPid);
+ } catch (Exception e) {
+ }
+ return false;
+ }
+ }
+
+ private final class And implements VAcceptCriteria {
+ public boolean accept(VDragEvent drag, UIDL configuration) {
+ UIDL childUIDL = configuration.getChildUIDL(0);
+ UIDL childUIDL2 = configuration.getChildUIDL(1);
+ VAcceptCriteria acceptCriteria = VAcceptCriterion.get(childUIDL
+ .getStringAttribute("name"));
+ VAcceptCriteria acceptCriteria2 = VAcceptCriterion.get(childUIDL2
+ .getStringAttribute("name"));
+ if (acceptCriteria == null || acceptCriteria2 == null) {
+ ApplicationConnection.getConsole().log(
+ "And criteria didn't found a chidl criteria");
+ return false;
+ }
+ boolean accept = acceptCriteria.accept(drag, childUIDL);
+ boolean accept2 = acceptCriteria2.accept(drag, childUIDL2);
+ return accept && accept2;
+ }
+ }
+
+ private final class AcceptAll implements VAcceptCriteria {
+ public boolean accept(VDragEvent drag, UIDL configuration) {
+ return true;
+ }
+ }
+
+ private final class HasItemId implements VAcceptCriteria {
+ public boolean accept(VDragEvent drag, UIDL configuration) {
+ return drag.getTransferrable().getItemId() != null;
+ }
+ }
+
+ /**
+ * TODO this method could be written by generator
+ *
+ * TODO consider moving implementations to top level classes
+ *
+ * TODO use fully qualified names of server side counterparts as keys
+ */
+ public void populateCriterionMap(Map<String, VAcceptCriteria> map) {
+ VAcceptCriteria crit;
+
+ crit = new HasItemId();
+ map.put("needsItemId", crit);
+
+ crit = new AcceptAll();
+ map.put("acceptAll", crit);
+
+ crit = new And();
+ map.put("and", crit);
+
+ crit = new OverTreeNode();
+ map.put("overTreeNode", crit);
+
+ crit = new ComponentCriteria();
+ map.put("component", crit);
+
+ }
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Position;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.EventListener;
+import com.google.gwt.user.client.Event.NativePreviewEvent;
+import com.google.gwt.user.client.Event.NativePreviewHandler;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.MouseEventDetails;
+import com.vaadin.terminal.gwt.client.Paintable;
+import com.vaadin.terminal.gwt.client.ValueMap;
+
+/**
+ * Helper class to manage the state of drag and drop event on Vaadin client
+ * side. Can be used to implement most of the drag and drop operation
+ * automatically via cross-browser event preview method or just as a helper when
+ * implementing own low level drag and drop operation (like with HTML5 api).
+ * <p>
+ * Singleton. Only one drag and drop operation can be active anyways. Use
+ * {@link #get()} to get instance.
+ *
+ */
+public class VDragAndDropManager {
+
+ public enum DragEventType {
+ ENTER, LEAVE, OVER, DROP
+ }
+
+ private static final String DD_SERVICE = "DD";
+
+ private static VDragAndDropManager instance;
+ private HandlerRegistration handlerRegistration;
+ private VDragEvent currentDrag;
+
+ /**
+ * If dragging is currently on a drophandler, this field has reference to it
+ */
+ private VDropHandler currentDropHandler;
+
+ public VDropHandler getCurrentDropHandler() {
+ return currentDropHandler;
+ }
+
+ /**
+ * If drag and drop operation is not handled by {@link VDragAndDropManager}s
+ * internal handler, this can be used to update current {@link VDropHandler}.
+ *
+ * @param currentDropHandler
+ */
+ public void setCurrentDropHandler(VDropHandler currentDropHandler) {
+ this.currentDropHandler = currentDropHandler;
+ }
+
+ private VAcceptCallback acceptCallback;
+
+ public static VDragAndDropManager get() {
+ if (instance == null) {
+ instance = new VDragAndDropManager();
+ }
+ return instance;
+ }
+
+ /* Singleton */
+ private VDragAndDropManager() {
+ }
+
+ /**
+ * This method is used to start Vaadin client side drag and drop operation.
+ * Operation may be started by virtually any Widget.
+ * <p>
+ * Cancels possible existing drag. TODO figure out if this is always a bug
+ * if one is active. Maybe a good and cheap lifesaver thought.
+ * <p>
+ * If possible, method automatically detects current {@link VDropHandler} and
+ * fires {@link VDropHandler#dragEnter(VDragEvent)} event on it.
+ * <p>
+ * May also be used to control the drag and drop operation. If this option
+ * is used, {@link VDropHandler} is searched on mouse events and appropriate
+ * methods on it called automatically.
+ *
+ * @param transferable
+ * @param nativeEvent
+ * @param handleDragEvents
+ * if true, {@link VDragAndDropManager} handles the drag and drop
+ * operation GWT event preview.
+ * @return
+ */
+ public VDragEvent startDrag(VTransferable transferable,
+ NativeEvent startEvent, boolean handleDragEvents) {
+ interruptDrag();
+
+ currentDrag = new VDragEvent(transferable, startEvent);
+ VDropHandler dh = null;
+ if (startEvent != null) {
+ dh = findDragTarget((Element) startEvent.getEventTarget().cast());
+ }
+ if (dh != null) {
+ // drag has started on a DropHandler, kind of drag over happens
+ currentDropHandler = dh;
+ updateCurrentEvent(startEvent);
+ dh.dragEnter(currentDrag);
+ }
+
+ if (handleDragEvents) {
+
+ handlerRegistration = Event
+ .addNativePreviewHandler(new NativePreviewHandler() {
+
+ public void onPreviewNativeEvent(
+ NativePreviewEvent event) {
+ updateCurrentEvent(event.getNativeEvent());
+ updateDragImagePosition();
+
+ NativeEvent nativeEvent = event.getNativeEvent();
+ Element targetElement = (Element) nativeEvent
+ .getEventTarget().cast();
+ if (dragElement != null
+ && targetElement.isOrHasChild(dragElement)) {
+ ApplicationConnection.getConsole().log(
+ "Event on dragImage, ignored");
+ event.cancel();
+ nativeEvent.stopPropagation();
+ return;
+ }
+
+ int typeInt = event.getTypeInt();
+ switch (typeInt) {
+ case Event.ONMOUSEOVER:
+ ApplicationConnection.getConsole().log(
+ event.getNativeEvent().getType());
+ VDropHandler target = findDragTarget(targetElement);
+ if (target != null && target != currentDrag) {
+ currentDropHandler = target;
+ target.dragEnter(currentDrag);
+ } else if (target == null
+ && currentDropHandler != null) {
+ ApplicationConnection.getConsole().log(
+ "Invalid state!?");
+ currentDropHandler = null;
+ }
+ break;
+ case Event.ONMOUSEOUT:
+ ApplicationConnection.getConsole().log(
+ event.getNativeEvent().getType());
+
+ Element relatedTarget = (Element) nativeEvent
+ .getRelatedEventTarget().cast();
+ VDropHandler newDragHanler = findDragTarget(relatedTarget);
+ if (dragElement != null
+ && dragElement
+ .isOrHasChild(relatedTarget)) {
+ ApplicationConnection.getConsole().log(
+ "Mouse out of dragImage, ignored");
+ return;
+ }
+
+ if (currentDropHandler != null
+ && currentDropHandler != newDragHanler) {
+ currentDropHandler.dragLeave(currentDrag);
+ currentDropHandler = null;
+ acceptCallback = null;
+ }
+ break;
+ case Event.ONMOUSEMOVE:
+ if (currentDropHandler != null) {
+ currentDropHandler.dragOver(currentDrag);
+ }
+ nativeEvent.preventDefault();
+
+ break;
+
+ case Event.ONMOUSEUP:
+ endDrag();
+ break;
+
+ default:
+ break;
+ }
+
+ }
+
+ });
+ }
+ return currentDrag;
+ }
+
+ private void interruptDrag() {
+ if (currentDrag != null) {
+ ApplicationConnection.getConsole()
+ .log("Drag operation interrupted");
+ if (currentDropHandler != null) {
+ currentDrag.currentGwtEvent = null;
+ currentDropHandler.dragLeave(currentDrag);
+ currentDropHandler = null;
+ }
+ currentDrag = null;
+ }
+ }
+
+ private void updateDragImagePosition() {
+ if (currentDrag.currentGwtEvent != null && dragElement != null) {
+ Style style = dragElement.getStyle();
+ int clientY = currentDrag.currentGwtEvent.getClientY() + 6;
+ int clientX = currentDrag.currentGwtEvent.getClientX() + 6;
+ style.setTop(clientY, Unit.PX);
+ style.setLeft(clientX, Unit.PX);
+ }
+ }
+
+ /**
+ * First seeks the widget from this element, then iterates widgets until one
+ * implement HasDropHandler. Returns DropHandler from that.
+ *
+ * @param element
+ * @return
+ */
+ private VDropHandler findDragTarget(Element element) {
+
+ EventListener eventListener = Event.getEventListener(element);
+ while (eventListener == null) {
+ element = element.getParentElement();
+ if (element == null) {
+ break;
+ }
+ eventListener = Event.getEventListener(element);
+ }
+ if (eventListener == null) {
+ ApplicationConnection.getConsole().log(
+ "No suitable DropHandler found");
+ return null;
+ } else {
+ Widget w = (Widget) eventListener;
+ while (!(w instanceof VHasDropHandler)) {
+ w = w.getParent();
+ if (w == null) {
+ break;
+ }
+ }
+ if (w == null) {
+ ApplicationConnection.getConsole().log(
+ "No suitable DropHandler found2");
+ return null;
+ } else {
+ VDropHandler dh = ((VHasDropHandler) w).getDropHandler();
+ if (dh == null) {
+ ApplicationConnection.getConsole().log(
+ "No suitable DropHandler found3");
+ }
+ return dh;
+ }
+ }
+ }
+
+ private void updateCurrentEvent(NativeEvent event) {
+ currentDrag.currentGwtEvent = event;
+ }
+
+ public void endDrag() {
+ if (handlerRegistration != null) {
+ handlerRegistration.removeHandler();
+ handlerRegistration = null;
+ }
+ if (currentDropHandler != null) {
+ // we have dropped on a drop target
+ boolean sendTransferrableToServer = currentDropHandler
+ .drop(currentDrag);
+ if (sendTransferrableToServer) {
+ doRequest(DragEventType.DROP);
+ }
+ currentDropHandler = null;
+ acceptCallback = null;
+
+ }
+
+ currentDrag = null;
+
+ if (dragElement != null) {
+ RootPanel.getBodyElement().removeChild(dragElement);
+ dragElement = null;
+ }
+ }
+
+ private int visitId = 0;
+ private Element dragElement;
+
+ /**
+ * Visits server during drag and drop procedure. Transferable and event type
+ * is given to server side counterpart of DropHandler.
+ *
+ * If another server visit is started before the current is received, the
+ * current is just dropped. TODO consider if callback should have
+ * interrupted() method for cleanup.
+ *
+ * @param acceptCallback
+ */
+ public void visitServer(DragEventType type, VAcceptCallback acceptCallback) {
+ doRequest(type);
+ this.acceptCallback = acceptCallback;
+ }
+
+ private void doRequest(DragEventType drop) {
+ Paintable paintable = currentDropHandler.getPaintable();
+ ApplicationConnection client = currentDropHandler
+ .getApplicationConnection();
+ /*
+ * For drag events we are using special id that are routed to
+ * "drag service" which then again finds the corresponding DropHandler
+ * on server side.
+ *
+ * TODO add rest of the data in Transferable
+ *
+ * TODO implement partial updates to Transferable (currently the whole
+ * Transferable is sent on each request)
+ */
+ visitId++;
+ client.updateVariable(DD_SERVICE, "visitId", visitId, false);
+ client.updateVariable(DD_SERVICE, "eventId", currentDrag.getEventId(),
+ false);
+ client.updateVariable(DD_SERVICE, "dhowner", paintable, false);
+
+ VTransferable transferable = currentDrag.getTransferrable();
+
+ if (transferable.getItemId() != null) {
+ client.updateVariable(DD_SERVICE, "itemId", transferable
+ .getItemId(), false);
+ }
+ if (transferable.getPropertyId() != null) {
+ client.updateVariable(DD_SERVICE, "propertyId", transferable
+ .getPropertyId(), false);
+ }
+
+ client.updateVariable(DD_SERVICE, "component", transferable
+ .getComponent(), false);
+
+ client.updateVariable(DD_SERVICE, "type", drop.ordinal(), false);
+
+ if (currentDrag.currentGwtEvent != null) {
+ try {
+ MouseEventDetails mouseEventDetails = new MouseEventDetails(
+ currentDrag.currentGwtEvent);
+ currentDrag.getEventDetails().put("mouseEvent",
+ mouseEventDetails.serialize());
+ } catch (Exception e) {
+ // NOP, (at least oophm on Safari) can't serialize html dd event
+ // to
+ // mouseevent
+ }
+ } else {
+ currentDrag.getEventDetails().put("mouseEvent", null);
+ }
+ client.updateVariable(DD_SERVICE, "evt", currentDrag.getEventDetails(),
+ false);
+
+ client.updateVariable(DD_SERVICE, "tra", transferable.getVariableMap(),
+ true);
+
+ }
+
+ public void handleServerResponse(ValueMap valueMap) {
+ if (acceptCallback == null) {
+ return;
+ }
+ int visitId = valueMap.getInt("visitId");
+ if (this.visitId == visitId) {
+ acceptCallback.handleResponse(valueMap);
+ acceptCallback = null;
+ }
+ }
+
+ void setDragElement(Element node) {
+ if (currentDrag != null) {
+ if (dragElement != null && dragElement != node) {
+ RootPanel.getBodyElement().removeChild(dragElement);
+ } else if (node == dragElement) {
+ return;
+ }
+
+ dragElement = node;
+ Style style = node.getStyle();
+ style.setPosition(Position.ABSOLUTE);
+ style.setZIndex(600000);
+ RootPanel.getBodyElement().appendChild(node);
+ }
+ }
+
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.user.client.Element;
+
+/**
+ * DragEvent used by Vaadin client side engine. Supports components, items,
+ * properties and custom payload (HTML5 style).
+ *
+ *
+ */
+public class VDragEvent {
+
+ private static int eventId = 0;
+
+ private VTransferable transferable;
+
+ NativeEvent currentGwtEvent;
+
+ private NativeEvent startEvent;
+
+ private int id;
+
+ private Date start;
+
+ private HashMap<String, Object> dropDetails = new HashMap<String, Object>();
+
+ VDragEvent(VTransferable t, NativeEvent startEvent) {
+ transferable = t;
+ this.startEvent = startEvent;
+ id = eventId++;
+ start = new Date();
+ }
+
+ public VTransferable getTransferrable() {
+ return transferable;
+ }
+
+ public NativeEvent getCurrentGwtEvent() {
+ return currentGwtEvent;
+ }
+
+ public int getEventId() {
+ return id;
+ }
+
+ public long sinceStart() {
+ return new Date().getTime() - start.getTime();
+ }
+
+ /**
+ * Sets the element that will be used as "drag icon".
+ *
+ * TODO decide if this method should be here or in {@link VTransferable} (in
+ * HTML5 it is in DataTransfer) or {@link VDragAndDropManager}
+ *
+ * TODO should be possible to override behaviour an set to HTML5
+ * DataTransfer
+ *
+ * @param node
+ */
+ public void setDragImage(Element node) {
+ VDragAndDropManager.get().setDragElement(node);
+ }
+
+ /**
+ * TODO consider using similar smaller (than map) api as in Transferable
+ *
+ * TODO clean up when drop handler changes
+ *
+ * @return
+ */
+ public Map<String, Object> getEventDetails() {
+ return dropDetails;
+ }
+
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.Paintable;
+
+/**
+ * Vaadin Widgets (TODO or Paintables, see {@link VHasDropHandler}) that want to
+ * receive something via drag and drop implement this interface.
+ */
+public interface VDropHandler {
+
+ /**
+ * Called by D'D' manager when drag gets over this drop handler.
+ *
+ * @param drag
+ */
+ public void dragEnter(VDragEvent drag);
+
+ /**
+ * Called by D'D' manager when drag gets out this drop handler.
+ *
+ * @param drag
+ */
+ public void dragLeave(VDragEvent drag);
+
+ /**
+ * The actual drop happened on this drop handler.
+ *
+ * @param drag
+ * @return true if Tranferrable of this drag event needs to be sent to
+ * server, false if drop was finally canceled or no server visit is
+ * needed
+ */
+ public boolean drop(VDragEvent drag);
+
+ /**
+ * When drag is over current drag handler.
+ *
+ * With drag implementation by {@link VDragAndDropManager} will be called
+ * when mouse is moved. HTML5 implementations call this continuously even
+ * though mouse is not moved.
+ *
+ * @param currentDrag
+ */
+ public void dragOver(VDragEvent currentDrag);
+
+ /**
+ * Returns the Paintable into which this DragHandler is assosiated
+ */
+ public Paintable getPaintable();
+
+ /**
+ * Returns the application connection to which this {@link VDropHandler}
+ * belongs to. DragAndDropManager uses this fucction to send Transferable to
+ * server side.
+ */
+ public ApplicationConnection getApplicationConnection();
+
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import com.vaadin.terminal.gwt.client.Paintable;
+
+/**
+ * Used to detect Widget from widget tree that has {@link #getDropHandler()}
+ *
+ * Decide whether to get rid of this class. If so, {@link VAbstractDropHandler} must
+ * extend {@link Paintable}.
+ *
+ */
+public interface VHasDropHandler {
+ public VDropHandler getDropHandler();
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import com.google.gwt.core.client.JsArrayString;
+import com.google.gwt.dom.client.NativeEvent;
+
+public class VHtml5DragEvent extends NativeEvent {
+ protected VHtml5DragEvent() {
+ }
+
+ public final native JsArrayString getTypes()
+ /*-{
+ return this.dataTransfer.types;
+ }-*/;
+
+ public final native String getDataAsText(String type)
+ /*-{
+ var v = this.dataTransfer.getData(type);
+ return v;
+ }-*/;
+
+ /**
+ * Works on FF 3.6 and possibly with gears.
+ *
+ * @param index
+ * @return
+ */
+ public final native String getFileAsString(int index)
+ /*-{
+ if(this.dataTransfer.files.length > 0 && this.dataTransfer.files[0].getAsText) {
+ return this.dataTransfer.files[index].getAsText("UTF-8");
+ }
+ return null;
+ }-*/;
+
+ public final native void setDragEffect(String effect)
+ /*-{
+ try {
+ this.dataTransfer.dropEffect = effect;
+ } catch (e){}
+ }-*/;
+
+ public final native String getEffectAllowed()
+ /*-{
+ return this.dataTransfer.effectAllowed;
+ }-*/;
+}
--- /dev/null
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.vaadin.terminal.DragSource;
+import com.vaadin.terminal.gwt.client.Paintable;
+
+/**
+ * Client side counterpart for Transferable in com.vaadin.event.Transferable
+ *
+ */
+public class VTransferable {
+
+ private Paintable component;
+
+ private final Map<String, Object> variables = new HashMap<String, Object>();
+
+ /**
+ * @return the component
+ */
+ public Paintable getComponent() {
+ return component;
+ }
+
+ /**
+ * @param component
+ * the component to set
+ */
+ public void setComponent(Paintable component) {
+ this.component = component;
+ }
+
+ /**
+ * This is commonly actually a key to property id on client side than the
+ * actual propertyId.
+ *
+ * Translated by terminal and {@link DragSource}
+ *
+ * @return the propertyId
+ */
+ public String getPropertyId() {
+ return (String) variables.get("propertyId");
+ }
+
+ /**
+ * This is commonly actually a key to property id on client side than the
+ * actual propertyId.
+ *
+ * Translated by terminal and {@link DragSource}
+ *
+ * @param propertyId
+ * the propertyId to set
+ */
+ public void setPropertyId(String propertyId) {
+ variables.put("propertyId", propertyId);
+ }
+
+ /**
+ * @return the itemId
+ */
+ public String getItemId() {
+ return (String) variables.get("itemId");
+ }
+
+ /**
+ * This is commonly actually a key to item id on client side than the actual
+ * itemId.
+ *
+ * Translated by terminal and {@link DragSource}
+ *
+ * @param itemId
+ * the itemId to set
+ */
+ public void setItemId(String itemId) {
+ variables.put("itemId", itemId);
+ }
+
+ public Object getData(String dataFlawor) {
+ return variables.get(dataFlawor);
+ }
+
+ public void setData(String dataFlawor, Object value) {
+ variables.put(dataFlawor, value);
+ }
+
+ public Collection<String> getDataFlawors() {
+ return variables.keySet();
+ }
+
+ /**
+ * This method should only be called by {@link VDragAndDropManager}.
+ *
+ * @return data in this Transferable that needs to be moved to server.
+ */
+ public Map<String, Object> getVariableMap() {
+ return variables;
+ }
+
+}
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
-import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager;
-import com.vaadin.terminal.gwt.client.ui.dd.Transferable;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager;
+import com.vaadin.terminal.gwt.client.ui.dd.VTransferable;
/**
* Example code to implement Component that has something to drag.
// Start the drag and drop operation
// create Transferable, that contains the payload
- Transferable transferable = new Transferable();
+ VTransferable transferable = new VTransferable();
transferable.setData("Text", "myPayload");
// Tell DragAndDropManager to start a drag and drop operation.
// Also let it handle all events (last parameter true). Could
// also do all event handling here too.
- DragAndDropManager.get().startDrag(transferable,
+ VDragAndDropManager.get().startDrag(transferable,
mDownEvent.getNativeEvent(), true);
mouseDown = false;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.ValueMap;
-import com.vaadin.terminal.gwt.client.ui.dd.AcceptCallback;
-import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager;
-import com.vaadin.terminal.gwt.client.ui.dd.DragEvent;
-import com.vaadin.terminal.gwt.client.ui.dd.DropHandler;
-import com.vaadin.terminal.gwt.client.ui.dd.HasDropHandler;
-import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager.DragEventType;
+import com.vaadin.terminal.gwt.client.ui.dd.VAcceptCallback;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragEvent;
+import com.vaadin.terminal.gwt.client.ui.dd.VDropHandler;
+import com.vaadin.terminal.gwt.client.ui.dd.VHasDropHandler;
+import com.vaadin.terminal.gwt.client.ui.dd.VDragAndDropManager.DragEventType;
-public class VMyDropTarget extends Composite implements HasDropHandler,
- DropHandler, Paintable {
+public class VMyDropTarget extends Composite implements VHasDropHandler,
+ VDropHandler, Paintable {
private ApplicationConnection client;
- public void dragEnter(DragEvent drag) {
- DragAndDropManager.get().visitServer(DragEventType.ENTER,
- new AcceptCallback() {
+ public void dragEnter(VDragEvent drag) {
+ VDragAndDropManager.get().visitServer(DragEventType.ENTER,
+ new VAcceptCallback() {
public void handleResponse(ValueMap responseData) {
// show hints, error messages etc
}
});
}
- public void dragLeave(DragEvent drag) {
+ public void dragLeave(VDragEvent drag) {
// TODO Auto-generated method stub
}
- public void dragOver(DragEvent currentDrag) {
+ public void dragOver(VDragEvent currentDrag) {
// TODO Auto-generated method stub
}
- public boolean drop(DragEvent drag) {
+ public boolean drop(VDragEvent drag) {
// TODO Auto-generated method stub
// return true to tell DDManager do server visit
return false;
return this;
}
- public DropHandler getDropHandler() {
+ public VDropHandler getDropHandler() {
// Drophandler implemented by Paintable itself
return this;
}