Включение пунктов меню

По умолчанию каждый раз пользовательское событие происходит, NSMenu автоматически включает и отключает каждый видимый пункт меню. Можно также вынудить меню обновить использование NSMenu update метод.

Существует два способа включить меню:

Для выбора системы использовать NSMenu setAutoenablesItems: с параметром YES (для автоматического включения меню) или NO (для ручного включения меню). Автоматическое включение меню идет по умолчанию.

Автоматическое включение меню

Когда Вы используете автоматическое включение меню, NSMenu обновляет состояние каждого пункта меню каждый раз, когда происходит пользовательское событие. Обновить состояние пункта меню, NSMenu сначала определяет цель элемента и затем определяет, реализует ли цель validateMenuItem: или validateUserInterfaceItem: (в том порядке). Более подробно:

Реализация проверки

Как отмечено выше, прежде чем это будет выведено на экран, пункт меню проверяет, чтобы видеть, реализует ли его цель validateMenuItem: или validateUserInterfaceItem:. Если это делает, то включенное состояние пункта меню определяется возвращаемым значением метода. Можно поэтому условно включить или отключить пункт меню путем реализации любого из этих методов в цели меню (см. Выбор validateMenuItem: или validateUserInterfaceItem: определить, который является самым надлежащим). Стратегия реализации является тем же, какой бы ни Вы выбираете:

  1. Чтобы решить, должен ли элемент быть включен, необходимо знать то, что он сделает, если пользователь выбирает его. Вы обычно сначала поэтому проверяете для наблюдения, какое действие связано с элементом (необходимо протестировать на каждое из действий, Вы интересуетесь).

    При проверке действия, а не, скажем, заголовок удостоверяется что: (a) Ваш код работает с различными локализациями и устойчив против изменений в заголовке вследствие изменений в пользовательском интерфейсе и (b), Вы избегаете хрупкости необходимости не забыть использовать тот же тег для каждого элемента пользовательского интерфейса, вызывающего тот же метод на цель. (В случае validateUserInterfaceItem:, можно только проверить действие или тег.)

  2. Если действие - что-то, что Вы интересуетесь, то возвращаете булево значение, подходящее для текущего контекста.

  3. Если действие не что-то, что Вы интересуетесь, то также:

    1. Если Ваш суперкласс реализует метод проверки (например, NSDocument и NSObjectController реализация validateUserInterfaceItem:, и NSObjectController реализации validateMenuItem:), вызовите реализацию super; иначе

    2. Возвратите значение по умолчанию YES указать, что Вы обрабатываете метод проверки, даже если Вы не реализуете действие.

Следующий пример иллюстрирует реализацию validateUserInterfaceItem: в подклассе NSDocument.

- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem
{
    SEL theAction = [anItem action];
 
    if (theAction == @selector(copy:)) {
        if ( /* there is a current selection and it is copyable */ )
        {
            return YES;
        }
        return NO;
    }
    else {
        if (theAction == @selector(paste:)) {
            if ( /* there is a something on the pasteboard we can use and
                the user interface is in a configuration in which it makes sense to paste */ ) {
                return YES;
            }
            return NO;
        }
        else {
        /* check for other relevant actions ... */
        }
    }
    // Subclass of NSDocument, so invoke super's implementation
    return [super validateUserInterfaceItem:anItem];
}

Выбор validateMenuItem: или validateUserInterfaceItem:

Обычно необходимо использовать validateUserInterfaceItem: вместо validateMenuItem: потому что прежний будет также работать на элементы панели инструментов, имеющие ту же цель и действие. Если, однако, существует дополнительная работа, которую Вы хотите выполнить, который является определенным для пункта меню, использовать validateMenuItem:— например, validateMenuItem: также хорошее место, чтобы переключить заголовки или установить состояние на пунктах меню, чтобы удостовериться, что они всегда корректны.

Вот пример использования validateUserInterfaceItem: переопределять автоматическое включение. Если Ваше приложение имеет пункт меню Copy, отправляющий copy: сообщение действия первому респонденту, тому пункту меню автоматически включают любое время объект, отвечающий на copy:, такой как NSText возразите, первый респондент ключевого или главного окна. При создании класса, экземпляры которого могли бы стать первым респондентом, и не поддерживающего копирование всего, что оно позволяет пользователю выбирать, необходимо реализовать validateUserInterfaceItem: в том классе. validateUserInterfaceItem: должен тогда возвратиться NO если элементы, которые не могут быть скопированы, выбраны (или если никакие элементы не выбраны), и YES если могут быть скопированы все элементы в выборе. Путем реализации validateUserInterfaceItem::, можно было отключить пункт меню Copy даже при том, что целевой объект действительно реализует copy: метод. Если класс никогда не разрешает копировать, то Вы просто опускаете реализацию copy: в том классе и пункте меню Copy отключен автоматически каждый раз, когда экземпляр того класса является первым респондентом.

Ручное включение меню

При использовании ручного включения меню Вы используете setEnabled: включить или отключить каждый пункт меню индивидуально. Ни один из пунктов меню, даже те, которыми управляют классы Набора Приложения как NSTextView, обновляются автоматически.

Для включения ручного включения меню использовать NSMenu setAutoenablesItems: с параметром NO.