.canReceiveDragHandler triggers unreliably

Hi. In the following code I’m trying to implement a selection rectangle (i.e. a rectangle which is drawn when you drag over a surface with the mouse).

I’m finding that if you draw a rectangle downwards, and move the mouse back up again (in order to move the bottom border of the selection rectangle back up), quite often the .canReceiveDragHandler function stops triggering. You can see this because the mouse’s X and Y coordinates are no longer written to the post window. If you move the pointer so that it crosses one of the selection rectangle’s borders, the function starts triggering again.

I can’t see a problem with my logic, but to be honest I find the UI framework difficult to grasp generally.

  • Does this code work okay for you?
  • Is there a problem with it?
  • Have I misunderstood something important?

Code below:

(
~window = Window("Selection rectangle", Rect(50,50,800,600));
~scale = 1.0;
~minscale = 1.0;
~maxscale = 5.0;
~dragView = DragBoth(~window, Rect(0, 0, 800, 600)).background_(Color.black).beginDragAction_({|me,x,y|me.object=x@y}).canReceiveDragHandler_({
	|me,x,y|
	var left,top,width,height;
	postln([x,y]);
	if ((me.object.x) < x,{
		left = me.object.x;
		width = x - (me.object.x);
	},{
		left = x;
		width = (me.object.x) - x;
	});
	if ((me.object.y) < y,{
		top = me.object.y;
		height = y - (me.object.y);
	},{
		top = y;
		height = (me.object.y) - y;
	});
	~selectionView.bounds = Rect(left,top,width,height);
});
~selectionView = View(~dragView,Rect(10,10,10,10)).background_(Color.new255(red: 255, green: 255, blue: 255, alpha: 50));
~window.front;
)

It won’t run due to Class not defined error for BorderView. Is that one of your own classes?

Best,
Paul

Oh crap. Sorry about that - thanks for highlighting! I’ll modify the code and repost.

Reposted, and this part is necessary to have more than 20 characters.

Now I have a solid rectangle, I can see what the problem is! :slight_smile:

Yes. Is the issue that when the mouse is over ~selectionView, it doesn’t trigger canReceiveDragHandler_ function belonging to ~dragView?

Yes, that’s it - that is quite evil! So ~selectionView needs its own handler that calls the parent’s. I was just working on this, and there is the added complication that the mouse’s coordinates are different within ~selectionView compared to what they are within the parent, so that needs compensating for. I’ll post the solution when I figure it out.

(
~window = Window("Selection rectangle", Rect(50,50,800,600));
~scale = 1.0;
~minscale = 1.0;
~maxscale = 5.0;
~dragView = DragBoth(~window, Rect(0, 0, 800, 600)).background_(Color.black).beginDragAction_({|me,x,y|me.object=x@y}).canReceiveDragHandler_({
	|me,x,y|
	var left,top,width,height;
	postln([x,y]);
	if ((me.object.x) < x,{
		left = me.object.x;
		width = x - (me.object.x);
	},{
		left = x;
		width = (me.object.x) - x;
	});
	if ((me.object.y) < y,{
		top = me.object.y;
		height = y - (me.object.y);
	},{
		top = y;
		height = (me.object.y) - y;
	});
	~selectionView.bounds = Rect(left,top,width,height);
});
~selectionView = View(~dragView,Rect(10,10,10,10)).background_(Color.new255(red: 255, green: 255, blue: 255, alpha: 50)).canReceiveDragHandler_({|me,x,y|me.parent.canReceiveDragHandler.value(me.parent,me.bounds.left + x,me.bounds.top + y);});
~window.front;
)

That seems to do it. Thanks for your help, @TXMod!

1 Like

Setting acceptsMouse to false for ~selectionView is a better solution.

~selectionView = View(~dragView,Rect(10,10,10,10)).background_(Color.new255(red: 255, green: 255, blue: 255, alpha: 50)).acceptsMouse_(false);
1 Like