Plugins/Displays/Bubbles/GrowlBubblesWindowController.m
author boredzo
Sun Jul 06 15:10:15 2008 +0000 (2008-07-06)
changeset 4135 9d0747a53f45
parent 3958 157225f6bfee
child 4246 4f52d1d98978
child 4771 d398be175a6e
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
//  GrowlBubblesWindowController.m
boredzo@2402
     3
//  Growl
boredzo@2402
     4
//
boredzo@2402
     5
//  Created by Nelson Elhage on Wed Jun 09 2004.
boredzo@2402
     6
//  Name changed from KABubbleWindowController.m by Justin Burns on Fri Nov 05 2004.
ingmarstein@3040
     7
//  Copyright (c) 2004-2006 The Growl Project. All rights reserved.
boredzo@2402
     8
//
boredzo@2402
     9
boredzo@2402
    10
#import "GrowlBubblesWindowController.h"
boredzo@2402
    11
#import "GrowlBubblesWindowView.h"
boredzo@2402
    12
#import "GrowlBubblesPrefsController.h"
boredzo@2402
    13
#import "GrowlBubblesDefines.h"
ingmarstein@2699
    14
#import "GrowlApplicationNotification.h"
boredzo@2402
    15
#import "NSWindow+Transforms.h"
ingmarstein@2641
    16
#include "CFDictionaryAdditions.h"
jkp@2818
    17
#import "GrowlWindowTransition.h"
jkp@2817
    18
#import "GrowlFadingWindowTransition.h"
bgannin@3270
    19
#import "GrowlPositionController.h"
boredzo@2402
    20
boredzo@2402
    21
@implementation GrowlBubblesWindowController
boredzo@2402
    22
boredzo@2402
    23
#define GrowlBubblesPadding				5.0f
boredzo@2402
    24
boredzo@2402
    25
#pragma mark -
boredzo@2402
    26
rudy@2782
    27
- (id) init {
rudy@2782
    28
	screenNumber = 0U;
boredzo@2402
    29
	READ_GROWL_PREF_INT(GrowlBubblesScreen, GrowlBubblesPrefDomain, &screenNumber);
evands@3954
    30
	NSArray *screens = [NSScreen screens];
ingmarstein@3958
    31
	unsigned screensCount = [screens count];
evands@3954
    32
	if (screensCount) {
evands@3954
    33
		[self setScreen:((screensCount >= (screenNumber + 1)) ? [screens objectAtIndex:screenNumber] : [screens objectAtIndex:0])];
evands@3954
    34
	}
ingmarstein@2943
    35
rudy@2785
    36
	CFNumberRef prefsDuration = NULL;
rudy@2785
    37
	READ_GROWL_PREF_VALUE(GrowlBubblesDuration, GrowlBubblesPrefDomain, CFNumberRef, &prefsDuration);
evands@3637
    38
	[self setDisplayDuration:(prefsDuration ?
evands@3637
    39
							  [(NSNumber *)prefsDuration doubleValue] :
evands@3637
    40
							  GrowlBubblesDurationPrefDefault)];
boredzo@4135
    41
	if (prefsDuration) CFRelease(prefsDuration);
evands@3637
    42
boredzo@2402
    43
	// I tried setting the width/height to zero, since the view resizes itself later.
boredzo@2402
    44
	// This made it ignore the alpha at the edges (using 1.0 instead). Why?
boredzo@2402
    45
	// A window with a frame of NSZeroRect is off-screen and doesn't respect opacity even
boredzo@2402
    46
	// if moved on screen later. -Evan
boredzo@2402
    47
	NSPanel *panel = [[NSPanel alloc] initWithContentRect:NSMakeRect(0.0f, 0.0f, 270.0f, 65.0f)
boredzo@2402
    48
												styleMask:NSBorderlessWindowMask | NSNonactivatingPanelMask
boredzo@2402
    49
												  backing:NSBackingStoreBuffered
rudy@3005
    50
													defer:YES];
boredzo@2402
    51
	NSRect panelFrame = [panel frame];
boredzo@2402
    52
	[panel setBecomesKeyOnlyIfNeeded:YES];
boredzo@2402
    53
	[panel setHidesOnDeactivate:NO];
boredzo@2402
    54
	[panel setBackgroundColor:[NSColor clearColor]];
boredzo@2402
    55
	[panel setLevel:NSStatusWindowLevel];
boredzo@2402
    56
	[panel setSticky:YES];
jkp@2817
    57
	[panel setAlphaValue:0.0f];
boredzo@2402
    58
	[panel setOpaque:NO];
boredzo@2402
    59
	[panel setHasShadow:YES];
boredzo@2402
    60
	[panel setCanHide:NO];
boredzo@2402
    61
	[panel setOneShot:YES];
boredzo@2402
    62
	[panel useOptimizedDrawing:YES];
rudy@2782
    63
	[panel setMovableByWindowBackground:NO];
ingmarstein@2943
    64
rudy@2782
    65
	// Create the content view...
boredzo@2402
    66
	GrowlBubblesWindowView *view = [[GrowlBubblesWindowView alloc] initWithFrame:panelFrame];
boredzo@2402
    67
	[view setTarget:self];
boredzo@2402
    68
	[view setAction:@selector(notificationClicked:)];
boredzo@2402
    69
	[panel setContentView:view];
evands@3534
    70
	[view release];
ingmarstein@2943
    71
jkp@2817
    72
	// call super so everything else is set up...
ingmarstein@2943
    73
	if ((self = [super initWithWindow:panel])) {
ingmarstein@2943
    74
		// set up the transitions...
ingmarstein@2943
    75
		GrowlFadingWindowTransition *fader = [[GrowlFadingWindowTransition alloc] initWithWindow:panel];
ingmarstein@2943
    76
		[self addTransition:fader];
ingmarstein@2943
    77
		[self setStartPercentage:0 endPercentage:100 forTransition:fader];
ingmarstein@2943
    78
		[fader setAutoReverses:YES];
ingmarstein@2943
    79
		[fader release];
ingmarstein@2943
    80
	}
evands@3543
    81
	[panel release];
ingmarstein@2943
    82
jkp@2817
    83
	return self;
boredzo@2402
    84
}
boredzo@2402
    85
jkp@2817
    86
#pragma mark -
jkp@2817
    87
rudy@2782
    88
- (void) setNotification: (GrowlApplicationNotification *) theNotification {
rudy@2782
    89
	[super setNotification:theNotification];
rudy@2782
    90
	if (!theNotification)
rudy@2782
    91
		return;
ingmarstein@2943
    92
rudy@2782
    93
	NSDictionary *noteDict = [notification dictionaryRepresentation];
bgannin@3404
    94
	NSString *title = [notification title];
bgannin@3404
    95
	NSString *text  = [notification notificationDescription];
rudy@2782
    96
	NSImage *icon   = getObjectForKey(noteDict, GROWL_NOTIFICATION_ICON);
rudy@2782
    97
	int priority    = getIntegerForKey(noteDict, GROWL_NOTIFICATION_PRIORITY);
bgannin@3404
    98
	
rudy@2782
    99
	GrowlBubblesWindowView *view = [[self window] contentView];
rudy@2782
   100
	[view setPriority:priority];
bgannin@3404
   101
	[view setTitle:title];
bgannin@3404
   102
	[view setText:text];
rudy@2782
   103
	[view setIcon:icon];
rudy@2782
   104
	[view sizeToFit];
jkp@2841
   105
}
rudy@2782
   106
jkp@2841
   107
#pragma mark -
jkp@2841
   108
#pragma mark positioning methods
jkp@2841
   109
jkp@2841
   110
- (NSPoint) idealOriginInRect:(NSRect)rect {
jkp@2841
   111
	NSRect viewFrame = [[[self window] contentView] frame];
bgannin@3317
   112
	enum GrowlPosition originatingPosition = [[GrowlPositionController sharedInstance] originPosition];
bgannin@3270
   113
	NSPoint idealOrigin;
bgannin@3270
   114
	
bgannin@3270
   115
	switch(originatingPosition){
bgannin@3270
   116
		case GrowlTopRightPosition:
bgannin@3270
   117
			idealOrigin = NSMakePoint(NSMaxX(rect) - NSWidth(viewFrame) - GrowlBubblesPadding,
bgannin@3270
   118
									  NSMaxY(rect) - GrowlBubblesPadding - NSHeight(viewFrame));
bgannin@3270
   119
			break;
bgannin@3270
   120
		case GrowlTopLeftPosition:
bgannin@3270
   121
			idealOrigin = NSMakePoint(NSMinX(rect) + GrowlBubblesPadding,
bgannin@3270
   122
									  NSMaxY(rect) - GrowlBubblesPadding - NSHeight(viewFrame));
bgannin@3270
   123
			break;
bgannin@3270
   124
		case GrowlBottomLeftPosition:
bgannin@3270
   125
			idealOrigin = NSMakePoint(NSMinX(rect) + GrowlBubblesPadding,
bgannin@3270
   126
									  NSMinY(rect) + GrowlBubblesPadding);
bgannin@3270
   127
			break;
bgannin@3270
   128
		case GrowlBottomRightPosition:
bgannin@3270
   129
			idealOrigin = NSMakePoint(NSMaxX(rect) - NSWidth(viewFrame) - GrowlBubblesPadding,
bgannin@3270
   130
									  NSMinY(rect) + GrowlBubblesPadding);
bgannin@3270
   131
			break;
bgannin@3270
   132
		default:
bgannin@3270
   133
			idealOrigin = NSMakePoint(NSMaxX(rect) - NSWidth(viewFrame) - GrowlBubblesPadding,
bgannin@3270
   134
									  NSMaxY(rect) - GrowlBubblesPadding - NSHeight(viewFrame));
bgannin@3270
   135
			break;			
bgannin@3270
   136
	}
bgannin@3270
   137
	
bgannin@3270
   138
	return idealOrigin;	
jkp@2841
   139
}
jkp@2841
   140
boredzo@3095
   141
- (enum GrowlExpansionDirection) primaryExpansionDirection {
bgannin@3317
   142
	enum GrowlPosition originatingPosition = [[GrowlPositionController sharedInstance] originPosition];
bgannin@3270
   143
	enum GrowlExpansionDirection directionToExpand;
bgannin@3270
   144
	
bgannin@3270
   145
	switch(originatingPosition){
bgannin@3270
   146
		case GrowlTopLeftPosition:
bgannin@3270
   147
			directionToExpand = GrowlDownExpansionDirection;
bgannin@3270
   148
			break;
bgannin@3270
   149
		case GrowlTopRightPosition:
bgannin@3270
   150
			directionToExpand = GrowlDownExpansionDirection;
bgannin@3270
   151
			break;
bgannin@3270
   152
		case GrowlBottomLeftPosition:
bgannin@3270
   153
			directionToExpand = GrowlUpExpansionDirection;
bgannin@3270
   154
			break;
bgannin@3270
   155
		case GrowlBottomRightPosition:
bgannin@3270
   156
			directionToExpand = GrowlUpExpansionDirection;
bgannin@3270
   157
			break;
bgannin@3270
   158
		default:
bgannin@3270
   159
			directionToExpand = GrowlDownExpansionDirection;
bgannin@3270
   160
			break;			
bgannin@3270
   161
	}
bgannin@3270
   162
	
bgannin@3270
   163
	return directionToExpand;
jkp@2841
   164
}
jkp@2841
   165
boredzo@3095
   166
- (enum GrowlExpansionDirection) secondaryExpansionDirection {
bgannin@3317
   167
	enum GrowlPosition originatingPosition = [[GrowlPositionController sharedInstance] originPosition];
bgannin@3270
   168
	enum GrowlExpansionDirection directionToExpand;
bgannin@3270
   169
	
bgannin@3270
   170
	switch(originatingPosition){
bgannin@3270
   171
		case GrowlTopLeftPosition:
bgannin@3270
   172
			directionToExpand = GrowlRightExpansionDirection;
bgannin@3270
   173
			break;
bgannin@3270
   174
		case GrowlTopRightPosition:
bgannin@3270
   175
			directionToExpand = GrowlLeftExpansionDirection;
bgannin@3270
   176
			break;
bgannin@3270
   177
		case GrowlBottomLeftPosition:
bgannin@3270
   178
			directionToExpand = GrowlRightExpansionDirection;
bgannin@3270
   179
			break;
bgannin@3270
   180
		case GrowlBottomRightPosition:
bgannin@3270
   181
			directionToExpand = GrowlLeftExpansionDirection;
bgannin@3270
   182
			break;
bgannin@3270
   183
		default:
bgannin@3270
   184
			directionToExpand = GrowlRightExpansionDirection;
bgannin@3270
   185
			break;
bgannin@3270
   186
	}
bgannin@3270
   187
	
bgannin@3270
   188
	return directionToExpand;
jkp@2841
   189
}
jkp@2841
   190
jkp@2841
   191
- (float) requiredDistanceFromExistingDisplays {
jkp@2841
   192
	return GrowlBubblesPadding;
rudy@2782
   193
}
rudy@2782
   194
boredzo@2402
   195
@end