Merge branches 'tree-state-bmpbundle' and 'imglist-scalefactor'

Refactor wxImageList and convert it to use physical pixels and
add support for high DPI state images wxTreeCtrl using the new
wxImageList.

See #24000, #24033.
This commit is contained in:
Vadim Zeitlin 2023-11-17 01:03:27 +01:00
commit ef4fecc186
29 changed files with 829 additions and 222 deletions

View file

@ -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 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. 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 Changes in behaviour which may result in build errors
----------------------------------------------------- -----------------------------------------------------

View file

@ -162,12 +162,12 @@ public:
wxNODISCARD static wxSize wxNODISCARD static wxSize
GetConsensusSizeFor(double scale, const wxVector<wxBitmapBundle>& bundles); GetConsensusSizeFor(double scale, const wxVector<wxBitmapBundle>& bundles);
wxNODISCARD static wxSize wxNODISCARD static wxSize
GetConsensusSizeFor(wxWindow* win, const wxVector<wxBitmapBundle>& bundles); GetConsensusSizeFor(const wxWindow* win, const wxVector<wxBitmapBundle>& bundles);
// Create wxImageList and fill it with the images from the given bundles in // 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. // the sizes appropriate for the DPI scaling used for the specified window.
wxNODISCARD static wxImageList* wxNODISCARD static wxImageList*
CreateImageList(wxWindow* win, const wxVector<wxBitmapBundle>& bundles); CreateImageList(const wxWindow* win, const wxVector<wxBitmapBundle>& bundles);
private: private:
typedef wxObjectDataPtr<wxBitmapBundleImpl> wxBitmapBundleImplPtr; typedef wxObjectDataPtr<wxBitmapBundleImpl> wxBitmapBundleImplPtr;

View file

@ -10,42 +10,38 @@
#ifndef _WX_IMAGLISTG_H_ #ifndef _WX_IMAGLISTG_H_
#define _WX_IMAGLISTG_H_ #define _WX_IMAGLISTG_H_
#include "wx/bitmap.h"
#include "wx/gdicmn.h" #include "wx/gdicmn.h"
#include "wx/vector.h" #include "wx/vector.h"
class WXDLLIMPEXP_FWD_CORE wxDC; class WXDLLIMPEXP_CORE wxGenericImageList : public wxImageListBase
class WXDLLIMPEXP_FWD_CORE wxIcon;
class WXDLLIMPEXP_FWD_CORE wxColour;
class WXDLLIMPEXP_CORE wxGenericImageList: public wxObject
{ {
public: public:
wxGenericImageList(); wxGenericImageList();
wxGenericImageList( int width, int height, bool mask = true, int initialCount = 1 ); wxGenericImageList( int width, int height, bool mask = true, int initialCount = 1 );
virtual ~wxGenericImageList(); virtual ~wxGenericImageList();
bool Create( int width, int height, bool mask = true, int initialCount = 1 ); bool Create( int width, int height, bool mask = true, int initialCount = 1 );
void Destroy(); virtual void Destroy() override;
virtual int GetImageCount() const; virtual int GetImageCount() const override;
virtual bool GetSize( int index, int &width, int &height ) const; virtual bool GetSize( int index, int &width, int &height ) const override;
virtual wxSize GetSize() const { return m_size; }
int Add( const wxBitmap& bitmap ); using wxImageListBase::GetSize;
int Add( const wxBitmap& bitmap, const wxBitmap& mask );
int Add( const wxBitmap& bitmap, const wxColour& maskColour ); virtual int Add( const wxBitmap& bitmap ) override;
wxBitmap GetBitmap(int index) const; virtual int Add( const wxBitmap& bitmap, const wxBitmap& mask ) override;
wxIcon GetIcon(int index) const; virtual int Add( const wxBitmap& bitmap, const wxColour& maskColour ) override;
bool Replace( int index,
virtual wxBitmap GetBitmap(int index) const override;
virtual wxIcon GetIcon(int index) const override;
virtual bool Replace( int index,
const wxBitmap& bitmap, const wxBitmap& bitmap,
const wxBitmap& mask = wxNullBitmap ); const wxBitmap& mask = wxNullBitmap ) override;
bool Remove( int index ); virtual bool Remove( int index ) override;
bool RemoveAll(); virtual bool RemoveAll() override;
virtual 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, int flags = wxIMAGELIST_DRAW_NORMAL,
bool solidBackground = false); bool solidBackground = false) override;
#if WXWIN_COMPATIBILITY_3_0 #if WXWIN_COMPATIBILITY_3_0
wxDEPRECATED_MSG("Don't use this overload: it's not portable and does nothing") 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; wxBitmap GetImageListBitmap(const wxBitmap& bitmap) const;
wxVector<wxBitmap> m_images; wxVector<wxBitmap> m_images;
bool m_useMask;
// Size of a single bitmap in the list.
wxSize m_size;
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxGenericImageList); wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxGenericImageList);
}; };
@ -81,12 +73,7 @@ class WXDLLIMPEXP_CORE wxImageList: public wxGenericImageList
wxDECLARE_DYNAMIC_CLASS(wxImageList); wxDECLARE_DYNAMIC_CLASS(wxImageList);
public: public:
wxImageList() {} using wxGenericImageList::wxGenericImageList;
wxImageList( int width, int height, bool mask = true, int initialCount = 1 )
: wxGenericImageList(width, height, mask, initialCount)
{
}
}; };
#endif // !wxHAS_NATIVE_IMAGELIST #endif // !wxHAS_NATIVE_IMAGELIST

View file

@ -71,6 +71,7 @@ public:
virtual unsigned int GetIndent() const override { return m_indent; } virtual unsigned int GetIndent() const override { return m_indent; }
virtual void SetIndent(unsigned int indent) override; virtual void SetIndent(unsigned int indent) override;
virtual void SetStateImages(const wxVector<wxBitmapBundle>& images) override;
virtual void SetImageList(wxImageList *imageList) override; virtual void SetImageList(wxImageList *imageList) override;
virtual void SetStateImageList(wxImageList *imageList) override; virtual void SetStateImageList(wxImageList *imageList) override;

View file

@ -12,6 +12,13 @@
#include "wx/defs.h" #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 * wxImageList is used for wxListCtrl, wxTreeCtrl. These controls refer to
* images for their items by an index into an image list. * images for their items by an index into an image list.
@ -40,6 +47,51 @@ enum
#define wxIMAGELIST_DRAW_SELECTED 0x0004 #define wxIMAGELIST_DRAW_SELECTED 0x0004
#define wxIMAGELIST_DRAW_FOCUSED 0x0008 #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 physical pixels.
wxSize m_size;
bool m_useMask = false;
};
#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) #if defined(__WXMSW__) && !defined(__WXUNIVERSAL__)
#include "wx/msw/imaglist.h" #include "wx/msw/imaglist.h"
#define wxHAS_NATIVE_IMAGELIST #define wxHAS_NATIVE_IMAGELIST

View file

@ -10,20 +10,14 @@
#ifndef _WX_IMAGLIST_H_ #ifndef _WX_IMAGLIST_H_
#define _WX_IMAGLIST_H_ #define _WX_IMAGLIST_H_
#include "wx/bitmap.h" class WXDLLIMPEXP_CORE wxImageList : public wxImageListBase
// 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: public:
/* /*
* Public interface * Public interface
*/ */
wxImageList() { Init(); } wxImageList() = default;
// Creates an image list. // Creates an image list.
// Specify the width and height of the images in the list, // Specify the width and height of the images in the list,
@ -31,7 +25,6 @@ public:
// from icons), and the initial size of the list. // from icons), and the initial size of the list.
wxImageList(int width, int height, bool mask = true, int initialCount = 1) wxImageList(int width, int height, bool mask = true, int initialCount = 1)
{ {
Init();
Create(width, height, mask, initialCount); Create(width, height, mask, initialCount);
} }
virtual ~wxImageList(); virtual ~wxImageList();
@ -41,13 +34,12 @@ public:
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Returns the number of images in the image list. // 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 // 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 using wxImageListBase::GetSize;
wxSize GetSize() const { return m_size; }
// Operations // Operations
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -59,17 +51,21 @@ public:
bool Create(int width, int height, bool mask = true, int initialNumber = 1); bool Create(int width, int height, bool mask = true, int initialNumber = 1);
// Destroys the image list, Create() may then be called again later. // 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. // Adds a bitmap, and optionally a mask bitmap.
// Note that wxImageList creates *new* bitmaps, so you may delete // Note that wxImageList creates *new* bitmaps, so you may delete
// 'bitmap' and 'mask' after calling Add. // '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 // Adds a bitmap, using the specified colour to create the mask bitmap
// Note that wxImageList creates *new* bitmaps, so you may delete // Note that wxImageList creates *new* bitmaps, so you may delete
// 'bitmap' after calling Add. // '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. // Adds a bitmap and mask from an icon.
int Add(const wxIcon& icon); int Add(const wxIcon& icon);
@ -77,31 +73,31 @@ public:
// Replaces a bitmap, optionally passing a mask bitmap. // Replaces a bitmap, optionally passing a mask bitmap.
// Note that wxImageList creates new bitmaps, so you may delete // Note that wxImageList creates new bitmaps, so you may delete
// 'bitmap' and 'mask' after calling Replace. // '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. // Replaces a bitmap and mask from an icon.
// You can delete 'icon' after calling Replace. // You can delete 'icon' after calling Replace.
bool Replace(int index, const wxIcon& icon); bool Replace(int index, const wxIcon& icon);
// Removes the image at the given index. // Removes the image at the given index.
bool Remove(int index); virtual bool Remove(int index) override;
// Remove all images // Remove all images
bool RemoveAll(); virtual bool RemoveAll() override;
// Draws the given image on a dc at the specified position. // Draws the given image on a dc at the specified position.
// If 'solidBackground' is true, Draw sets the image list background // If 'solidBackground' is true, Draw sets the image list background
// colour to the background colour of the wxDC, to speed up // colour to the background colour of the wxDC, to speed up
// drawing by eliminating masked drawing where possible. // 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, int flags = wxIMAGELIST_DRAW_NORMAL,
bool solidBackground = false); bool solidBackground = false) override;
// Get a bitmap // Get a bitmap
wxBitmap GetBitmap(int index) const; virtual wxBitmap GetBitmap(int index) const override;
// Get an icon // Get an icon
wxIcon GetIcon(int index) const; virtual wxIcon GetIcon(int index) const override;
// TODO: miscellaneous functionality // TODO: miscellaneous functionality
/* /*
@ -195,8 +191,7 @@ public:
WXHIMAGELIST GetHIMAGELIST() const { return m_hImageList; } WXHIMAGELIST GetHIMAGELIST() const { return m_hImageList; }
protected: protected:
WXHIMAGELIST m_hImageList; WXHIMAGELIST m_hImageList = nullptr;
wxSize m_size;
private: private:
// Private helper used by GetImageListBitmaps(). // Private helper used by GetImageListBitmaps().
@ -207,14 +202,6 @@ private:
void GetImageListBitmaps(wxMSWBitmaps& bitmaps, void GetImageListBitmaps(wxMSWBitmaps& bitmaps,
const wxBitmap& bitmap, const wxBitmap& mask); const wxBitmap& bitmap, const wxBitmap& mask);
bool m_useMask;
void Init()
{
m_hImageList = nullptr;
m_useMask = false;
}
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxImageList); wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxImageList);
}; };

View file

@ -72,6 +72,8 @@ public:
virtual unsigned int GetIndent() const override; virtual unsigned int GetIndent() const override;
virtual void SetIndent(unsigned int indent) override; virtual void SetIndent(unsigned int indent) override;
virtual void SetStateImages(const wxVector<wxBitmapBundle>& images) override;
virtual void SetImageList(wxImageList *imageList) override; virtual void SetImageList(wxImageList *imageList) override;
virtual void SetStateImageList(wxImageList *imageList) override; virtual void SetStateImageList(wxImageList *imageList) override;

View file

@ -35,6 +35,8 @@ public:
virtual unsigned int GetIndent() const override; virtual unsigned int GetIndent() const override;
virtual void SetIndent(unsigned int indent) override; virtual void SetIndent(unsigned int indent) override;
virtual void SetStateImages(const wxVector<wxBitmapBundle>& images) override;
virtual void SetImageList(wxImageList *imageList) override; virtual void SetImageList(wxImageList *imageList) override;
virtual void SetStateImageList(wxImageList *imageList) override; virtual void SetStateImageList(wxImageList *imageList) override;

View file

@ -56,10 +56,22 @@ public:
unsigned int GetSpacing() const { return m_spacing; } unsigned int GetSpacing() const { return m_spacing; }
void SetSpacing(unsigned int spacing) { m_spacing = spacing; } void SetSpacing(unsigned int spacing) { m_spacing = spacing; }
// In addition to {Set,Get,Assign}ImageList() methods inherited from // In addition to SetImages() inherited from wxWithImages, this class
// wxWithImages, this control has similar functions for the state image // also provides SetStateImages() function which can be used to set the
// list that can be used to show a state icon corresponding to an // images showing an icon corresponding to an app-defined item state
// app-defined item state (for example, checked/unchecked). // (for example, checked/unchecked).
virtual void SetStateImages(const wxVector<wxBitmapBundle>& 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
// don't allow to define high resolution icons for high DPI screens, so
// SetStateImages() above should be preferred.
wxImageList *GetStateImageList() const wxImageList *GetStateImageList() const
{ {
return m_imagesState.GetImageList(); return m_imagesState.GetImageList();

View file

@ -76,6 +76,15 @@ public:
{ {
m_images = images; 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(); OnImagesChanged();
} }
@ -129,6 +138,33 @@ public:
return m_imageList; return m_imageList;
} }
// Return physical bitmap size that should be used for all images.
//
// Returns (0, 0) if we don't have any images.
wxSize GetImageSize(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 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. // Return logical size of the image to use or (0, 0) if there are none.
wxSize GetImageLogicalSize(const wxWindow* window, int iconIndex) const wxSize GetImageLogicalSize(const wxWindow* window, int iconIndex) const
{ {
@ -143,7 +179,7 @@ public:
else if ( m_imageList ) else if ( m_imageList )
{ {
// All images in the image list are of the same size. // All images in the image list are of the same size.
size = m_imageList->GetSize(); size = window->FromPhys(m_imageList->GetSize());
} }
} }
@ -171,7 +207,23 @@ public:
{ {
if ( !m_images.empty() ) 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 ) else if ( m_imageList )
{ {

View file

@ -59,7 +59,8 @@ public:
Constructor specifying the image size, whether image masks should be created, Constructor specifying the image size, whether image masks should be created,
and the initial size of the list. 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 @param width
Width of the images in the list. 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. 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 The physical size of the bitmap should be the same as the size specified
when constructing wxImageList. If the logical width of the bitmap is when constructing wxImageList. If the width of the bitmap is greater
greater than the image list width, bitmap is split into smaller images than the image list width, bitmap is split into smaller images of the
of the required width. required width, allowing to add multiple images from a single bitmap.
@param bitmap @param bitmap
Bitmap representing the opaque areas of the image. 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. 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 The physical size of the bitmap should be the same as the size specified
when constructing wxImageList. If the logical width of the bitmap is when constructing wxImageList. If the width of the bitmap is greater
greater than the image list width, bitmap is split into smaller images than the image list width, bitmap is split into smaller images of the
of the required width. required width, allowing to add multiple images from a single bitmap.
@param bitmap @param bitmap
Bitmap representing the opaque areas of the image. Bitmap representing the opaque areas of the image.
@ -118,7 +119,7 @@ public:
/** /**
Adds a new image using an icon. 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. when constructing wxImageList.
@param icon @param icon
@ -201,9 +202,9 @@ public:
@param index @param index
currently unused, should be 0 currently unused, should be 0
@param width @param width
receives the width of the images in the list receives the width of the images in the list in pixels
@param height @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 @return @true if the function succeeded, @false if it failed
(for example, if the image list was not yet initialized). (for example, if the image list was not yet initialized).

View file

@ -30,9 +30,11 @@
In addition to normal images, handled with the methods mentioned above, In addition to normal images, handled with the methods mentioned above,
wxTreeCtrl also provides optional state images that may be used to indicate 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 some additional state of the item, e.g. checked or unchecked status. These
images can be set using SetStateImageList() and AssignStateImageList() images can be set using SetStateImages() (preferred, as they allow to
functions that behave in the same way as the corresponding methods of specify high resolution versions of the state images too) or legacy
wxWithImages. 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 Finally, in the generic version of this control (wxGenericTreeCtrl), also
provides SetButtonsImageList() and AssignButtonsImageList(), which can be provides SetButtonsImageList() and AssignButtonsImageList(), which can be
@ -281,6 +283,8 @@ public:
automatically deleted by wxTreeCtrl as appropriate (i.e. it takes automatically deleted by wxTreeCtrl as appropriate (i.e. it takes
ownership of the list). ownership of the list).
@note Prefer using SetStateImages() in the new code.
@see SetStateImageList(). @see SetStateImageList().
*/ */
void AssignStateImageList(wxImageList* imageList); void AssignStateImageList(wxImageList* imageList);
@ -695,12 +699,38 @@ public:
*/ */
virtual size_t GetSelections(wxArrayTreeItemIds& selection) const; 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 Returns the state image list (from which application-defined state
images are taken). images are taken).
@see HasStateImages(), GetStateImageCount()
*/ */
wxImageList* GetStateImageList() const; 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 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 the tree item id at this point plus extra information @a flags. @a flags
@ -976,10 +1006,26 @@ public:
by @ref wxTreeCtrl "wxTreeCtrl"'s destructor, you must delete it by @ref wxTreeCtrl "wxTreeCtrl"'s destructor, you must delete it
yourself. yourself.
@see AssignStateImageList(). @note Prefer using SetStateImages() in the new code.
@see AssignStateImageList()
*/ */
virtual void SetStateImageList(wxImageList* imageList); 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.
@see HasStateImages(), GetStateImageCount()
@since 3.3.0
*/
virtual void SetStateImages(const wxVector<wxBitmapBundle>& images);
/** /**
Sets the mode flags associated with the display of the tree control. The Sets the mode flags associated with the display of the tree control. The
new mode takes effect immediately. new mode takes effect immediately.

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -40,11 +40,15 @@
#include "icon4.xpm" #include "icon4.xpm"
#include "icon5.xpm" #include "icon5.xpm"
#include "state1.xpm" // Please note that these headers were generated from the original PNG icons
#include "state2.xpm" // made by Aleksandr Zyrianov and licensed under CC-BY-SA 4.0 and so are
#include "state3.xpm" // covered by this licence and not wxWindows licence itself.
#include "state4.xpm" #include "state0_png.h"
#include "state5.xpm" #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 "unchecked.xpm"
#include "checked.xpm" #include "checked.xpm"
@ -192,8 +196,12 @@ bool MyApp::OnInit()
if ( !wxApp::OnInit() ) if ( !wxApp::OnInit() )
return false; 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 // Create the main frame window
MyFrame *frame = new MyFrame("wxTreeCtrl Test", 50, 50, 450, 600); MyFrame *frame = new MyFrame();
// Show the frame // Show the frame
frame->Show(true); frame->Show(true);
@ -203,8 +211,9 @@ bool MyApp::OnInit()
// My frame constructor // My frame constructor
MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h) MyFrame::MyFrame()
: wxFrame(nullptr, wxID_ANY, title, wxPoint(x, y), wxSize(w, h)), : wxFrame(nullptr, wxID_ANY, "wxTreeCtrl test",
wxDefaultPosition, FromDIP(wxSize(450, 600), nullptr)),
m_treeCtrl(nullptr) m_treeCtrl(nullptr)
#if wxUSE_LOG #if wxUSE_LOG
, m_textCtrl(nullptr) , m_textCtrl(nullptr)
@ -703,12 +712,12 @@ void MyFrame::OnToggleStates(wxCommandEvent& WXUNUSED(event))
{ {
if ( wxGetApp().ShowStates() ) if ( wxGetApp().ShowStates() )
{ {
m_treeCtrl->CreateStateImageList(true); m_treeCtrl->SetStateImages({});
wxGetApp().SetShowStates(false); wxGetApp().SetShowStates(false);
} }
else else
{ {
m_treeCtrl->CreateStateImageList(false); m_treeCtrl->CreateStateImages();
wxGetApp().SetShowStates(true); wxGetApp().SetShowStates(true);
} }
} }
@ -731,7 +740,7 @@ void MyFrame::OnToggleAlternateStates(wxCommandEvent& WXUNUSED(event))
bool alternateStates = m_treeCtrl->AlternateStates(); bool alternateStates = m_treeCtrl->AlternateStates();
m_treeCtrl->SetAlternateStates(!alternateStates); m_treeCtrl->SetAlternateStates(!alternateStates);
m_treeCtrl->CreateStateImageList(); m_treeCtrl->CreateStateImages();
// normal states < alternate states // normal states < alternate states
// so we must reset broken states // so we must reset broken states
@ -949,12 +958,48 @@ MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id,
m_reverseSort = false; m_reverseSort = false;
CreateImages(16); CreateImages(16);
CreateStateImageList(); CreateStateImages();
// Add some items to the tree // Add some items to the tree
AddTestItemsToTree(NUM_CHILDREN_PER_LEVEL, NUM_LEVELS); 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) void MyTreeCtrl::CreateImages(int size)
{ {
if ( size == -1 ) if ( size == -1 )
@ -994,39 +1039,6 @@ void MyTreeCtrl::CreateImages(int size)
// DPI, to ensure they are of the desired size. // DPI, to ensure they are of the desired size.
wxVector<wxBitmapBundle> images; wxVector<wxBitmapBundle> 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++ ) for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
{ {
images.push_back(wxBitmapBundle::FromImpl(new FixedSizeImpl(iconSize, icons[i]))); images.push_back(wxBitmapBundle::FromImpl(new FixedSizeImpl(iconSize, icons[i])));
@ -1035,52 +1047,38 @@ void MyTreeCtrl::CreateImages(int size)
SetImages(images); SetImages(images);
} }
void MyTreeCtrl::CreateStateImageList(bool del) void MyTreeCtrl::CreateStateImages()
{ {
if ( del ) std::vector<wxBitmapBundle> images;
{
SetStateImageList(nullptr);
return;
}
wxImageList *states;
wxBusyCursor wait;
if (m_alternateStates) if (m_alternateStates)
{ {
wxIcon icons[5]; // Macro similar to wxBITMAP_BUNDLE_2 but not using resources even
icons[0] = wxIcon(state1_xpm); // yellow // under the platforms supporting them.
icons[1] = wxIcon(state2_xpm); // green #define myBITMAP_BUNDLE_FROM_DATA_2(name) \
icons[2] = wxIcon(state3_xpm); // red wxBitmapBundle::FromBitmaps(wxBITMAP_PNG_FROM_DATA(name), \
icons[3] = wxIcon(state4_xpm); // blue wxBITMAP_PNG_FROM_DATA(name##_2x))
icons[4] = wxIcon(state5_xpm); // black
int width = icons[0].GetWidth(), images.push_back(myBITMAP_BUNDLE_FROM_DATA_2(state0));
height = icons[0].GetHeight(); images.push_back(myBITMAP_BUNDLE_FROM_DATA_2(state1));
images.push_back(myBITMAP_BUNDLE_FROM_DATA_2(state2));
// Make a state image list containing small icons #undef myBITMAP_BUNDLE_FROM_DATA_2
states = new wxImageList(width, height, true);
for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
states->Add(icons[i]);
} }
else else
{ {
wxIcon icons[2]; std::vector<wxIcon> icons;
icons[0] = wxIcon(unchecked_xpm); icons.push_back(wxIcon(unchecked_xpm));
icons[1] = wxIcon(checked_xpm); icons.push_back(wxIcon(checked_xpm));
int width = icons[0].GetWidth(), const wxSize iconSize(icons[0].GetWidth(), icons[0].GetHeight());
height = icons[0].GetHeight(); for ( const wxIcon& icon : icons )
{
// Make an state image list containing small icons images.push_back(wxBitmapBundle::FromImpl(new FixedSizeImpl(iconSize, icon)));
states = new wxImageList(width, height, true); }
for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
states->Add(icons[i]);
} }
AssignStateImageList(states); SetStateImages(images);
} }
void MyTreeCtrl::CreateButtonsImageList(int size) void MyTreeCtrl::CreateButtonsImageList(int size)
@ -1290,7 +1288,7 @@ void MyTreeCtrl::DoToggleState(const wxTreeItemId& item)
srand (time(nullptr)); srand (time(nullptr));
do { do {
nState = rand() % GetStateImageList()->GetImageCount(); nState = rand() % GetStateImageCount();
} while (nState == state); } while (nState == state);
SetItemState(item, nState); SetItemState(item, nState);

View file

@ -113,7 +113,7 @@ public:
void CreateImages(int size); void CreateImages(int size);
void CreateButtonsImageList(int size = 11); void CreateButtonsImageList(int size = 11);
void CreateStateImageList(bool del = false); void CreateStateImages();
void AddTestItemsToTree(size_t numChildren, size_t depth); void AddTestItemsToTree(size_t numChildren, size_t depth);
@ -181,7 +181,7 @@ class MyFrame: public wxFrame
{ {
public: public:
// ctor and dtor // ctor and dtor
MyFrame(const wxString& title, int x, int y, int w, int h); MyFrame();
virtual ~MyFrame(); virtual ~MyFrame();
// menu callbacks // menu callbacks

View file

@ -25,6 +25,11 @@
#include "wx/mstream.h" #include "wx/mstream.h"
#endif #endif
extern bool wxDumpBitmap(const wxBitmap& bitmap, const char* path)
{
return bitmap.SaveFile(path, wxBITMAP_TYPE_BMP);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxVariant support // wxVariant support
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View file

@ -619,7 +619,7 @@ void RecordSizePref(SizePrefs& prefs, const wxSize& size)
/* static */ /* static */
wxSize wxSize
wxBitmapBundle::GetConsensusSizeFor(wxWindow* win, wxBitmapBundle::GetConsensusSizeFor(const wxWindow* win,
const wxVector<wxBitmapBundle>& bundles) const wxVector<wxBitmapBundle>& bundles)
{ {
return GetConsensusSizeFor(win->GetDPIScaleFactor(), bundles); return GetConsensusSizeFor(win->GetDPIScaleFactor(), bundles);
@ -669,17 +669,13 @@ wxBitmapBundle::GetConsensusSizeFor(double scale,
/* static */ /* static */
wxImageList* wxImageList*
wxBitmapBundle::CreateImageList(wxWindow* win, wxBitmapBundle::CreateImageList(const wxWindow* win,
const wxVector<wxBitmapBundle>& bundles) const wxVector<wxBitmapBundle>& bundles)
{ {
wxCHECK_MSG( win, nullptr, "must have a valid window" ); wxCHECK_MSG( win, nullptr, "must have a valid window" );
wxCHECK_MSG( !bundles.empty(), nullptr, "should have some images" ); wxCHECK_MSG( !bundles.empty(), nullptr, "should have some images" );
wxSize size = GetConsensusSizeFor(win, bundles); const wxSize size = GetConsensusSizeFor(win, bundles);
// wxImageList wants the logical size for the platforms where logical and
// physical pixels are different.
size /= win->GetContentScaleFactor();
wxImageList* const iml = new wxImageList(size.x, size.y); wxImageList* const iml = new wxImageList(size.x, size.y);

View file

@ -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. // Ensure image size is the same as the size of the images on the image list.
wxBitmap bmpResized; wxBitmap bmpResized;
const wxSize sz = bmp.GetLogicalSize(); const wxSize sz = bmp.GetSize();
if ( sz.x == m_size.x && sz.y == m_size.y ) if ( sz.x == m_size.x && sz.y == m_size.y )
{ {
bmpResized = bmp; bmpResized = bmp;
@ -125,14 +125,19 @@ int wxGenericImageList::Add( const wxBitmap &bitmap )
// Cannot add image to invalid list // Cannot add image to invalid list
wxCHECK_MSG( m_size != wxSize(0, 0), -1, "Invalid image 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 const wxSize bitmapSize = bitmap.GetSize();
// logical pixels, just as window coordinates and sizes are.
const wxSize bitmapSize = bitmap.GetLogicalSize();
// There is a special case: a bitmap may contain more than one image, // 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 // in which case we're supposed to chop it in parts, just as Windows
// ImageList_Add() does. // 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)); m_images.push_back(GetImageListBitmap(bitmap));
} }

View file

@ -800,8 +800,10 @@ void wxLogDialog::CreateDetailsControls(wxWindow *parent)
m_listctrl->InsertColumn(1, wxT("Time")); m_listctrl->InsertColumn(1, wxT("Time"));
// prepare the imagelist // prepare the imagelist
static const int ICON_SIZE = 16; wxSize iconSize(16, 16);
wxImageList *imageList = new wxImageList(ICON_SIZE, ICON_SIZE); iconSize *= parent->GetDPIScaleFactor();
wxImageList *imageList = new wxImageList(iconSize.x, iconSize.y);
// order should be the same as in the switch below! // order should be the same as in the switch below!
static wxString const icons[] = static wxString const icons[] =
@ -816,7 +818,7 @@ void wxLogDialog::CreateDetailsControls(wxWindow *parent)
for ( size_t icon = 0; icon < WXSIZEOF(icons); icon++ ) for ( size_t icon = 0; icon < WXSIZEOF(icons); icon++ )
{ {
wxBitmap bmp = wxArtProvider::GetBitmap(icons[icon], wxART_MESSAGE_BOX, 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. // This may very well fail if there are insufficient colours available.
// Degrade gracefully. // Degrade gracefully.

View file

@ -744,9 +744,7 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest(const wxPoint& point,
// assuming every image (normal and selected) has the same size! // assuming every image (normal and selected) has the same size!
if ( (GetImage() != NO_IMAGE) && theCtrl->HasImages() ) if ( (GetImage() != NO_IMAGE) && theCtrl->HasImages() )
{ {
int image_h; image_w = theCtrl->GetImageLogicalSize(theCtrl).x;
theCtrl->GetImageLogicalSize(theCtrl, GetImage(),
image_w, image_h);
} }
int state_w = -1; int state_w = -1;
@ -755,7 +753,7 @@ wxGenericTreeItem *wxGenericTreeItem::HitTest(const wxPoint& point,
theCtrl->m_imagesState.HasImages() ) theCtrl->m_imagesState.HasImages() )
{ {
int state_h; int state_h;
theCtrl->GetStateImageList()->GetSize(GetState(), theCtrl->m_imagesState.GetImageLogicalSize(theCtrl, GetState(),
state_w, state_h); state_w, state_h);
} }
@ -879,18 +877,18 @@ wxGenericTreeItem::DoCalculateSize(wxGenericTreeCtrl* control,
int text_h = m_heightText + 2; int text_h = m_heightText + 2;
int image_h = 0, image_w = 0; int image_h = 0, image_w = 0;
int image = GetCurrentImage(); if ( GetCurrentImage() != NO_IMAGE && control->HasImages() )
if ( image != NO_IMAGE && control->HasImages() )
{ {
control->GetImageLogicalSize(control, image, image_w, image_h); const wxSize imageSize = control->GetImageLogicalSize(control);
image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT; image_h = imageSize.y;
image_w = imageSize.x + MARGIN_BETWEEN_IMAGE_AND_TEXT;
} }
int state_h = 0, state_w = 0; int state_h = 0, state_w = 0;
int state = GetState(); int state = GetState();
if ( state != wxTREE_ITEMSTATE_NONE && control->m_imagesState.HasImages() ) 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 ) if ( image_w != 0 )
state_w += MARGIN_BETWEEN_STATE_AND_IMAGE; state_w += MARGIN_BETWEEN_STATE_AND_IMAGE;
else else
@ -2410,15 +2408,7 @@ void wxGenericTreeCtrl::CalculateLineHeight()
if ( HasImages() ) if ( HasImages() )
{ {
// Calculate a m_lineHeight value from the normal Image sizes. // Calculate a m_lineHeight value from the normal Image sizes.
// May be toggle off. Then wxGenericTreeCtrl will spread when m_lineHeight = GetImageLogicalSize(this).y;
// 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;
}
} }
if ( m_imagesState.HasImages() ) if ( m_imagesState.HasImages() )
@ -2457,13 +2447,13 @@ void wxGenericTreeCtrl::CalculateLineHeight()
void wxGenericTreeCtrl::OnImagesChanged() void wxGenericTreeCtrl::OnImagesChanged()
{ {
if ( HasImages() ) // 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 call it solely for the side effect of updating the image list. // we don't use it ourselves, but it also has an important side effect
GetUpdatedImageListFor(this); // of ensuring that we can always get the size to use for the images.
GetUpdatedImageListFor(this);
UpdateAfterImageListChange(); UpdateAfterImageListChange();
}
} }
void wxGenericTreeCtrl::UpdateAfterImageListChange() void wxGenericTreeCtrl::UpdateAfterImageListChange()
@ -2484,6 +2474,16 @@ void wxGenericTreeCtrl::SetImageList(wxImageList *imageList)
UpdateAfterImageListChange(); UpdateAfterImageListChange();
} }
void wxGenericTreeCtrl::SetStateImages(const wxVector<wxBitmapBundle>& 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) void wxGenericTreeCtrl::SetStateImageList(wxImageList *imageList)
{ {
m_imagesState.SetImageList(imageList); m_imagesState.SetImageList(imageList);
@ -2547,8 +2547,9 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
{ {
if ( HasImages() ) if ( HasImages() )
{ {
GetImageLogicalSize(this, image, image_w, image_h); const wxSize imageSize = GetImageLogicalSize(this);
image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT; image_h = imageSize.y;
image_w = imageSize.x + MARGIN_BETWEEN_IMAGE_AND_TEXT;
} }
else else
{ {
@ -2562,7 +2563,7 @@ void wxGenericTreeCtrl::PaintItem(wxGenericTreeItem *item, wxDC& dc)
{ {
if ( m_imagesState.HasImages() ) if ( m_imagesState.HasImages() )
{ {
GetStateImageList()->GetSize(state, state_w, state_h); m_imagesState.GetImageLogicalSize(this, state, state_w, state_h);
if ( image_w != 0 ) if ( image_w != 0 )
state_w += MARGIN_BETWEEN_STATE_AND_IMAGE; state_w += MARGIN_BETWEEN_STATE_AND_IMAGE;
else else
@ -3462,12 +3463,9 @@ bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
if ( textOnly ) if ( textOnly )
{ {
int image_w = 0; int image_w = 0;
int image = ((wxGenericTreeItem*) item.m_pItem)->GetCurrentImage(); if ( i->GetCurrentImage() != NO_IMAGE && HasImages() )
if ( image != NO_IMAGE && HasImages() )
{ {
int image_h; image_w = GetImageLogicalSize(this).x + MARGIN_BETWEEN_IMAGE_AND_TEXT;
GetImageLogicalSize( this, image, image_w, image_h );
image_w += MARGIN_BETWEEN_IMAGE_AND_TEXT;
} }
int state_w = 0; int state_w = 0;
@ -3475,7 +3473,7 @@ bool wxGenericTreeCtrl::GetBoundingRect(const wxTreeItemId& item,
if ( state != wxTREE_ITEMSTATE_NONE && m_imagesState.HasImages() ) if ( state != wxTREE_ITEMSTATE_NONE && m_imagesState.HasImages() )
{ {
int state_h; int state_h;
GetStateImageList()->GetSize( state, state_w, state_h ); m_imagesState.GetImageLogicalSize( this, state, state_w, state_h );
if ( image_w != 0 ) if ( image_w != 0 )
state_w += MARGIN_BETWEEN_STATE_AND_IMAGE; state_w += MARGIN_BETWEEN_STATE_AND_IMAGE;
else else

View file

@ -447,16 +447,19 @@ bool wxHtmlHelpWindow::Create(wxWindow* parent, wxWindowID id,
#endif #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, ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_BOOK,
wxART_HELP_BROWSER, wxART_HELP_BROWSER,
wxSize(16, 16))); iconSize));
ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_FOLDER, ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_FOLDER,
wxART_HELP_BROWSER, wxART_HELP_BROWSER,
wxSize(16, 16))); iconSize));
ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_PAGE, ContentsImageList->Add(wxArtProvider::GetIcon(wxART_HELP_PAGE,
wxART_HELP_BROWSER, wxART_HELP_BROWSER,
wxSize(16, 16))); iconSize));
m_ContentsBox->AssignImageList(ContentsImageList); m_ContentsBox->AssignImageList(ContentsImageList);

View file

@ -946,6 +946,12 @@ void wxTreeCtrl::SetImageList(wxImageList *imageList)
SetAnyImageList(imageList, TVSIL_NORMAL); SetAnyImageList(imageList, TVSIL_NORMAL);
} }
void wxTreeCtrl::SetStateImages(const wxVector<wxBitmapBundle>& images)
{
m_imagesState.SetImages(images);
SetAnyImageList(m_imagesState.GetUpdatedImageListFor(this), TVSIL_STATE);
}
void wxTreeCtrl::SetStateImageList(wxImageList *imageList) void wxTreeCtrl::SetStateImageList(wxImageList *imageList)
{ {
m_imagesState.SetImageList(imageList); m_imagesState.SetImageList(imageList);

View file

@ -629,6 +629,12 @@ void wxTreeCtrl::OnImagesChanged()
} }
} }
void wxTreeCtrl::SetStateImages(const wxVector<wxBitmapBundle>& images)
{
m_imagesState.SetImages(images);
m_qtTreeWidget->update();
}
void wxTreeCtrl::SetStateImageList(wxImageList *imageList) void wxTreeCtrl::SetStateImageList(wxImageList *imageList)
{ {
m_imagesState.SetImageList(imageList); m_imagesState.SetImageList(imageList);

View file

@ -16,6 +16,7 @@
#include "wx/artprov.h" #include "wx/artprov.h"
#include "wx/dcmemory.h" #include "wx/dcmemory.h"
#include "wx/imaglist.h"
#include "asserthelper.h" #include "asserthelper.h"
@ -470,6 +471,37 @@ TEST_CASE("BitmapBundle::Scale", "[bmpbundle][scale]")
CHECK( b.GetDefaultSize() == wxSize(8, 8) ); CHECK( b.GetDefaultSize() == wxSize(8, 8) );
} }
TEST_CASE("BitmapBundle::ImageList", "[bmpbundle][imagelist]")
{
wxVector<wxBitmapBundle> 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 #endif // ports with scaled bitmaps support
TEST_CASE("BitmapBundle::GetConsensusSize", "[bmpbundle]") TEST_CASE("BitmapBundle::GetConsensusSize", "[bmpbundle]")