]> git.sesse.net Git - vlc/blob - modules/gui/wince/preferences.cpp
* modules/gui/wince: some more code cleanup + fixes.
[vlc] / modules / gui / wince / preferences.cpp
1 /*****************************************************************************
2  * preferences.cpp : WinCE gui plugin for VLC
3  *****************************************************************************
4  * Copyright (C) 2000-2004 VideoLAN
5  * $Id$
6  *
7  * Authors: Marodon Cedric <cedric_marodon@yahoo.fr>
8  *          Gildas Bazin <gbazin@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31 #include <vlc/vlc.h>
32 #include <vlc/intf.h>
33
34 #include "wince.h"
35
36 #include <winuser.h>
37 #include <windows.h>
38 #include <windowsx.h>
39 #include <commctrl.h>
40 #include <commdlg.h>
41
42 #include <vlc_config_cat.h>
43
44 #include "preferences_widgets.h"
45
46 #define GENERAL_ID 1242
47 #define PLUGIN_ID 1243
48 #define CAPABILITY_ID 1244
49
50 /*****************************************************************************
51  * Event Table.
52  *****************************************************************************/
53
54 /* IDs for the controls and the menu commands */
55 enum
56 {
57     Notebook_Event,
58     MRL_Event,
59     ResetAll_Event,
60     Advanced_Event
61 };
62
63 /*****************************************************************************
64  * Classes declarations.
65  *****************************************************************************/
66 class ConfigTreeData;
67 class PrefsTreeCtrl
68 {
69 public:
70
71     PrefsTreeCtrl() { }
72     PrefsTreeCtrl( intf_thread_t *_p_intf, PrefsDialog *p_prefs_dialog,
73                    HWND hwnd, HINSTANCE _hInst );
74     virtual ~PrefsTreeCtrl();
75
76     void ApplyChanges();
77     /*void CleanChanges();*/
78
79     void OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent, HINSTANCE hInst );
80         
81     ConfigTreeData *FindModuleConfig( ConfigTreeData *config_data );
82
83     HWND hwndTV;
84
85 private:
86     intf_thread_t *p_intf;
87     PrefsDialog *p_prefs_dialog;
88     vlc_bool_t b_advanced;
89
90     HTREEITEM root_item;
91     HTREEITEM general_item;
92     HTREEITEM plugins_item;
93 };
94
95 class PrefsPanel
96 {
97 public:
98
99     PrefsPanel() { }
100     PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
101                 PrefsDialog *, int i_object_id, char *, char * );
102     virtual ~PrefsPanel() {}
103
104     void Hide();
105     void Show();
106
107     HWND config_window;
108
109     int oldvalue;
110     int maxvalue;
111
112     void ApplyChanges();
113
114 private:
115     intf_thread_t *p_intf;
116     PrefsDialog *p_prefs_dialog;
117
118     vlc_bool_t b_advanced;
119
120     HWND label;
121
122     vector<ConfigControl *> config_array;
123 };
124
125 class ConfigTreeData
126 {
127 public:
128
129     ConfigTreeData() { b_submodule = 0; panel = NULL; psz_section = NULL;
130                        psz_help = NULL; }
131     virtual ~ConfigTreeData() { if( panel ) delete panel;
132                                 if( psz_section) free(psz_section);
133                                 if( psz_help) free(psz_help); }
134
135     vlc_bool_t b_submodule;
136
137     PrefsPanel *panel;
138     int i_object_id;
139     char *psz_section;
140     char *psz_help;
141 };
142
143 /*****************************************************************************
144  * Constructor.
145  *****************************************************************************/
146 PrefsDialog::PrefsDialog( intf_thread_t *_p_intf, HINSTANCE _hInst )
147 {
148     /* Initializations */
149     p_intf = _p_intf;
150     hInst = _hInst;
151     prefs_tree = NULL;
152 }
153
154 /***********************************************************************
155
156 FUNCTION: 
157   WndProc
158
159 PURPOSE: 
160   Processes messages sent to the main window.
161
162 ***********************************************************************/
163 LRESULT PrefsDialog::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
164 {
165     SHINITDLGINFO shidi;
166     SHMENUBARINFO mbi;
167     RECT rcClient;
168
169     switch( msg )
170     {
171     case WM_INITDIALOG:
172         shidi.dwMask = SHIDIM_FLAGS;
173         shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN |
174             SHIDIF_FULLSCREENNOMENUBAR;//SHIDIF_SIZEDLGFULLSCREEN;
175         shidi.hDlg = hwnd;
176         SHInitDialog( &shidi );
177
178         //Create the menubar
179         memset( &mbi, 0, sizeof (SHMENUBARINFO) );
180         mbi.cbSize     = sizeof (SHMENUBARINFO);
181         mbi.hwndParent = hwnd;
182         mbi.nToolBarId = IDR_DUMMYMENU;
183         mbi.hInstRes   = hInst;
184         mbi.nBmpId     = 0;
185         mbi.cBmpImages = 0;
186
187         if( !SHCreateMenuBar(&mbi) )
188         {
189             MessageBox(hwnd, _T("SHCreateMenuBar Failed"), _T("Error"), MB_OK);
190             //return -1;
191         }
192
193         hwndCB = mbi.hwndMB;
194
195         // Get the client area rect to put the panels in
196         GetClientRect(hwnd, &rcClient);
197
198         /* Create the buttons */            
199         advanced_checkbox =
200             CreateWindow( _T("BUTTON"), _T("Advanced options"),
201                         WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
202                         5, 10, 15, 15, hwnd, NULL, hInst, NULL );
203         SendMessage( advanced_checkbox, BM_SETCHECK, BST_UNCHECKED, 0 );
204
205         advanced_label = CreateWindow( _T("STATIC"), _T("Advanced options"),
206                         WS_CHILD | WS_VISIBLE | SS_LEFT,
207                         5 + 15 + 5, 10, 110, 15,
208                         hwnd, NULL, hInst, NULL);
209
210         if( config_GetInt( p_intf, "advanced" ) )
211         {
212             SendMessage( advanced_checkbox, BM_SETCHECK, BST_CHECKED, 0 );
213             /*dummy_event.SetInt(TRUE);
214               OnAdvanced( dummy_event );*/
215         }
216
217         reset_button = CreateWindow( _T("BUTTON"), _T("Reset All"),
218                         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
219                         rcClient.right - 5 - 80, 10 - 3, 80, 15 + 6,
220                         hwnd, NULL, hInst, NULL );
221
222         /* Create the preferences tree control */
223         prefs_tree = new PrefsTreeCtrl( p_intf, this, hwnd, hInst );
224
225         UpdateWindow( hwnd );
226         break;
227
228     case WM_CLOSE:
229         EndDialog( hwnd, LOWORD( wp ) );
230         break;
231
232     case WM_COMMAND:
233         if( LOWORD(wp) == IDOK )
234         {
235             OnOk();
236             EndDialog( hwnd, LOWORD( wp ) );
237         }
238         break;
239
240     case WM_NOTIFY:
241
242         if( lp && prefs_tree &&
243             ((LPNMHDR)lp)->hwndFrom == prefs_tree->hwndTV &&
244             ((LPNMHDR)lp)->code == TVN_SELCHANGED )
245         {
246             prefs_tree->OnSelectTreeItem( (NM_TREEVIEW FAR *)(LPNMHDR)lp,
247                                           hwnd, hInst );
248         }
249         break;
250
251     case WM_VSCROLL:
252     {
253         TVITEM tvi = {0};
254         tvi.mask = TVIF_PARAM;
255         tvi.hItem = TreeView_GetSelection( prefs_tree->hwndTV );
256         TreeView_GetItem( prefs_tree->hwndTV, &tvi );
257         ConfigTreeData *config_data =
258             prefs_tree->FindModuleConfig( (ConfigTreeData *)tvi.lParam );
259         if ( hwnd == config_data->panel->config_window ) 
260         {
261             int dy;
262             RECT rc;
263             GetWindowRect( hwnd, &rc);
264             int newvalue = config_data->panel->oldvalue;
265             switch ( GET_WM_VSCROLL_CODE(wp,lp) ) 
266             {
267             case SB_BOTTOM       : newvalue = 0; break;
268             case SB_TOP          : newvalue = config_data->panel->maxvalue; break;
269             case SB_LINEDOWN     : newvalue += 10; break;
270             case SB_PAGEDOWN     : newvalue += rc.bottom - rc.top - 25; break; // faux ! une page c'est la longueur réelle de notebook
271             case SB_LINEUP       : newvalue -= 10; break;
272             case SB_PAGEUP       : newvalue -= rc.bottom - rc.top - 25; break;
273             case SB_THUMBPOSITION:
274             case SB_THUMBTRACK   : newvalue = GET_WM_VSCROLL_POS(wp,lp); break;
275             }
276             newvalue = max(0,min(config_data->panel->maxvalue,newvalue));
277             SetScrollPos( hwnd,SB_VERT,newvalue,TRUE);//SB_CTL si hwnd=hwndScrollBar, SB_VERT si window
278             dy = config_data->panel->oldvalue - newvalue;
279
280             ScrollWindowEx( hwnd, 0, dy, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN );
281             UpdateWindow ( hwnd);
282
283             config_data->panel->oldvalue = newvalue;                                
284         }
285         break;
286     }
287
288     default:
289         break;
290     }
291
292     return FALSE;
293 }
294
295 /*****************************************************************************
296  * Private methods.
297  *****************************************************************************/
298
299 /*****************************************************************************
300  * Events methods.
301  *****************************************************************************/
302 void PrefsDialog::OnOk( void )
303 {
304     prefs_tree->ApplyChanges();
305     config_SaveConfigFile( p_intf, NULL );
306 }
307
308 /*****************************************************************************
309  * PrefsTreeCtrl class definition.
310  *****************************************************************************/
311 PrefsTreeCtrl::PrefsTreeCtrl( intf_thread_t *_p_intf,
312                               PrefsDialog *_p_prefs_dialog, HWND hwnd,
313                               HINSTANCE hInst )
314 {
315     vlc_list_t      *p_list;
316     module_t        *p_module;
317     module_config_t *p_item;
318     int i_index;
319
320     INITCOMMONCONTROLSEX iccex;
321     RECT rcClient;
322     TVITEM tvi = {0}; 
323     TVINSERTSTRUCT tvins = {0}; 
324     HTREEITEM hPrev;
325
326     size_t i_capability_count = 0;
327     size_t i_child_index;
328
329     HTREEITEM capability_item;
330
331     /* Initializations */
332     p_intf = _p_intf;
333     p_prefs_dialog = _p_prefs_dialog;
334     b_advanced = VLC_FALSE;
335
336     /* Create a tree view */
337     // Initialize the INITCOMMONCONTROLSEX structure.
338     iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
339     iccex.dwICC = ICC_TREEVIEW_CLASSES;
340
341     // Registers Statusbar control classes from the common control dll
342     InitCommonControlsEx( &iccex );
343
344     // Get the client area rect to put the tv in
345     GetClientRect(hwnd, &rcClient);
346
347     // Create the tree-view control.
348     hwndTV = CreateWindowEx( 0, WC_TREEVIEW, NULL,
349         WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES |
350         TVS_LINESATROOT | TVS_HASBUTTONS,
351         5, 10 + 2*(15 + 10) + 105 + 5, rcClient.right - 5 - 5, 6*15,
352         hwnd, NULL, hInst, NULL );
353
354     tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; 
355     tvi.pszText = _T("root");
356     tvi.cchTextMax = lstrlen(_T("root"));
357     tvi.lParam = (LPARAM) 1; // root level
358     tvins.item = tvi;
359     tvins.hInsertAfter = TVI_FIRST; 
360     tvins.hParent = TVI_ROOT; 
361
362     // Add the item to the tree-view control. 
363     hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins );
364     root_item = hPrev;
365
366     /* List the plugins */
367     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
368     if( !p_list ) return;
369
370     /*
371      * Build a tree of the main options
372      */
373     ConfigTreeData *config_data = new ConfigTreeData;
374     config_data->i_object_id = GENERAL_ID;
375     config_data->psz_help = strdup("nothing");//strdup( GENERAL_HELP );
376     config_data->psz_section = strdup( GENERAL_TITLE );
377     tvi.pszText = _T("General settings");
378     tvi.cchTextMax = lstrlen(_T("General settings"));
379     tvi.lParam = (long) config_data;
380     tvins.item = tvi;
381     tvins.hInsertAfter = hPrev;
382     tvins.hParent = root_item; //level 2
383
384     // Add the item to the tree-view control.
385     hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
386     general_item = hPrev;
387
388     for( i_index = 0; i_index < p_list->i_count; i_index++ )
389     {
390         p_module = (module_t *)p_list->p_values[i_index].p_object;
391         if( !strcmp( p_module->psz_object_name, "main" ) )
392             break;
393     }
394     if( i_index < p_list->i_count )
395     {
396         /* We found the main module */
397
398         /* Enumerate config categories and store a reference so we can
399          * generate their config panel them when it is asked by the user. */
400         p_item = p_module->p_config;
401
402         if( p_item ) do
403         {
404             switch( p_item->i_type )
405             {
406             case CONFIG_HINT_CATEGORY:
407                 ConfigTreeData *config_data = new ConfigTreeData;
408                 config_data->psz_section = strdup( p_item->psz_text );
409                 if( p_item->psz_longtext )
410                 {
411                     config_data->psz_help =
412                         strdup( p_item->psz_longtext );
413                 }
414                 else
415                 {
416                     config_data->psz_help = NULL;
417                 }
418                 config_data->i_object_id = p_module->i_object_id;
419
420                 /* Add the category to the tree */
421                 // Set the text of the item. 
422                 tvi.pszText = _FROMMB(p_item->psz_text); 
423                 tvi.cchTextMax = _tcslen(tvi.pszText);
424                 tvi.lParam = (long)config_data;
425                 tvins.item = tvi;
426                 tvins.hInsertAfter = hPrev; 
427                 tvins.hParent = general_item; //level 3
428     
429                 // Add the item to the tree-view control. 
430                 hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );
431
432                 break;
433             }
434         }
435         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
436
437         TreeView_SortChildren( hwndTV, general_item, 0 );
438     }
439         
440     /*
441      * Build a tree of all the plugins
442      */
443     config_data = new ConfigTreeData;
444     config_data->i_object_id = PLUGIN_ID;
445     config_data->psz_help = strdup("nothing");//strdup( PLUGIN_HELP );
446     config_data->psz_section = strdup("nothing");//strdup( PLUGIN_TITLE );
447     tvi.pszText = _T("Modules");
448     tvi.cchTextMax = lstrlen(_T("Modules"));
449     tvi.lParam = (long) config_data;
450     tvins.item = tvi;
451     tvins.hInsertAfter = hPrev;
452     tvins.hParent = root_item;// level 2
453
454     // Add the item to the tree-view control.
455     hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
456     plugins_item = hPrev;
457
458     i_capability_count = 0;
459     for( i_index = 0; i_index < p_list->i_count; i_index++ )
460     {
461         i_child_index = 0;
462
463         p_module = (module_t *)p_list->p_values[i_index].p_object;
464
465         /* Exclude the main module */
466         if( !strcmp( p_module->psz_object_name, "main" ) )
467             continue;
468
469         /* Exclude empty plugins (submodules don't have config options, they
470          * are stored in the parent module) */
471         if( p_module->b_submodule )
472             p_item = ((module_t *)p_module->p_parent)->p_config;
473         else
474             p_item = p_module->p_config;
475
476         if( !p_item ) continue;
477         do
478         {
479             if( p_item->i_type & CONFIG_ITEM )
480                 break;
481         }
482         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
483         if( p_item->i_type == CONFIG_HINT_END ) continue;
484
485         /* Find the capability child item */
486         /*long cookie; size_t i_child_index;*/
487         capability_item = TreeView_GetChild( hwndTV, plugins_item );
488         while( capability_item != 0 )
489         {
490             TVITEM capability_tvi = {0};
491             TCHAR psz_text[256];
492             i_child_index++;
493
494             capability_tvi.mask = TVIF_TEXT;
495             capability_tvi.pszText = psz_text;
496             capability_tvi.cchTextMax = 256;
497             capability_tvi.hItem = capability_item;
498             TreeView_GetItem( hwndTV, &capability_tvi );
499             if( !strcmp( _TOMB(capability_tvi.pszText),
500                          p_module->psz_capability ) ) break;
501  
502             capability_item =
503                 TreeView_GetNextSibling( hwndTV, capability_item );
504         }
505
506         if( i_child_index == i_capability_count &&
507             p_module->psz_capability && *p_module->psz_capability )
508         {
509             /* We didn't find it, add it */
510             ConfigTreeData *config_data = new ConfigTreeData;
511             config_data->psz_section =
512                 strdup( GetCapabilityHelp( p_module->psz_capability , 1 ) );
513             config_data->psz_help =
514                 strdup( GetCapabilityHelp( p_module->psz_capability , 2 ) );
515             config_data->i_object_id = CAPABILITY_ID;
516             tvi.pszText = _FROMMB(p_module->psz_capability);
517             tvi.cchTextMax = _tcslen(tvi.pszText);
518             tvi.lParam = (long) config_data;
519             tvins.item = tvi;
520             tvins.hInsertAfter = plugins_item; 
521             tvins.hParent = plugins_item;// level 3
522
523             // Add the item to the tree-view control. 
524             capability_item = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
525
526             i_capability_count++;
527         }
528
529         /* Add the plugin to the tree */
530         ConfigTreeData *config_data = new ConfigTreeData;
531         config_data->b_submodule = p_module->b_submodule;
532         config_data->i_object_id = p_module->b_submodule ?
533             ((module_t *)p_module->p_parent)->i_object_id :
534             p_module->i_object_id;
535         config_data->psz_help = NULL;
536         tvi.pszText = _FROMMB(p_module->psz_object_name);
537         tvi.cchTextMax = _tcslen(tvi.pszText);
538         tvi.lParam = (long) config_data;
539         tvins.item = tvi;
540         tvins.hInsertAfter = capability_item; 
541         tvins.hParent = capability_item;// level 4
542
543         // Add the item to the tree-view control. 
544         TreeView_InsertItem( hwndTV, &tvins );
545     }
546
547     /* Sort all this mess */
548     /*long cookie; size_t i_child_index;*/
549     TreeView_SortChildren( hwndTV, plugins_item, 0 );
550     capability_item = TreeView_GetChild( hwndTV, plugins_item );
551     while( capability_item != 0 )
552     {
553         TreeView_SortChildren( hwndTV, capability_item, 0 );
554         capability_item = TreeView_GetNextSibling( hwndTV, capability_item );
555     }
556
557     /* Clean-up everything */
558     vlc_list_release( p_list );
559
560     TreeView_Expand( hwndTV, root_item, TVE_EXPANDPARTIAL |TVE_EXPAND );
561     TreeView_Expand( hwndTV, general_item, TVE_EXPANDPARTIAL |TVE_EXPAND );
562 }
563
564 PrefsTreeCtrl::~PrefsTreeCtrl()
565 {
566 }
567
568 void PrefsTreeCtrl::ApplyChanges()
569 {
570     /*long cookie, cookie2;*/
571     ConfigTreeData *config_data;
572
573     /* Apply changes to the main module */
574     HTREEITEM item = TreeView_GetChild( hwndTV, general_item );
575     while( item != 0 )
576     {
577         TVITEM tvi = {0};
578         tvi.mask = TVIF_PARAM;
579         tvi.hItem = item;
580         TreeView_GetItem( hwndTV, &tvi );
581         config_data = (ConfigTreeData *)tvi.lParam;
582         if( config_data && config_data->panel )
583         {
584             config_data->panel->ApplyChanges();
585         }
586
587         item = TreeView_GetNextSibling( hwndTV, item );
588     }
589
590     /* Apply changes to the plugins */
591     item = TreeView_GetChild( hwndTV, plugins_item );
592     while( item != 0 )
593     {
594         HTREEITEM item2 = TreeView_GetChild( hwndTV, item );
595         while( item2 != 0 )
596         {       
597             TVITEM tvi = {0};
598             tvi.mask = TVIF_PARAM;
599             tvi.hItem = item2;
600             TreeView_GetItem( hwndTV, &tvi );
601             config_data = (ConfigTreeData *)tvi.lParam;
602             if( config_data && config_data->panel )
603             {
604                 config_data->panel->ApplyChanges();
605             }
606             item2 = TreeView_GetNextSibling( hwndTV, item2 );
607         }
608         item = TreeView_GetNextSibling( hwndTV, item );
609     }
610 }
611
612 ConfigTreeData *PrefsTreeCtrl::FindModuleConfig( ConfigTreeData *config_data )
613 {
614     /* We need this complexity because submodules don't have their own config
615      * options. They use the parent module ones. */
616
617     if( !config_data || !config_data->b_submodule )
618     {
619         return config_data;
620     }
621
622     /*long cookie, cookie2;*/
623     ConfigTreeData *config_new;
624     HTREEITEM item = TreeView_GetChild( hwndTV, plugins_item );
625     while( item != 0 )
626     {
627         HTREEITEM item2 = TreeView_GetChild( hwndTV, item );
628         while( item2 != 0 )
629         {       
630             TVITEM tvi = {0};
631             tvi.mask = TVIF_PARAM;
632             tvi.hItem = item2;
633             TreeView_GetItem( hwndTV, &tvi );
634             config_new = (ConfigTreeData *)tvi.lParam;
635             if( config_new && !config_new->b_submodule &&
636                 config_new->i_object_id == config_data->i_object_id )
637             {
638                 return config_new;
639             }
640             item2 = TreeView_GetNextSibling( hwndTV, item2 );
641         }
642         item = TreeView_GetNextSibling( hwndTV, item );
643     }
644
645     /* Found nothing */
646     return NULL;
647 }
648
649 void PrefsTreeCtrl::OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent,
650                                       HINSTANCE hInst )
651 {
652     ConfigTreeData *config_data = NULL;
653
654     if( pnmtv->itemOld.hItem )
655         config_data = FindModuleConfig( (ConfigTreeData *)pnmtv->itemOld.lParam );
656
657     if( config_data && config_data->panel )
658     {
659         config_data->panel->Hide();
660     }
661
662     /* Don't use event.GetItem() because we also send fake events */
663     TVITEM tvi = {0};
664     tvi.mask = TVIF_PARAM;
665     tvi.hItem = TreeView_GetSelection( hwndTV );
666     TreeView_GetItem( hwndTV, &tvi );
667     config_data = FindModuleConfig( (ConfigTreeData *)tvi.lParam );
668     if( config_data )
669     {
670         if( !config_data->panel )
671         {
672             /* The panel hasn't been created yet. Let's do it. */
673             config_data->panel =
674                 new PrefsPanel( parent, hInst, p_intf, p_prefs_dialog,
675                                 config_data->i_object_id,
676                                 config_data->psz_section,
677                                 config_data->psz_help );
678         }
679         else
680         {
681             config_data->panel->Show();
682         }
683     }
684 }
685
686 /*****************************************************************************
687  * PrefsPanel class definition.
688  *****************************************************************************/
689 PrefsPanel::PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
690                         PrefsDialog *_p_prefs_dialog,
691                         int i_object_id, char *psz_section, char *psz_help )
692 {
693     module_config_t *p_item;
694     module_t *p_module = NULL;
695
696     /* Initializations */
697     p_intf = _p_intf;
698     p_prefs_dialog = _p_prefs_dialog;
699
700     b_advanced = VLC_TRUE;
701
702     if( i_object_id == PLUGIN_ID || i_object_id == GENERAL_ID ||
703         i_object_id == CAPABILITY_ID )
704     {
705         label = CreateWindow( _T("STATIC"), _FROMMB(psz_section),
706                               WS_CHILD | WS_VISIBLE | SS_LEFT,
707                               5, 10 + (15 + 10), 200, 15,
708                               parent, NULL, hInst, NULL );
709         config_window = NULL;
710     }
711     else
712     {
713         /* Get a pointer to the module */
714         p_module = (module_t *)vlc_object_get( p_intf,  i_object_id );
715         if( p_module->i_object_type != VLC_OBJECT_MODULE )
716         {
717             /* 0OOoo something went really bad */
718             return;
719         }
720
721         /* Enumerate config options and add corresponding config boxes
722          * (submodules don't have config options, they are stored in the
723          *  parent module) */
724         if( p_module->b_submodule )
725             p_item = ((module_t *)p_module->p_parent)->p_config;
726         else
727             p_item = p_module->p_config;
728
729         /* Find the category if it has been specified */
730         if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY )
731         {
732             while( !p_item->i_type == CONFIG_HINT_CATEGORY ||
733                    strcmp( psz_section, p_item->psz_text ) )
734             {
735                 if( p_item->i_type == CONFIG_HINT_END )
736                     break;
737                 p_item++;
738             }
739         }
740
741         /* Add a head title to the panel */
742         label = CreateWindow( _T("STATIC"), _FROMMB(psz_section ?
743                         p_item->psz_text : p_module->psz_longname),
744                         WS_CHILD | WS_VISIBLE | SS_LEFT,
745                         5, 10 + (15 + 10), 250, 15,
746                         parent, NULL, hInst, NULL );
747
748         WNDCLASS wc;
749         memset( &wc, 0, sizeof(wc) );
750         wc.style          = CS_HREDRAW | CS_VREDRAW;
751         wc.lpfnWndProc    = (WNDPROC) _p_prefs_dialog->BaseWndProc;
752         wc.cbClsExtra     = 0;
753         wc.cbWndExtra     = 0;
754         wc.hInstance      = hInst;
755         wc.hIcon          = 0;
756         wc.hCursor        = 0;
757         wc.hbrBackground  = (HBRUSH) GetStockObject(WHITE_BRUSH);
758         wc.lpszMenuName   = 0;
759         wc.lpszClassName  = _T("PrefsPanelClass");
760         RegisterClass(&wc);
761
762         RECT rc;
763         GetWindowRect( parent, &rc);
764         config_window = CreateWindow( _T("PrefsPanelClass"),
765                         _T("config_window"),
766                         WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER,
767                         5, 10 + 2*(15 + 10), rc.right - 5 - 7, 105,
768                         parent, NULL, hInst, (void *) _p_prefs_dialog );
769
770         int y_pos = 5;
771         if( p_item ) do
772         {
773             /* If a category has been specified, check we finished the job */
774             if( psz_section && p_item->i_type == CONFIG_HINT_CATEGORY &&
775                 strcmp( psz_section, p_item->psz_text ) )
776                 break;
777
778             ConfigControl *control =
779                 CreateConfigControl( VLC_OBJECT(p_intf),
780                                      p_item, config_window,
781                                      hInst, &y_pos );
782
783             /* Don't add items that were not recognized */
784             if( control == NULL ) continue;
785
786             /* Add the config data to our array so we can keep a trace of it */
787             config_array.push_back( control );
788         }
789         while( p_item->i_type != CONFIG_HINT_END && p_item++ );
790                 
791         GetWindowRect( config_window, &rc);
792         maxvalue = y_pos - (rc.bottom - rc.top) + 5;
793         oldvalue = 0;
794         SetScrollRange( config_window, SB_VERT, 0, maxvalue, TRUE );
795     }
796 }
797
798 void PrefsPanel::Hide()
799 {
800     ShowWindow( label, SW_HIDE );
801     if( config_window ) ShowWindow( config_window, SW_HIDE );
802 }
803
804 void PrefsPanel::Show()
805 {
806     ShowWindow( label, SW_SHOW );
807     if( config_window ) ShowWindow( config_window, SW_SHOW );
808 }
809
810 void PrefsPanel::ApplyChanges()
811 {
812     vlc_value_t val;
813
814     for( size_t i = 0; i < config_array.size(); i++ )
815     {
816         ConfigControl *control = config_array[i];
817
818         switch( control->GetType() )
819         {
820         case CONFIG_ITEM_STRING:
821         case CONFIG_ITEM_FILE:
822         case CONFIG_ITEM_DIRECTORY:
823         case CONFIG_ITEM_MODULE:
824             config_PutPsz( p_intf, control->GetName(),
825                            control->GetPszValue() );
826             break;
827         case CONFIG_ITEM_KEY:
828             /* So you don't need to restart to have the changes take effect */
829             val.i_int = control->GetIntValue();
830             var_Set( p_intf->p_vlc, control->GetName(), val );
831         case CONFIG_ITEM_INTEGER:
832         case CONFIG_ITEM_BOOL:
833             config_PutInt( p_intf, control->GetName(),
834                            control->GetIntValue() );
835             break;
836         case CONFIG_ITEM_FLOAT:
837             config_PutFloat( p_intf, control->GetName(),
838                              control->GetFloatValue() );
839             break;
840         }
841     }
842 }