]> git.sesse.net Git - vlc/blob - modules/gui/macosx/misc.m
macosx: slim the split view divider and turn it black
[vlc] / modules / gui / macosx / misc.m
1 /*****************************************************************************
2  * misc.m: code not specific to vlc
3  *****************************************************************************
4  * Copyright (C) 2003-2011 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Felix Paul Kühne <fkuehne at videolan dot org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #import <Cocoa/Cocoa.h>
26 #import <Carbon/Carbon.h>
27
28 #import "CompatibilityFixes.h"
29 #import "intf.h"                                          /* VLCApplication */
30 #import "MainWindow.h"
31 #import "misc.h"
32 #import "playlist.h"
33 #import "controls.h"
34 #import <vlc_url.h>
35
36 /*****************************************************************************
37  * NSAnimation (VLCAdditions)
38  *
39  *  Missing extension to NSAnimation
40  *****************************************************************************/
41
42 @implementation NSAnimation (VLCAdditions)
43 /* fake class attributes  */
44 static NSMapTable *VLCAdditions_userInfo = NULL;
45
46 + (void)load
47 {
48     /* init our fake object attribute */
49     VLCAdditions_userInfo = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, NSObjectMapValueCallBacks, 16);
50 }
51
52 - (void)dealloc
53 {
54     NSMapRemove(VLCAdditions_userInfo, self);
55     [super dealloc];
56 }
57
58 - (void)setUserInfo: (void *)userInfo
59 {
60     NSMapInsert(VLCAdditions_userInfo, self, (void*)userInfo);
61 }
62
63 - (void *)userInfo
64 {
65     return NSMapGet(VLCAdditions_userInfo, self);
66 }
67 @end
68
69 /*****************************************************************************
70  * NSScreen (VLCAdditions)
71  *
72  *  Missing extension to NSScreen
73  *****************************************************************************/
74
75 @implementation NSScreen (VLCAdditions)
76
77 static NSMutableArray *blackoutWindows = NULL;
78
79 + (void)load
80 {
81     /* init our fake object attribute */
82     blackoutWindows = [[NSMutableArray alloc] initWithCapacity:1];
83 }
84
85 + (NSScreen *)screenWithDisplayID: (CGDirectDisplayID)displayID
86 {
87     NSUInteger count = [[NSScreen screens] count];
88
89     for( NSUInteger i = 0; i < count; i++ )
90     {
91         NSScreen *screen = [[NSScreen screens] objectAtIndex: i];
92         if([screen displayID] == displayID)
93             return screen;
94     }
95     return nil;
96 }
97
98 - (BOOL)isMainScreen
99 {
100     return ([self displayID] == [[[NSScreen screens] objectAtIndex:0] displayID]);
101 }
102
103 - (BOOL)isScreen: (NSScreen*)screen
104 {
105     return ([self displayID] == [screen displayID]);
106 }
107
108 - (CGDirectDisplayID)displayID
109 {
110         return (CGDirectDisplayID)[[[self deviceDescription] objectForKey: @"NSScreenNumber"] intValue];
111 }
112
113 - (void)blackoutOtherScreens
114 {
115     /* Free our previous blackout window (follow blackoutWindow alloc strategy) */
116     [blackoutWindows makeObjectsPerformSelector:@selector(close)];
117     [blackoutWindows removeAllObjects];
118
119     NSUInteger screenCount = [[NSScreen screens] count];
120     for(NSUInteger i = 0; i < screenCount; i++)
121     {
122         NSScreen *screen = [[NSScreen screens] objectAtIndex: i];
123         VLCWindow *blackoutWindow;
124         NSRect screen_rect;
125
126         if([self isScreen: screen])
127             continue;
128
129         screen_rect = [screen frame];
130         screen_rect.origin.x = screen_rect.origin.y = 0;
131
132         /* blackoutWindow alloc strategy
133             - The NSMutableArray blackoutWindows has the blackoutWindow references
134             - blackoutOtherDisplays is responsible for alloc/releasing its Windows
135         */
136         blackoutWindow = [[VLCWindow alloc] initWithContentRect: screen_rect styleMask: NSBorderlessWindowMask
137                 backing: NSBackingStoreBuffered defer: NO screen: screen];
138         [blackoutWindow setBackgroundColor:[NSColor blackColor]];
139         [blackoutWindow setLevel: NSFloatingWindowLevel]; /* Disappear when Expose is triggered */
140
141         [blackoutWindow displayIfNeeded];
142         [blackoutWindow orderFront: self animate: YES];
143
144         [blackoutWindows addObject: blackoutWindow];
145         [blackoutWindow release];
146
147         if( [screen isMainScreen ] )
148         {
149             if ([screen isMainScreen])
150             {
151                 if (OSX_LEOPARD)
152                     SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar);
153                 else
154                     [NSApp setPresentationOptions:(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)];
155             }
156         }
157     }
158 }
159
160 + (void)unblackoutScreens
161 {
162     NSUInteger blackoutWindowCount = [blackoutWindows count];
163
164     for(NSUInteger i = 0; i < blackoutWindowCount; i++)
165     {
166         VLCWindow *blackoutWindow = [blackoutWindows objectAtIndex: i];
167         [blackoutWindow closeAndAnimate: YES];
168     }
169
170     if (OSX_LEOPARD)
171         SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar);
172     else
173         [NSApp setPresentationOptions:(NSApplicationPresentationDefault)];
174 }
175
176 @end
177
178 /*****************************************************************************
179  * VLCWindow
180  *
181  *  Missing extension to NSWindow
182  *****************************************************************************/
183
184 @implementation VLCWindow
185 - (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask
186     backing:(NSBackingStoreType)backingType defer:(BOOL)flag
187 {
188     self = [super initWithContentRect:contentRect styleMask:styleMask backing:backingType defer:flag];
189     if( self )
190     {
191         b_isset_canBecomeKeyWindow = NO;
192         /* we don't want this window to be restored on relaunch */
193         if ([self respondsToSelector:@selector(setRestorable:)])
194             [self setRestorable:NO];
195     }
196     return self;
197 }
198 - (void)setCanBecomeKeyWindow: (BOOL)canBecomeKey
199 {
200     b_isset_canBecomeKeyWindow = YES;
201     b_canBecomeKeyWindow = canBecomeKey;
202 }
203
204 - (BOOL)canBecomeKeyWindow
205 {
206     if(b_isset_canBecomeKeyWindow)
207         return b_canBecomeKeyWindow;
208
209     return [super canBecomeKeyWindow];
210 }
211
212 - (void)closeAndAnimate: (BOOL)animate
213 {
214     NSInvocation *invoc;
215
216     if (!animate)
217     {
218         [super close];
219         return;
220     }
221
222     invoc = [NSInvocation invocationWithMethodSignature:[super methodSignatureForSelector:@selector(close)]];
223     [invoc setTarget: self];
224
225     if (![self isVisible] || [self alphaValue] == 0.0)
226     {
227         [super close];
228         return;
229     }
230
231     [self orderOut: self animate: YES callback: invoc];
232 }
233
234 - (void)orderOut: (id)sender animate: (BOOL)animate
235 {
236     NSInvocation *invoc = [NSInvocation invocationWithMethodSignature:[super methodSignatureForSelector:@selector(orderOut:)]];
237     [invoc setTarget: self];
238     [invoc setArgument: sender atIndex: 0];
239     [self orderOut: sender animate: animate callback: invoc];
240 }
241
242 - (void)orderOut: (id)sender animate: (BOOL)animate callback:(NSInvocation *)callback
243 {
244     NSViewAnimation *anim;
245     NSViewAnimation *current_anim;
246     NSMutableDictionary *dict;
247
248     if (!animate)
249     {
250         [self orderOut: sender];
251         return;
252     }
253
254     dict = [[NSMutableDictionary alloc] initWithCapacity:2];
255
256     [dict setObject:self forKey:NSViewAnimationTargetKey];
257
258     [dict setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];
259     anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]];
260     [dict release];
261
262     [anim setAnimationBlockingMode:NSAnimationNonblocking];
263     [anim setDuration:0.9];
264     [anim setFrameRate:30];
265     [anim setUserInfo: callback];
266
267     @synchronized(self) {
268         current_anim = self->animation;
269
270         if ([[[current_anim viewAnimations] objectAtIndex:0] objectForKey: NSViewAnimationEffectKey] == NSViewAnimationFadeOutEffect && [current_anim isAnimating])
271         {
272             [anim release];
273         }
274         else
275         {
276             if (current_anim)
277             {
278                 [current_anim stopAnimation];
279                 [anim setCurrentProgress:1.0-[current_anim currentProgress]];
280                 [current_anim release];
281             }
282             else
283                 [anim setCurrentProgress:1.0 - [self alphaValue]];
284             self->animation = anim;
285             [self setDelegate: self];
286             [anim startAnimation];
287         }
288     }
289 }
290
291 - (void)orderFront: (id)sender animate: (BOOL)animate
292 {
293     NSViewAnimation *anim;
294     NSViewAnimation *current_anim;
295     NSMutableDictionary *dict;
296
297     if (!animate)
298     {
299         [super orderFront: sender];
300         [self setAlphaValue: 1.0];
301         return;
302     }
303
304     if (![self isVisible])
305     {
306         [self setAlphaValue: 0.0];
307         [super orderFront: sender];
308     }
309     else if ([self alphaValue] == 1.0)
310     {
311         [super orderFront: self];
312         return;
313     }
314
315     dict = [[NSMutableDictionary alloc] initWithCapacity:2];
316
317     [dict setObject:self forKey:NSViewAnimationTargetKey];
318
319     [dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
320     anim = [[NSViewAnimation alloc] initWithViewAnimations:[NSArray arrayWithObjects:dict, nil]];
321     [dict release];
322
323     [anim setAnimationBlockingMode:NSAnimationNonblocking];
324     [anim setDuration:0.5];
325     [anim setFrameRate:30];
326
327     @synchronized(self) {
328         current_anim = self->animation;
329
330         if ([[[current_anim viewAnimations] objectAtIndex:0] objectForKey: NSViewAnimationEffectKey] == NSViewAnimationFadeInEffect && [current_anim isAnimating])
331         {
332             [anim release];
333         }
334         else
335         {
336             if (current_anim)
337             {
338                 [current_anim stopAnimation];
339                 [anim setCurrentProgress:1.0 - [current_anim currentProgress]];
340                 [current_anim release];
341             }
342             else
343                 [anim setCurrentProgress:[self alphaValue]];
344             self->animation = anim;
345             [self setDelegate: self];
346             [self orderFront: sender];
347             [anim startAnimation];
348         }
349     }
350 }
351
352 - (void)animationDidEnd:(NSAnimation*)anim
353 {
354     if ([self alphaValue] <= 0.0)
355     {
356         NSInvocation * invoc;
357         [super orderOut: nil];
358         [self setAlphaValue: 1.0];
359         if ((invoc = [anim userInfo]))
360             [invoc invoke];
361     }
362 }
363 @end
364
365 /*****************************************************************************
366  * VLCControllerView
367  *****************************************************************************/
368
369 @implementation VLCControllerView
370
371 - (void)dealloc
372 {
373     [self unregisterDraggedTypes];
374     [super dealloc];
375 }
376
377 - (void)awakeFromNib
378 {
379     [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType,
380         NSFilenamesPboardType, nil]];
381 }
382
383 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
384 {
385     if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
386                 == NSDragOperationGeneric)
387     {
388         return NSDragOperationGeneric;
389     }
390     else
391     {
392         return NSDragOperationNone;
393     }
394 }
395
396 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
397 {
398     return YES;
399 }
400
401 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
402 {
403     NSPasteboard *o_paste = [sender draggingPasteboard];
404     NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
405     NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
406     NSData *o_carried_data = [o_paste dataForType:o_desired_type];
407
408     if( o_carried_data )
409     {
410         if ([o_desired_type isEqualToString:NSFilenamesPboardType])
411         {
412             NSArray *o_array = [NSArray array];
413             NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
414             NSUInteger count = [o_values count];
415
416             for( NSUInteger i = 0; i < count; i++)
417             {
418                 NSDictionary *o_dic;
419                 char *psz_uri = make_URI([[o_values objectAtIndex:i] UTF8String], NULL);
420                 if( !psz_uri )
421                     continue;
422
423                 o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
424
425                 free( psz_uri );
426                 o_array = [o_array arrayByAddingObject: o_dic];
427             }
428             [(VLCPlaylist *)[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
429             return YES;
430         }
431     }
432     [self setNeedsDisplay:YES];
433     return YES;
434 }
435
436 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
437 {
438     [self setNeedsDisplay:YES];
439 }
440
441 @end
442
443 /*****************************************************************************
444  * VLBrushedMetalImageView
445  *****************************************************************************/
446
447 @implementation VLBrushedMetalImageView
448
449 - (BOOL)mouseDownCanMoveWindow
450 {
451     return YES;
452 }
453
454 - (void)dealloc
455 {
456     [self unregisterDraggedTypes];
457     [super dealloc];
458 }
459
460 - (void)awakeFromNib
461 {
462     [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType,
463         NSFilenamesPboardType, nil]];
464 }
465
466 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
467 {
468     if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
469                 == NSDragOperationGeneric)
470     {
471         return NSDragOperationGeneric;
472     }
473     else
474     {
475         return NSDragOperationNone;
476     }
477 }
478
479 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
480 {
481     return YES;
482 }
483
484 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
485 {
486     NSPasteboard *o_paste = [sender draggingPasteboard];
487     NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
488     NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
489     NSData *o_carried_data = [o_paste dataForType:o_desired_type];
490     BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
491
492     if( o_carried_data )
493     {
494         if ([o_desired_type isEqualToString:NSFilenamesPboardType])
495         {
496             NSArray *o_array = [NSArray array];
497             NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
498             NSUInteger count = [o_values count];
499
500             for( NSUInteger i = 0; i < count; i++)
501             {
502                 NSDictionary *o_dic;
503                 char *psz_uri = make_URI([[o_values objectAtIndex:i] UTF8String], NULL);
504                 if( !psz_uri )
505                     continue;
506
507                 o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
508                 free( psz_uri );
509
510                 o_array = [o_array arrayByAddingObject: o_dic];
511             }
512             if( b_autoplay )
513                 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
514             else
515                 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
516             return YES;
517         }
518     }
519     [self setNeedsDisplay:YES];
520     return YES;
521 }
522
523 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
524 {
525     [self setNeedsDisplay:YES];
526 }
527
528 @end
529
530
531 /*****************************************************************************
532  * MPSlider
533  *****************************************************************************/
534 @implementation MPSlider
535
536 void _drawKnobInRect(NSRect knobRect)
537 {
538     // Center knob in given rect
539     knobRect.origin.x += (int)((float)(knobRect.size.width - 7)/2.0);
540     knobRect.origin.y += (int)((float)(knobRect.size.height - 7)/2.0);
541
542     // Draw diamond
543     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 6, 1, 1), NSCompositeSourceOver);
544     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 5, 3, 1), NSCompositeSourceOver);
545     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 4, 5, 1), NSCompositeSourceOver);
546     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 0, knobRect.origin.y + 3, 7, 1), NSCompositeSourceOver);
547     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 2, 5, 1), NSCompositeSourceOver);
548     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 1, 3, 1), NSCompositeSourceOver);
549     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 0, 1, 1), NSCompositeSourceOver);
550 }
551
552 void _drawFrameInRect(NSRect frameRect)
553 {
554     // Draw frame
555     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, 1), NSCompositeSourceOver);
556     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y + frameRect.size.height-1, frameRect.size.width, 1), NSCompositeSourceOver);
557     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver);
558     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x+frameRect.size.width-1, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver);
559 }
560
561 - (void)drawRect:(NSRect)rect
562 {
563     // Draw default to make sure the slider behaves correctly
564     [[NSGraphicsContext currentContext] saveGraphicsState];
565     NSRectClip(NSZeroRect);
566     [super drawRect:rect];
567     [[NSGraphicsContext currentContext] restoreGraphicsState];
568
569     // Full size
570     rect = [self bounds];
571     int diff = (int)(([[self cell] knobThickness] - 7.0)/2.0) - 1;
572     rect.origin.x += diff-1;
573     rect.origin.y += diff;
574     rect.size.width -= 2*diff-2;
575     rect.size.height -= 2*diff;
576
577     // Draw dark
578     NSRect knobRect = [[self cell] knobRectFlipped:NO];
579     [[[NSColor blackColor] colorWithAlphaComponent:0.6] set];
580     _drawFrameInRect(rect);
581     _drawKnobInRect(knobRect);
582
583     // Draw shadow
584     [[[NSColor blackColor] colorWithAlphaComponent:0.1] set];
585     rect.origin.x++;
586     rect.origin.y++;
587     knobRect.origin.x++;
588     knobRect.origin.y++;
589     _drawFrameInRect(rect);
590     _drawKnobInRect(knobRect);
591 }
592
593 @end
594
595 /*****************************************************************************
596  * TimeLineSlider
597  *****************************************************************************/
598
599 @implementation TimeLineSlider
600
601 - (void)drawKnobInRect:(NSRect)knobRect
602 {
603     NSRect image_rect;
604     NSImage *img = [NSImage imageNamed:@"progression-knob"];
605     image_rect.size = [img size];
606     image_rect.origin.x = 0;
607     image_rect.origin.y = 0;
608     knobRect.origin.x += (knobRect.size.width - image_rect.size.width) / 2;
609     knobRect.size.width = image_rect.size.width;
610     knobRect.size.height = image_rect.size.height;
611     [img drawInRect:knobRect fromRect:image_rect operation:NSCompositeSourceOver fraction:1];
612 }
613
614 - (void)drawRect:(NSRect)rect
615 {
616     /* Draw default to make sure the slider behaves correctly */
617     [[NSGraphicsContext currentContext] saveGraphicsState];
618     NSRectClip(NSZeroRect);
619     [super drawRect:rect];
620     [[NSGraphicsContext currentContext] restoreGraphicsState];
621
622     NSRect knobRect = [[self cell] knobRectFlipped:NO];
623     knobRect.origin.y+=1;
624     [self drawKnobInRect: knobRect];
625 }
626
627 @end
628
629 /*****************************************************************************
630  * ITSlider
631  *****************************************************************************/
632
633 @implementation ITSlider
634
635 - (void)drawKnobInRect:(NSRect)knobRect
636 {
637     NSRect image_rect;
638     NSImage *img = [NSImage imageNamed:@"volume-slider-knob"];
639     image_rect.size = [img size];
640     image_rect.origin.x = 0;
641     image_rect.origin.y = 0;
642     knobRect.origin.x += (knobRect.size.width - image_rect.size.width) / 2;
643     knobRect.size.width = image_rect.size.width;
644     knobRect.size.height = image_rect.size.height;
645     [img drawInRect:knobRect fromRect:image_rect operation:NSCompositeSourceOver fraction:1];
646 }
647
648 - (void)drawRect:(NSRect)rect
649 {
650     /* Draw default to make sure the slider behaves correctly */
651     [[NSGraphicsContext currentContext] saveGraphicsState];
652     NSRectClip(NSZeroRect);
653     [super drawRect:rect];
654     [[NSGraphicsContext currentContext] restoreGraphicsState];
655
656     NSRect knobRect = [[self cell] knobRectFlipped:NO];
657     knobRect.origin.y+=2;
658     [self drawKnobInRect: knobRect];
659 }
660
661 @end
662
663 /*****************************************************************************
664  * VLCTimeField implementation
665  *****************************************************************************
666  * we need this to catch our click-event in the controller window
667  *****************************************************************************/
668
669 @implementation VLCTimeField
670 + (void)initialize{
671     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
672     NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"NO" forKey:@"DisplayTimeAsTimeRemaining"];
673
674     [defaults registerDefaults:appDefaults];
675 }
676
677 - (void)mouseDown: (NSEvent *)ourEvent
678 {
679     if( [ourEvent clickCount] > 1 )
680         [[[VLCMain sharedInstance] controls] goToSpecificTime: nil];
681     else
682     {
683         if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayTimeAsTimeRemaining"])
684             [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"DisplayTimeAsTimeRemaining"];
685         else
686             [[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"DisplayTimeAsTimeRemaining"];
687     }
688 }
689
690 - (BOOL)timeRemaining
691 {
692     return [[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayTimeAsTimeRemaining"];
693 }
694 @end
695
696 /*****************************************************************************
697  * VLCMainWindowSplitView implementation
698  * comments taken from NSSplitView.h (10.7 SDK)
699  *****************************************************************************/
700 @implementation VLCMainWindowSplitView : NSSplitView
701 /* Return the color of the dividers that the split view is drawing between subviews. The default implementation of this method returns [NSColor clearColor] for the thick divider style. It will also return [NSColor clearColor] for the thin divider style when the split view is in a textured window. All other thin dividers are drawn with a color that looks good between two white panes. You can override this method to change the color of dividers.
702  */
703 - (NSColor *)dividerColor
704 {
705     return [NSColor blackColor];
706 }
707
708 /* Return the thickness of the dividers that the split view is drawing between subviews. The default implementation returns a value that depends on the divider style. You can override this method to change the size of dividers.
709  */
710 - (CGFloat)dividerThickness
711 {
712     return 0.01;
713 }
714 @end