]> git.sesse.net Git - vlc/blob - modules/gui/win32/preferences.cpp
08e59d6503a5f1c0b4ff57dd1f289e408fbceff3
[vlc] / modules / gui / win32 / preferences.cpp
1 /*****************************************************************************\r
2  * preferences.cpp: the "Preferences" dialog box\r
3  *****************************************************************************\r
4  * Copyright (C) 2002-2003 VideoLAN\r
5  *\r
6  * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
7  *          Boris Dores <babal@via.ecp.fr>\r
8  *\r
9  * This program is free software; you can redistribute it and/or modify\r
10  * it under the terms of the GNU General Public License as published by\r
11  * the Free Software Foundation; either version 2 of the License, or\r
12  * (at your option) any later version.\r
13  *\r
14  * This program is distributed in the hope that it will be useful,\r
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
17  * GNU General Public License for more details.\r
18  *\r
19  * You should have received a copy of the GNU General Public License\r
20  * along with this program; if not, write to the Free Software\r
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
22  *****************************************************************************/\r
23 \r
24 #include <vcl.h>\r
25 #pragma hdrstop\r
26 \r
27 #include <stdlib.h>                                      /* malloc(), free() */\r
28 #include <string.h>                                                /* strcmp */\r
29 \r
30 #include <vlc/vlc.h>\r
31 #include <vlc/intf.h>\r
32 \r
33 #include "preferences.h"\r
34 #include "win32_common.h"\r
35 \r
36 //---------------------------------------------------------------------------\r
37 //#pragma package(smart_init)\r
38 #pragma link "CSPIN"\r
39 #pragma resource "*.dfm"\r
40 \r
41 /****************************************************************************\r
42  * A THintWindow with a limited width\r
43  ****************************************************************************/\r
44 void __fastcall TNarrowHintWindow::ActivateHint( const Windows::TRect &Rect,\r
45     const System::AnsiString AHint )\r
46 {\r
47     TRect NarrowRect = CalcHintRect( 300, AHint, NULL );\r
48     NarrowRect.Left = Rect.Left;\r
49     NarrowRect.Top = Rect.Top;\r
50     NarrowRect.Right += Rect.Left;\r
51     NarrowRect.Bottom += Rect.Top;\r
52     THintWindow::ActivateHint( NarrowRect, AHint );\r
53 }\r
54 \r
55 \r
56 /****************************************************************************\r
57  * Just a wrapper to embed an AnsiString into a TObject\r
58  ****************************************************************************/\r
59 __fastcall TObjectString::TObjectString( char * String )\r
60 {\r
61     FString = AnsiString( String );\r
62 }\r
63 //---------------------------------------------------------------------------\r
64 AnsiString __fastcall TObjectString::String()\r
65 {\r
66     return FString;\r
67 }\r
68 \r
69 \r
70 /****************************************************************************\r
71  * A TCheckListBox that automatically disposes any TObject\r
72  * associated with the string items\r
73  ****************************************************************************/\r
74 __fastcall TCleanCheckListBox::~TCleanCheckListBox()\r
75 {\r
76     for( int i = 0 ; i < Items->Count ; i++ )\r
77     {\r
78         if( Items->Objects[i] != NULL )\r
79             delete Items->Objects[i];\r
80     }\r
81 }\r
82 \r
83 \r
84 /****************************************************************************\r
85  * Functions to help components creation\r
86  ****************************************************************************/\r
87 __fastcall TPanelPref::TPanelPref( TComponent* Owner,\r
88     module_config_t *_p_config, intf_thread_t *_p_intf ) : TPanel( Owner )\r
89 {\r
90     p_intf = _p_intf;\r
91     p_config = _p_config;\r
92     BevelInner = bvNone;\r
93     BevelOuter = bvNone;\r
94     BorderStyle = bsNone;\r
95 }\r
96 //---------------------------------------------------------------------------\r
97 TCleanCheckListBox * __fastcall TPanelPref::CreateCleanCheckListBox(\r
98     TWinControl *Parent, int Left, int Width, int Top, int Height )\r
99 {\r
100     TCleanCheckListBox *CleanCheckListBox = new TCleanCheckListBox( Parent );\r
101     CleanCheckListBox->Parent = Parent;\r
102     CleanCheckListBox->Left = Left;\r
103     CleanCheckListBox->Width = Width;\r
104     CleanCheckListBox->Top = Top;\r
105     CleanCheckListBox->Height = Height;\r
106     return CleanCheckListBox;\r
107 }\r
108 //---------------------------------------------------------------------------\r
109 TButton * __fastcall TPanelPref::CreateButton( TWinControl *Parent,\r
110             int Left, int Width, int Top, int Height, AnsiString Caption )\r
111 {\r
112     TButton *Button = new TButton( Parent );\r
113     Button->Parent = Parent;\r
114     Button->Left = Left;\r
115     Button->Width = Width;\r
116     Button->Top = Top;\r
117     Button->Height = Height;\r
118     Button->Caption = Caption;\r
119     return Button;\r
120 }\r
121 //---------------------------------------------------------------------------\r
122 TCheckBox * __fastcall TPanelPref::CreateCheckBox( TWinControl *Parent,\r
123             int Left, int Width, int Top, int Height, AnsiString Caption )\r
124 {\r
125     TCheckBox *CheckBox = new TCheckBox( Parent );\r
126     CheckBox->Parent = Parent;\r
127     CheckBox->Left = Left;\r
128     CheckBox->Width = Width;\r
129     CheckBox->Top = Top;\r
130     CheckBox->Height = Height;\r
131     CheckBox->Caption = Caption;\r
132     return CheckBox;\r
133 }\r
134 //---------------------------------------------------------------------------\r
135 TLabel * __fastcall TPanelPref::CreateLabel( TWinControl *Parent,\r
136             int Left, int Width, int Top, int Height, AnsiString Caption,\r
137             bool WordWrap )\r
138 {\r
139     TLabel *Label = new TLabel( Parent );\r
140     Label->Parent = Parent;\r
141     Label->Caption = Caption;\r
142     Label->Left = Left;\r
143     Label->Width = Width;\r
144     Label->Top = Top;\r
145     Label->Height = Height;\r
146     Label->WordWrap = WordWrap;\r
147     return Label;\r
148 }\r
149 //---------------------------------------------------------------------------\r
150 TEdit * __fastcall TPanelPref::CreateEdit( TWinControl *Parent,\r
151             int Left, int Width, int Top, int Height, AnsiString Text )\r
152 {\r
153     TEdit *Edit = new TEdit( Parent );\r
154     Edit->Parent = Parent;\r
155     Edit->Left = Left;\r
156     Edit->Width = Width;\r
157     Edit->Top = Top;\r
158     Edit->Height = Height;\r
159     Edit->Text = Text;\r
160     return Edit;\r
161 }\r
162 //---------------------------------------------------------------------------\r
163 TCSpinEdit * __fastcall TPanelPref::CreateSpinEdit( TWinControl *Parent,\r
164             int Left, int Width, int Top, int Height,\r
165             long Min, long Max, long Value )\r
166 {\r
167     TCSpinEdit *SpinEdit = new TCSpinEdit( Parent );\r
168     SpinEdit->Parent = Parent;\r
169     SpinEdit->Left = Left;\r
170     SpinEdit->Width = Width;\r
171     SpinEdit->Top = Top;\r
172     SpinEdit->Height = Height;\r
173     SpinEdit->MinValue = Min;\r
174     SpinEdit->MaxValue = Max;\r
175     SpinEdit->Value = Value;\r
176     return SpinEdit;\r
177 }\r
178 //---------------------------------------------------------------------------\r
179 \r
180 #define LIBWIN32_PREFSIZE_VPAD                4\r
181 #define LIBWIN32_PREFSIZE_HPAD                4\r
182 #define LIBWIN32_PREFSIZE_LEFT                16\r
183 #define LIBWIN32_PREFSIZE_EDIT_LEFT           (LIBWIN32_PREFSIZE_LEFT+32)\r
184 #define LIBWIN32_PREFSIZE_WIDTH               375\r
185 #define LIBWIN32_PREFSIZE_EDIT_WIDTH          (LIBWIN32_PREFSIZE_WIDTH-32)\r
186 #define LIBWIN32_PREFSIZE_BUTTON_WIDTH        150\r
187 #define LIBWIN32_PREFSIZE_SPINEDIT_WIDTH      100\r
188 #define LIBWIN32_PREFSIZE_RIGHT               (LIBWIN32_PREFSIZE_LEFT+LIBWIN32_PREFSIZE_WIDTH)\r
189 #define LIBWIN32_PREFSIZE_BUTTON_HEIGHT       23\r
190 #define LIBWIN32_PREFSIZE_LABEL_HEIGHT        26\r
191 #define LIBWIN32_PREFSIZE_CHECKLISTBOX_HEIGHT 120\r
192 #define LIBWIN32_PREFSIZE_EDIT_HEIGHT         21\r
193 #define LIBWIN32_PREFSIZE_CHECKBOX_HEIGHT     17\r
194 #define LIBWIN32_PREFSIZE_SPINEDIT_HEIGHT     21\r
195 \r
196 /****************************************************************************\r
197  * Panel for module management\r
198  ****************************************************************************/\r
199 __fastcall TPanelPlugin::TPanelPlugin( TComponent* Owner,\r
200         module_config_t *p_config, intf_thread_t *_p_intf,\r
201         bool b_multi_plugins ) : TPanelPref( Owner, p_config, _p_intf )\r
202 {\r
203     this->b_multi_plugins = b_multi_plugins;\r
204 \r
205     /* init configure button */\r
206     ButtonConfig = CreateButton( this,\r
207             LIBWIN32_PREFSIZE_RIGHT - LIBWIN32_PREFSIZE_BUTTON_WIDTH,\r
208             LIBWIN32_PREFSIZE_BUTTON_WIDTH,\r
209             LIBWIN32_PREFSIZE_VPAD,\r
210             LIBWIN32_PREFSIZE_BUTTON_HEIGHT,\r
211             "Configure..." );\r
212     ButtonConfig->Enabled = false;\r
213     ButtonConfig->OnClick = ButtonConfigClick;\r
214 \r
215     /* init label */\r
216     AnsiString Text = AnsiString( p_config->psz_text ) + ":";\r
217     Label = CreateLabel( this,\r
218             LIBWIN32_PREFSIZE_LEFT,\r
219             LIBWIN32_PREFSIZE_RIGHT - LIBWIN32_PREFSIZE_BUTTON_WIDTH\r
220              - LIBWIN32_PREFSIZE_HPAD,\r
221             LIBWIN32_PREFSIZE_VPAD,\r
222             LIBWIN32_PREFSIZE_LABEL_HEIGHT,\r
223             Text.c_str(), true );\r
224 \r
225     /* vertical alignement */\r
226     if ( ButtonConfig->Height > Label->Height )\r
227         Label->Top += ( ButtonConfig->Height - Label->Height ) / 2;\r
228     else\r
229         ButtonConfig->Top += ( Label->Height - ButtonConfig->Height ) / 2;\r
230 \r
231     /* init checklistbox */\r
232     CleanCheckListBox = CreateCleanCheckListBox( this,\r
233             LIBWIN32_PREFSIZE_EDIT_LEFT,\r
234             LIBWIN32_PREFSIZE_EDIT_WIDTH,\r
235             max( Label->Top + Label->Height , ButtonConfig->Top\r
236                  + ButtonConfig->Height ) + LIBWIN32_PREFSIZE_VPAD,\r
237                  LIBWIN32_PREFSIZE_CHECKLISTBOX_HEIGHT );\r
238     CleanCheckListBox->OnClick = CheckListBoxClick;\r
239     CleanCheckListBox->OnClickCheck = CheckListBoxClickCheck;\r
240     CleanCheckListBox->Hint = p_config->psz_longtext;\r
241     CleanCheckListBox->ShowHint = true;\r
242 \r
243     /* init up and down buttons */\r
244     if ( b_multi_plugins )\r
245     {\r
246         ButtonUp = CreateButton ( this, LIBWIN32_PREFSIZE_LEFT,\r
247                 CleanCheckListBox->Left - LIBWIN32_PREFSIZE_HPAD\r
248                     - LIBWIN32_PREFSIZE_LEFT,\r
249                 CleanCheckListBox->Top + ( CleanCheckListBox->Height\r
250                     - 2*LIBWIN32_PREFSIZE_BUTTON_HEIGHT ) / 3,\r
251                 LIBWIN32_PREFSIZE_BUTTON_HEIGHT,\r
252                 "+" );\r
253         ButtonUp->Enabled = false;\r
254         ButtonUp->OnClick = ButtonUpClick;\r
255         ButtonUp->Hint = "Raise the plugin priority";\r
256         ButtonUp->ShowHint = true;\r
257 \r
258         ButtonDown = CreateButton ( this, LIBWIN32_PREFSIZE_LEFT,\r
259                 CleanCheckListBox->Left - LIBWIN32_PREFSIZE_HPAD\r
260                     - LIBWIN32_PREFSIZE_LEFT,\r
261                 CleanCheckListBox->Top + ( CleanCheckListBox->Height\r
262                     - 2*LIBWIN32_PREFSIZE_BUTTON_HEIGHT ) * 2 / 3\r
263                     + LIBWIN32_PREFSIZE_BUTTON_HEIGHT,\r
264                 LIBWIN32_PREFSIZE_BUTTON_HEIGHT,\r
265                 "-" );\r
266         ButtonDown->Enabled = false;\r
267         ButtonDown->OnClick = ButtonDownClick;\r
268         ButtonDown->Hint = "Decrease the plugin priority";\r
269         ButtonDown->ShowHint = true;\r
270     }\r
271     else\r
272     {\r
273         ButtonUp = NULL;\r
274         ButtonDown = NULL;\r
275     }\r
276 \r
277     /* panel height */\r
278     Height = CleanCheckListBox->Top + CleanCheckListBox->Height\r
279             + LIBWIN32_PREFSIZE_VPAD;\r
280 };\r
281 //---------------------------------------------------------------------------\r
282 void __fastcall TPanelPlugin::CheckListBoxClick( TObject *Sender )\r
283 {\r
284     module_t *p_parser;\r
285     vlc_list_t *p_list;\r
286     int i_index;\r
287 \r
288     /* check that the click is valid (we are on an item, and the click\r
289      * started on an item */\r
290     if( CleanCheckListBox->ItemIndex == -1 )\r
291     {\r
292         if ( ButtonUp != NULL ) ButtonUp->Enabled = false;\r
293         if ( ButtonDown != NULL ) ButtonDown->Enabled = false;\r
294         return;\r
295     }\r
296 \r
297     AnsiString Name = ((TObjectString*)CleanCheckListBox->Items->\r
298         Objects[CleanCheckListBox->ItemIndex])->String().c_str();\r
299     if( Name == "" )\r
300         return;\r
301 \r
302     /* enable up and down buttons */\r
303     if ( b_multi_plugins && ButtonUp != NULL && ButtonDown != NULL )\r
304     {\r
305         if ( CleanCheckListBox->ItemIndex == 0 )\r
306             ButtonUp->Enabled = false; else ButtonUp->Enabled = true;\r
307         if ( CleanCheckListBox->ItemIndex\r
308             == CleanCheckListBox->Items->Count - 1 )\r
309             ButtonDown->Enabled = false; else ButtonDown->Enabled = true;\r
310     }\r
311 \r
312     /* look for module 'Name' */\r
313     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );\r
314 \r
315     for( i_index = 0; i_index < p_list->i_count; i_index++ )\r
316     {\r
317         p_parser = (module_t *)p_list->p_values[i_index].p_object ;\r
318 \r
319         if( strcmp( p_parser->psz_object_name, Name.c_str() ) == 0 )\r
320         {\r
321             ModuleSelected = p_parser;\r
322             ButtonConfig->Enabled =\r
323                 p_parser->i_config_items ? true : false;\r
324 \r
325             break;\r
326         }\r
327     }\r
328     vlc_list_release( p_list );\r
329 }\r
330 //---------------------------------------------------------------------------\r
331 void __fastcall TPanelPlugin::CheckListBoxClickCheck( TObject *Sender )\r
332 {\r
333     if ( ! b_multi_plugins )\r
334     {\r
335         /* one item maximum must be checked */\r
336         if( CleanCheckListBox->Checked[CleanCheckListBox->ItemIndex] )\r
337         {\r
338             for( int item = 0; item < CleanCheckListBox->Items->Count; item++ )\r
339             {\r
340                 if( item != CleanCheckListBox->ItemIndex )\r
341                 {\r
342                     CleanCheckListBox->Checked[item] = false;\r
343                 }\r
344             }\r
345         }\r
346     }\r
347 }\r
348 //---------------------------------------------------------------------------\r
349 void __fastcall TPanelPlugin::ButtonConfigClick( TObject *Sender )\r
350 {\r
351     p_intf->p_sys->p_window->\r
352                         CreatePreferences( ModuleSelected->psz_object_name );\r
353 }\r
354 //---------------------------------------------------------------------------\r
355 void __fastcall TPanelPlugin::ButtonUpClick( TObject *Sender )\r
356 {\r
357     if( CleanCheckListBox->ItemIndex != -1 && CleanCheckListBox->ItemIndex > 0 )\r
358     {\r
359         int Pos = CleanCheckListBox->ItemIndex;\r
360         CleanCheckListBox->Items->Move ( Pos , Pos - 1 );\r
361         CleanCheckListBox->ItemIndex = Pos - 1;\r
362         CheckListBoxClick ( Sender );\r
363     }\r
364 }\r
365 //---------------------------------------------------------------------------\r
366 void __fastcall TPanelPlugin::ButtonDownClick( TObject *Sender )\r
367 {\r
368     if( CleanCheckListBox->ItemIndex != -1\r
369         && CleanCheckListBox->ItemIndex < CleanCheckListBox->Items->Count - 1 )\r
370     {\r
371         int Pos = CleanCheckListBox->ItemIndex;\r
372         CleanCheckListBox->Items->Move ( Pos , Pos + 1 );\r
373         CleanCheckListBox->ItemIndex = Pos + 1;\r
374         CheckListBoxClick ( Sender );\r
375     }\r
376 }\r
377 //---------------------------------------------------------------------------\r
378 void __fastcall TPanelPlugin::SetValue ( AnsiString Values )\r
379 {\r
380     int TopChecked = 0;\r
381     while ( Values.Length() != 0 )\r
382     {\r
383         AnsiString Value;\r
384 \r
385         int NextValue = Values.Pos ( "," );\r
386         if ( NextValue == 0 )\r
387         {\r
388             Value = Values.Trim();\r
389             Values = "";\r
390         }\r
391         else\r
392         {\r
393             Value = Values.SubString(1,NextValue-1).Trim();\r
394             Values = Values.SubString ( NextValue + 1\r
395                     , Values.Length() - NextValue );\r
396         }\r
397 \r
398         if ( Value.Length() > 0 )\r
399         {\r
400             for ( int i = TopChecked; i < CleanCheckListBox->Items->Count; i++ )\r
401             {\r
402                 if ( ((TObjectString*)CleanCheckListBox->Items->Objects[i])\r
403                         ->String() == Value )\r
404                 {\r
405                     CleanCheckListBox->Checked[i] = true;\r
406                     CleanCheckListBox->Items->Move ( i , TopChecked );\r
407                     TopChecked++;\r
408                 }\r
409             }\r
410         }\r
411     }\r
412 }\r
413 //---------------------------------------------------------------------------\r
414 void __fastcall TPanelPlugin::UpdateChanges()\r
415 {\r
416     AnsiString Name = "";\r
417 \r
418     /* find the selected plugin (if any) */\r
419     for( int item = 0; item < CleanCheckListBox->Items->Count; item++ )\r
420     {\r
421         if( CleanCheckListBox->Checked[item] )\r
422         {\r
423             if ( Name.Length() == 0 )\r
424             {\r
425                 Name = ((TObjectString*)CleanCheckListBox->Items->Objects[item])\r
426                        ->String();\r
427             }\r
428             else\r
429             {\r
430                 Name = Name + ","\r
431                      + ((TObjectString*)CleanCheckListBox->Items->Objects[item])\r
432                        ->String();\r
433             }\r
434         }\r
435     }\r
436 \r
437     config_PutPsz( p_intf, p_config->psz_name,\r
438                    Name.Length() ? Name.c_str() : NULL );\r
439 }\r
440 \r
441 \r
442 /****************************************************************************\r
443  * Panel for string management\r
444  ****************************************************************************/\r
445 __fastcall TPanelString::TPanelString( TComponent* Owner,\r
446         module_config_t *p_config, intf_thread_t *_p_intf )\r
447         : TPanelPref( Owner, p_config, _p_intf )\r
448 {\r
449     /* init description label */\r
450     AnsiString Text = AnsiString ( p_config->psz_text ) + ":";\r
451     Label = CreateLabel( this,\r
452             LIBWIN32_PREFSIZE_LEFT,\r
453             LIBWIN32_PREFSIZE_WIDTH,\r
454             LIBWIN32_PREFSIZE_VPAD,\r
455             LIBWIN32_PREFSIZE_LABEL_HEIGHT,\r
456             Text.c_str(), true );\r
457 \r
458     /* init edit */\r
459     Edit = CreateEdit( this,\r
460             LIBWIN32_PREFSIZE_EDIT_LEFT,\r
461             LIBWIN32_PREFSIZE_EDIT_WIDTH,\r
462             LIBWIN32_PREFSIZE_VPAD + Label->Height + LIBWIN32_PREFSIZE_VPAD,\r
463             LIBWIN32_PREFSIZE_EDIT_HEIGHT, "" );\r
464     vlc_mutex_lock( p_config->p_lock );\r
465     Edit->Text = p_config->psz_value ? p_config->psz_value : "";\r
466     vlc_mutex_unlock( p_config->p_lock );\r
467     Edit->Hint = p_config->psz_longtext;\r
468     Edit->ShowHint = true;\r
469 \r
470     /* panel height */\r
471     Height = LIBWIN32_PREFSIZE_VPAD + Label->Height + LIBWIN32_PREFSIZE_VPAD\r
472             + Edit->Height + LIBWIN32_PREFSIZE_VPAD;\r
473 };\r
474 //---------------------------------------------------------------------------\r
475 void __fastcall TPanelString::UpdateChanges()\r
476 {\r
477     config_PutPsz( p_intf, p_config->psz_name,\r
478                    Edit->Text.Length() ? Edit->Text.c_str() : NULL );\r
479 }\r
480 \r
481 \r
482 /****************************************************************************\r
483  * Panel for integer management\r
484  ****************************************************************************/\r
485 __fastcall TPanelInteger::TPanelInteger( TComponent* Owner,\r
486         module_config_t *p_config, intf_thread_t *_p_intf )\r
487         : TPanelPref( Owner, p_config, _p_intf )\r
488 {\r
489     /* init description label */\r
490     AnsiString Text = AnsiString ( p_config->psz_text ) + ":";\r
491     Label = CreateLabel( this,\r
492             LIBWIN32_PREFSIZE_LEFT,\r
493             LIBWIN32_PREFSIZE_WIDTH - LIBWIN32_PREFSIZE_SPINEDIT_WIDTH\r
494              - LIBWIN32_PREFSIZE_HPAD,\r
495             LIBWIN32_PREFSIZE_VPAD,\r
496             LIBWIN32_PREFSIZE_LABEL_HEIGHT, Text.c_str(), true );\r
497 \r
498     /* init spinedit */\r
499     SpinEdit = CreateSpinEdit( this,\r
500             LIBWIN32_PREFSIZE_RIGHT - LIBWIN32_PREFSIZE_SPINEDIT_WIDTH,\r
501             LIBWIN32_PREFSIZE_SPINEDIT_WIDTH,\r
502             LIBWIN32_PREFSIZE_VPAD,\r
503             LIBWIN32_PREFSIZE_SPINEDIT_HEIGHT,\r
504             -1, 100000, p_config->i_value );\r
505     SpinEdit->Hint = p_config->psz_longtext;\r
506     SpinEdit->ShowHint = true;\r
507 \r
508     /* vertical alignement and panel height */\r
509     if ( SpinEdit->Height > Label->Height )\r
510     {\r
511         Label->Top += ( SpinEdit->Height - Label->Height ) / 2;\r
512         Height = SpinEdit->Top + SpinEdit->Height + LIBWIN32_PREFSIZE_VPAD;\r
513     }\r
514     else\r
515     {\r
516         SpinEdit->Top += ( Label->Height - SpinEdit->Height ) / 2;\r
517         Height = Label->Top + Label->Height + LIBWIN32_PREFSIZE_VPAD;\r
518     }\r
519 };\r
520 //---------------------------------------------------------------------------\r
521 void __fastcall TPanelInteger::UpdateChanges()\r
522 {\r
523     /* Warning: we're casting from long to int */\r
524     config_PutInt( p_intf, p_config->psz_name, (int)SpinEdit->Value );\r
525 }\r
526 \r
527 \r
528 /****************************************************************************\r
529  * Panel for float management\r
530  ****************************************************************************/\r
531 __fastcall TPanelFloat::TPanelFloat( TComponent* Owner,\r
532         module_config_t *p_config, intf_thread_t *_p_intf )\r
533         : TPanelPref( Owner, p_config, _p_intf )\r
534 {\r
535 #define MAX_FLOAT_CHARS 20\r
536     /* init description label */\r
537     AnsiString Text = AnsiString( p_config->psz_text ) + ":";\r
538     Label = CreateLabel( this,\r
539             LIBWIN32_PREFSIZE_LEFT,\r
540             LIBWIN32_PREFSIZE_WIDTH,\r
541             LIBWIN32_PREFSIZE_VPAD,\r
542             LIBWIN32_PREFSIZE_LABEL_HEIGHT,\r
543             Text.c_str(), true );\r
544 \r
545     /* init edit */\r
546     char *psz_value = (char *)malloc( MAX_FLOAT_CHARS );\r
547     snprintf( psz_value, MAX_FLOAT_CHARS, "%f", p_config->f_value );\r
548     /* we use the spinedit size, to be similar with the integers */\r
549     Edit = CreateEdit( this,\r
550             LIBWIN32_PREFSIZE_RIGHT - LIBWIN32_PREFSIZE_SPINEDIT_WIDTH,\r
551             LIBWIN32_PREFSIZE_SPINEDIT_WIDTH,\r
552             LIBWIN32_PREFSIZE_VPAD,\r
553             LIBWIN32_PREFSIZE_SPINEDIT_HEIGHT,\r
554             psz_value );\r
555     free( psz_value );\r
556     Edit->Hint = p_config->psz_longtext;\r
557     Edit->ShowHint = true;\r
558 \r
559     /* vertical alignement and panel height */\r
560     if ( Edit->Height > Label->Height )\r
561     {\r
562         Label->Top += ( Edit->Height - Label->Height ) / 2;\r
563         Height = Edit->Top + Edit->Height + LIBWIN32_PREFSIZE_VPAD;\r
564     }\r
565     else\r
566     {\r
567         Edit->Top += ( Label->Height - Edit->Height ) / 2;\r
568         Height = Label->Top + Label->Height + LIBWIN32_PREFSIZE_VPAD;\r
569     }\r
570 \r
571 #undef MAX_FLOAT_CHARS\r
572 };\r
573 //---------------------------------------------------------------------------\r
574 void __fastcall TPanelFloat::UpdateChanges()\r
575 {\r
576     /* Warning: we're casting from double to float */\r
577     config_PutFloat( p_intf, p_config->psz_name, atof( Edit->Text.c_str() ) );\r
578 }\r
579 \r
580 \r
581 /****************************************************************************\r
582  * Panel for boolean management\r
583  ****************************************************************************/\r
584 __fastcall TPanelBool::TPanelBool( TComponent* Owner,\r
585         module_config_t *p_config, intf_thread_t *_p_intf )\r
586         : TPanelPref( Owner, p_config, _p_intf )\r
587 {\r
588     /* init checkbox */\r
589     CheckBox = CreateCheckBox( this,\r
590             LIBWIN32_PREFSIZE_LEFT,\r
591             LIBWIN32_PREFSIZE_WIDTH,\r
592             LIBWIN32_PREFSIZE_VPAD,\r
593             LIBWIN32_PREFSIZE_CHECKBOX_HEIGHT, p_config->psz_text );\r
594     CheckBox->Checked = p_config->i_value;\r
595     CheckBox->Hint = p_config->psz_longtext;\r
596     CheckBox->ShowHint = true;\r
597 \r
598     /* panel height */\r
599     Height = LIBWIN32_PREFSIZE_VPAD + CheckBox->Height + LIBWIN32_PREFSIZE_VPAD;\r
600 };\r
601 //---------------------------------------------------------------------------\r
602 void __fastcall TPanelBool::UpdateChanges()\r
603 {\r
604     config_PutInt( p_intf, p_config->psz_name, CheckBox->Checked ? 1 : 0 );\r
605 }\r
606 \r
607 \r
608 /****************************************************************************\r
609  * Callbacks for the dialog\r
610  ****************************************************************************/\r
611 __fastcall TPreferencesDlg::TPreferencesDlg( TComponent* Owner,\r
612     intf_thread_t *_p_intf ) : TForm( Owner )\r
613 {\r
614     p_intf = _p_intf;\r
615     Icon = p_intf->p_sys->p_window->Icon;\r
616     Application->HintHidePause = 0x1000000;\r
617     HintWindowClass = __classid ( TNarrowHintWindow );\r
618     /* prevent the form from being resized horizontally */\r
619     Constraints->MinWidth = Width;\r
620     Constraints->MaxWidth = Width;\r
621 }\r
622 //---------------------------------------------------------------------------\r
623 void __fastcall TPreferencesDlg::FormClose( TObject *Sender,\r
624       TCloseAction &Action )\r
625 {\r
626     Action = caHide;\r
627 }\r
628 \r
629 \r
630 /****************************************************************************\r
631  * CreateConfigDialog: dynamically creates the configuration dialog\r
632  * box from all the configuration data provided by the selected module.\r
633  ****************************************************************************/\r
634 #define ADD_PANEL                               \\r
635 {                                               \\r
636             Panel = new TPanel( this );         \\r
637             Panel->Parent = ScrollBox;          \\r
638             Panel->Caption = "";                \\r
639             Panel->BevelOuter = bvNone;         \\r
640             Panel->Height = 12;                 \\r
641 }\r
642 \r
643 void __fastcall TPreferencesDlg::CreateConfigDialog( char *psz_module_name )\r
644 {\r
645     module_t           *p_parser;\r
646     vlc_list_t         *p_list;\r
647     int                 i_index;\r
648 \r
649     module_config_t    *p_item;\r
650     int                 i_pages, i_ctrl;\r
651 \r
652     TTabSheet          *TabSheet;\r
653     TScrollBox         *ScrollBox = NULL;\r
654     TPanel             *Panel;\r
655     TPanelPlugin       *PanelPlugin;\r
656     TPanelString       *PanelString;\r
657     TPanelInteger      *PanelInteger;\r
658     TPanelFloat        *PanelFloat;\r
659     TPanelBool         *PanelBool;\r
660 \r
661     /* Look for the selected module */\r
662     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );\r
663 \r
664     for( i_index = 0; i_index < p_list->i_count; i_index++ )\r
665     {\r
666         p_parser = (module_t *)p_list->p_values[i_index].p_object ;\r
667 \r
668         if( psz_module_name\r
669              && !strcmp( psz_module_name, p_parser->psz_object_name ) )\r
670         {\r
671             break;\r
672         }\r
673     }\r
674     if( !p_parser || i_index == p_list->i_count )\r
675     {\r
676         vlc_list_release( p_list );\r
677         return;\r
678     }\r
679 \r
680     /*\r
681      * We found it, now we can start building its configuration interface\r
682      */\r
683 \r
684     /* Enumerate config options and add corresponding config boxes */\r
685     p_item = p_parser->p_config;\r
686     if( p_item ) do\r
687     {\r
688         switch( p_item->i_type )\r
689         {\r
690         case CONFIG_HINT_CATEGORY:\r
691 \r
692             /* create a new tabsheet. */\r
693             TabSheet = new TTabSheet( this );\r
694             TabSheet->PageControl = PageControlPref;\r
695             TabSheet->Caption = p_item->psz_text;\r
696             TabSheet->Visible = true;\r
697 \r
698             /* pack a scrollbox into the tabsheet */\r
699             ScrollBox = new TScrollBox( this );\r
700             ScrollBox->Parent = TabSheet;\r
701             ScrollBox->Align = alClient;\r
702             ScrollBox->BorderStyle = bsNone;\r
703             ScrollBox->HorzScrollBar->Tracking = true;\r
704             ScrollBox->VertScrollBar->Tracking = true;\r
705 \r
706             /* add a panel as top margin */\r
707             ADD_PANEL;\r
708 \r
709             break;\r
710 \r
711         case CONFIG_ITEM_MODULE:\r
712 \r
713             /* add new panel for the config option */\r
714             PanelPlugin = new TPanelPlugin( this, p_item, p_intf, true );\r
715             PanelPlugin->Parent = ScrollBox;\r
716 \r
717             /* Look for valid modules */\r
718             for( i_index = 0; i_index < p_list->i_count; i_index++ )\r
719             {\r
720                 p_parser = (module_t *)p_list->p_values[i_index].p_object ;\r
721 \r
722                 if( !strcmp( p_parser->psz_capability, p_item->psz_type ) )\r
723                 {\r
724                     AnsiString ModuleDesc;\r
725                     if ( p_parser->psz_longname != NULL ) {\r
726                         ModuleDesc = AnsiString( p_parser->psz_longname ) +\r
727                             " (" + AnsiString( p_parser->psz_object_name ) +\r
728                             ")";\r
729                     }\r
730                     else\r
731                         ModuleDesc = AnsiString( p_parser->psz_object_name );\r
732 \r
733                     PanelPlugin->CleanCheckListBox->Items->AddObject(\r
734                         ModuleDesc.c_str(),\r
735                         new TObjectString( p_parser->psz_object_name ) );\r
736                 }\r
737             }\r
738 \r
739             /* check relevant boxes */\r
740             PanelPlugin->SetValue ( AnsiString ( p_item->psz_value ) );\r
741 \r
742             break;\r
743 \r
744         case CONFIG_ITEM_FILE:\r
745 \r
746         case CONFIG_ITEM_STRING:\r
747 \r
748             /* add new panel for the config option */\r
749             PanelString = new TPanelString( this, p_item, p_intf );\r
750             PanelString->Parent = ScrollBox;\r
751 \r
752             break;\r
753 \r
754         case CONFIG_ITEM_INTEGER:\r
755 \r
756             /* add new panel for the config option */\r
757             PanelInteger = new TPanelInteger( this, p_item, p_intf );\r
758             PanelInteger->Parent = ScrollBox;\r
759 \r
760             break;\r
761 \r
762         case CONFIG_ITEM_FLOAT:\r
763 \r
764             /* add new panel for the config option */\r
765             PanelFloat = new TPanelFloat( this, p_item, p_intf );\r
766             PanelFloat->Parent = ScrollBox;\r
767 \r
768             break;\r
769 \r
770         case CONFIG_ITEM_BOOL:\r
771 \r
772             /* add new panel for the config option */\r
773             PanelBool = new TPanelBool( this, p_item, p_intf );\r
774             PanelBool->Parent = ScrollBox;\r
775 \r
776             break;\r
777         default:\r
778             msg_Warn( p_intf, "unknown config type: %i", p_item->i_type );\r
779             break;\r
780         }\r
781 \r
782         p_item++;\r
783     }\r
784     while( p_item->i_type != CONFIG_HINT_END );\r
785 \r
786     /* Reorder panels inside the tabsheets */\r
787     for( i_pages = 0; i_pages < PageControlPref->PageCount; i_pages++ )\r
788     {\r
789         /* get scrollbox from the tabsheet */\r
790         ScrollBox = (TScrollBox *)PageControlPref->Pages[i_pages]->Controls[0];\r
791 \r
792         /* add a panel as bottom margin */\r
793         ADD_PANEL;\r
794 \r
795         for( i_ctrl = ScrollBox->ControlCount - 1; i_ctrl >= 0 ; i_ctrl-- )\r
796         {\r
797             ScrollBox->Controls[i_ctrl]->Align = alTop;\r
798         }\r
799     }\r
800 \r
801     vlc_list_release( p_list );\r
802 \r
803     /* set active tabsheet\r
804      * FIXME: i don't know why, but both lines are necessary */\r
805     PageControlPref->ActivePageIndex = 1;\r
806     PageControlPref->ActivePageIndex = 0;\r
807 }\r
808 #undef ADD_PANEL\r
809 //---------------------------------------------------------------------------\r
810 void __fastcall TPreferencesDlg::ButtonOkClick( TObject *Sender )\r
811 {\r
812     ButtonApplyClick( Sender );\r
813     Hide();\r
814 }\r
815 //---------------------------------------------------------------------------\r
816 void __fastcall TPreferencesDlg::ButtonApplyClick( TObject *Sender )\r
817 {\r
818     TScrollBox *ScrollBox;\r
819     TPanelPref *Panel;\r
820     int i, j;\r
821 \r
822     for( i = 0; i < PageControlPref->PageCount; i++ )\r
823     {\r
824         /* get scrollbox from the tabsheet */\r
825         ScrollBox = (TScrollBox *)PageControlPref->Pages[i]->Controls[0];\r
826 \r
827         for( j = 0; j < ScrollBox->ControlCount ; j++ )\r
828         {\r
829             /* skip the panels */\r
830             if( ScrollBox->Controls[j]->InheritsFrom( __classid( TPanelPref ) ) )\r
831             {\r
832                 Panel = (TPanelPref *)ScrollBox->Controls[j];\r
833                 Panel->UpdateChanges();\r
834             }\r
835         }\r
836     }\r
837 }\r
838 //---------------------------------------------------------------------------\r
839 void __fastcall TPreferencesDlg::ButtonSaveClick( TObject *Sender )\r
840 {\r
841     ButtonApplyClick( Sender );\r
842     config_SaveConfigFile( p_intf, NULL );\r
843 }\r
844 //---------------------------------------------------------------------------\r
845 void __fastcall TPreferencesDlg::ButtonCancelClick( TObject *Sender )\r
846 {\r
847     Hide();\r
848 }\r
849 //---------------------------------------------------------------------------\r