diff --git a/checkin_notes b/checkin_notes index 937b5e5a1d..30ff9e75ee 100644 --- a/checkin_notes +++ b/checkin_notes @@ -8696,3 +8696,12 @@ David 26 Nov 2011 ssim/ ssim.cpp + +Charlie 28 Nov 2011 + - MGR: In Simple View, if task has no slide show, then display the + institution, science area and description. + This is in progress: not yet finished. + + clientgui/ + sg_PanelBase.cpp,.h + sg_TaskPanel.cpp,.h diff --git a/clientgui/sg_PanelBase.cpp b/clientgui/sg_PanelBase.cpp index ce1bf32648..a9aff19a83 100755 --- a/clientgui/sg_PanelBase.cpp +++ b/clientgui/sg_PanelBase.cpp @@ -174,6 +174,15 @@ void CSimplePanelBase::OnPaint(wxPaintEvent& /*event*/) { } +wxBitmap CSimplePanelBase::GetBackgroundBmp() { + if (!m_GotBGBitMap) { + MakeBGBitMap(); + } + + return m_TaskPanelBGBitMap; +} + + void CSimplePanelBase::UpdateStaticText(CTransparentStaticText **whichText, wxString s) { EllipseStringIfNeeded(s, *whichText); if ((*whichText)->GetLabel() != s) { diff --git a/clientgui/sg_PanelBase.h b/clientgui/sg_PanelBase.h index 78425a7143..4a7756c938 100755 --- a/clientgui/sg_PanelBase.h +++ b/clientgui/sg_PanelBase.h @@ -70,6 +70,7 @@ class CSimplePanelBase : public wxPanel void ReskinInterface(); virtual wxRect GetProgressRect() { return wxRect(0, 0, 0, 0); } + wxBitmap GetBackgroundBmp(); void UpdateStaticText(CTransparentStaticText **whichText, wxString s); void EllipseStringIfNeeded(wxString& s, wxWindow *win); diff --git a/clientgui/sg_TaskPanel.cpp b/clientgui/sg_TaskPanel.cpp index 0f1169b052..02c831df31 100755 --- a/clientgui/sg_TaskPanel.cpp +++ b/clientgui/sg_TaskPanel.cpp @@ -1,1051 +1,1148 @@ -// 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 - -#define SORTTASKLIST 1 /* TRUE to sort task selection control alphabetically */ - -#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" - - -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 -#define HIDEDEFAULTSLIDE 1 - -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, false); -} - - -void CSlideShowPanel::AdvanceSlideShow(bool changeSlide, bool reload) { - double xRatio, yRatio, ratio; - TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData(); - if (selData == NULL) return; - - if (reload) { - m_bCurrentSlideIsDefault = false; - selData->lastSlideShown = -1; - } - - int numSlides = (int)selData->slideShowFileNames.size(); - - if (numSlides <= 0) { -#if HIDEDEFAULTSLIDE - Show(false); - return; -#else - if (m_bCurrentSlideIsDefault) return; - - CSkinSimple* pSkinSimple = wxGetApp().GetSkinManager()->GetSimple(); - wxASSERT(pSkinSimple); - wxASSERT(wxDynamicCast(pSkinSimple, CSkinSimple)); - - m_SlideBitmap = *pSkinSimple->GetWorkunitAnimationImage()->GetBitmap(); - if (m_SlideBitmap.Ok()) { - m_bCurrentSlideIsDefault = true; - } -#endif - } else { -#if HIDEDEFAULTSLIDE - Show(true); -#endif - // TODO: Should we allow slide show to advance if task is not running? - int newSlide = selData->lastSlideShown; - - if (selData->dotColor == greenDot) { // Advance only if running - if (changeSlide) { - if (++newSlide >= numSlides) { - newSlide = 0; - } - } - } - if (newSlide < 0) { - newSlide = 0; - } - - if (selData->lastSlideShown != newSlide) { // Don't update if only one slide - - selData->lastSlideShown = newSlide; - - wxBitmap *bm = new wxBitmap(); - bm->LoadFile(selData->slideShowFileNames[newSlide], wxBITMAP_TYPE_ANY); - if (bm->Ok()) { - m_SlideBitmap = *bm; - delete bm; - 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(*wxLIGHT_GREY, 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) -#ifdef __WXMAC__ - EVT_ERASE_BACKGROUND(CSimpleTaskPanel::OnEraseBackground) -#endif -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_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"); - m_progressBarRect = NULL; - - SetForegroundColour(*wxBLACK); - - wxBoxSizer* bSizer1; - bSizer1 = new wxBoxSizer( wxVERTICAL ); - - wxBoxSizer* bSizer2; - bSizer2 = new wxBoxSizer( wxHORIZONTAL ); - - m_myTasksLabel = new CTransparentStaticText( this, wxID_ANY, _("Tasks:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_myTasksLabel->Wrap( -1 ); - 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:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_TaskProjectLabel->Wrap( -1 ); - 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 ); - wxFont theFont = m_TaskProjectName->GetFont(); - theFont.SetWeight(wxFONTWEIGHT_BOLD); - m_TaskProjectName->SetFont(theFont); - 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 ); - - 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 ); - 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 ); - 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 optimizations in - // CSimpleGUIPanel::OnEraseBackground and CSimpleTaskPanel::OnEraseBackground. - m_ProgressBar = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL ); - m_iPctDoneX10 = 1000; - m_ProgressBar->SetValue( 100 ); - 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.000%"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT | wxST_NO_AUTORESIZE ); - m_ProgressValueText->Wrap( -1 ); - 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 ); - 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(); -#ifdef __WXMAC__ - m_ProgressRect.Inflate(0, -2); - m_ProgressRect.Offset(0, -2); -#endif -} - - -CSimpleTaskPanel::~CSimpleTaskPanel() -{ - TaskSelectionData *selData; - int count = m_TaskSelectionCtrl->GetCount(); - for(int j = count-1; j >=0; --j) { - selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(j); - selData->slideShowFileNames.Clear(); - delete selData; - // Indicate to Clear() we have cleaned up the Selection Data - m_TaskSelectionCtrl->SetClientData(j, NULL); - } - m_TaskSelectionCtrl->Clear(); - - m_pulseTimer->Stop(); - delete m_pulseTimer; - - if (m_progressBarRect) { - delete m_progressBarRect; - } -} - - -void CSimpleTaskPanel::OnTaskSelection(wxCommandEvent& /*event*/) -{ - int sel = m_TaskSelectionCtrl->GetSelection(); - if (sel != m_CurrentTaskSelection) { - m_CurrentTaskSelection = sel; - m_bStableTaskInfoChanged = true; - UpdatePanel(); - } -} - - -void CSimpleTaskPanel::UpdatePanel(bool delayShow) { - wxString s = wxEmptyString; - wxString projName = wxEmptyString; - TaskSelectionData *selData; - CMainDocument* pDoc = wxGetApp().GetDocument(); - wxASSERT(pDoc); - int workCount = pDoc->GetSimpleGUIWorkCount(); - - // Workaround for Linux refresh problem - static bool wasDelayed = false; - -#ifndef __WXMAC__ - Freeze(); -#endif - - if ((workCount <= 0) || delayShow) { - if ((workCount != m_oldWorkCount) || delayShow) { - wasDelayed = true; - 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(); - if (m_iPctDoneX10 >= 0) { - m_iPctDoneX10 = -1; - m_ProgressBar->Pulse(); - m_pulseTimer->Start(100); - } - this->Layout(); - -#ifdef __WXMAC__ - m_ProgressRect = m_ProgressBar->GetRect(); - m_ProgressRect.Inflate(0, -2); - m_ProgressRect.Offset(0, -2); -#endif - } - - DisplayIdleState(); - - } else { - if ((m_oldWorkCount == 0) || wasDelayed) { - wasDelayed = false; - 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(); - this->Layout(); - -#ifdef __WXMAC__ - m_ProgressRect = m_ProgressBar->GetRect(); - m_ProgressRect.Inflate(0, -2); - m_ProgressRect.Offset(0, -2); -#endif - } - - UpdateTaskSelectionList(false); - - // 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, true); - 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)); - int pctDoneX10 = result->fraction_done * 1000.0; - if (m_iPctDoneX10 != pctDoneX10) { - if (m_iPctDoneX10 < 0) { - m_pulseTimer->Stop(); - } - int pctDone = pctDoneX10 / 10; - if (pctDone != (m_iPctDoneX10 / 10)) { - m_ProgressBar->SetValue(pctDone); - } - s.Printf(_("%.3f%%"), result->fraction_done*100); - m_iPctDoneX10 = pctDoneX10; - 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)); - if (m_iPctDoneX10 >= 0) { - m_iPctDoneX10 = -1; - 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() { - wxLogTrace(wxT("Function Start/End"), wxT("CSimpleTaskPanel::ReskinInterface - Function Begin")); - CSimplePanelBase::ReskinInterface(); - m_SlideShowArea->AdvanceSlideShow(false, false); - UpdateTaskSelectionList(true); - wxLogTrace(wxT("Function Start/End"), wxT("CSimpleTaskPanel::ReskinInterface - Function Begin")); -} - - -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 strGPUBuffer = wxEmptyString; - wxString pct_done_str = 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 (avp->ncudas) { - strGPUBuffer = wxString(" (NVIDIA GPU)", wxConvUTF8); - } - if (avp->natis) { - strGPUBuffer = wxString(" (ATI GPU)", wxConvUTF8); - } - - appName->Printf( - wxT("%s%s%s"), - state_result->project->anonymous_platform?_("Local: "):wxT(""), - strAppBuffer.c_str(), - strGPUBuffer.c_str() - ); - } - - 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: %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(_("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::FindSlideShowFiles(TaskSelectionData *selData) { - RESULT* state_result; - char urlDirectory[1024]; - char fileName[1024]; - char resolvedFileName[1024]; - int j; - CMainDocument* pDoc = wxGetApp().GetDocument(); - wxASSERT(pDoc); - - - selData->slideShowFileNames.Clear(); - state_result = pDoc->state.lookup_result(selData->result->project_url, selData->result->name); - if (!state_result) { - pDoc->ForceCacheUpdate(); - state_result = pDoc->state.lookup_result(selData->result->project_url, selData->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)) { - selData->slideShowFileNames.Add(wxString(resolvedFileName,wxConvUTF8)); - } - } else { - break; - } - } - - if ( selData->slideShowFileNames.size() == 0 ) { - 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)) { - selData->slideShowFileNames.Add(wxString(resolvedFileName,wxConvUTF8)); - } - } else { - break; - } - } - } - } - selData->lastSlideShown = -1; -} - - -void CSimpleTaskPanel::UpdateTaskSelectionList(bool reskin) { - wxLogTrace(wxT("Function Start/End"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - Function Begin")); - int i, j, count, newColor; - TaskSelectionData *selData; - RESULT* result; - RESULT* ctrlResult; - PROJECT* project; - std::vectoris_alive; - bool needRefresh = false; - wxString resname; - CMainDocument* pDoc = wxGetApp().GetDocument(); - CSkinSimple* pSkinSimple = wxGetApp().GetSkinManager()->GetSimple(); - - wxASSERT(pDoc); - wxASSERT(pSkinSimple); - wxASSERT(wxDynamicCast(pSkinSimple, CSkinSimple)); - - 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; - } - - resname = wxEmptyString; -#if SELECTBYRESULTNAME - resname = wxString::FromUTF8(result->name); -#else - GetApplicationAndProjectNames(result, &resname, NULL); -#endif - - // loop through the items already in Task Selection Control to find this result - count = m_TaskSelectionCtrl->GetCount(); - 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 in the list then we have a new one! lets add it - if (!found) { - int alphaOrder; - for(j = 0; j < count; ++j) { - alphaOrder = (m_TaskSelectionCtrl->GetString(j)).CmpNoCase(resname); -#if SORTTASKLIST - if (alphaOrder > 0) { - break; // Insert the new item here (sorted by item label) - } -#endif - // wxComboBox and wxBitmapComboBox have bugs on Windows when multiple - // entries have identical text, so add enough spaces to make each - // entry's text unique. - if (alphaOrder == 0) { - resname.Append((const wxChar *)wxT(" ")); -#if !SORTTASKLIST - j = -1; // If not sorted, check new name from start for duplicate -#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; - FindSlideShowFiles(selData); - project = pDoc->state.lookup_project(result->project_url); - if (project) { - selData->project_files_downloaded_time = project->project_files_downloaded_time; - } else { - selData->project_files_downloaded_time = 0.0; - } - -#if SORTTASKLIST - if (j < count) { - std::vector::iterator iter = is_alive.begin(); - m_TaskSelectionCtrl->Insert(resname, wxNullBitmap, j, (void*)selData); - is_alive.insert(iter+j, true); - if (j <= m_CurrentTaskSelection) { - ++m_CurrentTaskSelection; - m_TaskSelectionCtrl->SetSelection(m_CurrentTaskSelection); - } - } else -#endif - { - m_TaskSelectionCtrl->Append(resname, wxNullBitmap, (void*)selData); - is_alive.push_back(true); - } - ++count; - } // End if (!found) - } // End for (i) loop - - // 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)) { - wxLogTrace(wxT("Function Status"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - Task '%d' no longer alive"), j); - selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(j); - wxLogTrace(wxT("Function Status"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - selData '%p' "), selData); - wxLogTrace(wxT("Function Status"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - result_name '%s' "), selData->result_name); - selData->slideShowFileNames.Clear(); - wxLogTrace(wxT("Function Status"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - Deleting selData")); - delete selData; - wxLogTrace(wxT("Function Status"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - Deleting control data")); - // Indicate to Delete() we have cleaned up the Selection Data - m_TaskSelectionCtrl->SetClientData(j, NULL); - m_TaskSelectionCtrl->Delete(j); - if (j == m_CurrentTaskSelection) { - int newCount = m_TaskSelectionCtrl->GetCount(); - if (m_CurrentTaskSelection < newCount) { - // Select the next item if one exists - m_TaskSelectionCtrl->SetSelection(m_CurrentTaskSelection); - } else if (newCount > 0) { - // Select the previous item if one exists - m_CurrentTaskSelection = newCount-1; - m_TaskSelectionCtrl->SetSelection(m_CurrentTaskSelection); - } else { - m_CurrentTaskSelection = -1; - m_TaskSelectionCtrl->SetSelection(wxNOT_FOUND); - } - m_bStableTaskInfoChanged = true; - needRefresh = true; - } else if (j < m_CurrentTaskSelection) { - --m_CurrentTaskSelection; - m_TaskSelectionCtrl->SetSelection(m_CurrentTaskSelection); - } - } - } - - if ((m_CurrentTaskSelection >= 0) && !m_bStableTaskInfoChanged) { - selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(m_CurrentTaskSelection); - project = pDoc->state.lookup_project(selData->project_url); - if ( project && (project->project_files_downloaded_time > selData->project_files_downloaded_time) ) { - FindSlideShowFiles(selData); - selData->project_files_downloaded_time = project->project_files_downloaded_time; - } - } - - 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 || ctrlResult->project_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 (reskin || (newColor != selData->dotColor)) { - switch (newColor) { - case greenDot: - m_TaskSelectionCtrl->SetItemBitmap(j, *pSkinSimple->GetWorkunitRunningImage()->GetBitmap()); - break; - case yellowDot: - m_TaskSelectionCtrl->SetItemBitmap(j, *pSkinSimple->GetWorkunitWaitingImage()->GetBitmap()); - break; - case redDot: - m_TaskSelectionCtrl->SetItemBitmap(j, *pSkinSimple->GetWorkunitSuspendedImage()->GetBitmap()); - break; - } - selData->dotColor = newColor; - needRefresh = true; - } - } - if (needRefresh) { - m_TaskSelectionCtrl->Refresh(); - } - wxLogTrace(wxT("Function Start/End"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - Function End")); -} - - -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")); - } - } -} - - -#ifdef __WXMAC__ -// Avoid unnecessary drawing due to Mac progress indicator's animation -void CSimpleTaskPanel::OnEraseBackground(wxEraseEvent& event) { - wxRect clipRect; - wxDC *dc = event.GetDC(); - - if (m_progressBarRect == NULL) { - m_progressBarRect = new wxRect(m_ProgressBar->GetRect()); - m_progressBarRect->Inflate(1, 0); - } - dc->GetClippingBox(&clipRect.x, &clipRect.y, &clipRect.width, &clipRect.height); - if (clipRect.IsEmpty() || m_progressBarRect->Contains(clipRect)) { - return; - } - - CSimplePanelBase::OnEraseBackground(event); -} -#endif +// 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 + +#define SORTTASKLIST 1 /* TRUE to sort task selection control alphabetically */ + +#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" + + +#define SLIDESHOWBORDER 3 +#define HIDEDEFAULTSLIDE 1 + +enum { redDot, yellowDot, greenDot }; + + +IMPLEMENT_DYNAMIC_CLASS(CTextBox, wxTextCtrl) + +BEGIN_EVENT_TABLE(CTextBox, wxTextCtrl) + EVT_ERASE_BACKGROUND(CTextBox::OnEraseBackground) +END_EVENT_TABLE() + +CTextBox::CTextBox() { +} + +CTextBox::CTextBox( wxWindow* parent) : + wxTextCtrl( parent, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY ) +{ + SetDefaultStyle(wxTextAttr(wxNullColour, wxColour(255, 255, 255, 0))); + SetBackgroundColour(wxColour(255, 255, 255, 0)); + +} + +void CTextBox::OnEraseBackground(wxEraseEvent& event) { + wxDC *dc = event.GetDC(); + wxRect r = GetRect(); + wxBitmap backgroundBitmap = ((CSimpleTaskPanel*)GetGrandParent())->GetBackgroundBmp().GetSubBitmap(r); + dc->DrawBitmap(backgroundBitmap, 0, 0); +//dc->SetBrush(*wxRED_BRUSH); +//dc->DrawRectangle(r.x, r.y, r.width, r.height); +} + + + +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() + +CSlideShowPanel::CSlideShowPanel() { +} + + +CSlideShowPanel::CSlideShowPanel( wxWindow* parent ) : + wxPanel( parent, wxID_ANY, wxDefaultPosition, wxSize(290+(2*SLIDESHOWBORDER), 126+(2*SLIDESHOWBORDER)), wxBORDER_NONE ) +{ + wxBoxSizer* bSizer1; + bSizer1 = new wxBoxSizer( wxVERTICAL ); + + m_institution = new CTransparentStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer1->Add( m_institution, 0, 0, 0 ); + m_scienceArea = new CTransparentStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); + bSizer1->Add( m_scienceArea, 0, 0, 0 ); +// m_description = new CTextBox( this ); + m_description = new wxTextCtrl( this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY ); +// m_description->SetDefaultStyle(wxTextAttr(*wxBLACK, wxColour(0,0,0,0))); + bSizer1->Add( m_description, 1, wxEXPAND, 0 ); + + this->SetSizer( bSizer1 ); + this->Layout(); + + m_SlideBitmap = wxNullBitmap; + m_bCurrentSlideIsDefault = false; + m_bGotAllProjectsList = false; + +#ifdef __WXMAC__ + // Tell accessibility aids to ignore this panel (but not its contents) + HIObjectSetAccessibilityIgnored((HIObjectRef)GetHandle(), true); +#endif + + m_ChangeSlideTimer = new wxTimer(this, ID_CHANGE_SLIDE_TIMER); + m_ChangeSlideTimer->Start(10000); +} + +CSlideShowPanel::~CSlideShowPanel() +{ + if ( m_ChangeSlideTimer->IsRunning() ) { + m_ChangeSlideTimer->Stop(); + } + delete m_ChangeSlideTimer; +} + + +void CSlideShowPanel::OnSlideShowTimer(wxTimerEvent& WXUNUSED(event)) { + AdvanceSlideShow(true, false); +} + + +void CSlideShowPanel::AdvanceSlideShow(bool changeSlide, bool reload) { + double xRatio, yRatio, ratio; + unsigned int i; + TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData(); + if (selData == NULL) return; + + if (reload) { + m_bCurrentSlideIsDefault = false; + selData->lastSlideShown = -1; + } + + int numSlides = (int)selData->slideShowFileNames.size(); + + if (numSlides <= 0) { +#if HIDEDEFAULTSLIDE + if (!reload) { + return; + } + wxRect r = GetRect(); + wxBitmap backgroundBitmap = ((CSimpleTaskPanel*)GetParent())->GetBackgroundBmp().GetSubBitmap(r); + wxWindowDC dc(this); + dc.DrawBitmap(backgroundBitmap, 0, 0); + + // Force redraws if text unchanged; hide all if not in all-projects list + m_institution->Show(false); + m_scienceArea->Show(false); + m_description->Show(false); + + if (!m_bGotAllProjectsList) { + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + + pDoc->rpc.get_all_projects_list(m_AllProjectsList); + m_bGotAllProjectsList = true; + } + + for (i=0; iurl.c_str(), selData->project_url)) { + m_institution->SetLabel(wxString(m_AllProjectsList.projects[i]->home.c_str(), wxConvUTF8)); + m_scienceArea->SetLabel(wxString(m_AllProjectsList.projects[i]->specific_area.c_str(), wxConvUTF8)); + m_description->SetValue(wxString(m_AllProjectsList.projects[i]->description.c_str(), wxConvUTF8)); + + m_institution->Show(true); + m_scienceArea->Show(true); + m_description->Show(true); + m_description->Enable(); + break; + } + } + return; +#else + SetBackgroundColour(*wxBLACK); + + if (m_bCurrentSlideIsDefault) return; + + CSkinSimple* pSkinSimple = wxGetApp().GetSkinManager()->GetSimple(); + wxASSERT(pSkinSimple); + wxASSERT(wxDynamicCast(pSkinSimple, CSkinSimple)); + + m_SlideBitmap = *pSkinSimple->GetWorkunitAnimationImage()->GetBitmap(); + if (m_SlideBitmap.Ok()) { + m_bCurrentSlideIsDefault = true; + } +#endif + } else { +#if HIDEDEFAULTSLIDE + m_institution->Show(false); + m_scienceArea->Show(false); + m_description->Show(false); +#endif + // TODO: Should we allow slide show to advance if task is not running? + int newSlide = selData->lastSlideShown; + + if (selData->dotColor == greenDot) { // Advance only if running + if (changeSlide) { + if (++newSlide >= numSlides) { + newSlide = 0; + } + } + } + if (newSlide < 0) { + newSlide = 0; + } + + if (selData->lastSlideShown != newSlide) { // Don't update if only one slide + + selData->lastSlideShown = newSlide; + + wxBitmap *bm = new wxBitmap(); + bm->LoadFile(selData->slideShowFileNames[newSlide], wxBITMAP_TYPE_ANY); + if (bm->Ok()) { + m_SlideBitmap = *bm; + delete bm; + 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); +#if HIDEDEFAULTSLIDE + int numSlides = 0; + TaskSelectionData* selData = ((CSimpleTaskPanel*)GetParent())->GetTaskSelectionData(); + if (selData) { + numSlides = (int)selData->slideShowFileNames.size(); + } + if (numSlides > 0) +#endif + { + int w, h; + wxPen oldPen = dc.GetPen(); + wxBrush oldBrush = dc.GetBrush(); + int oldMode = dc.GetBackgroundMode(); + wxPen bgPen(*wxLIGHT_GREY, 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 + ); + } + } +} + + +void CSlideShowPanel::OnEraseBackground(wxEraseEvent& event) { + wxDC *dc = event.GetDC(); + wxRect r = GetRect(); + wxBitmap backgroundBitmap = ((CSimpleTaskPanel*)GetParent())->GetBackgroundBmp().GetSubBitmap(r); + dc->DrawBitmap(backgroundBitmap, 0, 0); +} + + + + +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) +#ifdef __WXMAC__ + EVT_ERASE_BACKGROUND(CSimpleTaskPanel::OnEraseBackground) +#endif +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_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"); + m_progressBarRect = NULL; + + SetForegroundColour(*wxBLACK); + + wxBoxSizer* bSizer1; + bSizer1 = new wxBoxSizer( wxVERTICAL ); + + wxBoxSizer* bSizer2; + bSizer2 = new wxBoxSizer( wxHORIZONTAL ); + + m_myTasksLabel = new CTransparentStaticText( this, wxID_ANY, _("Tasks:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_myTasksLabel->Wrap( -1 ); + 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:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_TaskProjectLabel->Wrap( -1 ); + 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 ); + wxFont theFont = m_TaskProjectName->GetFont(); + theFont.SetWeight(wxFONTWEIGHT_BOLD); + m_TaskProjectName->SetFont(theFont); + 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 ); + + 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 ); + 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 ); + 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 optimizations in + // CSimpleGUIPanel::OnEraseBackground and CSimpleTaskPanel::OnEraseBackground. + m_ProgressBar = new wxGauge( this, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL ); + m_iPctDoneX10 = 1000; + m_ProgressBar->SetValue( 100 ); + 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.000%"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT | wxST_NO_AUTORESIZE ); + m_ProgressValueText->Wrap( -1 ); + 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 ); + 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(); +#ifdef __WXMAC__ + m_ProgressRect.Inflate(0, -2); + m_ProgressRect.Offset(0, -2); +#endif +} + + +CSimpleTaskPanel::~CSimpleTaskPanel() +{ + TaskSelectionData *selData; + int count = m_TaskSelectionCtrl->GetCount(); + for(int j = count-1; j >=0; --j) { + selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(j); + selData->slideShowFileNames.Clear(); + delete selData; + // Indicate to Clear() we have cleaned up the Selection Data + m_TaskSelectionCtrl->SetClientData(j, NULL); + } + m_TaskSelectionCtrl->Clear(); + + m_pulseTimer->Stop(); + delete m_pulseTimer; + + if (m_progressBarRect) { + delete m_progressBarRect; + } +} + + +void CSimpleTaskPanel::OnTaskSelection(wxCommandEvent& /*event*/) +{ + int sel = m_TaskSelectionCtrl->GetSelection(); + if (sel != m_CurrentTaskSelection) { + m_CurrentTaskSelection = sel; + m_bStableTaskInfoChanged = true; + UpdatePanel(); + } +} + + +void CSimpleTaskPanel::UpdatePanel(bool delayShow) { + wxString s = wxEmptyString; + wxString projName = wxEmptyString; + TaskSelectionData *selData; + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + int workCount = pDoc->GetSimpleGUIWorkCount(); + + // Workaround for Linux refresh problem + static bool wasDelayed = false; + +#ifndef __WXMAC__ + Freeze(); +#endif + + if ((workCount <= 0) || delayShow) { + if ((workCount != m_oldWorkCount) || delayShow) { + wasDelayed = true; + 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(); + if (m_iPctDoneX10 >= 0) { + m_iPctDoneX10 = -1; + m_ProgressBar->Pulse(); + m_pulseTimer->Start(100); + } + this->Layout(); + +#ifdef __WXMAC__ + m_ProgressRect = m_ProgressBar->GetRect(); + m_ProgressRect.Inflate(0, -2); + m_ProgressRect.Offset(0, -2); +#endif + } + + DisplayIdleState(); + + } else { + if ((m_oldWorkCount == 0) || wasDelayed) { + wasDelayed = false; + 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(); + this->Layout(); + +#ifdef __WXMAC__ + m_ProgressRect = m_ProgressBar->GetRect(); + m_ProgressRect.Inflate(0, -2); + m_ProgressRect.Offset(0, -2); +#endif + } + + UpdateTaskSelectionList(false); + + // 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, true); + 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)); + int pctDoneX10 = result->fraction_done * 1000.0; + if (m_iPctDoneX10 != pctDoneX10) { + if (m_iPctDoneX10 < 0) { + m_pulseTimer->Stop(); + } + int pctDone = pctDoneX10 / 10; + if (pctDone != (m_iPctDoneX10 / 10)) { + m_ProgressBar->SetValue(pctDone); + } + s.Printf(_("%.3f%%"), result->fraction_done*100); + m_iPctDoneX10 = pctDoneX10; + 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)); + if (m_iPctDoneX10 >= 0) { + m_iPctDoneX10 = -1; + 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() { + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleTaskPanel::ReskinInterface - Function Begin")); + CSimplePanelBase::ReskinInterface(); + m_SlideShowArea->AdvanceSlideShow(false, false); + UpdateTaskSelectionList(true); + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleTaskPanel::ReskinInterface - Function Begin")); +} + + +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 strGPUBuffer = wxEmptyString; + wxString pct_done_str = 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 (avp->ncudas) { + strGPUBuffer = wxString(" (NVIDIA GPU)", wxConvUTF8); + } + if (avp->natis) { + strGPUBuffer = wxString(" (ATI GPU)", wxConvUTF8); + } + + appName->Printf( + wxT("%s%s%s"), + state_result->project->anonymous_platform?_("Local: "):wxT(""), + strAppBuffer.c_str(), + strGPUBuffer.c_str() + ); + } + + 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: %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(_("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::FindSlideShowFiles(TaskSelectionData *selData) { + RESULT* state_result; + char urlDirectory[1024]; + char fileName[1024]; + char resolvedFileName[1024]; + int j; + CMainDocument* pDoc = wxGetApp().GetDocument(); + wxASSERT(pDoc); + + + selData->slideShowFileNames.Clear(); + state_result = pDoc->state.lookup_result(selData->result->project_url, selData->result->name); + if (!state_result) { + pDoc->ForceCacheUpdate(); + state_result = pDoc->state.lookup_result(selData->result->project_url, selData->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)) { + selData->slideShowFileNames.Add(wxString(resolvedFileName,wxConvUTF8)); + } + } else { + break; + } + } + + if ( selData->slideShowFileNames.size() == 0 ) { + 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)) { + selData->slideShowFileNames.Add(wxString(resolvedFileName,wxConvUTF8)); + } + } else { + break; + } + } + } + } + selData->lastSlideShown = -1; +} + + +void CSimpleTaskPanel::UpdateTaskSelectionList(bool reskin) { + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - Function Begin")); + int i, j, count, newColor; + TaskSelectionData *selData; + RESULT* result; + RESULT* ctrlResult; + PROJECT* project; + std::vectoris_alive; + bool needRefresh = false; + wxString resname; + CMainDocument* pDoc = wxGetApp().GetDocument(); + CSkinSimple* pSkinSimple = wxGetApp().GetSkinManager()->GetSimple(); + + wxASSERT(pDoc); + wxASSERT(pSkinSimple); + wxASSERT(wxDynamicCast(pSkinSimple, CSkinSimple)); + + 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; + } + + resname = wxEmptyString; +#if SELECTBYRESULTNAME + resname = wxString::FromUTF8(result->name); +#else + GetApplicationAndProjectNames(result, &resname, NULL); +#endif + + // loop through the items already in Task Selection Control to find this result + count = m_TaskSelectionCtrl->GetCount(); + 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 in the list then we have a new one! lets add it + if (!found) { + int alphaOrder; + for(j = 0; j < count; ++j) { + alphaOrder = (m_TaskSelectionCtrl->GetString(j)).CmpNoCase(resname); +#if SORTTASKLIST + if (alphaOrder > 0) { + break; // Insert the new item here (sorted by item label) + } +#endif + // wxComboBox and wxBitmapComboBox have bugs on Windows when multiple + // entries have identical text, so add enough spaces to make each + // entry's text unique. + if (alphaOrder == 0) { + resname.Append((const wxChar *)wxT(" ")); +#if !SORTTASKLIST + j = -1; // If not sorted, check new name from start for duplicate +#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; + FindSlideShowFiles(selData); + project = pDoc->state.lookup_project(result->project_url); + if (project) { + selData->project_files_downloaded_time = project->project_files_downloaded_time; + } else { + selData->project_files_downloaded_time = 0.0; + } + +#if SORTTASKLIST + if (j < count) { + std::vector::iterator iter = is_alive.begin(); + m_TaskSelectionCtrl->Insert(resname, wxNullBitmap, j, (void*)selData); + is_alive.insert(iter+j, true); + if (j <= m_CurrentTaskSelection) { + ++m_CurrentTaskSelection; + m_TaskSelectionCtrl->SetSelection(m_CurrentTaskSelection); + } + } else +#endif + { + m_TaskSelectionCtrl->Append(resname, wxNullBitmap, (void*)selData); + is_alive.push_back(true); + } + ++count; + } // End if (!found) + } // End for (i) loop + + // 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)) { + wxLogTrace(wxT("Function Status"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - Task '%d' no longer alive"), j); + selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(j); + wxLogTrace(wxT("Function Status"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - selData '%p' "), selData); + wxLogTrace(wxT("Function Status"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - result_name '%s' "), selData->result_name); + selData->slideShowFileNames.Clear(); + wxLogTrace(wxT("Function Status"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - Deleting selData")); + delete selData; + wxLogTrace(wxT("Function Status"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - Deleting control data")); + // Indicate to Delete() we have cleaned up the Selection Data + m_TaskSelectionCtrl->SetClientData(j, NULL); + m_TaskSelectionCtrl->Delete(j); + if (j == m_CurrentTaskSelection) { + int newCount = m_TaskSelectionCtrl->GetCount(); + if (m_CurrentTaskSelection < newCount) { + // Select the next item if one exists + m_TaskSelectionCtrl->SetSelection(m_CurrentTaskSelection); + } else if (newCount > 0) { + // Select the previous item if one exists + m_CurrentTaskSelection = newCount-1; + m_TaskSelectionCtrl->SetSelection(m_CurrentTaskSelection); + } else { + m_CurrentTaskSelection = -1; + m_TaskSelectionCtrl->SetSelection(wxNOT_FOUND); + } + m_bStableTaskInfoChanged = true; + needRefresh = true; + } else if (j < m_CurrentTaskSelection) { + --m_CurrentTaskSelection; + m_TaskSelectionCtrl->SetSelection(m_CurrentTaskSelection); + } + } + } + + if ((m_CurrentTaskSelection >= 0) && !m_bStableTaskInfoChanged) { + selData = (TaskSelectionData*)m_TaskSelectionCtrl->GetClientData(m_CurrentTaskSelection); + project = pDoc->state.lookup_project(selData->project_url); + if ( project && (project->project_files_downloaded_time > selData->project_files_downloaded_time) ) { + FindSlideShowFiles(selData); + selData->project_files_downloaded_time = project->project_files_downloaded_time; + } + } + + 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 || ctrlResult->project_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 (reskin || (newColor != selData->dotColor)) { + switch (newColor) { + case greenDot: + m_TaskSelectionCtrl->SetItemBitmap(j, *pSkinSimple->GetWorkunitRunningImage()->GetBitmap()); + break; + case yellowDot: + m_TaskSelectionCtrl->SetItemBitmap(j, *pSkinSimple->GetWorkunitWaitingImage()->GetBitmap()); + break; + case redDot: + m_TaskSelectionCtrl->SetItemBitmap(j, *pSkinSimple->GetWorkunitSuspendedImage()->GetBitmap()); + break; + } + selData->dotColor = newColor; + needRefresh = true; + } + } + if (needRefresh) { + m_TaskSelectionCtrl->Refresh(); + } + wxLogTrace(wxT("Function Start/End"), wxT("CSimpleTaskPanel::UpdateTaskSelectionList - Function End")); +} + + +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")); + } + } +} + + +#ifdef __WXMAC__ +// Avoid unnecessary drawing due to Mac progress indicator's animation +void CSimpleTaskPanel::OnEraseBackground(wxEraseEvent& event) { + wxRect clipRect; + wxDC *dc = event.GetDC(); + + if (m_progressBarRect == NULL) { + m_progressBarRect = new wxRect(m_ProgressBar->GetRect()); + m_progressBarRect->Inflate(1, 0); + } + dc->GetClippingBox(&clipRect.x, &clipRect.y, &clipRect.width, &clipRect.height); + if (clipRect.IsEmpty() || m_progressBarRect->Contains(clipRect)) { + return; + } + + CSimplePanelBase::OnEraseBackground(event); +} +#endif diff --git a/clientgui/sg_TaskPanel.h b/clientgui/sg_TaskPanel.h index 3d05cc8ee8..c07625a571 100755 --- a/clientgui/sg_TaskPanel.h +++ b/clientgui/sg_TaskPanel.h @@ -38,6 +38,25 @@ typedef struct { /////////////////////////////////////////////////////////////////////////// +/// Class CTextBox +/////////////////////////////////////////////////////////////////////////////// +class CTextBox : public wxTextCtrl +{ + DECLARE_DYNAMIC_CLASS( CTextBox ) + DECLARE_EVENT_TABLE() + public: + CTextBox(); + CTextBox( wxWindow* parent); + + void OnEraseBackground(wxEraseEvent& event); + virtual bool HasTransparentBackground() { return true; }; +}; + + + +/////////////////////////////////////////////////////////////////////////// +/// Class CSlideShowPanel +/////////////////////////////////////////////////////////////////////////////// class CSlideShowPanel : public wxPanel { @@ -52,12 +71,17 @@ class CSlideShowPanel : public wxPanel void OnSlideShowTimer(wxTimerEvent& WXUNUSED(event)); void AdvanceSlideShow(bool changeSlide, bool reload); void OnPaint(wxPaintEvent& WXUNUSED(event)); + void OnEraseBackground(wxEraseEvent& event); private: + CTransparentStaticText* m_institution; + CTransparentStaticText* m_scienceArea; + wxTextCtrl* m_description; wxTimer* m_ChangeSlideTimer; wxBitmap m_SlideBitmap; bool m_bCurrentSlideIsDefault; - + bool m_bGotAllProjectsList; + ALL_PROJECTS_LIST m_AllProjectsList; };