Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (8.09 MB, 764 trang )
of UIComponent can receive the series of operations initiated by a drag gesture and dispatch events accordingly; these events include dragEnter, dragExit, dragOver, drag
Drop, and dragComplete.
To initialize a drag-and-drop gesture, add data relevant to the drag-and-drop operation
to a DragSource object within a mouseDown event handler. The DragSource object is given
to the DragManager through the static doDrag() method. The DragSource object held by
the DragManager is used to determine the acceptance of a drop event on a target container
and is handled in the dragDrop event handler to perform the appropriate action.
The following example demonstrates moving children from one visual element container to another:
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
import
import
import
import
import
import
mx.core.IUIComponent;
mx.managers.DragManager;
mx.core.DragSource;
spark.components.SkinnableContainer;
mx.events.DragEvent;
mx.core.IVisualElement;
private function handleStartDrag( evt:MouseEvent ):void
{
// grab the item renderer and relevant data
var dragItem:IUIComponent = evt.target as IUIComponent;
var dragSource:DragSource = new DragSource();
dragSource.addData( dragItem, "item" );
DragManager.doDrag( dragItem, dragSource, evt );
}
protected function handleDragEnter( evt:DragEvent ):void
{
if( evt.dragSource.hasFormat( "item" ) )
DragManager.acceptDragDrop( evt.target as IUIComponent );
}
protected function handleDragDrop( evt:DragEvent ):void
{
var dragItem:Object = evt.dragSource.dataForFormat( "item" );
var dragItemOwner:SkinnableContainer = ( dragItem.owner as
SkinnableContainer );
dragItemOwner.removeElement( dragItem as IVisualElement );
var targetOwner:SkinnableContainer = ( evt.target as
SkinnableContainer );
targetOwner.addElement( dragItem as IVisualElement );
}
]]>
2.14 Drag and Drop Between Visual Containers | 65
www.it-ebooks.info
dragEnter="handleDragEnter(event);"
dragDrop="handleDragDrop(event);"
skinClass="com.oreilly.f4cb.CustomBorderSkin">
dragEnter="handleDragEnter(event);"
dragDrop="handleDragDrop(event);"
skinClass="com.oreilly.f4cb.CustomBorderSkin">
When a s:Button control in the display list of either of the SkinnableContainers
dispatches a mouseDown event, the handleStartDrag() method is invoked and a Drag
Source object is added to the DragManager. The static doDrag() method of the
DragManager initiates a drag-and-drop gesture. It requires at least three arguments:
the drag initiator item reference, a DragSource object, and the initiating MouseEvent. The
image rendered during a drag operation is a rectangle with alpha transparency, by default. The dragged image (referred to as a drag proxy) can be changed through the
dragImage and imageAlpha arguments of the doDrag() method.
Assigning event handlers for dragEnter and dragDrop events identifies the containers as
targets for the drag-and-drop actions initiated by the Button controls. Within the
handleDragEnter() method, the data format is evaluated to see whether the target container accepts drop actions. The static acceptDragDrop() method of the DragManager
registers the container as a drop target. Once a container is accepted as a receiver for
drag-and-drop actions, any subsequent actions associated with the gesture are passed
to the container and the appropriate events are dispatched. Within the dragDrop event
handler, the drag initiator held on the DragSource object of the operation is used to
remove that object from its current owner container and add it to the target drop
container.
Though the previous example demonstrates using the default operation of moving an
element from one container to another, it is possible to implement a copy operation.
The following example demonstrates copying a visual element from one container to
another without allowing the initiating owner to receive a drop operation:
66 | Chapter 2: Containers
www.it-ebooks.info
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
import
import
import
import
import
import
import
spark.components.Button;
mx.managers.DragManager;
mx.core.DragSource;
spark.components.SkinnableContainer;
mx.events.DragEvent;
mx.core.IVisualElement;
mx.core.IUIComponent;
private function handleStartDrag( evt:MouseEvent ):void
{
// grab the item renderer and relevant data
var dragItem:Button = evt.target as Button;
var transferObject:Object = {label:dragItem.label,
owner:dragItem.owner};
var dragSource:DragSource = new DragSource();
dragSource.addData( transferObject, "item" );
DragManager.doDrag( dragItem, dragSource, evt, null, 0, 0, 0.5,
false );
}
protected function handleDragEnter( evt:DragEvent ):void
{
if( evt.dragSource.hasFormat( "item" ) )
{
var targetOwner:SkinnableContainer = ( evt.target as
SkinnableContainer );
var transferObject:Object = evt.dragSource.dataForFormat(
"item" );
if( targetOwner != transferObject.owner )
{
DragManager.acceptDragDrop( evt.target as IUIComponent );
}
}
}
protected function handleDragDrop( evt:DragEvent ):void
{
var transferObject:Object = evt.dragSource.dataForFormat( "item" );
var dragItem:Button = new Button();
dragItem.label = transferObject.label;
var targetOwner:SkinnableContainer = ( evt.target as
SkinnableContainer );
targetOwner.addElement( dragItem as IVisualElement );
}
]]>
2.14 Drag and Drop Between Visual Containers | 67
www.it-ebooks.info
dragEnter="handleDragEnter(event);"
dragDrop="handleDragDrop(event);"
skinClass="com.oreilly.f4cb.CustomBorderSkin">
dragEnter="handleDragEnter(event);"
dragDrop="handleDragDrop(event);"
skinClass="com.oreilly.f4cb.CustomBorderSkin">
When the mouseDown event handler is invoked, a generic object representing the initiating s:Button (with any appropriate property values preserved) is created and passed as
the data transfer object of the DragSource instance. The handleDragEnter event handler
is used not only to determine the validity of the drag initiator, but also to see if the
source and target of the operation are the same. If so, no further drag-and-drop operations are allowed on the container that dispatched the dragEnter event. If the target
container is a valid receiver for the drag-and-drop action, the handleDragDrop() method
is invoked and a new Button control is created based on the generic object of the
DragSource and is added to the target container.
Using the DragManager is a convenient way to move and copy visual elements from one
container to another. If you need more control over the drag-and-drop operation, however, you can transfer elements from one container to another using mouse event handlers and methods of the content API, such as addElement() and removeElement().
2.15 Drag and Drop Between Data Containers
Problem
You want to enable drag-and-drop capabilities between multiple DataGroup containers
so you can easily add and remove data items.
68 | Chapter 2: Containers
www.it-ebooks.info
Solution
Assign a mouseDown event handler to item renderers as they are added to a DataGroup
container and assign drag-and-drop event handlers to any receiving data containers.
Upon receipt of the mouseDown event, assign the data held on the target item renderer
as the DataSource handled by the DragManager to initiate the drag-and-drop operation.
Use the data from the DataSource object to determine the acceptance of a drop gesture
for the target container as drag events are dispatched and, when the dragDrop event is
received, remove the dragged data from the collection of the initiating container and
add the data to the collection of the target drop container.
Discussion
Within a drag-and-drop operation, there is an initiator and a receiver. The initiator
begins the drag-and-drop operation by invoking the static doDrag() method of the
DragManager, typically in response to a user gesture such as a mouseDown event. Any
UIComponent-based element can be a receiver of drag-and-drop gestures and dispatch
events accordingly. Some list-based components in the Flex SDK, such as List, have
built-in support for managing drag-and-drop operations to help automate the process
of moving data from one container to another or within a container itself. DataGroup
and SkinnableDataContainer do not have built-in support, but they can be enabled to
receive drag-and-drop operations as they are extensions of UIComponent.
The example for this recipe is split up into two parts, a view and a controller, to better
demonstrate how to programmatically move data from one data container’s collection
to another. The view is an extension of an ActionScript-based controller and is made
up of two scroll-enabled s:SkinnableDataContainer containers with their own specified
data collections and itemRenderer instances:
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
import com.oreilly.f4cb.CustomScrollableSkin;
]]>
2.15 Drag and Drop Between Data Containers | 69
www.it-ebooks.info