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