1 /*****************************************************************************
2 * PreferencesWindow.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 #include <stdlib.h> /* atoi(), strtod() */
31 #include <vlc_config_cat.h>
33 #include "PreferencesWindow.h"
35 #define TYPE_CATEGORY 0
36 #define TYPE_SUBCATEGORY 2
39 /*****************************************************************************
40 * PreferencesWindow::PreferencesWindow
41 *****************************************************************************/
42 PreferencesWindow::PreferencesWindow( intf_thread_t * p_interface,
43 BRect frame, const char * name )
44 : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
46 fConfigScroll( NULL ),
51 /* The "background" view */
52 fPrefsView = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
53 fPrefsView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
54 AddChild( fPrefsView );
56 /* Create a scrollable outline view for the preferences tree */
58 rect.InsetBy( 10, 10 );
59 rect.right = rect.left + 150;
60 fOutline = new BOutlineListView( rect, "preferences tree",
61 B_SINGLE_SELECTION_LIST,
62 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM );
63 BScrollView * scrollview =
64 new BScrollView( "scrollview", fOutline,
65 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
67 fPrefsView->AddChild( scrollview );
69 /* We need to be informed if the user selects an item */
70 fOutline->SetSelectionMessage( new BMessage( PREFS_ITEM_SELECTED ) );
72 /* Create a dummy, empty view so we can correctly place the real
75 rect.left = rect.right + 15 + B_V_SCROLL_BAR_WIDTH;
76 rect.right = Bounds().right - 15;
77 fDummyView = new BView( rect, "", B_FOLLOW_ALL_SIDES, B_WILL_DRAW );
78 fDummyView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
79 fPrefsView->AddChild( fDummyView );
83 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
86 msg_Warn( p_intf, "couldn't find any module !" );
90 /* Find the main module */
91 module_t * p_module = NULL;
92 module_config_t * p_item = NULL;
93 for( int i = 0; i < p_list->i_count; i++ )
95 p_module = (module_t*) p_list->p_values[i].p_object;
97 if( !strcmp( p_module->psz_object_name, "main" ) &&
98 ( p_item = p_module->p_config ) )
104 ConfigItem * catItem = NULL, * subcatItem, * otherItem;
108 /* We found the main module, build the category tree */
109 for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
111 switch( p_item->i_type )
113 case CONFIG_CATEGORY:
114 catItem = new ConfigItem( p_intf,
115 config_CategoryNameGet( p_item->i_value ),
119 config_CategoryHelpGet( p_item->i_value ) );
120 fOutline->AddItem( catItem );
123 case CONFIG_SUBCATEGORY:
126 subcatItem = new ConfigItem( p_intf,
127 config_CategoryNameGet( p_item->i_value ),
131 config_CategoryHelpGet( p_item->i_value ) );
132 fOutline->AddUnder( subcatItem, catItem );
136 msg_Warn( p_intf, "subcategory without a category" );
143 /* Now parse all others modules */
145 int category, subcategory, options;
147 for( int i = 0; i < p_list->i_count; i++ )
153 p_module = (module_t*) p_list->p_values[i].p_object;
155 if( !strcmp( p_module->psz_object_name, "main" ) )
158 if( p_module->b_submodule ||
159 !( p_item = p_module->p_config ) )
162 for( ; p_item->i_type != CONFIG_HINT_END; p_item++ )
164 switch( p_item->i_type )
166 case CONFIG_CATEGORY:
167 category = p_item->i_value;
169 case CONFIG_SUBCATEGORY:
170 subcategory = p_item->i_value;
173 if( p_item->i_type & CONFIG_ITEM )
176 if( options > 0 && category >= 0 && subcategory >= 0 )
182 if( options < 1 || category < 0 || subcategory < 0 )
185 fprintf( stderr, "cat %d, sub %d, %s\n", category, subcategory,
186 p_module->psz_shortname ? p_module->psz_shortname :
187 p_module->psz_object_name );
190 for( int j = 0; j < fOutline->CountItemsUnder( NULL, true ); j++ )
192 catItem = (ConfigItem*)
193 fOutline->ItemUnderAt( NULL, true, j );
194 if( catItem->ObjectId() == category )
204 for( int j = 0; j < fOutline->CountItemsUnder( catItem, true ); j++ )
206 subcatItem = (ConfigItem*)
207 fOutline->ItemUnderAt( catItem, true, j );
208 if( subcatItem->ObjectId() == subcategory )
215 subcatItem = catItem;
217 otherItem = new ConfigItem( p_intf,
218 p_module->psz_shortname ?
219 p_module->psz_shortname : p_module->psz_object_name,
220 p_module->b_submodule,
221 p_module->b_submodule ?
222 ((module_t *)p_module->p_parent)->i_object_id :
223 p_module->i_object_id,
226 fOutline->AddUnder( otherItem, subcatItem );
229 vlc_list_release( p_list );
231 for( int i = 0; i < fOutline->FullListCountItems(); i++ )
233 otherItem = (ConfigItem *)
234 fOutline->FullListItemAt( i );
235 if( fOutline->Superitem( otherItem ) )
237 fOutline->Collapse( otherItem );
241 /* Set the correct values */
242 ApplyChanges( false );
244 /* Select the first item */
245 fOutline->Select( 0 );
247 /* Add the buttons */
250 rect.InsetBy( 10, 10 );
251 rect.left = rect.right - 80;
252 rect.top = rect.bottom - 25;
253 button = new BButton( rect, "", _("Apply"), new BMessage( PREFS_APPLY ),
254 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
255 button->MakeDefault( true );
256 fPrefsView->AddChild( button );
257 rect.OffsetBy( -90, 0 );
258 button = new BButton( rect, "", _("Save"), new BMessage( PREFS_SAVE ),
259 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
260 fPrefsView->AddChild( button );
261 rect.OffsetBy( -90, 0 );
262 button = new BButton( rect, "", _("Defaults"),
263 new BMessage( PREFS_DEFAULTS ),
264 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
265 fPrefsView->AddChild( button );
271 /*****************************************************************************
272 * PreferencesWindow::~PreferencesWindow
273 *****************************************************************************/
274 PreferencesWindow::~PreferencesWindow()
278 /*****************************************************************************
279 * PreferencesWindow::QuitRequested
280 *****************************************************************************/
281 bool PreferencesWindow::QuitRequested()
290 /*****************************************************************************
291 * PreferencesWindow::MessageReceived
292 *****************************************************************************/
293 void PreferencesWindow::MessageReceived( BMessage * message )
295 switch( message->what )
297 case PREFS_ITEM_SELECTED:
302 config_ResetAll( p_intf );
303 ApplyChanges( false );
307 ApplyChanges( true );
315 BWindow::MessageReceived( message );
319 /*****************************************************************************
320 * PreferencesWindow::FrameResized
321 *****************************************************************************/
322 void PreferencesWindow::FrameResized( float width, float height )
324 BWindow::FrameResized( width, height );
329 /*****************************************************************************
330 * PreferencesWindow::Update
331 *****************************************************************************/
332 void PreferencesWindow::Update()
334 /* Get the selected item, if any */
335 if( fOutline->CurrentSelection() < 0 )
337 fCurrent = (ConfigItem*)
338 fOutline->ItemAt( fOutline->CurrentSelection() );
340 /* Detach the old box if any */
341 if( fDummyView->CountChildren() > 0 )
342 fDummyView->RemoveChild( fDummyView->ChildAt( 0 ) );
344 /* Add the new one... */
345 fDummyView->AddChild( fCurrent->Box() );
347 /* ...then resize it (we must resize it after it's attached or the
348 children don't get adjusted) */
349 fCurrent->Box()->ResizeTo( fDummyView->Bounds().Width(),
350 fDummyView->Bounds().Height() );
353 /* Force redrawing of its children */
354 BRect rect = fCurrent->fConfigBox->Bounds();
355 rect.InsetBy( 10,10 );
357 fCurrent->fConfigScroll->ResizeTo( rect.Width(), rect.Height() );
358 fCurrent->fConfigScroll->Draw( fCurrent->fConfigScroll->Bounds() );
365 /*****************************************************************************
366 * PreferencesWindow::UpdateScrollBar
367 *****************************************************************************/
368 void PreferencesWindow::UpdateScrollBar()
370 /* We have to fix the scrollbar manually because it doesn't handle
371 correctly simple BViews */
379 /* Get the available BRect for display */
380 BRect display = fCurrent->fConfigScroll->Bounds();
381 display.right -= B_V_SCROLL_BAR_WIDTH;
383 /* Fix the scrollbar */
384 BScrollBar * scrollBar;
386 BRect visible = display & fCurrent->fConfigView->Bounds();
387 BRect total = display | fCurrent->fConfigView->Bounds();
388 scrollBar = fCurrent->fConfigScroll->ScrollBar( B_VERTICAL );
389 max = (long)( fCurrent->fConfigView->Bounds().Height() - visible.Height() );
390 if( max < 0 ) max = 0;
391 scrollBar->SetRange( 0, max );
392 scrollBar->SetProportion( visible.Height() / total.Height() );
393 scrollBar->SetSteps( 10, 100 );
397 /*****************************************************************************
398 * PreferencesWindow::ApplyChanges
399 * Apply changes if doIt is true, revert them otherwise
400 *****************************************************************************/
401 void PreferencesWindow::ApplyChanges( bool doIt )
405 for( int i = 0; i < fOutline->CountItems(); i++ )
407 item = (ConfigItem*) fOutline->ItemAt( i );
412 /*****************************************************************************
413 * PreferencesWindow::SaveChanges
414 *****************************************************************************/
415 void PreferencesWindow::SaveChanges()
417 ApplyChanges( true );
418 config_SaveConfigFile( p_intf, NULL );
421 /*****************************************************************************
422 * PreferencesWindow::ReallyQuit
423 *****************************************************************************/
424 void PreferencesWindow::ReallyQuit()
431 /***********************************************************************
432 * ConfigItem::ConfigItem
433 ***********************************************************************
435 **********************************************************************/
436 ConfigItem::ConfigItem( intf_thread_t * _p_intf, char * name,
437 bool subModule, int objectId,
438 int type, char * help )
439 : BStringItem( name )
442 fSubModule = subModule;
443 fObjectId = objectId;
445 fHelp = strdup( help );
450 r = BRect( 0, 0, 100, 100 );
451 fBox = new BBox( r, NULL, B_FOLLOW_ALL );
452 fBox->SetLabel( name );
454 if( fType == TYPE_CATEGORY )
460 fTextView = new VTextView( r, NULL, B_FOLLOW_ALL, B_WILL_DRAW);
461 fTextView->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) );
462 fTextView->MakeEditable( false );
463 fTextView->MakeSelectable( false );
464 fTextView->Insert( fHelp );
465 fBox->AddChild( fTextView );
469 /***********************************************************************
470 * ConfigItem::~ConfigItem
471 ***********************************************************************
473 **********************************************************************/
474 ConfigItem::~ConfigItem()
482 /***********************************************************************
484 ***********************************************************************
486 **********************************************************************/
487 void ConfigItem::Apply( bool doIt )
489 ConfigWidget * widget;
495 /* This is a category */
499 /* Call ConfigWidget::Apply for every child of your fView */
500 for( int i = 0; i < fView->CountChildren(); i++ )
502 widget = (ConfigWidget*) fView->ChildAt( i );
503 widget->Apply( doIt );
507 /***********************************************************************
508 * ConfigWidget::ConfigWidget
509 ***********************************************************************
510 * Builds a view with the right controls for the given config variable.
511 * rect: the BRect where we place ourselves. All we care is its width
512 * and its top coordinate, since we adapt our height to take only
514 **********************************************************************/
515 ConfigWidget::ConfigWidget( intf_thread_t * _p_intf, BRect rect,
516 module_config_t * p_item )
517 : BView( rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW )
524 case CONFIG_ITEM_STRING:
525 case CONFIG_ITEM_FILE:
526 case CONFIG_ITEM_MODULE:
527 case CONFIG_ITEM_DIRECTORY:
528 case CONFIG_ITEM_INTEGER:
529 case CONFIG_ITEM_FLOAT:
530 ResizeTo( Bounds().Width(), 25 );
531 fTextControl = new BTextControl( Bounds(), NULL, label, NULL,
533 AddChild( fTextControl );
536 case CONFIG_ITEM_BOOL:
537 ResizeTo( Bounds().Width(), 25 );
538 fCheckBox = new BCheckBox( Bounds(), NULL, label, new BMessage() );
539 AddChild( fCheckBox );
542 case CONFIG_ITEM_KEY:
543 ResizeTo( Bounds().Width(), 25 );
544 r.left = r.right - 60;
545 fPopUpMenu = new BPopUpMenu( "" );
546 fMenuField = new BMenuField( r, NULL, NULL, fPopUpMenu );
548 i < sizeof( vlc_keys ) / sizeof( key_descriptor_t ); i++ )
550 menuItem = new BMenuItem( vlc_keys[i].psz_key_string, NULL );
551 fPopUpMenu->AddItem( menuItem );
554 r.right = r.left - 10; r.left = r.left - 60;
555 fShiftCheck = new BCheckBox( r, NULL, "Shift", new BMessage );
557 r.right = r.left - 10; r.left = r.left - 60;
558 fCtrlCheck = new BCheckBox( r, NULL, "Ctrl", new BMessage );
560 r.right = r.left - 10; r.left = r.left - 60;
561 fAltCheck = new BCheckBox( r, NULL, "Alt", new BMessage );
563 /* Can someone tell me how we're supposed to get GUI items aligned ? */
564 r.right = r.left - 10; r.left = 0;
566 fStringView = new BStringView( r, NULL, label );
568 AddChild( fStringView );
569 AddChild( fAltCheck );
570 AddChild( fCtrlCheck );
571 AddChild( fShiftCheck );
572 AddChild( fMenuField );
577 /***********************************************************************
578 * ConfigWidget::Apply
579 ***********************************************************************
581 **********************************************************************/
582 void ConfigWidget::Apply( bool doIt )
587 case CONFIG_ITEM_STRING:
588 case CONFIG_ITEM_FILE:
589 case CONFIG_ITEM_MODULE:
590 case CONFIG_ITEM_DIRECTORY:
593 config_PutPsz( p_intf, fConfigName, fTextControl->Text() );
597 fTextControl->SetText( config_GetPsz( p_intf, fConfigName ) );
601 case CONFIG_ITEM_INTEGER:
604 config_PutInt( p_intf, fConfigName,
605 atoi( fTextControl->Text() ) );
609 memset( string, 0, 1024 );
610 snprintf( string, 1023, "%d",
611 config_GetInt( p_intf, fConfigName ) );
612 fTextControl->SetText( string );
616 case CONFIG_ITEM_FLOAT:
619 config_PutFloat( p_intf, fConfigName,
620 strtod( fTextControl->Text(), NULL ) );
624 memset( string, 0, 1024 );
625 snprintf( string, 1023, "%f",
626 config_GetFloat( p_intf, fConfigName ) );
627 fTextControl->SetText( string );
631 case CONFIG_ITEM_BOOL:
634 config_PutInt( p_intf, fConfigName, fCheckBox->Value() );
638 fCheckBox->SetValue( config_GetInt( p_intf, fConfigName ) );
642 case CONFIG_ITEM_KEY:
645 menuItem = fPopUpMenu->FindMarked();
648 int value = vlc_keys[fPopUpMenu->IndexOf( menuItem )].i_key_code;
649 if( fAltCheck->Value() )
651 value |= KEY_MODIFIER_ALT;
653 if( fCtrlCheck->Value() )
655 value |= KEY_MODIFIER_CTRL;
657 if( fShiftCheck->Value() )
659 value |= KEY_MODIFIER_SHIFT;
661 config_PutInt( p_intf, fConfigName, value );
666 int value = config_GetInt( p_intf, fConfigName );
667 fAltCheck->SetValue( value & KEY_MODIFIER_ALT );
668 fCtrlCheck->SetValue( value & KEY_MODIFIER_CTRL );
669 fShiftCheck->SetValue( value & KEY_MODIFIER_SHIFT );
672 i < sizeof( vlc_keys ) / sizeof( key_descriptor_t ); i++ )
674 if( (unsigned) vlc_keys[i].i_key_code ==
675 ( value & ~KEY_MODIFIER ) )
677 menuItem = fPopUpMenu->ItemAt( i );
678 menuItem->SetMarked( true );
689 VTextView::VTextView( BRect frame, const char *name,
690 uint32 resizingMode, uint32 flags )
691 : BTextView( frame, name, BRect( 10,10,10,10 ), resizingMode, flags )
693 FrameResized( Bounds().Width(), Bounds().Height() );
696 void VTextView::FrameResized( float width, float height )
698 BTextView::FrameResized( width, height );
699 SetTextRect( BRect( 10,10, width-11, height-11 ) );