+
+// ----------------------------------------------------------------------------
+// wxFileIconsTable icons
+// ----------------------------------------------------------------------------
+
+/* Open folder */
+static const char * file_icons_tbl_folder_open_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"16 16 6 1",
+/* colors */
+" s None c None",
+". c #000000",
+"+ c #c0c0c0",
+"@ c #808080",
+"# c #ffff00",
+"$ c #ffffff",
+/* pixels */
+" ",
+" @@@@@ ",
+" @$$$$$@ ",
+" @$#+#+#$@@@@@@ ",
+" @$+#+#+$$$$$$@.",
+" @$#+#+#+#+#+#@.",
+"@@@@@@@@@@@@@#@.",
+"@$$$$$$$$$$@@+@.",
+"@$#+#+#+#+##.@@.",
+" @$#+#+#+#+#+.@.",
+" @$+#+#+#+#+#.@.",
+" @$+#+#+#+##@..",
+" @@@@@@@@@@@@@.",
+" .............",
+" ",
+" "};
+
+/* Computer */
+static const char * file_icons_tbl_computer_xpm[] = {
+"16 16 7 1",
+" s None c None",
+". c #808080",
+"X c #c0c0c0",
+"o c Black",
+"O c Gray100",
+"+ c #008080",
+"@ c Blue",
+" ........... ",
+" .XXXXXXXXXX.o",
+" .OOOOOOOOO..o",
+" .OoooooooX..o",
+" .Oo+...@+X..o",
+" .Oo+XXX.+X..o",
+" .Oo+....+X..o",
+" .Oo++++++X..o",
+" .OXXXXXXXX.oo",
+" ..........o.o",
+" ...........Xo",
+" .XXXXXXXXXX.o",
+" .o.o.o.o.o...o",
+" .oXoXoXoXoXo.o ",
+".XOXXXXXXXXX.o ",
+"............o "};
+
+/* Drive */
+static const char * file_icons_tbl_drive_xpm[] = {
+"16 16 7 1",
+" s None c None",
+". c #808080",
+"X c #c0c0c0",
+"o c Black",
+"O c Gray100",
+"+ c Green",
+"@ c #008000",
+" ",
+" ",
+" ",
+" ",
+" ............. ",
+" .XXXXXXXXXXXX.o",
+".OOOOOOOOOOOO..o",
+".XXXXXXXXX+@X..o",
+".XXXXXXXXXXXX..o",
+".X..........X..o",
+".XOOOOOOOOOOX..o",
+"..............o ",
+" ooooooooooooo ",
+" ",
+" ",
+" "};
+
+/* CD-ROM */
+static const char *file_icons_tbl_cdrom_xpm[] = {
+"16 16 10 1",
+" s None c None",
+". c #808080",
+"X c #c0c0c0",
+"o c Yellow",
+"O c Blue",
+"+ c Black",
+"@ c Gray100",
+"# c #008080",
+"$ c Green",
+"% c #008000",
+" ... ",
+" ..XoX.. ",
+" .O.XoXXX+ ",
+" ...O.oXXXX+ ",
+" .O..X.XXXX+ ",
+" ....X.+..XXX+",
+" .XXX.+@+.XXX+",
+" .X@XX.+.X@@X+",
+" .....X...#XX@+ ",
+".@@@...XXo.O@X+ ",
+".@XXX..XXoXOO+ ",
+".@++++..XoX+++ ",
+".@$%@@XX+++X.+ ",
+".............+ ",
+" ++++++++++++ ",
+" "};
+
+/* Floppy */
+static const char * file_icons_tbl_floppy_xpm[] = {
+"16 16 7 1",
+" s None c None",
+". c #808080",
+"X c Gray100",
+"o c #c0c0c0",
+"O c Black",
+"+ c Cyan",
+"@ c Red",
+" ......X",
+" .ooooooO",
+" .+++++OO",
+" .++++++O",
+" .++++++O",
+" .ooooooO",
+" .......o....oO",
+" .oooooo.o.O.XoO",
+".XXXXXXXXOOOOOO ",
+".ooooooooo@o..O ",
+".ooo....oooo..O ",
+".o..OOOO...o..O ",
+".oooXXXXoooo..O ",
+".............O ",
+" OOOOOOOOOOOO ",
+" "};
+
+/* Removeable */
+static const char * file_icons_tbl_removeable_xpm[] = {
+"16 16 7 1",
+" s None c None",
+". c #808080",
+"X c #c0c0c0",
+"o c Black",
+"O c Gray100",
+"+ c Red",
+"@ c #800000",
+" ",
+" ",
+" ",
+" ............. ",
+" .XXXXXXXXXXXX.o",
+".OOOOOOOOOOOO..o",
+".OXXXXXXXXXXX..o",
+".O+@.oooooo.X..o",
+".OXXOooooooOX..o",
+".OXXXOOOOOOXX..o",
+".OXXXXXXXXXXX..o",
+".O............o ",
+" ooooooooooooo ",
+" ",
+" ",
+" "};
+
+// ----------------------------------------------------------------------------
+// wxFileIconsTable & friends
+// ----------------------------------------------------------------------------
+
+// global instance of a wxFileIconsTable
+wxFileIconsTable* wxTheFileIconsTable = (wxFileIconsTable *)NULL;
+
+// A module to allow icons table cleanup
+
+class wxFileIconsTableModule: public wxModule
+{
+DECLARE_DYNAMIC_CLASS(wxFileIconsTableModule)
+public:
+ wxFileIconsTableModule() {}
+ bool OnInit() { wxTheFileIconsTable = new wxFileIconsTable; return TRUE; }
+ void OnExit()
+ {
+ if (wxTheFileIconsTable)
+ {
+ delete wxTheFileIconsTable;
+ wxTheFileIconsTable = NULL;
+ }
+ }
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxFileIconsTableModule, wxModule)
+
+class wxFileIconEntry : public wxObject
+{
+public:
+ wxFileIconEntry(int i) { id = i; }
+
+ int id;
+};
+
+wxFileIconsTable::wxFileIconsTable()
+{
+ m_HashTable = NULL;
+ m_smallImageList = NULL;
+}
+
+wxFileIconsTable::~wxFileIconsTable()
+{
+ if (m_HashTable)
+ {
+ WX_CLEAR_HASH_TABLE(*m_HashTable);
+ delete m_HashTable;
+ }
+ if (m_smallImageList) delete m_smallImageList;
+}
+
+// delayed initialization - wait until first use (wxArtProv not created yet)
+void wxFileIconsTable::Create()
+{
+ wxCHECK_RET(!m_smallImageList && !m_HashTable, wxT("creating icons twice"));
+ m_HashTable = new wxHashTable(wxKEY_STRING);
+ m_smallImageList = new wxImageList(16, 16);
+
+ // folder:
+ m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_FOLDER, wxART_CMN_DIALOG));
+ // folder_open
+ m_smallImageList->Add(wxIcon(file_icons_tbl_folder_open_xpm));
+ // computer
+ m_smallImageList->Add(wxIcon(file_icons_tbl_computer_xpm));
+ // drive
+ m_smallImageList->Add(wxIcon(file_icons_tbl_drive_xpm));
+ // cdrom
+ m_smallImageList->Add(wxIcon(file_icons_tbl_cdrom_xpm));
+ // floppy
+ m_smallImageList->Add(wxIcon(file_icons_tbl_floppy_xpm));
+ // removeable
+ m_smallImageList->Add(wxIcon(file_icons_tbl_removeable_xpm));
+ // file
+ m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_CMN_DIALOG));
+ // executable
+ if (GetIconID(wxEmptyString, _T("application/x-executable")) == file)
+ {
+ m_smallImageList->Add(wxArtProvider::GetBitmap(wxART_EXECUTABLE_FILE, wxART_CMN_DIALOG));
+ delete m_HashTable->Get(_T("exe"));
+ m_HashTable->Delete(_T("exe"));
+ m_HashTable->Put(_T("exe"), new wxFileIconEntry(executable));
+ }
+ /* else put into list by GetIconID
+ (KDE defines application/x-executable for *.exe and has nice icon)
+ */
+}
+
+wxImageList *wxFileIconsTable::GetSmallImageList()
+{
+ if (!m_smallImageList)
+ Create();
+
+ return m_smallImageList;
+}
+
+#if wxUSE_MIMETYPE
+// VS: we don't need this function w/o wxMimeTypesManager because we'll only have
+// one icon and we won't resize it
+
+static wxBitmap CreateAntialiasedBitmap(const wxImage& img)
+{
+ wxImage smallimg (16, 16);
+ unsigned char *p1, *p2, *ps;
+ unsigned char mr = img.GetMaskRed(),
+ mg = img.GetMaskGreen(),
+ mb = img.GetMaskBlue();
+
+ unsigned x, y;
+ unsigned sr, sg, sb, smask;
+
+ p1 = img.GetData(), p2 = img.GetData() + 3 * 32, ps = smallimg.GetData();
+ smallimg.SetMaskColour(mr, mr, mr);
+
+ for (y = 0; y < 16; y++)
+ {
+ for (x = 0; x < 16; x++)
+ {
+ sr = sg = sb = smask = 0;
+ if (p1[0] != mr || p1[1] != mg || p1[2] != mb)
+ sr += p1[0], sg += p1[1], sb += p1[2];
+ else smask++;
+ p1 += 3;
+ if (p1[0] != mr || p1[1] != mg || p1[2] != mb)
+ sr += p1[0], sg += p1[1], sb += p1[2];
+ else smask++;
+ p1 += 3;
+ if (p2[0] != mr || p2[1] != mg || p2[2] != mb)
+ sr += p2[0], sg += p2[1], sb += p2[2];
+ else smask++;
+ p2 += 3;
+ if (p2[0] != mr || p2[1] != mg || p2[2] != mb)
+ sr += p2[0], sg += p2[1], sb += p2[2];
+ else smask++;
+ p2 += 3;
+
+ if (smask > 2)
+ ps[0] = ps[1] = ps[2] = mr;
+ else
+ ps[0] = sr >> 2, ps[1] = sg >> 2, ps[2] = sb >> 2;
+ ps += 3;
+ }
+ p1 += 32 * 3, p2 += 32 * 3;
+ }
+
+ return wxBitmap(smallimg);
+}
+
+// finds empty borders and return non-empty area of image:
+static wxImage CutEmptyBorders(const wxImage& img)
+{
+ unsigned char mr = img.GetMaskRed(),
+ mg = img.GetMaskGreen(),
+ mb = img.GetMaskBlue();
+ unsigned char *dt = img.GetData(), *dttmp;
+ unsigned w = img.GetWidth(), h = img.GetHeight();
+
+ unsigned top, bottom, left, right, i;
+ bool empt;
+
+#define MK_DTTMP(x,y) dttmp = dt + ((x + y * w) * 3)
+#define NOEMPTY_PIX(empt) if (dttmp[0] != mr || dttmp[1] != mg || dttmp[2] != mb) {empt = FALSE; break;}
+
+ for (empt = TRUE, top = 0; empt && top < h; top++)
+ {
+ MK_DTTMP(0, top);
+ for (i = 0; i < w; i++, dttmp+=3)
+ NOEMPTY_PIX(empt)
+ }
+ for (empt = TRUE, bottom = h-1; empt && bottom > top; bottom--)
+ {
+ MK_DTTMP(0, bottom);
+ for (i = 0; i < w; i++, dttmp+=3)
+ NOEMPTY_PIX(empt)
+ }
+ for (empt = TRUE, left = 0; empt && left < w; left++)
+ {
+ MK_DTTMP(left, 0);
+ for (i = 0; i < h; i++, dttmp+=3*w)
+ NOEMPTY_PIX(empt)
+ }
+ for (empt = TRUE, right = w-1; empt && right > left; right--)
+ {
+ MK_DTTMP(right, 0);
+ for (i = 0; i < h; i++, dttmp+=3*w)
+ NOEMPTY_PIX(empt)
+ }
+ top--, left--, bottom++, right++;
+
+ return img.GetSubImage(wxRect(left, top, right - left + 1, bottom - top + 1));
+}
+#endif // wxUSE_MIMETYPE
+
+int wxFileIconsTable::GetIconID(const wxString& extension, const wxString& mime)
+{
+ if (!m_smallImageList)
+ Create();
+
+#if wxUSE_MIMETYPE
+ if (!extension.IsEmpty())
+ {
+ wxFileIconEntry *entry = (wxFileIconEntry*) m_HashTable->Get(extension);
+ if (entry) return (entry -> id);
+ }
+
+ wxFileType *ft = (mime.IsEmpty()) ?
+ wxTheMimeTypesManager -> GetFileTypeFromExtension(extension) :
+ wxTheMimeTypesManager -> GetFileTypeFromMimeType(mime);
+
+ wxIconLocation iconLoc;
+ wxIcon ic;
+ if ( ft && ft->GetIcon(&iconLoc) )
+ {
+ ic = wxIcon(iconLoc);
+ }
+
+ delete ft;
+
+ if ( !ic.Ok() )
+ {
+ int newid = file;
+ m_HashTable->Put(extension, new wxFileIconEntry(newid));
+ return newid;
+ }
+
+ wxBitmap tmpBmp;
+ tmpBmp.CopyFromIcon(ic);
+ wxImage img = tmpBmp.ConvertToImage();
+
+ int id = m_smallImageList->GetImageCount();
+ if (img.GetWidth() == 16 && img.GetHeight() == 16)
+ m_smallImageList->Add(wxBitmap(img));
+ else
+ {
+ if (img.GetWidth() != 32 || img.GetHeight() != 32)
+ m_smallImageList->Add(CreateAntialiasedBitmap(CutEmptyBorders(img).Rescale(32, 32)));
+ else
+ m_smallImageList->Add(CreateAntialiasedBitmap(img));
+ }
+ m_HashTable->Put(extension, new wxFileIconEntry(id));
+ return id;
+
+#else // !wxUSE_MIMETYPE
+
+ if (extension == wxT("exe"))
+ return executable;
+ else
+ return file;
+#endif // wxUSE_MIMETYPE/!wxUSE_MIMETYPE
+}
+