1 #import "ITTransientStatusWindow.h"
2 #import "ITWindowEffect.h"
3 #import <ApplicationServices/ApplicationServices.h>
4 #import "ITCoreGraphicsHacks.h"
5 #import "ITTextField.h"
6 #import "ITTSWBackgroundView.h"
8 #define EFFECT_FPS 30.0
11 /*************************************************************************/
13 #pragma mark PRIVATE METHOD DECLARATIONS
14 /*************************************************************************/
16 @interface ITTransientStatusWindow (Private)
17 - (id)initWithContentView:(NSView *)contentView
18 exitMode:(ITTransientStatusWindowExitMode)exitMode
19 backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType;
20 - (void)rebuildWindow;
21 - (void)startVanishTimer;
22 - (void)stopVanishTimer;
26 /*************************************************************************/
28 #pragma mark IMPLEMENTATION
29 /*************************************************************************/
31 @implementation ITTransientStatusWindow
34 /*************************************************************************/
36 #pragma mark SHARED STATIC OBJECTS
37 /*************************************************************************/
39 static ITTransientStatusWindow *staticWindow = nil;
42 /*************************************************************************/
44 #pragma mark INITIALIZATION METHODS
45 /*************************************************************************/
47 + (ITTransientStatusWindow *)sharedWindow
49 if ( ! (staticWindow) ) {
50 staticWindow = [[self alloc] initWithContentView:nil
51 exitMode:ITTransientStatusWindowExitAfterDelay
52 backgroundType:ITTransientStatusWindowRounded];
57 - (id)initWithContentView:(NSView *)contentView
58 exitMode:(ITTransientStatusWindowExitMode)exitMode
59 backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType
63 // If no Content View was provided, use a generic view.
64 if ( ! (contentView) ) {
65 contentView = [[[NSView alloc] initWithFrame:
66 NSMakeRect(100.0, 100.0, 200.0, 200.0)] autorelease];
69 // Set the content rect to the frame of the content view, now guaranteed to exist.
70 contentRect = [contentView frame];
72 if ( ( self = [super initWithContentRect:contentRect
73 styleMask:NSBorderlessWindowMask
74 backing:NSBackingStoreBuffered
77 _visibilityState = ITWindowHiddenState;
79 _exitDelay = DEFAULT_EXIT_DELAY;
80 _backgroundType = backgroundType;
81 _verticalPosition = ITWindowPositionBottom;
82 _horizontalPosition = ITWindowPositionLeft;
83 _screenPadding = 32.0;
87 _reallyIgnoresEvents = YES;
89 [self setScreen:[NSScreen mainScreen]];
91 // if ( _backgroundType == ITTransientStatusWindowRounded ) {
92 // _contentSubView = contentView;
94 // [self setContentView:contentView];
97 [self setIgnoresMouseEvents:YES];
98 [self setLevel:NSScreenSaverWindowLevel];
99 [self setContentView:contentView];
100 [self rebuildWindow];
111 /*************************************************************************/
113 #pragma mark INSTANCE METHODS
114 /*************************************************************************/
116 - (BOOL)ignoresMouseEvents
118 return _reallyIgnoresEvents;
121 - (void)setIgnoresMouseEvents:(BOOL)flag
126 key = CGSCreateCString("IgnoreForEvents");
127 ignore = CGSCreateBoolean( (flag ? kCGSTrue : kCGSFalse) );
128 CGSSetWindowProperty([NSApp contextID], (CGSWindowID)[self windowNumber], key, ignore);
130 CGSReleaseObj(ignore);
132 _reallyIgnoresEvents = flag;
139 if ( _backgroundType == ITTransientStatusWindowRounded ) {
140 return _contentSubView;
142 return [super contentView];
146 - (void)setContentView:(NSView *)aView
148 if ( _backgroundType == ITTransientStatusWindowRounded ) {
149 [_contentSubView removeFromSuperview];
150 _contentSubView = aView;
151 [_contentSubView setFrame:[[super contentView] frame]];
152 [[super contentView] addSubview:_contentSubView];
153 [_contentSubView setNextResponder:self];
155 [super setContentView:aView];
161 - (IBAction)appear:(id)sender
163 if ( _visibilityState == ITWindowHiddenState ) {
164 // Window is hidden. Appear as normal, and start the timer.
165 [_entryEffect performAppear];
166 } else if ( _visibilityState == ITWindowVisibleState ) {
167 // Window is completely visible. Simply reset the timer.
168 [self startVanishTimer];
169 } else if ( _visibilityState == ITWindowAppearingState ) {
170 // Window is on its way in. Do nothing.
171 } else if ( _visibilityState == ITWindowVanishingState ) {
172 // Window is on its way out. Cancel the vanish.
173 [_exitEffect cancelVanish];
177 - (IBAction)vanish:(id)sender
179 if ( _visibilityState == ITWindowVisibleState ) {
180 // Window is totally visible. Perform exit effect.
181 [_exitEffect performVanish];
182 } else if ( _visibilityState == ITWindowHiddenState ) {
183 // Window is hidden. Do nothing.
184 } else if ( _visibilityState == ITWindowAppearingState ) {
185 // Window is on its way in. Cancel appear.
186 [_entryEffect cancelAppear];
187 } else if ( _visibilityState == ITWindowVanishingState ) {
188 // Window is on its way out. Do nothing.
192 - (void)setScreen:(NSScreen *)newScreen
195 _screen = [newScreen retain];
203 - (void)setSizing:(ITTransientStatusWindowSizing)newSizing
208 - (ITTransientStatusWindowSizing)sizing
213 - (ITWindowVisibilityState)visibilityState
215 return _visibilityState;
218 - (void)setVisibilityState:(ITWindowVisibilityState)newState
220 _visibilityState = newState;
222 if ( _visibilityState == ITWindowVisibleState ) {
223 [self startVanishTimer];
224 } else if ( (_visibilityState == ITWindowVanishingState) || (_visibilityState == ITWindowHiddenState) ) {
225 [self stopVanishTimer];
229 - (ITTransientStatusWindowExitMode)exitMode
234 - (void)setExitMode:(ITTransientStatusWindowExitMode)newMode
238 if ( _visibilityState == ITWindowVisibleState ) {
239 if ( _exitMode == ITTransientStatusWindowExitOnCommand ) {
240 [self stopVanishTimer];
241 } else if ( _exitMode == ITTransientStatusWindowExitAfterDelay ) {
242 [self startVanishTimer];
252 - (void)setExitDelay:(float)seconds
254 _exitDelay = seconds;
257 - (ITTransientStatusWindowBackgroundType)backgroundType
259 // return _backgroundType;
260 return ITTransientStatusWindowRounded;
263 - (void)setBackgroundType:(ITTransientStatusWindowBackgroundType)newType
265 // setBackgroundType: is currently ignored. Defaults to ITTransientStatusWindowRounded.
266 // _backgroundType = newType;
267 _backgroundType = ITTransientStatusWindowRounded;
270 - (ITVerticalWindowPosition)verticalPosition;
272 return _verticalPosition;
275 - (void)setVerticalPosition:(ITVerticalWindowPosition)newPosition;
277 _verticalPosition = newPosition;
280 - (ITHorizontalWindowPosition)horizontalPosition;
282 return _horizontalPosition;
285 - (void)setHorizontalPosition:(ITHorizontalWindowPosition)newPosition;
287 _horizontalPosition = newPosition;
290 - (float)effectProgress
292 return _effectProgress;
295 - (void)setEffectProgress:(float)newProgress
297 _effectProgress = newProgress;
300 - (float)screenPadding
302 return _screenPadding;
305 - (void)setScreenPadding:(float)newPadding
307 _screenPadding = newPadding;
310 /*- (int)screenNumber
312 return _screenNumber;
315 - (void)setScreenNumber:(int)newNumber
317 _screenNumber = newNumber;
320 - (ITWindowEffect *)entryEffect
325 - (void)setEntryEffect:(ITWindowEffect *)newEffect
327 [_entryEffect releaseWhenIdle];
328 _entryEffect = [newEffect retain];
331 - (ITWindowEffect *)exitEffect
336 - (void)setExitEffect:(ITWindowEffect *)newEffect
338 [_exitEffect releaseWhenIdle];
339 _exitEffect = [newEffect retain];
343 /*************************************************************************/
345 #pragma mark PRIVATE METHODS
346 /*************************************************************************/
348 - (void)rebuildWindow;
350 if ( _backgroundType == ITTransientStatusWindowRounded ) {
351 ITTSWBackgroundView *roundedView = [[[ITTSWBackgroundView alloc] initWithFrame:[self frame]] autorelease];
353 [self setBackgroundColor:[NSColor clearColor]];
354 [self setHasShadow:NO];
357 [self setContentView:roundedView];
358 // [super setContentView:roundedView];
359 // [_contentSubView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
360 // [self setContentView:_contentSubView];
366 - (void)startVanishTimer
368 if ( _exitMode == ITTransientStatusWindowExitAfterDelay) {
369 [self stopVanishTimer];
370 _exitTimer = [NSTimer scheduledTimerWithTimeInterval:_exitDelay
372 selector:@selector(doDelayedExit)
378 - (void)doDelayedExit
384 - (void)stopVanishTimer
387 [_exitTimer invalidate];