* modules/gui/wxwindows/*: the wxWindows plugin is now UNICODE happy.
[vlc.git] / modules / gui / wxwindows / preferences.cpp
1 /*****************************************************************************
2  * preferences.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2001 VideoLAN
5  * $Id: preferences.cpp,v 1.12 2003/05/11 13:22:23 gbazin Exp $
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31
32 #include <vlc/vlc.h>
33
34 #ifdef WIN32                                                 /* mingw32 hack */
35 #undef Yield
36 #undef CreateDialog
37 #endif
38
39 /* Let vlc take care of the i18n stuff */
40 #define WXINTL_NO_GETTEXT_MACRO
41
42 #include <wx/wxprec.h>
43 #include <wx/wx.h>
44 #include <wx/window.h>
45 #include <wx/notebook.h>
46 #include <wx/textctrl.h>
47 #include <wx/combobox.h>
48 #include <wx/spinctrl.h>
49 #include <wx/statline.h>
50 #include <wx/treectrl.h>
51 #include <wx/clntdata.h>
52 #include <wx/dynarray.h>
53
54 #include <vlc/intf.h>
55
56 #if defined MODULE_NAME_IS_skins
57 #   include "../skins/src/skin_common.h"
58 #   include "../skins/src/wxdialogs.h"
59 #else
60 #   include "wxwindows.h"
61 #endif
62
63
64 #ifndef wxRB_SINGLE
65 #   define wxRB_SINGLE 0
66 #endif
67
68 /*****************************************************************************
69  * Classes declarations.
70  *****************************************************************************/
71 class PrefsTreeCtrl : public wxTreeCtrl
72 {
73 public:
74
75     PrefsTreeCtrl() { }
76     PrefsTreeCtrl( wxWindow *parent, intf_thread_t *_p_intf,
77                    PrefsDialog *p_prefs_dialog, wxBoxSizer *_p_sizer );
78     virtual ~PrefsTreeCtrl();
79
80     void ApplyChanges();
81
82 private:
83     /* Event handlers (these functions should _not_ be virtual) */
84     void OnSelectTreeItem( wxTreeEvent& event );
85
86     DECLARE_EVENT_TABLE()
87
88     intf_thread_t *p_intf;
89     PrefsDialog *p_prefs_dialog;
90     wxBoxSizer *p_sizer;
91     wxWindow *p_parent;
92
93     wxTreeItemId root_item;
94     wxTreeItemId plugins_item;
95 };
96
97 struct ConfigData
98 {
99     ConfigData( wxPanel *_panel, int _i_conf_type,
100                 vlc_bool_t _b_advanced, char *psz_name )
101     { panel = _panel; b_advanced = _b_advanced; b_config_list = VLC_FALSE;
102       i_config_type = _i_conf_type; option_name = wxU(psz_name); }
103
104     vlc_bool_t b_advanced;
105     int i_config_type;
106     vlc_bool_t b_config_list;
107
108     union control
109     {
110         wxComboBox *combobox;
111         wxRadioButton *radio;
112         wxSpinCtrl *spinctrl;
113         wxCheckBox *checkbox;
114         wxTextCtrl *textctrl;
115
116     } control;
117
118     wxPanel *panel;
119     wxString option_name;
120 };
121
122 WX_DEFINE_ARRAY(ConfigData *, ArrayOfConfigData);
123
124 class PrefsPanel : public wxPanel
125 {
126 public:
127
128     PrefsPanel() { }
129     PrefsPanel( wxWindow *parent, intf_thread_t *_p_intf,
130                 PrefsDialog *_p_prefs_dialog,
131                 module_t *p_module, char * );
132     virtual ~PrefsPanel() {}
133
134     void ApplyChanges();
135
136 private:
137     void OnAdvanced( wxCommandEvent& WXUNUSED(event) );
138     DECLARE_EVENT_TABLE()
139
140     intf_thread_t *p_intf;
141     PrefsDialog *p_prefs_dialog;
142
143     vlc_bool_t b_advanced;
144
145     wxBoxSizer *config_sizer;
146     wxScrolledWindow *config_window;
147
148     ArrayOfConfigData config_array;
149 };
150
151 class ConfigTreeData : public wxTreeItemData
152 {
153 public:
154
155     ConfigTreeData() { panel == NULL; }
156     virtual ~ConfigTreeData() { if( panel ) delete panel; }
157
158     PrefsPanel *panel;
159     wxBoxSizer *sizer;
160 };
161
162 class ConfigEvtHandler : public wxEvtHandler
163 {
164 public:
165     ConfigEvtHandler( intf_thread_t *p_intf, PrefsDialog *p_prefs_dialog );
166     virtual ~ConfigEvtHandler();
167
168     void ConfigEvtHandler::OnCommandEvent( wxCommandEvent& event );
169
170 private:
171
172     DECLARE_EVENT_TABLE()
173
174     intf_thread_t *p_intf;
175     PrefsDialog *p_prefs_dialog;
176 };
177
178 /*****************************************************************************
179  * Event Table.
180  *****************************************************************************/
181
182 /* IDs for the controls and the menu commands */
183 enum
184 {
185     Notebook_Event = wxID_HIGHEST,
186     MRL_Event,
187     Reset_Event,
188     Advanced_Event,
189 };
190
191 BEGIN_EVENT_TABLE(PrefsDialog, wxFrame)
192     /* Button events */
193     EVT_BUTTON(wxID_OK, PrefsDialog::OnOk)
194     EVT_BUTTON(wxID_CANCEL, PrefsDialog::OnCancel)
195     EVT_BUTTON(wxID_SAVE, PrefsDialog::OnSave)
196
197     /* Don't destroy the window when the user closes it */
198     EVT_CLOSE(PrefsDialog::OnCancel)
199 END_EVENT_TABLE()
200
201 // menu and control ids
202 enum
203 {
204     PrefsTree_Ctrl = wxID_HIGHEST
205 };
206
207 BEGIN_EVENT_TABLE(PrefsTreeCtrl, wxTreeCtrl)
208     EVT_TREE_SEL_CHANGED(PrefsTree_Ctrl, PrefsTreeCtrl::OnSelectTreeItem)
209 END_EVENT_TABLE()
210
211 BEGIN_EVENT_TABLE(PrefsPanel, wxPanel)
212     /* Button events */
213     EVT_BUTTON(Advanced_Event, PrefsPanel::OnAdvanced)
214
215 END_EVENT_TABLE()
216
217 BEGIN_EVENT_TABLE(ConfigEvtHandler, wxEvtHandler)
218     EVT_BUTTON(-1, ConfigEvtHandler::OnCommandEvent)
219     EVT_TEXT(-1, ConfigEvtHandler::OnCommandEvent)
220     EVT_RADIOBOX(-1, ConfigEvtHandler::OnCommandEvent)
221     EVT_SPINCTRL(-1, ConfigEvtHandler::OnCommandEvent)
222 END_EVENT_TABLE()
223
224 /*****************************************************************************
225  * Constructor.
226  *****************************************************************************/
227 PrefsDialog::PrefsDialog( intf_thread_t *_p_intf, Interface *_p_main_interface)
228   :  wxFrame( _p_main_interface, -1, wxU(_("Preferences")), wxDefaultPosition,
229               wxSize(650,450), wxDEFAULT_FRAME_STYLE )
230 {
231     /* Initializations */
232     p_intf = _p_intf;
233     p_main_interface = _p_main_interface;
234     SetIcon( *p_intf->p_sys->p_icon );
235
236     /* Create a panel to put everything in */
237     wxPanel *panel = new wxPanel( this, -1 );
238     panel->SetAutoLayout( TRUE );
239
240     /* Create the preferences tree control */
241     wxBoxSizer *controls_sizer = new wxBoxSizer( wxHORIZONTAL );
242     prefs_tree =
243         new PrefsTreeCtrl( panel, p_intf, this, controls_sizer );
244
245     /* Separation */
246     wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
247
248     /* Create the buttons */
249     wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
250     ok_button->SetDefault();
251     wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
252                                             wxU(_("Cancel")) );
253     wxButton *save_button = new wxButton( panel, wxID_SAVE, wxU(_("Save")) );
254     //wxButton *reset_button = new wxButton( panel, Reset_Event, _("Reset") );
255
256     /* Place everything in sizers */
257     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
258     button_sizer->Add( ok_button, 0, wxALL, 5 );
259     button_sizer->Add( cancel_button, 0, wxALL, 5 );
260     button_sizer->Add( save_button, 0, wxALL, 5 );
261     //button_sizer->Add( reset_button, 0, wxALL, 5 );
262     button_sizer->Layout();
263
264     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
265     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
266     panel_sizer->Add( controls_sizer, 1, wxEXPAND | wxALL, 5 );
267     panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
268     panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALIGN_BOTTOM |
269                       wxALL, 5 );
270     panel_sizer->Layout();
271     panel->SetSizer( panel_sizer );
272     main_sizer->Add( panel, 1, wxEXPAND, 0 );
273     main_sizer->Layout();
274     SetSizer( main_sizer );
275 }
276
277 PrefsDialog::~PrefsDialog()
278 {
279 }
280
281 /*****************************************************************************
282  * Private methods.
283  *****************************************************************************/
284
285
286 /*****************************************************************************
287  * Events methods.
288  *****************************************************************************/
289 void PrefsDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
290 {
291     prefs_tree->ApplyChanges();
292
293     this->Hide();
294 }
295
296 void PrefsDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
297 {
298     this->Hide();
299 }
300
301 void PrefsDialog::OnSave( wxCommandEvent& WXUNUSED(event) )
302 {
303     prefs_tree->ApplyChanges();
304
305     config_SaveConfigFile( p_intf, NULL );
306 }
307
308 /*****************************************************************************
309  * PrefsTreeCtrl class definition.
310  *****************************************************************************/
311 PrefsTreeCtrl::PrefsTreeCtrl( wxWindow *_p_parent, intf_thread_t *_p_intf,
312                               PrefsDialog *_p_prefs_dialog,
313                               wxBoxSizer *_p_sizer )
314   : wxTreeCtrl( _p_parent, PrefsTree_Ctrl, wxDefaultPosition, wxDefaultSize,
315                 wxTR_NO_LINES | wxTR_FULL_ROW_HIGHLIGHT |
316                 wxTR_LINES_AT_ROOT | wxTR_HIDE_ROOT |
317                 wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS | wxSUNKEN_BORDER )
318 {
319     vlc_list_t      *p_list;
320     module_t        *p_module;
321     module_config_t *p_item;
322     int i_index;
323
324     /* Initializations */
325     p_intf = _p_intf;
326     p_prefs_dialog = _p_prefs_dialog;
327     p_sizer = _p_sizer;
328     p_parent = _p_parent;
329
330     root_item = AddRoot( wxT("") );
331
332     /* List the plugins */
333     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
334     if( !p_list ) return;
335
336     /*
337      * Build a tree of the main options
338      */
339     for( i_index = 0; i_index < p_list->i_count; i_index++ )
340     {
341         p_module = (module_t *)p_list->p_values[i_index].p_object;
342         if( !strcmp( p_module->psz_object_name, "main" ) )
343             break;
344     }
345     if( i_index < p_list->i_count )
346     {
347         /* We found the main module */
348
349         /* Enumerate config options and add corresponding config boxes */
350         p_item = p_module->p_config;
351
352         if( p_item ) do
353         {
354             switch( p_item->i_type )
355             {
356             case CONFIG_HINT_CATEGORY:
357                 ConfigTreeData *config_data = new ConfigTreeData;
358                 config_data->panel =
359                     new PrefsPanel( p_parent, p_intf, p_prefs_dialog,
360                                     p_module, p_item->psz_text );
361                 config_data->panel->Hide();
362
363                 /* Add the category to the tree */
364                 AppendItem( root_item, wxU(p_item->psz_text),
365                             -1, -1, config_data );
366                 break;
367             }
368         }
369         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
370
371         SortChildren( root_item );
372     }
373
374
375     /*
376      * Build a tree of all the plugins
377      */
378     plugins_item = AppendItem( root_item, wxU(_("Plugins")) );
379
380     for( i_index = 0; i_index < p_list->i_count; i_index++ )
381     {
382         p_module = (module_t *)p_list->p_values[i_index].p_object;
383
384         /* Exclude the main module */
385         if( !strcmp( p_module->psz_object_name, "main" ) )
386             continue;
387
388         /* Exclude empty plugins */
389         p_item = p_module->p_config;
390         if( !p_item ) continue;
391         do
392         {
393             if( p_item->i_type & CONFIG_ITEM )
394                 break;
395         }
396         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
397         if( p_item->i_type == CONFIG_HINT_END ) continue;
398
399         /* Find the capability child item */
400         long cookie; size_t i_child_index;
401         wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
402         for( i_child_index = 0;
403              i_child_index < GetChildrenCount( plugins_item, FALSE );
404              i_child_index++ )
405         {
406             if( !GetItemText(capability_item).Cmp(
407                     wxU(p_module->psz_capability ) ) )
408             {
409                 break;
410             }
411             capability_item = GetNextChild( plugins_item, cookie );
412         }
413
414         if( i_child_index == GetChildrenCount( plugins_item, FALSE ) &&
415             p_module->psz_capability && *p_module->psz_capability )
416         {
417             /* We didn't find it, add it */
418             capability_item = AppendItem( plugins_item,
419                                           wxU(p_module->psz_capability) );
420         }
421
422         /* Add the plugin to the tree */
423         ConfigTreeData *config_data = new ConfigTreeData;
424         config_data->panel =
425             new PrefsPanel( p_parent, p_intf, p_prefs_dialog, p_module, NULL );
426         config_data->panel->Hide();
427         AppendItem( capability_item, wxU(p_module->psz_object_name), -1, -1,
428                     config_data );
429     }
430
431     /* Sort all this mess */
432     long cookie; size_t i_child_index;
433     SortChildren( plugins_item );
434     wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
435     for( i_child_index = 0;
436          i_child_index < GetChildrenCount( plugins_item, FALSE );
437          i_child_index++ )
438     {
439         capability_item = GetNextChild( plugins_item, cookie );
440         SortChildren( capability_item );
441     }
442
443     /* Clean-up everything */
444     vlc_list_release( p_list );
445
446     p_sizer->Add( this, 1, wxEXPAND | wxALL, 0 );
447     p_sizer->Layout();
448
449     /* Update Tree Ctrl */
450 #ifndef WIN32 /* Workaround a bug in win32 implementation */
451     SelectItem( GetFirstChild( root_item, cookie ) );
452 #endif
453 }
454
455 PrefsTreeCtrl::~PrefsTreeCtrl()
456 {
457 }
458
459 void PrefsTreeCtrl::ApplyChanges()
460 {
461     long cookie, cookie2;
462     ConfigTreeData *config_data;
463
464     /* Apply changes to the main module */
465     wxTreeItemId item = GetFirstChild( root_item, cookie );
466     for( size_t i_child_index = 0;
467          i_child_index < GetChildrenCount( root_item, FALSE );
468          i_child_index++ )
469     {
470         config_data = (ConfigTreeData *)GetItemData( item );
471         if( config_data )
472         {
473             config_data->panel->ApplyChanges();
474         }
475
476         item = GetNextChild( root_item, cookie );
477     }
478
479     /* Apply changes to the plugins */
480     item = GetFirstChild( plugins_item, cookie );
481     for( size_t i_child_index = 0;
482          i_child_index < GetChildrenCount( plugins_item, FALSE );
483          i_child_index++ )
484     {
485         wxTreeItemId item2 = GetFirstChild( item, cookie2 );
486         for( size_t i_child_index = 0;
487              i_child_index < GetChildrenCount( item, FALSE );
488              i_child_index++ )
489         {
490             config_data = (ConfigTreeData *)GetItemData( item2 );
491             if( config_data )
492             {
493                 config_data->panel->ApplyChanges();
494             }
495
496             item2 = GetNextChild( item, cookie2 );
497         }
498
499         item = GetNextChild( plugins_item, cookie );
500     }
501 }
502
503 void PrefsTreeCtrl::OnSelectTreeItem( wxTreeEvent& event )
504 {
505     ConfigTreeData *config_data;
506
507     config_data = (ConfigTreeData *)GetItemData( event.GetOldItem() );
508     if( config_data && config_data->panel )
509     {
510         config_data->panel->Hide();
511         p_sizer->Remove( config_data->panel );
512     }
513
514     config_data = (ConfigTreeData *)GetItemData( event.GetItem() );
515     if( config_data && config_data->panel )
516     {
517         config_data->panel->Show();
518         p_sizer->Add( config_data->panel, 2, wxEXPAND | wxALL, 0 );
519         p_sizer->Layout();
520     }
521 }
522
523 /*****************************************************************************
524  * PrefsPanel class definition.
525  *****************************************************************************/
526 PrefsPanel::PrefsPanel( wxWindow* parent, intf_thread_t *_p_intf,
527                         PrefsDialog *_p_prefs_dialog,
528                         module_t *p_module, char *psz_section )
529   :  wxPanel( parent, -1, wxDefaultPosition, wxDefaultSize )
530 {
531     module_config_t *p_item;
532     vlc_list_t      *p_list;
533     module_t        *p_parser;
534
535     wxStaticText *label;
536     wxComboBox *combo;
537     wxSpinCtrl *spin;
538     wxCheckBox *checkbox;
539     wxTextCtrl *textctrl;
540     wxButton *button;
541     wxArrayString array;
542
543     /* Initializations */
544     p_intf = _p_intf;
545     p_prefs_dialog =_p_prefs_dialog,
546
547     b_advanced = VLC_TRUE;
548     SetAutoLayout( TRUE );
549
550     wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
551
552     /* Enumerate config options and add corresponding config boxes */
553     p_item = p_module->p_config;
554
555     /* Find the category if it has been specified */
556     if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY )
557     {
558         while( !p_item->i_type == CONFIG_HINT_CATEGORY ||
559                strcmp( psz_section, p_item->psz_text ) )
560         {
561             if( p_item->i_type == CONFIG_HINT_END )
562                 break;
563             p_item++;
564         }
565     }
566
567     /* Add a head title to the panel */
568     wxStaticBox *static_box = new wxStaticBox( this, -1, wxT("") );
569     wxStaticBoxSizer *box_sizer = new wxStaticBoxSizer( static_box,
570                                                         wxHORIZONTAL );
571     label = new wxStaticText( this, -1,
572                               wxU(psz_section ? p_item->psz_text :
573                               p_module->psz_longname) );
574
575     box_sizer->Add( label, 1, wxALL, 5 );
576     sizer->Add( box_sizer, 0, wxEXPAND | wxALL, 5 );
577
578     /* Now put all the config options into a scrolled window */
579     config_sizer = new wxBoxSizer( wxVERTICAL );
580     config_window = new wxScrolledWindow( this, -1, wxDefaultPosition,
581                                           wxDefaultSize );
582     config_window->SetAutoLayout( TRUE );
583     config_window->SetScrollRate( 5, 5 );
584
585     if( p_item ) do
586     {
587         /* If a category has been specified, check we finished the job */
588         if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY &&
589             strcmp( psz_section, p_item->psz_text ) )
590             break;
591
592         /* put each config option in a separate panel so we can hide advanced
593          * options easily */
594         wxPanel *panel = new wxPanel( config_window, -1, wxDefaultPosition,
595                                       wxDefaultSize );
596         wxBoxSizer *panel_sizer = new wxBoxSizer( wxHORIZONTAL );
597         ConfigData *config_data =
598             new ConfigData( panel, p_item->i_type,
599                             p_item->b_advanced, p_item->psz_name );
600
601         switch( p_item->i_type )
602         {
603         case CONFIG_ITEM_MODULE:
604             label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
605             combo = new wxComboBox( panel, -1, wxU(p_item->psz_value),
606                                     wxDefaultPosition, wxDefaultSize,
607                                     0, NULL, wxCB_READONLY | wxCB_SORT );
608
609             /* build a list of available modules */
610             p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
611             combo->Append( wxU(_("Default")), (void *)NULL );
612             combo->SetSelection( 0 );
613             for( int i_index = 0; i_index < p_list->i_count; i_index++ )
614             {
615                 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
616
617                 if( !strcmp( p_parser->psz_capability,
618                              p_item->psz_type ) )
619                 {
620                     combo->Append( wxU(p_parser->psz_longname),
621                                    p_parser->psz_object_name );
622                     if( p_item->psz_value &&
623                         !strcmp(p_item->psz_value, p_parser->psz_object_name) )
624                         combo->SetValue( wxU(p_parser->psz_longname) );
625                 }
626             }
627
628             combo->SetToolTip( wxU(p_item->psz_longtext) );
629             config_data->control.combobox = combo;
630             panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
631             panel_sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
632             break;
633
634         case CONFIG_ITEM_STRING:
635         case CONFIG_ITEM_FILE:
636         case CONFIG_ITEM_DIRECTORY:
637             label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
638             panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
639
640             if( !p_item->ppsz_list )
641             {
642                 textctrl = new wxTextCtrl( panel, -1, wxU(p_item->psz_value),
643                                            wxDefaultPosition, wxDefaultSize,
644                                            wxTE_PROCESS_ENTER);
645                 textctrl->SetToolTip( wxU(p_item->psz_longtext) );
646                 config_data->control.textctrl = textctrl;
647                 panel_sizer->Add( textctrl, 1, wxALL, 5 );
648             }
649             else
650             {
651                 combo = new wxComboBox( panel, -1, wxU(p_item->psz_value),
652                                         wxDefaultPosition, wxDefaultSize,
653                                         0, NULL, wxCB_READONLY | wxCB_SORT );
654
655                 /* build a list of available options */
656                 for( int i_index = 0; p_item->ppsz_list[i_index]; i_index++ )
657                 {
658                     combo->Append( wxU(p_item->ppsz_list[i_index]) );
659                 }
660
661                 if( p_item->psz_value )
662                     combo->SetValue( wxU(p_item->psz_value) );
663                 combo->SetToolTip( wxU(p_item->psz_longtext) );
664                 config_data->control.combobox = combo;
665                 config_data->b_config_list = VLC_TRUE;
666                 panel_sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
667             }
668
669             if( p_item->i_type == CONFIG_ITEM_FILE )
670             {
671                 button = new wxButton( panel, -1, wxU(_("Browse...")) );
672                 panel_sizer->Add( button, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
673                 button->SetClientData((void *)config_data);
674             }
675             break;
676
677         case CONFIG_ITEM_INTEGER:
678             label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
679             spin = new wxSpinCtrl( panel, -1,
680                                    wxString::Format(wxT("%d"),p_item->i_value),
681                                    wxDefaultPosition, wxDefaultSize,
682                                    wxSP_ARROW_KEYS,
683                                    0, 16000, p_item->i_value);
684             spin->SetToolTip( wxU(p_item->psz_longtext) );
685             config_data->control.spinctrl = spin;
686             panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
687             panel_sizer->Add( spin, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
688
689             spin->SetClientData((void *)config_data);
690             break;
691
692         case CONFIG_ITEM_FLOAT:
693             label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
694             spin = new wxSpinCtrl( panel, -1,
695                                    wxString::Format(wxT("%f"),p_item->f_value),
696                                    wxDefaultPosition, wxDefaultSize,
697                                    wxSP_ARROW_KEYS,
698                                    0, 16000, (int)p_item->f_value);
699             spin->SetToolTip( wxU(p_item->psz_longtext) );
700             config_data->control.spinctrl = spin;
701             panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
702             panel_sizer->Add( spin, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
703             break;
704
705         case CONFIG_ITEM_BOOL:
706             checkbox = new wxCheckBox( panel, -1, wxU(p_item->psz_text) );
707             if( p_item->i_value ) checkbox->SetValue(TRUE);
708             checkbox->SetToolTip( wxU(p_item->psz_longtext) );
709             config_data->control.checkbox = checkbox;
710             panel_sizer->Add( checkbox, 0, wxALL, 5 );
711             break;
712
713         default:
714             delete panel; panel = NULL;
715             delete panel_sizer;
716             delete config_data;
717             break;
718         }
719
720         /* Don't add items that were not recognized */
721         if( panel == NULL ) continue;
722
723         panel_sizer->Layout();
724         panel->SetSizerAndFit( panel_sizer );
725
726         /* Add the config data to our array so we can keep a trace of it */
727         config_array.Add( config_data );
728
729         config_sizer->Add( panel, 0, wxEXPAND | wxALL, 2 );
730     }
731     while( p_item->i_type != CONFIG_HINT_END && p_item++ );
732
733     /* Display a nice message if no configuration options are available */
734     if( !config_array.GetCount() )
735     {
736         config_sizer->Add( new wxStaticText( config_window, -1,
737                            wxU(_("No configuration options available")) ), 1,
738                            wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER, 2 );
739     }
740
741     config_sizer->Layout();
742     config_window->SetSizer( config_sizer );
743     sizer->Add( config_window, 1, wxEXPAND | wxALL, 5 );
744
745     /* Intercept all menu events in our custom event handler */
746     config_window->PushEventHandler(
747         new ConfigEvtHandler( p_intf, p_prefs_dialog ) );
748
749     /* Update panel */
750     wxCommandEvent dummy_event;
751     b_advanced = !config_GetInt( p_intf, "advanced" );
752     OnAdvanced( dummy_event );
753
754     /* Create advanced button */
755     if( config_array.GetCount() )
756     {
757         wxButton *advanced_button = new wxButton( this, Advanced_Event,
758                                                   wxU(_("Advanced...")) );
759         sizer->Add( advanced_button, 0, wxALL, 5 );
760     }
761
762     sizer->Layout();
763     SetSizer( sizer );
764 }
765
766 void PrefsPanel::ApplyChanges()
767 {
768     for( size_t i = 0; i < config_array.GetCount(); i++ )
769     {
770         ConfigData *config_data = config_array.Item(i);
771
772         switch( config_data->i_config_type )
773         {
774         case CONFIG_ITEM_MODULE:
775             config_PutPsz( p_intf, config_data->option_name.mb_str(), (char *)
776                            config_data->control.combobox->GetClientData(
777                            config_data->control.combobox->GetSelection() ) );
778             break;
779         case CONFIG_ITEM_STRING:
780         case CONFIG_ITEM_FILE:
781         case CONFIG_ITEM_DIRECTORY:
782             if( !config_data->b_config_list )
783                 config_PutPsz( p_intf, config_data->option_name.mb_str(),
784                                config_data->control.textctrl->GetValue().mb_str() );
785             else
786                 config_PutPsz( p_intf, config_data->option_name.mb_str(),
787                                config_data->control.combobox->GetValue().mb_str() );
788             break;
789         case CONFIG_ITEM_BOOL:
790             config_PutInt( p_intf, config_data->option_name.mb_str(),
791                            config_data->control.checkbox->IsChecked() );
792             break;
793         case CONFIG_ITEM_INTEGER:
794             config_PutInt( p_intf, config_data->option_name.mb_str(),
795                            config_data->control.spinctrl->GetValue() );
796             break;
797         case CONFIG_ITEM_FLOAT:
798             config_PutFloat( p_intf, config_data->option_name.mb_str(),
799                              config_data->control.spinctrl->GetValue() );
800             break;
801         }
802     }
803 }
804
805 void PrefsPanel::OnAdvanced( wxCommandEvent& WXUNUSED(event) )
806 {
807     b_advanced = !b_advanced;
808
809     for( size_t i = 0; i < config_array.GetCount(); i++ )
810     {
811         ConfigData *config_data = config_array.Item(i);
812         if( config_data->b_advanced )
813         {
814             config_data->panel->Show( b_advanced );
815             config_sizer->Show( config_data->panel, b_advanced );
816         }
817     }
818
819     config_sizer->Layout();
820     config_window->FitInside();
821 }
822
823 /*****************************************************************************
824  * A small helper class which intercepts all events
825  *****************************************************************************/
826 ConfigEvtHandler::ConfigEvtHandler( intf_thread_t *_p_intf,
827                                     PrefsDialog *_p_prefs_dialog )
828 {
829     /* Initializations */
830     p_intf = _p_intf;
831     p_prefs_dialog = _p_prefs_dialog;
832 }
833
834 ConfigEvtHandler::~ConfigEvtHandler()
835 {
836 }
837
838 void ConfigEvtHandler::OnCommandEvent( wxCommandEvent& event )
839 {
840     if( !event.GetEventObject() )
841     {
842         event.Skip();
843         return;
844     }
845
846     ConfigData *config_data = (ConfigData *)
847         ((wxEvtHandler *)event.GetEventObject())->GetClientData();
848
849     if( !config_data )
850     {
851         event.Skip();
852         return;
853     }
854
855     if( config_data->i_config_type == CONFIG_ITEM_FILE )
856     {
857         wxFileDialog dialog( p_prefs_dialog, wxU(_("Open file")),
858                              wxT(""), wxT(""), wxT("*.*"), wxOPEN | wxSAVE );
859
860         if( dialog.ShowModal() == wxID_OK )
861         {
862             config_data->control.textctrl->SetValue( dialog.GetPath() );      
863         }
864     }
865
866     switch( config_data->i_config_type )
867     {
868     case CONFIG_ITEM_MODULE:
869         break;
870     case CONFIG_ITEM_STRING:
871         break;
872     case CONFIG_ITEM_FILE:
873         break;
874     case CONFIG_ITEM_INTEGER:
875         break;
876     case CONFIG_ITEM_FLOAT:
877         break;
878     case CONFIG_ITEM_BOOL:
879         break;
880     }
881
882     event.Skip();
883 }