]> source.dussan.org Git - vaadin-framework.git/commitdiff
styles, table drop handler, small changes
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Tue, 16 Feb 2010 11:39:34 +0000 (11:39 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Tue, 16 Feb 2010 11:39:34 +0000 (11:39 +0000)
svn changeset:11339/svn branch:6.3_dd

14 files changed:
WebContent/VAADIN/themes/base/styles.css
WebContent/VAADIN/themes/base/table/table.css
WebContent/VAADIN/themes/base/tree/tree.css
WebContent/VAADIN/themes/reindeer/styles.css
WebContent/VAADIN/themes/runo/styles.css
src/com/vaadin/terminal/gwt/client/Util.java
src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
src/com/vaadin/terminal/gwt/client/ui/VTree.java
src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java
src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java
src/com/vaadin/terminal/gwt/client/ui/dd/VerticalDropLocation.java [new file with mode: 0644]
src/com/vaadin/ui/Table.java
src/com/vaadin/ui/Tree.java
tests/src/com/vaadin/tests/dd/DDTest4.java [new file with mode: 0644]

index f8cd9a8f8b4579cc51761aecb578a2b5560071ff..eca4525510011e1af97ee286d80c812efaaabc8a 100644 (file)
@@ -1,5 +1,5 @@
-.v-theme-version:after {content:"6_3_0_dev-20100215";}
-.v-theme-version-6_3_0_dev-20100215 {display: none;}
+.v-theme-version:after {content:"6_3_0_dev-20100216";}
+.v-theme-version-6_3_0_dev-20100216 {display: none;}
 /* Automatically compiled css file from subdirectories. */
 
 .v-absolutelayout-wrapper {
@@ -1330,6 +1330,19 @@ div.v-progressindicator-indeterminate-disabled {
        padding: 0;
        cursor: pointer;
 }
+
+/* TODO remove important, replace with better anchors or order */
+.v-table tr.v-table-row-drag-center {
+       background-color: cyan !important;
+}
+/* TODO consider using height neutral styling (scrollbar issues when pagelength = table.length ) */
+.v-table-row-drag-top .v-table-cell-content {
+       border-top: 1px solid cyan ;
+}
+.v-table-row-drag-bottom .v-table-cell-content {
+       border-bottom: 1px solid cyan;
+}
+
 .v-table-body-noselection .v-table-row,
 .v-table-body-noselection .v-table-row-odd {
        cursor: default;
@@ -1602,10 +1615,23 @@ div.v-tree-node-leaf {
 .v-tree-node-caption .v-icon {
        vertical-align: middle;
 }
+
 .v-tree-node-selected span {
        background: #999;
        color: #fff;
 }
+
+.v-tree-node-drag-top .v-tree-node-caption {
+       border-top:2px solid green;
+}
+.v-tree-node-drag-bottom .v-tree-node-caption {
+       border-bottom:2px solid green;
+}
+.v-tree-node-drag-center .v-tree-node-caption {
+       background-color:green;
+}
+
+
 .v-tree-node-children {
        padding-left: 1em;
 }
index 7747cd14f1c804272469410de1a06ecd40edcb71..235594493ff019f1d64fcc1177ab30e1d07e16e0 100644 (file)
        padding: 0;
        cursor: pointer;
 }
+
+/* TODO remove important, replace with better anchors or order */
+.v-table tr.v-table-row-drag-center {
+       background-color: cyan !important;
+}
+/* TODO consider using height neutral styling (scrollbar issues when pagelength = table.length ) */
+.v-table-row-drag-top .v-table-cell-content {
+       border-top: 1px solid cyan ;
+}
+.v-table-row-drag-bottom .v-table-cell-content {
+       border-bottom: 1px solid cyan;
+}
+
 .v-table-body-noselection .v-table-row,
 .v-table-body-noselection .v-table-row-odd {
        cursor: default;
index 21e41d74a071fe653bf28411bacade62ce3ce5eb..8a6fc3b878213b0b38c88eba9eb5694d4245d1a0 100644 (file)
@@ -24,10 +24,22 @@ div.v-tree-node-leaf {
 .v-tree-node-caption .v-icon {
        vertical-align: middle;
 }
+
 .v-tree-node-selected span {
        background: #999;
        color: #fff;
 }
+
+.v-tree-node-drag-top .v-tree-node-caption {
+       border-top:2px solid green;
+}
+.v-tree-node-drag-bottom .v-tree-node-caption {
+       border-bottom:2px solid green;
+}
+.v-tree-node-drag-center .v-tree-node-caption {
+       background-color:green;
+}
+
 .v-tree-node-children {
        padding-left: 1em;
 }
index eebbff3ee22ae9dd401010d8b87f588f21bc59d3..c4081182c804e2eb704b5b4b0d892f1ec297fb5d 100644 (file)
@@ -1,5 +1,5 @@
-.v-theme-version:after {content:"6_3_0_dev-20100215";}
-.v-theme-version-6_3_0_dev-20100215 {display: none;}
+.v-theme-version:after {content:"6_3_0_dev-20100216";}
+.v-theme-version-6_3_0_dev-20100216 {display: none;}
 /* Automatically compiled css file from subdirectories. */
 
 .v-absolutelayout-wrapper {
@@ -1330,6 +1330,19 @@ div.v-progressindicator-indeterminate-disabled {
        padding: 0;
        cursor: pointer;
 }
+
+/* TODO remove important, replace with better anchors or order */
+.v-table tr.v-table-row-drag-center {
+       background-color: cyan !important;
+}
+/* TODO consider using height neutral styling (scrollbar issues when pagelength = table.length ) */
+.v-table-row-drag-top .v-table-cell-content {
+       border-top: 1px solid cyan ;
+}
+.v-table-row-drag-bottom .v-table-cell-content {
+       border-bottom: 1px solid cyan;
+}
+
 .v-table-body-noselection .v-table-row,
 .v-table-body-noselection .v-table-row-odd {
        cursor: default;
@@ -1602,10 +1615,23 @@ div.v-tree-node-leaf {
 .v-tree-node-caption .v-icon {
        vertical-align: middle;
 }
+
 .v-tree-node-selected span {
        background: #999;
        color: #fff;
 }
+
+.v-tree-node-drag-top .v-tree-node-caption {
+       border-top:2px solid green;
+}
+.v-tree-node-drag-bottom .v-tree-node-caption {
+       border-bottom:2px solid green;
+}
+.v-tree-node-drag-center .v-tree-node-caption {
+       background-color:green;
+}
+
+
 .v-tree-node-children {
        padding-left: 1em;
 }
index 29929ae32edde44a86b07cf90538dc6527b08017..8d07f54c530065616b8118285efd72896b46f9b4 100644 (file)
@@ -1,5 +1,5 @@
-.v-theme-version:after {content:"6_3_0_dev-20100215";}
-.v-theme-version-6_3_0_dev-20100215 {display: none;}
+.v-theme-version:after {content:"6_3_0_dev-20100216";}
+.v-theme-version-6_3_0_dev-20100216 {display: none;}
 /* Automatically compiled css file from subdirectories. */
 
 .v-absolutelayout-wrapper {
@@ -1330,6 +1330,19 @@ div.v-progressindicator-indeterminate-disabled {
        padding: 0;
        cursor: pointer;
 }
+
+/* TODO remove important, replace with better anchors or order */
+.v-table tr.v-table-row-drag-center {
+       background-color: cyan !important;
+}
+/* TODO consider using height neutral styling (scrollbar issues when pagelength = table.length ) */
+.v-table-row-drag-top .v-table-cell-content {
+       border-top: 1px solid cyan ;
+}
+.v-table-row-drag-bottom .v-table-cell-content {
+       border-bottom: 1px solid cyan;
+}
+
 .v-table-body-noselection .v-table-row,
 .v-table-body-noselection .v-table-row-odd {
        cursor: default;
@@ -1602,10 +1615,23 @@ div.v-tree-node-leaf {
 .v-tree-node-caption .v-icon {
        vertical-align: middle;
 }
+
 .v-tree-node-selected span {
        background: #999;
        color: #fff;
 }
+
+.v-tree-node-drag-top .v-tree-node-caption {
+       border-top:2px solid green;
+}
+.v-tree-node-drag-bottom .v-tree-node-caption {
+       border-bottom:2px solid green;
+}
+.v-tree-node-drag-center .v-tree-node-caption {
+       background-color:green;
+}
+
+
 .v-tree-node-children {
        padding-left: 1em;
 }
index 9c6d998adcc87e141ccf1d25bcdad687ffab9e08..5738e1ba49f0ae37eb067c6837a5c9c58ef81271 100644 (file)
@@ -16,6 +16,8 @@ import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.EventListener;
 import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.HasWidgets;
@@ -845,4 +847,33 @@ public class Util {
         }
     }-*/;
 
+    /**
+     * Helper method to find first instance of given Widget type found by
+     * traversing DOM upwards.
+     * 
+     * @param element
+     * @param class1
+     */
+    public static <T> T findWidget(Element element, Class class1) {
+        if (element != null) {
+            EventListener eventListener = null;
+            while (eventListener == null && element != null) {
+                eventListener = Event.getEventListener(element);
+                if (eventListener == null) {
+                    element = (Element) element.getParentElement();
+                }
+            }
+            if (eventListener != null) {
+                Widget w = (Widget) eventListener;
+                while (w != null) {
+                    if (class1 == null || w.getClass() == class1) {
+                        return (T) w;
+                    }
+                    w = w.getParent();
+                }
+            }
+        }
+        return null;
+    }
+
 }
index f878dbd9542dc43cd9dd6ff41502f7563d672b48..99e3ddb3ad7337aa20dcf065b86603cef5fbc07f 100644 (file)
@@ -40,9 +40,13 @@ import com.vaadin.terminal.gwt.client.RenderSpace;
 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.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.VHasDropHandler;
 import com.vaadin.terminal.gwt.client.ui.dd.VTransferable;
+import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation;
 
 /**
  * VScrollTable
@@ -67,7 +71,8 @@ import com.vaadin.terminal.gwt.client.ui.dd.VTransferable;
  * 
  * TODO implement unregistering for child components in Cells
  */
-public class VScrollTable extends FlowPanel implements Table, ScrollHandler {
+public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
+        VHasDropHandler {
 
     public static final String CLASSNAME = "v-table";
     public static final String ITEM_CLICK_EVENT_ID = "itemClick";
@@ -263,6 +268,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler {
         }
 
         UIDL rowData = null;
+        UIDL ac = null;
         for (final Iterator it = uidl.getChildIterator(); it.hasNext();) {
             final UIDL c = (UIDL) it.next();
             if (c.getTag().equals("rows")) {
@@ -271,8 +277,21 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler {
                 updateActionMap(c);
             } else if (c.getTag().equals("visiblecolumns")) {
                 tHead.updateCellsFromUIDL(c);
+            } else if (c.getTag().equals("-ac")) {
+                ac = c;
             }
         }
+        if (ac == null) {
+            if (dropHandler != null) {
+                // remove dropHandler if not present anymore
+                dropHandler = null;
+            }
+        } else {
+            if (dropHandler == null) {
+                dropHandler = new VScrollTableDropHandler();
+            }
+            dropHandler.updateAcceptRules(ac);
+        }
         updateHeader(uidl.getStringArrayAttribute("vcolorder"));
 
         if (!recalcWidths && initializedAndAttached) {
@@ -2921,6 +2940,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler {
     private int contentAreaBorderHeight = -1;
     private int scrollLeft;
     private int scrollTop;
+    private VScrollTableDropHandler dropHandler;
 
     /**
      * @return border top + border bottom of the scrollable area of table
@@ -3099,4 +3119,157 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler {
         }
     }
 
+    public VScrollTableDropHandler getDropHandler() {
+        return dropHandler;
+    }
+
+    private static class TableDDDetails {
+        int overkey = -1;
+        VerticalDropLocation dropLocation;
+        String colkey;
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof TableDDDetails) {
+                TableDDDetails other = (TableDDDetails) obj;
+                return dropLocation == other.dropLocation
+                        && overkey == other.overkey
+                        && ((colkey != null && colkey.equals(other.colkey)) || (colkey == null && other.colkey == null));
+            }
+            return false;
+        }
+
+        // @Override
+        // public int hashCode() {
+        // return overkey;
+        // }
+    }
+
+    public class VScrollTableDropHandler extends VAbstractDropHandler {
+
+        private static final String ROWSTYLEBASE = "v-table-row-drag-";
+        private TableDDDetails dropDetails;
+        private TableDDDetails lastEmphasized;
+
+        @Override
+        public void dragEnter(VDragEvent drag) {
+            updateDropDetails(drag);
+            super.dragEnter(drag);
+        }
+
+        private void updateDropDetails(VDragEvent drag) {
+            dropDetails = new TableDDDetails();
+            Element elementOver = drag.getElementOver();
+
+            VScrollTableRow row = Util.findWidget(elementOver,
+                    VScrollTableRow.class);
+            if (row != null) {
+                dropDetails.overkey = row.rowKey;
+                Element tr = row.getElement();
+                Element element = elementOver;
+                while (element != null && element.getParentElement() != tr) {
+                    element = (Element) element.getParentElement();
+                }
+                int childIndex = DOM.getChildIndex(tr, element);
+                dropDetails.colkey = tHead.getHeaderCell(childIndex)
+                        .getColKey();
+                dropDetails.dropLocation = VerticalDropLocation.get(row
+                        .getElement(), drag.getCurrentGwtEvent().getClientY(),
+                        0.2);
+            }
+
+            drag.getDropDetails().put("itemIdOver", dropDetails.overkey + "");
+            drag.getDropDetails().put(
+                    "detail",
+                    dropDetails.dropLocation != null ? dropDetails.dropLocation
+                            .toString() : null);
+
+        }
+
+        @Override
+        public void dragOver(VDragEvent drag) {
+            TableDDDetails oldDetails = dropDetails;
+            updateDropDetails(drag);
+            if (!oldDetails.equals(dropDetails)) {
+                deEmphasis();
+                VAcceptCallback cb = new VAcceptCallback() {
+                    public void accepted(VDragEvent event) {
+                        dragAccepted(event);
+                    }
+                };
+                validate(cb, drag);
+            }
+        }
+
+        @Override
+        public void dragLeave(VDragEvent drag) {
+            deEmphasis();
+            super.dragLeave(drag);
+        }
+
+        @Override
+        public boolean drop(VDragEvent drag) {
+            deEmphasis();
+            return super.drop(drag);
+        }
+
+        private void deEmphasis() {
+            if (lastEmphasized == null) {
+                return;
+            }
+            for (Widget w : scrollBody.renderedRows) {
+                VScrollTableRow row = (VScrollTableRow) w;
+                if (lastEmphasized != null
+                        && row.rowKey == lastEmphasized.overkey) {
+                    if (row != null) {
+                        String stylename = ROWSTYLEBASE
+                                + lastEmphasized.dropLocation.toString()
+                                        .toLowerCase();
+                        VScrollTableRow.setStyleName(row.getElement(),
+                                stylename, false);
+                    }
+                    lastEmphasized = null;
+                    return;
+                }
+            }
+        }
+
+        /**
+         * TODO needs different drop modes ?? (on cells, on rows), now only
+         * supports rows
+         */
+        private void emphasis(TableDDDetails details) {
+            deEmphasis();
+            // iterate old and new emphasized row
+            for (Widget w : scrollBody.renderedRows) {
+                VScrollTableRow row = (VScrollTableRow) w;
+                if (details != null && details.overkey == row.rowKey) {
+                    if (row != null) {
+                        String stylename = ROWSTYLEBASE
+                                + details.dropLocation.toString().toLowerCase();
+                        VScrollTableRow.setStyleName(row.getElement(),
+                                stylename, true);
+                    }
+                    lastEmphasized = details;
+                    return;
+                }
+            }
+        }
+
+        @Override
+        protected void dragAccepted(VDragEvent drag) {
+            emphasis(dropDetails);
+        }
+
+        @Override
+        public Paintable getPaintable() {
+            return VScrollTable.this;
+        }
+
+        public ApplicationConnection getApplicationConnection() {
+            return client;
+        }
+
+    }
+
 }
index 1a3edd32beb8e490ecfae3ace06b487ad898b0fe..d0f50d2632bc61ba15d333fa2d8b76b1967d1434 100644 (file)
@@ -10,14 +10,13 @@ import java.util.Iterator;
 import java.util.Set;
 
 import com.google.gwt.dom.client.NativeEvent;
-import com.google.gwt.dom.client.Style;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.EventListener;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.SimplePanel;
+import com.google.gwt.user.client.ui.UIObject;
 import com.google.gwt.user.client.ui.Widget;
 import com.vaadin.terminal.gwt.client.ApplicationConnection;
 import com.vaadin.terminal.gwt.client.BrowserInfo;
@@ -32,6 +31,7 @@ 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.VerticalDropLocation;
 
 /**
  * 
@@ -179,25 +179,7 @@ public class VTree extends FlowPanel implements Paintable, VHasDropHandler {
     }
 
     private String findCurrentMouseOverKey(Element elementOver) {
-        TreeNode treeNode = null;
-        Element curEl = elementOver;
-        while (curEl != null) {
-            try {
-                EventListener eventListener = Event.getEventListener(curEl);
-                if (eventListener != null) {
-                    // found a widget
-                    if (eventListener instanceof TreeNode) {
-                        treeNode = (TreeNode) eventListener;
-                    }
-                    break;
-                } else {
-                    curEl = (Element) curEl.getParentElement();
-                }
-            } catch (Exception e) {
-                ApplicationConnection.getConsole().log(e.getMessage());
-                e.printStackTrace();
-            }
-        }
+        TreeNode treeNode = Util.findWidget(elementOver, TreeNode.class);
         return treeNode == null ? null : treeNode.key;
     }
 
@@ -290,24 +272,9 @@ public class VTree extends FlowPanel implements Paintable, VHasDropHandler {
         if (treeNode == null) {
             return null;
         }
-        // TODO no scroll support
-        int offsetHeight = treeNode.nodeCaptionDiv.getOffsetHeight();
-        int absoluteTop = treeNode.getAbsoluteTop();
-        int clientY = event.getClientY();
-        int fromTop = clientY - absoluteTop;
-
-        String detail;
-        float percentageFromTop = (fromTop / (float) offsetHeight);
-        if (percentageFromTop < 0.2) {
-            detail = "Top";
-        } else if (percentageFromTop > 0.8) {
-            detail = "Bottom";
-        } else {
-            detail = "Center";
-        }
-
-        return detail;
-
+        VerticalDropLocation verticalDropLocation = VerticalDropLocation.get(
+                treeNode.getElement(), event.getClientY(), 0.2);
+        return verticalDropLocation.toString();
     }
 
     private void handleUpdate(UIDL uidl) {
@@ -387,16 +354,13 @@ public class VTree extends FlowPanel implements Paintable, VHasDropHandler {
         }
 
         public void emphasis(String string) {
-            // ApplicationConnection.getConsole().log("OUTLINE" + string);
-            Style style = nodeCaptionDiv.getStyle();
-            String top = "Top".equals(string) ? "2px solid green" : "";
-            String bottom = "Bottom".equals(string) ? "2px solid green" : "";
-            String bg = "Center".equals(string) ? "green" : "";
-
-            style.setProperty("borderTop", top);
-            style.setProperty("borderBottom", bottom);
-            style.setBackgroundColor(bg);
-
+            String base = "v-tree-node-drag-";
+            UIObject.setStyleName(getElement(), base + "top", "Top"
+                    .equals(string));
+            UIObject.setStyleName(getElement(), base + "bottom", "Bottom"
+                    .equals(string));
+            UIObject.setStyleName(getElement(), base + "center", "Center"
+                    .equals(string));
         }
 
         @Override
index 74e4d4ca981daec4a4ff6f13b5a1b46c7e721cd4..f6a3d09b71c3947c88ac28f6ff40a12489a01b55 100644 (file)
@@ -1,5 +1,7 @@
 package com.vaadin.terminal.gwt.client.ui.dd;
 
+import java.util.Iterator;
+
 import com.google.gwt.user.client.Command;
 import com.vaadin.event.Transferable;
 import com.vaadin.event.dd.DropTarget;
@@ -10,7 +12,7 @@ import com.vaadin.terminal.gwt.client.UIDL;
 public abstract class VAbstractDropHandler implements VDropHandler {
 
     private UIDL criterioUIDL;
-    private VAcceptCriteria acceptCriteria;
+    private VAcceptCriteria acceptCriteria = new AcceptAll();
 
     /**
      * Implementor/user of {@link VAbstractDropHandler} must pass the UIDL
@@ -21,6 +23,16 @@ public abstract class VAbstractDropHandler implements VDropHandler {
      */
     public void updateAcceptRules(UIDL uidl) {
         criterioUIDL = uidl;
+        /*
+         * supports updating the accept rule root directly or so that it is
+         * contained in given uidl node
+         */
+        if (!uidl.getTag().equals("-ac")) {
+            Iterator<Object> childIterator = uidl.getChildIterator();
+            while (!uidl.getTag().equals("-ac") && childIterator.hasNext()) {
+                uidl = (UIDL) childIterator.next();
+            }
+        }
         acceptCriteria = VAcceptCriterion.get(uidl.getStringAttribute("name"));
         if (acceptCriteria == null) {
             throw new IllegalArgumentException(
@@ -32,7 +44,7 @@ public abstract class VAbstractDropHandler implements VDropHandler {
     /**
      * Default implementation does nothing.
      */
-    public void dragOver(VDragEvent currentDrag) {
+    public void dragOver(VDragEvent drag) {
 
     }
 
index 69053f45ec36dfa0c1a96be0dbf7f1fafbf609bc..8d301c70f26ddd5f8c9a5e29085d449bbe822802 100644 (file)
@@ -11,7 +11,6 @@ import com.google.gwt.dom.client.Style.Unit;
 import com.google.gwt.event.shared.HandlerRegistration;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.Event;
-import com.google.gwt.user.client.EventListener;
 import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.Event.NativePreviewEvent;
 import com.google.gwt.user.client.Event.NativePreviewHandler;
@@ -66,8 +65,8 @@ public class VDragAndDropManager {
                         return;
 
                     } else {
-                        ApplicationConnection.getConsole().log(
-                                "Event on dragImage, target changed");
+                        // ApplicationConnection.getConsole().log(
+                        // "Event on dragImage, target changed");
                         // special handling for events over dragImage
                         // pretty much all events are mousemove althout below
                         // kind of happens mouseover
@@ -89,6 +88,13 @@ public class VDragAndDropManager {
                                 }
                                 // dragenter on new
                                 currentDropHandler = findDragTarget;
+                                if (findDragTarget != null) {
+                                    ApplicationConnection.getConsole().log(
+                                            "DropHandler now"
+                                                    + currentDropHandler
+                                                            .getPaintable());
+                                }
+
                                 if (currentDropHandler != null) {
                                     currentDrag
                                             .setElementOver((com.google.gwt.user.client.Element) targetElement);
@@ -114,10 +120,10 @@ public class VDragAndDropManager {
                         }
 
                     }
-                } catch (Exception e) {
+                } catch (RuntimeException e) {
                     ApplicationConnection.getConsole().log(
-                            "FIXME : ERROR in elementFromPoint hack.");
-                    throw new RuntimeException(e);
+                            "ERROR during elementFromPoint hack.");
+                    throw e;
                 } finally {
                     dragElement.getStyle().setProperty("display", display);
                 }
@@ -133,7 +139,11 @@ public class VDragAndDropManager {
                     if (currentDropHandler != null) {
                         currentDropHandler.dragLeave(currentDrag);
                     }
+
                     currentDropHandler = target;
+                    ApplicationConnection.getConsole().log(
+                            "DropHandler now"
+                                    + currentDropHandler.getPaintable());
                     target.dragEnter(currentDrag);
                 } else if (target == null && currentDropHandler != null) {
                     ApplicationConnection.getConsole().log("Invalid state!?");
@@ -402,25 +412,12 @@ public class VDragAndDropManager {
      * @return
      */
     private VDropHandler findDragTarget(Element element) {
-        EventListener eventListener = Event.getEventListener(element);
-        while (eventListener == null) {
-            element = element.getParentElement();
-            if (element == null) {
-                break;
-            }
-            try {
-                eventListener = Event.getEventListener(element);
-            } catch (Exception e) {
-                // CCE Should not happen but it does to me // MT 1.2.2010
-                e.printStackTrace();
+        try {
+            Widget w = Util.findWidget(
+                    (com.google.gwt.user.client.Element) element, null);
+            if (w == null) {
+                return null;
             }
-        }
-        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) {
@@ -439,7 +436,14 @@ public class VDragAndDropManager {
                 }
                 return dh;
             }
+
+        } catch (Exception e) {
+            ApplicationConnection.getConsole().log(
+                    "FIXME: Exception when detecting drop handler");
+            e.printStackTrace();
+            return null;
         }
+
     }
 
     private void updateCurrentEvent(NativeEvent event) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/dd/VerticalDropLocation.java b/src/com/vaadin/terminal/gwt/client/ui/dd/VerticalDropLocation.java
new file mode 100644 (file)
index 0000000..8c1f1a7
--- /dev/null
@@ -0,0 +1,24 @@
+package com.vaadin.terminal.gwt.client.ui.dd;
+
+import com.google.gwt.user.client.Element;
+
+public enum VerticalDropLocation {
+    Top, Bottom, Center;
+
+    public static VerticalDropLocation get(Element element, int clientY,
+            double topBottomRatio) {
+
+        int absoluteTop = element.getAbsoluteTop();
+        int offsetHeight = element.getOffsetHeight();
+        int fromTop = clientY - absoluteTop;
+
+        float percentageFromTop = (fromTop / (float) offsetHeight);
+        if (percentageFromTop < topBottomRatio) {
+            return Top;
+        } else if (percentageFromTop > 1 - topBottomRatio) {
+            return Bottom;
+        } else {
+            return Center;
+        }
+    }
+}
index afc91d7bcfd56155e164c862ffb6cbfdabd363a5..aae0c9545657e7c9bed66e6a2cb9f1879f4e6af6 100644 (file)
@@ -30,12 +30,17 @@ import com.vaadin.event.Action.Handler;
 import com.vaadin.event.ItemClickEvent.ItemClickListener;
 import com.vaadin.event.ItemClickEvent.ItemClickSource;
 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.event.dd.TargetDetailsImpl;
 import com.vaadin.terminal.KeyMapper;
 import com.vaadin.terminal.PaintException;
 import com.vaadin.terminal.PaintTarget;
 import com.vaadin.terminal.Resource;
 import com.vaadin.terminal.gwt.client.MouseEventDetails;
 import com.vaadin.terminal.gwt.client.ui.VScrollTable;
+import com.vaadin.ui.Tree.Location;
 
 /**
  * <p>
@@ -57,7 +62,8 @@ import com.vaadin.terminal.gwt.client.ui.VScrollTable;
 @SuppressWarnings("serial")
 @ClientWidget(VScrollTable.class)
 public class Table extends AbstractSelect implements Action.Container,
-        Container.Ordered, Container.Sortable, ItemClickSource, DragSource {
+        Container.Ordered, Container.Sortable, ItemClickSource, DragSource,
+        DropTarget {
 
     /**
      * Modes that Table support as drag sourse.
@@ -339,6 +345,8 @@ public class Table extends AbstractSelect implements Action.Container,
 
     private DragModes dragMode = DragModes.NONE;
 
+    private DropHandler dropHandler;
+
     /* Table constructors */
 
     /**
@@ -2372,6 +2380,10 @@ public class Table extends AbstractSelect implements Action.Container,
             }
         }
         target.endTag("visiblecolumns");
+
+        if (dropHandler != null) {
+            dropHandler.getAcceptCriterion().paint(target);
+        }
     }
 
     /**
@@ -3367,4 +3379,54 @@ public class Table extends AbstractSelect implements Action.Container,
         updateTransferable(rawVariables, transferable);
         return (TableTransferable) transferable;
     }
+
+    public DropHandler getDropHandler() {
+        return dropHandler;
+    }
+
+    public void setDropHandler(DropHandler dropHandler) {
+        this.dropHandler = dropHandler;
+    }
+
+    /*
+     * TODO add propertyId
+     */
+    public class TableTargetDetails extends TargetDetailsImpl {
+        private Object idOver;
+
+        public TableTargetDetails(Map<String, Object> rawDropData) {
+            super(rawDropData);
+            // eagar fetch itemid, mapper may be emptied
+            String keyover = (String) getData("itemIdOver");
+            if (keyover != null) {
+                idOver = itemIdMapper.get(keyover);
+            }
+        }
+
+        public Object getItemIdOver() {
+            return idOver;
+        }
+
+        public Location getDropLocation() {
+            String s = (String) getData("detail");
+            if ("Top".equals(s)) {
+                return Location.TOP;
+            } else if ("Bottom".equals(s)) {
+                return Location.BOTTOM;
+            } else {
+                return Location.MIDDLE;
+            }
+        }
+
+        @Override
+        public Table getTarget() {
+            return (Table) super.getTarget();
+        }
+
+    }
+
+    public TargetDetails translateDragDropDetails(
+            Map<String, Object> clientVariables) {
+        return new TableTargetDetails(clientVariables);
+    }
 }
index 15990500d69f4342b9f980430216ab724fea0f4c..3bb1e6f696446abefd24cf4326091ea9be467afb 100644 (file)
@@ -1157,7 +1157,7 @@ public class Tree extends AbstractSelect implements Container.Hierarchical,
     }
 
     public enum Location {
-        TOP, BOTTOM, MIDDLE
+        TOP, BOTTOM, MIDDLE;
     }
 
     public class TreeDropDetails extends TargetDetailsImpl {
diff --git a/tests/src/com/vaadin/tests/dd/DDTest4.java b/tests/src/com/vaadin/tests/dd/DDTest4.java
new file mode 100644 (file)
index 0000000..fd922c9
--- /dev/null
@@ -0,0 +1,131 @@
+package com.vaadin.tests.dd;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.demo.tutorial.addressbook.data.Person;
+import com.vaadin.demo.tutorial.addressbook.data.PersonContainer;
+import com.vaadin.event.DataBoundTransferable;
+import com.vaadin.event.dd.DropEvent;
+import com.vaadin.event.dd.DropHandler;
+import com.vaadin.event.dd.acceptCriteria.AcceptCriterion;
+import com.vaadin.event.dd.acceptCriteria.ComponentFilter;
+import com.vaadin.terminal.ThemeResource;
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.Tree;
+import com.vaadin.ui.Window;
+import com.vaadin.ui.Table.TableTargetDetails;
+import com.vaadin.ui.Tree.Location;
+
+public class DDTest4 extends TestBase {
+
+    java.util.Random r = new java.util.Random(1);
+
+    HorizontalLayout hl = new HorizontalLayout();
+    Table table = new Table("Drag and drop sortable table");
+
+    private Tree tree3;
+
+    @Override
+    protected void setup() {
+        Window w = getLayout().getWindow();
+        /* darn reindeer has no icons */
+
+        // hl.addComponent(tree1);
+        hl.addComponent(table);
+        // hl.addComponent(tree2);
+        hl.setWidth("100%");
+        hl.setSpacing(true);
+        hl.setExpandRatio(table, 1);
+        table.setWidth("100%");
+        table.setPageLength(10);
+        populateTable();
+        addComponent(hl);
+
+        /*
+         * Make table rows draggable
+         */
+        table.setDragMode(Table.DragModes.ROWS);
+
+        table.setDropHandler(new DropHandler() {
+            // accept only drags from this table
+            AcceptCriterion crit = new ComponentFilter(table);
+
+            public AcceptCriterion getAcceptCriterion() {
+                return crit;
+            }
+
+            public void drop(DropEvent dropEvent) {
+                Table.TableTargetDetails dropTargetData = (TableTargetDetails) dropEvent
+                        .getDropTargetData();
+                DataBoundTransferable transferable = (DataBoundTransferable) dropEvent
+                        .getTransferable();
+                Object itemIdOver = dropTargetData.getItemIdOver();
+                Object itemId = transferable.getItemId();
+                if (itemId == null || itemIdOver == null
+                        || itemId.equals(itemIdOver)) {
+                    return; // no move happened
+                }
+
+                // IndexedContainer goodies... (hint: don't use it in real apps)
+                IndexedContainer containerDataSource = (IndexedContainer) table
+                        .getContainerDataSource();
+                IndexedContainer clone = null;
+                try {
+                    clone = (IndexedContainer) containerDataSource.clone();
+                    int newIndex = containerDataSource.indexOfId(itemIdOver);
+                    if (dropTargetData.getDropLocation() != Location.TOP) {
+                        newIndex++;
+                    }
+                    containerDataSource.removeItem(itemId);
+                    Item newItem = containerDataSource.addItemAt(newIndex,
+                            itemId);
+
+                    Item item = clone.getItem(itemId);
+                    for (Object propId : item.getItemPropertyIds()) {
+                        newItem.getItemProperty(propId).setValue(
+                                item.getItemProperty(propId).getValue());
+                    }
+                } catch (CloneNotSupportedException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+
+            }
+        });
+
+    }
+
+    private void populateTable() {
+        table.addContainerProperty("Name", String.class, "");
+        table.addContainerProperty("Weight", Integer.class, 0);
+
+        PersonContainer testData = PersonContainer.createWithTestData();
+
+        for (int i = 0; i < 10; i++) {
+            Item addItem = table.addItem("Item" + i);
+            Person p = testData.getIdByIndex(i);
+            addItem.getItemProperty("Name").setValue(
+                    p.getFirstName() + " " + p.getLastName());
+            addItem.getItemProperty("Weight").setValue(50 + r.nextInt(60));
+        }
+
+    }
+
+    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;
+    }
+
+}