1 #import "ITTransientStatusWindow.h"
2 #import "ITWindowEffect.h"
3 #import <CoreGraphics/CoreGraphics.h>
4 #import "ITCoreGraphicsHacks.h"
5 #import "ITTextField.h"
6 #import "ITGrayRoundedView.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;
90 // if ( _backgroundType == ITTransientStatusWindowRounded ) {
91 // _contentSubView = contentView;
93 // [self setContentView:contentView];
96 [self setIgnoresMouseEvents:YES];
97 [self setLevel:NSScreenSaverWindowLevel];
98 [self setContentView:contentView];
105 /*************************************************************************/
107 #pragma mark INSTANCE METHODS
108 /*************************************************************************/
110 - (BOOL)ignoresMouseEvents
112 return _reallyIgnoresEvents;
115 - (void)setIgnoresMouseEvents:(BOOL)flag
120 key = CGSCreateCString("IgnoreForEvents");
121 ignore = CGSCreateBoolean( (flag ? kCGSTrue : kCGSFalse) );
122 CGSSetWindowProperty([NSApp contextID], (CGSWindowID)[self windowNumber], key, ignore);
124 CGSReleaseObj(ignore);
126 _reallyIgnoresEvents = flag;
134 if ( _backgroundType == ITTransientStatusWindowRounded ) {
135 return _contentSubView;
137 return [super contentView];
141 - (void)setContentView:(NSView *)aView
143 if ( _backgroundType == ITTransientStatusWindowRounded ) {
144 [_contentSubView removeFromSuperview];
145 _contentSubView = aView;
146 [_contentSubView setFrame:[[super contentView] frame]];
147 [[super contentView] addSubview:_contentSubView];
148 [_contentSubView setNextResponder:self];
150 [super setContentView:aView];
156 - (IBAction)appear:(id)sender
158 if ( _visibilityState == ITWindowHiddenState ) {
159 // Window is hidden. Appear as normal, and start the timer.
160 [_entryEffect performAppear];
161 } else if ( _visibilityState == ITWindowVisibleState ) {
162 // Window is completely visible. Simply reset the timer.
163 [self startVanishTimer];
164 } else if ( _visibilityState == ITWindowAppearingState ) {
165 // Window is on its way in. Do nothing.
166 } else if ( _visibilityState == ITWindowVanishingState ) {
167 // Window is on its way out. Cancel the vanish.
168 [_exitEffect cancelVanish];
172 - (IBAction)vanish:(id)sender
174 if ( _visibilityState == ITWindowVisibleState ) {
175 // Window is totally visible. Perform exit effect.
176 [_exitEffect performVanish];
177 } else if ( _visibilityState == ITWindowHiddenState ) {
178 // Window is hidden. Do nothing.
179 } else if ( _visibilityState == ITWindowAppearingState ) {
180 // Window is on its way in. Cancel appear.
181 [_entryEffect cancelAppear];
182 } else if ( _visibilityState == ITWindowVanishingState ) {
183 // Window is on its way out. Do nothing.
187 - (ITWindowVisibilityState)visibilityState
189 return _visibilityState;
192 - (void)setVisibilityState:(ITWindowVisibilityState)newState
194 _visibilityState = newState;
196 if ( _visibilityState == ITWindowVisibleState ) {
197 [self startVanishTimer];
201 - (ITTransientStatusWindowExitMode)exitMode
206 - (void)setExitMode:(ITTransientStatusWindowExitMode)newMode
210 if ( _visibilityState == ITWindowVisibleState ) {
211 if ( _exitMode == ITTransientStatusWindowExitOnCommand ) {
212 [self stopVanishTimer];
213 } else if ( _exitMode == ITTransientStatusWindowExitAfterDelay ) {
214 [self startVanishTimer];
224 - (void)setExitDelay:(float)seconds
226 _exitDelay = seconds;
229 - (ITTransientStatusWindowBackgroundType)backgroundType
231 // return _backgroundType;
232 return ITTransientStatusWindowRounded;
235 - (void)setBackgroundType:(ITTransientStatusWindowBackgroundType)newType
237 // setBackgroundType: is currently ignored. Defaults to ITTransientStatusWindowRounded.
238 // _backgroundType = newType;
239 _backgroundType = ITTransientStatusWindowRounded;
242 - (ITVerticalWindowPosition)verticalPosition;
244 return _verticalPosition;
247 - (void)setVerticalPosition:(ITVerticalWindowPosition)newPosition;
249 _verticalPosition = newPosition;
252 - (ITHorizontalWindowPosition)horizontalPosition;
254 return _horizontalPosition;
257 - (void)setHorizontalPosition:(ITHorizontalWindowPosition)newPosition;
259 _horizontalPosition = newPosition;
262 - (float)effectProgress
264 return _effectProgress;
267 - (void)setEffectProgress:(float)newProgress
269 _effectProgress = newProgress;
272 - (float)screenPadding
274 return _screenPadding;
277 - (void)setScreenPadding:(float)newPadding
279 _screenPadding = newPadding;
284 return _screenNumber;
287 - (void)setScreenNumber:(int)newNumber
289 _screenNumber = newNumber;
292 - (ITWindowEffect *)entryEffect
297 - (void)setEntryEffect:(ITWindowEffect *)newEffect
299 [_entryEffect releaseWhenIdle];
300 _entryEffect = [newEffect retain];
303 - (ITWindowEffect *)exitEffect
308 - (void)setExitEffect:(ITWindowEffect *)newEffect
310 [_exitEffect releaseWhenIdle];
311 _exitEffect = [newEffect retain];
315 /*************************************************************************/
317 #pragma mark PRIVATE METHODS
318 /*************************************************************************/
320 - (void)rebuildWindow;
322 if ( _backgroundType == ITTransientStatusWindowRounded ) {
323 ITGrayRoundedView *roundedView = [[[ITGrayRoundedView alloc] initWithFrame:[self frame]] autorelease];
325 [self setBackgroundColor:[NSColor clearColor]];
326 [self setHasShadow:NO];
329 [self setContentView:roundedView];
330 // [super setContentView:roundedView];
331 // [_contentSubView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
332 // [self setContentView:_contentSubView];
338 - (void)startVanishTimer
340 if ( _exitMode == ITTransientStatusWindowExitAfterDelay) {
341 [self stopVanishTimer];
342 _exitTimer = [NSTimer scheduledTimerWithTimeInterval:_exitDelay
344 selector:@selector(doDelayedExit)
350 - (void)doDelayedExit
356 - (void)stopVanishTimer
359 [_exitTimer invalidate];