|Re: GEF as native Drag Source [message #1273708 is a reply to message #210598]
||Thu, 20 March 2014 12:06
| Kent Xu
Registered: August 2011
I recently faced a similar use case. I can not find any tips online about this topic other than this post so I decided to dig deep into the mechanism. It turns out to be quite doable though it takes some time to understand the system and customize it to client's specific needs. |
I know this discussion has been asleep for a very long time but I hope the info is still useful to others in the future.
Using the simple shape example to describe the use case.
I want to do the following:
1. drag the shape normally on stage
2. when mouse moves out of the stage onto a drop target in another RCP view, cancels the on stage move (and its feedback) and allow the user to drop onto the drop target
3. scrollinggraphicalview has an auto expand (reveal) feature that expands the stage by 5px if you move the mouse close to the edge. I want to keep that so that if you move slowly to the edge, the expanding mechanism kicks in but if you keep moving out of the stage, it is cancelled and everything resets on the stage.
It is not feasible to mix native gef move with cross viewer move. It is true that native drag is disabled once you add one or more AbstractTransferDragSourceListener. Within GEF, every drag/move is powered by a single LightWeightSystem. The GEF drag/drop use case is quite different than a typical SWT or inter application drag/drop. What we are doing is to talk to facilitate the communication between one SWT (a lightweightsystem with its own inner drag/move logic) and other DropTargets other SWT widget or app. See "TheLastOne" (it is named like that) inner class for some clues. They are just two different systems and are hardwired.
Therefore I choose to registers a custom AbstractTransferDragSourceListener. Yes, that means losing native events, but we make it up by triggering important events ourselves. Then let the GEF tool do the rest just like what it would when using native drag.
One of the challenge in this approach is to get mouse move/drag events because DragSourceListener only provides start and finish callbacks. We need those events in order to move the object while it is still in the editor region. To address this issue, I added a AbstractTransferDropTargetListener on to the editor view.
The final solution consists of 3 pieces.
1. create AbstractTransferDragSourceListener and AbstractTransferDropTargetListener for the editor (added to viewer). The former is not very special, just pass the drag information as you need and do clean up on dragFinished. The latter is crucial but simple. Just override createTargetRequest() to dispatch the proper editor event via current editDomain. For most use cases, it means mouseDrag and mouseHover.
2. create DropTarget and DropTargetListener for the external drop view
3. create a Transfer for the drag source and drop target listeners.
Other things I have done:
1. overwrite DragSource image to be invisible to avoid having two drag feedback in editor (OSX)
2. I used a singleton based on SimpleObjecdtTransfer since I only need DnD within one VM. Other Transfers are possible depends on your need. I actually used it to store many other Stage-to-viewer global transfer status info and references.
In most cases, you want to cancel the drag commands once you moved onto external drop targets. The TransferDropTargetListener added to the editor can not help with that because it only works when the mouse is on its zone. Therefore it is important to add a mechanism to notify the editor when the mouse is "out".
I still want to keep the auto expand feature in GEF scrolling editor when the stage expands when you drag the object close to the edge. This can be done by calling the selected Tool's nativeDragFinished.
Powered by FUDForum
. Page generated in 0.02555 seconds