Skip to content

Commit

Permalink
Generic wxTreeCtrl icons high DPI improvements
Browse files Browse the repository at this point in the history
See #22887.

(cherry picked from commit 2de6e8b)
  • Loading branch information
vadz committed Oct 18, 2022
1 parent 7c6b529 commit 8dd1375
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 32 deletions.
1 change: 1 addition & 0 deletions docs/changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ All (GUI):
- Improve wxWebView::RunScriptAsync() performance (Tobias Taschner, #22781).
- Fix data race when processing events generated in a worker thread.
- Fix compilation problem in wx/propgrid/editors.h (Loïc Bartoletti, #22875).
- Fix wxGenericTreeCtrl icons rendering in high DPI (Gerhard Stein, #22887).

wxGTK:

Expand Down
64 changes: 64 additions & 0 deletions include/wx/withimages.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,70 @@ class WXDLLIMPEXP_CORE wxWithImages
return m_imageList;
}

#if wxABI_VERSION >= 30202
// Return logical size of the image to use or (0, 0) if there are none.
wxSize GetImageLogicalSize(const wxWindow* window, int iconIndex) const
{
wxSize size;

if ( iconIndex != NO_IMAGE )
{
if ( !m_images.empty() )
{
size = m_images.at(iconIndex).GetPreferredLogicalSizeFor(window);
}
else if ( m_imageList )
{
// All images in the image list are of the same size.
size = m_imageList->GetSize();
}
}

return size;
}

// Overload provided to facilitate transition from the existing code using
// wxImageList::GetSize() -- don't use it in the new code.
void GetImageLogicalSize(const wxWindow* window, int iconIndex,
int& width, int& height) const
{
const wxSize size = GetImageLogicalSize(window, iconIndex);
width = size.x;
height = size.y;
}

// Return the bitmap to use at the current DPI of the given window.
//
// If index == NO_IMAGE, just returns wxNullBitmap.
wxBitmap GetImageBitmapFor(const wxWindow* window, int iconIndex) const
{
wxBitmap bitmap;

if ( iconIndex != NO_IMAGE )
{
if ( !m_images.empty() )
{
bitmap = m_images.at(iconIndex).GetBitmapFor(window);
}
else if ( m_imageList )
{
bitmap = m_imageList->GetBitmap(iconIndex);
}
else
{
wxFAIL_MSG
(
"Image index specified, but there are no images.\n"
"\n"
"Did you forget to call SetImages()?"
);
}
}

return bitmap;
}
#endif // wxABI_VERSION >= 3.2.2

protected:
// This function is called when the images associated with the control
// change, due to either SetImages() or SetImageList() being called.
Expand Down
52 changes: 21 additions & 31 deletions src/generic/treectlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest(const wxPoint& point,
if ( (GetImage() != NO_IMAGE) && theCtrl->HasImages() )
{
int image_h;
theCtrl->GetImageList()->GetSize(GetImage(),
theCtrl->GetImageLogicalSize(theCtrl, GetImage(),
image_w, image_h);
}

Expand Down Expand Up @@ -851,7 +851,7 @@ wxGenericTreeItem::DoCalculateSize(wxGenericTreeCtrl* control,
int image = GetCurrentImage();
if ( image != NO_IMAGE && control->HasImages() )
{
control->GetImageList()->GetSize(image, image_w, image_h);
control->GetImageLogicalSize(control, image, image_w, image_h);
image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT;
}

Expand Down Expand Up @@ -2385,7 +2385,7 @@ void wxGenericTreeCtrl::CalculateLineHeight()
for (int i = 0; i < n ; i++)
{
int width = 0, height = 0;
GetImageList()->GetSize(i, width, height);
GetImageLogicalSize(this, i, width, height);
if (height > m_lineHeight) m_lineHeight = height;
}
}
Expand All @@ -2399,7 +2399,7 @@ void wxGenericTreeCtrl::CalculateLineHeight()
for (int i = 0; i < n ; i++)
{
int width = 0, height = 0;
m_imagesState.GetImageList()->GetSize(i, width, height);
m_imagesState.GetImageLogicalSize(this, i, width, height);
if (height > m_lineHeight) m_lineHeight = height;
}
}
Expand All @@ -2413,7 +2413,7 @@ void wxGenericTreeCtrl::CalculateLineHeight()
for (int i = 0; i < n ; i++)
{
int width = 0, height = 0;
m_imagesButtons.GetImageList()->GetSize(i, width, height);
m_imagesButtons.GetImageLogicalSize(this, i, width, height);
if (height > m_lineHeight) m_lineHeight = height;
}
}
Expand Down Expand Up @@ -2442,9 +2442,8 @@ void wxGenericTreeCtrl::UpdateAfterImageListChange()
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 (GetImageList())
// Don't do this if we're in the process of deleting the tree control.
if (HasImages())
CalculateLineHeight();
}

Expand Down Expand Up @@ -2517,7 +2516,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
{
if ( HasImages() )
{
GetImageList()->GetSize(image, image_w, image_h);
GetImageLogicalSize(this, image, image_w, image_h);
image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT;
}
else
Expand Down Expand Up @@ -2648,27 +2647,25 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)

if ( state != wxTREE_ITEMSTATE_NONE )
{
dc.SetClippingRegion( item->GetX(), item->GetY(), state_w, total_h );
GetStateImageList()->Draw( state, dc,
wxDCClipper clip(dc, item->GetX(), item->GetY(), state_w, total_h);
dc.DrawBitmap( m_imagesState.GetImageBitmapFor(this, state),
item->GetX(),
item->GetY() +
(total_h > state_h ? (total_h-state_h)/2
: 0),
wxIMAGELIST_DRAW_TRANSPARENT );
dc.DestroyClippingRegion();
true /* use mask */ );
}

if ( image != NO_IMAGE )
{
dc.SetClippingRegion(item->GetX() + state_w, item->GetY(),
wxDCClipper clip(dc, item->GetX() + state_w, item->GetY(),
image_w, total_h);
GetImageList()->Draw( image, dc,
dc.DrawBitmap( GetImageBitmapFor(this, image),
item->GetX() + state_w,
item->GetY() +
(total_h > image_h ? (total_h-image_h)/2
: 0),
wxIMAGELIST_DRAW_TRANSPARENT );
dc.DestroyClippingRegion();
true /* use mask */ );
}

dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
Expand Down Expand Up @@ -2830,22 +2827,21 @@ wxGenericTreeCtrl::PaintLevel(wxGenericTreeItem *item,
if ( m_imagesButtons.HasImages() )
{
// draw the image button here
int image_h = 0,
image_w = 0;
int image = item->IsExpanded() ? wxTreeItemIcon_Expanded
: wxTreeItemIcon_Normal;
if ( item->IsSelected() )
image += wxTreeItemIcon_Selected - wxTreeItemIcon_Normal;

wxImageList* const
imageListButtons = m_imagesButtons.GetImageList();
imageListButtons->GetSize(image, image_w, image_h);
const wxBitmap& bmp = m_imagesButtons.GetImageBitmapFor(this, image);

// we need logical coordinates for wxDC.
int image_h = FromPhys(bmp.GetHeight()),
image_w = FromPhys(bmp.GetWidth());
int xx = x - image_w/2;
int yy = y_mid - image_h/2;

wxDCClipper clip(dc, xx, yy, image_w, image_h);
imageListButtons->Draw(image, dc, xx, yy,
wxIMAGELIST_DRAW_TRANSPARENT);
dc.DrawBitmap( bmp, xx, yy, true /* use mask */ );
}
else // no custom buttons
{
Expand Down Expand Up @@ -3007,10 +3003,6 @@ void wxGenericTreeCtrl::OnPaint( wxPaintEvent &WXUNUSED(event) )
dc.SetFont( m_normalFont );
dc.SetPen( m_dottedPen );

// this is now done dynamically
//if(GetImageList() == NULL)
// m_lineHeight = (int)(dc.GetCharHeight() + 4);

int y = 2;
PaintLevel( m_anchor, dc, 0, y );
}
Expand Down Expand Up @@ -3447,7 +3439,7 @@ bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
if ( image != NO_IMAGE && HasImages() )
{
int image_h;
GetImageList()->GetSize( image, image_w, image_h );
GetImageLogicalSize( this, image, image_w, image_h );
image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT;
}

Expand Down Expand Up @@ -3997,8 +3989,6 @@ void wxGenericTreeCtrl::CalculatePositions()
dc.SetFont( m_normalFont );

dc.SetPen( m_dottedPen );
//if(GetImageList() == NULL)
// m_lineHeight = (int)(dc.GetCharHeight() + 4);

int y = 2;
CalculateLevel( m_anchor, dc, 0, y ); // start recursion
Expand Down
10 changes: 9 additions & 1 deletion version-script.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,15 @@
# and once released its version cannot be changed.


# public symbols added in 3.2.1 (please keep in alphabetical order):
# public symbols added in 3.2.2 (please keep in alphabetical order):
@WX_VERSION_TAG@.2 {
extern "C++" {
"wxWithImages::GetImageLogicalSize";
"wxWithImages::GetImageBitmapFor";
};
};

# public symbols added in 3.2.1
@WX_VERSION_TAG@.1 {
extern "C++" {
"wxApp::GTKAllowDiagnosticsControl()";
Expand Down

0 comments on commit 8dd1375

Please sign in to comment.