// Berkeley Open Infrastructure for Network Computing // http://boinc.berkeley.edu // Copyright (C) 2005 University of California // // This 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 2.1 of the License, or (at your option) any later version. // // This software 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. // // To view the GNU Lesser General Public License visit // http://www.gnu.org/copyleft/lesser.html // or write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #if defined(__GNUG__) && !defined(__APPLE__) #pragma implementation "sg_BoincSimpleGUI.h" #endif #include "stdwx.h" #include "BOINCGUIApp.h" #include "Events.h" #include "BOINCBaseFrame.h" #include "sg_BoincSimpleGUI.h" #include "sg_SkinClass.h" #include "sg_ImageLoader.h" #include "sg_ProjectsComponent.h" #include "sg_ClientStateIndicator.h" #include "sg_StatImageLoader.h" #include "sg_ViewTabPage.h" #include "wizardex.h" #include "BOINCWizards.h" #include "BOINCBaseWizard.h" #include "WizardAttachProject.h" #include "WizardAccountManager.h" #include "error_numbers.h" #include #include "res/boinc.xpm" IMPLEMENT_DYNAMIC_CLASS(CSimpleFrame, CBOINCBaseFrame) BEGIN_EVENT_TABLE(CSimpleFrame, CBOINCBaseFrame) EVT_BUTTON(-1,CSimpleFrame::OnBtnClick) EVT_SIZE(CSimpleFrame::OnSize) EVT_ERASE_BACKGROUND(CSimpleFrame::OnEraseBackground) EVT_FRAME_CONNECT(CSimpleFrame::OnConnect) EVT_TIMER(ID_SIMPLEFRAMERENDERTIMER, CSimpleFrame::OnFrameRender) EVT_FLATNOTEBOOK_PAGE_CHANGED(-1, CSimpleFrame::OnPageChanged) END_EVENT_TABLE() CSimpleFrame::CSimpleFrame() { wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::CSimpleFrame - Default Constructor Function Begin")); wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::CSimpleFrame - Default Constructor Function End")); } CSimpleFrame::CSimpleFrame(wxString title, wxIcon* icon) : CBOINCBaseFrame((wxFrame *)NULL, ID_SIMPLEFRAME, title, wxDefaultPosition, wxSize(416, 600), wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE) { wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::CSimpleFrame - Overloaded Constructor Function Begin")); RestoreState(); // Initialize Application SetIcon(*icon); //init app skin class appSkin = SkinClass::Instance(); appSkin->init_skin(skinName); m_ImageList.push_back(*(appSkin->GetIcnWorkingWkUnit())); projectViewInitialized = false; resultViewInitialized = false; emptyViewInitialized = false; notebookViewInitialized = false; dlgOpen = false; //set polling timer for interface m_pFrameRenderTimer = new wxTimer(this, ID_SIMPLEFRAMERENDERTIMER); wxASSERT(m_pFrameRenderTimer); m_pFrameRenderTimer->Start(1000); // Send event every 1 second InitEmptyView(); wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::CSimpleFrame - Overloaded Constructor Function End")); } CSimpleFrame::~CSimpleFrame() { wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::CSimpleFrame - Destructor Function Begin")); wxASSERT(m_pFrameRenderTimer); SaveState(); if (m_pFrameRenderTimer) { m_pFrameRenderTimer->Stop(); delete m_pFrameRenderTimer; } wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::CSimpleFrame - Destructor Function End")); } bool CSimpleFrame::RestoreState() { CBOINCBaseFrame::RestoreState(); wxConfigBase* pConfig = wxConfigBase::Get(FALSE); wxString strBaseConfigLocation = wxString(wxT("/")); wxASSERT(pConfig); skinName = wxT("default"); // 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; // // Restore Frame State // pConfig->SetPath(strBaseConfigLocation); pConfig->Read(wxT("Skin"), &skinName, wxT("default")); return true; } bool CSimpleFrame::SaveState() { CBOINCBaseFrame::SaveState(); wxConfigBase* pConfig = wxConfigBase::Get(FALSE); wxString strBaseConfigLocation = wxString(wxT("/")); 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("Skin"), skinName); return true; } void CSimpleFrame::OnConnect(CFrameEvent& WXUNUSED(event)) { wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnConnect - Function Begin")); CMainDocument* pDoc = wxGetApp().GetDocument(); CWizardAccountManager* pAMWizard = NULL; CWizardAttachProject* pAPWizard = NULL; wxString strComputer = wxEmptyString; wxString strName = wxEmptyString; wxString strURL = wxEmptyString; bool bCachedCredentials = false; ACCT_MGR_INFO ami; PROJECT_INIT_STATUS pis; wxASSERT(pDoc); wxASSERT(wxDynamicCast(pDoc, CMainDocument)); // 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(); } pDoc->rpc.acct_mgr_info(ami); if (ami.acct_mgr_url.size() && !ami.have_credentials) { pAMWizard = new CWizardAccountManager(this); if (!IsShown()) { Show(); } if (pAMWizard->Run()) { // If successful, hide the main window Hide(); } } else if (0 >= pDoc->GetProjectCount()) { pAPWizard = new CWizardAttachProject(this); if (!IsShown()) { Show(); } pDoc->rpc.get_project_init_status(pis); strName = wxString(pis.name.c_str(), wxConvUTF8); strURL = wxString(pis.url.c_str(), wxConvUTF8); bCachedCredentials = pis.url.length() && pis.has_account_key; pAPWizard->Run(strName, strURL, bCachedCredentials); } if (pAMWizard) pAMWizard->Destroy(); if (pAPWizard){ pAPWizard->Destroy(); //update Project Component projComponent->UpdateInterface(); } wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnConnect - Function End")); } void CSimpleFrame::OnProjectsAttachToProject() { wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::OnProjectsAttachToProject - Function Begin")); CMainDocument* pDoc = wxGetApp().GetDocument(); wxASSERT(pDoc); wxASSERT(wxDynamicCast(pDoc, CMainDocument)); if (!pDoc->IsUserAuthorized()) return; if (pDoc->IsConnected()) { m_pFrameRenderTimer->Stop(); CWizardAttachProject* pWizard = new CWizardAttachProject(this); wxString strName = wxEmptyString; wxString strURL = wxEmptyString; pWizard->Run( strName, strURL, false ); if (pWizard) pWizard->Destroy(); m_pFrameRenderTimer->Start(); } else { ShowNotCurrentlyConnectedAlert(); } wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::OnProjectsAttachToProject - Function End")); } void CSimpleFrame::OnFrameRender(wxTimerEvent& WXUNUSED(event)) { // State changes can cause the BSG to crash if a dialogue is open. // Only do the min updates if a dialogue is open if ( dlgOpen ) return; CMainDocument* pDoc = wxGetApp().GetDocument(); if (!projectViewInitialized && pDoc->IsConnected()) { InitProjectView(); } else if ( pDoc->IsConnected() ) { UpdateProjectView(); } // Now check to see if we show the empty state or results if ( pDoc->GetSimpleGUIWorkCount() > 0 ) { // If empty was displayed, remove if ( emptyViewInitialized ) { DestroyEmptyView(); } // If we hadn't previously shown the results, create them. if ( !resultViewInitialized ) { Freeze(); InitResultView(); UpdateResultView(); Thaw(); } else { UpdateResultView(); } } else { if ( resultViewInitialized ) { DestroyNotebook(); } if ( !emptyViewInitialized ) { InitEmptyView(); } UpdateEmptyView(); } } void CSimpleFrame::UpdateEmptyView() { clientState->DisplayState(); } void CSimpleFrame::DestroyEmptyView() { delete clientState; emptyViewInitialized = false; } void CSimpleFrame::InitEmptyView() { //Set Background color SetBackgroundColour(appSkin->GetAppBgCol()); // Flex Grid Sizer mainSizer = new wxFlexGridSizer(3,2); SetSizer(mainSizer); clientState = new ClientStateIndicator(this,wxPoint(31,124)); clientState->DisplayState(); emptyViewInitialized = true; } void CSimpleFrame::UpdateProjectView() { //update Project Component projComponent->UpdateInterface(); } void CSimpleFrame::InitResultView() { SetSizer(mainSizer); mainSizer->Add(31, 98,0); mainSizer->Add(343, 98,0); mainSizer->Add(31, 98,0); mainSizer->Add(0, 0,1); mainSizer->Layout(); resultViewInitialized=true; //present any results available UpdateResultView(); //make sure the first tab is in front if (m_windows.size() > 0 ) { wrkUnitNB->SetSelection(0); } } void CSimpleFrame::DestroyNotebook() { mainSizer->Detach(wrkUnitNB); delete wrkUnitNB; m_windows.clear(); resultViewInitialized = false; notebookViewInitialized = false; } void CSimpleFrame::InitProjectView() { // Do not update screen at this point Freeze(); /////////////// MY PROJECTS COMPONENT ///////////////////// projComponent = new CProjectsComponent(this,wxPoint(31,443)); /////////////////////////////////////////////////////////// Thaw(); projectViewInitialized = true; } void CSimpleFrame::UpdateResultView(){ CMainDocument* pDoc = wxGetApp().GetDocument(); //update GUI wxString strBuffer = wxEmptyString; //assume they are all inactive for(int x = 0; x < (int)m_windows.size(); x ++) { CViewTabPage *currTab = m_windows[x]; currTab->isAlive = false; } // Update Tabs RESULT* result; for(int i = 0; i < (int) pDoc->results.results.size(); i++){ result = pDoc->result(i); if ( result == NULL || !result->active_task ) { continue; } // get tab window bool found = false; for(int j = 0; j < (int)m_windows.size(); j++) { CViewTabPage *currTab = m_windows[j]; //std::string curtabname = currTab->GetTabName(); //std::string resultname = result->name; if(result->name == currTab->GetTabName()){ //currTab FOUND; currTab->isAlive = true; currTab->resultWU = result; found = true; //update tab interface currTab->UpdateInterface(); if(result->active_task_state == 1 && wrkUnitNB->GetPageImageIndex(j) != 0){ wrkUnitNB->SetPageImageIndex(j, 0); // this is working process } else if ( result->active_task_state != 1 && wrkUnitNB->GetPageImageIndex(j) != -1 ) { wrkUnitNB->SetPageImageIndex(j, -1); // this is working process } //break; } } if(!found){ // First check to see if the underlying state object contains this data // if not, then force an update and skip this result for now. RESULT* resState = NULL; std::string projUrl = result->project_url; std::string nme = result->name; resState = pDoc->state.lookup_result(projUrl, nme); if(!resState){ pDoc->ForceCacheUpdate(); continue; } wxString appShortName = wxString(resState->app->name.c_str(), wxConvUTF8 ); bool addNotebookToSizer = false; //stop timer untill we add the page m_pFrameRenderTimer->Stop(); // Do not update screen at this point Freeze(); //Check if notebook was initialized if(!notebookViewInitialized){ //init nootebok InitNotebook(); addNotebookToSizer = true; // since this is first page } // create one and add it to notebook std::string index = " "; //index += i; appShortName += wxString(index.c_str(), wxConvUTF8 ); CViewTabPage *wTab = new CViewTabPage(wrkUnitNB,result,nme,projUrl); wrkUnitNB->AddPage(wTab, appShortName, true); if(result->active_task_state == 1){ int pageIndex = wrkUnitNB->GetPageIndex(wTab); wrkUnitNB->SetPageImageIndex(pageIndex, 0); // this is working process } //add page to vector m_windows.push_back(wTab); if(addNotebookToSizer){ wrkUnitNB->SetSelection(0); // Put Grid in the sizer mainSizer->Add(wrkUnitNB); } //Update screen Thaw(); mainSizer->Layout(); //start the timer m_pFrameRenderTimer->Start(); } } //delete the ones that are not alive //assume they are all inactive int deleteIndex = 0; for(int x = 0; x < (int)m_windows.size(); x ++) { CViewTabPage *currTab = m_windows[x]; if(!currTab->isAlive){ //delete the notebook page wrkUnitNB->DeletePage(deleteIndex); //delete the page in vector m_windows.erase(m_windows.begin()+x); }else{ deleteIndex++; } } // Refresh(); } void CSimpleFrame::InitNotebook() { wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::InitNotebook - Function Start")); // FlatNotebook wrkUnitNB = new wxFlatNotebook(this, -1, wxDefaultPosition, wxSize(370,330), wxFNB_TABS_BORDER_SIMPLE | wxFNB_NO_X_BUTTON | wxFNB_NO_NAV_BUTTONS | wxFNB_FANCY_TABS); wrkUnitNB->SetUseBackground(true); wrkUnitNB->SetBackgroundColour(appSkin->GetAppBgCol()); wrkUnitNB->SetTabAreaColour(appSkin->GetAppBgCol()); wrkUnitNB->SetGradientColors(appSkin->GetTabFromColAc(),appSkin->GetTabToColAc(),appSkin->GetTabBrdColAc()); wrkUnitNB->SetActiveTabTextColour(wxColour(255,255,255)); wrkUnitNB->SetGradientColorsInactive(appSkin->GetTabFromColIn(),appSkin->GetTabToColIn(),appSkin->GetTabBrdColIn()); wrkUnitNB->SetNonActiveTabTextColour(wxColour(255,255,255)); wrkUnitNB->SetImageList(&m_ImageList); notebookViewInitialized = true; wxLogTrace(wxT("Function Start/End"), wxT("CAdvancedFrame::InitNotebook - Function End")); } /// void CSimpleFrame::ReskinAppGUI(){ wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::ReskinAppGUI - Function Start")); //bg color m_ImageList.push_back(*(appSkin->GetIcnWorkingWkUnit())); SetBackgroundColour(appSkin->GetAppBgCol()); if(notebookViewInitialized){ // notebook tab color wrkUnitNB->SetTabAreaColour(appSkin->GetAppBgCol()); wrkUnitNB->SetUseBackground(true); wrkUnitNB->SetGradientColors(appSkin->GetTabFromColAc(),appSkin->GetTabToColAc(),appSkin->GetTabBrdColAc()); wrkUnitNB->SetGradientColorsInactive(appSkin->GetTabFromColIn(),appSkin->GetTabToColIn(),appSkin->GetTabBrdColIn()); // notebook pages for(int i = 0; i < (int)m_windows.size(); i++){ CViewTabPage *wTab = m_windows.at(i); wTab->ReskinInterface(); } } else { clientState->ReskinInterface(); } //reskin component projComponent->ReskinInterface(); Refresh(); wxLogTrace(wxT("Function Start/End"), wxT("CSimpleFrame::ReskinAppGUI - Function End")); } void CSimpleFrame::OnBtnClick(wxCommandEvent& event){ //init function wxObject *m_wxBtnObj = event.GetEventObject(); } //end function void CSimpleFrame::OnPageChanged(wxFlatNotebookEvent& WXUNUSED(event)) { // btnCollapse->Refresh(); } void CSimpleFrame::OnEraseBackground(wxEraseEvent& event){ wxObject *m_wxWin = event.GetEventObject(); if(m_wxWin==this){event.Skip(true);DrawBackImg(event,this,appSkin->GetAppBg(),0);return;} event.Skip(true); } void CSimpleFrame::DrawBackImg(wxEraseEvent& event,wxWindow *win,wxBitmap* bitMap,int opz){ event.Skip(false); wxDC *dc; dc=event.GetDC(); dc->SetBackground(wxBrush(win->GetBackgroundColour(),wxSOLID)); dc->Clear(); switch (opz) { case 0:{ dc->DrawBitmap(*bitMap, 0, 0); break;} case 1:{ wxRect rec=win->GetClientRect(); rec.SetLeft((rec.GetWidth()-bitMap->GetWidth()) / 2); rec.SetTop ((rec.GetHeight()-bitMap->GetHeight()) / 2); dc->DrawBitmap(*bitMap,rec.GetLeft(),rec.GetTop(),0); break;} case 2:{ wxRect rec=win->GetClientRect(); for(int y=0;y < rec.GetHeight();y+=bitMap->GetHeight()){ for(int x=0;x < rec.GetWidth();x+=bitMap->GetWidth()){ dc->DrawBitmap(*bitMap,x,y,0); } } break;} } }