00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "Library.h"
00026 #include "SharedFile.h"
00027 #include "AlbumFolder.h"
00028 #include "Schema.h"
00029 #include "SchemaCache.h"
00030 #include "ShellIcons.h"
00031 #include "CoolInterface.h"
00032 #include "CtrlLibraryAlbumView.h"
00033 #include "CtrlLibraryTree.h"
00034 #include "CtrlLibraryFrame.h"
00035 #include "CtrlLibraryTip.h"
00036 #include "DlgFilePropertiesSheet.h"
00037 #include "Skin.h"
00038 #include "XML.h"
00039
00040 #ifdef _DEBUG
00041 #define new DEBUG_NEW
00042 #undef THIS_FILE
00043 static char THIS_FILE[] = __FILE__;
00044 #endif
00045
00046 IMPLEMENT_DYNCREATE(CLibraryAlbumView, CLibraryFileView)
00047
00048 BEGIN_MESSAGE_MAP(CLibraryAlbumView, CLibraryFileView)
00049
00050 ON_WM_CREATE()
00051 ON_WM_DESTROY()
00052 ON_WM_SIZE()
00053 ON_WM_VSCROLL()
00054 ON_WM_MOUSEWHEEL()
00055 ON_WM_PAINT()
00056 ON_WM_LBUTTONDOWN()
00057 ON_WM_MOUSEMOVE()
00058 ON_WM_LBUTTONUP()
00059 ON_WM_LBUTTONDBLCLK()
00060 ON_WM_RBUTTONDOWN()
00061 ON_WM_KEYDOWN()
00062
00063 END_MESSAGE_MAP()
00064
00065 LPCTSTR CLibraryAlbumView::m_pStaticStyle;
00066 COLORREF CLibraryAlbumView::m_crRows[2];
00067
00068
00070
00071
00072 CLibraryAlbumView::CLibraryAlbumView()
00073 {
00074 m_nCommandID = ID_LIBRARY_VIEW_ALBUM;
00075 }
00076
00077 CLibraryAlbumView::~CLibraryAlbumView()
00078 {
00079 }
00080
00082
00083
00084 BOOL CLibraryAlbumView::PreCreateWindow(CREATESTRUCT& cs)
00085 {
00086 cs.style |= WS_VSCROLL;
00087 return CLibraryFileView::PreCreateWindow( cs );
00088 }
00089
00090 int CLibraryAlbumView::OnCreate(LPCREATESTRUCT lpCreateStruct)
00091 {
00092 if ( CLibraryFileView::OnCreate( lpCreateStruct ) == -1 ) return -1;
00093
00094 m_pList = NULL;
00095 m_nCount = 0;
00096 m_nBuffer = 0;
00097 m_nScroll = 0;
00098
00099 m_nSelected = 0;
00100 m_pFocus = NULL;
00101 m_pFirst = NULL;
00102 m_bDrag = FALSE;
00103
00104 CBitmap bmStar;
00105 bmStar.LoadBitmap( IDB_SMALL_STAR );
00106 m_pStars.Create( 12, 12, ILC_COLOR16|ILC_MASK, 6, 0 );
00107 m_pStars.Add( &bmStar, RGB( 0, 255, 0 ) );
00108
00109 return 0;
00110 }
00111
00112 void CLibraryAlbumView::OnDestroy()
00113 {
00114 Clear();
00115 CLibraryFileView::OnDestroy();
00116 m_pStars.DeleteImageList();
00117 }
00118
00120
00121
00122 void CLibraryAlbumView::Update()
00123 {
00124 CLibraryTreeItem* pFolders = GetFolderSelection();
00125
00126 m_pStaticStyle = m_pStyle;
00127 m_pStyle = NULL;
00128
00129 if ( pFolders != NULL && pFolders->m_pVirtual != NULL &&
00130 pFolders->m_pSelNext == NULL )
00131 {
00132 CAlbumFolder* pFolder = pFolders->m_pVirtual;
00133
00134 if ( pFolder->m_sSchemaURI == CSchema::uriMusicAlbum )
00135 {
00136 m_pStyle = CSchema::uriMusicAlbum;
00137 }
00138 else if ( pFolder->m_sSchemaURI == CSchema::uriMusicArtist )
00139 {
00140 m_pStyle = CSchema::uriMusicArtist;
00141 }
00142 }
00143
00144 CSchema* pSchema = SchemaCache.Get( Settings.Library.FilterURI );
00145 DWORD nCookie = GetFolderCookie();
00146 BOOL bChanged = m_pStyle != m_pStaticStyle;
00147
00148 if ( Settings.Library.ShowVirtual ) pSchema = NULL;
00149
00150 CLibraryAlbumTrack** pList = m_pList + m_nCount - 1;
00151
00152 for ( int nItem = m_nCount ; nItem ; nItem--, pList-- )
00153 {
00154 CLibraryAlbumTrack* pTrack = *pList;
00155 CLibraryFile* pFile = Library.LookupFile( pTrack->m_nIndex );
00156
00157 if ( pFile != NULL && pFile->m_nSelectCookie == nCookie &&
00158 pFile->IsAvailable() &&
00159 ( ! pSchema || pSchema->Equals( pFile->m_pSchema ) ||
00160 ( ! pFile->m_pMetadata && pSchema->FilterType( pFile->m_sName ) ) ) )
00161 {
00162 bChanged |= pTrack->Update( pFile );
00163 pFile->m_nListCookie = nCookie;
00164 }
00165 else
00166 {
00167 if ( pTrack == m_pFocus ) m_pFocus = NULL;
00168 if ( pTrack == m_pFirst ) m_pFirst = NULL;
00169 if ( pTrack->m_bSelected ) Select( pTrack, TS_FALSE );
00170 delete pTrack;
00171 MoveMemory( pList, pList + 1, 4 * ( m_nCount - nItem ) );
00172 m_nCount--;
00173 bChanged = TRUE;
00174 }
00175 }
00176
00177 if ( bChanged )
00178 {
00179 CRect rcClient;
00180 GetClientRect( &rcClient );
00181 int nMax = m_nCount * m_szTrack.cy;
00182 m_nScroll = max( 0, min( m_nScroll, nMax - rcClient.Height() + 1 ) );
00183 }
00184
00185 for ( POSITION pos = LibraryMaps.GetFileIterator() ; pos ; )
00186 {
00187 CLibraryFile* pFile = LibraryMaps.GetNextFile( pos );
00188
00189 if ( pFile->m_nSelectCookie == nCookie &&
00190 pFile->m_nListCookie != nCookie &&
00191 pFile->IsAvailable() &&
00192 ( ! pSchema || pSchema->Equals( pFile->m_pSchema ) ||
00193 ( ! pFile->m_pMetadata && pSchema->FilterType( pFile->m_sName ) ) ) )
00194 {
00195 CLibraryAlbumTrack* pTrack = new CLibraryAlbumTrack( pFile );
00196
00197 if ( m_nCount == m_nBuffer )
00198 {
00199 m_nBuffer += 64;
00200 CLibraryAlbumTrack** pList = new CLibraryAlbumTrack*[ m_nBuffer ];
00201 if ( m_nCount ) CopyMemory( pList, m_pList, 4 * m_nCount );
00202 if ( m_pList ) delete [] m_pList;
00203 m_pList = pList;
00204 }
00205
00206 m_pList[ m_nCount++ ] = pTrack;
00207 pFile->m_nListCookie = nCookie;
00208 bChanged = TRUE;
00209 }
00210 }
00211
00212 if ( bChanged )
00213 {
00214 m_pStaticStyle = m_pStyle;
00215 qsort( m_pList, m_nCount, 4, SortList );
00216 UpdateScroll();
00217 }
00218 }
00219
00220 BOOL CLibraryAlbumView::Select(DWORD nObject)
00221 {
00222 CRect rcClient, rcItem;
00223
00224 CLibraryAlbumTrack** pList = m_pList + m_nCount - 1;
00225
00226 int nItem = m_nCount;
00227 for ( ; nItem ; nItem--, pList-- )
00228 {
00229 CLibraryAlbumTrack* pTrack = *pList;
00230 if ( pTrack->m_nIndex == nObject ) break;
00231 }
00232
00233 if ( nItem == 0 ) return FALSE;
00234
00235 m_pFocus = *pList;
00236 DeselectAll( m_pFocus );
00237 Select( m_pFocus );
00238 Invalidate();
00239
00240 GetClientRect( &rcClient );
00241 GetItemRect( m_pFocus, &rcItem );
00242
00243 if ( rcItem.top < rcClient.top )
00244 {
00245 ScrollBy( rcItem.top - rcClient.top );
00246 }
00247 else if ( rcItem.bottom > rcClient.bottom )
00248 {
00249 ScrollBy( rcItem.bottom - rcClient.bottom );
00250 }
00251
00252 return TRUE;
00253 }
00254
00255 DWORD CLibraryAlbumView::HitTestIndex(const CPoint& point) const
00256 {
00257 CLibraryAlbumTrack* pTrack = HitTest( point );
00258 return ( pTrack ) ? pTrack->m_nIndex : 0;
00259 }
00260
00261 int CLibraryAlbumView::SortList(LPCVOID pA, LPCVOID pB)
00262 {
00263 CLibraryAlbumTrack* ppA = *(CLibraryAlbumTrack**)pA;
00264 CLibraryAlbumTrack* ppB = *(CLibraryAlbumTrack**)pB;
00265
00266 if ( m_pStaticStyle == CSchema::uriMusicAlbum )
00267 {
00268 if ( ppA->m_nTrack != ppB->m_nTrack )
00269 {
00270 return ( ppA->m_nTrack < ppB->m_nTrack ) ? -1 : 1;
00271 }
00272 else
00273 {
00274 return _tcsicoll( ppA->m_sTitle, ppB->m_sTitle );
00275 }
00276 }
00277 else if ( m_pStaticStyle == CSchema::uriMusicArtist )
00278 {
00279 int nCompare = _tcsicoll( ppA->m_sAlbum, ppB->m_sAlbum );
00280
00281 if ( nCompare )
00282 {
00283 return nCompare;
00284 }
00285 else
00286 {
00287 return _tcsicoll( ppA->m_sTitle, ppB->m_sTitle );
00288 }
00289 }
00290 else
00291 {
00292 int nCompare = _tcsicoll( ppA->m_sArtist, ppB->m_sArtist );
00293
00294 if ( nCompare )
00295 {
00296 return nCompare;
00297 }
00298 else if ( nCompare = _tcsicoll( ppA->m_sAlbum, ppB->m_sAlbum ) )
00299 {
00300 return nCompare;
00301 }
00302 else
00303 {
00304 return _tcsicoll( ppA->m_sTitle, ppB->m_sTitle );
00305 }
00306 }
00307 }
00308
00310
00311
00312 void CLibraryAlbumView::Clear()
00313 {
00314 for ( int nItem = 0 ; nItem < m_nCount ; nItem++ )
00315 {
00316 delete m_pList[ nItem ];
00317 }
00318
00319 if ( m_pList ) delete [] m_pList;
00320
00321 m_pList = NULL;
00322 m_nCount = 0;
00323 m_nBuffer = 0;
00324 m_nScroll = 0;
00325 m_nSelected = 0;
00326 m_pFocus = NULL;
00327 m_pFirst = NULL;
00328
00329 SelClear();
00330 m_pSelTrack.RemoveAll();
00331 }
00332
00333 int CLibraryAlbumView::GetTrackIndex(CLibraryAlbumTrack* pTrack) const
00334 {
00335 CLibraryAlbumTrack** pList = m_pList;
00336
00337 for ( int nItem = 0 ; nItem < m_nCount ; nItem++, pList++ )
00338 {
00339 if ( *pList == pTrack ) return nItem;
00340 }
00341
00342 return -1;
00343 }
00344
00345 BOOL CLibraryAlbumView::Select(CLibraryAlbumTrack* pTrack, TRISTATE bSelect)
00346 {
00347 switch ( bSelect )
00348 {
00349 case TS_UNKNOWN:
00350 pTrack->m_bSelected = ! pTrack->m_bSelected;
00351 break;
00352 case TS_FALSE:
00353 if ( pTrack->m_bSelected == FALSE ) return FALSE;
00354 pTrack->m_bSelected = FALSE;
00355 break;
00356 case TS_TRUE:
00357 if ( pTrack->m_bSelected == TRUE ) return FALSE;
00358 pTrack->m_bSelected = TRUE;
00359 break;
00360 }
00361
00362 if ( pTrack->m_bSelected )
00363 {
00364 if ( m_pSelTrack.Find( pTrack ) == NULL )
00365 {
00366 m_nSelected++;
00367 SelAdd( pTrack->m_nIndex );
00368 m_pSelTrack.AddTail( pTrack );
00369 }
00370 }
00371 else
00372 {
00373 if ( POSITION pos = m_pSelTrack.Find( pTrack ) )
00374 {
00375 m_nSelected--;
00376 SelRemove( pTrack->m_nIndex );
00377 m_pSelTrack.RemoveAt( pos );
00378 }
00379 }
00380
00381 return TRUE;
00382 }
00383
00384 BOOL CLibraryAlbumView::DeselectAll(CLibraryAlbumTrack* pTrack)
00385 {
00386 CLibraryAlbumTrack** pList = m_pList + m_nCount - 1;
00387 BOOL bChanged = FALSE;
00388
00389 for ( int nItem = m_nCount ; nItem ; nItem--, pList-- )
00390 {
00391 if ( *pList != pTrack )
00392 {
00393 if ( (*pList)->m_bSelected ) bChanged = Select( *pList, TS_FALSE );
00394 }
00395 }
00396
00397 return bChanged;
00398 }
00399
00400 BOOL CLibraryAlbumView::SelectTo(CLibraryAlbumTrack* pTrack)
00401 {
00402 BOOL bChanged = FALSE;
00403
00404 if ( pTrack )
00405 {
00406 m_pFocus = pTrack;
00407
00408 int nFirst = GetTrackIndex( m_pFirst );
00409 int nFocus = GetTrackIndex( m_pFocus );
00410
00411 if ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 )
00412 {
00413 bChanged = Select( m_pFocus, TS_UNKNOWN );
00414 }
00415 else if ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 )
00416 {
00417 bChanged = DeselectAll();
00418
00419 if ( nFirst >= 0 && nFocus >= 0 )
00420 {
00421 if ( nFirst <= nFocus )
00422 {
00423 for ( ; nFirst <= nFocus ; nFirst++ ) Select( m_pList[ nFirst ], TS_TRUE );
00424 }
00425 else
00426 {
00427 for ( ; nFocus <= nFirst ; nFocus++ ) Select( m_pList[ nFocus ], TS_TRUE );
00428 }
00429
00430 bChanged = TRUE;
00431 }
00432 else
00433 {
00434 bChanged |= Select( m_pFocus, TS_TRUE );
00435 }
00436 }
00437 else
00438 {
00439 if ( m_pFocus->m_bSelected == FALSE ) bChanged = DeselectAll( m_pFocus );
00440 bChanged |= Select( m_pFocus );
00441 }
00442
00443 if ( m_nSelected == 1 && m_pFocus->m_bSelected ) m_pFirst = m_pFocus;
00444
00445 CRect rcClient, rcItem;
00446
00447 GetClientRect( &rcClient );
00448 GetItemRect( m_pFocus, &rcItem );
00449
00450 if ( rcItem.top < rcClient.top )
00451 {
00452 ScrollBy( rcItem.top - rcClient.top );
00453 }
00454 else if ( rcItem.bottom > rcClient.bottom )
00455 {
00456 ScrollBy( rcItem.bottom - rcClient.bottom );
00457 }
00458 }
00459 else if ( ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) == 0 &&
00460 ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) == 0 )
00461 {
00462 bChanged = DeselectAll();
00463 }
00464
00465 if ( m_nSelected == 0 ) m_pFirst = NULL;
00466
00467 return bChanged;
00468 }
00469
00470 void CLibraryAlbumView::SelectTo(int nDelta)
00471 {
00472 if ( m_nCount == 0 ) return;
00473
00474 int nFocus = GetTrackIndex( m_pFocus );
00475
00476 if ( nFocus < 0 )
00477 {
00478 nFocus = 0;
00479 }
00480 else
00481 {
00482 nFocus += nDelta;
00483 if ( nFocus < 0 ) nFocus = 0;
00484 if ( nFocus >= m_nCount ) nFocus = m_nCount - 1;
00485 }
00486
00487 if ( SelectTo( m_pList[ nFocus ] ) ) Invalidate();
00488 }
00489
00491
00492
00493 void CLibraryAlbumView::OnSize(UINT nType, int cx, int cy)
00494 {
00495 CLibraryFileView::OnSize( nType, cx, cy );
00496
00497 m_szTrack.cx = cx;
00498 m_szTrack.cy = 22;
00499 m_nRows = cy / m_szTrack.cy;
00500 }
00501
00502 void CLibraryAlbumView::UpdateScroll()
00503 {
00504 SCROLLINFO pInfo;
00505 CRect rc;
00506
00507 GetClientRect( &rc );
00508
00509 pInfo.cbSize = sizeof(pInfo);
00510 pInfo.fMask = SIF_ALL & ~SIF_TRACKPOS;
00511 pInfo.nMin = 0;
00512 pInfo.nMax = m_nCount * m_szTrack.cy;
00513 pInfo.nPage = rc.Height();
00514 pInfo.nPos = m_nScroll = max( 0, min( m_nScroll, pInfo.nMax - (int)pInfo.nPage + 1 ) );
00515
00516 SetScrollInfo( SB_VERT, &pInfo, TRUE );
00517
00518 Invalidate();
00519 }
00520
00521 void CLibraryAlbumView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
00522 {
00523 CRect rc;
00524 GetClientRect( &rc );
00525
00526 SetFocus();
00527
00528 switch ( nSBCode )
00529 {
00530 case SB_BOTTOM:
00531 ScrollTo( 0xFFFFFF );
00532 break;
00533 case SB_LINEDOWN:
00534 ScrollBy( m_szTrack.cy );
00535 break;
00536 case SB_LINEUP:
00537 ScrollBy( -m_szTrack.cy );
00538 break;
00539 case SB_PAGEDOWN:
00540 ScrollBy( rc.Height() );
00541 break;
00542 case SB_PAGEUP:
00543 ScrollBy( -rc.Height() );
00544 break;
00545 case SB_THUMBPOSITION:
00546 case SB_THUMBTRACK:
00547 {
00548 SCROLLINFO pScroll = { sizeof(SCROLLINFO), SIF_TRACKPOS };
00549 GetScrollInfo( SB_VERT, &pScroll );
00550 ScrollTo( pScroll.nTrackPos );
00551 }
00552 break;
00553 case SB_TOP:
00554 ScrollTo( 0 );
00555 break;
00556 }
00557 }
00558
00559 BOOL CLibraryAlbumView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
00560 {
00561 ScrollBy( zDelta * -m_szTrack.cy / WHEEL_DELTA * 5 );
00562 return CLibraryFileView::OnMouseWheel( nFlags, zDelta, pt );
00563 }
00564
00565 void CLibraryAlbumView::ScrollBy(int nDelta)
00566 {
00567 ScrollTo( max( 0, m_nScroll + nDelta ) );
00568 }
00569
00570 void CLibraryAlbumView::ScrollTo(int nPosition)
00571 {
00572 if ( nPosition == m_nScroll ) return;
00573 m_nScroll = nPosition;
00574
00575 UpdateScroll();
00576 RedrawWindow( NULL, NULL, RDW_INVALIDATE );
00577 }
00578
00579 void CLibraryAlbumView::OnPaint()
00580 {
00581 CPaintDC dc( this );
00582
00583 CRect rcBuffer( 0, 0, m_szTrack.cx, m_szTrack.cy );
00584 CDC* pBuffer = CoolInterface.GetBuffer( dc, m_szTrack );
00585 if ( theApp.m_bRTL ) pBuffer->SetTextAlign( TA_RTLREADING );
00586
00587 CFont* pOldFont = (CFont*)pBuffer->SelectObject( &CoolInterface.m_fntNormal );
00588 pBuffer->SetBkMode( OPAQUE );
00589 pBuffer->SetBkColor( CoolInterface.m_crWindow );
00590 pBuffer->SetTextColor( CoolInterface.m_crText );
00591
00592 m_crRows[0] = CCoolInterface::CalculateColour( CoolInterface.m_crWindow, Skin.m_crSchemaRow[0], 128 );
00593 m_crRows[1] = CCoolInterface::CalculateColour( CoolInterface.m_crWindow, Skin.m_crSchemaRow[1], 128 );
00594
00595 CRect rcClient, rcTrack;
00596 GetClientRect( &rcClient );
00597
00598 rcTrack = rcBuffer;
00599 rcTrack.OffsetRect( rcClient.left, rcClient.top - m_nScroll );
00600
00601 CLibraryAlbumTrack** pList = m_pList;
00602
00603 for ( int nItem = 0 ; nItem < m_nCount && rcTrack.top < rcClient.bottom ; nItem++, pList++ )
00604 {
00605 CLibraryAlbumTrack* pTrack = *pList;
00606
00607 if ( rcTrack.bottom >= rcClient.top && dc.RectVisible( &rcTrack ) )
00608 {
00609 pBuffer->FillSolidRect( &rcBuffer, CoolInterface.m_crWindow );
00610 pTrack->Paint( this, pBuffer, rcBuffer, nItem );
00611 dc.BitBlt( rcTrack.left, rcTrack.top, rcBuffer.right, rcBuffer.bottom,
00612 pBuffer, 0, 0, SRCCOPY );
00613 dc.ExcludeClipRect( &rcTrack );
00614 }
00615
00616 rcTrack.OffsetRect( 0, m_szTrack.cy );
00617 }
00618
00619 pBuffer->SelectObject( pOldFont );
00620 dc.FillSolidRect( &rcClient, CoolInterface.m_crWindow );
00621 }
00622
00623 CLibraryAlbumTrack* CLibraryAlbumView::HitTest(const CPoint& point, CRect* pRect) const
00624 {
00625 CRect rcClient, rcTrack( 0, 0, m_szTrack.cx, m_szTrack.cy );
00626 GetClientRect( &rcClient );
00627 rcTrack.OffsetRect( rcClient.left, rcClient.top - m_nScroll );
00628
00629 CLibraryAlbumTrack** pList = m_pList;
00630
00631 for ( int nItem = m_nCount ; nItem && rcTrack.top < rcClient.bottom ; nItem--, pList++ )
00632 {
00633 CLibraryAlbumTrack* pTrack = *pList;
00634
00635 if ( rcTrack.PtInRect( point ) )
00636 {
00637 if ( pRect ) *pRect = rcTrack;
00638 return pTrack;
00639 }
00640
00641 rcTrack.OffsetRect( 0, m_szTrack.cy );
00642 }
00643
00644 return NULL;
00645 }
00646
00647 BOOL CLibraryAlbumView::GetItemRect(CLibraryAlbumTrack* pTrack, CRect* pRect)
00648 {
00649 CRect rcClient, rcTrack( 0, 0, m_szTrack.cx, m_szTrack.cy );
00650 GetClientRect( &rcClient );
00651 rcTrack.OffsetRect( rcClient.left, rcClient.top - m_nScroll );
00652
00653 CLibraryAlbumTrack** pList = m_pList;
00654
00655 for ( int nItem = m_nCount ; nItem ; nItem--, pList++ )
00656 {
00657 if ( *pList == pTrack )
00658 {
00659 *pRect = rcTrack;
00660 return TRUE;
00661 }
00662
00663 rcTrack.OffsetRect( 0, m_szTrack.cy );
00664 }
00665
00666 return FALSE;
00667 }
00668
00669 void CLibraryAlbumView::OnLButtonDown(UINT nFlags, CPoint point)
00670 {
00671 SetFocus();
00672 SetCapture();
00673
00674 CRect rcTrack;
00675 CLibraryAlbumTrack* pHit = HitTest( point, &rcTrack );
00676
00677 if ( pHit != NULL && pHit->HitTestRating( rcTrack, point ) )
00678 {
00679 pHit->LockRating();
00680 m_pRating = NULL;
00681 Invalidate();
00682 return;
00683 }
00684
00685 if ( SelectTo( pHit ) ) Invalidate();
00686
00687 if ( pHit && ( nFlags & MK_RBUTTON ) == 0 )
00688 {
00689 m_bDrag = TRUE;
00690 m_ptDrag = point;
00691 }
00692
00693 CLibraryFileView::OnLButtonDown( nFlags, point );
00694 }
00695
00696 void CLibraryAlbumView::OnMouseMove(UINT nFlags, CPoint point)
00697 {
00698 if ( m_bDrag & ( nFlags & MK_LBUTTON ) )
00699 {
00700 CSize szDiff = point - m_ptDrag;
00701
00702 if ( abs( szDiff.cx ) > 5 || abs( szDiff.cy ) > 5 )
00703 {
00704 m_bDrag = FALSE;
00705 StartDragging( point );
00706 }
00707 }
00708
00709
00710
00711 CLibraryTipCtrl* pTip = &((CLibraryFrame*)GetOwner())->m_wndViewTip;
00712 CRect rcTrack;
00713
00714 if ( CLibraryAlbumTrack* pTrack = HitTest( point, &rcTrack ) )
00715 {
00716 pTip->Show( (LPVOID)pTrack->m_nIndex );
00717
00718 if ( pTrack->HitTestRating( rcTrack, point ) )
00719 {
00720 m_pRating = pTrack;
00721 Invalidate();
00722 SetCursor( theApp.LoadCursor( IDC_HAND ) );
00723 }
00724 else if ( m_pRating != NULL )
00725 {
00726 m_pRating = NULL;
00727 Invalidate();
00728 }
00729 }
00730 else
00731 {
00732 pTip->Hide();
00733
00734 if ( m_pRating != NULL )
00735 {
00736 m_pRating = NULL;
00737 Invalidate();
00738 }
00739 }
00740 }
00741
00742 void CLibraryAlbumView::OnLButtonUp(UINT nFlags, CPoint point)
00743 {
00744 ReleaseCapture();
00745 m_bDrag = FALSE;
00746
00747 if ( ( nFlags & (MK_SHIFT|MK_CONTROL) ) == 0 && m_pFocus && m_pFocus->m_bSelected )
00748 {
00749 if ( DeselectAll( m_pFocus ) ) Invalidate();
00750 }
00751 }
00752
00753 void CLibraryAlbumView::OnLButtonDblClk(UINT nFlags, CPoint point)
00754 {
00755 SendMessage( WM_COMMAND, ID_LIBRARY_LAUNCH );
00756 }
00757
00758 void CLibraryAlbumView::OnRButtonDown(UINT nFlags, CPoint point)
00759 {
00760 OnLButtonDown( nFlags, point );
00761 CLibraryFileView::OnRButtonDown( nFlags, point );
00762 }
00763
00764 void CLibraryAlbumView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
00765 {
00766 switch ( nChar )
00767 {
00768 case VK_LEFT:
00769 case VK_UP:
00770 SelectTo( -1 );
00771 break;
00772 case VK_DOWN:
00773 case VK_RIGHT:
00774 SelectTo( 1 );
00775 break;
00776 case VK_PRIOR:
00777 SelectTo( -m_nRows );
00778 break;
00779 case VK_NEXT:
00780 SelectTo( m_nRows );
00781 break;
00782 case VK_HOME:
00783 SelectTo( -m_nCount );
00784 break;
00785 case VK_END:
00786 SelectTo( m_nCount );
00787 break;
00788 default:
00789 if ( _istalnum( nChar ) )
00790 {
00791 CLibraryAlbumTrack* pStart = m_pFocus;
00792
00793 for ( int nLoop = 0 ; nLoop < 2 ; nLoop++ )
00794 {
00795 CLibraryAlbumTrack** pChild = m_pList;
00796
00797 for ( int nCount = m_nCount ; nCount ; nCount--, pChild++ )
00798 {
00799 if ( pStart != NULL )
00800 {
00801 if ( pStart == *pChild ) pStart = NULL;
00802 }
00803 else
00804 {
00805 LPCTSTR psz = NULL;
00806
00807 if ( m_pStyle == CSchema::uriMusicAlbum )
00808 psz = (*pChild)->m_sTitle;
00809 else if ( m_pStyle == CSchema::uriMusicArtist )
00810 psz = (*pChild)->m_sAlbum;
00811 else
00812 psz = (*pChild)->m_sArtist;
00813
00814 if ( psz && *psz && toupper( *psz ) == (int)nChar )
00815 {
00816 if ( SelectTo( *pChild ) ) Invalidate();
00817 return;
00818 }
00819 }
00820 }
00821 }
00822 }
00823 }
00824
00825 CLibraryFileView::OnKeyDown( nChar, nRepCnt, nFlags );
00826 }
00827
00829
00830
00831 #define MAX_DRAG_SIZE 256
00832 #define MAX_DRAG_SIZE_2 128
00833
00834 void CLibraryAlbumView::StartDragging(CPoint& ptMouse)
00835 {
00836 CImageList* pImage = CreateDragImage( ptMouse );
00837 if ( pImage == NULL ) return;
00838
00839 ReleaseCapture();
00840 ClientToScreen( &ptMouse );
00841 DragObjects( pImage, ptMouse );
00842 }
00843
00844 CImageList* CLibraryAlbumView::CreateDragImage(const CPoint& ptMouse)
00845 {
00846 CRect rcClient, rcOne, rcAll( 32000, 32000, -32000, -32000 );
00847
00848 GetClientRect( &rcClient );
00849
00850 for ( POSITION pos = m_pSelTrack.GetHeadPosition() ; pos ; )
00851 {
00852 CLibraryAlbumTrack* pTrack = (CLibraryAlbumTrack*)m_pSelTrack.GetNext( pos );
00853 GetItemRect( pTrack, &rcOne );
00854
00855 if ( rcOne.IntersectRect( &rcClient, &rcOne ) )
00856 {
00857 rcAll.left = min( rcAll.left, rcOne.left );
00858 rcAll.top = min( rcAll.top, rcOne.top );
00859 rcAll.right = max( rcAll.right, rcOne.right );
00860 rcAll.bottom = max( rcAll.bottom, rcOne.bottom );
00861 }
00862 }
00863
00864 BOOL bClipped = rcAll.Height() > MAX_DRAG_SIZE;
00865
00866 if ( bClipped )
00867 {
00868 rcAll.left = max( rcAll.left, ptMouse.x - MAX_DRAG_SIZE_2 );
00869 rcAll.right = max( rcAll.right, ptMouse.x + MAX_DRAG_SIZE_2 );
00870 rcAll.top = max( rcAll.top, ptMouse.y - MAX_DRAG_SIZE_2 );
00871 rcAll.bottom = max( rcAll.bottom, ptMouse.y + MAX_DRAG_SIZE_2 );
00872 }
00873
00874 CClientDC dcClient( this );
00875 CBitmap bmDrag;
00876 CDC dcDrag;
00877
00878 if ( ! dcDrag.CreateCompatibleDC( &dcClient ) )
00879 return NULL;
00880 if ( ! bmDrag.CreateCompatibleBitmap( &dcClient, rcAll.Width(), rcAll.Height() ) )
00881 return NULL;
00882
00883 CBitmap *pOldDrag = dcDrag.SelectObject( &bmDrag );
00884
00885 dcDrag.FillSolidRect( 0, 0, rcAll.Width(), rcAll.Height(), RGB( 0, 255, 0 ) );
00886
00887 CRgn pRgn;
00888
00889 if ( bClipped )
00890 {
00891 CPoint ptMiddle( ptMouse.x - rcAll.left, ptMouse.y - rcAll.top );
00892 pRgn.CreateEllipticRgn( ptMiddle.x - MAX_DRAG_SIZE_2, ptMiddle.y - MAX_DRAG_SIZE_2,
00893 ptMiddle.x + MAX_DRAG_SIZE_2, ptMiddle.y + MAX_DRAG_SIZE_2 );
00894 dcDrag.SelectClipRgn( &pRgn );
00895 }
00896
00897 CDC* pBuffer = CoolInterface.GetBuffer( dcClient, m_szTrack );
00898 CRect rcBuffer( 0, 0, m_szTrack.cx, m_szTrack.cy );
00899
00900 CFont* pOldFont = (CFont*)pBuffer->SelectObject( &CoolInterface.m_fntNormal );
00901
00902 for ( POSITION pos = m_pSelTrack.GetHeadPosition() ; pos ; )
00903 {
00904 CLibraryAlbumTrack* pTrack = (CLibraryAlbumTrack*)m_pSelTrack.GetNext( pos );
00905 GetItemRect( pTrack, &rcOne );
00906 CRect rcDummy;
00907
00908 if ( rcDummy.IntersectRect( &rcAll, &rcOne ) )
00909 {
00910 pBuffer->FillSolidRect( &rcBuffer, RGB( 0, 255, 0 ) );
00911 pTrack->Paint( this, pBuffer, rcBuffer, -1 );
00912 dcDrag.BitBlt( rcOne.left - rcAll.left, rcOne.top - rcAll.top,
00913 m_szTrack.cx, m_szTrack.cy, pBuffer, 0, 0, SRCCOPY );
00914 }
00915 }
00916
00917 pBuffer->SelectObject( pOldFont );
00918 dcDrag.SelectObject( pOldDrag );
00919 dcDrag.DeleteDC();
00920
00921 CImageList* pAll = new CImageList();
00922 pAll->Create( rcAll.Width(), rcAll.Height(), ILC_COLOR16|ILC_MASK, 1, 1 );
00923 pAll->Add( &bmDrag, RGB( 0, 255, 0 ) );
00924
00925 bmDrag.DeleteObject();
00926
00927 pAll->BeginDrag( 0, ptMouse - rcAll.TopLeft() );
00928
00929 return pAll;
00930 }
00931
00932
00934
00935
00936 CLibraryAlbumTrack::CLibraryAlbumTrack(CLibraryFile* pFile)
00937 {
00938 m_nIndex = pFile->m_nIndex;
00939 m_nCookie = pFile->m_nUpdateCookie - 1;
00940 m_bSelected = FALSE;
00941
00942 Update( pFile );
00943 }
00944
00945 CLibraryAlbumTrack::~CLibraryAlbumTrack()
00946 {
00947 }
00948
00950
00951
00952 BOOL CLibraryAlbumTrack::Update(CLibraryFile* pFile)
00953 {
00954 BOOL bShared = pFile->IsShared();
00955
00956 if ( m_nCookie == pFile->m_nUpdateCookie && m_bShared == bShared ) return FALSE;
00957
00958 m_nCookie = pFile->m_nUpdateCookie;
00959 m_bShared = bShared;
00960 m_nShell = ShellIcons.Get( pFile->m_sName, 16 );
00961 m_nRating = pFile->m_nRating;
00962 m_bComments = pFile->m_sComments.GetLength() > 0;
00963 m_nTrack = 0;
00964 m_sTrack.Empty();
00965 m_sTitle.Empty();
00966 m_sArtist.Empty();
00967 m_sAlbum.Empty();
00968 m_nLength = 0;
00969 m_sLength.Empty();
00970 m_nBitrate = 0;
00971 m_sBitrate.Empty();
00972
00973 if ( pFile->IsSchemaURI( CSchema::uriAudio ) )
00974 {
00975 CString str = pFile->m_pMetadata->GetAttributeValue( _T("track") );
00976 LPCTSTR psz = str;
00977
00978 while ( *psz == '0' ) psz++;
00979 if ( *psz ) _stscanf( psz, _T("%i"), &m_nTrack );
00980
00981 m_sTitle = pFile->m_pMetadata->GetAttributeValue( _T("title") );
00982 m_sArtist = pFile->m_pMetadata->GetAttributeValue( _T("artist") );
00983 m_sAlbum = pFile->m_pMetadata->GetAttributeValue( _T("album") );
00984
00985 _stscanf( pFile->m_pMetadata->GetAttributeValue( _T("seconds") ), _T("%i"), &m_nLength );
00986 _stscanf( pFile->m_pMetadata->GetAttributeValue( _T("bitrate") ), _T("%i"), &m_nBitrate );
00987 }
00988
00989 int nDash = pFile->m_sName.Find( '-' );
00990
00991 if ( nDash > 0 )
00992 {
00993 if ( m_sArtist.IsEmpty() ) m_sArtist = pFile->m_sName.Left( nDash );
00994 nDash = pFile->m_sName.ReverseFind( '-' );
00995 if ( m_sTitle.IsEmpty() )
00996 {
00997 m_sTitle = pFile->m_sName.Mid( nDash + 1 );
00998 nDash = m_sTitle.ReverseFind( '.' );
00999 if ( nDash >= 0 ) m_sTitle = m_sTitle.Left( nDash );
01000 }
01001 }
01002 else if ( m_sTitle.IsEmpty() )
01003 {
01004 m_sTitle = pFile->m_sName;
01005 nDash = m_sTitle.ReverseFind( '.' );
01006 if ( nDash >= 0 ) m_sTitle = m_sTitle.Left( nDash );
01007 }
01008
01009 m_sTitle.TrimLeft();
01010 m_sTitle.TrimRight();
01011 m_sArtist.TrimLeft();
01012 m_sArtist.TrimRight();
01013 m_sAlbum.TrimLeft();
01014 m_sAlbum.TrimRight();
01015
01016 if ( m_nTrack > 0 )
01017 {
01018 m_sTrack.Format( _T("%i"), m_nTrack );
01019 }
01020
01021 if ( m_nLength > 0 )
01022 {
01023 m_sLength.Format( _T("%i:%.2i"), m_nLength / 60, m_nLength % 60 );
01024 }
01025
01026 if ( m_nBitrate > 0 )
01027 {
01028 m_sBitrate.Format( _T("%ik"), m_nBitrate );
01029 }
01030
01031 return TRUE;
01032 }
01033
01035
01036
01037 void CLibraryAlbumTrack::Paint(CLibraryAlbumView* pView, CDC* pDC, const CRect& rcTrack, int nCount)
01038 {
01039 COLORREF crBack1 = CLibraryAlbumView::m_crRows[ nCount & 1 ];
01040 COLORREF crBack2 = m_bSelected ? CoolInterface.m_crHighlight : crBack1;
01041
01042 CRect rcLine( &rcTrack );
01043 rcLine.DeflateRect( 1, 1 );
01044 rcLine.left ++; rcLine.right --;
01045
01046 CRect rcTemp( rcLine.left, rcLine.top, rcLine.left + 22, rcLine.bottom );
01047 rcLine.left += 22;
01048
01049 pDC->SetBkColor( crBack1 );
01050 if ( nCount >= 0 ) PaintText( pDC, rcTemp, 0, 100, NULL );
01051 if ( m_bSelected ) pDC->SetBkColor( crBack2 );
01052
01053 ShellIcons.Draw( pDC, m_nShell, 16, rcTemp.left + 3,
01054 ( rcTemp.top + rcTemp.bottom ) / 2 - 8, CLR_NONE, m_bSelected );
01055
01056 pDC->SetTextColor( m_bSelected ? CoolInterface.m_crHiText : CoolInterface.m_crText );
01057
01058 rcTemp.SetRect( rcLine.right - 78, rcLine.top, rcLine.right, rcLine.bottom );
01059 rcLine.right -= 78;
01060
01061 CPoint ptStar( rcTemp.left + 3, ( rcTemp.top + rcTemp.bottom ) / 2 - 6 );
01062 PaintText( pDC, rcTemp, 0, 100, NULL );
01063
01064 if ( pView->m_pRating == this && m_nSetRating < 7 )
01065 {
01066 for ( int nRating = 2 ; nRating <= 6 ; nRating++ )
01067 {
01068 ImageList_DrawEx( pView->m_pStars, m_nSetRating >= nRating ? 2 : 1,
01069 *pDC, ptStar.x, ptStar.y, 12, 12, crBack2, crBack2,
01070 m_nSetRating >= nRating ? ILD_NORMAL : ILD_BLEND50 );
01071 ptStar.x += 12;
01072 }
01073 }
01074 else
01075 {
01076 for ( int nRating = 2 ; nRating <= 6 ; nRating++ )
01077 {
01078 ImageList_DrawEx( pView->m_pStars, m_nRating >= nRating ? 0 : 1,
01079 *pDC, ptStar.x, ptStar.y, 12, 12, crBack2, crBack2,
01080 m_nRating >= nRating ? ILD_NORMAL : ILD_BLEND50 );
01081 ptStar.x += 12;
01082 }
01083 }
01084
01085 if ( pView->m_pRating == this && m_nSetRating == 7 )
01086 {
01087 ImageList_DrawEx( pView->m_pStars, 5,
01088 *pDC, ptStar.x, ptStar.y, 12, 12, crBack2, crBack2, ILD_NORMAL );
01089 }
01090 else
01091 {
01092 ImageList_DrawEx( pView->m_pStars, m_bComments ? 3 : 4,
01093 *pDC, ptStar.x, ptStar.y, 12, 12, crBack2, crBack2,
01094 m_bComments ? ILD_NORMAL : ILD_BLEND50 );
01095 }
01096
01097 if ( pView->m_pStyle == CSchema::uriMusicAlbum )
01098 {
01099
01100 PaintText( pDC, rcLine, 0, 5, &m_sTrack, TRUE );
01101 PaintText( pDC, rcLine, 5, 84, &m_sTitle );
01102 PaintText( pDC, rcLine, 84, 92, &m_sLength, TRUE );
01103 PaintText( pDC, rcLine, 92, 100, &m_sBitrate, TRUE );
01104 }
01105 else if ( pView->m_pStyle == CSchema::uriMusicArtist )
01106 {
01107
01108 PaintText( pDC, rcLine, 0, 30, &m_sAlbum );
01109 PaintText( pDC, rcLine, 30, 84, &m_sTitle );
01110 PaintText( pDC, rcLine, 84, 92, &m_sLength, TRUE );
01111 PaintText( pDC, rcLine, 92, 100, &m_sBitrate, TRUE );
01112 }
01113 else
01114 {
01115
01116 PaintText( pDC, rcLine, 0, 25, &m_sArtist );
01117 PaintText( pDC, rcLine, 25, 50, &m_sAlbum );
01118 PaintText( pDC, rcLine, 50, 84, &m_sTitle );
01119 PaintText( pDC, rcLine, 84, 92, &m_sLength, TRUE );
01120 PaintText( pDC, rcLine, 92, 100, &m_sBitrate, TRUE );
01121 }
01122 }
01123
01124 void CLibraryAlbumTrack::PaintText(CDC* pDC, const CRect& rcTrack, int nFrom, int nTo, const CString* pstr, BOOL bCenter)
01125 {
01126 CRect rcText;
01127
01128 rcText.left = rcTrack.left + rcTrack.Width() * nFrom / 100 + 1;
01129 rcText.right = rcTrack.left + rcTrack.Width() * nTo / 100 - 1;
01130 rcText.top = rcTrack.top;
01131 rcText.bottom = rcTrack.bottom;
01132
01133 COLORREF crOld = pDC->GetPixel( rcText.left, rcText.top );
01134
01135 if ( pstr != NULL )
01136 {
01137 if ( bCenter || pstr->GetLength() )
01138 {
01139 CSize szText = pDC->GetTextExtent( *pstr );
01140 int nText = pstr->GetLength();
01141
01142 if ( szText.cx + 8 > rcText.Width() )
01143 {
01144 while ( nText > 0 )
01145 {
01146 nText--;
01147 szText = pDC->GetTextExtent( *pstr, nText );
01148 szText.cx += 8;
01149 if ( szText.cx + 8 <= rcText.Width() ) break;
01150 }
01151
01152 CString str = pstr->Left( nText ) + _T('\x2026');
01153
01154 pDC->ExtTextOut( bCenter ? ( ( rcText.left + rcText.right ) / 2 - szText.cx / 2 ) : ( rcText.left + 4 ),
01155 ( rcText.top + rcText.bottom ) / 2 - szText.cy / 2 - 1,
01156 ETO_CLIPPED|ETO_OPAQUE, &rcText, str, NULL );
01157 }
01158 else
01159 {
01160 pDC->ExtTextOut( bCenter ? ( ( rcText.left + rcText.right ) / 2 - szText.cx / 2 ) : ( rcText.left + 4 ),
01161 ( rcText.top + rcText.bottom ) / 2 - szText.cy / 2 - 1,
01162 ETO_CLIPPED|ETO_OPAQUE, &rcText, *pstr, nText, NULL );
01163 }
01164 }
01165 else
01166 {
01167 CSize szText = pDC->GetTextExtent( _T("?") );
01168
01169 pDC->ExtTextOut( ( rcText.left + 4 ),
01170 ( rcText.top + rcText.bottom ) / 2 - szText.cy / 2 - 1,
01171 ETO_CLIPPED|ETO_OPAQUE, &rcText, _T("?"), 1, NULL );
01172 }
01173 }
01174 else
01175 {
01176 pDC->ExtTextOut( rcText.left, rcText.top, ETO_OPAQUE, &rcText, NULL, 0, NULL );
01177 }
01178
01179 pDC->SetPixel( rcText.left, rcText.top, crOld );
01180 pDC->SetPixel( rcText.right - 1, rcText.top, crOld );
01181 pDC->SetPixel( rcText.left, rcText.bottom - 1, crOld );
01182 pDC->SetPixel( rcText.right - 1, rcText.bottom - 1, crOld );
01183 }
01184
01186
01187
01188 BOOL CLibraryAlbumTrack::HitTestRating(const CRect& rcBlock, const CPoint& point)
01189 {
01190 if ( point.x < rcBlock.right - 79 ) return FALSE;
01191
01192 if ( point.x >= rcBlock.right - 3 - 12 )
01193 {
01194 m_nSetRating = 7;
01195 return TRUE;
01196 }
01197
01198 int nPos = rcBlock.right - 72;
01199
01200 for ( m_nSetRating = 1 ; m_nSetRating <= 6 ; m_nSetRating++ )
01201 {
01202 if ( point.x < nPos ) break;
01203 nPos += 12;
01204 }
01205
01206 m_nSetRating = min( m_nSetRating, 6 );
01207
01208 return TRUE;
01209 }
01210
01211 BOOL CLibraryAlbumTrack::LockRating()
01212 {
01213 if ( m_nSetRating == 7 )
01214 {
01215 CFilePropertiesSheet dlg;
01216 dlg.Add( m_nIndex );
01217 return dlg.DoModal( 2 ) == IDOK;
01218 }
01219 else if ( m_nSetRating >= 0 && m_nSetRating <= 6 )
01220 {
01221 CQuickLock oLock( Library.m_pSection );
01222 CLibraryFile* pFile = Library.LookupFile( m_nIndex );
01223 if ( pFile == NULL ) return FALSE;
01224
01225 pFile->m_nRating = m_nRating = ( m_nSetRating > 1 ? m_nSetRating : 0 );
01226 pFile->SaveMetadata();
01227
01228 Library.Update();
01229 return TRUE;
01230 }
01231 else
01232 {
01233 return FALSE;
01234 }
01235 }