//
#import "GrowlITTSWController.h"
+#import "GrowlITTSWPrefs.h"
-#import <ITKit/ITTSWBackgroundView.h>
#import <ITKit/ITWindowEffect.h>
+#import <ITKit/ITTSWBackgroundView.h>
#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];
@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];
}
}
- 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];
#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