Add wxGridCellActivatableEditor and show it in the grid sample

Add a helper class making it easier to define activation-only editors
and use it to implement MyGridStarEditor in the sample, showing a
typical example of using such editor.
This commit is contained in:
Vadim Zeitlin
2020-06-30 02:30:36 +02:00
parent 3cc3236f10
commit ca84560350
3 changed files with 193 additions and 1 deletions

View File

@@ -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<int>(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));