ITKit for Menutunes
[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
8 /*************************************************************************/
9 #pragma mark -
10 #pragma mark EVIL HACKERY
11 /*************************************************************************/
12
13 @interface NSApplication (HACKHACKHACKHACK)
14 - (CGSConnectionID)contextID;
15 @end
16
17
18 /*************************************************************************/
19 #pragma mark -
20 #pragma mark PRIVATE METHOD DECLARATIONS
21 /*************************************************************************/
22
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;
32 @end
33
34
35 /*************************************************************************/
36 #pragma mark -
37 #pragma mark IMPLEMENTATION
38 /*************************************************************************/
39
40 @implementation ITTransientStatusWindow
41
42
43 /*************************************************************************/
44 #pragma mark -
45 #pragma mark SHARED STATIC OBJECTS
46 /*************************************************************************/
47
48 static ITTransientStatusWindow *staticWindow = nil;
49
50
51 /*************************************************************************/
52 #pragma mark -
53 #pragma mark INITIALIZATION METHODS
54 /*************************************************************************/
55
56 + (ITTransientStatusWindow *)sharedWindow
57 {
58     if ( ! (staticWindow) ) {
59         staticWindow = [[self alloc] initWithContentView:nil
60                                                 exitMode:ITTransientStatusWindowExitAfterDelay
61                                           backgroundType:ITTransientStatusWindowRounded];
62     }
63     return staticWindow;
64 }
65
66 - (id)initWithContentView:(NSView *)contentView
67                  exitMode:(ITTransientStatusWindowExitMode)exitMode
68            backgroundType:(ITTransientStatusWindowBackgroundType)backgroundType
69 {
70     NSRect contentRect;
71     
72     CGSValueObj          key;
73     CGSValueObj          ignore;
74
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];
79     }
80     
81     // Set the content rect to the frame of the content view, now guaranteed to exist.
82     contentRect = [contentView frame];
83     
84     if ( ( self = [super initWithContentRect:contentRect
85                                    styleMask:NSBorderlessWindowMask
86                                      backing:NSBackingStoreBuffered
87                                        defer:NO] ) ) {
88                                     
89         _visibilityState    = ITTransientStatusWindowHiddenState;
90         _exitMode           = exitMode;
91         _exitDelay          = DEFAULT_EXIT_DELAY;
92         _backgroundType     = backgroundType;
93         _verticalPosition   = ITTransientStatusWindowPositionBottom;
94         _horizontalPosition = ITTransientStatusWindowPositionLeft;
95         _entryEffect        = ITTransientStatusWindowEffectNone;
96         _exitEffect         = ITTransientStatusWindowEffectDissolve;
97         
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
109         key = CGSCreateCString("IgnoreForEvents");
110         ignore = CGSCreateBoolean(kCGSTrue);
111         
112         CGSSetWindowProperty([NSApp contextID], (CGSWindowID)[self windowNumber], key, ignore);
113
114         CGSReleaseObj(key);
115         CGSReleaseObj(ignore);
116         
117         [self setLevel:NSScreenSaverWindowLevel];
118         [self setContentView:contentView];
119         [self rebuildWindow];
120     }
121     return self;
122 }
123
124
125 /*************************************************************************/
126 #pragma mark -
127 #pragma mark INSTANCE METHODS
128 /*************************************************************************/
129
130 - (void)orderFront:(id)sender
131 {
132     if ( _exitMode = ITTransientStatusWindowExitAfterDelay ) {
133         // set the timer, and orderOut: when it lapses.
134     }
135
136     if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
137         [super orderFront:sender];
138     } else {
139         [self performEffect];
140     }
141 }
142
143 - (void)makeKeyAndOrderFront:(id)sender
144 {
145     if ( _exitMode = ITTransientStatusWindowExitAfterDelay ) {
146         // set the timer, and orderOut: when it lapses.
147     }
148
149     if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
150         [super makeKeyAndOrderFront:sender];
151     } else {
152         [self performEffect];
153         [self makeKeyWindow];
154     }
155 }
156
157 - (void)orderOut:(id)sender
158 {
159     if ( _entryEffect == ITTransientStatusWindowEffectNone ) {
160         [super orderOut:sender];
161     } else {
162         [self performEffect];
163     }
164 }
165
166 /*
167
168 - (id)contentView
169 {
170     if ( _backgroundType == ITTransientStatusWindowRounded ) {
171         return _contentSubView;
172     } else {
173         return [super contentView];
174     }
175 }
176
177 - (void)setContentView:(NSView *)aView
178 {
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];
185     } else {
186         [super setContentView:aView];
187     }
188 }
189
190 */
191
192 - (ITTransientStatusWindowVisibilityState)visibilityState
193 {
194     return _visibilityState;
195 }
196
197 - (ITTransientStatusWindowExitMode)ExitMode
198 {
199     return _exitMode;
200 }
201
202 - (void)setExitMode:(ITTransientStatusWindowExitMode)newMode
203 {
204     _exitMode = newMode;
205 }
206
207 - (float)exitDelay
208 {
209     return _exitDelay;
210 }
211
212 - (void)setExitDelay:(float)seconds
213 {
214     _exitDelay = seconds;
215 }
216
217 - (ITTransientStatusWindowBackgroundType)backgroundType
218 {
219 //  return _backgroundType;
220     return ITTransientStatusWindowRounded;
221 }
222
223 - (void)setBackgroundType:(ITTransientStatusWindowBackgroundType)newType
224 {
225 //  setBackgroundType: is currently ignored.  Defaults to ITTransientStatusWindowRounded.
226 //  _backgroundType = newType;
227     _backgroundType = ITTransientStatusWindowRounded;
228 }
229
230 - (ITTransientStatusWindowPosition)verticalPosition;
231 {
232     return _verticalPosition;
233 }
234
235 - (void)setVerticalPosition:(ITTransientStatusWindowPosition)newPosition;
236 {
237     _verticalPosition = newPosition;
238 }
239
240 - (ITTransientStatusWindowPosition)horizontalPosition;
241 {
242     return _horizontalPosition;
243 }
244
245 - (void)setHorizontalPosition:(ITTransientStatusWindowPosition)newPosition;
246 {
247     _horizontalPosition = newPosition;
248 }
249
250 - (ITTransientStatusWindowEffect)entryEffect
251 {
252     return _entryEffect;
253 }
254
255 - (void)setEntryEffect:(ITTransientStatusWindowEffect)newEffect;
256 {
257     _entryEffect = newEffect;
258 }
259
260 - (ITTransientStatusWindowEffect)exitEffect;
261 {
262     return _exitEffect;
263 }
264
265 - (void)setExitEffect:(ITTransientStatusWindowEffect)newEffect;
266 {
267     _exitEffect = newEffect;
268 }
269
270
271 /*************************************************************************/
272 #pragma mark -
273 #pragma mark PRIVATE METHODS
274 /*************************************************************************/
275
276 - (void)rebuildWindow;
277 {
278     if ( _backgroundType == ITTransientStatusWindowRounded ) {
279         ITGrayRoundedView *roundedView = [[[ITGrayRoundedView alloc] initWithFrame:[self frame]] autorelease];
280
281         [self setBackgroundColor:[NSColor clearColor]];
282         [self setHasShadow:NO];
283         [self setOpaque:NO];
284         
285         [self setContentView:roundedView];
286 //      [super setContentView:roundedView];
287 //      [_contentSubView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
288 //      [self setContentView:_contentSubView];
289     } else {
290         // YUO == CLWONBAOT
291     }
292 }
293
294 - (void)performEffect
295 {
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];
303         }
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];
311         }
312     }
313 }
314
315 - (void)dissolveEffect:(BOOL)entering
316 {
317     
318     [super orderFront:self];
319 }
320
321 - (void)slideVerticalEffect:(BOOL)entering
322 {
323     [super orderFront:self];
324 }
325
326 - (void)slideHorizontalEffect:(BOOL)entering
327 {
328     [super orderFront:self];
329 }
330
331
332 @end