1 /*****************************************************************************
2 * preferences.cpp : wxWindows plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2000-2001 VideoLAN
5 * $Id: preferences.cpp,v 1.25 2003/08/14 19:25:56 sigmunau Exp $
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdlib.h> /* malloc(), free() */
28 #include <errno.h> /* ENOMEM */
29 #include <string.h> /* strerror() */
34 #ifdef WIN32 /* mingw32 hack */
39 /* Let vlc take care of the i18n stuff */
40 #define WXINTL_NO_GETTEXT_MACRO
42 #include <wx/wxprec.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>
56 #if defined MODULE_NAME_IS_skins
57 # include "../skins/src/skin_common.h"
60 #include "wxwindows.h"
63 # define wxRB_SINGLE 0
66 /*****************************************************************************
67 * Classes declarations.
68 *****************************************************************************/
70 class PrefsTreeCtrl : public wxTreeCtrl
75 PrefsTreeCtrl( wxWindow *parent, intf_thread_t *_p_intf,
76 PrefsDialog *p_prefs_dialog, wxBoxSizer *_p_sizer );
77 virtual ~PrefsTreeCtrl();
83 /* Event handlers (these functions should _not_ be virtual) */
84 void OnSelectTreeItem( wxTreeEvent& event );
85 ConfigTreeData *FindModuleConfig( ConfigTreeData *config_data );
89 intf_thread_t *p_intf;
90 PrefsDialog *p_prefs_dialog;
94 wxTreeItemId root_item;
95 wxTreeItemId plugins_item;
100 ConfigData( wxPanel *_panel, int _i_conf_type,
101 vlc_bool_t _b_advanced, char *psz_name )
102 { panel = _panel; b_advanced = _b_advanced; b_config_list = VLC_FALSE;
103 i_config_type = _i_conf_type; option_name = wxU(psz_name); }
105 vlc_bool_t b_advanced;
107 vlc_bool_t b_config_list;
111 wxComboBox *combobox;
112 wxRadioButton *radio;
113 wxSpinCtrl *spinctrl;
114 wxCheckBox *checkbox;
115 wxTextCtrl *textctrl;
120 wxString option_name;
123 WX_DEFINE_ARRAY(ConfigData *, ArrayOfConfigData);
125 class PrefsPanel : public wxPanel
130 PrefsPanel( wxWindow *parent, intf_thread_t *_p_intf,
131 PrefsDialog *_p_prefs_dialog, int i_object_id, char * );
132 virtual ~PrefsPanel() {}
137 void OnAdvanced( wxCommandEvent& WXUNUSED(event) );
138 DECLARE_EVENT_TABLE()
140 intf_thread_t *p_intf;
141 PrefsDialog *p_prefs_dialog;
143 vlc_bool_t b_advanced;
145 wxBoxSizer *config_sizer;
146 wxScrolledWindow *config_window;
148 ArrayOfConfigData config_array;
151 class ConfigTreeData : public wxTreeItemData
155 ConfigTreeData() { b_submodule = 0; panel = NULL; psz_section = NULL; }
156 virtual ~ConfigTreeData() { if( panel ) delete panel; }
158 vlc_bool_t b_submodule;
166 class ConfigEvtHandler : public wxEvtHandler
169 ConfigEvtHandler( intf_thread_t *p_intf, PrefsDialog *p_prefs_dialog );
170 virtual ~ConfigEvtHandler();
172 void ConfigEvtHandler::OnCommandEvent( wxCommandEvent& event );
176 DECLARE_EVENT_TABLE()
178 intf_thread_t *p_intf;
179 PrefsDialog *p_prefs_dialog;
182 /*****************************************************************************
184 *****************************************************************************/
186 /* IDs for the controls and the menu commands */
189 Notebook_Event = wxID_HIGHEST,
195 BEGIN_EVENT_TABLE(PrefsDialog, wxFrame)
197 EVT_BUTTON(wxID_OK, PrefsDialog::OnOk)
198 EVT_BUTTON(wxID_CANCEL, PrefsDialog::OnCancel)
199 EVT_BUTTON(wxID_SAVE, PrefsDialog::OnSave)
200 EVT_BUTTON(ResetAll_Event, PrefsDialog::OnResetAll)
202 /* Don't destroy the window when the user closes it */
203 EVT_CLOSE(PrefsDialog::OnCancel)
206 // menu and control ids
209 PrefsTree_Ctrl = wxID_HIGHEST
212 BEGIN_EVENT_TABLE(PrefsTreeCtrl, wxTreeCtrl)
213 EVT_TREE_SEL_CHANGED(PrefsTree_Ctrl, PrefsTreeCtrl::OnSelectTreeItem)
216 BEGIN_EVENT_TABLE(PrefsPanel, wxPanel)
218 EVT_CHECKBOX(Advanced_Event, PrefsPanel::OnAdvanced)
222 BEGIN_EVENT_TABLE(ConfigEvtHandler, wxEvtHandler)
223 EVT_BUTTON(-1, ConfigEvtHandler::OnCommandEvent)
224 EVT_TEXT(-1, ConfigEvtHandler::OnCommandEvent)
225 EVT_RADIOBOX(-1, ConfigEvtHandler::OnCommandEvent)
226 EVT_SPINCTRL(-1, ConfigEvtHandler::OnCommandEvent)
229 /*****************************************************************************
231 *****************************************************************************/
232 PrefsDialog::PrefsDialog( intf_thread_t *_p_intf, wxWindow *p_parent)
233 : wxFrame( p_parent, -1, wxU(_("Preferences")), wxDefaultPosition,
234 wxSize(650,450), wxDEFAULT_FRAME_STYLE )
236 /* Initializations */
238 SetIcon( *p_intf->p_sys->p_icon );
240 /* Create a panel to put everything in */
241 wxPanel *panel = new wxPanel( this, -1 );
242 panel->SetAutoLayout( TRUE );
244 /* Create the preferences tree control */
245 wxBoxSizer *controls_sizer = new wxBoxSizer( wxHORIZONTAL );
247 new PrefsTreeCtrl( panel, p_intf, this, controls_sizer );
250 wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
252 /* Create the buttons */
253 wxButton *ok_button = new wxButton( panel, wxID_OK, wxU(_("OK")) );
254 ok_button->SetDefault();
255 wxButton *cancel_button = new wxButton( panel, wxID_CANCEL,
257 wxButton *save_button = new wxButton( panel, wxID_SAVE, wxU(_("Save")) );
258 wxButton *reset_button = new wxButton( panel, ResetAll_Event,
259 wxU(_("Reset All")) );
261 /* Place everything in sizers */
262 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
263 button_sizer->Add( ok_button, 0, wxALL, 5 );
264 button_sizer->Add( cancel_button, 0, wxALL, 5 );
265 button_sizer->Add( save_button, 0, wxALL, 5 );
266 button_sizer->Add( reset_button, 0, wxALL, 5 );
267 button_sizer->Layout();
269 wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
270 wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
271 panel_sizer->Add( controls_sizer, 1, wxEXPAND | wxALL, 5 );
272 panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
273 panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALIGN_BOTTOM |
275 panel_sizer->Layout();
276 panel->SetSizer( panel_sizer );
277 main_sizer->Add( panel, 1, wxEXPAND, 0 );
278 main_sizer->Layout();
279 SetSizer( main_sizer );
282 PrefsDialog::~PrefsDialog()
286 /*****************************************************************************
288 *****************************************************************************/
291 /*****************************************************************************
293 *****************************************************************************/
294 void PrefsDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
296 prefs_tree->ApplyChanges();
298 prefs_tree->CleanChanges();
301 void PrefsDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
304 prefs_tree->CleanChanges();
307 void PrefsDialog::OnSave( wxCommandEvent& WXUNUSED(event) )
309 prefs_tree->ApplyChanges();
310 config_SaveConfigFile( p_intf, NULL );
313 void PrefsDialog::OnResetAll( wxCommandEvent& WXUNUSED(event) )
315 wxMessageDialog dlg( this,
316 wxU(_("Beware this will reset your VLC Media Player config file.\n"
317 "Are you sure you want to continue?")),
318 wxU(_("Reset config file")), wxYES_NO|wxNO_DEFAULT|wxCENTRE );
320 if ( dlg.ShowModal() == wxID_YES )
322 /* TODO: need to reset all the controls */
323 config_ResetAll( p_intf );
324 prefs_tree->CleanChanges();
325 config_SaveConfigFile( p_intf, NULL );
329 /*****************************************************************************
330 * PrefsTreeCtrl class definition.
331 *****************************************************************************/
332 PrefsTreeCtrl::PrefsTreeCtrl( wxWindow *_p_parent, intf_thread_t *_p_intf,
333 PrefsDialog *_p_prefs_dialog,
334 wxBoxSizer *_p_sizer )
335 : wxTreeCtrl( _p_parent, PrefsTree_Ctrl, wxDefaultPosition, wxDefaultSize,
336 wxTR_NO_LINES | wxTR_FULL_ROW_HIGHLIGHT |
337 wxTR_LINES_AT_ROOT | wxTR_HIDE_ROOT |
338 wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS | wxSUNKEN_BORDER )
342 module_config_t *p_item;
345 /* Initializations */
347 p_prefs_dialog = _p_prefs_dialog;
349 p_parent = _p_parent;
351 root_item = AddRoot( wxT("") );
353 /* List the plugins */
354 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
355 if( !p_list ) return;
358 * Build a tree of the main options
360 for( i_index = 0; i_index < p_list->i_count; i_index++ )
362 p_module = (module_t *)p_list->p_values[i_index].p_object;
363 if( !strcmp( p_module->psz_object_name, "main" ) )
366 if( i_index < p_list->i_count )
368 /* We found the main module */
370 /* Enumerate config categories and store a reference so we can
371 * generate their config panel them when it is asked by the user. */
372 p_item = p_module->p_config;
376 switch( p_item->i_type )
378 case CONFIG_HINT_CATEGORY:
379 ConfigTreeData *config_data = new ConfigTreeData;
380 config_data->psz_section = strdup(p_item->psz_text);
381 config_data->i_object_id = p_module->i_object_id;
383 /* Add the category to the tree */
384 AppendItem( root_item, wxU(p_item->psz_text),
385 -1, -1, config_data );
389 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
391 SortChildren( root_item );
396 * Build a tree of all the plugins
398 plugins_item = AppendItem( root_item, wxU(_("Plugins")) );
400 for( i_index = 0; i_index < p_list->i_count; i_index++ )
402 p_module = (module_t *)p_list->p_values[i_index].p_object;
404 /* Exclude the main module */
405 if( !strcmp( p_module->psz_object_name, "main" ) )
408 /* Exclude empty plugins (submodules don't have config options, they
409 * are stored in the parent module) */
410 if( p_module->b_submodule )
411 p_item = ((module_t *)p_module->p_parent)->p_config;
413 p_item = p_module->p_config;
415 if( !p_item ) continue;
418 if( p_item->i_type & CONFIG_ITEM )
421 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
422 if( p_item->i_type == CONFIG_HINT_END ) continue;
424 /* Find the capability child item */
425 long cookie; size_t i_child_index;
426 wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
427 for( i_child_index = 0;
428 i_child_index < GetChildrenCount( plugins_item, FALSE );
431 if( !GetItemText(capability_item).Cmp(
432 wxU(p_module->psz_capability ) ) )
436 capability_item = GetNextChild( plugins_item, cookie );
439 if( i_child_index == GetChildrenCount( plugins_item, FALSE ) &&
440 p_module->psz_capability && *p_module->psz_capability )
442 /* We didn't find it, add it */
443 capability_item = AppendItem( plugins_item,
444 wxU(p_module->psz_capability) );
447 /* Add the plugin to the tree */
448 ConfigTreeData *config_data = new ConfigTreeData;
449 config_data->b_submodule = p_module->b_submodule;
450 config_data->i_object_id = p_module->b_submodule ?
451 ((module_t *)p_module->p_parent)->i_object_id :
452 p_module->i_object_id;
453 AppendItem( capability_item, wxU(p_module->psz_object_name), -1, -1,
457 /* Sort all this mess */
458 long cookie; size_t i_child_index;
459 SortChildren( plugins_item );
460 wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
461 for( i_child_index = 0;
462 i_child_index < GetChildrenCount( plugins_item, FALSE );
465 capability_item = GetNextChild( plugins_item, cookie );
466 SortChildren( capability_item );
469 /* Clean-up everything */
470 vlc_list_release( p_list );
472 p_sizer->Add( this, 1, wxEXPAND | wxALL, 0 );
475 /* Update Tree Ctrl */
476 #ifndef WIN32 /* Workaround a bug in win32 implementation */
477 SelectItem( GetFirstChild( root_item, cookie ) );
481 PrefsTreeCtrl::~PrefsTreeCtrl()
485 void PrefsTreeCtrl::ApplyChanges()
487 long cookie, cookie2;
488 ConfigTreeData *config_data;
490 /* Apply changes to the main module */
491 wxTreeItemId item = GetFirstChild( root_item, cookie );
492 for( size_t i_child_index = 0;
493 i_child_index < GetChildrenCount( root_item, FALSE );
496 config_data = (ConfigTreeData *)GetItemData( item );
497 if( config_data && config_data->panel )
499 config_data->panel->ApplyChanges();
502 item = GetNextChild( root_item, cookie );
505 /* Apply changes to the plugins */
506 item = GetFirstChild( plugins_item, cookie );
507 for( size_t i_child_index = 0;
508 i_child_index < GetChildrenCount( plugins_item, FALSE );
511 wxTreeItemId item2 = GetFirstChild( item, cookie2 );
512 for( size_t i_child_index = 0;
513 i_child_index < GetChildrenCount( item, FALSE );
516 config_data = (ConfigTreeData *)GetItemData( item2 );
517 if( config_data && config_data->panel )
519 config_data->panel->ApplyChanges();
522 item2 = GetNextChild( item, cookie2 );
525 item = GetNextChild( plugins_item, cookie );
529 void PrefsTreeCtrl::CleanChanges()
531 long cookie, cookie2;
532 ConfigTreeData *config_data;
534 config_data = !GetSelection() ? NULL :
535 FindModuleConfig( (ConfigTreeData *)GetItemData( GetSelection() ) );
538 config_data->panel->Hide();
539 p_sizer->Remove( config_data->panel );
542 /* Clean changes for the main module */
543 wxTreeItemId item = GetFirstChild( root_item, cookie );
544 for( size_t i_child_index = 0;
545 i_child_index < GetChildrenCount( root_item, FALSE );
548 config_data = (ConfigTreeData *)GetItemData( item );
549 if( config_data && config_data->panel )
551 delete config_data->panel;
552 config_data->panel = NULL;
555 item = GetNextChild( root_item, cookie );
558 /* Clean changes for the plugins */
559 item = GetFirstChild( plugins_item, cookie );
560 for( size_t i_child_index = 0;
561 i_child_index < GetChildrenCount( plugins_item, FALSE );
564 wxTreeItemId item2 = GetFirstChild( item, cookie2 );
565 for( size_t i_child_index = 0;
566 i_child_index < GetChildrenCount( item, FALSE );
569 config_data = (ConfigTreeData *)GetItemData( item2 );
571 if( config_data && config_data->panel )
573 delete config_data->panel;
574 config_data->panel = NULL;
577 item2 = GetNextChild( item, cookie2 );
580 item = GetNextChild( plugins_item, cookie );
586 OnSelectTreeItem( event );
590 ConfigTreeData *PrefsTreeCtrl::FindModuleConfig( ConfigTreeData *config_data )
592 /* We need this complexity because submodules don't have their own config
593 * options. They use the parent module ones. */
595 if( !config_data || !config_data->b_submodule )
600 long cookie, cookie2;
601 ConfigTreeData *config_new;
602 wxTreeItemId item = GetFirstChild( plugins_item, cookie );
603 for( size_t i_child_index = 0;
604 i_child_index < GetChildrenCount( plugins_item, FALSE );
607 wxTreeItemId item2 = GetFirstChild( item, cookie2 );
608 for( size_t i_child_index = 0;
609 i_child_index < GetChildrenCount( item, FALSE );
612 config_new = (ConfigTreeData *)GetItemData( item2 );
613 if( config_new && !config_new->b_submodule &&
614 config_new->i_object_id == config_data->i_object_id )
619 item2 = GetNextChild( item, cookie2 );
622 item = GetNextChild( plugins_item, cookie );
629 void PrefsTreeCtrl::OnSelectTreeItem( wxTreeEvent& event )
631 ConfigTreeData *config_data;
633 config_data = FindModuleConfig( (ConfigTreeData *)GetItemData(
634 event.GetOldItem() ) );
635 if( config_data && config_data->panel )
637 config_data->panel->Hide();
638 p_sizer->Remove( config_data->panel );
641 /* Don't use event.GetItem() because we also send fake events */
642 config_data = FindModuleConfig( (ConfigTreeData *)GetItemData(
646 if( !config_data->panel )
648 /* The panel hasn't been created yet. Let's do it. */
650 new PrefsPanel( p_parent, p_intf, p_prefs_dialog,
651 config_data->i_object_id,
652 config_data->psz_section );
656 config_data->panel->Show();
659 p_sizer->Add( config_data->panel, 2, wxEXPAND | wxALL, 0 );
664 /*****************************************************************************
665 * PrefsPanel class definition.
666 *****************************************************************************/
667 PrefsPanel::PrefsPanel( wxWindow* parent, intf_thread_t *_p_intf,
668 PrefsDialog *_p_prefs_dialog,
669 int i_object_id, char *psz_section )
670 : wxPanel( parent, -1, wxDefaultPosition, wxDefaultSize )
672 module_config_t *p_item;
679 wxCheckBox *checkbox;
680 wxTextCtrl *textctrl;
684 vlc_bool_t b_has_advanced = VLC_FALSE;
686 /* Initializations */
688 p_prefs_dialog =_p_prefs_dialog,
690 b_advanced = VLC_TRUE;
691 SetAutoLayout( TRUE );
693 wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
695 /* Get a pointer to the module */
696 module_t *p_module = (module_t *)vlc_object_get( p_intf, i_object_id );
697 if( p_module->i_object_type != VLC_OBJECT_MODULE )
699 /* 0OOoo something went really bad */
703 /* Enumerate config options and add corresponding config boxes
704 * (submodules don't have config options, they are stored in the
706 if( p_module->b_submodule )
707 p_item = ((module_t *)p_module->p_parent)->p_config;
709 p_item = p_module->p_config;
711 /* Find the category if it has been specified */
712 if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY )
714 while( !p_item->i_type == CONFIG_HINT_CATEGORY ||
715 strcmp( psz_section, p_item->psz_text ) )
717 if( p_item->i_type == CONFIG_HINT_END )
723 /* Add a head title to the panel */
724 wxStaticBox *static_box = new wxStaticBox( this, -1, wxT("") );
725 wxStaticBoxSizer *box_sizer = new wxStaticBoxSizer( static_box,
727 label = new wxStaticText( this, -1,
728 wxU(psz_section ? p_item->psz_text :
729 p_module->psz_longname) );
731 box_sizer->Add( label, 1, wxALL, 5 );
732 sizer->Add( box_sizer, 0, wxEXPAND | wxALL, 5 );
734 /* Now put all the config options into a scrolled window */
735 config_sizer = new wxBoxSizer( wxVERTICAL );
736 config_window = new wxScrolledWindow( this, -1, wxDefaultPosition,
737 wxDefaultSize, wxSTATIC_BORDER | wxHSCROLL | wxVSCROLL );
738 config_window->SetAutoLayout( TRUE );
739 config_window->SetScrollRate( 5, 5 );
743 /* If a category has been specified, check we finished the job */
744 if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY &&
745 strcmp( psz_section, p_item->psz_text ) )
748 /* put each config option in a separate panel so we can hide advanced
750 wxPanel *panel = new wxPanel( config_window, -1, wxDefaultPosition,
752 wxBoxSizer *panel_sizer = new wxBoxSizer( wxHORIZONTAL );
753 ConfigData *config_data =
754 new ConfigData( panel, p_item->i_type,
755 p_item->b_advanced, p_item->psz_name );
757 switch( p_item->i_type )
759 case CONFIG_ITEM_MODULE:
760 label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
761 combo = new wxComboBox( panel, -1, wxU(p_item->psz_value),
762 wxDefaultPosition, wxDefaultSize,
763 0, NULL, wxCB_READONLY | wxCB_SORT );
765 /* build a list of available modules */
766 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
767 combo->Append( wxU(_("Default")), (void *)NULL );
768 combo->SetSelection( 0 );
769 for( int i_index = 0; i_index < p_list->i_count; i_index++ )
771 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
773 if( !strcmp( p_parser->psz_capability,
776 combo->Append( wxU(p_parser->psz_longname),
777 p_parser->psz_object_name );
778 if( p_item->psz_value &&
779 !strcmp(p_item->psz_value, p_parser->psz_object_name) )
780 combo->SetValue( wxU(p_parser->psz_longname) );
783 vlc_list_release( p_list );
785 combo->SetToolTip( wxU(p_item->psz_longtext) );
786 config_data->control.combobox = combo;
787 panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
788 panel_sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
789 if( p_item->b_advanced ) b_has_advanced = VLC_TRUE;
792 case CONFIG_ITEM_STRING:
793 case CONFIG_ITEM_FILE:
794 case CONFIG_ITEM_DIRECTORY:
795 label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
796 panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
798 if( !p_item->ppsz_list )
800 textctrl = new wxTextCtrl( panel, -1, wxU(p_item->psz_value),
801 wxDefaultPosition, wxDefaultSize,
803 textctrl->SetToolTip( wxU(p_item->psz_longtext) );
804 config_data->control.textctrl = textctrl;
805 panel_sizer->Add( textctrl, 1, wxALL, 5 );
809 combo = new wxComboBox( panel, -1, wxU(p_item->psz_value),
810 wxDefaultPosition, wxDefaultSize,
811 0, NULL, wxCB_READONLY | wxCB_SORT );
813 /* build a list of available options */
814 for( int i_index = 0; p_item->ppsz_list[i_index]; i_index++ )
816 combo->Append( wxU(p_item->ppsz_list[i_index]) );
817 if( p_item->psz_value && !strcmp( p_item->psz_value,
818 p_item->ppsz_list[i_index] ) )
819 combo->SetSelection( i_index );
822 if( p_item->psz_value )
823 combo->SetValue( wxU(p_item->psz_value) );
824 combo->SetToolTip( wxU(p_item->psz_longtext) );
825 config_data->control.combobox = combo;
826 config_data->b_config_list = VLC_TRUE;
827 panel_sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
830 if( p_item->i_type == CONFIG_ITEM_FILE )
832 button = new wxButton( panel, -1, wxU(_("Browse...")) );
833 panel_sizer->Add( button, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
834 button->SetClientData((void *)config_data);
836 if( p_item->b_advanced ) b_has_advanced = VLC_TRUE;
839 case CONFIG_ITEM_INTEGER:
840 label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
841 spin = new wxSpinCtrl( panel, -1,
842 wxString::Format(wxT("%d"),p_item->i_value),
843 wxDefaultPosition, wxDefaultSize,
845 -16000, 16000, p_item->i_value);
846 spin->SetToolTip( wxU(p_item->psz_longtext) );
847 config_data->control.spinctrl = spin;
848 panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
849 panel_sizer->Add( spin, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
851 spin->SetClientData((void *)config_data);
852 if( p_item->b_advanced ) b_has_advanced = VLC_TRUE;
854 case CONFIG_ITEM_KEY:
856 label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
857 wxCheckBox *alt = new wxCheckBox( panel, -1, wxU(_("Alt")) );
858 alt->SetValue( p_item->i_value & KEY_MODIFIER_ALT );
859 wxCheckBox *ctrl = new wxCheckBox( panel, -1, wxU(_("Ctrl")) );
860 ctrl->SetValue( p_item->i_value & KEY_MODIFIER_CTRL );
861 wxCheckBox *shift = new wxCheckBox( panel, -1, wxU(_("Shift")) );
862 shift->SetValue( p_item->i_value & KEY_MODIFIER_SHIFT );
863 combo = new wxComboBox( panel, -1, wxU("f"), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY | wxCB_SORT );
864 for( int i = 0; i < sizeof(keys)/sizeof(key_descriptor_s); i++ )
866 combo->Append( wxU(_(keys[i].psz_key_string)), (void*)&keys[i].i_key_code );
868 combo->SetValue( wxU( KeyToString( p_item->i_value&~KEY_MODIFIER )));
869 config_data->control.combobox = combo;
870 panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
871 panel_sizer->Add( alt, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
872 panel_sizer->Add( ctrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
873 panel_sizer->Add( shift, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
874 panel_sizer->Add( combo, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
877 case CONFIG_ITEM_FLOAT:
878 label = new wxStaticText(panel, -1, wxU(p_item->psz_text));
879 textctrl = new wxTextCtrl( panel, -1,
880 wxString::Format(wxT("%f"),p_item->f_value),
881 wxDefaultPosition, wxDefaultSize,
882 wxTE_PROCESS_ENTER );
883 textctrl->SetToolTip( wxU(p_item->psz_longtext) );
884 config_data->control.textctrl = textctrl;
885 panel_sizer->Add( label, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
886 panel_sizer->Add( textctrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
887 if( p_item->b_advanced ) b_has_advanced = VLC_TRUE;
890 case CONFIG_ITEM_BOOL:
891 checkbox = new wxCheckBox( panel, -1, wxU(p_item->psz_text) );
892 if( p_item->i_value ) checkbox->SetValue(TRUE);
893 checkbox->SetToolTip( wxU(p_item->psz_longtext) );
894 config_data->control.checkbox = checkbox;
895 panel_sizer->Add( checkbox, 0, wxALL, 5 );
896 if( p_item->b_advanced ) b_has_advanced = VLC_TRUE;
900 delete panel; panel = NULL;
906 /* Don't add items that were not recognized */
907 if( panel == NULL ) continue;
909 panel_sizer->Layout();
910 panel->SetSizerAndFit( panel_sizer );
912 /* Add the config data to our array so we can keep a trace of it */
913 config_array.Add( config_data );
915 config_sizer->Add( panel, 0, wxEXPAND | wxALL, 2 );
917 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
919 /* Display a nice message if no configuration options are available */
920 if( !config_array.GetCount() )
922 config_sizer->Add( new wxStaticText( config_window, -1,
923 wxU(_("No configuration options available")) ), 1,
924 wxALIGN_CENTER_VERTICAL | wxALIGN_CENTER, 2 );
927 config_sizer->Layout();
928 config_window->SetSizer( config_sizer );
929 sizer->Add( config_window, 1, wxEXPAND | wxALL, 5 );
931 /* Intercept all menu events in our custom event handler */
932 config_window->PushEventHandler(
933 new ConfigEvtHandler( p_intf, p_prefs_dialog ) );
936 wxCommandEvent dummy_event;
937 b_advanced = !config_GetInt( p_intf, "advanced" );
938 OnAdvanced( dummy_event );
940 /* Create advanced checkbox if needed */
941 if( config_array.GetCount() && b_has_advanced )
943 wxCheckBox *advanced_checkbox =
944 new wxCheckBox( this, Advanced_Event, wxU(_("Advanced options")) );
946 if( b_advanced ) advanced_checkbox->SetValue(TRUE);
947 sizer->Add( advanced_checkbox, 0, wxALL|wxALIGN_RIGHT, 0 );
954 void PrefsPanel::ApplyChanges()
956 for( size_t i = 0; i < config_array.GetCount(); i++ )
958 ConfigData *config_data = config_array.Item(i);
960 switch( config_data->i_config_type )
962 case CONFIG_ITEM_MODULE:
963 config_PutPsz( p_intf, config_data->option_name.mb_str(), (char *)
964 config_data->control.combobox->GetClientData(
965 config_data->control.combobox->GetSelection() ) );
967 case CONFIG_ITEM_STRING:
968 case CONFIG_ITEM_FILE:
969 case CONFIG_ITEM_DIRECTORY:
970 if( !config_data->b_config_list )
971 config_PutPsz( p_intf, config_data->option_name.mb_str(),
972 config_data->control.textctrl->GetValue().mb_str() );
974 config_PutPsz( p_intf, config_data->option_name.mb_str(),
975 config_data->control.combobox->GetValue().mb_str() );
977 case CONFIG_ITEM_BOOL:
978 config_PutInt( p_intf, config_data->option_name.mb_str(),
979 config_data->control.checkbox->IsChecked() );
981 case CONFIG_ITEM_INTEGER:
982 config_PutInt( p_intf, config_data->option_name.mb_str(),
983 config_data->control.spinctrl->GetValue() );
985 case CONFIG_ITEM_FLOAT:
988 if( (wxSscanf(config_data->control.textctrl->GetValue(),
989 wxT("%f"), &f_value) == 1) )
990 config_PutFloat( p_intf, config_data->option_name.mb_str(),
998 void PrefsPanel::OnAdvanced( wxCommandEvent& WXUNUSED(event) )
1000 b_advanced = !b_advanced;
1002 for( size_t i = 0; i < config_array.GetCount(); i++ )
1004 ConfigData *config_data = config_array.Item(i);
1005 if( config_data->b_advanced )
1007 config_data->panel->Show( b_advanced );
1008 config_sizer->Show( config_data->panel, b_advanced );
1012 config_sizer->Layout();
1013 config_window->FitInside();
1014 config_window->Refresh();
1017 /*****************************************************************************
1018 * A small helper class which intercepts all events
1019 *****************************************************************************/
1020 ConfigEvtHandler::ConfigEvtHandler( intf_thread_t *_p_intf,
1021 PrefsDialog *_p_prefs_dialog )
1023 /* Initializations */
1025 p_prefs_dialog = _p_prefs_dialog;
1028 ConfigEvtHandler::~ConfigEvtHandler()
1032 void ConfigEvtHandler::OnCommandEvent( wxCommandEvent& event )
1034 if( !event.GetEventObject() )
1040 ConfigData *config_data = (ConfigData *)
1041 ((wxEvtHandler *)event.GetEventObject())->GetClientData();
1049 if( config_data->i_config_type == CONFIG_ITEM_FILE )
1051 wxFileDialog dialog( p_prefs_dialog, wxU(_("Open file")),
1052 wxT(""), wxT(""), wxT("*.*"),
1053 #if defined( __WXMSW__ )
1059 if( dialog.ShowModal() == wxID_OK )
1061 config_data->control.textctrl->SetValue( dialog.GetPath() );
1065 switch( config_data->i_config_type )
1067 case CONFIG_ITEM_MODULE:
1069 case CONFIG_ITEM_STRING:
1071 case CONFIG_ITEM_FILE:
1073 case CONFIG_ITEM_INTEGER:
1075 case CONFIG_ITEM_FLOAT:
1077 case CONFIG_ITEM_BOOL: