]> source.dussan.org Git - vaadin-framework.git/commitdiff
cross plat improvementes for html5 drags
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Tue, 16 Mar 2010 14:53:56 +0000 (14:53 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Tue, 16 Mar 2010 14:53:56 +0000 (14:53 +0000)
svn changeset:11916/svn branch:6.3

src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java
src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java
src/com/vaadin/terminal/gwt/client/ui/dd/VDragEvent.java
src/com/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent.java
src/com/vaadin/ui/DragAndDropWrapper.java
tests/src/com/vaadin/tests/dd/AcceptAnythingWindow.java
tests/src/com/vaadin/tests/dd/DragDropPane.java

index 7f50b8f9beaf3d3512c1745b7676438d3ab2386a..e35eec9799fef094a210f2246e0fd9fd262abb4c 100644 (file)
@@ -13,8 +13,10 @@ import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.xhr.client.ReadyStateChangeHandler;
 import com.google.gwt.xhr.client.XMLHttpRequest;
 import com.vaadin.terminal.gwt.client.ApplicationConnection;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
 import com.vaadin.terminal.gwt.client.MouseEventDetails;
 import com.vaadin.terminal.gwt.client.Paintable;
 import com.vaadin.terminal.gwt.client.RenderInformation;
@@ -94,6 +96,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
     private final static int WRAPPER = 2;
     private int dragStarMode;
     private int filecounter = 0;
+    private boolean dragLeavPostponed;
 
     @Override
     public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
@@ -119,12 +122,18 @@ public class VDragAndDropWrapper extends VCustomComponent implements
         if (dropHandler == null) {
             return true;
         }
+        if (dragLeavPostponed) {
+            // returned quickly back to wrapper
+            dragLeavPostponed = false;
+            return false;
+        }
         ApplicationConnection.getConsole().log("HTML 5 Drag Enter");
         VTransferable transferable = new VTransferable();
         transferable.setDragSource(this);
 
         vaadinDragEvent = VDragAndDropManager.get().startDrag(transferable,
                 event, false);
+        VDragAndDropManager.get().setCurrentDropHandler(getDropHandler());
         event.preventDefault();
         event.stopPropagation();
         return false;
@@ -136,17 +145,21 @@ public class VDragAndDropWrapper extends VCustomComponent implements
         }
 
         ApplicationConnection.getConsole().log("HTML 5 Drag Leave posponed...");
+        dragLeavPostponed = true;
         DeferredCommand.addCommand(new Command() {
             public void execute() {
                 // Yes, dragleave happens before drop. Makes no sense to me.
                 // IMO shouldn't fire leave at all if drop happens (I guess this
                 // is what IE does).
                 // In Vaadin we fire it only if drop did not happen.
-                if (vaadinDragEvent != null) {
+                if (dragLeavPostponed
+                        && vaadinDragEvent != null
+                        && VDragAndDropManager.get().getCurrentDropHandler() == getDropHandler()) {
                     ApplicationConnection.getConsole().log(
                             "...HTML 5 Drag Leave");
-                    getDropHandler().dragLeave(vaadinDragEvent);
+                    VDragAndDropManager.get().interruptDrag();
                 }
+                dragLeavPostponed = false;
             }
         });
         event.preventDefault();
@@ -160,14 +173,18 @@ public class VDragAndDropWrapper extends VCustomComponent implements
         }
 
         ApplicationConnection.getConsole().log("HTML 5 Drag Over");
+        vaadinDragEvent.setCurrentGwtEvent(event);
         getDropHandler().dragOver(vaadinDragEvent);
         // needed to be set for Safari, otherwise drop will not happen
-        String s = event.getEffectAllowed();
-        if ("all".equals(s) || s.contains("opy")) {
-            event.setDragEffect("copy");
-        } else {
-            event.setDragEffect(s);
-            ApplicationConnection.getConsole().log("Drag effect set to " + s);
+        if (BrowserInfo.get().isWebkit()) {
+            String s = event.getEffectAllowed();
+            if ("all".equals(s) || s.contains("opy")) {
+                event.setDragEffect("copy");
+            } else {
+                event.setDragEffect(s);
+                ApplicationConnection.getConsole().log(
+                        "Drag effect set to " + s);
+            }
         }
         event.preventDefault();
         event.stopPropagation();
@@ -175,7 +192,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
     }
 
     public boolean html5DragDrop(VHtml5DragEvent event) {
-        if (dropHandler == null) {
+        if (dropHandler == null || !currentlyValid) {
             return true;
         }
 
@@ -183,16 +200,21 @@ public class VDragAndDropWrapper extends VCustomComponent implements
         VTransferable transferable = vaadinDragEvent.getTransferable();
 
         JsArrayString types = event.getTypes();
+        ApplicationConnection.getConsole().log("Types fetched");
         for (int i = 0; i < types.length(); i++) {
             String type = types.get(i);
             ApplicationConnection.getConsole().log("Type: " + type);
-            if ("text/plain".equals(type)) {
+            if ("Text".equals(type) || "Url".equals(type)
+                    || "text/html".equals(type)) {
                 String data = event.getDataAsText(type);
-                ApplicationConnection.getConsole().log(type + " : " + data);
-                transferable.setData("text/plain", data);
+                if (data != null) {
+                    ApplicationConnection.getConsole().log(type + " : " + data);
+                    transferable.setData(type, data);
+                }
             }
         }
 
+        ApplicationConnection.getConsole().log("checking files");
         int fileCount = event.getFileCount();
         if (fileCount > 0) {
             transferable.setData("filecount", fileCount);
@@ -208,6 +230,8 @@ public class VDragAndDropWrapper extends VCustomComponent implements
 
         }
 
+        ApplicationConnection.getConsole().log("Ending drag");
+
         VDragAndDropManager.get().endDrag();
         vaadinDragEvent = null;
         event.preventDefault();
@@ -230,7 +254,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
     }
 
     /**
-     * Currently supports only FF36 as no other browser supprots natively File
+     * Currently supports only FF36 as no other browser supports natively File
      * api.
      * 
      * @param fileId
@@ -248,8 +272,18 @@ public class VDragAndDropWrapper extends VCustomComponent implements
 
                         ExtendedXHR extendedXHR = (ExtendedXHR) ExtendedXHR
                                 .create();
-                        extendedXHR.open("POST", client.getAppUri());
                         String name = "XHRFILE" + getPid() + "." + fileId;
+                        extendedXHR
+                                .setOnReadyStateChange(new ReadyStateChangeHandler() {
+                                    public void onReadyStateChange(
+                                            XMLHttpRequest xhr) {
+                                        if (xhr.getReadyState() == XMLHttpRequest.DONE) {
+                                            client.sendPendingVariableChanges();
+                                            xhr.clearOnReadyStateChange();
+                                        }
+                                    }
+                                });
+                        extendedXHR.open("POST", client.getAppUri());
                         multipartSend(extendedXHR, object, name);
 
                     }
@@ -294,6 +328,11 @@ public class VDragAndDropWrapper extends VCustomComponent implements
     private VerticalDropLocation emphasizedVDrop;
     private HorizontalDropLocation emphasizedHDrop;
 
+    /**
+     * Flag used by html5 dd
+     */
+    private boolean currentlyValid;
+
     private static final String OVER_STYLE = "v-ddwrapper-over";
 
     public class CustomDropHandler extends VAbstractDropHandler {
@@ -302,6 +341,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
         public void dragEnter(VDragEvent drag) {
             updateDropDetails(drag);
             ApplicationConnection.getConsole().log("DDWrapper DragEnter");
+            currentlyValid = false;
             super.dragEnter(drag);
         }
 
@@ -309,16 +349,20 @@ public class VDragAndDropWrapper extends VCustomComponent implements
         public void dragLeave(VDragEvent drag) {
             ApplicationConnection.getConsole().log("DDWrapper DragLeave");
             deEmphasis(true);
+            dragLeavPostponed = false;
         }
 
         @Override
         public void dragOver(final VDragEvent drag) {
-            updateDropDetails(drag);
-            validate(new VAcceptCallback() {
-                public void accepted(VDragEvent event) {
-                    dragAccepted(drag);
-                }
-            }, drag);
+            boolean detailsChanged = updateDropDetails(drag);
+            if (detailsChanged) {
+                currentlyValid = false;
+                validate(new VAcceptCallback() {
+                    public void accepted(VDragEvent event) {
+                        dragAccepted(drag);
+                    }
+                }, drag);
+            }
         }
 
         @Override
@@ -349,6 +393,7 @@ public class VDragAndDropWrapper extends VCustomComponent implements
 
         @Override
         protected void dragAccepted(VDragEvent drag) {
+            currentlyValid = true;
             emphasis(drag);
         }
 
@@ -392,11 +437,11 @@ public class VDragAndDropWrapper extends VCustomComponent implements
             
             } else {
                 el.attachEvent("ondragenter",  function(ev) {
-                            return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragEnter(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev);
+                    return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragEnter(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev);
                 });
                 
                 el.attachEvent("ondragleave",  function(ev) {
-                        return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragLeave(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev);
+                    return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragLeave(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev);
                 });
         
                 el.attachEvent("ondragover",  function(ev) {
@@ -410,15 +455,22 @@ public class VDragAndDropWrapper extends VCustomComponent implements
         
     }-*/;
 
-    public void updateDropDetails(VDragEvent drag) {
+    public boolean updateDropDetails(VDragEvent drag) {
+        VerticalDropLocation oldVL = verticalDropLocation;
         verticalDropLocation = DDUtil.getVerticalDropLocation(getElement(),
                 drag.getCurrentGwtEvent().getClientY(), 0.2);
         drag.getDropDetails().put("verticalLocation",
                 verticalDropLocation.toString());
+        HorizontalDropLocation oldHL = horizontalDropLocation;
         horizontalDropLocation = DDUtil.getHorizontalDropLocation(getElement(),
                 drag.getCurrentGwtEvent().getClientX(), 0.2);
         drag.getDropDetails().put("horizontalLocation",
                 horizontalDropLocation.toString());
+        if (oldHL != horizontalDropLocation || oldVL != verticalDropLocation) {
+            return true;
+        } else {
+            return false;
+        }
     }
 
     protected void deEmphasis(boolean doLayout) {
index fdb3c47ba3c6429bd92bbaa70fb1dc4e6395eea1..fdb5801a28c7e39c6c401e8ff2b0bacc4b55672e 100644 (file)
@@ -43,7 +43,7 @@ public class VDragAndDropManager {
 
         public void onPreviewNativeEvent(NativePreviewEvent event) {
             NativeEvent nativeEvent = event.getNativeEvent();
-            updateCurrentEvent(nativeEvent);
+            currentDrag.setCurrentGwtEvent(nativeEvent);
             updateDragImagePosition();
 
             int typeInt = event.getTypeInt();
@@ -279,7 +279,7 @@ public class VDragAndDropManager {
         isStarted = false;
 
         currentDrag = new VDragEvent(transferable, startEvent);
-        updateCurrentEvent(startEvent);
+        currentDrag.setCurrentGwtEvent(startEvent);
 
         final Command startDrag = new Command() {
 
@@ -287,8 +287,8 @@ public class VDragAndDropManager {
                 isStarted = true;
                 VDropHandler dh = null;
                 if (startEvent != null) {
-                    dh = findDragTarget((Element) currentDrag.currentGwtEvent
-                            .getEventTarget().cast());
+                    dh = findDragTarget((Element) currentDrag
+                            .getCurrentGwtEvent().getEventTarget().cast());
                 }
                 if (dh != null) {
                     // drag has started on a DropHandler, kind of drag over
@@ -357,7 +357,8 @@ public class VDragAndDropManager {
                             case Event.ONMOUSEMOVE:
                                 deferredStartRegistration.removeHandler();
                                 deferredStartRegistration = null;
-                                updateCurrentEvent(event.getNativeEvent());
+                                currentDrag.setCurrentGwtEvent(event
+                                        .getNativeEvent());
                                 startDrag.execute();
                                 break;
                             default:
@@ -386,24 +387,26 @@ public class VDragAndDropManager {
         return currentDrag;
     }
 
-    private void interruptDrag() {
+    public void interruptDrag() {
         if (currentDrag != null) {
             ApplicationConnection.getConsole()
                     .log("Drag operation interrupted");
             if (currentDropHandler != null) {
-                currentDrag.currentGwtEvent = null;
+                currentDrag.setCurrentGwtEvent(null);
                 currentDropHandler.dragLeave(currentDrag);
                 currentDropHandler = null;
+                serverCallback = null;
+                visitId = -1; // ignore possibly on going server check
             }
             currentDrag = null;
         }
     }
 
     private void updateDragImagePosition() {
-        if (currentDrag.currentGwtEvent != null && dragElement != null) {
+        if (currentDrag.getCurrentGwtEvent() != null && dragElement != null) {
             Style style = dragElement.getStyle();
-            int clientY = currentDrag.currentGwtEvent.getClientY();
-            int clientX = currentDrag.currentGwtEvent.getClientX();
+            int clientY = currentDrag.getCurrentGwtEvent().getClientY();
+            int clientX = currentDrag.getCurrentGwtEvent().getClientX();
             style.setTop(clientY, Unit.PX);
             style.setLeft(clientX, Unit.PX);
         }
@@ -451,10 +454,6 @@ public class VDragAndDropManager {
 
     }
 
-    private void updateCurrentEvent(NativeEvent event) {
-        currentDrag.currentGwtEvent = event;
-    }
-
     public void endDrag() {
         if (handlerRegistration != null) {
             handlerRegistration.removeHandler();
@@ -535,10 +534,10 @@ public class VDragAndDropManager {
 
         client.updateVariable(DD_SERVICE, "type", drop.ordinal(), false);
 
-        if (currentDrag.currentGwtEvent != null) {
+        if (currentDrag.getCurrentGwtEvent() != null) {
             try {
                 MouseEventDetails mouseEventDetails = new MouseEventDetails(
-                        currentDrag.currentGwtEvent);
+                        currentDrag.getCurrentGwtEvent());
                 currentDrag.getDropDetails().put("mouseEvent",
                         mouseEventDetails.serialize());
             } catch (Exception e) {
index 8877d70f046728ea1c28f55bfa81269441d2ffe7..a5b06cea84e45223ffe5b4efc798adc83c330df1 100644 (file)
@@ -30,7 +30,7 @@ public class VDragEvent {
 
     private VTransferable transferable;
 
-    NativeEvent currentGwtEvent;
+    private NativeEvent currentGwtEvent;
 
     private NativeEvent startEvent;
 
@@ -64,6 +64,10 @@ public class VDragEvent {
         return currentGwtEvent;
     }
 
+    public void setCurrentGwtEvent(NativeEvent event) {
+        currentGwtEvent = event;
+    }
+
     int getEventId() {
         return id;
     }
index 47b1ba81ed2cc11be007d92a2219f55f563a878a..3f3cf54e87b3743ad28f7980a2b56a6d505e91f4 100644 (file)
@@ -17,7 +17,8 @@ public class VHtml5DragEvent extends NativeEvent {
 
     public final native JsArrayString getTypes()
     /*-{
-        return this.dataTransfer.types;
+        // IE does not support types, return some basic values
+        return this.dataTransfer.types ? this.dataTransfer.types : ["Text","Url","Html"];
      }-*/;
 
     public final native String getDataAsText(String type)
index 65bcbaaa6a93a47403ff7f037f4fcd44f08b79e9..9d3e9a6f196bc579d7bb3aa35d3a37bfb7e828c6 100644 (file)
@@ -265,6 +265,7 @@ public class DragAndDropWrapper extends CustomComponent implements DropTarget,
                 while ((bytesRead = stream.read(buf)) != -1) {
                     receiveUpload.write(buf, 0, bytesRead);
                 }
+                receiveUpload.close();
             } catch (IOException e) {
                 throw new UploadException(e);
             }
index 38ecc308b534a7873ff035e924c765090c694ab5..d2dfd454e31c85c0f19af76a74a1e3da60a90dea 100644 (file)
@@ -103,7 +103,7 @@ public class AcceptAnythingWindow extends Window {
 
                 } else {
                     // drag coming outside of Vaadin
-                    String object = (String) transferable.getData("text/plain");
+                    String object = (String) transferable.getData("Text");
 
                     String content = (String) transferable
                             .getData("fileContents");
index 400e5f9e2621961a2b6b5f2e42945aba207d650a..82401a99f70119b16f75cb8c1264c3c80835a490 100644 (file)
@@ -1,5 +1,9 @@
 package com.vaadin.tests.dd;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
 import com.vaadin.event.DataBoundTransferable;
 import com.vaadin.event.Transferable;
 import com.vaadin.event.dd.DragAndDropEvent;
@@ -12,6 +16,8 @@ import com.vaadin.ui.Component;
 import com.vaadin.ui.DragAndDropWrapper;
 import com.vaadin.ui.Label;
 import com.vaadin.ui.AbsoluteLayout.ComponentPosition;
+import com.vaadin.ui.DragAndDropWrapper.WrapperTransferable.Html5File;
+import com.vaadin.ui.Upload.Receiver;
 
 /**
  * replacement for a proto class to keep tests working
@@ -104,11 +110,14 @@ public class DragDropPane extends DragAndDropWrapper implements DropHandler {
 
         else {
             // drag coming outside of Vaadin
-            String object = (String) ctr.getData("text/plain");
 
-            String content = (String) ctr.getData("fileContents");
+            WrapperTransferable wtr = (WrapperTransferable) ctr;
 
-            Label l = new Label();
+            String object = (String) ctr.getData("Text");
+            String html = (String) ctr.getData("Html");
+            String url = (String) ctr.getData("Url");
+
+            final Label l = new Label();
             l.setCaption("Generated from HTML5 drag:");
             if (object != null) {
                 l.setValue(object);
@@ -116,7 +125,28 @@ public class DragDropPane extends DragAndDropWrapper implements DropHandler {
                 l.setValue("HTML5 dd");
             }
 
-            l.setDescription(content);
+            Html5File[] files = wtr.getFiles();
+            if (files != null) {
+                for (Html5File html5File : files) {
+                    l.setCaption(html5File.getFileName());
+                    html5File.setReceiver(new Receiver() {
+                        public OutputStream receiveUpload(String filename,
+                                String MIMEType) {
+
+                            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream() {
+                                @Override
+                                public void close() throws IOException {
+                                    super.close();
+                                    l.setValue((new String(toByteArray())
+                                            .substring(0, 80) + "..."));
+                                }
+                            };
+                            return byteArrayOutputStream;
+                        }
+                    });
+                }
+            }
+
             l.setSizeUndefined();
 
             root.addComponent(l);