763f11c9695a0ff899dcde4780ec4c3d1d53856c
[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.11 2003/06/07 12:19:23 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     bool ScrollingTextTimer( void *data )
125     { 
126         if( (ControlText *)data != NULL
127             && !( (ControlText *)data )->GetSelected() )
128         {
129             ( (ControlText *)data )->DoScroll();
130         }
131         return True;
132     }
133
134     //-----------------------------------------------------------------------
135     void ControlText::StartScrolling()
136     {
137         X11Timer *timer = new X11Timer( g_pIntf, 100000, ScrollingTextTimer, 
138                                         (void*)this );
139         X11TimerManager *timerManager = X11TimerManager::Instance( g_pIntf );
140         timerManager->addTimer( timer );
141     }
142     //-----------------------------------------------------------------------
143     void ControlText::StopScrolling()
144     {
145     }
146     //-----------------------------------------------------------------------
147
148     #endif
149 //---------------------------------------------------------------------------
150
151
152
153
154 //---------------------------------------------------------------------------
155 // CONTROL TEXT
156 //---------------------------------------------------------------------------
157 ControlText::ControlText( string id, bool visible, int x, int y, string text,
158     string font, int align, int width, string display, bool scroll,
159     int scrollspace, string help, SkinWindow *Parent )
160     : GenericControl( id, visible, help, Parent )
161 {
162     InitLeft         = x;
163     Top              = y;
164     InitWidth        = width;
165     FontName         = font;
166     Text             = text;
167     Align            = align;
168     Selected         = false;
169
170     // Scrolling parameters
171     InitScroll       = scroll;
172     Scroll           = false;
173     ScrollSpace      = scrollspace;
174     PauseScroll      = false;
175
176     // Initialize display
177     if( display != "none" )
178     {
179         int begin = 0;
180         int pos = display.find( ';', 0 );
181         while( pos > 0 )
182         {
183             DisplayList.push_back( display.substr( begin, pos - begin ) );
184             begin = pos + 1;
185             pos = display.find( ';', begin );
186         }
187         DisplayList.push_back(
188             display.substr( begin, display.size() - begin ) );
189         Display = DisplayList.begin();
190     }
191
192 }
193 //---------------------------------------------------------------------------
194 ControlText::~ControlText()
195 {
196     if( TextClipRgn != NULL )
197         delete TextClipRgn;
198     TextWidth = 0;
199     SetScrolling();
200 }
201 //---------------------------------------------------------------------------
202 void ControlText::Init()
203 {
204     TextFont     = p_intf->p_sys->p_theme->FntBank->Get( FontName );
205
206     // Init clipping region
207     TextClipRgn = NULL;
208
209     // Get size of control
210     SetSize();
211     SetScrolling();
212 }
213 //---------------------------------------------------------------------------
214 void ControlText::SetScrolling()
215 {
216     if( !Scroll && TextWidth > Width )
217     {
218         if( InitScroll )
219         {
220             Scroll = true;
221             StartScrolling();
222         }
223     }
224     else if( Scroll && TextWidth <= Width )
225     {
226         Scroll = false;
227         StopScrolling();
228     }
229 }
230 //---------------------------------------------------------------------------
231 void ControlText::SetSize()
232 {
233     // Get size parameters
234     int w, h;
235     TextFont->GetSize( Text, w, h );
236     TextWidth = w;
237
238     // Get width if not set
239     if( InitWidth <= 0 )
240         Width  = w;
241     else
242         Width  = InitWidth;
243
244     // Set height
245     Height = h;
246
247     // Set position wether alignment
248     if( Align == VLC_FONT_ALIGN_CENTER )
249     {
250         Left     = InitLeft - Width / 2;
251         TextLeft = InitLeft - TextWidth / 2;
252     }
253     else if( Align == VLC_FONT_ALIGN_RIGHT )
254     {
255         Left     = InitLeft - Width;
256         TextLeft = InitLeft - TextWidth;
257     }
258     else
259     {
260         Left     = InitLeft;
261         TextLeft = InitLeft;
262     }
263
264     // Create clipping region
265     if( TextClipRgn != NULL )
266         delete TextClipRgn;
267
268     TextClipRgn = (SkinRegion *)new OSRegion( Left, Top, Width, Height );
269
270 }
271 //---------------------------------------------------------------------------
272 bool ControlText::ProcessEvent( Event *evt )
273 {
274     unsigned int msg = evt->GetMessage();
275     unsigned int p1  = evt->GetParam1();
276     long         p2  = evt->GetParam2();
277
278     switch( msg )
279     {
280         case CTRL_SET_TEXT:
281             if( DisplayList.size() > 0 )
282             {
283                 if( p_intf->p_sys->p_theme->EvtBank->Get( (*Display) )
284                     ->IsEqual( (Event*)p1 ) )
285                 {
286                     SetText( (char *)p2 );
287                 }
288             }
289             break;
290     }
291     return false;
292 }
293 //---------------------------------------------------------------------------
294 void ControlText::Draw( int x, int y, int w, int h, Graphics *dest )
295 {
296     if( !Visible )
297         return;
298
299     // Test if control is in refresh zone
300     int xI, yI, wI, hI;
301     if( !GetIntersectRgn( x,y,w,h, Left,Top,Width,Height, xI,yI,wI,hI) )
302         return;
303
304     // Change clipping region
305     TextClipRgn->Move( -x, -y );
306     dest->SetClipRegion( TextClipRgn );
307
308     // Draw text
309     if( TextWidth <= Width || !Scroll )
310     {
311         TextFont->Print( dest, Text, Left - x, Top - y, Width, Height, Align );
312     }
313     else
314     {
315         if( TextLeft > Left + ScrollSpace )
316         {
317             TextFont->Print( dest, Text, TextLeft - x, Top - y,
318                          TextWidth, Height, Align );
319             TextFont->Print( dest, Text, TextLeft - x - TextWidth - ScrollSpace,
320                          Top - y, TextWidth, Height, Align );
321         }
322         else if( TextLeft + TextWidth + ScrollSpace < Left + Width )
323         {
324             TextFont->Print( dest, Text, TextLeft - x, Top - y,
325                          TextWidth, Height, Align );
326             TextFont->Print( dest, Text, TextLeft - x + TextWidth + ScrollSpace,
327                          Top - y, TextWidth, Height, Align );
328         }
329         else
330         {
331             TextFont->Print( dest, Text, TextLeft - x, Top - y,
332                          TextWidth, Height, Align );
333         }
334     }
335
336     // Reset clipping region to old region
337     SkinRegion *destClipRgn = (SkinRegion *)new OSRegion( 0, 0, w, h );
338     dest->SetClipRegion( destClipRgn );
339     delete destClipRgn;
340     TextClipRgn->Move( x, y );
341 }
342 //---------------------------------------------------------------------------
343 void ControlText::SetText( const string newText )
344 {
345     if( Text != newText )
346     {
347         Selected = false;
348         Text     = newText;
349         SetSize();
350         SetScrolling();
351         ParentWindow->Refresh( Left, Top, Width, Height );
352     }
353 }
354 //---------------------------------------------------------------------------
355 void ControlText::DoScroll()
356 {
357     if( !PauseScroll )
358     {
359         TextLeft -= 2;
360         if( TextLeft + TextWidth < Left )
361             TextLeft += TextWidth + ScrollSpace;
362
363         ParentWindow->Refresh( Left, Top, Width, Height );
364     }
365 }
366 //---------------------------------------------------------------------------
367 void ControlText::MoveRelative( int xOff, int yOff )
368 {
369     InitLeft += xOff;
370     Top      += yOff;
371     SetSize();
372 }
373 //---------------------------------------------------------------------------
374 bool ControlText::MouseUp( int x, int y, int button )
375 {
376     Selected = false;
377     if( MouseOver( x, y ) && button == 1 )
378     {
379         if( DisplayList.size() > 1 || TextWidth > Width )
380             return true;
381     }
382     return false;
383
384 }
385 //---------------------------------------------------------------------------
386 bool ControlText::MouseDown( int x, int y, int button )
387 {
388     if( MouseOver( x, y ) && button == 1 )
389     {
390         if( TextWidth > Width )
391         {
392             PauseScroll = !PauseScroll;
393             OSAPI_GetMousePos( MouseX, MouseY );
394             SelectedX = MouseX;
395             Selected = true;
396             return true;
397         }
398         else if( DisplayList.size() > 1 )
399         {
400             return true;
401         }
402     }
403     return false;
404 }
405 //---------------------------------------------------------------------------
406 bool ControlText::MouseMove( int x, int y, int button )
407 {
408     if( Selected && button == 1 )
409     {
410         OSAPI_GetMousePos( MouseX, MouseY );
411
412         if( MouseX != SelectedX )
413         {
414             TextLeft += MouseX - SelectedX;
415             SelectedX = MouseX;
416
417             while( TextLeft + TextWidth < Left )
418                 TextLeft += TextWidth + ScrollSpace;
419
420             while( TextLeft > Left + ScrollSpace )
421                 TextLeft -= TextWidth + ScrollSpace;
422
423             ParentWindow->Refresh( Left, Top, Width, Height );
424         }
425     }
426     return false;
427 }
428 //---------------------------------------------------------------------------
429 bool ControlText::MouseOver( int x, int y )
430 {
431     if( x >= Left && x < Left + Width && y >= Top && y < Top + Height )
432         return true;
433     else
434         return false;
435 }
436 //---------------------------------------------------------------------------
437 bool ControlText::MouseDblClick( int x, int y, int button )
438 {
439     Selected = false;
440     if( x >= Left && x < Left + Width && y >= Top && y < Top + Height
441         && button == 1 && DisplayList.size() > 1 )
442     {
443         Display++;
444         if( Display == DisplayList.end() )
445             Display = DisplayList.begin();
446         return true;
447     }
448     else
449     {
450         return false;
451     }
452 }
453 //---------------------------------------------------------------------------
454