00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "MatchObjects.h"
00026 #include "QueryHit.h"
00027 #include "Schema.h"
00028 #include "SchemaCache.h"
00029 #include "G2Packet.h"
00030 #include "CtrlBrowseFrame.h"
00031 #include "CtrlMatch.h"
00032 #include "DlgHitColumns.h"
00033 #include "Skin.h"
00034
00035 #ifdef _DEBUG
00036 #define new DEBUG_NEW
00037 #undef THIS_FILE
00038 static char THIS_FILE[] = __FILE__;
00039 #endif
00040
00041 IMPLEMENT_DYNAMIC(CBrowseFrameCtrl, CWnd)
00042
00043 BEGIN_MESSAGE_MAP(CBrowseFrameCtrl, CWnd)
00044 ON_WM_CREATE()
00045 ON_WM_DESTROY()
00046 ON_WM_SETCURSOR()
00047 ON_WM_LBUTTONDOWN()
00048 ON_WM_SIZE()
00049 ON_WM_PAINT()
00050 ON_UPDATE_COMMAND_UI(ID_SEARCH_DETAILS, OnUpdateSearchDetails)
00051 ON_COMMAND(ID_SEARCH_DETAILS, OnSearchDetails)
00052 ON_NOTIFY(BTN_SELCHANGED, IDC_BROWSE_TREE, OnTreeSelection)
00053 ON_UPDATE_COMMAND_UI(ID_LIBRARY_TREE_PHYSICAL, OnUpdateLibraryTreePhysical)
00054 ON_COMMAND(ID_LIBRARY_TREE_PHYSICAL, OnLibraryTreePhysical)
00055 ON_UPDATE_COMMAND_UI(ID_LIBRARY_TREE_VIRTUAL, OnUpdateLibraryTreeVirtual)
00056 ON_COMMAND(ID_LIBRARY_TREE_VIRTUAL, OnLibraryTreeVirtual)
00057 END_MESSAGE_MAP()
00058
00059 #define SIZE_INTERNAL 1982
00060 #define SPLIT_SIZE 6
00061 #define BAR_HEIGHT 28
00062
00063
00065
00066
00067 CBrowseFrameCtrl::CBrowseFrameCtrl()
00068 {
00069 m_bTreeVisible = FALSE;
00070 m_nTreeSize = Settings.Search.BrowseTreeSize;
00071 m_bPanelEnable = FALSE;
00072 m_bPanelVisible = Settings.Search.DetailPanelVisible;
00073 m_nPanelSize = Settings.Search.DetailPanelSize;
00074 m_pTree[0] = NULL;
00075 m_pTree[1] = NULL;
00076 m_nTree = 1;
00077 }
00078
00079 CBrowseFrameCtrl::~CBrowseFrameCtrl()
00080 {
00081 if ( m_pTree[0] != NULL ) m_pTree[0]->Release();
00082 if ( m_pTree[1] != NULL ) m_pTree[1]->Release();
00083 }
00084
00086
00087
00088 BOOL CBrowseFrameCtrl::Create(CWnd* pParentWnd, CMatchCtrl* pMatch)
00089 {
00090 CRect rect( 0, 0, 0, 0 );
00091 m_wndList = pMatch;
00092 m_wndList->SetBrowseMode();
00093 return CWnd::Create( NULL, _T("CBrowseFrameCtrl"), WS_CHILD|WS_VISIBLE,
00094 rect, pParentWnd, IDC_BROWSE_FRAME, NULL );
00095 }
00096
00097 int CBrowseFrameCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
00098 {
00099 if ( CWnd::OnCreate( lpCreateStruct ) == -1 ) return -1;
00100
00101 if ( ! m_wndTreeTop.Create( this, WS_CHILD|WS_VISIBLE|CBRS_NOALIGN, AFX_IDW_TOOLBAR ) ) return -1;
00102 m_wndTreeTop.SetBarStyle( m_wndTreeTop.GetBarStyle() | CBRS_TOOLTIPS|CBRS_BORDER_BOTTOM );
00103 m_wndTreeTop.SetOwner( GetOwner() );
00104
00105 m_wndTree.Create( this );
00106 m_wndDetails.Create( this );
00107 m_wndList->SetParent( this );
00108 m_wndList->SetOwner( GetParent() );
00109
00110 return 0;
00111 }
00112
00113 void CBrowseFrameCtrl::OnDestroy()
00114 {
00115 CWnd::OnDestroy();
00116 }
00117
00118 void CBrowseFrameCtrl::OnSkinChange()
00119 {
00120 Skin.CreateToolBar( _T("CBrowseTree.Top"), &m_wndTreeTop );
00121 Skin.Translate( _T("CMatchCtrl"), &m_wndList->m_wndHeader );
00122 }
00123
00124 void CBrowseFrameCtrl::OnSize(UINT nType, int cx, int cy)
00125 {
00126 CWnd::OnSize( nType, cx, cy );
00127
00128 CRect rc;
00129 GetClientRect( &rc );
00130
00131 if ( rc.Height() < 32 ) return;
00132
00133 if ( rc.Width() < m_nTreeSize + SPLIT_SIZE )
00134 {
00135 m_nTreeSize = max( 0, rc.Width() - SPLIT_SIZE );
00136 }
00137
00138 HDWP hDWP = BeginDeferWindowPos( 4 );
00139
00140 if ( m_bTreeVisible )
00141 {
00142 DeferWindowPos( hDWP, m_wndTreeTop, NULL, rc.left, rc.top, m_nTreeSize,
00143 BAR_HEIGHT, SWP_SHOWWINDOW );
00144 DeferWindowPos( hDWP, m_wndTree, NULL, rc.left, rc.top + BAR_HEIGHT, m_nTreeSize,
00145 rc.Height() - BAR_HEIGHT, SWP_SHOWWINDOW );
00146 rc.left += m_nTreeSize + SPLIT_SIZE;
00147 }
00148 else
00149 {
00150 m_wndTreeTop.ShowWindow( SW_HIDE );
00151 m_wndTree.ShowWindow( SW_HIDE );
00152 }
00153
00154 rc.top ++;
00155
00156 if ( rc.Height() < m_nPanelSize + SPLIT_SIZE )
00157 {
00158 m_nPanelSize = max( 0, rc.Height() - SPLIT_SIZE );
00159 }
00160
00161 if ( m_bPanelEnable && m_bPanelVisible )
00162 {
00163 DeferWindowPos( hDWP, m_wndDetails, NULL, rc.left, rc.bottom - m_nPanelSize, rc.Width(),
00164 m_nPanelSize, SWP_NOZORDER|SWP_SHOWWINDOW );
00165 rc.bottom -= m_nPanelSize + SPLIT_SIZE;
00166 }
00167 else
00168 {
00169 m_wndDetails.ShowWindow( SW_HIDE );
00170 }
00171
00172 DeferWindowPos( hDWP, m_wndList->GetSafeHwnd(), NULL, rc.left, rc.top,
00173 rc.Width(), rc.Height(), SWP_NOZORDER|SWP_SHOWWINDOW );
00174
00175 EndDeferWindowPos( hDWP );
00176 }
00177
00178 void CBrowseFrameCtrl::OnPaint()
00179 {
00180 CPaintDC dc( this );
00181 CRect rcClient;
00182
00183 GetClientRect( &rcClient );
00184
00185 CRect rcBar( rcClient.left + m_nTreeSize,
00186 rcClient.top,
00187 rcClient.left + m_nTreeSize + SPLIT_SIZE,
00188 rcClient.bottom );
00189
00190 if ( m_wndTree.IsWindowVisible() )
00191 {
00192 dc.FillSolidRect( rcBar.left, rcBar.top, 1, rcBar.Height(), GetSysColor( COLOR_BTNFACE ) );
00193 dc.FillSolidRect( rcBar.left + 1, rcBar.top, 1, rcBar.Height(), GetSysColor( COLOR_3DHIGHLIGHT ) );
00194 dc.FillSolidRect( rcBar.right - 1, rcBar.top, 1, rcBar.Height(), GetSysColor( COLOR_3DSHADOW ) );
00195 dc.FillSolidRect( rcBar.left + 2, rcBar.top, rcBar.Width() - 3, rcBar.Height(), GetSysColor( COLOR_BTNFACE ) );
00196 dc.ExcludeClipRect( &rcBar );
00197 dc.FillSolidRect( rcBar.left, rcBar.top, rcClient.right - rcBar.left, 1, GetSysColor( COLOR_3DHIGHLIGHT ) );
00198 }
00199 else
00200 {
00201 dc.FillSolidRect( rcClient.left, rcClient.top, rcClient.Width(), 1, GetSysColor( COLOR_3DHIGHLIGHT ) );
00202 }
00203
00204 rcBar.SetRect( rcClient.left,
00205 rcClient.bottom - m_nPanelSize - SPLIT_SIZE,
00206 rcClient.right,
00207 rcClient.bottom - m_nPanelSize );
00208
00209 if ( m_wndDetails.IsWindowVisible() )
00210 {
00211 if ( m_wndTree.IsWindowVisible() ) rcBar.left += m_nTreeSize + SPLIT_SIZE;
00212
00213 dc.FillSolidRect( rcBar.left, rcBar.top, rcBar.Width(), 1, GetSysColor( COLOR_BTNFACE ) );
00214 dc.FillSolidRect( rcBar.left, rcBar.top + 1, rcBar.Width(), 1, GetSysColor( COLOR_3DHIGHLIGHT ) );
00215 dc.FillSolidRect( rcBar.left, rcBar.bottom - 1, rcBar.Width(), 1, GetSysColor( COLOR_3DSHADOW ) );
00216 dc.FillSolidRect( rcBar.left, rcBar.top + 2, rcBar.Width(), rcBar.Height() - 3,
00217 GetSysColor( COLOR_BTNFACE ) );
00218 dc.ExcludeClipRect( &rcBar );
00219 }
00220 }
00221
00222 BOOL CBrowseFrameCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
00223 {
00224 CRect rcClient, rc;
00225 CPoint point;
00226
00227 GetCursorPos( &point );
00228 GetClientRect( &rcClient );
00229 ClientToScreen( &rcClient );
00230
00231 rc.SetRect( theApp.m_bRTL ? rcClient.right - m_nTreeSize - SPLIT_SIZE :
00232 rcClient.left + m_nTreeSize,
00233 rcClient.top,
00234 theApp.m_bRTL ? rcClient.right - m_nTreeSize :
00235 rcClient.left + m_nTreeSize + SPLIT_SIZE,
00236 rcClient.bottom );
00237
00238 if ( m_wndTree.IsWindowVisible() && rc.PtInRect( point ) )
00239 {
00240 SetCursor( AfxGetApp()->LoadStandardCursor( IDC_SIZEWE ) );
00241 return TRUE;
00242 }
00243
00244 rc.SetRect( rcClient.left,
00245 rcClient.bottom - m_nPanelSize - SPLIT_SIZE,
00246 rcClient.right,
00247 rcClient.bottom - m_nPanelSize );
00248
00249 if ( m_wndTree.IsWindowVisible() )
00250 {
00251 if ( theApp.m_bRTL )
00252 rc.right -= m_nTreeSize + SPLIT_SIZE;
00253 else
00254 rc.left += m_nTreeSize + SPLIT_SIZE;
00255 }
00256
00257 if ( m_wndDetails.IsWindowVisible() && rc.PtInRect( point ) )
00258 {
00259 SetCursor( AfxGetApp()->LoadStandardCursor( IDC_SIZENS ) );
00260 return TRUE;
00261 }
00262
00263 return CWnd::OnSetCursor( pWnd, nHitTest, message );
00264 }
00265
00266 void CBrowseFrameCtrl::OnLButtonDown(UINT nFlags, CPoint point)
00267 {
00268 CRect rcClient, rc;
00269 GetClientRect( &rcClient );
00270
00271 rc.SetRect( rcClient.left + m_nTreeSize,
00272 rcClient.top,
00273 rcClient.left + m_nTreeSize + SPLIT_SIZE,
00274 rcClient.bottom );
00275
00276 if ( m_wndTree.IsWindowVisible() && rc.PtInRect( point ) )
00277 {
00278 DoSizeTree();
00279 return;
00280 }
00281
00282 rc.SetRect( rcClient.left,
00283 rcClient.bottom - m_nPanelSize - SPLIT_SIZE,
00284 rcClient.right,
00285 rcClient.bottom - m_nPanelSize );
00286
00287 if ( m_wndTree.IsWindowVisible() ) rc.left += m_nTreeSize + SPLIT_SIZE;
00288
00289 if ( m_wndDetails.IsWindowVisible() && rc.PtInRect( point ) )
00290 {
00291 DoSizePanel();
00292 return;
00293 }
00294
00295 CWnd::OnLButtonDown( nFlags, point );
00296 }
00297
00298 BOOL CBrowseFrameCtrl::DoSizeTree()
00299 {
00300 MSG* pMsg = &AfxGetThreadState()->m_msgCur;
00301 CRect rcClient;
00302 CPoint point;
00303
00304 GetClientRect( &rcClient );
00305 ClientToScreen( &rcClient );
00306 ClipCursor( &rcClient );
00307 SetCapture();
00308
00309 GetClientRect( &rcClient );
00310
00311 int nOffset = 0xFFFF;
00312
00313 while ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 )
00314 {
00315 while ( ::PeekMessage( pMsg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ) );
00316
00317 if ( ! AfxGetThread()->PumpMessage() )
00318 {
00319 AfxPostQuitMessage( 0 );
00320 break;
00321 }
00322
00323 GetCursorPos( &point );
00324 ScreenToClient( &point );
00325
00326 int nSplit = point.x - rcClient.left;
00327
00328 if ( nOffset == 0xFFFF ) nOffset = m_nTreeSize - nSplit;
00329 nSplit += nOffset;
00330
00331 nSplit = max( nSplit, 0 );
00332 nSplit = min( nSplit, int(rcClient.right - SPLIT_SIZE) );
00333
00334 if ( nSplit < 8 )
00335 nSplit = 0;
00336 if ( nSplit > rcClient.right - SPLIT_SIZE - 8 )
00337 nSplit = rcClient.right - SPLIT_SIZE;
00338
00339 if ( nSplit != m_nTreeSize )
00340 {
00341 m_nTreeSize = nSplit;
00342 Settings.Search.BrowseTreeSize = (DWORD)m_nTreeSize;
00343 OnSize( SIZE_INTERNAL, 0, 0 );
00344 Invalidate();
00345 }
00346 }
00347
00348 ReleaseCapture();
00349 ClipCursor( NULL );
00350
00351 return TRUE;
00352 }
00353
00354 BOOL CBrowseFrameCtrl::DoSizePanel()
00355 {
00356 MSG* pMsg = &AfxGetThreadState()->m_msgCur;
00357 CRect rcClient;
00358 CPoint point;
00359
00360 GetClientRect( &rcClient );
00361 if ( m_bTreeVisible ) rcClient.left += m_nTreeSize + SPLIT_SIZE;
00362 ClientToScreen( &rcClient );
00363 ClipCursor( &rcClient );
00364 SetCapture();
00365
00366 ScreenToClient( &rcClient );
00367
00368 int nOffset = 0xFFFF;
00369
00370 while ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 )
00371 {
00372 while ( ::PeekMessage( pMsg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ) );
00373
00374 if ( ! AfxGetThread()->PumpMessage() )
00375 {
00376 AfxPostQuitMessage( 0 );
00377 break;
00378 }
00379
00380 GetCursorPos( &point );
00381 ScreenToClient( &point );
00382
00383 int nSplit = rcClient.bottom - point.y;
00384
00385 if ( nOffset == 0xFFFF ) nOffset = m_nPanelSize - nSplit;
00386 nSplit += nOffset;
00387
00388 if ( nSplit < 8 )
00389 nSplit = 0;
00390 if ( nSplit > rcClient.Height() - SPLIT_SIZE - 8 )
00391 nSplit = rcClient.Height() - SPLIT_SIZE;
00392
00393 if ( nSplit != m_nPanelSize )
00394 {
00395 m_nPanelSize = nSplit;
00396 Settings.Search.DetailPanelSize = nSplit;
00397 OnSize( SIZE_INTERNAL, 0, 0 );
00398 Invalidate();
00399 }
00400 }
00401
00402 ReleaseCapture();
00403 ClipCursor( NULL );
00404
00405 return TRUE;
00406 }
00407
00408 void CBrowseFrameCtrl::OnPhysicalTree(CG2Packet* pPacket)
00409 {
00410 CSingleLock lRoot( m_wndTree.SyncRoot(), TRUE );
00411
00412 if ( m_pTree[0] != NULL ) m_pTree[0]->Release();
00413 m_pTree[0] = pPacket;
00414 pPacket->AddRef();
00415 if ( m_nTree == 0 ) m_wndTree.OnTreePacket( pPacket );
00416
00417 if ( ! m_bTreeVisible )
00418 {
00419 m_bTreeVisible = TRUE;
00420 PostMessage( WM_SIZE, SIZE_INTERNAL, 0 );
00421 }
00422 }
00423
00424 void CBrowseFrameCtrl::OnVirtualTree(CG2Packet* pPacket)
00425 {
00426 CSingleLock lRoot( m_wndTree.SyncRoot(), TRUE );
00427
00428 if ( m_pTree[1] != NULL ) m_pTree[1]->Release();
00429 m_pTree[1] = pPacket;
00430 pPacket->AddRef();
00431 if ( m_nTree == 1 ) m_wndTree.OnTreePacket( pPacket );
00432
00433 if ( ! m_bTreeVisible )
00434 {
00435 m_bTreeVisible = TRUE;
00436 PostMessage( WM_SIZE, SIZE_INTERNAL, 0 );
00437 }
00438 }
00439
00440 void CBrowseFrameCtrl::OnTreeSelection(NMHDR* pNotify, LRESULT* pResult)
00441 {
00442 CSingleLock lMatches( &m_wndList->m_pMatches->m_pSection, TRUE );
00443 CSingleLock lTree( m_wndTree.SyncRoot(), TRUE );
00444
00445 CMatchFile** ppFile = m_wndList->m_pMatches->m_pFiles;
00446 BOOL bGlobal = m_wndTree.GetSelectedCount() == 0;
00447
00448 for ( DWORD nFiles = m_wndList->m_pMatches->m_nFiles ; nFiles ; nFiles--, ppFile++ )
00449 {
00450 CMatchFile* pFile = (*ppFile);
00451
00452 for ( CQueryHit* pHit = pFile->m_pHits ; pHit ; pHit = pHit->m_pNext )
00453 {
00454 if ( pHit->m_bMatched = bGlobal ) continue;
00455
00456 for ( CBrowseTreeItem* pSel = m_wndTree.GetFirstSelected() ; pSel ;
00457 pSel = pSel->m_pSelNext )
00458 {
00459 SelectTree( pSel, pHit );
00460 }
00461 }
00462 }
00463
00464 CBrowseTreeItem* pTree = m_wndTree.GetFirstSelected();
00465
00466 if ( pTree != NULL && pTree->m_pSelNext == NULL && pTree->m_pSchema != NULL )
00467 {
00468 CString strURI = pTree->m_pSchema->GetContainedURI( CSchema::stFile );
00469
00470 if ( strURI.GetLength() &&
00471 ( m_wndList->m_pSchema == NULL || m_wndList->m_pSchema->m_sURI != strURI ) )
00472 {
00473 if ( CSchema* pSchema = SchemaCache.Get( strURI ) )
00474 {
00475 CPtrList pColumns;
00476 CSchemaColumnsDlg::LoadColumns( pSchema, &pColumns );
00477 m_wndList->SelectSchema( pSchema, &pColumns );
00478 }
00479 }
00480 }
00481
00482 m_wndList->m_pMatches->Filter();
00483 m_wndList->Update();
00484
00485 GetOwner()->PostMessage( WM_COMMAND, MAKELONG( IDC_MATCHES, LBN_SELCHANGE ), 0 );
00486
00487 *pResult = 0;
00488 }
00489
00490 void CBrowseFrameCtrl::SelectTree(CBrowseTreeItem* pItem, CQueryHit* pHit)
00491 {
00492 DWORD* pIndex = pItem->m_pFiles;
00493
00494 for ( DWORD nIndex = pItem->m_nFiles ; nIndex ; nIndex--, pIndex++ )
00495 {
00496 if ( (*pIndex) == pHit->m_nIndex )
00497 {
00498 pHit->m_bMatched = TRUE;
00499 return;
00500 }
00501 }
00502
00503 if ( pItem->m_bExpanded == TRUE ) return;
00504
00505 CBrowseTreeItem** ppChild = pItem->m_pList;
00506
00507 for ( DWORD nIndex = pItem->m_nCount ; nIndex ; nIndex--, ppChild++ )
00508 {
00509 SelectTree( *ppChild, pHit );
00510 }
00511 }
00512
00513 void CBrowseFrameCtrl::OnSelChangeMatches()
00514 {
00515 CSingleLock pLock( &m_wndList->m_pMatches->m_pSection, TRUE );
00516 m_wndDetails.Update( m_wndList->m_pMatches->GetSelectedFile( TRUE ) );
00517 pLock.Unlock();
00518
00519 if ( m_bPanelEnable == FALSE )
00520 {
00521 m_bPanelEnable = TRUE;
00522 OnSize( SIZE_INTERNAL, 0, 0 );
00523 }
00524 }
00525
00526 void CBrowseFrameCtrl::OnUpdateSearchDetails(CCmdUI* pCmdUI)
00527 {
00528 BOOL bVisible = m_bPanelEnable && m_wndList->IsWindowVisible();
00529 pCmdUI->Enable( bVisible );
00530 pCmdUI->SetCheck( bVisible && m_bPanelVisible );
00531 }
00532
00533 void CBrowseFrameCtrl::OnSearchDetails()
00534 {
00535 m_bPanelVisible = Settings.Search.DetailPanelVisible = ! m_bPanelVisible;
00536 OnSize( SIZE_INTERNAL, 0, 0 );
00537 }
00538
00539 void CBrowseFrameCtrl::OnUpdateLibraryTreePhysical(CCmdUI *pCmdUI)
00540 {
00541 pCmdUI->Enable( m_pTree[0] != NULL );
00542 pCmdUI->SetCheck( m_pTree[0] != NULL && m_nTree == 0 );
00543 }
00544
00545 void CBrowseFrameCtrl::OnLibraryTreePhysical()
00546 {
00547 CSingleLock lRoot( m_wndTree.SyncRoot(), TRUE );
00548
00549 if ( m_pTree[0] != NULL )
00550 {
00551 m_nTree = 0;
00552 m_wndTree.OnTreePacket( m_pTree[ m_nTree ] );
00553 }
00554 }
00555
00556 void CBrowseFrameCtrl::OnUpdateLibraryTreeVirtual(CCmdUI *pCmdUI)
00557 {
00558 pCmdUI->Enable( m_pTree[1] != NULL );
00559 pCmdUI->SetCheck( m_pTree[1] != NULL && m_nTree == 1 );
00560 }
00561
00562 void CBrowseFrameCtrl::OnLibraryTreeVirtual()
00563 {
00564 CSingleLock lRoot( m_wndTree.SyncRoot(), TRUE );
00565
00566 if ( m_pTree[1] != NULL )
00567 {
00568 m_nTree = 1;
00569 m_wndTree.OnTreePacket( m_pTree[ m_nTree ] );
00570 }
00571 }