API proposal: drag view

Pavel Safrata pavel.safrata at oracle.com
Tue Jan 15 23:28:26 PST 2013


Hi Steve,
I know I'm writing this for a fourth time already but you seem to ignore 
it. DnD can start in a different, native application. How do we get the 
image in this case, if OS doesn't provide access to it?

I think we can't. This is the platform limitation. And the platform 
limitation must be reflected in our API, it cannot just fail without a 
warning.

As I wrote in my previous email, yes, we  could keep the value set by 
user. But it won't solve the problem above.

Pavel

On 15.1.2013 23:16, steve.x.northover at oracle.com wrote:
> 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.
>
> Steve
>
> 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