diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index 754deb5460..e02f45f3ae 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -523,6 +523,34 @@ protected: // Smart pointer to wxGridCellEditor, calling DecRef() on it automatically. typedef wxObjectDataPtr wxGridCellEditorPtr; +// Base class for editors that can be only activated and not edited normally. +class wxGridCellActivatableEditor : public wxGridCellEditor +{ +public: + // In this class these methods must be overridden. + virtual wxGridActivationResult + TryActivate(int row, int col, wxGrid* grid, + const wxGridActivationSource& actSource) = 0; + virtual void DoActivate(int row, int col, wxGrid* grid) = 0; + + // All the other methods that normally must be implemented in an editor are + // defined as just stubs below, as they should be never called. + + virtual void Create(wxWindow*, wxWindowID, wxEvtHandler*) wxOVERRIDE + { wxFAIL; } + virtual void BeginEdit(int, int, wxGrid*) wxOVERRIDE + { wxFAIL; } + virtual bool EndEdit(int, int, const wxGrid*, + const wxString&, wxString*) wxOVERRIDE + { wxFAIL; return false; } + virtual void ApplyEdit(int, int, wxGrid*) wxOVERRIDE + { wxFAIL; } + virtual void Reset() wxOVERRIDE + { wxFAIL; } + virtual wxString GetValue() const wxOVERRIDE + { wxFAIL; return wxString(); } +}; + // ---------------------------------------------------------------------------- // wxGridHeaderRenderer and company: like wxGridCellRenderer but for headers // ---------------------------------------------------------------------------- diff --git a/interface/wx/grid.h b/interface/wx/grid.h index 112365d672..bd11205d7d 100644 --- a/interface/wx/grid.h +++ b/interface/wx/grid.h @@ -551,7 +551,10 @@ public: the cell, but starting with wxWidgets 3.1.4 it's also possible to define "activatable" cell editors, that change the value of the cell directly when it's activated (typically by pressing Space key or clicking on it), see - TryActivate() method. + TryActivate() method. Note that when implementing an editor which is always + activatable, i.e. never shows any in-place editor, it is more convenient to + derive its class from wxGridCellActivatableEditor than from wxGridCellEditor + itself. @library{wxcore} @category{grid} @@ -767,6 +770,34 @@ protected: virtual ~wxGridCellEditor(); }; +/** + Base class for activatable editors. + + Inheriting from this class makes it simpler to implement editors that + support only activation, but not in-place editing, as they only need to + implement TryActivate(), DoActivate() and Clone() methods, but not all the + other pure virtual methods of wxGridCellEditor. + + @since 3.1.4 + */ +class wxGridCellActivatableEditor : public wxGridCellEditor +{ +public: + /** + Same method as in wxGridCellEditor, but pure virtual. + + Note that the implementation of this method must never return + wxGridActivationResult::DoEdit() for the editors inheriting from this + class, as it doesn't support normal editing. + */ + virtual wxGridActivationResult + TryActivate(int row, int col, wxGrid* grid, + const wxGridActivationSource& actSource) = 0; + + /// Same method as in wxGridCellEditor, but pure virtual. + virtual void DoActivate(int row, int col, wxGrid* grid) = 0; +}; + /** Smart pointer wrapping wxGridCellEditor. diff --git a/samples/grid/griddemo.cpp b/samples/grid/griddemo.cpp index 475173d1dd..77b645cc6d 100644 --- a/samples/grid/griddemo.cpp +++ b/samples/grid/griddemo.cpp @@ -121,6 +121,135 @@ private: wxDECLARE_NO_COPY_CLASS(CustomColumnHeadersProvider); }; +// ---------------------------------------------------------------------------- +// Custom wxGrid renderer and editor for showing stars as used for rating +// ---------------------------------------------------------------------------- + +// Max number of stars shown by MyGridStarRenderer. +static const int MAX_STARS = 5; + +// Helper function returning the number between 0 and MAX_STARS corresponding +// to the value of the cell. +static int GetStarValue(wxGrid& grid, int row, int col) +{ + unsigned long n = 0; + if ( !grid.GetCellValue(row, col).ToULong(&n) || n > MAX_STARS ) + n = 0; + + return static_cast(n); +} + +// Another helper returning the string containing the appropriate number of +// black and white stars. +static wxString GetStarString(int numBlackStars) +{ + const wxUniChar BLACK_STAR = 0x2605; + const wxUniChar WHITE_STAR = 0x2606; + + return wxString(BLACK_STAR, numBlackStars) + + wxString(WHITE_STAR, MAX_STARS - numBlackStars); +} + +// Renders the value of the cell, which is supposed to be a number between 1 +// and 5, as a sequence of that number of black stars followed by the number of +// white stars needed to have 5 stars in total. +class MyGridStarRenderer : public wxGridCellRenderer +{ +public: + virtual void Draw(wxGrid& grid, + wxGridCellAttr& attr, + wxDC& dc, + const wxRect& rect, + int row, int col, + bool isSelected) wxOVERRIDE + { + wxGridCellRenderer::Draw(grid, attr, dc, rect, row, col, isSelected); + + grid.DrawTextRectangle(dc, GetStarString(GetStarValue(grid, row, col)), + rect, attr); + } + + virtual wxSize GetBestSize(wxGrid& WXUNUSED(grid), + wxGridCellAttr& attr, + wxDC& dc, + int WXUNUSED(row), + int WXUNUSED(col)) wxOVERRIDE + { + dc.SetFont(attr.GetFont()); + return dc.GetTextExtent(GetStarString(MAX_STARS)); + } + + virtual wxGridCellRenderer *Clone() const wxOVERRIDE + { + return new MyGridStarRenderer(); + } +}; + +// Activatable editor cycling the number of stars on each activation. +class MyGridStarEditor : public wxGridCellActivatableEditor +{ +public: + virtual wxGridActivationResult + TryActivate(int row, int col, wxGrid* grid, + const wxGridActivationSource& actSource) wxOVERRIDE + { + int numStars = -1; + + switch ( actSource.GetOrigin() ) + { + case wxGridActivationSource::Program: + // It isn't really possible to programmatically start editing a + // cell using this editor. + return wxGridActivationResult::DoNothing(); + + case wxGridActivationSource::Key: + switch ( actSource.GetKeyEvent().GetKeyCode() ) + { + case '0': numStars = 0; break; + case '1': numStars = 1; break; + case '2': numStars = 2; break; + case '3': numStars = 3; break; + case '4': numStars = 4; break; + case '5': numStars = 5; break; + case ' ': + // Use space key to cycle over the values. + break; + + default: + return wxGridActivationResult::DoNothing(); + } + + break; + + case wxGridActivationSource::Mouse: + // Ideally we should use the mouse event position to determine + // on which star the user clicked, but for now keep it simple + // and just cycle through the star value. + break; + } + + if ( numStars == -1 ) + numStars = (GetStarValue(*grid, row, col) + 1) % (MAX_STARS + 1); + + m_value.Printf("%d", numStars); + + return wxGridActivationResult::DoChange(m_value); + } + + virtual void DoActivate(int row, int col, wxGrid* grid) wxOVERRIDE + { + grid->SetCellValue(row, col, m_value); + } + + virtual wxGridCellEditor *Clone() const + { + return new MyGridStarEditor(); + } + +private: + wxString m_value; +}; + // ---------------------------------------------------------------------------- // wxWin macros // ---------------------------------------------------------------------------- @@ -517,6 +646,10 @@ GridFrame::GridFrame() grid->SetCellAlignment(4, 4, wxALIGN_CENTRE, wxALIGN_CENTRE); grid->SetCellRenderer(4, 4, new MyGridCellRenderer); + grid->SetCellValue(4, 5, "3"); + grid->SetCellRenderer(4, 5, new MyGridStarRenderer); + grid->SetCellEditor(4, 5, new MyGridStarEditor); + grid->SetCellRenderer(3, 0, new wxGridCellBoolRenderer); grid->SetCellEditor(3, 0, new wxGridCellBoolEditor); grid->SetCellBackgroundColour(3, 0, wxColour(255, 127, 127));