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 "CoolInterface.h"
00026 #include "ShellIcons.h"
00027 #include "Library.h"
00028 #include "SharedFolder.h"
00029 #include "SharedFile.h"
00030 #include "Schema.h"
00031 #include "SchemaCache.h"
00032 #include "TigerTree.h"
00033 #include "ThumbCache.h"
00034 #include "SHA.h"
00035 #include "ED2K.h"
00036 #include "ImageServices.h"
00037 #include "CtrlLibraryTip.h"
00038
00039 #ifdef _DEBUG
00040 #define new DEBUG_NEW
00041 #undef THIS_FILE
00042 static char THIS_FILE[] = __FILE__;
00043 #endif
00044
00045 IMPLEMENT_DYNAMIC(CLibraryTipCtrl, CCoolTipCtrl)
00046
00047 BEGIN_MESSAGE_MAP(CLibraryTipCtrl, CCoolTipCtrl)
00048
00049 ON_WM_DESTROY()
00050 ON_WM_TIMER()
00051
00052 END_MESSAGE_MAP()
00053
00054 #define THUMB_STORE_SIZE 128
00055
00057
00058
00059 CLibraryTipCtrl::CLibraryTipCtrl()
00060 {
00061 m_hThread = NULL;
00062 m_bThread = FALSE;
00063 m_crLight = CCoolInterface::CalculateColour( CoolInterface.m_crTipBack, RGB( 255, 255, 255 ), 128 );
00064 }
00065
00066 CLibraryTipCtrl::~CLibraryTipCtrl()
00067 {
00068 }
00069
00071
00072
00073 BOOL CLibraryTipCtrl::OnPrepare()
00074 {
00075 {
00076 CQuickLock oLock( Library.m_pSection );
00077 CLibraryFile* pFile = Library.LookupFile( (DWORD)m_pContext );
00078 if ( pFile == NULL ) return FALSE;
00079
00080 CSingleLock pLock( &m_pSection, TRUE );
00081
00082
00083
00084 m_sName = pFile->m_sName;
00085 m_sPath = pFile->GetPath();
00086 m_nIndex = pFile->m_nIndex;
00087 m_sSize = Settings.SmartVolume( pFile->GetSize(), FALSE );
00088 m_nIcon = 0;
00089
00090 if ( pFile->m_pFolder != NULL ) m_sFolder = pFile->m_pFolder->m_sPath;
00091 m_sType.Empty();
00092 m_sSHA1.Empty();
00093 m_sTTH.Empty();
00094 m_sED2K.Empty();
00095
00096
00097
00098 m_sType = ShellIcons.GetTypeString( m_sName );
00099 m_nIcon = ShellIcons.Get( m_sName, 48 );
00100
00101
00102
00103 if ( pFile->m_bSHA1 && Settings.General.GUIMode != GUI_BASIC)
00104 {
00105 m_sSHA1 = _T("sha1:") + CSHA::HashToString( &pFile->m_pSHA1 );
00106 }
00107 if ( pFile->m_bTiger && Settings.General.GUIMode != GUI_BASIC)
00108 {
00109 m_sTTH = _T("tree:tiger/:") + CTigerNode::HashToString( &pFile->m_pTiger );
00110 }
00111 if ( pFile->m_bED2K && Settings.General.GUIMode != GUI_BASIC)
00112 {
00113 m_sED2K = _T("ed2k:") + CED2K::HashToString( &pFile->m_pED2K );
00114 }
00115
00116
00117
00118 CSchema* pSchema = pFile->m_pSchema;
00119 CString str, sData, sFormat;
00120
00121 m_pMetadata.Clear();
00122
00123 LoadString( str, IDS_TIP_LOCATION );
00124 m_pMetadata.Add( str, m_sFolder );
00125 LoadString( str, IDS_TIP_TYPE );
00126 m_pMetadata.Add( str, m_sType );
00127 LoadString( str, IDS_TIP_SIZE );
00128 m_pMetadata.Add( str, m_sSize );
00129
00130 LoadString( sFormat, IDS_TIP_TODAYTOTAL );
00131
00132 sData.Format( sFormat, pFile->m_nHitsToday, pFile->m_nHitsTotal );
00133 LoadString( str, IDS_TIP_HITS );
00134 m_pMetadata.Add( str, sData );
00135 sData.Format( sFormat, pFile->m_nUploadsToday, pFile->m_nUploadsTotal );
00136 LoadString( str, IDS_TIP_UPLOADS );
00137 m_pMetadata.Add( str, sData );
00138
00139 if ( pFile->m_pMetadata && pSchema )
00140 {
00141 m_pMetadata.Setup( pSchema, FALSE );
00142 m_pMetadata.Combine( pFile->m_pMetadata );
00143 m_pMetadata.Clean();
00144 }
00145 }
00146
00147 CalcSizeHelper();
00148
00149 return m_sz.cx > 0;
00150 }
00151
00153
00154
00155 void CLibraryTipCtrl::OnCalcSize(CDC* pDC)
00156 {
00157 AddSize( pDC, m_sName );
00158 m_sz.cy += TIP_TEXTHEIGHT;
00159 pDC->SelectObject( &CoolInterface.m_fntNormal );
00160
00161 if ( m_sSHA1.GetLength() )
00162 {
00163 AddSize( pDC, m_sSHA1 );
00164 m_sz.cy += TIP_TEXTHEIGHT;
00165 }
00166 if ( m_sTTH.GetLength() )
00167 {
00168 AddSize( pDC, m_sTTH );
00169 m_sz.cy += TIP_TEXTHEIGHT;
00170 }
00171 if ( m_sED2K.GetLength() )
00172 {
00173 AddSize( pDC, m_sED2K );
00174 m_sz.cy += TIP_TEXTHEIGHT;
00175 }
00176
00177 m_sz.cy += TIP_RULE;
00178
00179 int nMetaHeight = m_pMetadata.GetCount() * TIP_TEXTHEIGHT;
00180 int nValueWidth = 0;
00181 m_nKeyWidth = 40;
00182
00183 m_pMetadata.ComputeWidth( pDC, m_nKeyWidth, nValueWidth );
00184
00185 if ( m_nKeyWidth ) m_nKeyWidth += TIP_GAP;
00186 m_sz.cx = max( m_sz.cx, LONG(m_nKeyWidth + nValueWidth + 102) );
00187 m_sz.cy += max( nMetaHeight, 96 );
00188 m_sz.cy += 11;
00189 }
00190
00192
00193
00194 void CLibraryTipCtrl::OnPaint(CDC* pDC)
00195 {
00196 CSingleLock pLock( &m_pSection, TRUE );
00197 CPoint pt( 0, 0 );
00198
00199 DrawText( pDC, &pt, m_sName );
00200 pt.y += TIP_TEXTHEIGHT;
00201 pDC->SelectObject( &CoolInterface.m_fntNormal );
00202
00203 if ( m_sSHA1.GetLength() )
00204 {
00205 DrawText( pDC, &pt, m_sSHA1 );
00206 pt.y += TIP_TEXTHEIGHT;
00207 }
00208 if ( m_sTTH.GetLength() )
00209 {
00210 DrawText( pDC, &pt, m_sTTH );
00211 pt.y += TIP_TEXTHEIGHT;
00212 }
00213 if ( m_sED2K.GetLength() )
00214 {
00215 DrawText( pDC, &pt, m_sED2K );
00216 pt.y += TIP_TEXTHEIGHT;
00217 }
00218
00219 DrawRule( pDC, &pt );
00220
00221 CRect rcThumb( pt.x, pt.y, pt.x + 96, pt.y + 96 );
00222 CRect rcWork( &rcThumb );
00223 DrawThumb( pDC, rcWork );
00224 pDC->ExcludeClipRect( &rcThumb );
00225
00226 int nCount = 0;
00227
00228 for ( POSITION pos = m_pMetadata.GetIterator() ; pos ; )
00229 {
00230 CMetaItem* pItem = m_pMetadata.GetNext( pos );
00231
00232 DrawText( pDC, &pt, theApp.m_bRTL ? ':' + pItem->m_sKey : pItem->m_sKey + ':', 100 );
00233 DrawText( pDC, &pt, pItem->m_sValue, 100 + m_nKeyWidth );
00234 pt.y += TIP_TEXTHEIGHT;
00235
00236 if ( ++nCount == 5 )
00237 {
00238 pt.x += 98; pt.y -= 2;
00239 DrawRule( pDC, &pt, TRUE );
00240 pt.x -= 98; pt.y -= 2;
00241 }
00242 }
00243 }
00244
00245 void CLibraryTipCtrl::DrawThumb(CDC* pDC, CRect& rcThumb)
00246 {
00247 pDC->Draw3dRect( &rcThumb, CoolInterface.m_crTipBorder, CoolInterface.m_crTipBorder );
00248 rcThumb.DeflateRect( 1, 1 );
00249
00250 if ( m_bmThumb.m_hObject )
00251 {
00252 CDC dcMem;
00253 dcMem.CreateCompatibleDC( pDC );
00254
00255 CBitmap* pOld = (CBitmap*)dcMem.SelectObject( &m_bmThumb );
00256
00257 CPoint ptImage( ( rcThumb.left + rcThumb.right ) / 2 - m_szThumb.cx / 2,
00258 ( rcThumb.top + rcThumb.bottom ) / 2 - m_szThumb.cy / 2 );
00259
00260 pDC->BitBlt( ptImage.x, ptImage.y, m_szThumb.cx, m_szThumb.cy,
00261 &dcMem, 0, 0, SRCCOPY );
00262 pDC->ExcludeClipRect( ptImage.x, ptImage.y,
00263 ptImage.x + m_szThumb.cx, ptImage.y + m_szThumb.cy );
00264
00265 dcMem.SelectObject( pOld );
00266
00267 pDC->FillSolidRect( &rcThumb, m_crLight );
00268 }
00269 else
00270 {
00271 CPoint pt( ( rcThumb.left + rcThumb.right ) / 2 - 24,
00272 ( rcThumb.top + rcThumb.bottom ) / 2 - 24 );
00273
00274 ImageList_DrawEx( ShellIcons.GetHandle( 48 ), m_nIcon, pDC->GetSafeHdc(),
00275 pt.x, pt.y, 48, 48, m_crLight, CLR_NONE, ILD_NORMAL );
00276
00277 pDC->ExcludeClipRect( pt.x, pt.y, pt.x + 48, pt.y + 48 );
00278 pDC->FillSolidRect( &rcThumb, m_crLight );
00279 }
00280 }
00281
00283
00284
00285 void CLibraryTipCtrl::OnShow()
00286 {
00287 OnHide();
00288
00289 if ( m_hThread == NULL )
00290 {
00291 m_bThread = TRUE;
00292 CWinThread* pThread = AfxBeginThread( ThreadStart, this, THREAD_PRIORITY_IDLE );
00293 m_hThread = pThread->m_hThread;
00294 }
00295
00296 m_pWakeup.SetEvent();
00297 }
00298
00299 void CLibraryTipCtrl::OnHide()
00300 {
00301 m_pSection.Lock();
00302 if ( m_bmThumb.m_hObject ) m_bmThumb.DeleteObject();
00303 m_pSection.Unlock();
00304 m_tHidden = GetTickCount();
00305 }
00306
00307 void CLibraryTipCtrl::OnTimer(UINT nIDEvent)
00308 {
00309 CCoolTipCtrl::OnTimer( nIDEvent );
00310
00311 if ( m_hThread != NULL && ! m_bVisible && GetTickCount() - m_tHidden > 20000 )
00312 {
00313 StopThread();
00314 }
00315 }
00316
00317 void CLibraryTipCtrl::OnDestroy()
00318 {
00319 if ( m_hThread != NULL ) StopThread();
00320
00321 CCoolTipCtrl::OnDestroy();
00322 }
00323
00324 void CLibraryTipCtrl::StopThread()
00325 {
00326 m_bThread = FALSE;
00327 m_pWakeup.SetEvent();
00328
00329 int nAttempt = 20;
00330 for ( ; nAttempt > 0 ; nAttempt-- )
00331 {
00332 DWORD nCode;
00333
00334 if ( ! GetExitCodeThread( m_hThread, &nCode ) ) break;
00335 if ( nCode != STILL_ACTIVE ) break;
00336
00337 Sleep( 100 );
00338 }
00339
00340 if ( nAttempt == 0 )
00341 {
00342 TerminateThread( m_hThread, 0 );
00343 theApp.Message( MSG_DEBUG, _T("WARNING: Terminating CLibraryTipCtrl thread.") );
00344 Sleep( 100 );
00345 }
00346
00347 m_hThread = NULL;
00348 }
00349
00351
00352
00353 UINT CLibraryTipCtrl::ThreadStart(LPVOID pParam)
00354 {
00355 CLibraryTipCtrl* pTip = (CLibraryTipCtrl*)pParam;
00356 pTip->OnRun();
00357 return 0;
00358 }
00359
00360 void CLibraryTipCtrl::OnRun()
00361 {
00362 CImageServices pServices;
00363
00364 while ( m_bThread )
00365 {
00366 WaitForSingleObject( m_pWakeup, INFINITE );
00367 if ( ! m_bThread ) break;
00368
00369 m_pSection.Lock();
00370 CString strPath = m_sPath;
00371 m_pSection.Unlock();
00372
00373 CImageFile pFile( &pServices );
00374 CThumbCache pCache;
00375 CSize Size( THUMB_STORE_SIZE, THUMB_STORE_SIZE );
00376 BOOL bSuccess = FALSE;
00377
00378 if ( !pCache.Load( strPath, &Size, m_nIndex, &pFile ) )
00379 {
00380 bSuccess = pFile.LoadFromFile( strPath, FALSE, TRUE ) && pFile.EnsureRGB();
00381 if ( bSuccess )
00382 {
00383 int nSize = THUMB_STORE_SIZE * pFile.m_nWidth / pFile.m_nHeight;
00384
00385 if ( nSize > THUMB_STORE_SIZE )
00386 {
00387 nSize = THUMB_STORE_SIZE * pFile.m_nHeight / pFile.m_nWidth;
00388 pFile.Resample( THUMB_STORE_SIZE, nSize );
00389 }
00390 else
00391 {
00392 pFile.Resample( nSize, THUMB_STORE_SIZE );
00393 }
00394 pCache.Store( strPath, &Size, m_nIndex, &pFile );
00395 }
00396 }
00397 else bSuccess = TRUE;
00398
00399 if ( bSuccess )
00400 {
00401 int nSize = 94 * pFile.m_nWidth / pFile.m_nHeight;
00402
00403 if ( nSize > 94 )
00404 {
00405 nSize = 94 * pFile.m_nHeight / pFile.m_nWidth;
00406 pFile.Resample( 94, nSize );
00407 }
00408 else
00409 {
00410 pFile.Resample( nSize, 94 );
00411 }
00412
00413 m_pSection.Lock();
00414
00415 if ( m_bmThumb.m_hObject ) m_bmThumb.DeleteObject();
00416
00417 if ( m_sPath == strPath )
00418 {
00419 m_bmThumb.Attach( pFile.CreateBitmap() );
00420 m_szThumb.cx = pFile.m_nWidth;
00421 m_szThumb.cy = pFile.m_nHeight;
00422 Invalidate();
00423 }
00424
00425 m_pSection.Unlock();
00426 }
00427 }
00428
00429 m_bThread = FALSE;
00430 }
00431