diff options
author | Matti Tahvonen <matti.tahvonen@itmill.com> | 2010-01-28 17:46:50 +0000 |
---|---|---|
committer | Matti Tahvonen <matti.tahvonen@itmill.com> | 2010-01-28 17:46:50 +0000 |
commit | 810017204ef10e2d5fbea15ed17b0c1e8a6b0daa (patch) | |
tree | 86dd95e68bddc78016f5eeab6687554ea79563a7 /src/com/vaadin | |
parent | 1e2a4afc96a7376b922b342224f8e2e4297385aa (diff) | |
download | vaadin-framework-810017204ef10e2d5fbea15ed17b0c1e8a6b0daa.tar.gz vaadin-framework-810017204ef10e2d5fbea15ed17b0c1e8a6b0daa.zip |
some preliminary drag and drop stuff
svn changeset:11052/svn branch:6.3_dd
Diffstat (limited to 'src/com/vaadin')
-rw-r--r-- | src/com/vaadin/data/util/ContainerHierarchicalWrapper.java | 23 | ||||
-rw-r--r-- | src/com/vaadin/data/util/HierarchicalContainer.java | 26 | ||||
-rw-r--r-- | src/com/vaadin/data/util/IndexedContainer.java | 3 | ||||
-rw-r--r-- | src/com/vaadin/launcher/DevelopmentServerLauncher.java | 4 | ||||
-rw-r--r-- | src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml | 12 | ||||
-rwxr-xr-x | src/com/vaadin/terminal/gwt/client/ApplicationConnection.java | 9 | ||||
-rw-r--r-- | src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java | 9 | ||||
-rw-r--r-- | src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java | 55 | ||||
-rw-r--r-- | src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java | 37 | ||||
-rw-r--r-- | src/com/vaadin/terminal/gwt/client/ui/VTree.java | 238 | ||||
-rw-r--r-- | src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java | 33 | ||||
-rw-r--r-- | src/com/vaadin/ui/AbsoluteLayout.java | 1 | ||||
-rw-r--r-- | src/com/vaadin/ui/CustomLayout.java | 56 | ||||
-rw-r--r-- | src/com/vaadin/ui/Select.java | 6 | ||||
-rw-r--r-- | src/com/vaadin/ui/Table.java | 76 | ||||
-rw-r--r-- | src/com/vaadin/ui/Tree.java | 89 |
16 files changed, 579 insertions, 98 deletions
diff --git a/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java b/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java index 6420aaf838..d516c870a2 100644 --- a/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java +++ b/src/com/vaadin/data/util/ContainerHierarchicalWrapper.java @@ -129,16 +129,6 @@ public class ContainerHierarchicalWrapper implements Container.Hierarchical, return 0; } }; - Object[] array = roots.toArray(); - Arrays.sort(array, basedOnOrderFromWrappedContainer); - roots = new LinkedHashSet<Object>(); - for (int i = 0; i < array.length; i++) { - roots.add(array[i]); - } - for (Object object : children.keySet()) { - LinkedList<Object> object2 = children.get(object); - Collections.sort(object2, basedOnOrderFromWrappedContainer); - } // Calculate the set of all items in the hierarchy final HashSet<Object> s = new HashSet<Object>(); @@ -163,6 +153,18 @@ public class ContainerHierarchicalWrapper implements Container.Hierarchical, s.add(id); } } + + Object[] array = roots.toArray(); + Arrays.sort(array, basedOnOrderFromWrappedContainer); + roots = new LinkedHashSet<Object>(); + for (int i = 0; i < array.length; i++) { + roots.add(array[i]); + } + for (Object object : children.keySet()) { + LinkedList<Object> object2 = children.get(object); + Collections.sort(object2, basedOnOrderFromWrappedContainer); + } + } } } @@ -204,6 +206,7 @@ public class ContainerHierarchicalWrapper implements Container.Hierarchical, */ private void addToHierarchyWrapper(Object itemId) { roots.add(itemId); + } /* diff --git a/src/com/vaadin/data/util/HierarchicalContainer.java b/src/com/vaadin/data/util/HierarchicalContainer.java index f5b65f1dad..2b5519e651 100644 --- a/src/com/vaadin/data/util/HierarchicalContainer.java +++ b/src/com/vaadin/data/util/HierarchicalContainer.java @@ -139,6 +139,25 @@ public class HierarchicalContainer extends IndexedContainer implements return true; } + @Override + public Item addItemAt(int index, Object newItemId) { + Item retval = super.addItemAt(index, newItemId); + if (getParent(newItemId) == null) { + int refIndex = roots.size() - 1; + int indexOfId = indexOfId(roots.get(refIndex)); + while (indexOfId > index) { + refIndex--; + if (refIndex < 0) { + // inserts as first + break; + } + indexOfId = indexOfId(roots.get(refIndex)); + } + roots.add(refIndex + 1, newItemId); + } + return retval; + } + /** * <p> * Sets the parent of an Item. The new parent item must exist and be able to @@ -293,7 +312,12 @@ public class HierarchicalContainer extends IndexedContainer implements if (isRoot(itemId)) { roots.remove(itemId); } - children.remove(itemId); + LinkedList<Object> remove = children.remove(itemId); + if (remove != null) { + for (Object object : remove) { + removeItem(object); + } + } final Object p = parent.get(itemId); if (p != null) { final LinkedList c = children.get(p); diff --git a/src/com/vaadin/data/util/IndexedContainer.java b/src/com/vaadin/data/util/IndexedContainer.java index f5dddf5e23..d6d6d9e77c 100644 --- a/src/com/vaadin/data/util/IndexedContainer.java +++ b/src/com/vaadin/data/util/IndexedContainer.java @@ -557,6 +557,9 @@ public class IndexedContainer implements Container.Indexed, return null; } } + if (index < 0) { + index = 0; + } return addItemAt(index, newItemId); } diff --git a/src/com/vaadin/launcher/DevelopmentServerLauncher.java b/src/com/vaadin/launcher/DevelopmentServerLauncher.java index 1ba7e69da0..68470937b3 100644 --- a/src/com/vaadin/launcher/DevelopmentServerLauncher.java +++ b/src/com/vaadin/launcher/DevelopmentServerLauncher.java @@ -12,8 +12,6 @@ import org.mortbay.jetty.Server; import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.webapp.WebAppContext;
-import com.vaadin.launcher.util.BrowserLauncher;
-
/**
* Class for running Jetty servlet container within Eclipse project.
*
@@ -42,7 +40,7 @@ public class DevelopmentServerLauncher { // Start Browser
System.out.println("Starting Web Browser.");
if (url != null) {
- BrowserLauncher.openBrowser(url);
+ // BrowserLauncher.openBrowser(url);
}
}
diff --git a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml index d7cf1ca4d0..3aaf2e5d1b 100644 --- a/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml +++ b/src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml @@ -14,10 +14,6 @@ <inherits name="com.google.gwt.user.User" /> <inherits name="com.google.gwt.http.HTTP" /> - - <inherits name="com.google.gwt.xml.XML" /> - - <inherits name="com.google.gwt.json.JSON" /> <source path="client" /> @@ -27,10 +23,18 @@ <when-property-is name="user.agent" value="ie6"/> </replace-with> + <!-- Opera needs a different implementation due to GWT issue 3956 (#4099) --> + <replace-with class="com.google.gwt.user.client.impl.HistoryImplTimer"> + <when-type-is class="com.google.gwt.user.client.impl.HistoryImpl" /> + <when-property-is name="user.agent" value="opera" /> + </replace-with> + <generate-with class="com.vaadin.terminal.gwt.widgetsetutils.WidgetMapGenerator"> <when-type-is class="com.vaadin.terminal.gwt.client.WidgetMap"/> </generate-with> <entry-point class="com.vaadin.terminal.gwt.client.DefaultWidgetSet" /> + <set-property name="user.agent" value="safari,gecko1_8"/> + </module> diff --git a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java index 1c3128dbdf..bd35acddd7 100755 --- a/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java +++ b/src/com/vaadin/terminal/gwt/client/ApplicationConnection.java @@ -40,6 +40,7 @@ import com.vaadin.terminal.gwt.client.ui.VContextMenu; import com.vaadin.terminal.gwt.client.ui.VNotification; import com.vaadin.terminal.gwt.client.ui.VView; import com.vaadin.terminal.gwt.client.ui.VNotification.HideEvent; +import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager; import com.vaadin.terminal.gwt.server.AbstractCommunicationManager; /** @@ -596,7 +597,7 @@ public class ApplicationConnection { for (int i = 1; i < variableBurst.size(); i += 2) { String id = variableBurst.get(i); id = id.substring(0, id.indexOf(VAR_FIELD_SEPARATOR)); - if (!idToPaintableDetail.containsKey(id)) { + if (!idToPaintableDetail.containsKey(id) && !id.startsWith("DD")) { // variable owner does not exist anymore variableBurst.remove(i - 1); variableBurst.remove(i - 1); @@ -805,6 +806,12 @@ public class ApplicationConnection { } } + if (json.containsKey("dd")) { + // response contains data for drag and drop service + DragAndDropManager.get().handleServerResponse( + json.getValueMap("dd")); + } + // Check which widgets' size has been updated Set<Paintable> sizeUpdatedWidgets = new HashSet<Paintable>(); diff --git a/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java index 2a7ee079a9..8e423523ab 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java @@ -158,9 +158,12 @@ public class VAbsoluteLayout extends ComplexPanel implements Container { for (Iterator<Object> childIterator = uidl.getChildIterator(); childIterator .hasNext();) { UIDL cc = (UIDL) childIterator.next(); - UIDL componentUIDL = cc.getChildUIDL(0); - unrenderedPids.remove(componentUIDL.getId()); - getWrapper(client, componentUIDL).updateFromUIDL(cc); + // skip the last one (support for VDragDropPane + if (childIterator.hasNext()) { + UIDL componentUIDL = cc.getChildUIDL(0); + unrenderedPids.remove(componentUIDL.getId()); + getWrapper(client, componentUIDL).updateFromUIDL(cc); + } } for (String pid : unrenderedPids) { diff --git a/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java b/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java index 1c2fcf5b6f..416455c162 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java @@ -191,6 +191,7 @@ public class VGridLayout extends SimplePanel implements Paintable, Container { renderRemainingComponents(pendingCells); for (Cell cell : relativeHeighted) { + // rendering done above so cell.cc should not be null Widget widget2 = cell.cc.getWidget(); client.handleComponentRelativeSize(widget2); cell.cc.updateWidgetSize(); @@ -685,19 +686,20 @@ public class VGridLayout extends SimplePanel implements Paintable, Container { Cell cell = paintableToCell.get(paintable); if (!cell.hasRelativeHeight() || !cell.hasRelativeWidth()) { // cell sizes will only stay still if only relatively - // sized - // components + // sized components // check if changed child affects min col widths - cell.cc.setWidth(""); - cell.cc.setHeight(""); + if (cell.cc != null) { + cell.cc.setWidth(""); + cell.cc.setHeight(""); - cell.cc.updateWidgetSize(); + cell.cc.updateWidgetSize(); - /* - * If this is the result of an caption icon onload event the - * caption size may have changed - */ - cell.cc.updateCaptionSize(); + /* + * If this is the result of an caption icon onload event the + * caption size may have changed + */ + cell.cc.updateCaptionSize(); + } int width = cell.getWidth(); int allocated = columnWidths[cell.col]; @@ -853,9 +855,16 @@ public class VGridLayout extends SimplePanel implements Paintable, Container { } public RenderSpace getAllocatedSpace() { - return new RenderSpace(getAvailableWidth() - - cc.getCaptionWidthAfterComponent(), getAvailableHeight() - - cc.getCaptionHeightAboveComponent()); + if (cc != null) { + return new RenderSpace(getAvailableWidth() + - cc.getCaptionWidthAfterComponent(), + getAvailableHeight() + - cc.getCaptionHeightAboveComponent()); + } else { + // this should not happen normally + return new RenderSpace(getAvailableWidth(), + getAvailableHeight()); + } } public boolean hasContent() { @@ -965,6 +974,8 @@ public class VGridLayout extends SimplePanel implements Paintable, Container { int rowspan = 1; UIDL childUidl; int alignment; + // may be null after setUidl() if content has vanished or changed, set + // in render() ChildComponentContainer cc; public void setUidl(UIDL c) { @@ -986,21 +997,21 @@ public class VGridLayout extends SimplePanel implements Paintable, Container { if (childUidl != null) { if (c == null) { // content has vanished, old content will be removed from - // canvas - // later durin render phase + // canvas later during the render phase cc = null; } else if (cc != null && cc.getWidget() != client.getPaintable(c)) { // content has changed - cc = null; - if (widgetToComponentContainer.containsKey(client - .getPaintable(c))) { - // cc exist for this component (moved) use that for this - // cell - cc = widgetToComponentContainer.get(client - .getPaintable(c)); + Paintable newPaintable = client.getPaintable(c); + if (widgetToComponentContainer.containsKey(newPaintable)) { + // if a key in the map, newPaintable must be a widget + replaceChildComponent(cc.getWidget(), + (Widget) newPaintable); + cc = widgetToComponentContainer.get(newPaintable); cc.setWidth(""); cc.setHeight(""); + } else { + cc = null; } } } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java index 8520e52eec..a680835126 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java @@ -40,6 +40,8 @@ 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.DragAndDropManager; +import com.vaadin.terminal.gwt.client.ui.dd.Transferable; /** * VScrollTable @@ -148,6 +150,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { private String height; private String width = ""; private boolean rendering = false; + private int dragmode; public VScrollTable() { bodyContainer.addScrollHandler(this); @@ -190,6 +193,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { totalRows = newTotalRows; } + dragmode = uidl.hasAttribute("dragmode") ? uidl + .getIntAttribute("dragmode") : 0; + setCacheRate(uidl.hasAttribute("cr") ? uidl.getDoubleAttribute("cr") : CACHE_RATE_DEFAULT); @@ -2228,13 +2234,14 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { private String[] actionKeys = null; private final TableRowElement rowElement; + private boolean mDown; private VScrollTableRow(int rowKey) { this.rowKey = rowKey; rowElement = Document.get().createTRElement(); setElement(rowElement); - DOM.sinkEvents(getElement(), Event.ONMOUSEUP | Event.ONDBLCLICK - | Event.ONCONTEXTMENU); + DOM.sinkEvents(getElement(), Event.MOUSEEVENTS + | Event.ONDBLCLICK | Event.ONCONTEXTMENU); } private void paintComponent(Paintable p, UIDL uidl) { @@ -2458,6 +2465,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { handleClickEvent(event, targetTdOrTr); break; case Event.ONMOUSEUP: + mDown = false; handleClickEvent(event, targetTdOrTr); if (event.getButton() == Event.BUTTON_LEFT && selectMode > Table.SELECT_MODE_NONE) { @@ -2479,6 +2487,31 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler { case Event.ONCONTEXTMENU: showContextMenu(event); break; + case Event.ONMOUSEDOWN: + if (dragmode != 0) { + mDown = true; + event.preventDefault(); + } + break; + case Event.ONMOUSEOUT: + mDown = false; + break; + case Event.ONMOUSEMOVE: + if (mDown && dragmode != 0) { + Transferable transferable = new Transferable(); + transferable.setComponent(VScrollTable.this); + transferable.setItemId("" + rowKey); + + // TODO propertyId + com.vaadin.terminal.gwt.client.ui.dd.DragEvent ev = DragAndDropManager + .get().startDrag(transferable, event, + true); + Element cloneNode = (Element) getElement() + .cloneNode(true); + cloneNode.getStyle().setOpacity(0.4); + ev.setDragImage(cloneNode); + mDown = false; + } default: break; } diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTree.java b/src/com/vaadin/terminal/gwt/client/ui/VTree.java index 3394821efb..f3fa28c656 100644 --- a/src/com/vaadin/terminal/gwt/client/ui/VTree.java +++ b/src/com/vaadin/terminal/gwt/client/ui/VTree.java @@ -9,7 +9,11 @@ import java.util.HashSet; 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.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.Window; @@ -22,11 +26,20 @@ import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.Paintable; import com.vaadin.terminal.gwt.client.UIDL; import com.vaadin.terminal.gwt.client.Util; +import com.vaadin.terminal.gwt.client.ValueMap; +import com.vaadin.terminal.gwt.client.ui.dd.AbstractDropHandler; +import com.vaadin.terminal.gwt.client.ui.dd.AcceptCallback; +import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager; +import com.vaadin.terminal.gwt.client.ui.dd.DragEvent; +import com.vaadin.terminal.gwt.client.ui.dd.DropHandler; +import com.vaadin.terminal.gwt.client.ui.dd.HasDropHandler; +import com.vaadin.terminal.gwt.client.ui.dd.Transferable; +import com.vaadin.terminal.gwt.client.ui.dd.DragAndDropManager.DragEventType; /** * */ -public class VTree extends FlowPanel implements Paintable { +public class VTree extends FlowPanel implements Paintable, HasDropHandler { public static final String CLASSNAME = "v-tree"; @@ -37,6 +50,7 @@ public class VTree extends FlowPanel implements Paintable { private String paintableId; private boolean selectable; private boolean isMultiselect; + private String currentMouseOverKey; private final HashMap<String, TreeNode> keyToNode = new HashMap<String, TreeNode>(); @@ -56,6 +70,10 @@ public class VTree extends FlowPanel implements Paintable { private boolean rendering; + private int dragModes; + + private AbstractDropHandler dropHandler; + public VTree() { super(); setStyleName(CLASSNAME); @@ -116,6 +134,9 @@ public class VTree extends FlowPanel implements Paintable { if ("actions".equals(childUidl.getTag())) { updateActionMap(childUidl); continue; + } else if ("dh".equals(childUidl.getTag())) { + updateDropHandler(childUidl); + continue; } final TreeNode childTree = new TreeNode(); if (childTree.ie6compatnode != null) { @@ -132,10 +153,161 @@ public class VTree extends FlowPanel implements Paintable { selectedIds = uidl.getStringArrayVariableAsSet("selected"); + if (uidl.hasAttribute("dragModes")) { + dragModes = uidl.getIntAttribute("dragModes"); + } + rendering = false; } + private void updateTreeRelatedTransferData(DragEvent drag) { + drag.getTransferrable().setData("itemIdOver", currentMouseOverKey); + + if (currentMouseOverKey != null) { + String detail = getDropDetail(drag.getCurrentGwtEvent()); + Boolean overTreeNode = null; + if (!keyToNode.get(currentMouseOverKey).isLeaf() + && "Center".equals(detail)) { + overTreeNode = true; + } + drag.getTransferrable().setData("itemIdOverIsNode", overTreeNode); + + drag.getTransferrable().setData("detail", detail); + + } + } + + private void updateDropHandler(UIDL childUidl) { + if (dropHandler == null) { + dropHandler = new AbstractDropHandler() { + + @Override + public void dragEnter(DragEvent drag) { + updateTreeRelatedTransferData(drag); + super.dragEnter(drag); + } + + @Override + protected void dragAccepted(final DragEvent drag) { + } + + @Override + public void dragOver(final DragEvent currentDrag) { + final Object oldIdOver = currentDrag.getTransferrable() + .getData("itemIdOver"); + final String oldDetail = (String) currentDrag + .getTransferrable().getData("detail"); + /* + * Using deferred command, so event bubbles to TreeNode + * event listener. Currently here via preview + */ + DeferredCommand.addCommand(new Command() { + public void execute() { + final String detail = getDropDetail(currentDrag + .getCurrentGwtEvent()); + boolean nodeHasChanged = (currentMouseOverKey != null && currentMouseOverKey != oldIdOver) + || (oldIdOver != null); + boolean detailHasChanded = !detail + .equals(oldIdOver); + + if (nodeHasChanged || detailHasChanded) { + ApplicationConnection.getConsole().log( + "Change in Transferable " + + currentMouseOverKey + " " + + detail); + + updateTreeRelatedTransferData(currentDrag); + AcceptCallback accpectedCb = new AcceptCallback() { + public void handleResponse( + ValueMap responseData) { + if (responseData == null // via client + // side + // validation + || responseData + .containsKey("accepted")) { + keyToNode.get(currentMouseOverKey) + .emphasis(detail); + } + } + }; + if (validateOnServer()) { + DragAndDropManager.get().visitServer( + DragEventType.OVER, accpectedCb); + + } else { + if (validates(currentDrag + .getTransferrable())) { + accpectedCb.handleResponse(null); + } else { + keyToNode.get(currentMouseOverKey) + .emphasis(null); + } + if (oldIdOver != null + && oldIdOver != currentMouseOverKey) { + keyToNode.get(oldIdOver).emphasis(null); + } + } + } + + } + }); + } + + @Override + public void dragLeave(DragEvent drag) { + cleanUp(); + } + + private void cleanUp() { + if (currentMouseOverKey != null) { + keyToNode.get(currentMouseOverKey).emphasis(null); + currentMouseOverKey = null; + } + } + + @Override + public boolean drop(DragEvent drag) { + cleanUp(); + return super.drop(drag); + } + + @Override + public Paintable getPaintable() { + return VTree.this; + } + + public ApplicationConnection getApplicationConnection() { + return client; + } + + }; + } + dropHandler.updateRules(childUidl); + } + + public String getDropDetail(NativeEvent event) { + TreeNode treeNode = keyToNode.get(currentMouseOverKey); + // 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; + + } + private void handleUpdate(UIDL uidl) { final TreeNode rootNode = keyToNode.get(uidl .getStringAttribute("rootKey")); @@ -204,12 +376,27 @@ public class VTree extends FlowPanel implements Paintable { private Element ie6compatnode; + private Event mouseDownEvent; + public TreeNode() { constructDom(); - sinkEvents(Event.ONCLICK | Event.ONDBLCLICK | Event.ONMOUSEUP + sinkEvents(Event.ONCLICK | Event.ONDBLCLICK | Event.MOUSEEVENTS | Event.ONCONTEXTMENU); } + public void emphasis(String string) { + // ApplicationConnection.getConsole().log("OUTLINE" + string); + Style style = nodeCaptionDiv.getStyle(); + String top = "Top".equals(string) ? "2px solid green" : null; + String bottom = "Bottom".equals(string) ? "2px solid green" : null; + String bg = "Center".equals(string) ? "green" : null; + + style.setProperty("borderTop", top); + style.setProperty("borderBottom", bottom); + style.setBackgroundColor(bg); + + } + @Override public void onBrowserEvent(Event event) { super.onBrowserEvent(event); @@ -235,6 +422,45 @@ public class VTree extends FlowPanel implements Paintable { } else if (type == Event.ONCONTEXTMENU) { showContextMenu(event); } + + if (dragModes != 0 || dropHandler != null) { + if (type == Event.ONMOUSEDOWN) { + if (nodeCaptionDiv.isOrHasChild(event.getTarget())) { + ApplicationConnection.getConsole().log( + "TreeNode m down"); + event.preventDefault(); // prevent text selection + mouseDownEvent = event; + } + } else if (type == Event.ONMOUSEMOVE + || type == Event.ONMOUSEOUT) { + + if (mouseDownEvent != null) { + ApplicationConnection.getConsole().log( + "TreeNode drag start " + event.getType()); + // start actual drag on slight move when mouse is down + Transferable t = new Transferable(); + t.setComponent(VTree.this); + t.setItemId(key); + DragEvent drag = DragAndDropManager.get().startDrag(t, + mouseDownEvent, true); + Element node = (Element) nodeCaptionDiv.cloneNode(true); + node.getStyle().setOpacity(0.4); + node.getStyle().setBackgroundColor("#999"); + drag.setDragImage(node); + event.stopPropagation(); + + mouseDownEvent = null; + } + } else if (type == Event.ONMOUSEUP) { + mouseDownEvent = null; + } + if (type == Event.ONMOUSEOVER) { + mouseDownEvent = null; + currentMouseOverKey = key; + event.stopPropagation(); + } + + } } private void fireClick(Event evt) { @@ -344,6 +570,10 @@ public class VTree extends FlowPanel implements Paintable { } } + public boolean isLeaf() { + return getStyleName().contains("leaf"); + } + private void setState(boolean state, boolean notifyServer) { if (open == state) { return; @@ -484,4 +714,8 @@ public class VTree extends FlowPanel implements Paintable { } } } + + public DropHandler getDropHandler() { + return dropHandler; + } } diff --git a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java index 2bc10b4cc0..d6fa230f3c 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java @@ -316,6 +316,8 @@ public abstract class AbstractCommunicationManager implements private int timeoutInterval = -1; + private DragAndDropService dragAndDropService; + /** * TODO New constructor - document me! * @@ -939,6 +941,10 @@ public abstract class AbstractCommunicationManager implements // add any pending locale definitions requested by the client printLocaleDeclarations(outWriter); + if (dragAndDropService != null) { + dragAndDropService.printJSONResponse(outWriter); + } + outWriter.print("}]"); } outWriter.flush(); @@ -1006,8 +1012,7 @@ public abstract class AbstractCommunicationManager implements if (i + 1 < variableRecords.length) { nextVariable = variableRecords[i + 1]; } - final VariableOwner owner = (VariableOwner) idPaintableMap - .get(variable[VAR_PID]); + final VariableOwner owner = getVariableOwner(variable[VAR_PID]); if (owner != null && owner.isEnabled()) { // TODO this should be Map<String, Object>, but the // VariableOwner API does not guarantee the key is a @@ -1058,8 +1063,13 @@ public abstract class AbstractCommunicationManager implements } } } catch (Exception e) { - handleChangeVariablesError(application2, - (Component) owner, e, m); + if (owner instanceof Component) { + handleChangeVariablesError(application2, + (Component) owner, e, m); + } else { + // TODO DragDropService error handling + throw new RuntimeException(e); + } } } else { @@ -1112,6 +1122,21 @@ public abstract class AbstractCommunicationManager implements return success; } + private VariableOwner getVariableOwner(String string) { + VariableOwner owner = (VariableOwner) idPaintableMap.get(string); + if (owner == null && string.startsWith("DD")) { + return getDragAndDropService(); + } + return owner; + } + + private VariableOwner getDragAndDropService() { + if (dragAndDropService == null) { + dragAndDropService = new DragAndDropService(); + } + return dragAndDropService; + } + /** * Reads the request data from the Request and returns it converted to an * UTF-8 string. diff --git a/src/com/vaadin/ui/AbsoluteLayout.java b/src/com/vaadin/ui/AbsoluteLayout.java index 406ee9072d..e8a6ae5a9d 100644 --- a/src/com/vaadin/ui/AbsoluteLayout.java +++ b/src/com/vaadin/ui/AbsoluteLayout.java @@ -50,6 +50,7 @@ public class AbsoluteLayout extends AbstractLayout { public void addComponent(Component c) { components.add(c); super.addComponent(c); + requestRepaint(); } @Override diff --git a/src/com/vaadin/ui/CustomLayout.java b/src/com/vaadin/ui/CustomLayout.java index 26495a3715..0baa0dd468 100644 --- a/src/com/vaadin/ui/CustomLayout.java +++ b/src/com/vaadin/ui/CustomLayout.java @@ -1,4 +1,4 @@ -/* +/* @ITMillApache2LicenseForJavaFiles@ */ @@ -37,8 +37,6 @@ import com.vaadin.terminal.gwt.client.ui.VCustomLayout; * </p> * * @author IT Mill Ltd. - * @author Duy B. Vo (<a - * href="mailto:devduy@gmail.com?subject=Vaadin">devduy@gmail.com</a>) * @version * @VERSION@ * @since 3.0 @@ -59,14 +57,6 @@ public class CustomLayout extends AbstractLayout { private String templateName = null; /** - * Default constructor only used by subclasses because the subclasses are - * responsible for setting the appropriate fields. - */ - protected CustomLayout() { - setWidth(100, UNITS_PERCENTAGE); - } - - /** * Constructs a custom layout with the template given in the stream. * * @param templateStream @@ -78,24 +68,10 @@ public class CustomLayout extends AbstractLayout { * @throws IOException */ public CustomLayout(InputStream templateStream) throws IOException { - this(); - initTemplateContentsFromInputStream(templateStream); - } - - /** - * Constructor for custom layout with given template name. Template file is - * fetched from "<theme>/layout/<templateName>". - */ - public CustomLayout(String template) { - this(); - templateName = template; - } - protected void initTemplateContentsFromInputStream( - InputStream templateStream) throws IOException { InputStreamReader reader = new InputStreamReader(templateStream, "UTF-8"); - StringBuilder b = new StringBuilder(BUFFER_SIZE); + StringBuffer b = new StringBuffer(BUFFER_SIZE); char[] cbuf = new char[BUFFER_SIZE]; int offset = 0; @@ -109,6 +85,16 @@ public class CustomLayout extends AbstractLayout { } templateContents = b.toString(); + setWidth(100, UNITS_PERCENTAGE); + } + + /** + * Constructor for custom layout with given template name. Template file is + * fetched from "<theme>/layout/<templateName>". + */ + public CustomLayout(String template) { + templateName = template; + setWidth(100, UNITS_PERCENTAGE); } /** @@ -260,9 +246,7 @@ public class CustomLayout extends AbstractLayout { * * @param name * template name - * @deprecated Use {@link #setTemplateName(String)} instead */ - @Deprecated @Override public void setStyle(String name) { setTemplateName(name); @@ -273,11 +257,6 @@ public class CustomLayout extends AbstractLayout { return templateName; } - /** Get the contents of the template */ - public String getTemplateContents() { - return templateContents; - } - /** * Set the name of the template used to draw custom layout. * @@ -294,17 +273,6 @@ public class CustomLayout extends AbstractLayout { } /** - * Set the contents of the template used to draw the custom layout. - * - * @param templateContents - */ - public void setTemplateContents(String templateContents) { - this.templateContents = templateContents; - templateName = null; - requestRepaint(); - } - - /** * Although most layouts support margins, CustomLayout does not. The * behaviour of this layout is determined almost completely by the actual * template. diff --git a/src/com/vaadin/ui/Select.java b/src/com/vaadin/ui/Select.java index e8e0dfebaa..4174001d87 100644 --- a/src/com/vaadin/ui/Select.java +++ b/src/com/vaadin/ui/Select.java @@ -234,6 +234,12 @@ public class Select extends AbstractSelect implements AbstractSelect.Filtering, currentPage = -1; // current page is always set by client optionRequest = true; + + // Hide the error indicator if needed + if (isRequired() && isEmpty() && getComponentError() == null + && getErrorMessage() != null) { + target.addAttribute("hideErrors", true); + } } /** diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java index 0563756d40..5b99f614f1 100644 --- a/src/com/vaadin/ui/Table.java +++ b/src/com/vaadin/ui/Table.java @@ -23,7 +23,9 @@ import com.vaadin.data.Property; import com.vaadin.data.util.ContainerOrderedWrapper; import com.vaadin.data.util.IndexedContainer; import com.vaadin.event.Action; +import com.vaadin.event.DataBindedTransferrable; import com.vaadin.event.ItemClickEvent; +import com.vaadin.event.Transferable; import com.vaadin.event.Action.Handler; import com.vaadin.event.ItemClickEvent.ItemClickListener; import com.vaadin.event.ItemClickEvent.ItemClickSource; @@ -31,6 +33,7 @@ import com.vaadin.terminal.KeyMapper; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; +import com.vaadin.terminal.TransferTranslator; import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.ui.VScrollTable; @@ -54,7 +57,15 @@ 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 { + Container.Ordered, Container.Sortable, ItemClickSource, + TransferTranslator { + + /** + * Modes that Table support as drag sourse. + */ + public enum DragModes { + NONE, ROWS, CELLS + } private static final int CELL_KEY = 0; @@ -327,6 +338,8 @@ public class Table extends AbstractSelect implements Action.Container, private double cacheRate = CACHE_RATE_DEFAULT; + private DragModes dragMode = DragModes.NONE; + /* Table constructors */ /** @@ -2014,6 +2027,10 @@ public class Table extends AbstractSelect implements Action.Container, target.addAttribute("tabindex", getTabIndex()); } + if (dragMode != DragModes.NONE) { + target.addAttribute("dragmode", dragMode.ordinal()); + } + // Initialize temps final Object[] colids = getVisibleColumns(); final int cols = colids.length; @@ -3299,4 +3316,61 @@ public class Table extends AbstractSelect implements Action.Container, } } } + + public void setDragMode(DragModes newDragMode) { + dragMode = newDragMode; + requestRepaint(); + } + + class TableTransferrable implements DataBindedTransferrable { + + private final HashMap<String, Object> data = new HashMap<String, Object>(); + + public Object getItemId() { + return data.get("itemId"); + } + + public Object getPropertyId() { + return getItemCaptionPropertyId(); + } + + public Component getSourceComponent() { + return Table.this; + } + + public Object getData(String dataFlawor) { + return data.get(dataFlawor); + } + + public Collection<String> getDataFlawors() { + return data.keySet(); + } + + public void setData(String dataFlawor, Object value) { + data.put(dataFlawor, value); + } + + } + + private void updateTransferrable(Map<String, Object> rawVariables, + Transferable tr, boolean isDropTarget) { + Map<String, Object> payload = (Map<String, Object>) rawVariables + .get("payload"); + if (!isDropTarget) { + Object object = payload.get("itemId"); + if (object != null) { + tr.setData("itemId", itemIdMapper.get((String) object)); + payload.remove("itemId"); + } + } + } + + public Transferable getTransferrable(Transferable transferable, + Map<String, Object> rawVariables, boolean isDropTarget) { + if (transferable == null) { + transferable = new TableTransferrable(); + } + updateTransferrable(rawVariables, transferable, isDropTarget); + return transferable; + } } diff --git a/src/com/vaadin/ui/Tree.java b/src/com/vaadin/ui/Tree.java index 28a410fa13..8e5cd8aca7 100644 --- a/src/com/vaadin/ui/Tree.java +++ b/src/com/vaadin/ui/Tree.java @@ -22,14 +22,20 @@ import com.vaadin.data.Container; import com.vaadin.data.Item; import com.vaadin.data.util.ContainerHierarchicalWrapper; import com.vaadin.data.util.IndexedContainer; +import com.vaadin.event.AbstractDropHandler; import com.vaadin.event.Action; +import com.vaadin.event.DataBindedTransferrable; +import com.vaadin.event.DropHandler; +import com.vaadin.event.HasDropHandler; import com.vaadin.event.ItemClickEvent; +import com.vaadin.event.Transferable; import com.vaadin.event.ItemClickEvent.ItemClickListener; import com.vaadin.event.ItemClickEvent.ItemClickSource; import com.vaadin.terminal.KeyMapper; import com.vaadin.terminal.PaintException; import com.vaadin.terminal.PaintTarget; import com.vaadin.terminal.Resource; +import com.vaadin.terminal.TransferTranslator; import com.vaadin.terminal.gwt.client.MouseEventDetails; import com.vaadin.terminal.gwt.client.ui.VTree; @@ -45,7 +51,7 @@ import com.vaadin.terminal.gwt.client.ui.VTree; @SuppressWarnings("serial") @ClientWidget(VTree.class) public class Tree extends AbstractSelect implements Container.Hierarchical, - Action.Container, ItemClickSource { + Action.Container, ItemClickSource, TransferTranslator, HasDropHandler { private static final Method EXPAND_METHOD; @@ -102,6 +108,68 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, */ private boolean initialPaint = true; + // TODO sort DD members and methods + public static int DRAG_SORTABLE = 1; + public static int DRAG_OUT = 2; + public static int DRAG_NONE = 0; + + private int itemDragModes = DRAG_OUT; + + class TreeTransferrable implements DataBindedTransferrable { + + private final HashMap<String, Object> data = new HashMap<String, Object>(); + + public Object getItemId() { + return data.get("itemId"); + } + + public Object getPropertyId() { + return getItemCaptionPropertyId(); + } + + public Component getSourceComponent() { + return Tree.this; + } + + public Object getData(String dataFlawor) { + return data.get(dataFlawor); + } + + public Collection<String> getDataFlawors() { + return data.keySet(); + } + + public void setData(String dataFlawor, Object value) { + data.put(dataFlawor, value); + } + } + + public Transferable getTransferrable(Transferable transferable, + Map<String, Object> rawVariables, boolean isDropTarget) { + if (transferable == null) { + transferable = new TreeTransferrable(); + } + Map<String, Object> payload = (Map<String, Object>) rawVariables + .get("payload"); + if (isDropTarget) { + // updating drag target variables + Object object = payload.get("itemIdOver"); + Object object2 = itemIdMapper.get((String) object); + transferable.setData("itemIdOver", object2); + payload.remove("itemIdOver"); + } else { + // updating drag source variables + Object object = payload.get("itemId"); + if (object != null) { + transferable.setData("itemId", itemIdMapper + .get((String) object)); + } + payload.remove("itemId"); + } + + return transferable; + } + /* Tree constructors */ /** @@ -435,6 +503,10 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, target.addAttribute("nullselect", true); } + if (itemDragModes != 0) { + target.addAttribute("dragModes", itemDragModes); + } + } // Initialize variables @@ -579,6 +651,11 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, // New items target.addVariable(this, "newitem", new String[] {}); + + if (abstractDropHandler != null) { + abstractDropHandler.paint(target); + } + } } @@ -1019,6 +1096,8 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, private ItemStyleGenerator itemStyleGenerator; + private AbstractDropHandler abstractDropHandler; + public void addListener(ItemClickListener listener) { addListener(VTree.ITEM_CLICK_EVENT_ID, ItemClickEvent.class, listener, ItemClickEvent.ITEM_CLICK_METHOD); @@ -1075,4 +1154,12 @@ public class Tree extends AbstractSelect implements Container.Hierarchical, return super.removeItem(itemId); } + public DropHandler getDropHandler() { + return abstractDropHandler; + } + + public void setDropHandler(AbstractDropHandler abstractDropHandler) { + this.abstractDropHandler = abstractDropHandler; + } + } |