* Fixed mouse events
[vlc.git] / modules / gui / skins / src / window.cpp
1 /*****************************************************************************
2  * window.cpp: Window class
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: window.cpp,v 1.10 2003/04/15 16:42:02 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 "anchor.h"
32 #include "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 Window::Window( 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 Window::~Window()
88 {
89     // Destroy the controls
90     for( unsigned int i = 0; i < ControlList.size(); i++ )
91         delete ControlList[i];
92 }
93 //---------------------------------------------------------------------------
94 void Window::Open()
95 {
96     if( !Hidden )
97         return;
98
99     Changing = true;
100
101     if( Transition )
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 Window::Close()
114 {
115     Changing = true;
116
117     if( Transition )
118         Fade( 0, Transition, WINDOW_HIDE );
119     else
120         OSAPI_PostMessage( this, WINDOW_FADE, WINDOW_HIDE, 1242 );
121 }
122 //---------------------------------------------------------------------------
123 void Window::Show()
124 {
125     Changing = false;
126     Hidden   = false;
127     OSShow( true );
128 }
129 //---------------------------------------------------------------------------
130 void Window::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 Window::Fade( int To, int Time, unsigned int evt )
142 {
143     StartAlpha = Alpha;
144     EndAlpha   = To;
145     StartTime  = OSAPI_GetTime();
146     EndTime    = StartTime + Time;
147     Lock++;
148
149     OSAPI_PostMessage( this, WINDOW_FADE, evt, Lock );
150 }
151 //---------------------------------------------------------------------------
152 bool Window::ProcessEvent( Event *evt )
153 {
154     unsigned int i;
155     unsigned int msg = evt->GetMessage();
156     unsigned int p1  = evt->GetParam1();
157     int          p2  = evt->GetParam2();
158
159     // Send event to control if necessary
160     if( msg > VLC_CONTROL )
161     {
162         for( i = 0; i < ControlList.size(); i++ )
163             ControlList[i]->GenericProcessEvent( evt );
164         return true;
165     }
166
167     // Message processing
168     switch( msg )
169     {
170         case WINDOW_FADE:
171             if( Lock == p2 && ChangeAlpha( OSAPI_GetTime() ) )
172             {
173                 OSAPI_PostMessage( this, WINDOW_FADE, p1, p2 );
174             }
175             else
176             {
177                 OSAPI_PostMessage( this, p1, 0, 0 );
178             }
179             return true;
180
181         case WINDOW_MOVE:
182             WindowManualMoveInit();
183             WindowMoving = true;
184             if( MoveAlpha )
185                 Fade( MoveAlpha, 100 );
186             return true;
187
188         case WINDOW_OPEN:
189             switch( p1 )
190             {
191                 case 0:
192                     Close();
193                     break;
194                 case 1:
195                     Open();
196                     break;
197                 case 2:
198                     if( Hidden )
199                         Open();
200                     else
201                         Close();
202                     break;
203             }
204             return true;
205
206         case WINDOW_CLOSE:
207             switch( p1 )
208             {
209                 case 0:
210                     Open();
211                     break;
212                 case 1:
213                     Close();
214                     break;
215                 case 2:
216                     if( Hidden )
217                         Open();
218                     else
219                         Close();
220                     break;
221             }
222             return true;
223
224         case WINDOW_SHOW:
225             Show();
226             return true;
227
228         case WINDOW_HIDE:
229             Hide();
230             return true;
231
232         case WINDOW_LEAVE:
233             MouseMove( -1, -1, 0 );
234             return true;
235
236         case WINDOW_REFRESH:
237             RefreshAll();
238             return true;
239
240         default:
241             // OS specific messages processing
242             return ProcessOSEvent( evt );
243     }
244 }
245 //---------------------------------------------------------------------------
246 bool Window::ChangeAlpha( int time )
247 {
248     if( time >= EndTime )
249     {
250         if( Lock )
251         {
252             SetTransparency( EndAlpha );
253             Lock = 0;
254         }
255         return false;
256     }
257
258     int NewAlpha = StartAlpha + (EndAlpha - StartAlpha) * (time - StartTime)
259         / (EndTime - StartTime);
260     if( NewAlpha != Alpha )
261         SetTransparency( NewAlpha );
262     if( NewAlpha == EndAlpha )
263     {
264         Lock = 0;
265         return false;
266     }
267     return true;
268 }
269 //---------------------------------------------------------------------------
270 void Window::RefreshImage( int x, int y, int w, int h )
271 {
272     unsigned int i;
273
274     // Create Bitmap Buffer
275     Graphics *Buffer = (Graphics *)new OSGraphics( w, h, this );
276
277     // Draw every control
278         for( i = 0; i < ControlList.size(); i++ )
279             ControlList[i]->Draw( x, y, w, h, Buffer );
280
281     // Copy buffer in Image
282     Image->CopyFrom( x, y, w, h, Buffer, 0, 0, SRC_COPY );
283
284     // Free memory
285     delete Buffer;
286 }
287 //---------------------------------------------------------------------------
288 void Window::Refresh( int x, int y, int w, int h )
289 {
290     if( Image == NULL )
291         return;
292
293     // Refresh buffer image
294     RefreshImage( x, y, w, h );
295
296     if( Hidden )
297         return;
298
299     // And copy buffer to window
300     RefreshFromImage( x, y, w, h );
301
302 }
303 //---------------------------------------------------------------------------
304 void Window::RefreshAll()
305 {
306     Refresh( 0, 0, Width, Height );
307 }
308 //---------------------------------------------------------------------------
309 void Window::MouseDown( int x, int y, int button )
310 {
311     // Checking event in controls
312
313     fprintf( stderr, "  -> mousedown\n" );
314
315     for( int i = ControlList.size() - 1; i >= 0 ; i-- )
316     {
317         if( ControlList[i]->MouseDown( x, y, button ) )
318         {
319             return;
320         }
321     }
322 }
323 //---------------------------------------------------------------------------
324 void Window::MouseMove( int x, int y, int button  )
325 {
326     int i;
327
328     // Move window if selected !
329     if( WindowMoving )
330     {
331         WindowManualMove();
332     }
333
334     // Checking event in controls
335     for( i = ControlList.size() - 1; i >= 0 ; i-- )
336     {
337         ControlList[i]->MouseMove( x, y, button );
338     }
339
340     // Checking help text
341     for( i = ControlList.size() - 1; i >= 0 ; i-- )
342     {
343         if( ControlList[i]->MouseOver( x, y ) )
344         {
345             if( ControlList[i]->SendNewHelpText() )
346             {
347                 break;
348             }
349         }
350     }
351
352     // If help text not found, change it to ""
353     if( i == -1 )
354     {
355         p_intf->p_sys->p_theme->EvtBank->Get( "help" )
356             ->PostTextMessage( " " );
357     }
358
359     // Checking for change in Tool Tip
360     for( i = ControlList.size() - 1; i >= 0 ; i-- )
361     {
362         if( ControlList[i]->ToolTipTest( x, y ) )
363             break;
364     }
365
366     // If no change, delete tooltip text
367     if( i == -1 )
368         ChangeToolTipText( "none" );
369 }
370 //---------------------------------------------------------------------------
371 void Window::MouseUp( int x, int y, int button )
372 {
373     int i;
374
375     // Move window if selected !
376     if( WindowMoving )
377     {
378         if( MoveAlpha )
379             Fade( NormalAlpha, 100 );
380
381         // Check for magnetism
382         p_intf->p_sys->p_theme->CheckAnchors();
383
384         WindowMoving = false;
385     }
386
387     fprintf( stderr, "  -> mouseup\n" );
388
389     // Checking event in controls
390     for( i = ControlList.size() - 1; i >= 0 ; i-- )
391     {
392         if( ControlList[i]->MouseUp( x, y, button ) )
393             return;
394     }
395 }
396 //---------------------------------------------------------------------------
397 void Window::MouseDblClick( int x, int y, int button )
398 {
399     int i;
400
401     // Checking event in controls
402     for( i = ControlList.size() - 1; i >= 0 ; i-- )
403     {
404         if( ControlList[i]->MouseDblClick( x, y, button ) )
405             return;
406     }
407 }
408 //---------------------------------------------------------------------------
409 void Window::Init()
410 {
411     // Get size of window
412     ReSize();
413
414     // Refresh Image buffer
415     RefreshImage( 0, 0, Width, Height );
416
417 fprintf(stderr, "kludge in window.cpp!\n");
418     RefreshFromImage( 0, 0, Width, Height );
419     // Move window as it hasn't been moved yet
420     Move( Left, Top );
421 }
422 //---------------------------------------------------------------------------
423 void Window::ReSize()
424 {
425     // Initialization
426     unsigned int i;
427     int w    = 0;
428     int h    = 0;
429     int MinX = 10000000;
430     int MinY = 10000000;
431
432     // Search size of window and negative values to move all
433     for( i = 0; i < ControlList.size(); i++ )
434     {
435 #define min(a,b) ((a)<(b))?(a):(b)
436 #define max(a,b) ((a)>(b))?(a):(b)
437         w    = max( w,    ControlList[i]->Left + ControlList[i]->Width );
438         h    = max( h,    ControlList[i]->Top + ControlList[i]->Height );
439         MinX = min( MinX, ControlList[i]->Left );
440         MinY = min( MinY, ControlList[i]->Top );
441 #undef max
442 #undef min
443     }
444
445     // Correct values
446     w = w - MinX;
447     h = h - MinY;
448     if( w <= 0 )
449         w = 1;
450     if( h <= 0 )
451         h = 1;
452
453     // Move window and controls !
454     if( MinX != 0 || MinY != 0 )
455     {
456         Move( Left + MinX, Top + MinY );
457         for( i = 0; i < ControlList.size(); i++ )
458             ControlList[i]->MoveRelative( -MinX, -MinY );
459     }
460
461     // Create buffer image for repainting if size has changed
462     if( w != Width || h != Height )
463     {
464         // Change image buffer
465         if( Image != NULL )
466             delete (OSGraphics *)Image;
467         Image = (Graphics *)new OSGraphics( w, h, this );
468
469
470         Size( w, h );
471     }
472
473 }
474 //---------------------------------------------------------------------------
475 void Window::GetSize( int &w, int &h )
476 {
477     w = Width;
478     h = Height;
479 }
480 //---------------------------------------------------------------------------
481 void Window::GetPos( int &x, int &y )
482 {
483     x = Left;
484     y = Top;
485 }
486 //---------------------------------------------------------------------------
487