preferences.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:30k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * preferences.cpp : WinCE gui plugin for VLC
  3.  *****************************************************************************
  4.  * Copyright (C) 2000-2004 the VideoLAN team
  5.  * $Id: 012dab91d425bdfa31f6cb59c79c471c917e780c $
  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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #ifdef HAVE_CONFIG_H
  28. # include "config.h"
  29. #endif
  30. #include <vlc_common.h>
  31. #include <vlc_interface.h>
  32. #include "wince.h"
  33. #include <winuser.h>
  34. #include <windows.h>
  35. #include <windowsx.h>
  36. #include <commctrl.h>
  37. #include <commdlg.h>
  38. #include <vlc_config_cat.h>
  39. #include "preferences_widgets.h"
  40. #define TYPE_CATEGORY 0
  41. #define TYPE_CATSUBCAT 1  /* Category with embedded subcategory */
  42. #define TYPE_SUBCATEGORY 2
  43. #define TYPE_MODULE 3
  44. /*****************************************************************************
  45.  * Event Table.
  46.  *****************************************************************************/
  47. /* IDs for the controls and the menu commands */
  48. enum
  49. {
  50.     Notebook_Event,
  51.     MRL_Event,
  52.     ResetAll_Event,
  53.     Advanced_Event
  54. };
  55. /*****************************************************************************
  56.  * Classes declarations.
  57.  *****************************************************************************/
  58. class ConfigTreeData;
  59. class PrefsTreeCtrl
  60. {
  61. public:
  62.     PrefsTreeCtrl() { }
  63.     PrefsTreeCtrl( intf_thread_t *_p_intf, PrefsDialog *p_prefs_dialog,
  64.                    HWND hwnd, HINSTANCE _hInst );
  65.     virtual ~PrefsTreeCtrl();
  66.     void ApplyChanges();
  67.     /*void CleanChanges();*/
  68.     void OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent, HINSTANCE hInst );
  69.  
  70.     ConfigTreeData *FindModuleConfig( ConfigTreeData *config_data );
  71.     HWND hwndTV;
  72. private:
  73.     intf_thread_t *p_intf;
  74.     PrefsDialog *p_prefs_dialog;
  75.     bool b_advanced;
  76.     HTREEITEM general_item;
  77.     HTREEITEM plugins_item;
  78. };
  79. class PrefsPanel
  80. {
  81. public:
  82.     PrefsPanel() { }
  83.     PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
  84.                 PrefsDialog *, module_t *p_module, char *, char *, ConfigTreeData * );
  85.     virtual ~PrefsPanel() {}
  86.     void Hide();
  87.     void Show();
  88.     HWND config_window;
  89.     int oldvalue;
  90.     int maxvalue;
  91.     void ApplyChanges();
  92. private:
  93.     intf_thread_t *p_intf;
  94.     PrefsDialog *p_prefs_dialog;
  95.     bool b_advanced;
  96.     HWND label;
  97.     vector<ConfigControl *> config_array;
  98. };
  99. class ConfigTreeData
  100. {
  101. public:
  102.     ConfigTreeData() { b_submodule = 0; panel = NULL; psz_name = NULL;
  103.                        psz_help = NULL; }
  104.     virtual ~ConfigTreeData() { delete panel;
  105.                                 free( psz_name );
  106.                                 free( psz_help ); }
  107.     bool b_submodule;
  108.     PrefsPanel *panel;
  109.     module_t *p_module;
  110.     int i_object_id;
  111.     int i_subcat_id;
  112.     int i_type;
  113.     char *psz_name;
  114.     char *psz_help;
  115. };
  116. /*****************************************************************************
  117.  * Constructor.
  118.  *****************************************************************************/
  119. PrefsDialog::PrefsDialog( intf_thread_t *p_intf, CBaseWindow *p_parent,
  120.                           HINSTANCE h_inst )
  121.   :  CBaseWindow( p_intf, p_parent, h_inst )
  122. {
  123.     /* Initializations */
  124.     prefs_tree = NULL;
  125. }
  126. /***********************************************************************
  127. FUNCTION:
  128.   WndProc
  129. PURPOSE:
  130.   Processes messages sent to the main window.
  131. ***********************************************************************/
  132. LRESULT PrefsDialog::WndProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp )
  133. {
  134.     SHINITDLGINFO shidi;
  135.     SHMENUBARINFO mbi;
  136.     RECT rcClient;
  137.     switch( msg )
  138.     {
  139.     case WM_INITDIALOG:
  140.         shidi.dwMask = SHIDIM_FLAGS;
  141.         shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN |
  142.             SHIDIF_FULLSCREENNOMENUBAR;//SHIDIF_SIZEDLGFULLSCREEN;
  143.         shidi.hDlg = hwnd;
  144.         SHInitDialog( &shidi );
  145.         //Create the menubar
  146.         memset( &mbi, 0, sizeof (SHMENUBARINFO) );
  147.         mbi.cbSize     = sizeof (SHMENUBARINFO);
  148.         mbi.hwndParent = hwnd;
  149.         mbi.dwFlags    = SHCMBF_EMPTYBAR;
  150.         mbi.hInstRes   = hInst;
  151.         if( !SHCreateMenuBar(&mbi) )
  152.         {
  153.             MessageBox(hwnd, _T("SHCreateMenuBar Failed"), _T("Error"), MB_OK);
  154.             //return -1;
  155.         }
  156.         hwndCB = mbi.hwndMB;
  157.         // Get the client area rect to put the panels in
  158.         GetClientRect(hwnd, &rcClient);
  159.         /* Create the buttons */
  160.         advanced_checkbox =
  161.             CreateWindow( _T("BUTTON"), _T("Advanced options"),
  162.                         WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
  163.                         5, 10, 15, 15, hwnd, NULL, hInst, NULL );
  164.         SendMessage( advanced_checkbox, BM_SETCHECK, BST_UNCHECKED, 0 );
  165.         advanced_label = CreateWindow( _T("STATIC"), _T("Advanced options"),
  166.                         WS_CHILD | WS_VISIBLE | SS_LEFT,
  167.                         5 + 15 + 5, 10, 110, 15,
  168.                         hwnd, NULL, hInst, NULL);
  169.         if( config_GetInt( p_intf, "advanced" ) )
  170.         {
  171.             SendMessage( advanced_checkbox, BM_SETCHECK, BST_CHECKED, 0 );
  172.             /*dummy_event.SetInt(TRUE);
  173.               OnAdvanced( dummy_event );*/
  174.         }
  175.         reset_button = CreateWindow( _T("BUTTON"), _T("Reset All"),
  176.                         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
  177.                         rcClient.right - 5 - 80, 10 - 3, 80, 15 + 6,
  178.                         hwnd, NULL, hInst, NULL );
  179.         /* Create the preferences tree control */
  180.         prefs_tree = new PrefsTreeCtrl( p_intf, this, hwnd, hInst );
  181.         UpdateWindow( hwnd );
  182.         break;
  183.     case WM_CLOSE:
  184.         EndDialog( hwnd, LOWORD( wp ) );
  185.         break;
  186.     case WM_SETFOCUS:
  187.         SHFullScreen( hwnd, SHFS_SHOWSIPBUTTON );
  188.         break;
  189.     case WM_COMMAND:
  190.         if( LOWORD(wp) == IDOK )
  191.         {
  192.             OnOk();
  193.             EndDialog( hwnd, LOWORD( wp ) );
  194.         }
  195.         break;
  196.     case WM_NOTIFY:
  197.         if( lp && prefs_tree &&
  198.             ((LPNMHDR)lp)->hwndFrom == prefs_tree->hwndTV &&
  199.             ((LPNMHDR)lp)->code == TVN_SELCHANGED )
  200.         {
  201.             prefs_tree->OnSelectTreeItem( (NM_TREEVIEW FAR *)(LPNMHDR)lp,
  202.                                           hwnd, hInst );
  203.         }
  204.         break;
  205.     case WM_VSCROLL:
  206.     {
  207.         TVITEM tvi = {0};
  208.         tvi.mask = TVIF_PARAM;
  209.         tvi.hItem = TreeView_GetSelection( prefs_tree->hwndTV );
  210.     if( !tvi.hItem ) break;
  211.         if( !TreeView_GetItem( prefs_tree->hwndTV, &tvi ) ) break;
  212.         ConfigTreeData *config_data =
  213.             prefs_tree->FindModuleConfig( (ConfigTreeData *)tvi.lParam );
  214.         if( config_data && hwnd == config_data->panel->config_window )
  215.         {
  216.             int dy;
  217.             RECT rc;
  218.             GetWindowRect( hwnd, &rc);
  219.             int newvalue = config_data->panel->oldvalue;
  220.             switch ( GET_WM_VSCROLL_CODE(wp,lp) )
  221.             {
  222.             case SB_BOTTOM       : newvalue = 0; break;
  223.             case SB_TOP          : newvalue = config_data->panel->maxvalue; break;
  224.             case SB_LINEDOWN     : newvalue += 10; break;
  225.             case SB_PAGEDOWN     : newvalue += rc.bottom - rc.top - 25; break; // wrong! one page is notebook actual length
  226.             case SB_LINEUP       : newvalue -= 10; break;
  227.             case SB_PAGEUP       : newvalue -= rc.bottom - rc.top - 25; break;
  228.             case SB_THUMBPOSITION:
  229.             case SB_THUMBTRACK   : newvalue = GET_WM_VSCROLL_POS(wp,lp); break;
  230.             }
  231.             newvalue = max(0,min(config_data->panel->maxvalue,newvalue));
  232.             SetScrollPos( hwnd,SB_VERT,newvalue,TRUE);//SB_CTL si hwnd=hwndScrollBar, SB_VERT si window
  233.             dy = config_data->panel->oldvalue - newvalue;
  234.             ScrollWindowEx( hwnd, 0, dy, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN );
  235.             UpdateWindow ( hwnd);
  236.             config_data->panel->oldvalue = newvalue;
  237.         }
  238.         break;
  239.     }
  240.     default:
  241.         break;
  242.     }
  243.     return FALSE;
  244. }
  245. /*****************************************************************************
  246.  * Private methods.
  247.  *****************************************************************************/
  248. /*****************************************************************************
  249.  * Events methods.
  250.  *****************************************************************************/
  251. void PrefsDialog::OnOk( void )
  252. {
  253.     prefs_tree->ApplyChanges();
  254.     config_SaveConfigFile( p_intf, NULL );
  255. }
  256. /*****************************************************************************
  257.  * PrefsTreeCtrl class definition.
  258.  *****************************************************************************/
  259. PrefsTreeCtrl::PrefsTreeCtrl( intf_thread_t *_p_intf,
  260.                               PrefsDialog *_p_prefs_dialog, HWND hwnd,
  261.                               HINSTANCE hInst )
  262. {
  263.     module_t        *p_module = NULL;
  264.     module_config_t *p_item;
  265.     INITCOMMONCONTROLSEX iccex;
  266.     RECT rcClient;
  267.     TVITEM tvi = {0};
  268.     TVINSERTSTRUCT tvins = {0};
  269.     HTREEITEM hPrev;
  270.     size_t i_capability_count = 0;
  271.     size_t i_child_index;
  272.     HTREEITEM category_item, subcategory_item;
  273.     /* Initializations */
  274.     p_intf = _p_intf;
  275.     p_prefs_dialog = _p_prefs_dialog;
  276.     b_advanced = false;
  277.     /* Create a tree view */
  278.     // Initialize the INITCOMMONCONTROLSEX structure.
  279.     iccex.dwSize = sizeof( INITCOMMONCONTROLSEX );
  280.     iccex.dwICC = ICC_TREEVIEW_CLASSES;
  281.     // Registers Statusbar control classes from the common control dll
  282.     InitCommonControlsEx( &iccex );
  283.     // Get the client area rect to put the tv in
  284.     GetClientRect(hwnd, &rcClient);
  285.     // Create the tree-view control.
  286.     hwndTV = CreateWindowEx( 0, WC_TREEVIEW, NULL,
  287.         WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES |
  288.         TVS_LINESATROOT | TVS_HASBUTTONS,
  289.         5, 10 + 2*(15 + 10) + 105 + 5, rcClient.right - 5 - 5, 6*15,
  290.         hwnd, NULL, hInst, NULL );
  291.     tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
  292.     /*
  293.      * Build a tree of the main options
  294.      */
  295.     ConfigTreeData *config_data = new ConfigTreeData;
  296.     config_data->i_object_id = TYPE_CATEGORY;
  297.     config_data->psz_help = strdup(MAIN_HELP);
  298.     config_data->psz_name = strdup( "General" );
  299.     tvi.pszText = _T("General settings");
  300.     tvi.cchTextMax = lstrlen(_T("General settings"));
  301.     tvi.lParam = (long)config_data;
  302.     tvins.item = tvi;
  303.     tvins.hInsertAfter = TVI_FIRST;
  304.     tvins.hParent = TVI_ROOT;
  305.     // Add the item to the tree-view control.
  306.     hPrev = (HTREEITEM) TreeView_InsertItem( hwndTV, &tvins);
  307.     general_item = hPrev;
  308.     /* Build the categories list */
  309.     p_module = module_get_main();
  310.     unsigned int confsize;
  311.     const char *psz_help;
  312.     module_config_t * p_config;
  313.     /* Enumerate config categories and store a reference so we can
  314.      * generate their config panel when it is asked by the user. */
  315.     p_config = module_config_get (p_module, &confsize);
  316.     for( size_t i = 0; i < confsize; i++ )
  317.     {
  318.     /* Work on a new item */
  319.         module_config_t *p_item = p_config + i;
  320.             switch( p_item->i_type )
  321.             {
  322.                 case CONFIG_CATEGORY:
  323.                     if( p_item->value.i == -1 )   break; // Don't display it
  324.                     config_data = new ConfigTreeData;
  325.                     config_data->psz_name = strdup( config_CategoryNameGet(p_item->value.i ) );
  326.                     psz_help = config_CategoryHelpGet( p_item->value.i );
  327.                     if( psz_help )
  328.                     {
  329.                         config_data->psz_help = strdup( psz_help );
  330.                     }
  331.                     else
  332.                     {
  333.                         config_data->psz_help = NULL;
  334.                     }
  335.                     config_data->i_type = TYPE_CATEGORY;
  336.                     config_data->i_object_id = p_item->value.i;
  337.                     config_data->p_module =  p_module;
  338.                     tvi.pszText = _FROMMB(config_data->psz_name);
  339.                     tvi.cchTextMax = _tcslen(tvi.pszText);
  340.                     /* Add the category to the tree */
  341.                     tvi.lParam = (long)config_data;
  342.                     tvins.item = tvi;
  343.                     tvins.hInsertAfter = hPrev;
  344.                     tvins.hParent = general_item; //level 3
  345.                     // Add the item to the tree-view control.
  346.                     hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );
  347.                     break;
  348.                 case CONFIG_SUBCATEGORY:
  349.                     if( p_item->value.i == -1 ) break; // Don't display it
  350.                     /* Special case: move the "general" subcategories to their parent category */
  351.                     if(config_data && p_item->value.i == SUBCAT_VIDEO_GENERAL ||
  352.                         p_item->value.i == SUBCAT_ADVANCED_MISC ||
  353.                         p_item->value.i == SUBCAT_INPUT_GENERAL ||
  354.                         p_item->value.i == SUBCAT_INTERFACE_GENERAL ||
  355.                         p_item->value.i == SUBCAT_SOUT_GENERAL||
  356.                         p_item->value.i == SUBCAT_PLAYLIST_GENERAL||
  357.                         p_item->value.i == SUBCAT_AUDIO_GENERAL )
  358.                     {
  359.                         config_data->i_type = TYPE_CATSUBCAT;
  360.                         config_data->i_subcat_id = p_item->value.i;
  361.                         free( config_data->psz_name );
  362.                         config_data->psz_name = strdup( config_CategoryNameGet( p_item->value.i ) );
  363.                         free( config_data->psz_help );
  364.                         const char *psz_help = config_CategoryHelpGet( p_item->value.i );
  365.                         if( psz_help )
  366.                         {
  367.                             config_data->psz_help = strdup( psz_help );
  368.                         }
  369.                         else
  370.                         {
  371.                             config_data->psz_help = NULL;
  372.                         }
  373.                         continue;
  374.                     }
  375.                     config_data = new ConfigTreeData;
  376.                     config_data->psz_name = strdup(  config_CategoryNameGet( p_item->value.i ) );
  377.                     psz_help = config_CategoryHelpGet( p_item->value.i );
  378.                     if( psz_help )
  379.                     {
  380.                         config_data->psz_help = strdup( psz_help );
  381.                     }
  382.                     else
  383.                     {
  384.                         config_data->psz_help = NULL;
  385.                     }
  386.                     config_data->i_type = TYPE_SUBCATEGORY;
  387.                     config_data->i_object_id = p_item->value.i;
  388.                     tvi.pszText = _FROMMB(config_data->psz_name);
  389.                     tvi.cchTextMax = _tcslen(tvi.pszText);
  390.                     tvi.lParam = (long)config_data;
  391.                     tvins.item = tvi;
  392.                     tvins.hInsertAfter = hPrev;
  393.                     tvins.hParent = hPrev;
  394.                     // Add the item to the tree-view control.
  395.                     TreeView_InsertItem( hwndTV, &tvins );
  396.                     break;
  397.             }
  398.         }
  399.     TreeView_SortChildren( hwndTV, general_item, 0 );
  400.     module_config_free( p_config );
  401.     /* List the plugins */
  402.     module_t **p_list = module_list_get( NULL );
  403.     /*
  404.     * Build a tree of all the plugins
  405.     */
  406.     for( size_t i_index = 0; p_list[i_index]; i_index++ )
  407.     {
  408.         /* Take every module */
  409.         p_module = p_list[i_index];
  410.         /* Exclude the main module */
  411.         if( module_is_main( p_module ) )
  412.             continue;
  413.         /* Exclude empty plugins (submodules don't have config options, they
  414.          * are stored in the parent module) */
  415.         unsigned int confsize;
  416.         i_child_index = 0;
  417.         int i_category = 0, i_subcategory = 0, i_options = 0;
  418.         bool b_options = false;
  419.         p_config = module_config_get( (module_t *) p_module,&confsize);
  420.         /* Loop through the configurations items */
  421.         for( size_t i = 0; i < confsize; i++ )
  422.         {
  423.             module_config_t *p_item = p_config + i;
  424.             if( p_item->i_type == CONFIG_CATEGORY )
  425.                 i_category = p_item->value.i;
  426.             else if( p_item->i_type == CONFIG_SUBCATEGORY )
  427.                 i_subcategory = p_item->value.i;
  428.             if( p_item->i_type & CONFIG_ITEM )
  429.                 b_options = true;
  430.             if( b_options && i_category && i_subcategory )
  431.                 break;
  432.         }
  433.         module_config_free (p_config);
  434.         /* Dummy item, please proceed */
  435.         if( !b_options || i_category == 0 || i_subcategory == 0 ) continue;
  436.         category_item = TreeView_GetChild( hwndTV, general_item );
  437.         while(category_item != 0)
  438.         {
  439.             TVITEM category_tvi = {0};
  440.             category_tvi.mask = TVIF_PARAM;
  441.             category_tvi.lParam = NULL;
  442.             category_tvi.hItem = category_item;
  443.             TreeView_GetItem( hwndTV, &category_tvi );
  444.             ConfigTreeData * data = (ConfigTreeData *)category_tvi.lParam;
  445.             if( data->i_object_id == i_category )
  446.             {
  447.                 subcategory_item = TreeView_GetChild( hwndTV, category_item );
  448.                 while(subcategory_item != 0)
  449.                 {
  450.                     TVITEM subcategory_tvi = {0};
  451.                     subcategory_tvi.mask = TVIF_PARAM;
  452.                     subcategory_tvi.lParam = NULL;
  453.                     subcategory_tvi.hItem = subcategory_item;
  454.                     TreeView_GetItem( hwndTV, &subcategory_tvi );
  455.                     ConfigTreeData * subdata = (ConfigTreeData *)subcategory_tvi.lParam;
  456.                     if( subdata->i_object_id == i_subcategory )
  457.                     {
  458.                         config_data = new ConfigTreeData;
  459.                         config_data->psz_name = strdup( module_get_object( p_module ) );
  460.                         config_data->psz_help = NULL;
  461.                         config_data->i_type = TYPE_MODULE;
  462.                         config_data->i_object_id = p_item->value.i;
  463.                         config_data->p_module = p_module;
  464.                         tvi.pszText = _FROMMB(module_get_name( p_module, false ));
  465.                         tvi.cchTextMax = _tcslen(tvi.pszText);
  466.                         tvi.lParam = (long)config_data;
  467.                         tvins.item = tvi;
  468.                         tvins.hInsertAfter = subcategory_item;
  469.                         tvins.hParent = subcategory_item;
  470.                 // Add the item to the tree-view control.
  471.                         hPrev = (HTREEITEM)TreeView_InsertItem( hwndTV, &tvins );
  472.                         break;
  473.                     }
  474.                     subcategory_item = TreeView_GetNextSibling( hwndTV, subcategory_item );
  475.                 }
  476.                 break;
  477.             }
  478.             category_item = TreeView_GetNextSibling( hwndTV, category_item );
  479.         }
  480.     }
  481.     /* Sort all this mess */
  482.     TreeView_SortChildren( hwndTV, general_item, 0 );
  483.     category_item = TreeView_GetChild( hwndTV, general_item );
  484.     while( category_item != 0 )
  485.     {
  486.         TreeView_SortChildren( hwndTV, category_item, 0 );
  487.         category_item = TreeView_GetNextSibling( hwndTV, category_item );
  488.     }
  489.     /* Clean-up everything */
  490.     module_list_free( p_list );
  491.     TreeView_Expand( hwndTV, general_item, TVE_EXPANDPARTIAL |TVE_EXPAND );
  492. }
  493. PrefsTreeCtrl::~PrefsTreeCtrl()
  494. {
  495. }
  496. void PrefsTreeCtrl::ApplyChanges()
  497. {
  498.     ConfigTreeData *config_data;
  499.     /* Apply changes to the main module */
  500.     HTREEITEM item = TreeView_GetChild( hwndTV, general_item );
  501.     while( item != 0 )
  502.     {
  503.         TVITEM tvi = {0};
  504.         tvi.mask = TVIF_PARAM;
  505.         tvi.hItem = item;
  506.         TreeView_GetItem( hwndTV, &tvi );
  507.         config_data = (ConfigTreeData *)tvi.lParam;
  508.         if( config_data && config_data->panel )
  509.         {
  510.             config_data->panel->ApplyChanges();
  511.         }
  512.         item = TreeView_GetNextSibling( hwndTV, item );
  513.     }
  514.     /* Apply changes to the plugins */
  515.     item = TreeView_GetChild( hwndTV, general_item );
  516.     while( item != 0 )
  517.     {
  518.         HTREEITEM item2 = TreeView_GetChild( hwndTV, item );
  519.         while( item2 != 0 )
  520.         {
  521.             HTREEITEM item3 = TreeView_GetChild( hwndTV, item2 );
  522.             while(item3 !=0)
  523.             {
  524.                 TVITEM tvi = {0};
  525.                 tvi.mask = TVIF_PARAM;
  526.                 tvi.hItem = item3;
  527.                 TreeView_GetItem( hwndTV, &tvi );
  528.                 config_data = (ConfigTreeData *)tvi.lParam;
  529.                 if( config_data && config_data->panel )
  530.                 {
  531.                     config_data->panel->ApplyChanges();
  532.                 }
  533.                 item3 = TreeView_GetNextSibling( hwndTV, item3 );
  534.             }
  535.             item2 = TreeView_GetNextSibling( hwndTV, item2 );
  536.         }
  537.         item = TreeView_GetNextSibling( hwndTV, item );
  538.     }
  539. }
  540. ConfigTreeData *PrefsTreeCtrl::FindModuleConfig( ConfigTreeData *config_data )
  541. {
  542.     if( !config_data || !config_data->p_module )
  543.     {
  544.         return config_data;
  545.     }
  546.     ConfigTreeData *config_new;
  547.     HTREEITEM item = TreeView_GetChild( hwndTV, general_item );
  548.     while( item != 0 )
  549.     {
  550.         HTREEITEM item2 = TreeView_GetChild( hwndTV, item );
  551.         while( item2 != 0 )
  552.         {
  553.             HTREEITEM item3 = TreeView_GetChild( hwndTV, item2 );
  554.             while( item3 != 0 )
  555.             {
  556.                 TVITEM tvi = {0};
  557.                 tvi.mask = TVIF_PARAM;
  558.                 tvi.hItem = item3;
  559.                 TreeView_GetItem( hwndTV, &tvi );
  560.                 config_new = (ConfigTreeData *)tvi.lParam;
  561.                 if( config_new && config_new->p_module == config_data->p_module )
  562.                 {
  563.                     return config_new;
  564.                 }
  565.                 item3 = TreeView_GetNextSibling( hwndTV, item3 );
  566.             }
  567.             item2 = TreeView_GetNextSibling( hwndTV, item2 );
  568.         }
  569.         item = TreeView_GetNextSibling( hwndTV, item );
  570.     }
  571.     /* Found nothing */
  572.     return NULL;
  573. }
  574. void PrefsTreeCtrl::OnSelectTreeItem( LPNM_TREEVIEW pnmtv, HWND parent,
  575.                                       HINSTANCE hInst )
  576. {
  577.     ConfigTreeData *config_data = NULL;
  578.     if( pnmtv->itemOld.hItem )
  579.         config_data = FindModuleConfig( (ConfigTreeData *)pnmtv->itemOld.lParam );
  580.     if( config_data && config_data->panel )
  581.     {
  582.         config_data->panel->Hide();
  583.     }
  584.     /* Don't use event.GetItem() because we also send fake events */
  585.     TVITEM tvi = {0};
  586.     tvi.mask = TVIF_PARAM;
  587.     tvi.hItem = TreeView_GetSelection( hwndTV );
  588.     TreeView_GetItem( hwndTV, &tvi );
  589.     config_data = FindModuleConfig( (ConfigTreeData *)tvi.lParam );
  590.     if( config_data )
  591.     {
  592.         if( !config_data->panel )
  593.         {
  594.             /* The panel hasn't been created yet. Let's do it. */
  595.             config_data->panel =
  596.                 new PrefsPanel( parent, hInst, p_intf, p_prefs_dialog,
  597.                                 config_data->p_module,
  598.                                 config_data->psz_name,
  599.                                 config_data->psz_help, config_data );
  600.         }
  601.         else
  602.         {
  603.             config_data->panel->Show();
  604.         }
  605.     }
  606. }
  607. /*****************************************************************************
  608.  * PrefsPanel class definition.
  609.  *****************************************************************************/
  610. PrefsPanel::PrefsPanel( HWND parent, HINSTANCE hInst, intf_thread_t *_p_intf,
  611.                         PrefsDialog *_p_prefs_dialog,
  612.                         module_t *p_module, char *psz_name, char *psz_help, ConfigTreeData * config_data )
  613. {
  614.     module_config_t *p_item, *p_config, *p_end;
  615.     /* Initializations */
  616.     p_intf = _p_intf;
  617.     p_prefs_dialog = _p_prefs_dialog;
  618.     module_t **p_list;
  619.     b_advanced = true;
  620.     if( config_data->i_type == TYPE_CATEGORY )
  621.     {
  622.         label = CreateWindow( _T("STATIC"), _FROMMB(psz_name),
  623.                               WS_CHILD | WS_VISIBLE | SS_LEFT,
  624.                               5, 10 + (15 + 10), 200, 15,
  625.                               parent, NULL, hInst, NULL );
  626.         config_window = NULL;
  627.     }
  628.     else
  629.     {
  630.         /* Get a pointer to the module */
  631.         if( config_data->i_type == TYPE_MODULE )
  632.         {
  633.             p_module = config_data->p_module;
  634.         }
  635.         else
  636.         {
  637.             /* List the plugins */
  638.             size_t i_index;
  639.             bool b_found = false;
  640.             p_list = module_list_get( NULL );
  641.             for( i_index = 0; p_list[i_index]; i_index++ )
  642.             {
  643.                 p_module = p_list[i_index];
  644.                 if( !strcmp( module_get_object(p_module), "main" ) )
  645.                 {
  646.                     b_found = true;
  647.                     break;
  648.                 }
  649.             }
  650.             if( !p_module && !b_found )
  651.             {
  652.                 msg_Warn( p_intf, "unable to create preferences "
  653.                         "(main module not found)" );
  654.                 return;
  655.             }
  656.         }
  657.         /* Enumerate config options and add corresponding config boxes
  658.          * (submodules don't have config options, they are stored in the
  659.          *  parent module) */
  660.         unsigned confsize;
  661.         p_config = module_config_get( (module_t *) p_module,&confsize);
  662.         p_item = p_config;
  663.         p_end = p_config + confsize;
  664.         /* Find the category if it has been specified */
  665.         if( config_data->i_type == TYPE_SUBCATEGORY ||
  666.             config_data->i_type == TYPE_CATSUBCAT )
  667.         {
  668.             for( ; p_item && p_item < p_end ; p_item++ )
  669.             {
  670.                 if( p_item->i_type == CONFIG_SUBCATEGORY &&
  671.                     ( config_data->i_type == TYPE_SUBCATEGORY &&
  672.                     p_item->value.i == config_data->i_object_id ) ||
  673.                     ( config_data->i_type == TYPE_CATSUBCAT &&
  674.                     p_item->value.i == config_data->i_subcat_id ) )
  675.                 {
  676.                     break;
  677.                 }
  678.             }
  679.         }
  680.         /* Add a head title to the panel */
  681.         const char *psz_head;
  682.         if( config_data->i_type == TYPE_SUBCATEGORY ||
  683.             config_data->i_type == TYPE_CATSUBCAT )
  684.         {
  685.             psz_head = config_data->psz_name;
  686.             p_item++;
  687.         }
  688.         else
  689.         {
  690.             psz_head = module_GetLongName(p_module);
  691.         }
  692.         label = CreateWindow( _T("STATIC"), _FROMMB(psz_head ?
  693.                 psz_head : _("Unknown")),
  694.                         WS_CHILD | WS_VISIBLE | SS_LEFT,
  695.                         5, 10 + (15 + 10), 250, 15,
  696.                                  parent, NULL, hInst, NULL );
  697.         WNDCLASS wc;
  698.         memset( &wc, 0, sizeof(wc) );
  699.         wc.style          = CS_HREDRAW | CS_VREDRAW;
  700.         wc.lpfnWndProc    = (WNDPROC) _p_prefs_dialog->BaseWndProc;
  701.         wc.cbClsExtra     = 0;
  702.         wc.cbWndExtra     = 0;
  703.         wc.hInstance      = hInst;
  704.         wc.hIcon          = 0;
  705.         wc.hCursor        = 0;
  706.         wc.hbrBackground  = (HBRUSH) GetStockObject(WHITE_BRUSH);
  707.         wc.lpszMenuName   = 0;
  708.         wc.lpszClassName  = _T("PrefsPanelClass");
  709.         RegisterClass(&wc);
  710.         RECT rc;
  711.         GetWindowRect( parent, &rc);
  712.         config_window = CreateWindow( _T("PrefsPanelClass"),
  713.                         _T("config_window"),
  714.                         WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER,
  715.                         5, 10 + 2*(15 + 10), rc.right - 5 - 7, 105,
  716.                         parent, NULL, hInst, (void *) _p_prefs_dialog );
  717.         int y_pos = 5;
  718.         for( ; p_item && p_item < p_end ; p_item++ )
  719.         {
  720.             /* If a category has been specified, check we finished the job */
  721.             if( ( ( config_data->i_type == TYPE_SUBCATEGORY &&
  722.                     p_item->value.i != config_data->i_object_id ) ||
  723.                     ( config_data->i_type == TYPE_CATSUBCAT  &&
  724.                     p_item->value.i != config_data->i_subcat_id ) ) &&
  725.                     (p_item->i_type == CONFIG_CATEGORY ||
  726.                     p_item->i_type == CONFIG_SUBCATEGORY ) )
  727.                 break;
  728.             ConfigControl *control = NULL;
  729.             control = CreateConfigControl( VLC_OBJECT(p_intf),
  730.                                      p_item, config_window,
  731.                                      hInst, &y_pos );
  732.             /* Don't add items that were not recognized */
  733.             if( control == NULL ) continue;
  734.             /* Add the config data to our array so we can keep a trace of it */
  735.             config_array.push_back( control );
  736.         }
  737.         GetWindowRect( config_window, &rc);
  738.         maxvalue = y_pos - (rc.bottom - rc.top) + 5;
  739.         oldvalue = 0;
  740.         SetScrollRange( config_window, SB_VERT, 0, maxvalue, TRUE );
  741.     }
  742. }
  743. void PrefsPanel::Hide()
  744. {
  745.     ShowWindow( label, SW_HIDE );
  746.     if( config_window ) ShowWindow( config_window, SW_HIDE );
  747. }
  748. void PrefsPanel::Show()
  749. {
  750.     ShowWindow( label, SW_SHOW );
  751.     if( config_window ) ShowWindow( config_window, SW_SHOW );
  752. }
  753. void PrefsPanel::ApplyChanges()
  754. {
  755.     vlc_value_t val;
  756.     for( size_t i = 0; i < config_array.size(); i++ )
  757.     {
  758.         ConfigControl *control = config_array[i];
  759.         switch( control->GetType() )
  760.         {
  761.         case CONFIG_ITEM_STRING:
  762.         case CONFIG_ITEM_FILE:
  763.         case CONFIG_ITEM_DIRECTORY:
  764.         case CONFIG_ITEM_MODULE:
  765.             config_PutPsz( p_intf, control->GetName(),
  766.                            control->GetPszValue() );
  767.             break;
  768.         case CONFIG_ITEM_KEY:
  769.             /* So you don't need to restart to have the changes take effect */
  770.             val.i_int = control->GetIntValue();
  771.             var_Set( p_intf->p_libvlc, control->GetName(), val );
  772.         case CONFIG_ITEM_INTEGER:
  773.         case CONFIG_ITEM_BOOL:
  774.             config_PutInt( p_intf, control->GetName(),
  775.                            control->GetIntValue() );
  776.             break;
  777.         case CONFIG_ITEM_FLOAT:
  778.             config_PutFloat( p_intf, control->GetName(),
  779.                              control->GetFloatValue() );
  780.             break;
  781.         }
  782.     }
  783. }