source: filezilla/trunk/fuentes/src/interface/systemimagelist.cpp @ 130

Last change on this file since 130 was 130, checked in by jrpelegrina, 3 years ago

First release to xenial

File size: 6.5 KB
Line 
1#include <filezilla.h>
2#include "systemimagelist.h"
3#ifdef __WXMSW__
4#include "shlobj.h"
5
6        // Once again lots of the shell stuff is missing in MinGW's headers
7        #ifndef IDO_SHGIOI_LINK
8                #define IDO_SHGIOI_LINK 0x0FFFFFFE
9        #endif
10        #ifndef SHGetIconOverlayIndex
11                extern "C" int WINAPI SHGetIconOverlayIndexW(LPCWSTR pszIconPath, int iIconIndex);
12                extern "C" int WINAPI SHGetIconOverlayIndexA(LPCSTR pszIconPath, int iIconIndex);
13                #define SHGetIconOverlayIndex SHGetIconOverlayIndexW
14        #endif
15#endif
16#ifndef __WXMSW__
17#include "themeprovider.h"
18#include <wx/rawbmp.h>
19#endif
20
21wxImageListEx::wxImageListEx()
22        : wxImageList()
23{
24}
25
26wxImageListEx::wxImageListEx(int width, int height, const bool mask /*=true*/, int initialCount /*=1*/)
27        : wxImageList(width, height, mask, initialCount)
28{
29}
30
31#ifdef __WXMSW__
32HIMAGELIST wxImageListEx::Detach()
33{
34         HIMAGELIST hImageList = (HIMAGELIST)m_hImageList;
35         m_hImageList = 0;
36         return hImageList;
37}
38#endif
39
40#ifndef __WXMSW__
41static inline void AlphaComposite_Over_Inplace(wxAlphaPixelData::Iterator &a, wxAlphaPixelData::Iterator &b)
42{
43        // Alpha compositing of a single pixel, b gets composited over a
44        // (well-known over operator), result stored in a.
45        // All RGB and A values have range from 0 to 255, RGB values aren't
46        // premultiplied by A.
47        // Safe for multiple compositions.
48
49        if (!b.Alpha())
50        {
51                // Nothing to do
52                return;
53        }
54
55        int new_alpha = a.Alpha() + b.Alpha() - a.Alpha() * b.Alpha() / 255; // Could only get 0 if both alphas were 0, caught that already.
56        a.Red() = ((int)a.Red() * (255 - b.Alpha()) * a.Alpha() / 255 + (int)b.Red() * b.Alpha()) / new_alpha;
57        a.Green() = ((int)a.Green() * (255 - b.Alpha()) * a.Alpha() / 255 + (int)b.Green() * b.Alpha()) / new_alpha;
58        a.Blue() = ((int)a.Blue() * (255 - b.Alpha()) * a.Alpha() / 255 + (int)b.Blue() * b.Alpha()) / new_alpha;
59        a.Alpha() = new_alpha;
60}
61
62static void OverlaySymlink(wxBitmap& bmp)
63{
64        // This is ugly, but apparently needed so that the data is _really_ in the right internal format
65        bmp = bmp.ConvertToImage();
66        wxBitmap symlink = wxArtProvider::GetBitmap(_T("ART_SYMLINK"),  wxART_OTHER, wxSize(bmp.GetWidth(), bmp.GetHeight())).ConvertToImage();
67
68        wxAlphaPixelData target(bmp);
69        wxAlphaPixelData source(symlink);
70
71        int sx = bmp.GetWidth();
72        if (symlink.GetWidth() < sx)
73                sx = symlink.GetWidth();
74        int sy = bmp.GetHeight();
75        if (symlink.GetHeight() < sy)
76                sy = symlink.GetHeight();
77
78        // Do some rudimentary alpha copying
79        wxAlphaPixelData::Iterator t(target);
80        wxAlphaPixelData::Iterator s(source);
81        for (int y = 0; y < sy; y++)
82        {
83                s.MoveTo(source, 0, y);
84                t.MoveTo(target, 0, y);
85                for (int x = 0; x < sx; x++, s++, t++)
86                        AlphaComposite_Over_Inplace(t, s);
87        }
88}
89#endif
90
91CSystemImageList::CSystemImageList(int size /*=-1*/)
92        : m_pImageList()
93{
94        if (size != -1)
95                CreateSystemImageList(size);
96}
97
98bool CSystemImageList::CreateSystemImageList(int size)
99{
100        if (m_pImageList)
101                return true;
102
103#ifdef __WXMSW__
104        SHFILEINFO shFinfo{};
105        wxChar buffer[MAX_PATH + 10];
106        if (!GetWindowsDirectory(buffer, MAX_PATH))
107#ifdef _tcscpy
108                _tcscpy(buffer, _T("C:\\"));
109#else
110                strcpy(buffer, _T("C:\\"));
111#endif
112
113        m_pImageList = new wxImageListEx((WXHIMAGELIST)SHGetFileInfo(buffer,
114                                                          0,
115                                                          &shFinfo,
116                                                          sizeof( shFinfo ),
117                                                          SHGFI_SYSICONINDEX |
118                                                          ((size != 16) ? SHGFI_ICON : SHGFI_SMALLICON) ));
119#else
120        m_pImageList = new wxImageListEx(size, size);
121
122        wxBitmap file = wxArtProvider::GetBitmap(_T("ART_FILE"),  wxART_OTHER, wxSize(size, size));
123        wxBitmap folderclosed = wxArtProvider::GetBitmap(_T("ART_FOLDERCLOSED"),  wxART_OTHER, wxSize(size, size));
124        wxBitmap folder = wxArtProvider::GetBitmap(_T("ART_FOLDER"),  wxART_OTHER, wxSize(size, size));
125        m_pImageList->Add(file);
126        m_pImageList->Add(folderclosed);
127        m_pImageList->Add(folder);
128        OverlaySymlink(file);
129        OverlaySymlink(folderclosed);
130        OverlaySymlink(folder);
131        m_pImageList->Add(file);
132        m_pImageList->Add(folderclosed);
133        m_pImageList->Add(folder);
134#endif
135
136        return true;
137}
138
139CSystemImageList::~CSystemImageList()
140{
141        if (!m_pImageList)
142                return;
143
144#ifdef __WXMSW__
145        m_pImageList->Detach();
146#endif
147
148        delete m_pImageList;
149
150        m_pImageList = 0;
151}
152
153#ifndef __WXMSW__
154// This function converts to the right size with the given background colour
155wxBitmap PrepareIcon(wxIcon icon, wxSize size)
156{
157        if (icon.GetWidth() == size.GetWidth() && icon.GetHeight() == size.GetHeight())
158                return icon;
159        wxBitmap bmp;
160        bmp.CopyFromIcon(icon);
161        return bmp.ConvertToImage().Rescale(size.GetWidth(), size.GetHeight());
162}
163#endif
164
165int CSystemImageList::GetIconIndex(iconType type, const wxString& fileName /*=_T("")*/, bool physical /*=true*/, bool symlink /*=false*/)
166{
167        if (!m_pImageList)
168                return -1;
169
170#ifdef __WXMSW__
171        if (fileName.empty())
172                physical = false;
173
174        SHFILEINFO shFinfo;
175        memset(&shFinfo, 0, sizeof(SHFILEINFO));
176        if (SHGetFileInfo(!fileName.empty() ? fileName : _T("{B97D3074-1830-4b4a-9D8A-17A38B074052}"),
177                (type != iconType::file) ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL,
178                &shFinfo,
179                sizeof(SHFILEINFO),
180                SHGFI_ICON | ((type == iconType::opened_dir) ? SHGFI_OPENICON : 0) | ((physical) ? 0 : SHGFI_USEFILEATTRIBUTES) ) )
181        {
182                int icon = shFinfo.iIcon;
183                // we only need the index from the system image list
184                DestroyIcon(shFinfo.hIcon);
185                return icon;
186        }
187#else
188        int icon;
189        switch (type)
190        {
191        case iconType::file:
192        default:
193                icon = symlink ? 3 : 0;
194                break;
195        case iconType::dir:
196                return symlink ? 4 : 1;
197        case iconType::opened_dir:
198                return symlink ? 5 : 2;
199        }
200
201        wxFileName fn(fileName);
202        wxString ext = fn.GetExt();
203        if (ext.empty())
204                return icon;
205
206        if (symlink)
207        {
208                auto cacheIter = m_iconCache.find(ext);
209                if (cacheIter != m_iconCache.end())
210                        return cacheIter->second;
211        }
212        else
213        {
214                auto cacheIter = m_iconSymlinkCache.find(ext);
215                if (cacheIter != m_iconSymlinkCache.end())
216                        return cacheIter->second;
217        }
218
219        wxFileType *pType = wxTheMimeTypesManager->GetFileTypeFromExtension(ext);
220        if (!pType)
221        {
222                m_iconCache[ext] = icon;
223                return icon;
224        }
225
226        wxIconLocation loc;
227        if (pType->GetIcon(&loc) && loc.IsOk())
228        {
229                wxLogNull nul;
230                wxIcon newIcon(loc);
231
232                if (newIcon.Ok())
233                {
234                        wxBitmap bmp = PrepareIcon(newIcon, CThemeProvider::GetIconSize(iconSizeSmall));
235                        if (symlink)
236                                OverlaySymlink(bmp);
237                        int index = m_pImageList->Add(bmp);
238                        if (index > 0)
239                                icon = index;
240                }
241        }
242        delete pType;
243
244        if (symlink)
245                m_iconCache[ext] = icon;
246        else
247                m_iconSymlinkCache[ext] = icon;
248        return icon;
249#endif
250        return -1;
251}
252
253#ifdef __WXMSW__
254int CSystemImageList::GetLinkOverlayIndex()
255{
256        static int overlay = -1;
257        if (overlay == -1)
258        {
259                overlay = SHGetIconOverlayIndex(0, IDO_SHGIOI_LINK);
260                if (overlay < 0)
261                        overlay = 0;
262        }
263
264        return overlay;
265}
266#endif
Note: See TracBrowser for help on using the repository browser.