OSDN Git Service

Continued work on BrowserRefsDlg
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / BrowseRefsDlg.cpp
index beaf97e..fe33cc8 100644 (file)
@@ -4,14 +4,15 @@
 #include "stdafx.h"\r
 #include "TortoiseProc.h"\r
 #include "BrowseRefsDlg.h"\r
+#include "LogDlg.h"\r
 \r
 \r
 // CBrowseRefsDlg dialog\r
 \r
-IMPLEMENT_DYNAMIC(CBrowseRefsDlg, CDialog)\r
+IMPLEMENT_DYNAMIC(CBrowseRefsDlg, CResizableStandAloneDialog)\r
 \r
 CBrowseRefsDlg::CBrowseRefsDlg(CWnd* pParent /*=NULL*/)\r
-       : CDialog(CBrowseRefsDlg::IDD, pParent)\r
+       : CResizableStandAloneDialog(CBrowseRefsDlg::IDD, pParent)\r
 {\r
 \r
 }\r
@@ -23,12 +24,15 @@ CBrowseRefsDlg::~CBrowseRefsDlg()
 void CBrowseRefsDlg::DoDataExchange(CDataExchange* pDX)\r
 {\r
        CDialog::DoDataExchange(pDX);\r
-       DDX_Control(pDX, IDC_TREE_REF, m_RefTreeCtrl);\r
+       DDX_Control(pDX, IDC_TREE_REF,                  m_RefTreeCtrl);\r
+       DDX_Control(pDX, IDC_LIST_REF_LEAFS,    m_ListRefLeafs);\r
 }\r
 \r
 \r
-BEGIN_MESSAGE_MAP(CBrowseRefsDlg, CDialog)\r
+BEGIN_MESSAGE_MAP(CBrowseRefsDlg, CResizableStandAloneDialog)\r
        ON_BN_CLICKED(IDOK, &CBrowseRefsDlg::OnBnClickedOk)\r
+       ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_REF, &CBrowseRefsDlg::OnTvnSelchangedTreeRef)\r
+       ON_NOTIFY(NM_RCLICK, IDC_LIST_REF_LEAFS, &CBrowseRefsDlg::OnNMRClickListRefLeafs)\r
 END_MESSAGE_MAP()\r
 \r
 \r
@@ -41,13 +45,24 @@ void CBrowseRefsDlg::OnBnClickedOk()
 \r
 BOOL CBrowseRefsDlg::OnInitDialog()\r
 {\r
-       CDialog::OnInitDialog();\r
+       CResizableStandAloneDialog::OnInitDialog();\r
+\r
+       AddAnchor(IDC_TREE_REF, TOP_LEFT, BOTTOM_LEFT);\r
+       AddAnchor(IDC_LIST_REF_LEAFS, TOP_LEFT, BOTTOM_RIGHT);\r
+\r
+       m_ListRefLeafs.SetExtendedStyle(m_ListRefLeafs.GetExtendedStyle()|LVS_EX_FULLROWSELECT);\r
+       m_ListRefLeafs.InsertColumn(0,L"Name",0,150);\r
+       m_ListRefLeafs.InsertColumn(1,L"Date Last Commit",0,100);\r
+       m_ListRefLeafs.InsertColumn(2,L"Last Commit",0,300);\r
+       m_ListRefLeafs.InsertColumn(3,L"Hash",0,80);\r
+\r
+       AddAnchor(IDOK,BOTTOM_RIGHT);\r
+       AddAnchor(IDCANCEL,BOTTOM_RIGHT);\r
 \r
        Refresh();\r
 \r
 \r
-       return TRUE;  // return TRUE unless you set the focus to a control\r
-       // EXCEPTION: OCX Property Pages should return FALSE\r
+       return TRUE;\r
 }\r
 \r
 CShadowTree* CShadowTree::GetNextSub(CString& nameLeft)\r
@@ -77,8 +92,9 @@ typedef std::map<CString,CString> MAP_STRING_STRING;
 \r
 void CBrowseRefsDlg::Refresh()\r
 {\r
-       m_RefMap.clear();\r
-       g_Git.GetMapHashToFriendName(m_RefMap);\r
+//     m_RefMap.clear();\r
+//     g_Git.GetMapHashToFriendName(m_RefMap);\r
+               \r
 \r
        m_RefTreeCtrl.DeleteAllItems();\r
        m_TreeRoot.m_ShadowTree.clear();\r
@@ -86,23 +102,81 @@ void CBrowseRefsDlg::Refresh()
        m_TreeRoot.m_hTree=m_RefTreeCtrl.InsertItem(L"Refs",NULL,NULL);\r
        m_RefTreeCtrl.SetItemData(m_TreeRoot.m_hTree,(DWORD_PTR)&m_TreeRoot);\r
 \r
+       CString allRefs;\r
+       g_Git.Run(L"git for-each-ref --format="\r
+                         L"%(refname)%04"\r
+                         L"%(objectname)%04"\r
+                         L"%(authordate:relative)%04"\r
+                         L"%(subject)%04"\r
+                         L"%(authorname)",\r
+                         &allRefs,CP_UTF8);\r
+\r
+       int linePos=0;\r
+       CString singleRef;\r
 \r
-       MAP_STRING_STRING refName;\r
+       MAP_STRING_STRING refMap;\r
 \r
        //First sort on ref name\r
-       for(MAP_HASH_NAME::iterator iterRef=m_RefMap.begin();iterRef!=m_RefMap.end();++iterRef)\r
-               for(STRING_VECTOR::iterator iterRefName=iterRef->second.begin();iterRefName!=iterRef->second.end();++iterRefName)\r
-                       refName[*iterRefName]=iterRef->first;\r
+       while(!(singleRef=allRefs.Tokenize(L"\r\n",linePos)).IsEmpty())\r
+       {\r
+               int valuePos=0;\r
+               CString refName=singleRef.Tokenize(L"\04",valuePos);\r
+               CString refRest=singleRef.Mid(valuePos);\r
+               refMap[refName]=refRest;\r
+       }\r
+\r
+\r
+\r
+//     for(MAP_HASH_NAME::iterator iterRef=m_RefMap.begin();iterRef!=m_RefMap.end();++iterRef)\r
+//             for(STRING_VECTOR::iterator iterRefName=iterRef->second.begin();iterRefName!=iterRef->second.end();++iterRefName)\r
+//                     refName[*iterRefName]=iterRef->first;\r
 \r
        //Populate ref tree\r
-       for(MAP_STRING_STRING::iterator iterRefName=refName.begin();iterRefName!=refName.end();++iterRefName)\r
+       for(MAP_STRING_STRING::iterator iterRefMap=refMap.begin();iterRefMap!=refMap.end();++iterRefMap)\r
        {\r
-               CShadowTree& treeLeaf=GetTreeNode(iterRefName->first);\r
-               treeLeaf.m_csRef=iterRefName->second;\r
+               CShadowTree& treeLeaf=GetTreeNode(iterRefMap->first);\r
+               CString values=iterRefMap->second;\r
+\r
+               int valuePos=0;\r
+               treeLeaf.m_csRef=     values.Tokenize(L"\04",valuePos);\r
+               treeLeaf.m_csDate=    values.Tokenize(L"\04",valuePos);\r
+               treeLeaf.m_csSubject= values.Tokenize(L"\04",valuePos);\r
+               treeLeaf.m_csAuthor=  values.Tokenize(L"\04",valuePos);\r
        }\r
 \r
-       m_RefTreeCtrl.Expand(m_TreeRoot.m_hTree,TVE_EXPAND);\r
+       CString currHead;\r
+       g_Git.Run(L"git symbolic-ref HEAD",&currHead,CP_UTF8);\r
+\r
+       currHead.Trim(L"\r\n\t ");\r
+\r
+       if(!SelectRef(currHead))\r
+               //Probably not on a branch. Select root node.\r
+               m_RefTreeCtrl.Expand(m_TreeRoot.m_hTree,TVE_EXPAND);\r
+\r
+}\r
+\r
+bool CBrowseRefsDlg::SelectRef(CString refName)\r
+{\r
+       if(wcsnicmp(refName,L"refs/",5)!=0)\r
+               return false; // Not a ref name\r
+\r
+       CShadowTree& treeLeafHead=GetTreeNode(refName);\r
+       if(treeLeafHead.m_pParent==NULL)\r
+               return false; //Weird... should not occur.\r
+\r
+       //This is the current head.\r
+       m_RefTreeCtrl.Select(treeLeafHead.m_pParent->m_hTree,TVGN_CARET);\r
+\r
+       for(int indexPos = 0; indexPos < m_ListRefLeafs.GetItemCount(); ++indexPos)\r
+       {\r
+               CShadowTree* pCurrShadowTree = (CShadowTree*)m_ListRefLeafs.GetItemData(indexPos);\r
+               if(pCurrShadowTree == &treeLeafHead)\r
+               {\r
+                       m_ListRefLeafs.SetItemState(indexPos,LVIS_SELECTED,LVIS_SELECTED);\r
+               }\r
+       }\r
 \r
+       return true;\r
 }\r
 \r
 CShadowTree& CBrowseRefsDlg::GetTreeNode(CString refName, CShadowTree* pTreePos)\r
@@ -123,13 +197,94 @@ CShadowTree& CBrowseRefsDlg::GetTreeNode(CString refName, CShadowTree* pTreePos)
                ASSERT(FALSE);\r
                return *pTreePos;\r
        }\r
-       if(pNextTree->m_hTree==NULL)\r
+\r
+       if(!refName.IsEmpty())\r
        {\r
-               //New tree. Create node in control.\r
-               pNextTree->m_hTree=m_RefTreeCtrl.InsertItem(pNextTree->m_csName,pTreePos->m_hTree,NULL);\r
-               m_RefTreeCtrl.SetItemData(pNextTree->m_hTree,(DWORD_PTR)pNextTree);\r
+               //When the refName is not empty, this node is not a leaf, so lets add it to the tree control.\r
+               //Leafs are for the list control.\r
+               if(pNextTree->m_hTree==NULL)\r
+               {\r
+                       //New tree. Create node in control.\r
+                       pNextTree->m_hTree=m_RefTreeCtrl.InsertItem(pNextTree->m_csName,pTreePos->m_hTree,NULL);\r
+                       m_RefTreeCtrl.SetItemData(pNextTree->m_hTree,(DWORD_PTR)pNextTree);\r
+               }\r
        }\r
 \r
        return GetTreeNode(refName,pNextTree);\r
 }\r
 \r
+\r
+void CBrowseRefsDlg::OnTvnSelchangedTreeRef(NMHDR *pNMHDR, LRESULT *pResult)\r
+{\r
+       LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);\r
+       *pResult = 0;\r
+\r
+       FillListCtrlForTreeNode(pNMTreeView->itemNew.hItem);\r
+}\r
+\r
+void CBrowseRefsDlg::FillListCtrlForTreeNode(HTREEITEM treeNode)\r
+{\r
+       m_ListRefLeafs.DeleteAllItems();\r
+\r
+       CShadowTree* pTree=(CShadowTree*)(m_RefTreeCtrl.GetItemData(treeNode));\r
+       if(pTree==NULL)\r
+       {\r
+               ASSERT(FALSE);\r
+               return;\r
+       }\r
+       FillListCtrlForShadowTree(pTree,L"",true);\r
+}\r
+\r
+void CBrowseRefsDlg::FillListCtrlForShadowTree(CShadowTree* pTree, CString refNamePrefix, bool isFirstLevel)\r
+{\r
+       if(pTree->IsLeaf())\r
+       {\r
+               int indexItem=m_ListRefLeafs.InsertItem(m_ListRefLeafs.GetItemCount(),L"");\r
+\r
+               m_ListRefLeafs.SetItemData(indexItem,(DWORD_PTR)pTree);\r
+               m_ListRefLeafs.SetItemText(indexItem,0,refNamePrefix+pTree->m_csName);\r
+               m_ListRefLeafs.SetItemText(indexItem,1,pTree->m_csDate);\r
+               m_ListRefLeafs.SetItemText(indexItem,2,pTree->m_csSubject);\r
+               m_ListRefLeafs.SetItemText(indexItem,3,pTree->m_csRef);\r
+       }\r
+       else\r
+       {\r
+\r
+               CString csThisName;\r
+               if(!isFirstLevel)\r
+                       csThisName=refNamePrefix+pTree->m_csName+L"/";\r
+               for(CShadowTree::TShadowTreeMap::iterator itSubTree=pTree->m_ShadowTree.begin(); itSubTree!=pTree->m_ShadowTree.end(); ++itSubTree)\r
+               {\r
+                       FillListCtrlForShadowTree(&itSubTree->second,csThisName,false);\r
+               }\r
+       }\r
+}\r
+\r
+void CBrowseRefsDlg::OnNMRClickListRefLeafs(NMHDR *pNMHDR, LRESULT *pResult)\r
+{\r
+       LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);\r
+       *pResult = 0;\r
+\r
+       CMenu popupMenu;\r
+       popupMenu.CreatePopupMenu();\r
+       popupMenu.AppendMenu(MF_STRING,eCmd_ViewLog,L"View log");\r
+\r
+       CShadowTree* pTree = (CShadowTree*)m_ListRefLeafs.GetItemData(pNMHDR->idFrom);\r
+       if(pTree==NULL)\r
+               return;\r
+\r
+\r
+       const MSG* pCurrMsg=GetCurrentMessage();\r
+       eCmd cmd=(eCmd)popupMenu.TrackPopupMenuEx(TPM_LEFTALIGN|TPM_RETURNCMD, pCurrMsg->pt.x, pCurrMsg->pt.y, this, 0);\r
+       switch(cmd)\r
+       {\r
+       case eCmd_ViewLog:\r
+               {\r
+                       CLogDlg dlg;\r
+                       theApp.m_pMainWnd = &dlg;\r
+                       dlg.SetParams("", "", pTree->m_csRef, "", "");\r
+                       dlg.DoModal();\r
+               }\r
+               break;\r
+       }\r
+}\r