2006-12-27 18:33:44 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2006-12-29 21:55:23 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-12-27 18:33:44 +00:00
|
|
|
/* ############# */
|
|
|
|
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) {
|
2006-12-29 21:55:23 +00:00
|
|
|
DoProgressDrawing(grid,attr,dc,rect,row,col,isSelected);
|
2006-12-27 18:33:44 +00:00
|
|
|
}
|
2006-12-29 21:55:23 +00:00
|
|
|
else {
|
2006-12-27 18:33:44 +00:00
|
|
|
wxGridCellStringRenderer::Draw(grid,attr,dc,rect,row,col,isSelected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-29 21:55:23 +00:00
|
|
|
void CBOINCGridCellProgressRenderer::DoProgressDrawing(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc, const wxRect& rectCell, int row, int col, bool isSelected) {
|
2006-12-27 18:33:44 +00:00
|
|
|
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();
|
2006-12-29 21:55:23 +00:00
|
|
|
dc.SetBrush(*wxLIGHT_GREY_BRUSH);
|
2006-12-27 18:33:44 +00:00
|
|
|
dc.DrawRectangle(p1);
|
|
|
|
dc.SetBrush(old);
|
|
|
|
dc.DrawRectangle(p2);
|
|
|
|
dc.DestroyClippingRegion();
|
|
|
|
grid.DrawTextRectangle(dc, strValue, rect, hAlign, vAlign);
|
|
|
|
}
|