]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/preferences.cpp
* repaired basic_skins
[vlc] / 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.19 2003/06/09 12:33:17 asmax 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 #endif
59
60 #include "wxwindows.h"
61
62 #ifndef wxRB_SINGLE
63 #   define wxRB_SINGLE 0
64 #endif
65
66 /*****************************************************************************
67  * Classes declarations.
68  *****************************************************************************/
69 class PrefsTreeCtrl : public wxTreeCtrl
70 {
71 public:
72
73     PrefsTreeCtrl() { }
74     PrefsTreeCtrl( wxWindow *parent, intf_thread_t *_p_intf,
75                    PrefsDialog *p_prefs_dialog, wxBoxSizer *_p_sizer );
76     virtual ~PrefsTreeCtrl();
77
78     void ApplyChanges();
79     void CleanChanges();
80
81 private:
82     /* Event handlers (these functions should _not_ be virtual) */
83     void OnSelectTreeItem( wxTreeEvent& event );
84
85     DECLARE_EVENT_TABLE()
86
87     intf_thread_t *p_intf;
88     PrefsDialog *p_prefs_dialog;
89     wxBoxSizer *p_sizer;
90     wxWindow *p_parent;
91
92     wxTreeItemId root_item;
93     wxTreeItemId plugins_item;
94 };
95
96 struct ConfigData
97 {
98     ConfigData( wxPanel *_panel, int _i_conf_type,
99                 vlc_bool_t _b_advanced, char *psz_name )
100     { panel = _panel; b_advanced = _b_advanced; b_config_list = VLC_FALSE;
101       i_config_type = _i_conf_type; option_name = wxU(psz_name); }
102
103     vlc_bool_t b_advanced;
104     int i_config_type;
105     vlc_bool_t b_config_list;
106
107     union control
108     {
109         wxComboBox *combobox;
110         wxRadioButton *radio;
111         wxSpinCtrl *spinctrl;
112         wxCheckBox *checkbox;
113         wxTextCtrl *textctrl;
114
115     } control;
116
117     wxPanel *panel;
118     wxString option_name;
119 };
120
121 WX_DEFINE_ARRAY(ConfigData *, ArrayOfConfigData);
122
123 class PrefsPanel : public wxPanel
124 {
125 public:
126
127     PrefsPanel() { }
128     PrefsPanel( wxWindow *parent, intf_thread_t *_p_intf,
129                 PrefsDialog *_p_prefs_dialog, int i_object_id, char * );
130     virtual ~PrefsPanel() {}
131
132     void ApplyChanges();
133
134 private:
135     void OnAdvanced( wxCommandEvent& WXUNUSED(event) );
136     DECLARE_EVENT_TABLE()
137
138     intf_thread_t *p_intf;
139     PrefsDialog *p_prefs_dialog;
140
141     vlc_bool_t b_advanced;
142
143     wxBoxSizer *config_sizer;
144     wxScrolledWindow *config_window;
145
146     ArrayOfConfigData config_array;
147 };
148
149 class ConfigTreeData : public wxTreeItemData
150 {
151 public:
152
153     ConfigTreeData() { panel = NULL; psz_section = NULL; }
154     virtual ~ConfigTreeData() { if( panel ) delete panel; }
155
156     PrefsPanel *panel;
157     wxBoxSizer *sizer;
158     int i_object_id;
159     char *psz_section;
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     ResetAll_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     EVT_BUTTON(ResetAll_Event, PrefsDialog::OnResetAll)
197
198     /* Don't destroy the window when the user closes it */
199     EVT_CLOSE(PrefsDialog::OnCancel)
200 END_EVENT_TABLE()
201
202 // menu and control ids
203 enum
204 {
205     PrefsTree_Ctrl = wxID_HIGHEST
206 };
207
208 BEGIN_EVENT_TABLE(PrefsTreeCtrl, wxTreeCtrl)
209     EVT_TREE_SEL_CHANGED(PrefsTree_Ctrl, PrefsTreeCtrl::OnSelectTreeItem)
210 END_EVENT_TABLE()
211
212 BEGIN_EVENT_TABLE(PrefsPanel, wxPanel)
213     /* Button events */
214     EVT_CHECKBOX(Advanced_Event, PrefsPanel::OnAdvanced)
215
216 END_EVENT_TABLE()
217
218 BEGIN_EVENT_TABLE(ConfigEvtHandler, wxEvtHandler)
219     EVT_BUTTON(-1, ConfigEvtHandler::OnCommandEvent)
220     EVT_TEXT(-1, ConfigEvtHandler::OnCommandEvent)
221     EVT_RADIOBOX(-1, ConfigEvtHandler::OnCommandEvent)
222     EVT_SPINCTRL(-1, ConfigEvtHandler::OnCommandEvent)
223 END_EVENT_TABLE()
224
225 /*****************************************************************************
226  * Constructor.
227  *****************************************************************************/
228 PrefsDialog::PrefsDialog( intf_thread_t *_p_intf, wxWindow *p_parent)
229   :  wxFrame( p_parent, -1, wxU(_("Preferences")), wxDefaultPosition,
230               wxSize(650,450), wxDEFAULT_FRAME_STYLE )
231 {
232     /* Initializations */
233     p_intf = _p_intf;
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, ResetAll_Event,
255                                            wxU(_("Reset All")) );
256
257     /* Place everything in sizers */
258     wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
259     button_sizer->Add( ok_button, 0, wxALL, 5 );
260     button_sizer->Add( cancel_button, 0, wxALL, 5 );
261     button_sizer->Add( save_button, 0, wxALL, 5 );
262     button_sizer->Add( reset_button, 0, wxALL, 5 );
263     button_sizer->Layout();
264
265     wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
266     wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
267     panel_sizer->Add( controls_sizer, 1, wxEXPAND | wxALL, 5 );
268     panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
269     panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALIGN_BOTTOM |
270                       wxALL, 5 );
271     panel_sizer->Layout();
272     panel->SetSizer( panel_sizer );
273     main_sizer->Add( panel, 1, wxEXPAND, 0 );
274     main_sizer->Layout();
275     SetSizer( main_sizer );
276 }
277
278 PrefsDialog::~PrefsDialog()
279 {
280 }
281
282 /*****************************************************************************
283  * Private methods.
284  *****************************************************************************/
285
286
287 /*****************************************************************************
288  * Events methods.
289  *****************************************************************************/
290 void PrefsDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
291 {
292     prefs_tree->ApplyChanges();
293     this->Hide();
294     prefs_tree->CleanChanges();
295 }
296
297 void PrefsDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
298 {
299     this->Hide();
300     prefs_tree->CleanChanges();
301 }
302
303 void PrefsDialog::OnSave( wxCommandEvent& WXUNUSED(event) )
304 {
305     prefs_tree->ApplyChanges();
306     config_SaveConfigFile( p_intf, NULL );
307 }
308
309 void PrefsDialog::OnResetAll( wxCommandEvent& WXUNUSED(event) )
310 {
311     wxMessageDialog dlg( this,
312         wxU(_("Beware this will reset your VLC Media Player config file.\n"
313               "Are you sure you want to continue?")),
314         wxU(_("Reset config file")), wxYES_NO|wxNO_DEFAULT|wxCENTRE );
315
316     if ( dlg.ShowModal() == wxID_YES )
317     {
318         /* TODO: need to reset all the controls */
319         config_ResetAll( p_intf );
320         prefs_tree->CleanChanges();
321         config_SaveConfigFile( p_intf, NULL );
322     }
323 }
324
325 /*****************************************************************************
326  * PrefsTreeCtrl class definition.
327  *****************************************************************************/
328 PrefsTreeCtrl::PrefsTreeCtrl( wxWindow *_p_parent, intf_thread_t *_p_intf,
329                               PrefsDialog *_p_prefs_dialog,
330                               wxBoxSizer *_p_sizer )
331   : wxTreeCtrl( _p_parent, PrefsTree_Ctrl, wxDefaultPosition, wxDefaultSize,
332                 wxTR_NO_LINES | wxTR_FULL_ROW_HIGHLIGHT |
333                 wxTR_LINES_AT_ROOT | wxTR_HIDE_ROOT |
334                 wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS | wxSUNKEN_BORDER )
335 {
336     vlc_list_t      *p_list;
337     module_t        *p_module;
338     module_config_t *p_item;
339     int i_index;
340
341     /* Initializations */
342     p_intf = _p_intf;
343     p_prefs_dialog = _p_prefs_dialog;
344     p_sizer = _p_sizer;
345     p_parent = _p_parent;
346
347     root_item = AddRoot( wxT("") );
348
349     /* List the plugins */
350     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
351     if( !p_list ) return;
352
353     /*
354      * Build a tree of the main options
355      */
356     for( i_index = 0; i_index < p_list->i_count; i_index++ )
357     {
358         p_module = (module_t *)p_list->p_values[i_index].p_object;
359         if( !strcmp( p_module->psz_object_name, "main" ) )
360             break;
361     }
362     if( i_index < p_list->i_count )
363     {
364         /* We found the main module */
365
366         /* Enumerate config categories and store a reference so we can
367          * generate their config panel them when it is asked by the user. */
368         p_item = p_module->p_config;
369
370         if( p_item ) do
371         {
372             switch( p_item->i_type )
373             {
374             case CONFIG_HINT_CATEGORY:
375                 ConfigTreeData *config_data = new ConfigTreeData;
376                 config_data->psz_section = strdup(p_item->psz_text);
377                 config_data->i_object_id = p_module->i_object_id;
378
379                 /* Add the category to the tree */
380                 AppendItem( root_item, wxU(p_item->psz_text),
381                             -1, -1, config_data );
382                 break;
383             }
384         }
385         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
386
387         SortChildren( root_item );
388     }
389
390
391     /*
392      * Build a tree of all the plugins
393      */
394     plugins_item = AppendItem( root_item, wxU(_("Plugins")) );
395
396     for( i_index = 0; i_index < p_list->i_count; i_index++ )
397     {
398         p_module = (module_t *)p_list->p_values[i_index].p_object;
399
400         /* Exclude the main module */
401         if( !strcmp( p_module->psz_object_name, "main" ) )
402             continue;
403
404         /* Exclude empty plugins */
405         p_item = p_module->p_config;
406         if( !p_item ) continue;
407         do
408         {
409             if( p_item->i_type & CONFIG_ITEM )
410                 break;
411         }
412         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
413         if( p_item->i_type == CONFIG_HINT_END ) continue;
414
415         /* Find the capability child item */
416         long cookie; size_t i_child_index;
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             if( !GetItemText(capability_item).Cmp(
423                     wxU(p_module->psz_capability ) ) )
424             {
425                 break;
426             }
427             capability_item = GetNextChild( plugins_item, cookie );
428         }
429
430         if( i_child_index == GetChildrenCount( plugins_item, FALSE ) &&
431             p_module->psz_capability && *p_module->psz_capability )
432         {
433             /* We didn't find it, add it */
434             capability_item = AppendItem( plugins_item,
435                                           wxU(p_module->psz_capability) );
436         }
437
438         /* Add the plugin to the tree */
439         ConfigTreeData *config_data = new ConfigTreeData;
440         config_data->i_object_id = p_module->i_object_id;
441         AppendItem( capability_item, wxU(p_module->psz_object_name), -1, -1,
442                     config_data );
443     }
444
445     /* Sort all this mess */
446     long cookie; size_t i_child_index;
447     SortChildren( plugins_item );
448     wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
449     for( i_child_index = 0;
450          i_child_index < GetChildrenCount( plugins_item, FALSE );
451          i_child_index++ )
452     {
453         capability_item = GetNextChild( plugins_item, cookie );
454         SortChildren( capability_item );
455     }
456
457     /* Clean-up everything */
458     vlc_list_release( p_list );
459
460     p_sizer->Add( this, 1, wxEXPAND | wxALL, 0 );
461     p_sizer->Layout();
462
463     /* Update Tree Ctrl */
464 #ifndef WIN32 /* Workaround a bug in win32 implementation */
465     SelectItem( GetFirstChild( root_item, cookie ) );
466 #endif
467 }
468
469 PrefsTreeCtrl::~PrefsTreeCtrl()
470 {
471 }
472
473 void PrefsTreeCtrl::ApplyChanges()
474 {
475     long cookie, cookie2;
476     ConfigTreeData *config_data;
477
478     /* Apply changes to the main module */
479     wxTreeItemId item = GetFirstChild( root_item, cookie );
480     for( size_t i_child_index = 0;
481          i_child_index < GetChildrenCount( root_item, FALSE );
482          i_child_index++ )
483     {
484         config_data = (ConfigTreeData *)GetItemData( item );
485         if( config_data && config_data->panel )
486         {
487             config_data->panel->ApplyChanges();
488         }
489
490         item = GetNextChild( root_item, cookie );
491     }
492
493     /* Apply changes to the plugins */
494     item = GetFirstChild( plugins_item, cookie );
495     for( size_t i_child_index = 0;
496          i_child_index < GetChildrenCount( plugins_item, FALSE );
497          i_child_index++ )
498     {
499         wxTreeItemId item2 = GetFirstChild( item, cookie2 );
500         for( size_t i_child_index = 0;
501              i_child_index < GetChildrenCount( item, FALSE );
502              i_child_index++ )
503         {
504             config_data = (ConfigTreeData *)GetItemData( item2 );
505             if( config_data && config_data->panel )
506             {
507                 config_data->panel->ApplyChanges();
508             }
509
510             item2 = GetNextChild( item, cookie2 );
511         }
512
513         item = GetNextChild( plugins_item, cookie );
514     }
515 }
516
517 void PrefsTreeCtrl::CleanChanges()
518 {
519     long cookie, cookie2;
520     ConfigTreeData *config_data;
521
522     /* Clean changes for the main module */
523     wxTreeItemId item = GetFirstChild( root_item, cookie );
524     for( size_t i_child_index = 0;
525          i_child_index < GetChildrenCount( root_item, FALSE );
526          i_child_index++ )
527     {
528         config_data = (ConfigTreeData *)GetItemData( item );
529         if( config_data && config_data->panel )
530         {
531             if( item == GetSelection() )
532             {
533                 config_data->panel->Hide();
534                 p_sizer->Remove( config_data->panel );
535             }
536
537             delete config_data->panel;
538             config_data->panel = NULL;
539
540             if( item == GetSelection() )
541             {
542                 wxTreeEvent event;
543                 OnSelectTreeItem( event );
544             }
545         }
546
547         item = GetNextChild( root_item, cookie );
548     }
549
550     /* Clean changes for the plugins */
551     item = GetFirstChild( plugins_item, cookie );
552     for( size_t i_child_index = 0;
553          i_child_index < GetChildrenCount( plugins_item, FALSE );
554          i_child_index++ )
555     {
556         wxTreeItemId item2 = GetFirstChild( item, cookie2 );
557         for( size_t i_child_index = 0;
558              i_child_index < GetChildrenCount( item, FALSE );
559              i_child_index++ )
560         {
561             config_data = (ConfigTreeData *)GetItemData( item2 );
562
563             if( config_data && config_data->panel )
564             {
565                 if( item2 == GetSelection() )
566                 {
567                     config_data->panel->Hide();
568                     p_sizer->Remove( config_data->panel );
569                 }
570
571                 delete config_data->panel;
572                 config_data->panel = NULL;
573
574                 if( item2 == GetSelection() )
575                 {
576                     wxTreeEvent event;
577                     OnSelectTreeItem( event );
578                 }
579             }
580
581             item2 = GetNextChild( item, cookie2 );
582         }
583
584         item = GetNextChild( plugins_item, cookie );
585     }
586 }
587
588 void PrefsTreeCtrl::OnSelectTreeItem( wxTreeEvent& event )
589 {
590     ConfigTreeData *config_data;
591
592     config_data = (ConfigTreeData *)GetItemData( event.GetOldItem() );
593     if( config_data && config_data->panel )
594     {
595         config_data->panel->Hide();
596         p_sizer->Remove( config_data->panel );
597     }
598
599     /* Don't use event.GetItem() because we also send fake events */
600     config_data = (ConfigTreeData *)GetItemData( GetSelection() );
601     if( config_data )
602     {
603         if( !config_data->panel )
604         {
605             /* The panel hasn't been created yet. Let's do it. */
606             config_data->panel =
607                 new PrefsPanel( p_parent, p_intf, p_prefs_dialog,
608                                 config_data->i_object_id,
609                                 config_data->psz_section );
610         }
611         else
612         {
613             config_data->panel->Show();
614         }
615
616         p_sizer->Add( config_data->panel, 2, wxEXPAND | wxALL, 0 );
617         p_sizer->Layout();
618     }
619 }
620
621 /*****************************************************************************
622  * PrefsPanel class definition.
623  *****************************************************************************/
624 PrefsPanel::PrefsPanel( wxWindow* parent, intf_thread_t *_p_intf,
625                         PrefsDialog *_p_prefs_dialog,
626                         int i_object_id, char *psz_section )
627   :  wxPanel( parent, -1, wxDefaultPosition, wxDefaultSize )
628 {
629     module_config_t *p_item;
630     vlc_list_t      *p_list;
631     module_t        *p_parser;
632
633     wxStaticText *label;
634     wxComboBox *combo;
635     wxSpinCtrl *spin;
636     wxCheckBox *checkbox;
637     wxTextCtrl *textctrl;
638     wxButton *button;
639     wxArrayString array;
640
641     /* Initializations */
642     p_intf = _p_intf;
643     p_prefs_dialog =_p_prefs_dialog,
644
645     b_advanced = VLC_TRUE;
646     SetAutoLayout( TRUE );
647
648     wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
649
650     /* Get a pointer to the module */
651     module_t *p_module = (module_t *)vlc_object_get( p_intf, i_object_id );
652     if( p_module->i_object_type != VLC_OBJECT_MODULE )
653     {
654         /* 0OOoo something went really bad */
655         return;
656     }
657
658     /* Enumerate config options and add corresponding config boxes */
659     p_item = p_module->p_config;
660
661     /* Find the category if it has been specified */
662     if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY )
663     {
664         while( !p_item->i_type == CONFIG_HINT_CATEGORY ||
665                strcmp( psz_section, p_item->psz_text ) )
666         {
667             if( p_item->i_type == CONFIG_HINT_END )
668                 break;
669             p_item++;
670         }
671     }
672
673     /* Add a head title to the panel */
674     wxStaticBox *static_box = new wxStaticBox( this, -1, wxT("") );
675     wxStaticBoxSizer *box_sizer = new wxStaticBoxSizer( static_box,
676                                                         wxHORIZONTAL );
677     label = new wxStaticText( this, -1,
678                               wxU(psz_section ? p_item->psz_text :
679                               p_module->psz_longname) );
680
681     box_sizer->Add( label, 1, wxALL, 5 );
682     sizer->Add( box_sizer, 0, wxEXPAND | wxALL, 5 );
683
684     /* Now put all the config options into a scrolled window */
685     config_sizer = new wxBoxSizer( wxVERTICAL );
686     config_window = new wxScrolledWindow( this, -1, wxDefaultPosition,
687         wxDefaultSize, wxSTATIC_BORDER | wxHSCROLL | wxVSCROLL );
688     config_window->SetAutoLayout( TRUE );
689     config_window->SetScrollRate( 5, 5 );
690
691     if( p_item ) do
692     {
693         /* If a category has been specified, check we finished the job */
694         if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY &&
695             strcmp( psz_section, p_item->psz_text ) )
696             break;
697
698         /* put each config option in a separate panel so we can hide advanced
699          * options easily */
700         wxPanel *panel = new wxPanel( config_window, -1, wxDefaultPosition,
701                                       wxDefaultSize );
702         wxBoxSizer *panel_sizer = new wxBoxSizer( wxHORIZONTAL );
703         ConfigData *config_data =
704             new ConfigData( panel, p_item->i_type,
705                             p_item->b_advanced, p_item->psz_name );
706
707         switch( p_item->i_type )
708         {
709         case CONFIG_ITEM_MODULE:
710             label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
711             combo = new wxComboBox( panel, -1, wxU(p_item->psz_value),
712                                     wxDefaultPosition, wxDefaultSize,
713                                     0, NULL, wxCB_READONLY | wxCB_SORT );
714
715             /* build a list of available modules */
716             p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
717             combo->Append( wxU(_("Default")), (void *)NULL );
718             combo->SetSelection( 0 );
719             for( int i_index = 0; i_index < p_list->i_count; i_index++ )
720             {
721                 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
722
723                 if( !strcmp( p_parser->psz_capability,
724                              p_item->psz_type ) )
725                 {
726                     combo->Append( wxU(p_parser->psz_longname),
727                                    p_parser->psz_object_name );
728                     if( p_item->psz_value &&
729                         !strcmp(p_item->psz_value, p_parser->psz_object_name) )
730                         combo->SetValue( wxU(p_parser->psz_longname) );
731                 }
732             }
733             vlc_list_release( p_list );
734
735             combo->SetToolTip( wxU(p_item->psz_longtext) );
736             config_data->control.combobox = combo;
737             panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
738             panel_sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
739             break;
740
741         case CONFIG_ITEM_STRING:
742         case CONFIG_ITEM_FILE:
743         case CONFIG_ITEM_DIRECTORY:
744             label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
745             panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
746
747             if( !p_item->ppsz_list )
748             {
749                 textctrl = new wxTextCtrl( panel, -1, wxU(p_item->psz_value),
750                                            wxDefaultPosition, wxDefaultSize,
751                                            wxTE_PROCESS_ENTER);
752                 textctrl->SetToolTip( wxU(p_item->psz_longtext) );
753                 config_data->control.textctrl = textctrl;
754                 panel_sizer->Add( textctrl, 1, wxALL, 5 );
755             }
756             else
757             {
758                 combo = new wxComboBox( panel, -1, wxU(p_item->psz_value),
759                                         wxDefaultPosition, wxDefaultSize,
760                                         0, NULL, wxCB_READONLY | wxCB_SORT );
761
762                 /* build a list of available options */
763                 for( int i_index = 0; p_item->ppsz_list[i_index]; i_index++ )
764                 {
765                     combo->Append( wxU(p_item->ppsz_list[i_index]) );
766                 }
767
768                 if( p_item->psz_value )
769                     combo->SetValue( wxU(p_item->psz_value) );
770                 combo->SetToolTip( wxU(p_item->psz_longtext) );
771                 config_data->control.combobox = combo;
772                 config_data->b_config_list = VLC_TRUE;
773                 panel_sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
774             }
775
776             if( p_item->i_type == CONFIG_ITEM_FILE )
777             {
778                 button = new wxButton( panel, -1, wxU(_("Browse...")) );
779                 panel_sizer->Add( button, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
780                 button->SetClientData((void *)config_data);
781             }
782             break;
783
784         case CONFIG_ITEM_INTEGER:
785             label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
786             spin = new wxSpinCtrl( panel, -1,
787                                    wxString::Format(wxT("%d"),p_item->i_value),
788                                    wxDefaultPosition, wxDefaultSize,
789                                    wxSP_ARROW_KEYS,
790                                    -16000, 16000, p_item->i_value);
791             spin->SetToolTip( wxU(p_item->psz_longtext) );
792             config_data->control.spinctrl = spin;
793             panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
794             panel_sizer->Add( spin, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
795
796             spin->SetClientData((void *)config_data);
797             break;
798
799         case CONFIG_ITEM_FLOAT:
800             label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
801             spin = new wxSpinCtrl( panel, -1,
802                                    wxString::Format(wxT("%f"),p_item->f_value),
803                                    wxDefaultPosition, wxDefaultSize,
804                                    wxSP_ARROW_KEYS,
805                                    -16000, 16000, (int)p_item->f_value);
806             spin->SetToolTip( wxU(p_item->psz_longtext) );
807             config_data->control.spinctrl = spin;
808             panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
809             panel_sizer->Add( spin, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
810             break;
811
812         case CONFIG_ITEM_BOOL:
813             checkbox = new wxCheckBox( panel, -1, wxU(p_item->psz_text) );
814             if( p_item->i_value ) checkbox->SetValue(TRUE);
815             checkbox->SetToolTip( wxU(p_item->psz_longtext) );
816             config_data->control.checkbox = checkbox;
817             panel_sizer->Add( checkbox, 0, wxALL, 5 );
818             break;
819
820         default:
821             delete panel; panel = NULL;
822             delete panel_sizer;
823             delete config_data;
824             break;
825         }
826
827         /* Don't add items that were not recognized */
828         if( panel == NULL ) continue;
829
830         panel_sizer->Layout();
831         panel->SetSizerAndFit( panel_sizer );
832
833         /* Add the config data to our array so we can keep a trace of it */
834         config_array.Add( config_data );
835
836         config_sizer->Add( panel, 0, wxEXPAND | wxALL, 2 );
837     }
838     while( p_item->i_type != CONFIG_HINT_END && p_item++ );
839
840     /* Display a nice message if no configuration options are available */
841     if( !config_array.GetCount() )
842     {
843         config_sizer->Add( new wxStaticText( config_window, -1,
844                            wxU(_("No configuration options available")) ), 1,
845                            wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER, 2 );
846     }
847
848     config_sizer->Layout();
849     config_window->SetSizer( config_sizer );
850     sizer->Add( config_window, 1, wxEXPAND | wxALL, 5 );
851
852     /* Intercept all menu events in our custom event handler */
853     config_window->PushEventHandler(
854         new ConfigEvtHandler( p_intf, p_prefs_dialog ) );
855
856     /* Update panel */
857     wxCommandEvent dummy_event;
858     b_advanced = !config_GetInt( p_intf, "advanced" );
859     OnAdvanced( dummy_event );
860
861     /* Create advanced checkbox */
862     if( config_array.GetCount() )
863     {
864         wxCheckBox *advanced_checkbox =
865            new wxCheckBox( this, Advanced_Event, wxU(_("Advanced options")) );
866
867         if( b_advanced ) advanced_checkbox->SetValue(TRUE);
868         sizer->Add( advanced_checkbox, 0, wxALL|wxALIGN_RIGHT, 0 );
869     }
870
871     sizer->Layout();
872     SetSizer( sizer );
873 }
874
875 void PrefsPanel::ApplyChanges()
876 {
877     for( size_t i = 0; i < config_array.GetCount(); i++ )
878     {
879         ConfigData *config_data = config_array.Item(i);
880
881         switch( config_data->i_config_type )
882         {
883         case CONFIG_ITEM_MODULE:
884             config_PutPsz( p_intf, config_data->option_name.mb_str(), (char *)
885                            config_data->control.combobox->GetClientData(
886                            config_data->control.combobox->GetSelection() ) );
887             break;
888         case CONFIG_ITEM_STRING:
889         case CONFIG_ITEM_FILE:
890         case CONFIG_ITEM_DIRECTORY:
891             if( !config_data->b_config_list )
892                 config_PutPsz( p_intf, config_data->option_name.mb_str(),
893                                config_data->control.textctrl->GetValue().mb_str() );
894             else
895                 config_PutPsz( p_intf, config_data->option_name.mb_str(),
896                                config_data->control.combobox->GetValue().mb_str() );
897             break;
898         case CONFIG_ITEM_BOOL:
899             config_PutInt( p_intf, config_data->option_name.mb_str(),
900                            config_data->control.checkbox->IsChecked() );
901             break;
902         case CONFIG_ITEM_INTEGER:
903             config_PutInt( p_intf, config_data->option_name.mb_str(),
904                            config_data->control.spinctrl->GetValue() );
905             break;
906         case CONFIG_ITEM_FLOAT:
907             config_PutFloat( p_intf, config_data->option_name.mb_str(),
908                              config_data->control.spinctrl->GetValue() );
909             break;
910         }
911     }
912 }
913
914 void PrefsPanel::OnAdvanced( wxCommandEvent& WXUNUSED(event) )
915 {
916     b_advanced = !b_advanced;
917
918     for( size_t i = 0; i < config_array.GetCount(); i++ )
919     {
920         ConfigData *config_data = config_array.Item(i);
921         if( config_data->b_advanced )
922         {
923             config_data->panel->Show( b_advanced );
924             config_sizer->Show( config_data->panel, b_advanced );
925         }
926     }
927
928     config_sizer->Layout();
929     config_window->FitInside();
930     config_window->Refresh();
931 }
932
933 /*****************************************************************************
934  * A small helper class which intercepts all events
935  *****************************************************************************/
936 ConfigEvtHandler::ConfigEvtHandler( intf_thread_t *_p_intf,
937                                     PrefsDialog *_p_prefs_dialog )
938 {
939     /* Initializations */
940     p_intf = _p_intf;
941     p_prefs_dialog = _p_prefs_dialog;
942 }
943
944 ConfigEvtHandler::~ConfigEvtHandler()
945 {
946 }
947
948 void ConfigEvtHandler::OnCommandEvent( wxCommandEvent& event )
949 {
950     if( !event.GetEventObject() )
951     {
952         event.Skip();
953         return;
954     }
955
956     ConfigData *config_data = (ConfigData *)
957         ((wxEvtHandler *)event.GetEventObject())->GetClientData();
958
959     if( !config_data )
960     {
961         event.Skip();
962         return;
963     }
964
965     if( config_data->i_config_type == CONFIG_ITEM_FILE )
966     {
967         wxFileDialog dialog( p_prefs_dialog, wxU(_("Open file")),
968                              wxT(""), wxT(""), wxT("*.*"), wxOPEN | wxSAVE );
969
970         if( dialog.ShowModal() == wxID_OK )
971         {
972             config_data->control.textctrl->SetValue( dialog.GetPath() );      
973         }
974     }
975
976     switch( config_data->i_config_type )
977     {
978     case CONFIG_ITEM_MODULE:
979         break;
980     case CONFIG_ITEM_STRING:
981         break;
982     case CONFIG_ITEM_FILE:
983         break;
984     case CONFIG_ITEM_INTEGER:
985         break;
986     case CONFIG_ITEM_FLOAT:
987         break;
988     case CONFIG_ITEM_BOOL:
989         break;
990     }
991
992     event.Skip();
993 }