From aca0c74e60764f75740d56171d78c44d8de6fd49 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 11 Nov 2021 00:50:20 +0000 Subject: [PATCH] Add wxListCtrl::Set{Normal,Small}Images() These new functions allow to use wxBitmapBundle for the images in this control instead of wxImageList. Update the sample to use the new API. --- include/wx/generic/listctrl.h | 2 +- include/wx/listbase.h | 24 ++++++++++++-- include/wx/msw/listctrl.h | 2 +- include/wx/qt/listctrl.h | 2 +- interface/wx/listctrl.h | 62 ++++++++++++++++++++++++++++++----- samples/listctrl/listtest.cpp | 56 ++++++++++++++----------------- samples/listctrl/listtest.h | 4 +-- src/common/listctrlcmn.cpp | 41 ++++++++++++++++++++--- src/generic/listctrl.cpp | 4 +-- src/msw/listctrl.cpp | 10 +++--- src/qt/listctrl.cpp | 2 +- 11 files changed, 150 insertions(+), 59 deletions(-) diff --git a/include/wx/generic/listctrl.h b/include/wx/generic/listctrl.h index 5c752446bf..022d2d1316 100644 --- a/include/wx/generic/listctrl.h +++ b/include/wx/generic/listctrl.h @@ -212,7 +212,7 @@ public: protected: // Implement base class pure virtual methods. long DoInsertColumn(long col, const wxListItem& info) wxOVERRIDE; - void DoSetImageList(wxImageList *imageList, int which) wxOVERRIDE; + void DoUpdateImages(int which) wxOVERRIDE; virtual wxSize DoGetBestClientSize() const wxOVERRIDE; diff --git a/include/wx/listbase.h b/include/wx/listbase.h index 71136441c3..3441b3b84c 100644 --- a/include/wx/listbase.h +++ b/include/wx/listbase.h @@ -334,8 +334,18 @@ class WXDLLIMPEXP_CORE wxListCtrlBase : public wxSystemThemedControl public: wxListCtrlBase() { } - // Image list methods. - // ------------------- + // Image-related methods. + // ---------------------- + + // Preferred way of specifying the images is by using the SetXXXImages(), + // methods using wxImageList below still work, but don't allow specifying + // images in different resolutions, which is necessary for good appearance + // on high DPI displays. + + // "Normal" images are used only in icon view, the "report" view uses + // "small" images. + void SetNormalImages(const wxVector& images); + void SetSmallImages(const wxVector& images); // Associate the given (possibly NULL to indicate that no images will be // used) image list with the control. The ownership of the image list @@ -437,9 +447,17 @@ public: virtual void CheckItem(long WXUNUSED(item), bool WXUNUSED(check)) { } protected: + // Return pointer to the corresponding m_imagesXXX. + const wxWithImages* GetImages(int which) const; + wxWithImages* GetImages(int which); + + // Helper updating or creating the image list, if necessary, unlike + // GetImageList() which just returns the previously set image list. + wxImageList* GetUpdatedImageList(int which); + // Real implementations methods to which our public forwards. virtual long DoInsertColumn(long col, const wxListItem& info) = 0; - virtual void DoSetImageList(wxImageList *imageList, int which) = 0; + virtual void DoUpdateImages(int which) = 0; // Overridden methods of the base class. virtual wxSize DoGetBestClientSize() const wxOVERRIDE; diff --git a/include/wx/msw/listctrl.h b/include/wx/msw/listctrl.h index 882a6ceb74..afa21dd1eb 100644 --- a/include/wx/msw/listctrl.h +++ b/include/wx/msw/listctrl.h @@ -400,7 +400,7 @@ protected: // Implement base class pure virtual methods. long DoInsertColumn(long col, const wxListItem& info) wxOVERRIDE; - void DoSetImageList(wxImageList *imageList, int which) wxOVERRIDE; + void DoUpdateImages(int which) wxOVERRIDE; // free memory taken by all internal data void FreeAllInternalData(); diff --git a/include/wx/qt/listctrl.h b/include/wx/qt/listctrl.h index 25ddaa39a7..eefb5b42f0 100644 --- a/include/wx/qt/listctrl.h +++ b/include/wx/qt/listctrl.h @@ -269,7 +269,7 @@ protected: // Implement base class pure virtual methods. virtual long DoInsertColumn(long col, const wxListItem& info) wxOVERRIDE; - void DoSetImageList(wxImageList *imageList, int which) wxOVERRIDE; + void DoUpdateImages(int which) wxOVERRIDE; bool m_hasCheckBoxes; diff --git a/interface/wx/listctrl.h b/interface/wx/listctrl.h index 17420746fc..1629b6c510 100644 --- a/interface/wx/listctrl.h +++ b/interface/wx/listctrl.h @@ -376,10 +376,15 @@ public: bool Arrange(int flag = wxLIST_ALIGN_DEFAULT); /** - Sets the image list associated with the control and takes ownership of it - (i.e. the control will, unlike when using SetImageList(), delete the list - when destroyed). @a which is one of @c wxIMAGE_LIST_NORMAL, @c wxIMAGE_LIST_SMALL, - @c wxIMAGE_LIST_STATE (the last is unimplemented). + Sets the image list associated with the control and takes ownership of it. + + Not that it is recommended to use SetNormalImages() or SetSmallImages() + instead of this function in the new code. + + After calling this function the control will, unlike when using + SetImageList(), delete the list when destroyed. @a which must be one of + @c wxIMAGE_LIST_NORMAL, @c wxIMAGE_LIST_SMALL, @c wxIMAGE_LIST_STATE + (support for the last one is unimplemented). @see SetImageList() */ @@ -1108,8 +1113,11 @@ public: /** Sets the image list associated with the control. - @a which is one of @c wxIMAGE_LIST_NORMAL, @c wxIMAGE_LIST_SMALL, - @c wxIMAGE_LIST_STATE (the last is unimplemented). + Not that it is recommended to use SetNormalImages() or SetSmallImages() + instead of this function in the new code. + + @a which must be one of @c wxIMAGE_LIST_NORMAL, @c wxIMAGE_LIST_SMALL, + @c wxIMAGE_LIST_STATE (support for the last one is unimplemented). This method does not take ownership of the image list, you have to delete it yourself. @@ -1123,6 +1131,40 @@ public: */ void SetImageList(wxImageList* imageList, int which); + /** + Sets the images to use when showing large, normal icons in this control. + + These images are used by the items when the list control is in + wxLC_ICON mode, in all the other modes the images set by + SetSmallImages() are used. + + This function should be preferred to calling SetImageList() or + AssignImageList() with @c wxIMAGE_LIST_NORMAL argument in the new code, + as using wxBitmapBundle makes it possible to specify multiple versions + of the icons, allowing the control to choose the right one for the + current DPI scaling. + + @since 3.1.6 + */ + void SetNormalImages(const wxVector& images); + + /** + Sets the images to use when showing small icons in this control. + + These images are used by the items when the list control is in + wxLC_SMALL_ICON or wxLC_REPORT mode, use SetNormalImages() for the + icons used in wxLC_ICON mode. + + This function should be preferred to calling SetImageList() or + AssignImageList() with @c wxIMAGE_LIST_SMALL argument in the new code, + as using wxBitmapBundle makes it possible to specify multiple versions + of the icons, allowing the control to choose the right one for the + current DPI scaling. + + @since 3.1.6 + */ + void SetSmallImages(const wxVector& images); + /** Check if the item is visible. @@ -1427,8 +1469,12 @@ protected: /** This function must be overridden in the derived class for a control with - @c wxLC_VIRTUAL style having an "image list" (see SetImageList(); if the - control doesn't have an image list, it is not necessary to override it). + @c wxLC_VIRTUAL style using images. + + If the control doesn't use images, i.e. SetNormalImages() or + SetSmallImages() hadn't been called, it is not necessary to override + it. + It should return the index of the items image in the controls image list or -1 for no image. diff --git a/samples/listctrl/listtest.cpp b/samples/listctrl/listtest.cpp index edae453f8b..224af7a483 100644 --- a/samples/listctrl/listtest.cpp +++ b/samples/listctrl/listtest.cpp @@ -178,35 +178,32 @@ MyFrame::MyFrame(const wxString& title) // Give it an icon SetIcon(wxICON(sample)); - // Make an image list containing large icons - m_imageListNormal = new wxImageList(32, 32, true); - m_imageListSmall = new wxImageList(16, 16, true); - + // Fill vectors containing normal and small icons. #ifdef wxHAS_IMAGES_IN_RESOURCES - m_imageListNormal->Add( wxIcon("icon1", wxBITMAP_TYPE_ICO_RESOURCE) ); - m_imageListNormal->Add( wxIcon("icon2", wxBITMAP_TYPE_ICO_RESOURCE) ); - m_imageListNormal->Add( wxIcon("icon3", wxBITMAP_TYPE_ICO_RESOURCE) ); - m_imageListNormal->Add( wxIcon("icon4", wxBITMAP_TYPE_ICO_RESOURCE) ); - m_imageListNormal->Add( wxIcon("icon5", wxBITMAP_TYPE_ICO_RESOURCE) ); - m_imageListNormal->Add( wxIcon("icon6", wxBITMAP_TYPE_ICO_RESOURCE) ); - m_imageListNormal->Add( wxIcon("icon7", wxBITMAP_TYPE_ICO_RESOURCE) ); - m_imageListNormal->Add( wxIcon("icon8", wxBITMAP_TYPE_ICO_RESOURCE) ); - m_imageListNormal->Add( wxIcon("icon9", wxBITMAP_TYPE_ICO_RESOURCE) ); + m_imagesNormal.push_back( wxIcon("icon1", wxBITMAP_TYPE_ICO_RESOURCE) ); + m_imagesNormal.push_back( wxIcon("icon2", wxBITMAP_TYPE_ICO_RESOURCE) ); + m_imagesNormal.push_back( wxIcon("icon3", wxBITMAP_TYPE_ICO_RESOURCE) ); + m_imagesNormal.push_back( wxIcon("icon4", wxBITMAP_TYPE_ICO_RESOURCE) ); + m_imagesNormal.push_back( wxIcon("icon5", wxBITMAP_TYPE_ICO_RESOURCE) ); + m_imagesNormal.push_back( wxIcon("icon6", wxBITMAP_TYPE_ICO_RESOURCE) ); + m_imagesNormal.push_back( wxIcon("icon7", wxBITMAP_TYPE_ICO_RESOURCE) ); + m_imagesNormal.push_back( wxIcon("icon8", wxBITMAP_TYPE_ICO_RESOURCE) ); + m_imagesNormal.push_back( wxIcon("icon9", wxBITMAP_TYPE_ICO_RESOURCE) ); - m_imageListSmall->Add( wxIcon("iconsmall", wxBITMAP_TYPE_ICO_RESOURCE) ); + m_imagesSmall.push_back( wxIcon("iconsmall", wxBITMAP_TYPE_ICO_RESOURCE, 16, 16) ); #else - m_imageListNormal->Add( wxIcon( toolbrai_xpm ) ); - m_imageListNormal->Add( wxIcon( toolchar_xpm ) ); - m_imageListNormal->Add( wxIcon( tooldata_xpm ) ); - m_imageListNormal->Add( wxIcon( toolnote_xpm ) ); - m_imageListNormal->Add( wxIcon( tooltodo_xpm ) ); - m_imageListNormal->Add( wxIcon( toolchec_xpm ) ); - m_imageListNormal->Add( wxIcon( toolgame_xpm ) ); - m_imageListNormal->Add( wxIcon( tooltime_xpm ) ); - m_imageListNormal->Add( wxIcon( toolword_xpm ) ); + m_imagesNormal.push_back( wxIcon( toolbrai_xpm ) ); + m_imagesNormal.push_back( wxIcon( toolchar_xpm ) ); + m_imagesNormal.push_back( wxIcon( tooldata_xpm ) ); + m_imagesNormal.push_back( wxIcon( toolnote_xpm ) ); + m_imagesNormal.push_back( wxIcon( tooltodo_xpm ) ); + m_imagesNormal.push_back( wxIcon( toolchec_xpm ) ); + m_imagesNormal.push_back( wxIcon( toolgame_xpm ) ); + m_imagesNormal.push_back( wxIcon( tooltime_xpm ) ); + m_imagesNormal.push_back( wxIcon( toolword_xpm ) ); - m_imageListSmall->Add( wxIcon( small1_xpm) ); + m_imagesSmall.push_back( wxIcon( small1_xpm) ); #endif // Make a menubar @@ -312,9 +309,6 @@ MyFrame::MyFrame(const wxString& title) MyFrame::~MyFrame() { delete wxLog::SetActiveTarget(m_logOld); - - delete m_imageListNormal; - delete m_imageListSmall; } bool MyFrame::CheckNonVirtual() const @@ -532,7 +526,7 @@ void MyFrame::OnReportView(wxCommandEvent& WXUNUSED(event)) void MyFrame::InitWithReportItems() { - m_listCtrl->SetImageList(m_imageListSmall, wxIMAGE_LIST_SMALL); + m_listCtrl->SetSmallImages(m_imagesSmall); // note that under MSW for SetColumnWidth() to work we need to create the // items with images initially even if we specify dummy image id @@ -621,8 +615,8 @@ void MyFrame::InitWithReportItems() void MyFrame::InitWithIconItems(bool withText, bool sameIcon) { - m_listCtrl->SetImageList(m_imageListNormal, wxIMAGE_LIST_NORMAL); - m_listCtrl->SetImageList(m_imageListSmall, wxIMAGE_LIST_SMALL); + m_listCtrl->SetNormalImages(m_imagesNormal); + m_listCtrl->SetSmallImages(m_imagesSmall); for ( int i = 0; i < NUM_ICONS; i++ ) { @@ -705,7 +699,7 @@ void MyFrame::OnSetItemsCount(wxCommandEvent& WXUNUSED(event)) void MyFrame::InitWithVirtualItems() { - m_listCtrl->SetImageList(m_imageListSmall, wxIMAGE_LIST_SMALL); + m_listCtrl->SetSmallImages(m_imagesSmall); if ( m_smallVirtual ) { diff --git a/samples/listctrl/listtest.h b/samples/listctrl/listtest.h index 04410ecbf1..9db71c27c9 100644 --- a/samples/listctrl/listtest.h +++ b/samples/listctrl/listtest.h @@ -159,8 +159,8 @@ protected: void OnUpdateToggleHeader(wxUpdateUIEvent& event); void OnUpdateRowLines(wxUpdateUIEvent& event); - wxImageList *m_imageListNormal; - wxImageList *m_imageListSmall; + wxVector m_imagesNormal; + wxVector m_imagesSmall; wxPanel *m_panel; MyListCtrl *m_listCtrl; diff --git a/src/common/listctrlcmn.cpp b/src/common/listctrlcmn.cpp index e8ae509c16..22b5e68e49 100644 --- a/src/common/listctrlcmn.cpp +++ b/src/common/listctrlcmn.cpp @@ -292,23 +292,54 @@ wxItemAttr* wxListCtrlBase::OnGetItemColumnAttr(long item, long WXUNUSED(column) // Images support // ---------------------------------------------------------------------------- -wxImageList *wxListCtrlBase::GetImageList(int which) const +void wxListCtrlBase::SetNormalImages(const wxVector& images) +{ + m_imagesNormal.SetImages(images); + + DoUpdateImages(wxIMAGE_LIST_NORMAL); +} + +void wxListCtrlBase::SetSmallImages(const wxVector& images) +{ + m_imagesSmall.SetImages(images); + + DoUpdateImages(wxIMAGE_LIST_SMALL); +} + +wxWithImages* wxListCtrlBase::GetImages(int which) { if ( which == wxIMAGE_LIST_NORMAL ) { - return m_imagesNormal.GetImageList(); + return &m_imagesNormal; } else if ( which == wxIMAGE_LIST_SMALL ) { - return m_imagesSmall.GetImageList(); + return &m_imagesSmall; } else if ( which == wxIMAGE_LIST_STATE ) { - return m_imagesState.GetImageList(); + return &m_imagesState; } return NULL; } +const wxWithImages* wxListCtrlBase::GetImages(int which) const +{ + return const_cast(this)->GetImages(which); +} + +wxImageList* wxListCtrlBase::GetUpdatedImageList(int which) +{ + wxWithImages* const images = GetImages(which); + return images ? images->GetUpdatedImageListFor(this) : NULL; +} + +wxImageList *wxListCtrlBase::GetImageList(int which) const +{ + const wxWithImages* const images = GetImages(which); + return images ? images->GetImageList() : NULL; +} + void wxListCtrlBase::SetImageList(wxImageList *imageList, int which) { if ( which == wxIMAGE_LIST_NORMAL ) @@ -330,7 +361,7 @@ void wxListCtrlBase::SetImageList(wxImageList *imageList, int which) } // Actually update the images shown in the control. - DoSetImageList(imageList, which); + DoUpdateImages(which); } void wxListCtrlBase::AssignImageList(wxImageList *imageList, int which) diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index 2cd65838bb..befb26bc2b 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -5402,9 +5402,9 @@ long wxGenericListCtrl::GetNextItem( long item, int geom, int state ) const return m_mainWin->GetNextItem( item, geom, state ); } -void wxGenericListCtrl::DoSetImageList( wxImageList *imageList, int which ) +void wxGenericListCtrl::DoUpdateImages(int which ) { - m_mainWin->SetImageList( imageList, which ); + m_mainWin->SetImageList( GetUpdatedImageList(which), which ); } bool wxGenericListCtrl::Arrange( int WXUNUSED(flag) ) diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index 8078adf6ba..f0f151d9af 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -315,11 +315,11 @@ bool wxListCtrl::Create(wxWindow *parent, // If SetImageList() had been called before the control was created, take // it into account now. - if ( wxImageList* const iml = GetImageList(wxIMAGE_LIST_NORMAL) ) + if ( wxImageList* const iml = GetUpdatedImageList(wxIMAGE_LIST_NORMAL) ) ListView_SetImageList(GetHwnd(), GetHimagelistOf(iml), LVSIL_NORMAL); - if ( wxImageList* const iml = GetImageList(wxIMAGE_LIST_SMALL) ) + if ( wxImageList* const iml = GetUpdatedImageList(wxIMAGE_LIST_SMALL) ) ListView_SetImageList(GetHwnd(), GetHimagelistOf(iml), LVSIL_SMALL); - if ( wxImageList* const iml = GetImageList(wxIMAGE_LIST_STATE) ) + if ( wxImageList* const iml = GetUpdatedImageList(wxIMAGE_LIST_STATE) ) ListView_SetImageList(GetHwnd(), GetHimagelistOf(iml), LVSIL_STATE); return true; @@ -1509,7 +1509,7 @@ long wxListCtrl::GetNextItem(long item, int geom, int state) const } -void wxListCtrl::DoSetImageList(wxImageList *imageList, int which) +void wxListCtrl::DoUpdateImages(int which) { // It's possible that this function is called before the control is // created, don't do anything else in this case -- the image list will be @@ -1537,6 +1537,8 @@ void wxListCtrl::DoSetImageList(wxImageList *imageList, int which) return; } + wxImageList* const imageList = GetUpdatedImageList(which); + (void) ListView_SetImageList(GetHwnd(), (HIMAGELIST) imageList ? imageList->GetHIMAGELIST() : 0, flags); // For ComCtl32 prior 6.0 we need to re-assign all existing diff --git a/src/qt/listctrl.cpp b/src/qt/listctrl.cpp index f06292f7cb..c6b0e2109b 100644 --- a/src/qt/listctrl.cpp +++ b/src/qt/listctrl.cpp @@ -1534,7 +1534,7 @@ long wxListCtrl::GetNextItem(long item, int WXUNUSED(geometry), int state) const return -1; } -void wxListCtrl::DoSetImageList(wxImageList* WXUNUSED(imageList), int WXUNUSED(which)) +void wxListCtrl::DoUpdateImages(int WXUNUSED(which)) { // TODO: Ensure the icons are actually updated. }