-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGrowlITTSWWindow.m
255 lines (213 loc) · 8.72 KB
/
GrowlITTSWWindow.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
//
// GrowlITTSWWindow.m
// Growl
//
// Created by Joseph Spiros on 2/28/09.
// Copyright 2009 iThink Software. All rights reserved.
//
#import "GrowlITTSWWindow.h"
#define SW_PAD 24.00
#define SW_SPACE 24.00
#define SW_MINW 211.00
#define SW_BORDER 32.00
#define SW_METER_PAD 4.00
#define SW_BUTTON_PAD_R 30.00
#define SW_BUTTON_PAD_B 24.00
#define SW_BUTTON_DIV 12.00
#define SW_BUTTON_EXTRA_W 8.00
#define SW_SHADOW_SAT 1.25
@interface GrowlITTSWWindow (Private)
- (NSRect)setupWindowWithDataSize:(NSSize)dataSize;
@end
@implementation GrowlITTSWWindow
/*************************************************************************/
#pragma mark -
#pragma mark INITIALIZATION / DEALLOCATION METHODS
/*************************************************************************/
- (id)initWithContentView:(NSView *)contentView
exitMode:(ITTransientStatusWindowExitMode)exitMode
backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType
{
if ( ( self = [super initWithContentView:contentView
exitMode:exitMode
backgroundType:backgroundType] ) ) {
// Set default values.
_image = [[NSImage imageNamed:@"NSApplicationIcon"] retain];
_sizing = ITTransientStatusWindowRegular;
}
return self;
}
- (void)dealloc
{
[_image release];
[super dealloc];
}
/*************************************************************************/
#pragma mark -
#pragma mark ACCESSOR METHODS
/*************************************************************************/
- (void)setImage:(NSImage *)newImage
{
if (!newImage) {
newImage = [NSImage imageNamed:@"NSApplicationIcon"];
}
[_image autorelease];
_image = [newImage copy];
}
- (void)setSizing:(ITTransientStatusWindowSizing)newSizing
{
_sizing = newSizing;
}
/*************************************************************************/
#pragma mark -
#pragma mark INSTANCE METHODS
/*************************************************************************/
- (void)appear:(id)sender
{
[super appear:sender];
}
- (void)vanish:(id)sender
{
[super vanish:sender];
}
- (NSRect)setupWindowWithDataSize:(NSSize)dataSize
{
float divisor = 1.0;
NSRect imageRect;
float imageWidth = 0.0;
float imageHeight = 0.0;
float dataWidth = dataSize.width;
float dataHeight = dataSize.height;
float contentHeight = 0.0;
float windowWidth = 0.0;
float windowHeight = 0.0;
NSRect visibleFrame = [[self screen] visibleFrame];
NSPoint screenOrigin = visibleFrame.origin;
float screenWidth = visibleFrame.size.width;
float screenHeight = visibleFrame.size.height;
float maxWidth = ( screenWidth - (SW_BORDER * 2) );
float maxHeight = ( screenHeight - (SW_BORDER * 2) );
float excessWidth = 0.0;
float excessHeight = 0.0;
NSPoint windowOrigin = NSZeroPoint;
ITImageView *imageView;
BOOL shouldAnimate = ( ! (([self visibilityState] == ITWindowAppearingState) ||
([self visibilityState] == ITWindowVanishingState)) );
if ( _sizing == ITTransientStatusWindowSmall ) {
divisor = SMALL_DIVISOR;
} else if ( _sizing == ITTransientStatusWindowMini ) {
divisor = MINI_DIVISOR;
}
// Get image width and height.
imageWidth = ( [_image size].width / divisor );
imageHeight = ( [_image size].height / divisor );
// Set the content height to the greater of the text and image heights.
contentHeight = ( ( imageHeight > dataHeight ) ? imageHeight : dataHeight );
// Setup the Window, and remove all its contentview's subviews.
windowWidth = ( (SW_PAD / divisor) + imageWidth + ((dataWidth > 0) ? (SW_SPACE / divisor) + dataWidth : 0) + (SW_PAD / divisor) );
windowHeight = ( (SW_PAD / divisor) + contentHeight + (SW_PAD / divisor) );
// Constrain size to max limits. Adjust data sizes accordingly.
excessWidth = (windowWidth - maxWidth );
excessHeight = (windowHeight - maxHeight);
if ( excessWidth > 0.0 ) {
windowWidth = maxWidth;
dataWidth -= excessWidth;
}
if ( excessHeight > 0.0 ) {
windowHeight = maxHeight;
dataHeight -= excessHeight;
}
if ( [self horizontalPosition] == ITWindowPositionLeft ) {
windowOrigin.x = ( SW_BORDER + screenOrigin.x );
} else if ( [self horizontalPosition] == ITWindowPositionCenter ) {
windowOrigin.x = ( screenOrigin.x + (screenWidth / 2) - (windowWidth / 2) );
} else if ( [self horizontalPosition] == ITWindowPositionRight ) {
windowOrigin.x = ( screenOrigin.x + screenWidth - (windowWidth + SW_BORDER) );
}
if ( [self verticalPosition] == ITWindowPositionTop ) {
windowOrigin.y = ( screenOrigin.y + screenHeight - (windowHeight + SW_BORDER) );
} else if ( [self verticalPosition] == ITWindowPositionMiddle ) {
// Middle-oriented windows should be slightly proud of the screen's middle.
windowOrigin.y = ( (screenOrigin.y + (screenHeight / 2) - (windowHeight / 2)) + (screenHeight / 8) );
} else if ( [self verticalPosition] == ITWindowPositionBottom ) {
windowOrigin.y = ( SW_BORDER + screenOrigin.y );
}
[self setFrame:NSMakeRect( windowOrigin.x,
windowOrigin.y,
windowWidth,
windowHeight) display:YES animate:shouldAnimate];
[[[self contentView] subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
// Setup, position, fill, and add the image view to the content view.
imageRect = NSMakeRect( (SW_PAD / divisor) + ((dataWidth > 0) ? 4 : 0),
((SW_PAD / divisor) + ((contentHeight - imageHeight) / 2)),
imageWidth,
imageHeight );
imageView = [[[ITImageView alloc] initWithFrame:imageRect] autorelease];
[imageView setAutoresizingMask:(NSViewMinYMargin | NSViewMaxYMargin)];
[imageView setImage:_image];
[imageView setCastsShadow:YES];
[[self contentView] addSubview:imageView];
return NSMakeRect( ((SW_PAD / divisor) + imageWidth + (SW_SPACE / divisor)),
((SW_PAD / divisor) + ((contentHeight - dataHeight) / 2)),
dataWidth,
dataHeight);
}
- (void)buildTextWindowWithString:(id)text
{
float divisor = 1.0;
float dataWidth = 0.0;
float dataHeight = 0.0;
NSRect dataRect;
NSArray *lines = [(([text isKindOfClass:[NSString class]]) ? text : [text mutableString]) componentsSeparatedByString:@"\n"];
id oneLine = nil;
NSEnumerator *lineEnum = [lines objectEnumerator];
float baseFontSize = 18.0;
ITTextField *textField;
NSFont *font;
NSDictionary *attr;
if ( _sizing == ITTransientStatusWindowSmall ) {
divisor = SMALL_DIVISOR;
} else if ( _sizing == ITTransientStatusWindowMini ) {
divisor = MINI_DIVISOR;
}
font = [NSFont fontWithName:@"LucidaGrande-Bold" size:(baseFontSize / divisor)];
attr = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
// Iterate over each line to get text width and height
while ( (oneLine = [lineEnum nextObject]) ) {
// Get the width of one line, adding 8.0 because Apple sucks donkey rectum.
float oneLineWidth = ( [oneLine sizeWithAttributes:attr].width + 8.0 );
// Add the height of this line to the total text height
dataHeight += [oneLine sizeWithAttributes:attr].height;
// If this line wider than the last one, set it as the text width.
dataWidth = ( ( dataWidth > oneLineWidth ) ? dataWidth : oneLineWidth );
}
// Add 4.0 to the final dataHeight to accomodate the shadow.
dataHeight += 4.0;
dataRect = [self setupWindowWithDataSize:NSMakeSize(dataWidth, dataHeight)];
// Create, position, setup, fill, and add the text view to the content view.
textField = [[[ITTextField alloc] initWithFrame:dataRect] autorelease];
[textField setAutoresizingMask:(NSViewHeightSizable | NSViewWidthSizable)];
[textField setEditable:NO];
[textField setSelectable:NO];
[textField setBordered:NO];
[textField setDrawsBackground:NO];
[textField setFont:font];
[textField setTextColor:[NSColor whiteColor]];
[textField setCastsShadow:YES];
[[textField cell] setWraps:NO];
if ([text isKindOfClass:[NSString class]]) {
[textField setStringValue:text];
} else {
[textField setAttributedStringValue:text];
}
[textField setShadowSaturation:SW_SHADOW_SAT];
[[self contentView] addSubview:textField];
// Display the window.
[[self contentView] setNeedsDisplay:YES];
_textField = textField;
}
- (NSTimeInterval)animationResizeTime:(NSRect)newFrame
{
return (NSTimeInterval)0.25;
}
@end