Как имитировать автоматическое создание вкладки в окне macOS с нажатой клавишей Option?

Поведение по умолчанию: клавиша option вызывает вкладку

У меня есть приложение для macOS, основанное на документах, с пользовательским файлом NSDocumentController. Приложение может обрабатывать два типа документов, каждый со своими окнами и представлениями.

Теперь, если пользователь отключил возможность всегда создавать вкладки в окнах, cmd-N всегда будет создавать новое окно.

И если пользователь вводит cmd-option-N, платформа автоматически создает вкладку внутри переднего окна, независимо от глобальных предпочтений или настроек вкладок приложения. Это не требует дополнительного программирования с моей стороны.

Все идет нормально.

Теперь у меня есть тип документа вторичный, созданный cmd-shift-N. Это создает, благодаря моему пользовательскому DocumentController, новое окно каждый раз, как и ожидалось.

Задача: добиться того же с дополнительным модификатором

Я хочу, чтобы пользователь мог ввести cmd-shift-option-N, чтобы создать новую вкладку внутри существующего окна документа, точно так же, как cmd-option-N для основного типа документа.

Однако кажется, что фреймворк обрабатывает только простой cmd-option-N для автоматического создания вкладок. Для других комбинаций модификаторов (как здесь, со сдвигом) это не работает: если я настроил меню только для cmd-shift-N, то при нажатии cmd-shift-option-N будет просто звуковой сигнал. И если я добавлю явное меню для cmd-shift-option-N, оно создаст новое окно, а не вкладку, как хотелось бы.

Поэтому мне нужно подражать поведению превращения нового документа во вкладку, а не в новое окно. Как мне это сделать, если глобальная вкладка больше настроена на то, чтобы не создавать вкладки?


person Thomas Tempelmann    schedule 20.05.2021    source источник


Ответы (1)


Методом проб и ошибок я пришел к следующему решению.

Для этого требуется подкласс NSDocument, назовем его CustomDocument.

В нем я добавляю флаг, который контролирует, хочу ли я добавить новое окно в качестве вкладки:

@interface CustomDocument : NSDocument
   @property BOOL foceIntoTab;
@end

Затем мне нужно реализовать собственный обработчик для создания оконного контроллера, в котором я сначала определяю, есть ли уже окно, к которому я бы добавил другое, затем создаю новый контроллер и, наконец, добавляю его как вкладку:

- (void)makeWindowControllers // override
{
    __block NSWindow *frontWindow = nil;
    if (self.forceIntoTab) {
        // Find the topmost window that's of my document type
        [NSApp enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack usingBlock:^(NSWindow *window, BOOL *stop) {
            if ([window.windowController.document isKindOfClass:CustomDocument.class]) {
                frontWindow = window;
                *stop = YES;
            }
        }];
    }

    NSWindowController *windowController = [[NSStoryboard storyboardWithName:@"Main" bundle:nil] instantiateControllerWithIdentifier:@"Custom Controller"];

    if (frontWindow) {
        [frontWindow.tabGroup addWindow:windowController.window];
        [windowController.window orderFront:frontWindow];
        [windowController.window makeKeyWindow];
    }

    NSViewController *viewController = windowController.contentViewController;
    [viewController setRepresentedObject:self];
    [self addWindowController:windowController];
}

Осталось установить forceIntoTab при создании нового окна через строку меню. Я мог бы сделать это, например, в своем собственном классе DocumentController:

- (nullable __kindof NSDocument *)makeUntitledDocumentOfType:(NSString *)typeName error:(NSError **)outError // override
{
    CustomDocument *doc = [super makeUntitledDocumentOfType:typeName error:outError];
    doc.forceIntoTab = YES;
    return doc;
}
person Thomas Tempelmann    schedule 20.05.2021
comment
Новые документы всегда добавляются в виде вкладки? Как вы поймаете ключ option? - person Willeke; 20.05.2021
comment
@Willeke Я не понимаю вашу первую часть вопроса. Для второй части я добавляю альтернативный пункт меню, который использует клавишу выбора в ярлыке и с собственным обработчиком действий. - person Thomas Tempelmann; 21.05.2021