]> git.sesse.net Git - vlc/blob - modules/gui/skins/controls/playlist.cpp
* modules/gui/skins/*: we now #include skin files using a relative
[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.2 2003/04/16 21:40:07 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 //--- 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, Window *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                 for( int i = PlayList->i_size - 1; i >= 0; i-- )
219                 {
220                     if( Select[i] && i != PlayList->i_index )
221                         playlist_Delete( PlayList, i );
222                 }
223                 RefreshAll();
224             }
225             break;
226     }
227     return false;
228 }
229 //---------------------------------------------------------------------------
230 void ControlPlayList::RefreshList()
231 {
232     if( NumOfItems != PlayList->i_size )
233     {
234         if( NumOfItems > 0 )
235             delete Select;
236         NumOfItems = PlayList->i_size;
237         if( PlayList->i_size > 0 )
238         {
239             Select = new bool[NumOfItems];
240             for( int i = 0; i < NumOfItems; i++ )
241                 Select[i] = false;
242             int h;
243             sprintf( Num, " %i", NumOfItems + 1 );
244             TextFont->GetSize( Num, NumWidth, h);
245             FileWidth = CaseWidth - NumWidth - InfoWidth;
246         }
247
248         int Range = PlayList->i_size - Line * Column;
249         if( Range < 0 )
250             Range = 0;
251
252         Slider->ChangeSliderRange( Range );
253         StartIndex = Slider->GetCursorPosition();
254     }
255 }
256 //---------------------------------------------------------------------------
257 void ControlPlayList::RefreshAll()
258 {
259     ParentWindow->Refresh( TextLeft, TextTop, TextWidth, TextHeight );
260 }
261 //---------------------------------------------------------------------------
262 void ControlPlayList::Draw( int x, int y, int w, int h, Graphics *dest )
263 {
264     if( !Visible )
265         return;
266
267     int xI, yI, wI, hI;
268     // Slider Image
269     Slider->Draw( x, y, w, h, dest );
270
271     // TextZone
272     if( GetIntersectRgn( x, y, w, h, TextLeft, TextTop, TextWidth, TextHeight,
273                          xI, yI, wI, hI) )
274     {
275         // Change clipping region
276         Region *destClipRgn = (Region *)new OSRegion( 0, 0, w, h );
277         TextClipRgn->Move( TextLeft - x, TextTop - y );
278         dest->SetClipRegion( TextClipRgn );
279
280         // Draw each line
281         DrawAllCase( dest, x, y, wI, hI );
282
283         // Reset clipping region to old region
284         dest->SetClipRegion( destClipRgn );
285         delete destClipRgn;
286         TextClipRgn->Move( x - TextLeft, y - TextTop );
287     }
288 }
289 //---------------------------------------------------------------------------
290 void ControlPlayList::DrawAllCase( Graphics *dest, int x, int y, int w, int h )
291 {
292     int i;
293     for( i = 0; i < PlayList->i_size - StartIndex && i < Line * Column; i++ )
294     {
295         DrawCase( dest, i + StartIndex, x, y, w, h );
296     }
297 }
298 //---------------------------------------------------------------------------
299 void ControlPlayList::DrawCase( Graphics *dest, int i, int x, int y, int w,
300                                 int h )
301 {
302     // Test if case is in range
303     int j = i - StartIndex;
304     if( j < 0 || j >= Line * Column )
305         return;
306
307     // Draw background if selected
308     if( Select[i] )
309     {
310         dest->DrawRect(
311             CaseLeft[j] - x,
312             TextTop + j * CaseHeight - y,
313             CaseRight[j] - CaseLeft[j],
314             CaseHeight,
315             SelectColor
316         );
317     }
318
319     // Choose font
320     Font *F;
321     if( PlayList->i_index == i )
322         F = PlayFont;
323     else
324         F = TextFont;
325
326     // Print number
327     sprintf( Num, "%i", i + 1 );
328     F->Print( dest,
329         Num,
330         CaseTextLeft[j] - x, TextTop + j * CaseHeight - y,
331         NumWidth - Margin, CaseHeight, DT_RIGHT );
332
333     // Print name
334     F->Print( dest,
335         GetFileName( i ),
336         NumWidth + Margin + CaseTextLeft[j] - x,
337         TextTop + j * CaseHeight - y,
338         FileWidth - 2 * Margin, CaseHeight, DT_LEFT );
339
340     // Print info
341     F->Print( dest,
342         "no info",
343         NumWidth + FileWidth + Margin + CaseTextLeft[j] - x,
344         TextTop + j * CaseHeight - y,
345         InfoWidth - Margin, CaseHeight, DT_CENTER );
346 }
347 //---------------------------------------------------------------------------
348 char * ControlPlayList::GetFileName( int i )
349 {
350     if( LongFileName )
351     {
352         return PlayList->pp_items[i]->psz_name;
353     }
354     else
355     {
356         string f = PlayList->pp_items[i]->psz_name;
357         int pos  = f.rfind( DIRECTORY_SEPARATOR, f.size() );
358         return PlayList->pp_items[i]->psz_name + pos + 1;
359     }
360 }
361 //---------------------------------------------------------------------------
362 void ControlPlayList::MoveRelative( int xOff, int yOff )
363 {
364     Slider->MoveRelative( xOff, yOff );
365     Left     += xOff;
366     Top      += yOff;
367     TextLeft += xOff;
368     TextTop  += yOff;
369     for( int i = 1; i < Line; i++ )
370     {
371         CaseLeft[i]     += xOff;
372         CaseTextLeft[i] += xOff;
373         CaseRight[i]    += xOff;
374     }
375 }
376 //---------------------------------------------------------------------------
377 double ControlPlayList::Dist( int x1, int y1, int x2, int y2 )
378 {
379     return sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) );
380 }
381 //---------------------------------------------------------------------------
382 bool ControlPlayList::MouseDown( int x, int y, int button )
383 {
384     if( !Enabled )
385         return false;
386
387     // If hit into slider
388     if( Slider->MouseDown( x, y, button ) )
389     {
390         int New = Slider->GetCursorPosition();
391         if( New != StartIndex )
392         {
393             StartIndex = New;
394             ParentWindow->Refresh( TextLeft,TextTop,TextWidth,TextHeight );
395         }
396         return true;
397     }
398
399     if( !TextClipRgn->Hit( x - TextLeft, y - TextTop ) )
400         return false;
401
402     // If hit in a case
403     int i, j;
404     for( i = 0; i < PlayList->i_size - StartIndex && i < Line * Column; i++)
405     {
406         if( x >= CaseLeft[i] && x <= CaseRight[i] && y >= TextTop +
407             i * CaseHeight  && y < TextTop + (i + 1) * CaseHeight )
408         {
409             for( j = 0; j < NumOfItems; j++ )
410             {
411                 if( j == i + StartIndex )
412                     Select[j] = !Select[j];
413             }
414             RefreshAll();
415             return true;
416         }
417     }
418
419     return false;
420 }
421 //---------------------------------------------------------------------------
422 bool ControlPlayList::MouseUp( int x, int y, int button )
423 {
424     if( !Enabled )
425         return false;
426
427     // If hit into slider
428     if( Slider->MouseUp( x, y, button ) )
429         return true;
430
431     return false;
432 }
433 //---------------------------------------------------------------------------
434 bool ControlPlayList::MouseMove( int x, int y, int button )
435 {
436     if( !Enabled || !button )
437         return false;
438
439     // If hit into slider
440     if( Slider->MouseMove( x, y, button ) )
441     {
442         int New = Slider->GetCursorPosition();
443         if( New != StartIndex )
444         {
445             StartIndex = New;
446             RefreshAll();
447         }
448         return true;
449     }
450
451     return false;
452 }
453 //---------------------------------------------------------------------------
454 bool ControlPlayList::MouseOver( int x, int y )
455 {
456     if( TextClipRgn->Hit( x - Left, y - Top ) || Slider->MouseOver( x, y ) )
457         return true;
458     else
459         return false;
460 }
461 //---------------------------------------------------------------------------
462 bool ControlPlayList::MouseDblClick( int x, int y, int button )
463 {
464     if( !Enabled || button != 1 )
465         return false;
466
467     int i;
468
469     if( !TextClipRgn->Hit( x - TextLeft, y - TextTop ) )
470         return false;
471
472     for( i = 0; i < PlayList->i_size - StartIndex && i < Line * Column; i++ )
473     {
474         if( x >= CaseLeft[i] && x <= CaseRight[i] && y >=
475             TextTop + i * CaseHeight  && y < TextTop + (i + 1) * CaseHeight )
476         {
477             playlist_Goto( PlayList, i + StartIndex );
478             OSAPI_PostMessage( NULL, VLC_INTF_REFRESH, 0, (int)false );
479             return true;
480         }
481     }
482     return false;
483 }
484 //---------------------------------------------------------------------------
485 bool ControlPlayList::ToolTipTest( int x, int y )
486 {
487     if( !Enabled )
488         return false;
489
490     int i, w, h;
491     for( i = 0; i < PlayList->i_size - StartIndex && i < Line * Column; i++ )
492     {
493         if( x >= CaseLeft[i] && x <= CaseRight[i] && y >=
494             TextTop + i * CaseHeight  && y < TextTop + (i + 1) * CaseHeight )
495         {
496             TextFont->GetSize( PlayList->pp_items[i + StartIndex]->psz_name, w,
497                                h );
498             if( w > FileWidth )
499             {
500                 ParentWindow->ChangeToolTipText(
501                     (string)PlayList->pp_items[i + StartIndex]->psz_name );
502                 return true;
503             }
504         }
505     }
506     return false;
507 }
508 //---------------------------------------------------------------------------
509 void ControlPlayList::InitSliderCurve( double *ptx, double *pty, int nb,
510                                        string scroll_up, string scroll_down )
511 {
512     Slider = new ControlSlider( "none", true, "none", scroll_up, scroll_down,
513         ptx, pty, nb, "none", "", ParentWindow );
514 }
515 //---------------------------------------------------------------------------
516