1 // BrowseRefsDlg.cpp : implementation file
5 #include "TortoiseProc.h"
6 #include "BrowseRefsDlg.h"
8 #include "AddRemoteDlg.h"
10 #include "Settings\SettingGitRemote.h"
11 #include "SinglePropSheetDlg.h"
12 #include "MessageBox.h"
13 #include "RefLogDlg.h"
15 void SetSortArrow(CListCtrl
* control
, int nColumn
, bool bAscending
)
20 CHeaderCtrl
* pHeader
= control
->GetHeaderCtrl();
21 HDITEM HeaderItem
= {0};
22 HeaderItem
.mask
= HDI_FORMAT
;
23 for (int i
=0; i
<pHeader
->GetItemCount(); ++i
)
25 pHeader
->GetItem(i
, &HeaderItem
);
26 HeaderItem
.fmt
&= ~(HDF_SORTDOWN
| HDF_SORTUP
);
27 pHeader
->SetItem(i
, &HeaderItem
);
31 pHeader
->GetItem(nColumn
, &HeaderItem
);
32 HeaderItem
.fmt
|= (bAscending
? HDF_SORTUP
: HDF_SORTDOWN
);
33 pHeader
->SetItem(nColumn
, &HeaderItem
);
37 // CBrowseRefsDlg dialog
39 IMPLEMENT_DYNAMIC(CBrowseRefsDlg
, CResizableStandAloneDialog
)
41 CBrowseRefsDlg::CBrowseRefsDlg(CString cmdPath
, CWnd
* pParent
/*=NULL*/)
42 : CResizableStandAloneDialog(CBrowseRefsDlg::IDD
, pParent
),
45 m_currSortDesc(false),
46 m_initialRef(L
"HEAD"),
47 m_pickRef_Kind(gPickRef_All
)
52 CBrowseRefsDlg::~CBrowseRefsDlg()
56 void CBrowseRefsDlg::DoDataExchange(CDataExchange
* pDX
)
58 CDialog::DoDataExchange(pDX
);
59 DDX_Control(pDX
, IDC_TREE_REF
, m_RefTreeCtrl
);
60 DDX_Control(pDX
, IDC_LIST_REF_LEAFS
, m_ListRefLeafs
);
64 BEGIN_MESSAGE_MAP(CBrowseRefsDlg
, CResizableStandAloneDialog
)
65 ON_BN_CLICKED(IDOK
, &CBrowseRefsDlg::OnBnClickedOk
)
66 ON_NOTIFY(TVN_SELCHANGED
, IDC_TREE_REF
, &CBrowseRefsDlg::OnTvnSelchangedTreeRef
)
68 ON_NOTIFY(LVN_COLUMNCLICK
, IDC_LIST_REF_LEAFS
, &CBrowseRefsDlg::OnLvnColumnclickListRefLeafs
)
70 ON_NOTIFY(NM_DBLCLK
, IDC_LIST_REF_LEAFS
, &CBrowseRefsDlg::OnNMDblclkListRefLeafs
)
74 // CBrowseRefsDlg message handlers
76 void CBrowseRefsDlg::OnBnClickedOk()
81 BOOL
CBrowseRefsDlg::OnInitDialog()
83 CResizableStandAloneDialog::OnInitDialog();
85 AddAnchor(IDC_TREE_REF
, TOP_LEFT
, BOTTOM_LEFT
);
86 AddAnchor(IDC_LIST_REF_LEAFS
, TOP_LEFT
, BOTTOM_RIGHT
);
88 m_ListRefLeafs
.SetExtendedStyle(m_ListRefLeafs
.GetExtendedStyle()|LVS_EX_FULLROWSELECT
);
89 m_ListRefLeafs
.InsertColumn(eCol_Name
, L
"Name",0,150);
90 m_ListRefLeafs
.InsertColumn(eCol_Date
, L
"Date Last Commit",0,100);
91 m_ListRefLeafs
.InsertColumn(eCol_Msg
, L
"Last Commit",0,300);
92 m_ListRefLeafs
.InsertColumn(eCol_Hash
, L
"Hash",0,80);
94 AddAnchor(IDOK
,BOTTOM_RIGHT
);
95 AddAnchor(IDCANCEL
,BOTTOM_RIGHT
);
97 Refresh(m_initialRef
);
99 EnableSaveRestore(L
"BrowseRefs");
102 m_ListRefLeafs
.SetFocus();
106 CShadowTree
* CShadowTree::GetNextSub(CString
& nameLeft
, bool bCreateIfNotExist
)
108 int posSlash
=nameLeft
.Find('/');
113 nameLeft
.Empty();//Nothing left
117 nameSub
=nameLeft
.Left(posSlash
);
118 nameLeft
=nameLeft
.Mid(posSlash
+1);
120 if(nameSub
.IsEmpty())
123 if(!bCreateIfNotExist
&& m_ShadowTree
.find(nameSub
)==m_ShadowTree
.end())
126 CShadowTree
& nextNode
=m_ShadowTree
[nameSub
];
127 nextNode
.m_csRefName
=nameSub
;
128 nextNode
.m_pParent
=this;
132 CShadowTree
* CShadowTree::FindLeaf(CString partialRefName
)
136 if(m_csRefName
.GetLength() > partialRefName
.GetLength())
138 if(partialRefName
.Right(m_csRefName
.GetLength()) == m_csRefName
)
140 //Match of leaf name. Try match on total name.
141 CString totalRefName
= GetRefName();
142 if(totalRefName
.Right(partialRefName
.GetLength()) == partialRefName
)
143 return this; //Also match. Found.
148 //Not a leaf. Search all nodes.
149 for(TShadowTreeMap::iterator itShadowTree
= m_ShadowTree
.begin(); itShadowTree
!= m_ShadowTree
.end(); ++itShadowTree
)
151 CShadowTree
* pSubtree
= itShadowTree
->second
.FindLeaf(partialRefName
);
153 return pSubtree
; //Found
156 return NULL
;//Not found
160 typedef std::map
<CString
,CString
> MAP_STRING_STRING
;
162 CString
CBrowseRefsDlg::GetSelectedRef(bool onlyIfLeaf
)
164 POSITION pos
=m_ListRefLeafs
.GetFirstSelectedItemPosition();
165 //List ctrl selection?
169 CShadowTree
* pTree
=(CShadowTree
*)m_ListRefLeafs
.GetItemData(
170 m_ListRefLeafs
.GetNextSelectedItem(pos
));
171 return pTree
->GetRefName();
175 //Tree ctrl selection?
176 HTREEITEM hTree
=m_RefTreeCtrl
.GetSelectedItem();
179 CShadowTree
* pTree
=(CShadowTree
*)m_RefTreeCtrl
.GetItemData(hTree
);
180 return pTree
->GetRefName();
183 return CString();//None
186 void CBrowseRefsDlg::Refresh(CString selectRef
)
189 // g_Git.GetMapHashToFriendName(m_RefMap);
191 if(!selectRef
.IsEmpty())
193 if(selectRef
== "HEAD")
196 g_Git
.Run(L
"git symbolic-ref HEAD",&selectRef
,CP_UTF8
);
197 selectRef
.Trim(L
"\r\n\t ");
202 selectRef
= GetSelectedRef(false);
205 m_RefTreeCtrl
.DeleteAllItems();
206 m_ListRefLeafs
.DeleteAllItems();
207 m_TreeRoot
.m_ShadowTree
.clear();
208 m_TreeRoot
.m_csRefName
="refs";
209 // m_TreeRoot.m_csShowName="Refs";
210 m_TreeRoot
.m_hTree
=m_RefTreeCtrl
.InsertItem(L
"Refs",NULL
,NULL
);
211 m_RefTreeCtrl
.SetItemData(m_TreeRoot
.m_hTree
,(DWORD_PTR
)&m_TreeRoot
);
214 g_Git
.Run(L
"git for-each-ref --format="
217 L
"%(authordate:relative)%04"
220 L
"%(authordate:iso8601)",
226 MAP_STRING_STRING refMap
;
228 //First sort on ref name
229 while(!(singleRef
=allRefs
.Tokenize(L
"\r\n",linePos
)).IsEmpty())
232 CString refName
=singleRef
.Tokenize(L
"\04",valuePos
);
233 CString refRest
=singleRef
.Mid(valuePos
);
235 //Use ref based on m_pickRef_Kind
236 if(wcsncmp(refName
,L
"refs/heads",10)==0 && !(m_pickRef_Kind
& gPickRef_Head
) )
238 if(wcsncmp(refName
,L
"refs/tags",9)==0 && !(m_pickRef_Kind
& gPickRef_Tag
) )
240 if(wcsncmp(refName
,L
"refs/remotes",12)==0 && !(m_pickRef_Kind
& gPickRef_Remote
) )
243 refMap
[refName
] = refRest
; //Use
249 for(MAP_STRING_STRING::iterator iterRefMap
=refMap
.begin();iterRefMap
!=refMap
.end();++iterRefMap
)
251 CShadowTree
& treeLeaf
=GetTreeNode(iterRefMap
->first
,NULL
,true);
252 CString values
=iterRefMap
->second
;
255 treeLeaf
.m_csRefHash
= values
.Tokenize(L
"\04",valuePos
);
256 treeLeaf
.m_csDate
= values
.Tokenize(L
"\04",valuePos
);
257 treeLeaf
.m_csSubject
= values
.Tokenize(L
"\04",valuePos
);
258 treeLeaf
.m_csAuthor
= values
.Tokenize(L
"\04",valuePos
);
259 treeLeaf
.m_csDate_Iso8601
= values
.Tokenize(L
"\04",valuePos
);
263 if(selectRef
.IsEmpty() || !SelectRef(selectRef
, false))
264 //Probably not on a branch. Select root node.
265 m_RefTreeCtrl
.Expand(m_TreeRoot
.m_hTree
,TVE_EXPAND
);
269 bool CBrowseRefsDlg::SelectRef(CString refName
, bool bExactMatch
)
272 refName
= GetFullRefName(refName
);
273 if(wcsnicmp(refName
,L
"refs/",5)!=0)
274 return false; // Not a ref name
276 CShadowTree
& treeLeafHead
=GetTreeNode(refName
,NULL
,false);
277 if(treeLeafHead
.m_hTree
!= NULL
)
279 //Not a leaf. Select tree node and return
280 m_RefTreeCtrl
.Select(treeLeafHead
.m_hTree
,TVGN_CARET
);
284 if(treeLeafHead
.m_pParent
==NULL
)
285 return false; //Weird... should not occur.
287 //This is the current head.
288 m_RefTreeCtrl
.Select(treeLeafHead
.m_pParent
->m_hTree
,TVGN_CARET
);
290 for(int indexPos
= 0; indexPos
< m_ListRefLeafs
.GetItemCount(); ++indexPos
)
292 CShadowTree
* pCurrShadowTree
= (CShadowTree
*)m_ListRefLeafs
.GetItemData(indexPos
);
293 if(pCurrShadowTree
== &treeLeafHead
)
295 m_ListRefLeafs
.SetItemState(indexPos
,LVIS_SELECTED
,LVIS_SELECTED
);
296 m_ListRefLeafs
.EnsureVisible(indexPos
,FALSE
);
303 CShadowTree
& CBrowseRefsDlg::GetTreeNode(CString refName
, CShadowTree
* pTreePos
, bool bCreateIfNotExist
)
307 if(wcsnicmp(refName
,L
"refs/",5)==0)
308 refName
=refName
.Mid(5);
309 pTreePos
=&m_TreeRoot
;
311 if(refName
.IsEmpty())
312 return *pTreePos
;//Found leaf
314 CShadowTree
* pNextTree
=pTreePos
->GetNextSub(refName
,bCreateIfNotExist
);
317 //Should not occur when all ref-names are valid and bCreateIfNotExist is true.
318 ASSERT(!bCreateIfNotExist
);
322 if(!refName
.IsEmpty())
324 //When the refName is not empty, this node is not a leaf, so lets add it to the tree control.
325 //Leafs are for the list control.
326 if(pNextTree
->m_hTree
==NULL
)
328 //New tree. Create node in control.
329 pNextTree
->m_hTree
=m_RefTreeCtrl
.InsertItem(pNextTree
->m_csRefName
,pTreePos
->m_hTree
,NULL
);
330 m_RefTreeCtrl
.SetItemData(pNextTree
->m_hTree
,(DWORD_PTR
)pNextTree
);
334 return GetTreeNode(refName
, pNextTree
, bCreateIfNotExist
);
338 void CBrowseRefsDlg::OnTvnSelchangedTreeRef(NMHDR
*pNMHDR
, LRESULT
*pResult
)
340 LPNMTREEVIEW pNMTreeView
= reinterpret_cast<LPNMTREEVIEW
>(pNMHDR
);
343 FillListCtrlForTreeNode(pNMTreeView
->itemNew
.hItem
);
346 void CBrowseRefsDlg::FillListCtrlForTreeNode(HTREEITEM treeNode
)
348 m_ListRefLeafs
.DeleteAllItems();
350 m_currSortDesc
= false;
351 SetSortArrow(&m_ListRefLeafs
,-1,false);
353 CShadowTree
* pTree
=(CShadowTree
*)(m_RefTreeCtrl
.GetItemData(treeNode
));
359 FillListCtrlForShadowTree(pTree
,L
"",true);
362 void CBrowseRefsDlg::FillListCtrlForShadowTree(CShadowTree
* pTree
, CString refNamePrefix
, bool isFirstLevel
)
366 int indexItem
=m_ListRefLeafs
.InsertItem(m_ListRefLeafs
.GetItemCount(),L
"");
368 m_ListRefLeafs
.SetItemData(indexItem
,(DWORD_PTR
)pTree
);
369 m_ListRefLeafs
.SetItemText(indexItem
,eCol_Name
, refNamePrefix
+pTree
->m_csRefName
);
370 m_ListRefLeafs
.SetItemText(indexItem
,eCol_Date
, pTree
->m_csDate
);
371 m_ListRefLeafs
.SetItemText(indexItem
,eCol_Msg
, pTree
->m_csSubject
);
372 m_ListRefLeafs
.SetItemText(indexItem
,eCol_Hash
, pTree
->m_csRefHash
);
379 csThisName
=refNamePrefix
+pTree
->m_csRefName
+L
"/";
380 for(CShadowTree::TShadowTreeMap::iterator itSubTree
=pTree
->m_ShadowTree
.begin(); itSubTree
!=pTree
->m_ShadowTree
.end(); ++itSubTree
)
382 FillListCtrlForShadowTree(&itSubTree
->second
,csThisName
,false);
387 bool CBrowseRefsDlg::ConfirmDeleteRef(CString completeRefName
)
392 UINT mbIcon
=MB_ICONQUESTION
;
393 csMessage
=L
"Are you sure you want to delete the ";
394 if(wcsncmp(completeRefName
,L
"refs/heads",10)==0)
396 CString branchToDelete
= completeRefName
.Mid(11);
397 csTitle
.Format(L
"Confirm deletion of branch %s", branchToDelete
);
398 csMessage
+= "branch:\r\n\r\n<b>";
399 csMessage
+= branchToDelete
;
402 //Check if branch is fully merged in HEAD
403 CString branchHash
= g_Git
.GetHash(completeRefName
);
404 CString commonAncestor
;
406 cmd
.Format(L
"git.exe merge-base HEAD %s",completeRefName
);
407 g_Git
.Run(cmd
,&commonAncestor
,CP_UTF8
);
409 branchHash
=branchHash
.Left(40);
410 commonAncestor
=commonAncestor
.Left(40);
412 if(commonAncestor
!= branchHash
)
414 csMessage
+= L
"\r\n\r\n<b>Warning:\r\nThis branch is not fully merged into HEAD.</b>";
415 mbIcon
=MB_ICONWARNING
;
418 else if(wcsncmp(completeRefName
,L
"refs/tags",9)==0)
420 CString tagToDelete
= completeRefName
.Mid(10);
421 csTitle
.Format(L
"Confirm deletion of tag %s", tagToDelete
);
422 csMessage
+= "tag:\r\n\r\n<b>";
423 csMessage
+= tagToDelete
;
427 return CMessageBox::Show(m_hWnd
,csMessage
,csTitle
,MB_YESNO
|mbIcon
)==IDYES
;
432 bool CBrowseRefsDlg::DoDeleteRef(CString completeRefName
, bool bForce
)
434 if(wcsncmp(completeRefName
,L
"refs/heads",10)==0)
436 CString branchToDelete
= completeRefName
.Mid(11);
438 cmd
.Format(L
"git.exe branch -%c %s",bForce
?L
'D':L
'd',branchToDelete
);
440 if(g_Git
.Run(cmd
,&resultDummy
,CP_UTF8
)!=0)
443 errorMsg
.Format(L
"Could not delete branch %s. Message from git:\r\n\r\n%s",branchToDelete
,resultDummy
);
444 CMessageBox::Show(m_hWnd
,errorMsg
,L
"Error deleting branch",MB_OK
|MB_ICONERROR
);
448 else if(wcsncmp(completeRefName
,L
"refs/tags",9)==0)
450 CString tagToDelete
= completeRefName
.Mid(10);
452 cmd
.Format(L
"git.exe tag -d %s",tagToDelete
);
454 if(g_Git
.Run(cmd
,&resultDummy
,CP_UTF8
)!=0)
457 errorMsg
.Format(L
"Could not delete tag %s. Message from git:\r\n\r\n%s",tagToDelete
,resultDummy
);
458 CMessageBox::Show(m_hWnd
,errorMsg
,L
"Error deleting tag",MB_OK
|MB_ICONERROR
);
465 CString
CBrowseRefsDlg::GetFullRefName(CString partialRefName
)
467 CShadowTree
* pLeaf
= m_TreeRoot
.FindLeaf(partialRefName
);
470 return pLeaf
->GetRefName();
474 void CBrowseRefsDlg::OnContextMenu(CWnd
* pWndFrom
, CPoint point
)
476 if(pWndFrom
==&m_RefTreeCtrl
) OnContextMenu_RefTreeCtrl(point
);
477 else if(pWndFrom
==&m_ListRefLeafs
) OnContextMenu_ListRefLeafs(point
);
480 void CBrowseRefsDlg::OnContextMenu_RefTreeCtrl(CPoint point
)
482 CPoint clientPoint
=point
;
483 m_RefTreeCtrl
.ScreenToClient(&clientPoint
);
485 HTREEITEM hTreeItem
=m_RefTreeCtrl
.HitTest(clientPoint
);
487 m_RefTreeCtrl
.Select(hTreeItem
,TVGN_CARET
);
489 ShowContextMenu(point
,hTreeItem
,VectorPShadowTree());
493 void CBrowseRefsDlg::OnContextMenu_ListRefLeafs(CPoint point
)
495 std::vector
<CShadowTree
*> selectedLeafs
;
496 selectedLeafs
.reserve(m_ListRefLeafs
.GetSelectedCount());
497 POSITION pos
=m_ListRefLeafs
.GetFirstSelectedItemPosition();
500 selectedLeafs
.push_back(
501 (CShadowTree
*)m_ListRefLeafs
.GetItemData(
502 m_ListRefLeafs
.GetNextSelectedItem(pos
)));
505 ShowContextMenu(point
,m_RefTreeCtrl
.GetSelectedItem(),selectedLeafs
);
508 void CBrowseRefsDlg::ShowContextMenu(CPoint point
, HTREEITEM hTreePos
, VectorPShadowTree
& selectedLeafs
)
511 popupMenu
.CreatePopupMenu();
513 if(selectedLeafs
.size()==1)
515 bool bShowReflogOption
= false;
516 popupMenu
.AppendMenu(MF_STRING
,eCmd_ViewLog
,L
"View log");
517 if(selectedLeafs
[0]->IsFrom(L
"refs/heads"))
519 popupMenu
.AppendMenu(MF_STRING
,eCmd_DeleteBranch
,L
"Delete Branch");
520 bShowReflogOption
= true;
522 else if(selectedLeafs
[0]->IsFrom(L
"refs/remotes"))
524 bShowReflogOption
= true;
526 else if(selectedLeafs
[0]->IsFrom(L
"refs/tags"))
528 popupMenu
.AppendMenu(MF_STRING
,eCmd_DeleteTag
,L
"Delete Tag");
531 if(bShowReflogOption
)
532 popupMenu
.AppendMenu(MF_STRING
, eCmd_ShowReflog
, L
"Show Reflog");
537 // CShadowTree* pTree = (CShadowTree*)m_ListRefLeafs.GetItemData(pNMHDR->idFrom);
544 CShadowTree
* pTree
=(CShadowTree
*)m_RefTreeCtrl
.GetItemData(hTreePos
);
545 if(pTree
->IsFrom(L
"refs/remotes"))
547 // popupMenu.AppendMenu(MF_STRING,eCmd_AddRemote,L"Add Remote");
548 if(!m_cmdPath
.IsEmpty())
549 popupMenu
.AppendMenu(MF_STRING
,eCmd_ManageRemotes
,L
"Manage Remotes");
551 else if(pTree
->IsFrom(L
"refs/heads"))
552 popupMenu
.AppendMenu(MF_STRING
,eCmd_CreateBranch
,L
"Create Branch");
553 else if(pTree
->IsFrom(L
"refs/tags"))
554 popupMenu
.AppendMenu(MF_STRING
,eCmd_CreateTag
,L
"Create Tag");
558 eCmd cmd
=(eCmd
)popupMenu
.TrackPopupMenuEx(TPM_LEFTALIGN
|TPM_RETURNCMD
, point
.x
, point
.y
, this, 0);
564 dlg
.SetStartRef(selectedLeafs
[0]->GetRefName());
568 case eCmd_DeleteBranch
:
570 if(ConfirmDeleteRef(selectedLeafs
[0]->GetRefName()))
571 DoDeleteRef(selectedLeafs
[0]->GetRefName(), true);
577 if(ConfirmDeleteRef(selectedLeafs
[0]->GetRefName()))
578 DoDeleteRef(selectedLeafs
[0]->GetRefName(), true);
582 case eCmd_ShowReflog
:
584 CRefLogDlg
refLogDlg(this);
585 refLogDlg
.m_CurrentBranch
= selectedLeafs
[0]->GetRefName();
591 CAddRemoteDlg(this).DoModal();
595 case eCmd_ManageRemotes
:
597 CSinglePropSheetDlg(L
"Git Remote Settings",new CSettingGitRemote(m_cmdPath
),this).DoModal();
598 // CSettingGitRemote W_Remotes(m_cmdPath);
599 // W_Remotes.DoModal();
603 case eCmd_CreateBranch
:
605 CAppUtils::CreateBranchTag(false);
611 CAppUtils::CreateBranchTag(true);
618 BOOL
CBrowseRefsDlg::PreTranslateMessage(MSG
* pMsg
)
620 if (pMsg
->message
== WM_KEYDOWN
)
622 switch (pMsg
->wParam
)
626 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
628 if ( GetDlgItem(IDOK)->IsWindowEnabled() )
630 PostMessage(WM_COMMAND, IDOK);
645 return CResizableStandAloneDialog::PreTranslateMessage(pMsg
);
648 class CRefLeafListCompareFunc
651 CRefLeafListCompareFunc(CListCtrl
* pList
, int col
, bool desc
):m_col(col
),m_desc(desc
),m_pList(pList
){}
653 static int CALLBACK
StaticCompare(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
655 return ((CRefLeafListCompareFunc
*)lParamSort
)->Compare(lParam1
,lParam2
);
658 int Compare(LPARAM lParam1
, LPARAM lParam2
)
661 (CShadowTree
*)m_pList
->GetItemData(lParam1
),
662 (CShadowTree
*)m_pList
->GetItemData(lParam2
));
665 int Compare(CShadowTree
* pLeft
, CShadowTree
* pRight
)
667 int result
=CompareNoDesc(pLeft
,pRight
);
673 int CompareNoDesc(CShadowTree
* pLeft
, CShadowTree
* pRight
)
677 case CBrowseRefsDlg::eCol_Name
: return pLeft
->GetRefName().CompareNoCase(pRight
->GetRefName());
678 case CBrowseRefsDlg::eCol_Date
: return pLeft
->m_csDate_Iso8601
.CompareNoCase(pRight
->m_csDate_Iso8601
);
679 case CBrowseRefsDlg::eCol_Msg
: return pLeft
->m_csSubject
.CompareNoCase(pRight
->m_csSubject
);
680 case CBrowseRefsDlg::eCol_Hash
: return pLeft
->m_csRefHash
.CompareNoCase(pRight
->m_csRefHash
);
693 void CBrowseRefsDlg::OnLvnColumnclickListRefLeafs(NMHDR
*pNMHDR
, LRESULT
*pResult
)
695 LPNMLISTVIEW pNMLV
= reinterpret_cast<LPNMLISTVIEW
>(pNMHDR
);
698 if(m_currSortCol
== pNMLV
->iSubItem
)
699 m_currSortDesc
= !m_currSortDesc
;
702 m_currSortCol
= pNMLV
->iSubItem
;
703 m_currSortDesc
= false;
706 CRefLeafListCompareFunc
compareFunc(&m_ListRefLeafs
, m_currSortCol
, m_currSortDesc
);
707 m_ListRefLeafs
.SortItemsEx(&CRefLeafListCompareFunc::StaticCompare
, (DWORD_PTR
)&compareFunc
);
709 SetSortArrow(&m_ListRefLeafs
,m_currSortCol
,!m_currSortDesc
);
712 void CBrowseRefsDlg::OnDestroy()
714 m_pickedRef
= GetSelectedRef(true);
716 CResizableStandAloneDialog::OnDestroy();
719 void CBrowseRefsDlg::OnNMDblclkListRefLeafs(NMHDR
*pNMHDR
, LRESULT
*pResult
)
721 LPNMITEMACTIVATE pNMItemActivate
= reinterpret_cast<LPNMITEMACTIVATE
>(pNMHDR
);
727 CString
CBrowseRefsDlg::PickRef(bool returnAsHash
, CString initialRef
, int pickRef_Kind
)
729 CBrowseRefsDlg
dlg(CString(),NULL
);
731 dlg
.m_initialRef
= initialRef
;
732 dlg
.m_pickRef_Kind
= pickRef_Kind
;
734 if(dlg
.DoModal() != IDOK
)
737 return dlg
.m_pickedRef
;
740 bool CBrowseRefsDlg::PickRefForCombo(CComboBoxEx
* pComboBox
, int pickRef_Kind
)
743 pComboBox
->GetLBText(pComboBox
->GetCurSel(), origRef
);
744 CString resultRef
= PickRef(false,origRef
,pickRef_Kind
);
745 if(resultRef
.IsEmpty())
747 if(wcsncmp(resultRef
,L
"refs/",5)==0)
748 resultRef
= resultRef
.Mid(5);
749 // if(wcsncmp(resultRef,L"heads/",6)==0)
750 // resultRef = resultRef.Mid(6);
752 //Find closest match of choice in combobox
755 CString comboRefName
;
756 for(int i
= 0; i
< pComboBox
->GetCount(); ++i
)
758 pComboBox
->GetLBText(i
, comboRefName
);
759 if(matchLength
< comboRefName
.GetLength() && resultRef
.Right(comboRefName
.GetLength()) == comboRefName
)
761 matchLength
= comboRefName
.GetLength();
766 pComboBox
->SetCurSel(ixFound
);
768 ASSERT(FALSE
);//No match found. So either pickRef_Kind is wrong or the combobox does not contain the ref specified in the picker (which it should unless the repo has changed before creating the CBrowseRef dialog)