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