]> git.sesse.net Git - vlc/blob - modules/gui/macosx/misc.m
macosx: implemented the logo and marquee filters in the video filters panel, optimize...
[vlc] / modules / gui / macosx / misc.m
1 /*****************************************************************************
2  * misc.m: code not specific to vlc
3  *****************************************************************************
4  * Copyright (C) 2003-2011 VLC authors and VideoLAN
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 (OSX_LION)
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     [self setImageScaling: NSScaleToFit];
465     [self setImageFrameStyle: NSImageFrameNone];
466     [self setImageAlignment: NSImageAlignCenter];
467 }
468
469 - (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
470 {
471     if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
472                 == NSDragOperationGeneric)
473     {
474         return NSDragOperationGeneric;
475     }
476     else
477     {
478         return NSDragOperationNone;
479     }
480 }
481
482 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
483 {
484     return YES;
485 }
486
487 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
488 {
489     NSPasteboard *o_paste = [sender draggingPasteboard];
490     NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
491     NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
492     NSData *o_carried_data = [o_paste dataForType:o_desired_type];
493     BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
494
495     if( o_carried_data )
496     {
497         if ([o_desired_type isEqualToString:NSFilenamesPboardType])
498         {
499             NSArray *o_array = [NSArray array];
500             NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
501             NSUInteger count = [o_values count];
502
503             for( NSUInteger i = 0; i < count; i++)
504             {
505                 NSDictionary *o_dic;
506                 char *psz_uri = make_URI([[o_values objectAtIndex:i] UTF8String], NULL);
507                 if( !psz_uri )
508                     continue;
509
510                 o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
511                 free( psz_uri );
512
513                 o_array = [o_array arrayByAddingObject: o_dic];
514             }
515             if( b_autoplay )
516                 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
517             else
518                 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
519             return YES;
520         }
521     }
522     [self setNeedsDisplay:YES];
523     return YES;
524 }
525
526 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
527 {
528     [self setNeedsDisplay:YES];
529 }
530
531 @end
532
533
534 /*****************************************************************************
535  * MPSlider
536  *****************************************************************************/
537 @implementation MPSlider
538
539 void _drawKnobInRect(NSRect knobRect)
540 {
541     // Center knob in given rect
542     knobRect.origin.x += (int)((float)(knobRect.size.width - 7)/2.0);
543     knobRect.origin.y += (int)((float)(knobRect.size.height - 7)/2.0);
544
545     // Draw diamond
546     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 6, 1, 1), NSCompositeSourceOver);
547     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 5, 3, 1), NSCompositeSourceOver);
548     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 4, 5, 1), NSCompositeSourceOver);
549     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 0, knobRect.origin.y + 3, 7, 1), NSCompositeSourceOver);
550     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 1, knobRect.origin.y + 2, 5, 1), NSCompositeSourceOver);
551     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 2, knobRect.origin.y + 1, 3, 1), NSCompositeSourceOver);
552     NSRectFillUsingOperation(NSMakeRect(knobRect.origin.x + 3, knobRect.origin.y + 0, 1, 1), NSCompositeSourceOver);
553 }
554
555 void _drawFrameInRect(NSRect frameRect)
556 {
557     // Draw frame
558     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, 1), NSCompositeSourceOver);
559     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y + frameRect.size.height-1, frameRect.size.width, 1), NSCompositeSourceOver);
560     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver);
561     NSRectFillUsingOperation(NSMakeRect(frameRect.origin.x+frameRect.size.width-1, frameRect.origin.y, 1, frameRect.size.height), NSCompositeSourceOver);
562 }
563
564 - (void)drawRect:(NSRect)rect
565 {
566     // Draw default to make sure the slider behaves correctly
567     [[NSGraphicsContext currentContext] saveGraphicsState];
568     NSRectClip(NSZeroRect);
569     [super drawRect:rect];
570     [[NSGraphicsContext currentContext] restoreGraphicsState];
571
572     // Full size
573     rect = [self bounds];
574     int diff = (int)(([[self cell] knobThickness] - 7.0)/2.0) - 1;
575     rect.origin.x += diff-1;
576     rect.origin.y += diff;
577     rect.size.width -= 2*diff-2;
578     rect.size.height -= 2*diff;
579
580     // Draw dark
581     NSRect knobRect = [[self cell] knobRectFlipped:NO];
582     [[[NSColor blackColor] colorWithAlphaComponent:0.6] set];
583     _drawFrameInRect(rect);
584     _drawKnobInRect(knobRect);
585
586     // Draw shadow
587     [[[NSColor blackColor] colorWithAlphaComponent:0.1] set];
588     rect.origin.x++;
589     rect.origin.y++;
590     knobRect.origin.x++;
591     knobRect.origin.y++;
592     _drawFrameInRect(rect);
593     _drawKnobInRect(knobRect);
594 }
595
596 @end
597
598 /*****************************************************************************
599  * TimeLineSlider
600  *****************************************************************************/
601
602 @implementation TimeLineSlider
603
604 - (void)drawKnobInRect:(NSRect)knobRect
605 {
606     NSRect image_rect;
607     NSImage *img = [NSImage imageNamed:@"progression-knob"];
608     image_rect.size = [img size];
609     image_rect.origin.x = 0;
610     image_rect.origin.y = 0;
611     knobRect.origin.x += (knobRect.size.width - image_rect.size.width) / 2;
612     knobRect.size.width = image_rect.size.width;
613     knobRect.size.height = image_rect.size.height;
614     [img drawInRect:knobRect fromRect:image_rect operation:NSCompositeSourceOver fraction:1];
615 }
616
617 - (void)drawRect:(NSRect)rect
618 {
619     /* Draw default to make sure the slider behaves correctly */
620     [[NSGraphicsContext currentContext] saveGraphicsState];
621     NSRectClip(NSZeroRect);
622     [super drawRect:rect];
623     [[NSGraphicsContext currentContext] restoreGraphicsState];
624
625     NSRect knobRect = [[self cell] knobRectFlipped:NO];
626     knobRect.origin.y+=1;
627     [self drawKnobInRect: knobRect];
628 }
629
630 @end
631
632 /*****************************************************************************
633  * ITSlider
634  *****************************************************************************/
635
636 @implementation ITSlider
637
638 - (void)drawKnobInRect:(NSRect)knobRect
639 {
640     NSRect image_rect;
641     NSImage *img = [NSImage imageNamed:@"volume-slider-knob"];
642     image_rect.size = [img size];
643     image_rect.origin.x = 0;
644     image_rect.origin.y = 0;
645     knobRect.origin.x += (knobRect.size.width - image_rect.size.width) / 2;
646     knobRect.size.width = image_rect.size.width;
647     knobRect.size.height = image_rect.size.height;
648     [img drawInRect:knobRect fromRect:image_rect operation:NSCompositeSourceOver fraction:1];
649 }
650
651 - (void)drawRect:(NSRect)rect
652 {
653     /* Draw default to make sure the slider behaves correctly */
654     [[NSGraphicsContext currentContext] saveGraphicsState];
655     NSRectClip(NSZeroRect);
656     [super drawRect:rect];
657     [[NSGraphicsContext currentContext] restoreGraphicsState];
658
659     NSRect knobRect = [[self cell] knobRectFlipped:NO];
660     knobRect.origin.y+=2;
661     [self drawKnobInRect: knobRect];
662 }
663
664 @end
665
666 /*****************************************************************************
667  * VLCTimeField implementation
668  *****************************************************************************
669  * we need this to catch our click-event in the controller window
670  *****************************************************************************/
671
672 @implementation VLCTimeField
673 + (void)initialize{
674     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
675     NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"NO" forKey:@"DisplayTimeAsTimeRemaining"];
676
677     [defaults registerDefaults:appDefaults];
678 }
679
680 - (void)mouseDown: (NSEvent *)ourEvent
681 {
682     if( [ourEvent clickCount] > 1 )
683         [[[VLCMain sharedInstance] controls] goToSpecificTime: nil];
684     else
685     {
686         if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayTimeAsTimeRemaining"])
687             [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"DisplayTimeAsTimeRemaining"];
688         else
689             [[NSUserDefaults standardUserDefaults] setObject:@"YES" forKey:@"DisplayTimeAsTimeRemaining"];
690     }
691 }
692
693 - (BOOL)timeRemaining
694 {
695     return [[NSUserDefaults standardUserDefaults] boolForKey:@"DisplayTimeAsTimeRemaining"];
696 }
697 @end
698
699 /*****************************************************************************
700  * VLCMainWindowSplitView implementation
701  * comment 1 + 2 taken from NSSplitView.h (10.7 SDK)
702  *****************************************************************************/
703 @implementation VLCMainWindowSplitView : NSSplitView
704 /* 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.
705  */
706 - (NSColor *)dividerColor
707 {
708     return [NSColor colorWithCalibratedRed:.60 green:.60 blue:.60 alpha:1.];
709 }
710
711 /* 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.
712  */
713 - (CGFloat)dividerThickness
714 {
715     return 1.0;
716 }
717
718 - (void)adjustSubviews
719 {
720     NSArray *o_subviews = [self subviews];
721     NSRect viewDimensions = [self frame];
722     NSRect leftViewDimensions = [[o_subviews objectAtIndex:0] frame];
723     NSRect rightViewDimensions = [[o_subviews objectAtIndex:1] frame];
724     CGFloat f_dividerThickness = [self dividerThickness];
725
726     leftViewDimensions.size.height = viewDimensions.size.height;
727     [[o_subviews objectAtIndex:0] setFrame: leftViewDimensions];
728
729     rightViewDimensions.origin.x = leftViewDimensions.size.width + f_dividerThickness;
730     rightViewDimensions.size.width = viewDimensions.size.width - leftViewDimensions.size.width - f_dividerThickness;
731     rightViewDimensions.size.height = viewDimensions.size.height;
732     [[o_subviews objectAtIndex:1] setFrame: rightViewDimensions];
733 }
734 @end