]> git.sesse.net Git - vlc/blob - modules/gui/win32/preferences.cpp
85a7f79a6a7d0291b4e84b1e2b9ed1ff08924b33
[vlc] / modules / gui / win32 / preferences.cpp
1 /*****************************************************************************\r
2  * preferences.cpp: the "Preferences" dialog box\r
3  *****************************************************************************\r
4  * Copyright (C) 2002 VideoLAN\r
5  *\r
6  * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License\r
19  * along with this program; if not, write to the Free Software\r
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
21  *****************************************************************************/\r
22 \r
23 #include <vcl.h>\r
24 #pragma hdrstop\r
25 \r
26 #include <stdlib.h>                                      /* malloc(), free() */\r
27 #include <string.h>                                                /* strcmp */\r
28 \r
29 #include <vlc/vlc.h>\r
30 #include <vlc/intf.h>\r
31 \r
32 #include "preferences.h"\r
33 #include "win32_common.h"\r
34 \r
35 //---------------------------------------------------------------------------\r
36 //#pragma package(smart_init)\r
37 #pragma link "CSPIN"\r
38 #pragma resource "*.dfm"\r
39 \r
40 extern intf_thread_t *p_intfGlobal;\r
41 \r
42 \r
43 /****************************************************************************\r
44  * Functions to help components creation\r
45  ****************************************************************************/\r
46 __fastcall TGroupBoxPref::TGroupBoxPref( TComponent* Owner,\r
47             module_config_t *p_config_arg ) : TGroupBox( Owner )\r
48 {\r
49     p_config = p_config_arg;\r
50     Caption = p_config->psz_text;\r
51 }\r
52 //---------------------------------------------------------------------------\r
53 TListView * __fastcall TGroupBoxPref::CreateListView( TWinControl *Parent,\r
54             int Left, int Width, int Top, int Height, TViewStyle ViewStyle )\r
55 {\r
56     TListView *ListView = new TListView( Parent );\r
57     ListView->Parent = Parent;\r
58     ListView->ViewStyle = ViewStyle;\r
59     ListView->Left = Left;\r
60     ListView->Width = Width;\r
61     ListView->Top = Top;\r
62     ListView->Height = Height;\r
63     return ListView;\r
64 }\r
65 //---------------------------------------------------------------------------\r
66 TButton * __fastcall TGroupBoxPref::CreateButton( TWinControl *Parent,\r
67             int Left, int Width, int Top, int Height, AnsiString Caption )\r
68 {\r
69     TButton *Button = new TButton( Parent );\r
70     Button->Parent = Parent;\r
71     Button->Left = Left;\r
72     Button->Width = Width;\r
73     Button->Top = Top;\r
74     Button->Height = Height;\r
75     Button->Caption = Caption;\r
76     return Button;\r
77 }\r
78 //---------------------------------------------------------------------------\r
79 TCheckBox * __fastcall TGroupBoxPref::CreateCheckBox( TWinControl *Parent,\r
80             int Left, int Width, int Top, int Height, AnsiString Caption )\r
81 {\r
82     TCheckBox *CheckBox = new TCheckBox( Parent );\r
83     CheckBox->Parent = Parent;\r
84     CheckBox->Left = Left;\r
85     CheckBox->Width = Width;\r
86     CheckBox->Top = Top;\r
87     CheckBox->Height = Height;\r
88     CheckBox->Caption = Caption;\r
89     return CheckBox;\r
90 }\r
91 //---------------------------------------------------------------------------\r
92 TLabel * __fastcall TGroupBoxPref::CreateLabel( TWinControl *Parent,\r
93             int Left, int Width, int Top, int Height, AnsiString Caption,\r
94             bool WordWrap )\r
95 {\r
96     TLabel *Label = new TLabel( Parent );\r
97     Label->Parent = Parent;\r
98     Label->Caption = Caption;\r
99     Label->Left = Left;\r
100     Label->Width = Width;\r
101     Label->Top = Top;\r
102     Label->Height = Height;\r
103     Label->WordWrap = WordWrap;\r
104     return Label;\r
105 }\r
106 //---------------------------------------------------------------------------\r
107 TEdit * __fastcall TGroupBoxPref::CreateEdit( TWinControl *Parent,\r
108             int Left, int Width, int Top, int Height, AnsiString Text )\r
109 {\r
110     TEdit *Edit = new TEdit( Parent );\r
111     Edit->Parent = Parent;\r
112     Edit->Left = Left;\r
113     Edit->Width = Width;\r
114     Edit->Top = Top;\r
115     Edit->Height = Height;\r
116     Edit->Text = Text;\r
117     return Edit;\r
118 }\r
119 //---------------------------------------------------------------------------\r
120 TCSpinEdit * __fastcall TGroupBoxPref::CreateSpinEdit( TWinControl *Parent,\r
121             int Left, int Width, int Top, int Height,\r
122             long Min, long Max, long Value )\r
123 {\r
124     TCSpinEdit *SpinEdit = new TCSpinEdit( Parent );\r
125     SpinEdit->Parent = Parent;\r
126     SpinEdit->Left = Left;\r
127     SpinEdit->Width = Width;\r
128     SpinEdit->Top = Top;\r
129     SpinEdit->Height = Height;\r
130     SpinEdit->MinValue = Min;\r
131     SpinEdit->MaxValue = Max;\r
132     SpinEdit->Value = Value;\r
133     return SpinEdit;\r
134 }\r
135 //---------------------------------------------------------------------------\r
136 void __fastcall TGroupBoxPref::UpdateChanges()\r
137 {\r
138 }\r
139 \r
140 \r
141 /****************************************************************************\r
142  * GroupBox for module management\r
143  ****************************************************************************/\r
144 __fastcall TGroupBoxPlugin::TGroupBoxPlugin( TComponent* Owner,\r
145             module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
146 {\r
147     /* init listview */\r
148     ListView = CreateListView( this, 16, 164, 24, 160, vsReport );\r
149     ListView->ReadOnly = true;\r
150     ListView->Columns->Add();\r
151     ListView->Columns->Items[0]->Width = 160;\r
152     ListView->Columns->Items[0]->Caption = "Name";//p_config->psz_text;\r
153     ListView->OnSelectItem = ListViewSelectItem;\r
154 \r
155     /* init description label */\r
156     LabelDesc = CreateLabel( this, 230, 225, 50, 52,\r
157                              p_config->psz_longtext, true );\r
158 \r
159     /* init hint label */\r
160     LabelHint = CreateLabel( this, 230, 225, 135, 13, "", false );\r
161 \r
162     /* init configure button */\r
163     ButtonConfig = CreateButton( this, 16, 70, 192, 25, "Configure" );\r
164     ButtonConfig->Enabled = false;\r
165     ButtonConfig->OnClick = ButtonConfigClick;\r
166 \r
167     /* init select button */\r
168     ButtonSelect = CreateButton( this, 110, 70, 192, 25, "Select" );\r
169     ButtonSelect->OnClick = ButtonSelectClick;\r
170 \r
171     /* init 'Selected' label */\r
172     LabelSelected = CreateLabel( this, 230, 45, 198, 13, "Selected", false );\r
173 \r
174     /* init 'Selected' edit */\r
175     Edit = CreateEdit( this, 280, 164, 194, 21, "" );\r
176     vlc_mutex_lock( p_config->p_lock );\r
177     Edit->Text = p_config->psz_value ? p_config->psz_value : "";\r
178     vlc_mutex_unlock( p_config->p_lock );\r
179 \r
180     Height = 233;\r
181 };\r
182 //---------------------------------------------------------------------------\r
183 void __fastcall TGroupBoxPlugin::ListViewSelectItem( TObject *Sender,\r
184         TListItem *Item, bool Selected )\r
185 {\r
186     module_t **pp_parser;\r
187     vlc_list_t *p_list;\r
188     AnsiString Name;\r
189 \r
190     Name = Item->Caption;\r
191     if( Name == "" )\r
192     {\r
193         return;\r
194     }\r
195 \r
196     /* look for module 'Name' */\r
197     for( pp_parser = (module_t **)p_list->pp_objects ;\r
198          *pp_parser ;\r
199          pp_parser++ )\r
200     {\r
201         if( strcmp( (*pp_parser)->psz_object_name, Name.c_str() ) == 0 )\r
202         {\r
203             ModuleSelected = (*pp_parser);\r
204             LabelHint->Caption = (*pp_parser)->psz_longname ?\r
205                                  (*pp_parser)->psz_longname : "";\r
206             ButtonConfig->Enabled = (*pp_parser)->i_config_items ? true : false;\r
207 \r
208             break;\r
209         }\r
210     }\r
211 }\r
212 //---------------------------------------------------------------------------\r
213 void __fastcall TGroupBoxPlugin::ButtonSelectClick( TObject *Sender )\r
214 {\r
215     if( !ModuleSelected ) return;\r
216     Edit->Text = ModuleSelected->psz_object_name;\r
217 }\r
218 //---------------------------------------------------------------------------\r
219 void __fastcall TGroupBoxPlugin::ButtonConfigClick( TObject *Sender )\r
220 {\r
221     p_intfGlobal->p_sys->p_window->\r
222                         CreatePreferences( ModuleSelected->psz_object_name );\r
223 }\r
224 //---------------------------------------------------------------------------\r
225 void __fastcall TGroupBoxPlugin::UpdateChanges()\r
226 {\r
227     /* XXX: Necessary, since c_str() returns only a temporary pointer... */\r
228     free( p_config->psz_value );\r
229     p_config->psz_value = (char *)malloc( Edit->Text.Length() + 1 );\r
230     strcpy( p_config->psz_value, Edit->Text.c_str() );\r
231 }\r
232 \r
233 \r
234 /****************************************************************************\r
235  * GroupBox for string management\r
236  ****************************************************************************/\r
237 __fastcall TGroupBoxString::TGroupBoxString( TComponent* Owner,\r
238             module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
239 {\r
240     /* init description label */\r
241     LabelDesc = CreateLabel( this, 230, 225, 24, 26,\r
242                              p_config->psz_longtext, true );\r
243 \r
244     /* init edit */\r
245     Edit = CreateEdit( this, 16, 164, 24, 21, "" );\r
246     vlc_mutex_lock( p_config->p_lock );\r
247     Edit->Text = p_config->psz_value ? p_config->psz_value : "";\r
248     vlc_mutex_unlock( p_config->p_lock );\r
249 \r
250     /* vertical alignment */\r
251     Height = LabelDesc->Height + 24;\r
252     LabelDesc->Top = Top + ( Height - LabelDesc->Height ) / 2 + 4;\r
253     Edit->Top = Top + ( Height - Edit->Height ) / 2 + 4;\r
254 };\r
255 //---------------------------------------------------------------------------\r
256 void __fastcall TGroupBoxString::UpdateChanges()\r
257 {\r
258     /* XXX: Necessary, since c_str() returns only a temporary pointer... */\r
259     free( p_config->psz_value );\r
260     p_config->psz_value = (char *)malloc( Edit->Text.Length() + 1 );\r
261     strcpy( p_config->psz_value, Edit->Text.c_str() );\r
262 }\r
263 \r
264 \r
265 /****************************************************************************\r
266  * GroupBox for integer management\r
267  ****************************************************************************/\r
268 __fastcall TGroupBoxInteger::TGroupBoxInteger( TComponent* Owner,\r
269             module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
270 {\r
271     /* init description label */\r
272     LabelDesc = CreateLabel( this, 230, 225, 19, 26,\r
273                              p_config->psz_longtext, true );\r
274 \r
275     /* init spinedit */\r
276     SpinEdit = CreateSpinEdit( this, 16, 164, 24, 21,\r
277                                -1, 100000, p_config->i_value );\r
278 \r
279     /* vertical alignment */\r
280     Height = LabelDesc->Height + 24;\r
281     LabelDesc->Top = Top + ( Height - LabelDesc->Height ) / 2 + 4;\r
282     SpinEdit->Top = Top + ( Height - SpinEdit->Height ) / 2 + 4;\r
283 };\r
284 //---------------------------------------------------------------------------\r
285 void __fastcall TGroupBoxInteger::UpdateChanges()\r
286 {\r
287     /* Warning: we're casting from long to int */\r
288     p_config->i_value = (int)SpinEdit->Value;\r
289 }\r
290 \r
291 \r
292 /****************************************************************************\r
293  * GroupBox for boolean management\r
294  ****************************************************************************/\r
295 __fastcall TGroupBoxBool::TGroupBoxBool( TComponent* Owner,\r
296             module_config_t *p_config ) : TGroupBoxPref( Owner, p_config )\r
297 {\r
298     /* init description label */\r
299     LabelDesc = CreateLabel( this, 230, 225, 19, 26,\r
300                              p_config->psz_longtext, true );\r
301 \r
302     /* init checkbox */\r
303     CheckBox = CreateCheckBox( this, 16, 184, 28, 17, p_config->psz_text );\r
304     CheckBox->Checked = p_config->i_value;\r
305 \r
306     /* vertical alignment */\r
307     Height = LabelDesc->Height + 24;\r
308     LabelDesc->Top = Top + ( Height - LabelDesc->Height ) / 2 + 4;\r
309     CheckBox->Top = Top + ( Height - CheckBox->Height ) / 2 + 4;\r
310 };\r
311 //---------------------------------------------------------------------------\r
312 void __fastcall TGroupBoxBool::UpdateChanges()\r
313 {\r
314     p_config->i_value = CheckBox->Checked ? 1 : 0;\r
315 }\r
316 \r
317 \r
318 /****************************************************************************\r
319  * Callbacks for the dialog\r
320  ****************************************************************************/\r
321 //---------------------------------------------------------------------------\r
322 __fastcall TPreferencesDlg::TPreferencesDlg( TComponent* Owner )\r
323         : TForm( Owner )\r
324 {\r
325     Icon = p_intfGlobal->p_sys->p_window->Icon;\r
326 }\r
327 //---------------------------------------------------------------------------\r
328 void __fastcall TPreferencesDlg::FormClose( TObject *Sender,\r
329       TCloseAction &Action )\r
330 {\r
331     Action = caHide;\r
332 }\r
333 //---------------------------------------------------------------------------\r
334 void __fastcall TPreferencesDlg::FormShow( TObject *Sender )\r
335 {\r
336 /*\r
337     p_intfGlobal->p_sys->p_window->MenuPreferences->Checked = true;\r
338     p_intfGlobal->p_sys->p_window->PopupPreferences->Checked = true;\r
339 */\r
340 }\r
341 //---------------------------------------------------------------------------\r
342 void __fastcall TPreferencesDlg::FormHide( TObject *Sender )\r
343 {\r
344 /*\r
345     p_intfGlobal->p_sys->p_window->MenuPreferences->Checked = false;\r
346     p_intfGlobal->p_sys->p_window->PopupPreferences->Checked = false;\r
347 */\r
348 }\r
349 \r
350 \r
351 /****************************************************************************\r
352  * CreateConfigDialog: dynamically creates the configuration dialog\r
353  * box from all the configuration data provided by the selected module.\r
354  ****************************************************************************/\r
355 #define ADD_PANEL                               \\r
356 {                                               \\r
357             Panel = new TPanel( this );         \\r
358             Panel->Parent = ScrollBox;          \\r
359             Panel->Caption = "";                \\r
360             Panel->BevelOuter = bvNone;         \\r
361             Panel->Height = 12;                 \\r
362 }\r
363 \r
364 void __fastcall TPreferencesDlg::CreateConfigDialog( char *psz_module_name )\r
365 {\r
366     module_t          **pp_parser;\r
367     vlc_list_t         *p_list;\r
368 \r
369     module_config_t    *p_item;\r
370     int                 i_pages, i_ctrl;\r
371     \r
372     TTabSheet          *TabSheet;\r
373     TScrollBox         *ScrollBox;\r
374     TPanel             *Panel;\r
375     TGroupBoxPlugin    *GroupBoxPlugin;\r
376     TGroupBoxString    *GroupBoxString;\r
377     TGroupBoxInteger   *GroupBoxInteger;\r
378     TGroupBoxBool      *GroupBoxBool;\r
379     TListItem          *ListItem;\r
380 \r
381     /* Look for the selected module */\r
382     p_list = vlc_list_find( p_intfGlobal, VLC_OBJECT_MODULE, FIND_ANYWHERE );\r
383 \r
384     for( pp_parser = (module_t **)p_list->pp_objects ;\r
385          *pp_parser ;\r
386          pp_parser++ )\r
387     {\r
388         if( psz_module_name\r
389              && !strcmp( psz_module_name, (*pp_parser)->psz_object_name ) )\r
390         {\r
391             break;\r
392         }\r
393     }\r
394     if( !(*pp_parser) )\r
395     {\r
396         vlc_list_release( p_list );\r
397         return;\r
398     }\r
399 \r
400     /*\r
401      * We found it, now we can start building its configuration interface\r
402      */\r
403 \r
404     /* Enumerate config options and add corresponding config boxes */\r
405     p_item = (*pp_parser)->p_config;\r
406     if( p_item ) do\r
407     {\r
408         switch( p_item->i_type )\r
409         {\r
410         case CONFIG_HINT_CATEGORY:\r
411 \r
412             /* create a new tabsheet. */\r
413             TabSheet = new TTabSheet( this );\r
414             TabSheet->PageControl = PageControlPref;\r
415             TabSheet->Caption = p_item->psz_text;\r
416             TabSheet->Visible = true;\r
417 \r
418             /* pack a scrollbox into the tabsheet */\r
419             ScrollBox = new TScrollBox( this );\r
420             ScrollBox->Parent = TabSheet;\r
421             ScrollBox->Align = alClient;\r
422             ScrollBox->BorderStyle = bsNone;\r
423             ScrollBox->HorzScrollBar->Tracking = true;\r
424             ScrollBox->VertScrollBar->Tracking = true;\r
425 \r
426             break;\r
427 \r
428         case CONFIG_ITEM_MODULE:\r
429 \r
430             /* add new groupbox for the config option */\r
431             GroupBoxPlugin = new TGroupBoxPlugin( this, p_item );\r
432             GroupBoxPlugin->Parent = ScrollBox;\r
433 \r
434             /* add panel as separator */\r
435             ADD_PANEL;\r
436 \r
437             /* Look for valid modules */\r
438             pp_parser = (module_t **)p_list->pp_objects;\r
439 \r
440             for( ; *pp_parser ; pp_parser++ )\r
441             {\r
442                 if( !strcmp( (*pp_parser)->psz_capability, p_item->psz_type ) )\r
443                 {\r
444                     ListItem = GroupBoxPlugin->ListView->Items->Add();\r
445                     ListItem->Caption = (*pp_parser)->psz_object_name;\r
446                 }\r
447             }\r
448 \r
449             break;\r
450 \r
451         case CONFIG_ITEM_FILE:\r
452 \r
453         case CONFIG_ITEM_STRING:\r
454 \r
455             /* add new groupbox for the config option */\r
456             GroupBoxString = new TGroupBoxString( this, p_item );\r
457             GroupBoxString->Parent = ScrollBox;\r
458 \r
459             /* add panel as separator */\r
460             ADD_PANEL;\r
461 \r
462             break;\r
463 \r
464         case CONFIG_ITEM_INTEGER:\r
465 \r
466             /* add new groupbox for the config option */\r
467             GroupBoxInteger = new TGroupBoxInteger( this, p_item );\r
468             GroupBoxInteger->Parent = ScrollBox;\r
469 \r
470             /* add panel as separator */\r
471             ADD_PANEL;\r
472 \r
473             break;\r
474 \r
475         case CONFIG_ITEM_BOOL:\r
476 \r
477             /* add new groupbox for the config option */\r
478             GroupBoxBool = new TGroupBoxBool( this, p_item );\r
479             GroupBoxBool->Parent = ScrollBox;\r
480 \r
481             /* add panel as separator */\r
482             ADD_PANEL;\r
483 \r
484             break;\r
485         }\r
486         \r
487         p_item++;\r
488     }\r
489     while( p_item->i_type != CONFIG_HINT_END );\r
490 \r
491     /* Reorder groupboxes inside the tabsheets */\r
492     for( i_pages = 0; i_pages < PageControlPref->PageCount; i_pages++ )\r
493     {\r
494         /* get scrollbox from the tabsheet */\r
495         ScrollBox = (TScrollBox *)PageControlPref->Pages[i_pages]->Controls[0];\r
496 \r
497         for( i_ctrl = ScrollBox->ControlCount - 1; i_ctrl >= 0 ; i_ctrl-- )\r
498         {\r
499             ScrollBox->Controls[i_ctrl]->Align = alTop;\r
500         }\r
501     }\r
502 \r
503     vlc_list_release( p_list );\r
504 \r
505     /* set active tabsheet\r
506      * FIXME: i don't know why, but both lines are necessary */\r
507     PageControlPref->ActivePageIndex = 1;\r
508     PageControlPref->ActivePageIndex = 0;\r
509 }\r
510 #undef ADD_PANEL\r
511 //---------------------------------------------------------------------------\r
512 void __fastcall TPreferencesDlg::ButtonOkClick( TObject *Sender )\r
513 {\r
514     ButtonApplyClick( Sender );\r
515     Hide();\r
516 }\r
517 //---------------------------------------------------------------------------\r
518 void __fastcall TPreferencesDlg::ButtonApplyClick( TObject *Sender )\r
519 {\r
520     TScrollBox *ScrollBox;\r
521     TGroupBoxPref *GroupBox;\r
522     int i, j;\r
523 \r
524     for( i = 0; i < PageControlPref->PageCount; i++ )\r
525     {\r
526         /* get scrollbox from the tabsheet */\r
527         ScrollBox = (TScrollBox *)PageControlPref->Pages[i]->Controls[0];\r
528 \r
529         for( j = 0; j < ScrollBox->ControlCount ; j++ )\r
530         {\r
531             /* skip the panels */\r
532             if( ScrollBox->Controls[j]->InheritsFrom( __classid( TGroupBoxPref ) ) )\r
533             {\r
534                 GroupBox = (TGroupBoxPref *)ScrollBox->Controls[j];\r
535                 GroupBox->UpdateChanges();\r
536                 SaveValue( GroupBox->p_config );\r
537             }\r
538         }\r
539     }\r
540 }\r
541 //---------------------------------------------------------------------------\r
542 void __fastcall TPreferencesDlg::ButtonSaveClick( TObject *Sender )\r
543 {\r
544     ButtonApplyClick( Sender );\r
545     config_SaveConfigFile( p_intfGlobal, NULL );\r
546 }\r
547 //---------------------------------------------------------------------------\r
548 void __fastcall TPreferencesDlg::ButtonCancelClick( TObject *Sender )\r
549 {\r
550     Hide();\r
551 }\r
552 //---------------------------------------------------------------------------\r
553 void __fastcall TPreferencesDlg::SaveValue( module_config_t *p_config )\r
554 {\r
555     switch( p_config->i_type )\r
556     {\r
557         case CONFIG_ITEM_STRING:\r
558         case CONFIG_ITEM_FILE:\r
559         case CONFIG_ITEM_MODULE:\r
560             config_PutPsz( p_intfGlobal, p_config->psz_name,\r
561                            *p_config->psz_value ? p_config->psz_value : NULL );\r
562             break;\r
563         case CONFIG_ITEM_INTEGER:\r
564         case CONFIG_ITEM_BOOL:\r
565             config_PutInt( p_intfGlobal, p_config->psz_name,\r
566                            p_config->i_value );\r
567             break;\r
568     }\r
569 }\r
570 //---------------------------------------------------------------------------\r
571 \r