boinc/clientgui/BOINCGridCtrl.cpp

305 lines
8.9 KiB
C++
Raw Normal View History

// 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);
}