📄 ctrllibraryalbumview.cpp
字号:
//
// CtrlLibraryAlbumView.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza 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.
//
// Shareaza 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 Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "Library.h"
#include "SharedFile.h"
#include "AlbumFolder.h"
#include "Schema.h"
#include "SchemaCache.h"
#include "ShellIcons.h"
#include "CoolInterface.h"
#include "CtrlLibraryAlbumView.h"
#include "CtrlLibraryTree.h"
#include "CtrlLibraryFrame.h"
#include "CtrlLibraryTip.h"
#include "DlgFilePropertiesSheet.h"
#include "Skin.h"
#include "XML.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
IMPLEMENT_DYNCREATE(CLibraryAlbumView, CLibraryFileView)
BEGIN_MESSAGE_MAP(CLibraryAlbumView, CLibraryFileView)
//{{AFX_MSG_MAP(CLibraryAlbumView)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
ON_WM_VSCROLL()
ON_WM_MOUSEWHEEL()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
LPCTSTR CLibraryAlbumView::m_pStaticStyle;
COLORREF CLibraryAlbumView::m_crRows[2];
/////////////////////////////////////////////////////////////////////////////
// CLibraryAlbumView construction
CLibraryAlbumView::CLibraryAlbumView()
{
m_nCommandID = ID_LIBRARY_VIEW_ALBUM;
}
CLibraryAlbumView::~CLibraryAlbumView()
{
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryAlbumView create and destroy
BOOL CLibraryAlbumView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= WS_VSCROLL;
return CLibraryFileView::PreCreateWindow( cs );
}
int CLibraryAlbumView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if ( CLibraryFileView::OnCreate( lpCreateStruct ) == -1 ) return -1;
m_pList = NULL;
m_nCount = 0;
m_nBuffer = 0;
m_nScroll = 0;
m_nSelected = 0;
m_pFocus = NULL;
m_pFirst = NULL;
m_bDrag = FALSE;
CBitmap bmStar;
bmStar.LoadBitmap( IDB_SMALL_STAR );
m_pStars.Create( 12, 12, ILC_COLOR16|ILC_MASK, 6, 0 );
m_pStars.Add( &bmStar, RGB( 0, 255, 0 ) );
return 0;
}
void CLibraryAlbumView::OnDestroy()
{
Clear();
CLibraryFileView::OnDestroy();
m_pStars.DeleteImageList();
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryAlbumView view operations
void CLibraryAlbumView::Update()
{
CLibraryTreeItem* pFolders = GetFolderSelection();
m_pStaticStyle = m_pStyle;
m_pStyle = NULL;
if ( pFolders != NULL && pFolders->m_pVirtual != NULL &&
pFolders->m_pSelNext == NULL )
{
CAlbumFolder* pFolder = pFolders->m_pVirtual;
if ( pFolder->m_sSchemaURI == CSchema::uriMusicAlbum )
{
m_pStyle = CSchema::uriMusicAlbum;
}
else if ( pFolder->m_sSchemaURI == CSchema::uriMusicArtist )
{
m_pStyle = CSchema::uriMusicArtist;
}
}
CSchema* pSchema = SchemaCache.Get( Settings.Library.FilterURI );
DWORD nCookie = GetFolderCookie();
BOOL bChanged = m_pStyle != m_pStaticStyle;
if ( Settings.Library.ShowVirtual ) pSchema = NULL;
CLibraryAlbumTrack** pList = m_pList + m_nCount - 1;
for ( int nItem = m_nCount ; nItem ; nItem--, pList-- )
{
CLibraryAlbumTrack* pTrack = *pList;
CLibraryFile* pFile = Library.LookupFile( pTrack->m_nIndex );
if ( pFile != NULL && pFile->m_nSelectCookie == nCookie &&
pFile->IsAvailable() &&
( ! pSchema || pSchema->Equals( pFile->m_pSchema ) ||
( ! pFile->m_pMetadata && pSchema->FilterType( pFile->m_sName ) ) ) )
{
bChanged |= pTrack->Update( pFile );
pFile->m_nListCookie = nCookie;
}
else
{
if ( pTrack == m_pFocus ) m_pFocus = NULL;
if ( pTrack == m_pFirst ) m_pFirst = NULL;
if ( pTrack->m_bSelected ) Select( pTrack, TS_FALSE );
delete pTrack;
MoveMemory( pList, pList + 1, 4 * ( m_nCount - nItem ) );
m_nCount--;
bChanged = TRUE;
}
}
if ( bChanged )
{
CRect rcClient;
GetClientRect( &rcClient );
int nMax = m_nCount * m_szTrack.cy;
m_nScroll = max( 0, min( m_nScroll, nMax - rcClient.Height() + 1 ) );
}
for ( POSITION pos = LibraryMaps.GetFileIterator() ; pos ; )
{
CLibraryFile* pFile = LibraryMaps.GetNextFile( pos );
if ( pFile->m_nSelectCookie == nCookie &&
pFile->m_nListCookie != nCookie &&
pFile->IsAvailable() &&
( ! pSchema || pSchema->Equals( pFile->m_pSchema ) ||
( ! pFile->m_pMetadata && pSchema->FilterType( pFile->m_sName ) ) ) )
{
CLibraryAlbumTrack* pTrack = new CLibraryAlbumTrack( pFile );
if ( m_nCount == m_nBuffer )
{
m_nBuffer += 64;
CLibraryAlbumTrack** pList = new CLibraryAlbumTrack*[ m_nBuffer ];
if ( m_nCount ) CopyMemory( pList, m_pList, 4 * m_nCount );
if ( m_pList ) delete [] m_pList;
m_pList = pList;
}
m_pList[ m_nCount++ ] = pTrack;
pFile->m_nListCookie = nCookie;
bChanged = TRUE;
}
}
if ( bChanged )
{
m_pStaticStyle = m_pStyle;
qsort( m_pList, m_nCount, 4, SortList );
UpdateScroll();
}
}
BOOL CLibraryAlbumView::Select(DWORD nObject)
{
CRect rcClient, rcItem;
CLibraryAlbumTrack** pList = m_pList + m_nCount - 1;
for ( int nItem = m_nCount ; nItem ; nItem--, pList-- )
{
CLibraryAlbumTrack* pTrack = *pList;
if ( pTrack->m_nIndex == nObject ) break;
}
if ( nItem == 0 ) return FALSE;
m_pFocus = *pList;
DeselectAll( m_pFocus );
Select( m_pFocus );
Invalidate();
GetClientRect( &rcClient );
GetItemRect( m_pFocus, &rcItem );
if ( rcItem.top < rcClient.top )
{
ScrollBy( rcItem.top - rcClient.top );
}
else if ( rcItem.bottom > rcClient.bottom )
{
ScrollBy( rcItem.bottom - rcClient.bottom );
}
return TRUE;
}
DWORD CLibraryAlbumView::HitTestIndex(const CPoint& point) const
{
CLibraryAlbumTrack* pTrack = HitTest( point );
return ( pTrack ) ? pTrack->m_nIndex : 0;
}
int CLibraryAlbumView::SortList(LPCVOID pA, LPCVOID pB)
{
CLibraryAlbumTrack* ppA = *(CLibraryAlbumTrack**)pA;
CLibraryAlbumTrack* ppB = *(CLibraryAlbumTrack**)pB;
if ( m_pStaticStyle == CSchema::uriMusicAlbum )
{
if ( ppA->m_nTrack != ppB->m_nTrack )
{
return ( ppA->m_nTrack < ppB->m_nTrack ) ? -1 : 1;
}
else
{
return _tcsicoll( ppA->m_sTitle, ppB->m_sTitle );
}
}
else if ( m_pStaticStyle == CSchema::uriMusicArtist )
{
int nCompare = _tcsicoll( ppA->m_sAlbum, ppB->m_sAlbum );
if ( nCompare )
{
return nCompare;
}
else
{
return _tcsicoll( ppA->m_sTitle, ppB->m_sTitle );
}
}
else
{
int nCompare = _tcsicoll( ppA->m_sArtist, ppB->m_sArtist );
if ( nCompare )
{
return nCompare;
}
else if ( nCompare = _tcsicoll( ppA->m_sAlbum, ppB->m_sAlbum ) )
{
return nCompare;
}
else
{
return _tcsicoll( ppA->m_sTitle, ppB->m_sTitle );
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryAlbumView item list management operations
void CLibraryAlbumView::Clear()
{
for ( int nItem = 0 ; nItem < m_nCount ; nItem++ )
{
delete m_pList[ nItem ];
}
if ( m_pList ) delete [] m_pList;
m_pList = NULL;
m_nCount = 0;
m_nBuffer = 0;
m_nScroll = 0;
m_nSelected = 0;
m_pFocus = NULL;
m_pFirst = NULL;
SelClear();
m_pSelTrack.RemoveAll();
}
int CLibraryAlbumView::GetTrackIndex(CLibraryAlbumTrack* pTrack) const
{
CLibraryAlbumTrack** pList = m_pList;
for ( int nItem = 0 ; nItem < m_nCount ; nItem++, pList++ )
{
if ( *pList == pTrack ) return nItem;
}
return -1;
}
BOOL CLibraryAlbumView::Select(CLibraryAlbumTrack* pTrack, TRISTATE bSelect)
{
switch ( bSelect )
{
case TS_UNKNOWN:
pTrack->m_bSelected = ! pTrack->m_bSelected;
break;
case TS_FALSE:
if ( pTrack->m_bSelected == FALSE ) return FALSE;
pTrack->m_bSelected = FALSE;
break;
case TS_TRUE:
if ( pTrack->m_bSelected == TRUE ) return FALSE;
pTrack->m_bSelected = TRUE;
break;
}
if ( pTrack->m_bSelected )
{
if ( m_pSelTrack.Find( pTrack ) == NULL )
{
m_nSelected++;
SelAdd( pTrack->m_nIndex );
m_pSelTrack.AddTail( pTrack );
}
}
else
{
if ( POSITION pos = m_pSelTrack.Find( pTrack ) )
{
m_nSelected--;
SelRemove( pTrack->m_nIndex );
m_pSelTrack.RemoveAt( pos );
}
}
return TRUE;
}
BOOL CLibraryAlbumView::DeselectAll(CLibraryAlbumTrack* pTrack)
{
CLibraryAlbumTrack** pList = m_pList + m_nCount - 1;
BOOL bChanged = FALSE;
for ( int nItem = m_nCount ; nItem ; nItem--, pList-- )
{
if ( *pList != pTrack )
{
if ( (*pList)->m_bSelected ) bChanged = Select( *pList, TS_FALSE );
}
}
return bChanged;
}
BOOL CLibraryAlbumView::SelectTo(CLibraryAlbumTrack* pTrack)
{
BOOL bChanged = FALSE;
if ( pTrack )
{
m_pFocus = pTrack;
int nFirst = GetTrackIndex( m_pFirst );
int nFocus = GetTrackIndex( m_pFocus );
if ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 )
{
bChanged = Select( m_pFocus, TS_UNKNOWN );
}
else if ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 )
{
bChanged = DeselectAll();
if ( nFirst >= 0 && nFocus >= 0 )
{
if ( nFirst <= nFocus )
{
for ( ; nFirst <= nFocus ; nFirst++ ) Select( m_pList[ nFirst ], TS_TRUE );
}
else
{
for ( ; nFocus <= nFirst ; nFocus++ ) Select( m_pList[ nFocus ], TS_TRUE );
}
bChanged = TRUE;
}
else
{
bChanged |= Select( m_pFocus, TS_TRUE );
}
}
else
{
if ( m_pFocus->m_bSelected == FALSE ) bChanged = DeselectAll( m_pFocus );
bChanged |= Select( m_pFocus );
}
if ( m_nSelected == 1 && m_pFocus->m_bSelected ) m_pFirst = m_pFocus;
CRect rcClient, rcItem;
GetClientRect( &rcClient );
GetItemRect( m_pFocus, &rcItem );
if ( rcItem.top < rcClient.top )
{
ScrollBy( rcItem.top - rcClient.top );
}
else if ( rcItem.bottom > rcClient.bottom )
{
ScrollBy( rcItem.bottom - rcClient.bottom );
}
}
else if ( ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) == 0 &&
( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) == 0 )
{
bChanged = DeselectAll();
}
if ( m_nSelected == 0 ) m_pFirst = NULL;
return bChanged;
}
void CLibraryAlbumView::SelectTo(int nDelta)
{
if ( m_nCount == 0 ) return;
int nFocus = GetTrackIndex( m_pFocus );
if ( nFocus < 0 )
{
nFocus = 0;
}
else
{
nFocus += nDelta;
if ( nFocus < 0 ) nFocus = 0;
if ( nFocus >= m_nCount ) nFocus = m_nCount - 1;
}
if ( SelectTo( m_pList[ nFocus ] ) ) Invalidate();
}
/////////////////////////////////////////////////////////////////////////////
// CLibraryAlbumView message handlers
void CLibraryAlbumView::OnSize(UINT nType, int cx, int cy)
{
CLibraryFileView::OnSize( nType, cx, cy );
m_szTrack.cx = cx;
m_szTrack.cy = 22;
m_nRows = cy / m_szTrack.cy;
}
void CLibraryAlbumView::UpdateScroll()
{
SCROLLINFO pInfo;
CRect rc;
GetClientRect( &rc );
pInfo.cbSize = sizeof(pInfo);
pInfo.fMask = SIF_ALL & ~SIF_TRACKPOS;
pInfo.nMin = 0;
pInfo.nMax = m_nCount * m_szTrack.cy;
pInfo.nPage = rc.Height();
pInfo.nPos = m_nScroll = max( 0, min( m_nScroll, pInfo.nMax - (int)pInfo.nPage + 1 ) );
SetScrollInfo( SB_VERT, &pInfo, TRUE );
Invalidate();
}
void CLibraryAlbumView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CRect rc;
GetClientRect( &rc );
SetFocus();
switch ( nSBCode )
{
case SB_BOTTOM:
ScrollTo( 0xFFFFFF );
break;
case SB_LINEDOWN:
ScrollBy( m_szTrack.cy );
break;
case SB_LINEUP:
ScrollBy( -m_szTrack.cy );
break;
case SB_PAGEDOWN:
ScrollBy( rc.Height() );
break;
case SB_PAGEUP:
ScrollBy( -rc.Height() );
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
{
SCROLLINFO pScroll = { sizeof(SCROLLINFO), SIF_TRACKPOS };
GetScrollInfo( SB_VERT, &pScroll );
ScrollTo( pScroll.nTrackPos );
}
break;
case SB_TOP:
ScrollTo( 0 );
break;
}
}
BOOL CLibraryAlbumView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
ScrollBy( zDelta * -m_szTrack.cy / WHEEL_DELTA * 5 );
return CLibraryFileView::OnMouseWheel( nFlags, zDelta, pt );
}
void CLibraryAlbumView::ScrollBy(int nDelta)
{
ScrollTo( max( 0, m_nScroll + nDelta ) );
}
void CLibraryAlbumView::ScrollTo(int nPosition)
{
if ( nPosition == m_nScroll ) return;
m_nScroll = nPosition;
UpdateScroll();
RedrawWindow( NULL, NULL, RDW_INVALIDATE );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -