1 /*****************************************************************************
2 * PreferencesWindow.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: PreferencesWindow.cpp,v 1.18 2003/05/07 17:27:30 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, "", _("Close"), new BMessage( PREFS_CLOSE ),
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, "", _("Apply"), new BMessage( PREFS_APPLY ),
284 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
285 fPrefsView->AddChild( button );
286 rect.OffsetBy( -90, 0 );
287 button = new BButton( rect, "", _("Save"), new BMessage( PREFS_SAVE ),
288 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
289 fPrefsView->AddChild( button );
290 rect.OffsetBy( -90, 0 );
291 button = new BButton( rect, "", _("Revert"), new BMessage( PREFS_REVERT ),
292 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
293 fPrefsView->AddChild( button );
299 /*****************************************************************************
300 * PreferencesWindow::~PreferencesWindow
301 *****************************************************************************/
302 PreferencesWindow::~PreferencesWindow()
306 /*****************************************************************************
307 * PreferencesWindow::QuitRequested
308 *****************************************************************************/
309 bool PreferencesWindow::QuitRequested()
316 /*****************************************************************************
317 * PreferencesWindow::MessageReceived
318 *****************************************************************************/
319 void PreferencesWindow::MessageReceived( BMessage * message )
321 switch( message->what )
323 case PREFS_ITEM_SELECTED:
328 PostMessage( B_QUIT_REQUESTED );
332 ApplyChanges( false );
336 ApplyChanges( true );
344 BWindow::MessageReceived( message );
348 /*****************************************************************************
349 * PreferencesWindow::FrameResized
350 *****************************************************************************/
351 void PreferencesWindow::FrameResized( float width, float height )
353 BWindow::FrameResized( width, height );
355 /* Get the current ConfigView */
357 view = (ConfigView*) fConfigScroll->ChildAt( 0 );
359 view->ResizeTo( fDummyView->Bounds().Width() - B_V_SCROLL_BAR_WIDTH,
360 fDummyView->Bounds().Height() );
365 /*****************************************************************************
366 * PreferencesWindow::Update
367 *****************************************************************************/
368 void PreferencesWindow::Update()
370 /* Get the selected item, if any */
371 if( fOutline->CurrentSelection() < 0 )
373 StringItemWithView * selectedItem =
374 (StringItemWithView*) fOutline->ItemAt( fOutline->CurrentSelection() );
376 if( !selectedItem->fConfigView )
377 /* This must be the "Modules" item */
382 /* If we don't do this, the ConfigView will remember a wrong position */
383 BScrollBar * scrollBar = fConfigScroll->ScrollBar( B_VERTICAL );
384 scrollBar->SetValue( 0 );
386 /* Detach the current ConfigView, remove the BScrollView */
388 while( ( view = fConfigScroll->ChildAt( 0 ) ) )
389 fConfigScroll->RemoveChild( view );
390 fDummyView->RemoveChild( fConfigScroll );
391 delete fConfigScroll;
394 selectedItem->fConfigView->ResizeTo( fDummyView->Bounds().Width() -
395 B_V_SCROLL_BAR_WIDTH,
396 fDummyView->Bounds().Height() );
398 /* Create a BScrollView with the new ConfigView in it */
399 fConfigScroll = new BScrollView( "", selectedItem->fConfigView, B_FOLLOW_ALL_SIDES,
400 0, false, true, B_NO_BORDER );
401 fDummyView->AddChild( fConfigScroll );
406 /*****************************************************************************
407 * PreferencesWindow::UpdateScrollBar
408 *****************************************************************************/
409 void PreferencesWindow::UpdateScrollBar()
411 /* We have to fix the scrollbar manually because it doesn't handle
412 correctly simple BViews */
414 /* Get the current config view */
416 view = (ConfigView*) fConfigScroll->ChildAt( 0 );
418 /* Get the available BRect for display */
419 BRect display = fConfigScroll->Bounds();
420 display.right -= B_V_SCROLL_BAR_WIDTH;
422 /* Fix the scrollbar */
423 BScrollBar * scrollBar;
425 BRect visible = display & view->fRealBounds;
426 BRect total = display | view->fRealBounds;
427 scrollBar = fConfigScroll->ScrollBar( B_VERTICAL );
428 max = (long)( view->fRealBounds.Height() - visible.Height() );
429 if( max < 0 ) max = 0;
430 scrollBar->SetRange( 0, max );
431 scrollBar->SetProportion( visible.Height() / total.Height() );
434 /*****************************************************************************
435 * PreferencesWindow::ApplyChanges
436 * Apply changes if doIt is true, revert them otherwise
437 *****************************************************************************/
438 void PreferencesWindow::ApplyChanges( bool doIt )
440 StringItemWithView * item;
445 for( int i = 0; i < fOutline->CountItems(); i++ )
447 item = (StringItemWithView*) fOutline->ItemAt( i );
448 view = item->fConfigView;
451 /* This must be the "Modules" item */
454 for( int j = 0; j < view->CountChildren(); j++ )
456 child = view->ChildAt( j );
457 name = child->Name();
460 case 's': /* BTextControl, string variable */
462 config_PutPsz( p_intf, name + 1, ((BTextControl*)child)->Text() );
464 ((BTextControl*)child)->SetText( config_GetPsz( p_intf, name + 1 ) );
466 case 'i': /* BTextControl, int variable */
468 config_PutInt( p_intf, name + 1, atoi( ((BTextControl*)child)->Text() ) );
472 string << config_GetInt( p_intf, name + 1 );
473 ((BTextControl*)child)->SetText( string.String() );
476 case 'f': /* BTextControl, float variable */
478 config_PutFloat( p_intf, name + 1,
479 strtod( ((BTextControl*)child)->Text(), NULL ) );
483 string << config_GetFloat( p_intf, name + 1 );
484 ((BTextControl*)child)->SetText( string.String() );
487 case 'b': /* BCheckBox, bool variable */
489 config_PutInt( p_intf, name + 1, ((BCheckBox*)child)->Value() );
491 ((BCheckBox*)child)->SetValue( config_GetInt( p_intf, name + 1 ) );
498 /*****************************************************************************
499 * PreferencesWindow::SaveChanges
500 *****************************************************************************/
501 void PreferencesWindow::SaveChanges()
503 ApplyChanges( true );
504 config_SaveConfigFile( p_intf, NULL );
507 /*****************************************************************************
508 * PreferencesWindow::ReallyQuit
509 *****************************************************************************/
510 void PreferencesWindow::ReallyQuit()