OSDN Git Service

RebaseDlg: Implement Pick squash and edit by context menu
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / RebaseDlg.cpp
1 // RebaseDlg.cpp : implementation file\r
2 //\r
3 \r
4 #include "stdafx.h"\r
5 #include "TortoiseProc.h"\r
6 #include "RebaseDlg.h"\r
7 #include "AppUtils.h"\r
8 \r
9 // CRebaseDlg dialog\r
10 \r
11 IMPLEMENT_DYNAMIC(CRebaseDlg, CResizableStandAloneDialog)\r
12 \r
13 CRebaseDlg::CRebaseDlg(CWnd* pParent /*=NULL*/)\r
14         : CResizableStandAloneDialog(CRebaseDlg::IDD, pParent)\r
15     , m_bPickAll(FALSE)\r
16     , m_bSquashAll(FALSE)\r
17     , m_bEditAll(FALSE)\r
18 {\r
19         m_RebaseStage=CHOOSE_BRANCH;\r
20 }\r
21 \r
22 CRebaseDlg::~CRebaseDlg()\r
23 {\r
24 }\r
25 \r
26 void CRebaseDlg::DoDataExchange(CDataExchange* pDX)\r
27 {\r
28     CDialog::DoDataExchange(pDX);\r
29     DDX_Control(pDX, IDC_REBASE_PROGRESS, m_ProgressBar);\r
30     DDX_Control(pDX, IDC_STATUS_STATIC, m_CtrlStatusText);\r
31     DDX_Check(pDX, IDC_PICK_ALL, m_bPickAll);\r
32     DDX_Check(pDX, IDC_SQUASH_ALL, m_bSquashAll);\r
33     DDX_Check(pDX, IDC_EDIT_ALL, m_bEditAll);\r
34         DDX_Control(pDX, IDC_REBASE_SPLIT, m_wndSplitter);\r
35         DDX_Control(pDX,IDC_COMMIT_LIST,m_CommitList);\r
36         DDX_Control(pDX,IDC_REBASE_COMBOXEX_BRANCH, this->m_BranchCtrl);\r
37         DDX_Control(pDX,IDC_REBASE_COMBOXEX_UPSTREAM,   this->m_UpstreamCtrl);\r
38 \r
39 }\r
40 \r
41 \r
42 BEGIN_MESSAGE_MAP(CRebaseDlg, CResizableStandAloneDialog)\r
43     ON_BN_CLICKED(IDC_PICK_ALL, &CRebaseDlg::OnBnClickedPickAll)\r
44     ON_BN_CLICKED(IDC_SQUASH_ALL, &CRebaseDlg::OnBnClickedSquashAll)\r
45     ON_BN_CLICKED(IDC_EDIT_ALL, &CRebaseDlg::OnBnClickedEditAll)\r
46     ON_BN_CLICKED(IDC_REBASE_SPLIT, &CRebaseDlg::OnBnClickedRebaseSplit)\r
47         ON_WM_SIZE()\r
48         ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_BRANCH,   &CRebaseDlg::OnCbnSelchangeBranch)\r
49         ON_CBN_SELCHANGE(IDC_REBASE_COMBOXEX_UPSTREAM, &CRebaseDlg::OnCbnSelchangeUpstream)\r
50 END_MESSAGE_MAP()\r
51 \r
52 void CRebaseDlg::AddRebaseAnchor()\r
53 {\r
54         AddAnchor(IDC_REBASE_TAB,TOP_LEFT,BOTTOM_RIGHT);\r
55         AddAnchor(IDC_COMMIT_LIST,TOP_LEFT, TOP_RIGHT);\r
56         AddAnchor(IDC_REBASE_SPLIT,TOP_LEFT, TOP_RIGHT);\r
57         AddAnchor(IDC_STATUS_STATIC, BOTTOM_LEFT,BOTTOM_RIGHT);\r
58         AddAnchor(IDC_REBASE_CONTINUE,BOTTOM_RIGHT);\r
59         AddAnchor(IDC_REBASE_ABORT, BOTTOM_RIGHT);\r
60         AddAnchor(IDC_REBASE_PROGRESS,BOTTOM_LEFT, BOTTOM_RIGHT);\r
61         AddAnchor(IDC_PICK_ALL,TOP_LEFT);\r
62         AddAnchor(IDC_SQUASH_ALL,TOP_LEFT);\r
63         AddAnchor(IDC_EDIT_ALL,TOP_LEFT);       \r
64         AddAnchor(IDC_REBASE_COMBOXEX_UPSTREAM,TOP_LEFT);\r
65         AddAnchor(IDC_REBASE_COMBOXEX_BRANCH,TOP_LEFT);\r
66         AddAnchor(IDC_REBASE_STATIC_UPSTREAM,TOP_LEFT);\r
67         AddAnchor(IDC_REBASE_STATIC_BRANCH,TOP_LEFT);\r
68         \r
69 }\r
70 \r
71 BOOL CRebaseDlg::OnInitDialog()\r
72 {\r
73         CResizableStandAloneDialog::OnInitDialog();\r
74 \r
75         CRect rectDummy;\r
76         //IDC_REBASE_DUMY_TAB\r
77         \r
78         GetClientRect(m_DlgOrigRect);\r
79         m_CommitList.GetClientRect(m_CommitListOrigRect);\r
80 \r
81         CWnd *pwnd=this->GetDlgItem(IDC_REBASE_DUMY_TAB);\r
82         pwnd->GetWindowRect(&rectDummy);\r
83 \r
84         rectDummy.top-=20;\r
85         rectDummy.bottom-=20;\r
86 \r
87         rectDummy.left-=5;\r
88         rectDummy.right-=5;\r
89         \r
90         if (!m_ctrlTabCtrl.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, IDC_REBASE_TAB))\r
91         {\r
92                 TRACE0("Failed to create output tab window\n");\r
93                 return FALSE;      // fail to create\r
94         }\r
95         m_ctrlTabCtrl.SetResizeMode(CMFCTabCtrl::RESIZE_NO);\r
96         // Create output panes:\r
97         //const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;\r
98         const DWORD dwStyle =LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_BORDER | WS_TABSTOP |LVS_SINGLESEL |WS_CHILD | WS_VISIBLE;\r
99 \r
100         if (! this->m_FileListCtrl.Create(dwStyle,rectDummy,&this->m_ctrlTabCtrl,0) )\r
101         {\r
102                 TRACE0("Failed to create output windows\n");\r
103                 return FALSE;      // fail to create\r
104         }\r
105 \r
106         if( ! this->m_LogMessageCtrl.Create(_T("Scintilla"),_T("source"),0,rectDummy,&m_ctrlTabCtrl,0,0) )\r
107         {\r
108                 TRACE0("Failed to create log message control");\r
109                 return FALSE;\r
110         }\r
111 \r
112         m_tooltips.Create(this);\r
113 \r
114         m_FileListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLSTATUS , _T("RebaseDlg"));\r
115 \r
116         m_ctrlTabCtrl.AddTab(&m_FileListCtrl,_T("Conflict File"));\r
117         m_ctrlTabCtrl.AddTab(&m_LogMessageCtrl,_T("Commit Message"),1);\r
118         AddRebaseAnchor();\r
119 \r
120 \r
121         EnableSaveRestore(_T("RebaseDlg"));\r
122 \r
123         DWORD yPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));\r
124         RECT rcDlg, rcLogMsg, rcFileList;\r
125         GetClientRect(&rcDlg);\r
126         m_CommitList.GetWindowRect(&rcLogMsg);\r
127         ScreenToClient(&rcLogMsg);\r
128         this->m_ctrlTabCtrl.GetWindowRect(&rcFileList);\r
129         ScreenToClient(&rcFileList);\r
130         if (yPos)\r
131         {\r
132                 RECT rectSplitter;\r
133                 m_wndSplitter.GetWindowRect(&rectSplitter);\r
134                 ScreenToClient(&rectSplitter);\r
135                 int delta = yPos - rectSplitter.top;\r
136                 if ((rcLogMsg.bottom + delta > rcLogMsg.top)&&(rcLogMsg.bottom + delta < rcFileList.bottom - 30))\r
137                 {\r
138                         m_wndSplitter.SetWindowPos(NULL, 0, yPos, 0, 0, SWP_NOSIZE);\r
139                         DoSize(delta);\r
140                 }\r
141         }\r
142 \r
143         if( this->m_RebaseStage == CHOOSE_BRANCH)\r
144         {\r
145                 this->LoadBranchInfo();\r
146 \r
147         }else\r
148         {\r
149                 this->m_BranchCtrl.EnableWindow(FALSE);\r
150                 this->m_UpstreamCtrl.EnableWindow(FALSE);\r
151         }\r
152 \r
153         m_CommitList.m_IsIDReplaceAction = TRUE;\r
154         m_CommitList.m_IsOldFirst = TRUE;\r
155         m_CommitList.m_IsRebaseReplaceGraph = TRUE;\r
156 \r
157         m_CommitList.DeleteAllItems();\r
158         m_CommitList.InsertGitColumn();\r
159 \r
160         FetchLogList();\r
161         return TRUE;\r
162 }\r
163 // CRebaseDlg message handlers\r
164 \r
165 void CRebaseDlg::OnBnClickedPickAll()\r
166 {\r
167     // TODO: Add your control notification handler code here\r
168         this->UpdateData();\r
169         if(this->m_bPickAll)\r
170                 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_PICK);\r
171 \r
172         this->m_bEditAll=FALSE;\r
173         this->m_bSquashAll=FALSE;\r
174         this->UpdateData(FALSE);\r
175         \r
176 }\r
177 \r
178 void CRebaseDlg::OnBnClickedSquashAll()\r
179 {\r
180     // TODO: Add your control notification handler code here\r
181         this->UpdateData();\r
182         if(this->m_bSquashAll)\r
183                 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_SQUASH);\r
184 \r
185         this->m_bEditAll=FALSE;\r
186         this->m_bPickAll=FALSE;\r
187         this->UpdateData(FALSE);\r
188 \r
189 }\r
190 \r
191 void CRebaseDlg::OnBnClickedEditAll()\r
192 {\r
193     // TODO: Add your control notification handler code here\r
194         this->UpdateData();\r
195         if( this->m_bEditAll )\r
196                 this->SetAllRebaseAction(CTGitPath::LOGACTIONS_REBASE_EDIT);\r
197 \r
198         this->m_bPickAll=FALSE;\r
199         this->m_bSquashAll=FALSE;\r
200         this->UpdateData(FALSE);\r
201 \r
202 }\r
203 \r
204 void CRebaseDlg::SetAllRebaseAction(int action)\r
205 {\r
206         for(int i=0;i<this->m_CommitList.m_logEntries.size();i++)\r
207         {\r
208                 m_CommitList.m_logEntries[i].m_Action=action;\r
209         }\r
210         m_CommitList.Invalidate();\r
211 }\r
212 \r
213 void CRebaseDlg::OnBnClickedRebaseSplit()\r
214 {\r
215         this->UpdateData();\r
216     // TODO: Add your control notification handler code here\r
217 }\r
218 \r
219 LRESULT CRebaseDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)\r
220 {\r
221         switch (message) {\r
222         case WM_NOTIFY:\r
223                 if (wParam == IDC_REBASE_SPLIT)\r
224                 { \r
225                         SPC_NMHDR* pHdr = (SPC_NMHDR*) lParam;\r
226                         DoSize(pHdr->delta);\r
227                 }\r
228                 break;\r
229         }\r
230 \r
231         return __super::DefWindowProc(message, wParam, lParam);\r
232 }\r
233 \r
234 void CRebaseDlg::DoSize(int delta)\r
235 {\r
236         \r
237         this->RemoveAllAnchors();\r
238 \r
239         CSplitterControl::ChangeHeight(GetDlgItem(IDC_COMMIT_LIST), delta, CW_TOPALIGN);\r
240         //CSplitterControl::ChangeHeight(GetDlgItem(), delta, CW_TOPALIGN);\r
241         CSplitterControl::ChangeHeight(GetDlgItem(IDC_REBASE_TAB), -delta, CW_BOTTOMALIGN);\r
242         //CSplitterControl::ChangeHeight(GetDlgItem(), -delta, CW_BOTTOMALIGN);\r
243         CSplitterControl::ChangePos(GetDlgItem(IDC_SQUASH_ALL),0,delta);\r
244         CSplitterControl::ChangePos(GetDlgItem(IDC_PICK_ALL),0,delta);\r
245         CSplitterControl::ChangePos(GetDlgItem(IDC_EDIT_ALL),0,delta);\r
246         \r
247         this->AddRebaseAnchor();\r
248         // adjust the minimum size of the dialog to prevent the resizing from\r
249         // moving the list control too far down.\r
250         CRect rcLogMsg;\r
251         m_CommitList.GetClientRect(rcLogMsg);\r
252         SetMinTrackSize(CSize(m_DlgOrigRect.Width(), m_DlgOrigRect.Height()-m_CommitListOrigRect.Height()+rcLogMsg.Height()));\r
253 \r
254         SetSplitterRange();\r
255 //      m_CommitList.Invalidate();\r
256 \r
257 //      GetDlgItem(IDC_LOGMESSAGE)->Invalidate();\r
258 \r
259         this->m_ctrlTabCtrl.Invalidate();\r
260         this->m_CommitList.Invalidate();\r
261         this->m_FileListCtrl.Invalidate();\r
262         this->m_LogMessageCtrl.Invalidate();\r
263 \r
264 }\r
265 \r
266 void CRebaseDlg::SetSplitterRange()\r
267 {\r
268         if ((m_CommitList)&&(m_ctrlTabCtrl))\r
269         {\r
270                 CRect rcTop;\r
271                 m_CommitList.GetWindowRect(rcTop);\r
272                 ScreenToClient(rcTop);\r
273                 CRect rcMiddle;\r
274                 m_ctrlTabCtrl.GetWindowRect(rcMiddle);\r
275                 ScreenToClient(rcMiddle);\r
276                 if (rcMiddle.Height() && rcMiddle.Width())\r
277                         m_wndSplitter.SetRange(rcTop.top+60, rcMiddle.bottom-80);\r
278         }\r
279 }\r
280 \r
281 void CRebaseDlg::OnSize(UINT nType,int cx, int cy)\r
282 {\r
283          // first, let the resizing take place\r
284     __super::OnSize(nType, cx, cy);\r
285 \r
286     //set range\r
287     SetSplitterRange();\r
288 }\r
289 \r
290 void CRebaseDlg::SaveSplitterPos()\r
291 {\r
292         if (!IsIconic())\r
293         {\r
294                 CRegDWORD regPos = CRegDWORD(_T("Software\\TortoiseGit\\TortoiseProc\\ResizableState\\RebaseDlgSizer"));\r
295                 RECT rectSplitter;\r
296                 m_wndSplitter.GetWindowRect(&rectSplitter);\r
297                 ScreenToClient(&rectSplitter);\r
298                 regPos = rectSplitter.top;\r
299         }\r
300 }\r
301 \r
302 void CRebaseDlg::LoadBranchInfo()\r
303 {\r
304         m_BranchCtrl.SetMaxHistoryItems(0x7FFFFFFF);\r
305         m_UpstreamCtrl.SetMaxHistoryItems(0x7FFFFFFF);\r
306 \r
307         STRING_VECTOR list;\r
308         list.clear();\r
309         int current;\r
310         g_Git.GetBranchList(list,&current,CGit::BRANCH_ALL);\r
311         m_BranchCtrl.AddString(list);\r
312         m_UpstreamCtrl.AddString(list);\r
313 \r
314         m_BranchCtrl.SetCurSel(current);\r
315 \r
316         AddBranchToolTips(&m_BranchCtrl);\r
317         AddBranchToolTips(&m_UpstreamCtrl);\r
318 \r
319 }\r
320 \r
321 void CRebaseDlg::OnCbnSelchangeBranch()\r
322 {\r
323         FetchLogList();\r
324 }\r
325 \r
326 void CRebaseDlg::OnCbnSelchangeUpstream()\r
327 {\r
328         FetchLogList();\r
329 }\r
330 \r
331 void CRebaseDlg::FetchLogList()\r
332 {\r
333         m_CommitList.Clear();\r
334         this->m_CommitList.FillGitLog(NULL,0,&m_UpstreamCtrl.GetString(),&m_BranchCtrl.GetString());\r
335         if( m_CommitList.GetItemCount() == 0 )\r
336                 m_CommitList.ShowText(_T("Nothing Rebase"));\r
337 \r
338         CString hash=g_Git.GetHash(m_UpstreamCtrl.GetString());\r
339         \r
340         if(m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash.size() >=0 )\r
341         {\r
342                 if(hash ==  m_CommitList.m_logEntries[m_CommitList.m_logEntries.size()-1].m_ParentHash[0])\r
343                 {\r
344                         m_CommitList.Clear();\r
345                         m_CommitList.ShowText(_T("Nothing Rebase"));\r
346                 }\r
347         }\r
348         \r
349         m_tooltips.Pop();\r
350         AddBranchToolTips(&this->m_BranchCtrl);\r
351         AddBranchToolTips(&this->m_UpstreamCtrl);\r
352         \r
353         for(int i=0;i<m_CommitList.m_logEntries.size();i++)\r
354         {\r
355                 m_CommitList.m_logEntries[i].m_Action = CTGitPath::LOGACTIONS_REBASE_PICK;\r
356         }\r
357         \r
358         m_CommitList.Invalidate();\r
359 }\r
360 \r
361 void CRebaseDlg::AddBranchToolTips(CHistoryCombo *pBranch)\r
362 {\r
363         if(pBranch)\r
364         {\r
365                 CString text=pBranch->GetString();\r
366                 CString tooltip;\r
367                 BYTE_VECTOR data;\r
368                 g_Git.GetLog(data,text,NULL,1,0);\r
369                 GitRev rev;\r
370                 rev.ParserFromLog(data);\r
371                 tooltip.Format(_T("CommitHash:%s\nCommit by: %s  %s\n <b>%s</b> \n %s"),\r
372                         rev.m_CommitHash,\r
373                         rev.m_AuthorName,\r
374                         CAppUtils::FormatDateAndTime(rev.m_AuthorDate,DATE_LONGDATE),\r
375                         rev.m_Subject,\r
376                         rev.m_Body);\r
377 \r
378                 pBranch->DisableTooltip();\r
379                 this->m_tooltips.AddTool(pBranch->GetComboBoxCtrl(),tooltip);\r
380         }\r
381 }\r
382 \r
383 BOOL CRebaseDlg::PreTranslateMessage(MSG*pMsg)\r
384 {\r
385         m_tooltips.RelayEvent(pMsg);\r
386         return CResizableStandAloneDialog::PreTranslateMessage(pMsg);\r
387 }