// 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 "BOINCGridCtrl.h" #endif #include "stdwx.h" #include "BOINCGridCtrl.h" CBOINCGridCtrl::CBOINCGridCtrl( wxWindow* parent, wxWindowID iGridWindowID ) : wxGrid( parent, iGridWindowID) { } CBOINCGridCtrl::~CBOINCGridCtrl() { } int CBOINCGridCtrl::GetFirstSelectedRow() { int ret= -1; //Row mode ? wxArrayInt selRows = this->GetSelectedRows(); if(selRows.size() >0) { return selRows[0]; } //block mode ? wxGridCellCoordsArray selBlocks = this->GetSelectionBlockTopLeft(); if(selBlocks.size()>0) { return selBlocks[0].GetRow(); } //cell mode wxGridCellCoordsArray selCells = this->GetSelectionBlockTopLeft(); if(selCells.size()>0) { return selCells[0].GetRow(); } return ret; } bool CBOINCGridCtrl::OnSaveState(wxConfigBase* pConfig) { wxString strBaseConfigLocation = wxEmptyString; wxInt32 iIndex = 0; wxInt32 iColumnCount = this->GetCols(); wxASSERT(pConfig); // Retrieve the base location to store configuration information // Should be in the following form: "/Projects/" strBaseConfigLocation = pConfig->GetPath() + wxT("/"); // Cycle through the columns recording anything interesting for (iIndex = 0; iIndex < iColumnCount; iIndex++) { wxString label = this->GetColLabelValue(iIndex); pConfig->SetPath(strBaseConfigLocation + label); pConfig->Write(wxT("Width"), this->GetColumnWidth(iIndex)); } return true; } bool CBOINCGridCtrl::OnRestoreState(wxConfigBase* pConfig) { wxString strBaseConfigLocation = wxEmptyString; wxInt32 iIndex = 0; wxInt32 iTempValue = 0; wxInt32 iColumnCount = this->GetCols(); wxASSERT(pConfig); // Retrieve the base location to store configuration information // Should be in the following form: "/Projects/" strBaseConfigLocation = pConfig->GetPath() + wxT("/"); // Cycle through the columns recording anything interesting for (iIndex = 0; iIndex < iColumnCount; iIndex++) { wxString label = this->GetColLabelValue(iIndex); pConfig->SetPath(strBaseConfigLocation + label); pConfig->Read(wxT("Width"), &iTempValue, -1); if (-1 != iTempValue) { this->SetColumnWidth(iIndex,iTempValue); } } return true; } void CBOINCGridCtrl::SetColAlignment(int col,int hAlign,int vAlign) { wxGridCellAttr *attr = m_table->GetAttr(-1, col, wxGridCellAttr::Col ); if(!attr) { attr = new wxGridCellAttr; } attr->SetAlignment(hAlign,vAlign); SetColAttr(col, attr); } void CBOINCGridCtrl::DrawTextRectangle( wxDC& dc, const wxArrayString& lines, const wxRect& rect, int horizAlign, int vertAlign, int textOrientation ) { long textWidth, textHeight; long lineWidth, lineHeight; int nLines; dc.SetClippingRegion( rect ); nLines = lines.GetCount(); if( nLines > 0 ) { int l; float x = 0.0, y = 0.0; if( textOrientation == wxHORIZONTAL ) GetTextBoxSize(dc, lines, &textWidth, &textHeight); else GetTextBoxSize( dc, lines, &textHeight, &textWidth ); switch( vertAlign ) { case wxALIGN_BOTTOM: if( textOrientation == wxHORIZONTAL ) y = rect.y + (rect.height - textHeight - 1); else x = rect.x + rect.width - textWidth; break; case wxALIGN_CENTRE: if( textOrientation == wxHORIZONTAL ) y = rect.y + ((rect.height - textHeight)/2); else x = rect.x + ((rect.width - textWidth)/2); break; case wxALIGN_TOP: default: if( textOrientation == wxHORIZONTAL ) y = rect.y + 1; else x = rect.x + 1; break; } // Align each line of a multi-line label for( l = 0; l < nLines; l++ ) { dc.GetTextExtent(lines[l], &lineWidth, &lineHeight); switch( horizAlign ) { case wxALIGN_RIGHT: if( textOrientation == wxHORIZONTAL ) x = rect.x + (rect.width - lineWidth - 1); else y = rect.y + lineWidth + 1; break; case wxALIGN_CENTRE: if( textOrientation == wxHORIZONTAL ) x = rect.x + ((rect.width - lineWidth)/2); else y = rect.y + rect.height - ((rect.height - lineWidth)/2); break; case wxALIGN_LEFT: default: if( textOrientation == wxHORIZONTAL ) x = rect.x + 1; else y = rect.y + rect.height - 1; break; } if( textOrientation == wxHORIZONTAL ) { wxString formattedText = FormatTextWithEllipses(dc,lines[l],rect.width); dc.DrawText( formattedText, (int)x, (int)y ); y += lineHeight; } else { dc.DrawRotatedText( lines[l], (int)x, (int)y, 90.0 ); x += lineHeight; } } } dc.DestroyClippingRegion(); } wxString CBOINCGridCtrl::FormatTextWithEllipses(wxDC& dc,const wxString &text,int width) { wxString retText; wxString drawntext, ellipsis; wxCoord w, h, base_w; wxListItem item; // determine if the string can fit inside the current width dc.GetTextExtent(text, &w, &h); if (w <= width) { retText = text; } else // otherwise, truncate and add an ellipsis if possible { // determine the base width ellipsis = wxString(wxT("...")); dc.GetTextExtent(ellipsis, &base_w, &h); // continue until we have enough space or only one character left wxCoord w_c, h_c; size_t len = text.Length(); drawntext = text.Left(len); while (len > 1) { dc.GetTextExtent(drawntext.Last(), &w_c, &h_c); drawntext.RemoveLast(); len--; w -= w_c; if (w + base_w <= width) break; } // if still not enough space, remove ellipsis characters while (ellipsis.Length() > 0 && w + base_w > width) { ellipsis = ellipsis.Left(ellipsis.Length() - 1); dc.GetTextExtent(ellipsis, &base_w, &h); } // now draw the text retText = drawntext + ellipsis; } return retText; } /* ############# */ CBOINCGridCellProgressRenderer::CBOINCGridCellProgressRenderer(int col) : wxGridCellStringRenderer() { column = col; } void CBOINCGridCellProgressRenderer::Draw(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rect, int row, int col, bool isSelected) { if(col==column) { DoProgressDrawing(grid,attr,dc,rect,row,col,isSelected); } else { wxGridCellStringRenderer::Draw(grid,attr,dc,rect,row,col,isSelected); } } void CBOINCGridCellProgressRenderer::DoProgressDrawing(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rectCell, int row, int col, bool isSelected) { wxRect rect = rectCell; rect.Inflate(-1); // erase only this cells background, overflow cells should have been erased wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected); int hAlign, vAlign; attr.GetAlignment(&hAlign, &vAlign); // now we only have to draw the text SetTextColoursAndFont(grid, attr, dc, isSelected); wxString value = grid.GetCellValue(row,col); wxString strValue = value + " %"; double dv = atof(value); wxRect p1(rect); wxRect p2(rect); int r = (int)((rect.GetRight()-rect.GetLeft())*dv / 100.0); p1.SetRight(rect.GetLeft()+r); p2.SetLeft(rect.GetLeft()+r+1); dc.SetClippingRegion(rect); wxBrush old = dc.GetBrush(); dc.SetBrush(*wxLIGHT_GREY_BRUSH); dc.DrawRectangle(p1); dc.SetBrush(old); dc.DrawRectangle(p2); dc.DestroyClippingRegion(); grid.DrawTextRectangle(dc, strValue, rect, hAlign, vAlign); }