Iβm not sure if Iβm doing everything right, or if I hacked it all.
I have a really simple test application (not document-based) that I created to learn how to work with modal dialog applications in Cocoa applications.
With the "TestModalDialog" application project, I have a simple MainMenu.xib with a default view and a "Show dialog" button, I added. I created a second XIB called TheDialog.xib, which has the Cancel and OK buttons. This xib has as its owner a class derived from NSWindowController called "TheDialogController"; window exit and delegate connected to the controller.
Selecting "Show dialog" on the main screen will launch the dialog. Selecting "Cancel" or "OK" will reject the dialog. Here is a pretty simple code:
// TestModalDialogAppDelegate.h // TestModalDialog #import <Cocoa/Cocoa.h> @class TheDialogController; @interface TestModalDialogAppDelegate : NSObject <NSApplicationDelegate> { NSWindow *window; TheDialogController* theDialogController; } @property (assign) IBOutlet NSWindow *window; - (IBAction)showDialog:(id)sender; @end // TestModalDialogAppDelegate.m // TestModalDialog #import "TestModalDialogAppDelegate.h" #import "TheDialogController.h" @implementation TestModalDialogAppDelegate @synthesize window; - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { theDialogController= [[TheDialogController alloc] init]; } - (void)dealloc { if(nil != theDialogController) [theDialogController release]; [super dealloc]; } - (IBAction)showDialog:(id)sender { if(nil == theDialogController) { NSAlert* alert= [NSAlert alertWithMessageText:@"Dialog Error" defaultButton:nil alternateButton:nil otherButton:nil informativeTextWithFormat:@"The dialog controller was not allocated."]; [alert runModal]; return; } NSInteger result= [NSApp runModalForWindow:[theDialogController window]]; // Do something with result.... } @end // TheDialogController.h // TestModalDialog #import <Cocoa/Cocoa.h> @interface TheDialogController : NSWindowController { // BOOL userClickedCloseOrOk; // Removed based on answer. // Should declare a common define - just being lazy. NSInteger userClickedOk; // Added based on answer. UInt16 timesShown; } - (IBAction)showWindow:(id)sender; - (IBAction)closeDialog:(id)sender; - (IBAction)okDialog:(id)sender; //- (BOOL)windowShouldClose:(id)sender; // Removed based on answer. - (void)windowWillClose:(NSNotification*)notification; // Added based on answer. - (void)windowDidBecomeKey:(NSNotification*)notification; // To set title when modal. @end // TheDialogController.m // TestModalDialog #import "TheDialogController.h" @implementation TheDialogController - (id)init { self = [super initWithWindowNibName:@"TheDialog"]; userClickedOk= 0; // Added based on answer. // userClickedCloseOrOk= FALSE; // Removed based on answer. return self; } -(void)dealloc { // Do member cleanup if needed. [super dealloc]; } - (void)windowDidLoad { [super windowDidLoad]; // Initialize as needed.... [[self window] center]; // Center the window. } // Does not show with runModalForWindow. - (IBAction)showWindow:(id)sender { // Just playing with the window title.... ++timesShown; NSString* newTitle= [NSString stringWithFormat:@"Shown %d Times", timesShown]; [[self window] setTitle:newTitle]; return [super showWindow:sender]; } // This method no longer used for this solution based on the answer. //- (BOOL)windowShouldClose:(id)sender //{ // if(!userClickedCloseOrOk) // The user did not click one of our buttons. // [NSApp abortModal]; // else // userClickedCloseOrOk= FALSE; // Clear for next time. // // return TRUE; //} // Added based on answer. - (void)windowWillClose:(NSNotification*)notification { [NSApp stopModalWithCode:userClickedOk]; userClickedOk= 0; // Reset for next time. } // Note - the title will update every time the window becomes key. To do the // update only once per modal session, a flag can be added. There might be a better // notification to catch. - (void)windowDidBecomeKey:(NSNotification*)notification { ++timesShown; NSString* newTitle= [NSString stringWithFormat:@"Shown %d Times", timesShown]; [[self window] setTitle:newTitle]; } - (IBAction)closeDialog:(id)sender { //userClickedCloseOrOk= TRUE; // Removed based on answer. //[NSApp abortModal]; // Removed based on answer. //[[self window] performClose:self]; // Removed based on answer. [[self window] close]; // Know we want to close - based on answer. } - (IBAction)okDialog:(id)sender { userClickedOk= 1; // Added based on answer. //userClickedCloseOrOk= TRUE; // Removed based on answer. //[NSApp stopModal]; // Removed based on answer. //[[self window] performClose:self]; // Removed based on answer. [[self window] close]; // Know we want to close - based on answer. } @end
I had problems with modality - before I put userClickedCloseOrOk and tests, if the user clicked the close button (top left red dot), the dialog will close, but the modal session will still work.
I understand that I could just leave the button from the dialog box to start, but with that there I demonstrated a good way to catch this script or is there a better way? Or am I starting with something wrong that creates this problem for me?
Any advice would be appreciated.
NOTE. - The code from the original example is commented out and replaced with code based on the response. A new notification handler has also been added.
source share