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