OSDN Git Service

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