Merge branch 'generic-listctrl-hidpi-images'
Support high DPI images in generic wxListCtrl. See #22916.
This commit is contained in:
commit
5845312825
4 changed files with 104 additions and 77 deletions
41
include/wx/generic/private/drawbitmap.h
Normal file
41
include/wx/generic/private/drawbitmap.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/generic/private/drawbitmap.h
|
||||
// Purpose: Small helper for drawing images.
|
||||
// Author: Vadim Zeitlin
|
||||
// Created: 2022-10-25
|
||||
// Copyright: (c) 2022 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_GENERIC_PRIVATE_DRAWBITMAP_H_
|
||||
#define _WX_GENERIC_PRIVATE_DRAWBITMAP_H_
|
||||
|
||||
#include "wx/dc.h"
|
||||
#include "wx/window.h"
|
||||
#include "wx/withimages.h"
|
||||
|
||||
// Just a trivial wrapper for wxDC::DrawBitmap() using wxWithImages: this is
|
||||
// used in several places in the generic wxListCtrl and wxTreeCtrl code.
|
||||
inline void
|
||||
wxDrawImageBitmap(wxWindow* window,
|
||||
const wxWithImages& images,
|
||||
int image,
|
||||
wxDC& dc,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
dc.DrawBitmap(images.GetImageBitmapFor(window, image),
|
||||
x, y,
|
||||
true /* use mask */);
|
||||
}
|
||||
|
||||
// Overload for the controls deriving from both wxWindow and wxWithImages, as
|
||||
// both wxListCtrl and wxTreeCtrl do.
|
||||
template <typename T>
|
||||
inline void
|
||||
wxDrawImageBitmap(T* window, int image, wxDC& dc, int x, int y)
|
||||
{
|
||||
wxDrawImageBitmap(window, *window, image, dc, x, y);
|
||||
}
|
||||
|
||||
#endif // _WX_GENERIC_PRIVATE_DRAWBITMAP_H_
|
||||
|
|
@ -640,7 +640,7 @@ public:
|
|||
void DrawImage( int index, wxDC *dc, int x, int y );
|
||||
void GetImageSize( int index, int &width, int &height ) const;
|
||||
|
||||
void SetImageList( wxImageList *imageList, int which );
|
||||
void SetImages( wxWithImages *images, const int which );
|
||||
void SetItemSpacing( int spacing, bool isSmall = false );
|
||||
int GetItemSpacing( bool isSmall = false );
|
||||
|
||||
|
|
@ -694,8 +694,9 @@ public:
|
|||
SetItem( info );
|
||||
}
|
||||
|
||||
wxImageList* GetSmallImageList() const
|
||||
{ return m_small_image_list; }
|
||||
wxWithImages* GetSmallImages() const
|
||||
{ return m_small_images; }
|
||||
|
||||
|
||||
// set the scrollbars and update the positions of the items
|
||||
void RecalculatePositions();
|
||||
|
|
@ -811,8 +812,9 @@ protected:
|
|||
bool m_dirty;
|
||||
|
||||
wxColour *m_highlightColour;
|
||||
wxImageList *m_small_image_list;
|
||||
wxImageList *m_normal_image_list;
|
||||
wxWithImages *m_small_images;
|
||||
wxWithImages *m_normal_images;
|
||||
|
||||
int m_small_spacing;
|
||||
int m_normal_spacing;
|
||||
bool m_hasFocus;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
#include "wx/imaglist.h"
|
||||
#include "wx/renderer.h"
|
||||
|
||||
#include "wx/generic/private/drawbitmap.h"
|
||||
#include "wx/generic/private/listctrl.h"
|
||||
#include "wx/generic/private/widthcalc.h"
|
||||
|
||||
|
|
@ -1134,19 +1136,19 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
|
|||
// and the width of the icon, if any
|
||||
int ix = 0, iy = 0; // init them just to suppress the compiler warnings
|
||||
const int image = item.m_image;
|
||||
wxImageList *imageList;
|
||||
wxWithImages *smallImages;
|
||||
if ( image != -1 )
|
||||
{
|
||||
imageList = m_owner->GetSmallImageList();
|
||||
if ( imageList )
|
||||
smallImages = m_owner->GetSmallImages();
|
||||
if ( smallImages )
|
||||
{
|
||||
imageList->GetSize(image, ix, iy);
|
||||
smallImages->GetImageLogicalSize(this, image, ix, iy);
|
||||
wLabel += ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
imageList = nullptr;
|
||||
smallImages = nullptr;
|
||||
}
|
||||
|
||||
// ignore alignment if there is not enough space anyhow
|
||||
|
|
@ -1175,16 +1177,15 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
|
|||
wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h);
|
||||
|
||||
// if we have an image, draw it on the right of the label
|
||||
if ( imageList )
|
||||
if ( smallImages )
|
||||
{
|
||||
imageList->Draw
|
||||
(
|
||||
image,
|
||||
dc,
|
||||
xAligned + wLabel - ix - HEADER_IMAGE_MARGIN_IN_REPORT_MODE,
|
||||
HEADER_OFFSET_Y + (h - iy)/2,
|
||||
wxIMAGELIST_DRAW_TRANSPARENT
|
||||
);
|
||||
wxDrawImageBitmap
|
||||
(
|
||||
this, *smallImages, image,
|
||||
dc,
|
||||
xAligned + wLabel - ix - HEADER_IMAGE_MARGIN_IN_REPORT_MODE,
|
||||
HEADER_OFFSET_Y + (h - iy)/2
|
||||
);
|
||||
}
|
||||
|
||||
dc.DrawText( item.GetText(),
|
||||
|
|
@ -1592,8 +1593,8 @@ void wxListMainWindow::Init()
|
|||
m_headerWidth =
|
||||
m_lineHeight = 0;
|
||||
|
||||
m_small_image_list = nullptr;
|
||||
m_normal_image_list = nullptr;
|
||||
m_small_images = nullptr;
|
||||
m_normal_images = nullptr;
|
||||
|
||||
m_small_spacing = 30;
|
||||
m_normal_spacing = 40;
|
||||
|
|
@ -1751,10 +1752,10 @@ wxCoord wxListMainWindow::GetLineHeight() const
|
|||
wxCoord y;
|
||||
dc.GetTextExtent(wxT("H"), nullptr, &y);
|
||||
|
||||
if ( m_small_image_list && m_small_image_list->GetImageCount() )
|
||||
if ( m_small_images && m_small_images->GetImageCount() )
|
||||
{
|
||||
int iw = 0, ih = 0;
|
||||
m_small_image_list->GetSize(0, iw, ih);
|
||||
m_small_images->GetImageLogicalSize(this, 0, iw, ih);
|
||||
y = wxMax(y, ih);
|
||||
}
|
||||
|
||||
|
|
@ -3302,41 +3303,25 @@ void wxListMainWindow::OnKillFocus( wxFocusEvent &WXUNUSED(event) )
|
|||
|
||||
void wxListMainWindow::DrawImage( int index, wxDC *dc, int x, int y )
|
||||
{
|
||||
if ( HasFlag(wxLC_ICON) && (m_normal_image_list))
|
||||
if ( HasFlag(wxLC_ICON) && m_normal_images )
|
||||
{
|
||||
m_normal_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
|
||||
wxDrawImageBitmap(this, *m_normal_images, index, *dc, x, y);
|
||||
}
|
||||
else if ( HasFlag(wxLC_SMALL_ICON) && (m_small_image_list))
|
||||
else if ( HasFlag(wxLC_SMALL_ICON | wxLC_LIST | wxLC_REPORT) && m_small_images )
|
||||
{
|
||||
m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
|
||||
}
|
||||
else if ( HasFlag(wxLC_LIST) && (m_small_image_list))
|
||||
{
|
||||
m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
|
||||
}
|
||||
else if ( InReportView() && (m_small_image_list))
|
||||
{
|
||||
m_small_image_list->Draw( index, *dc, x, y, wxIMAGELIST_DRAW_TRANSPARENT );
|
||||
wxDrawImageBitmap(this, *m_small_images, index, *dc, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void wxListMainWindow::GetImageSize( int index, int &width, int &height ) const
|
||||
{
|
||||
if ( HasFlag(wxLC_ICON) && m_normal_image_list )
|
||||
if ( HasFlag(wxLC_ICON) && m_normal_images )
|
||||
{
|
||||
m_normal_image_list->GetSize( index, width, height );
|
||||
m_normal_images->GetImageLogicalSize(this, index, width, height);
|
||||
}
|
||||
else if ( HasFlag(wxLC_SMALL_ICON) && m_small_image_list )
|
||||
else if ( HasFlag(wxLC_SMALL_ICON | wxLC_LIST | wxLC_REPORT) && m_small_images )
|
||||
{
|
||||
m_small_image_list->GetSize( index, width, height );
|
||||
}
|
||||
else if ( HasFlag(wxLC_LIST) && m_small_image_list )
|
||||
{
|
||||
m_small_image_list->GetSize( index, width, height );
|
||||
}
|
||||
else if ( InReportView() && m_small_image_list )
|
||||
{
|
||||
m_small_image_list->GetSize( index, width, height );
|
||||
m_small_images->GetImageLogicalSize(this, index, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3345,28 +3330,29 @@ void wxListMainWindow::GetImageSize( int index, int &width, int &height ) const
|
|||
}
|
||||
}
|
||||
|
||||
void wxListMainWindow::SetImageList( wxImageList *imageList, int which )
|
||||
|
||||
void wxListMainWindow::SetImages( wxWithImages *images, const int which )
|
||||
{
|
||||
m_dirty = true;
|
||||
|
||||
// calc the spacing from the icon size
|
||||
int width = 0;
|
||||
|
||||
if ((imageList) && (imageList->GetImageCount()) )
|
||||
if ((images) && (images->HasImages()) )
|
||||
{
|
||||
int height;
|
||||
imageList->GetSize(0, width, height);
|
||||
images->GetImageLogicalSize(this, 0, width, height);
|
||||
}
|
||||
|
||||
if (which == wxIMAGE_LIST_NORMAL)
|
||||
{
|
||||
m_normal_image_list = imageList;
|
||||
m_normal_images = images;
|
||||
m_normal_spacing = width + 8;
|
||||
}
|
||||
|
||||
if (which == wxIMAGE_LIST_SMALL)
|
||||
{
|
||||
m_small_image_list = imageList;
|
||||
m_small_images = images;
|
||||
m_small_spacing = width + 14;
|
||||
m_lineHeight = 0; // ensure that the line height will be recalc'd
|
||||
}
|
||||
|
|
@ -3403,10 +3389,10 @@ wxListMainWindow::ComputeMinHeaderWidth(const wxListHeaderData* column) const
|
|||
const int image = column->GetImage();
|
||||
if ( image != -1 )
|
||||
{
|
||||
if ( m_small_image_list )
|
||||
if ( m_small_images )
|
||||
{
|
||||
int ix = 0, iy = 0;
|
||||
m_small_image_list->GetSize(image, ix, iy);
|
||||
m_small_images->GetImageLogicalSize(this, image, ix, iy);
|
||||
width += ix + HEADER_IMAGE_MARGIN_IN_REPORT_MODE;
|
||||
}
|
||||
}
|
||||
|
|
@ -4029,9 +4015,9 @@ void wxListMainWindow::RecalculatePositions()
|
|||
const size_t count = GetItemCount();
|
||||
|
||||
int iconSpacing;
|
||||
if ( HasFlag(wxLC_ICON) && m_normal_image_list )
|
||||
if ( HasFlag(wxLC_ICON) && m_normal_images )
|
||||
iconSpacing = m_normal_spacing;
|
||||
else if ( HasFlag(wxLC_SMALL_ICON) && m_small_image_list )
|
||||
else if ( HasFlag(wxLC_SMALL_ICON) && m_small_images )
|
||||
iconSpacing = m_small_spacing;
|
||||
else
|
||||
iconSpacing = 0;
|
||||
|
|
@ -4626,10 +4612,10 @@ void wxListMainWindow::InsertItem( wxListItem &item )
|
|||
{
|
||||
// Reset the buffered height if it's not big enough for the new image.
|
||||
int image = item.GetImage();
|
||||
if ( m_small_image_list && image != -1 && InReportView() )
|
||||
if ( m_small_images && image != -1 && InReportView() )
|
||||
{
|
||||
int imageWidth, imageHeight;
|
||||
m_small_image_list->GetSize(image, imageWidth, imageHeight);
|
||||
m_small_images->GetImageLogicalSize(this, image, imageWidth, imageHeight);
|
||||
|
||||
if ( imageHeight > m_lineHeight )
|
||||
m_lineHeight = 0;
|
||||
|
|
@ -5456,7 +5442,7 @@ long wxGenericListCtrl::GetNextItem( long item, int geom, int state ) const
|
|||
|
||||
void wxGenericListCtrl::DoUpdateImages(int which )
|
||||
{
|
||||
m_mainWin->SetImageList( GetUpdatedImageList(which), which );
|
||||
m_mainWin->SetImages( GetImages(which), which );
|
||||
}
|
||||
|
||||
bool wxGenericListCtrl::Arrange( int WXUNUSED(flag) )
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include "wx/renderer.h"
|
||||
|
||||
#include "wx/generic/private/drawbitmap.h"
|
||||
|
||||
#ifdef __WXMAC__
|
||||
#include "wx/osx/private.h"
|
||||
#endif
|
||||
|
|
@ -2648,24 +2650,23 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
|
|||
if ( state != wxTREE_ITEMSTATE_NONE )
|
||||
{
|
||||
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),
|
||||
true /* use mask */ );
|
||||
|
||||
wxDrawImageBitmap(this, m_imagesState, state,
|
||||
dc,
|
||||
item->GetX(),
|
||||
item->GetY() +
|
||||
total_h > state_h ? (total_h-state_h)/2 : 0);
|
||||
}
|
||||
|
||||
if ( image != NO_IMAGE )
|
||||
{
|
||||
wxDCClipper clip(dc, item->GetX() + state_w, item->GetY(),
|
||||
image_w, total_h);
|
||||
dc.DrawBitmap( GetImageBitmapFor(this, image),
|
||||
item->GetX() + state_w,
|
||||
item->GetY() +
|
||||
(total_h > image_h ? (total_h-image_h)/2
|
||||
: 0),
|
||||
true /* use mask */ );
|
||||
wxDrawImageBitmap(this, image,
|
||||
dc,
|
||||
item->GetX() + state_w,
|
||||
item->GetY() +
|
||||
total_h > image_h ? (total_h-image_h)/2 : 0);
|
||||
}
|
||||
|
||||
dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
|
||||
|
|
@ -2832,16 +2833,13 @@ wxGenericTreeCtrl::PaintLevel(wxGenericTreeItem *item,
|
|||
if ( item->IsSelected() )
|
||||
image += wxTreeItemIcon_Selected - wxTreeItemIcon_Normal;
|
||||
|
||||
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 image_w, image_h;
|
||||
m_imagesButtons.GetImageLogicalSize(this, image, image_w, image_h);
|
||||
int xx = x - image_w/2;
|
||||
int yy = y_mid - image_h/2;
|
||||
|
||||
wxDCClipper clip(dc, xx, yy, image_w, image_h);
|
||||
dc.DrawBitmap( bmp, xx, yy, true /* use mask */ );
|
||||
wxDrawImageBitmap(this, m_imagesButtons, image, dc, xx, yy);
|
||||
}
|
||||
else // no custom buttons
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue