1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2009-2012 - TortoiseGit
4 // Copyright (C) 2012 Sven Strickroth <email@cs-ware.de>
5 // Copyright (C) 2003-2012 - TortoiseSVN
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software Foundation,
19 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 // RepositoryBrowser.cpp : implementation file
25 #include "TortoiseProc.h"
26 #include "RepositoryBrowser.h"
30 #include "UnicodeUtils.h"
31 #include "SysImageList.h"
35 #include "PathUtils.h"
37 void SetSortArrowA(CListCtrl
* control
, int nColumn
, bool bAscending
)
43 CHeaderCtrl
* pHeader
= control
->GetHeaderCtrl();
44 HDITEM HeaderItem
= {0};
45 HeaderItem
.mask
= HDI_FORMAT
;
46 for (int i
= 0; i
< pHeader
->GetItemCount(); ++i
)
48 pHeader
->GetItem(i
, &HeaderItem
);
49 HeaderItem
.fmt
&= ~(HDF_SORTDOWN
| HDF_SORTUP
);
50 pHeader
->SetItem(i
, &HeaderItem
);
54 pHeader
->GetItem(nColumn
, &HeaderItem
);
55 HeaderItem
.fmt
|= (bAscending
? HDF_SORTUP
: HDF_SORTDOWN
);
56 pHeader
->SetItem(nColumn
, &HeaderItem
);
60 class CRepoListCompareFunc
63 CRepoListCompareFunc(CListCtrl
* pList
, int col
, bool desc
)
69 static int CALLBACK
StaticCompare(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
71 return ((CRepoListCompareFunc
*) lParamSort
)->Compare(lParam1
, lParam2
);
74 int Compare(LPARAM lParam1
, LPARAM lParam2
)
76 CShadowFilesTree
* pLeft
= (CShadowFilesTree
*)m_pList
->GetItemData(lParam1
);
77 CShadowFilesTree
* pRight
= (CShadowFilesTree
*)m_pList
->GetItemData(lParam2
);
82 case CRepositoryBrowser::eCol_Name
:
83 result
= SortStrCmp(pLeft
->m_sName
, pRight
->m_sName
);
86 case CRepositoryBrowser::eCol_Extension
:
87 result
= m_pList
->GetItemText(static_cast<int>(lParam1
), 1).CompareNoCase(m_pList
->GetItemText(static_cast<int>(lParam2
), 1));
88 if (result
== 0) // if extensions are the same, use the filename to sort
89 result
= SortStrCmp(pRight
->m_sName
, pRight
->m_sName
);
92 case CRepositoryBrowser::eCol_FileSize
:
93 if (pLeft
->m_iSize
> pRight
->m_iSize
)
95 else if (pLeft
->m_iSize
< pRight
->m_iSize
)
98 result
= SortStrCmp(pLeft
->m_sName
, pRight
->m_sName
);
104 if (pLeft
->m_bFolder
!= pRight
->m_bFolder
)
106 if (pRight
->m_bFolder
)
114 int SortStrCmp(CString
&left
, CString
&right
)
116 if (CRepositoryBrowser::s_bSortLogical
)
117 return StrCmpLogicalW(left
, right
);
118 return StrCmpI(left
, right
);
126 // CRepositoryBrowser dialog
128 bool CRepositoryBrowser::s_bSortLogical
= true;
130 IMPLEMENT_DYNAMIC(CRepositoryBrowser
, CResizableStandAloneDialog
)
132 CRepositoryBrowser::CRepositoryBrowser(CString rev
, CWnd
* pParent
/*=NULL*/)
133 : CResizableStandAloneDialog(CRepositoryBrowser::IDD
, pParent
)
135 , m_currSortDesc(false)
140 CRepositoryBrowser::~CRepositoryBrowser()
144 void CRepositoryBrowser::DoDataExchange(CDataExchange
* pDX
)
146 CDialog::DoDataExchange(pDX
);
147 DDX_Control(pDX
, IDC_REPOTREE
, m_RepoTree
);
148 DDX_Control(pDX
, IDC_REPOLIST
, m_RepoList
);
152 BEGIN_MESSAGE_MAP(CRepositoryBrowser
, CResizableStandAloneDialog
)
153 ON_NOTIFY(TVN_SELCHANGED
, IDC_REPOTREE
, &CRepositoryBrowser::OnTvnSelchangedRepoTree
)
155 ON_NOTIFY(LVN_COLUMNCLICK
, IDC_REPOLIST
, &CRepositoryBrowser::OnLvnColumnclickRepoList
)
156 ON_NOTIFY(NM_DBLCLK
, IDC_REPOLIST
, &CRepositoryBrowser::OnNMDblclk_RepoList
)
157 ON_BN_CLICKED(IDC_BUTTON_REVISION
, &CRepositoryBrowser::OnBnClickedButtonRevision
)
165 // CRepositoryBrowser message handlers
167 BOOL
CRepositoryBrowser::OnInitDialog()
169 CResizableStandAloneDialog::OnInitDialog();
170 CAppUtils::MarkWindowAsUnpinnable(m_hWnd
);
172 AddAnchor(IDC_STATIC
, TOP_LEFT
);
173 AddAnchor(IDC_BUTTON_REVISION
, TOP_LEFT
, TOP_RIGHT
);
174 AddAnchor(IDC_REPOTREE
, TOP_LEFT
, BOTTOM_LEFT
);
175 AddAnchor(IDC_REPOLIST
, TOP_LEFT
, BOTTOM_RIGHT
);
176 AddAnchor(IDHELP
, BOTTOM_RIGHT
);
177 AddAnchor(IDOK
, BOTTOM_RIGHT
);
178 AddAnchor(IDCANCEL
, BOTTOM_RIGHT
);
180 CRepositoryBrowser::s_bSortLogical
= !CRegDWORD(L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoStrCmpLogical", 0, false, HKEY_CURRENT_USER
);
181 if (CRepositoryBrowser::s_bSortLogical
)
182 CRepositoryBrowser::s_bSortLogical
= !CRegDWORD(L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\NoStrCmpLogical", 0, false, HKEY_LOCAL_MACHINE
);
185 temp
.LoadString(IDS_STATUSLIST_COLFILENAME
);
186 m_RepoList
.InsertColumn(eCol_Name
, temp
, 0, 150);
187 temp
.LoadString(IDS_STATUSLIST_COLEXT
);
188 m_RepoList
.InsertColumn(eCol_Extension
, temp
, 0, 100);
189 temp
.LoadString(IDS_LOG_SIZE
);
190 m_RepoList
.InsertColumn(eCol_FileSize
, temp
, 0, 100);
192 // set up the list control
193 // set the extended style of the list control
194 // the style LVS_EX_FULLROWSELECT interferes with the background watermark image but it's more important to be able to select in the whole row.
195 CRegDWORD
regFullRowSelect(_T("Software\\TortoiseGit\\FullRowSelect"), TRUE
);
196 DWORD exStyle
= LVS_EX_HEADERDRAGDROP
| LVS_EX_DOUBLEBUFFER
| LVS_EX_INFOTIP
| LVS_EX_SUBITEMIMAGES
;
197 if (DWORD(regFullRowSelect
))
198 exStyle
|= LVS_EX_FULLROWSELECT
;
199 m_RepoList
.SetExtendedStyle(exStyle
);
200 m_RepoList
.SetImageList(&SYS_IMAGE_LIST(), LVSIL_SMALL
);
202 m_RepoTree
.SetImageList(&SYS_IMAGE_LIST(), TVSIL_NORMAL
);
203 if (SysInfo::Instance().IsVistaOrLater())
205 DWORD exStyle
= TVS_EX_FADEINOUTEXPANDOS
| TVS_EX_AUTOHSCROLL
| TVS_EX_DOUBLEBUFFER
;
206 m_RepoTree
.SetExtendedStyle(exStyle
, exStyle
);
209 SetWindowTheme(m_RepoTree
.GetSafeHwnd(), L
"Explorer", NULL
);
210 SetWindowTheme(m_RepoList
.GetSafeHwnd(), L
"Explorer", NULL
);
212 m_nIconFolder
= SYS_IMAGE_LIST().GetDirIconIndex();
213 m_nOpenIconFolder
= SYS_IMAGE_LIST().GetDirOpenIconIndex();
215 EnableSaveRestore(L
"Reposbrowser");
217 DWORD xPos
= CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RepobrowserDivider"), 0);
221 GetDlgItem(IDC_REPOTREE
)->GetClientRect(&rc
);
222 xPos
= rc
.right
- rc
.left
;
225 HandleDividerMove(CPoint(xPos
+ 20, 10), false);
227 CString sWindowTitle
;
228 GetWindowText(sWindowTitle
);
229 CAppUtils::SetWindowTitle(m_hWnd
, g_Git
.m_CurrentDir
, sWindowTitle
);
233 m_RepoList
.SetFocus();
238 void CRepositoryBrowser::OnOK()
240 SaveDividerPosition();
241 CResizableStandAloneDialog::OnOK();
244 void CRepositoryBrowser::OnCancel()
246 SaveDividerPosition();
247 CResizableStandAloneDialog::OnCancel();
250 void CRepositoryBrowser::OnNMDblclk_RepoList(NMHDR
*pNMHDR
, LRESULT
*pResult
)
252 UNREFERENCED_PARAMETER(pNMHDR
);
255 LPNMITEMACTIVATE pNmItemActivate
= reinterpret_cast<LPNMITEMACTIVATE
>(pNMHDR
);
256 if (pNmItemActivate
->iItem
< 0)
259 CShadowFilesTree
* pItem
= (CShadowFilesTree
*)m_RepoList
.GetItemData(pNmItemActivate
->iItem
);
260 if (pItem
== NULL
|| !pItem
->m_bFolder
)
263 FillListCtrlForShadowTree(pItem
);
264 m_RepoTree
.SelectItem(pItem
->m_hTree
);
267 void CRepositoryBrowser::Refresh()
269 m_RepoTree
.DeleteAllItems();
270 m_RepoList
.DeleteAllItems();
271 m_TreeRoot
.m_ShadowTree
.clear();
272 m_TreeRoot
.m_sName
= "";
273 m_TreeRoot
.m_bFolder
= true;
275 TVINSERTSTRUCT tvinsert
= {0};
276 tvinsert
.hParent
= TVI_ROOT
;
277 tvinsert
.hInsertAfter
= TVI_ROOT
;
278 tvinsert
.itemex
.mask
= TVIF_DI_SETITEM
| TVIF_PARAM
| TVIF_TEXT
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
| TVIF_STATE
;
279 tvinsert
.itemex
.pszText
= L
"/";
280 tvinsert
.itemex
.lParam
= (LPARAM
)&m_TreeRoot
;
281 tvinsert
.itemex
.iImage
= m_nIconFolder
;
282 tvinsert
.itemex
.iSelectedImage
= m_nOpenIconFolder
;
283 m_TreeRoot
.m_hTree
= m_RepoTree
.InsertItem(&tvinsert
);
285 ReadTree(&m_TreeRoot
);
286 m_RepoTree
.Expand(m_TreeRoot
.m_hTree
, TVE_EXPAND
);
287 FillListCtrlForShadowTree(&m_TreeRoot
);
288 m_RepoTree
.SelectItem(m_TreeRoot
.m_hTree
);
291 int CRepositoryBrowser::ReadTreeRecursive(git_repository
&repo
, git_tree
* tree
, CShadowFilesTree
* treeroot
)
293 size_t count
= git_tree_entrycount(tree
);
295 for (int i
= 0; i
< count
; i
++)
297 const git_tree_entry
*entry
= git_tree_entry_byindex(tree
, i
);
300 int mode
= git_tree_entry_attributes(entry
);
302 CString base
= CUnicodeUtils::GetUnicode(git_tree_entry_name(entry
), CP_UTF8
);
304 git_object
*object
= NULL
;
305 git_tree_entry_2object(&object
, &repo
, entry
);
309 CShadowFilesTree
* pNextTree
= &treeroot
->m_ShadowTree
[base
];
310 pNextTree
->m_sName
= base
;
311 pNextTree
->m_pParent
= treeroot
;
315 pNextTree
->m_bFolder
= true;
317 TVINSERTSTRUCT tvinsert
= {0};
318 tvinsert
.hParent
= treeroot
->m_hTree
;
319 tvinsert
.hInsertAfter
= TVI_SORT
;
320 tvinsert
.itemex
.mask
= TVIF_DI_SETITEM
| TVIF_PARAM
| TVIF_TEXT
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
| TVIF_STATE
;
321 tvinsert
.itemex
.pszText
= base
.GetBuffer(base
.GetLength());
322 tvinsert
.itemex
.lParam
= (LPARAM
)pNextTree
;
323 tvinsert
.itemex
.iImage
= m_nIconFolder
;
324 tvinsert
.itemex
.iSelectedImage
= m_nOpenIconFolder
;
325 pNextTree
->m_hTree
= m_RepoTree
.InsertItem(&tvinsert
);
326 base
.ReleaseBuffer();
328 ReadTreeRecursive(repo
, (git_tree
*)object
, pNextTree
);
332 const git_oid
* oid
= git_object_id(object
);
335 git_blob_lookup(&blob
, &repo
, oid
);
339 pNextTree
->m_iSize
= git_blob_rawsize(blob
);
343 git_object_free(object
);
349 int CRepositoryBrowser::ReadTree(CShadowFilesTree
* treeroot
)
351 CStringA gitdir
= CUnicodeUtils::GetMulti(g_Git
.m_CurrentDir
, CP_UTF8
);
352 git_repository
*repository
= NULL
;
353 git_commit
*commit
= NULL
;
354 git_tree
* tree
= NULL
;
358 ret
= git_repository_open(&repository
, gitdir
.GetBuffer());
362 CGitHash hash
= g_Git
.GetHash(m_sRevision
);
363 ret
= git_commit_lookup(&commit
, repository
, (git_oid
*) hash
.m_hash
);
367 ret
= git_commit_tree(&tree
, commit
);
371 ret
= ReadTreeRecursive(*repository
, tree
, treeroot
);
375 this->GetDlgItem(IDC_BUTTON_REVISION
)->SetWindowText(m_sRevision
);
382 git_commit_free(commit
);
385 git_repository_free(repository
);
390 void CRepositoryBrowser::OnTvnSelchangedRepoTree(NMHDR
*pNMHDR
, LRESULT
*pResult
)
392 LPNMTREEVIEW pNMTreeView
= reinterpret_cast<LPNMTREEVIEW
>(pNMHDR
);
395 FillListCtrlForTreeNode(pNMTreeView
->itemNew
.hItem
);
398 void CRepositoryBrowser::FillListCtrlForTreeNode(HTREEITEM treeNode
)
400 m_RepoList
.DeleteAllItems();
402 CShadowFilesTree
* pTree
= (CShadowFilesTree
*)(m_RepoTree
.GetItemData(treeNode
));
408 FillListCtrlForShadowTree(pTree
);
411 void CRepositoryBrowser::FillListCtrlForShadowTree(CShadowFilesTree
* pTree
)
413 for (TShadowFilesTreeMap::iterator itShadowTree
= pTree
->m_ShadowTree
.begin(); itShadowTree
!= pTree
->m_ShadowTree
.end(); ++itShadowTree
)
415 int icon
= m_nIconFolder
;
416 if (!(*itShadowTree
).second
.m_bFolder
)
417 icon
= SYS_IMAGE_LIST().GetFileIconIndex((*itShadowTree
).second
.m_sName
);
419 int indexItem
= m_RepoList
.InsertItem(m_RepoList
.GetItemCount(), (*itShadowTree
).second
.m_sName
, icon
);
421 m_RepoList
.SetItemData(indexItem
, (DWORD_PTR
)&(*itShadowTree
).second
);
422 if (!(*itShadowTree
).second
.m_bFolder
)
426 temp
= CPathUtils::GetFileExtFromPath((*itShadowTree
).second
.m_sName
);
427 m_RepoList
.SetItemText(indexItem
, eCol_Extension
, temp
);
429 StrFormatByteSize((*itShadowTree
).second
.m_iSize
, temp
.GetBuffer(20), 20);
430 temp
.ReleaseBuffer();
431 m_RepoList
.SetItemText(indexItem
, eCol_FileSize
, temp
);
435 CRepoListCompareFunc
compareFunc(&m_RepoList
, m_currSortCol
, m_currSortDesc
);
436 m_RepoList
.SortItemsEx(&CRepoListCompareFunc::StaticCompare
, (DWORD_PTR
)&compareFunc
);
438 SetSortArrowA(&m_RepoList
, m_currSortCol
, !m_currSortDesc
);
441 void CRepositoryBrowser::OnContextMenu(CWnd
* pWndFrom
, CPoint point
)
443 if (pWndFrom
== &m_RepoList
)
444 OnContextMenu_RepoList(point
);
447 void CRepositoryBrowser::OnContextMenu_RepoList(CPoint point
)
449 TShadowFilesTreeList selectedLeafs
;
450 selectedLeafs
.reserve(m_RepoList
.GetSelectedCount());
451 POSITION pos
= m_RepoList
.GetFirstSelectedItemPosition();
454 selectedLeafs
.push_back((CShadowFilesTree
*)m_RepoList
.GetItemData(m_RepoList
.GetNextSelectedItem(pos
)));
458 popupMenu
.CreatePopupMenu();
460 bool bAddSeparator
= false;
462 if (selectedLeafs
.size() == 1)
465 temp
.LoadString(IDS_MENULOG
);
466 popupMenu
.AppendMenuIcon(eCmd_ViewLog
, temp
, IDI_LOG
);
467 bAddSeparator
= true;
470 eCmd cmd
= (eCmd
)popupMenu
.TrackPopupMenuEx(TPM_LEFTALIGN
|TPM_RETURNCMD
, point
.x
, point
.y
, this, 0);
476 sCmd
.Format(_T("/command:log /path:\"%s%s\""), g_Git
.m_CurrentDir
, selectedLeafs
.at(0)->GetFullName());
477 CAppUtils::RunTortoiseProc(sCmd
);
483 BOOL
CRepositoryBrowser::PreTranslateMessage(MSG
* pMsg
)
485 if (pMsg
->message
== WM_KEYDOWN
)
487 switch (pMsg
->wParam
)
497 return CResizableStandAloneDialog::PreTranslateMessage(pMsg
);
500 void CRepositoryBrowser::OnLvnColumnclickRepoList(NMHDR
*pNMHDR
, LRESULT
*pResult
)
502 LPNMLISTVIEW pNMLV
= reinterpret_cast<LPNMLISTVIEW
>(pNMHDR
);
506 if (m_currSortCol
== pNMLV
->iSubItem
)
507 m_currSortDesc
= !m_currSortDesc
;
510 m_currSortCol
= pNMLV
->iSubItem
;
511 m_currSortDesc
= false;
514 CRepoListCompareFunc
compareFunc(&m_RepoList
, m_currSortCol
, m_currSortDesc
);
515 m_RepoList
.SortItemsEx(&CRepoListCompareFunc::StaticCompare
, (DWORD_PTR
)&compareFunc
);
517 SetSortArrowA(&m_RepoList
, m_currSortCol
, !m_currSortDesc
);
520 void CRepositoryBrowser::OnBnClickedButtonRevision()
522 // use the git log to allow selection of a version
524 // tell the dialog to use mode for selecting revisions
526 // only one revision must be selected however
527 dlg
.SingleSelection(true);
528 if (dlg
.DoModal() == IDOK
)
530 // get selected hash if any
531 m_sRevision
= dlg
.GetSelectedHash();
536 void CRepositoryBrowser::SaveDividerPosition()
539 GetDlgItem(IDC_REPOTREE
)->GetClientRect(&rc
);
540 CRegDWORD xPos
= CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RepobrowserDivider"));
541 xPos
= rc
.right
- rc
.left
;
544 void CRepositoryBrowser::HandleDividerMove(CPoint point
, bool bDraw
)
546 RECT rect
, tree
, list
, treelist
, treelistclient
;
548 // create an union of the tree and list control rectangle
549 GetDlgItem(IDC_REPOLIST
)->GetWindowRect(&list
);
550 GetDlgItem(IDC_REPOTREE
)->GetWindowRect(&tree
);
551 UnionRect(&treelist
, &tree
, &list
);
552 treelistclient
= treelist
;
553 ScreenToClient(&treelistclient
);
555 ClientToScreen(&point
);
556 GetClientRect(&rect
);
557 ClientToScreen(&rect
);
559 CPoint point2
= point
;
560 if (point2
.x
< treelist
.left
+ REPOBROWSER_CTRL_MIN_WIDTH
)
561 point2
.x
= treelist
.left
+ REPOBROWSER_CTRL_MIN_WIDTH
;
562 if (point2
.x
> treelist
.right
- REPOBROWSER_CTRL_MIN_WIDTH
)
563 point2
.x
= treelist
.right
- REPOBROWSER_CTRL_MIN_WIDTH
;
565 point
.x
-= rect
.left
;
566 point
.y
-= treelist
.top
;
568 OffsetRect(&treelist
, -treelist
.left
, -treelist
.top
);
570 if (point
.x
< treelist
.left
+REPOBROWSER_CTRL_MIN_WIDTH
)
571 point
.x
= treelist
.left
+REPOBROWSER_CTRL_MIN_WIDTH
;
572 if (point
.x
> treelist
.right
-REPOBROWSER_CTRL_MIN_WIDTH
)
573 point
.x
= treelist
.right
-REPOBROWSER_CTRL_MIN_WIDTH
;
578 DrawXorBar(pDC
, oldx
+ 2, treelistclient
.top
, 4, treelistclient
.bottom
- treelistclient
.top
- 2);
585 //position the child controls
586 GetDlgItem(IDC_REPOTREE
)->GetWindowRect(&treelist
);
587 treelist
.right
= point2
.x
- 2;
588 ScreenToClient(&treelist
);
589 RemoveAnchor(IDC_REPOTREE
);
590 GetDlgItem(IDC_REPOTREE
)->MoveWindow(&treelist
);
591 GetDlgItem(IDC_REPOLIST
)->GetWindowRect(&treelist
);
592 treelist
.left
= point2
.x
+ 2;
593 ScreenToClient(&treelist
);
594 RemoveAnchor(IDC_REPOLIST
);
595 GetDlgItem(IDC_REPOLIST
)->MoveWindow(&treelist
);
597 AddAnchor(IDC_REPOTREE
, TOP_LEFT
, BOTTOM_LEFT
);
598 AddAnchor(IDC_REPOLIST
, TOP_LEFT
, BOTTOM_RIGHT
);
601 void CRepositoryBrowser::OnMouseMove(UINT nFlags
, CPoint point
)
603 if (bDragMode
== FALSE
)
606 RECT rect
, tree
, list
, treelist
, treelistclient
;
607 // create an union of the tree and list control rectangle
608 GetDlgItem(IDC_REPOLIST
)->GetWindowRect(&list
);
609 GetDlgItem(IDC_REPOTREE
)->GetWindowRect(&tree
);
610 UnionRect(&treelist
, &tree
, &list
);
611 treelistclient
= treelist
;
612 ScreenToClient(&treelistclient
);
614 //convert the mouse coordinates relative to the top-left of
616 ClientToScreen(&point
);
617 GetClientRect(&rect
);
618 ClientToScreen(&rect
);
619 point
.x
-= rect
.left
;
620 point
.y
-= treelist
.top
;
622 //same for the window coordinates - make them relative to 0,0
623 OffsetRect(&treelist
, -treelist
.left
, -treelist
.top
);
625 if (point
.x
< treelist
.left
+ REPOBROWSER_CTRL_MIN_WIDTH
)
626 point
.x
= treelist
.left
+ REPOBROWSER_CTRL_MIN_WIDTH
;
627 if (point
.x
> treelist
.right
- REPOBROWSER_CTRL_MIN_WIDTH
)
628 point
.x
= treelist
.right
- REPOBROWSER_CTRL_MIN_WIDTH
;
630 if ((nFlags
& MK_LBUTTON
) && (point
.x
!= oldx
))
636 DrawXorBar(pDC
, oldx
+ 2, treelistclient
.top
, 4, treelistclient
.bottom
- treelistclient
.top
- 2);
637 DrawXorBar(pDC
, point
.x
+ 2, treelistclient
.top
, 4, treelistclient
.bottom
- treelistclient
.top
- 2);
646 CStandAloneDialogTmpl
<CResizableDialog
>::OnMouseMove(nFlags
, point
);
649 void CRepositoryBrowser::OnLButtonDown(UINT nFlags
, CPoint point
)
651 RECT rect
, tree
, list
, treelist
, treelistclient
;
653 // create an union of the tree and list control rectangle
654 GetDlgItem(IDC_REPOLIST
)->GetWindowRect(&list
);
655 GetDlgItem(IDC_REPOTREE
)->GetWindowRect(&tree
);
656 UnionRect(&treelist
, &tree
, &list
);
657 treelistclient
= treelist
;
658 ScreenToClient(&treelistclient
);
660 //convert the mouse coordinates relative to the top-left of
662 ClientToScreen(&point
);
663 GetClientRect(&rect
);
664 ClientToScreen(&rect
);
665 point
.x
-= rect
.left
;
666 point
.y
-= treelist
.top
;
668 //same for the window coordinates - make them relative to 0,0
669 OffsetRect(&treelist
, -treelist
.left
, -treelist
.top
);
671 if (point
.x
< treelist
.left
+ REPOBROWSER_CTRL_MIN_WIDTH
)
672 return CStandAloneDialogTmpl
< CResizableDialog
>::OnLButtonDown(nFlags
, point
);
673 if (point
.x
> treelist
.right
- 3)
674 return CStandAloneDialogTmpl
< CResizableDialog
>::OnLButtonDown(nFlags
, point
);
675 if (point
.x
> treelist
.right
- REPOBROWSER_CTRL_MIN_WIDTH
)
676 point
.x
= treelist
.right
- REPOBROWSER_CTRL_MIN_WIDTH
;
678 if ((point
.y
< treelist
.top
+ 3) || (point
.y
> treelist
.bottom
- 3))
679 return CStandAloneDialogTmpl
<CResizableDialog
>::OnLButtonDown(nFlags
, point
);
686 DrawXorBar(pDC
, point
.x
+ 2, treelistclient
.top
, 4, treelistclient
.bottom
- treelistclient
.top
- 2);
692 CStandAloneDialogTmpl
<CResizableDialog
>::OnLButtonDown(nFlags
, point
);
695 void CRepositoryBrowser::OnLButtonUp(UINT nFlags
, CPoint point
)
697 if (bDragMode
== FALSE
)
700 HandleDividerMove(point
, true);
705 CStandAloneDialogTmpl
<CResizableDialog
>::OnLButtonUp(nFlags
, point
);
708 void CRepositoryBrowser::OnCaptureChanged(CWnd
*pWnd
)
712 __super::OnCaptureChanged(pWnd
);
715 void CRepositoryBrowser::DrawXorBar(CDC
* pDC
, int x1
, int y1
, int width
, int height
)
717 static WORD _dotPatternBmp
[8] =
719 0x0055, 0x00aa, 0x0055, 0x00aa,
720 0x0055, 0x00aa, 0x0055, 0x00aa
724 HBRUSH hbr
, hbrushOld
;
726 hbm
= CreateBitmap(8, 8, 1, 1, _dotPatternBmp
);
727 hbr
= CreatePatternBrush(hbm
);
729 pDC
->SetBrushOrg(x1
, y1
);
730 hbrushOld
= (HBRUSH
)pDC
->SelectObject(hbr
);
732 PatBlt(pDC
->GetSafeHdc(), x1
, y1
, width
, height
, PATINVERT
);
734 pDC
->SelectObject(hbrushOld
);
740 BOOL
CRepositoryBrowser::OnSetCursor(CWnd
* pWnd
, UINT nHitTest
, UINT message
)
746 GetClientRect(&rect
);
749 if (PtInRect(&rect
, pt
))
752 // are we right of the tree control?
753 GetDlgItem(IDC_REPOTREE
)->GetWindowRect(&rect
);
754 if ((pt
.x
> rect
.right
) && (pt
.y
>= rect
.top
+ 3) && (pt
.y
<= rect
.bottom
- 3))
756 // but left of the list control?
757 GetDlgItem(IDC_REPOLIST
)->GetWindowRect(&rect
);
758 if (pt
.x
< rect
.left
)
760 HCURSOR hCur
= LoadCursor(NULL
, MAKEINTRESOURCE(IDC_SIZEWE
));
767 return CStandAloneDialogTmpl
<CResizableDialog
>::OnSetCursor(pWnd
, nHitTest
, message
);