1 /*****************************************************************************
2 * PreferencesWindow.cpp: beos interface
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: PreferencesWindow.cpp,v 1.16 2003/05/05 13:06:02 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 /*****************************************************************************
35 * StringItemWithView::StringItemWithView
36 *****************************************************************************/
37 StringItemWithView::StringItemWithView( const char * text )
40 /* We use the default constructor */
43 /*****************************************************************************
44 * ConfigView::ConfigView
45 *****************************************************************************/
46 ConfigView::ConfigView( BRect frame, const char * name,
47 uint32 resizingMode, uint32 flags )
48 : BView( frame, name, resizingMode, flags )
50 /* We use the default constructor */
53 /*****************************************************************************
54 * PreferencesWindow::PreferencesWindow
55 *****************************************************************************/
56 PreferencesWindow::PreferencesWindow( intf_thread_t * p_interface,
57 BRect frame, const char * name )
58 : BWindow( frame, name, B_FLOATING_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
59 B_NOT_ZOOMABLE | B_NOT_H_RESIZABLE ),
60 fConfigScroll( NULL ),
65 /* The "background" view */
66 rgb_color background = ui_color( B_PANEL_BACKGROUND_COLOR );
67 fPrefsView = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW );
68 fPrefsView->SetViewColor( background );
69 AddChild( fPrefsView );
71 /* Create the preferences tree */
73 rect.InsetBy( 10, 10 );
74 rect.right = rect.left + 150;
75 fOutline = new BOutlineListView( rect, "preferences tree",
76 B_SINGLE_SELECTION_LIST,
77 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM );
78 BScrollView * scrollview = new BScrollView( "scrollview", fOutline,
79 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
81 fPrefsView->AddChild( scrollview );
83 /* We need to be informed if the user selects an item */
84 fOutline->SetSelectionMessage( new BMessage( PREFS_ITEM_SELECTED ) );
86 /* Create a dummy view so we can correctly place the real config views later */
88 rect.left = rect.right + 15 + B_V_SCROLL_BAR_WIDTH;
89 rect.right = Bounds().right - 15;
90 fDummyView = new BView( rect, "", B_FOLLOW_ALL_SIDES, B_WILL_DRAW );
91 fPrefsView->AddChild( fDummyView );
95 - manage CONFIG_HINT_SUBCATEGORY
96 - use a pop-up for CONFIG_HINT_MODULE
97 - use BSliders for integer_with_range and float_with_range
98 - add a tab for BeOS specific configution (screenshot path, etc)
99 - add the needed LockLooper()s
100 - fix window resizing
101 - make this intuitive ! */
103 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
106 msg_Warn( p_intf, "couldn't find any module !" );
111 for( int i = 0; i < p_list->i_count; i++ )
113 p_module = (module_t*) p_list->p_values[i].p_object;
115 /* If the module has no config option, ignore it */
116 module_config_t * p_item;
117 p_item = p_module->p_config;
122 if( p_item->i_type & CONFIG_ITEM )
124 } while( p_item->i_type != CONFIG_HINT_END && p_item++ );
125 if( p_item->i_type == CONFIG_HINT_END )
128 /* Build the config view for this module */
129 rect = fDummyView->Bounds();
130 rect.right -= B_V_SCROLL_BAR_WIDTH;
131 ConfigView * configView;
132 configView = new ConfigView( rect, "config view",
133 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW );
134 configView->SetViewColor( background );
136 rect = configView->Bounds();
137 rect.InsetBy( 10, 10 );
138 rect.bottom = rect.top + TEXT_HEIGHT;
139 BTextControl * textControl;
140 BCheckBox * checkBox;
142 /* FIXME: we use the BControl name to store the VLC variable name.
143 To know what variable type it is, I add one character at the beginning
144 of the name (see ApplyChanges()); it's not pretty, but it works. To
147 p_item = p_module->p_config;
148 bool firstItem = true;
151 switch( p_item->i_type )
153 case CONFIG_ITEM_STRING:
154 case CONFIG_ITEM_FILE:
155 case CONFIG_ITEM_MODULE:
156 case CONFIG_ITEM_DIRECTORY:
158 rect.OffsetBy( 0, 25 );
162 memset( name, 0, 128 );
163 sprintf( name, "s%s", p_item->psz_name );
164 textControl = new BTextControl( rect, name, p_item->psz_text,
167 configView->AddChild( textControl );
170 case CONFIG_ITEM_INTEGER:
172 rect.OffsetBy( 0, 25 );
176 memset( name, 0, 128 );
177 sprintf( name, "i%s", p_item->psz_name );
178 textControl = new BTextControl( rect, name, p_item->psz_text,
181 configView->AddChild( textControl );
184 case CONFIG_ITEM_FLOAT:
186 rect.OffsetBy( 0, 25 );
190 memset( name, 0, 128 );
191 sprintf( name, "f%s", p_item->psz_name );
192 textControl = new BTextControl( rect, name, p_item->psz_text,
195 configView->AddChild( textControl );
198 case CONFIG_ITEM_BOOL:
200 rect.OffsetBy( 0,25 );
204 memset( name, 0, 128 );
205 sprintf( name, "b%s", p_item->psz_name );
206 checkBox = new BCheckBox( rect, name, p_item->psz_text,
207 new BMessage(), B_FOLLOW_NONE );
208 configView->AddChild( checkBox );
212 } while( p_item->i_type != CONFIG_HINT_END && p_item++ );
214 /* Adjust the configView size */
216 configView->fRealBounds = BRect( 0, 0, configView->Bounds().Width(), rect.bottom );
217 configView->ResizeTo( configView->Bounds().Width(), configView->Bounds().Height() );
219 /* Add the item to the tree */
220 StringItemWithView * stringItem;
221 stringItem = new StringItemWithView( p_module->psz_object_name );
222 stringItem->fConfigView = configView;
223 fOutline->AddItem( stringItem );
226 vlc_list_release( p_list );
228 /* Set the correct values */
229 ApplyChanges( false );
231 /* Select the first item */
232 fOutline->Select( 0 );
234 /* Add the buttons */
237 rect.InsetBy( 10, 10 );
238 rect.left = rect.right - 80;
239 rect.top = rect.bottom - 25;
240 button = new BButton( rect, "", _("OK"), new BMessage( PREFS_OK ),
241 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
242 fPrefsView->AddChild( button );
243 rect.OffsetBy( -90, 0 );
244 button = new BButton( rect, "", _("Revert"), new BMessage( PREFS_REVERT ),
245 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
246 fPrefsView->AddChild( button );
247 rect.OffsetBy( -90, 0 );
248 button = new BButton( rect, "", _("Apply"), new BMessage( PREFS_APPLY ),
249 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
250 fPrefsView->AddChild( button );
256 /*****************************************************************************
257 * PreferencesWindow::~PreferencesWindow
258 *****************************************************************************/
259 PreferencesWindow::~PreferencesWindow()
263 /*****************************************************************************
264 * PreferencesWindow::QuitRequested
265 *****************************************************************************/
266 bool PreferencesWindow::QuitRequested()
273 /*****************************************************************************
274 * PreferencesWindow::MessageReceived
275 *****************************************************************************/
276 void PreferencesWindow::MessageReceived( BMessage * message )
278 switch( message->what )
280 case PREFS_ITEM_SELECTED:
285 ApplyChanges( true );
286 PostMessage( B_QUIT_REQUESTED );
290 ApplyChanges( false );
294 ApplyChanges( true );
298 BWindow::MessageReceived( message );
302 /*****************************************************************************
303 * PreferencesWindow::FrameResized
304 *****************************************************************************/
305 void PreferencesWindow::FrameResized( float width, float height )
307 BWindow::FrameResized( width, height );
309 StringItemWithView * item;
311 for( int i = 0; i < fOutline->CountItems(); i++ )
313 /* Fix ConfigView sizes */
314 item = (StringItemWithView*) fOutline->ItemAt( i );
315 view = item->fConfigView;
316 view->ResizeTo( fDummyView->Bounds().Width() - B_V_SCROLL_BAR_WIDTH,
317 fDummyView->Bounds().Height() );
323 /*****************************************************************************
324 * PreferencesWindow::Update
325 *****************************************************************************/
326 void PreferencesWindow::Update()
328 /* Get the selected item */
329 if( fOutline->CurrentSelection() < 0 )
331 StringItemWithView * selectedItem =
332 (StringItemWithView*) fOutline->ItemAt( fOutline->CurrentSelection() );
336 /* If we don't do this, the ConfigView will remember a wrong position */
337 BScrollBar * scrollBar = fConfigScroll->ScrollBar( B_VERTICAL );
338 scrollBar->SetValue( 0 );
340 /* Detach the current ConfigView, remove the BScrollView */
342 while( ( view = fConfigScroll->ChildAt( 0 ) ) )
343 fConfigScroll->RemoveChild( view );
344 fDummyView->RemoveChild( fConfigScroll );
345 delete fConfigScroll;
348 /* Create a BScrollView with the new ConfigView in it */
349 fConfigScroll = new BScrollView( "", selectedItem->fConfigView, B_FOLLOW_ALL_SIDES,
350 0, false, true, B_NO_BORDER );
351 fDummyView->AddChild( fConfigScroll );
356 /*****************************************************************************
357 * PreferencesWindow::UpdateScrollBar
358 *****************************************************************************/
359 void PreferencesWindow::UpdateScrollBar()
361 /* We have to fix the scrollbar manually because it doesn't handle
362 correctly simple BViews */
364 /* Get the current config view */
366 if( fOutline->CurrentSelection() < 0 )
368 StringItemWithView * selectedItem =
369 (StringItemWithView*) fOutline->ItemAt( fOutline->CurrentSelection() );
370 view = selectedItem->fConfigView;
372 /* Get the available BRect for display */
373 BRect display = fConfigScroll->Bounds();
374 display.right -= B_V_SCROLL_BAR_WIDTH;
376 /* Fix the scrollbar */
377 BScrollBar * scrollBar;
379 BRect visible = display & view->fRealBounds;
380 BRect total = display | view->fRealBounds;
381 scrollBar = fConfigScroll->ScrollBar( B_VERTICAL );
382 max = (long)( view->fRealBounds.Height() - visible.Height() );
383 if( max < 0 ) max = 0;
384 scrollBar->SetRange( 0, max );
385 scrollBar->SetProportion( visible.Height() / total.Height() );
388 /*****************************************************************************
389 * PreferencesWindow::ApplyChanges
390 * Apply changes if doIt is true, revert them otherwise
391 *****************************************************************************/
392 void PreferencesWindow::ApplyChanges( bool doIt )
394 StringItemWithView * item;
399 for( int i = 0; i < fOutline->CountItems(); i++ )
401 item = (StringItemWithView*) fOutline->ItemAt( i );
402 view = item->fConfigView;
404 for( int j = 0; j < view->CountChildren(); j++ )
406 child = view->ChildAt( j );
407 name = child->Name();
410 case 's': /* BTextControl, string variable */
412 config_PutPsz( p_intf, name + 1, ((BTextControl*)child)->Text() );
414 ((BTextControl*)child)->SetText( config_GetPsz( p_intf, name + 1 ) );
416 case 'i': /* BTextControl, int variable */
418 config_PutInt( p_intf, name + 1, atoi( ((BTextControl*)child)->Text() ) );
422 string << config_GetInt( p_intf, name + 1 );
423 ((BTextControl*)child)->SetText( string.String() );
426 case 'f': /* BTextControl, float variable */
428 config_PutFloat( p_intf, name + 1,
429 strtod( ((BTextControl*)child)->Text(), NULL ) );
433 string << config_GetFloat( p_intf, name + 1 );
434 ((BTextControl*)child)->SetText( string.String() );
437 case 'b': /* BCheckBox, bool variable */
439 config_PutInt( p_intf, name + 1, ((BCheckBox*)child)->Value() );
441 ((BCheckBox*)child)->SetValue( config_GetInt( p_intf, name + 1 ) );
448 /*****************************************************************************
449 * PreferencesWindow::ReallyQuit
450 *****************************************************************************/
451 void PreferencesWindow::ReallyQuit()