]> git.sesse.net Git - vlc/blob - modules/gui/skins/src/theme.cpp
490fbb2934218fd8a8e21cf3feae33fd34573a12
[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.3 2003/03/19 18:14:48 karibu 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     EvtBank->Init();
199
200     // Initialize the controls
201     InitControls();
202
203     // Initialize the windows
204     InitWindows();
205 }
206 //---------------------------------------------------------------------------
207 void Theme::InitWindows()
208 {
209     for( list<Window *>::const_iterator win = WindowList.begin();
210          win != WindowList.end(); win++ )
211     {
212         (*win)->Init();
213     }
214 }
215 //---------------------------------------------------------------------------
216 void Theme::InitControls()
217 {
218     for( list<Window *>::const_iterator win = WindowList.begin();
219          win != WindowList.end(); win++ )
220     {
221         for( unsigned int i = 0; i < (*win)->ControlList.size(); i++ )
222         {
223             (*win)->ControlList[i]->Init();
224         }
225     }
226 }
227 //---------------------------------------------------------------------------
228 Window * Theme::GetWindow( string name )
229 {
230     for( list<Window *>::const_iterator win = WindowList.begin();
231          win != WindowList.end(); win++ )
232     {
233         if( name == OSAPI_GetWindowTitle( *win ) )
234         {
235             return (*win);
236         }
237     }
238     return NULL;
239 }
240 //---------------------------------------------------------------------------
241 void Theme::MoveSkin( Window *wnd, int left, int top )
242 {
243     int x, y, oldx, oldy;
244     Window *win;
245     list<Anchor *>::const_iterator anc;
246     list<Anchor *>::const_iterator hang;
247     wnd->GetPos( oldx, oldy );
248
249     // Move child windows recursively
250     for( anc = wnd->AnchorList.begin(); anc != wnd->AnchorList.end(); anc++ )
251     {
252         for( hang = (*anc)->HangList.begin(); hang != (*anc)->HangList.end();
253             hang++ )
254         {
255             win = (*hang)->GetParent();
256             win->GetPos( x, y );
257             MoveSkin( win, left, top );
258         }
259     }
260
261     // Move window only if has not been moved yet
262     if( !wnd->Moved )
263     {
264         wnd->Moved = true;
265         wnd->Move( oldx + left, oldy + top );
266     }
267 }
268 //---------------------------------------------------------------------------
269 bool Theme::MoveSkinMagnet( Window *wnd, int left, int top )
270 {
271
272     // If magnetism not activate
273     if( !Magnet )
274     {
275         wnd->Move( left, top );
276         return false;
277     }
278
279     // Screen bounds initialization
280     int NewLeft = left;
281     int NewTop  = top;
282     int Sx, Sy, Wx, Wy;
283     OSAPI_GetScreenSize( Sx, Sy );
284     int width, height;
285     wnd->GetSize( width, height );
286     wnd->GetPos( Wx, Wy );
287
288     // Magnetism with screen bounds
289     if( left < Magnet && left > -Magnet)
290         NewLeft = 0;
291     else if( left + width > Sx - Magnet && left + width < Sx + Magnet )
292         NewLeft = Sx - width;
293     if( top < Magnet && top > -Magnet )
294         NewTop = 0;
295     else if( top + height > Sy - Magnet && top + height < Sy + Magnet )
296         NewTop = Sy - height;
297
298     // Deal with anchors
299     HangToAnchors( wnd, NewLeft, NewTop );
300
301     // All windows can be moved
302     list<Window *>::const_iterator win;
303     for( win = WindowList.begin(); win != WindowList.end(); win++ )
304         (*win)->Moved = false;
305
306     // Move Window
307     MoveSkin( wnd, NewLeft - Wx, NewTop - Wy );
308
309     return true;
310 }
311 //---------------------------------------------------------------------------
312 void Theme::HangToAnchors( Window *wnd, int &x, int &y, bool init )
313 {
314     // Magnetism initialization
315     int win_x, win_y, win_anchor_x, win_anchor_y, wnd_anchor_x, wnd_anchor_y;
316     list<Window *>::const_iterator win;
317     list<Anchor *>::const_iterator win_anchor, wnd_anchor;
318
319     // Parse list of windows
320     for( win = WindowList.begin(); win != WindowList.end(); win++ )
321     {
322         // If window is moved window
323         if( (*win) == wnd )
324             continue;               // Check next window
325
326         // If window is hidden
327         if( !init )
328         {
329             if( (*win)->IsHidden() )
330                 continue;           // Check next window
331         }
332         else
333         {
334             if( !(*win)->OnStartThemeVisible )
335                 continue;           // Check next window
336         }
337
338         // Parse anchor lists
339         for( wnd_anchor  = wnd->AnchorList.begin();
340              wnd_anchor != wnd->AnchorList.end(); wnd_anchor++ )
341         {
342             for( win_anchor  = (*win)->AnchorList.begin();
343                  win_anchor != (*win)->AnchorList.end(); win_anchor++ )
344             {
345                 if( (*wnd_anchor)->GetPriority() <
346                     (*win_anchor)->GetPriority() )
347                 {
348                     // Parent anchor is win and child is wnd !!!
349
350
351                     if( !(*win_anchor)->Hang( (*wnd_anchor), x, y ) )
352                     {
353                         // If child is in parent list and parent doesn't hang ch
354                         if( (*win_anchor)->IsInList( (*wnd_anchor) ) )
355                             (*win_anchor)->Remove( (*wnd_anchor) );
356                     }
357                     else
358                     {
359                         // If parent hang child and child is not still in list
360                         if( !(*win_anchor)->IsInList( (*wnd_anchor) ) )
361                             (*win_anchor)->Add( (*wnd_anchor) );
362
363                         // Move window to stick anchor
364                         (*wnd_anchor)->GetPos( wnd_anchor_x, wnd_anchor_y );
365                         (*win_anchor)->GetPos( win_anchor_x, win_anchor_y );
366                         (*win)->GetPos( win_x, win_y );
367
368                         x = win_x + win_anchor_x - wnd_anchor_x;
369                         y = win_y + win_anchor_y - wnd_anchor_y;
370
371                         break;
372                     }
373
374                 }
375                 else if( (*win_anchor)->Hang( (*wnd_anchor), x, y ) )
376                 {
377                     // Move window to stick anchor
378                     (*wnd_anchor)->GetPos( wnd_anchor_x, wnd_anchor_y );
379                     (*win_anchor)->GetPos( win_anchor_x, win_anchor_y );
380                     (*win)->GetPos( win_x, win_y );
381
382                     x = win_x + win_anchor_x - wnd_anchor_x;
383                     y = win_y + win_anchor_y - wnd_anchor_y;
384
385                     break;
386                 }
387             }
388         }
389     }
390 }
391 //---------------------------------------------------------------------------
392 void Theme::CheckAnchors()
393 {
394     list<Window *>::const_iterator win;
395     int x, y;
396
397     for( win = WindowList.begin(); win != WindowList.end(); win++ )
398     {
399         (*win)->GetPos( x, y );
400         HangToAnchors( (*win), x, y, true );
401     }
402 }
403 //---------------------------------------------------------------------------
404 void Theme::UpdateLog( msg_subscription_t *Sub )
405 {
406     if( Log != NULL )
407         Log->Update( Sub );
408 }
409 //---------------------------------------------------------------------------
410 void Theme::ShowLog( int show )
411 {
412     if( Log == NULL )
413         return;
414
415     if( show == 1 )
416     {
417         Log->Show();
418     }
419     else if( show == 0 )
420     {
421         Log->Hide();
422     }
423     else if( show == 2 )
424     {
425         if( Log->IsVisible() )
426             Log->Hide();
427         else
428             Log->Show();
429     }
430 }
431 //---------------------------------------------------------------------------
432 void Theme::ClearLog()
433 {
434     if( Log!= NULL )
435         Log->Clear();
436 }
437 //---------------------------------------------------------------------------
438