Re: Setting key equivalent for menus depending on window
On 20 Oct 2013, at 01:15 am, Kyle Sluder k...@ksluder.com wrote: Rather than rely on intercepting responder chain-based validation, wouldn't it be much easier and more reliable to make some object the delegate of all of your NSMenus and implement -menuNeedsUpdate:? But wouldn’t this object then need to know details about the different windows which are presented in the app in order to decide which shortcut key to set? I have the feeling that the tabbed window (or its delegate) is the place to make changes to the default menu configuration. I think I will try updating the menu in the windowDidBecomeKey/windowDidResignKey calls of the window’s delegate. The thing I don’t like about this is that the delegate (my document subclass) now needs to have a link to the menu items which are created in the main menu nib. I could try ’scanning' for the relevant menu items, maybe searching by tag. Let’s see how far I get with that. Thanks! Martin --Kyle Sluder On Oct 19, 2013, at 1:28 PM, Andy Lee ag...@mac.com wrote: Uli and I both remembered the app delegate is checked *after* the window-related objects in the responder chain, which is what you discovered. I *thought* you could work around this by changing the actions of the Close menu items to methods that only the app delegate implements. But you really don't want to do that, because it'll break any parts of the built-in menu validation that assume performClose: is the action for closing windows. So I propose yet another solution, which may well be, again, flawed. It does not go through validateMenuItem:. The following may seem like a lot of explaining, but it is only a few one- or two-line methods. * Have the app delegate listen for NSWindowDidBecomeMainNotification. * Handle the notification by setting the menu item shortcuts appropriately for the main window. There are different approaches you could take to set the shortcuts appropriately for the window. One way would be to add two category methods on NSWindow, something like + (void)updateShortcutForCloseMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@w]; } + (void)updateShortcutForCloseTabMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@]; } For your window that has tabs, use an NSWindow subclass that overrides these methods: + (void)updateShortcutForCloseMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@W]; } + (void)updateShortcutForCloseTabMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@w]; } Your app delegate could have outlets to the two menu items in question. Then your notification-handling method can be: - (void)handleWindowDidBecomeMainNotification:(NSNotification *)notif { [[[NSApp mainWindow] class] updateShortcutForCloseMenuItem:_closeMenuItem]; [[[NSApp mainWindow] class] updateShortcutForCloseTabMenuItem:_closeTabMenuItem]; } I think the only case this does not handle is when the very last window is closed. You may or may not care what the shortcuts are, since the menu items will be dimmed. If you do care, you can: * Have the app delegate listen for NSWindowDidResignMainNotification. * Handle the notification by first checking whether [NSApp mainWindow] is nil. If so (and *only* if so, for the reason Uli pointed out), set the shortcuts to whatever you want them to be in that case. For example, you could do this (which is why I made those update methods class methods): - (void)handleWindowDidResignMainNotification:(NSNotification *)notif { if ([NSApp mainWindow] == nil) { [NSWindow updateShortcutForCloseMenuItem:_closeMenuItem]; [NSWindow updateShortcutForCloseTabMenuItem:_closeTabMenuItem]; } } --Andy On Oct 19, 2013, at 2:32 PM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: I guess I didn’t understand correctly since my app delegate does not get asked to validate the Close menu item. So far the only thing that get’s asked to validate this is the tabbed window object. Even the window’s delegate is not asked. The documentation states: For document-based applications, the default responder chain for the main window consists of the following responders and delegates: • The main window’s first responder and the successive responder objects up the view hierarchy • The main window itself • The window's NSWindowController object (which inherits from NSResponder) • The main window’s delegate. • The NSDocument object (if different from the main window’s delegate) • The application object, NSApp • The application object's delegate • The application's document controller (an NSDocumentController object, which does not inherit from NSResponder) My NSPersistentDocument subclass is the main window’s delegate. Clearly my thinking is flawed, but where? If I want the Close menu item to vary depending on the window that is key,
Re: Setting key equivalent for menus depending on window
OK, I tried the suggestion to do the update in windowDidBecomeKey and this works nicely with the following (perhaps a little ugly) code: - (void) specialiseCloseMenu:(BOOL)state { NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu]; NSMenu *fileMenu = [[mainMenu itemAtIndex:1] submenu]; NSMenuItem *closeMenuItem = [fileMenu itemWithTag:1090]; NSMenuItem *closeTabMenuItem = [fileMenu itemWithTag:1110]; if (state) { [closeMenuItem setKeyEquivalent:@W]; [closeTabMenuItem setKeyEquivalent:@w]; } else { [closeMenuItem setKeyEquivalent:@w]; [closeTabMenuItem setKeyEquivalent:@]; } } - (void) windowDidBecomeKey:(NSNotification *)notification { [self specialiseCloseMenu:YES]; } - (void) windowDidResignKey:(NSNotification *)notification { [self specialiseCloseMenu:NO]; } Thanks all for your help and thoughts. Cheers, Martin On 20 Oct 2013, at 01:21 pm, Martin Hewitson martin.hewit...@aei.mpg.de wrote: On 20 Oct 2013, at 01:15 am, Kyle Sluder k...@ksluder.com wrote: Rather than rely on intercepting responder chain-based validation, wouldn't it be much easier and more reliable to make some object the delegate of all of your NSMenus and implement -menuNeedsUpdate:? But wouldn’t this object then need to know details about the different windows which are presented in the app in order to decide which shortcut key to set? I have the feeling that the tabbed window (or its delegate) is the place to make changes to the default menu configuration. I think I will try updating the menu in the windowDidBecomeKey/windowDidResignKey calls of the window’s delegate. The thing I don’t like about this is that the delegate (my document subclass) now needs to have a link to the menu items which are created in the main menu nib. I could try ’scanning' for the relevant menu items, maybe searching by tag. Let’s see how far I get with that. Thanks! Martin --Kyle Sluder On Oct 19, 2013, at 1:28 PM, Andy Lee ag...@mac.com wrote: Uli and I both remembered the app delegate is checked *after* the window-related objects in the responder chain, which is what you discovered. I *thought* you could work around this by changing the actions of the Close menu items to methods that only the app delegate implements. But you really don't want to do that, because it'll break any parts of the built-in menu validation that assume performClose: is the action for closing windows. So I propose yet another solution, which may well be, again, flawed. It does not go through validateMenuItem:. The following may seem like a lot of explaining, but it is only a few one- or two-line methods. * Have the app delegate listen for NSWindowDidBecomeMainNotification. * Handle the notification by setting the menu item shortcuts appropriately for the main window. There are different approaches you could take to set the shortcuts appropriately for the window. One way would be to add two category methods on NSWindow, something like + (void)updateShortcutForCloseMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@w]; } + (void)updateShortcutForCloseTabMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@]; } For your window that has tabs, use an NSWindow subclass that overrides these methods: + (void)updateShortcutForCloseMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@W]; } + (void)updateShortcutForCloseTabMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@w]; } Your app delegate could have outlets to the two menu items in question. Then your notification-handling method can be: - (void)handleWindowDidBecomeMainNotification:(NSNotification *)notif { [[[NSApp mainWindow] class] updateShortcutForCloseMenuItem:_closeMenuItem]; [[[NSApp mainWindow] class] updateShortcutForCloseTabMenuItem:_closeTabMenuItem]; } I think the only case this does not handle is when the very last window is closed. You may or may not care what the shortcuts are, since the menu items will be dimmed. If you do care, you can: * Have the app delegate listen for NSWindowDidResignMainNotification. * Handle the notification by first checking whether [NSApp mainWindow] is nil. If so (and *only* if so, for the reason Uli pointed out), set the shortcuts to whatever you want them to be in that case. For example, you could do this (which is why I made those update methods class methods): - (void)handleWindowDidResignMainNotification:(NSNotification *)notif { if ([NSApp mainWindow] == nil) { [NSWindow updateShortcutForCloseMenuItem:_closeMenuItem]; [NSWindow updateShortcutForCloseTabMenuItem:_closeTabMenuItem]; } } --Andy On Oct 19, 2013, at 2:32 PM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: I guess I didn’t understand correctly since my app delegate does not get asked to validate the Close menu item. So far the only thing
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 4:21 AM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: On 20 Oct 2013, at 01:15 am, Kyle Sluder k...@ksluder.com wrote: Rather than rely on intercepting responder chain-based validation, wouldn't it be much easier and more reliable to make some object the delegate of all of your NSMenus and implement -menuNeedsUpdate:? But wouldn’t this object then need to know details about the different windows which are presented in the app in order to decide which shortcut key to set? No. That's what protocols are for, either formal or informal. @implementation MyAppDelegate @synthesize _closeMenuItem, _closeAllMenuItem; - (void)menuNeedsUpdate:(NSMenu *)menu { // First, set the default shortcuts in case the main window is unwilling or unable _closeMenuItem.keyEquivalent = @w; _closeAllMenuItem.keyEquivalent = @; // Let the main window muck with the key equivalents if appropriate id mainWindowDelegate = [[NSApp mainWindow] delegate]; if ([delegate respondsToSelector:@selector(updateCloseMenuItem:closeAllMenuItem:)]) [delegate updateCloseMenuItem:_closeMenuItem closeAllMenuItem:_closeAllMenuItem]; } If you want to be super-fancy, you could take a hint from NSFontManager and send an “update menus” message down the responder chain, but I prefer the simplicity of this approach. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 2:02 PM, Kyle Sluder k...@ksluder.com wrote: On Oct 20, 2013, at 4:21 AM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: On 20 Oct 2013, at 01:15 am, Kyle Sluder k...@ksluder.com wrote: Rather than rely on intercepting responder chain-based validation, wouldn't it be much easier and more reliable to make some object the delegate of all of your NSMenus and implement -menuNeedsUpdate:? But wouldn’t this object then need to know details about the different windows which are presented in the app in order to decide which shortcut key to set? No. That's what protocols are for, either formal or informal. @implementation MyAppDelegate @synthesize _closeMenuItem, _closeAllMenuItem; - (void)menuNeedsUpdate:(NSMenu *)menu { // First, set the default shortcuts in case the main window is unwilling or unable _closeMenuItem.keyEquivalent = @w; _closeAllMenuItem.keyEquivalent = @; // Let the main window muck with the key equivalents if appropriate id mainWindowDelegate = [[NSApp mainWindow] delegate]; if ([delegate respondsToSelector:@selector(updateCloseMenuItem:closeAllMenuItem:)]) [delegate updateCloseMenuItem:_closeMenuItem closeAllMenuItem:_closeAllMenuItem]; } If you want to be super-fancy, you could take a hint from NSFontManager and send an “update menus” message down the responder chain, but I prefer the simplicity of this approach. -menuNeedsUpdate: has the same problem that -validateMenuItem: has. It doesn't get called until the menu is about to be actually drawn, which doesn't happen until the user clicks on your menu. This is inadequate for what the OP wants to do, because he is setting keyboard shortcuts, which are supposed to be used without accessing the menu. If the shortcuts aren't updated until the menu is drawn, the keyboard shortcuts will not work at program start, which is irritating. They could also very easily get out of sync with the interface, if the following sequence of events occurs: 1. User clicks on the File menu while there are no tabs open. ⌘-W is mapped to Close Window. 2. User switches to a window that has a bunch of tabs, but never clicks on the File menu, so ⌘-W is still mapped to Close Window. 3. User hits ⌘-W, intending to close one tab. Surprise! He just closed the whole window instead. Needless to say, this does not provide a good experience to your users. Charles ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 2:29 PM, Charles Srstka wrote: -menuNeedsUpdate: has the same problem that -validateMenuItem: has. It doesn't get called until the menu is about to be actually drawn, which doesn't happen until the user clicks on your menu. This isn't correct. Menus are updated/validated when resolving keyboard shortcuts. What makes you think otherwise? Lots of things wouldn't work if that weren't so. This is inadequate for what the OP wants to do, because he is setting keyboard shortcuts, which are supposed to be used without accessing the menu. If the shortcuts aren't updated until the menu is drawn, the keyboard shortcuts will not work at program start, which is irritating. They could also very easily get out of sync with the interface, if the following sequence of events occurs: 1. User clicks on the File menu while there are no tabs open. ⌘-W is mapped to Close Window. 2. User switches to a window that has a bunch of tabs, but never clicks on the File menu, so ⌘-W is still mapped to Close Window. 3. User hits ⌘-W, intending to close one tab. Surprise! He just closed the whole window instead. Needless to say, this does not provide a good experience to your users. Which is why Cocoa doesn't work that way. Regards, Ken ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 12:37 PM, Ken Thomases k...@codeweavers.com wrote: On Oct 20, 2013, at 2:29 PM, Charles Srstka wrote: -menuNeedsUpdate: has the same problem that -validateMenuItem: has. It doesn't get called until the menu is about to be actually drawn, which doesn't happen until the user clicks on your menu. This isn't correct. Menus are updated/validated when resolving keyboard shortcuts. What makes you think otherwise? Lots of things wouldn't work if that weren't so. Well, the docs are surprisingly quite explicit: “Invoked when a menu is about to be displayed at the start of a tracking session so the delegate can modify the menu.” But, as you state, I know that menus update themselves for key equivalent processing. I’m not near my Mac, so I can’t verify that -menuNeedsUpdate: is called in that scenario, or only the lazy-population methods. --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 14:38, Ken Thomases k...@codeweavers.com wrote: This isn't correct. Menus are updated/validated when resolving keyboard shortcuts. What makes you think otherwise? Lots of things wouldn't work if that weren't so. For what it's worth, Cocoa's key equiv updating doesn't always work perfectly. We've had problems here and there that required creative and brute force workarounds. Just a heads-up for those doing non-trivial key equiv management. Steve via iPad ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 2:37 PM, Ken Thomases k...@codeweavers.com wrote: On Oct 20, 2013, at 2:29 PM, Charles Srstka wrote: -menuNeedsUpdate: has the same problem that -validateMenuItem: has. It doesn't get called until the menu is about to be actually drawn, which doesn't happen until the user clicks on your menu. This isn't correct. Menus are updated/validated when resolving keyboard shortcuts. What makes you think otherwise? Lots of things wouldn't work if that weren't so. Huh, I just tested this, and you're right. I stand corrected. However, this appears to be undocumented behavior, since the documentation clearly states that this is supposed to be invoked when the menu is being displayed: https://developer.apple.com/library/Mac/documentation/Cocoa/Reference/NSMenuDelegate_Protocol/Reference/Reference.html#//apple_ref/doc/uid/TP40008605-CH1-SW14 menuNeedsUpdate: Invoked when a menu is about to be displayed at the start of a tracking session so the delegate can modify the menu. - (void)menuNeedsUpdate:(NSMenu *)menu Parameters menu The menu object that is about to be displayed. Given that this behavior is not guaranteed by the documentation, I'm not sure that it should be relied on. Charles ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 2:46 PM, Mills, Steve smi...@makemusic.com wrote: On Oct 20, 2013, at 14:38, Ken Thomases k...@codeweavers.com wrote: This isn't correct. Menus are updated/validated when resolving keyboard shortcuts. What makes you think otherwise? Lots of things wouldn't work if that weren't so. For what it's worth, Cocoa's key equiv updating doesn't always work perfectly. We've had problems here and there that required creative and brute force workarounds. Just a heads-up for those doing non-trivial key equiv management. I've played around with this a bit more, using the standard Xcode non-document app template, and its behavior is actually quite weird. 1. Typing a keyboard shortcut that's connected to one of the items currently in the menu works as you would expect. menuNeedsUpdate: gets called each time you type the shortcut. Typing ⌘-O repeatedly causes menuNeedsUpdate: to repeatedly fire, since the Open menu item has that shortcut (even though it's inactive). 2. However, shortcuts that are not connected to any menu item, like ⌘-E or ⌘-R, only cause menuNeedsUpdate: to fire the *first* time you type them. After you've typed one of them once, typing that shortcut again, *or any other invalid shortcut for that matter*, just causes the system to beep, and menuNeedsUpdate: is *not* fired. 3. Now here's where it gets weird: Typing ⌘-T of course brings up the Font panel like it always does, and causes menuNeedsUpdate: to fire each time it does so. *However*, if you type an invalid shortcut like ⌘-E or ⌘-R beforehand, subsequently typing ⌘-T will *not* cause menuNeedsUpdate: to fire, and it will never fire again for that shortcut until you actually click on a menu to cause it to draw. 4. Oddly enough, the keystroke combo ⌘-shift-W seems to have some kind of special immunity to this behavior, since it seems to repeatedly cause menuNeedsUpdate: to fire regardless of whether another invalid shortcut has been pressed. However, I *really* wouldn't want to be relying on this behavior, myself, particularly given that the shortcut could theoretically be different for different localizations, and could conceivably fall on one of the update once, ignore after keyboard shortcuts. 5. Validation definitely does *not* fire for unmapped keyboard shortcuts. It only fires if the keyboard shortcut in question is already mapped to an item that performs an action on the object which called validateMenuItem:, so I stand by my statement that validation will not work adequately for this purpose. Charles ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 2:50 PM, Charles Srstka wrote: On Oct 20, 2013, at 2:37 PM, Ken Thomases k...@codeweavers.com wrote: On Oct 20, 2013, at 2:29 PM, Charles Srstka wrote: -menuNeedsUpdate: has the same problem that -validateMenuItem: has. It doesn't get called until the menu is about to be actually drawn, which doesn't happen until the user clicks on your menu. This isn't correct. Menus are updated/validated when resolving keyboard shortcuts. What makes you think otherwise? Lots of things wouldn't work if that weren't so. Huh, I just tested this, and you're right. I stand corrected. However, this appears to be undocumented behavior, since the documentation clearly states that this is supposed to be invoked when the menu is being displayed: https://developer.apple.com/library/Mac/documentation/Cocoa/Reference/NSMenuDelegate_Protocol/Reference/Reference.html#//apple_ref/doc/uid/TP40008605-CH1-SW14 menuNeedsUpdate: Invoked when a menu is about to be displayed at the start of a tracking session so the delegate can modify the menu. - (void)menuNeedsUpdate:(NSMenu *)menu Parameters menu The menu object that is about to be displayed. Given that this behavior is not guaranteed by the documentation, I'm not sure that it should be relied on. Well, you're right about the documentation (although it says it will be called when the menu is about to be display, not that it won't be called under other circumstances). However, I will refer you to a WWDC video I've referenced before on this list: WWDC 2010 Session 145 - Key Event Handling in Cocoa Applications. It mentions -menuNeedsUpdate: being called around the 7:55 mark. It states it's called prior to display, for keyboard shortcut resolution, for accessibility, and for the Search field in the Help menu. (I wouldn't necessarily assume it's limited to those occasions, either.) Regards, Ken ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 3:14 PM, Charles Srstka cocoa...@charlessoft.com wrote: 5. Validation definitely does *not* fire for unmapped keyboard shortcuts. It only fires if the keyboard shortcut in question is already mapped to an item that performs an action on the object which called validateMenuItem:, so I stand by my statement that validation will not work adequately for this purpose. I meant to say which implements validateMenuItem: here. Argh. Charles ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 7:21 AM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: On 20 Oct 2013, at 01:15 am, Kyle Sluder k...@ksluder.com wrote: Rather than rely on intercepting responder chain-based validation, wouldn't it be much easier and more reliable to make some object the delegate of all of your NSMenus and implement -menuNeedsUpdate:? But wouldn’t this object then need to know details about the different windows which are presented in the app in order to decide which shortcut key to set? That's why in my later proposal (using notifications rather than delegation or responder-chain stuff) I added category methods to NSWindow, with default behavior that you can override in the window that contains tabs. The app delegate does know about the category methods, but it just sends messages to windows, it doesn't have any knowledge of what shortcuts are appropriate for which window. Rather, each window knows its own shortcuts. I have the feeling that the tabbed window (or its delegate) is the place to make changes to the default menu configuration. I think I will try updating the menu in the windowDidBecomeKey/windowDidResignKey calls of the window’s delegate. I see by your follow-up that it seems to work, so I'm just tossing out my additional two cents here. The thing I don’t like about this is that the delegate (my document subclass) now needs to have a link to the menu items which are created in the main menu nib. That is another reason I like my later proposal. The app delegate is in MainMenu.nib, so you can create outlets from it directly to the menu items. --Andy ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Sun, Oct 20, 2013, at 01:14 PM, Charles Srstka wrote: I've played around with this a bit more, using the standard Xcode non-document app template, and its behavior is actually quite weird. 1. Typing a keyboard shortcut that's connected to one of the items currently in the menu works as you would expect. menuNeedsUpdate: gets called each time you type the shortcut. Typing ⌘-O repeatedly causes menuNeedsUpdate: to repeatedly fire, since the Open menu item has that shortcut (even though it's inactive). 2. However, shortcuts that are not connected to any menu item, like ⌘-E or ⌘-R, In the default non-document template, ⌘E maps to Edit Find Use Selection for Find. only cause menuNeedsUpdate: to fire the *first* time you type them. After you've typed one of them once, typing that shortcut again, *or any other invalid shortcut for that matter*, just causes the system to beep, and menuNeedsUpdate: is *not* fired. This describes the behavior for key equivalents for disabled menu items as well as key combinations that don't map to menu items. 3. Now here's where it gets weird: Typing ⌘-T of course brings up the Font panel like it always does, and causes menuNeedsUpdate: to fire each time it does so. *However*, if you type an invalid shortcut like ⌘-E or ⌘-R beforehand, subsequently typing ⌘-T will *not* cause menuNeedsUpdate: to fire, and it will never fire again for that shortcut until you actually click on a menu to cause it to draw. This leads me to believe that NSMenu is populating the menu hierarchy once and caching a mapping of key equivalents to menu items. Which is unfortunate, and goes against the implication from the 10.6 AppKit release notes that menus are fully repopulated once per event. So I filed a bug: rdar://problem/15274535 (NSMenu does not ask its delegate to populate the menu for every key equivalent) If you try to get around this by implementing -menuHasKeyEquivalent:forEvent:target:action:, things get weirder still: - This method is called for every potential key equivalent. This would be useful, except: - Even if you return NO, NSMenu still looks for a menu item with that key equivalent and invokes its action, in direct violation of the documentation for this method. I cannot reconcile this behavior with the documentation or the intended behavior of the frameworks at all, so I filed another bug: rdar://problem/15274476 (NSMenu performs key equivalent despite delegate's insistence). --Kyle Sluder ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 20, 2013, at 6:37 PM, Kyle Sluder k...@ksluder.com wrote: 2. However, shortcuts that are not connected to any menu item, like ⌘-E or ⌘-R, In the default non-document template, ⌘E maps to Edit Find Use Selection for Find. Ah, hadn't seen that. How about ⌘R? only cause menuNeedsUpdate: to fire the *first* time you type them. After you've typed one of them once, typing that shortcut again, *or any other invalid shortcut for that matter*, just causes the system to beep, and menuNeedsUpdate: is *not* fired. This describes the behavior for key equivalents for disabled menu items as well as key combinations that don't map to menu items. Not necessarily. It doesn't behave this way for ⌘O, which is disabled in the default non-document template, for instance. Charles ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Setting key equivalent for menus depending on window
Dear list, I have an app with tabs and I’m trying to change the default 'close' keyboard equivalent for only the main window which has the tabs. I’d like to have Main Window with tabs: close (cmd-shift-w) close tab (cmd-w) All other windows: close (cmd-w) close tab (inactive, no keyboard shortcut) This is pretty much the way things work in Xcode. So, my question is, is there a smart way to do this, or do I need to implement -validateMenuItem: on every window in the app and set the keyboard shortcuts there? Thanks for any insights, Martin ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 19, 2013, at 6:58 AM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: Main Window with tabs: close (cmd-shift-w) close tab (cmd-w) All other windows: close (cmd-w) close tab (inactive, no keyboard shortcut) This is pretty much the way things work in Xcode. So, my question is, is there a smart way to do this, or do I need to implement -validateMenuItem: on every window in the app and set the keyboard shortcuts there? Untested idea: implement windowDidBecomeKey: and windowDidResignKey: in the delegate of the window that has tabs and do the switching of shortcuts there. If you want to be extra careful you could have two ivars that remember what the shortcuts were before you changed them to cmd-shift-w and cmd-w. Then in windowDidResignKey: plug those shortcuts in rather than hard-code cmd-w and @. --Andy ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On 19 Oct 2013, at 14:27, Andy Lee ag...@mac.com wrote: On Oct 19, 2013, at 6:58 AM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: Main Window with tabs: close (cmd-shift-w) close tab (cmd-w) All other windows: close (cmd-w) close tab (inactive, no keyboard shortcut) This is pretty much the way things work in Xcode. So, my question is, is there a smart way to do this, or do I need to implement -validateMenuItem: on every window in the app and set the keyboard shortcuts there? Untested idea: implement windowDidBecomeKey: and windowDidResignKey: in the delegate of the window that has tabs and do the switching of shortcuts there. Would rather recommend against this. I don’t think there’s any guarantee given what gets called first, validateMenuItem: or windowDidResignKey:. You might be obliterating something already set by the incoming window. If you want to be extra careful you could have two ivars that remember what the shortcuts were before you changed them to cmd-shift-w and cmd-w. Then in windowDidResignKey: plug those shortcuts in rather than hard-code cmd-w and @“”. Also, while I’m not aware of any localization that doesn’t use Cmd-W for close, it’s in general a good idea to keep your shortcuts localizable (e.g. on a German keyboard, there’s no way to type Cmd-~, because it has no ~-key, so window rotation is done using Cmd- there). I’d recommend adding a validateMenuItem: handler in the application delegate, as long as you’re aware that this won’t be called for modal panels or windows that have sheets on them, but since those generally don’t enable the “Close” menu item, you should be fine. At least then you’re modifying the items. Also, I’m not sure whether menu shortcut disambiguation lets you do that, but have you tried hiding and showing menu items with the same names but different shortcuts instead of actually changing the items’ shortcut? I.e. create your menu as Close Cmd-Shift-W - -performCloseForTabbedWindow: Close Cmd-W - -performClose: Close TabCmd-W - -performCloseTab: Close Tab - -performCloseTabDummy: And then hide/show the “tab” items? That way, localization would be easier, and you’re not hard-coding any shortcuts. Though that doesn’t solve the issue of properly restoring the items after you’ve hidden them. Cheers, -- Uli Kusterer “The Witnesses of TeachText are everywhere...” http://zathras.de ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 19, 2013, at 8:46 AM, Uli Kusterer witness.of.teacht...@gmx.net wrote: On 19 Oct 2013, at 14:27, Andy Lee ag...@mac.com wrote: On Oct 19, 2013, at 6:58 AM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: Main Window with tabs: close (cmd-shift-w) close tab (cmd-w) All other windows: close (cmd-w) close tab (inactive, no keyboard shortcut) This is pretty much the way things work in Xcode. So, my question is, is there a smart way to do this, or do I need to implement -validateMenuItem: on every window in the app and set the keyboard shortcuts there? Untested idea: implement windowDidBecomeKey: and windowDidResignKey: in the delegate of the window that has tabs and do the switching of shortcuts there. Would rather recommend against this. I don’t think there’s any guarantee given what gets called first, validateMenuItem: or windowDidResignKey:. You might be obliterating something already set by the incoming window. True. I’d recommend adding a validateMenuItem: handler in the application delegate, as long as you’re aware that this won’t be called for modal panels or windows that have sheets on them, but since those generally don’t enable the “Close” menu item, you should be fine. At least then you’re modifying the items. My first thought was that the app delegate might not get a validateMenuItem: message if something earlier in the responder chain handles those menu items. But you could change the actions of the menu items to something unique to make sure nothing else in the responder chain handles them. --Andy ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On 19 Oct 2013, at 15:04, Andy Lee ag...@mac.com wrote: My first thought was that the app delegate might not get a validateMenuItem: message if something earlier in the responder chain handles those menu items. But you could change the actions of the menu items to something unique to make sure nothing else in the responder chain handles them. Drat. Good point. Cheers, -- Uli Kusterer “The Witnesses of TeachText are everywhere...” http://zathras.de ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 19, 2013, at 9:04 AM, Andy Lee ag...@mac.com wrote: My first thought was that the app delegate might not get a validateMenuItem: message if something earlier in the responder chain handles those menu items. But you could change the actions of the menu items to something unique to make sure nothing else in the responder chain handles them. You could also change the *target* of the menu items to the app delegate instead of First Responder, and then it wouldn't matter what the action selectors are. --Andy ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
OK, so the idea is, + validateMenuItem in app delegate gets a first shot at setting the keyboard shortcuts + I override validateMenuItem in my tabbed window and reset the keyboard shortcuts + Other windows stick with the settings arranged by the app delegate Did I understand correctly? Thanks to all who replied. Cheers, Martin On 19, Oct, 2013, at 02:46 pm, Uli Kusterer witness.of.teacht...@gmx.net wrote: On 19 Oct 2013, at 14:27, Andy Lee ag...@mac.com wrote: On Oct 19, 2013, at 6:58 AM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: Main Window with tabs: close (cmd-shift-w) close tab (cmd-w) All other windows: close (cmd-w) close tab (inactive, no keyboard shortcut) This is pretty much the way things work in Xcode. So, my question is, is there a smart way to do this, or do I need to implement -validateMenuItem: on every window in the app and set the keyboard shortcuts there? Untested idea: implement windowDidBecomeKey: and windowDidResignKey: in the delegate of the window that has tabs and do the switching of shortcuts there. Would rather recommend against this. I don’t think there’s any guarantee given what gets called first, validateMenuItem: or windowDidResignKey:. You might be obliterating something already set by the incoming window. If you want to be extra careful you could have two ivars that remember what the shortcuts were before you changed them to cmd-shift-w and cmd-w. Then in windowDidResignKey: plug those shortcuts in rather than hard-code cmd-w and @“”. Also, while I’m not aware of any localization that doesn’t use Cmd-W for close, it’s in general a good idea to keep your shortcuts localizable (e.g. on a German keyboard, there’s no way to type Cmd-~, because it has no ~-key, so window rotation is done using Cmd- there). I’d recommend adding a validateMenuItem: handler in the application delegate, as long as you’re aware that this won’t be called for modal panels or windows that have sheets on them, but since those generally don’t enable the “Close” menu item, you should be fine. At least then you’re modifying the items. Also, I’m not sure whether menu shortcut disambiguation lets you do that, but have you tried hiding and showing menu items with the same names but different shortcuts instead of actually changing the items’ shortcut? I.e. create your menu as Close Cmd-Shift-W - -performCloseForTabbedWindow: Close Cmd-W - -performClose: Close TabCmd-W - -performCloseTab: Close Tab - -performCloseTabDummy: And then hide/show the “tab” items? That way, localization would be easier, and you’re not hard-coding any shortcuts. Though that doesn’t solve the issue of properly restoring the items after you’ve hidden them. Cheers, -- Uli Kusterer “The Witnesses of TeachText are everywhere...” http://zathras.de Martin Hewitson Albert-Einstein-Institut Max-Planck-Institut fuer Gravitationsphysik und Universitaet Hannover Callinstr. 38, 30167 Hannover, Germany Tel: +49-511-762-17121, Fax: +49-511-762-5861 E-Mail: martin.hewit...@aei.mpg.de WWW: http://www.aei.mpg.de/~hewitson ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
I guess I didn’t understand correctly since my app delegate does not get asked to validate the Close menu item. So far the only thing that get’s asked to validate this is the tabbed window object. Even the window’s delegate is not asked. The documentation states: For document-based applications, the default responder chain for the main window consists of the following responders and delegates: The main window’s first responder and the successive responder objects up the view hierarchy The main window itself The window's NSWindowController object (which inherits from NSResponder) The main window’s delegate. The NSDocument object (if different from the main window’s delegate) The application object, NSApp The application object's delegate The application's document controller (an NSDocumentController object, which does not inherit from NSResponder) My NSPersistentDocument subclass is the main window’s delegate. Clearly my thinking is flawed, but where? If I want the Close menu item to vary depending on the window that is key, and I have to do this with validateMenuItem:, then the responder chain above seems to suggest that I need to have a validateMenuItem: in each and every window in the app. I hope that’s not the case…. Martin On 19 Oct 2013, at 07:28 pm, Martin Hewitson martin.hewit...@aei.mpg.de wrote: OK, so the idea is, + validateMenuItem in app delegate gets a first shot at setting the keyboard shortcuts + I override validateMenuItem in my tabbed window and reset the keyboard shortcuts + Other windows stick with the settings arranged by the app delegate Did I understand correctly? Thanks to all who replied. Cheers, Martin On 19, Oct, 2013, at 02:46 pm, Uli Kusterer witness.of.teacht...@gmx.net wrote: On 19 Oct 2013, at 14:27, Andy Lee ag...@mac.com wrote: On Oct 19, 2013, at 6:58 AM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: Main Window with tabs: close (cmd-shift-w) close tab (cmd-w) All other windows: close (cmd-w) close tab (inactive, no keyboard shortcut) This is pretty much the way things work in Xcode. So, my question is, is there a smart way to do this, or do I need to implement -validateMenuItem: on every window in the app and set the keyboard shortcuts there? Untested idea: implement windowDidBecomeKey: and windowDidResignKey: in the delegate of the window that has tabs and do the switching of shortcuts there. Would rather recommend against this. I don’t think there’s any guarantee given what gets called first, validateMenuItem: or windowDidResignKey:. You might be obliterating something already set by the incoming window. If you want to be extra careful you could have two ivars that remember what the shortcuts were before you changed them to cmd-shift-w and cmd-w. Then in windowDidResignKey: plug those shortcuts in rather than hard-code cmd-w and @“”. Also, while I’m not aware of any localization that doesn’t use Cmd-W for close, it’s in general a good idea to keep your shortcuts localizable (e.g. on a German keyboard, there’s no way to type Cmd-~, because it has no ~-key, so window rotation is done using Cmd- there). I’d recommend adding a validateMenuItem: handler in the application delegate, as long as you’re aware that this won’t be called for modal panels or windows that have sheets on them, but since those generally don’t enable the “Close” menu item, you should be fine. At least then you’re modifying the items. Also, I’m not sure whether menu shortcut disambiguation lets you do that, but have you tried hiding and showing menu items with the same names but different shortcuts instead of actually changing the items’ shortcut? I.e. create your menu as Close Cmd-Shift-W - -performCloseForTabbedWindow: Close Cmd-W - -performClose: Close TabCmd-W - -performCloseTab: Close Tab - -performCloseTabDummy: And then hide/show the “tab” items? That way, localization would be easier, and you’re not hard-coding any shortcuts. Though that doesn’t solve the issue of properly restoring the items after you’ve hidden them. Cheers, -- Uli Kusterer “The Witnesses of TeachText are everywhere...” http://zathras.de Martin Hewitson Albert-Einstein-Institut Max-Planck-Institut fuer Gravitationsphysik und Universitaet Hannover Callinstr. 38, 30167 Hannover, Germany Tel: +49-511-762-17121, Fax: +49-511-762-5861 E-Mail: martin.hewit...@aei.mpg.de WWW: http://www.aei.mpg.de/~hewitson Martin Hewitson Albert-Einstein-Institut Max-Planck-Institut fuer Gravitationsphysik und Universitaet Hannover Callinstr. 38, 30167 Hannover, Germany Tel: +49-511-762-17121, Fax: +49-511-762-5861 E-Mail:
Re: Setting key equivalent for menus depending on window
On Oct 19, 2013, at 1:32 PM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: I guess I didn’t understand correctly since my app delegate does not get asked to validate the Close menu item. So far the only thing that get’s asked to validate this is the tabbed window object. Even the window’s delegate is not asked. The documentation states: For document-based applications, the default responder chain for the main window consists of the following responders and delegates: The main window’s first responder and the successive responder objects up the view hierarchy The main window itself The window's NSWindowController object (which inherits from NSResponder) The main window’s delegate. The NSDocument object (if different from the main window’s delegate) The application object, NSApp The application object's delegate The application's document controller (an NSDocumentController object, which does not inherit from NSResponder) My NSPersistentDocument subclass is the main window’s delegate. Clearly my thinking is flawed, but where? If I want the Close menu item to vary depending on the window that is key, and I have to do this with validateMenuItem:, then the responder chain above seems to suggest that I need to have a validateMenuItem: in each and every window in the app. I hope that’s not the case…. https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/MenuList/Articles/EnablingMenuItems.html • If the menu item’s target is set, then NSMenu first checks to see if that object implements the item’s action method. If it does not, then the item is disabled. If the target does implement the item’s action method, NSMenu first checks to see if that object implements validateMenuItem: or validateUserInterfaceItem: method. If it does not, then the menu item is enabled. If it does, then the enabled status of the menu item is determined by the return value of the method. • If the menu item’s target is not set (that is, if it is nil—typically if the menu item is connected to First Responder) and the NSMenu object is not a contextual menu, then NSMenu uses the responder chain (described in “The Responder Chain” in Cocoa Event Handling Guide) to determine the target. If there is no object in the responder chain that implements the item’s action, the item is disabled. If there is an object in the responder chain that implements the item’s action, NSMenu then checks to see if that object implements the validateMenuItem:orvalidateUserInterfaceItem: method. If it does not, then the menu item is enabled. If it does, then the enabled status of the menu item is determined by the return value of the method. Key phrase in both cases: implements the item's action. If your Close menu item has an action method of performClose:, then any object (target or in the responder chain) must implement that action method before it will be asked to validate the menu item. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On 19, Oct, 2013, at 08:59 pm, Michael Babin mba...@orderndev.com wrote: On Oct 19, 2013, at 1:32 PM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: I guess I didn’t understand correctly since my app delegate does not get asked to validate the Close menu item. So far the only thing that get’s asked to validate this is the tabbed window object. Even the window’s delegate is not asked. The documentation states: For document-based applications, the default responder chain for the main window consists of the following responders and delegates: The main window’s first responder and the successive responder objects up the view hierarchy The main window itself The window's NSWindowController object (which inherits from NSResponder) The main window’s delegate. The NSDocument object (if different from the main window’s delegate) The application object, NSApp The application object's delegate The application's document controller (an NSDocumentController object, which does not inherit from NSResponder) My NSPersistentDocument subclass is the main window’s delegate. Clearly my thinking is flawed, but where? If I want the Close menu item to vary depending on the window that is key, and I have to do this with validateMenuItem:, then the responder chain above seems to suggest that I need to have a validateMenuItem: in each and every window in the app. I hope that’s not the case…. https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/MenuList/Articles/EnablingMenuItems.html • If the menu item’s target is set, then NSMenu first checks to see if that object implements the item’s action method. If it does not, then the item is disabled. If the target does implement the item’s action method, NSMenu first checks to see if that object implements validateMenuItem: or validateUserInterfaceItem: method. If it does not, then the menu item is enabled. If it does, then the enabled status of the menu item is determined by the return value of the method. • If the menu item’s target is not set (that is, if it is nil—typically if the menu item is connected to First Responder) and the NSMenu object is not a contextual menu, then NSMenu uses the responder chain (described in “The Responder Chain” in Cocoa Event Handling Guide) to determine the target. If there is no object in the responder chain that implements the item’s action, the item is disabled. If there is an object in the responder chain that implements the item’s action, NSMenu then checks to see if that object implements the validateMenuItem:orvalidateUserInterfaceItem: method. If it does not, then the menu item is enabled. If it does, then the enabled status of the menu item is determined by the return value of the method. Key phrase in both cases: implements the item's action. If your Close menu item has an action method of performClose:, then any object (target or in the responder chain) must implement that action method before it will be asked to validate the menu item. This I understand, but I'm still unclear on the logical route I should take to ensure that my tabbed window's delegate is asked to validate the Close menu but for all other windows the app delegate is asked. Should I then implement performClose: in my app delegate? I can implement it in my document subclass because it can just send the action on to the document window. (I recall actually trying that earlier today but still the delegate was no asked to validate Close, which led me to implement a window subclass to intercept the validation there. If I've understood correctly, the document subclass should get the validation request if it has implemented performClose:, right?) But what about in the app delegate? Just an empty performClose:? OK, I'll do some more thinking here and run some more tests to understand the various cases. Thanks! Martin Martin Hewitson Albert-Einstein-Institut Max-Planck-Institut fuer Gravitationsphysik und Universitaet Hannover Callinstr. 38, 30167 Hannover, Germany Tel: +49-511-762-17121, Fax: +49-511-762-5861 E-Mail: martin.hewit...@aei.mpg.de WWW: http://www.aei.mpg.de/~hewitson ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
On Oct 19, 2013, at 12:28 PM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: OK, so the idea is, + validateMenuItem in app delegate gets a first shot at setting the keyboard shortcuts + I override validateMenuItem in my tabbed window and reset the keyboard shortcuts + Other windows stick with the settings arranged by the app delegate Did I understand correctly? validateMenuItem: isn't going to work. It only gets called when the menu item in question is revealed, usually by the user clicking on the menu containing it. You can verify this yourself by putting a log in validateMenuItem: and seeing when it gets logged. Presumably, you want your shortcuts to work even if the user hasn't clicked on any of the menus yet, which means you want to set them somewhere other than validateMenuItem:. I'd probably go with the windowDid(Become)|(Resign)Key: methods myself. Unless the menu is somehow displayed at the same time as the window's focus is changing, windowDidResignKey: and validateMenuItem: shouldn't be part of the same session (other than if the window lost focus because the user selected Close from the menu bar, but in that case validateMenuItem: would be called before the item was even selected). It's possible that there could be some scenario that I'm overlooking, though, in which case someone will hopefully chime in. Charles ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Setting key equivalent for menus depending on window
Uli and I both remembered the app delegate is checked *after* the window-related objects in the responder chain, which is what you discovered. I *thought* you could work around this by changing the actions of the Close menu items to methods that only the app delegate implements. But you really don't want to do that, because it'll break any parts of the built-in menu validation that assume performClose: is the action for closing windows. So I propose yet another solution, which may well be, again, flawed. It does not go through validateMenuItem:. The following may seem like a lot of explaining, but it is only a few one- or two-line methods. * Have the app delegate listen for NSWindowDidBecomeMainNotification. * Handle the notification by setting the menu item shortcuts appropriately for the main window. There are different approaches you could take to set the shortcuts appropriately for the window. One way would be to add two category methods on NSWindow, something like + (void)updateShortcutForCloseMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@w]; } + (void)updateShortcutForCloseTabMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@]; } For your window that has tabs, use an NSWindow subclass that overrides these methods: + (void)updateShortcutForCloseMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@W]; } + (void)updateShortcutForCloseTabMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@w]; } Your app delegate could have outlets to the two menu items in question. Then your notification-handling method can be: - (void)handleWindowDidBecomeMainNotification:(NSNotification *)notif { [[[NSApp mainWindow] class] updateShortcutForCloseMenuItem:_closeMenuItem]; [[[NSApp mainWindow] class] updateShortcutForCloseTabMenuItem:_closeTabMenuItem]; } I think the only case this does not handle is when the very last window is closed. You may or may not care what the shortcuts are, since the menu items will be dimmed. If you do care, you can: * Have the app delegate listen for NSWindowDidResignMainNotification. * Handle the notification by first checking whether [NSApp mainWindow] is nil. If so (and *only* if so, for the reason Uli pointed out), set the shortcuts to whatever you want them to be in that case. For example, you could do this (which is why I made those update methods class methods): - (void)handleWindowDidResignMainNotification:(NSNotification *)notif { if ([NSApp mainWindow] == nil) { [NSWindow updateShortcutForCloseMenuItem:_closeMenuItem]; [NSWindow updateShortcutForCloseTabMenuItem:_closeTabMenuItem]; } } --Andy On Oct 19, 2013, at 2:32 PM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: I guess I didn’t understand correctly since my app delegate does not get asked to validate the Close menu item. So far the only thing that get’s asked to validate this is the tabbed window object. Even the window’s delegate is not asked. The documentation states: For document-based applications, the default responder chain for the main window consists of the following responders and delegates: • The main window’s first responder and the successive responder objects up the view hierarchy • The main window itself • The window's NSWindowController object (which inherits from NSResponder) • The main window’s delegate. • The NSDocument object (if different from the main window’s delegate) • The application object, NSApp • The application object's delegate • The application's document controller (an NSDocumentController object, which does not inherit from NSResponder) My NSPersistentDocument subclass is the main window’s delegate. Clearly my thinking is flawed, but where? If I want the Close menu item to vary depending on the window that is key, and I have to do this with validateMenuItem:, then the responder chain above seems to suggest that I need to have a validateMenuItem: in each and every window in the app. I hope that’s not the case…. Martin On 19 Oct 2013, at 07:28 pm, Martin Hewitson martin.hewit...@aei.mpg.de wrote: OK, so the idea is, + validateMenuItem in app delegate gets a first shot at setting the keyboard shortcuts + I override validateMenuItem in my tabbed window and reset the keyboard shortcuts + Other windows stick with the settings arranged by the app delegate Did I understand correctly? Thanks to all who replied. Cheers, Martin On 19, Oct, 2013, at 02:46 pm, Uli Kusterer witness.of.teacht...@gmx.net wrote: On 19 Oct 2013, at 14:27, Andy Lee ag...@mac.com wrote: On Oct 19, 2013, at 6:58 AM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: Main Window with tabs: close (cmd-shift-w) close tab (cmd-w) All other windows: close (cmd-w) close tab (inactive, no
Re: Setting key equivalent for menus depending on window
Rather than rely on intercepting responder chain-based validation, wouldn't it be much easier and more reliable to make some object the delegate of all of your NSMenus and implement -menuNeedsUpdate:? --Kyle Sluder On Oct 19, 2013, at 1:28 PM, Andy Lee ag...@mac.com wrote: Uli and I both remembered the app delegate is checked *after* the window-related objects in the responder chain, which is what you discovered. I *thought* you could work around this by changing the actions of the Close menu items to methods that only the app delegate implements. But you really don't want to do that, because it'll break any parts of the built-in menu validation that assume performClose: is the action for closing windows. So I propose yet another solution, which may well be, again, flawed. It does not go through validateMenuItem:. The following may seem like a lot of explaining, but it is only a few one- or two-line methods. * Have the app delegate listen for NSWindowDidBecomeMainNotification. * Handle the notification by setting the menu item shortcuts appropriately for the main window. There are different approaches you could take to set the shortcuts appropriately for the window. One way would be to add two category methods on NSWindow, something like + (void)updateShortcutForCloseMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@w]; } + (void)updateShortcutForCloseTabMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@]; } For your window that has tabs, use an NSWindow subclass that overrides these methods: + (void)updateShortcutForCloseMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@W]; } + (void)updateShortcutForCloseTabMenuItem:(NSMenuItem *)menuItem { [menuItem setKeyEquivalent:@w]; } Your app delegate could have outlets to the two menu items in question. Then your notification-handling method can be: - (void)handleWindowDidBecomeMainNotification:(NSNotification *)notif { [[[NSApp mainWindow] class] updateShortcutForCloseMenuItem:_closeMenuItem]; [[[NSApp mainWindow] class] updateShortcutForCloseTabMenuItem:_closeTabMenuItem]; } I think the only case this does not handle is when the very last window is closed. You may or may not care what the shortcuts are, since the menu items will be dimmed. If you do care, you can: * Have the app delegate listen for NSWindowDidResignMainNotification. * Handle the notification by first checking whether [NSApp mainWindow] is nil. If so (and *only* if so, for the reason Uli pointed out), set the shortcuts to whatever you want them to be in that case. For example, you could do this (which is why I made those update methods class methods): - (void)handleWindowDidResignMainNotification:(NSNotification *)notif { if ([NSApp mainWindow] == nil) { [NSWindow updateShortcutForCloseMenuItem:_closeMenuItem]; [NSWindow updateShortcutForCloseTabMenuItem:_closeTabMenuItem]; } } --Andy On Oct 19, 2013, at 2:32 PM, Martin Hewitson martin.hewit...@aei.mpg.de wrote: I guess I didn’t understand correctly since my app delegate does not get asked to validate the Close menu item. So far the only thing that get’s asked to validate this is the tabbed window object. Even the window’s delegate is not asked. The documentation states: For document-based applications, the default responder chain for the main window consists of the following responders and delegates: • The main window’s first responder and the successive responder objects up the view hierarchy • The main window itself • The window's NSWindowController object (which inherits from NSResponder) • The main window’s delegate. • The NSDocument object (if different from the main window’s delegate) • The application object, NSApp • The application object's delegate • The application's document controller (an NSDocumentController object, which does not inherit from NSResponder) My NSPersistentDocument subclass is the main window’s delegate. Clearly my thinking is flawed, but where? If I want the Close menu item to vary depending on the window that is key, and I have to do this with validateMenuItem:, then the responder chain above seems to suggest that I need to have a validateMenuItem: in each and every window in the app. I hope that’s not the case…. Martin On 19 Oct 2013, at 07:28 pm, Martin Hewitson martin.hewit...@aei.mpg.de wrote: OK, so the idea is, + validateMenuItem in app delegate gets a first shot at setting the keyboard shortcuts + I override validateMenuItem in my tabbed window and reset the keyboard shortcuts + Other windows stick with the settings arranged by the app delegate Did I understand correctly? Thanks to all who replied. Cheers, Martin On 19, Oct, 2013, at 02:46 pm, Uli Kusterer witness.of.teacht...@gmx.net wrote: On