You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 4 Next »

"Drag and drop" is the term applied to the action of dragging an object from one place to another. A "drag" begins by pressing down on an eligible object and moving while applying pressure (either by keeping a finger in touch with the screen or pressing down on a mouse button). The "drop" happens when the pressure is released (e.g., letting go of the mouse button). If the drop happens over a suitable place (the "drop target"), then item being dragging is incorporated into the drop target somehow. A drag and drop can either cause the initial object to move to the new location or a copy of the initial object added to the new location.

Drag and Drop in FlexJS is accomplished using beads. When you add the beads to components, you enable them to have some part of them to be dragged and/or act as a drop target. This document will show you how to add the code necessary to make it all work.

DragMouseController

The DragMouseController is the bead you add to a component strand to activate dragging. This will not, by itself, cause anything to be dragged. What it will do is enable special events to be dispatched from the strand which you can catch and use.

<js:Group id="bucketGroup">
<js:beads>
<js:DragMouseController />
</js:beads>
<!-- components in the group -->
</js:Group> 

In this example, a Group has the DragMouseController in its bead list. When the Group is instantiated, set up a listener for the "dragStart" event:

bucketGroup.addEventListener("dragStart", handleDragStart);

The event handler needs to do three things:

  1. Determine which item is being dragged. This is most likely the event.target - one of the members of the Group.
  2. Set the DragEvent.dataSource with the data that represents the item being dragged.
  3. Set the DragMouseController.dragImage to a component that represents the item being dragged. Most often this will be a similar component or one made to look like it.
DragEvent.dataSource = (event.target as MyObject).data;
var dragImage:Label = new Label();
dragImage.text = (event.target as MyObject).toString();
DragMouseController.dragImage = dragImage;

In this example the event.target is cast to a class called "MyObject" which has a data property and that becomes the dragSource. Then a dragImage is created as a simple Label with the Label text being a string representation of the object selected. You can make any UI component or component composite a dragImage.

Once that has been set up in the "dragStart" event handler, the DragMouseController bead takes over and displays the dragImage as you move around the screen.

DropMouseController 

Use DropMouseController with the component strand that will accept the drop from the drag source strand. This can be the same component if you want to use drag and drop to re-arrange a strand's children. The DropMouseController emits its own events, such as "dragEvent" and "dragDrop". You can use these events to provide feedback to the user (such as adding a border when the dragImage enters the drop target space). 

The "dragDrop" event is the event to handle when the user releases the mouse over the strand with the DropMouseController bead. You use this event to incorporate the data being dragged into the target component.

<js:Group id="dropZone">
<js:beads>
<js:VerticalLayout />
<js:DropMouseController dragDrop="handleDrop(event)" />
</js:beads>
</js:Group>

The event listener for the DropMouseController's "dragDrop" event can do whatever it needs to do it incorporate the data.

private function handleDrop(event:DragEvent):void
{
var data:Object = DragEvent.dataSource;
var newItem:OtherObject = new OtherObject(data);
dropZone.addElement(newItem);
dropZone.dispatchEvent(new Event("layoutNeeded"));
}

In this example the dropped data is used to create a new instance of "OtherObject" and it is added as an element to the dropZone Group. Notice that the dropZone group is told to update its layout after the new item is added. FlexJS will not automatically run layouts.

Drag Initiator

Once the drop has completed, its often useful to the source component is know that the drop was accepted. Perhaps you will want to delete the original component or change it somehow to reflect the drag and drop action. You do this by implementing the IDragInitiator interface and setting the object into the DragMouseController:

// code from DragMouseController example, including...
DragMouseController.dragImage = dragImage; // see above
DragMouseController.dragInitiator = this;

Whatever the component class is that has these two Groups becomes the drag initiator, implementing IDragIntiator interface. This means the class will need to implement two functions:

public function acceptingDrop(dropTarget:Object, type:String):void
{
// maybe highlight the component that was dragged.
}
public function acceptedDrop(dropTarget:Object, type:String):void
{
// maybe delete the component that was dragged.
}

The dropTarget parameter in each function just lets you know what object accepted the drop - maybe you will have different drop targets and will react differently depending on where the drop happens. The type is an indicator of what was dropped. You should save some way to identify the drag source in the "dragStart" event.

DataContainer and List Components

Very often a List is used with drag and drop; either to move or copy items from one list to another or to re-arrange items in one list. FlexJS provides specialty beads for Lists.

SingleSelectionDragSourceBead can be used with Lists whose items are to be dragged around. This bead creates a DragMouseController and listens to its events. This bead also implements IDragInitiator.

SingleSelectionDragImageBead can be used with Lists as quick way to display a drag image from the list's itemRenderer that is being dragged about.

SingleSelectionDropTargetBead can be used with Lists that are accepting drops. This can be the same list that uses SingleSelectionDragSourceBead to allow for items to be re-arranged. This bead creates a DropMouseController and listens to its events.

<js:List>
<js:beads>
<js:SingleSelectionDragSourceBead />
<js:SingleSelectionDragImageBead />
<js:SingleSelectionDropTargetBead />
<!-- beads for the data provider -->
</js:beads>
</js:List>

By having these three beads present, the user will now be able to drag one item from the list to a new location within the same list. When the user presses down on an item renderer, the SingleSelectionDragSourceBead will respond by checking to see if there is a drag image; the SingleSelectionDragImageBead will have responded by creating a simple Group+Label as the drag image using the row's data and toString() function; see below to customize the drag image.

As the user drags, the SingleSelectionDropTargetBead is receiving the "dragOver" and "dragEnter" events. This bead does not respond to those, but you could create derivations of it that would respond. 

When the user finally drops, the SingleSelectionDropTargetBead will be notified by the DropMouseController and adds the data from the drag source to the list's data provider. Once the is incorporated, the IDragInitiator, the SingleSelectionDragSourceBead, is called upon to remove the original data unless SingleSelectionDragSourceBead's dragType property was set to "copy".

  • These three beads can also be used with DataGrid in exactly the same way as List or DataContainer. 
  • Pair SingleSelectionDragSourceBead with SingleSelectionImageBead since the image you want to see is that of the item being dragged.
  • Drag between lists by putting SingleSelectionDropTargetBead in another List.

Customizing the Drag Image

When you use the basic DragMouseController and DropMouseController beads, you have to create the drag image yourself. This can be as simple as Label or something more complex; the SingleSelectionDragImageBead creates a Group with a Label child, for example.

When you want to customize the drag image for list or grid drag and drop, you do so by creating a class that extends SingleSelectionDragImageImage and override its protected function, createDragImage(). This function should return a UIBase component. Then you can substitute your custom bead for the <js:SingleSelectionDragImageBead />. 

 

 

  • No labels