mouse entered mouse exit

hi
i’m using the below to show a panel with some info in it, the problem is that once the panel is activated by the mouseEntered, the mouseExited does not take affect, I have to click on the main window and then run my mouse over the mouseEntered area again for the panel to close.

What i’m trying to achieve is when the mouse enter’s into a specific area it will show a panel/window with my information, and when the mouse exits this area the panel/window will close and so on to the next area, is what i’m doing the right way, or is their a specific way to achieve my goal.

on mouseEntered_(theEvent)
WD349info’s |makeKeyAndOrderFront_|(me)
end mouseEntered_

on mouseExited_(theEvent)
WD349info’s orderOut_(me)
end mouseExited_

cheers
Budgie

What is the object that the mouse enters to trigger the window opening? Also, what is the parent class of your script?

Ric

gidday Ric

I’m using some code that Shane posted on another thread, which works fine as it is, but i’m trying to do as stated previously.

the mouse enters a NSBox to trigger, ive tried it with a NSButton also.

script MOUSE_ENTER_EXITAppDelegate
	property parent : class "NSObject"
    
    property custView : missing value
    property WD349info : missing value
    
    
    on mouseEntered_(theEvent)
       -- log "Entered"
      WD349info's |makeKeyAndOrderFront_|(me)
        
   end mouseEntered_
    
 on mouseExited_(theEvent)
     log "Exited"
   --   WD349info's orderOut_(me)
end mouseExited_

    
    
  on applicationWillFinishLaunching_(aNotification)
        
        set taClass to current application's class "NSTrackingArea"
        set trackingArea to taClass's alloc()'s initWithRect_options_owner_userInfo_(missing value, 545, me, missing value)
        log trackingArea -- helpful for working out enums
        my custView's addTrackingArea_(trackingArea)
        
        
		-- Insert code here to initialize your application before any files are opened 
	end applicationWillFinishLaunching_
	
	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return current application's NSTerminateNow
	end applicationShouldTerminate_
	
end script

It doesn’t work because the WD349info window becomes key, so the main window is no longer responding. Change the |makeKeyAndOrderFront_|(me) line to orderFront_(me).

Ric

on the money Ric, cheers for your help, appreciated

the above works sweet for 1 event, but now i’m now trying to have multiple custviews and mouseEntered/Exited events, how would I go about setting this up please?

You could do it like the following:

script MouseWindowAppDelegate
	property parent : class "NSObject"
	property custView1 : missing value
	property custView2 : missing value
	property WD349info : missing value
	property trackingArea1 : missing value
	property trackingArea2 : missing value
	
	on mouseEntered_(theEvent)
		if theEvent's trackingArea() is trackingArea1 then
			WD349info's orderFront_(me)
		else if theEvent's trackingArea() is trackingArea2 then
			log "I'm in area2"
		end if
	end mouseEntered_
	
	on mouseExited_(theEvent)
		log "Exited"
		WD349info's orderOut_(me)
	end mouseExited_
	
	on applicationWillFinishLaunching_(aNotification)
		set trackingArea1 to current application's NSTrackingArea's alloc()'s initWithRect_options_owner_userInfo_(missing value, 545, me, missing value)
		custView1's addTrackingArea_(trackingArea1)
		set trackingArea2 to current application's NSTrackingArea's alloc()'s initWithRect_options_owner_userInfo_(missing value, 545, me, missing value)
		custView2's addTrackingArea_(trackingArea2)
	end applicationWillFinishLaunching_
	
end script

Notice that I’ve set up 2 tracking areas, and I check to see which one is sending theEvent in the mouseEntered method. Notice also that I’ve declared trackingArea1 and trackingArea2 as properties, since they are used across different methods

Ric

thanks for the insight Ric, this is exactly what i was trying to achieve.

cheers
budgie

I wanted to add some more comments here about using tracking areas, and about some errors and ambiguities in the docs concerning them.

The initWithRect_options_owner_userInfo_ method has the userInfo parameter typed as an NSDictionary, but it appears that it should be typed as “id” since you can pass strings, numbers, dates, etc. as well as dictionaries (or their applescript equivalents) for this parameter.

The docs say “When handling such an event you can obtain the dictionary by sending userData to the NSEvent object”. This is incorrect (in ASOC anyway, I haven’t tried it in Objective C). You need to say “theEvent’s trackingArea()'s userInfo()” where “theEvent” is the parameter passed in to the mouseEntered:, mouseExited:, etc. methods.

The mouseEntered:, mouseExited: and mouseMoved: methods can be implemented in whatever script is referenced in the initWithRect_options_owner_userInfo_ method in the “owner” parameter. However, if you want to implement the cursorUpdate: method, it is not called in the “owner’s” class unless that class (script) is the topmost view that the cursor is over. So, this means that you have to implement this method in a subclass of the view for which you are adding the tracking rectangle. This isn’t real obvious in the docs.

I made this example to illustrate these points. The “options” parameter value of 549 in this example is the sum of the 512, 32, 4 and 1 choices which I show in the commented out part of the script. If you wanted to have the mouseMoved: method called, you would have to add 2 ( to make 551). The interface just has two boxes that are referenced by the IBOutlets “box1” and “box2”. The boxes have their class set to my other script “TheBoxes”

script MouseWindowAppDelegate
	property parent : class "NSObject"
	property box1 : missing value
	property box2 : missing value
	property WD349info : missing value
	
	on mouseEntered_(theEvent)
		if theEvent's trackingArea()'s userInfo() as string is "box1" then
			WD349info's orderFront_(me) -- Opens another window when the mouse enters box1
		else if theEvent's trackingArea()'s userInfo() as string is "box2" then
			log "I'm in box2"
		end if
	end mouseEntered_
	
	on mouseMoved_(theEvent) -- Not called unless the options number in initWithRect_options_owner_userInfo_ is 551
		log "mouse moved"
	end mouseMoved_
	
	on mouseExited_(theEvent)
		log "Exited"
		WD349info's orderOut_(me)
	end mouseExited_
	
	on applicationWillFinishLaunching_(aNotification)
		set trackingArea1 to current application's NSTrackingArea's alloc()'s initWithRect_options_owner_userInfo_(box1's frame(), 549, me, "box1")
		box1's addTrackingArea_(trackingArea1)
		set trackingArea2 to current application's NSTrackingArea's alloc()'s initWithRect_options_owner_userInfo_(box2's frame(), 549, me, "box2")
		box2's addTrackingArea_(trackingArea2)
		(*log current application's NSTrackingMouseEnteredAndExited as integer -- 1
		log current application's NSTrackingMouseMoved as integer -- 2
		log current application's NSTrackingCursorUpdate as integer -- 4
		log current application's NSTrackingActiveWhenFirstResponder as integer -- 16
		log current application's NSTrackingActiveInKeyWindow as integer -- 32
		log current application's NSTrackingActiveInActiveApp as integer --64
		log current application's NSTrackingActiveAlways as integer -- 128
		log current application's NSTrackingAssumeInside as integer -- 256
		log current application's NSTrackingInVisibleRect as integer -- 512
		log current application's NSTrackingEnabledDuringMouseDrag as integer -- 1024
		*)
	end applicationWillFinishLaunching_
	
end script

The cursorUpdate: method is then implemented in another class called TheBoxes:

script TheBoxes
	property parent : class "NSBox"
	
	on cursorUpdate_(theEvent)
		if theEvent's trackingArea()'s userInfo() as string is "box1" then
			current application's NSCursor's pointingHandCursor()'s |set|()
		else if theEvent's trackingArea()'s userInfo() as string is "box2" then
			current application's NSCursor's closedHandCursor()'s |set|()
		end if
	end cursorUpdate_
	
end script

By using the userInfo in my if statements instead of the trackingArea’s identity, as I did in the example I posted previously, I don’t need to have properties for them, which I would need to have reference to in my other script.

Ric