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