同步显示非模态模板选择器

时间:2012-02-20 02:59:16

标签: cocoa nsdocument

我正在使用文档架构编写Cocoa应用程序。每当在此应用程序中创建无标题文档时,应向用户显示一个窗口,让他们选择模板并提示其他信息。这些窗口中只有一个应该一次显示,并且最好在模板选择器可见时应该可以与应用程序的其余部分进行交互。 (这就是Pages的行为方式。)

我通过覆盖-[NSDocumentController openUntitledDocumentAndDisplay:error:]来完成大部分工作:

- (id)openUntitledDocumentAndDisplay:(BOOL)displayDocument 
                               error:(NSError *__autoreleasing *)outError {
    TsDocument * doc = [self makeUntitledDocumentOfType:self.defaultType 
                                                  error:outError];
    if(!doc) {
        return nil;
    }

    TsNewWindowController * newController = [TsNewWindowController new];
    newController.document = doc;

    if([NSApp runModalForWindow:newController.window] == NSRunAbortedResponse) {
        if(outError) {
            *outError = [NSError errorWithDomain:NSCocoaErrorDomain 
                                            code:NSUserCancelledError 
                                       userInfo:nil];
        }
        return nil;
    }

    [self addDocument:doc];

    if(displayDocument) {
        [doc makeWindowControllers];
        [doc showWindows];
    }

    return doc;
}

但是,正如您所看到的,窗口以模态方式显示,阻止访问应用程序的其余部分。有没有一种简单的方法可以实现我想要的而不需要模板选择模式?


更清楚地解释一些事情:

  1. 我当然知道-runModalForWindow:将以模态方式运行窗口 - 它就在名称中!我正在寻找另一种方式来显示仍会阻止-openUntitledDocumentAndDisplay:error:的窗口,或者根本不需要我阻止该方法。

  2. 我认为我不能简单地创建文档,显示newController的窗口,并稍后调用文档的makeWindowControllersshowWindows因为,如果应用程序退出,恢复不会显示模板选择器 - 它显示正常的编辑界面。

2 个答案:

答案 0 :(得分:4)

您需要创建并使用NSWindowController,但在调用openUntitledDocument…::之前需要这样做。

在未发行的Adium Xtras Creator中,我点了几点:

  • 在应用程序的委托中,在applicationOpenUntitledFile:中,我会显示模板选择窗口并返回YES
  • 在文档控制器的removeDocument:中,我将消息传递给super,然后检查是否仍有任何文档打开。如果没有,我会显示模板选择窗口。
  • 在文档控制器的addDocument:中,我隐藏了模板选择窗口,然后传递给super

因此:

  • 如果用户尝试以任何方式创建新文档(没有特定类型),则会显示模板选择器。
  • 如果用户以任何方式创建新文档(显式类型),模板选择器将被隐藏。 (我执行此操作的应用程序将其“新建”菜单项设置为包含特定类型的子菜单。)
  • 如果用户以任何方式打开任何文档,模板选择器将被隐藏。
  • 如果用户关闭上一个打开的文档,则会显示模板选择器。
  • 如果用户或其他应用程序尝试以任何方式重新打开应用程序,则会显示模板选择器。

答案 1 :(得分:1)

您正在调用runModalForWindow:,因此当然它正在将窗口作为模态窗口运行。

为什么不直接显示窗口?使用NSWindowController并调用showWindow:以显示模板窗口。在窗口控制器中,实现对用户选择做出反应的操作,然后创建相应的文档(或取消)。

我认为您不需要在openUntitledDocumentAndDisplay:error:中实际创建文档。