Object following the mouse

Is it possible to make an applescript that makes an object like a button follow the mouse around? Like a variable that is the position of the mouse?

:?:

There is no handler in ASStudio that can track the mouse while it is not being clicked or dragged, but you can drag any object… like a button… that uses the ‘mouse down’ and ‘mouse dragged’ handler’s using the code below.

The mouse down handler sets the point in the button where the mouse went down, in terms of the difference between the origin of the button (bottom left) and the actual x,y position that was clicked within the button. The mouse dragged handler then uses those property variables (diffX and diffY) to smoothly begin dragging the button. If you drag too fast or your button is too small, the handler may not be able to keep up with you and you’ll drag right out of the button. A transparent button with a larger footprint than the visible ‘handle’ may be a wise idea, if your design allows.

You could also use this code to drag other objects at the same time, as well. For example, to eliminate the unsightly highlighting of your button as you select it, you could create an image view with your ‘button’ image in it, and then create a transparent image which lays on top of it, and then use the code below to drag both the button and the image view (see example code). Note that doing this with many objects can add a lot of processing overhead and make your code so slow that you can’t drag slow enough to keep from dragging out of the button.

property diffX : 0
property diffY : 0

on mouse dragged theObject event theEvent
	set {dragX, dragY} to location of theEvent
	
	set adjX to (dragX - diffX)
	set adjY to (dragY - diffY)
	
	tell window "theWindow"
		tell button "theButton"
			set position to {adjX, adjY}
		end tell

		(* Also drag optional secondary objects *)
		--> Assumes same dimensions as button
		--tell image view "theImage"
			--set position to {adjX, adjY}
		--end tell
	end tell
end mouse dragged

on mouse down theObject event theEvent
	if name of theObject is "theButton" then
		set {downX, downY} to location of theEvent
		set {objX, objY} to position of theObject
		
		set diffX to (downX - objX)
		set diffY to (downY - objY)
	end if
end mouse down

Good luck,
j

You can also use the “mouse location” command from XTool osax, but then you should use a infinite repeat loop to track allways the mouse position, which would be very cpu-intensive…

OK, thanks. About that http://www.osaxen.com/xtool.html. Would i have to include it in any application i used it for so that i could give the application to a friend or put it up for download?[/url]

You could instruct your users to download and install XTool or (I think) being a GPL thing, you could bundle it in your own app, as described here:
http://macscripter.net/faq/scripting_additions.php?id=P193

Not really; Mac OS X is well able to look after itself. What it will do, however, is make your application completely unresponsive, unable to handle any other GUI events, while it remains in that loop.

The solution: instead of creating your own infinite loop that blocks everything else, use the application’s own main event loop to drive your object-moving code in between other tasks. Use Interface Builder to add an idle handler to your application and put your object-moving code in that. You can set the time between idle calls using the idle handler’s return value, which should be an integer or real representing the delay between each idle call in seconds (use something nice and short).

HTH

Not true. You can specify a real below 1 in your idle handler, but it will return allways “1”, which is the minimum value in a idle handler (both AS and ASS).
Also, the app will become unresponsive to “other events”, but not to its own tasks. So, if you configure it to follow the mouse, it will follow the mouse. Just attach this to a button and test it yourself:

on clicked theObject
	set {wx1, wy1, wx2, wy2} to bounds of window of theObject
	
	set {x1, y1, x2, y2} to bounds of theObject
	
	set {scrx, scry} to screen resolution
	
	set relativeWY to scry - wy1
	
	set bwidth to x2 - x1
	set bheight to y2 - y1
	
	repeat 500 times
		set {mousex, mousey} to mouse location
		set position of theObject to {mousex - wx1 - (bwidth / 2), relativeWY - mousey - (bheight / 2)}
	end repeat
end clicked

It does not seem very useful, but it is the requested code… :wink:

Prior to AS 1.9.2 it was indeed the case that idle delays could only be given in whole seconds, with a minimum of one second. However, the AS 1.9.2 release notes state “The Idle handler return value can now be a real number”, which I assume means that it can handle fractional delays. This is irritatingly vague, however, and don’t indicate if it applies to Studio apps or only to AS applets, so it’s possible Studio apps are still stuck with whole-second delays. You’d need to experiment, or enquire on Apple’s Studio Users list in hopes of a clarification from one of the Apple engineers.

An infinite loop will be fine if following the mouse is the only thing you want the application to do. If you want it to respond to, say, the user clicking on other buttons, selecting menu items, or anything else you’re SOOL: AS 1.9.2 processes events on a first-in, first-out basis, meaning the user’s code has to return from handling the current event before the next event can be processed. Since handling user interactions is pretty much the raison-d’etre of writing Studio apps, it seems more sensible to use a solution that won’t block under OS 10.3+.

What a user thinks they want is not necessarily the same thing as what they actually need. It seems only fair to provide them a sporting chance… :wink:

E&OE, YMMV, HTH, etc.