76e28dd9eda0996018394faea6fd1120a45d8a88
[vlc.git] / modules / gui / macosx / fspanel.m
1 /*****************************************************************************\r
2  * fspanel.m: MacOS X full screen panel\r
3  *****************************************************************************\r
4  * Copyright (C) 2006 the VideoLAN team\r
5  * $Id$\r
6  *\r
7  * Authors: J\8er\99me Decoodt <djc at videolan dot org>\r
8  *          Felix K\9fhne <fkuehne at videolan dot org>\r
9  *\r
10  * This program is free software; you can redistribute it and/or modify\r
11  * it under the terms of the GNU General Public License as published by\r
12  * the Free Software Foundation; either version 2 of the License, or\r
13  * (at your option) any later version.\r
14  * \r
15  * This program is distributed in the hope that it will be useful,\r
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
18  * GNU General Public License for more details.\r
19  *\r
20  * You should have received a copy of the GNU General Public License\r
21  * along with this program; if not, write to the Free Software\r
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.\r
23  *****************************************************************************/\r
24 \r
25 /*****************************************************************************\r
26  * Preamble\r
27  *****************************************************************************/\r
28 #import "intf.h"\r
29 #import "controls.h"\r
30 #import "vout.h"\r
31 #import "fspanel.h"\r
32 \r
33 #define KEEP_VISIBLE_AFTER_ACTION 4 /* time in half-sec until this panel will hide again after an user's action */\r
34 \r
35 /*****************************************************************************\r
36  * VLCFSPanel\r
37  *****************************************************************************/\r
38 @implementation VLCFSPanel\r
39 /* We override this initializer so we can set the NSBorderlessWindowMask styleMask, and set a few other important settings */\r
40 - (id)initWithContentRect:(NSRect)contentRect \r
41                 styleMask:(unsigned int)aStyle \r
42                   backing:(NSBackingStoreType)bufferingType \r
43                     defer:(BOOL)flag\r
44 {\r
45     id win = [super initWithContentRect:contentRect styleMask:NSTexturedBackgroundWindowMask backing:bufferingType defer:flag];\r
46     [win setOpaque:NO];\r
47     [win setHasShadow: NO];\r
48     [win setBackgroundColor:[NSColor clearColor]];\r
49     \r
50     /* let the window sit on top of everything else and start out completely transparent */\r
51     [win setLevel:NSFloatingWindowLevel];\r
52     [win setAlphaValue:0.0];\r
53     i_device = 0;\r
54 \r
55     [win center];\r
56     return win;\r
57 }\r
58 \r
59 - (void)awakeFromNib\r
60 {\r
61     [self setContentView:[[VLCFSPanelView alloc] initWithFrame: [self frame]]];\r
62     BOOL isInside = (NSPointInRect([NSEvent mouseLocation],[self frame]));\r
63     [[self contentView] addTrackingRect:[[self contentView] bounds] owner:self userData:nil assumeInside:isInside];\r
64     if (isInside)\r
65         [self mouseEntered:NULL];\r
66     if (!isInside)\r
67         [self mouseExited:NULL];\r
68     \r
69     /* get a notification if VLC isn't the active app anymore */\r
70     [[NSNotificationCenter defaultCenter]\r
71     addObserver: self\r
72        selector: @selector(setNonActive:)\r
73            name: NSApplicationDidResignActiveNotification\r
74          object: NSApp];\r
75     \r
76     /* get a notification if VLC is the active app again */\r
77     [[NSNotificationCenter defaultCenter]\r
78     addObserver: self\r
79        selector: @selector(setActive:)\r
80            name: NSApplicationDidBecomeActiveNotification\r
81          object: NSApp];\r
82 }\r
83 \r
84 /* Windows created with NSBorderlessWindowMask normally can't be key, but we want ours to be */\r
85 - (BOOL)canBecomeKeyWindow\r
86 {\r
87     return YES;\r
88 }\r
89 \r
90 - (BOOL)mouseDownCanMoveWindow\r
91 {\r
92     return YES;\r
93 }\r
94 \r
95 -(void)dealloc\r
96 {\r
97     [[NSNotificationCenter defaultCenter] removeObserver: self];\r
98     \r
99     if( hideAgainTimer )\r
100         [hideAgainTimer release];\r
101     [self setFadeTimer:nil];\r
102     [super dealloc];\r
103 }\r
104 \r
105 -(void)center\r
106 {\r
107     /* centre the panel in the lower third of the screen */\r
108     NSPoint theCoordinate;\r
109     NSRect theScreensFrame;\r
110     NSRect theWindowsFrame;\r
111 \r
112     if( i_device < 0 || i_device >= (signed int)[[NSScreen screens] count] )\r
113         /* invalid preferences or none specified, using main screen */\r
114         theScreensFrame = [[NSScreen mainScreen] frame];\r
115     else\r
116         /* user-defined screen */\r
117         theScreensFrame = [[[NSScreen screens] objectAtIndex: i_device] frame];\r
118 \r
119     theWindowsFrame = [self frame];\r
120     \r
121     theCoordinate.x = (theScreensFrame.size.width - theWindowsFrame.size.width) / 2 + theScreensFrame.origin.x;\r
122     theCoordinate.y = (theScreensFrame.size.height / 3) - theWindowsFrame.size.height + theScreensFrame.origin.y;\r
123     [self setFrameTopLeftPoint: theCoordinate];\r
124 }\r
125 \r
126 - (void)setPlay\r
127 {\r
128     [[self contentView] setPlay];\r
129 }\r
130 \r
131 - (void)setPause\r
132 {\r
133     [[self contentView] setPause];\r
134 }\r
135 \r
136 - (void)setStreamTitle:(NSString *)o_title\r
137 {\r
138     [[self contentView] setStreamTitle: o_title];\r
139 }\r
140 \r
141 - (void)setStreamPos:(float) f_pos andTime:(NSString *)o_time\r
142 {\r
143     [[self contentView] setStreamPos:f_pos andTime: o_time];\r
144 }\r
145 \r
146 - (void)setSeekable:(BOOL) b_seekable\r
147 {\r
148     [[self contentView] setSeekable: b_seekable];\r
149 }\r
150 \r
151 - (void)setVolumeLevel: (float)f_volumeLevel\r
152 {\r
153     [[self contentView] setVolumeLevel: f_volumeLevel];\r
154 }\r
155 \r
156 - (void)setNonActive:(id)noData\r
157 {\r
158     b_nonActive = YES;\r
159     [self orderOut: self];\r
160 }\r
161 \r
162 - (void)setActive:(id)noData\r
163 {\r
164     b_nonActive = NO;\r
165     [self orderFront: self];\r
166 }\r
167 \r
168 /* This routine is called repeatedly to fade in the window */\r
169 - (void)focus:(NSTimer *)timer\r
170 {\r
171     /* we need to push ourselves to front if the vout window was closed since our last display */\r
172     if( b_voutWasUpdated )\r
173     {\r
174         [self orderFront: self];\r
175         b_voutWasUpdated = NO;\r
176     }\r
177 \r
178     if( [self alphaValue] < 1.0 )\r
179         [self setAlphaValue:[self alphaValue]+0.1];\r
180     if( [self alphaValue] >= 1.0 )\r
181     {\r
182         b_displayed = YES;\r
183         [self setAlphaValue: 1.0];\r
184         [self setFadeTimer:nil];\r
185         if( b_fadeQueued )\r
186         {\r
187             b_fadeQueued=NO;\r
188             [self setFadeTimer:[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unfocus:) userInfo:NULL repeats:YES]];\r
189         }\r
190     }\r
191 }\r
192 \r
193 /* This routine is called repeatedly to hide the window */\r
194 - (void)unfocus:(NSTimer *)timer\r
195 {\r
196     if( b_keptVisible )\r
197     {\r
198         b_keptVisible = NO;\r
199         b_fadeQueued = NO;\r
200         [[self fadeTimer] release];\r
201         [self setFadeTimer: NULL];\r
202         [self fadeIn];\r
203         return;\r
204     }\r
205     if( [self alphaValue] > 0.0 )\r
206         [self setAlphaValue:[self alphaValue]-0.1];\r
207     if( [self alphaValue] <= 0.1 )\r
208     {\r
209         b_displayed = NO;\r
210         [self setAlphaValue:0.0];\r
211         [self setFadeTimer:nil];\r
212         if( b_fadeQueued )\r
213         {\r
214             b_fadeQueued=NO;\r
215             [self setFadeTimer:\r
216                 [NSTimer scheduledTimerWithTimeInterval:0.1 \r
217                                                  target:self \r
218                                                selector:@selector(focus:) \r
219                                                userInfo:NULL \r
220                                                 repeats:YES]];\r
221         }\r
222     }\r
223 }\r
224 \r
225 - (void)mouseExited:(NSEvent *)theEvent\r
226 {\r
227     /* give up our focus, so the vout may show us again without letting the user clicking it */\r
228     if( [[[[VLCMain sharedInstance] getControls] getVoutView] isFullscreen] )\r
229         [[[[[VLCMain sharedInstance] getControls] getVoutView] window] makeKeyWindow];\r
230 }\r
231 \r
232 - (void)fadeIn\r
233 {\r
234     /* in case that the user don't want us to appear, just return here */\r
235     if(! config_GetInt( VLCIntf, "macosx-fspanel" ) || b_nonActive )\r
236         return;\r
237     \r
238     if( [self alphaValue] < 1.0 )\r
239     {\r
240         if (![self fadeTimer])\r
241             [self setFadeTimer:[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(focus:) userInfo:[NSNumber numberWithShort:1] repeats:YES]];\r
242         else if ([[[self fadeTimer] userInfo] shortValue]==0)\r
243             b_fadeQueued=YES;\r
244     }\r
245     [self autoHide];\r
246 }\r
247 \r
248 - (void)fadeOut\r
249 {\r
250     if( NSPointInRect([NSEvent mouseLocation],[self frame]))\r
251         return;\r
252 \r
253     if( ( [self alphaValue] > 0.0 ) )\r
254     {\r
255         if (![self fadeTimer])\r
256             [self setFadeTimer:[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(unfocus:) userInfo:[NSNumber numberWithShort:0] repeats:YES]];\r
257         else if ([[[self fadeTimer] userInfo] shortValue]==1)\r
258             b_fadeQueued=YES;\r
259     }\r
260 }\r
261 \r
262 /* triggers a timer to autoHide us again after some seconds of no activity */\r
263 - (void)autoHide\r
264 {\r
265     /* this will tell the timer to start over again or to start at all */\r
266     b_keptVisible = YES;\r
267     \r
268     /* get us a valid timer */\r
269     if(! b_alreadyCounting )\r
270     {\r
271         hideAgainTimer = [NSTimer scheduledTimerWithTimeInterval: 0.5\r
272                                                           target: self \r
273                                                         selector: @selector(keepVisible:)\r
274                                                         userInfo: nil \r
275                                                          repeats: YES];\r
276         [hideAgainTimer fire];\r
277         [hideAgainTimer retain];\r
278         b_alreadyCounting = YES;\r
279     }\r
280 }\r
281 \r
282 - (void)keepVisible:(NSTimer *)timer\r
283 {\r
284     /* if the user triggered an action, start over again */\r
285     if( b_keptVisible )\r
286     {\r
287         i_timeToKeepVisibleInSec = KEEP_VISIBLE_AFTER_ACTION;\r
288         b_keptVisible = NO;\r
289     }\r
290     \r
291     /* count down until we hide ourselfes again and do so if necessary */\r
292     i_timeToKeepVisibleInSec -= 1;\r
293     if( i_timeToKeepVisibleInSec < 1 )\r
294     {\r
295         [self fadeOut];\r
296         [timer invalidate];\r
297         [timer release];\r
298         b_alreadyCounting = NO;\r
299         timer = NULL;\r
300     }\r
301 }\r
302 \r
303 /* A getter and setter for our main timer that handles window fading */\r
304 - (NSTimer *)fadeTimer\r
305 {\r
306     return fadeTimer;\r
307 }\r
308 \r
309 - (void)setFadeTimer:(NSTimer *)timer\r
310 {\r
311     [timer retain];\r
312     [fadeTimer invalidate];\r
313     [fadeTimer release];\r
314     fadeTimer=timer;\r
315 }\r
316 \r
317 - (void)mouseDown:(NSEvent *)theEvent\r
318 {\r
319     mouseClic = [theEvent locationInWindow];\r
320 }\r
321 \r
322 - (void)mouseDragged:(NSEvent *)theEvent\r
323 {\r
324     NSPoint point = [NSEvent mouseLocation];\r
325     point.x -= mouseClic.x;\r
326     point.y -= mouseClic.y;\r
327     [self setFrameOrigin:point];\r
328 }\r
329 \r
330 - (BOOL)isDisplayed\r
331 {\r
332     return b_displayed;\r
333 }\r
334 \r
335 - (void)setVoutWasUpdated: (int)i_newdevice;\r
336 {\r
337     b_voutWasUpdated = YES;\r
338     if( i_newdevice != i_device )\r
339     {\r
340         i_device = i_newdevice;\r
341         [self center];\r
342     }\r
343 }\r
344 @end\r
345 \r
346 /*****************************************************************************\r
347  * FSPanelView\r
348  *****************************************************************************/\r
349 @implementation VLCFSPanelView\r
350 \r
351 #define addButton( o_button, imageOff, imageOn, _x, _y, action )                                \\r
352     s_rc.origin.x = _x;                                                                         \\r
353     s_rc.origin.y = _y;                                                                         \\r
354     o_button = [[NSButton alloc] initWithFrame: s_rc];                                 \\r
355     [o_button setButtonType: NSMomentaryChangeButton];                                          \\r
356     [o_button setBezelStyle: NSRegularSquareBezelStyle];                                        \\r
357     [o_button setBordered: NO];                                                                 \\r
358     [o_button setFont:[NSFont systemFontOfSize:0]];                                             \\r
359     [o_button setImage:[NSImage imageNamed:imageOff]];                                 \\r
360     [o_button setAlternateImage:[NSImage imageNamed:imageOn]];                         \\r
361     [o_button sizeToFit];                                                                       \\r
362     [o_button setTarget: self];                                                                 \\r
363     [o_button setAction: @selector(action:)];                                                   \\r
364     [self addSubview:o_button];\r
365 \r
366 #define addTextfield( o_text, align, font, color, size )                                    \\r
367     o_text = [[NSTextField alloc] initWithFrame: s_rc];                            \\r
368     [o_text setDrawsBackground: NO];                                                        \\r
369     [o_text setBordered: NO];                                                               \\r
370     [o_text setEditable: NO];                                                               \\r
371     [o_text setSelectable: NO];                                                             \\r
372     [o_text setStringValue: _NS("(no item is being played)")];                                                    \\r
373     [o_text setAlignment: align];                                                           \\r
374     [o_text setTextColor: [NSColor color]];                                                 \\r
375     [o_text setFont:[NSFont font:[NSFont smallSystemFontSize] - size]];                     \\r
376     [self addSubview:o_text];\r
377 \r
378 - (id)initWithFrame:(NSRect)frameRect\r
379 {\r
380     id view = [super initWithFrame:frameRect];\r
381     fillColor = [[NSColor clearColor] retain];\r
382     NSRect s_rc = [self frame];\r
383     addButton( o_prev, @"fs_skip_previous" , @"fs_skip_previous_highlight", 174, 15, prev );\r
384     addButton( o_bwd, @"fs_rewind"        , @"fs_rewind_highlight"       , 211, 14, backward );\r
385     addButton( o_play, @"fs_play"          , @"fs_play_highlight"         , 267, 10, play );\r
386     addButton( o_fwd, @"fs_forward"       , @"fs_forward_highlight"      , 313, 14, forward );\r
387     addButton( o_next, @"fs_skip_next"     , @"fs_skip_next_highlight"    , 365, 15, next );\r
388     addButton( o_fullscreen, @"fs_exit_fullscreen", @"fs_exit_fullscreen_hightlight", 507, 13, windowAction );\r
389 /*\r
390     addButton( o_button, @"image (off state)", @"image (on state)", 38, 51, something );\r
391  */\r
392 \r
393     /* time slider */\r
394     s_rc = [self frame];\r
395     s_rc.origin.x = 15;\r
396     s_rc.origin.y = 53;\r
397     s_rc.size.width = 518;\r
398     s_rc.size.height = 9;\r
399     o_fs_timeSlider = [[VLCFSTimeSlider alloc] initWithFrame: s_rc];\r
400     [o_fs_timeSlider setMinValue:0];\r
401     [o_fs_timeSlider setMaxValue:10000];\r
402     [o_fs_timeSlider setFloatValue: 0];\r
403     [o_fs_timeSlider setContinuous: YES];\r
404     [o_fs_timeSlider setTarget: self];\r
405     [o_fs_timeSlider setAction: @selector(fsTimeSliderUpdate:)];\r
406     [self addSubview: o_fs_timeSlider];\r
407 \r
408     /* volume slider */\r
409     s_rc = [self frame];\r
410     s_rc.origin.x = 26;\r
411     s_rc.origin.y = 17.5;\r
412     s_rc.size.width = 95;\r
413     s_rc.size.height = 10;\r
414     o_fs_volumeSlider = [[VLCFSVolumeSlider alloc] initWithFrame: s_rc];\r
415     [o_fs_volumeSlider setMinValue:0];\r
416     [o_fs_volumeSlider setMaxValue:32];\r
417     [o_fs_volumeSlider setFloatValue: 0];\r
418     [o_fs_volumeSlider setContinuous: YES];\r
419     [o_fs_volumeSlider setTarget: self];\r
420     [o_fs_volumeSlider setAction: @selector(fsVolumeSliderUpdate:)];\r
421     [self addSubview: o_fs_volumeSlider];\r
422     \r
423     /* time counter and stream title output fields */\r
424     s_rc = [self frame];\r
425     s_rc.origin.x = 98;\r
426     s_rc.origin.y = 64;\r
427     s_rc.size.width = 352;\r
428     s_rc.size.height = 14;\r
429     addTextfield( o_streamTitle_txt, NSCenterTextAlignment, systemFontOfSize, whiteColor, 0 );\r
430     s_rc.origin.x = 486;\r
431     s_rc.origin.y = 64;\r
432     s_rc.size.width = 50;\r
433     addTextfield( o_streamPosition_txt, NSRightTextAlignment, systemFontOfSize, whiteColor, 0 );\r
434 \r
435     return view;\r
436 }\r
437 \r
438 - (void)dealloc\r
439 {\r
440     [o_fs_timeSlider release];\r
441     [o_fs_volumeSlider release];\r
442     [o_prev release];\r
443     [o_next release];\r
444     [o_bwd release];\r
445     [o_play release];\r
446     [o_fwd release];\r
447     [o_fullscreen release];\r
448     [o_streamTitle_txt release];\r
449     [o_streamPosition_txt release];\r
450     [super dealloc];\r
451 }\r
452 \r
453 - (void)setPlay\r
454 {\r
455     [o_play setImage:[NSImage imageNamed:@"fs_play"]];\r
456     [o_play setAlternateImage: [NSImage imageNamed:@"fs_play_highlight"]];\r
457 }\r
458 \r
459 - (void)setPause\r
460 {\r
461     [o_play setImage: [NSImage imageNamed:@"fs_pause"]];\r
462     [o_play setAlternateImage: [NSImage imageNamed:@"fs_pause_highlight"]];\r
463 }\r
464 \r
465 - (void)setStreamTitle:(NSString *)o_title\r
466 {\r
467     [o_streamTitle_txt setStringValue: o_title];\r
468 }\r
469 \r
470 - (void)setStreamPos:(float) f_pos andTime:(NSString *)o_time\r
471 {\r
472     [o_streamPosition_txt setStringValue: o_time];\r
473     [o_fs_timeSlider setFloatValue: f_pos];\r
474 }\r
475 \r
476 - (void)setSeekable:(BOOL)b_seekable\r
477 {\r
478     [o_bwd setEnabled: b_seekable];\r
479     [o_fwd setEnabled: b_seekable];\r
480     [o_fs_timeSlider setEnabled: b_seekable];\r
481 }\r
482 \r
483 - (void)setVolumeLevel: (float)f_volumeLevel\r
484 {\r
485     [o_fs_volumeSlider setFloatValue: f_volumeLevel];\r
486 }\r
487 \r
488 - (IBAction)play:(id)sender\r
489 {\r
490     [[[VLCMain sharedInstance] getControls] play: sender];\r
491 }\r
492 \r
493 - (IBAction)forward:(id)sender\r
494 {\r
495     [[[VLCMain sharedInstance] getControls] forward: sender];\r
496 }\r
497 \r
498 - (IBAction)backward:(id)sender\r
499 {\r
500     [[[VLCMain sharedInstance] getControls] backward: sender];\r
501 }\r
502 \r
503 - (IBAction)prev:(id)sender\r
504 {\r
505     [[[VLCMain sharedInstance] getControls] prev: sender];\r
506 }\r
507 \r
508 - (IBAction)next:(id)sender\r
509 {\r
510     [[[VLCMain sharedInstance] getControls] next: sender];\r
511 }\r
512 \r
513 - (IBAction)windowAction:(id)sender\r
514 {\r
515     [[[VLCMain sharedInstance] getControls] windowAction: sender];\r
516 }\r
517 \r
518 - (IBAction)fsTimeSliderUpdate:(id)sender\r
519 {\r
520     [[VLCMain sharedInstance] timesliderUpdate: sender];\r
521 }\r
522 \r
523 - (IBAction)fsVolumeSliderUpdate:(id)sender\r
524 {\r
525     [[[VLCMain sharedInstance] getControls] volumeSliderUpdated: sender];\r
526 }\r
527 \r
528 #define addImage(image, _x, _y, mode, _width)                                               \\r
529     img = [NSImage imageNamed:image];                                              \\r
530     image_rect.size = [img size];                                                           \\r
531     image_rect.origin.x = 0;                                                                \\r
532     image_rect.origin.y = 0;                                                                \\r
533     frame.origin.x = _x;                                                                    \\r
534     frame.origin.y = _y;                                                                    \\r
535     frame.size = [img size];                                                                \\r
536     if( _width ) frame.size.width = _width;                                                 \\r
537     [img drawInRect:frame fromRect:image_rect operation:mode fraction:1];\r
538 \r
539 - (void)drawRect:(NSRect)rect\r
540 {\r
541         NSRect frame = [self frame];\r
542     NSRect image_rect;\r
543     NSImage *img;\r
544     addImage( @"fs_background", 0, 0, NSCompositeCopy, 0 );\r
545     addImage( @"fs_volume_slider_bar", 26, 22, NSCompositeSourceOver, 0 );\r
546     addImage( @"fs_volume_mute", 16, 18, NSCompositeSourceOver, 0 );\r
547     addImage( @"fs_volume_max", 124, 17, NSCompositeSourceOver, 0 );\r
548     addImage( @"fs_time_slider", 15, 53, NSCompositeSourceOver, 0);\r
549 }\r
550 \r
551 @end\r
552 \r
553 /*****************************************************************************\r
554  * VLCFSTimeSlider\r
555  *****************************************************************************/\r
556 @implementation VLCFSTimeSlider\r
557 - (void)drawKnobInRect:(NSRect)knobRect\r
558 {\r
559     NSRect image_rect;\r
560     NSImage *img = [NSImage imageNamed:@"fs_time_slider_knob_highlight"];\r
561     image_rect.size = [img size];\r
562     image_rect.origin.x = 0;\r
563     image_rect.origin.y = 0;\r
564     knobRect.origin.x += (knobRect.size.width - image_rect.size.width) / 2;\r
565     knobRect.size.width = image_rect.size.width;\r
566     knobRect.size.height = image_rect.size.height;\r
567     [img drawInRect:knobRect fromRect:image_rect operation:NSCompositeSourceOver fraction:1];\r
568 }\r
569 \r
570 - (void)drawRect:(NSRect)rect\r
571 {\r
572     /* Draw default to make sure the slider behaves correctly */\r
573     [[NSGraphicsContext currentContext] saveGraphicsState];\r
574     NSRectClip(NSZeroRect);\r
575     [super drawRect:rect];\r
576     [[NSGraphicsContext currentContext] restoreGraphicsState];\r
577     \r
578     NSRect knobRect = [[self cell] knobRectFlipped:NO];\r
579     knobRect.origin.y+=7.5;\r
580     [[[NSColor blackColor] colorWithAlphaComponent:0.6] set];\r
581     [self drawKnobInRect: knobRect];\r
582 }\r
583 \r
584 @end\r
585 \r
586 /*****************************************************************************\r
587 * VLCFSVolumeSlider\r
588 *****************************************************************************/\r
589 @implementation VLCFSVolumeSlider\r
590 - (void)drawKnobInRect:(NSRect) knobRect\r
591 {\r
592     NSRect image_rect;\r
593     NSImage *img = [NSImage imageNamed:@"fs_volume_slider_knob"];\r
594     image_rect.size = [img size];\r
595     image_rect.origin.x = 0;\r
596     image_rect.origin.y = 0;\r
597     knobRect.origin.x += (knobRect.size.width - image_rect.size.width) / 2;\r
598     knobRect.size.width = image_rect.size.width;\r
599     knobRect.size.height = image_rect.size.height;\r
600     [img drawInRect:knobRect fromRect:image_rect operation:NSCompositeSourceOver fraction:1];\r
601 }\r
602 \r
603 - (void)drawRect:(NSRect)rect\r
604 {\r
605     /* Draw default to make sure the slider behaves correctly */\r
606     [[NSGraphicsContext currentContext] saveGraphicsState];\r
607     NSRectClip(NSZeroRect);\r
608     [super drawRect:rect];\r
609     [[NSGraphicsContext currentContext] restoreGraphicsState];\r
610     \r
611     NSRect knobRect = [[self cell] knobRectFlipped:NO];\r
612     knobRect.origin.y+=6;\r
613     [[[NSColor blackColor] colorWithAlphaComponent:0.6] set];\r
614     [self drawKnobInRect: knobRect];\r
615 }\r
616 \r
617 @end\r
618 \r