The system supplied text menu works by sending a number of messages like changeFont: modifyFont: and addFontTrait: up the first responder chain until it reaches an NSTextView for example.
I'd like to extend this to control row styles in my NSOutlineView but I have only been able to override changeFont: in my window controller and intercept the message (maybe a better place to do this but it works for now). This works for changing fonts but the other menu items like Bold, Bigger, Smaller which use modifyFont: and addFontTrait: aren't ever getting called in the window controller so I can't modify their behavior to work on the outline view. Interestingly they appear selectable in the menu but only changeFont: is called and as I understand it I need to get a tag value from the NSMenuItem which is the sender of the methods modifyFont: and addFontTrait:.
Does anyone know how to implement this functionality by getting those other methods to be called anywhere? Thanks!
This is documented in the Cocoa Text Architecture Guide: Font Handling – Handling Font Changes. The -addFontTrait:
and -modifyFont:
messages are not sent up the responder chain. They are sent directly to the font manager. The font manager makes a note of the requested modifications and sends -changeFont:
up the responder chain.
You should only need to implement -changeFont:
as you have.
You do not get the tag from the menu item. The font manager does that. That's the source of the information that the font manager records internally.
Your -changeFont:
method should call -convertFont:
on the font manager, passing the current font. That method will return a new font modified as per the recorded change request. You would do that for all the fonts which should be affected. (For example, you might have a selection with multiple fonts in it.)
You do not normally have direct access to the requested modifications, such as "add the Bold trait" or "make the font bigger".
You can customize the font manager by subclassing NSFontManager
and passing your subclass to +[NSFontManager setFontManagerFactory:]
very early in app start-up. In your custom font manager, you can separately track the changes requested by the various action messages like -addFontTrait:
. Here is where you would check the tag
of the sender
. Then, in your outline view you could query the properties of your the sender of -changeFont:
, after verifying that it's an instance of your subclass, to determine what change(s) were requested.
Remember, though, that your custom subclass will be used throughout your app, not just for your outline view. So, your customizations should be in addition to the normal behavior of NSFontManager
, not instead of, so it doesn't break stuff.