Make using non-wxControl-derived wxGrid editors really work

While feacaf8714 changed the API to allow
using any wxWindow (and not only a window of a wxControl-derived class)
as the associated window of the grid editor, actually doing resulted in
an immediate crash due to dereferencing a null pointer in wxGrid code
which still expected to have a wxControl.

Fix this by replacing all calls to wxGridCellEditor::GetControl() inside
wxGrid with wxGridCellEditor::GetWindow(), to ensure that a non-null
editor window is used even in this case.

Closes https://github.com/wxWidgets/wxWidgets/pull/1509
This commit is contained in:
Ilya Sinitsyn
2019-08-27 03:47:55 +07:00
committed by Vadim Zeitlin
parent 0ea4366163
commit 1bce1a1d4c
2 changed files with 76 additions and 12 deletions

View File

@@ -2774,7 +2774,7 @@ void wxGrid::CalcDimensions()
// how big is the editor // how big is the editor
wxGridCellAttr* attr = GetCellAttr(r, c); wxGridCellAttr* attr = GetCellAttr(r, c);
wxGridCellEditor* editor = attr->GetEditor(this, r, c); wxGridCellEditor* editor = attr->GetEditor(this, r, c);
editor->GetControl()->GetSize(&w2, &h2); editor->GetWindow()->GetSize(&w2, &h2);
w2 += x; w2 += x;
h2 += y; h2 += y;
if ( w2 > w ) if ( w2 > w )
@@ -6877,7 +6877,7 @@ bool wxGrid::IsCellEditControlShown() const
{ {
if ( editor->IsCreated() ) if ( editor->IsCreated() )
{ {
isShown = editor->GetControl()->IsShown(); isShown = editor->GetWindow()->IsShown();
} }
editor->DecRef(); editor->DecRef();
@@ -6959,13 +6959,13 @@ void wxGrid::ShowCellEditControl()
this, this,
row, row,
col, col,
editor->GetControl()); editor->GetWindow());
GetEventHandler()->ProcessEvent(evt); GetEventHandler()->ProcessEvent(evt);
} }
else if ( editor->GetControl() && else if ( editor->GetWindow() &&
editor->GetControl()->GetParent() != gridWindow ) editor->GetWindow()->GetParent() != gridWindow )
{ {
editor->GetControl()->Reparent(gridWindow); editor->GetWindow()->Reparent(gridWindow);
} }
// resize editor to overflow into righthand cells if allowed // resize editor to overflow into righthand cells if allowed
@@ -7009,9 +7009,9 @@ void wxGrid::ShowCellEditControl()
editor->SetCellAttr( attr ); editor->SetCellAttr( attr );
editor->SetSize( rect ); editor->SetSize( rect );
if (nXMove != 0) if (nXMove != 0)
editor->GetControl()->Move( editor->GetWindow()->Move(
editor->GetControl()->GetPosition().x + nXMove, editor->GetWindow()->GetPosition().x + nXMove,
editor->GetControl()->GetPosition().y ); editor->GetWindow()->GetPosition().y );
editor->Show( true, attr ); editor->Show( true, attr );
// recalc dimensions in case we need to // recalc dimensions in case we need to
@@ -7036,10 +7036,10 @@ void wxGrid::HideCellEditControl()
wxGridCellAttr *attr = GetCellAttr(row, col); wxGridCellAttr *attr = GetCellAttr(row, col);
wxGridCellEditor *editor = attr->GetEditor(this, row, col); wxGridCellEditor *editor = attr->GetEditor(this, row, col);
const bool editorHadFocus = editor->GetControl()->HasFocus(); const bool editorHadFocus = editor->GetWindow()->HasFocus();
if ( editor->GetControl()->GetParent() != m_gridWin ) if ( editor->GetWindow()->GetParent() != m_gridWin )
editor->GetControl()->Reparent(m_gridWin); editor->GetWindow()->Reparent(m_gridWin);
editor->Show( false ); editor->Show( false );
editor->DecRef(); editor->DecRef();

View File

@@ -74,6 +74,7 @@ private:
NONGTK_TEST( LabelClick ); NONGTK_TEST( LabelClick );
NONGTK_TEST( SortClick ); NONGTK_TEST( SortClick );
CPPUNIT_TEST( ColumnOrder ); CPPUNIT_TEST( ColumnOrder );
WXUISIM_TEST( WindowAsEditorControl );
CPPUNIT_TEST_SUITE_END(); CPPUNIT_TEST_SUITE_END();
void CellEdit(); void CellEdit();
@@ -95,6 +96,7 @@ private:
void CellFormatting(); void CellFormatting();
void Editable(); void Editable();
void ReadOnly(); void ReadOnly();
void WindowAsEditorControl();
void PseudoTest_NativeHeader() { ms_nativeheader = true; } void PseudoTest_NativeHeader() { ms_nativeheader = true; }
void PseudoTest_NativeLabels() { ms_nativeheader = false; void PseudoTest_NativeLabels() { ms_nativeheader = false;
ms_nativelabels = true; } ms_nativelabels = true; }
@@ -742,4 +744,66 @@ void GridTestCase::ReadOnly()
#endif #endif
} }
void GridTestCase::WindowAsEditorControl()
{
#if wxUSE_UIACTIONSIMULATOR
// A very simple editor using a window not derived from wxControl as the
// editor.
class TestEditor : public wxGridCellEditor
{
public:
TestEditor() {}
void Create(wxWindow* parent,
wxWindowID id,
wxEvtHandler* evtHandler) wxOVERRIDE
{
SetWindow(new wxWindow(parent, id));
wxGridCellEditor::Create(parent, id, evtHandler);
}
void BeginEdit(int, int, wxGrid*) wxOVERRIDE {}
bool EndEdit(int, int, wxGrid const*, wxString const&,
wxString* newval) wxOVERRIDE
{
*newval = GetValue();
return true;
}
void ApplyEdit(int row, int col, wxGrid* grid) wxOVERRIDE
{
grid->GetTable()->SetValue(row, col, GetValue());
}
void Reset() wxOVERRIDE {}
wxGridCellEditor* Clone() const wxOVERRIDE { return new TestEditor(); }
wxString GetValue() const wxOVERRIDE { return "value"; }
wxDECLARE_NO_COPY_CLASS(TestEditor);
};
wxGridCellAttr* attr = new wxGridCellAttr();
attr->SetRenderer(new wxGridCellStringRenderer());
attr->SetEditor(new TestEditor());
m_grid->SetAttr(1, 1, attr);
EventCounter created(m_grid, wxEVT_GRID_EDITOR_CREATED);
wxUIActionSimulator sim;
m_grid->SetFocus();
m_grid->SetGridCursor(1, 1);
m_grid->EnableCellEditControl();
sim.Char(WXK_RETURN);
wxYield();
CPPUNIT_ASSERT_EQUAL(1, created.GetCount());
#endif
}
#endif //wxUSE_GRID #endif //wxUSE_GRID