DAMN YOU PROJECT BUILDER FOR IMPORTING ONLY FOUNDATION!!!
[ITKit.git] / ITTransientStatusWindow.m
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"
7
8 #define EFFECT_FPS 30.0
9
10
11 /*************************************************************************/
12 #pragma mark -
13 #pragma mark PRIVATE METHOD DECLARATIONS
14 /*************************************************************************/
15
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;
23 @end
24
25
26 /*************************************************************************/
27 #pragma mark -
28 #pragma mark IMPLEMENTATION
29 /*************************************************************************/
30
31 @implementation ITTransientStatusWindow
32
33
34 /*************************************************************************/
35 #pragma mark -
36 #pragma mark SHARED STATIC OBJECTS
37 /*************************************************************************/
38
39 static ITTransientStatusWindow *staticWindow = nil;
40
41
42 /*************************************************************************/
43 #pragma mark -
44 #pragma mark INITIALIZATION METHODS
45 /*************************************************************************/
46
47 + (ITTransientStatusWindow *)sharedWindow
48 {
49     if ( ! (staticWindow) ) {
50         staticWindow = [[self alloc] initWithContentView:nil
51                                                 exitMode:ITTransientStatusWindowExitAfterDelay
52                                           backgroundType:ITTransientStatusWindowRounded];
53     }
54     return staticWindow;
55 }
56
57 - (id)initWithContentView:(NSView *)contentView
58                  exitMode:(ITTransientStatusWindowExitMode)exitMode
59            backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType
60 {
61     NSRect contentRect;
62     
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];
67     }
68     
69     // Set the content rect to the frame of the content view, now guaranteed to exist.
70     contentRect = [contentView frame];
71     
72     if ( ( self = [super initWithContentRect:contentRect
73                                    styleMask:NSBorderlessWindowMask
74                                      backing:NSBackingStoreBuffered
75                                        defer:NO] ) ) {
76                                     
77         _visibilityState     = ITWindowHiddenState;
78         _exitMode            = exitMode;
79         _exitDelay           = DEFAULT_EXIT_DELAY;
80         _backgroundType      = backgroundType;
81         _verticalPosition    = ITWindowPositionBottom;
82         _horizontalPosition  = ITWindowPositionLeft;
83         _screenPadding       = 32.0;
84         _screenNumber        = 0;
85         _entryEffect         = nil;
86         _exitEffect          = nil;
87         _reallyIgnoresEvents = YES;
88         _exitTimer           = nil;
89
90 //      if ( _backgroundType == ITTransientStatusWindowRounded ) {
91 //          _contentSubView = contentView;
92 //      } else {
93 //          [self setContentView:contentView];
94 //      }
95
96         [self setIgnoresMouseEvents:YES];
97         [self setLevel:NSScreenSaverWindowLevel];
98         [self setContentView:contentView];
99         [self rebuildWindow];
100     }
101     return self;
102 }
103
104
105 /*************************************************************************/
106 #pragma mark -
107 #pragma mark INSTANCE METHODS
108 /*************************************************************************/
109
110 - (BOOL)ignoresMouseEvents
111 {
112     return _reallyIgnoresEvents;
113 }
114
115 - (void)setIgnoresMouseEvents:(BOOL)flag
116 {
117     CGSValueObj          key;
118     CGSValueObj          ignore;
119
120     key = CGSCreateCString("IgnoreForEvents");
121     ignore = CGSCreateBoolean( (flag ? kCGSTrue : kCGSFalse) );
122     CGSSetWindowProperty([NSApp contextID], (CGSWindowID)[self windowNumber], key, ignore);
123     CGSReleaseObj(key);
124     CGSReleaseObj(ignore);
125
126     _reallyIgnoresEvents = flag;
127 }
128
129
130 /*
131
132 - (id)contentView
133 {
134     if ( _backgroundType == ITTransientStatusWindowRounded ) {
135         return _contentSubView;
136     } else {
137         return [super contentView];
138     }
139 }
140
141 - (void)setContentView:(NSView *)aView
142 {
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];
149     } else {
150         [super setContentView:aView];
151     }
152 }
153
154 */
155
156 - (IBAction)appear:(id)sender
157 {
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];
169     }
170 }
171
172 - (IBAction)vanish:(id)sender
173 {
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.
184     }
185 }
186
187 - (ITWindowVisibilityState)visibilityState
188 {
189     return _visibilityState;
190 }
191
192 - (void)setVisibilityState:(ITWindowVisibilityState)newState
193 {
194     _visibilityState = newState;
195     
196     if ( _visibilityState == ITWindowVisibleState ) {
197         [self startVanishTimer];
198     } else if ( (_visibilityState == ITWindowVanishingState) || (_visibilityState == ITWindowHiddenState) ) {
199         [self stopVanishTimer];
200     }
201 }
202
203 - (ITTransientStatusWindowExitMode)exitMode
204 {
205     return _exitMode;
206 }
207
208 - (void)setExitMode:(ITTransientStatusWindowExitMode)newMode
209 {
210     _exitMode = newMode;
211     
212     if ( _visibilityState == ITWindowVisibleState ) {
213         if ( _exitMode == ITTransientStatusWindowExitOnCommand ) {
214             [self stopVanishTimer];
215         } else if ( _exitMode == ITTransientStatusWindowExitAfterDelay ) {
216             [self startVanishTimer];
217         }
218     }
219 }
220
221 - (float)exitDelay
222 {
223     return _exitDelay;
224 }
225
226 - (void)setExitDelay:(float)seconds
227 {
228     _exitDelay = seconds;
229 }
230
231 - (ITTransientStatusWindowBackgroundType)backgroundType
232 {
233 //  return _backgroundType;
234     return ITTransientStatusWindowRounded;
235 }
236
237 - (void)setBackgroundType:(ITTransientStatusWindowBackgroundType)newType
238 {
239 //  setBackgroundType: is currently ignored.  Defaults to ITTransientStatusWindowRounded.
240 //  _backgroundType = newType;
241     _backgroundType = ITTransientStatusWindowRounded;
242 }
243
244 - (ITVerticalWindowPosition)verticalPosition;
245 {
246     return _verticalPosition;
247 }
248
249 - (void)setVerticalPosition:(ITVerticalWindowPosition)newPosition;
250 {
251     _verticalPosition = newPosition;
252 }
253
254 - (ITHorizontalWindowPosition)horizontalPosition;
255 {
256     return _horizontalPosition;
257 }
258
259 - (void)setHorizontalPosition:(ITHorizontalWindowPosition)newPosition;
260 {
261     _horizontalPosition = newPosition;
262 }
263
264 - (float)effectProgress
265 {
266     return _effectProgress;
267 }
268
269 - (void)setEffectProgress:(float)newProgress
270 {
271     _effectProgress = newProgress;
272 }
273
274 - (float)screenPadding
275 {
276     return _screenPadding;
277 }
278
279 - (void)setScreenPadding:(float)newPadding
280 {
281     _screenPadding = newPadding;
282 }
283
284 - (int)screenNumber
285 {
286     return _screenNumber;
287 }
288
289 - (void)setScreenNumber:(int)newNumber
290 {
291     _screenNumber = newNumber;
292 }
293
294 - (ITWindowEffect *)entryEffect
295 {
296     return _entryEffect;
297 }
298
299 - (void)setEntryEffect:(ITWindowEffect *)newEffect
300 {
301     [_entryEffect releaseWhenIdle];
302     _entryEffect = [newEffect retain];
303 }
304
305 - (ITWindowEffect *)exitEffect
306 {
307     return _exitEffect;
308 }
309
310 - (void)setExitEffect:(ITWindowEffect *)newEffect
311 {
312     [_exitEffect releaseWhenIdle];
313     _exitEffect = [newEffect retain];
314 }
315
316
317 /*************************************************************************/
318 #pragma mark -
319 #pragma mark PRIVATE METHODS
320 /*************************************************************************/
321
322 - (void)rebuildWindow;
323 {
324     if ( _backgroundType == ITTransientStatusWindowRounded ) {
325         ITGrayRoundedView *roundedView = [[[ITGrayRoundedView alloc] initWithFrame:[self frame]] autorelease];
326
327         [self setBackgroundColor:[NSColor clearColor]];
328         [self setHasShadow:NO];
329         [self setOpaque:NO];
330         
331         [self setContentView:roundedView];
332 //      [super setContentView:roundedView];
333 //      [_contentSubView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
334 //      [self setContentView:_contentSubView];
335     } else {
336         // YUO == CLWONBAOT
337     }
338 }
339
340 - (void)startVanishTimer
341 {
342     if ( _exitMode == ITTransientStatusWindowExitAfterDelay) {
343         [self stopVanishTimer];
344         _exitTimer = [NSTimer scheduledTimerWithTimeInterval:_exitDelay
345                                                       target:self
346                                                     selector:@selector(doDelayedExit)
347                                                     userInfo:nil
348                                                      repeats:NO];
349     }
350 }
351
352 - (void)doDelayedExit
353 {
354     [self vanish:self];
355     _exitTimer = nil;
356 }
357
358 - (void)stopVanishTimer
359 {
360     if ( _exitTimer ) {
361         [_exitTimer invalidate];
362         _exitTimer = nil;
363     }
364 }
365
366 @end