Fix positioning of grid editor inside the grid client area

The existing logic for adjusting the editor window position by moving it
was flawed as it didn't take into account the fact that the editor could
decide to use a different (and usually bigger) rectangle than the one we
provided it with, if it doesn't fit into the given one. Fix it to ensure
that the editor window is fully inside the grid client area by moving it
only after letting it choose its own size.

The existing code was also inconsistent as CalcDimensions() didn't take
any adjustment to the cell rectangle done in ShowCellEditControl() into
account at all and always just blithely assumed it was positioned at the
cell top left corner, which resulted in wrong virtual size calculation
and could make scrollbars appear when starting editing, as happened in
the "Bugs table" example of the grid sample when showing any comboboxes
in the last grid row. Fix this code to use the actual editor rectangle
instead.
This commit is contained in:
Vadim Zeitlin 2020-06-22 01:53:59 +02:00
parent f8a0438385
commit 097f1a17cb

View File

@ -3015,22 +3015,17 @@ void wxGrid::CalcDimensions()
// take into account editor if shown
if ( IsCellEditControlShown() )
{
int w2, h2;
int r = m_currentCellCoords.GetRow();
int c = m_currentCellCoords.GetCol();
int x = GetColLeft(c);
int y = GetRowTop(r);
// how big is the editor
wxGridCellAttrPtr attr = GetCellAttrPtr(r, c);
wxGridCellEditorPtr editor = attr->GetEditorPtr(this, r, c);
editor->GetWindow()->GetSize(&w2, &h2);
w2 += x;
h2 += y;
if ( w2 > w )
w = w2;
if ( h2 > h )
h = h2;
const wxRect rect = editor->GetWindow()->GetRect();
if ( rect.GetRight() > w )
w = rect.GetRight();
if ( rect.GetBottom() > h )
h = rect.GetBottom();
}
wxPoint offset = GetGridWindowOffset(m_gridWin);
@ -7284,10 +7279,6 @@ void wxGrid::ShowCellEditControl()
// convert to scrolled coords
CalcGridWindowScrolledPosition( rect.x, rect.y, &rect.x, &rect.y, gridWindow );
int nXMove = 0;
if (rect.x < 0)
nXMove = rect.x;
#ifdef __WXQT__
// Substract 1 pixel in every dimension to fit in the cell area.
// If not, Qt will draw the control outside the cell.
@ -7336,10 +7327,6 @@ void wxGrid::ShowCellEditControl()
maxWidth = rect.width;
}
int client_right = gridWindow->GetClientSize().GetWidth();
if (rect.x + maxWidth > client_right)
maxWidth = client_right - rect.x;
if ((maxWidth > rect.width) && (col < m_numCols) && m_table)
{
GetCellSize( row, col, &cell_rows, &cell_cols );
@ -7358,17 +7345,35 @@ void wxGrid::ShowCellEditControl()
else
break;
}
if (rect.GetRight() > client_right)
rect.SetRight( client_right - 1 );
}
editor->SetCellAttr( attr.get() );
editor->SetSize( rect );
if (nXMove != 0)
editor->GetWindow()->Move(
editor->GetWindow()->GetPosition().x + nXMove,
editor->GetWindow()->GetPosition().y );
// Note that the actual rectangle used by the editor could be
// different from the one we proposed.
rect = editor->GetWindow()->GetRect();
// Ensure that the edit control fits into the visible part of the
// window by shifting it if necessary: we don't want to truncate
// any part of it by trying to position it too far to the left or
// top and we definitely don't want to start showing scrollbars by
// positioning it too far to the right or bottom.
const wxSize sizeMax = gridWindow->GetClientSize();
if ( !wxRect(sizeMax).Contains(rect) )
{
if ( rect.x < 0 )
rect.x = 0;
if ( rect.y < 0 )
rect.y = 0;
if ( rect.x > sizeMax.x - rect.width )
rect.x = sizeMax.x - rect.width;
if ( rect.y > sizeMax.y - rect.height )
rect.y = sizeMax.y - rect.height;
editor->GetWindow()->Move(rect.x, rect.y);
}
editor->Show( true, attr.get() );
// recalc dimensions in case we need to