📄 listviews.cpp
字号:
/***************************************************************************** * ListViews.h: BeOS interface list view class implementation ***************************************************************************** * Copyright (C) 1999, 2000, 2001 VideoLAN * $Id: ListViews.cpp 10101 2005-03-02 16:47:31Z robux4 $ * * Authors: Stephan Aßmus <stippi@yellowbites.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/#include <stdio.h>#include <malloc.h>#include <Bitmap.h>#include <Entry.h>#include <String.h>/* VLC headers */#include <vlc/vlc.h>#include <vlc/intf.h>#include "InterfaceWindow.h"#include "ListViews.h"#include "MsgVals.h"#define MAX_DRAG_HEIGHT 200.0#define ALPHA 170#define TEXT_OFFSET 20.0/***************************************************************************** * PlaylistItem class *****************************************************************************/PlaylistItem::PlaylistItem( const char *name ) : BStringItem( name ), fName( "" ){ entry_ref ref; if ( get_ref_for_path( name, &ref) == B_OK ) fName.SetTo( ref.name );}PlaylistItem::~PlaylistItem(){}/***************************************************************************** * PlaylistItem::DrawItem *****************************************************************************/voidPlaylistItem::Draw( BView *owner, BRect frame, bool tintedLine, uint32 mode, bool active, bool playing ){ rgb_color color = (rgb_color){ 255, 255, 255, 255 }; if ( tintedLine ) color = tint_color( color, 1.04 ); // background if ( IsSelected() ) color = tint_color( color, B_DARKEN_2_TINT ); owner->SetLowColor( color ); owner->FillRect( frame, B_SOLID_LOW ); // label owner->SetHighColor( 0, 0, 0, 255 ); font_height fh; owner->GetFontHeight( &fh ); const char* text = Text(); switch ( mode ) { case DISPLAY_NAME: if ( fName.CountChars() > 0 ) text = fName.String(); break; case DISPLAY_PATH: default: break; } BString truncatedString( text ); owner->TruncateString( &truncatedString, B_TRUNCATE_MIDDLE, frame.Width() - TEXT_OFFSET - 4.0 ); owner->DrawString( truncatedString.String(), BPoint( frame.left + TEXT_OFFSET, frame.top + fh.ascent + 1.0 ) ); // playmark if ( active ) { rgb_color black = (rgb_color){ 0, 0, 0, 255 }; rgb_color green = (rgb_color){ 0, 255, 0, 255 }; BRect r( 0.0, 0.0, 10.0, 10.0 ); r.OffsetTo( frame.left + 4.0, ceilf( ( frame.top + frame.bottom ) / 2.0 ) - 5.0 ); if ( !playing ) green = tint_color( color, B_DARKEN_1_TINT ); rgb_color lightGreen = tint_color( green, B_LIGHTEN_2_TINT ); rgb_color darkGreen = tint_color( green, B_DARKEN_2_TINT ); BPoint arrow[3]; arrow[0] = r.LeftTop(); arrow[1] = r.LeftBottom(); arrow[2].x = r.right; arrow[2].y = ( r.top + r.bottom ) / 2.0; owner->BeginLineArray( 6 ); // black outline owner->AddLine( arrow[0], arrow[1], black ); owner->AddLine( BPoint( arrow[1].x + 1.0, arrow[1].y - 1.0 ), arrow[2], black ); owner->AddLine( arrow[0], arrow[2], black ); // inset arrow arrow[0].x += 1.0; arrow[0].y += 2.0; arrow[1].x += 1.0; arrow[1].y -= 2.0; arrow[2].x -= 2.0; // highlights and shadow owner->AddLine( arrow[1], arrow[2], darkGreen ); owner->AddLine( arrow[0], arrow[2], lightGreen ); owner->AddLine( arrow[0], arrow[1], lightGreen ); owner->EndLineArray(); // fill green arrow[0].x += 1.0; arrow[0].y += 1.0; arrow[1].x += 1.0; arrow[1].y -= 1.0; arrow[2].x -= 2.0; owner->SetHighColor( green ); owner->FillPolygon( arrow, 3 ); }}/***************************************************************************** * DragSortableListView class *****************************************************************************/DragSortableListView::DragSortableListView( BRect frame, const char* name, list_view_type type, uint32 resizingMode, uint32 flags ) : BListView( frame, name, type, resizingMode, flags ), fDropRect( 0.0, 0.0, -1.0, -1.0 ), fDropIndex( -1 ){ SetViewColor( B_TRANSPARENT_32_BIT );}DragSortableListView::~DragSortableListView(){}/***************************************************************************** * DragSortableListView::Draw *****************************************************************************/voidDragSortableListView::Draw( BRect updateRect ){ int32 firstIndex = IndexOf( updateRect.LeftTop() ); int32 lastIndex = IndexOf( updateRect.RightBottom() ); if ( firstIndex >= 0 ) { if ( lastIndex < firstIndex ) lastIndex = CountItems() - 1; // update rect contains items BRect r( updateRect ); for ( int32 i = firstIndex; i <= lastIndex; i++) { r = ItemFrame( i ); DrawListItem( this, i, r ); } updateRect.top = r.bottom + 1.0; if ( updateRect.IsValid() ) { SetLowColor( 255, 255, 255, 255 ); FillRect( updateRect, B_SOLID_LOW ); } } else { SetLowColor( 255, 255, 255, 255 ); FillRect( updateRect, B_SOLID_LOW ); } // drop anticipation indication if ( fDropRect.IsValid() ) { SetHighColor( 255, 0, 0, 255 ); StrokeRect( fDropRect ); }}/***************************************************************************** * DragSortableListView::InitiateDrag *****************************************************************************/boolDragSortableListView::InitiateDrag( BPoint point, int32 index, bool ){ bool success = false; BListItem* item = ItemAt( CurrentSelection( 0 ) ); if ( !item ) { // workarround a timing problem Select( index ); item = ItemAt( index ); } if ( item ) { // create drag message BMessage msg( B_SIMPLE_DATA ); MakeDragMessage( &msg ); // figure out drag rect float width = Bounds().Width(); BRect dragRect(0.0, 0.0, width, -1.0); // figure out, how many items fit into our bitmap int32 numItems; bool fade = false; for (numItems = 0; BListItem* item = ItemAt( CurrentSelection( numItems ) ); numItems++) { dragRect.bottom += ceilf( item->Height() ) + 1.0; if ( dragRect.Height() > MAX_DRAG_HEIGHT ) { fade = true; dragRect.bottom = MAX_DRAG_HEIGHT; numItems++; break; } } BBitmap* dragBitmap = new BBitmap( dragRect, B_RGB32, true ); if ( dragBitmap && dragBitmap->IsValid() ) { if ( BView *v = new BView( dragBitmap->Bounds(), "helper", B_FOLLOW_NONE, B_WILL_DRAW ) ) { dragBitmap->AddChild( v ); dragBitmap->Lock(); BRect itemBounds( dragRect) ; itemBounds.bottom = 0.0; // let all selected items, that fit into our drag_bitmap, draw for ( int32 i = 0; i < numItems; i++ ) { int32 index = CurrentSelection( i ); BListItem* item = ItemAt( index ); itemBounds.bottom = itemBounds.top + ceilf( item->Height() ); if ( itemBounds.bottom > dragRect.bottom ) itemBounds.bottom = dragRect.bottom; DrawListItem( v, index, itemBounds ); itemBounds.top = itemBounds.bottom + 1.0; } // make a black frame arround the edge v->SetHighColor( 0, 0, 0, 255 ); v->StrokeRect( v->Bounds() ); v->Sync(); uint8 *bits = (uint8 *)dragBitmap->Bits(); int32 height = (int32)dragBitmap->Bounds().Height() + 1; int32 width = (int32)dragBitmap->Bounds().Width() + 1; int32 bpr = dragBitmap->BytesPerRow(); if (fade) { for ( int32 y = 0; y < height - ALPHA / 2; y++, bits += bpr ) { uint8 *line = bits + 3; for (uint8 *end = line + 4 * width; line < end; line += 4) *line = ALPHA; } for ( int32 y = height - ALPHA / 2; y < height; y++, bits += bpr ) { uint8 *line = bits + 3; for (uint8 *end = line + 4 * width; line < end; line += 4) *line = (height - y) << 1; } } else { for ( int32 y = 0; y < height; y++, bits += bpr ) { uint8 *line = bits + 3; for (uint8 *end = line + 4 * width; line < end; line += 4) *line = ALPHA; } } dragBitmap->Unlock(); success = true; } } if (success) DragMessage( &msg, dragBitmap, B_OP_ALPHA, BPoint( 0.0, 0.0 ) ); else { delete dragBitmap; DragMessage( &msg, dragRect.OffsetToCopy( point ), this ); } } return success;}/***************************************************************************** * DragSortableListView::WindowActivated *****************************************************************************/voidDragSortableListView::WindowActivated( bool active ){ // workarround for buggy focus indication of BScrollView if ( BView* view = Parent() ) view->Invalidate();}/***************************************************************************** * DragSortableListView::MessageReceived *****************************************************************************/voidDragSortableListView::MessageReceived(BMessage* message){ switch ( message->what ) { case B_MODIFIERS_CHANGED: ModifiersChanged(); break; case B_SIMPLE_DATA: { DragSortableListView *list = NULL; if ( message->FindPointer( "list", (void **)&list ) == B_OK && list == this ) { int32 count = CountItems(); if ( fDropIndex < 0 || fDropIndex > count ) fDropIndex = count; BList items; int32 index; for ( int32 i = 0; message->FindInt32( "index", i, &index ) == B_OK; i++ ) if ( BListItem* item = ItemAt(index) ) items.AddItem( (void*)item ); if ( items.CountItems() > 0 ) { if ( modifiers() & B_SHIFT_KEY ) CopyItems( items, fDropIndex ); else MoveItems( items, fDropIndex ); } fDropIndex = -1; } break; } default: BListView::MessageReceived( message ); break; }}/***************************************************************************** * DragSortableListView::MouseMoved *****************************************************************************/voidDragSortableListView::MouseMoved(BPoint where, uint32 transit, const BMessage *msg){ if ( msg && ( msg->what == B_SIMPLE_DATA || msg->what == MSG_SOUNDPLAY ) ) { bool replaceAll = !msg->HasPointer("list") && !(modifiers() & B_SHIFT_KEY); switch ( transit ) { case B_ENTERED_VIEW: // remember drag message // this is needed to react on modifier changes fDragMessageCopy = *msg; case B_INSIDE_VIEW: { if ( replaceAll ) { BRect r( Bounds() ); r.bottom--; // compensate for scrollbar offset _SetDropAnticipationRect( r ); fDropIndex = -1; } else { // offset where by half of item height BRect r( ItemFrame( 0 ) ); where.y += r.Height() / 2.0; int32 index = IndexOf( where ); if ( index < 0 ) index = CountItems(); _SetDropIndex( index );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -