added renderers/editors for long/float, not fully tested yet, but seems to
work - see the demo in the (updated) sample git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6210 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -32,6 +32,10 @@
|
|||||||
#include "wx/dynarray.h"
|
#include "wx/dynarray.h"
|
||||||
#include "wx/timer.h"
|
#include "wx/timer.h"
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// constants
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Default parameters for wxGrid
|
// Default parameters for wxGrid
|
||||||
//
|
//
|
||||||
#define WXGRID_DEFAULT_NUMBER_ROWS 10
|
#define WXGRID_DEFAULT_NUMBER_ROWS 10
|
||||||
@@ -49,6 +53,15 @@
|
|||||||
#define WXGRID_MIN_COL_WIDTH 15
|
#define WXGRID_MIN_COL_WIDTH 15
|
||||||
#define WXGRID_DEFAULT_SCROLLBAR_WIDTH 16
|
#define WXGRID_DEFAULT_SCROLLBAR_WIDTH 16
|
||||||
|
|
||||||
|
// type names for grid table values
|
||||||
|
#define wxGRID_VALUE_STRING _T("string")
|
||||||
|
#define wxGRID_VALUE_BOOL _T("bool")
|
||||||
|
#define wxGRID_VALUE_NUMBER _T("long")
|
||||||
|
#define wxGRID_VALUE_FLOAT _T("double")
|
||||||
|
|
||||||
|
#define wxGRID_VALUE_TEXT wxGRID_VALUE_STRING
|
||||||
|
#define wxGRID_VALUE_LONG wxGRID_VALUE_NUMBER
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// forward declarations
|
// forward declarations
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -65,6 +78,7 @@ class WXDLLEXPORT wxGridTypeRegistry;
|
|||||||
|
|
||||||
class WXDLLEXPORT wxCheckBox;
|
class WXDLLEXPORT wxCheckBox;
|
||||||
class WXDLLEXPORT wxTextCtrl;
|
class WXDLLEXPORT wxTextCtrl;
|
||||||
|
class WXDLLEXPORT wxSpinCtrl;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxGridCellRenderer: this class is responsible for actually drawing the cell
|
// wxGridCellRenderer: this class is responsible for actually drawing the cell
|
||||||
@@ -90,6 +104,9 @@ public:
|
|||||||
const wxRect& rect,
|
const wxRect& rect,
|
||||||
int row, int col,
|
int row, int col,
|
||||||
bool isSelected) = 0;
|
bool isSelected) = 0;
|
||||||
|
|
||||||
|
// virtual dtor for any base class
|
||||||
|
virtual ~wxGridCellRenderer();
|
||||||
};
|
};
|
||||||
|
|
||||||
// the default renderer for the cells containing string data
|
// the default renderer for the cells containing string data
|
||||||
@@ -103,13 +120,59 @@ public:
|
|||||||
const wxRect& rect,
|
const wxRect& rect,
|
||||||
int row, int col,
|
int row, int col,
|
||||||
bool isSelected);
|
bool isSelected);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// set the text colours before drawing
|
||||||
|
void SetTextColoursAndFont(wxGrid& grid,
|
||||||
|
wxGridCellAttr& attr,
|
||||||
|
wxDC& dc,
|
||||||
|
bool isSelected);
|
||||||
|
};
|
||||||
|
|
||||||
|
// the default renderer for the cells containing numeric (long) data
|
||||||
|
class WXDLLEXPORT wxGridCellNumberRenderer : public wxGridCellStringRenderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// draw the string right aligned
|
||||||
|
virtual void Draw(wxGrid& grid,
|
||||||
|
wxGridCellAttr& attr,
|
||||||
|
wxDC& dc,
|
||||||
|
const wxRect& rect,
|
||||||
|
int row, int col,
|
||||||
|
bool isSelected);
|
||||||
|
};
|
||||||
|
|
||||||
|
class WXDLLEXPORT wxGridCellFloatRenderer : public wxGridCellStringRenderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wxGridCellFloatRenderer(int width, int precision);
|
||||||
|
|
||||||
|
// get/change formatting parameters
|
||||||
|
int GetWidth() const { return m_width; }
|
||||||
|
void SetWidth(int width) { m_width = width; }
|
||||||
|
int GetPrecision() const { return m_precision; }
|
||||||
|
void SetPrecision(int precision) { m_precision = precision; }
|
||||||
|
|
||||||
|
// draw the string right aligned with given width/precision
|
||||||
|
virtual void Draw(wxGrid& grid,
|
||||||
|
wxGridCellAttr& attr,
|
||||||
|
wxDC& dc,
|
||||||
|
const wxRect& rect,
|
||||||
|
int row, int col,
|
||||||
|
bool isSelected);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// formatting parameters
|
||||||
|
int m_width,
|
||||||
|
m_precision;
|
||||||
|
|
||||||
|
wxString m_format;
|
||||||
};
|
};
|
||||||
|
|
||||||
// renderer for boolean fields
|
// renderer for boolean fields
|
||||||
class WXDLLEXPORT wxGridCellBoolRenderer : public wxGridCellRenderer
|
class WXDLLEXPORT wxGridCellBoolRenderer : public wxGridCellRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// draw a check mark or nothing
|
// draw a check mark or nothing
|
||||||
virtual void Draw(wxGrid& grid,
|
virtual void Draw(wxGrid& grid,
|
||||||
wxGridCellAttr& attr,
|
wxGridCellAttr& attr,
|
||||||
@@ -215,10 +278,72 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
wxTextCtrl *Text() const { return (wxTextCtrl *)m_control; }
|
wxTextCtrl *Text() const { return (wxTextCtrl *)m_control; }
|
||||||
|
|
||||||
|
// parts of our virtual functions reused by the derived classes
|
||||||
|
void DoBeginEdit(const wxString& startValue);
|
||||||
|
void DoReset(const wxString& startValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxString m_startValue;
|
wxString m_startValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// the editor for numeric (long) data
|
||||||
|
class WXDLLEXPORT wxGridCellNumberEditor : public wxGridCellTextEditor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// allows to specify the range - if min == max == -1, no range checking is
|
||||||
|
// done
|
||||||
|
wxGridCellNumberEditor(int min = -1, int max = -1);
|
||||||
|
|
||||||
|
virtual void Create(wxWindow* parent,
|
||||||
|
wxWindowID id,
|
||||||
|
wxEvtHandler* evtHandler);
|
||||||
|
|
||||||
|
virtual void BeginEdit(int row, int col, wxGrid* grid);
|
||||||
|
virtual bool EndEdit(int row, int col, bool saveValue, wxGrid* grid);
|
||||||
|
|
||||||
|
virtual void Reset();
|
||||||
|
virtual void StartingKey(wxKeyEvent& event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
wxSpinCtrl *Spin() const { return (wxSpinCtrl *)m_control; }
|
||||||
|
|
||||||
|
// if HasRange(), we use wxSpinCtrl - otherwise wxTextCtrl
|
||||||
|
bool HasRange() const { return m_min != m_max; }
|
||||||
|
|
||||||
|
// string representation of m_valueOld
|
||||||
|
wxString GetString() const
|
||||||
|
{ return wxString::Format(_T("%ld"), m_valueOld); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_min,
|
||||||
|
m_max;
|
||||||
|
|
||||||
|
long m_valueOld;
|
||||||
|
};
|
||||||
|
|
||||||
|
// the editor for floating point numbers (double) data
|
||||||
|
class WXDLLEXPORT wxGridCellFloatEditor : public wxGridCellTextEditor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void Create(wxWindow* parent,
|
||||||
|
wxWindowID id,
|
||||||
|
wxEvtHandler* evtHandler);
|
||||||
|
|
||||||
|
virtual void BeginEdit(int row, int col, wxGrid* grid);
|
||||||
|
virtual bool EndEdit(int row, int col, bool saveValue, wxGrid* grid);
|
||||||
|
|
||||||
|
virtual void Reset();
|
||||||
|
virtual void StartingKey(wxKeyEvent& event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// string representation of m_valueOld
|
||||||
|
wxString GetString() const
|
||||||
|
{ return wxString::Format(_T("%f"), m_valueOld); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_valueOld;
|
||||||
|
};
|
||||||
|
|
||||||
// the editor for boolean data
|
// the editor for boolean data
|
||||||
class WXDLLEXPORT wxGridCellBoolEditor : public wxGridCellEditor
|
class WXDLLEXPORT wxGridCellBoolEditor : public wxGridCellEditor
|
||||||
{
|
{
|
||||||
|
@@ -186,10 +186,8 @@ GridFrame::GridFrame()
|
|||||||
logger->SetTimestamp( NULL );
|
logger->SetTimestamp( NULL );
|
||||||
|
|
||||||
// this will create a grid and, by default, an associated grid
|
// this will create a grid and, by default, an associated grid
|
||||||
// table for string data
|
// table for string gs_dataBugsGrid
|
||||||
//
|
grid->CreateGrid( 100, 100 );
|
||||||
//grid->CreateGrid( 100, 100 );
|
|
||||||
grid->SetTable(new SimpleTable(100, 100), TRUE);
|
|
||||||
|
|
||||||
grid->SetRowSize( 0, 60 );
|
grid->SetRowSize( 0, 60 );
|
||||||
grid->SetCellValue( 0, 0, "Ctrl+Home\nwill go to\nthis cell" );
|
grid->SetCellValue( 0, 0, "Ctrl+Home\nwill go to\nthis cell" );
|
||||||
@@ -695,74 +693,274 @@ BigGridFrame::BigGridFrame(long sizeGrid)
|
|||||||
// BugsGridFrame: a "realistic" table
|
// BugsGridFrame: a "realistic" table
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
BugsGridFrame::BugsGridFrame()
|
enum Columns
|
||||||
: wxFrame(NULL, -1, "Bugs table",
|
|
||||||
wxDefaultPosition, wxSize(500, 300))
|
|
||||||
{
|
{
|
||||||
enum Severity
|
Col_Id,
|
||||||
{
|
Col_Summary,
|
||||||
Wish,
|
Col_Severity,
|
||||||
Minor,
|
Col_Priority,
|
||||||
Normal,
|
Col_Platform,
|
||||||
Major,
|
Col_Opened,
|
||||||
Critical
|
Col_Max
|
||||||
};
|
};
|
||||||
|
|
||||||
static const wxChar* severities[] =
|
enum Severity
|
||||||
{
|
{
|
||||||
|
Sev_Wish,
|
||||||
|
Sev_Minor,
|
||||||
|
Sev_Normal,
|
||||||
|
Sev_Major,
|
||||||
|
Sev_Critical,
|
||||||
|
Sev_Max
|
||||||
|
};
|
||||||
|
|
||||||
|
static const wxChar* severities[] =
|
||||||
|
{
|
||||||
_T("wishlist"),
|
_T("wishlist"),
|
||||||
_T("minor"),
|
_T("minor"),
|
||||||
_T("normal"),
|
_T("normal"),
|
||||||
_T("major"),
|
_T("major"),
|
||||||
_T("critical"),
|
_T("critical"),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct GridData
|
static struct BugsGridData
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
const wxChar *summary;
|
const wxChar *summary;
|
||||||
Severity severity;
|
Severity severity;
|
||||||
int prio;
|
int prio;
|
||||||
const wxChar *platform;
|
const wxChar *platform;
|
||||||
bool opened;
|
bool opened;
|
||||||
} data [] =
|
} gs_dataBugsGrid [] =
|
||||||
{
|
{
|
||||||
{ 18, _T("foo doesn't work"), Major, 1, _T("wxMSW"), TRUE },
|
{ 18, _T("foo doesn't work"), Sev_Major, 1, _T("wxMSW"), TRUE },
|
||||||
{ 27, _T("bar crashes"), Critical, 1, _T("all"), FALSE },
|
{ 27, _T("bar crashes"), Sev_Critical, 1, _T("all"), FALSE },
|
||||||
{ 45, _T("printing is slow"), Minor, 3, _T("wxMSW"), TRUE },
|
{ 45, _T("printing is slow"), Sev_Minor, 3, _T("wxMSW"), TRUE },
|
||||||
{ 68, _T("Rectangle() fails"), Normal, 1, _T("wxMSW"), FALSE },
|
{ 68, _T("Rectangle() fails"), Sev_Normal, 1, _T("wxMSW"), FALSE },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const wxChar *headers[] =
|
static const wxChar *headers[Col_Max] =
|
||||||
{
|
{
|
||||||
_T("Id"),
|
_T("Id"),
|
||||||
_T("Summary"),
|
_T("Summary"),
|
||||||
_T("Severity"),
|
_T("Severity"),
|
||||||
_T("Priority"),
|
_T("Priority"),
|
||||||
_T("Platform"),
|
_T("Platform"),
|
||||||
_T("Opened?"),
|
_T("Opened?"),
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO the correct data type must be used for each column
|
wxString BugsGridTable::GetTypeName(int WXUNUSED(row), int col)
|
||||||
|
{
|
||||||
wxGrid *grid = new wxGrid(this, -1, wxDefaultPosition);
|
switch ( col )
|
||||||
wxGridTableBase *table =
|
|
||||||
new wxGridStringTable(WXSIZEOF(data), WXSIZEOF(headers));
|
|
||||||
for ( size_t row = 0; row < WXSIZEOF(data); row++ )
|
|
||||||
{
|
{
|
||||||
const GridData& gd = data[row];
|
case Col_Id:
|
||||||
table->SetValue(row, 0, wxString::Format("%d", gd.id));
|
case Col_Priority:
|
||||||
table->SetValue(row, 1, gd.summary);
|
return wxGRID_VALUE_NUMBER;;
|
||||||
table->SetValue(row, 2, severities[gd.severity]);
|
|
||||||
table->SetValue(row, 3, wxString::Format("%d", gd.prio));
|
case Col_Severity:
|
||||||
table->SetValue(row, 4, gd.platform);
|
// fall thorugh (TODO should be a list)
|
||||||
table->SetValue(row, 5, gd.opened ? _T("True") : wxEmptyString);
|
|
||||||
|
case Col_Summary:
|
||||||
|
case Col_Platform:
|
||||||
|
return wxGRID_VALUE_STRING;
|
||||||
|
|
||||||
|
case Col_Opened:
|
||||||
|
return wxGRID_VALUE_BOOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( size_t col = 0; col < WXSIZEOF(headers); col++ )
|
wxFAIL_MSG(_T("unknown column"));
|
||||||
{
|
|
||||||
table->SetColLabelValue(col, headers[col]);
|
|
||||||
}
|
|
||||||
|
|
||||||
grid->SetTable(table, TRUE);
|
return wxEmptyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
long BugsGridTable::GetNumberRows()
|
||||||
|
{
|
||||||
|
return WXSIZEOF(gs_dataBugsGrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
long BugsGridTable::GetNumberCols()
|
||||||
|
{
|
||||||
|
return Col_Max;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BugsGridTable::IsEmptyCell( int row, int col )
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString BugsGridTable::GetValue( int row, int col )
|
||||||
|
{
|
||||||
|
const BugsGridData& gd = gs_dataBugsGrid[row];
|
||||||
|
|
||||||
|
switch ( col )
|
||||||
|
{
|
||||||
|
case Col_Id:
|
||||||
|
case Col_Priority:
|
||||||
|
case Col_Opened:
|
||||||
|
wxFAIL_MSG(_T("unexpected column"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Col_Severity:
|
||||||
|
return severities[gd.severity];
|
||||||
|
|
||||||
|
case Col_Summary:
|
||||||
|
return gd.summary;
|
||||||
|
|
||||||
|
case Col_Platform:
|
||||||
|
return gd.platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxEmptyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BugsGridTable::SetValue( int row, int col, const wxString& value )
|
||||||
|
{
|
||||||
|
BugsGridData& gd = gs_dataBugsGrid[row];
|
||||||
|
|
||||||
|
switch ( col )
|
||||||
|
{
|
||||||
|
case Col_Id:
|
||||||
|
case Col_Priority:
|
||||||
|
case Col_Opened:
|
||||||
|
wxFAIL_MSG(_T("unexpected column"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Col_Severity:
|
||||||
|
{
|
||||||
|
size_t n;
|
||||||
|
for ( n = 0; n < WXSIZEOF(severities); n++ )
|
||||||
|
{
|
||||||
|
if ( severities[n] == value )
|
||||||
|
{
|
||||||
|
gd.severity = (Severity)n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( n == WXSIZEOF(severities) )
|
||||||
|
{
|
||||||
|
wxLogWarning(_T("Invalid severity value '%s'."),
|
||||||
|
value.c_str());
|
||||||
|
gd.severity = Sev_Normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case Col_Summary:
|
||||||
|
gd.summary = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Col_Platform:
|
||||||
|
gd.platform = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BugsGridTable::CanGetValueAs( int WXUNUSED(row), int col, const wxString& typeName )
|
||||||
|
{
|
||||||
|
if ( typeName == wxGRID_VALUE_STRING )
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else if ( typeName == wxGRID_VALUE_BOOL )
|
||||||
|
{
|
||||||
|
return col == Col_Opened;
|
||||||
|
}
|
||||||
|
else if ( typeName == wxGRID_VALUE_NUMBER )
|
||||||
|
{
|
||||||
|
return col == Col_Id || col == Col_Priority || col == Col_Severity;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BugsGridTable::CanSetValueAs( int row, int col, const wxString& typeName )
|
||||||
|
{
|
||||||
|
return CanGetValueAs(row, col, typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
long BugsGridTable::GetValueAsLong( int row, int col )
|
||||||
|
{
|
||||||
|
const BugsGridData& gd = gs_dataBugsGrid[row];
|
||||||
|
|
||||||
|
switch ( col )
|
||||||
|
{
|
||||||
|
case Col_Id:
|
||||||
|
return gd.id;
|
||||||
|
|
||||||
|
case Col_Priority:
|
||||||
|
return gd.prio;
|
||||||
|
|
||||||
|
case Col_Severity:
|
||||||
|
return gd.severity;
|
||||||
|
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG(_T("unexpected column"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BugsGridTable::GetValueAsBool( int row, int col )
|
||||||
|
{
|
||||||
|
if ( col == Col_Opened )
|
||||||
|
{
|
||||||
|
return gs_dataBugsGrid[row].opened;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxFAIL_MSG(_T("unexpected column"));
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BugsGridTable::SetValueAsLong( int row, int col, long value )
|
||||||
|
{
|
||||||
|
BugsGridData& gd = gs_dataBugsGrid[row];
|
||||||
|
|
||||||
|
switch ( col )
|
||||||
|
{
|
||||||
|
case Col_Priority:
|
||||||
|
gd.prio = value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
wxFAIL_MSG(_T("unexpected column"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BugsGridTable::SetValueAsBool( int row, int col, bool value )
|
||||||
|
{
|
||||||
|
if ( col == Col_Opened )
|
||||||
|
{
|
||||||
|
gs_dataBugsGrid[row].opened = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxFAIL_MSG(_T("unexpected column"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString BugsGridTable::GetColLabelValue( int col )
|
||||||
|
{
|
||||||
|
return headers[col];
|
||||||
|
}
|
||||||
|
|
||||||
|
BugsGridTable::BugsGridTable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BugsGridFrame::BugsGridFrame()
|
||||||
|
: wxFrame(NULL, -1, "Bugs table",
|
||||||
|
wxDefaultPosition, wxSize(500, 300))
|
||||||
|
{
|
||||||
|
wxGrid *grid = new wxGrid(this, -1, wxDefaultPosition);
|
||||||
|
wxGridTableBase *table = new BugsGridTable();
|
||||||
|
grid->SetTable(table, TRUE);
|
||||||
|
|
||||||
|
for ( size_t row = 0; row < WXSIZEOF(gs_dataBugsGrid); row++ )
|
||||||
|
{
|
||||||
|
grid->SetReadOnly(row, Col_Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -125,24 +125,6 @@ public:
|
|||||||
// memory
|
// memory
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class SimpleTable : public wxGridStringTable {
|
|
||||||
public:
|
|
||||||
SimpleTable( int numRows, int numCols )
|
|
||||||
: wxGridStringTable( numRows, numCols ) {}
|
|
||||||
|
|
||||||
// override this to fake a row as all bools
|
|
||||||
wxString GetTypeName( int row, int col )
|
|
||||||
{
|
|
||||||
if (row == 8)
|
|
||||||
return wxT("bool");
|
|
||||||
else if (row == 9 && col == 1)
|
|
||||||
return wxT("unknown type"); // to test fallback
|
|
||||||
else
|
|
||||||
return wxGridStringTable::GetTypeName(row, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class BigGridTable : public wxGridTableBase
|
class BigGridTable : public wxGridTableBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -173,9 +155,33 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// another, more realistic, grid example
|
// another, more realistic, grid example: shows typed columns and more
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class BugsGridTable : public wxGridTableBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BugsGridTable();
|
||||||
|
|
||||||
|
virtual long GetNumberRows();
|
||||||
|
virtual long GetNumberCols();
|
||||||
|
virtual bool IsEmptyCell( int row, int col );
|
||||||
|
virtual wxString GetValue( int row, int col );
|
||||||
|
virtual void SetValue( int row, int col, const wxString& value );
|
||||||
|
|
||||||
|
virtual wxString GetColLabelValue( int col );
|
||||||
|
|
||||||
|
virtual wxString GetTypeName( int row, int col );
|
||||||
|
virtual bool CanGetValueAs( int row, int col, const wxString& typeName );
|
||||||
|
virtual bool CanSetValueAs( int row, int col, const wxString& typeName );
|
||||||
|
|
||||||
|
virtual long GetValueAsLong( int row, int col );
|
||||||
|
virtual bool GetValueAsBool( int row, int col );
|
||||||
|
|
||||||
|
virtual void SetValueAsLong( int row, int col, long value );
|
||||||
|
virtual void SetValueAsBool( int row, int col, bool value );
|
||||||
|
};
|
||||||
|
|
||||||
class BugsGridFrame : public wxFrame
|
class BugsGridFrame : public wxFrame
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -41,10 +41,11 @@
|
|||||||
#include "wx/log.h"
|
#include "wx/log.h"
|
||||||
#include "wx/textctrl.h"
|
#include "wx/textctrl.h"
|
||||||
#include "wx/checkbox.h"
|
#include "wx/checkbox.h"
|
||||||
|
#include "wx/valtext.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// this include needs to be outside precomp for BCC
|
|
||||||
#include "wx/textfile.h"
|
#include "wx/textfile.h"
|
||||||
|
#include "wx/spinctrl.h"
|
||||||
|
|
||||||
#include "wx/grid.h"
|
#include "wx/grid.h"
|
||||||
|
|
||||||
@@ -500,12 +501,17 @@ void wxGridCellTextEditor::BeginEdit(int row, int col, wxGrid* grid)
|
|||||||
wxT("The wxGridCellEditor must be Created first!"));
|
wxT("The wxGridCellEditor must be Created first!"));
|
||||||
|
|
||||||
m_startValue = grid->GetTable()->GetValue(row, col);
|
m_startValue = grid->GetTable()->GetValue(row, col);
|
||||||
Text()->SetValue(m_startValue);
|
|
||||||
|
DoBeginEdit(m_startValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellTextEditor::DoBeginEdit(const wxString& startValue)
|
||||||
|
{
|
||||||
|
Text()->SetValue(startValue);
|
||||||
Text()->SetInsertionPointEnd();
|
Text()->SetInsertionPointEnd();
|
||||||
Text()->SetFocus();
|
Text()->SetFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool wxGridCellTextEditor::EndEdit(int row, int col, bool saveValue,
|
bool wxGridCellTextEditor::EndEdit(int row, int col, bool saveValue,
|
||||||
wxGrid* grid)
|
wxGrid* grid)
|
||||||
{
|
{
|
||||||
@@ -532,7 +538,12 @@ void wxGridCellTextEditor::Reset()
|
|||||||
wxASSERT_MSG(m_control,
|
wxASSERT_MSG(m_control,
|
||||||
wxT("The wxGridCellEditor must be Created first!"));
|
wxT("The wxGridCellEditor must be Created first!"));
|
||||||
|
|
||||||
Text()->SetValue(m_startValue);
|
DoReset(m_startValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellTextEditor::DoReset(const wxString& startValue)
|
||||||
|
{
|
||||||
|
Text()->SetValue(startValue);
|
||||||
Text()->SetInsertionPointEnd();
|
Text()->SetInsertionPointEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,6 +587,187 @@ void wxGridCellTextEditor::HandleReturn(wxKeyEvent& event)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxGridCellNumberEditor
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wxGridCellNumberEditor::wxGridCellNumberEditor(int min, int max)
|
||||||
|
{
|
||||||
|
m_min = min;
|
||||||
|
m_max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellNumberEditor::Create(wxWindow* parent,
|
||||||
|
wxWindowID id,
|
||||||
|
wxEvtHandler* evtHandler)
|
||||||
|
{
|
||||||
|
if ( HasRange() )
|
||||||
|
{
|
||||||
|
// create a spin ctrl
|
||||||
|
m_control = new wxSpinCtrl(parent, -1, wxEmptyString,
|
||||||
|
wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxSP_ARROW_KEYS,
|
||||||
|
m_min, m_max);
|
||||||
|
|
||||||
|
wxGridCellEditor::Create(parent, id, evtHandler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// just a text control
|
||||||
|
wxGridCellTextEditor::Create(parent, id, evtHandler);
|
||||||
|
|
||||||
|
#if wxUSE_VALIDATORS
|
||||||
|
Text()->SetValidator(new wxTextValidator(wxFILTER_NUMERIC));
|
||||||
|
#endif // wxUSE_VALIDATORS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellNumberEditor::BeginEdit(int row, int col, wxGrid* grid)
|
||||||
|
{
|
||||||
|
// first get the value
|
||||||
|
wxGridTableBase *table = grid->GetTable();
|
||||||
|
if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
|
||||||
|
{
|
||||||
|
m_valueOld = table->GetValueAsLong(row, col);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxFAIL_MSG( _T("this cell doesn't have numeric value") );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( HasRange() )
|
||||||
|
{
|
||||||
|
Spin()->SetValue(m_valueOld);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DoBeginEdit(GetString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxGridCellNumberEditor::EndEdit(int row, int col, bool saveValue,
|
||||||
|
wxGrid* grid)
|
||||||
|
{
|
||||||
|
bool changed;
|
||||||
|
long value;
|
||||||
|
|
||||||
|
if ( HasRange() )
|
||||||
|
{
|
||||||
|
value = Spin()->GetValue();
|
||||||
|
changed = value != m_valueOld;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
changed = Text()->GetValue().ToLong(&value) && (value != m_valueOld);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( changed )
|
||||||
|
{
|
||||||
|
grid->GetTable()->SetValueAsLong(row, col, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellNumberEditor::Reset()
|
||||||
|
{
|
||||||
|
if ( HasRange() )
|
||||||
|
{
|
||||||
|
Spin()->SetValue(m_valueOld);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DoReset(GetString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellNumberEditor::StartingKey(wxKeyEvent& event)
|
||||||
|
{
|
||||||
|
if ( !HasRange() )
|
||||||
|
{
|
||||||
|
long keycode = event.KeyCode();
|
||||||
|
if ( isdigit(keycode) || keycode == '+' || keycode == '-' )
|
||||||
|
{
|
||||||
|
wxGridCellTextEditor::StartingKey(event);
|
||||||
|
|
||||||
|
// skip Skip() below
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxGridCellFloatEditor
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void wxGridCellFloatEditor::Create(wxWindow* parent,
|
||||||
|
wxWindowID id,
|
||||||
|
wxEvtHandler* evtHandler)
|
||||||
|
{
|
||||||
|
wxGridCellTextEditor::Create(parent, id, evtHandler);
|
||||||
|
|
||||||
|
#if wxUSE_VALIDATORS
|
||||||
|
Text()->SetValidator(new wxTextValidator(wxFILTER_NUMERIC));
|
||||||
|
#endif // wxUSE_VALIDATORS
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellFloatEditor::BeginEdit(int row, int col, wxGrid* grid)
|
||||||
|
{
|
||||||
|
// first get the value
|
||||||
|
wxGridTableBase *table = grid->GetTable();
|
||||||
|
if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
|
||||||
|
{
|
||||||
|
m_valueOld = table->GetValueAsDouble(row, col);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxFAIL_MSG( _T("this cell doesn't have float value") );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoBeginEdit(GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxGridCellFloatEditor::EndEdit(int row, int col, bool saveValue,
|
||||||
|
wxGrid* grid)
|
||||||
|
{
|
||||||
|
double value;
|
||||||
|
if ( Text()->GetValue().ToDouble(&value) && (value != m_valueOld) )
|
||||||
|
{
|
||||||
|
grid->GetTable()->SetValueAsDouble(row, col, value);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellFloatEditor::Reset()
|
||||||
|
{
|
||||||
|
DoReset(GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellFloatEditor::StartingKey(wxKeyEvent& event)
|
||||||
|
{
|
||||||
|
long keycode = event.KeyCode();
|
||||||
|
if ( isdigit(keycode) ||
|
||||||
|
keycode == '+' || keycode == '-' || keycode == '.' )
|
||||||
|
{
|
||||||
|
wxGridCellTextEditor::StartingKey(event);
|
||||||
|
|
||||||
|
// skip Skip() below
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxGridCellBoolEditor
|
// wxGridCellBoolEditor
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -738,20 +930,19 @@ void wxGridCellRenderer::Draw(wxGrid& grid,
|
|||||||
dc.DrawRectangle(rect);
|
dc.DrawRectangle(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxGridCellRenderer::~wxGridCellRenderer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxGridCellStringRenderer
|
// wxGridCellStringRenderer
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
void wxGridCellStringRenderer::Draw(wxGrid& grid,
|
void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid& grid,
|
||||||
wxGridCellAttr& attr,
|
wxGridCellAttr& attr,
|
||||||
wxDC& dc,
|
wxDC& dc,
|
||||||
const wxRect& rectCell,
|
|
||||||
int row, int col,
|
|
||||||
bool isSelected)
|
bool isSelected)
|
||||||
{
|
{
|
||||||
wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
|
|
||||||
|
|
||||||
// now we only have to draw the text
|
|
||||||
dc.SetBackgroundMode( wxTRANSPARENT );
|
dc.SetBackgroundMode( wxTRANSPARENT );
|
||||||
|
|
||||||
// TODO some special colours for attr.IsReadOnly() case?
|
// TODO some special colours for attr.IsReadOnly() case?
|
||||||
@@ -766,21 +957,107 @@ void wxGridCellStringRenderer::Draw(wxGrid& grid,
|
|||||||
dc.SetTextBackground( attr.GetBackgroundColour() );
|
dc.SetTextBackground( attr.GetBackgroundColour() );
|
||||||
dc.SetTextForeground( attr.GetTextColour() );
|
dc.SetTextForeground( attr.GetTextColour() );
|
||||||
}
|
}
|
||||||
|
|
||||||
dc.SetFont( attr.GetFont() );
|
dc.SetFont( attr.GetFont() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellStringRenderer::Draw(wxGrid& grid,
|
||||||
|
wxGridCellAttr& attr,
|
||||||
|
wxDC& dc,
|
||||||
|
const wxRect& rectCell,
|
||||||
|
int row, int col,
|
||||||
|
bool isSelected)
|
||||||
|
{
|
||||||
|
wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
|
||||||
|
|
||||||
|
// now we only have to draw the text
|
||||||
|
SetTextColoursAndFont(grid, attr, dc, isSelected);
|
||||||
|
|
||||||
int hAlign, vAlign;
|
int hAlign, vAlign;
|
||||||
attr.GetAlignment(&hAlign, &vAlign);
|
attr.GetAlignment(&hAlign, &vAlign);
|
||||||
|
|
||||||
wxRect rect = rectCell;
|
wxRect rect = rectCell;
|
||||||
rect.x++;
|
rect.Inflate(-1);
|
||||||
rect.y++;
|
|
||||||
rect.width -= 2;
|
|
||||||
rect.height -= 2;
|
|
||||||
|
|
||||||
grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
|
grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
|
||||||
rect, hAlign, vAlign);
|
rect, hAlign, vAlign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxGridCellNumberRenderer::Draw(wxGrid& grid,
|
||||||
|
wxGridCellAttr& attr,
|
||||||
|
wxDC& dc,
|
||||||
|
const wxRect& rectCell,
|
||||||
|
int row, int col,
|
||||||
|
bool isSelected)
|
||||||
|
{
|
||||||
|
wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
|
||||||
|
|
||||||
|
SetTextColoursAndFont(grid, attr, dc, isSelected);
|
||||||
|
|
||||||
|
// draw the text right aligned by default
|
||||||
|
int hAlign, vAlign;
|
||||||
|
attr.GetAlignment(&hAlign, &vAlign);
|
||||||
|
hAlign = wxRIGHT;
|
||||||
|
|
||||||
|
wxRect rect = rectCell;
|
||||||
|
rect.Inflate(-1);
|
||||||
|
|
||||||
|
wxGridTableBase *table = grid.GetTable();
|
||||||
|
wxString text;
|
||||||
|
if ( table->CanGetValueAs(row, col, wxGRID_VALUE_NUMBER) )
|
||||||
|
{
|
||||||
|
text.Printf(_T("%ld"), table->GetValueAsLong(row, col));
|
||||||
|
}
|
||||||
|
//else: leave the string empty or put 0 into it?
|
||||||
|
|
||||||
|
grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxGridCellFloatRenderer
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wxGridCellFloatRenderer::wxGridCellFloatRenderer(int width, int precision)
|
||||||
|
{
|
||||||
|
SetWidth(width);
|
||||||
|
SetPrecision(precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxGridCellFloatRenderer::Draw(wxGrid& grid,
|
||||||
|
wxGridCellAttr& attr,
|
||||||
|
wxDC& dc,
|
||||||
|
const wxRect& rectCell,
|
||||||
|
int row, int col,
|
||||||
|
bool isSelected)
|
||||||
|
{
|
||||||
|
wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
|
||||||
|
|
||||||
|
SetTextColoursAndFont(grid, attr, dc, isSelected);
|
||||||
|
|
||||||
|
// draw the text right aligned by default
|
||||||
|
int hAlign, vAlign;
|
||||||
|
attr.GetAlignment(&hAlign, &vAlign);
|
||||||
|
hAlign = wxRIGHT;
|
||||||
|
|
||||||
|
wxRect rect = rectCell;
|
||||||
|
rect.Inflate(-1);
|
||||||
|
|
||||||
|
wxGridTableBase *table = grid.GetTable();
|
||||||
|
wxString text;
|
||||||
|
if ( table->CanGetValueAs(row, col, wxGRID_VALUE_FLOAT) )
|
||||||
|
{
|
||||||
|
if ( !m_format )
|
||||||
|
{
|
||||||
|
m_format.Printf(_T("%%%d.%d%%f"), m_width, m_precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
text.Printf(m_format, table->GetValueAsDouble(row, col));
|
||||||
|
}
|
||||||
|
//else: leave the string empty or put 0 into it?
|
||||||
|
|
||||||
|
grid.DrawTextRectangle(dc, text, rect, hAlign, vAlign);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxGridCellBoolRenderer
|
// wxGridCellBoolRenderer
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -1475,13 +1752,13 @@ wxString wxGridTableBase::GetColLabelValue( int col )
|
|||||||
|
|
||||||
wxString wxGridTableBase::GetTypeName( int WXUNUSED(row), int WXUNUSED(col) )
|
wxString wxGridTableBase::GetTypeName( int WXUNUSED(row), int WXUNUSED(col) )
|
||||||
{
|
{
|
||||||
return wxT("string");
|
return wxGRID_VALUE_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row), int WXUNUSED(col),
|
bool wxGridTableBase::CanGetValueAs( int WXUNUSED(row), int WXUNUSED(col),
|
||||||
const wxString& typeName )
|
const wxString& typeName )
|
||||||
{
|
{
|
||||||
return typeName == wxT("string");
|
return typeName == wxGRID_VALUE_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxGridTableBase::CanSetValueAs( int row, int col, const wxString& typeName )
|
bool wxGridTableBase::CanSetValueAs( int row, int col, const wxString& typeName )
|
||||||
@@ -2288,13 +2565,18 @@ void wxGrid::Create()
|
|||||||
m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
|
m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
|
||||||
m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
|
m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
|
||||||
|
|
||||||
// data type registration
|
// data type registration: register all standard data types
|
||||||
|
// TODO: may be allow the app to selectively disable some of them?
|
||||||
m_typeRegistry = new wxGridTypeRegistry;
|
m_typeRegistry = new wxGridTypeRegistry;
|
||||||
RegisterDataType(wxT("string"), new wxGridCellStringRenderer,
|
RegisterDataType(wxGRID_VALUE_STRING,
|
||||||
|
new wxGridCellStringRenderer,
|
||||||
new wxGridCellTextEditor);
|
new wxGridCellTextEditor);
|
||||||
RegisterDataType(wxT("bool"), new wxGridCellBoolRenderer,
|
RegisterDataType(wxGRID_VALUE_BOOL,
|
||||||
|
new wxGridCellBoolRenderer,
|
||||||
new wxGridCellBoolEditor);
|
new wxGridCellBoolEditor);
|
||||||
|
RegisterDataType(wxGRID_VALUE_NUMBER,
|
||||||
|
new wxGridCellNumberRenderer,
|
||||||
|
new wxGridCellNumberEditor);
|
||||||
|
|
||||||
// subwindow components that make up the wxGrid
|
// subwindow components that make up the wxGrid
|
||||||
m_cornerLabelWin = new wxGridCornerLabelWindow( this,
|
m_cornerLabelWin = new wxGridCornerLabelWindow( this,
|
||||||
|
Reference in New Issue
Block a user