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