From bf789a23dbc04474ddaa5a326a7b7c68b29fb50e Mon Sep 17 00:00:00 2001 From: Charlie Fenton Date: Thu, 27 Jan 2011 14:36:49 +0000 Subject: [PATCH] Add new Simple GUI svn path=/trunk/boinc/; revision=22948 --- checkin_notes | 26 + clientgui/AdvancedFrame.cpp | 17 + clientgui/AdvancedFrame.h | 1 + clientgui/BOINCGUIApp.cpp | 14 +- clientgui/BOINCGUIApp.h | 1 + clientgui/Events.h | 14 + clientgui/MacBitmapComboBox.cpp | 294 +++++++ clientgui/MacBitmapComboBox.h | 98 +++ clientgui/SkinManager.cpp | 15 +- clientgui/res/GreenDot16.xpm | 89 +++ clientgui/res/RedDot16.xpm | 86 ++ clientgui/res/YellowDot16.xpm | 48 ++ clientgui/sg_BoincSimpleFrame.cpp | 914 +++++++++++++++++++++ clientgui/sg_BoincSimpleFrame.h | 147 ++++ clientgui/sg_CustomControls.cpp | 11 +- clientgui/sg_CustomControls.h | 2 + clientgui/sg_PanelBase.cpp | 145 ++++ clientgui/sg_PanelBase.h | 89 +++ clientgui/sg_ProjectCommandPopup.cpp | 298 +++++++ clientgui/sg_ProjectCommandPopup.h | 60 ++ clientgui/sg_ProjectPanel.cpp | 463 +++++++++++ clientgui/sg_ProjectPanel.h | 87 ++ clientgui/sg_ProjectWebSitesPopup.cpp | 115 +++ clientgui/sg_ProjectWebSitesPopup.h | 51 ++ clientgui/sg_TaskCommandPopup.cpp | 269 +++++++ clientgui/sg_TaskCommandPopup.h | 57 ++ clientgui/sg_TaskPanel.cpp | 933 ++++++++++++++++++++++ clientgui/sg_TaskPanel.h | 138 ++++ mac_build/boinc.xcodeproj/project.pbxproj | 94 ++- 29 files changed, 4556 insertions(+), 20 deletions(-) create mode 100644 clientgui/MacBitmapComboBox.cpp create mode 100644 clientgui/MacBitmapComboBox.h create mode 100644 clientgui/res/GreenDot16.xpm create mode 100644 clientgui/res/RedDot16.xpm create mode 100644 clientgui/res/YellowDot16.xpm create mode 100755 clientgui/sg_BoincSimpleFrame.cpp create mode 100644 clientgui/sg_BoincSimpleFrame.h create mode 100755 clientgui/sg_PanelBase.cpp create mode 100755 clientgui/sg_PanelBase.h create mode 100644 clientgui/sg_ProjectCommandPopup.cpp create mode 100644 clientgui/sg_ProjectCommandPopup.h create mode 100755 clientgui/sg_ProjectPanel.cpp create mode 100755 clientgui/sg_ProjectPanel.h create mode 100644 clientgui/sg_ProjectWebSitesPopup.cpp create mode 100644 clientgui/sg_ProjectWebSitesPopup.h create mode 100644 clientgui/sg_TaskCommandPopup.cpp create mode 100644 clientgui/sg_TaskCommandPopup.h create mode 100755 clientgui/sg_TaskPanel.cpp create mode 100755 clientgui/sg_TaskPanel.h diff --git a/checkin_notes b/checkin_notes index 75df52f4c8..a305274606 100644 --- a/checkin_notes +++ b/checkin_notes @@ -278,3 +278,29 @@ Charlie 27 Jan 2011 mac_build/ Mac_SA_Insecure.sh + +Charlie 27 Jan 2011 + Add new Simple GUI. + + clientgui/ + AdvancedFrame.cpp, .h + BOINCGUIApp.cpp, .h + Events.h + MacBitmapComboBox.cpp, .h (new) + sg_BoincSimpleFrame.cpp, .h (new) + sg_CustomControls.cpp, .h + sg_TaskPanel.cpp, .h (new) + sg_PanelBase.cpp, .h (new) + sg_ProjectCommandPopup.cpp, .h (new) + sg_ProjectPanel.cpp, .h (new) + sg_ProjectWebSitesPopup.cpp, .h (new) + sg_TaskCommandPopup.cpp, .h (new) + SkinManager.cpp + res/ + RedDot16.xpm (new) + YellowDot16.xpm (new) + GreenDot16.xpm (new) + mac_build/ + boinc.xcodeproj/ + project.pbxproj + \ No newline at end of file diff --git a/clientgui/AdvancedFrame.cpp b/clientgui/AdvancedFrame.cpp index 427d2ca6d7..3486a9310f 100644 --- a/clientgui/AdvancedFrame.cpp +++ b/clientgui/AdvancedFrame.cpp @@ -154,6 +154,7 @@ void CStatusBar::OnSize(wxSizeEvent& event) { wxLogTrace(wxT("Function Start/End"), wxT("CStatusBar::OnSize - Function End")); } +#define ID_NEWSG 6120 /* CAF */ IMPLEMENT_DYNAMIC_CLASS(CAdvancedFrame, CBOINCBaseFrame) @@ -161,6 +162,7 @@ BEGIN_EVENT_TABLE (CAdvancedFrame, CBOINCBaseFrame) // View EVT_MENU_RANGE(ID_ADVNOTICESVIEW, ID_ADVRESOURCEUSAGEVIEW, CAdvancedFrame::OnChangeView) EVT_MENU(ID_CHANGEGUI, CAdvancedFrame::OnChangeGUI) + EVT_MENU(ID_NEWSG, CAdvancedFrame::OnNewSG) /* CAF */ // Tools EVT_MENU(ID_WIZARDATTACH, CAdvancedFrame::OnWizardAttach) EVT_MENU(ID_WIZARDUPDATE, CAdvancedFrame::OnWizardUpdate) @@ -407,6 +409,12 @@ bool CAdvancedFrame::CreateMenu() { if (wxGetApp().IsAccessibilityEnabled()) { menuView->Enable(ID_CHANGEGUI, false); } + + menuView->Append( + ID_NEWSG, + _("New Simple View..."), + _("Display the new simple graphical interface.") + ); // Tools menu @@ -1074,6 +1082,15 @@ void CAdvancedFrame::OnChangeGUI(wxCommandEvent& WXUNUSED(event)) { } +void CAdvancedFrame::OnNewSG(wxCommandEvent& WXUNUSED(event)) { + wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnNewSG - Function Begin")); + + wxGetApp().SetActiveGUI(BOINC_NEWSIMPLEGUI, true); + + wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnNewSG - Function End")); +} + + void CAdvancedFrame::OnWizardAttach( wxCommandEvent& WXUNUSED(event) ) { wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnWizardAttach - Function Begin")); diff --git a/clientgui/AdvancedFrame.h b/clientgui/AdvancedFrame.h index 3f9659daff..1ce5eff010 100644 --- a/clientgui/AdvancedFrame.h +++ b/clientgui/AdvancedFrame.h @@ -60,6 +60,7 @@ public: void OnChangeView( wxCommandEvent& event ); void OnChangeGUI( wxCommandEvent& event ); + void OnNewSG( wxCommandEvent& event ); /* CAF */ void OnWizardAttach( wxCommandEvent& event ); void OnWizardUpdate( wxCommandEvent& event ); diff --git a/clientgui/BOINCGUIApp.cpp b/clientgui/BOINCGUIApp.cpp index 18ab27528d..3e5bc248c8 100644 --- a/clientgui/BOINCGUIApp.cpp +++ b/clientgui/BOINCGUIApp.cpp @@ -40,7 +40,6 @@ #include "Events.h" #include "common/wxFlatNotebook.h" #include "BOINCInternetFSHandler.h" -//#include "BOINCMemoryFSHandler.h" #include "LogBOINC.h" #include "BOINCGUIApp.h" #include "SkinManager.h" @@ -49,12 +48,11 @@ #include "BOINCTaskBar.h" #include "BOINCBaseFrame.h" #include "AdvancedFrame.h" -#include "sg_ImageLoader.h" -#include "sg_StatImageLoader.h" #include "sg_BoincSimpleGUI.h" #include "DlgExitMessage.h" #include "DlgEventLog.h" #include "procinfo.h" +#include "sg_BoincSimpleFrame.h" DEFINE_EVENT_TYPE(wxEVT_RPC_FINISHED) @@ -999,6 +997,16 @@ bool CBOINCGUIApp::SetActiveGUI(int iGUISelection, bool bShowWindow) { wxPoint(iLeft, iTop), wxSize(iWidth, iHeight) ); + } else if (BOINC_NEWSIMPLEGUI == iGUISelection){ + // Initialize the simple gui window + pNewFrame = new CNewSimpleFrame( + m_pSkinManager->GetAdvanced()->GetApplicationName(), + m_pSkinManager->GetAdvanced()->GetApplicationIcon(), + m_pSkinManager->GetAdvanced()->GetApplicationIcon32(), + wxPoint(iLeft, iTop), + wxSize(iWidth, iHeight) + ); + } else { // Initialize the simple gui window pNewFrame = new CSimpleFrame( diff --git a/clientgui/BOINCGUIApp.h b/clientgui/BOINCGUIApp.h index e1a25b2899..bf9560c7ee 100644 --- a/clientgui/BOINCGUIApp.h +++ b/clientgui/BOINCGUIApp.h @@ -37,6 +37,7 @@ /// #define BOINC_ADVANCEDGUI 1 #define BOINC_SIMPLEGUI 2 +#define BOINC_NEWSIMPLEGUI 3 class wxLogBOINC; diff --git a/clientgui/Events.h b/clientgui/Events.h index 6a50c8c0f5..7615983953 100644 --- a/clientgui/Events.h +++ b/clientgui/Events.h @@ -156,6 +156,20 @@ #define ID_SIMPLE_RESUME 6605 #define ID_SIMPLE_PREFERENCES 6606 #define ID_SIMPLE_MESSAGESVIEW 6607 +#define ID_SIMPLE_PROGRESSPULSETIMER 6608 + +// +// New Simple GUI +// +#define ID_SGTASKSELECTOR 12001 +#define ID_TASKSCOMMANDBUTTON 12002 +#define ID_ADDROJECTBUTTON 12101 +#define ID_SGPROJECTSELECTOR 12102 +#define ID_PROJECTWEBSITESBUTTON 12103 +#define ID_PROJECTCOMMANDBUTTON 12104 +#define ID_SGNOTICESBUTTON 12201 +#define ID_SGPAUSERESUMEBUTTON 12202 +#define ID_SGOPTIONS 12301 // // Taskbar/System Tray diff --git a/clientgui/MacBitmapComboBox.cpp b/clientgui/MacBitmapComboBox.cpp new file mode 100644 index 0000000000..d95e49bbca --- /dev/null +++ b/clientgui/MacBitmapComboBox.cpp @@ -0,0 +1,294 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#include "stdwx.h" +#include +#include "MacBitmapComboBox.h" + +#define POPUPBUTTONCONTROLHEIGHT 20 + +// wxChoice uses CreatePopupButtonControl + +const wxChar CBOINCBitmapChoiceNameStr[] = wxT("popup"); +const wxChar CBOINCBitmapComboBoxNameStr[] = wxT("combo"); + +IMPLEMENT_DYNAMIC_CLASS(CBOINCBitmapChoice, wxChoice) + +CBOINCBitmapChoice::CBOINCBitmapChoice() {} + +CBOINCBitmapChoice::CBOINCBitmapChoice(wxWindow *parent, wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + int n, const wxString choices[], + long style, + const wxValidator& validator, + const wxString& name) +{ + Create(parent, id, pos, size, n, choices, style, validator, name); + + if (! value.IsEmpty()) { + SetStringSelection(value); + } +} + +CBOINCBitmapChoice::~CBOINCBitmapChoice() { +} + +void CBOINCBitmapChoice::SetItemBitmap(unsigned int n, const wxBitmap& bitmap) { + MenuHandle mhandle = (MenuHandle) m_macPopUpMenuHandle; + unsigned int index = n + 1; + + if ( mhandle == NULL || index == 0) + return ; + + if ( bitmap.Ok() ) + { + CGImageRef imageRef = (CGImageRef)( bitmap.CGImageCreate() ) ; + SetMenuItemIconHandle( mhandle , index , + kMenuCGImageRefType , (Handle) imageRef ) ; + +#if 0// wxUSE_BMPBUTTON + ControlButtonContentInfo info ; + wxMacCreateBitmapButton( &info , bitmap ) ; + if ( info.contentType != kControlNoContent ) + { + if ( info.contentType == kControlContentIconRef ) + SetMenuItemIconHandle( mhandle , index , + kMenuIconRefType , (Handle) info.u.iconRef ) ; + else if ( info.contentType == kControlContentCGImageRef ) + SetMenuItemIconHandle( mhandle , index , + kMenuCGImageRefType , (Handle) info.u.imageRef ) ; + } + wxMacReleaseBitmapButton( &info ) ; +#endif + } +} + + + +IMPLEMENT_DYNAMIC_CLASS(CBOINCBitmapComboBox, wxPanel) + +BEGIN_EVENT_TABLE(CBOINCBitmapComboBox, wxPanel) +// EVT_ERASE_BACKGROUND(CBOINCBitmapComboBox::OnEraseBackground) + EVT_PAINT(CBOINCBitmapComboBox::OnPaint) +// EVT_CHOICE(CBOINCBitmapComboBox::OnSelection) +END_EVENT_TABLE() + +CBOINCBitmapComboBox::CBOINCBitmapComboBox() {} + +CBOINCBitmapComboBox::CBOINCBitmapComboBox(wxWindow *parent, wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + int n, const wxString choices[], + long style, + const wxValidator& validator, + const wxString& name) : + wxPanel( parent, id, pos, size, wxCLIP_CHILDREN | wxBORDER_NONE ) +{ + int i; + + m_ChoiceControl = new CBOINCBitmapChoice(this, id, value, wxDefaultPosition, wxSize(size.x, POPUPBUTTONCONTROLHEIGHT), n, choices, style, validator); + m_bHaveLargeBitmaps = (size.y > 0); + wxBoxSizer* bSizer1; + bSizer1 = new wxBoxSizer( wxVERTICAL ); + int margin = m_bHaveLargeBitmaps ? (size.y - POPUPBUTTONCONTROLHEIGHT)/2 : 0; + bSizer1->Add( m_ChoiceControl, 1, wxTOP | wxBOTTOM | wxEXPAND, margin); + this->SetSizer( bSizer1 ); + Layout(); + if (m_bHaveLargeBitmaps) { + for (i=0; iSetItemBitmap(n, bitmap); + if (n == (unsigned int)m_ChoiceControl->GetSelection()) { + Refresh(); + } +} + + +void CBOINCBitmapComboBox::SetStringSelection(const wxString& text) { + m_ChoiceControl->SetStringSelection(text); + Refresh(); +} + + +void CBOINCBitmapComboBox::SetSelection(int sel) { + m_ChoiceControl->SetSelection(sel); + Refresh(); +} + + +int CBOINCBitmapComboBox::Append(const wxString& text) { + if (m_bHaveLargeBitmaps) { + m_BitmapCache.push_back(wxNullBitmap); + } + + return m_ChoiceControl->Append(text); +} + + +int CBOINCBitmapComboBox::Append(const wxString& text, void *clientData) { + if (m_bHaveLargeBitmaps) { + m_BitmapCache.push_back(wxNullBitmap); + } + + return m_ChoiceControl->Append(text, clientData); +} + + +int CBOINCBitmapComboBox::Append(const wxString& text, const wxBitmap& bitmap, void *clientData) { + if (m_bHaveLargeBitmaps) { + m_BitmapCache.push_back(bitmap); + } + + int n = m_ChoiceControl->Append(text, clientData); + SetItemBitmap(n, bitmap); + return n; +} + + +void CBOINCBitmapComboBox::Insert(const wxString& item, unsigned int pos) { + if (m_bHaveLargeBitmaps) { + std::vector::iterator insertionPoint = m_BitmapCache.begin(); + m_BitmapCache.insert(insertionPoint + pos, wxNullBitmap); + } + m_ChoiceControl->Insert(item, pos); +} + + +void CBOINCBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap, unsigned int pos) { + if (m_bHaveLargeBitmaps) { + std::vector::iterator insertionPoint = m_BitmapCache.begin(); + wxBitmap* bm = new wxBitmap(bitmap); + m_BitmapCache.insert(insertionPoint + pos, *bm); + delete bm; + } + + m_ChoiceControl->Insert(item, pos); +} + + +void CBOINCBitmapComboBox::Delete(unsigned int n) { + if (n < m_ChoiceControl->GetCount()) { + if (m_bHaveLargeBitmaps) { + std::vector::iterator deletionPoint = m_BitmapCache.begin(); + m_BitmapCache.erase(deletionPoint + n); + } + + m_ChoiceControl->Delete(n); + Refresh(); + } +} + + +void CBOINCBitmapComboBox::Clear() { + m_BitmapCache.clear(); + m_ChoiceControl->Clear(); +} + + +void CBOINCBitmapComboBox::OnSelection(wxCommandEvent& event) { + Refresh(); // To draw the bitmap + event.Skip(); +} + + +void CBOINCBitmapComboBox::OnPaint(wxPaintEvent& event) { + int x, y; + wxPaintDC myDC(this); + unsigned int i = GetSelection(); + if (m_BitmapCache.size() <= i) { + return; + } + + wxPen oldPen = myDC.GetPen(); + wxBrush oldBrush = myDC.GetBrush(); + int oldMode = myDC.GetBackgroundMode(); + + myDC.SetPen(*wxMEDIUM_GREY_PEN); + myDC.SetBrush(*wxTRANSPARENT_BRUSH); + myDC.SetBackgroundMode(wxSOLID); + + GetSize(&x, &y); + if ((m_BitmapCache.at(i)).Ok()) { + myDC.DrawBitmap(m_BitmapCache.at(i), 9, 1, false); + myDC.DrawRectangle(8, 0, y, y); + } + + // Restore Mode, Pen and Brush + myDC.SetBackgroundMode(oldMode); + myDC.SetPen(oldPen); + myDC.SetBrush(oldBrush); +} + + +void CBOINCBitmapComboBox::EmptyBitmapCache() { +#if 0 + unsigned int i, cacheSize; + + cacheSize = m_BitmapCache.size(); + for (i=0; iSetToolTip(s); +} + + +void CBOINCBitmapComboBox::SetToolTip(wxToolTip* tip) { + m_ChoiceControl->SetToolTip(tip); +} diff --git a/clientgui/MacBitmapComboBox.h b/clientgui/MacBitmapComboBox.h new file mode 100644 index 0000000000..80fcaf83f6 --- /dev/null +++ b/clientgui/MacBitmapComboBox.h @@ -0,0 +1,98 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#ifndef __MACBITMAPCOMBOBOX__ +#define __MACBITMAPCOMBOBOX__ + +#include + +WXDLLEXPORT_DATA(extern const wxChar) CBOINCBitmapChoiceNameStr[]; +WXDLLEXPORT_DATA(extern const wxChar) CBOINCBitmapComboBoxNameStr[]; + +#define EVT_BOINCBITMAPCOMBOBOX EVT_CHOICE + +class CBOINCBitmapChoice : public wxChoice +{ + DECLARE_DYNAMIC_CLASS(CBOINCBitmapChoice ) + +public: + CBOINCBitmapChoice() ; + + virtual ~CBOINCBitmapChoice(); + + CBOINCBitmapChoice(wxWindow *parent, wxWindowID id, + const wxString& value = "", + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + int n = 0, const wxString choices[] = NULL, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = CBOINCBitmapChoiceNameStr); + + void SetItemBitmap(unsigned int n, const wxBitmap& bitmap); +}; + +class CBOINCBitmapComboBox : public wxPanel +{ + DECLARE_DYNAMIC_CLASS( CBOINCBitmapComboBox ) + DECLARE_EVENT_TABLE() + +public: + CBOINCBitmapComboBox() ; + + virtual ~CBOINCBitmapComboBox(); + + CBOINCBitmapComboBox(wxWindow *parent, wxWindowID id, + const wxString& value = "", + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + int n = 0, const wxString choices[] = NULL, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = CBOINCBitmapComboBoxNameStr); + + void SetItemBitmap(unsigned int n, const wxBitmap& bitmap); + void SetStringSelection(const wxString& text); + void SetSelection(int sel); + int GetCount() { return m_ChoiceControl->GetCount(); } + void * GetClientData(unsigned int n) const { return m_ChoiceControl->GetClientData(n); } + void SetClientData(unsigned int n, void *data) { m_ChoiceControl->SetClientData(n, data); } + int GetSelection() { return m_ChoiceControl->GetCurrentSelection(); } + wxString GetValue() { return m_ChoiceControl->GetStringSelection(); } + wxString GetStringSelection() { return m_ChoiceControl->GetStringSelection(); } + + int Append(const wxString& text); + int Append(const wxString& text, void *clientData); + int Append(const wxString& text, const wxBitmap& bitmap, void *clientData); + void Insert(const wxString& item, unsigned int pos); + void Insert(const wxString& item, const wxBitmap& bitmap, unsigned int pos); + void Delete(unsigned int n); + void Clear(); + void SetToolTip(wxString& s); + void SetToolTip(wxToolTip* tip); + +private: + void OnPaint(wxPaintEvent& event); + void OnSelection(wxCommandEvent& event); + void EmptyBitmapCache(); + + CBOINCBitmapChoice *m_ChoiceControl; + bool m_bHaveLargeBitmaps; + std::vector m_BitmapCache; +}; + +#endif //__MACBITMAPCOMBOBOX__ diff --git a/clientgui/SkinManager.cpp b/clientgui/SkinManager.cpp index e2b7a16a7a..659a768136 100644 --- a/clientgui/SkinManager.cpp +++ b/clientgui/SkinManager.cpp @@ -718,6 +718,7 @@ int CSkinSimple::Parse(MIOFILE& in) { bool CSkinSimple::InitializeDelayedValidation() { m_BackgroundImage.SetDefaults( +// wxT("background"), (const char**)background_image_xpm, wxT("133:181:178") wxT("background"), (const char**)background_image_xpm, wxT("0:0:0") ); m_SpacerImage.SetDefaults(wxT("spacer"), (const char**)spacer_image_xpm); @@ -725,7 +726,7 @@ bool CSkinSimple::InitializeDelayedValidation() { if (show_error_msgs) { fprintf(stderr, "Skin Manager: Failed to parse static line color. Using default.\n"); } - m_StaticLineColor = ParseColor(wxString(wxT("5:5:5"))); + m_StaticLineColor = ParseColor(wxString(wxT("204:102:51"))); wxASSERT(m_StaticLineColor.Ok()); } m_StateIndicatorBackgroundImage.SetDefaults( @@ -738,19 +739,19 @@ bool CSkinSimple::InitializeDelayedValidation() { wxT("error indicator"), (const char**)error_indicator_image_xpm ); m_WorkunitActiveTab.SetDefaults( - wxT("active"), (const char**)workunit_active_image_xpm, wxT("102:102:102"), wxT("102:102:102"), wxT("179:179:179") + wxT("active"), (const char**)workunit_active_image_xpm, wxString(wxT("20:82:82")), wxString(wxT("134:179:176")), wxString(wxT("51:102:102")) ); m_WorkunitSuspendedTab.SetDefaults( - wxT("suspended"), (const char**)workunit_suspended_image_xpm, wxT("80:80:80"), wxT("50:50:50"), wxT("50:50:50") + wxT("suspended"), (const char**)workunit_suspended_image_xpm, wxString(wxT("102:153:153")), wxString(wxT("134:179:176")), wxString(wxT("84:175:175")) ); m_WorkunitTabAreaBackgroundImage.SetDefaults( wxT("workunit tab area background"), (const char**)workunit_tab_area_background_image_xpm ); m_WorkunitAreaBackgroundImage.SetDefaults( - wxT("workunit area background"), (const char**)workunit_area_background_image_xpm, wxT("0:0:0") + wxT("workunit area background"), (const char**)workunit_area_background_image_xpm ); m_WorkunitAnimationBackgroundImage.SetDefaults( - wxT("workunit animation background"), (const char**)workunit_animation_background_image_xpm, wxT("0:0:0") + wxT("workunit animation background"), (const char**)workunit_animation_background_image_xpm ); m_WorkunitAnimationImage.SetDefaults( wxT("workunit animation"), (const char**)workunit_animation_image_xpm @@ -1264,8 +1265,8 @@ bool CSkinManager::ReloadSkin(wxLocale* pLocale, wxString strSkin) { m_strSelectedSkin = strSkin; // Check to see if the skin we want to change to is the default skin - if (GetDefaultSkinName() == m_strSelectedSkin || GetDefaultBOINCSkinName() == m_strSelectedSkin) { - m_strSelectedSkin = GetDefaultSkinName(); + if (GetDefaultSkinName() == m_strSelectedSkin) { + m_strSelectedSkin = GetDefaultBOINCSkinName(); } // First we try the users canonical locale resources. diff --git a/clientgui/res/GreenDot16.xpm b/clientgui/res/GreenDot16.xpm new file mode 100644 index 0000000000..24d9eebc12 --- /dev/null +++ b/clientgui/res/GreenDot16.xpm @@ -0,0 +1,89 @@ +/* XPM */ +static char *GreenDot16_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 67 2", +/* colors */ +"AA c #FFFFFFFFFFFF", +"BA c #F0F0E0E0F8F8", +"CA c #E8E8F8F8F0F0", +"DA c #E8E8E0E0F8F8", +"EA c #E0E0F8F8E8E8", +"FA c #E0E0F8F8D8D8", +"GA c #E0E0E8E8E8E8", +"HA c #D8D8F8F8E8E8", +"IA c #D8D8F8F8D8D8", +"JA c #D8D8F8F8C8C8", +"KA c #C0C0F8F8C0C0", +"LA c #C0C0F8F8B8B8", +"MA c #B8B8F8F8B0B0", +"NA c #B8B8F0F0C0C0", +"OA c #B8B8E8E8B8B8", +"PA c #B0B0F0F0A0A0", +"AB c #B0B0E8E8A8A8", +"BB c #A8A8E8E8A0A0", +"CB c #A0A0E0E09898", +"DB c #9898F8F89898", +"EB c #9898E0E0A0A0", +"FB c #9898D0D0A0A0", +"GB c #8888D0D09090", +"HB c #8888C8C88080", +"IB c #8080F8F88888", +"JB c #8080D0D07070", +"KB c #7878F8F87878", +"LB c #7878C8C87070", +"MB c #7878B8B87070", +"NB c #7070C0C06868", +"OB c #6868B8B86060", +"PB c #6868A8A85858", +"AC c #6060E8E86868", +"BC c #6060B0B05858", +"CC c #5858B0B05050", +"DC c #5858B0B04848", +"EC c #5858A8A85050", +"FC c #4848D0D04848", +"GC c #4848B0B04848", +"HC c #4848A0A04040", +"IC c #4040E0E04848", +"JC c #4040A0A03838", +"KC c #3838A0A03838", +"LC c #383898983838", +"MC c #3030D8D84040", +"NC c #3030D0D03030", +"OC c #303098982828", +"PC c #2828B0B03030", +"AD c #2828B0B02020", +"BD c #282898982828", +"CD c #282890901818", +"DD c #282888882828", +"ED c #2020C0C01818", +"FD c #2020A0A02828", +"GD c #202088881818", +"HD c #1818A0A01818", +"ID c #181890901010", +"JD c #181888881818", +"KD c #101088880808", +"LD c #0808B0B00808", +"MD c #0808A8A81818", +"ND c #0808A8A80808", +"OD c #080898981818", +"PD c #080898980808", +"AE c #080888881010", +"BE c #080888880808", +"CE c #000078780000", +/* pixels */ +"AABAGAAAIAABCBBCPBCBLAFAAACADAAA", +"GAAAEANAHBDCJCGDOCOCDCMBMAEACAAA", +"KAFACBCCBDKDHDNDNDPDBELCOBBBKAIA", +"JAPACCGDPDNDLDLDLDNDHDHDBDDCCBJA", +"MANBJCFDCDMDNDNDLDNDNDHDJDLCJBMA", +"CBKCBDFDHDMDNDNDNDNDMDODIDIDCCIB", +"IBFDPDODNDMDNDNDNDNDNDMDODODPCAC", +"MCPDPDNDNDNDNDNDNDNDNDNDNDNDHDIC", +"NCPDLDNDNDLDNDNDPDNDNDNDNDNDEDNC", +"KBHDPDPDPDNDNDNDNDNDNDNDPDMDADFC", +"DBHCAEFDMDHDNDNDLDPDODMDJDJDGCIB", +"MANBLCKCBEMDNDNDNDMDLDIDJDBDLBKA", +"IAPABCKCBEPDNDLDLDNDNDAEBDOBABIA", +"FAIACBBCBDIDPDPDPDPDBEDDBCOAFAFA", +"AAAAIAOAHBECHCCELCKCECLBOAEAAAAA", +"DAAACAHACAFBEBLBLBGBNACACACADAAA"}; diff --git a/clientgui/res/RedDot16.xpm b/clientgui/res/RedDot16.xpm new file mode 100644 index 0000000000..5c33dc1796 --- /dev/null +++ b/clientgui/res/RedDot16.xpm @@ -0,0 +1,86 @@ +/* XPM */ +static char *RedDot16_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 64 2", +/* colors */ +"AA c #FFFFFFFFFFFF", +"BA c #F8F8F8F8E8E8", +"CA c #F8F8E8E8F0F0", +"DA c #F8F8E8E8E8E8", +"EA c #F8F8E8E8D0D0", +"FA c #F8F8D0D0C0C0", +"GA c #F8F8C8C8B8B8", +"HA c #F8F8C8C8A8A8", +"IA c #F8F8B8B8A8A8", +"JA c #F8F8A8A89898", +"KA c #F8F8A0A0A8A8", +"LA c #F8F89898A0A0", +"MA c #F8F888889898", +"NA c #F8F878787070", +"OA c #F8F870706060", +"PA c #F8F840404848", +"AB c #F8F838384040", +"BB c #F8F820202020", +"CB c #F8F818181818", +"DB c #F8F818180808", +"EB c #F8F810102828", +"FB c #F8F808081818", +"GB c #F8F808080808", +"HB c #F0F098989898", +"IB c #F0F070708080", +"JB c #F0F060605050", +"KB c #E8E8F8F8F8F8", +"LB c #E8E898989898", +"MB c #E8E880808888", +"NB c #E8E870707878", +"OB c #E8E818181010", +"PB c #E8E810102020", +"AC c #E8E810100000", +"BC c #E8E808081010", +"CC c #E8E808080808", +"DC c #E0E058584848", +"EC c #D8D8E8E8E8E8", +"FC c #D8D828283838", +"GC c #D8D810101818", +"HC c #D8D810100808", +"IC c #D8D808082020", +"JC c #D8D800000808", +"KC c #D0D030304040", +"LC c #D0D020202020", +"MC c #C8C8D0D0D0D0", +"NC c #C8C828284040", +"OC c #C8C828283030", +"PC c #C8C820202020", +"AD c #C8C810101010", +"BD c #C8C808081818", +"CD c #C8C808080000", +"DD c #C0C0E0E0E0E0", +"ED c #C0C0D8D8E0E0", +"FD c #C0C048484848", +"GD c #C0C038383838", +"HD c #C0C010100808", +"ID c #B8B820202020", +"JD c #B8B818181818", +"KD c #B8B810100808", +"LD c #B0B048483030", +"MD c #B0B008080808", +"ND c #A8A840403030", +"OD c #A8A818180808", +"PD c #A0A038383030", +/* pixels */ +"KBDDAABAIAGADCKDKDJBGAGABAAADDKB", +"EDAAAAKAGDADHDOBACCDMDGDLACAAAEC", +"AADANBFCPBFBGBCCGBFBFBPBFCIBAABA", +"EAHBOCBCGBFBGBGBCBDBGBFBBDFCHBEA", +"HAPDLCBCCCGBGBDBDBCCGBCCCCPCNDGA", +"IAODGCOBFBBBACACJCCCEBGBOBGCKDIA", +"PAJCBBCCCCCCCCCCDBCCGBCCFBOBHCAB", +"GBFBGBCCCBGBGBGBGBGBGBGBGBGBEBGB", +"GBEBGBGBFBCCGBGBGBGBGBCBCCGBFBGB", +"ABCCJCGBGBGBGBGBGBCCCCGBGBGBCCBC", +"JAJDOBCBGBGBGBCCGBGBGBGBFBJCADNA", +"HALDADCCCCGBGBCCCCGBGBGBEBADFDKA", +"EAJAIDCDFBGBGBGBGBGBFBFBCDFCKAEA", +"AABAMBKCBCJCACGBCCJCFBICNCMAAAAA", +"ECAADALBFDJDGCHDACHDMDGDHBAACAMC", +"KBEDAAAAFAIAOAGCMDOAHAFADADABAKB"}; diff --git a/clientgui/res/YellowDot16.xpm b/clientgui/res/YellowDot16.xpm new file mode 100644 index 0000000000..b887a3cf6b --- /dev/null +++ b/clientgui/res/YellowDot16.xpm @@ -0,0 +1,48 @@ +/* XPM */ +static char *YellowDot16_xpm[] = { +/* width height ncolors chars_per_pixel */ +"16 16 26 1", +/* colors */ +"A c #FFFFFFFFFFFF", +"B c #F8F8F8F8E8E8", +"C c #F8F8F8F8D8D8", +"D c #F8F8F8F8C0C0", +"E c #F8F8F8F89898", +"F c #F8F8F8F88888", +"G c #F8F8F0F0B0B0", +"H c #F8F8F0F06868", +"I c #F8F8F0F05858", +"J c #F8F8E8E8A0A0", +"K c #F8F8E8E88888", +"L c #F8F8E8E85858", +"M c #F8F8E8E84040", +"N c #F8F8E0E00808", +"O c #F8F8D8D81818", +"P c #F8F8D8D80808", +"Q c #F8F8C8C81818", +"R c #F0F0E8E82020", +"S c #F0F0E0E01010", +"T c #F0F0D0D02828", +"U c #E8E8E0E05050", +"V c #E8E8E0E01818", +"W c #E8E8D8D83838", +"X c #E8E8D8D80808", +"Y c #E8E8D0D02020", +"Z c #E8E8D0D01818", +/* pixels */ +"AAAAACJKKJCAAAAA", +"AAAGHRSSSSRHJAAA", +"ACEMOPNNNNPPLECA", +"BGMQPTSPNOOOPMGB", +"DFZPPPPPNNPPPOKD", +"EUZPPPNNNPPPPYME", +"HTSNPPNPNNPPNZWH", +"ITNNPPNPPNPPNNTI", +"HTNNNPNPXPNPNNTI", +"HMZNPPNPPNPNNZMH", +"FUZNPPPNNNPPNZUE", +"GFZPPPNNPNPPPZFG", +"AEMPOOOPPSOQPMGA", +"ABELPPPNNPPOMEBA", +"AAAEHRVNNVRIGAAA", +"AAAAACEKEECAAAAA"}; diff --git a/clientgui/sg_BoincSimpleFrame.cpp b/clientgui/sg_BoincSimpleFrame.cpp new file mode 100755 index 0000000000..f84eab9b72 --- /dev/null +++ b/clientgui/sg_BoincSimpleFrame.cpp @@ -0,0 +1,914 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + + +#if defined(__GNUG__) && !defined(__APPLE__) +#pragma implementation "sg_BoincSimpleFrame.h" +#endif + +#include "stdwx.h" +#ifdef __WXMAC__ +#include "MacAccessiblity.h" +#endif +#include "diagnostics.h" +#include "str_util.h" +#include "mfile.h" +#include "miofile.h" +#include "parse.h" +#include "error_numbers.h" +#include "BOINCGUIApp.h" +#include "SkinManager.h" +#include "MainDocument.h" +#include "Events.h" +#include "BOINCBaseFrame.h" +#include "wizardex.h" +#include "BOINCBaseWizard.h" +#include "WizardAttach.h" +#include "error_numbers.h" +#include "version.h" + +#include "sg_BoincSimpleFrame.h" +#include "sg_TaskPanel.h" +#include "sg_ProjectPanel.h" +#include "sg_DlgMessages.h" +#include "sg_DlgPreferences.h" +#include "DlgEventLog.h" +#include "DlgAbout.h" + +#define ID_OLDSG 6121 /* CAF TEMPORARY */ + + +IMPLEMENT_DYNAMIC_CLASS(CNewSimpleFrame, CBOINCBaseFrame) + +BEGIN_EVENT_TABLE(CNewSimpleFrame, CBOINCBaseFrame) + EVT_SIZE(CNewSimpleFrame::OnSize) + EVT_MENU(ID_CHANGEGUI, CNewSimpleFrame::OnChangeGUI) + EVT_MENU(ID_OLDSG, CNewSimpleFrame::OnOldSG) /* CAF TEMPORARY */ + EVT_HELP(wxID_ANY, CNewSimpleFrame::OnHelp) + EVT_FRAME_CONNECT(CNewSimpleFrame::OnConnect) + EVT_FRAME_RELOADSKIN(CNewSimpleFrame::OnReloadSkin) + EVT_FRAME_NOTIFICATION(CNewSimpleFrame::OnNotification) + EVT_MENU(ID_PREFERENCES, CNewSimpleFrame::OnPreferences) + EVT_MENU(ID_SGOPTIONS, CNewSimpleFrame::OnOptions) + EVT_MENU(ID_HELPBOINC, CNewSimpleFrame::OnHelpBOINC) + EVT_MENU(ID_HELPBOINCMANAGER, CNewSimpleFrame::OnHelpBOINC) + EVT_MENU(ID_HELPBOINCWEBSITE, CNewSimpleFrame::OnHelpBOINC) + EVT_MENU(wxID_ABOUT, CNewSimpleFrame::OnHelpAbout) +END_EVENT_TABLE() + + +CNewSimpleFrame::CNewSimpleFrame() { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::CNewSimpleFrame - Default Constructor Function Begin")); + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::CNewSimpleFrame - Default Constructor Function End")); +} + + +CNewSimpleFrame::CNewSimpleFrame(wxString title, wxIcon* icon, wxIcon* icon32, wxPoint position, wxSize size) : + CBOINCBaseFrame((wxFrame *)NULL, ID_SIMPLEFRAME, title, position, size, + wxMINIMIZE_BOX | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN) +{ + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::CNewSimpleFrame - Overloaded Constructor Function Begin")); + + // Initialize Application + wxIconBundle icons; + icons.AddIcon(*icon); + icons.AddIcon(*icon32); + SetIcons(icons); + + CSkinAdvanced* pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced(); + wxString strMenuName; + wxString strMenuDescription; + + wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced)); + + // File menu + wxMenu *menuFile = new wxMenu; + + // %s is the application name + // i.e. 'BOINC Manager', 'GridRepublic Manager' + strMenuDescription.Printf( + _("Close the %s window"), + pSkinAdvanced->GetApplicationName().c_str() + ); + strMenuName = _("&Close Window"); + strMenuName += wxT("\tCtrl+W"); + menuFile->Append( + ID_CLOSEWINDOW, + strMenuName, + strMenuDescription + ); + + // View menu + wxMenu *menuTools = new wxMenu; + + menuTools->Append( + ID_CHANGEGUI, + _("Advanced View...\tCtrl+Shift+A"), + _("Display the advanced (accessible) graphical interface.") + ); + + menuTools->Append( /* CAF TEMPORARY */ + ID_OLDSG, + _("Old Simple View..."), + _("Display the old simple graphical interface.") + ); + + menuTools->Append( + ID_PREFERENCES, + _("Computing &preferences..."), + _("Configure computing preferences") + ); + + menuTools->Append( + ID_SGOPTIONS, + _("Manager Settings..."), + _("Configure display options and proxy settings") + ); + + // Help menu + wxMenu *menuHelp = new wxMenu; + + // %s is the project name + // i.e. 'BOINC Manager', 'GridRepublic' + strMenuName.Printf( + _("%s &help"), + pSkinAdvanced->GetApplicationShortName().c_str() + ); + // %s is the project name + // i.e. 'BOINC', 'GridRepublic' + strMenuDescription.Printf( + _("Show information about %s"), + pSkinAdvanced->GetApplicationShortName().c_str() + ); + menuHelp->Append( + ID_HELPBOINC, + strMenuName, + strMenuDescription + ); + + // %s is the application name + // i.e. 'BOINC Manager', 'GridRepublic Manager' + strMenuName.Printf( + _("&%s"), + pSkinAdvanced->GetApplicationName().c_str() + ); + // %s is the application name + // i.e. 'BOINC Manager', 'GridRepublic Manager' + strMenuDescription.Printf( + _("Show information about the %s"), + pSkinAdvanced->GetApplicationName().c_str() + ); + menuHelp->Append( + ID_HELPBOINCMANAGER, + strMenuName, + strMenuDescription + ); + + // %s is the project name + // i.e. 'BOINC', 'GridRepublic' + strMenuName.Printf( + _("%s &website"), + pSkinAdvanced->GetApplicationShortName().c_str() + ); + // %s is the application name + // i.e. 'BOINC Manager', 'GridRepublic Manager' + strMenuDescription.Printf( + _("Show information about BOINC and %s"), + pSkinAdvanced->GetApplicationName().c_str() + ); + menuHelp->Append( + ID_HELPBOINCWEBSITE, + strMenuName, + strMenuDescription + ); + + // %s is the project name + // i.e. 'BOINC Manager', 'GridRepublic Manager' + strMenuName.Printf( + _("&About %s..."), + pSkinAdvanced->GetApplicationName().c_str() + ); + menuHelp->Append( + wxID_ABOUT, + strMenuName, + _("Licensing and copyright information.") + ); + + // construct menu + m_pMenubar = new wxMenuBar; + m_pMenubar->Append( + menuFile, + _("&File") + ); + m_pMenubar->Append( + menuTools, + _("&Tools") + ); + m_pMenubar->Append( + menuHelp, + _("&Help") + ); + + wxMenuBar* m_pOldMenubar = GetMenuBar(); + SetMenuBar(m_pMenubar); + if (m_pOldMenubar) { + delete m_pOldMenubar; + } + +#ifdef __WXMAC__ + m_pMenubar->MacInstallMenuBar(); + + // Enable Mac OS X's standard Preferences menu item (handled in MacSysMenu.cpp) + EnableMenuCommand(NULL, kHICommandPreferences); +#endif + + m_Shortcuts[0].Set(wxACCEL_NORMAL, WXK_HELP, ID_HELPBOINCMANAGER); + m_pAccelTable = new wxAcceleratorTable(2, m_Shortcuts); + + SetAcceleratorTable(*m_pAccelTable); + + dlgMsgsPtr = NULL; + m_pBackgroundPanel = new CSimpleGUIPanel(this); + + RestoreState(); +} + + +CNewSimpleFrame::~CNewSimpleFrame() { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::CNewSimpleFrame - Destructor Function Begin")); + + SaveState(); + + if (m_pAccelTable) + delete m_pAccelTable; + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::CNewSimpleFrame - Destructor Function End")); +} + + +bool CNewSimpleFrame::SaveState() { + CBOINCBaseFrame::SaveState(); + wxConfigBase* pConfig = wxConfigBase::Get(FALSE); + wxString strBaseConfigLocation = wxString(wxT("/Simple")); + + wxASSERT(pConfig); + + // An odd case happens every once and awhile where wxWidgets looses + // the pointer to the config object, or it is cleaned up before + // the window has finished it's cleanup duty. If we detect a NULL + // pointer, return false. + if (!pConfig) return false; + + // + // Save Frame State + // + pConfig->SetPath(strBaseConfigLocation); + + pConfig->Write(wxT("XPos"), GetPosition().x); + pConfig->Write(wxT("YPos"), GetPosition().y); + + return true; +} + + +bool CNewSimpleFrame::RestoreState() { + CBOINCBaseFrame::RestoreState(); + return true; +} + + +int CNewSimpleFrame::_GetCurrentViewPage() { + if (isMessagesDlgOpen()) { + return VW_SGUI | VW_SMSG; + } else { + return VW_SGUI; + } + return 0; // Should never happen. +} + + +void CNewSimpleFrame::OnChangeGUI(wxCommandEvent& WXUNUSED(event)) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnChangeGUI - Function Begin")); + + wxGetApp().SetActiveGUI(BOINC_ADVANCEDGUI, true); + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnChangeGUI - Function End")); +} + + +/* CAF TEMPORARY */ +void CNewSimpleFrame::OnOldSG(wxCommandEvent& WXUNUSED(event)) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnNewSG - Function Begin")); + + wxGetApp().SetActiveGUI(BOINC_SIMPLEGUI, true); + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnNewSG - Function End")); +} + + +void CNewSimpleFrame::OnPreferences(wxCommandEvent& WXUNUSED(event)) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnPreferences - Function Begin")); + + m_pBackgroundPanel->SetDlgOpen(true); + + CDlgPreferences dlg(GetParent()); + dlg.ShowModal(); + + m_pBackgroundPanel->SetDlgOpen(false); + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnPreferences - Function End")); +} + + +void CNewSimpleFrame::OnOptions(wxCommandEvent& WXUNUSED(event)) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnOptions - Function Begin")); + + m_pBackgroundPanel->SetDlgOpen(true); + +// TODO: Get code from CAdvancedFrame::OnOptions() or create simple language selection dialog + + m_pBackgroundPanel->SetDlgOpen(false); + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnOptions - Function End")); +} + + +// TODO: Create ID_HELPBOINCMANAGER web page for each organization for new BOINC version +void CNewSimpleFrame::OnHelpBOINC(wxCommandEvent& event) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnHelpBOINC - Function Begin")); + + if (IsShown()) { + wxString strURL = wxGetApp().GetSkinManager()->GetAdvanced()->GetOrganizationHelpUrl(); + + wxString wxurl; + wxurl.Printf( + wxT("%s?target=simple&version=%s&controlid=%d"), + strURL.c_str(), + wxString(BOINC_VERSION_STRING, wxConvUTF8).c_str(), + event.GetId() + ); + wxLaunchDefaultBrowser(wxurl); + } + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnHelpBOINC - Function End")); +} + + +void CNewSimpleFrame::OnHelpAbout(wxCommandEvent& /*event*/) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnHelpAbout - Function Begin")); + + m_pBackgroundPanel->SetDlgOpen(true); + + CDlgAbout dlg(this); + dlg.ShowModal(); + + m_pBackgroundPanel->SetDlgOpen(false); + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnHelpAbout - Function End")); +} + + +void CNewSimpleFrame::OnHelp(wxHelpEvent& event) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnHelp - Function Begin")); + + if (IsShown()) { + wxString strURL = wxGetApp().GetSkinManager()->GetAdvanced()->GetOrganizationHelpUrl(); + + wxString wxurl; + wxurl.Printf( + wxT("%s?target=simple&version=%s&controlid=%d"), + strURL.c_str(), + wxString(BOINC_VERSION_STRING, wxConvUTF8).c_str(), + event.GetId() + ); + wxLaunchDefaultBrowser(wxurl); + } + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnHelp - Function End")); +} + + +void CNewSimpleFrame::OnReloadSkin(CFrameEvent& WXUNUSED(event)) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnReloadSkin - Function Start")); + + m_pBackgroundPanel->ReskinInterface(); + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnReloadSkin - Function End")); +} + + +void CNewSimpleFrame::OnNotification(CFrameEvent& WXUNUSED(event)) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnNotification - Function Begin")); + + CDlgMessages dlg(GetParent()); + + m_pBackgroundPanel->SetDlgOpen(true); + SetMsgsDlgOpen(&dlg); + + m_pBackgroundPanel->NoticesViewed(); + dlg.ShowModal(); + + m_pBackgroundPanel->SetDlgOpen(false); + SetMsgsDlgOpen(NULL); + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnNotification - Function End")); +} + + +void CNewSimpleFrame::OnRefreshView(CFrameEvent& WXUNUSED(event)) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnRefreshView - Function Start")); + + static bool bAlreadyRunning = false; + + if (bAlreadyRunning) return; + bAlreadyRunning = true; + + m_pBackgroundPanel->OnFrameRender(); + + if (dlgMsgsPtr) { + dlgMsgsPtr->OnRefresh(); + } + + bAlreadyRunning = false; + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnRefreshView - Function End")); +} + + +void CNewSimpleFrame::OnProjectsAttachToProject() { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnProjectsAttachToProject - Function Begin")); + + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (!pDoc->IsUserAuthorized()) + return; + + if (pDoc->IsConnected()) { + + CWizardAttach* pWizard = new CWizardAttach(this); + + wxString strName = wxEmptyString; + wxString strURL = wxEmptyString; + wxString strTeamName = wxEmptyString; + pWizard->Run( strName, strURL, strTeamName, false ); + + if (pWizard) + pWizard->Destroy(); + + } else { + ShowNotCurrentlyConnectedAlert(); + } + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnProjectsAttachToProject - Function End")); +} + + +void CNewSimpleFrame::OnConnect(CFrameEvent& WXUNUSED(event)) { + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnConnect - Function Begin")); + + CMainDocument* pDoc = wxGetApp().GetDocument(); + CWizardAttach* pWizard = NULL; + wxString strComputer = wxEmptyString; + wxString strName = wxEmptyString; + wxString strURL = wxEmptyString; + wxString strTeamName = wxEmptyString; + bool bCachedCredentials = false; + ACCT_MGR_INFO ami; + PROJECT_INIT_STATUS pis; + CC_STATUS status; + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + pDoc->ForceCacheUpdate(); + pDoc->GetCoreClientStatus(status, true); + +#ifdef __WXMAC__ + wxGetApp().GetMacSystemMenu()->BuildMenu(); +#endif + + // If we are connected to the localhost, run a really quick screensaver + // test to trigger a firewall popup. + pDoc->GetConnectedComputerName(strComputer); + if (pDoc->IsComputerNameLocal(strComputer)) { + wxGetApp().StartBOINCScreensaverTest(); + wxGetApp().StartBOINCDefaultScreensaverTest(); + } + + + pDoc->rpc.get_project_init_status(pis); + pDoc->rpc.acct_mgr_info(ami); + if (ami.acct_mgr_url.size() && !ami.have_credentials) { + if (!IsShown()) { + Show(); + } + + pWizard = new CWizardAttach(this); + if (pWizard->SyncToAccountManager()) { + // If successful, hide the main window + Hide(); + } + } else if ((pis.url.size() || (0 >= pDoc->GetSimpleProjectCount())) && !status.disallow_attach) { + if (!IsShown()) { + Show(); + } + + strName = wxString(pis.name.c_str(), wxConvUTF8); + strURL = wxString(pis.url.c_str(), wxConvUTF8); + strTeamName = wxString(pis.team_name.c_str(), wxConvUTF8); + bCachedCredentials = pis.url.length() && pis.has_account_key; + + pWizard = new CWizardAttach(this); + pWizard->Run(strName, strURL, strTeamName, bCachedCredentials); + } + + if (pWizard) { + pWizard->Destroy(); + m_pBackgroundPanel->UpdateProjectView(); + } + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnConnect - Function End")); +} + + +IMPLEMENT_DYNAMIC_CLASS(CSimpleGUIPanel, wxPanel) + +BEGIN_EVENT_TABLE(CSimpleGUIPanel, wxPanel) + EVT_SIZE(CSimpleGUIPanel::OnSize) + EVT_ERASE_BACKGROUND(CSimpleGUIPanel::OnEraseBackground) + EVT_BUTTON(ID_SGNOTICESBUTTON,CSimpleGUIPanel::OnShowNotices) + EVT_BUTTON(ID_SGPAUSERESUMEBUTTON,CSimpleGUIPanel::OnPauseResume) + EVT_BUTTON(wxID_HELP,CSimpleGUIPanel::OnHelp) + EVT_TIMER(ID_SIMPLEMESSAGECHECKTIMER, CSimpleGUIPanel::OnCheckForNewNotices) + EVT_PAINT(CSimpleGUIPanel::OnPaint) +END_EVENT_TABLE() + + +CSimpleGUIPanel::CSimpleGUIPanel() { + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Default Constructor Function Begin")); + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Default Constructor Function End")); +} + + +CSimpleGUIPanel::CSimpleGUIPanel(wxWindow* parent) : + wxPanel(parent, -1, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN | wxBORDER_NONE) +{ + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Overloaded Constructor Function Begin")); + + m_taskPanel = NULL; + m_projPanel = NULL; + m_oldWorkCount = 0; + m_bNewNoticeAlert = false; + m_bNoticesButtonIsRed = false; + m_bisPaused = false; + + checkForNewNoticesTimer = new wxTimer(this, ID_SIMPLEMESSAGECHECKTIMER); + checkForNewNoticesTimer->Start(5000); + + dlgOpen = false; + m_sPauseString = _("Pause"); + m_sResumeString = _("Resume"); + m_sPauseButtonToolTip = _("Stop all activity"); + m_sResumeButtonToolTip = _("Resume activity"); + + + m_taskPanel = new CSimpleTaskPanel(this); + m_projPanel = new CSimpleProjectPanel(this); + + // Box Sizer + mainSizer = new wxBoxSizer(wxVERTICAL); + mainSizer->AddSpacer(68); + mainSizer->Add(m_taskPanel, 1, wxLEFT | wxRIGHT | wxEXPAND | wxALIGN_CENTER, SIDEMARGINS); + mainSizer->AddSpacer(8); + mainSizer->Add(m_projPanel, 0, wxLEFT | wxRIGHT | wxEXPAND | wxALIGN_CENTER, SIDEMARGINS); + mainSizer->AddSpacer(8); + + wxBoxSizer* buttonsSizer; + buttonsSizer = new wxBoxSizer( wxHORIZONTAL ); + + m_NoticesButton = new wxButton( this, ID_SGNOTICESBUTTON, _("Notices"), wxDefaultPosition, wxDefaultSize, 0 ); + m_NoticesButton->SetToolTip( _("Open a window to view notices from projects or BOINC")); + buttonsSizer->Add( m_NoticesButton, 0, wxEXPAND | wxALIGN_LEFT, 0 ); + buttonsSizer->AddStretchSpacer(); + + int pauseWidth, resumeWidth, y; + GetTextExtent(m_sPauseString, &pauseWidth, &y); + GetTextExtent(m_sResumeString, &resumeWidth, &y); + m_PauseResumeButton = new wxButton( this, ID_SGPAUSERESUMEBUTTON, + (pauseWidth > resumeWidth) ? m_sPauseString : m_sResumeString, + wxDefaultPosition, wxDefaultSize, 0 ); + + buttonsSizer->Add( m_PauseResumeButton, 0, wxEXPAND | wxALIGN_RIGHT, 0 ); + buttonsSizer->AddStretchSpacer(); + + m_HelpButton = new wxButton( this, wxID_HELP, _("Help"), wxDefaultPosition, wxDefaultSize, 0 ); + buttonsSizer->Add( m_HelpButton, 0, wxEXPAND | wxALIGN_RIGHT, 0 ); + m_HelpButton->SetToolTip( _("Get help with BOINC")); + + mainSizer->Add( buttonsSizer, 0, wxLEFT | wxRIGHT | wxEXPAND, 2 * SIDEMARGINS ); + mainSizer->AddSpacer(10); + + SetSizer(mainSizer); + Layout(); + + mainSizer->Fit(GetParent()); + + m_PauseResumeButton->SetLabel(m_sPauseString); + m_PauseResumeButton->SetToolTip(m_sPauseButtonToolTip); + + SetBackgroundBitmap(); + +#ifdef __WXMAC__ + // Tell accessibility aids to ignore this panel (but not its contents) + HIObjectSetAccessibilityIgnored((HIObjectRef)GetHandle(), true); +#endif + + m_projPanel->Hide(); + m_PauseResumeButton->Disable(); + OnFrameRender(); + + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Overloaded Constructor Function End")); +} + + +CSimpleGUIPanel::~CSimpleGUIPanel() +{ + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Destructor Function Begin")); + +#ifdef __WXMAC__ +// RemoveMacAccessibilitySupport(); /* CAF */ +#endif + + checkForNewNoticesTimer->Stop(); + delete checkForNewNoticesTimer; + m_bmpBg = wxNullBitmap; // Deletes old bitmap via reference counting + + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::CSimpleGUIPanel - Destructor Function End")); +} + + +void CSimpleGUIPanel::SetBackgroundBitmap() { + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::SetBackgroundBitmap - Function Start")); + + CSkinSimple* pSkinSimple = wxGetApp().GetSkinManager()->GetSimple(); + + wxASSERT(pSkinSimple); + wxASSERT(wxDynamicCast(pSkinSimple, CSkinSimple)); + + wxColour bgColor(*pSkinSimple->GetBackgroundImage()->GetBackgroundColor()); + SetBackgroundColour(bgColor); + + wxRect panelRect = GetRect(); + m_bmpBg = wxBitmap(panelRect.width, panelRect.height); + wxMemoryDC dc(m_bmpBg); + wxBrush bgBrush(bgColor); + dc.SetBackground(bgBrush); + dc.Clear(); + dc.DrawBitmap(*pSkinSimple->GetBackgroundImage()->GetBitmap(), 0, 0, false); + + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::SetBackgroundBitmap - Function End")); +} + +void CSimpleGUIPanel::ReskinInterface() { + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::ReskinInterface - Function Start")); + + Freeze(); + //bg color + m_bmpBg = wxNullBitmap; // Deletes old bitmap via reference counting + SetBackgroundBitmap(); + + m_taskPanel->ReskinInterface(); + m_projPanel->ReskinInterface(); + + Thaw(); + Refresh(); + + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::ReskinInterface - Function End")); +} + + +void CSimpleGUIPanel::OnProjectsAttachToProject() { + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::OnProjectsAttachToProject - Function Begin")); + + CNewSimpleFrame* pFrame = wxDynamicCast(GetParent(), CNewSimpleFrame); + wxASSERT(pFrame); + + pFrame->OnProjectsAttachToProject(); + + wxLogTrace(wxT("Function Start/End"), wxT("CNewSimpleFrame::OnProjectsAttachToProject - Function End")); +} + + +// called from CNewSimpleFrame::OnRefreshView() +void CSimpleGUIPanel::OnFrameRender() { + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + int workCount = pDoc->GetSimpleGUIWorkCount(); + CC_STATUS status; + + // OnFrameRender() may be called while SimpleGUI initialization is + // in progress due to completion of a periodic get_messages RPC, + // causing unintended recursion in CMainDocument::RequestRPC(). + // Check for that situation here. + if (pDoc->WaitingForRPC()) return; + + if (workCount != m_oldWorkCount) { + if (workCount <= 0) { + m_projPanel->Hide(); + } else if (m_oldWorkCount == 0) { + m_projPanel->Show(); + } + } + + if (IsShown()) { + if ( pDoc->IsConnected() ) { + + // Show resume or pause as appropriate + pDoc->GetCoreClientStatus(status); + + m_bisPaused = (RUN_MODE_NEVER == status.task_mode); + m_PauseResumeButton->SetLabel(m_bisPaused ? m_sResumeString : m_sPauseString); + m_PauseResumeButton->SetToolTip(m_bisPaused ? m_sResumeButtonToolTip : m_sPauseButtonToolTip); + m_PauseResumeButton->Enable(); + + UpdateProjectView(); + } else { + m_PauseResumeButton->SetToolTip(wxEmptyString); + m_PauseResumeButton->Disable(); + } + + if (m_bNewNoticeAlert) { + wxRect r = m_NoticesButton->GetRect(); + r.Inflate(4, 4); + RefreshRect(r, m_bNoticesButtonIsRed); + m_bNoticesButtonIsRed = !m_bNoticesButtonIsRed; + } + + + // State changes can cause the BSG to crash if a dialogue is open. + // Defer state change until after the dialogue is closed + if ( dlgOpen ) { + return; + } + + m_oldWorkCount = workCount; + + m_taskPanel->Update(); + +#ifdef __WXMAC__ + //Accessibility + // Hide all but top level view from accessibility support so that + // the screen reader will tell user to switch to advanced view. +// if (oldSimpleGUIWorkCount != workCount) { /* CAF */ +// oldSimpleGUIWorkCount = workCount; +// HIViewRef simple = (HIViewRef)GetHandle(); +// AccessibilityIgnoreAllChildren(simple, 1); +// } +#endif + } +} + + +void CSimpleGUIPanel::UpdateProjectView() +{ + //update Project Panel + m_projPanel->UpdateInterface(); +} + + +void CSimpleGUIPanel::OnCheckForNewNotices(wxTimerEvent& WXUNUSED(event)) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + if ( pDoc->GetUnreadNoticeCount() ) { + m_bNewNoticeAlert = true; + checkForNewNoticesTimer->Stop(); + } +} + + +void CSimpleGUIPanel::NoticesViewed() { + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + + m_bNewNoticeAlert = false; + m_bNoticesButtonIsRed = false; + wxRect r = m_NoticesButton->GetRect(); + r.Inflate(4, 4); + RefreshRect(r, true); + m_bNoticesButtonIsRed = !m_bNoticesButtonIsRed; + pDoc->UpdateUnreadNoticeState(); + checkForNewNoticesTimer->Start(); +} + + +void CSimpleGUIPanel::OnShowNotices(wxCommandEvent& /*event*/) { + NoticesViewed(); + + CDlgMessages dlg(GetParent()); + SetDlgOpen(true); + + ((CNewSimpleFrame*)GetParent())->SetMsgsDlgOpen(&dlg); + + dlg.ShowModal(); + + SetDlgOpen(false); + ((CNewSimpleFrame*)GetParent())->SetMsgsDlgOpen(NULL); +} + + +void CSimpleGUIPanel::OnPauseResume(wxCommandEvent& /*event*/) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + CC_STATUS ccs; + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (m_bisPaused) { + pDoc->GetCoreClientStatus(ccs); + + if ((RUN_MODE_NEVER == ccs.task_mode) && (0 >= ccs.task_mode_delay)) { + pDoc->SetActivityRunMode(RUN_MODE_AUTO, 0); + } else { + pDoc->SetActivityRunMode(RUN_MODE_RESTORE, 0); + } + } else { + pDoc->SetActivityRunMode(RUN_MODE_NEVER, 3600); + } + + m_PauseResumeButton->SetLabel(m_bisPaused ? m_sResumeString : m_sPauseString); + m_PauseResumeButton->SetToolTip(m_bisPaused ? m_sResumeButtonToolTip : m_sPauseButtonToolTip); +} + + +// TODO: Create ID_SIMPLE_HELP web page for each organization for new BOINC version +void CSimpleGUIPanel::OnHelp(wxCommandEvent& WXUNUSED(event)) { + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::OnHelp - Function Begin")); + + wxString strURL = wxGetApp().GetSkinManager()->GetAdvanced()->GetOrganizationHelpUrl(); + + wxString wxurl; + wxurl.Printf( + wxT("%s?target=simple&version=%s&controlid=%d"), + strURL.c_str(), + wxString(BOINC_VERSION_STRING, wxConvUTF8).c_str(), + ID_SIMPLE_HELP + + ); + + wxLaunchDefaultBrowser(wxurl); + + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleGUIPanel::OnHelp - Function End")); +} + + +void CSimpleGUIPanel::OnPaint(wxPaintEvent& event) { + wxPaintDC myDC(this); + + if (m_bNewNoticeAlert) { + wxRect r = m_NoticesButton->GetRect(); + r.Inflate(3, 3); + if (m_bNoticesButtonIsRed) { + wxPen oldPen = myDC.GetPen(); + wxBrush oldBrush = myDC.GetBrush(); + int oldMode = myDC.GetBackgroundMode(); + wxPen bgPen(*wxRED, 3); + myDC.SetBackgroundMode(wxSOLID); + myDC.SetPen(bgPen); + myDC.SetBrush(*wxTRANSPARENT_BRUSH); +#ifdef __WXMAC__ + myDC.DrawRoundedRectangle(r.x, r.y, r.width, r.height, 12); +#else + myDC.DrawRectangle(r.x, r.y, r.width, r.height); +#endif + // Restore Mode, Pen and Brush + myDC.SetBackgroundMode(oldMode); + myDC.SetPen(oldPen); + myDC.SetBrush(oldBrush); + } + } +} + + +void CSimpleGUIPanel::OnEraseBackground(wxEraseEvent& event) { + wxDC *dc = event.GetDC(); + dc->DrawBitmap(m_bmpBg, 0, 0); +} + + diff --git a/clientgui/sg_BoincSimpleFrame.h b/clientgui/sg_BoincSimpleFrame.h new file mode 100644 index 0000000000..afbf91f75a --- /dev/null +++ b/clientgui/sg_BoincSimpleFrame.h @@ -0,0 +1,147 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + + +#ifndef _BOINCSIMPLEFRAME_H_ +#define _BOINCSIMPLEFRAME_H_ + +#include "BOINCBaseFrame.h" + +#if defined(__GNUG__) && !defined(__APPLE__) +#pragma interface "sg_BoincSimpleFrame.cpp" +#endif + +class CSimpleTaskPanel; +class CSimpleProjectPanel; +class CSimpleTaskPanel; +class CDlgMessages; + +class CSimpleGUIPanel : public wxPanel +{ + DECLARE_DYNAMIC_CLASS(CSimpleGUIPanel) + +public: + CSimpleGUIPanel(); + CSimpleGUIPanel(wxWindow* parent); + + ~CSimpleGUIPanel(); + // + // My tasks panel (shown when there are active tasks) + CSimpleTaskPanel *m_taskPanel; + // My projects panel + CSimpleProjectPanel *m_projPanel; + ////////////////////////////; + + void SetBackgroundBitmap(); + void ReskinInterface(); + void UpdateProjectView(); + void OnFrameRender(); + void OnProjectsAttachToProject(); + void OnShowNotices(wxCommandEvent& event); + void OnPauseResume(wxCommandEvent& event); + void OnHelp( wxCommandEvent& event ); + void SetDlgOpen(bool newDlgState) { dlgOpen = newDlgState; } + bool GetDlgOpen() { return dlgOpen; } + wxBitmap *GetBackgroundBitMap() { return &m_bmpBg; } + void OnCheckForNewNotices(wxTimerEvent& WXUNUSED(event)); + void NoticesViewed(); + + ////////// + wxBoxSizer *mainSizer; + ////////// + bool m_bNewNoticeAlert; + bool m_bNoticesButtonIsRed; + DECLARE_EVENT_TABLE() + +protected: + void OnPaint(wxPaintEvent& event); + void OnEraseBackground(wxEraseEvent& event); +#ifdef __WXMAC__ +// void SetupMacAccessibilitySupport(); +// void RemoveMacAccessibilitySupport(); + +// EventHandlerRef m_pSGAccessibilityEventHandlerRef; + +#endif + wxBitmap m_bmpBg; + wxButton *m_NoticesButton; + wxButton *m_PauseResumeButton; + wxButton *m_HelpButton; + wxString m_sPauseString; + wxString m_sResumeString; + int m_oldWorkCount; + bool m_bisPaused; + +private: + bool dlgOpen; + wxTimer* checkForNewNoticesTimer; + wxString m_sPauseButtonToolTip; + wxString m_sResumeButtonToolTip; +}; + + +// Define a new frame +class CNewSimpleFrame : public CBOINCBaseFrame +{ + DECLARE_DYNAMIC_CLASS(CNewSimpleFrame) + +public: + CNewSimpleFrame(); + CNewSimpleFrame(wxString title, wxIcon* icon, wxIcon* icon32, wxPoint position, wxSize size); + + ~CNewSimpleFrame(); + + void OnChangeGUI( wxCommandEvent& event ); + void OnPreferences( wxCommandEvent& event ); + void OnOptions( wxCommandEvent& event ); + void OnOldSG( wxCommandEvent& event ); + void OnHelp( wxHelpEvent& event ); + void OnHelpBOINC( wxCommandEvent& event ); + void OnHelpAbout( wxCommandEvent& event ); + + void OnProjectsAttachToProject(); + + void OnConnect(CFrameEvent& event ); + void OnReloadSkin( CFrameEvent& event ); + void OnRefreshView( CFrameEvent& event ); + void OnNotification( CFrameEvent& event ); + + void SetMsgsDlgOpen(CDlgMessages* newDlgPtr) { dlgMsgsPtr = newDlgPtr; } + bool isMessagesDlgOpen() { return (dlgMsgsPtr != NULL); } + + bool SaveState(); + bool RestoreState(); + +protected: + virtual int _GetCurrentViewPage(); + + wxMenuBar* m_pMenubar; + wxAcceleratorEntry m_Shortcuts[1]; + wxAcceleratorTable* m_pAccelTable; + + CSimpleGUIPanel* m_pBackgroundPanel; + + +private: + CDlgMessages* dlgMsgsPtr; + + DECLARE_EVENT_TABLE() +}; + +#endif // _BOINCSIMPLEFRAME_H_ + + diff --git a/clientgui/sg_CustomControls.cpp b/clientgui/sg_CustomControls.cpp index cf2267dc70..d24e496ebe 100644 --- a/clientgui/sg_CustomControls.cpp +++ b/clientgui/sg_CustomControls.cpp @@ -69,7 +69,8 @@ END_EVENT_TABLE() CTransparentStaticText::CTransparentStaticText() {} CTransparentStaticText::CTransparentStaticText(wxWindow* parent, wxWindowID id, const wxString& label, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) { - Create(parent, id, label, pos, size, style, name); + // Set name same as label for accessibility on Windows + Create(parent, id, label, pos, size, style, label); } @@ -84,6 +85,14 @@ bool CTransparentStaticText::Create(wxWindow* parent, wxWindowID id, const wxStr } +#ifndef __WXMAC__ +void CTransparentStaticText::SetLabel(const wxString& label) { + wxStaticText::SetLabel(label); + GetParent()->RefreshRect(GetRect()); +} +#endif + + void CTransparentStaticText::OnPaint(wxPaintEvent& /*event*/) { wxPaintDC dc(this); dc.SetFont(GetFont()); diff --git a/clientgui/sg_CustomControls.h b/clientgui/sg_CustomControls.h index f3bd1d6b0a..7446204e16 100644 --- a/clientgui/sg_CustomControls.h +++ b/clientgui/sg_CustomControls.h @@ -91,6 +91,8 @@ public: #ifdef __WXMAC__ virtual void OnEraseBackground(wxEraseEvent& /*event*/) {}; +#else + virtual void SetLabel(const wxString& label); #endif virtual void OnPaint(wxPaintEvent& event); diff --git a/clientgui/sg_PanelBase.cpp b/clientgui/sg_PanelBase.cpp new file mode 100755 index 0000000000..72629f7c81 --- /dev/null +++ b/clientgui/sg_PanelBase.cpp @@ -0,0 +1,145 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#include "stdwx.h" +#include "sg_PanelBase.h" + +IMPLEMENT_DYNAMIC_CLASS(CSimplePanelBase, wxPanel) + +BEGIN_EVENT_TABLE(CSimplePanelBase, wxPanel) + EVT_ERASE_BACKGROUND(CSimplePanelBase::OnEraseBackground) +END_EVENT_TABLE() + + +CSimplePanelBase::CSimplePanelBase() { +} + + +CSimplePanelBase::CSimplePanelBase( wxWindow* parent ) : + wxPanel( parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN | wxBORDER_NONE ) +{ +#ifdef __WXMSW__ + SetDoubleBuffered(true); +#endif + +#ifdef __WXMAC__ + // Tell accessibility aids to ignore this panel (but not its contents) + HIObjectSetAccessibilityIgnored((HIObjectRef)GetHandle(), true); +#endif +} + + +CSimplePanelBase::~CSimplePanelBase() +{ +} + + +void CSimplePanelBase::ReskinInterface() { + m_GotBGBitMap = false; +} + + +// Create a background bitmap simulating partial transparency +void CSimplePanelBase::MakeBGBitMap() { + wxRect r; + wxBitmap rawBmp; + wxBitmap whiteBmp; + wxImage bgImage; + wxImage whiteImage; + register unsigned char *bgImagePixels; + register unsigned char *whitePixels; + register int i, j, k; + wxPen bgPen(*wxWHITE, 1, wxTRANSPARENT); + wxBrush bgBrush(*wxWHITE); + + GetPosition(&r.x, &r.y); + GetSize(&r.width, &r.height); + wxBitmap *bgBmp(((CSimpleGUIPanel*)GetParent())->GetBackgroundBitMap()); + wxRect bgRect(0, 0, bgBmp->GetWidth(), bgBmp->GetHeight()); + if (bgRect.Contains(r)) { + rawBmp = bgBmp->GetSubBitmap(r); + } else { + fprintf(stderr, "SimpleGUI background image is too small\n"); + rawBmp = wxBitmap(r.width, r.height); + wxMemoryDC dc(rawBmp); + wxPen rawPen(*wxBLACK, 1, wxTRANSPARENT); + wxBrush rawBrush(*wxBLACK); + dc.SetBackgroundMode(wxSOLID); + dc.SetPen(rawPen); + dc.SetBrush(rawBrush); + dc.DrawRectangle(0, 0, r.width, r.height); + } + + whiteBmp = wxBitmap(r.width, r.height); + wxMemoryDC dc(whiteBmp); + dc.SetBackgroundMode(wxSOLID); + dc.SetPen(bgPen); + dc.SetBrush(bgBrush); + dc.DrawRoundedRectangle(0, 0, r.width, r.height, 10.0); + + bgImage = rawBmp.ConvertToImage(); + bgImagePixels = bgImage.GetData(); // RGBRGBRGB... + whiteImage = whiteBmp.ConvertToImage(); + whitePixels = whiteImage.GetData(); // RGBRGBRGB... + + for (i=0; iDrawBitmap(m_TaskPanelBGBitMap, 0, 0); + wxPen oldPen= dc->GetPen(); + wxBrush oldBrush = dc->GetBrush(); + int oldMode = dc->GetBackgroundMode(); + wxCoord w, h; + wxPen bgPen(*wxBLUE, 3); + wxBrush bgBrush(*wxBLUE, wxTRANSPARENT); + + dc->SetBackgroundMode(wxSOLID); + dc->SetPen(bgPen); + dc->SetBrush(bgBrush); + dc->GetSize(&w, &h); + dc->DrawRoundedRectangle(0, 0, w, h, 10.0); + + // Restore Mode, Pen and Brush + dc->SetBackgroundMode(oldMode); + dc->SetPen(oldPen); + dc->SetBrush(oldBrush); +} diff --git a/clientgui/sg_PanelBase.h b/clientgui/sg_PanelBase.h new file mode 100755 index 0000000000..c26f53e142 --- /dev/null +++ b/clientgui/sg_PanelBase.h @@ -0,0 +1,89 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#ifndef __sg_PanelBase__ +#define __sg_PanelBase__ + +#include "sg_BoincSimpleFrame.h" + + +// TODO: Move these to events.h +enum{ + ID_CHANGE_SLIDE_TIMER = 14000, + WEBSITE_URL_MENU_ID = 34500, + WEBSITE_URL_MENU_ID_REMOVE_PROJECT = 34550, + WEBSITE_URL_MENU_ID_HOMEPAGE = 34551, +}; + + + +/////////////////////////////////////////////////////////////////////////// + +#ifdef __WXMAC__ +#define SMALL_FONT 12 +#define MEDIUM_FONT 16 +#define LARGE_FONT 20 +#else +#define SMALL_FONT 9 +#define MEDIUM_FONT 12 +#define LARGE_FONT 16 +#endif + +#define SIDEMARGINS 30 + + +/////////////////////////////////////////////////////////////////////////////// +/// Class CSimplePanelBase +/////////////////////////////////////////////////////////////////////////////// + +#ifdef __WXMAC__ +#include "MacBitmapComboBox.h" +#else +// TODO: Subclass CBOINCBitmapComboBox to be accessible on Windows. Either: +// Add WxBitmapComboBoxAccessible class (like CNoticeListCtrlAccessible for CNoticeListCtrl) +// or simulate bitmap combo box using accessible standard Windows controls (as done for +// CBOINCBitmapComboBox on Mac) +// TODO: Add wx/bmpcbox.h to stdwx.h +#include +#define CBOINCBitmapComboBox wxBitmapComboBox +#define EVT_BOINCBITMAPCOMBOBOX EVT_COMBOBOX +#endif + + +class CSimplePanelBase : public wxPanel +{ + DECLARE_DYNAMIC_CLASS( CSimplePanelBase ) + DECLARE_EVENT_TABLE() + + private: + void MakeBGBitMap(); + void OnEraseBackground(wxEraseEvent& event); + + protected: + wxBitmap m_TaskPanelBGBitMap; + bool m_GotBGBitMap; + + public: + CSimplePanelBase(); + CSimplePanelBase( wxWindow* parent); + ~CSimplePanelBase(); + + void ReskinInterface(); + virtual wxRect GetProgressRect() { return wxRect(0, 0, 0, 0); } +}; + +#endif //__sg_PanelBase__ diff --git a/clientgui/sg_ProjectCommandPopup.cpp b/clientgui/sg_ProjectCommandPopup.cpp new file mode 100644 index 0000000000..3298dabc17 --- /dev/null +++ b/clientgui/sg_ProjectCommandPopup.cpp @@ -0,0 +1,298 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + + +#include "stdwx.h" +#include "Events.h" +#include "BOINCGUIApp.h" +#include "MainDocument.h" +#include "DlgItemProperties.h" +#include "sg_ProjectPanel.h" +#include "sg_ProjectCommandPopup.h" + +IMPLEMENT_DYNAMIC_CLASS(CSimpleProjectCommandPopupButton, wxButton) + +BEGIN_EVENT_TABLE(CSimpleProjectCommandPopupButton, wxButton) + EVT_LEFT_DOWN(CSimpleProjectCommandPopupButton::OnProjectCommandsButton) + EVT_MENU(ID_TASK_PROJECT_UPDATE, CSimpleProjectCommandPopupButton::OnProjectUpdate) + EVT_MENU(ID_TASK_PROJECT_SUSPEND, CSimpleProjectCommandPopupButton::OnProjectSuspendResume) + EVT_MENU(ID_TASK_PROJECT_NONEWWORK, CSimpleProjectCommandPopupButton::OnProjectNoNewWork) + EVT_MENU(ID_TASK_PROJECT_RESET, CSimpleProjectCommandPopupButton::OnResetProject) + EVT_MENU(ID_TASK_PROJECT_DETACH, CSimpleProjectCommandPopupButton::OnProjectDetach) + EVT_MENU(ID_TASK_PROJECT_SHOW_PROPERTIES, CSimpleProjectCommandPopupButton::OnProjectShowProperties) +END_EVENT_TABLE() + +CSimpleProjectCommandPopupButton::CSimpleProjectCommandPopupButton() { +} + +CSimpleProjectCommandPopupButton::CSimpleProjectCommandPopupButton(wxWindow* parent, wxWindowID id, + const wxString& label, const wxPoint& pos, const wxSize& size, + long style, const wxValidator& validator, const wxString& name) : + wxButton(parent, id, label, pos, size, style, validator, name) + { + + m_ProjectCommandsPopUpMenu = new wxMenu(); + AddMenuItems(); +} + + +CSimpleProjectCommandPopupButton::~CSimpleProjectCommandPopupButton() { + delete m_ProjectCommandsPopUpMenu; +} + + +void CSimpleProjectCommandPopupButton::AddMenuItems() { + m_UpdateProjectMenuItem = m_ProjectCommandsPopUpMenu->Append( + ID_TASK_PROJECT_UPDATE, + _("Update"), + _("Report all completed tasks, get latest credit, get latest preferences, and possibly get more tasks.") + ); + + m_SuspendResumeMenuItem = m_ProjectCommandsPopUpMenu->Append( + ID_TASK_PROJECT_SUSPEND, + _("Suspend"), + _("Suspend tasks for this project.") + ); + + m_NoNewTasksMenuItem = m_ProjectCommandsPopUpMenu->Append( + ID_TASK_PROJECT_NONEWWORK, + _("No new tasks"), + _("Don't get new tasks for this project.") + ); + + m_ResetProjectMenuItem = m_ProjectCommandsPopUpMenu->Append( + ID_TASK_PROJECT_RESET, + _("Reset project"), + _("Delete all files and tasks associated with this project, and get new tasks. You can update the project first to report any completed tasks.") + ); + + m_RemoveProjectMenuItem = m_ProjectCommandsPopUpMenu->Append( + ID_TASK_PROJECT_DETACH, + _("Remove"), + _("Remove this project. Tasks in progress will be lost (use 'Update' first to report any completed tasks).") + ); + + m_ShowPropertiesMenuItem = m_ProjectCommandsPopUpMenu->Append( + ID_TASK_PROJECT_SHOW_PROPERTIES, + _("Properties"), + _("Show project details.") + ); +} + + +void CSimpleProjectCommandPopupButton::OnProjectCommandsButton(wxMouseEvent& /*event*/) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + ProjectSelectionData* selData = ((CSimpleProjectPanel*)GetParent())->GetProjectSelectionData(); + if (selData == NULL) return; + char* ctrl_url = selData->project_url; + PROJECT* project = pDoc->state.lookup_project(ctrl_url); + if (!project) return; + + if (project->suspended_via_gui) { + m_SuspendResumeMenuItem->SetItemLabel(_("Resume")); + m_SuspendResumeMenuItem->SetHelp(_("Resume tasks for this project.")); + } else { + m_SuspendResumeMenuItem->SetItemLabel(_("Suspend")); + m_SuspendResumeMenuItem->SetHelp(_("Suspend tasks for this project.")); + } + + if (project->dont_request_more_work) { + m_NoNewTasksMenuItem->SetItemLabel(_("Allow new tasks")); + m_NoNewTasksMenuItem->SetHelp(_("Allow fetching new tasks for this project.")); + } else { + m_NoNewTasksMenuItem->SetItemLabel(_("No new tasks")); + m_NoNewTasksMenuItem->SetHelp(_("Don't fetch new tasks for this project.")); + } + + m_RemoveProjectMenuItem->Enable(!project->attached_via_acct_mgr); + + PopupMenu(m_ProjectCommandsPopUpMenu); +} + + +void CSimpleProjectCommandPopupButton::OnProjectUpdate( wxCommandEvent& WXUNUSED(event) ) { + int projectIndex; + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + ProjectSelectionData* selData = ((CSimpleProjectPanel*)GetParent())->GetProjectSelectionData(); + if (selData == NULL) return; + char* ctrl_url = selData->project_url; + PROJECT* project = FindProjectIndexFromURL(ctrl_url, &projectIndex); + if (!project) return; + + pDoc->ProjectUpdate(projectIndex); +} + + +void CSimpleProjectCommandPopupButton::OnProjectSuspendResume(wxCommandEvent& WXUNUSED(event)) { + int projectIndex; + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + ProjectSelectionData* selData = ((CSimpleProjectPanel*)GetParent())->GetProjectSelectionData(); + if (selData == NULL) return; + char* ctrl_url = selData->project_url; + PROJECT* project = FindProjectIndexFromURL(ctrl_url, &projectIndex); + if (!project) return; + + if (project->suspended_via_gui) { + pDoc->ProjectResume(projectIndex); + } else { + pDoc->ProjectSuspend(projectIndex); + } +} + + +void CSimpleProjectCommandPopupButton::OnProjectNoNewWork(wxCommandEvent& WXUNUSED(event)) { + int projectIndex; + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + ProjectSelectionData* selData = ((CSimpleProjectPanel*)GetParent())->GetProjectSelectionData(); + if (selData == NULL) return; + char* ctrl_url = selData->project_url; + PROJECT* project = FindProjectIndexFromURL(ctrl_url, &projectIndex); + if (!project) return; + + if (project->dont_request_more_work) { + pDoc->ProjectAllowMoreWork(projectIndex); + } else { + pDoc->ProjectNoMoreWork(projectIndex); + } +} + + +void CSimpleProjectCommandPopupButton::OnResetProject(wxCommandEvent& WXUNUSED(event)) { + int projectIndex; + wxInt32 iAnswer = 0; + wxString strMessage = wxEmptyString; + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (!pDoc->IsUserAuthorized()) + return; + + ProjectSelectionData* selData = ((CSimpleProjectPanel*)GetParent())->GetProjectSelectionData(); + if (selData == NULL) return; + char* ctrl_url = selData->project_url; + PROJECT* project = FindProjectIndexFromURL(ctrl_url, &projectIndex); + if (!project) return; + + wxString projname(project->project_name.c_str(), wxConvUTF8); + strMessage.Printf( + _("Are you sure you want to reset project '%s'?"), + projname.c_str() + ); + + iAnswer = wxGetApp().SafeMessageBox( + strMessage, + _("Reset Project"), + wxYES_NO | wxICON_QUESTION, + this + ); + + if (wxYES == iAnswer) { + pDoc->ProjectReset(projectIndex); + } +} + + +void CSimpleProjectCommandPopupButton::OnProjectDetach(wxCommandEvent& WXUNUSED(event)) { + int projectIndex; + wxInt32 iAnswer = 0; + wxString strMessage = wxEmptyString; + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (!pDoc->IsUserAuthorized()) + return; + + ProjectSelectionData* selData = ((CSimpleProjectPanel*)GetParent())->GetProjectSelectionData(); + if (selData == NULL) return; + char* ctrl_url = selData->project_url; + PROJECT* project = FindProjectIndexFromURL(ctrl_url, &projectIndex); + if (!project) return; + + wxString projname(project->project_name.c_str(), wxConvUTF8); + strMessage.Printf( + _("Are you sure you want to remove project '%s'?"), + projname.c_str() + ); + + iAnswer = wxGetApp().SafeMessageBox( + strMessage, + _("Remove Project"), + wxYES_NO | wxICON_QUESTION, + this + ); + + if (wxYES == iAnswer) { + pDoc->ProjectDetach(projectIndex); + } +} + + +void CSimpleProjectCommandPopupButton::OnProjectShowProperties(wxCommandEvent& WXUNUSED(event)) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + ProjectSelectionData* selData = ((CSimpleProjectPanel*)GetParent())->GetProjectSelectionData(); + if (selData == NULL) return; + char* ctrl_url = selData->project_url; + PROJECT* project = pDoc->state.lookup_project(ctrl_url); + if (!project) return; + + CDlgItemProperties dlg(this); + dlg.renderInfos(project); + dlg.ShowModal(); +} + + +PROJECT* CSimpleProjectCommandPopupButton::FindProjectIndexFromURL(char *project_url, int *index) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + int prjCount = pDoc->GetSimpleProjectCount(); + for(int i = 0; i < prjCount; i++){ + PROJECT* project = pDoc->project(i); + if(!strcmp(project->master_url, project_url)){ + *index = i; + return project; + } + } + *index = -1; + return NULL; +} + diff --git a/clientgui/sg_ProjectCommandPopup.h b/clientgui/sg_ProjectCommandPopup.h new file mode 100644 index 0000000000..9c2354c88e --- /dev/null +++ b/clientgui/sg_ProjectCommandPopup.h @@ -0,0 +1,60 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#ifndef __sg_ProjectCommandPopup__ +#define __sg_ProjectCommandPopup__ + +class CSimpleProjectCommandPopupButton : public wxButton +{ + DECLARE_DYNAMIC_CLASS( CSimpleProjectCommandPopupButton ) + DECLARE_EVENT_TABLE() + + public: + CSimpleProjectCommandPopupButton(); + + CSimpleProjectCommandPopupButton(wxWindow* parent, wxWindowID id, + const wxString& label = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxT("ProjectCommandsPopupMenu")); + + ~CSimpleProjectCommandPopupButton(); + + private: + void AddMenuItems(); + void OnProjectCommandsButton(wxMouseEvent& event); + void OnProjectUpdate(wxCommandEvent& event); + void OnProjectSuspendResume(wxCommandEvent& event); + void OnProjectNoNewWork(wxCommandEvent& event); + void OnResetProject(wxCommandEvent& event); + void OnProjectDetach(wxCommandEvent& event); + void OnProjectShowProperties(wxCommandEvent& event); + PROJECT* FindProjectIndexFromURL(char *project_url, int *index); + + protected: + wxMenu* m_ProjectCommandsPopUpMenu; + wxMenuItem* m_UpdateProjectMenuItem; + wxMenuItem* m_SuspendResumeMenuItem; + wxMenuItem* m_NoNewTasksMenuItem; + wxMenuItem* m_ResetProjectMenuItem; + wxMenuItem* m_RemoveProjectMenuItem; + wxMenuItem* m_ShowPropertiesMenuItem; +}; + +#endif // __sg_ProjectCommandPopup__ diff --git a/clientgui/sg_ProjectPanel.cpp b/clientgui/sg_ProjectPanel.cpp new file mode 100755 index 0000000000..d159bd7d61 --- /dev/null +++ b/clientgui/sg_ProjectPanel.cpp @@ -0,0 +1,463 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#define TESTBIGICONPOPUP 0 + +#include "stdwx.h" +#include "Events.h" +#include "app_ipc.h" +#include "BOINCGUIApp.h" +#include "MainDocument.h" +#include "SkinManager.h" +#include "wizardex.h" +#include "BOINCBaseWizard.h" +#include "WizardAttach.h" +#include "sg_ProjectPanel.h" +#if TESTBIGICONPOPUP +#include "test/sah_40.xpm" +#include "test/einstein_icon.xpm" +#endif + + + +IMPLEMENT_DYNAMIC_CLASS(CSimpleProjectPanel, CSimplePanelBase) + +BEGIN_EVENT_TABLE(CSimpleProjectPanel, CSimplePanelBase) + EVT_BOINCBITMAPCOMBOBOX(ID_SGPROJECTSELECTOR, CSimpleProjectPanel::OnProjectSelection) + EVT_BUTTON(ID_ADDROJECTBUTTON, CSimpleProjectPanel::OnAddProject) +#if TESTBIGICONPOPUP + EVT_BUTTON(ID_PROJECTWEBSITESBUTTON, CSimpleProjectPanel::OnProjectWebSiteButton) + EVT_BUTTON(ID_PROJECTCOMMANDBUTTON, CSimpleProjectPanel::OnProjectCommandButton) +#endif +END_EVENT_TABLE() + + +#if TESTBIGICONPOPUP +static wxString tempArray[] = {_T("String1"), _T("String2"), _T("String3"), _T("String4") }; +static wxBitmap bmArray[3]; +#endif + +#define SIDEMARGINS 30 + +CSimpleProjectPanel::CSimpleProjectPanel() { +} + + +CSimpleProjectPanel::CSimpleProjectPanel( wxWindow* parent ) : + CSimplePanelBase( parent ) +{ + wxSize sz; + wxString str = wxEmptyString; + wxWindowDC dc(this); + + m_UsingAccountManager = -1; // Force action the first time + m_CurrentSelectedProjectURL[0] = '\0'; + + m_sAddProjectString = _("Add Project"); + m_sSynchronizeString = _("Synchronize"); + m_sTotalWorkDoneString = _("My total work done this Project"); + + m_sAddProjectToolTip = _("Volunteer for any or all of 30+ projects in many areas of science"); + m_sSynchronizeToolTip = _("Synchronize projects with account manager system"); + + m_GotBGBitMap = false; // Can't be made until parent has been laid out. + SetFont(wxFont(SMALL_FONT,wxSWISS,wxNORMAL,wxNORMAL,false,wxT("Arial"))); + + wxBoxSizer* bSizer1; + bSizer1 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer2; + bSizer2 = new wxBoxSizer( wxHORIZONTAL ); + + bSizer1->AddSpacer(5); + m_myProjectsLabel = new CTransparentStaticText( this, wxID_ANY, _("My Projects:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_myProjectsLabel->Wrap( -1 ); +// m_myProjectsLabel->SetFont(wxFont(MEDIUM_FONT,wxSWISS,wxNORMAL,wxBOLD,false,wxT("Arial"))); + m_myProjectsLabel->Enable( false ); + bSizer2->Add( m_myProjectsLabel, 0, wxRIGHT, 5 ); + bSizer2->AddStretchSpacer(); + + int addProjectWidth, synchronizeWidth, y; + GetTextExtent(m_sAddProjectString, &addProjectWidth, &y); + GetTextExtent(m_sSynchronizeString, &synchronizeWidth, &y); + m_TaskAddProjectButton = new wxButton( this, ID_ADDROJECTBUTTON, + (addProjectWidth > synchronizeWidth) ? m_sAddProjectString : m_sSynchronizeString, + wxDefaultPosition, wxDefaultSize, 0 ); + + bSizer2->Add( m_TaskAddProjectButton, 0, wxRIGHT | wxEXPAND | wxALIGN_RIGHT, SIDEMARGINS ); + bSizer1->Add( bSizer2, 0, wxEXPAND | wxTOP | wxLEFT, 10 ); + +#ifdef __WXMSW__ + bSizer1->AddSpacer(5); +#endif + +#if TESTBIGICONPOPUP + m_ProjectSelectionCtrl = new CBOINCBitmapComboBox( this, ID_SGPROJECTSELECTOR, wxT(""), wxDefaultPosition, wxSize(-1, 42), 4, tempArray, wxCB_READONLY ); + CSkinSimple* pSkinSimple = wxGetApp().GetSkinManager()->GetSimple(); + bmArray[0] = *pSkinSimple->GetProjectImage()->GetBitmap(); + m_ProjectSelectionCtrl->SetItemBitmap(0, bmArray[0]); + bmArray[1] = wxBitmap((const char**)sah_40_xpm); + m_ProjectSelectionCtrl->SetItemBitmap(1, bmArray[1]); + bmArray[2] = wxBitmap((const char**)einstein_icon_xpm); + m_ProjectSelectionCtrl->SetItemBitmap(3, bmArray[2]); +// m_ProjectSelectionCtrl->SetStringSelection(tempArray[1]); + m_ProjectSelectionCtrl->SetSelection(1); +#else + m_ProjectSelectionCtrl = new CBOINCBitmapComboBox( this, ID_SGPROJECTSELECTOR, wxT(""), wxDefaultPosition, wxSize(-1, 42), 0, NULL, wxCB_READONLY ); +#endif + // TODO: Might want better wording for Project Selection Combo Box tooltip + str = _("Select a project to access with the controls below"); + m_ProjectSelectionCtrl->SetToolTip(str); + bSizer1->Add( m_ProjectSelectionCtrl, 0, wxLEFT | wxRIGHT | wxEXPAND, SIDEMARGINS ); + +#ifdef __WXMSW__ + bSizer1->AddSpacer(8); +#endif + + // Make sure m_TotalCreditValue string is large enough + str.Printf(_("%s: %0.2f"), m_sTotalWorkDoneString.c_str(), 9999999999.99); + m_TotalCreditValue = new CTransparentStaticText( this, wxID_ANY, str, wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE ); + m_TotalCreditValue->Wrap( -1 ); + m_TotalCreditValue->Enable( false ); + + bSizer1->Add( m_TotalCreditValue, 0, wxLEFT | wxRIGHT | wxEXPAND, SIDEMARGINS ); + + bSizer1->AddSpacer(5); + + wxBoxSizer* bSizer3; + bSizer3 = new wxBoxSizer( wxHORIZONTAL ); + + m_ProjectWebSitesButton = new CSimpleProjectWebSitesPopupButton( this, ID_PROJECTWEBSITESBUTTON, _("Project Web Sites"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer3->Add( m_ProjectWebSitesButton, 0, wxEXPAND | wxALIGN_LEFT, 0 ); + bSizer3->AddStretchSpacer(); + + m_ProjectCommandsButton = new CSimpleProjectCommandPopupButton( this, ID_PROJECTCOMMANDBUTTON, _("Project Commands"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer3->Add( m_ProjectCommandsButton, 0, wxEXPAND | wxALIGN_RIGHT, 0 ); + + bSizer1->Add( bSizer3, 0, wxLEFT | wxRIGHT | wxEXPAND, SIDEMARGINS ); + + bSizer1->AddSpacer(10); + + this->SetSizer( bSizer1 ); + this->Layout(); + + m_TaskAddProjectButton->SetLabel(m_sAddProjectString); + m_TaskAddProjectButton->Disable(); +} + + +CSimpleProjectPanel::~CSimpleProjectPanel() +{ +} + + +ProjectSelectionData* CSimpleProjectPanel::GetProjectSelectionData() { + int count = m_ProjectSelectionCtrl->GetCount(); + if (count <= 0) { + return NULL; + } + + int n = m_ProjectSelectionCtrl->GetSelection(); + return (ProjectSelectionData*)m_ProjectSelectionCtrl->GetClientData(n); +} + + +void CSimpleProjectPanel::UpdateInterface() { + int n, count; + bool b_needMenuRebuild = false; + wxString str = wxEmptyString; + wxString projName = wxEmptyString; + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + + // Should we display the synchronize button instead of the + // attach to project button? + if ( pDoc->IsConnected() ) { + CC_STATUS status; + int is_acct_mgr_detected = 0; + + pDoc->GetCoreClientStatus(status); + + if (pDoc->m_iAcct_mgr_info_rpc_result == 0) { + // We use an integer rather than a bool to force action the first time + is_acct_mgr_detected = pDoc->ami.acct_mgr_url.size() ? 1 : 0; + + if (m_UsingAccountManager != is_acct_mgr_detected) { + m_UsingAccountManager = is_acct_mgr_detected; + if (is_acct_mgr_detected) { + m_TaskAddProjectButton->SetLabel(m_sSynchronizeString); + m_TaskAddProjectButton->Enable(); + m_TaskAddProjectButton->Show(); + m_TaskAddProjectButton->SetToolTip(m_sAddProjectToolTip); + } else { + m_TaskAddProjectButton->SetLabel(m_sAddProjectString); + if (!status.disallow_attach) { + m_TaskAddProjectButton->Enable(); + m_TaskAddProjectButton->Show(); + m_TaskAddProjectButton->SetToolTip(m_sSynchronizeToolTip); + } + } + } + } else { + m_TaskAddProjectButton->Hide(); + } + + UpdateProjectList(); + + count = m_ProjectSelectionCtrl->GetCount(); + if (count > 0) { + n = m_ProjectSelectionCtrl->GetSelection(); + if ((n < 0) || (n > count -1)) { + m_ProjectSelectionCtrl->SetSelection(0); + n = 0; + } + + // Check to see if we need to rebuild the menu + char* ctrl_url = ((ProjectSelectionData*)m_ProjectSelectionCtrl->GetClientData(n))->project_url; + if (strcmp(m_CurrentSelectedProjectURL, ctrl_url)) { + b_needMenuRebuild = true; + strncpy(m_CurrentSelectedProjectURL, ctrl_url, sizeof(m_CurrentSelectedProjectURL)); + } + + PROJECT* project = pDoc->state.lookup_project(ctrl_url); + if ( project != NULL && project->last_rpc_time > m_Project_last_rpc_time ) { + b_needMenuRebuild = true; + m_Project_last_rpc_time = project->last_rpc_time; + } + + if (b_needMenuRebuild) { + m_ProjectWebSitesButton->RebuildMenu(); + } + + m_ProjectWebSitesButton->Enable(); + + str.Printf(_("%s: %0.2f"), m_sTotalWorkDoneString.c_str(), project->user_total_credit); + m_TotalCreditValue->SetLabel(str); + m_TotalCreditValue->SetName(str); // For accessibility on Windows + projName = m_ProjectSelectionCtrl->GetStringSelection(); + str.Printf(_("Pop up a menu of websites for project %s"), projName.c_str()); + m_ProjectWebSitesButton->SetToolTip(str); + str.Printf(_("Pop up a menu of commands to apply to project %s"), projName.c_str()); + m_ProjectCommandsButton->SetToolTip(str); + } else { + m_ProjectWebSitesButton->Disable(); + m_CurrentSelectedProjectURL[0] = '\0'; + m_TotalCreditValue->SetLabel(wxEmptyString); + m_TotalCreditValue->SetName(wxEmptyString); // For accessibility on Windows + m_ProjectWebSitesButton->SetToolTip(wxEmptyString); + m_ProjectCommandsButton->SetToolTip(wxEmptyString); + } + } +} + + +void CSimpleProjectPanel::OnAddProject(wxCommandEvent& /*event*/) { + if (m_UsingAccountManager) { + OnWizardUpdate(); + } else { + OnWizardAttach(); + } +} + + +void CSimpleProjectPanel::OnWizardAttach() { + wxLogTrace(wxT("Function Start/End"), wxT("CProjectsComponent::OnWizardAttach - Function Begin")); + + CMainDocument* pDoc = wxGetApp().GetDocument(); + CSimpleGUIPanel* pPanel = wxDynamicCast(GetParent(), CSimpleGUIPanel); + + wxASSERT(pDoc); + wxASSERT(pPanel); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (!pDoc->IsUserAuthorized()) return; + + if (!pDoc->IsConnected()) return; + + pPanel->SetDlgOpen(true); + + pPanel->OnProjectsAttachToProject(); +// btnAddProj->Refresh(); + + pPanel->SetDlgOpen(false); + + wxLogTrace(wxT("Function Start/End"), wxT("CProjectsComponent::OnWizardAttach - Function End")); +} + + +void CSimpleProjectPanel::OnWizardUpdate() { + wxLogTrace(wxT("Function Start/End"), wxT("CProjectsComponent::OnWizardUpdate - Function Begin")); + + CMainDocument* pDoc = wxGetApp().GetDocument(); + CSimpleGUIPanel* pPanel = wxDynamicCast(GetParent(), CSimpleGUIPanel); + + wxASSERT(pDoc); + wxASSERT(pPanel); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (!pDoc->IsUserAuthorized()) return; + + if (!pDoc->IsConnected()) return; + + pPanel->SetDlgOpen(true); + + CWizardAttach* pWizard = new CWizardAttach(this); + + pWizard->SyncToAccountManager(); + + if (pWizard) + pWizard->Destroy(); + +// btnSynchronize->Refresh(); + + pPanel->SetDlgOpen(false); + + wxLogTrace(wxT("Function Start/End"), wxT("CProjectsComponent::OnWizardUpdate - Function End")); +} + + +#if TESTBIGICONPOPUP +void CSimpleProjectPanel::OnProjectWebSiteButton(wxCommandEvent& /*event*/) { + m_ProjectSelectionCtrl->Delete(0); /*** CAF *** FOR TESTING ONLY ***/ +} + + +void CSimpleProjectPanel::OnProjectCommandButton(wxCommandEvent& /*event*/) { +/*** CAF *** FOR TESTING ONLY ***/ + static int i = 1; + wxString s; + + if (++i > 8) i = 0; + int sel = i % 3; +// m_ProjectSelectionCtrl->SetStringSelection(tempArray[sel]); + m_ProjectSelectionCtrl->SetSelection(sel); +#if 0 //TESTBIGICONPOPUP + wxRect r; + wxWindowDC dc(this); + r = m_ProjectSelectionCtrl->GetRect(); + dc.DrawBitmap(bmArray[sel], r.x + 9, r.y, false); +#endif + +} +#endif + + +void CSimpleProjectPanel::OnProjectSelection(wxCommandEvent& /*event*/) { + UpdateInterface(); + +// const int sel = m_ProjectSelectionCtrl->GetSelection(); +#if 0 //TESTBIGICONPOPUP + wxRect r; + wxWindowDC dc(this); + + r = m_ProjectSelectionCtrl->GetRect(); + dc.DrawBitmap(bmArray[sel], r.x + 9, r.y - 10, false); +#endif +} + + +void CSimpleProjectPanel::UpdateProjectList() { + CMainDocument* pDoc = wxGetApp().GetDocument(); + ProjectSelectionData* selData; + PROJECT* project; + char* ctrl_url; + int i, j; + + if ( pDoc->IsConnected() ) { + int projCnt = pDoc->GetSimpleProjectCount(); + int ctrlCount = m_ProjectSelectionCtrl->GetCount(); + + // If a new project has been added, figure out which one and then add it; + while ( projCnt > ctrlCount ) { + for(i=0; istate.projects[i]; + bool found = false; + for(j=0; jGetClientData(j))->project_url; + if (!strcmp(project->master_url, ctrl_url)) { + found = true; + break; + } + } + if ( !found ) { + selData = new ProjectSelectionData; + strncpy(selData->project_url, project->master_url, sizeof(selData->project_url)); + wxBitmap* projectBM = GetProjectSpecificBitmap(selData->project_url); + wxString projname(project->project_name.c_str(), wxConvUTF8); + m_ProjectSelectionCtrl->Append(projname, *projectBM, (void*)selData); + ctrlCount = m_ProjectSelectionCtrl->GetCount(); + } + } + } + + if ( projCnt < ctrlCount ) { + project = NULL; + // Check items in descending order so deletion won't change indexes of items yet to be checked + for(j=ctrlCount-1; j>=0; --j) { + char* ctrl_url = ((ProjectSelectionData*)m_ProjectSelectionCtrl->GetClientData(j))->project_url; + project = pDoc->state.lookup_project(ctrl_url); + if ( project == NULL ) { + selData = (ProjectSelectionData*)m_ProjectSelectionCtrl->GetClientData(j); + delete selData; + m_ProjectSelectionCtrl->Delete(j); + } + } + + } + + // Check to see if we need to reload the project icon + ctrlCount = m_ProjectSelectionCtrl->GetCount(); + for(j=0; jGetClientData(j))->project_url; + project = pDoc->state.lookup_project(ctrl_url); + if ( project->project_files_downloaded_time > m_Project_files_downloaded_time ) { + wxBitmap* projectBM = GetProjectSpecificBitmap(ctrl_url); + m_Project_files_downloaded_time = project->project_files_downloaded_time; + m_ProjectSelectionCtrl->SetItemBitmap(j, *projectBM); + } + } + } +} + + +std::string CSimpleProjectPanel::GetProjectIconLoc(char* project_url) { + char urlDirectory[256]; + CMainDocument* pDoc = wxGetApp().GetDocument(); + PROJECT* project = pDoc->state.lookup_project(project_url); + url_to_project_dir(project->master_url, urlDirectory); + return (std::string)urlDirectory + "/stat_icon"; +} + + +wxBitmap* CSimpleProjectPanel::GetProjectSpecificBitmap(char* project_url) { + char defaultIcnPath[256]; + CSkinSimple* pSkinSimple = wxGetApp().GetSkinManager()->GetSimple(); + + wxASSERT(pSkinSimple); + + // Only update if it is project specific is found + if(boinc_resolve_filename(GetProjectIconLoc(project_url).c_str(), defaultIcnPath, sizeof(defaultIcnPath)) == 0) { + wxBitmap* projectBM = new wxBitmap(); + if ( projectBM->LoadFile(wxString(defaultIcnPath,wxConvUTF8), wxBITMAP_TYPE_ANY) ) { + return projectBM; + } + } + return pSkinSimple->GetProjectImage()->GetBitmap(); +} + + diff --git a/clientgui/sg_ProjectPanel.h b/clientgui/sg_ProjectPanel.h new file mode 100755 index 0000000000..2adb0cdf99 --- /dev/null +++ b/clientgui/sg_ProjectPanel.h @@ -0,0 +1,87 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#ifndef __sg_ProjectPanel__ +#define __sg_ProjectPanel__ + +#include "sg_CustomControls.h" +#include "sg_PanelBase.h" +#include "sg_ProjectWebSitesPopup.h" +#include "sg_ProjectCommandPopup.h" + +typedef struct { + char project_url[256]; +} ProjectSelectionData; + + + +/////////////////////////////////////////////////////////////////////////////// +/// Class CSimpleProjectPanel +/////////////////////////////////////////////////////////////////////////////// + +#if 0 +#ifdef __WXMAC__ +#include "MacBitmapComboBox.h" +#else +#define CBOINCBitmapComboBox wxBitmapComboBox +#define EVT_BOINCBITMAPCOMBOBOX EVT_COMBOBOX +#endif +#endif + +class CSimpleProjectPanel : public CSimplePanelBase +{ + DECLARE_DYNAMIC_CLASS( CSimpleProjectPanel ) + DECLARE_EVENT_TABLE() + + public: + CSimpleProjectPanel(); + CSimpleProjectPanel( wxWindow* parent); + ~CSimpleProjectPanel(); + + ProjectSelectionData* GetProjectSelectionData(); + void UpdateInterface(); + + private: + void OnProjectSelection(wxCommandEvent &event); + void OnProjectCommandButton(wxCommandEvent& /*event*/); + void OnAddProject(wxCommandEvent& /*event*/); + void OnWizardAttach(); + void OnWizardUpdate(); + void OnProjectWebSiteButton(wxCommandEvent& /*event*/); + void UpdateProjectList(); + std::string CSimpleProjectPanel::GetProjectIconLoc(char* project_url); + wxBitmap* CSimpleProjectPanel::GetProjectSpecificBitmap(char* project_url); + + protected: + CTransparentStaticText* m_myProjectsLabel; + CBOINCBitmapComboBox* m_ProjectSelectionCtrl; + wxButton* m_TaskAddProjectButton; + CTransparentStaticText* m_TotalCreditValue; + CSimpleProjectWebSitesPopupButton* m_ProjectWebSitesButton; + CSimpleProjectCommandPopupButton* m_ProjectCommandsButton; + wxString m_sAddProjectString; + wxString m_sSynchronizeString; + wxString m_sTotalWorkDoneString; + int m_UsingAccountManager; + char m_CurrentSelectedProjectURL[256]; + double m_Project_files_downloaded_time; + double m_Project_last_rpc_time; + wxString m_sAddProjectToolTip; + wxString m_sSynchronizeToolTip; +}; + +#endif //__sg_ProjectPanel__ diff --git a/clientgui/sg_ProjectWebSitesPopup.cpp b/clientgui/sg_ProjectWebSitesPopup.cpp new file mode 100644 index 0000000000..8474b80d05 --- /dev/null +++ b/clientgui/sg_ProjectWebSitesPopup.cpp @@ -0,0 +1,115 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#include "stdwx.h" +#include "Events.h" +#include "BOINCGUIApp.h" +#include "MainDocument.h" +#include "sg_ProjectPanel.h" +#include "sg_ProjectWebSitesPopup.h" + + +IMPLEMENT_DYNAMIC_CLASS(CSimpleProjectWebSitesPopupButton, wxButton) + +BEGIN_EVENT_TABLE(CSimpleProjectWebSitesPopupButton, wxButton) + EVT_LEFT_DOWN(CSimpleProjectWebSitesPopupButton::OnProjectWebSiteButton) + EVT_MENU(WEBSITE_URL_MENU_ID,CSimpleProjectWebSitesPopupButton::OnMenuLinkClicked) + EVT_MENU(WEBSITE_URL_MENU_ID_REMOVE_PROJECT,CSimpleProjectWebSitesPopupButton::OnMenuLinkClicked) +END_EVENT_TABLE() + +CSimpleProjectWebSitesPopupButton::CSimpleProjectWebSitesPopupButton() { +} + +CSimpleProjectWebSitesPopupButton::CSimpleProjectWebSitesPopupButton(wxWindow* parent, wxWindowID id, + const wxString& label, const wxPoint& pos, const wxSize& size, + long style, const wxValidator& validator, const wxString& name) : + wxButton(parent, id, label, pos, size, style, validator, name) + { + + m_ProjectWebSitesPopUpMenu = new wxMenu(); +} + + +CSimpleProjectWebSitesPopupButton::~CSimpleProjectWebSitesPopupButton() { + delete m_ProjectWebSitesPopUpMenu; +} + + +void CSimpleProjectWebSitesPopupButton::AddMenuItems() +{ + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + ProjectSelectionData* selData = ((CSimpleProjectPanel*)GetParent())->GetProjectSelectionData(); + if (selData == NULL) return; + char* ctrl_url = selData->project_url; + PROJECT* project = pDoc->state.lookup_project(ctrl_url); + if (!project) return; + + size_t urlCount = project->gui_urls.size(); + + // Add the home page link + wxMenuItem *urlItem = new wxMenuItem(m_ProjectWebSitesPopUpMenu, WEBSITE_URL_MENU_ID_HOMEPAGE,wxString(project->project_name.c_str(), wxConvUTF8)); + Connect( WEBSITE_URL_MENU_ID_HOMEPAGE, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CSimpleProjectWebSitesPopupButton::OnMenuLinkClicked) ); + m_ProjectWebSitesPopUpMenu->Append(urlItem); + + + // Add any GUI urls + for(unsigned int i = 0; i < urlCount; i++){ + urlItem = new wxMenuItem(m_ProjectWebSitesPopUpMenu, WEBSITE_URL_MENU_ID + i, wxGetTranslation(wxString(project->gui_urls[i].name.c_str(), wxConvUTF8))); + Connect( WEBSITE_URL_MENU_ID + i, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(CSimpleProjectWebSitesPopupButton::OnMenuLinkClicked) ); + + m_ProjectWebSitesPopUpMenu->Append(urlItem); + } +} + + +void CSimpleProjectWebSitesPopupButton::RebuildMenu() { + for(int i=(int) m_ProjectWebSitesPopUpMenu->GetMenuItemCount()-1; i>=0; --i){ + wxMenuItem* item = m_ProjectWebSitesPopUpMenu->FindItemByPosition(i); + m_ProjectWebSitesPopUpMenu->Delete(item); + } + AddMenuItems(); +} + + + +void CSimpleProjectWebSitesPopupButton::OnProjectWebSiteButton(wxMouseEvent& WXUNUSED(event)) { + PopupMenu(m_ProjectWebSitesPopUpMenu); +} + + +void CSimpleProjectWebSitesPopupButton::OnMenuLinkClicked(wxCommandEvent& event) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + int menuIDevt = event.GetId(); + + ProjectSelectionData* selData = ((CSimpleProjectPanel*)GetParent())->GetProjectSelectionData(); + if (selData == NULL) return; + char* ctrl_url = selData->project_url; + + if (menuIDevt == WEBSITE_URL_MENU_ID_HOMEPAGE ) { + wxLaunchDefaultBrowser(wxString(ctrl_url, wxConvUTF8)); + } else{ + int menuId = menuIDevt - WEBSITE_URL_MENU_ID; + PROJECT* project = pDoc->state.lookup_project(ctrl_url); + project->gui_urls[menuId].name.c_str(); + + wxLaunchDefaultBrowser(wxString(project->gui_urls[menuId].url.c_str(),wxConvUTF8)); + } +} diff --git a/clientgui/sg_ProjectWebSitesPopup.h b/clientgui/sg_ProjectWebSitesPopup.h new file mode 100644 index 0000000000..5e89d3c369 --- /dev/null +++ b/clientgui/sg_ProjectWebSitesPopup.h @@ -0,0 +1,51 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#ifndef __sg_ProjectWebsitesPopup__ +#define __sg_ProjectWebsitesPopup__ + + +class CSimpleProjectWebSitesPopupButton : public wxButton +{ + DECLARE_DYNAMIC_CLASS( CSimpleProjectWebSitesPopupButton ) + DECLARE_EVENT_TABLE() + + public: + CSimpleProjectWebSitesPopupButton(); + + CSimpleProjectWebSitesPopupButton(wxWindow* parent, wxWindowID id, + const wxString& label = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxT("ProjectWebsitesPopupMenu")); + + ~CSimpleProjectWebSitesPopupButton(); + + void RebuildMenu(); + + private: + void AddMenuItems(); + void OnProjectWebSiteButton(wxMouseEvent& event); + void OnMenuLinkClicked(wxCommandEvent& event); + + protected: + wxMenu* m_ProjectWebSitesPopUpMenu; +}; + +#endif // __sg_ProjectWebsitesPopup__ diff --git a/clientgui/sg_TaskCommandPopup.cpp b/clientgui/sg_TaskCommandPopup.cpp new file mode 100644 index 0000000000..e2f89cea70 --- /dev/null +++ b/clientgui/sg_TaskCommandPopup.cpp @@ -0,0 +1,269 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + + +#include "stdwx.h" +#include "Events.h" +#include "BOINCGUIApp.h" +#include "MainDocument.h" +#include "DlgItemProperties.h" +#include "sg_TaskPanel.h" +#include "sg_TaskCommandPopup.h" + +IMPLEMENT_DYNAMIC_CLASS(CSimpleTaskPopupButton, wxButton) + +BEGIN_EVENT_TABLE(CSimpleTaskPopupButton, wxButton) + EVT_LEFT_DOWN(CSimpleTaskPopupButton::OnTasksCommandButton) + EVT_MENU(ID_TASK_WORK_SHOWGRAPHICS, CSimpleTaskPopupButton::OnTaskShowGraphics) + EVT_MENU(ID_TASK_WORK_SUSPEND, CSimpleTaskPopupButton::OnTaskSuspendResume) + EVT_MENU(ID_TASK_WORK_ABORT, CSimpleTaskPopupButton::OnTaskAbort) + EVT_MENU(ID_TASK_SHOW_PROPERTIES, CSimpleTaskPopupButton::OnTaskShowProperties) +END_EVENT_TABLE() + +CSimpleTaskPopupButton::CSimpleTaskPopupButton() { +} + +CSimpleTaskPopupButton::CSimpleTaskPopupButton(wxWindow* parent, wxWindowID id, + const wxString& label, const wxPoint& pos, const wxSize& size, + long style, const wxValidator& validator, const wxString& name) : + wxButton(parent, id, label, pos, size, style, validator, name) + { + + m_TaskSuspendedViaGUI = false; + m_TaskCommandPopUpMenu = new wxMenu(); + AddMenuItems(); +} + + +CSimpleTaskPopupButton::~CSimpleTaskPopupButton() { + delete m_TaskCommandPopUpMenu; +} + + +void CSimpleTaskPopupButton::AddMenuItems() { + m_ShowGraphicsMenuItem = m_TaskCommandPopUpMenu->Append( + ID_TASK_WORK_SHOWGRAPHICS, + _("Show graphics"), + _("Show application graphics in a window.") + ); + + m_SuspendResumeMenuItem = m_TaskCommandPopUpMenu->Append( + ID_TASK_WORK_SUSPEND, + _("Suspend"), + _("Suspend work for this result.") + ); + + m_AbortMenuItem = m_TaskCommandPopUpMenu->Append( + ID_TASK_WORK_ABORT, + _("Abort"), + _("Abandon work on the result. You will get no credit for it.") + ); + + m_ShowPropertiesMenuItem = m_TaskCommandPopUpMenu->Append( + ID_TASK_SHOW_PROPERTIES, + _("Properties"), + _("Show task details.") + ); +} + + +void CSimpleTaskPopupButton::OnTasksCommandButton(wxMouseEvent& /*event*/) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + bool enableShowGraphics = true; + bool enableAbort = true; + + wxASSERT(pDoc); + + TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData(); + if (selData == NULL) return; + + RESULT* result = pDoc->state.lookup_result(selData->project_url, selData->result_name); + if (!result) return; + + if (result->suspended_via_gui) { + m_TaskSuspendedViaGUI = true; + m_SuspendResumeMenuItem->SetItemLabel(_("Resume")); + m_SuspendResumeMenuItem->SetHelp(_("Resume work for this task.")); + } else { + m_TaskSuspendedViaGUI = false; + m_SuspendResumeMenuItem->SetItemLabel(_("Suspend")); + m_SuspendResumeMenuItem->SetHelp(_("Suspend work for this task.")); + } + + // Disable Show Graphics button if any selected task can't display graphics + if (((!result->supports_graphics) || pDoc->GetState()->executing_as_daemon) + && !strlen(result->graphics_exec_path) + ) { + enableShowGraphics = false; + } + + if (result->suspended_via_gui || + result->project_suspended_via_gui || + (result->scheduler_state != CPU_SCHED_SCHEDULED) + ) { + enableShowGraphics = false; + } + + m_ShowGraphicsMenuItem->Enable(enableShowGraphics); + + // Disable Abort button if any selected task already aborted + if ( + result->active_task_state == PROCESS_ABORT_PENDING || + result->active_task_state == PROCESS_ABORTED || + result->state == RESULT_ABORTED + ) { + enableAbort = false; + } + + m_AbortMenuItem->Enable(enableAbort); + + PopupMenu(m_TaskCommandPopUpMenu); + + +#if TESTBIGICONPOPUP +/*** CAF *** FOR TESTING ONLY ***/ + static int i; + wxString s; + + if (i > 9) i = 0; + if ( i < 5) { + s = (wxT("This is a very very very and extremely long label.")); + } else { + s = (wxT("short.")); + } + + switch (i++) { + case 0: + case 5: + UpdateStaticText(&m_TaskProjectName, s); + break; + case 1: + case 6: + UpdateStaticText(&m_TaskApplicationName, s); + break; + case 2: + case 7: + UpdateStaticText(&m_ElapsedTimeValue, s); + break; + case 3: + case 8: + UpdateStaticText(&m_TimeRemainingValue, s); + break; + case 4: + case 9: + UpdateStaticText(&m_StatusValueText, s); + break; + } + + m_ProgressBar->SetValue( i * 10 ); + int sel = i % 3; +// m_TaskSelectionCtrl->SetStringSelection(tempArray[sel]); + m_TaskSelectionCtrl->SetSelection(sel); +#endif +} + + +void CSimpleTaskPopupButton::OnTaskShowGraphics(wxCommandEvent& WXUNUSED(event)) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData(); + if (selData == NULL) return; + + RESULT* result = pDoc->state.lookup_result(selData->project_url, selData->result_name); + if (result) { + pDoc->WorkShowGraphics(result); + } +} + + +void CSimpleTaskPopupButton::OnTaskSuspendResume(wxCommandEvent& WXUNUSED(event)) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData(); + if (selData == NULL) return; + + if (m_TaskSuspendedViaGUI) { + pDoc->WorkResume(selData->project_url, selData->result_name); + } else { + pDoc->WorkSuspend(selData->project_url, selData->result_name); + } +} + + +void CSimpleTaskPopupButton::OnTaskAbort(wxCommandEvent& WXUNUSED(event)) { + wxInt32 iAnswer = 0; + wxString strMessage = wxEmptyString; + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + if (!pDoc->IsUserAuthorized()) // Probably no longer relevant + return; + + TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData(); + if (selData == NULL) return; + + RESULT* result = pDoc->state.lookup_result(selData->project_url, selData->result_name); + if (result) { +#if SELECTBYRESULTNAME + wxString name = wxString(selData->result_name, wxConvUTF8, strlen(selData->result_name)); +#else + wxString name = ((CSimpleTaskPanel*)GetParent())->GetSelectedTaskString(); +#endif + strMessage.Printf( + _("Are you sure you want to abort this task '%s'?\n(Progress: %.1lf%%, Status: %s)"), + name.c_str(), result->fraction_done * 100.0, result_description(result, false).c_str()); + + iAnswer = wxGetApp().SafeMessageBox( + strMessage, + _("Abort task"), + wxYES_NO | wxICON_QUESTION, + this + ); + + if (wxYES != iAnswer) { + return; + } + + pDoc->WorkAbort(result->project_url, result->name); + } +} + + +void CSimpleTaskPopupButton::OnTaskShowProperties(wxCommandEvent& WXUNUSED(event)) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData(); + if (selData == NULL) return; + + RESULT* result = pDoc->state.lookup_result(selData->project_url, selData->result_name); + if (result) { + CDlgItemProperties dlg(this); + dlg.renderInfos(result); + dlg.ShowModal(); + } +} diff --git a/clientgui/sg_TaskCommandPopup.h b/clientgui/sg_TaskCommandPopup.h new file mode 100644 index 0000000000..0f8fb54238 --- /dev/null +++ b/clientgui/sg_TaskCommandPopup.h @@ -0,0 +1,57 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + + +#ifndef __sg_TaskCommandPopup__ +#define __sg_TaskCommandPopup__ + +class CSimpleTaskPopupButton : public wxButton +{ + DECLARE_DYNAMIC_CLASS( CSimpleTaskPopupButton ) + DECLARE_EVENT_TABLE() + + public: + CSimpleTaskPopupButton(); + + CSimpleTaskPopupButton(wxWindow* parent, wxWindowID id, + const wxString& label = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxT("TaskCommandsPopupMenu")); + + ~CSimpleTaskPopupButton(); + + private: + void AddMenuItems(); + void OnTasksCommandButton(wxMouseEvent& event); + void OnTaskShowGraphics(wxCommandEvent& event); + void OnTaskSuspendResume(wxCommandEvent& event); + void OnTaskAbort(wxCommandEvent& event); + void OnTaskShowProperties(wxCommandEvent& event); + + protected: + wxMenu* m_TaskCommandPopUpMenu; + wxMenuItem* m_ShowGraphicsMenuItem; + wxMenuItem* m_SuspendResumeMenuItem; + wxMenuItem* m_AbortMenuItem; + wxMenuItem* m_ShowPropertiesMenuItem; + bool m_TaskSuspendedViaGUI; +}; + +#endif // __sg_TaskCommandPopup__ diff --git a/clientgui/sg_TaskPanel.cpp b/clientgui/sg_TaskPanel.cpp new file mode 100755 index 0000000000..b556689337 --- /dev/null +++ b/clientgui/sg_TaskPanel.cpp @@ -0,0 +1,933 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#define TESTBIGICONPOPUP 0 + +#include "stdwx.h" +#include "miofile.h" +#include "Events.h" +#include "BOINCGUIApp.h" +#include "SkinManager.h" +#include "MainDocument.h" +#include "sg_TaskCommandPopup.h" +#include "sg_TaskPanel.h" +#include "boinc_api.h" +#include "filesys.h" +#include "res/GreenDot16.xpm" +#include "res/YellowDot16.xpm" +#include "res/RedDot16.xpm" + + +enum { redDot, yellowDot, greenDot }; + + +IMPLEMENT_DYNAMIC_CLASS(CSlideShowPanel, wxPanel) + +BEGIN_EVENT_TABLE(CSlideShowPanel, wxPanel) +// EVT_ERASE_BACKGROUND(CSlideShowPanel::OnEraseBackground) + EVT_TIMER(ID_CHANGE_SLIDE_TIMER, CSlideShowPanel::OnSlideShowTimer) + EVT_PAINT(CSlideShowPanel::OnPaint) +END_EVENT_TABLE() + +#define SLIDESHOWBORDER 3 + +CSlideShowPanel::CSlideShowPanel() { +} + + +CSlideShowPanel::CSlideShowPanel( wxWindow* parent ) : + wxPanel( parent, wxID_ANY, wxDefaultPosition, wxSize(290+(2*SLIDESHOWBORDER), 126+(2*SLIDESHOWBORDER)), wxSTATIC_BORDER ) +{ + SetBackgroundColour(*wxBLACK); + + m_ChangeSlideTimer = new wxTimer(this, ID_CHANGE_SLIDE_TIMER); + m_ChangeSlideTimer->Start(10000); + + m_SlideBitmap = wxNullBitmap; + m_bCurrentSlideIsDefault = false; + +#ifdef __WXMAC__ + // Tell accessibility aids to ignore this panel (but not its contents) + HIObjectSetAccessibilityIgnored((HIObjectRef)GetHandle(), true); +#endif +} + +CSlideShowPanel::~CSlideShowPanel() +{ + if ( m_ChangeSlideTimer->IsRunning() ) { + m_ChangeSlideTimer->Stop(); + } + delete m_ChangeSlideTimer; +} + + +void CSlideShowPanel::OnSlideShowTimer(wxTimerEvent& WXUNUSED(event)) { + AdvanceSlideShow(true); +} + + +void CSlideShowPanel::AdvanceSlideShow(bool changeSlide) { + char fileName[1024], resolvedFileName[1024]; + double xRatio, yRatio, ratio; + TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData(); + if (selData == NULL) return; + + if ((selData->numSlides <= 0) && m_bCurrentSlideIsDefault) return; + + if (selData->numSlides <= 0) { + CSkinSimple* pSkinSimple = wxGetApp().GetSkinManager()->GetSimple(); + wxASSERT(pSkinSimple); + wxASSERT(wxDynamicCast(pSkinSimple, CSkinSimple)); + + m_SlideBitmap = *pSkinSimple->GetWorkunitAnimationImage()->GetBitmap(); + if (m_SlideBitmap.Ok()) { + m_bCurrentSlideIsDefault = true; + } + } else { + // TODO: Should we allow slide show to advance if task is not running? + if (selData->dotColor == greenDot) { // Advance only if running + if (changeSlide) { + if (++(selData->lastSlideShown) >= selData->numSlides) { + selData->lastSlideShown = 0; + } + } + } + if (selData->lastSlideShown < 0) { + selData->lastSlideShown = 0; + } + + sprintf(fileName, "%s%02d", selData->slide_show_filename_prefix, selData->lastSlideShown); + if (boinc_resolve_filename(fileName, resolvedFileName, sizeof(resolvedFileName)) == 0) { + wxBitmap *bm = new wxBitmap(); + bm->LoadFile(wxString(resolvedFileName,wxConvUTF8), wxBITMAP_TYPE_ANY); + m_SlideBitmap = *bm; + delete bm; + } + if (m_SlideBitmap.Ok()) { + m_bCurrentSlideIsDefault = false; + } + } + if (m_SlideBitmap.Ok()) { + // Check to see if they need to be rescaled to fit in the window + ratio = 1.0; + xRatio = ((double) GetSize().GetWidth() - (2*SLIDESHOWBORDER))/((double) m_SlideBitmap.GetWidth()); + yRatio = ((double) GetSize().GetHeight() - (2*SLIDESHOWBORDER))/((double) m_SlideBitmap.GetHeight()); + if ( xRatio < ratio ) { + ratio = xRatio; + } + if ( yRatio < ratio ) { + ratio = yRatio; + } + if ( ratio < 1.0 ) { + wxImage img = m_SlideBitmap.ConvertToImage(); + img.Rescale((int) (m_SlideBitmap.GetWidth()*ratio), (int) (m_SlideBitmap.GetHeight()*ratio)); + wxBitmap *bm = new wxBitmap(img); + m_SlideBitmap = *bm; + delete bm; + } + Refresh(); + } +} + + +void CSlideShowPanel::OnPaint(wxPaintEvent& WXUNUSED(event)) +{ + wxPaintDC dc(this); + int w, h; + wxPen oldPen = dc.GetPen(); + wxBrush oldBrush = dc.GetBrush(); + int oldMode = dc.GetBackgroundMode(); + wxPen bgPen(*wxBLUE, 3); + dc.SetBackgroundMode(wxSOLID); + dc.SetPen(bgPen); + dc.SetBrush(*wxBLACK_BRUSH); + + GetSize(&w, &h); + dc.DrawRectangle(0, 0, w, h); + // Restore Mode, Pen and Brush + dc.SetBackgroundMode(oldMode); + dc.SetPen(oldPen); + dc.SetBrush(oldBrush); + + if(m_SlideBitmap.Ok()) + { + dc.DrawBitmap(m_SlideBitmap, + (w - m_SlideBitmap.GetWidth())/2, + (h - m_SlideBitmap.GetHeight())/2 + ); + } +} + + + + + +IMPLEMENT_DYNAMIC_CLASS(CSimpleTaskPanel, CSimplePanelBase) + +BEGIN_EVENT_TABLE(CSimpleTaskPanel, CSimplePanelBase) + EVT_BOINCBITMAPCOMBOBOX(ID_SGTASKSELECTOR, CSimpleTaskPanel::OnTaskSelection) +// EVT_BUTTON(ID_TASKSCOMMANDBUTTON, CSimpleTaskPanel::OnTasksCommand) +// EVT_LEFT_DOWN(CSimpleTaskPanel::OnTasksCommand) + EVT_TIMER(ID_SIMPLE_PROGRESSPULSETIMER, CSimpleTaskPanel::OnPulseProgressIndicator) +END_EVENT_TABLE() + +#if TESTBIGICONPOPUP +static wxString tempArray[] = {_T("String1"), _T("String2"), _T("String3") }; +#endif + +CSimpleTaskPanel::CSimpleTaskPanel() { +} + +CSimpleTaskPanel::CSimpleTaskPanel( wxWindow* parent ) : + CSimplePanelBase( parent ) +{ + wxSize sz; + int w, h; + wxString str = wxEmptyString; + + m_pulseTimer = new wxTimer(this, ID_SIMPLE_PROGRESSPULSETIMER); + m_oldWorkCount = -1; + error_time = 0; + m_GreenDot = wxBitmap((const char**)GreenDot16_xpm); + m_YellowDot = wxBitmap((const char**)YellowDot16_xpm); + m_RedDot = wxBitmap((const char**)RedDot16_xpm); + m_GotBGBitMap = false; // Can't be made until parent has been laid out. + m_bStableTaskInfoChanged = false; + m_CurrentTaskSelection = -1; + m_sNoProjectsString = _("You don't have any projects. Please Add a Project."); + m_sNotAvailableString = _("Not available"); + + SetFont(wxFont(SMALL_FONT,wxSWISS,wxNORMAL,wxNORMAL,false,wxT("Arial"))); + + wxBoxSizer* bSizer1; + bSizer1 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer2; + bSizer2 = new wxBoxSizer( wxHORIZONTAL ); + + m_myTasksLabel = new CTransparentStaticText( this, wxID_ANY, _("My Tasks:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_myTasksLabel->Wrap( -1 ); +// m_myTasksLabel->SetFont(wxFont(MEDIUM_FONT,wxSWISS,wxNORMAL,wxBOLD,false,wxT("Arial"))); + m_myTasksLabel->Enable( false ); + bSizer2->Add( m_myTasksLabel, 0, wxRIGHT, 5 ); + +#if TESTBIGICONPOPUP + m_TaskSelectionCtrl = new CBOINCBitmapComboBox( this, ID_SGTASKSELECTOR, wxT(""), wxDefaultPosition, wxDefaultSize, 3, tempArray, wxCB_READONLY ); + m_TaskSelectionCtrl->SetItemBitmap(0, m_RedDot); + m_TaskSelectionCtrl->SetItemBitmap(1, m_GreenDot); + m_TaskSelectionCtrl->SetItemBitmap(2, m_YellowDot); +// m_TaskSelectionCtrl->SetStringSelection(tempArray[1]); + m_TaskSelectionCtrl->SetSelection(1); +#else + m_TaskSelectionCtrl = new CBOINCBitmapComboBox( this, ID_SGTASKSELECTOR, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY ); +#endif + // TODO: Might want better wording for Task Selection Combo Box tooltip + str = _("Select a task to access"); + m_TaskSelectionCtrl->SetToolTip(str); + bSizer2->Add( m_TaskSelectionCtrl, 1, wxRIGHT | wxEXPAND, SIDEMARGINS ); + + bSizer1->Add( bSizer2, 0, wxEXPAND | wxTOP | wxLEFT, 10 ); + + bSizer1->AddSpacer(5); + + wxBoxSizer* bSizer3; + bSizer3 = new wxBoxSizer( wxHORIZONTAL ); + + m_TaskProjectLabel = new CTransparentStaticText( this, wxID_ANY, _("From Project:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_TaskProjectLabel->Wrap( -1 ); + m_TaskProjectLabel->Enable( false ); + bSizer3->Add( m_TaskProjectLabel, 0, wxRIGHT, 5 ); + + m_TaskProjectName = new CTransparentStaticText( this, wxID_ANY, wxT("SETI@home"), wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE ); + m_TaskProjectName->Wrap( -1 ); + m_TaskProjectName->SetFont(wxFont(LARGE_FONT,wxSWISS,wxNORMAL,wxNORMAL,false,wxT("Arial"))); + m_TaskProjectName->Enable( false ); + bSizer3->Add( m_TaskProjectName, 1, 0, 0 ); + + bSizer1->Add( bSizer3, 0, wxLEFT | wxRIGHT | wxEXPAND, SIDEMARGINS ); + +#if SELECTBYRESULTNAME + m_TaskApplicationName = new CTransparentStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE ); + m_TaskApplicationName->Wrap( -1 ); + m_TaskApplicationName->Enable( false ); + + bSizer1->Add( m_TaskApplicationName, 0, wxLEFT | wxRIGHT | wxEXPAND, SIDEMARGINS ); +#endif + + bSizer1->AddSpacer(10); + + m_SlideShowArea = new CSlideShowPanel(this); + m_SlideShowArea->SetMinSize(wxSize(290+(2*SLIDESHOWBORDER), 126+(2*SLIDESHOWBORDER))); + m_SlideShowArea->Enable( false ); + + bSizer1->Add( m_SlideShowArea, 0, wxLEFT | wxRIGHT | wxEXPAND, SIDEMARGINS ); + + bSizer1->AddSpacer(10); + + m_ElapsedTimeValue = new CTransparentStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE ); + m_ElapsedTimeValue->Wrap( -1 ); + m_ElapsedTimeValue->Enable( false ); + bSizer1->Add( m_ElapsedTimeValue, 0, wxLEFT | wxRIGHT | wxEXPAND, SIDEMARGINS ); + + bSizer1->AddSpacer(7); + + m_TimeRemainingValue = new CTransparentStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE ); + m_TimeRemainingValue->Wrap( -1 ); + m_TimeRemainingValue->Enable( false ); + bSizer1->Add( m_TimeRemainingValue, 0, wxLEFT | wxRIGHT | wxEXPAND, SIDEMARGINS ); + + bSizer1->AddSpacer(7); + + wxBoxSizer* bSizer4; + bSizer4 = new wxBoxSizer( wxHORIZONTAL ); + + // TODO: Standard Mac progress indicator's animation uses lots of CPU + // time, and also triggers unnecessary Erase events. Should we use a + // non-standard progress indicator on Mac? See also workarounds in + // CSimplePanelBase::OnEraseBackground(), CSimpleGUIPanel::OnEraseBackground(). + m_ProgressBar = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL ); + m_ProgressBar->SetValue( 50 ); + GetTextExtent(wxT("0"), &w, &h); + m_ProgressBar->SetMinSize(wxSize(245, h)); + m_ProgressBar->SetToolTip(_("This task's progress")); + bSizer4->Add( m_ProgressBar, 0, wxRIGHT, 5 ); + + m_ProgressValueText = new CTransparentStaticText( this, wxID_ANY, wxT("100.0%"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT | wxST_NO_AUTORESIZE ); + m_ProgressValueText->Wrap( -1 ); + m_ProgressValueText->Enable( false ); + bSizer4->Add( m_ProgressValueText, 0, wxALIGN_RIGHT, 0 ); + + bSizer1->Add( bSizer4, 0, wxLEFT | wxRIGHT | wxEXPAND, SIDEMARGINS ); + + bSizer1->AddSpacer(7); + + // TODO: Can we determine the longest status string and initialize with it? + m_StatusValueText = new CTransparentStaticText( this, wxID_ANY, m_sNoProjectsString, wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE ); +// m_StatusValueText = new CTransparentStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxST_NO_AUTORESIZE ); + m_StatusValueText->Wrap( -1 ); + m_StatusValueText->Enable( false ); + bSizer1->Add( m_StatusValueText, 0, wxLEFT | wxRIGHT | wxEXPAND, SIDEMARGINS ); + + bSizer1->AddSpacer(7); + + m_TaskCommandsButton = new CSimpleTaskPopupButton( this, ID_TASKSCOMMANDBUTTON, _("Task Commands"), wxDefaultPosition, wxDefaultSize, 0 ); + m_TaskCommandsButton->SetToolTip(_("Pop up a menu of commands to apply to this task")); + bSizer1->Add( m_TaskCommandsButton, 0, wxLEFT | wxRIGHT | wxEXPAND | wxALIGN_CENTER_HORIZONTAL, SIDEMARGINS ); + + bSizer1->AddSpacer(10); + + this->SetSizer( bSizer1 ); + this->Layout(); + + m_ProgressRect = m_ProgressBar->GetRect(); + m_ProgressRect.Inflate(1, 0); +} + + +CSimpleTaskPanel::~CSimpleTaskPanel() +{ + TaskSelectionData *selData; + int count = m_TaskSelectionCtrl->GetCount(); + for(int j = count-1; j >=0; --j) { + selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(j); + delete selData; + m_TaskSelectionCtrl->SetClientData(j, NULL); + } + m_TaskSelectionCtrl->Clear(); + + m_pulseTimer->Stop(); + delete m_pulseTimer; +} + + +void CSimpleTaskPanel::OnTaskSelection(wxCommandEvent& /*event*/) +{ + int sel = m_TaskSelectionCtrl->GetSelection(); + if (sel != m_CurrentTaskSelection) { + m_CurrentTaskSelection = sel; + m_bStableTaskInfoChanged = true; + Update(); + } +} + + +void CSimpleTaskPanel::Update() { + wxString s = wxEmptyString; + wxString projName = wxEmptyString; + TaskSelectionData *selData; + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + + int workCount = pDoc->GetSimpleGUIWorkCount(); + +#ifndef __WXMAC__ + Freeze(); +#endif + + if (workCount <= 0) { + if (workCount != m_oldWorkCount) { + m_myTasksLabel->Hide(); + m_TaskSelectionCtrl->Hide(); + m_TaskProjectLabel->Hide(); + m_TaskProjectName->Hide(); +#if SELECTBYRESULTNAME + m_TaskApplicationName->Hide(); +#endif + m_SlideShowArea->Hide(); + m_ElapsedTimeValue->Hide(); + m_TimeRemainingValue->Hide(); + m_ProgressValueText->Hide(); + m_TaskCommandsButton->Hide(); + m_ProgressBar->Pulse(); + m_pulseTimer->Start(100); + } + + DisplayIdleState(); + + } else { + if (m_oldWorkCount == 0) { + m_myTasksLabel->Show(); + m_TaskSelectionCtrl->Show(); + m_TaskProjectLabel->Show(); + m_TaskProjectName->Show(); +#if SELECTBYRESULTNAME + m_TaskApplicationName->Show(); +#endif + m_SlideShowArea->Show(); + m_ElapsedTimeValue->Show(); + m_TimeRemainingValue->Show(); + m_ProgressValueText->Show(); + m_TaskCommandsButton->Show(); + } + + UpdateTaskSelectionList(); + + // We now have valid result pointers, so extract our data + int count = m_TaskSelectionCtrl->GetCount(); + if (count <= 0) { + m_CurrentTaskSelection = -1; + } else { + if ((m_CurrentTaskSelection < 0) || (m_CurrentTaskSelection > count -1)) { + m_TaskSelectionCtrl->SetSelection(0); + m_CurrentTaskSelection = 0; + m_bStableTaskInfoChanged = true; + } + selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(m_CurrentTaskSelection); + RESULT* result = selData->result; + if (result) { + if (m_bStableTaskInfoChanged) { +#if SELECTBYRESULTNAME + wxString str = wxEmptyString; + GetApplicationAndProjectNames(result, &s, &projName); + str.Printf(_("Application: %s"), s.c_str()); + UpdateStaticText(&m_TaskApplicationName, str); + UpdateStaticText(&m_TaskProjectName, projName); +#else + GetApplicationAndProjectNames(result, NULL, &projName); +#endif + UpdateStaticText(&m_TaskProjectName, projName); + m_SlideShowArea->AdvanceSlideShow(false); + m_bStableTaskInfoChanged = false; + } + float f = result->elapsed_time; + if (f == 0.) f = result->current_cpu_time; +// f = result->final_elapsed_time; + UpdateStaticText(&m_ElapsedTimeValue, GetElapsedTimeString(f)); + UpdateStaticText(&m_TimeRemainingValue, GetTimeRemainingString(result->estimated_cpu_time_remaining)); + float percNum = result->fraction_done * 100.0; + m_ProgressBar->SetValue(percNum); + m_pulseTimer->Stop(); + s.Printf(_("%.1lf%%"), percNum); + UpdateStaticText(&m_ProgressValueText, s); + UpdateStaticText(&m_StatusValueText, GetStatusString(result)); + } else { + UpdateStaticText(&m_TaskProjectName, m_sNotAvailableString); +#if SELECTBYRESULTNAME + UpdateStaticText(&m_TaskApplicationName, _("Application: Not available") ); +#endif + UpdateStaticText(&m_ElapsedTimeValue, GetElapsedTimeString(-1.0)); + UpdateStaticText(&m_TimeRemainingValue, GetTimeRemainingString(-1.0)); + m_ProgressBar->Pulse(); + m_pulseTimer->Start(100); + UpdateStaticText(&m_ProgressValueText, wxEmptyString); + UpdateStaticText(&m_StatusValueText, GetStatusString(NULL)); + } + } + } + m_oldWorkCount = workCount; + +#ifndef __WXMAC__ + Thaw(); +#endif +} + + +void CSimpleTaskPanel::ReskinInterface() { + CSimplePanelBase::ReskinInterface(); + m_SlideShowArea->AdvanceSlideShow(false); +} + + +void CSimpleTaskPanel::OnPulseProgressIndicator(wxTimerEvent& /*event*/) { + m_ProgressBar->Pulse(); +} + + +TaskSelectionData* CSimpleTaskPanel::GetTaskSelectionData() { + int count = m_TaskSelectionCtrl->GetCount(); + if (count <= 0) { + return NULL; + } + + int n = m_TaskSelectionCtrl->GetSelection(); + return (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(n); +} + + +// Either appName argument or projName argument may be NULL +void CSimpleTaskPanel::GetApplicationAndProjectNames(RESULT* result, wxString* appName, wxString* projName) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + RESULT* state_result = NULL; + wxString strAppBuffer = wxEmptyString; + wxString strClassBuffer = wxEmptyString; + + wxASSERT(pDoc); + wxASSERT(wxDynamicCast(pDoc, CMainDocument)); + + state_result = pDoc->state.lookup_result(result->project_url, result->name); + if (!state_result) { + pDoc->ForceCacheUpdate(); + state_result = pDoc->state.lookup_result(result->project_url, result->name); + } + + if (!state_result) return; + + if (appName != NULL) { + WORKUNIT* wup = state_result->wup; + if (!wup) return; + APP* app = wup->app; + if (!app) return; + APP_VERSION* avp = state_result->avp; + if (!avp) return; + + if (strlen(app->user_friendly_name)) { + strAppBuffer = wxString(state_result->app->user_friendly_name, wxConvUTF8); + } else { + strAppBuffer = wxString(state_result->avp->app_name, wxConvUTF8); + } + + if (strlen(avp->plan_class)) { + strClassBuffer.Printf( + wxT(" (%s)"), + wxString(avp->plan_class, wxConvUTF8).c_str() + ); + } + +#if SELECTBYRESULTNAME + appName->Printf( + wxT("%d: %s%s %d.%02d %s"), + state_result->slot, + state_result->project->anonymous_platform?_("Local: "):wxT(""), + strAppBuffer.c_str(), + state_result->avp->version_num / 100, + state_result->avp->version_num % 100, + strClassBuffer.c_str() + ); +#else + appName->Printf(wxT("%s%s %d.%02d %s (in slot %d)"), + state_result->project->anonymous_platform?_("Local: "):wxT(""), + strAppBuffer.c_str(), + state_result->avp->version_num / 100, + state_result->avp->version_num % 100, + strClassBuffer.c_str(), + state_result->slot + ); +#endif + } + + if (projName != NULL) { + *projName = wxString(state_result->project->project_name.c_str(), wxConvUTF8 ); + if (projName->IsEmpty()) { + *projName = _("Not Available"); + } + } +} + + +wxString CSimpleTaskPanel::GetElapsedTimeString(double f) { + wxString s = wxEmptyString; + wxString str = wxEmptyString; + + if (f < 0) { + s = m_sNotAvailableString; + } else { + s = FormatTime(f); + } + str.Printf(_("Elapsed Time: %s"), s.c_str()); + return str; +} + + +wxString CSimpleTaskPanel::GetTimeRemainingString(double f) { + wxString s = wxEmptyString; + wxString str = wxEmptyString; + + if (f < 0) { + s = m_sNotAvailableString; + } else { + s = FormatTime(f); + } + str.Printf(_("Time Remaining: %s"), s.c_str()); + return str; +} + + +wxString CSimpleTaskPanel::GetStatusString(RESULT* result) { + wxString s = wxEmptyString; + wxString str = wxEmptyString; + + if (result == NULL) { + s = m_sNotAvailableString; + } else { + s = result_description(result, false); + } + + str.Printf(_("Status: %s"), s.c_str()); + return str; +} + + +wxString CSimpleTaskPanel::FormatTime(float fBuffer) { + wxInt32 iHour = 0; + wxInt32 iMin = 0; + wxInt32 iSec = 0; + wxTimeSpan ts; + wxString strBuffer= wxEmptyString; + + if (0 >= fBuffer) { + strBuffer = wxT("---"); + } else { + iHour = (wxInt32)(fBuffer / (60 * 60)); + iMin = (wxInt32)(fBuffer / 60) % 60; + iSec = (wxInt32)(fBuffer) % 60; + + ts = wxTimeSpan(iHour, iMin, iSec); + + strBuffer = ts.Format(); + } + + return strBuffer; +} + + +void CSimpleTaskPanel::UpdateTaskSelectionList() { + int i, j, count, numSlides, newColor; + TaskSelectionData *selData; + RESULT* result; + RESULT* ctrlResult; + RESULT* state_result; + std::vectoris_alive; + char urlDirectory[1024]; + char fileName[1024]; + char resolvedFileName[1024]; + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + + count = m_TaskSelectionCtrl->GetCount(); + + // Mark all inactive (this lets us loop only once) + for (i=0; iresults.results.size(); i++) { + bool found = false; + result = pDoc->result(i); + // only check tasks that are active + if ( result == NULL || !result->active_task ) { + continue; + } + // loop through the items already in Task Selection Control to find this result + for(j = 0; j < count; ++j) { + selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(j); + if (!strcmp(result->name, selData->result_name) && + !strcmp(result->project_url, selData->project_url) + ) { + selData->result = result; + found = true; + is_alive.at(j) = true; + break; // skip out of this loop + } + } + + // if it isn't currently one of the tabs then we have a new one! lets add it + if ( !found ) { +#if SELECTBYRESULTNAME + wxString resname(result->name, wxConvUTF8); +#else + wxString resname = wxEmptyString; + GetApplicationAndProjectNames(result, &resname, NULL); +#endif + selData = new TaskSelectionData; + selData->result = result; + strncpy(selData->result_name, result->name, sizeof(selData->result_name)); + strncpy(selData->project_url, result->project_url, sizeof(selData->project_url)); + selData->dotColor = -1; + selData->slide_show_filename_prefix[0] = '\0'; + numSlides = 0; + state_result = pDoc->state.lookup_result(result->project_url, result->name); + if (!state_result) { + pDoc->ForceCacheUpdate(); + state_result = pDoc->state.lookup_result(result->project_url, result->name); + } + if (state_result) { + url_to_project_dir(state_result->project->master_url, urlDirectory); + for(j=0; j<99; ++j) { + sprintf(fileName, "%s/slideshow_%s_%02d", urlDirectory, state_result->app->name, j); + if(boinc_resolve_filename(fileName, resolvedFileName, sizeof(resolvedFileName)) == 0) { + if (boinc_file_exists(resolvedFileName)) { + numSlides = j+1; + } else { + break; + } + } + } + if (numSlides > 0) { + sprintf(selData->slide_show_filename_prefix, "%s/slideshow_%s_", urlDirectory, state_result->app->name); + } else { + for(j=0; j<99; ++j) { + sprintf(fileName, "%s/slideshow_%02d", urlDirectory, j); + if(boinc_resolve_filename(fileName, resolvedFileName, sizeof(resolvedFileName)) == 0) { + if (boinc_file_exists(resolvedFileName)) { + numSlides = j+1; + } else { + break; + } + } + } + if (numSlides > 0) { + sprintf(selData->slide_show_filename_prefix, "%s/slideshow_", urlDirectory); + } + } + } + selData->numSlides = numSlides; + selData->lastSlideShown = -1; + + m_TaskSelectionCtrl->Append(resname, wxNullBitmap, (void*)selData); + } + } + + // Check items in descending order so deletion won't change indexes of items yet to be checked + for(j = count-1; j >=0; --j) { + if(! is_alive.at(j)) { + selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(j); + delete selData; + m_TaskSelectionCtrl->Delete(j); + if (j == m_CurrentTaskSelection) { + m_bStableTaskInfoChanged = true; + } + } + } + + count = m_TaskSelectionCtrl->GetCount(); + for(j = 0; j < count; ++j) { + selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(j); + ctrlResult = selData->result; + if (Suspended() || (ctrlResult->suspended_via_gui)) { + newColor = redDot; + } else if (isRunning(ctrlResult)) { + newColor = greenDot; + } else if (ctrlResult->scheduler_state == CPU_SCHED_PREEMPTED) { + newColor = yellowDot; + } else { + newColor = redDot; + } + + if (newColor != selData->dotColor) { + switch (newColor) { + case greenDot: + m_TaskSelectionCtrl->SetItemBitmap(j, m_GreenDot); + break; + case yellowDot: + m_TaskSelectionCtrl->SetItemBitmap(j, m_YellowDot); + break; + case redDot: + m_TaskSelectionCtrl->SetItemBitmap(j, m_RedDot); + break; + } + selData->dotColor = newColor; + m_TaskSelectionCtrl->Refresh(); + } + } +} + + +bool CSimpleTaskPanel::isRunning(RESULT* result) { + bool outcome = false; + + // It must be scheduled to be running + if ( result->scheduler_state == CPU_SCHED_SCHEDULED ) { + // If either the project or task have been suspended, then it cannot be running + if ( !result->suspended_via_gui && !result->project_suspended_via_gui ) { + CC_STATUS status; + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + + pDoc->GetCoreClientStatus(status); + // Make sure that the core client isn't global suspended for some reason + if ( status.task_suspend_reason == 0 || status.task_suspend_reason == SUSPEND_REASON_CPU_THROTTLE ) { + outcome = true; + } + } + } + + return outcome; +} + + +bool CSimpleTaskPanel::DownloadingResults() { + bool return_value = false; + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + + if ( pDoc->results.results.size() > 0 ) { + RESULT* result; + for(unsigned int i=0; !return_value && i < pDoc->results.results.size(); i++ ) { + result = pDoc->result(i); + if ( result != NULL && result->state == RESULT_FILES_DOWNLOADING ) { + return_value = true; + } + } + } + return return_value; +} + +bool CSimpleTaskPanel::Suspended() { + CC_STATUS status; + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + + bool result = false; + pDoc->GetCoreClientStatus(status); + if ( pDoc->IsConnected() && status.task_suspend_reason > 0 && status.task_suspend_reason != SUSPEND_REASON_DISK_SIZE && status.task_suspend_reason != SUSPEND_REASON_CPU_THROTTLE ) { + result = true; + } + return result; +} + +// Check to see if a project update is scheduled or in progress +bool CSimpleTaskPanel::ProjectUpdateScheduled() { + PROJECT* project; + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + + int prjCount = pDoc->GetSimpleProjectCount(); + for(int i=0; istate.projects[i]; + if ( project->sched_rpc_pending || project->master_url_fetch_pending || project->scheduler_rpc_in_progress ) { + return true; + } + } + return false; +} + +void CSimpleTaskPanel::DisplayIdleState() { + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + + if ( pDoc->IsReconnecting() ) { + error_time = 0; + UpdateStaticText(&m_StatusValueText, _("Retrieving current status.")); + } else if ( pDoc->IsConnected() && pDoc->state.projects.size() == 0) { + error_time = 0; + UpdateStaticText(&m_StatusValueText, m_sNoProjectsString); + } else if ( DownloadingResults() ) { + error_time = 0; + UpdateStaticText(&m_StatusValueText, _("Downloading work from the server.")); + } else if ( Suspended() ) { + CC_STATUS status; + pDoc->GetCoreClientStatus(status); + if ( status.task_suspend_reason & SUSPEND_REASON_BATTERIES ) { + UpdateStaticText(&m_StatusValueText, _("Processing Suspended: Running On Batteries.")); + } else if ( status.task_suspend_reason & SUSPEND_REASON_USER_ACTIVE ) { + UpdateStaticText(&m_StatusValueText, _("Processing Suspended: User Active.")); + } else if ( status.task_suspend_reason & SUSPEND_REASON_USER_REQ ) { + UpdateStaticText(&m_StatusValueText, _("Processing Suspended: User paused processing.")); + } else if ( status.task_suspend_reason & SUSPEND_REASON_TIME_OF_DAY ) { + UpdateStaticText(&m_StatusValueText, _("Processing Suspended: Time of Day.")); + } else if ( status.task_suspend_reason & SUSPEND_REASON_BENCHMARKS ) { + UpdateStaticText(&m_StatusValueText, _("Processing Suspended: Benchmarks Running.")); + } else { + UpdateStaticText(&m_StatusValueText, _("Processing Suspended.")); + } + } else if ( ProjectUpdateScheduled() ) { + error_time = 0; + UpdateStaticText(&m_StatusValueText, _("Waiting to contact project servers.")); + } else { + if ( error_time == 0 ) { + error_time = time(NULL) + 10; + UpdateStaticText(&m_StatusValueText, _("Retrieving current status")); + } else if ( error_time < time(NULL) ) { + // TODO: should we display "ERROR" like old Simple GUI? + if ( pDoc->IsConnected() ) { + UpdateStaticText(&m_StatusValueText, _("No work available to process")); + } else { + UpdateStaticText(&m_StatusValueText, _("Unable to connect to the core client")); + } + } else { + UpdateStaticText(&m_StatusValueText, _("Retrieving current status")); + } + } +} + + +void CSimpleTaskPanel::UpdateStaticText(CTransparentStaticText **whichText, wxString s) { + EllipseStringIfNeeded(s, *whichText); + if ((*whichText)->GetLabel() != s) { + (*whichText)->SetLabel(s); + (*whichText)->SetName(s); // For accessibility on Windows + } +} + + +void CSimpleTaskPanel::EllipseStringIfNeeded(wxString& s, wxWindow *win) { + int x, y; + int w, h; + wxSize sz = GetSize(); + win->GetPosition(&x, &y); + int maxWidth = sz.GetWidth() - x - SIDEMARGINS; + + win->GetTextExtent(s, &w, &h); + + // Adapted from ellipis code in wxRendererGeneric::DrawHeaderButtonContents() + if (w > maxWidth) { + int ellipsisWidth; + win->GetTextExtent( wxT("..."), &ellipsisWidth, NULL); + if (ellipsisWidth > maxWidth) { + s.Clear(); + w = 0; + } else { + do { + s.Truncate( s.length() - 1 ); + win->GetTextExtent( s, &w, &h); + } while (((w + ellipsisWidth) > maxWidth) && s.length() ); + s.append( wxT("...") ); + w += ellipsisWidth; + } + } +} \ No newline at end of file diff --git a/clientgui/sg_TaskPanel.h b/clientgui/sg_TaskPanel.h new file mode 100755 index 0000000000..1e3772995a --- /dev/null +++ b/clientgui/sg_TaskPanel.h @@ -0,0 +1,138 @@ +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2008 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#ifndef __sg_TaskPanel__ +#define __sg_TaskPanel__ + + +#define SELECTBYRESULTNAME 0 + +#include "sg_CustomControls.h" +#include "sg_PanelBase.h" + + +typedef struct { + RESULT * result; + char result_name[256]; + char project_url[256]; + int dotColor; + char slide_show_filename_prefix[1024]; + int numSlides; + int lastSlideShown; +} TaskSelectionData; + + + +/////////////////////////////////////////////////////////////////////////// + +class CSlideShowPanel : public wxPanel +{ + DECLARE_DYNAMIC_CLASS( CSlideShowPanel ) + DECLARE_EVENT_TABLE() + + public: + CSlideShowPanel(); + CSlideShowPanel( wxWindow* parent); + ~CSlideShowPanel(); + + void OnSlideShowTimer(wxTimerEvent& WXUNUSED(event)); + void AdvanceSlideShow(bool changeSlide); + void OnPaint(wxPaintEvent& WXUNUSED(event)); + + private: + wxTimer* m_ChangeSlideTimer; + wxBitmap m_SlideBitmap; + bool m_bCurrentSlideIsDefault; + +}; + + +/////////////////////////////////////////////////////////////////////////////// +/// Class CSimpleTaskPanel +/////////////////////////////////////////////////////////////////////////////// + +#if 0 +#ifdef __WXMAC__ +#include "MacBitmapComboBox.h" +#else +#define CBOINCBitmapComboBox wxBitmapComboBox +#define EVT_BOINCBITMAPCOMBOBOX EVT_COMBOBOX +#endif +#endif + +class CSimpleTaskPanel : public CSimplePanelBase +{ + DECLARE_DYNAMIC_CLASS( CSimpleTaskPanel ) + DECLARE_EVENT_TABLE() + + public: + CSimpleTaskPanel(); + CSimpleTaskPanel( wxWindow* parent); + ~CSimpleTaskPanel(); + + TaskSelectionData* GetTaskSelectionData(); + wxString GetSelectedTaskString() { return m_TaskSelectionCtrl->GetValue(); } + void Update(); + wxRect GetProgressRect() { return m_ProgressRect; } + void ReskinInterface(); + void EllipseStringIfNeeded(wxString& s, wxWindow *win); + + private: + void OnTaskSelection(wxCommandEvent &event); + void GetApplicationAndProjectNames(RESULT* result, wxString* appName, wxString* projName); + wxString GetElapsedTimeString(double f); + wxString GetTimeRemainingString(double f); + wxString GetStatusString(RESULT* result); + wxString FormatTime(float fBuffer); + void UpdateTaskSelectionList(); + bool isRunning(RESULT* result); + bool DownloadingResults(); + bool Suspended(); + bool ProjectUpdateScheduled(); + void DisplayIdleState(); + void UpdateStaticText(CTransparentStaticText **whichText, wxString s); + void OnPulseProgressIndicator(wxTimerEvent& event); + + protected: + CTransparentStaticText* m_myTasksLabel; + CBOINCBitmapComboBox* m_TaskSelectionCtrl; + CTransparentStaticText* m_TaskProjectLabel; + CTransparentStaticText* m_TaskProjectName; +#if SELECTBYRESULTNAME + CTransparentStaticText* m_TaskApplicationName; +#endif + CSlideShowPanel* m_SlideShowArea; + CTransparentStaticText* m_ElapsedTimeValue; + CTransparentStaticText* m_TimeRemainingValue; + wxGauge* m_ProgressBar; + CTransparentStaticText* m_ProgressValueText; + CTransparentStaticText* m_StatusValueText; + wxButton* m_TaskCommandsButton; + wxRect m_ProgressRect; + int m_oldWorkCount; + time_t error_time; + wxBitmap m_GreenDot; + wxBitmap m_YellowDot; + wxBitmap m_RedDot; + wxTimer* m_pulseTimer; + bool m_bStableTaskInfoChanged; + int m_CurrentTaskSelection; + wxString m_sNotAvailableString; + wxString m_sNoProjectsString; +}; + +#endif //__sg_TaskPanel__ diff --git a/mac_build/boinc.xcodeproj/project.pbxproj b/mac_build/boinc.xcodeproj/project.pbxproj index 14e79e8a22..dbb93634a2 100755 --- a/mac_build/boinc.xcodeproj/project.pbxproj +++ b/mac_build/boinc.xcodeproj/project.pbxproj @@ -183,7 +183,6 @@ DD616A3008150050006981C1 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F51BDF4903086C46012012A7 /* InfoPlist.strings */; }; DD635A420D384FA500BAC1A5 /* texfont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD635A410D384FA500BAC1A5 /* texfont.cpp */; }; DD6381F90870DD83007A2F8E /* make_app_icon_h.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD6381F80870DD83007A2F8E /* make_app_icon_h.cpp */; }; - DD63F7510B64EECE0053037F /* libwx_mac_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DDA90F260B64673D008F2E87 /* libwx_mac_static.a */; }; DD6617880A3FFD8C00FFEBEB /* check_security.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD6617870A3FFD8C00FFEBEB /* check_security.cpp */; }; DD67F8140ADB9DD000B0015E /* wxPieCtrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD40E75D0ADB87BC00214518 /* wxPieCtrl.cpp */; }; DD6802300E701ACD0067D009 /* cert_sig.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD68022E0E701ACD0067D009 /* cert_sig.cpp */; }; @@ -201,6 +200,10 @@ DD7475520D86273300860636 /* coproc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7475500D86273300860636 /* coproc.cpp */; }; DD7748B50A356D6C0025D05E /* SetupSecurity.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7748B40A356D6C0025D05E /* SetupSecurity.cpp */; }; DD7749680A3596380025D05E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD1929D80918A2F100C31BCF /* Security.framework */; }; + DD7A5D8312EEBE5E0006268E /* sg_TaskCommandPopup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7A5D8212EEBE5E0006268E /* sg_TaskCommandPopup.cpp */; }; + DD7A5D9F12EEBFC20006268E /* sg_ProjectWebSitesPopup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7A5D9E12EEBFC20006268E /* sg_ProjectWebSitesPopup.cpp */; }; + DD7A5DAB12EEC37B0006268E /* sg_ProjectCommandPopup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7A5DAA12EEC37B0006268E /* sg_ProjectCommandPopup.cpp */; }; + DD7A5E5012EEE3A20006268E /* sg_BoincSimpleFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDAFA7AC12D4834D00997329 /* sg_BoincSimpleFrame.cpp */; }; DD7AEB4A0C87CE1300AC3B5C /* screensaver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7AEB490C87CE1300AC3B5C /* screensaver.cpp */; }; DD7BF7DA0B8E7A9800A009F7 /* str_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7BF7D70B8E7A9800A009F7 /* str_util.cpp */; }; DD7BF7E10B8E7B3700A009F7 /* str_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7BF7D70B8E7A9800A009F7 /* str_util.cpp */; }; @@ -283,6 +286,7 @@ DDAD31D90EC26B14002DA09D /* mac_address.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDAD31D60EC26B14002DA09D /* mac_address.cpp */; }; DDAEC9FF07FA5A5C00A7BC36 /* SetVersion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDAEC9E707FA58A000A7BC36 /* SetVersion.cpp */; }; DDB219B210B3BBA900417AEF /* WaitPermissions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDB219B110B3BBA900417AEF /* WaitPermissions.cpp */; }; + DDB42E3412F1B6A400E6D8A2 /* libwx_mac_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DDA90F260B64673D008F2E87 /* libwx_mac_static.a */; }; DDB693500ABFE9C600689FD8 /* procinfo_mac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDB6934F0ABFE9C600689FD8 /* procinfo_mac.cpp */; }; DDB6E3EF0D5B27AA00ED12B8 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 20286C33FDCF999611CA2CEA /* Carbon.framework */; }; DDB74A6C0D74259E00E97A40 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDFE854A0B60CFD0009B43D9 /* AppKit.framework */; }; @@ -302,14 +306,17 @@ DDBC6CA50D5D458700564C49 /* boinc_ss_logo.png in Resources */ = {isa = PBXBuildFile; fileRef = DDBC6CA40D5D458700564C49 /* boinc_ss_logo.png */; }; DDBD51760C169B770074905B /* LoginItemAPI.c in Sources */ = {isa = PBXBuildFile; fileRef = DD1277BE081F3E73007B5DE1 /* LoginItemAPI.c */; }; DDBE74390C03B1C600453BB8 /* cs_platforms.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDBE74380C03B1C600453BB8 /* cs_platforms.cpp */; }; + DDBEABA212DB1E930087252D /* MacBitmapComboBox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDBEABA112DB1E930087252D /* MacBitmapComboBox.cpp */; }; DDC06AB410A3E93F00C8D9A5 /* url.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDC06AB210A3E93F00C8D9A5 /* url.cpp */; }; DDC06AB810A3E97700C8D9A5 /* url.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDC06AB210A3E93F00C8D9A5 /* url.cpp */; }; DDC06ABC10A3E98D00C8D9A5 /* url.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDC06AB210A3E93F00C8D9A5 /* url.cpp */; }; DDC132F30E2DAB1B0014D305 /* AsyncRPC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDC132F20E2DAB1B0014D305 /* AsyncRPC.cpp */; }; + DDC321AE12E45162006CB55F /* sg_PanelBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDC321AC12E45162006CB55F /* sg_PanelBase.cpp */; }; DDC3D55E0D507D1700BE6D23 /* BOINCClientManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDC3D55C0D507D1700BE6D23 /* BOINCClientManager.cpp */; }; DDC836E60EDEA5DB001C2EF9 /* TermsOfUsePage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDC836E50EDEA5DB001C2EF9 /* TermsOfUsePage.cpp */; }; DDC988FE0F3BD44100EE8D0E /* gui_rpc_client_ops.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD73E34E08A0694000656EB1 /* gui_rpc_client_ops.cpp */; }; DDCF84080E1B7C0A005EDC45 /* DlgItemProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDCF84060E1B7C0A005EDC45 /* DlgItemProperties.cpp */; }; + DDD0697312D70C9400120920 /* sg_TaskPanel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDD0697112D70C9400120920 /* sg_TaskPanel.cpp */; }; DDD095490A3EDF2D00C95BA4 /* switcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDD095480A3EDF2D00C95BA4 /* switcher.cpp */; }; DDD3370A106224E800867C7D /* AddRemoveUser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDD33709106224E800867C7D /* AddRemoveUser.cpp */; }; DDD3370F10622C6C00867C7D /* LoginItemAPI.c in Sources */ = {isa = PBXBuildFile; fileRef = DD1277BE081F3E73007B5DE1 /* LoginItemAPI.c */; }; @@ -370,6 +377,7 @@ DDD9C5AB10CCF6A300A1E4CD /* coproc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7475500D86273300860636 /* coproc.cpp */; }; DDD9C5AC10CCF6AB00A1E4CD /* coproc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DD7475500D86273300860636 /* coproc.cpp */; }; DDDC35260909212D006076EC /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F51BDF4903086C46012012A7 /* InfoPlist.strings */; }; + DDDD6D8012E4611300C258A0 /* sg_ProjectPanel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDDD6D7E12E4611300C258A0 /* sg_ProjectPanel.cpp */; }; DDDE43B10EC04C1800083520 /* DlgExitMessage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDDE43B00EC04C1800083520 /* DlgExitMessage.cpp */; }; DDE1372A10DC5E5300161D6B /* cs_notice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDE1372810DC5E5300161D6B /* cs_notice.cpp */; }; DDE1372F10DC5E8D00161D6B /* notice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDE1372D10DC5E8D00161D6B /* notice.cpp */; }; @@ -821,6 +829,12 @@ DD7475500D86273300860636 /* coproc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coproc.cpp; sourceTree = ""; }; DD7748980A356C880025D05E /* SetUpSecurity */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SetUpSecurity; sourceTree = BUILT_PRODUCTS_DIR; }; DD7748B40A356D6C0025D05E /* SetupSecurity.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SetupSecurity.cpp; path = ../clientgui/mac/SetupSecurity.cpp; sourceTree = SOURCE_ROOT; }; + DD7A5D8112EEBDF30006268E /* sg_TaskCommandPopup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sg_TaskCommandPopup.h; path = ../clientgui/sg_TaskCommandPopup.h; sourceTree = SOURCE_ROOT; }; + DD7A5D8212EEBE5E0006268E /* sg_TaskCommandPopup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sg_TaskCommandPopup.cpp; path = ../clientgui/sg_TaskCommandPopup.cpp; sourceTree = SOURCE_ROOT; }; + DD7A5D9D12EEBFC20006268E /* sg_ProjectWebSitesPopup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sg_ProjectWebSitesPopup.h; path = ../clientgui/sg_ProjectWebSitesPopup.h; sourceTree = SOURCE_ROOT; }; + DD7A5D9E12EEBFC20006268E /* sg_ProjectWebSitesPopup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sg_ProjectWebSitesPopup.cpp; path = ../clientgui/sg_ProjectWebSitesPopup.cpp; sourceTree = SOURCE_ROOT; }; + DD7A5DA712EEC33F0006268E /* sg_ProjectCommandPopup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sg_ProjectCommandPopup.h; path = ../clientgui/sg_ProjectCommandPopup.h; sourceTree = SOURCE_ROOT; }; + DD7A5DAA12EEC37B0006268E /* sg_ProjectCommandPopup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sg_ProjectCommandPopup.cpp; path = ../clientgui/sg_ProjectCommandPopup.cpp; sourceTree = SOURCE_ROOT; }; DD7AEB490C87CE1300AC3B5C /* screensaver.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = screensaver.cpp; path = ../clientscr/screensaver.cpp; sourceTree = SOURCE_ROOT; }; DD7AEB680C87CE6500AC3B5C /* screensaver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = screensaver.h; path = ../clientscr/screensaver.h; sourceTree = SOURCE_ROOT; }; DD7BF7D70B8E7A9800A009F7 /* str_util.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = str_util.cpp; sourceTree = ""; }; @@ -909,6 +923,8 @@ DDAD31D70EC26B14002DA09D /* mac_address.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mac_address.h; path = ../lib/mac_address.h; sourceTree = SOURCE_ROOT; }; DDAEC9E107FA583B00A7BC36 /* SetVersion */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SetVersion; sourceTree = BUILT_PRODUCTS_DIR; }; DDAEC9E707FA58A000A7BC36 /* SetVersion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SetVersion.cpp; path = ../clientgui/mac/SetVersion.cpp; sourceTree = SOURCE_ROOT; }; + DDAFA7AC12D4834D00997329 /* sg_BoincSimpleFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sg_BoincSimpleFrame.cpp; sourceTree = ""; }; + DDAFA7AD12D4834D00997329 /* sg_BoincSimpleFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sg_BoincSimpleFrame.h; sourceTree = ""; }; DDB219A410B3BB6100417AEF /* WaitPermissions.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WaitPermissions.app; sourceTree = BUILT_PRODUCTS_DIR; }; DDB219A610B3BB6200417AEF /* WaitPermissions-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "WaitPermissions-Info.plist"; sourceTree = ""; }; DDB219B110B3BBA900417AEF /* WaitPermissions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WaitPermissions.cpp; path = ../mac_installer/WaitPermissions.cpp; sourceTree = SOURCE_ROOT; }; @@ -928,10 +944,14 @@ DDBDF4A90987091800464F83 /* ValidateEmailAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ValidateEmailAddress.cpp; path = ../clientgui/ValidateEmailAddress.cpp; sourceTree = SOURCE_ROOT; }; DDBDF4AA0987091800464F83 /* ValidateEmailAddress.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ValidateEmailAddress.h; path = ../clientgui/ValidateEmailAddress.h; sourceTree = SOURCE_ROOT; }; DDBE74380C03B1C600453BB8 /* cs_platforms.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = cs_platforms.cpp; sourceTree = ""; }; + DDBEABA012DB1E930087252D /* MacBitmapComboBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MacBitmapComboBox.h; path = ../clientgui/MacBitmapComboBox.h; sourceTree = ""; }; + DDBEABA112DB1E930087252D /* MacBitmapComboBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MacBitmapComboBox.cpp; path = ../clientgui/MacBitmapComboBox.cpp; sourceTree = ""; }; DDC06AB210A3E93F00C8D9A5 /* url.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = url.cpp; path = ../lib/url.cpp; sourceTree = SOURCE_ROOT; }; DDC06AB310A3E93F00C8D9A5 /* url.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = url.h; path = ../lib/url.h; sourceTree = SOURCE_ROOT; }; DDC132F10E2DAB1B0014D305 /* AsyncRPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncRPC.h; sourceTree = ""; }; DDC132F20E2DAB1B0014D305 /* AsyncRPC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AsyncRPC.cpp; sourceTree = ""; }; + DDC321AC12E45162006CB55F /* sg_PanelBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sg_PanelBase.cpp; path = ../clientgui/sg_PanelBase.cpp; sourceTree = SOURCE_ROOT; }; + DDC321AD12E45162006CB55F /* sg_PanelBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sg_PanelBase.h; path = ../clientgui/sg_PanelBase.h; sourceTree = SOURCE_ROOT; }; DDC3D55C0D507D1700BE6D23 /* BOINCClientManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BOINCClientManager.cpp; path = ../clientgui/BOINCClientManager.cpp; sourceTree = SOURCE_ROOT; }; DDC3D55D0D507D1700BE6D23 /* BOINCClientManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BOINCClientManager.h; path = ../clientgui/BOINCClientManager.h; sourceTree = SOURCE_ROOT; }; DDC63EEF0985B89600383FD2 /* DlgGenericMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = DlgGenericMessage.cpp; path = ../clientgui/DlgGenericMessage.cpp; sourceTree = SOURCE_ROOT; }; @@ -954,6 +974,8 @@ DDCE783F0A70BF72008218B6 /* sg_ProjectsComponent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sg_ProjectsComponent.h; path = ../clientgui/sg_ProjectsComponent.h; sourceTree = SOURCE_ROOT; }; DDCF84060E1B7C0A005EDC45 /* DlgItemProperties.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DlgItemProperties.cpp; sourceTree = ""; }; DDCF84070E1B7C0A005EDC45 /* DlgItemProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DlgItemProperties.h; sourceTree = ""; }; + DDD0697112D70C9400120920 /* sg_TaskPanel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sg_TaskPanel.cpp; path = ../clientgui/sg_TaskPanel.cpp; sourceTree = SOURCE_ROOT; }; + DDD0697212D70C9400120920 /* sg_TaskPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sg_TaskPanel.h; path = ../clientgui/sg_TaskPanel.h; sourceTree = SOURCE_ROOT; }; DDD0953F0A3EDD2500C95BA4 /* switcher */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = switcher; sourceTree = BUILT_PRODUCTS_DIR; }; DDD095480A3EDF2D00C95BA4 /* switcher.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = switcher.cpp; sourceTree = ""; }; DDD337021062235D00867C7D /* AddRemoveUser */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = AddRemoveUser; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -966,6 +988,8 @@ DDD52DC90C03CAE6009B5FC0 /* ViewWork.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ViewWork.h; path = ../clientgui/ViewWork.h; sourceTree = SOURCE_ROOT; }; DDD74D8707CF482E0065AC9D /* boinc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = boinc; sourceTree = BUILT_PRODUCTS_DIR; }; DDD9C59210CCF54300A1E4CD /* coproc_detect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = coproc_detect.cpp; path = ../client/coproc_detect.cpp; sourceTree = SOURCE_ROOT; }; + DDDD6D7E12E4611300C258A0 /* sg_ProjectPanel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sg_ProjectPanel.cpp; path = ../clientgui/sg_ProjectPanel.cpp; sourceTree = SOURCE_ROOT; }; + DDDD6D7F12E4611300C258A0 /* sg_ProjectPanel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sg_ProjectPanel.h; path = ../clientgui/sg_ProjectPanel.h; sourceTree = SOURCE_ROOT; }; DDDE43B00EC04C1800083520 /* DlgExitMessage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DlgExitMessage.cpp; path = ../clientgui/DlgExitMessage.cpp; sourceTree = SOURCE_ROOT; }; DDDE43B80EC04C3C00083520 /* DlgExitMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DlgExitMessage.h; path = ../clientgui/DlgExitMessage.h; sourceTree = SOURCE_ROOT; }; DDE1372810DC5E5300161D6B /* cs_notice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cs_notice.cpp; path = ../client/cs_notice.cpp; sourceTree = SOURCE_ROOT; }; @@ -1074,10 +1098,10 @@ DD3E15310A774397007E0084 /* Carbon.framework in Frameworks */, DD3E15320A774397007E0084 /* IOKit.framework in Frameworks */, DD3E15330A774397007E0084 /* Security.framework in Frameworks */, - DD63F7510B64EECE0053037F /* libwx_mac_static.a in Frameworks */, DDA546610D16964E008CC69A /* QuickTime.framework in Frameworks */, DD21B49D0D750FC600AFFEE5 /* AppKit.framework in Frameworks */, DD1682B10F8DC6D90096D714 /* OpenGL.framework in Frameworks */, + DDB42E3412F1B6A400E6D8A2 /* libwx_mac_static.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1413,6 +1437,8 @@ DD58C45F08F334EA00C1DF66 /* ProxyPage.h */, DD58C46008F334EA00C1DF66 /* resource.h */, DD81C41707C5D13E0098A04D /* stdwx.cpp */, + DDAFA7AC12D4834D00997329 /* sg_BoincSimpleFrame.cpp */, + DDAFA7AD12D4834D00997329 /* sg_BoincSimpleFrame.h */, DDCAD7D10A6C603A0086C7EE /* sg_BoincSimpleGUI.cpp */, DDCAD7D20A6C603A0086C7EE /* sg_BoincSimpleGUI.h */, DD4C560A0AD389A2009E23C6 /* sg_ClientStateIndicator.cpp */, @@ -1427,12 +1453,24 @@ DD4C560F0AD389A2009E23C6 /* sg_ImageButton.h */, DDCAD7D50A6C603A0086C7EE /* sg_ImageLoader.cpp */, DDCAD7D60A6C603A0086C7EE /* sg_ImageLoader.h */, + DDC321AC12E45162006CB55F /* sg_PanelBase.cpp */, + DDC321AD12E45162006CB55F /* sg_PanelBase.h */, DD4C56100AD389A2009E23C6 /* sg_ProgressBar.cpp */, DD4C56110AD389A2009E23C6 /* sg_ProgressBar.h */, + DDDD6D7E12E4611300C258A0 /* sg_ProjectPanel.cpp */, + DDDD6D7F12E4611300C258A0 /* sg_ProjectPanel.h */, + DD7A5DAA12EEC37B0006268E /* sg_ProjectCommandPopup.cpp */, + DD7A5DA712EEC33F0006268E /* sg_ProjectCommandPopup.h */, DDCE783E0A70BF72008218B6 /* sg_ProjectsComponent.cpp */, DDCE783F0A70BF72008218B6 /* sg_ProjectsComponent.h */, + DD7A5D9D12EEBFC20006268E /* sg_ProjectWebSitesPopup.h */, + DD7A5D9E12EEBFC20006268E /* sg_ProjectWebSitesPopup.cpp */, DDCAD7D90A6C603A0086C7EE /* sg_StatImageLoader.cpp */, DDCAD7DA0A6C603A0086C7EE /* sg_StatImageLoader.h */, + DD7A5D8212EEBE5E0006268E /* sg_TaskCommandPopup.cpp */, + DD7A5D8112EEBDF30006268E /* sg_TaskCommandPopup.h */, + DDD0697112D70C9400120920 /* sg_TaskPanel.cpp */, + DDD0697212D70C9400120920 /* sg_TaskPanel.h */, DDCAD7DB0A6C603A0086C7EE /* sg_ViewTabPage.cpp */, DDCAD7DC0A6C603A0086C7EE /* sg_ViewTabPage.h */, DD247AF70AEA308A0034104A /* SkinManager.cpp */, @@ -1733,6 +1771,8 @@ DD1F0ACD0822069E00AFC5FA /* MacGUI.pch */, DDA99BF31099AF18002F8E9B /* MacAccessiblity.cpp */, DD29728E10BB657A00DF3C2E /* MacAccessiblity.h */, + DDBEABA112DB1E930087252D /* MacBitmapComboBox.cpp */, + DDBEABA012DB1E930087252D /* MacBitmapComboBox.h */, DD2F32F707F2A88B00645DDC /* MacSysMenu.cpp */, DDA9D3BB09189A8C0060E7A7 /* Mac_GUI.cpp */, DD2F32EF07F2A83E00645DDC /* MacSysMenu.h */, @@ -2595,6 +2635,14 @@ DDA850A41207EED900B473A6 /* WizardAttach.cpp in Sources */, DD4FA25D121828E400154856 /* BOINCHtmlLBox.cpp in Sources */, DD4FA2621218290600154856 /* BOINCVListBox.cpp in Sources */, + DDD0697312D70C9400120920 /* sg_TaskPanel.cpp in Sources */, + DDBEABA212DB1E930087252D /* MacBitmapComboBox.cpp in Sources */, + DDC321AE12E45162006CB55F /* sg_PanelBase.cpp in Sources */, + DDDD6D8012E4611300C258A0 /* sg_ProjectPanel.cpp in Sources */, + DD7A5D8312EEBE5E0006268E /* sg_TaskCommandPopup.cpp in Sources */, + DD7A5D9F12EEBFC20006268E /* sg_ProjectWebSitesPopup.cpp in Sources */, + DD7A5DAB12EEC37B0006268E /* sg_ProjectCommandPopup.cpp in Sources */, + DD7A5E5012EEE3A20006268E /* sg_BoincSimpleFrame.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3151,7 +3199,11 @@ ../clientgui, ); INFOPLIST_FILE = Info.plist; - LIBRARY_SEARCH_PATHS = "../../wxMac-2.8.10/src/build/Deployment/"; + LIBRARY_SEARCH_PATHS = ( + "../../wxMac-2.8.10/src/build/Deployment/", + "\"$(SRCROOT)/../../jpeg-6b\"", + "\"$(SRCROOT)/../../wxMac-2.8.10/src/build/Deployment\"", + ); OTHER_CFLAGS = ( "-DHAVE_CONFIG_H", "-D_FILE_OFFSET_BITS=64", @@ -3197,7 +3249,11 @@ ../clientgui, ); INFOPLIST_FILE = Info.plist; - LIBRARY_SEARCH_PATHS = "../../wxMac-2.8.10/src/build/Deployment/"; + LIBRARY_SEARCH_PATHS = ( + "../../wxMac-2.8.10/src/build/Deployment/", + "\"$(SRCROOT)/../../jpeg-6b\"", + "\"$(SRCROOT)/../../wxMac-2.8.10/src/build/Deployment\"", + ); OTHER_CFLAGS = ( "-DHAVE_CONFIG_H", "-D_FILE_OFFSET_BITS=64", @@ -3243,7 +3299,11 @@ ../clientgui, ); INFOPLIST_FILE = Info.plist; - LIBRARY_SEARCH_PATHS = "../../wxMac-2.8.10/src/build/Deployment/"; + LIBRARY_SEARCH_PATHS = ( + "../../wxMac-2.8.10/src/build/Deployment/", + "\"$(SRCROOT)/../../jpeg-6b\"", + "\"$(SRCROOT)/../../wxMac-2.8.10/src/build/Deployment\"", + ); OTHER_CFLAGS = ( "-DHAVE_CONFIG_H", "-D_FILE_OFFSET_BITS=64", @@ -3289,7 +3349,11 @@ ../clientgui, ); INFOPLIST_FILE = Info.plist; - LIBRARY_SEARCH_PATHS = "../../wxMac-2.8.10/src/build/Deployment/"; + LIBRARY_SEARCH_PATHS = ( + "../../wxMac-2.8.10/src/build/Deployment/", + "\"$(SRCROOT)/../../jpeg-6b\"", + "\"$(SRCROOT)/../../wxMac-2.8.10/src/build/Deployment\"", + ); OTHER_CFLAGS = ( "-DHAVE_CONFIG_H", "-D_FILE_OFFSET_BITS=64", @@ -3766,7 +3830,11 @@ ../clientgui, ); INFOPLIST_FILE = Info.plist; - LIBRARY_SEARCH_PATHS = "../../wxMac-2.8.10/src/build/Deployment/"; + LIBRARY_SEARCH_PATHS = ( + "../../wxMac-2.8.10/src/build/Deployment/", + "\"$(SRCROOT)/../../jpeg-6b\"", + "\"$(SRCROOT)/../../wxMac-2.8.10/src/build/Deployment\"", + ); OTHER_CFLAGS = ( "-DHAVE_CONFIG_H", "-D_FILE_OFFSET_BITS=64", @@ -3811,7 +3879,11 @@ ../clientgui, ); INFOPLIST_FILE = Info.plist; - LIBRARY_SEARCH_PATHS = "../../wxMac-2.8.10/src/build/Deployment/"; + LIBRARY_SEARCH_PATHS = ( + "../../wxMac-2.8.10/src/build/Deployment/", + "\"$(SRCROOT)/../../jpeg-6b\"", + "\"$(SRCROOT)/../../wxMac-2.8.10/src/build/Deployment\"", + ); OTHER_CFLAGS = ( "-DHAVE_CONFIG_H", "-D_FILE_OFFSET_BITS=64", @@ -4286,7 +4358,11 @@ ../clientgui, ); INFOPLIST_FILE = Info.plist; - LIBRARY_SEARCH_PATHS = "../../wxMac-2.8.10/src/build/Deployment/"; + LIBRARY_SEARCH_PATHS = ( + "../../wxMac-2.8.10/src/build/Deployment/", + "\"$(SRCROOT)/../../jpeg-6b\"", + "\"$(SRCROOT)/../../wxMac-2.8.10/src/build/Deployment\"", + ); OTHER_CFLAGS = ( "-DHAVE_CONFIG_H", "-D_FILE_OFFSET_BITS=64",