From: Matti Tahvonen Date: Tue, 16 Feb 2010 11:39:34 +0000 (+0000) Subject: styles, table drop handler, small changes X-Git-Tag: 6.7.0.beta1~1988^2~15 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7affda148684f0359856eaba85a3d381aec7faa9;p=vaadin-framework.git styles, table drop handler, small changes svn changeset:11339/svn branch:6.3_dd --- diff --git a/WebContent/VAADIN/themes/base/styles.css b/WebContent/VAADIN/themes/base/styles.css index f8cd9a8f8b..eca4525510 100644 --- a/WebContent/VAADIN/themes/base/styles.css +++ b/WebContent/VAADIN/themes/base/styles.css @@ -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; } diff --git a/WebContent/VAADIN/themes/base/table/table.css b/WebContent/VAADIN/themes/base/table/table.css index 7747cd14f1..235594493f 100644 --- a/WebContent/VAADIN/themes/base/table/table.css +++ b/WebContent/VAADIN/themes/base/table/table.css @@ -86,6 +86,19 @@ 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; diff --git a/WebContent/VAADIN/themes/base/tree/tree.css b/WebContent/VAADIN/themes/base/tree/tree.css index 21e41d74a0..8a6fc3b878 100644 --- a/WebContent/VAADIN/themes/base/tree/tree.css +++ b/WebContent/VAADIN/themes/base/tree/tree.css @@ -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; } diff --git a/WebContent/VAADIN/themes/reindeer/styles.css b/WebContent/VAADIN/themes/reindeer/styles.css index eebbff3ee2..c4081182c8 100644 --- a/WebContent/VAADIN/themes/reindeer/styles.css +++ b/WebContent/VAADIN/themes/reindeer/styles.css @@ -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; } diff --git a/WebContent/VAADIN/themes/runo/styles.css b/WebContent/VAADIN/themes/runo/styles.css index 29929ae32e..8d07f54c53 100644 --- a/WebContent/VAADIN/themes/runo/styles.css +++ b/WebContent/VAADIN/themes/runo/styles.css @@ -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; } diff --git a/src/com/vaadin/terminal/gwt/client/Util.java b/src/com/vaadin/terminal/gwt/client/Util.java index 9c6d998adc..5738e1ba49 100644 --- a/src/com/vaadin/terminal/gwt/client/Util.java +++ b/src/com/vaadin/terminal/gwt/client/Util.java @@ -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 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; + } + } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index f878dbd954..99e3ddb3ad 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -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; + } + + } + } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTree.java b/src/com/vaadin/terminal/gwt/client/ui/VTree.java index 1a3edd32be..d0f50d2632 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTree.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTree.java @@ -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 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 74e4d4ca98..f6a3d09b71 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VAbstractDropHandler.java @@ -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 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) { } 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 69053f45ec..8d301c70f2 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VDragAndDropManager.java @@ -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 index 0000000000..8c1f1a7aa1 --- /dev/null +++ b/src/com/vaadin/terminal/gwt/client/ui/dd/VerticalDropLocation.java @@ -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; + } + } +} diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index afc91d7bcf..aae0c95456 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -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; /** *

@@ -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 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 clientVariables) { + return new TableTargetDetails(clientVariables); + } } diff --git a/src/com/vaadin/ui/Tree.java b/src/com/vaadin/ui/Tree.java index 15990500d6..3bb1e6f696 100644 --- a/src/com/vaadin/ui/Tree.java +++ b/src/com/vaadin/ui/Tree.java @@ -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 index 0000000000..fd922c9f4e --- /dev/null +++ b/tests/src/com/vaadin/tests/dd/DDTest4.java @@ -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; + } + +}