Merge branch 'grid-selection-refactoring'

Completely overhauled selection handling in wxGrid.

Make various ways of extending selection (using Shift-arrow keys,
Ctrl-Shift-arrows, Shift-click etc) work as expected from the user point
of view instead of producing various bizarre results. Also improve
row/column header click selection as well as Ctrl/Shift-Space handling.

Internally, store selection as just a vector of blocks, independently of
the selection mode, and provide a simple API for iterating over it which
remains usable even with selections containing millions of cells (as
long as they're still composed of only a few blocks, which is the case
in practice).

Add more tests and add display of the current selection to the sample.

See https://github.com/wxWidgets/wxWidgets/pull/1772
This commit is contained in:
Vadim Zeitlin
2020-04-15 15:32:09 +02:00
9 changed files with 2322 additions and 1502 deletions

View File

@@ -432,7 +432,7 @@ GridFrame::GridFrame()
grid = new wxGrid( this,
wxID_ANY,
wxPoint( 0, 0 ),
FromDIP(wxSize( 400, 300 )) );
FromDIP(wxSize( 800, 450 )) );
#if wxUSE_LOG
@@ -440,7 +440,7 @@ GridFrame::GridFrame()
wxID_ANY,
wxEmptyString,
wxDefaultPosition,
wxDefaultSize,
wxSize(-1, 8*GetCharHeight()),
wxTE_MULTILINE );
logger = new wxLogTextCtrl( logWin );
@@ -1220,32 +1220,66 @@ void GridFrame::SetCornerLabelValue( wxCommandEvent& WXUNUSED(ev) )
void GridFrame::ShowSelection( wxCommandEvent& WXUNUSED(ev) )
{
switch ( grid->GetSelectionMode() )
int count = 0;
wxString desc;
const wxGridBlocks& sel = grid->GetSelectedBlocks();
for ( wxGridBlocks::iterator it = sel.begin(); it != sel.end(); ++it )
{
case wxGrid::wxGridSelectCells:
wxLogMessage("%zu individual cells and "
"%zu blocks of contiguous cells selected",
grid->GetSelectedCells().size(),
grid->GetSelectionBlockTopLeft().size());
return;
const wxGridBlockCoords& b = *it;
case wxGrid::wxGridSelectRows:
case wxGrid::wxGridSelectColumns:
case wxGrid::wxGridSelectRowsOrColumns:
const wxArrayInt& rows = grid->GetSelectedRows();
if ( !rows.empty() )
wxLogMessage("%zu rows selected", rows.size());
wxString blockDesc;
if ( b.GetLeftCol() == 0 &&
b.GetRightCol() == grid->GetNumberCols() - 1 )
{
if ( b.GetTopRow() == b.GetBottomRow() )
blockDesc.Printf("row %d", b.GetTopRow() + 1);
else
blockDesc.Printf("rows %d..%d",
b.GetTopRow() + 1, b.GetBottomRow() + 1);
}
else if ( b.GetTopRow() == 0 &&
b.GetBottomRow() == grid->GetNumberRows() - 1 )
{
if ( b.GetLeftCol() == b.GetRightCol() )
blockDesc.Printf("column %d", b.GetLeftCol() + 1);
else
blockDesc.Printf("columns %d..%d",
b.GetLeftCol() + 1,
b.GetRightCol() + 1);
}
else if ( b.GetTopRow() == b.GetBottomRow() &&
b.GetLeftCol() == b.GetRightCol() )
{
blockDesc.Printf("cell R%dC%d",
b.GetTopRow() + 1, b.GetLeftCol() + 1);
}
else
{
blockDesc.Printf("block R%dC%d - R%dC%d",
b.GetTopRow() + 1,
b.GetLeftCol() + 1,
b.GetBottomRow() + 1,
b.GetRightCol() + 1);
}
const wxArrayInt& cols = grid->GetSelectedCols();
if ( !cols.empty() )
wxLogMessage("%zu columns selected", rows.size());
if ( rows.empty() && cols.empty() )
wxLogMessage("No selection");
return;
if ( count++ )
desc += "\n\t";
desc += blockDesc;
}
wxLogError("Unknown grid selection mode.");
switch ( count )
{
case 0:
wxLogMessage("No selection");
break;
case 1:
wxLogMessage("Selection: %s", desc);
break;
default:
wxLogMessage("%d selected blocks:\n\t%s", count, desc);
}
}
void GridFrame::SelectCells( wxCommandEvent& WXUNUSED(ev) )