OSDN Git Service

Finish Submodule Add Command
[tortoisegit/TortoiseGitJp.git] / src / TortoiseProc / ResolveDlg.cpp
1 // TortoiseSVN - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseSVN\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 "TortoiseProc.h"\r
21 #include "messagebox.h"\r
22 #include "ResolveDlg.h"\r
23 #include "CommonResource.h"\r
24 \r
25 #define REFRESHTIMER   100\r
26 \r
27 IMPLEMENT_DYNAMIC(CResolveDlg, CResizableStandAloneDialog)\r
28 CResolveDlg::CResolveDlg(CWnd* pParent /*=NULL*/)\r
29         : CResizableStandAloneDialog(CResolveDlg::IDD, pParent)\r
30         , m_bThreadRunning(FALSE)\r
31         , m_bCancelled(false)\r
32 {\r
33 }\r
34 \r
35 CResolveDlg::~CResolveDlg()\r
36 {\r
37 }\r
38 \r
39 void CResolveDlg::DoDataExchange(CDataExchange* pDX)\r
40 {\r
41         CResizableStandAloneDialog::DoDataExchange(pDX);\r
42         DDX_Control(pDX, IDC_RESOLVELIST, m_resolveListCtrl);\r
43         DDX_Control(pDX, IDC_SELECTALL, m_SelectAll);\r
44 }\r
45 \r
46 \r
47 BEGIN_MESSAGE_MAP(CResolveDlg, CResizableStandAloneDialog)\r
48         ON_BN_CLICKED(IDC_SELECTALL, OnBnClickedSelectall)\r
49         ON_BN_CLICKED(IDHELP, OnBnClickedHelp)\r
50         ON_REGISTERED_MESSAGE(CGitStatusListCtrl::SVNSLNM_NEEDSREFRESH, OnSVNStatusListCtrlNeedsRefresh)\r
51         ON_REGISTERED_MESSAGE(CGitStatusListCtrl::SVNSLNM_ADDFILE, OnFileDropped)\r
52         ON_WM_TIMER()\r
53 END_MESSAGE_MAP()\r
54 \r
55 BOOL CResolveDlg::OnInitDialog()\r
56 {\r
57         CResizableStandAloneDialog::OnInitDialog();\r
58 \r
59         m_resolveListCtrl.Init(SVNSLC_COLEXT | SVNSLC_COLTEXTSTATUS | SVNSLC_COLPROPSTATUS, _T("ResolveDlg"), SVNSLC_POPALL ^ (SVNSLC_POPIGNORE|SVNSLC_POPADD|SVNSLC_POPCOMMIT));\r
60         m_resolveListCtrl.SetConfirmButton((CButton*)GetDlgItem(IDOK));\r
61         m_resolveListCtrl.SetSelectButton(&m_SelectAll);\r
62         m_resolveListCtrl.SetCancelBool(&m_bCancelled);\r
63         m_resolveListCtrl.SetBackgroundImage(IDI_RESOLVE_BKG);\r
64         m_resolveListCtrl.EnableFileDrop();\r
65 \r
66         AdjustControlSize(IDC_SELECTALL);\r
67 \r
68         AddAnchor(IDC_RESOLVELIST, TOP_LEFT, BOTTOM_RIGHT);\r
69         AddAnchor(IDC_SELECTALL, BOTTOM_LEFT);\r
70         AddAnchor(IDOK, BOTTOM_RIGHT);\r
71         AddAnchor(IDCANCEL, BOTTOM_RIGHT);\r
72         AddAnchor(IDHELP, BOTTOM_RIGHT);\r
73         if (hWndExplorer)\r
74                 CenterWindow(CWnd::FromHandle(hWndExplorer));\r
75         EnableSaveRestore(_T("ResolveDlg"));\r
76 \r
77         // first start a thread to obtain the file list with the status without\r
78         // blocking the dialog\r
79         if(AfxBeginThread(ResolveThreadEntry, this) == NULL)\r
80         {\r
81                 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);\r
82         }\r
83         InterlockedExchange(&m_bThreadRunning, TRUE);\r
84 \r
85         return TRUE;\r
86 }\r
87 \r
88 void CResolveDlg::OnOK()\r
89 {\r
90         if (m_bThreadRunning)\r
91                 return;\r
92 \r
93         //save only the files the user has selected into the path list\r
94         m_resolveListCtrl.WriteCheckedNamesToPathList(m_pathList);\r
95 \r
96         CResizableStandAloneDialog::OnOK();\r
97 }\r
98 \r
99 void CResolveDlg::OnCancel()\r
100 {\r
101         m_bCancelled = true;\r
102         if (m_bThreadRunning)\r
103                 return;\r
104 \r
105         CResizableStandAloneDialog::OnCancel();\r
106 }\r
107 \r
108 void CResolveDlg::OnBnClickedSelectall()\r
109 {\r
110         UINT state = (m_SelectAll.GetState() & 0x0003);\r
111         if (state == BST_INDETERMINATE)\r
112         {\r
113                 // It is not at all useful to manually place the checkbox into the indeterminate state...\r
114                 // We will force this on to the unchecked state\r
115                 state = BST_UNCHECKED;\r
116                 m_SelectAll.SetCheck(state);\r
117         }\r
118         theApp.DoWaitCursor(1);\r
119         m_resolveListCtrl.SelectAll(state == BST_CHECKED);\r
120         theApp.DoWaitCursor(-1);\r
121 }\r
122 \r
123 UINT CResolveDlg::ResolveThreadEntry(LPVOID pVoid)\r
124 {\r
125         return ((CResolveDlg*)pVoid)->ResolveThread();\r
126 }\r
127 UINT CResolveDlg::ResolveThread()\r
128 {\r
129         // get the status of all selected file/folders recursively\r
130         // and show the ones which are in conflict\r
131         DialogEnableWindow(IDOK, false);\r
132 \r
133         m_bCancelled = false;\r
134 \r
135         if (!m_resolveListCtrl.GetStatus(&m_pathList))\r
136         {\r
137                 m_resolveListCtrl.SetEmptyString(m_resolveListCtrl.GetLastErrorMessage());\r
138         }\r
139         m_resolveListCtrl.Show(SVNSLC_SHOWCONFLICTED|SVNSLC_SHOWINEXTERNALS, SVNSLC_SHOWCONFLICTED);\r
140 \r
141         InterlockedExchange(&m_bThreadRunning, FALSE);\r
142         return 0;\r
143 }\r
144 \r
145 void CResolveDlg::OnBnClickedHelp()\r
146 {\r
147         OnHelp();\r
148 }\r
149 \r
150 BOOL CResolveDlg::PreTranslateMessage(MSG* pMsg)\r
151 {\r
152         if (pMsg->message == WM_KEYDOWN)\r
153         {\r
154                 switch (pMsg->wParam)\r
155                 {\r
156                 case VK_RETURN:\r
157                         {\r
158                                 if (GetAsyncKeyState(VK_CONTROL)&0x8000)\r
159                                 {\r
160                                         if ( GetDlgItem(IDOK)->IsWindowEnabled() )\r
161                                         {\r
162                                                 PostMessage(WM_COMMAND, IDOK);\r
163                                         }\r
164                                         return TRUE;\r
165                                 }\r
166                         }\r
167                         break;\r
168                 case VK_F5:\r
169                         {\r
170                                 if (!m_bThreadRunning)\r
171                                 {\r
172                                         if(AfxBeginThread(ResolveThreadEntry, this) == NULL)\r
173                                         {\r
174                                                 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);\r
175                                         }\r
176                                         else\r
177                                                 InterlockedExchange(&m_bThreadRunning, TRUE);\r
178                                 }\r
179                         }\r
180                         break;\r
181                 }\r
182         }\r
183 \r
184         return CResizableStandAloneDialog::PreTranslateMessage(pMsg);\r
185 }\r
186 \r
187 LRESULT CResolveDlg::OnSVNStatusListCtrlNeedsRefresh(WPARAM, LPARAM)\r
188 {\r
189         if(AfxBeginThread(ResolveThreadEntry, this) == NULL)\r
190         {\r
191                 CMessageBox::Show(this->m_hWnd, IDS_ERR_THREADSTARTFAILED, IDS_APPNAME, MB_OK | MB_ICONERROR);\r
192         }\r
193         return 0;\r
194 }\r
195 \r
196 LRESULT CResolveDlg::OnFileDropped(WPARAM, LPARAM lParam)\r
197 {\r
198         BringWindowToTop();\r
199         SetForegroundWindow();\r
200         SetActiveWindow();\r
201         // if multiple files/folders are dropped\r
202         // this handler is called for every single item\r
203         // separately.\r
204         // To avoid creating multiple refresh threads and\r
205         // causing crashes, we only add the items to the\r
206         // list control and start a timer.\r
207         // When the timer expires, we start the refresh thread,\r
208         // but only if it isn't already running - otherwise we\r
209         // restart the timer.\r
210         CTGitPath path;\r
211         path.SetFromWin((LPCTSTR)lParam);\r
212 \r
213         if (!m_resolveListCtrl.HasPath(path))\r
214         {\r
215                 if (m_pathList.AreAllPathsFiles())\r
216                 {\r
217                         m_pathList.AddPath(path);\r
218                         m_pathList.RemoveDuplicates();\r
219                 }\r
220                 else\r
221                 {\r
222                         // if the path list contains folders, we have to check whether\r
223                         // our just (maybe) added path is a child of one of those. If it is\r
224                         // a child of a folder already in the list, we must not add it. Otherwise\r
225                         // that path could show up twice in the list.\r
226                         bool bHasParentInList = false;\r
227                         for (int i=0; i<m_pathList.GetCount(); ++i)\r
228                         {\r
229                                 if (m_pathList[i].IsAncestorOf(path))\r
230                                 {\r
231                                         bHasParentInList = true;\r
232                                         break;\r
233                                 }\r
234                         }\r
235                         if (!bHasParentInList)\r
236                         {\r
237                                 m_pathList.AddPath(path);\r
238                                 m_pathList.RemoveDuplicates();\r
239                         }\r
240                 }\r
241         }\r
242 \r
243         // Always start the timer, since the status of an existing item might have changed\r
244         SetTimer(REFRESHTIMER, 200, NULL);\r
245         ATLTRACE(_T("Item %s dropped, timer started\n"), path.GetWinPath());\r
246         return 0;\r
247 }\r
248 \r
249 void CResolveDlg::OnTimer(UINT_PTR nIDEvent)\r
250 {\r
251         switch (nIDEvent)\r
252         {\r
253         case REFRESHTIMER:\r
254                 if (m_bThreadRunning)\r
255                 {\r
256                         SetTimer(REFRESHTIMER, 200, NULL);\r
257                         ATLTRACE("Wait some more before refreshing\n");\r
258                 }\r
259                 else\r
260                 {\r
261                         KillTimer(REFRESHTIMER);\r
262                         ATLTRACE("Refreshing after items dropped\n");\r
263                         OnSVNStatusListCtrlNeedsRefresh(0, 0);\r
264                 }\r
265                 break;\r
266         }\r
267         __super::OnTimer(nIDEvent);\r
268 }\r