Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble using custom modal sheet with Cocoa

My objective: Display a custom sheet with a determinate NSProgressIndicator while the app works through a lengthy loop. I want the sheet to be application-modal, not document-modal. The user cannot dismiss the modal sheet. They must wait for the app to finish processing the loop.

Problem: I can't get the custom sheet to attach to the window. It appears as a separate window lacking the window title bar (as a sheet should). Additionally, the sheet is not released (does not close) when the loop finishes.

I have 2 separate nib files for the sheet and main application window, and also 2 controller classes for each window.

Here's the pertinent information: Controller implementation for the custom sheet:

@implementation ProgressSheetController //subclass of NSPanel

-(void)showProgressSheet:(NSWindow *)window
{
    //progressPanel is an IBOutlet to the NSPanel
    if(!progressPanel)
        [NSBundle loadNibNamed:@"ProgressPanel" owner:self];

    [NSApp beginSheet: progressPanel
       modalForWindow: window
        modalDelegate: nil
       didEndSelector: nil
          contextInfo: nil];

    //modalSession is an instance variable
    modalSession = [NSApp beginModalSessionForWindow:progressPanel];

    [NSApp runModalSession:modalSession];
}

-(void)removeProgressSheet
{
    [NSApp endModalSession:modalSession];
    [NSApp endSheet:progressPanel];
    [progressPanel orderOut:nil];
}

//some other methods 
@end

Implementation for the main application window. testFiles method is an IBAction connected to a button.

@implementation MainWindowViewController //subclass of NSObject

-(IBAction)testFiles:(id)sender;
{
    //filesToTest is a mutable array instance variable
    int count = [filesToTest count];

    float progressIncrement = 100.0 / count;

    ProgressSheetController *modalProgressSheet = [[ProgressSheetController alloc] init];
    [modalProgressSheet showProgressSheet:[NSApp mainWindow]];

    int i,
    for(i=0; i<count; i++)
    {
        //do some stuff with the object at index i in the filesToTest array

        //this method I didn't show in ProgressSheetController.m but I think it's self explanatory
        [modalProgressSheet incrementProgressBarBy:progressIncrement];
    }
    //tear down the custom progress sheet
    [modalProgressSheet removeProgressSheet];
    [modalProgressSheet release];
}
@end

One thought: Am I subclassing correctly? Should I use NSWindowController instead? Thank you in advance for your help!

like image 474
David Nix Avatar asked Dec 06 '22 01:12

David Nix


1 Answers

Found this gem doing some googling. The behavior for my NSPanel in Interface Builder was set to "Visible at Launch" which is the default for new windows when using IB. What happened was as soon as the nib was loaded, the window was made visible BEFORE [NSApp beginSheet:...]. Therefore, unchecking the "Visible at Launch" option solved my problem and now a sheet appears connected to the window like I want.

like image 71
David Nix Avatar answered Dec 19 '22 06:12

David Nix