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 #if defined(__GNUG__) && !defined(__APPLE__)
20 #pragma implementation "sg_BoincSimpleFrame.h"
21 #endif
22 
23 #include "stdwx.h"
24 #include "diagnostics.h"
25 #include "str_util.h"
26 #include "mfile.h"
27 #include "miofile.h"
28 #include "parse.h"
29 #include "error_numbers.h"
30 #include "BOINCGUIApp.h"
31 #include "SkinManager.h"
32 #include "MainDocument.h"
33 #include "Events.h"
34 #include "BOINCBaseFrame.h"
35 #include "browser.h"
36 #include "wizardex.h"
37 #include "BOINCBaseWizard.h"
38 #include "WizardAttach.h"
39 #include "error_numbers.h"
40 #include "version.h"
41 
42 #include "sg_BoincSimpleFrame.h"
43 #include "sg_TaskPanel.h"
44 #include "sg_ProjectPanel.h"
45 #include "sg_DlgMessages.h"
46 #include "sg_DlgPreferences.h"
47 #include "DlgEventLog.h"
48 #include "DlgAbout.h"
49 #include "DlgOptions.h"
50 #include "DlgDiagnosticLogFlags.h"
51 
52 
53 #ifdef __WXMAC__
54 #include "util.h"
55 #include "mac_util.h"
56 #endif
57 
58 // Workaround for Linux refresh problem
59 // and Mac keyboard navigation problem
60 #ifdef __WXMSW__
61 #define REFRESH_WAIT 0
62 #else
63 #define REFRESH_WAIT 1
64 #endif
65 
IMPLEMENT_DYNAMIC_CLASS(CSimpleFrame,CBOINCBaseFrame)66 IMPLEMENT_DYNAMIC_CLASS(CSimpleFrame, CBOINCBaseFrame)
67 
68 BEGIN_EVENT_TABLE(CSimpleFrame, CBOINCBaseFrame)
69     EVT_SIZE(CSimpleFrame::OnSize)
70     EVT_MENU_OPEN(CSimpleFrame::OnMenuOpening)
71     EVT_MENU(ID_CHANGEGUI, CSimpleFrame::OnChangeGUI)
72     EVT_MENU(ID_SGDEFAULTSKINSELECTOR, CSimpleFrame::OnSelectDefaultSkin)
73     EVT_MENU_RANGE(ID_SGFIRSTSKINSELECTOR, ID_LASTSGSKINSELECTOR, CSimpleFrame::OnSelectSkin)
74     EVT_HELP(wxID_ANY, CSimpleFrame::OnHelp)
75     EVT_FRAME_CONNECT(CSimpleFrame::OnConnect)
76     EVT_FRAME_RELOADSKIN(CSimpleFrame::OnReloadSkin)
77     EVT_FRAME_NOTIFICATION(CSimpleFrame::OnNotification)
78     EVT_MENU(ID_PREFERENCES, CSimpleFrame::OnPreferences)
79     EVT_MENU(ID_SGOPTIONS, CSimpleFrame::OnOptions)
80 	EVT_MENU(ID_SGDIAGNOSTICLOGFLAGS, CSimpleFrame::OnDiagnosticLogFlags)
81     EVT_MENU(ID_WIZARDATTACHPROJECT, CSimpleFrame::OnProjectsAttachToProject)
82     EVT_MENU(ID_HELPBOINC, CSimpleFrame::OnHelpBOINC)
83     EVT_MENU(ID_HELPBOINCMANAGER, CSimpleFrame::OnHelpBOINC)
84     EVT_MENU(ID_HELPBOINCWEBSITE, CSimpleFrame::OnHelpBOINC)
85     EVT_MENU(wxID_ABOUT, CSimpleFrame::OnHelpAbout)
86     EVT_MENU(ID_CHECK_VERSION, CSimpleFrame::OnCheckVersion)
87 	EVT_MENU(ID_EVENTLOG, CSimpleFrame::OnEventLog)
88     EVT_MOVE(CSimpleFrame::OnMove)
89 #ifdef __WXMAC__
90 	EVT_MENU(wxID_PREFERENCES, CSimpleFrame::OnPreferences)
91 #endif
92 END_EVENT_TABLE()
93 
94 
95 CSimpleFrame::CSimpleFrame() {
96     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::CSimpleFrame - Default Constructor Function Begin"));
97     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::CSimpleFrame - Default Constructor Function End"));
98 }
99 
100 
CSimpleFrame(wxString title,wxIconBundle * icons,wxPoint position,wxSize size)101 CSimpleFrame::CSimpleFrame(wxString title, wxIconBundle* icons, wxPoint position, wxSize size) :
102     CBOINCBaseFrame((wxFrame *)NULL, ID_SIMPLEFRAME, title, position, size,
103                     wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN)
104 {
105     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame:: - Overloaded Constructor Function Begin"));
106 
107     // Initialize Application
108     SetIcons(*icons);
109 
110     CSkinAdvanced*     pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
111     wxString           strMenuName;
112     wxString           strMenuDescription;
113 
114     wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
115 
116     // File menu
117     wxMenu *menuFile = new wxMenu;
118 
119     strMenuDescription.Printf(
120         _("Close the %s window"),
121         pSkinAdvanced->GetApplicationName().c_str()
122     );
123     strMenuName = _("&Close window");
124     strMenuName += wxT("\tCtrl+W");
125     menuFile->Append(
126         ID_CLOSEWINDOW,
127         strMenuName,
128         strMenuDescription
129     );
130 
131     strMenuDescription.Printf(
132         _("Exit %s"),
133         pSkinAdvanced->GetApplicationName().c_str()
134     );
135 
136     strMenuName.Printf(
137         _("Exit %s"),
138         pSkinAdvanced->GetApplicationName().c_str()
139     );
140 
141     menuFile->Append(
142         wxID_EXIT,
143         strMenuName,
144         strMenuDescription
145     );
146 
147 #ifdef __WXMAC__
148     // wxWidgets actually puts this in the BOINCManager menu
149     menuFile->Append(
150         wxID_PREFERENCES,
151         _("Preferences...")
152     );
153 #endif
154 
155     // Skins submenu
156     m_pSubmenuSkins = new wxMenu;
157 
158     BuildSkinSubmenu(m_pSubmenuSkins);
159 
160     // All other skin names will be appended as radio
161     // menu items with ID_SGFIRSTSKINSELECTOR + index
162 
163     // View menu
164     wxMenu *menuView = new wxMenu;
165 
166 
167     menuView->Append(
168         ID_SGSKINSELECTOR,
169         _("Skin"),
170         m_pSubmenuSkins,
171         _("Select the appearance of the user interface.")
172     );
173 
174     // Skins submenu always contains the Default entry
175     if (m_pSubmenuSkins->GetMenuItemCount() <= 1) {
176         menuView->Enable(ID_SGSKINSELECTOR, false);
177     }
178     menuView->AppendSeparator();
179     menuView->Append(
180         ID_CHANGEGUI,
181         _("Advanced View...\tCtrl+Shift+A"),
182         _("Display the advanced graphical interface.")
183     );
184 
185 
186     // Options menu
187     wxMenu *menuOptions = new wxMenu;
188 
189     menuOptions->Append(
190         ID_PREFERENCES,
191         _("Computing &preferences..."),
192         _("Configure computing preferences")
193     );
194 
195     menuOptions->Append(
196         ID_SGOPTIONS,
197         _("&Other options..."),
198         _("Configure display options and proxy settings")
199     );
200 
201     // Tools menu
202     wxMenu *menuTools = new wxMenu;
203     menuTools->Append(
204         ID_WIZARDATTACHPROJECT,
205         _("&Add project..."),
206         _("Add a project")
207     );
208     menuTools->AppendSeparator();
209     menuTools->Append(
210         ID_EVENTLOG,
211         _("Event Log...\tCtrl+Shift+E"),
212         _("Display diagnostic messages.")
213     );
214 
215     // Help menu
216     wxMenu *menuHelp = new wxMenu;
217 
218     strMenuName.Printf(
219         _("%s &help"),
220         pSkinAdvanced->GetApplicationShortName().c_str()
221     );
222     strMenuDescription.Printf(
223         _("Show information about %s"),
224         pSkinAdvanced->GetApplicationShortName().c_str()
225     );
226     menuHelp->Append(
227         ID_HELPBOINC,
228         strMenuName,
229         strMenuDescription
230     );
231 
232     strMenuName.Printf(
233         _("&%s"),
234         pSkinAdvanced->GetApplicationName().c_str()
235     );
236     strMenuDescription.Printf(
237         _("Show information about the %s"),
238         pSkinAdvanced->GetApplicationName().c_str()
239     );
240     menuHelp->Append(
241         ID_HELPBOINCMANAGER,
242         strMenuName,
243         strMenuDescription
244     );
245     menuHelp->AppendSeparator();
246     strMenuName.Printf(
247         _("%s &web site"),
248         pSkinAdvanced->GetApplicationShortName().c_str()
249     );
250     strMenuDescription.Printf(
251         _("Show information about BOINC and %s"),
252         pSkinAdvanced->GetApplicationName().c_str()
253     );
254     menuHelp->Append(
255         ID_HELPBOINCWEBSITE,
256         strMenuName,
257         strMenuDescription
258     );
259     menuHelp->AppendSeparator();
260 
261     strMenuName.Printf(
262         _("Check for new %s version"),
263         pSkinAdvanced->GetApplicationShortName().c_str()
264     );
265     strMenuDescription.Printf(
266         _("Check for new %s version"),
267         pSkinAdvanced->GetApplicationShortName().c_str()
268     );
269     menuHelp->Append(
270         ID_CHECK_VERSION,
271         strMenuName,
272         strMenuDescription
273     );
274     menuHelp->AppendSeparator();
275 
276     strMenuName.Printf(
277         _("&About %s..."),
278         pSkinAdvanced->GetApplicationName().c_str()
279     );
280     menuHelp->Append(
281         wxID_ABOUT,
282         strMenuName,
283         _("Licensing and copyright information.")
284     );
285 
286     // construct menu
287     m_pMenubar = new wxMenuBar;
288     m_pMenubar->Append(
289         menuFile,
290         _("&File")
291     );
292     m_pMenubar->Append(
293         menuView,
294         _("&View")
295     );
296     m_pMenubar->Append(
297         menuOptions,
298         _("&Options")
299     );
300     m_pMenubar->Append(
301         menuTools,
302         _("&Tools")
303     );
304     m_pMenubar->Append(
305         menuHelp,
306         _("&Help")
307     );
308 
309     wxMenuBar* m_pOldMenubar = GetMenuBar();
310     SetMenuBar(m_pMenubar);
311     if (m_pOldMenubar) {
312         delete m_pOldMenubar;
313     }
314 
315 #ifdef __WXGTK__
316     // Force a redraw of the menu under Ubuntu's new interface
317     SendSizeEvent();
318 #endif
319 #ifdef __WXMAC__
320     // Mac needs a short delay to ensure that controls are
321     // created in proper order to allow keyboard navigation
322     m_iFrameRefreshRate = 1;    // 1 millisecond
323     m_pPeriodicRPCTimer->Start(m_iFrameRefreshRate);
324 #endif
325 
326     m_Shortcuts[0].Set(wxACCEL_NORMAL, WXK_HELP, ID_HELPBOINCMANAGER);
327     m_Shortcuts[1].Set(wxACCEL_CTRL|wxACCEL_SHIFT, (int)'E', ID_EVENTLOG);
328     m_Shortcuts[2].Set(wxACCEL_CTRL|wxACCEL_SHIFT, (int)'F', ID_SGDIAGNOSTICLOGFLAGS);
329     m_pAccelTable = new wxAcceleratorTable(3, m_Shortcuts);
330 
331     SetAcceleratorTable(*m_pAccelTable);
332 
333     dlgMsgsPtr = NULL;
334 
335     m_pBackgroundPanel = new CSimpleGUIPanel(this);
336 
337     RestoreState();
338 }
339 
340 
~CSimpleFrame()341 CSimpleFrame::~CSimpleFrame() {
342     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::CSimpleFrame - Destructor Function Begin"));
343 
344     SaveState();
345 
346     if (m_pAccelTable)
347         delete m_pAccelTable;
348 
349     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::CSimpleFrame - Destructor Function End"));
350 }
351 
352 
SaveWindowPosition()353 bool CSimpleFrame::SaveWindowPosition() {
354     wxConfigBase*   pConfig = wxConfigBase::Get(FALSE);
355 	wxString        strBaseConfigLocation = wxString(wxT("/Simple"));
356     wxPoint         pos = GetPosition();
357 
358     wxASSERT(pConfig);
359 
360     // An odd case happens every once and awhile where wxWidgets looses
361     //   the pointer to the config object, or it is cleaned up before
362     //   the window has finished it's cleanup duty.  If we detect a NULL
363     //   pointer, return false.
364     if (!pConfig) return false;
365 
366     pConfig->SetPath(strBaseConfigLocation);
367 
368     pConfig->Write(wxT("XPos"), pos.x);
369     pConfig->Write(wxT("YPos"), pos.y);
370     return true;
371 }
372 
373 
SaveState()374 bool CSimpleFrame::SaveState() {
375 	CBOINCBaseFrame::SaveState();
376     return SaveWindowPosition();
377 }
378 
379 
RestoreState()380 bool CSimpleFrame::RestoreState() {
381 	CBOINCBaseFrame::RestoreState();
382     return true;
383 }
384 
385 
OnMove(wxMoveEvent & event)386 void CSimpleFrame::OnMove(wxMoveEvent& event) {
387     SaveWindowPosition();
388     event.Skip();
389 }
390 
391 
_GetCurrentViewPage()392 int CSimpleFrame::_GetCurrentViewPage() {
393     if (isMessagesDlgOpen()) {
394         return VW_SGUI | VW_SMSG;
395     } else {
396         return VW_SGUI;
397     }
398     return 0;       // Should never happen.
399 }
400 
401 
OnMenuOpening(wxMenuEvent & event)402 void CSimpleFrame::OnMenuOpening( wxMenuEvent &event) {
403     wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnMenuOpening - Function Begin"));
404 
405     CMainDocument*     pDoc = wxGetApp().GetDocument();
406     wxMenu* menuFile = NULL;
407     wxMenu* menuHelp = NULL;
408     wxMenu* menuChangeGUI = NULL;
409 
410     wxASSERT(pDoc);
411 
412     bool isConnected = pDoc->IsConnected();
413     wxMenu* menu = event.GetMenu();
414 
415     menu->FindItem(ID_CLOSEWINDOW, &menuFile);
416     menu->FindItem(ID_HELPBOINC, &menuHelp);
417     menu->FindItem(ID_CHANGEGUI, &menuChangeGUI);
418     size_t numItems = menu->GetMenuItemCount();
419     for (size_t pos = 0; pos < numItems; ++pos) {
420         wxMenuItem * item = menu->FindItemByPosition(pos);
421         if ((menu == menuFile) || (menu == menuHelp) || (menu == menuChangeGUI)) {
422             // Always enable all items in File menu or Help menu:
423             // ID_CLOSEWINDOW, wxID_EXIT, ID_HELPBOINC, ID_HELPBOINCMANAGER,
424             // ID_HELPBOINCWEBSITE, wxID_ABOUT, ID_CHANGEGUI
425             item->Enable(true);
426         } else {
427             // Disable other menu items if not connected to client
428             item->Enable(isConnected);
429         }
430     }
431 
432     // wxID_EXIT and wxID_PREFERENCES are not in File menu on some platforms
433     wxMenuItem* exitItem = menu->FindChildItem(wxID_EXIT, NULL);
434     if (exitItem) {
435         exitItem->Enable(true);
436     }
437 
438     wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnMenuOpening - Function End"));
439 }
440 
441 
OnChangeGUI(wxCommandEvent & WXUNUSED (event))442 void CSimpleFrame::OnChangeGUI(wxCommandEvent& WXUNUSED(event)) {
443     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnChangeGUI - Function Begin"));
444 
445     wxGetApp().SetActiveGUI(BOINC_ADVANCEDGUI, true);
446 
447     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnChangeGUI - Function End"));
448 }
449 
450 
BuildSkinSubmenu(wxMenu * submenu)451 void CSimpleFrame::BuildSkinSubmenu( wxMenu *submenu) {
452     unsigned int i;
453     wxMenuItem *skinItem;
454     wxArrayString astrSkins;
455     wxString strSelectedSkin;
456     CSkinManager* pSkinManager = wxGetApp().GetSkinManager();
457 
458     wxASSERT(pSkinManager);
459     wxASSERT(wxDynamicCast(pSkinManager, CSkinManager));
460 
461 
462     // The "Default" skin menu item is localized, but
463     // the name of the default skin is not localized
464     skinItem = submenu->AppendRadioItem(
465         ID_SGDEFAULTSKINSELECTOR,
466         _("Default")
467     );
468 
469     astrSkins = pSkinManager->GetCurrentSkins();
470     strSelectedSkin = pSkinManager->GetSelectedSkin();
471 
472     if (strSelectedSkin == pSkinManager->GetDefaultSkinName()) {
473         skinItem->Check(true);
474     }
475 
476     // Skins list always contains the Default entry
477     if (astrSkins.GetCount() <= 1) {
478         skinItem->Check(true);
479         skinItem->Enable(false);
480         return; // No non-default skins
481     }
482 
483 //    I'd like to put a separator here, but we can't separate radio items
484 
485     for (i = 0; i < astrSkins.GetCount(); i++) {
486         if (astrSkins[i] == pSkinManager->GetDefaultSkinName()) {
487             continue;
488         }
489 
490         skinItem = submenu->AppendRadioItem(
491             ID_SGFIRSTSKINSELECTOR + i,
492             astrSkins[i]
493         );
494         if (astrSkins[i] == strSelectedSkin) {
495             skinItem->Check(true);
496         }
497     }
498 }
499 
500 
501 
OnSelectDefaultSkin(wxCommandEvent & WXUNUSED (event))502 void CSimpleFrame::OnSelectDefaultSkin( wxCommandEvent& WXUNUSED(event) ) {
503     CSkinManager* pSkinManager = wxGetApp().GetSkinManager();
504 
505     wxASSERT(pSkinManager);
506     wxASSERT(wxDynamicCast(pSkinManager, CSkinManager));
507 
508     // The "Default" skin menu item is localized, but
509     // the name of the default skin is not localized
510     pSkinManager->ReloadSkin(pSkinManager->GetDefaultSkinName());
511 }
512 
513 
OnSelectSkin(wxCommandEvent & event)514 void CSimpleFrame::OnSelectSkin( wxCommandEvent& event ){
515     CSkinManager *pSkinManager = wxGetApp().GetSkinManager();
516     wxMenuItem *oldItem, *selectedItem;
517     wxMenuBar *pMenuBar = GetMenuBar();
518     int newSkinId = event.GetId();
519     int oldSkinID;
520 
521     wxASSERT(pSkinManager);
522     wxASSERT(wxDynamicCast(pSkinManager, CSkinManager));
523 
524 
525     selectedItem = pMenuBar->FindItem(newSkinId);
526     if (!selectedItem) return;
527 
528     wxString oldSkinName = pSkinManager->GetSelectedSkin();
529     wxString newSkinName = selectedItem->GetItemLabelText();
530     if (newSkinName == oldSkinName) return;
531 
532     if (oldSkinName == pSkinManager->GetDefaultSkinName()) {
533         // The "Default" skin menu item is localized, but
534         // the name of the default skin is not localized
535         oldSkinID = ID_SGDEFAULTSKINSELECTOR;
536     } else {
537         oldSkinID = m_pSubmenuSkins->FindItem(oldSkinName);
538     }
539     oldItem = m_pSubmenuSkins->FindItem(oldSkinID);
540     if (oldItem) {
541         oldItem->Check(false);
542     }
543 
544     selectedItem->Check(true);
545     pSkinManager->ReloadSkin(newSkinName);
546 
547     wxGetApp().SaveState();
548     wxConfigBase::Get(FALSE)->Flush();
549 }
550 
551 
OnPreferences(wxCommandEvent & WXUNUSED (event))552 void CSimpleFrame::OnPreferences(wxCommandEvent& WXUNUSED(event)) {
553     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnPreferences - Function Begin"));
554 
555 	m_pBackgroundPanel->SetDlgOpen(true);
556 
557 	CDlgPreferences dlg(GetParent());
558     if (dlg.OKToShow()) {
559         dlg.ShowModal();
560     }
561 
562     m_pBackgroundPanel->SetDlgOpen(false);
563 
564     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnPreferences - Function End"));
565 }
566 
567 
OnOptions(wxCommandEvent & WXUNUSED (event))568 void CSimpleFrame::OnOptions(wxCommandEvent& WXUNUSED(event)) {
569     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnOptions - Function Begin"));
570 
571 	m_pBackgroundPanel->SetDlgOpen(true);
572 
573 // TODO:  Create simple language selection dialog
574     CDlgOptions dlg(this);
575     dlg.ShowModal();
576 
577     m_pBackgroundPanel->SetDlgOpen(false);
578 
579     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnOptions - Function End"));
580 }
581 
582 
OnDiagnosticLogFlags(wxCommandEvent & WXUNUSED (event))583 void CSimpleFrame::OnDiagnosticLogFlags(wxCommandEvent& WXUNUSED(event)) {
584     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnDiagnosticLogFlags - Function Begin"));
585 
586     CDlgDiagnosticLogFlags dlg(this);
587 	dlg.ShowModal();
588 
589     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnDiagnosticLogFlags - Function End"));
590 }
591 
592 
593 // TODO: Create ID_HELPBOINCMANAGER web page for each organization for new BOINC version
OnHelpBOINC(wxCommandEvent & event)594 void CSimpleFrame::OnHelpBOINC(wxCommandEvent& event) {
595     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnHelpBOINC - Function Begin"));
596 
597     if (IsShown()) {
598     	wxString strURL = wxGetApp().GetSkinManager()->GetAdvanced()->GetOrganizationHelpUrl();
599 
600 		wxString wxurl;
601 		wxurl.Printf(
602             wxT("%s?target=simple&version=%s&controlid=%d"),
603             strURL.c_str(),
604             wxString(BOINC_VERSION_STRING, wxConvUTF8).c_str(),
605             event.GetId()
606         );
607 		wxLaunchDefaultBrowser(wxurl);
608     }
609 
610     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnHelpBOINC - Function End"));
611 }
612 
613 
OnHelpAbout(wxCommandEvent &)614 void CSimpleFrame::OnHelpAbout(wxCommandEvent& /*event*/) {
615     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnHelpAbout - Function Begin"));
616 
617 	m_pBackgroundPanel->SetDlgOpen(true);
618 
619     CDlgAbout dlg(this);
620     wxGetApp().SetAboutDialogIsOpen(true);
621     dlg.ShowModal();
622     wxGetApp().SetAboutDialogIsOpen(false);
623 
624     m_pBackgroundPanel->SetDlgOpen(false);
625 
626     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnHelpAbout - Function End"));
627 }
628 
OnCheckVersion(wxCommandEvent & WXUNUSED (event))629 void CSimpleFrame::OnCheckVersion(wxCommandEvent& WXUNUSED(event)) {
630     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnCheckVersion - Function Begin"));
631 
632     wxGetApp().GetDocument()->CheckForVersionUpdate(true);
633 
634     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnCheckVersion - Function End"));
635 }
636 
637 
OnHelp(wxHelpEvent & event)638 void CSimpleFrame::OnHelp(wxHelpEvent& event) {
639     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnHelp - Function Begin"));
640 
641     if (IsShown()) {
642     	wxString strURL = wxGetApp().GetSkinManager()->GetAdvanced()->GetOrganizationHelpUrl();
643 
644 		wxString wxurl;
645 		wxurl.Printf(
646             wxT("%s?target=simple&version=%s&controlid=%d"),
647             strURL.c_str(),
648             wxString(BOINC_VERSION_STRING, wxConvUTF8).c_str(),
649             event.GetId()
650         );
651         wxLaunchDefaultBrowser(wxurl);
652     }
653 
654     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnHelp - Function End"));
655 }
656 
657 
OnReloadSkin(CFrameEvent & WXUNUSED (event))658 void CSimpleFrame::OnReloadSkin(CFrameEvent& WXUNUSED(event)) {
659     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnReloadSkin - Function Start"));
660 
661     CSkinAdvanced*      pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
662     wxASSERT(pSkinAdvanced);
663 
664     m_pBackgroundPanel->ReskinInterface();
665     SetTitle(pSkinAdvanced->GetApplicationName());
666     SetIcon(pSkinAdvanced->GetApplicationIcon()->GetIcon(wxDefaultSize));
667 
668     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnReloadSkin - Function End"));
669 }
670 
671 
OnNotification(CFrameEvent & WXUNUSED (event))672 void CSimpleFrame::OnNotification(CFrameEvent& WXUNUSED(event)) {
673     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnNotification - Function Begin"));
674 
675 	CDlgMessages dlg(GetParent());
676 
677     m_pBackgroundPanel->SetDlgOpen(true);
678     SetMsgsDlgOpen(&dlg);
679 
680     m_pBackgroundPanel->NoticesViewed();
681     dlg.ShowModal();
682 
683     m_pBackgroundPanel->SetDlgOpen(false);
684     SetMsgsDlgOpen(NULL);
685 
686     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnNotification - Function End"));
687 }
688 
689 
OnRefreshView(CFrameEvent & WXUNUSED (event))690 void CSimpleFrame::OnRefreshView(CFrameEvent& WXUNUSED(event)) {
691     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnRefreshView - Function Start"));
692 
693     m_pBackgroundPanel->OnFrameRender();
694 
695     if (dlgMsgsPtr) {
696         dlgMsgsPtr->OnRefresh();
697     }
698 
699 #ifdef __WXMAC__
700     if (m_iFrameRefreshRate != 1000) {
701         m_iFrameRefreshRate = 1000;
702         m_pPeriodicRPCTimer->Start(m_iFrameRefreshRate);
703     }
704 
705     // We disabled tooltips on Mac while menus were popped up because they cover menus
706     wxToolTip::Enable(true);
707 #endif
708 
709     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnRefreshView - Function End"));
710 }
711 
712 
OnProjectsAttachToProject(wxCommandEvent & WXUNUSED (event))713 void CSimpleFrame::OnProjectsAttachToProject(wxCommandEvent& WXUNUSED(event)) {
714     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnProjectsAttachToProject - Function Begin"));
715 
716     CMainDocument* pDoc     = wxGetApp().GetDocument();
717 
718     wxASSERT(pDoc);
719     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
720 
721     if (!pDoc->IsUserAuthorized())
722         return;
723 
724     if (pDoc->IsConnected()) {
725 
726         CWizardAttach* pWizard = new CWizardAttach(this);
727 
728         pWizard->Run(
729             wxEmptyString,
730             wxEmptyString,
731             wxEmptyString,
732             wxEmptyString,
733             wxEmptyString,
734             wxEmptyString,
735             wxEmptyString,
736             false,
737             false
738         );
739 
740         if (pWizard)
741             pWizard->Destroy();
742 
743     } else {
744         ShowNotCurrentlyConnectedAlert();
745     }
746 
747     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnProjectsAttachToProject - Function End"));
748 }
749 
750 
OnConnect(CFrameEvent & WXUNUSED (event))751 void CSimpleFrame::OnConnect(CFrameEvent& WXUNUSED(event)) {
752     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnConnect - Function Begin"));
753 
754     CMainDocument*     pDoc = wxGetApp().GetDocument();
755     CWizardAttach*     pWizard = NULL;
756     wxString strComputer = wxEmptyString;
757     std::string strProjectName;
758     std::string strProjectURL;
759     std::string strProjectAuthenticator;
760     std::string strProjectInstitution;
761     std::string strProjectDescription;
762     std::string strProjectKnown;
763     std::string strProjectSetupCookie;
764     bool        bAccountKeyDetected = false;
765     bool        bEmbedded = false;
766     ACCT_MGR_INFO ami;
767     PROJECT_INIT_STATUS pis;
768 	CC_STATUS     status;
769     int wasShown = 0;
770     int wasVisible = 0;
771 
772     wxASSERT(pDoc);
773     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
774 
775     pDoc->ForceCacheUpdate();
776     pDoc->GetCoreClientStatus(status, true);
777 
778 	// If we are connected to the localhost, run a really quick screensaver
779     //   test to trigger a firewall popup.
780     pDoc->GetConnectedComputerName(strComputer);
781     if (pDoc->IsComputerNameLocal(strComputer)) {
782         wxGetApp().StartBOINCScreensaverTest();
783         wxGetApp().StartBOINCDefaultScreensaverTest();
784     }
785 
786 
787     pDoc->rpc.get_project_init_status(pis);
788     pDoc->rpc.acct_mgr_info(ami);
789 
790     if (ami.acct_mgr_url.size() && ami.have_credentials) {
791         // Fall through
792         //
793         // There isn't a need to bring up the attach wizard, the account manager will
794         // take care of ataching to projects when it completes the RPCs
795         //
796     } else if (ami.acct_mgr_url.size() && !ami.have_credentials) {
797         wasShown = IsShown();
798         Show();
799         wasVisible = wxGetApp().IsApplicationVisible();
800         if (!wasVisible) {
801             wxGetApp().ShowApplication(true);
802         }
803 
804         pWizard = new CWizardAttach(this);
805         if (pWizard->SyncToAccountManager()) {
806 
807             // _GRIDREPUBLIC, _PROGRESSTHRUPROCESSORS and _CHARITYENGINE
808             // are defined for those branded builds on Windows only
809 #if defined(_GRIDREPUBLIC) || defined(_PROGRESSTHRUPROCESSORS) || defined(_CHARITYENGINE) || defined(__WXMAC__)
810 #ifdef __WXMAC__
811             // For GridRepublic, Charity Engine or ProgressThruProcessors,
812             // the Mac installer put a branding file in our data directory
813             long iBrandID = 0;  // 0 is unbranded (default) BOINC
814 
815             FILE *f = boinc_fopen("/Library/Application Support/BOINC Data/Branding", "r");
816             if (f) {
817                 fscanf(f, "BrandId=%ld\n", &iBrandID);
818                 fclose(f);
819             }
820             if ((iBrandID > 0) && (iBrandID < 4))
821 #endif
822             {
823                 // If successful, hide the main window if we showed it
824                 if (!wasVisible) {
825                     wxGetApp().ShowApplication(false);
826                 }
827 #ifndef __WXMAC__   // See comment in CBOINCGUIApp::OnFinishInit()
828                 if (!wasShown) {
829                     Hide();
830                 }
831 #endif
832             }
833 #endif
834         }
835     } else if ((0 >= pDoc->GetProjectCount()) && !status.disallow_attach) {
836         if (pis.url.size() > 0) {
837 
838             strProjectName = pis.name.c_str();
839             strProjectURL = pis.url.c_str();
840             strProjectSetupCookie = pis.setup_cookie.c_str();
841             bAccountKeyDetected = pis.has_account_key;
842             bEmbedded = pis.embedded;
843 
844             // If credentials are not cached, then we should try one last place to look up the
845             //   authenticator.  Some projects will set a "Setup" cookie off of their URL with a
846             //   pretty short timeout.  Lets take a crack at detecting it.
847             //
848             if (pis.url.length() && !pis.has_account_key) {
849                 detect_setup_authenticator(pis.url, strProjectAuthenticator);
850             }
851 
852         } else {
853             detect_simple_account_credentials(
854                 strProjectName, strProjectURL, strProjectAuthenticator, strProjectInstitution, strProjectDescription, strProjectKnown
855             );
856         }
857 
858         Show();
859         wxGetApp().ShowApplication(true);
860         pWizard = new CWizardAttach(this);
861 
862         pWizard->Run(
863             wxURI::Unescape(strProjectName),
864             wxURI::Unescape(strProjectURL),
865             wxURI::Unescape(strProjectAuthenticator),
866             wxURI::Unescape(strProjectInstitution),
867             wxURI::Unescape(strProjectDescription),
868             wxURI::Unescape(strProjectKnown),
869             wxURI::Unescape(strProjectSetupCookie),
870             bAccountKeyDetected,
871             bEmbedded
872         );
873     }
874 
875  	if (pWizard) {
876         pWizard->Destroy();
877         m_pBackgroundPanel->UpdateProjectView();
878 	}
879 
880     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnConnect - Function End"));
881 }
882 
883 
OnEventLog(wxCommandEvent & WXUNUSED (event))884 void CSimpleFrame::OnEventLog(wxCommandEvent& WXUNUSED(event)) {
885     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnEventLog - Function Begin"));
886 
887     wxGetApp().DisplayEventLog();
888 
889     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnEventLog - Function End"));
890 }
891 
892 
IMPLEMENT_DYNAMIC_CLASS(CSimpleGUIPanel,wxPanel)893 IMPLEMENT_DYNAMIC_CLASS(CSimpleGUIPanel, wxPanel)
894 
895 BEGIN_EVENT_TABLE(CSimpleGUIPanel, wxPanel)
896     EVT_ERASE_BACKGROUND(CSimpleGUIPanel::OnEraseBackground)
897 	EVT_BUTTON(ID_SGNOTICESBUTTON,CSimpleGUIPanel::OnShowNotices)
898 	EVT_BUTTON(ID_SGSUSPENDRESUMEBUTTON,CSimpleGUIPanel::OnSuspendResume)
899 	EVT_BUTTON(ID_SIMPLE_HELP,CSimpleGUIPanel::OnHelp)
900 	EVT_TIMER(ID_SIMPLEMESSAGECHECKTIMER, CSimpleGUIPanel::OnCheckForNewNotices)
901     EVT_PAINT(CSimpleGUIPanel::OnPaint)
902 END_EVENT_TABLE()
903 
904 
905 CSimpleGUIPanel::CSimpleGUIPanel() {
906     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Default Constructor Function Begin"));
907     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Default Constructor Function End"));
908 }
909 
910 
CSimpleGUIPanel(wxWindow * parent)911 CSimpleGUIPanel::CSimpleGUIPanel(wxWindow* parent) :
912     wxPanel(parent, -1, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN | wxBORDER_NONE)
913 {
914     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Overloaded Constructor Function Begin"));
915 
916     CSkinAdvanced*     pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
917 
918     wxASSERT(pSkinAdvanced);
919     wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
920 
921     m_taskPanel = NULL;
922     m_projPanel = NULL;
923     m_oldWorkCount = 0;
924     m_bNewNoticeAlert = false;
925     m_bNoticesButtonIsRed = false;
926     m_irefreshCount = 0;
927 
928 	checkForNewNoticesTimer = new wxTimer(this, ID_SIMPLEMESSAGECHECKTIMER);
929 	checkForNewNoticesTimer->Start(5000);
930 
931 	dlgOpen = false;
932     m_sSuspendString = _("Suspend");
933     m_sResumeString = _("Resume");
934     m_sSuspendButtonToolTip = _("Suspend Computing");
935     m_sResumeButtonToolTip = _("Resume Computing");
936 
937 	m_taskPanel = new CSimpleTaskPanel(this);
938     m_projPanel = new CSimpleProjectPanel(this);
939 
940     // Box Sizer
941     mainSizer = new wxBoxSizer(wxVERTICAL);
942     mainSizer->AddSpacer(ADJUSTFORYDPI(68));
943     mainSizer->Add(m_taskPanel, 1, wxLEFT | wxRIGHT | wxEXPAND | wxALIGN_CENTER, SIDEMARGINS);
944     mainSizer->AddSpacer(ADJUSTFORYDPI(8));
945     mainSizer->Add(m_projPanel, 0, wxLEFT | wxRIGHT | wxEXPAND | wxALIGN_CENTER, SIDEMARGINS);
946     mainSizer->AddSpacer(ADJUSTFORYDPI(8));
947 
948 	wxBoxSizer* buttonsSizer;
949 	buttonsSizer = new wxBoxSizer( wxHORIZONTAL );
950 
951 	m_NoticesButton = new wxButton( this, ID_SGNOTICESBUTTON, _("Notices"), wxDefaultPosition, wxDefaultSize, 0 );
952     m_NoticesButton->SetToolTip( _("Open a window to view notices from projects or BOINC"));
953 	buttonsSizer->Add( m_NoticesButton, 0, wxEXPAND | wxALIGN_LEFT, 0 );
954     buttonsSizer->AddStretchSpacer();
955 
956     int suspendWidth, resumeWidth, y;
957     GetTextExtent(m_sSuspendString, &suspendWidth, &y);
958     GetTextExtent(m_sResumeString, &resumeWidth, &y);
959 
960     m_bIsSuspended = suspendWidth > resumeWidth;
961     m_SuspendResumeButton = new wxButton( this, ID_SGSUSPENDRESUMEBUTTON,
962                             m_bIsSuspended ? m_sSuspendString : m_sResumeString,
963                             wxDefaultPosition, wxDefaultSize, 0 );
964     m_SuspendResumeButton->SetToolTip(wxEmptyString);
965 
966 	buttonsSizer->Add( m_SuspendResumeButton, 0, wxEXPAND | wxALIGN_RIGHT, 0 );
967     buttonsSizer->AddStretchSpacer();
968 
969     m_HelpButton = new wxButton( this, ID_SIMPLE_HELP, _("Help"), wxDefaultPosition, wxDefaultSize, 0 );
970 	buttonsSizer->Add( m_HelpButton, 0, wxEXPAND | wxALIGN_RIGHT, 0 );
971 
972     wxString helpTip;
973     helpTip.Printf(_("Get help with %s"), pSkinAdvanced->GetApplicationShortName().c_str());
974     m_HelpButton->SetToolTip(helpTip);
975 
976 	mainSizer->Add( buttonsSizer, 0, wxLEFT | wxRIGHT | wxEXPAND, 2 * SIDEMARGINS );
977     mainSizer->AddSpacer(ADJUSTFORYDPI(10));
978 
979 	SetSizer(mainSizer);
980     Layout();
981 
982     mainSizer->Fit(GetParent());
983 
984     SetBackgroundBitmap();
985 
986 #ifdef __WXMAC__
987     // Tell accessibility aids to ignore this panel (but not its contents)
988     HIObjectSetAccessibilityIgnored((HIObjectRef)GetHandle(), true);
989 
990     if (compareOSVersionTo(10, 7) >= 0) {
991         m_iRedRingRadius = 4;
992     } else {
993         m_iRedRingRadius = 12;
994     }
995 #endif
996 
997     m_SuspendResumeButton->Disable();
998 
999     OnFrameRender();
1000 
1001     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Overloaded Constructor Function End"));
1002 }
1003 
1004 
~CSimpleGUIPanel()1005 CSimpleGUIPanel::~CSimpleGUIPanel()
1006 {
1007     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Destructor Function Begin"));
1008 
1009     checkForNewNoticesTimer->Stop();
1010 	delete checkForNewNoticesTimer;
1011     m_bmpBg = wxNullBitmap; // Deletes old bitmap via reference counting
1012 
1013     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Destructor Function End"));
1014 }
1015 
1016 
SetBackgroundBitmap()1017 void CSimpleGUIPanel::SetBackgroundBitmap() {
1018     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::SetBackgroundBitmap - Function Start"));
1019 
1020     CSkinSimple* pSkinSimple = wxGetApp().GetSkinManager()->GetSimple();
1021 
1022     wxASSERT(pSkinSimple);
1023     wxASSERT(wxDynamicCast(pSkinSimple, CSkinSimple));
1024 
1025     wxColour bgColor(*pSkinSimple->GetBackgroundImage()->GetBackgroundColor());
1026     SetBackgroundColour(bgColor);
1027     wxRect panelRect = GetRect();
1028     m_bmpBg = wxBitmap(panelRect.width, panelRect.height);
1029     wxMemoryDC dc(m_bmpBg);
1030     wxBrush bgBrush(bgColor);
1031     dc.SetBackground(bgBrush);
1032     dc.Clear();
1033 #ifdef __WXMAC__
1034     // Work around an apparent bug in wxMemoryDC::Clear() in wxCarbon 2.9.4
1035     // TODO: remove this when the wxCarbon bug is fixed
1036     dc.SetBrush(bgBrush);
1037     wxPen bgPen(bgColor);
1038     dc.SetPen(bgPen);
1039     dc.DrawRectangle(panelRect);
1040 #endif
1041 
1042     int srcX, srcY, destX, destY, h, w;
1043     wxBitmap* srcBmp = pSkinSimple->GetBackgroundImage()->GetBitmap();
1044     wxSize srcSize = srcBmp->GetSize();
1045     switch(pSkinSimple->GetBackgroundImage()->GetHorizontalAnchor()) {
1046     case BKGD_ANCHOR_HORIZ_LEFT:
1047     default:
1048         srcX = 0;
1049         destX = 0;
1050         break;
1051     case BKGD_ANCHOR_HORIZ_CENTER:
1052         if (panelRect.width < srcSize.GetWidth()) {
1053             srcX = (srcSize.GetWidth() - panelRect.width) / 2;
1054             destX = 0;
1055         } else {
1056             srcX = 0;
1057             destX = (panelRect.width - srcSize.GetWidth()) / 2;
1058         }
1059         break;
1060     case BKGD_ANCHOR_HORIZ_RIGHT:
1061         if (panelRect.width < srcSize.GetWidth()) {
1062             srcX = (srcSize.GetWidth() - panelRect.width);
1063             destX = 0;
1064         } else {
1065             srcX = 0;
1066             destX = (panelRect.width - srcSize.GetWidth());
1067         }
1068         break;
1069     }
1070     w = wxMin(panelRect.width, srcSize.GetWidth());
1071 
1072     switch(pSkinSimple->GetBackgroundImage()->GetVerticalAnchor()) {
1073     case BKGD_ANCHOR_VERT_TOP:
1074     default:
1075         srcY = 0;
1076         destY = 0;
1077         break;
1078     case BKGD_ANCHOR_VERT_CENTER:
1079         if (panelRect.height < srcSize.GetHeight()) {
1080             srcY = (srcSize.GetHeight() - panelRect.height) / 2;
1081             destY = 0;
1082         } else {
1083             srcY = 0;
1084             destY = (panelRect.height - srcSize.GetHeight()) / 2;
1085         }
1086         break;
1087     case BKGD_ANCHOR_VERT_BOTTOM:
1088         if (panelRect.height < srcSize.GetHeight()) {
1089             srcY = (srcSize.GetHeight() - panelRect.height);
1090             destY = 0;
1091         } else {
1092             srcY = 0;
1093             destY = (panelRect.height - srcSize.GetHeight());
1094         }
1095         break;
1096     }
1097     h = wxMin(panelRect.height, srcSize.GetHeight());
1098 
1099     wxMemoryDC srcDC(*srcBmp);
1100     dc.Blit(destX, destY, w, h, &srcDC, srcX, srcY, wxCOPY);
1101 
1102 //    dc.DrawBitmap(*pSkinSimple->GetBackgroundImage()->GetBitmap(), 0, 0, false);
1103 
1104     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::SetBackgroundBitmap - Function End"));
1105 }
1106 
ReskinInterface()1107 void CSimpleGUIPanel::ReskinInterface() {
1108     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::ReskinInterface - Function Start"));
1109 
1110     Freeze();
1111     //bg color
1112     m_bmpBg = wxNullBitmap; // Deletes old bitmap via reference counting
1113     SetBackgroundBitmap();
1114 
1115     m_taskPanel->ReskinInterface();
1116 	m_projPanel->ReskinInterface();
1117 
1118     Thaw();
1119     Refresh();
1120 
1121     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::ReskinInterface - Function End"));
1122 }
1123 
1124 
OnProjectsAttachToProject(wxCommandEvent & event)1125 void CSimpleGUIPanel::OnProjectsAttachToProject(wxCommandEvent& event) {
1126     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::OnProjectsAttachToProject - Function Begin"));
1127 
1128     CSimpleFrame* pFrame = wxDynamicCast(GetParent(), CSimpleFrame);
1129     wxASSERT(pFrame);
1130 
1131     pFrame->OnProjectsAttachToProject(event);
1132 
1133     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnProjectsAttachToProject - Function End"));
1134 }
1135 
1136 
1137 // called from CSimpleFrame::OnRefreshView()
OnFrameRender()1138 void CSimpleGUIPanel::OnFrameRender() {
1139     CMainDocument*      pDoc = wxGetApp().GetDocument();
1140     wxASSERT(pDoc);
1141     int                 workCount = pDoc->GetSimpleGUIWorkCount();
1142 	CC_STATUS           status;
1143     bool                isSuspended;
1144 
1145     // OnFrameRender() may be called while SimpleGUI initialization is
1146     // in progress due to completion of a periodic get_messages RPC,
1147     // causing unintended recursion in CMainDocument::RequestRPC().
1148     // Check for that situation here.
1149     if (pDoc->WaitingForRPC()) return;
1150 
1151     // Workaround for Linux refresh problem
1152     if (m_irefreshCount < REFRESH_WAIT) {
1153         ++m_irefreshCount;
1154         m_taskPanel->UpdatePanel(true);
1155         return;
1156     }
1157 
1158     if (workCount != m_oldWorkCount) {
1159         if (workCount < 0) {
1160             m_projPanel->Hide();
1161         } else if (m_oldWorkCount == 0) {
1162             m_projPanel->Show();
1163         }
1164         this->Layout();
1165         ReskinInterface();
1166     }
1167 
1168     if (IsShown()) {
1169 	    if ( pDoc->IsConnected() ) {
1170 
1171             // Show Resume or Suspend as appropriate
1172             pDoc->GetCoreClientStatus(status);
1173 
1174             isSuspended = (RUN_MODE_NEVER == status.task_mode);
1175             if ((isSuspended != m_bIsSuspended) || (!m_SuspendResumeButton->IsEnabled())) {
1176                 m_bIsSuspended = isSuspended;
1177                 m_SuspendResumeButton->SetLabel(m_bIsSuspended ? m_sResumeString : m_sSuspendString);
1178                 m_SuspendResumeButton->SetToolTip(m_bIsSuspended ? m_sResumeButtonToolTip : m_sSuspendButtonToolTip);
1179             }
1180             m_SuspendResumeButton->Enable();
1181 	    } else {
1182             m_SuspendResumeButton->SetToolTip(wxEmptyString);
1183             m_SuspendResumeButton->Disable();
1184         }
1185 
1186 		UpdateProjectView();
1187 
1188         if (m_bNewNoticeAlert) {
1189             wxRect r = m_NoticesButton->GetRect();
1190             r.Inflate(4, 4);
1191             RefreshRect(r, m_bNoticesButtonIsRed);
1192             m_bNoticesButtonIsRed = !m_bNoticesButtonIsRed;
1193         }
1194 
1195 
1196         // State changes can cause the BSG to crash if a dialogue is open.
1197         // Defer state change until after the dialogue is closed
1198         if ( dlgOpen ) {
1199             return;
1200         }
1201 
1202         m_oldWorkCount = workCount;
1203 
1204         m_taskPanel->UpdatePanel(false);
1205     }
1206 }
1207 
1208 
UpdateProjectView()1209 void CSimpleGUIPanel::UpdateProjectView()
1210 {
1211 	//update Project Panel
1212     m_projPanel->UpdateInterface();
1213 }
1214 
1215 
OnCheckForNewNotices(wxTimerEvent & WXUNUSED (event))1216 void CSimpleGUIPanel::OnCheckForNewNotices(wxTimerEvent& WXUNUSED(event)) {
1217 	CMainDocument* pDoc = wxGetApp().GetDocument();
1218 	if ( pDoc->GetUnreadNoticeCount() ) {
1219         m_bNewNoticeAlert = true;
1220         checkForNewNoticesTimer->Stop();
1221 	}
1222 }
1223 
1224 
NoticesViewed()1225 void CSimpleGUIPanel::NoticesViewed() {
1226 	CMainDocument* pDoc = wxGetApp().GetDocument();
1227 
1228     wxASSERT(pDoc);
1229 
1230 	m_bNewNoticeAlert = false;
1231     m_bNoticesButtonIsRed = false;
1232     wxRect r = m_NoticesButton->GetRect();
1233     r.Inflate(4, 4);
1234     RefreshRect(r, true);
1235     m_bNoticesButtonIsRed = !m_bNoticesButtonIsRed;
1236 	pDoc->UpdateUnreadNoticeState();
1237 	checkForNewNoticesTimer->Start();
1238 }
1239 
1240 
OnShowNotices(wxCommandEvent &)1241 void CSimpleGUIPanel::OnShowNotices(wxCommandEvent& /*event*/) {
1242     NoticesViewed();
1243 
1244 	CDlgMessages dlg(GetParent());
1245     SetDlgOpen(true);
1246 
1247     ((CSimpleFrame*)GetParent())->SetMsgsDlgOpen(&dlg);
1248 
1249     dlg.ShowModal();
1250 
1251     SetDlgOpen(false);
1252     ((CSimpleFrame*)GetParent())->SetMsgsDlgOpen(NULL);
1253 }
1254 
1255 
OnSuspendResume(wxCommandEvent &)1256 void CSimpleGUIPanel::OnSuspendResume(wxCommandEvent& /*event*/) {
1257     CMainDocument* pDoc      = wxGetApp().GetDocument();
1258     CC_STATUS ccs;
1259 
1260     wxASSERT(pDoc);
1261     wxASSERT(wxDynamicCast(pDoc, CMainDocument));
1262 
1263     if (m_bIsSuspended) {
1264         pDoc->GetCoreClientStatus(ccs);
1265 
1266         if ((RUN_MODE_NEVER == ccs.task_mode) && (0 >= ccs.task_mode_delay)) {
1267             pDoc->SetActivityRunMode(RUN_MODE_AUTO, 0);
1268         } else {
1269             pDoc->SetActivityRunMode(RUN_MODE_RESTORE, 0);
1270         }
1271     } else {
1272         pDoc->SetActivityRunMode(RUN_MODE_NEVER, 3600);
1273     }
1274 
1275     m_SuspendResumeButton->SetLabel(m_bIsSuspended ? m_sResumeString : m_sSuspendString);
1276     m_SuspendResumeButton->SetToolTip(m_bIsSuspended ? m_sResumeButtonToolTip : m_sSuspendButtonToolTip);
1277 }
1278 
1279 
1280 // TODO: Create ID_SIMPLE_HELP web page for each organization for new BOINC version
OnHelp(wxCommandEvent & WXUNUSED (event))1281 void CSimpleGUIPanel::OnHelp(wxCommandEvent& WXUNUSED(event)) {
1282     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::OnHelp - Function Begin"));
1283 
1284 	wxString strURL = wxGetApp().GetSkinManager()->GetAdvanced()->GetOrganizationHelpUrl();
1285 
1286     wxString wxurl;
1287     wxurl.Printf(
1288         wxT("%s?target=simple&version=%s&controlid=%d"),
1289         strURL.c_str(),
1290         wxString(BOINC_VERSION_STRING, wxConvUTF8).c_str(),
1291         ID_SIMPLE_HELP
1292 
1293     );
1294 
1295     wxLaunchDefaultBrowser(wxurl);
1296 
1297     wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::OnHelp - Function End"));
1298 }
1299 
1300 
OnPaint(wxPaintEvent & WXUNUSED (event))1301 void CSimpleGUIPanel::OnPaint(wxPaintEvent& WXUNUSED(event)) {
1302 	wxPaintDC myDC(this);
1303 
1304     if (m_bNewNoticeAlert) {
1305         wxRect r = m_NoticesButton->GetRect();
1306         if (m_bNoticesButtonIsRed) {
1307 			CSkinSimple* pSkinSimple = wxGetApp().GetSkinManager()->GetSimple();
1308             wxPen oldPen = myDC.GetPen();
1309             wxBrush oldBrush = myDC.GetBrush();
1310             int oldMode = myDC.GetBackgroundMode();
1311 			wxPen bgPen(pSkinSimple->GetNoticeAlertColor(), 3);
1312             myDC.SetBackgroundMode(wxSOLID);
1313             myDC.SetPen(bgPen);
1314             myDC.SetBrush(*wxTRANSPARENT_BRUSH);
1315 #ifdef __WXMAC__
1316             r.Inflate(2, 2);
1317             myDC.DrawRoundedRectangle(r.x, r.y, r.width, r.height+1, m_iRedRingRadius);
1318 #elif defined(__WXMSW__)
1319             r.Inflate(3, 3);
1320             myDC.DrawRectangle(r.x, r.y, r.width, r.height);
1321 #else
1322             r.Inflate(3, 3);
1323             myDC.DrawRoundedRectangle(r.x, r.y, r.width, r.height, 6);
1324 #endif
1325             // Restore Mode, Pen and Brush
1326             myDC.SetBackgroundMode(oldMode);
1327             myDC.SetPen(oldPen);
1328             myDC.SetBrush(oldBrush);
1329         }
1330     }
1331 }
1332 
1333 
1334 // We don't reliably get EraseBackground events under Linux,
1335 // so there is a workaround at CSimplePanelBase::MakeBGBitMap()
OnEraseBackground(wxEraseEvent & event)1336 void CSimpleGUIPanel::OnEraseBackground(wxEraseEvent& event) {
1337     wxDC *dc = event.GetDC();
1338 
1339 #ifdef __WXMAC__
1340     // Avoid unnecessary drawing due to Mac progress indicator's animation
1341     wxRect clipRect;
1342     wxRect taskRect = m_taskPanel->GetRect();
1343     dc->GetClippingBox(&clipRect.x, &clipRect.y, &clipRect.width, &clipRect.height);
1344     if (clipRect.IsEmpty() || taskRect.Contains(clipRect)) {
1345         return;
1346     }
1347 #endif
1348     dc->DrawBitmap(m_bmpBg, 0, 0);
1349 }
1350