Merge branch 'grid-autosize'
Optimize wxGrid::AutoSizeColumns() for big grids. This includes an optimization of wxDC::GetTextExtent() at the price of slightly reduced precision in wxMSW. See https://github.com/wxWidgets/wxWidgets/pull/1893
This commit is contained in:
@@ -212,6 +212,20 @@ public:
|
||||
return GetBestSize(grid, attr, dc, row, col).GetWidth();
|
||||
}
|
||||
|
||||
|
||||
// Unlike GetBestSize(), this functions is optional: it is used when
|
||||
// auto-sizing columns to determine the best width without iterating over
|
||||
// all cells in this column, if possible.
|
||||
//
|
||||
// If it isn't, return wxDefaultSize as the base class version does by
|
||||
// default.
|
||||
virtual wxSize GetMaxBestSize(wxGrid& WXUNUSED(grid),
|
||||
wxGridCellAttr& WXUNUSED(attr),
|
||||
wxDC& WXUNUSED(dc))
|
||||
{
|
||||
return wxDefaultSize;
|
||||
}
|
||||
|
||||
// create a new object which is the copy of this one
|
||||
virtual wxGridCellRenderer *Clone() const = 0;
|
||||
};
|
||||
@@ -1065,6 +1079,16 @@ public:
|
||||
return wxGridCellAttrPtr(GetAttr(row, col, kind));
|
||||
}
|
||||
|
||||
// This is an optimization for a common case when the entire column uses
|
||||
// roughly the same attribute, which can thus be reused for measuring all
|
||||
// the cells in this column. Override this to return true (possibly for
|
||||
// some columns only) to speed up AutoSizeColumns() for the grids using
|
||||
// this table.
|
||||
virtual bool CanMeasureColUsingSameAttr(int WXUNUSED(col)) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// these functions take ownership of the pointer
|
||||
virtual void SetAttr(wxGridCellAttr* attr, int row, int col);
|
||||
virtual void SetRowAttr(wxGridCellAttr *attr, int row);
|
||||
@@ -1869,11 +1893,8 @@ public:
|
||||
{ AutoSizeColOrRow(row, setAsMin, wxGRID_ROW); }
|
||||
|
||||
// auto size all columns (very ineffective for big grids!)
|
||||
void AutoSizeColumns( bool setAsMin = true )
|
||||
{ (void)SetOrCalcColumnSizes(false, setAsMin); }
|
||||
|
||||
void AutoSizeRows( bool setAsMin = true )
|
||||
{ (void)SetOrCalcRowSizes(false, setAsMin); }
|
||||
void AutoSizeColumns( bool setAsMin = true );
|
||||
void AutoSizeRows( bool setAsMin = true );
|
||||
|
||||
// auto size the grid, that is make the columns/rows of the "right" size
|
||||
// and also set the grid size to just fit its contents
|
||||
@@ -2414,10 +2435,6 @@ protected:
|
||||
wxColour m_gridFrozenBorderColour;
|
||||
int m_gridFrozenBorderPenWidth;
|
||||
|
||||
// common part of AutoSizeColumn/Row() and GetBestSize()
|
||||
int SetOrCalcColumnSizes(bool calcOnly, bool setAsMin = true);
|
||||
int SetOrCalcRowSizes(bool calcOnly, bool setAsMin = true);
|
||||
|
||||
// common part of AutoSizeColumn/Row()
|
||||
void AutoSizeColOrRow(int n, bool setAsMin, wxGridDirection direction);
|
||||
|
||||
|
@@ -57,6 +57,13 @@ protected:
|
||||
class WXDLLIMPEXP_ADV wxGridCellNumberRenderer : public wxGridCellStringRenderer
|
||||
{
|
||||
public:
|
||||
explicit wxGridCellNumberRenderer(long minValue = LONG_MIN,
|
||||
long maxValue = LONG_MAX)
|
||||
: m_minValue(minValue),
|
||||
m_maxValue(maxValue)
|
||||
{
|
||||
}
|
||||
|
||||
// draw the string right aligned
|
||||
virtual void Draw(wxGrid& grid,
|
||||
wxGridCellAttr& attr,
|
||||
@@ -70,11 +77,21 @@ public:
|
||||
wxDC& dc,
|
||||
int row, int col) wxOVERRIDE;
|
||||
|
||||
virtual wxSize GetMaxBestSize(wxGrid& grid,
|
||||
wxGridCellAttr& attr,
|
||||
wxDC& dc) wxOVERRIDE;
|
||||
|
||||
// Optional parameters for this renderer are "<min>,<max>".
|
||||
virtual void SetParameters(const wxString& params) wxOVERRIDE;
|
||||
|
||||
virtual wxGridCellRenderer *Clone() const wxOVERRIDE
|
||||
{ return new wxGridCellNumberRenderer; }
|
||||
{ return new wxGridCellNumberRenderer(m_minValue, m_maxValue); }
|
||||
|
||||
protected:
|
||||
wxString GetString(const wxGrid& grid, int row, int col);
|
||||
|
||||
long m_minValue,
|
||||
m_maxValue;
|
||||
};
|
||||
|
||||
class WXDLLIMPEXP_ADV wxGridCellFloatRenderer : public wxGridCellStringRenderer
|
||||
@@ -141,6 +158,10 @@ public:
|
||||
wxDC& dc,
|
||||
int row, int col) wxOVERRIDE;
|
||||
|
||||
virtual wxSize GetMaxBestSize(wxGrid& grid,
|
||||
wxGridCellAttr& attr,
|
||||
wxDC& dc) wxOVERRIDE;
|
||||
|
||||
virtual wxGridCellRenderer *Clone() const wxOVERRIDE
|
||||
{ return new wxGridCellBoolRenderer; }
|
||||
};
|
||||
@@ -175,6 +196,10 @@ public:
|
||||
wxDC& dc,
|
||||
int row, int col) wxOVERRIDE;
|
||||
|
||||
virtual wxSize GetMaxBestSize(wxGrid& grid,
|
||||
wxGridCellAttr& attr,
|
||||
wxDC& dc) wxOVERRIDE;
|
||||
|
||||
virtual wxGridCellRenderer *Clone() const wxOVERRIDE;
|
||||
|
||||
// output strptime()-like format string
|
||||
@@ -213,8 +238,37 @@ protected:
|
||||
|
||||
#endif // wxUSE_DATETIME
|
||||
|
||||
// Renderer for fields taking one of a limited set of values: this is the same
|
||||
// as the renderer for strings, except that it can implement GetMaxBestSize().
|
||||
class WXDLLIMPEXP_ADV wxGridCellChoiceRenderer : public wxGridCellStringRenderer
|
||||
{
|
||||
public:
|
||||
wxGridCellChoiceRenderer() { }
|
||||
|
||||
virtual wxSize GetMaxBestSize(wxGrid& grid,
|
||||
wxGridCellAttr& attr,
|
||||
wxDC& dc) wxOVERRIDE;
|
||||
|
||||
// Parameters string is a comma-separated list of values.
|
||||
virtual void SetParameters(const wxString& params) wxOVERRIDE;
|
||||
|
||||
virtual wxGridCellRenderer *Clone() const wxOVERRIDE
|
||||
{
|
||||
return new wxGridCellChoiceRenderer(*this);
|
||||
}
|
||||
|
||||
protected:
|
||||
wxGridCellChoiceRenderer(const wxGridCellChoiceRenderer& other)
|
||||
: m_choices(other.m_choices)
|
||||
{
|
||||
}
|
||||
|
||||
wxArrayString m_choices;
|
||||
};
|
||||
|
||||
|
||||
// renders a number using the corresponding text string
|
||||
class WXDLLIMPEXP_ADV wxGridCellEnumRenderer : public wxGridCellStringRenderer
|
||||
class WXDLLIMPEXP_ADV wxGridCellEnumRenderer : public wxGridCellChoiceRenderer
|
||||
{
|
||||
public:
|
||||
wxGridCellEnumRenderer( const wxString& choices = wxEmptyString );
|
||||
@@ -234,14 +288,8 @@ public:
|
||||
|
||||
virtual wxGridCellRenderer *Clone() const wxOVERRIDE;
|
||||
|
||||
// parameters string format is "item1[,item2[...,itemN]]" where itemN will
|
||||
// be used if the cell value is N-1
|
||||
virtual void SetParameters(const wxString& params) wxOVERRIDE;
|
||||
|
||||
protected:
|
||||
wxString GetString(const wxGrid& grid, int row, int col);
|
||||
|
||||
wxArrayString m_choices;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -88,6 +88,26 @@ public:
|
||||
virtual int GetBestWidth(wxGrid& grid, wxGridCellAttr& attr, wxDC& dc,
|
||||
int row, int col, int height);
|
||||
|
||||
/**
|
||||
Get the maximum possible size for a cell using this renderer, if
|
||||
possible.
|
||||
|
||||
This function may be overridden in the derived class if it can return
|
||||
the maximum size needed for displaying the cells rendered it without
|
||||
iterating over all cells. The base class version simply returns
|
||||
::wxDefaultSize, indicating that this is infeasible and that
|
||||
GetBestSize() should be called for each cell individually.
|
||||
|
||||
Note that this method will only be used if
|
||||
wxGridTableBase::CanMeasureColUsingSameAttr() is overriden to return
|
||||
@true.
|
||||
|
||||
@since 3.1.4
|
||||
*/
|
||||
virtual wxSize GetMaxBestSize(wxGrid& grid,
|
||||
wxGridCellAttr& attr,
|
||||
wxDC& dc);
|
||||
|
||||
protected:
|
||||
/**
|
||||
The destructor is private because only DecRef() can delete us.
|
||||
@@ -2517,6 +2537,25 @@ public:
|
||||
returns @true.
|
||||
*/
|
||||
virtual bool CanHaveAttributes();
|
||||
|
||||
/**
|
||||
Override to return true if the same attribute can be used for measuring
|
||||
all cells in the given column.
|
||||
|
||||
This function is provided for optimization purposes: it returns @false
|
||||
by default, but can be overridden to return @true when all the cells in
|
||||
the same grid column use sensibly the same attribute, i.e. they use the
|
||||
same renderer (either explicitly, or implicitly, due to their type as
|
||||
returned by GetTypeName()) and the font of the same size.
|
||||
|
||||
Returning @true from this function allows AutoSizeColumns() to skip
|
||||
looking up the attribute and the renderer for each individual cell,
|
||||
which results in very noticeable performance improvements for the grids
|
||||
with many rows.
|
||||
|
||||
@since 3.1.4
|
||||
*/
|
||||
virtual bool CanMeasureColUsingSameAttr(int col) const;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -105,17 +105,27 @@ void wxTextMeasureBase::GetMultiLineTextExtent(const wxString& text,
|
||||
wxCoord *height,
|
||||
wxCoord *heightOneLine)
|
||||
{
|
||||
// It's noticeably faster to handle the case of a string which isn't
|
||||
// actually multiline specially here, to skip iteration above in this case.
|
||||
if ( text.find('\n') == wxString::npos )
|
||||
{
|
||||
GetTextExtent(text, width, height);
|
||||
if ( heightOneLine && height )
|
||||
*heightOneLine = *height;
|
||||
return;
|
||||
}
|
||||
|
||||
MeasuringGuard guard(*this);
|
||||
|
||||
wxCoord widthTextMax = 0, widthLine,
|
||||
heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
|
||||
|
||||
wxString curLine;
|
||||
wxString::const_iterator lineStart = text.begin();
|
||||
for ( wxString::const_iterator pc = text.begin(); ; ++pc )
|
||||
{
|
||||
if ( pc == text.end() || *pc == wxS('\n') )
|
||||
{
|
||||
if ( curLine.empty() )
|
||||
if ( pc == lineStart )
|
||||
{
|
||||
// we can't use GetTextExtent - it will return 0 for both width
|
||||
// and height and an empty line should count in height
|
||||
@@ -137,7 +147,7 @@ void wxTextMeasureBase::GetMultiLineTextExtent(const wxString& text,
|
||||
}
|
||||
else
|
||||
{
|
||||
CallGetTextExtent(curLine, &widthLine, &heightLine);
|
||||
CallGetTextExtent(wxString(lineStart, pc), &widthLine, &heightLine);
|
||||
if ( widthLine > widthTextMax )
|
||||
widthTextMax = widthLine;
|
||||
heightTextTotal += heightLine;
|
||||
@@ -149,13 +159,10 @@ void wxTextMeasureBase::GetMultiLineTextExtent(const wxString& text,
|
||||
}
|
||||
else // '\n'
|
||||
{
|
||||
curLine.clear();
|
||||
lineStart = pc;
|
||||
++lineStart;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
curLine += *pc;
|
||||
}
|
||||
}
|
||||
|
||||
if ( width )
|
||||
|
@@ -9967,6 +9967,14 @@ wxGrid::AutoSizeColOrRow(int colOrRow, bool setAsMin, wxGridDirection direction)
|
||||
col = -1;
|
||||
}
|
||||
|
||||
// If possible, reuse the same attribute and renderer for all cells: this
|
||||
// is an important optimization (resulting in up to 80% speed up of
|
||||
// AutoSizeColumns()) as finding the attribute and renderer for the cell
|
||||
// are very slow operations, due to the number of steps involved in them.
|
||||
const bool canReuseAttr = column && m_table->CanMeasureColUsingSameAttr(col);
|
||||
wxGridCellAttrPtr attr;
|
||||
wxGridCellRendererPtr renderer;
|
||||
|
||||
wxCoord extent, extentMax = 0;
|
||||
int max = column ? m_numRows : m_numCols;
|
||||
for ( int rowOrCol = 0; rowOrCol < max; rowOrCol++ )
|
||||
@@ -10005,8 +10013,27 @@ wxGrid::AutoSizeColOrRow(int colOrRow, bool setAsMin, wxGridDirection direction)
|
||||
}
|
||||
|
||||
// get cell ( main cell if CellSpan_Inside ) renderer best size
|
||||
wxGridCellAttrPtr attr = GetCellAttrPtr(row, col);
|
||||
wxGridCellRendererPtr renderer = attr->GetRendererPtr(this, row, col);
|
||||
if ( !canReuseAttr || !attr )
|
||||
{
|
||||
attr = GetCellAttrPtr(row, col);
|
||||
renderer = attr->GetRendererPtr(this, row, col);
|
||||
|
||||
if ( canReuseAttr )
|
||||
{
|
||||
// Try to get the best width for the entire column at once, if
|
||||
// it's supported by the renderer.
|
||||
extent = renderer->GetMaxBestSize(*this, *attr, dc).x;
|
||||
|
||||
if ( extent != wxDefaultCoord )
|
||||
{
|
||||
extentMax = extent;
|
||||
|
||||
// No need to check all the values.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( renderer )
|
||||
{
|
||||
extent = column
|
||||
@@ -10206,50 +10233,28 @@ wxCoord wxGrid::CalcColOrRowLabelAreaMinSize(wxGridDirection direction)
|
||||
return extentMax;
|
||||
}
|
||||
|
||||
int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin)
|
||||
void wxGrid::AutoSizeColumns(bool setAsMin)
|
||||
{
|
||||
int width = m_rowLabelWidth;
|
||||
|
||||
wxGridUpdateLocker locker;
|
||||
if(!calcOnly)
|
||||
locker.Create(this);
|
||||
wxGridUpdateLocker locker(this);
|
||||
|
||||
for ( int col = 0; col < m_numCols; col++ )
|
||||
{
|
||||
if ( !calcOnly )
|
||||
AutoSizeColumn(col, setAsMin);
|
||||
|
||||
width += GetColWidth(col);
|
||||
}
|
||||
|
||||
return width;
|
||||
AutoSizeColumn(col, setAsMin);
|
||||
}
|
||||
|
||||
int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin)
|
||||
void wxGrid::AutoSizeRows(bool setAsMin)
|
||||
{
|
||||
int height = m_colLabelHeight;
|
||||
|
||||
wxGridUpdateLocker locker;
|
||||
if(!calcOnly)
|
||||
locker.Create(this);
|
||||
wxGridUpdateLocker locker(this);
|
||||
|
||||
for ( int row = 0; row < m_numRows; row++ )
|
||||
{
|
||||
if ( !calcOnly )
|
||||
AutoSizeRow(row, setAsMin);
|
||||
|
||||
height += GetRowHeight(row);
|
||||
}
|
||||
|
||||
return height;
|
||||
AutoSizeRow(row, setAsMin);
|
||||
}
|
||||
|
||||
void wxGrid::AutoSize()
|
||||
{
|
||||
wxGridUpdateLocker locker(this);
|
||||
|
||||
wxSize size(SetOrCalcColumnSizes(false) - m_rowLabelWidth + m_extraWidth,
|
||||
SetOrCalcRowSizes(false) - m_colLabelHeight + m_extraHeight);
|
||||
AutoSizeColumns();
|
||||
AutoSizeRows();
|
||||
|
||||
// we know that we're not going to have scrollbars so disable them now to
|
||||
// avoid trouble in SetClientSize() which can otherwise set the correct
|
||||
@@ -10257,7 +10262,7 @@ void wxGrid::AutoSize()
|
||||
SetScrollbars(m_xScrollPixelsPerLine, m_yScrollPixelsPerLine,
|
||||
0, 0, 0, 0, true);
|
||||
|
||||
SetClientSize(size.x + m_rowLabelWidth, size.y + m_colLabelHeight);
|
||||
SetSize(DoGetBestSize());
|
||||
}
|
||||
|
||||
void wxGrid::AutoSizeRowLabelSize( int row )
|
||||
@@ -10294,15 +10299,30 @@ void wxGrid::AutoSizeColLabelSize( int col )
|
||||
|
||||
wxSize wxGrid::DoGetBestSize() const
|
||||
{
|
||||
wxGrid * const self = const_cast<wxGrid *>(this);
|
||||
wxSize size(m_rowLabelWidth + m_extraWidth,
|
||||
m_colLabelHeight + m_extraHeight);
|
||||
|
||||
// we do the same as in AutoSize() here with the exception that we don't
|
||||
// change the column/row sizes, only calculate them
|
||||
wxSize size(self->SetOrCalcColumnSizes(true) - m_rowLabelWidth + m_extraWidth,
|
||||
self->SetOrCalcRowSizes(true) - m_colLabelHeight + m_extraHeight);
|
||||
if ( m_colWidths.empty() )
|
||||
{
|
||||
size.x += m_defaultColWidth*m_numCols;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int col = 0; col < m_numCols; col++ )
|
||||
size.x += GetColWidth(col);
|
||||
}
|
||||
|
||||
return wxSize(size.x + m_rowLabelWidth, size.y + m_colLabelHeight)
|
||||
+ GetWindowBorderSize();
|
||||
if ( m_rowHeights.empty() )
|
||||
{
|
||||
size.y += m_defaultRowHeight*m_numRows;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int row = 0; row < m_numRows; row++ )
|
||||
size.y += GetRowHeight(row);
|
||||
}
|
||||
|
||||
return size + GetWindowBorderSize();
|
||||
}
|
||||
|
||||
void wxGrid::Fit()
|
||||
@@ -10997,7 +11017,7 @@ int wxGridTypeRegistry::FindDataType(const wxString& typeName)
|
||||
if ( typeName == wxGRID_VALUE_CHOICE )
|
||||
{
|
||||
RegisterDataType(wxGRID_VALUE_CHOICE,
|
||||
new wxGridCellStringRenderer,
|
||||
new wxGridCellChoiceRenderer,
|
||||
new wxGridCellChoiceEditor);
|
||||
}
|
||||
else
|
||||
|
@@ -165,6 +165,24 @@ wxSize wxGridCellDateRenderer::GetBestSize(wxGrid& grid,
|
||||
return DoGetBestSize(attr, dc, GetString(grid, row, col));
|
||||
}
|
||||
|
||||
wxSize wxGridCellDateRenderer::GetMaxBestSize(wxGrid& WXUNUSED(grid),
|
||||
wxGridCellAttr& attr,
|
||||
wxDC& dc)
|
||||
{
|
||||
wxSize size;
|
||||
|
||||
// Try to produce the longest string in the current format: as we don't
|
||||
// know which month is the longest, we need to try all of them.
|
||||
for ( int m = wxDateTime::Jan; m <= wxDateTime::Dec; ++m )
|
||||
{
|
||||
const wxDateTime d(28, static_cast<wxDateTime::Month>(m), 9999);
|
||||
|
||||
size.IncTo(DoGetBestSize(attr, dc, d.Format(m_oformat, m_tz)));
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void wxGridCellDateRenderer::SetParameters(const wxString& params)
|
||||
{
|
||||
if (!params.empty())
|
||||
@@ -194,6 +212,38 @@ bool wxGridCellDateTimeRenderer::Parse(const wxString& text, wxDateTime& result)
|
||||
|
||||
#endif // wxUSE_DATETIME
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxGridCellChoiceRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxSize wxGridCellChoiceRenderer::GetMaxBestSize(wxGrid& WXUNUSED(grid),
|
||||
wxGridCellAttr& attr,
|
||||
wxDC& dc)
|
||||
{
|
||||
wxSize size;
|
||||
|
||||
for ( size_t n = 0; n < m_choices.size(); ++n )
|
||||
{
|
||||
size.IncTo(DoGetBestSize(attr, dc, m_choices[n]));
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void wxGridCellChoiceRenderer::SetParameters(const wxString& params)
|
||||
{
|
||||
m_choices.clear();
|
||||
|
||||
if ( params.empty() )
|
||||
return;
|
||||
|
||||
wxStringTokenizer tk(params, wxT(','));
|
||||
while ( tk.HasMoreTokens() )
|
||||
{
|
||||
m_choices.Add(tk.GetNextToken());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxGridCellEnumRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -260,24 +310,6 @@ wxSize wxGridCellEnumRenderer::GetBestSize(wxGrid& grid,
|
||||
return DoGetBestSize(attr, dc, GetString(grid, row, col));
|
||||
}
|
||||
|
||||
void wxGridCellEnumRenderer::SetParameters(const wxString& params)
|
||||
{
|
||||
if ( !params )
|
||||
{
|
||||
// what can we do?
|
||||
return;
|
||||
}
|
||||
|
||||
m_choices.Empty();
|
||||
|
||||
wxStringTokenizer tk(params, wxT(','));
|
||||
while ( tk.HasMoreTokens() )
|
||||
{
|
||||
m_choices.Add(tk.GetNextToken());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxGridCellAutoWrapStringRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -557,18 +589,8 @@ wxSize wxGridCellStringRenderer::DoGetBestSize(const wxGridCellAttr& attr,
|
||||
wxDC& dc,
|
||||
const wxString& text)
|
||||
{
|
||||
wxCoord x = 0, y = 0, max_x = 0;
|
||||
dc.SetFont(attr.GetFont());
|
||||
wxStringTokenizer tk(text, wxT('\n'));
|
||||
while ( tk.HasMoreTokens() )
|
||||
{
|
||||
dc.GetTextExtent(tk.GetNextToken(), &x, &y);
|
||||
max_x = wxMax(max_x, x);
|
||||
}
|
||||
|
||||
y *= 1 + text.Freq(wxT('\n')); // multiply by the number of lines.
|
||||
|
||||
return wxSize(max_x, y);
|
||||
return dc.GetMultiLineTextExtent(text);
|
||||
}
|
||||
|
||||
wxSize wxGridCellStringRenderer::GetBestSize(wxGrid& grid,
|
||||
@@ -726,6 +748,34 @@ wxSize wxGridCellNumberRenderer::GetBestSize(wxGrid& grid,
|
||||
return DoGetBestSize(attr, dc, GetString(grid, row, col));
|
||||
}
|
||||
|
||||
wxSize wxGridCellNumberRenderer::GetMaxBestSize(wxGrid& WXUNUSED(grid),
|
||||
wxGridCellAttr& attr,
|
||||
wxDC& dc)
|
||||
{
|
||||
// In theory, it's possible that there is a value in min..max range which
|
||||
// is longer than both min and max, e.g. we could conceivably have "88" be
|
||||
// wider than both "87" and "91" with some fonts, but it seems something
|
||||
// too exotic to worry about in practice.
|
||||
wxSize size = DoGetBestSize(attr, dc, wxString::Format("%ld", m_minValue));
|
||||
size.IncTo(DoGetBestSize(attr, dc, wxString::Format("%ld", m_maxValue)));
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void wxGridCellNumberRenderer::SetParameters(const wxString& params)
|
||||
{
|
||||
if ( params.empty() )
|
||||
return;
|
||||
|
||||
wxString maxStr;
|
||||
const wxString minStr = params.BeforeFirst(',', &maxStr);
|
||||
|
||||
if ( !minStr.ToLong(&m_minValue) || !maxStr.ToLong(&m_maxValue) )
|
||||
{
|
||||
wxLogDebug("Invalid wxGridCellNumberRenderer parameters \"%s\"", params);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxGridCellFloatRenderer
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -922,10 +972,17 @@ void wxGridCellFloatRenderer::SetParameters(const wxString& params)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
wxSize wxGridCellBoolRenderer::GetBestSize(wxGrid& grid,
|
||||
wxGridCellAttr& WXUNUSED(attr),
|
||||
wxDC& WXUNUSED(dc),
|
||||
wxGridCellAttr& attr,
|
||||
wxDC& dc,
|
||||
int WXUNUSED(row),
|
||||
int WXUNUSED(col))
|
||||
{
|
||||
return GetMaxBestSize(grid, attr, dc);
|
||||
}
|
||||
|
||||
wxSize wxGridCellBoolRenderer::GetMaxBestSize(wxGrid& grid,
|
||||
wxGridCellAttr& WXUNUSED(attr),
|
||||
wxDC& WXUNUSED(dc))
|
||||
{
|
||||
static wxPrivate::DpiDependentValue<wxSize> s_sizeCheckMark;
|
||||
|
||||
|
@@ -1451,22 +1451,12 @@ void wxGridCellChoiceEditor::SetSize(const wxRect& rect)
|
||||
wxASSERT_MSG(m_control,
|
||||
wxT("The wxGridCellChoiceEditor must be created first!"));
|
||||
|
||||
// Check that the height is not too small to fit the combobox.
|
||||
wxRect rectTallEnough = rect;
|
||||
const wxSize bestSize = m_control->GetBestSize();
|
||||
const wxCoord diffY = bestSize.GetHeight() - rectTallEnough.GetHeight();
|
||||
if ( diffY > 0 )
|
||||
{
|
||||
// Do make it tall enough.
|
||||
rectTallEnough.height += diffY;
|
||||
// Check that the rectangle is big enough to fit the combobox, we can't
|
||||
// afford truncating it.
|
||||
wxSize size = rect.GetSize();
|
||||
size.IncTo(m_control->GetBestSize());
|
||||
|
||||
// Also centre the effective rectangle vertically with respect to the
|
||||
// original one.
|
||||
rectTallEnough.y -= diffY/2;
|
||||
}
|
||||
//else: The rectangle provided is already tall enough.
|
||||
|
||||
wxGridCellEditor::SetSize(rectTallEnough);
|
||||
wxGridCellEditor::SetSize(wxRect(size).CentreIn(rect));
|
||||
}
|
||||
|
||||
void wxGridCellChoiceEditor::PaintBackground(wxDC& dc,
|
||||
|
@@ -108,7 +108,13 @@ void wxTextMeasure::DoGetTextExtent(const wxString& string,
|
||||
// the result computed by GetTextExtentPoint32() may be too small as it
|
||||
// accounts for under/overhang of the first/last character while we want
|
||||
// just the bounding rect for this string so adjust the width as needed
|
||||
if ( len > 0 )
|
||||
// when using italic fonts as the difference is really noticeable for them
|
||||
// (it may still exist, but seems to be at most 1px for the other fonts,
|
||||
// and calling GetCharABCWidths() is pretty slow and much slower than
|
||||
// calling GetTextExtentPoint32() itself, so avoid its overhead unless it's
|
||||
// really, really necessary).
|
||||
const wxFont font = GetFont();
|
||||
if ( font.IsOk() && font.GetStyle() != wxFONTSTYLE_NORMAL && len > 0 )
|
||||
{
|
||||
ABC widthABC;
|
||||
const wxChar chFirst = *string.begin();
|
||||
|
@@ -66,6 +66,7 @@ struct GraphicsBenchmarkOptions
|
||||
testCircles =
|
||||
testEllipses =
|
||||
testTextExtent =
|
||||
testMultiLineTextExtent =
|
||||
testPartialTextExtents = false;
|
||||
|
||||
usePaint =
|
||||
@@ -95,6 +96,7 @@ struct GraphicsBenchmarkOptions
|
||||
testCircles,
|
||||
testEllipses,
|
||||
testTextExtent,
|
||||
testMultiLineTextExtent,
|
||||
testPartialTextExtents;
|
||||
|
||||
bool usePaint,
|
||||
@@ -634,7 +636,10 @@ private:
|
||||
wxStopWatch sw;
|
||||
for ( long n = 0; n < opts.numIters; n++ )
|
||||
{
|
||||
size += dc.GetTextExtent(str);
|
||||
if ( opts.testMultiLineTextExtent )
|
||||
size += dc.GetMultiLineTextExtent(str);
|
||||
else
|
||||
size += dc.GetTextExtent(str);
|
||||
}
|
||||
|
||||
const long t = sw.Time();
|
||||
@@ -847,6 +852,7 @@ public:
|
||||
{ wxCMD_LINE_SWITCH, "", "circles" },
|
||||
{ wxCMD_LINE_SWITCH, "", "ellipses" },
|
||||
{ wxCMD_LINE_SWITCH, "", "textextent" },
|
||||
{ wxCMD_LINE_SWITCH, "", "multilinetextextent" },
|
||||
{ wxCMD_LINE_SWITCH, "", "partialtextextents" },
|
||||
{ wxCMD_LINE_SWITCH, "", "paint" },
|
||||
{ wxCMD_LINE_SWITCH, "", "client" },
|
||||
@@ -922,6 +928,7 @@ public:
|
||||
opts.testCircles = parser.Found("circles");
|
||||
opts.testEllipses = parser.Found("ellipses");
|
||||
opts.testTextExtent = parser.Found("textextent");
|
||||
opts.testMultiLineTextExtent = parser.Found("multilinetextextent");
|
||||
opts.testPartialTextExtents = parser.Found("partialtextextents");
|
||||
if ( !(opts.testBitmaps || opts.testImages || opts.testLines
|
||||
|| opts.testRawBitmaps || opts.testRectangles
|
||||
|
Reference in New Issue
Block a user