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