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

CtrlLibraryTree.cpp

Go to the documentation of this file.
00001 //
00002 // CtrlLibraryTree.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "CoolInterface.h"
00026 #include "ShellIcons.h"
00027 #include "Library.h"
00028 #include "LibraryFolders.h"
00029 #include "CtrlLibraryTree.h"
00030 #include "CtrlLibraryFrame.h"
00031 #include "CtrlCoolTip.h"
00032 #include "SharedFolder.h"
00033 #include "AlbumFolder.h"
00034 #include "Schema.h"
00035 
00036 #ifdef _DEBUG
00037 #define new DEBUG_NEW
00038 #undef THIS_FILE
00039 static char THIS_FILE[] = __FILE__;
00040 #endif
00041 
00042 IMPLEMENT_DYNAMIC(CLibraryTreeCtrl, CWnd)
00043 
00044 BEGIN_MESSAGE_MAP(CLibraryTreeCtrl, CWnd)
00045         //{{AFX_MSG_MAP(CLibraryTreeCtrl)
00046         ON_WM_SIZE()
00047         ON_WM_VSCROLL()
00048         ON_WM_ERASEBKGND()
00049         ON_WM_PAINT()
00050         ON_WM_LBUTTONDOWN()
00051         ON_WM_LBUTTONDBLCLK()
00052         ON_WM_MOUSEWHEEL()
00053         ON_WM_KEYDOWN()
00054         ON_WM_RBUTTONDOWN()
00055         ON_WM_MOUSEMOVE()
00056         ON_WM_LBUTTONUP()
00057         //}}AFX_MSG_MAP
00058 END_MESSAGE_MAP()
00059 
00060 #define ITEM_HEIGHT     16
00061 
00062 
00064 // CLibraryTreeCtrl construction
00065 
00066 CLibraryTreeCtrl::CLibraryTreeCtrl()
00067 {
00068         m_pRoot = new CLibraryTreeItem();
00069         m_pRoot->m_bExpanded = TRUE;
00070 
00071         m_nTotal                = 0;
00072         m_nVisible              = 0;
00073         m_nScroll               = 0;
00074         m_nSelected             = 0;
00075         m_pSelFirst             = NULL;
00076         m_pSelLast              = NULL;
00077         m_pFocus                = NULL;
00078         m_bDrag                 = FALSE;
00079         m_pDropItem             = NULL;
00080         m_nCleanCookie  = 0;
00081         m_pTip                  = NULL;
00082 }
00083 
00084 CLibraryTreeCtrl::~CLibraryTreeCtrl()
00085 {
00086         delete m_pRoot;
00087 }
00088 
00090 // CLibraryTreeCtrl operations
00091 
00092 BOOL CLibraryTreeCtrl::Create(CWnd* pParentWnd)
00093 {
00094         CRect rect;
00095         return CWnd::Create( NULL, _T("CLibraryTreeCtrl"),
00096                 WS_CHILD|WS_VISIBLE|WS_TABSTOP|WS_VSCROLL, rect, pParentWnd, IDC_LIBRARY_TREE, NULL );
00097 }
00098 
00099 void CLibraryTreeCtrl::SetToolTip(CCoolTipCtrl* pTip)
00100 {
00101         if ( m_pTip ) m_pTip->Hide();
00102         m_pTip = pTip;
00103         if ( m_pTip ) m_pTip->SetOwner( this );
00104 }
00105 
00106 void CLibraryTreeCtrl::Clear()
00107 {
00108         if ( m_pRoot->m_nCount == 0 ) return;
00109 
00110         m_pRoot->Clear();
00111 
00112         m_nTotal                = 0;
00113         m_nSelected             = 0;
00114         m_pSelFirst             = NULL;
00115         m_pSelLast              = NULL;
00116         m_pFocus                = NULL;
00117         m_pDropItem             = NULL;
00118 
00119         if ( m_pTip ) m_pTip->Hide();
00120 
00121         // NotifySelection(); NOT NOTIFIED
00122         UpdateScroll();
00123         Invalidate();
00124 }
00125 
00127 // CLibraryTreeCtrl expand
00128 
00129 BOOL CLibraryTreeCtrl::Expand(CLibraryTreeItem* pItem, TRISTATE bExpand, BOOL bInvalidate)
00130 {
00131         if ( pItem == NULL ) return FALSE;
00132 
00133         switch ( bExpand )
00134         {
00135         case TS_UNKNOWN:
00136                 pItem->m_bExpanded = ! pItem->m_bExpanded;
00137                 break;
00138         case TS_TRUE:
00139                 if ( pItem->m_bExpanded ) return FALSE;
00140                 pItem->m_bExpanded = TRUE;
00141                 break;
00142         case TS_FALSE:
00143                 if ( ! pItem->m_bExpanded ) return FALSE;
00144                 pItem->m_bExpanded = FALSE;
00145                 break;
00146         }
00147 
00148         if ( pItem->m_pPhysical )
00149         {
00150                 pItem->m_pPhysical->m_bExpanded = pItem->m_bExpanded;
00151         }
00152         else
00153         {
00154                 pItem->m_pVirtual->m_bExpanded = pItem->m_bExpanded;
00155         }
00156 
00157         if ( ! pItem->IsVisible() ) return FALSE;
00158 
00159         if ( pItem->m_bExpanded )
00160         {
00161                 m_nTotal += pItem->GetChildCount();
00162         }
00163         else
00164         {
00165                 m_nTotal -= pItem->GetChildCount();
00166                 DeselectAll( NULL, pItem, FALSE );
00167         }
00168 
00169         pItem->m_bContract1 = pItem->m_bExpanded == TRUE && bExpand == TS_TRUE && bInvalidate == FALSE;
00170 
00171         if ( pItem->m_bContract1 == FALSE )
00172         {
00173                 for ( CLibraryTreeItem* pParent = pItem ; pParent != NULL ; pParent = pParent->m_pParent )
00174                         pParent->m_bContract1 = FALSE;
00175         }
00176 
00177         if ( bInvalidate )
00178         {
00179                 UpdateScroll();
00180                 Invalidate();
00181         }
00182 
00183         return TRUE;
00184 }
00185 
00186 BOOL CLibraryTreeCtrl::CollapseRecursive(CLibraryTreeItem* pItem)
00187 {
00188         BOOL bChanged = FALSE;
00189 
00190         if ( pItem != m_pRoot && pItem->m_bExpanded && pItem->m_bContract1 )
00191         {
00192                 bChanged |= Expand( pItem, TS_FALSE, FALSE );
00193         }
00194 
00195         CLibraryTreeItem** pChild = pItem->m_pList;
00196 
00197         for ( int nCount = pItem->m_nCount ; nCount ; nCount--, pChild++ )
00198         {
00199                 bChanged |= CollapseRecursive( *pChild );
00200         }
00201 
00202         return bChanged;
00203 }
00204 
00206 // CLibraryTreeCtrl selection
00207 
00208 BOOL CLibraryTreeCtrl::Select(CLibraryTreeItem* pItem, TRISTATE bSelect, BOOL bInvalidate)
00209 {
00210         if ( pItem == NULL ) return FALSE;
00211 
00212         switch ( bSelect )
00213         {
00214         case TS_UNKNOWN:
00215                 pItem->m_bSelected = ! pItem->m_bSelected;
00216                 break;
00217         case TS_TRUE:
00218                 if ( pItem->m_bSelected ) return FALSE;
00219                 pItem->m_bSelected = TRUE;
00220                 break;
00221         case TS_FALSE:
00222                 if ( ! pItem->m_bSelected ) return FALSE;
00223                 pItem->m_bSelected = FALSE;
00224                 break;
00225         }
00226 
00227         if ( pItem->m_bSelected )
00228         {
00229                 m_nSelected++;
00230 
00231                 if ( m_pSelLast )
00232                 {
00233                         m_pSelLast->m_pSelNext = pItem;
00234                         pItem->m_pSelPrev = m_pSelLast;
00235                         pItem->m_pSelNext = NULL;
00236                         m_pSelLast = pItem;
00237                 }
00238                 else
00239                 {
00240                         m_pSelFirst = m_pSelLast = pItem;
00241                         pItem->m_pSelPrev = pItem->m_pSelNext = NULL;
00242                 }
00243         }
00244         else
00245         {
00246                 m_nSelected--;
00247 
00248                 if ( pItem->m_pSelPrev )
00249                         pItem->m_pSelPrev->m_pSelNext = pItem->m_pSelNext;
00250                 else
00251                         m_pSelFirst = pItem->m_pSelNext;
00252 
00253                 if ( pItem->m_pSelNext )
00254                         pItem->m_pSelNext = pItem->m_pSelNext->m_pSelPrev = pItem->m_pSelPrev;
00255                 else
00256                         m_pSelLast = pItem->m_pSelPrev;
00257         }
00258 
00259         if ( pItem->IsVisible() )
00260         {
00261                 if ( bInvalidate ) Invalidate();
00262                 return TRUE;
00263         }
00264         else
00265         {
00266                 return FALSE;
00267         }
00268 }
00269 
00270 BOOL CLibraryTreeCtrl::SelectAll(CLibraryTreeItem* pParent, BOOL bInvalidate)
00271 {
00272         if ( pParent == NULL ) pParent = m_pRoot;
00273         else if ( pParent->m_bExpanded == FALSE ) return FALSE;
00274 
00275         CLibraryTreeItem** pChild = pParent->m_pList;
00276         BOOL bChanged = FALSE;
00277 
00278         for ( int nCount = pParent->m_nCount ; nCount ; nCount--, pChild++ )
00279         {
00280                 if ( (*pChild)->m_bSelected == FALSE )
00281                 {
00282                         Select( *pChild, TS_TRUE, FALSE );
00283                         bChanged = TRUE;
00284                 }
00285 
00286                 if ( (*pChild)->m_bExpanded && (*pChild)->m_nCount )
00287                 {
00288                         bChanged |= SelectAll( *pChild, FALSE );
00289                 }
00290         }
00291 
00292         if ( bInvalidate && bChanged && pParent == m_pRoot ) Invalidate();
00293 
00294         return bChanged;
00295 }
00296 
00297 BOOL CLibraryTreeCtrl::DeselectAll(CLibraryTreeItem* pExcept, CLibraryTreeItem* pParent, BOOL bInvalidate)
00298 {
00299         if ( pParent == NULL ) pParent = m_pRoot;
00300 
00301         CLibraryTreeItem** pChild = pParent->m_pList;
00302         BOOL bChanged = FALSE;
00303 
00304         for ( int nCount = pParent->m_nCount ; nCount ; nCount--, pChild++ )
00305         {
00306                 if ( *pChild != pExcept && (*pChild)->m_bSelected )
00307                 {
00308                         Select( *pChild, TS_FALSE, FALSE );
00309                         bChanged = TRUE;
00310                 }
00311 
00312                 if ( (*pChild)->m_nCount ) bChanged |= DeselectAll( pExcept, *pChild, FALSE );
00313         }
00314 
00315         if ( bInvalidate && bChanged && pParent == m_pRoot ) Invalidate();
00316 
00317         return bChanged;
00318 }
00319 
00320 int CLibraryTreeCtrl::GetSelectedCount() const
00321 {
00322         return m_nSelected;
00323 }
00324 
00325 CLibraryTreeItem* CLibraryTreeCtrl::GetFirstSelected() const
00326 {
00327         return m_pSelFirst;
00328 }
00329 
00330 CLibraryTreeItem* CLibraryTreeCtrl::GetLastSelected() const
00331 {
00332         return m_pSelLast;
00333 }
00334 
00335 BOOL CLibraryTreeCtrl::Highlight(CLibraryTreeItem* pItem)
00336 {
00337         m_pFocus = pItem;
00338 
00339         for ( CLibraryTreeItem* pParent = m_pFocus->m_pParent ; pParent ; pParent = pParent->m_pParent )
00340         {
00341                 Expand( pParent, TS_TRUE, FALSE );
00342 
00343                 pParent->m_bContract2 = pParent->m_bContract1;
00344                 pParent->m_bContract1 = FALSE;
00345         }
00346 
00347         CollapseRecursive( m_pRoot );
00348 
00349         for ( CLibraryTreeItem* pParent = m_pFocus->m_pParent ; pParent ; pParent = pParent->m_pParent )
00350         {
00351                 pParent->m_bContract1 = pParent->m_bContract2;
00352         }
00353 
00354         CRect rcItem, rcClient;
00355 
00356         if ( GetRect( m_pFocus, &rcItem ) )
00357         {
00358                 GetClientRect( &rcClient );
00359 
00360                 if ( rcItem.top <= rcClient.top )
00361                         ScrollBy( rcItem.top - rcClient.top );
00362                 else if ( rcItem.bottom > rcClient.bottom )
00363                         ScrollBy( rcItem.bottom - rcClient.bottom );
00364         }
00365 
00366         UpdateScroll();
00367         Invalidate();
00368 
00369         return TRUE;
00370 }
00371 
00373 // CLibraryTreeCtrl internal helpers
00374 
00375 BOOL CLibraryTreeCtrl::CleanItems(CLibraryTreeItem* pItem, DWORD nCookie, BOOL bVisible)
00376 {
00377         CLibraryTreeItem** pChild = pItem->m_pList + pItem->m_nCount - 1;
00378         BOOL bChanged = FALSE;
00379 
00380         for ( int nChild = pItem->m_nCount ; nChild ; nChild--, pChild-- )
00381         {
00382                 if ( (*pChild)->m_nCleanCookie != nCookie )
00383                 {
00384                         if ( m_pFocus == *pChild ) m_pFocus = NULL;
00385 
00386                         if ( (*pChild)->m_bSelected ) Select( *pChild, TS_FALSE, FALSE );
00387                         bChanged |= DeselectAll( NULL, *pChild, FALSE );
00388 
00389                         if ( bVisible )
00390                         {
00391                                 m_nTotal -= (*pChild)->GetChildCount() + 1;
00392                                 bChanged = TRUE;
00393                         }
00394 
00395                         delete *pChild;
00396                         MoveMemory( pChild, pChild + 1, 4 * ( pItem->m_nCount - nChild ) );
00397                         pItem->m_nCount--;
00398                 }
00399         }
00400 
00401         return bChanged;
00402 }
00403 
00404 void CLibraryTreeCtrl::NotifySelection()
00405 {
00406         if (!m_hWnd) return;
00407         NMHDR pNM = { GetSafeHwnd(), GetDlgCtrlID(), LTN_SELCHANGED };
00408         GetOwner()->SendMessage( WM_NOTIFY, pNM.idFrom, (LPARAM)&pNM );
00409 }
00410 
00412 // CLibraryTreeCtrl search
00413 
00414 CLibraryTreeItem* CLibraryTreeCtrl::GetFolderItem(LPVOID pSearch, CLibraryTreeItem* pParent)
00415 {
00416         if ( pParent == NULL ) pParent = m_pRoot;
00417 
00418         CLibraryTreeItem** pChild = pParent->m_pList;
00419 
00420         for ( int nChild = pParent->m_nCount ; nChild ; nChild--, pChild++ )
00421         {
00422                 if ( pSearch == (*pChild)->m_pPhysical ) return *pChild;
00423                 if ( pSearch == (*pChild)->m_pVirtual  ) return *pChild;
00424 
00425                 if ( (*pChild)->m_nCount )
00426                 {
00427                         CLibraryTreeItem* pFound = GetFolderItem( pSearch, *pChild );
00428                         if ( pFound ) return pFound;
00429                 }
00430         }
00431 
00432         return NULL;
00433 }
00434 
00436 // CLibraryTreeCtrl message handlers
00437 
00438 void CLibraryTreeCtrl::OnSize(UINT nType, int cx, int cy)
00439 {
00440         CWnd::OnSize( nType, cx, cy );
00441 
00442         m_nVisible = cy;
00443 
00444         UpdateScroll();
00445 }
00446 
00447 void CLibraryTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point)
00448 {
00449         CRect rc;
00450         CLibraryTreeItem* pHit = HitTest( point, &rc );
00451         BOOL bChanged = FALSE;
00452 
00453         SetFocus();
00454 
00455         if ( m_pTip ) m_pTip->Hide();
00456 
00457         if ( pHit && pHit->m_nCount && point.x >= rc.left && point.x < rc.left + 16 )
00458         {
00459                 bChanged = Expand( pHit, TS_UNKNOWN );
00460         }
00461         else if ( nFlags & MK_CONTROL )
00462         {
00463                 if ( pHit ) bChanged = Select( pHit, TS_UNKNOWN );
00464         }
00465         else if ( nFlags & MK_SHIFT )
00466         {
00467                 if ( pHit ) bChanged = Select( pHit );
00468         }
00469         else
00470         {
00471                 if ( ( nFlags & MK_RBUTTON ) == 0 || ( pHit && pHit->m_bSelected == FALSE ) )
00472                         bChanged = DeselectAll( pHit );
00473                 if ( pHit ) bChanged |= Select( pHit );
00474         }
00475 
00476         m_pFocus = pHit;
00477 
00478         if ( pHit != NULL )
00479         {
00480                 if ( m_pFocus->m_pVirtual && ( nFlags & MK_RBUTTON ) == 0 )
00481                 {
00482                         m_bDrag = TRUE;
00483                         m_ptDrag = point;
00484                         SetCapture();
00485                 }
00486         }
00487 
00488         if ( bChanged ) NotifySelection();
00489 }
00490 
00491 void CLibraryTreeCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
00492 {
00493         OnLButtonDown( nFlags, point );
00494 
00495         if ( m_pFocus != NULL && m_pFocus->m_nCount )
00496         {
00497                 if ( Expand( m_pFocus, TS_UNKNOWN ) ) NotifySelection();
00498         }
00499 }
00500 
00501 void CLibraryTreeCtrl::OnRButtonDown(UINT nFlags, CPoint point)
00502 {
00503         OnLButtonDown( nFlags, point );
00504         CWnd::OnRButtonDown( nFlags, point );
00505 }
00506 
00507 void CLibraryTreeCtrl::OnMouseMove(UINT nFlags, CPoint point)
00508 {
00509         if ( m_bDrag & ( nFlags & MK_LBUTTON ) )
00510         {
00511                 CSize szDiff = point - m_ptDrag;
00512 
00513                 if ( abs( szDiff.cx ) > 5 || abs( szDiff.cy ) > 5 )
00514                 {
00515                         m_bDrag = FALSE;
00516                         StartDragging( point );
00517                 }
00518         }
00519         else if ( m_pTip != NULL )
00520         {
00521                 if ( CLibraryTreeItem* pItem = HitTest( point ) )
00522                 {
00523                         m_pTip->Show( pItem->m_pPhysical ? (LPVOID)pItem->m_pPhysical : (LPVOID)pItem->m_pVirtual );
00524                 }
00525                 else
00526                 {
00527                         m_pTip->Hide();
00528                 }
00529         }
00530 
00531         CWnd::OnMouseMove( nFlags, point );
00532 }
00533 
00534 void CLibraryTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point)
00535 {
00536         ReleaseCapture();
00537         m_bDrag = FALSE;
00538 
00539         CWnd::OnLButtonUp( nFlags, point );
00540 }
00541 
00542 void CLibraryTreeCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
00543 {
00544         CLibraryTreeItem* pTo = NULL;
00545         BOOL bChanged = FALSE;
00546         CRect rc;
00547 
00548         if ( m_pTip ) m_pTip->Hide();
00549 
00550         if ( nChar == VK_HOME || ( nChar == VK_UP && m_pFocus == NULL ) )
00551         {
00552                 if ( m_pRoot->m_nCount ) pTo = m_pRoot->m_pList[0];
00553         }
00554         else if ( nChar == VK_END || ( nChar == VK_DOWN && m_pFocus == NULL ) )
00555         {
00556                 if ( m_pRoot->m_nCount ) pTo = m_pRoot->m_pList[ m_pRoot->m_nCount - 1 ];
00557         }
00558         else if ( nChar == VK_UP && m_pFocus != NULL )
00559         {
00560                 if ( GetRect( m_pFocus, &rc ) )
00561                 {
00562                         CPoint pt( rc.left, ( rc.top + rc.bottom ) / 2 );
00563                         pt.y -= ITEM_HEIGHT;
00564                         pTo = HitTest( pt );
00565                 }
00566         }
00567         else if ( nChar == VK_DOWN && m_pFocus != NULL )
00568         {
00569                 if ( GetRect( m_pFocus, &rc ) )
00570                 {
00571                         CPoint pt( rc.left, ( rc.top + rc.bottom ) / 2 );
00572                         pt.y += ITEM_HEIGHT;
00573                         pTo = HitTest( pt );
00574                 }
00575         }
00576         else if ( ( nChar == VK_LEFT || nChar == VK_SUBTRACT ) && m_pFocus != NULL )
00577         {
00578                 while ( TRUE )
00579                 {
00580                         if ( m_pFocus->m_bExpanded && m_pFocus->m_nCount )
00581                         {
00582                                 Expand( m_pFocus, TS_FALSE );
00583                                 break;
00584                         }
00585 
00586                         if ( m_pFocus->m_pParent == m_pRoot ) break;
00587                         m_pFocus = m_pFocus->m_pParent;
00588 
00589                         bChanged |= DeselectAll( m_pFocus );
00590                         bChanged |= Select( m_pFocus );
00591                 }
00592 
00593                 Highlight( m_pFocus );
00594         }
00595         else if ( ( nChar == VK_RIGHT || nChar == VK_ADD ) && m_pFocus != NULL )
00596         {
00597                 if ( ! m_pFocus->m_bExpanded && m_pFocus->m_nCount )
00598                 {
00599                         bChanged |= Expand( m_pFocus, TS_TRUE );
00600                 }
00601         }
00602         else if ( _istalnum( nChar ) )
00603         {
00604                 CLibraryTreeItem* pStart        = m_pFocus;
00605                 CLibraryTreeItem* pBase         = pStart ? pStart->m_pParent : m_pRoot;
00606 
00607                 for ( int nLoop = 0 ; nLoop < 2 ; nLoop++ )
00608                 {
00609                         CLibraryTreeItem** pChild = pBase->m_pList;
00610 
00611                         for ( int nCount = pBase->m_nCount ; nCount ; nCount--, pChild++ )
00612                         {
00613                                 if ( pStart != NULL )
00614                                 {
00615                                         if ( pStart == *pChild ) pStart = NULL;
00616                                 }
00617                                 else if ( toupper( (*pChild)->m_sText.GetAt( 0 ) ) == (int)nChar )
00618                                 {
00619                                         DeselectAll( m_pFocus = *pChild, NULL, FALSE );
00620                                         Select( m_pFocus, TS_TRUE, FALSE );
00621                                         Highlight( m_pFocus );
00622                                         NotifySelection();
00623                                         return;
00624                                 }
00625                         }
00626                 }
00627         }
00628 
00629         if ( pTo != NULL )
00630         {
00631                 if ( ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) == 0 || m_pFocus == NULL )
00632                 {
00633                         bChanged |= DeselectAll( m_pFocus = pTo );
00634                         bChanged |= Select( m_pFocus );
00635                 }
00636                 else
00637                 {
00638                         bChanged |= Select( m_pFocus = pTo );
00639                 }
00640 
00641                 Highlight( m_pFocus );
00642         }
00643 
00644         if ( bChanged ) NotifySelection();
00645 }
00646 
00648 // CLibraryTreeCtrl scrolling
00649 
00650 void CLibraryTreeCtrl::UpdateScroll()
00651 {
00652         SCROLLINFO pInfo;
00653 
00654         pInfo.cbSize    = sizeof(pInfo);
00655         pInfo.fMask             = SIF_ALL & ~SIF_TRACKPOS;
00656         pInfo.nMin              = 0;
00657         pInfo.nMax              = m_nTotal * ITEM_HEIGHT;
00658         pInfo.nPage             = m_nVisible;
00659         pInfo.nPos              = m_nScroll = max( 0, min( m_nScroll, pInfo.nMax - (int)pInfo.nPage + 1 ) );
00660 
00661         SetScrollInfo( SB_VERT, &pInfo, TRUE );
00662 }
00663 
00664 void CLibraryTreeCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
00665 {
00666         switch ( nSBCode )
00667         {
00668         case SB_BOTTOM:
00669                 ScrollTo( 0xFFFFFFFF );
00670                 break;
00671         case SB_LINEDOWN:
00672                 ScrollBy( 16 );
00673                 break;
00674         case SB_LINEUP:
00675                 ScrollBy( -16 );
00676                 break;
00677         case SB_PAGEDOWN:
00678                 ScrollBy( m_nVisible );
00679                 break;
00680         case SB_PAGEUP:
00681                 ScrollBy( -m_nVisible );
00682                 break;
00683         case SB_THUMBPOSITION:
00684         case SB_THUMBTRACK:
00685                 ScrollTo( nPos );
00686                 break;
00687         case SB_TOP:
00688                 ScrollTo( 0 );
00689                 break;
00690         }
00691 }
00692 
00693 BOOL CLibraryTreeCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
00694 {
00695         ScrollBy( zDelta * 3 * -ITEM_HEIGHT / WHEEL_DELTA );
00696         return TRUE;
00697 }
00698 
00699 void CLibraryTreeCtrl::ScrollBy(int nDelta)
00700 {
00701         ScrollTo( max( 0, m_nScroll + nDelta ) );
00702 }
00703 
00704 void CLibraryTreeCtrl::ScrollTo(int nPosition)
00705 {
00706         if ( nPosition == m_nScroll ) return;
00707         m_nScroll = nPosition;
00708 
00709         UpdateScroll();
00710 
00711         CRect rc;
00712         GetClientRect( &rc );
00713         RedrawWindow( &rc, NULL, RDW_INVALIDATE );
00714 }
00715 
00717 // CLibraryTreeCtrl painting
00718 
00719 BOOL CLibraryTreeCtrl::OnEraseBkgnd(CDC* pDC)
00720 {
00721         return TRUE;
00722 }
00723 
00724 void CLibraryTreeCtrl::OnPaint()
00725 {
00726         CPaintDC dc( this );
00727 
00728         CRect rcClient;
00729         GetClientRect( &rcClient );
00730 
00731         CPoint pt( rcClient.left, rcClient.top - m_nScroll );
00732 
00733         CLibraryTreeItem** pChild = m_pRoot->m_pList;
00734 
00735         CFont* pOldFont = (CFont*)dc.SelectObject( &CoolInterface.m_fntNormal );
00736 
00737         for ( int nCount = m_pRoot->m_nCount ; nCount && pt.y < rcClient.bottom ; nCount--, pChild++ )
00738         {
00739                 Paint( dc, rcClient, pt, *pChild );
00740         }
00741 
00742         dc.SelectObject( pOldFont );
00743 
00744         dc.FillSolidRect( &rcClient, CoolInterface.m_crWindow );
00745 }
00746 
00747 void CLibraryTreeCtrl::Paint(CDC& dc, CRect& rcClient, CPoint& pt, CLibraryTreeItem* pItem)
00748 {
00749         CRect rc( pt.x, pt.y, pt.x, pt.y + ITEM_HEIGHT );
00750         pt.y += ITEM_HEIGHT;
00751 
00752         if ( rc.top >= rcClient.bottom )
00753         {
00754                 return;
00755         }
00756         else if ( rc.bottom >= rcClient.top )
00757         {
00758                 if ( pItem->m_bBold ) dc.SelectObject( &CoolInterface.m_fntBold );
00759 
00760                 rc.right += 32 + dc.GetTextExtent( pItem->m_sText ).cx + 6;
00761 
00762                 if ( dc.RectVisible( &rc ) )
00763                 {
00764                         pItem->Paint( dc, rc, m_pDropItem == pItem );
00765                         dc.ExcludeClipRect( &rc );
00766                 }
00767 
00768                 if ( pItem->m_bBold ) dc.SelectObject( &CoolInterface.m_fntNormal );
00769         }
00770 
00771         if ( pItem->m_bExpanded && pItem->m_nCount )
00772         {
00773                 pt.x += 16;
00774 
00775                 CLibraryTreeItem** pChild = pItem->m_pList;
00776 
00777                 for ( int nCount = pItem->m_nCount ; nCount ; nCount--, pChild++ )
00778                 {
00779                         Paint( dc, rcClient, pt, *pChild );
00780                         if ( pt.y >= rcClient.bottom ) break;
00781                 }
00782 
00783                 pt.x -= 16;
00784         }
00785 }
00786 
00788 // CLibraryTreeCtrl hit testing
00789 
00790 CLibraryTreeItem* CLibraryTreeCtrl::HitTest(const POINT& point, RECT* pRect) const
00791 {
00792         CRect rcClient;
00793         GetClientRect( &rcClient );
00794 
00795         CPoint pt( rcClient.left, rcClient.top - m_nScroll );
00796 
00797         CLibraryTreeItem** pChild = m_pRoot->m_pList;
00798 
00799         for ( int nCount = m_pRoot->m_nCount ; nCount && pt.y < rcClient.bottom ; nCount--, pChild++ )
00800         {
00801                 CLibraryTreeItem* pItem = HitTest( rcClient, pt, *pChild, point, pRect );
00802                 if ( pItem ) return pItem;
00803         }
00804 
00805         return NULL;
00806 }
00807 
00808 CLibraryTreeItem* CLibraryTreeCtrl::HitTest(CRect& rcClient, CPoint& pt, CLibraryTreeItem* pItem, const POINT& point, RECT* pRect) const
00809 {
00810         CRect rc( rcClient.left, pt.y, rcClient.right, pt.y + ITEM_HEIGHT );
00811         pt.y += ITEM_HEIGHT;
00812 
00813         if ( rc.top >= rcClient.bottom + ITEM_HEIGHT )
00814         {
00815                 return NULL;
00816         }
00817         else if ( rc.bottom >= rcClient.top - ITEM_HEIGHT )
00818         {
00819                 if ( rc.PtInRect( point ) )
00820                 {
00821                         if ( pRect )
00822                         {
00823                                 CopyMemory( pRect, &rc, sizeof(RECT) );
00824                                 pRect->left = pt.x;
00825                         }
00826                         return pItem;
00827                 }
00828         }
00829 
00830         if ( pItem->m_bExpanded && pItem->m_nCount )
00831         {
00832                 pt.x += 16;
00833 
00834                 CLibraryTreeItem** pChild = pItem->m_pList;
00835 
00836                 for ( int nCount = pItem->m_nCount ; nCount ; nCount--, pChild++ )
00837                 {
00838                         CLibraryTreeItem* pItem = HitTest( rcClient, pt, *pChild, point, pRect );
00839                         if ( pItem ) return pItem;
00840                         if ( pt.y >= rcClient.bottom + ITEM_HEIGHT ) break;
00841                 }
00842 
00843                 pt.x -= 16;
00844         }
00845 
00846         return NULL;
00847 }
00848 
00850 // CLibraryTreeCtrl rect lookup
00851 
00852 BOOL CLibraryTreeCtrl::GetRect(CLibraryTreeItem* pItem, RECT* pRect)
00853 {
00854         CRect rcClient;
00855         GetClientRect( &rcClient );
00856 
00857         CPoint pt( rcClient.left, rcClient.top - m_nScroll );
00858 
00859         CLibraryTreeItem** pChild = m_pRoot->m_pList;
00860 
00861         for ( int nCount = m_pRoot->m_nCount ; nCount ; nCount--, pChild++ )
00862         {
00863                 if ( GetRect( pt, *pChild, pItem, pRect ) ) return TRUE;
00864         }
00865 
00866         return FALSE;
00867 }
00868 
00869 BOOL CLibraryTreeCtrl::GetRect(CPoint& pt, CLibraryTreeItem* pItem, CLibraryTreeItem* pFind, RECT* pRect)
00870 {
00871         if ( pItem == pFind )
00872         {
00873                 pRect->left             = pt.x;
00874                 pRect->top              = pt.y;
00875                 pRect->right    = pt.x;
00876                 pRect->bottom   = pt.y = pRect->top + ITEM_HEIGHT;
00877 
00878                 CClientDC dc( this );
00879                 CFont* pOld = (CFont*)dc.SelectObject( pItem->m_bBold ?
00880                         &CoolInterface.m_fntBold : &CoolInterface.m_fntNormal );
00881                 pRect->right += 33 + dc.GetTextExtent( pItem->m_sText ).cx + 4;
00882                 dc.SelectObject( pOld );
00883 
00884                 return TRUE;
00885         }
00886         else
00887         {
00888                 pt.y += ITEM_HEIGHT;
00889         }
00890 
00891         if ( pItem->m_bExpanded && pItem->m_nCount )
00892         {
00893                 pt.x += 16;
00894 
00895                 CLibraryTreeItem** pChild = pItem->m_pList;
00896 
00897                 for ( int nCount = pItem->m_nCount ; nCount ; nCount--, pChild++ )
00898                 {
00899                         if ( GetRect( pt, *pChild, pFind, pRect ) ) return TRUE;
00900                 }
00901 
00902                 pt.x -= 16;
00903         }
00904 
00905         return FALSE;
00906 }
00907 
00909 // CLibraryTreeCtrl drag setup
00910 
00911 #define MAX_DRAG_SIZE   256
00912 #define MAX_DRAG_SIZE_2 128
00913 
00914 void CLibraryTreeCtrl::StartDragging(CPoint& ptMouse)
00915 {
00916         CImageList* pImage = CreateDragImage( ptMouse );
00917         if ( pImage == NULL ) return;
00918 
00919         ReleaseCapture();
00920         ClientToScreen( &ptMouse );
00921 
00922         CLibraryFrame* pFrame   = (CLibraryFrame*)GetOwner();
00923         CLibraryList* pList             = new CLibraryList( m_nSelected );
00924 
00925         for (   CLibraryTreeItem* pItem = m_pSelFirst ; pItem ;
00926                         pItem = pItem->m_pSelNext )
00927         {
00928                 if ( pItem->m_pVirtual ) pList->AddTail( (DWORD)pItem->m_pVirtual );
00929         }
00930 
00931         pFrame->DragObjects( pList, pImage, ptMouse );
00932 }
00933 
00934 CImageList* CLibraryTreeCtrl::CreateDragImage(const CPoint& ptMouse)
00935 {
00936         CRect rcClient, rcOne, rcAll( 32000, 32000, -32000, -32000 );
00937 
00938         GetClientRect( &rcClient );
00939 
00940         for (   CLibraryTreeItem* pItem = m_pSelFirst ; pItem ;
00941                         pItem = pItem->m_pSelNext )
00942         {
00943                 GetRect( pItem, &rcOne );
00944 
00945                 if ( rcOne.IntersectRect( &rcClient, &rcOne ) )
00946                 {
00947                         rcAll.left              = min( rcAll.left, rcOne.left );
00948                         rcAll.top               = min( rcAll.top, rcOne.top );
00949                         rcAll.right             = max( rcAll.right, rcOne.right );
00950                         rcAll.bottom    = max( rcAll.bottom, rcOne.bottom );
00951                 }
00952         }
00953 
00954         BOOL bClipped = rcAll.Height() > MAX_DRAG_SIZE;
00955 
00956         if ( bClipped )
00957         {
00958                 rcAll.left              = max( rcAll.left, ptMouse.x - MAX_DRAG_SIZE_2 );
00959                 rcAll.right             = max( rcAll.right, ptMouse.x + MAX_DRAG_SIZE_2 );
00960                 rcAll.top               = max( rcAll.top, ptMouse.y - MAX_DRAG_SIZE_2 );
00961                 rcAll.bottom    = max( rcAll.bottom, ptMouse.y + MAX_DRAG_SIZE_2 );
00962         }
00963 
00964         CClientDC dcClient( this );
00965         CDC dcMem, dcDrag;
00966         CBitmap bmDrag;
00967 
00968         if ( ! dcMem.CreateCompatibleDC( &dcClient ) )
00969                 return NULL;
00970         if ( ! dcDrag.CreateCompatibleDC( &dcClient ) )
00971                 return NULL;
00972         if ( ! bmDrag.CreateCompatibleBitmap( &dcClient, rcAll.Width(), rcAll.Height() ) )
00973                 return NULL;
00974 
00975         CBitmap *pOldDrag = dcDrag.SelectObject( &bmDrag );
00976 
00977         dcDrag.FillSolidRect( 0, 0, rcAll.Width(), rcAll.Height(), RGB( 250, 255, 250 ) );
00978 
00979         CRgn pRgn;
00980 
00981         if ( bClipped )
00982         {
00983                 CPoint ptMiddle( ptMouse.x - rcAll.left, ptMouse.y - rcAll.top );
00984                 pRgn.CreateEllipticRgn( ptMiddle.x - MAX_DRAG_SIZE_2, ptMiddle.y - MAX_DRAG_SIZE_2,
00985                                                                 ptMiddle.x + MAX_DRAG_SIZE_2, ptMiddle.y + MAX_DRAG_SIZE_2 );
00986                 dcDrag.SelectClipRgn( &pRgn );
00987         }
00988 
00989         CFont* pOldFont = (CFont*)dcDrag.SelectObject( &CoolInterface.m_fntNormal );
00990 
00991         for ( CLibraryTreeItem* pItem = m_pSelFirst ; pItem ; pItem = pItem->m_pSelNext )
00992         {
00993                 GetRect( pItem, &rcOne );
00994                 CRect rcDummy;
00995 
00996                 if ( rcDummy.IntersectRect( &rcAll, &rcOne ) )
00997                 {
00998                         rcOne.OffsetRect( -rcAll.left, -rcAll.top );
00999                         pItem->Paint( dcDrag, rcOne, FALSE, RGB( 250, 255, 250 ) );
01000                 }
01001         }
01002 
01003         dcDrag.SelectObject( pOldFont );
01004         dcDrag.SelectObject( pOldDrag );
01005         dcDrag.DeleteDC();
01006 
01007         CImageList* pAll = new CImageList();
01008         pAll->Create( rcAll.Width(), rcAll.Height(), ILC_COLOR16|ILC_MASK, 1, 1 );
01009         pAll->Add( &bmDrag, RGB( 250, 255, 250 ) );
01010 
01011         bmDrag.DeleteObject();
01012 
01013         pAll->BeginDrag( 0, ptMouse - rcAll.TopLeft() );
01014 
01015         return pAll;
01016 }
01017 
01018 
01020 // CLibraryTreeItem construction
01021 
01022 CLibraryTreeItem::CLibraryTreeItem(CLibraryTreeItem* pParent)
01023 {
01024         m_pParent               = pParent;
01025         m_pList                 = NULL;
01026         m_nCount                = 0;
01027         m_nBuffer               = 0;
01028         m_pSelPrev              = NULL;
01029         m_pSelNext              = NULL;
01030         m_nCleanCookie  = 0;
01031 
01032         m_bExpanded             = FALSE;
01033         m_bSelected             = FALSE;
01034         m_bContract1    = FALSE;
01035         m_bContract2    = FALSE;
01036 
01037         m_pPhysical             = NULL;
01038         m_pVirtual              = NULL;
01039         m_nCookie               = 0;
01040         m_bBold                 = FALSE;
01041     m_bShared           = TRUE;
01042         m_bCollection   = FALSE;
01043         m_nIcon16               = -1;
01044 }
01045 
01046 CLibraryTreeItem::~CLibraryTreeItem()
01047 {
01048         if ( m_pList )
01049         {
01050                 Clear();
01051                 delete [] m_pList;
01052         }
01053 }
01054 
01056 // CLibraryTreeItem add
01057 
01058 CLibraryTreeItem* CLibraryTreeItem::Add(LPCTSTR pszName)
01059 {
01060         if ( m_nCount == m_nBuffer )
01061         {
01062                 if ( m_nBuffer ) m_nBuffer += min( m_nBuffer, 16 ); else m_nBuffer = 4;
01063 
01064                 CLibraryTreeItem** pList = new CLibraryTreeItem*[ m_nBuffer ];
01065 
01066                 if ( m_nCount ) CopyMemory( pList, m_pList, m_nCount * 4 );
01067                 if ( m_pList ) delete [] m_pList;
01068 
01069                 m_pList = pList;
01070         }
01071 
01072         if ( m_nCount == 0 ) return m_pList[ m_nCount++ ] = new CLibraryTreeItem( this );
01073 
01074     int nFirst = 0;
01075         for ( int nLast = m_nCount - 1 ; nLast >= nFirst ; )
01076         {
01077                 int nMiddle = ( nFirst + nLast ) >> 1;
01078 
01079                 CLibraryTreeItem* pItem = m_pList[ nMiddle ];
01080 
01081                 if ( _tcsicoll( pszName, pItem->m_sText ) >= 0 )
01082                 {
01083                         nFirst = nMiddle + 1;
01084                 }
01085                 else
01086                 {
01087                         nLast = nMiddle - 1;
01088                 }
01089         }
01090 
01091         MoveMemory( m_pList + nFirst + 1, m_pList + nFirst, ( m_nCount - nFirst ) << 2 );
01092         m_nCount++;
01093 
01094         return m_pList[ nFirst ] = new CLibraryTreeItem( this );
01095 }
01096 
01098 // CLibraryTreeItem delete
01099 
01100 void CLibraryTreeItem::Delete()
01101 {
01102         m_pParent->Delete( this );
01103 }
01104 
01105 void CLibraryTreeItem::Delete(CLibraryTreeItem* pItem)
01106 {
01107         ASSERT( pItem->m_bSelected == FALSE );
01108 
01109         CLibraryTreeItem** pChild = m_pList;
01110 
01111         for ( int nChild = m_nCount ; nChild ; nChild--, pChild++ )
01112         {
01113                 if ( *pChild == pItem )
01114                 {
01115                         MoveMemory( pChild, pChild + 1, 4 * ( nChild - 1 ) );
01116                         m_nCount--;
01117                         break;
01118                 }
01119         }
01120 
01121         delete pItem;
01122 }
01123 
01124 void CLibraryTreeItem::Delete(int nItem)
01125 {
01126         if ( nItem < 0 || nItem >= m_nCount ) return;
01127 
01128         ASSERT( m_pList[ nItem ]->m_bSelected == FALSE );
01129         delete m_pList[ nItem ];
01130         MoveMemory( m_pList + nItem, m_pList + nItem + 1, 4 * ( m_nCount - nItem - 1 ) );
01131         m_nCount--;
01132 }
01133 
01135 // CLibraryTreeItem clear
01136 
01137 void CLibraryTreeItem::Clear()
01138 {
01139         if ( m_pList )
01140         {
01141                 for ( int nChild = 0 ; nChild < m_nCount ; nChild++ ) delete m_pList[ nChild ];
01142                 delete [] m_pList;
01143         }
01144 
01145         m_pList         = NULL;
01146         m_nCount        = 0;
01147         m_nBuffer       = 0;
01148 }
01149 
01151 // CLibraryTreeItem visibility
01152 
01153 BOOL CLibraryTreeItem::IsVisible() const
01154 {
01155         for ( CLibraryTreeItem* pRoot = m_pParent ; pRoot ; pRoot = pRoot->m_pParent )
01156         {
01157                 if ( ! pRoot->m_bExpanded ) return FALSE;
01158         }
01159 
01160         return TRUE;
01161 }
01162 
01163 int CLibraryTreeItem::GetChildCount() const
01164 {
01165         int nCount = m_nCount;
01166 
01167         CLibraryTreeItem** pChild = m_pList;
01168 
01169         for ( int nChild = m_nCount ; nChild ; nChild--, pChild++ )
01170         {
01171                 if ( (*pChild)->m_bExpanded ) nCount += (*pChild)->GetChildCount();
01172         }
01173 
01174         return nCount;
01175 }
01176 
01178 // CLibraryTreeItem paint
01179 
01180 void CLibraryTreeItem::Paint(CDC& dc, CRect& rc, BOOL bTarget, COLORREF crBack) const
01181 {
01182         if ( crBack == CLR_NONE ) crBack = CoolInterface.m_crWindow;
01183 
01184         if ( m_nCount )
01185         {
01186                 ImageList_DrawEx( ShellIcons.GetHandle( 16 ),
01187                         m_bExpanded ? SHI_MINUS : SHI_PLUS,
01188                         dc.GetSafeHdc(), rc.left, rc.top, 16, 16,
01189                         crBack, CLR_NONE, ILD_NORMAL );
01190         }
01191         else
01192         {
01193                 dc.FillSolidRect( rc.left, rc.top, 16, 16, crBack );
01194         }
01195 
01196         int nImage = ( m_bExpanded && m_nCount ) ? SHI_FOLDER_OPEN : SHI_FOLDER_CLOSED;
01197         if ( m_nIcon16 >= 0 ) nImage = m_nIcon16;
01198 
01199         UINT nIconStyle = ( m_bSelected || bTarget ) ? ILD_SELECTED : ILD_NORMAL;
01200 
01201         if ( ! m_bShared ) nIconStyle |= INDEXTOOVERLAYMASK( SHI_O_LOCKED );
01202         if ( m_bCollection ) nIconStyle |= INDEXTOOVERLAYMASK( SHI_O_COLLECTION );
01203 
01204         ImageList_DrawEx( ShellIcons.GetHandle( 16 ), nImage,
01205                 dc.GetSafeHdc(), rc.left + 16, rc.top, 16, 16,
01206                 crBack, CLR_DEFAULT, nIconStyle );
01207 
01208         crBack = ( m_bSelected || bTarget ) ? CoolInterface.m_crHighlight : crBack;
01209         COLORREF crText = ( m_bSelected || bTarget ) ? CoolInterface.m_crHiText : CoolInterface.m_crText;
01210 
01211         dc.SetTextColor( crText );
01212         dc.SetBkColor( crBack );
01213         dc.SetBkMode( OPAQUE );
01214 
01215         rc.left += 32;
01216         CString strName = m_sText;
01217         if ( theApp.m_bRTL ) strName = _T("\x202A") + strName;
01218         dc.ExtTextOut( rc.left + 3, rc.top + 1, ETO_OPAQUE|ETO_CLIPPED, &rc,
01219                 strName, NULL );
01220         rc.left -= 32;
01221 }
01222 
01224 // CLibraryTreeItem get child files
01225 
01226 int CLibraryTreeItem::GetFileList(CLibraryList* pList, BOOL bRecursive) const
01227 {
01228         if ( LibraryFolders.CheckFolder( m_pPhysical, TRUE ) )
01229         {
01230                 return m_pPhysical->GetFileList( pList, bRecursive );
01231         }
01232         else if ( LibraryFolders.CheckAlbum( m_pVirtual ) )
01233         {
01234                 return m_pVirtual->GetFileList( pList, bRecursive );
01235         }
01236 
01237         return 0;
01238 }

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