]> git.sesse.net Git - vlc/blob - modules/gui/beos/ListViews.cpp
Removes trailing spaces. Removes tabs.
[vlc] / modules / gui / beos / ListViews.cpp
1 /*****************************************************************************
2  * ListViews.h: BeOS interface list view class implementation
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Stephan Aßmus <stippi@yellowbites.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #if 0
25
26 #include <malloc.h>
27
28 #include <Bitmap.h>
29 #include <Entry.h>
30 #include <String.h>
31
32 /* VLC headers */
33 #include <vlc/vlc.h>
34 #include <vlc_interface.h>
35
36 #include "InterfaceWindow.h"
37 #include "ListViews.h"
38 #include "MsgVals.h"
39
40 #define MAX_DRAG_HEIGHT        200.0
41 #define ALPHA                170
42 #define TEXT_OFFSET            20.0
43
44 /*****************************************************************************
45  * PlaylistItem class
46  *****************************************************************************/
47 PlaylistItem::PlaylistItem( const char *name )
48     : BStringItem( name ),
49       fName( "" )
50 {
51     entry_ref ref;
52     if ( get_ref_for_path( name, &ref) == B_OK )
53         fName.SetTo( ref.name );
54 }
55
56 PlaylistItem::~PlaylistItem()
57 {
58 }
59
60 /*****************************************************************************
61  * PlaylistItem::DrawItem
62  *****************************************************************************/
63 void
64 PlaylistItem::Draw( BView *owner, BRect frame, bool tintedLine,
65                     uint32 mode, bool active, bool playing )
66 {
67     rgb_color color = (rgb_color){ 255, 255, 255, 255 };
68     if ( tintedLine )
69         color = tint_color( color, 1.04 );
70     // background
71     if ( IsSelected() )
72         color = tint_color( color, B_DARKEN_2_TINT );
73     owner->SetLowColor( color );
74     owner->FillRect( frame, B_SOLID_LOW );
75     // label
76     owner->SetHighColor( 0, 0, 0, 255 );
77     font_height fh;
78     owner->GetFontHeight( &fh );
79     const char* text = Text();
80     switch ( mode )
81     {
82         case DISPLAY_NAME:
83             if ( fName.CountChars() > 0 )
84                 text = fName.String();
85             break;
86         case DISPLAY_PATH:
87         default:
88             break;
89     }
90     BString truncatedString( text );
91     owner->TruncateString( &truncatedString, B_TRUNCATE_MIDDLE,
92                            frame.Width() - TEXT_OFFSET - 4.0 );
93     owner->DrawString( truncatedString.String(),
94                        BPoint( frame.left + TEXT_OFFSET,
95                                frame.top + fh.ascent + 1.0 ) );
96     // playmark
97     if ( active )
98     {
99         rgb_color black = (rgb_color){ 0, 0, 0, 255 };
100         rgb_color green = (rgb_color){ 0, 255, 0, 255 };
101         BRect r( 0.0, 0.0, 10.0, 10.0 );
102         r.OffsetTo( frame.left + 4.0,
103                     ceilf( ( frame.top + frame.bottom ) / 2.0 ) - 5.0 );
104         if ( !playing )
105             green = tint_color( color, B_DARKEN_1_TINT );
106         rgb_color lightGreen = tint_color( green, B_LIGHTEN_2_TINT );
107         rgb_color darkGreen = tint_color( green, B_DARKEN_2_TINT );
108         BPoint arrow[3];
109         arrow[0] = r.LeftTop();
110         arrow[1] = r.LeftBottom();
111         arrow[2].x = r.right;
112         arrow[2].y = ( r.top + r.bottom ) / 2.0;
113         owner->BeginLineArray( 6 );
114             // black outline
115             owner->AddLine( arrow[0], arrow[1], black );
116             owner->AddLine( BPoint( arrow[1].x + 1.0, arrow[1].y - 1.0 ),
117                             arrow[2], black );
118             owner->AddLine( arrow[0], arrow[2], black );
119             // inset arrow
120             arrow[0].x += 1.0;
121             arrow[0].y += 2.0;
122             arrow[1].x += 1.0;
123             arrow[1].y -= 2.0;
124             arrow[2].x -= 2.0;
125             // highlights and shadow
126             owner->AddLine( arrow[1], arrow[2], darkGreen );
127             owner->AddLine( arrow[0], arrow[2], lightGreen );
128             owner->AddLine( arrow[0], arrow[1], lightGreen );
129         owner->EndLineArray();
130         // fill green
131         arrow[0].x += 1.0;
132         arrow[0].y += 1.0;
133         arrow[1].x += 1.0;
134         arrow[1].y -= 1.0;
135         arrow[2].x -= 2.0;
136         owner->SetHighColor( green );
137         owner->FillPolygon( arrow, 3 );
138     }
139 }
140
141 /*****************************************************************************
142  * DragSortableListView class
143  *****************************************************************************/
144 DragSortableListView::DragSortableListView( BRect frame, const char* name,
145                                             list_view_type type, uint32 resizingMode,
146                                             uint32 flags )
147     : BListView( frame, name, type, resizingMode, flags ),
148       fDropRect( 0.0, 0.0, -1.0, -1.0 ),
149       fDropIndex( -1 )
150 {
151     SetViewColor( B_TRANSPARENT_32_BIT );
152 }
153
154 DragSortableListView::~DragSortableListView()
155 {
156 }
157
158 /*****************************************************************************
159  * DragSortableListView::Draw
160  *****************************************************************************/
161 void
162 DragSortableListView::Draw( BRect updateRect )
163 {
164     int32 firstIndex = IndexOf( updateRect.LeftTop() );
165     int32 lastIndex = IndexOf( updateRect.RightBottom() );
166     if ( firstIndex >= 0 )
167     {
168         if ( lastIndex < firstIndex )
169             lastIndex = CountItems() - 1;
170         // update rect contains items
171         BRect r( updateRect );
172         for ( int32 i = firstIndex; i <= lastIndex; i++)
173         {
174             r = ItemFrame( i );
175             DrawListItem( this, i, r );
176         }
177         updateRect.top = r.bottom + 1.0;
178         if ( updateRect.IsValid() )
179         {
180             SetLowColor( 255, 255, 255, 255 );
181             FillRect( updateRect, B_SOLID_LOW );
182         }
183     }
184     else
185     {
186         SetLowColor( 255, 255, 255, 255 );
187         FillRect( updateRect, B_SOLID_LOW );
188     }
189     // drop anticipation indication
190     if ( fDropRect.IsValid() )
191     {
192         SetHighColor( 255, 0, 0, 255 );
193         StrokeRect( fDropRect );
194     }
195 }
196
197 /*****************************************************************************
198  * DragSortableListView::InitiateDrag
199  *****************************************************************************/
200 bool
201 DragSortableListView::InitiateDrag( BPoint point, int32 index, bool )
202 {
203     bool success = false;
204     BListItem* item = ItemAt( CurrentSelection( 0 ) );
205     if ( !item )
206     {
207         // workarround a timing problem
208         Select( index );
209         item = ItemAt( index );
210     }
211     if ( item )
212     {
213         // create drag message
214         BMessage msg( B_SIMPLE_DATA );
215         MakeDragMessage( &msg );
216         // figure out drag rect
217         float width = Bounds().Width();
218         BRect dragRect(0.0, 0.0, width, -1.0);
219         // figure out, how many items fit into our bitmap
220         int32 numItems;
221         bool fade = false;
222         for (numItems = 0; BListItem* item = ItemAt( CurrentSelection( numItems ) ); numItems++) {
223             dragRect.bottom += ceilf( item->Height() ) + 1.0;
224             if ( dragRect.Height() > MAX_DRAG_HEIGHT ) {
225                 fade = true;
226                 dragRect.bottom = MAX_DRAG_HEIGHT;
227                 numItems++;
228                 break;
229             }
230         }
231         BBitmap* dragBitmap = new BBitmap( dragRect, B_RGB32, true );
232         if ( dragBitmap && dragBitmap->IsValid() ) {
233             if ( BView *v = new BView( dragBitmap->Bounds(), "helper", B_FOLLOW_NONE, B_WILL_DRAW ) ) {
234                 dragBitmap->AddChild( v );
235                 dragBitmap->Lock();
236                 BRect itemBounds( dragRect) ;
237                 itemBounds.bottom = 0.0;
238                 // let all selected items, that fit into our drag_bitmap, draw
239                 for ( int32 i = 0; i < numItems; i++ ) {
240                     int32 index = CurrentSelection( i );
241                     BListItem* item = ItemAt( index );
242                     itemBounds.bottom = itemBounds.top + ceilf( item->Height() );
243                     if ( itemBounds.bottom > dragRect.bottom )
244                         itemBounds.bottom = dragRect.bottom;
245                     DrawListItem( v, index, itemBounds );
246                     itemBounds.top = itemBounds.bottom + 1.0;
247                 }
248                 // make a black frame arround the edge
249                 v->SetHighColor( 0, 0, 0, 255 );
250                 v->StrokeRect( v->Bounds() );
251                 v->Sync();
252  
253                 uint8 *bits = (uint8 *)dragBitmap->Bits();
254                 int32 height = (int32)dragBitmap->Bounds().Height() + 1;
255                 int32 width = (int32)dragBitmap->Bounds().Width() + 1;
256                 int32 bpr = dragBitmap->BytesPerRow();
257  
258                 if (fade) {
259                     for ( int32 y = 0; y < height - ALPHA / 2; y++, bits += bpr ) {
260                         uint8 *line = bits + 3;
261                         for (uint8 *end = line + 4 * width; line < end; line += 4)
262                             *line = ALPHA;
263                     }
264                     for ( int32 y = height - ALPHA / 2; y < height; y++, bits += bpr ) {
265                         uint8 *line = bits + 3;
266                         for (uint8 *end = line + 4 * width; line < end; line += 4)
267                             *line = (height - y) << 1;
268                     }
269                 } else {
270                     for ( int32 y = 0; y < height; y++, bits += bpr ) {
271                         uint8 *line = bits + 3;
272                         for (uint8 *end = line + 4 * width; line < end; line += 4)
273                             *line = ALPHA;
274                     }
275                 }
276                 dragBitmap->Unlock();
277                 success = true;
278             }
279         }
280         if (success)
281             DragMessage( &msg, dragBitmap, B_OP_ALPHA, BPoint( 0.0, 0.0 ) );
282         else {
283             delete dragBitmap;
284             DragMessage( &msg, dragRect.OffsetToCopy( point ), this );
285         }
286     }
287     return success;
288 }
289
290 /*****************************************************************************
291  * DragSortableListView::WindowActivated
292  *****************************************************************************/
293 void
294 DragSortableListView::WindowActivated( bool active )
295 {
296     // workarround for buggy focus indication of BScrollView
297     if ( BView* view = Parent() )
298         view->Invalidate();
299 }
300
301 /*****************************************************************************
302  * DragSortableListView::MessageReceived
303  *****************************************************************************/
304 void
305 DragSortableListView::MessageReceived(BMessage* message)
306 {
307     switch ( message->what )
308     {
309         case B_MODIFIERS_CHANGED:
310             ModifiersChanged();
311             break;
312         case B_SIMPLE_DATA:
313         {
314             DragSortableListView *list = NULL;
315             if ( message->FindPointer( "list", (void **)&list ) == B_OK
316                  && list == this )
317             {
318                 int32 count = CountItems();
319                 if ( fDropIndex < 0 || fDropIndex > count )
320                     fDropIndex = count;
321                 BList items;
322                 int32 index;
323                 for ( int32 i = 0; message->FindInt32( "index", i, &index ) == B_OK; i++ )
324                     if ( BListItem* item = ItemAt(index) )
325                         items.AddItem( (void*)item );
326                 if ( items.CountItems() > 0 )
327                 {
328                     if ( modifiers() & B_SHIFT_KEY )
329                         CopyItems( items, fDropIndex );
330                     else
331                         MoveItems( items, fDropIndex );
332                 }
333                 fDropIndex = -1;
334             }
335             break;
336         }
337         default:
338             BListView::MessageReceived( message );
339             break;
340     }
341 }
342
343 /*****************************************************************************
344  * DragSortableListView::MouseMoved
345  *****************************************************************************/
346 void
347 DragSortableListView::MouseMoved(BPoint where, uint32 transit, const BMessage *msg)
348 {
349     if ( msg && ( msg->what == B_SIMPLE_DATA || msg->what == MSG_SOUNDPLAY ) )
350     {
351         bool replaceAll = !msg->HasPointer("list") && !(modifiers() & B_SHIFT_KEY);
352         switch ( transit )
353         {
354             case B_ENTERED_VIEW:
355                 // remember drag message
356                 // this is needed to react on modifier changes
357                 fDragMessageCopy = *msg;
358             case B_INSIDE_VIEW:
359             {
360                 if ( replaceAll )
361                 {
362                     BRect r( Bounds() );
363                     r.bottom--;    // compensate for scrollbar offset
364                     _SetDropAnticipationRect( r );
365                     fDropIndex = -1;
366                 }
367                 else
368                 {
369                     // offset where by half of item height
370                     BRect r( ItemFrame( 0 ) );
371                     where.y += r.Height() / 2.0;
372  
373                     int32 index = IndexOf( where );
374                     if ( index < 0 )
375                         index = CountItems();
376                     _SetDropIndex( index );
377                 }
378                 break;
379             }
380             case B_EXITED_VIEW:
381                 // forget drag message
382                 fDragMessageCopy.what = 0;
383             case B_OUTSIDE_VIEW:
384                 _RemoveDropAnticipationRect();
385                 break;
386         }
387     }
388     else
389     {
390         _RemoveDropAnticipationRect();
391         BListView::MouseMoved(where, transit, msg);
392         fDragMessageCopy.what = 0;
393     }
394 }
395
396 /*****************************************************************************
397  * DragSortableListView::MouseUp
398  *****************************************************************************/
399 void
400 DragSortableListView::MouseUp( BPoint where )
401 {
402     // remove drop mark
403     _SetDropAnticipationRect( BRect( 0.0, 0.0, -1.0, -1.0 ) );
404     // be sure to forget drag message
405     fDragMessageCopy.what = 0;
406     BListView::MouseUp( where );
407 }
408
409 /*****************************************************************************
410  * DragSortableListView::DrawItem
411  *****************************************************************************/
412 void
413 DragSortableListView::DrawItem( BListItem *item, BRect itemFrame, bool complete )
414 {
415     DrawListItem( this, IndexOf( item ), itemFrame );
416 }
417
418 /*****************************************************************************
419  * DragSortableListView::ModifiersChaned
420  *****************************************************************************/
421 void
422 DragSortableListView::ModifiersChanged()
423 {
424     BPoint where;
425     uint32 buttons;
426     GetMouse( &where, &buttons, false );
427     uint32 transit = Bounds().Contains( where ) ? B_INSIDE_VIEW : B_OUTSIDE_VIEW;
428     MouseMoved( where, transit, &fDragMessageCopy );
429 }
430
431 /*****************************************************************************
432  * DragSortableListView::MoveItems
433  *****************************************************************************/
434 void
435 DragSortableListView::MoveItems( BList& items, int32 index )
436 {
437     DeselectAll();
438     // we remove the items while we look at them, the insertion index is decreased
439     // when the items index is lower, so that we insert at the right spot after
440     // removal
441     BList removedItems;
442     int32 count = items.CountItems();
443     for ( int32 i = 0; i < count; i++ )
444     {
445         BListItem* item = (BListItem*)items.ItemAt( i );
446         int32 removeIndex = IndexOf( item );
447         if ( RemoveItem( item ) && removedItems.AddItem( (void*)item ) )
448         {
449             if ( removeIndex < index )
450                 index--;
451         }
452         // else ??? -> blow up
453     }
454     for ( int32 i = 0; BListItem* item = (BListItem*)removedItems.ItemAt( i ); i++ )
455     {
456         if ( AddItem( item, index ) )
457         {
458             // after we're done, the newly inserted items will be selected
459             Select( index, true );
460             // next items will be inserted after this one
461             index++;
462         }
463         else
464             delete item;
465     }
466 }
467
468 /*****************************************************************************
469  * DragSortableListView::CopyItems
470  *****************************************************************************/
471 void
472 DragSortableListView::CopyItems( BList& items, int32 index )
473 {
474     DeselectAll();
475     // by inserting the items after we copied all items first, we avoid
476     // cloning an item we already inserted and messing everything up
477     // in other words, don't touch the list before we know which items
478     // need to be cloned
479     BList clonedItems;
480     int32 count = items.CountItems();
481     for ( int32 i = 0; i < count; i++ )
482     {
483         BListItem* item = CloneItem( IndexOf( (BListItem*)items.ItemAt( i ) ) );
484         if ( item && !clonedItems.AddItem( (void*)item ) )
485             delete item;
486     }
487     for ( int32 i = 0; BListItem* item = (BListItem*)clonedItems.ItemAt( i ); i++ )
488     {
489         if ( AddItem( item, index ) )
490         {
491             // after we're done, the newly inserted items will be selected
492             Select( index, true );
493             // next items will be inserted after this one
494             index++;
495         }
496         else
497             delete item;
498     }
499 }
500
501 /*****************************************************************************
502  * DragSortableListView::RemoveItemList
503  *****************************************************************************/
504 void
505 DragSortableListView::RemoveItemList( BList& items )
506 {
507     int32 count = items.CountItems();
508     for ( int32 i = 0; i < count; i++ )
509     {
510         BListItem* item = (BListItem*)items.ItemAt( i );
511         if ( RemoveItem( item ) )
512             delete item;
513     }
514 }
515
516 /*****************************************************************************
517  * DragSortableListView::RemoveSelected
518  *****************************************************************************/
519 void
520 DragSortableListView::RemoveSelected()
521 {
522     BList items;
523     for ( int32 i = 0; BListItem* item = ItemAt( CurrentSelection( i ) ); i++ )
524         items.AddItem( (void*)item );
525     RemoveItemList( items );
526 }
527
528 /*****************************************************************************
529  * DragSortableListView::CountSelectedItems
530  *****************************************************************************/
531 int32
532 DragSortableListView::CountSelectedItems() const
533 {
534     int32 count = 0;
535     while ( CurrentSelection( count ) >= 0 )
536         count++;
537     return count;
538 }
539
540 /*****************************************************************************
541  * DragSortableListView::_SetDropAnticipationRect
542  *****************************************************************************/
543 void
544 DragSortableListView::_SetDropAnticipationRect( BRect r )
545 {
546     if ( fDropRect != r )
547     {
548         if ( fDropRect.IsValid() )
549             Invalidate( fDropRect );
550         fDropRect = r;
551         if ( fDropRect.IsValid() )
552             Invalidate( fDropRect );
553     }
554 }
555
556 /*****************************************************************************
557  * DragSortableListView::_SetDropAnticipationRect
558  *****************************************************************************/
559 void
560 DragSortableListView::_SetDropIndex( int32 index )
561 {
562     if ( fDropIndex != index )
563     {
564         fDropIndex = index;
565         if ( fDropIndex == -1 )
566             _SetDropAnticipationRect( BRect( 0.0, 0.0, -1.0, -1.0 ) );
567         else
568         {
569             int32 count = CountItems();
570             if ( fDropIndex == count )
571             {
572                 BRect r;
573                 if ( BListItem* item = ItemAt( count - 1 ) )
574                 {
575                     r = ItemFrame( count - 1 );
576                     r.top = r.bottom + 1.0;
577                     r.bottom = r.top + 1.0;
578                 }
579                 else
580                 {
581                     r = Bounds();
582                     r.bottom--;    // compensate for scrollbars moved slightly out of window
583                 }
584                 _SetDropAnticipationRect( r );
585             }
586             else
587             {
588                 BRect r = ItemFrame( fDropIndex );
589                 r.bottom = r.top + 1.0;
590                 _SetDropAnticipationRect( r );
591             }
592         }
593     }
594 }
595
596 /*****************************************************************************
597  * DragSortableListView::_RemoveDropAnticipationRect
598  *****************************************************************************/
599 void
600 DragSortableListView::_RemoveDropAnticipationRect()
601 {
602     _SetDropAnticipationRect( BRect( 0.0, 0.0, -1.0, -1.0 ) );
603     _SetDropIndex( -1 );
604 }
605
606
607 /*****************************************************************************
608  * PlaylistView class
609  *****************************************************************************/
610 PlaylistView::PlaylistView( intf_thread_t * _p_intf,
611                             BRect frame, InterfaceWindow* mainWindow,
612                             BMessage* selectionChangeMessage )
613     : DragSortableListView( frame, "playlist listview",
614                             B_MULTIPLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES,
615                             B_WILL_DRAW | B_NAVIGABLE | B_PULSE_NEEDED
616                             | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE ),
617       p_intf( _p_intf ),
618       fCurrentIndex( -1 ),
619       fPlaying( false ),
620       fDisplayMode( DISPLAY_PATH ),
621       fMainWindow( mainWindow ),
622       fSelectionChangeMessage( selectionChangeMessage ),
623       fLastClickedItem( NULL )
624 {
625 }
626
627 PlaylistView::~PlaylistView()
628 {
629     delete fSelectionChangeMessage;
630 }
631
632 /*****************************************************************************
633  * PlaylistView::AttachedToWindow
634  *****************************************************************************/
635 void
636 PlaylistView::AttachedToWindow()
637 {
638     // get pulse message every two frames
639     Window()->SetPulseRate( 80000 );
640 }
641
642 /*****************************************************************************
643  * PlaylistView::MessageReceived
644  *****************************************************************************/
645 void
646 PlaylistView::MessageReceived( BMessage* message)
647 {
648     switch ( message->what )
649     {
650         case MSG_SOUNDPLAY:
651         case B_SIMPLE_DATA:
652             if ( message->HasPointer( "list" ) )
653             {
654                 // message comes from ourself
655                 DragSortableListView::MessageReceived( message );
656             }
657             else
658             {
659                 // message comes from another app (for example Tracker)
660                 message->AddInt32( "drop index", fDropIndex );
661                 fMainWindow->PostMessage( message, fMainWindow );
662             }
663             break;
664         default:
665             DragSortableListView::MessageReceived( message );
666             break;
667     }
668 }
669
670 /*****************************************************************************
671  * PlaylistView::MouseDown
672  *****************************************************************************/
673 void
674 PlaylistView::MouseDown( BPoint where )
675 {
676     int32 clicks = 1;
677     Window()->CurrentMessage()->FindInt32( "clicks", &clicks );
678     bool handled = false;
679     for ( int32 i = 0; PlaylistItem* item = (PlaylistItem*)ItemAt( i ); i++ )
680     {
681         BRect r = ItemFrame( i );
682         if ( r.Contains( where ) )
683         {
684             if ( clicks == 2 )
685             {
686                 // only do something if user clicked the same item twice
687                 if ( fLastClickedItem == item )
688                 {
689                     playlist_t * p_playlist;
690                     p_playlist = (playlist_t *) vlc_object_find( p_intf,
691                         VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
692                     if( p_playlist )
693                     {
694                         playlist_Goto( p_playlist, i );
695                         vlc_object_release( p_playlist );
696                     }
697                     handled = true;
698                 }
699             }
700             else
701             {
702                 // remember last clicked item
703                 fLastClickedItem = item;
704                 if ( i == fCurrentIndex )
705                 {
706                     r.right = r.left + TEXT_OFFSET;
707                     if ( r.Contains ( where ) )
708                     {
709                         fMainWindow->PostMessage( PAUSE_PLAYBACK );
710                         InvalidateItem( i );
711                         handled = true;
712                     }
713                 }
714             }
715             break;
716         }
717     }
718     if ( !handled )
719         DragSortableListView::MouseDown(where);
720 }
721
722 /*****************************************************************************
723  * PlaylistView::KeyDown
724  *****************************************************************************/
725 void
726 PlaylistView::KeyDown( const char* bytes, int32 numBytes )
727 {
728     if ( numBytes < 1 )
729         return;
730  
731     if ( ( bytes[0] == B_BACKSPACE ) || ( bytes[0] == B_DELETE ) )
732     {
733         RemoveSelected();
734     }
735     DragSortableListView::KeyDown( bytes, numBytes );
736 }
737
738 /*****************************************************************************
739  * PlaylistView::Pulse
740  *****************************************************************************/
741 void
742 PlaylistView::Pulse()
743 {
744     if ( fMainWindow->IsStopped() )
745         SetPlaying( false );
746 }
747
748 /*****************************************************************************
749  * PlaylistView::SelectionChanged
750  *****************************************************************************/
751 void
752 PlaylistView::SelectionChanged()
753 {
754     BLooper* looper = Looper();
755     if ( fSelectionChangeMessage && looper )
756     {
757         BMessage message( *fSelectionChangeMessage );
758         looper->PostMessage( &message );
759     }
760 }
761
762
763 /*****************************************************************************
764  * PlaylistView::MoveItems
765  *****************************************************************************/
766 void
767 PlaylistView::MoveItems( BList& items, int32 index )
768 {
769 #if 0
770     DeselectAll();
771     // we remove the items while we look at them, the insertion index is decreased
772     // when the items index is lower, so that we insert at the right spot after
773     // removal
774     if ( fVlcWrapper->PlaylistLock() )
775     {
776         BList removedItems;
777         BList removeItems;
778         int32 count = items.CountItems();
779         int32 indexOriginal = index;
780         // remember currently playing item
781         BListItem* playingItem = _PlayingItem();
782         // collect item pointers for removal by index
783         for ( int32 i = 0; i < count; i++ )
784         {
785             int32 removeIndex = IndexOf( (BListItem*)items.ItemAt( i ) );
786             void* item = fVlcWrapper->PlaylistItemAt( removeIndex );
787             if ( item && removeItems.AddItem( item ) )
788             {
789                 if ( removeIndex < index )
790                     index--;
791             }
792             // else ??? -> blow up
793         }
794         // actually remove items using pointers
795         for ( int32 i = 0; i < count; i++ )
796         {
797             void* item = fVlcWrapper->PlaylistRemoveItem( removeItems.ItemAt( i ) );
798             if ( item && !removedItems.AddItem( item ) )
799                 free( item );
800         }
801         // add items at index
802         for ( int32 i = 0; void* item = removedItems.ItemAt( i ); i++ )
803         {
804             if ( fVlcWrapper->PlaylistAddItem( item, index ) )
805                 // next items will be inserted after this one
806                 index++;
807             else
808                 free( item );
809         }
810         // update GUI
811         DragSortableListView::MoveItems( items, indexOriginal );
812         // restore currently playing item
813         _SetPlayingIndex( playingItem );
814         // update interface (in case it isn't playing,
815         // there is a chance that it needs to update)
816         fMainWindow->PostMessage( MSG_UPDATE );
817         fVlcWrapper->PlaylistUnlock();
818     }
819 #endif
820 }
821
822 /*****************************************************************************
823  * PlaylistView::CopyItems
824  *****************************************************************************/
825 void
826 PlaylistView::CopyItems( BList& items, int32 toIndex )
827 {
828 #if 0
829     DeselectAll();
830     // we remove the items while we look at them, the insertion index is decreased
831     // when the items index is lower, so that we insert at the right spot after
832     // removal
833     if ( fVlcWrapper->PlaylistLock() )
834     {
835         BList clonedItems;
836         int32 count = items.CountItems();
837         // remember currently playing item
838         BListItem* playingItem = _PlayingItem();
839         // collect cloned item pointers
840         for ( int32 i = 0; i < count; i++ )
841         {
842             int32 index = IndexOf( (BListItem*)items.ItemAt( i ) );
843             void* item = fVlcWrapper->PlaylistItemAt( index );
844             void* cloned = fVlcWrapper->PlaylistCloneItem( item );
845             if ( cloned && !clonedItems.AddItem( cloned ) )
846                 free( cloned );
847  
848         }
849         // add cloned items at index
850         int32 index = toIndex;
851         for ( int32 i = 0; void* item = clonedItems.ItemAt( i ); i++ )
852         {
853             if ( fVlcWrapper->PlaylistAddItem( item, index ) )
854                 // next items will be inserted after this one
855                 index++;
856             else
857                 free( item );
858         }
859         // update GUI
860         DragSortableListView::CopyItems( items, toIndex );
861         // restore currently playing item
862         _SetPlayingIndex( playingItem );
863         // update interface (in case it isn't playing,
864         // there is a chance that it needs to update)
865         fMainWindow->PostMessage( MSG_UPDATE );
866         fVlcWrapper->PlaylistUnlock();
867     }
868 #endif
869 }
870
871 /*****************************************************************************
872  * PlaylistView::RemoveItemList
873  *****************************************************************************/
874 void
875 PlaylistView::RemoveItemList( BList& items )
876 {
877 #if 0
878     if ( fVlcWrapper->PlaylistLock() )
879     {
880         // remember currently playing item
881         BListItem* playingItem = _PlayingItem();
882         // collect item pointers for removal
883         BList removeItems;
884         int32 count = items.CountItems();
885         for ( int32 i = 0; i < count; i++ )
886         {
887             int32 index = IndexOf( (BListItem*)items.ItemAt( i ) );
888             void* item = fVlcWrapper->PlaylistItemAt( index );
889             if ( item && !removeItems.AddItem( item ) )
890                 free( item );
891         }
892         // remove items from playlist
893         count = removeItems.CountItems();
894         for ( int32 i = 0; void* item = removeItems.ItemAt( i ); i++ )
895         {
896             fVlcWrapper->PlaylistRemoveItem( item );
897         }
898         // update GUI
899         DragSortableListView::RemoveItemList( items );
900         // restore currently playing item
901         _SetPlayingIndex( playingItem );
902         // update interface (in case it isn't playing,
903         // there is a chance that it needs to update)
904         fMainWindow->PostMessage( MSG_UPDATE );
905         fVlcWrapper->PlaylistUnlock();
906     }
907 #endif
908 }
909
910 /*****************************************************************************
911  * PlaylistView::CloneItem
912  *****************************************************************************/
913 BListItem*
914 PlaylistView::CloneItem( int32 atIndex ) const
915 {
916     BListItem* clone = NULL;
917     if ( PlaylistItem* item = dynamic_cast<PlaylistItem*>( ItemAt( atIndex ) ) )
918         clone = new PlaylistItem( item->Text() );
919     return clone;
920 }
921
922 /*****************************************************************************
923  * PlaylistView::DrawListItem
924  *****************************************************************************/
925 void
926 PlaylistView::DrawListItem( BView* owner, int32 index, BRect frame ) const
927 {
928     if ( PlaylistItem* item = dynamic_cast<PlaylistItem*>( ItemAt( index ) ) )
929         item->Draw( owner,  frame, index % 2,
930                     fDisplayMode, index == fCurrentIndex, fPlaying );
931 }
932
933 /*****************************************************************************
934  * PlaylistView::MakeDragMessage
935  *****************************************************************************/
936 void
937 PlaylistView::MakeDragMessage( BMessage* message ) const
938 {
939     if ( message )
940     {
941         message->AddPointer( "list", (void*)this );
942         int32 index;
943         for ( int32 i = 0; ( index = CurrentSelection( i ) ) >= 0; i++ )
944         {
945             message->AddInt32( "index", index );
946             // add refs to message (inter application communication)
947             if ( BStringItem* item = dynamic_cast<BStringItem*>( ItemAt( index ) ) )
948             {
949                 entry_ref ref;
950                 if ( get_ref_for_path( item->Text(), &ref ) == B_OK )
951                     message->AddRef( "refs", &ref );
952             }
953         }
954     }
955 }
956
957 /*****************************************************************************
958  * PlaylistView::SetCurrent
959  *****************************************************************************/
960 void
961 PlaylistView::SetCurrent( int32 index )
962 {
963     if ( fCurrentIndex != index )
964     {
965         InvalidateItem( fCurrentIndex );
966         fCurrentIndex = index;
967         InvalidateItem( fCurrentIndex );
968     }
969 }
970
971 /*****************************************************************************
972  * PlaylistView::SetPlaying
973  *****************************************************************************/
974 void
975 PlaylistView::SetPlaying( bool playing )
976 {
977     if ( fPlaying != playing )
978     {
979         fPlaying = playing;
980         InvalidateItem( fCurrentIndex );
981     }
982 }
983
984 /*****************************************************************************
985  * PlaylistView::SetPlaying
986  *****************************************************************************/
987 void
988 PlaylistView::RebuildList()
989 {
990     playlist_t * p_playlist = pl_Yield( p_intf );
991
992     // remove all items
993     BListItem * item;
994     int32 count = CountItems();
995     while( ( item = RemoveItem( --count ) ) )
996         delete item;
997
998     // rebuild listview from VLC's playlist
999     PL_LOCK;
1000     FOREACH_ARRAY( playlist_item_t *p_item, p_playlist->items )
1001         AddItem( new PlaylistItem( p_item->p_input->psz_name ) );
1002     FOREACH_END();
1003     PL_UNLOCK;
1004
1005     vlc_object_release( p_playlist );
1006 }
1007
1008
1009 /*****************************************************************************
1010  * PlaylistView::SortReverse
1011  *****************************************************************************/
1012 void
1013 PlaylistView::SortReverse()
1014 {
1015 #if 0
1016     if ( int32 count = CountSelectedItems() )
1017     {
1018         int32 last  = count - 1;
1019         // remember currently playing item
1020         BListItem* playingItem = _PlayingItem();
1021         for ( int32 first = 0; first < count / 2; first++, last-- )
1022         {
1023             int32 index1 = CurrentSelection( first);
1024             int32 index2 = CurrentSelection( last);
1025             if ( SwapItems( index1, index2 ) )
1026             {
1027                 // index2 > index1, so the list won't get messed up
1028                 // if we remove the items in that order
1029                 // TODO: Error checking + handling!
1030                 void* item2 = fVlcWrapper->PlaylistRemoveItem( index2 );
1031                 void* item1 = fVlcWrapper->PlaylistRemoveItem( index1 );
1032                 fVlcWrapper->PlaylistAddItem( item2, index1 );
1033                 fVlcWrapper->PlaylistAddItem( item1, index2 );
1034             }
1035         }
1036         // restore currently playing item
1037         _SetPlayingIndex( playingItem );
1038     }
1039 #endif
1040 }
1041
1042 /*****************************************************************************
1043  * PlaylistView::SortByPath
1044  *****************************************************************************/
1045 void
1046 PlaylistView::SortByPath()
1047 {
1048  
1049 }
1050
1051 /*****************************************************************************
1052  * PlaylistView::SortByName
1053  *****************************************************************************/
1054 void
1055 PlaylistView::SortByName()
1056 {
1057 }
1058
1059 /*****************************************************************************
1060  * PlaylistView::SetDisplayMode
1061  *****************************************************************************/
1062 void
1063 PlaylistView::SetDisplayMode( uint32 mode )
1064 {
1065     if ( mode != fDisplayMode )
1066     {
1067         fDisplayMode = mode;
1068         Invalidate();
1069     }
1070 }
1071
1072 /*****************************************************************************
1073  * PlaylistView::_PlayingItem
1074  *****************************************************************************/
1075 BListItem*
1076 PlaylistView::_PlayingItem() const
1077 {
1078     playlist_t * p_playlist;
1079     p_playlist = (playlist_t *) vlc_object_find( p_intf,
1080         VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1081
1082     if( !p_playlist )
1083     {
1084         return NULL;
1085     }
1086
1087     BListItem * item = ItemAt( p_playlist->i_index );
1088     vlc_object_release( p_playlist );
1089     return item;
1090 }
1091
1092 /*****************************************************************************
1093  * PlaylistView::_SetPlayingIndex
1094  *****************************************************************************/
1095 void
1096 PlaylistView::_SetPlayingIndex( BListItem* playingItem )
1097 {
1098     for ( int32 i = 0; BListItem* item = ItemAt( i ); i++ )
1099     {
1100         if ( item == playingItem )
1101         {
1102             playlist_t * p_playlist;
1103             p_playlist = (playlist_t *) vlc_object_find( p_intf,
1104                 VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
1105  
1106             if( !p_playlist )
1107             {
1108                 return;
1109             }
1110
1111             playlist_Goto( p_playlist, i );
1112             SetCurrent( i );
1113
1114             vlc_object_release( p_playlist );
1115             break;
1116         }
1117     }
1118 }
1119
1120 #endif