Plugins/Displays/Bezel/GrowlBezelWindowController.m
author boredzo
Sun Jul 06 15:10:15 2008 +0000 (2008-07-06)
changeset 4135 9d0747a53f45
parent 3958 157225f6bfee
child 4246 4f52d1d98978
child 4743 88628c6c7011
permissions -rw-r--r--
CFRelease the duration preference value if we get one. Found by the clang static analyzer.
boredzo@2402
     1
//
boredzo@2402
     2
//  GrowlBezelWindowController.m
boredzo@2402
     3
//  Display Plugins
boredzo@2402
     4
//
boredzo@2402
     5
//  Created by Jorge Salvador Caffarena on 09/09/04.
boredzo@2402
     6
//  Copyright 2004 Jorge Salvador Caffarena. All rights reserved.
boredzo@2402
     7
//
boredzo@2402
     8
boredzo@2402
     9
#import "GrowlBezelWindowController.h"
boredzo@2402
    10
#import "GrowlBezelWindowView.h"
boredzo@2402
    11
#import "GrowlBezelPrefs.h"
boredzo@2402
    12
#import "NSWindow+Transforms.h"
rudy@2807
    13
#include "CFDictionaryAdditions.h"
jkp@2817
    14
#import "GrowlFadingWindowTransition.h"
jkp@2818
    15
#import "GrowlFlippingWindowTransition.h"
rudy@2829
    16
#import "GrowlShrinkingWindowTransition.h"
rudy@3300
    17
#import "GrowlRipplingWindowTransition.h"
jkp@2818
    18
#import "GrowlWindowTransition.h"
ingmarstein@2941
    19
#import "GrowlApplicationNotification.h"
boredzo@2402
    20
boredzo@2402
    21
@implementation GrowlBezelWindowController
boredzo@2402
    22
boredzo@2402
    23
#define MIN_DISPLAY_TIME 3.0
boredzo@2402
    24
#define GrowlBezelPadding 10.0f
boredzo@2402
    25
rudy@2807
    26
- (id) init {
rudy@2807
    27
	int sizePref = 0;
rudy@2807
    28
	screenNumber = 0U;
rudy@2807
    29
	shrinkEnabled = NO;
rudy@2807
    30
	flipEnabled = NO;
rudy@2807
    31
rudy@2807
    32
	CFNumberRef prefsDuration = NULL;
rudy@2807
    33
	READ_GROWL_PREF_VALUE(GrowlBezelDuration, GrowlBezelPrefDomain, CFNumberRef, &prefsDuration);
evands@3637
    34
	[self setDisplayDuration:(prefsDuration ?
evands@3637
    35
							  [(NSNumber *)prefsDuration doubleValue] :
evands@3637
    36
							  MIN_DISPLAY_TIME)];
boredzo@4135
    37
	if (prefsDuration) CFRelease(prefsDuration);
rudy@2807
    38
rudy@2807
    39
	READ_GROWL_PREF_INT(BEZEL_SCREEN_PREF, GrowlBezelPrefDomain, &screenNumber);
evands@3954
    40
	NSArray *screens = [NSScreen screens];
ingmarstein@3958
    41
	unsigned screensCount = [screens count];
evands@3954
    42
	if (screensCount) {
evands@3954
    43
		[self setScreen:((screensCount >= (screenNumber + 1)) ? [screens objectAtIndex:screenNumber] : [screens objectAtIndex:0])];
evands@3954
    44
	}
ingmarstein@2943
    45
rudy@2807
    46
	READ_GROWL_PREF_INT(BEZEL_SIZE_PREF, GrowlBezelPrefDomain, &sizePref);
rudy@2807
    47
	READ_GROWL_PREF_BOOL(BEZEL_SHRINK_PREF, GrowlBezelPrefDomain, &shrinkEnabled);
rudy@2807
    48
	READ_GROWL_PREF_BOOL(BEZEL_FLIP_PREF, GrowlBezelPrefDomain, &flipEnabled);
rudy@2807
    49
rudy@2807
    50
	NSRect sizeRect;
rudy@2807
    51
	sizeRect.origin.x = 0.0f;
rudy@2807
    52
	sizeRect.origin.y = 0.0f;
rudy@2807
    53
rudy@2807
    54
	if (sizePref == BEZEL_SIZE_NORMAL) {
rudy@2807
    55
		sizeRect.size.width = 211.0f;
rudy@2807
    56
		sizeRect.size.height = 206.0f;
rudy@2807
    57
	} else {
rudy@2807
    58
		sizeRect.size.width = 160.0f;
rudy@2807
    59
		sizeRect.size.height = 160.0f;
rudy@2807
    60
	}
rudy@2807
    61
	NSPanel *panel = [[NSPanel alloc] initWithContentRect:sizeRect
rudy@2807
    62
												styleMask:NSBorderlessWindowMask
rudy@2807
    63
												  backing:NSBackingStoreBuffered
rudy@3005
    64
													defer:YES];
rudy@2807
    65
	NSRect panelFrame = [panel frame];
rudy@2807
    66
	[panel setBecomesKeyOnlyIfNeeded:YES];
rudy@2807
    67
	[panel setHidesOnDeactivate:NO];
rudy@2807
    68
	[panel setBackgroundColor:[NSColor clearColor]];
rudy@2807
    69
	[panel setLevel:NSStatusWindowLevel];
rudy@2807
    70
	[panel setIgnoresMouseEvents:YES];
rudy@2807
    71
	[panel setSticky:YES];
rudy@2807
    72
	[panel setOpaque:NO];
rudy@2807
    73
	[panel setHasShadow:NO];
rudy@2807
    74
	[panel setCanHide:NO];
rudy@2807
    75
	[panel setOneShot:YES];
rudy@2807
    76
	[panel useOptimizedDrawing:YES];
jkp@2817
    77
	[panel setAlphaValue:0.0f];
rudy@2807
    78
	[panel setDelegate:self];
rudy@2807
    79
rudy@2807
    80
	GrowlBezelWindowView *view = [[GrowlBezelWindowView alloc] initWithFrame:panelFrame];
rudy@2807
    81
	[view setTarget:self];
rudy@2807
    82
	[view setAction:@selector(notificationClicked:)];
rudy@2807
    83
	[panel setContentView:view];
evands@3534
    84
	[view release];
evands@3534
    85
evands@3534
    86
	panelFrame = [[panel contentView] frame];
rudy@2807
    87
	[panel setFrame:panelFrame display:NO];
rudy@2807
    88
jkp@2817
    89
	// call super so everything else is set up...
ingmarstein@2943
    90
	if ((self = [super initWithWindow:panel])) {
ingmarstein@2943
    91
		// set up the transitions...
rudy@3300
    92
		/*GrowlRipplingWindowTransition *ripple = [[GrowlRipplingWindowTransition alloc] initWithWindow:panel];
rudy@3300
    93
		[self addTransition:ripple];
rudy@3300
    94
		[self setStartPercentage:0 endPercentage:100 forTransition:ripple];
rudy@3300
    95
		[ripple setAutoReverses:NO];
rudy@3300
    96
		[ripple release];
rudy@3300
    97
		[panel setAlphaValue:1.0f];
rudy@3300
    98
		*/
ingmarstein@2943
    99
		GrowlFadingWindowTransition *fader = [[GrowlFadingWindowTransition alloc] initWithWindow:panel];
ingmarstein@2943
   100
		[self addTransition:fader];
ingmarstein@2943
   101
		[self setStartPercentage:0 endPercentage:100 forTransition:fader];
ingmarstein@2943
   102
		[fader setAutoReverses:YES];
ingmarstein@2943
   103
		[fader release];
ingmarstein@2943
   104
ingmarstein@2943
   105
		if (shrinkEnabled) {
ingmarstein@2943
   106
			GrowlShrinkingWindowTransition *shrinker = [[GrowlShrinkingWindowTransition alloc] initWithWindow:panel];
ingmarstein@2943
   107
			[self addTransition:shrinker];
ingmarstein@2943
   108
			[self setStartPercentage:0 endPercentage:80 forTransition:shrinker];
ingmarstein@2943
   109
			[shrinker setAutoReverses:YES];
ingmarstein@2943
   110
			[shrinker release];
ingmarstein@2943
   111
		}
ingmarstein@2943
   112
		if (flipEnabled) {
ingmarstein@2943
   113
			GrowlFlippingWindowTransition *flipper = [[GrowlFlippingWindowTransition alloc] initWithWindow:panel];
ingmarstein@2943
   114
			[self addTransition:flipper];
ingmarstein@2943
   115
			[self setStartPercentage:0 endPercentage:100 forTransition:flipper];
ingmarstein@2943
   116
			[flipper setFlipsX:YES];
ingmarstein@2943
   117
			[flipper setAutoReverses:YES];
ingmarstein@2943
   118
			[flipper release];
ingmarstein@2943
   119
		}
rudy@2822
   120
	}
evands@3543
   121
	[panel release];
evands@3543
   122
jkp@2817
   123
	return self;
rudy@2807
   124
}
rudy@2807
   125
jkp@2817
   126
#pragma mark -
jkp@2817
   127
rudy@2807
   128
- (void) setNotification: (GrowlApplicationNotification *) theNotification {
rudy@2807
   129
	[super setNotification:theNotification];
rudy@2807
   130
	if (!theNotification)
rudy@2807
   131
		return;
ingmarstein@2941
   132
rudy@2807
   133
	NSDictionary *noteDict = [notification dictionaryRepresentation];
rudy@2807
   134
	NSString *title = [notification title];
evands@2922
   135
	NSString *text  = [notification notificationDescription];
rudy@2807
   136
	NSImage *icon   = getObjectForKey(noteDict, GROWL_NOTIFICATION_ICON);
ingmarstein@2941
   137
	int myPriority  = getIntegerForKey(noteDict, GROWL_NOTIFICATION_PRIORITY);
ingmarstein@2943
   138
rudy@2807
   139
	GrowlBezelWindowView *view = [[self window] contentView];
evands@2910
   140
	[view setPriority:myPriority];
bgannin@3404
   141
	[view setTitle:title];
bgannin@3404
   142
	[view setText:text];
rudy@2807
   143
	[view setIcon:icon];
boredzo@2402
   144
}
boredzo@2402
   145
boredzo@2402
   146
#pragma mark -
jkp@2841
   147
#pragma mark positioning methods
jkp@2841
   148
jkp@2841
   149
- (NSPoint) idealOriginInRect:(NSRect)rect {
jkp@2841
   150
	NSRect viewFrame = [[[self window] contentView] frame];
ingmarstein@2943
   151
jkp@2841
   152
	NSPoint result;
jkp@2841
   153
	int positionPref = BEZEL_POSITION_DEFAULT;
jkp@2841
   154
	READ_GROWL_PREF_INT(BEZEL_POSITION_PREF, GrowlBezelPrefDomain, &positionPref);
jkp@2841
   155
	switch (positionPref) {
jkp@2841
   156
		default:
jkp@2841
   157
		case BEZEL_POSITION_DEFAULT:
jkp@2841
   158
			result.x = rect.origin.x + ceilf((NSWidth(rect) - NSWidth(viewFrame)) * 0.5f);
jkp@2841
   159
			result.y = rect.origin.y + 140.0f;
jkp@2841
   160
			break;
jkp@2841
   161
		case BEZEL_POSITION_TOPRIGHT:
jkp@2841
   162
			result.x = NSMaxX(rect) - NSWidth(viewFrame) - GrowlBezelPadding;
jkp@2841
   163
			result.y = NSMaxY(rect) - GrowlBezelPadding - NSHeight(viewFrame);
jkp@2841
   164
			break;
jkp@2841
   165
		case BEZEL_POSITION_BOTTOMRIGHT:
jkp@2841
   166
			result.x = NSMaxX(rect) - NSWidth(viewFrame) - GrowlBezelPadding;
jkp@2841
   167
			result.y = rect.origin.y + GrowlBezelPadding;
jkp@2841
   168
			break;
jkp@2841
   169
		case BEZEL_POSITION_BOTTOMLEFT:
jkp@2841
   170
			result.x = rect.origin.x + GrowlBezelPadding;
jkp@2841
   171
			result.y = rect.origin.y + GrowlBezelPadding;
jkp@2841
   172
			break;
jkp@2841
   173
		case BEZEL_POSITION_TOPLEFT:
jkp@2841
   174
			result.x = rect.origin.x + GrowlBezelPadding;
jkp@2841
   175
			result.y = NSMaxY(rect) - GrowlBezelPadding - NSHeight(viewFrame);
jkp@2841
   176
			break;
jkp@2841
   177
	}
jkp@2841
   178
	return result;
jkp@2841
   179
}
jkp@2841
   180
boredzo@3095
   181
- (enum GrowlExpansionDirection) primaryExpansionDirection {
jkp@2841
   182
	return GrowlNoExpansionDirection;
jkp@2841
   183
}
jkp@2841
   184
boredzo@3095
   185
- (enum GrowlExpansionDirection) secondaryExpansionDirection {
jkp@2841
   186
	return GrowlNoExpansionDirection;
jkp@2841
   187
}
jkp@2841
   188
jkp@2841
   189
- (float) requiredDistanceFromExistingDisplays {
jkp@2841
   190
	return GrowlBezelPadding;
jkp@2841
   191
}
jkp@2841
   192
bgannin@3280
   193
- (BOOL) requiresPositioning {
bgannin@3280
   194
	return NO;
bgannin@3280
   195
}
bgannin@3280
   196
boredzo@2402
   197
@end