Sheets implement window modal (as opposed to application modal) dialogs that are attached to the window. Thus, when a dialog pops up asking for attention, it blocks interaction only with that particular window, not the entire application. When a sheet is opened or closed, it appears to slide out of the title bar. Because the sheet is attached to another window, such as a document window, the user never loses track of what dialog belongs with which window. Figure 3-8 shows an example of a sheet.
The Application Kit defines a number of convenient functions for displaying standard alert and message sheets, including NSBeginAlertSheet, NSBegin-InformationalAlertSheet, and NSBeginCriticalAlertSheet. Each function takes the same parameters; they differ only in the icon displayed on the left of the sheet. The function prototype for NSBeginAlertSheet is the following:
void NSBeginAlertSheet(NSString *title, NSString *defaultButton, NSString *alternateButton, NSString *otherButton, NSWindow *docWindow, id modalDelegate, SEL didEndSelector, SEL didDismissSelector, void *contextInfo, NSString *msg, ...)
Table 3-2 describes each parameter.
Parameter |
Description |
---|---|
Title |
The title of the sheet, displayed at the top of the sheet in bold-faced font. |
defaultButton |
The title of the sheet's default button, generally "OK". Passing nil or an empty string will give a localized default button title (i.e., "OK" in English). |
alternateButton |
The title of the sheet's alternate button, such as "Don't Save," that appears on the left side of the sheet when three buttons are present. Passing nil causes this button to not be created. |
otherButton |
Title for a third button, such as "Cancel", that appears in the middle. Passing nil causes this button to not be created. |
docWindow |
The window to which the sheet is attached. |
modalDelegate |
The object that handles user interaction with the sheet. |
didEndSelector |
A selector of the method implemented by the modal delegate that will be invoked when the modal session is ended, but before the sheet is dismissed. |
didDismissSelector |
Selector of the method implemented by the modal delegate is invoked after the sheet is dismissed. This may be NULL if you don't want to end a didDismissSelector. |
contextInfo |
Pointer to additional data to be passed to didEndSelector or didDismissSelector. |
msg |
A printf formatted message to be displayed in the sheet. Optional printf-style arguments may follow the message. |
An alert similar to the one in Figure 3-8 can be created with a call to NSBeginInformationalAlertSheet, as shown in Example 3-2.
NSBeginInformationalAlertSheet( @"Do you want to save changes to \ this document before closing?" @"Save", @"Don't Save", @"Cancel", mainWindow, self, @selector(sheetDidEnd:returnCode:contextInfo:), NULL, NULL, @"If you don't save, your changes will be lost.");
You can display any window as a sheet by using APIs provided by NSApplication. To display a sheet, invoke the following method:
beginSheet:modalForWindow: modalDelegate:didEndSelector:contextInfo:
The first argument, beginSheet:, is the NSWindow we wish to display as a sheet. The modalForWindow: argument specifies the window to which the sheet is attached. Since application execution continues while a sheet is open, the sheet uses a modal delegate to handle user interaction. This delegate is assigned in the modalDelegate: argument. The callback method is indicated in didEndSelector: and has the following signature:
- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo;
In this method, contextInfo: is the object passed in the NSApplication method used to open the sheet. It is used to optionally pass arbitrary information between the creator of the sheet and the modal delegate.
To end a document modal session, use NSApplication's methods endSheet: or endSheet:returnCode:. Each method takes the sheet window as a parameter. The second, endSheet:returnCode:, also takes an integer return code that is passed to the didEndSelector: method. Example 3-3 shows how to open and close a sheet in an application.
/* * This method is invoked to open a sheet. * Assume sheetWindow and mainWindow are Interface Builder * outlet instance variables connected to windows in a nib. */ - (void)openSheet:(id)sender { SEL selector = @selector(sheetDidEnd:returnCode:contextInfo:); [NSApp beginSheet:sheetWindow modalForWindow:mainWindow modalDelegate:self didEndSelector:selector contextInfo:NULL]; } /* * This could be the action of the "Cancel" button of the sheet * in Figure 3-8. */ - (void)cancelSheet:(id)sender { [NSApp endSheet:sheetWindow returnCode:NSCancelButton]; } /* * This could be the action of the "Save" button of the sheet * in Figure 3-8. */ - (void)acceptSheet:(id)sender { [NSApp endSheet:sheetWindow returnCode:NSOKButton]; } - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo { /* * Can do something here based on the value of returnCode * or do something in the button actions themselves. */ if ( returnCode == NSOKButton ) { // If OK was clicked... } else if ( returnCode == NSCancelButton ) { // If Cancel was clicked.... } [sheet orderOut:nil]; }
In this example, NSOKButton and NSCancelButton are global constants often used to identify those buttons in a dialog. The endSheet: methods only end the document modal session; they do not remove the sheet from the screen. To hide the sheet, send an orderOut: message to the sheet window, which Example 3-3 does in the callback method sheetDidEnd:returnCode:contextInfo:.
Finally, there are yet more ways to display sheets: the AppKit classes that implement standard Mac OS X user interfaces, such as NSPrintPanel and NSOpenPanel, all provide ways to display their respective interfaces as document modal sheets.