]> git.sesse.net Git - vlc/blob - modules/gui/wxwidgets/dialogs/preferences_widgets.cpp
Merge branch 'master' of git@git.videolan.org:vlc
[vlc] / modules / gui / wxwidgets / dialogs / preferences_widgets.cpp
1 /*****************************************************************************
2  * preferences_widgets.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *          Sigmund Augdal Helberg <dnumgis@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #include "wxwidgets.hpp"
26 #include "preferences_widgets.h"
27 #include <vlc_keys.h>
28 #include <vlc_config_cat.h>
29
30 #include <wx/statline.h>
31 #include <wx/spinctrl.h>
32
33 /*****************************************************************************
34  * CreateConfigControl wrapper
35  *****************************************************************************/
36 ConfigControl *CreateConfigControl( vlc_object_t *p_this,
37                                     module_config_t *p_item, wxWindow *parent )
38 {
39     ConfigControl *p_control = NULL;
40
41     switch( p_item->i_type )
42     {
43     case CONFIG_ITEM_MODULE:
44         p_control = new ModuleConfigControl( p_this, p_item, parent );
45         break;
46     case CONFIG_ITEM_MODULE_CAT:
47         p_control = new ModuleCatConfigControl( p_this, p_item, parent );
48         break;
49     case CONFIG_ITEM_MODULE_LIST_CAT:
50         p_control = new ModuleListCatConfigControl( p_this, p_item, parent );
51         break;
52
53     case CONFIG_ITEM_STRING:
54         if( !p_item->i_list )
55         {
56             p_control = new StringConfigControl( p_this, p_item, parent );
57         }
58         else
59         {
60             p_control = new StringListConfigControl( p_this, p_item, parent );
61         }
62         break;
63
64     case CONFIG_ITEM_FILE:
65     case CONFIG_ITEM_DIRECTORY:
66         p_control = new FileConfigControl( p_this, p_item, parent );
67         break;
68
69     case CONFIG_ITEM_INTEGER:
70         if( p_item->i_list )
71         {
72             p_control = new IntegerListConfigControl( p_this, p_item, parent );
73         }
74         else if( p_item->min.i != 0 || p_item->max.i != 0 )
75         {
76             p_control = new RangedIntConfigControl( p_this, p_item, parent );
77         }
78         else
79         {
80             p_control = new IntegerConfigControl( p_this, p_item, parent );
81         }
82         break;
83
84     case CONFIG_ITEM_KEY:
85         p_control = new KeyConfigControl( p_this, p_item, parent );
86         break;
87
88     case CONFIG_ITEM_FLOAT:
89         p_control = new FloatConfigControl( p_this, p_item, parent );
90         break;
91
92     case CONFIG_ITEM_BOOL:
93         p_control = new BoolConfigControl( p_this, p_item, parent );
94         break;
95
96     case CONFIG_SECTION:
97         p_control = new SectionConfigControl( p_this, p_item, parent );
98         break;
99
100     default:
101         break;
102     }
103
104     return p_control;
105 }
106
107 /*****************************************************************************
108  * ConfigControl implementation
109  *****************************************************************************/
110 ConfigControl::ConfigControl( vlc_object_t *_p_this,
111                               module_config_t *p_item, wxWindow *parent )
112   : wxPanel( parent ), p_this( _p_this ),
113     pf_update_callback( NULL ), p_update_data( NULL ),
114     name( wxU(p_item->psz_name) ), i_type( p_item->i_type ),
115     b_advanced( p_item->b_advanced )
116
117 {
118     sizer = new wxBoxSizer( wxHORIZONTAL );
119 }
120
121 ConfigControl::~ConfigControl()
122 {
123 }
124
125 wxSizer *ConfigControl::Sizer()
126 {
127     return sizer;
128 }
129
130 wxString ConfigControl::GetName()
131 {
132     return name;
133 }
134
135 int ConfigControl::GetType()
136 {
137     return i_type;
138 }
139
140 bool ConfigControl::IsAdvanced()
141 {
142     return b_advanced;
143 }
144
145 void ConfigControl::SetUpdateCallback( void (*p_callback)( void * ),
146                                              void *p_data )
147 {
148     pf_update_callback = p_callback;
149     p_update_data = p_data;
150 }
151
152 void ConfigControl::OnUpdate( wxCommandEvent& WXUNUSED(event) )
153 {
154     if( pf_update_callback )
155     {
156         pf_update_callback( p_update_data );
157     }
158 }
159
160 void ConfigControl::OnUpdateScroll( wxScrollEvent& WXUNUSED(event) )
161 {
162     wxCommandEvent cevent;
163     OnUpdate(cevent);
164 }
165
166
167 /*****************************************************************************
168  * KeyConfigControl implementation
169  *****************************************************************************/
170 wxString *KeyConfigControl::m_keysList = NULL;
171
172 KeyConfigControl::KeyConfigControl( vlc_object_t *p_this,
173                                     module_config_t *p_item, wxWindow *parent )
174   : ConfigControl( p_this, p_item, parent )
175 {
176     // Number of keys descriptions
177     unsigned int i_keys = sizeof(vlc_keys)/sizeof(key_descriptor_t);
178
179     // Init the keys decriptions array
180     if( m_keysList == NULL )
181     {
182         m_keysList = new wxString[i_keys];
183         for( unsigned int i = 0; i < i_keys; i++ )
184         {
185             m_keysList[i] = wxU(vlc_keys[i].psz_key_string);
186         }
187     }
188
189     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
190     alt = new wxCheckBox( this, -1, wxU(_("Alt")) );
191     alt->SetValue( p_item->value.i & KEY_MODIFIER_ALT );
192     ctrl = new wxCheckBox( this, -1, wxU(_("Ctrl")) );
193     ctrl->SetValue( p_item->value.i & KEY_MODIFIER_CTRL );
194     shift = new wxCheckBox( this, -1, wxU(_("Shift")) );
195     shift->SetValue( p_item->value.i & KEY_MODIFIER_SHIFT );
196     combo = new wxComboBox( this, -1, wxT(""), wxDefaultPosition,
197                             wxDefaultSize, i_keys, m_keysList,
198                             wxCB_READONLY );
199     for( unsigned int i = 0; i < i_keys; i++ )
200     {
201         combo->SetClientData( i, (void*)vlc_keys[i].i_key_code );
202         if( (unsigned int)vlc_keys[i].i_key_code ==
203             ( ((unsigned int)p_item->value.i) & ~KEY_MODIFIER ) )
204         {
205             combo->SetSelection( i );
206             combo->SetValue( wxU(_(vlc_keys[i].psz_key_string)) );
207         }
208     }
209
210     sizer->Add( label, 2, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
211     sizer->Add( alt,   1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
212     sizer->Add( ctrl,  1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
213     sizer->Add( shift, 1, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
214     sizer->Add( combo, 2, wxALIGN_CENTER_VERTICAL | wxALL | wxEXPAND, 5 );
215     sizer->Layout();
216     this->SetSizerAndFit( sizer );
217 }
218
219 KeyConfigControl::~KeyConfigControl()
220 {
221     if( m_keysList )
222     {
223         delete[] m_keysList;
224         m_keysList = NULL;
225     }
226 }
227
228 int KeyConfigControl::GetIntValue()
229 {
230     int result = 0;
231     if( alt->IsChecked() )
232     {
233         result |= KEY_MODIFIER_ALT;
234     }
235     if( ctrl->IsChecked() )
236     {
237         result |= KEY_MODIFIER_CTRL;
238     }
239     if( shift->IsChecked() )
240     {
241         result |= KEY_MODIFIER_SHIFT;
242     }
243     int selected = combo->GetSelection();
244     if( selected != -1 )
245     {
246         result |= (int)combo->GetClientData( selected );
247     }
248     return result;
249 }
250
251 /*****************************************************************************
252  * ModuleConfigControl implementation
253  *****************************************************************************/
254 ModuleConfigControl::ModuleConfigControl( vlc_object_t *p_this,
255                                           module_config_t *p_item,
256                                           wxWindow *parent )
257   : ConfigControl( p_this, p_item, parent )
258 {
259     vlc_list_t *p_list;
260     module_t *p_parser;
261
262     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
263     combo = new wxComboBox( this, -1, wxL2U(p_item->value.psz),
264                             wxDefaultPosition, wxDefaultSize,
265                             0, NULL, wxCB_READONLY | wxCB_SORT );
266
267     /* build a list of available modules */
268     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
269     combo->Append( wxU(_("Default")), (void *)NULL );
270     combo->SetSelection( 0 );
271     for( int i_index = 0; i_index < p_list->i_count; i_index++ )
272     {
273         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
274
275         if( module_IsCapable( p_parser, p_item->psz_type ) )
276         {
277             combo->Append( wxU(module_GetLongName(p_parser)),
278                            (char *)module_GetObjName(p_parser) );
279             if( p_item->value.psz && !strcmp(p_item->value.psz,
280                                              module_GetObjName(p_parser)) )
281                 combo->SetValue( wxU(module_GetLongName(p_parser)) );
282         }
283     }
284     vlc_list_release( p_list );
285
286     combo->SetToolTip( wxU(p_item->psz_longtext) );
287     sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
288     sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
289     sizer->Layout();
290     this->SetSizerAndFit( sizer );
291 }
292
293 ModuleCatConfigControl::~ModuleCatConfigControl()
294 {
295     ;
296 }
297
298 wxString ModuleCatConfigControl::GetPszValue()
299 {
300     return wxU( (char *)combo->GetClientData( combo->GetSelection() ));
301 }
302
303 /*****************************************************************************
304  * ModuleCatConfigControl implementation
305  *****************************************************************************/
306 ModuleCatConfigControl::ModuleCatConfigControl( vlc_object_t *p_this,
307                                                 module_config_t *p_item,
308                                                 wxWindow *parent )
309   : ConfigControl( p_this, p_item, parent )
310 {
311     vlc_list_t *p_list;
312     module_t *p_parser;
313
314     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
315     combo = new wxComboBox( this, -1, wxL2U(p_item->value.psz),
316                             wxDefaultPosition, wxDefaultSize,
317                             0, NULL, wxCB_READONLY | wxCB_SORT );
318
319     combo->Append( wxU(_("Default")), (void *)NULL );
320     combo->SetSelection( 0 );
321
322     /* build a list of available modules */
323     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
324     for(  int i_index = 0; i_index < p_list->i_count; i_index++ )
325     {
326         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
327
328         if( !strcmp( module_GetObjName(p_parser), "main" ) )
329               continue;
330
331         unsigned int i_confsize;
332         module_config_t *p_config, *p_start, *p_end;
333         p_start = module_GetConfig( p_parser, &i_confsize );
334         p_end = p_start + i_confsize;
335
336         for( p_config = p_start; p_config < p_end; p_config++ )
337         {
338             /* Hack: required subcategory is stored in min.i */
339             if( p_config->i_type == CONFIG_SUBCATEGORY &&
340                 p_config->value.i == p_item->min.i )
341             {
342                 combo->Append( wxU(module_GetLongName(p_parser)),
343                                (char *)module_GetObjName(p_parser) );
344                 if( p_item->value.psz &&
345                     !strcmp(p_item->value.psz, module_GetObjName(p_parser)) )
346                     combo->SetValue( wxU(module_GetLongName(p_parser)) );
347             }
348         }
349
350         module_PutConfig( p_start );
351     }
352     vlc_list_release( p_list );
353
354     combo->SetToolTip( wxU(p_item->psz_longtext) );
355     sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
356     sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
357     sizer->Layout();
358     this->SetSizerAndFit( sizer );
359 }
360
361 ModuleConfigControl::~ModuleConfigControl()
362 {
363     ;
364 }
365
366 wxString ModuleConfigControl::GetPszValue()
367 {
368     return wxU( (char *)combo->GetClientData( combo->GetSelection() ));
369 }
370
371
372 /*****************************************************************************
373  * ModuleListCatonfigControl implementation
374  *****************************************************************************/
375 BEGIN_EVENT_TABLE(ModuleListCatConfigControl, wxPanel)
376     EVT_CHECKBOX( wxID_HIGHEST , ModuleListCatConfigControl::OnUpdate )
377 END_EVENT_TABLE()
378
379
380 ModuleListCatConfigControl::ModuleListCatConfigControl( vlc_object_t *p_this,
381                                                      module_config_t *p_item,
382                                                      wxWindow *parent )
383   : ConfigControl( p_this, p_item, parent )
384 {
385     vlc_list_t *p_list;
386     module_t *p_parser;
387
388     delete sizer;
389     sizer = new wxBoxSizer( wxVERTICAL );
390     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
391     sizer->Add( label );
392
393     text = new wxTextCtrl( this, -1, wxU(p_item->value.psz),
394                            wxDefaultPosition,wxSize( 300, 20 ) );
395
396
397     /* build a list of available modules */
398     p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
399     for(  int i_index = 0; i_index < p_list->i_count; i_index++ )
400     {
401         p_parser = (module_t *)p_list->p_values[i_index].p_object ;
402
403         if( !strcmp( module_GetObjName(p_parser), "main" ) )
404               continue;
405
406         unsigned int i_confsize;
407         module_config_t *p_config, *p_start, *p_end;
408
409         p_start = module_GetConfig( p_parser, &i_confsize );
410         p_end = p_start + i_confsize;
411
412         for( p_config = p_start; p_config < p_end; p_config++ )
413         {
414             /* Hack: required subcategory is stored in min.i */
415             if( p_config->i_type == CONFIG_SUBCATEGORY &&
416                 p_config->value.i == p_item->min.i )
417             {
418                 moduleCheckBox *mc = new moduleCheckBox;
419                 mc->checkbox =
420                     new wxCheckBox( this, wxID_HIGHEST,
421                                     wxU(module_GetLongName(p_parser)) );
422
423                 mc->psz_module = strdup( module_GetObjName(p_parser) );
424                 pp_checkboxes.push_back( mc );
425
426                 if( p_item->value.psz &&
427                     strstr( p_item->value.psz, mc->psz_module ) )
428                 {
429                     mc->checkbox->SetValue( true );
430                 }
431                 sizer->Add( mc->checkbox );
432             }
433         }
434
435         module_PutConfig( p_start );
436     }
437     vlc_list_release( p_list );
438
439     text->SetToolTip( wxU(p_item->psz_longtext) );
440     sizer->Add(text, 0, wxEXPAND|wxALL, 5 );
441
442     sizer->Add (new wxStaticText( this, -1, wxU( vlc_wraptext( _("Select "
443         "the desired modules. For more advanced control, the "
444         "resulting \"chain\" can be modified.") , 72 ) ) ) );
445
446     sizer->Layout();
447     this->SetSizerAndFit( sizer );
448 }
449
450 ModuleListCatConfigControl::~ModuleListCatConfigControl()
451 {
452     ;
453 }
454
455 wxString ModuleListCatConfigControl::GetPszValue()
456 {
457     return text->GetValue() ;
458 }
459
460 void  ModuleListCatConfigControl::OnUpdate( wxCommandEvent &event )
461 {
462     bool b_waschecked = false;
463     wxString newtext =  text->GetValue();
464
465     for( unsigned int i = 0 ; i< pp_checkboxes.size() ; i++ )
466     {
467         b_waschecked = newtext.Find( wxT(":")+wxU(pp_checkboxes[i]->psz_module)+wxT(":")) != -1 || newtext.BeforeFirst( ':' ) == wxString(wxU(pp_checkboxes[i]->psz_module)) || newtext.AfterLast( ':' ) == wxString(wxU(pp_checkboxes[i]->psz_module));
468         /* For some reasons, ^^ doesn't compile :( */
469         if( (pp_checkboxes[i]->checkbox->IsChecked() && ! b_waschecked )||
470             (! pp_checkboxes[i]->checkbox->IsChecked() && b_waschecked) )
471         {
472             if( b_waschecked )
473             {
474                 /* Maybe not the clest solution */
475                 if( ! newtext.Replace(wxString(wxT(":"))
476                                       +wxU(pp_checkboxes[i]->psz_module)+wxT(":"),
477                                       wxT(":")))
478                 {
479                     if( newtext.BeforeFirst( ':' ) == wxString(wxU(pp_checkboxes[i]->psz_module)) )
480                     {
481                         newtext = newtext.AfterFirst( ':' );
482                     }
483                     else if( newtext.AfterLast( ':' ) == wxString(wxU(pp_checkboxes[i]->psz_module)) )
484                     {
485                         newtext = newtext.BeforeLast( ':' );
486                     }
487                     else if( newtext == wxString(wxU(pp_checkboxes[i]->psz_module)) )
488                     {
489                         newtext = wxT("");
490                     }
491                     else
492                     {
493                         newtext.Replace(wxU(pp_checkboxes[i]->psz_module),wxU(""));
494                     }
495                 }
496             }
497             else
498             {
499                 if( newtext.Len() == 0 )
500                 {
501                     newtext = wxU(pp_checkboxes[i]->psz_module);
502                 }
503                 else
504                 {
505                     newtext += wxU( ":" );
506                     newtext += wxU(pp_checkboxes[i]->psz_module);
507                 }
508             }
509         }
510     }
511     text->SetValue( newtext );
512 }
513
514 /*****************************************************************************
515  * StringConfigControl implementation
516  *****************************************************************************/
517 StringConfigControl::StringConfigControl( vlc_object_t *p_this,
518                                           module_config_t *p_item,
519                                           wxWindow *parent )
520   : ConfigControl( p_this, p_item, parent )
521 {
522     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
523     sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
524     textctrl = new wxTextCtrl( this, -1,
525                                wxL2U(p_item->value.psz),
526                                wxDefaultPosition,
527                                wxDefaultSize,
528                                wxTE_PROCESS_ENTER);
529     textctrl->SetToolTip( wxU(p_item->psz_longtext) );
530     sizer->Add( textctrl, 1, wxALL, 5 );
531     sizer->Layout();
532     this->SetSizerAndFit( sizer );
533 }
534
535 StringConfigControl::~StringConfigControl()
536 {
537     ;
538 }
539
540 wxString StringConfigControl::GetPszValue()
541 {
542     return textctrl->GetValue();
543 }
544
545 BEGIN_EVENT_TABLE(StringConfigControl, wxPanel)
546     /* Text events */
547     EVT_TEXT(-1, StringConfigControl::OnUpdate)
548 END_EVENT_TABLE()
549
550 /*****************************************************************************
551  * StringListConfigControl implementation
552  *****************************************************************************/
553 StringListConfigControl::StringListConfigControl( vlc_object_t *p_this,
554                                                   module_config_t *p_item,
555                                                   wxWindow *parent )
556   : ConfigControl( p_this, p_item, parent )
557 {
558     psz_default_value = (char *)p_item->value.psz;
559     if( psz_default_value ) psz_default_value = strdup( psz_default_value );
560
561     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
562     sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
563     combo = new wxComboBox( this, -1, wxT(""),
564                             wxDefaultPosition, wxDefaultSize,
565                             0, NULL, wxCB_READONLY );
566
567     // was required to do so - because local p_item is a memcpy of
568     // this one, so it won't see the change done by pf_updat_list
569     module_config_t *p_module_config = config_FindConfig( p_this, p_item->psz_name );
570     if(p_module_config && p_module_config->pf_update_list)
571     {
572        vlc_value_t val;
573        val.psz_string = strdup(p_module_config->value.psz);
574
575        p_module_config->pf_update_list(p_this, p_item->psz_name, val, val, NULL);
576
577        // assume in a×y case that dirty was set to true
578        // because lazy programmes will use the same callback for
579        // this, like the one behind the refresh push button?
580        p_module_config->b_dirty = false;
581
582        free( val.psz_string );
583     }
584
585     UpdateCombo( p_module_config );
586
587     combo->SetToolTip( wxU(p_item->psz_longtext) );
588     sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
589
590     for( int i = 0; i < p_item->i_action; i++ )
591     {
592         wxButton *button =
593             new wxButton( this, wxID_HIGHEST+i,
594                           wxU(_(p_item->ppsz_action_text[i])) );
595         sizer->Add( button, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
596     }
597
598     sizer->Layout();
599     this->SetSizerAndFit( sizer );
600 }
601
602 StringListConfigControl::~StringListConfigControl()
603 {
604     free( psz_default_value );
605 }
606
607 void StringListConfigControl::UpdateCombo( module_config_t *p_item )
608 {
609     bool b_found = false;
610     int i_index;
611
612     /* build a list of available options */
613     for( i_index = 0; i_index < p_item->i_list; i_index++ )
614     {
615         combo->Append( ( p_item->ppsz_list_text &&
616                          p_item->ppsz_list_text[i_index] ) ?
617                        wxU(p_item->ppsz_list_text[i_index]) :
618                        wxL2U(p_item->ppsz_list[i_index]) );
619         combo->SetClientData( i_index, (void *)p_item->ppsz_list[i_index] );
620         if( ( p_item->value.psz &&
621               !strcmp( p_item->value.psz, p_item->ppsz_list[i_index] ) ) ||
622              ( !p_item->value.psz && !*p_item->ppsz_list[i_index] ) )
623         {
624             combo->SetSelection( i_index );
625             combo->SetValue( ( p_item->ppsz_list_text &&
626                                p_item->ppsz_list_text[i_index] ) ?
627                              wxU(p_item->ppsz_list_text[i_index]) :
628                              wxL2U(p_item->ppsz_list[i_index]) );
629             b_found = true;
630         }
631     }
632
633     if( p_item->value.psz && !b_found )
634     {
635         /* Add custom entry to list */
636         combo->Append( wxL2U(p_item->value.psz) );
637         combo->SetClientData( i_index, (void *)psz_default_value );
638         combo->SetSelection( i_index );
639         combo->SetValue( wxL2U(p_item->value.psz) );
640     }
641 }
642
643 BEGIN_EVENT_TABLE(StringListConfigControl, wxPanel)
644     /* Button events */
645     EVT_BUTTON(-1, StringListConfigControl::OnAction)
646
647     /* Text events */
648     EVT_TEXT(-1, StringListConfigControl::OnUpdate)
649 END_EVENT_TABLE()
650
651 void StringListConfigControl::OnAction( wxCommandEvent& event )
652 {
653     int i_action = event.GetId() - wxID_HIGHEST;
654
655     module_config_t *p_item = config_FindConfig( p_this, GetName().mb_str(wxConvUTF8) );
656     if( !p_item ) return;
657
658     if( i_action < 0 || i_action >= p_item->i_action ) return;
659
660     vlc_value_t val;
661     wxString value = GetPszValue();
662     *((const char **)&val.psz_string) = value.mb_str(wxConvUTF8);
663     p_item->ppf_action[i_action]( p_this, GetName().mb_str(wxConvUTF8), val, val, 0 );
664
665     if( p_item->b_dirty )
666     {
667         combo->Clear();
668         UpdateCombo( p_item );
669         p_item->b_dirty = false;
670     }
671 }
672
673 wxString StringListConfigControl::GetPszValue()
674 {
675     int selected = combo->GetSelection();
676     if( selected != -1 )
677     {
678         return wxL2U((char *)combo->GetClientData( selected ));
679     }
680     return wxString();
681 }
682
683 /*****************************************************************************
684  * FileConfigControl implementation
685  *****************************************************************************/
686 FileConfigControl::FileConfigControl( vlc_object_t *p_this,
687                                       module_config_t *p_item,
688                                       wxWindow *parent )
689   : ConfigControl( p_this, p_item, parent )
690 {
691     directory = p_item->i_type == CONFIG_ITEM_DIRECTORY;
692     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
693     sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
694     textctrl = new wxTextCtrl( this, -1,
695                                wxL2U(p_item->value.psz),
696                                wxDefaultPosition,
697                                wxDefaultSize,
698                                wxTE_PROCESS_ENTER);
699     textctrl->SetToolTip( wxU(p_item->psz_longtext) );
700     sizer->Add( textctrl, 1, wxALL, 5 );
701     browse = new wxButton( this, wxID_HIGHEST, wxU(_("Browse...")) );
702     sizer->Add( browse, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
703     sizer->Layout();
704     this->SetSizerAndFit( sizer );
705 }
706
707 BEGIN_EVENT_TABLE(FileConfigControl, wxPanel)
708     /* Button events */
709     EVT_BUTTON(wxID_HIGHEST, FileConfigControl::OnBrowse)
710 END_EVENT_TABLE()
711
712 void FileConfigControl::OnBrowse( wxCommandEvent& event )
713 {
714     if( directory )
715     {
716         wxDirDialog dialog( this, wxU(_("Choose directory")) );
717
718         if( dialog.ShowModal() == wxID_OK )
719         {
720             textctrl->SetValue( dialog.GetPath() );
721         }
722     }
723     else
724     {
725         wxFileDialog dialog( this, wxU(_("Choose file")),
726                              wxT(""), wxT(""), wxT("*.*"),
727 #if defined( __WXMSW__ )
728                              wxOPEN
729 #else
730                              wxOPEN
731 #endif
732                            );
733         if( dialog.ShowModal() == wxID_OK )
734         {
735             textctrl->SetValue( dialog.GetPath() );
736         }
737     }
738 }
739
740 FileConfigControl::~FileConfigControl()
741 {
742     ;
743 }
744
745 wxString FileConfigControl::GetPszValue()
746 {
747     return textctrl->GetValue();
748 }
749
750 /*****************************************************************************
751  * IntegerConfigControl implementation
752  *****************************************************************************/
753 BEGIN_EVENT_TABLE(IntegerConfigControl, wxPanel)
754     EVT_TEXT(-1, IntegerConfigControl::OnUpdate)
755     EVT_COMMAND_SCROLL(-1, IntegerConfigControl::OnUpdateScroll)
756 END_EVENT_TABLE()
757
758 IntegerConfigControl::IntegerConfigControl( vlc_object_t *p_this,
759                                             module_config_t *p_item,
760                                             wxWindow *parent )
761   : ConfigControl( p_this, p_item, parent )
762 {
763     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
764     spin = new wxSpinCtrl( this, -1,
765                            wxString::Format(wxT("%d"),
766                                             p_item->value.i),
767                            wxDefaultPosition, wxDefaultSize,
768                            wxSP_ARROW_KEYS,
769                            -100000000, 100000000, p_item->value.i);
770     spin->SetToolTip( wxU(p_item->psz_longtext) );
771     sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
772     sizer->Add( spin, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
773     sizer->Layout();
774     this->SetSizerAndFit( sizer );
775     i_value = p_item->value.i;
776 }
777
778 IntegerConfigControl::~IntegerConfigControl()
779 {
780     ;
781 }
782
783 int IntegerConfigControl::GetIntValue()
784 {
785     /* We avoid using GetValue because of a recursion bug with wxSpinCtrl with
786      * wxGTK. */
787     return spin->GetValue();
788 }
789
790 void IntegerConfigControl::OnUpdate( wxCommandEvent &event )
791 {
792     ConfigControl::OnUpdate( event );
793 }
794 void IntegerConfigControl::OnUpdateScroll( wxScrollEvent &event )
795 {
796     wxCommandEvent cevent;
797     cevent.SetInt(event.GetPosition());
798     OnUpdate(cevent);
799 }
800
801 /*****************************************************************************
802  * IntegerListConfigControl implementation
803  *****************************************************************************/
804 IntegerListConfigControl::IntegerListConfigControl( vlc_object_t *p_this,
805                                                     module_config_t *p_item,
806                                                     wxWindow *parent )
807   : ConfigControl( p_this, p_item, parent )
808 {
809     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
810     sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
811     combo = new wxComboBox( this, -1, wxT(""),
812                             wxDefaultPosition, wxDefaultSize,
813                             0, NULL, wxCB_READONLY );
814
815     module_config_t *p_module_config = config_FindConfig( p_this, p_item->psz_name );
816     if(p_module_config && p_module_config->pf_update_list)
817     {
818        vlc_value_t val;
819        val.i_int = p_module_config->value.i;
820
821        p_module_config->pf_update_list(p_this, p_item->psz_name, val, val, NULL);
822
823        // assume in any case that dirty was set to true
824        // because lazy programmes will use the same callback for
825        // this, like the one behind the refresh push button?
826        p_module_config->b_dirty = false;
827     }
828
829     UpdateCombo( p_module_config );
830
831     combo->SetToolTip( wxU(p_item->psz_longtext) );
832     sizer->Add( combo, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
833
834     sizer->Layout();
835     this->SetSizerAndFit( sizer );
836 }
837
838 IntegerListConfigControl::~IntegerListConfigControl()
839 {
840 }
841
842 void IntegerListConfigControl::UpdateCombo( module_config_t *p_item )
843 {
844     /* build a list of available options */
845     for( int i_index = 0; i_index < p_item->i_list; i_index++ )
846     {
847         if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
848         {
849             combo->Append( wxU(p_item->ppsz_list_text[i_index]) );
850         }
851         else
852         {
853             combo->Append( wxString::Format(wxT("%i"),
854                                             p_item->pi_list[i_index]) );
855         }
856         combo->SetClientData( i_index, (void *)p_item->pi_list[i_index] );
857         if( p_item->value.i == p_item->pi_list[i_index] )
858         {
859             combo->SetSelection( i_index );
860             if( p_item->ppsz_list_text && p_item->ppsz_list_text[i_index] )
861             {
862                 combo->SetValue( wxU(p_item->ppsz_list_text[i_index]) );
863             }
864             else
865             {
866                 combo->SetValue( wxString::Format(wxT("%i"),
867                                                   p_item->pi_list[i_index]) );
868             }
869         }
870     }
871 }
872
873 BEGIN_EVENT_TABLE(IntegerListConfigControl, wxPanel)
874     /* Button events */
875     EVT_BUTTON(-1, IntegerListConfigControl::OnAction)
876
877     /* Update events */
878     EVT_TEXT(-1, IntegerListConfigControl::OnUpdate)
879 END_EVENT_TABLE()
880
881 void IntegerListConfigControl::OnAction( wxCommandEvent& event )
882 {
883     int i_action = event.GetId() - wxID_HIGHEST;
884
885     module_config_t *p_item;
886     p_item = config_FindConfig( p_this, GetName().mb_str(wxConvUTF8) );
887     if( !p_item ) return;
888
889     if( i_action < 0 || i_action >= p_item->i_action ) return;
890
891     vlc_value_t val;
892     val.i_int = GetIntValue();
893     p_item->ppf_action[i_action]( p_this, GetName().mb_str(wxConvUTF8), val, val, 0 );
894
895     if( p_item->b_dirty )
896     {
897         combo->Clear();
898         UpdateCombo( p_item );
899         p_item->b_dirty = false;
900     }
901 }
902
903 int IntegerListConfigControl::GetIntValue()
904 {
905     int selected = combo->GetSelection();
906     if( selected != -1 )
907     {
908         return (int)combo->GetClientData( selected );
909     }
910     return -1;
911 }
912
913 /*****************************************************************************
914  * RangedIntConfigControl implementation
915  *****************************************************************************/
916 BEGIN_EVENT_TABLE(RangedIntConfigControl, wxPanel)
917     EVT_COMMAND_SCROLL(-1, RangedIntConfigControl::OnUpdateScroll)
918 END_EVENT_TABLE()
919
920 RangedIntConfigControl::RangedIntConfigControl( vlc_object_t *p_this,
921                                                 module_config_t *p_item,
922                                                 wxWindow *parent )
923   : ConfigControl( p_this, p_item, parent )
924 {
925     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
926     slider = new wxSlider( this, -1, p_item->value.i, p_item->min.i,
927                            p_item->max.i, wxDefaultPosition, wxDefaultSize,
928                            wxSL_LABELS | wxSL_HORIZONTAL );
929     slider->SetToolTip( wxU(p_item->psz_longtext) );
930     sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
931     sizer->Add( slider, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
932     sizer->Layout();
933     this->SetSizerAndFit( sizer );
934 }
935
936 RangedIntConfigControl::~RangedIntConfigControl()
937 {
938     ;
939 }
940
941 int RangedIntConfigControl::GetIntValue()
942 {
943     return slider->GetValue();
944 }
945
946
947 /*****************************************************************************
948  * FloatConfigControl implementation
949  *****************************************************************************/
950 BEGIN_EVENT_TABLE(FloatConfigControl, wxPanel)
951     EVT_TEXT(-1, FloatConfigControl::OnUpdate)
952 END_EVENT_TABLE()
953
954 FloatConfigControl::FloatConfigControl( vlc_object_t *p_this,
955                                         module_config_t *p_item,
956                                         wxWindow *parent )
957   : ConfigControl( p_this, p_item, parent )
958 {
959     label = new wxStaticText(this, -1, wxU(p_item->psz_text));
960     textctrl = new wxTextCtrl( this, -1,
961                                wxString::Format(wxT("%f"),
962                                                 p_item->value.f),
963                                wxDefaultPosition, wxDefaultSize,
964                                wxTE_PROCESS_ENTER );
965     textctrl->SetToolTip( wxU(p_item->psz_longtext) );
966     sizer->Add( label, 1, wxALIGN_CENTER_VERTICAL | wxALL, 5 );
967     sizer->Add( textctrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
968     sizer->Layout();
969     this->SetSizerAndFit( sizer );
970 }
971
972 FloatConfigControl::~FloatConfigControl()
973 {
974     ;
975 }
976
977 float FloatConfigControl::GetFloatValue()
978 {
979     float f_value;
980     if( (wxSscanf(textctrl->GetValue(), wxT("%f"), &f_value) == 1) )
981         return f_value;
982     else return 0.0;
983 }
984
985 /*****************************************************************************
986  * BoolConfigControl implementation
987  *****************************************************************************/
988 BEGIN_EVENT_TABLE(BoolConfigControl, wxPanel)
989     EVT_CHECKBOX(-1, BoolConfigControl::OnUpdate)
990 END_EVENT_TABLE()
991
992 BoolConfigControl::BoolConfigControl( vlc_object_t *p_this,
993                                       module_config_t *p_item,
994                                       wxWindow *parent )
995   : ConfigControl( p_this, p_item, parent )
996 {
997     checkbox = new wxCheckBox( this, -1, wxU(p_item->psz_text) );
998     if( p_item->value.i ) checkbox->SetValue(TRUE);
999     checkbox->SetToolTip( wxU(p_item->psz_longtext) );
1000     sizer->Add( checkbox, 0, wxALL, 5 );
1001     sizer->Layout();
1002     this->SetSizerAndFit( sizer );
1003 }
1004
1005 BoolConfigControl::~BoolConfigControl()
1006 {
1007     ;
1008 }
1009
1010 int BoolConfigControl::GetIntValue()
1011 {
1012     if( checkbox->IsChecked() ) return 1;
1013     else return 0;
1014 }
1015
1016 /*****************************************************************************
1017  * SectionConfigControl implementation
1018  *****************************************************************************/
1019 SectionConfigControl::SectionConfigControl( vlc_object_t *p_this,
1020                                             module_config_t *p_item,
1021                                             wxWindow *parent )
1022   : ConfigControl( p_this, p_item, parent )
1023 {
1024     delete sizer;
1025     sizer = new wxBoxSizer( wxVERTICAL );
1026     sizer->Add( new wxStaticText( this, -1, wxU( p_item->psz_text ) ) );
1027     sizer->Add( new wxStaticLine( this, -1 ), 0, wxEXPAND, 5 );
1028     sizer->Layout();
1029     this->SetSizerAndFit( sizer );
1030 }
1031
1032 SectionConfigControl::~SectionConfigControl()
1033 {
1034     ;
1035 }