站内搜索: 请输入搜索关键词
当前页面: 图书首页 > Eclipse Rich Client Platform: Designing, Coding, and Packaging Java Applications

Section 16.4.  Drag and Drop with Editors - Eclipse Rich Client Platform: Designing, Coding, and Packaging Java Applications

Previous Page
Next Page

16.4. Drag and Drop with Editors

Each 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:

  • Decide which transfer types are to be supported by the editor area and implement them. In Hyperbola, the transfer type is an IEditorInput that describes the editor to be opened when the drop completes. Since drag and drop can occur between applications, a transfer type is used to serialize the required information. Even if the drag and drop occurs within the same application, a transfer type is needed.

  • Because editor inputs are serialized when they are transferred in a drag and drop event, the ChatEditorInput must be modified to implement IPersistableElement.

  • Add a drop adapter that knows the actions to take when an IEditorInput transfer type is dropped onto the editor area. Drop adapters are simplethey perform actions based on the transfer type dropped. In the Hyperbola case, the drop adapter opens an editor.

  • Enable the Contacts view to initiate a drag operation. The Contacts view also has to create the editor inputs that are dropped in the editor area.

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:


Previous Page
Next Page