1 /*****************************************************************************
2 * preferences.cpp : wxWindows plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2000-2001 VideoLAN
5 * $Id: preferences.cpp,v 1.2 2003/03/29 01:50:12 gbazin 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 #include "wxwindows.h"
59 # define wxRB_SINGLE 0
62 /*****************************************************************************
63 * Classes declarations.
64 *****************************************************************************/
65 class PrefsTreeCtrl : public wxTreeCtrl
70 PrefsTreeCtrl( wxWindow *parent, intf_thread_t *_p_intf,
71 PrefsDialog *p_prefs_dialog, wxBoxSizer *_p_sizer );
72 virtual ~PrefsTreeCtrl();
75 /* Event handlers (these functions should _not_ be virtual) */
76 void OnSelectTreeItem( wxTreeEvent& event );
80 intf_thread_t *p_intf;
81 PrefsDialog *p_prefs_dialog;
86 WX_DEFINE_ARRAY(wxEvtHandler *, ArrayOfControls);
88 class PrefsPanel : public wxScrolledWindow
93 PrefsPanel( wxWindow *parent, intf_thread_t *_p_intf,
94 module_t *p_module, char * );
95 virtual ~PrefsPanel() {}
98 void OnFileBrowse( wxCommandEvent& WXUNUSED(event) );
99 void OnDirectoryBrowse( wxCommandEvent& WXUNUSED(event) );
100 DECLARE_EVENT_TABLE()
102 intf_thread_t *p_intf;
103 ArrayOfControls controls_array;
106 class ConfigTreeData : public wxTreeItemData
110 ConfigTreeData() { panel == NULL; }
111 virtual ~ConfigTreeData() { if( panel ) delete panel; }
117 class ConfigData : public wxClientData
120 ConfigData() { b_advanced = VLC_FALSE; }
121 ConfigData( vlc_bool_t _b_advanced ) { b_advanced = _b_advanced; }
122 virtual ~ConfigData() { }
124 vlc_bool_t IsAdvanced() { return b_advanced; }
127 vlc_bool_t b_advanced;
130 /*****************************************************************************
132 *****************************************************************************/
134 /* IDs for the controls and the menu commands */
137 Notebook_Event = wxID_HIGHEST,
142 BEGIN_EVENT_TABLE(PrefsDialog, wxDialog)
144 EVT_BUTTON(wxID_OK, PrefsDialog::OnOk)
145 EVT_BUTTON(wxID_CANCEL, PrefsDialog::OnCancel)
149 // menu and control ids
152 PrefsTree_Ctrl = wxID_HIGHEST
155 BEGIN_EVENT_TABLE(PrefsTreeCtrl, wxTreeCtrl)
156 EVT_TREE_SEL_CHANGED(PrefsTree_Ctrl, PrefsTreeCtrl::OnSelectTreeItem)
161 FileBrowse_Event = wxID_HIGHEST,
162 DirectoryBrowse_Event,
166 BEGIN_EVENT_TABLE(PrefsPanel, wxScrolledWindow)
168 EVT_BUTTON(FileBrowse_Event, PrefsPanel::OnFileBrowse)
169 EVT_BUTTON(DirectoryBrowse_Event, PrefsPanel::OnDirectoryBrowse)
173 /*****************************************************************************
175 *****************************************************************************/
176 PrefsDialog::PrefsDialog( intf_thread_t *_p_intf, Interface *_p_main_interface)
177 : wxDialog( _p_main_interface, -1, _("Preferences"), wxDefaultPosition,
178 wxSize(600,400), wxDEFAULT_FRAME_STYLE )
180 /* Initializations */
182 p_main_interface = _p_main_interface;
184 /* Create a panel to put everything in */
185 wxPanel *panel = new wxPanel( this, -1 );
186 panel->SetAutoLayout( TRUE );
188 /* Create the preferences tree control */
189 wxBoxSizer *controls_sizer = new wxBoxSizer( wxHORIZONTAL );
190 PrefsTreeCtrl *prefs_tree =
191 new PrefsTreeCtrl( panel, p_intf, this, controls_sizer );
194 wxStaticLine *static_line = new wxStaticLine( panel, wxID_OK );
196 /* Create the buttons */
197 wxButton *ok_button = new wxButton( panel, wxID_OK, _("OK") );
198 ok_button->SetDefault();
199 wxButton *cancel_button = new wxButton( panel, wxID_CANCEL, _("Cancel") );
201 /* Place everything in sizers */
202 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
203 button_sizer->Add( ok_button, 0, wxALL, 5 );
204 button_sizer->Add( cancel_button, 0, wxALL, 5 );
205 button_sizer->Layout();
207 wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
208 wxBoxSizer *panel_sizer = new wxBoxSizer( wxVERTICAL );
209 panel_sizer->Add( controls_sizer, 1, wxEXPAND | wxALL, 5 );
210 panel_sizer->Add( static_line, 0, wxEXPAND | wxALL, 5 );
211 panel_sizer->Add( button_sizer, 0, wxALIGN_LEFT | wxALIGN_BOTTOM |
213 panel_sizer->Layout();
214 panel->SetSizer( panel_sizer );
215 main_sizer->Add( panel, 1, wxEXPAND, 0 );
216 main_sizer->Layout();
217 SetSizer( main_sizer );
220 PrefsDialog::~PrefsDialog()
224 /*****************************************************************************
226 *****************************************************************************/
229 /*****************************************************************************
231 *****************************************************************************/
232 void PrefsDialog::OnOk( wxCommandEvent& WXUNUSED(event) )
237 void PrefsDialog::OnCancel( wxCommandEvent& WXUNUSED(event) )
242 void PrefsTreeCtrl::OnSelectTreeItem( wxTreeEvent& event )
244 ConfigTreeData *config_data;
246 config_data = (ConfigTreeData *)GetItemData( event.GetOldItem() );
247 if( config_data && config_data->panel )
249 config_data->panel->Hide();
250 p_sizer->Remove( config_data->panel );
253 config_data = (ConfigTreeData *)GetItemData( event.GetItem() );
254 if( config_data && config_data->panel )
256 config_data->panel->Show();
257 config_data->panel->FitInside();
258 p_sizer->Add( config_data->panel, 2, wxEXPAND | wxALL, 0 );
263 void PrefsPanel::OnFileBrowse( wxCommandEvent& WXUNUSED(event) )
265 wxFileDialog dialog( this, _("Open file"), "", "", "*.*",
268 if( dialog.ShowModal() == wxID_OK )
271 file_combo->SetValue( dialog.GetPath() );
276 void PrefsPanel::OnDirectoryBrowse( wxCommandEvent& WXUNUSED(event) )
278 wxFileDialog dialog( this, _("Open file"), "", "", "*.*",
281 if( dialog.ShowModal() == wxID_OK )
284 file_combo->SetValue( dialog.GetPath() );
289 /*****************************************************************************
290 * PrefsTreeCtrl class definition.
291 *****************************************************************************/
292 PrefsTreeCtrl::PrefsTreeCtrl( wxWindow *_p_parent, intf_thread_t *_p_intf,
293 PrefsDialog *_p_prefs_dialog,
294 wxBoxSizer *_p_sizer )
295 : wxTreeCtrl( _p_parent, PrefsTree_Ctrl, wxDefaultPosition, wxDefaultSize,
296 wxTR_NO_LINES | wxTR_FULL_ROW_HIGHLIGHT |
297 wxTR_LINES_AT_ROOT | wxTR_HIDE_ROOT |
298 wxTR_HAS_BUTTONS | wxTR_TWIST_BUTTONS | wxSUNKEN_BORDER )
302 module_config_t *p_item;
305 /* Initializations */
307 p_prefs_dialog = _p_prefs_dialog;
309 p_parent = _p_parent;
311 wxTreeItemId root_item = AddRoot( "" );
313 /* List the plugins */
314 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
315 if( !p_list ) return;
318 * Build a tree of the main options
320 for( i_index = 0; i_index < p_list->i_count; i_index++ )
322 p_module = (module_t *)p_list->p_values[i_index].p_object;
323 if( !strcmp( p_module->psz_object_name, "main" ) )
326 if( i_index < p_list->i_count )
328 /* We found the main module */
330 /* Enumerate config options and add corresponding config boxes */
331 p_item = p_module->p_config;
335 if( p_item->b_advanced && !config_GetInt( p_intf, "advanced" ))
339 switch( p_item->i_type )
341 case CONFIG_HINT_CATEGORY:
342 ConfigTreeData *config_data = new ConfigTreeData;
344 new PrefsPanel( p_parent, p_intf,
345 p_module, p_item->psz_text );
346 config_data->panel->Hide();
348 /* Add the category to the tree */
349 AppendItem( root_item, p_item->psz_text, -1, -1, config_data );
353 while( p_item->i_type != CONFIG_HINT_END && p_item++ );
355 SortChildren( root_item );
359 * Build a tree of all the plugins
362 wxTreeItemId plugins_item = AppendItem( root_item, _("Plugins") );
364 for( i_index = 0; i_index < p_list->i_count; i_index++ )
366 p_module = (module_t *)p_list->p_values[i_index].p_object;
368 /* Find the capabiltiy child item */
369 long cookie; size_t i_child_index;
370 wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
371 for( i_child_index = 0;
372 i_child_index < GetChildrenCount( plugins_item, FALSE );
375 if( !GetItemText(capability_item).Cmp(p_module->psz_capability) )
379 capability_item = GetNextChild( plugins_item, cookie );
382 if( i_child_index == GetChildrenCount( plugins_item, FALSE ) )
384 /* We didn't find it, add it */
385 capability_item = AppendItem( plugins_item,
386 p_module->psz_capability );
389 /* Add the plugin to the tree */
390 ConfigTreeData *config_data = new ConfigTreeData;
392 new PrefsPanel( p_parent, p_intf, p_module, NULL );
393 config_data->panel->Hide();
394 AppendItem( capability_item, p_module->psz_object_name, -1, -1,
398 /* Sort all this mess */
399 long cookie; size_t i_child_index;
400 SortChildren( plugins_item );
401 wxTreeItemId capability_item = GetFirstChild( plugins_item, cookie);
402 for( i_child_index = 0;
403 i_child_index < GetChildrenCount( plugins_item, FALSE );
406 capability_item = GetNextChild( plugins_item, cookie );
407 SortChildren( capability_item );
410 /* Clean-up everything */
411 vlc_list_release( p_list );
413 p_sizer->Add( this, 1, wxEXPAND | wxALL, 0 );
418 PrefsTreeCtrl::~PrefsTreeCtrl()
422 /*****************************************************************************
423 * PrefsPanel class definition.
424 *****************************************************************************/
425 PrefsPanel::PrefsPanel( wxWindow* parent, intf_thread_t *_p_intf,
426 module_t *p_module, char *psz_section )
427 : wxScrolledWindow( parent, -1, wxDefaultPosition, wxDefaultSize )
429 module_config_t *p_item;
435 wxRadioButton *radio;
437 wxCheckBox *checkbox;
438 wxTextCtrl *textctrl;
440 wxStaticLine *static_line;
441 wxBoxSizer *horizontal_sizer;
442 wxSortedArrayString sorted_array;
445 /* Initializations */
447 SetAutoLayout( TRUE );
448 SetScrollRate( 5, 5 );
450 wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
452 /* Enumerate config options and add corresponding config boxes */
453 p_item = p_module->p_config;
455 /* Find the category if it has been specified */
456 if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY )
458 while( !p_item->i_type == CONFIG_HINT_CATEGORY ||
459 strcmp( psz_section, p_item->psz_text ) )
461 if( p_item->i_type == CONFIG_HINT_END )
467 /* Add a head title to the panel */
468 wxStaticBox *static_box = new wxStaticBox( this, -1, "" );
469 wxStaticBoxSizer *box_sizer = new wxStaticBoxSizer( static_box,
471 label = new wxStaticText( this, -1,
472 psz_section ? p_item->psz_text :
473 p_module->psz_longname );
475 box_sizer->Add( label, 1, wxALL, 5 );
476 sizer->Add( box_sizer, 0, wxEXPAND | wxALL, 5 );
480 if( p_item->b_advanced && !config_GetInt( p_intf, "advanced" ) )
485 /* If a category has been specified, check we finished the job */
486 if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY &&
487 strcmp( psz_section, p_item->psz_text ) )
490 switch( p_item->i_type )
492 case CONFIG_HINT_CATEGORY:
494 label = new wxStaticText(this, -1, p_item->psz_text);
495 sizer->Add( label, 0, wxALL, 5 );
499 case CONFIG_ITEM_MODULE:
500 label = new wxStaticText(this, -1, p_item->psz_text);
501 combo = new wxComboBox( this, -1, p_item->psz_value,
502 wxDefaultPosition, wxSize(200,-1),
505 /* build a list of available modules */
506 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
507 for( int i_index = 0; i_index < p_list->i_count; i_index++ )
509 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
511 if( !strcmp( p_parser->psz_capability,
514 combo->Append( p_parser->psz_longname );
518 combo->SetToolTip( p_item->psz_longtext );
519 horizontal_sizer = new wxBoxSizer( wxHORIZONTAL );
520 horizontal_sizer->Add( label, 0, wxALL, 5 );
521 horizontal_sizer->Add( combo, 0, wxALL, 5 );
522 sizer->Add( horizontal_sizer, 0, wxALL, 5 );
525 case CONFIG_ITEM_STRING:
526 case CONFIG_ITEM_FILE:
527 label = new wxStaticText(this, -1, p_item->psz_text);
528 textctrl = new wxTextCtrl( this, -1, p_item->psz_value,
529 wxDefaultPosition, wxDefaultSize,
531 textctrl->SetToolTip( p_item->psz_longtext );
532 horizontal_sizer = new wxBoxSizer( wxHORIZONTAL );
533 horizontal_sizer->Add( label, 0, wxALL, 5 );
534 horizontal_sizer->Add( textctrl, 0, wxALL, 5 );
535 if( p_item->i_type == CONFIG_ITEM_FILE )
537 button = new wxButton( this, -1, _("Browse...") );
538 horizontal_sizer->Add( button, 0, wxALL, 5 );
540 sizer->Add( horizontal_sizer, 0, wxALL, 5 );
543 case CONFIG_ITEM_INTEGER:
544 label = new wxStaticText(this, -1, p_item->psz_text);
545 spin = new wxSpinCtrl( this, -1,
546 wxString::Format(_("%d"), p_item->i_value),
547 wxDefaultPosition, wxDefaultSize,
549 0, 16000, p_item->i_value);
550 spin->SetToolTip( p_item->psz_longtext );
551 horizontal_sizer = new wxBoxSizer( wxHORIZONTAL );
552 horizontal_sizer->Add( label, 0, wxALL, 5 );
553 horizontal_sizer->Add( spin, 0, wxALL, 5 );
554 sizer->Add( horizontal_sizer, 0, wxALL, 5 );
557 case CONFIG_ITEM_FLOAT:
558 label = new wxStaticText(this, -1, p_item->psz_text);
559 spin = new wxSpinCtrl( this, -1,
560 wxString::Format(_("%d"), p_item->i_value),
561 wxDefaultPosition, wxDefaultSize,
563 0, 16000, p_item->i_value);
564 spin->SetToolTip( p_item->psz_longtext );
565 horizontal_sizer = new wxBoxSizer( wxHORIZONTAL );
566 horizontal_sizer->Add( label, 0, wxALL, 5 );
567 horizontal_sizer->Add( spin, 0, wxALL, 5 );
568 sizer->Add( horizontal_sizer, 0, wxALL, 5 );
571 case CONFIG_ITEM_BOOL:
572 checkbox = new wxCheckBox( this, -1, p_item->psz_text );
573 if( p_item->i_value ) checkbox->SetValue(TRUE);
574 checkbox->SetToolTip( p_item->psz_longtext );
575 horizontal_sizer = new wxBoxSizer( wxHORIZONTAL );
576 horizontal_sizer->Add( checkbox, 0, wxALL, 5 );
577 sizer->Add( horizontal_sizer, 0, wxALL, 5 );
581 while( p_item->i_type != CONFIG_HINT_END && p_item++ );