1 /*****************************************************************************
2 * PreferencesWindow.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 the VideoLAN team
7 * Authors: Eric Petit <titer@m0k.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
28 #include <vlc_interface.h>
30 #include <vlc_config_cat.h>
32 #include "PreferencesWindow.h"
34 #define TYPE_CATEGORY 0
35 #define TYPE_SUBCATEGORY 2
38 /*****************************************************************************
39 * PreferencesWindow::PreferencesWindow
40 *****************************************************************************/
41 PreferencesWindow::PreferencesWindow( intf_thread_t * _p_intf,
42 BRect frame, const char * name )
43 : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
51 SetSizeLimits( PREFS_WINDOW_WIDTH, 2000, PREFS_WINDOW_HEIGHT, 2000 );
53 /* The "background" view */
54 fPrefsView = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
55 fPrefsView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
56 AddChild( fPrefsView );
58 /* Create a scrollable outline view for the preferences tree */
60 rect.InsetBy( 10, 10 );
61 rect.right = rect.left + 150;
62 fOutline = new BOutlineListView( rect, "preferences tree",
63 B_SINGLE_SELECTION_LIST,
64 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM );
65 BScrollView * scrollview =
66 new BScrollView( "scrollview", fOutline,
67 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
69 fPrefsView->AddChild( scrollview );
71 /* We need to be informed if the user selects an item */
72 fOutline->SetSelectionMessage( new BMessage( PREFS_ITEM_SELECTED ) );
74 /* Create a dummy, empty view so we can correctly place the real
77 rect.left = rect.right + 15 + B_V_SCROLL_BAR_WIDTH;
78 rect.right = Bounds().right - 15;
79 fDummyView = new BView( rect, "", B_FOLLOW_ALL_SIDES, B_WILL_DRAW );
80 fDummyView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
81 fPrefsView->AddChild( fDummyView );
85 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
88 msg_Warn( p_intf, "couldn't find any module !" );
92 /* Find the main module */
93 module_t * p_module = NULL;
94 module_config_t * p_item = NULL;
95 for( int i = 0; i < p_list->i_count; i++ )
97 p_module = (module_t*) p_list->p_values[i].p_object;
99 if( !strcmp( p_module->psz_object_name, "main" ) &&
100 ( p_item = p_module->p_config ) )
106 ConfigItem * catItem = NULL, * subcatItem, * otherItem;
110 /* We found the main module, build the category tree */
111 for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
113 switch( p_item->i_type )
115 case CONFIG_CATEGORY:
116 catItem = new ConfigItem( p_intf,
117 config_CategoryNameGet( p_item->i_value ),
121 config_CategoryHelpGet( p_item->i_value ) );
122 fOutline->AddItem( catItem );
125 case CONFIG_SUBCATEGORY:
128 subcatItem = new ConfigItem( p_intf,
129 config_CategoryNameGet( p_item->i_value ),
133 config_CategoryHelpGet( p_item->i_value ) );
134 fOutline->AddUnder( subcatItem, catItem );
138 msg_Warn( p_intf, "subcategory without a category" );
145 /* Now parse all others modules */
147 int category, subcategory, options;
149 for( int i = 0; i < p_list->i_count; i++ )
155 p_module = (module_t*) p_list->p_values[i].p_object;
157 if( !strcmp( p_module->psz_object_name, "main" ) )
160 if( p_module->b_submodule ||
161 !( p_item = p_module->p_config ) )
164 for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
166 switch( p_item->i_type )
168 case CONFIG_CATEGORY:
169 category = p_item->i_value;
171 case CONFIG_SUBCATEGORY:
172 subcategory = p_item->i_value;
175 if( p_item->i_type & CONFIG_ITEM )
178 if( options > 0 && category >= 0 && subcategory >= 0 )
184 if( options < 1 || category < 0 || subcategory < 0 )
188 for( int j = 0; j < fOutline->CountItemsUnder( NULL, true ); j++ )
190 catItem = (ConfigItem*)
191 fOutline->ItemUnderAt( NULL, true, j );
192 if( catItem->ObjectId() == category )
202 for( int j = 0; j < fOutline->CountItemsUnder( catItem, true ); j++ )
204 subcatItem = (ConfigItem*)
205 fOutline->ItemUnderAt( catItem, true, j );
206 if( subcatItem->ObjectId() == subcategory )
213 subcatItem = catItem;
215 otherItem = new ConfigItem( p_intf,
216 p_module->psz_shortname ?
217 p_module->psz_shortname : p_module->psz_object_name,
218 p_module->b_submodule,
219 p_module->b_submodule ?
220 ((module_t *)p_module->p_parent)->i_object_id :
221 p_module->i_object_id,
224 fOutline->AddUnder( otherItem, subcatItem );
227 vlc_list_release( p_list );
229 /* Collapse the whole tree */
230 for( int i = 0; i < fOutline->FullListCountItems(); i++ )
232 otherItem = (ConfigItem *) fOutline->FullListItemAt( i );
233 fOutline->Collapse( otherItem );
236 /* Set the correct values */
239 /* Select the first item */
240 fOutline->Select( 0 );
242 /* Add the buttons */
245 rect.InsetBy( 10, 10 );
246 rect.left = rect.right - 80;
247 rect.top = rect.bottom - 25;
248 button = new BButton( rect, "", _("Apply"), new BMessage( PREFS_APPLY ),
249 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
250 button->MakeDefault( true );
251 fPrefsView->AddChild( button );
252 rect.OffsetBy( -90, 0 );
253 button = new BButton( rect, "", _("Save"), new BMessage( PREFS_SAVE ),
254 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
255 fPrefsView->AddChild( button );
256 rect.OffsetBy( -90, 0 );
257 button = new BButton( rect, "", _("Defaults"),
258 new BMessage( PREFS_DEFAULTS ),
259 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
260 fPrefsView->AddChild( button );
266 /*****************************************************************************
267 * PreferencesWindow::~PreferencesWindow
268 *****************************************************************************/
269 PreferencesWindow::~PreferencesWindow()
273 /*****************************************************************************
274 * PreferencesWindow::QuitRequested
275 *****************************************************************************/
276 bool PreferencesWindow::QuitRequested()
285 /*****************************************************************************
286 * PreferencesWindow::MessageReceived
287 *****************************************************************************/
288 void PreferencesWindow::MessageReceived( BMessage * message )
290 switch( message->what )
292 case PREFS_ITEM_SELECTED:
297 config_ResetAll( p_intf );
298 config_SaveConfigFile( p_intf, NULL );
308 config_SaveConfigFile( p_intf, NULL );
312 BWindow::MessageReceived( message );
316 /*****************************************************************************
317 * PreferencesWindow::FrameResized
318 *****************************************************************************/
319 void PreferencesWindow::FrameResized( float width, float height )
321 BWindow::FrameResized( width, height );
322 fCurrent->UpdateScrollBar();
325 /*****************************************************************************
326 * PreferencesWindow::Update
327 *****************************************************************************/
328 void PreferencesWindow::Update()
330 /* Get the selected item, if any */
331 if( fOutline->CurrentSelection() < 0 )
334 /* Detach the old box if any */
337 fCurrent->ResetScroll();
338 fDummyView->RemoveChild( fCurrent->Box() );
341 /* Add the new one... */
342 fCurrent = (ConfigItem *)
343 fOutline->ItemAt( fOutline->CurrentSelection() );
344 fDummyView->AddChild( fCurrent->Box() );
346 /* ...then resize it (we must resize it after it's attached or the
347 children don't get adjusted) */
348 fCurrent->Box()->ResizeTo( fDummyView->Bounds().Width(),
349 fDummyView->Bounds().Height() );
350 fCurrent->UpdateScrollBar();
353 /*****************************************************************************
354 * PreferencesWindow::Apply
355 * Apply changes if doIt is true, revert them otherwise
356 *****************************************************************************/
357 void PreferencesWindow::Apply( bool doIt )
361 for( int i = 0; i < fOutline->FullListCountItems(); i++ )
363 item = (ConfigItem*) fOutline->FullListItemAt( i );
368 /*****************************************************************************
369 * PreferencesWindow::ReallyQuit
370 *****************************************************************************/
371 void PreferencesWindow::ReallyQuit()
378 /***********************************************************************
379 * ConfigItem::ConfigItem
380 ***********************************************************************
382 **********************************************************************/
383 ConfigItem::ConfigItem( intf_thread_t * _p_intf, char * name,
384 bool subModule, int objectId,
385 int type, char * help )
386 : BStringItem( name )
389 fSubModule = subModule;
390 fObjectId = objectId;
392 fHelp = strdup( help );
395 r = BRect( 0, 0, 100, 100 );
396 fBox = new BBox( r, NULL, B_FOLLOW_ALL );
397 fBox->SetLabel( name );
403 if( fType == TYPE_CATEGORY )
405 /* Category: we just show the help text */
410 fTextView = new VTextView( r, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
411 fTextView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
412 fTextView->MakeEditable( false );
413 fTextView->MakeSelectable( false );
414 fTextView->Insert( fHelp );
415 fBox->AddChild( fTextView );
420 vlc_list_t * p_list = NULL;
421 module_t * p_module = NULL;
422 if( fType == TYPE_MODULE )
424 p_module = (module_t *) vlc_object_get( p_intf, fObjectId );
428 if( !( p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE,
433 for( int i = 0; i < p_list->i_count; i++ )
435 p_module = (module_t*) p_list->p_values[i].p_object;
437 if( !strcmp( p_module->psz_object_name, "main" ) )
444 if( !p_module || p_module->i_object_type != VLC_OBJECT_MODULE )
446 /* Shouldn't happen */
450 module_config_t * p_item;
451 p_item = fSubModule ? ((module_t *)p_module->p_parent)->p_config :
454 if( fType == TYPE_SUBCATEGORY )
456 for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
458 if( p_item->i_type == CONFIG_SUBCATEGORY &&
459 p_item->i_value == fObjectId )
467 r = BRect( 10,20,fBox->Bounds().right-B_V_SCROLL_BAR_WIDTH-10,
468 fBox->Bounds().bottom-10 );
469 fView = new BView( r, NULL, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
470 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE );
471 fView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
476 ConfigWidget * widget;
477 for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
479 if( ( p_item->i_type == CONFIG_CATEGORY ||
480 p_item->i_type == CONFIG_SUBCATEGORY ) &&
481 fType == TYPE_SUBCATEGORY &&
482 p_item->i_value != fObjectId )
487 widget = new ConfigWidget( p_intf, r, p_item );
488 if( !widget->InitCheck() )
493 fView->AddChild( widget );
494 r.top += widget->Bounds().Height();
497 if( fType == TYPE_MODULE )
499 vlc_object_release( p_module );
503 vlc_list_release( p_list );
506 /* Create a scroll view around our fView */
507 fScroll = new BScrollView( NULL, fView, B_FOLLOW_ALL, 0, false,
508 true, B_FANCY_BORDER );
509 fScroll->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
510 fBox->AddChild( fScroll );
512 /* Adjust fView's height to the size it actually needs (we do this
513 only now so the BScrollView fits the BBox) */
514 fView->ResizeTo( fView->Bounds().Width(), r.top + 10 );
517 /***********************************************************************
518 * ConfigItem::~ConfigItem
519 ***********************************************************************
521 **********************************************************************/
522 ConfigItem::~ConfigItem()
530 /*****************************************************************************
531 * ConfigItem::UpdateScrollBar
532 *****************************************************************************/
533 void ConfigItem::UpdateScrollBar()
535 /* We have to fix the scrollbar manually because it doesn't handle
536 correctly simple BViews */
543 /* Get the available BRect for display */
544 BRect display = fScroll->Bounds();
545 display.right -= B_V_SCROLL_BAR_WIDTH;
547 /* Fix the scrollbar */
548 BScrollBar * scrollBar;
549 BRect visible = display & fView->Bounds();
550 BRect total = display | fView->Bounds();
551 scrollBar = fScroll->ScrollBar( B_VERTICAL );
552 long max = (long)( fView->Bounds().Height() - visible.Height() );
553 if( max < 0 ) max = 0;
554 scrollBar->SetRange( 0, max );
555 scrollBar->SetProportion( visible.Height() / total.Height() );
556 scrollBar->SetSteps( 10, 100 );
558 /* We have to force redraw to avoid visual bugs when resizing
560 fScroll->Invalidate();
564 /*****************************************************************************
565 * ConfigItem::ResetScroll
566 *****************************************************************************/
567 void ConfigItem::ResetScroll()
574 fView->ScrollTo( 0, 0 );
577 /***********************************************************************
579 ***********************************************************************
581 **********************************************************************/
582 void ConfigItem::Apply( bool doIt )
589 /* Call ConfigWidget::Apply for every child of your fView */
590 ConfigWidget * widget;
591 for( int i = 0; i < fView->CountChildren(); i++ )
593 widget = (ConfigWidget*) fView->ChildAt( i );
594 widget->Apply( doIt );
598 /***********************************************************************
599 * ConfigWidget::ConfigWidget
600 ***********************************************************************
601 * Builds a view with the right controls for the given config variable.
602 * rect: the BRect where we place ourselves. All we care is its width
603 * and its top coordinate, since we adapt our height to take only
605 **********************************************************************/
606 ConfigWidget::ConfigWidget( intf_thread_t * _p_intf, BRect rect,
607 module_config_t * p_item )
608 : BView( rect, NULL, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
613 SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
616 BMenuItem * menuItem;
617 /* Skip deprecated options */
618 if( p_item->psz_current )
626 fType = p_item->i_type;
627 fName = strdup( p_item->psz_name );
631 case CONFIG_ITEM_MODULE:
632 case CONFIG_ITEM_MODULE_CAT:
633 case CONFIG_ITEM_MODULE_LIST_CAT:
634 case CONFIG_ITEM_STRING:
635 case CONFIG_ITEM_FILE:
636 case CONFIG_ITEM_DIRECTORY:
637 case CONFIG_ITEM_INTEGER:
638 case CONFIG_ITEM_FLOAT:
639 ResizeTo( Bounds().Width(), 25 );
640 fTextControl = new VTextControl( Bounds(), NULL,
641 p_item->psz_text, NULL, new BMessage(),
642 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
643 AddChild( fTextControl );
645 case CONFIG_ITEM_KEY:
646 ResizeTo( Bounds().Width(), 25 );
648 r.left = r.right - 100;
649 fPopUpMenu = new BPopUpMenu( "" );
650 fMenuField = new BMenuField( r, NULL, NULL, fPopUpMenu,
651 B_FOLLOW_RIGHT | B_FOLLOW_TOP );
653 i < sizeof( vlc_keys ) / sizeof( key_descriptor_t );
656 menuItem = new BMenuItem( vlc_keys[i].psz_key_string, NULL );
657 fPopUpMenu->AddItem( menuItem );
659 r.right = r.left - 10; r.left = r.left - 60;
660 fShiftCheck = new BCheckBox( r, NULL, "Shift",
661 new BMessage(), B_FOLLOW_RIGHT | B_FOLLOW_TOP );
662 r.right = r.left - 10; r.left = r.left - 60;
663 fCtrlCheck = new BCheckBox( r, NULL, "Ctrl",
664 new BMessage(), B_FOLLOW_RIGHT | B_FOLLOW_TOP );
665 r.right = r.left - 10; r.left = r.left - 60;
666 fAltCheck = new BCheckBox( r, NULL, "Alt",
667 new BMessage(), B_FOLLOW_RIGHT | B_FOLLOW_TOP );
668 r.right = r.left - 10; r.left = 0; r.bottom -= 10;
669 fStringView = new BStringView( r, NULL, p_item->psz_text,
670 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
671 AddChild( fStringView );
672 AddChild( fAltCheck );
673 AddChild( fCtrlCheck );
674 AddChild( fShiftCheck );
675 AddChild( fMenuField );
677 case CONFIG_ITEM_BOOL:
678 ResizeTo( Bounds().Width(), 25 );
679 fCheckBox = new BCheckBox( Bounds(), NULL, p_item->psz_text,
680 new BMessage(), B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
681 AddChild( fCheckBox );
691 ConfigWidget::~ConfigWidget()
696 /***********************************************************************
697 * ConfigWidget::Apply
698 ***********************************************************************
700 **********************************************************************/
701 void ConfigWidget::Apply( bool doIt )
703 BMenuItem * menuItem;
709 case CONFIG_ITEM_STRING:
710 case CONFIG_ITEM_FILE:
711 case CONFIG_ITEM_MODULE:
712 case CONFIG_ITEM_MODULE_CAT:
713 case CONFIG_ITEM_MODULE_LIST_CAT:
714 case CONFIG_ITEM_DIRECTORY:
717 config_PutPsz( p_intf, fName, fTextControl->Text() );
721 fTextControl->SetText( config_GetPsz( p_intf, fName ) );
725 case CONFIG_ITEM_INTEGER:
728 config_PutInt( p_intf, fName, atoi( fTextControl->Text() ) );
732 snprintf( string, 256, "%d", config_GetInt( p_intf, fName ) );
733 fTextControl->SetText( string );
737 case CONFIG_ITEM_FLOAT:
740 config_PutFloat( p_intf, fName, atof( fTextControl->Text() ) );
744 snprintf( string, 256, "%f", config_GetFloat( p_intf, fName ) );
745 fTextControl->SetText( string );
749 case CONFIG_ITEM_KEY:
752 menuItem = fPopUpMenu->FindMarked();
755 val.i_int = vlc_keys[fPopUpMenu->IndexOf( menuItem )].i_key_code;
756 if( fAltCheck->Value() )
758 val.i_int |= KEY_MODIFIER_ALT;
760 if( fCtrlCheck->Value() )
762 val.i_int |= KEY_MODIFIER_CTRL;
764 if( fShiftCheck->Value() )
766 val.i_int |= KEY_MODIFIER_SHIFT;
768 var_Set( p_intf->p_libvlc, fName, val );
773 val.i_int = config_GetInt( p_intf, fName );
774 fAltCheck->SetValue( val.i_int & KEY_MODIFIER_ALT );
775 fCtrlCheck->SetValue( val.i_int & KEY_MODIFIER_CTRL );
776 fShiftCheck->SetValue( val.i_int & KEY_MODIFIER_SHIFT );
779 i < sizeof( vlc_keys ) / sizeof( key_descriptor_t ); i++ )
781 if( (unsigned) vlc_keys[i].i_key_code ==
782 ( val.i_int & ~KEY_MODIFIER ) )
784 menuItem = fPopUpMenu->ItemAt( i );
785 menuItem->SetMarked( true );
792 case CONFIG_ITEM_BOOL:
795 config_PutInt( p_intf, fName, fCheckBox->Value() );
799 fCheckBox->SetValue( config_GetInt( p_intf, fName ) );
808 VTextView::VTextView( BRect frame, const char *name,
809 uint32 resizingMode, uint32 flags )
810 : BTextView( frame, name, BRect( 10,10,10,10 ), resizingMode, flags )
812 FrameResized( Bounds().Width(), Bounds().Height() );
815 void VTextView::FrameResized( float width, float height )
817 BTextView::FrameResized( width, height );
818 SetTextRect( BRect( 10,10, width-11, height-11 ) );
821 VTextControl::VTextControl( BRect frame, const char *name,
822 const char *label, const char *text,
823 BMessage * message, uint32 resizingMode )
824 : BTextControl( frame, name, label, text, message, resizingMode )
826 FrameResized( Bounds().Width(), Bounds().Height() );
829 void VTextControl::FrameResized( float width, float height )
831 BTextControl::FrameResized( width, height );
832 SetDivider( width / 2 );