]> git.sesse.net Git - vlc/blobdiff - modules/gui/beos/PreferencesWindow.cpp
Removes trailing spaces. Removes tabs.
[vlc] / modules / gui / beos / PreferencesWindow.cpp
index c9e0f04904a61061d5e4e1755164def8fceb3370..248741a40d579d1515337adc36034ed612f3c478 100644 (file)
@@ -1,10 +1,10 @@
 /*****************************************************************************
  * PreferencesWindow.cpp: beos interface
  *****************************************************************************
- * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: PreferencesWindow.cpp,v 1.14 2003/04/22 16:36:16 titer Exp $
+ * Copyright (C) 1999, 2000, 2001 the VideoLAN team
+ * $Id$
  *
- * Authors: Eric Petit <titer@videolan.org>
+ * Authors: Eric Petit <titer@m0k.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
-/* system headers */
-#include <malloc.h>
-#include <string.h>
 
-/* BeOS headers */
-#include <InterfaceKit.h>
-#include <Entry.h>
-#include <Path.h>
-#include <TranslatorRoster.h>
+#include <String.h>
 
-/* VLC headers */
 #include <vlc/vlc.h>
-#include <vlc/intf.h>
+#include <vlc_interface.h>
+#include <vlc_keys.h>
+#include <vlc_config_cat.h>
 
-/* BeOS module headers */
-#include "VlcWrapper.h"
-#include "MsgVals.h"
 #include "PreferencesWindow.h"
 
-static const char* kTranslatorField = "be:translator";
-static const char* kTypeField = "be:type";
-static const char* kDefaultScreenShotPath = "/boot/home/vlc screenshot";
-static const uint32 kDefaultScreenShotFormat = 'PNG ';
-
-// add_translator_items
-status_t
-add_translator_items( BMenu* intoMenu, uint32 fromType, uint32 command )
-{ 
-       BTranslatorRoster* roster = BTranslatorRoster::Default();
-       translator_id* ids = NULL;
-       int32 count = 0;
-       
-       status_t err = B_NO_INIT;
-       if ( roster )
-               err = roster->GetAllTranslators( &ids, &count );
-       if ( err < B_OK )
-               return err;
-       for ( int32 tix = 0; tix < count; tix++ )
-       { 
-               const translation_format* formats = NULL;
-               int32 num_formats = 0;
-               bool checkOutFormats = false; 
-               err = roster->GetInputFormats( ids[tix], &formats, &num_formats );
-               if ( err == B_OK )
-               {
-                       for ( int iix = 0; iix < num_formats; iix++ )
-                       {
-                               if ( formats[iix].type == fromType )
-                               { 
-                                       checkOutFormats = true;
-                                       break;
-                               }
-                       }
-               }
-               if ( !checkOutFormats )
-                       continue;
-               err = roster->GetOutputFormats(ids[tix], &formats, &num_formats);
-               if ( err == B_OK )
-               {
-                       for ( int32 oix = 0; oix < num_formats; oix++ )
-                       {
-                               if ( formats[oix].type != fromType )
-                               {
-                                       BMessage* message = new BMessage( command );
-                                       message->AddInt32( kTranslatorField, ids[tix] );
-                                       message->AddInt32( kTypeField, formats[oix].type );
-                                       intoMenu->AddItem( new BMenuItem( formats[oix].name, message ) );
-                               }
-                       }
-               } 
-       }
-       delete[] ids;
-       return B_OK; 
-}
-
-// get_config_string
-char*
-get_config_string( intf_thread_t* intf, const char* field, const char* defaultString )
-{
-       char* string = config_GetPsz( intf, field );
-       if ( !string )
-       {
-               string = strdup( defaultString );
-               config_PutPsz( intf, field, string );
-       }
-       return string;
-}
-
-// get_config_int
-int32
-get_config_int( intf_thread_t* intf, const char* field, int32 defaultValue )
-{
-       int32 value = config_GetInt( intf, field );
-       if ( value < 0 )
-       {
-               value = defaultValue;
-               config_PutInt( intf, field, value );
-       }
-       return value;
-}
-
-// get_config_float
-float
-get_config_float( intf_thread_t* intf, const char* field, float defaultValue )
-{
-       float value = config_GetFloat( intf, field );
-       if ( value < 0 )
-       {
-               value = defaultValue;
-               config_PutFloat( intf, field, value );
-       }
-       return value;
-}
-
-
-/*****************************************************************************
- * DirectoryTextControl class
- *****************************************************************************/
-class DirectoryTextControl : public BTextControl
-{
- public:
-       DirectoryTextControl( BRect frame, const char* name, 
-                                                 const char* label, const char* text,
-                                                 BMessage* message,
-                                                 uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,
-                                                 uint32 flags = B_WILL_DRAW | B_NAVIGABLE );
-       virtual                         ~DirectoryTextControl();
-
-       virtual void            MessageReceived(BMessage *msg);
-};
-
-DirectoryTextControl::DirectoryTextControl( BRect frame, const char* name, 
-                                                                                       const char* label, const char* text,
-                                                                                       BMessage* message,
-                                                                                       uint32 resizingMode, uint32 flags)
-       : BTextControl( frame, name, label, text, message, resizingMode, flags )
-{
-}
-
-DirectoryTextControl::~DirectoryTextControl()
-{
-}
-
-/*****************************************************************************
- * DirectoryTextControl::MessageReceived
- *****************************************************************************/
-void
-DirectoryTextControl::MessageReceived( BMessage* message )
-{
-       switch ( message->what )
-       {
-               case B_SIMPLE_DATA:
-               {
-                       entry_ref ref;
-                       if ( message->FindRef( "refs", &ref ) == B_OK ) {
-                               BString directory;
-                               BEntry entry;
-                               BPath path;
-                               if ( entry.SetTo( &ref, true ) == B_OK
-                                        && entry.IsDirectory()
-                                        && path.SetTo( &entry ) == B_OK )
-                               {
-                                       SetText( path.Path() );
-                               }
-                       }
-                       break;
-               }
-               default:
-                       BTextControl::MessageReceived( message );
-                       break;
-       }
-}
-
-
+#define TYPE_CATEGORY 0
+#define TYPE_SUBCATEGORY 2
+#define TYPE_MODULE 3
 
 /*****************************************************************************
- * Preferences::PreferencesWindow
+ * PreferencesWindow::PreferencesWindow
  *****************************************************************************/
-PreferencesWindow::PreferencesWindow( intf_thread_t * p_interface,
+PreferencesWindow::PreferencesWindow( intf_thread_t * _p_intf,
                                       BRect frame, const char * name )
     : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
-               B_NOT_ZOOMABLE | B_NOT_RESIZABLE ),
-         fDVDMenusBackup( false ),
-         fPostProcessingBackup( 0 ),
-         fBrightnessBackup( 100.0 ),
-         fContrastBackup( 100.0 ),
-         fHueBackup( 0 ),
-         fSaturationBackup( 100.0 ),
-         fScreenShotPathBackup( kDefaultScreenShotPath ),
-         fScreenShotFormatBackup( kDefaultScreenShotFormat ),
-         p_intf( p_interface )
+               B_NOT_ZOOMABLE )
 {
+    p_intf   = _p_intf;
+    fCurrent = NULL;
+
     BRect rect;
 
-    /* "background" view */
-    rgb_color background = ui_color( B_PANEL_BACKGROUND_COLOR );
+    SetSizeLimits( PREFS_WINDOW_WIDTH, 2000, PREFS_WINDOW_HEIGHT, 2000 );
+
+    /* The "background" view */
     fPrefsView = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
-    fPrefsView->SetViewColor( background );
+    fPrefsView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
     AddChild( fPrefsView );
 
-    /* add the tabs */
+    /* Create a scrollable outline view for the preferences tree */
     rect = Bounds();
-    rect.top += 10.0;
-    rect.bottom -= 45.0;
-    fTabView = new BTabView( rect, "preferences view" );
-    fTabView->SetViewColor( background );
-    
-    fGeneralView = new BView( fTabView->Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
-    fGeneralView->SetViewColor( background );
-    fAdjustView = new BView( fTabView->Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
-    fAdjustView->SetViewColor( background );
-    
-    fGeneralTab = new BTab();
-    fTabView->AddTab( fGeneralView, fGeneralTab );
-    fGeneralTab->SetLabel( _("General") );
-    
-    fAdjustTab = new BTab();
-    fTabView->AddTab( fAdjustView, fAdjustTab );
-    fAdjustTab->SetLabel( _("Picture") );
-    
-    /* fills the tabs */
-    /* general tab */
-    rect = fGeneralView->Bounds();
-    rect.InsetBy( 10, 10 );
-    rect.bottom = rect.top + 10;
-    fDvdMenusCheck = new BCheckBox( rect, "dvdmenus", _("Use DVD menus"),
-                                  new BMessage( DVDMENUS_CHECK ) );
-    fGeneralView->AddChild( fDvdMenusCheck );
-    
-    rect.top = rect.bottom + 20;
-    rect.bottom = rect.top + 30;
-    fPpSlider = new BSlider( rect, "post-processing", _("MPEG4 post-processing level"),
-                               new BMessage( FFMPEG_UPDATE ),
-                               0, 6, B_TRIANGLE_THUMB,
-                               B_FOLLOW_LEFT, B_WILL_DRAW ); 
-    fPpSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
-    fPpSlider->SetHashMarkCount( 7 );
-    fPpSlider->SetLimitLabels( _("None"), _("Maximum") );
-    fGeneralView->AddChild( fPpSlider );
-
-
-       rect.top = fPpSlider->Frame().bottom + 5.0;
-       rect.bottom = rect.top + 15.0;
-       fScreenShotPathTC = new DirectoryTextControl( rect, "screenshot path",
-                                                                                                 _("Screenshot Path:"),
-                                                                                                 fScreenShotPathBackup.String(),
-                                                                                                 new BMessage( SET_FOLDER ) );
-//     fScreenShotPathTC->ResizeToPreferred();
-
-       rect.top = fScreenShotPathTC->Frame().bottom + 5.0;
-       rect.bottom = rect.top + 15.0;  // TODO: this will be so tricky to get right!
-       BMenu* translatorMenu = new BMenu( "translators" );
-       add_translator_items( translatorMenu, B_TRANSLATOR_BITMAP, SET_TRANSLATOR );
-       fScreenShotFormatMF = new BMenuField( rect, "translators field",
-                                                                                 _("Screenshot Format:"), translatorMenu );
-       fScreenShotFormatMF->Menu()->SetRadioMode( true );
-       fScreenShotFormatMF->Menu()->SetLabelFromMarked( true );
-       // this will most likely not work for BMenuFields
-//     fScreenShotFormatMF->ResizeToPreferred();
-
-       fGeneralView->AddChild( fScreenShotPathTC );
-       fGeneralView->AddChild( fScreenShotFormatMF );
-
-       // make sure the controls labels are aligned nicely
-       float labelWidthM = fScreenShotFormatMF->StringWidth( fScreenShotFormatMF->Label() ) + 5.0;
-       float labelWidthP = fScreenShotPathTC->StringWidth( fScreenShotPathTC->Label() ) + 5.0;
-       if ( labelWidthM > labelWidthP )
-       {
-               fScreenShotPathTC->SetDivider( labelWidthM );
-               fScreenShotFormatMF->SetDivider( labelWidthM );
-       }
-       else
-       {
-               fScreenShotPathTC->SetDivider( labelWidthP );
-               fScreenShotFormatMF->SetDivider( labelWidthP );
-       }
-
-    /* restart message */
-    rect = fGeneralView->Bounds();
-    rect.bottom -= 40.0;
-    font_height fh;
-    be_plain_font->GetHeight( &fh );
-    rect.top = rect.bottom - ceilf( fh.ascent + fh.descent ) - 2.0;
-    fRestartString = new BStringView( rect, NULL,
-        _("DVD-menu and MPEG4 settings take effect after playback is restarted.") );
-    fRestartString->SetAlignment( B_ALIGN_CENTER );
-    fGeneralView->AddChild( fRestartString );
-
-    
-    /* adjust tab */
-    rect = fAdjustView->Bounds();
     rect.InsetBy( 10, 10 );
-    rect.bottom = rect.top + 30;
-    fBrightnessSlider = new BSlider( rect, "brightness", _("Brightness"),
-                                       new BMessage( ADJUST_UPDATE ),
-                                       0, 200, B_TRIANGLE_THUMB,
-                                       B_FOLLOW_LEFT, B_WILL_DRAW );
-    rect.OffsetBy( 0, 40 );
-    fContrastSlider = new BSlider( rect, "contrast", _("Contrast"),
-                                     new BMessage( ADJUST_UPDATE ),
-                                     0, 200, B_TRIANGLE_THUMB,
-                                     B_FOLLOW_LEFT, B_WILL_DRAW );
-    rect.OffsetBy( 0, 40 );
-    fHueSlider = new BSlider( rect, "hue", _("Hue"),
-                                new BMessage( ADJUST_UPDATE ),
-                                0, 360, B_TRIANGLE_THUMB,
-                                B_FOLLOW_LEFT, B_WILL_DRAW );
-    rect.OffsetBy( 0, 40 );
-    fSaturationSlider = new BSlider( rect, "saturation", _("Saturation"),
-                                       new BMessage( ADJUST_UPDATE ),
-                                       0, 200, B_TRIANGLE_THUMB,
-                                       B_FOLLOW_LEFT, B_WILL_DRAW );
-    fAdjustView->AddChild( fBrightnessSlider );
-    fAdjustView->AddChild( fContrastSlider );
-    fAdjustView->AddChild( fHueSlider );
-    fAdjustView->AddChild( fSaturationSlider );
-    
-    fPrefsView->AddChild( fTabView );
-
-    /* buttons */
-    BButton *button;
+    rect.right = rect.left + 150;
+    fOutline = new BOutlineListView( rect, "preferences tree",
+                                     B_SINGLE_SELECTION_LIST,
+                                     B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM );
+    BScrollView * scrollview =
+        new BScrollView( "scrollview", fOutline,
+                         B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
+                         0, false, true );
+    fPrefsView->AddChild( scrollview );
+
+    /* We need to be informed if the user selects an item */
+    fOutline->SetSelectionMessage( new BMessage( PREFS_ITEM_SELECTED ) );
+
+    /* Create a dummy, empty view so we can correctly place the real
+       config views later */
+    rect.bottom -= 40;
+    rect.left = rect.right + 15 + B_V_SCROLL_BAR_WIDTH;
+    rect.right = Bounds().right - 15;
+    fDummyView = new BView( rect, "", B_FOLLOW_ALL_SIDES, B_WILL_DRAW );
+    fDummyView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
+    fPrefsView->AddChild( fDummyView );
+
+    /* Fill the tree */
+    vlc_list_t * p_list;
+    p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+    if( !p_list )
+    {
+        msg_Warn( p_intf, "couldn't find any module !" );
+        return;
+    }
+
+    /* Find the main module */
+    module_t * p_module = NULL;
+    module_config_t * p_item = NULL;
+    for( int i = 0; i < p_list->i_count; i++ )
+    {
+        p_module = (module_t*) p_list->p_values[i].p_object;
+
+        if( !strcmp( p_module->psz_object_name, "main" ) &&
+            ( p_item = p_module->p_config ) )
+            break;
+        else
+            p_module = NULL;
+    }
+
+    ConfigItem * catItem = NULL, * subcatItem, * otherItem;
+
+    if( p_module )
+    {
+        /* We found the main module, build the category tree */
+        for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
+        {
+            switch( p_item->i_type )
+            {
+                case CONFIG_CATEGORY:
+                    catItem = new ConfigItem( p_intf,
+                        config_CategoryNameGet( p_item->i_value ),
+                        false,
+                        p_item->i_value,
+                        TYPE_CATEGORY,
+                        config_CategoryHelpGet( p_item->i_value ) );
+                    fOutline->AddItem( catItem );
+                    break;
+
+                case CONFIG_SUBCATEGORY:
+                    if( catItem )
+                    {
+                        subcatItem = new ConfigItem( p_intf,
+                            config_CategoryNameGet( p_item->i_value ),
+                            false,
+                            p_item->i_value,
+                            TYPE_SUBCATEGORY,
+                            config_CategoryHelpGet( p_item->i_value ) );
+                        fOutline->AddUnder( subcatItem, catItem );
+                    }
+                    else
+                    {
+                        msg_Warn( p_intf, "subcategory without a category" );
+                    }
+                    break;
+            }
+        }
+    }
+
+    /* Now parse all others modules */
+
+    int category, subcategory, options;
+
+    for( int i = 0; i < p_list->i_count; i++ )
+    {
+        category    = -1;
+        subcategory = -1;
+        options     = 0;
+
+        p_module = (module_t*) p_list->p_values[i].p_object;
+
+        if( !strcmp( p_module->psz_object_name, "main" ) )
+            continue;
+
+        if( p_module->b_submodule ||
+            !( p_item = p_module->p_config ) )
+            continue;
+
+        for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
+        {
+            switch( p_item->i_type )
+            {
+                case CONFIG_CATEGORY:
+                    category = p_item->i_value;
+                    break;
+                case CONFIG_SUBCATEGORY:
+                    subcategory = p_item->i_value;
+                    break;
+                default:
+                    if( p_item->i_type & CONFIG_ITEM )
+                        options++;
+            }
+            if( options > 0 && category >= 0 && subcategory >= 0 )
+            {
+                break;
+            }
+        }
+
+        if( options < 1 || category < 0 || subcategory < 0 )
+            continue;
+
+        catItem = NULL;
+        for( int j = 0; j < fOutline->CountItemsUnder( NULL, true ); j++ )
+        {
+            catItem = (ConfigItem*)
+                fOutline->ItemUnderAt( NULL, true, j );
+            if( catItem->ObjectId() == category )
+                break;
+            else
+                catItem = NULL;
+        }
+
+        if( !catItem )
+            continue;
+
+        subcatItem = NULL;
+        for( int j = 0; j < fOutline->CountItemsUnder( catItem, true ); j++ )
+        {
+            subcatItem = (ConfigItem*)
+                fOutline->ItemUnderAt( catItem, true, j );
+            if( subcatItem->ObjectId() == subcategory )
+                break;
+            else
+                subcatItem = NULL;
+        }
+
+        if( !subcatItem )
+            subcatItem = catItem;
+
+        otherItem = new ConfigItem( p_intf,
+            p_module->psz_shortname ?
+              p_module->psz_shortname : p_module->psz_object_name,
+            p_module->b_submodule,
+            p_module->b_submodule ?
+              ((module_t *)p_module->p_parent)->i_object_id :
+              p_module->i_object_id,
+            TYPE_MODULE,
+            NULL );
+        fOutline->AddUnder( otherItem, subcatItem );
+    }
+
+    vlc_list_release( p_list );
+
+    /* Collapse the whole tree */
+    for( int i = 0; i < fOutline->FullListCountItems(); i++ )
+    {
+        otherItem = (ConfigItem *) fOutline->FullListItemAt( i );
+        fOutline->Collapse( otherItem );
+    }
+
+    /* Set the correct values */
+    Apply( false );
+
+    /* Select the first item */
+    fOutline->Select( 0 );
+
+    /* Add the buttons */
+    BButton * button;
     rect = Bounds();
     rect.InsetBy( 10, 10 );
-    rect.top = rect.bottom - 25;
     rect.left = rect.right - 80;
-    button = new BButton( rect, NULL, _("OK"), new BMessage( PREFS_OK ) );
+    rect.top = rect.bottom - 25;
+    button = new BButton( rect, "", _("Apply"), new BMessage( PREFS_APPLY ),
+                          B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
+    button->MakeDefault( true );
     fPrefsView->AddChild( button );
-
-       SetDefaultButton( button );
-
     rect.OffsetBy( -90, 0 );
-    button = new BButton( rect, NULL, _("Cancel"), new BMessage( PREFS_CANCEL ) );
+    button = new BButton( rect, "", _("Save"), new BMessage( PREFS_SAVE ),
+                          B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
     fPrefsView->AddChild( button );
-
     rect.OffsetBy( -90, 0 );
-    button = new BButton( rect, NULL, _("Revert"), new BMessage( PREFS_REVERT ) );
+    button = new BButton( rect, "", _("Defaults"),
+                          new BMessage( PREFS_DEFAULTS ),
+                          B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
     fPrefsView->AddChild( button );
 
-       rect.left = Bounds().left + 10.0;
-       rect.right = rect.left + 80.0;
-    button = new BButton( rect, NULL, _("Defaults"), new BMessage( PREFS_DEFAULTS ) );
-    fPrefsView->AddChild( button );
-
-
-       // sync GUI to VLC 
-       _SetToSettings();
-
-    // start window thread in hidden state
     Hide();
     Show();
 }
@@ -383,81 +273,96 @@ PreferencesWindow::~PreferencesWindow()
 /*****************************************************************************
  * PreferencesWindow::QuitRequested
  *****************************************************************************/
-bool
-PreferencesWindow::QuitRequested()
+bool PreferencesWindow::QuitRequested()
 {
-       // work arround problem when window is closed or Ok pressed though
-       // the text control has focus (it will not have commited changes)
-       config_PutPsz( p_intf, "beos-screenshot-path", fScreenShotPathTC->Text() );
-       if ( !IsHidden() )
-               Hide();
-       return false;
+    if( !IsHidden() )
+    {
+        Hide();
+    }
+    return false;
 }
 
 /*****************************************************************************
  * PreferencesWindow::MessageReceived
  *****************************************************************************/
-void PreferencesWindow::MessageReceived( BMessage * p_message )
+void PreferencesWindow::MessageReceived( BMessage * message )
 {
-    switch ( p_message->what )
+    switchmessage->what )
     {
-       case SET_TRANSLATOR:
-       case SET_FOLDER:
-               _ApplyScreenShotSettings();
-               break;
-        case DVDMENUS_CHECK:
-               _ApplyDVDSettings();
-               break;
-        case ADJUST_UPDATE:
-               _ApplyPictureSettings();
-               break;
-        case FFMPEG_UPDATE:
-               _ApplyFFmpegSettings();
+        case PREFS_ITEM_SELECTED:
+            Update();
             break;
-        case PREFS_REVERT:
-               _RevertChanges();
-               break;
+
         case PREFS_DEFAULTS:
-            _SetDefaults();
-            _ApplyChanges();
+            config_ResetAll( p_intf );
+            config_SaveConfigFile( p_intf, NULL );
+            Apply( false );
             break;
-        case PREFS_CANCEL:
-               _RevertChanges();
-               // fall through
-        case PREFS_OK:
-            PostMessage( B_QUIT_REQUESTED );
+
+        case PREFS_APPLY:
+            Apply( true );
             break;
-        default:
-            BWindow::MessageReceived( p_message );
+
+        case PREFS_SAVE:
+            Apply( true );
+            config_SaveConfigFile( p_intf, NULL );
             break;
+
+        default:
+            BWindow::MessageReceived( message );
     }
 }
 
 /*****************************************************************************
- * PreferencesWindow::Show
+ * PreferencesWindow::FrameResized
  *****************************************************************************/
-void
-PreferencesWindow::Show()
+void PreferencesWindow::FrameResized( float width, float height )
 {
-       // collect settings for backup
-    fDVDMenusBackup = fDvdMenusCheck->Value() == B_CONTROL_ON;
-    fPostProcessingBackup = fPpSlider->Value();
-    fBrightnessBackup = fBrightnessSlider->Value();
-    fContrastBackup = fContrastSlider->Value();
-    fHueBackup = fHueSlider->Value();
-    fSaturationBackup = fSaturationSlider->Value();
-    fScreenShotPathBackup.SetTo( fScreenShotPathTC->Text() );
-       if ( BMenuItem* item = fScreenShotFormatMF->Menu()->FindMarked() )
-       {
-               BMessage* message = item->Message();
-               if ( message && message->FindInt32( kTypeField,
-                                                       (int32*)&fScreenShotFormatBackup ) != B_OK )
-                       fScreenShotFormatBackup = kDefaultScreenShotFormat;
-       }
-       else
-           fScreenShotFormatBackup = kDefaultScreenShotFormat;
-
-       BWindow::Show();
+    BWindow::FrameResized( width, height );
+    fCurrent->UpdateScrollBar();
+}
+
+/*****************************************************************************
+ * PreferencesWindow::Update
+ *****************************************************************************/
+void PreferencesWindow::Update()
+{
+    /* Get the selected item, if any */
+    if( fOutline->CurrentSelection() < 0 )
+        return;
+
+    /* Detach the old box if any */
+    if( fCurrent )
+    {
+        fCurrent->ResetScroll();
+        fDummyView->RemoveChild( fCurrent->Box() );
+    }
+
+    /* Add the new one... */
+    fCurrent = (ConfigItem *)
+        fOutline->ItemAt( fOutline->CurrentSelection() );
+    fDummyView->AddChild( fCurrent->Box() );
+
+    /* ...then resize it (we must resize it after it's attached or the
+       children don't get adjusted) */
+    fCurrent->Box()->ResizeTo( fDummyView->Bounds().Width(),
+                               fDummyView->Bounds().Height() );
+    fCurrent->UpdateScrollBar();
+}
+
+/*****************************************************************************
+ * PreferencesWindow::Apply
+ * Apply changes if doIt is true, revert them otherwise
+ *****************************************************************************/
+void PreferencesWindow::Apply( bool doIt )
+{
+    ConfigItem * item;
+
+    for( int i = 0; i < fOutline->FullListCountItems(); i++ )
+    {
+        item = (ConfigItem*) fOutline->FullListItemAt( i );
+        item->Apply( doIt );
+    }
 }
 
 /*****************************************************************************
@@ -470,184 +375,459 @@ void PreferencesWindow::ReallyQuit()
     Quit();
 }
 
-void
-PreferencesWindow::_SetGUI( bool dvdMenus, int32 postProcessing,
-                                                  float brightness, float contrast,
-                                                  int32 hue, float saturation,
-                                                  const char* screenShotPath,
-                                                  uint32 screenShotTranslator)
+/***********************************************************************
+ * ConfigItem::ConfigItem
+ ***********************************************************************
+ *
+ **********************************************************************/
+ConfigItem::ConfigItem( intf_thread_t * _p_intf, char * name,
+                        bool subModule, int objectId,
+                        int type, char * help )
+    : BStringItem( name )
 {
-       fDvdMenusCheck->SetValue( dvdMenus );
-       fPpSlider->SetValue( postProcessing );
-       fBrightnessSlider->SetValue( brightness );
-       fContrastSlider->SetValue( contrast );
-       fHueSlider->SetValue( hue );
-       fSaturationSlider->SetValue( saturation );
-       // mark appropriate translator item
-       bool found = false;
-       for ( int32 i = 0; BMenuItem* item = fScreenShotFormatMF->Menu()->ItemAt( i ); i++ )
-       {
-               if ( BMessage* message = item->Message() )
-               {
-                       uint32 format;
-                       if ( message->FindInt32( kTypeField, (int32*)&format ) == B_OK
-                                && format == screenShotTranslator )
-                       {
-                               item->SetMarked( true );
-                               found = true;
-                               break;
-                       }
-               }
-       }
-       if ( !found )
-       {
-               if ( BMenuItem* item = fScreenShotFormatMF->Menu()->ItemAt( 0 ) )
-                       item->SetMarked( true );
-       }
-       fScreenShotPathTC->SetText( screenShotPath );
-}
+    p_intf     = _p_intf;
+    fSubModule = subModule;
+    fObjectId  = objectId;
+    fType      = type;
+    fHelp      = strdup( help );
+
+    BRect r;
+    r = BRect( 0, 0, 100, 100 );
+    fBox = new BBox( r, NULL, B_FOLLOW_ALL );
+    fBox->SetLabel( name );
+
+    fTextView = NULL;
+    fScroll   = NULL;
+    fView     = NULL;
+
+    if( fType == TYPE_CATEGORY )
+    {
+        /* Category: we just show the help text */
+        r = fBox->Bounds();
+        r.InsetBy( 10, 10 );
+        r.top += 5;
+
+        fTextView = new VTextView( r, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
+        fTextView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
+        fTextView->MakeEditable( false );
+        fTextView->MakeSelectable( false );
+        fTextView->Insert( fHelp );
+        fBox->AddChild( fTextView );
+
+        return;
+    }
 
+    vlc_list_t * p_list = NULL;
+    module_t * p_module = NULL;
+    if( fType == TYPE_MODULE )
+    {
+        p_module = (module_t *) vlc_object_get( p_intf, fObjectId );
+    }
+    else
+    {
+        if( !( p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE,
+                                       FIND_ANYWHERE ) ) )
+        {
+            return;
+        }
+        for( int i = 0; i < p_list->i_count; i++ )
+        {
+            p_module = (module_t*) p_list->p_values[i].p_object;
 
-/*****************************************************************************
- * PreferencesWindow::_SetDefaults
- *****************************************************************************/
-void PreferencesWindow::_SetDefaults()
-{
-       _SetGUI( false, 0, 100.0, 100.0, 0, 100.0,
-                       kDefaultScreenShotPath, kDefaultScreenShotFormat );
+            if( !strcmp( p_module->psz_object_name, "main" ) )
+                break;
+            else
+                p_module = NULL;
+        }
+    }
+
+    if( !p_module || p_module->i_object_type != VLC_OBJECT_MODULE )
+    {
+        /* Shouldn't happen */
+        return;
+    }
+
+    module_config_t * p_item;
+    p_item = fSubModule ? ((module_t *)p_module->p_parent)->p_config :
+               p_module->p_config;
+
+    if( fType == TYPE_SUBCATEGORY )
+    {
+        for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
+        {
+            if( p_item->i_type == CONFIG_SUBCATEGORY &&
+                p_item->i_value == fObjectId )
+            {
+                break;
+            }
+        }
+    }
+
+    r = fBox->Bounds();
+    r = BRect( 10,20,fBox->Bounds().right-B_V_SCROLL_BAR_WIDTH-10,
+               fBox->Bounds().bottom-10 );
+    fView = new BView( r, NULL, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
+                       B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE );
+    fView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
+
+    r = fView->Bounds();
+    r.InsetBy( 10,10 );
+
+    ConfigWidget * widget;
+    for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
+    {
+        if( ( p_item->i_type == CONFIG_CATEGORY ||
+              p_item->i_type == CONFIG_SUBCATEGORY ) &&
+            fType == TYPE_SUBCATEGORY &&
+            p_item->i_value != fObjectId )
+        {
+            break;
+        }
+
+        widget = new ConfigWidget( p_intf, r, p_item );
+        if( !widget->InitCheck() )
+        {
+            delete widget;
+            continue;
+        }
+        fView->AddChild( widget );
+        r.top += widget->Bounds().Height();
+    }
+
+    if( fType == TYPE_MODULE )
+    {
+        vlc_object_release( p_module );
+    }
+    else
+    {
+        vlc_list_release( p_list );
+    }
+
+    /* Create a scroll view around our fView */
+    fScroll = new BScrollView( NULL, fView, B_FOLLOW_ALL, 0, false,
+                               true, B_FANCY_BORDER );
+    fScroll->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
+    fBox->AddChild( fScroll );
+
+    /* Adjust fView's height to the size it actually needs (we do this
+       only now so the BScrollView fits the BBox) */
+    fView->ResizeTo( fView->Bounds().Width(), r.top + 10 );
 }
 
-/*****************************************************************************
- * PreferencesWindow::_SetToSettings
- *****************************************************************************/
-void PreferencesWindow::_SetToSettings()
+/***********************************************************************
+ * ConfigItem::~ConfigItem
+ ***********************************************************************
+ *
+ **********************************************************************/
+ConfigItem::~ConfigItem()
 {
-       char* path = get_config_string( p_intf, "beos-screenshot-path", kDefaultScreenShotPath );
-
-       p_intf->p_sys->b_dvdmenus = get_config_int( p_intf, "beos-use-dvd-menus", false );
-
-       _SetGUI( p_intf->p_sys->b_dvdmenus,
-                       get_config_int( p_intf, "ffmpeg-pp-q", 0 ),
-                       100 *  get_config_float( p_intf, "brightness", 1.0 ),
-                       100 * get_config_float( p_intf, "contrast", 1.0 ),
-                       get_config_int( p_intf, "hue", 0 ),
-                       100 * get_config_float( p_intf, "saturation", 1.0 ),
-                       path,
-                       get_config_int( p_intf, "beos-screenshot-format",
-                                                       kDefaultScreenShotFormat ) );
-       free( path );
+    if( fHelp )
+    {
+        free( fHelp );
+    }
 }
 
 /*****************************************************************************
- * PreferencesWindow::_RevertChanges
+ * ConfigItem::UpdateScrollBar
  *****************************************************************************/
-void
-PreferencesWindow::_RevertChanges()
+void ConfigItem::UpdateScrollBar()
 {
-       _SetGUI( fDVDMenusBackup,
-                       fPostProcessingBackup,
-                       fBrightnessBackup,
-                       fContrastBackup,
-                       fHueBackup,
-                       fSaturationBackup,
-                       fScreenShotPathBackup.String(),
-                       fScreenShotFormatBackup );
-
-       _ApplyChanges();
+    /* We have to fix the scrollbar manually because it doesn't handle
+       correctly simple BViews */
+
+    if( !fScroll )
+    {
+        return;
+    }
+
+    /* Get the available BRect for display */
+    BRect display = fScroll->Bounds();
+    display.right -= B_V_SCROLL_BAR_WIDTH;
+
+    /* Fix the scrollbar */
+    BScrollBar * scrollBar;
+    BRect visible = display & fView->Bounds();
+    BRect total   = display | fView->Bounds();
+    scrollBar = fScroll->ScrollBar( B_VERTICAL );
+    long max = (long)( fView->Bounds().Height() - visible.Height() );
+    if( max < 0 ) max = 0;
+    scrollBar->SetRange( 0, max );
+    scrollBar->SetProportion( visible.Height() / total.Height() );
+    scrollBar->SetSteps( 10, 100 );
+
+    /* We have to force redraw to avoid visual bugs when resizing
+       (BeOS bug?) */
+    fScroll->Invalidate();
+    fView->Invalidate();
 }
 
 /*****************************************************************************
- * PreferencesWindow::_ApplyChanges
+ * ConfigItem::ResetScroll
  *****************************************************************************/
-void PreferencesWindow::_ApplyChanges()
+void ConfigItem::ResetScroll()
 {
-       _ApplyScreenShotSettings();
-       _ApplyPictureSettings();
-       _ApplyFFmpegSettings();
-       _ApplyDVDSettings();
+    if( !fScroll )
+    {
+        return;
+    }
+
+    fView->ScrollTo( 0, 0 );
 }
 
-/*****************************************************************************
- * PreferencesWindow::_ApplyScreenShotSettings
- *****************************************************************************/
-void
-PreferencesWindow::_ApplyScreenShotSettings()
+/***********************************************************************
+ * ConfigItem::Apply
+ ***********************************************************************
+ *
+ **********************************************************************/
+void ConfigItem::Apply( bool doIt )
 {
-       // screen shot settings
-       uint32 translator = kDefaultScreenShotFormat;
-       if ( BMenuItem* item = fScreenShotFormatMF->Menu()->FindMarked() )
-       {
-               BMessage* message = item->Message();
-               if ( message && message->FindInt32( kTypeField, (int32*)&translator ) != B_OK )
-                       translator = kDefaultScreenShotFormat;
-       }
-       config_PutInt( p_intf, "beos-screenshot-format", translator );
-       config_PutPsz( p_intf, "beos-screenshot-path", fScreenShotPathTC->Text() );
+    if( !fScroll )
+    {
+        return;
+    }
+
+    /* Call ConfigWidget::Apply for every child of your fView */
+    ConfigWidget * widget;
+    for( int i = 0; i < fView->CountChildren(); i++ )
+    {
+        widget = (ConfigWidget*) fView->ChildAt( i );
+        widget->Apply( doIt );
+    }
 }
 
-/*****************************************************************************
- * PreferencesWindow::_ApplyPictureSettings
- *****************************************************************************/
-void
-PreferencesWindow::_ApplyPictureSettings()
+/***********************************************************************
+ * ConfigWidget::ConfigWidget
+ ***********************************************************************
+ * Builds a view with the right controls for the given config variable.
+ *  rect: the BRect where we place ourselves. All we care is its width
+ *    and its top coordinate, since we adapt our height to take only
+ *    the place we need
+ **********************************************************************/
+ConfigWidget::ConfigWidget( intf_thread_t * _p_intf, BRect rect,
+                            module_config_t * p_item )
+    : BView( rect, NULL, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
+             B_WILL_DRAW )
 {
-       VlcWrapper* p_wrapper = p_intf->p_sys->p_wrapper;
-
-       // picture adjustment settings
-    config_PutFloat( p_intf, "brightness",
-                     (float)fBrightnessSlider->Value() / 100 );
-    config_PutFloat( p_intf, "contrast",
-                     (float)fContrastSlider->Value() / 100 );
-    config_PutInt( p_intf, "hue", fHueSlider->Value() );
-    config_PutFloat( p_intf, "saturation",
-                     (float)fSaturationSlider->Value() / 100 );
-
-       // take care of changing "filters on the fly"
-    if( config_GetFloat( p_intf, "brightness" ) != 1 ||
-        config_GetFloat( p_intf, "contrast" ) != 1 ||
-        config_GetInt( p_intf, "hue" ) != 0 ||
-        config_GetFloat( p_intf, "saturation" ) != 1 )
+    p_intf = _p_intf;
+
+    SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
+
+    BRect r;
+    BMenuItem * menuItem;
+    /* Skip deprecated options */
+    if( p_item->psz_current )
     {
-       char* string = config_GetPsz( p_intf, "filter" );
-        if( !string || strcmp( string, "adjust" ) )
-        {
-            config_PutPsz( p_intf, "filter", "adjust" );
-            p_wrapper->FilterChange();
-        }
-        if ( string )
-               free( string );
+        fInitOK = false;
+        return;
     }
-    else
+
+    fInitOK = true;
+
+    fType = p_item->i_type;
+    fName = strdup( p_item->psz_name );
+
+    switch( fType )
     {
-       char* string = config_GetPsz( p_intf, "filter" );
-        if ( string )
-        {
-            config_PutPsz( p_intf, "filter", NULL );
-            p_wrapper->FilterChange();
-               free( string );
-        }
+        case CONFIG_ITEM_MODULE:
+        case CONFIG_ITEM_MODULE_CAT:
+        case CONFIG_ITEM_MODULE_LIST_CAT:
+        case CONFIG_ITEM_STRING:
+        case CONFIG_ITEM_FILE:
+        case CONFIG_ITEM_DIRECTORY:
+        case CONFIG_ITEM_INTEGER:
+        case CONFIG_ITEM_FLOAT:
+            ResizeTo( Bounds().Width(), 25 );
+            fTextControl = new VTextControl( Bounds(), NULL,
+                p_item->psz_text, NULL, new BMessage(),
+                B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
+            AddChild( fTextControl );
+            break;
+        case CONFIG_ITEM_KEY:
+            ResizeTo( Bounds().Width(), 25 );
+            r = Bounds();
+            r.left = r.right - 100;
+            fPopUpMenu = new BPopUpMenu( "" );
+            fMenuField = new BMenuField( r, NULL, NULL, fPopUpMenu,
+                B_FOLLOW_RIGHT | B_FOLLOW_TOP );
+            for( unsigned i = 0;
+                 i < sizeof( vlc_keys ) / sizeof( key_descriptor_t );
+                 i++ )
+            {
+                menuItem = new BMenuItem( vlc_keys[i].psz_key_string, NULL );
+                fPopUpMenu->AddItem( menuItem );
+            }
+            r.right = r.left - 10; r.left = r.left - 60;
+            fShiftCheck = new BCheckBox( r, NULL, "Shift",
+                new BMessage(), B_FOLLOW_RIGHT | B_FOLLOW_TOP );
+            r.right = r.left - 10; r.left = r.left - 60;
+            fCtrlCheck = new BCheckBox( r, NULL, "Ctrl",
+                new BMessage(), B_FOLLOW_RIGHT | B_FOLLOW_TOP );
+            r.right = r.left - 10; r.left = r.left - 60;
+            fAltCheck = new BCheckBox( r, NULL, "Alt",
+                new BMessage(), B_FOLLOW_RIGHT | B_FOLLOW_TOP );
+            r.right = r.left - 10; r.left = 0; r.bottom -= 10;
+            fStringView = new BStringView( r, NULL, p_item->psz_text,
+                B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
+            AddChild( fStringView );
+            AddChild( fAltCheck );
+            AddChild( fCtrlCheck );
+            AddChild( fShiftCheck );
+            AddChild( fMenuField );
+            break;
+        case CONFIG_ITEM_BOOL:
+            ResizeTo( Bounds().Width(), 25 );
+            fCheckBox = new BCheckBox( Bounds(), NULL, p_item->psz_text,
+                new BMessage(), B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
+            AddChild( fCheckBox );
+            break;
+        case CONFIG_SECTION:
+            fInitOK = false;
+            break;
+        default:
+            fInitOK = false;
     }
 }
 
-/*****************************************************************************
- * PreferencesWindow::_ApplyFFmpegSettings
- *****************************************************************************/
-void
-PreferencesWindow::_ApplyFFmpegSettings()
+ConfigWidget::~ConfigWidget()
 {
-       // ffmpeg post processing
-    config_PutInt( p_intf, "ffmpeg-pp-q", fPpSlider->Value() );
+    free( fName );
 }
 
-/*****************************************************************************
- * PreferencesWindow::_ApplyDVDSettings
- *****************************************************************************/
-void
-PreferencesWindow::_ApplyDVDSettings()
+/***********************************************************************
+ * ConfigWidget::Apply
+ ***********************************************************************
+ *
+ **********************************************************************/
+void ConfigWidget::Apply( bool doIt )
 {
-       // dvd menus
-       bool dvdMenus = fDvdMenusCheck->Value() == B_CONTROL_ON;
-       p_intf->p_sys->b_dvdmenus = dvdMenus;
-       config_PutInt( p_intf, "beos-use-dvd-menus", dvdMenus );
+    BMenuItem * menuItem;
+    char string[256];
+    vlc_value_t val;
+
+    switch( fType )
+    {
+        case CONFIG_ITEM_STRING:
+        case CONFIG_ITEM_FILE:
+        case CONFIG_ITEM_MODULE:
+        case CONFIG_ITEM_MODULE_CAT:
+        case CONFIG_ITEM_MODULE_LIST_CAT:
+        case CONFIG_ITEM_DIRECTORY:
+            if( doIt )
+            {
+                config_PutPsz( p_intf, fName, fTextControl->Text() );
+            }
+            else
+            {
+                fTextControl->SetText( config_GetPsz( p_intf, fName ) );
+            }
+            break;
+
+        case CONFIG_ITEM_INTEGER:
+            if( doIt )
+            {
+                config_PutInt( p_intf, fName, atoi( fTextControl->Text() ) );
+            }
+            else
+            {
+                snprintf( string, 256, "%d", config_GetInt( p_intf, fName ) );
+                fTextControl->SetText( string );
+            }
+            break;
+
+        case CONFIG_ITEM_FLOAT:
+            if( doIt )
+            {
+                config_PutFloat( p_intf, fName, atof( fTextControl->Text() ) );
+            }
+            else
+            {
+                snprintf( string, 256, "%f", config_GetFloat( p_intf, fName ) );
+                fTextControl->SetText( string );
+            }
+            break;
+
+        case CONFIG_ITEM_KEY:
+            if( doIt )
+            {
+                menuItem = fPopUpMenu->FindMarked();
+                if( menuItem )
+                {
+                    val.i_int = vlc_keys[fPopUpMenu->IndexOf( menuItem )].i_key_code;
+                    if( fAltCheck->Value() )
+                    {
+                        val.i_int |= KEY_MODIFIER_ALT;
+                    }
+                    if( fCtrlCheck->Value() )
+                    {
+                        val.i_int |= KEY_MODIFIER_CTRL;
+                    }
+                    if( fShiftCheck->Value() )
+                    {
+                        val.i_int |= KEY_MODIFIER_SHIFT;
+                    }
+                    var_Set( p_intf->p_libvlc, fName, val );
+                }
+            }
+            else
+            {
+                val.i_int = config_GetInt( p_intf, fName );
+                fAltCheck->SetValue( val.i_int & KEY_MODIFIER_ALT );
+                fCtrlCheck->SetValue( val.i_int & KEY_MODIFIER_CTRL );
+                fShiftCheck->SetValue( val.i_int & KEY_MODIFIER_SHIFT );
+                for( unsigned i = 0;
+                     i < sizeof( vlc_keys ) / sizeof( key_descriptor_t ); i++ )
+                {
+                    if( (unsigned) vlc_keys[i].i_key_code ==
+                            ( val.i_int & ~KEY_MODIFIER ) )
+                    {
+                        menuItem = fPopUpMenu->ItemAt( i );
+                        menuItem->SetMarked( true );
+                        break;
+                    }
+                }
+            }
+            break;
+
+        case CONFIG_ITEM_BOOL:
+            if( doIt )
+            {
+                config_PutInt( p_intf, fName, fCheckBox->Value() );
+            }
+            else
+            {
+                fCheckBox->SetValue( config_GetInt( p_intf, fName ) );
+            }
+            break;
+
+        default:
+            break;
+    }
 }
 
+VTextView::VTextView( BRect frame, const char *name,
+                      uint32 resizingMode, uint32 flags )
+    : BTextView( frame, name, BRect( 10,10,10,10 ), resizingMode, flags )
+{
+    FrameResized( Bounds().Width(), Bounds().Height() );
+}
+
+void VTextView::FrameResized( float width, float height )
+{
+    BTextView::FrameResized( width, height );
+    SetTextRect( BRect( 10,10, width-11, height-11 ) );
+}
+
+VTextControl::VTextControl( BRect frame, const char *name,
+                            const char *label, const char *text,
+                            BMessage * message, uint32 resizingMode )
+    : BTextControl( frame, name, label, text, message, resizingMode )
+{
+    FrameResized( Bounds().Width(), Bounds().Height() );
+}
+
+void VTextControl::FrameResized( float width, float height )
+{
+    BTextControl::FrameResized( width, height );
+    SetDivider( width / 2 );
+}