ensure row >= GetRowCount() if GetLineAt reaches invalid item
refactored method structure for better readability
This commit is contained in:
@@ -134,6 +134,7 @@ public:
|
|||||||
bool GetLineStart(unsigned int row, int& start);
|
bool GetLineStart(unsigned int row, int& start);
|
||||||
bool GetLineHeight(unsigned int row, int& height);
|
bool GetLineHeight(unsigned int row, int& height);
|
||||||
bool GetLineAt(int y, unsigned int& row);
|
bool GetLineAt(int y, unsigned int& row);
|
||||||
|
bool GetLineInfo(unsigned int row, int &start, int &height);
|
||||||
|
|
||||||
void Put(unsigned int row, int height);
|
void Put(unsigned int row, int height);
|
||||||
|
|
||||||
@@ -146,8 +147,6 @@ public:
|
|||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool GetLineInfo(unsigned int row, int &start, int &height);
|
|
||||||
|
|
||||||
HeightToRowRangesMap m_heightToRowRange;
|
HeightToRowRangesMap m_heightToRowRange;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -3346,8 +3346,10 @@ wxRect wxDataViewMainWindow::GetLinesRect( unsigned int rowFrom, unsigned int ro
|
|||||||
|
|
||||||
int wxDataViewMainWindow::GetLineStart( unsigned int row ) const
|
int wxDataViewMainWindow::GetLineStart( unsigned int row ) const
|
||||||
{
|
{
|
||||||
if (GetOwner()->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT)
|
// check for the easy case first
|
||||||
{
|
if (!GetOwner()->HasFlag(wxDV_VARIABLE_LINE_HEIGHT))
|
||||||
|
return row * m_lineHeight;
|
||||||
|
|
||||||
int start = 0;
|
int start = 0;
|
||||||
if ( m_rowHeightCache->GetLineStart(row, start) )
|
if ( m_rowHeightCache->GetLineStart(row, start) )
|
||||||
return start;
|
return start;
|
||||||
@@ -3356,27 +3358,20 @@ int wxDataViewMainWindow::GetLineStart( unsigned int row ) const
|
|||||||
for (r = 0; r < row; r++)
|
for (r = 0; r < row; r++)
|
||||||
{
|
{
|
||||||
int height = 0;
|
int height = 0;
|
||||||
if ( m_rowHeightCache->GetLineHeight(r, height) )
|
if ( !m_rowHeightCache->GetLineHeight(r, height) )
|
||||||
{
|
{
|
||||||
start += height;
|
// row height not in cache -> get it from the renderer...
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
wxDataViewItem item = GetItemByRow(r);
|
wxDataViewItem item = GetItemByRow(r);
|
||||||
if ( !item )
|
if (!item)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
height = QueryAndCacheLineHeight(r, item);
|
height = QueryAndCacheLineHeight(r, item);
|
||||||
|
}
|
||||||
|
|
||||||
start += height;
|
start += height;
|
||||||
}
|
}
|
||||||
|
|
||||||
return start;
|
return start;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return row * m_lineHeight;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxDataViewMainWindow::GetLineAt( unsigned int y ) const
|
int wxDataViewMainWindow::GetLineAt( unsigned int y ) const
|
||||||
@@ -3386,37 +3381,57 @@ int wxDataViewMainWindow::GetLineAt( unsigned int y ) const
|
|||||||
return y / m_lineHeight;
|
return y / m_lineHeight;
|
||||||
|
|
||||||
unsigned int row = 0;
|
unsigned int row = 0;
|
||||||
unsigned int yy = 0;
|
|
||||||
|
|
||||||
if ( m_rowHeightCache->GetLineAt(y, row) )
|
if ( m_rowHeightCache->GetLineAt(y, row) )
|
||||||
return row;
|
return row;
|
||||||
|
|
||||||
|
// OnPaint asks GetLineAt for the very last y position and this is always
|
||||||
|
// below the last item (--> an invalid item). To prevent iterating over all
|
||||||
|
// items, check if y is below the last row.
|
||||||
|
// Because this is done very often (for each repaint) its worth to handle
|
||||||
|
// this special case separately.
|
||||||
|
int height = 0;
|
||||||
|
int start = 0;
|
||||||
|
unsigned int rowCount = GetRowCount();
|
||||||
|
if (rowCount == 0 ||
|
||||||
|
(m_rowHeightCache->GetLineInfo(rowCount - 1, start, height) &&
|
||||||
|
y >= start + height))
|
||||||
|
{
|
||||||
|
return rowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sum all item heights until y is reached
|
||||||
|
unsigned int yy = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
int height = 0;
|
height = 0;
|
||||||
if ( !m_rowHeightCache->GetLineHeight(row, height) )
|
if ( !m_rowHeightCache->GetLineHeight(row, height) )
|
||||||
{
|
{
|
||||||
// row height not in cache -> get it from the renderer...
|
// row height not in cache -> get it from the renderer...
|
||||||
|
|
||||||
wxDataViewItem item = GetItemByRow(row);
|
wxDataViewItem item = GetItemByRow(row);
|
||||||
if ( !item )
|
if ( !item )
|
||||||
return row; // should be the last row
|
{
|
||||||
|
wxASSERT(row >= GetRowCount());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
height = QueryAndCacheLineHeight(row, item);
|
height = QueryAndCacheLineHeight(row, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
yy += height;
|
yy += height;
|
||||||
if (y < yy)
|
if (y < yy)
|
||||||
return row;
|
break;
|
||||||
|
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxDataViewMainWindow::GetLineHeight( unsigned int row ) const
|
int wxDataViewMainWindow::GetLineHeight( unsigned int row ) const
|
||||||
{
|
{
|
||||||
if (GetOwner()->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT)
|
// check for the easy case first
|
||||||
{
|
if (!GetOwner()->HasFlag(wxDV_VARIABLE_LINE_HEIGHT))
|
||||||
|
return m_lineHeight;
|
||||||
|
|
||||||
int height = 0;
|
int height = 0;
|
||||||
if ( m_rowHeightCache->GetLineHeight(row, height) )
|
if ( m_rowHeightCache->GetLineHeight(row, height) )
|
||||||
return height;
|
return height;
|
||||||
@@ -3427,14 +3442,8 @@ int wxDataViewMainWindow::GetLineHeight( unsigned int row ) const
|
|||||||
|
|
||||||
height = QueryAndCacheLineHeight(row, item);
|
height = QueryAndCacheLineHeight(row, item);
|
||||||
return height;
|
return height;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return m_lineHeight;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int wxDataViewMainWindow::QueryAndCacheLineHeight(unsigned int row, wxDataViewItem item) const
|
int wxDataViewMainWindow::QueryAndCacheLineHeight(unsigned int row, wxDataViewItem item) const
|
||||||
{
|
{
|
||||||
const wxDataViewModel *model = GetModel();
|
const wxDataViewModel *model = GetModel();
|
||||||
|
Reference in New Issue
Block a user