Applied #9956 (wxGenericTreeControl: Cache GetTextExtent results to greatly speedup CalculatePositions)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_8_BRANCH@62184 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -126,6 +126,7 @@ All (GUI):
|
||||
dialog.
|
||||
- Corrected writing direction for Farsi.
|
||||
- Added wxBORDER_THEME to XRC.
|
||||
- Speeded up wxTreeCtrl by caching text size (botg).
|
||||
|
||||
wxMSW:
|
||||
|
||||
|
@@ -137,7 +137,12 @@ class WXDLLEXPORT wxGenericTreeItem
|
||||
{
|
||||
public:
|
||||
// ctors & dtor
|
||||
wxGenericTreeItem() { m_data = NULL; }
|
||||
wxGenericTreeItem() {
|
||||
m_data = NULL;
|
||||
m_widthText =
|
||||
m_heightText = -1;
|
||||
}
|
||||
|
||||
wxGenericTreeItem( wxGenericTreeItem *parent,
|
||||
const wxString& text,
|
||||
int image,
|
||||
@@ -158,13 +163,29 @@ public:
|
||||
// selected/expanded/whatever state)
|
||||
int GetCurrentImage() const;
|
||||
|
||||
void SetText( const wxString &text );
|
||||
void SetImage(int image, wxTreeItemIcon which) { m_images[which] = image; }
|
||||
void SetText(const wxString& text)
|
||||
{
|
||||
m_text = text;
|
||||
|
||||
ResetTextSize();
|
||||
}
|
||||
|
||||
void SetImage(int image, wxTreeItemIcon which)
|
||||
{
|
||||
m_images[which] = image;
|
||||
m_width = 0;
|
||||
}
|
||||
|
||||
void SetData(wxTreeItemData *data) { m_data = data; }
|
||||
|
||||
void SetHasPlus(bool has = true) { m_hasPlus = has; }
|
||||
|
||||
void SetBold(bool bold) { m_isBold = bold; }
|
||||
void SetBold(bool bold)
|
||||
{
|
||||
m_isBold = bold;
|
||||
|
||||
ResetTextSize();
|
||||
}
|
||||
|
||||
int GetX() const { return m_x; }
|
||||
int GetY() const { return m_y; }
|
||||
@@ -172,14 +193,43 @@ public:
|
||||
void SetX(int x) { m_x = x; }
|
||||
void SetY(int y) { m_y = y; }
|
||||
|
||||
int GetHeight() const { return m_height; }
|
||||
int GetWidth() const { return m_width; }
|
||||
int GetHeight() const { return m_height; }
|
||||
int GetWidth() const { return m_width; }
|
||||
|
||||
void SetHeight(int h) { m_height = h; }
|
||||
void SetWidth(int w) { m_width = w; }
|
||||
int GetTextHeight() const
|
||||
{
|
||||
wxASSERT_MSG( m_heightText != -1, _T("must call CalculateSize() first") );
|
||||
|
||||
return m_heightText;
|
||||
}
|
||||
|
||||
int GetTextWidth() const
|
||||
{
|
||||
wxASSERT_MSG( m_widthText != -1, _T("must call CalculateSize() first") );
|
||||
|
||||
return m_widthText;
|
||||
}
|
||||
|
||||
wxGenericTreeItem *GetParent() const { return m_parent; }
|
||||
|
||||
// sets the items font for the specified DC if it uses any special font or
|
||||
// simply returns false otherwise
|
||||
bool SetFont(wxGenericTreeCtrl *control, wxDC& dc) const
|
||||
{
|
||||
wxFont font;
|
||||
|
||||
wxTreeItemAttr * const attr = GetAttributes();
|
||||
if ( attr && attr->HasFont() )
|
||||
font = attr->GetFont();
|
||||
else if ( IsBold() )
|
||||
font = control->m_boldFont;
|
||||
else
|
||||
return false;
|
||||
|
||||
dc.SetFont(font);
|
||||
return true;
|
||||
}
|
||||
|
||||
// operations
|
||||
|
||||
// deletes all children notifying the treectrl about it
|
||||
@@ -189,13 +239,25 @@ public:
|
||||
size_t GetChildrenCount(bool recursively = true) const;
|
||||
|
||||
void Insert(wxGenericTreeItem *child, size_t index)
|
||||
{ m_children.Insert(child, index); }
|
||||
{ m_children.Insert(child, index); }
|
||||
|
||||
// calculate and cache the item size using either the provided DC (which is
|
||||
// supposed to have wxGenericTreeCtrl::m_normalFont selected into it!) or a
|
||||
// wxClientDC on the control window
|
||||
void CalculateSize(wxGenericTreeCtrl *control, wxDC& dc)
|
||||
{ DoCalculateSize(control, dc, true /* dc uses normal font */); }
|
||||
void CalculateSize(wxGenericTreeCtrl *control);
|
||||
|
||||
void GetSize( int &x, int &y, const wxGenericTreeCtrl* );
|
||||
|
||||
// return the item at given position (or NULL if no item), onButton is
|
||||
// true if the point belongs to the item's button, otherwise it lies
|
||||
// on the item's label
|
||||
void ResetSize() { m_width = 0; }
|
||||
void ResetTextSize() { m_width = 0; m_widthText = -1; }
|
||||
void RecursiveResetSize();
|
||||
void RecursiveResetTextSize();
|
||||
|
||||
// return the item at given position (or NULL if no item), onButton is
|
||||
// true if the point belongs to the item's button, otherwise it lies
|
||||
// on the item's label
|
||||
wxGenericTreeItem *HitTest( const wxPoint& point,
|
||||
const wxGenericTreeCtrl *,
|
||||
int &flags,
|
||||
@@ -232,19 +294,34 @@ public:
|
||||
if ( m_ownsAttr ) delete m_attr;
|
||||
m_attr = attr;
|
||||
m_ownsAttr = false;
|
||||
m_width = 0;
|
||||
m_widthText = -1;
|
||||
}
|
||||
// set them and delete when done
|
||||
void AssignAttributes(wxTreeItemAttr *attr)
|
||||
{
|
||||
SetAttributes(attr);
|
||||
m_ownsAttr = true;
|
||||
m_width = 0;
|
||||
m_widthText = -1;
|
||||
}
|
||||
|
||||
private:
|
||||
// calculate the size of this item, i.e. set m_width, m_height and
|
||||
// m_widthText and m_heightText properly
|
||||
//
|
||||
// if dcUsesNormalFont is true, the current dc font must be the normal tree
|
||||
// control font
|
||||
void DoCalculateSize(wxGenericTreeCtrl *control,
|
||||
wxDC& dc,
|
||||
bool dcUsesNormalFont);
|
||||
|
||||
// since there can be very many of these, we save size by chosing
|
||||
// the smallest representation for the elements and by ordering
|
||||
// the members to avoid padding.
|
||||
wxString m_text; // label to be rendered for item
|
||||
int m_widthText;
|
||||
int m_heightText;
|
||||
|
||||
wxTreeItemData *m_data; // user-provided data
|
||||
|
||||
@@ -524,6 +601,9 @@ wxGenericTreeItem::wxGenericTreeItem(wxGenericTreeItem *parent,
|
||||
// We don't know the height here yet.
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
|
||||
m_widthText = -1;
|
||||
m_heightText = -1;
|
||||
}
|
||||
|
||||
wxGenericTreeItem::~wxGenericTreeItem()
|
||||
@@ -553,11 +633,6 @@ void wxGenericTreeItem::DeleteChildren(wxGenericTreeCtrl *tree)
|
||||
m_children.Empty();
|
||||
}
|
||||
|
||||
void wxGenericTreeItem::SetText( const wxString &text )
|
||||
{
|
||||
m_text = text;
|
||||
}
|
||||
|
||||
size_t wxGenericTreeItem::GetChildrenCount(bool recursively) const
|
||||
{
|
||||
size_t count = m_children.Count();
|
||||
@@ -702,6 +777,97 @@ int wxGenericTreeItem::GetCurrentImage() const
|
||||
return image;
|
||||
}
|
||||
|
||||
void wxGenericTreeItem::CalculateSize(wxGenericTreeCtrl* control)
|
||||
{
|
||||
// check if we need to do anything before creating the DC
|
||||
if ( m_width != 0 )
|
||||
return;
|
||||
|
||||
wxClientDC dc(control);
|
||||
DoCalculateSize(control, dc, false /* normal font not used */);
|
||||
}
|
||||
|
||||
void
|
||||
wxGenericTreeItem::DoCalculateSize(wxGenericTreeCtrl* control,
|
||||
wxDC& dc,
|
||||
bool dcUsesNormalFont)
|
||||
{
|
||||
if ( m_width != 0 ) // Size known, nothing to do
|
||||
return;
|
||||
|
||||
if ( m_widthText == -1 )
|
||||
{
|
||||
bool fontChanged;
|
||||
if ( SetFont(control, dc) )
|
||||
{
|
||||
fontChanged = true;
|
||||
}
|
||||
else // we have no special font
|
||||
{
|
||||
if ( !dcUsesNormalFont )
|
||||
{
|
||||
// but we do need to ensure that the normal font is used: notice
|
||||
// that this doesn't count as changing the font as we don't need
|
||||
// to restore it
|
||||
dc.SetFont(control->m_normalFont);
|
||||
}
|
||||
|
||||
fontChanged = false;
|
||||
}
|
||||
|
||||
dc.GetTextExtent( GetText(), &m_widthText, &m_heightText );
|
||||
|
||||
// restore normal font if the DC used it previously and we changed it
|
||||
if ( fontChanged )
|
||||
dc.SetFont(control->m_normalFont);
|
||||
}
|
||||
|
||||
int text_h = m_heightText + 2;
|
||||
|
||||
int image_h = 0;
|
||||
int image_w = 0;
|
||||
int image = GetCurrentImage();
|
||||
if ( image != NO_IMAGE )
|
||||
{
|
||||
if ( control->m_imageListNormal )
|
||||
{
|
||||
control->m_imageListNormal->GetSize( image, image_w, image_h );
|
||||
image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT;
|
||||
}
|
||||
}
|
||||
|
||||
m_height = (image_h > text_h) ? image_h : text_h;
|
||||
|
||||
if (m_height < 30)
|
||||
m_height += 2; // at least 2 pixels
|
||||
else
|
||||
m_height += m_height / 10; // otherwise 10% extra spacing
|
||||
|
||||
if (m_height > control->m_lineHeight)
|
||||
control->m_lineHeight = m_height;
|
||||
|
||||
m_width = image_w + m_widthText + 2;
|
||||
}
|
||||
|
||||
void wxGenericTreeItem::RecursiveResetSize()
|
||||
{
|
||||
m_width = 0;
|
||||
|
||||
const size_t count = m_children.Count();
|
||||
for (size_t i = 0; i < count; i++ )
|
||||
m_children[i]->RecursiveResetSize();
|
||||
}
|
||||
|
||||
void wxGenericTreeItem::RecursiveResetTextSize()
|
||||
{
|
||||
m_width = 0;
|
||||
m_widthText = -1;
|
||||
|
||||
const size_t count = m_children.Count();
|
||||
for (size_t i = 0; i < count; i++ )
|
||||
m_children[i]->RecursiveResetTextSize();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// wxGenericTreeCtrl implementation
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -970,10 +1136,9 @@ void wxGenericTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& te
|
||||
{
|
||||
wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
|
||||
|
||||
wxClientDC dc(this);
|
||||
wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem;
|
||||
pItem->SetText(text);
|
||||
CalculateSize(pItem, dc);
|
||||
pItem->CalculateSize(this);
|
||||
RefreshLine(pItem);
|
||||
}
|
||||
|
||||
@@ -985,9 +1150,7 @@ void wxGenericTreeCtrl::SetItemImage(const wxTreeItemId& item,
|
||||
|
||||
wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem;
|
||||
pItem->SetImage(image, which);
|
||||
|
||||
wxClientDC dc(this);
|
||||
CalculateSize(pItem, dc);
|
||||
pItem->CalculateSize(this);
|
||||
RefreshLine(pItem);
|
||||
}
|
||||
|
||||
@@ -1022,10 +1185,7 @@ void wxGenericTreeCtrl::SetItemBold(const wxTreeItemId& item, bool bold)
|
||||
|
||||
// recalculate the item size as bold and non bold fonts have different
|
||||
// widths
|
||||
wxClientDC dc(this);
|
||||
CalculateSize(pItem, dc);
|
||||
|
||||
RefreshLine(pItem);
|
||||
pItem->CalculateSize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1073,7 +1233,8 @@ void wxGenericTreeCtrl::SetItemFont(const wxTreeItemId& item, const wxFont& font
|
||||
wxCHECK_RET( item.IsOk(), wxT("invalid tree item") );
|
||||
|
||||
wxGenericTreeItem *pItem = (wxGenericTreeItem*) item.m_pItem;
|
||||
pItem->Attr().SetFont(font);
|
||||
pItem->ResetTextSize();
|
||||
pItem->CalculateSize(this);
|
||||
RefreshLine(pItem);
|
||||
}
|
||||
|
||||
@@ -1090,6 +1251,9 @@ bool wxGenericTreeCtrl::SetFont( const wxFont &font )
|
||||
m_normalFont.GetFaceName(),
|
||||
m_normalFont.GetEncoding());
|
||||
|
||||
if (m_anchor)
|
||||
m_anchor->RecursiveResetTextSize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2100,6 +2264,10 @@ void wxGenericTreeCtrl::SetImageList(wxImageList *imageList)
|
||||
m_imageListNormal = imageList;
|
||||
m_ownsImageListNormal = false;
|
||||
m_dirty = true;
|
||||
|
||||
if (m_anchor)
|
||||
m_anchor->RecursiveResetSize();
|
||||
|
||||
// Don't do any drawing if we're setting the list to NULL,
|
||||
// since we may be in the process of deleting the tree control.
|
||||
if (imageList)
|
||||
@@ -2119,6 +2287,10 @@ void wxGenericTreeCtrl::SetButtonsImageList(wxImageList *imageList)
|
||||
m_imageListButtons = imageList;
|
||||
m_ownsImageListButtons = false;
|
||||
m_dirty = true;
|
||||
|
||||
if (m_anchor)
|
||||
m_anchor->RecursiveResetSize();
|
||||
|
||||
CalculateLineHeight();
|
||||
}
|
||||
|
||||
@@ -2160,16 +2332,9 @@ int wxGenericTreeCtrl::GetLineHeight(wxGenericTreeItem *item) const
|
||||
|
||||
void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
|
||||
{
|
||||
// TODO implement "state" icon on items
|
||||
item->SetFont(this, dc);
|
||||
|
||||
wxTreeItemAttr *attr = item->GetAttributes();
|
||||
if ( attr && attr->HasFont() )
|
||||
dc.SetFont(attr->GetFont());
|
||||
else if (item->IsBold())
|
||||
dc.SetFont(m_boldFont);
|
||||
|
||||
long text_w = 0, text_h = 0;
|
||||
dc.GetTextExtent( item->GetText(), &text_w, &text_h );
|
||||
wxCoord text_h = item->GetTextHeight();
|
||||
|
||||
int image_h = 0, image_w = 0;
|
||||
int image = item->GetCurrentImage();
|
||||
@@ -2187,7 +2352,8 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
|
||||
}
|
||||
|
||||
int total_h = GetLineHeight(item);
|
||||
bool drawItemBackground = false;
|
||||
bool drawItemBackground = false,
|
||||
hasBgColour = false;
|
||||
|
||||
if ( item->IsSelected() )
|
||||
{
|
||||
@@ -2197,9 +2363,11 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
|
||||
else
|
||||
{
|
||||
wxColour colBg;
|
||||
wxTreeItemAttr * const attr = item->GetAttributes();
|
||||
if ( attr && attr->HasBackgroundColour() )
|
||||
{
|
||||
drawItemBackground = true;
|
||||
drawItemBackground =
|
||||
hasBgColour = true;
|
||||
colBg = attr->GetBackgroundColour();
|
||||
}
|
||||
else
|
||||
@@ -2271,7 +2439,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
|
||||
#if !defined(__WXGTK20__) && !defined(__WXMAC__)
|
||||
dc.DrawRectangle( rect );
|
||||
#else
|
||||
if ( attr && attr->HasBackgroundColour() )
|
||||
if ( hasBgColour )
|
||||
{
|
||||
dc.DrawRectangle( rect );
|
||||
}
|
||||
@@ -3398,47 +3566,8 @@ void wxGenericTreeCtrl::OnInternalIdle()
|
||||
|
||||
void wxGenericTreeCtrl::CalculateSize( wxGenericTreeItem *item, wxDC &dc )
|
||||
{
|
||||
wxCoord text_w = 0;
|
||||
wxCoord text_h = 0;
|
||||
|
||||
wxTreeItemAttr *attr = item->GetAttributes();
|
||||
if ( attr && attr->HasFont() )
|
||||
dc.SetFont(attr->GetFont());
|
||||
else if ( item->IsBold() )
|
||||
dc.SetFont(m_boldFont);
|
||||
else
|
||||
dc.SetFont(m_normalFont);
|
||||
|
||||
dc.GetTextExtent( item->GetText(), &text_w, &text_h );
|
||||
text_h+=2;
|
||||
|
||||
// restore normal font
|
||||
dc.SetFont( m_normalFont );
|
||||
|
||||
int image_h = 0;
|
||||
int image_w = 0;
|
||||
int image = item->GetCurrentImage();
|
||||
if ( image != NO_IMAGE )
|
||||
{
|
||||
if ( m_imageListNormal )
|
||||
{
|
||||
m_imageListNormal->GetSize( image, image_w, image_h );
|
||||
image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT;
|
||||
}
|
||||
}
|
||||
|
||||
int total_h = (image_h > text_h) ? image_h : text_h;
|
||||
|
||||
if (total_h < 30)
|
||||
total_h += 2; // at least 2 pixels
|
||||
else
|
||||
total_h += total_h/10; // otherwise 10% extra spacing
|
||||
|
||||
item->SetHeight(total_h);
|
||||
if (total_h>m_lineHeight)
|
||||
m_lineHeight=total_h;
|
||||
|
||||
item->SetWidth(image_w+text_w+2);
|
||||
// Should not be called anymore
|
||||
// Does this function need to stay for ABI compatibility?
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -3458,7 +3587,7 @@ void wxGenericTreeCtrl::CalculateLevel( wxGenericTreeItem *item, wxDC &dc, int l
|
||||
goto Recurse;
|
||||
}
|
||||
|
||||
CalculateSize( item, dc );
|
||||
item->CalculateSize(this, dc);
|
||||
|
||||
// set its position
|
||||
item->SetX( x+m_spacing );
|
||||
|
Reference in New Issue
Block a user