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

CtrlDownloads.cpp

Go to the documentation of this file.
00001 //
00002 // CtrlDownloads.cpp
00003 //
00004 //      Date:                   "$Date: 2005/10/03 20:44:33 $"
00005 //      Revision:               "$Revision: 1.39 $"
00006 //  Last change by:     "$Author: spooky23 $"
00007 //
00008 // Copyright (c) Shareaza Development Team, 2002-2005.
00009 // This file is part of SHAREAZA (www.shareaza.com)
00010 //
00011 // Shareaza is free software; you can redistribute it
00012 // and/or modify it under the terms of the GNU General Public License
00013 // as published by the Free Software Foundation; either version 2 of
00014 // the License, or (at your option) any later version.
00015 //
00016 // Shareaza is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU General Public License
00022 // along with Shareaza; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 // CDownloadsCtrl construction
00082 
00083 CDownloadsCtrl::CDownloadsCtrl()
00084 {
00085         // Try to get the number of lines to scroll when the mouse wheel is rotated
00086         if( !SystemParametersInfo ( SPI_GETWHEELSCROLLLINES, 0, &m_nScrollWheelLines, 0) )
00087         {
00088                 m_nScrollWheelLines = 3;
00089         }
00090 }
00091 
00092 CDownloadsCtrl::~CDownloadsCtrl()
00093 {
00094 }
00095 
00097 // CDownloadsCtrl operations
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 // CDownloadsCtrl system message handlers
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 // CDownloadsCtrl column helpers
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 // CDownloadsCtrl item helpers
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                 // If a download is selected, select all downloads
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                 // If a source is selected, select all sources for that download
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         // If nothing is selected, select all downloads
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 // CDownloadsCtrl presentation message handlers
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 // CDownloadsCtrl painting
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                 // There are reviews but no ratings- give it an "average" rating
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                         // Add rating overlay
00971                         switch ( nRating )
00972                         {
00973                         case 0:         // No reviews or no reviews with ratings
00974                                 break;
00975                         case 1:         // Ratings suggest fake file
00976                                 nIconStyle |= INDEXTOOVERLAYMASK( SHI_O_RATING_FAKE );
00977                                 break;
00978                         case 2: 
00979                         case 3: 
00980                         case 4: // Ratings suggest average file
00981                                 nIconStyle |= INDEXTOOVERLAYMASK( SHI_O_RATING_AVERAGE );
00982                                 break;
00983                         default:        // Ratings suggest good file
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 // CDownloadsCtrl interaction message handlers
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         //for (j=DOWNLOAD_COLUMN_TITLE; j <= DOWNLOAD_COLUMN_PERCENTAGE; j++)
01491         //      m_pbSortAscending[j]=FALSE;
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 );    // Add the current file to playlist
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:                 // If the enter key is pressed activate the function relevant to the current focus
01686                 OnEnterKey();           // Run the function that does the actions on the download window when enter key is pressed
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 );                                                                // Get the data for the current focus
01699                 if ( pDownload != NULL )                                                                                                // If the selected object is a download...
01700                 {
01701                         if ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 )                                            // And the control key is pressed...
01702                         {
01703                                 GetOwner()->PostMessage( WM_TIMER, 5 );
01704                                 GetOwner()->PostMessage( WM_COMMAND, ID_DOWNLOADS_LAUNCH );             // Launch the current file
01705                         }
01706                 }
01707                 else if ( pSource != NULL )                                                                                             // If the selected object is a download source...
01708                 {
01709                         GetOwner()->PostMessage( WM_TIMER, 5 );
01710                         GetOwner()->PostMessage( WM_COMMAND, ID_TRANSFERS_CONNECT );            // Connect to the source
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 }

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