diff --git a/AppKit/CPAlert.j b/AppKit/CPAlert.j index 37208a12e..5f8db4129 100644 --- a/AppKit/CPAlert.j +++ b/AppKit/CPAlert.j @@ -96,7 +96,8 @@ var bottomHeight = 71; id _delegate @accessors(property=delegate); id _modalDelegate; - SEL _didEndSelector; + SEL _didEndSelector @accessors(property=didEndSelector); + Function _didEndBlock; _CPAlertThemeView _themeView @accessors(property=themeView, readonly); CPWindow _window @accessors(property=window, readonly); @@ -224,16 +225,15 @@ var bottomHeight = 71; } -/*! @deprecated -*/ -- (void)setWindowStyle:(int)aStyle +/*! @deprecated */ +- (void)setWindowStyle:(int)style { CPLog.warn("DEPRECATED: setWindowStyle: is deprecated. use setTheme: instead"); - [self setTheme:(aStyle === CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]]; + + [self setTheme:(style === CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]]; } -/*! @deprecated -*/ +/*! @deprecated */ - (int)windowStyle { CPLog.warn("DEPRECATED: windowStyle: is deprecated. use theme instead"); @@ -242,18 +242,19 @@ var bottomHeight = 71; /*! - set the text of the alert's message + Set the text of the alert's message. @param aText CPString containing the text */ -- (void)setMessageText:(CPString)aText +- (void)setMessageText:(CPString)text { - [_messageLabel setStringValue:aText]; + [_messageLabel setStringValue:text]; _needsLayout = YES; } /*! - return the content of the message text + Return the content of the message text. + @return CPString containing the message text */ - (CPString)messageText @@ -262,13 +263,13 @@ var bottomHeight = 71; } /*! - set the text of the alert's informative text + Set the text of the alert's informative text. @param aText CPString containing the informative text */ -- (void)setInformativeText:(CPString)aText +- (void)setInformativeText:(CPString)text { - [_informativeLabel setStringValue:aText]; + [_informativeLabel setStringValue:text]; _needsLayout = YES; } @@ -285,6 +286,7 @@ var bottomHeight = 71; /*! Sets the title of the alert window. This API is not present in Cocoa. + @param aTitle CPString containing the window title */ - (void)setTitle:(CPString)aTitle @@ -294,7 +296,7 @@ var bottomHeight = 71; } /*! - set the accessory view + Set the accessory view. @param aView the accessory view */ @@ -305,7 +307,7 @@ var bottomHeight = 71; } /*! - set if alert shows the suppression button + Set if the alert shows the suppression button. @param shouldShowSuppressionButton YES or NO */ @@ -596,6 +598,17 @@ var bottomHeight = 71; [CPApp runModalForWindow:_window]; } +/*! + The same as \c runModal, but executes the code in \c block when the + alert is dismissed. +*/ +- (void)runModalWithDidEndBlock:(Function /*(CPAlert alert, int returnCode)*/)block +{ + _didEndBlock = block; + + [self runModal]; +} + /*! Runs the receiver modally as an alert sheet attached to a specified window. @@ -630,6 +643,20 @@ var bottomHeight = 71; [self beginSheetModalForWindow:aWindow modalDelegate:nil didEndSelector:nil contextInfo:nil]; } +/*! + Runs the receiver modally as an alert sheet attached to a specified window. + Executes the code in \c block when the alert is dismissed. + + @param window The parent window for the sheet. + @param block Code block to execute on dismissal +*/ +- (void)beginSheetModalForWindow:(CPWindow)aWindow didEndBlock:(Function /*(CPAlert alert, int returnCode)*/)block +{ + _didEndBlock = block; + + [self beginSheetModalForWindow:aWindow modalDelegate:nil didEndSelector:nil contextInfo:nil]; +} + #pragma mark Private /*! @@ -697,14 +724,28 @@ var bottomHeight = 71; */ - (void)_alertDidEnd:(CPWindow)aWindow returnCode:(int)returnCode contextInfo:(id)contextInfo { - if (_didEndSelector) - objj_msgSend(_modalDelegate, _didEndSelector, self, returnCode, contextInfo); + if (_didEndBlock) + { + if (typeof(_didEndBlock) === "function") + _didEndBlock(self, returnCode); + else + CPLog.warn("%s: didEnd block is not a function", [self description]); - _modalDelegate = nil; - _didEndSelector = nil; - - if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)]) - [_delegate alertDidEnd:self returnCode:returnCode]; + // didEnd blocks are transient + _didEndBlock = nil; + } + else if (_modalDelegate) + { + if (_didEndSelector) + objj_msgSend(_modalDelegate, _didEndSelector, self, returnCode, contextInfo); + } + else if (_delegate) + { + if (_didEndSelector) + objj_msgSend(_delegate, _didEndSelector, self, returnCode); + else if ([_delegate respondsToSelector:@selector(alertDidEnd:returnCode:)]) + [_delegate alertDidEnd:self returnCode:returnCode]; + } } @end diff --git a/Tests/Manual/CPAlertTest/AppController.j b/Tests/Manual/CPAlertTest/AppController.j index a0d1d97a0..bb91b42b3 100644 --- a/Tests/Manual/CPAlertTest/AppController.j +++ b/Tests/Manual/CPAlertTest/AppController.j @@ -16,9 +16,10 @@ CPArray variations; CPArray messages; int messageIndex; + BOOL useBlocks; } -- (void)applicationDidFinishLaunching:(CPNotification)aNotification +- (void)_init { messages = [ [@"Are you sure you want to theorise before you have data?", @@ -30,6 +31,7 @@ [@"Sometimes a message can be really long and just appear to go on and on. It could be a speech. It could be the television.", nil] ]; + messageIndex = 0; variations = [ @@ -43,6 +45,11 @@ [CPDocModalWindowMask, CPInformationalAlertStyle], [CPDocModalWindowMask, CPCriticalAlertStyle] ]; +} + +- (void)applicationDidFinishLaunching:(CPNotification)aNotification +{ + [self _init]; theWindow = [[CPWindow alloc] initWithContentRect:CGRectMake(100, 100, 500, 500) styleMask:CPTitledWindowMask]; [theWindow setTitle:@"CPAlert Test"]; @@ -54,6 +61,13 @@ [label setStringValue:"Respond to the alert dialog with the mouse or the keyboard."]; [contentView addSubview:label]; + var button = [CPButton buttonWithTitle:@"Start again using didEnd blocks"]; + + [button setTarget:self]; + [button setAction:@selector(testWithBlocks:)]; + [button setCenter:[contentView center]]; + [contentView addSubview:button]; + [theWindow orderFront:self]; [self showNextAlertVariation]; @@ -62,9 +76,17 @@ //[CPMenu setMenuBarVisible:YES]; } +- (@action)testWithBlocks:(id)sender +{ + useBlocks = YES; + [self _init]; + [self showNextAlertVariation]; +} + - (void)alertDidEnd:(CPAlert)anAlert returnCode:(CPInteger)returnCode { - CPLogConsole(_cmd); + CPLog.info("%s alert = %s, code = %d", _cmd, [anAlert description], returnCode); + if (returnCode === 0) [label setStringValue:"You chose the default action."]; else @@ -75,7 +97,7 @@ - (void)customDidEnd:(CPAlert)anAlert code:(id)code context:(id)context { - CPLogConsole(_cmd + anAlert + code + context); + CPLog.info("%s alert = %s, code = %d, context = %s", _cmd, [anAlert description], code, context); } - (void)showNextAlertVariation @@ -92,17 +114,37 @@ var windowStyle = variation[0]; [alert setDelegate:self]; - [alert setMessageText:message[0]]; - [alert setInformativeText:message[1]]; + [alert setMessageText:message[0] || @""]; + [alert setInformativeText:message[1] || @""]; + if (message.length > 2) [alert addButtonWithTitle:message[2]]; + if (message.length > 3) [alert addButtonWithTitle:message[3]]; + [alert setTheme:(windowStyle === CPHUDBackgroundWindowMask) ? [CPTheme defaultHudTheme] : [CPTheme defaultTheme]]; [alert setAlertStyle:variation[1]]; if (windowStyle & CPDocModalWindowMask) - [alert beginSheetModalForWindow:theWindow modalDelegate:self didEndSelector:@selector(customDidEnd:code:context:) contextInfo:@"here is some context"]; + { + if (useBlocks) + [alert beginSheetModalForWindow:theWindow didEndBlock:function(alert, returnCode) + { + CPLog.info("didEndBlock: alert = %s, code = %d", [alert description], returnCode); + + [self showNextAlertVariation]; + }]; + else + [alert beginSheetModalForWindow:theWindow modalDelegate:self didEndSelector:@selector(customDidEnd:code:context:) contextInfo:@"here is some context"]; + } + else if (useBlocks) + [alert runModalWithDidEndBlock:function(alert, returnCode) + { + CPLog.info("didEndBlock: alert = %s, code = %d", [alert description], returnCode); + + [self showNextAlertVariation]; + }]; else [alert runModal]; }