From 527343602e91d60c65fb7589a6ddcf4683930c78 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Sat, 7 Apr 2007 19:59:51 +0000
Subject: [PATCH] 1. changed wxIconBundle to use m_refData and COW to make
 copying icon bundles    fast (which was needed for 2) 2. make it possible to
 return wxIconBundles from wxArtProvider 3. implement Mac-specific
 wxArtProvider doing (2)

(modified patch 1581960)


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45309 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 Makefile.in                   |  16 +++
 build/bakefiles/files.bkl     |   1 +
 build/msw/makefile.vc         |   4 +-
 docs/changes.txt              |   1 +
 docs/latex/wx/artprov.tex     |  65 ++++++++--
 docs/latex/wx/iconbndl.tex    |  28 ++++-
 include/wx/artprov.h          |  21 +++-
 include/wx/gdicmn.h           |   4 +-
 include/wx/iconbndl.h         |  61 ++++++---
 include/wx/mac/carbon/icon.h  |   3 +
 include/wx/toplevel.h         |   2 +-
 samples/treectrl/treetest.cpp |  64 ++++++++--
 samples/treectrl/treetest.h   |   8 +-
 src/common/artprov.cpp        |  82 ++++++++++--
 src/common/artstd.cpp         |   2 +-
 src/common/gdicmn.cpp         |   2 +
 src/common/iconbndl.cpp       | 231 ++++++++++++++++++++++++----------
 src/gtk/toplevel.cpp          |  18 +--
 src/mac/carbon/artmac.cpp     | 108 ++++++++++++++++
 src/mac/carbon/icon.cpp       |  24 ++++
 src/unix/utilsx11.cpp         |  30 ++---
 21 files changed, 622 insertions(+), 153 deletions(-)
 create mode 100644 src/mac/carbon/artmac.cpp

diff --git a/Makefile.in b/Makefile.in
index 32565adb82..0906a7f627 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -4391,6 +4391,7 @@ COND_TOOLKIT_MAC___GUI_SRC_OBJECTS =  \
 	monodll_accel.o \
 	monodll_aga.o \
 	monodll_app.o \
+	monodll_artmac.o \
 	monodll_bitmap.o \
 	monodll_bmpbuttn.o \
 	monodll_brush.o \
@@ -6193,6 +6194,7 @@ COND_TOOLKIT_MAC___GUI_SRC_OBJECTS_1 =  \
 	monolib_accel.o \
 	monolib_aga.o \
 	monolib_app.o \
+	monolib_artmac.o \
 	monolib_bitmap.o \
 	monolib_bmpbuttn.o \
 	monolib_brush.o \
@@ -8224,6 +8226,7 @@ COND_TOOLKIT_MAC___GUI_SRC_OBJECTS_2 =  \
 	coredll_accel.o \
 	coredll_aga.o \
 	coredll_app.o \
+	coredll_artmac.o \
 	coredll_bitmap.o \
 	coredll_bmpbuttn.o \
 	coredll_brush.o \
@@ -9693,6 +9696,7 @@ COND_TOOLKIT_MAC___GUI_SRC_OBJECTS_3 =  \
 	corelib_accel.o \
 	corelib_aga.o \
 	corelib_app.o \
+	corelib_artmac.o \
 	corelib_bitmap.o \
 	corelib_bmpbuttn.o \
 	corelib_brush.o \
@@ -13558,6 +13562,9 @@ monodll_textctrlce.o: $(srcdir)/src/msw/wince/textctrlce.cpp $(MONODLL_ODEP)
 monodll_aga.o: $(srcdir)/src/mac/carbon/aga.cpp $(MONODLL_ODEP)
 	$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/mac/carbon/aga.cpp
 
+monodll_artmac.o: $(srcdir)/src/mac/carbon/artmac.cpp $(MONODLL_ODEP)
+	$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/mac/carbon/artmac.cpp
+
 monodll_dccg.o: $(srcdir)/src/mac/carbon/dccg.cpp $(MONODLL_ODEP)
 	$(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/mac/carbon/dccg.cpp
 
@@ -17731,6 +17738,9 @@ monolib_textctrlce.o: $(srcdir)/src/msw/wince/textctrlce.cpp $(MONOLIB_ODEP)
 monolib_aga.o: $(srcdir)/src/mac/carbon/aga.cpp $(MONOLIB_ODEP)
 	$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/mac/carbon/aga.cpp
 
+monolib_artmac.o: $(srcdir)/src/mac/carbon/artmac.cpp $(MONOLIB_ODEP)
+	$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/mac/carbon/artmac.cpp
+
 monolib_dccg.o: $(srcdir)/src/mac/carbon/dccg.cpp $(MONOLIB_ODEP)
 	$(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/mac/carbon/dccg.cpp
 
@@ -22915,6 +22925,9 @@ coredll_textctrlce.o: $(srcdir)/src/msw/wince/textctrlce.cpp $(COREDLL_ODEP)
 coredll_aga.o: $(srcdir)/src/mac/carbon/aga.cpp $(COREDLL_ODEP)
 	$(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/mac/carbon/aga.cpp
 
+coredll_artmac.o: $(srcdir)/src/mac/carbon/artmac.cpp $(COREDLL_ODEP)
+	$(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/mac/carbon/artmac.cpp
+
 coredll_dccg.o: $(srcdir)/src/mac/carbon/dccg.cpp $(COREDLL_ODEP)
 	$(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/mac/carbon/dccg.cpp
 
@@ -25891,6 +25904,9 @@ corelib_textctrlce.o: $(srcdir)/src/msw/wince/textctrlce.cpp $(CORELIB_ODEP)
 corelib_aga.o: $(srcdir)/src/mac/carbon/aga.cpp $(CORELIB_ODEP)
 	$(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/mac/carbon/aga.cpp
 
+corelib_artmac.o: $(srcdir)/src/mac/carbon/artmac.cpp $(CORELIB_ODEP)
+	$(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/mac/carbon/artmac.cpp
+
 corelib_dccg.o: $(srcdir)/src/mac/carbon/dccg.cpp $(CORELIB_ODEP)
 	$(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/mac/carbon/dccg.cpp
 
diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl
index f7aa9e9646..3d2921ab1f 100644
--- a/build/bakefiles/files.bkl
+++ b/build/bakefiles/files.bkl
@@ -2100,6 +2100,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
     src/mac/carbon/accel.cpp
     src/mac/carbon/aga.cpp
     src/mac/carbon/app.cpp
+    src/mac/carbon/artmac.cpp
     src/mac/carbon/bitmap.cpp
     src/mac/carbon/bmpbuttn.cpp
     src/mac/carbon/brush.cpp
diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc
index 133a5a2c71..147b32cd55 100644
--- a/build/msw/makefile.vc
+++ b/build/msw/makefile.vc
@@ -4486,7 +4486,7 @@ clean:
 	-if exist $(LIBDIRNAME)\wx$(PORTNAME)$(WXUNIVNAME)$(WX_RELEASE_NODOT)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)_gl.lib del $(LIBDIRNAME)\wx$(PORTNAME)$(WXUNIVNAME)$(WX_RELEASE_NODOT)$(WXUNICODEFLAG)$(WXDEBUGFLAG)$(WX_LIB_FLAVOUR)_gl.lib
 	cd ..\..\samples
 	$(MAKE) -f makefile.vc $(MAKEARGS) clean
-	cd $(MAKEDIR)
+	cd "$(MAKEDIR)"
 
 setup_h: $(SETUPHDIR)\wx ..\..\include\wx\$(__SETUP_H_SUBDIR_FILENAMES)\setup.h $(SETUPHDIR)\wx\setup.h $(SETUPHDIR)\wx\msw\rcdefs.h
 
@@ -4833,7 +4833,7 @@ $(LIBDIRNAME)\wx$(PORTNAME)$(WXUNIVNAME)$(WX_RELEASE_NODOT)$(WXUNICODEFLAG)$(WXD
 sub_samples: 
 	cd ..\..\samples
 	$(MAKE) -f makefile.vc $(MAKEARGS) all
-	cd $(MAKEDIR)
+	cd "$(MAKEDIR)"
 
 $(LIBDIRNAME): 
 	if not exist $(LIBDIRNAME) mkdir $(LIBDIRNAME)
diff --git a/docs/changes.txt b/docs/changes.txt
index d9141a11c5..b9068df632 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -115,6 +115,7 @@ wxGTK:
 
 wxMac:
 
+- Better IconRef support (Alan Shouls)
 - Fix duplicate (empty) help menu in non-English programs (Andreas Jacobs)
 - Allow accelerators to be used with buttons too (Ryan Wilcox)
 - Support resource forks in wxCopyFile() (Hank Schultz)
diff --git a/docs/latex/wx/artprov.tex b/docs/latex/wx/artprov.tex
index 179111d9e6..264f579b7e 100644
--- a/docs/latex/wx/artprov.tex
+++ b/docs/latex/wx/artprov.tex
@@ -10,9 +10,10 @@ When wxWidgets needs to display an icon or a bitmap (e.g. in the standard file
 dialog), it does not use a hard-coded resource but asks wxArtProvider for it
 instead. This way users can plug in their own wxArtProvider class and easily
 replace standard art with their own version. All
-that is needed is to derive a class from wxArtProvider, override its
-\helpref{CreateBitmap}{wxartprovidercreatebitmap} method and register the
-provider with
+that is needed is to derive a class from wxArtProvider, override either its
+\helpref{CreateBitmap}{wxartprovidercreatebitmap} and/or its
+\helpref{CreateIconBundle}{wxartprovidercreateiconbundle} methods
+and register the provider with
 \helpref{wxArtProvider::Push}{wxartproviderpush}:
 
 \begin{verbatim}
@@ -22,12 +23,20 @@ provider with
     wxBitmap CreateBitmap(const wxArtID& id, 
                           const wxArtClient& client,
                           const wxSize size)
+
+    // optionally override this one as well
+    wxIconBundle CreateIconBundle(const wxArtID& id,
+                                  const wxArtClient& client)
     { ... }
   };
   ...
   wxArtProvider::Push(new MyProvider);
 \end{verbatim}
 
+If you need bitmap images (of the same artwork) that should be displayed at different sizes
+you should probably consider overriding \helpref{CreateIconBundle()}{wxartprovidercreateiconbundle} 
+and supplying icon bundles that contain different bitmap sizes.
+
 There's another way of taking advantage of this class: you can use it in your code and use
 platform native icons as provided by \helpref{wxArtProvider::GetBitmap}{wxartprovidergetbitmap} or 
 \helpref{wxArtProvider::GetIcon}{wxartprovidergeticon} (NB: this is not yet really
@@ -37,7 +46,7 @@ small).
 
 \membersection{Identifying art resources}\label{artprovideridentifying}
 
-Every bitmap is known to wxArtProvider under an unique ID that is used by when
+Every bitmap and icon bundle are known to wxArtProvider under an unique ID that is used when
 requesting a resource from it. The ID is represented by wxArtID type and can
 have one of these predefined values (you can see bitmaps represented by these
 constants in the \helpref{artprov}{sampleartprovider} sample):
@@ -159,10 +168,10 @@ by \helpref{GetBitmap}{wxartprovidergetbitmap}.
 
 \func{wxBitmap}{CreateBitmap}{\param{const wxArtID\& }{id}, \param{const wxArtClient\& }{client}, \param{const wxSize\& }{size}}
 
-Derived art provider classes must override this method to create requested 
-art resource. Note that returned bitmaps are cached by wxArtProvider and it is therefore
-not necessary to optimize CreateBitmap for speed (e.g. you may create wxBitmap objects
-from XPMs here).
+Derived art provider classes must override this method or the CreateIconBundle() method
+to create requested art resource. Note that returned bitmaps are cached by wxArtProvider
+and it is therefore not necessary to optimize CreateBitmap() for speed (e.g. you may create
+wxBitmap objects from XPMs here).
 
 \wxheading{Parameters}
 
@@ -178,10 +187,33 @@ dimensions, it will be automatically rescaled to meet client's request.}
 
 This is {\bf not} part of wxArtProvider's public API, use
 \helpref{wxArtProvider::GetBitmap}{wxartprovidergetbitmap} or 
+\helpref{wxArtProvider::GetIconBundle}{wxartprovidergeticonbundle} or
 \helpref{wxArtProvider::GetIcon}{wxartprovidergeticon}
 to query wxArtProvider for a resource.
 
 
+\func{wxIconBundle}{CreateIconBundle}{\param{const wxArtID\& }{id}, \param{const wxArtClient\& }{client}}
+
+Derived art provider classes must override this method or the CreateIconBundle method
+to create requested art resource. Note that returned icon bundles are cached by wxArtProvider
+and it is therefore not necessary to optimize CreateIconBundle for speed (e.g. you may create icon bundles
+from artwork resources here).
+
+\wxheading{Parameters}
+
+\docparam{id}{wxArtID unique identifier of the icon bundle.}
+
+\docparam{client}{wxArtClient identifier of the client (i.e. who is asking for the icon bundle).
+This only servers as a hint.}
+
+\wxheading{Note}
+
+This is {\bf not} part of wxArtProvider's public API, use
+\helpref{wxArtProvider::GetBitmap}{wxartprovidergetbitmap} or 
+\helpref{wxArtProvider::GetIconBundle}{wxartprovidergeticonbundle} or
+\helpref{wxArtProvider::GetIcon}{wxartprovidergeticon}
+to query wxArtProvider for a resource.
+
 \membersection{wxArtProvider::Delete}\label{wxartproviderdelete}
 
 \func{static bool}{Delete}{\param{wxArtProvider* }{provider}}
@@ -208,6 +240,23 @@ Query registered providers for bitmap with given ID.
 The bitmap if one of registered providers recognizes the ID or wxNullBitmap otherwise.
 
 
+\membersection{wxArtProvider::GetIconBundle}\label{wxartprovidergeticonbundle}
+
+\func{static wxIconBundle}{GetIconBundle}{\param{const wxArtID\& }{id}, \param{const wxArtClient\& }{client = wxART\_OTHER}}
+
+Query registered providers for icon bundle with given ID.
+
+\wxheading{Parameters}
+
+\docparam{id}{wxArtID unique identifier of the icon bundle.}
+
+\docparam{client}{wxArtClient identifier of the client (i.e. who is asking for the icon bundle).}
+
+\wxheading{Return value}
+
+The icon bundle if one of registered providers recognizes the ID or wxNullIconBundle otherwise.
+
+
 \membersection{wxArtProvider::GetIcon}\label{wxartprovidergeticon}
 
 \func{static wxIcon}{GetIcon}{\param{const wxArtID\& }{id}, \param{const wxArtClient\& }{client = wxART\_OTHER}, \param{const wxSize\& }{size = wxDefaultSize}}
diff --git a/docs/latex/wx/iconbndl.tex b/docs/latex/wx/iconbndl.tex
index d1a68478c3..e76082bb04 100644
--- a/docs/latex/wx/iconbndl.tex
+++ b/docs/latex/wx/iconbndl.tex
@@ -6,7 +6,12 @@ see also \helpref{wxDialog::SetIcons}{wxdialogseticons} and
 
 \wxheading{Derived from}
 
-No base class
+\helpref{wxGDIObject}{wxgdiobject}\\
+\helpref{wxObject}{wxobject}
+
+\wxheading{Predefined objects}
+
+{\bf wxNullIconBundle}
 
 \latexignore{\rtfignore{\wxheading{Members}}}
 
@@ -50,7 +55,7 @@ replaced by the new one.
 
 \membersection{wxIconBundle::GetIcon}\label{wxiconbundlegeticon}
 
-\constfunc{const wxIcon\&}{GetIcon}{\param{const wxSize\& }{size}}
+\constfunc{wxIcon}{GetIcon}{\param{const wxSize\& }{size}}
 
 Returns the icon with the given size; if no such icon exists,
 returns the icon with size wxSYS\_ICON\_X/wxSYS\_ICON\_Y;
@@ -58,13 +63,24 @@ if no such icon exists,
 returns the first icon in the bundle. If size = wxSize( -1, -1 ),
 returns the icon with size wxSYS\_ICON\_X/wxSYS\_ICON\_Y.
 
-\constfunc{const wxIcon\&}{GetIcon}{\param{wxCoord }{size = -1}}
+\constfunc{wxIcon}{GetIcon}{\param{wxCoord }{size = -1}}
 
 Same as GetIcon( wxSize( size, size ) ).
 
-\membersection{wxIconBundle::operator=}\label{wxiconbundleoperatorassign}
+\membersection{wxIconBundle::operator $=$}\label{wxiconbundleoperatorassign}
+
+\func{wxIconBundle\&}{operator $=$}{\param{const wxIconBundle\& }{ic}}
+
+Assignment operator, using \helpref{reference counting}{trefcount}.
+
+\membersection{wxIconBundle::operator $==$}\label{wxiconbundleoperatorequals}
+
+\func{bool}{operator $==$}{\param{const wxIconBundle\& }{ic}}
+
+Equality operator. This returns \true if two icon bundles are equal.
 
-\func{const wxIconBundle\&}{operator=}{\param{const wxIconBundle\& }{ic}}
+\membersection{wxIconBundle::operator $!=$}\label{wxiconbundleoperatornotequals}
 
-Assignment operator.
+\func{bool}{operator $!=$}{\param{const wxIconBundle\& }{ic}}
 
+Inequality operator. This returns \true if two icon bundles are not equal.
diff --git a/include/wx/artprov.h b/include/wx/artprov.h
index 184a21791f..e98bd41182 100644
--- a/include/wx/artprov.h
+++ b/include/wx/artprov.h
@@ -15,6 +15,7 @@
 #include "wx/string.h"
 #include "wx/bitmap.h"
 #include "wx/icon.h"
+#include "wx/iconbndl.h"
 
 class WXDLLEXPORT wxArtProvidersList;
 class WXDLLEXPORT wxArtProviderCache;
@@ -44,6 +45,7 @@ typedef wxString wxArtID;
 #define wxART_HELP_BROWSER         wxART_MAKE_CLIENT_ID(wxART_HELP_BROWSER)
 #define wxART_MESSAGE_BOX          wxART_MAKE_CLIENT_ID(wxART_MESSAGE_BOX)
 #define wxART_BUTTON               wxART_MAKE_CLIENT_ID(wxART_BUTTON)
+#define wxART_LIST                 wxART_MAKE_CLIENT_ID(wxART_LIST)
 
 #define wxART_OTHER                wxART_MAKE_CLIENT_ID(wxART_OTHER)
 
@@ -146,6 +148,11 @@ public:
                           const wxArtClient& client = wxART_OTHER,
                           const wxSize& size = wxDefaultSize);
 
+    // Query the providers for iconbundle with given ID and return it. Return
+    // wxNullIconBundle if no provider provides it.
+    static wxIconBundle GetIconBundle(const wxArtID& id,
+                                      const wxArtClient& client = wxART_OTHER);
+
     // Get the size hint of an icon from a specific wxArtClient, queries
     // the topmost provider if platform_dependent = false
     static wxSize GetSizeHint(const wxArtClient& client, bool platform_dependent = false);
@@ -177,12 +184,18 @@ protected:
         return GetSizeHint(client, true);
     }
 
-    // Derived classes must override this method to create requested
-    // art resource. This method is called only once per instance's
-    // lifetime for each requested wxArtID.
+    // Derived classes must override CreateBitmap or CreateIconBundle
+    // (or both) to create requested art resource. This method is called
+    // only once per instance's lifetime for each requested wxArtID.
     virtual wxBitmap CreateBitmap(const wxArtID& WXUNUSED(id),
                                   const wxArtClient& WXUNUSED(client),
-                                  const wxSize& WXUNUSED(size)) = 0;
+                                  const wxSize& WXUNUSED(size)) { return wxNullBitmap; }
+
+    virtual wxIconBundle CreateIconBundle(const wxArtID& WXUNUSED(id),
+                                          const wxArtClient& WXUNUSED(client))
+    {
+        return wxNullIconBundle;
+    }
 
 private:
     static void CommonAddingProvider();
diff --git a/include/wx/gdicmn.h b/include/wx/gdicmn.h
index 18dce6cbfb..acd374d4c3 100644
--- a/include/wx/gdicmn.h
+++ b/include/wx/gdicmn.h
@@ -37,6 +37,7 @@ class WXDLLIMPEXP_CORE wxPalette;
 class WXDLLIMPEXP_CORE wxPen;
 class WXDLLIMPEXP_CORE wxRegion;
 class WXDLLIMPEXP_BASE wxString;
+class WXDLLIMPEXP_CORE wxIconBundle;
 
 // ---------------------------------------------------------------------------
 // constants
@@ -712,9 +713,10 @@ extern WXDLLEXPORT_DATA(wxIcon)       wxNullIcon;
 extern WXDLLEXPORT_DATA(wxCursor)     wxNullCursor;
 extern WXDLLEXPORT_DATA(wxPen)        wxNullPen;
 extern WXDLLEXPORT_DATA(wxBrush)      wxNullBrush;
-extern WXDLLEXPORT_DATA(wxPalette)     wxNullPalette;
+extern WXDLLEXPORT_DATA(wxPalette)    wxNullPalette;
 extern WXDLLEXPORT_DATA(wxFont)       wxNullFont;
 extern WXDLLEXPORT_DATA(wxColour)     wxNullColour;
+extern WXDLLEXPORT_DATA(wxIconBundle) wxNullIconBundle;
 
 extern WXDLLEXPORT_DATA(wxColourDatabase*)  wxTheColourDatabase;
 
diff --git a/include/wx/iconbndl.h b/include/wx/iconbndl.h
index 3749467240..8a76d39eb5 100644
--- a/include/wx/iconbndl.h
+++ b/include/wx/iconbndl.h
@@ -13,57 +13,80 @@
 #define _WX_ICONBNDL_H_
 
 #include "wx/dynarray.h"
+#include "wx/gdiobj.h"
 // for wxSize
 #include "wx/gdicmn.h"
+#include "wx/icon.h"
 
 class WXDLLIMPEXP_CORE wxIcon;
 class WXDLLIMPEXP_BASE wxString;
 
-WX_DECLARE_EXPORTED_OBJARRAY( wxIcon, wxIconArray );
+class WXDLLEXPORT wxIconBundle;
+
+WX_DECLARE_EXPORTED_OBJARRAY(wxIcon, wxIconArray);
 
 // this class can't load bitmaps of type wxBITMAP_TYPE_ICO_RESOURCE,
 // if you need them, you have to load them manually and call
 // wxIconCollection::AddIcon
-class WXDLLEXPORT wxIconBundle
+class WXDLLEXPORT wxIconBundle : public wxGDIObject
 {
 public:
     // default constructor
-    wxIconBundle() : m_icons() {}
+    wxIconBundle();
+
     // initializes the bundle with the icon(s) found in the file
-    wxIconBundle( const wxString& file, long type ) : m_icons()
-        { AddIcon( file, type ); }
+    wxIconBundle(const wxString& file, long type);
+
     // initializes the bundle with a single icon
-    wxIconBundle( const wxIcon& icon ) : m_icons()
-        { AddIcon( icon ); }
+    wxIconBundle(const wxIcon& icon);
+
+    // initializes the bundle from another icon bundle
+    wxIconBundle(const wxIconBundle& icon);
 
-    const wxIconBundle& operator =( const wxIconBundle& ic );
-    wxIconBundle( const wxIconBundle& ic ) : m_icons()
-        { *this = ic; }
+    wxIconBundle& operator=(const wxIconBundle& ic)
+        { if ( this != &ic) Ref(ic); return *this; }
+
+    virtual bool IsOk() const;
 
-    ~wxIconBundle() { DeleteIcons(); }
 
     // adds all the icons contained in the file to the collection,
     // if the collection already contains icons with the same
     // width and height, they are replaced
-    void AddIcon( const wxString& file, long type );
+    void AddIcon(const wxString& file, long type);
+
     // adds the icon to the collection, if the collection already
     // contains an icon with the same width and height, it is
     // replaced
-    void AddIcon( const wxIcon& icon );
+    void AddIcon(const wxIcon& icon);
 
     // returns the icon with the given size; if no such icon exists,
     // returns the icon with size wxSYS_ICON_[XY]; if no such icon exists,
     // returns the first icon in the bundle
-    const wxIcon& GetIcon( const wxSize& size ) const;
+    wxIcon GetIcon(const wxSize& size) const;
+
     // equivalent to GetIcon( wxSize( size, size ) )
-    const wxIcon& GetIcon( wxCoord size = wxDefaultCoord ) const
+    wxIcon GetIcon(wxCoord size = wxDefaultCoord) const
         { return GetIcon( wxSize( size, size ) ); }
+
+
+    // enumerate all icons in the bundle: don't use these functions if ti can
+    // be avoided, using GetIcon() directly is better
+
+    // return the number of available icons
+    size_t GetIconCount() const;
+
+    // return the icon at index (must be < GetIconCount())
+    wxIcon GetIconByIndex(size_t n) const;
+
+protected:
+    virtual wxObjectRefData *CreateRefData() const;
+    virtual wxObjectRefData *CloneRefData(const wxObjectRefData *data) const;
+
 private:
     // delete all icons
     void DeleteIcons();
-public:
-    wxIconArray m_icons;
+
+    DECLARE_DYNAMIC_CLASS(wxIconBundle)
 };
 
-#endif
-    // _WX_ICONBNDL_H_
+#endif // _WX_ICONBNDL_H_
diff --git a/include/wx/mac/carbon/icon.h b/include/wx/mac/carbon/icon.h
index 2e9e0d0af9..5e786bca58 100644
--- a/include/wx/mac/carbon/icon.h
+++ b/include/wx/mac/carbon/icon.h
@@ -29,6 +29,9 @@ public:
     {
       LoadFile(loc.GetFileName(), wxBITMAP_TYPE_ICON);
     }
+
+    wxIcon(WXHICON icon, const wxSize& size);
+
     virtual ~wxIcon();
 
     bool LoadFile(const wxString& name, wxBitmapType flags /* = wxBITMAP_TYPE_ICON_RESOURCE */ ,
diff --git a/include/wx/toplevel.h b/include/wx/toplevel.h
index a4530bd2b8..3814678337 100644
--- a/include/wx/toplevel.h
+++ b/include/wx/toplevel.h
@@ -145,7 +145,7 @@ public:
     virtual bool IsIconized() const = 0;
 
     // get the frame icon
-    const wxIcon& GetIcon() const { return m_icons.GetIcon( -1 ); }
+    wxIcon GetIcon() const { return m_icons.GetIcon( -1 ); }
 
     // get the frame icons
     const wxIconBundle& GetIcons() const { return m_icons; }
diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp
index 1eab7f8e13..73a7bb62f9 100644
--- a/samples/treectrl/treetest.cpp
+++ b/samples/treectrl/treetest.cpp
@@ -24,6 +24,7 @@
 #include "wx/colordlg.h"
 #include "wx/numdlg.h"
 
+#include "wx/artprov.h"
 #include "wx/image.h"
 #include "wx/imaglist.h"
 #include "wx/treectrl.h"
@@ -96,6 +97,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     MENU_LINK(DeleteAll)
     MENU_LINK(Recreate)
     MENU_LINK(ToggleImages)
+    MENU_LINK(ToggleAlternateImages)
     MENU_LINK(ToggleButtons)
     MENU_LINK(SetImageSize)
     MENU_LINK(CollapseAndReset)
@@ -209,6 +211,7 @@ MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h)
     style_menu->AppendCheckItem(TreeTest_ToggleSel, wxT("Toggle &selection mode"));
 #endif // NO_MULTIPLE_SELECTION
     style_menu->AppendCheckItem(TreeTest_ToggleImages, wxT("Toggle show ima&ges"));
+    style_menu->AppendCheckItem(TreeTest_ToggleAlternateImages, wxT("Toggle alternate images"));
     style_menu->Append(TreeTest_SetImageSize, wxT("Set image si&ze..."));
     style_menu->AppendSeparator();
     style_menu->Append(TreeTest_SetFgColour, wxT("Set &foreground colour..."));
@@ -276,6 +279,7 @@ MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h)
     CreateTreeWithDefStyle();
 
     menu_bar->Check(TreeTest_ToggleImages, true);
+    menu_bar->Check(TreeTest_ToggleAlternateImages, false);
 
 #if wxUSE_STATUSBAR
     // create a status bar
@@ -601,6 +605,14 @@ void MyFrame::OnToggleImages(wxCommandEvent& WXUNUSED(event))
     }
 }
 
+void MyFrame::OnToggleAlternateImages(wxCommandEvent& WXUNUSED(event))
+{
+    bool alternateImages = m_treeCtrl->AlternateImages();
+
+    m_treeCtrl->SetAlternateImages(!alternateImages);
+    m_treeCtrl->CreateImageList(0);
+}
+
 void MyFrame::OnToggleButtons(wxCommandEvent& WXUNUSED(event))
 {
 #if USE_GENERIC_TREECTRL || !defined(__WXMSW__)
@@ -706,7 +718,8 @@ IMPLEMENT_DYNAMIC_CLASS(MyTreeCtrl, wxTreeCtrl)
 MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id,
                        const wxPoint& pos, const wxSize& size,
                        long style)
-          : wxTreeCtrl(parent, id, pos, size, style)
+          : wxTreeCtrl(parent, id, pos, size, style),
+            m_alternateImages(false)
 {
     m_reverseSort = false;
 
@@ -734,15 +747,29 @@ void MyTreeCtrl::CreateImageList(int size)
     // should correspond to TreeCtrlIcon_xxx enum
     wxBusyCursor wait;
     wxIcon icons[5];
-    icons[0] = wxIcon(icon1_xpm);
-    icons[1] = wxIcon(icon2_xpm);
-    icons[2] = wxIcon(icon3_xpm);
-    icons[3] = wxIcon(icon4_xpm);
-    icons[4] = wxIcon(icon5_xpm);
 
-    int sizeOrig = icons[0].GetWidth();
+    if (m_alternateImages)
+    {
+        icons[TreeCtrlIcon_File] = wxIcon(icon1_xpm);
+        icons[TreeCtrlIcon_FileSelected] = wxIcon(icon2_xpm);
+        icons[TreeCtrlIcon_Folder] = wxIcon(icon3_xpm);
+        icons[TreeCtrlIcon_FolderSelected] = wxIcon(icon4_xpm);
+        icons[TreeCtrlIcon_FolderOpened] = wxIcon(icon5_xpm);
+    }
+    else
+    {
+        wxSize iconSize(size, size);
+
+        icons[TreeCtrlIcon_File] =
+        icons[TreeCtrlIcon_FileSelected] = wxArtProvider::GetIcon(wxART_NORMAL_FILE, wxART_LIST, iconSize);
+        icons[TreeCtrlIcon_Folder] =
+        icons[TreeCtrlIcon_FolderSelected] =
+        icons[TreeCtrlIcon_FolderOpened] = wxArtProvider::GetIcon(wxART_FOLDER, wxART_LIST, iconSize);
+    }
+
     for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
     {
+        int sizeOrig = icons[0].GetWidth();
         if ( size == sizeOrig )
         {
             images->Add(icons[i]);
@@ -771,12 +798,25 @@ void MyTreeCtrl::CreateButtonsImageList(int size)
     // should correspond to TreeCtrlIcon_xxx enum
     wxBusyCursor wait;
     wxIcon icons[4];
-    icons[0] = wxIcon(icon3_xpm);   // closed
-    icons[1] = wxIcon(icon3_xpm);   // closed, selected
-    icons[2] = wxIcon(icon5_xpm);   // open
-    icons[3] = wxIcon(icon5_xpm);   // open, selected
 
-    for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
+    if (m_alternateImages)
+    {
+        icons[0] = wxIcon(icon3_xpm);   // closed
+        icons[1] = wxIcon(icon3_xpm);   // closed, selected
+        icons[2] = wxIcon(icon5_xpm);   // open
+        icons[3] = wxIcon(icon5_xpm);   // open, selected
+    }
+    else
+    {
+        wxSize iconSize(size, size);
+
+        icons[0] =                                                                 // closed
+        icons[1] = wxArtProvider::GetIcon(wxART_FOLDER, wxART_LIST, iconSize);     // closed, selected
+        icons[2] =                                                                 // open
+        icons[3] = wxArtProvider::GetIcon(wxART_FOLDER_OPEN, wxART_LIST, iconSize);// open, selected
+    }
+
+   for ( size_t i = 0; i < WXSIZEOF(icons); i++ )
     {
         int sizeOrig = icons[i].GetWidth();
         if ( size == sizeOrig )
diff --git a/samples/treectrl/treetest.h b/samples/treectrl/treetest.h
index f9a2f3bcaa..14e26e6a13 100644
--- a/samples/treectrl/treetest.h
+++ b/samples/treectrl/treetest.h
@@ -61,7 +61,7 @@ public:
         TreeCtrlIcon_FolderOpened
     };
 
-    MyTreeCtrl() { }
+    MyTreeCtrl() { m_alternateImages = false; }
     MyTreeCtrl(wxWindow *parent, const wxWindowID id,
                const wxPoint& pos, const wxSize& size,
                long style);
@@ -111,6 +111,9 @@ public:
 
     void SetLastItem(wxTreeItemId id) { m_lastItem = id; }
 
+    void SetAlternateImages(bool show) { m_alternateImages = show; }
+    bool AlternateImages() const { return m_alternateImages; }
+
 protected:
     virtual int OnCompareItems(const wxTreeItemId& i1, const wxTreeItemId& i2);
 
@@ -133,6 +136,7 @@ private:
     bool         m_reverseSort;             // flag for OnCompareItems
     wxTreeItemId m_lastItem,                // for OnEnsureVisible()
                  m_draggedItem;             // item being dragged right now
+    bool         m_alternateImages;
 
     // NB: due to an ugly wxMSW hack you _must_ use DECLARE_DYNAMIC_CLASS()
     //     if you want your overloaded OnCompareItems() to be called.
@@ -193,6 +197,7 @@ public:
     void OnRecreate(wxCommandEvent& event);
     void OnToggleButtons(wxCommandEvent& event);
     void OnToggleImages(wxCommandEvent& event);
+    void OnToggleAlternateImages(wxCommandEvent& event);
     void OnSetImageSize(wxCommandEvent& event);
     void OnCollapseAndReset(wxCommandEvent& event);
 
@@ -274,6 +279,7 @@ enum
     TreeTest_DeleteAll,
     TreeTest_Recreate,
     TreeTest_ToggleImages,
+    TreeTest_ToggleAlternateImages,
     TreeTest_ToggleButtons,
     TreeTest_SetImageSize,
     TreeTest_ToggleSel,
diff --git a/src/common/artprov.cpp b/src/common/artprov.cpp
index dd5cdb4bd5..bd79bb96e3 100644
--- a/src/common/artprov.cpp
+++ b/src/common/artprov.cpp
@@ -43,6 +43,7 @@ WX_DEFINE_LIST(wxArtProvidersList)
 // ----------------------------------------------------------------------------
 
 WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxBitmap, wxArtProviderBitmapsHash);
+WX_DECLARE_EXPORTED_STRING_HASH_MAP(wxIconBundle, wxArtProviderIconBundlesHash);
 
 class WXDLLEXPORT wxArtProviderCache
 {
@@ -51,14 +52,22 @@ public:
     void PutBitmap(const wxString& full_id, const wxBitmap& bmp)
         { m_bitmapsHash[full_id] = bmp; }
 
+    bool GetIconBundle(const wxString& full_id, wxIconBundle* bmp);
+    void PutIconBundle(const wxString& full_id, const wxIconBundle& iconbundle)
+        { m_iconBundlesHash[full_id] = iconbundle; }
+
     void Clear();
 
     static wxString ConstructHashID(const wxArtID& id,
                                     const wxArtClient& client,
                                     const wxSize& size);
 
+    static wxString ConstructHashID(const wxArtID& id,
+                                    const wxArtClient& client);
+
 private:
-    wxArtProviderBitmapsHash m_bitmapsHash;
+    wxArtProviderBitmapsHash m_bitmapsHash;         // cache of wxBitmaps
+    wxArtProviderIconBundlesHash m_iconBundlesHash; // cache of wxIconBundles
 };
 
 bool wxArtProviderCache::GetBitmap(const wxString& full_id, wxBitmap* bmp)
@@ -75,21 +84,43 @@ bool wxArtProviderCache::GetBitmap(const wxString& full_id, wxBitmap* bmp)
     }
 }
 
+bool wxArtProviderCache::GetIconBundle(const wxString& full_id, wxIconBundle* bmp)
+{
+    wxArtProviderIconBundlesHash::iterator entry = m_iconBundlesHash.find(full_id);
+    if ( entry == m_iconBundlesHash.end() )
+    {
+        return false;
+    }
+    else
+    {
+        *bmp = entry->second;
+        return true;
+    }
+}
+
 void wxArtProviderCache::Clear()
 {
     m_bitmapsHash.clear();
+    m_iconBundlesHash.clear();
 }
 
-/*static*/ wxString wxArtProviderCache::ConstructHashID(
-                                const wxArtID& id, const wxArtClient& client,
-                                const wxSize& size)
+/* static */ wxString
+wxArtProviderCache::ConstructHashID(const wxArtID& id,
+                                    const wxArtClient& client)
 {
-    wxString str;
-    str.Printf(wxT("%s-%s-%i-%i"), id.c_str(), client.c_str(), size.x, size.y);
-    return str;
+    return id + _T('-') + client;
 }
 
 
+/* static */ wxString
+wxArtProviderCache::ConstructHashID(const wxArtID& id,
+                                    const wxArtClient& client,
+                                    const wxSize& size)
+{
+    return ConstructHashID(id, client) + _T('-') +
+            wxString::Format(_T("%d-%d"), size.x, size.y);
+}
+
 // ============================================================================
 // wxArtProvider class
 // ============================================================================
@@ -216,20 +247,53 @@ wxArtProvider::~wxArtProvider()
 #endif
                 break;
             }
+            // We could try the IconBundles here and convert what we find
+            // to a bitmap.
         }
-
         sm_cache->PutBitmap(hashId, bmp);
-    }
+        }
 
     return bmp;
 }
 
+/*static*/ wxIconBundle wxArtProvider::GetIconBundle(const wxArtID& id, const wxArtClient& client)
+{
+    // safety-check against writing client,id,size instead of id,client,size:
+    wxASSERT_MSG( client.Last() == _T('C'), _T("invalid 'client' parameter") );
+
+    wxCHECK_MSG( sm_providers, wxNullIconBundle, _T("no wxArtProvider exists") );
+
+    wxString hashId = wxArtProviderCache::ConstructHashID(id, client);
+
+    wxIconBundle iconbundle;
+    if ( !sm_cache->GetIconBundle(hashId, &iconbundle) )
+    {
+        for (wxArtProvidersList::compatibility_iterator node = sm_providers->GetFirst();
+             node; node = node->GetNext())
+        {
+            iconbundle = node->GetData()->CreateIconBundle(id, client);
+            if ( iconbundle.IsOk() )
+                break;
+        }
+
+        sm_cache->PutIconBundle(hashId, iconbundle);
+    }
+
+    return iconbundle;
+}
+
 /*static*/ wxIcon wxArtProvider::GetIcon(const wxArtID& id,
                                          const wxArtClient& client,
                                          const wxSize& size)
 {
     wxCHECK_MSG( sm_providers, wxNullIcon, _T("no wxArtProvider exists") );
 
+    // First look for an appropriate icon bundle - this will give us the best icon
+    wxIconBundle iconBundle = GetIconBundle(id, client);
+    if ( iconBundle.IsOk() )
+        return iconBundle.GetIcon(size);
+
+    // If there is no icon bundle then look for a bitmap
     wxBitmap bmp = GetBitmap(id, client, size);
     if ( !bmp.Ok() )
         return wxNullIcon;
diff --git a/src/common/artstd.cpp b/src/common/artstd.cpp
index c3e4fe994b..c5a9679e38 100644
--- a/src/common/artstd.cpp
+++ b/src/common/artstd.cpp
@@ -77,7 +77,7 @@ protected:
     wxArtProvider::Push(new wxDefaultArtProvider);
 }
 
-#if !defined(__WXGTK20__) || defined(__WXUNIVERSAL__)
+#if !(defined(__WXGTK20__) || defined(__WXMAC__)) || defined(__WXUNIVERSAL__)
 /*static*/ void wxArtProvider::InitNativeProvider()
 {
 }
diff --git a/src/common/gdicmn.cpp b/src/common/gdicmn.cpp
index a4b09c9493..0214f8cad3 100644
--- a/src/common/gdicmn.cpp
+++ b/src/common/gdicmn.cpp
@@ -25,6 +25,7 @@
     #include "wx/brush.h"
     #include "wx/palette.h"
     #include "wx/icon.h"
+    #include "wx/iconbndl.h"
     #include "wx/cursor.h"
     #include "wx/settings.h"
     #include "wx/bitmap.h"
@@ -52,6 +53,7 @@ WXDLLIMPEXP_DATA_CORE(wxPen)     wxNullPen;
 #if wxUSE_PALETTE
 WXDLLIMPEXP_DATA_CORE(wxPalette) wxNullPalette;
 #endif
+WXDLLIMPEXP_DATA_CORE(wxIconBundle) wxNullIconBundle;
 
 const wxSize wxDefaultSize(wxDefaultCoord, wxDefaultCoord);
 const wxPoint wxDefaultPosition(wxDefaultCoord, wxDefaultCoord);
diff --git a/src/common/iconbndl.cpp b/src/common/iconbndl.cpp
index e15376f5bb..19ede4871a 100644
--- a/src/common/iconbndl.cpp
+++ b/src/common/iconbndl.cpp
@@ -1,13 +1,21 @@
 /////////////////////////////////////////////////////////////////////////////
 // Name:        src/common/iconbndl.cpp
 // Purpose:     wxIconBundle
-// Author:      Mattia Barbon
+// Author:      Mattia Barbon, Vadim Zeitlin
 // Created:     23.03.2002
 // RCS-ID:      $Id$
 // Copyright:   (c) Mattia barbon
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
@@ -30,113 +38,200 @@
 
 WX_DEFINE_OBJARRAY(wxIconArray)
 
-const wxIconBundle& wxIconBundle::operator =( const wxIconBundle& ic )
+IMPLEMENT_DYNAMIC_CLASS(wxIconBundle, wxGDIObject)
+
+#define M_ICONBUNDLEDATA ((wxIconBundleRefData *)m_refData)
+
+// ----------------------------------------------------------------------------
+// wxIconBundleRefData
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxIconBundleRefData : public wxGDIRefData
+{
+public:
+    // default and copy ctors and assignment operators are ok
+
+protected:
+    wxIconArray m_icons;
+
+    friend class WXDLLEXPORT wxIconBundle;
+};
+
+// ============================================================================
+// wxIconBundle implementation
+// ============================================================================
+
+wxIconBundle::wxIconBundle()
+            : wxGDIObject()
+{
+    m_refData = new wxIconBundleRefData;
+}
+
+wxIconBundle::wxIconBundle(const wxString& file, long type)
+            : wxGDIObject()
 {
-    if( this == &ic ) return *this;
+    m_refData = new wxIconBundleRefData;
+    AddIcon(file, type);
+}
 
-    size_t i, max = ic.m_icons.GetCount();
+wxIconBundle::wxIconBundle(const wxIconBundle& icon)
+            : wxGDIObject()
+{
+    Ref(icon);
+}
 
-    DeleteIcons();
-    for( i = 0; i < max; ++i )
-        m_icons.Add( ic.m_icons[i] );
+wxIconBundle::wxIconBundle(const wxIcon& icon)
+            : wxGDIObject()
+{
+    m_refData = new wxIconBundleRefData;
+    AddIcon(icon);
+}
 
-    return *this;
+wxObjectRefData *wxIconBundle::CreateRefData() const
+{
+    return new wxIconBundleRefData;
+}
+
+wxObjectRefData *wxIconBundle::CloneRefData(const wxObjectRefData *data) const
+{
+    return new wxIconBundleRefData(*wx_static_cast(const wxIconBundleRefData *, data));
 }
 
 void wxIconBundle::DeleteIcons()
 {
-    m_icons.Empty();
+    wxIconBundleRefData* ref = new wxIconBundleRefData();
+    UnRef();
+    m_refData = ref;
 }
 
-#if wxUSE_IMAGE
-void wxIconBundle::AddIcon( const wxString& file, long type )
-#else
-void wxIconBundle::AddIcon( const wxString& WXUNUSED(file), long WXUNUSED(type) )
-#endif
+bool wxIconBundle::IsOk() const
+{
+    return M_ICONBUNDLEDATA && !M_ICONBUNDLEDATA->m_icons.IsEmpty();
+}
+
+void wxIconBundle::AddIcon(const wxString& file, long type)
 {
+#ifdef __WXMAC__
+    // Deal with standard icons
+    if ( type == wxBITMAP_TYPE_ICON_RESOURCE )
+    {
+        wxIcon tmp(file, type);
+        if (tmp.Ok())
+        {
+            AddIcon(tmp);
+            return;
+        }
+    }
+#endif // __WXMAC__
+
 #if wxUSE_IMAGE && (!defined(__WXMSW__) || wxUSE_WXDIB)
-    size_t count = wxImage::GetImageCount( file, type );
-    size_t i;
     wxImage image;
 
-    for( i = 0; i < count; ++i )
+    const size_t count = wxImage::GetImageCount( file, type );
+    for ( size_t i = 0; i < count; ++i )
     {
-        if( !image.LoadFile( file, type, i ) )
+        if ( !image.LoadFile( file, type, i ) )
         {
             wxLogError( _("Failed to load image %d from file '%s'."),
                         i, file.c_str() );
             continue;
         }
 
-        wxIcon* tmp = new wxIcon();
-        tmp->CopyFromBitmap( wxBitmap( image ) );
-        AddIcon( *tmp );
-        delete tmp;
+        wxIcon tmp;
+        tmp.CopyFromBitmap(wxBitmap(image));
+        AddIcon(tmp);
     }
-#endif
+#else // !wxUSE_IMAGE
+    wxUnusedVar(file);
+    wxUnusedVar(type);
+#endif // wxUSE_IMAGE/!wxUSE_IMAGE
 }
 
-const wxIcon& wxIconBundle::GetIcon( const wxSize& size ) const
+wxIcon wxIconBundle::GetIcon(const wxSize& size) const
 {
-    // temp. variable needed to fix Borland C++ 5.5.1 problem
-    // with passing a return value through two functions
-    wxIcon *tmp;
-
-    size_t max = m_icons.GetCount();
-
-    // if we have one or no icon, we can return now without doing more work:
-    if ( max <= 1 )
-    {
-        if ( max == 1 ) // fix for broken BCC
-            tmp = &m_icons[0];
-        else // max == 0
-            tmp = &wxNullIcon;
-        return *tmp;
-    }
+    wxCHECK_MSG( IsOk(), wxNullIcon, _T("invalid icon bundle") );
 
-    // there are more icons, find the best match:
-    wxCoord sysX = wxSystemSettings::GetMetric( wxSYS_ICON_X ),
-            sysY = wxSystemSettings::GetMetric( wxSYS_ICON_Y );
+    const wxIconArray& iconArray = M_ICONBUNDLEDATA->m_icons;
 
-    wxIcon *sysIcon = 0;
+    const size_t count = iconArray.size();
 
-    for( size_t i = 0; i < max; i++ )
+    // optimize for the common case of icon bundles containing one icon only
+    wxIcon iconBest;
+    switch ( count )
     {
-        if( !m_icons[i].Ok() )
-            continue;
-        wxCoord sx = m_icons[i].GetWidth(), sy = m_icons[i].GetHeight();
-        // requested size
-        if( sx == size.x && sy == size.y )
-        {
-            tmp = &m_icons[i]; // fix for broken BCC
-            return *tmp;
-        }
-        // keep track if there is a system-size icon
-        if( sx == sysX && sy == sysY )
-            sysIcon = &m_icons[i];
+        case 0:
+            // nothing to do, iconBest is already invalid
+            break;
+
+        case 1:
+            iconBest = iconArray[0];
+            break;
+
+        default:
+            // there is more than one icon, find the best match:
+            wxCoord sysX = wxSystemSettings::GetMetric( wxSYS_ICON_X ),
+                    sysY = wxSystemSettings::GetMetric( wxSYS_ICON_Y );
+
+            for ( size_t i = 0; i < count; i++ )
+            {
+                const wxIcon& icon = iconArray[i];
+                wxCoord sx = icon.GetWidth(),
+                        sy = icon.GetHeight();
+
+                // if we got an icon of exactly the requested size, we're done
+                if ( sx == size.x && sy == size.y )
+                {
+                    iconBest = icon;
+                    break;
+                }
+
+                // the best icon is by default (arbitrarily) the first one but
+                // if we find a system-sized icon, take it instead
+                if ( sx == sysX && sy == sysY || !iconBest.IsOk() )
+                    iconBest = icon;
+            }
     }
 
-    // return the system-sized icon if we've got one
-    if( sysIcon ) return *sysIcon;
-    // we certainly have at least one icon thanks to the <=1 check above
-    tmp = &m_icons[0];
-    return *tmp;
+#ifdef __WXMAC__
+    return wxIcon(iconBest.GetHICON(), size);
+#else
+    return iconBest;
+#endif
 }
 
-void wxIconBundle::AddIcon( const wxIcon& icon )
+void wxIconBundle::AddIcon(const wxIcon& icon)
 {
-    size_t i, max = m_icons.GetCount();
+    wxCHECK_RET( icon.IsOk(), _T("invalid icon") );
 
-    for( i = 0; i < max; ++i )
+    AllocExclusive();
+
+    wxIconArray& iconArray = M_ICONBUNDLEDATA->m_icons;
+
+    // replace existing icon with the same size if we already have it
+    const size_t count = iconArray.size();
+    for ( size_t i = 0; i < count; ++i )
     {
-        wxIcon& tmp = m_icons[i];
-        if( tmp.Ok() && tmp.GetWidth() == icon.GetWidth() &&
-            tmp.GetHeight() == icon.GetHeight() )
+        wxIcon& tmp = iconArray[i];
+        if ( tmp.Ok() &&
+                tmp.GetWidth() == icon.GetWidth() &&
+                tmp.GetHeight() == icon.GetHeight() )
         {
             tmp = icon;
             return;
         }
     }
 
-    m_icons.Add( icon );
+    // if we don't, add an icon with new size
+    iconArray.Add(icon);
 }
+
+size_t wxIconBundle::GetIconCount() const
+{
+    return M_ICONBUNDLEDATA->m_icons.size();
+}
+
+wxIcon wxIconBundle::GetIconByIndex(size_t n) const
+{
+    return M_ICONBUNDLEDATA->m_icons[n];
+}
+
diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp
index f47a53f8b8..b97cae2363 100644
--- a/src/gtk/toplevel.cpp
+++ b/src/gtk/toplevel.cpp
@@ -1175,7 +1175,13 @@ void wxTopLevelWindowGTK::SetTitle( const wxString &title )
 
 void wxTopLevelWindowGTK::SetIcon( const wxIcon &icon )
 {
-    SetIcons( wxIconBundle( icon ) );
+    // passing wxNullIcon to SetIcon() is possible (it means that we shouldn't
+    // have any icon), but adding an invalid icon to wxIconBundle is not
+    wxIconBundle icons;
+    if ( icon.Ok() )
+        icons.AddIcon(icon);
+
+    SetIcons(icons);
 }
 
 void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
@@ -1185,15 +1191,13 @@ void wxTopLevelWindowGTK::SetIcons( const wxIconBundle &icons )
     wxTopLevelWindowBase::SetIcons( icons );
 
     GList *list = NULL;
-    size_t max = icons.m_icons.GetCount();
 
-    for (size_t i = 0; i < max; i++)
+    const size_t numIcons = icons.GetIconCount();
+    for ( size_t i = 0; i < numIcons; i++ )
     {
-        if (icons.m_icons[i].Ok())
-        {
-            list = g_list_prepend(list, icons.m_icons[i].GetPixbuf());
-        }
+        list = g_list_prepend(list, icons.GetIconByIndex(i).GetPixbuf());
     }
+
     gtk_window_set_icon_list(GTK_WINDOW(m_widget), list);
     g_list_free(list);
 }
diff --git a/src/mac/carbon/artmac.cpp b/src/mac/carbon/artmac.cpp
new file mode 100644
index 0000000000..466ba9be56
--- /dev/null
+++ b/src/mac/carbon/artmac.cpp
@@ -0,0 +1,108 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        src/mac/carbon/artmac.cpp
+// Purpose:     wxArtProvider instance with native Mac stock icons
+// Author:      Alan Shouls
+// Created:     2006-10-30
+// RCS-ID:      $Id$
+// Copyright:   (c) wxWindows team
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// ---------------------------------------------------------------------------
+// headers
+// ---------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#if defined(__BORLANDC__)
+    #pragma hdrstop
+#endif
+
+#ifndef WX_PRECOMP
+    #include "wx/image.h"
+#endif
+
+#include "wx/artprov.h"
+#include "wx/image.h"
+
+// ----------------------------------------------------------------------------
+// wxMacArtProvider
+// ----------------------------------------------------------------------------
+
+class wxMacArtProvider : public wxArtProvider
+{
+protected:
+    virtual wxBitmap CreateBitmap(const wxArtID& id, const wxArtClient& client,
+                                  const wxSize& size);
+    virtual wxIconBundle CreateIconBundle(const wxArtID& id,
+                                          const wxArtClient& client);
+};
+
+/* static */ void wxArtProvider::InitNativeProvider()
+{
+    wxArtProvider::Push(new wxMacArtProvider);
+}
+
+// ----------------------------------------------------------------------------
+// helper macros
+// ----------------------------------------------------------------------------
+
+#define CREATE_STD_ICON(iconId, xpmRc) \
+    { \
+        wxIconBundle icon(_T(iconId), wxBITMAP_TYPE_ICON_RESOURCE); \
+        return icon; \
+    }
+
+// Macro used in CreateBitmap to get wxICON_FOO icons:
+#define ART_MSGBOX(artId, iconId, xpmRc) \
+    if ( id == artId ) \
+    { \
+        CREATE_STD_ICON(#iconId, xpmRc) \
+    }
+
+static wxIconBundle wxMacArtProvider_CreateIconBundle(const wxArtID& id)
+{
+    ART_MSGBOX(wxART_ERROR,       wxICON_ERROR,       error)
+    ART_MSGBOX(wxART_INFORMATION, wxICON_INFORMATION, info)
+    ART_MSGBOX(wxART_WARNING,     wxICON_WARNING,     warning)
+    ART_MSGBOX(wxART_QUESTION,    wxICON_QUESTION,    question)
+
+    ART_MSGBOX(wxART_FOLDER,      wxICON_FOLDER,      folder)
+    ART_MSGBOX(wxART_FOLDER_OPEN, wxICON_FOLDER_OPEN, folder_open)
+    ART_MSGBOX(wxART_NORMAL_FILE, wxICON_NORMAL_FILE, deffile)
+
+    return wxNullIconBundle;
+}
+
+// ----------------------------------------------------------------------------
+// CreateIconBundle
+// ----------------------------------------------------------------------------
+
+wxIconBundle wxMacArtProvider::CreateIconBundle(const wxArtID& id, const wxArtClient& client)
+{
+    // On the Mac folders in lists are always drawn closed, so if an open
+    // folder icon is asked for we will ask for a closed one in its place
+    if ( client == wxART_LIST && id == wxART_FOLDER_OPEN )
+        return wxMacArtProvider_CreateIconBundle(wxART_FOLDER);
+
+    return wxMacArtProvider_CreateIconBundle(id);
+}
+
+// ----------------------------------------------------------------------------
+// CreateBitmap
+// ----------------------------------------------------------------------------
+
+wxBitmap wxMacArtProvider::CreateBitmap(const wxArtID& id,
+                                        const wxArtClient& client,
+                                        const wxSize& reqSize)
+{
+    wxIconBundle ic(CreateIconBundle(id, client));
+    if (ic.IsOk())
+    {
+        wxIcon theIcon(ic.GetIcon(reqSize));
+        return wxBitmap(theIcon);
+    }
+
+    return wxNullBitmap;
+}
diff --git a/src/mac/carbon/icon.cpp b/src/mac/carbon/icon.cpp
index 7084b59cfc..68e908bf25 100644
--- a/src/mac/carbon/icon.cpp
+++ b/src/mac/carbon/icon.cpp
@@ -53,6 +53,18 @@ wxIcon::wxIcon(
     LoadFile( icon_file, (wxBitmapType) flags, desiredWidth, desiredHeight );
 }
 
+wxIcon::wxIcon(WXHICON icon, const wxSize& size)
+      : wxGDIObject()
+{
+    // as the icon owns that ref, we have to acquire it as well
+    if (icon)
+        AcquireIconRef( (IconRef) icon ) ;
+
+    m_refData = new wxIconRefData( icon ) ;
+    M_ICONDATA->SetWidth( size.x ) ;
+    M_ICONDATA->SetHeight( size.y ) ;
+}
+
 wxIcon::~wxIcon()
 {
 }
@@ -126,6 +138,18 @@ bool wxIcon::LoadFile(
         {
             theId = kAlertStopIcon ;
         }
+        else if ( filename == wxT("wxICON_FOLDER") )
+        {
+            theId = kGenericFolderIcon ;
+        }
+        else if ( filename == wxT("wxICON_FOLDER_OPEN") )
+        {
+            theId = kOpenFolderIcon ;
+        }
+        else if ( filename == wxT("wxICON_NORMAL_FILE") )
+        {
+            theId = kGenericDocumentIcon ;
+        }
         else
         {
 #if 0
diff --git a/src/unix/utilsx11.cpp b/src/unix/utilsx11.cpp
index f6627e6e69..67e641c3cb 100644
--- a/src/unix/utilsx11.cpp
+++ b/src/unix/utilsx11.cpp
@@ -106,31 +106,32 @@ private:
 // Setting icons for window manager:
 // ----------------------------------------------------------------------------
 
-void wxSetIconsX11( WXDisplay* display, WXWindow window,
-                    const wxIconBundle& ib )
+void
+wxSetIconsX11(WXDisplay* display, WXWindow window, const wxIconBundle& ib)
 {
 #if !wxUSE_NANOX
     size_t size = 0;
-    size_t i, max = ib.m_icons.GetCount();
 
-    for( i = 0; i < max; ++i )
-        if( ib.m_icons[i].Ok() )
-            size += 2 + ib.m_icons[i].GetWidth() * ib.m_icons[i].GetHeight();
+    const size_t numIcons = ib.GetIconCount();
+    for ( size_t i = 0; i < numIcons; ++i )
+    {
+        const wxIcon icon = ib.GetIconByIndex(i);
+
+        size += 2 + icon.GetWidth() * icon.GetHeight();
+    }
 
     wxMAKE_ATOM(_NET_WM_ICON, (Display*)display);
 
-    if( size > 0 )
+    if ( size > 0 )
     {
-//       The code below is correct for 64-bit machines also.
-//       wxUint32* data = new wxUint32[size];
-//       wxUint32* ptr = data;
         unsigned long* data = new unsigned long[size];
         unsigned long* ptr = data;
 
-        for( i = 0; i < max; ++i )
+        for ( size_t i = 0; i < numIcons; ++i )
         {
-            const wxImage image = ib.m_icons[i].ConvertToImage();
-            int width = image.GetWidth(), height = image.GetHeight();
+            const wxImage image = ib.GetIconByIndex(i).ConvertToImage();
+            int width = image.GetWidth(),
+                height = image.GetHeight();
             unsigned char* imageData = image.GetData();
             unsigned char* imageDataEnd = imageData + ( width * height * 3 );
             bool hasMask = image.HasMask();
@@ -153,7 +154,8 @@ void wxSetIconsX11( WXDisplay* display, WXWindow window,
             *ptr++ = width;
             *ptr++ = height;
 
-            while( imageData < imageDataEnd ) {
+            while ( imageData < imageDataEnd )
+            {
                 r = imageData[0];
                 g = imageData[1];
                 b = imageData[2];
-- 
2.50.0

