Question

My app has an 'inspector' panel defined by a .xib file and a custom window controller class: AdjustmentsWindow.xib and AdjustmentsWindowController.m.

I want to have a Window -> Show Adjustments menu item in the application's main menu bar, that when selected will show the adjustments window. I dropped and NSObject instance into the xib containing the main menu, and changed its class to "AdjustmentsWindowController". I also hooked the menu item's action to the controller's -showWindow: method. So far so good: The window controller is instanced on app launch, and when you select the menu item it shows its window.

But I want the same menu item to double as 'Hide Adjustments' when the window is already visible (effectively toggling visibility). So here is what I did:

AdjustmentsWindowController.m:

- (void) windowDidLoad
{
    [super windowDidLoad];    
    [[self window] setDelegate:self];
}

- (void) showWindow:(id)sender
{
    // (Sent by 'original' menu item or 'restored' menu item)

    [super showWindow:sender];

    // Modify menu item:

    NSMenuItem* item = (NSMenuItem*) sender;
    [item setTitle:@"Hide Adjustments"];
    [item setAction:@selector(hideWindow:)];
}


- (void) hideWindow:(id) sender
{
    // (Sent by 'modified' menu item)

    NSMenuItem* item = (NSMenuItem*) sender;

    // Modify back to original state:

    [item setTitle:@"Show Adjustments"];
    [item setAction:@selector(showWindow:)];
    [self close];
}

- (void) windowWillClose:(NSNotification *)notification
{
    // (Sent when user manually closes window)

    NSMenu* menu = [[NSApplication sharedApplication] mainMenu];

    // Find menu item and restore to its original state

    NSMenuItem* windowItem = [menu itemWithTitle:@"Window"];
    if ([windowItem hasSubmenu]) {
        NSMenu* submenu = [windowItem submenu];
        NSMenuItem* item = [submenu itemWithTitle:@"Hide Adjustments"];
        [item setTitle:@"Show Adjustments"];
        [item setAction:@selector(showWindow:)];
    }
}

My question is, is this the right/smartest/most elegant way to achieve this? I mean, this is pretty standard behaviour in cocoa apps (cf. Numbers' "Inspector"), how does everyone else do it?

One way to improve it would be to avoid the code duplication of restoring the menu item to its original title/action. Also, ideally I would replace the title strings with calls to NSLocalizedString(). But perhaps there's a more elegant, standard approach that I don't know...

Was it helpful?

Solution

Application Menu and Pop-up List Programming Topics said

validateMenuItem: is also a good place to toggle titles or set state on menu items to make sure they're always correct.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top