Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

ListViews.cpp

00001 /*****************************************************************************
00002  * ListViews.h: BeOS interface list view class implementation
00003  *****************************************************************************
00004  * Copyright (C) 1999, 2000, 2001 the VideoLAN team
00005  * $Id: ListViews.cpp 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Stephan Aßmus <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 #include <stdio.h>
00025 #include <malloc.h>
00026 
00027 #include <Bitmap.h>
00028 #include <Entry.h>
00029 #include <String.h>
00030 
00031 /* VLC headers */
00032 #include <vlc/vlc.h>
00033 #include <vlc/intf.h>
00034 
00035 #include "InterfaceWindow.h"
00036 #include "ListViews.h"
00037 #include "MsgVals.h"
00038 
00039 #define MAX_DRAG_HEIGHT        200.0
00040 #define ALPHA                170
00041 #define TEXT_OFFSET            20.0
00042 
00043 /*****************************************************************************
00044  * PlaylistItem class
00045  *****************************************************************************/
00046 PlaylistItem::PlaylistItem( const char *name )
00047     : BStringItem( name ),
00048       fName( "" )
00049 {
00050     entry_ref ref;
00051     if ( get_ref_for_path( name, &ref) == B_OK )
00052         fName.SetTo( ref.name );
00053 }
00054 
00055 PlaylistItem::~PlaylistItem()
00056 {
00057 }
00058 
00059 /*****************************************************************************
00060  * PlaylistItem::DrawItem
00061  *****************************************************************************/
00062 void
00063 PlaylistItem::Draw( BView *owner, BRect frame, bool tintedLine,
00064                     uint32 mode, bool active, bool playing )
00065 {
00066     rgb_color color = (rgb_color){ 255, 255, 255, 255 };
00067     if ( tintedLine )
00068         color = tint_color( color, 1.04 );
00069     // background
00070     if ( IsSelected() )
00071         color = tint_color( color, B_DARKEN_2_TINT );
00072     owner->SetLowColor( color );
00073     owner->FillRect( frame, B_SOLID_LOW );
00074     // label
00075     owner->SetHighColor( 0, 0, 0, 255 );
00076     font_height fh;
00077     owner->GetFontHeight( &fh );
00078     const char* text = Text();
00079     switch ( mode )
00080     {
00081         case DISPLAY_NAME:
00082             if ( fName.CountChars() > 0 )
00083                 text = fName.String();
00084             break;
00085         case DISPLAY_PATH:
00086         default:
00087             break;
00088     }
00089     BString truncatedString( text );
00090     owner->TruncateString( &truncatedString, B_TRUNCATE_MIDDLE,
00091                            frame.Width() - TEXT_OFFSET - 4.0 );
00092     owner->DrawString( truncatedString.String(),
00093                        BPoint( frame.left + TEXT_OFFSET,
00094                                frame.top + fh.ascent + 1.0 ) );
00095     // playmark
00096     if ( active )
00097     {
00098         rgb_color black = (rgb_color){ 0, 0, 0, 255 };
00099         rgb_color green = (rgb_color){ 0, 255, 0, 255 };
00100         BRect r( 0.0, 0.0, 10.0, 10.0 );
00101         r.OffsetTo( frame.left + 4.0,
00102                     ceilf( ( frame.top + frame.bottom ) / 2.0 ) - 5.0 );
00103         if ( !playing )
00104             green = tint_color( color, B_DARKEN_1_TINT );
00105         rgb_color lightGreen = tint_color( green, B_LIGHTEN_2_TINT );
00106         rgb_color darkGreen = tint_color( green, B_DARKEN_2_TINT );
00107         BPoint arrow[3];
00108         arrow[0] = r.LeftTop();
00109         arrow[1] = r.LeftBottom();
00110         arrow[2].x = r.right;
00111         arrow[2].y = ( r.top + r.bottom ) / 2.0;
00112         owner->BeginLineArray( 6 );
00113             // black outline
00114             owner->AddLine( arrow[0], arrow[1], black );
00115             owner->AddLine( BPoint( arrow[1].x + 1.0, arrow[1].y - 1.0 ),
00116                             arrow[2], black );
00117             owner->AddLine( arrow[0], arrow[2], black );
00118             // inset arrow
00119             arrow[0].x += 1.0;
00120             arrow[0].y += 2.0;
00121             arrow[1].x += 1.0;
00122             arrow[1].y -= 2.0;
00123             arrow[2].x -= 2.0;
00124             // highlights and shadow
00125             owner->AddLine( arrow[1], arrow[2], darkGreen );
00126             owner->AddLine( arrow[0], arrow[2], lightGreen );
00127             owner->AddLine( arrow[0], arrow[1], lightGreen );
00128         owner->EndLineArray();
00129         // fill green
00130         arrow[0].x += 1.0;
00131         arrow[0].y += 1.0;
00132         arrow[1].x += 1.0;
00133         arrow[1].y -= 1.0;
00134         arrow[2].x -= 2.0;
00135         owner->SetHighColor( green );
00136         owner->FillPolygon( arrow, 3 );
00137     }
00138 }
00139 
00140 /*****************************************************************************
00141  * DragSortableListView class
00142  *****************************************************************************/
00143 DragSortableListView::DragSortableListView( BRect frame, const char* name,
00144                                             list_view_type type, uint32 resizingMode,
00145                                             uint32 flags )
00146     : BListView( frame, name, type, resizingMode, flags ),
00147       fDropRect( 0.0, 0.0, -1.0, -1.0 ),
00148       fDropIndex( -1 )
00149 {
00150     SetViewColor( B_TRANSPARENT_32_BIT );
00151 }
00152 
00153 DragSortableListView::~DragSortableListView()
00154 {
00155 }
00156 
00157 /*****************************************************************************
00158  * DragSortableListView::Draw
00159  *****************************************************************************/
00160 void
00161 DragSortableListView::Draw( BRect updateRect )
00162 {
00163     int32 firstIndex = IndexOf( updateRect.LeftTop() );
00164     int32 lastIndex = IndexOf( updateRect.RightBottom() );
00165     if ( firstIndex >= 0 )
00166     {
00167         if ( lastIndex < firstIndex )
00168             lastIndex = CountItems() - 1;
00169         // update rect contains items
00170         BRect r( updateRect );
00171         for ( int32 i = firstIndex; i <= lastIndex; i++)
00172         {
00173             r = ItemFrame( i );
00174             DrawListItem( this, i, r );
00175         }
00176         updateRect.top = r.bottom + 1.0;
00177         if ( updateRect.IsValid() )
00178         {
00179             SetLowColor( 255, 255, 255, 255 );
00180             FillRect( updateRect, B_SOLID_LOW );
00181         }
00182     }
00183     else
00184     {
00185         SetLowColor( 255, 255, 255, 255 );
00186         FillRect( updateRect, B_SOLID_LOW );
00187     }
00188     // drop anticipation indication
00189     if ( fDropRect.IsValid() )
00190     {
00191         SetHighColor( 255, 0, 0, 255 );
00192         StrokeRect( fDropRect );
00193     }
00194 }
00195 
00196 /*****************************************************************************
00197  * DragSortableListView::InitiateDrag
00198  *****************************************************************************/
00199 bool
00200 DragSortableListView::InitiateDrag( BPoint point, int32 index, bool )
00201 {
00202     bool success = false;
00203     BListItem* item = ItemAt( CurrentSelection( 0 ) );
00204     if ( !item )
00205     {
00206         // workarround a timing problem
00207         Select( index );
00208         item = ItemAt( index );
00209     }
00210     if ( item )
00211     {
00212         // create drag message
00213         BMessage msg( B_SIMPLE_DATA );
00214         MakeDragMessage( &msg );
00215         // figure out drag rect
00216         float width = Bounds().Width();
00217         BRect dragRect(0.0, 0.0, width, -1.0);
00218         // figure out, how many items fit into our bitmap
00219         int32 numItems;
00220         bool fade = false;
00221         for (numItems = 0; BListItem* item = ItemAt( CurrentSelection( numItems ) ); numItems++) {
00222             dragRect.bottom += ceilf( item->Height() ) + 1.0;
00223             if ( dragRect.Height() > MAX_DRAG_HEIGHT ) {
00224                 fade = true;
00225                 dragRect.bottom = MAX_DRAG_HEIGHT;
00226                 numItems++;
00227                 break;
00228             }
00229         }
00230         BBitmap* dragBitmap = new BBitmap( dragRect, B_RGB32, true );
00231         if ( dragBitmap && dragBitmap->IsValid() ) {
00232             if ( BView *v = new BView( dragBitmap->Bounds(), "helper", B_FOLLOW_NONE, B_WILL_DRAW ) ) {
00233                 dragBitmap->AddChild( v );
00234                 dragBitmap->Lock();
00235                 BRect itemBounds( dragRect) ;
00236                 itemBounds.bottom = 0.0;
00237                 // let all selected items, that fit into our drag_bitmap, draw
00238                 for ( int32 i = 0; i < numItems; i++ ) {
00239                     int32 index = CurrentSelection( i );
00240                     BListItem* item = ItemAt( index );
00241                     itemBounds.bottom = itemBounds.top + ceilf( item->Height() );
00242                     if ( itemBounds.bottom > dragRect.bottom )
00243                         itemBounds.bottom = dragRect.bottom;
00244                     DrawListItem( v, index, itemBounds );
00245                     itemBounds.top = itemBounds.bottom + 1.0;
00246                 }
00247                 // make a black frame arround the edge
00248                 v->SetHighColor( 0, 0, 0, 255 );
00249                 v->StrokeRect( v->Bounds() );
00250                 v->Sync();
00251     
00252                 uint8 *bits = (uint8 *)dragBitmap->Bits();
00253                 int32 height = (int32)dragBitmap->Bounds().Height() + 1;
00254                 int32 width = (int32)dragBitmap->Bounds().Width() + 1;
00255                 int32 bpr = dragBitmap->BytesPerRow();
00256     
00257                 if (fade) {
00258                     for ( int32 y = 0; y < height - ALPHA / 2; y++, bits += bpr ) {
00259                         uint8 *line = bits + 3;
00260                         for (uint8 *end = line + 4 * width; line < end; line += 4)
00261                             *line = ALPHA;
00262                     }
00263                     for ( int32 y = height - ALPHA / 2; y < height; y++, bits += bpr ) {
00264                         uint8 *line = bits + 3;
00265                         for (uint8 *end = line + 4 * width; line < end; line += 4)
00266                             *line = (height - y) << 1;
00267                     }
00268                 } else {
00269                     for ( int32 y = 0; y < height; y++, bits += bpr ) {
00270                         uint8 *line = bits + 3;
00271                         for (uint8 *end = line + 4 * width; line < end; line += 4)
00272                             *line = ALPHA;
00273                     }
00274                 }
00275                 dragBitmap->Unlock();
00276                 success = true;
00277             }
00278         }
00279         if (success)
00280             DragMessage( &msg, dragBitmap, B_OP_ALPHA, BPoint( 0.0, 0.0 ) );
00281         else {
00282             delete dragBitmap;
00283             DragMessage( &msg, dragRect.OffsetToCopy( point ), this );
00284         }
00285     }
00286     return success;
00287 }
00288 
00289 /*****************************************************************************
00290  * DragSortableListView::WindowActivated
00291  *****************************************************************************/
00292 void
00293 DragSortableListView::WindowActivated( bool active )
00294 {
00295     // workarround for buggy focus indication of BScrollView
00296     if ( BView* view = Parent() )
00297         view->Invalidate();
00298 }
00299 
00300 /*****************************************************************************
00301  * DragSortableListView::MessageReceived
00302  *****************************************************************************/
00303 void
00304 DragSortableListView::MessageReceived(BMessage* message)
00305 {
00306     switch ( message->what )
00307     {
00308         case B_MODIFIERS_CHANGED:
00309             ModifiersChanged();
00310             break;
00311         case B_SIMPLE_DATA:
00312         {
00313             DragSortableListView *list = NULL;
00314             if ( message->FindPointer( "list", (void **)&list ) == B_OK
00315                  && list == this )
00316             {
00317                 int32 count = CountItems();
00318                 if ( fDropIndex < 0 || fDropIndex > count )
00319                     fDropIndex = count;
00320                 BList items;
00321                 int32 index;
00322                 for ( int32 i = 0; message->FindInt32( "index", i, &index ) == B_OK; i++ )
00323                     if ( BListItem* item = ItemAt(index) )
00324                         items.AddItem( (void*)item );
00325                 if ( items.CountItems() > 0 )
00326                 {
00327                     if ( modifiers() & B_SHIFT_KEY )
00328                         CopyItems( items, fDropIndex );
00329                     else
00330                         MoveItems( items, fDropIndex );
00331                 }
00332                 fDropIndex = -1;
00333             }
00334             break;
00335         }
00336         default:
00337             BListView::MessageReceived( message );
00338             break;
00339     }
00340 }
00341 
00342 /*****************************************************************************
00343  * DragSortableListView::MouseMoved
00344  *****************************************************************************/
00345 void
00346 DragSortableListView::MouseMoved(BPoint where, uint32 transit, const BMessage *msg)
00347 {
00348     if ( msg && ( msg->what == B_SIMPLE_DATA || msg->what == MSG_SOUNDPLAY ) )
00349     {
00350         bool replaceAll = !msg->HasPointer("list") && !(modifiers() & B_SHIFT_KEY);
00351         switch ( transit )
00352         {
00353             case B_ENTERED_VIEW:
00354                 // remember drag message
00355                 // this is needed to react on modifier changes
00356                 fDragMessageCopy = *msg;
00357             case B_INSIDE_VIEW:
00358             {
00359                 if ( replaceAll )
00360                 {
00361                     BRect r( Bounds() );
00362                     r.bottom--;    // compensate for scrollbar offset
00363                     _SetDropAnticipationRect( r );
00364                     fDropIndex = -1;
00365                 }
00366                 else
00367                 {
00368                     // offset where by half of item height
00369                     BRect r( ItemFrame( 0 ) );
00370                     where.y += r.Height() / 2.0;
00371     
00372                     int32 index = IndexOf( where );
00373                     if ( index < 0 )
00374                         index = CountItems();
00375                     _SetDropIndex( index );
00376                 }
00377                 break;
00378             }
00379             case B_EXITED_VIEW:
00380                 // forget drag message
00381                 fDragMessageCopy.what = 0;
00382             case B_OUTSIDE_VIEW:
00383                 _RemoveDropAnticipationRect();
00384                 break;
00385         }
00386     }
00387     else
00388     {
00389         _RemoveDropAnticipationRect();
00390         BListView::MouseMoved(where, transit, msg);
00391         fDragMessageCopy.what = 0;
00392     }
00393 }
00394 
00395 /*****************************************************************************
00396  * DragSortableListView::MouseUp
00397  *****************************************************************************/
00398 void
00399 DragSortableListView::MouseUp( BPoint where )
00400 {
00401     // remove drop mark
00402     _SetDropAnticipationRect( BRect( 0.0, 0.0, -1.0, -1.0 ) );
00403     // be sure to forget drag message
00404     fDragMessageCopy.what = 0;
00405     BListView::MouseUp( where );
00406 }
00407 
00408 /*****************************************************************************
00409  * DragSortableListView::DrawItem
00410  *****************************************************************************/
00411 void
00412 DragSortableListView::DrawItem( BListItem *item, BRect itemFrame, bool complete )
00413 {
00414     DrawListItem( this, IndexOf( item ), itemFrame );
00415 }
00416 
00417 /*****************************************************************************
00418  * DragSortableListView::ModifiersChaned
00419  *****************************************************************************/
00420 void
00421 DragSortableListView::ModifiersChanged()
00422 {
00423     BPoint where;
00424     uint32 buttons;
00425     GetMouse( &where, &buttons, false );
00426     uint32 transit = Bounds().Contains( where ) ? B_INSIDE_VIEW : B_OUTSIDE_VIEW;
00427     MouseMoved( where, transit, &fDragMessageCopy );
00428 }
00429 
00430 /*****************************************************************************
00431  * DragSortableListView::MoveItems
00432  *****************************************************************************/
00433 void
00434 DragSortableListView::MoveItems( BList& items, int32 index )
00435 {
00436     DeselectAll();
00437     // we remove the items while we look at them, the insertion index is decreased
00438     // when the items index is lower, so that we insert at the right spot after
00439     // removal
00440     BList removedItems;
00441     int32 count = items.CountItems();
00442     for ( int32 i = 0; i < count; i++ )
00443     {
00444         BListItem* item = (BListItem*)items.ItemAt( i );
00445         int32 removeIndex = IndexOf( item );
00446         if ( RemoveItem( item ) && removedItems.AddItem( (void*)item ) )
00447         {
00448             if ( removeIndex < index )
00449                 index--;
00450         }
00451         // else ??? -> blow up
00452     }
00453     for ( int32 i = 0; BListItem* item = (BListItem*)removedItems.ItemAt( i ); i++ )
00454     {
00455         if ( AddItem( item, index ) )
00456         {
00457             // after we're done, the newly inserted items will be selected
00458             Select( index, true );
00459             // next items will be inserted after this one
00460             index++;
00461         }
00462         else
00463             delete item;
00464     }
00465 }
00466 
00467 /*****************************************************************************
00468  * DragSortableListView::CopyItems
00469  *****************************************************************************/
00470 void
00471 DragSortableListView::CopyItems( BList& items, int32 index )
00472 {
00473     DeselectAll();
00474     // by inserting the items after we copied all items first, we avoid
00475     // cloning an item we already inserted and messing everything up
00476     // in other words, don't touch the list before we know which items
00477     // need to be cloned
00478     BList clonedItems;
00479     int32 count = items.CountItems();
00480     for ( int32 i = 0; i < count; i++ )
00481     {
00482         BListItem* item = CloneItem( IndexOf( (BListItem*)items.ItemAt( i ) ) );
00483         if ( item && !clonedItems.AddItem( (void*)item ) )
00484             delete item;
00485     }
00486     for ( int32 i = 0; BListItem* item = (BListItem*)clonedItems.ItemAt( i ); i++ )
00487     {
00488         if ( AddItem( item, index ) )
00489         {
00490             // after we're done, the newly inserted items will be selected
00491             Select( index, true );
00492             // next items will be inserted after this one
00493             index++;
00494         }
00495         else
00496             delete item;
00497     }
00498 }
00499 
00500 /*****************************************************************************
00501  * DragSortableListView::RemoveItemList
00502  *****************************************************************************/
00503 void
00504 DragSortableListView::RemoveItemList( BList& items )
00505 {
00506     int32 count = items.CountItems();
00507     for ( int32 i = 0; i < count; i++ )
00508     {
00509         BListItem* item = (BListItem*)items.ItemAt( i );
00510         if ( RemoveItem( item ) )
00511             delete item;
00512     }
00513 }
00514 
00515 /*****************************************************************************
00516  * DragSortableListView::RemoveSelected
00517  *****************************************************************************/
00518 void
00519 DragSortableListView::RemoveSelected()
00520 {
00521     BList items;
00522     for ( int32 i = 0; BListItem* item = ItemAt( CurrentSelection( i ) ); i++ )
00523         items.AddItem( (void*)item );
00524     RemoveItemList( items );
00525 }
00526 
00527 /*****************************************************************************
00528  * DragSortableListView::CountSelectedItems
00529  *****************************************************************************/
00530 int32
00531 DragSortableListView::CountSelectedItems() const
00532 {
00533     int32 count = 0;
00534     while ( CurrentSelection( count ) >= 0 )
00535         count++;
00536     return count;
00537 }
00538 
00539 /*****************************************************************************
00540  * DragSortableListView::_SetDropAnticipationRect
00541  *****************************************************************************/
00542 void
00543 DragSortableListView::_SetDropAnticipationRect( BRect r )
00544 {
00545     if ( fDropRect != r )
00546     {
00547         if ( fDropRect.IsValid() )
00548             Invalidate( fDropRect );
00549         fDropRect = r;
00550         if ( fDropRect.IsValid() )
00551             Invalidate( fDropRect );
00552     }
00553 }
00554 
00555 /*****************************************************************************
00556  * DragSortableListView::_SetDropAnticipationRect
00557  *****************************************************************************/
00558 void
00559 DragSortableListView::_SetDropIndex( int32 index )
00560 {
00561     if ( fDropIndex != index )
00562     {
00563         fDropIndex = index;
00564         if ( fDropIndex == -1 )
00565             _SetDropAnticipationRect( BRect( 0.0, 0.0, -1.0, -1.0 ) );
00566         else
00567         {
00568             int32 count = CountItems();
00569             if ( fDropIndex == count )
00570             {
00571                 BRect r;
00572                 if ( BListItem* item = ItemAt( count - 1 ) )
00573                 {
00574                     r = ItemFrame( count - 1 );
00575                     r.top = r.bottom + 1.0;
00576                     r.bottom = r.top + 1.0;
00577                 }
00578                 else
00579                 {
00580                     r = Bounds();
00581                     r.bottom--;    // compensate for scrollbars moved slightly out of window
00582                 }
00583                 _SetDropAnticipationRect( r );
00584             }
00585             else
00586             {
00587                 BRect r = ItemFrame( fDropIndex );
00588                 r.bottom = r.top + 1.0;
00589                 _SetDropAnticipationRect( r );
00590             }
00591         }
00592     }
00593 }
00594 
00595 /*****************************************************************************
00596  * DragSortableListView::_RemoveDropAnticipationRect
00597  *****************************************************************************/
00598 void
00599 DragSortableListView::_RemoveDropAnticipationRect()
00600 {
00601     _SetDropAnticipationRect( BRect( 0.0, 0.0, -1.0, -1.0 ) );
00602     _SetDropIndex( -1 );
00603 }
00604 
00605 
00606 /*****************************************************************************
00607  * PlaylistView class
00608  *****************************************************************************/
00609 PlaylistView::PlaylistView( intf_thread_t * _p_intf,
00610                             BRect frame, InterfaceWindow* mainWindow,
00611                             BMessage* selectionChangeMessage )
00612     : DragSortableListView( frame, "playlist listview",
00613                             B_MULTIPLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES,
00614                             B_WILL_DRAW | B_NAVIGABLE | B_PULSE_NEEDED
00615                             | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE ),
00616       p_intf( _p_intf ),
00617       fCurrentIndex( -1 ),
00618       fPlaying( false ),
00619       fDisplayMode( DISPLAY_PATH ),
00620       fMainWindow( mainWindow ),
00621       fSelectionChangeMessage( selectionChangeMessage ),
00622       fLastClickedItem( NULL )
00623 {
00624 }
00625 
00626 PlaylistView::~PlaylistView()
00627 {
00628     delete fSelectionChangeMessage;
00629 }
00630 
00631 /*****************************************************************************
00632  * PlaylistView::AttachedToWindow
00633  *****************************************************************************/
00634 void
00635 PlaylistView::AttachedToWindow()
00636 {
00637     // get pulse message every two frames
00638     Window()->SetPulseRate( 80000 );
00639 }
00640 
00641 /*****************************************************************************
00642  * PlaylistView::MessageReceived
00643  *****************************************************************************/
00644 void
00645 PlaylistView::MessageReceived( BMessage* message)
00646 {
00647     switch ( message->what )
00648     {
00649         case MSG_SOUNDPLAY:
00650         case B_SIMPLE_DATA:
00651             if ( message->HasPointer( "list" ) )
00652             {
00653                 // message comes from ourself
00654                 DragSortableListView::MessageReceived( message );
00655             }
00656             else
00657             {
00658                 // message comes from another app (for example Tracker)
00659                 message->AddInt32( "drop index", fDropIndex );
00660                 fMainWindow->PostMessage( message, fMainWindow );
00661             }
00662             break;
00663         default:
00664             DragSortableListView::MessageReceived( message );
00665             break;
00666     }
00667 }
00668 
00669 /*****************************************************************************
00670  * PlaylistView::MouseDown
00671  *****************************************************************************/
00672 void
00673 PlaylistView::MouseDown( BPoint where )
00674 {
00675     int32 clicks = 1;
00676     Window()->CurrentMessage()->FindInt32( "clicks", &clicks );
00677     bool handled = false;
00678     for ( int32 i = 0; PlaylistItem* item = (PlaylistItem*)ItemAt( i ); i++ )
00679     {
00680         BRect r = ItemFrame( i );
00681         if ( r.Contains( where ) )
00682         {
00683             if ( clicks == 2 )
00684             {
00685                 // only do something if user clicked the same item twice
00686                 if ( fLastClickedItem == item )
00687                 {
00688                     playlist_t * p_playlist;
00689                     p_playlist = (playlist_t *) vlc_object_find( p_intf,
00690                         VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
00691                     if( p_playlist )
00692                     {
00693                         playlist_Goto( p_playlist, i );
00694                         vlc_object_release( p_playlist );
00695                     }
00696                     handled = true;
00697                 }
00698             }
00699             else
00700             {
00701                 // remember last clicked item
00702                 fLastClickedItem = item;
00703                 if ( i == fCurrentIndex )
00704                 {
00705                     r.right = r.left + TEXT_OFFSET;
00706                     if ( r.Contains ( where ) )
00707                     {
00708                         fMainWindow->PostMessage( PAUSE_PLAYBACK );
00709                         InvalidateItem( i );
00710                         handled = true;
00711                     }
00712                 }
00713             }
00714             break;
00715         }
00716     }
00717     if ( !handled )
00718         DragSortableListView::MouseDown(where);
00719 }
00720 
00721 /*****************************************************************************
00722  * PlaylistView::KeyDown
00723  *****************************************************************************/
00724 void
00725 PlaylistView::KeyDown( const char* bytes, int32 numBytes )
00726 {
00727     if ( numBytes < 1 )
00728         return;
00729         
00730     if ( ( bytes[0] == B_BACKSPACE ) || ( bytes[0] == B_DELETE ) )
00731     {
00732         RemoveSelected();
00733     }
00734     DragSortableListView::KeyDown( bytes, numBytes );
00735 }
00736 
00737 /*****************************************************************************
00738  * PlaylistView::Pulse
00739  *****************************************************************************/
00740 void
00741 PlaylistView::Pulse()
00742 {
00743     if ( fMainWindow->IsStopped() )
00744         SetPlaying( false );
00745 }
00746 
00747 /*****************************************************************************
00748  * PlaylistView::SelectionChanged
00749  *****************************************************************************/
00750 void
00751 PlaylistView::SelectionChanged()
00752 {
00753     BLooper* looper = Looper();
00754     if ( fSelectionChangeMessage && looper )
00755     {
00756         BMessage message( *fSelectionChangeMessage );
00757         looper->PostMessage( &message );
00758     }
00759 }
00760 
00761 
00762 /*****************************************************************************
00763  * PlaylistView::MoveItems
00764  *****************************************************************************/
00765 void
00766 PlaylistView::MoveItems( BList& items, int32 index )
00767 {
00768 #if 0
00769     DeselectAll();
00770     // we remove the items while we look at them, the insertion index is decreased
00771     // when the items index is lower, so that we insert at the right spot after
00772     // removal
00773     if ( fVlcWrapper->PlaylistLock() )
00774     {
00775         BList removedItems;
00776         BList removeItems;
00777         int32 count = items.CountItems();
00778         int32 indexOriginal = index;
00779         // remember currently playing item
00780         BListItem* playingItem = _PlayingItem();
00781         // collect item pointers for removal by index
00782         for ( int32 i = 0; i < count; i++ )
00783         {
00784             int32 removeIndex = IndexOf( (BListItem*)items.ItemAt( i ) );
00785             void* item = fVlcWrapper->PlaylistItemAt( removeIndex );
00786             if ( item && removeItems.AddItem( item ) )
00787             {
00788                 if ( removeIndex < index )
00789                     index--;
00790             }
00791             // else ??? -> blow up
00792         }
00793         // actually remove items using pointers
00794         for ( int32 i = 0; i < count; i++ )
00795         {
00796             void* item = fVlcWrapper->PlaylistRemoveItem( removeItems.ItemAt( i ) );
00797             if ( item && !removedItems.AddItem( item ) )
00798                 free( item );
00799         }
00800         // add items at index
00801         for ( int32 i = 0; void* item = removedItems.ItemAt( i ); i++ )
00802         {
00803             if ( fVlcWrapper->PlaylistAddItem( item, index ) )
00804                 // next items will be inserted after this one
00805                 index++;
00806             else
00807                 free( item );
00808         }
00809         // update GUI
00810         DragSortableListView::MoveItems( items, indexOriginal );
00811         // restore currently playing item
00812         _SetPlayingIndex( playingItem );
00813         // update interface (in case it isn't playing,
00814         // there is a chance that it needs to update)
00815         fMainWindow->PostMessage( MSG_UPDATE );
00816         fVlcWrapper->PlaylistUnlock();
00817     }
00818 #endif
00819 }
00820 
00821 /*****************************************************************************
00822  * PlaylistView::CopyItems
00823  *****************************************************************************/
00824 void
00825 PlaylistView::CopyItems( BList& items, int32 toIndex )
00826 {
00827 #if 0
00828     DeselectAll();
00829     // we remove the items while we look at them, the insertion index is decreased
00830     // when the items index is lower, so that we insert at the right spot after
00831     // removal
00832     if ( fVlcWrapper->PlaylistLock() )
00833     {
00834         BList clonedItems;
00835         int32 count = items.CountItems();
00836         // remember currently playing item
00837         BListItem* playingItem = _PlayingItem();
00838         // collect cloned item pointers
00839         for ( int32 i = 0; i < count; i++ )
00840         {
00841             int32 index = IndexOf( (BListItem*)items.ItemAt( i ) );
00842             void* item = fVlcWrapper->PlaylistItemAt( index );
00843             void* cloned = fVlcWrapper->PlaylistCloneItem( item );
00844             if ( cloned && !clonedItems.AddItem( cloned ) )
00845                 free( cloned );
00846             
00847         }
00848         // add cloned items at index
00849         int32 index = toIndex;
00850         for ( int32 i = 0; void* item = clonedItems.ItemAt( i ); i++ )
00851         {
00852             if ( fVlcWrapper->PlaylistAddItem( item, index ) )
00853                 // next items will be inserted after this one
00854                 index++;
00855             else
00856                 free( item );
00857         }
00858         // update GUI
00859         DragSortableListView::CopyItems( items, toIndex );
00860         // restore currently playing item
00861         _SetPlayingIndex( playingItem );
00862         // update interface (in case it isn't playing,
00863         // there is a chance that it needs to update)
00864         fMainWindow->PostMessage( MSG_UPDATE );
00865         fVlcWrapper->PlaylistUnlock();
00866     }
00867 #endif
00868 }
00869 
00870 /*****************************************************************************
00871  * PlaylistView::RemoveItemList
00872  *****************************************************************************/
00873 void
00874 PlaylistView::RemoveItemList( BList& items )
00875 {
00876 #if 0
00877     if ( fVlcWrapper->PlaylistLock() )
00878     {
00879         // remember currently playing item
00880         BListItem* playingItem = _PlayingItem();
00881         // collect item pointers for removal
00882         BList removeItems;
00883         int32 count = items.CountItems();
00884         for ( int32 i = 0; i < count; i++ )
00885         {
00886             int32 index = IndexOf( (BListItem*)items.ItemAt( i ) );
00887             void* item = fVlcWrapper->PlaylistItemAt( index );
00888             if ( item && !removeItems.AddItem( item ) )
00889                 free( item );
00890         }
00891         // remove items from playlist
00892         count = removeItems.CountItems();
00893         for ( int32 i = 0; void* item = removeItems.ItemAt( i ); i++ )
00894         {
00895             fVlcWrapper->PlaylistRemoveItem( item );
00896         }
00897         // update GUI
00898         DragSortableListView::RemoveItemList( items );
00899         // restore currently playing item
00900         _SetPlayingIndex( playingItem );
00901         // update interface (in case it isn't playing,
00902         // there is a chance that it needs to update)
00903         fMainWindow->PostMessage( MSG_UPDATE );
00904         fVlcWrapper->PlaylistUnlock();
00905     }
00906 #endif
00907 }
00908 
00909 /*****************************************************************************
00910  * PlaylistView::CloneItem
00911  *****************************************************************************/
00912 BListItem*
00913 PlaylistView::CloneItem( int32 atIndex ) const
00914 {
00915     BListItem* clone = NULL;
00916     if ( PlaylistItem* item = dynamic_cast<PlaylistItem*>( ItemAt( atIndex ) ) )
00917         clone = new PlaylistItem( item->Text() );
00918     return clone;
00919 }
00920 
00921 /*****************************************************************************
00922  * PlaylistView::DrawListItem
00923  *****************************************************************************/
00924 void
00925 PlaylistView::DrawListItem( BView* owner, int32 index, BRect frame ) const
00926 {
00927     if ( PlaylistItem* item = dynamic_cast<PlaylistItem*>( ItemAt( index ) ) )
00928         item->Draw( owner,  frame, index % 2,
00929                     fDisplayMode, index == fCurrentIndex, fPlaying );
00930 }
00931 
00932 /*****************************************************************************
00933  * PlaylistView::MakeDragMessage
00934  *****************************************************************************/
00935 void
00936 PlaylistView::MakeDragMessage( BMessage* message ) const
00937 {
00938     if ( message )
00939     {
00940         message->AddPointer( "list", (void*)this );
00941         int32 index;
00942         for ( int32 i = 0; ( index = CurrentSelection( i ) ) >= 0; i++ )
00943         {
00944             message->AddInt32( "index", index );
00945             // add refs to message (inter application communication)
00946             if ( BStringItem* item = dynamic_cast<BStringItem*>( ItemAt( index ) ) )
00947             {
00948                 entry_ref ref;
00949                 if ( get_ref_for_path( item->Text(), &ref ) == B_OK )
00950                     message->AddRef( "refs", &ref );
00951             }
00952         }
00953     }
00954 }
00955 
00956 /*****************************************************************************
00957  * PlaylistView::SetCurrent
00958  *****************************************************************************/
00959 void
00960 PlaylistView::SetCurrent( int32 index )
00961 {
00962     if ( fCurrentIndex != index )
00963     {
00964         InvalidateItem( fCurrentIndex );
00965         fCurrentIndex = index;
00966         InvalidateItem( fCurrentIndex );
00967     }
00968 }
00969 
00970 /*****************************************************************************
00971  * PlaylistView::SetPlaying
00972  *****************************************************************************/
00973 void
00974 PlaylistView::SetPlaying( bool playing )
00975 {
00976     if ( fPlaying != playing )
00977     {
00978         fPlaying = playing;
00979         InvalidateItem( fCurrentIndex );
00980     }
00981 }
00982 
00983 /*****************************************************************************
00984  * PlaylistView::SetPlaying
00985  *****************************************************************************/
00986 void
00987 PlaylistView::RebuildList()
00988 {
00989     playlist_t * p_playlist;
00990     p_playlist = (playlist_t *) vlc_object_find( p_intf,
00991         VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
00992 
00993     if( !p_playlist )
00994     {
00995         return;
00996     }
00997 
00998     // remove all items
00999     BListItem * item;
01000     int32 count = CountItems();
01001     while( ( item = RemoveItem( --count ) ) )
01002         delete item;
01003     
01004     // rebuild listview from VLC's playlist
01005     vlc_mutex_lock( &p_playlist->object_lock );
01006     for( int i = 0; i < p_playlist->i_size; i++ )
01007         AddItem( new PlaylistItem( p_playlist->pp_items[i]->input.psz_name ) );
01008     vlc_mutex_unlock( &p_playlist->object_lock );
01009 
01010     vlc_object_release( p_playlist );
01011 }
01012 
01013 
01014 /*****************************************************************************
01015  * PlaylistView::SortReverse
01016  *****************************************************************************/
01017 void
01018 PlaylistView::SortReverse()
01019 {
01020 #if 0
01021     if ( int32 count = CountSelectedItems() )
01022     {
01023         int32 last  = count - 1;
01024         // remember currently playing item
01025         BListItem* playingItem = _PlayingItem();
01026         for ( int32 first = 0; first < count / 2; first++, last-- )
01027         {
01028             int32 index1 = CurrentSelection( first);
01029             int32 index2 = CurrentSelection( last);
01030             if ( SwapItems( index1, index2 ) )
01031             {
01032                 // index2 > index1, so the list won't get messed up
01033                 // if we remove the items in that order
01034                 // TODO: Error checking + handling!
01035                 void* item2 = fVlcWrapper->PlaylistRemoveItem( index2 );
01036                 void* item1 = fVlcWrapper->PlaylistRemoveItem( index1 );
01037                 fVlcWrapper->PlaylistAddItem( item2, index1 );
01038                 fVlcWrapper->PlaylistAddItem( item1, index2 );
01039             }
01040         }
01041         // restore currently playing item
01042         _SetPlayingIndex( playingItem );
01043     }
01044 #endif
01045 }
01046 
01047 /*****************************************************************************
01048  * PlaylistView::SortByPath
01049  *****************************************************************************/
01050 void
01051 PlaylistView::SortByPath()
01052 {
01053     
01054 }
01055 
01056 /*****************************************************************************
01057  * PlaylistView::SortByName
01058  *****************************************************************************/
01059 void
01060 PlaylistView::SortByName()
01061 {
01062 }
01063 
01064 /*****************************************************************************
01065  * PlaylistView::SetDisplayMode
01066  *****************************************************************************/
01067 void
01068 PlaylistView::SetDisplayMode( uint32 mode )
01069 {
01070     if ( mode != fDisplayMode )
01071     {
01072         fDisplayMode = mode;
01073         Invalidate();
01074     }
01075 }
01076 
01077 /*****************************************************************************
01078  * PlaylistView::_PlayingItem
01079  *****************************************************************************/
01080 BListItem*
01081 PlaylistView::_PlayingItem() const
01082 {
01083     playlist_t * p_playlist;
01084     p_playlist = (playlist_t *) vlc_object_find( p_intf,
01085         VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
01086 
01087     if( !p_playlist )
01088     {
01089         return NULL;
01090     }
01091 
01092     BListItem * item = ItemAt( p_playlist->i_index );
01093     vlc_object_release( p_playlist );
01094     return item;
01095 }
01096 
01097 /*****************************************************************************
01098  * PlaylistView::_SetPlayingIndex
01099  *****************************************************************************/
01100 void
01101 PlaylistView::_SetPlayingIndex( BListItem* playingItem )
01102 {
01103     for ( int32 i = 0; BListItem* item = ItemAt( i ); i++ )
01104     {
01105         if ( item == playingItem )
01106         {
01107             playlist_t * p_playlist;
01108             p_playlist = (playlist_t *) vlc_object_find( p_intf,
01109                 VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
01110         
01111             if( !p_playlist )
01112             {
01113                 return;
01114             }
01115 
01116             playlist_Goto( p_playlist, i );
01117             SetCurrent( i );
01118 
01119             vlc_object_release( p_playlist );
01120             break;
01121         }
01122     }
01123 }

Generated on Tue Dec 20 10:14:37 2005 for vlc-0.8.4a by  doxygen 1.4.2