OSDN Git Service

Show selected refs in list ctrl
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / BrowseRefsDlg.cpp
1 // BrowseRefsDlg.cpp : implementation file\r
2 //\r
3 \r
4 #include "stdafx.h"\r
5 #include "TortoiseProc.h"\r
6 #include "BrowseRefsDlg.h"\r
7 \r
8 \r
9 // CBrowseRefsDlg dialog\r
10 \r
11 IMPLEMENT_DYNAMIC(CBrowseRefsDlg, CResizableStandAloneDialog)\r
12 \r
13 CBrowseRefsDlg::CBrowseRefsDlg(CWnd* pParent /*=NULL*/)\r
14         : CResizableStandAloneDialog(CBrowseRefsDlg::IDD, pParent)\r
15 {\r
16 \r
17 }\r
18 \r
19 CBrowseRefsDlg::~CBrowseRefsDlg()\r
20 {\r
21 }\r
22 \r
23 void CBrowseRefsDlg::DoDataExchange(CDataExchange* pDX)\r
24 {\r
25         CDialog::DoDataExchange(pDX);\r
26         DDX_Control(pDX, IDC_TREE_REF,                  m_RefTreeCtrl);\r
27         DDX_Control(pDX, IDC_LIST_REF_LEAFS,    m_ListRefLeafs);\r
28 }\r
29 \r
30 \r
31 BEGIN_MESSAGE_MAP(CBrowseRefsDlg, CResizableStandAloneDialog)\r
32         ON_BN_CLICKED(IDOK, &CBrowseRefsDlg::OnBnClickedOk)\r
33         ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_REF, &CBrowseRefsDlg::OnTvnSelchangedTreeRef)\r
34 END_MESSAGE_MAP()\r
35 \r
36 \r
37 // CBrowseRefsDlg message handlers\r
38 \r
39 void CBrowseRefsDlg::OnBnClickedOk()\r
40 {\r
41         OnOK();\r
42 }\r
43 \r
44 BOOL CBrowseRefsDlg::OnInitDialog()\r
45 {\r
46         CResizableStandAloneDialog::OnInitDialog();\r
47 \r
48         AddAnchor(IDC_TREE_REF, TOP_LEFT, BOTTOM_LEFT);\r
49         AddAnchor(IDC_LIST_REF_LEAFS, TOP_LEFT, BOTTOM_RIGHT);\r
50 \r
51         m_ListRefLeafs.SetExtendedStyle(m_ListRefLeafs.GetExtendedStyle()|LVS_EX_FULLROWSELECT);\r
52         m_ListRefLeafs.InsertColumn(0,L"Name",0,150);\r
53         m_ListRefLeafs.InsertColumn(1,L"Date Last Commit",0,100);\r
54         m_ListRefLeafs.InsertColumn(2,L"Last Commit",0,300);\r
55         m_ListRefLeafs.InsertColumn(3,L"Hash",0,80);\r
56 \r
57         AddAnchor(IDOK,BOTTOM_RIGHT);\r
58         AddAnchor(IDCANCEL,BOTTOM_RIGHT);\r
59 \r
60         Refresh();\r
61 \r
62 \r
63         return TRUE;\r
64 }\r
65 \r
66 CShadowTree* CShadowTree::GetNextSub(CString& nameLeft)\r
67 {\r
68         int posSlash=nameLeft.Find('/');\r
69         CString nameSub;\r
70         if(posSlash<0)\r
71         {\r
72                 nameSub=nameLeft;\r
73                 nameLeft.Empty();//Nothing left\r
74         }\r
75         else\r
76         {\r
77                 nameSub=nameLeft.Left(posSlash);\r
78                 nameLeft=nameLeft.Mid(posSlash+1);\r
79         }\r
80         if(nameSub.IsEmpty())\r
81                 return NULL;\r
82 \r
83         CShadowTree& nextNode=m_ShadowTree[nameSub];\r
84         nextNode.m_csName=nameSub;\r
85         nextNode.m_pParent=this;\r
86         return &nextNode;\r
87 }\r
88 \r
89 typedef std::map<CString,CString> MAP_STRING_STRING;\r
90 \r
91 void CBrowseRefsDlg::Refresh()\r
92 {\r
93         m_RefMap.clear();\r
94         g_Git.GetMapHashToFriendName(m_RefMap);\r
95 \r
96         m_RefTreeCtrl.DeleteAllItems();\r
97         m_TreeRoot.m_ShadowTree.clear();\r
98         m_TreeRoot.m_csName="Refs";\r
99         m_TreeRoot.m_hTree=m_RefTreeCtrl.InsertItem(L"Refs",NULL,NULL);\r
100         m_RefTreeCtrl.SetItemData(m_TreeRoot.m_hTree,(DWORD_PTR)&m_TreeRoot);\r
101 \r
102 \r
103         MAP_STRING_STRING refName;\r
104 \r
105         //First sort on ref name\r
106         for(MAP_HASH_NAME::iterator iterRef=m_RefMap.begin();iterRef!=m_RefMap.end();++iterRef)\r
107                 for(STRING_VECTOR::iterator iterRefName=iterRef->second.begin();iterRefName!=iterRef->second.end();++iterRefName)\r
108                         refName[*iterRefName]=iterRef->first;\r
109 \r
110         //Populate ref tree\r
111         for(MAP_STRING_STRING::iterator iterRefName=refName.begin();iterRefName!=refName.end();++iterRefName)\r
112         {\r
113                 CShadowTree& treeLeaf=GetTreeNode(iterRefName->first);\r
114                 treeLeaf.m_csRef=iterRefName->second;\r
115         }\r
116 \r
117         m_RefTreeCtrl.Expand(m_TreeRoot.m_hTree,TVE_EXPAND);\r
118 \r
119 }\r
120 \r
121 CShadowTree& CBrowseRefsDlg::GetTreeNode(CString refName, CShadowTree* pTreePos)\r
122 {\r
123         if(pTreePos==NULL)\r
124         {\r
125                 if(wcsnicmp(refName,L"refs/",5)==0)\r
126                         refName=refName.Mid(5);\r
127                 pTreePos=&m_TreeRoot;\r
128         }\r
129         if(refName.IsEmpty())\r
130                 return *pTreePos;//Found leaf\r
131 \r
132         CShadowTree* pNextTree=pTreePos->GetNextSub(refName);\r
133         if(pNextTree==NULL)\r
134         {\r
135                 //Should not occur when all ref-names are valid.\r
136                 ASSERT(FALSE);\r
137                 return *pTreePos;\r
138         }\r
139 \r
140         if(!refName.IsEmpty())\r
141         {\r
142                 //When the refName is not empty, this node is not a leaf, so lets add it to the tree control.\r
143                 //Leafs are for the list control.\r
144                 if(pNextTree->m_hTree==NULL)\r
145                 {\r
146                         //New tree. Create node in control.\r
147                         pNextTree->m_hTree=m_RefTreeCtrl.InsertItem(pNextTree->m_csName,pTreePos->m_hTree,NULL);\r
148                         m_RefTreeCtrl.SetItemData(pNextTree->m_hTree,(DWORD_PTR)pNextTree);\r
149                 }\r
150         }\r
151 \r
152         return GetTreeNode(refName,pNextTree);\r
153 }\r
154 \r
155 \r
156 void CBrowseRefsDlg::OnTvnSelchangedTreeRef(NMHDR *pNMHDR, LRESULT *pResult)\r
157 {\r
158         LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);\r
159         *pResult = 0;\r
160 \r
161         FillListCtrlForTreeNode(pNMTreeView->itemNew.hItem);\r
162 }\r
163 \r
164 void CBrowseRefsDlg::FillListCtrlForTreeNode(HTREEITEM treeNode)\r
165 {\r
166         m_ListRefLeafs.DeleteAllItems();\r
167 \r
168         CShadowTree* pTree=(CShadowTree*)(m_RefTreeCtrl.GetItemData(treeNode));\r
169         if(pTree==NULL)\r
170         {\r
171                 ASSERT(FALSE);\r
172                 return;\r
173         }\r
174         FillListCtrlForShadowTree(pTree,L"",true);\r
175 }\r
176 \r
177 void CBrowseRefsDlg::FillListCtrlForShadowTree(CShadowTree* pTree, CString refNamePrefix, bool isFirstLevel)\r
178 {\r
179         if(pTree->IsLeaf())\r
180         {\r
181                 int indexItem=m_ListRefLeafs.InsertItem(m_ListRefLeafs.GetItemCount(),L"");\r
182 \r
183                 m_ListRefLeafs.SetItemData(indexItem,(DWORD_PTR)pTree);\r
184                 m_ListRefLeafs.SetItemText(indexItem,0,refNamePrefix+pTree->m_csName);\r
185                 m_ListRefLeafs.SetItemText(indexItem,3,pTree->m_csRef);\r
186         }\r
187         else\r
188         {\r
189 \r
190                 CString csThisName;\r
191                 if(!isFirstLevel)\r
192                         csThisName=refNamePrefix+pTree->m_csName+L"/";\r
193                 for(CShadowTree::TShadowTreeMap::iterator itSubTree=pTree->m_ShadowTree.begin(); itSubTree!=pTree->m_ShadowTree.end(); ++itSubTree)\r
194                 {\r
195                         FillListCtrlForShadowTree(&itSubTree->second,csThisName,false);\r
196                 }\r
197         }\r
198 }\r