macosx: merge Eric Dudiak's code from GSoC 2008
authorFelix Paul Kühne <fkuehne@videolan.org>
Thu, 21 May 2009 20:25:37 +0000 (22:25 +0200)
committerFelix Paul Kühne <fkuehne@videolan.org>
Thu, 21 May 2009 20:26:47 +0000 (22:26 +0200)
Nibs will be added later on. No user-visible change as of yet.

16 files changed:
NEWS
THANKS
modules/gui/macosx/controls.h
modules/gui/macosx/controls.m
modules/gui/macosx/embeddedwindow.h
modules/gui/macosx/embeddedwindow.m
modules/gui/macosx/equalizer.h
modules/gui/macosx/equalizer.m
modules/gui/macosx/intf.h
modules/gui/macosx/intf.m
modules/gui/macosx/playlist.h
modules/gui/macosx/playlist.m
modules/gui/macosx/sidebarview.h [new file with mode: 0644]
modules/gui/macosx/sidebarview.m [new file with mode: 0644]
modules/gui/macosx/sidestatusview.h [new file with mode: 0644]
modules/gui/macosx/sidestatusview.m [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 4ec556f..433a682 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,9 @@
 Changes between 1.0.0-rc1 and 1.1.0-git:
 ----------------------------------------
 
+Mac OS X Interface:
+ * Completely reworked user interface (based upon works from GSoC 2008)
+
 
 Changes between 0.9.9a and 1.0.0-rc1:
 ------------------------------------
diff --git a/THANKS b/THANKS
index fedc885..1a36daf 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -93,6 +93,7 @@ Dugal Harris - DirectShow fixes and MJPEG patches
 Dylan Aïssi <aissi dot dylan at free dot fr> - French translation
 Dylan Yudaken <dyudaken -- gmail # com> - hotkeys patch
 Emmanuel Blindauer <manu at agat.net> - aRts audio output
+Eric Dudiak <dudiak at gmail dot com> - Mac OS X Interface rework (GSoC 2008)
 Enrico Gueli <e_gueli at yahoo.it> - Brightness threshold in adjust video filter
 Enrique Osuna <enrique.osuna at gmail.com> - Various bug fixes in libvlc. Major Mac OS X Framework improvements.
 Eren Türkay <turkay dot eren \a/ gmail point com> - Speex boundary checks and security fix
index bd123bd..b6c1509 100644 (file)
@@ -38,6 +38,8 @@
     IBOutlet id o_btn_shuffle;
     IBOutlet id o_btn_addNode;
     IBOutlet id o_btn_repeat;
+    IBOutlet id o_btn_repeat_embed;
+    IBOutlet id o_btn_shuffle_embed;
     
     NSImage * o_repeat_single;
     NSImage * o_repeat_all;
 
 @end
 
+/*****************************************************************************
+ * VLCAutoGeneratedMenuContent interface
+ *****************************************************************************
+ * This holds our data for autogenerated menus
+ *****************************************************************************/
+@interface VLCAutoGeneratedMenuContent : NSObject
+{
+    char *psz_name;
+    vlc_object_t * _vlc_object;
+    vlc_value_t value;
+    int i_type;
+}
+
+- (id)initWithVariableName: (const char *)name 
+                  ofObject: (vlc_object_t *)object
+                  andValue: (vlc_value_t)value 
+                    ofType: (int)type;
+- (const char *)name;
+- (vlc_value_t)value;
+- (vlc_object_t *)vlcObject;
+- (int)type;
+
+@end
+
 /*****************************************************************************
  * VLCTimeField interface
  *****************************************************************************
index 88a6b00..b0aea74 100644 (file)
 #include <vlc_osd.h>
 #include <vlc_keys.h>
 
-/*****************************************************************************
- * VLCAutoGeneratedMenuContent interface
- *****************************************************************************
- * This holds our data for autogenerated menus
- *****************************************************************************/
-@interface VLCAutoGeneratedMenuContent : NSObject
-{
-    char *psz_name;
-    vlc_object_t * _vlc_object;
-    vlc_value_t value;
-    int i_type;
-}
-
-- (id)initWithVariableName: (const char *)name 
-           ofObject: (vlc_object_t *)object
-           andValue: (vlc_value_t)value 
-           ofType: (int)type;
-- (const char *)name;
-- (vlc_value_t)value;
-- (vlc_object_t *)vlcObject;
-- (int)type;
-
-@end
-
 #pragma mark -
 /*****************************************************************************
  * VLCControls implementation
 
 - (id)voutView
 {
-    id window;
-    id voutView = nil;
-    id embeddedViewList = [[VLCMain sharedInstance] embeddedList];
-    NSEnumerator *enumerator = [[NSApp orderedWindows] objectEnumerator];
-    while( !voutView && ( window = [enumerator nextObject] ) )
+    id o_window;
+    id o_voutView = nil;
+    id o_embeddedViewList = [[VLCMain sharedInstance] embeddedList];
+    NSEnumerator *o_enumerator = [[NSApp orderedWindows] objectEnumerator];
+    while( !o_voutView && ( o_window = [o_enumerator nextObject] ) )
     {
         /* We have an embedded vout */
-        if( [embeddedViewList windowContainsEmbedded: window] )
+        if( [o_embeddedViewList windowContainsEmbedded: o_window] )
         {
-            voutView = [embeddedViewList viewForWindow: window];
+            o_voutView = [o_embeddedViewList viewForWindow: o_window];
         }
         /* We have a detached vout */
-        else if( [[window className] isEqualToString: @"VLCVoutWindow"] )
+        else if( [[o_window className] isEqualToString: @"VLCVoutWindow"] )
         {
-            voutView = [window voutView];
+            o_voutView = [o_window voutView];
         }
     }
-    return [[voutView retain] autorelease];
+    return [[o_voutView retain] autorelease];
 }
 
 - (IBAction)stop:(id)sender
 {
     [o_btn_repeat setImage: o_repeat_single];
     [o_btn_repeat setAlternateImage: o_repeat_all];
+    [o_btn_repeat_embed setImage: [NSImage imageNamed:@"sidebarRepeatOneOn"]];
 }
 - (void)repeatAll
 {
     [o_btn_repeat setImage: o_repeat_all];
     [o_btn_repeat setAlternateImage: o_repeat_off];
+    [o_btn_repeat_embed setImage: [NSImage imageNamed:@"sidebarRepeatOn"]];
 }
 - (void)repeatOff
 {
     [o_btn_repeat setImage: o_repeat_off];
     [o_btn_repeat setAlternateImage: o_repeat_single];
+    [o_btn_repeat_embed setImage: [NSImage imageNamed:@"sidebarRepeat"]];
 }
 - (void)shuffle
 {
     playlist_t *p_playlist = pl_Hold( VLCIntf );
     var_Get( p_playlist, "random", &val );
     [o_btn_shuffle setState: val.b_bool];
+       if(val.b_bool)
+        [o_btn_shuffle_embed setImage: [NSImage imageNamed:@"sidebarShuffleOn"]];
+       else
+        [o_btn_shuffle_embed setImage: [NSImage imageNamed:@"sidebarShuffle"]];    
     pl_Release( VLCIntf );
 }
 
index ead8618..1a500a6 100644 (file)
     IBOutlet id o_btn_backward;
     IBOutlet id o_btn_forward;
     IBOutlet id o_btn_fullscreen;
+    IBOutlet id o_btn_equalizer;
+    IBOutlet id o_btn_playlist;
     IBOutlet id o_btn_play;
-    IBOutlet id o_slider;
+    IBOutlet id o_btn_prev;
+    IBOutlet id o_btn_stop;
+    IBOutlet id o_btn_next;
+    IBOutlet id o_btn_volume_down;
+    IBOutlet id o_volumeslider;
+    IBOutlet id o_btn_volume_up;
+    IBOutlet id o_timeslider;
+    IBOutlet id o_main_pgbar;
     IBOutlet id o_time;
+    IBOutlet id o_scrollfield;
+    IBOutlet id o_horizontal_split;
+    IBOutlet id o_vertical_split;
+    IBOutlet id o_videosubview;
+    IBOutlet id o_sidebar_list;
     IBOutlet id o_view;
+    IBOutlet id o_background_view;
+       IBOutlet id o_searchfield;
+       IBOutlet id o_status;
+       IBOutlet id o_playlist;
+       IBOutlet id o_playlist_view;
+       IBOutlet id o_playlist_table;
+       IBOutlet id o_vlc_main;
 
     NSImage * o_img_play;
     NSImage * o_img_play_pressed;
     BOOL              b_window_is_invisible;
 
     NSSize videoRatio;
-    int originalLevel;
+    NSInteger originalLevel;
 }
 
 - (void)controlTintChanged;
 
 - (void)setTime: (NSString *)o_arg_ime position: (float)f_position;
+- (id)getPgbar;
 - (void)playStatusUpdated: (int)i_status;
 - (void)setSeekable: (BOOL)b_seekable;
+- (void)setStop:(BOOL)b_input;
+- (void)setPrev:(BOOL)b_input;
+- (void)setNext:(BOOL)b_input;
+- (void)setVolumeEnabled:(BOOL)b_input;
+
+- (void)setScrollString:(NSString *)o_string;
+
+- (void)setVolumeSlider:(float)f_level;
 
 - (void)setVideoRatio:(NSSize)ratio;
 
 - (NSView *)mainView;
 
+- (IBAction)togglePlaylist:(id)sender;
+
 - (BOOL)isFullscreen;
 
 - (void)lockFullscreenAnimation;
 - (void)setFrameOnMainThread:(NSData*)packedargs;
 @end
 
+/*****************************************************************************
+ * embeddedbackground
+ *****************************************************************************/
+
+
+@interface embeddedbackground : NSView
+{
+    IBOutlet id o_window;
+    IBOutlet id o_timeslider;
+    IBOutlet id o_main_pgbar;
+    IBOutlet id o_time;
+    IBOutlet id o_scrollfield;
+    IBOutlet id o_searchfield;
+    IBOutlet id o_btn_backward;
+    IBOutlet id o_btn_forward;
+    IBOutlet id o_btn_fullscreen;
+    IBOutlet id o_btn_equalizer;
+    IBOutlet id o_btn_playlist;
+    IBOutlet id o_btn_play;
+    IBOutlet id o_btn_prev;
+    IBOutlet id o_btn_stop;
+    IBOutlet id o_btn_next;
+    IBOutlet id o_btn_volume_down;
+    IBOutlet id o_volumeslider;
+    IBOutlet id o_btn_volume_up;
+    
+    NSPoint dragStart;
+}
+
+@end
+
+/*****************************************************************************
+ * statusbar
+ *****************************************************************************/
+
+
+@interface statusbar : NSView
+{
+    IBOutlet id o_text;
+       
+       BOOL mainwindow;
+}
+
+@end
\ No newline at end of file
index b59ccf9..3392fd1 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * embeddedwindow.m: MacOS X interface module
  *****************************************************************************
- * Copyright (C) 2005-2009 the VideoLAN team
+ * Copyright (C) 2005-2008 the VideoLAN team
  * $Id$
  *
  * Authors: Benjamin Pracht <bigben at videolan dot org>
  * Preamble
  *****************************************************************************/
 
+/* DisableScreenUpdates, SetSystemUIMode, ... */
+#import <QuickTime/QuickTime.h>
+
 #import "intf.h"
 #import "controls.h"
 #import "vout.h"
 #import "embeddedwindow.h"
 #import "fspanel.h"
+#import "playlist.h"
 
-/* SetSystemUIMode, ... */
-#import <Carbon/Carbon.h>
+/*****************************************************************************
+ * extension to NSWindow's interface to fix compilation warnings
+ * and let us access this functions properly
+ * this uses a private Apple-API, but works fine on all current OSX releases
+ * keep checking for compatiblity with future releases though
+ *****************************************************************************/
+
+@interface NSWindow (UndocumentedWindowProperties)
+- (void)setBottomCornerRounded: (BOOL)value;
+@end
 
 /*****************************************************************************
  * VLCEmbeddedWindow Implementation
 
 @implementation VLCEmbeddedWindow
 
-- (id)initWithContentRect:(NSRect)contentRect styleMask: (NSUInteger)windowStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation
-{
-    BOOL b_useTextured = YES;
-    if( [[NSWindow class] instancesRespondToSelector:@selector(setContentBorderThickness:forEdge:)] )
-    {
-        b_useTextured = NO;
-        windowStyle ^= NSTexturedBackgroundWindowMask;
-    }
-    self = [super initWithContentRect:contentRect styleMask:windowStyle backing:bufferingType defer:deferCreation];
-    if(! b_useTextured )
-    {
-        [self setContentBorderThickness:28.0 forEdge:NSMinYEdge];
-    }
-    return self;
-}
-
 - (void)awakeFromNib
 {
     [self setDelegate: self];
+    [self setBottomCornerRounded:NO];
 
+    /* button strings */
     [o_btn_backward setToolTip: _NS("Rewind")];
     [o_btn_forward setToolTip: _NS("Fast Forward")];
     [o_btn_fullscreen setToolTip: _NS("Fullscreen")];
     [o_btn_play setToolTip: _NS("Play")];
-    [o_slider setToolTip: _NS("Position")];
-
-    o_img_play = [NSImage imageNamed: @"play_embedded"];
-    o_img_pause = [NSImage imageNamed: @"pause_embedded"];
+    [o_timeslider setToolTip: _NS("Position")];
+    [o_btn_prev setToolTip: _NS("Previous")];
+    [o_btn_stop setToolTip: _NS("Stop")];
+    [o_btn_next setToolTip: _NS("Next")];
+    [o_volumeslider setToolTip: _NS("Volume")];
+    [o_btn_playlist setToolTip: _NS("Playlist")];
+    [self setTitle: _NS("VLC media player")];
+
+    if(MACOS_VERSION < 10.5f) {
+        o_img_play = [NSImage imageNamed: @"play"];
+        o_img_pause = [NSImage imageNamed: @"pause"];
+        [o_btn_play setImage: [NSImage imageNamed: @"play"]];
+    }
+    else {
+        o_img_play = [NSImage imageNamed: @"play_big"];
+        o_img_pause = [NSImage imageNamed: @"pause_big"];
+    }
     [self controlTintChanged];
     [[NSNotificationCenter defaultCenter] addObserver: self
                                              selector: @selector( controlTintChanged )
                                                  name: NSControlTintDidChangeNotification
                                                object: nil];
 
+    /* Set color of sidebar to Leopard's "Sidebar Blue" */
+    [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedRed:0.820
+                                                                  green:0.843
+                                                                   blue:0.886
+                                                                  alpha:1.0]];
+    
+    [self setMinSize:NSMakeSize([o_sidebar_list convertRect:[o_sidebar_list bounds]
+                                                     toView: nil].size.width + 551., 114.)];
+
     /* Useful to save o_view frame in fullscreen mode */
     o_temp_view = [[NSView alloc] init];
     [o_temp_view setAutoresizingMask:NSViewHeightSizable | NSViewWidthSizable];
     [o_btn_fullscreen setState: NO];
     b_fullscreen = NO;
 
-    [self setMovableByWindowBackground:YES];
-
-    [self setDelegate:self];
-
     /* Make sure setVisible: returns NO */
     [self orderOut:self];
-    b_window_is_invisible = YES;
+    //b_window_is_invisible = YES;
     videoRatio = NSMakeSize( 0., 0. );
 }
 
     if( [o_btn_play alternateImage] == o_img_play_pressed )
         b_playing = YES;
     
-    if( [NSColor currentControlTint] == NSGraphiteControlTint )
-    {
-        o_img_play_pressed = [NSImage imageNamed: @"play_embedded_graphite"];
-        o_img_pause_pressed = [NSImage imageNamed: @"pause_embedded_graphite"];
-        [o_btn_backward setAlternateImage: [NSImage imageNamed: @"skip_previous_embedded_graphite"]];
-        [o_btn_forward setAlternateImage: [NSImage imageNamed: @"skip_forward_embedded_graphite"]];
-        [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_graphite"]];
+    if (MACOS_VERSION < 10.5f) {
+        /* System is running Tiger and should use aqua buttons */
+        [o_btn_backward setImage: [NSImage imageNamed: @"skip_previous_active"]];
+        [o_btn_forward setImage: [NSImage imageNamed: @"skip_forward_active"]];
+        if( [NSColor currentControlTint] == NSGraphiteControlTint )
+        {
+            o_img_play_pressed = [NSImage imageNamed: @"play_graphite"];
+            o_img_pause_pressed = [NSImage imageNamed: @"pause_graphite"];
+            [o_btn_backward setAlternateImage: [NSImage imageNamed: @"skip_previous_graphite"]];
+            [o_btn_forward setAlternateImage: [NSImage imageNamed: @"skip_forward_graphite"]];
+        }
+        else
+        {
+            o_img_play_pressed = [NSImage imageNamed: @"play_blue"];
+            o_img_pause_pressed = [NSImage imageNamed: @"pause_blue"];
+            [o_btn_backward setAlternateImage: [NSImage imageNamed: @"skip_previous_blue"]];
+            [o_btn_forward setAlternateImage: [NSImage imageNamed: @"skip_forward_blue"]];
+        }
     }
-    else
-    {
-        o_img_play_pressed = [NSImage imageNamed: @"play_embedded_blue"];
-        o_img_pause_pressed = [NSImage imageNamed: @"pause_embedded_blue"];
-        [o_btn_backward setAlternateImage: [NSImage imageNamed: @"skip_previous_embedded_blue"]];
-        [o_btn_forward setAlternateImage: [NSImage imageNamed: @"skip_forward_embedded_blue"]];
-        [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_blue"]];
+    else{
+        /* System is running Leopard or later and should use metal buttons */
+        o_img_play_pressed = [NSImage imageNamed: @"play_big_down"];
+        o_img_pause_pressed = [NSImage imageNamed: @"pause_big_down"];
     }
     
     if( b_playing )
 - (void)setTime:(NSString *)o_arg_time position:(float)f_position
 {
     [o_time setStringValue: o_arg_time];
-    [o_slider setFloatValue: f_position];
+    [o_timeslider setFloatValue: f_position];
 }
 
 - (void)playStatusUpdated:(int)i_status
 {
     [o_btn_forward setEnabled: b_seekable];
     [o_btn_backward setEnabled: b_seekable];
-    [o_slider setEnabled: b_seekable];
+    [o_timeslider setEnabled: b_seekable];
+}
+
+- (void)setScrollString:(NSString *)o_string
+{
+    [o_scrollfield setStringValue: o_string];
+}
+
+- (id)getPgbar
+{
+    if( o_main_pgbar )
+        return o_main_pgbar;
+    
+    return nil;
+}
+
+- (void)setStop:(BOOL)b_input
+{
+    [o_btn_stop setEnabled: b_input];
+}
+
+- (void)setNext:(BOOL)b_input
+{
+    [o_btn_next setEnabled: b_input];
+}
+
+- (void)setPrev:(BOOL)b_input
+{
+    [o_btn_prev setEnabled: b_input];
+}
+
+- (void)setVolumeEnabled:(BOOL)b_input
+{
+    [o_volumeslider setEnabled: b_input];
+}
+
+- (void)setVolumeSlider:(float)f_level
+{
+    [o_volumeslider setFloatValue: f_level];
 }
 
 - (BOOL)windowShouldZoom:(NSWindow *)sender toFrame:(NSRect)newFrame
 {
     playlist_t * p_playlist = pl_Hold( VLCIntf );
 
-    playlist_Stop( p_playlist );
+    /* Only want to stop playback if video is playing */
+    if( videoRatio.height != 0. && videoRatio.width != 0. )
+        playlist_Stop( p_playlist );
     pl_Release( VLCIntf );
     return YES;
 }
 
 - (NSSize)windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize
 {
+       NSView *playlist_area = [[o_vertical_split subviews] objectAtIndex:1];
+       NSRect newList = [playlist_area frame];
+       if( newList.size.height < 50 && newList.size.height > 0 ) {
+               [self togglePlaylist:self];
+       }
+    
+    /* With no video open or with the playlist open the behavior is odd */    
+    if( newList.size.height > 50 )
+        return proposedFrameSize;
+       
     if( videoRatio.height == 0. || videoRatio.width == 0. )
         return proposedFrameSize;
 
     NSRect contentRect = [self contentRectForFrameRect:[self frame]];
     float marginy = viewRect.origin.y + [self frame].size.height - contentRect.size.height;
     float marginx = contentRect.size.width - viewRect.size.width;
+
     proposedFrameSize.height = (proposedFrameSize.width - marginx) * videoRatio.height / videoRatio.width + marginy;
 
     return proposedFrameSize;
 }
 
+- (void)becomeMainWindow
+{
+    [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedRed:0.820
+                                                                  green:0.843
+                                                                   blue:0.886
+                                                                  alpha:1.0]];
+       [o_status becomeMainWindow];
+    [super becomeMainWindow];
+}
+
+- (void)resignMainWindow
+{
+    [o_sidebar_list setBackgroundColor: [NSColor colorWithCalibratedWhite:0.91 alpha:1.0]];
+       [o_status resignMainWindow];
+    [super resignMainWindow];
+}
+
+- (float)splitView:(NSSplitView *) splitView constrainSplitPosition:(float) proposedPosition ofSubviewAt:(int) index
+{
+       if([splitView isVertical])
+               return proposedPosition;
+       else {
+               float bottom = [splitView frame].size.height - [splitView dividerThickness];
+               if(proposedPosition > bottom - 50) {
+                       [o_btn_playlist setState: NSOffState];
+                       [o_searchfield setHidden:YES];
+                       [o_playlist_view setHidden:YES];
+                       return bottom;
+               }
+               else {
+                       [o_btn_playlist setState: NSOnState];
+                       [o_searchfield setHidden:NO];
+                       [o_playlist_view setHidden:NO];
+                       [o_playlist swapPlaylists: o_playlist_table];
+                       [o_vlc_main togglePlaylist:self];
+                       return proposedPosition;
+               }
+       }
+}
+
+- (void)splitViewWillResizeSubviews:(NSNotification *) notification
+{
+
+}
+
+- (float)splitView:(NSSplitView *) splitView constrainMinCoordinate:(float) proposedMin ofSubviewAt:(int) offset
+{
+       if([splitView isVertical])
+               return 125.;
+       else
+               return 0.;
+}
+
+- (float)splitView:(NSSplitView *) splitView constrainMaxCoordinate:(float) proposedMax ofSubviewAt:(int) offset
+{
+    if([splitView isVertical])
+               return MIN([self frame].size.width - 551, 300);
+       else
+               return [splitView frame].size.height;
+}
+
+- (BOOL)splitView:(NSSplitView *) splitView canCollapseSubview:(NSView *) subview
+{
+       if([splitView isVertical])
+               return NO;
+       else
+               return NO;
+}
+
+- (NSRect)splitView:(NSSplitView *)splitView effectiveRect:(NSRect)proposedEffectiveRect forDrawnRect:(NSRect)drawnRect
+   ofDividerAtIndex:(NSInteger)dividerIndex
+{
+       if([splitView isVertical]) {
+               drawnRect.origin.x -= 3;
+               drawnRect.size.width += 5;
+               return drawnRect;
+       }
+       else
+               return drawnRect;
+}
+
+- (IBAction)togglePlaylist:(id)sender
+{
+       NSView *playback_area = [[o_vertical_split subviews] objectAtIndex:0];
+       NSView *playlist_area = [[o_vertical_split subviews] objectAtIndex:1];
+       NSRect newVid = [playback_area frame];
+       NSRect newList = [playlist_area frame];
+       if(newList.size.height < 50 && sender != self && sender != o_vlc_main) {
+               newList.size.height = newVid.size.height/2;
+               newVid.size.height = newVid.size.height/2;
+               newVid.origin.y = newVid.origin.y + newList.size.height;
+               [o_btn_playlist setState: NSOnState];
+               [o_searchfield setHidden:NO];
+               [o_playlist_view setHidden:NO];
+               [o_playlist swapPlaylists: o_playlist_table];
+               [o_vlc_main togglePlaylist:self];
+       }
+       else {
+               newVid.size.height = newVid.size.height + newList.size.height;
+               newList.size.height = 0;
+               newVid.origin.y = 0;
+               [o_btn_playlist setState: NSOffState];
+               [o_searchfield setHidden:YES];
+               [o_playlist_view setHidden:YES];
+       }
+       [playback_area setFrame: newVid];
+       [playlist_area setFrame: newList];
+}
+
 /*****************************************************************************
  * Fullscreen support
  */
         [o_fullscreen_window setBackgroundColor: [NSColor blackColor]];
         [o_fullscreen_window setCanBecomeKeyWindow: YES];
 
-        if (![self isVisible] || [self alphaValue] == 0.0)
+        if (![self isVisible] || [self alphaValue] == 0.0 || MACOS_VERSION < 10.4f)
         {
-            /* We don't animate if we are not visible, instead we
+            /* We don't animate if we are not visible or if we are running on
+             * Mac OS X <10.4 which doesn't support NSAnimation, instead we
              * simply fade the display */
             CGDisplayFadeReservationToken token;
  
             [o_temp_view setFrame:[o_view frame]];
             [o_fullscreen_window setContentView:o_view];
 
+            [o_fullscreen_window makeKeyAndOrderFront:self];
+
             [o_fullscreen_window makeKeyAndOrderFront:self];
             [o_fullscreen_window orderFront:self animate:YES];
 
         }
  
         /* Make sure we don't see the o_view disappearing of the screen during this operation */
-        NSDisableScreenUpdates();
-               [[self contentView] replaceSubview:o_view with:o_temp_view];
+        DisableScreenUpdates();
+        [[self contentView] replaceSubview:o_view with:o_temp_view];
         [o_temp_view setFrame:[o_view frame]];
         [o_fullscreen_window setContentView:o_view];
         [o_fullscreen_window makeKeyAndOrderFront:self];
-        NSEnableScreenUpdates();
+        EnableScreenUpdates();
+    }
+
+    if (MACOS_VERSION < 10.4f)
+    {
+        /* We were already fullscreen nothing to do when NSAnimation
+         * is not supported */
+        [self unlockFullscreenAnimation];
+        return;
     }
 
     /* We are in fullscreen (and no animation is running) */
         return;
     }
 
-    if (fadeout)
+    if (fadeout || MACOS_VERSION < 10.4f)
     {
-        /* We don't animate if we are not visible, instead we
+        /* We don't animate if we are not visible or if we are running on
+        * Mac OS X <10.4 which doesn't support NSAnimation, instead we
         * simply fade the display */
         CGDisplayFadeReservationToken token;
 
 {
     /* This function is private and should be only triggered at the end of the fullscreen change animation */
     /* Make sure we don't see the o_view disappearing of the screen during this operation */
-    NSDisableScreenUpdates();
+    DisableScreenUpdates();
     [o_view retain];
     [o_view removeFromSuperviewWithoutNeedingDisplay];
     [[self contentView] replaceSubview:o_temp_view with:o_view];
     if ([self isVisible])
         [super makeKeyAndOrderFront:self]; /* our version contains a workaround */
     [o_fullscreen_window orderOut: self];
-    NSEnableScreenUpdates();
+    EnableScreenUpdates();
 
     [o_fullscreen_window release];
     o_fullscreen_window = nil;
 
 }
 @end
+
+/*****************************************************************************
+ * embeddedbackground
+ *****************************************************************************/
+
+
+@implementation embeddedbackground
+
+- (void)dealloc
+{
+    [self unregisterDraggedTypes];
+    [super dealloc];
+}
+
+- (void)awakeFromNib
+{
+    [self registerForDraggedTypes:[NSArray arrayWithObjects:NSTIFFPboardType,
+                                   NSFilenamesPboardType, nil]];
+    [self addSubview: o_timeslider];
+    [self addSubview: o_scrollfield];
+    [self addSubview: o_time];
+    [self addSubview: o_main_pgbar];
+    [self addSubview: o_btn_backward];
+    [self addSubview: o_btn_forward];
+    [self addSubview: o_btn_fullscreen];
+    [self addSubview: o_btn_equalizer];
+    [self addSubview: o_btn_playlist];
+    [self addSubview: o_btn_play];
+    [self addSubview: o_btn_prev];
+    [self addSubview: o_btn_stop];
+    [self addSubview: o_btn_next];
+    [self addSubview: o_btn_volume_down];
+    [self addSubview: o_volumeslider];
+    [self addSubview: o_btn_volume_up];
+    [self addSubview: o_searchfield];
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+    if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
+        == NSDragOperationGeneric)
+    {
+        return NSDragOperationGeneric;
+    }
+    else
+    {
+        return NSDragOperationNone;
+    }
+}
+
+- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
+{
+    return YES;
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+    NSPasteboard *o_paste = [sender draggingPasteboard];
+    NSArray *o_types = [NSArray arrayWithObjects: NSFilenamesPboardType, nil];
+    NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
+    NSData *o_carried_data = [o_paste dataForType:o_desired_type];
+    BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
+    
+    if( o_carried_data )
+    {
+        if ([o_desired_type isEqualToString:NSFilenamesPboardType])
+        {
+            int i;
+            NSArray *o_array = [NSArray array];
+            NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType]
+                                 sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
+            
+            for( i = 0; i < (int)[o_values count]; i++)
+            {
+                NSDictionary *o_dic;
+                o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"];
+                o_array = [o_array arrayByAddingObject: o_dic];
+            }
+            if( b_autoplay )
+                [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
+            else
+                [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
+            return YES;
+        }
+    }
+    [self setNeedsDisplay:YES];
+    return YES;
+}
+
+- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
+{
+    [self setNeedsDisplay:YES];
+}
+
+- (void)drawRect:(NSRect)rect
+{
+    NSImage *leftImage = [NSImage imageNamed:@"display_left"];
+    NSImage *middleImage = [NSImage imageNamed:@"display_middle"];
+    NSImage *rightImage = [NSImage imageNamed:@"display_right"];
+    [middleImage setSize:NSMakeSize(NSWidth( [self bounds] ) - 134 - [leftImage size].width - [rightImage size].width, [middleImage size].height)];
+    [middleImage setScalesWhenResized:YES];
+    [leftImage compositeToPoint:NSMakePoint( 122., 40. ) operation:NSCompositeSourceOver];
+    [middleImage compositeToPoint:NSMakePoint( 122. + [leftImage size].width, 40. ) operation:NSCompositeSourceOver];
+    [rightImage compositeToPoint:NSMakePoint( NSWidth( [self bounds] ) - 12 - [rightImage size].width, 40. ) operation:NSCompositeSourceOver];
+}
+
+- (void)mouseDown:(NSEvent *)event
+{
+    dragStart = [self convertPoint:[event locationInWindow] fromView:nil];
+}
+
+- (void)mouseDragged:(NSEvent *)event
+{
+    NSPoint dragLocation = [self convertPoint:[event locationInWindow] fromView:nil];
+    NSPoint winOrigin = [o_window frame].origin;
+
+    NSPoint newOrigin = NSMakePoint(winOrigin.x + (dragLocation.x - dragStart.x),
+                                    winOrigin.y + (dragLocation.y - dragStart.y));
+    [o_window setFrameOrigin: newOrigin];
+}
+
+@end
+
+/*****************************************************************************
+ * statusbar
+ *****************************************************************************/
+
+
+@implementation statusbar
+- (void)awakeFromNib
+{
+    [self addSubview: o_text];
+       mainwindow = YES;
+}
+
+- (void)resignMainWindow
+{
+       mainwindow = NO;
+       [self needsDisplay];
+}
+
+- (void)becomeMainWindow
+{
+       mainwindow = YES;
+       [self needsDisplay];
+}
+
+- (void)drawRect:(NSRect)rect
+{
+       if(mainwindow)
+               [[NSColor colorWithCalibratedRed:0.820
+                                                                  green:0.843
+                                                                       blue:0.886
+                                                                  alpha:1.0] set];
+       else
+               [[NSColor colorWithCalibratedWhite:0.91 alpha:1.0] set];
+       NSRectFill(rect);
+       /*NSRect divider = rect;
+       divider.origin.y += divider.size.height - 1;
+       divider.size.height = 1;
+       [[NSColor colorWithCalibratedWhite:0.65 alpha:1.] set];
+       NSRectFill(divider);*/
+}
+@end
index e736be4..2d59670 100644 (file)
@@ -27,6 +27,7 @@
 @interface VLCEqualizer : NSObject
 {
     IBOutlet id o_btn_equalizer;
+    IBOutlet id o_btn_equalizer_embedded;
     IBOutlet id o_ckb_2pass;
     IBOutlet id o_ckb_enable;
     IBOutlet id o_fld_preamp;
index 4f78770..367ff0b 100644 (file)
@@ -151,6 +151,7 @@ static bool GetFiltersStatus( intf_thread_t *p_intf,
 {
     int i;
     [o_btn_equalizer setToolTip: _NS("Equalizer")];
+    [o_btn_equalizer_embedded setToolTip: _NS("Equalizer")];
     [o_ckb_2pass setTitle: _NS("2 Pass")];
     [o_ckb_2pass setToolTip: _NS("Apply the "
         "equalizer filter twice. The effect will be sharper.")];
@@ -342,11 +343,13 @@ static bool GetFiltersStatus( intf_thread_t *p_intf,
     {
         [o_window orderOut:sender];
         [o_btn_equalizer setState:NSOffState];
+        [o_btn_equalizer_embedded setState:NSOffState];
     }
     else
     {
         [o_window makeKeyAndOrderFront:sender];
         [o_btn_equalizer setState:NSOnState];
+        [o_btn_equalizer_embedded setState:NSOnState];
     }
 }
 
index d983f82..5c56000 100644 (file)
@@ -274,6 +274,7 @@ struct intf_sys_t
     IBOutlet NSMenu * o_mu_window;
     IBOutlet NSMenuItem * o_mi_minimize;
     IBOutlet NSMenuItem * o_mi_close_window;
+    IBOutlet NSMenuItem * o_mi_player;
     IBOutlet NSMenuItem * o_mi_controller;
     IBOutlet NSMenuItem * o_mi_equalizer;
     IBOutlet NSMenuItem * o_mi_extended;
index ef0baaa..3124c48 100644 (file)
@@ -698,6 +698,7 @@ static VLCMain *_o_sharedMainInstance = nil;
     [o_mu_window setTitle: _NS("Window")];
     [o_mi_minimize setTitle: _NS("Minimize Window")];
     [o_mi_close_window setTitle: _NS("Close Window")];
+    [o_mi_player setTitle: _NS("Player...")];
     [o_mi_controller setTitle: _NS("Controller...")];
     [o_mi_equalizer setTitle: _NS("Equalizer...")];
     [o_mi_extended setTitle: _NS("Extended Controls...")];
@@ -1675,10 +1676,13 @@ static void manage_cleanup( void * args )
         }
 
         [o_btn_stop setEnabled: b_input];
+        [o_embedded_window setStop: b_input];
         [o_btn_ff setEnabled: b_seekable];
         [o_btn_rewind setEnabled: b_seekable];
         [o_btn_prev setEnabled: (b_plmul || b_chapters)];
+        [o_embedded_window setPrev: (b_plmul || b_chapters)];
         [o_btn_next setEnabled: (b_plmul || b_chapters)];
+        [o_embedded_window setNext: (b_plmul || b_chapters)];
 
         [o_timeslider setFloatValue: 0.0];
         [o_timeslider setEnabled: b_seekable];
@@ -1687,6 +1691,7 @@ static void manage_cleanup( void * args )
         [[[self controls] fspanel] setSeekable: b_seekable];
 
         [o_embedded_window setSeekable: b_seekable];
+        [o_embedded_window setTime:@"00:00" position:0.0];
 
         p_intf->p_sys->b_current_title_update = true;
         
@@ -1807,6 +1812,8 @@ static void manage_cleanup( void * args )
         i_volume_step = config_GetInt( p_intf->p_libvlc, "volume-step" );
         [o_volumeslider setFloatValue: (float)i_lastShownVolume / i_volume_step];
         [o_volumeslider setEnabled: TRUE];
+        [o_embedded_window setVolumeSlider: (float)i_lastShownVolume / i_volume_step];
+        [o_embedded_window setVolumeEnabled: TRUE];
         [[[self controls] fspanel] setVolumeLevel: (float)i_lastShownVolume / i_volume_step];
         p_intf->p_sys->b_mute = ( i_lastShownVolume == 0 );
         p_intf->p_sys->b_volume_update = FALSE;
index 02f291a..96cee08 100644 (file)
     IBOutlet id o_tc_duration;
     IBOutlet id o_outline_view;
 
+    IBOutlet id o_tc_name_other;
+    IBOutlet id o_tc_author_other;
+    IBOutlet id o_tc_duration_other;
+    IBOutlet id o_outline_view_other;
+
     NSMutableDictionary *o_outline_dict;
 }
 
 - (void)initStrings;
 - (playlist_item_t *)selectedPlaylistItem;
 - (NSOutlineView *)outlineView;
-
+- (void)swapPlaylists:(id)newList;
 @end
 
 /*****************************************************************************
 
     IBOutlet id o_btn_playlist;
     IBOutlet id o_playlist_view;
+    IBOutlet id o_sidebar;
     IBOutlet id o_status_field;
+    IBOutlet id o_status_field_embed;
     IBOutlet id o_search_field;
+    IBOutlet id o_search_field_other;
     IBOutlet id o_mi_save_playlist;
     IBOutlet id o_ctx_menu;
 
 
 - (IBAction)addNode:(id)sender;
 
+- (void)playSidebarItem:(id)item;
+- (id)playingItem;
+
 - (void)appendArray:(NSArray*)o_array atPos:(int)i_position enqueue:(BOOL)b_enqueue;
 - (void)appendNodeArray:(NSArray*)o_array inNode:(playlist_item_t *)p_node atPos:(int)i_position enqueue:(BOOL)b_enqueue;
 
index 269e513..54f548a 100644 (file)
@@ -49,6 +49,7 @@
 #import "controls.h"
 #import "vlc_osd.h"
 #import "misc.h"
+#import "sidebarview.h"
 #import <vlc_interface.h>
 #import <vlc_services_discovery.h>
 
     [o_outline_view setAllowsEmptySelection: NO];
     [o_outline_view expandItem: [o_outline_view itemAtRow:0]];
 
+       [o_outline_view_other setTarget: self];
+    [o_outline_view_other setDelegate: self];
+    [o_outline_view_other setDataSource: self];
+    [o_outline_view_other setAllowsEmptySelection: NO];
+
     pl_Release( VLCIntf );
     [self initStrings];
 }
     [[o_tc_name headerCell] setStringValue:_NS("Name")];
     [[o_tc_author headerCell] setStringValue:_NS("Author")];
     [[o_tc_duration headerCell] setStringValue:_NS("Duration")];
+
+       [[o_tc_name_other headerCell] setStringValue:_NS("Name")];
+    [[o_tc_author_other headerCell] setStringValue:_NS("Author")];
+    [[o_tc_duration_other headerCell] setStringValue:_NS("Duration")];
+}
+
+- (void)swapPlaylists:(id)newList
+{
+       if(newList != o_outline_view)
+       {
+               id o_outline_view_temp = o_outline_view;
+               id o_tc_author_temp = o_tc_author;
+               id o_tc_duration_temp = o_tc_duration;
+               id o_tc_name_temp = o_tc_name;
+               o_outline_view = o_outline_view_other;
+               o_tc_author = o_tc_author_other;
+               o_tc_duration = o_tc_duration_other;
+               o_tc_name = o_tc_name_other;
+               o_outline_view_other = o_outline_view_temp;
+               o_tc_author_other = o_tc_author_temp;
+               o_tc_duration_other = o_tc_duration_temp;
+               o_tc_name_other = o_tc_name_temp;
+       }
 }
 
 - (NSOutlineView *)outlineView
     [super awakeFromNib];
 
     [o_outline_view setDoubleAction: @selector(playItem:)];
+    [o_outline_view_other setDoubleAction: @selector(playItem:)];
 
     [o_outline_view registerForDraggedTypes:
         [NSArray arrayWithObjects: NSFilenamesPboardType,
         @"VLCPlaylistItemPboardType", nil]];
     [o_outline_view setIntercellSpacing: NSMakeSize (0.0, 1.0)];
 
+    [o_outline_view_other registerForDraggedTypes:
+     [NSArray arrayWithObjects: NSFilenamesPboardType,
+      @"VLCPlaylistItemPboardType", nil]];
+    [o_outline_view_other setIntercellSpacing: NSMakeSize (0.0, 1.0)];
+
     /* This uses private Apple API which works fine until 10.5.
      * We need to keep checking in the future!
      * These methods are being added artificially to NSOutlineView's interface above */
     [o_mi_services setTitle: _NS("Services discovery")];
     [o_mm_mi_services setTitle: _NS("Services discovery")];
     [o_status_field setStringValue: _NS("No items in the playlist")];
+    [o_status_field_embed setStringValue: _NS("No items in the playlist")];
 
     [o_search_field setToolTip: _NS("Search in Playlist")];
+    [o_search_field_other setToolTip: _NS("Search in Playlist")];
     [o_mi_addNode setTitle: _NS("Add Folder to Playlist")];
 
     [o_save_accessory_text setStringValue: _NS("File Format:")];
     [[o_save_accessory_popup itemAtIndex:2] setTitle: _NS("HTML Playlist")];
 }
 
+- (void)swapPlaylists:(id)newList
+{
+       if(newList != o_outline_view)
+       {
+               id o_search_field_temp = o_search_field;
+               o_search_field = o_search_field_other;
+               o_search_field_other = o_search_field_temp;
+               [super swapPlaylists:newList];
+               [self playlistUpdated];
+       }
+}
+
 - (void)playlistUpdated
 {
     /* Clear indications of any existing column sorting */
     // TODO Find a way to keep the dict size to a minimum
     //[o_outline_dict removeAllObjects];
     [o_outline_view reloadData];
+    [o_sidebar updateSidebar:[self playingItem]];
     [[[[VLCMain sharedInstance] wizard] playlistWizard] reloadOutlineView];
     [[[[VLCMain sharedInstance] bookmarks] dataTable] reloadData];
 
         [o_status_field setStringValue: [NSString stringWithFormat:
                     _NS("%i items"),
                 playlist_CurrentSize( p_playlist )]];
+        [o_status_field_embed setStringValue: [NSString stringWithFormat:
+                                               _NS("%i items"),
+                                               playlist_CurrentSize( p_playlist )]];        
     }
     else
     {
         if( playlist_IsEmpty( p_playlist ) )
+        {
             [o_status_field setStringValue: _NS("No items in the playlist")];
+            [o_status_field_embed setStringValue: _NS("No items in the playlist")];
+        }
         else
+        {
             [o_status_field setStringValue: _NS("1 item")];
+            [o_status_field_embed setStringValue: _NS("1 item")];
+        }
     }
     PL_UNLOCK;
     pl_Release( VLCIntf );
     pl_Release( p_intf );
 }
 
+- (void)playSidebarItem:(id)item
+{
+    intf_thread_t * p_intf = VLCIntf;
+    playlist_t * p_playlist = pl_Hold( p_intf );
+    
+    playlist_item_t *p_item;
+    playlist_item_t *p_node = NULL;
+    
+    p_item = [item pointerValue];
+    
+    if( p_item )
+    {
+        if( p_item->i_children == -1 )
+        {
+            p_node = p_item->p_parent;
+            
+        }
+        else
+        {
+            p_node = p_item;
+            if( p_node->i_children > 0 && p_node->pp_children[0]->i_children == -1 )
+            {
+                p_item = p_node->pp_children[0];
+            }
+            else
+            {
+                p_item = NULL;
+            }
+        }
+        playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, pl_Unlocked, p_node, p_item );
+    }
+    pl_Release( p_intf );
+}
+
 - (IBAction)revealItemInFinder:(id)sender
 {
     playlist_item_t * p_item = [[o_outline_view itemAtRow:[o_outline_view selectedRow]] pointerValue];
     pl_Release( VLCIntf );
 }
 
+- (id)playingItem
+{
+    playlist_t *p_playlist = pl_Hold( VLCIntf );
+    
+    id o_playing_item;
+    
+    o_playing_item = [o_outline_dict objectForKey:
+                      [NSString stringWithFormat:@"%p",  playlist_CurrentPlayingItem( p_playlist )]];
+    
+    pl_Release( VLCIntf );
+    
+    return o_playing_item;
+}
+
 - (IBAction)addNode:(id)sender
 {
     playlist_t * p_playlist = pl_Hold( VLCIntf );
         [o_status_field setStringValue: [NSString stringWithFormat:
                     _NS("%i items"),
              playlist_CurrentSize( p_playlist )]];
+        [o_status_field_embed setStringValue: [NSString stringWithFormat:
+                                               _NS("%i items"),
+                                               playlist_CurrentSize( p_playlist )]];
     }
     else
     {
         if( playlist_IsEmpty( p_playlist ) )
         {
             [o_status_field setStringValue: _NS("No items in the playlist")];
+            [o_status_field_embed setStringValue: _NS("No items in the playlist")];
         }
         else
         {
             [o_status_field setStringValue: _NS("1 item")];
+            [o_status_field_embed setStringValue: _NS("1 item")];
         }
     }
     PL_UNLOCK;
diff --git a/modules/gui/macosx/sidebarview.h b/modules/gui/macosx/sidebarview.h
new file mode 100644 (file)
index 0000000..13c9728
--- /dev/null
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * sidebarview.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2005-2008 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Eric Dudiak <dudiak at gmail dot com>
+ *          Colloquy <http://colloquy.info/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+@interface sidebarview : NSSplitView 
+{
+       long _mainSubviewIndex;
+}
+@end
+
+/*****************************************************************************
+ * VLCSidebar interface
+ *****************************************************************************/
+@interface VLCSidebar : NSObject
+{
+    IBOutlet id o_outline_view;
+    IBOutlet id o_playlist;
+}
+
+- (NSOutlineView *)outlineView;
+- (void)updateSidebar:(id)item;
+
+@end
\ No newline at end of file
diff --git a/modules/gui/macosx/sidebarview.m b/modules/gui/macosx/sidebarview.m
new file mode 100644 (file)
index 0000000..7398cc5
--- /dev/null
@@ -0,0 +1,201 @@
+/*****************************************************************************
+ * sidebarview.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2005-2008 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Eric Dudiak <dudiak at gmail dot com>
+ *          Colloquy <http://colloquy.info/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import "sidebarview.h"
+#import "intf.h"
+#import "playlist.h"
+
+@implementation sidebarview
+- (void) resetCursorRects 
+{
+       if( ! [self isPaneSplitter] )
+               [super resetCursorRects];
+}
+
+- (id) initWithCoder:(NSCoder *) decoder {
+       if( ( self = [super initWithCoder:decoder] ) )
+               _mainSubviewIndex = 1;
+       return self;
+}
+
+- (float) dividerThickness
+{
+       return 1.0;
+}
+
+- (BOOL) isVertical
+{
+    return YES;
+}
+
+- (void) drawDividerInRect:(NSRect) rect
+{
+       [[NSColor colorWithCalibratedWhite:0.65 alpha:1.] set];
+       NSRectFill( rect );
+}
+
+- (void) adjustSubviews
+{
+       if( _mainSubviewIndex == -1 || [[self subviews] count] != 2 ) {
+               [super adjustSubviews];
+               return;
+       }
+    
+       float dividerThickness = [self dividerThickness];
+       NSRect newFrame = [self frame];
+    
+       NSView *mainView = [[self subviews] objectAtIndex:_mainSubviewIndex];
+       NSView *otherView = ( _mainSubviewIndex ? [[self subviews] objectAtIndex:0] : [[self subviews] objectAtIndex:1] );
+    
+       NSRect mainFrame = [mainView frame];
+       NSRect otherFrame = [otherView frame];
+    
+
+       mainFrame.size.width = NSWidth( newFrame ) - dividerThickness - NSWidth( otherFrame );
+       mainFrame.size.height = NSHeight( newFrame );
+       mainFrame.origin.x = ( _mainSubviewIndex ? NSWidth( otherFrame ) + dividerThickness : 0. );
+       mainFrame.origin.y = 0.;
+
+       otherFrame.size.width = NSWidth( otherFrame );
+       otherFrame.size.height = NSHeight( newFrame );
+       otherFrame.origin.x = ( _mainSubviewIndex ? 0. : NSWidth( mainFrame ) + dividerThickness );
+       otherFrame.origin.y = 0.;
+    
+       [mainView setFrame:mainFrame];
+       [otherView setFrame:otherFrame];
+    
+       [self setNeedsDisplay:YES];
+}
+@end
+
+/*****************************************************************************
+ * VLCPlaylist implementation
+ *****************************************************************************/
+@implementation VLCSidebar
+
+- (void)awakeFromNib
+{
+    [o_outline_view setTarget: self];
+    [o_outline_view setDelegate: self];
+    [o_outline_view setDataSource: self];
+    [o_outline_view setAllowsEmptySelection: NO];
+}
+
+- (NSOutlineView *)outlineView
+{
+    return o_outline_view;
+}
+
+- (void)outlineView:(NSOutlineView *)outlineView
+    willDisplayCell:(id)cell
+     forTableColumn:(NSTableColumn *)tableColumn
+               item:(id)item
+{
+    if ( ![outlineView isExpandable:item] )
+    {
+        [cell setFont: [NSFont systemFontOfSize: 12]];
+        [cell setTextColor:[NSColor blackColor]];
+    }
+    else
+    {
+        [cell setFont: [NSFont boldSystemFontOfSize: 10]];
+        [cell setTextColor:[NSColor colorWithCalibratedWhite:0.365 alpha:1.0]];
+    }
+}
+
+- (void)updateSidebar:(id)item
+{
+    int i_row = -1;
+    [o_outline_view reloadData];
+    i_row = [o_outline_view rowForItem:item];
+    if( i_row > -1 )
+    {
+        [o_outline_view selectRow:i_row byExtendingSelection: NO];
+        [o_outline_view scrollRowToVisible: i_row];
+    }
+}
+
+- (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
+{
+    if( [outlineView isExpandable:item] )
+        return 12.;
+    else
+        return 20.;
+}
+
+- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item
+{
+    if( [outlineView isExpandable:item] )
+        return NO;
+    else
+    {
+        if( ![[o_playlist playingItem] isEqual: item] )
+            [o_playlist playSidebarItem:item];
+        return YES;
+    }
+}
+
+- (void)outlineViewItemDidExpand:(NSNotification *)notification
+{
+    int i_row = -1;
+    i_row = [o_outline_view rowForItem:[o_playlist playingItem]];
+    if( i_row > -1 )
+    {
+        [o_outline_view selectRow:i_row byExtendingSelection: NO];
+        [o_outline_view scrollRowToVisible: i_row];
+    }
+}
+
+@end
+
+@implementation VLCSidebar (NSOutlineViewDataSource)
+
+/* return the number of children for Obj-C pointer item */ /* DONE */
+- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
+{
+    return [o_playlist outlineView:outlineView numberOfChildrenOfItem:item];
+}
+
+/* return the child at index for the Obj-C pointer item */ /* DONE */
+- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
+{
+    return [o_playlist outlineView:outlineView child:index ofItem:item];
+}
+
+/* is the item expandable */
+- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
+{
+    return [o_playlist outlineView:outlineView isItemExpandable:item];
+}
+
+/* retrieve the string values for the cells */
+- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)o_tc byItem:(id)item
+{
+    if( [outlineView isExpandable:item] )
+        return [[o_playlist outlineView:outlineView objectValueForTableColumn:o_tc byItem:item] uppercaseString];
+    else
+        return [o_playlist outlineView:outlineView objectValueForTableColumn:o_tc byItem:item];
+}
+
+@end
diff --git a/modules/gui/macosx/sidestatusview.h b/modules/gui/macosx/sidestatusview.h
new file mode 100644 (file)
index 0000000..eb330e2
--- /dev/null
@@ -0,0 +1,33 @@
+/*****************************************************************************
+ * sidestatusview.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2005-2008 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Eric Dudiak <dudiak at gmail dot com>
+ *          Colloquy <http://colloquy.info/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+@interface sidestatusview : NSView {
+    IBOutlet NSSplitView *splitView;
+       float _clickOffset;
+       BOOL _insideResizeArea;
+}
+
+@end
diff --git a/modules/gui/macosx/sidestatusview.m b/modules/gui/macosx/sidestatusview.m
new file mode 100644 (file)
index 0000000..25c96f7
--- /dev/null
@@ -0,0 +1,107 @@
+/*****************************************************************************
+ * sidestatusview.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2005-2008 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Eric Dudiak <dudiak at gmail dot com>
+ *          Colloquy <http://colloquy.info/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import "sidestatusview.h"
+
+@implementation sidestatusview
+-(void)resetCursorRects
+{
+       [super resetCursorRects];
+       if( ! splitView ) return;
+    
+       NSImage *resizeImage = [NSImage imageNamed:@"sidebarResizeWidget"];
+       NSRect location;
+       location.size = [resizeImage size];
+       location.origin = NSMakePoint( NSWidth( [self bounds] ) - [resizeImage size].width, 0. );
+       [self addCursorRect:location cursor:[NSCursor resizeLeftRightCursor]];
+}
+
+- (void)drawRect:(NSRect)rect
+{
+       NSImage *backgroundImage = [NSImage imageNamed:@"sidebarStatusAreaBackground"];
+    [backgroundImage setSize:NSMakeSize(NSWidth( [self bounds] ), [backgroundImage size].height)];
+    [backgroundImage setScalesWhenResized:YES];
+    [backgroundImage compositeToPoint:NSMakePoint( 0., 0. ) operation:NSCompositeCopy];
+    
+       if( splitView ) {
+               NSImage *resizeImage = [NSImage imageNamed:@"sidebarResizeWidget"];
+               [resizeImage compositeToPoint:NSMakePoint( NSWidth( [self bounds] ) - [resizeImage size].width, 0. ) operation:NSCompositeCopy];
+       }
+}
+
+- (void)mouseDown:(NSEvent *)event
+{
+       if( ! splitView ) return;
+    NSPoint clickLocation = [self convertPoint:[event locationInWindow] fromView:nil];
+    
+       NSImage *resizeImage = [NSImage imageNamed:@"sidebarResizeWidget"];
+       NSRect location;
+       location.size = [resizeImage size];
+       location.origin = NSMakePoint( NSWidth( [self bounds] ) - [resizeImage size].width, 0. );
+    
+       _insideResizeArea = ( NSPointInRect( clickLocation, location ) );
+       if( ! _insideResizeArea ) return;
+    
+       clickLocation = [self convertPoint:[event locationInWindow] fromView:[self superview]];
+       _clickOffset = NSWidth( [[self superview] frame] ) - clickLocation.x;
+}
+
+- (void)mouseDragged:(NSEvent *)event
+{
+       if( ! splitView || ! _insideResizeArea ) return;
+    
+       [[NSNotificationCenter defaultCenter] postNotificationName:NSSplitViewWillResizeSubviewsNotification object:splitView];
+    
+    NSPoint clickLocation = [self convertPoint:[event locationInWindow] fromView:[self superview]];
+    
+       NSRect newFrame = [[self superview] frame];
+       newFrame.size.width = clickLocation.x + _clickOffset;
+    
+       id delegate = [splitView delegate];
+       if( delegate && [delegate respondsToSelector:@selector( splitView:constrainSplitPosition:ofSubviewAt: )] ) {
+               float new = [delegate splitView:splitView constrainSplitPosition:newFrame.size.width ofSubviewAt:0];
+               newFrame.size.width = new;
+       }
+    
+       if( delegate && [delegate respondsToSelector:@selector( splitView:constrainMinCoordinate:ofSubviewAt: )] ) {
+               float min = [delegate splitView:splitView constrainMinCoordinate:0. ofSubviewAt:0];
+               newFrame.size.width = MAX( min, newFrame.size.width );
+       }
+    
+       if( delegate && [delegate respondsToSelector:@selector( splitView:constrainMaxCoordinate:ofSubviewAt: )] ) {
+               float max = [delegate splitView:splitView constrainMaxCoordinate:0. ofSubviewAt:0];
+               newFrame.size.width = MIN( max, newFrame.size.width );
+       }
+    
+    if( delegate ) {
+        [delegate setMinSize:NSMakeSize(newFrame.size.width + 551., 114.)];
+    }
+    
+       [[self superview] setFrame:newFrame];
+    
+       [splitView adjustSubviews];
+    
+       [[NSNotificationCenter defaultCenter] postNotificationName:NSSplitViewDidResizeSubviewsNotification object:splitView];
+}
+@end