The response rate of DragBoth.canReceiveDragHandler_ and popup messaging on DragBoth

Dear all,

Inspired by the following thread,

I have written the two codes below the post. I would like to know

  1. which one is more user friendly (= more convenient) for you to use;
  2. if there is a way to reduce the response rate of canReceiveDragHandler_ in code 2;
  3. if there is a way to have the message appear on/above the DragBoth instead of posting to the Post window.

I think code 2 is more convenient, but .postln in the canReceiveDragHandler_ posts the message too often.

code 1

(
s.waitForBoot{
	var win, buffer;
	win = Window("accepts all items and posts messages", Rect(200,200,500,40)).front;
	DragBoth(win, Rect(10,10,480,20))
	.align_(\center)
	.string_("drag an audio file here")
	.action_{ |dropped|
		("\nThe dropped item:" + dropped.object).postln;
		if(PathName(dropped.object).isFile) {
			var aSoundFile = SoundFile();
			if(aSoundFile.openRead(dropped.object)){
				aSoundFile.close;
				if (buffer.class.asSymbol == \Buffer) {
					buffer.free;
					"The previous buffer has been freed.".postln
				};
				buffer = Buffer.read(s, dropped.object, action: { |buf|
					buf.postln;
					buf.play
				});
			} {
				"The item you have dropped is not a supported sound file for SuperCollider. Please drop a sound file that is supported.".postln
			}
		} {
			"The item you have dropped is not a file. Please drop a supported sound file.".postln
		}
	};
	win.onClose_{
		buffer.free;
		"\nThe buffer you loaded is freed.".postln;
		s.cachedBuffersDo { |buf| buf.postln };
	}
}
)

code 2

(
s.waitForBoot{
	var soundFileOrNot, win, buffer;
	soundFileOrNot = { SoundFile.openRead(View.currentDrag).asString == "a SoundFile" };
	win = Window("accepts only one of the sound files supported by SuperCollider", Rect(200,200,500,40))
	.acceptsMouseOver_(true)
	.front;
	DragBoth(win, Rect(10,10,480,20))
	.align_(\center)
	.string_("drag an audio file here")
	.canReceiveDragHandler_{ 
		if(soundFileOrNot.().not) {
			"\nThe item you are dropping is not a supported sound file. Please drag a supported sound file.".postln
		};
		soundFileOrNot.()
	}
	.action_{ |dropped|
		"".postln;
		if (buffer.class.asSymbol == \Buffer) {
			buffer.free;
			"The previous buffer has been freed.".postln
		};
		buffer = Buffer.read(s, dropped.object, action: { |buf|
			buf.postln;
			buf.play
		})
	};
	win.onClose_{
		buffer.free;
		"\nThe buffer you loaded is freed.".postln;
		s.cachedBuffersDo { |buf| buf.postln };
	}
}
)

When something is repeatedly firing for the same value, a good approach is to stash the previous value in a variable, and compare.

(
var previousCheckedDrag;

w = Window("test", Rect(800, 200, 500, 400)).front;
w.layout = VLayout(
	z = DragSource(),
	y = DragBoth()
);

y.canReceiveDragHandler_({
	if(View.currentDrag !== previousCheckedDrag) {
		View.currentDrag.debug("canReceive responding...");
		previousCheckedDrag = View.currentDrag;
	};
	true
})
.action_({
	previousCheckedDrag = nil;
	View.currentDrag.debug("accepted drag");
});

z.object = "hi!";
)

This way will show only one “canReceive responding” per drag-in.

It might be good to add something to clear previousCheckedDrag if the mouse button is released for an unsuccessful drag-n-drop (like, dropping it outside of a DragBoth / DragSink).

BTW:

soundFileOrNot = { SoundFile.openRead(View.currentDrag).asString == "a SoundFile" };

If you’re opening a file handle to check something, make sure to close it before exiting the function. This will accumulate (leak) file handles.

soundFileOrNot = {
	var file = SoundFile.openRead(View.currentDrag);
	// also this is a better test for successful opening
	// going through a string is not necessary
	if(file.notNil) {
		file.close;
		true
	} {
		false
	};
};

Also…

	.canReceiveDragHandler_{
		// don't repeat the test
		// you were leaking not just one, but two SoundFile handles
		// for every mouse move
		var isSoundFile = soundFileOrNot.();
		if(isSoundFile.not) {
			"\nThe item you are dropping is not a supported sound file. Please drag a supported sound file.".postln
		};
		isSoundFile
	}

hjh

2 Likes

Thank you so much! It helps me a lot!