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