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) ));
133 - (BOOL)ignoresMouseEvents
135 return _reallyIgnoresEvents;
138 - (void)setIgnoresMouseEvents:(BOOL)flag
143 key = CGSCreateCString("IgnoreForEvents");
144 ignore = CGSCreateBoolean( (flag ? kCGSTrue : kCGSFalse) );
145 CGSSetWindowProperty([NSApp contextID], (CGSWindowID)[self windowNumber], key, ignore);
147 CGSReleaseObj(ignore);
149 _reallyIgnoresEvents = flag;
152 - (void)orderFront:(id)sender
154 if ( _exitMode == ITTransientStatusWindowExitAfterDelay ) {
155 // set the timer, and orderOut: when it lapses.
158 if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
159 [super orderFront:sender];
161 [self performEffect];
165 - (void)makeKeyAndOrderFront:(id)sender
167 if ( _exitMode == ITTransientStatusWindowExitAfterDelay ) {
168 // set the timer, and orderOut: when it lapses.
171 if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
172 [super makeKeyAndOrderFront:sender];
174 [self performEffect];
175 [self makeKeyWindow];
179 - (void)orderOut:(id)sender
181 if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
182 [super orderOut:sender];
184 [self performEffect];
188 - (NSTimeInterval)animationResizeTime:(NSRect)newFrame
197 if ( _backgroundType == ITTransientStatusWindowRounded ) {
198 return _contentSubView;
200 return [super contentView];
204 - (void)setContentView:(NSView *)aView
206 if ( _backgroundType == ITTransientStatusWindowRounded ) {
207 [_contentSubView removeFromSuperview];
208 _contentSubView = aView;
209 [_contentSubView setFrame:[[super contentView] frame]];
210 [[super contentView] addSubview:_contentSubView];
211 [_contentSubView setNextResponder:self];
213 [super setContentView:aView];
219 - (ITTransientStatusWindowVisibilityState)visibilityState
221 return _visibilityState;
224 - (ITTransientStatusWindowExitMode)exitMode
229 - (void)setExitMode:(ITTransientStatusWindowExitMode)newMode
239 - (void)setExitDelay:(float)seconds
241 _exitDelay = seconds;
244 - (ITTransientStatusWindowBackgroundType)backgroundType
246 // return _backgroundType;
247 return ITTransientStatusWindowRounded;
250 - (void)setBackgroundType:(ITTransientStatusWindowBackgroundType)newType
252 // setBackgroundType: is currently ignored. Defaults to ITTransientStatusWindowRounded.
253 // _backgroundType = newType;
254 _backgroundType = ITTransientStatusWindowRounded;
257 - (ITTransientStatusWindowPosition)verticalPosition;
259 return _verticalPosition;
262 - (void)setVerticalPosition:(ITTransientStatusWindowPosition)newPosition;
264 _verticalPosition = newPosition;
267 - (ITTransientStatusWindowPosition)horizontalPosition;
269 return _horizontalPosition;
272 - (void)setHorizontalPosition:(ITTransientStatusWindowPosition)newPosition;
274 _horizontalPosition = newPosition;
277 - (ITTransientStatusWindowEffect)entryEffect
282 - (void)setEntryEffect:(ITTransientStatusWindowEffect)newEffect;
284 _entryEffect = newEffect;
287 - (ITTransientStatusWindowEffect)exitEffect;
292 - (void)setExitEffect:(ITTransientStatusWindowEffect)newEffect;
294 _exitEffect = newEffect;
298 /*************************************************************************/
300 #pragma mark PRIVATE METHODS
301 /*************************************************************************/
303 - (void)rebuildWindow;
305 if ( _backgroundType == ITTransientStatusWindowRounded ) {
306 ITGrayRoundedView *roundedView = [[[ITGrayRoundedView alloc] initWithFrame:[self frame]] autorelease];
308 [self setBackgroundColor:[NSColor clearColor]];
309 [self setHasShadow:NO];
312 [self setContentView:roundedView];
313 // [super setContentView:roundedView];
314 // [_contentSubView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
315 // [self setContentView:_contentSubView];
321 - (void)performEffect
323 if ( _visibilityState == ITTransientStatusWindowHiddenState ) {
324 if ( _entryEffect == ITTransientStatusWindowEffectDissolve ) {
325 [self dissolveEffect:YES];
326 } else if ( _entryEffect == ITTransientStatusWindowEffectSlideVertically ) {
327 [self slideVerticalEffect:YES];
328 } else if ( _entryEffect == ITTransientStatusWindowEffectSlideHorizontally ) {
329 [self slideHorizontalEffect:YES];
331 } else if ( _visibilityState == ITTransientStatusWindowVisibleState ) {
332 if ( _exitEffect == ITTransientStatusWindowEffectDissolve ) {
333 [self dissolveEffect:NO];
334 } else if ( _exitEffect == ITTransientStatusWindowEffectSlideVertically ) {
335 [self slideVerticalEffect:NO];
336 } else if ( _exitEffect == ITTransientStatusWindowEffectSlideHorizontally ) {
337 [self slideHorizontalEffect:NO];
342 - (void)dissolveEffect:(BOOL)entering
345 [super orderFront:self];
347 [super orderOut:self];
351 - (void)slideVerticalEffect:(BOOL)entering
354 [super orderFront:self];
356 [super orderOut:self];
360 - (void)slideHorizontalEffect:(BOOL)entering
363 [super orderFront:self];
365 [super orderOut:self];