From 3b012b40d19c9b9b3acb7b675e82e07aad309cbe Mon Sep 17 00:00:00 2001 From: Matti Tahvonen Date: Tue, 16 Feb 2010 15:58:56 +0000 Subject: [PATCH] draft of DragAndDropWrapper + small changes svn changeset:11349/svn branch:6.3_dd --- .../VAADIN/themes/base/common/common.css | 17 +- WebContent/VAADIN/themes/base/styles.css | 22 +- WebContent/VAADIN/themes/base/tree/tree.css | 6 +- WebContent/VAADIN/themes/reindeer/styles.css | 22 +- WebContent/VAADIN/themes/runo/styles.css | 22 +- .../vaadin/event/ComponentTransferable.java | 2 +- src/com/vaadin/event/dd/DragSource.java | 3 +- src/com/vaadin/event/dd/DropHandler.java | 4 +- src/com/vaadin/event/dd/TargetDetails.java | 5 +- .../vaadin/event/dd/TargetDetailsImpl.java | 1 + .../terminal/gwt/client/DefaultWidgetSet.java | 1 + .../gwt/client/ui/VDragAndDropWrapper.java | 336 ++++++++++++++++++ .../terminal/gwt/client/ui/VDragDropPane.java | 10 +- .../terminal/gwt/client/ui/VScrollTable.java | 2 +- .../vaadin/terminal/gwt/client/ui/VTree.java | 13 +- .../gwt/client/ui/dd/ComponentCriteria.java | 2 +- .../client/ui/dd/VAbstractDropHandler.java | 1 - .../gwt/client/ui/dd/VDragAndDropManager.java | 14 +- .../gwt/client/ui/dd/VHasDropHandler.java | 4 +- .../gwt/client/ui/dd/VTransferable.java | 8 +- src/com/vaadin/ui/CustomComponent.java | 6 + src/com/vaadin/ui/DragAndDropWrapper.java | 109 ++++++ src/com/vaadin/ui/DragDropPane.java | 7 +- tests/src/com/vaadin/tests/dd/DDTest1.java | 3 +- tests/src/com/vaadin/tests/dd/DDTest5.java | 170 +++++++++ 25 files changed, 743 insertions(+), 47 deletions(-) create mode 100644 src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java create mode 100644 src/com/vaadin/ui/DragAndDropWrapper.java create mode 100644 tests/src/com/vaadin/tests/dd/DDTest5.java diff --git a/WebContent/VAADIN/themes/base/common/common.css b/WebContent/VAADIN/themes/base/common/common.css index 082f6b4f7f..29fb1363d4 100644 --- a/WebContent/VAADIN/themes/base/common/common.css +++ b/WebContent/VAADIN/themes/base/common/common.css @@ -226,4 +226,19 @@ div.v-app-loading { opacity: 0.4; filter: alpha(opacity=40); border: 1px solid #999; -} \ No newline at end of file +} + + +.v-ddwrapper { + background-color: cyan; +} + +.v-ddwrapper-over-center { + background-color: LightGreen; +} +.v-ddwrapper-over-top { + border-top: 2px solid green; +} +.v-ddwrapper-over-bottom { + border-bottom: 2px solid green; +} diff --git a/WebContent/VAADIN/themes/base/styles.css b/WebContent/VAADIN/themes/base/styles.css index eca4525510..770f1c9d4c 100644 --- a/WebContent/VAADIN/themes/base/styles.css +++ b/WebContent/VAADIN/themes/base/styles.css @@ -458,6 +458,21 @@ div.v-app-loading { border: 1px solid #999; } + +.v-ddwrapper { + background-color: cyan; +} + +.v-ddwrapper-over-center { + background-color: LightGreen; +} +.v-ddwrapper-over-top { + border-top: 2px solid green; +} +.v-ddwrapper-over-bottom { + border-bottom: 2px solid green; +} + .v-csslayout { overflow: hidden; } @@ -1621,17 +1636,16 @@ div.v-tree-node-leaf { color: #fff; } -.v-tree-node-drag-top .v-tree-node-caption { +.v-tree-node-caption-drag-top { border-top:2px solid green; } -.v-tree-node-drag-bottom .v-tree-node-caption { +.v-tree-node-caption-drag-bottom { border-bottom:2px solid green; } -.v-tree-node-drag-center .v-tree-node-caption { +.v-tree-node-caption-drag-center { background-color:green; } - .v-tree-node-children { padding-left: 1em; } diff --git a/WebContent/VAADIN/themes/base/tree/tree.css b/WebContent/VAADIN/themes/base/tree/tree.css index 8a6fc3b878..084247e7d5 100644 --- a/WebContent/VAADIN/themes/base/tree/tree.css +++ b/WebContent/VAADIN/themes/base/tree/tree.css @@ -30,13 +30,13 @@ div.v-tree-node-leaf { color: #fff; } -.v-tree-node-drag-top .v-tree-node-caption { +.v-tree-node-caption-drag-top { border-top:2px solid green; } -.v-tree-node-drag-bottom .v-tree-node-caption { +.v-tree-node-caption-drag-bottom { border-bottom:2px solid green; } -.v-tree-node-drag-center .v-tree-node-caption { +.v-tree-node-caption-drag-center { background-color:green; } diff --git a/WebContent/VAADIN/themes/reindeer/styles.css b/WebContent/VAADIN/themes/reindeer/styles.css index c4081182c8..e927ab81cb 100644 --- a/WebContent/VAADIN/themes/reindeer/styles.css +++ b/WebContent/VAADIN/themes/reindeer/styles.css @@ -458,6 +458,21 @@ div.v-app-loading { border: 1px solid #999; } + +.v-ddwrapper { + background-color: cyan; +} + +.v-ddwrapper-over-center { + background-color: LightGreen; +} +.v-ddwrapper-over-top { + border-top: 2px solid green; +} +.v-ddwrapper-over-bottom { + border-bottom: 2px solid green; +} + .v-csslayout { overflow: hidden; } @@ -1621,17 +1636,16 @@ div.v-tree-node-leaf { color: #fff; } -.v-tree-node-drag-top .v-tree-node-caption { +.v-tree-node-caption-drag-top { border-top:2px solid green; } -.v-tree-node-drag-bottom .v-tree-node-caption { +.v-tree-node-caption-drag-bottom { border-bottom:2px solid green; } -.v-tree-node-drag-center .v-tree-node-caption { +.v-tree-node-caption-drag-center { background-color:green; } - .v-tree-node-children { padding-left: 1em; } diff --git a/WebContent/VAADIN/themes/runo/styles.css b/WebContent/VAADIN/themes/runo/styles.css index 8d07f54c53..a3ad1f1f86 100644 --- a/WebContent/VAADIN/themes/runo/styles.css +++ b/WebContent/VAADIN/themes/runo/styles.css @@ -458,6 +458,21 @@ div.v-app-loading { border: 1px solid #999; } + +.v-ddwrapper { + background-color: cyan; +} + +.v-ddwrapper-over-center { + background-color: LightGreen; +} +.v-ddwrapper-over-top { + border-top: 2px solid green; +} +.v-ddwrapper-over-bottom { + border-bottom: 2px solid green; +} + .v-csslayout { overflow: hidden; } @@ -1621,17 +1636,16 @@ div.v-tree-node-leaf { color: #fff; } -.v-tree-node-drag-top .v-tree-node-caption { +.v-tree-node-caption-drag-top { border-top:2px solid green; } -.v-tree-node-drag-bottom .v-tree-node-caption { +.v-tree-node-caption-drag-bottom { border-bottom:2px solid green; } -.v-tree-node-drag-center .v-tree-node-caption { +.v-tree-node-caption-drag-center { background-color:green; } - .v-tree-node-children { padding-left: 1em; } diff --git a/src/com/vaadin/event/ComponentTransferable.java b/src/com/vaadin/event/ComponentTransferable.java index f3d7e04162..c1b713690a 100644 --- a/src/com/vaadin/event/ComponentTransferable.java +++ b/src/com/vaadin/event/ComponentTransferable.java @@ -5,7 +5,7 @@ import com.vaadin.ui.Component; public interface ComponentTransferable extends Transferable { /** - * @return the component where the drag operation started + * @return the component that started the drag operation */ public Component getSourceComponent(); diff --git a/src/com/vaadin/event/dd/DragSource.java b/src/com/vaadin/event/dd/DragSource.java index 9d901f0d41..3b69f1b028 100644 --- a/src/com/vaadin/event/dd/DragSource.java +++ b/src/com/vaadin/event/dd/DragSource.java @@ -1,10 +1,11 @@ package com.vaadin.event.dd; +import java.io.Serializable; import java.util.Map; import com.vaadin.event.Transferable; -public interface DragSource { +public interface DragSource extends Serializable { /** * DragSource may convert client side variables to meaningful values on diff --git a/src/com/vaadin/event/dd/DropHandler.java b/src/com/vaadin/event/dd/DropHandler.java index 2bb03aa7b0..b5ebbc0fa1 100644 --- a/src/com/vaadin/event/dd/DropHandler.java +++ b/src/com/vaadin/event/dd/DropHandler.java @@ -1,9 +1,11 @@ package com.vaadin.event.dd; +import java.io.Serializable; + import com.vaadin.event.dd.acceptCriteria.AcceptAll; import com.vaadin.event.dd.acceptCriteria.AcceptCriterion; -public interface DropHandler { +public interface DropHandler extends Serializable { public void drop(DropEvent dropEvent); diff --git a/src/com/vaadin/event/dd/TargetDetails.java b/src/com/vaadin/event/dd/TargetDetails.java index d3f488052b..7711160f6e 100644 --- a/src/com/vaadin/event/dd/TargetDetails.java +++ b/src/com/vaadin/event/dd/TargetDetails.java @@ -1,6 +1,9 @@ package com.vaadin.event.dd; -public interface TargetDetails { +import java.io.Serializable; + +public interface TargetDetails extends Serializable { + public Object getData(String key); public Object setData(String key, Object value); diff --git a/src/com/vaadin/event/dd/TargetDetailsImpl.java b/src/com/vaadin/event/dd/TargetDetailsImpl.java index be9fa5598f..ae7c7d0a5e 100644 --- a/src/com/vaadin/event/dd/TargetDetailsImpl.java +++ b/src/com/vaadin/event/dd/TargetDetailsImpl.java @@ -24,4 +24,5 @@ public class TargetDetailsImpl implements TargetDetails { public DropTarget getTarget() { return (DropTarget) data.get(DragAndDropService.DROPTARGET_KEY); } + } \ No newline at end of file diff --git a/src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java b/src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java index 919c267eb0..8ee6b0bb14 100644 --- a/src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java +++ b/src/com/vaadin/terminal/gwt/client/DefaultWidgetSet.java @@ -9,6 +9,7 @@ import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ui.VButton; import com.vaadin.terminal.gwt.client.ui.VCheckBox; import com.vaadin.terminal.gwt.client.ui.VDateFieldCalendar; +import com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper; import com.vaadin.terminal.gwt.client.ui.VFilterSelect; import com.vaadin.terminal.gwt.client.ui.VListSelect; import com.vaadin.terminal.gwt.client.ui.VNativeSelect; diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java new file mode 100644 index 0000000000..f6b4baa29d --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/VDragAndDropWrapper.java @@ -0,0 +1,336 @@ +package com.vaadin.terminal.gwt.client.ui; + +import java.util.Map; + +import com.google.gwt.core.client.JsArrayString; +import com.google.gwt.event.dom.client.MouseDownEvent; +import com.google.gwt.event.dom.client.MouseDownHandler; +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.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.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.VHtml5DragEvent; +import com.vaadin.terminal.gwt.client.ui.dd.VTransferable; +import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation; + +/** + * + * Must have features: + * + * stylenames to root element depending on place on component + * + * + * allow size to change on emphasis/deemphasis (behave well for vaadin layout + * system) + * + * html5 drops + * + * drop details: locations + sizes in document hierarchy up to wrapper + * + * + */ +public class VDragAndDropWrapper extends VCustomComponent implements + VHasDropHandler { + + private static final String CLASSNAME = "v-ddwrapper"; + + public VDragAndDropWrapper() { + super(); + hookHtml5Events(getElement()); + setStyleName(CLASSNAME); + addDomHandler(new MouseDownHandler() { + public void onMouseDown(MouseDownEvent event) { + if (dragStarMode > 0) { + // TODO should support drag mode WRAPPER too, now works for + // COMPONENT + VTransferable transferable = new VTransferable(); + transferable.setDragSource(VDragAndDropWrapper.this); + Paintable paintable = client.getPaintable((Element) event + .getNativeEvent().getEventTarget().cast()); + + transferable.setData("component", paintable); + VDragEvent startDrag = VDragAndDropManager.get().startDrag( + transferable, event.getNativeEvent(), true); + if (dragStarMode == WRAPPER) { + paintable = VDragAndDropWrapper.this; + } + + startDrag.createDragImage( + ((Widget) paintable).getElement(), true); + event.preventDefault(); // prevent text selection + + } + } + }, MouseDownEvent.getType()); + } + + private ApplicationConnection client; + private VAbstractDropHandler dropHandler; + private VDragEvent vaadinDragEvent; + + private final static int NONE = 0; + private final static int COMPONENT = 1; + private final static int WRAPPER = 2; + private int dragStarMode; + + @Override + public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { + this.client = client; + super.updateFromUIDL(uidl, client); + if (!uidl.hasAttribute("cached") && !uidl.hasAttribute("hidden")) { + int childCount = uidl.getChildCount(); + if (childCount > 1) { + UIDL childUIDL = uidl.getChildUIDL(1); + if (dropHandler == null) { + dropHandler = new CustomDropHandler(); + } + dropHandler.updateAcceptRules(childUIDL); + } else { + dropHandler = null; + } + + dragStarMode = uidl.getIntAttribute("dragStartMode"); + } + } + + public boolean html5DragEnter(VHtml5DragEvent event) { + if (dropHandler == null) { + return true; + } + ApplicationConnection.getConsole().log("HTML 5 Drag Enter"); + VTransferable transferable = new VTransferable(); + + vaadinDragEvent = VDragAndDropManager.get().startDrag(transferable, + event, false); + event.preventDefault(); + event.stopPropagation(); + return false; + } + + public boolean html5DragLeave(VHtml5DragEvent event) { + if (dropHandler == null) { + return true; + } + + ApplicationConnection.getConsole().log("HTML 5 Drag Leave posponed..."); + 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) { + ApplicationConnection.getConsole().log( + "...HTML 5 Drag Leave"); + getDropHandler().dragLeave(vaadinDragEvent); + } + } + }); + event.preventDefault(); + event.stopPropagation(); + return false; + } + + public boolean html5DragOver(VHtml5DragEvent event) { + if (dropHandler == null) { + return true; + } + + ApplicationConnection.getConsole().log("HTML 5 Drag Over"); + 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); + } + event.preventDefault(); + event.stopPropagation(); + return false; + } + + public boolean html5DragDrop(VHtml5DragEvent event) { + if (dropHandler == null) { + return true; + } + + ApplicationConnection.getConsole().log("HTML 5 Drag Drop"); + VTransferable transferable = vaadinDragEvent.getTransferable(); + + JsArrayString types = event.getTypes(); + for (int i = 0; i < types.length(); i++) { + String type = types.get(i); + ApplicationConnection.getConsole().log("Type: " + type); + if ("text/plain".equals(type)) { + String data = event.getDataAsText(type); + ApplicationConnection.getConsole().log(type + " : " + data); + transferable.setData("text/plain", data); + } + } + + String fileAsString = event.getFileAsString(0); + if (fileAsString != null) { + ApplicationConnection.getConsole().log(fileAsString); + transferable.setData("fileContents", fileAsString); + } + + VDragAndDropManager.get().endDrag(); + vaadinDragEvent = null; + event.preventDefault(); + event.stopPropagation(); + + return false; + } + + public VDropHandler getDropHandler() { + return dropHandler; + } + + private class CustomDropHandler extends VAbstractDropHandler { + + private static final String OVER_STYLE = "v-ddwrapper-over"; + private VerticalDropLocation verticalDropLocation; + + @Override + public void dragEnter(VDragEvent drag) { + ApplicationConnection.getConsole().log("DDWrapper DragEnter"); + super.dragEnter(drag); + } + + @Override + public void dragLeave(VDragEvent drag) { + ApplicationConnection.getConsole().log("DDWrapper DragLeave"); + deEmphasis(); + } + + @Override + public void dragOver(final VDragEvent drag) { + validate(new VAcceptCallback() { + public void accepted(VDragEvent event) { + dragAccepted(drag); + } + }, drag); + } + + @Override + public boolean drop(VDragEvent drag) { + ApplicationConnection.getConsole().log("Drop" + drag.sinceStart()); + deEmphasis(); + + Map dd = drag.getDropDetails(); + + // this is absolute layout based, and we may want to set + // component + // relatively to where the drag ended. + // need to add current location of the drop area + + int absoluteLeft = getAbsoluteLeft(); + int absoluteTop = getAbsoluteTop(); + + dd.put("absoluteLeft", absoluteLeft); + dd.put("absoluteTop", absoluteTop); + + dd.put("verticalLocation", verticalDropLocation.toString()); + + return super.drop(drag); + } + + private void deEmphasis() { + if (verticalDropLocation != null) { + VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE, + false); + VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE + "-" + + verticalDropLocation.toString().toLowerCase(), false); + } + } + + @Override + protected void dragAccepted(VDragEvent drag) { + emphasis(drag); + } + + private void emphasis(VDragEvent drag) { + deEmphasis(); + verticalDropLocation = VerticalDropLocation.get(getElement(), drag + .getCurrentGwtEvent().getClientY(), 0.2); + // TODO add more detailed stylenames depending on which part of + // wrapper the drag currently is (vertical done, needs horizontal) + VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE, true); + VDragAndDropWrapper.setStyleName(getElement(), OVER_STYLE + "-" + + verticalDropLocation.toString().toLowerCase(), true); + + // TODO build (to be an example) an emphasis mode where drag image + // is fitted before or after the content + + } + + @Override + public Paintable getPaintable() { + return VDragAndDropWrapper.this; + } + + public ApplicationConnection getApplicationConnection() { + return client; + } + + } + + /** + * Prototype code, memory leak risk. + * + * @param el + */ + private native void hookHtml5Events(Element el) + /*-{ + + var me = this; + + if(el.addEventListener) { + el.addEventListener("dragenter", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragEnter(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }, false); + + el.addEventListener("dragleave", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragLeave(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }, false); + + el.addEventListener("dragover", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragOver(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }, false); + + el.addEventListener("drop", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragDrop(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }, false); + + } 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); + }); + + el.attachEvent("ondragleave", function(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) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragOver(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }); + + el.attachEvent("ondrop", function(ev) { + return me.@com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper::html5DragDrop(Lcom/vaadin/terminal/gwt/client/ui/dd/VHtml5DragEvent;)(ev); + }); + } + + }-*/; + +} diff --git a/src/com/vaadin/terminal/gwt/client/ui/VDragDropPane.java b/src/com/vaadin/terminal/gwt/client/ui/VDragDropPane.java index 937f2f6bed..22fd48f54d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VDragDropPane.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VDragDropPane.java @@ -11,7 +11,6 @@ import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Widget; import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.client.BrowserInfo; import com.vaadin.terminal.gwt.client.Container; import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.Paintable; @@ -43,7 +42,8 @@ public class VDragDropPane extends VAbsoluteLayout implements Container, .cast()); if (paintable != null) { VTransferable transferable = new VTransferable(); - transferable.setComponent(paintable); + transferable.setDragSource(VDragDropPane.this); + transferable.setData("component", paintable); VDragEvent drag = VDragAndDropManager.get().startDrag( transferable, event.getNativeEvent(), true); drag.createDragImage(((Widget) paintable).getElement(), @@ -57,10 +57,8 @@ public class VDragDropPane extends VAbsoluteLayout implements Container, } }, MouseDownEvent.getType()); - if (!BrowserInfo.get().isIE()) { - // TODO make this IE compatible - hookHtml5Events(getElement()); - } + hookHtml5Events(getElement()); + getStyleElement().getStyle().setBackgroundColor("yellow"); } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 99e3ddb3ad..8b75cfa761 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -2520,7 +2520,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler, case Event.ONMOUSEMOVE: if (mDown && dragmode != 0) { VTransferable transferable = new VTransferable(); - transferable.setComponent(VScrollTable.this); + transferable.setDragSource(VScrollTable.this); transferable.setData("itemId", "" + rowKey); // TODO propertyId diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTree.java b/src/com/vaadin/terminal/gwt/client/ui/VTree.java index d0f50d2632..22b897d9c7 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTree.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTree.java @@ -207,7 +207,7 @@ public class VTree extends FlowPanel implements Paintable, VHasDropHandler { final String detail = getDropDetail(currentDrag .getCurrentGwtEvent()); boolean nodeHasChanged = (currentMouseOverKey != null && currentMouseOverKey != oldIdOver) - || (oldIdOver != null); + || (currentMouseOverKey == null && oldIdOver != null); boolean detailHasChanded = (detail != null && !detail .equals(oldDetail)) || (detail == null && oldDetail != null); @@ -273,7 +273,7 @@ public class VTree extends FlowPanel implements Paintable, VHasDropHandler { return null; } VerticalDropLocation verticalDropLocation = VerticalDropLocation.get( - treeNode.getElement(), event.getClientY(), 0.2); + treeNode.nodeCaptionDiv, event.getClientY(), 0.2); return verticalDropLocation.toString(); } @@ -361,6 +361,13 @@ public class VTree extends FlowPanel implements Paintable, VHasDropHandler { .equals(string)); UIObject.setStyleName(getElement(), base + "center", "Center" .equals(string)); + base = "v-tree-node-caption-drag-"; + UIObject.setStyleName(nodeCaptionDiv, base + "top", "Top" + .equals(string)); + UIObject.setStyleName(nodeCaptionDiv, base + "bottom", "Bottom" + .equals(string)); + UIObject.setStyleName(nodeCaptionDiv, base + "center", "Center" + .equals(string)); } @Override @@ -405,7 +412,7 @@ public class VTree extends FlowPanel implements Paintable, VHasDropHandler { "TreeNode drag start " + event.getType()); // start actual drag on slight move when mouse is down VTransferable t = new VTransferable(); - t.setComponent(VTree.this); + t.setDragSource(VTree.this); t.setData("itemId", key); VDragEvent drag = VDragAndDropManager.get().startDrag( t, mouseDownEvent, true); diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/ComponentCriteria.java b/src/com/vaadin/terminal/gwt/client/ui/dd/ComponentCriteria.java index 860653b67a..ae129365c4 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/ComponentCriteria.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/ComponentCriteria.java @@ -11,7 +11,7 @@ final class ComponentCriteria implements VAcceptCriteria { public void accept(VDragEvent drag, UIDL configuration, VAcceptCallback callback) { try { - Paintable component = drag.getTransferable().getComponent(); + Paintable component = drag.getTransferable().getDragSource(); int c = configuration.getIntAttribute("c"); for (int i = 0; i < c; i++) { String requiredPid = configuration diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java index f6a3d09b71..aaf90f899d 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java @@ -72,7 +72,6 @@ public abstract class VAbstractDropHandler implements VDropHandler { */ public void dragEnter(final VDragEvent drag) { validate(new VAcceptCallback() { - public void accepted(VDragEvent event) { dragAccepted(drag); } diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java index 8d301c70f2..e499f929b8 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java @@ -362,11 +362,7 @@ public class VDragAndDropManager { deferredStartRegistration.removeHandler(); deferredStartRegistration = null; currentDrag = null; - if (dragElement != null) { - RootPanel.getBodyElement().removeChild( - dragElement); - dragElement = null; - } + clearDragElement(); break; } @@ -469,6 +465,10 @@ public class VDragAndDropManager { currentDrag = null; + clearDragElement(); + } + + private void clearDragElement() { if (dragElement != null) { if (dragElement.getParentElement() != null) { RootPanel.getBodyElement().removeChild(dragElement); @@ -518,7 +518,7 @@ public class VDragAndDropManager { VTransferable transferable = currentDrag.getTransferable(); client.updateVariable(DD_SERVICE, "component", transferable - .getComponent(), false); + .getDragSource(), false); client.updateVariable(DD_SERVICE, "type", drop.ordinal(), false); @@ -572,7 +572,7 @@ public class VDragAndDropManager { void setDragElement(Element node) { if (currentDrag != null) { if (dragElement != null && dragElement != node) { - RootPanel.getBodyElement().removeChild(dragElement); + clearDragElement(); } else if (node == dragElement) { return; } diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VHasDropHandler.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VHasDropHandler.java index ea58757a36..7fc358223c 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/VHasDropHandler.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VHasDropHandler.java @@ -5,8 +5,8 @@ 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}. + * Decide whether to get rid of this class. If so, {@link VAbstractDropHandler} + * must extend {@link Paintable}. * */ public interface VHasDropHandler { diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java index e2ef58cc2d..e810fa6cea 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VTransferable.java @@ -18,12 +18,12 @@ public class VTransferable { private final Map variables = new HashMap(); /** - * Returns the component currently being dragged or from which the - * transferable is created (eg. a tree which node is dragged). + * Returns the component from which the transferable is created (eg. a tree + * which node is dragged). * * @return the component */ - public Paintable getComponent() { + public Paintable getDragSource() { return component; } @@ -38,7 +38,7 @@ public class VTransferable { * @param component * the component to set */ - public void setComponent(Paintable component) { + public void setDragSource(Paintable component) { this.component = component; } diff --git a/src/com/vaadin/ui/CustomComponent.java b/src/com/vaadin/ui/CustomComponent.java index 976775b8f3..661c72b951 100644 --- a/src/com/vaadin/ui/CustomComponent.java +++ b/src/com/vaadin/ui/CustomComponent.java @@ -126,8 +126,11 @@ public class CustomComponent extends AbstractComponentContainer { * The component type is textual type of the component. This is included in * the UIDL as component tag attribute. * + * @deprecated not more useful as the whole tag system has been removed + * * @return the component type. */ + @Deprecated public String getComponentType() { return componentType; } @@ -138,9 +141,12 @@ public class CustomComponent extends AbstractComponentContainer { * The component type is textual type of the component. This is included in * the UIDL as component tag attribute. * + * @deprecated not more useful as the whole tag system has been removed + * * @param componentType * the componentType to set. */ + @Deprecated public void setComponentType(String componentType) { this.componentType = componentType; } diff --git a/src/com/vaadin/ui/DragAndDropWrapper.java b/src/com/vaadin/ui/DragAndDropWrapper.java new file mode 100644 index 0000000000..827aa354b0 --- /dev/null +++ b/src/com/vaadin/ui/DragAndDropWrapper.java @@ -0,0 +1,109 @@ +package com.vaadin.ui; + +import java.util.Collection; +import java.util.Map; + +import com.vaadin.event.ComponentTransferable; +import com.vaadin.event.Transferable; +import com.vaadin.event.dd.DragSource; +import com.vaadin.event.dd.DropHandler; +import com.vaadin.event.dd.DropTarget; +import com.vaadin.event.dd.TargetDetails; +import com.vaadin.terminal.PaintException; +import com.vaadin.terminal.PaintTarget; +import com.vaadin.terminal.gwt.client.ui.VDragAndDropWrapper; + +@ClientWidget(VDragAndDropWrapper.class) +public class DragAndDropWrapper extends CustomComponent implements DropTarget, + DragSource { + + public class DDWrapperTransferable implements ComponentTransferable { + private final Map rawVariables; + + private DDWrapperTransferable(Map rawVariables) { + this.rawVariables = rawVariables; + } + + public void setData(String dataFlawor, Object value) { + // TODO Auto-generated method stub + + } + + public Collection getDataFlawors() { + return rawVariables.keySet(); + } + + public Object getData(String dataFlawor) { + return rawVariables.get(dataFlawor); + } + + public Component getSourceComponent() { + return DragAndDropWrapper.this; + } + + /** + * The component in wrapper that is being dragged or null if the + * transferrable is not a component (most likely an html5 drag). + * + * @return + */ + public Component getDraggedComponent() { + Component object = (Component) rawVariables.get("component"); + return object; + } + } + + public enum DragStartMode { + NONE, COMPONENT, WRAPPER + } + + private DragStartMode dragStartMode = DragStartMode.NONE; + + public DragAndDropWrapper(Component root) { + super(root); + } + + @Override + public void paintContent(PaintTarget target) throws PaintException { + super.paintContent(target); + target.addAttribute("dragStartMode", dragStartMode.ordinal()); + if (getDropHandler() != null) { + getDropHandler().getAcceptCriterion().paint(target); + } + } + + /** + * + */ + private static final long serialVersionUID = 1L; + private DropHandler dropHandler; + + public DropHandler getDropHandler() { + return dropHandler; + } + + public void setDropHandler(DropHandler dropHandler) { + this.dropHandler = dropHandler; + requestRepaint(); + } + + public TargetDetails translateDragDropDetails( + Map clientVariables) { + // TODO Auto-generated method stub + return null; + } + + public Transferable getTransferable(Transferable transferable, + final Map rawVariables) { + return new DDWrapperTransferable(rawVariables); + } + + public void setDragStartMode(DragStartMode dragStartMode) { + this.dragStartMode = dragStartMode; + requestRepaint(); + } + + public DragStartMode getDragStartMode() { + return dragStartMode; + } +} diff --git a/src/com/vaadin/ui/DragDropPane.java b/src/com/vaadin/ui/DragDropPane.java index 24c366156c..923c594551 100644 --- a/src/com/vaadin/ui/DragDropPane.java +++ b/src/com/vaadin/ui/DragDropPane.java @@ -78,7 +78,12 @@ public class DragDropPane extends AbsoluteLayout implements DropTarget { Transferable transferable = event.getTransferable(); if (transferable instanceof ComponentTransferable) { ComponentTransferable ctr = (ComponentTransferable) transferable; - Component component = ctr.getSourceComponent(); + // use "component" (from DragDropPane) if available, else take + // the source component + Component component = (Component) ctr.getData("component"); + if (component == null) { + component = ctr.getSourceComponent(); + } if (component.getParent() != pane) { if (transferable instanceof DataBoundTransferable) { diff --git a/tests/src/com/vaadin/tests/dd/DDTest1.java b/tests/src/com/vaadin/tests/dd/DDTest1.java index 49f47da436..0fad439afe 100644 --- a/tests/src/com/vaadin/tests/dd/DDTest1.java +++ b/tests/src/com/vaadin/tests/dd/DDTest1.java @@ -74,7 +74,8 @@ public class DDTest1 extends TestBase { if (transferable instanceof ComponentTransferable) { ComponentTransferable ct = (ComponentTransferable) transferable; - Component component = ct.getSourceComponent(); + Component component = (Component) ct + .getData("component"); if (component != null) { if (component.toString() != null && component.toString().contains("Bar")) { diff --git a/tests/src/com/vaadin/tests/dd/DDTest5.java b/tests/src/com/vaadin/tests/dd/DDTest5.java new file mode 100644 index 0000000000..6150808058 --- /dev/null +++ b/tests/src/com/vaadin/tests/dd/DDTest5.java @@ -0,0 +1,170 @@ +package com.vaadin.tests.dd; + +import java.util.Iterator; + +import com.vaadin.event.dd.DropEvent; +import com.vaadin.event.dd.DropHandler; +import com.vaadin.event.dd.DropTarget; +import com.vaadin.event.dd.acceptCriteria.AcceptAll; +import com.vaadin.event.dd.acceptCriteria.AcceptCriterion; +import com.vaadin.terminal.ThemeResource; +import com.vaadin.tests.components.TestBase; +import com.vaadin.ui.Component; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.DragAndDropWrapper; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Window; +import com.vaadin.ui.DragAndDropWrapper.DDWrapperTransferable; +import com.vaadin.ui.DragAndDropWrapper.DragStartMode; + +public class DDTest5 extends TestBase { + + java.util.Random r = new java.util.Random(1); + + HorizontalLayout hl = new HorizontalLayout(); + + private DragAndDropWrapper dragAndDropWrapper2; + + private DropHandler dh; + + private static int count; + + class WrappedLabel extends DragAndDropWrapper { + + private static final long serialVersionUID = 1L; + + public WrappedLabel(String content) { + super(new Label(content + " c:" + ++count)); + setDragStartMode(DragStartMode.WRAPPER); + } + + @Override + public DropHandler getDropHandler() { + return dh; + } + + } + + @Override + protected void setup() { + Window w = getLayout().getWindow(); + + Label l; + + l = new Label("Drag me"); + DragAndDropWrapper dragAndDropWrapper = new DragAndDropWrapper(l); + dragAndDropWrapper.setDragStartMode(DragStartMode.COMPONENT); + dragAndDropWrapper.setWidth("100px"); + dragAndDropWrapper.setHeight("100px"); + getLayout().addComponent(dragAndDropWrapper); + + l = new Label("Drag me too"); + dragAndDropWrapper = new DragAndDropWrapper(l); + dragAndDropWrapper.setDragStartMode(DragStartMode.WRAPPER); + dragAndDropWrapper.setWidth("100px"); + dragAndDropWrapper.setHeight("100px"); + getLayout().addComponent(dragAndDropWrapper); + + final CssLayout cssLayout = new CssLayout(); + cssLayout.setHeight("300px"); + + dragAndDropWrapper2 = new DragAndDropWrapper(cssLayout); + dragAndDropWrapper2.setCaption("Drop here"); + + dh = new DropHandler() { + + public AcceptCriterion getAcceptCriterion() { + return AcceptAll.get(); + } + + public void drop(DropEvent dropEvent) { + + /* + * TODO wrap componentns in wrappers (so we can build reordering + * here) + */ + + if (dropEvent.getTransferable() instanceof DDWrapperTransferable) { + DDWrapperTransferable transferable = (DDWrapperTransferable) dropEvent + .getTransferable(); + Component sourceComponent = transferable + .getSourceComponent(); + + Component draggedComponent = transferable + .getDraggedComponent(); + + DropTarget target = dropEvent.getDropTargetData() + .getTarget(); + + WrappedLabel wrappedLabel = new WrappedLabel( + draggedComponent.toString()); + if (target instanceof WrappedLabel) { + int i = 1; // add next to reference by default + Iterator componentIterator = cssLayout + .getComponentIterator(); + Component next = componentIterator.next(); + while (next != target && componentIterator.hasNext()) { + if (next != sourceComponent) { + // don't count on index if component is being + // moved + i++; + } + next = componentIterator.next(); + } + + if (sourceComponent instanceof WrappedLabel) { + cssLayout.removeComponent(sourceComponent); + wrappedLabel = (WrappedLabel) sourceComponent; + } + if (dropEvent.getDropTargetData().getData( + "verticalLocation").equals("Top")) { + // before reference if dropped on topmost part + i--; + if (i < 0) { + i = 0; + } + } + cssLayout.addComponent(wrappedLabel, i); + + } else { + cssLayout.addComponent(wrappedLabel); + } + + } else { + // no component, add label with "Text" + + String data = (String) dropEvent.getTransferable().getData( + "text/plain"); + if (data == null || "".equals(data)) { + data = "-- no Text --"; + } + cssLayout.addComponent(new WrappedLabel(data)); + + } + + } + }; + + dragAndDropWrapper2.setDropHandler(dh); + + getLayout().addComponent(dragAndDropWrapper2); + + } + + private final static ThemeResource FOLDER = new ThemeResource( + "../runo/icons/16/folder.png"); + private final static ThemeResource DOC = new ThemeResource( + "../runo/icons/16/document.png"); + + @Override + protected String getDescription() { + return "dd"; + } + + @Override + protected Integer getTicketNumber() { + return 119; + } + +} -- 2.39.5