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 "LibraryFolders.h"
00027 #include "AlbumFolder.h"
00028 #include "Schema.h"
00029 #include "CtrlLibraryFrame.h"
00030 #include "CtrlLibraryTree.h"
00031 #include "CtrlLibraryTileView.h"
00032 #include "DlgFolderProperties.h"
00033 #include "CoolInterface.h"
00034 #include "ShellIcons.h"
00035 #include "Skin.h"
00036
00037 #ifdef _DEBUG
00038 #define new DEBUG_NEW
00039 #undef THIS_FILE
00040 static char THIS_FILE[] = __FILE__;
00041 #endif
00042
00043 BEGIN_MESSAGE_MAP(CLibraryTileView, CLibraryView)
00044
00045 ON_WM_CREATE()
00046 ON_WM_DESTROY()
00047 ON_WM_SIZE()
00048 ON_WM_PAINT()
00049 ON_WM_VSCROLL()
00050 ON_WM_MOUSEWHEEL()
00051 ON_WM_LBUTTONDOWN()
00052 ON_WM_MOUSEMOVE()
00053 ON_WM_LBUTTONUP()
00054 ON_WM_RBUTTONDOWN()
00055 ON_WM_KEYDOWN()
00056 ON_WM_LBUTTONDBLCLK()
00057 ON_WM_CONTEXTMENU()
00058 ON_WM_CHAR()
00059 ON_UPDATE_COMMAND_UI(ID_LIBRARY_ALBUM_OPEN, OnUpdateLibraryAlbumOpen)
00060 ON_COMMAND(ID_LIBRARY_ALBUM_OPEN, OnLibraryAlbumOpen)
00061 ON_UPDATE_COMMAND_UI(ID_LIBRARY_ALBUM_DELETE, OnUpdateLibraryAlbumDelete)
00062 ON_COMMAND(ID_LIBRARY_ALBUM_DELETE, OnLibraryAlbumDelete)
00063 ON_UPDATE_COMMAND_UI(ID_LIBRARY_ALBUM_PROPERTIES, OnUpdateLibraryAlbumProperties)
00064 ON_COMMAND(ID_LIBRARY_ALBUM_PROPERTIES, OnLibraryAlbumProperties)
00065
00066 END_MESSAGE_MAP()
00067
00068
00070
00071
00072 CLibraryTileView::CLibraryTileView()
00073 {
00074 m_nCommandID = ID_LIBRARY_VIEW_TILE;
00075 m_pszToolBar = _T("CLibraryTileView");
00076 }
00077
00078 CLibraryTileView::~CLibraryTileView()
00079 {
00080 }
00081
00083
00084
00085 BOOL CLibraryTileView::PreCreateWindow(CREATESTRUCT& cs)
00086 {
00087 return CLibraryView::PreCreateWindow( cs );
00088 }
00089
00090 int CLibraryTileView::OnCreate(LPCREATESTRUCT lpCreateStruct)
00091 {
00092 if ( CLibraryView::OnCreate( lpCreateStruct ) == -1 ) return -1;
00093
00094 m_szBlock.cx = 252;
00095 m_szBlock.cy = 56;
00096 m_nColumns = 1;
00097 m_nRows = 0;
00098
00099 m_pList = NULL;
00100 m_nCount = 0;
00101 m_nBuffer = 0;
00102 m_nScroll = 0;
00103 m_nSelected = 0;
00104 m_pFocus = NULL;
00105 m_pFirst = NULL;
00106 m_bDrag = FALSE;
00107
00108 return 0;
00109 }
00110
00111 void CLibraryTileView::OnDestroy()
00112 {
00113 Clear();
00114 CLibraryView::OnDestroy();
00115 }
00116
00118
00119
00120 BOOL CLibraryTileView::CheckAvailable(CLibraryTreeItem* pSel)
00121 {
00122 m_bAvailable = FALSE;
00123
00124 if ( pSel != NULL && pSel->m_pSelNext == NULL && pSel->m_pVirtual != NULL )
00125 {
00126 m_bAvailable = ( pSel->m_pVirtual->GetFileCount() == 0 );
00127 }
00128
00129 return m_bAvailable;
00130 }
00131
00132 void CLibraryTileView::Update()
00133 {
00134 CLibraryTreeItem* pFolders = GetFolderSelection();
00135 CAlbumFolder* pFolder = NULL;
00136
00137 if ( pFolders == NULL || pFolders->m_pVirtual == NULL )
00138 {
00139 pFolder = Library.GetAlbumRoot();
00140 }
00141 else
00142 {
00143 if ( pFolders == NULL || pFolders->m_pSelNext != NULL ||
00144 pFolders->m_pVirtual == NULL ||
00145 pFolders->m_pVirtual->GetFileCount() > 0 )
00146 {
00147 if ( m_nCount > 0 )
00148 {
00149 Clear();
00150 Invalidate();
00151 }
00152
00153 return;
00154 }
00155
00156 pFolder = pFolders->m_pVirtual;
00157 }
00158
00159 DWORD nCookie = GetFolderCookie();
00160 BOOL bChanged = FALSE;
00161
00162 CLibraryTileItem** pList = m_pList + m_nCount - 1;
00163
00164 for ( int nItem = m_nCount ; nItem ; nItem--, pList-- )
00165 {
00166 CLibraryTileItem* pTile = *pList;
00167
00168 if ( pFolder->CheckFolder( pTile->m_pFolder ) )
00169 {
00170 bChanged |= pTile->Update();
00171 pTile->m_pFolder->m_nListCookie = nCookie;
00172 }
00173 else
00174 {
00175 if ( pTile->m_bSelected ) Select( pTile, TS_FALSE );
00176 if ( pTile == m_pFocus ) m_pFocus = NULL;
00177 if ( pTile == m_pFirst ) m_pFirst = NULL;
00178
00179 delete pTile;
00180 MoveMemory( pList, pList + 1, 4 * ( m_nCount - nItem ) );
00181 m_nCount--;
00182
00183 bChanged = TRUE;
00184 }
00185 }
00186
00187 if ( bChanged )
00188 {
00189 CRect rcClient;
00190 GetClientRect( &rcClient );
00191 int nMax = ( ( m_nCount + m_nColumns - 1 ) / m_nColumns ) * m_szBlock.cy;
00192 m_nScroll = max( 0, min( m_nScroll, nMax - rcClient.Height() + 1 ) );
00193 }
00194
00195 for ( POSITION pos = pFolder->GetFolderIterator() ; pos ; )
00196 {
00197 CAlbumFolder* pChild = pFolder->GetNextFolder( pos );
00198
00199 if ( pChild->m_nListCookie != nCookie )
00200 {
00201 CLibraryTileItem* pTile = new CLibraryTileItem( pChild );
00202
00203 if ( m_nCount == m_nBuffer )
00204 {
00205 m_nBuffer += 64;
00206 CLibraryTileItem** pList = new CLibraryTileItem*[ m_nBuffer ];
00207 if ( m_nCount ) CopyMemory( pList, m_pList, 4 * m_nCount );
00208 if ( m_pList ) delete [] m_pList;
00209 m_pList = pList;
00210 }
00211
00212 m_pList[ m_nCount++ ] = pTile;
00213 pChild->m_nListCookie = nCookie;
00214 bChanged = TRUE;
00215 }
00216 }
00217
00218 if ( bChanged )
00219 {
00220 qsort( m_pList, m_nCount, 4, SortList );
00221 UpdateScroll();
00222 }
00223 }
00224
00225 BOOL CLibraryTileView::Select(DWORD nObject)
00226 {
00227 return FALSE;
00228 }
00229
00231
00232
00233 void CLibraryTileView::Clear()
00234 {
00235 for ( int nItem = 0 ; nItem < m_nCount ; nItem++ )
00236 {
00237 delete m_pList[ nItem ];
00238 }
00239
00240 if ( m_pList ) delete [] m_pList;
00241
00242 m_pList = NULL;
00243 m_nCount = 0;
00244 m_nBuffer = 0;
00245 m_nScroll = 0;
00246 m_nSelected = 0;
00247 m_pFocus = NULL;
00248 m_pFirst = NULL;
00249
00250 m_pSelTile.RemoveAll();
00251 SelClear();
00252 }
00253
00254 int CLibraryTileView::GetTileIndex(CLibraryTileItem* pTile) const
00255 {
00256 CLibraryTileItem** pList = m_pList;
00257
00258 for ( int nItem = 0 ; nItem < m_nCount ; nItem++, pList++ )
00259 {
00260 if ( *pList == pTile ) return nItem;
00261 }
00262
00263 return -1;
00264 }
00265
00266 BOOL CLibraryTileView::Select(CLibraryTileItem* pTile, TRISTATE bSelect)
00267 {
00268 switch ( bSelect )
00269 {
00270 case TS_UNKNOWN:
00271 pTile->m_bSelected = ! pTile->m_bSelected;
00272 break;
00273 case TS_FALSE:
00274 if ( pTile->m_bSelected == FALSE ) return FALSE;
00275 pTile->m_bSelected = FALSE;
00276 break;
00277 case TS_TRUE:
00278 if ( pTile->m_bSelected == TRUE ) return FALSE;
00279 pTile->m_bSelected = TRUE;
00280 break;
00281 }
00282
00283 if ( pTile->m_bSelected )
00284 {
00285 m_nSelected++;
00286 m_pSelTile.AddTail( pTile );
00287 SelAdd( (DWORD)pTile->m_pFolder );
00288 }
00289 else
00290 {
00291 m_nSelected--;
00292 if ( POSITION pos = m_pSelTile.Find( pTile ) )
00293 {
00294 m_pSelTile.RemoveAt( pos );
00295 SelRemove( (DWORD)pTile->m_pFolder );
00296 }
00297 }
00298
00299 return TRUE;
00300 }
00301
00302 BOOL CLibraryTileView::DeselectAll(CLibraryTileItem* pTile)
00303 {
00304 CLibraryTileItem** pList = m_pList + m_nCount - 1;
00305 BOOL bChanged = FALSE;
00306
00307 for ( int nItem = m_nCount ; nItem ; nItem--, pList-- )
00308 {
00309 if ( *pList != pTile )
00310 {
00311 if ( (*pList)->m_bSelected ) bChanged = Select( *pList, TS_FALSE );
00312 }
00313 }
00314
00315 return bChanged;
00316 }
00317
00318 BOOL CLibraryTileView::SelectTo(CLibraryTileItem* pTile)
00319 {
00320 BOOL bChanged = FALSE;
00321
00322 if ( pTile )
00323 {
00324 m_pFocus = pTile;
00325
00326 int nFirst = GetTileIndex( m_pFirst );
00327 int nFocus = GetTileIndex( m_pFocus );
00328
00329 if ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 )
00330 {
00331 bChanged = Select( m_pFocus, TS_UNKNOWN );
00332 }
00333 else if ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 )
00334 {
00335 bChanged = DeselectAll();
00336
00337 if ( nFirst >= 0 && nFocus >= 0 )
00338 {
00339 if ( nFirst <= nFocus )
00340 {
00341 for ( ; nFirst <= nFocus ; nFirst++ ) Select( m_pList[ nFirst ], TS_TRUE );
00342 }
00343 else
00344 {
00345 for ( ; nFocus <= nFirst ; nFocus++ ) Select( m_pList[ nFocus ], TS_TRUE );
00346 }
00347
00348 bChanged = TRUE;
00349 }
00350 else
00351 {
00352 bChanged |= Select( m_pFocus, TS_TRUE );
00353 }
00354 }
00355 else
00356 {
00357 if ( m_pFocus->m_bSelected == FALSE ) bChanged = DeselectAll( m_pFocus );
00358 bChanged |= Select( m_pFocus );
00359 }
00360
00361 if ( m_nSelected == 1 && m_pFocus->m_bSelected ) m_pFirst = m_pFocus;
00362
00363 Highlight( m_pFocus );
00364 }
00365 else if ( ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) == 0 &&
00366 ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) == 0 )
00367 {
00368 bChanged = DeselectAll();
00369 }
00370
00371 if ( m_nSelected == 0 ) m_pFirst = NULL;
00372
00373 return bChanged;
00374 }
00375
00376 void CLibraryTileView::SelectTo(int nDelta)
00377 {
00378 if ( m_nCount == 0 ) return;
00379
00380 int nFocus = GetTileIndex( m_pFocus );
00381
00382 if ( nFocus < 0 )
00383 {
00384 nFocus = 0;
00385 }
00386 else
00387 {
00388 nFocus += nDelta;
00389 if ( nFocus < 0 ) nFocus = 0;
00390 if ( nFocus >= m_nCount ) nFocus = m_nCount - 1;
00391 }
00392
00393 if ( SelectTo( m_pList[ nFocus ] ) ) Invalidate();
00394 }
00395
00396 void CLibraryTileView::Highlight(CLibraryTileItem* pItem)
00397 {
00398 CRect rcClient, rcItem;
00399
00400 GetClientRect( &rcClient );
00401 GetItemRect( pItem, &rcItem );
00402
00403 if ( rcItem.top < rcClient.top )
00404 {
00405 ScrollBy( rcItem.top - rcClient.top );
00406 }
00407 else if ( rcItem.bottom > rcClient.bottom )
00408 {
00409 ScrollBy( rcItem.bottom - rcClient.bottom );
00410 }
00411 }
00412
00413 int CLibraryTileView::SortList(LPCVOID pA, LPCVOID pB)
00414 {
00415 CLibraryTileItem* ppA = *(CLibraryTileItem**)pA;
00416 CLibraryTileItem* ppB = *(CLibraryTileItem**)pB;
00417 return _tcsicoll( ppA->m_sTitle, ppB->m_sTitle );
00418 }
00419
00421
00422
00423 void CLibraryTileView::OnSize(UINT nType, int cx, int cy)
00424 {
00425 CLibraryView::OnSize( nType, cx, cy );
00426
00427 m_nColumns = cx / m_szBlock.cx;
00428 m_nRows = cy / m_szBlock.cy + 1;
00429
00430 m_nColumns = max( m_nColumns, 1 );
00431
00432 UpdateScroll();
00433 }
00434
00435 void CLibraryTileView::UpdateScroll()
00436 {
00437 if ( m_nColumns == 0 ) return;
00438
00439 SCROLLINFO pInfo;
00440 CRect rc;
00441
00442 GetClientRect( &rc );
00443
00444 pInfo.cbSize = sizeof(pInfo);
00445 pInfo.fMask = SIF_ALL & ~SIF_TRACKPOS;
00446 pInfo.nMin = 0;
00447 pInfo.nMax = ( ( m_nCount + m_nColumns - 1 ) / m_nColumns ) * m_szBlock.cy;
00448 pInfo.nPage = rc.Height();;
00449 pInfo.nPos = m_nScroll = max( 0, min( m_nScroll, pInfo.nMax - (int)pInfo.nPage + 1 ) );
00450
00451 SetScrollInfo( SB_VERT, &pInfo, TRUE );
00452
00453 Invalidate();
00454 }
00455
00456 void CLibraryTileView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
00457 {
00458 CRect rc;
00459 GetClientRect( &rc );
00460
00461 SetFocus();
00462
00463 switch ( nSBCode )
00464 {
00465 case SB_BOTTOM:
00466 ScrollTo( 0xFFFFFF );
00467 break;
00468 case SB_LINEDOWN:
00469 ScrollBy( 32 );
00470 break;
00471 case SB_LINEUP:
00472 ScrollBy( -32 );
00473 break;
00474 case SB_PAGEDOWN:
00475 ScrollBy( rc.Height() );
00476 break;
00477 case SB_PAGEUP:
00478 ScrollBy( -rc.Height() );
00479 break;
00480 case SB_THUMBPOSITION:
00481 case SB_THUMBTRACK:
00482 ScrollTo( nPos );
00483 break;
00484 case SB_TOP:
00485 ScrollTo( 0 );
00486 break;
00487 }
00488 }
00489
00490 BOOL CLibraryTileView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
00491 {
00492 ScrollBy( zDelta * -m_szBlock.cy / WHEEL_DELTA / 2 );
00493 return TRUE;
00494 }
00495
00496 void CLibraryTileView::ScrollBy(int nDelta)
00497 {
00498 ScrollTo( max( 0, m_nScroll + nDelta ) );
00499 }
00500
00501 void CLibraryTileView::ScrollTo(int nPosition)
00502 {
00503 if ( nPosition == m_nScroll ) return;
00504 m_nScroll = nPosition;
00505
00506 UpdateScroll();
00507 RedrawWindow( NULL, NULL, RDW_INVALIDATE );
00508 }
00509
00510 void CLibraryTileView::OnPaint()
00511 {
00512 CPaintDC dc( this );
00513
00514 CDC* pBuffer = CoolInterface.GetBuffer( dc, m_szBlock );
00515 CRect rcBuffer( 0, 0, m_szBlock.cx, m_szBlock.cy );
00516
00517 CFont* pOldFont = (CFont*)pBuffer->SelectObject( &CoolInterface.m_fntNormal );
00518 pBuffer->SetBkMode( OPAQUE );
00519 pBuffer->SetBkColor( CoolInterface.m_crWindow );
00520 pBuffer->SetTextColor( CoolInterface.m_crText );
00521
00522 CDC dcMem;
00523 dcMem.CreateCompatibleDC( &dc );
00524
00525 CRect rcClient;
00526 GetClientRect( &rcClient );
00527 CPoint pt( rcClient.left, rcClient.top - m_nScroll );
00528
00529 CLibraryTileItem** pList = m_pList;
00530
00531 for ( int nItem = m_nCount ; nItem && pt.y < rcClient.bottom ; nItem--, pList++ )
00532 {
00533 CLibraryTileItem* pTile = *pList;
00534
00535 CRect rcBlock( pt.x, pt.y, pt.x + m_szBlock.cx, pt.y + m_szBlock.cy );
00536
00537 if ( rcBlock.bottom >= rcClient.top && dc.RectVisible( &rcBlock ) )
00538 {
00539 pBuffer->FillSolidRect( &rcBuffer, CoolInterface.m_crWindow );
00540 pTile->Paint( pBuffer, rcBuffer, &dcMem );
00541 dc.BitBlt( rcBlock.left, rcBlock.top, m_szBlock.cx, m_szBlock.cy,
00542 pBuffer, 0, 0, SRCCOPY );
00543 dc.ExcludeClipRect( &rcBlock );
00544 }
00545
00546 pt.x += m_szBlock.cx;
00547
00548 if ( pt.x + m_szBlock.cx > rcClient.right )
00549 {
00550 pt.x = rcClient.left;
00551 pt.y += m_szBlock.cy;
00552 }
00553 }
00554
00555 pBuffer->SelectObject( pOldFont );
00556 dc.FillSolidRect( &rcClient, CoolInterface.m_crWindow );
00557 }
00558
00559 CLibraryTileItem* CLibraryTileView::HitTest(const CPoint& point) const
00560 {
00561 CRect rcClient;
00562 GetClientRect( &rcClient );
00563
00564 CPoint pt( rcClient.left, rcClient.top - m_nScroll );
00565
00566 CLibraryTileItem** pList = m_pList;
00567
00568 for ( int nItem = m_nCount ; nItem && pt.y < rcClient.bottom ; nItem--, pList++ )
00569 {
00570 CLibraryTileItem* pTile = *pList;
00571
00572 CRect rcBlock( pt.x, pt.y, pt.x + m_szBlock.cx, pt.y + m_szBlock.cy );
00573
00574 if ( rcBlock.PtInRect( point ) ) return pTile;
00575
00576 pt.x += m_szBlock.cx;
00577
00578 if ( pt.x + m_szBlock.cx > rcClient.right )
00579 {
00580 pt.x = rcClient.left;
00581 pt.y += m_szBlock.cy;
00582 }
00583 }
00584
00585 return NULL;
00586 }
00587
00588 BOOL CLibraryTileView::GetItemRect(CLibraryTileItem* pTile, CRect* pRect)
00589 {
00590 CRect rcClient;
00591 GetClientRect( &rcClient );
00592
00593 CPoint pt( rcClient.left, rcClient.top - m_nScroll );
00594
00595 CLibraryTileItem** pList = m_pList;
00596
00597 for ( int nItem = m_nCount ; nItem ; nItem--, pList++ )
00598 {
00599 CRect rcBlock( pt.x, pt.y, pt.x + m_szBlock.cx, pt.y + m_szBlock.cy );
00600
00601 if ( pTile == *pList )
00602 {
00603 *pRect = rcBlock;
00604 return TRUE;
00605 }
00606
00607 pt.x += m_szBlock.cx;
00608
00609 if ( pt.x + m_szBlock.cx > rcClient.right )
00610 {
00611 pt.x = rcClient.left;
00612 pt.y += m_szBlock.cy;
00613 }
00614 }
00615
00616 return FALSE;
00617 }
00618
00619 void CLibraryTileView::OnLButtonDown(UINT nFlags, CPoint point)
00620 {
00621 CLibraryTileItem* pHit = HitTest( point );
00622
00623 if ( SelectTo( pHit ) ) Invalidate();
00624
00625 SetFocus();
00626 SetCapture();
00627
00628 if ( pHit && ( nFlags & MK_RBUTTON ) == 0 && Settings.Library.ShowVirtual )
00629 {
00630 m_bDrag = TRUE;
00631 m_ptDrag = point;
00632 }
00633
00634 CLibraryView::OnLButtonDown( nFlags, point );
00635 }
00636
00637 void CLibraryTileView::OnMouseMove(UINT nFlags, CPoint point)
00638 {
00639 if ( m_bDrag & ( nFlags & MK_LBUTTON ) )
00640 {
00641 CSize szDiff = point - m_ptDrag;
00642
00643 if ( abs( szDiff.cx ) > 5 || abs( szDiff.cy ) > 5 )
00644 {
00645 m_bDrag = FALSE;
00646 StartDragging( point );
00647 }
00648 }
00649
00650 CLibraryView::OnMouseMove( nFlags, point );
00651 }
00652
00653 void CLibraryTileView::OnLButtonUp(UINT nFlags, CPoint point)
00654 {
00655 ReleaseCapture();
00656 m_bDrag = FALSE;
00657
00658 if ( ( nFlags & (MK_SHIFT|MK_CONTROL) ) == 0 && m_pFocus && m_pFocus->m_bSelected )
00659 {
00660 if ( DeselectAll( m_pFocus ) ) Invalidate();
00661 }
00662 }
00663
00664 void CLibraryTileView::OnLButtonDblClk(UINT nFlags, CPoint point)
00665 {
00666 SendMessage( WM_COMMAND, ID_LIBRARY_ALBUM_OPEN );
00667 }
00668
00669 void CLibraryTileView::OnRButtonDown(UINT nFlags, CPoint point)
00670 {
00671 OnLButtonDown( nFlags, point );
00672 CLibraryView::OnRButtonDown( nFlags, point );
00673 }
00674
00675 void CLibraryTileView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
00676 {
00677 switch ( nChar )
00678 {
00679 case VK_LEFT:
00680 SelectTo( - 1 );
00681 break;
00682 case VK_RIGHT:
00683 SelectTo( 1 );
00684 break;
00685 case VK_UP:
00686 SelectTo( -m_nColumns );
00687 break;
00688 case VK_DOWN:
00689 SelectTo( m_nColumns );
00690 break;
00691 case VK_PRIOR:
00692 SelectTo( m_nRows * -m_nColumns );
00693 break;
00694 case VK_NEXT:
00695 ScrollBy( m_nRows * m_nColumns );
00696 break;
00697 case VK_HOME:
00698 SelectTo( -m_nCount );
00699 break;
00700 case VK_END:
00701 SelectTo( m_nCount );
00702 break;
00703 case VK_RETURN:
00704 PostMessage( WM_COMMAND, ID_LIBRARY_ALBUM_OPEN );
00705 break;
00706 }
00707
00708 CLibraryView::OnKeyDown( nChar, nRepCnt, nFlags );
00709 }
00710
00711 void CLibraryTileView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
00712 {
00713 if ( _istalnum( nChar ) )
00714 {
00715 CLibraryTileItem* pStart = m_pFocus;
00716
00717 for ( int nLoop = 0 ; nLoop < 2 ; nLoop++ )
00718 {
00719 CLibraryTileItem** pChild = m_pList;
00720
00721 for ( int nCount = m_nCount ; nCount ; nCount--, pChild++ )
00722 {
00723 if ( pStart != NULL )
00724 {
00725 if ( pStart == *pChild ) pStart = NULL;
00726 }
00727 else if ( toupper( (*pChild)->m_sTitle.GetAt( 0 ) ) == toupper( (int)nChar ) )
00728 {
00729 DeselectAll( m_pFocus = *pChild );
00730 Select( m_pFocus, TS_TRUE );
00731 Highlight( m_pFocus );
00732 Invalidate();
00733 return;
00734 }
00735 }
00736 }
00737 }
00738
00739 CLibraryView::OnChar( nChar, nRepCnt, nFlags );
00740 }
00741
00743
00744
00745 #define MAX_DRAG_SIZE 256
00746 #define MAX_DRAG_SIZE_2 128
00747
00748 void CLibraryTileView::StartDragging(CPoint& ptMouse)
00749 {
00750 CImageList* pImage = CreateDragImage( ptMouse );
00751 if ( ! pImage ) return;
00752
00753 ReleaseCapture();
00754 ClientToScreen( &ptMouse );
00755 DragObjects( pImage, ptMouse );
00756 }
00757
00758 CImageList* CLibraryTileView::CreateDragImage(const CPoint& ptMouse)
00759 {
00760 CRect rcClient, rcOne, rcAll( 32000, 32000, -32000, -32000 );
00761
00762 GetClientRect( &rcClient );
00763
00764 for ( POSITION pos = m_pSelTile.GetHeadPosition() ; pos ; )
00765 {
00766 CLibraryTileItem* pTile = (CLibraryTileItem*)m_pSelTile.GetNext( pos );
00767 GetItemRect( pTile, &rcOne );
00768
00769 if ( rcOne.IntersectRect( &rcClient, &rcOne ) )
00770 {
00771 rcAll.left = min( rcAll.left, rcOne.left );
00772 rcAll.top = min( rcAll.top, rcOne.top );
00773 rcAll.right = max( rcAll.right, rcOne.right );
00774 rcAll.bottom = max( rcAll.bottom, rcOne.bottom );
00775 }
00776 }
00777
00778 BOOL bClipped = rcAll.Height() > MAX_DRAG_SIZE;
00779
00780 if ( bClipped )
00781 {
00782 rcAll.left = max( rcAll.left, ptMouse.x - MAX_DRAG_SIZE_2 );
00783 rcAll.right = max( rcAll.right, ptMouse.x + MAX_DRAG_SIZE_2 );
00784 rcAll.top = max( rcAll.top, ptMouse.y - MAX_DRAG_SIZE_2 );
00785 rcAll.bottom = max( rcAll.bottom, ptMouse.y + MAX_DRAG_SIZE_2 );
00786 }
00787
00788 CClientDC dcClient( this );
00789 CDC dcMem, dcDrag;
00790 CBitmap bmDrag;
00791
00792 if ( ! dcMem.CreateCompatibleDC( &dcClient ) )
00793 return NULL;
00794 if ( ! dcDrag.CreateCompatibleDC( &dcClient ) )
00795 return NULL;
00796 if ( ! bmDrag.CreateCompatibleBitmap( &dcClient, rcAll.Width(), rcAll.Height() ) )
00797 return NULL;
00798
00799 CBitmap *pOldDrag = dcDrag.SelectObject( &bmDrag );
00800
00801 dcDrag.FillSolidRect( 0, 0, rcAll.Width(), rcAll.Height(), RGB( 250, 255, 250 ) );
00802
00803 CRgn pRgn;
00804
00805 if ( bClipped )
00806 {
00807 CPoint ptMiddle( ptMouse.x - rcAll.left, ptMouse.y - rcAll.top );
00808 pRgn.CreateEllipticRgn( ptMiddle.x - MAX_DRAG_SIZE_2, ptMiddle.y - MAX_DRAG_SIZE_2,
00809 ptMiddle.x + MAX_DRAG_SIZE_2, ptMiddle.y + MAX_DRAG_SIZE_2 );
00810 dcDrag.SelectClipRgn( &pRgn );
00811 }
00812
00813 CDC* pBuffer = CoolInterface.GetBuffer( dcClient, m_szBlock );
00814 CRect rcBuffer( 0, 0, m_szBlock.cx, m_szBlock.cy );
00815
00816 CFont* pOldFont = (CFont*)pBuffer->SelectObject( &CoolInterface.m_fntNormal );
00817
00818 for ( POSITION pos = m_pSelTile.GetHeadPosition() ; pos ; )
00819 {
00820 CLibraryTileItem* pTile = (CLibraryTileItem*)m_pSelTile.GetNext( pos );
00821 GetItemRect( pTile, &rcOne );
00822 CRect rcDummy;
00823
00824 if ( rcDummy.IntersectRect( &rcAll, &rcOne ) )
00825 {
00826 pBuffer->FillSolidRect( &rcBuffer, RGB( 250, 255, 250 ) );
00827 pTile->Paint( pBuffer, rcBuffer, &dcMem );
00828 dcDrag.BitBlt( rcOne.left - rcAll.left, rcOne.top - rcAll.top,
00829 m_szBlock.cx, m_szBlock.cy, pBuffer, 0, 0, SRCCOPY );
00830 }
00831 }
00832
00833 pBuffer->SelectObject( pOldFont );
00834
00835 dcDrag.SelectObject( pOldDrag );
00836
00837 dcDrag.DeleteDC();
00838
00839 CImageList* pAll = new CImageList();
00840 pAll->Create( rcAll.Width(), rcAll.Height(), ILC_COLOR16|ILC_MASK, 1, 1 );
00841 pAll->Add( &bmDrag, RGB( 250, 255, 250 ) );
00842
00843 bmDrag.DeleteObject();
00844
00845 pAll->BeginDrag( 0, ptMouse - rcAll.TopLeft() );
00846
00847 return pAll;
00848 }
00849
00850
00852
00853
00854 CLibraryTileItem::CLibraryTileItem(CAlbumFolder* pFolder)
00855 {
00856 m_pFolder = pFolder;
00857 m_nCookie = 0xFFFFFFFF;
00858 m_bSelected = FALSE;
00859 Update();
00860 }
00861
00862 CLibraryTileItem::~CLibraryTileItem()
00863 {
00864 }
00865
00867
00868
00869 BOOL CLibraryTileItem::Update()
00870 {
00871 if ( m_pFolder->m_nUpdateCookie == m_nCookie ) return FALSE;
00872
00873 m_nCookie = m_pFolder->m_nUpdateCookie;
00874 m_sTitle = m_pFolder->m_sName;
00875 m_nIcon32 = m_pFolder->m_pSchema ? m_pFolder->m_pSchema->m_nIcon32 : -1;
00876 m_nIcon48 = m_pFolder->m_pSchema ? m_pFolder->m_pSchema->m_nIcon48 : -1;
00877 m_bCollection = m_pFolder->m_bCollSHA1;
00878
00879 CSchema* pSchema = m_pFolder->m_pSchema;
00880
00881 if ( pSchema != NULL && m_pFolder->m_pXML != NULL )
00882 {
00883 m_sSubtitle1 = pSchema->m_sTileLine1;
00884 m_sSubtitle2 = pSchema->m_sTileLine2;
00885
00886 pSchema->ResolveTokens( m_sSubtitle1, m_pFolder->m_pXML );
00887 pSchema->ResolveTokens( m_sSubtitle2, m_pFolder->m_pXML );
00888 }
00889 else
00890 {
00891 m_sSubtitle1.Empty();
00892 m_sSubtitle2.Empty();
00893 }
00894
00895 return TRUE;
00896 }
00897
00899
00900
00901 void CLibraryTileItem::Paint(CDC* pDC, const CRect& rcBlock, CDC* pMemDC)
00902 {
00903 CRect rc( &rcBlock );
00904
00905 UINT nStyle = 0;
00906
00907 if ( m_bSelected ) nStyle |= ILD_SELECTED;
00908 if ( m_bCollection ) nStyle |= INDEXTOOVERLAYMASK(SHI_O_COLLECTION);
00909
00910 if ( m_nIcon48 >= 0 )
00911 {
00912 ImageList_DrawEx( ShellIcons.GetHandle( 48 ), m_nIcon48, *pDC,
00913 rc.left + 5, rc.top + 4, 48, 48, CLR_NONE, CLR_DEFAULT, nStyle );
00914 }
00915 else if ( m_nIcon32 >= 0 )
00916 {
00917 ImageList_DrawEx( ShellIcons.GetHandle( 32 ), m_nIcon32, *pDC,
00918 rc.left + 5 + 8, rc.top + 4 + 8, 32, 32, CLR_NONE, CLR_DEFAULT, nStyle );
00919 }
00920
00921 rc.left += 48 + 5;
00922 rc.DeflateRect( 10, 5 );
00923
00924 if ( m_bSelected )
00925 {
00926 pDC->SetBkColor( CoolInterface.m_crHighlight );
00927 pDC->SetTextColor( CoolInterface.m_crHiText );
00928 pDC->SetBkMode( OPAQUE );
00929 }
00930 else
00931 {
00932 pDC->SetBkColor( CoolInterface.m_crWindow );
00933 pDC->SetTextColor( CoolInterface.m_crText );
00934 pDC->SetBkMode( TRANSPARENT );
00935 }
00936
00937 int nX = rc.left + 2;
00938 int nY = ( rc.top + rc.bottom ) / 2;
00939 int nH = pDC->GetTextExtent( _T("Xy") ).cy;
00940
00941 if ( m_sSubtitle1.GetLength() > 0 )
00942 {
00943 CRect rcUnion( nX, nY, nX, nY );
00944
00945 if ( m_sSubtitle2.GetLength() > 0 )
00946 {
00947 nY -= ( nH * 3 ) / 2;
00948 if ( m_bCollection ) pDC->SelectObject( &CoolInterface.m_fntBold );
00949 DrawText( pDC, &rc, nX, nY, m_sTitle, &rcUnion );
00950 if ( m_bCollection ) pDC->SelectObject( &CoolInterface.m_fntNormal );
00951 if ( ! m_bSelected ) pDC->SetTextColor( CoolInterface.m_crDisabled );
00952 DrawText( pDC, &rc, nX, nY + nH, m_sSubtitle1, &rcUnion );
00953 DrawText( pDC, &rc, nX, nY + nH + nH, m_sSubtitle2, &rcUnion );
00954 }
00955 else
00956 {
00957 if ( m_bCollection ) pDC->SelectObject( &CoolInterface.m_fntBold );
00958 DrawText( pDC, &rc, nX, nY - nH, m_sTitle, &rcUnion );
00959 if ( m_bCollection ) pDC->SelectObject( &CoolInterface.m_fntNormal );
00960 if ( ! m_bSelected ) pDC->SetTextColor( CoolInterface.m_crDisabled );
00961 DrawText( pDC, &rc, nX, nY, m_sSubtitle1, &rcUnion );
00962 }
00963
00964 pDC->FillSolidRect( &rcUnion, pDC->GetBkColor() );
00965 }
00966 else
00967 {
00968 nY -= nH / 2;
00969 if ( m_bCollection ) pDC->SelectObject( &CoolInterface.m_fntBold );
00970 DrawText( pDC, &rc, nX, nY, m_sTitle );
00971 if ( m_bCollection ) pDC->SelectObject( &CoolInterface.m_fntNormal );
00972 }
00973
00974 pDC->SelectClipRgn( NULL );
00975 }
00976
00977 void CLibraryTileItem::DrawText(CDC* pDC, const CRect* prcClip, int nX, int nY, LPCTSTR pszText, CRect* prcUnion)
00978 {
00979 CSize sz = pDC->GetTextExtent( pszText, _tcslen( pszText ) );
00980 CRect rc( nX - 2, nY - 1, nX + sz.cx + 2, nY + sz.cy + 1 );
00981
00982 rc.IntersectRect( &rc, prcClip );
00983
00984 pDC->ExtTextOut( nX, nY, ETO_CLIPPED|ETO_OPAQUE, &rc, pszText, _tcslen( pszText ), NULL );
00985 pDC->ExcludeClipRect( rc.left, rc.top, rc.right, rc.bottom );
00986
00987 if ( prcUnion != NULL ) prcUnion->UnionRect( prcUnion, &rc );
00988 }
00989
00991
00992
00993 void CLibraryTileView::OnContextMenu(CWnd* pWnd, CPoint point)
00994 {
00995 Skin.TrackPopupMenu( m_pszToolBar, point, ID_LIBRARY_ALBUM_OPEN );
00996 }
00997
00998 void CLibraryTileView::OnUpdateLibraryAlbumOpen(CCmdUI* pCmdUI)
00999 {
01000 pCmdUI->Enable( m_nSelected == 1 );
01001 }
01002
01003 void CLibraryTileView::OnLibraryAlbumOpen()
01004 {
01005 if ( m_pSelTile.GetCount() == 0 ) return;
01006 CLibraryTileItem* pItem = (CLibraryTileItem*)m_pSelTile.GetHead();
01007 GetFrame()->Display( pItem->m_pFolder );
01008 }
01009
01010 void CLibraryTileView::OnUpdateLibraryAlbumDelete(CCmdUI* pCmdUI)
01011 {
01012 pCmdUI->Enable( m_nSelected > 0 );
01013 }
01014
01015 void CLibraryTileView::OnLibraryAlbumDelete()
01016 {
01017 if ( m_nSelected == 0 ) return;
01018
01019 CString strFormat, strMessage;
01020 Skin.LoadString( strFormat, IDS_LIBRARY_FOLDER_DELETE );
01021 strMessage.Format( strFormat, m_nSelected );
01022
01023 if ( AfxMessageBox( strMessage, MB_ICONQUESTION|MB_OKCANCEL ) != IDOK ) return;
01024
01025 {
01026 CQuickLock oLock( Library.m_pSection );
01027
01028 for ( POSITION pos = m_pSelTile.GetHeadPosition() ; pos ; )
01029 {
01030 CLibraryTileItem* pTile = (CLibraryTileItem*)m_pSelTile.GetNext( pos );
01031 CAlbumFolder* pFolder = pTile->m_pFolder;
01032 if ( LibraryFolders.CheckAlbum( pFolder ) ) pFolder->Delete();
01033 }
01034
01035 }
01036 PostUpdate();
01037 }
01038
01039 void CLibraryTileView::OnUpdateLibraryAlbumProperties(CCmdUI* pCmdUI)
01040 {
01041 pCmdUI->Enable( m_nSelected == 1 );
01042 }
01043
01044 void CLibraryTileView::OnLibraryAlbumProperties()
01045 {
01046 if ( m_pSelTile.GetCount() == 0 ) return;
01047 CLibraryTileItem* pItem = (CLibraryTileItem*)m_pSelTile.GetHead();
01048
01049 CAlbumFolder* pFolder = pItem->m_pFolder;
01050 CFolderPropertiesDlg dlg( NULL, pFolder );
01051
01052 if ( dlg.DoModal() == IDOK ) GetFrame()->Display( pFolder );
01053 }