AddHandler does not work or gives a syntax error

Hello,

I have these codes in a TextArea subclass:
Sub Open()
AddHandler me.NSTextViewMBS.shouldChangeTextInRange,AddressOf ShouldChangeTextInRange
End Sub
Sub Close()
RemoveHandler self.NSTextViewMBS.shouldChangeTextInRange,AddressOf ShouldChangeTextInRange
End Sub
Public Function ShouldChangeTextInRange(tv As NSTextViewMBS, Range As NSRangeMBS, Replacement As String) as Boolean
Return True
End Function

When I run this code, I get two possible behaviours:
•Either a compile error stating “Syntax error” at the AddHandler and RemoveHandler lines
•Or no compile error (app launches fine); AddHandler is executed but the method is never called. The RemoveHandler call then throws a RuntimeException (“RemoveHandler has not been added with AddHandler”).
I can’t predict which one of these cases happens, the IDE seems confused.

NSTextViewMBS is a property of the TextArea, coming from the MBS plugin. It has 2 events, shouldChangeTextInRange being one of them.
What’s wrong with this?

Looks really unsuspicious. Just to be sure: You are putting this into #If TargetMacOS pragma directives, aren’t you (or compiling just for macOS)?
And what Xojo version (and MBS plugins) are you using?

Indeed, enclosed in #if targetMacOS and debugged on MacOS (for the moment).
MBS version 19.5 and Xojo 2019 2.1.
Thanks.

Ah! I think what I missed is that you don’t buffer the NSTextViewMBS. It possibly gets out of scope. What happens if you store it in your subclass?

Good guess. Now, I get no error with RemoveHandler, so the handler has indeed been registered; one good point.
The method is never called though…
Thanks!

After checking the original class in Apple‘s docs, I am not sure if what you try is possible that easily. ShouldReplaceTextInRange is a NSTextView delegate method, not really part of the TextView class.
Xojo uses custom subclasses which define own delegate methods.
NSTextViewMBS is meant to be placed inside a NSView(MBS) programmatically, not as a full „typecast“ into the XojTextView in terms of the delegate methods. It is another NSTextView subclass.

I think you either have to change your custom control to use a programmatically created MBS class instead of the Xojo control or change the delegate of the Xojo control to a custom class which forwards the „Event“ delegate method calls to its original instance.

[quote=465945:@Ulrich Bogun]After checking the original class in Apple‘s docs, I am not sure if what you try is possible that easily. ShouldReplaceTextInRange is a NSTextView delegate method, not really part of the TextView class.
Xojo uses custom subclasses which define own delegate methods.
NSTextViewMBS is meant to be placed inside a NSView(MBS) programmatically, not as a full „typecast“ into the XojTextView in terms of the delegate methods. It is another NSTextView subclass.

I think you either have to change your custom control to use a programmatically created MBS class instead of the Xojo control or change the delegate of the Xojo control to a custom class which forwards the „Event“ delegate method calls to its original instance.[/quote]
I think I don’t fully understand this, although your explanation looks to be correct.
So, based on what I’ve understood, I’ve checked whether the NSTextView object belongs to the text field using this:
me.NSTextViewMBS.insertionPointColor=NSColorMBS.greenColor
This works, so clearly the problem is at the delegate level; the class is correctly linked to its TextArea.

I’ve already used delegates, so I understand the principle; my problem is certainly related to the hierarchy of controls in the Cocoa world… This is a new area (no pun intended) to me, as, usually, Xojo protects us against under-the-hood implementation…
Anyway… About the 2 solutions you give, the latter looks better; I don’t know if/how Xojo would allow to create a TextArea based on a plugin class. Even if I knew, the RAD point would be lost. However, I’m not sure what you mean by “change a delegate to a custom class”. You mean I should subclass the delegate class?

Thank you.

Not meaning to question your words, just because we could be talking different things:
With “you had been working with delegates”, do you mean the Xojo definition of it? Or declaring into the macOS system, creating a custom class (either based on NSObject or the control class) that does the delegate work?

Some explanations if the first is valid:
In Apple terms a delegate class is a pure virtual class: Just a collection of methods that work in conjunction with a control class. macOS and iOS classes using a delegate do have a delegate property. So in Xcode you would not use events but create a custom delegate class that does the event handling for your project, and assign it to the control’s delegate property.

In Xojo it usually does rarely make sense to use such a declared class by itself but rather include the delegate methods into a custom declared control class and set its delegate property to itself. On the Xojo side the delegate methods can fire events to make your class fully customizable.

Xojo’s TextField and TextArea allow text replacements, which very probably means the XojTextField/View classes already implement the delegate methods, while their classes are using NSTextView as their super class.
NSTextViewMBS does so too, else it would not give you the events it features. It is a different subclass of NSTextView, a cousin of Xojo’s TextArea, sharing the same parent but not connected otherwise.
So casting a NSTextViewMBS to a Xojo TextArea gives you access to all the features that both classes share = all the NSTextView features. But it will not turn a Xojo TextArea into a NSTextViewMBS = the events will not fire because the Xojo subclass defined them differently already.

If you are not used to macOS declares, I would rather advise to take route 1. @Christian Schmitz put a lot of examples into his plugins, and you will find some for custom controls using his classes. Yes, it is not fully RAD, but I would estimate this to be the faster solution.

[quote=466037:@Ulrich Bogun]Not meaning to question your words, just because we could be talking different things:
With “you had been working with delegates”, do you mean the Xojo definition of it? Or declaring into the macOS system, creating a custom class (either based on NSObject or the control class) that does the delegate work?[/quote]
No problem in asking :wink:
I mean the Xojo definition.
In the past, I’ve dealt with Mac OS declares, but they were Carbon ones, a very different thing.

Kind of using AddHandler for an event that already had AddHandler called upon, I’m following you correctly?
So, it would be advisable to ask for either of these in Xojo:
•Allow a custom NSTextView in the constructor, to add more properties/methods/events;
•Have the additional events that the NSTextView provides available in Xojo’s AddEvent window (called from the Xojo’s own event declaration).
Correct?

I think I already looked at the examples. I’ll do that again.
As for not being used to Cocoa declares, I can learn :wink:

Thank you.

If you have the MBS MacCocoa plugin installed, you should be able to drag an NSTextViewControl to your window from the Library. It doesn’t look as nice in the IDE as the Xojo TextArea and the inspector doesn’t have much, but it does allow you to add event handlers in the IDE. And you can access all the NSTextView stuff in me.view

Great; indeed NSTextViewControl is in the list and the events are called! I’ll play with it to make customisations like the TextArea version (mandatory for Linux and Windows); at that point, I’m not sure I’ll have identical functions in both objects, but it sounds promising.

Thank you!