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.
This commit is contained in:
Vadim Zeitlin
2021-11-11 00:50:20 +00:00
parent 9ea8feec37
commit aca0c74e60
11 changed files with 150 additions and 59 deletions

View File

@@ -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;

View File

@@ -334,8 +334,18 @@ class WXDLLIMPEXP_CORE wxListCtrlBase : public wxSystemThemedControl<wxControl>
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<wxBitmapBundle>& images);
void SetSmallImages(const wxVector<wxBitmapBundle>& 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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -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<wxBitmapBundle>& 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<wxBitmapBundle>& 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.

View File

@@ -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 )
{

View File

@@ -159,8 +159,8 @@ protected:
void OnUpdateToggleHeader(wxUpdateUIEvent& event);
void OnUpdateRowLines(wxUpdateUIEvent& event);
wxImageList *m_imageListNormal;
wxImageList *m_imageListSmall;
wxVector<wxBitmapBundle> m_imagesNormal;
wxVector<wxBitmapBundle> m_imagesSmall;
wxPanel *m_panel;
MyListCtrl *m_listCtrl;

View File

@@ -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<wxBitmapBundle>& images)
{
m_imagesNormal.SetImages(images);
DoUpdateImages(wxIMAGE_LIST_NORMAL);
}
void wxListCtrlBase::SetSmallImages(const wxVector<wxBitmapBundle>& 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<wxListCtrlBase*>(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)

View File

@@ -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) )

View File

@@ -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

View File

@@ -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.
}