16.4. Drag and Drop with EditorsEach Workbench window has an editor area that is optionally visible. When the editor area is visible, it can be used as a target for drag and drop operations. For example, this is used by the IDE to open an editor on a file dropped on the editor area. This is possible even if the editor area is blank. Drag and drop on the editor area is set up using the IWorkbenchWindowConfigurer for a particular window. To show how this works, let's enhance Hyperbola to allow dragging contacts from the Contacts view into the editor area to initiate a chat. There are four main parts involved in making this happen:
The next sections step through the code needed for each of these four parts. The transfer type for dragging editor inputs from one part to another is already defined in the Workbench and is called EditorInputTransfer. This is the class that serializes the editor inputs into a byte array that is then added to the drag and drop events. The transfer is added to the Workbench window by calling the IWorkbenchWindowConfigurer method addEditorAreaTransfer(Transfer) from the WorkbenchAdvisor, as shown below. org.eclipsercp.hyperbola/ApplicationWorkbenchWindowAdvisor public void preWindowOpen(IWorkbenchWindowConfigurer configurer) { ... configurer.addEditorAreaTransfer(EditorInputTransfer.getInstance()); configurer.configureEditorAreaDropListener( new EditorAreaDropAdapter (configurer.getWindow()); } Notice that this also configures a DropTargetListener to listen for drops in the editor area. The drop adapter registered is Hyperbola's EditorAreaDropAdapter shown in the following. It processes the drop event and opens an editor if the transfer type is an editor input. The adapter can open multiple editors if the transfer contains an array of editor inputs. You can extend its behavior to accept application-specific objects as well. The editor area for each window can be individually configured and reconfigured with additional editor area transfers and drop listeners at any time. org.eclipsercp.hyperbola/EditorAreaDropAdapter public class EditorAreaDropAdapter extends DropTargetAdapter { public void handleDrop(IWorkbenchPage page, DropTargetEvent event) { if (EditorInputTransfer.getInstance(). isSupportedType(event.currentDataType)) { EditorInputTransfer.EditorInputData[] editorInputs = (EditorInputTransfer.EditorInputData []) event.data; for (int i = 0; i < editorInputs.length; i++) { IEditorInput editorInput = editorInputs[i].input; String editorId = editorInputs[i].editorId; openEditor(page, editorInput, editorId); } } ... } } Once the editor area is configured to accept drop requests, the next step is to enable dragging from the Contacts view. Add the following method to the ContactsView and call it from createPartControl(): org.eclipsercp.hyperbola/ContactsView protected void initDragAndDrop(final StructuredViewer viewer) { int operations = DND.DROP_COPY; Transfer[] transferTypes = new Transfer[]{EditorInputTransfer.getInstance()}; DragSourceListener listener = new DragSourceAdapter() { public void dragSetData(DragSourceEvent event) { if (EditorInputTransfer.getInstance().isSupportedType(event.dataType)) { String[] names = getNames(); EditorInputTransfer.EditorInputData[] inputs = new EditorInputTransfer.EditorInputData[names.length]; if (names.length > 0) { for (int i = 0; i < names.length; i++) inputs[i] = EditorInputTransfer.createEditorInputData( ChatEditor.ID, new ChatEditorInput(getSession(), names[i])); event.data = inputs; return; } } event.doit = false; } public void dragFinished(DragSourceEvent event) {} public void dragStart(DragSourceEvent event) { super.dragStart(event); } }; viewer.addDragSupport(operations, transferTypes, listener); } The method adds drag and drop support to the ContactsView's treeViewer. When a drag is started, the listener initializes the event by creating an editor input for each of the contacts selected in the viewer. The selection is obtained using getNames(). If the event does not support EditorInputTransfers, then the drag is cancelled by setting event.doit to false. The last step is to modify ChatEditorInput to implement IPersistableElement. The IPersistableElement allows the input to be serialized during a drag and drop. Drag and drop transfers are always serialized, even when the drop occurs inside the application. This requires two changes; the first is to implement saveState(IMemento) and getFactoryId(). The next is to implement a factory that can deserialize the chat editor inputs. Since the chat editor input is simple, all it takes to serialize the input is to remember the user name. The factory can create a new input using the name. org.eclipsercp.hyperbola/ChatEditorInput
public class ChatEditorInput implements IEditorInput, IPersistableElement
{
public String getFactoryId() {
return ChatEditorInputFactory.ID;
}
public void saveState(IMemento memento) {
memento.putString(KEY_NAME, getParticipant());
}
...
}
public class ChatEditorInputFactory implements IElementFactory {
public static final String ID = "org.eclipsercp.hyperbola.chatinput";
public IAdaptable createElement(IMemento memento) {
String name = memento.getString(ChatEditorInput.KEY_NAME);
if (name != null)
return new ChatEditorInput(Session.getInstance(), name);
return null;
}
}With these changes Hyperbola is drag and drop enabled. We only set up the Contacts view to initiate drags, but it's easy to see how other views could be similarly set up. If you want to learn more about drag and drop, read the following articles:
|