]> git.sesse.net Git - vlc/blob - modules/gui/macosx/prefs_widgets.m
Added widget, fix save, etc.
[vlc] / modules / gui / macosx / prefs_widgets.m
1 /*****************************************************************************
2  * prefs_widgets.m: Preferences controls
3  *****************************************************************************
4  * Copyright (C) 2002-2003 VideoLAN
5  * $Id$
6  *
7  * Authors: Derk-Jan Hartman <hartman at videolan.org>
8  *          Jérôme Decoodt <djc at videolan.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 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>
30
31 #include <vlc/vlc.h>
32 #include "vlc_keys.h"
33
34 #include "intf.h"
35 #include "prefs_widgets.h"
36
37 #define PREFS_WRAP 300
38 #define OFFSET_RIGHT 20
39 #define OFFSET_BETWEEN 2
40
41 #define LEFTMARGIN  18
42 #define RIGHTMARGIN 18
43
44 #define UPWARDS_WHITE_ARROW                 "\xE2\x87\xA7" 
45 #define OPTION_KEY                          "\xE2\x8C\xA5"
46 #define UP_ARROWHEAD                        "\xE2\x8C\x83"
47 #define PLACE_OF_INTEREST_SIGN              "\xE2\x8C\x98"
48
49 #define MACOS_VERSION 3
50
51 #define POPULATE_A_KEY( o_menu, string, value )                             \
52 {                                                                           \
53     NSMenuItem *o_mi;                                                       \
54 /*  Normal */                                                               \
55     o_mi = [[NSMenuItem alloc] initWithTitle:string action:nil keyEquivalent:@""]; \
56     [o_mi setKeyEquivalentModifierMask:                                     \
57         0];                                                                 \
58     [o_mi setAlternate: NO];                                                \
59     [o_mi setTag:                                                           \
60         ( value )];                                                         \
61     [o_menu addItem: o_mi];                                                 \
62 if( MACOS_VERSION >= 3 )                                                    \
63 {                                                                           \
64 /*  Ctrl */                                                                 \
65     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
66         [[NSString stringWithUTF8String:                                    \
67             UP_ARROWHEAD                                                    \
68         ] stringByAppendingString: string]                                  \
69         action:nil keyEquivalent:@""];                                      \
70     [o_mi setKeyEquivalentModifierMask:                                     \
71         NSControlKeyMask];                                                  \
72     [o_mi setAlternate: YES];                                               \
73     [o_mi setTag:                                                           \
74         KEY_MODIFIER_CTRL | ( value )];                                     \
75     [o_menu addItem: o_mi];                                                 \
76 /* Ctrl+Alt */                                                              \
77     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
78         [[NSString stringWithUTF8String:                                    \
79             UP_ARROWHEAD OPTION_KEY                                         \
80         ] stringByAppendingString: string]                                  \
81         action:nil keyEquivalent:@""];                                      \
82     [o_mi setKeyEquivalentModifierMask:                                     \
83         NSControlKeyMask | NSAlternateKeyMask];                             \
84     [o_mi setAlternate: YES];                                               \
85     [o_mi setTag:                                                           \
86         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT) | ( value )];                \
87     [o_menu addItem: o_mi];                                                 \
88 /* Ctrl+Shift */                                                            \
89     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
90         [[NSString stringWithUTF8String:                                    \
91             UP_ARROWHEAD UPWARDS_WHITE_ARROW                                \
92         ] stringByAppendingString: string]                                  \
93         action:nil keyEquivalent:@""];                                      \
94     [o_mi setKeyEquivalentModifierMask:                                     \
95        NSControlKeyMask | NSShiftKeyMask];                                  \
96     [o_mi setAlternate: YES];                                               \
97     [o_mi setTag:                                                           \
98         (KEY_MODIFIER_CTRL | KEY_MODIFIER_SHIFT) | ( value )];              \
99     [o_menu addItem: o_mi];                                                 \
100 /* Ctrl+Apple */                                                            \
101     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
102         [[NSString stringWithUTF8String:                                    \
103             UP_ARROWHEAD PLACE_OF_INTEREST_SIGN                             \
104         ] stringByAppendingString: string]                                  \
105         action:nil keyEquivalent:@""];                                      \
106     [o_mi setKeyEquivalentModifierMask:                                     \
107         NSControlKeyMask | NSCommandKeyMask];                               \
108     [o_mi setAlternate: YES];                                               \
109     [o_mi setTag:                                                           \
110         (KEY_MODIFIER_CTRL | KEY_MODIFIER_COMMAND) | ( value )];            \
111     [o_menu addItem: o_mi];                                                 \
112 /* Ctrl+Alt+Shift */                                                        \
113     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
114         [[NSString stringWithUTF8String:                                    \
115             UP_ARROWHEAD OPTION_KEY UPWARDS_WHITE_ARROW                     \
116         ] stringByAppendingString: string]                                  \
117         action:nil keyEquivalent:@""];                                      \
118     [o_mi setKeyEquivalentModifierMask:                                     \
119         NSControlKeyMask | NSAlternateKeyMask | NSShiftKeyMask];            \
120     [o_mi setAlternate: YES];                                               \
121     [o_mi setTag:                                                           \
122         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT) | ( value )]; \
123     [o_menu addItem: o_mi];                                                 \
124 /* Ctrl+Alt+Apple */                                                        \
125     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
126         [[NSString stringWithUTF8String:                                    \
127             UP_ARROWHEAD OPTION_KEY PLACE_OF_INTEREST_SIGN                  \
128         ] stringByAppendingString: string]                                  \
129         action:nil keyEquivalent:@""];                                      \
130     [o_mi setKeyEquivalentModifierMask:                                     \
131         NSControlKeyMask | NSAlternateKeyMask | NSCommandKeyMask];          \
132     [o_mi setAlternate: YES];                                               \
133     [o_mi setTag:                                                           \
134         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT | KEY_MODIFIER_COMMAND) | ( value )]; \
135     [o_menu addItem: o_mi];                                                 \
136 /* Ctrl+Shift+Apple */                                                      \
137     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
138         [[NSString stringWithUTF8String:                                    \
139             UP_ARROWHEAD UPWARDS_WHITE_ARROW PLACE_OF_INTEREST_SIGN         \
140         ] stringByAppendingString: string]                                  \
141         action:nil keyEquivalent:@""];                                      \
142     [o_mi setKeyEquivalentModifierMask:                                     \
143         NSControlKeyMask | NSShiftKeyMask | NSCommandKeyMask];              \
144     [o_mi setAlternate: YES];                                               \
145     [o_mi setTag:                                                           \
146         (KEY_MODIFIER_CTRL | KEY_MODIFIER_SHIFT | KEY_MODIFIER_COMMAND) | ( value )]; \
147     [o_menu addItem: o_mi];                                                 \
148 /* Ctrl+Alt+Shift+Apple */                                                  \
149     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
150         [[NSString stringWithUTF8String:                                    \
151             UP_ARROWHEAD OPTION_KEY UPWARDS_WHITE_ARROW PLACE_OF_INTEREST_SIGN  \
152         ] stringByAppendingString: string]                                  \
153         action:nil keyEquivalent:@""];                                      \
154     [o_mi setKeyEquivalentModifierMask:                                     \
155         NSControlKeyMask | NSAlternateKeyMask | NSShiftKeyMask | NSCommandKeyMask]; \
156     [o_mi setAlternate: YES];                                               \
157     [o_mi setTag:                                                           \
158         (KEY_MODIFIER_CTRL | KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT | KEY_MODIFIER_COMMAND) | ( value )]; \
159     [o_menu addItem: o_mi];                                                 \
160 /* Alt */                                                                   \
161     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
162         [[NSString stringWithUTF8String:                                    \
163             OPTION_KEY                                                      \
164         ] stringByAppendingString: string]                                  \
165         action:nil keyEquivalent:@""];                                      \
166     [o_mi setKeyEquivalentModifierMask:                                     \
167         NSAlternateKeyMask];                                                \
168     [o_mi setAlternate: YES];                                               \
169     [o_mi setTag:                                                           \
170         KEY_MODIFIER_ALT | ( value )];                                      \
171     [o_menu addItem: o_mi];                                                 \
172 /* Alt+Shift */                                                             \
173     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
174         [[NSString stringWithUTF8String:                                    \
175             OPTION_KEY UPWARDS_WHITE_ARROW                                  \
176         ] stringByAppendingString: string]                                  \
177         action:nil keyEquivalent:@""];                                      \
178     [o_mi setKeyEquivalentModifierMask:                                     \
179         NSAlternateKeyMask | NSShiftKeyMask];                               \
180     [o_mi setAlternate: YES];                                               \
181     [o_mi setTag:                                                           \
182         (KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT) | ( value )];               \
183     [o_menu addItem: o_mi];                                                 \
184 /* Alt+Apple */                                                             \
185     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
186         [[NSString stringWithUTF8String:                                    \
187             OPTION_KEY PLACE_OF_INTEREST_SIGN                               \
188         ] stringByAppendingString: string]                                  \
189         action:nil keyEquivalent:@""];                                      \
190     [o_mi setKeyEquivalentModifierMask:                                     \
191         NSAlternateKeyMask | NSCommandKeyMask];                             \
192     [o_mi setAlternate: YES];                                               \
193     [o_mi setTag:                                                           \
194         (KEY_MODIFIER_ALT | KEY_MODIFIER_COMMAND) | ( value )];             \
195     [o_menu addItem: o_mi];                                                 \
196 /* Alt+Shift+Apple */                                                       \
197     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
198         [[NSString stringWithUTF8String:                                    \
199             OPTION_KEY UPWARDS_WHITE_ARROW PLACE_OF_INTEREST_SIGN           \
200         ] stringByAppendingString: string]                                  \
201         action:nil keyEquivalent:@""];                                      \
202     [o_mi setKeyEquivalentModifierMask:                                     \
203         NSAlternateKeyMask | NSShiftKeyMask | NSCommandKeyMask];            \
204     [o_mi setAlternate: YES];                                               \
205     [o_mi setTag:                                                           \
206         (KEY_MODIFIER_ALT | KEY_MODIFIER_SHIFT | KEY_MODIFIER_COMMAND) | ( value )]; \
207     [o_menu addItem: o_mi];                                                 \
208 /* Shift */                                                                 \
209     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
210         [[NSString stringWithUTF8String:                                    \
211             UPWARDS_WHITE_ARROW                                             \
212         ] stringByAppendingString: string]                                  \
213         action:nil keyEquivalent:@""];                                      \
214     [o_mi setKeyEquivalentModifierMask:                                     \
215         NSShiftKeyMask];                                                    \
216     [o_mi setAlternate: YES];                                               \
217     [o_mi setTag:                                                           \
218         KEY_MODIFIER_SHIFT | ( value )];                                    \
219     [o_menu addItem: o_mi];                                                 \
220 /* Shift+Apple */                                                           \
221     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
222         [[NSString stringWithUTF8String:                                    \
223             UPWARDS_WHITE_ARROW PLACE_OF_INTEREST_SIGN                      \
224         ] stringByAppendingString: string]                                  \
225         action:nil keyEquivalent:@""];                                      \
226     [o_mi setKeyEquivalentModifierMask:                                     \
227         NSShiftKeyMask | NSCommandKeyMask];                                 \
228     [o_mi setAlternate: YES];                                               \
229     [o_mi setTag:                                                           \
230         (KEY_MODIFIER_SHIFT | KEY_MODIFIER_COMMAND) | ( value )];           \
231     [o_menu addItem: o_mi];                                                 \
232 /* Apple */                                                                 \
233     o_mi = [[NSMenuItem alloc] initWithTitle:                               \
234         [[NSString stringWithUTF8String:                                    \
235         PLACE_OF_INTEREST_SIGN                                              \
236         ] stringByAppendingString: string]                                  \
237         action:nil keyEquivalent:@""];                                      \
238     [o_mi setKeyEquivalentModifierMask:                                     \
239         NSCommandKeyMask];                                                  \
240     [o_mi setAlternate: YES];                                               \
241     [o_mi setTag:                                                           \
242         KEY_MODIFIER_COMMAND | ( value )];                                  \
243     [o_menu addItem: o_mi];                                                 \
244 }                                                                           \
245 }
246
247 #define ADD_LABEL( o_label, superFrame, x_offset, my_y_offset, label )    \
248 {                                                                         \
249     NSRect s_rc = superFrame;                                             \
250     s_rc.size.height = 17;                                                \
251     s_rc.origin.x = x_offset - 3;                                         \
252     s_rc.origin.y = superFrame.size.height - 17 + my_y_offset;            \
253     o_label = [[[NSTextField alloc] initWithFrame: s_rc] retain];         \
254     [o_label setDrawsBackground: NO];                                     \
255     [o_label setBordered: NO];                                            \
256     [o_label setEditable: NO];                                            \
257     [o_label setSelectable: NO];                                          \
258     [o_label setStringValue: label];                                      \
259     [o_label setFont:[NSFont systemFontOfSize:0]];                        \
260     [o_label sizeToFit];                                                  \
261 }
262
263 #define ADD_TEXTFIELD( o_textfield, superFrame, x_offset, my_y_offset, my_width, tooltip, init_value ) \
264 {                                                                               \
265     NSRect s_rc = superFrame;                                                   \
266     s_rc.origin.x = x_offset;                                                   \
267     s_rc.origin.y = my_y_offset;                                                \
268     s_rc.size.height = 22;                                                      \
269     s_rc.size.width = my_width;                                                 \
270     o_textfield = [[[NSTextField alloc] initWithFrame: s_rc] retain];           \
271     [o_textfield setFont:[NSFont systemFontOfSize:0]];                          \
272     [o_textfield setToolTip: tooltip];                                          \
273     [o_textfield setStringValue: init_value];                                   \
274 }
275
276 #define ADD_COMBO( o_combo, superFrame, x_offset, my_y_offset, x2_offset, tooltip ) \
277 {                                                                               \
278     NSRect s_rc = superFrame;                                                   \
279     s_rc.origin.x = x_offset + 2;                                               \
280     s_rc.origin.y = my_y_offset;                                                \
281     s_rc.size.height = 26;                                                      \
282     s_rc.size.width = superFrame.size.width + 2 - s_rc.origin.x - (x2_offset);  \
283     o_combo = [[[NSComboBox alloc] initWithFrame: s_rc] retain];                \
284     [o_combo setFont:[NSFont systemFontOfSize:0]];                              \
285     [o_combo setToolTip: tooltip];                                              \
286     [o_combo setUsesDataSource:TRUE];                                           \
287     [o_combo setDataSource:self];                                               \
288     [o_combo setNumberOfVisibleItems:10];                                       \
289     [o_combo setCompletes:YES];                                                 \
290 }
291
292 #define ADD_RIGHT_BUTTON( o_button, superFrame, x_offset, my_y_offset, tooltip, title )   \
293 {                                                                                      \
294     NSRect s_rc = superFrame;                                                          \
295     o_button = [[[NSButton alloc] initWithFrame: s_rc] retain];                        \
296     [o_button setButtonType: NSMomentaryPushInButton];                                 \
297     [o_button setBezelStyle: NSRoundedBezelStyle];                                     \
298     [o_button setTitle: title];                                                        \
299     [o_button setFont:[NSFont systemFontOfSize:0]];                                    \
300     [o_button sizeToFit];                                                              \
301     s_rc = [o_button frame];                                                           \
302     s_rc.origin.x = superFrame.size.width - [o_button frame].size.width - 6;           \
303     s_rc.origin.y = my_y_offset - 6;                                                   \
304     s_rc.size.width += 12;                                                             \
305     [o_button setFrame: s_rc];                                                         \
306     [o_button setToolTip: tooltip];                                                    \
307     [o_button setTarget: self];                                                        \
308     [o_button setAction: @selector(openFileDialog:)];                                  \
309 }
310
311 #define ADD_POPUP( o_popup, superFrame, x_offset, my_y_offset, x2_offset, tooltip ) \
312 {                                                                               \
313     NSRect s_rc = superFrame;                                                   \
314     s_rc.origin.x = x_offset - 1;                                               \
315     s_rc.origin.y = my_y_offset;                                                \
316     s_rc.size.height = 26;                                                      \
317     s_rc.size.width = superFrame.size.width + 2 - s_rc.origin.x - (x2_offset);  \
318     o_popup = [[[NSPopUpButton alloc] initWithFrame: s_rc] retain];             \
319     [o_popup setFont:[NSFont systemFontOfSize:0]];                              \
320     [o_popup setToolTip: tooltip];                                              \
321 }
322
323 #define ADD_STEPPER( o_stepper, superFrame, x_offset, my_y_offset, tooltip, lower, higher ) \
324 {                                                                               \
325     NSRect s_rc = superFrame;                                                   \
326     s_rc.origin.x = x_offset;                                                   \
327     s_rc.origin.y = my_y_offset;                                                \
328     s_rc.size.height = 23;                                                      \
329     s_rc.size.width = 23;                                                       \
330     o_stepper = [[[NSStepper alloc] initWithFrame: s_rc] retain];               \
331     [o_stepper setFont:[NSFont systemFontOfSize:0]];                            \
332     [o_stepper setToolTip: tooltip];                                            \
333     [o_stepper setMaxValue: higher];                                            \
334     [o_stepper setMinValue: lower];                                             \
335     [o_stepper setTarget: self];                                                \
336     [o_stepper setAction: @selector(stepperChanged:)];                          \
337     [o_stepper sendActionOn:NSLeftMouseUpMask|NSLeftMouseDownMask|NSLeftMouseDraggedMask]; \
338 }
339
340 #define ADD_SLIDER( o_slider, superFrame, x_offset, my_y_offset, my_width, tooltip, lower, higher ) \
341 {                                                                               \
342     NSRect s_rc = superFrame;                                                   \
343     s_rc.origin.x = x_offset;                                                   \
344     s_rc.origin.y = my_y_offset;                                                \
345     s_rc.size.height = 21;                                                      \
346     s_rc.size.width = my_width;                                                 \
347     o_slider = [[[NSSlider alloc] initWithFrame: s_rc] retain];                 \
348     [o_slider setFont:[NSFont systemFontOfSize:0]];                             \
349     [o_slider setToolTip: tooltip];                                             \
350     [o_slider setMaxValue: higher];                                             \
351     [o_slider setMinValue: lower];                                              \
352 }
353
354 #define ADD_CHECKBOX( o_checkbox, superFrame, x_offset, my_y_offset, label, tooltip, init_value, position )    \
355 {                                                                         \
356     NSRect s_rc = superFrame;                                             \
357     s_rc.size.height = 18;                                                \
358     s_rc.origin.x = x_offset - 2;                                         \
359     s_rc.origin.y = superFrame.size.height - 18 + my_y_offset;            \
360     o_checkbox = [[[NSButton alloc] initWithFrame: s_rc] retain];         \
361     [o_checkbox setFont:[NSFont systemFontOfSize:0]];                     \
362     [o_checkbox setButtonType: NSSwitchButton];                           \
363     [o_checkbox setImagePosition: position];                              \
364     [o_checkbox setIntValue: init_value];                                 \
365     [o_checkbox setTitle: label];                                         \
366     [o_checkbox setToolTip: tooltip];                                     \
367     [o_checkbox sizeToFit];                                               \
368 }
369
370 #define ADD_CHECKBOX( o_checkbox, superFrame, x_offset, my_y_offset, label, tooltip, init_value, position )    \
371 {                                                                         \
372     NSRect s_rc = superFrame;                                             \
373     s_rc.size.height = 18;                                                \
374     s_rc.origin.x = x_offset - 2;                                         \
375     s_rc.origin.y = superFrame.size.height - 18 + my_y_offset;            \
376     o_checkbox = [[[NSButton alloc] initWithFrame: s_rc] retain];         \
377     [o_checkbox setFont:[NSFont systemFontOfSize:0]];                     \
378     [o_checkbox setButtonType: NSSwitchButton];                           \
379     [o_checkbox setImagePosition: position];                              \
380     [o_checkbox setIntValue: init_value];                                 \
381     [o_checkbox setTitle: label];                                         \
382     [o_checkbox setToolTip: tooltip];                                     \
383     [o_checkbox sizeToFit];                                               \
384 }
385
386 @implementation VLCConfigControl
387
388 - (id)initWithFrame: (NSRect)frame
389 {
390     return [self initWithFrame: frame
391                     item: nil];
392 }
393
394 - (id)initWithFrame: (NSRect)frame
395         item: (module_config_t *)_p_item
396 {
397     self = [super initWithFrame: frame];
398
399     if( self != nil )
400     {
401         p_item = _p_item;
402         psz_name = strdup( p_item->psz_name );
403         o_label = NULL;
404         i_type = p_item->i_type;
405         b_advanced = p_item->b_advanced;
406         [self setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin ];
407     }
408     return (self);
409 }
410
411 - (void)dealloc
412 {
413     if( o_label ) [o_label release];
414     if( psz_name ) free( psz_name );
415     [super dealloc];
416 }
417
418 + (int)calcVerticalMargin: (int)i_curItem lastItem: (int)i_lastItem
419 {
420     int i_margin;
421     switch( i_curItem )
422     {
423     case CONFIG_ITEM_STRING:
424         switch( i_lastItem )
425         {
426         case CONFIG_ITEM_STRING:
427             i_margin = 8;
428             break;
429         case CONFIG_ITEM_STRING_LIST:
430             i_margin = 7;
431             break;
432         case CONFIG_ITEM_FILE:
433             i_margin = 8;
434             break;
435         case CONFIG_ITEM_MODULE:
436             i_margin = 4;
437             break;
438         case CONFIG_ITEM_INTEGER:
439             i_margin = 7;
440             break;
441         case CONFIG_ITEM_RANGED_INTEGER:
442             i_margin = 5;
443             break;
444         case CONFIG_ITEM_BOOL:
445             i_margin = 7;
446             break;
447         case CONFIG_ITEM_KEY_BEFORE_10_3:
448             i_margin = 7;
449             break;
450         case CONFIG_ITEM_KEY_AFTER_10_3:
451             i_margin = 6;
452             break;
453         case CONFIG_ITEM_MODULE_LIST:
454             i_margin = 8;
455             break;
456         default:
457             i_margin = 20;
458             break;
459         }
460         break;
461     case CONFIG_ITEM_STRING_LIST:
462         switch( i_lastItem )
463         {
464         case CONFIG_ITEM_STRING:
465             i_margin = 8;
466             break;
467         case CONFIG_ITEM_STRING_LIST:
468             i_margin = 7;
469             break;
470         case CONFIG_ITEM_FILE:
471             i_margin = 6;
472             break;
473         case CONFIG_ITEM_MODULE:
474             i_margin = 4;
475             break;
476         case CONFIG_ITEM_INTEGER:
477             i_margin = 7;
478             break;
479         case CONFIG_ITEM_RANGED_INTEGER:
480             i_margin = 5;
481             break;
482         case CONFIG_ITEM_BOOL:
483             i_margin = 7;
484             break;
485         case CONFIG_ITEM_KEY_BEFORE_10_3:
486             i_margin = 7;
487             break;
488         case CONFIG_ITEM_KEY_AFTER_10_3:
489             i_margin = 6;
490             break;
491         case CONFIG_ITEM_MODULE_LIST:
492             i_margin = 8;
493             break;
494         default:
495             i_margin = 20;
496             break;
497         }
498         break;
499     case CONFIG_ITEM_FILE:
500         switch( i_lastItem )
501         {
502         case CONFIG_ITEM_STRING:
503             i_margin = 13;
504             break;
505         case CONFIG_ITEM_STRING_LIST:
506             i_margin = 10;
507             break;
508         case CONFIG_ITEM_FILE:
509             i_margin = 9;
510             break;
511         case CONFIG_ITEM_MODULE:
512             i_margin = 9;
513             break;
514         case CONFIG_ITEM_INTEGER:
515             i_margin = 10;
516             break;
517         case CONFIG_ITEM_RANGED_INTEGER:
518             i_margin = 8;
519             break;
520         case CONFIG_ITEM_BOOL:
521             i_margin = 10;
522             break;
523         case CONFIG_ITEM_KEY_BEFORE_10_3:
524             i_margin = 10;
525             break;
526         case CONFIG_ITEM_KEY_AFTER_10_3:
527             i_margin = 9;
528             break;
529         case CONFIG_ITEM_MODULE_LIST:
530             i_margin = 11;
531             break;
532         default:
533             i_margin = 23;
534             break;
535         }
536         break;
537     case CONFIG_ITEM_MODULE:
538         switch( i_lastItem )
539         {
540         case CONFIG_ITEM_STRING:
541             i_margin = 8;
542             break;
543         case CONFIG_ITEM_STRING_LIST:
544             i_margin = 7;
545             break;
546         case CONFIG_ITEM_FILE:
547             i_margin = 6;
548             break;
549         case CONFIG_ITEM_MODULE:
550             i_margin = 5;
551             break;
552         case CONFIG_ITEM_INTEGER:
553             i_margin = 7;
554             break;
555         case CONFIG_ITEM_RANGED_INTEGER:
556             i_margin = 6;
557             break;
558         case CONFIG_ITEM_BOOL:
559             i_margin = 8;
560             break;
561         case CONFIG_ITEM_KEY_BEFORE_10_3:
562             i_margin = 8;
563             break;
564         case CONFIG_ITEM_KEY_AFTER_10_3:
565             i_margin = 7;
566             break;
567         case CONFIG_ITEM_MODULE_LIST:
568             i_margin = 9;
569             break;
570         default:
571             i_margin = 20;
572             break;
573         }
574         break;
575     case CONFIG_ITEM_INTEGER:
576         switch( i_lastItem )
577         {
578         case CONFIG_ITEM_STRING:
579             i_margin = 8;
580             break;
581         case CONFIG_ITEM_STRING_LIST:
582             i_margin = 7;
583             break;
584         case CONFIG_ITEM_FILE:
585             i_margin = 6;
586             break;
587         case CONFIG_ITEM_MODULE:
588             i_margin = 4;
589             break;
590         case CONFIG_ITEM_INTEGER:
591             i_margin = 7;
592             break;
593         case CONFIG_ITEM_RANGED_INTEGER:
594             i_margin = 5;
595             break;
596         case CONFIG_ITEM_BOOL:
597             i_margin = 7;
598             break;
599         case CONFIG_ITEM_KEY_BEFORE_10_3:
600             i_margin = 7;
601             break;
602         case CONFIG_ITEM_KEY_AFTER_10_3:
603             i_margin = 6;
604             break;
605         case CONFIG_ITEM_MODULE_LIST:
606             i_margin = 8;
607             break;
608         default:
609             i_margin = 20;
610             break;
611         }
612         break;
613     case CONFIG_ITEM_RANGED_INTEGER:
614         switch( i_lastItem )
615         {
616         case CONFIG_ITEM_STRING:
617             i_margin = 8;
618             break;
619         case CONFIG_ITEM_STRING_LIST:
620             i_margin = 7;
621             break;
622         case CONFIG_ITEM_FILE:
623             i_margin = 8;
624             break;
625         case CONFIG_ITEM_MODULE:
626             i_margin = 4;
627             break;
628         case CONFIG_ITEM_INTEGER:
629             i_margin = 7;
630             break;
631         case CONFIG_ITEM_RANGED_INTEGER:
632             i_margin = 5;
633             break;
634         case CONFIG_ITEM_BOOL:
635             i_margin = 7;
636             break;
637         case CONFIG_ITEM_KEY_BEFORE_10_3:
638             i_margin = 7;
639             break;
640         case CONFIG_ITEM_KEY_AFTER_10_3:
641             i_margin = 6;
642             break;
643         case CONFIG_ITEM_MODULE_LIST:
644             i_margin = 8;
645             break;
646         default:
647             i_margin = 20;
648             break;
649         }
650         break;
651     case CONFIG_ITEM_BOOL:
652         switch( i_lastItem )
653         {
654         case CONFIG_ITEM_STRING:
655             i_margin = 6;
656             break;
657         case CONFIG_ITEM_STRING_LIST:
658             i_margin = 5;
659             break;
660         case CONFIG_ITEM_FILE:
661             i_margin = 4;
662             break;
663         case CONFIG_ITEM_MODULE:
664             i_margin = 2;
665             break;
666         case CONFIG_ITEM_INTEGER:
667             i_margin = 5;
668             break;
669         case CONFIG_ITEM_RANGED_INTEGER:
670             i_margin = 3;
671             break;
672         case CONFIG_ITEM_BOOL:
673             i_margin = 3;
674             break;
675         case CONFIG_ITEM_KEY_BEFORE_10_3:
676             i_margin = 3;
677             break;
678         case CONFIG_ITEM_KEY_AFTER_10_3:
679             i_margin = 2;
680             break;
681         case CONFIG_ITEM_MODULE_LIST:
682             i_margin = 6;
683             break;
684         default:
685             i_margin = 18;
686             break;
687         }
688         break;
689     case CONFIG_ITEM_KEY_BEFORE_10_3:
690         switch( i_lastItem )
691         {
692         case CONFIG_ITEM_STRING:
693             i_margin = 6;
694             break;
695         case CONFIG_ITEM_STRING_LIST:
696             i_margin = 5;
697             break;
698         case CONFIG_ITEM_FILE:
699             i_margin = 4;
700             break;
701         case CONFIG_ITEM_MODULE:
702             i_margin = 2;
703             break;
704         case CONFIG_ITEM_INTEGER:
705             i_margin = 5;
706             break;
707         case CONFIG_ITEM_RANGED_INTEGER:
708             i_margin = 3;
709             break;
710         case CONFIG_ITEM_BOOL:
711             i_margin = 3;
712             break;
713         case CONFIG_ITEM_KEY_BEFORE_10_3:
714             i_margin = 10;
715             break;
716         case CONFIG_ITEM_KEY_AFTER_10_3:
717             i_margin = 6;
718             break;
719         case CONFIG_ITEM_MODULE_LIST:
720             i_margin = 6;
721             break;
722         default:
723             i_margin = 18;
724             break;
725         }
726         break;
727     case CONFIG_ITEM_KEY_AFTER_10_3:
728         switch( i_lastItem )
729         {
730         case CONFIG_ITEM_STRING:
731             i_margin = 8;
732             break;
733         case CONFIG_ITEM_STRING_LIST:
734             i_margin = 7;
735             break;
736         case CONFIG_ITEM_FILE:
737             i_margin = 6;
738             break;
739         case CONFIG_ITEM_MODULE:
740             i_margin = 6;
741             break;
742         case CONFIG_ITEM_INTEGER:
743             i_margin = 7;
744             break;
745         case CONFIG_ITEM_RANGED_INTEGER:
746             i_margin = 5;
747             break;
748         case CONFIG_ITEM_BOOL:
749             i_margin = 7;
750             break;
751         case CONFIG_ITEM_KEY_BEFORE_10_3:
752             i_margin = 7;
753             break;
754         case CONFIG_ITEM_KEY_AFTER_10_3:
755             i_margin = 8;
756             break;
757         case CONFIG_ITEM_MODULE_LIST:
758             i_margin = 10;
759             break;
760         default:
761             i_margin = 20;
762             break;
763         }
764         break;
765     case CONFIG_ITEM_MODULE_LIST:
766         switch( i_lastItem )
767         {
768         case CONFIG_ITEM_STRING:
769             i_margin = 10;
770             break;
771         case CONFIG_ITEM_STRING_LIST:
772             i_margin = 7;
773             break;
774         case CONFIG_ITEM_FILE:
775             i_margin = 6;
776             break;
777         case CONFIG_ITEM_MODULE:
778             i_margin = 6;
779             break;
780         case CONFIG_ITEM_INTEGER:
781             i_margin = 9;
782             break;
783         case CONFIG_ITEM_RANGED_INTEGER:
784             i_margin = 5;
785             break;
786         case CONFIG_ITEM_BOOL:
787             i_margin = 7;
788             break;
789         case CONFIG_ITEM_KEY_BEFORE_10_3:
790             i_margin = 7;
791             break;
792         case CONFIG_ITEM_KEY_AFTER_10_3:
793             i_margin = 5;
794             break;
795         case CONFIG_ITEM_MODULE_LIST:
796             i_margin = 8;
797             break;
798         default:
799             i_margin = 20;
800             break;
801         }
802         break;
803     default:
804         i_margin = 20;
805         break;
806     }
807     return i_margin;
808 }
809
810 + (VLCConfigControl *)newControl: (module_config_t *)_p_item
811                       withView: (NSView *)o_parent_view
812                       yOffset:(int) i_yPos
813                       lastItem: (int) i_lastItem
814 {
815     VLCConfigControl *p_control = NULL;
816     switch( _p_item->i_type )
817     {
818     case CONFIG_ITEM_STRING:
819         if( !_p_item->i_list )
820         {
821             p_control = [[StringConfigControl alloc] initWithItem: _p_item
822                     withView: o_parent_view
823                     withVerticalOffset: i_yPos
824                     withLastItem: i_lastItem];
825         }
826         else
827         {
828             p_control = [[StringListConfigControl alloc] initWithItem: _p_item
829                     withView: o_parent_view
830                     withVerticalOffset: i_yPos
831                     withLastItem: i_lastItem];
832         }
833         break;
834     case CONFIG_ITEM_FILE:
835     case CONFIG_ITEM_DIRECTORY:
836         p_control = [[FileConfigControl alloc] initWithItem: _p_item
837                     withView: o_parent_view
838                     withVerticalOffset: i_yPos
839                     withLastItem: i_lastItem];
840         break;
841     case CONFIG_ITEM_MODULE:
842     case CONFIG_ITEM_MODULE_CAT:
843         p_control = [[ModuleConfigControl alloc] initWithItem: _p_item
844                     withView: o_parent_view
845                     withVerticalOffset: i_yPos
846                     withLastItem: i_lastItem];
847         break;
848     case CONFIG_ITEM_INTEGER:
849         if( _p_item->i_list )
850         {
851             p_control = [[IntegerListConfigControl alloc] initWithItem: _p_item
852                         withView: o_parent_view
853                         withVerticalOffset: i_yPos
854                         withLastItem: i_lastItem];
855         }
856         else if( _p_item->i_min != 0 || _p_item->i_max != 0 )
857         {
858             p_control = [[RangedIntegerConfigControl alloc] initWithItem: _p_item
859                         withView: o_parent_view
860                         withVerticalOffset: i_yPos
861                         withLastItem: i_lastItem];
862         }
863         else
864         {
865             p_control = [[IntegerConfigControl alloc] initWithItem: _p_item
866                         withView: o_parent_view
867                         withVerticalOffset: i_yPos
868                         withLastItem: i_lastItem];
869         }
870         break;
871     case CONFIG_ITEM_BOOL:
872         p_control = [[BoolConfigControl alloc] initWithItem: _p_item
873                     withView: o_parent_view
874                     withVerticalOffset: i_yPos
875                     withLastItem: i_lastItem];
876         break;
877     case CONFIG_ITEM_FLOAT:
878         if( _p_item->f_min != 0 || _p_item->f_max != 0 )
879         {
880             p_control = [[RangedFloatConfigControl alloc] initWithItem: _p_item
881                         withView: o_parent_view
882                         withVerticalOffset: i_yPos
883                         withLastItem: i_lastItem];
884         }
885         else
886         {
887             p_control = [[FloatConfigControl alloc] initWithItem: _p_item
888                         withView: o_parent_view
889                         withVerticalOffset: i_yPos
890                         withLastItem: i_lastItem];
891         }
892         break;
893     case CONFIG_ITEM_KEY:
894         if( MACOS_VERSION < 3 )
895         {
896             p_control = [[KeyConfigControlBefore103 alloc] initWithItem: _p_item
897                         withView: o_parent_view
898                         withVerticalOffset: i_yPos
899                         withLastItem: i_lastItem];
900         }
901         else
902         {
903             p_control = [[KeyConfigControlAfter103 alloc] initWithItem: _p_item
904                         withView: o_parent_view
905                         withVerticalOffset: i_yPos
906                         withLastItem: i_lastItem];
907         }
908         break;
909     case CONFIG_ITEM_MODULE_LIST:
910     case CONFIG_ITEM_MODULE_LIST_CAT:
911         p_control = [[ModuleListConfigControl alloc] initWithItem: _p_item
912                     withView: o_parent_view
913                     withVerticalOffset: i_yPos
914                     withLastItem: i_lastItem];
915         break;
916     default:
917         break;
918     }
919     return p_control;
920 }
921
922 - (NSString *)getName
923 {
924     return [[VLCMain sharedInstance] localizedString: psz_name];
925 }
926
927 - (int)getType
928 {
929     return i_type;
930 }
931
932 - (BOOL)isAdvanced
933 {
934     return b_advanced;
935 }
936
937 - (int)intValue
938 {
939     return 0;
940 }
941
942 - (float)floatValue
943 {
944     return 0;
945 }
946
947 - (char *)stringValue
948 {
949     return NULL;
950 }
951
952 - (void)applyChanges
953 {
954     vlc_value_t val;
955     switch( p_item->i_type )
956     {
957     case CONFIG_ITEM_STRING:
958     case CONFIG_ITEM_FILE:
959     case CONFIG_ITEM_DIRECTORY:
960     case CONFIG_ITEM_MODULE:
961     case CONFIG_ITEM_MODULE_LIST:
962     case CONFIG_ITEM_MODULE_LIST_CAT:
963 fprintf( stderr, "Applying %s to %s\n" , [self stringValue], psz_name );
964         config_PutPsz( VLCIntf, psz_name, [self stringValue] );
965         break;
966     case CONFIG_ITEM_KEY:
967         /* So you don't need to restart to have the changes take effect */
968 fprintf( stderr, "Applying %d to %s\n" , [self intValue], psz_name );
969         val.i_int = [self intValue];
970         var_Set( VLCIntf->p_vlc, psz_name, val );
971     case CONFIG_ITEM_INTEGER:
972     case CONFIG_ITEM_BOOL:
973 fprintf( stderr, "Applying %d to %s\n" , [self intValue], psz_name );
974         config_PutInt( VLCIntf, psz_name, [self intValue] );
975         break;
976     case CONFIG_ITEM_FLOAT:
977 fprintf( stderr, "Applying %f to %s\n" , [self floatValue], psz_name );
978         config_PutFloat( VLCIntf, psz_name, [self floatValue] );
979         break;
980     }
981 }
982
983 @end
984
985
986 @implementation StringConfigControl
987
988 - (id) initWithItem: (module_config_t *)_p_item
989            withView: (NSView *)o_parent_view
990            withVerticalOffset: (int)i_yPos
991            withLastItem: (int)i_lastItem
992 {
993     NSRect mainFrame = [o_parent_view frame];
994     NSString *o_labelString, *o_textfieldString, *o_textfieldTooltip;
995     mainFrame.size.height = 22;
996     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
997     mainFrame.origin.x = LEFTMARGIN;
998     mainFrame.origin.y = i_yPos;
999
1000     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1001     {
1002         /* add the label */
1003         if( p_item->psz_text )
1004             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1005         else
1006             o_labelString = [NSString stringWithString:@""];
1007         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
1008         [o_label setAutoresizingMask:NSViewNotSizable ];
1009         [self addSubview: o_label];
1010
1011         /* build the textfield */
1012         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
1013             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1014         if( p_item->psz_value )
1015             o_textfieldString = [[VLCMain sharedInstance] localizedString: p_item->psz_value];
1016         else
1017             o_textfieldString = [NSString stringWithString: @""];
1018         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
1019                         0, mainFrame.size.width - [o_label frame].size.width - 2,
1020                         o_textfieldTooltip, o_textfieldString )
1021         [o_textfield setAutoresizingMask:NSViewWidthSizable ];
1022         [self addSubview: o_textfield];
1023     }
1024     return self;
1025 }
1026
1027 - (void)dealloc
1028 {
1029     [o_label release];
1030     [o_textfield release];
1031     [super dealloc];
1032 }
1033
1034 - (char *)stringValue
1035 {
1036     return strdup( [[VLCMain sharedInstance] delocalizeString:[o_textfield stringValue]] );
1037 }
1038
1039 @end
1040
1041 @implementation StringListConfigControl
1042
1043 - (id) initWithItem: (module_config_t *)_p_item
1044            withView: (NSView *)o_parent_view
1045            withVerticalOffset: (int)i_yPos
1046            withLastItem: (int)i_lastItem
1047 {
1048     NSRect mainFrame = [o_parent_view frame];
1049     NSString *o_labelString, *o_textfieldTooltip;
1050     mainFrame.size.height = 22;
1051     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1052     mainFrame.origin.x = LEFTMARGIN;
1053     mainFrame.origin.y = i_yPos;
1054
1055     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1056     {
1057         int i_index;
1058         /* add the label */
1059         if( p_item->psz_text )
1060             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1061         else
1062             o_labelString = [NSString stringWithString:@""];
1063         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
1064         [o_label setAutoresizingMask:NSViewNotSizable ];
1065         [self addSubview: o_label];
1066
1067         /* build the textfield */
1068         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
1069             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1070         ADD_COMBO( o_combo, mainFrame, [o_label frame].size.width,
1071             -2, 0, o_textfieldTooltip )
1072         [o_combo setAutoresizingMask:NSViewWidthSizable ];
1073         for( i_index = 0; i_index < p_item->i_list; i_index++ )
1074         {
1075             if( p_item->psz_value && !strcmp( p_item->psz_value, p_item->ppsz_list[i_index] ) )
1076             {
1077                 [o_combo selectItemAtIndex: i_index];
1078             }
1079         }
1080         [self addSubview: o_combo];
1081     }
1082     return self;
1083 }
1084
1085 - (void)dealloc
1086 {
1087     [o_combo release];
1088     [super dealloc];
1089 }
1090
1091 - (char *)stringValue
1092 {
1093     if( [o_combo indexOfSelectedItem] >= 0 )
1094         return strdup( p_item->ppsz_list[[o_combo indexOfSelectedItem]] );
1095     else
1096         return strdup( [[VLCMain sharedInstance] delocalizeString: [o_combo stringValue]] );
1097 }
1098
1099 @end
1100
1101 @implementation StringListConfigControl (NSComboBoxDataSource)
1102
1103 - (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox
1104 {
1105         return p_item->i_list;
1106 }
1107
1108 - (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)i_index
1109 {
1110     if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
1111     {
1112         return [[VLCMain sharedInstance] localizedString: p_item->ppsz_list_text[i_index]];
1113     } else return [[VLCMain sharedInstance] localizedString: p_item->ppsz_list[i_index]];
1114 }
1115
1116 @end
1117
1118 @implementation FileConfigControl
1119
1120 - (id) initWithItem: (module_config_t *)_p_item
1121            withView: (NSView *)o_parent_view
1122            withVerticalOffset: (int)i_yPos
1123            withLastItem: (int)i_lastItem
1124 {
1125     NSRect mainFrame = [o_parent_view frame];
1126     NSString *o_labelString, *o_buttonTooltip, *o_textfieldString, *o_textfieldTooltip;
1127     mainFrame.size.height = 46;
1128     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1129     mainFrame.origin.x = LEFTMARGIN;
1130     mainFrame.origin.y = i_yPos;
1131
1132     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1133     {
1134         /* is it a directory */
1135         b_directory = ( [self getType] == CONFIG_ITEM_DIRECTORY ) ? YES : NO;
1136
1137         /* add the label */
1138         if( p_item->psz_text )
1139             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1140         else
1141             o_labelString = [NSString stringWithString:@""];
1142         ADD_LABEL( o_label, mainFrame, 0, 3, o_labelString )
1143         [o_label setAutoresizingMask:NSViewNotSizable ];
1144         [self addSubview: o_label];
1145
1146         /* build the button */
1147         o_buttonTooltip = [[VLCMain sharedInstance] wrapString:
1148             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1149         ADD_RIGHT_BUTTON( o_button, mainFrame, 0, 0, o_buttonTooltip, _NS("Browse...") )
1150         [o_button setAutoresizingMask:NSViewMinXMargin ];
1151         [self addSubview: o_button];
1152
1153         /* build the textfield */
1154         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
1155             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1156         if( p_item->psz_value )
1157             o_textfieldString = [[VLCMain sharedInstance] localizedString: p_item->psz_value];
1158         else
1159             o_textfieldString = [NSString stringWithString: @""];
1160         ADD_TEXTFIELD( o_textfield, mainFrame, 12,
1161                         2, mainFrame.size.width - 8 - [o_button frame].size.width,
1162                         o_textfieldTooltip, o_textfieldString )
1163         [o_textfield setAutoresizingMask:NSViewWidthSizable ];
1164         [self addSubview: o_textfield];
1165     }
1166     return self;
1167 }
1168
1169 - (void)dealloc
1170 {
1171     [o_textfield release];
1172     [o_button release];
1173     [super dealloc];
1174 }
1175
1176 - (IBAction)openFileDialog: (id)sender
1177 {
1178     NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
1179     
1180     [o_open_panel setTitle: (b_directory)?_NS("Select a directory"):_NS("Select a file")];
1181     [o_open_panel setPrompt: _NS("Select")];
1182     [o_open_panel setAllowsMultipleSelection: NO];
1183     [o_open_panel setCanChooseFiles: !b_directory];
1184     [o_open_panel setCanChooseDirectories: b_directory];
1185     [o_open_panel beginSheetForDirectory:nil
1186         file:nil
1187         types:nil
1188         modalForWindow:[sender window]
1189         modalDelegate: self
1190         didEndSelector: @selector(pathChosenInPanel: 
1191                         withReturn:
1192                         contextInfo:)
1193         contextInfo: nil];
1194 }
1195
1196 - (void)pathChosenInPanel:(NSOpenPanel *)o_sheet withReturn:(int)i_return_code contextInfo:(void  *)o_context_info
1197 {
1198     if( i_return_code == NSOKButton )
1199     {
1200         NSString *o_path = [[o_sheet filenames] objectAtIndex: 0];
1201         [o_textfield setStringValue: o_path];
1202     }
1203 }
1204
1205 - (char *)stringValue
1206 {
1207     if( [[o_textfield stringValue] length] != 0)
1208         return strdup( [[o_textfield stringValue] fileSystemRepresentation] );
1209     else
1210         return NULL;
1211 }
1212
1213 @end
1214
1215 @implementation ModuleConfigControl
1216
1217 - (id) initWithItem: (module_config_t *)_p_item
1218            withView: (NSView *)o_parent_view
1219            withVerticalOffset: (int)i_yPos
1220            withLastItem: (int)i_lastItem
1221 {
1222     NSRect mainFrame = [o_parent_view frame];
1223     NSString *o_labelString, *o_popupTooltip;
1224     mainFrame.size.height = 22;
1225     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1226     mainFrame.origin.x = LEFTMARGIN;
1227     mainFrame.origin.y = i_yPos;
1228
1229     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1230     {
1231         int i_index;
1232         vlc_list_t *p_list;
1233         module_t *p_parser;
1234         /* add the label */
1235         if( p_item->psz_text )
1236             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1237         else
1238             o_labelString = [NSString stringWithString:@""];
1239         ADD_LABEL( o_label, mainFrame, 0, -1, o_labelString )
1240         [o_label setAutoresizingMask:NSViewNotSizable ];
1241         [self addSubview: o_label];
1242
1243         /* build the popup */
1244         o_popupTooltip = [[VLCMain sharedInstance] wrapString:
1245             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1246         ADD_POPUP( o_popup, mainFrame, [o_label frame].size.width,
1247             -2, 0, o_popupTooltip )
1248         [o_popup setAutoresizingMask:NSViewWidthSizable ];
1249         [o_popup addItemWithTitle: _NS("Default")];
1250         [[o_popup lastItem] setTag: -1];
1251         [o_popup selectItem: [o_popup lastItem]];
1252         
1253         /* build a list of available modules */
1254         p_list = vlc_list_find( VLCIntf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1255         for( i_index = 0; i_index < p_list->i_count; i_index++ )
1256         {
1257             p_parser = (module_t *)p_list->p_values[i_index].p_object ;
1258             if( p_item->i_type == CONFIG_ITEM_MODULE )
1259             {
1260                 if( !strcmp( p_parser->psz_capability,
1261                             p_item->psz_type ) )
1262                 {
1263                     NSString *o_description = [[VLCMain sharedInstance]
1264                         localizedString: p_parser->psz_longname];
1265                     [o_popup addItemWithTitle: o_description];
1266
1267                     if( p_item->psz_value &&
1268                         !strcmp( p_item->psz_value, p_parser->psz_object_name ) )
1269                     {
1270                         [o_popup selectItem:[o_popup lastItem]];
1271                     }
1272                 }
1273             }
1274             else
1275             {
1276                 module_config_t *p_config;
1277                 if( !strcmp( p_parser->psz_object_name, "main" ) )
1278                       continue;
1279
1280                 p_config = p_parser->p_config;
1281                 if( p_config ) do
1282                 {
1283                     /* Hack: required subcategory is stored in i_min */
1284                     if( p_config->i_type == CONFIG_SUBCATEGORY &&
1285                         p_config->i_value == p_item->i_min )
1286                     {
1287                         NSString *o_description = [[VLCMain sharedInstance]
1288                             localizedString: p_parser->psz_longname];
1289                         [o_popup addItemWithTitle: o_description];
1290                         
1291                         if( p_item->psz_value && !strcmp(p_item->psz_value,
1292                                                 p_parser->psz_object_name) )
1293                             [o_popup selectItem:[o_popup lastItem]];
1294                     }
1295                 } while( p_config->i_type != CONFIG_HINT_END && p_config++ );
1296             }
1297         }
1298         vlc_list_release( p_list );
1299         [self addSubview: o_popup];
1300     }
1301     return self;
1302 }
1303
1304 - (void)dealloc
1305 {
1306     [o_popup release];
1307     [super dealloc];
1308 }
1309
1310 - (char *)stringValue
1311 {
1312     NSString *newval = [o_popup titleOfSelectedItem];
1313     char *returnval = NULL;
1314     int i_index;
1315     vlc_list_t *p_list;
1316     module_t *p_parser;
1317
1318     p_list = vlc_list_find( VLCIntf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
1319     for( i_index = 0; i_index < p_list->i_count; i_index++ )
1320     {
1321         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
1322         if( p_item->i_type == CONFIG_ITEM_MODULE )
1323         {
1324             if( !strcmp( p_parser->psz_capability,
1325                     p_item->psz_type ) )
1326             {
1327                 NSString *o_description = [[VLCMain sharedInstance]
1328                     localizedString: p_parser->psz_longname];
1329                 if( [newval isEqualToString: o_description] )
1330                 {
1331                     returnval = strdup(p_parser->psz_object_name);
1332                     break;
1333                 }
1334             }
1335         }
1336         else
1337         {
1338             module_config_t *p_config;
1339             if( !strcmp( p_parser->psz_object_name, "main" ) )
1340                   continue;
1341
1342             p_config = p_parser->p_config;
1343             if( p_config ) do
1344             {
1345                 /* Hack: required subcategory is stored in i_min */
1346                 if( p_config->i_type == CONFIG_SUBCATEGORY &&
1347                     p_config->i_value == p_item->i_min )
1348                 {
1349                     NSString *o_description = [[VLCMain sharedInstance]
1350                         localizedString: p_parser->psz_longname];
1351                     if( [newval isEqualToString: o_description] )
1352                     {
1353                         returnval = strdup(p_parser->psz_object_name);
1354                         break;
1355                     }
1356                 }
1357             } while( p_config->i_type != CONFIG_HINT_END && p_config++ );
1358         }
1359     }
1360     vlc_list_release( p_list );
1361     return returnval;
1362 }
1363
1364 @end
1365
1366 @implementation IntegerConfigControl
1367
1368 - (id) initWithItem: (module_config_t *)_p_item
1369            withView: (NSView *)o_parent_view
1370            withVerticalOffset: (int)i_yPos
1371            withLastItem: (int)i_lastItem
1372 {
1373     NSRect mainFrame = [o_parent_view frame];
1374     NSString *o_labelString, *o_tooltip, *o_textfieldString;
1375     mainFrame.size.height = 23;
1376     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1377     mainFrame.origin.x = LEFTMARGIN;
1378     mainFrame.origin.y = i_yPos;
1379
1380     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1381     {
1382         o_tooltip = [[VLCMain sharedInstance] wrapString:
1383             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1384
1385         /* add the label */
1386         if( p_item->psz_text )
1387             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1388         else
1389             o_labelString = [NSString stringWithString:@""];
1390         ADD_LABEL( o_label, mainFrame, 0, -2, o_labelString )
1391         [o_label setAutoresizingMask:NSViewNotSizable ];
1392         [self addSubview: o_label];
1393
1394         /* build the stepper */
1395         ADD_STEPPER( o_stepper, mainFrame, mainFrame.size.width - 19,
1396             0, o_tooltip, -1600, 1600)
1397         [o_stepper setIntValue: p_item->i_value];
1398         [o_stepper setAutoresizingMask:NSViewMinXMargin ];
1399         [self addSubview: o_stepper];
1400
1401         /* build the textfield */
1402         if( p_item->psz_value )
1403             o_textfieldString = [[VLCMain sharedInstance] localizedString: p_item->psz_value];
1404         else
1405             o_textfieldString = [NSString stringWithString: @""];
1406         ADD_TEXTFIELD( o_textfield, mainFrame, mainFrame.size.width - 19 - 52,
1407             1, 49, o_tooltip, @"" )
1408         [o_textfield setIntValue: p_item->i_value];
1409         [o_textfield setDelegate: self];
1410         [[NSNotificationCenter defaultCenter] addObserver: self
1411             selector: @selector(textfieldChanged:)
1412             name: NSControlTextDidChangeNotification
1413             object: o_textfield];
1414         [o_textfield setAutoresizingMask:NSViewMinXMargin ];
1415         [self addSubview: o_textfield];
1416     }
1417     return self;
1418 }
1419
1420 - (void)dealloc
1421 {
1422     [o_stepper release];
1423     [o_textfield release];
1424     [super dealloc];
1425 }
1426
1427 - (IBAction)stepperChanged:(id)sender
1428 {
1429     [o_textfield setIntValue: [o_stepper intValue]];
1430 }
1431
1432 - (void)textfieldChanged:(NSNotification *)o_notification
1433 {
1434     [o_stepper setIntValue: [o_textfield intValue]];
1435 }
1436
1437 - (int)intValue
1438 {
1439     return [o_textfield intValue];
1440 }
1441
1442 @end
1443
1444 @implementation IntegerListConfigControl
1445
1446 - (id) initWithItem: (module_config_t *)_p_item
1447            withView: (NSView *)o_parent_view
1448            withVerticalOffset: (int)i_yPos
1449            withLastItem: (int)i_lastItem
1450 {
1451     NSRect mainFrame = [o_parent_view frame];
1452     NSString *o_labelString, *o_textfieldTooltip;
1453     mainFrame.size.height = 22;
1454     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1455     mainFrame.origin.x = LEFTMARGIN;
1456     mainFrame.origin.y = i_yPos;
1457
1458     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1459     {
1460         int i_index;
1461         /* add the label */
1462         if( p_item->psz_text )
1463             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1464         else
1465             o_labelString = [NSString stringWithString:@""];
1466         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
1467         [o_label setAutoresizingMask:NSViewNotSizable ];
1468         [self addSubview: o_label];
1469
1470         /* build the textfield */
1471         o_textfieldTooltip = [[VLCMain sharedInstance] wrapString:
1472             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1473         ADD_COMBO( o_combo, mainFrame, [o_label frame].size.width,
1474             -2, 0, o_textfieldTooltip )
1475         [o_combo setAutoresizingMask:NSViewWidthSizable ];
1476         for( i_index = 0; i_index < p_item->i_list; i_index++ )
1477         {
1478             if( p_item->i_value == p_item->pi_list[i_index] )
1479             {
1480                 [o_combo selectItemAtIndex: i_index];
1481             }
1482         }
1483         [self addSubview: o_combo];
1484     }
1485     return self;
1486 }
1487
1488 - (void)dealloc
1489 {
1490     [o_combo release];
1491     [super dealloc];
1492 }
1493
1494 - (int)intValue
1495 {
1496     if( [o_combo indexOfSelectedItem] >= 0 )
1497         return p_item->pi_list[[o_combo indexOfSelectedItem]];
1498     else
1499         return [o_combo intValue];
1500 }
1501
1502 @end
1503
1504 @implementation IntegerListConfigControl (NSComboBoxDataSource)
1505
1506 - (int)numberOfItemsInComboBox:(NSComboBox *)aComboBox
1507 {
1508     return p_item->i_list;
1509 }
1510
1511 - (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(int)i_index
1512 {
1513     if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
1514     {
1515         return [[VLCMain sharedInstance] localizedString: p_item->ppsz_list_text[i_index]];
1516     } else return [NSString stringWithFormat: @"%i", p_item->pi_list[i_index]];
1517 }
1518
1519 @end
1520
1521 @implementation RangedIntegerConfigControl
1522
1523 - (id) initWithItem: (module_config_t *)_p_item
1524            withView: (NSView *)o_parent_view
1525            withVerticalOffset: (int)i_yPos
1526            withLastItem: (int)i_lastItem
1527 {
1528     NSRect mainFrame = [o_parent_view frame];
1529     NSString *o_labelString, *o_tooltip;
1530     mainFrame.size.height = 50;
1531     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1532     mainFrame.origin.x = LEFTMARGIN;
1533     mainFrame.origin.y = i_yPos;
1534
1535     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1536     {
1537         /* add the label */
1538         if( p_item->psz_text )
1539             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1540         else
1541             o_labelString = [NSString stringWithString:@""];
1542         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
1543         [o_label setAutoresizingMask:NSViewNotSizable ];
1544         [self addSubview: o_label];
1545
1546         /* build the textfield */
1547         o_tooltip = [[VLCMain sharedInstance] wrapString:
1548             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1549         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
1550             28, 49, o_tooltip, @"" )
1551         [o_textfield setIntValue: p_item->i_value];
1552         [o_textfield setAutoresizingMask:NSViewMaxXMargin ];
1553         [o_textfield setDelegate: self];
1554         [[NSNotificationCenter defaultCenter] addObserver: self
1555             selector: @selector(textfieldChanged:)
1556             name: NSControlTextDidChangeNotification
1557             object: o_textfield];
1558         [self addSubview: o_textfield];
1559
1560         /* build the mintextfield */
1561         ADD_LABEL( o_textfield_min, mainFrame, 12, -30, @"-8888" )
1562         [o_textfield_min setIntValue: p_item->i_min];
1563         [o_textfield_min setAutoresizingMask:NSViewMaxXMargin ];
1564         [self addSubview: o_textfield_min];
1565
1566         /* build the maxtextfield */
1567         ADD_LABEL( o_textfield_max, mainFrame, mainFrame.size.width - 31, -30, @"8888" )
1568         [o_textfield_max setIntValue: p_item->i_max];
1569         [o_textfield_max setAutoresizingMask:NSViewMinXMargin ];
1570         [self addSubview: o_textfield_max];
1571
1572         /* build the slider */
1573         ADD_SLIDER( o_slider, mainFrame, [o_textfield_min frame].origin.x + [o_textfield_min frame].size.width + 6,
1574             -1, mainFrame.size.width - [o_textfield_max frame].size.width - [o_textfield_max frame].size.width - 14
1575             - [o_textfield_min frame].origin.x, o_tooltip, p_item->i_min, p_item->i_max )
1576         [o_slider setIntValue: p_item->i_value];
1577         [o_slider setAutoresizingMask:NSViewWidthSizable ];
1578         [o_slider setTarget: self];
1579         [o_slider setAction: @selector(sliderChanged:)];
1580         [o_slider sendActionOn:NSLeftMouseUpMask|NSLeftMouseDownMask|NSLeftMouseDraggedMask];
1581         [self addSubview: o_slider];
1582
1583     }
1584     return self;
1585 }
1586
1587 - (void)dealloc
1588 {
1589     [o_textfield release];
1590     [o_textfield_min release];
1591     [o_textfield_max release];
1592     [o_slider release];
1593     [super dealloc];
1594 }
1595
1596 - (IBAction)sliderChanged:(id)sender
1597 {
1598     [o_textfield setIntValue: [o_slider intValue]];
1599 }
1600
1601 - (void)textfieldChanged:(NSNotification *)o_notification
1602 {
1603     [o_slider setIntValue: [o_textfield intValue]];
1604 }
1605
1606 - (int)intValue
1607 {
1608     return [o_slider intValue];
1609 }
1610
1611 @end
1612
1613 @implementation FloatConfigControl
1614
1615 - (id) initWithItem: (module_config_t *)_p_item
1616            withView: (NSView *)o_parent_view
1617            withVerticalOffset: (int)i_yPos
1618            withLastItem: (int)i_lastItem
1619 {
1620     NSRect mainFrame = [o_parent_view frame];
1621     NSString *o_labelString, *o_tooltip, *o_textfieldString;
1622     mainFrame.size.height = 23;
1623     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1624     mainFrame.origin.x = LEFTMARGIN;
1625     mainFrame.origin.y = i_yPos;
1626
1627     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1628     {
1629         o_tooltip = [[VLCMain sharedInstance] wrapString:
1630             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1631
1632         /* add the label */
1633         if( p_item->psz_text )
1634             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1635         else
1636             o_labelString = [NSString stringWithString:@""];
1637         ADD_LABEL( o_label, mainFrame, 0, -2, o_labelString )
1638         [o_label setAutoresizingMask:NSViewNotSizable ];
1639         [self addSubview: o_label];
1640
1641         /* build the stepper */
1642         ADD_STEPPER( o_stepper, mainFrame, mainFrame.size.width - 19,
1643             0, o_tooltip, -1600, 1600)
1644         [o_stepper setFloatValue: p_item->f_value];
1645         [o_stepper setAutoresizingMask:NSViewMinXMargin ];
1646         [self addSubview: o_stepper];
1647
1648         /* build the textfield */
1649         if( p_item->psz_value )
1650             o_textfieldString = [[VLCMain sharedInstance] localizedString: p_item->psz_value];
1651         else
1652             o_textfieldString = [NSString stringWithString: @""];
1653         ADD_TEXTFIELD( o_textfield, mainFrame, mainFrame.size.width - 19 - 52,
1654             1, 49, o_tooltip, @"" )
1655         [o_textfield setFloatValue: p_item->f_value];
1656         [o_textfield setDelegate: self];
1657         [[NSNotificationCenter defaultCenter] addObserver: self
1658             selector: @selector(textfieldChanged:)
1659             name: NSControlTextDidChangeNotification
1660             object: o_textfield];
1661         [o_textfield setAutoresizingMask:NSViewMinXMargin ];
1662         [self addSubview: o_textfield];
1663     }
1664     return self;
1665 }
1666
1667 - (void)dealloc
1668 {
1669     [o_stepper release];
1670     [o_textfield release];
1671     [super dealloc];
1672 }
1673
1674 - (IBAction)stepperChanged:(id)sender
1675 {
1676     [o_textfield setFloatValue: [o_stepper floatValue]];
1677 }
1678
1679 - (void)textfieldChanged:(NSNotification *)o_notification
1680 {
1681     [o_stepper setFloatValue: [o_textfield floatValue]];
1682 }
1683
1684 - (int)floatValue
1685 {
1686     return [o_stepper floatValue];
1687 }
1688
1689 @end
1690
1691 @implementation RangedFloatConfigControl
1692
1693 - (id) initWithItem: (module_config_t *)_p_item
1694            withView: (NSView *)o_parent_view
1695            withVerticalOffset: (int)i_yPos
1696            withLastItem: (int)i_lastItem
1697 {
1698     NSRect mainFrame = [o_parent_view frame];
1699     NSString *o_labelString, *o_tooltip;
1700     mainFrame.size.height = 50;
1701     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1702     mainFrame.origin.x = LEFTMARGIN;
1703     mainFrame.origin.y = i_yPos;
1704
1705     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1706     {
1707         /* add the label */
1708         if( p_item->psz_text )
1709             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1710         else
1711             o_labelString = [NSString stringWithString:@""];
1712         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
1713         [o_label setAutoresizingMask:NSViewNotSizable ];
1714         [self addSubview: o_label];
1715
1716         /* build the textfield */
1717         o_tooltip = [[VLCMain sharedInstance] wrapString:
1718             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1719         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
1720             28, 49, o_tooltip, @"" )
1721         [o_textfield setFloatValue: p_item->f_value];
1722         [o_textfield setAutoresizingMask:NSViewMaxXMargin ];
1723         [o_textfield setDelegate: self];
1724         [[NSNotificationCenter defaultCenter] addObserver: self
1725             selector: @selector(textfieldChanged:)
1726             name: NSControlTextDidChangeNotification
1727             object: o_textfield];
1728         [self addSubview: o_textfield];
1729
1730         /* build the mintextfield */
1731         ADD_LABEL( o_textfield_min, mainFrame, 12, -30, @"-8888" )
1732         [o_textfield_min setFloatValue: p_item->f_min];
1733         [o_textfield_min setAutoresizingMask:NSViewMaxXMargin ];
1734         [self addSubview: o_textfield_min];
1735
1736         /* build the maxtextfield */
1737         ADD_LABEL( o_textfield_max, mainFrame, mainFrame.size.width - 31, -30, @"8888" )
1738         [o_textfield_max setFloatValue: p_item->f_max];
1739         [o_textfield_max setAutoresizingMask:NSViewMinXMargin ];
1740         [self addSubview: o_textfield_max];
1741
1742         /* build the slider */
1743         ADD_SLIDER( o_slider, mainFrame, [o_textfield_min frame].origin.x + [o_textfield_min frame].size.width + 6,
1744             -1, mainFrame.size.width - [o_textfield_max frame].size.width - [o_textfield_max frame].size.width - 14
1745             - [o_textfield_min frame].origin.x, o_tooltip, p_item->f_min, p_item->f_max )
1746         [o_slider setFloatValue: p_item->f_value];
1747         [o_slider setAutoresizingMask:NSViewWidthSizable ];
1748         [o_slider setTarget: self];
1749         [o_slider setAction: @selector(sliderChanged:)];
1750         [o_slider sendActionOn:NSLeftMouseUpMask|NSLeftMouseDownMask|NSLeftMouseDraggedMask];
1751         [self addSubview: o_slider];
1752
1753     }
1754     return self;
1755 }
1756
1757 - (void)dealloc
1758 {
1759     [o_textfield release];
1760     [o_textfield_min release];
1761     [o_textfield_max release];
1762     [o_slider release];
1763     [super dealloc];
1764 }
1765
1766 - (IBAction)sliderChanged:(id)sender
1767 {
1768     [o_textfield setFloatValue: [o_slider floatValue]];
1769 }
1770
1771 - (void)textfieldChanged:(NSNotification *)o_notification
1772 {
1773     [o_slider setFloatValue: [o_textfield floatValue]];
1774 }
1775
1776 - (int)floatValue
1777 {
1778     return [o_slider floatValue];
1779 }
1780
1781 @end
1782
1783 @implementation BoolConfigControl
1784
1785 - (id) initWithItem: (module_config_t *)_p_item
1786            withView: (NSView *)o_parent_view
1787            withVerticalOffset: (int)i_yPos
1788            withLastItem: (int)i_lastItem
1789 {
1790     NSRect mainFrame = [o_parent_view frame];
1791     NSString *o_labelString, *o_tooltip;
1792     mainFrame.size.height = 17;
1793     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
1794     mainFrame.origin.x = LEFTMARGIN;
1795     mainFrame.origin.y = i_yPos;
1796
1797     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1798     {
1799         /* add the checkbox */
1800         if( p_item->psz_text )
1801             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1802         else
1803             o_labelString = [NSString stringWithString:@""];
1804         o_tooltip = [[VLCMain sharedInstance] wrapString:
1805             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1806         ADD_CHECKBOX( o_checkbox, mainFrame, 0, 0, o_labelString, o_tooltip, p_item->i_value, NSImageRight)
1807         [o_checkbox setAutoresizingMask:NSViewNotSizable ];
1808         [self addSubview: o_checkbox];
1809     }
1810     return self;
1811 }
1812
1813 - (void)dealloc
1814 {
1815     [o_checkbox release];
1816     [super dealloc];
1817 }
1818
1819 - (int)intValue
1820 {
1821     return [o_checkbox intValue];
1822 }
1823
1824 @end
1825
1826 @implementation KeyConfigControlBefore103
1827
1828 - (id) initWithItem: (module_config_t *)_p_item
1829            withView: (NSView *)o_parent_view
1830            withVerticalOffset: (int)i_yPos
1831            withLastItem: (int)i_lastItem
1832 {
1833     NSRect mainFrame = [o_parent_view frame];
1834     NSString *o_labelString, *o_tooltip;
1835     mainFrame.size.height = 37;
1836     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1837     mainFrame.origin.x = LEFTMARGIN;
1838     mainFrame.origin.y = i_yPos;
1839
1840     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1841     {
1842         /* add the label */
1843         if( p_item->psz_text )
1844             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1845         else
1846             o_labelString = [NSString stringWithString:@""];
1847         ADD_LABEL( o_label, mainFrame, 0, -10, o_labelString )
1848         [o_label setAutoresizingMask:NSViewNotSizable ];
1849         [self addSubview: o_label];
1850
1851         /* add the checkboxes */
1852         o_tooltip = [[VLCMain sharedInstance] wrapString:
1853             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1854         ADD_CHECKBOX( o_cmd_checkbox, mainFrame,
1855             [o_label frame].size.width + 2, 0,
1856             [NSString stringWithUTF8String:PLACE_OF_INTEREST_SIGN],
1857             o_tooltip, ((((unsigned int)p_item->i_value) & KEY_MODIFIER_COMMAND)?YES:NO), NSImageLeft )
1858         [o_cmd_checkbox setState: p_item->i_value & KEY_MODIFIER_COMMAND];
1859         ADD_CHECKBOX( o_ctrl_checkbox, mainFrame,
1860             [o_cmd_checkbox frame].size.width + [o_cmd_checkbox frame].origin.x + 6, 0,
1861             [NSString stringWithUTF8String:UP_ARROWHEAD],
1862             o_tooltip, ((((unsigned int)p_item->i_value) & KEY_MODIFIER_CTRL)?YES:NO), NSImageLeft )
1863         [o_ctrl_checkbox setState: p_item->i_value & KEY_MODIFIER_CTRL];
1864         ADD_CHECKBOX( o_alt_checkbox, mainFrame,
1865             [o_label frame].size.width + 2, -2 - [o_cmd_checkbox frame].size.height,
1866             [NSString stringWithUTF8String:OPTION_KEY],
1867             o_tooltip, ((((unsigned int)p_item->i_value) & KEY_MODIFIER_ALT)?YES:NO), NSImageLeft )
1868         [o_alt_checkbox setState: p_item->i_value & KEY_MODIFIER_ALT];
1869         ADD_CHECKBOX( o_shift_checkbox, mainFrame,
1870             [o_cmd_checkbox frame].size.width + [o_cmd_checkbox frame].origin.x + 6,
1871             -2 - [o_cmd_checkbox frame].size.height,
1872             [NSString stringWithUTF8String:UPWARDS_WHITE_ARROW],
1873             o_tooltip, ((((unsigned int)p_item->i_value) & KEY_MODIFIER_SHIFT)?YES:NO), NSImageLeft )
1874         [o_shift_checkbox setState: p_item->i_value & KEY_MODIFIER_SHIFT];
1875         [self addSubview: o_cmd_checkbox];
1876         [self addSubview: o_ctrl_checkbox];
1877         [self addSubview: o_alt_checkbox];
1878         [self addSubview: o_shift_checkbox];
1879
1880         /* build the popup */
1881         ADD_POPUP( o_popup, mainFrame, [o_shift_checkbox frame].origin.x + [o_shift_checkbox frame].size.width + 4,
1882             4, 0, o_tooltip )
1883         [o_popup setAutoresizingMask:NSViewWidthSizable ];
1884     
1885         if( o_keys_menu == nil )
1886         {
1887             unsigned int i;
1888             o_keys_menu = [[NSMenu alloc] initWithTitle: @"Keys Menu"];
1889             for ( i = 0; i < sizeof(vlc_keys) / sizeof(key_descriptor_t); i++)
1890                 if( vlc_keys[i].psz_key_string && *vlc_keys[i].psz_key_string )
1891                     POPULATE_A_KEY( o_keys_menu, [NSString stringWithCString:vlc_keys[i].psz_key_string]
1892                                      , vlc_keys[i].i_key_code)
1893         }
1894         [o_popup setMenu:[o_keys_menu copyWithZone:nil]];
1895         [o_popup selectItemWithTitle: [[VLCMain sharedInstance] localizedString:KeyToString(( ((unsigned int)p_item->i_value) & ~KEY_MODIFIER ))]];
1896         [self addSubview: o_popup];
1897
1898     }
1899     return self;
1900 }
1901
1902 - (void)dealloc
1903 {
1904     [o_cmd_checkbox release];
1905     [o_ctrl_checkbox release];
1906     [o_alt_checkbox release];
1907     [o_shift_checkbox release];
1908     [o_popup release];
1909     [super dealloc];
1910 }
1911
1912 - (int)intValue
1913 {
1914     unsigned int i_new_key = 0;
1915
1916     i_new_key |= ([o_cmd_checkbox state] == NSOnState) ? KEY_MODIFIER_COMMAND : 0;
1917     i_new_key |= ([o_ctrl_checkbox state] == NSOnState) ? KEY_MODIFIER_CTRL : 0;
1918     i_new_key |= ([o_alt_checkbox state] == NSOnState) ? KEY_MODIFIER_ALT : 0;
1919     i_new_key |= ([o_shift_checkbox state] == NSOnState) ? KEY_MODIFIER_SHIFT : 0;
1920
1921     i_new_key |= StringToKey([[[o_popup selectedItem] title] cString]);
1922     return i_new_key;
1923 }
1924
1925 @end
1926
1927 @implementation KeyConfigControlAfter103
1928
1929 - (id) initWithItem: (module_config_t *)_p_item
1930            withView: (NSView *)o_parent_view
1931            withVerticalOffset: (int)i_yPos
1932            withLastItem: (int)i_lastItem
1933 {
1934     NSRect mainFrame = [o_parent_view frame];
1935     NSString *o_labelString, *o_tooltip;
1936     mainFrame.size.height = 22;
1937     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN + 1;
1938     mainFrame.origin.x = LEFTMARGIN;
1939     mainFrame.origin.y = i_yPos;
1940
1941     if( [super initWithFrame: mainFrame item: _p_item] != nil )
1942     {
1943         /* add the label */
1944         if( p_item->psz_text )
1945             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
1946         else
1947             o_labelString = [NSString stringWithString:@""];
1948         ADD_LABEL( o_label, mainFrame, 0, -1, o_labelString )
1949         [o_label setAutoresizingMask:NSViewNotSizable ];
1950         [self addSubview: o_label];
1951
1952         /* build the popup */
1953         o_tooltip = [[VLCMain sharedInstance] wrapString:
1954             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
1955         ADD_POPUP( o_popup, mainFrame, [o_label frame].origin.x + [o_label frame].size.width + 3,
1956             -2, 0, o_tooltip )
1957         [o_popup setAutoresizingMask:NSViewWidthSizable ];
1958     
1959         if( o_keys_menu == nil )
1960         {
1961             unsigned int i;
1962             o_keys_menu = [[NSMenu alloc] initWithTitle: @"Keys Menu"];
1963             for ( i = 0; i < sizeof(vlc_keys) / sizeof(key_descriptor_t); i++)
1964                 if( vlc_keys[i].psz_key_string && *vlc_keys[i].psz_key_string )
1965                     POPULATE_A_KEY( o_keys_menu, [NSString stringWithCString:vlc_keys[i].psz_key_string]
1966                                      , vlc_keys[i].i_key_code)
1967         }
1968         [o_popup setMenu:[o_keys_menu copyWithZone:nil]];
1969         [o_popup selectItemWithTag: p_item->i_value];
1970         [self addSubview: o_popup];
1971
1972     }
1973     return self;
1974 }
1975
1976 - (void)dealloc
1977 {
1978     [o_popup release];
1979     [super dealloc];
1980 }
1981
1982 - (int)intValue
1983 {
1984     return [o_popup selectedTag];
1985 }
1986
1987 @end
1988
1989 @implementation ModuleListConfigControl
1990
1991 - (id) initWithItem: (module_config_t *)_p_item
1992            withView: (NSView *)o_parent_view
1993            withVerticalOffset: (int)i_yPos
1994            withLastItem: (int)i_lastItem
1995 {
1996 if( _p_item->i_type == CONFIG_ITEM_MODULE_LIST )
1997 //TODO....
1998         return nil;
1999
2000 //Fill our array to know how may items we have...
2001     vlc_list_t *p_list;
2002     module_t *p_parser;
2003     int i_index;
2004     NSRect mainFrame = [o_parent_view frame];
2005     NSString *o_labelString, *o_textfieldString, *o_tooltip;
2006
2007     o_modulearray = [[NSMutableArray alloc] initWithCapacity:10];
2008     /* build a list of available modules */
2009     p_list = vlc_list_find( VLCIntf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
2010     for( i_index = 0; i_index < p_list->i_count; i_index++ )
2011     {
2012         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
2013
2014         if( !strcmp( p_parser->psz_object_name, "main" ) )
2015             continue;
2016
2017         module_config_t *p_config = p_parser->p_config;
2018         if( p_config ) do
2019         {
2020             NSString *o_modulelongname, *o_modulename;
2021             NSNumber *o_moduleenabled = nil;
2022             /* Hack: required subcategory is stored in i_min */
2023             if( p_config->i_type == CONFIG_SUBCATEGORY &&
2024                 p_config->i_value == _p_item->i_min )
2025             {
2026                 o_modulelongname = [NSString stringWithCString:p_parser->psz_longname];
2027                 o_modulename = [NSString stringWithCString:p_parser->psz_object_name];
2028
2029                 if( _p_item->psz_value &&
2030                     strstr( _p_item->psz_value, p_parser->psz_object_name ) )
2031                     o_moduleenabled = [NSNumber numberWithBool:YES];
2032                 else
2033                     o_moduleenabled = [NSNumber numberWithBool:NO];
2034
2035                 [o_modulearray addObject:[NSMutableArray arrayWithObjects: o_modulename, o_modulelongname, o_moduleenabled, nil]];
2036             }
2037         } while( p_config->i_type != CONFIG_HINT_END && p_config++ );
2038     }
2039     vlc_list_release( p_list );
2040
2041     mainFrame.size.height = 30 + 18 * [o_modulearray count];
2042     mainFrame.size.width = mainFrame.size.width - LEFTMARGIN - RIGHTMARGIN;
2043     mainFrame.origin.x = LEFTMARGIN;
2044     mainFrame.origin.y = i_yPos;
2045     if( [super initWithFrame: mainFrame item: _p_item] != nil )
2046     {
2047         /* add the label */
2048         if( p_item->psz_text )
2049             o_labelString = [[VLCMain sharedInstance] localizedString: p_item->psz_text];
2050         else
2051             o_labelString = [NSString stringWithString:@""];
2052         ADD_LABEL( o_label, mainFrame, 0, -3, o_labelString )
2053         [o_label setAutoresizingMask:NSViewNotSizable ];
2054         [self addSubview: o_label];
2055
2056         /* build the textfield */
2057         o_tooltip = [[VLCMain sharedInstance] wrapString:
2058             [[VLCMain sharedInstance] localizedString: p_item->psz_longtext ] toWidth: PREFS_WRAP];
2059         if( p_item->psz_value )
2060             o_textfieldString = [[VLCMain sharedInstance] localizedString: p_item->psz_value];
2061         else
2062             o_textfieldString = [NSString stringWithString: @""];
2063         ADD_TEXTFIELD( o_textfield, mainFrame, [o_label frame].size.width + 2,
2064             mainFrame.size.height - 22, mainFrame.size.width - [o_label frame].size.width - 2,
2065             o_tooltip, o_textfieldString )
2066         [o_textfield setAutoresizingMask:NSViewWidthSizable ];
2067         [self addSubview: o_textfield];
2068
2069
2070 {
2071     NSRect s_rc = mainFrame;
2072     s_rc.size.height = mainFrame.size.height - 30;
2073     s_rc.size.width = mainFrame.size.width - 12;
2074     s_rc.origin.x = 12;
2075     s_rc.origin.y = 0;
2076     o_scrollview = [[[NSScrollView alloc] initWithFrame: s_rc] retain];
2077     [o_scrollview setDrawsBackground: NO];
2078     [o_scrollview setBorderType: NSBezelBorder];
2079     [o_scrollview setAutohidesScrollers:YES];
2080
2081     NSTableView *o_tableview;
2082     o_tableview = [[NSTableView alloc] initWithFrame : s_rc];
2083     [o_tableview setUsesAlternatingRowBackgroundColors:YES];
2084     [o_tableview setHeaderView:nil];
2085 /* TODO: find a good way to fix the row height and text size*/
2086 /* FIXME: support for multiple selection... */
2087 //    [o_tableview setAllowsMultipleSelection:YES];
2088     
2089     NSCell *o_headerCell = [[NSCell alloc] initTextCell:@"Enabled"];
2090     NSCell *o_dataCell = [[NSButtonCell alloc] init];
2091     [(NSButtonCell*)o_dataCell setButtonType:NSSwitchButton];
2092     [o_dataCell setTitle:@""];
2093     [o_dataCell setFont:[NSFont systemFontOfSize:0]];
2094     NSTableColumn *o_tableColumn = [[NSTableColumn alloc]initWithIdentifier:[NSString stringWithCString: "Enabled"]];
2095     [o_tableColumn setHeaderCell: o_headerCell];
2096     [o_tableColumn setDataCell: o_dataCell];
2097     [o_tableColumn setWidth:17];
2098     [o_tableview addTableColumn: o_tableColumn];
2099
2100     o_headerCell = [[NSCell alloc] initTextCell:@"Module Name"];
2101     o_dataCell = [[NSTextFieldCell alloc] init];
2102     [o_dataCell setFont:[NSFont systemFontOfSize:12]];
2103     o_tableColumn = [[NSTableColumn alloc]initWithIdentifier:[NSString stringWithCString: "Module"]];
2104     [o_tableColumn setHeaderCell: o_headerCell];
2105     [o_tableColumn setDataCell: o_dataCell];
2106     [o_tableColumn setWidth:388 - 17];
2107     [o_tableview addTableColumn: o_tableColumn];
2108         [o_tableview registerForDraggedTypes:[NSArray arrayWithObjects:
2109             @"VLC media player module", nil]];
2110
2111     [o_tableview setDataSource:self];
2112     [o_tableview setTarget: self];
2113     [o_tableview setAction: @selector(tableChanged:)];
2114     [o_tableview sendActionOn:NSLeftMouseUpMask|NSLeftMouseDownMask|NSLeftMouseDraggedMask];
2115     [o_scrollview setDocumentView: o_tableview];
2116 }
2117     [o_scrollview setAutoresizingMask:NSViewWidthSizable ];
2118     [self addSubview: o_scrollview];
2119
2120
2121     }
2122     return self;
2123 }
2124
2125 - (IBAction)tableChanged:(id)sender
2126 {
2127     NSString *o_newstring = @"";
2128     unsigned int i;
2129     for( i = 0 ; i < [o_modulearray count] ; i++ )
2130         if( [[[o_modulearray objectAtIndex:i] objectAtIndex:2] boolValue] != NO )
2131         {
2132             o_newstring = [o_newstring stringByAppendingString:[[o_modulearray objectAtIndex:i] objectAtIndex:0]];
2133             o_newstring = [o_newstring stringByAppendingString:@","];
2134         }
2135     
2136     [o_textfield setStringValue: [o_newstring substringToIndex: ([o_newstring length])?[o_newstring length] - 1:0]];
2137 }
2138
2139 - (void)dealloc
2140 {
2141     [o_scrollview release];
2142     [super dealloc];
2143 }
2144
2145
2146 - (char *)stringValue
2147 {
2148     return strdup( [[o_textfield stringValue] cString] );
2149 }
2150
2151 @end
2152
2153 @implementation ModuleListConfigControl (NSTableDataSource)
2154
2155 - (BOOL)tableView:(NSTableView*)table writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pb
2156 {
2157         // We only want to allow dragging of selected rows.
2158         NSEnumerator    *iter = [rows objectEnumerator];
2159         NSNumber                *row;
2160         while ((row = [iter nextObject]) != nil)
2161         {
2162                 if (![table isRowSelected:[row intValue]])
2163                         return NO;
2164         }
2165         
2166         [pb declareTypes:[NSArray arrayWithObject:@"VLC media player module"] owner:nil];
2167         [pb setPropertyList:rows forType:@"VLC media player module"];
2168         return YES;
2169
2170 }
2171
2172 - (NSDragOperation)tableView:(NSTableView*)table validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op
2173 {
2174         // Make drops at the end of the table go to the end.
2175         if (row == -1)
2176         {
2177                 row = [table numberOfRows];
2178                 op = NSTableViewDropAbove;
2179                 [table setDropRow:row dropOperation:op];
2180         }
2181         
2182         // We don't ever want to drop onto a row, only between rows.
2183         if (op == NSTableViewDropOn)
2184                 [table setDropRow:(row+1) dropOperation:NSTableViewDropAbove];
2185         return NSTableViewDropAbove;
2186 }
2187
2188 - (BOOL)tableView:(NSTableView*)table acceptDrop:(id <NSDraggingInfo>)info row:(int)dropRow dropOperation:(NSTableViewDropOperation)op;
2189 {
2190         NSPasteboard    *pb = [info draggingPasteboard];
2191         NSDragOperation srcMask = [info draggingSourceOperationMask];
2192         BOOL accepted = NO;
2193
2194         NS_DURING
2195                         
2196         NSArray *array;
2197
2198         // Intra-table drag - data is the array of rows.
2199         if (!accepted && (array = [pb propertyListForType:@"VLC media player module"]) != NULL)
2200         {
2201             NSEnumerator *      iter = nil;
2202             id val;
2203                         BOOL isCopy = (srcMask & NSDragOperationMove) ? NO:YES;
2204             // Move the modules
2205                         iter = [array objectEnumerator];
2206                         while ((val = [iter nextObject]) != NULL)
2207                         {
2208                 NSArray *o_tmp = [[o_modulearray objectAtIndex:[val intValue]] mutableCopyWithZone:nil];
2209                 [o_modulearray removeObject:o_tmp];
2210                 [o_modulearray insertObject:o_tmp atIndex:(dropRow>[val intValue]) ? dropRow - 1 : dropRow];
2211                 dropRow++;
2212             }
2213
2214             // Select the newly-dragged items.
2215             iter = [array objectEnumerator];
2216 //TODO...
2217                         [table deselectAll:self];
2218
2219             [self tableChanged:self];
2220             [table setNeedsDisplay:YES];
2221                         // Indicate that we finished the drag.
2222                         accepted = YES;
2223                 }
2224         [table reloadData];
2225         [table setNeedsDisplay:YES];
2226                         
2227                 NS_HANDLER
2228                 
2229                         // An exception occurred. Uh-oh. Update the track table so that
2230                         //      it stays consistent, and re-raise the exception.
2231                         [table reloadData];
2232                         [localException raise];
2233             [table setNeedsDisplay:YES];
2234     NS_ENDHANDLER
2235                 
2236         return accepted;
2237 }
2238
2239 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
2240 {
2241     return [o_modulearray count];
2242 }
2243
2244 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
2245 {
2246     if( [[aTableColumn identifier] isEqualToString:[NSString stringWithCString:"Enabled"]] )
2247         return [[o_modulearray objectAtIndex:rowIndex] objectAtIndex:2];
2248     if( [[aTableColumn identifier] isEqualToString:[NSString stringWithCString:"Module"]] )
2249         return [[o_modulearray objectAtIndex:rowIndex] objectAtIndex:1];
2250         
2251     return nil;
2252 }
2253
2254 - (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
2255 {
2256     [[o_modulearray objectAtIndex:rowIndex] replaceObjectAtIndex:2 withObject: anObject];
2257 }
2258 @end