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 )
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
rendererAdd="handleRendererAdd(event)"
dataProvider="{collectionOne}"
dragEnter="handleDragEnter(event);"
dragDrop="handleDragDrop(event);"
itemRenderer="spark.skins.spark.
DefaultComplexItemRenderer"
skinClass="com.oreilly.f4cb.CustomScrollableSkin">
paddingTop="5" paddingBottom="5" />
rendererAdd="handleRendererAdd(event)"
dataProvider="{collectionTwo}"
dragEnter="handleDragEnter(event);"
dragDrop="handleDragDrop(event);"
itemRenderer="spark.skins.spark.DefaultItemRenderer"
skinClass="com.oreilly.f4cb.CustomScrollableSkin">
paddingTop="5" paddingBottom="5" />
The collection for each SkinnableDataContainer container is a set of s:Button controls.
The containers’ itemRenderer instances differ in how they render data on the content
layer: the first declared container renders each button with its skin intact by assigning
the DefaultCompleteItemRenderer class as the item renderer, while the second declared
container renders only the label assigned to the button control by assigning the
DefaultItemRenderer class as the item renderer.
The handleRendererAdd() method is assigned as an event handler for rendererAdd. Similar to the elementAdd and elementRemove events of the content API, DataGroup and
SkinnableDataContainer dispatch rendererAdd and rendererRemove events whenever an
element representing a data object from the collection is added to or removed from the
content layer of the container, respectively. Event handlers for the dragEnter and drag
Drop events are assigned to each container in order to handle those specific operations
during a drag-and-drop operation:
70 | Chapter 2: Containers
www.it-ebooks.info
package
{
import flash.display.DisplayObjectContainer;
import flash.events.MouseEvent;
import
import
import
import
import
import
mx.collections.IList;
mx.core.DragSource;
mx.core.IUIComponent;
mx.core.IVisualElement;
mx.events.DragEvent;
mx.managers.DragManager;
import
import
import
import
import
spark.components.Application;
spark.components.Group;
spark.components.SkinnableDataContainer;
spark.components.supportClasses.ItemRenderer;
spark.events.RendererExistenceEvent;
public class ApplicationViewController extends Application
{
private var dragItem:Group;
protected function handleRendererAdd( evt:RendererExistenceEvent ):void
{
// assign weak reference listener to visual item renderer
var item:IVisualElement = evt.renderer;
( item as DisplayObjectContainer ).mouseChildren = false;
item.addEventListener( MouseEvent.MOUSE_DOWN, handleStartDrag, false,
0, true );
}
private function handleStartDrag( evt:MouseEvent ):void
{
// grab the item renderer and relevant data
var target:UIComponent = evt.target as UIComponent;
var dragItem:Object = {owner:target.owner,
data:( target as
IDataRenderer ).data};
var dragSource:DragSource = new DragSource();
dragSource.addData( dragItem, "itemRenderer" );
DragManager.doDrag( target, dragSource, evt );
}
protected function handleDragEnter( evt:DragEvent ):void
{
if( evt.dragSource.hasFormat( "itemRenderer" ) )
DragManager.acceptDragDrop( evt.target as IUIComponent );
}
protected function handleDragDrop( evt:DragEvent ):void
{
var dragItem:Object = evt.dragSource.dataForFormat( "itemRenderer" );
var ownerCollection:IList = ( dragItem.owner as
SkinnableDataContainer ).dataProvider;
ownerCollection.removeItemAt( ownerCollection.getItemIndex(
2.15 Drag and Drop Between Data Containers | 71
www.it-ebooks.info
dragItem.data ) );
}
}
}
var targetCollection:IList = ( evt.target as
SkinnableDataContainer ).dataProvider;
targetCollection.addItem( dragItem.data );
The event object for a rendererAdd event dispatched from a DataGroup or a Skinnable
DataContainer is a RendererExistenceEvent. The item renderer that dispatched the event
can be referenced using the renderer property of the event object and is attributed as
an IVisualElement. In this example, a weak-referenced mouseDown event handler is assigned to the item renderer upon receipt of a rendererAdd event by the Application
ViewController and is attributed as the handleStartDrag() method.
When the mouseDown event handler is invoked, the initiating element is attributed as a
UIComponent instance and a generic Object is created to hold the data property assigned
to the element during instantiation. The generic Object is assigned as the drag data on
a DragSource object, which is passed into the DragManager to initiate a drag-and-drop
operation. When the dragged item enters the content layer of a container, the
dragEnter event handler assigned to that container is invoked and is used to determine
whether the data being dragged is acceptable for the container, using the static accept
DragDrop() method of DragManager. If the container is accepted as a receiver, the drag
Drop event handler is invoked upon a drop operation. Upon an accepted drop operation,
the generic Object handled by the DragSource is used to remove the dragged data from
the collection of its original container and add it to the collection of the drop target
container.
Using the DragManager is a convenient way to move data items from one container to
another. However, if more control over the operation is needed, data items can be
transferred between containers or within a single container using the mouse event handlers and methods of the collections API, such as addItem(), addItemAt(), and
removeItem().
2.16 Add a Spark Layout Container to a MX Navigation
Container
Problem
You want to add visual components from the Spark set to a MX navigation container.
72 | Chapter 2: Containers
www.it-ebooks.info
Solution
Add a Spark NavigatorContent container as a child of the desired MX navigation container. Elements from both the Spark and MX component sets can be added as children
to the NavigatorContent container.
Discussion
Although it is recommended to use Spark containers in preference to MX containers
because of their improved runtime performance and separation of responsibilities, the
two sets do not have identical navigation containers in the Flex 4 SDK. Consequently,
depending on development requirements, use of MX navigation containers may be
necessary. Containers and components from the Spark set cannot be declared directly
as content for Halo containers, however, because child containers are attributed as
implementations of INavigatorContent.
To add Spark elements to a MX container, they must be added to a NavigatorContent
container as in the following example:
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
width="100%" height="100%">
width="100%" height="100%">
2.16 Add a Spark Layout Container to a MX Navigation Container | 73
www.it-ebooks.info