ListViews.cpp
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:37k
源码类别:

多媒体

开发平台:

MultiPlatform

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