1 /*****************************************************************************
2 * PreferencesWindow.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: PreferencesWindow.cpp,v 1.17 2003/05/07 16:47:10 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 ),
87 /* The "background" view */
88 rgb_color background = ui_color( B_PANEL_BACKGROUND_COLOR );
89 fPrefsView = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
90 fPrefsView->SetViewColor( background );
91 AddChild( fPrefsView );
93 /* Create the preferences tree */
95 rect.InsetBy( 10, 10 );
96 rect.right = rect.left + 150;
97 fOutline = new BOutlineListView( rect, "preferences tree",
98 B_SINGLE_SELECTION_LIST,
99 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM );
100 BScrollView * scrollview = new BScrollView( "scrollview", fOutline,
101 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
103 fPrefsView->AddChild( scrollview );
105 /* We need to be informed if the user selects an item */
106 fOutline->SetSelectionMessage( new BMessage( PREFS_ITEM_SELECTED ) );
108 /* Create a dummy view so we can correctly place the real config views later */
110 rect.left = rect.right + 15 + B_V_SCROLL_BAR_WIDTH;
111 rect.right = Bounds().right - 15;
112 fDummyView = new BView( rect, "", B_FOLLOW_ALL_SIDES, B_WILL_DRAW );
113 fPrefsView->AddChild( fDummyView );
115 /* Add a category for modules configuration */
116 StringItemWithView * modulesItem;
117 modulesItem = new StringItemWithView( _("Modules") );
118 modulesItem->fConfigView = NULL;
119 fOutline->AddItem( modulesItem );
123 - manage CONFIG_HINT_SUBCATEGORY
124 - use a pop-up for CONFIG_HINT_MODULE
125 - use BSliders for integer_with_range and float_with_range
126 - add the needed LockLooper()s
127 - fix horizontal window resizing
128 - make this intuitive ! */
130 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
133 msg_Warn( p_intf, "couldn't find any module !" );
138 for( int i = 0; i < p_list->i_count; i++ )
140 p_module = (module_t*) p_list->p_values[i].p_object;
142 /* If the module has no config option, ignore it */
143 module_config_t * p_item;
144 p_item = p_module->p_config;
149 if( p_item->i_type & CONFIG_ITEM )
151 } while( p_item->i_type != CONFIG_HINT_END && p_item++ );
152 if( p_item->i_type == CONFIG_HINT_END )
155 /* Build the config view for this module */
156 rect = fDummyView->Bounds();
157 rect.right -= B_V_SCROLL_BAR_WIDTH;
158 ConfigView * configView;
159 configView = new ConfigView( rect, "config view",
160 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW );
161 configView->SetViewColor( background );
163 rect = configView->Bounds();
164 rect.InsetBy( 10, 10 );
165 rect.bottom = rect.top + TEXT_HEIGHT;
166 BTextControl * textControl;
167 BCheckBox * checkBox;
169 /* FIXME: we use the BControl name to store the VLC variable name.
170 To know what variable type it is, I add one character at the beginning
171 of the name (see ApplyChanges()); it's not pretty, but it works. To
174 p_item = p_module->p_config;
175 bool firstItem = true;
178 switch( p_item->i_type )
180 case CONFIG_ITEM_STRING:
181 case CONFIG_ITEM_FILE:
182 case CONFIG_ITEM_MODULE:
183 case CONFIG_ITEM_DIRECTORY:
185 rect.OffsetBy( 0, 25 );
189 memset( name, 0, 128 );
190 sprintf( name, "s%s", p_item->psz_name );
191 textControl = new BTextControl( rect, name, p_item->psz_text,
194 configView->AddChild( textControl );
197 case CONFIG_ITEM_INTEGER:
199 rect.OffsetBy( 0, 25 );
203 memset( name, 0, 128 );
204 sprintf( name, "i%s", p_item->psz_name );
205 textControl = new BTextControl( rect, name, p_item->psz_text,
208 configView->AddChild( textControl );
211 case CONFIG_ITEM_FLOAT:
213 rect.OffsetBy( 0, 25 );
217 memset( name, 0, 128 );
218 sprintf( name, "f%s", p_item->psz_name );
219 textControl = new BTextControl( rect, name, p_item->psz_text,
222 configView->AddChild( textControl );
225 case CONFIG_ITEM_BOOL:
227 rect.OffsetBy( 0,25 );
231 memset( name, 0, 128 );
232 sprintf( name, "b%s", p_item->psz_name );
233 checkBox = new BCheckBox( rect, name, p_item->psz_text,
234 new BMessage(), B_FOLLOW_NONE );
235 configView->AddChild( checkBox );
239 } while( p_item->i_type != CONFIG_HINT_END && p_item++ );
241 /* Adjust the configView size */
243 configView->fRealBounds = BRect( 0, 0, configView->Bounds().Width(), rect.bottom );
244 configView->ResizeTo( configView->Bounds().Width(), configView->Bounds().Height() );
246 /* Add the item to the tree */
247 StringItemWithView * stringItem;
248 stringItem = new StringItemWithView( p_module->psz_object_name );
249 stringItem->fConfigView = configView;
250 if( !strcmp( p_module->psz_object_name, "beos" )
251 || !strcmp( p_module->psz_object_name, "main" ) )
252 fOutline->AddItem( stringItem );
254 fOutline->AddUnder( stringItem, modulesItem );
257 vlc_list_release( p_list );
259 /* Set the correct values */
260 ApplyChanges( false );
262 /* Sort items, collapse the Modules one */
263 fOutline->FullListSortItems( compare_func );
264 fOutline->Collapse( modulesItem );
266 /* Select the first item */
267 fOutline->Select( 0 );
269 /* Add the buttons */
272 rect.InsetBy( 10, 10 );
273 rect.left = rect.right - 80;
274 rect.top = rect.bottom - 25;
275 button = new BButton( rect, "", _("OK"), new BMessage( PREFS_OK ),
276 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
277 fPrefsView->AddChild( button );
278 rect.OffsetBy( -90, 0 );
279 button = new BButton( rect, "", _("Revert"), new BMessage( PREFS_REVERT ),
280 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
281 fPrefsView->AddChild( button );
282 rect.OffsetBy( -90, 0 );
283 button = new BButton( rect, "", _("Apply"), new BMessage( PREFS_APPLY ),
284 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
285 fPrefsView->AddChild( button );
291 /*****************************************************************************
292 * PreferencesWindow::~PreferencesWindow
293 *****************************************************************************/
294 PreferencesWindow::~PreferencesWindow()
298 /*****************************************************************************
299 * PreferencesWindow::QuitRequested
300 *****************************************************************************/
301 bool PreferencesWindow::QuitRequested()
308 /*****************************************************************************
309 * PreferencesWindow::MessageReceived
310 *****************************************************************************/
311 void PreferencesWindow::MessageReceived( BMessage * message )
313 switch( message->what )
315 case PREFS_ITEM_SELECTED:
320 ApplyChanges( true );
321 PostMessage( B_QUIT_REQUESTED );
325 ApplyChanges( false );
329 ApplyChanges( true );
333 BWindow::MessageReceived( message );
337 /*****************************************************************************
338 * PreferencesWindow::FrameResized
339 *****************************************************************************/
340 void PreferencesWindow::FrameResized( float width, float height )
342 BWindow::FrameResized( width, height );
344 /* Get the current ConfigView */
346 view = (ConfigView*) fConfigScroll->ChildAt( 0 );
348 view->ResizeTo( fDummyView->Bounds().Width() - B_V_SCROLL_BAR_WIDTH,
349 fDummyView->Bounds().Height() );
354 /*****************************************************************************
355 * PreferencesWindow::Update
356 *****************************************************************************/
357 void PreferencesWindow::Update()
359 /* Get the selected item, if any */
360 if( fOutline->CurrentSelection() < 0 )
362 StringItemWithView * selectedItem =
363 (StringItemWithView*) fOutline->ItemAt( fOutline->CurrentSelection() );
365 if( !selectedItem->fConfigView )
366 /* This must be the "Modules" item */
371 /* If we don't do this, the ConfigView will remember a wrong position */
372 BScrollBar * scrollBar = fConfigScroll->ScrollBar( B_VERTICAL );
373 scrollBar->SetValue( 0 );
375 /* Detach the current ConfigView, remove the BScrollView */
377 while( ( view = fConfigScroll->ChildAt( 0 ) ) )
378 fConfigScroll->RemoveChild( view );
379 fDummyView->RemoveChild( fConfigScroll );
380 delete fConfigScroll;
383 selectedItem->fConfigView->ResizeTo( fDummyView->Bounds().Width() -
384 B_V_SCROLL_BAR_WIDTH,
385 fDummyView->Bounds().Height() );
387 /* Create a BScrollView with the new ConfigView in it */
388 fConfigScroll = new BScrollView( "", selectedItem->fConfigView, B_FOLLOW_ALL_SIDES,
389 0, false, true, B_NO_BORDER );
390 fDummyView->AddChild( fConfigScroll );
395 /*****************************************************************************
396 * PreferencesWindow::UpdateScrollBar
397 *****************************************************************************/
398 void PreferencesWindow::UpdateScrollBar()
400 /* We have to fix the scrollbar manually because it doesn't handle
401 correctly simple BViews */
403 /* Get the current config view */
405 view = (ConfigView*) fConfigScroll->ChildAt( 0 );
407 /* Get the available BRect for display */
408 BRect display = fConfigScroll->Bounds();
409 display.right -= B_V_SCROLL_BAR_WIDTH;
411 /* Fix the scrollbar */
412 BScrollBar * scrollBar;
414 BRect visible = display & view->fRealBounds;
415 BRect total = display | view->fRealBounds;
416 scrollBar = fConfigScroll->ScrollBar( B_VERTICAL );
417 max = (long)( view->fRealBounds.Height() - visible.Height() );
418 if( max < 0 ) max = 0;
419 scrollBar->SetRange( 0, max );
420 scrollBar->SetProportion( visible.Height() / total.Height() );
423 /*****************************************************************************
424 * PreferencesWindow::ApplyChanges
425 * Apply changes if doIt is true, revert them otherwise
426 *****************************************************************************/
427 void PreferencesWindow::ApplyChanges( bool doIt )
429 StringItemWithView * item;
434 for( int i = 0; i < fOutline->CountItems(); i++ )
436 item = (StringItemWithView*) fOutline->ItemAt( i );
437 view = item->fConfigView;
440 /* This must be the "Modules" item */
443 for( int j = 0; j < view->CountChildren(); j++ )
445 child = view->ChildAt( j );
446 name = child->Name();
449 case 's': /* BTextControl, string variable */
451 config_PutPsz( p_intf, name + 1, ((BTextControl*)child)->Text() );
453 ((BTextControl*)child)->SetText( config_GetPsz( p_intf, name + 1 ) );
455 case 'i': /* BTextControl, int variable */
457 config_PutInt( p_intf, name + 1, atoi( ((BTextControl*)child)->Text() ) );
461 string << config_GetInt( p_intf, name + 1 );
462 ((BTextControl*)child)->SetText( string.String() );
465 case 'f': /* BTextControl, float variable */
467 config_PutFloat( p_intf, name + 1,
468 strtod( ((BTextControl*)child)->Text(), NULL ) );
472 string << config_GetFloat( p_intf, name + 1 );
473 ((BTextControl*)child)->SetText( string.String() );
476 case 'b': /* BCheckBox, bool variable */
478 config_PutInt( p_intf, name + 1, ((BCheckBox*)child)->Value() );
480 ((BCheckBox*)child)->SetValue( config_GetInt( p_intf, name + 1 ) );
487 /*****************************************************************************
488 * PreferencesWindow::ReallyQuit
489 *****************************************************************************/
490 void PreferencesWindow::ReallyQuit()