676975e72c1fc52debaeb4b2d80e4ebb192abc28
[vlc.git] / modules / gui / skins / controls / text.cpp
1 /*****************************************************************************
2  * text.cpp: Text control
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: text.cpp,v 1.10 2003/06/05 22:16:15 asmax Exp $
6  *
7  * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
8  *          Emmanuel Puig    <karibu@via.ecp.fr>
9  *          Cyril Deguet     <asmax@videolan.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111,
24  * USA.
25  *****************************************************************************/
26
27
28 //--- VLC -------------------------------------------------------------------
29 #include <vlc/intf.h>
30
31 //--- SKIN ------------------------------------------------------------------
32 #include "../os_api.h"
33 #include "../src/bitmap.h"
34 #include "../src/banks.h"
35 #include "../src/graphics.h"
36 #include "../os_graphics.h"
37 #include "../src/font.h"
38 #include "../os_font.h"
39 #include "generic.h"
40 #include "text.h"
41 #include "../src/event.h"
42 #include "../src/theme.h"
43 #include "../src/window.h"
44 #include "../os_window.h"
45 #include "../src/skin_common.h"
46
47 #ifdef X11_SKINS
48 #include "../x11/x11_timer.h"
49 extern intf_thread_t *g_pIntf;
50 #endif
51
52
53
54 //---------------------------------------------------------------------------
55 // Scrolling : one for each OS
56 //---------------------------------------------------------------------------
57
58     #if defined( WIN32 )
59     //-----------------------------------------------------------------------
60     // Win32 methods
61     //-----------------------------------------------------------------------
62     void CALLBACK ScrollingTextTimer( HWND hwnd, UINT uMsg, UINT_PTR idEvent,
63         DWORD dwTime )
64     {
65         if( (ControlText *)idEvent != NULL
66             && !( (ControlText *)idEvent )->GetSelected() )
67         {
68             ( (ControlText *)idEvent )->DoScroll();
69         }
70
71     }
72     //-----------------------------------------------------------------------
73     void ControlText::StartScrolling()
74     {
75         SetTimer( ( (Win32Window *)ParentWindow )->GetHandle(), (UINT_PTR)this,
76                   100, (TIMERPROC)ScrollingTextTimer );
77     }
78     //-----------------------------------------------------------------------
79     void ControlText::StopScrolling()
80     {
81         KillTimer( ( (Win32Window *)ParentWindow )->GetHandle(),
82                    (UINT_PTR)this );
83     }
84     //-----------------------------------------------------------------------
85
86     #elif defined GTK2_SKINS
87
88     //-----------------------------------------------------------------------
89     // Gtk2 methods
90     //-----------------------------------------------------------------------
91     gboolean ScrollingTextTimer( gpointer data )
92     {
93         if( (ControlText *)data != NULL )
94         {
95             if( !( (ControlText *)data )->IsScrolling() )
96                 return false;
97
98             if( !( (ControlText *)data )->GetSelected() )
99                ( (ControlText *)data )->DoScroll();
100
101             return true;
102         }
103         else
104         {
105             return false;
106         }
107     }
108     //-----------------------------------------------------------------------
109     void ControlText::StartScrolling()
110     {
111         g_timeout_add( 100, (GSourceFunc)ScrollingTextTimer, (gpointer)this );
112     }
113     //-----------------------------------------------------------------------
114     void ControlText::StopScrolling()
115     {
116     }
117     //-----------------------------------------------------------------------
118
119     #elif defined X11_SKINS
120
121     //-----------------------------------------------------------------------
122     // X11 methods
123     //----------------------------------------------------------------------- 
124     void ScrollingTextTimer( void *data )
125     { 
126         if( (ControlText *)data != NULL
127             && !( (ControlText *)data )->GetSelected() )
128         {
129             ( (ControlText *)data )->DoScroll();
130         }
131     }
132
133     //-----------------------------------------------------------------------
134     void ControlText::StartScrolling()
135     {
136         X11Timer *timer = new X11Timer( g_pIntf, 100000, ScrollingTextTimer, 
137                                         (void*)this );
138         X11TimerManager *timerManager = X11TimerManager::Instance( g_pIntf );
139         timerManager->addTimer( timer );
140     }
141     //-----------------------------------------------------------------------
142     void ControlText::StopScrolling()
143     {
144     }
145     //-----------------------------------------------------------------------
146
147     #endif
148 //---------------------------------------------------------------------------
149
150
151
152
153 //---------------------------------------------------------------------------
154 // CONTROL TEXT
155 //---------------------------------------------------------------------------
156 ControlText::ControlText( string id, bool visible, int x, int y, string text,
157     string font, int align, int width, string display, bool scroll,
158     int scrollspace, string help, SkinWindow *Parent )
159     : GenericControl( id, visible, help, Parent )
160 {
161     InitLeft         = x;
162     Top              = y;
163     InitWidth        = width;
164     FontName         = font;
165     Text             = text;
166     Align            = align;
167     Selected         = false;
168
169     // Scrolling parameters
170     InitScroll       = scroll;
171     Scroll           = false;
172     ScrollSpace      = scrollspace;
173     PauseScroll      = false;
174
175     // Initialize display
176     if( display != "none" )
177     {
178         int begin = 0;
179         int pos = display.find( ';', 0 );
180         while( pos > 0 )
181         {
182             DisplayList.push_back( display.substr( begin, pos - begin ) );
183             begin = pos + 1;
184             pos = display.find( ';', begin );
185         }
186         DisplayList.push_back(
187             display.substr( begin, display.size() - begin ) );
188         Display = DisplayList.begin();
189     }
190
191 }
192 //---------------------------------------------------------------------------
193 ControlText::~ControlText()
194 {
195     if( TextClipRgn != NULL )
196         delete TextClipRgn;
197     TextWidth = 0;
198     SetScrolling();
199 }
200 //---------------------------------------------------------------------------
201 void ControlText::Init()
202 {
203     TextFont     = p_intf->p_sys->p_theme->FntBank->Get( FontName );
204
205     // Init clipping region
206     TextClipRgn = NULL;
207
208     // Get size of control
209     SetSize();
210     SetScrolling();
211 }
212 //---------------------------------------------------------------------------
213 void ControlText::SetScrolling()
214 {
215     if( !Scroll && TextWidth > Width )
216     {
217         if( InitScroll )
218         {
219             Scroll = true;
220             StartScrolling();
221         }
222     }
223     else if( Scroll && TextWidth <= Width )
224     {
225         Scroll = false;
226         StopScrolling();
227     }
228 }
229 //---------------------------------------------------------------------------
230 void ControlText::SetSize()
231 {
232     // Get size parameters
233     int w, h;
234     TextFont->GetSize( Text, w, h );
235     TextWidth = w;
236
237     // Get width if not set
238     if( InitWidth <= 0 )
239         Width  = w;
240     else
241         Width  = InitWidth;
242
243     // Set height
244     Height = h;
245
246     // Set position wether alignment
247     if( Align == VLC_FONT_ALIGN_CENTER )
248     {
249         Left     = InitLeft - Width / 2;
250         TextLeft = InitLeft - TextWidth / 2;
251     }
252     else if( Align == VLC_FONT_ALIGN_RIGHT )
253     {
254         Left     = InitLeft - Width;
255         TextLeft = InitLeft - TextWidth;
256     }
257     else
258     {
259         Left     = InitLeft;
260         TextLeft = InitLeft;
261     }
262
263     // Create clipping region
264     if( TextClipRgn != NULL )
265         delete TextClipRgn;
266
267     TextClipRgn = (SkinRegion *)new OSRegion( Left, Top, Width, Height );
268
269 }
270 //---------------------------------------------------------------------------
271 bool ControlText::ProcessEvent( Event *evt )
272 {
273     unsigned int msg = evt->GetMessage();
274     unsigned int p1  = evt->GetParam1();
275     long         p2  = evt->GetParam2();
276
277     switch( msg )
278     {
279         case CTRL_SET_TEXT:
280             if( DisplayList.size() > 0 )
281             {
282                 if( p_intf->p_sys->p_theme->EvtBank->Get( (*Display) )
283                     ->IsEqual( (Event*)p1 ) )
284                 {
285                     SetText( (char *)p2 );
286                 }
287             }
288             break;
289     }
290     return false;
291 }
292 //---------------------------------------------------------------------------
293 void ControlText::Draw( int x, int y, int w, int h, Graphics *dest )
294 {
295     if( !Visible )
296         return;
297
298     // Test if control is in refresh zone
299     int xI, yI, wI, hI;
300     if( !GetIntersectRgn( x,y,w,h, Left,Top,Width,Height, xI,yI,wI,hI) )
301         return;
302
303     // Change clipping region
304     TextClipRgn->Move( -x, -y );
305     dest->SetClipRegion( TextClipRgn );
306
307     // Draw text
308     if( TextWidth <= Width || !Scroll )
309     {
310         TextFont->Print( dest, Text, Left - x, Top - y, Width, Height, Align );
311     }
312     else
313     {
314         if( TextLeft > Left + ScrollSpace )
315         {
316             TextFont->Print( dest, Text, TextLeft - x, Top - y,
317                          TextWidth, Height, Align );
318             TextFont->Print( dest, Text, TextLeft - x - TextWidth - ScrollSpace,
319                          Top - y, TextWidth, Height, Align );
320         }
321         else if( TextLeft + TextWidth + ScrollSpace < Left + Width )
322         {
323             TextFont->Print( dest, Text, TextLeft - x, Top - y,
324                          TextWidth, Height, Align );
325             TextFont->Print( dest, Text, TextLeft - x + TextWidth + ScrollSpace,
326                          Top - y, TextWidth, Height, Align );
327         }
328         else
329         {
330             TextFont->Print( dest, Text, TextLeft - x, Top - y,
331                          TextWidth, Height, Align );
332         }
333     }
334
335     // Reset clipping region to old region
336     SkinRegion *destClipRgn = (SkinRegion *)new OSRegion( 0, 0, w, h );
337     dest->SetClipRegion( destClipRgn );
338     delete destClipRgn;
339     TextClipRgn->Move( x, y );
340 }
341 //---------------------------------------------------------------------------
342 void ControlText::SetText( const string newText )
343 {
344     if( Text != newText )
345     {
346         Selected = false;
347         Text     = newText;
348         SetSize();
349         SetScrolling();
350         ParentWindow->Refresh( Left, Top, Width, Height );
351     }
352 }
353 //---------------------------------------------------------------------------
354 void ControlText::DoScroll()
355 {
356     if( !PauseScroll )
357     {
358         TextLeft -= 2;
359         if( TextLeft + TextWidth < Left )
360             TextLeft += TextWidth + ScrollSpace;
361
362         ParentWindow->Refresh( Left, Top, Width, Height );
363     }
364 }
365 //---------------------------------------------------------------------------
366 void ControlText::MoveRelative( int xOff, int yOff )
367 {
368     InitLeft += xOff;
369     Top      += yOff;
370     SetSize();
371 }
372 //---------------------------------------------------------------------------
373 bool ControlText::MouseUp( int x, int y, int button )
374 {
375     Selected = false;
376     if( MouseOver( x, y ) && button == 1 )
377     {
378         if( DisplayList.size() > 1 || TextWidth > Width )
379             return true;
380     }
381     return false;
382
383 }
384 //---------------------------------------------------------------------------
385 bool ControlText::MouseDown( int x, int y, int button )
386 {
387     if( MouseOver( x, y ) && button == 1 )
388     {
389         if( TextWidth > Width )
390         {
391             PauseScroll = !PauseScroll;
392             OSAPI_GetMousePos( MouseX, MouseY );
393             SelectedX = MouseX;
394             Selected = true;
395             return true;
396         }
397         else if( DisplayList.size() > 1 )
398         {
399             return true;
400         }
401     }
402     return false;
403 }
404 //---------------------------------------------------------------------------
405 bool ControlText::MouseMove( int x, int y, int button )
406 {
407     if( Selected && button == 1 )
408     {
409         OSAPI_GetMousePos( MouseX, MouseY );
410
411         if( MouseX != SelectedX )
412         {
413             TextLeft += MouseX - SelectedX;
414             SelectedX = MouseX;
415
416             while( TextLeft + TextWidth < Left )
417                 TextLeft += TextWidth + ScrollSpace;
418
419             while( TextLeft > Left + ScrollSpace )
420                 TextLeft -= TextWidth + ScrollSpace;
421
422             ParentWindow->Refresh( Left, Top, Width, Height );
423         }
424     }
425     return false;
426 }
427 //---------------------------------------------------------------------------
428 bool ControlText::MouseOver( int x, int y )
429 {
430     if( x >= Left && x < Left + Width && y >= Top && y < Top + Height )
431         return true;
432     else
433         return false;
434 }
435 //---------------------------------------------------------------------------
436 bool ControlText::MouseDblClick( int x, int y, int button )
437 {
438     Selected = false;
439     if( x >= Left && x < Left + Width && y >= Top && y < Top + Height
440         && button == 1 && DisplayList.size() > 1 )
441     {
442         Display++;
443         if( Display == DisplayList.end() )
444             Display = DisplayList.begin();
445         return true;
446     }
447     else
448     {
449         return false;
450     }
451 }
452 //---------------------------------------------------------------------------
453