|  | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head> | 
|  | <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | 
|  | <title>Drag and Drop in the Eclipse UI</title> | 
|  | <meta name="Author" content="John Arthorne"> | 
|  | <link rel="stylesheet" href="../default_style.css"></head> | 
|  |  | 
|  | <body link="#0000ff" vlink="#800080" bgcolor="#ffffff"> | 
|  |  | 
|  | <div align="right"><font size="-2">Copyright © 2003 International Business Machines Corp.</font> | 
|  | <table border="0" cellspacing="0" cellpadding="2" width="100%"> | 
|  | <tbody> | 
|  | <tr> | 
|  | <td align="left" valign="top" colspan="2" bgcolor="#0080c0"><b> | 
|  | <font face="Arial,Helvetica" color="#ffffff"> Eclipse Corner Article</font></b></td> | 
|  | </tr> | 
|  | </tbody> | 
|  | </table> | 
|  | </div> | 
|  |  | 
|  | <div align="left"> | 
|  | <h1><img src="images/Idea.jpg" height="86" width="120" align="middle"> | 
|  | </h1> | 
|  | </div> | 
|  |  | 
|  | <p> </p> | 
|  |  | 
|  | <h1 align="center">Drag and Drop in the Eclipse UI</h1> | 
|  |  | 
|  | <blockquote> <b>Summary</b>  <br> | 
|  | In this article, we discuss the drag and drop facilities provided by JFace and | 
|  | the Eclipse platform UI. After reading this, you will know how to add drag and | 
|  | drop support to your own Eclipse views, and how that support will interact with | 
|  | the standard views in the Eclipse platform. Along the way, we'll also discuss | 
|  | that keyboard relative of drag and drop: cut and paste. You'll learn that putting | 
|  | your own custom objects on the clipboard is easy once you've figured out the | 
|  | basics of drag and drop. This article is intended to be read as a companion | 
|  | to the <a href="../Article-SWT-DND/DND-in-SWT.html">SWT | 
|  | drag and drop article</a>.<br> | 
|  | <p><b> By John Arthorne, IBM OTI Labs</b><br> | 
|  | <font size="-1">August 25, 2003</font></p> | 
|  | </blockquote> | 
|  |  | 
|  | <hr width="100%">  <a name="1"> </a> | 
|  | <h2> | 
|  | Doing the drag and drop</h2> | 
|  |  | 
|  | <div align="right"><a name="1"><i>Never keep up with the Joneses. Drag them down to your level.</i> <br> | 
|  |  Quentin Crisp</a></div> | 
|  |  | 
|  | <p>In keeping with the general philosophy of JFace, the JFace drag and drop | 
|  | adds a layer of functionality on top of the SWT drag and drop support.  This layer | 
|  | allows the developer to deal directly with domain objects (such as resources, | 
|  | tasks, etc), without having to worry too much about the underlying window | 
|  | controls.  Rather than concealing or replacing the drag and drop support in SWT, | 
|  | the JFace drag and drop support works as an extension to the same concepts | 
|  | found in SWT drag and drop. | 
|  | </p> | 
|  | <h3>Transfer types</h3> | 
|  | As you'll know from the <a href="../Article-SWT-DND/DND-in-SWT.html">SWT drag and drop article</a>, | 
|  | the notion of transfer types is central to the drag and drop support in Eclipse-based UIs. | 
|  | To recap, transfer types allow drag sources to specify what kinds of object they allow to be | 
|  | dragged out of their widget, and they allow drop targets to specify what kinds of | 
|  | objects they are willing to receive.  For each transfer type, there is a subclass of | 
|  | <code>org.eclipse.swt.dnd.Transfer</code>.  These subclasses implement the marshaling | 
|  | behavior that converts between objects and bytes, allowing drag and drop | 
|  | transfers between applications. The following table summarizes the transfer types | 
|  | provided by the basic Eclipse platform, along with the object they are capable of transferring: | 
|  | </p> | 
|  | <p> | 
|  | <table BORDER COLS=2 WIDTH="90%" > | 
|  | <tr> | 
|  | <td><b>Transfer class</b></td> | 
|  | <td><b>Object it transfers</b></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td><code>org.eclipse.swt.dnd.FileTransfer</code></td> | 
|  | <td><code>java.lang.String[]</code> (list of absolute file paths)</td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td><code>org.eclipse.swt.dnd.RTFTransfer</code></td> | 
|  | <td><code>java.lang.String</code> (may contain RTF formatting characters)</td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td><code>org.eclipse.swt.dnd.TextTransfer</code></td> | 
|  | <td><code>java.lang.String</code></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td><code>org.eclipse.ui.part.MarkerTransfer</code></td> | 
|  | <td><code>org.eclipse.core.resources.IMarker[]</code></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td><code>org.eclipse.ui.part.ResourceTransfer</code></td> | 
|  | <td><code>org.eclipse.core.resources.IResource[]</code></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td><code>org.eclipse.ui.part.EditorInputTransfer</code></td> | 
|  | <td><code>org.eclipse.ui.part.EditorInputTransfer.EditorInputData[]</code></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td><code>org.eclipse.ui.part.PluginTransfer</code></td> | 
|  | <td><code>org.eclipse.ui.part.PluginTransferData</code></td> | 
|  | </tr> | 
|  | </table> | 
|  | </p> | 
|  | <p> | 
|  | The set of transfer types is open ended, because third party | 
|  | tool writers can implement their own transfer types for their domain objects. | 
|  | To implement your own transfer type, it is recommended that you subclass | 
|  | <code>org.eclipse.swt.dnd.ByteArrayTransfer</code>. | 
|  | See the <a href="../Article-SWT-DND/DND-in-SWT.html">SWT drag and drop article</a> for more information | 
|  | on defining your own transfer types. | 
|  | </p> | 
|  | <p> | 
|  | <p><img src="images/tip.gif"> | 
|  | An important point about transfer types is that they don't necessarily need to store | 
|  | the entire object as serialized bytes.  In most cases it is simpler and more | 
|  | efficient to just store enough information about where the object is found.  For | 
|  | example, <code>FileTransfer</code> simply encodes a string which represents the | 
|  | absolute path of the file in the file system.  It does not store the entire file in the | 
|  | transfer object. | 
|  | </p> | 
|  | <h3>Transfer types supported by the standard views</h3> | 
|  | <p> | 
|  | Many of the basic views you see in Eclipse already support various | 
|  | transfer types. It is important to understand what transfer types are supported by | 
|  | each view, because this dictates how the drag and drop support in your view will | 
|  | interact with other basic views found in the Eclipse platform UI. | 
|  | </p> | 
|  | <p> | 
|  | The Navigator view supports dragging and dropping files (<code>FileTransfer</code>), | 
|  | and resources (<code>ResourceTransfer</code>). For example, you can drag a file | 
|  | from the Navigator view into Windows Explorer or the Windows Desktop. Similarly, | 
|  | you can import resources into Eclipse simply by dragging them from Windows into | 
|  | the Navigator view of your workbench. You can also drag files between two instances | 
|  | of Eclipse, or drag within a single Navigator to copy and move files within | 
|  | your workspace.  If your view supports either <code>FileTransfer</code> or | 
|  | <code>ResourceTransfer</code>, then users will be able to transfer resources between | 
|  | your view and the Navigator view. | 
|  | </p> | 
|  | <p> | 
|  | The Tasks and Bookmarks views support dragging of markers (<code>MarkerTransfer</code>). | 
|  | Dragging a selection of tasks from the Tasks view into an application such as MS | 
|  | Word will generate a textual marker report (<code>TextTransfer</code>). You can also drag markers | 
|  | out of the Tasks and Bookmarks views into other parts of the workbench, such as | 
|  | the editor area. Dragging a marker to the editor area will open the associated | 
|  | resource in the editor and jump to that marker location in the editor. | 
|  | </p> | 
|  | <p> | 
|  | Finally, the editor area supports dropping of editor inputs (<code>EditorInputTransfer</code>), | 
|  | resources, or markers.  Dragging these objects to the editor will cause it to locate and | 
|  | open an appropriate editor for the given resource, editor input or marker.  In the case | 
|  | of markers, it will also jump to that marker location in the editor. | 
|  | </p> | 
|  | <h3>A running example: go go gadgets!</h3> | 
|  | <div align="right"><a name="1"><i>"Gosh, Scotland is beautiful, Uncle Gadget."<br> | 
|  | "It certainly is, Penny. This is where they make Scotch tape, ya know."</i> <br> | 
|  |  Inspector Gadget</a></div> | 
|  |  | 
|  | <p> | 
|  | For the remainder of this article, we'll make use of a running example.  This example | 
|  | is an Eclipse plug-in for manipulating a simple object model of <i>gadgets</i>.  Gadgets | 
|  | are simply named objects that can be formed into trees.  Each gadget knows its parent | 
|  | and its children.  The example includes two views, one containing a table viewer, and | 
|  | the other containing a tree viewer.  Drag and drop can be used to copy or move | 
|  | gadgets between these views, and to rearrange the order or hierarchy of gadgets | 
|  | within a view.  There is a <code>GadgetTransfer</code> class for encoding an array | 
|  | of gadgets to and from a byte array.  Complete source code for the example is found | 
|  | <a href="gadgetsrc.zip">here</a>. | 
|  | </p> | 
|  | <h3>Adding JFace viewer drag support</h3> | 
|  | Adding drag support to a viewer means that it enables the user to select | 
|  | any item in the viewer with the mouse, and drag it into another viewer | 
|  | or another application. Drag support can be added to any subclass of | 
|  | <code>org.eclipse.jface.viewers.StructuredViewer</code> | 
|  | using the <code>addDragSupport(int, Transfer[], DragSourceListener)</code> | 
|  | method. From our gadget example, here is the code for associating a drag listener | 
|  | with a tree viewer: | 
|  | </p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | TreeViewer gadgetViewer = new TreeViewer(...); | 
|  | int ops = DND.DROP_COPY | DND.DROP_MOVE; | 
|  | Transfer[] transfers = new Transfer[] { GadgetTransfer.getInstance()}; | 
|  | viewer.addDragSupport(ops, transfers, new GadgetDragListener(viewer)); | 
|  | </pre> | 
|  | </font> | 
|  | <br> | 
|  | <p> | 
|  | <code>GadgetDragListener</code> is an implementation of the SWT interface | 
|  | <code>org.eclipse.swt.dnd.DragSourceListener</code>.  There is nothing specific | 
|  | to JFace about the implementation of <code>DragSourceListener</code>, so you | 
|  | can learn more about its implementation in the <a href="../Article-SWT-DND/DND-in-SWT.html">SWT drag and drop article</a>. | 
|  | </p> | 
|  |  | 
|  | <h3>Adding viewer drop support</h3> | 
|  | <p> | 
|  | Drop support can be added to viewers using the <code>StructuredViewer.addDropSupport(int, | 
|  | Transfer[], DropTargetListener)</code> method. This allows your viewer to | 
|  | be the target of a drop operation. The code for adding drop support is almost the | 
|  | same as for adding drag support: | 
|  | </p> | 
|  | <p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | TreeViewer gadgetViewer = new TreeViewer(...); | 
|  | int ops = DND.DROP_COPY | DND.DROP_MOVE; | 
|  | Transfer[] transfers = new Transfer[] { GadgetTransfer.getInstance()}; | 
|  | viewer.addDropSupport(ops, transfers, new GadgetTreeDropAdapter(viewer)); | 
|  | </pre> | 
|  | </font> | 
|  | </p> | 
|  | <p> | 
|  | JFace provides a standard implementation of <code>DropTargetListener</code> | 
|  | called <code>org.eclipse.jface.viewers.ViewerDropAdapter</code>. | 
|  | This adapter makes it easy to add drop support for simple cases.  If you have more | 
|  | complex requirements, you can always override the SWT <code>DropTargetListener</code> | 
|  | interface directly for ultimate flexibility. | 
|  | When sub-classing <code>ViewerDropAdapter</code>, simply implement its two | 
|  | abstract methods: <code>validateDrop(Object target, int operation, TransferData transferType)</code>, | 
|  | and <code>performDrop(Object data)</code>. | 
|  | </p> | 
|  | <p> | 
|  | <code>validateDrop</code> is called whenever the user moves over a new item | 
|  | in your viewer, or changes the drop type with one of the modifier keys. | 
|  | The method provides the current drop target, operation, and transfer type. | 
|  | The return value of this method indicates whether a drop at the current location is | 
|  | valid or not. A return value of false will change the drag icon to indicate | 
|  | to the user that it is illegal to drop what they are dragging at the current | 
|  | location.  In our gadget example, it is always legal to drop a gadget, so the | 
|  | <code>validateDrop</code> implementation simply looks like this: | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | public boolean validateDrop(Object target, int op, TransferData type) { | 
|  | return GadgetTransfer.getInstance().isSupportedType(type); | 
|  | } | 
|  | </pre> | 
|  | </font> | 
|  | <p> | 
|  | This code just makes sure that the user is indeed dropping a gadget, and not | 
|  | some other object such as a resource or marker. If you have more complex | 
|  | validation requirements based on the target object, you can do that here.  For example, | 
|  | in a file navigator, you may want to allow dropping on top of directories, but not on top of | 
|  | files. | 
|  | </p> | 
|  | <p> | 
|  | <code>performDrop</code> is called when the user lets go of the mouse button, | 
|  | indicating that they want the drop to occur. Your implementation should | 
|  | accordingly perform the expected behavior for that drop. Context for the | 
|  | drop is provided by the methods <code>getCurrentTarget</code>, <code>getCurrentOperation</code>, | 
|  | and <code>getCurrentLocation</code> on <code>ViewerDropAdapter</code>. Most | 
|  | importantly, at the time when <code>performDrop </code>is called, <code>getCurrentTarget</code> | 
|  | will provide the object in your viewer that is currently under the mouse.  Here is the | 
|  | <code>performDrop</code> method from our gadget example: | 
|  | </p> | 
|  | <p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | public boolean performDrop(Object data) { | 
|  | 1     Gadget target = (Gadget)getCurrentTarget(); | 
|  | 2     if (target == null) | 
|  | 3        target = (Gadget)getViewer().getInput(); | 
|  | 4     Gadget[] toDrop = (Gadget[])data; | 
|  | 5     TreeViewer viewer = (TreeViewer)getViewer(); | 
|  | 6     //cannot drop a gadget onto itself or a child | 
|  | 7     for (int i = 0; i < toDrop.length; i++) | 
|  | 8        if (toDrop[i].equals(target) || target.hasParent(toDrop[i])) | 
|  | 9           return false; | 
|  | 10    for (int i = 0; i < toDrop.length; i++) { | 
|  | 11       toDrop[i].setParent(target); | 
|  | 12       viewer.add(target, toDrop[i]); | 
|  | 13       viewer.reveal(toDrop[i]); | 
|  | 14    } | 
|  | 15    return true; | 
|  | } | 
|  | </pre> | 
|  | </font> | 
|  | </p> | 
|  | <p> | 
|  | In lines 1-3, it is determining what the target gadget is.  The target is the item that | 
|  | is currently under the mouse when the drop occurs.  If there is no item under the mouse, it | 
|  | takes the viewer's input element as the target.  On lines 7-9, it is making sure | 
|  | that the user is not dropping an item onto itself, or onto a child of itself.  You may | 
|  | be wondering why this validation was not done in the <code>validateDrop</code> | 
|  | method.  In SWT, the transfer of data from the source to the target is done lazily | 
|  | when the drop is initiated.  So, as the user is dragging, the destination has no | 
|  | way of finding out what source object is being dragged until the drop is performed. | 
|  | Returning <code>false</code> from the <code>performDrop</code> method will | 
|  | cancel the drop.  On lines 10-13, it is performing the actual drop.  This involves updating | 
|  | the gadget with its new parent (line 11), and then adding and revealing the new item | 
|  | in the viewer (lines 12-13).  Finally, the method returns true on line 15 to indicate | 
|  | that the drop was successful. | 
|  | </p> | 
|  | <p> | 
|  | <code>ViewerDropAdapter</code> has two more interesting methods for controlling | 
|  | drag feedback effects. The method <code>setFeedbackEnabled</code> is used to turn | 
|  | insertion feedback on or off.  If insertion feedback is on, the cursor will change when | 
|  | the mouse is hovering between two items to indicate where the insertion will occur. | 
|  | Using this effect, you can allow the user to sort items in a tree using drag and drop. | 
|  | In your drop adapter, use the method <code>getCurrentLocation</code> to determine | 
|  | if the cursor is currently directly on, before, or after the current target object.  Here | 
|  | is how the gadget drop example can be updated to make use of this location | 
|  | information: | 
|  | <p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | public boolean performDrop(Object data) { | 
|  | //set the target gadget according to current cursor location | 
|  | Gadget target = (Gadget)getCurrentTarget(); | 
|  | if (target != null) { | 
|  | int loc = getCurrentLocation(); | 
|  | if (loc == LOCATION_BEFORE || loc == LOCATION_AFTER) | 
|  | target = target.getParent(); | 
|  | } | 
|  | if (target == null) | 
|  | target = (Gadget)getViewer().getInput(); | 
|  | Gadget[] toDrop = (Gadget[])data; | 
|  | TreeViewer viewer = (TreeViewer)getViewer(); | 
|  | // ... remainder of method is the same as previous example ... | 
|  | </pre> | 
|  | </font> | 
|  | </p> | 
|  | <p> | 
|  | In this snippet, it looks at the cursor location to see if it is before or after an | 
|  | item in the tree.  When a gadget is dropped between other gadgets, it sets the | 
|  | parent to be the parent of the neighboring gadget.  Said another way, the | 
|  | dropped gadget will become a sibling of the gadget it is dropped next to. | 
|  | </p> | 
|  | <p> | 
|  | The method <code>ViewerDropAdapter.setScrollExpandEnabled</code> is used to | 
|  | turn scroll and expansion effects on or off.  When this is turned on, hovering | 
|  | near the bottom of a tree or table will cause the widget to automatically scroll in | 
|  | that direction.  Hovering over a collapsed tree item for a sufficient amount of time | 
|  | will cause the item to be expanded.  In most cases you should leave these effects | 
|  | on, otherwise users will not able to use drag and drop effectively when your tree | 
|  | or table contains many items. | 
|  | </p> | 
|  |  | 
|  | <h3>Plugin drop handling</h3> | 
|  | <div align="right"><a name="1"><i>When I can't handle events, I let them handle themselves.</i> <br> | 
|  |  Henry Ford</a></div> | 
|  | <p> | 
|  | Due to the UI layering imposed by the plug-in mechanism, viewers are often | 
|  | not aware of the content and nature of other viewers. This can make drag | 
|  | and drop operations between plug-ins difficult. For example, our gadget | 
|  | plug-in may want to allow the user to drop gadget objects into the Navigator | 
|  | view.  Since the Navigator view doesn't know anything about gadget objects | 
|  | (the Navigator only displays <code>org.eclipse.core.resources.IResource</code> | 
|  | objects), it would not be able to support this.  Similarly, another plug-in may want | 
|  | to drop some other kind of objects into the views from the gadget example. | 
|  | To address this problem, a plug-in drop support mechanism | 
|  | is provided by the workbench. This mechanism essentially delegates the | 
|  | drop behavior back to the originator of the drag operation. In the gadget example, | 
|  | we use this extension point to drop gadgets into the Navigator view, and create | 
|  | files containing descriptions of the gadgets that were dropped. Here are the | 
|  | steps required to add drag and drop behavior using this mechanism: | 
|  | <p> | 
|  | Step 1) In your plugin.xml, define an extension on the "org.eclipse.ui.dropActions" | 
|  | extension point. Here is an example XML declaration: | 
|  | <p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | <extension | 
|  | id="gadgetDrop" | 
|  | name="Gadget Resource Drop" | 
|  | point="org.eclipse.ui.dropActions"> | 
|  | <action | 
|  | class="org.eclipse.ui.examples.gdt.dnd.GadgetPluginDropAdapter" | 
|  | id="org.eclipse.ui.examples.gdt.gadgetDrop"> | 
|  | </action> | 
|  | </extension> | 
|  | </pre> | 
|  | </font> | 
|  | </p> | 
|  | <p> | 
|  | Step 2) Implement the code that will perform the drop.  This work is done by | 
|  | the class defined in the extension markup above, which must implement | 
|  | <code>org.eclipse.ui.part.IDropActionDelegate</code>. | 
|  | This interface defines a single run() method that gets called when the | 
|  | drop occurs.  The run method is supplied with the object being dragged, as well as the | 
|  | object under the cursor when the drop occurs.  Here is an example implementation of | 
|  | the drop delegate from the gadget example: | 
|  | </p> | 
|  | <p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | public boolean run(Object source, Object target) { | 
|  | 1     if (target instanceof IContainer) { | 
|  | 2        GadgetTransfer transfer = GadgetTransfer.getInstance(); | 
|  | 3        Gadget[] gadgets = transfer.fromByteArray((byte[])source); | 
|  | 4        IContainer parent = (IContainer)target; | 
|  | 5        for (int i = 0; i < gadgets.length; i++) { | 
|  | 6           writeGadgetFile(parent, gadgets[i]); | 
|  | 7        } | 
|  | 8        return true; | 
|  | 9     } | 
|  | 10    //drop was not successful so return false | 
|  | 11    return false; | 
|  | } | 
|  | </pre> | 
|  | </font> | 
|  | </p> | 
|  | <p> | 
|  | On line 1, it ensures that the gadget is being dropped on some kind of container. | 
|  | In practice, your drop delegate may support being dropped on several different | 
|  | types of objects, with different behavior for each type.  On lines 2-3, it makes use | 
|  | of a convenience method to extract the transferred gadgets from the byte array in the | 
|  | transfer data. Since the plug-in transfer data contains a byte array, this is the exact | 
|  | same code that typically exists in your custom <code>Transfer</code> subclass. | 
|  | It then iterates over the transferred gadgets, and creates a file in the target container | 
|  | for that gadget.  Finally, it returns true if the drop was successful (line 8), or false if the drop | 
|  | occurred on a target object that was not supported (line 11). | 
|  | </p> | 
|  |  | 
|  | <p> | 
|  | Step 3) In the viewer that will be the source of the drag and drop, | 
|  | add drag support using the <code>StructuredViewer.addDragSupport()</code> method | 
|  | described earlier. In the array of supported transfer types, include the | 
|  | singleton instance of <code>org.eclipse.ui.part.PluginTransfer</code>. In your | 
|  | implementation of <code>DragSourceListener</code>, the <code>dragSetData</code> | 
|  | method must set the data to be an instance of <code>org.eclipse.ui.part.PluginTransferData</code>. | 
|  | This object consists of the id of your drop action, | 
|  | along with the data being transferred.  Here is the code in the drag listener from the | 
|  | gadget example: | 
|  | </p> | 
|  | <p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | public void dragSetData(DragSourceEvent event) { | 
|  | 1     IStructuredSelection selection = (IStructuredSelection)viewer.getSelection(); | 
|  | 2     Gadget[] gadgets = (Gadget[])selection.toList().toArray(new Gadget[selection.size()]); | 
|  | 3     if (GadgetTransfer.getInstance().isSupportedType(event.dataType)) { | 
|  | 4        event.data = gadgets; | 
|  | 5     } else if (PluginTransfer.getInstance().isSupportedType(event.dataType)) { | 
|  | 6        byte[] data = GadgetTransfer.getInstance().toByteArray(gadgets); | 
|  | 7        event.data = new PluginTransferData("org.eclipse.ui.examples.gdt.gadgetDrop", data); | 
|  | 8     } | 
|  | 9  } | 
|  | } | 
|  | </pre> | 
|  | </font> | 
|  | </p> | 
|  | <p> | 
|  | Lines 1-2 are the familiar code for creating an array of gadgets from the viewer's | 
|  | selection.  Line 4 handles the old case of a gadget transfer by simply setting the | 
|  | event data to be the correct type for <code>GadgetTransfer</code>.  Lines 6-7 | 
|  | are the interesting new code for handling a plug-in drag event.  First, it uses a convenience | 
|  | method on the <code>GadgetTransfer</code> class for converting the array of gadgets | 
|  | into a byte array.  Next, it creates a <code>PluginTransferData</code> object, passing | 
|  | in the id of the plug-in drop action that was declared in the plugin.xml in step 1), along | 
|  | with the serialized gadget array. | 
|  | </p> | 
|  |  | 
|  | <p>Step 4) In the viewer that will receive the drop, the drop listener | 
|  | for that viewer must subclass <code>org.eclipse.ui.part.PluginDropAdapter</code>, | 
|  | which in turn subclasses <code>ViewerDropAdapter</code> as described earlier. | 
|  | Be sure to invoke the super methods for validateDrop and performDrop in | 
|  | cases where your adapter does not understand the transfer type. Following | 
|  | from our earlier example, the viewers declaration would look | 
|  | like this: | 
|  | </p> | 
|  | <p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | TreeViewer gadgetViewer = new TreeViewer(...); | 
|  | int ops = DND.DROP_COPY | DND.DROP_MOVE; | 
|  | Transfer[] transfers = new Transfer[] { | 
|  | GadgetTransfer.getInstance(), PluginTransfer.getInstance()}; | 
|  | viewer.addDropSupport(ops, transfers, new GadgetTreeDropAdapter(viewer)); | 
|  | </pre> | 
|  | </font> | 
|  | </p> | 
|  | <p> | 
|  | The basic Workbench views such as the Navigator view | 
|  | already have this support added. It is recommended that anyone defining | 
|  | their own views should add the plug-in support, in anticipation of future | 
|  | third party plug-ins wanting to drop content into their views. For more information | 
|  | about this advanced drag and drop mechanism, refer to the documentation | 
|  | for the <code>org.eclipse.ui.dropActions</code> extension point. | 
|  | </p> | 
|  | <h2>Cut, copy and paste</h2> | 
|  | <div align="right"><a name="1"><i>"I'll get you next time Gadget... Next time!" </i> <br> | 
|  |  Dr. Claw </a></div> | 
|  | <p> | 
|  | Cut and paste can be thought of as the keyboard equivalent of drag and drop.  Once you've | 
|  | mastered drag and drop support, you'll find that cut and paste is a snap.  Once | 
|  | again, the gadgets example provides a complete implementation of cut and paste | 
|  | support.  Here is code for adding cut and paste support from within an Eclipse view | 
|  | (this code goes in the view's <code>createPartControl</code> method): | 
|  | </p> | 
|  | <p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | public void createPartControl(Composite parent) { | 
|  | viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); | 
|  |  | 
|  | //... initialize viewer's content and label providers ... | 
|  |  | 
|  | clipboard = new Clipboard(getSite().getShell().getDisplay()); | 
|  | IActionBars bars = getViewSite().getActionBars(); | 
|  | bars.setGlobalActionHandler( | 
|  | IWorkbenchActionConstants.CUT, | 
|  | new CutGadgetAction(viewer, clipboard)); | 
|  | bars.setGlobalActionHandler( | 
|  | IWorkbenchActionConstants.COPY, | 
|  | new CopyGadgetAction(viewer, clipboard)); | 
|  | bars.setGlobalActionHandler( | 
|  | IWorkbenchActionConstants.PASTE, | 
|  | new PasteTreeGadgetAction(viewer, clipboard)); | 
|  | } | 
|  | </pre> | 
|  | </font> | 
|  | </p> | 
|  | <p> | 
|  | This code simply creates a new SWT clipboard, and then defines global actions | 
|  | for cut, copy, and paste using that clipboard.  The <code>IActionBars</code> | 
|  | interface is used for hooking into global actions.  <b>Note:</b> SWT clipboard | 
|  | objects are operating system resources that must be disposed when no longer | 
|  | needed.  In the gadget example, we <code>dispose()</code> the clipboard | 
|  | when the view is disposed. Disposing of an SWT clipboard instance does not remove | 
|  | the data from the operating system's clipboard. | 
|  | </p> | 
|  | <p> | 
|  | The actions that are provided as global action handlers should be subclasses of the | 
|  | <code>org.eclipse.jface.action.Action</code> class.  The code for these actions is | 
|  | similar to the drag and drop code, except that they use the clipboard as the transfer | 
|  | mechanism, rather than the drag and drop event handlers.  Here is the code for the | 
|  | run method of the cut action: | 
|  | </p> | 
|  | <p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | public void run() { | 
|  | 1     IStructuredSelection selection = (IStructuredSelection)viewer.getSelection(); | 
|  | 2     Gadget[] gadgets = (Gadget[])selection.toList().toArray(new Gadget[selection.size()]); | 
|  | 3     clipboard.setContents( | 
|  | 4        new Object[] { gadgets }, | 
|  | 5        new Transfer[] { GadgetTransfer.getInstance()}); | 
|  | 6     for (int i = 0; i < gadgets.length; i++) { | 
|  | 7        gadgets[i].setParent(null); | 
|  | 8     } | 
|  | 9     viewer.refresh(); | 
|  | } | 
|  | </pre> | 
|  | </font> | 
|  | </p> | 
|  | <p> | 
|  | On lines 3-5, the gadgets are placed on the clipboard, along with the <code> | 
|  | Transfer</code> object that will be used for serializing them.  Lines 6-8 remove | 
|  | the gadgets from the source view (since they are being cut, not copied), and line 9 | 
|  | refreshes the view to update it with the new contents.  The copy action is almost | 
|  | identical, except lines 6-9 are removed, since we don't want to remove the gadgets | 
|  | from the source view on copy.  The paste action for pasting into a tree looks like this: | 
|  | </p> | 
|  | <p> | 
|  | <font color="#4444cc"> | 
|  | <pre> | 
|  | public void run() { | 
|  | 1     IStructuredSelection sel = (IStructuredSelection)viewer.getSelection(); | 
|  | 2     Gadget parent = (Gadget)sel.getFirstElement(); | 
|  | 3     if (parent == null) | 
|  | 4        parent = (Gadget)viewer.getInput(); | 
|  | 5     Gadget[] gadgets = (Gadget[])clipboard.getContents(GadgetTransfer.getInstance()); | 
|  | 6     if (gadgets == null) | 
|  | 7        return; | 
|  | 8     //cannot drop a gadget onto itself or a child | 
|  | 9     for (int i = 0; i < gadgets.length; i++) | 
|  | 10       if (gadgets[i].equals(parent) || parent.hasParent(gadgets[i])) | 
|  | 11          return; | 
|  | 12    for (int i = 0; i < gadgets.length; i++) { | 
|  | 13       gadgets[i].setParent(parent); | 
|  | 14    } | 
|  | 15    viewer.refresh(); | 
|  | } | 
|  | </pre> | 
|  | </font> | 
|  | </p> | 
|  | <p> | 
|  | Lines 1-4 compute the parent gadget for the gadgets that are about to be pasted. | 
|  | If there is a gadget currently selected, it will become the new parent, otherwise the root | 
|  | gadget is used.  Line 5 is the crucial step that takes the gadget objects off the clipboard. | 
|  | You should always check that the returned value is not null, since there may not be | 
|  | an object of the requested type on the clipboard.  Lines 9-15 are the familiar code | 
|  | that we had in the drop event handler, first ensuring that we're not dropping a gadget | 
|  | onto itself or a child of itself, and then setting the parent elements for the dropped | 
|  | gadgets. | 
|  |  | 
|  | <p><img src="images/tip.gif"> | 
|  | In your implementation, you will probably want to factor out the paste and drop | 
|  | code into a common place, since they both do the same thing.  Likewise, the code for | 
|  | the cut action is similar to the code in <code>dragFinished</code> in the drag action | 
|  | handler.  For clarity, the gadget example duplicates the code in both places, but you'll | 
|  | make your code easier to maintain if you keep it all in one place. | 
|  | </p> | 
|  |  | 
|  | <h3>Summary and further information</h3> | 
|  | <p> | 
|  | You now have all the information you need for adding drag/drop and cut/paste support | 
|  | in your own JFace viewers.  You should also know all about the standard transfer types | 
|  | supplied by the platform, and what transfers are supported by the standard views | 
|  | in the platform. | 
|  | </p> | 
|  | <p> | 
|  | For more information, browse through the complete source from the | 
|  | <a href="gadgetsrc.zip">gadgets example</a>.  The UI readme | 
|  | example, available from the eclipse.org | 
|  | <a href="http://www.eclipse.org/downloads/index.php">downloads page</a>, | 
|  | also implements some drag and drop support.  For more in depth examples, you | 
|  | can look at the drag and drop support implemented within the UI plug-in itself. For | 
|  | example, see <code>org.eclipse.ui.views.navigator.ResourceNavigator </code>to | 
|  | see how the Navigator view implements its drag and drop behavior. The Navigator | 
|  | uses two helper classes, <code>NavigatorDragAdapter</code> and | 
|  | <code>NavigatorDropAdapter</code>, which are also instructive to look at. | 
|  | </p> | 
|  | <h3>Acknowledgements</h3> | 
|  | <p> Thanks to Knut Radloff from the Eclipse Platform UI Team and Jim des Rivières | 
|  | at OTI Labs for proof reading and providing feedback for this article. </p> | 
|  | <p><small>Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun | 
|  | Microsystems, Inc. in the United States, other countries, or both.</small></p> | 
|  | </body> | 
|  | </html> |