Question

I am using a very simple custom view (containing only a read-only NSTextField and an NSSegmentedControl) in an NSMenuItem (using the -setView: method). This part works as expected.

Here's the problem: in the -menuNeedsUpdate: NSMenu delegate method I'm conditionally hiding the menu item. When I call [item setHidden:YES], the menu item with a custom view doesn't hide, but other 'vanilla' menu items do.

My custom view is built in its own XIB, and I'm accessing it through a custom NSViewController.

Update

The menu item stays visible even if I check the Hidden checkbox in Interface Builder, and remove the line where it's hidden in code.

Update 2

I also tried setting hidden on the custom view before and after setting hidden on the menu item. The result is as if the menu item is not hidden, but the view is; the view's controls aren't visible, but there is still a gap where they should be.

Update 3

I modified Apple's MenuItemView sample code to hide one of the menu items after it's added (insert [menuItem setHidden:YES]; at line 87), and it has the same effect as in my code (which is to say, none).

I'm starting to think the only way to hide this menu item will be to set its view to nil when I need to hide it and put it back when I need to show it, but it doesn't seem that should be necessary.

Update 4

Using Mike's answer below, here is the code I'm using:

// Declared in the header file
IBOutlet NSMenuItem *previousMenuItem;
IBOutlet NSMenuItem *togglingMenuItem; //Needs to be RETAINED

. . .

- (void)menuNeedsUpdate:(NSMenu *)menu {
    BOOL hideItem = YES; // Some criteria, obviously

    // Remove the menu item, if it was already present
    if ([menu indexOfItem:togglingMenuItem] >= 0) {
        [menu removeItem:togglingMenuItem];
    }

    // Put it back if it should be visible
    if (!onePageVisible) {
        [menu insertItem:togglingMenuItem
                 atIndex:[menu indexOfItem:previousMenuItem] + 1];
    }
}
Was it helpful?

Solution

Rather than hiding an item, can you remove/re-add as needed?

 [rootMenu removeItemAtIndex: 23];

OTHER TIPS

I had to override NSMenuItem's setHidden: method and set the view's height to zero if hidden, like so:

- (void) setHidden:(BOOL)flag {

[super setHidden:flag];

NSView *view = [self view];
[view setHidden:flag];

// if our view is hidden, give it a zero height so it won't draw at all
if (flag)
    [view setFrameSize:NSMakeSize([view frame].size.width, 0)];
else {

    [view setFrameSize:NSMakeSize([view frame].size.width, [self menuItemHeight])];
}

}

In menu delegate method menu:updateItem:atIndex:shouldCancel: i find my custom view menu item by tag and set it's view to nil if it is hidden or assign custom view if visible:

- (BOOL)menu:(NSMenu *)menu 
    updateItem:(NSMenuItem *)item 
    atIndex:(NSInteger)index 
    shouldCancel:(BOOL)shouldCancel
{

    if ([item tag] == CUSTOM_VIEW_TAG)
    {
        [item setView:[item isHidden]?nil:customView];
        return NO; //we've done our dirty work
    }

    return YES;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top