summaryrefslogtreecommitdiffstats
path: root/documentation/advanced/advanced-dragndrop.asciidoc
diff options
context:
space:
mode:
authorelmot <elmot@vaadin.com>2015-09-25 16:40:44 +0300
committerelmot <elmot@vaadin.com>2015-09-25 16:40:44 +0300
commita1b265c318dbda4a213cec930785b81e4c0f7d2b (patch)
treeb149daf5a4f50b4f6446c906047cf86495fe0433 /documentation/advanced/advanced-dragndrop.asciidoc
parentb9743a48a1bd0394f19c54ee938c6395a80f3cd8 (diff)
downloadvaadin-framework-a1b265c318dbda4a213cec930785b81e4c0f7d2b.tar.gz
vaadin-framework-a1b265c318dbda4a213cec930785b81e4c0f7d2b.zip
Framework documentation IN
Change-Id: I767477c1fc3745f9e1f58075fe30c9ac8da63581
Diffstat (limited to 'documentation/advanced/advanced-dragndrop.asciidoc')
-rw-r--r--documentation/advanced/advanced-dragndrop.asciidoc567
1 files changed, 567 insertions, 0 deletions
diff --git a/documentation/advanced/advanced-dragndrop.asciidoc b/documentation/advanced/advanced-dragndrop.asciidoc
new file mode 100644
index 0000000000..69335c6369
--- /dev/null
+++ b/documentation/advanced/advanced-dragndrop.asciidoc
@@ -0,0 +1,567 @@
+---
+title: Drag and Drop
+order: 12
+layout: page
+---
+
+[[advanced.dragndrop]]
+= Drag and Drop
+
+((("Drag and Drop", id="term.advanced.dragndrop", range="startofrange")))
+
+
+Dragging an object from one location to another by grabbing it with mouse,
+holding the mouse button pressed, and then releasing the button to "drop" it to
+the other location is a common way to move, copy, or associate objects. For
+example, most operating systems allow dragging and dropping files between
+folders or dragging a document on a program to open it. In Vaadin, it is
+possible to drag and drop components and parts of certain components.
+
+Dragged objects, or __transferables__, are essentially data objects. You can
+drag and drop rows in [classname]#Table# and nodes in [classname]#Tree#
+components, either within or between the components. You can also drag entire
+components by wrapping them inside [classname]#DragAndDropWrapper#.
+
+Dragging starts from a __drag source__, which defines the transferable.
+Transferables implement the [classname]#Transferable# interfaces. For trees and
+tables, which are bound to [classname]#Container# data sources, a node or row
+transferable is a reference to an [classname]#Item# in the Vaadin Data Model.
+Dragged components are referenced with a [classname]#WrapperTransferable#.
+Starting dragging does not require any client-server communication, you only
+need to enable dragging. All drag and drop logic occurs in two operations:
+determining ( __accepting__) where dropping is allowed and actually dropping.
+Drops can be done on a __drop target__, which implements the
+[classname]#DropTarget# interface. Three components implement the interface:
+[classname]#Tree#, [classname]#Table#, and [classname]#DragAndDropWrapper#.
+These accept and drop operations need to be provided in a __drop handler__.
+Essentially all you need to do to enable drag and drop is to enable dragging in
+the drag source and implement the [methodname]#getAcceptCriterion()# and
+[methodname]#drop()# methods in the [classname]#DropHandler# interface.
+
+The client-server architecture of Vaadin causes special requirements for the
+drag and drop functionality. The logic for determining where a dragged object
+can be dropped, that is, __accepting__ a drop, should normally be done on the
+client-side, in the browser. Server communications are too slow to have much of
+such logic on the server-side. The drag and drop feature therefore offers a
+number of ways to avoid the server communications to ensure a good user
+experience.
+
+[[advanced.dragndrop.drophandler]]
+== Handling Drops
+
+Most of the user-defined drag and drop logic occurs in a __drop handler__, which
+is provided by implementing the [methodname]#drop()# method in the
+[classname]#DropHandler# interface. A closely related definition is the drop
+accept criterion, which is defined in the [methodname]#getAcceptCriterion()#
+method in the same interface. It is described in
+<<advanced.dragndrop.acceptcriteria>> later.
+
+The [methodname]#drop()# method gets a [classname]#DragAndDropEvent# as its
+parameters. The event object provides references to two important object:
+[classname]#Transferable# and [classname]#TargetDetails#.
+
+A [classname]#Transferable# contains a reference to the object (component or
+data item) that is being dragged. A tree or table item is represented as a
+[classname]#TreeTransferable# or [classname]#TableTransferable# object, which
+carries the item identifier of the dragged tree or table item. These special
+transferables, which are bound to some data in a container, are
+[classname]#DataBoundTransferable#. Dragged components are represented as
+[classname]#WrapperTransferable# objects, as the components are wrapped in a
+[classname]#DragAndDropWrapper#.
+
+The [classname]#TargetDetails# object provides information about the exact
+location where the transferable object is being dropped. The exact class of the
+details object depends on the drop target and you need to cast it to the proper
+subclass to get more detailed information. If the target is selection component,
+essentially a tree or a table, the [classname]#AbstractSelectTargetDetails#
+object tells the item on which the drop is being made. For trees, the
+[classname]#TreeTargetDetails# gives some more details. For wrapped components,
+the information is provided in a [classname]#WrapperDropDetails# object. In
+addition to the target item or component, the details objects provide a __drop
+location__. For selection components, the location can be obtained with the
+[methodname]#getDropLocation()# and for wrapped components with
+[methodname]#verticalDropLocation()# and [methodname]#horizontalDropLocation()#.
+The locations are specified as either [classname]#VerticalDropLocation# or
+[classname]#HorizontalDropLocation# objects. The drop location objects specify
+whether the transferable is being dropped above, below, or directly on (at the
+middle of) a component or item.
+
+Dropping on a [classname]#Tree#, [classname]#Table#, and a wrapped component is
+explained further in the following sections.
+
+
+[[advanced.dragndrop.treedrop]]
+== Dropping Items On a [classname]#Tree#
+
+You can drag items from, to, or within a [classname]#Tree#. Making tree a drag
+source requires simply setting the drag mode with [methodname]#setDragMode()#.
+[classname]#Tree# currently supports only one drag mode,
+[literal]#++TreeDragMode.NODE++#, which allows dragging single tree nodes. While
+dragging, the dragged node is referenced with a [classname]#TreeTransferable#
+object, which is a [classname]#DataBoundTransferable#. The tree node is
+identified by the item ID of the container item.
+
+When a transferable is dropped on a tree, the drop location is stored in a
+[classname]#TreeTargetDetails# object, which identifies the target location by
+item ID of the tree node on which the drop is made. You can get the item ID with
+[methodname]#getItemIdOver()# method in
+[classname]#AbstractSelectTargetDetails#, which the
+[classname]#TreeTargetDetails# inherits. A drop can occur directly on or above
+or below a node; the exact location is a [classname]#VerticalDropLocation#,
+which you can get with the [methodname]#getDropLocation()# method.
+
+In the example below, we have a [classname]#Tree# and we allow reordering the
+tree items by drag and drop.
+
+
+[source, java]
+----
+final Tree tree = new Tree("Inventory");
+tree.setContainerDataSource(TreeExample.createTreeContent());
+layout.addComponent(tree);
+
+// Expand all items
+for (Iterator<?> it = tree.rootItemIds().iterator(); it.hasNext();)
+ tree.expandItemsRecursively(it.next());
+
+// Set the tree in drag source mode
+tree.setDragMode(TreeDragMode.NODE);
+
+// Allow the tree to receive drag drops and handle them
+tree.setDropHandler(new DropHandler() {
+ public AcceptCriterion getAcceptCriterion() {
+ return AcceptAll.get();
+ }
+
+ public void drop(DragAndDropEvent event) {
+ // Wrapper for the object that is dragged
+ Transferable t = event.getTransferable();
+
+ // Make sure the drag source is the same tree
+ if (t.getSourceComponent() != tree)
+ return;
+
+ TreeTargetDetails target = (TreeTargetDetails)
+ event.getTargetDetails();
+
+ // Get ids of the dragged item and the target item
+ Object sourceItemId = t.getData("itemId");
+ Object targetItemId = target.getItemIdOver();
+
+ // On which side of the target the item was dropped
+ VerticalDropLocation location = target.getDropLocation();
+
+ HierarchicalContainer container = (HierarchicalContainer)
+ tree.getContainerDataSource();
+
+ // Drop right on an item -> make it a child
+ if (location == VerticalDropLocation.MIDDLE)
+ tree.setParent(sourceItemId, targetItemId);
+
+ // Drop at the top of a subtree -> make it previous
+ else if (location == VerticalDropLocation.TOP) {
+ Object parentId = container.getParent(targetItemId);
+ container.setParent(sourceItemId, parentId);
+ container.moveAfterSibling(sourceItemId, targetItemId);
+ container.moveAfterSibling(targetItemId, sourceItemId);
+ }
+
+ // Drop below another item -> make it next
+ else if (location == VerticalDropLocation.BOTTOM) {
+ Object parentId = container.getParent(targetItemId);
+ container.setParent(sourceItemId, parentId);
+ container.moveAfterSibling(sourceItemId, targetItemId);
+ }
+ }
+});
+----
+
+[[advanced.dragndrop.treedrop.criteria]]
+=== Accept Criteria for Trees
+
+[classname]#Tree# defines some specialized accept criteria for trees.
+
+[classname]#TargetInSubtree#(client-side):: Accepts if the target item is in the specified sub-tree. The sub-tree is specified by the item ID of the root of the sub-tree in the constructor. The second constructor includes a depth parameter, which specifies how deep from the given root node are drops accepted. Value [literal]#++-1++# means infinite, that is, the entire sub-tree, and is therefore the same as the simpler constructor.
+[classname]#TargetItemAllowsChildren#(client-side):: Accepts a drop if the tree has [methodname]#setChildrenAllowed()# enabled for the target item. The criterion does not require parameters, so the class is a singleton and can be acquired with [methodname]#Tree.TargetItemAllowsChildren.get()#. For example, the following composite criterion accepts drops only on nodes that allow children, but between all nodes:
++
+[source, java]
+----
+return new Or (Tree.TargetItemAllowsChildren.get(), new Not(VerticalLocationIs.MIDDLE));
+----
+
+[classname]#TreeDropCriterion#(server-side):: Accepts drops on only some items, which as specified by a set of item IDs. You must extend the abstract class and implement the [methodname]#getAllowedItemIds()# to return the set. While the criterion is server-side, it is lazy-loading, so that the list of accepted target nodes is loaded only once from the server for each drag operation. See <<advanced.dragndrop.acceptcriteria>> for an example.
+
+
+In addition, the accept criteria defined in [classname]#AbstractSelect# are
+available for a [classname]#Tree#, as listed in
+<<advanced.dragndrop.acceptcriteria>>.
+
+
+
+[[advanced.dragndrop.tabledrop]]
+== Dropping Items On a [classname]#Table#
+
+You can drag items from, to, or within a [classname]#Table#. Making table a drag
+source requires simply setting the drag mode with [methodname]#setDragMode()#.
+[classname]#Table# supports dragging both single rows, with
+[literal]#++TableDragMode.ROW++#, and multiple rows, with
+[literal]#++TableDragMode.MULTIROW++#. While dragging, the dragged node or nodes
+are referenced with a [classname]#TreeTransferable# object, which is a
+[classname]#DataBoundTransferable#. Tree nodes are identified by the item IDs of
+the container items.
+
+When a transferable is dropped on a table, the drop location is stored in a
+[classname]#AbstractSelectTargetDetails# object, which identifies the target row
+by its item ID. You can get the item ID with [methodname]#getItemIdOver()#
+method. A drop can occur directly on or above or below a row; the exact location
+is a [classname]#VerticalDropLocation#, which you can get with the
+[methodname]#getDropLocation()# method from the details object.
+
+[[advanced.dragndrop.tabledrop.criteria]]
+=== Accept Criteria for Tables
+
+[classname]#Table# defines one specialized accept criterion for tables.
+
+[classname]#TableDropCriterion#(server-side):: Accepts drops only on (or above or below) items that are specified by a set of item IDs. You must extend the abstract class and implement the [methodname]#getAllowedItemIds()# to return the set. While the criterion is server-side, it is lazy-loading, so that the list of accepted target items is loaded only once from the server for each drag operation.
+
+
+
+
+[[advanced.dragndrop.acceptcriteria]]
+== Accepting Drops
+
+((("Drag and Drop", "Accept Criteria", id="term.advanced.dragndrop.acceptcriteria", range="startofrange")))
+
+
+You can not drop the objects you are dragging around just anywhere. Before a
+drop is possible, the specific drop location on which the mouse hovers must be
+__accepted__. Hovering a dragged object over an accepted location displays an
+__accept indicator__, which allows the user to position the drop properly. As
+such checks have to be done all the time when the mouse pointer moves around the
+drop targets, it is not feasible to send the accept requests to the server-side,
+so drops on a target are normally accepted by a client-side __accept
+criterion__.
+
+A drop handler must define the criterion on the objects which it accepts to be
+dropped on the target. The criterion needs to be provided in the
+[classname]#getAcceptCriterion()# method of the [classname]#DropHandler#
+interface. A criterion is represented in an [classname]#AcceptCriterion# object,
+which can be a composite of multiple criteria that are evaluated using logical
+operations. There are two basic types of criteria: __client-side__ and
+__server-side criteria__. The various built-in criteria allow accepting drops
+based on the identity of the source and target components, and on the __data
+flavor__ of the dragged objects.
+
+To allow dropping any transferable objects, you can return a universal accept
+criterion, which you can get with [methodname]#AcceptAll.get()#.
+
+
+[source, java]
+----
+tree.setDropHandler(new DropHandler() {
+ public AcceptCriterion getAcceptCriterion() {
+ return AcceptAll.get();
+ }
+ ...
+----
+
+[[advanced.dragndrop.acceptcriteria.client-side]]
+=== Client-Side Criteria
+
+The __client-side criteria__, which inherit the
+[classname]#ClientSideCriterion#, are verified on the client-side, so server
+requests are not needed for verifying whether each component on which the mouse
+pointer hovers would accept a certain object.
+
+The following client-side criteria are define in
+[package]#com.vaadin.event.dd.acceptcriterion#:
+
+[classname]#AcceptAll#:: Accepts all transferables and targets.
+[classname]#And#:: Performs the logical AND operation on two or more client-side criteria; accepts the transferable if all the given sub-criteria accept it.
+[classname]#ContainsDataFlavour#:: The transferable must contain the defined data flavour.
+[classname]#Not#:: Performs the logical NOT operation on a client-side criterion; accepts the transferable if and only if the sub-criterion does not accept it.
+[classname]#Or#:: Performs the logical OR operation on two or more client-side criteria; accepts the transferable if any of the given sub-criteria accepts it.
+[classname]#SourceIs#:: Accepts all transferables from any of the given source components
+[classname]#SourceIsTarget#:: Accepts the transferable only if the source component is the same as the target. This criterion is useful for ensuring that items are dragged only within a tree or a table, and not from outside it.
+[classname]#TargetDetailIs#:: Accepts any transferable if the target detail, such as the item of a tree node or table row, is of the given data flavor and has the given value.
+
+
+In addition, target components such as [classname]#Tree# and [classname]#Table#
+define some component-specific client-side accept criteria. See
+<<advanced.dragndrop.treedrop>> for more details.
+
+[classname]#AbstractSelect# defines the following criteria for all selection
+components, including [classname]#Tree# and [classname]#Table#.
+
+[classname]#AcceptItem#:: Accepts only specific items from a specific selection component. The selection component, which must inherit [classname]#AbstractSelect#, is given as the first parameter for the constructor. It is followed by a list of allowed item identifiers in the drag source.
+[classname]#AcceptItem.ALL#:: Accepts all transferables as long as they are items.
+[classname]#TargetItemIs#:: Accepts all drops on the specified target items. The constructor requires the target component ( [classname]#AbstractSelect#) followed by a list of allowed item identifiers.
+[classname]#VerticalLocationIs.MIDDLE#,[classname]#TOP#, and[classname]#BOTTOM#:: The three static criteria accepts drops on, above, or below an item. For example, you could accept drops only in between items with the following:
+[source, java]
+----
+public AcceptCriterion getAcceptCriterion() {
+ return new Not(VerticalLocationIs.MIDDLE);
+}
+----
+
+
+
+
+
+[[advanced.dragndrop.acceptcriteria.server-side]]
+=== Server-Side Criteria
+
+The __server-side criteria__ are verified on the server-side with the
+[methodname]#accept()# method of the [classname]#ServerSideCriterion# class.
+This allows fully programmable logic for accepting drops, but the negative side
+is that it causes a very large amount of server requests. A request is made for
+every target position on which the pointer hovers. This problem is eased in many
+cases by the component-specific lazy loading criteria
+[classname]#TableDropCriterion# and [classname]#TreeDropCriterion#. They do the
+server visit once for each drag and drop operation and return all accepted rows
+or nodes for current [classname]#Transferable# at once.
+
+The [methodname]#accept()# method gets the drag event as a parameter so it can
+perform its logic much like in [methodname]#drop()#.
+
+
+[source, java]
+----
+public AcceptCriterion getAcceptCriterion() {
+ // Server-side accept criterion that allows drops on any other
+ // location except on nodes that may not have children
+ ServerSideCriterion criterion = new ServerSideCriterion() {
+ public boolean accept(DragAndDropEvent dragEvent) {
+ TreeTargetDetails target = (TreeTargetDetails)
+ dragEvent.getTargetDetails();
+
+ // The tree item on which the load hovers
+ Object targetItemId = target.getItemIdOver();
+
+ // On which side of the target the item is hovered
+ VerticalDropLocation location = target.getDropLocation();
+ if (location == VerticalDropLocation.MIDDLE)
+ if (! tree.areChildrenAllowed(targetItemId))
+ return false; // Not accepted
+
+ return true; // Accept everything else
+ }
+ };
+ return criterion;
+}
+----
+
+The server-side criteria base class [classname]#ServerSideCriterion# provides a
+generic [methodname]#accept()# method. The more specific
+[classname]#TableDropCriterion# and [classname]#TreeDropCriterion# are
+conveniency extensions that allow definiting allowed drop targets as a set of
+items. They also provide some optimization by lazy loading, which reduces server
+communications significantly.
+
+
+[source, java]
+----
+public AcceptCriterion getAcceptCriterion() {
+ // Server-side accept criterion that allows drops on any
+ // other tree node except on node that may not have children
+ TreeDropCriterion criterion = new TreeDropCriterion() {
+ @Override
+ protected Set<Object> getAllowedItemIds(
+ DragAndDropEvent dragEvent, Tree tree) {
+ HashSet<Object> allowed = new HashSet<Object>();
+ for (Iterator<Object> i =
+ tree.getItemIds().iterator(); i.hasNext();) {
+ Object itemId = i.next();
+ if (tree.hasChildren(itemId))
+ allowed.add(itemId);
+ }
+ return allowed;
+ }
+ };
+ return criterion;
+}
+----
+
+
+[[advanced.dragndrop.acceptcriteria.indicators]]
+=== Accept Indicators
+
+When a dragged object hovers on a drop target, an __accept indicator__ is
+displayed to show whether or not the location is accepted. For
+[parameter]#MIDDLE# location, the indicator is a box around the target (tree
+node, table row, or component). For vertical drop locations, the accepted
+locations are shown as horizontal lines, and for horizontal drop locations as
+vertical lines.
+
+For [classname]#DragAndDropWrapper# drop targets, you can disable the accept
+indicators or __drag hints__ with the [parameter]#no-vertical-drag-hints#,
+[parameter]#no-horizontal-drag-hints#, and [parameter]#no-box-drag-hints#
+styles. You need to add the styles to the __layout that contains__ the wrapper,
+not to the wrapper itself.
+
+
+[source, java]
+----
+// Have a wrapper
+DragAndDropWrapper wrapper = new DragAndDropWrapper(c);
+layout.addComponent(wrapper);
+
+// Disable the hints
+layout.addStyleName("no-vertical-drag-hints");
+layout.addStyleName("no-horizontal-drag-hints");
+layout.addStyleName("no-box-drag-hints");
+----
+
+
+(((range="endofrange", startref="term.advanced.dragndrop.acceptcriteria")))
+
+[[advanced.dragndrop.dragging]]
+== Dragging Components
+
+Dragging a component requires wrapping the source component within a
+[classname]#DragAndDropWrapper#. You can then allow dragging by putting the
+wrapper (and the component) in drag mode with [methodname]#setDragStartMode()#.
+The method supports two drag modes: [parameter]#DragStartMode.WRAPPER# and
+[parameter]#DragStartMode.COMPONENT#, which defines whether the entire wrapper
+is shown as the drag image while dragging or just the wrapped component.
+
+
+[source, java]
+----
+// Have a component to drag
+final Button button = new Button("An Absolute Button");
+
+// Put the component in a D&D wrapper and allow dragging it
+final DragAndDropWrapper buttonWrap = new DragAndDropWrapper(button);
+buttonWrap.setDragStartMode(DragStartMode.COMPONENT);
+
+// Set the wrapper to wrap tightly around the component
+buttonWrap.setSizeUndefined();
+
+// Add the wrapper, not the component, to the layout
+layout.addComponent(buttonWrap, "left: 50px; top: 50px;");
+----
+
+The default height of [classname]#DragAndDropWrapper# is undefined, but the
+default width is 100%. If you want to ensure that the wrapper fits tightly
+around the wrapped component, you should call [methodname]#setSizeUndefined()#
+for the wrapper. Doing so, you should make sure that the wrapped component does
+not have a relative size, which would cause a paradox.
+
+Dragged components are referenced in the [classname]#WrapperTransferable#. You
+can get the reference to the dragged component with
+[methodname]#getDraggedComponent()#. The method will return [literal]#++null++#
+if the transferable is not a component. Also HTML 5 drags (see later) are held
+in wrapper transferables.
+
+
+[[advanced.dragndrop.drop-on-component]]
+== Dropping on a Component
+
+Drops on a component are enabled by wrapping the component in a
+[classname]#DragAndDropWrapper#. The wrapper is an ordinary component; the
+constructor takes the wrapped component as a parameter. You just need to define
+the [classname]#DropHandler# for the wrapper with
+[methodname]#setDropHandler()#.
+
+In the following example, we allow moving components in an absolute layout.
+Details on the drop handler are given later.
+
+
+[source, java]
+----
+// A layout that allows moving its contained components
+// by dragging and dropping them
+final AbsoluteLayout absLayout = new AbsoluteLayout();
+absLayout.setWidth("100%");
+absLayout.setHeight("400px");
+
+... put some (wrapped) components in the layout ...
+
+// Wrap the layout to allow handling drops
+DragAndDropWrapper layoutWrapper =
+ new DragAndDropWrapper(absLayout);
+
+// Handle moving components within the AbsoluteLayout
+layoutWrapper.setDropHandler(new DropHandler() {
+ public AcceptCriterion getAcceptCriterion() {
+ return AcceptAll.get();
+ }
+
+ public void drop(DragAndDropEvent event) {
+ ...
+ }
+});
+----
+
+[[advanced.dragndrop.drop-on-component.details]]
+=== Target Details for Wrapped Components
+
+The drop handler receives the drop target details in a
+[classname]#WrapperTargetDetails# object, which implements the
+[classname]#TargetDetails# interface.
+
+
+[source, java]
+----
+public void drop(DragAndDropEvent event) {
+ WrapperTransferable t =
+ (WrapperTransferable) event.getTransferable();
+ WrapperTargetDetails details =
+ (WrapperTargetDetails) event.getTargetDetails();
+----
+
+The wrapper target details include a [classname]#MouseEventDetails# object,
+which you can get with [methodname]#getMouseEvent()#. You can use it to get the
+mouse coordinates for the position where the mouse button was released and the
+drag ended. Similarly, you can find out the drag start position from the
+transferable object (if it is a [classname]#WrapperTransferable#) with
+[methodname]#getMouseDownEvent()#.
+
+
+[source, java]
+----
+// Calculate the drag coordinate difference
+int xChange = details.getMouseEvent().getClientX()
+ - t.getMouseDownEvent().getClientX();
+int yChange = details.getMouseEvent().getClientY()
+ - t.getMouseDownEvent().getClientY();
+
+// Move the component in the absolute layout
+ComponentPosition pos =
+ absLayout.getPosition(t.getSourceComponent());
+pos.setLeftValue(pos.getLeftValue() + xChange);
+pos.setTopValue(pos.getTopValue() + yChange);
+----
+
+You can get the absolute x and y coordinates of the target wrapper with
+[methodname]#getAbsoluteLeft()# and [methodname]#getAbsoluteTop()#, which allows
+you to translate the absolute mouse coordinates to coordinates relative to the
+wrapper. Notice that the coordinates are really the position of the wrapper, not
+the wrapped component; the wrapper reserves some space for the accept
+indicators.
+
+The [methodname]#verticalDropLocation()# and
+[methodname]#horizontalDropLocation()# return the more detailed drop location in
+the target.
+
+
+
+[[advanced.dragndrop.external]]
+== Dragging Files from Outside the Browser
+
+The [classname]#DragAndDropWrapper# allows dragging files from outside the
+browser and dropping them on a component wrapped in the wrapper. Dropped files
+are automatically uploaded to the application and can be acquired from the
+wrapper with [methodname]#getFiles()#. The files are represented as
+[classname]#Html5File# objects as defined in the inner class. You can define an
+upload [classname]#Receiver# to receive the content of a file to an
+[classname]#OutputStream#.
+
+Dragging and dropping files to browser is supported in HTML 5 and requires a
+compatible browser, such as Mozilla Firefox 3.6 or newer.
+
+
+(((range="endofrange", startref="term.advanced.dragndrop")))
+
+