This wasn't *really* a leak, but this makes the static analyzer happy and is cleaner, anyway.
5 // Created by rudy on Sun Apr 17 2005.
6 // Copyright (c) 2005 The Growl Project. All rights reserved.
10 #import "GrowlPreferencesController.h"
11 #import "GrowlPathUtilities.h"
12 //#import "GrowlPluginController.h"
15 #define kRestartGrowl NSLocalizedString(@"Restart Growl", @"")
16 #define kRestartGrowlTooltip NSLocalizedString(@"Restart Growl", @"")
17 #define kStartGrowl NSLocalizedString(@"Start Growl", @"")
18 #define kStartGrowlTooltip NSLocalizedString(@"Start Growl", @"")
19 #define kStopGrowl NSLocalizedString(@"Stop Growl", @"")
20 #define kStopGrowlTooltip NSLocalizedString(@"Stop Growl", @"")
21 #define kDefaultDisplay NSLocalizedString(@"Default display", @"")
22 #define kDefaultDisplayTooltip NSLocalizedString(@"Set the default display style", @"")
23 #define kOpenGrowlPreferences NSLocalizedString(@"Open Growl Preferences...", @"")
24 #define kOpenGrowlPreferencesTooltip NSLocalizedString(@"Open the Growl preference pane", @"")
25 #define kSquelchMode NSLocalizedString(@"Log only, don't display", @"")
26 #define kSquelchModeTooltip NSLocalizedString(@"Don't show notifications, but still log them", @"")
27 #define kStopGrowlMenu NSLocalizedString(@"Hide Status Item", @"")
28 #define kStopGrowlMenuTooltip NSLocalizedString(@"Hide this status item", @"")
29 #define kStickyWhenAwayMenu NSLocalizedString(@"Sticky Notifications", @"")
30 #define kStickyWhenAwayMenuTooltip NSLocalizedString(@"Toggles the sticky notification state", @"")
31 #define kDefaultDisplayChanged NSLocalizedString(@"Default display changed to %@", @"")
34 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
35 [NSApplication sharedApplication];
37 GrowlMenu *menu = [[[GrowlMenu alloc] init] autorelease];
38 [NSApp setDelegate:menu];
47 @implementation GrowlMenu
49 - (void) applicationDidFinishLaunching:(NSNotification *)aNotification {
50 #pragma unused(aNotification)
52 preferences = [GrowlPreferencesController sharedController];
54 NSMenu *m = [self createMenu];
56 statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
58 NSBundle *bundle = [NSBundle mainBundle];
60 clawImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"growlmenu" ofType:@"png"]];
61 clawHighlightImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"growlmenu-alt" ofType:@"png"]];
62 squelchImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"squelch" ofType:@"png"]];
66 [statusItem setMenu:m]; // retains m
67 [statusItem setToolTip:@"Growl"];
68 [statusItem setHighlightMode:YES];
72 [self setGrowlMenuEnabled:YES];
74 NSNotificationCenter *nc = [NSDistributedNotificationCenter defaultCenter];
76 selector:@selector(shutdown:)
77 name:@"GrowlMenuShutdown"
80 selector:@selector(reloadPrefs:)
81 name:GrowlPreferencesChanged
84 [GrowlApplicationBridge setGrowlDelegate:self];
87 #pragma mark Growl delegate methods
89 - (NSString *) applicationNameForGrowl {
93 - (NSDictionary *) registrationDictionaryForGrowl {
94 NSArray *notifications = [NSArray arrayWithObject:@"Display changed"];
95 NSDictionary *registrationDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
96 notifications, GROWL_NOTIFICATIONS_ALL,
97 notifications, GROWL_NOTIFICATIONS_DEFAULT,
98 [NSDictionary dictionaryWithObject:NSLocalizedString(@"Display changed", "Notification posted by GrowlMenu when the display style changes")
99 forKey:@"Display changed"], GROWL_NOTIFICATIONS_HUMAN_READABLE_NAMES,
102 return registrationDictionary;
107 - (void) setGrowlMenuEnabled:(BOOL)state {
108 NSString *growlMenuPath = [[NSBundle mainBundle] bundlePath];
109 [preferences setStartAtLogin:growlMenuPath enabled:state];
110 [preferences setBool:state forKey:GrowlMenuExtraKey];
113 - (void) applicationWillTerminate:(NSNotification *)aNotification {
114 #pragma unused(aNotification)
119 // [[NSStatusBar systemStatusBar] removeStatusItem:statusItem];
120 // [statusItem release];
122 [clawHighlightImage release];
123 [squelchImage release];
127 - (void) shutdown:(id)sender {
128 [self setGrowlMenuEnabled:NO];
129 [NSApp terminate:sender];
132 - (void) reloadPrefs:(NSNotification *)notification {
133 // ignore notifications which are sent by ourselves
134 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
135 NSNumber *pidValue = [[notification userInfo] objectForKey:@"pid"];
136 if (!pidValue || [pidValue intValue] != pid)
141 - (void) openGrowlPreferences:(id)sender {
142 #pragma unused(sender)
143 NSString *prefPane = [[GrowlPathUtilities growlPrefPaneBundle] bundlePath];
144 [[NSWorkspace sharedWorkspace] openFile:prefPane];
147 - (void) defaultDisplay:(id)sender {
148 NSString *pluginName = [sender title];
149 [preferences setDefaultDisplayPluginName:pluginName];
151 CFStringRef description = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, (CFStringRef)kDefaultDisplayChanged, pluginName);
152 const NSString *keys[5] = { GROWL_APP_NAME, GROWL_NOTIFICATION_NAME, GROWL_NOTIFICATION_TITLE, GROWL_NOTIFICATION_DESCRIPTION, GROWL_DISPLAY_PLUGIN };
153 const CFStringRef values[5] = { CFSTR("GrowlMenu"), CFSTR("Display changed"), CFSTR("Display changed"), description, (CFStringRef)pluginName };
154 CFDictionaryRef feedbackDictionary = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, 5, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
155 CFRelease(description);
156 [GrowlApplicationBridge notifyWithDictionary:(NSDictionary *)feedbackDictionary];
157 CFRelease(feedbackDictionary);
160 - (void) stopGrowl:(id)sender {
161 #pragma unused(sender)
162 //If Growl is running, we should stop it.
163 if ([preferences isGrowlRunning])
164 [preferences setGrowlRunning:NO noMatterWhat:NO];
167 - (void) startGrowl:(id)sender {
168 #pragma unused(sender)
169 if (![preferences isGrowlRunning]) {
170 //If Growl isn't running, we should start it.
171 [preferences setGrowlRunning:YES noMatterWhat:NO];
173 //If Growl is running, we should restart it.
174 //Actually, we should HUP it, but we don't.
175 [preferences setGrowlRunning:NO noMatterWhat:NO];
176 [preferences setGrowlRunning:YES noMatterWhat:YES];
180 - (void) squelchMode:(id)sender {
181 #pragma unused(sender)
182 BOOL squelchMode = ![preferences squelchMode];
183 [preferences setSquelchMode:squelchMode];
187 - (void) stickyWhenIdle:(id)sender {
188 #pragma unused(sender)
189 BOOL idleModeState = ![preferences stickyWhenAway];
190 [preferences setStickyWhenAway:idleModeState];
194 if ([preferences squelchMode]) {
195 [statusItem setImage:squelchImage];
197 [statusItem setImage:clawImage];
198 [statusItem setAlternateImage:clawHighlightImage];
202 - (NSMenu *) createMenu {
203 NSZone *menuZone = [NSMenu menuZone];
204 NSMenu *m = [[NSMenu allocWithZone:menuZone] init];
206 NSMenuItem *tempMenuItem;
208 tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kStartGrowl action:@selector(startGrowl:) keyEquivalent:@""];
209 [tempMenuItem setTarget:self];
210 [tempMenuItem setTag:1];
212 if ([preferences isGrowlRunning]) {
213 [tempMenuItem setTitle:kRestartGrowl];
214 [tempMenuItem setToolTip:kRestartGrowlTooltip];
216 [tempMenuItem setToolTip:kStartGrowlTooltip];
219 tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kStopGrowl action:@selector(stopGrowl:) keyEquivalent:@""];
220 [tempMenuItem setTag:2];
221 [tempMenuItem setTarget:self];
222 [tempMenuItem setToolTip:kStopGrowlTooltip];
224 [m addItem:[NSMenuItem separatorItem]];
227 //Squelch mode is "log-only" mode... but logging was removed from Growl 1.1.
228 tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kSquelchMode action:@selector(squelchMode:) keyEquivalent:@""];
229 [tempMenuItem setTarget:self];
230 [tempMenuItem setTag:4];
231 [tempMenuItem setToolTip:kSquelchModeTooltip];
234 tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kStickyWhenAwayMenu action:@selector(stickyWhenIdle:) keyEquivalent:@""];
235 [tempMenuItem setTarget:self];
236 [tempMenuItem setTag:6];
237 [tempMenuItem setToolTip:kStickyWhenAwayMenuTooltip];
239 /*NSMenu *displays = [[NSMenu allocWithZone:menuZone] init];
241 NSEnumerator *displayEnumerator = [[[GrowlPluginController sharedController] displayPlugins] objectEnumerator];
242 while ((name = [displayEnumerator nextObject])) {
243 tempMenuItem = (NSMenuItem *)[displays addItemWithTitle:name action:@selector(defaultDisplay:) keyEquivalent:@""];
244 [tempMenuItem setTarget:self];
245 [tempMenuItem setTag:3];
247 tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kDefaultDisplay action:NULL keyEquivalent:@""];
248 [tempMenuItem setTarget:self];
249 [tempMenuItem setSubmenu:displays];
250 [displays release];*/
251 [m addItem:[NSMenuItem separatorItem]];
253 tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kStopGrowlMenu action:@selector(shutdown:) keyEquivalent:@""];
254 [tempMenuItem setTag:5];
255 [tempMenuItem setTarget:self];
256 [tempMenuItem setToolTip:kStopGrowlMenuTooltip];
258 tempMenuItem = (NSMenuItem *)[m addItemWithTitle:kOpenGrowlPreferences action:@selector(openGrowlPreferences:) keyEquivalent:@""];
259 [tempMenuItem setTarget:self];
260 [tempMenuItem setToolTip:kOpenGrowlPreferencesTooltip];
265 - (BOOL) validateMenuItem:(NSMenuItem *)item {
266 switch ([item tag]) {
268 if ([preferences isGrowlRunning]) {
269 [item setTitle:kRestartGrowl];
270 [item setToolTip:kRestartGrowlTooltip];
272 [item setTitle:kStartGrowl];
273 [item setToolTip:kStartGrowlTooltip];
277 return [preferences isGrowlRunning];
279 [item setState:[[item title] isEqualToString:[preferences defaultDisplayPluginName]]];
282 [item setState:[preferences squelchMode]];
285 [item setState:[preferences stickyWhenAway]];