API proposal: drag view

steve.x.northover at oracle.com steve.x.northover at oracle.com
Tue Jan 15 14:16:47 PST 2013

At the operating system level, the image is provided as input when the 
drag starts.  Even if it were remembered in the operating system (which 
it is not for example, on Windows), we wouldn't set the bits from an FX 
image then query them back and then wrap them all the way up to FX again 
in an an FX image.  The drag image cannot change underneath us.  Hence, 
we have the option of storing the image in a get/set field.

There is no reason that a new instance of a Glass drag board needs to be 
created during the drag, even if that is what we are doing now.  I 
suspect that we might be creating a new instance for the duration of the 
drag, which is fine.  Since we own both Glass and Prism and all the code 
in question, we can change the code to make whatever we wish be 
guaranteed on all platforms, subject to platform restrictions.

If the getter gets and sets a field, then the getter will work every 
time.  It sound like you are telling me this is not possible because of 
our implementation, of which we have full control.  Do we not cache the 
FX dragboard for the full duration of the drag (even if Glass might 
not)?  Since there can only ever be one drag started at a time, it 
should be easy enough and correct to do this.  We can clear the instance 
when the drag ends.


On 15/01/2013 2:43 PM, Pavel Safrata wrote:
> First of all, the DnD could have been started outside of our 
> application and in this case I'm not sure it's possible for the image 
> to appear in the java object somehow. Second, we don't keep the 
> DragBoard instance in scenegraph. We always get one from glass, and 
> glass gets it by createDragboard() call. I think currently it reuses 
> the same instance, but it is not guaranteed anywhere so we should not 
> rely on it.
> Anyway, the getter will sometimes work and sometimes not (unless all 
> operating systems provide an access to the drag image). By the way, we 
> most probably could keep the value set by user in Glass, but having 
> "getter that works only during drag detection" sounds better than 
> "getter that works during drag detection and sometimes also during 
> dragging depending on where the gesture started".
> Pavel
> On 15.1.2013 20:03, steve.x.northover at oracle.com wrote:
>> I don't understand why it only works during drag detection.  We set 
>> the Java object in a field and we return that field.  Do you mean 
>> that setting the image outside of drag detect will not update the 
>> image that is used by the operating system?  I understand that this 
>> is most likely a restriction.
>> Steve
>> On 15/01/2013 1:56 PM, Pavel Safrata wrote:
>>> Richard,
>>> you're right, this could work. And the getter (or a boolean 
>>> hasDragImage()) could be used in this case. So are we OK with a 
>>> getter that works only during drag detection?
>>> Thanks,
>>> Pavel
>>> On 15.1.2013 19:46, Richard Bair wrote:
>>>> I assumed the Tree / Table could override this method and configure 
>>>> the drag board int he startDragAndDrop call itself?
>>>> On Jan 15, 2013, at 10:41 AM, steve.x.northover at oracle.com wrote:
>>>>> Got it.  You need to start drag and drop before you get a drag 
>>>>> board.  Drag and drop is started in drag detect which takes a 
>>>>> MouseEvent, not a DragEvent.
>>>>> How are we going to allow tree and table to provide default drag 
>>>>> images?
>>>>> Steve
>>>>> On 15/01/2013 1:06 PM, Pavel Safrata wrote:
>>>>>> Hi Steve,
>>>>>> I take it that you want it only for the drag start and you are 
>>>>>> not concerned about an inaccessible value during the rest of the 
>>>>>> gesture (we are not always the source so we don't always set the 
>>>>>> drag image). Still, how would you even access the dragboard in a 
>>>>>> different node than the one that started the DnD to call the 
>>>>>> getter if we provided it? I don't think we have a mechanism for 
>>>>>> one node starting DnD and another node altering the dragboard.
>>>>>> Thanks,
>>>>>> Pavel
>>>>>> On 15.1.2013 18:55, steve.x.northover at oracle.com wrote:
>>>>>>> Without a getter, the application has no idea whether a drag 
>>>>>>> image has already been set for them.  Having a setter without a 
>>>>>>> getter generally makes no sense.  Since we set the drag image, 
>>>>>>> we can easily return the image that we set.
>>>>>>> Steve
>>>>>>> On 15/01/2013 4:20 AM, Pavel Safrata wrote:
>>>>>>>> Hi Richard, Steve,
>>>>>>>> On 14.1.2013 20:51, steve.x.northover at oracle.com wrote:
>>>>>>>>> +1
>>>>>>>>> I'd like to see some example code where the tree and table set 
>>>>>>>>> a default image as part of the implementation of these 
>>>>>>>>> controls. Applications would get a reasonable image for free 
>>>>>>>>> and be able to override it as necessary.  Having and getter is 
>>>>>>>>> necessary for this.
>>>>>>>> Is it? What will be done with it? User will get the image and 
>>>>>>>> programatically check if it looks good?
>>>>>>>> (please see my answers to Richard's comments below).
>>>>>>>>> BTW, the last time I looked, on Windows, when you set image 
>>>>>>>>> content, then you will get a drag image for free.  This 
>>>>>>>>> doesn't happen on the Mac.  We should stop doing this on Windows.
>>>>>>>>> Steve
>>>>>>>>> On 14/01/2013 2:09 PM, Richard Bair wrote:
>>>>>>>>>> HI Pavel!
>>>>>>>>>> Overall great. I don't see why you can't have a getter. The 
>>>>>>>>>> only way to set the drag view is via an API we control so it 
>>>>>>>>>> seems pretty easy to implement the getter as well.
>>>>>>>> No. DnD is an OS feature. You can drag data from native 
>>>>>>>> applications to FX. Is it possible on all systems to find out 
>>>>>>>> what did the native application use as drag image? I'm really 
>>>>>>>> not sure. Anybody has the knowledge?
>>>>>>>>>> You could either have a DragView class which encapsulates the 
>>>>>>>>>> node/image and the offsetX and offsetY, or you could just 
>>>>>>>>>> break it out into three properties on the DragBoard and save 
>>>>>>>>>> yourself the extra class.
>>>>>>>> If we are OK with the properties having value only during 
>>>>>>>> starting DnD and not during the rest of the gesture, then yes, 
>>>>>>>> this could be done. But I still don't see the value.
>>>>>>>>>> I think you should just have an image based dragImage 
>>>>>>>>>> property and dragImageOffsetX and dragImageOffsetY 
>>>>>>>>>> properties. We shouldn't by default put anything in as the 
>>>>>>>>>> drag image, except for a few UI controls. We'll want a 
>>>>>>>>>> ListView, TreeView, TableView, TreeTableView to automatically 
>>>>>>>>>> pre-populate the DragBoard before the onDragDetected code is 
>>>>>>>>>> called, so that those control give you a nice drag image for 
>>>>>>>>>> free but the developer is free to replace it or clear it as 
>>>>>>>>>> they see fit.
>>>>>>>> I don't think this is possible with the proposed API. The 
>>>>>>>> DragBoard instance doesn't exist until you start DnD in the 
>>>>>>>> DRAG_DETECTED handler, so you cannot really pre-populate it. 
>>>>>>>> Would it be sufficient if the controls contained 
>>>>>>>> getDefaultDragImage() method that users would explicitly call?
>>>>>>>>>> The developer could use the synchronous version of snapshot. 
>>>>>>>>>> But I think either snapshot should be fixed to be transparent 
>>>>>>>>>> by default instead of a white fill by default or add another 
>>>>>>>>>> snapshot method which produces a transparent fill by default.
>>>>>>>> True. Kevin, how easy/hard it would be to add such snapshot 
>>>>>>>> method?
>>>>>>>> Thanks,
>>>>>>>> Pavel
>>>>>>>>>> Basically:
>>>>>>>>>> source.setOnDragDetected(new EventHandler<MouseEvent>() {
>>>>>>>>>>      public void handle(MouseEvent event) {
>>>>>>>>>>          DragBoard db = 
>>>>>>>>>> source.startDragAndDrop(TransferMode.ANY);
>>>>>>>>>>          db.setContent(…);
>>>>>>>>>>          db.setDragImage(source.snapshot());
>>>>>>>>>>          db.setDragImageOffsetX(event.getX());
>>>>>>>>>>          db.setDragImageOffsetY(event.getY());
>>>>>>>>>>          event.consume();
>>>>>>>>>>      }
>>>>>>>>>> }
>>>>>>>>>> Maybe also have a convenience method on DragBoard:
>>>>>>>>>>      db.updateDragImage(node, x, y);
>>>>>>>>>> which then just calls the 3 setters as appropriate.
>>>>>>>>>> Richard
>>>>>>>>>> On Jan 13, 2013, at 11:59 PM, Pavel 
>>>>>>>>>> Safrata<pavel.safrata at oracle.com>  wrote:
>>>>>>>>>>> Hello,
>>>>>>>>>>> this is a proposal of an API allowing to specify the image 
>>>>>>>>>>> floating with mouse cursor during a drag&drop operation.
>>>>>>>>>>> Jira: http://javafx-jira.kenai.com/browse/RT-14730
>>>>>>>>>>> I propose to add two methods to DragBoard:
>>>>>>>>>>> setDragView(Image image, double offsetX, double offsetY)
>>>>>>>>>>> setDragView(Node node, double offsetX, double offsetY)
>>>>>>>>>>> The first one simply uses the given image for the drag view 
>>>>>>>>>>> with the offsetX and offsetY specifying cursor position over 
>>>>>>>>>>> the image. The second one renders the given node to an image 
>>>>>>>>>>> and uses the result (the coordinates being in the node's 
>>>>>>>>>>> local space).
>>>>>>>>>>> The typical usage will look like this:
>>>>>>>>>>>         sourceNode.setOnDragDetected(new 
>>>>>>>>>>> EventHandler<MouseEvent>() {
>>>>>>>>>>>             public void handle(MouseEvent event) {
>>>>>>>>>>>                 Dragboard db = 
>>>>>>>>>>> source.startDragAndDrop(TransferMode.ANY);
>>>>>>>>>>>                 ClipboardContent content = ...
>>>>>>>>>>>                 db.setContent(content);
>>>>>>>>>>>                 db.setDragView(sourceNode, event.getX(), 
>>>>>>>>>>> event.getY()); // that's it
>>>>>>>>>>>                 event.consume();
>>>>>>>>>>>             }
>>>>>>>>>>>         });
>>>>>>>>>>> This API is meant for telling the operating system what 
>>>>>>>>>>> visual cues to provide, I don't think it is useful (and I'm 
>>>>>>>>>>> not sure it is even possible) to provide getters.
>>>>>>>>>>> There is a possibility to provide default drag view - if 
>>>>>>>>>>> none of those methods is called, the default drag view would 
>>>>>>>>>>> be an image of the drag gesture source. This should work 
>>>>>>>>>>> nice most of the times. However, it may cause inconveniences 
>>>>>>>>>>> to some existing apps - for instance a text editor node 
>>>>>>>>>>> which puts the selected text on the DragBoard - after 
>>>>>>>>>>> updating FX the application starts to show the entire editor 
>>>>>>>>>>> in the drag view. For this reason I think the default 
>>>>>>>>>>> behavior should remain unchanged.
>>>>>>>>>>> Thanks,
>>>>>>>>>>> Pavel

More information about the openjfx-dev mailing list