diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index f6b7244760..2cf170caec 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -158,6 +158,24 @@ wxDEFINE_EVENT( wxEVT_GRID_TABBING, wxGridEvent ); // implementation // ============================================================================ +namespace +{ + +// Helper function for consistent cell span determination based on cell size. +wxGrid::CellSpan GetCellSpan(int numRows, int numCols) +{ + if ( numRows == 1 && numCols == 1 ) + return wxGrid::CellSpan_None; // just a normal cell + + if ( numRows < 0 || numCols < 0 ) + return wxGrid::CellSpan_Inside; // covered by a multi-span cell + + // this cell spans multiple cells to its right/bottom + return wxGrid::CellSpan_Main; +} + +} // anonymous namespace + wxIMPLEMENT_ABSTRACT_CLASS(wxGridCellEditorEvtHandler, wxEvtHandler); wxBEGIN_EVENT_TABLE( wxGridCellEditorEvtHandler, wxEvtHandler ) @@ -6217,7 +6235,15 @@ void wxGrid::DrawGridCellArea( wxDC& dc, const wxGridCellCoordsArray& cells ) { if (!m_table->IsEmptyCell(row + l, j)) { - if ( GetCellAttrPtr(row + l, j)->CanOverflow() ) + wxGridCellAttrPtr attr = GetCellAttrPtr(row + l, j); + int numRows, numCols; + attr->GetSize(&numRows, &numCols); + if ( GetCellSpan(numRows, numCols) + == wxGrid::CellSpan_Inside ) + // As above: don't bother drawing inside cells. + continue; + + if ( attr->CanOverflow() ) { wxGridCellCoords cell(row + l, j); bool marked = false; @@ -9120,14 +9146,7 @@ wxGrid::GetCellSize( int row, int col, int *num_rows, int *num_cols ) const { GetCellAttrPtr(row, col)->GetSize( num_rows, num_cols ); - if ( *num_rows == 1 && *num_cols == 1 ) - return CellSpan_None; // just a normal cell - - if ( *num_rows < 0 || *num_cols < 0 ) - return CellSpan_Inside; // covered by a multi-span cell - - // this cell spans multiple cells to its right/bottom - return CellSpan_Main; + return GetCellSpan(*num_rows, *num_cols); } wxGridCellRenderer* wxGrid::GetCellRenderer(int row, int col) const diff --git a/tests/controls/gridtest.cpp b/tests/controls/gridtest.cpp index 87e5475749..72d6f8ae4b 100644 --- a/tests/controls/gridtest.cpp +++ b/tests/controls/gridtest.cpp @@ -1423,6 +1423,32 @@ TEST_CASE_METHOD(GridTestCase, "Grid::AutoSizeColumn", "[grid]") } } +TEST_CASE_METHOD(GridTestCase, "Grid::DrawInvalidCell", "[grid][multicell]") +{ + // Set up a multicell with inside an overflowing cell. + // This is artificial and normally inside cells are probably not expected + // to have a value but this is merely done to check if inside cells are + // drawn, which they shouldn't be. + m_grid->SetCellSize(0, 0, 2, 1); + m_grid->SetCellValue( 1, 0, wxString('W', 42) ); + + // Update()s, yields and sleep are needed to try to make the test fail with + // macOS, GTK and MSW. + // MSW needs just the yields (or updates), macOS in addition needs to sleep + // (doesn't work with updates) and for GTK it's usually enough to just do + // two updates (not yields). This test does all unconditionally. + m_grid->Update(); + wxYield(); + wxMilliSleep(20); + + // Try to force redrawing of the inside cell: if it still draws there will + // be an infinite recursion. + m_grid->SetColSize(1, m_grid->GetColSize(1) + 1); + + m_grid->Update(); + wxYield(); +} + // Test wxGridBlockCoords here because it'a a part of grid sources. std::ostream& operator<<(std::ostream& os, const wxGridBlockCoords& block) {