dolphin/Branches/MusicMod/Player/Src/PlaylistControler.cpp

452 lines
10 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// Plainamp, Open source Winamp core
//
// Copyright © 2005 Sebastian Pipping <webmaster@hartwork.org>
//
// --> http://www.hartwork.org
//
// This source code is released under the GNU General Public License (GPL).
// See GPL.txt for details. Any non-GPL usage is strictly forbidden.
////////////////////////////////////////////////////////////////////////////////
#include "PlaylistControler.h"
#include "Config.h"
#include "Font.h"
bool bPlaylistFollow;
ConfBool cbPlaylistFollow( &bPlaylistFollow, TEXT( "PlaylistFollow" ), CONF_MODE_PUBLIC, true );
void PlaylistControler::MoveSelected( int iDistance )
{
if( iDistance == -1 )
{
if( ListView_GetItemState( _hView, 0, LVIS_SELECTED ) )
{
// Cannot move upwards
return;
}
}
else if( iDistance == 1 )
{
if( ListView_GetItemState( _hView, _database.GetMaxIndex(), LVIS_SELECTED ) )
{
// Cannot move downwards
return;
}
}
else
{
// More distance maybe later
return;
}
const int iFocus = ListView_GetNextItem( _hView, ( UINT )-1, LVIS_FOCUSED );
// Negative is to the top
LRESULT iBefore = 0;
LRESULT iAfter = -2; // Extra value to check after big for-loop
for( ; ; )
{
// Count
LRESULT iAfter = ListView_GetNextItem( _hView, iBefore - 1, LVNI_SELECTED );
if( iAfter == -1 ) break; // No more selections selected
LRESULT iFirst = iAfter;
// Search end of selection block
iBefore = iAfter + 1;
for( ; ; )
{
iAfter = ListView_GetNextItem( _hView, iBefore - 1, LVNI_SELECTED );
if( iAfter == iBefore )
{
// Keep searching
iBefore++;
}
else
{
// End found (iBefore is the first not selected)
const int iSelSize = iBefore - iFirst;
if( iDistance == -1 )
{
// Updwards
const int iOldIndex = iFirst - 1;
const int iNewIndex = iOldIndex + iSelSize;
TCHAR * szData = ( TCHAR * )_database.Get( iOldIndex );
_database.Erase( iOldIndex );
_database.Insert( iNewIndex, szData );
ListView_SetItemState( _hView, iOldIndex, LVIS_SELECTED, LVIS_SELECTED );
ListView_SetItemState( _hView, iNewIndex, 0, LVIS_SELECTED );
ListView_RedrawItems( _hView, iOldIndex, iNewIndex );
}
else
{
// Downwards
const int iOldIndex = iFirst + iSelSize;
const int iNewIndex = iFirst;
TCHAR * szData = ( TCHAR * )_database.Get( iOldIndex );
_database.Erase( iOldIndex );
_database.Insert( iNewIndex, szData );
ListView_SetItemState( _hView, iOldIndex, LVIS_SELECTED, LVIS_SELECTED );
ListView_SetItemState( _hView, iNewIndex, 0, LVIS_SELECTED );
ListView_RedrawItems( _hView, iNewIndex, iOldIndex );
}
iBefore++;
break;
}
}
}
if( iAfter != -2 ) return; // Nothing was selected so nothing was moved
ListView_SetItemState( _hView, iFocus + iDistance, LVIS_FOCUSED, LVIS_FOCUSED );
Refresh();
}
int PlaylistControler::GetCurIndex()
{
return _database.GetCurIndex();
}
int PlaylistControler::GetMaxIndex()
{
return _database.GetMaxIndex();
}
int PlaylistControler::GetSize()
{
return _database.GetSize();
}
void PlaylistControler::SetCurIndex( int iIndex )
{
const int iCurIndexBefore = _database.GetCurIndex();
_database.SetCurIndex( iIndex );
if( bPlaylistFollow )
{
ListView_SetItemState( _hView, ( UINT )-1, 0, LVIS_SELECTED | LVIS_FOCUSED );
ListView_SetItemState( _hView, iIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED );
}
if( iCurIndexBefore != -1 )
ListView_RedrawItems( _hView, iCurIndexBefore, iCurIndexBefore );
ListView_RedrawItems( _hView, iIndex, iIndex );
}
// Returns <true> on digit count change
bool PlaylistControler::FixDigitsMore()
{
const int iCountAfter = _database.GetSize();
const int iDigitsBefore = _iDigits;
while( iCountAfter > _iDigitMax )
{
_iDigitMin *= 10; // 10 -> 100
_iDigitMax = _iDigitMax * 10 + 9; // 99 -> 999
_iDigits++; // 2 -> 3
}
return ( ( _iDigits != iDigitsBefore )
|| ( iCountAfter == 1 ) ); // Force update when first item is inserted
}
// Returns <true> on digit count change
bool PlaylistControler::FixDigitsLess()
{
const int iCountAfter = _database.GetSize();
const int iDigitsBefore = _iDigits;
while( ( iCountAfter < _iDigitMin ) && ( _iDigits > 1 ) )
{
_iDigitMin /= 10; // 999 -> 99
_iDigitMax /= 10; // 100 -> 10
_iDigits--; // 3 -> 2
}
return ( _iDigits != iDigitsBefore );
}
void PlaylistControler::Refresh()
{
AutosizeColumns();
const int iFirst = ListView_GetTopIndex( _hView );
const int iLast = iFirst + ListView_GetCountPerPage( _hView );
ListView_RedrawItems( _hView, iFirst, iLast );
}
PlaylistControler::PlaylistControler( HWND hView, bool bEnableZeroPadding, int * piIndexSlave )
{
_hView = hView;
_bZeroPadding = bEnableZeroPadding;
_iDigits = 1;
_iDigitMin = 1;
_iDigitMax = 9;
_database.SetCurIndexSlave( piIndexSlave );
Refresh();
// TODO clear list view here???
}
void PlaylistControler::PushBack( TCHAR * szText )
{
const int iSize = _database.GetMaxIndex();
_database.PushBack( szText );
ListView_SetItemCount( _hView, _database.GetSize() );
if( FixDigitsMore() ) Refresh();
}
void PlaylistControler::Insert( int i, TCHAR * szText )
{
const int iSize = _database.GetMaxIndex();
_database.Insert( i, szText );
ListView_SetItemCount( _hView, _database.GetSize() );
if( FixDigitsMore() ) Refresh();
}
void PlaylistControler::RemoveAll()
{
_database.Clear();
ListView_DeleteAllItems( _hView );
if( FixDigitsLess() ) Refresh();
}
void PlaylistControler::RemoveSelected( bool bPositive )
{
SendMessage( _hView, WM_SETREDRAW, FALSE, 0 );
if( bPositive )
{
LRESULT iWalk = 0;
for( ; ; )
{
// MSDN: The specified item itself is excluded from the search.
iWalk = ListView_GetNextItem( _hView, iWalk - 1, LVNI_SELECTED );
if( iWalk != -1 )
{
_database.Erase( iWalk );
ListView_DeleteItem( _hView, iWalk );
}
else
{
break;
}
}
}
else
{
LRESULT iBefore = 0;
LRESULT iAfter = 0;
for( ; ; )
{
// MSDN: The specified item itself is excluded from the search.
iAfter = ListView_GetNextItem( _hView, iBefore - 1, LVNI_SELECTED );
if( iAfter != -1 )
{
// <iAfter> is the first selected
// so we delete all before and restart
// at the beginning
const int iDelIndex = iBefore;
for( int i = iBefore; i < iAfter; i++ )
{
_database.Erase( iDelIndex );
ListView_DeleteItem( _hView, iDelIndex );
}
iBefore++; // Exclude the one we found selected right before
}
else
{
if( iBefore == 0 )
{
// All selected
_database.Clear();
ListView_DeleteAllItems( _hView );
}
else
{
const int iSize = _database.GetSize();
const int iDelIndex = iBefore;
for( int i = iBefore; i < iSize; i++ )
{
_database.Erase( iDelIndex );
ListView_DeleteItem( _hView, iDelIndex );
}
}
break;
}
}
}
bool bRefresh = FixDigitsLess();
SendMessage( _hView, WM_SETREDRAW, TRUE, 0 );
if( bRefresh ) Refresh();
}
void PlaylistControler::SelectAll( bool bPositive )
{
ListView_SetItemState( _hView, ( UINT )-1, bPositive ? LVIS_SELECTED : 0, LVIS_SELECTED );
}
void PlaylistControler::SelectInvert()
{
SendMessage( _hView, WM_SETREDRAW, FALSE, 0 );
const int iOneTooMuch = _database.GetSize();
for( int i = 0; i < iOneTooMuch; i++ )
{
ListView_SetItemState(
_hView,
i,
( ListView_GetItemState( _hView, i, LVIS_SELECTED ) == LVIS_SELECTED )
? 0
: LVIS_SELECTED,
LVIS_SELECTED
);
}
SendMessage( _hView, WM_SETREDRAW, TRUE, 0 );
}
const TCHAR * PlaylistControler::Get( int i )
{
return _database.Get( i );
}
void PlaylistControler::Fill( LVITEM & request )
{
if( ( request.mask & LVIF_TEXT ) == 0 ) return;
if( request.iSubItem )
{
// Text
_sntprintf( request.pszText, request.cchTextMax, TEXT( "%s" ), _database.Get( request.iItem ) );
}
else
{
// Number
if( _bZeroPadding )
{
TCHAR szFormat[ 6 ];
_stprintf( szFormat, TEXT( "%%0%dd" ), _iDigits );
_sntprintf( request.pszText, request.cchTextMax, szFormat, request.iItem + 1 );
}
else
{
_sntprintf( request.pszText, request.cchTextMax, TEXT( "%d" ), request.iItem + 1 );
}
}
}
void PlaylistControler::EnableZeroPadding( bool bActive )
{
if( bActive == _bZeroPadding ) return;
LVCOLUMN col;
memset( &col, 0, sizeof( LVCOLUMN ) );
col.mask = LVCF_FMT;
if( bActive )
{
// TODO recalculation yes/no?
/*
int iSize = _database.GetSize();
if( iSize != 0 )
{
int iDigits = 0;
while( iSize > 0 )
{
iSize /= 10;
iDigits++;
}
_iDigits = iSize;
_iDigitMin = 1;
_iDigitMax = 9;
while( iSize-- > 0 )
{
_iDigitMin *= 10;
_iDigitMax = _iDigitMax * 10 + 9;
}
}
else
{
_iDigits = 1;
_iDigitMin = 1;
_iDigitMax = 9;
}
*/
col.fmt = LVCFMT_LEFT;
ListView_SetColumn( _hView, 0, &col );
Refresh();
}
else
{
col.fmt = LVCFMT_RIGHT;
ListView_SetColumn( _hView, 0, &col );
Refresh();
}
_bZeroPadding = bActive;
}
void PlaylistControler::AutosizeColumns()
{
RECT r;
if( !GetClientRect( _hView, &r ) ) return;
if( _bZeroPadding )
{
ListView_SetColumnWidth( _hView, 0, LVSCW_AUTOSIZE );
const int iWidth = ListView_GetColumnWidth( _hView, 0 );
ListView_SetColumnWidth( _hView, 1, r.right - r.left - iWidth );
}
else
{
HDC hdc = GetDC( _hView );
const HFONT hOldFont = ( HFONT )SelectObject( hdc, Font::Get() );
SIZE size;
BOOL res = GetTextExtentPoint32( hdc, TEXT( "0" ), 1, &size );
SelectObject( hdc, hOldFont );
ReleaseDC( _hView, hdc );
const int iWidth = res ? ( int )( size.cx * ( _iDigits + 0.25f ) ) : 120;
ListView_SetColumnWidth( _hView, 0, iWidth );
ListView_SetColumnWidth( _hView, 1, r.right - r.left - iWidth );
}
}
void PlaylistControler::Resize( HWND hParent )
{
/*
RECT rc;
GetClientRect( hParent, &rc );
MoveWindow( _hView, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE );
*/
AutosizeColumns();
}