1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2008 University of California
4 //
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
9 //
10 // BOINC 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.
13 // See the GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC. If not, see <http://www.gnu.org/licenses/>.
17
18
19 #include "stdwx.h"
20 #include "Events.h"
21 #include "BOINCGUIApp.h"
22 #include "MainDocument.h"
23 #include "DlgItemProperties.h"
24 #include "sg_TaskPanel.h"
25 #include "sg_TaskCommandPopup.h"
26
IMPLEMENT_DYNAMIC_CLASS(CSimpleTaskPopupButton,CTransparentButton)27 IMPLEMENT_DYNAMIC_CLASS(CSimpleTaskPopupButton, CTransparentButton)
28
29 BEGIN_EVENT_TABLE(CSimpleTaskPopupButton, CTransparentButton)
30 EVT_LEFT_DOWN(CSimpleTaskPopupButton::OnTaskCommandsMouseDown)
31 EVT_MENU(ID_TASK_WORK_SHOWGRAPHICS, CSimpleTaskPopupButton::OnTaskShowGraphics)
32 EVT_MENU(ID_TASK_WORK_SUSPEND, CSimpleTaskPopupButton::OnTaskSuspendResume)
33 EVT_MENU(ID_TASK_WORK_ABORT, CSimpleTaskPopupButton::OnTaskAbort)
34 EVT_MENU(ID_TASK_SHOW_PROPERTIES, CSimpleTaskPopupButton::OnTaskShowProperties)
35 END_EVENT_TABLE()
36
37 CSimpleTaskPopupButton::CSimpleTaskPopupButton() {
38 }
39
CSimpleTaskPopupButton(wxWindow * parent,wxWindowID id,const wxString & label,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)40 CSimpleTaskPopupButton::CSimpleTaskPopupButton(wxWindow* parent, wxWindowID id,
41 const wxString& label, const wxPoint& pos, const wxSize& size,
42 long style, const wxValidator& validator, const wxString& name) :
43 CTransparentButton(parent, id, label, pos, size, style, validator, name)
44 {
45
46 m_TaskSuspendedViaGUI = false;
47 m_TaskCommandPopUpMenu = new wxMenu();
48 AddMenuItems();
49 Connect(
50 id,
51 wxEVT_BUTTON,
52 (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &CSimpleTaskPopupButton::OnTaskCommandsKeyboardNav
53 );
54
55 }
56
57
~CSimpleTaskPopupButton()58 CSimpleTaskPopupButton::~CSimpleTaskPopupButton() {
59 delete m_TaskCommandPopUpMenu;
60 }
61
62
AddMenuItems()63 void CSimpleTaskPopupButton::AddMenuItems() {
64 m_ShowGraphicsMenuItem = m_TaskCommandPopUpMenu->Append(
65 ID_TASK_WORK_SHOWGRAPHICS,
66 _("Show graphics"),
67 _("Show application graphics in a window.")
68 );
69
70 m_SuspendResumeMenuItem = m_TaskCommandPopUpMenu->Append(
71 ID_TASK_WORK_SUSPEND,
72 _("Suspend"),
73 _("Suspend this task.")
74 );
75
76 m_AbortMenuItem = m_TaskCommandPopUpMenu->Append(
77 ID_TASK_WORK_ABORT,
78 _("Abort"),
79 _("Abandon this task. You will get no credit for it.")
80 );
81
82 m_ShowPropertiesMenuItem = m_TaskCommandPopUpMenu->Append(
83 ID_TASK_SHOW_PROPERTIES,
84 _("Properties"),
85 _("Show task details.")
86 );
87 }
88
89
OnTaskCommandsMouseDown(wxMouseEvent &)90 void CSimpleTaskPopupButton::OnTaskCommandsMouseDown(wxMouseEvent&) {
91 ShowTaskCommandsMenu(ScreenToClient(wxGetMousePosition()));
92 }
93
94
OnTaskCommandsKeyboardNav(wxCommandEvent &)95 void CSimpleTaskPopupButton::OnTaskCommandsKeyboardNav(wxCommandEvent&) {
96 ShowTaskCommandsMenu(wxPoint(GetSize().GetWidth()/2, GetSize().GetHeight()/2));
97 }
98
99
ShowTaskCommandsMenu(wxPoint pos)100 void CSimpleTaskPopupButton::ShowTaskCommandsMenu(wxPoint pos) {
101 CMainDocument* pDoc = wxGetApp().GetDocument();
102 bool enableShowGraphics = true;
103 bool enableAbort = true;
104 CC_STATUS status;
105 wxString strMachineName;
106
107 wxASSERT(pDoc);
108
109 TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData();
110 if (selData == NULL) return;
111
112 RESULT* result = lookup_result(selData->project_url, selData->result_name);
113
114 if (!result) return;
115
116 if (result->suspended_via_gui) {
117 m_TaskSuspendedViaGUI = true;
118 m_SuspendResumeMenuItem->SetItemLabel(_("Resume"));
119 m_SuspendResumeMenuItem->SetHelp(_("Resume work for this task."));
120 } else {
121 m_TaskSuspendedViaGUI = false;
122 m_SuspendResumeMenuItem->SetItemLabel(_("Suspend"));
123 m_SuspendResumeMenuItem->SetHelp(_("Suspend work for this task."));
124 }
125
126 pDoc->GetCoreClientStatus(status);
127 if (status.task_suspend_reason & ~(SUSPEND_REASON_CPU_THROTTLE)) {
128 enableShowGraphics = false;
129 }
130
131 pDoc->GetConnectedComputerName(strMachineName);
132 if (!pDoc->IsComputerNameLocal(strMachineName)) {
133 enableShowGraphics = false;
134 }
135
136 // Disable Show Graphics button if selected task can't display graphics
137 if (!strlen(result->web_graphics_url) && !strlen(result->graphics_exec_path)) {
138 enableShowGraphics = false;
139 }
140
141 if (result->suspended_via_gui ||
142 result->project_suspended_via_gui ||
143 (result->scheduler_state != CPU_SCHED_SCHEDULED)
144 ) {
145 enableShowGraphics = false;
146 }
147
148 m_ShowGraphicsMenuItem->Enable(enableShowGraphics);
149
150 // Disable Abort button if any selected task already aborted
151 if (
152 result->active_task_state == PROCESS_ABORT_PENDING ||
153 result->active_task_state == PROCESS_ABORTED ||
154 result->state == RESULT_ABORTED
155 ) {
156 enableAbort = false;
157 }
158
159 m_AbortMenuItem->Enable(enableAbort);
160
161 #ifdef __WXMAC__
162 // Disable tooltips on Mac while menus are popped up because they cover menus
163 wxToolTip::Enable(false);
164 #endif
165
166 PopupMenu(m_TaskCommandPopUpMenu, pos.x, pos.y);
167
168
169 #if TESTBIGICONPOPUP
170 /*** CAF *** FOR TESTING ONLY ***/
171 static int i;
172 wxString s;
173
174 if (i > 9) i = 0;
175 if ( i < 5) {
176 s = (wxT("This is a very very very and extremely long label."));
177 } else {
178 s = (wxT("short."));
179 }
180
181 switch (i++) {
182 case 0:
183 case 5:
184 UpdateStaticText(&m_TaskProjectName, s);
185 break;
186 case 1:
187 case 6:
188 UpdateStaticText(&m_TaskApplicationName, s);
189 break;
190 case 2:
191 case 7:
192 UpdateStaticText(&m_ElapsedTimeValue, s);
193 break;
194 case 3:
195 case 8:
196 UpdateStaticText(&m_TimeRemainingValue, s);
197 break;
198 case 4:
199 case 9:
200 UpdateStaticText(&m_StatusValueText, s);
201 break;
202 }
203
204 m_ProgressBar->SetValue( i * 10 );
205 int sel = i % 3;
206 // m_TaskSelectionCtrl->SetStringSelection(tempArray[sel]);
207 m_TaskSelectionCtrl->SetSelection(sel);
208 #endif
209 }
210
211
OnTaskShowGraphics(wxCommandEvent & WXUNUSED (event))212 void CSimpleTaskPopupButton::OnTaskShowGraphics(wxCommandEvent& WXUNUSED(event)) {
213 CMainDocument* pDoc = wxGetApp().GetDocument();
214
215 wxASSERT(pDoc);
216 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
217
218 TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData();
219 if (selData == NULL) return;
220
221 RESULT* result = lookup_result(selData->project_url, selData->result_name);
222 if (result) {
223 pDoc->WorkShowGraphics(result);
224 }
225 }
226
227
OnTaskSuspendResume(wxCommandEvent & WXUNUSED (event))228 void CSimpleTaskPopupButton::OnTaskSuspendResume(wxCommandEvent& WXUNUSED(event)) {
229 CMainDocument* pDoc = wxGetApp().GetDocument();
230
231 wxASSERT(pDoc);
232 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
233
234 TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData();
235 if (selData == NULL) return;
236
237 if (m_TaskSuspendedViaGUI) {
238 pDoc->WorkResume(selData->project_url, selData->result_name);
239 } else {
240 pDoc->WorkSuspend(selData->project_url, selData->result_name);
241 }
242 }
243
244
OnTaskAbort(wxCommandEvent & WXUNUSED (event))245 void CSimpleTaskPopupButton::OnTaskAbort(wxCommandEvent& WXUNUSED(event)) {
246 wxInt32 iAnswer = 0;
247 wxString strMessage = wxEmptyString;
248 CMainDocument* pDoc = wxGetApp().GetDocument();
249
250 wxASSERT(pDoc);
251 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
252
253 if (!pDoc->IsUserAuthorized()) // Probably no longer relevant
254 return;
255
256 TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData();
257 if (selData == NULL) return;
258
259 RESULT* result = lookup_result(selData->project_url, selData->result_name);
260 if (result) {
261 #if SELECTBYRESULTNAME
262 wxString name = wxString(selData->result_name, wxConvUTF8, strlen(selData->result_name));
263 #else
264 wxString name = ((CSimpleTaskPanel*)GetParent())->GetSelectedTaskString();
265 #endif
266 strMessage.Printf(
267 _("Are you sure you want to abort this task '%s'?\n(Progress: %.1lf%%, Status: %s)"),
268 name.c_str(), result->fraction_done * 100.0, result_description(result, false).c_str());
269
270 iAnswer = wxGetApp().SafeMessageBox(
271 strMessage,
272 _("Abort task"),
273 wxYES_NO | wxICON_QUESTION,
274 this
275 );
276
277 if (wxYES != iAnswer) {
278 return;
279 }
280
281 pDoc->WorkAbort(result->project_url, result->name);
282 }
283 }
284
285
OnTaskShowProperties(wxCommandEvent & WXUNUSED (event))286 void CSimpleTaskPopupButton::OnTaskShowProperties(wxCommandEvent& WXUNUSED(event)) {
287 TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData();
288 if (selData == NULL) return;
289
290 RESULT* result = lookup_result(selData->project_url, selData->result_name);
291 if (result) {
292 CDlgItemProperties dlg(this);
293 dlg.renderInfos(result);
294 dlg.ShowModal();
295 }
296 }
297
298
299 // CMainDocument::state.lookup_result() does not yield current scheduler_state;
300 // we must use CMainDocument::result() for that.
lookup_result(char * url,char * name)301 RESULT* CSimpleTaskPopupButton::lookup_result(char* url, char* name) {
302 CMainDocument* pDoc = wxGetApp().GetDocument();
303
304 wxASSERT(pDoc);
305 wxASSERT(wxDynamicCast(pDoc, CMainDocument));
306
307 return pDoc->result(wxString(name, wxConvUTF8), wxString(url, wxConvUTF8));
308 }
309