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