1 #import "ITTransientStatusWindow.h"
2 #import <CoreGraphics/CoreGraphics.h>
3 #import "ITCoreGraphicsHacks.h"
4 #import "ITTextField.h"
5 #import "ITGrayRoundedView.h"
8 /*************************************************************************/
10 #pragma mark EVIL HACKERY
11 /*************************************************************************/
13 @interface NSApplication (HACKHACKHACKHACK)
14 - (CGSConnectionID)contextID;
18 /*************************************************************************/
20 #pragma mark PRIVATE METHOD DECLARATIONS
21 /*************************************************************************/
23 @interface ITTransientStatusWindow (Private)
24 - (id)initWithContentView:(NSView *)contentView
25 exitMode:(ITTransientStatusWindowExitMode)exitMode
26 backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType;
27 - (void)rebuildWindow;
28 - (void)performEffect;
29 - (void)dissolveEffect:(BOOL)entering;
30 - (void)slideVerticalEffect:(BOOL)entering;
31 - (void)slideHorizontalEffect:(BOOL)entering;
35 /*************************************************************************/
37 #pragma mark IMPLEMENTATION
38 /*************************************************************************/
40 @implementation ITTransientStatusWindow
43 /*************************************************************************/
45 #pragma mark SHARED STATIC OBJECTS
46 /*************************************************************************/
48 static ITTransientStatusWindow *staticWindow = nil;
51 /*************************************************************************/
53 #pragma mark INITIALIZATION METHODS
54 /*************************************************************************/
56 + (ITTransientStatusWindow *)sharedWindow
58 if ( ! (staticWindow) ) {
59 staticWindow = [[self alloc] initWithContentView:nil
60 exitMode:ITTransientStatusWindowExitAfterDelay
61 backgroundType:ITTransientStatusWindowRounded];
66 - (id)initWithContentView:(NSView *)contentView
67 exitMode:(ITTransientStatusWindowExitMode)exitMode
68 backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType
75 // If no Content View was provided, use a generic NSImageView with the app icon.
76 if ( ! (contentView) ) {
77 contentView = [[[NSView alloc] initWithFrame:
78 NSMakeRect(100.0, 100.0, 200.0, 200.0)] autorelease];
81 // Set the content rect to the frame of the content view, now guaranteed to exist.
82 contentRect = [contentView frame];
84 if ( ( self = [super initWithContentRect:contentRect
85 styleMask:NSBorderlessWindowMask
86 backing:NSBackingStoreBuffered
89 _visibilityState = ITTransientStatusWindowHiddenState;
91 _exitDelay = DEFAULT_EXIT_DELAY;
92 _backgroundType = backgroundType;
93 _verticalPosition = ITTransientStatusWindowPositionBottom;
94 _horizontalPosition = ITTransientStatusWindowPositionLeft;
95 _entryEffect = ITTransientStatusWindowEffectNone;
96 _exitEffect = ITTransientStatusWindowEffectDissolve;
101 // if ( _backgroundType == ITTransientStatusWindowRounded ) {
102 // _contentSubView = contentView;
104 // [self setContentView:contentView];
107 // [self setIgnoresMouseEvents:YES];
109 key = CGSCreateCString("IgnoreForEvents");
110 ignore = CGSCreateBoolean(kCGSTrue);
112 CGSSetWindowProperty([NSApp contextID], (CGSWindowID)[self windowNumber], key, ignore);
115 CGSReleaseObj(ignore);
117 [self setLevel:NSScreenSaverWindowLevel];
118 [self setContentView:contentView];
119 [self rebuildWindow];
125 /*************************************************************************/
127 #pragma mark INSTANCE METHODS
128 /*************************************************************************/
130 - (void)orderFront:(id)sender
132 if ( _exitMode = ITTransientStatusWindowExitAfterDelay ) {
133 // set the timer, and orderOut: when it lapses.
136 if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
137 [super orderFront:sender];
139 [self performEffect];
143 - (void)makeKeyAndOrderFront:(id)sender
145 if ( _exitMode = ITTransientStatusWindowExitAfterDelay ) {
146 // set the timer, and orderOut: when it lapses.
149 if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
150 [super makeKeyAndOrderFront:sender];
152 [self performEffect];
153 [self makeKeyWindow];
157 - (void)orderOut:(id)sender
159 if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
160 [super orderOut:sender];
162 [self performEffect];
170 if ( _backgroundType == ITTransientStatusWindowRounded ) {
171 return _contentSubView;
173 return [super contentView];
177 - (void)setContentView:(NSView *)aView
179 if ( _backgroundType == ITTransientStatusWindowRounded ) {
180 [_contentSubView removeFromSuperview];
181 _contentSubView = aView;
182 [_contentSubView setFrame:[[super contentView] frame]];
183 [[super contentView] addSubview:_contentSubView];
184 [_contentSubView setNextResponder:self];
186 [super setContentView:aView];
192 - (ITTransientStatusWindowVisibilityState)visibilityState
194 return _visibilityState;
197 - (ITTransientStatusWindowExitMode)ExitMode
202 - (void)setExitMode:(ITTransientStatusWindowExitMode)newMode
212 - (void)setExitDelay:(float)seconds
214 _exitDelay = seconds;
217 - (ITTransientStatusWindowBackgroundType)backgroundType
219 // return _backgroundType;
220 return ITTransientStatusWindowRounded;
223 - (void)setBackgroundType:(ITTransientStatusWindowBackgroundType)newType
225 // setBackgroundType: is currently ignored. Defaults to ITTransientStatusWindowRounded.
226 // _backgroundType = newType;
227 _backgroundType = ITTransientStatusWindowRounded;
230 - (ITTransientStatusWindowPosition)verticalPosition;
232 return _verticalPosition;
235 - (void)setVerticalPosition:(ITTransientStatusWindowPosition)newPosition;
237 _verticalPosition = newPosition;
240 - (ITTransientStatusWindowPosition)horizontalPosition;
242 return _horizontalPosition;
245 - (void)setHorizontalPosition:(ITTransientStatusWindowPosition)newPosition;
247 _horizontalPosition = newPosition;
250 - (ITTransientStatusWindowEffect)entryEffect
255 - (void)setEntryEffect:(ITTransientStatusWindowEffect)newEffect;
257 _entryEffect = newEffect;
260 - (ITTransientStatusWindowEffect)exitEffect;
265 - (void)setExitEffect:(ITTransientStatusWindowEffect)newEffect;
267 _exitEffect = newEffect;
271 /*************************************************************************/
273 #pragma mark PRIVATE METHODS
274 /*************************************************************************/
276 - (void)rebuildWindow;
278 if ( _backgroundType == ITTransientStatusWindowRounded ) {
279 ITGrayRoundedView *roundedView = [[[ITGrayRoundedView alloc] initWithFrame:[self frame]] autorelease];
281 [self setBackgroundColor:[NSColor clearColor]];
282 [self setHasShadow:NO];
285 [self setContentView:roundedView];
286 // [super setContentView:roundedView];
287 // [_contentSubView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
288 // [self setContentView:_contentSubView];
294 - (void)performEffect
296 if ( _visibilityState == ITTransientStatusWindowHiddenState ) {
297 if ( _entryEffect == ITTransientStatusWindowEffectDissolve ) {
298 [self dissolveEffect:YES];
299 } else if ( _entryEffect == ITTransientStatusWindowEffectSlideVertically ) {
300 [self slideEffect:YES];
301 } else if ( _entryEffect == ITTransientStatusWindowEffectSlideHorizontally ) {
302 [self slideEffect:YES];
304 } else if ( _visibilityState == ITTransientStatusWindowVisibleState ) {
305 if ( _exitEffect == ITTransientStatusWindowEffectDissolve ) {
306 [self dissolveEffect:NO];
307 } else if ( _exitEffect == ITTransientStatusWindowEffectSlideVertically ) {
308 [self slideEffect:NO];
309 } else if ( _exitEffect == ITTransientStatusWindowEffectSlideHorizontally ) {
310 [self slideEffect:NO];
315 - (void)dissolveEffect:(BOOL)entering
318 [super orderFront:self];
321 - (void)slideVerticalEffect:(BOOL)entering
323 [super orderFront:self];
326 - (void)slideHorizontalEffect:(BOOL)entering
328 [super orderFront:self];