From 366d06847bb3cccd3852c6681e9902ada5029067 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 25 Oct 2023 18:36:39 +0200 Subject: [PATCH 01/18] Remove confusing boolean parameter from treectrl sample Don't use CreateStateImageList(true) to delete the image list. No real changes, just make the code more understandable. --- samples/treectrl/treetest.cpp | 12 +++--------- samples/treectrl/treetest.h | 2 +- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp index 652b596312..fddda848c3 100644 --- a/samples/treectrl/treetest.cpp +++ b/samples/treectrl/treetest.cpp @@ -703,12 +703,12 @@ void MyFrame::OnToggleStates(wxCommandEvent& WXUNUSED(event)) { if ( wxGetApp().ShowStates() ) { - m_treeCtrl->CreateStateImageList(true); + m_treeCtrl->SetStateImageList(nullptr); wxGetApp().SetShowStates(false); } else { - m_treeCtrl->CreateStateImageList(false); + m_treeCtrl->CreateStateImageList(); wxGetApp().SetShowStates(true); } } @@ -1035,14 +1035,8 @@ void MyTreeCtrl::CreateImages(int size) SetImages(images); } -void MyTreeCtrl::CreateStateImageList(bool del) +void MyTreeCtrl::CreateStateImageList() { - if ( del ) - { - SetStateImageList(nullptr); - return; - } - wxImageList *states; wxBusyCursor wait; diff --git a/samples/treectrl/treetest.h b/samples/treectrl/treetest.h index dc7d190b6a..24a751c34c 100644 --- a/samples/treectrl/treetest.h +++ b/samples/treectrl/treetest.h @@ -113,7 +113,7 @@ public: void CreateImages(int size); void CreateButtonsImageList(int size = 11); - void CreateStateImageList(bool del = false); + void CreateStateImageList(); void AddTestItemsToTree(size_t numChildren, size_t depth); From 188dc81d6e6e2f321a1effbc1652227e6c9baa63 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 25 Oct 2023 18:57:43 +0200 Subject: [PATCH 02/18] Extract custom wxBitmapBundleImpl in treectrl sample No changes yet, just prepare for using this class in another function. This commit is best viewed with Git --color-moved option. --- samples/treectrl/treetest.cpp | 69 ++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp index fddda848c3..92b648de14 100644 --- a/samples/treectrl/treetest.cpp +++ b/samples/treectrl/treetest.cpp @@ -955,6 +955,42 @@ MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id, AddTestItemsToTree(NUM_CHILDREN_PER_LEVEL, NUM_LEVELS); } +namespace +{ + class FixedSizeImpl : public wxBitmapBundleImpl + { + public: + FixedSizeImpl(const wxSize& sizeDef, const wxIcon& icon) + : m_sizeDef(sizeDef), + m_icon(icon) + { + } + + wxSize GetDefaultSize() const override + { + return m_sizeDef; + } + + wxSize GetPreferredBitmapSizeAtScale(double scale) const override + { + return m_sizeDef*scale; + } + + wxBitmap GetBitmap(const wxSize& size) override + { + wxBitmap bmp(m_icon); + if ( size != bmp.GetSize() ) + wxBitmap::Rescale(bmp, size); + + return bmp; + } + + private: + const wxSize m_sizeDef; + const wxIcon m_icon; + }; +} // anonymous namespace + void MyTreeCtrl::CreateImages(int size) { if ( size == -1 ) @@ -994,39 +1030,6 @@ void MyTreeCtrl::CreateImages(int size) // DPI, to ensure they are of the desired size. wxVector images; - class FixedSizeImpl : public wxBitmapBundleImpl - { - public: - FixedSizeImpl(const wxSize& sizeDef, const wxIcon& icon) - : m_sizeDef(sizeDef), - m_icon(icon) - { - } - - wxSize GetDefaultSize() const override - { - return m_sizeDef; - } - - wxSize GetPreferredBitmapSizeAtScale(double scale) const override - { - return m_sizeDef*scale; - } - - wxBitmap GetBitmap(const wxSize& size) override - { - wxBitmap bmp(m_icon); - if ( size != bmp.GetSize() ) - wxBitmap::Rescale(bmp, size); - - return bmp; - } - - private: - const wxSize m_sizeDef; - const wxIcon m_icon; - }; - for ( size_t i = 0; i < WXSIZEOF(icons); i++ ) { images.push_back(wxBitmapBundle::FromImpl(new FixedSizeImpl(iconSize, icons[i]))); From 6021f44e6a76e4b64033b81da121fbf542667056 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 25 Oct 2023 19:25:29 +0200 Subject: [PATCH 03/18] Fix clearing images used with wxWithImages Doing this must reset any existing image list, as some controls (notably wxTreeCtrl) use the image list internally and keeping using it would still show the old images even after resetting them. --- include/wx/withimages.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/wx/withimages.h b/include/wx/withimages.h index 12fe439586..63a16f298c 100644 --- a/include/wx/withimages.h +++ b/include/wx/withimages.h @@ -76,6 +76,15 @@ public: { m_images = images; + // Setting the images overrides any image list set before, especially + // because we may have set it ourselves if GetUpdatedImageListFor() was + // called and we don't want to remain with the outdated image list now + // (if the new images are not empty, this would happen only slightly + // later when the image list is updated again, but if they are empty, + // it's not going to happen at all). + FreeIfNeeded(); + m_imageList = nullptr; + OnImagesChanged(); } From 233cca22e4c4de6c17f75c6ce833d9383fa26522 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 25 Oct 2023 19:29:23 +0200 Subject: [PATCH 04/18] Fix not updating wxGenericTreeCtrl when clearing images We need to call UpdateAfterImageListChange() even when we don't have any images, as without it item sizes could remain wrong. Calling GetUpdatedImageListFor() is not necessary in this case, but does no harm neither, so always call it too for simplicity. This commit is best viewed ignoring whitespace-only changes. --- src/generic/treectlg.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index e3dcd34ea0..49d0987335 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -2457,13 +2457,10 @@ void wxGenericTreeCtrl::CalculateLineHeight() void wxGenericTreeCtrl::OnImagesChanged() { - if ( HasImages() ) - { - // We call it solely for the side effect of updating the image list. - GetUpdatedImageListFor(this); + // We call it solely for the side effect of updating the image list. + GetUpdatedImageListFor(this); - UpdateAfterImageListChange(); - } + UpdateAfterImageListChange(); } void wxGenericTreeCtrl::UpdateAfterImageListChange() From bc4a99d3c4a05e09254b5e9c49996c0c6afd81cb Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 25 Oct 2023 19:32:36 +0200 Subject: [PATCH 05/18] Fix initial size of treectrl sample window in high DPI Adjust it to the DPI as it was way too small at 200% scaling. Also stop passing parameters to MyFrame ctor, it's only used once so we can just as well hardcode them in it to simplify things a little. --- samples/treectrl/treetest.cpp | 7 ++++--- samples/treectrl/treetest.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp index 92b648de14..13e447e64f 100644 --- a/samples/treectrl/treetest.cpp +++ b/samples/treectrl/treetest.cpp @@ -193,7 +193,7 @@ bool MyApp::OnInit() return false; // Create the main frame window - MyFrame *frame = new MyFrame("wxTreeCtrl Test", 50, 50, 450, 600); + MyFrame *frame = new MyFrame(); // Show the frame frame->Show(true); @@ -203,8 +203,9 @@ bool MyApp::OnInit() // My frame constructor -MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h) - : wxFrame(nullptr, wxID_ANY, title, wxPoint(x, y), wxSize(w, h)), +MyFrame::MyFrame() + : wxFrame(nullptr, wxID_ANY, "wxTreeCtrl test", + wxDefaultPosition, FromDIP(wxSize(450, 600), nullptr)), m_treeCtrl(nullptr) #if wxUSE_LOG , m_textCtrl(nullptr) diff --git a/samples/treectrl/treetest.h b/samples/treectrl/treetest.h index 24a751c34c..de6b9bf0d0 100644 --- a/samples/treectrl/treetest.h +++ b/samples/treectrl/treetest.h @@ -181,7 +181,7 @@ class MyFrame: public wxFrame { public: // ctor and dtor - MyFrame(const wxString& title, int x, int y, int w, int h); + MyFrame(); virtual ~MyFrame(); // menu callbacks From 308e902102f01fb2894308d1a8dae1ffb231ea2b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 25 Oct 2023 19:10:55 +0200 Subject: [PATCH 06/18] Add wxTreeCtrl::SetStateImages() Unlike the existing SetStateImageList() function, the new one allows to provide the high-resolution versions of the state images too. Update the treectrl sample to use the new API. Closes #23993. --- include/wx/generic/treectlg.h | 1 + include/wx/msw/treectrl.h | 2 ++ include/wx/qt/treectrl.h | 2 ++ include/wx/treectrl.h | 15 ++++++--- interface/wx/treectrl.h | 26 +++++++++++++--- samples/treectrl/treetest.cpp | 57 ++++++++++++++--------------------- samples/treectrl/treetest.h | 2 +- src/generic/treectlg.cpp | 10 ++++++ src/msw/treectrl.cpp | 6 ++++ src/qt/treectrl.cpp | 6 ++++ 10 files changed, 83 insertions(+), 44 deletions(-) diff --git a/include/wx/generic/treectlg.h b/include/wx/generic/treectlg.h index e431299f88..bd6ae56b40 100644 --- a/include/wx/generic/treectlg.h +++ b/include/wx/generic/treectlg.h @@ -71,6 +71,7 @@ public: virtual unsigned int GetIndent() const override { return m_indent; } virtual void SetIndent(unsigned int indent) override; + virtual void SetStateImages(const wxVector& images) override; virtual void SetImageList(wxImageList *imageList) override; virtual void SetStateImageList(wxImageList *imageList) override; diff --git a/include/wx/msw/treectrl.h b/include/wx/msw/treectrl.h index cdc4aebd32..98b8c8bc29 100644 --- a/include/wx/msw/treectrl.h +++ b/include/wx/msw/treectrl.h @@ -72,6 +72,8 @@ public: virtual unsigned int GetIndent() const override; virtual void SetIndent(unsigned int indent) override; + virtual void SetStateImages(const wxVector& images) override; + virtual void SetImageList(wxImageList *imageList) override; virtual void SetStateImageList(wxImageList *imageList) override; diff --git a/include/wx/qt/treectrl.h b/include/wx/qt/treectrl.h index 77c49072a8..3f252c4928 100644 --- a/include/wx/qt/treectrl.h +++ b/include/wx/qt/treectrl.h @@ -35,6 +35,8 @@ public: virtual unsigned int GetIndent() const override; virtual void SetIndent(unsigned int indent) override; + virtual void SetStateImages(const wxVector& images) override; + virtual void SetImageList(wxImageList *imageList) override; virtual void SetStateImageList(wxImageList *imageList) override; diff --git a/include/wx/treectrl.h b/include/wx/treectrl.h index e004abc3ed..d72655227e 100644 --- a/include/wx/treectrl.h +++ b/include/wx/treectrl.h @@ -56,10 +56,17 @@ public: unsigned int GetSpacing() const { return m_spacing; } void SetSpacing(unsigned int spacing) { m_spacing = spacing; } - // In addition to {Set,Get,Assign}ImageList() methods inherited from - // wxWithImages, this control has similar functions for the state image - // list that can be used to show a state icon corresponding to an - // app-defined item state (for example, checked/unchecked). + // In addition to SetImages() inherited from wxWithImages, this class + // also provides SetStateImages() function which can be used to set the + // images showing an icon corresponding to an app-defined item state + // (for example, checked/unchecked). + virtual void SetStateImages(const wxVector& images) = 0; + + // These functions parallel {Set,Get,Assign}ImageList() methods + // inherited from wxWithImages, but correspond to SetStateImages(). + // As with the other functions using wxImageList, they still work but + // don't allow to define high resolution icons for high DPI screens, so + // SetStateImages() above should be preferred. wxImageList *GetStateImageList() const { return m_imagesState.GetImageList(); diff --git a/interface/wx/treectrl.h b/interface/wx/treectrl.h index 382e81d5a2..5fafa5efd8 100644 --- a/interface/wx/treectrl.h +++ b/interface/wx/treectrl.h @@ -30,9 +30,11 @@ In addition to normal images, handled with the methods mentioned above, wxTreeCtrl also provides optional state images that may be used to indicate some additional state of the item, e.g. checked or unchecked status. These - images can be set using SetStateImageList() and AssignStateImageList() - functions that behave in the same way as the corresponding methods of - wxWithImages. + images can be set using SetStateImages() (preferred, as they allow to + specify high resolution versions of the state images too) or legacy + SetStateImageList() and AssignStateImageList() functions that behave in the + same way as the corresponding methods of wxWithImages. Note that state + images are currently not supported in the native wxQt version. Finally, in the generic version of this control (wxGenericTreeCtrl), also provides SetButtonsImageList() and AssignButtonsImageList(), which can be @@ -281,6 +283,8 @@ public: automatically deleted by wxTreeCtrl as appropriate (i.e. it takes ownership of the list). + @note Prefer using SetStateImages() in the new code. + @see SetStateImageList(). */ void AssignStateImageList(wxImageList* imageList); @@ -976,10 +980,24 @@ public: by @ref wxTreeCtrl "wxTreeCtrl"'s destructor, you must delete it yourself. - @see AssignStateImageList(). + @note Prefer using SetStateImages() in the new code. + + @see AssignStateImageList() */ virtual void SetStateImageList(wxImageList* imageList); + /** + Sets the images to use for the application-defined item states. + + This function takes a vector of wxBitmapBundle objects which can + specify multiple versions of the same icon for different display + resolutions for each state. If the vector is empty, no state images are + shown. + + @since 3.3.0 + */ + virtual void SetStateImages(const wxVector& images); + /** Sets the mode flags associated with the display of the tree control. The new mode takes effect immediately. diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp index 13e447e64f..a23b542517 100644 --- a/samples/treectrl/treetest.cpp +++ b/samples/treectrl/treetest.cpp @@ -704,12 +704,12 @@ void MyFrame::OnToggleStates(wxCommandEvent& WXUNUSED(event)) { if ( wxGetApp().ShowStates() ) { - m_treeCtrl->SetStateImageList(nullptr); + m_treeCtrl->SetStateImages({}); wxGetApp().SetShowStates(false); } else { - m_treeCtrl->CreateStateImageList(); + m_treeCtrl->CreateStateImages(); wxGetApp().SetShowStates(true); } } @@ -732,7 +732,7 @@ void MyFrame::OnToggleAlternateStates(wxCommandEvent& WXUNUSED(event)) bool alternateStates = m_treeCtrl->AlternateStates(); m_treeCtrl->SetAlternateStates(!alternateStates); - m_treeCtrl->CreateStateImageList(); + m_treeCtrl->CreateStateImages(); // normal states < alternate states // so we must reset broken states @@ -950,7 +950,7 @@ MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id, m_reverseSort = false; CreateImages(16); - CreateStateImageList(); + CreateStateImages(); // Add some items to the tree AddTestItemsToTree(NUM_CHILDREN_PER_LEVEL, NUM_LEVELS); @@ -1039,46 +1039,33 @@ void MyTreeCtrl::CreateImages(int size) SetImages(images); } -void MyTreeCtrl::CreateStateImageList() +void MyTreeCtrl::CreateStateImages() { - wxImageList *states; - wxBusyCursor wait; + std::vector icons; if (m_alternateStates) { - wxIcon icons[5]; - icons[0] = wxIcon(state1_xpm); // yellow - icons[1] = wxIcon(state2_xpm); // green - icons[2] = wxIcon(state3_xpm); // red - icons[3] = wxIcon(state4_xpm); // blue - icons[4] = wxIcon(state5_xpm); // black - - int width = icons[0].GetWidth(), - height = icons[0].GetHeight(); - - // Make a state image list containing small icons - states = new wxImageList(width, height, true); - - for ( size_t i = 0; i < WXSIZEOF(icons); i++ ) - states->Add(icons[i]); + icons.push_back(wxIcon(state1_xpm)); // yellow + icons.push_back(wxIcon(state2_xpm)); // green + icons.push_back(wxIcon(state3_xpm)); // red + icons.push_back(wxIcon(state4_xpm)); // blue + icons.push_back(wxIcon(state5_xpm)); // black } else { - wxIcon icons[2]; - icons[0] = wxIcon(unchecked_xpm); - icons[1] = wxIcon(checked_xpm); - - int width = icons[0].GetWidth(), - height = icons[0].GetHeight(); - - // Make an state image list containing small icons - states = new wxImageList(width, height, true); - - for ( size_t i = 0; i < WXSIZEOF(icons); i++ ) - states->Add(icons[i]); + icons.push_back(wxIcon(unchecked_xpm)); + icons.push_back(wxIcon(checked_xpm)); } - AssignStateImageList(states); + std::vector images; + + const wxSize iconSize(icons[0].GetWidth(), icons[0].GetHeight()); + for ( const wxIcon& icon : icons ) + { + images.push_back(wxBitmapBundle::FromImpl(new FixedSizeImpl(iconSize, icon))); + } + + SetStateImages(images); } void MyTreeCtrl::CreateButtonsImageList(int size) diff --git a/samples/treectrl/treetest.h b/samples/treectrl/treetest.h index de6b9bf0d0..01bcb292f7 100644 --- a/samples/treectrl/treetest.h +++ b/samples/treectrl/treetest.h @@ -113,7 +113,7 @@ public: void CreateImages(int size); void CreateButtonsImageList(int size = 11); - void CreateStateImageList(); + void CreateStateImages(); void AddTestItemsToTree(size_t numChildren, size_t depth); diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index 49d0987335..2271b0d8f0 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -2481,6 +2481,16 @@ void wxGenericTreeCtrl::SetImageList(wxImageList *imageList) UpdateAfterImageListChange(); } +void wxGenericTreeCtrl::SetStateImages(const wxVector& images) +{ + m_imagesState.SetImages(images); + + // As above, only call it for the side effect of updating the image list. + m_imagesState.GetUpdatedImageListFor(this); + + UpdateAfterImageListChange(); +} + void wxGenericTreeCtrl::SetStateImageList(wxImageList *imageList) { m_imagesState.SetImageList(imageList); diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index cfd4466023..b0b725982d 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -946,6 +946,12 @@ void wxTreeCtrl::SetImageList(wxImageList *imageList) SetAnyImageList(imageList, TVSIL_NORMAL); } +void wxTreeCtrl::SetStateImages(const wxVector& images) +{ + m_imagesState.SetImages(images); + SetAnyImageList(m_imagesState.GetUpdatedImageListFor(this), TVSIL_STATE); +} + void wxTreeCtrl::SetStateImageList(wxImageList *imageList) { m_imagesState.SetImageList(imageList); diff --git a/src/qt/treectrl.cpp b/src/qt/treectrl.cpp index 5b6fe397d0..1faedcbc6f 100644 --- a/src/qt/treectrl.cpp +++ b/src/qt/treectrl.cpp @@ -629,6 +629,12 @@ void wxTreeCtrl::OnImagesChanged() } } +void wxTreeCtrl::SetStateImages(const wxVector& images) +{ + m_imagesState.SetImages(images); + m_qtTreeWidget->update(); +} + void wxTreeCtrl::SetStateImageList(wxImageList *imageList) { m_imagesState.SetImageList(imageList); From a5449a94a16c59d7e1015cca173eb10015dc2fe6 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 26 Oct 2023 01:36:44 +0200 Subject: [PATCH 07/18] Add high DPI versions of state icons to the treectrl sample This allows to check that the high DPI are really used in high DPI, instead of scaled up versions of the smaller icons. --- samples/treectrl/state0_2x_png.h | 68 ++++++++++++++++++++++ samples/treectrl/state0_png.h | 38 +++++++++++++ samples/treectrl/state1_2x_png.h | 98 ++++++++++++++++++++++++++++++++ samples/treectrl/state1_png.h | 54 ++++++++++++++++++ samples/treectrl/state2_2x_png.h | 96 +++++++++++++++++++++++++++++++ samples/treectrl/state2_png.h | 55 ++++++++++++++++++ samples/treectrl/treetest.cpp | 49 ++++++++++------ 7 files changed, 440 insertions(+), 18 deletions(-) create mode 100644 samples/treectrl/state0_2x_png.h create mode 100644 samples/treectrl/state0_png.h create mode 100644 samples/treectrl/state1_2x_png.h create mode 100644 samples/treectrl/state1_png.h create mode 100644 samples/treectrl/state2_2x_png.h create mode 100644 samples/treectrl/state2_png.h diff --git a/samples/treectrl/state0_2x_png.h b/samples/treectrl/state0_2x_png.h new file mode 100644 index 0000000000..1afe5e52f0 --- /dev/null +++ b/samples/treectrl/state0_2x_png.h @@ -0,0 +1,68 @@ +/* state0_2x.png - 525 bytes */ +static const unsigned char state0_2x_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, + 0xf4, 0x00, 0x00, 0x01, 0xd4, 0x49, 0x44, 0x41, + 0x54, 0x58, 0xc3, 0x63, 0x60, 0x80, 0x02, 0xe9, + 0x86, 0xa3, 0x06, 0x52, 0x0d, 0x87, 0x97, 0x4b, + 0x35, 0x1e, 0x79, 0x01, 0xc4, 0xff, 0x69, 0x84, + 0x9f, 0x4b, 0x35, 0x1e, 0x5d, 0x26, 0xd3, 0x70, + 0x48, 0x8f, 0x01, 0x19, 0x48, 0x36, 0x1e, 0x89, + 0x06, 0x4a, 0xfe, 0xa2, 0xa1, 0xc5, 0xe8, 0xf8, + 0xa7, 0x54, 0xd3, 0x91, 0x28, 0x84, 0xcf, 0xe9, + 0x6b, 0x39, 0xdc, 0x11, 0xe0, 0x90, 0x80, 0x06, + 0xfb, 0xff, 0x01, 0xc1, 0x0d, 0x47, 0x96, 0x32, + 0x00, 0x19, 0x2f, 0x07, 0xcc, 0x01, 0xc0, 0x34, + 0x01, 0x72, 0xc0, 0xbf, 0x01, 0x74, 0xc0, 0x3f, + 0x06, 0x4a, 0x0d, 0x51, 0x6d, 0x3f, 0xfe, 0x3f, + 0x7a, 0xe9, 0xd5, 0xff, 0x9e, 0xb3, 0x2f, 0x90, + 0xa5, 0x9f, 0x22, 0x07, 0x18, 0xf6, 0x9d, 0xfa, + 0xff, 0xe4, 0xc3, 0x8f, 0xff, 0x30, 0xb0, 0xe8, + 0xcc, 0x73, 0xfa, 0x3a, 0xa0, 0x6b, 0xff, 0xc3, + 0xff, 0xe8, 0xc0, 0xa0, 0xf7, 0x14, 0xfd, 0x1c, + 0x50, 0xbc, 0xe9, 0x36, 0x8a, 0xe5, 0x5f, 0x7e, + 0xfe, 0xf9, 0xaf, 0xdc, 0x76, 0x8c, 0x7e, 0x0e, + 0x90, 0x6d, 0x3a, 0xfa, 0x7f, 0xde, 0xa9, 0x67, + 0xff, 0xdf, 0x7c, 0xfd, 0xf5, 0xff, 0xee, 0x9b, + 0x6f, 0xff, 0x63, 0x97, 0x5d, 0xa5, 0x6f, 0x14, + 0x50, 0x03, 0x53, 0x9c, 0x08, 0xb5, 0xbb, 0x4e, + 0xd0, 0xd7, 0x01, 0x21, 0x0b, 0x2f, 0xff, 0x5f, + 0x7d, 0xf1, 0xe5, 0xff, 0x97, 0x9f, 0x7f, 0x82, + 0xe3, 0xfd, 0x1f, 0x10, 0x6f, 0xb9, 0xfa, 0xe6, + 0xbf, 0x42, 0xcb, 0x31, 0xda, 0x3b, 0x00, 0x94, + 0xc2, 0x4f, 0x3f, 0xfa, 0xf4, 0x7f, 0xe3, 0x95, + 0xd7, 0xff, 0x3f, 0xfd, 0xf8, 0x83, 0x92, 0x00, + 0xcb, 0x36, 0xdf, 0xa1, 0x6f, 0x14, 0x74, 0xa3, + 0x65, 0xc1, 0x59, 0x27, 0x9e, 0xd2, 0xd7, 0x01, + 0x53, 0x8f, 0x3e, 0x41, 0x71, 0x40, 0xdb, 0x9e, + 0x07, 0xf4, 0x75, 0xc0, 0xa1, 0xbb, 0xef, 0x51, + 0x1c, 0x10, 0xb4, 0xe0, 0x12, 0xfd, 0x1c, 0xa0, + 0xd4, 0x7a, 0xec, 0xff, 0xf7, 0xdf, 0x7f, 0xe1, + 0x96, 0x7f, 0x06, 0x16, 0x40, 0x72, 0xcd, 0x47, + 0xe9, 0xe7, 0x80, 0xa8, 0x25, 0x57, 0x50, 0x7c, + 0xbf, 0xeb, 0xe6, 0x5b, 0xfa, 0x96, 0x03, 0x33, + 0x8e, 0xa1, 0xc6, 0x7f, 0xcd, 0xf6, 0xbb, 0xf4, + 0x75, 0xc0, 0xb5, 0x17, 0x5f, 0x50, 0x1c, 0xe0, + 0x38, 0xed, 0x1c, 0xfd, 0x1c, 0x00, 0x2a, 0x70, + 0xfe, 0xa1, 0xd5, 0x80, 0xea, 0x1d, 0xc7, 0xe9, + 0xe7, 0x00, 0x69, 0x20, 0x7e, 0xf6, 0xf1, 0x27, + 0x8a, 0x03, 0x56, 0x5d, 0x78, 0xf9, 0xbf, 0x7c, + 0xcb, 0x9d, 0xff, 0x65, 0x5b, 0xee, 0xd0, 0x27, + 0x0a, 0xe2, 0x96, 0x5f, 0xfb, 0xff, 0x03, 0x29, + 0x17, 0x80, 0x42, 0xe4, 0xf2, 0xf3, 0x2f, 0xff, + 0xf3, 0xd6, 0xdf, 0xa2, 0x5f, 0x39, 0x60, 0x04, + 0xac, 0x88, 0x52, 0x57, 0x5d, 0xff, 0x1f, 0xb1, + 0xf8, 0xca, 0x7f, 0xdd, 0xee, 0x93, 0x14, 0x45, + 0xc1, 0x80, 0x37, 0x4a, 0x5f, 0x0c, 0x70, 0xb3, + 0xfc, 0xe8, 0xb2, 0x01, 0x74, 0xc0, 0x12, 0x06, + 0x50, 0xf7, 0x08, 0xdc, 0x57, 0xa3, 0xbf, 0xe5, + 0x3f, 0xc4, 0x1b, 0x8e, 0xea, 0x80, 0xfb, 0x87, + 0xa0, 0x8e, 0x22, 0x9d, 0x1d, 0xf1, 0x43, 0xaa, + 0xf1, 0x70, 0x24, 0x4a, 0x0f, 0x19, 0x1c, 0x12, + 0xc0, 0xbe, 0x1a, 0x50, 0xf2, 0x19, 0x0d, 0x2d, + 0x06, 0x99, 0xbd, 0x04, 0xee, 0x73, 0x20, 0x00, + 0x00, 0x10, 0x36, 0xc0, 0x2e, 0xe6, 0x2a, 0xe9, + 0x42, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, + 0x44, 0xae, 0x42, 0x60, 0x82}; diff --git a/samples/treectrl/state0_png.h b/samples/treectrl/state0_png.h new file mode 100644 index 0000000000..58ae744b90 --- /dev/null +++ b/samples/treectrl/state0_png.h @@ -0,0 +1,38 @@ +/* state0.png - 287 bytes */ +static const unsigned char state0_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, + 0x61, 0x00, 0x00, 0x00, 0xe6, 0x49, 0x44, 0x41, + 0x54, 0x38, 0xcb, 0x63, 0x90, 0x68, 0x3b, 0x24, + 0x2a, 0xdd, 0x78, 0x64, 0x8d, 0x54, 0xe3, 0x91, + 0x2f, 0x40, 0xfc, 0x9f, 0x48, 0xfc, 0x45, 0xb2, + 0xe9, 0xf0, 0x6a, 0xa9, 0x86, 0xfd, 0x22, 0x0c, + 0x50, 0xcd, 0xff, 0xc9, 0xc3, 0x47, 0x57, 0x31, + 0x90, 0x68, 0x33, 0x3a, 0xfe, 0xcc, 0x80, 0x4f, + 0x81, 0x42, 0xcb, 0xb1, 0xff, 0xb3, 0x8e, 0x3f, + 0xfd, 0xdf, 0xb0, 0xf3, 0x1e, 0x4e, 0x35, 0x78, + 0x0d, 0xf0, 0x9d, 0x7b, 0xf1, 0x3f, 0x08, 0xfc, + 0xf9, 0xf7, 0xef, 0xbf, 0x62, 0xeb, 0x31, 0xd2, + 0x0d, 0x00, 0x86, 0xcf, 0xff, 0xfc, 0x0d, 0xb7, + 0xfe, 0xc7, 0x2c, 0xbd, 0x4a, 0xba, 0x0b, 0x40, + 0xb6, 0x77, 0xef, 0x7f, 0xf8, 0xbf, 0x6c, 0xcb, + 0x1d, 0xbc, 0xe1, 0x80, 0xd5, 0x00, 0xd9, 0xa6, + 0xa3, 0xff, 0x73, 0xd7, 0xdd, 0xfc, 0xff, 0xf0, + 0xfd, 0x77, 0xb0, 0x17, 0x3c, 0x67, 0x5f, 0x20, + 0x2f, 0x0c, 0xae, 0xbd, 0xf8, 0x02, 0x36, 0xc0, + 0x71, 0xda, 0x39, 0xd2, 0x0d, 0xd0, 0xee, 0x3a, + 0xf1, 0xff, 0xef, 0xbf, 0xff, 0xff, 0x5f, 0x7f, + 0xf9, 0x05, 0x0e, 0x0b, 0x92, 0x0d, 0xc8, 0x58, + 0x73, 0x03, 0x6c, 0xfb, 0xfa, 0xcb, 0xaf, 0x48, + 0x0f, 0x03, 0x10, 0x06, 0xc5, 0x3d, 0x08, 0xec, + 0xba, 0xf9, 0xf6, 0xbf, 0xfb, 0x2c, 0x32, 0xc2, + 0x40, 0xb3, 0xf3, 0xc4, 0xff, 0xb9, 0x27, 0x9f, + 0xfd, 0x9f, 0x03, 0xc4, 0x91, 0x4b, 0xae, 0xe0, + 0x35, 0x80, 0xb2, 0xa4, 0x0c, 0xce, 0x55, 0xe4, + 0x1a, 0xd0, 0x70, 0x64, 0x25, 0x03, 0x28, 0x4b, + 0x42, 0x0d, 0xf9, 0x4c, 0x8a, 0xcd, 0x20, 0xcd, + 0x20, 0xbd, 0x00, 0x4e, 0x99, 0x73, 0x54, 0x25, + 0xd3, 0x47, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82}; diff --git a/samples/treectrl/state1_2x_png.h b/samples/treectrl/state1_2x_png.h new file mode 100644 index 0000000000..f9a2b57539 --- /dev/null +++ b/samples/treectrl/state1_2x_png.h @@ -0,0 +1,98 @@ +/* state1_2x.png - 765 bytes */ +static const unsigned char state1_2x_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, + 0xf4, 0x00, 0x00, 0x02, 0xc4, 0x49, 0x44, 0x41, + 0x54, 0x58, 0xc3, 0x63, 0x60, 0x20, 0x12, 0xec, + 0xd4, 0x73, 0xe3, 0xde, 0xaf, 0xe6, 0x10, 0xbe, + 0x4f, 0xcd, 0x71, 0x12, 0x90, 0x3e, 0xb5, 0x5f, + 0xcd, 0xf1, 0x31, 0x10, 0x7f, 0x03, 0xe2, 0x5f, + 0x40, 0xfc, 0x0a, 0x24, 0x06, 0x94, 0x9b, 0x05, + 0xa4, 0x23, 0x8e, 0xa8, 0x5b, 0xf3, 0x32, 0x50, + 0x0b, 0xec, 0x51, 0x73, 0x51, 0x82, 0x18, 0xec, + 0xf8, 0x09, 0x88, 0xff, 0x13, 0x83, 0x0f, 0xa8, + 0x3b, 0x7e, 0x05, 0xd2, 0x73, 0x0e, 0x6a, 0xda, + 0xa9, 0x92, 0x6d, 0xf1, 0x7e, 0x05, 0x07, 0x0e, + 0xa0, 0x6f, 0xda, 0x81, 0x06, 0xfd, 0x20, 0xd6, + 0x62, 0x2c, 0xf8, 0xd7, 0x3e, 0x75, 0xc7, 0x2e, + 0x90, 0x59, 0x24, 0x59, 0x7e, 0x50, 0xd9, 0x4e, + 0xf6, 0x80, 0x9a, 0xe3, 0x49, 0x0a, 0x2c, 0x46, + 0xc7, 0xc7, 0x0f, 0x69, 0xda, 0x4a, 0x12, 0x65, + 0xf9, 0x3e, 0x15, 0x47, 0x6d, 0xa0, 0x86, 0xd7, + 0x54, 0xb4, 0x1c, 0x86, 0x1f, 0xef, 0x51, 0x77, + 0xd6, 0xc3, 0x1f, 0xec, 0xca, 0x0e, 0x2a, 0x40, + 0x85, 0xcf, 0x08, 0x19, 0x76, 0xbb, 0x65, 0xca, + 0xff, 0x57, 0xdb, 0x0f, 0xa0, 0x60, 0x90, 0x18, + 0x31, 0x8e, 0xd8, 0xaf, 0xed, 0x20, 0x81, 0xd5, + 0xf2, 0x33, 0xc6, 0xc6, 0xac, 0xd0, 0xd4, 0x4d, + 0xd0, 0xa0, 0x67, 0xab, 0xb7, 0xfe, 0x47, 0x07, + 0xcf, 0x56, 0x6d, 0x21, 0x36, 0x24, 0xce, 0x1c, + 0x93, 0xb1, 0xe4, 0xc4, 0xf4, 0xbd, 0x9a, 0x53, + 0x07, 0xb1, 0xc1, 0xf9, 0x78, 0xc1, 0x1a, 0x0c, + 0x07, 0x3c, 0x9e, 0xbf, 0x9a, 0xe8, 0xe8, 0x00, + 0xa6, 0xaf, 0x46, 0x8c, 0x44, 0x47, 0x4a, 0x6a, + 0x7f, 0x30, 0x75, 0x11, 0x86, 0x03, 0xee, 0x4f, + 0x59, 0x48, 0x4a, 0x7a, 0xf8, 0x82, 0x92, 0x28, + 0xf7, 0xab, 0x3a, 0x4c, 0x27, 0x25, 0x41, 0xdd, + 0xed, 0x9a, 0x89, 0xe1, 0x80, 0x3b, 0x5d, 0x33, + 0x48, 0x4a, 0x94, 0xfb, 0x54, 0x1d, 0xa7, 0x81, + 0x2d, 0x07, 0xc5, 0x07, 0x50, 0xe0, 0x33, 0x29, + 0x9a, 0x6f, 0xd6, 0xf7, 0x63, 0x38, 0xe0, 0x66, + 0x5d, 0x1f, 0xa9, 0xb9, 0xe2, 0x0b, 0xb8, 0xc4, + 0x3c, 0xa0, 0xe6, 0x14, 0x48, 0x6a, 0x96, 0xba, + 0x56, 0xd2, 0x86, 0xe1, 0x80, 0x6b, 0xc5, 0xad, + 0x64, 0x64, 0x4d, 0x87, 0x70, 0x92, 0x83, 0x1f, + 0x84, 0x2f, 0x67, 0xd6, 0x60, 0x38, 0xe0, 0x72, + 0x46, 0x35, 0xc9, 0x0e, 0x00, 0x26, 0xc6, 0x99, + 0xc0, 0xd4, 0xef, 0x78, 0x98, 0x54, 0x8d, 0x17, + 0xe2, 0x8a, 0x30, 0x1c, 0x70, 0x3e, 0xb6, 0x90, + 0xac, 0x12, 0x12, 0x18, 0x05, 0x8e, 0x2f, 0x49, + 0xd5, 0x78, 0x36, 0x24, 0x13, 0xc3, 0x01, 0x67, + 0x82, 0x33, 0xc8, 0x09, 0x81, 0x97, 0xa0, 0x10, + 0xf8, 0x42, 0xaa, 0xc6, 0x93, 0x9e, 0x09, 0x18, + 0x0e, 0x38, 0xe9, 0x11, 0x4f, 0x4e, 0x08, 0xfc, + 0x60, 0x20, 0xa7, 0xb6, 0x3b, 0x66, 0x17, 0x86, + 0xe1, 0x80, 0x63, 0xb6, 0xa1, 0xa4, 0x87, 0x00, + 0xb0, 0xda, 0x06, 0x45, 0xc1, 0x53, 0x52, 0x35, + 0x1e, 0x36, 0xf6, 0xc1, 0x70, 0xc0, 0x61, 0x23, + 0x6f, 0x72, 0x1c, 0xf0, 0x10, 0xe4, 0x80, 0xa3, + 0x24, 0x6b, 0xd4, 0x74, 0xc6, 0xa8, 0x8c, 0x40, + 0x62, 0x64, 0x25, 0x42, 0x72, 0xb2, 0x21, 0xd5, + 0xb0, 0xaa, 0xd3, 0x04, 0xb2, 0x0a, 0x22, 0xaa, + 0x61, 0x75, 0x87, 0x10, 0x86, 0x6d, 0x2a, 0x9e, + 0x7c, 0xa4, 0x16, 0xc5, 0x20, 0x7c, 0xbd, 0xb2, + 0xf3, 0xff, 0xcb, 0xad, 0xfb, 0xfe, 0x3f, 0x5b, + 0xb9, 0xe5, 0xff, 0x29, 0x9f, 0x64, 0x72, 0x1c, + 0xf0, 0x7e, 0xb3, 0x94, 0x2f, 0x17, 0xb4, 0x2a, + 0x76, 0x98, 0x4c, 0x52, 0x51, 0x5c, 0xdc, 0x82, + 0x92, 0x00, 0x7f, 0xbd, 0xfb, 0xf0, 0xff, 0x90, + 0x81, 0x17, 0xa9, 0x65, 0xc0, 0x54, 0x78, 0x6d, + 0xb8, 0x57, 0xc5, 0x49, 0x99, 0x94, 0xec, 0xf8, + 0x64, 0xf1, 0x7a, 0xcc, 0x82, 0x28, 0x30, 0x8d, + 0x14, 0x07, 0x7c, 0xdb, 0xad, 0xe4, 0x22, 0x87, + 0xd2, 0x26, 0x00, 0x35, 0x12, 0xc8, 0xad, 0x8e, + 0xff, 0xfd, 0xf9, 0xfb, 0xff, 0xa8, 0x55, 0x10, + 0x09, 0x71, 0xef, 0xd4, 0x82, 0xd1, 0x22, 0x02, + 0xa6, 0x05, 0x76, 0xa0, 0x23, 0x2e, 0x12, 0x63, + 0xc0, 0x21, 0x7d, 0xcf, 0xff, 0xaf, 0x76, 0x1c, + 0xf8, 0xff, 0xe7, 0xdb, 0x8f, 0xff, 0x3f, 0x5e, + 0xbe, 0xf9, 0x7f, 0xb3, 0xb6, 0x97, 0x94, 0x1a, + 0xf0, 0x14, 0xc8, 0x2e, 0x7c, 0xcd, 0xf1, 0xa7, + 0x34, 0x4c, 0xf9, 0x2f, 0x30, 0x82, 0x1e, 0xa3, + 0x27, 0x04, 0x6c, 0x3a, 0xd3, 0xc8, 0x11, 0x4f, + 0x80, 0xbe, 0xd7, 0x20, 0xba, 0x63, 0x02, 0xd4, + 0x70, 0x81, 0x8a, 0x96, 0x9f, 0x06, 0x75, 0xf1, + 0x48, 0xea, 0x1d, 0x81, 0xe2, 0x09, 0xd8, 0x52, + 0x6e, 0xa0, 0xb0, 0x6b, 0xf6, 0x1d, 0x94, 0xe0, + 0x40, 0x4d, 0x7e, 0x4a, 0x3b, 0xa7, 0x93, 0x48, + 0xe9, 0x9c, 0x82, 0x0a, 0x36, 0x50, 0x3e, 0xdf, + 0xaf, 0xe2, 0x20, 0x43, 0xb5, 0x5e, 0x32, 0xb0, + 0x47, 0xc3, 0x03, 0xec, 0x68, 0xfa, 0x83, 0x0d, + 0x56, 0x73, 0x3c, 0x02, 0x89, 0x53, 0x70, 0x5b, + 0xe2, 0x1d, 0x28, 0x71, 0x01, 0xc5, 0x0f, 0x82, + 0xe4, 0x40, 0x6a, 0xb0, 0x76, 0x3c, 0x70, 0x00, + 0x00, 0x5d, 0x96, 0x8a, 0x03, 0xb0, 0xf9, 0xb5, + 0xa3, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, + 0x44, 0xae, 0x42, 0x60, 0x82}; diff --git a/samples/treectrl/state1_png.h b/samples/treectrl/state1_png.h new file mode 100644 index 0000000000..5d1514a96e --- /dev/null +++ b/samples/treectrl/state1_png.h @@ -0,0 +1,54 @@ +/* state1.png - 415 bytes */ +static const unsigned char state1_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, + 0x61, 0x00, 0x00, 0x01, 0x66, 0x49, 0x44, 0x41, + 0x54, 0x38, 0xcb, 0x63, 0x60, 0x40, 0x03, 0xfb, + 0xd4, 0x1c, 0xf5, 0x0f, 0xa8, 0x39, 0x4e, 0xdd, + 0xaf, 0xe6, 0x78, 0x1d, 0x88, 0xbf, 0x01, 0xf1, + 0x17, 0x20, 0xbe, 0xb2, 0x5f, 0xd5, 0x69, 0xc2, + 0x7e, 0x4d, 0x07, 0x1d, 0x06, 0x5c, 0xe0, 0x98, + 0x8c, 0x25, 0xe7, 0x7e, 0x55, 0x87, 0xe9, 0x40, + 0x03, 0xfe, 0x02, 0x35, 0xfc, 0xc7, 0x81, 0xff, + 0x00, 0xf1, 0x94, 0x55, 0xda, 0xa1, 0x6c, 0x98, + 0x9a, 0xd5, 0x1d, 0x0f, 0x20, 0x2b, 0x3e, 0x66, + 0x17, 0xf6, 0xff, 0x4a, 0x5e, 0x03, 0x18, 0x83, + 0xd8, 0xc8, 0x72, 0x40, 0x17, 0xee, 0x45, 0x31, + 0x04, 0xa8, 0x79, 0x06, 0xba, 0x6d, 0x97, 0xd2, + 0x2a, 0xff, 0xc3, 0xc0, 0xa5, 0xd4, 0x0a, 0x2c, + 0xae, 0x71, 0x98, 0x0c, 0xd6, 0xbc, 0x47, 0xdd, + 0x59, 0x0f, 0x28, 0xf0, 0x0f, 0x5d, 0xc1, 0xf9, + 0xe8, 0x7c, 0xb8, 0x01, 0xe7, 0xa2, 0xf2, 0xb0, + 0x7a, 0x67, 0x9f, 0x8a, 0xa3, 0x36, 0x03, 0x34, + 0xc0, 0x30, 0x14, 0x9c, 0x0e, 0x48, 0x83, 0x1b, + 0x70, 0xda, 0x3f, 0x15, 0x6b, 0x98, 0x00, 0xc3, + 0xab, 0x8f, 0x01, 0xc8, 0xb8, 0x81, 0x4d, 0xf2, + 0x84, 0x6b, 0x0c, 0xdc, 0x80, 0x13, 0x2e, 0xd1, + 0xd8, 0x03, 0x55, 0xd5, 0xf1, 0x32, 0xc8, 0x80, + 0x1f, 0xd8, 0x24, 0x8f, 0x5a, 0x05, 0xc1, 0x0d, + 0x38, 0x6a, 0x19, 0x88, 0x2b, 0x56, 0x3e, 0xe1, + 0x34, 0xe0, 0x90, 0xbe, 0x27, 0xdc, 0x80, 0x43, + 0xfa, 0x1e, 0x58, 0x0d, 0x38, 0xa0, 0xee, 0xf8, + 0x95, 0x01, 0x9a, 0x60, 0x30, 0x15, 0xa8, 0x3b, + 0xc1, 0xa3, 0x11, 0xc4, 0xc6, 0x6a, 0x80, 0x9a, + 0xe3, 0x55, 0x9c, 0x81, 0x08, 0xc2, 0x17, 0xe2, + 0x8a, 0xfe, 0x9f, 0x09, 0x4c, 0xc3, 0xe5, 0x7c, + 0x50, 0x20, 0x4e, 0x02, 0x47, 0x23, 0xb6, 0xd4, + 0x77, 0x2e, 0x32, 0x0f, 0xec, 0xfc, 0x7f, 0xbf, + 0x7f, 0xff, 0x3f, 0x6c, 0xe2, 0x8b, 0x4d, 0xf3, + 0x5f, 0x78, 0xd2, 0xde, 0xa7, 0xea, 0x38, 0x0d, + 0x5d, 0xc1, 0x71, 0xa7, 0xa8, 0xff, 0x3f, 0x5f, + 0xbf, 0xfd, 0xff, 0xf9, 0xc6, 0xdd, 0xff, 0x07, + 0xb5, 0x5d, 0xb1, 0xb9, 0x60, 0x0a, 0x3c, 0x25, + 0x6e, 0x53, 0xf1, 0x64, 0x07, 0xa6, 0xac, 0x7d, + 0x78, 0xf2, 0x00, 0x3a, 0xde, 0x03, 0xd2, 0x83, + 0x92, 0x1f, 0x40, 0x02, 0x20, 0x97, 0xe0, 0xcb, + 0x4c, 0x50, 0xb9, 0x29, 0xfb, 0x15, 0x1c, 0x38, + 0x70, 0xe6, 0xca, 0x83, 0x1a, 0x76, 0xba, 0xa0, + 0x74, 0x0e, 0x0a, 0x61, 0xa0, 0xe2, 0xef, 0x40, + 0xfc, 0x19, 0x94, 0x9d, 0x41, 0x01, 0x86, 0x2d, + 0x3b, 0x03, 0x00, 0x58, 0x21, 0xed, 0xb5, 0xd7, + 0x41, 0xa9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x49, + 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82}; diff --git a/samples/treectrl/state2_2x_png.h b/samples/treectrl/state2_2x_png.h new file mode 100644 index 0000000000..7093d894d0 --- /dev/null +++ b/samples/treectrl/state2_2x_png.h @@ -0,0 +1,96 @@ +/* state2_2x.png - 744 bytes */ +static const unsigned char state2_2x_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x73, 0x7a, 0x7a, + 0xf4, 0x00, 0x00, 0x02, 0xaf, 0x49, 0x44, 0x41, + 0x54, 0x58, 0xc3, 0xd5, 0x97, 0x4b, 0x68, 0xd4, + 0x50, 0x14, 0x86, 0x0f, 0x5a, 0x45, 0xf0, 0x55, + 0x17, 0xba, 0x50, 0xd1, 0xa2, 0x1b, 0x77, 0x82, + 0x52, 0xdc, 0x88, 0x16, 0x5c, 0x89, 0x82, 0x6e, + 0x8a, 0xa8, 0x68, 0xb7, 0x55, 0x11, 0x5c, 0xaa, + 0x0b, 0x11, 0xa4, 0xa2, 0x28, 0xe6, 0xe1, 0x30, + 0x38, 0xa3, 0xa5, 0x2a, 0x3e, 0x40, 0x69, 0x71, + 0x54, 0xa4, 0x16, 0xb5, 0x15, 0x7c, 0x80, 0x50, + 0x0a, 0x62, 0xb1, 0x4a, 0xb5, 0x62, 0x5d, 0xd8, + 0xd6, 0xbe, 0x26, 0x33, 0xc9, 0xcc, 0xe4, 0x71, + 0x3c, 0xc9, 0x98, 0x99, 0xc9, 0x98, 0x74, 0x6e, + 0xe6, 0x85, 0x5e, 0xf8, 0x21, 0x90, 0x7b, 0xef, + 0x77, 0xee, 0x39, 0x27, 0x7f, 0x12, 0x80, 0xff, + 0x75, 0x48, 0x1c, 0x34, 0x44, 0x45, 0x08, 0x47, + 0x05, 0x08, 0x91, 0x36, 0x57, 0x15, 0x4e, 0xc0, + 0x26, 0x92, 0x41, 0xc2, 0x3f, 0xd2, 0x25, 0x1e, + 0xf6, 0x54, 0x05, 0x3e, 0x15, 0x84, 0x25, 0x04, + 0x1c, 0xcf, 0x81, 0xdb, 0x1a, 0x9b, 0x08, 0xc1, + 0xe2, 0xca, 0xa7, 0x9e, 0x07, 0xce, 0x05, 0x9e, + 0x16, 0x0f, 0xe7, 0x2a, 0x7b, 0x7a, 0x0e, 0xd6, + 0x10, 0x28, 0xe1, 0x19, 0x80, 0x00, 0xca, 0x64, + 0x00, 0x56, 0x57, 0xb2, 0xf6, 0xf7, 0x67, 0x80, + 0x5b, 0x92, 0x04, 0xb8, 0x55, 0x11, 0xf8, 0x34, + 0x0f, 0x9b, 0xf2, 0x1a, 0xcf, 0x4b, 0x06, 0xcd, + 0xad, 0x2f, 0xff, 0xe9, 0x79, 0x78, 0xc5, 0x00, + 0xb7, 0xf5, 0xb2, 0xdc, 0x8d, 0xd7, 0x98, 0x49, + 0x71, 0xeb, 0x4a, 0x54, 0x5e, 0x34, 0x63, 0xaa, + 0xbf, 0x15, 0xd5, 0x6f, 0x9d, 0xa8, 0x0d, 0x77, + 0xa3, 0xfa, 0x25, 0x82, 0x89, 0x37, 0x27, 0xad, + 0x7b, 0x39, 0x41, 0xec, 0x2a, 0x0b, 0x1c, 0x43, + 0x30, 0x87, 0x36, 0xfb, 0x1c, 0xbb, 0xbe, 0x16, + 0xd5, 0xaf, 0x8f, 0x10, 0x0d, 0x1d, 0xbd, 0x86, + 0xa1, 0xc6, 0x51, 0xe9, 0xdc, 0x67, 0x07, 0x30, + 0x60, 0xae, 0x2d, 0xbd, 0xf6, 0x22, 0x1c, 0xb3, + 0x4e, 0x1e, 0x5e, 0x66, 0x01, 0x0a, 0x0e, 0x43, + 0xc3, 0xf8, 0xdd, 0x0d, 0xe9, 0x6c, 0xf1, 0x70, + 0xb8, 0x24, 0xf8, 0x24, 0x07, 0xb5, 0xb4, 0xd1, + 0x2f, 0x3b, 0xad, 0xc9, 0xde, 0x8b, 0x26, 0x01, + 0xb5, 0xef, 0xcf, 0xa8, 0x0c, 0x87, 0x30, 0xde, + 0xde, 0x80, 0xf1, 0x8e, 0x6d, 0x98, 0x7a, 0x1f, + 0x74, 0xc4, 0x90, 0xfa, 0x70, 0xd5, 0xce, 0xc2, + 0x68, 0x49, 0xe6, 0x44, 0x1b, 0x5c, 0x70, 0x3c, + 0x62, 0xe1, 0xa5, 0x18, 0xbb, 0xb9, 0xce, 0xb5, + 0xf1, 0xf4, 0xd1, 0xbe, 0x4c, 0x00, 0xda, 0x8f, + 0x9e, 0xec, 0x3d, 0x11, 0x5a, 0x8a, 0x3d, 0x7d, + 0x9d, 0x69, 0x2c, 0x4c, 0x5d, 0x2f, 0xce, 0x42, + 0x7d, 0x7a, 0x28, 0x13, 0x80, 0x3a, 0xd8, 0xe1, + 0x30, 0xa7, 0x09, 0x01, 0x56, 0x15, 0xd3, 0xf9, + 0x77, 0x58, 0xe1, 0xc9, 0x3e, 0xce, 0x51, 0x02, + 0xa5, 0xab, 0x29, 0x6f, 0x0e, 0xdc, 0xf0, 0x6b, + 0x3a, 0xf5, 0x2c, 0xa6, 0x23, 0x05, 0xe7, 0xd3, + 0x69, 0xdb, 0x1d, 0x70, 0x75, 0xe8, 0x31, 0x01, + 0x67, 0xe7, 0xcf, 0xd5, 0xa7, 0x04, 0xd8, 0xe8, + 0xc7, 0x74, 0x9e, 0x17, 0x84, 0x5f, 0xa9, 0x45, + 0x6d, 0xa4, 0xf7, 0xef, 0xe6, 0x0b, 0xcc, 0xf5, + 0xc8, 0x14, 0x74, 0xb3, 0xc1, 0x39, 0xd8, 0xcd, + 0x92, 0xfa, 0xd4, 0xc0, 0xed, 0x2c, 0x59, 0x4f, + 0x61, 0xa2, 0xe7, 0x68, 0xe1, 0x72, 0xf1, 0xb0, + 0x73, 0x66, 0xd3, 0x39, 0x0d, 0x35, 0x34, 0xb1, + 0xbf, 0xe0, 0x46, 0x81, 0x79, 0x04, 0x55, 0xb3, + 0x35, 0xa7, 0x47, 0x92, 0xd1, 0xa2, 0x3f, 0x9a, + 0x0c, 0xef, 0xc6, 0x13, 0xe0, 0x08, 0xcb, 0x46, + 0xb1, 0xb6, 0x3a, 0x47, 0xea, 0xa5, 0x6b, 0xcb, + 0x59, 0x03, 0x30, 0xdf, 0x96, 0xcd, 0xae, 0xf0, + 0xb1, 0xf3, 0xb0, 0x90, 0x26, 0xfc, 0x64, 0xda, + 0x24, 0xb8, 0x00, 0xe5, 0x27, 0x8d, 0x19, 0x79, + 0xd6, 0xdd, 0xbd, 0x0c, 0x23, 0xe3, 0x22, 0x2c, + 0x72, 0x33, 0x9d, 0xb3, 0x3e, 0xde, 0x76, 0x25, + 0x89, 0x9e, 0xb2, 0x33, 0x0e, 0xb8, 0x7c, 0x09, + 0x56, 0x50, 0x6a, 0xe2, 0x7e, 0x36, 0x91, 0x23, + 0x3b, 0x30, 0xf9, 0xae, 0x05, 0x95, 0xa7, 0x07, + 0x30, 0x7a, 0xb9, 0xc6, 0x6f, 0x10, 0xb2, 0xc3, + 0x9c, 0x4c, 0xa3, 0xf0, 0x0b, 0xcf, 0x1d, 0x89, + 0xd7, 0x27, 0xfc, 0x67, 0x82, 0x87, 0x36, 0x0b, + 0x1e, 0x13, 0x61, 0xbd, 0x69, 0x14, 0x7e, 0x16, + 0x27, 0xde, 0x9e, 0x72, 0x9a, 0x8f, 0xd3, 0x7a, + 0x59, 0x95, 0x36, 0x27, 0xba, 0x78, 0xe8, 0x77, + 0xb1, 0xfc, 0x60, 0x7b, 0x5e, 0x06, 0x8e, 0x17, + 0xd7, 0x0f, 0x22, 0x44, 0xcc, 0x00, 0xe4, 0x62, + 0x16, 0x67, 0x7a, 0xa0, 0xeb, 0x60, 0x31, 0x3d, + 0x60, 0x4b, 0x32, 0x03, 0x18, 0xac, 0x56, 0xf7, + 0xbb, 0xe8, 0x93, 0xf9, 0xc5, 0xb3, 0x9f, 0xf1, + 0x6b, 0xb7, 0xdc, 0x32, 0x88, 0xbd, 0x37, 0xed, + 0x80, 0x22, 0x6c, 0xb5, 0x7e, 0x34, 0x45, 0xb8, + 0x57, 0x25, 0x85, 0xe9, 0x75, 0xbf, 0xe5, 0x9f, + 0xf8, 0xcb, 0xfe, 0x0d, 0x94, 0xfe, 0x4f, 0x09, + 0x57, 0x69, 0x8e, 0x2a, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, +}; diff --git a/samples/treectrl/state2_png.h b/samples/treectrl/state2_png.h new file mode 100644 index 0000000000..dc76a2b92f --- /dev/null +++ b/samples/treectrl/state2_png.h @@ -0,0 +1,55 @@ +/* state2.png - 417 bytes */ +static const unsigned char state2_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0xf3, 0xff, + 0x61, 0x00, 0x00, 0x01, 0x68, 0x49, 0x44, 0x41, + 0x54, 0x38, 0xcb, 0x9d, 0x91, 0xcb, 0x2b, 0x85, + 0x51, 0x14, 0xc5, 0x97, 0x89, 0xd7, 0xc0, 0xc0, + 0x63, 0x24, 0x13, 0x03, 0x0c, 0xc8, 0x63, 0xce, + 0x5f, 0xc0, 0x40, 0x11, 0x8a, 0x3f, 0x42, 0x21, + 0x19, 0xf9, 0x03, 0xa4, 0x6f, 0x9f, 0x18, 0x18, + 0x78, 0x26, 0x4a, 0x94, 0x4c, 0x64, 0x60, 0xe2, + 0x55, 0x86, 0x66, 0x92, 0x92, 0xae, 0x24, 0xba, + 0x2e, 0xfb, 0x1c, 0xd7, 0xed, 0x5e, 0xdf, 0xb7, + 0x0c, 0xbc, 0xaf, 0xcf, 0xbd, 0xd8, 0xb5, 0x26, + 0xe7, 0xec, 0xf5, 0x3b, 0x6b, 0x9f, 0x0d, 0x64, + 0xa8, 0x98, 0x41, 0xa3, 0x33, 0xa8, 0xc7, 0x7f, + 0xca, 0x1a, 0x74, 0xa8, 0x20, 0x50, 0x81, 0xaf, + 0x82, 0xf6, 0x3f, 0x99, 0x39, 0x8b, 0x7c, 0x2b, + 0x38, 0x57, 0x01, 0x5f, 0x15, 0xe1, 0x38, 0x0a, + 0x7e, 0x0d, 0x50, 0x0f, 0x23, 0x9f, 0xcc, 0x6f, + 0x1a, 0xfa, 0x6d, 0xf4, 0x32, 0x15, 0xdc, 0xd9, + 0x99, 0x0a, 0xc6, 0x37, 0x5a, 0x19, 0xdf, 0xec, + 0xa2, 0x9b, 0xab, 0xa4, 0x0a, 0x62, 0x3a, 0x86, + 0xd2, 0xac, 0x80, 0x7b, 0xc1, 0x64, 0x62, 0x77, + 0x80, 0x0c, 0x7c, 0xbe, 0x97, 0x9f, 0xe4, 0xe3, + 0x56, 0x2f, 0xad, 0x07, 0xc9, 0x16, 0xbd, 0x5a, + 0x05, 0x49, 0xb7, 0x50, 0xc3, 0xc4, 0xfe, 0x30, + 0xdd, 0x52, 0x03, 0x1f, 0x56, 0x5b, 0x18, 0x24, + 0x1d, 0xfd, 0x9b, 0x23, 0xaa, 0x20, 0xa9, 0x13, + 0xa8, 0xfa, 0x19, 0x20, 0x58, 0x4f, 0x9f, 0xdd, + 0xcd, 0x57, 0x91, 0x7e, 0x8a, 0x4f, 0x91, 0xed, + 0x97, 0x33, 0x0f, 0x6b, 0xe1, 0xb3, 0x7b, 0x68, + 0xf9, 0x66, 0x5e, 0x6a, 0x64, 0x10, 0xbf, 0x66, + 0xe0, 0x2e, 0xe9, 0x16, 0x6b, 0x3f, 0xee, 0x0c, + 0x9a, 0xbf, 0xae, 0x8d, 0xc8, 0x51, 0x83, 0x83, + 0x74, 0x80, 0x7f, 0x7f, 0x46, 0xff, 0xf6, 0x98, + 0x76, 0xba, 0x3c, 0x7d, 0x23, 0x87, 0x24, 0x72, + 0x3e, 0x3e, 0xce, 0xa0, 0x27, 0xdd, 0x6c, 0x27, + 0x0b, 0x99, 0x3a, 0x59, 0xe1, 0xe3, 0x56, 0x1f, + 0x43, 0x56, 0x4a, 0x2b, 0xe8, 0x7e, 0x79, 0x7d, + 0x14, 0xb9, 0x2a, 0x38, 0x0d, 0x6b, 0x72, 0x8b, + 0x75, 0xb4, 0x53, 0x25, 0xa1, 0x00, 0x15, 0x9c, + 0xd1, 0x20, 0x0f, 0x6a, 0x30, 0x18, 0xd6, 0xf0, + 0xb0, 0xdc, 0x44, 0x92, 0x7c, 0xba, 0x3a, 0xfc, + 0x09, 0x40, 0x15, 0x0c, 0x40, 0x05, 0x17, 0xa1, + 0x11, 0xa7, 0x8a, 0x99, 0x3a, 0x5d, 0x63, 0x62, + 0xa7, 0x3f, 0x13, 0x20, 0x02, 0xf5, 0xb0, 0x97, + 0xa1, 0x21, 0x9b, 0x76, 0x11, 0x35, 0x28, 0x52, + 0x83, 0x36, 0xeb, 0xa1, 0xf3, 0x2f, 0x52, 0x83, + 0xb6, 0xa8, 0x41, 0xd1, 0x33, 0x03, 0x89, 0xb1, + 0xaf, 0xc7, 0x76, 0x9e, 0x74, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, + 0x82}; diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp index a23b542517..9a8d4c7cc1 100644 --- a/samples/treectrl/treetest.cpp +++ b/samples/treectrl/treetest.cpp @@ -40,11 +40,15 @@ #include "icon4.xpm" #include "icon5.xpm" -#include "state1.xpm" -#include "state2.xpm" -#include "state3.xpm" -#include "state4.xpm" -#include "state5.xpm" +// Please note that these headers were generated from the original PNG icons +// made by Aleksandr Zyrianov and licensed under CC-BY-SA 4.0 and so are +// covered by this licence and not wxWindows licence itself. +#include "state0_png.h" +#include "state0_2x_png.h" +#include "state1_png.h" +#include "state1_2x_png.h" +#include "state2_png.h" +#include "state2_2x_png.h" #include "unchecked.xpm" #include "checked.xpm" @@ -192,6 +196,10 @@ bool MyApp::OnInit() if ( !wxApp::OnInit() ) return false; + // We use PNG images here, so we could just add PNG image handler but this + // is simpler. + wxInitAllImageHandlers(); + // Create the main frame window MyFrame *frame = new MyFrame(); @@ -1041,28 +1049,33 @@ void MyTreeCtrl::CreateImages(int size) void MyTreeCtrl::CreateStateImages() { - std::vector icons; + std::vector images; if (m_alternateStates) { - icons.push_back(wxIcon(state1_xpm)); // yellow - icons.push_back(wxIcon(state2_xpm)); // green - icons.push_back(wxIcon(state3_xpm)); // red - icons.push_back(wxIcon(state4_xpm)); // blue - icons.push_back(wxIcon(state5_xpm)); // black + // Macro similar to wxBITMAP_BUNDLE_2 but not using resources even + // under the platforms supporting them. + #define myBITMAP_BUNDLE_FROM_DATA_2(name) \ + wxBitmapBundle::FromBitmaps(wxBITMAP_PNG_FROM_DATA(name), \ + wxBITMAP_PNG_FROM_DATA(name##_2x)) + + images.push_back(myBITMAP_BUNDLE_FROM_DATA_2(state0)); + images.push_back(myBITMAP_BUNDLE_FROM_DATA_2(state1)); + images.push_back(myBITMAP_BUNDLE_FROM_DATA_2(state2)); + + #undef myBITMAP_BUNDLE_FROM_DATA_2 } else { + std::vector icons; icons.push_back(wxIcon(unchecked_xpm)); icons.push_back(wxIcon(checked_xpm)); - } - std::vector images; - - const wxSize iconSize(icons[0].GetWidth(), icons[0].GetHeight()); - for ( const wxIcon& icon : icons ) - { - images.push_back(wxBitmapBundle::FromImpl(new FixedSizeImpl(iconSize, icon))); + const wxSize iconSize(icons[0].GetWidth(), icons[0].GetHeight()); + for ( const wxIcon& icon : icons ) + { + images.push_back(wxBitmapBundle::FromImpl(new FixedSizeImpl(iconSize, icon))); + } } SetStateImages(images); From f9a22962e011d043f8d5c635c347e5c31f32ff22 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 26 Oct 2023 01:46:00 +0200 Subject: [PATCH 08/18] Add wxTreeCtrl::GetStateImageCount() and HasStateImages() Add these functions for consistency with SetStateImages() and to avoid using GetStateImageList() in the treectrl sample, which can now use GetStateImageCount() instead. --- include/wx/treectrl.h | 5 +++++ interface/wx/treectrl.h | 28 ++++++++++++++++++++++++++++ samples/treectrl/treetest.cpp | 2 +- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/include/wx/treectrl.h b/include/wx/treectrl.h index d72655227e..a0579011d9 100644 --- a/include/wx/treectrl.h +++ b/include/wx/treectrl.h @@ -62,6 +62,11 @@ public: // (for example, checked/unchecked). virtual void SetStateImages(const wxVector& images) = 0; + // Simple accessors similar to the inherited from wxWithImages + // HasImages() and GetImageCount() for normal images. + bool HasStateImages() const { return m_imagesState.HasImages(); } + int GetStateImageCount() const { return m_imagesState.GetImageCount(); } + // These functions parallel {Set,Get,Assign}ImageList() methods // inherited from wxWithImages, but correspond to SetStateImages(). // As with the other functions using wxImageList, they still work but diff --git a/interface/wx/treectrl.h b/interface/wx/treectrl.h index 5fafa5efd8..30fa4fb572 100644 --- a/interface/wx/treectrl.h +++ b/interface/wx/treectrl.h @@ -699,12 +699,38 @@ public: */ virtual size_t GetSelections(wxArrayTreeItemIds& selection) const; + /** + Returns the number of state images used by the control. + + Returns the number of images passed to the last call to + SetStateImages() or 0 if it had been never called. + + @see HasImages() + + @since 3.3.0 + */ + int GetStateImageCount() const; + /** Returns the state image list (from which application-defined state images are taken). + + @see HasStateImages(), GetStateImageCount() */ wxImageList* GetStateImageList() const; + /** + Returns true if the control uses any state images. + + This is equivalent to comparing GetStateImageCount() return value with + 0 but more clear. + + @see SetStateImages(), GetStateImageCount() + + @since 3.3.0 + */ + bool HasStateImages() const; + /** Calculates which (if any) item is under the given @a point, returning the tree item id at this point plus extra information @a flags. @a flags @@ -994,6 +1020,8 @@ public: resolutions for each state. If the vector is empty, no state images are shown. + @see HasStateImages(), GetStateImageCount() + @since 3.3.0 */ virtual void SetStateImages(const wxVector& images); diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp index 9a8d4c7cc1..85439caf2c 100644 --- a/samples/treectrl/treetest.cpp +++ b/samples/treectrl/treetest.cpp @@ -1288,7 +1288,7 @@ void MyTreeCtrl::DoToggleState(const wxTreeItemId& item) srand (time(nullptr)); do { - nState = rand() % GetStateImageList()->GetImageCount(); + nState = rand() % GetStateImageCount(); } while (nState == state); SetItemState(item, nState); From a4051c6c2a699e108c9ae18e81baddad3ba6839b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 29 Oct 2023 02:36:02 +0200 Subject: [PATCH 09/18] Don't use GetStateImageList() in wxGenericTreeCtrl implementation Use wxWithImages functions directly. No real changes. --- src/generic/treectlg.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index 2271b0d8f0..61aa747c57 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -755,7 +755,7 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest(const wxPoint& point, theCtrl->m_imagesState.HasImages() ) { int state_h; - theCtrl->GetStateImageList()->GetSize(GetState(), + theCtrl->m_imagesState.GetImageLogicalSize(theCtrl, GetState(), state_w, state_h); } @@ -890,7 +890,7 @@ wxGenericTreeItem::DoCalculateSize(wxGenericTreeCtrl* control, int state = GetState(); if ( state != wxTREE_ITEMSTATE_NONE && control->m_imagesState.HasImages() ) { - control->GetStateImageList()->GetSize(state, state_w, state_h); + control->m_imagesState.GetImageLogicalSize(control, state, state_w, state_h); if ( image_w != 0 ) state_w += MARGIN_BETWEEN_STATE_AND_IMAGE; else @@ -2569,7 +2569,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) { if ( m_imagesState.HasImages() ) { - GetStateImageList()->GetSize(state, state_w, state_h); + m_imagesState.GetImageLogicalSize(this, state, state_w, state_h); if ( image_w != 0 ) state_w += MARGIN_BETWEEN_STATE_AND_IMAGE; else @@ -3482,7 +3482,7 @@ bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item, if ( state != wxTREE_ITEMSTATE_NONE && m_imagesState.HasImages() ) { int state_h; - GetStateImageList()->GetSize( state, state_w, state_h ); + m_imagesState.GetImageLogicalSize( this, state, state_w, state_h ); if ( image_w != 0 ) state_w += MARGIN_BETWEEN_STATE_AND_IMAGE; else From 260a109db646e34ea60d4272668cd58f5c47ea26 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 3 Nov 2023 01:27:57 +0100 Subject: [PATCH 10/18] Remove outdated comment about making wxImageList ref counting This hasn't happened since 26 years, so don't pretend it's going to happen now that this class is semi-deprecated. --- include/wx/msw/imaglist.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/wx/msw/imaglist.h b/include/wx/msw/imaglist.h index 8ebd8a61ce..19736b3eb3 100644 --- a/include/wx/msw/imaglist.h +++ b/include/wx/msw/imaglist.h @@ -12,10 +12,6 @@ #include "wx/bitmap.h" -// Eventually we'll make this a reference-counted wxGDIObject. For -// now, the app must take care of ownership issues. That is, the -// image lists must be explicitly deleted after the control(s) that uses them -// is (are) deleted, or when the app exits. class WXDLLIMPEXP_CORE wxImageList : public wxObject { public: From 0003ac6873c754126375295dd0052017df6fb367 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 3 Nov 2023 01:36:00 +0100 Subject: [PATCH 11/18] Replace wxImageList::Init() with member initializers in wxMSW No real change, just initialize members in their declarations and get rid of now unnecessary Init(). --- include/wx/msw/imaglist.h | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/include/wx/msw/imaglist.h b/include/wx/msw/imaglist.h index 19736b3eb3..3c3b8f90f4 100644 --- a/include/wx/msw/imaglist.h +++ b/include/wx/msw/imaglist.h @@ -19,7 +19,7 @@ public: * Public interface */ - wxImageList() { Init(); } + wxImageList() = default; // Creates an image list. // Specify the width and height of the images in the list, @@ -27,7 +27,6 @@ public: // from icons), and the initial size of the list. wxImageList(int width, int height, bool mask = true, int initialCount = 1) { - Init(); Create(width, height, mask, initialCount); } virtual ~wxImageList(); @@ -191,7 +190,7 @@ public: WXHIMAGELIST GetHIMAGELIST() const { return m_hImageList; } protected: - WXHIMAGELIST m_hImageList; + WXHIMAGELIST m_hImageList = nullptr; wxSize m_size; private: @@ -203,13 +202,7 @@ private: void GetImageListBitmaps(wxMSWBitmaps& bitmaps, const wxBitmap& bitmap, const wxBitmap& mask); - bool m_useMask; - - void Init() - { - m_hImageList = nullptr; - m_useMask = false; - } + bool m_useMask = false; wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxImageList); }; From 3f971f52c1ab284d69ea35e6dd9337c195fbd60a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 3 Nov 2023 01:37:55 +0100 Subject: [PATCH 12/18] Add using declaration for ctors to generic wxImageList Instead of explicitly forwarding the ctors to the base class manually, just use them. --- include/wx/generic/imaglist.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/wx/generic/imaglist.h b/include/wx/generic/imaglist.h index 2560418e41..d35cfec0ab 100644 --- a/include/wx/generic/imaglist.h +++ b/include/wx/generic/imaglist.h @@ -81,12 +81,7 @@ class WXDLLIMPEXP_CORE wxImageList: public wxGenericImageList wxDECLARE_DYNAMIC_CLASS(wxImageList); public: - wxImageList() {} - - wxImageList( int width, int height, bool mask = true, int initialCount = 1 ) - : wxGenericImageList(width, height, mask, initialCount) - { - } + using wxGenericImageList::wxGenericImageList; }; #endif // !wxHAS_NATIVE_IMAGELIST From 0d4792cc2d75f0bc8c80b6db48d6162a295cab05 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 3 Nov 2023 01:49:34 +0100 Subject: [PATCH 13/18] Refactor wxImageList classes to use wxImageListBase This ensures that the native MSW and generic implementations provide the same API by forcing them to implement the same pure virtual functions. --- include/wx/generic/imaglist.h | 42 ++++++++++++---------------- include/wx/imaglist.h | 52 +++++++++++++++++++++++++++++++++++ include/wx/msw/imaglist.h | 38 ++++++++++++------------- 3 files changed, 87 insertions(+), 45 deletions(-) diff --git a/include/wx/generic/imaglist.h b/include/wx/generic/imaglist.h index d35cfec0ab..a72bac36d7 100644 --- a/include/wx/generic/imaglist.h +++ b/include/wx/generic/imaglist.h @@ -10,42 +10,38 @@ #ifndef _WX_IMAGLISTG_H_ #define _WX_IMAGLISTG_H_ -#include "wx/bitmap.h" #include "wx/gdicmn.h" #include "wx/vector.h" -class WXDLLIMPEXP_FWD_CORE wxDC; -class WXDLLIMPEXP_FWD_CORE wxIcon; -class WXDLLIMPEXP_FWD_CORE wxColour; - - -class WXDLLIMPEXP_CORE wxGenericImageList: public wxObject +class WXDLLIMPEXP_CORE wxGenericImageList : public wxImageListBase { public: wxGenericImageList(); wxGenericImageList( int width, int height, bool mask = true, int initialCount = 1 ); virtual ~wxGenericImageList(); bool Create( int width, int height, bool mask = true, int initialCount = 1 ); - void Destroy(); + virtual void Destroy() override; - virtual int GetImageCount() const; - virtual bool GetSize( int index, int &width, int &height ) const; - virtual wxSize GetSize() const { return m_size; } + virtual int GetImageCount() const override; + virtual bool GetSize( int index, int &width, int &height ) const override; - int Add( const wxBitmap& bitmap ); - int Add( const wxBitmap& bitmap, const wxBitmap& mask ); - int Add( const wxBitmap& bitmap, const wxColour& maskColour ); - wxBitmap GetBitmap(int index) const; - wxIcon GetIcon(int index) const; - bool Replace( int index, + using wxImageListBase::GetSize; + + virtual int Add( const wxBitmap& bitmap ) override; + virtual int Add( const wxBitmap& bitmap, const wxBitmap& mask ) override; + virtual int Add( const wxBitmap& bitmap, const wxColour& maskColour ) override; + + virtual wxBitmap GetBitmap(int index) const override; + virtual wxIcon GetIcon(int index) const override; + virtual bool Replace( int index, const wxBitmap& bitmap, - const wxBitmap& mask = wxNullBitmap ); - bool Remove( int index ); - bool RemoveAll(); + const wxBitmap& mask = wxNullBitmap ) override; + virtual bool Remove( int index ) override; + virtual bool RemoveAll() override; virtual bool Draw(int index, wxDC& dc, int x, int y, int flags = wxIMAGELIST_DRAW_NORMAL, - bool solidBackground = false); + bool solidBackground = false) override; #if WXWIN_COMPATIBILITY_3_0 wxDEPRECATED_MSG("Don't use this overload: it's not portable and does nothing") @@ -61,10 +57,6 @@ private: wxBitmap GetImageListBitmap(const wxBitmap& bitmap) const; wxVector m_images; - bool m_useMask; - - // Size of a single bitmap in the list. - wxSize m_size; wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxGenericImageList); }; diff --git a/include/wx/imaglist.h b/include/wx/imaglist.h index 76954f68b6..4a5d78121f 100644 --- a/include/wx/imaglist.h +++ b/include/wx/imaglist.h @@ -12,6 +12,13 @@ #include "wx/defs.h" +#include "wx/bitmap.h" + +class WXDLLIMPEXP_FWD_CORE wxDC; +class WXDLLIMPEXP_FWD_CORE wxIcon; +class WXDLLIMPEXP_FWD_CORE wxColour; + + /* * wxImageList is used for wxListCtrl, wxTreeCtrl. These controls refer to * images for their items by an index into an image list. @@ -40,6 +47,51 @@ enum #define wxIMAGELIST_DRAW_SELECTED 0x0004 #define wxIMAGELIST_DRAW_FOCUSED 0x0008 +// Define the interface of platform-specific wxImageList class. +class wxImageListBase : public wxObject +{ +public: + /* + This class should provide default ctor as well as the following ctor: + + wxImageList(int width, int height, bool mask = true, int initialCount = 1) + + and Create() member function taking the same parameters and returning + bool. + */ + + virtual void Destroy() = 0; + + // Returns the size the image list was created with. + wxSize GetSize() const { return m_size; } + + virtual int GetImageCount() const = 0; + virtual bool GetSize(int index, int &width, int &height) const = 0; + + virtual int Add(const wxBitmap& bitmap) = 0; + virtual int Add(const wxBitmap& bitmap, const wxBitmap& mask) = 0; + virtual int Add(const wxBitmap& bitmap, const wxColour& maskColour) = 0; + + virtual bool Replace(int index, + const wxBitmap& bitmap, + const wxBitmap& mask = wxNullBitmap) = 0; + virtual bool Remove(int index) = 0; + virtual bool RemoveAll() = 0; + + virtual bool Draw(int index, wxDC& dc, int x, int y, + int flags = wxIMAGELIST_DRAW_NORMAL, + bool solidBackground = false) = 0; + + virtual wxBitmap GetBitmap(int index) const = 0; + virtual wxIcon GetIcon(int index) const = 0; + +protected: + // Size of a single bitmap in the list in logical pixels. + wxSize m_size; + + bool m_useMask = false; +}; + #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) #include "wx/msw/imaglist.h" #define wxHAS_NATIVE_IMAGELIST diff --git a/include/wx/msw/imaglist.h b/include/wx/msw/imaglist.h index 3c3b8f90f4..17d6060646 100644 --- a/include/wx/msw/imaglist.h +++ b/include/wx/msw/imaglist.h @@ -10,9 +10,7 @@ #ifndef _WX_IMAGLIST_H_ #define _WX_IMAGLIST_H_ -#include "wx/bitmap.h" - -class WXDLLIMPEXP_CORE wxImageList : public wxObject +class WXDLLIMPEXP_CORE wxImageList : public wxImageListBase { public: /* @@ -36,13 +34,12 @@ public: //////////////////////////////////////////////////////////////////////////// // Returns the number of images in the image list. - int GetImageCount() const; + virtual int GetImageCount() const override; // Returns the size (same for all images) of the images in the list - bool GetSize(int index, int &width, int &height) const; + virtual bool GetSize(int index, int &width, int &height) const override; - // Returns the overall size - wxSize GetSize() const { return m_size; } + using wxImageListBase::GetSize; // Operations //////////////////////////////////////////////////////////////////////////// @@ -54,17 +51,21 @@ public: bool Create(int width, int height, bool mask = true, int initialNumber = 1); // Destroys the image list, Create() may then be called again later. - void Destroy(); + virtual void Destroy() override; // Adds a bitmap, and optionally a mask bitmap. // Note that wxImageList creates *new* bitmaps, so you may delete // 'bitmap' and 'mask' after calling Add. - int Add(const wxBitmap& bitmap, const wxBitmap& mask = wxNullBitmap); + virtual int Add(const wxBitmap& bitmap, const wxBitmap& mask) override; + virtual int Add(const wxBitmap& bitmap) override + { + return Add(bitmap, wxNullBitmap); + } // Adds a bitmap, using the specified colour to create the mask bitmap // Note that wxImageList creates *new* bitmaps, so you may delete // 'bitmap' after calling Add. - int Add(const wxBitmap& bitmap, const wxColour& maskColour); + virtual int Add(const wxBitmap& bitmap, const wxColour& maskColour) override; // Adds a bitmap and mask from an icon. int Add(const wxIcon& icon); @@ -72,31 +73,31 @@ public: // Replaces a bitmap, optionally passing a mask bitmap. // Note that wxImageList creates new bitmaps, so you may delete // 'bitmap' and 'mask' after calling Replace. - bool Replace(int index, const wxBitmap& bitmap, const wxBitmap& mask = wxNullBitmap); + virtual bool Replace(int index, const wxBitmap& bitmap, const wxBitmap& mask = wxNullBitmap) override; // Replaces a bitmap and mask from an icon. // You can delete 'icon' after calling Replace. bool Replace(int index, const wxIcon& icon); // Removes the image at the given index. - bool Remove(int index); + virtual bool Remove(int index) override; // Remove all images - bool RemoveAll(); + virtual bool RemoveAll() override; // Draws the given image on a dc at the specified position. // If 'solidBackground' is true, Draw sets the image list background // colour to the background colour of the wxDC, to speed up // drawing by eliminating masked drawing where possible. - bool Draw(int index, wxDC& dc, int x, int y, + virtual bool Draw(int index, wxDC& dc, int x, int y, int flags = wxIMAGELIST_DRAW_NORMAL, - bool solidBackground = false); + bool solidBackground = false) override; // Get a bitmap - wxBitmap GetBitmap(int index) const; + virtual wxBitmap GetBitmap(int index) const override; // Get an icon - wxIcon GetIcon(int index) const; + virtual wxIcon GetIcon(int index) const override; // TODO: miscellaneous functionality /* @@ -191,7 +192,6 @@ public: protected: WXHIMAGELIST m_hImageList = nullptr; - wxSize m_size; private: // Private helper used by GetImageListBitmaps(). @@ -202,8 +202,6 @@ private: void GetImageListBitmaps(wxMSWBitmaps& bitmaps, const wxBitmap& bitmap, const wxBitmap& mask); - bool m_useMask = false; - wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxImageList); }; From 53b4f4ddf23285cba3fc3243632eae1b047b9831 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 3 Nov 2023 02:17:33 +0100 Subject: [PATCH 14/18] Use physical size in wxImageList This seems to be the only way to fix using this class, which is fundamentally incompatible with high DPI support, with bitmaps of different logical but identical physical sizes. By using physical size we ensure that the code chopping up the provided bitmap in multiple images doesn't do it with the bitmap having the same physical size but a different logical size from all the other bitmaps. And, conceptually, logical size of the bitmaps in it really shouldn't matter to the image list as it doesn't have a scaling factor and so can't do anything useful with the logical size. Moreover, we can't add wxImageList::SetScaleFactor() neither because this class is, by design, supposed to be shareable between different controls which may use different scale factors, so it doesn't make sense to speak of the scale factor of the image list itself. This undoes the changes made in the generic implementation back in c374eefd34 (Fold wxOSX-specific wxImageList into generic version, 2018-10-30) and also eb52e86553 (Take into account scale factor of images added to wxImageList, 2021-04-03). Also update a couple of places where wxImageList is still used to use physical sizes. Unfortunately some others can't be easily fixed, e.g. global wxFileIconsTable would have to be completely rewritten. Finally, add a unit test checking that things work as expected now: previously the size of 24x24 bitmap in the image list containing (scaled) 32x32 bitmaps would be 21x21 due to sub-bitmap extraction kicking in. Closes #23994. --- docs/changes.txt | 5 +++++ include/wx/imaglist.h | 2 +- include/wx/withimages.h | 2 +- interface/wx/imaglist.h | 25 +++++++++++++------------ src/common/bmpbndl.cpp | 6 +----- src/generic/imaglist.cpp | 15 ++++++++++----- src/generic/logg.cpp | 8 +++++--- src/html/helpwnd.cpp | 11 +++++++---- tests/graphics/bmpbundle.cpp | 32 ++++++++++++++++++++++++++++++++ 9 files changed, 75 insertions(+), 31 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 624767ba25..e20e6429ac 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -77,6 +77,11 @@ Changes in behaviour not resulting in compilation errors called any longer by default, you need to explicitly enable 3.0 compatibility or change your code to override the newer overload, taking a wxWindow pointer. +- wxImageList size is now expressed in physical pixels, i.e. its size must be + the same as the size of bitmaps added to it, in pixels. This is inconvenient + but should be viewed as a hint not to use wxImageList (but wxBitmapBundle) + in the applications supporting high DPI. + Changes in behaviour which may result in build errors ----------------------------------------------------- diff --git a/include/wx/imaglist.h b/include/wx/imaglist.h index 4a5d78121f..e57df6cac0 100644 --- a/include/wx/imaglist.h +++ b/include/wx/imaglist.h @@ -86,7 +86,7 @@ public: virtual wxIcon GetIcon(int index) const = 0; protected: - // Size of a single bitmap in the list in logical pixels. + // Size of a single bitmap in the list in physical pixels. wxSize m_size; bool m_useMask = false; diff --git a/include/wx/withimages.h b/include/wx/withimages.h index 12fe439586..c3f556f388 100644 --- a/include/wx/withimages.h +++ b/include/wx/withimages.h @@ -143,7 +143,7 @@ public: else if ( m_imageList ) { // All images in the image list are of the same size. - size = m_imageList->GetSize(); + size = window->FromPhys(m_imageList->GetSize()); } } diff --git a/interface/wx/imaglist.h b/interface/wx/imaglist.h index 720690813b..885d5b6778 100644 --- a/interface/wx/imaglist.h +++ b/interface/wx/imaglist.h @@ -59,7 +59,8 @@ public: Constructor specifying the image size, whether image masks should be created, and the initial size of the list. - Note that the size is specified in logical pixels. + Note that the size is specified in physical pixels and must correspond + to the size of bitmaps, in pixels, that will be added to this list. @param width Width of the images in the list. @@ -83,10 +84,10 @@ public: /** Adds a new image or images using a bitmap and optional mask bitmap. - The logical size of the bitmap should be the same as the size specified - when constructing wxImageList. If the logical width of the bitmap is - greater than the image list width, bitmap is split into smaller images - of the required width. + The physical size of the bitmap should be the same as the size specified + when constructing wxImageList. If the width of the bitmap is greater + than the image list width, bitmap is split into smaller images of the + required width, allowing to add multiple images from a single bitmap. @param bitmap Bitmap representing the opaque areas of the image. @@ -101,10 +102,10 @@ public: /** Adds a new image or images using a bitmap and mask colour. - The logical size of the bitmap should be the same as the size specified - when constructing wxImageList. If the logical width of the bitmap is - greater than the image list width, bitmap is split into smaller images - of the required width. + The physical size of the bitmap should be the same as the size specified + when constructing wxImageList. If the width of the bitmap is greater + than the image list width, bitmap is split into smaller images of the + required width, allowing to add multiple images from a single bitmap. @param bitmap Bitmap representing the opaque areas of the image. @@ -118,7 +119,7 @@ public: /** Adds a new image using an icon. - The logical size of the icon should be the same as the size specified + The physical size of the icon should be the same as the size specified when constructing wxImageList. @param icon @@ -201,9 +202,9 @@ public: @param index currently unused, should be 0 @param width - receives the width of the images in the list + receives the width of the images in the list in pixels @param height - receives the height of the images in the list + receives the height of the images in the list in pixels @return @true if the function succeeded, @false if it failed (for example, if the image list was not yet initialized). diff --git a/src/common/bmpbndl.cpp b/src/common/bmpbndl.cpp index b108a67281..fbe985c45b 100644 --- a/src/common/bmpbndl.cpp +++ b/src/common/bmpbndl.cpp @@ -675,11 +675,7 @@ wxBitmapBundle::CreateImageList(wxWindow* win, wxCHECK_MSG( win, nullptr, "must have a valid window" ); wxCHECK_MSG( !bundles.empty(), nullptr, "should have some images" ); - wxSize size = GetConsensusSizeFor(win, bundles); - - // wxImageList wants the logical size for the platforms where logical and - // physical pixels are different. - size /= win->GetContentScaleFactor(); + const wxSize size = GetConsensusSizeFor(win, bundles); wxImageList* const iml = new wxImageList(size.x, size.y); diff --git a/src/generic/imaglist.cpp b/src/generic/imaglist.cpp index 7b37e4a457..2a768cd12f 100644 --- a/src/generic/imaglist.cpp +++ b/src/generic/imaglist.cpp @@ -83,7 +83,7 @@ wxBitmap wxGenericImageList::GetImageListBitmap(const wxBitmap& bitmap) const // Ensure image size is the same as the size of the images on the image list. wxBitmap bmpResized; - const wxSize sz = bmp.GetLogicalSize(); + const wxSize sz = bmp.GetSize(); if ( sz.x == m_size.x && sz.y == m_size.y ) { bmpResized = bmp; @@ -125,14 +125,19 @@ int wxGenericImageList::Add( const wxBitmap &bitmap ) // Cannot add image to invalid list wxCHECK_MSG( m_size != wxSize(0, 0), -1, "Invalid image list" ); - // We use the logical size here as image list images size is specified in - // logical pixels, just as window coordinates and sizes are. - const wxSize bitmapSize = bitmap.GetLogicalSize(); + const wxSize bitmapSize = bitmap.GetSize(); // There is a special case: a bitmap may contain more than one image, // in which case we're supposed to chop it in parts, just as Windows // ImageList_Add() does. - if ( bitmapSize.x == m_size.x ) + // + // However we don't apply this special case to bitmaps with a scale factor + // different from 1: their actual physical size could be the same as ours + // for all we know (we don't have a scale factor here and wxImageList API + // prevents it from having one), so leave them alone. This is clearly a + // hack but OTOH nobody uses multi-image bitmaps with a scale factor and it + // avoids problems when using scaled bitmaps in the image list, see #23994. + if ( bitmapSize.x == m_size.x || bitmap.GetScaleFactor() != 1.0 ) { m_images.push_back(GetImageListBitmap(bitmap)); } diff --git a/src/generic/logg.cpp b/src/generic/logg.cpp index db68977aa1..fd526a2444 100644 --- a/src/generic/logg.cpp +++ b/src/generic/logg.cpp @@ -800,8 +800,10 @@ void wxLogDialog::CreateDetailsControls(wxWindow *parent) m_listctrl->InsertColumn(1, wxT("Time")); // prepare the imagelist - static const int ICON_SIZE = 16; - wxImageList *imageList = new wxImageList(ICON_SIZE, ICON_SIZE); + wxSize iconSize(16, 16); + iconSize *= parent->GetDPIScaleFactor(); + + wxImageList *imageList = new wxImageList(iconSize.x, iconSize.y); // order should be the same as in the switch below! static wxString const icons[] = @@ -816,7 +818,7 @@ void wxLogDialog::CreateDetailsControls(wxWindow *parent) for ( size_t icon = 0; icon < WXSIZEOF(icons); icon++ ) { wxBitmap bmp = wxArtProvider::GetBitmap(icons[icon], wxART_MESSAGE_BOX, - wxSize(ICON_SIZE, ICON_SIZE)); + iconSize); // This may very well fail if there are insufficient colours available. // Degrade gracefully. diff --git a/src/html/helpwnd.cpp b/src/html/helpwnd.cpp index de859d6a11..07bb8bc493 100644 --- a/src/html/helpwnd.cpp +++ b/src/html/helpwnd.cpp @@ -447,16 +447,19 @@ bool wxHtmlHelpWindow::Create(wxWindow* parent, wxWindowID id, #endif ); - wxImageList *ContentsImageList = new wxImageList(16, 16); + wxSize iconSize(16, 16); + iconSize *= GetDPIScaleFactor(); + + wxImageList *ContentsImageList = new wxImageList(iconSize.x, iconSize.y); ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_BOOK, wxART_HELP_BROWSER, - wxSize(16, 16))); + iconSize)); ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_FOLDER, wxART_HELP_BROWSER, - wxSize(16, 16))); + iconSize)); ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_PAGE, wxART_HELP_BROWSER, - wxSize(16, 16))); + iconSize)); m_ContentsBox->AssignImageList(ContentsImageList); diff --git a/tests/graphics/bmpbundle.cpp b/tests/graphics/bmpbundle.cpp index bc890fb9e2..92163013c9 100644 --- a/tests/graphics/bmpbundle.cpp +++ b/tests/graphics/bmpbundle.cpp @@ -16,6 +16,7 @@ #include "wx/artprov.h" #include "wx/dcmemory.h" +#include "wx/imaglist.h" #include "asserthelper.h" @@ -470,6 +471,37 @@ TEST_CASE("BitmapBundle::Scale", "[bmpbundle][scale]") CHECK( b.GetDefaultSize() == wxSize(8, 8) ); } +TEST_CASE("BitmapBundle::ImageList", "[bmpbundle][imagelist]") +{ + wxVector images; + images.push_back(wxBitmapBundle::FromBitmaps(wxBitmap(16, 16), wxBitmap(32, 32))); + images.push_back(wxBitmapBundle::FromBitmap(wxBitmap(24, 24))); + images.push_back(wxBitmapBundle::FromBitmaps(wxBitmap(16, 16), wxBitmap(32, 32))); + + // There are 2 bundles with preferred size of 32x32, so they should win. + const wxSize size = wxBitmapBundle::GetConsensusSizeFor(2.0, images); + CHECK( size == wxSize(32, 32) ); + + wxImageList iml(size.x, size.y); + for ( const auto& bundle : images ) + { + wxBitmap bmp = bundle.GetBitmap(size); + REQUIRE( bmp.IsOk() ); + CHECK( bmp.GetSize() == size ); + REQUIRE( iml.Add(bmp) != -1 ); + } + + CHECK( iml.GetBitmap(0).GetSize() == size ); +#ifdef wxHAS_DPI_INDEPENDENT_PIXELS + CHECK( iml.GetBitmap(0).GetScaleFactor() == 2 ); +#endif + + CHECK( iml.GetBitmap(1).GetSize() == size ); +#ifdef wxHAS_DPI_INDEPENDENT_PIXELS + CHECK( iml.GetBitmap(1).GetScaleFactor() == Approx(1.3333333333) ); +#endif +} + #endif // ports with scaled bitmaps support TEST_CASE("BitmapBundle::GetConsensusSize", "[bmpbundle]") From 089bf467a99a6607c977fbc35c21ac5d335378d3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 6 Nov 2023 22:05:25 +0100 Subject: [PATCH 15/18] Allow passing const wxWindow* to more wxBitmapBundle methods Take const pointer in GetConsensusSizeFor(), which only uses this parameter to get the DPI scale factor, and CreateImageList(), using it only to pass it on to GetConsensusSizeFor(). No real changes. --- include/wx/bmpbndl.h | 4 ++-- src/common/bmpbndl.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/wx/bmpbndl.h b/include/wx/bmpbndl.h index b8e140d0d0..7b60fd9d18 100644 --- a/include/wx/bmpbndl.h +++ b/include/wx/bmpbndl.h @@ -162,12 +162,12 @@ public: wxNODISCARD static wxSize GetConsensusSizeFor(double scale, const wxVector& bundles); wxNODISCARD static wxSize - GetConsensusSizeFor(wxWindow* win, const wxVector& bundles); + GetConsensusSizeFor(const wxWindow* win, const wxVector& bundles); // Create wxImageList and fill it with the images from the given bundles in // the sizes appropriate for the DPI scaling used for the specified window. wxNODISCARD static wxImageList* - CreateImageList(wxWindow* win, const wxVector& bundles); + CreateImageList(const wxWindow* win, const wxVector& bundles); private: typedef wxObjectDataPtr wxBitmapBundleImplPtr; diff --git a/src/common/bmpbndl.cpp b/src/common/bmpbndl.cpp index fbe985c45b..af1e419cc3 100644 --- a/src/common/bmpbndl.cpp +++ b/src/common/bmpbndl.cpp @@ -619,7 +619,7 @@ void RecordSizePref(SizePrefs& prefs, const wxSize& size) /* static */ wxSize -wxBitmapBundle::GetConsensusSizeFor(wxWindow* win, +wxBitmapBundle::GetConsensusSizeFor(const wxWindow* win, const wxVector& bundles) { return GetConsensusSizeFor(win->GetDPIScaleFactor(), bundles); @@ -669,7 +669,7 @@ wxBitmapBundle::GetConsensusSizeFor(double scale, /* static */ wxImageList* -wxBitmapBundle::CreateImageList(wxWindow* win, +wxBitmapBundle::CreateImageList(const wxWindow* win, const wxVector& bundles) { wxCHECK_MSG( win, nullptr, "must have a valid window" ); From 2d6817b0a8799f428d64207ab1d8bf030a8b4e36 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 6 Nov 2023 22:08:51 +0100 Subject: [PATCH 16/18] Add a function to save a bitmap callable from debugger This allows to dump a bitmap to a disk file in order to examine it outside of the debugger when debugging. Note that at least MSVC and gdb are not smart enough to allow calling wxBitmap::SaveFile() directly. --- src/common/bmpbase.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/bmpbase.cpp b/src/common/bmpbase.cpp index aa1608011b..ee9feda5d1 100644 --- a/src/common/bmpbase.cpp +++ b/src/common/bmpbase.cpp @@ -25,6 +25,11 @@ #include "wx/mstream.h" #endif +extern bool wxDumpBitmap(const wxBitmap& bitmap, const char* path) +{ + return bitmap.SaveFile(path, wxBITMAP_TYPE_BMP); +} + // ---------------------------------------------------------------------------- // wxVariant support // ---------------------------------------------------------------------------- From baa56732fc8387ae352cc2ed9c5ee4d641f5044f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 7 Nov 2023 00:03:56 +0100 Subject: [PATCH 17/18] Allow to get the size of all images in wxWithImages This simplifies wxGenericTreeCtrl code but doesn't change much yet. --- include/wx/withimages.h | 19 +++++++++++++++++++ src/generic/treectlg.cpp | 39 +++++++++++++++------------------------ 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/include/wx/withimages.h b/include/wx/withimages.h index c3f556f388..97a7c3c123 100644 --- a/include/wx/withimages.h +++ b/include/wx/withimages.h @@ -129,6 +129,25 @@ public: return m_imageList; } + // Return logical bitmap size that should be used for all images. + // + // Returns (0, 0) if we don't have any images. + wxSize GetImageLogicalSize(const wxWindow* window) const + { + wxSize size; + + // Prefer to use the image list here if we have it because we must have + // already decided for the best size to use when creating it. + // + // Otherwise we need to compute the best size here ourselves. + if ( m_imageList ) + size = m_imageList->GetSize(); + else if ( !m_images.empty() ) + size = wxBitmapBundle::GetConsensusSizeFor(window, m_images); + + return window->FromPhys(size); + } + // Return logical size of the image to use or (0, 0) if there are none. wxSize GetImageLogicalSize(const wxWindow* window, int iconIndex) const { diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index e3dcd34ea0..a27d785699 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -744,9 +744,7 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest(const wxPoint& point, // assuming every image (normal and selected) has the same size! if ( (GetImage() != NO_IMAGE) && theCtrl->HasImages() ) { - int image_h; - theCtrl->GetImageLogicalSize(theCtrl, GetImage(), - image_w, image_h); + image_w = theCtrl->GetImageLogicalSize(theCtrl).x; } int state_w = -1; @@ -879,11 +877,11 @@ wxGenericTreeItem::DoCalculateSize(wxGenericTreeCtrl* control, int text_h = m_heightText + 2; int image_h = 0, image_w = 0; - int image = GetCurrentImage(); - if ( image != NO_IMAGE && control->HasImages() ) + if ( GetCurrentImage() != NO_IMAGE && control->HasImages() ) { - control->GetImageLogicalSize(control, image, image_w, image_h); - image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT; + const wxSize imageSize = control->GetImageLogicalSize(control); + image_h = imageSize.y; + image_w = imageSize.x + MARGIN_BETWEEN_IMAGE_AND_TEXT; } int state_h = 0, state_w = 0; @@ -2410,15 +2408,7 @@ void wxGenericTreeCtrl::CalculateLineHeight() if ( HasImages() ) { // Calculate a m_lineHeight value from the normal Image sizes. - // May be toggle off. Then wxGenericTreeCtrl will spread when - // necessary (which might look ugly). - int n = GetImageCount(); - for (int i = 0; i < n ; i++) - { - int width = 0, height = 0; - GetImageLogicalSize(this, i, width, height); - if (height > m_lineHeight) m_lineHeight = height; - } + m_lineHeight = GetImageLogicalSize(this).y; } if ( m_imagesState.HasImages() ) @@ -2459,7 +2449,10 @@ void wxGenericTreeCtrl::OnImagesChanged() { if ( HasImages() ) { - // We call it solely for the side effect of updating the image list. + // We call it solely for the side effect of updating the image list, + // which may be used by the application code using this class, even if + // we don't use it ourselves, but it also has an important side effect + // of ensuring that we can always get the size to use for the images. GetUpdatedImageListFor(this); UpdateAfterImageListChange(); @@ -2547,8 +2540,9 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc) { if ( HasImages() ) { - GetImageLogicalSize(this, image, image_w, image_h); - image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT; + const wxSize imageSize = GetImageLogicalSize(this); + image_h = imageSize.y; + image_w = imageSize.x + MARGIN_BETWEEN_IMAGE_AND_TEXT; } else { @@ -3462,12 +3456,9 @@ bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item, if ( textOnly ) { int image_w = 0; - int image = ((wxGenericTreeItem*) item.m_pItem)->GetCurrentImage(); - if ( image != NO_IMAGE && HasImages() ) + if ( i->GetCurrentImage() != NO_IMAGE && HasImages() ) { - int image_h; - GetImageLogicalSize( this, image, image_w, image_h ); - image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT; + image_w = GetImageLogicalSize(this).x + MARGIN_BETWEEN_IMAGE_AND_TEXT; } int state_w = 0; From 7aef62071526b9983da7b30fb4655a930560b0b0 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 7 Nov 2023 00:19:25 +0100 Subject: [PATCH 18/18] Fix using bitmaps of different dimensions in wxWithImages Although this is not ideal, it may still happen and sometimes can even give acceptable results, e.g. using (16, 32) and (24) bitmap bundles can actuall works nicely enough at x2 scaling if 16px bitmaps are upscaled by the factor of 3. To make this work, request the explicit physical bitmap size and override its scale factor to ensure the resulting bitmap has the correct logical size. --- include/wx/withimages.h | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/include/wx/withimages.h b/include/wx/withimages.h index 97a7c3c123..5c8efd34e2 100644 --- a/include/wx/withimages.h +++ b/include/wx/withimages.h @@ -129,10 +129,10 @@ public: return m_imageList; } - // Return logical bitmap size that should be used for all images. + // Return physical bitmap size that should be used for all images. // // Returns (0, 0) if we don't have any images. - wxSize GetImageLogicalSize(const wxWindow* window) const + wxSize GetImageSize(const wxWindow* window) const { wxSize size; @@ -145,7 +145,15 @@ public: else if ( !m_images.empty() ) size = wxBitmapBundle::GetConsensusSizeFor(window, m_images); - return window->FromPhys(size); + return size; + } + + // Return logical bitmap size that should be used for all images. + // + // Returns (0, 0) if we don't have any images. + wxSize GetImageLogicalSize(const wxWindow* window) const + { + return window->FromPhys(GetImageSize(window)); } // Return logical size of the image to use or (0, 0) if there are none. @@ -190,7 +198,23 @@ public: { if ( !m_images.empty() ) { - bitmap = m_images.at(iconIndex).GetBitmapFor(window); + // Note that it's not enough to just use GetBitmapFor() here to + // choose the bitmap of the size most appropriate for the window + // DPI as we need it to be of the same size as the other images + // used in the same control, so we have to use fixed size here. + const wxSize size = GetImageSize(window); + + bitmap = m_images.at(iconIndex).GetBitmap(size); + + // We also may need to adjust the scale factor to ensure that + // this bitmap takes the same space as all the others, as + // GetBitmap() may set it wrong in this case. + const wxSize logicalSize = window->FromPhys(size); + + if ( bitmap.GetLogicalSize() != logicalSize ) + { + bitmap.SetScaleFactor(size.y / logicalSize.y); + } } else if ( m_imageList ) {