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