00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "StdAfx.h"
00027 #include "Shareaza.h"
00028 #include "Settings.h"
00029 #include "Transfers.h"
00030 #include "Downloads.h"
00031 #include "Download.h"
00032 #include "DownloadSource.h"
00033 #include "DownloadTransfer.h"
00034 #include "CoolInterface.h"
00035 #include "ShellIcons.h"
00036 #include "FragmentBar.h"
00037 #include "Skin.h"
00038 #include "CtrlDownloads.h"
00039 #include "WndDownloads.h"
00040
00041 IMPLEMENT_DYNAMIC(CDownloadsCtrl, CWnd)
00042
00043 BEGIN_MESSAGE_MAP(CDownloadsCtrl, CWnd)
00044 ON_WM_CREATE()
00045 ON_WM_DESTROY()
00046 ON_WM_SIZE()
00047 ON_WM_PAINT()
00048 ON_WM_VSCROLL()
00049 ON_WM_HSCROLL()
00050 ON_WM_MOUSEWHEEL()
00051 ON_NOTIFY(HDN_ITEMCLICKA, AFX_IDW_PANE_FIRST, OnSortPanelItems)
00052 ON_NOTIFY(HDN_ITEMCLICKW, AFX_IDW_PANE_FIRST, OnSortPanelItems)
00053 ON_NOTIFY(HDN_ITEMCHANGEDW, AFX_IDW_PANE_FIRST, OnChangeHeader)
00054 ON_NOTIFY(HDN_ITEMCHANGEDA, AFX_IDW_PANE_FIRST, OnChangeHeader)
00055 ON_NOTIFY(HDN_ENDDRAG, AFX_IDW_PANE_FIRST, OnChangeHeader)
00056 ON_WM_KEYDOWN()
00057 ON_WM_LBUTTONDOWN()
00058 ON_WM_RBUTTONDOWN()
00059 ON_WM_LBUTTONDBLCLK()
00060 ON_WM_MOUSEMOVE()
00061 ON_WM_LBUTTONUP()
00062 ON_WM_RBUTTONUP()
00063 ON_WM_SETFOCUS()
00064 ON_WM_KILLFOCUS()
00065 END_MESSAGE_MAP()
00066
00067 #define HEADER_HEIGHT 20
00068 #define ITEM_HEIGHT 17
00069
00070 #define DOWNLOAD_COLUMN_TITLE 0
00071 #define DOWNLOAD_COLUMN_SIZE 1
00072 #define DOWNLOAD_COLUMN_PROGRESS 2
00073 #define DOWNLOAD_COLUMN_SPEED 3
00074 #define DOWNLOAD_COLUMN_STATUS 4
00075 #define DOWNLOAD_COLUMN_CLIENT 5
00076 #define DOWNLOAD_COLUMN_DOWNLOADED 6
00077 #define DOWNLOAD_COLUMN_PERCENTAGE 7
00078 #define COLUMNS_TO_SORT DOWNLOAD_COLUMN_PERCENTAGE - DOWNLOAD_COLUMN_TITLE
00079
00081
00082
00083 CDownloadsCtrl::CDownloadsCtrl()
00084 {
00085
00086 if( !SystemParametersInfo ( SPI_GETWHEELSCROLLLINES, 0, &m_nScrollWheelLines, 0) )
00087 {
00088 m_nScrollWheelLines = 3;
00089 }
00090 }
00091
00092 CDownloadsCtrl::~CDownloadsCtrl()
00093 {
00094 }
00095
00097
00098
00099 BOOL CDownloadsCtrl::Create(CWnd* pParentWnd, UINT nID)
00100 {
00101 CRect rect( 0, 0, 0, 0 );
00102 return CWnd::Create( NULL, NULL, WS_CHILD|WS_CLIPSIBLINGS, rect, pParentWnd, nID, NULL );
00103 }
00104
00105 BOOL CDownloadsCtrl::Update()
00106 {
00107 OnSize( 1982, 0, 0 );
00108 return TRUE;
00109 }
00110
00111 BOOL CDownloadsCtrl::Update(int nGroupCookie)
00112 {
00113 m_nGroupCookie = nGroupCookie;
00114 OnSize( 1982, 0, 0 );
00115 return TRUE;
00116 }
00117
00119
00120
00121 int CDownloadsCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
00122 {
00123 if ( CWnd::OnCreate( lpCreateStruct ) == -1 ) return -1;
00124
00125 CRect rect( 0, 0, 0, 0 );
00126
00127 if ( Settings.Downloads.SortColumns )
00128 m_wndHeader.Create( WS_CHILD|HDS_BUTTONS|HDS_DRAGDROP|HDS_HOTTRACK|HDS_FULLDRAG, rect, this, AFX_IDW_PANE_FIRST );
00129 else
00130 m_wndHeader.Create( WS_CHILD|HDS_DRAGDROP|HDS_HOTTRACK|HDS_FULLDRAG, rect, this, AFX_IDW_PANE_FIRST );
00131
00132 m_wndHeader.SetFont( &theApp.m_gdiFont );
00133
00134 m_wndTip.Create( this, &Settings.Interface.TipDownloads );
00135
00136 InsertColumn( DOWNLOAD_COLUMN_TITLE, _T("Downloaded File"), LVCFMT_LEFT, 210 );
00137 InsertColumn( DOWNLOAD_COLUMN_SIZE, _T("Size"), LVCFMT_CENTER, 80 );
00138 InsertColumn( DOWNLOAD_COLUMN_PROGRESS, _T("Progress"), LVCFMT_CENTER, 130 );
00139 InsertColumn( DOWNLOAD_COLUMN_SPEED, _T("Speed"), LVCFMT_CENTER, 80 );
00140 InsertColumn( DOWNLOAD_COLUMN_STATUS, _T("Status"), LVCFMT_CENTER, 80 );
00141 InsertColumn( DOWNLOAD_COLUMN_CLIENT, _T("Client"), LVCFMT_CENTER, 80 );
00142 InsertColumn( DOWNLOAD_COLUMN_DOWNLOADED, _T("Downloaded"), LVCFMT_CENTER, 0 );
00143 InsertColumn( DOWNLOAD_COLUMN_PERCENTAGE, _T("Complete"), LVCFMT_CENTER, 60 );
00144
00145 LoadColumnState();
00146
00147 CBitmap bmImages;
00148 bmImages.LoadBitmap( IDB_PROTOCOLS );
00149 if ( theApp.m_bRTL )
00150 bmImages.m_hObject = CreateMirroredBitmap( (HBITMAP)bmImages.m_hObject );
00151 m_pProtocols.Create( 16, 16, ILC_COLOR16|ILC_MASK, 7, 1 );
00152 m_pProtocols.Add( &bmImages, RGB( 0, 255, 0 ) );
00153
00154 m_nGroupCookie = 0;
00155 m_nFocus = 0;
00156 m_bCreateDragImage = FALSE;
00157 m_pDragDrop = NULL;
00158 m_bDrag = FALSE;
00159 m_pDeselect1 = NULL;
00160 m_pDeselect2 = NULL;
00161
00162 m_pbSortAscending = new BOOL[COLUMNS_TO_SORT + 1];
00163 for (int i=DOWNLOAD_COLUMN_TITLE; i <= DOWNLOAD_COLUMN_PERCENTAGE; i++)
00164 m_pbSortAscending[i]=TRUE;
00165
00166 return 0;
00167 }
00168
00169 void CDownloadsCtrl::OnDestroy()
00170 {
00171 delete[] m_pbSortAscending;
00172 SaveColumnState();
00173 CWnd::OnDestroy();
00174 }
00175
00177
00178
00179 void CDownloadsCtrl::InsertColumn(int nColumn, LPCTSTR pszCaption, int nFormat, int nWidth)
00180 {
00181 HDITEM pColumn;
00182
00183 ZeroMemory( &pColumn, sizeof(pColumn) );
00184
00185 pColumn.mask = HDI_FORMAT | HDI_LPARAM | HDI_TEXT | HDI_WIDTH;
00186 pColumn.cxy = nWidth;
00187 pColumn.pszText = (LPTSTR)pszCaption;
00188 pColumn.fmt = nFormat;
00189 pColumn.lParam = nColumn;
00190
00191 m_wndHeader.InsertItem( m_wndHeader.GetItemCount(), &pColumn );
00192 }
00193
00194 void CDownloadsCtrl::SaveColumnState()
00195 {
00196 HDITEM pItem = { HDI_WIDTH|HDI_ORDER };
00197
00198 CString strOrdering, strWidths, strItem;
00199
00200 for ( int nColumns = 0 ; m_wndHeader.GetItem( nColumns, &pItem ) ; nColumns++ )
00201 {
00202 m_wndHeader.GetItem( nColumns, &pItem );
00203
00204 strItem.Format( _T("%.2x"), pItem.iOrder );
00205 strOrdering += strItem;
00206
00207 strItem.Format( _T("%.4x"), pItem.cxy );
00208 strWidths += strItem;
00209 }
00210
00211 theApp.WriteProfileString( _T("ListStates"), _T("CDownloadCtrl.Ordering"), strOrdering );
00212 theApp.WriteProfileString( _T("ListStates"), _T("CDownloadCtrl.Widths"), strWidths );
00213 }
00214
00215 BOOL CDownloadsCtrl::LoadColumnState()
00216 {
00217 CString strOrdering, strWidths, strItem;
00218
00219 strOrdering = theApp.GetProfileString( _T("ListStates"), _T("CDownloadCtrl.Ordering"), _T("") );
00220 strWidths = theApp.GetProfileString( _T("ListStates"), _T("CDownloadCtrl.Widths"), _T("") );
00221
00222 HDITEM pItem = { HDI_WIDTH|HDI_ORDER };
00223
00224 if ( _tcsncmp( strWidths, _T("0000"), 4 ) == 0 &&
00225 _tcsncmp( strOrdering, _T("00"), 2 ) == 0 )
00226 {
00227 strWidths = strWidths.Mid( 4 );
00228 strOrdering = strOrdering.Mid( 2 );
00229 }
00230
00231 for ( int nColumns = 0 ; m_wndHeader.GetItem( nColumns, &pItem ) ; nColumns++ )
00232 {
00233 if ( strWidths.GetLength() < 4 || strOrdering.GetLength() < 2 ) return FALSE;
00234
00235 _stscanf( strWidths.Left( 4 ), _T("%x"), &pItem.cxy );
00236 _stscanf( strOrdering.Left( 2 ), _T("%x"), &pItem.iOrder );
00237
00238 strWidths = strWidths.Mid( 4 );
00239 strOrdering = strOrdering.Mid( 2 );
00240
00241 m_wndHeader.SetItem( nColumns, &pItem );
00242 }
00243
00244 return TRUE;
00245 }
00246
00248
00249
00250 BOOL CDownloadsCtrl::IsFiltered(CDownload* pDownload)
00251 {
00252 DWORD nFilterMask = Settings.Downloads.FilterMask;
00253 if ( Settings.General.GUIMode == GUI_BASIC ) nFilterMask = 0xFFFFFFFF;
00254
00255 if ( pDownload->IsMoving() )
00256 {
00257 return ( ( nFilterMask & DLF_ACTIVE ) == 0 );
00258 }
00259 else if ( pDownload->IsPaused() )
00260 {
00261 return ( ( nFilterMask & DLF_PAUSED ) == 0 );
00262 }
00263 else if ( pDownload->IsDownloading() )
00264 {
00265 return ( ( nFilterMask & DLF_ACTIVE ) == 0 );
00266 }
00267 else if ( pDownload->GetSourceCount() > 0 )
00268 {
00269 if ( pDownload->IsDownloading() )
00270 {
00271 return ( ( nFilterMask & DLF_ACTIVE ) == 0 );
00272 }
00273 else
00274 {
00275 return ( ( nFilterMask & DLF_QUEUED ) == 0 );
00276 }
00277 }
00278 else if ( pDownload->m_nSize == SIZE_UNKNOWN )
00279 {
00280 return ( ( nFilterMask & DLF_SOURCES ) == 0 );
00281 }
00282 else
00283 {
00284 return ( ( nFilterMask & DLF_SOURCES ) == 0 );
00285 }
00286
00287 return FALSE;
00288 }
00289
00290 BOOL CDownloadsCtrl::IsExpandable(CDownload* pDownload)
00291 {
00292 if ( Settings.Downloads.ShowSources )
00293 {
00294 return ( pDownload->GetSourceCount() > 0 );
00295 }
00296 else
00297 {
00298 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00299 {
00300 if ( pSource->m_pTransfer != NULL && pSource->m_pTransfer->m_nState > dtsConnecting )
00301 {
00302 return TRUE;
00303 }
00304 }
00305
00306 return FALSE;
00307 }
00308 }
00309
00310 void CDownloadsCtrl::SelectTo(int nIndex)
00311 {
00312 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00313
00314 BOOL bShift = GetAsyncKeyState( VK_SHIFT ) & 0x8000;
00315 BOOL bControl = GetAsyncKeyState( VK_CONTROL ) & 0x8000;
00316 BOOL bRight = GetAsyncKeyState( VK_RBUTTON ) & 0x8000;
00317
00318 if ( ! bShift && ! bControl && ! bRight )
00319 {
00320 if ( m_pDeselect1 == NULL && m_pDeselect2 == NULL ) DeselectAll();
00321 }
00322
00323 Update();
00324
00325 INT nMin, nMax;
00326 GetScrollRange( SB_VERT, &nMin, &nMax );
00327 nIndex = max( 0, min( nIndex, nMax - 1 ) );
00328
00329 CDownloadSource* pSource;
00330 CDownload* pDownload;
00331
00332 if ( bShift )
00333 {
00334 if ( m_nFocus < nIndex )
00335 {
00336 for ( m_nFocus ++ ; m_nFocus <= nIndex ; m_nFocus ++ )
00337 {
00338 GetAt( m_nFocus, &pDownload, &pSource );
00339 if ( pDownload != NULL ) pDownload->m_bSelected = TRUE;
00340 if ( pSource != NULL ) pSource->m_bSelected = TRUE;
00341 }
00342 }
00343 else if ( m_nFocus > nIndex )
00344 {
00345 for ( m_nFocus -- ; m_nFocus >= nIndex ; m_nFocus -- )
00346 {
00347 GetAt( m_nFocus, &pDownload, &pSource );
00348 if ( pDownload != NULL ) pDownload->m_bSelected = TRUE;
00349 if ( pSource != NULL ) pSource->m_bSelected = TRUE;
00350 }
00351 }
00352
00353 m_nFocus = nIndex;
00354 }
00355 else
00356 {
00357 m_nFocus = nIndex;
00358 GetAt( m_nFocus, &pDownload, &pSource );
00359
00360 if ( bControl )
00361 {
00362 if ( pDownload != NULL ) pDownload->m_bSelected = ! pDownload->m_bSelected;
00363 if ( pSource != NULL ) pSource->m_bSelected = ! pSource->m_bSelected;
00364 }
00365 else
00366 {
00367 if ( pDownload != NULL ) pDownload->m_bSelected = TRUE;
00368 if ( pSource != NULL ) pSource->m_bSelected = TRUE;
00369 }
00370 }
00371
00372 CRect rcClient;
00373 GetClientRect( &rcClient );
00374
00375 int nScroll = GetScrollPos( SB_VERT );
00376 int nHeight = ( rcClient.bottom - HEADER_HEIGHT ) / ITEM_HEIGHT - 1;
00377 nHeight = max( 0, nHeight );
00378
00379 if ( m_nFocus < nScroll )
00380 {
00381 SetScrollPos( SB_VERT, m_nFocus );
00382 Update();
00383 }
00384 else if ( m_nFocus > nScroll + nHeight )
00385 {
00386 SetScrollPos( SB_VERT, max( 0, m_nFocus - nHeight ) );
00387 Update();
00388 }
00389 else
00390 {
00391 Invalidate();
00392 }
00393 }
00394
00395 void CDownloadsCtrl::SelectAll(CDownload* pDownload, CDownloadSource* pSource)
00396 {
00397 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00398
00399 BOOL bSelected = FALSE;
00400
00401 for ( POSITION pos = Downloads.GetIterator() ; pos != NULL ; )
00402 {
00403 CDownload* pDownload = Downloads.GetNext( pos );
00404
00405
00406 if ( pDownload != NULL && pDownload->m_bSelected )
00407 {
00408 for ( POSITION pos2 = Downloads.GetIterator() ; pos2 != NULL ; )
00409 {
00410 CDownload* pDownload = Downloads.GetNext( pos2 );
00411
00412 if ( pDownload != NULL ) pDownload->m_bSelected = TRUE;
00413 }
00414
00415 bSelected = TRUE;
00416 }
00417
00418
00419 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource != NULL ; pSource = pSource->m_pNext )
00420 {
00421 if ( pSource != NULL && pSource->m_bSelected )
00422 {
00423 for ( CDownloadSource* pSource2 = pDownload->GetFirstSource() ; pSource2 != NULL ; pSource2 = pSource2->m_pNext )
00424 {
00425 if ( pSource2 != NULL ) pSource2->m_bSelected = TRUE;
00426 }
00427
00428 bSelected = TRUE;
00429 break;
00430 }
00431 }
00432 }
00433
00434
00435 if ( bSelected != TRUE )
00436 {
00437 for ( POSITION pos = Downloads.GetIterator() ; pos != NULL ; )
00438 {
00439 CDownload* pDownload = Downloads.GetNext( pos );
00440
00441 if ( pDownload != NULL ) pDownload->m_bSelected = TRUE;
00442 }
00443 }
00444
00445 Invalidate();
00446 }
00447
00448 void CDownloadsCtrl::DeselectAll(CDownload* pExcept1, CDownloadSource* pExcept2)
00449 {
00450 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00451
00452 for ( POSITION pos = Downloads.GetIterator() ; pos != NULL ; )
00453 {
00454 CDownload* pDownload = Downloads.GetNext( pos );
00455
00456 if ( pDownload != pExcept1 ) pDownload->m_bSelected = FALSE;
00457
00458 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource != NULL ; pSource = pSource->m_pNext )
00459 {
00460 if ( pSource != pExcept2 ) pSource->m_bSelected = FALSE;
00461 }
00462 }
00463
00464 Invalidate();
00465 }
00466
00467 int CDownloadsCtrl::GetSelectedCount()
00468 {
00469 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00470 int nCount = 0;
00471
00472 for ( POSITION pos = Downloads.GetIterator() ; pos ; )
00473 {
00474 CDownload* pDownload = Downloads.GetNext( pos );
00475 if ( pDownload->m_bSelected ) nCount ++;
00476 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00477 if ( pSource->m_bSelected ) nCount ++;
00478 }
00479
00480 pLock.Unlock();
00481
00482 return nCount;
00483 }
00484
00485 BOOL CDownloadsCtrl::HitTest(const CPoint& point, CDownload** ppDownload, CDownloadSource** ppSource, int* pnIndex, RECT* prcItem)
00486 {
00487 CRect rcClient, rcItem;
00488
00489 GetClientRect( &rcClient );
00490 rcClient.top += HEADER_HEIGHT;
00491
00492 rcItem.CopyRect( &rcClient );
00493 rcItem.left -= GetScrollPos( SB_HORZ );
00494 rcItem.bottom = rcItem.top + ITEM_HEIGHT;
00495
00496 int nScroll = GetScrollPos( SB_VERT );
00497 int nIndex = 0;
00498
00499 if ( ppDownload != NULL ) *ppDownload = NULL;
00500 if ( ppSource != NULL ) *ppSource = NULL;
00501
00502 for ( POSITION posDownload = Downloads.GetIterator() ; posDownload && rcItem.top < rcClient.bottom ; )
00503 {
00504 CDownload* pDownload = Downloads.GetNext( posDownload );
00505
00506 if ( m_nGroupCookie != 0 && m_nGroupCookie != pDownload->m_nGroupCookie ) continue;
00507 if ( IsFiltered( pDownload ) ) continue;
00508
00509 if ( nScroll > 0 )
00510 {
00511 nScroll --;
00512 }
00513 else
00514 {
00515 if ( rcItem.PtInRect( point ) )
00516 {
00517 if ( ppDownload != NULL ) *ppDownload = pDownload;
00518 if ( pnIndex != NULL ) *pnIndex = nIndex;
00519 if ( prcItem != NULL ) *prcItem = rcItem;
00520 return TRUE;
00521 }
00522 rcItem.OffsetRect( 0, ITEM_HEIGHT );
00523 }
00524
00525 nIndex ++;
00526 if ( ! pDownload->m_bExpanded ) continue;
00527
00528 if ( Settings.Downloads.ShowSources )
00529 {
00530 int nSources = pDownload->GetSourceCount();
00531
00532 if ( nScroll >= nSources )
00533 {
00534 nScroll -= nSources;
00535 nIndex += nSources;
00536 continue;
00537 }
00538 }
00539
00540 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00541 {
00542 if ( Settings.Downloads.ShowSources || ( pSource->m_pTransfer != NULL && pSource->m_pTransfer->m_nState > dtsConnecting ) )
00543 {
00544 if ( nScroll > 0 )
00545 {
00546 nScroll --;
00547 }
00548 else
00549 {
00550 if ( rcItem.PtInRect( point ) )
00551 {
00552 if ( ppSource != NULL ) *ppSource = pSource;
00553 if ( pnIndex != NULL ) *pnIndex = nIndex;
00554 if ( prcItem != NULL ) *prcItem = rcItem;
00555 return TRUE;
00556 }
00557 rcItem.OffsetRect( 0, ITEM_HEIGHT );
00558 }
00559
00560 nIndex ++;
00561 }
00562 }
00563 }
00564
00565 return FALSE;
00566 }
00567
00568 BOOL CDownloadsCtrl::GetAt(int nSelect, CDownload** ppDownload, CDownloadSource** ppSource)
00569 {
00570 int nScroll = GetScrollPos( SB_VERT );
00571 int nIndex = 0;
00572
00573 if ( ppDownload != NULL ) *ppDownload = NULL;
00574 if ( ppSource != NULL ) *ppSource = NULL;
00575
00576 for ( POSITION posDownload = Downloads.GetIterator() ; posDownload ; )
00577 {
00578 CDownload* pDownload = Downloads.GetNext( posDownload );
00579
00580 if ( m_nGroupCookie != 0 && m_nGroupCookie != pDownload->m_nGroupCookie ) continue;
00581 if ( IsFiltered( pDownload ) ) continue;
00582
00583 if ( nIndex++ == nSelect )
00584 {
00585 if ( ppDownload != NULL ) *ppDownload = pDownload;
00586 return TRUE;
00587 }
00588
00589 if ( ! pDownload->m_bExpanded ) continue;
00590
00591 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00592 {
00593 if ( Settings.Downloads.ShowSources || ( pSource->m_pTransfer != NULL && pSource->m_pTransfer->m_nState > dtsConnecting ) )
00594 {
00595 if ( nIndex++ == nSelect )
00596 {
00597 if ( ppSource != NULL ) *ppSource = pSource;
00598 return TRUE;
00599 }
00600 }
00601 }
00602 }
00603
00604 return FALSE;
00605 }
00606
00607 BOOL CDownloadsCtrl::GetRect(CDownload* pSelect, RECT* prcItem)
00608 {
00609 CRect rcClient, rcItem;
00610
00611 GetClientRect( &rcClient );
00612 rcClient.top += HEADER_HEIGHT;
00613
00614 rcItem.CopyRect( &rcClient );
00615 rcItem.left -= GetScrollPos( SB_HORZ );
00616 rcItem.bottom = rcItem.top + ITEM_HEIGHT;
00617
00618 int nScroll = GetScrollPos( SB_VERT );
00619 rcItem.OffsetRect( 0, ITEM_HEIGHT * -nScroll );
00620
00621 for ( POSITION posDownload = Downloads.GetIterator() ; posDownload ; )
00622 {
00623 CDownload* pDownload = Downloads.GetNext( posDownload );
00624
00625 if ( m_nGroupCookie != 0 && m_nGroupCookie != pDownload->m_nGroupCookie ) continue;
00626 if ( IsFiltered( pDownload ) ) continue;
00627
00628 if ( pDownload == pSelect )
00629 {
00630 *prcItem = rcItem;
00631 return TRUE;
00632 }
00633
00634 rcItem.OffsetRect( 0, ITEM_HEIGHT );
00635
00636 if ( ! pDownload->m_bExpanded ) continue;
00637
00638 if ( Settings.Downloads.ShowSources )
00639 {
00640 int nSources = pDownload->GetSourceCount();
00641 rcItem.OffsetRect( 0, ITEM_HEIGHT * nSources );
00642 continue;
00643 }
00644
00645 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00646 {
00647 if ( pSource->m_pTransfer != NULL && pSource->m_pTransfer->m_nState > dtsConnecting )
00648 {
00649 rcItem.OffsetRect( 0, ITEM_HEIGHT );
00650 }
00651 }
00652 }
00653
00654 return FALSE;
00655 }
00656
00657 void CDownloadsCtrl::MoveSelected(int nDelta)
00658 {
00659 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00660 CList<CDownload*> pList;
00661 POSITION pos;
00662
00663 for ( pos = Downloads.GetIterator() ; pos ; )
00664 {
00665 CDownload* pDownload = Downloads.GetNext( pos );
00666 if ( pDownload->m_bSelected ) pList.AddTail( pDownload );
00667 }
00668
00669 pos = nDelta > 0 ? pList.GetTailPosition() : pList.GetHeadPosition();
00670
00671 while ( pos )
00672 {
00673 CDownload* pDownload = nDelta > 0 ? pList.GetPrev( pos ) : pList.GetNext( pos );
00674 Downloads.Move( pDownload, nDelta );
00675 }
00676
00677 Update();
00678 }
00679
00680 BOOL CDownloadsCtrl::DropShowTarget(CPtrList* pSel, const CPoint& ptScreen)
00681 {
00682 CPoint ptLocal( ptScreen );
00683 CRect rcClient;
00684
00685 ScreenToClient( &ptLocal );
00686 GetClientRect( &rcClient );
00687
00688 BOOL bLocal = rcClient.PtInRect( ptLocal );
00689 CDownload* pHit = NULL;
00690
00691 if ( bLocal ) HitTest( ptLocal, &pHit, NULL, NULL, NULL );
00692
00693 if ( pHit != m_pDragDrop )
00694 {
00695 CImageList::DragShowNolock( FALSE );
00696 m_pDragDrop = pHit;
00697 RedrawWindow();
00698 CImageList::DragShowNolock( TRUE );
00699 }
00700
00701 return bLocal;
00702 }
00703
00704 BOOL CDownloadsCtrl::DropObjects(CPtrList* pSel, const CPoint& ptScreen)
00705 {
00706 CPoint ptLocal( ptScreen );
00707 CRect rcClient;
00708
00709 ScreenToClient( &ptLocal );
00710 GetClientRect( &rcClient );
00711
00712 m_pDragDrop = NULL;
00713
00714 if ( pSel == NULL || ! rcClient.PtInRect( ptLocal ) ) return FALSE;
00715
00716 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00717 CDownload* pHit = NULL;
00718
00719 HitTest( ptLocal, &pHit, NULL, NULL, NULL );
00720
00721 for ( POSITION pos = pSel->GetHeadPosition() ; pos ; )
00722 {
00723 CDownload* pDownload = (CDownload*)pSel->GetNext( pos );
00724
00725 if ( Downloads.Check( pDownload ) && pDownload != pHit )
00726 {
00727 Downloads.Reorder( pDownload, pHit );
00728 }
00729 }
00730
00731 return TRUE;
00732 }
00733
00735
00736
00737 void CDownloadsCtrl::OnSize(UINT nType, int cx, int cy)
00738 {
00739 int nWidth = 0, nHeight = 0;
00740 CRect rcClient;
00741 HDITEM pColumn;
00742
00743 if ( nType != 1982 ) CWnd::OnSize( nType, cx, cy );
00744
00745 GetClientRect( &rcClient );
00746
00747 ZeroMemory( &pColumn, sizeof(pColumn) );
00748 pColumn.mask = HDI_WIDTH;
00749
00750 for ( int nColumn = 0 ; m_wndHeader.GetItem( nColumn, &pColumn ) ; nColumn ++ )
00751 nWidth += pColumn.cxy;
00752
00753 SCROLLINFO pScroll;
00754 ZeroMemory( &pScroll, sizeof(pScroll) );
00755 pScroll.cbSize = sizeof(pScroll);
00756 pScroll.fMask = SIF_RANGE|SIF_PAGE;
00757 pScroll.nMin = 0;
00758 pScroll.nMax = nWidth;
00759 pScroll.nPage = rcClient.right;
00760 SetScrollInfo( SB_HORZ, &pScroll, TRUE );
00761
00762 int nScroll = GetScrollPos( SB_HORZ );
00763 m_wndHeader.SetWindowPos( NULL, -nScroll, 0, rcClient.right + nScroll, HEADER_HEIGHT, SWP_SHOWWINDOW );
00764
00765 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00766
00767 for ( POSITION posDownload = Downloads.GetIterator() ; posDownload ; )
00768 {
00769 CDownload* pDownload = Downloads.GetNext( posDownload );
00770
00771 if ( m_nGroupCookie != 0 && m_nGroupCookie != pDownload->m_nGroupCookie || IsFiltered( pDownload ) )
00772 {
00773 pDownload->m_bSelected = FALSE;
00774 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00775 pSource->m_bSelected = FALSE;
00776 continue;
00777 }
00778
00779 nHeight ++;
00780
00781 if ( ! pDownload->m_bExpanded )
00782 {
00783 }
00784 else if ( Settings.Downloads.ShowSources )
00785 {
00786 nHeight += pDownload->GetSourceCount();
00787 }
00788 else
00789 {
00790 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource ; pSource = pSource->m_pNext )
00791 {
00792 if ( Settings.Downloads.ShowSources || ( pSource->m_pTransfer != NULL && pSource->m_pTransfer->m_nState > dtsConnecting ) )
00793 {
00794 nHeight ++;
00795 }
00796 }
00797 }
00798 }
00799
00800 pLock.Unlock();
00801
00802 ZeroMemory( &pScroll, sizeof(pScroll) );
00803 pScroll.cbSize = sizeof(pScroll);
00804 pScroll.fMask = SIF_RANGE|SIF_PAGE;
00805 pScroll.nMin = 0;
00806 pScroll.nMax = nHeight;
00807 pScroll.nPage = ( rcClient.bottom - HEADER_HEIGHT ) / ITEM_HEIGHT + 1;
00808 SetScrollInfo( SB_VERT, &pScroll, TRUE );
00809
00810 m_nFocus = min( m_nFocus, max( 0, nHeight - 1 ) );
00811
00812 Invalidate();
00813 }
00814
00816
00817
00818 void CDownloadsCtrl::OnPaint()
00819 {
00820 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00821 CRect rcClient, rcItem;
00822 CPaintDC dc( this );
00823 if ( theApp.m_bRTL ) dc.SetTextAlign( TA_RTLREADING );
00824
00825 GetClientRect( &rcClient );
00826 rcClient.top += HEADER_HEIGHT;
00827
00828 rcItem.CopyRect( &rcClient );
00829 rcItem.left -= GetScrollPos( SB_HORZ );
00830 rcItem.bottom = rcItem.top + ITEM_HEIGHT;
00831
00832 int nScroll = GetScrollPos( SB_VERT );
00833 int nIndex = 0;
00834
00835 CFont* pfOld = (CFont*)dc.SelectObject( &theApp.m_gdiFont );
00836 BOOL bFocus = ( GetFocus() == this );
00837
00838 for ( POSITION posDownload = Downloads.GetIterator() ; posDownload && rcItem.top < rcClient.bottom ; )
00839 {
00840 CDownload* pDownload = Downloads.GetNext( posDownload );
00841
00842 if ( m_nGroupCookie != 0 && m_nGroupCookie != pDownload->m_nGroupCookie ) continue;
00843 if ( IsFiltered( pDownload ) ) continue;
00844
00845 if ( nScroll > 0 )
00846 {
00847 nScroll --;
00848 }
00849 else
00850 {
00851 PaintDownload( dc, rcItem, pDownload, bFocus && ( m_nFocus == nIndex ), m_pDragDrop == pDownload );
00852 rcItem.OffsetRect( 0, ITEM_HEIGHT );
00853 }
00854
00855 nIndex ++;
00856
00857 if ( ! pDownload->m_bExpanded ) continue;
00858
00859 if ( Settings.Downloads.ShowSources )
00860 {
00861 int nSources = pDownload->GetSourceCount();
00862
00863 if ( nScroll >= nSources )
00864 {
00865 nScroll -= nSources;
00866 nIndex += nSources;
00867 continue;
00868 }
00869 }
00870
00871 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource && rcItem.top < rcClient.bottom ; pSource = pSource->m_pNext )
00872 {
00873 if ( Settings.Downloads.ShowSources || ( pSource->m_pTransfer != NULL && pSource->m_pTransfer->m_nState > dtsConnecting ) )
00874 {
00875 if ( nScroll > 0 )
00876 {
00877 nScroll --;
00878 }
00879 else
00880 {
00881 PaintSource( dc, rcItem, pDownload, pSource, bFocus && ( m_nFocus == nIndex ) );
00882 rcItem.OffsetRect( 0, ITEM_HEIGHT );
00883 }
00884
00885 nIndex ++;
00886 }
00887 }
00888 }
00889
00890 dc.SelectObject( pfOld );
00891
00892 rcClient.top = rcItem.top;
00893 if ( rcClient.top < rcClient.bottom )
00894 dc.FillSolidRect( &rcClient, CoolInterface.m_crWindow );
00895 }
00896
00897 void CDownloadsCtrl::PaintDownload(CDC& dc, const CRect& rcRow, CDownload* pDownload, BOOL bFocus, BOOL bDrop)
00898 {
00899 COLORREF crNatural = m_bCreateDragImage ? RGB( 250, 255, 250 ) : CoolInterface.m_crWindow;
00900 COLORREF crBack = pDownload->m_bSelected ? CoolInterface.m_crBackSel : crNatural;
00901
00902 if ( bDrop )
00903 {
00904 CRect rcDrop( rcRow.left, rcRow.top, rcRow.right, rcRow.top + 2 );
00905 dc.Draw3dRect( &rcDrop, 0, 0 );
00906 dc.ExcludeClipRect( &rcDrop );
00907 }
00908
00909 dc.SetBkColor( crBack );
00910 dc.SetBkMode( OPAQUE );
00911
00912 if ( pDownload->m_bVerify == TS_FALSE )
00913 dc.SetTextColor( RGB( 255, 0, 0 ) );
00914 else if ( pDownload->m_bSelected )
00915 dc.SetTextColor( CoolInterface.m_crText );
00916 else if ( pDownload->m_bVerify == TS_TRUE )
00917 {
00918 if( pDownload->m_bBTH && ( pDownload->m_nTorrentUploaded < pDownload->m_nTorrentDownloaded ) )
00919 dc.SetTextColor( CoolInterface.m_crText );
00920 else
00921 dc.SetTextColor( RGB( 0, 127, 0 ) );
00922 }
00923 else
00924 dc.SetTextColor( CoolInterface.m_crText );
00925
00926 int nTextLeft = rcRow.right, nTextRight = rcRow.left;
00927 HDITEM pColumn;
00928
00929 ZeroMemory( &pColumn, sizeof(pColumn) );
00930 pColumn.mask = HDI_FORMAT | HDI_LPARAM;
00931
00932 int nTransfers = pDownload->GetTransferCount();
00933 int nSources = pDownload->GetSourceCount();
00934 int nRating = pDownload->GetReviewAverage();
00935
00936 if ( ( nRating == 0 ) && ( pDownload->GetReviewCount() > 0 ) )
00937 {
00938
00939 nRating = 3;
00940 }
00941
00942 for ( int nColumn = 0 ; m_wndHeader.GetItem( nColumn, &pColumn ) ; nColumn++ )
00943 {
00944 CString strText;
00945 CRect rcCell;
00946 CString strSource;
00947 BOOL bDisplayText = TRUE;
00948 UINT nIconStyle;
00949
00950 m_wndHeader.GetItemRect( nColumn, &rcCell );
00951 rcCell.left += rcRow.left;
00952 rcCell.right += rcRow.left;
00953 rcCell.top = rcRow.top;
00954 rcCell.bottom = rcRow.bottom;
00955
00956 switch ( pColumn.lParam )
00957 {
00958 case DOWNLOAD_COLUMN_TITLE:
00959 dc.FillSolidRect( rcCell.left, rcCell.bottom - 1, 32, 1, crNatural );
00960 if ( IsExpandable( pDownload ) )
00961 {
00962 ImageList_DrawEx( ShellIcons.GetHandle( 16 ), pDownload->m_bExpanded ? SHI_MINUS : SHI_PLUS, dc.GetSafeHdc(),
00963 rcCell.left, rcCell.top, 16, 16, crNatural, CLR_DEFAULT, ILD_NORMAL );
00964 }
00965 else
00966 dc.FillSolidRect( rcCell.left, rcCell.top, 16, 16, crNatural );
00967 rcCell.left += 16;
00968 nIconStyle = pDownload->m_bSelected ? ILD_SELECTED : ILD_NORMAL;
00969
00970
00971 switch ( nRating )
00972 {
00973 case 0:
00974 break;
00975 case 1:
00976 nIconStyle |= INDEXTOOVERLAYMASK( SHI_O_RATING_FAKE );
00977 break;
00978 case 2:
00979 case 3:
00980 case 4:
00981 nIconStyle |= INDEXTOOVERLAYMASK( SHI_O_RATING_AVERAGE );
00982 break;
00983 default:
00984 nIconStyle |= INDEXTOOVERLAYMASK( SHI_O_RATING_GOOD );
00985 break;
00986 }
00987
00988 ImageList_DrawEx( ShellIcons.GetHandle( 16 ), ShellIcons.Get( pDownload->m_sRemoteName, 16 ), dc.GetSafeHdc(),
00989 rcCell.left, rcCell.top, 16, 16, crNatural, CLR_DEFAULT, nIconStyle );
00990 rcCell.left += 16;
00991 dc.FillSolidRect( rcCell.left, rcCell.top, 1, rcCell.Height(), crNatural );
00992 rcCell.left += 1;
00993
00994 strText = pDownload->GetDisplayName();
00995 break;
00996
00997 case DOWNLOAD_COLUMN_SIZE:
00998 if ( pDownload->m_nSize < SIZE_UNKNOWN )
00999 strText = Settings.SmartVolume( pDownload->m_nSize, FALSE );
01000 else
01001 LoadString( strText, IDS_STATUS_UNKNOWN );
01002 break;
01003
01004 case DOWNLOAD_COLUMN_PROGRESS:
01005 if ( rcCell.Width() > 50 )
01006 {
01007 bDisplayText = FALSE;
01008 dc.Draw3dRect( &rcCell, crBack, crBack );
01009 rcCell.DeflateRect( 1, 1 );
01010 dc.Draw3dRect( &rcCell, crBack, crBack );
01011 rcCell.DeflateRect( 0, 1 );
01012 dc.Draw3dRect( &rcCell, RGB( 50, 50, 50 ), RGB( 50, 50, 50 ) );
01013 rcCell.DeflateRect( 1, 1 );
01014 if ( Settings.Downloads.SimpleBar )
01015 CFragmentBar::DrawDownloadSimple( &dc, &rcCell, pDownload, crNatural );
01016 else
01017 CFragmentBar::DrawDownload( &dc, &rcCell, pDownload, crNatural );
01018 }
01019 else if ( ( pDownload->m_nSize < SIZE_UNKNOWN ) && ( pDownload->m_nSize > 0 ) )
01020 {
01021 strText.Format( _T("%.0f%%"), pDownload->GetProgress() * 100.0 );
01022 }
01023
01024 break;
01025
01026 case DOWNLOAD_COLUMN_SPEED:
01027 if ( ! pDownload->IsMoving() )
01028 {
01029 if ( DWORD nSpeed = pDownload->GetAverageSpeed() * 8 )
01030 strText = Settings.SmartVolume( nSpeed, FALSE, TRUE );
01031 }
01032 break;
01033
01034 case DOWNLOAD_COLUMN_STATUS:
01035 strText = GetDownloadStatus( pDownload );
01036 break;
01037
01038 case DOWNLOAD_COLUMN_CLIENT:
01039 if ( pDownload->IsCompleted() )
01040 {
01041 if ( pDownload->m_bVerify == TS_TRUE )
01042 LoadString( strText, IDS_STATUS_VERIFIED );
01043 else if ( pDownload->m_bVerify == TS_FALSE )
01044 LoadString( strText, IDS_STATUS_UNVERIFIED );
01045 }
01046 else if ( nSources > 0 )
01047 {
01048 LoadSourcesString( strSource, nSources );
01049 strText.Format( _T("(%i %s)"), nSources, strSource );
01050 }
01051 else
01052 LoadString( strText, IDS_STATUS_NOSOURCES );
01053 break;
01054 case DOWNLOAD_COLUMN_DOWNLOADED:
01055 strText = Settings.SmartVolume( pDownload->GetVolumeComplete(), FALSE );
01056 break;
01057 case DOWNLOAD_COLUMN_PERCENTAGE:
01058 if ( ( pDownload->m_nSize < SIZE_UNKNOWN ) && ( pDownload->m_nSize > 0 ) )
01059 {
01060 if ( rcCell.Width() > 50 )
01061 strText.Format( _T("%.2f%%"), pDownload->GetProgress() * 100.0 );
01062 else
01063 strText.Format( _T("%.0f%%"), pDownload->GetProgress() * 100.0 );
01064 }
01065 else
01066 LoadString( strText, IDS_STATUS_UNKNOWN );
01067 break;
01068 }
01069
01070 nTextLeft = min( nTextLeft, int(rcCell.left) );
01071 nTextRight = max( nTextRight, int(rcCell.right) );
01072
01073 if ( ! bDisplayText ) continue;
01074
01075 if ( rcCell.Width() < 8 ) strText.Empty();
01076
01077 if ( dc.GetTextExtent( strText ).cx > rcCell.Width() - 8 )
01078 {
01079 while ( dc.GetTextExtent( strText + _T('\x2026') ).cx > ( rcCell.Width() - 8 ) && strText.GetLength() > 0 )
01080 {
01081 strText.Truncate( strText.GetLength() - 1 );
01082 }
01083
01084 if ( strText.GetLength() > 0 ) strText += _T('\x2026');
01085 }
01086
01087 int nWidth = dc.GetTextExtent( strText ).cx;
01088 int nPosition = 0;
01089
01090 switch ( pColumn.fmt & LVCFMT_JUSTIFYMASK )
01091 {
01092 default:
01093 nPosition = ( rcCell.left + 4 );
01094 break;
01095 case LVCFMT_CENTER:
01096 nPosition = ( ( rcCell.left + rcCell.right ) / 2 ) - ( nWidth / 2 );
01097 break;
01098 case LVCFMT_RIGHT:
01099 nPosition = ( rcCell.right - 4 - nWidth );
01100 break;
01101 }
01102
01103 dc.SetBkColor( crBack );
01104 dc.ExtTextOut( nPosition, rcCell.top + 2, ETO_CLIPPED|ETO_OPAQUE,
01105 &rcCell, strText, NULL );
01106 }
01107
01108 if ( nTextRight < rcRow.right )
01109 {
01110 CRect rcBlank( nTextRight, rcRow.top, rcRow.right, rcRow.bottom );
01111 dc.FillSolidRect( &rcBlank, crBack );
01112 }
01113
01114 if ( bFocus )
01115 {
01116 CRect rcFocus( nTextLeft, rcRow.top, max( int(rcRow.right), nTextRight ), rcRow.bottom );
01117 dc.Draw3dRect( &rcFocus, CoolInterface.m_crBorder, CoolInterface.m_crBorder );
01118 }
01119 }
01120
01121 void CDownloadsCtrl::PaintSource(CDC& dc, const CRect& rcRow, CDownload* pDownload, CDownloadSource* pSource, BOOL bFocus)
01122 {
01123 COLORREF crNatural = m_bCreateDragImage ? RGB( 250, 255, 250 ) : CoolInterface.m_crWindow;
01124 COLORREF crBack = pSource->m_bSelected ? CoolInterface.m_crBackSel : crNatural;
01125
01126 dc.SetBkColor( crBack );
01127 dc.SetBkMode( OPAQUE );
01128
01129 if ( pSource->m_bSelected )
01130 dc.SetTextColor( CoolInterface.m_crText );
01131 else
01132 dc.SetTextColor( CoolInterface.m_crText );
01133
01134 int nTextLeft = rcRow.right, nTextRight = rcRow.left;
01135 HDITEM pColumn;
01136
01137 ZeroMemory( &pColumn, sizeof(pColumn) );
01138 pColumn.mask = HDI_FORMAT | HDI_LPARAM;
01139
01140 for ( int nColumn = 0 ; m_wndHeader.GetItem( nColumn, &pColumn ) ; nColumn++ )
01141 {
01142 CString strText;
01143 CRect rcCell;
01144
01145 m_wndHeader.GetItemRect( nColumn, &rcCell );
01146 rcCell.left += rcRow.left;
01147 rcCell.right += rcRow.left;
01148 rcCell.top = rcRow.top;
01149 rcCell.bottom = rcRow.bottom;
01150
01151 switch ( pColumn.lParam )
01152 {
01153 case DOWNLOAD_COLUMN_TITLE:
01154 dc.FillSolidRect( rcCell.left, rcCell.top, 24, rcCell.Height(), crNatural );
01155 rcCell.left += 24;
01156 dc.FillSolidRect( rcCell.left, rcCell.bottom - 1, 16, 1, crNatural );
01157 ImageList_DrawEx( m_pProtocols, pSource->m_nProtocol, dc.GetSafeHdc(),
01158 rcCell.left, rcCell.top, 16, 16, crNatural, CLR_DEFAULT, pSource->m_bSelected ? ILD_SELECTED : ILD_NORMAL );
01159 rcCell.left += 16;
01160 dc.FillSolidRect( rcCell.left, rcCell.top, 1, rcCell.Height(), crNatural );
01161 rcCell.left += 1;
01162
01163 if ( pSource->m_pTransfer != NULL )
01164 {
01165 if ( Settings.Search.ShowNames && pSource->m_sNick.GetLength() )
01166 strText = pSource->m_sNick + _T(" (") + pSource->m_pTransfer->m_sAddress + _T(")");
01167 else
01168 strText = pSource->m_pTransfer->m_sAddress;
01169 }
01170 else
01171 {
01172 if ( Settings.Search.ShowNames && pSource->m_sNick.GetLength() )
01173 strText = pSource->m_sNick + _T(" (") + inet_ntoa( pSource->m_pAddress ) + _T(")");
01174 else
01175 {
01176 if( ( pSource->m_nProtocol == PROTOCOL_ED2K ) && ( pSource->m_bPushOnly == TRUE ) )
01177 {
01178 strText.Format( _T("%lu@%s"), pSource->m_pAddress.S_un.S_addr,
01179 (LPCTSTR)CString( inet_ntoa( (IN_ADDR&)pSource->m_pServerAddress) ) );
01180 }
01181 else
01182 {
01183 strText = inet_ntoa( pSource->m_pAddress );
01184 }
01185 }
01186 }
01187 if( pSource->m_bPushOnly )
01188 {
01189 strText += _T(" (push)");
01190 }
01191 break;
01192
01193 case DOWNLOAD_COLUMN_SIZE:
01194 if ( pSource->m_pTransfer != NULL )
01195 strText = Settings.SmartVolume( pSource->m_pTransfer->m_nDownloaded, FALSE );
01196 break;
01197
01198 case DOWNLOAD_COLUMN_PROGRESS:
01199 dc.Draw3dRect( &rcCell, crBack, crBack );
01200 rcCell.DeflateRect( 1, 1 );
01201 dc.Draw3dRect( &rcCell, crBack, crBack );
01202 rcCell.DeflateRect( 0, 1 );
01203 dc.Draw3dRect( &rcCell, RGB( 50, 50, 50 ), RGB( 50, 50, 50 ) );
01204 rcCell.DeflateRect( 1, 1 );
01205 CFragmentBar::DrawSource( &dc, &rcCell, pSource, crNatural );
01206 break;
01207
01208 case DOWNLOAD_COLUMN_SPEED:
01209 if ( pSource->m_pTransfer != NULL )
01210 {
01211 if ( DWORD nSpeed = pSource->m_pTransfer->GetMeasuredSpeed() * 8 )
01212 strText = Settings.SmartVolume( nSpeed, FALSE, TRUE );
01213 }
01214 break;
01215
01216 case DOWNLOAD_COLUMN_STATUS:
01217 if ( pSource->m_pTransfer != NULL )
01218 strText = pSource->m_pTransfer->GetStateText( FALSE );
01219 else if ( pSource->m_tAttempt )
01220 {
01221 DWORD nTime = GetTickCount();
01222
01223 if ( pSource->m_tAttempt >= nTime )
01224 {
01225 nTime = ( pSource->m_tAttempt - nTime ) / 1000;
01226 strText.Format( _T("%.2u:%.2u"), nTime / 60, nTime % 60 );
01227 }
01228 }
01229 break;
01230
01231 case DOWNLOAD_COLUMN_CLIENT:
01232 strText = pSource->m_sServer;
01233 break;
01234 case DOWNLOAD_COLUMN_DOWNLOADED:
01235 if ( pSource->m_pTransfer != NULL )
01236 strText = Settings.SmartVolume( pSource->m_pTransfer->m_nDownloaded, FALSE );
01237 break;
01238 case DOWNLOAD_COLUMN_PERCENTAGE:
01239 if ( ( pDownload->m_nSize < SIZE_UNKNOWN ) && ( pDownload->m_nSize > 0 ) && ( pSource->m_pTransfer ) )
01240 strText.Format( _T("%i%%"), ((int) ( (double)( pSource->m_pTransfer->m_nDownloaded ) / (double)( pSource->m_pDownload->m_nSize ) * 100 )) );
01241 else
01242 strText = _T("-");
01243 break;
01244
01245 }
01246
01247 nTextLeft = min( nTextLeft, int(rcCell.left) );
01248 nTextRight = max( nTextRight, int(rcCell.right) );
01249
01250 if ( pColumn.lParam == DOWNLOAD_COLUMN_PROGRESS ) continue;
01251
01252 if ( rcCell.Width() < 8 ) strText.Empty();
01253
01254 if ( dc.GetTextExtent( strText ).cx > rcCell.Width() - 8 )
01255 {
01256 while ( dc.GetTextExtent( strText + _T('\x2026') ).cx > ( rcCell.Width() - 8 ) && strText.GetLength() > 0 )
01257 {
01258 strText.Truncate( strText.GetLength() - 1 );
01259 }
01260
01261 if ( strText.GetLength() > 0 ) strText += _T('\x2026');
01262 }
01263
01264 int nWidth = dc.GetTextExtent( strText ).cx;
01265 int nPosition = 0;
01266
01267 switch ( pColumn.fmt & LVCFMT_JUSTIFYMASK )
01268 {
01269 default:
01270 nPosition = ( rcCell.left + 4 );
01271 break;
01272 case LVCFMT_CENTER:
01273 nPosition = ( ( rcCell.left + rcCell.right ) / 2 ) - ( nWidth / 2 );
01274 break;
01275 case LVCFMT_RIGHT:
01276 nPosition = ( rcCell.right - 4 - nWidth );
01277 break;
01278 }
01279
01280 dc.SetBkColor( crBack );
01281 dc.ExtTextOut( nPosition, rcCell.top + 2, ETO_CLIPPED|ETO_OPAQUE,
01282 &rcCell, strText, NULL );
01283 }
01284
01285 if ( nTextRight < rcRow.right )
01286 {
01287 CRect rcBlank( nTextRight, rcRow.top, rcRow.right, rcRow.bottom );
01288 dc.FillSolidRect( &rcBlank, crBack );
01289 }
01290
01291 if ( bFocus )
01292 {
01293 CRect rcFocus( nTextLeft, rcRow.top, max( int(rcRow.right), nTextRight ), rcRow.bottom );
01294 dc.Draw3dRect( &rcFocus, CoolInterface.m_crBorder, CoolInterface.m_crBorder );
01295 }
01296 }
01297
01299
01300
01301 void CDownloadsCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
01302 {
01303 SCROLLINFO pInfo;
01304
01305 pInfo.cbSize = sizeof(pInfo);
01306 pInfo.fMask = SIF_ALL & ~SIF_TRACKPOS;
01307
01308 GetScrollInfo( SB_VERT, &pInfo );
01309 int nDelta = pInfo.nPos;
01310
01311 switch ( nSBCode )
01312 {
01313 case SB_BOTTOM:
01314 pInfo.nPos = pInfo.nMax - pInfo.nPage;
01315 break;
01316 case SB_LINEDOWN:
01317 pInfo.nPos ++;
01318 break;
01319 case SB_LINEUP:
01320 pInfo.nPos --;
01321 break;
01322 case SB_PAGEDOWN:
01323 pInfo.nPos += pInfo.nPage;
01324 break;
01325 case SB_PAGEUP:
01326 pInfo.nPos -= pInfo.nPage;
01327 break;
01328 case SB_THUMBPOSITION:
01329 case SB_THUMBTRACK:
01330 pInfo.nPos = nPos;
01331 break;
01332 case SB_TOP:
01333 pInfo.nPos = 0;
01334 break;
01335 }
01336
01337 pInfo.nPos = max( 0, min( pInfo.nPos, pInfo.nMax - (int)pInfo.nPage + 1 ) );
01338 if ( pInfo.nPos == nDelta ) return;
01339
01340 SetScrollInfo( SB_VERT, &pInfo, TRUE );
01341 Invalidate();
01342 }
01343
01344 void CDownloadsCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
01345 {
01346 SCROLLINFO pInfo;
01347
01348 pInfo.cbSize = sizeof(pInfo);
01349 pInfo.fMask = SIF_ALL & ~SIF_TRACKPOS;
01350
01351 GetScrollInfo( SB_HORZ, &pInfo );
01352 int nDelta = pInfo.nPos;
01353
01354 switch ( nSBCode )
01355 {
01356 case SB_BOTTOM:
01357 pInfo.nPos = pInfo.nMax - pInfo.nPage;
01358 break;
01359 case SB_LINEDOWN:
01360 pInfo.nPos ++;
01361 break;
01362 case SB_LINEUP:
01363 pInfo.nPos --;
01364 break;
01365 case SB_PAGEDOWN:
01366 pInfo.nPos += pInfo.nPage;
01367 break;
01368 case SB_PAGEUP:
01369 pInfo.nPos -= pInfo.nPage;
01370 break;
01371 case SB_THUMBPOSITION:
01372 case SB_THUMBTRACK:
01373 pInfo.nPos = nPos;
01374 break;
01375 case SB_TOP:
01376 pInfo.nPos = 0;
01377 break;
01378 }
01379
01380 pInfo.nPos = max( 0, min( pInfo.nPos, pInfo.nMax - (int)pInfo.nPage + 1 ) );
01381 if ( pInfo.nPos == nDelta ) return;
01382
01383 SetScrollInfo( SB_HORZ, &pInfo, TRUE );
01384
01385 CRect rcClient;
01386 GetClientRect( &rcClient );
01387
01388 m_wndHeader.SetWindowPos( NULL, -pInfo.nPos, 0,
01389 rcClient.right + pInfo.nPos, HEADER_HEIGHT, SWP_NOZORDER );
01390
01391 RedrawWindow( NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW );
01392 }
01393
01394 BOOL CDownloadsCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
01395 {
01396 OnVScroll( SB_THUMBPOSITION, (int)( GetScrollPos( SB_VERT ) - zDelta / WHEEL_DELTA * m_nScrollWheelLines ), NULL );
01397 return TRUE;
01398 }
01399
01400 void CDownloadsCtrl::OnChangeHeader(NMHDR* pNotifyStruct, LRESULT* pResult)
01401 {
01402 Update();
01403 }
01404
01405 CString CDownloadsCtrl::GetDownloadStatus(CDownload *pDownload)
01406 {
01407 CString strText;
01408 int nSources = pDownload->GetSourceCount();
01409
01410 if ( pDownload->IsCompleted() )
01411 if( pDownload->IsSeeding() )
01412 {
01413 if ( pDownload->m_bTorrentTrackerError )
01414 LoadString( strText, IDS_STATUS_TRACKERDOWN );
01415 else
01416 LoadString( strText, IDS_STATUS_SEEDING );
01417 }
01418 else
01419 LoadString( strText, IDS_STATUS_COMPLETED );
01420 else if ( pDownload->IsPaused() )
01421 {
01422 if ( pDownload->m_bDiskFull )
01423 if( pDownload->IsMoving() )
01424 LoadString( strText, IDS_STATUS_CANTMOVE );
01425 else
01426 LoadString( strText, IDS_STATUS_FILEERROR );
01427 else
01428 LoadString( strText, IDS_STATUS_PAUSED );
01429 }
01430 else if ( pDownload->IsMoving() )
01431 LoadString( strText, IDS_STATUS_MOVING );
01432 else if ( pDownload->GetProgress() == 1.0f && pDownload->IsStarted() )
01433 LoadString( strText, IDS_STATUS_VERIFYING );
01434 else if ( pDownload->IsDownloading() )
01435 {
01436 DWORD nTime = pDownload->GetTimeRemaining();
01437
01438 if ( nTime == 0xFFFFFFFF )
01439 LoadString( strText, IDS_STATUS_ACTIVE );
01440 else
01441 {
01442 if ( nTime > 86400 )
01443 strText.Format( _T("%i:%.2i:%.2i:%.2i"), nTime / 86400, ( nTime / 3600 ) % 24, ( nTime / 60 ) % 60, nTime % 60 );
01444 else
01445 strText.Format( _T("%i:%.2i:%.2i"), nTime / 3600, ( nTime / 60 ) % 60, nTime % 60 );
01446 }
01447 }
01448 else if ( ! pDownload->IsTrying() )
01449 LoadString( strText, IDS_STATUS_QUEUED );
01450 else if ( nSources > 0 )
01451 LoadString( strText, IDS_STATUS_PENDING );
01452 else if ( pDownload->m_bBTH )
01453 {
01454 if ( pDownload->IsTasking() )
01455 LoadString( strText, IDS_STATUS_CREATING );
01456 else if ( pDownload->m_bTorrentTrackerError )
01457 LoadString( strText, IDS_STATUS_TRACKERDOWN );
01458 else
01459 LoadString( strText, IDS_STATUS_TORRENT );
01460 }
01461 else
01462 LoadString( strText, IDS_STATUS_SEARCHING );
01463
01464 return strText;
01465 }
01466
01467 int CDownloadsCtrl::GetClientStatus(CDownload *pDownload)
01468 {
01469 int nSources = pDownload->GetSourceCount();
01470
01471 if ( pDownload->IsCompleted() )
01472 return -1;
01473 else if ( nSources >= 1 )
01474 return nSources;
01475 else
01476 return nSources;
01477
01478 return nSources;
01479 }
01480
01481 void CDownloadsCtrl::BubbleSortDownloads(int nColumn)
01482 {
01483 POSITION pos;
01484 int nTransfers, j, pass;
01485 CDownload *x, *y;
01486 BOOL bSwitch=TRUE, bSort, bOK;
01487 CString s, t;
01488
01489 bSort=m_pbSortAscending[nColumn];
01490
01491
01492 m_pbSortAscending[nColumn]= !bSort;
01493
01494 nTransfers = Downloads.GetCount();
01495 for (pass=0; (pass < nTransfers-1) && (bSwitch == TRUE); pass++)
01496 {
01497 bSwitch=FALSE;
01498 pos=Downloads.GetIterator();
01499 for (j=0 ; (j < nTransfers-pass-1) && (pos != NULL) ; j++ )
01500 {
01501 x = Downloads.GetNext( pos );
01502 y = Downloads.GetNext( pos );
01503 s = x->GetDisplayName();
01504 t = y->GetDisplayName();
01505 bOK = FALSE;
01506 if ( m_pbSortAscending[nColumn] == FALSE )
01507 {
01508 switch ( nColumn )
01509 {
01510 case DOWNLOAD_COLUMN_TITLE:
01511 if ( x->GetDisplayName().CompareNoCase( y->GetDisplayName() ) > 0 )
01512 bOK = TRUE;
01513 break;
01514 case DOWNLOAD_COLUMN_SIZE:
01515 if ( x->m_nSize > y->m_nSize )
01516 bOK = TRUE;
01517 break;
01518 case DOWNLOAD_COLUMN_PROGRESS:
01519 if ( x->GetProgress() > y->GetProgress() )
01520 bOK = TRUE;
01521 break;
01522 case DOWNLOAD_COLUMN_SPEED:
01523 if ( x->GetMeasuredSpeed() > y->GetMeasuredSpeed() )
01524 bOK = TRUE;
01525 break;
01526 case DOWNLOAD_COLUMN_STATUS:
01527 if ( GetDownloadStatus( x ).CompareNoCase(GetDownloadStatus(y)) > 0 )
01528 bOK = TRUE;
01529 break;
01530 case DOWNLOAD_COLUMN_CLIENT:
01531 if ( GetClientStatus( x ) > GetClientStatus(y) )
01532 bOK = TRUE;
01533 break;
01534 case DOWNLOAD_COLUMN_DOWNLOADED:
01535 if ( x->GetVolumeComplete() > y->GetVolumeComplete() )
01536 bOK = TRUE;
01537 break;
01538 case DOWNLOAD_COLUMN_PERCENTAGE:
01539 if ( ((double)(x->GetVolumeComplete() ) / (double)(x->m_nSize)) > ((double)(y->GetVolumeComplete() ) / (double)(y->m_nSize)) )
01540 bOK = TRUE;
01541 break;
01542 }
01543 if (bOK)
01544 {
01545 bSwitch = TRUE;
01546 Downloads.Swap( y, x );
01547 }
01548 }
01549 else
01550 {
01551 switch ( nColumn )
01552 {
01553 case DOWNLOAD_COLUMN_TITLE:
01554 if ( x->GetDisplayName().CompareNoCase(y->GetDisplayName()) < 0 )
01555 bOK = TRUE;
01556 break;
01557 case DOWNLOAD_COLUMN_SIZE:
01558 if ( x->m_nSize < y->m_nSize )
01559 bOK = TRUE;
01560 break;
01561 case DOWNLOAD_COLUMN_PROGRESS:
01562 if ( x->GetProgress() < y->GetProgress() )
01563 bOK = TRUE;
01564 break;
01565 case DOWNLOAD_COLUMN_SPEED:
01566 if ( x->GetMeasuredSpeed() < y->GetMeasuredSpeed() )
01567 bOK = TRUE;
01568 break;
01569 case DOWNLOAD_COLUMN_STATUS:
01570 if ( GetDownloadStatus(x).CompareNoCase( GetDownloadStatus(y) ) < 0 )
01571 bOK = TRUE;
01572 break;
01573 case DOWNLOAD_COLUMN_CLIENT:
01574 if ( GetClientStatus(x) < GetClientStatus(y) )
01575 bOK = TRUE;
01576 break;
01577 case DOWNLOAD_COLUMN_DOWNLOADED:
01578 if ( x->GetVolumeComplete() < y->GetVolumeComplete() )
01579 bOK = TRUE;
01580 break;
01581 case DOWNLOAD_COLUMN_PERCENTAGE:
01582 if ( ((double)(x->GetVolumeComplete() ) / (double)(x->m_nSize)) < ((double)(y->GetVolumeComplete() ) / (double)(y->m_nSize)) )
01583 bOK = TRUE;
01584 break;
01585
01586 }
01587 if (bOK)
01588 {
01589 bSwitch = TRUE;
01590 Downloads.Swap( x, y );
01591 }
01592 }
01593
01594 if ( pos != NULL )
01595 Downloads.GetPrevious( pos );
01596 }
01597 }
01598 }
01599
01600 void CDownloadsCtrl::OnSortPanelItems(NMHDR* pNotifyStruct, LRESULT* pResult)
01601 {
01602 CSingleLock pLock( &Transfers.m_pSection, TRUE );
01603 NMLISTVIEW *pLV = (NMLISTVIEW *) pNotifyStruct;
01604 BubbleSortDownloads( pLV->iItem );
01605 Invalidate();
01606 }
01607
01608
01609 void CDownloadsCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
01610 {
01611 CSingleLock pLock( &Transfers.m_pSection, TRUE );
01612 CDownloadSource* pSource;
01613 CDownload* pDownload;
01614
01615 m_wndTip.Hide();
01616
01617 switch ( nChar )
01618 {
01619 case VK_HOME:
01620 SelectTo( 0 );
01621 return;
01622 case VK_END:
01623 {
01624 INT nMin, nMax;
01625 GetScrollRange( SB_VERT, &nMin, &nMax );
01626 SelectTo( max( 0, nMax - 1 ) );
01627 }
01628 return;
01629 case VK_UP:
01630 if ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 )
01631 MoveSelected( -1 );
01632 else
01633 SelectTo( m_nFocus - 1 );
01634 return;
01635 case VK_DOWN:
01636 if ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 )
01637 MoveSelected( 1 );
01638 else
01639 SelectTo( m_nFocus + 1 );
01640 return;
01641 case VK_PRIOR:
01642 SelectTo( m_nFocus - 10 );
01643 return;
01644 case VK_NEXT:
01645 SelectTo( m_nFocus + 10 );
01646 return;
01647 case VK_LEFT:
01648 case VK_SUBTRACT:
01649 if ( GetAt( m_nFocus, &pDownload, &pSource ) )
01650 {
01651 if ( pSource != NULL ) pDownload = pSource->m_pDownload;
01652 if ( pDownload->m_bExpanded == TRUE )
01653 {
01654 pDownload->m_bExpanded = FALSE;
01655 Update();
01656 }
01657 }
01658 return;
01659 case VK_RIGHT:
01660 case VK_ADD:
01661 if ( GetAt( m_nFocus, &pDownload, NULL ) && pDownload != NULL && pDownload->m_bExpanded == FALSE )
01662 {
01663 pDownload->m_bExpanded = TRUE;
01664 Update();
01665 }
01666 return;
01667 case 'A':
01668 if ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 )
01669 SelectAll();
01670 return;
01671 case 'E':
01672 if ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 )
01673 {
01674 GetOwner()->PostMessage( WM_TIMER, 5 );
01675 GetOwner()->PostMessage( WM_COMMAND, ID_DOWNLOADS_ENQUEUE );
01676 }
01677 return;
01678 case 'R':
01679 if ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 )
01680 GetOwner()->PostMessage( WM_COMMAND, ID_DOWNLOADS_VIEW_REVIEWS );
01681 return;
01682 case VK_DELETE:
01683 GetOwner()->PostMessage( WM_COMMAND, ID_DOWNLOADS_CLEAR );
01684 return;
01685 case VK_RETURN:
01686 OnEnterKey();
01687 return;
01688 }
01689
01690 CWnd::OnKeyDown( nChar, nRepCnt, nFlags );
01691 }
01692
01693 void CDownloadsCtrl::OnEnterKey()
01694 {
01695 CDownloadSource* pSource;
01696 CDownload* pDownload;
01697
01698 GetAt( m_nFocus, &pDownload, &pSource );
01699 if ( pDownload != NULL )
01700 {
01701 if ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 )
01702 {
01703 GetOwner()->PostMessage( WM_TIMER, 5 );
01704 GetOwner()->PostMessage( WM_COMMAND, ID_DOWNLOADS_LAUNCH );
01705 }
01706 }
01707 else if ( pSource != NULL )
01708 {
01709 GetOwner()->PostMessage( WM_TIMER, 5 );
01710 GetOwner()->PostMessage( WM_COMMAND, ID_TRANSFERS_CONNECT );
01711 }
01712 }
01713
01714 void CDownloadsCtrl::OnLButtonDown(UINT nFlags, CPoint point)
01715 {
01716 CSingleLock pLock( &Transfers.m_pSection, TRUE );
01717 CDownloadSource* pSource;
01718 CDownload* pDownload;
01719 CRect rcItem;
01720 int nIndex;
01721
01722 SetFocus();
01723 m_wndTip.Hide();
01724
01725 if ( HitTest( point, &pDownload, &pSource, &nIndex, &rcItem ) )
01726 {
01727 int nTitleStarts = GetExpandableColumnX();
01728 if ( point.x > nTitleStarts && point.x <= nTitleStarts + rcItem.left + 16 )
01729 {
01730 if ( pDownload != NULL && IsExpandable( pDownload ) )
01731 {
01732 pDownload->m_bExpanded = ! pDownload->m_bExpanded;
01733
01734 if ( ! pDownload->m_bExpanded )
01735 {
01736 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource != NULL ; pSource = pSource->m_pNext )
01737 pSource->m_bSelected = FALSE;
01738 }
01739
01740 Update();
01741 }
01742 }
01743 else
01744 {
01745 if ( pDownload != NULL && pDownload->m_bSelected )
01746 {
01747 if ( ( nFlags & ( MK_SHIFT | MK_CONTROL | MK_RBUTTON ) ) == 0 )
01748 {
01749 m_pDeselect1 = pDownload;
01750 }
01751 }
01752 else if ( pSource != NULL && pSource->m_bSelected )
01753 {
01754 if ( ( nFlags & ( MK_SHIFT | MK_CONTROL | MK_RBUTTON ) ) == 0 )
01755 {
01756 m_pDeselect2 = pSource;
01757 }
01758 }
01759 else if ( nFlags & MK_RBUTTON )
01760 {
01761 DeselectAll();
01762 }
01763
01764 SelectTo( nIndex );
01765 }
01766 }
01767 else if ( ( nFlags & ( MK_SHIFT | MK_CONTROL ) ) == 0 )
01768 {
01769 DeselectAll();
01770 Update();
01771 }
01772
01773 if ( ( nFlags & MK_LBUTTON ) && GetSelectedCount() > 0 )
01774 {
01775 m_bDrag = TRUE;
01776 m_ptDrag = point;
01777 }
01778 }
01779
01780 void CDownloadsCtrl::OnRButtonDown(UINT nFlags, CPoint point)
01781 {
01782 m_wndTip.Hide();
01783 OnLButtonDown( nFlags, point );
01784 CWnd::OnRButtonDown( nFlags, point );
01785 }
01786
01787 void CDownloadsCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
01788 {
01789 CSingleLock pLock( &Transfers.m_pSection, TRUE );
01790 CDownloadSource* pSource;
01791 CDownload* pDownload;
01792 CRect rcItem;
01793
01794 SetFocus();
01795
01796 if ( HitTest( point, &pDownload, &pSource, NULL, &rcItem ) )
01797 {
01798 int nTitleStarts = GetExpandableColumnX();
01799 if ( pDownload != NULL && point.x > nTitleStarts && point.x <= nTitleStarts + rcItem.left + 16 )
01800 {
01801 if ( IsExpandable( pDownload ) )
01802 {
01803 pDownload->m_bExpanded = ! pDownload->m_bExpanded;
01804
01805 if ( ! pDownload->m_bExpanded )
01806 {
01807 for ( CDownloadSource* pSource = pDownload->GetFirstSource() ; pSource != NULL ; pSource = pSource->m_pNext )
01808 pSource->m_bSelected = FALSE;
01809 }
01810
01811 Update();
01812 }
01813 }
01814 else if ( pDownload != NULL )
01815 {
01816 GetOwner()->PostMessage( WM_TIMER, 5 );
01817 GetOwner()->PostMessage( WM_COMMAND, ID_DOWNLOADS_LAUNCH );
01818 }
01819 else if ( pSource != NULL )
01820 {
01821 GetOwner()->PostMessage( WM_TIMER, 5 );
01822 GetOwner()->PostMessage( WM_COMMAND, ID_TRANSFERS_CONNECT );
01823 }
01824 }
01825
01826 CWnd::OnLButtonDblClk( nFlags, point );
01827 }
01828
01829 void CDownloadsCtrl::OnMouseMove(UINT nFlags, CPoint point)
01830 {
01831 CWnd::OnMouseMove( nFlags, point );
01832
01833 if ( ( nFlags & ( MK_LBUTTON|MK_RBUTTON) ) == 0 )
01834 {
01835 CDownloadSource* pSource;
01836 CDownload* pDownload;
01837 CRect rcItem;
01838
01839 if ( HitTest( point, &pDownload, &pSource, NULL, &rcItem ) )
01840 {
01841 if ( pDownload != NULL && point.x > rcItem.left + 16 )
01842 {
01843 m_wndTip.Show( pDownload );
01844 return;
01845 }
01846 else if ( pSource != NULL )
01847 {
01848 m_wndTip.Show( pSource );
01849 return;
01850 }
01851 }
01852 }
01853 else if ( m_bDrag )
01854 {
01855 if ( abs( point.x - m_ptDrag.x ) >= GetSystemMetrics( SM_CXDRAG ) ||
01856 abs( point.y - m_ptDrag.y ) >= GetSystemMetrics( SM_CYDRAG ) )
01857 {
01858 OnBeginDrag( point );
01859 m_bDrag = FALSE;
01860
01861 }
01862 }
01863
01864 m_wndTip.Hide();
01865 }
01866
01867 void CDownloadsCtrl::OnLButtonUp(UINT nFlags, CPoint point)
01868 {
01869 m_bDrag = FALSE;
01870
01871 if ( m_pDeselect1 != NULL )
01872 {
01873 DeselectAll( m_pDeselect1 );
01874 m_pDeselect1 = NULL;
01875 }
01876 else if ( m_pDeselect2 != NULL )
01877 {
01878 DeselectAll( NULL, m_pDeselect2 );
01879 m_pDeselect2 = NULL;
01880 }
01881
01882 CWnd::OnLButtonUp( nFlags, point );
01883 }
01884
01885 void CDownloadsCtrl::OnRButtonUp(UINT nFlags, CPoint point)
01886 {
01887 m_bDrag = FALSE;
01888
01889 if ( m_pDeselect1 != NULL )
01890 {
01891 DeselectAll( m_pDeselect1 );
01892 m_pDeselect1 = NULL;
01893 }
01894 else if ( m_pDeselect2 != NULL )
01895 {
01896 DeselectAll( NULL, m_pDeselect2 );
01897 m_pDeselect2 = NULL;
01898 }
01899
01900 CWnd::OnRButtonUp( nFlags, point );
01901 }
01902
01903 void CDownloadsCtrl::OnSetFocus(CWnd* pOldWnd)
01904 {
01905 CWnd::OnSetFocus( pOldWnd );
01906 Invalidate();
01907 }
01908
01909 void CDownloadsCtrl::OnKillFocus(CWnd* pNewWnd)
01910 {
01911 CWnd::OnKillFocus( pNewWnd );
01912 Invalidate();
01913 }
01914
01915 void CDownloadsCtrl::OnBeginDrag(CPoint ptAction)
01916 {
01917 m_wndTip.Hide();
01918 m_pDeselect1 = NULL;
01919 m_pDeselect2 = NULL;
01920
01921 CPtrList* pSel = new CPtrList();
01922
01923 for ( POSITION pos = Downloads.GetIterator() ; pos ; )
01924 {
01925 CDownload* pDownload = Downloads.GetNext( pos );
01926 if ( pDownload->m_bSelected ) pSel->AddTail( pDownload );
01927 }
01928
01929 if ( pSel->GetCount() == 0 )
01930 {
01931 delete pSel;
01932 return;
01933 }
01934
01935 m_bCreateDragImage = TRUE;
01936 CImageList* pDragImage = CreateDragImage( pSel, ptAction );
01937 m_bCreateDragImage = FALSE;
01938
01939 if ( pDragImage == NULL )
01940 {
01941 delete pSel;
01942 return;
01943 }
01944
01945 m_pDragDrop = NULL;
01946 UpdateWindow();
01947
01948 ClientToScreen( &ptAction );
01949
01950 CDownloadsWnd* pWindow = (CDownloadsWnd*)GetOwner();
01951 ASSERT_KINDOF( CDownloadsWnd, pWindow );
01952 pWindow->DragDownloads( pSel, pDragImage, ptAction );
01953 }
01954
01955 #define MAX_DRAG_SIZE 128
01956 #define MAX_DRAG_SIZE_2 (MAX_DRAG_SIZE/2)
01957
01958 CImageList* CDownloadsCtrl::CreateDragImage(CPtrList* pSel, const CPoint& ptMouse)
01959 {
01960 CRect rcClient, rcOne, rcAll( 32000, 32000, -32000, -32000 );
01961
01962 GetClientRect( &rcClient );
01963
01964 for ( POSITION pos = pSel->GetHeadPosition() ; pos ; )
01965 {
01966 CDownload* pDownload = (CDownload*)pSel->GetNext( pos );
01967 GetRect( pDownload, &rcOne );
01968
01969 if ( rcOne.IntersectRect( &rcClient, &rcOne ) )
01970 {
01971 rcAll.left = min( rcAll.left, rcOne.left );
01972 rcAll.top = min( rcAll.top, rcOne.top );
01973 rcAll.right = max( rcAll.right, rcOne.right );
01974 rcAll.bottom = max( rcAll.bottom, rcOne.bottom );
01975 }
01976 }
01977
01978 BOOL bClipped = rcAll.Height() > MAX_DRAG_SIZE;
01979
01980 if ( bClipped )
01981 {
01982 rcAll.left = max( rcAll.left, ptMouse.x - MAX_DRAG_SIZE_2 );
01983 rcAll.right = max( rcAll.right, ptMouse.x + MAX_DRAG_SIZE_2 );
01984 rcAll.top = max( rcAll.top, ptMouse.y - MAX_DRAG_SIZE_2 );
01985 rcAll.bottom = max( rcAll.bottom, ptMouse.y + MAX_DRAG_SIZE_2 );
01986 }
01987
01988 CClientDC dcClient( this );
01989 CDC dcMem, dcDrag;
01990 CBitmap bmDrag;
01991
01992 if ( ! dcMem.CreateCompatibleDC( &dcClient ) )
01993 return NULL;
01994 if ( ! dcDrag.CreateCompatibleDC( &dcClient ) )
01995 return NULL;
01996 if ( ! bmDrag.CreateCompatibleBitmap( &dcClient, rcAll.Width(), rcAll.Height() ) )
01997 return NULL;
01998
01999 CBitmap *pOldDrag = dcDrag.SelectObject( &bmDrag );
02000
02001 dcDrag.FillSolidRect( 0, 0, rcAll.Width(), rcAll.Height(), RGB( 250, 255, 250 ) );
02002
02003 CRgn pRgn;
02004
02005 if ( bClipped )
02006 {
02007 CPoint ptMiddle( ptMouse.x - rcAll.left, ptMouse.y - rcAll.top );
02008 pRgn.CreateEllipticRgn( ptMiddle.x - MAX_DRAG_SIZE_2, ptMiddle.y - MAX_DRAG_SIZE_2,
02009 ptMiddle.x + MAX_DRAG_SIZE_2, ptMiddle.y + MAX_DRAG_SIZE_2 );
02010 dcDrag.SelectClipRgn( &pRgn );
02011 }
02012
02013 CFont* pOldFont = (CFont*)dcDrag.SelectObject( &CoolInterface.m_fntNormal );
02014
02015 for ( POSITION pos = pSel->GetHeadPosition() ; pos ; )
02016 {
02017 CDownload* pDownload = (CDownload*)pSel->GetNext( pos );
02018 GetRect( pDownload, &rcOne );
02019 CRect rcDummy, rcOut( &rcOne );
02020 rcOut.OffsetRect( -rcAll.left, -rcAll.top );
02021
02022 if ( rcDummy.IntersectRect( &rcAll, &rcOne ) )
02023 {
02024 dcDrag.FillSolidRect( &rcOut, RGB( 250, 255, 250 ) );
02025 PaintDownload( dcDrag, rcOut, pDownload, FALSE, FALSE );
02026 }
02027 }
02028
02029 dcDrag.SelectObject( pOldFont );
02030 dcDrag.SelectObject( pOldDrag );
02031 dcDrag.DeleteDC();
02032
02033 CImageList* pAll = new CImageList();
02034 pAll->Create( rcAll.Width(), rcAll.Height(), ILC_COLOR16|ILC_MASK, 1, 1 );
02035 pAll->Add( &bmDrag, RGB( 250, 255, 250 ) );
02036
02037 bmDrag.DeleteObject();
02038
02039 pAll->BeginDrag( 0, ptMouse - rcAll.TopLeft() );
02040
02041 return pAll;
02042 }
02043
02044 int CDownloadsCtrl::GetExpandableColumnX() const
02045 {
02046 HDITEM pColumn;
02047 int nTitleStarts = 0;
02048
02049 ZeroMemory( &pColumn, sizeof(pColumn) );
02050 pColumn.mask = HDI_LPARAM | HDI_WIDTH;
02051
02052 for ( int nColumn = 0 ; m_wndHeader.GetItem( m_wndHeader.OrderToIndex( nColumn ), &pColumn ) ; nColumn++ )
02053 {
02054 if ( pColumn.lParam == DOWNLOAD_COLUMN_TITLE ) break;
02055 else nTitleStarts += pColumn.cxy;
02056 }
02057 return nTitleStarts;
02058 }