optimize wxGrid::BlockToDeviceRect() to avoid iterating over all cells, it's enough to only iterate over the visible ones (#9527)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54175 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-06-12 23:49:35 +00:00
parent f6a46bb028
commit 731330ec4c

View File

@@ -11015,37 +11015,36 @@ void wxGrid::ClearSelection()
// This function returns the rectangle that encloses the given block // This function returns the rectangle that encloses the given block
// in device coords clipped to the client size of the grid window. // in device coords clipped to the client size of the grid window.
// //
wxRect wxGrid::BlockToDeviceRect( const wxGridCellCoords &topLeft, wxRect wxGrid::BlockToDeviceRect( const wxGridCellCoords& topLeft,
const wxGridCellCoords &bottomRight ) const const wxGridCellCoords& bottomRight ) const
{ {
wxRect rect( wxGridNoCellRect ); wxRect resultRect;
wxRect cellRect; wxRect tempCellRect = CellToRect(topLeft);
if ( tempCellRect != wxGridNoCellRect )
cellRect = CellToRect( topLeft );
if ( cellRect != wxGridNoCellRect )
{ {
rect = cellRect; resultRect = tempCellRect;
} }
else else
{ {
rect = wxRect(0, 0, 0, 0); resultRect = wxRect(0, 0, 0, 0);
} }
cellRect = CellToRect( bottomRight ); tempCellRect = CellToRect(bottomRight);
if ( cellRect != wxGridNoCellRect ) if ( tempCellRect != wxGridNoCellRect )
{ {
rect += cellRect; resultRect += tempCellRect;
} }
else else
{ {
// If both inputs were "wxGridNoCellRect," then there's nothing to do.
return wxGridNoCellRect; return wxGridNoCellRect;
} }
int i, j; // Ensure that left/right and top/bottom pairs are in order.
int left = rect.GetLeft(); int left = resultRect.GetLeft();
int top = rect.GetTop(); int top = resultRect.GetTop();
int right = rect.GetRight(); int right = resultRect.GetRight();
int bottom = rect.GetBottom(); int bottom = resultRect.GetBottom();
int leftCol = topLeft.GetCol(); int leftCol = topLeft.GetCol();
int topRow = topLeft.GetRow(); int topRow = topLeft.GetRow();
@@ -11054,65 +11053,89 @@ wxRect wxGrid::BlockToDeviceRect( const wxGridCellCoords &topLeft,
if (left > right) if (left > right)
{ {
i = left; int tmp = left;
left = right; left = right;
right = i; right = tmp;
i = leftCol;
tmp = leftCol;
leftCol = rightCol; leftCol = rightCol;
rightCol = i; rightCol = tmp;
} }
if (top > bottom) if (top > bottom)
{ {
i = top; int tmp = top;
top = bottom; top = bottom;
bottom = i; bottom = tmp;
i = topRow;
tmp = topRow;
topRow = bottomRow; topRow = bottomRow;
bottomRow = i; bottomRow = tmp;
} }
for ( j = topRow; j <= bottomRow; j++ ) // The following loop is ONLY necessary to detect and handle merged cells.
{ int cw, ch;
for ( i = leftCol; i <= rightCol; i++ ) m_gridWin->GetClientSize( &cw, &ch );
{
if ((j == topRow) || (j == bottomRow) || (i == leftCol) || (i == rightCol))
{
cellRect = CellToRect( j, i );
if (cellRect.x < left) // Get the origin coordinates: notice that they will be negative if the
left = cellRect.x; // grid is scrolled downwards/to the right.
if (cellRect.y < top) int gridOriginX = 0;
top = cellRect.y; int gridOriginY = 0;
if (cellRect.x + cellRect.width > right) CalcScrolledPosition(gridOriginX, gridOriginY, &gridOriginX, &gridOriginY);
right = cellRect.x + cellRect.width;
if (cellRect.y + cellRect.height > bottom) int onScreenLeftmostCol = internalXToCol(-gridOriginX);
bottom = cellRect.y + cellRect.height; int onScreenUppermostRow = internalYToRow(-gridOriginY);
int onScreenRightmostCol = internalXToCol(-gridOriginX + cw);
int onScreenBottommostRow = internalYToRow(-gridOriginY + ch);
// Bound our loop so that we only examine the portion of the selected block
// that is shown on screen. Therefore, we compare the Top-Left block values
// to the Top-Left screen values, and the Bottom-Right block values to the
// Bottom-Right screen values, choosing appropriately.
const int visibleTopRow = wxMax(topRow, onScreenUppermostRow);
const int visibleBottomRow = wxMin(bottomRow, onScreenBottommostRow);
const int visibleLeftCol = wxMax(leftCol, onScreenLeftmostCol);
const int visibleRightCol = wxMin(rightCol, onScreenRightmostCol);
for ( int j = visibleTopRow; j <= visibleBottomRow; j++ )
{
for ( int i = visibleLeftCol; i <= visibleRightCol; i++ )
{
if ( (j == visibleTopRow) || (j == visibleBottomRow) ||
(i == visibleLeftCol) || (i == visibleRightCol) )
{
tempCellRect = CellToRect( j, i );
if (tempCellRect.x < left)
left = tempCellRect.x;
if (tempCellRect.y < top)
top = tempCellRect.y;
if (tempCellRect.x + tempCellRect.width > right)
right = tempCellRect.x + tempCellRect.width;
if (tempCellRect.y + tempCellRect.height > bottom)
bottom = tempCellRect.y + tempCellRect.height;
} }
else else
{ {
i = rightCol; // jump over inner cells. i = visibleRightCol; // jump over inner cells.
} }
} }
} }
// convert to scrolled coords // Convert to scrolled coords
//
CalcScrolledPosition( left, top, &left, &top ); CalcScrolledPosition( left, top, &left, &top );
CalcScrolledPosition( right, bottom, &right, &bottom ); CalcScrolledPosition( right, bottom, &right, &bottom );
int cw, ch;
m_gridWin->GetClientSize( &cw, &ch );
if (right < 0 || bottom < 0 || left > cw || top > ch) if (right < 0 || bottom < 0 || left > cw || top > ch)
return wxRect(0,0,0,0); return wxRect(0,0,0,0);
rect.SetLeft( wxMax(0, left) ); resultRect.SetLeft( wxMax(0, left) );
rect.SetTop( wxMax(0, top) ); resultRect.SetTop( wxMax(0, top) );
rect.SetRight( wxMin(cw, right) ); resultRect.SetRight( wxMin(cw, right) );
rect.SetBottom( wxMin(ch, bottom) ); resultRect.SetBottom( wxMin(ch, bottom) );
return rect; return resultRect;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------