]> git.sesse.net Git - vlc/blob - modules/gui/beos/PreferencesWindow.cpp
beos/* : New Preferences window that lets you configure everything.
[vlc] / modules / gui / beos / PreferencesWindow.cpp
1 /*****************************************************************************
2  * PreferencesWindow.cpp: beos interface
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  * $Id: PreferencesWindow.cpp,v 1.15 2003/05/03 13:37:21 titer Exp $
6  *
7  * Authors: Eric Petit <titer@videolan.org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 #include <stdlib.h> /* atoi(), strtod() */
25
26 #include <InterfaceKit.h>
27 #include <SupportKit.h>
28
29 #include <vlc/vlc.h>
30 #include <vlc/intf.h>
31
32 #include "PreferencesWindow.h"
33
34 /*****************************************************************************
35  * StringItemWithView::StringItemWithView
36  *****************************************************************************/
37 StringItemWithView::StringItemWithView( const char * text )
38     : BStringItem( text )
39 {
40     /* We use the default constructor */
41 }
42
43 /*****************************************************************************
44  * ConfigView::ConfigView
45  *****************************************************************************/
46 ConfigView::ConfigView( BRect frame, const char * name,
47                         uint32 resizingMode, uint32 flags )
48     : BView( frame, name, resizingMode, flags )
49 {
50     /* We use the default constructor */
51 }
52
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 ),
60       fConfigScroll( NULL ),
61       p_intf( p_interface )
62 {
63     BRect rect;
64
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 );
70     
71     /* Create the preferences tree */
72     rect = Bounds();
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
79     rect.right += B_V_SCROLL_BAR_WIDTH;
80     BScrollView * scrollview = new BScrollView( "scrollview", fOutline,
81                                                 B_FOLLOW_LEFT | B_FOLLOW_TOP_BOTTOM,
82                                                 0, false, true );
83     fPrefsView->AddChild( scrollview );
84     
85     /* We need to be informed if the user selects an item */
86     fOutline->SetSelectionMessage( new BMessage( PREFS_ITEM_SELECTED ) );
87
88     /* Create a dummy view so we can correctly place the real config views later */
89     rect.bottom -= 40;
90     rect.left = rect.right + 15;
91     rect.right = Bounds().right - 15;
92     fDummyView = new BView( rect, "", B_FOLLOW_ALL_SIDES, B_WILL_DRAW );
93     fPrefsView->AddChild( fDummyView );
94    
95     /* Fill the tree */
96     /* TODO:
97         - manage CONFIG_HINT_SUBCATEGORY
98         - use a pop-up for CONFIG_HINT_MODULE
99         - use BSliders for integer_with_range and float_with_range
100         - add a tab for BeOS specific configution (screenshot path, etc)
101         - add the needed LockLooper()s
102         - fix window resizing
103         - make this intuitive ! */
104     vlc_list_t * p_list;
105     p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
106     if( !p_list )
107     {
108         msg_Warn( p_intf, "couldn't find any module !" );
109         return;
110     }
111
112     module_t * p_module;
113     for( int i = 0; i < p_list->i_count; i++ )
114     {
115         p_module = (module_t*) p_list->p_values[i].p_object;
116         
117         /* If the module has no config option, ignore it */
118         module_config_t * p_item;
119         p_item = p_module->p_config;
120         if( !p_item )
121             continue;
122         do
123         {
124             if( p_item->i_type & CONFIG_ITEM )
125                 break;
126         } while( p_item->i_type != CONFIG_HINT_END && p_item++ );
127         if( p_item->i_type == CONFIG_HINT_END )
128             continue;
129         
130         /* Build the config view for this module */
131         rect = fDummyView->Bounds();
132         rect.right -= B_V_SCROLL_BAR_WIDTH;
133         ConfigView * configView;
134         configView = new ConfigView( rect, "config view",
135                                      B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW );
136         configView->SetViewColor( background );
137         
138         rect = configView->Bounds();
139         rect.InsetBy( 10, 10 );
140         rect.bottom = rect.top + TEXT_HEIGHT;
141         BTextControl * textControl;
142         BCheckBox * checkBox;
143
144         /* FIXME: we use the BControl name to store the VLC variable name.
145            To know what variable type it is, I add one character at the beginning
146            of the name (see ApplyChanges()); it's not pretty, but it works. To
147            be cleaned later. */    
148         char name[128];
149         p_item = p_module->p_config;
150         bool firstItem = true;
151         do
152         {
153             switch( p_item->i_type )
154             {
155                 case CONFIG_ITEM_STRING:
156                 case CONFIG_ITEM_FILE:
157                 case CONFIG_ITEM_MODULE:
158                 case CONFIG_ITEM_DIRECTORY:
159                     if( !firstItem )
160                         rect.OffsetBy( 0, 25 );
161                     else
162                         firstItem = false;
163                     
164                     memset( name, 0, 128 );
165                     sprintf( name, "s%s", p_item->psz_name );
166                     textControl = new BTextControl( rect, name, p_item->psz_text,
167                                                     "", new BMessage(),
168                                                     B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
169                     configView->AddChild( textControl );
170                     break;
171
172                 case CONFIG_ITEM_INTEGER:
173                     if( !firstItem )
174                         rect.OffsetBy( 0, 25 );
175                     else
176                         firstItem = false;
177                         
178                     memset( name, 0, 128 );
179                     sprintf( name, "i%s", p_item->psz_name );
180                     textControl = new BTextControl( rect, name, p_item->psz_text,
181                                                     "", new BMessage(),
182                                                     B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
183                     configView->AddChild( textControl );
184                     break;
185
186                 case CONFIG_ITEM_FLOAT:
187                     if( !firstItem )
188                         rect.OffsetBy( 0, 25 );
189                     else
190                         firstItem = false;
191                         
192                     memset( name, 0, 128 );
193                     sprintf( name, "f%s", p_item->psz_name );
194                     textControl = new BTextControl( rect, name, p_item->psz_text,
195                                                     "", new BMessage(),
196                                                     B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
197                     configView->AddChild( textControl );
198                     break;
199             
200                 case CONFIG_ITEM_BOOL:
201                     if( !firstItem )
202                         rect.OffsetBy( 0,25 );
203                     else
204                        firstItem = false;
205                        
206                     memset( name, 0, 128 );
207                     sprintf( name, "b%s", p_item->psz_name );
208                     checkBox = new BCheckBox( rect, name, p_item->psz_text,
209                                               new BMessage(), B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP );
210                     configView->AddChild( checkBox );
211                     break;
212             }
213
214         } while( p_item->i_type != CONFIG_HINT_END && p_item++ );
215     
216         /* Adjust the configView size */
217         rect.bottom += 10;
218         configView->fRealBounds = BRect( 0, 0, configView->Bounds().Width(), rect.bottom );
219         configView->ResizeTo( configView->Bounds().Width(), configView->Bounds().Height() );
220
221         /* Add the item to the tree */
222         StringItemWithView * stringItem;
223         stringItem = new StringItemWithView( p_module->psz_object_name );
224         stringItem->fConfigView = configView;
225         fOutline->AddItem( stringItem );
226     }
227     
228     vlc_list_release( p_list );
229     
230     /* Set the correct values */
231     ApplyChanges( false );
232     
233     /* Select the first item */
234     fOutline->Select( 0 );
235     
236     /* Add the buttons */
237     BButton * button;
238     rect = Bounds();
239     rect.InsetBy( 10, 10 );
240     rect.left = rect.right - 80;
241     rect.top = rect.bottom - 25;
242     button = new BButton( rect, "", _("OK"), new BMessage( PREFS_OK ),
243                           B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
244     fPrefsView->AddChild( button );
245     rect.OffsetBy( -90, 0 );
246     button = new BButton( rect, "", _("Revert"), new BMessage( PREFS_REVERT ),
247                           B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
248     fPrefsView->AddChild( button );
249     rect.OffsetBy( -90, 0 );
250     button = new BButton( rect, "", _("Apply"), new BMessage( PREFS_APPLY ),
251                           B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM );
252     fPrefsView->AddChild( button );
253     
254     Hide();
255     Show();
256 }
257
258 /*****************************************************************************
259  * PreferencesWindow::~PreferencesWindow
260  *****************************************************************************/
261 PreferencesWindow::~PreferencesWindow()
262 {
263 }
264
265 /*****************************************************************************
266  * PreferencesWindow::QuitRequested
267  *****************************************************************************/
268 bool PreferencesWindow::QuitRequested()
269 {
270     if( !IsHidden() )
271         Hide();
272         return false;
273 }
274
275 /*****************************************************************************
276  * PreferencesWindow::MessageReceived
277  *****************************************************************************/
278 void PreferencesWindow::MessageReceived( BMessage * message )
279 {
280     switch( message->what )
281     {
282         case PREFS_ITEM_SELECTED:
283             Update();
284             break;
285         
286         case PREFS_OK:
287             ApplyChanges( true );
288             PostMessage( B_QUIT_REQUESTED );
289             break;
290         
291         case PREFS_REVERT:
292             ApplyChanges( false );
293             break;
294         
295         case PREFS_APPLY:
296             ApplyChanges( true );
297             break;
298
299         default:
300             BWindow::MessageReceived( message );
301     }
302 }
303
304 /*****************************************************************************
305  * PreferencesWindow::FrameResized
306  *****************************************************************************/
307 void PreferencesWindow::FrameResized( float width, float height )
308 {
309     BWindow::FrameResized( width, height );
310     UpdateScrollBar();
311 }
312
313 /*****************************************************************************
314  * PreferencesWindow::Update
315  *****************************************************************************/
316 void PreferencesWindow::Update()
317 {
318     /* Get the selected item */
319     if( fOutline->CurrentSelection() < 0 )
320         return;
321     StringItemWithView * selectedItem =
322         (StringItemWithView*) fOutline->ItemAt( fOutline->CurrentSelection() );
323
324     if( fConfigScroll )
325     {
326         /* If we don't do this, the ConfigView will remember a wrong position */
327         BScrollBar * scrollBar = fConfigScroll->ScrollBar( B_VERTICAL );
328         scrollBar->SetValue( 0 );
329
330         /* Detach the current ConfigView, remove the BScrollView */
331         BView * view;
332         while( ( view = fConfigScroll->ChildAt( 0 ) ) )
333             fConfigScroll->RemoveChild( view );
334         fDummyView->RemoveChild( fConfigScroll );
335         delete fConfigScroll;
336     }
337     
338     /* Create a BScrollView with the new ConfigView in it */
339     fConfigScroll = new BScrollView( "", selectedItem->fConfigView, B_FOLLOW_ALL_SIDES,
340                                      0, false, true, B_NO_BORDER );
341     fDummyView->AddChild( fConfigScroll );
342     UpdateScrollBar();
343 }
344
345
346 /*****************************************************************************
347  * PreferencesWindow::UpdateScrollBar
348  *****************************************************************************/
349 void PreferencesWindow::UpdateScrollBar()
350 {
351     /* We have to fix the scrollbar manually because it doesn't handle
352        correctly simple BViews */
353        
354     /* Get the current config view */
355     if( fOutline->CurrentSelection() < 0 )
356         return;
357     StringItemWithView * selectedItem =
358         (StringItemWithView*) fOutline->ItemAt( fOutline->CurrentSelection() );
359     
360     /* Fix the scrollbar */
361         BRect visible = fConfigScroll->Bounds() & selectedItem->fConfigView->fRealBounds;
362         BRect total = fConfigScroll->Bounds() | selectedItem->fConfigView->fRealBounds;
363     BScrollBar * scrollBar = fConfigScroll->ScrollBar( B_VERTICAL );
364     long max = (long)( selectedItem->fConfigView->fRealBounds.Height() -
365                        fConfigScroll->Bounds().Height() );
366     if( max < 0 ) max = 0;
367     scrollBar->SetRange( 0, max );
368     scrollBar->SetProportion( visible.Height() / total.Height() );
369 }
370
371 /*****************************************************************************
372  * PreferencesWindow::ApplyChanges
373  * Apply changes if doIt is true, revert them otherwise
374  *****************************************************************************/
375 void PreferencesWindow::ApplyChanges( bool doIt )
376 {
377     StringItemWithView * item;
378     ConfigView * view;
379     BView * child;
380     const char * name;
381     BString string;
382     for( int i = 0; i < fOutline->CountItems(); i++ )
383     {
384         item = (StringItemWithView*) fOutline->ItemAt( i );
385         view = item->fConfigView;
386         
387         for( int j = 0; j < view->CountChildren(); j++ )
388         {
389             child = view->ChildAt( j );
390             name = child->Name();
391             switch( *name )
392             {
393                 case 's': /* BTextControl, string variable */
394                     if( doIt )
395                         config_PutPsz( p_intf, name + 1, ((BTextControl*)child)->Text() );
396                     else
397                         ((BTextControl*)child)->SetText( config_GetPsz( p_intf, name + 1 ) );
398                     break;
399                 case 'i': /* BTextControl, int variable */
400                     if( doIt )
401                         config_PutInt( p_intf, name + 1, atoi( ((BTextControl*)child)->Text() ) );
402                     else
403                     {
404                         string = "";
405                         string << config_GetInt( p_intf, name + 1 );
406                         ((BTextControl*)child)->SetText( string.String() );
407                     }
408                     break;
409                 case 'f': /* BTextControl, float variable */
410                     if( doIt )
411                         config_PutFloat( p_intf, name + 1,
412                                          strtod( ((BTextControl*)child)->Text(), NULL ) );
413                     else
414                     {
415                         string = "";
416                         string << config_GetFloat( p_intf, name + 1 );
417                         ((BTextControl*)child)->SetText( string.String() );
418                     }
419                     break;
420                 case 'b': /* BCheckBox, bool variable */
421                     if( doIt )
422                         config_PutInt( p_intf, name + 1, ((BCheckBox*)child)->Value() );
423                     else
424                         ((BCheckBox*)child)->SetValue( config_GetInt( p_intf, name + 1 ) );
425                     break;
426             }
427         }
428     }
429 }
430
431 /*****************************************************************************
432  * PreferencesWindow::ReallyQuit
433  *****************************************************************************/
434 void PreferencesWindow::ReallyQuit()
435 {
436     Lock();
437     Hide();
438     Quit();
439 }