Community
Participate
Working Groups
The following classes are copied or used by several clients (e.g. GEF). They therefore are generally useful and should be considered to be promoted as API at the workbench level. org.eclipse.jdt.internal.ui.dnd.DelegatingDragAdapter org.eclipse.jdt.internal.ui.dnd.LocalSelectionTransfer org.eclipse.jdt.internal.ui.dnd.TransferDragSourceListener org.eclipse.jdt.internal.ui.dnd.TransferDropTargetListener
Nick, do you want these classes?
Deferred to v3.
Reopen to investigate
Several clients within IBM are using the GEF implementation, or have duplicated the efforts of creating their own implementations. This should be moved up to JFace (I guess SWT wouldn't distrubute such "utility" classes).
Should integrate the code for 2.2. Investigate adopting the delegates for the Navigator.
The GEF implementation is not identical to the JDT implemention. Important differences include: 1) The active drop-target listener may be a function of the mouse location, therefore we update the active drop target more frequently. On every dragOver callback we update the active listener. 2) Whenever the current listener is changed, the old listener will be sent dragLeave(), the new listener is sent dragEnter(). This is necessary for the old listener to clean up any feedback it was showing, and to be consistent with the DropListener interface, which guarantees that either dragLeave or dragFinished will be called. 3) DelegatingDragAdapter should not be updating the set of Transfers[] inside the dragStart method. See bug 34983. If the set of transfers go to none, then drag will no longer function at all. So, DelegatingDragAdapter must make all Tranfers available via a getTransfers[] method, and calling dragSource.setTranfer([]) must be done externally by the client. You can check out our implementations from CVS, or download them from our downloads page.
Nick suggested asking the SWT team for input regarding enhanced drag and drop listener support. I released an experimental version of the delegating drag and drop support to org.eclipse.jface. The files are: org.eclipse.jface.util.DelegatingDragAdapter org.eclipse.jface.util.DelegatingDropAdapter org.eclipse.jface.util.TransferDragSourceListener org.eclipse.jface.util.TransferDropTargetListener The two concepts/benefits of the delegating drag and drop are: 1) Allowing a 1:1 mapping between transfer type and listener. The listener implementation depends on the transfer type. This is certainly true for dragSetData and drop. In the Resource Navigator use case the dragEnter, dragFinished and dragStart implementations vary depending on the transfer type. The listener code will be greatly simplified if it can be separated by transfer type. The current SWT listener in DragSource/DropTarget does not allow for a clean separation by transfer type. 2) Controlling enablement of listeners. Drag listener enablement often depends on selection state. Based on the selection some or all transfer types may not be valid. In the GEF use case finer control over drop enablement is needed as well. Drop enablement may change based in the drag operation and location. The question is if SWT can provide more fine grained drag and drop listener support. Scenario 1) could be supported by adding API that allows setting a listener for a specific transfer type. The code I released adds a method #getTransfer() to the drag/drop listener interface for this purpose. There are other options. Scenario 2) could be supported by adding a doit field to the dropTargetEvent. The current code uses the dragStart doit field of the DragSourceEvent and adds a method #isEnabled to the drop listener interface to determine enablement of a particular listener. Interested parties are encouraged to provide further input they may have, including corrections and additions to the two scenarios I provide and the changes to SWT that I suggest. Please verify that the SWT changes I suugest and the preliminary code I released would be sufficient for your use cases.
I am currently implementing DND on the Mac and looking at what additional capability could be provided on all platforms. I am also making a concerted effort to make all platforms perform DND in a more consistent manner. I will keep this bug report in mind as I do this. I expect there will be a number of changes for 3.0.
Regarding scenario 1 in comment #7. One possible extension of DND is to allow the transfer of more than one type of data in the drop. I am currently looking into this. Also, a target may support the download of multiple types but have a preferred type. I am not clear on how adding listeners based on transfer type will work well in either of these situations. Regarding scenario 2 in comment #7. At any time the event.detail field can be set to DND.DROP_NONE. This is the equivalent of setting doit to false for the drop target. I do not see why an additional field is required.
"At any time the event.detail field can be set to DND.DROP_NONE. This is the equivalent of setting doit to false for the drop target. I do not see why an additional field is required" Additional field? Did you mean the additional isEnabled(...) method? I suppose that instead of the isEnabled(..) method, we could call one of the existing Drop callbacks and check the detail field. But, this has a drawback: It is possible that a delegate would really like to be the active listener, but it wants to display the NOT cursor (detail = DROP_NONE) in addition to some other feedback (such as scrolling the view or a tooltip). This case can only be handled with the additional isEnabled method.
Scenario 2 in comment 7 talks about adding a doit field to the DropTargetEvent - that is what I am referring to when I said "additional field". The only purpose I could see of a doit field in the DropTargetEvent is for the drop target at any time to say "bug off and stop telling me about any more of these DND events - I am not interested". Since this does not actually terminate the DND operation in the OS (some other target may still be interested in it), I do not see why the current capability provided by SWT is not sufficient. The delegate can set the feedback and detail fields to none if that is what it wants. If the delegate wants to have an "enabled" field to track its state, that is fine but why should the event be changed or the reporting of events?
The idea of delegates is to make life easier when handling many transfer types. Are you saying that each delegate should track whether it is interested in drop events using a flag? That is exactly the kind of duplication the delegation mechanism wants to avoid.
Sorry, I misread comment 7, seeing the "2)" instead of "scenario 2)". I agree with Veronika, a doit field would not be useful because there would be no obvious time when the listener's notification would resume, which is required. Even if a delegate sets doit=false, you must continue to poll it to see if it still isn't interested (if doit == false still), in which case what's the point. I think Knut was also proposing: DragSource#addDragSourceListener(DragSourceListener, Transfer[]); DropTarget#addDropTargetListener(DropTargetListener, Transfer[]); But I'm not sure how such API would be used. What would it mean if two droptargetlisteners were added with a common Transfer type?
The doit field in the DropTargetEvent would work like and could replace the isEnabled method in the (transfer) drop target listener. Now, isEnabled is called to update the currently active listener in dragEnter, dragOperationChanged, dragOver and drop. Instead, the appropriate event would be sent to the listeners until one returns doit == true. That listener would then be made active listener. Again, the purpose is the same as with the isEnabled method. The API I envisioned to address scenario 1 would support exactly a 1:1 mapping. E.g., addDragSourceListener(DragSourceListener, Transfer) The semantics when there is more than one listener for the same transfer type currently (in the experimental code) is to select the first one, just like in GEF. The 1:1 relationship should probably be enforced by the API and exceptions thrown. It seems that multiple transfer types and delegating drag/drop listeners are conflicting features. Delegation aims to separate DnD by transfer type whereas multiple transfer types requires knowledge about more than one and probably all of them.
Another use case: WSAD is using a form of delegating DnD in the "Data Definition" and "DB Servers" views in the Data Perspective. It is similar to scenario 2, selection dependent transfer type enablement. The difference is that more than one delegation listener is defined for one transfer type. Different listeners handle different selections in the view. They all use the same transfer type. This suggests that we would need more than just an addDragSourceListener(DragSourceListener, Transfer) API. E.g., this is a 1:n relationship of transfer type and listener.
Created attachment 5948 [details] Delegating drag/drop Changes to Resource Navigator for using delegating DND. The Delegating DND framework itself is released in org.eclipse.jface. It is marked as experimental and should be removed if it is decided that this should not be included in 3.0. Should consider this when working on drag and drop design for General Purpose Navigator.
Reassigning to Nick since he is taking ownership of DND.
Stefan now owns the DND support in the workbench. Nothing planned here for 3.1, but should revisit post-3.1.
The following utility classes were added to JFace as "experimental" in 3.0: DelegatingDragAdapter DelegatingDropAdapter TransferDragSourceListener TransferDropTargetListener I have removed the "experimental" tags in 3.1.
So this is fixed then, milestone = 3.0
I guess we did satisfy the original request. Closing then.