1 #import "ITTransientStatusWindow.h"
2 #import <CoreGraphics/CoreGraphics.h>
3 #import "ITCoreGraphicsHacks.h"
4 #import "ITTextField.h"
5 #import "ITGrayRoundedView.h"
8 @class ITGrayRoundedView;
10 /*************************************************************************/
12 #pragma mark EVIL HACKERY
13 /*************************************************************************/
15 @interface NSApplication (HACKHACKHACKHACK)
16 - (CGSConnectionID)contextID;
20 /*************************************************************************/
22 #pragma mark PRIVATE METHOD DECLARATIONS
23 /*************************************************************************/
25 @interface ITTransientStatusWindow (Private)
26 - (id)initWithContentView:(NSView *)contentView
27 exitMode:(ITTransientStatusWindowExitMode)exitMode
28 backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType;
29 - (void)rebuildWindow;
30 - (void)performEffect;
31 - (void)dissolveEffect:(BOOL)entering;
32 - (void)slideVerticalEffect:(BOOL)entering;
33 - (void)slideHorizontalEffect:(BOOL)entering;
37 /*************************************************************************/
39 #pragma mark IMPLEMENTATION
40 /*************************************************************************/
42 @implementation ITTransientStatusWindow
45 /*************************************************************************/
47 #pragma mark SHARED STATIC OBJECTS
48 /*************************************************************************/
50 static ITTransientStatusWindow *staticWindow = nil;
53 /*************************************************************************/
55 #pragma mark INITIALIZATION METHODS
56 /*************************************************************************/
58 + (ITTransientStatusWindow *)sharedWindow
60 if ( ! (staticWindow) ) {
61 staticWindow = [[self alloc] initWithContentView:nil
62 exitMode:ITTransientStatusWindowExitAfterDelay
63 backgroundType:ITTransientStatusWindowRounded];
68 - (id)initWithContentView:(NSView *)contentView
69 exitMode:(ITTransientStatusWindowExitMode)exitMode
70 backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType
74 // If no Content View was provided, use a generic NSView with the app icon.
75 if ( ! (contentView) ) {
76 contentView = [[[NSView alloc] initWithFrame:
77 NSMakeRect(100.0, 100.0, 200.0, 200.0)] autorelease];
80 // Set the content rect to the frame of the content view, now guaranteed to exist.
81 contentRect = [contentView frame];
83 if ( ( self = [super initWithContentRect:contentRect
84 styleMask:NSBorderlessWindowMask
85 backing:NSBackingStoreBuffered
88 _visibilityState = ITTransientStatusWindowHiddenState;
90 _exitDelay = DEFAULT_EXIT_DELAY;
91 _backgroundType = backgroundType;
92 _verticalPosition = ITTransientStatusWindowPositionBottom;
93 _horizontalPosition = ITTransientStatusWindowPositionLeft;
94 _entryEffect = ITTransientStatusWindowEffectNone;
95 _exitEffect = ITTransientStatusWindowEffectDissolve;
96 _effectTime = DEFAULT_EFFECT_TIME;
97 _reallyIgnoresEvents = YES;
101 // if ( _backgroundType == ITTransientStatusWindowRounded ) {
102 // _contentSubView = contentView;
104 // [self setContentView:contentView];
107 [self setIgnoresMouseEvents:YES];
108 [self setLevel:NSScreenSaverWindowLevel];
109 [self setContentView:contentView];
110 [self rebuildWindow];
116 /*************************************************************************/
118 #pragma mark INSTANCE METHODS
119 /*************************************************************************/
121 - (void)setRotation:(float)angle
123 CGAffineTransform transform = CGAffineTransformMakeRotation(angle);
124 transform.tx = -32.0;
125 transform.ty = [self frame].size.height + 32.0;
126 CGSSetWindowTransform([NSApp contextID],
127 (CGSWindowID)[self windowNumber],
128 CGAffineTransformTranslate(transform,
129 (([self frame].origin.x - 32.0) * -1),
130 (([[self screen] frame].size.height - ([self frame].origin.y) + 32.0) * -1) ));
131 NSLog(@"%f %f", ([self frame].origin.x * -1), ([self frame].origin.y * -1));
134 - (BOOL)ignoresMouseEvents
136 return _reallyIgnoresEvents;
139 - (void)setIgnoresMouseEvents:(BOOL)flag
144 key = CGSCreateCString("IgnoreForEvents");
145 ignore = CGSCreateBoolean( (flag ? kCGSTrue : kCGSFalse) );
146 CGSSetWindowProperty([NSApp contextID], (CGSWindowID)[self windowNumber], key, ignore);
148 CGSReleaseObj(ignore);
150 _reallyIgnoresEvents = flag;
153 - (void)orderFront:(id)sender
155 if ( _exitMode == ITTransientStatusWindowExitAfterDelay ) {
156 // set the timer, and orderOut: when it lapses.
159 if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
160 [super orderFront:sender];
162 [self performEffect];
166 - (void)makeKeyAndOrderFront:(id)sender
168 if ( _exitMode == ITTransientStatusWindowExitAfterDelay ) {
169 // set the timer, and orderOut: when it lapses.
172 if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
173 [super makeKeyAndOrderFront:sender];
175 [self performEffect];
176 [self makeKeyWindow];
180 - (void)orderOut:(id)sender
182 if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
183 [super orderOut:sender];
185 [self performEffect];
189 - (NSTimeInterval)animationResizeTime:(NSRect)newFrame
198 if ( _backgroundType == ITTransientStatusWindowRounded ) {
199 return _contentSubView;
201 return [super contentView];
205 - (void)setContentView:(NSView *)aView
207 if ( _backgroundType == ITTransientStatusWindowRounded ) {
208 [_contentSubView removeFromSuperview];
209 _contentSubView = aView;
210 [_contentSubView setFrame:[[super contentView] frame]];
211 [[super contentView] addSubview:_contentSubView];
212 [_contentSubView setNextResponder:self];
214 [super setContentView:aView];
220 - (ITTransientStatusWindowVisibilityState)visibilityState
222 return _visibilityState;
225 - (ITTransientStatusWindowExitMode)exitMode
230 - (void)setExitMode:(ITTransientStatusWindowExitMode)newMode
240 - (void)setExitDelay:(float)seconds
242 _exitDelay = seconds;
245 - (ITTransientStatusWindowBackgroundType)backgroundType
247 // return _backgroundType;
248 return ITTransientStatusWindowRounded;
251 - (void)setBackgroundType:(ITTransientStatusWindowBackgroundType)newType
253 // setBackgroundType: is currently ignored. Defaults to ITTransientStatusWindowRounded.
254 // _backgroundType = newType;
255 _backgroundType = ITTransientStatusWindowRounded;
258 - (ITTransientStatusWindowPosition)verticalPosition;
260 return _verticalPosition;
263 - (void)setVerticalPosition:(ITTransientStatusWindowPosition)newPosition;
265 _verticalPosition = newPosition;
268 - (ITTransientStatusWindowPosition)horizontalPosition;
270 return _horizontalPosition;
273 - (void)setHorizontalPosition:(ITTransientStatusWindowPosition)newPosition;
275 _horizontalPosition = newPosition;
278 - (ITTransientStatusWindowEffect)entryEffect
283 - (void)setEntryEffect:(ITTransientStatusWindowEffect)newEffect;
285 _entryEffect = newEffect;
288 - (ITTransientStatusWindowEffect)exitEffect;
293 - (void)setExitEffect:(ITTransientStatusWindowEffect)newEffect;
295 _exitEffect = newEffect;
299 /*************************************************************************/
301 #pragma mark PRIVATE METHODS
302 /*************************************************************************/
304 - (void)rebuildWindow;
306 if ( _backgroundType == ITTransientStatusWindowRounded ) {
307 ITGrayRoundedView *roundedView = [[[ITGrayRoundedView alloc] initWithFrame:[self frame]] autorelease];
309 [self setBackgroundColor:[NSColor clearColor]];
310 [self setHasShadow:NO];
313 [self setContentView:roundedView];
314 // [super setContentView:roundedView];
315 // [_contentSubView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
316 // [self setContentView:_contentSubView];
322 - (void)performEffect
324 if ( _visibilityState == ITTransientStatusWindowHiddenState ) {
325 if ( _entryEffect == ITTransientStatusWindowEffectDissolve ) {
326 [self dissolveEffect:YES];
327 } else if ( _entryEffect == ITTransientStatusWindowEffectSlideVertically ) {
328 [self slideVerticalEffect:YES];
329 } else if ( _entryEffect == ITTransientStatusWindowEffectSlideHorizontally ) {
330 [self slideHorizontalEffect:YES];
332 } else if ( _visibilityState == ITTransientStatusWindowVisibleState ) {
333 if ( _exitEffect == ITTransientStatusWindowEffectDissolve ) {
334 [self dissolveEffect:NO];
335 } else if ( _exitEffect == ITTransientStatusWindowEffectSlideVertically ) {
336 [self slideVerticalEffect:NO];
337 } else if ( _exitEffect == ITTransientStatusWindowEffectSlideHorizontally ) {
338 [self slideHorizontalEffect:NO];
343 - (void)dissolveEffect:(BOOL)entering
346 [super orderFront:self];
348 [super orderOut:self];
352 - (void)slideVerticalEffect:(BOOL)entering
355 [super orderFront:self];
357 [super orderOut:self];
361 - (void)slideHorizontalEffect:(BOOL)entering
364 [super orderFront:self];
366 [super orderOut:self];