Add PostCmdActions to GitProgressList
[TortoiseGit.git] / src / TortoiseProc / GitProgressDlg.cpp
blobe502c940f2abdd3ef30b9f893c16540101fbda49
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2014 - TortoiseGit
4 // Copyright (C) 2003-2008 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "stdafx.h"
21 #include "TortoiseProc.h"
22 #include "GitProgressDlg.h"
23 #include "AppUtils.h"
24 #include "SmartHandle.h"
27 IMPLEMENT_DYNAMIC(CGitProgressDlg, CResizableStandAloneDialog)
28 CGitProgressDlg::CGitProgressDlg(CWnd* pParent /*=NULL*/)
29 : CResizableStandAloneDialog(CGitProgressDlg::IDD, pParent)
30 , m_dwCloseOnEnd((DWORD)-1)
34 CGitProgressDlg::~CGitProgressDlg()
38 void CGitProgressDlg::DoDataExchange(CDataExchange* pDX)
40 CResizableStandAloneDialog::DoDataExchange(pDX);
41 DDX_Control(pDX, IDC_SVNPROGRESS, m_ProgList);
42 DDX_Control(pDX, IDC_TITLE_ANIMATE, m_Animate);
43 DDX_Control(pDX, IDC_PROGRESSBAR, m_ProgCtrl);
44 DDX_Control(pDX, IDC_INFOTEXT, m_InfoCtrl);
45 DDX_Control(pDX, IDC_PROGRESSLABEL, m_ProgLableCtrl);
46 DDX_Control(pDX, IDC_LOGBUTTON, m_cMenuButton);
49 BEGIN_MESSAGE_MAP(CGitProgressDlg, CResizableStandAloneDialog)
50 ON_BN_CLICKED(IDC_LOGBUTTON, OnBnClickedLogbutton)
51 ON_WM_CLOSE()
52 ON_WM_SETCURSOR()
53 ON_EN_SETFOCUS(IDC_INFOTEXT, &CGitProgressDlg::OnEnSetfocusInfotext)
54 ON_WM_CTLCOLOR()
55 ON_MESSAGE(WM_PROG_CMD_FINISH, OnCmdEnd)
56 ON_MESSAGE(WM_PROG_CMD_START, OnCmdStart)
57 ON_REGISTERED_MESSAGE(WM_TASKBARBTNCREATED, OnTaskbarBtnCreated)
58 END_MESSAGE_MAP()
62 BOOL CGitProgressDlg::OnInitDialog()
64 __super::OnInitDialog();
66 // Let the TaskbarButtonCreated message through the UIPI filter. If we don't
67 // do this, Explorer would be unable to send that message to our window if we
68 // were running elevated. It's OK to make the call all the time, since if we're
69 // not elevated, this is a no-op.
70 CHANGEFILTERSTRUCT cfs = { sizeof(CHANGEFILTERSTRUCT) };
71 typedef BOOL STDAPICALLTYPE ChangeWindowMessageFilterExDFN(HWND hWnd, UINT message, DWORD action, PCHANGEFILTERSTRUCT pChangeFilterStruct);
72 CAutoLibrary hUser = AtlLoadSystemLibraryUsingFullPath(_T("user32.dll"));
73 if (hUser)
75 ChangeWindowMessageFilterExDFN *pfnChangeWindowMessageFilterEx = (ChangeWindowMessageFilterExDFN*)GetProcAddress(hUser, "ChangeWindowMessageFilterEx");
76 if (pfnChangeWindowMessageFilterEx)
78 pfnChangeWindowMessageFilterEx(m_hWnd, WM_TASKBARBTNCREATED, MSGFLT_ALLOW, &cfs);
81 m_ProgList.m_pTaskbarList.Release();
82 if (FAILED(m_ProgList.m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList)))
83 m_ProgList.m_pTaskbarList = nullptr;
85 UpdateData(FALSE);
87 AddAnchor(IDC_SVNPROGRESS, TOP_LEFT, BOTTOM_RIGHT);
88 AddAnchor(IDC_TITLE_ANIMATE, TOP_LEFT, BOTTOM_RIGHT);
89 AddAnchor(IDC_PROGRESSLABEL, BOTTOM_LEFT, BOTTOM_CENTER);
90 AddAnchor(IDC_PROGRESSBAR, BOTTOM_CENTER, BOTTOM_RIGHT);
91 AddAnchor(IDC_INFOTEXT, BOTTOM_LEFT, BOTTOM_RIGHT);
92 AddAnchor(IDCANCEL, BOTTOM_RIGHT);
93 AddAnchor(IDOK, BOTTOM_RIGHT);
94 AddAnchor(IDC_LOGBUTTON, BOTTOM_RIGHT);
95 //SetPromptParentWindow(this->m_hWnd);
97 m_Animate.Open(IDR_DOWNLOAD);
98 m_ProgList.m_pAnimate = &m_Animate;
99 m_ProgList.m_pProgControl = &m_ProgCtrl;
100 m_ProgList.m_pProgressLabelCtrl = &m_ProgLableCtrl;
101 m_ProgList.m_pInfoCtrl = &m_InfoCtrl;
102 m_ProgList.m_pPostWnd = this;
103 m_ProgList.m_bSetTitle = true;
105 if (hWndExplorer)
106 CenterWindow(CWnd::FromHandle(hWndExplorer));
107 EnableSaveRestore(_T("GITProgressDlg"));
109 m_background_brush.CreateSolidBrush(GetSysColor(COLOR_WINDOW));
110 m_ProgList.Init();
112 return TRUE;
115 LRESULT CGitProgressDlg::OnTaskbarBtnCreated(WPARAM /*wParam*/, LPARAM /*lParam*/)
117 m_ProgList.m_pTaskbarList.Release();
118 m_ProgList.m_pTaskbarList.CoCreateInstance(CLSID_TaskbarList);
119 SetUUIDOverlayIcon(m_hWnd);
120 return 0;
123 void CGitProgressDlg::OnBnClickedLogbutton()
125 ShowWindow(SW_HIDE);
126 m_PostCmdList.at(m_cMenuButton.GetCurrentEntry()).action();
127 EndDialog(IDOK);
131 void CGitProgressDlg::OnClose()
133 DialogEnableWindow(IDCANCEL, TRUE);
134 __super::OnClose();
137 void CGitProgressDlg::OnOK()
139 if ((m_ProgList.IsCancelled())&&(!m_ProgList.IsRunning()))
141 // I have made this wait a sensible amount of time (10 seconds) for the thread to finish
142 // You must be careful in the thread that after posting the WM_COMMAND/IDOK message, you
143 // don't do any more operations on the window which might require message passing
144 // If you try to send windows messages once we're waiting here, then the thread can't finished
145 // because the Window's message loop is blocked at this wait
146 WaitForSingleObject(m_ProgList.m_pThread->m_hThread, 10000);
147 __super::OnOK();
149 m_ProgList.Cancel();
152 void CGitProgressDlg::OnCancel()
154 if ((m_ProgList.IsCancelled())&&(!m_ProgList.IsRunning()))
155 __super::OnCancel();
156 m_ProgList.Cancel();
160 BOOL CGitProgressDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
162 if (!GetDlgItem(IDOK)->IsWindowEnabled())
164 // only show the wait cursor over the list control
165 if ((pWnd)&&(pWnd == GetDlgItem(IDC_SVNPROGRESS)))
167 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT));
168 SetCursor(hCur);
169 return TRUE;
172 HCURSOR hCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
173 SetCursor(hCur);
174 return CResizableStandAloneDialog::OnSetCursor(pWnd, nHitTest, message);
177 BOOL CGitProgressDlg::PreTranslateMessage(MSG* pMsg)
179 if (pMsg->message == WM_KEYDOWN)
181 if (pMsg->wParam == VK_ESCAPE)
183 // pressing the ESC key should close the dialog. But since we disabled the escape
184 // key (so the user doesn't get the idea that he could simply undo an e.g. update)
185 // this won't work.
186 // So if the user presses the ESC key, change it to VK_RETURN so the dialog gets
187 // the impression that the OK button was pressed.
188 if ((!m_ProgList.IsRunning())&&(!GetDlgItem(IDCANCEL)->IsWindowEnabled())
189 &&(GetDlgItem(IDOK)->IsWindowEnabled())&&(GetDlgItem(IDOK)->IsWindowVisible()))
191 // since we convert ESC to RETURN, make sure the OK button has the focus.
192 GetDlgItem(IDOK)->SetFocus();
193 pMsg->wParam = VK_RETURN;
197 return __super::PreTranslateMessage(pMsg);
202 void CGitProgressDlg::OnEnSetfocusInfotext()
204 CString sTemp;
205 GetDlgItemText(IDC_INFOTEXT, sTemp);
206 if (sTemp.IsEmpty())
207 GetDlgItem(IDC_INFOTEXT)->HideCaret();
211 LRESULT CGitProgressDlg::OnCtlColorStatic(WPARAM wParam, LPARAM lParam)
213 HDC hDC = (HDC)wParam;
214 HWND hwndCtl = (HWND)lParam;
216 if (::GetDlgCtrlID(hwndCtl) == IDC_TITLE_ANIMATE)
218 CDC *pDC = CDC::FromHandle(hDC);
219 pDC->SetBkColor(GetSysColor(COLOR_WINDOW));
220 pDC->SetBkMode(TRANSPARENT);
221 return (LRESULT)(HBRUSH)m_background_brush.GetSafeHandle();
223 return FALSE;
226 HBRUSH CGitProgressDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
228 HBRUSH hbr;
229 if (pWnd->GetDlgCtrlID() == IDC_TITLE_ANIMATE)
231 pDC->SetBkColor(GetSysColor(COLOR_WINDOW)); // add this
232 pDC->SetBkMode(TRANSPARENT);
233 return (HBRUSH)m_background_brush.GetSafeHandle();
235 else
236 hbr = CResizableStandAloneDialog::OnCtlColor(pDC, pWnd, nCtlColor);
238 // TODO: Return a different brush if the default is not desired
239 return hbr;
242 LRESULT CGitProgressDlg::OnCmdEnd(WPARAM wParam, LPARAM /*lParam*/)
244 ATLASSERT(wParam);
246 RefreshCursor();
248 DialogEnableWindow(IDCANCEL, FALSE);
249 DialogEnableWindow(IDOK, TRUE);
251 m_PostCmdList.clear();
252 if (m_ProgList.m_Command->m_PostCmdCallback)
253 m_ProgList.m_Command->m_PostCmdCallback(m_ProgList.DidErrorsOccur() ? 1 : 0, m_PostCmdList);
255 if (!m_PostCmdList.empty())
257 for (auto it = m_PostCmdList.cbegin(); it != m_PostCmdList.cend(); ++it)
258 m_cMenuButton.AddEntry((*it).icon, (*it).label);
259 m_cMenuButton.ShowWindow(SW_SHOW);
262 CWnd * pWndOk = GetDlgItem(IDOK);
263 if (pWndOk && ::IsWindow(pWndOk->GetSafeHwnd()))
265 SendMessage(DM_SETDEFID, IDOK);
266 GetDlgItem(IDOK)->SetFocus();
269 return 0;
271 LRESULT CGitProgressDlg::OnCmdStart(WPARAM /*wParam*/, LPARAM /*lParam*/)
273 DialogEnableWindow(IDOK, FALSE);
274 DialogEnableWindow(IDCANCEL, TRUE);
276 return 0;