Show selected refs in list ctrl
[TortoiseGit.git] / src / TortoiseProc / BrowseRefsDlg.cpp
blob50a4fe69d6fd3ad6817f5a7e03243725147fc69b
1 // BrowseRefsDlg.cpp : implementation file
2 //
4 #include "stdafx.h"
5 #include "TortoiseProc.h"
6 #include "BrowseRefsDlg.h"
9 // CBrowseRefsDlg dialog
11 IMPLEMENT_DYNAMIC(CBrowseRefsDlg, CResizableStandAloneDialog)
13 CBrowseRefsDlg::CBrowseRefsDlg(CWnd* pParent /*=NULL*/)
14 : CResizableStandAloneDialog(CBrowseRefsDlg::IDD, pParent)
19 CBrowseRefsDlg::~CBrowseRefsDlg()
23 void CBrowseRefsDlg::DoDataExchange(CDataExchange* pDX)
25 CDialog::DoDataExchange(pDX);
26 DDX_Control(pDX, IDC_TREE_REF, m_RefTreeCtrl);
27 DDX_Control(pDX, IDC_LIST_REF_LEAFS, m_ListRefLeafs);
31 BEGIN_MESSAGE_MAP(CBrowseRefsDlg, CResizableStandAloneDialog)
32 ON_BN_CLICKED(IDOK, &CBrowseRefsDlg::OnBnClickedOk)
33 ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_REF, &CBrowseRefsDlg::OnTvnSelchangedTreeRef)
34 END_MESSAGE_MAP()
37 // CBrowseRefsDlg message handlers
39 void CBrowseRefsDlg::OnBnClickedOk()
41 OnOK();
44 BOOL CBrowseRefsDlg::OnInitDialog()
46 CResizableStandAloneDialog::OnInitDialog();
48 AddAnchor(IDC_TREE_REF, TOP_LEFT, BOTTOM_LEFT);
49 AddAnchor(IDC_LIST_REF_LEAFS, TOP_LEFT, BOTTOM_RIGHT);
51 m_ListRefLeafs.SetExtendedStyle(m_ListRefLeafs.GetExtendedStyle()|LVS_EX_FULLROWSELECT);
52 m_ListRefLeafs.InsertColumn(0,L"Name",0,150);
53 m_ListRefLeafs.InsertColumn(1,L"Date Last Commit",0,100);
54 m_ListRefLeafs.InsertColumn(2,L"Last Commit",0,300);
55 m_ListRefLeafs.InsertColumn(3,L"Hash",0,80);
57 AddAnchor(IDOK,BOTTOM_RIGHT);
58 AddAnchor(IDCANCEL,BOTTOM_RIGHT);
60 Refresh();
63 return TRUE;
66 CShadowTree* CShadowTree::GetNextSub(CString& nameLeft)
68 int posSlash=nameLeft.Find('/');
69 CString nameSub;
70 if(posSlash<0)
72 nameSub=nameLeft;
73 nameLeft.Empty();//Nothing left
75 else
77 nameSub=nameLeft.Left(posSlash);
78 nameLeft=nameLeft.Mid(posSlash+1);
80 if(nameSub.IsEmpty())
81 return NULL;
83 CShadowTree& nextNode=m_ShadowTree[nameSub];
84 nextNode.m_csName=nameSub;
85 nextNode.m_pParent=this;
86 return &nextNode;
89 typedef std::map<CString,CString> MAP_STRING_STRING;
91 void CBrowseRefsDlg::Refresh()
93 m_RefMap.clear();
94 g_Git.GetMapHashToFriendName(m_RefMap);
96 m_RefTreeCtrl.DeleteAllItems();
97 m_TreeRoot.m_ShadowTree.clear();
98 m_TreeRoot.m_csName="Refs";
99 m_TreeRoot.m_hTree=m_RefTreeCtrl.InsertItem(L"Refs",NULL,NULL);
100 m_RefTreeCtrl.SetItemData(m_TreeRoot.m_hTree,(DWORD_PTR)&m_TreeRoot);
103 MAP_STRING_STRING refName;
105 //First sort on ref name
106 for(MAP_HASH_NAME::iterator iterRef=m_RefMap.begin();iterRef!=m_RefMap.end();++iterRef)
107 for(STRING_VECTOR::iterator iterRefName=iterRef->second.begin();iterRefName!=iterRef->second.end();++iterRefName)
108 refName[*iterRefName]=iterRef->first;
110 //Populate ref tree
111 for(MAP_STRING_STRING::iterator iterRefName=refName.begin();iterRefName!=refName.end();++iterRefName)
113 CShadowTree& treeLeaf=GetTreeNode(iterRefName->first);
114 treeLeaf.m_csRef=iterRefName->second;
117 m_RefTreeCtrl.Expand(m_TreeRoot.m_hTree,TVE_EXPAND);
121 CShadowTree& CBrowseRefsDlg::GetTreeNode(CString refName, CShadowTree* pTreePos)
123 if(pTreePos==NULL)
125 if(wcsnicmp(refName,L"refs/",5)==0)
126 refName=refName.Mid(5);
127 pTreePos=&m_TreeRoot;
129 if(refName.IsEmpty())
130 return *pTreePos;//Found leaf
132 CShadowTree* pNextTree=pTreePos->GetNextSub(refName);
133 if(pNextTree==NULL)
135 //Should not occur when all ref-names are valid.
136 ASSERT(FALSE);
137 return *pTreePos;
140 if(!refName.IsEmpty())
142 //When the refName is not empty, this node is not a leaf, so lets add it to the tree control.
143 //Leafs are for the list control.
144 if(pNextTree->m_hTree==NULL)
146 //New tree. Create node in control.
147 pNextTree->m_hTree=m_RefTreeCtrl.InsertItem(pNextTree->m_csName,pTreePos->m_hTree,NULL);
148 m_RefTreeCtrl.SetItemData(pNextTree->m_hTree,(DWORD_PTR)pNextTree);
152 return GetTreeNode(refName,pNextTree);
156 void CBrowseRefsDlg::OnTvnSelchangedTreeRef(NMHDR *pNMHDR, LRESULT *pResult)
158 LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
159 *pResult = 0;
161 FillListCtrlForTreeNode(pNMTreeView->itemNew.hItem);
164 void CBrowseRefsDlg::FillListCtrlForTreeNode(HTREEITEM treeNode)
166 m_ListRefLeafs.DeleteAllItems();
168 CShadowTree* pTree=(CShadowTree*)(m_RefTreeCtrl.GetItemData(treeNode));
169 if(pTree==NULL)
171 ASSERT(FALSE);
172 return;
174 FillListCtrlForShadowTree(pTree,L"",true);
177 void CBrowseRefsDlg::FillListCtrlForShadowTree(CShadowTree* pTree, CString refNamePrefix, bool isFirstLevel)
179 if(pTree->IsLeaf())
181 int indexItem=m_ListRefLeafs.InsertItem(m_ListRefLeafs.GetItemCount(),L"");
183 m_ListRefLeafs.SetItemData(indexItem,(DWORD_PTR)pTree);
184 m_ListRefLeafs.SetItemText(indexItem,0,refNamePrefix+pTree->m_csName);
185 m_ListRefLeafs.SetItemText(indexItem,3,pTree->m_csRef);
187 else
190 CString csThisName;
191 if(!isFirstLevel)
192 csThisName=refNamePrefix+pTree->m_csName+L"/";
193 for(CShadowTree::TShadowTreeMap::iterator itSubTree=pTree->m_ShadowTree.begin(); itSubTree!=pTree->m_ShadowTree.end(); ++itSubTree)
195 FillListCtrlForShadowTree(&itSubTree->second,csThisName,false);