33 Adding Drag and Drop Functionality

This chapter describes how to add drag and drop functionality to your pages, which allows users to drag the values of attributes or objects from one component to another, or allows users to drag and drop components.

This chapter includes the following sections:

33.1 About Drag and Drop Functionality

The ADF Faces framework provides the ability to drag and drop items from one place to another on a page. In most cases, drag and drop can easily be implemented by added the appropriate tags to the source and target and implementing code in a managed bean. Drag and drop provides users with the GUI experience that is expected in web applications. For example, in the File Explorer application, you can drag a file from the Table tab and drop it into another directory folder, as shown in Figure 33-1.

Figure 33-1 Drag and Drop in the File Explorer Application

You can drag a file to another directory folder

In this scenario, you are actually dragging an object from one collection (Folder0) and dropping it into another collection (Folder2). This is one of the many supported drag and drop scenarios. ADF Faces supports the following scenarios:

  • Dragging an attribute value from one component instance and copying it to another. For example, a user might be able to drag an outputText component onto an inputText component, which would result in the value of the text attribute of the outputText component becoming the value of the text attribute on the inputText component.

  • Dragging the value of one object and dropping it so that it becomes the value of another object. For example, a user might be able to drag an outputText component onto another outputText component, which would result in an array of String objects populating the text attribute of the second outputText component.

  • Dragging an object from one collection and dropping it into another, as shown in Figure 33-1.

  • Dragging a component from one place on a page to another. For example, a user might be able to drag an existing panelBox component to a new place within a panelGrid component.

  • Dragging an activity in a calendar from one start time or date to another.

  • Dragging a component into or out of a panelDashboard component.

  • Dragging a marker in a DVT scatter or bubble graph to change its value.

  • Dragging an object from a DVT Gantt chart to another component.

When users click on a source and begin to drag, the browser displays the element being dragged as a ghost element attached to the mouse pointer. Once the ghost element hovers over a valid target, the target component shows some feedback (for example, it becomes highlighted). If the user drags the ghost element over an invalid target, the cursor changes to indicate that the target is not valid.

When dragging attribute values, the user can only copy the value to the target. For all other drag and drop scenarios, on the drop, the element can be copied (copy and paste), moved (cut and paste), or linked (creating a shortcut for a file in a directory in which the link is a reference to the real file object).

The component that will be dragged and that contains the value is called the source. The component that will accept the drop is called the target. You use a specific tag as a child to the source and target components that tells the framework to allow the drop. Table 33-1 shows the different drag and drop scenarios, the valid source(s) and target(s), and the associated tags to be used for that scenario.

Table 33-1 Drag and Drop Scenarios

Scenario Source Target

Dragging an attribute value

An attribute value on a component

An attribute value on another component, as long as it is the same object type

Tag: attributeDragSource

Tag: attributeDropTarget

Dragging an object from one component to another

Any component

Any component

Tag: attributeDragSource

Tag: dropTarget

Dragging an item from one collection and dropping it into another

table, tree, and treeTable components

table, tree, and treeTable components

Tag: dragSource

Tag: collectionDropTarget

Dragging a component from one container to another

Any component

Any component

Tag: componentDragSource

Tag: dropTarget

Dragging a calendar activity from one start time or date to another

calendarActivity object

calendar component

Tag: None needed

Tag: calendarDropTarget

Dragging a panelBox component into a panelDashboard component.

panelBox component

panelDashboard component

Tag: componentDragSource

Tag: dataFlavor

Dragging a panelBox component out of a panelDashboard component.

panelBox component in a panelDashboard component

Any component

Tag: componentDragSource

Tag: dropTarget

Dragging a marker in a DVT graph

graph component

graph component

Tag: dragSource

Tag: dropTarget

Dragging an object from a DVT Gantt chart and dropping it on another component

Gantt chart

Any component

Tag: dragSource

Tag: dropTarget


You can restrict the type of the object that can be dropped on a target by adding a dataFlavor tag. This helps when the target can accept only one object type, but the source may be one of a number of different types. The dataFlavor tag also allows you to set multiple types so that the target can accept objects from more than one source or from a source that may contain more than one type. Both the target and the source must contain the dataFlavor tag, and the values must be the same in order for the drop to be successful.

Note:

Drag and drop functionality is not supported between windows. Any drag that extends past the window boundaries will be canceled. Drag and drop functionality is supported between popup windows and the base page for the popup.

Also note that drag and drop functionality is not accessible; that is, there are no keyboard strokes that can be used to execute a drag and drop. Therefore, if your application requires all functionality to be accessible, you must provide this logic. For example, your page might also present users with a method for selecting objects and a Move button or menu item that allows them to move those selected objects.

33.1.1 Additional Functionality for Drag and Drop

You may find it helpful to understand other ADF Faces features before you implement drag and drop. Following are links to other sections that may be useful for implementing drag and drop.

33.2 Adding Drag and Drop Functionality for Attributes

You add drag and drop functionality for attributes by defining one component's attribute to be a target and another component's attribute to be a source.

Note:

The target and source attribute values must both be the same data type. For example, attribute drag and drop is available when both the source and target are of type String. If they are both of type number, they both use the same converters.

The following procedure assumes you have your target and source components already on the JSF page.

Before you begin:

It may be helpful to have an understanding of drag and drop functionality. For more information, see Section 33.2, "Adding Drag and Drop Functionality for Attributes."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 33.1.1, "Additional Functionality for Drag and Drop."

To add drag and drop functionality for attributes:

  1. In the Component Palette, from the Operations panel, drag and drop an Attribute Drop Target as a child to the target component.

  2. In the Insert Attribute Drop Target dialog, use the Attribute dropdown to select the attribute that will be populated by the drag and drop action. This dropdown list shows all valid attributes on the target component.

  3. From the Component Palette, drag and drop an Attribute Drag Source as a child to the component that can provide a value for the target.

  4. In the Insert Attribute Drag Source dialog, use the Attribute dropdown to select the attribute whose value will be used to populate the target attribute. This dropdown list shows all valid attributes on the source component.

33.3 Adding Drag and Drop Functionality for Objects

When you want users to be able to drag things other than attribute values, or you want users to be able to do something other than copy attributes from one component to another, you use the dropTarget tag. Additionally, use the DataFlavor object to determine the valid Java types of sources for the drop target. Because there may be several drop targets and drag sources, you can further restrict valid combinations by using discriminant values. You also must implement any required functionality in response to the drag and drop action.

For example, suppose you have an outputText component and you want the user to be able to drag the outputText component to a panelBox component and have that component display an array, as shown in Figure 33-6.

Figure 33-2 Dragging and Dropping an Array Object

Drag and drop an object

The outputText component contains an attributeDragSource tag. However, because you want to drag an array (and not just the String value of the attribute), you must use the dropTarget tag instead of the attributeDropTarget tag. Also use a dataFlavor tag to ensure that only an array object will be accepted on the target.

You can also define a discriminant value for the dataFlavor tag. This is helpful if you have two targets and two sources, all with the same object type. By creating a discriminant value, you can be sure that each target will accept only valid sources. For example, suppose you have two targets that both accept an EMPLOYEE object, TargetA and TargetB. Suppose you also have two sources, both of which are EMPLOYEE objects. By setting a discriminant value on TargetA with a value of alpha, only the EMPLOYEE source that provides the discriminant value of alpha will be accepted.

You also must implement a listener for the drop event. The object of the drop event is called the transferable, which contains the payload of the drop. Your listener must access the transferable object, and from there, use the DataFlavor object to verify that the object can be dropped. You then use the drop event to get the target component and update the property with the dropped object. More details about this listener are covered in the procedure in Section 33.9.1, "How to Add Drag and Drop Functionality for a DVT Component".

33.3.1 How to Add Drag and Drop Functionality for a Single Object

To add drag and drop functionality, first add tags to a component that define it as a target for a drag and drop action. Then implement the event handler method that will handle the logic for the drag and drop action. Last, you define the sources for the drag and drop.

Before you begin:

It may be helpful to have an understanding of drag and drop functionality. For more information, see Section 33.3, "Adding Drag and Drop Functionality for Objects."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 33.1.1, "Additional Functionality for Drag and Drop."

You will need to complete this task:

Create the source and target components on the page.

To add drag and drop functionality:

  1. In the JSF page that contains the target, add a dropTarget tag as a child to the target component by dragging and dropping a Drop Target tag (located in the Operations panel) from the Component Palette.

  2. In the Insert Drop Target dialog, enter an expression that evaluates to a method on a managed bean that will handle the event (you will create this code in Step 5).

    For information about using managed beans, see Section 3.6, "Creating and Using Managed Beans."

    Tip:

    You can also intercept the drop on the client by populating the clientDropListener attribute. For more information, see Section 33.3.3, "What You May Need to Know About Using the ClientDropListener."
  3. In the Insert Data Flavor dialog, enter the class for the object that can be dropped onto the target, for example java.lang.Object. This selection will be used to create a dataFlavor tag, which determines the type of object that can be dropped onto the target, for example a String or a Date. Multiple dataFlavor tags are allowed under a single drop target to allow the drop target to accept any of those types.

    Tip:

    To specify a typed array in a DataFlavor tag, add brackets ([]) to the class name, for example, java.lang.Object[].
  4. In the Structure window, select the dropTarget tag. In the Property inspector, select a value for the actions attribute. This defines what actions are supported by the drop target. Valid values can be COPY (copy and paste), MOVE (cut and paste), and LINK (copy and paste as a link), for example:.

    MOVE COPY
    

    If no actions are specified, the default is COPY.

    Example 33-1 shows the code for a dropTarget component inserted into an panelBox component that takes an array object as a drop target. Note that because an action was not defined, the only allowed action will be COPY.

    Example 33-1 JSP Code for a dropTarget tag

    <af:panelBox text="PanelBox2">
      <f:facet name="toolbar"/>
      <af:dropTarget dropListener="#{myBean.handleDrop}">
        <af:dataFlavor flavorClass="java.lang.Object[]"/>
      </af:dropTarget>
    </af:panelBox>
    
  5. In the managed bean referenced in the EL expression created in Step 2, create the event handler method (using the same name as in the EL expression) that will handle the drag and drop functionality.

    This method must take a DropEvent event as a parameter and return a DnDAction object, which is the action that will be performed when the source is dropped. Valid return values are DnDAction.COPY, DnDAction.MOVE, and DnDAction.LINK, and were set when you defined the target attribute in Step 5. This method should check the DropEvent event to determine whether or not it will accept the drop. If the method accepts the drop, it should perform the drop and return the DnDAction object it performed. Otherwise, it should return DnDAction.NONE to indicate that the drop was rejected.

    The method must also check for the presence for each dataFlavor object in preference order.

    Tip:

    If your target has more than one defined dataFlavor object, then you can use the Transferable.getSuitableTransferData() method, which returns a List of TransferData objects available in the Transferable object in order, from highest suitability to lowest.

    The DataFlavor object defines the type of data being dropped, for example java.lang.Object, and must be as defined in the DataFlavor tag on the JSP, as created in Step 3.

    Tip:

    To specify a typed array in a DataFlavor object, add brackets ([]) to the class name, for example, java.lang.Object[].

    DataFlavor objects support polymorphism so that if the drop target accepts java.util.List, and the transferable object contains a java.util.ArrayList, the drop will succeed. Likewise, this functionality supports automatic conversion between Arrays and Lists.

    If the drag and drop framework doesn't know how to represent a server DataFlavor object on the client component, the drop target will be configured to allow all drops to succeed on the client.

    Example 33-2 shows a private method that the event handler method calls (the event handler itself does nothing but call this method; it is needed because this method also needs a String parameter that will become the value of the outputText component in the panelBox component). This method copies an array object from the event payload and assigns it to the component that initiated the event.

    Example 33-2 Event Handler Code for a dropListener

    public DnDAction handleDrop(DropEvent dropEvent) 
    {
      Transferable dropTransferable = dropEvent.getTransferable();
              Object[] drinks = dropTransferable.getData(DataFlavor.OBJECT_ARRAY_FLAVOR);
            
        if (drinks != null)
        {
          UIComponent dropComponent = dropEvent.getDropComponent();
              
    // Update the specified property of the drop component with the Object[] dropped
          dropComponent.getAttributes().put("value", Arrays.toString(drinks));
              
          return DnDAction.COPY;
        }
        else
        {
          return DnDAction.NONE;      
        }    
      }   
    
  6. Add a clientAttribute tag as a child to the source component by dragging a Client Attribute (located in the Operations panel), from the Component Palette. This tag is used to define the payload of the source for the event. Define the following for the clientAttribute tag in the Property Inspector:

    • Name: Enter any name for the payload.

    • Value: Enter an EL expression that evaluates to the value of the payload. In the drinks example, this would resolve to the Array that holds the different drink values.

  7. Drag and drop an Attribute Drag Source (located in the Operations panel), from the palette as another child to the source component. In the Insert Attribute Drag Source dialog, use the dropdown list to select the name defined for the clientAttribute tag created in the previous step. Doing so makes the value of the clientAttribute tag the source's payload. Example 33-3 shows the code for an outputText component that is the source of the drag and drop operation.

    Example 33-3 JSP Code for a Drag Source

    <af:outputText value="Drag to see drinks">
      <af:clientAttribute name="drinks" value="#{myBean.drinks}"/>
      <af:attributeDragSource attribute="drinks"/>
    </af:outputText>
    

33.3.2 What Happens at Runtime

When performing a drag and drop operation, users can press keys on the keyboard (called keyboard modifiers) to select the action they wish to take on a drag and drop. The drag and drop framework supports the following keyboard modifiers:

  • SHIFT: MOVE

  • CTRL: COPY

  • CTRL+SHIFT: LINK

When a user executes the drag and drop operation, the drop target first determines that it can accept the drag source's data flavor value. Next, if the source and target are collections, the framework intersects the actions allowed between the drag source and drop target and executes the action (one of COPY, MOVE, or LINK) in that order from the intersection. When there is only one valid action, that action is executed. When there is more than one possible action and the user's keyboard modifier matches that choice, then that is the one that is executed. If either no keyboard modifier is used, or the keyboard modifier used does not match an allowed action, then the framework chooses COPY, MOVE, LINK in that order, from the set of allowed actions.

For example, suppose you have a drop target that supports COPY and MOVE. First the drop target determines that drag source is a valid data flavor. Next, it determines which action to perform when the user performs the drop. In this example, the set is COPY and MOVE. If the user holds down the SHIFT key while dragging (the keyboard modifier for MOVE), the framework would choose the MOVE action. If the user is doing anything other than holding down the SHIFT key when dragging, the action will be COPY because COPY is the default when no modifier key is chosen (it is first in the order). If the user is pressing the CTRL key, that modifier matches COPY, so COPY would be performed. If the user was pressing the CTRL+SHIFT keys, the action would still be COPY because that modifier matches the LINK action which is not in the intersected set of allowed actions.

Note:

Because information is lost during the roundtrip between Java and JavaScript, the data in the drop may not be the type that you expect. For example, all numeric types appear as double objects, char objects appear as String objects, List and Array objects appear as List objects, and most other objects appear as Map objects. For more information, see Section 6.4.3, "What You May Need to Know About Marshalling and Unmarshalling Data.".

33.3.3 What You May Need to Know About Using the ClientDropListener

The dropTarget tag contains the clientDropListener attribute where you can reference JavaScript that will handle the drop event on the client. The client handler should not take any parameters and returns an AdfDnDContext action. For example, if the method returns AdfDnDContext.ACTION_NONE the drop operation will be canceled and no server call will be made; if the method returns AdfDnDContext.ACTION_COPY, a copy operation will be allowed and a server call will be made which will execute the dropListener method if it exists.

For example, suppose you want to log a message when the drop event is invoked. You might create a client handler to handle logging that message and then returning the correct action so that the server listener is invoked. Example 33-4 shows a client handler that uses the logger to print a message.

Example 33-4 clientDropListener Handler

<script>
/**
 * Shows a message.
 */
function showMessage()
{
  AdfLogger.LOGGER.logMessage(AdfLogger.ALL, "clientDropListener handler,
    copying...");
  return AdfDnDContext.ACTION_COPY;
}
</script>

33.4 Adding Drag and Drop Functionality for Collections

You use the collectionDropTarget and dragSource tags to add drag and drop functionality that allows users to drag an item from one collection (for example, a row from a table), and drop it into another collection component such, as a tree. For example, in the File Explorer application, users can drag a file from the table that displays directory contents to any folder in the directory tree. Figure 33-3 shows the File0.doc object being dragged from the table displaying the contents of the Folder0 directory to the Folder3 directory. Once the drop is complete, the object will become part of the collection that makes up Folder3.

Figure 33-3 Drag and Drop Functionality in the File Explorer Application

Drag a file to a directory

As with dragging and dropping single objects, you can have a drop on a collection with a copy, move, or copy and paste as a link (or a combination of the three), and use dataFlavor tags to limit what a target will accept.

When the target source is a collection and it supports the move operation, you may also want to also implement a method for the dragDropEndListener attribute, which is referenced from the source component and is used to clean up the collection after the drag and drop operation. For more information, see Section 33.4.2, "What You May Need to Know About the dragDropEndListener".

33.4.1 How to Add Drag and Drop Functionality for Collections

To add drag and drop functionality for collections, instead of using the dropTarget tag, you use the collectionDropTarget tag. You then must implement the event handler method that will handle the logic for the drag and drop action. Next, you define the source for the drag and drop operation using the dragSource tag.

Before you begin:

It may be helpful to have an understanding of drag and drop functionality. For more information, see Section 33.4, "Adding Drag and Drop Functionality for Collections."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 33.1.1, "Additional Functionality for Drag and Drop."

You will need to complete this task:

Create the source and target components on the page.

To add drag and drop functionality:

  1. Add a collectionDropTarget tag as a child to the target collection component by dragging a Collection Drop Target from the Component Palette.

  2. In the Insert Collection Drop Target dialog, enter an expression for the dropListener attribute that evaluates to a method on a managed bean that will handle the event (you will create this code in Step 4).

  3. In the Property Inspector, set the following:

    • actions: Select the actions that can be performed on the source during the drag and drop operation.

      If no actions are specified, the default is COPY.

    • modelName: Define the model for the collection.

      The value of the modelName attribute is a String object used to identify the drag source for compatibility purposes. The value of this attribute must match the value of the discriminant attribute of the dragSource tag you will use in a Step 6. In other words, this is an arbitrary name and works when the target and the source share the same modelName value or discriminant value.

  4. In the managed bean inserted into the EL expression in Step 2, implement the handler for the drop event.

    This method must take a DropEvent event as a parameter and return a DnDAction. This method should use the DropEvent to get the Transferable object and from there get the RowKeySet (the rows that were selected for the drag). Using the CollectionModel obtained through the Transferable object, the actual rowData can be obtained to complete the drop. The method should then check the DropEvent to determine whether it will accept the drop or not. If the method accepts the drop, it should perform the drop and return the DnDAction it performed -- DnDAction.COPY, DnDAction.MOVE or DnDAction.LINK, otherwise it should return DnDAction.NONE to indicate that the drop was rejected.

    Example 33-5 shows the event handler method on the CollectionDnd.java managed bean used in the collectionDropTarget demo that handles the copy of the row between two tables.

    Example 33-5 Event Handler Code for a dropListener for a Collection

    public DnDAction handleDrop(DropEvent dropEvent)
    {
      Transferable transferable = dropEvent.getTransferable();
      // The data in the transferable is the row key for the dragged component.
      DataFlavor<RowKeySet> rowKeySetFlavor =
                           DataFlavor.getDataFlavor(RowKeySet.class, "DnDDemoModel");
      RowKeySet rowKeySet = transferable.getData(rowKeySetFlavor);
      if (rowKeySet != null)
      {
        // Get the model for the dragged component.
        CollectionModel dragModel = transferable.getData(CollectionModel.class);
        if (dragModel != null)
        {
          // Set the row key for this model using the row key from the transferable.
          Object currKey = rowKeySet.iterator().next();
          dragModel.setRowKey(currKey);
            
          // And now get the actual data from the dragged model.
          // Note this won't work in a region.
          DnDDemoData dnDDemoData = (DnDDemoData)dragModel.getRowData();
          
          // Put the dragged data into the target model directly. 
          // Note that if you wanted validation/business rules on the drop,
          // this would be different.
          // getTargetValues() is the target collection used by the target component
          getTargetValues().add(dnDDemoData);
        }
        return dropEvent.getProposedAction();
      }
      else
      {
        return DnDAction.NONE;      
      }
    }
      
    
  5. In the Component Palette, from the Operations panel, drag and drop a Drag Source as a child to the source component.

  6. With the dragSource tag selected, in the Property Inspector set the actions, discriminant, and any dragDropEndListener as configured for the target. For instance, the dragSource tag may appear similar to the following:

    <af:dragSource actions="MOVE" discriminant="DnDDemoModel
    dragDropEndListener="#{collectionDnD.endListener}"/>
    

33.4.2 What You May Need to Know About the dragDropEndListener

There may be cases when after a drop event, you have to clean up the source collection. For example, if the drag caused a move, you may have to clean up the source component so that the moved item is no longer part of the collection.

The dragSource tag contains the dragDropEndListener attribute that allows you to register a handler that contains logic for after the drag drop operation ends.

For example, if you allow a drag and drop to move an object, you may have to physically remove the object from the source component once you know the drop succeeded. Example 33-6 shows a handler for a dragDropEndListener. attribute

Example 33-6 Handler for dragDropEndListener

public void endListener(DropEvent dropEvent)
{
  Transferable transferable = dropEvent.getTransferable();
  
  // The data in the transferrable is the row key for the dragged component.
  DataFlavor<RowKeySet> rowKeySetFlavor =
      DataFlavor.getDataFlavor(RowKeySet.class, "DnDDemoModel");
  RowKeySet rowKeySet = transferable.getData(rowKeySetFlavor);
  if (rowKeySet != null)
  {
    Integer currKey = (Integer)rowKeySet.iterator().next();

   // Remove the dragged data from the source model directly.
   // getSourceValues() represents a collection object used by the source
   // component
    Object removed = getSourceValues().remove(currKey.intValue());
  }
  // Need to add the drag source table so it gets redrawn.
  // The drag source component needs to be partially refreshed explicitly, while 
  // drop target component automatically refreshed and displayed.
    AdfFacesContext.getCurrentInstance().addPartialTarget(dropEvent.getDragComponent());
  

33.5 Adding Drag and Drop Functionality for Components

You can allow components to be moved from one parent to another, or you can allow child components of a parent component to be reordered. For example, Figure 33-4 shows the darker panelBox component being moved from being the first child component of the panelGrid component to the last.

Figure 33-4 Drag and Drop Functionality Between Components

You can drag and drop components

Note:

If you want to move components into or out of a panelDashboard component, then you need to use procedures specific to that component. For more information, see Section 33.6, "Adding Drag and Drop Functionality Into and Out of a panelDashboard Component."

33.5.1 How to Add Drag and Drop Functionality for Components

Adding drag and drop functionality for components is similar for objects. However, instead of using the attributeDragSource tag, use the componentDragSource tag. As with dragging and dropping objects or collections, you also must implement a dropListener handler.

Before you begin:

It may be helpful to have an understanding of drag and drop functionality. For more information, see Section 33.5, "Adding Drag and Drop Functionality for Components."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 33.1.1, "Additional Functionality for Drag and Drop."

To add drag and drop functionality:

  1. From the Operations panel of the Component Palette, drag and drop a Drop Target as a child to the target component.

  2. In the Insert Drop Target dialog, enter an expression that evaluates to a method on a managed bean that will handle the event (you will create this code in Step 4).

  3. With the dropTarget tag still selected, in the Property Inspector, select a valid action set for the actions attribute.

  4. In the managed bean referenced in the EL expression created in Step 2 for the dropListener attribute, create the event handler method (using the same name as in the EL expression) that will handle the drag and drop functionality.

    If the method accepts the drop, it should perform the drop and return the DnDAction it performed -- DnDAction.COPY, DnDAction.MOVE or DnDAction.LINK, otherwise it should return DnDAction.NONE to indicate that the drop was rejected

    This handler method should use the DropEvent event to get the transferable object and its data and then complete the move or copy, and reorder the components as needed. Once the method completes the drop, it should return the DnDAction it performed. Otherwise, it should return DnDAction.NONE to indicate that the drop was rejected.

    Example 33-7 shows the handleComponentMove event handler on the DemoDropHandler.java managed bean used by the componentDragSource JSF page in the demo application.

    Example 33-7 Event Handler Code for a dropListener That Handles a Component Move

    public DnDAction handleComponentMove(DropEvent dropEvent)
    {
      Transferable dropTransferable = dropEvent.getTransferable();
      UIComponent movedComponent =  dropTransferable.getData
                                   (DataFlavor.UICOMPONENT_FLAVOR);
      if ((movedComponent != null) &&
           DnDAction.MOVE.equals(dropEvent.getProposedAction()))
      {
        UIComponent dropComponent = dropEvent.getDropComponent();
        UIComponent dropParent = dropComponent.getParent();
        UIComponent movedParent = movedComponent.getParent();
        UIComponent rootParent = null;
        ComponentChange change = null;
        
        // Build the new list of IDs, placing the moved component after the dropped
        //component.
        String movedLayoutId = movedParent.getId();
        String dropLayoutId = dropComponent.getId();
          
        List<String> reorderedIdList = new
                                       ArrayList<String>(dropParent.getChildCount());
            
        for (UIComponent currChild : dropParent.getChildren())
        {
          String currId = currChild.getId();
            
          if (!currId.equals(movedLayoutId))
          {
            reorderedIdList.add(currId);
            if (currId.equals(dropLayoutId))
            {
              reorderedIdList.add(movedLayoutId);
            }
          }
        }
          
        change = new ReorderChildrenComponentChange(reorderedIdList);
        rootParent = dropParent;
        // apply the change to the component tree immediately
        // change.changeComponent(rootParent);
          
        // redraw the shared parent
        AdfFacesContext.getCurrentInstance().addPartialTarget(rootParent);
        
        return DnDAction.MOVE;
      }
      else
      {
        return DnDAction.NONE;      
      }
    }
    
  5. Add a componentDragSource tag to the source component by dragging and dropping a Component Drag Source from the Component Palette as a child of the source component. For instance, the componentDragSource tag may appear similar to the following:

    <af:componentDragSource discriminant="col2"/>
    

33.6 Adding Drag and Drop Functionality Into and Out of a panelDashboard Component

By default the panelDashboard component supports dragging and dropping components within itself. That is, you can reorder components in a panelDashboard component without needing to implement a listener or use additional tags. However, if you want to be able to drag a component into a panelDashboard component, or to drag a component out of a panelDashboard component, you do need to use tags and implement a listener. Because you would be dragging and dropping a component, you use the componentDragSource tag when dragging into the panelDashboard. However, because the panelDashboard already supports being a drop target, you do not need to use the dropTarget tag. Instead, you need to use a dataFlavor tag with a discriminant. The tag and discriminant notify the framework that the drop is from an external component.

Dragging a component out of a panelDashboard is mostly the same as dragging and dropping any other component. You use a dropTarget tag for the target and the componentDragSource tag for the source. However, you must also use the dataFlavor tag and a discriminant.

33.6.1 How to Add Drag and Drop Functionality Into a panelDashboard Component

Because the panelDashboard component has built-in drag and drop functionality used to reorder panelBox components within the dashboard, you need not use a dropTarget tag, but you do need to use a dataFlavor tag with a discriminant and implement the dropListener. In that implementation, you need to handle the reorder of the components.

Before you begin:

It may be helpful to have an understanding of drag and drop functionality. For more information, see Section 33.6, "Adding Drag and Drop Functionality Into and Out of a panelDashboard Component."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 33.1.1, "Additional Functionality for Drag and Drop."

Before you begin:

  1. Create a panelDashboard component. For more information, see Section 9.7, "Arranging Contents in a Dashboard."

  2. Create another component outside of the panelDashboard that contains panelBox components. For more information about panelBox components, see Section 9.8.3, "How to Use the panelBox Component."

To add drag and drop functionality into a panelDashboard component:

  1. In the Structure window, select the panelDashboard component that is to be the target component.

  2. In the Property Inspector, for DropListener, enter an expression that evaluates to a method on a managed bean that will handle the drop event (you will create this code in Step 6).

  3. In the Component Palette, from the Operations panel, drag a Data Flavor and drop it as a child to the panelDashboard component.

  4. In the Insert Data Flavor dialog, enter javax.faces.component.UIComponent.

  5. In the Property Inspector, set Discriminant to a unique name that will identify the components allowed to be dragged into the panelDashboard component, for example, dragIntoDashboard.

  6. In the managed bean referenced in the EL expression created in Step 2 for the dropListener attribute, create the event handler method (using the same name as in the EL expression) that will handle the drag and drop functionality.

    This method must take a DropEvent event as a parameter and return a DnDAction of NONE, because the panelDashboard handles the positioning of its child components.

    This handler method should use the dropEvent.getTransferable().getData(DataFlavor.UICOMPONENT_FLAVOR) to get the transferable object and its data. Once the method completes the drop, you can use the org.apache.myfaces.trinidad.change.ReorderChildrenComponent Change method to preserve the new ordering of the children and the dropEvent.getDropSiteIndex() method to get the location at which the user wants the dragged component. You can also use the dashboardComponent.prepareOptimizedEncodingOfInsertedChild() method to animate the drop of the component.

    Example 33-8 shows the move event handler and helper methods on the DemoDashboardBean.java managed bean used by the dashboard JSF page in the ADF Faces demo application.

    Example 33-8 Handler for DropListener on a panelDashboard Component

    public DnDAction move(DropEvent e)
    {
      UIComponent dropComponent = e.getDropComponent();
      UIComponent movedComponent = e.getTransferable().getData(DataFlavor.UICOMPONENT_FLAVOR);
      UIComponent movedParent = movedComponent.getParent();
       // Ensure that we are handling the re-order of a direct child of the panelDashboard:
      if (movedParent.equals(dropComponent) && dropComponent.equals(_dashboard))
      {
        // Move the already rendered child and redraw the side bar since the insert indexes have
        // changed:
        _moveDashboardChild(e.getDropSiteIndex(), movedComponent.getId());
      }
      else
      {
        // This isn't a re-order but rather the user dropped a minimized side bar item into the
        // dashboard, in which case that item should be restored at the specified drop location.
        String panelKey = _getAssociatedPanelKey(movedComponent);
        if (panelKey != null)
        {
          UIComponent panelBoxToShow = _dashboard.findComponent(panelKey);
            // Make this panelBox rendered:
            panelBoxToShow.setRendered(true);
     
          int insertIndex = e.getDropSiteIndex();
    
          // Move the already rendered child and redraw the side bar since the insert indexes have
          // changed and because the side bar minimized states are out of date:
          _moveDashboardChild(insertIndex, panelKey);
    
          // Let the dashboard know that only the one child should be encoded during the render phase:
          _dashboard.prepareOptimizedEncodingOfInsertedChild(
            FacesContext.getCurrentInstance(),
            insertIndex);
        }
      }
     
      return DnDAction.NONE; // the client is already updated, so no need to redraw it again
    }
    
      private void _moveDashboardChild(int dropIndex, String movedId)
      {
        // Build the new list of IDs, placing the moved component at the drop index.
        List<String> reorderedIdList = new ArrayList<String>(_dashboard.getChildCount());
        int index = 0;
        boolean added = false;
     
        for (UIComponent currChild : _dashboard.getChildren())
        {
          if (currChild.isRendered())
          {
            if (index == dropIndex)
            {
              reorderedIdList.add(movedId);
              added = true;
            }
     
            String currId = currChild.getId();
            if (currId.equals(movedId) && index < dropIndex)
            {
              // component is moved later, need to shift the index by 1
              dropIndex++;
            }
     
            if (!currId.equals(movedId))
            {
              reorderedIdList.add(currId);
            }
            index++;
          }
        }
     
        if (!added)
        {
          // Added to the very end:
          reorderedIdList.add(movedId);
        }
     
        // Apply the change to the component tree immediately:
        ComponentChange change = new ReorderChildrenComponentChange(reorderedIdList);
        change.changeComponent(_dashboard);
     
        // Add the side bar as a partial target since we need to redraw the state of the side bar items
        // since their insert indexes are changed and possibly because the side bar minimized states
        // are out of date:
        RequestContext rc = RequestContext.getCurrentInstance();
        rc.addPartialTarget(_sideBarContainer);
      }
    
  7. In the Component Palette, from the Operations panel, drag a Component Drag Source and drop it as a child to the panelBox component that will be the source component.

  8. In the Property Inspector, set Discriminant to be the same value as entered for the Discriminant on the panelDashboard in Step 5.

33.6.2 How to Add Drag and Drop Functionality Out of a panelDashboard Component

Implementing drag and drop functionality out of a panelDashboard component is similar to standard drag and drop functionality for other components, except that you must use a dataFlavor tag with a discriminant.

Before you begin:

It may be helpful to have an understanding of drag and drop functionality. For more information, see Section 33.6, "Adding Drag and Drop Functionality Into and Out of a panelDashboard Component."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 33.1.1, "Additional Functionality for Drag and Drop."

How to add drag and drop functionality out of a panelDashboard component:

  1. In the Component Palette, from the Operations panel, drag and drop a Drop Target as a child to the target component.

  2. In the Insert Drop Target dialog, enter an expression that evaluates to a method on a managed bean that will handle the event (you will create this code in Step 5) and enter javax.faces.component.UIComponent as the FlavorClass.

  3. With the dropTarget tag still selected, in the Property Inspector, select MOVE as the value action attribute.

  4. In the Structure window, select the dataFlavor tag and in the Property Inspector, set Discriminant to a unique name that will identify the panelBox components allowed to be dragged into this component, for example, dragOutOfDashboard.

  5. In the managed bean referenced in the EL expression created in Step 2 for the dropListener attribute, create the event handler method (using the same name as in the EL expression) that will handle the drag and drop functionality.

    This handler method should use the DropEvent event to get the transferable object and its data and then complete the move and reorder the components as needed. Once the method completes the drop, it should return a DnDAction of NONE.

    You can use the dashboardComponent.prepareOptimizedEncodingOfDeletedChild() method to animate the removal of the panelBox component.

    Example 33-9 shows the handleSideBarDrop event handler and helper methods on the oracle.adfdemo.view.layout.DemoDashboardBean.java managed bean used by the dashboard JSF page in the demo application.

    Example 33-9 Event Handler Code for a dropListener That Handles a panelBox Move Out of a panelDashboard Component

    public DnDAction handleSideBarDrop(DropEvent e)
    {
      UIComponent movedComponent = e.getTransferable().getData(DataFlavor.UICOMPONENT_FLAVOR);
      UIComponent movedParent = movedComponent.getParent();
     
      // Ensure that the drag source is one of the items from the dashboard:
      if (movedParent.equals(_dashboard))
      {
        _minimize(movedComponent);
      }
    
      return DnDAction.NONE; // the client is already updated, so no need to redraw it again
    }
    
      private void _minimize(UIComponent panelBoxToMinimize)
      {
        // Make this panelBox non-rendered:
        panelBoxToMinimize.setRendered(false);
     
        // If the dashboard is showing, let's perform an optimized render so the whole dashboard doesn't
        // have to be re-encoded.
        // If the dashboard is hidden (because the panelBox is maximized), we will not do an optimized
        // encode since we need to draw the whole thing.
        if (_maximizedPanelKey == null)
        {
          int deleteIndex = 0;
          List<UIComponent> children = _dashboard.getChildren();
          for (UIComponent child : children)
          {
            if (child.equals(panelBoxToMinimize))
            {
              _dashboard.prepareOptimizedEncodingOfDeletedChild(
                FacesContext.getCurrentInstance(),
                deleteIndex);
              break;
            }
     
            if (child.isRendered())
            {
              // Only count rendered children since that's all that the panelDashboard can see:
              deleteIndex++;
            }
          }
        }
     
        RequestContext rc = RequestContext.getCurrentInstance();
        if (_maximizedPanelKey != null)
        {
          // Exit maximized mode:
          _maximizedPanelKey = null;
     
          _switcher.setFacetName("restored");
          rc.addPartialTarget(_switcher);
        }
     
        // Redraw the side bar so that we can update the colors of the opened items:
        rc.addPartialTarget(_sideBarContainer);
      }
    
  6. In the Component Palette, from the Operations panel, drag and drop a Component Drag Source as a child of the source panelBox component within the panelDashboard component.

  7. In the Property Inspector, set Discriminant to be the same value as entered for the Discriminant on the dataFlavor tag for the target component in Step 4.

33.7 Adding Drag and Drop Functionality to a Calendar

The calendar includes functionality that allows users to drag the handle of an activity to change the end time. However, if you want users to be able to drag and drop an activity to a different start time, or even a different day, then you implement drag and drop functionality. Drag and drop allows you to not only move an activity, but also to copy one.

33.7.1 How to Add Drag and Drop Functionality to a Calendar

You add drag and drop functionality by using the calendarDropTarget tag. Unlike dragging and dropping a collection, there is no need for a source tag; the target (that is the object to which the activity is being moved, in this case, the calendar) is responsible for moving the activities. If the source (that is, the item to be moved or copied), is an activity within the calendar, then you use only the calendarDropTarget tag. The tag expects the transferable to be a CalendarActivity object.

However, you can also drag and drop objects from outside the calendar. When you want to enable this, use dataFlavor tags configured to allow the source object (which will be something other than a calendarActivity object) to be dropped.

Before you begin:

It may be helpful to have an understanding of drag and drop functionality. For more information, see Section 33.7, "Adding Drag and Drop Functionality to a Calendar."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 33.1.1, "Additional Functionality for Drag and Drop."

To add drag and drop functionality to a calendar:

  1. In the Component Palette, from the Operations panel, drag and drop a Calendar Drop Target as a child to the calendar component.

  2. In the Insert Calendar Drop Target dialog, enter an expression for the dropListener attribute that evaluates to a method on a managed bean that will handle the event (you will create this code in Step 4).

  3. In the Property Inspector, set Actions. This value determines whether the activity (or other source) can be moved, copied, or copied as a link, or any combination of the three. If no action is specified, the default is COPY.

  4. In the managed bean inserted into the EL expression in Step 2, implement the handler for the drop event.

    This method must take a DropEvent event as a parameter and return a DnDAction. The DnDAction is the action that will be performed when the source is dropped. Valid return values are COPY, MOVE, and LINK, and are set when you define the actions attribute in Step 3. This method should use the DropEvent to get the transferable object, and from there, access the CalendarModel object in the dragged data and from there, access the actual data. The listener can then add that data to the model for the source and then return the DnDAction it performed: DnDAction.COPY, DnDAction.MOVE or DnDAction.LINK; otherwise, the listener should return DnDAction.NONE to indicate that the drop was rejected.

    The drop site for the drop event is an instance of the oracle.adf.view.rich.dnd.CalendarDropSite class. For an example of a drag and drop handler for a calendar, see the handleDrop method on the oracle.adfdemo.view.calendar.rich.DemoCalendarBean managed bean in the ADF Faces demo application.

  5. If the source for the activity is external to the calendar, drag a Data Flavor and drop it as a child to the calendarDropTarget tag. This tag determines the type of object that can be dropped onto the target, for example a String or a Date object. Multiple dataFlavor tags are allowed under a single drop target to allow the drop target to accept any of those types.

  6. In the Insert Data Flavor dialog, enter the class for the object that can be dropped onto the target, for example java.lang.Object.

    Tip:

    To specify a typed array in a dataFlavor tag, add brackets ([]) to the class name, for example, java.lang.Object[].

33.7.2 What You May Need to Know About Dragging and Dropping in a Calendar

For dragging and dropping activities within a calendar, users can drag and drop only within a view. That is, users can drag an activity from one time slot to another in the day view, but cannot cut an activity from a day view and paste it into a month view.

When the user is dragging and dropping activities in the day or week view, the calendar marks the drop site by half-hour increments. The user cannot move any all-day or multi-day activities in the day view.

In the week view, users can move all-day and multi-day activities, however, they can be dropped only within other all-day slots. That is, the user cannot change an all-day activity to an activity with start and end times. In the month view, users can move all-day and multi-day activities to any other day.

33.8 Adding Drag and Drop Functionality for DVT Graphs

You can configure drag and drop for the DVT bubble and scatter graphs, which allows the user to change the value of a marker by repositioning it. When you want users to be able to drag and drop in a graph, you use the dragSource and dropTarget tags. Additionally, you use the DataFlavor object to determine the valid Java type of the sources for the drop target, in this case a GraphSelection object. You also must implement any required functionality in response to the drag and drop action.

For example, you might have a scatterGraph component and you want the user to be able to drag a human scatter marker to adjust the performance rating of an employee, as shown in Figure 33-6.

Figure 33-5 Dragging and Dropping an Object

Drag and drop an object

The scatterGraph component contains both a dragSource tag and a dropTarget tag. You also use a dataFlavor tag to determine the type of object being dropped.

You also must implement a listener for the drop event. The object of the drop event is called the transferable, which contains the payload of the drop. Your listener must access the transferable object, and from there, use the DataFlavor object to verify that the object can be dropped. You then use the drop event to get the target component and update the property with the dropped object.

33.8.1 How to Add Drag and Drop Functionality for a DVT Graph

To add drag and drop functionality, first add source and target tags to the graph. Then implement the event handler method that will handle the logic for the drag and drop action. For information about what happens at runtime, see Section 33.3.2, "What Happens at Runtime."

Before you begin:

It may be helpful to have an understanding of drag and drop functionality. For more information, see Section 33.8, "Adding Drag and Drop Functionality for DVT Graphs."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 33.1.1, "Additional Functionality for Drag and Drop."

To add drag and drop functionality:

  1. In the Component Palette, from the Operations panel, drag a Drop Target tag and drop it as a child to the graph component.

  2. In the Insert Drop Target dialog, enter an expression that evaluates to a method on a managed bean that will handle the event (you will create this code in Step 6).

  3. In the Insert Data Flavor dialog, enter oracle.adf.view.faces.bi.component.graph.GraphSelection, which is the class for the object that can be dropped onto the target. This entry will be used to create a dataFlavor tag, which determines the type of object that can be dropped onto the target.

  4. In the Property Inspector, set a value for Discriminant, if needed. A discriminant is an arbitrary string used to determine which source can drop on the target. For example, suppose you have two graphs that both accept an GraphSelection object, GraphA and GraphB. You also have two sources, both of which are GraphSelection objects. By setting a discriminant value on GraphA with a value of alpha, only the GraphSelection source that provides the discriminant value of alpha will be accepted.

  5. In the Structure window, select the dropTarget tag. In the Property inspector, select MOVE as the value for Actions.

  6. In the Component Palette, from the Operations panel, drag and drop a Drag Source as a child to the graph component.

  7. With the dragSource tag selected, in the Property Inspector set MOVE as the allowed Action and add any needed discriminant, as configured for the dataFlavor tag.

  8. In the managed bean referenced in the EL expression created in Step 2, create the event handler method (using the same name as in the EL expression) that will handle the drag and drop functionality.

    This method must take a DropEvent event as a parameter and return a DnDAction object, which is the action that will be performed when the source is dropped, in this case DnDAction.MOVE. This method should check the DropEvent event to determine whether or not it will accept the drop. If the method accepts the drop, it should perform the drop and return the DnDAction object it performed. Otherwise, it should return DnDAction.NONE to indicate that the drop was rejected. The method must also check for the presence of the dataFlavor object, in this case oracle.adf.view.faces.bi.component.graph.GraphSelection.

33.9 Adding Drag and Drop Functionality for DVT Gantt Charts

When you want users to be able to drag and drop between Gantt charts and other components, you use the dragSource and dropTarget tags. Additionally, you use the DataFlavor object to determine the valid Java types of sources for the drop target. You also must implement any required functionality in response to the drag and drop action. Both the projectGantt and schedulingGantt components support drag and drop functionality.

For example, suppose you have an projectGantt component and you want the user to be able to drag one timeline to a treeTable component and have that component display information about the timeline, as shown in Figure 33-6.

Figure 33-6 Dragging and Dropping an Object

Drag and drop an object

The projectGantt component contains a dragSource tag. And because the user will drag the whole object and not just the String value of the output text that is displayed, you use the dropTarget tag instead of the attributeDropTarget tag.

You also use a dataFlavor tag to determine the type of object being dropped. On this tag, you can define a discriminant value. This is helpful if you have two targets and two sources, all with the same object type. By creating a discriminant value, you can be sure that each target will accept only valid sources. For example, suppose you have two targets that both accept an TaskDragInfo object, TargetA and TargetB. Suppose you also have two sources, both of which are TaskDragInfo objects. By setting a discriminant value on TargetA with a value of alpha, only the TaskDragInfo source that provides the discriminant value of alpha will be accepted.

You also must implement a listener for the drop event. The object of the drop event is called the transferable, which contains the payload of the drop. Your listener must access the transferable object, and from there, use the DataFlavor object to verify that the object can be dropped. You then use the drop event to get the target component and update the property with the dropped object.

33.9.1 How to Add Drag and Drop Functionality for a DVT Component

To add drag and drop functionality, first add tags to a component that define it as a target for a drag and drop action. Then implement the event handler method that will handle the logic for the drag and drop action. Last, you define the sources for the drag and drop. For information about what happens at runtime, see Section 33.3.2, "What Happens at Runtime." For information about using the clientDropListener attribute, see Section 33.3.3, "What You May Need to Know About Using the ClientDropListener."

Before you begin:

It may be helpful to have an understanding of drag and drop functionality. For more information, see Section 33.9, "Adding Drag and Drop Functionality for DVT Gantt Charts."

You may also find it helpful to understand functionality that can be added using other ADF Faces features. For more information, see Section 33.1.1, "Additional Functionality for Drag and Drop."

To add drag and drop functionality:

  1. In the Component Palette, from the Operations panel, drag a Drop Target tag and drop it as a child to the target component.

  2. In the Insert Drop Target dialog, enter an expression that evaluates to a method on a managed bean that will handle the event (you will create this code in Step 6).

    Tip:

    You can also intercept the drop on the client by populating the clientDropListener attribute. For more information, see Section 33.3.3, "What You May Need to Know About Using the ClientDropListener".
  3. In the Insert Data Flavor dialog, enter the class for the object that can be dropped onto the target, for example java.lang.Object. This selection will be used to create a dataFlavor tag, which determines the type of object that can be dropped onto the target. Multiple dataFlavor tags are allowed under a single drop target to allow the drop target to accept any of those types.

    Tip:

    To specify a typed array in a DataFlavor tag, add brackets ([]) to the class name, for example, java.lang.Object[].
  4. In the Property Inspector, set a value for Discriminant, if needed. A discriminant is an arbitrary string used to determine what sources of the type specified by the dataFlavor will be allowed as a source.

  5. In the Structure window, select the dropTarget tag. In the Property inspector, select a value for Actions. This defines what actions are supported by the drop target. Valid values can be COPY (copy and paste), MOVE (cut and paste), and LINK (copy and paste as a link), for example:.

    MOVE COPY
    

    If no actions are specified, the default is COPY.

    Example 33-10 shows the code for a dropTarget component that takes a TaskDragInfo object as a drop source. Note that because COPY was set as the value for the actions attribute, that will be the only allowed action.

    Example 33-10 JSP Code for a dropTarget tag

    <af:treeTable id="treeTableDropTarget"
                  var="task" value="#{projectGanttDragSource.treeTableModel}">
      <f:facet name="nodeStamp">
        <af:column headerText="Task Name">
          <af:outputText value="#{task.taskName}"/>
        </af:column>
      </f:facet>
      <af:column headerText="Resource">
        <af:outputText value="#{task.resourceName}"/>
      </af:column>
      <af:column headerText="Start Date">
        <af:outputText value="#{task.startTime}"/>
      </af:column>
      <af:column headerText="End Date">
        <af:outputText value="#{task.endTime}"/>
      </af:column>
      <af:dropTarget actions="COPY"
                     dropListener="#{projectGanttDragSource.onTableDrop}">
        <af:dataFlavor flavorClass=                "oracle.adf.view.faces.bi.component.gantt.TaskDragInfo"/>
      </af:dropTarget>
    </af:treeTable>
    
  6. In the managed bean referenced in the EL expression created in Step 2, create the event handler method (using the same name as in the EL expression) that will handle the drag and drop functionality.

    This method must take a DropEvent event as a parameter and return a DnDAction object, which is the action that will be performed when the source is dropped. Valid return values are DnDAction.COPY, DnDAction.MOVE, and DnDAction.LINK, and were set when you defined the target attribute in Step 5. This method should check the DropEvent event to determine whether or not it will accept the drop. If the method accepts the drop, it should perform the drop and return the DnDAction object it performed. Otherwise, it should return DnDAction.NONE to indicate that the drop was rejected.

    The method must also check for the presence for each dataFlavor object in preference order.

    Tip:

    If your target has more than one defined dataFlavor object, then you can use the Transferable.getSuitableTransferData() method, which returns a List of TransferData objects available in the Transferable object in order, from highest suitability to lowest.

    The DataFlavor object defines the type of data being dropped, for example java.lang.Object, and must be as defined in the DataFlavor tag on the JSP, as created in Step 3.

    Tip:

    To specify a typed array in a DataFlavor object, add brackets ([]) to the class name, for example, java.lang.Object[].

    DataFlavor objects support polymorphism so that if the drop target accepts java.util.List, and the transferable object contains a java.util.ArrayList, the drop will succeed. Likewise, this functionality supports automatic conversion between Arrays and Lists.

    If the drag and drop framework doesn't know how to represent a server DataFlavor object on the client component, the drop target will be configured to allow all drops to succeed on the client.

    Example 33-11 shows a handler method that copies a TaskDragInfo object from the event payload and assigns it to the component that initiated the event.

    Example 33-11 Event Handler Code for a dropListener

    public DnDAction onTableDrop(DropEvent evt)
    { 
      // retrieve the information about the task dragged
      DataFlavor<TaskDragInfo> _flv = DataFlavor.getDataFlavor(TaskDragInfo.class, null);
      Transferable _transferable = evt.getTransferable();
     
      // if there is no data in the transferable, then the drop is unsuccessful 
      TaskDragInfo _info = _transferable.getData(_flv);
      if (_info == null)
        return DnDAction.NONE;
     
      // find the task
      Task _draggedTask = findTask(_info.getTaskId());
      if (_draggedTask != null) {
      // process the dragged task here and indicate the drop is successful by returning DnDAction.COPY
       return DnDAction.COPY;
      }
      else
    return DnDAction.NONE;
    }
    
  7. In the Component Palette, from the Operations panel, drag and drop a Drag Source as a child to the source component.

  8. With the dragSource tag selected, in the Property Inspector set the allowed Actions and any needed discriminant, as configured for the target.