Index: RController.h =================================================================== --- RController.h (revision 795) +++ RController.h (working copy) @@ -115,7 +115,10 @@ BOOL runSystemAsRoot; BOOL busyRFlag; + BOOL growlIsAvailable; + NSDate *computationStarted; + float currentSize; float currentFontSize; float currentConsoleWidth; Index: RController.m =================================================================== --- RController.m (revision 795) +++ RController.m (working copy) @@ -47,6 +47,10 @@ #import "ColorsPrefPane.h" #import "EditorPrefPane.h" +#import +#import + + // size of the console output cache buffer #define DEFAULT_WRITE_BUFFER_SIZE 32768 // high water-mark of the buffer - it's [length - x] where x is the smallest possible size to be flushed before a new string will be split. @@ -127,9 +131,12 @@ readConsTransBufferSize = 1024; // initial size - will grow as needed readConsTransBuffer = (char*) malloc(readConsTransBufferSize); + growlIsAvailable = NO; + return self; } + - (void) setRootFlag: (BOOL) flag { if (!flag) removeRootAuthorization(); @@ -250,6 +257,8 @@ //currentFontSize = [[RTextView font] pointSize]; currentConsoleWidth = -1; chdir(R_ExpandFileName("~/")); + + } -(void) applicationDidFinishLaunching: (NSNotification *)aNotification @@ -287,9 +296,33 @@ selector:@selector(runRELP:) userInfo:0 repeats:NO]; + + + /* Check for Growl notification helper app and activate it if available */ + if(NSClassFromString(@"GrowlAppBridge") != nil && + [NSClassFromString(@"GrowlAppBridge") launchGrowlIfInstalledNotifyingTarget:self + selector:@selector(growlDidLaunch:) + context:nil]) { + } else + NSLog(@"Unable to locate or load GrowlAppBridge framework"); + } +- (void) growlDidLaunch:(void*)context { + growlIsAvailable = YES; + /* Register ourselves with Growl */ + [[NSDistributedNotificationCenter defaultCenter] + postNotificationName:GROWL_APP_REGISTRATION + object:nil + userInfo:[NSDictionary dictionaryWithObjectsAndKeys: + @"R",GROWL_APP_NAME, + [NSArray arrayWithObject:@"ComputationCompleted"],GROWL_NOTIFICATIONS_ALL, + [NSArray arrayWithObject:@"ComputationCompleted"],GROWL_NOTIFICATIONS_DEFAULT, + nil]]; +} + + -(void) addConnectionLog { NSPort *port1; @@ -1105,10 +1138,31 @@ } - (void) handleBusy: (BOOL) isBusy { - if (isBusy) + if (isBusy) { + computationStarted = [[NSDate date] retain]; [progressWheel startAnimation:self]; - else + } else { + if(computationStarted != nil && growlIsAvailable == YES && [[NSApplication sharedApplication] isActive] == NO) { + NSNumber *seconds = [[NSUserDefaults standardUserDefaults] objectForKey:@"SecondsUntilNotification"]; + if([[NSUserDefaults standardUserDefaults] boolForKey:@"ShouldSendGrowlNotification"] && + seconds && + [seconds floatValue] <= -[computationStarted timeIntervalSinceNow]) { + [[NSDistributedNotificationCenter defaultCenter] + postNotificationName:GROWL_NOTIFICATION + object:nil + userInfo:[NSDictionary dictionaryWithObjectsAndKeys: + @"R",GROWL_APP_NAME, + @"ComputationCompleted",GROWL_NOTIFICATION_NAME, + @"R",GROWL_NOTIFICATION_TITLE, + @"Computation Complete",GROWL_NOTIFICATION_DESCRIPTION, + nil] + deliverImmediately:YES]; + } + } + [computationStarted release]; + computationStarted = nil; [progressWheel stopAnimation:self]; + } busyRFlag = isBusy; if (toolbarStopItem) {