From: Vadim Zeitlin Date: Fri, 11 Feb 2000 19:40:56 +0000 (+0000) Subject: added wxGridCellRenderer X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/ab79958a7fdd0ad585436abefa5a49568a2d8122 added wxGridCellRenderer git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5971 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index 4a52aa1b2e..8bd6959381 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -54,12 +54,51 @@ // 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 @@ -107,6 +146,10 @@ public: 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(); } @@ -122,12 +165,14 @@ public: 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; @@ -138,6 +183,8 @@ private: 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; @@ -501,8 +548,6 @@ public: 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 ); @@ -617,7 +662,7 @@ public: 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& ); @@ -631,7 +676,6 @@ public: void EnableGridLines( bool enable = TRUE ); bool GridLinesEnabled() { return m_gridLinesEnabled; } - // ------ row and col formatting // int GetDefaultRowSize(); @@ -662,6 +706,13 @@ public: 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 // @@ -957,6 +1008,12 @@ protected: 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, diff --git a/samples/newgrid/griddemo.cpp b/samples/newgrid/griddemo.cpp index 6d650a36f3..768c9c5737 100644 --- a/samples/newgrid/griddemo.cpp +++ b/samples/newgrid/griddemo.cpp @@ -8,9 +8,17 @@ // 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". @@ -30,9 +38,19 @@ #include "griddemo.h" +// ---------------------------------------------------------------------------- +// wxWin macros +// ---------------------------------------------------------------------------- + IMPLEMENT_APP( GridApp ) +// ============================================================================ +// implementation +// ============================================================================ +// ---------------------------------------------------------------------------- +// GridApp +// ---------------------------------------------------------------------------- bool GridApp::OnInit() { @@ -42,7 +60,9 @@ bool GridApp::OnInit() return TRUE; } - +// ---------------------------------------------------------------------------- +// GridFrame +// ---------------------------------------------------------------------------- BEGIN_EVENT_TABLE( GridFrame, wxFrame ) EVT_MENU( ID_TOGGLEROWLABELS, GridFrame::ToggleRowLabels ) @@ -61,6 +81,9 @@ BEGIN_EVENT_TABLE( GridFrame, wxFrame ) 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 ) @@ -90,8 +113,6 @@ GridFrame::GridFrame() 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; @@ -111,7 +132,12 @@ GridFrame::GridFrame() 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" ); @@ -126,6 +152,7 @@ GridFrame::GridFrame() wxMenuBar *menuBar = new wxMenuBar; menuBar->Append( fileMenu, "&File" ); menuBar->Append( viewMenu, "&View" ); + menuBar->Append( colMenu, "&Colours" ); menuBar->Append( editMenu, "&Edit" ); menuBar->Append( helpMenu, "&Help" ); @@ -164,11 +191,16 @@ GridFrame::GridFrame() 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, @@ -411,6 +443,19 @@ void GridFrame::ClearGrid( wxCommandEvent& WXUNUSED(ev) ) 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 ) { @@ -524,3 +569,19 @@ void GridFrame::OnQuit( wxCommandEvent& WXUNUSED(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); +} diff --git a/samples/newgrid/griddemo.h b/samples/newgrid/griddemo.h index c6db901d21..c5ab79e0b2 100644 --- a/samples/newgrid/griddemo.h +++ b/samples/newgrid/griddemo.h @@ -20,7 +20,7 @@ class wxGrid; class GridApp : public wxApp { - public: +public: bool OnInit(); }; @@ -45,6 +45,9 @@ class GridFrame : public wxFrame void SetColLabelVertAlignment( wxCommandEvent& ); void SetGridLineColour( wxCommandEvent& ); + void SetCellFgColour(wxCommandEvent &); + void SetCellBgColour(wxCommandEvent &); + void InsertRow( wxCommandEvent& ); void InsertCol( wxCommandEvent& ); void DeleteSelectedRows( wxCommandEvent& ); @@ -59,37 +62,51 @@ class GridFrame : public wxFrame 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 diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 9af3fd5575..8f8fcddd87 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -189,6 +189,74 @@ wxRect wxGridNoCellRect( -1, -1, -1, -1 ); // 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 // ---------------------------------------------------------------------------- @@ -1181,6 +1249,7 @@ wxGrid::wxGrid( wxWindow *parent, wxGrid::~wxGrid() { + delete m_defaultRenderer; delete m_table; } @@ -1323,6 +1392,8 @@ void wxGrid::Init() m_defaultCellHAlign = wxLEFT; m_defaultCellVAlign = wxTOP; + m_defaultRenderer = (wxGridCellRenderer *)NULL; + m_gridLineColour = wxColour( 128, 128, 255 ); m_gridLinesEnabled = TRUE; @@ -3096,23 +3167,30 @@ void wxGrid::DrawGridCellArea( wxDC& dc ) 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 || @@ -3134,74 +3212,6 @@ void wxGrid::DrawCellBorder( wxDC& dc, const wxGridCellCoords& coords ) } -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 @@ -4627,6 +4637,30 @@ void wxGrid::GetDefaultCellAlignment( int *horiz, int *vert ) *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 // ---------------------------------------------------------------------------- @@ -4768,6 +4802,16 @@ void wxGrid::SetCellAlignment( int row, int col, int horiz, int vert ) } } +void wxGrid::SetCellRenderer(int row, int col, wxGridCellRenderer *renderer) +{ + if ( CanHaveAttributes() ) + { + wxGridCellAttr *attr = GetCellAttr(row, col); + attr->SetRenderer(renderer); + attr->DecRef(); + } +} + // ---------------------------------------------------------------------------- // row/col size // ----------------------------------------------------------------------------