Progress Check In
[ITKit.git] / ITTransientStatusWindow.m
1 #import "ITTransientStatusWindow.h"
2 #import <CoreGraphics/CoreGraphics.h>
3 #import "ITCoreGraphicsHacks.h"
4 #import "ITTextField.h"
5 #import "ITGrayRoundedView.h"
6
7 @class ITTextField;
8 @class ITGrayRoundedView;
9
10 /*************************************************************************/
11 #pragma mark -
12 #pragma mark EVIL HACKERY
13 /*************************************************************************/
14
15 @interface NSApplication (HACKHACKHACKHACK)
16 - (CGSConnectionID)contextID;
17 @end
18
19
20 /*************************************************************************/
21 #pragma mark -
22 #pragma mark PRIVATE METHOD DECLARATIONS
23 /*************************************************************************/
24
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;
34 @end
35
36
37 /*************************************************************************/
38 #pragma mark -
39 #pragma mark IMPLEMENTATION
40 /*************************************************************************/
41
42 @implementation ITTransientStatusWindow
43
44
45 /*************************************************************************/
46 #pragma mark -
47 #pragma mark SHARED STATIC OBJECTS
48 /*************************************************************************/
49
50 static ITTransientStatusWindow *staticWindow = nil;
51
52
53 /*************************************************************************/
54 #pragma mark -
55 #pragma mark INITIALIZATION METHODS
56 /*************************************************************************/
57
58 + (ITTransientStatusWindow *)sharedWindow
59 {
60     if ( ! (staticWindow) ) {
61         staticWindow = [[self alloc] initWithContentView:nil
62                                                 exitMode:ITTransientStatusWindowExitAfterDelay
63                                           backgroundType:ITTransientStatusWindowRounded];
64     }
65     return staticWindow;
66 }
67
68 - (id)initWithContentView:(NSView *)contentView
69                  exitMode:(ITTransientStatusWindowExitMode)exitMode
70            backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType
71 {
72     NSRect contentRect;
73     
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];
78     }
79     
80     // Set the content rect to the frame of the content view, now guaranteed to exist.
81     contentRect = [contentView frame];
82     
83     if ( ( self = [super initWithContentRect:contentRect
84                                    styleMask:NSBorderlessWindowMask
85                                      backing:NSBackingStoreBuffered
86                                        defer:NO] ) ) {
87                                     
88         _visibilityState     = ITTransientStatusWindowHiddenState;
89         _exitMode            = exitMode;
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;
98         _delayTimer = nil;
99         _fadeTimer  = nil;
100
101 //        if ( _backgroundType == ITTransientStatusWindowRounded ) {
102 //            _contentSubView = contentView;
103 //        } else {
104 //            [self setContentView:contentView];
105 //        }
106
107         [self setIgnoresMouseEvents:YES];
108         [self setLevel:NSScreenSaverWindowLevel];
109         [self setContentView:contentView];
110         [self rebuildWindow];
111     }
112     return self;
113 }
114
115
116 /*************************************************************************/
117 #pragma mark -
118 #pragma mark INSTANCE METHODS
119 /*************************************************************************/
120
121 - (void)setRotation:(float)angle
122 {
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) ));
131     NSLog(@"%f %f", ([self frame].origin.x * -1), ([self frame].origin.y * -1));
132 }
133
134 - (BOOL)ignoresMouseEvents
135 {
136     return _reallyIgnoresEvents;
137 }
138
139 - (void)setIgnoresMouseEvents:(BOOL)flag
140 {
141     CGSValueObj          key;
142     CGSValueObj          ignore;
143
144     key = CGSCreateCString("IgnoreForEvents");
145     ignore = CGSCreateBoolean( (flag ? kCGSTrue : kCGSFalse) );
146     CGSSetWindowProperty([NSApp contextID], (CGSWindowID)[self windowNumber], key, ignore);
147     CGSReleaseObj(key);
148     CGSReleaseObj(ignore);
149
150     _reallyIgnoresEvents = flag;
151 }
152
153 - (void)orderFront:(id)sender
154 {
155     if ( _exitMode == ITTransientStatusWindowExitAfterDelay ) {
156         // set the timer, and orderOut: when it lapses.
157     }
158
159     if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
160         [super orderFront:sender];
161     } else {
162         [self performEffect];
163     }
164 }
165
166 - (void)makeKeyAndOrderFront:(id)sender
167 {
168     if ( _exitMode == ITTransientStatusWindowExitAfterDelay ) {
169         // set the timer, and orderOut: when it lapses.
170     }
171
172     if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
173         [super makeKeyAndOrderFront:sender];
174     } else {
175         [self performEffect];
176         [self makeKeyWindow];
177     }
178 }
179
180 - (void)orderOut:(id)sender
181 {
182     if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
183         [super orderOut:sender];
184     } else {
185         [self performEffect];
186     }
187 }
188
189 - (NSTimeInterval)animationResizeTime:(NSRect)newFrame
190 {
191     return _effectTime;
192 }
193
194 /*
195
196 - (id)contentView
197 {
198     if ( _backgroundType == ITTransientStatusWindowRounded ) {
199         return _contentSubView;
200     } else {
201         return [super contentView];
202     }
203 }
204
205 - (void)setContentView:(NSView *)aView
206 {
207     if ( _backgroundType == ITTransientStatusWindowRounded ) {
208        [_contentSubView removeFromSuperview];
209         _contentSubView = aView;
210         [_contentSubView setFrame:[[super contentView] frame]];
211         [[super contentView] addSubview:_contentSubView];
212         [_contentSubView setNextResponder:self];
213     } else {
214         [super setContentView:aView];
215     }
216 }
217
218 */
219
220 - (ITTransientStatusWindowVisibilityState)visibilityState
221 {
222     return _visibilityState;
223 }
224
225 - (ITTransientStatusWindowExitMode)exitMode
226 {
227     return _exitMode;
228 }
229
230 - (void)setExitMode:(ITTransientStatusWindowExitMode)newMode
231 {
232     _exitMode = newMode;
233 }
234
235 - (float)exitDelay
236 {
237     return _exitDelay;
238 }
239
240 - (void)setExitDelay:(float)seconds
241 {
242     _exitDelay = seconds;
243 }
244
245 - (ITTransientStatusWindowBackgroundType)backgroundType
246 {
247 //  return _backgroundType;
248     return ITTransientStatusWindowRounded;
249 }
250
251 - (void)setBackgroundType:(ITTransientStatusWindowBackgroundType)newType
252 {
253 //  setBackgroundType: is currently ignored.  Defaults to ITTransientStatusWindowRounded.
254 //  _backgroundType = newType;
255     _backgroundType = ITTransientStatusWindowRounded;
256 }
257
258 - (ITTransientStatusWindowPosition)verticalPosition;
259 {
260     return _verticalPosition;
261 }
262
263 - (void)setVerticalPosition:(ITTransientStatusWindowPosition)newPosition;
264 {
265     _verticalPosition = newPosition;
266 }
267
268 - (ITTransientStatusWindowPosition)horizontalPosition;
269 {
270     return _horizontalPosition;
271 }
272
273 - (void)setHorizontalPosition:(ITTransientStatusWindowPosition)newPosition;
274 {
275     _horizontalPosition = newPosition;
276 }
277
278 - (ITTransientStatusWindowEffect)entryEffect
279 {
280     return _entryEffect;
281 }
282
283 - (void)setEntryEffect:(ITTransientStatusWindowEffect)newEffect;
284 {
285     _entryEffect = newEffect;
286 }
287
288 - (ITTransientStatusWindowEffect)exitEffect;
289 {
290     return _exitEffect;
291 }
292
293 - (void)setExitEffect:(ITTransientStatusWindowEffect)newEffect;
294 {
295     _exitEffect = newEffect;
296 }
297
298
299 /*************************************************************************/
300 #pragma mark -
301 #pragma mark PRIVATE METHODS
302 /*************************************************************************/
303
304 - (void)rebuildWindow;
305 {
306     if ( _backgroundType == ITTransientStatusWindowRounded ) {
307         ITGrayRoundedView *roundedView = [[[ITGrayRoundedView alloc] initWithFrame:[self frame]] autorelease];
308
309         [self setBackgroundColor:[NSColor clearColor]];
310         [self setHasShadow:NO];
311         [self setOpaque:NO];
312         
313         [self setContentView:roundedView];
314 //      [super setContentView:roundedView];
315 //      [_contentSubView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
316 //      [self setContentView:_contentSubView];
317     } else {
318         // YUO == CLWONBAOT
319     }
320 }
321
322 - (void)performEffect
323 {
324     if ( _visibilityState == ITTransientStatusWindowHiddenState ) {
325         if ( _entryEffect == ITTransientStatusWindowEffectDissolve ) {
326             [self dissolveEffect:YES];
327         } else if ( _entryEffect == ITTransientStatusWindowEffectSlideVertically ) {
328             [self slideVerticalEffect:YES];
329         } else if ( _entryEffect == ITTransientStatusWindowEffectSlideHorizontally ) {
330             [self slideHorizontalEffect:YES];
331         }
332     } else if ( _visibilityState == ITTransientStatusWindowVisibleState ) {
333         if ( _exitEffect == ITTransientStatusWindowEffectDissolve ) {
334             [self dissolveEffect:NO];
335         } else if ( _exitEffect == ITTransientStatusWindowEffectSlideVertically ) {
336             [self slideVerticalEffect:NO];
337         } else if ( _exitEffect == ITTransientStatusWindowEffectSlideHorizontally ) {
338             [self slideHorizontalEffect:NO];
339         }
340     }
341 }
342
343 - (void)dissolveEffect:(BOOL)entering
344 {
345     if ( entering ) {
346         [super orderFront:self];
347     } else {
348         [super orderOut:self];
349     }
350 }
351
352 - (void)slideVerticalEffect:(BOOL)entering
353 {
354     if ( entering ) {
355         [super orderFront:self];
356     } else {
357         [super orderOut:self];
358     }
359 }
360
361 - (void)slideHorizontalEffect:(BOOL)entering
362 {
363     if ( entering ) {
364         [super orderFront:self];
365     } else {
366         [super orderOut:self];
367     }
368 }
369
370
371 @end