Hello there, (Wilbert ? )
I am looking for a Cocoa method to workaround (subclass) the MouseMove event of the PB CanvasGadget who does not always works on Mac OS Sierra (http://www.purebasic.fr/english/viewtop ... 24&t=66703).
I took a look on the "[PB Cocoa] Methods, Tips & Tricks" thread (http://www.purebasic.fr/english/viewtop ... 19&t=50795) but i only found a method to handle a mousemove event over a window, not over a gadget.
Any idea ?
Looking for a Cocoa method to replace MouseMove in a Canvas
Looking for a Cocoa method to replace MouseMove in a Canvas
Last edited by Niffo on Fri Jun 16, 2017 3:58 pm, edited 2 times in total.
Niffo
Re: Looking for a Cocoa method to replace MoveMove in a Canv
There's more users which can help out with Cocoa.
You might want to look at NSTrackingArea .
It allows you to track mouse actions inside a specific area.
You might want to look at NSTrackingArea .
It allows you to track mouse actions inside a specific area.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Looking for a Cocoa method to replace MoveMove in a Canv
Here's some example of using a tracking area.
Coordinates for the tracking area start at bottom left (0, 0) which is a bit inconvenient.
Of course you can use #NSTrackingInVisibleRect to track the entire gadget.
Coordinates for the tracking area start at bottom left (0, 0) which is a bit inconvenient.
Of course you can use #NSTrackingInVisibleRect to track the entire gadget.
Code: Select all
;Import "-stdlib=libc++ -mmacosx-version-min=10.7" : EndImport
EnumerationBinary
#NSTrackingMouseEnteredAndExited = $001
#NSTrackingMouseMoved
#NSTrackingCursorUpdate
#NSTrackingActiveWhenFirstResponder = $010
#NSTrackingActiveInKeyWindow
#NSTrackingActiveInActiveApp
#NSTrackingActiveAlways
#NSTrackingAssumeInside = $100
#NSTrackingInVisibleRect
#NSTrackingEnabledDuringMouseDrag
EndEnumeration
ProcedureC _mouseEntered_(obj, sel, event)
Debug "mouseEntered"
EndProcedure
ProcedureC _mouseExited_(obj, sel, event)
Debug "mouseExited"
EndProcedure
ProcedureC _mouseMoved_(obj, sel, event)
Debug "mouseMoved"
EndProcedure
ProcedureC _cursorUpdate_(obj, sel, event)
Debug "cursorUpdate"
EndProcedure
Global Tracker.i
Procedure InitTracker()
Protected trackerClass.i
If Not Tracker
trackerClass = objc_allocateClassPair_(objc_getClass_("NSObject"), "myAreaTracker", 0)
class_addMethod_(trackerClass, sel_registerName_("mouseEntered:"), @_mouseEntered_(), "v@:@")
class_addMethod_(trackerClass, sel_registerName_("mouseExited:"), @_mouseExited_(), "v@:@")
class_addMethod_(trackerClass, sel_registerName_("mouseMoved:"), @_mouseMoved_(), "v@:@")
class_addMethod_(trackerClass, sel_registerName_("cursorUpdate:"), @_cursorUpdate_(), "v@:@")
objc_registerClassPair_(trackerClass)
Tracker = class_createInstance_(trackerClass, 0)
EndIf
EndProcedure
InitTracker()
Procedure CreateTrackingArea(x, y, w, h, options, userInfo = #nil)
Protected Rect.NSRect
Rect\origin\x = x : Rect\origin\y = y
Rect\size\width = w : Rect\size\height = h
ProcedureReturn CocoaMessage(0,CocoaMessage(0,0, "NSTrackingArea alloc"),
"initWithRect:@", @Rect, "options:", options,
"owner:", Tracker, "userInfo:", userInfo)
EndProcedure
If OpenWindow(0, 0, 0, 220, 220, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 10, 10, 200, 200)
TA = CreateTrackingArea(0, 0, 50, 50, #NSTrackingMouseEnteredAndExited | #NSTrackingMouseMoved | #NSTrackingActiveInActiveApp)
CocoaMessage(0, GadgetID(0), "addTrackingArea:", TA)
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Gadget And EventGadget() = 0
If EventType() = #PB_EventType_LeftButtonDown Or (EventType() = #PB_EventType_MouseMove And GetGadgetAttribute(0, #PB_Canvas_Buttons) & #PB_Canvas_LeftButton)
If StartDrawing(CanvasOutput(0))
x = GetGadgetAttribute(0, #PB_Canvas_MouseX)
y = GetGadgetAttribute(0, #PB_Canvas_MouseY)
Circle(x, y, 10, RGB(Random(255), Random(255), Random(255)))
StopDrawing()
EndIf
EndIf
EndIf
Until Event = #PB_Event_CloseWindow
EndIf
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Looking for a Cocoa method to replace MoveMove in a Canv
Thank you VERY MUCH Wilbert ! Seems to be exactly what i need. If i remember correctly, i tried to implement Cocoa NSTrackingArea sometime ago but with no success. On top of that, i used the concept of Tracking Area before in Carbon but this one did not allow the MouseMove events, only MouseEnter and MouseExit.
I am going to see if the "Control Bounds Changed" is automatic in case of resize of the gadget or if i have to call a "HIViewChangeTrackingArea()" like method.
I am going to see if the "Control Bounds Changed" is automatic in case of resize of the gadget or if i have to call a "HIViewChangeTrackingArea()" like method.
Niffo
Re: Looking for a Cocoa method to replace MoveMove in a Canv
If you use #NSTrackingInVisibleRect the area you specify doesn't matter, it will always track the entire view and if it resizes, it still works.Niffo wrote:I am going to see if the "Control Bounds Changed" is automatic in case of resize of the gadget or if i have to call a "HIViewChangeTrackingArea()" like method.
If you want a specific area and you have to change it, you can use removeTrackingArea: to remove the old one and add a new one.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Looking for a Cocoa method to replace MoveMove in a Canv
So nice, works like a charm !wilbert wrote:If you use #NSTrackingInVisibleRect the area you specify doesn't matter, it will always track the entire view and if it resizes, it still works.
I have multiple canvas gadgets and i need to have only one _mouseMoved_() callback. Do you know how i can get (or pass) the calling GadgetID from the callback function ?
With the "userInfo" parameter ? I read here that this parameter does not work with the "mouseMoved" event : https://developer.apple.com/library/con ... jects.html
Niffo
Re: Looking for a Cocoa method to replace MoveMove in a Canv
Well, that was a simple question which took quite some thinking to figure out a solution.
I think this will do the trick ...
I think this will do the trick ...
Code: Select all
;Import "-stdlib=libc++ -mmacosx-version-min=10.7" : EndImport
;- Callbacks
ProcedureC _mouseEntered_(obj, sel, event)
Protected GadgetNumber.i
object_getInstanceVariable_(obj, "_gadget", @GadgetNumber)
Debug "entered [" + Str(GadgetNumber) + "]"
EndProcedure
ProcedureC _mouseExited_(obj, sel, event)
Protected GadgetNumber.i
object_getInstanceVariable_(obj, "_gadget", @GadgetNumber)
Debug "exited [" + Str(GadgetNumber) + "]"
EndProcedure
ProcedureC _mouseMoved_(obj, sel, event)
Protected GadgetNumber.i
object_getInstanceVariable_(obj, "_gadget", @GadgetNumber)
Debug "moved [" + Str(GadgetNumber) + "]"
EndProcedure
;- Create myGadgetTracker class
Procedure InitTracker()
Protected trackerClass.i = objc_allocateClassPair_(objc_getClass_("NSTrackingArea"), "myGadgetTracker", 20)
class_addMethod_(trackerClass, sel_registerName_("mouseEntered:"), @_mouseEntered_(), "v@:@")
class_addMethod_(trackerClass, sel_registerName_("mouseExited:"), @_mouseExited_(), "v@:@")
class_addMethod_(trackerClass, sel_registerName_("mouseMoved:"), @_mouseMoved_(), "v@:@")
CompilerIf SizeOf(Integer) = 8
class_addIvar_(trackerClass, "_gadget", 8, 3, "q"); add .q variable named gadget
CompilerElse
class_addIvar_(trackerClass, "_gadget", 4, 2, "l"); add .l variable named gadget
CompilerEndIf
objc_registerClassPair_(trackerClass)
EndProcedure
InitTracker()
;- TrackGadget procedure
Procedure TrackGadget(GadgetNumber.i)
Protected ZeroRect.NSRect, TA.i = CocoaMessage(0, 0, "myGadgetTracker alloc")
CocoaMessage(0, TA, "initWithRect:@", @ZeroRect, "options:", $643, "owner:", TA, "userInfo:", 0)
object_setInstanceVariable_(TA, "_gadget", GadgetNumber)
CocoaMessage(0, GadgetID(GadgetNumber), "addTrackingArea:", TA)
ProcedureReturn TA
EndProcedure
; *** test ***
OpenWindow(0, 0, 0, 222, 200, "ButtonGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(0, 10, 10, 200, 20, "Standard Button")
ButtonGadget(1, 10, 40, 200, 20, "Left Button", #PB_Button_Left)
ButtonGadget(2, 10, 70, 200, 20, "Right Button", #PB_Button_Right)
ButtonGadget(3, 10,100, 200, 60, "Multiline Button (longer text gets automatically wrapped)", #PB_Button_MultiLine)
ButtonGadget(4, 10,170, 200, 20, "Toggle Button", #PB_Button_Toggle)
TrackGadget(0)
TrackGadget(1)
TrackGadget(2)
TrackGadget(3)
TrackGadget(4)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: Looking for a Cocoa method to replace MoveMove in a Canv
Incredible : works so nice, you really are THE god of Cocoa here !
Again, thank you very much for this very valuable code.
Now it's up to me to incorporate it in my subclassing multi-platform library.
Again, thank you very much for this very valuable code.
Now it's up to me to incorporate it in my subclassing multi-platform library.
Niffo
Re: Looking for a Cocoa method to replace MoveMove in a Canv
Wow, works very well and I would think it would be useful! An interesting example of callbacks.
I note that #PB_Button_MultiLine doesn't work on OS X.
I note that #PB_Button_MultiLine doesn't work on OS X.
MacBook Pro-M1 (2021), Sonoma 14.3.1 (CLT 15.3), PB 6.10b7 M1
Re: Looking for a Cocoa method to replace MoveMove in a Canv
ThanksWilliamL wrote:An interesting example of callbacks.
For me the most interesting part was to figure out how to add an instance variable to a custom class.
Can be quite useful at times.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)