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

View File

@@ -74,6 +74,7 @@ private:
NONGTK_TEST( LabelClick );
NONGTK_TEST( SortClick );
CPPUNIT_TEST( ColumnOrder );
WXUISIM_TEST( WindowAsEditorControl );
CPPUNIT_TEST_SUITE_END();
void CellEdit();
@@ -95,6 +96,7 @@ private:
void CellFormatting();
void Editable();
void ReadOnly();
void WindowAsEditorControl();
void PseudoTest_NativeHeader() { ms_nativeheader = true; }
void PseudoTest_NativeLabels() { ms_nativeheader = false;
ms_nativelabels = true; }
@@ -742,4 +744,66 @@ void GridTestCase::ReadOnly()
#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