3

I'd like to draw a proper, modern animated focus ring around a control, which according to Q&A 1785, should be a simple matter of overriding the -drawFocusRingMask and -focusRingMaskBounds methods.

Trouble is, for this project I have to use Xojo, which can declare and invoke Cocoa methods, but doesn't give me any opportunity to actually create my own view subclass.

So, is there any way to get a proper focus ring without making an actual subclass? Some other methods, perhaps introduced after this 10.7 tech note, that get the job done? Or some sneaky way to inject a method into an existing class at runtime?

Joe Strout
  • 2,634
  • 2
  • 28
  • 39
  • Can Xojo use libobjc functions, like [`class_addMethod()`](https://developer.apple.com/documentation/objectivec/1418901-class_addmethod?language=objc) (← clickable)? – hidefromkgb Nov 08 '17 at 16:37
  • Is that for a custom Cocoa control you've added? I believe if you do this through the MBS plugins, then you can also switch the NSControl's focusRing property without having to do what you're planning. I've done this in my own apps a few times. – Thomas Tempelmann Nov 08 '17 at 17:12
  • It's to get a focus ring around a TextArea control. Hoping to avoid the need for the MBS plugins. – Joe Strout Nov 09 '17 at 14:05

1 Answers1

2

As one comment suggested, class_addMethod() would be right if you want to add an optional protocol method. The public macoslib project has some code that shows how to do that, just search for that name.

However, if the function is already implemented, then you cannot add another. In that case method swizzling is the solution. It's a common method to replace a selector'd function address with another, and then call the original one.

I don't seem to have an example in Xojo for that at hand, though.

Update

For standard Cocoa controls the simplest solution is to set the NSView property focusRingType accordingly (available in macoslib). Implementing drawFocusRingMask is only necessary for custom controls.

Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149
  • This sounds promising, but so far I can't get it to work. I was able to call class_addMethod on the class of the TextArea (which incidentally is called XOJScrollView), and add both drawFocusRingMask and focusRingMaskBounds with implementations as shown in the Q&A, but I still don't get a focus ring. – Joe Strout Nov 09 '17 at 15:26
  • I also tried reaching deeper into the view hierarchy (XOJScrollView contains an NSClipView which contains a XOJTextView; and XOJScrollView also contains an NSScroller), and adding these methods to XOJTextView. Again the adds were successful, but still no focus rings appear. – Joe Strout Nov 09 '17 at 15:50
  • Confirmed that, in this case, setting focusRingType was sufficient. I was laboring under the mistaken belief that it would not work in this case. – Joe Strout Nov 10 '17 at 18:31