]> git.sesse.net Git - vlc/blob - modules/gui/skins/src/theme.cpp
* Gtk2 skins: it doesn't work but it runs without any segfault, so
[vlc] / modules / gui / skins / src / theme.cpp
1 /*****************************************************************************
2  * theme.cpp: Theme class
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: theme.cpp,v 1.6 2003/04/13 17:46:23 asmax Exp $
6  *
7  * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
8  *          Emmanuel Puig    <karibu@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111,
23  * USA.
24  *****************************************************************************/
25
26
27 //--- VLC -------------------------------------------------------------------
28 #include <vlc/intf.h>
29
30 //--- SKIN ------------------------------------------------------------------
31 #include "os_api.h"
32 #include "window.h"
33 #include "os_window.h"
34 #include "dialog.h"
35 #include "os_dialog.h"
36 #include "banks.h"
37 #include "anchor.h"
38 #include "event.h"
39 #include "os_event.h"
40 #include "generic.h"
41 #include "theme.h"
42 #include "vlcproc.h"
43 #include "skin_common.h"
44
45
46
47 //---------------------------------------------------------------------------
48 // THEME
49 //---------------------------------------------------------------------------
50 Theme::Theme( intf_thread_t *_p_intf )
51 {
52     p_intf = _p_intf;
53     BmpBank = new BitmapBank( p_intf );
54     FntBank = new FontBank( p_intf );
55     EvtBank = new EventBank( p_intf );
56     OffBank = new OffSetBank( p_intf );
57     Log = NULL;
58     ConstructPlaylist = false;
59
60     ShowInTray    = false;
61     ShowInTaskbar = false;
62
63 }
64 //---------------------------------------------------------------------------
65 Theme::~Theme()
66 {
67     // Delete the windows
68     list<Window *>::const_iterator win;
69     for( win = WindowList.begin(); win != WindowList.end(); win++ )
70     {
71         delete (OSWindow *)(*win);
72     }
73     delete (OSLogWindow *)Log;
74     delete OffBank;
75     delete EvtBank;
76     delete BmpBank;
77     delete FntBank;
78 }
79 //---------------------------------------------------------------------------
80 void Theme::ShowTheme()
81 {
82     // Get parameters form vlcrc config file
83     if( ShowInTray != (bool)config_GetInt( p_intf, "show_in_tray" ) )
84         ChangeTray();
85
86     if( ShowInTaskbar != (bool)config_GetInt( p_intf, "show_in_taskbar" ) )
87         ChangeTaskbar();
88
89     list<Window *>::const_iterator win;
90     Event *evt1;
91     Event *evt2;
92
93     // Synchronize control to visible aspect
94     for( win = WindowList.begin(); win != WindowList.end(); win++ )
95     {
96         // Synchronize windows visibility
97         if( (*win)->OnStartThemeVisible )
98         {
99             evt1 = (Event *)new OSEvent( p_intf, (*win), WINDOW_OPEN,  1, 0 );
100             evt2 = (Event *)new OSEvent( p_intf, (*win), WINDOW_CLOSE, 0, 0 );
101         }
102         else
103         {
104             evt1 = (Event *)new OSEvent( p_intf, (*win), WINDOW_OPEN,  0, 0 );
105             evt2 = (Event *)new OSEvent( p_intf, (*win), WINDOW_CLOSE, 1, 0 );
106         }
107         evt1->PostSynchroMessage( true );
108         evt2->PostSynchroMessage( true );
109     }
110
111     // Initialize magnetism
112     CheckAnchors();
113
114     // Show windows
115     OSAPI_PostMessage( NULL, VLC_SHOW, 0, 0 );
116 }
117 //---------------------------------------------------------------------------
118 void Theme::CreateSystemMenu()
119 {
120     AddSystemMenu( "Open file...", EvtBank->Get( "open" ) );
121     AddSystemMenu( "Change skin...", EvtBank->Get( "load_skin" ) );
122     AddSystemMenu( "Preferences...", NULL );
123     AddSystemMenu( "SEPARATOR", 0 );
124     AddSystemMenu( "Exit", EvtBank->Get( "quit" ) );
125 }
126 //---------------------------------------------------------------------------
127 void Theme::LoadConfig()
128 {
129     // Get config from vlcrc file
130     char *save = config_GetPsz( p_intf, "skin_config" );
131     if( save == NULL )
132         return;
133
134     // Initialization
135     list<Window *>::const_iterator win;
136     int i = 0;
137     int x, y, v, scan;
138
139     // Get config for each window
140     for( win = WindowList.begin(); win != WindowList.end(); win++ )
141     {
142         // Get config
143         scan = sscanf( &save[i * 13], "(%4d,%4d,%1d)", &x, &y, &v );
144
145         // If config has the correct number of arguments
146         if( scan > 2 )
147         {
148             (*win)->Move( x, y );
149             (*win)->OnStartThemeVisible = (bool)v;
150         }
151
152         // Next window
153         i++;
154     }
155 }
156 //---------------------------------------------------------------------------
157 void Theme::SaveConfig()
158 {
159     // Initialize char where config is stored
160     char *save  = new char[400];
161     list<Window *>::const_iterator win;
162     int i = 0;
163     int x, y;
164
165     // Save config of every window
166     for( win = WindowList.begin(); win != WindowList.end(); win++ )
167     {
168         // Print config
169         (*win)->GetPos( x, y );
170         sprintf( &save[i * 13], "(%4d,%4d,%1d)", x, y,
171             (*win)->OnStartThemeVisible );
172         i++;
173     }
174
175     // Save config to file
176     config_PutPsz( p_intf, "skin_config",     save );
177     config_PutInt( p_intf, "show_in_tray",    (int)ShowInTray );
178     config_PutInt( p_intf, "show_in_taskbar", (int)ShowInTaskbar );
179     config_SaveConfigFile( p_intf, "skins" );
180
181     // Free memory
182     delete[] save;
183
184 }
185 //---------------------------------------------------------------------------
186 void Theme::StartTheme( bool log, int magnet )
187 {
188     Magnet = magnet;
189     if( log )
190     {
191         Log = (LogWindow *)new OSLogWindow( p_intf );
192     }
193 }
194 //---------------------------------------------------------------------------
195 void Theme::InitTheme()
196 {
197     // Initialize the events
198 /* FIXME */
199 fprintf(stderr, "FIXME in theme.cpp !\n");
200 //    EvtBank->Init();
201
202     // Initialize the controls
203     InitControls();
204
205     // Initialize the windows
206 //    InitWindows();
207 }
208 //---------------------------------------------------------------------------
209 void Theme::InitWindows()
210 {
211     for( list<Window *>::const_iterator win = WindowList.begin();
212          win != WindowList.end(); win++ )
213     {
214         (*win)->Init();
215     }
216 }
217 //---------------------------------------------------------------------------
218 void Theme::InitControls()
219 {
220     for( list<Window *>::const_iterator win = WindowList.begin();
221          win != WindowList.end(); win++ )
222     {
223         for( unsigned int i = 0; i < (*win)->ControlList.size(); i++ )
224         {
225             (*win)->ControlList[i]->Init();
226         }
227     }
228 }
229 //---------------------------------------------------------------------------
230 Window * Theme::GetWindow( string name )
231 {
232     for( list<Window *>::const_iterator win = WindowList.begin();
233          win != WindowList.end(); win++ )
234     {
235         if( name == OSAPI_GetWindowTitle( *win ) )
236         {
237             return (*win);
238         }
239     }
240     return NULL;
241 }
242 //---------------------------------------------------------------------------
243 void Theme::MoveSkin( Window *wnd, int left, int top )
244 {
245     int x, y, oldx, oldy;
246     Window *win;
247     list<Anchor *>::const_iterator anc;
248     list<Anchor *>::const_iterator hang;
249     wnd->GetPos( oldx, oldy );
250
251     // Move child windows recursively
252     for( anc = wnd->AnchorList.begin(); anc != wnd->AnchorList.end(); anc++ )
253     {
254         for( hang = (*anc)->HangList.begin(); hang != (*anc)->HangList.end();
255             hang++ )
256         {
257             win = (*hang)->GetParent();
258             win->GetPos( x, y );
259             MoveSkin( win, left, top );
260         }
261     }
262
263     // Move window only if has not been moved yet
264     if( !wnd->Moved )
265     {
266         wnd->Moved = true;
267         wnd->Move( oldx + left, oldy + top );
268     }
269 }
270 //---------------------------------------------------------------------------
271 bool Theme::MoveSkinMagnet( Window *wnd, int left, int top )
272 {
273
274     // If magnetism not activate
275     if( !Magnet )
276     {
277         wnd->Move( left, top );
278         return false;
279     }
280
281     // Screen bounds initialization
282     int NewLeft = left;
283     int NewTop  = top;
284     int Sx, Sy, Wx, Wy;
285     OSAPI_GetScreenSize( Sx, Sy );
286     int width, height;
287     wnd->GetSize( width, height );
288     wnd->GetPos( Wx, Wy );
289
290     // Magnetism with screen bounds
291     if( left < Magnet && left > -Magnet)
292         NewLeft = 0;
293     else if( left + width > Sx - Magnet && left + width < Sx + Magnet )
294         NewLeft = Sx - width;
295     if( top < Magnet && top > -Magnet )
296         NewTop = 0;
297     else if( top + height > Sy - Magnet && top + height < Sy + Magnet )
298         NewTop = Sy - height;
299
300     // Deal with anchors
301     HangToAnchors( wnd, NewLeft, NewTop );
302
303     // All windows can be moved
304     list<Window *>::const_iterator win;
305     for( win = WindowList.begin(); win != WindowList.end(); win++ )
306         (*win)->Moved = false;
307
308     // Move Window
309     MoveSkin( wnd, NewLeft - Wx, NewTop - Wy );
310
311     return true;
312 }
313 //---------------------------------------------------------------------------
314 void Theme::HangToAnchors( Window *wnd, int &x, int &y, bool init )
315 {
316     // Magnetism initialization
317     int win_x, win_y, win_anchor_x, win_anchor_y, wnd_anchor_x, wnd_anchor_y;
318     list<Window *>::const_iterator win;
319     list<Anchor *>::const_iterator win_anchor, wnd_anchor;
320
321     // Parse list of windows
322     for( win = WindowList.begin(); win != WindowList.end(); win++ )
323     {
324         // If window is moved window
325         if( (*win) == wnd )
326             continue;               // Check next window
327
328         // If window is hidden
329         if( !init )
330         {
331             if( (*win)->IsHidden() )
332                 continue;           // Check next window
333         }
334         else
335         {
336             if( !(*win)->OnStartThemeVisible )
337                 continue;           // Check next window
338         }
339
340         // Parse anchor lists
341         for( wnd_anchor  = wnd->AnchorList.begin();
342              wnd_anchor != wnd->AnchorList.end(); wnd_anchor++ )
343         {
344             for( win_anchor  = (*win)->AnchorList.begin();
345                  win_anchor != (*win)->AnchorList.end(); win_anchor++ )
346             {
347                 if( (*wnd_anchor)->GetPriority() <
348                     (*win_anchor)->GetPriority() )
349                 {
350                     // Parent anchor is win and child is wnd !!!
351
352
353                     if( !(*win_anchor)->Hang( (*wnd_anchor), x, y ) )
354                     {
355                         // If child is in parent list and parent doesn't hang ch
356                         if( (*win_anchor)->IsInList( (*wnd_anchor) ) )
357                             (*win_anchor)->Remove( (*wnd_anchor) );
358                     }
359                     else
360                     {
361                         // If parent hang child and child is not still in list
362                         if( !(*win_anchor)->IsInList( (*wnd_anchor) ) )
363                         {
364                             (*win_anchor)->Add( (*wnd_anchor) );
365                         }
366
367                         // Move window to stick anchor
368                         (*wnd_anchor)->GetPos( wnd_anchor_x, wnd_anchor_y );
369                         (*win_anchor)->GetPos( win_anchor_x, win_anchor_y );
370                         (*win)->GetPos( win_x, win_y );
371
372                         x = win_x + win_anchor_x - wnd_anchor_x;
373                         y = win_y + win_anchor_y - wnd_anchor_y;
374
375                         break;
376                     }
377
378                 }
379                 else if( (*win_anchor)->Hang( (*wnd_anchor), x, y ) )
380                 {
381                     // Move window to stick anchor
382                     (*wnd_anchor)->GetPos( wnd_anchor_x, wnd_anchor_y );
383                     (*win_anchor)->GetPos( win_anchor_x, win_anchor_y );
384                     (*win)->GetPos( win_x, win_y );
385
386                     x = win_x + win_anchor_x - wnd_anchor_x;
387                     y = win_y + win_anchor_y - wnd_anchor_y;
388
389                     break;
390                 }
391             }
392         }
393     }
394 }
395 //---------------------------------------------------------------------------
396 void Theme::CheckAnchors()
397 {
398     list<Window *>::const_iterator win;
399     int x, y;
400
401     for( win = WindowList.begin(); win != WindowList.end(); win++ )
402     {
403         (*win)->GetPos( x, y );
404         HangToAnchors( (*win), x, y, true );
405         (*win)->Move( x, y );
406     }
407 }
408 //---------------------------------------------------------------------------
409 void Theme::UpdateLog( msg_subscription_t *Sub )
410 {
411     if( Log != NULL )
412         Log->Update( Sub );
413 }
414 //---------------------------------------------------------------------------
415 void Theme::ShowLog( int show )
416 {
417     if( Log == NULL )
418         return;
419
420     if( show == 1 )
421     {
422         Log->Show();
423     }
424     else if( show == 0 )
425     {
426         Log->Hide();
427     }
428     else if( show == 2 )
429     {
430         if( Log->IsVisible() )
431             Log->Hide();
432         else
433             Log->Show();
434     }
435 }
436 //---------------------------------------------------------------------------
437 void Theme::ClearLog()
438 {
439     if( Log!= NULL )
440         Log->Clear();
441 }
442 //---------------------------------------------------------------------------
443