]> git.sesse.net Git - vlc/blob - modules/gui/skins/src/window.cpp
* ./modules/gui/skins/*: first attempt at porting the skins to Win9x
[vlc] / modules / gui / skins / src / window.cpp
1 /*****************************************************************************
2  * window.cpp: Window class
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: window.cpp,v 1.20 2003/04/28 00:18:27 ipkiss 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 "anchor.h"
32 #include "../controls/generic.h"
33 #include "window.h"
34 #include "event.h"
35 #include "../os_api.h"
36 #include "graphics.h"
37 #include "../os_graphics.h"
38 #include "banks.h"
39 #include "theme.h"
40 #include "skin_common.h"
41
42 #include <stdio.h>
43
44
45 //---------------------------------------------------------------------------
46 // Skinable Window
47 //---------------------------------------------------------------------------
48 SkinWindow::SkinWindow( intf_thread_t *_p_intf, int x, int y, bool visible,
49     int transition, int normalalpha, int movealpha, bool dragdrop )
50 {
51     p_intf = _p_intf;
52
53     // Set position parameters
54     Left         = x;
55     Top          = y;
56     Width        = 0;
57     Height       = 0;
58     WindowMoving = false;
59     Moved        = false;
60
61     // Set transparency
62     Transition   = transition;
63     if( Transition < 1 )
64         Transition = 1;
65     NormalAlpha  = normalalpha;
66     MoveAlpha    = movealpha;
67     Alpha        = normalalpha;
68     StartAlpha   = 0;
69     EndAlpha     = 0;
70     StartTime    = 0;
71     EndTime      = 0;
72     Lock         = 0;
73
74     // Visible parameters
75     Image               = NULL;
76     Hidden              = true;
77     Changing            = false;
78     OnStartThemeVisible = visible;
79
80     // Drag & drop
81     DragDrop = dragdrop;
82
83     // ToolTip
84     ToolTipText = "none";
85 }
86 //---------------------------------------------------------------------------
87 SkinWindow::~SkinWindow()
88 {
89     // Destroy the controls
90     for( unsigned int i = 0; i < ControlList.size(); i++ )
91         delete ControlList[i];
92 }
93 //---------------------------------------------------------------------------
94 void SkinWindow::Open()
95 {
96     if( !Hidden )
97         return;
98
99     Changing = true;
100
101     if( Transition && IS_WINNT )
102     {
103         SetTransparency( 0 );
104         OSAPI_PostMessage( this, WINDOW_SHOW, 0, 0 );
105         Fade( NormalAlpha, Transition );
106     }
107     else
108     {
109         OSAPI_PostMessage( this, WINDOW_SHOW, 0, 0 );
110     }
111 }
112 //---------------------------------------------------------------------------
113 void SkinWindow::Close()
114 {
115     Changing = true;
116
117     if( Transition && IS_WINNT )
118         Fade( 0, Transition, WINDOW_HIDE );
119     else
120         OSAPI_PostMessage( this, WINDOW_FADE, WINDOW_HIDE, 1242 );
121 }
122 //---------------------------------------------------------------------------
123 void SkinWindow::Show()
124 {
125     Changing = false;
126     Hidden   = false;
127     OSShow( true );
128 }
129 //---------------------------------------------------------------------------
130 void SkinWindow::Hide()
131 {
132     if( Hidden )
133         return;
134
135     Changing = false;
136     Hidden   = true;
137     OSShow( false );
138     OSAPI_PostMessage( NULL, VLC_TEST_ALL_CLOSED, 0, 0 );
139 }
140 //---------------------------------------------------------------------------
141 void SkinWindow::Fade( int To, int Time, unsigned int evt )
142 {
143     // No fading effect on win9x
144     if( IS_WINNT )
145     {
146         StartAlpha = Alpha;
147         EndAlpha   = To;
148         StartTime  = OSAPI_GetTime();
149         EndTime    = StartTime + Time;
150         Lock++;
151
152         OSAPI_PostMessage( this, WINDOW_FADE, evt, Lock );
153     }
154 }
155 //---------------------------------------------------------------------------
156 bool SkinWindow::ProcessEvent( Event *evt )
157 {
158     unsigned int i;
159     unsigned int msg = evt->GetMessage();
160     unsigned int p1  = evt->GetParam1();
161     int          p2  = evt->GetParam2();
162
163     // Send event to control if necessary
164     if( msg > VLC_CONTROL )
165     {
166         for( i = 0; i < ControlList.size(); i++ )
167             ControlList[i]->GenericProcessEvent( evt );
168         return true;
169     }
170
171     // Message processing
172     switch( msg )
173     {
174         case WINDOW_FADE:
175             if( Lock == p2 && ChangeAlpha( OSAPI_GetTime() ) )
176             {
177                 OSAPI_PostMessage( this, WINDOW_FADE, p1, p2 );
178             }
179             else
180             {
181                 OSAPI_PostMessage( this, p1, 0, 0 );
182             }
183             return true;
184
185         case WINDOW_MOVE:
186             WindowManualMoveInit();
187             WindowMoving = true;
188             if( MoveAlpha )
189                 Fade( MoveAlpha, 100 );
190             return true;
191
192         case WINDOW_OPEN:
193             switch( p1 )
194             {
195                 case 0:
196                     Close();
197                     break;
198                 case 1:
199                     Open();
200                     break;
201                 case 2:
202                     if( Hidden )
203                         Open();
204                     else
205                         Close();
206                     break;
207             }
208             return true;
209
210         case WINDOW_CLOSE:
211             switch( p1 )
212             {
213                 case 0:
214                     Open();
215                     break;
216                 case 1:
217                     Close();
218                     break;
219                 case 2:
220                     if( Hidden )
221                         Open();
222                     else
223                         Close();
224                     break;
225             }
226             return true;
227
228         case WINDOW_SHOW:
229             Show();
230             return true;
231
232         case WINDOW_HIDE:
233             Hide();
234             return true;
235
236         case WINDOW_LEAVE:
237             MouseMove( -1, -1, 0 );
238             return true;
239
240         case WINDOW_REFRESH:
241             RefreshAll();
242             return true;
243
244         default:
245             // OS specific messages processing
246             return ProcessOSEvent( evt );
247     }
248 }
249 //---------------------------------------------------------------------------
250 bool SkinWindow::ChangeAlpha( int time )
251 {
252     if( IS_WINNT )
253     {
254         if( time >= EndTime )
255         {
256             if( Lock )
257             {
258                 SetTransparency( EndAlpha );
259                 Lock = 0;
260             }
261             return false;
262         }
263
264         int NewAlpha = StartAlpha + (EndAlpha - StartAlpha) * (time - StartTime)
265             / (EndTime - StartTime);
266         if( NewAlpha != Alpha )
267             SetTransparency( NewAlpha );
268         if( NewAlpha == EndAlpha )
269         {
270             Lock = 0;
271             return false;
272         }
273     }
274     return true;
275 }
276 //---------------------------------------------------------------------------
277 void SkinWindow::RefreshImage( int x, int y, int w, int h )
278 {
279     unsigned int i;
280
281     // Create Bitmap Buffer
282     Graphics *Buffer = (Graphics *)new OSGraphics( w, h, this );
283
284     // Draw every control
285         for( i = 0; i < ControlList.size(); i++ )
286             ControlList[i]->Draw( x, y, w, h, Buffer );
287
288     // Copy buffer in Image
289     Image->CopyFrom( x, y, w, h, Buffer, 0, 0, SRC_COPY );
290
291     // Free memory
292     delete Buffer;
293 }
294 //---------------------------------------------------------------------------
295 void SkinWindow::Refresh( int x, int y, int w, int h )
296 {
297     if( Image == NULL )
298         return;
299
300     // Refresh buffer image
301     RefreshImage( x, y, w, h );
302
303     if( Hidden )
304         return;
305
306     // And copy buffer to window
307     RefreshFromImage( x, y, w, h );
308
309 }
310 //---------------------------------------------------------------------------
311 void SkinWindow::RefreshAll()
312 {
313     Refresh( 0, 0, Width, Height );
314 }
315 //---------------------------------------------------------------------------
316 void SkinWindow::MouseDown( int x, int y, int button )
317 {
318     // Checking event in controls
319     for( int i = ControlList.size() - 1; i >= 0 ; i-- )
320     {
321         if( ControlList[i]->MouseDown( x, y, button ) )
322         {
323             return;
324         }
325     }
326
327 }
328 //---------------------------------------------------------------------------
329 void SkinWindow::MouseMove( int x, int y, int button  )
330 {
331     int i;
332
333     // Move window if selected !
334     if( WindowMoving )
335     {
336         WindowManualMove();
337     }
338
339     // Checking event in controls
340     for( i = ControlList.size() - 1; i >= 0 ; i-- )
341     {
342         ControlList[i]->MouseMove( x, y, button );
343     }
344
345     // Checking help text
346     for( i = ControlList.size() - 1; i >= 0 ; i-- )
347     {
348         if( ControlList[i]->MouseOver( x, y ) )
349         {
350             if( ControlList[i]->SendNewHelpText() )
351             {
352                 break;
353             }
354         }
355     }
356
357     // If help text not found, change it to ""
358     if( i == -1 )
359     {
360         p_intf->p_sys->p_theme->EvtBank->Get( "help" )
361             ->PostTextMessage( " " );
362     }
363
364     // Checking for change in Tool Tip
365     for( i = ControlList.size() - 1; i >= 0 ; i-- )
366     {
367         if( ControlList[i]->ToolTipTest( x, y ) )
368             break;
369     }
370
371     // If no change, delete tooltip text
372     if( i == -1 )
373         ChangeToolTipText( "none" );
374 }
375 //---------------------------------------------------------------------------
376 void SkinWindow::MouseUp( int x, int y, int button )
377 {
378     int i;
379
380     // Move window if selected !
381     if( WindowMoving )
382     {
383         if( MoveAlpha )
384             Fade( NormalAlpha, 100 );
385
386         // Check for magnetism
387         p_intf->p_sys->p_theme->CheckAnchors();
388
389         WindowMoving = false;
390     }
391
392     // Checking event in controls
393     for( i = ControlList.size() - 1; i >= 0 ; i-- )
394     {
395         if( ControlList[i]->MouseUp( x, y, button ) )
396         {
397             return;
398         }
399     }
400 }
401 //---------------------------------------------------------------------------
402 void SkinWindow::MouseDblClick( int x, int y, int button )
403 {
404     int i;
405
406     // Checking event in controls
407     for( i = ControlList.size() - 1; i >= 0 ; i-- )
408     {
409         if( ControlList[i]->MouseDblClick( x, y, button ) )
410             return;
411     }
412 }
413 //---------------------------------------------------------------------------
414 void SkinWindow::MouseScroll( int x, int y, int direction )
415 {
416     // Checking event in controls
417     for( int i = ControlList.size() - 1; i >= 0 ; i-- )
418     {
419         if( ControlList[i]->MouseScroll( x, y, direction ) )
420         {
421             return;
422         }
423     }
424 }
425 //---------------------------------------------------------------------------
426 void SkinWindow::Init()
427 {
428     // Get size of window
429     ReSize();
430
431     // Refresh Image buffer
432     RefreshImage( 0, 0, Width, Height );
433
434     // Move window as it hasn't been moved yet
435     Move( Left, Top );
436 }
437 //---------------------------------------------------------------------------
438 void SkinWindow::ReSize()
439 {
440     // Initialization
441     unsigned int i;
442     int w    = 0;
443     int h    = 0;
444     int MinX = 10000000;
445     int MinY = 10000000;
446
447     // Search size of window and negative values to move all
448     for( i = 0; i < ControlList.size(); i++ )
449     {
450 #define min(a,b) ((a)<(b))?(a):(b)
451 #define max(a,b) ((a)>(b))?(a):(b)
452         w    = max( w,    ControlList[i]->Left + ControlList[i]->Width );
453         h    = max( h,    ControlList[i]->Top + ControlList[i]->Height );
454         MinX = min( MinX, ControlList[i]->Left );
455         MinY = min( MinY, ControlList[i]->Top );
456 #undef max
457 #undef min
458     }
459
460     // Correct values
461     w = w - MinX;
462     h = h - MinY;
463     if( w <= 0 )
464         w = 1;
465     if( h <= 0 )
466         h = 1;
467
468     // Move window and controls !
469     if( MinX != 0 || MinY != 0 )
470     {
471         Move( Left + MinX, Top + MinY );
472         for( i = 0; i < ControlList.size(); i++ )
473             ControlList[i]->MoveRelative( -MinX, -MinY );
474     }
475
476     // Create buffer image for repainting if size has changed
477     if( w != Width || h != Height )
478     {
479         // Change image buffer
480         if( Image != NULL )
481             delete (OSGraphics *)Image;
482         Image = (Graphics *)new OSGraphics( w, h, this );
483
484
485         Size( w, h );
486     }
487
488 }
489 //---------------------------------------------------------------------------
490 void SkinWindow::GetSize( int &w, int &h )
491 {
492     w = Width;
493     h = Height;
494 }
495 //---------------------------------------------------------------------------
496 void SkinWindow::GetPos( int &x, int &y )
497 {
498     x = Left;
499     y = Top;
500 }
501 //---------------------------------------------------------------------------
502