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