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 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 Tab    Cmd-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: 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

Reply via email to