From fad781e94b464109aaa2243aa5ad2e593ea6e9bb Mon Sep 17 00:00:00 2001 From: Joseph Spiros Date: Sun, 1 Mar 2009 16:43:49 -0500 Subject: [PATCH] Implemented preference pane. --- English.lproj/GrowlITTSWPrefs.nib/classes.nib | 39 +++ English.lproj/GrowlITTSWPrefs.nib/info.nib | 2 +- .../GrowlITTSWPrefs.nib/keyedobjects.nib | Bin 10674 -> 12301 bytes GrowlITTSW.xcodeproj/project.pbxproj | 2 + GrowlITTSWController.m | 121 ++++---- GrowlITTSWDisplay.h | 1 + GrowlITTSWDisplay.m | 9 +- GrowlITTSWPrefs.h | 38 +++ GrowlITTSWPrefs.m | 272 ++++++++++++++++++ 9 files changed, 423 insertions(+), 61 deletions(-) diff --git a/English.lproj/GrowlITTSWPrefs.nib/classes.nib b/English.lproj/GrowlITTSWPrefs.nib/classes.nib index 1f69d3a..6462c4d 100644 --- a/English.lproj/GrowlITTSWPrefs.nib/classes.nib +++ b/English.lproj/GrowlITTSWPrefs.nib/classes.nib @@ -54,14 +54,53 @@ NSResponder + ACTIONS + + setAppearanceEffect + id + setAppearanceSpeed + id + setBackgroundColor + id + setBackgroundStyle + id + setScreen + id + setVanishDelay + id + setVanishEffect + id + setVanishSpeed + id + setWindowSize + id + CLASS GrowlITTSWPrefs LANGUAGE ObjC OUTLETS + appearanceEffectButton + NSPopUpButton + appearanceSpeedSlider + NSSlider + backgroundColorWell + NSColorWell + backgroundStyleButton + NSPopUpButton + screenButton + NSPopUpButton slider_opacity NSSlider + vanishDelaySlider + NSSlider + vanishEffectButton + NSPopUpButton + vanishSpeedSlider + NSSlider + windowSizeButton + NSPopUpButton SUPERCLASS NSPreferencePane diff --git a/English.lproj/GrowlITTSWPrefs.nib/info.nib b/English.lproj/GrowlITTSWPrefs.nib/info.nib index 61d25e2..2c41c85 100644 --- a/English.lproj/GrowlITTSWPrefs.nib/info.nib +++ b/English.lproj/GrowlITTSWPrefs.nib/info.nib @@ -10,7 +10,7 @@ 3 IBOpenObjects - 244 + 6 IBSystem Version 9G55 diff --git a/English.lproj/GrowlITTSWPrefs.nib/keyedobjects.nib b/English.lproj/GrowlITTSWPrefs.nib/keyedobjects.nib index d017b7d474a16f109e844ed2dd549f316c9d5bef..7a1f10afbd8674ef5ddfbdf48a138783ede161a7 100644 GIT binary patch literal 12301 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 #import +#import #import "RegexKitLite.h" -#import "GrowlPositioningDefines.h" - -@interface GrowlPositionController -+ (enum GrowlPosition)selectedOriginPosition; -@end - @implementation NSImage (SmoothAdditions) -- (NSImage *)imageScaledSmoothlyToSize:(NSSize)scaledSize -{ +- (NSImage *)imageScaledSmoothlyToSize:(NSSize)scaledSize { NSImage *newImage; NSImageRep *rep = [self bestRepresentationForDevice:nil]; @@ -39,43 +33,81 @@ @end +@interface GrowlITTSWController (Private) +- (void)syncWithPrefs; +@end + @implementation GrowlITTSWController -- (id)init -{ +- (id)init { if ( ( self = [super init] ) ) { - NSArray *screens = [NSScreen screens]; - _window = [[GrowlITTSWWindow sharedWindow] retain]; - - [_window setScreen:[screens objectAtIndex:0]]; - - [_window setExitMode:ITTransientStatusWindowExitAfterDelay]; - [_window setExitDelay:4.0]; - - [_window setSizing:ITTransientStatusWindowMini]; - - [_window setEntryEffect:[[[NSClassFromString(@"ITSlideVerticallyWindowEffect") alloc] initWithWindow:_window] autorelease]]; - [_window setExitEffect:[[[NSClassFromString(@"ITSlideHorizontallyWindowEffect") alloc] initWithWindow:_window] autorelease]]; - - [[_window entryEffect] setEffectTime:0.8]; - [[_window exitEffect] setEffectTime:0.8]; - - [(ITTSWBackgroundView *)[_window contentView]setBackgroundMode: - ITTSWBackgroundReadable]; + [_window setExitMode:ITTransientStatusWindowExitAfterDelay]; + [self syncWithPrefs]; + [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(syncWithPrefs) name:@"GrowlPreferencesChanged" object:nil]; } return self; } -- (void)dealloc -{ +- (void)dealloc { [_window release]; [super dealloc]; } -- (void)showWindowWithText:(NSString *)text image:(NSImage *)image -{ +- (void)syncWithPrefs { + NSScreen *screen = [GrowlITTSWPrefs screen]; + ITHorizontalWindowPosition horizontalPosition = [GrowlITTSWPrefs horizontalPosition]; + ITVerticalWindowPosition verticalPosition = [GrowlITTSWPrefs verticalPosition]; + + Class appearanceEffect = [GrowlITTSWPrefs appearanceEffect]; + float appearanceSpeed = [GrowlITTSWPrefs appearanceSpeed]; + Class vanishEffect = [GrowlITTSWPrefs vanishEffect]; + float vanishSpeed = [GrowlITTSWPrefs vanishSpeed]; + float vanishDelay = [GrowlITTSWPrefs vanishDelay]; + + ITTSWBackgroundMode backgroundStyle = [GrowlITTSWPrefs backgroundStyle]; + NSColor *backgroundColor = [GrowlITTSWPrefs backgroundColor]; + ITTransientStatusWindowSizing windowSize = [GrowlITTSWPrefs windowSize]; + + if ([_window screen] != screen) { + [_window setScreen:screen]; + } + if ([_window horizontalPosition] != horizontalPosition) { + [_window setHorizontalPosition:horizontalPosition]; + } + if ([_window verticalPosition] != verticalPosition) { + [_window setVerticalPosition:verticalPosition]; + } + + if (![[_window entryEffect] isKindOfClass:appearanceEffect]) { + [_window setEntryEffect:[[[appearanceEffect alloc] initWithWindow:_window] autorelease]]; + } + if ([[_window entryEffect] effectTime] != appearanceSpeed) { + [[_window entryEffect] setEffectTime:appearanceSpeed]; + } + if (![[_window exitEffect] isKindOfClass:vanishEffect]) { + [_window setExitEffect:[[[vanishEffect alloc] initWithWindow:_window] autorelease]]; + } + if ([[_window exitEffect] effectTime] != vanishSpeed) { + [[_window exitEffect] setEffectTime:vanishSpeed]; + } + if ([_window exitDelay] != vanishDelay) { + [_window setExitDelay:vanishDelay]; + } + + if ([(ITTSWBackgroundView *)[_window contentView] backgroundMode] != backgroundStyle) { + [(ITTSWBackgroundView *)[_window contentView] setBackgroundMode:backgroundStyle]; + } + if (([(ITTSWBackgroundView *)[_window contentView] backgroundMode] == ITTSWBackgroundColored) && ![[(ITTSWBackgroundView *)[_window contentView] backgroundColor] isEqual:backgroundColor]) { + [(ITTSWBackgroundView *)[_window contentView] setBackgroundColor:backgroundColor]; + } + if ([_window sizing] != windowSize) { + [_window setSizing:windowSize]; + } +} + +- (void)showWindowWithText:(NSString *)text image:(NSImage *)image { NSSize newSize; NSSize oldSize = [image size]; @@ -115,29 +147,6 @@ } } - switch ([GrowlPositionController selectedOriginPosition]) { - case GrowlMiddleColumnPosition: - [_window setVerticalPosition:ITWindowPositionMiddle]; - [_window setHorizontalPosition:ITWindowPositionCenter]; - break; - case GrowlTopLeftPosition: - [_window setVerticalPosition:ITWindowPositionTop]; - [_window setHorizontalPosition:ITWindowPositionLeft]; - break; - case GrowlBottomRightPosition: - [_window setVerticalPosition:ITWindowPositionBottom]; - [_window setHorizontalPosition:ITWindowPositionRight]; - break; - case GrowlTopRightPosition: - [_window setVerticalPosition:ITWindowPositionTop]; - [_window setHorizontalPosition:ITWindowPositionRight]; - break; - case GrowlBottomLeftPosition: - [_window setVerticalPosition:ITWindowPositionBottom]; - [_window setHorizontalPosition:ITWindowPositionLeft]; - break; - } - [_window setImage:image]; [_window buildTextWindowWithString:attributedText]; [_window appear:self]; diff --git a/GrowlITTSWDisplay.h b/GrowlITTSWDisplay.h index 1330358..dad8209 100644 --- a/GrowlITTSWDisplay.h +++ b/GrowlITTSWDisplay.h @@ -1,5 +1,6 @@ #import #import "GrowlDisplayPlugin.h" +#import "GrowlITTSWPrefs.h" @class GrowlApplicationNotification; diff --git a/GrowlITTSWDisplay.m b/GrowlITTSWDisplay.m index bbd7515..b6727e8 100644 --- a/GrowlITTSWDisplay.m +++ b/GrowlITTSWDisplay.m @@ -12,11 +12,12 @@ [super dealloc]; } -/* - (NSPreferencePane *) preferencePane { - if (!preferencePane) - preferencePane = [[GrowlITTSWPrefs alloc] initWithBundle:[NSBundle bundleWithIdentifier:@"com.ithinksw.growl.ittsw"]]; +- (NSPreferencePane *) preferencePane { + if (!preferencePane) { + preferencePane = [[GrowlITTSWPrefs alloc] initWithBundle:[NSBundle bundleWithIdentifier:@"com.ithinksw.growl-ittsw"]]; + } return preferencePane; -}*/ +} //we implement requiresPositioning entirely because it was added as a requirement for doing 1.1 plugins, however //we don't really care if positioning is required or not, because we are only ever in the menubar. diff --git a/GrowlITTSWPrefs.h b/GrowlITTSWPrefs.h index e2c287d..a83d30f 100644 --- a/GrowlITTSWPrefs.h +++ b/GrowlITTSWPrefs.h @@ -1,6 +1,44 @@ #import +#import +#import @interface GrowlITTSWPrefs : NSPreferencePane { + IBOutlet NSPopUpButton *appearanceEffectButton; + IBOutlet NSSlider *appearanceSpeedSlider; + IBOutlet NSPopUpButton *vanishEffectButton; + IBOutlet NSSlider *vanishSpeedSlider; + IBOutlet NSSlider *vanishDelaySlider; + + IBOutlet NSPopUpButton *backgroundStyleButton; + IBOutlet NSColorWell *backgroundColorWell; + IBOutlet NSPopUpButton *windowSizeButton; + + IBOutlet NSPopUpButton *screenButton; } ++ (Class)appearanceEffect; ++ (float)appearanceSpeed; ++ (Class)vanishEffect; ++ (float)vanishSpeed; ++ (float)vanishDelay; ++ (ITTSWBackgroundMode)backgroundStyle; ++ (NSColor *)backgroundColor; ++ (ITTransientStatusWindowSizing)windowSize; ++ (int)screenIndex; ++ (NSScreen *)screen; ++ (ITHorizontalWindowPosition)horizontalPosition; ++ (ITVerticalWindowPosition)verticalPosition; + +- (IBAction)setAppearanceEffect:(id)sender; +- (IBAction)setAppearanceSpeed:(id)sender; +- (IBAction)setVanishEffect:(id)sender; +- (IBAction)setVanishSpeed:(id)sender; +- (IBAction)setVanishDelay:(id)sender; + +- (IBAction)setBackgroundStyle:(id)sender; +- (IBAction)setBackgroundColor:(id)sender; +- (IBAction)setWindowSize:(id)sender; + +- (IBAction)setScreen:(id)sender; + @end diff --git a/GrowlITTSWPrefs.m b/GrowlITTSWPrefs.m index 395b2ff..df4f7bf 100644 --- a/GrowlITTSWPrefs.m +++ b/GrowlITTSWPrefs.m @@ -1,6 +1,278 @@ #import "GrowlITTSWPrefs.h" +#import "GrowlPositioningDefines.h" #import "GrowlDefinesInternal.h" +#define GrowlITTSWPrefsDomain @"com.ithinksw.growl-ittsw" + +@interface GrowlPositionController ++ (enum GrowlPosition)selectedOriginPosition; +@end @implementation GrowlITTSWPrefs ++ (Class)appearanceEffect { + SYNCHRONIZE_GROWL_PREFS(); + NSString *className = nil; + READ_GROWL_PREF_VALUE(@"appearanceEffect", GrowlITTSWPrefsDomain, NSString *, &className); + if (className) { + Class effectClass = NSClassFromString(className); + if (effectClass && [effectClass isSubclassOfClass:[ITWindowEffect class]]) { + return effectClass; + } + } + return NSClassFromString(@"ITCutWindowEffect"); +} + ++ (float)appearanceSpeed { + SYNCHRONIZE_GROWL_PREFS(); + float appearanceSpeed = 0.8f; + READ_GROWL_PREF_FLOAT(@"appearanceSpeed", GrowlITTSWPrefsDomain, &appearanceSpeed); + return appearanceSpeed; +} + ++ (Class)vanishEffect { + SYNCHRONIZE_GROWL_PREFS(); + NSString *className = nil; + READ_GROWL_PREF_VALUE(@"vanishEffect", GrowlITTSWPrefsDomain, NSString *, &className); + if (className) { + Class effectClass = NSClassFromString(className); + if (effectClass && [effectClass isSubclassOfClass:[ITWindowEffect class]]) { + return effectClass; + } + } + return NSClassFromString(@"ITCutWindowEffect"); +} + ++ (float)vanishSpeed { + SYNCHRONIZE_GROWL_PREFS(); + float vanishSpeed = 0.8f; + READ_GROWL_PREF_FLOAT(@"vanishSpeed", GrowlITTSWPrefsDomain, &vanishSpeed); + return vanishSpeed; +} + ++ (float)vanishDelay { + SYNCHRONIZE_GROWL_PREFS(); + float vanishDelay = 4.0f; + READ_GROWL_PREF_FLOAT(@"vanishDelay", GrowlITTSWPrefsDomain, &vanishDelay); + return vanishDelay; +} + ++ (ITTSWBackgroundMode)backgroundStyle { + SYNCHRONIZE_GROWL_PREFS(); + int backgroundStyle = ITTSWBackgroundReadable; + READ_GROWL_PREF_INT(@"backgroundStyle", GrowlITTSWPrefsDomain, &backgroundStyle); + return backgroundStyle; +} + ++ (NSColor *)backgroundColor { + SYNCHRONIZE_GROWL_PREFS(); + NSData *backgroundColorData = nil; + READ_GROWL_PREF_VALUE(@"backgroundColor", GrowlITTSWPrefsDomain, NSData *, &backgroundColorData); + if (backgroundColorData && [backgroundColorData isKindOfClass:[NSData class]]) { + NSColor *backgroundColor = [NSUnarchiver unarchiveObjectWithData:backgroundColorData]; + if (backgroundColor && [backgroundColor isKindOfClass:[NSColor class]]) { + return backgroundColor; + } + } + return [NSColor blueColor]; +} + ++ (ITTransientStatusWindowSizing)windowSize { + SYNCHRONIZE_GROWL_PREFS(); + ITTransientStatusWindowSizing windowSize = ITTransientStatusWindowMini; + READ_GROWL_PREF_INT(@"windowSize", GrowlITTSWPrefsDomain, &windowSize); + return windowSize; +} + ++ (int)screenIndex { + SYNCHRONIZE_GROWL_PREFS(); + int screenIndex = 0; + READ_GROWL_PREF_INT(@"screenIndex", GrowlITTSWPrefsDomain, &screenIndex); + return screenIndex; +} + ++ (NSScreen *)screen { + NSArray *screens = [NSScreen screens]; + int screenIndex = [GrowlITTSWPrefs screenIndex]; + if ([screens count] >= (screenIndex+1)) { + return [screens objectAtIndex:screenIndex]; + } + return [screens objectAtIndex:0]; +} + ++ (ITHorizontalWindowPosition)horizontalPosition { + switch ([GrowlPositionController selectedOriginPosition]) { + case GrowlBottomLeftPosition: + case GrowlTopLeftPosition: + return ITWindowPositionLeft; + break; + default: + case GrowlBottomRightPosition: + case GrowlTopRightPosition: + return ITWindowPositionRight; + break; + } +} + ++ (ITVerticalWindowPosition)verticalPosition { + switch ([GrowlPositionController selectedOriginPosition]) { + case GrowlBottomLeftPosition: + case GrowlBottomRightPosition: + return ITWindowPositionBottom; + break; + default: + case GrowlTopLeftPosition: + case GrowlTopRightPosition: + return ITWindowPositionTop; + break; + } +} + +- (NSString *)mainNibName { + return @"GrowlITTSWPrefs"; +} + +- (void)didSelect { + [appearanceEffectButton selectItemAtIndex:[appearanceEffectButton indexOfItemWithRepresentedObject:[GrowlITTSWPrefs appearanceEffect]]]; + [appearanceSpeedSlider setFloatValue:-([GrowlITTSWPrefs appearanceSpeed])]; + [vanishEffectButton selectItemAtIndex:[vanishEffectButton indexOfItemWithRepresentedObject:[GrowlITTSWPrefs vanishEffect]]]; + [vanishSpeedSlider setFloatValue:-([GrowlITTSWPrefs vanishSpeed])]; + [vanishDelaySlider setFloatValue:[GrowlITTSWPrefs vanishDelay]]; + + ITTSWBackgroundMode backgroundStyle = [GrowlITTSWPrefs backgroundStyle]; + [backgroundStyleButton selectItemWithTag:backgroundStyle]; + if (backgroundStyle == ITTSWBackgroundColored) { + [backgroundColorWell setEnabled:YES]; + } else { + [backgroundColorWell setEnabled:NO]; + } + [[NSColorPanel sharedColorPanel] setShowsAlpha:YES]; + [backgroundColorWell setColor:[GrowlITTSWPrefs backgroundColor]]; + [windowSizeButton selectItemWithTag:[GrowlITTSWPrefs windowSize]]; + + [screenButton removeAllItems]; + NSArray *screens = [NSScreen screens]; + int screenCount = 0; + for (NSScreen *screen in screens) { + NSSize screenSize = [screen frame].size; + NSMenuItem *screenItem = [[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@"Screen %i (%1.0fx%1.0f)", screenCount+1, screenSize.width, screenSize.height] action:NULL keyEquivalent:@""]; + [screenItem setRepresentedObject:screen]; + [[screenButton menu] addItem:screenItem]; + screenCount++; + } + if (screenCount > 1) { + [screenButton setEnabled:YES]; + } else { + [screenButton setEnabled:NO]; + } + [screenButton selectItemAtIndex:[screenButton indexOfItemWithRepresentedObject:[GrowlITTSWPrefs screen]]]; +} + +- (void)awakeFromNib { + NSArray *effectClasses = [ITWindowEffect effectClasses]; + for (Class effectClass in effectClasses) { + NSMenuItem *appearanceEffectItem = [[NSMenuItem alloc] initWithTitle:[effectClass effectName] action:NULL keyEquivalent:@""]; + NSMenuItem *vanishEffectItem = [[NSMenuItem alloc] initWithTitle:[effectClass effectName] action:NULL keyEquivalent:@""]; + [appearanceEffectItem setRepresentedObject:effectClass]; + [vanishEffectItem setRepresentedObject:effectClass]; + + [[appearanceEffectButton menu] addItem:[appearanceEffectItem autorelease]]; + [[vanishEffectButton menu] addItem:[vanishEffectItem autorelease]]; + } + + NSArray *backgroundStyles = [NSArray arrayWithObjects: + [NSDictionary dictionaryWithObjectsAndKeys:@"Mac OS X", @"name", [NSNumber numberWithInt:ITTSWBackgroundApple], @"index", nil], + [NSDictionary dictionaryWithObjectsAndKeys:@"Very Readable", @"name", [NSNumber numberWithInt:ITTSWBackgroundReadable], @"index", nil], + [NSDictionary dictionaryWithObjectsAndKeys:@"Custom Color...", @"name", [NSNumber numberWithInt:ITTSWBackgroundColored], @"index", nil], + nil]; + for (NSDictionary *backgroundStyleDict in backgroundStyles) { + NSString *backgroundStyleName = [backgroundStyleDict objectForKey:@"name"]; + ITTSWBackgroundMode backgroundStyle = [[backgroundStyleDict objectForKey:@"index"] intValue]; + NSMenuItem *backgroundStyleItem = [[NSMenuItem alloc] initWithTitle:backgroundStyleName action:NULL keyEquivalent:@""]; + [backgroundStyleItem setTag:backgroundStyle]; + + [[backgroundStyleButton menu] addItem:[backgroundStyleItem autorelease]]; + } + + NSArray *windowSizes = [NSArray arrayWithObjects: + [NSDictionary dictionaryWithObjectsAndKeys:@"Regular", @"name", [NSNumber numberWithInt:ITTransientStatusWindowRegular], @"index", nil], + [NSDictionary dictionaryWithObjectsAndKeys:@"Small", @"name", [NSNumber numberWithInt:ITTransientStatusWindowSmall], @"index", nil], + [NSDictionary dictionaryWithObjectsAndKeys:@"Mini", @"name", [NSNumber numberWithInt:ITTransientStatusWindowMini], @"index", nil], + nil]; + for (NSDictionary *windowSizeDict in windowSizes) { + NSString *windowSizeName = [windowSizeDict objectForKey:@"name"]; + ITTransientStatusWindowSizing windowSize = [[windowSizeDict objectForKey:@"index"] intValue]; + NSMenuItem *windowSizeItem = [[NSMenuItem alloc] initWithTitle:windowSizeName action:NULL keyEquivalent:@""]; + [windowSizeItem setTag:windowSize]; + + [[windowSizeButton menu] addItem:[windowSizeItem autorelease]]; + } + + [self didSelect]; +} + +- (IBAction)setAppearanceEffect:(id)sender { + SYNCHRONIZE_GROWL_PREFS(); + WRITE_GROWL_PREF_VALUE(@"appearanceEffect", NSStringFromClass([[appearanceEffectButton selectedItem] representedObject]), GrowlITTSWPrefsDomain); + UPDATE_GROWL_PREFS(); +} + +- (IBAction)setAppearanceSpeed:(id)sender { + SYNCHRONIZE_GROWL_PREFS(); + float appearanceSpeed = -([appearanceSpeedSlider floatValue]); + WRITE_GROWL_PREF_FLOAT(@"appearanceSpeed", appearanceSpeed, GrowlITTSWPrefsDomain); + UPDATE_GROWL_PREFS(); +} + +- (IBAction)setVanishEffect:(id)sender { + SYNCHRONIZE_GROWL_PREFS(); + WRITE_GROWL_PREF_VALUE(@"vanishEffect", NSStringFromClass([[vanishEffectButton selectedItem] representedObject]), GrowlITTSWPrefsDomain); + UPDATE_GROWL_PREFS(); +} + +- (IBAction)setVanishSpeed:(id)sender { + SYNCHRONIZE_GROWL_PREFS(); + float vanishSpeed = -([vanishSpeedSlider floatValue]); + WRITE_GROWL_PREF_FLOAT(@"vanishSpeed", vanishSpeed, GrowlITTSWPrefsDomain); + UPDATE_GROWL_PREFS(); +} + +- (IBAction)setVanishDelay:(id)sender { + SYNCHRONIZE_GROWL_PREFS(); + float vanishDelay = [vanishDelaySlider floatValue]; + WRITE_GROWL_PREF_FLOAT(@"vanishDelay", vanishDelay, GrowlITTSWPrefsDomain); + UPDATE_GROWL_PREFS(); +} + +- (IBAction)setBackgroundStyle:(id)sender { + SYNCHRONIZE_GROWL_PREFS(); + int style = [[backgroundStyleButton selectedItem] tag]; + if (style == 2) { // colored + [backgroundColorWell setEnabled:YES]; + } else { + [backgroundColorWell setEnabled:NO]; + } + WRITE_GROWL_PREF_INT(@"backgroundStyle", style, GrowlITTSWPrefsDomain); + UPDATE_GROWL_PREFS(); +} + +- (IBAction)setBackgroundColor:(id)sender { + SYNCHRONIZE_GROWL_PREFS(); + WRITE_GROWL_PREF_VALUE(@"backgroundColor", [NSArchiver archivedDataWithRootObject:[backgroundColorWell color]], GrowlITTSWPrefsDomain); + UPDATE_GROWL_PREFS(); +} + +- (IBAction)setWindowSize:(id)sender { + SYNCHRONIZE_GROWL_PREFS(); + int size = [[windowSizeButton selectedItem] tag]; + WRITE_GROWL_PREF_INT(@"windowSize", size, GrowlITTSWPrefsDomain); + UPDATE_GROWL_PREFS(); +} + +- (IBAction)setScreen:(id)sender { + SYNCHRONIZE_GROWL_PREFS(); + int screenIndex = [screenButton indexOfSelectedItem]; + WRITE_GROWL_PREF_INT(@"screenIndex", screenIndex, GrowlITTSWPrefsDomain); + UPDATE_GROWL_PREFS(); +} + @end -- 2.20.1