1 // BrowseRefsDlg.cpp : implementation file
5 #include "TortoiseProc.h"
6 #include "BrowseRefsDlg.h"
8 #include "AddRemoteDlg.h"
9 #include "CreateBranchTagDlg.h"
12 // CBrowseRefsDlg dialog
14 IMPLEMENT_DYNAMIC(CBrowseRefsDlg
, CResizableStandAloneDialog
)
16 CBrowseRefsDlg::CBrowseRefsDlg(CWnd
* pParent
/*=NULL*/)
17 : CResizableStandAloneDialog(CBrowseRefsDlg::IDD
, pParent
)
22 CBrowseRefsDlg::~CBrowseRefsDlg()
26 void CBrowseRefsDlg::DoDataExchange(CDataExchange
* pDX
)
28 CDialog::DoDataExchange(pDX
);
29 DDX_Control(pDX
, IDC_TREE_REF
, m_RefTreeCtrl
);
30 DDX_Control(pDX
, IDC_LIST_REF_LEAFS
, m_ListRefLeafs
);
34 BEGIN_MESSAGE_MAP(CBrowseRefsDlg
, CResizableStandAloneDialog
)
35 ON_BN_CLICKED(IDOK
, &CBrowseRefsDlg::OnBnClickedOk
)
36 ON_NOTIFY(TVN_SELCHANGED
, IDC_TREE_REF
, &CBrowseRefsDlg::OnTvnSelchangedTreeRef
)
41 // CBrowseRefsDlg message handlers
43 void CBrowseRefsDlg::OnBnClickedOk()
48 BOOL
CBrowseRefsDlg::OnInitDialog()
50 CResizableStandAloneDialog::OnInitDialog();
52 AddAnchor(IDC_TREE_REF
, TOP_LEFT
, BOTTOM_LEFT
);
53 AddAnchor(IDC_LIST_REF_LEAFS
, TOP_LEFT
, BOTTOM_RIGHT
);
55 m_ListRefLeafs
.SetExtendedStyle(m_ListRefLeafs
.GetExtendedStyle()|LVS_EX_FULLROWSELECT
);
56 m_ListRefLeafs
.InsertColumn(0,L
"Name",0,150);
57 m_ListRefLeafs
.InsertColumn(1,L
"Date Last Commit",0,100);
58 m_ListRefLeafs
.InsertColumn(2,L
"Last Commit",0,300);
59 m_ListRefLeafs
.InsertColumn(3,L
"Hash",0,80);
61 AddAnchor(IDOK
,BOTTOM_RIGHT
);
62 AddAnchor(IDCANCEL
,BOTTOM_RIGHT
);
70 CShadowTree
* CShadowTree::GetNextSub(CString
& nameLeft
)
72 int posSlash
=nameLeft
.Find('/');
77 nameLeft
.Empty();//Nothing left
81 nameSub
=nameLeft
.Left(posSlash
);
82 nameLeft
=nameLeft
.Mid(posSlash
+1);
87 CShadowTree
& nextNode
=m_ShadowTree
[nameSub
];
88 nextNode
.m_csRefName
=nameSub
;
89 nextNode
.m_pParent
=this;
93 typedef std::map
<CString
,CString
> MAP_STRING_STRING
;
95 void CBrowseRefsDlg::Refresh()
98 // g_Git.GetMapHashToFriendName(m_RefMap);
101 m_RefTreeCtrl
.DeleteAllItems();
102 m_TreeRoot
.m_ShadowTree
.clear();
103 m_TreeRoot
.m_csRefName
="refs";
104 // m_TreeRoot.m_csShowName="Refs";
105 m_TreeRoot
.m_hTree
=m_RefTreeCtrl
.InsertItem(L
"Refs",NULL
,NULL
);
106 m_RefTreeCtrl
.SetItemData(m_TreeRoot
.m_hTree
,(DWORD_PTR
)&m_TreeRoot
);
109 g_Git
.Run(L
"git for-each-ref --format="
112 L
"%(authordate:relative)%04"
120 MAP_STRING_STRING refMap
;
122 //First sort on ref name
123 while(!(singleRef
=allRefs
.Tokenize(L
"\r\n",linePos
)).IsEmpty())
126 CString refName
=singleRef
.Tokenize(L
"\04",valuePos
);
127 CString refRest
=singleRef
.Mid(valuePos
);
128 refMap
[refName
]=refRest
;
133 // for(MAP_HASH_NAME::iterator iterRef=m_RefMap.begin();iterRef!=m_RefMap.end();++iterRef)
134 // for(STRING_VECTOR::iterator iterRefName=iterRef->second.begin();iterRefName!=iterRef->second.end();++iterRefName)
135 // refName[*iterRefName]=iterRef->first;
138 for(MAP_STRING_STRING::iterator iterRefMap
=refMap
.begin();iterRefMap
!=refMap
.end();++iterRefMap
)
140 CShadowTree
& treeLeaf
=GetTreeNode(iterRefMap
->first
);
141 CString values
=iterRefMap
->second
;
144 treeLeaf
.m_csRefHash
= values
.Tokenize(L
"\04",valuePos
);
145 treeLeaf
.m_csDate
= values
.Tokenize(L
"\04",valuePos
);
146 treeLeaf
.m_csSubject
= values
.Tokenize(L
"\04",valuePos
);
147 treeLeaf
.m_csAuthor
= values
.Tokenize(L
"\04",valuePos
);
151 g_Git
.Run(L
"git symbolic-ref HEAD",&currHead
,CP_UTF8
);
153 currHead
.Trim(L
"\r\n\t ");
155 if(!SelectRef(currHead
))
156 //Probably not on a branch. Select root node.
157 m_RefTreeCtrl
.Expand(m_TreeRoot
.m_hTree
,TVE_EXPAND
);
161 bool CBrowseRefsDlg::SelectRef(CString refName
)
163 if(wcsnicmp(refName
,L
"refs/",5)!=0)
164 return false; // Not a ref name
166 CShadowTree
& treeLeafHead
=GetTreeNode(refName
);
167 if(treeLeafHead
.m_pParent
==NULL
)
168 return false; //Weird... should not occur.
170 //This is the current head.
171 m_RefTreeCtrl
.Select(treeLeafHead
.m_pParent
->m_hTree
,TVGN_CARET
);
173 for(int indexPos
= 0; indexPos
< m_ListRefLeafs
.GetItemCount(); ++indexPos
)
175 CShadowTree
* pCurrShadowTree
= (CShadowTree
*)m_ListRefLeafs
.GetItemData(indexPos
);
176 if(pCurrShadowTree
== &treeLeafHead
)
178 m_ListRefLeafs
.SetItemState(indexPos
,LVIS_SELECTED
,LVIS_SELECTED
);
185 CShadowTree
& CBrowseRefsDlg::GetTreeNode(CString refName
, CShadowTree
* pTreePos
)
189 if(wcsnicmp(refName
,L
"refs/",5)==0)
190 refName
=refName
.Mid(5);
191 pTreePos
=&m_TreeRoot
;
193 if(refName
.IsEmpty())
194 return *pTreePos
;//Found leaf
196 CShadowTree
* pNextTree
=pTreePos
->GetNextSub(refName
);
199 //Should not occur when all ref-names are valid.
204 if(!refName
.IsEmpty())
206 //When the refName is not empty, this node is not a leaf, so lets add it to the tree control.
207 //Leafs are for the list control.
208 if(pNextTree
->m_hTree
==NULL
)
210 //New tree. Create node in control.
211 pNextTree
->m_hTree
=m_RefTreeCtrl
.InsertItem(pNextTree
->m_csRefName
,pTreePos
->m_hTree
,NULL
);
212 m_RefTreeCtrl
.SetItemData(pNextTree
->m_hTree
,(DWORD_PTR
)pNextTree
);
216 return GetTreeNode(refName
,pNextTree
);
220 void CBrowseRefsDlg::OnTvnSelchangedTreeRef(NMHDR
*pNMHDR
, LRESULT
*pResult
)
222 LPNMTREEVIEW pNMTreeView
= reinterpret_cast<LPNMTREEVIEW
>(pNMHDR
);
225 FillListCtrlForTreeNode(pNMTreeView
->itemNew
.hItem
);
228 void CBrowseRefsDlg::FillListCtrlForTreeNode(HTREEITEM treeNode
)
230 m_ListRefLeafs
.DeleteAllItems();
232 CShadowTree
* pTree
=(CShadowTree
*)(m_RefTreeCtrl
.GetItemData(treeNode
));
238 FillListCtrlForShadowTree(pTree
,L
"",true);
241 void CBrowseRefsDlg::FillListCtrlForShadowTree(CShadowTree
* pTree
, CString refNamePrefix
, bool isFirstLevel
)
245 int indexItem
=m_ListRefLeafs
.InsertItem(m_ListRefLeafs
.GetItemCount(),L
"");
247 m_ListRefLeafs
.SetItemData(indexItem
,(DWORD_PTR
)pTree
);
248 m_ListRefLeafs
.SetItemText(indexItem
,0,refNamePrefix
+pTree
->m_csRefName
);
249 m_ListRefLeafs
.SetItemText(indexItem
,1,pTree
->m_csDate
);
250 m_ListRefLeafs
.SetItemText(indexItem
,2,pTree
->m_csSubject
);
251 m_ListRefLeafs
.SetItemText(indexItem
,3,pTree
->m_csRefHash
);
258 csThisName
=refNamePrefix
+pTree
->m_csRefName
+L
"/";
259 for(CShadowTree::TShadowTreeMap::iterator itSubTree
=pTree
->m_ShadowTree
.begin(); itSubTree
!=pTree
->m_ShadowTree
.end(); ++itSubTree
)
261 FillListCtrlForShadowTree(&itSubTree
->second
,csThisName
,false);
266 void CBrowseRefsDlg::OnContextMenu_ListRefLeafs(CPoint point
)
269 CPoint clientPoint
=point
;
270 m_RefTreeCtrl
.ScreenToClient(&clientPoint
);
272 int selectedItemCount
=m_ListRefLeafs
.GetSelectedCount();
275 std::vector
<CShadowTree
*> selectedTrees
;
276 selectedTrees
.reserve(selectedItemCount
);
277 POSITION pos
=m_ListRefLeafs
.GetFirstSelectedItemPosition();
280 selectedTrees
.push_back(
281 (CShadowTree
*)m_ListRefLeafs
.GetItemData(
282 m_ListRefLeafs
.GetNextSelectedItem(pos
)));
286 popupMenu
.CreatePopupMenu();
288 if(selectedItemCount
==1)
290 popupMenu
.AppendMenu(MF_STRING
,eCmd_ViewLog
,L
"View log");
292 // CShadowTree* pTree = (CShadowTree*)m_ListRefLeafs.GetItemData(pNMHDR->idFrom);
298 eCmd cmd
=(eCmd
)popupMenu
.TrackPopupMenuEx(TPM_LEFTALIGN
|TPM_RETURNCMD
, point
.x
, point
.y
, this, 0);
304 dlg
.SetStartRef(selectedTrees
[0]->m_csRefHash
);
311 void CBrowseRefsDlg::OnContextMenu(CWnd
* pWndFrom
, CPoint point
)
313 if(pWndFrom
==&m_RefTreeCtrl
) OnContextMenu_RefTreeCtrl(point
);
314 else if(pWndFrom
==&m_ListRefLeafs
) OnContextMenu_ListRefLeafs(point
);
317 void CBrowseRefsDlg::OnContextMenu_RefTreeCtrl(CPoint point
)
320 popupMenu
.CreatePopupMenu();
322 CPoint clientPoint
=point
;
323 m_RefTreeCtrl
.ScreenToClient(&clientPoint
);
325 HTREEITEM hTreeItem
=m_RefTreeCtrl
.HitTest(clientPoint
);
328 m_RefTreeCtrl
.Select(hTreeItem
,TVGN_CARET
);
329 CShadowTree
* pTree
=(CShadowTree
*)m_RefTreeCtrl
.GetItemData(hTreeItem
);
330 if(pTree
->IsFrom(L
"refs/remotes"))
331 popupMenu
.AppendMenu(MF_STRING
,eCmd_AddRemote
,L
"Add Remote");
332 else if(pTree
->IsFrom(L
"refs/heads"))
333 popupMenu
.AppendMenu(MF_STRING
,eCmd_CreateBranch
,L
"Create Branch");
334 else if(pTree
->IsFrom(L
"refs/tags"))
335 popupMenu
.AppendMenu(MF_STRING
,eCmd_CreateTag
,L
"Create Tag");
338 eCmd cmd
=(eCmd
)popupMenu
.TrackPopupMenuEx(TPM_LEFTALIGN
|TPM_RETURNCMD
, point
.x
, point
.y
, this, 0);
343 CAddRemoteDlg(this).DoModal();
347 case eCmd_CreateBranch
:
349 CCreateBranchTagDlg
dlg(this);
357 CCreateBranchTagDlg
dlg(this);
366 BOOL
CBrowseRefsDlg::PreTranslateMessage(MSG
* pMsg
)
368 if (pMsg
->message
== WM_KEYDOWN
)
370 switch (pMsg
->wParam
)
374 if (GetAsyncKeyState(VK_CONTROL)&0x8000)
376 if ( GetDlgItem(IDOK)->IsWindowEnabled() )
378 PostMessage(WM_COMMAND, IDOK);
393 return CResizableStandAloneDialog::PreTranslateMessage(pMsg
);