|
boredzo@2402
|
1 |
//
|
|
boredzo@2402
|
2 |
// GrowlSmokeWindowController.m
|
|
boredzo@2402
|
3 |
// Display Plugins
|
|
boredzo@2402
|
4 |
//
|
|
boredzo@2402
|
5 |
// Created by Matthew Walton on 11/09/2004.
|
|
ingmarstein@3040
|
6 |
// Copyright 2004-2006 The Growl Project. All rights reserved.
|
|
boredzo@2402
|
7 |
//
|
|
boredzo@2402
|
8 |
// Most of this is lifted from KABubbleWindowController in the Growl source
|
|
boredzo@2402
|
9 |
|
|
boredzo@2402
|
10 |
#import "GrowlSmokeWindowController.h"
|
|
boredzo@2402
|
11 |
#import "GrowlSmokeWindowView.h"
|
|
boredzo@2402
|
12 |
#import "GrowlSmokeDefines.h"
|
|
boredzo@2402
|
13 |
#import "GrowlDefinesInternal.h"
|
|
boredzo@2402
|
14 |
#import "NSWindow+Transforms.h"
|
|
ingmarstein@2699
|
15 |
#import "GrowlApplicationNotification.h"
|
|
rudy@2821
|
16 |
#import "GrowlWindowTransition.h"
|
|
rudy@2821
|
17 |
#import "GrowlFadingWindowTransition.h"
|
|
ingmarstein@2641
|
18 |
#include "CFDictionaryAdditions.h"
|
|
boredzo@2402
|
19 |
|
|
boredzo@2402
|
20 |
@implementation GrowlSmokeWindowController
|
|
boredzo@2402
|
21 |
|
|
rudy@2945
|
22 |
//static const double gAdditionalLinesDisplayTime = 0.5;
|
|
rudy@2945
|
23 |
//static const double gMaxDisplayTime = 10.0;
|
|
boredzo@2402
|
24 |
|
|
rudy@2821
|
25 |
- (id) init {
|
|
rudy@2905
|
26 |
screenNumber = 0U;
|
|
boredzo@2402
|
27 |
READ_GROWL_PREF_INT(GrowlSmokeScreenPref, GrowlSmokePrefDomain, &screenNumber);
|
|
evands@3954
|
28 |
NSArray *screens = [NSScreen screens];
|
|
ingmarstein@3958
|
29 |
unsigned screensCount = [screens count];
|
|
evands@3954
|
30 |
if (screensCount) {
|
|
evands@3954
|
31 |
[self setScreen:((screensCount >= (screenNumber + 1)) ? [screens objectAtIndex:screenNumber] : [screens objectAtIndex:0])];
|
|
evands@3954
|
32 |
}
|
|
rudy@2821
|
33 |
|
|
rudy@2821
|
34 |
CFNumberRef prefsDuration = NULL;
|
|
rudy@2821
|
35 |
READ_GROWL_PREF_VALUE(GrowlSmokeDurationPref, GrowlSmokePrefDomain, CFNumberRef, &prefsDuration);
|
|
evands@3637
|
36 |
[self setDisplayDuration:(prefsDuration ?
|
|
evands@3637
|
37 |
[(NSNumber *)prefsDuration doubleValue] :
|
|
evands@3637
|
38 |
GrowlSmokeDurationPrefDefault)];
|
|
boredzo@4135
|
39 |
if (prefsDuration) CFRelease(prefsDuration);
|
|
boredzo@2402
|
40 |
|
|
boredzo@2402
|
41 |
NSPanel *panel = [[NSPanel alloc] initWithContentRect:NSMakeRect(0.0f, 0.0f, GrowlSmokeNotificationWidth, 65.0f)
|
|
boredzo@2402
|
42 |
styleMask:NSBorderlessWindowMask | NSNonactivatingPanelMask
|
|
boredzo@2402
|
43 |
backing:NSBackingStoreBuffered
|
|
rudy@3005
|
44 |
defer:YES];
|
|
boredzo@2402
|
45 |
NSRect panelFrame = [panel frame];
|
|
boredzo@2402
|
46 |
[panel setBecomesKeyOnlyIfNeeded:YES];
|
|
boredzo@2402
|
47 |
[panel setHidesOnDeactivate:NO];
|
|
boredzo@2402
|
48 |
[panel setBackgroundColor:[NSColor clearColor]];
|
|
boredzo@2402
|
49 |
[panel setLevel:NSStatusWindowLevel];
|
|
boredzo@2402
|
50 |
[panel setSticky:YES];
|
|
boredzo@2402
|
51 |
[panel setAlphaValue:0.0f];
|
|
boredzo@2402
|
52 |
[panel setOpaque:NO];
|
|
boredzo@2402
|
53 |
[panel setHasShadow:YES];
|
|
boredzo@2402
|
54 |
[panel setCanHide:NO];
|
|
boredzo@2402
|
55 |
[panel setOneShot:YES];
|
|
boredzo@2402
|
56 |
[panel useOptimizedDrawing:YES];
|
|
ingmarstein@2943
|
57 |
|
|
boredzo@2402
|
58 |
GrowlSmokeWindowView *view = [[GrowlSmokeWindowView alloc] initWithFrame:panelFrame];
|
|
boredzo@2402
|
59 |
[view setTarget:self];
|
|
boredzo@2402
|
60 |
[view setAction:@selector(notificationClicked:)];
|
|
rudy@2821
|
61 |
[panel setContentView:view];
|
|
evands@3534
|
62 |
[view release];
|
|
rudy@2821
|
63 |
|
|
rudy@2821
|
64 |
// call super so everything else is set up...
|
|
ingmarstein@2943
|
65 |
if ((self = [super initWithWindow:panel])) {
|
|
ingmarstein@2943
|
66 |
// set up the transitions...
|
|
ingmarstein@2943
|
67 |
GrowlFadingWindowTransition *fader = [[GrowlFadingWindowTransition alloc] initWithWindow:panel];
|
|
ingmarstein@2943
|
68 |
[self addTransition:fader];
|
|
ingmarstein@2943
|
69 |
[self setStartPercentage:0 endPercentage:100 forTransition:fader];
|
|
ingmarstein@2943
|
70 |
[fader setAutoReverses:YES];
|
|
ingmarstein@2943
|
71 |
[fader release];
|
|
ingmarstein@2943
|
72 |
}
|
|
evands@3543
|
73 |
[panel release];
|
|
ingmarstein@2943
|
74 |
|
|
rudy@2821
|
75 |
return self;
|
|
rudy@2821
|
76 |
}
|
|
rudy@2821
|
77 |
|
|
boredzo@2402
|
78 |
#pragma mark -
|
|
ingmarstein@3036
|
79 |
- (void) setNotification:(GrowlApplicationNotification *)theNotification {
|
|
rudy@2821
|
80 |
[super setNotification:theNotification];
|
|
rudy@2821
|
81 |
if (!theNotification)
|
|
rudy@2821
|
82 |
return;
|
|
ingmarstein@2943
|
83 |
|
|
rudy@2821
|
84 |
NSDictionary *noteDict = [notification dictionaryRepresentation];
|
|
bgannin@3404
|
85 |
NSString *title = [notification title];
|
|
bgannin@3404
|
86 |
NSString *text = [notification notificationDescription];
|
|
rudy@2821
|
87 |
NSImage *icon = getObjectForKey(noteDict, GROWL_NOTIFICATION_ICON);
|
|
rudy@2821
|
88 |
int priority = getIntegerForKey(noteDict, GROWL_NOTIFICATION_PRIORITY);
|
|
ingmarstein@2943
|
89 |
|
|
rudy@2821
|
90 |
GrowlSmokeWindowView *view = [[self window] contentView];
|
|
rudy@2821
|
91 |
[view setPriority:priority];
|
|
bgannin@3404
|
92 |
[view setTitle:title];
|
|
bgannin@3404
|
93 |
[view setText:text];
|
|
rudy@2821
|
94 |
[view setIcon:icon];
|
|
rudy@2821
|
95 |
[view sizeToFit];
|
|
ingmarstein@3021
|
96 |
}
|
|
ingmarstein@3021
|
97 |
|
|
jkp@2841
|
98 |
#pragma mark -
|
|
jkp@2841
|
99 |
#pragma mark positioning methods
|
|
jkp@2841
|
100 |
|
|
jkp@2841
|
101 |
- (NSPoint) idealOriginInRect:(NSRect)rect {
|
|
jkp@2841
|
102 |
NSRect viewFrame = [[[self window] contentView] frame];
|
|
bgannin@3317
|
103 |
enum GrowlPosition originatingPosition = [[GrowlPositionController sharedInstance] originPosition];
|
|
bgannin@3271
|
104 |
NSPoint idealOrigin;
|
|
bgannin@3271
|
105 |
|
|
bgannin@3271
|
106 |
switch(originatingPosition){
|
|
bgannin@3271
|
107 |
case GrowlTopRightPosition:
|
|
bgannin@3271
|
108 |
idealOrigin = NSMakePoint(NSMaxX(rect) - NSWidth(viewFrame) - GrowlSmokePadding,
|
|
bgannin@3271
|
109 |
NSMaxY(rect) - GrowlSmokePadding - NSHeight(viewFrame));
|
|
bgannin@3271
|
110 |
break;
|
|
bgannin@3271
|
111 |
case GrowlTopLeftPosition:
|
|
bgannin@3271
|
112 |
idealOrigin = NSMakePoint(NSMinX(rect) + GrowlSmokePadding,
|
|
bgannin@3271
|
113 |
NSMaxY(rect) - GrowlSmokePadding - NSHeight(viewFrame));
|
|
bgannin@3271
|
114 |
break;
|
|
bgannin@3271
|
115 |
case GrowlBottomLeftPosition:
|
|
bgannin@3271
|
116 |
idealOrigin = NSMakePoint(NSMinX(rect) + GrowlSmokePadding,
|
|
bgannin@3271
|
117 |
NSMinY(rect) + GrowlSmokePadding);
|
|
bgannin@3271
|
118 |
break;
|
|
bgannin@3271
|
119 |
case GrowlBottomRightPosition:
|
|
bgannin@3271
|
120 |
idealOrigin = NSMakePoint(NSMaxX(rect) - NSWidth(viewFrame) - GrowlSmokePadding,
|
|
bgannin@3271
|
121 |
NSMinY(rect) + GrowlSmokePadding);
|
|
bgannin@3271
|
122 |
break;
|
|
bgannin@3271
|
123 |
default:
|
|
bgannin@3271
|
124 |
idealOrigin = NSMakePoint(NSMaxX(rect) - NSWidth(viewFrame) - GrowlSmokePadding,
|
|
bgannin@3271
|
125 |
NSMaxY(rect) - GrowlSmokePadding - NSHeight(viewFrame));
|
|
bgannin@3271
|
126 |
break;
|
|
bgannin@3271
|
127 |
}
|
|
bgannin@3271
|
128 |
|
|
bgannin@3271
|
129 |
return idealOrigin;
|
|
jkp@2841
|
130 |
}
|
|
jkp@2841
|
131 |
|
|
boredzo@3095
|
132 |
- (enum GrowlExpansionDirection) primaryExpansionDirection {
|
|
bgannin@3317
|
133 |
enum GrowlPosition originatingPosition = [[GrowlPositionController sharedInstance] originPosition];
|
|
bgannin@3271
|
134 |
enum GrowlExpansionDirection directionToExpand;
|
|
bgannin@3271
|
135 |
|
|
bgannin@3271
|
136 |
switch(originatingPosition){
|
|
bgannin@3271
|
137 |
case GrowlTopLeftPosition:
|
|
bgannin@3271
|
138 |
directionToExpand = GrowlDownExpansionDirection;
|
|
bgannin@3271
|
139 |
break;
|
|
bgannin@3271
|
140 |
case GrowlTopRightPosition:
|
|
bgannin@3271
|
141 |
directionToExpand = GrowlDownExpansionDirection;
|
|
bgannin@3271
|
142 |
break;
|
|
bgannin@3271
|
143 |
case GrowlBottomLeftPosition:
|
|
bgannin@3271
|
144 |
directionToExpand = GrowlUpExpansionDirection;
|
|
bgannin@3271
|
145 |
break;
|
|
bgannin@3271
|
146 |
case GrowlBottomRightPosition:
|
|
bgannin@3271
|
147 |
directionToExpand = GrowlUpExpansionDirection;
|
|
bgannin@3271
|
148 |
break;
|
|
bgannin@3271
|
149 |
default:
|
|
bgannin@3271
|
150 |
directionToExpand = GrowlDownExpansionDirection;
|
|
bgannin@3271
|
151 |
break;
|
|
bgannin@3271
|
152 |
}
|
|
bgannin@3271
|
153 |
|
|
bgannin@3271
|
154 |
return directionToExpand;
|
|
jkp@2841
|
155 |
}
|
|
jkp@2841
|
156 |
|
|
boredzo@3095
|
157 |
- (enum GrowlExpansionDirection) secondaryExpansionDirection {
|
|
bgannin@3317
|
158 |
enum GrowlPosition originatingPosition = [[GrowlPositionController sharedInstance] originPosition];
|
|
bgannin@3271
|
159 |
enum GrowlExpansionDirection directionToExpand;
|
|
bgannin@3271
|
160 |
|
|
bgannin@3271
|
161 |
switch(originatingPosition){
|
|
bgannin@3271
|
162 |
case GrowlTopLeftPosition:
|
|
bgannin@3271
|
163 |
directionToExpand = GrowlRightExpansionDirection;
|
|
bgannin@3271
|
164 |
break;
|
|
bgannin@3271
|
165 |
case GrowlTopRightPosition:
|
|
bgannin@3271
|
166 |
directionToExpand = GrowlLeftExpansionDirection;
|
|
bgannin@3271
|
167 |
break;
|
|
bgannin@3271
|
168 |
case GrowlBottomLeftPosition:
|
|
bgannin@3271
|
169 |
directionToExpand = GrowlRightExpansionDirection;
|
|
bgannin@3271
|
170 |
break;
|
|
bgannin@3271
|
171 |
case GrowlBottomRightPosition:
|
|
bgannin@3271
|
172 |
directionToExpand = GrowlLeftExpansionDirection;
|
|
bgannin@3271
|
173 |
break;
|
|
bgannin@3271
|
174 |
default:
|
|
bgannin@3271
|
175 |
directionToExpand = GrowlRightExpansionDirection;
|
|
bgannin@3271
|
176 |
break;
|
|
bgannin@3271
|
177 |
}
|
|
bgannin@3271
|
178 |
|
|
bgannin@3271
|
179 |
return directionToExpand;
|
|
jkp@2841
|
180 |
}
|
|
jkp@2841
|
181 |
|
|
jkp@2841
|
182 |
- (float) requiredDistanceFromExistingDisplays {
|
|
jkp@2841
|
183 |
return GrowlSmokePadding;
|
|
boredzo@2402
|
184 |
}
|
|
boredzo@2402
|
185 |
|
|
boredzo@2402
|
186 |
@end
|