How to detect when you move a drag and drop away from a drag sink

canReceiveDragHandler enables a View to respond in some way when something is dragged over it (but not yet dropped). In many UIs this would typically result in some kind of visible change to the view, for example, turning white.

This code illustrates my question (note that you’ll need to hold down Cmd / Ctrl to make the drag work):

(
var window,view1,view2;
window = Window.new.front;

view1 = View(window,Rect(10,10,150,20)).background_(Color.rand);
view1.beginDragAction = { |me| var number = 20.rand; me.dragLabel = format("I'm thinking of the number %...", number); number; };

view2 = View(window,Rect(10,50,150,20)).background_(Color.rand);
view2.canReceiveDragHandler = { |me| me.background_(Color.white); true; };
view2.receiveDragHandler = { postln(format("You were totally thinking of the number %!", View.currentDrag));  };
)

So the sink View turns white when something is dragged over it. However, as far as I can see there is no event that represents the thing being dragged off it again. This means that the View remains white permanently.

Yes, I can restore the original colour if the thing is actually dropped onto the sink View, but if it’s just dragged over it without dropping then I don’t see how I can.

Is there something I’m missing?

Maybe you could use mouseOverAction to detect when you’re no longer over the view?

Sorry, actually it’s .mouseLeaveAction to detect when you’re no longer over the view.

Oh, that seems super obvious now you mention it. :slight_smile: Makes me wonder now why we have .canReceiveDragAction when we could presumably already use .mouseEnterAction. I guess it’s about being able to return true or false to specify whether the sink accepts the drag or not.

Thanks a lot, TXMod!

1 Like

I never used drag so I might be wrong.

Clicking a view, holding the mouse button and moving the cursor around will keep the focus on this view, even if the cursor goes outside. Thus, entering other views does not evaluates mouseEnterAction. I think canReceiveDragAction changes this behavior (so one input event can interact with more than a single view).