1 /*****************************************************************************
2 * PreferencesWindow.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: PreferencesWindow.cpp,v 1.20 2003/05/13 11:18:25 titer Exp $
7 * Authors: Eric Petit <titer@videolan.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() */
26 #include <InterfaceKit.h>
27 #include <SupportKit.h>
32 #include "PreferencesWindow.h"
34 /* We use this function to order the items of the BOutlineView */
35 int compare_func( const BListItem * _first, const BListItem * _second )
37 StringItemWithView * first = (StringItemWithView*) _first;
38 StringItemWithView * second = (StringItemWithView*) _second;
40 /* the beos module first */
41 if( !strcmp( first->Text(), "beos" ) )
43 if( !strcmp( second->Text(), "beos" ) )
46 /* the main module in second */
47 if( !strcmp( first->Text(), "main" ) )
49 if( !strcmp( second->Text(), "main" ) )
52 /* alphabetic order */
53 return( strcmp( first->Text(), second->Text() ) );
56 /*****************************************************************************
57 * StringItemWithView::StringItemWithView
58 *****************************************************************************/
59 StringItemWithView::StringItemWithView( const char * text )
62 /* We use the default constructor */
65 /*****************************************************************************
66 * ConfigView::ConfigView
67 *****************************************************************************/
68 ConfigView::ConfigView( BRect frame, const char * name,
69 uint32 resizingMode, uint32 flags )
70 : BView( frame, name, resizingMode, flags )
72 /* We use the default constructor */
75 /*****************************************************************************
76 * PreferencesWindow::PreferencesWindow
77 *****************************************************************************/
78 PreferencesWindow::PreferencesWindow( intf_thread_t * p_interface,
79 BRect frame, const char * name )
80 : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
81 B_NOT_ZOOMABLE | B_NOT_H_RESIZABLE ),
82 fConfigScroll( NULL ),
85 SetSizeLimits( PREFS_WINDOW_WIDTH, PREFS_WINDOW_WIDTH,
90 /* The "background" view */
91 rgb_color background = ui_color( B_PANEL_BACKGROUND_COLOR );
92 fPrefsView = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
93 fPrefsView->SetViewColor( background );
94 AddChild( fPrefsView );
96 /* Create the preferences tree */
98 rect.InsetBy( 10, 10 );
99 rect.right = rect.left + 150;
100 fOutline = new BOutlineListView( rect, "preferences tree",
101 B_SINGLE_SELECTION_LIST,
102 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM );
103 BScrollView * scrollview = new BScrollView( "scrollview", fOutline,
104 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
106 fPrefsView->AddChild( scrollview );
108 /* We need to be informed if the user selects an item */
109 fOutline->SetSelectionMessage( new BMessage( PREFS_ITEM_SELECTED ) );
111 /* Create a dummy view so we can correctly place the real config views later */
113 rect.left = rect.right + 15 + B_V_SCROLL_BAR_WIDTH;
114 rect.right = Bounds().right - 15;
115 fDummyView = new BView( rect, "", B_FOLLOW_ALL_SIDES, B_WILL_DRAW );
116 fPrefsView->AddChild( fDummyView );
118 /* Add a category for modules configuration */
119 StringItemWithView * modulesItem;
120 modulesItem = new StringItemWithView( _("Modules") );
121 modulesItem->fConfigView = NULL;
122 fOutline->AddItem( modulesItem );
126 - manage CONFIG_HINT_SUBCATEGORY
127 - use a pop-up for CONFIG_HINT_MODULE
128 - use BSliders for integer_with_range and float_with_range
129 - add the needed LockLooper()s
130 - fix horizontal window resizing
131 - make this intuitive ! */
133 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
136 msg_Warn( p_intf, "couldn't find any module !" );
141 for( int i = 0; i < p_list->i_count; i++ )
143 p_module = (module_t*) p_list->p_values[i].p_object;
145 /* If the module has no config option, ignore it */
146 module_config_t * p_item;
147 p_item = p_module->p_config;
152 if( p_item->i_type & CONFIG_ITEM )
154 } while( p_item->i_type != CONFIG_HINT_END && p_item++ );
155 if( p_item->i_type == CONFIG_HINT_END )
158 /* Build the config view for this module */
159 rect = fDummyView->Bounds();
160 rect.right -= B_V_SCROLL_BAR_WIDTH;
161 ConfigView * configView;
162 configView = new ConfigView( rect, "config view",
163 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW );
164 configView->SetViewColor( background );
166 rect = configView->Bounds();
167 rect.InsetBy( 10, 10 );
168 rect.bottom = rect.top + TEXT_HEIGHT;
169 BTextControl * textControl;
170 BCheckBox * checkBox;
172 /* FIXME: we use the BControl name to store the VLC variable name.
173 To know what variable type it is, I add one character at the beginning
174 of the name (see ApplyChanges()); it's not pretty, but it works. To
177 p_item = p_module->p_config;
178 bool firstItem = true;
181 switch( p_item->i_type )
183 case CONFIG_ITEM_STRING:
184 case CONFIG_ITEM_FILE:
185 case CONFIG_ITEM_MODULE:
186 case CONFIG_ITEM_DIRECTORY:
188 rect.OffsetBy( 0, 25 );
192 memset( name, 0, 128 );
193 sprintf( name, "s%s", p_item->psz_name );
194 textControl = new BTextControl( rect, name, p_item->psz_text,
197 configView->AddChild( textControl );
200 case CONFIG_ITEM_INTEGER:
202 rect.OffsetBy( 0, 25 );
206 memset( name, 0, 128 );
207 sprintf( name, "i%s", p_item->psz_name );
208 textControl = new BTextControl( rect, name, p_item->psz_text,
211 configView->AddChild( textControl );
214 case CONFIG_ITEM_FLOAT:
216 rect.OffsetBy( 0, 25 );
220 memset( name, 0, 128 );
221 sprintf( name, "f%s", p_item->psz_name );
222 textControl = new BTextControl( rect, name, p_item->psz_text,
225 configView->AddChild( textControl );
228 case CONFIG_ITEM_BOOL:
230 rect.OffsetBy( 0,25 );
234 memset( name, 0, 128 );
235 sprintf( name, "b%s", p_item->psz_name );
236 checkBox = new BCheckBox( rect, name, p_item->psz_text,
237 new BMessage(), B_FOLLOW_NONE );
238 configView->AddChild( checkBox );
242 } while( p_item->i_type != CONFIG_HINT_END && p_item++ );
244 /* Adjust the configView size */
246 configView->fRealBounds = BRect( 0, 0, configView->Bounds().Width(), rect.bottom );
247 configView->ResizeTo( configView->Bounds().Width(), configView->Bounds().Height() );
249 /* Add the item to the tree */
250 StringItemWithView * stringItem;
251 stringItem = new StringItemWithView( p_module->psz_object_name );
252 stringItem->fConfigView = configView;
253 if( !strcmp( p_module->psz_object_name, "beos" )
254 || !strcmp( p_module->psz_object_name, "main" ) )
255 fOutline->AddItem( stringItem );
257 fOutline->AddUnder( stringItem, modulesItem );
260 vlc_list_release( p_list );
262 /* Set the correct values */
263 ApplyChanges( false );
265 /* Sort items, collapse the Modules one */
266 fOutline->FullListSortItems( compare_func );
267 fOutline->Collapse( modulesItem );
269 /* Select the first item */
270 fOutline->Select( 0 );
272 /* Add the buttons */
275 rect.InsetBy( 10, 10 );
276 rect.left = rect.right - 80;
277 rect.top = rect.bottom - 25;
278 button = new BButton( rect, "", _("Apply"), new BMessage( PREFS_APPLY ),
279 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
280 button->MakeDefault( true );
281 fPrefsView->AddChild( button );
282 rect.OffsetBy( -90, 0 );
283 button = new BButton( rect, "", _("Save"), new BMessage( PREFS_SAVE ),
284 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
285 fPrefsView->AddChild( button );
286 rect.OffsetBy( -90, 0 );
287 button = new BButton( rect, "", _("Defaults"), new BMessage( PREFS_DEFAULTS ),
288 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
289 fPrefsView->AddChild( button );
295 /*****************************************************************************
296 * PreferencesWindow::~PreferencesWindow
297 *****************************************************************************/
298 PreferencesWindow::~PreferencesWindow()
302 /*****************************************************************************
303 * PreferencesWindow::QuitRequested
304 *****************************************************************************/
305 bool PreferencesWindow::QuitRequested()
312 /*****************************************************************************
313 * PreferencesWindow::MessageReceived
314 *****************************************************************************/
315 void PreferencesWindow::MessageReceived( BMessage * message )
317 switch( message->what )
319 case PREFS_ITEM_SELECTED:
324 config_ResetAll( p_intf );
325 ApplyChanges( false );
329 ApplyChanges( true );
337 BWindow::MessageReceived( message );
341 /*****************************************************************************
342 * PreferencesWindow::FrameResized
343 *****************************************************************************/
344 void PreferencesWindow::FrameResized( float width, float height )
346 BWindow::FrameResized( width, height );
348 /* Get the current ConfigView */
350 view = (ConfigView*) fConfigScroll->ChildAt( 0 );
352 view->ResizeTo( fDummyView->Bounds().Width() - B_V_SCROLL_BAR_WIDTH,
353 fDummyView->Bounds().Height() );
358 /*****************************************************************************
359 * PreferencesWindow::Update
360 *****************************************************************************/
361 void PreferencesWindow::Update()
363 /* Get the selected item, if any */
364 if( fOutline->CurrentSelection() < 0 )
366 StringItemWithView * selectedItem =
367 (StringItemWithView*) fOutline->ItemAt( fOutline->CurrentSelection() );
369 if( !selectedItem->fConfigView )
370 /* This must be the "Modules" item */
375 /* If we don't do this, the ConfigView will remember a wrong position */
376 BScrollBar * scrollBar = fConfigScroll->ScrollBar( B_VERTICAL );
377 scrollBar->SetValue( 0 );
379 /* Detach the current ConfigView, remove the BScrollView */
381 while( ( view = fConfigScroll->ChildAt( 0 ) ) )
382 fConfigScroll->RemoveChild( view );
383 fDummyView->RemoveChild( fConfigScroll );
384 delete fConfigScroll;
387 selectedItem->fConfigView->ResizeTo( fDummyView->Bounds().Width() -
388 B_V_SCROLL_BAR_WIDTH,
389 fDummyView->Bounds().Height() );
391 /* Create a BScrollView with the new ConfigView in it */
392 fConfigScroll = new BScrollView( "", selectedItem->fConfigView, B_FOLLOW_ALL_SIDES,
393 0, false, true, B_NO_BORDER );
394 fDummyView->AddChild( fConfigScroll );
399 /*****************************************************************************
400 * PreferencesWindow::UpdateScrollBar
401 *****************************************************************************/
402 void PreferencesWindow::UpdateScrollBar()
404 /* We have to fix the scrollbar manually because it doesn't handle
405 correctly simple BViews */
407 /* Get the current config view */
409 view = (ConfigView*) fConfigScroll->ChildAt( 0 );
411 /* Get the available BRect for display */
412 BRect display = fConfigScroll->Bounds();
413 display.right -= B_V_SCROLL_BAR_WIDTH;
415 /* Fix the scrollbar */
416 BScrollBar * scrollBar;
418 BRect visible = display & view->fRealBounds;
419 BRect total = display | view->fRealBounds;
420 scrollBar = fConfigScroll->ScrollBar( B_VERTICAL );
421 max = (long)( view->fRealBounds.Height() - visible.Height() );
422 if( max < 0 ) max = 0;
423 scrollBar->SetRange( 0, max );
424 scrollBar->SetProportion( visible.Height() / total.Height() );
425 scrollBar->SetSteps( 10, 100 );
428 /*****************************************************************************
429 * PreferencesWindow::ApplyChanges
430 * Apply changes if doIt is true, revert them otherwise
431 *****************************************************************************/
432 void PreferencesWindow::ApplyChanges( bool doIt )
434 StringItemWithView * item;
439 for( int i = 0; i < fOutline->CountItems(); i++ )
441 item = (StringItemWithView*) fOutline->ItemAt( i );
442 view = item->fConfigView;
445 /* This must be the "Modules" item */
448 for( int j = 0; j < view->CountChildren(); j++ )
450 child = view->ChildAt( j );
451 name = child->Name();
454 case 's': /* BTextControl, string variable */
456 config_PutPsz( p_intf, name + 1, ((BTextControl*)child)->Text() );
458 ((BTextControl*)child)->SetText( config_GetPsz( p_intf, name + 1 ) );
460 case 'i': /* BTextControl, int variable */
462 config_PutInt( p_intf, name + 1, atoi( ((BTextControl*)child)->Text() ) );
466 string << config_GetInt( p_intf, name + 1 );
467 ((BTextControl*)child)->SetText( string.String() );
470 case 'f': /* BTextControl, float variable */
472 config_PutFloat( p_intf, name + 1,
473 strtod( ((BTextControl*)child)->Text(), NULL ) );
477 string << config_GetFloat( p_intf, name + 1 );
478 ((BTextControl*)child)->SetText( string.String() );
481 case 'b': /* BCheckBox, bool variable */
483 config_PutInt( p_intf, name + 1, ((BCheckBox*)child)->Value() );
485 ((BCheckBox*)child)->SetValue( config_GetInt( p_intf, name + 1 ) );
492 /*****************************************************************************
493 * PreferencesWindow::SaveChanges
494 *****************************************************************************/
495 void PreferencesWindow::SaveChanges()
497 ApplyChanges( true );
498 config_SaveConfigFile( p_intf, NULL );
501 /*****************************************************************************
502 * PreferencesWindow::ReallyQuit
503 *****************************************************************************/
504 void PreferencesWindow::ReallyQuit()