]> git.sesse.net Git - vlc/blob - modules/gui/skins/controls/playlist.cpp
* changed "Font" into "SkinFont" (see previous commit)
[vlc] / modules / gui / skins / controls / playlist.cpp
1 /*****************************************************************************
2  * playlist.cpp: Playlist control
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: playlist.cpp,v 1.9 2003/04/21 22:12:37 asmax 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 //--- GENERAL ---------------------------------------------------------------
28 #include <math.h>
29
30 //--- VLC -------------------------------------------------------------------
31 #include <vlc/intf.h>
32
33 //--- SKIN ------------------------------------------------------------------
34 #include "../os_api.h"
35 #include "../src/bitmap.h"
36 #include "../src/banks.h"
37 #include "../src/bezier.h"
38 #include "../src/graphics.h"
39 #include "../os_graphics.h"
40 #include "../src/font.h"
41 #include "../os_font.h"
42 #include "generic.h"
43 #include "slider.h"
44 #include "playlist.h"
45 #include "../src/event.h"
46 #include "../src/theme.h"
47 #include "../src/window.h"
48 #include "../src/skin_common.h"
49
50
51
52 //---------------------------------------------------------------------------
53 // Control Playlist
54 //---------------------------------------------------------------------------
55 ControlPlayList::ControlPlayList( string id, bool visible, int width,
56     int infowidth, string font, string playfont, int selcolor, double *ptx,
57     double *pty, int nb, bool longfilename, string help, SkinWindow *Parent )
58     : GenericControl( id, visible, help, Parent )
59 {
60     Left          = 0;
61     Top           = 0;
62     Column        = 1;
63     Line          = 1;
64     Margin        = 1;
65     Enabled       = true;
66     FontName      = font;
67     PlayFontName  = playfont;
68
69     // Text zone
70     CaseWidth    = width;
71     InfoWidth    = infowidth;
72     NumWidth     = 0;
73     FileWidth    = 0;
74     CaseHeight   = 1;
75     NumOfItems   = 0;
76     SelectColor  = selcolor;
77     TextCurve    = new Bezier( ptx, pty, nb, BEZIER_PTS_Y );
78     LongFileName = longfilename;
79
80     // Scroll
81     StartIndex  = 0;
82 }
83 //---------------------------------------------------------------------------
84 ControlPlayList::~ControlPlayList()
85 {
86     if( PlayList != NULL )
87     {
88         vlc_object_release( PlayList );
89     }
90 }
91 //---------------------------------------------------------------------------
92 void ControlPlayList::Init()
93 {
94     int i, j, h;
95     int *x, *y;
96
97     // Font & events
98     UpdateEvent = p_intf->p_sys->p_theme->EvtBank->Get( "playlist_refresh" );
99     TextFont    = p_intf->p_sys->p_theme->FntBank->Get( FontName );
100     if( PlayFontName == "none" )
101         PlayFont = p_intf->p_sys->p_theme->FntBank->Get( FontName );
102     else
103         PlayFont = p_intf->p_sys->p_theme->FntBank->Get( PlayFontName );
104
105     TextFont->GetSize( "lp", h, CaseHeight );
106
107     // Get bitmap from list
108     Img = NULL;
109
110     // Get points for Text curve
111     h  = TextCurve->GetNumOfDifferentPoints();
112     x  = new int[h + 1];
113     y  = new int[h + 1];
114     TextCurve->GetDifferentPoints( x, y, 0, 0 );
115
116     // Get top of first point
117     TextCurve->GetPoint( 0, i, TextTop );
118
119     // Set number of lines
120     Line = 0;
121     for( i = 0; i < h; i++ )
122     {
123         if( ( Line + 1 ) * CaseHeight < y[i] - TextTop )
124             Line++;
125     }
126     CaseLeft     = new int[Line];
127     CaseRight    = new int[Line];
128     CaseTextLeft = new int[Line];
129     for( i = 0; i < Line; i++ )
130     {
131         CaseLeft[i]     = x[i * CaseHeight];
132         CaseTextLeft[i] = x[i * CaseHeight];
133         for( j = 1; j < CaseHeight; j++ )
134         {
135             if( x[i * CaseHeight + j] < CaseLeft[i] )
136                 CaseLeft[i] = x[i * CaseHeight + j];
137             if( x[i * CaseHeight + j] > CaseTextLeft[i] )
138                 CaseTextLeft[i] = x[i * CaseHeight + j];
139         }
140         CaseRight[i] = CaseTextLeft[i] + CaseWidth;
141     }
142
143     // Get size of text zone
144     TextHeight = Line * CaseHeight;
145     TextLeft   = CaseLeft[0];
146     TextWidth  = CaseRight[0];
147     for( i = 1; i < Line; i++ )
148     {
149         if( CaseLeft[i] < TextLeft )
150             TextLeft = CaseLeft[i];
151         if( CaseRight[i] > TextWidth )
152             TextWidth = CaseRight[i];
153     }
154     TextWidth -= TextLeft;
155
156     // Set Text Clipping Region
157     TextClipRgn = (Region *)new OSRegion;
158     for( i = 0; i < Line; i++ )
159     {
160         for( j = 0; j < CaseHeight; j++ )
161         {
162             h = i * CaseHeight + j;
163             TextClipRgn->AddRectangle( x[h] - TextLeft, h, CaseWidth, 1 );
164         }
165     }
166
167     // Curve is no more needed so delete it
168     delete TextCurve;
169     delete[] x;
170     delete[] y;
171
172     // Get size of control
173     Left   = Slider->Left;
174     Top    = Slider->Top;
175     Width  = Slider->Left + Slider->Width;
176     Height = Slider->Top  + Slider->Height;
177     if( TextLeft < Left )
178         Left = TextLeft;
179     if( TextTop  < Top  )
180         Top  = TextTop;
181     if( TextLeft + TextWidth  > Width )
182         Width  = TextLeft + TextWidth;
183     if( TextTop + TextHeight > Height )
184         Height  = TextTop  + TextHeight;
185     Width  -= Left;
186     Height -= Top;
187
188     // Getting playlist
189     PlayList = (playlist_t *)
190         vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
191     if( PlayList == NULL )
192         msg_Err( p_intf, "cannot find a playlist object" );
193
194     Slider->Init();
195     Slider->Enable( p_intf->p_sys->p_theme->EvtBank->Get( "none" ), true );
196     RefreshList();
197 }
198 //---------------------------------------------------------------------------
199 bool ControlPlayList::ProcessEvent( Event *evt )
200 {
201     switch( evt->GetMessage() )
202     {
203         case CTRL_ENABLED:
204             Enable( (Event*)evt->GetParam1(), (bool)evt->GetParam2() );
205             break;
206
207         case CTRL_SYNCHRO:
208             if( UpdateEvent->IsEqual( (Event*)evt->GetParam1() ) )
209             {
210                 RefreshList();
211                 RefreshAll();
212             }
213             break;
214
215         case PLAYLIST_ID_DEL:
216             if( (GenericControl *)evt->GetParam1() == this )
217             {
218                 vlc_mutex_lock( &PlayList->object_lock );
219                 for( int i = PlayList->i_size - 1; i >= 0; i-- )
220                 {
221                     if( Select[i] && i != PlayList->i_index )
222                         playlist_Delete( PlayList, i );
223                 }
224                 vlc_mutex_unlock( &PlayList->object_lock );
225                 RefreshAll();
226             }
227             break;
228     }
229     return false;
230 }
231 //---------------------------------------------------------------------------
232 void ControlPlayList::RefreshList()
233 {
234     vlc_mutex_lock( &PlayList->object_lock );
235     
236     if( NumOfItems != PlayList->i_size )
237     {
238         if( NumOfItems > 0 )
239             delete Select;
240         NumOfItems = PlayList->i_size;
241         if( PlayList->i_size > 0 )
242         {
243             Select = new bool[NumOfItems];
244             for( int i = 0; i < NumOfItems; i++ )
245                 Select[i] = false;
246             int h;
247             sprintf( Num, " %i", NumOfItems + 1 );
248             TextFont->GetSize( Num, NumWidth, h);
249             FileWidth = CaseWidth - NumWidth - InfoWidth;
250         }
251
252         int Range = PlayList->i_size - Line * Column;
253         if( Range < 0 )
254             Range = 0;
255
256         Slider->ChangeSliderRange( Range );
257         StartIndex = Slider->GetCursorPosition();
258     }
259
260     vlc_mutex_unlock( &PlayList->object_lock );
261 }
262 //---------------------------------------------------------------------------
263 void ControlPlayList::RefreshAll()
264 {
265     ParentWindow->Refresh( TextLeft, TextTop, TextWidth, TextHeight );
266 }
267 //---------------------------------------------------------------------------
268 void ControlPlayList::Draw( int x, int y, int w, int h, Graphics *dest )
269 {
270     if( !Visible )
271         return;
272
273     int xI, yI, wI, hI;
274     // Slider Image
275     Slider->Draw( x, y, w, h, dest );
276
277     // TextZone
278     if( GetIntersectRgn( x, y, w, h, TextLeft, TextTop, TextWidth, TextHeight,
279                          xI, yI, wI, hI) )
280     {
281         // Change clipping region
282         Region *destClipRgn = (Region *)new OSRegion( 0, 0, w, h );
283         TextClipRgn->Move( TextLeft - x, TextTop - y );
284         dest->SetClipRegion( TextClipRgn );
285
286         // Draw each line
287         DrawAllCase( dest, x, y, wI, hI );
288
289         // Reset clipping region to old region
290         dest->SetClipRegion( destClipRgn );
291         delete destClipRgn;
292         TextClipRgn->Move( x - TextLeft, y - TextTop );
293     }
294 }
295 //---------------------------------------------------------------------------
296 void ControlPlayList::DrawAllCase( Graphics *dest, int x, int y, int w, int h )
297 {
298     int i;
299     for( i = 0; i < NumOfItems - StartIndex && i < Line * Column; i++ )
300     {
301         DrawCase( dest, i + StartIndex, x, y, w, h );
302     }
303 }
304 //---------------------------------------------------------------------------
305 void ControlPlayList::DrawCase( Graphics *dest, int i, int x, int y, int w,
306                                 int h )
307 {
308     // Test if case is in range
309     int j = i - StartIndex;
310     if( j < 0 || j >= Line * Column )
311         return;
312
313     // Draw background if selected
314     if( Select[i] )
315     {
316         dest->DrawRect(
317             CaseLeft[j] - x,
318             TextTop + j * CaseHeight - y,
319             CaseRight[j] - CaseLeft[j],
320             CaseHeight,
321             SelectColor
322         );
323     }
324
325     // Choose font
326     SkinFont *F;
327     if( PlayList->i_index == i )
328         F = PlayFont;
329     else
330         F = TextFont;
331
332     // Print number
333     sprintf( Num, "%i", i + 1 );
334     F->Print( dest,
335         Num,
336         CaseTextLeft[j] - x, TextTop + j * CaseHeight - y,
337         NumWidth - Margin, CaseHeight, VLC_FONT_ALIGN_RIGHT );
338
339     // Print name
340     F->Print( dest,
341         GetFileName( i ),
342         NumWidth + Margin + CaseTextLeft[j] - x,
343         TextTop + j * CaseHeight - y,
344         FileWidth - 2 * Margin, CaseHeight, VLC_FONT_ALIGN_LEFT );
345
346     // Print info
347     F->Print( dest,
348         "no info",
349         NumWidth + FileWidth + Margin + CaseTextLeft[j] - x,
350         TextTop + j * CaseHeight - y,
351         InfoWidth - Margin, CaseHeight, VLC_FONT_ALIGN_CENTER );
352 }
353 //---------------------------------------------------------------------------
354 char * ControlPlayList::GetFileName( int i )
355 {
356     if( LongFileName )
357     {
358         return PlayList->pp_items[i]->psz_name;
359     }
360     else
361     {
362         string f = PlayList->pp_items[i]->psz_name;
363         int pos  = f.rfind( DIRECTORY_SEPARATOR, f.size() );
364         return PlayList->pp_items[i]->psz_name + pos + 1;
365     }
366 }
367 //---------------------------------------------------------------------------
368 void ControlPlayList::MoveRelative( int xOff, int yOff )
369 {
370     Slider->MoveRelative( xOff, yOff );
371     Left     += xOff;
372     Top      += yOff;
373     TextLeft += xOff;
374     TextTop  += yOff;
375     for( int i = 1; i < Line; i++ )
376     {
377         CaseLeft[i]     += xOff;
378         CaseTextLeft[i] += xOff;
379         CaseRight[i]    += xOff;
380     }
381 }
382 //---------------------------------------------------------------------------
383 double ControlPlayList::Dist( int x1, int y1, int x2, int y2 )
384 {
385     return sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) );
386 }
387 //---------------------------------------------------------------------------
388 bool ControlPlayList::MouseDown( int x, int y, int button )
389 {
390     if( !Enabled )
391         return false;
392
393     // If hit into slider
394     if( Slider->MouseDown( x, y, button ) )
395     {
396         int New = Slider->GetCursorPosition();
397         if( New != StartIndex )
398         {
399             StartIndex = New;
400             ParentWindow->Refresh( TextLeft,TextTop,TextWidth,TextHeight );
401         }
402         return true;
403     }
404
405     if( !TextClipRgn->Hit( x - TextLeft, y - TextTop ) )
406         return false;
407
408     // If hit in a case
409     int i, j;
410     for( i = 0; i < PlayList->i_size - StartIndex && i < Line * Column; i++)
411     {
412         if( x >= CaseLeft[i] && x <= CaseRight[i] && y >= TextTop +
413             i * CaseHeight  && y < TextTop + (i + 1) * CaseHeight )
414         {
415             for( j = 0; j < NumOfItems; j++ )
416             {
417                 if( j == i + StartIndex )
418                     Select[j] = !Select[j];
419             }
420             RefreshAll();
421             return true;
422         }
423     }
424
425     return false;
426 }
427 //---------------------------------------------------------------------------
428 bool ControlPlayList::MouseUp( int x, int y, int button )
429 {
430     if( !Enabled )
431         return false;
432
433     // If hit into slider
434     if( Slider->MouseUp( x, y, button ) )
435         return true;
436
437     return false;
438 }
439 //---------------------------------------------------------------------------
440 bool ControlPlayList::MouseMove( int x, int y, int button )
441 {
442     if( !Enabled || !button )
443         return false;
444
445     // If hit into slider
446     if( Slider->MouseMove( x, y, button ) )
447     {
448         int New = Slider->GetCursorPosition();
449         if( New != StartIndex )
450         {
451             StartIndex = New;
452             RefreshAll();
453         }
454         return true;
455     }
456
457     return false;
458 }
459 //---------------------------------------------------------------------------
460 bool ControlPlayList::MouseScroll( int x, int y, int direction )
461 {
462     if( !Enabled )
463         return false;
464
465     if( !TextClipRgn->Hit( x - Left, y - Top ) && !Slider->MouseOver( x, y ) )
466         return false;
467
468     long pos = StartIndex;
469     switch( direction )
470     {
471         case MOUSE_SCROLL_UP:
472             if( pos > 0 ) pos--;
473             break;
474         case MOUSE_SCROLL_DOWN:
475             if( pos + Line  < NumOfItems ) pos++;
476             break;
477     }
478     StartIndex = pos;
479     Slider->SetCursorPosition( pos );
480     RefreshAll();
481     return true;
482 }
483 //---------------------------------------------------------------------------
484 bool ControlPlayList::MouseOver( int x, int y )
485 {
486     if( TextClipRgn->Hit( x - Left, y - Top ) || Slider->MouseOver( x, y ) )
487         return true;
488     else
489         return false;
490 }
491 //---------------------------------------------------------------------------
492 bool ControlPlayList::MouseDblClick( int x, int y, int button )
493 {
494     if( !Enabled || button != 1 )
495         return false;
496
497     int i;
498
499     if( !TextClipRgn->Hit( x - TextLeft, y - TextTop ) )
500         return false;
501
502     for( i = 0; i < PlayList->i_size - StartIndex && i < Line * Column; i++ )
503     {
504         if( x >= CaseLeft[i] && x <= CaseRight[i] && y >=
505             TextTop + i * CaseHeight  && y < TextTop + (i + 1) * CaseHeight )
506         {
507             playlist_Goto( PlayList, i + StartIndex );
508             OSAPI_PostMessage( NULL, VLC_INTF_REFRESH, 0, (int)false );
509             return true;
510         }
511     }
512     return false;
513 }
514 //---------------------------------------------------------------------------
515 bool ControlPlayList::ToolTipTest( int x, int y )
516 {
517     if( !Enabled )
518         return false;
519
520     int i, w, h;
521     for( i = 0; i < PlayList->i_size - StartIndex && i < Line * Column; i++ )
522     {
523         if( x >= CaseLeft[i] && x <= CaseRight[i] && y >=
524             TextTop + i * CaseHeight  && y < TextTop + (i + 1) * CaseHeight )
525         {
526             TextFont->GetSize( PlayList->pp_items[i + StartIndex]->psz_name, w,
527                                h );
528             if( w > FileWidth )
529             {
530                 ParentWindow->ChangeToolTipText(
531                     (string)PlayList->pp_items[i + StartIndex]->psz_name );
532                 return true;
533             }
534         }
535     }
536     return false;
537 }
538 //---------------------------------------------------------------------------
539 void ControlPlayList::InitSliderCurve( double *ptx, double *pty, int nb,
540                                        string scroll_up, string scroll_down )
541 {
542     Slider = new ControlSlider( "none", true, "none", scroll_up, scroll_down,
543         ptx, pty, nb, "none", "", ParentWindow );
544 }
545 //---------------------------------------------------------------------------
546