Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

CtrlLibraryThumbView.cpp

Go to the documentation of this file.
00001 //
00002 // CtrlLibraryThumbView.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "Library.h"
00026 #include "SharedFile.h"
00027 #include "SharedFolder.h"
00028 #include "ImageServices.h"
00029 #include "ThumbCache.h"
00030 #include "ShellIcons.h"
00031 #include "CoolInterface.h"
00032 #include "Schema.h"
00033 #include "SchemaCache.h"
00034 #include "CtrlLibraryThumbView.h"
00035 
00036 #ifdef _DEBUG
00037 #define new DEBUG_NEW
00038 #undef THIS_FILE
00039 static char THIS_FILE[] = __FILE__;
00040 #endif
00041 
00042 IMPLEMENT_DYNCREATE(CLibraryThumbView, CLibraryFileView)
00043 
00044 BEGIN_MESSAGE_MAP(CLibraryThumbView, CLibraryFileView)
00045         //{{AFX_MSG_MAP(CLibraryThumbView)
00046         ON_WM_CREATE()
00047         ON_WM_DESTROY()
00048         ON_WM_SIZE()
00049         ON_WM_PAINT()
00050         ON_WM_VSCROLL()
00051         ON_WM_MOUSEWHEEL()
00052         ON_WM_LBUTTONDOWN()
00053         ON_WM_MOUSEMOVE()
00054         ON_WM_LBUTTONUP()
00055         ON_WM_RBUTTONDOWN()
00056         ON_WM_KEYDOWN()
00057         ON_WM_LBUTTONDBLCLK()
00058         ON_WM_TIMER()
00059         //}}AFX_MSG_MAP
00060 END_MESSAGE_MAP()
00061 
00062 #define THUMB_ICON                      48
00063 #define THUMB_STORE_SIZE        128
00064 
00065 
00067 // CLibraryThumbView construction
00068 
00069 CLibraryThumbView::CLibraryThumbView()
00070 {
00071         m_nCommandID = ID_LIBRARY_VIEW_THUMBNAIL;
00072 }
00073 
00074 CLibraryThumbView::~CLibraryThumbView()
00075 {
00076 }
00077 
00079 // CLibraryThumbView create and destroy
00080 
00081 BOOL CLibraryThumbView::PreCreateWindow(CREATESTRUCT& cs)
00082 {
00083         cs.style |= WS_VSCROLL;
00084         return CLibraryFileView::PreCreateWindow( cs );
00085 }
00086 
00087 int CLibraryThumbView::OnCreate(LPCREATESTRUCT lpCreateStruct)
00088 {
00089         if ( CLibraryFileView::OnCreate( lpCreateStruct ) == -1 ) return -1;
00090 
00091         m_hThread               = NULL;
00092         m_bThread               = FALSE;
00093         m_nInvalidate   = 0;
00094         m_bRush                 = FALSE;
00095 
00096         m_szThumb               = CSize( Settings.Library.ThumbSize, Settings.Library.ThumbSize );
00097         m_szBlock.cx    = m_szThumb.cx + 32;
00098         m_szBlock.cy    = m_szThumb.cy + 44;
00099         m_nColumns              = 0;
00100         m_nRows                 = 0;
00101 
00102         m_pList                 = NULL;
00103         m_nCount                = 0;
00104         m_nBuffer               = 0;
00105         m_nScroll               = 0;
00106         m_nSelected             = 0;
00107         m_pFocus                = NULL;
00108         m_pFirst                = NULL;
00109         m_bDrag                 = FALSE;
00110 
00111         SetTimer( 1, 500, NULL );
00112 
00113         return 0;
00114 }
00115 
00116 void CLibraryThumbView::OnDestroy()
00117 {
00118         KillTimer( 1 );
00119         Clear();
00120         CLibraryFileView::OnDestroy();
00121 }
00122 
00124 // CLibraryThumbView view operations
00125 
00126 void CLibraryThumbView::Update()
00127 {
00128         CSingleLock pLock( &m_pSection, TRUE );
00129 
00130         CSchema* pSchema        = SchemaCache.Get( Settings.Library.FilterURI );
00131         DWORD nCookie           = GetFolderCookie();
00132         BOOL bChanged           = FALSE;
00133 
00134         if ( Settings.Library.ShowVirtual ) pSchema = NULL;
00135 
00136         CLibraryThumbItem** pList = m_pList + m_nCount - 1;
00137 
00138         for ( int nItem = m_nCount ; nItem ; nItem--, pList-- )
00139         {
00140                 CLibraryThumbItem* pThumb       = *pList;
00141                 CLibraryFile* pFile                     = Library.LookupFile( pThumb->m_nIndex );
00142 
00143                 if ( pFile != NULL && pFile->m_nSelectCookie == nCookie &&
00144                          ( ! pSchema || pSchema->Equals( pFile->m_pSchema ) ||
00145                          ( ! pFile->m_pMetadata && pSchema->FilterType( pFile->m_sName ) ) ) )
00146                 {
00147                         bChanged |= pThumb->Update( pFile );
00148 
00149                         pFile->m_nListCookie = nCookie;
00150                 }
00151                 else
00152                 {
00153                         if ( pThumb->m_bSelected ) Select( pThumb, TS_FALSE );
00154                         if ( pThumb == m_pFocus ) m_pFocus = NULL;
00155                         if ( pThumb == m_pFirst ) m_pFirst = NULL;
00156 
00157                         delete pThumb;
00158                         MoveMemory( pList, pList + 1, 4 * ( m_nCount - nItem ) );
00159                         m_nCount--;
00160 
00161                         bChanged = TRUE;
00162                 }
00163         }
00164 
00165         if ( bChanged )
00166         {
00167                 CRect rcClient;
00168                 GetClientRect( &rcClient );
00169                 int nMax        = ( ( m_nCount + m_nColumns - 1 ) / m_nColumns ) * m_szBlock.cy;
00170                 m_nScroll       = max( 0, min( m_nScroll, nMax - rcClient.Height() + 1 ) );
00171         }
00172 
00173         for ( POSITION pos = LibraryMaps.GetFileIterator() ; pos ; )
00174         {
00175                 CLibraryFile* pFile = LibraryMaps.GetNextFile( pos );
00176 
00177                 if ( pFile->m_nSelectCookie == nCookie &&
00178                          pFile->m_nListCookie != nCookie &&
00179                          ( ! pSchema || pSchema->Equals( pFile->m_pSchema ) ||
00180                          ( ! pFile->m_pMetadata && pSchema->FilterType( pFile->m_sName ) ) ) )
00181                 {
00182                         CLibraryThumbItem* pThumb = new CLibraryThumbItem( pFile );
00183 
00184                         if ( m_nCount == m_nBuffer )
00185                         {
00186                                 m_nBuffer += 64;
00187                                 CLibraryThumbItem** pList = new CLibraryThumbItem*[ m_nBuffer ];
00188                                 if ( m_nCount ) CopyMemory( pList, m_pList, 4 * m_nCount );
00189                                 if ( m_pList ) delete [] m_pList;
00190                                 m_pList = pList;
00191                         }
00192 
00193                         m_pList[ m_nCount++ ] = pThumb;
00194                         pFile->m_nListCookie = nCookie;
00195                         bChanged = TRUE;
00196                 }
00197         }
00198 
00199         if ( bChanged )
00200         {
00201                 qsort( m_pList, m_nCount, 4, SortList );
00202                 UpdateScroll();
00203                 StartThread();
00204         }
00205 }
00206 
00207 BOOL CLibraryThumbView::Select(DWORD nObject)
00208 {
00209         CRect rcClient, rcItem;
00210 
00211         CLibraryThumbItem** pList = m_pList + m_nCount - 1;
00212 
00213     int nItem = m_nCount;
00214         for ( ; nItem ; nItem--, pList-- )
00215         {
00216                 CLibraryThumbItem* pThumb = *pList;
00217                 if ( pThumb->m_nIndex == nObject ) break;
00218         }
00219 
00220         if ( nItem == 0 ) return FALSE;
00221 
00222         m_pFocus = *pList;
00223         DeselectAll( m_pFocus );
00224         Select( m_pFocus );
00225         Invalidate();
00226 
00227         GetClientRect( &rcClient );
00228         GetItemRect( m_pFocus, &rcItem );
00229 
00230         if ( rcItem.top < rcClient.top )
00231         {
00232                 ScrollBy( rcItem.top - rcClient.top );
00233         }
00234         else if ( rcItem.bottom > rcClient.bottom )
00235         {
00236                 ScrollBy( rcItem.bottom - rcClient.bottom );
00237         }
00238 
00239         return TRUE;
00240 }
00241 
00242 DWORD CLibraryThumbView::HitTestIndex(const CPoint& point) const
00243 {
00244         CLibraryThumbItem* pThumb = HitTest( point );
00245         return ( pThumb ) ? pThumb->m_nIndex : 0;
00246 }
00247 
00248 int CLibraryThumbView::SortList(LPCVOID pA, LPCVOID pB)
00249 {
00250         CLibraryThumbItem* ppA = *(CLibraryThumbItem**)pA;
00251         CLibraryThumbItem* ppB = *(CLibraryThumbItem**)pB;
00252         return _tcsicoll( ppA->m_sText, ppB->m_sText );
00253 }
00254 
00256 // CLibraryThumbView item list management operations
00257 
00258 void CLibraryThumbView::Clear()
00259 {
00260         StopThread();
00261 
00262         for ( int nItem = 0 ; nItem < m_nCount ; nItem++ )
00263         {
00264                 delete m_pList[ nItem ];
00265         }
00266 
00267         if ( m_pList ) delete [] m_pList;
00268 
00269         m_pList         = NULL;
00270         m_nCount        = 0;
00271         m_nBuffer       = 0;
00272         m_nScroll       = 0;
00273         m_nSelected     = 0;
00274         m_pFocus        = NULL;
00275         m_pFirst        = NULL;
00276         m_pSelThumb.RemoveAll();
00277         SelClear();
00278 }
00279 
00280 int CLibraryThumbView::GetThumbIndex(CLibraryThumbItem* pThumb) const
00281 {
00282         CLibraryThumbItem** pList = m_pList;
00283 
00284         for ( int nItem = 0 ; nItem < m_nCount ; nItem++, pList++ )
00285         {
00286                 if ( *pList == pThumb ) return nItem;
00287         }
00288 
00289         return -1;
00290 }
00291 
00292 BOOL CLibraryThumbView::Select(CLibraryThumbItem* pThumb, TRISTATE bSelect)
00293 {
00294         switch ( bSelect )
00295         {
00296         case TS_UNKNOWN:
00297                 pThumb->m_bSelected = ! pThumb->m_bSelected;
00298                 break;
00299         case TS_FALSE:
00300                 if ( pThumb->m_bSelected == FALSE ) return FALSE;
00301                 pThumb->m_bSelected = FALSE;
00302                 break;
00303         case TS_TRUE:
00304                 if ( pThumb->m_bSelected == TRUE ) return FALSE;
00305                 pThumb->m_bSelected = TRUE;
00306                 break;
00307         }
00308 
00309         if ( pThumb->m_bSelected )
00310         {
00311                 m_nSelected++;
00312                 m_pSelThumb.AddTail( pThumb );
00313                 SelAdd( pThumb->m_nIndex );
00314         }
00315         else
00316         {
00317                 m_nSelected--;
00318                 if ( POSITION pos = m_pSelThumb.Find( pThumb ) )
00319                 {
00320                         m_pSelThumb.RemoveAt( pos );
00321                         SelRemove( pThumb->m_nIndex );
00322                 }
00323         }
00324 
00325         return TRUE;
00326 }
00327 
00328 BOOL CLibraryThumbView::DeselectAll(CLibraryThumbItem* pThumb)
00329 {
00330         CLibraryThumbItem** pList = m_pList + m_nCount - 1;
00331         BOOL bChanged = FALSE;
00332 
00333         for ( int nItem = m_nCount ; nItem ; nItem--, pList-- )
00334         {
00335                 if ( *pList != pThumb )
00336                 {
00337                         if ( (*pList)->m_bSelected ) bChanged = Select( *pList, TS_FALSE );
00338                 }
00339         }
00340 
00341         return bChanged;
00342 }
00343 
00344 BOOL CLibraryThumbView::SelectTo(CLibraryThumbItem* pThumb)
00345 {
00346         BOOL bChanged = FALSE;
00347 
00348         if ( pThumb )
00349         {
00350                 m_pFocus = pThumb;
00351 
00352                 int nFirst      = GetThumbIndex( m_pFirst );
00353                 int nFocus      = GetThumbIndex( m_pFocus );
00354 
00355                 if ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 )
00356                 {
00357                         bChanged = Select( m_pFocus, TS_UNKNOWN );
00358                 }
00359                 else if ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 )
00360                 {
00361                         bChanged = DeselectAll();
00362 
00363                         if ( nFirst >= 0 && nFocus >= 0 )
00364                         {
00365                                 if ( nFirst <= nFocus )
00366                                 {
00367                                         for ( ; nFirst <= nFocus ; nFirst++ ) Select( m_pList[ nFirst ], TS_TRUE );
00368                                 }
00369                                 else
00370                                 {
00371                                         for ( ; nFocus <= nFirst ; nFocus++ ) Select( m_pList[ nFocus ], TS_TRUE );
00372                                 }
00373 
00374                                 bChanged = TRUE;
00375                         }
00376                         else
00377                         {
00378                                 bChanged |= Select( m_pFocus, TS_TRUE );
00379                         }
00380                 }
00381                 else
00382                 {
00383                         if ( m_pFocus->m_bSelected == FALSE ) bChanged = DeselectAll( m_pFocus );
00384                         bChanged |= Select( m_pFocus );
00385                 }
00386 
00387                 if ( m_nSelected == 1 && m_pFocus->m_bSelected ) m_pFirst = m_pFocus;
00388 
00389                 CRect rcClient, rcItem;
00390 
00391                 GetClientRect( &rcClient );
00392                 GetItemRect( m_pFocus, &rcItem );
00393 
00394                 if ( rcItem.top < rcClient.top )
00395                 {
00396                         ScrollBy( rcItem.top - rcClient.top );
00397                 }
00398                 else if ( rcItem.bottom > rcClient.bottom )
00399                 {
00400                         ScrollBy( rcItem.bottom - rcClient.bottom );
00401                 }
00402         }
00403         else if (       ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) == 0 &&
00404                                 ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) == 0 )
00405         {
00406                 bChanged = DeselectAll();
00407         }
00408 
00409         if ( m_nSelected == 0 ) m_pFirst = NULL;
00410 
00411         return bChanged;
00412 }
00413 
00414 void CLibraryThumbView::SelectTo(int nDelta)
00415 {
00416         if ( m_nCount == 0 ) return;
00417 
00418         int nFocus = GetThumbIndex( m_pFocus );
00419 
00420         if ( nFocus < 0 )
00421         {
00422                 nFocus = 0;
00423         }
00424         else
00425         {
00426                 nFocus += nDelta;
00427                 if ( nFocus < 0 ) nFocus = 0;
00428                 if ( nFocus >= m_nCount ) nFocus = m_nCount - 1;
00429         }
00430 
00431         if ( SelectTo( m_pList[ nFocus ] ) ) Invalidate();
00432 }
00433 
00435 // CLibraryThumbView message handlers
00436 
00437 void CLibraryThumbView::OnSize(UINT nType, int cx, int cy)
00438 {
00439         CLibraryFileView::OnSize( nType, cx, cy );
00440 
00441         m_nColumns      = cx / m_szBlock.cx;
00442         m_nRows         = cy / m_szBlock.cy + 1;
00443 
00444         UpdateScroll();
00445 }
00446 
00447 void CLibraryThumbView::UpdateScroll()
00448 {
00449         if ( m_nColumns == 0 ) return;
00450 
00451         SCROLLINFO pInfo;
00452         CRect rc;
00453 
00454         GetClientRect( &rc );
00455 
00456         pInfo.cbSize    = sizeof(pInfo);
00457         pInfo.fMask             = SIF_ALL & ~SIF_TRACKPOS;
00458         pInfo.nMin              = 0;
00459         pInfo.nMax              = ( ( m_nCount + m_nColumns - 1 ) / m_nColumns ) * m_szBlock.cy;
00460         pInfo.nPage             = rc.Height();;
00461         pInfo.nPos              = m_nScroll = max( 0, min( m_nScroll, pInfo.nMax - (int)pInfo.nPage + 1 ) );
00462 
00463         SetScrollInfo( SB_VERT, &pInfo, TRUE );
00464 
00465         Invalidate();
00466 }
00467 
00468 void CLibraryThumbView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
00469 {
00470         CRect rc;
00471         GetClientRect( &rc );
00472 
00473         SetFocus();
00474 
00475         switch ( nSBCode )
00476         {
00477         case SB_BOTTOM:
00478                 ScrollTo( 0xFFFFFF );
00479                 break;
00480         case SB_LINEDOWN:
00481                 ScrollBy( 32 );
00482                 break;
00483         case SB_LINEUP:
00484                 ScrollBy( -32 );
00485                 break;
00486         case SB_PAGEDOWN:
00487                 ScrollBy( rc.Height() );
00488                 break;
00489         case SB_PAGEUP:
00490                 ScrollBy( -rc.Height() );
00491                 break;
00492         case SB_THUMBPOSITION:
00493         case SB_THUMBTRACK:
00494                 ScrollTo( nPos );
00495                 break;
00496         case SB_TOP:
00497                 ScrollTo( 0 );
00498                 break;
00499         }
00500 }
00501 
00502 BOOL CLibraryThumbView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
00503 {
00504         ScrollBy( zDelta * -m_szBlock.cy / WHEEL_DELTA / 2 );
00505         return TRUE;
00506 }
00507 
00508 void CLibraryThumbView::ScrollBy(int nDelta)
00509 {
00510         ScrollTo( max( 0, m_nScroll + nDelta ) );
00511 }
00512 
00513 void CLibraryThumbView::ScrollTo(int nPosition)
00514 {
00515         if ( nPosition == m_nScroll ) return;
00516         m_nScroll = nPosition;
00517 
00518         UpdateScroll();
00519         RedrawWindow( NULL, NULL, RDW_INVALIDATE );
00520 }
00521 
00522 void CLibraryThumbView::OnTimer(UINT nIDEvent)
00523 {
00524         CSingleLock pLock( &m_pSection, TRUE );
00525 
00526         if ( m_nInvalidate && ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 ) == 0 )
00527         {
00528                 Invalidate();
00529                 m_nInvalidate = 0;
00530         }
00531 }
00532 
00533 void CLibraryThumbView::OnPaint()
00534 {
00535         CSingleLock pLock( &m_pSection, TRUE );
00536         CPaintDC dc( this );
00537 
00538         CDC* pBuffer = CoolInterface.GetBuffer( dc, m_szBlock );
00539         CRect rcBuffer( 0, 0, m_szBlock.cx, m_szBlock.cy );
00540 
00541         CFont* pOldFont = (CFont*)pBuffer->SelectObject( &CoolInterface.m_fntNormal );
00542         pBuffer->SetBkMode( OPAQUE );
00543         pBuffer->SetBkColor( CoolInterface.m_crWindow );
00544         pBuffer->SetTextColor( CoolInterface.m_crText );
00545 
00546         CDC dcMem;
00547         dcMem.CreateCompatibleDC( &dc );
00548 
00549         CRect rcClient;
00550         GetClientRect( &rcClient );
00551         CPoint pt( rcClient.left, rcClient.top - m_nScroll );
00552 
00553         CLibraryThumbItem** pList = m_pList;
00554         m_bRush = FALSE;
00555 
00556         for ( int nItem = m_nCount ; nItem && pt.y < rcClient.bottom ; nItem--, pList++ )
00557         {
00558                 CLibraryThumbItem* pThumb = *pList;
00559 
00560                 CRect rcBlock( pt.x, pt.y, pt.x + m_szBlock.cx, pt.y + m_szBlock.cy );
00561 
00562                 if ( rcBlock.bottom >= rcClient.top && dc.RectVisible( &rcBlock ) )
00563                 {
00564                         pBuffer->FillSolidRect( &rcBuffer, CoolInterface.m_crWindow );
00565                         pThumb->Paint( pBuffer, rcBuffer, m_szThumb, &dcMem );
00566                         dc.BitBlt( rcBlock.left, rcBlock.top, m_szBlock.cx, m_szBlock.cy,
00567                                 pBuffer, 0, 0, SRCCOPY );
00568                         dc.ExcludeClipRect( &rcBlock );
00569                         if ( pThumb->m_nThumb == CLibraryThumbItem::thumbWaiting ) m_bRush = TRUE;
00570                 }
00571 
00572                 pt.x += m_szBlock.cx;
00573 
00574                 if ( pt.x + m_szBlock.cx > rcClient.right )
00575                 {
00576                         pt.x = rcClient.left;
00577                         pt.y += m_szBlock.cy;
00578                 }
00579         }
00580 
00581         pBuffer->SelectObject( pOldFont );
00582         dc.FillSolidRect( &rcClient, CoolInterface.m_crWindow );
00583 }
00584 
00585 CLibraryThumbItem* CLibraryThumbView::HitTest(const CPoint& point) const
00586 {
00587         CRect rcClient;
00588         GetClientRect( &rcClient );
00589 
00590         CPoint pt( rcClient.left, rcClient.top - m_nScroll );
00591 
00592         CLibraryThumbItem** pList = m_pList;
00593 
00594         for ( int nItem = m_nCount ; nItem && pt.y < rcClient.bottom ; nItem--, pList++ )
00595         {
00596                 CLibraryThumbItem* pThumb = *pList;
00597 
00598                 CRect rcBlock( pt.x, pt.y, pt.x + m_szBlock.cx, pt.y + m_szBlock.cy );
00599 
00600                 if ( rcBlock.PtInRect( point ) ) return pThumb;
00601 
00602                 pt.x += m_szBlock.cx;
00603 
00604                 if ( pt.x + m_szBlock.cx > rcClient.right )
00605                 {
00606                         pt.x = rcClient.left;
00607                         pt.y += m_szBlock.cy;
00608                 }
00609         }
00610 
00611         return NULL;
00612 }
00613 
00614 BOOL CLibraryThumbView::GetItemRect(CLibraryThumbItem* pThumb, CRect* pRect)
00615 {
00616         CRect rcClient;
00617         GetClientRect( &rcClient );
00618 
00619         CPoint pt( rcClient.left, rcClient.top - m_nScroll );
00620 
00621         CLibraryThumbItem** pList = m_pList;
00622 
00623         for ( int nItem = m_nCount ; nItem ; nItem--, pList++ )
00624         {
00625                 CRect rcBlock( pt.x, pt.y, pt.x + m_szBlock.cx, pt.y + m_szBlock.cy );
00626 
00627                 if ( pThumb == *pList )
00628                 {
00629                         *pRect = rcBlock;
00630                         return TRUE;
00631                 }
00632 
00633                 pt.x += m_szBlock.cx;
00634 
00635                 if ( pt.x + m_szBlock.cx > rcClient.right )
00636                 {
00637                         pt.x = rcClient.left;
00638                         pt.y += m_szBlock.cy;
00639                 }
00640         }
00641 
00642         return FALSE;
00643 }
00644 
00645 void CLibraryThumbView::OnLButtonDown(UINT nFlags, CPoint point)
00646 {
00647         CLibraryThumbItem* pHit = HitTest( point );
00648 
00649         if ( SelectTo( pHit ) ) Invalidate();
00650 
00651         SetFocus();
00652         SetCapture();
00653 
00654         if ( pHit && ( nFlags & MK_RBUTTON ) == 0 )
00655         {
00656                 m_bDrag = TRUE;
00657                 m_ptDrag = point;
00658         }
00659 
00660         CLibraryFileView::OnLButtonDown( nFlags, point );
00661 }
00662 
00663 void CLibraryThumbView::OnMouseMove(UINT nFlags, CPoint point)
00664 {
00665         if ( m_bDrag & ( nFlags & MK_LBUTTON ) )
00666         {
00667                 CSize szDiff = point - m_ptDrag;
00668 
00669                 if ( abs( szDiff.cx ) > 5 || abs( szDiff.cy ) > 5 )
00670                 {
00671                         m_bDrag = FALSE;
00672                         StartDragging( point );
00673                 }
00674         }
00675 
00676         CLibraryFileView::OnMouseMove( nFlags, point );
00677 }
00678 
00679 void CLibraryThumbView::OnLButtonUp(UINT nFlags, CPoint point)
00680 {
00681         ReleaseCapture();
00682         m_bDrag = FALSE;
00683 
00684         if ( ( nFlags & (MK_SHIFT|MK_CONTROL) ) == 0 && m_pFocus && m_pFocus->m_bSelected )
00685         {
00686                 if ( DeselectAll( m_pFocus ) ) Invalidate();
00687         }
00688 }
00689 
00690 void CLibraryThumbView::OnLButtonDblClk(UINT nFlags, CPoint point)
00691 {
00692         SendMessage( WM_COMMAND, ID_LIBRARY_LAUNCH );
00693 }
00694 
00695 void CLibraryThumbView::OnRButtonDown(UINT nFlags, CPoint point)
00696 {
00697         OnLButtonDown( nFlags, point );
00698         CLibraryFileView::OnRButtonDown( nFlags, point );
00699 }
00700 
00701 void CLibraryThumbView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
00702 {
00703         switch ( nChar )
00704         {
00705         case VK_LEFT:
00706                 SelectTo( - 1 );
00707                 break;
00708         case VK_RIGHT:
00709                 SelectTo( 1 );
00710                 break;
00711         case VK_UP:
00712                 SelectTo( -m_nColumns );
00713                 break;
00714         case VK_DOWN:
00715                 SelectTo( m_nColumns );
00716                 break;
00717         case VK_PRIOR:
00718                 SelectTo( m_nRows * -m_nColumns );
00719                 break;
00720         case VK_NEXT:
00721                 SelectTo( m_nRows * m_nColumns );
00722                 break;
00723         case VK_HOME:
00724                 SelectTo( -m_nCount );
00725                 break;
00726         case VK_END:
00727                 SelectTo( m_nCount );
00728                 break;
00729         }
00730 
00731         CLibraryFileView::OnKeyDown( nChar, nRepCnt, nFlags );
00732 }
00733 
00735 // CLibraryThumbView drag setup
00736 
00737 #define MAX_DRAG_SIZE   256
00738 #define MAX_DRAG_SIZE_2 128
00739 
00740 void CLibraryThumbView::StartDragging(CPoint& ptMouse)
00741 {
00742         CSingleLock pLock( &m_pSection, TRUE );
00743 
00744         CImageList* pImage = CreateDragImage( ptMouse );
00745         if ( ! pImage ) return;
00746 
00747         ReleaseCapture();
00748         ClientToScreen( &ptMouse );
00749         DragObjects( pImage, ptMouse );
00750 }
00751 
00752 CImageList* CLibraryThumbView::CreateDragImage(const CPoint& ptMouse)
00753 {
00754         CRect rcClient, rcOne, rcAll( 32000, 32000, -32000, -32000 );
00755 
00756         GetClientRect( &rcClient );
00757 
00758         for ( POSITION pos = m_pSelThumb.GetHeadPosition() ; pos ; )
00759         {
00760                 CLibraryThumbItem* pThumb = (CLibraryThumbItem*)m_pSelThumb.GetNext( pos );
00761                 GetItemRect( pThumb, &rcOne );
00762 
00763                 if ( rcOne.IntersectRect( &rcClient, &rcOne ) )
00764                 {
00765                         rcAll.left              = min( rcAll.left, rcOne.left );
00766                         rcAll.top               = min( rcAll.top, rcOne.top );
00767                         rcAll.right             = max( rcAll.right, rcOne.right );
00768                         rcAll.bottom    = max( rcAll.bottom, rcOne.bottom );
00769                 }
00770         }
00771 
00772         BOOL bClipped = rcAll.Height() > MAX_DRAG_SIZE;
00773 
00774         if ( bClipped )
00775         {
00776                 rcAll.left              = max( rcAll.left, ptMouse.x - MAX_DRAG_SIZE_2 );
00777                 rcAll.right             = max( rcAll.right, ptMouse.x + MAX_DRAG_SIZE_2 );
00778                 rcAll.top               = max( rcAll.top, ptMouse.y - MAX_DRAG_SIZE_2 );
00779                 rcAll.bottom    = max( rcAll.bottom, ptMouse.y + MAX_DRAG_SIZE_2 );
00780         }
00781 
00782         CClientDC dcClient( this );
00783         CDC dcMem, dcDrag;
00784         CBitmap bmDrag;
00785 
00786         if ( ! dcMem.CreateCompatibleDC( &dcClient ) )
00787                 return NULL;
00788         if ( ! dcDrag.CreateCompatibleDC( &dcClient ) )
00789                 return NULL;
00790         if ( ! bmDrag.CreateCompatibleBitmap( &dcClient, rcAll.Width(), rcAll.Height() ) )
00791                 return NULL;
00792 
00793         CBitmap *pOldDrag = dcDrag.SelectObject( &bmDrag );
00794 
00795         dcDrag.FillSolidRect( 0, 0, rcAll.Width(), rcAll.Height(), RGB( 0, 255, 0 ) );
00796 
00797         CRgn pRgn;
00798 
00799         if ( bClipped )
00800         {
00801                 CPoint ptMiddle( ptMouse.x - rcAll.left, ptMouse.y - rcAll.top );
00802                 pRgn.CreateEllipticRgn( ptMiddle.x - MAX_DRAG_SIZE_2, ptMiddle.y - MAX_DRAG_SIZE_2,
00803                                                                 ptMiddle.x + MAX_DRAG_SIZE_2, ptMiddle.y + MAX_DRAG_SIZE_2 );
00804                 dcDrag.SelectClipRgn( &pRgn );
00805         }
00806 
00807         CDC* pBuffer = CoolInterface.GetBuffer( dcClient, m_szBlock );
00808         CRect rcBuffer( 0, 0, m_szBlock.cx, m_szBlock.cy );
00809 
00810         CFont* pOldFont = (CFont*)pBuffer->SelectObject( &CoolInterface.m_fntNormal );
00811 
00812         for ( POSITION pos = m_pSelThumb.GetHeadPosition() ; pos ; )
00813         {
00814                 CLibraryThumbItem* pThumb = (CLibraryThumbItem*)m_pSelThumb.GetNext( pos );
00815                 GetItemRect( pThumb, &rcOne );
00816                 CRect rcDummy;
00817 
00818                 if ( rcDummy.IntersectRect( &rcAll, &rcOne ) )
00819                 {
00820                         pBuffer->FillSolidRect( &rcBuffer, RGB( 0, 255, 0 ) );
00821                         pThumb->Paint( pBuffer, rcBuffer, m_szThumb, &dcMem );
00822                         dcDrag.BitBlt( rcOne.left - rcAll.left, rcOne.top - rcAll.top,
00823                                 m_szBlock.cx, m_szBlock.cy, pBuffer, 0, 0, SRCCOPY );
00824                 }
00825         }
00826 
00827         pBuffer->SelectObject( pOldFont );
00828 
00829         dcDrag.SelectObject( pOldDrag );
00830 
00831         dcDrag.DeleteDC();
00832 
00833         CImageList* pAll = new CImageList();
00834         pAll->Create( rcAll.Width(), rcAll.Height(), ILC_COLOR16|ILC_MASK, 1, 1 );
00835         pAll->Add( &bmDrag, RGB( 0, 255, 0 ) );
00836 
00837         bmDrag.DeleteObject();
00838 
00839         pAll->BeginDrag( 0, ptMouse - rcAll.TopLeft() );
00840 
00841         return pAll;
00842 }
00843 
00845 // CLibraryThumbView thread builder
00846 
00847 void CLibraryThumbView::StartThread()
00848 {
00849         CSingleLock pLock( &m_pSection, TRUE );
00850 
00851         if ( m_hThread != NULL && m_bThread ) return;
00852 
00853         CLibraryThumbItem** pList = m_pList;
00854         int nCount = 0;
00855 
00856         for ( int nItem = m_nCount ; nItem ; nItem--, pList++ )
00857         {
00858                 if ( (*pList)->m_nThumb == CLibraryThumbItem::thumbWaiting ) nCount++;
00859         }
00860 
00861         if ( nCount == 0 ) // all thumbnails extracted
00862                 return;
00863         else if ( m_hThread != NULL && m_bThread )
00864         {
00865                 // Thread is extracting but folder changed
00866                 // won't be executed?
00867                 StopThread();
00868         }
00869         else if ( m_hThread != NULL ) // finished extraction
00870         {
00871                 DWORD nCode;
00872                 if ( GetExitCodeThread( m_hThread, &nCode ) ) Sleep( 100 );
00873                 ASSERT( m_bThread == FALSE );
00874         }
00875 
00876         m_bThread       = TRUE;
00877         CWinThread* pThread = AfxBeginThread( ThreadStart, this, THREAD_PRIORITY_IDLE );
00878         m_hThread       = pThread->m_hThread;
00879 }
00880 
00881 void CLibraryThumbView::StopThread()
00882 {
00883         // If m_bThread == FALSE it means it has finished its work and will die by itself
00884         // No need to stop it.
00885         CSingleLock pLock( &m_pSection, TRUE );
00886         if ( m_hThread == NULL || ! m_bThread ) return;
00887 
00888         m_bThread = FALSE;
00889 
00890     int nAttempt = 100;
00891         for ( ; nAttempt > 0 ; nAttempt-- )
00892         {
00893                 DWORD nCode;
00894 
00895                 if ( ! GetExitCodeThread( m_hThread, &nCode ) ) break;
00896                 if ( nCode != STILL_ACTIVE ) break;
00897                 Sleep( 100 );
00898         }
00899 
00900         if ( nAttempt == 0 )
00901         {
00902                 TerminateThread( m_hThread, 0 );
00903                 theApp.Message( MSG_DEBUG, _T("WARNING: Terminating CLibraryThumbView thread.") );
00904                 Sleep( 100 );
00905         }
00906 
00907         m_hThread = NULL;
00908 }
00909 
00910 UINT CLibraryThumbView::ThreadStart(LPVOID pParam)
00911 {
00912         CLibraryThumbView* pView = (CLibraryThumbView*)pParam;
00913         pView->OnRun();
00914         return 0;
00915 }
00916 
00917 void CLibraryThumbView::OnRun()
00918 {
00919         CSingleLock pLock( &m_pSection );
00920         CImageServices pServices;
00921         CThumbCache pCache;
00922 
00923         while ( m_bThread )
00924         {
00925                 CLibraryThumbItem* pThumb = NULL;
00926                 DWORD nIndex = 0;
00927                 CString strPath;
00928                 BOOL bCache;
00929 
00930                 pLock.Lock();
00931 
00932                 CLibraryThumbItem** pList = m_pList;
00933                 for ( int nItem = m_nCount ; nItem ; nItem--, pList++ )
00934                 {
00935                         if ( (*pList)->m_nThumb == CLibraryThumbItem::thumbWaiting )
00936                         {
00937                                 CQuickLock oLock( Library.m_pSection );
00938                                 if ( CLibraryFile* pFile = Library.LookupFile( (*pList)->m_nIndex ) )
00939                                 {
00940                                         pThumb  = *pList;
00941                                         nIndex  = pFile->m_nIndex;
00942                                         strPath = pFile->GetPath();
00943                                         bCache  = pFile->m_bCachedPreview;
00944                                         break;
00945                                 }
00946                         }
00947                 }
00948 
00949                 pLock.Unlock();
00950 
00951                 if ( pThumb == NULL ) break;
00952                 pThumb = NULL;
00953 
00954                 DWORD tNow = GetTickCount();
00955 
00956                 CImageFile pFile( &pServices );
00957                 BOOL bSuccess = FALSE;
00958                 CSize Size( THUMB_STORE_SIZE, THUMB_STORE_SIZE );
00959 
00960                 if ( pCache.Load( strPath, &Size, nIndex, &pFile ) )
00961                 {
00962                         int nSize = m_szThumb.cy * pFile.m_nWidth / pFile.m_nHeight;
00963 
00964                         if ( nSize > m_szThumb.cx )
00965                         {
00966                                 nSize = m_szThumb.cx * pFile.m_nHeight / pFile.m_nWidth;
00967                                 pFile.Resample( m_szThumb.cx, nSize );
00968                         }
00969                         else
00970                         {
00971                                 pFile.Resample( nSize, m_szThumb.cy );
00972                         }
00973 
00974                         bSuccess = TRUE;
00975                 }
00976                 else if ( pFile.LoadFromFile( strPath, FALSE, TRUE ) && pFile.EnsureRGB() )
00977                 {
00978                         int nSize = THUMB_STORE_SIZE * pFile.m_nWidth / pFile.m_nHeight;
00979 
00980                         if ( ! m_bThread ) break;
00981 
00982                         if ( nSize > THUMB_STORE_SIZE )
00983                         {
00984                                 nSize = THUMB_STORE_SIZE * pFile.m_nHeight / pFile.m_nWidth;
00985                                 pFile.Resample( THUMB_STORE_SIZE, nSize );
00986                         }
00987                         else
00988                         {
00989                                 pFile.Resample( nSize, THUMB_STORE_SIZE );
00990                         }
00991 
00992                         if ( ! m_bThread ) break;
00993 
00994                         pCache.Store( strPath, &Size, nIndex, &pFile );
00995 
00996                         // Resample now to display dimensions
00997                         nSize = m_szThumb.cy * pFile.m_nWidth / pFile.m_nHeight;
00998 
00999                         if ( nSize > m_szThumb.cx )
01000                         {
01001                                 nSize = m_szThumb.cx * pFile.m_nHeight / pFile.m_nWidth;
01002                                 pFile.Resample( m_szThumb.cx, nSize );
01003                         }
01004                         else
01005                         {
01006                                 pFile.Resample( nSize, m_szThumb.cy );
01007                         }
01008 
01009                         bSuccess = TRUE;
01010                 }
01011 
01012                 pLock.Lock();
01013 
01014                 pList = m_pList;
01015                 for ( int nItem = m_nCount ; nItem ; nItem--, pList++ )
01016                 {
01017                         if ( (*pList)->m_nIndex == nIndex )
01018                         {
01019                                 pThumb = *pList;
01020                                 break;
01021                         }
01022                 }
01023 
01024                 if ( pThumb )
01025                 {
01026                         if ( pThumb->m_bmThumb.m_hObject ) pThumb->m_bmThumb.DeleteObject();
01027 
01028                         if ( bSuccess )
01029                         {
01030                                 pThumb->m_bmThumb.Attach( pFile.CreateBitmap() );
01031                                 pThumb->m_szThumb.cx = pFile.m_nWidth;
01032                                 pThumb->m_szThumb.cy = pFile.m_nHeight;
01033                                 pThumb->m_nThumb = CLibraryThumbItem::thumbValid;
01034                         }
01035                         else
01036                         {
01037                                 pThumb->m_nThumb = CLibraryThumbItem::thumbError;
01038                         }
01039 
01040                         m_nInvalidate++;
01041                 }
01042 
01043                 pLock.Unlock();
01044 
01045                 if ( bSuccess && ! bCache )
01046                 {
01047                         CQuickLock oLock( Library.m_pSection );
01048                         if ( CLibraryFile* pFile = Library.LookupFile( nIndex ) )
01049                         {
01050                                 pFile->m_bCachedPreview = TRUE;
01051                         }
01052                 }
01053 
01054                 if ( ! m_bRush )
01055                 {
01056                         //DWORD tDelay = GetTickCount() - tNow;
01057                         //if ( tDelay > 400 ) tDelay = 400;
01058                         //if ( tDelay < 20 ) tDelay = 20;
01059 
01060                         //while ( tDelay && m_bThread )
01061                         //{
01062                         //      DWORD tNow = min( tDelay, DWORD(50) );
01063                         //      tDelay -= tNow;
01064                         //      Sleep( tNow );
01065                         //}
01066                 }
01067         }
01068         m_bThread = FALSE;
01069 }
01070 
01071 
01073 // CLibraryThumbItem construction
01074 
01075 CLibraryThumbItem::CLibraryThumbItem(CLibraryFile* pFile)
01076 {
01077         m_nIndex        = pFile->m_nIndex;
01078         m_nCookie       = pFile->m_nUpdateCookie;
01079         m_sText         = pFile->m_sName;
01080         m_bShared       = pFile->IsShared();
01081         m_bSelected     = FALSE;
01082         m_nThumb        = 0;
01083         m_nShell        = ShellIcons.Get( m_sText, THUMB_ICON );
01084 }
01085 
01086 CLibraryThumbItem::~CLibraryThumbItem()
01087 {
01088 }
01089 
01091 // CLibraryThumbItem operations
01092 
01093 BOOL CLibraryThumbItem::Update(CLibraryFile* pFile)
01094 {
01095         BOOL bShared = pFile->IsShared();
01096 
01097         if ( m_nCookie == pFile->m_nUpdateCookie && m_bShared == bShared ) return FALSE;
01098 
01099         m_nCookie       = pFile->m_nUpdateCookie;
01100         m_sText         = pFile->m_sName;
01101         m_bShared       = bShared;
01102 
01103         m_nThumb        = thumbWaiting;
01104         if ( m_bmThumb.m_hObject ) m_bmThumb.DeleteObject();
01105 
01106         return TRUE;
01107 }
01108 
01110 // CLibraryThumbItem paint
01111 
01112 void CLibraryThumbItem::Paint(CDC* pDC, const CRect& rcBlock, const CSize& szThumb, CDC* pMemDC)
01113 {
01114         CRect rcThumb;
01115 
01116         rcThumb.left    = ( rcBlock.left + rcBlock.right ) / 2 - szThumb.cx / 2;
01117         rcThumb.right   = rcThumb.left + szThumb.cx;
01118         rcThumb.top             = rcBlock.top + 7;
01119         rcThumb.bottom  = rcThumb.top + szThumb.cy;
01120 
01121         CRect rcFrame( &rcThumb );
01122 
01123         if ( m_bSelected )
01124         {
01125                 for ( int nBorder = 3 ; nBorder ; nBorder-- )
01126                 {
01127                         rcFrame.InflateRect( 1, 1 );
01128                         pDC->Draw3dRect( &rcFrame, CoolInterface.m_crHighlight, CoolInterface.m_crHighlight );
01129                 }
01130         }
01131         else
01132         {
01133                 rcFrame.InflateRect( 1, 1 );
01134                 pDC->Draw3dRect( &rcFrame, CoolInterface.m_crMargin, CoolInterface.m_crMargin );
01135         }
01136 
01137         if ( m_bmThumb.m_hObject != NULL )
01138         {
01139                 pMemDC->SelectObject( &m_bmThumb );
01140 
01141                 CPoint ptImage( ( rcThumb.left + rcThumb.right ) / 2 - m_szThumb.cx / 2,
01142                                                 ( rcThumb.top + rcThumb.bottom ) / 2 - m_szThumb.cy / 2 );
01143 
01144                 pDC->BitBlt( ptImage.x, ptImage.y, m_szThumb.cx, m_szThumb.cy,
01145                         pMemDC, 0, 0, SRCCOPY );
01146         }
01147         else
01148         {
01149                 if ( m_nThumb == thumbWaiting )
01150                         pDC->FillSolidRect( &rcThumb, RGB( 255, 255, 255 ) );
01151                 else
01152                         pDC->FillSolidRect( &rcThumb, CoolInterface.m_crBackNormal );
01153 
01154                 ImageList_DrawEx( ShellIcons.GetHandle( THUMB_ICON ), m_nShell, pDC->GetSafeHdc(),
01155                         ( rcThumb.left + rcThumb.right ) / 2 - THUMB_ICON / 2,
01156                         ( rcThumb.top + rcThumb.bottom ) / 2 - THUMB_ICON / 2,
01157                         THUMB_ICON, THUMB_ICON, CLR_NONE, CLR_NONE, ILD_NORMAL );
01158         }
01159 
01160         if ( m_bSelected )
01161         {
01162                 pDC->SetBkColor( CoolInterface.m_crHighlight );
01163                 pDC->SetTextColor( CoolInterface.m_crHiText );
01164         }
01165         else if ( ! m_bShared )
01166         {
01167                 pDC->SetBkColor( CoolInterface.m_crWindow );
01168                 pDC->SetTextColor( CoolInterface.m_crHighlight );
01169         }
01170         else
01171         {
01172                 pDC->SetBkColor( CoolInterface.m_crWindow );
01173                 pDC->SetTextColor( CoolInterface.m_crText );
01174         }
01175 
01176         rcThumb.top             = rcThumb.bottom + 4;
01177         rcThumb.bottom  = rcThumb.top + 27;
01178         rcThumb.left    -= 3;
01179         rcThumb.right   += 3;
01180 
01181         CSize szText = pDC->GetTextExtent( m_sText );
01182 
01183         if ( szText.cx < rcThumb.Width() - 4 )
01184         {
01185                 rcThumb.left = ( rcThumb.left + rcThumb.right ) / 2 - szText.cx / 2 - 2;
01186                 rcThumb.right = rcThumb.left + szText.cx + 4;
01187                 rcThumb.bottom = rcThumb.top + szText.cy + 2;
01188                 pDC->FillSolidRect( &rcThumb, pDC->GetBkColor() );
01189                 pDC->ExtTextOut( rcThumb.left + 2, rcThumb.top, ETO_CLIPPED|ETO_OPAQUE,
01190                         &rcThumb, m_sText, NULL );
01191         }
01192         else
01193         {
01194                 int nSaveX              = rcThumb.right;
01195                 int nSaveY              = rcThumb.bottom;
01196                 int nHeight             = pDC->DrawText( m_sText, &rcThumb, DT_CENTER|DT_WORDBREAK|DT_CALCRECT|DT_NOPREFIX );
01197                 rcThumb.bottom  = min( LONG(nSaveY), rcThumb.top + nHeight + 2 );
01198                 rcThumb.right   = nSaveX;
01199                 pDC->FillSolidRect( &rcThumb, pDC->GetBkColor() );
01200                 pDC->DrawText( m_sText, &rcThumb, DT_CENTER|DT_WORDBREAK|DT_NOPREFIX );
01201         }
01202 }
01203 

Generated on Thu Dec 15 10:39:36 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2