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 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_interface.h>
34 #include <vlc_config_cat.h>
36 #include "PreferencesWindow.h"
38 #define TYPE_CATEGORY 0
39 #define TYPE_SUBCATEGORY 2
42 /*****************************************************************************
43 * PreferencesWindow::PreferencesWindow
44 *****************************************************************************/
45 PreferencesWindow::PreferencesWindow( intf_thread_t * _p_intf,
46 BRect frame, const char * name )
47 : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
55 SetSizeLimits( PREFS_WINDOW_WIDTH, 2000, PREFS_WINDOW_HEIGHT, 2000 );
57 /* The "background" view */
58 fPrefsView = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
59 fPrefsView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
60 AddChild( fPrefsView );
62 /* Create a scrollable outline view for the preferences tree */
64 rect.InsetBy( 10, 10 );
65 rect.right = rect.left + 150;
66 fOutline = new BOutlineListView( rect, "preferences tree",
67 B_SINGLE_SELECTION_LIST,
68 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM );
69 BScrollView * scrollview =
70 new BScrollView( "scrollview", fOutline,
71 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
73 fPrefsView->AddChild( scrollview );
75 /* We need to be informed if the user selects an item */
76 fOutline->SetSelectionMessage( new BMessage( PREFS_ITEM_SELECTED ) );
78 /* Create a dummy, empty view so we can correctly place the real
81 rect.left = rect.right + 15 + B_V_SCROLL_BAR_WIDTH;
82 rect.right = Bounds().right - 15;
83 fDummyView = new BView( rect, "", B_FOLLOW_ALL_SIDES, B_WILL_DRAW );
84 fDummyView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
85 fPrefsView->AddChild( fDummyView );
89 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
92 msg_Warn( p_intf, "couldn't find any module !" );
96 /* Find the main module */
97 module_t * p_module = NULL;
98 module_config_t * p_item = NULL;
99 for( int i = 0; i < p_list->i_count; i++ )
101 p_module = (module_t*) p_list->p_values[i].p_object;
103 if( !strcmp( p_module->psz_object_name, "main" ) &&
104 ( p_item = p_module->p_config ) )
110 ConfigItem * catItem = NULL, * subcatItem, * otherItem;
114 /* We found the main module, build the category tree */
115 for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
117 switch( p_item->i_type )
119 case CONFIG_CATEGORY:
120 catItem = new ConfigItem( p_intf,
121 config_CategoryNameGet( p_item->i_value ),
125 config_CategoryHelpGet( p_item->i_value ) );
126 fOutline->AddItem( catItem );
129 case CONFIG_SUBCATEGORY:
132 subcatItem = new ConfigItem( p_intf,
133 config_CategoryNameGet( p_item->i_value ),
137 config_CategoryHelpGet( p_item->i_value ) );
138 fOutline->AddUnder( subcatItem, catItem );
142 msg_Warn( p_intf, "subcategory without a category" );
149 /* Now parse all others modules */
151 int category, subcategory, options;
153 for( int i = 0; i < p_list->i_count; i++ )
159 p_module = (module_t*) p_list->p_values[i].p_object;
161 if( !strcmp( p_module->psz_object_name, "main" ) )
164 if( p_module->b_submodule ||
165 !( p_item = p_module->p_config ) )
168 for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
170 switch( p_item->i_type )
172 case CONFIG_CATEGORY:
173 category = p_item->i_value;
175 case CONFIG_SUBCATEGORY:
176 subcategory = p_item->i_value;
179 if( p_item->i_type & CONFIG_ITEM )
182 if( options > 0 && category >= 0 && subcategory >= 0 )
188 if( options < 1 || category < 0 || subcategory < 0 )
192 for( int j = 0; j < fOutline->CountItemsUnder( NULL, true ); j++ )
194 catItem = (ConfigItem*)
195 fOutline->ItemUnderAt( NULL, true, j );
196 if( catItem->ObjectId() == category )
206 for( int j = 0; j < fOutline->CountItemsUnder( catItem, true ); j++ )
208 subcatItem = (ConfigItem*)
209 fOutline->ItemUnderAt( catItem, true, j );
210 if( subcatItem->ObjectId() == subcategory )
217 subcatItem = catItem;
219 otherItem = new ConfigItem( p_intf,
220 p_module->psz_shortname ?
221 p_module->psz_shortname : p_module->psz_object_name,
222 p_module->b_submodule,
223 p_module->b_submodule ?
224 ((module_t *)p_module->p_parent)->i_object_id :
225 p_module->i_object_id,
228 fOutline->AddUnder( otherItem, subcatItem );
231 vlc_list_release( p_list );
233 /* Collapse the whole tree */
234 for( int i = 0; i < fOutline->FullListCountItems(); i++ )
236 otherItem = (ConfigItem *) fOutline->FullListItemAt( i );
237 fOutline->Collapse( otherItem );
240 /* Set the correct values */
243 /* Select the first item */
244 fOutline->Select( 0 );
246 /* Add the buttons */
249 rect.InsetBy( 10, 10 );
250 rect.left = rect.right - 80;
251 rect.top = rect.bottom - 25;
252 button = new BButton( rect, "", _("Apply"), new BMessage( PREFS_APPLY ),
253 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
254 button->MakeDefault( true );
255 fPrefsView->AddChild( button );
256 rect.OffsetBy( -90, 0 );
257 button = new BButton( rect, "", _("Save"), new BMessage( PREFS_SAVE ),
258 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
259 fPrefsView->AddChild( button );
260 rect.OffsetBy( -90, 0 );
261 button = new BButton( rect, "", _("Defaults"),
262 new BMessage( PREFS_DEFAULTS ),
263 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
264 fPrefsView->AddChild( button );
270 /*****************************************************************************
271 * PreferencesWindow::~PreferencesWindow
272 *****************************************************************************/
273 PreferencesWindow::~PreferencesWindow()
277 /*****************************************************************************
278 * PreferencesWindow::QuitRequested
279 *****************************************************************************/
280 bool PreferencesWindow::QuitRequested()
289 /*****************************************************************************
290 * PreferencesWindow::MessageReceived
291 *****************************************************************************/
292 void PreferencesWindow::MessageReceived( BMessage * message )
294 switch( message->what )
296 case PREFS_ITEM_SELECTED:
301 config_ResetAll( p_intf );
302 config_SaveConfigFile( p_intf, NULL );
312 config_SaveConfigFile( p_intf, NULL );
316 BWindow::MessageReceived( message );
320 /*****************************************************************************
321 * PreferencesWindow::FrameResized
322 *****************************************************************************/
323 void PreferencesWindow::FrameResized( float width, float height )
325 BWindow::FrameResized( width, height );
326 fCurrent->UpdateScrollBar();
329 /*****************************************************************************
330 * PreferencesWindow::Update
331 *****************************************************************************/
332 void PreferencesWindow::Update()
334 /* Get the selected item, if any */
335 if( fOutline->CurrentSelection() < 0 )
338 /* Detach the old box if any */
341 fCurrent->ResetScroll();
342 fDummyView->RemoveChild( fCurrent->Box() );
345 /* Add the new one... */
346 fCurrent = (ConfigItem *)
347 fOutline->ItemAt( fOutline->CurrentSelection() );
348 fDummyView->AddChild( fCurrent->Box() );
350 /* ...then resize it (we must resize it after it's attached or the
351 children don't get adjusted) */
352 fCurrent->Box()->ResizeTo( fDummyView->Bounds().Width(),
353 fDummyView->Bounds().Height() );
354 fCurrent->UpdateScrollBar();
357 /*****************************************************************************
358 * PreferencesWindow::Apply
359 * Apply changes if doIt is true, revert them otherwise
360 *****************************************************************************/
361 void PreferencesWindow::Apply( bool doIt )
365 for( int i = 0; i < fOutline->FullListCountItems(); i++ )
367 item = (ConfigItem*) fOutline->FullListItemAt( i );
372 /*****************************************************************************
373 * PreferencesWindow::ReallyQuit
374 *****************************************************************************/
375 void PreferencesWindow::ReallyQuit()
382 /***********************************************************************
383 * ConfigItem::ConfigItem
384 ***********************************************************************
386 **********************************************************************/
387 ConfigItem::ConfigItem( intf_thread_t * _p_intf, char * name,
388 bool subModule, int objectId,
389 int type, char * help )
390 : BStringItem( name )
393 fSubModule = subModule;
394 fObjectId = objectId;
396 fHelp = strdup( help );
399 r = BRect( 0, 0, 100, 100 );
400 fBox = new BBox( r, NULL, B_FOLLOW_ALL );
401 fBox->SetLabel( name );
407 if( fType == TYPE_CATEGORY )
409 /* Category: we just show the help text */
414 fTextView = new VTextView( r, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
415 fTextView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
416 fTextView->MakeEditable( false );
417 fTextView->MakeSelectable( false );
418 fTextView->Insert( fHelp );
419 fBox->AddChild( fTextView );
424 vlc_list_t * p_list = NULL;
425 module_t * p_module = NULL;
426 if( fType == TYPE_MODULE )
428 p_module = (module_t *) vlc_object_get( fObjectId );
432 if( !( p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE,
437 for( int i = 0; i < p_list->i_count; i++ )
439 p_module = (module_t*) p_list->p_values[i].p_object;
441 if( !strcmp( p_module->psz_object_name, "main" ) )
449 /* Shouldn't happen */
452 module_config_t * p_item;
453 p_item = fSubModule ? ((module_t *)p_module->p_parent)->p_config :
456 if( fType == TYPE_SUBCATEGORY )
458 for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
460 if( p_item->i_type == CONFIG_SUBCATEGORY &&
461 p_item->i_value == fObjectId )
469 r = BRect( 10,20,fBox->Bounds().right-B_V_SCROLL_BAR_WIDTH-10,
470 fBox->Bounds().bottom-10 );
471 fView = new BView( r, NULL, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
472 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE );
473 fView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
478 ConfigWidget * widget;
479 for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
481 if( ( p_item->i_type == CONFIG_CATEGORY ||
482 p_item->i_type == CONFIG_SUBCATEGORY ) &&
483 fType == TYPE_SUBCATEGORY &&
484 p_item->i_value != fObjectId )
489 widget = new ConfigWidget( p_intf, r, p_item );
490 if( !widget->InitCheck() )
495 fView->AddChild( widget );
496 r.top += widget->Bounds().Height();
499 if( fType == TYPE_MODULE )
501 vlc_object_release( p_module );
505 vlc_list_release( p_list );
508 /* Create a scroll view around our fView */
509 fScroll = new BScrollView( NULL, fView, B_FOLLOW_ALL, 0, false,
510 true, B_FANCY_BORDER );
511 fScroll->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
512 fBox->AddChild( fScroll );
514 /* Adjust fView's height to the size it actually needs (we do this
515 only now so the BScrollView fits the BBox) */
516 fView->ResizeTo( fView->Bounds().Width(), r.top + 10 );
519 /***********************************************************************
520 * ConfigItem::~ConfigItem
521 ***********************************************************************
523 **********************************************************************/
524 ConfigItem::~ConfigItem()
532 /*****************************************************************************
533 * ConfigItem::UpdateScrollBar
534 *****************************************************************************/
535 void ConfigItem::UpdateScrollBar()
537 /* We have to fix the scrollbar manually because it doesn't handle
538 correctly simple BViews */
545 /* Get the available BRect for display */
546 BRect display = fScroll->Bounds();
547 display.right -= B_V_SCROLL_BAR_WIDTH;
549 /* Fix the scrollbar */
550 BScrollBar * scrollBar;
551 BRect visible = display & fView->Bounds();
552 BRect total = display | fView->Bounds();
553 scrollBar = fScroll->ScrollBar( B_VERTICAL );
554 long max = (long)( fView->Bounds().Height() - visible.Height() );
555 if( max < 0 ) max = 0;
556 scrollBar->SetRange( 0, max );
557 scrollBar->SetProportion( visible.Height() / total.Height() );
558 scrollBar->SetSteps( 10, 100 );
560 /* We have to force redraw to avoid visual bugs when resizing
562 fScroll->Invalidate();
566 /*****************************************************************************
567 * ConfigItem::ResetScroll
568 *****************************************************************************/
569 void ConfigItem::ResetScroll()
576 fView->ScrollTo( 0, 0 );
579 /***********************************************************************
581 ***********************************************************************
583 **********************************************************************/
584 void ConfigItem::Apply( bool doIt )
591 /* Call ConfigWidget::Apply for every child of your fView */
592 ConfigWidget * widget;
593 for( int i = 0; i < fView->CountChildren(); i++ )
595 widget = (ConfigWidget*) fView->ChildAt( i );
596 widget->Apply( doIt );
600 /***********************************************************************
601 * ConfigWidget::ConfigWidget
602 ***********************************************************************
603 * Builds a view with the right controls for the given config variable.
604 * rect: the BRect where we place ourselves. All we care is its width
605 * and its top coordinate, since we adapt our height to take only
607 **********************************************************************/
608 ConfigWidget::ConfigWidget( intf_thread_t * _p_intf, BRect rect,
609 module_config_t * p_item )
610 : BView( rect, NULL, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
615 SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
618 BMenuItem * menuItem;
622 fType = p_item->i_type;
623 fName = strdup( p_item->psz_name );
627 case CONFIG_ITEM_MODULE:
628 case CONFIG_ITEM_MODULE_CAT:
629 case CONFIG_ITEM_MODULE_LIST_CAT:
630 case CONFIG_ITEM_STRING:
631 case CONFIG_ITEM_FILE:
632 case CONFIG_ITEM_DIRECTORY:
633 case CONFIG_ITEM_INTEGER:
634 case CONFIG_ITEM_FLOAT:
635 ResizeTo( Bounds().Width(), 25 );
636 fTextControl = new VTextControl( Bounds(), NULL,
637 p_item->psz_text, NULL, new BMessage(),
638 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
639 AddChild( fTextControl );
641 case CONFIG_ITEM_KEY:
642 ResizeTo( Bounds().Width(), 25 );
644 r.left = r.right - 100;
645 fPopUpMenu = new BPopUpMenu( "" );
646 fMenuField = new BMenuField( r, NULL, NULL, fPopUpMenu,
647 B_FOLLOW_RIGHT | B_FOLLOW_TOP );
649 i < sizeof( vlc_keys ) / sizeof( key_descriptor_t );
652 menuItem = new BMenuItem( vlc_keys[i].psz_key_string, NULL );
653 fPopUpMenu->AddItem( menuItem );
655 r.right = r.left - 10; r.left = r.left - 60;
656 fShiftCheck = new BCheckBox( r, NULL, "Shift",
657 new BMessage(), B_FOLLOW_RIGHT | B_FOLLOW_TOP );
658 r.right = r.left - 10; r.left = r.left - 60;
659 fCtrlCheck = new BCheckBox( r, NULL, "Ctrl",
660 new BMessage(), B_FOLLOW_RIGHT | B_FOLLOW_TOP );
661 r.right = r.left - 10; r.left = r.left - 60;
662 fAltCheck = new BCheckBox( r, NULL, "Alt",
663 new BMessage(), B_FOLLOW_RIGHT | B_FOLLOW_TOP );
664 r.right = r.left - 10; r.left = 0; r.bottom -= 10;
665 fStringView = new BStringView( r, NULL, p_item->psz_text,
666 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
667 AddChild( fStringView );
668 AddChild( fAltCheck );
669 AddChild( fCtrlCheck );
670 AddChild( fShiftCheck );
671 AddChild( fMenuField );
673 case CONFIG_ITEM_BOOL:
674 ResizeTo( Bounds().Width(), 25 );
675 fCheckBox = new BCheckBox( Bounds(), NULL, p_item->psz_text,
676 new BMessage(), B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
677 AddChild( fCheckBox );
687 ConfigWidget::~ConfigWidget()
692 /***********************************************************************
693 * ConfigWidget::Apply
694 ***********************************************************************
696 **********************************************************************/
697 void ConfigWidget::Apply( bool doIt )
699 BMenuItem * menuItem;
705 case CONFIG_ITEM_STRING:
706 case CONFIG_ITEM_FILE:
707 case CONFIG_ITEM_MODULE:
708 case CONFIG_ITEM_MODULE_CAT:
709 case CONFIG_ITEM_MODULE_LIST_CAT:
710 case CONFIG_ITEM_DIRECTORY:
713 config_PutPsz( p_intf, fName, fTextControl->Text() );
717 fTextControl->SetText( config_GetPsz( p_intf, fName ) );
721 case CONFIG_ITEM_INTEGER:
724 config_PutInt( p_intf, fName, atoi( fTextControl->Text() ) );
728 snprintf( string, 256, "%d", config_GetInt( p_intf, fName ) );
729 fTextControl->SetText( string );
733 case CONFIG_ITEM_FLOAT:
736 config_PutFloat( p_intf, fName, atof( fTextControl->Text() ) );
740 snprintf( string, 256, "%f", config_GetFloat( p_intf, fName ) );
741 fTextControl->SetText( string );
745 case CONFIG_ITEM_KEY:
748 menuItem = fPopUpMenu->FindMarked();
751 val.i_int = vlc_keys[fPopUpMenu->IndexOf( menuItem )].i_key_code;
752 if( fAltCheck->Value() )
754 val.i_int |= KEY_MODIFIER_ALT;
756 if( fCtrlCheck->Value() )
758 val.i_int |= KEY_MODIFIER_CTRL;
760 if( fShiftCheck->Value() )
762 val.i_int |= KEY_MODIFIER_SHIFT;
764 var_Set( p_intf->p_libvlc, fName, val );
769 val.i_int = config_GetInt( p_intf, fName );
770 fAltCheck->SetValue( val.i_int & KEY_MODIFIER_ALT );
771 fCtrlCheck->SetValue( val.i_int & KEY_MODIFIER_CTRL );
772 fShiftCheck->SetValue( val.i_int & KEY_MODIFIER_SHIFT );
775 i < sizeof( vlc_keys ) / sizeof( key_descriptor_t ); i++ )
777 if( (unsigned) vlc_keys[i].i_key_code ==
778 ( val.i_int & ~KEY_MODIFIER ) )
780 menuItem = fPopUpMenu->ItemAt( i );
781 menuItem->SetMarked( true );
788 case CONFIG_ITEM_BOOL:
791 config_PutInt( p_intf, fName, fCheckBox->Value() );
795 fCheckBox->SetValue( config_GetInt( p_intf, fName ) );
804 VTextView::VTextView( BRect frame, const char *name,
805 uint32 resizingMode, uint32 flags )
806 : BTextView( frame, name, BRect( 10,10,10,10 ), resizingMode, flags )
808 FrameResized( Bounds().Width(), Bounds().Height() );
811 void VTextView::FrameResized( float width, float height )
813 BTextView::FrameResized( width, height );
814 SetTextRect( BRect( 10,10, width-11, height-11 ) );
817 VTextControl::VTextControl( BRect frame, const char *name,
818 const char *label, const char *text,
819 BMessage * message, uint32 resizingMode )
820 : BTextControl( frame, name, label, text, message, resizingMode )
822 FrameResized( Bounds().Width(), Bounds().Height() );
825 void VTextControl::FrameResized( float width, float height )
827 BTextControl::FrameResized( width, height );
828 SetDivider( width / 2 );