summaryrefslogtreecommitdiffstats
path: root/src/com/vaadin
diff options
context:
space:
mode:
authorMatti Tahvonen <matti.tahvonen@itmill.com>2010-01-28 17:46:50 +0000
committerMatti Tahvonen <matti.tahvonen@itmill.com>2010-01-28 17:46:50 +0000
commit810017204ef10e2d5fbea15ed17b0c1e8a6b0daa (patch)
tree86dd95e68bddc78016f5eeab6687554ea79563a7 /src/com/vaadin
parent1e2a4afc96a7376b922b342224f8e2e4297385aa (diff)
downloadvaadin-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.java23
-rw-r--r--src/com/vaadin/data/util/HierarchicalContainer.java26
-rw-r--r--src/com/vaadin/data/util/IndexedContainer.java3
-rw-r--r--src/com/vaadin/launcher/DevelopmentServerLauncher.java4
-rw-r--r--src/com/vaadin/terminal/gwt/DefaultWidgetSet.gwt.xml12
-rwxr-xr-xsrc/com/vaadin/terminal/gwt/client/ApplicationConnection.java9
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VAbsoluteLayout.java9
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VGridLayout.java55
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java37
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTree.java238
-rw-r--r--src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java33
-rw-r--r--src/com/vaadin/ui/AbsoluteLayout.java1
-rw-r--r--src/com/vaadin/ui/CustomLayout.java56
-rw-r--r--src/com/vaadin/ui/Select.java6
-rw-r--r--src/com/vaadin/ui/Table.java76
-rw-r--r--src/com/vaadin/ui/Tree.java89
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;
+ }
+
}