// forward declarations
// ----------------------------------------------------------------------------
+class WXDLLEXPORT wxGrid;
+class WXDLLEXPORT wxGridCellAttr;
class WXDLLEXPORT wxGridCellAttrProviderData;
-class WXDLLEXPORT wxGridRowLabelWindow;
class WXDLLEXPORT wxGridColLabelWindow;
class WXDLLEXPORT wxGridCornerLabelWindow;
+class WXDLLEXPORT wxGridRowLabelWindow;
+class WXDLLEXPORT wxGridTableBase;
class WXDLLEXPORT wxGridWindow;
-class WXDLLEXPORT wxGrid;
+
+// ----------------------------------------------------------------------------
+// wxGridCellRenderer: this class is responsible for actually drawing the cell
+// in the grid. You may pass it to the wxGridCellAttr (below) to change the
+// format of one given cell or to wxGrid::SetDefaultRenderer() to change the
+// view of all cells. This is an ABC, you will normally use one of the
+// predefined derived classes or derive oyur own class from it.
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxGridCellRenderer
+{
+public:
+ // draw the given cell on the provided DC inside the given rectangle
+ // using the style specified by the attribute and the default or selected
+ // state corresponding to the isSelected value.
+ //
+ // this pure virtual function has a default implementation which will
+ // prepare the DC using the given attribute: it will draw the rectangle
+ // with the bg colour from attr and set the text colour and font
+ virtual void Draw(wxGrid& grid,
+ wxDC& dc,
+ const wxRect& rect,
+ int row, int col,
+ bool isSelected) = 0;
+};
+
+// the default renderer for the cells containing string data
+class WXDLLEXPORT wxGridCellStringRenderer : public wxGridCellRenderer
+{
+public:
+ // draw the string
+ virtual void Draw(wxGrid& grid,
+ wxDC& dc,
+ const wxRect& rect,
+ int row, int col,
+ bool isSelected);
+};
// ----------------------------------------------------------------------------
// wxGridCellAttr: this class can be used to alter the cells appearance in
m_vAlign = vAlign;
}
+ // takes ownership of the pointer
+ void SetRenderer(wxGridCellRenderer *renderer)
+ { delete m_renderer; m_renderer = renderer; }
+
// accessors
bool HasTextColour() const { return m_colText.Ok(); }
bool HasBackgroundColour() const { return m_colBack.Ok(); }
if ( vAlign ) *vAlign = m_vAlign;
}
+ wxGridCellRenderer *GetRenderer() const { return m_renderer; }
+
private:
// the common part of all ctors
- void Init() { m_nRef = 1; }
+ void Init() { m_nRef = 1; m_renderer = (wxGridCellRenderer *)NULL; }
// the dtor is private because only DecRef() can delete us
- ~wxGridCellAttr() { }
+ ~wxGridCellAttr() { delete m_renderer; }
// the ref count - when it goes to 0, we die
size_t m_nRef;
int m_hAlign,
m_vAlign;
+ wxGridCellRenderer *m_renderer;
+
// suppress the stupid gcc warning about the class having private dtor and
// no friends
friend class wxGridCellAttrDummyFriend;
void DrawCellBorder( wxDC& dc, const wxGridCellCoords& );
void DrawAllGridLines( wxDC& dc, const wxRegion & reg );
void DrawCell( wxDC& dc, const wxGridCellCoords& );
- void DrawCellBackground( wxDC& dc, const wxGridCellCoords& );
- void DrawCellValue( wxDC& dc, const wxGridCellCoords& );
void DrawRowLabels( wxDC& dc );
void DrawRowLabel( wxDC& dc, int row );
wxString GetColLabelValue( int col );
wxColour GetGridLineColour() { return m_gridLineColour; }
- void SetRowLabelSize( int width );
+ void SetRowLabelSize( int width );
void SetColLabelSize( int height );
void SetLabelBackgroundColour( const wxColour& );
void SetLabelTextColour( const wxColour& );
void EnableGridLines( bool enable = TRUE );
bool GridLinesEnabled() { return m_gridLinesEnabled; }
-
// ------ row and col formatting
//
int GetDefaultRowSize();
void SetDefaultCellAlignment( int horiz, int vert );
void SetCellAlignment( int row, int col, int horiz, int vert );
+ // takes ownership of the pointer
+ void SetDefaultRenderer(wxGridCellRenderer *renderer)
+ { delete m_defaultRenderer; m_defaultRenderer = renderer; }
+ wxGridCellRenderer *GetDefaultRenderer() const
+ { return m_defaultRenderer; }
+
+ void SetCellRenderer(int row, int col, wxGridCellRenderer *renderer);
// ------ cell value accessors
//
wxColour m_gridLineColour;
bool m_gridLinesEnabled;
+ // get the renderer for the given cell - if it has no special one, the
+ // default one will be returned, never NULL
+ wxGridCellRenderer *GetCellRenderer(int row, int col);
+
+ wxGridCellRenderer *m_defaultRenderer;
+
// default cell attributes
wxFont m_defaultCellFont;
int m_defaultCellHAlign,
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
#ifdef __GNUG__
-#pragma implementation
-#pragma interface
+ #pragma implementation
+ #pragma interface
#endif
// For compilers that support precompilation, includes "wx/wx.h".
#include "griddemo.h"
+// ----------------------------------------------------------------------------
+// wxWin macros
+// ----------------------------------------------------------------------------
+
IMPLEMENT_APP( GridApp )
+// ============================================================================
+// implementation
+// ============================================================================
+// ----------------------------------------------------------------------------
+// GridApp
+// ----------------------------------------------------------------------------
bool GridApp::OnInit()
{
return TRUE;
}
-
+// ----------------------------------------------------------------------------
+// GridFrame
+// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE( GridFrame, wxFrame )
EVT_MENU( ID_TOGGLEROWLABELS, GridFrame::ToggleRowLabels )
EVT_MENU( ID_DELETECOL, GridFrame::DeleteSelectedCols )
EVT_MENU( ID_CLEARGRID, GridFrame::ClearGrid )
+ EVT_MENU( ID_SET_CELL_FG_COLOUR, GridFrame::SetCellFgColour )
+ EVT_MENU( ID_SET_CELL_BG_COLOUR, GridFrame::SetCellBgColour )
+
EVT_MENU( ID_ABOUT, GridFrame::About )
EVT_MENU( wxID_EXIT, GridFrame::OnQuit )
viewMenu->Append( ID_TOGGLEROWLABELS, "&Row labels", "", TRUE );
viewMenu->Append( ID_TOGGLECOLLABELS, "&Col labels", "", TRUE );
viewMenu->Append( ID_TOGGLEEDIT, "&Editable", "", TRUE );
- viewMenu->Append( ID_SETLABELCOLOUR, "Set &label colour" );
- viewMenu->Append( ID_SETLABELTEXTCOLOUR, "Set label &text colour" );
wxMenu *rowLabelMenu = new wxMenu;
colLabelMenu->Append( ID_COLLABELHORIZALIGN, "&Horizontal" );
colLabelMenu->Append( ID_COLLABELVERTALIGN, "&Vertical" );
- viewMenu->Append( ID_GRIDLINECOLOUR, "&Grid line colour" );
+ wxMenu *colMenu = new wxMenu;
+ colMenu->Append( ID_SETLABELCOLOUR, "Set &label colour" );
+ colMenu->Append( ID_SETLABELTEXTCOLOUR, "Set label &text colour" );
+ colMenu->Append( ID_GRIDLINECOLOUR, "&Grid line colour" );
+ colMenu->Append( ID_SET_CELL_FG_COLOUR, "Set cell &foreground colour" );
+ colMenu->Append( ID_SET_CELL_BG_COLOUR, "Set cell &background colour" );
wxMenu *editMenu = new wxMenu;
editMenu->Append( ID_INSERTROW, "Insert &row" );
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append( fileMenu, "&File" );
menuBar->Append( viewMenu, "&View" );
+ menuBar->Append( colMenu, "&Colours" );
menuBar->Append( editMenu, "&Edit" );
menuBar->Append( helpMenu, "&Help" );
grid->SetCellValue( 99, 99, "Ctrl+End\nwill go to\nthis cell" );
grid->SetCellValue(2, 2, "red");
+
grid->SetCellTextColour(2, 2, *wxRED);
grid->SetCellValue(3, 3, "green on grey");
grid->SetCellTextColour(3, 3, *wxGREEN);
grid->SetCellBackgroundColour(3, 3, *wxLIGHT_GREY);
+ grid->SetCellValue(4, 4, "a weird looking cell");
+ grid->SetCellAlignment(4, 4, wxCENTRE, wxCENTRE);
+ grid->SetCellRenderer(4, 4, new MyGridCellRenderer);
+
wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
topSizer->Add( grid,
1,
grid->ClearGrid();
}
+void GridFrame::SetCellFgColour( wxCommandEvent& WXUNUSED(ev) )
+{
+ wxColour col = wxGetColourFromUser(this);
+ if ( col.Ok() )
+ grid->SetDefaultCellTextColour(col);
+}
+
+void GridFrame::SetCellBgColour( wxCommandEvent& WXUNUSED(ev) )
+{
+ wxColour col = wxGetColourFromUser(this);
+ if ( col.Ok() )
+ grid->SetDefaultCellBackgroundColour(col);
+}
void GridFrame::OnLabelLeftClick( wxGridEvent& ev )
{
Close( TRUE );
}
+// ----------------------------------------------------------------------------
+// MyGridCellRenderer
+// ----------------------------------------------------------------------------
+
+void MyGridCellRenderer::Draw(wxGrid& grid,
+ wxDC& dc,
+ const wxRect& rect,
+ int row, int col,
+ bool isSelected)
+{
+ wxGridCellStringRenderer::Draw(grid, dc, rect, row, col, isSelected);
+
+ dc.SetPen(*wxGREEN_PEN);
+ dc.SetBrush(*wxTRANSPARENT_BRUSH);
+ dc.DrawEllipse(rect);
+}
class GridApp : public wxApp
{
- public:
+public:
bool OnInit();
};
void SetColLabelVertAlignment( wxCommandEvent& );
void SetGridLineColour( wxCommandEvent& );
+ void SetCellFgColour(wxCommandEvent &);
+ void SetCellBgColour(wxCommandEvent &);
+
void InsertRow( wxCommandEvent& );
void InsertCol( wxCommandEvent& );
void DeleteSelectedRows( wxCommandEvent& );
void OnRangeSelected( wxGridRangeSelectEvent& );
void OnCellValueChanged( wxGridEvent& );
- public:
+public:
GridFrame();
~GridFrame();
void OnQuit( wxCommandEvent& );
void About( wxCommandEvent& );
- enum { ID_TOGGLEROWLABELS = 100,
- ID_TOGGLECOLLABELS,
- ID_TOGGLEEDIT,
- ID_SETLABELCOLOUR,
- ID_SETLABELTEXTCOLOUR,
- ID_ROWLABELALIGN,
- ID_ROWLABELHORIZALIGN,
- ID_ROWLABELVERTALIGN,
- ID_COLLABELALIGN,
- ID_COLLABELHORIZALIGN,
- ID_COLLABELVERTALIGN,
- ID_GRIDLINECOLOUR,
- ID_INSERTROW,
- ID_INSERTCOL,
- ID_DELETEROW,
- ID_DELETECOL,
- ID_CLEARGRID,
- ID_ABOUT,
-
- ID_TESTFUNC };
+ enum
+ {
+ ID_TOGGLEROWLABELS = 100,
+ ID_TOGGLECOLLABELS,
+ ID_TOGGLEEDIT,
+ ID_SETLABELCOLOUR,
+ ID_SETLABELTEXTCOLOUR,
+ ID_ROWLABELALIGN,
+ ID_ROWLABELHORIZALIGN,
+ ID_ROWLABELVERTALIGN,
+ ID_COLLABELALIGN,
+ ID_COLLABELHORIZALIGN,
+ ID_COLLABELVERTALIGN,
+ ID_GRIDLINECOLOUR,
+ ID_INSERTROW,
+ ID_INSERTCOL,
+ ID_DELETEROW,
+ ID_DELETECOL,
+ ID_CLEARGRID,
+ ID_SET_CELL_FG_COLOUR,
+ ID_SET_CELL_BG_COLOUR,
+ ID_ABOUT,
+
+ ID_TESTFUNC
+ };
DECLARE_EVENT_TABLE()
};
+class MyGridCellRenderer : public wxGridCellStringRenderer
+{
+public:
+ virtual void Draw(wxGrid& grid,
+ wxDC& dc,
+ const wxRect& rect,
+ int row, int col,
+ bool isSelected);
+};
#endif
// TODO: fixed so far - make configurable later (and also different for x/y)
static const size_t GRID_SCROLL_LINE = 10;
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxGridCellRenderer
+// ----------------------------------------------------------------------------
+
+void wxGridCellRenderer::Draw(wxGrid& grid,
+ wxDC& dc,
+ const wxRect& rect,
+ int row, int col,
+ bool isSelected)
+{
+ dc.SetBackgroundMode( wxSOLID );
+
+ if ( isSelected )
+ {
+ // FIXME customize
+ dc.SetBrush( *wxBLACK_BRUSH );
+ }
+ else
+ {
+ dc.SetBrush( wxBrush(grid.GetCellBackgroundColour(row, col), wxSOLID) );
+ }
+
+ dc.SetPen( *wxTRANSPARENT_PEN );
+
+ dc.DrawRectangle(rect);
+}
+
+void wxGridCellStringRenderer::Draw(wxGrid& grid,
+ wxDC& dc,
+ const wxRect& rectCell,
+ int row, int col,
+ bool isSelected)
+{
+ wxGridCellRenderer::Draw(grid, dc, rectCell, row, col, isSelected);
+
+ // now we only have to draw the text
+ dc.SetBackgroundMode( wxTRANSPARENT );
+
+ if ( isSelected )
+ {
+ // FIXME customize
+ dc.SetTextBackground( wxColour(0, 0, 0) );
+ dc.SetTextForeground( wxColour(255, 255, 255) );
+ }
+ else
+ {
+ dc.SetTextBackground( grid.GetCellBackgroundColour(row, col) );
+ dc.SetTextForeground( grid.GetCellTextColour(row, col) );
+ }
+ dc.SetFont( grid.GetCellFont(row, col) );
+
+ int hAlign, vAlign;
+ grid.GetCellAlignment(row, col, &hAlign, &vAlign);
+
+ wxRect rect = rectCell;
+ rect.x++;
+ rect.y++;
+ rect.width -= 2;
+ rect.height -= 2;
+
+ grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
+ rect, hAlign, vAlign);
+}
+
// ----------------------------------------------------------------------------
// wxGridCellAttrProviderData
// ----------------------------------------------------------------------------
wxGrid::~wxGrid()
{
+ delete m_defaultRenderer;
delete m_table;
}
m_defaultCellHAlign = wxLEFT;
m_defaultCellVAlign = wxTOP;
+ m_defaultRenderer = (wxGridCellRenderer *)NULL;
+
m_gridLineColour = wxColour( 128, 128, 255 );
m_gridLinesEnabled = TRUE;
void wxGrid::DrawCell( wxDC& dc, const wxGridCellCoords& coords )
{
- if ( m_colWidths[coords.GetCol()] <=0 ||
- m_rowHeights[coords.GetRow()] <= 0 ) return;
+ int row = coords.GetRow();
+ int col = coords.GetCol();
+ if ( m_colWidths[col] <= 0 || m_rowHeights[row] <= 0 )
+ return;
+
+ // we draw the cell border ourselves
#if !WXGRID_DRAW_LINES
if ( m_gridLinesEnabled )
DrawCellBorder( dc, coords );
#endif
- DrawCellBackground( dc, coords );
+ // but all the rest is drawn by the cell renderer and hence may be
+ // customized
+ wxGridCellRenderer *renderer = GetCellRenderer(row, col);
+ wxRect rect;
+ rect.x = m_colRights[col] - m_colWidths[col] + 1;
+ rect.y = m_rowBottoms[row] - m_rowHeights[row] + 1;
+ rect.width = m_colWidths[col] - 1;
+ rect.height = m_rowHeights[row] - 1;
- // TODO: separate functions here for different kinds of cells ?
- // e.g. text, image
- //
- DrawCellValue( dc, coords );
+ renderer->Draw(*this, dc, rect, row, col, IsInSelection(coords));
}
-
void wxGrid::DrawCellBorder( wxDC& dc, const wxGridCellCoords& coords )
{
if ( m_colWidths[coords.GetCol()] <=0 ||
}
-void wxGrid::DrawCellBackground( wxDC& dc, const wxGridCellCoords& coords )
-{
- if ( m_colWidths[coords.GetCol()] <=0 ||
- m_rowHeights[coords.GetRow()] <= 0 ) return;
-
- int row = coords.GetRow();
- int col = coords.GetCol();
-
- dc.SetBackgroundMode( wxSOLID );
-
- if ( IsInSelection( coords ) )
- {
- // TODO: improve this
- //
- dc.SetBrush( *wxBLACK_BRUSH );
- }
- else
- {
- dc.SetBrush( wxBrush(GetCellBackgroundColour(row, col), wxSOLID) );
- }
-
- dc.SetPen( *wxTRANSPARENT_PEN );
-
- dc.DrawRectangle( m_colRights[col] - m_colWidths[col] + 1,
- m_rowBottoms[row] - m_rowHeights[row] + 1,
- m_colWidths[col]-1,
- m_rowHeights[row]-1 );
-}
-
-
-void wxGrid::DrawCellValue( wxDC& dc, const wxGridCellCoords& coords )
-{
- if ( m_colWidths[coords.GetCol()] <=0 ||
- m_rowHeights[coords.GetRow()] <= 0 ) return;
-
- int row = coords.GetRow();
- int col = coords.GetCol();
-
- dc.SetBackgroundMode( wxTRANSPARENT );
-
- if ( IsInSelection( row, col ) )
- {
- // TODO: improve this
- //
- dc.SetTextBackground( wxColour(0, 0, 0) );
- dc.SetTextForeground( wxColour(255, 255, 255) );
- }
- else
- {
- dc.SetTextBackground( GetCellBackgroundColour(row, col) );
- dc.SetTextForeground( GetCellTextColour(row, col) );
- }
- dc.SetFont( GetCellFont(row, col) );
-
- int hAlign, vAlign;
- GetCellAlignment( row, col, &hAlign, &vAlign );
-
- wxRect rect;
- rect.SetX( m_colRights[col] - m_colWidths[col] + 2 );
- rect.SetY( m_rowBottoms[row] - m_rowHeights[row] + 2 );
- rect.SetWidth( m_colWidths[col] - 4 );
- rect.SetHeight( m_rowHeights[row] - 4 );
-
- DrawTextRectangle( dc, GetCellValue( row, col ), rect, hAlign, vAlign );
-}
-
-
-
// TODO: remove this ???
// This is used to redraw all grid lines e.g. when the grid line colour
// has been changed
*vert = m_defaultCellVAlign;
}
+wxGridCellRenderer *wxGrid::GetCellRenderer(int row, int col)
+{
+ wxGridCellRenderer *renderer = (wxGridCellRenderer *)NULL;
+ wxGridCellAttr *attr = m_table ? m_table->GetAttr(row, col) : NULL;
+ if ( attr )
+ {
+ renderer = attr->GetRenderer();
+
+ attr->DecRef();
+ }
+
+ if ( !renderer )
+ {
+ if ( !m_defaultRenderer )
+ {
+ m_defaultRenderer = new wxGridCellStringRenderer;
+ }
+
+ renderer = m_defaultRenderer;
+ }
+
+ return renderer;
+}
+
// ----------------------------------------------------------------------------
// access to cell attributes
// ----------------------------------------------------------------------------
}
}
+void wxGrid::SetCellRenderer(int row, int col, wxGridCellRenderer *renderer)
+{
+ if ( CanHaveAttributes() )
+ {
+ wxGridCellAttr *attr = GetCellAttr(row, col);
+ attr->SetRenderer(renderer);
+ attr->DecRef();
+ }
+}
+
// ----------------------------------------------------------------------------
// row/col size
// ----------------------------------------------------------------------------