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 "Transfers.h"
00026 #include "UploadQueues.h"
00027 #include "UploadQueue.h"
00028 #include "UploadFiles.h"
00029 #include "UploadFile.h"
00030 #include "UploadTransfer.h"
00031 #include "UploadTransferBT.h"
00032 #include "CoolInterface.h"
00033 #include "ShellIcons.h"
00034 #include "FragmentBar.h"
00035 #include "Skin.h"
00036 #include "CtrlUploads.h"
00037
00038 #include "Downloads.h"
00039
00040 IMPLEMENT_DYNAMIC(CUploadsCtrl, CWnd)
00041
00042 BEGIN_MESSAGE_MAP(CUploadsCtrl, CWnd)
00043 ON_WM_CREATE()
00044 ON_WM_DESTROY()
00045 ON_WM_SIZE()
00046 ON_WM_PAINT()
00047 ON_WM_VSCROLL()
00048 ON_WM_HSCROLL()
00049 ON_WM_MOUSEWHEEL()
00050 ON_NOTIFY(HDN_ITEMCHANGEDW, AFX_IDW_PANE_FIRST, OnChangeHeader)
00051 ON_NOTIFY(HDN_ITEMCHANGEDA, AFX_IDW_PANE_FIRST, OnChangeHeader)
00052 ON_NOTIFY(HDN_ENDDRAG, AFX_IDW_PANE_FIRST, OnChangeHeader)
00053 ON_WM_KEYDOWN()
00054 ON_WM_LBUTTONDOWN()
00055 ON_WM_RBUTTONDOWN()
00056 ON_WM_LBUTTONDBLCLK()
00057 ON_WM_MOUSEMOVE()
00058 ON_WM_LBUTTONUP()
00059 ON_WM_RBUTTONUP()
00060 ON_WM_SETFOCUS()
00061 ON_WM_KILLFOCUS()
00062 END_MESSAGE_MAP()
00063
00064 #define HEADER_HEIGHT 20
00065 #define ITEM_HEIGHT 17
00066
00067 #define UPLOAD_COLUMN_TITLE 0
00068 #define UPLOAD_COLUMN_USER 1
00069 #define UPLOAD_COLUMN_SIZE 2
00070 #define UPLOAD_COLUMN_PROGRESS 3
00071 #define UPLOAD_COLUMN_SPEED 4
00072 #define UPLOAD_COLUMN_CLIENT 5
00073 #define UPLOAD_COLUMN_RATING 6
00074
00075
00077
00078
00079 CUploadsCtrl::CUploadsCtrl()
00080 {
00081
00082 if( !SystemParametersInfo ( SPI_GETWHEELSCROLLLINES, 0, &m_nScrollWheelLines, 0) )
00083 {
00084 m_nScrollWheelLines = 3;
00085 }
00086 }
00087
00088 CUploadsCtrl::~CUploadsCtrl()
00089 {
00090 }
00091
00093
00094
00095 BOOL CUploadsCtrl::Create(CWnd* pParentWnd, UINT nID)
00096 {
00097 CRect rect( 0, 0, 0, 0 );
00098 return CWnd::Create( NULL, NULL, WS_CHILD|WS_CLIPSIBLINGS, rect, pParentWnd, nID, NULL );
00099 }
00100
00101 BOOL CUploadsCtrl::Update()
00102 {
00103 OnSize( 1982, 0, 0 );
00104 return TRUE;
00105 }
00106
00108
00109
00110 int CUploadsCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
00111 {
00112 if ( CWnd::OnCreate( lpCreateStruct ) == -1 ) return -1;
00113
00114 CRect rect( 0, 0, 0, 0 );
00115 m_wndHeader.Create( WS_CHILD|HDS_DRAGDROP|HDS_HOTTRACK|HDS_FULLDRAG, rect, this, AFX_IDW_PANE_FIRST );
00116 m_wndHeader.SetFont( &theApp.m_gdiFont );
00117
00118 m_wndTip.Create( this, &Settings.Interface.TipUploads );
00119
00120 InsertColumn( UPLOAD_COLUMN_TITLE, _T("Uploaded File"), LVCFMT_LEFT, 210 );
00121 InsertColumn( UPLOAD_COLUMN_USER, _T("Remote User"), LVCFMT_LEFT, 100 );
00122 InsertColumn( UPLOAD_COLUMN_SIZE, _T("Size"), LVCFMT_CENTER, 80 );
00123 InsertColumn( UPLOAD_COLUMN_PROGRESS, _T("Progress"), LVCFMT_CENTER, 130 );
00124 InsertColumn( UPLOAD_COLUMN_SPEED, _T("Speed"), LVCFMT_CENTER, 80 );
00125 InsertColumn( UPLOAD_COLUMN_CLIENT, _T("Client"), LVCFMT_CENTER, 100 );
00126 InsertColumn( UPLOAD_COLUMN_RATING, _T("Rating"), LVCFMT_CENTER, 0 );
00127
00128
00129 LoadColumnState();
00130
00131 CBitmap bmImages;
00132 bmImages.LoadBitmap( IDB_PROTOCOLS );
00133 if ( theApp.m_bRTL )
00134 bmImages.m_hObject = CreateMirroredBitmap( (HBITMAP)bmImages.m_hObject );
00135 m_pProtocols.Create( 16, 16, ILC_COLOR16|ILC_MASK, 7, 1 );
00136 m_pProtocols.Add( &bmImages, RGB( 0, 255, 0 ) );
00137
00138 m_nFocus = 0;
00139 m_pDeselect = NULL;
00140
00141 return 0;
00142 }
00143
00144 void CUploadsCtrl::OnDestroy()
00145 {
00146 SaveColumnState();
00147 CWnd::OnDestroy();
00148 }
00149
00151
00152
00153 void CUploadsCtrl::InsertColumn(int nColumn, LPCTSTR pszCaption, int nFormat, int nWidth)
00154 {
00155 HDITEM pColumn;
00156
00157 ZeroMemory( &pColumn, sizeof(pColumn) );
00158
00159 pColumn.mask = HDI_FORMAT | HDI_LPARAM | HDI_TEXT | HDI_WIDTH;
00160 pColumn.cxy = nWidth;
00161 pColumn.pszText = (LPTSTR)pszCaption;
00162 pColumn.fmt = nFormat;
00163 pColumn.lParam = nColumn;
00164
00165 m_wndHeader.InsertItem( m_wndHeader.GetItemCount(), &pColumn );
00166 }
00167
00168 void CUploadsCtrl::SaveColumnState()
00169 {
00170 HDITEM pItem = { HDI_WIDTH|HDI_ORDER };
00171
00172 CString strOrdering, strWidths, strItem;
00173
00174 for ( int nColumns = 0 ; m_wndHeader.GetItem( nColumns, &pItem ) ; nColumns++ )
00175 {
00176 m_wndHeader.GetItem( nColumns, &pItem );
00177
00178 strItem.Format( _T("%.2x"), pItem.iOrder );
00179 strOrdering += strItem;
00180
00181 strItem.Format( _T("%.4x"), pItem.cxy );
00182 strWidths += strItem;
00183 }
00184
00185 theApp.WriteProfileString( _T("ListStates"), _T("CUploadCtrl.Ordering"), strOrdering );
00186 theApp.WriteProfileString( _T("ListStates"), _T("CUploadCtrl.Widths"), strWidths );
00187 }
00188
00189 BOOL CUploadsCtrl::LoadColumnState()
00190 {
00191 CString strOrdering, strWidths, strItem;
00192
00193 strOrdering = theApp.GetProfileString( _T("ListStates"), _T("CUploadCtrl.Ordering"), _T("") );
00194 strWidths = theApp.GetProfileString( _T("ListStates"), _T("CUploadCtrl.Widths"), _T("") );
00195
00196 HDITEM pItem = { HDI_WIDTH|HDI_ORDER };
00197
00198 if ( _tcsncmp( strWidths, _T("0000"), 4 ) == 0 &&
00199 _tcsncmp( strOrdering, _T("00"), 2 ) == 0 )
00200 {
00201 strWidths = strWidths.Mid( 4 );
00202 strOrdering = strOrdering.Mid( 2 );
00203 }
00204
00205 for ( int nColumns = 0 ; m_wndHeader.GetItem( nColumns, &pItem ) ; nColumns++ )
00206 {
00207 if ( strWidths.GetLength() < 4 || strOrdering.GetLength() < 2 ) return FALSE;
00208
00209 _stscanf( strWidths.Left( 4 ), _T("%x"), &pItem.cxy );
00210 _stscanf( strOrdering.Left( 2 ), _T("%x"), &pItem.iOrder );
00211
00212 strWidths = strWidths.Mid( 4 );
00213 strOrdering = strOrdering.Mid( 2 );
00214
00215 m_wndHeader.SetItem( nColumns, &pItem );
00216 }
00217
00218 return TRUE;
00219 }
00220
00222
00223
00224 void CUploadsCtrl::SelectTo(int nIndex)
00225 {
00226 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00227
00228 BOOL bShift = GetAsyncKeyState( VK_SHIFT ) & 0x8000;
00229 BOOL bControl = GetAsyncKeyState( VK_CONTROL ) & 0x8000;
00230 BOOL bRight = GetAsyncKeyState( VK_RBUTTON ) & 0x8000;
00231
00232 if ( ! bShift && ! bControl && ! bRight && m_pDeselect == NULL ) DeselectAll();
00233
00234 Update();
00235
00236 INT nMin, nMax;
00237 GetScrollRange( SB_VERT, &nMin, &nMax );
00238 nIndex = max( 0, min( nIndex, nMax - 1 ) );
00239
00240 CUploadFile* pFile;
00241 CUploadQueue* pQueue;
00242
00243 if ( bShift )
00244 {
00245 if ( m_nFocus < nIndex )
00246 {
00247 for ( m_nFocus ++ ; m_nFocus <= nIndex ; m_nFocus ++ )
00248 {
00249 GetAt( m_nFocus, &pQueue, &pFile );
00250 if ( pQueue != NULL ) pQueue->m_bSelected = TRUE;
00251 if ( pFile != NULL ) pFile->m_bSelected = TRUE;
00252 }
00253 }
00254 else if ( m_nFocus > nIndex )
00255 {
00256 for ( m_nFocus -- ; m_nFocus >= nIndex ; m_nFocus -- )
00257 {
00258 GetAt( m_nFocus, &pQueue, &pFile );
00259 if ( pQueue != NULL ) pQueue->m_bSelected = TRUE;
00260 if ( pFile != NULL ) pFile->m_bSelected = TRUE;
00261 }
00262 }
00263
00264 m_nFocus = nIndex;
00265 }
00266 else
00267 {
00268 m_nFocus = nIndex;
00269 GetAt( m_nFocus, &pQueue, &pFile );
00270
00271 if ( bControl )
00272 {
00273 if ( pQueue != NULL ) pQueue->m_bSelected = ! pQueue->m_bSelected;
00274 if ( pFile != NULL ) pFile->m_bSelected = ! pFile->m_bSelected;
00275 }
00276 else
00277 {
00278 if ( pQueue != NULL ) pQueue->m_bSelected = TRUE;
00279 if ( pFile != NULL ) pFile->m_bSelected = TRUE;
00280 }
00281 }
00282
00283 CRect rcClient;
00284 GetClientRect( &rcClient );
00285
00286 int nScroll = GetScrollPos( SB_VERT );
00287 int nHeight = ( rcClient.bottom - HEADER_HEIGHT ) / ITEM_HEIGHT - 1;
00288 nHeight = max( 0, nHeight );
00289
00290 if ( m_nFocus < nScroll )
00291 {
00292 SetScrollPos( SB_VERT, m_nFocus );
00293 Update();
00294 }
00295 else if ( m_nFocus > nScroll + nHeight )
00296 {
00297 SetScrollPos( SB_VERT, max( 0, m_nFocus - nHeight ) );
00298 Update();
00299 }
00300 else
00301 {
00302 Invalidate();
00303 }
00304 }
00305
00306 void CUploadsCtrl::DeselectAll(CUploadFile* pExcept)
00307 {
00308 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00309 POSITION pos;
00310
00311 UploadQueues.m_pTorrentQueue->m_bSelected = FALSE;
00312 UploadQueues.m_pHistoryQueue->m_bSelected = FALSE;
00313
00314 for ( pos = UploadQueues.GetIterator() ; pos ; )
00315 {
00316 CUploadQueue* pQueue = UploadQueues.GetNext( pos );
00317 pQueue->m_bSelected = FALSE;
00318 }
00319
00320 for ( pos = UploadFiles.GetIterator() ; pos ; )
00321 {
00322 CUploadFile* pFile = UploadFiles.GetNext( pos );
00323 pFile->m_bSelected = FALSE;
00324 }
00325
00326 Invalidate();
00327 }
00328
00329 BOOL CUploadsCtrl::HitTest(const CPoint& point, CUploadQueue** ppQueue, CUploadFile** ppFile, int* pnIndex, RECT* prcItem)
00330 {
00331 CRect rcClient, rcItem;
00332
00333 GetClientRect( &rcClient );
00334 rcClient.top += HEADER_HEIGHT;
00335
00336 rcItem.CopyRect( &rcClient );
00337 rcItem.left -= GetScrollPos( SB_HORZ );
00338 rcItem.bottom = rcItem.top + ITEM_HEIGHT;
00339
00340 int nScroll = GetScrollPos( SB_VERT );
00341 int nIndex = 0;
00342
00343 if ( ppQueue != NULL ) *ppQueue = NULL;
00344 if ( ppFile != NULL ) *ppFile = NULL;
00345
00346 for ( POSITION posQueue = GetQueueIterator() ; posQueue && rcItem.top < rcClient.bottom ; )
00347 {
00348 CUploadQueue* pQueue = GetNextQueue( posQueue );
00349
00350 POSITION posFile = GetFileIterator( pQueue );
00351 if ( posFile == NULL ) continue;
00352
00353 if ( nScroll > 0 )
00354 {
00355 nScroll --;
00356 }
00357 else
00358 {
00359 if ( rcItem.PtInRect( point ) )
00360 {
00361 if ( ppQueue != NULL ) *ppQueue = pQueue;
00362 if ( pnIndex != NULL ) *pnIndex = nIndex;
00363 if ( prcItem != NULL ) *prcItem = rcItem;
00364 return TRUE;
00365 }
00366 rcItem.OffsetRect( 0, ITEM_HEIGHT );
00367 }
00368
00369 nIndex ++;
00370 if ( ! pQueue->m_bExpanded ) continue;
00371
00372 while ( posFile && rcItem.top < rcClient.bottom )
00373 {
00374 CUploadFile* pFile = GetNextFile( pQueue, posFile );
00375 if ( pFile == NULL ) continue;
00376
00377 if ( nScroll > 0 )
00378 {
00379 nScroll --;
00380 }
00381 else
00382 {
00383 if ( rcItem.PtInRect( point ) )
00384 {
00385 if ( ppFile != NULL ) *ppFile = pFile;
00386 if ( pnIndex != NULL ) *pnIndex = nIndex;
00387 if ( prcItem != NULL ) *prcItem = rcItem;
00388 return TRUE;
00389 }
00390 rcItem.OffsetRect( 0, ITEM_HEIGHT );
00391 }
00392
00393 nIndex ++;
00394 }
00395 }
00396
00397 return FALSE;
00398 }
00399
00400 BOOL CUploadsCtrl::GetAt(int nSelect, CUploadQueue** ppQueue, CUploadFile** ppFile)
00401 {
00402 int nScroll = GetScrollPos( SB_VERT );
00403 int nIndex = 0;
00404
00405 if ( ppQueue != NULL ) *ppQueue = NULL;
00406 if ( ppFile != NULL ) *ppFile = NULL;
00407
00408 for ( POSITION posQueue = GetQueueIterator() ; posQueue ; )
00409 {
00410 CUploadQueue* pQueue = GetNextQueue( posQueue );
00411
00412 POSITION posFile = GetFileIterator( pQueue );
00413 if ( posFile == NULL ) continue;
00414
00415 if ( nIndex++ == nSelect )
00416 {
00417 if ( ppQueue != NULL ) *ppQueue = pQueue;
00418 return TRUE;
00419 }
00420
00421 if ( ! pQueue->m_bExpanded ) continue;
00422
00423 while ( posFile )
00424 {
00425 CUploadFile* pFile = GetNextFile( pQueue, posFile );
00426 if ( pFile == NULL ) continue;
00427
00428 if ( nIndex++ == nSelect )
00429 {
00430 if ( ppFile != NULL ) *ppFile = pFile;
00431 return TRUE;
00432 }
00433 }
00434 }
00435
00436 return FALSE;
00437 }
00438
00440
00441
00442 POSITION CUploadsCtrl::GetQueueIterator()
00443 {
00444 if ( Settings.Uploads.FilterMask & ULF_TORRENT )
00445 {
00446 return (POSITION)UploadQueues.m_pTorrentQueue;
00447 }
00448 else if ( Settings.Uploads.FilterMask & ( ULF_ACTIVE | ULF_QUEUED ) )
00449 {
00450 return UploadQueues.GetIterator();
00451 }
00452 else if ( Settings.Uploads.FilterMask & ULF_HISTORY )
00453 {
00454 return (POSITION)UploadQueues.m_pHistoryQueue;
00455 }
00456 else
00457 {
00458 return NULL;
00459 }
00460 }
00461
00462 CUploadQueue* CUploadsCtrl::GetNextQueue(POSITION& pos)
00463 {
00464 ASSERT( pos != NULL );
00465
00466 if ( pos == (POSITION)UploadQueues.m_pTorrentQueue )
00467 {
00468 if ( Settings.Uploads.FilterMask & ( ULF_ACTIVE | ULF_QUEUED ) )
00469 {
00470 pos = UploadQueues.GetIterator();
00471 if ( pos == NULL ) pos = (POSITION)UploadQueues.m_pHistoryQueue;
00472 }
00473 else if ( Settings.Uploads.FilterMask & ULF_HISTORY )
00474 {
00475 pos = (POSITION)UploadQueues.m_pHistoryQueue;
00476 }
00477 else
00478 {
00479 pos = NULL;
00480 }
00481
00482 return UploadQueues.m_pTorrentQueue;
00483 }
00484 else if ( pos == (POSITION)UploadQueues.m_pHistoryQueue )
00485 {
00486 pos = NULL;
00487 return UploadQueues.m_pHistoryQueue;
00488 }
00489 else
00490 {
00491 CUploadQueue* pQueue = UploadQueues.GetNext( pos );
00492
00493 if ( pos == NULL )
00494 {
00495 if ( Settings.Uploads.FilterMask & ULF_HISTORY )
00496 {
00497 pos = (POSITION)UploadQueues.m_pHistoryQueue;
00498 }
00499 }
00500
00501 return pQueue;
00502 }
00503 }
00504
00505 POSITION CUploadsCtrl::GetFileIterator(CUploadQueue* pQueue)
00506 {
00507 if ( pQueue == UploadQueues.m_pTorrentQueue )
00508 {
00509 for ( POSITION posNext = UploadFiles.GetIterator() ; posNext ; )
00510 {
00511 POSITION posThis = posNext;
00512 CUploadFile* pFile = UploadFiles.GetNext( posNext );
00513 CUploadTransfer* pTransfer = pFile->GetActive();
00514 if ( pTransfer == NULL || pTransfer->m_nState == upsNull ) continue;
00515 if ( pTransfer->m_nProtocol != PROTOCOL_BT ) continue;
00516 return posThis;
00517 }
00518
00519 return NULL;
00520 }
00521 else if ( pQueue == UploadQueues.m_pHistoryQueue )
00522 {
00523 for ( POSITION posNext = UploadFiles.GetIterator() ; posNext ; )
00524 {
00525 POSITION posThis = posNext;
00526 CUploadFile* pFile = UploadFiles.GetNext( posNext );
00527 CUploadTransfer* pTransfer = pFile->GetActive();
00528 if ( pTransfer != NULL )
00529 {
00530 if ( pTransfer->m_nProtocol == PROTOCOL_BT && pTransfer->m_nState != upsNull ) continue;
00531 if ( pTransfer->m_pQueue != NULL ) continue;
00532 }
00533 return posThis;
00534 }
00535
00536 return NULL;
00537 }
00538 else
00539 {
00540 if ( Settings.Uploads.FilterMask & ULF_ACTIVE )
00541 {
00542 if ( pQueue->m_pActive.GetCount() > 0 )
00543 {
00544 return pQueue->m_pActive.GetHeadPosition();
00545 }
00546 }
00547
00548 if ( Settings.Uploads.FilterMask & ULF_QUEUED )
00549 {
00550 if ( pQueue->m_pQueued.GetCount() > 0 )
00551 {
00552 return (POSITION)1;
00553 }
00554 }
00555
00556 return NULL;
00557 }
00558 }
00559
00560 CUploadFile* CUploadsCtrl::GetNextFile(CUploadQueue* pQueue, POSITION& pos, int* pnPosition)
00561 {
00562 ASSERT( pos != NULL );
00563
00564 if ( pnPosition != NULL ) *pnPosition = -1;
00565
00566 if ( pQueue == UploadQueues.m_pTorrentQueue )
00567 {
00568 CUploadFile* pReturn = UploadFiles.GetNext( pos );
00569
00570 for ( ; pos ; )
00571 {
00572 POSITION posThis = pos;
00573 CUploadFile* pFile = UploadFiles.GetNext( pos );
00574 CUploadTransfer* pTransfer = pFile->GetActive();
00575 if ( pTransfer == NULL || pTransfer->m_nState == upsNull ) continue;
00576 if ( pTransfer->m_nProtocol != PROTOCOL_BT ) continue;
00577 pos = posThis;
00578 break;
00579 }
00580
00581 return pReturn;
00582 }
00583 else if ( pQueue == UploadQueues.m_pHistoryQueue )
00584 {
00585 CUploadFile* pReturn = UploadFiles.GetNext( pos );
00586
00587 for ( ; pos ; )
00588 {
00589 POSITION posThis = pos;
00590 CUploadFile* pFile = UploadFiles.GetNext( pos );
00591 CUploadTransfer* pTransfer = pFile->GetActive();
00592 if ( pTransfer != NULL )
00593 {
00594
00595 if ( pTransfer->m_nState != upsNull ) continue;
00596 if ( pTransfer->m_pQueue != NULL ) continue;
00597 }
00598 pos = posThis;
00599 break;
00600 }
00601
00602 return pReturn;
00603 }
00604 else if ( (int)pos > pQueue->m_pQueued.GetSize() )
00605 {
00606 CUploadTransfer* pTransfer = (CUploadTransfer*)pQueue->m_pActive.GetNext( pos );
00607
00608 if ( pos == NULL )
00609 {
00610 if ( Settings.Uploads.FilterMask & ULF_QUEUED )
00611 {
00612 if ( pQueue->m_pQueued.GetCount() > 0 )
00613 {
00614 pos = (POSITION)1;
00615 }
00616 }
00617 }
00618
00619 if ( pnPosition != NULL ) *pnPosition = 0;
00620 return pTransfer->m_pBaseFile;
00621 }
00622 else
00623 {
00624 CUploadTransfer* pTransfer = (CUploadTransfer*)pQueue->m_pQueued.GetAt( (int)pos - 1 );
00625 if ( pnPosition != NULL ) *pnPosition = (int)pos;
00626 pos = (POSITION)( (int)pos + 1 );
00627 if ( (int)pos > pQueue->m_pQueued.GetSize() ) pos = NULL;
00628 return pTransfer->m_pBaseFile;
00629 }
00630 }
00631
00633
00634
00635 void CUploadsCtrl::OnSize(UINT nType, int cx, int cy)
00636 {
00637 int nWidth = 0, nHeight = 0;
00638 CRect rcClient;
00639 HDITEM pColumn;
00640
00641 if ( nType != 1982 ) CWnd::OnSize( nType, cx, cy );
00642
00643 GetClientRect( &rcClient );
00644
00645 ZeroMemory( &pColumn, sizeof(pColumn) );
00646 pColumn.mask = HDI_WIDTH;
00647
00648 for ( int nColumn = 0 ; m_wndHeader.GetItem( nColumn, &pColumn ) ; nColumn ++ )
00649 nWidth += pColumn.cxy;
00650
00651 SCROLLINFO pScroll;
00652 ZeroMemory( &pScroll, sizeof(pScroll) );
00653 pScroll.cbSize = sizeof(pScroll);
00654 pScroll.fMask = SIF_RANGE|SIF_PAGE;
00655 pScroll.nMin = 0;
00656 pScroll.nMax = nWidth;
00657 pScroll.nPage = rcClient.right;
00658 SetScrollInfo( SB_HORZ, &pScroll, TRUE );
00659
00660 int nScroll = GetScrollPos( SB_HORZ );
00661 m_wndHeader.SetWindowPos( NULL, -nScroll, 0, rcClient.right + nScroll, HEADER_HEIGHT, SWP_SHOWWINDOW );
00662
00663 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00664
00665 for ( POSITION posQueue = GetQueueIterator() ; posQueue ; )
00666 {
00667 CUploadQueue* pQueue = GetNextQueue( posQueue );
00668
00669 POSITION posFile = GetFileIterator( pQueue );
00670
00671 if ( posFile == NULL )
00672 {
00673 pQueue->m_bSelected = FALSE;
00674 continue;
00675 }
00676
00677 nHeight ++;
00678
00679 if ( ! pQueue->m_bExpanded ) continue;
00680
00681 while ( posFile )
00682 {
00683 if ( GetNextFile( pQueue, posFile ) ) nHeight ++;
00684 }
00685 }
00686
00687 pLock.Unlock();
00688
00689 ZeroMemory( &pScroll, sizeof(pScroll) );
00690 pScroll.cbSize = sizeof(pScroll);
00691 pScroll.fMask = SIF_RANGE|SIF_PAGE;
00692 pScroll.nMin = 0;
00693 pScroll.nMax = nHeight;
00694 pScroll.nPage = ( rcClient.bottom - HEADER_HEIGHT ) / ITEM_HEIGHT + 1;
00695 SetScrollInfo( SB_VERT, &pScroll, TRUE );
00696
00697 m_nFocus = min( m_nFocus, max( 0, nHeight - 1 ) );
00698
00699 Invalidate();
00700 }
00701
00703
00704
00705 void CUploadsCtrl::OnPaint()
00706 {
00707 CSingleLock pLock( &Transfers.m_pSection, TRUE );
00708 CRect rcClient, rcItem;
00709 CPaintDC dc( this );
00710 if ( theApp.m_bRTL ) dc.SetTextAlign( TA_RTLREADING );
00711
00712 GetClientRect( &rcClient );
00713 rcClient.top += HEADER_HEIGHT;
00714
00715 rcItem.CopyRect( &rcClient );
00716 rcItem.left -= GetScrollPos( SB_HORZ );
00717 rcItem.bottom = rcItem.top + ITEM_HEIGHT;
00718
00719 int nScroll = GetScrollPos( SB_VERT );
00720 int nIndex = 0;
00721
00722 CFont* pfOld = (CFont*)dc.SelectObject( &theApp.m_gdiFont );
00723 BOOL bFocus = ( GetFocus() == this );
00724
00725 for ( POSITION posQueue = GetQueueIterator() ; posQueue && rcItem.top < rcClient.bottom ; )
00726 {
00727 CUploadQueue* pQueue = GetNextQueue( posQueue );
00728
00729 POSITION posFile = GetFileIterator( pQueue );
00730 if ( posFile == NULL ) continue;
00731
00732 if ( nScroll > 0 )
00733 {
00734 nScroll --;
00735 }
00736 else
00737 {
00738 PaintQueue( dc, rcItem, pQueue, bFocus && ( m_nFocus == nIndex ) );
00739 rcItem.OffsetRect( 0, ITEM_HEIGHT );
00740 }
00741
00742 nIndex ++;
00743
00744 if ( ! pQueue->m_bExpanded ) continue;
00745
00746 while ( posFile && rcItem.top < rcClient.bottom && rcItem.top < rcClient.bottom )
00747 {
00748 int nPosition;
00749 CUploadFile* pFile = GetNextFile( pQueue, posFile, &nPosition );
00750 if ( pFile == NULL ) continue;
00751
00752 if ( nScroll > 0 )
00753 {
00754 nScroll --;
00755 }
00756 else
00757 {
00758 PaintFile( dc, rcItem, pQueue, pFile, nPosition, bFocus && ( m_nFocus == nIndex ) );
00759 rcItem.OffsetRect( 0, ITEM_HEIGHT );
00760 }
00761
00762 nIndex ++;
00763 }
00764 }
00765
00766 dc.SelectObject( pfOld );
00767
00768 rcClient.top = rcItem.top;
00769 if ( rcClient.top < rcClient.bottom )
00770 dc.FillSolidRect( &rcClient, CoolInterface.m_crWindow );
00771 }
00772
00773 void CUploadsCtrl::PaintQueue(CDC& dc, const CRect& rcRow, CUploadQueue* pQueue, BOOL bFocus)
00774 {
00775 COLORREF crNatural = CoolInterface.m_crWindow;
00776 COLORREF crBack = pQueue->m_bSelected ? CoolInterface.m_crBackSel : crNatural;
00777
00778 dc.SetBkColor( crBack );
00779 dc.SetBkMode( OPAQUE );
00780
00781 if ( pQueue->m_bSelected )
00782 dc.SetTextColor( CoolInterface.m_crText );
00783 else
00784 dc.SetTextColor( CoolInterface.m_crText );
00785
00786 int nTextLeft = rcRow.right, nTextRight = rcRow.left;
00787 HDITEM pColumn;
00788
00789 ZeroMemory( &pColumn, sizeof(pColumn) );
00790 pColumn.mask = HDI_FORMAT | HDI_LPARAM;
00791
00792 dc.SelectObject( &theApp.m_gdiFontBold );
00793
00794 for ( int nColumn = 0 ; m_wndHeader.GetItem( nColumn, &pColumn ) ; nColumn++ )
00795 {
00796 CString strText;
00797 CRect rcCell;
00798
00799 m_wndHeader.GetItemRect( nColumn, &rcCell );
00800 rcCell.left += rcRow.left;
00801 rcCell.right += rcRow.left;
00802 rcCell.top = rcRow.top;
00803 rcCell.bottom = rcRow.bottom;
00804
00805 switch ( pColumn.lParam )
00806 {
00807 case UPLOAD_COLUMN_TITLE:
00808 dc.FillSolidRect( rcCell.left, rcCell.bottom - 1, 32, 1, crNatural );
00809 ImageList_DrawEx( ShellIcons.GetHandle( 16 ), pQueue->m_bExpanded ? SHI_MINUS : SHI_PLUS, dc.GetSafeHdc(),
00810 rcCell.left, rcCell.top, 16, 16, crNatural, CLR_DEFAULT, ILD_NORMAL );
00811 rcCell.left += 16;
00812 if ( pQueue == UploadQueues.m_pTorrentQueue )
00813 {
00814 ImageList_DrawEx( m_pProtocols, PROTOCOL_BT, dc.GetSafeHdc(),
00815 rcCell.left, rcCell.top, 16, 16, crNatural, CLR_DEFAULT, pQueue->m_bSelected ? ILD_SELECTED : ILD_NORMAL );
00816 }
00817 else if ( pQueue->m_nProtocols == ( 1 << PROTOCOL_HTTP ) )
00818 {
00819 ImageList_DrawEx( m_pProtocols, PROTOCOL_HTTP, dc.GetSafeHdc(),
00820 rcCell.left, rcCell.top, 16, 16, crNatural, CLR_DEFAULT, pQueue->m_bSelected ? ILD_SELECTED : ILD_NORMAL );
00821 }
00822 else if ( pQueue->m_nProtocols == ( 1 << PROTOCOL_ED2K ) )
00823 {
00824 ImageList_DrawEx( m_pProtocols, PROTOCOL_ED2K, dc.GetSafeHdc(),
00825 rcCell.left, rcCell.top, 16, 16, crNatural, CLR_DEFAULT, pQueue->m_bSelected ? ILD_SELECTED : ILD_NORMAL );
00826 }
00827 else
00828 {
00829 ImageList_DrawEx( ShellIcons.GetHandle( 16 ), pQueue->m_bExpanded ? SHI_FOLDER_OPEN : SHI_FOLDER_CLOSED, dc.GetSafeHdc(),
00830 rcCell.left, rcCell.top, 16, 16, crNatural, CLR_DEFAULT, pQueue->m_bSelected ? ILD_SELECTED : ILD_NORMAL );
00831 }
00832 rcCell.left += 16;
00833 dc.FillSolidRect( rcCell.left, rcCell.top, 1, rcCell.Height(), crNatural );
00834 rcCell.left += 1;
00835
00836 strText = pQueue->m_sName;
00837 break;
00838
00839 case UPLOAD_COLUMN_SIZE:
00840 if ( pQueue == UploadQueues.m_pTorrentQueue )
00841 strText.Format( _T("%i/%i"), pQueue->m_nMinTransfers, pQueue->m_nMaxTransfers );
00842 else if ( pQueue != UploadQueues.m_pHistoryQueue )
00843 strText.Format( _T("%i/%i"), pQueue->GetTransferCount(), pQueue->GetQueuedCount() );
00844 break;
00845
00846 case UPLOAD_COLUMN_SPEED:
00847 if ( pQueue != UploadQueues.m_pHistoryQueue )
00848 strText = Settings.SmartVolume( pQueue->GetMeasuredSpeed() * 8, FALSE, TRUE );
00849 break;
00850 }
00851
00852 nTextLeft = min( nTextLeft, int(rcCell.left) );
00853 nTextRight = max( nTextRight, int(rcCell.right) );
00854
00855 if ( rcCell.Width() < 8 ) strText.Empty();
00856
00857 if ( dc.GetTextExtent( strText ).cx > rcCell.Width() - 8 )
00858 {
00859 while ( dc.GetTextExtent( strText + _T('\x2026') ).cx > ( rcCell.Width() - 8 ) && strText.GetLength() > 0 )
00860 {
00861 strText.Truncate( strText.GetLength() - 1 );
00862 }
00863
00864 if ( strText.GetLength() > 0 ) strText += _T('\x2026');
00865 }
00866
00867 int nWidth = dc.GetTextExtent( strText ).cx;
00868 int nPosition = 0;
00869
00870 switch ( pColumn.fmt & LVCFMT_JUSTIFYMASK )
00871 {
00872 default:
00873 nPosition = ( rcCell.left + 4 );
00874 break;
00875 case LVCFMT_CENTER:
00876 nPosition = ( ( rcCell.left + rcCell.right ) / 2 ) - ( nWidth / 2 );
00877 break;
00878 case LVCFMT_RIGHT:
00879 nPosition = ( rcCell.right - 4 - nWidth );
00880 break;
00881 }
00882
00883 dc.SetBkColor( crBack );
00884 dc.ExtTextOut( nPosition, rcCell.top + 2, ETO_CLIPPED|ETO_OPAQUE,
00885 &rcCell, strText, NULL );
00886 }
00887
00888 if ( nTextRight < rcRow.right )
00889 {
00890 CRect rcBlank( nTextRight, rcRow.top, rcRow.right, rcRow.bottom );
00891 dc.FillSolidRect( &rcBlank, crBack );
00892 }
00893
00894 dc.SelectObject( &theApp.m_gdiFont );
00895
00896 if ( bFocus )
00897 {
00898 CRect rcFocus( nTextLeft, rcRow.top, max( int(rcRow.right), nTextRight ), rcRow.bottom );
00899 dc.Draw3dRect( &rcFocus, CoolInterface.m_crBorder, CoolInterface.m_crBorder );
00900 }
00901 }
00902
00903 void CUploadsCtrl::PaintFile(CDC& dc, const CRect& rcRow, CUploadQueue* pQueue, CUploadFile* pFile, int nPosition, BOOL bFocus)
00904 {
00905 CUploadTransfer* pTransfer = pFile->GetActive();
00906
00907 COLORREF crNatural = CoolInterface.m_crWindow;
00908 COLORREF crBack = pFile->m_bSelected ? CoolInterface.m_crBackSel : crNatural;
00909
00910 dc.SetBkColor( crBack );
00911 dc.SetBkMode( OPAQUE );
00912
00913 if ( pFile->m_bSelected )
00914 dc.SetTextColor( CoolInterface.m_crText );
00915 else if ( pTransfer == NULL || pTransfer->m_nState == upsNull )
00916 dc.SetTextColor( CoolInterface.m_crDisabled );
00917 else
00918 dc.SetTextColor( CoolInterface.m_crText );
00919
00920 int nTextLeft = rcRow.right, nTextRight = rcRow.left;
00921 HDITEM pColumn;
00922
00923 ZeroMemory( &pColumn, sizeof(pColumn) );
00924 pColumn.mask = HDI_FORMAT | HDI_LPARAM;
00925
00926 for ( int nColumn = 0 ; m_wndHeader.GetItem( nColumn, &pColumn ) ; nColumn++ )
00927 {
00928 CString strText;
00929 CRect rcCell;
00930
00931 m_wndHeader.GetItemRect( nColumn, &rcCell );
00932 rcCell.left += rcRow.left;
00933 rcCell.right += rcRow.left;
00934 rcCell.top = rcRow.top;
00935 rcCell.bottom = rcRow.bottom;
00936
00937 switch ( pColumn.lParam )
00938 {
00939 case UPLOAD_COLUMN_TITLE:
00940 dc.FillSolidRect( rcCell.left, rcCell.top, 24, rcCell.Height(), crNatural );
00941 rcCell.left += 24;
00942 dc.FillSolidRect( rcCell.left, rcCell.bottom - 1, 16, 1, crNatural );
00943 ImageList_DrawEx( ShellIcons.GetHandle( 16 ), ShellIcons.Get( pFile->m_sName, 16 ), dc.GetSafeHdc(),
00944 rcCell.left, rcCell.top, 16, 16, crNatural, CLR_DEFAULT, pFile->m_bSelected ? ILD_SELECTED : ILD_NORMAL );
00945 rcCell.left += 16;
00946 dc.FillSolidRect( rcCell.left, rcCell.top, 1, rcCell.Height(), crNatural );
00947 rcCell.left += 1;
00948 strText = pFile->m_sName;
00949 break;
00950
00951 case UPLOAD_COLUMN_USER:
00952 if ( pTransfer == NULL )
00953 strText.Empty();
00954 else if ( pTransfer->m_sNick.IsEmpty() )
00955 strText = pTransfer->m_sAddress;
00956 else
00957 strText = pTransfer->m_sNick + _T(" (") + pTransfer->m_sAddress + _T(")");
00958 break;
00959
00960 case UPLOAD_COLUMN_SIZE:
00961 strText = Settings.SmartVolume( pFile->m_nSize, FALSE );
00962 break;
00963
00964 case UPLOAD_COLUMN_PROGRESS:
00965 dc.Draw3dRect( &rcCell, crBack, crBack );
00966 rcCell.DeflateRect( 1, 1 );
00967 dc.Draw3dRect( &rcCell, crBack, crBack );
00968 rcCell.DeflateRect( 0, 1 );
00969 dc.Draw3dRect( &rcCell, RGB( 50, 50, 50 ), RGB( 50, 50, 50 ) );
00970 rcCell.DeflateRect( 1, 1 );
00971 CFragmentBar::DrawUpload( &dc, &rcCell, pFile, crNatural );
00972 break;
00973
00974 case UPLOAD_COLUMN_SPEED:
00975 if ( pTransfer == NULL || pTransfer->m_nState == upsNull )
00976 LoadString( strText, IDS_STATUS_COMPLETED );
00977 else if ( pTransfer->m_nProtocol == PROTOCOL_BT )
00978 {
00979 CUploadTransferBT* pBT = (CUploadTransferBT*)pTransfer;
00980
00981 if ( ! pBT->m_bInterested )
00982 LoadString( strText, IDS_STATUS_UNINTERESTED );
00983 else if ( pBT->m_bChoked )
00984 LoadString( strText, IDS_STATUS_CHOKED );
00985 else if ( DWORD nSpeed = pTransfer->GetMeasuredSpeed() * 8 )
00986 strText = Settings.SmartVolume( nSpeed, FALSE, TRUE );
00987 }
00988 else if ( nPosition > 0 )
00989 {
00990 CString strQ;
00991 LoadString( strQ, IDS_STATUS_Q );
00992 strText.Format( _T("%s %i"), strQ, nPosition );
00993 }
00994 else if ( DWORD nSpeed = pTransfer->GetMeasuredSpeed() * 8 )
00995 strText = Settings.SmartVolume( nSpeed, FALSE, TRUE );
00996 else
00997 LoadString( strText, IDS_STATUS_NEXT );
00998 break;
00999
01000 case UPLOAD_COLUMN_CLIENT:
01001 if ( pTransfer != NULL ) strText = pTransfer->m_sUserAgent;
01002 break;
01003 case UPLOAD_COLUMN_RATING:
01004 strText.Format(_T("%d"), pTransfer->m_nUserRating );
01005 break;
01006 }
01007
01008 nTextLeft = min( nTextLeft, int(rcCell.left) );
01009 nTextRight = max( nTextRight, int(rcCell.right) );
01010
01011 if ( pColumn.lParam == UPLOAD_COLUMN_PROGRESS ) continue;
01012
01013 if ( rcCell.Width() < 8 ) strText.Empty();
01014
01015 if ( dc.GetTextExtent( strText ).cx > rcCell.Width() - 8 )
01016 {
01017 while ( dc.GetTextExtent( strText + _T('\x2026') ).cx > ( rcCell.Width() - 8 ) && strText.GetLength() > 0 )
01018 {
01019 strText.Truncate( strText.GetLength() - 1 );
01020 }
01021
01022 if ( strText.GetLength() > 0 ) strText += _T('\x2026');
01023 }
01024
01025 int nWidth = dc.GetTextExtent( strText ).cx;
01026 int nPosition = 0;
01027
01028 switch ( pColumn.fmt & LVCFMT_JUSTIFYMASK )
01029 {
01030 default:
01031 nPosition = ( rcCell.left + 4 );
01032 break;
01033 case LVCFMT_CENTER:
01034 nPosition = ( ( rcCell.left + rcCell.right ) / 2 ) - ( nWidth / 2 );
01035 break;
01036 case LVCFMT_RIGHT:
01037 nPosition = ( rcCell.right - 4 - nWidth );
01038 break;
01039 }
01040
01041 dc.SetBkColor( crBack );
01042 dc.ExtTextOut( nPosition, rcCell.top + 2, ETO_CLIPPED|ETO_OPAQUE,
01043 &rcCell, strText, NULL );
01044 }
01045
01046 if ( nTextRight < rcRow.right )
01047 {
01048 CRect rcBlank( nTextRight, rcRow.top, rcRow.right, rcRow.bottom );
01049 dc.FillSolidRect( &rcBlank, crBack );
01050 }
01051
01052 if ( bFocus )
01053 {
01054 CRect rcFocus( nTextLeft, rcRow.top, max( int(rcRow.right), nTextRight ), rcRow.bottom );
01055 dc.Draw3dRect( &rcFocus, CoolInterface.m_crBorder, CoolInterface.m_crBorder );
01056 }
01057 }
01058
01060
01061
01062 void CUploadsCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
01063 {
01064 SCROLLINFO pInfo;
01065
01066 pInfo.cbSize = sizeof(pInfo);
01067 pInfo.fMask = SIF_ALL & ~SIF_TRACKPOS;
01068
01069 GetScrollInfo( SB_VERT, &pInfo );
01070 int nDelta = pInfo.nPos;
01071
01072 switch ( nSBCode )
01073 {
01074 case SB_BOTTOM:
01075 pInfo.nPos = pInfo.nMax - pInfo.nPage;
01076 break;
01077 case SB_LINEDOWN:
01078 pInfo.nPos ++;
01079 break;
01080 case SB_LINEUP:
01081 pInfo.nPos --;
01082 break;
01083 case SB_PAGEDOWN:
01084 pInfo.nPos += pInfo.nPage;
01085 break;
01086 case SB_PAGEUP:
01087 pInfo.nPos -= pInfo.nPage;
01088 break;
01089 case SB_THUMBPOSITION:
01090 case SB_THUMBTRACK:
01091 pInfo.nPos = nPos;
01092 break;
01093 case SB_TOP:
01094 pInfo.nPos = 0;
01095 break;
01096 }
01097
01098 pInfo.nPos = max( 0, min( pInfo.nPos, pInfo.nMax - (int)pInfo.nPage + 1 ) );
01099 if ( pInfo.nPos == nDelta ) return;
01100
01101 SetScrollInfo( SB_VERT, &pInfo, TRUE );
01102 Invalidate();
01103 }
01104
01105 void CUploadsCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
01106 {
01107 SCROLLINFO pInfo;
01108
01109 pInfo.cbSize = sizeof(pInfo);
01110 pInfo.fMask = SIF_ALL & ~SIF_TRACKPOS;
01111
01112 GetScrollInfo( SB_HORZ, &pInfo );
01113 int nDelta = pInfo.nPos;
01114
01115 switch ( nSBCode )
01116 {
01117 case SB_BOTTOM:
01118 pInfo.nPos = pInfo.nMax - pInfo.nPage;
01119 break;
01120 case SB_LINEDOWN:
01121 pInfo.nPos ++;
01122 break;
01123 case SB_LINEUP:
01124 pInfo.nPos --;
01125 break;
01126 case SB_PAGEDOWN:
01127 pInfo.nPos += pInfo.nPage;
01128 break;
01129 case SB_PAGEUP:
01130 pInfo.nPos -= pInfo.nPage;
01131 break;
01132 case SB_THUMBPOSITION:
01133 case SB_THUMBTRACK:
01134 pInfo.nPos = nPos;
01135 break;
01136 case SB_TOP:
01137 pInfo.nPos = 0;
01138 break;
01139 }
01140
01141 pInfo.nPos = max( 0, min( pInfo.nPos, pInfo.nMax - (int)pInfo.nPage + 1 ) );
01142 if ( pInfo.nPos == nDelta ) return;
01143
01144 SetScrollInfo( SB_HORZ, &pInfo, TRUE );
01145
01146 CRect rcClient;
01147 GetClientRect( &rcClient );
01148
01149 m_wndHeader.SetWindowPos( NULL, -pInfo.nPos, 0,
01150 rcClient.right + pInfo.nPos, HEADER_HEIGHT, SWP_NOZORDER );
01151
01152 RedrawWindow( NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW );
01153 }
01154
01155 BOOL CUploadsCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
01156 {
01157 OnVScroll( SB_THUMBPOSITION, (int)( GetScrollPos( SB_VERT ) - zDelta / WHEEL_DELTA * m_nScrollWheelLines ), NULL );
01158 return TRUE;
01159 }
01160
01161 void CUploadsCtrl::OnChangeHeader(NMHDR* pNotifyStruct, LRESULT* pResult)
01162 {
01163 Update();
01164 }
01165
01166 void CUploadsCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
01167 {
01168 CSingleLock pLock( &Transfers.m_pSection, TRUE );
01169 CUploadFile* pFile;
01170 CUploadQueue* pQueue;
01171
01172 m_wndTip.Hide();
01173
01174 switch ( nChar )
01175 {
01176 case VK_HOME:
01177 SelectTo( 0 );
01178 return;
01179 case VK_END:
01180 {
01181 INT nMin, nMax;
01182 GetScrollRange( SB_VERT, &nMin, &nMax );
01183 SelectTo( max( 0, nMax - 1 ) );
01184 }
01185 return;
01186 case VK_UP:
01187 SelectTo( m_nFocus - 1 );
01188 return;
01189 case VK_DOWN:
01190 SelectTo( m_nFocus + 1 );
01191 return;
01192 case VK_PRIOR:
01193 SelectTo( m_nFocus - 10 );
01194 return;
01195 case VK_NEXT:
01196 SelectTo( m_nFocus + 10 );
01197 return;
01198 case VK_LEFT:
01199 case '-':
01200 if ( GetAt( m_nFocus, &pQueue, &pFile ) )
01201 {
01202 if ( pFile != NULL && pFile->GetActive() != NULL )
01203 pQueue = pFile->GetActive()->m_pQueue;
01204 if ( pQueue != NULL && pQueue->m_bExpanded == TRUE )
01205 {
01206 pQueue->m_bExpanded = FALSE;
01207 Update();
01208 }
01209 }
01210 return;
01211 case VK_RIGHT:
01212 case '+':
01213 if ( GetAt( m_nFocus, &pQueue, NULL ) && pQueue != NULL && pQueue->m_bExpanded == FALSE )
01214 {
01215 pQueue->m_bExpanded = TRUE;
01216 Update();
01217 }
01218 return;
01219 }
01220
01221 CWnd::OnKeyDown( nChar, nRepCnt, nFlags );
01222 }
01223
01224 void CUploadsCtrl::OnLButtonDown(UINT nFlags, CPoint point)
01225 {
01226 CSingleLock pLock( &Transfers.m_pSection, TRUE );
01227 CUploadFile* pFile;
01228 CUploadQueue* pQueue;
01229 CRect rcItem;
01230 int nIndex;
01231
01232 SetFocus();
01233 m_wndTip.Hide();
01234
01235 if ( HitTest( point, &pQueue, &pFile, &nIndex, &rcItem ) )
01236 {
01237 int nTitleStarts = GetExpandableColumnX();
01238 if ( point.x > nTitleStarts && point.x <= nTitleStarts + rcItem.left + 16 )
01239 {
01240 if ( pQueue != NULL )
01241 {
01242 pQueue->m_bExpanded = ! pQueue->m_bExpanded;
01243
01244 if ( ! pQueue->m_bExpanded )
01245 {
01246 for ( POSITION posActive = pQueue->m_pActive.GetHeadPosition() ; posActive ; )
01247 {
01248 CUploadTransfer* pTransfer = (CUploadTransfer*)pQueue->m_pActive.GetNext( posActive );
01249 if ( pTransfer->m_pBaseFile != NULL ) pTransfer->m_pBaseFile->m_bSelected = FALSE;
01250 }
01251
01252 for ( int nPos = 0 ; nPos < pQueue->m_pQueued.GetSize() ; nPos ++ )
01253 {
01254 CUploadTransfer* pTransfer = (CUploadTransfer*)pQueue->m_pQueued.GetAt( nPos );
01255 if ( pTransfer->m_pBaseFile != NULL ) pTransfer->m_pBaseFile->m_bSelected = FALSE;
01256 }
01257 }
01258
01259 Update();
01260 }
01261 }
01262 else
01263 {
01264 if ( pFile != NULL && pFile->m_bSelected )
01265 {
01266 if ( ( nFlags & ( MK_SHIFT | MK_CONTROL | MK_RBUTTON ) ) == 0 )
01267 {
01268 m_pDeselect = pFile;
01269 }
01270 }
01271 else if ( nFlags & MK_RBUTTON )
01272 {
01273 DeselectAll();
01274 }
01275
01276 SelectTo( nIndex );
01277 }
01278 }
01279 else if ( ( nFlags & ( MK_SHIFT | MK_CONTROL ) ) == 0 )
01280 {
01281 DeselectAll();
01282 Update();
01283 }
01284 }
01285
01286 void CUploadsCtrl::OnRButtonDown(UINT nFlags, CPoint point)
01287 {
01288 m_wndTip.Hide();
01289 OnLButtonDown( nFlags, point );
01290 CWnd::OnRButtonDown( nFlags, point );
01291 }
01292
01293 void CUploadsCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
01294 {
01295 CSingleLock pLock( &Transfers.m_pSection, TRUE );
01296 CUploadFile* pFile;
01297 CUploadQueue* pQueue;
01298 CRect rcItem;
01299
01300 SetFocus();
01301
01302 if ( HitTest( point, &pQueue, &pFile, NULL, &rcItem ) )
01303 {
01304 int nTitleStarts = GetExpandableColumnX();
01305 if ( pQueue != NULL && point.x > nTitleStarts && point.x <= nTitleStarts + rcItem.left + 16 )
01306 {
01307 pQueue->m_bExpanded = ! pQueue->m_bExpanded;
01308
01309 if ( ! pQueue->m_bExpanded )
01310 {
01311 for ( POSITION posActive = pQueue->m_pActive.GetHeadPosition() ; posActive ; )
01312 {
01313 CUploadTransfer* pTransfer = (CUploadTransfer*)pQueue->m_pActive.GetNext( posActive );
01314 if ( pTransfer->m_pBaseFile != NULL ) pTransfer->m_pBaseFile->m_bSelected = FALSE;
01315 }
01316
01317 for ( int nPos = 0 ; nPos < pQueue->m_pQueued.GetSize() ; nPos ++ )
01318 {
01319 CUploadTransfer* pTransfer = (CUploadTransfer*)pQueue->m_pQueued.GetAt( nPos );
01320 if ( pTransfer->m_pBaseFile != NULL ) pTransfer->m_pBaseFile->m_bSelected = FALSE;
01321 }
01322 }
01323
01324 Update();
01325 }
01326 else if ( pQueue != NULL )
01327 {
01328 GetOwner()->PostMessage( WM_TIMER, 5 );
01329
01330 }
01331 else if ( pFile != NULL )
01332 {
01333 GetOwner()->PostMessage( WM_TIMER, 5 );
01334 GetOwner()->PostMessage( WM_COMMAND, ID_UPLOADS_LAUNCH );
01335 }
01336 }
01337
01338 CWnd::OnLButtonDblClk( nFlags, point );
01339 }
01340
01341 void CUploadsCtrl::OnMouseMove(UINT nFlags, CPoint point)
01342 {
01343 CWnd::OnMouseMove( nFlags, point );
01344
01345 if ( ( nFlags & ( MK_LBUTTON|MK_RBUTTON) ) == 0 )
01346 {
01347 CUploadFile* pFile;
01348 CRect rcItem;
01349
01350 if ( HitTest( point, NULL, &pFile, NULL, &rcItem ) )
01351 {
01352 if ( pFile != NULL )
01353 {
01354 m_wndTip.Show( pFile );
01355 return;
01356 }
01357 }
01358 }
01359
01360 m_wndTip.Hide();
01361 }
01362
01363 void CUploadsCtrl::OnLButtonUp(UINT nFlags, CPoint point)
01364 {
01365 if ( m_pDeselect != NULL )
01366 {
01367 DeselectAll( m_pDeselect );
01368 m_pDeselect = NULL;
01369 }
01370
01371 CWnd::OnLButtonUp( nFlags, point );
01372 }
01373
01374 void CUploadsCtrl::OnRButtonUp(UINT nFlags, CPoint point)
01375 {
01376 if ( m_pDeselect != NULL )
01377 {
01378 DeselectAll( m_pDeselect );
01379 m_pDeselect = NULL;
01380 }
01381
01382 CWnd::OnRButtonUp( nFlags, point );
01383 }
01384
01385 void CUploadsCtrl::OnSetFocus(CWnd* pOldWnd)
01386 {
01387 CWnd::OnSetFocus( pOldWnd );
01388 Invalidate();
01389 }
01390
01391 void CUploadsCtrl::OnKillFocus(CWnd* pNewWnd)
01392 {
01393 CWnd::OnKillFocus( pNewWnd );
01394 Invalidate();
01395 }
01396
01397 int CUploadsCtrl::GetExpandableColumnX() const
01398 {
01399 HDITEM pColumn;
01400 int nTitleStarts = 0;
01401
01402 ZeroMemory( &pColumn, sizeof(pColumn) );
01403 pColumn.mask = HDI_LPARAM | HDI_WIDTH;
01404
01405 for ( int nColumn = 0 ; m_wndHeader.GetItem( m_wndHeader.OrderToIndex( nColumn ), &pColumn ) ; nColumn++ )
01406 {
01407 if ( pColumn.lParam == UPLOAD_COLUMN_TITLE ) break;
01408 else nTitleStarts += pColumn.cxy;
01409 }
01410 return nTitleStarts;
01411 }