OSDN Git Service

Update version number to 1.2.1.0
[tortoisegit/TortoiseGitJp.git] / src / TortoiseMerge / FilePatchesDlg.cpp
1 // TortoiseMerge - a Diff/Patch program\r
2 \r
3 // Copyright (C) 2006, 2008 - Stefan Kueng\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 #include "stdafx.h"\r
20 #include "TortoiseMerge.h"\r
21 #include "FilePatchesDlg.h"\r
22 #include "Patch.h"\r
23 #include "AppUtils.h"\r
24 #include "PathUtils.h"\r
25 #include "SysProgressDlg.h"\r
26 \r
27 \r
28 IMPLEMENT_DYNAMIC(CFilePatchesDlg, CDialog)\r
29 CFilePatchesDlg::CFilePatchesDlg(CWnd* pParent /*=NULL*/)\r
30         : CDialog(CFilePatchesDlg::IDD, pParent)\r
31 {\r
32         m_ImgList.Create(16, 16, ILC_COLOR16 | ILC_MASK, 4, 1);\r
33         m_bMinimized = FALSE;\r
34 }\r
35 \r
36 CFilePatchesDlg::~CFilePatchesDlg()\r
37 {\r
38 }\r
39 \r
40 void CFilePatchesDlg::DoDataExchange(CDataExchange* pDX)\r
41 {\r
42         CDialog::DoDataExchange(pDX);\r
43         DDX_Control(pDX, IDC_FILELIST, m_cFileList);\r
44 }\r
45 \r
46 BOOL CFilePatchesDlg::SetFileStatusAsPatched(CString sPath)\r
47 {\r
48         for (int i=0; i<m_arFileStates.GetCount(); i++)\r
49         {\r
50                 if (sPath.CompareNoCase(GetFullPath(i))==0)\r
51                 {\r
52                         m_arFileStates.SetAt(i, FPDLG_FILESTATE_PATCHED);\r
53                         Invalidate();\r
54                         return TRUE;\r
55                 }\r
56         }\r
57         return FALSE;\r
58 }\r
59 \r
60 CString CFilePatchesDlg::GetFullPath(int nIndex)\r
61 {\r
62         CString temp = m_pPatch->GetFilename(nIndex);\r
63         temp.Replace('/', '\\');\r
64         //temp = temp.Mid(temp.Find('\\')+1);\r
65         if (PathIsRelative(temp))\r
66                 temp = m_sPath + temp;\r
67         return temp;\r
68 }\r
69 \r
70 BOOL CFilePatchesDlg::Init(CPatch * pPatch, CPatchFilesDlgCallBack * pCallBack, CString sPath, CWnd * pParent)\r
71 {\r
72         if ((pCallBack==NULL)||(pPatch==NULL))\r
73         {\r
74                 m_cFileList.DeleteAllItems();\r
75                 return FALSE;\r
76         }\r
77         m_arFileStates.RemoveAll();\r
78         m_pPatch = pPatch;\r
79         m_pCallBack = pCallBack;\r
80         m_sPath = sPath;\r
81         if (m_sPath.IsEmpty())\r
82         {\r
83                 CString title(MAKEINTRESOURCE(IDS_DIFF_TITLE));\r
84                 SetWindowText(title);\r
85         }\r
86         else\r
87         {\r
88                 CString title;\r
89                 title.LoadString(IDS_PATCH_TITLE);\r
90                 title += _T("  ") + m_sPath;\r
91                 CRect rect;\r
92                 GetClientRect(&rect);\r
93                 PathCompactPath(GetDC()->m_hDC, title.GetBuffer(), rect.Width());\r
94                 title.ReleaseBuffer();\r
95                 SetWindowText(title);\r
96                 if (m_sPath.Right(1).Compare(_T("\\"))==0)\r
97                         m_sPath = m_sPath.Left(m_sPath.GetLength()-1);\r
98 \r
99                 m_sPath = m_sPath + _T("\\");\r
100                 for (int i=m_ImgList.GetImageCount();i>0;i--)\r
101                 {\r
102                         m_ImgList.Remove(0);\r
103                 }\r
104         }\r
105 \r
106         m_cFileList.SetExtendedStyle(LVS_EX_INFOTIP | LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);\r
107         m_cFileList.DeleteAllItems();\r
108         int c = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;\r
109         while (c>=0)\r
110                 m_cFileList.DeleteColumn(c--);\r
111         m_cFileList.InsertColumn(0, _T(""));\r
112 \r
113         m_cFileList.SetRedraw(false);\r
114 \r
115         for(int i=0; i<m_pPatch->GetNumberOfFiles(); i++)\r
116         {\r
117                 CString sFile = CPathUtils::GetFileNameFromPath(m_pPatch->GetFilename(i));\r
118                 DWORD state;\r
119                 if (m_sPath.IsEmpty())\r
120                         state = FPDLG_FILESTATE_GOOD;\r
121                 else\r
122                 {\r
123                         if (m_pPatch->PatchFile(GetFullPath(i)))\r
124                                 state = FPDLG_FILESTATE_GOOD;\r
125                         else\r
126                                 state = FPDLG_FILESTATE_CONFLICTED;\r
127                 }\r
128                 m_arFileStates.Add(state);\r
129                 SHFILEINFO    sfi;\r
130                 SHGetFileInfo(\r
131                         GetFullPath(i), \r
132                         FILE_ATTRIBUTE_NORMAL,\r
133                         &sfi, \r
134                         sizeof(SHFILEINFO), \r
135                         SHGFI_ICON | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES);\r
136                 m_cFileList.InsertItem(i, sFile, m_ImgList.Add(sfi.hIcon));\r
137 \r
138         }\r
139         int mincol = 0;\r
140         int maxcol = ((CHeaderCtrl*)(m_cFileList.GetDlgItem(0)))->GetItemCount()-1;\r
141         int col;\r
142         for (col = mincol; col <= maxcol; col++)\r
143         {\r
144                 m_cFileList.SetColumnWidth(col,LVSCW_AUTOSIZE_USEHEADER);\r
145         }\r
146 \r
147         m_cFileList.SetImageList(&m_ImgList, LVSIL_SMALL);\r
148         m_cFileList.SetRedraw(true);\r
149 \r
150         RECT parentrect;\r
151         pParent->GetWindowRect(&parentrect);\r
152         RECT windowrect;\r
153         GetWindowRect(&windowrect);\r
154 \r
155         int width = windowrect.right - windowrect.left;\r
156         int height = windowrect.bottom - windowrect.top;\r
157         windowrect.right = parentrect.left;\r
158         windowrect.left = windowrect.right - width;\r
159         if (windowrect.left < 0)\r
160         {\r
161                 windowrect.left = 0;\r
162                 windowrect.right = width;\r
163         }\r
164         windowrect.top = parentrect.top;\r
165         windowrect.bottom = windowrect.top + height;\r
166 \r
167         SetWindowPos(NULL, windowrect.left, windowrect.top, width, height, SWP_NOACTIVATE | SWP_NOZORDER);\r
168 \r
169         m_nWindowHeight = windowrect.bottom - windowrect.top;\r
170         m_pMainFrame = pParent;\r
171         return TRUE;\r
172 }\r
173 \r
174 BEGIN_MESSAGE_MAP(CFilePatchesDlg, CDialog)\r
175         ON_WM_SIZE()\r
176         ON_NOTIFY(LVN_GETINFOTIP, IDC_FILELIST, OnLvnGetInfoTipFilelist)\r
177         ON_NOTIFY(NM_DBLCLK, IDC_FILELIST, OnNMDblclkFilelist)\r
178         ON_NOTIFY(NM_CUSTOMDRAW, IDC_FILELIST, OnNMCustomdrawFilelist)\r
179         ON_NOTIFY(NM_RCLICK, IDC_FILELIST, OnNMRclickFilelist)\r
180         ON_WM_NCLBUTTONDBLCLK()\r
181         ON_WM_MOVING()\r
182 END_MESSAGE_MAP()\r
183 \r
184 void CFilePatchesDlg::OnSize(UINT nType, int cx, int cy)\r
185 {\r
186         CDialog::OnSize(nType, cx, cy);\r
187         if (this->IsWindowVisible())\r
188         {\r
189                 CRect rect;\r
190                 GetClientRect(rect);\r
191                 GetDlgItem(IDC_FILELIST)->MoveWindow(rect.left, rect.top, cx, cy);\r
192                 m_cFileList.SetColumnWidth(0, cx);\r
193         }\r
194         CString title;\r
195         title.LoadString(IDS_PATCH_TITLE);\r
196         title += _T("  ") + m_sPath;\r
197         PathCompactPath(GetDC()->m_hDC, title.GetBuffer(), cx);\r
198         title.ReleaseBuffer();\r
199         SetWindowText(title);\r
200 }\r
201 \r
202 void CFilePatchesDlg::OnLvnGetInfoTipFilelist(NMHDR *pNMHDR, LRESULT *pResult)\r
203 {\r
204         LPNMLVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMLVGETINFOTIP>(pNMHDR);\r
205 \r
206         CString temp = GetFullPath(pGetInfoTip->iItem);\r
207         _tcsncpy_s(pGetInfoTip->pszText, pGetInfoTip->cchTextMax, temp, pGetInfoTip->cchTextMax);\r
208         *pResult = 0;\r
209 }\r
210 \r
211 void CFilePatchesDlg::OnNMDblclkFilelist(NMHDR *pNMHDR, LRESULT *pResult)\r
212 {\r
213         LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);\r
214         *pResult = 0;\r
215         if ((pNMLV->iItem < 0) || (pNMLV->iItem >= m_arFileStates.GetCount()))\r
216                 return;\r
217         if (m_pCallBack==NULL)\r
218                 return;\r
219         if (m_sPath.IsEmpty())\r
220         {\r
221                 m_pCallBack->DiffFiles(GetFullPath(pNMLV->iItem), m_pPatch->GetRevision(pNMLV->iItem),\r
222                                                            m_pPatch->GetFilename2(pNMLV->iItem), m_pPatch->GetRevision2(pNMLV->iItem));\r
223         }\r
224         else\r
225         {\r
226                 if (m_arFileStates.GetAt(pNMLV->iItem)!=FPDLG_FILESTATE_PATCHED)\r
227                 {\r
228                         m_pCallBack->PatchFile(GetFullPath(pNMLV->iItem), m_pPatch->GetRevision(pNMLV->iItem),false,true);\r
229                 }\r
230         }\r
231 }\r
232 \r
233 void CFilePatchesDlg::OnNMCustomdrawFilelist(NMHDR *pNMHDR, LRESULT *pResult)\r
234 {\r
235         NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );\r
236 \r
237         // Take the default processing unless we set this to something else below.\r
238         *pResult = CDRF_DODEFAULT;\r
239 \r
240         // First thing - check the draw stage. If it's the control's prepaint\r
241         // stage, then tell Windows we want messages for every item.\r
242 \r
243         if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage )\r
244         {\r
245                 *pResult = CDRF_NOTIFYITEMDRAW;\r
246         }\r
247         else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage )\r
248         {\r
249                 // This is the prepaint stage for an item. Here's where we set the\r
250                 // item's text color. Our return value will tell Windows to draw the\r
251                 // item itself, but it will use the new color we set here.\r
252 \r
253                 COLORREF crText = ::GetSysColor(COLOR_WINDOWTEXT);\r
254 \r
255                 if (m_arFileStates.GetCount() > (INT_PTR)pLVCD->nmcd.dwItemSpec)\r
256                 {\r
257                         if (m_arFileStates.GetAt(pLVCD->nmcd.dwItemSpec)==FPDLG_FILESTATE_CONFLICTED)\r
258                         {\r
259                                 crText = RGB(200, 0, 0);\r
260                         }\r
261                         if (m_arFileStates.GetAt(pLVCD->nmcd.dwItemSpec)==FPDLG_FILESTATE_PATCHED)\r
262                         {\r
263                                 crText = ::GetSysColor(COLOR_GRAYTEXT);\r
264                         }\r
265                         // Store the color back in the NMLVCUSTOMDRAW struct.\r
266                         pLVCD->clrText = crText;\r
267                 }\r
268 \r
269                 // Tell Windows to paint the control itself.\r
270                 *pResult = CDRF_DODEFAULT;\r
271         }\r
272 }\r
273 \r
274 void CFilePatchesDlg::OnNMRclickFilelist(NMHDR * /*pNMHDR*/, LRESULT *pResult)\r
275 {\r
276         *pResult = 0;\r
277         if (m_sPath.IsEmpty())\r
278                 return;\r
279         CString temp;\r
280         CMenu popup;\r
281         POINT point;\r
282         DWORD ptW = GetMessagePos();\r
283         point.x = GET_X_LPARAM(ptW);\r
284         point.y = GET_Y_LPARAM(ptW);\r
285         if (popup.CreatePopupMenu())\r
286         {\r
287                 UINT nFlags;\r
288                 \r
289                 nFlags = MF_STRING | (m_cFileList.GetSelectedCount()==1 ? MF_ENABLED : MF_DISABLED | MF_GRAYED);\r
290 \r
291                 temp.LoadString(IDS_PATCH_REVIEW);\r
292                 popup.AppendMenu(nFlags, ID_PATCH_REVIEW, temp);\r
293                 popup.SetDefaultItem(ID_PATCH_REVIEW, FALSE);\r
294 \r
295                 temp.LoadString(IDS_PATCH_PREVIEW);\r
296                 popup.AppendMenu(nFlags, ID_PATCHPREVIEW, temp);                \r
297 \r
298                 temp.LoadString(IDS_PATCH_ALL);\r
299                 popup.AppendMenu(MF_STRING | MF_ENABLED, ID_PATCHALL, temp);\r
300                 \r
301                 nFlags = MF_STRING | (m_cFileList.GetSelectedCount()>0 ? MF_ENABLED : MF_DISABLED | MF_GRAYED);\r
302                 temp.LoadString(IDS_PATCH_SELECTED);\r
303                 popup.AppendMenu(nFlags, ID_PATCHSELECTED, temp);\r
304                 \r
305                 // if the context menu is invoked through the keyboard, we have to use\r
306                 // a calculated position on where to anchor the menu on\r
307                 if ((point.x == -1) && (point.y == -1))\r
308                 {\r
309                         CRect rect;\r
310                         GetWindowRect(&rect);\r
311                         point = rect.CenterPoint();\r
312                 }\r
313 \r
314                 bool bReview=false;\r
315 \r
316                 int cmd = popup.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_NONOTIFY, point.x, point.y, this, 0);\r
317                 switch (cmd)\r
318                 {\r
319                 case ID_PATCH_REVIEW:\r
320                         bReview = true;\r
321                         //go through case\r
322                 case ID_PATCHPREVIEW:\r
323                         {\r
324                                 if (m_pCallBack)\r
325                                 {\r
326                                         int nIndex = m_cFileList.GetSelectionMark();\r
327                                         if ( m_arFileStates.GetAt(nIndex)!=FPDLG_FILESTATE_PATCHED)\r
328                                         {\r
329                                                 m_pCallBack->PatchFile(GetFullPath(nIndex), m_pPatch->GetRevision(nIndex),false,bReview);\r
330                                         }\r
331                                 }\r
332                         }\r
333                         break;\r
334                 case ID_PATCHALL:\r
335                         {\r
336                                 if (m_pCallBack)\r
337                                 {\r
338                                         CSysProgressDlg progDlg;\r
339                                         progDlg.SetTitle(IDR_MAINFRAME);\r
340                                         progDlg.SetShowProgressBar(true);\r
341                                         progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_PATCH_ALL)));\r
342                                         progDlg.ShowModeless(m_hWnd);\r
343 \r
344                                         for (int i=0; i<m_arFileStates.GetCount() && !progDlg.HasUserCancelled(); i++)\r
345                                         {\r
346                                                 if (m_arFileStates.GetAt(i)!= FPDLG_FILESTATE_PATCHED)\r
347                                                 {\r
348                                                         progDlg.SetLine(2, GetFullPath(i), true);\r
349                                                         m_pCallBack->PatchFile(GetFullPath(i), m_pPatch->GetRevision(i), TRUE);\r
350                                                 }\r
351                                                 progDlg.SetProgress64(i, m_arFileStates.GetCount());\r
352                                         }\r
353                                         progDlg.Stop();\r
354                                 }\r
355                         } \r
356                         break;\r
357                 case ID_PATCHSELECTED:\r
358                         {\r
359                                 if (m_pCallBack)\r
360                                 {\r
361                                         CSysProgressDlg progDlg;\r
362                                         progDlg.SetTitle(IDR_MAINFRAME);\r
363                                         progDlg.SetShowProgressBar(true);\r
364                                         progDlg.SetLine(1, CString(MAKEINTRESOURCE(IDS_PATCH_SELECTED)));\r
365                                         progDlg.ShowModeless(m_hWnd);\r
366 \r
367                                         // The list cannot be sorted by user, so the order of the\r
368                                         // items in the list is identical to the order in the array\r
369                                         // m_arFileStates.\r
370                                         int selCount = m_cFileList.GetSelectedCount();\r
371                                         int count = 1;\r
372                                         POSITION pos = m_cFileList.GetFirstSelectedItemPosition();\r
373                                         int index;\r
374                                         while (((index = m_cFileList.GetNextSelectedItem(pos)) >= 0) && (!progDlg.HasUserCancelled()))\r
375                                         {\r
376                                                 if (m_arFileStates.GetAt(index)!= FPDLG_FILESTATE_PATCHED)\r
377                                                 {\r
378                                                         progDlg.SetLine(2, GetFullPath(index), true);\r
379                                                         m_pCallBack->PatchFile(GetFullPath(index), m_pPatch->GetRevision(index), TRUE);\r
380                                                 }\r
381                                                 progDlg.SetProgress64(count++, selCount);\r
382                                         }\r
383                                         progDlg.Stop();\r
384                                 }\r
385                         } \r
386                         break;\r
387                 default:\r
388                         break;\r
389                 }\r
390         }\r
391 }\r
392 \r
393 void CFilePatchesDlg::OnNcLButtonDblClk(UINT nHitTest, CPoint point)\r
394 {\r
395         if (!m_bMinimized)\r
396         {\r
397                 RECT windowrect;\r
398                 RECT clientrect;\r
399                 GetWindowRect(&windowrect);\r
400                 GetClientRect(&clientrect);\r
401                 m_nWindowHeight = windowrect.bottom - windowrect.top;\r
402                 MoveWindow(windowrect.left, windowrect.top, \r
403                         windowrect.right - windowrect.left,\r
404                         m_nWindowHeight - (clientrect.bottom - clientrect.top));\r
405         }\r
406         else\r
407         {\r
408                 RECT windowrect;\r
409                 GetWindowRect(&windowrect);\r
410                 MoveWindow(windowrect.left, windowrect.top, windowrect.right - windowrect.left, m_nWindowHeight);\r
411         }\r
412         m_bMinimized = !m_bMinimized;\r
413         CDialog::OnNcLButtonDblClk(nHitTest, point);\r
414 }\r
415 \r
416 void CFilePatchesDlg::OnMoving(UINT fwSide, LPRECT pRect)\r
417 {\r
418 #define STICKYSIZE 5\r
419         RECT parentRect;\r
420         m_pMainFrame->GetWindowRect(&parentRect);\r
421         if (abs(parentRect.left - pRect->right) < STICKYSIZE)\r
422         {\r
423                 int width = pRect->right - pRect->left;\r
424                 pRect->right = parentRect.left;\r
425                 pRect->left = pRect->right - width;\r
426         }\r
427         CDialog::OnMoving(fwSide, pRect);\r
428 }\r
429 \r
430 void CFilePatchesDlg::OnOK()\r
431 {\r
432         return;\r
433 }\r