Fix assert with setting current cell in wxGrid::Redimension()
Avoid calling wxGrid::SetCurrentCell(0, 0) when the grid has no columns or rows, as it doesn't have any cells then and doing this logically fails the precondition assert in GetColPos(). Also refactor all 6 different snippets calling SetCurrentCell() in Redimension() into a single function to simplify the code and make it more maintainable. Add a unit test verifying that this works as intended. Closes https://github.com/wxWidgets/wxWidgets/pull/1546
This commit is contained in:
committed by
Vadim Zeitlin
parent
41b444e011
commit
dda6aa6bdc
@@ -2309,6 +2309,10 @@ private:
|
||||
// common part of Clip{Horz,Vert}GridLines
|
||||
void DoClipGridLines(bool& var, bool clip);
|
||||
|
||||
// Redimension() helper: update m_currentCellCoords if necessary after a
|
||||
// grid size change
|
||||
void UpdateCurrentCellOnRedim();
|
||||
|
||||
// update the sorting indicator shown in the specified column (whose index
|
||||
// must be valid)
|
||||
//
|
||||
|
@@ -2915,13 +2915,7 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_currentCellCoords == wxGridNoCellCoords )
|
||||
{
|
||||
// if we have just inserted cols into an empty grid the current
|
||||
// cell will be undefined...
|
||||
//
|
||||
SetCurrentCell( 0, 0 );
|
||||
}
|
||||
UpdateCurrentCellOnRedim();
|
||||
|
||||
if ( m_selection )
|
||||
m_selection->UpdateRows( pos, numRows );
|
||||
@@ -2960,13 +2954,7 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_currentCellCoords == wxGridNoCellCoords )
|
||||
{
|
||||
// if we have just inserted cols into an empty grid the current
|
||||
// cell will be undefined...
|
||||
//
|
||||
SetCurrentCell( 0, 0 );
|
||||
}
|
||||
UpdateCurrentCellOnRedim();
|
||||
|
||||
if ( !GetBatchCount() )
|
||||
{
|
||||
@@ -2996,15 +2984,7 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_numRows )
|
||||
{
|
||||
m_currentCellCoords = wxGridNoCellCoords;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_currentCellCoords.GetRow() >= m_numRows )
|
||||
m_currentCellCoords.Set( 0, 0 );
|
||||
}
|
||||
UpdateCurrentCellOnRedim();
|
||||
|
||||
if ( m_selection )
|
||||
m_selection->UpdateRows( pos, -((int)numRows) );
|
||||
@@ -3080,13 +3060,7 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_currentCellCoords == wxGridNoCellCoords )
|
||||
{
|
||||
// if we have just inserted cols into an empty grid the current
|
||||
// cell will be undefined...
|
||||
//
|
||||
SetCurrentCell( 0, 0 );
|
||||
}
|
||||
UpdateCurrentCellOnRedim();
|
||||
|
||||
if ( m_selection )
|
||||
m_selection->UpdateCols( pos, numCols );
|
||||
@@ -3144,13 +3118,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
if ( m_useNativeHeader )
|
||||
GetGridColHeader()->SetColumnCount(m_numCols);
|
||||
|
||||
if ( m_currentCellCoords == wxGridNoCellCoords )
|
||||
{
|
||||
// if we have just inserted cols into an empty grid the current
|
||||
// cell will be undefined...
|
||||
//
|
||||
SetCurrentCell( 0, 0 );
|
||||
}
|
||||
UpdateCurrentCellOnRedim();
|
||||
|
||||
if ( !GetBatchCount() )
|
||||
{
|
||||
CalcDimensions();
|
||||
@@ -3199,15 +3168,7 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_numCols )
|
||||
{
|
||||
m_currentCellCoords = wxGridNoCellCoords;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_currentCellCoords.GetCol() >= m_numCols )
|
||||
m_currentCellCoords.Set( 0, 0 );
|
||||
}
|
||||
UpdateCurrentCellOnRedim();
|
||||
|
||||
if ( m_selection )
|
||||
m_selection->UpdateCols( pos, -((int)numCols) );
|
||||
@@ -3622,6 +3583,41 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event, wxGridRowLabelWindo
|
||||
}
|
||||
}
|
||||
|
||||
void wxGrid::UpdateCurrentCellOnRedim()
|
||||
{
|
||||
if (m_currentCellCoords == wxGridNoCellCoords)
|
||||
{
|
||||
// We didn't have any valid selection before, which can only happen
|
||||
// if the grid was empty.
|
||||
// Check if this is still the case and ensure we do have valid
|
||||
// selection if the grid is not empty any more.
|
||||
if (m_numCols > 0 && m_numRows > 0)
|
||||
{
|
||||
SetCurrentCell(0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_numCols == 0 || m_numRows == 0)
|
||||
{
|
||||
// We have to reset the selection, as it must either use validate
|
||||
// coordinates otherwise, but there are no valid coordinates for
|
||||
// the grid cells any more now that it is empty.
|
||||
m_currentCellCoords = wxGridNoCellCoords;
|
||||
}
|
||||
else
|
||||
{
|
||||
int col = m_currentCellCoords.GetCol();
|
||||
int row = m_currentCellCoords.GetRow();
|
||||
if (col >= m_numCols)
|
||||
col = m_numCols - 1;
|
||||
if (row >= m_numRows)
|
||||
row = m_numRows - 1;
|
||||
SetCurrentCell(col, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wxGrid::UpdateColumnSortingIndicator(int col)
|
||||
{
|
||||
wxCHECK_RET( col != wxNOT_FOUND, "invalid column index" );
|
||||
|
@@ -58,6 +58,7 @@ private:
|
||||
CPPUNIT_TEST( Cursor );
|
||||
CPPUNIT_TEST( Selection );
|
||||
CPPUNIT_TEST( AddRowCol );
|
||||
CPPUNIT_TEST( DeleteAndAddRowCol );
|
||||
CPPUNIT_TEST( ColumnOrder );
|
||||
CPPUNIT_TEST( ColumnVisibility );
|
||||
CPPUNIT_TEST( LineFormatting );
|
||||
@@ -75,6 +76,7 @@ private:
|
||||
CPPUNIT_TEST( ColumnOrder );
|
||||
WXUISIM_TEST( ResizeScrolledHeader );
|
||||
WXUISIM_TEST( ColumnMinWidth );
|
||||
CPPUNIT_TEST( DeleteAndAddRowCol );
|
||||
CPPUNIT_TEST( PseudoTest_NativeLabels );
|
||||
NONGTK_TEST( LabelClick );
|
||||
NONGTK_TEST( SortClick );
|
||||
@@ -93,6 +95,7 @@ private:
|
||||
void Cursor();
|
||||
void Selection();
|
||||
void AddRowCol();
|
||||
void DeleteAndAddRowCol();
|
||||
void ColumnOrder();
|
||||
void ColumnVisibility();
|
||||
void LineFormatting();
|
||||
@@ -540,6 +543,35 @@ void GridTestCase::AddRowCol()
|
||||
CPPUNIT_ASSERT_EQUAL(7, m_grid->GetNumberCols());
|
||||
}
|
||||
|
||||
void GridTestCase::DeleteAndAddRowCol()
|
||||
{
|
||||
CPPUNIT_ASSERT_EQUAL(10, m_grid->GetNumberRows());
|
||||
CPPUNIT_ASSERT_EQUAL(2, m_grid->GetNumberCols());
|
||||
|
||||
m_grid->DeleteRows(0, 10);
|
||||
m_grid->DeleteCols(0, 2);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(0, m_grid->GetNumberRows());
|
||||
CPPUNIT_ASSERT_EQUAL(0, m_grid->GetNumberCols());
|
||||
|
||||
m_grid->AppendRows(5);
|
||||
m_grid->AppendCols(3);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(5, m_grid->GetNumberRows());
|
||||
CPPUNIT_ASSERT_EQUAL(3, m_grid->GetNumberCols());
|
||||
|
||||
// The order of functions calls can be important
|
||||
m_grid->DeleteCols(0, 3);
|
||||
m_grid->DeleteRows(0, 5);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(0, m_grid->GetNumberRows());
|
||||
CPPUNIT_ASSERT_EQUAL(0, m_grid->GetNumberCols());
|
||||
|
||||
// Different functions calls order
|
||||
m_grid->AppendCols(3);
|
||||
m_grid->AppendRows(5);
|
||||
}
|
||||
|
||||
void GridTestCase::ColumnOrder()
|
||||
{
|
||||
m_grid->AppendCols(2);
|
||||
|
Reference in New Issue
Block a user