]> git.sesse.net Git - vlc/blob - modules/gui/macosx/prefs.m
* remove/disable the update-checker on OSX until 0.8.4 is out
[vlc] / modules / gui / macosx / prefs.m
1 /*****************************************************************************
2  * prefs.m: MacOS X module for vlc
3  *****************************************************************************
4  * Copyright (C) 2002-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Derk-Jan Hartman <hartman 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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /* VLCPrefs manages the main preferences dialog 
26    the class is related to wxwindows intf, PrefsPanel */
27 /* VLCTreeItem should contain:
28    - the children of the treeitem
29    - the associated prefs widgets
30    - the documentview with all the prefs widgets in it
31    - a saveChanges action
32    - a revertChanges action
33    - an advanced action (to hide/show advanced options)
34    - a redraw view action
35    - the children action should generate a list of the treeitems children (to be used by VLCPrefs datasource)
36
37    The class is sort of a mix of wxwindows intfs, PrefsTreeCtrl and ConfigTreeData
38 */
39 /* VLCConfigControl are subclassed NSView's containing and managing individual config items
40    the classes are VERY closely related to wxwindows ConfigControls */
41
42 /*****************************************************************************
43  * Preamble
44  *****************************************************************************/
45 #include <stdlib.h>                                      /* malloc(), free() */
46 #include <sys/param.h>                                    /* for MAXPATHLEN */
47 #include <string.h>
48
49 #include <vlc/vlc.h>
50 #include <vlc_config_cat.h>
51
52 #include "intf.h"
53 #include "prefs.h"
54 #include "prefs_widgets.h"
55 #include "vlc_keys.h"
56
57 /*****************************************************************************
58  * VLCPrefs implementation
59  *****************************************************************************/
60 @implementation VLCPrefs
61
62 static VLCPrefs *_o_sharedMainInstance = nil;
63
64 + (VLCPrefs *)sharedInstance
65 {
66     return _o_sharedMainInstance ? _o_sharedMainInstance : [[self alloc] init];
67 }
68
69 - (id)init
70 {
71     if( _o_sharedMainInstance ) {
72         [self dealloc];
73     }
74     else
75     {
76         _o_sharedMainInstance = [super init];
77         p_intf = VLCIntf;
78         o_empty_view = [[NSView alloc] init];
79     }
80
81     return _o_sharedMainInstance;
82 }
83
84 - (void)dealloc
85 {
86     [o_empty_view release];
87     [super dealloc];
88 }
89
90 - (void)awakeFromNib
91 {
92     p_intf = VLCIntf;
93     b_advanced = config_GetInt( p_intf, "advanced" );
94
95     [self initStrings];
96     [o_advanced_ckb setState: b_advanced];
97     [o_prefs_view setBorderType: NSGrooveBorder];
98     [o_prefs_view setHasVerticalScroller: YES];
99     [o_prefs_view setDrawsBackground: NO];
100     [o_prefs_view setDocumentView: o_empty_view];
101     [o_tree selectRow:0 byExtendingSelection:NO];
102 }
103
104 - (void)setTitle: (NSString *) o_title_name
105 {
106     [o_title setStringValue: o_title_name];
107 }
108
109 - (void)setHelp: (NSString *) o_help_name
110 {
111     [o_help setStringValue: o_help_name];
112 }
113
114 - (void)showPrefs
115 {
116     /* load our nib (if not already loaded) */
117     [NSBundle loadNibNamed:@"Preferences" owner:self];
118
119     [o_prefs_window center];
120     [o_prefs_window makeKeyAndOrderFront:self];
121 }
122
123 - (void)initStrings
124 {
125     [o_prefs_window setTitle: _NS("Preferences")];
126     [o_save_btn setTitle: _NS("Save")];
127     [o_cancel_btn setTitle: _NS("Cancel")];
128     [o_reset_btn setTitle: _NS("Reset All")];
129     [o_advanced_ckb setTitle: _NS("Advanced")];
130 }
131
132 - (IBAction)savePrefs: (id)sender
133 {
134     /* TODO: call savePrefs on Root item */
135     [[VLCTreeItem rootItem] applyChanges];
136     config_SaveConfigFile( p_intf, NULL );
137     [o_prefs_window orderOut:self];
138 }
139
140 - (IBAction)closePrefs: (id)sender
141 {
142     [o_prefs_window orderOut:self];
143 }
144
145 - (IBAction)resetAll: (id)sender
146 {
147     NSBeginInformationalAlertSheet(_NS("Reset Preferences"), _NS("Cancel"),
148         _NS("Continue"), nil, o_prefs_window, self,
149         @selector(sheetDidEnd: returnCode: contextInfo:), NULL, nil,
150         _NS("Beware this will reset your VLC media player preferences.\n"
151             "Are you sure you want to continue?") );
152 }
153
154 - (void)sheetDidEnd:(NSWindow *)o_sheet returnCode:(int)i_return
155     contextInfo:(void *)o_context
156 {
157     if( i_return == NSAlertAlternateReturn )
158     {
159         [o_prefs_view setDocumentView: o_empty_view];
160         config_ResetAll( p_intf );
161         [[VLCTreeItem rootItem] resetView];
162         [[o_tree itemAtRow:[o_tree selectedRow]]
163             showView:o_prefs_view advancedView:
164             ( [o_advanced_ckb state] == NSOnState ) ? VLC_TRUE : VLC_FALSE];
165     }
166 }
167
168 - (IBAction)advancedToggle: (id)sender
169 {
170     b_advanced = !b_advanced;
171     [o_advanced_ckb setState: b_advanced];
172     /* refresh the view of the current treeitem */
173     [[o_tree itemAtRow:[o_tree selectedRow]] showView:o_prefs_view advancedView:
174         ( [o_advanced_ckb state] == NSOnState ) ? VLC_TRUE : VLC_FALSE];
175 }
176
177 - (void)loadConfigTree
178 {
179 }
180
181 - (void)outlineViewSelectionIsChanging:(NSNotification *)o_notification
182 {
183 }
184
185 /* update the document view to the view of the selected tree item */
186 - (void)outlineViewSelectionDidChange:(NSNotification *)o_notification
187 {
188     [[o_tree itemAtRow:[o_tree selectedRow]] showView: o_prefs_view
189         advancedView:( [o_advanced_ckb state] == NSOnState ) ?
190         VLC_TRUE : VLC_FALSE];
191 }
192
193 @end
194
195 @implementation VLCPrefs (NSTableDataSource)
196
197 - (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
198     return (item == nil) ? [[VLCTreeItem rootItem] numberOfChildren] :
199                             [item numberOfChildren];
200 }
201
202 - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
203 {
204     return (item == nil) ? YES : ( ([item numberOfChildren] != -1) && 
205                                    ([item numberOfChildren] != 0));
206 }
207
208 - (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item {
209     return (item == nil) ? [[VLCTreeItem rootItem] childAtIndex:index] :
210                             [item childAtIndex:index];
211 }
212
213 - (id)outlineView:(NSOutlineView *)outlineView
214     objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
215 {
216     return (item == nil) ? @"" : (id)[item getName];
217 }
218
219 @end
220
221 @implementation VLCTreeItem
222
223 static VLCTreeItem *o_root_item = nil;
224
225 #define IsALeafNode ((id)-1)
226
227 - (id)initWithName: (NSString *)o_item_name
228     withTitle: (NSString *)o_item_title
229     withHelp: (NSString *)o_item_help
230     ID: (int)i_id
231     parent:(VLCTreeItem *)o_parent_item
232     children:(NSMutableArray *)o_children_array
233     whithCategory: (int) i_category
234 {
235     self = [super init];
236
237     if( self != nil )
238     {
239         o_name = [o_item_name copy];
240         o_title= [o_item_title copy];
241         o_help= [o_item_help copy];
242         i_object_id = i_id;
243         o_parent = o_parent_item;
244         o_children = o_children_array;
245         i_object_category = i_category;
246         o_subviews = nil;
247     }
248     return( self );
249 }
250
251 + (VLCTreeItem *)rootItem
252 {
253    if (o_root_item == nil)
254         o_root_item = [[VLCTreeItem alloc] initWithName:@"main" withTitle:@"main" withHelp:@"" ID:0
255             parent:nil children:[[NSMutableArray alloc] initWithCapacity:10]
256             whithCategory: -1];
257    return o_root_item;
258 }
259
260 - (void)dealloc
261 {
262     if (o_children != IsALeafNode) [o_children release];
263     [o_name release];
264     [o_title release];
265     [o_help release];
266     [super dealloc];
267 }
268
269 /* Creates and returns the array of children
270  * Loads children incrementally */
271 - (NSArray *)children
272 {
273     if( o_children == IsALeafNode )
274         return o_children;
275     if( [ o_children count] == 0 )
276     {
277         intf_thread_t   *p_intf = VLCIntf;
278         vlc_list_t      *p_list;
279         module_t        *p_module = NULL;
280         module_config_t *p_item;
281         int             i_index;
282
283         /* List the modules */
284         p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
285         if( !p_list ) return nil;
286
287         if( [[self getName] isEqualToString: @"main"] )
288         {
289             /*
290             * Find the main module
291             */
292             for( i_index = 0; i_index < p_list->i_count; i_index++ )
293             {
294                 p_module = (module_t *)p_list->p_values[i_index].p_object;
295                 if( !strcmp( p_module->psz_object_name, "main" ) )
296                     break;
297             }
298             if( p_module == NULL )
299             {
300                 msg_Err( p_intf,
301                     "could not find the main module in our preferences" );
302                 return nil;
303             }
304             if( i_index < p_list->i_count )
305             {
306                 /* We found the main module */
307                 /* Enumerate config categories and store a reference so we can
308                  * generate their config panel them when it is asked by the user. */
309                 VLCTreeItem *p_last_category = NULL;
310                 p_item = p_module->p_config;
311                 o_children = [[NSMutableArray alloc] initWithCapacity:10];
312                 if( p_item ) do
313                 {
314                     NSString *o_child_name;
315                     NSString *o_child_title;
316                     NSString *o_child_help;
317                     switch( p_item->i_type )
318                     {
319                     case CONFIG_CATEGORY:
320                         o_child_name = [[VLCMain sharedInstance]
321                             localizedString: config_CategoryNameGet( p_item->i_value ) ];
322                         o_child_title = o_child_name;
323                         o_child_help = [[VLCMain sharedInstance]
324                             localizedString: config_CategoryHelpGet( p_item->i_value ) ];
325                         p_last_category = [VLCTreeItem alloc];
326                         [o_children addObject:[p_last_category
327                             initWithName: o_child_name
328                             withTitle: o_child_title
329                             withHelp: o_child_help
330                             ID: p_item->i_value
331                             parent:self
332                             children:[[NSMutableArray alloc]
333                                 initWithCapacity:10]
334                             whithCategory: p_item - p_module->p_config]];
335                         break;
336                     case CONFIG_SUBCATEGORY:
337                         o_child_name = [[VLCMain sharedInstance]
338                             localizedString: config_CategoryNameGet( p_item->i_value ) ];
339                         o_child_title = o_child_name;
340                         o_child_help = [[VLCMain sharedInstance]
341                             localizedString: config_CategoryHelpGet( p_item->i_value ) ];
342                         if( p_item->i_value != SUBCAT_PLAYLIST_GENERAL &&
343                             p_item->i_value != SUBCAT_VIDEO_GENERAL &&
344                             p_item->i_value != SUBCAT_AUDIO_GENERAL )
345                             [p_last_category->o_children
346                                 addObject:[[VLCTreeItem alloc]
347                                 initWithName: o_child_name
348                                 withTitle: o_child_title
349                                 withHelp: o_child_help
350                                 ID: p_item->i_value
351                                 parent:p_last_category
352                                 children:[[NSMutableArray alloc]
353                                     initWithCapacity:10]
354                                 whithCategory: p_item - p_module->p_config]];
355                         break;
356                     default:
357                         break;
358                     }
359                 } while( p_item->i_type != CONFIG_HINT_END && p_item++ );
360             }
361
362             /* Build a tree of the plugins */
363             /* Add the capabilities */
364             for( i_index = 0; i_index < p_list->i_count; i_index++ )
365             {
366                 p_module = (module_t *)p_list->p_values[i_index].p_object;
367
368                 /* Exclude the main module */
369                 if( !strcmp( p_module->psz_object_name, "main" ) )
370                     continue;
371
372                 /* Exclude empty plugins (submodules don't have config */
373                 /* options, they are stored in the parent module) */
374                 if( p_module->b_submodule )
375                     continue;
376                 else
377                     p_item = p_module->p_config;
378
379                 if( !p_item ) continue;
380                 int i_category = -1;
381                 int i_subcategory = -1;
382                 int i_options = 0;
383                 do
384                 {
385                     if( p_item->i_type == CONFIG_CATEGORY )
386                         i_category = p_item->i_value;
387                     else if( p_item->i_type == CONFIG_SUBCATEGORY )
388                         i_subcategory = p_item->i_value;
389
390                     if( p_item->i_type & CONFIG_ITEM )
391                         i_options ++;
392                     if( i_options > 0 && i_category >= 0 && i_subcategory >= 0 )
393                         break;
394                 } while( p_item->i_type != CONFIG_HINT_END && p_item++ );
395                 if( !i_options ) continue;
396
397                 /* Find the right category item */
398
399                 long cookie;
400                 vlc_bool_t b_found = VLC_FALSE;
401                 unsigned int i;
402                 VLCTreeItem* p_category_item, * p_subcategory_item;
403                 for (i = 0 ; i < [o_children count] ; i++)
404                 {
405                     p_category_item = [o_children objectAtIndex: i];
406                     if( p_category_item->i_object_id == i_category )
407                     {
408                         b_found = VLC_TRUE;
409                         break;
410                     }
411                 }
412                 if( !b_found ) continue;
413
414                 /* Find subcategory item */
415                 b_found = VLC_FALSE;
416                 cookie = -1;
417                 for (i = 0 ; i < [p_category_item->o_children count] ; i++)
418                 {
419                     p_subcategory_item = [p_category_item->o_children
420                                             objectAtIndex: i];
421                     if( p_subcategory_item->i_object_id == i_subcategory )
422                     {
423                         b_found = VLC_TRUE;
424                         break;
425                     }
426                 }
427                 if( !b_found )
428                     p_subcategory_item = p_category_item;
429
430                 [p_subcategory_item->o_children addObject:[[VLCTreeItem alloc]
431                     initWithName:[[VLCMain sharedInstance]
432                         localizedString: p_module->psz_shortname ?
433                         p_module->psz_shortname : p_module->psz_object_name ]
434                     withTitle:[[VLCMain sharedInstance]
435                         localizedString: p_module->psz_longname ?
436                         p_module->psz_longname : p_module->psz_object_name ]
437                     withHelp: @""
438                     ID: p_module->i_object_id
439                     parent:p_subcategory_item
440                     children:IsALeafNode
441                     whithCategory: -1]];
442             }
443         }
444         vlc_list_release( p_list );
445     }
446     return o_children;
447 }
448
449 - (int)getObjectID
450 {
451     return i_object_id;
452 }
453
454 - (NSString *)getName
455 {
456     return o_name;
457 }
458
459 - (NSString *)getTitle
460 {
461     return o_title;
462 }
463
464 - (NSString *)getHelp
465 {
466     return o_help;
467 }
468
469 - (VLCTreeItem *)childAtIndex:(int)i_index
470 {
471     return [[self children] objectAtIndex:i_index];
472 }
473
474 - (int)numberOfChildren {
475     id i_tmp = [self children];
476     return (i_tmp == IsALeafNode) ? (-1) : (int)[i_tmp count];
477 }
478
479 - (BOOL)hasPrefs:(NSString *)o_module_name
480 {
481     intf_thread_t *p_intf = VLCIntf;
482     module_t *p_parser;
483     vlc_list_t *p_list;
484     char *psz_module_name;
485     int i_index;
486
487     psz_module_name = (char *)[o_module_name UTF8String];
488
489     /* look for module */
490     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
491
492     for( i_index = 0; i_index < p_list->i_count; i_index++ )
493     {
494         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
495
496         if( !strcmp( p_parser->psz_object_name, psz_module_name ) )
497         {
498             BOOL b_has_prefs = p_parser->i_config_items != 0;
499             vlc_list_release( p_list );
500             return( b_has_prefs );
501         }
502     }
503
504     vlc_list_release( p_list );
505
506     return( NO );
507 }
508
509 - (NSView *)showView:(NSScrollView *)o_prefs_view
510     advancedView:(vlc_bool_t) b_advanced
511 {
512     NSRect          s_vrc;
513     NSView          *o_view;
514
515     [[VLCPrefs sharedInstance] setTitle: [self getTitle]];
516     [[VLCPrefs sharedInstance] setHelp: [self getHelp]];
517     /* NSLog( [self getHelp] ); */ 
518     s_vrc = [[o_prefs_view contentView] bounds]; s_vrc.size.height -= 4;
519     o_view = [[VLCFlippedView alloc] initWithFrame: s_vrc];
520     [o_view setAutoresizingMask: NSViewWidthSizable | NSViewMinYMargin |
521                                     NSViewMaxYMargin];
522
523 /* Create all subviews if it isn't already done because we cannot use */
524 /* setHiden for MacOS < 10.3*/
525     if( o_subviews == nil )
526     {
527         intf_thread_t   *p_intf = VLCIntf;
528         vlc_list_t      *p_list;
529         module_t        *p_parser = NULL;
530         module_config_t *p_item;
531
532         o_subviews = [[NSMutableArray alloc] initWithCapacity:10];
533         /* Get a pointer to the module */
534         if( i_object_category == -1 )
535         {
536             p_parser = (module_t *) vlc_object_get( p_intf, i_object_id );
537             if( !p_parser || p_parser->i_object_type != VLC_OBJECT_MODULE )
538             {
539                 /* 0OOoo something went really bad */
540                 return nil;
541             }
542             p_item = p_parser->p_config;
543             int i = 0;
544
545             p_item = p_parser->p_config + 1;
546
547             do
548             {
549                 if( !p_item )
550                 {
551                     msg_Err( p_intf, "null item found" );
552                     break;
553                 }
554                 switch(p_item->i_type)
555                 {
556                 case CONFIG_SUBCATEGORY:
557                     break;
558                 case CONFIG_CATEGORY:
559                     break;
560                 case CONFIG_SECTION:
561                     break;
562                 case CONFIG_HINT_END:
563                     break;
564                 case CONFIG_HINT_USAGE:
565                     break;
566                 default:
567                 {
568                     VLCConfigControl *o_control = nil;
569                     o_control = [VLCConfigControl newControl:p_item
570                                                   withView:o_view];
571                     if( o_control != nil )
572                     {
573                         [o_control setAutoresizingMask: NSViewMaxYMargin |
574                             NSViewWidthSizable];
575                         [o_subviews addObject: o_control];
576                     }
577                 }
578                     break;
579                 }
580             } while( p_item++->i_type != CONFIG_HINT_END );
581
582             vlc_object_release( p_parser );
583         }
584         else
585         {
586             int i = 0;
587             int i_index;
588             p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
589             if( !p_list ) return o_view;
590
591             /*
592             * Find the main module
593             */
594             for( i_index = 0; i_index < p_list->i_count; i_index++ )
595             {
596                 p_parser = (module_t *)p_list->p_values[i_index].p_object;
597                 if( !strcmp( p_parser->psz_object_name, "main" ) )
598                     break;
599             }
600             if( p_parser == NULL )
601             {
602                 msg_Err( p_intf, "could not find the main module in our "
603                                     "preferences" );
604                 return o_view;
605             }
606             p_item = (p_parser->p_config + i_object_category);
607             if( ( p_item->i_type == CONFIG_CATEGORY ) &&
608               ( ( p_item->i_value == CAT_PLAYLIST )  ||
609                 ( p_item->i_value == CAT_AUDIO )  ||
610                 ( p_item->i_value == CAT_VIDEO ) ) )
611                 p_item++;
612
613             do
614             {
615                 p_item++;
616                 if( !p_item )
617                 {
618                     msg_Err( p_intf, "null item found" );
619                     break;
620                 }
621                 switch( p_item->i_type )
622                 {
623                 case CONFIG_SUBCATEGORY:
624                     break;
625                 case CONFIG_CATEGORY:
626                     break;
627                 case CONFIG_SECTION:
628                     break;
629                 case CONFIG_HINT_END:
630                     break;
631                 case CONFIG_HINT_USAGE:
632                     break;
633                 default:
634                 {
635                     VLCConfigControl *o_control = nil;
636                     o_control = [VLCConfigControl newControl:p_item
637                                                   withView:o_view];
638                     if( o_control != nil )
639                     {
640                         [o_control setAutoresizingMask: NSViewMaxYMargin |
641                                                         NSViewWidthSizable];
642                         [o_subviews addObject: o_control];
643                     }
644                     break;
645                 }
646                 }
647             } while ( ( p_item->i_type != CONFIG_HINT_END ) &&
648                       ( p_item->i_type != CONFIG_SUBCATEGORY ) );
649
650             vlc_list_release( p_list );
651         }
652     }
653
654     if( o_view != nil )
655     {
656         int i_lastItem = 0;
657         int i_yPos = -2;
658         int i_max_label = 0;
659         int i_show_advanced = 0;
660
661         NSEnumerator *enumerator = [o_subviews objectEnumerator];
662         VLCConfigControl *o_widget;
663         NSRect o_frame;
664         
665         while( ( o_widget = [enumerator nextObject] ) )
666             if( ( [o_widget isAdvanced] ) && (! b_advanced) )
667                 continue;
668             else if( i_max_label < [o_widget getLabelSize] )
669                 i_max_label = [o_widget getLabelSize];
670
671         enumerator = [o_subviews objectEnumerator];
672         while( ( o_widget = [enumerator nextObject] ) )
673         {
674             int i_widget;
675             if( ( [o_widget isAdvanced] ) && (! b_advanced) )
676             {
677                 i_show_advanced++;
678                 continue;
679             }
680
681             i_widget = [o_widget getViewType];
682             i_yPos += [VLCConfigControl calcVerticalMargin:i_widget
683                 lastItem:i_lastItem];
684             [o_widget setYPos:i_yPos];
685             o_frame = [o_widget frame];
686             o_frame.size.width = [o_view frame].size.width -
687                                     LEFTMARGIN - RIGHTMARGIN;
688             [o_widget setFrame:o_frame];
689             [o_widget alignWithXPosition: i_max_label];
690             i_yPos += [o_widget frame].size.height;
691             i_lastItem = i_widget;
692             [o_view addSubview:o_widget];
693          }
694         if( i_show_advanced != 0 )
695         {
696             /* We add the advanced notice... */
697             NSRect s_rc = [o_view frame];
698             NSTextField *o_label;
699             s_rc.size.height = 17;
700             s_rc.origin.x = LEFTMARGIN;
701             s_rc.origin.y = i_yPos += [VLCConfigControl
702                                         calcVerticalMargin:CONFIG_ITEM_STRING
703                                         lastItem:i_lastItem];
704             o_label = [[[NSTextField alloc] initWithFrame: s_rc] retain];
705             [o_label setDrawsBackground: NO];
706             [o_label setBordered: NO];
707             [o_label setEditable: NO];
708             [o_label setSelectable: NO];
709             [o_label setStringValue: _NS("Some options are available but " \
710                                 "hidden. Check \"Advanced\" to see them.")];
711             [o_label setFont:[NSFont systemFontOfSize:10]];
712             [o_label sizeToFit];
713             [o_view addSubview:o_label];
714             i_yPos += [o_label frame].size.height;
715         }
716         o_frame = [o_view frame];
717         o_frame.size.height = i_yPos;
718         [o_view setFrame:o_frame];
719         [o_prefs_view setDocumentView:o_view];
720
721     }
722     return o_view;
723 }
724
725 - (void)applyChanges
726 {
727     unsigned int i;
728     if( o_subviews != nil )
729         //Item has been shown
730         for( i = 0 ; i < [o_subviews count] ; i++ )
731             [[o_subviews objectAtIndex:i] applyChanges];
732
733     if( o_children != IsALeafNode )
734         for( i = 0 ; i < [o_children count] ; i++ )
735             [[o_children objectAtIndex:i] applyChanges];
736 }
737
738 - (void)resetView
739 {
740     unsigned int i;
741     if( o_subviews != nil )
742     {
743         //Item has been shown
744         [o_subviews release];
745         o_subviews = nil;
746     }
747
748     if( o_children != IsALeafNode )
749         for( i = 0 ; i < [o_children count] ; i++ )
750             [[o_children objectAtIndex:i] resetView];
751 }
752
753 @end
754
755
756 @implementation VLCFlippedView
757
758 - (BOOL)isFlipped
759 {
760     return( YES );
761 }
762
763 @end