source: filezilla/trunk/fuentes/src/interface/themeprovider.cpp @ 3185

Last change on this file since 3185 was 3185, checked in by jrpelegrina, 2 years ago

Update new version: 3.15.02

File size: 8.2 KB
Line 
1#include <filezilla.h>
2#include "themeprovider.h"
3#include "filezillaapp.h"
4#include "Options.h"
5#include "xmlfunctions.h"
6
7#include <wx/animate.h>
8
9#include <utility>
10
11static CThemeProvider* instance = 0;
12
13CThemeProvider::CThemeProvider()
14{
15        wxArtProvider::Push(this);
16
17        m_themePath = GetThemePath();
18
19        RegisterOption(OPTION_THEME);
20
21        if( !instance )
22                instance = this;
23}
24
25CThemeProvider::~CThemeProvider()
26{
27        if( instance == this ) {
28                instance = 0;
29        }
30}
31
32CThemeProvider* CThemeProvider::Get()
33{
34        return instance;
35}
36
37static wxString SubdirFromSize(const int size)
38{
39        return wxString::Format(_T("%dx%d/"), size, size);
40}
41
42std::list<wxString> CThemeProvider::GetSearchDirs(const wxSize& bestSize)
43{
44        // Sort order:
45        // - Current theme before general resource dir
46        // - Try current size first
47        // - Then try scale down next larger icon
48        // - Then try scaling up next smaller icon
49
50
51        int sizes[] = { 48,32,24,20,16 };
52
53        std::list<wxString> sizeStrings;
54
55        for (auto const& size : sizes) {
56                if (size < bestSize.GetWidth())
57                        sizeStrings.push_back(SubdirFromSize(size));
58                else if (size > bestSize.GetWidth())
59                        sizeStrings.push_front(SubdirFromSize(size));
60        }
61        sizeStrings.push_front(SubdirFromSize(bestSize.GetWidth()));
62
63        std::list<wxString> dirs;
64        for (auto const& size : sizeStrings) {
65                dirs.push_back(m_themePath + size);
66        }
67
68        CLocalPath const resourceDir(wxGetApp().GetResourceDir());
69        for (auto const& size : sizeStrings) {
70                dirs.push_back(resourceDir.GetPath() + size);
71        }
72
73        return dirs;
74}
75
76wxBitmap CThemeProvider::CreateBitmap(const wxArtID& id, const wxArtClient& /*client*/, const wxSize& size)
77{
78        if (id.Left(4) != _T("ART_"))
79                return wxNullBitmap;
80        wxASSERT(size.GetWidth() == size.GetHeight());
81
82        std::list<wxString> dirs = GetSearchDirs(size);
83
84        // The ART_* IDs are always given in uppercase ASCII,
85        // all filenames used by FileZilla for the resources
86        // are lowercase ASCII. Locale-independent transformation
87        // needed e.g. if using Turkish locale.
88        wxString name = fz::str_tolower_ascii(id.Mid(4));
89       
90        wxLogNull logNull;
91
92        for (auto const& dir : dirs) {
93                wxString fileName = dir + name + _T(".png");
94
95                // MSW toolbar only greys out disabled buttons in a visually
96                // pleasing way if the bitmap has an alpha channel.
97                wxImage img(fileName, wxBITMAP_TYPE_PNG);
98                if (!img.Ok())
99                        continue;
100
101                if (img.HasMask() && !img.HasAlpha())
102                        img.InitAlpha();
103                if (size.IsFullySpecified())
104                        img.Rescale(size.x, size.y, wxIMAGE_QUALITY_HIGH);
105                return wxBitmap(img);
106        }
107
108        return wxNullBitmap;
109}
110
111wxAnimation CThemeProvider::CreateAnimation(const wxArtID& id, const wxSize& size)
112{
113        if (id.Left(4) != _T("ART_"))
114                return wxAnimation();
115        wxASSERT(size.GetWidth() == size.GetHeight());
116
117        std::list<wxString> dirs = GetSearchDirs(size);
118
119        // The ART_* IDs are always given in uppercase ASCII,
120        // all filenames used by FileZilla for the resources
121        // are lowercase ASCII. Locale-independent transformation
122        // needed e.g. if using Turkish locale.
123        wxString name = fz::str_tolower_ascii(id.Mid(4));
124
125        wxLogNull logNull;
126
127        for (auto const& dir : dirs) {
128                wxString fileName = dir + name + _T(".gif");
129
130                wxAnimation a(fileName);
131                if( a.IsOk() ) {
132                        return a;
133                }
134        }
135
136        return wxAnimation();
137}
138
139std::vector<wxString> CThemeProvider::GetThemes()
140{
141        std::vector<wxString> themes;
142
143        CLocalPath const resourceDir = wxGetApp().GetResourceDir();
144        if (wxFileName::FileExists(resourceDir.GetPath() + _T("theme.xml")))
145                themes.push_back(wxString());
146
147        wxDir dir(resourceDir.GetPath());
148        bool found;
149        wxString subdir;
150        for (found = dir.GetFirst(&subdir, _T("*"), wxDIR_DIRS); found; found = dir.GetNext(&subdir)) {
151                if (wxFileName::FileExists(resourceDir.GetPath() + subdir + _T("/") + _T("theme.xml")))
152                        themes.push_back(subdir + _T("/"));
153        }
154
155        return themes;
156}
157
158std::vector<std::unique_ptr<wxBitmap>> CThemeProvider::GetAllImages(const wxString& theme, const wxSize& size)
159{
160        wxString path = wxGetApp().GetResourceDir().GetPath() + theme + _T("/");
161
162        wxLogNull log;
163
164        wxString strSize = wxString::Format(_T("%dx%d/"), size.GetWidth(), size.GetHeight());
165        if (wxDir::Exists(path + strSize)) {
166                path += strSize;
167        }
168        else {
169                if (size.GetWidth() > 32)
170                        path += _T("48x48/");
171                else if (size.GetWidth() > 16)
172                        path += _T("32x32/");
173                else
174                        path += _T("16x16/");
175        }
176
177        std::vector<std::unique_ptr<wxBitmap>> bitmaps;
178
179        if (!wxDir::Exists(path))
180                return bitmaps;
181
182        wxDir dir(path);
183        if (!dir.IsOpened())
184                return bitmaps;
185
186        wxString file;
187        for (bool found = dir.GetFirst(&file, _T("*.png")); found; found = dir.GetNext(&file)) {
188                if (file.Right(13) == _T("_disabled.png"))
189                        continue;
190
191                wxFileName fn(path, file);
192                std::unique_ptr<wxBitmap> bmp(new wxBitmap);
193                if (bmp->LoadFile(fn.GetFullPath(), wxBITMAP_TYPE_PNG)) {
194                        bitmaps.push_back(std::move(bmp));
195                }
196        }
197        return bitmaps;
198}
199
200bool CThemeProvider::GetThemeData(const wxString& themePath, wxString& name, wxString& author, wxString& email)
201{
202        wxString const file(wxGetApp().GetResourceDir().GetPath() + themePath + _T("theme.xml"));
203        CXmlFile xml(file);
204        auto theme = xml.Load().child("Theme");
205        if (!theme)
206                return false;
207
208        name = GetTextElement(theme, "Name");
209        author = GetTextElement(theme, "Author");
210        email = GetTextElement(theme, "Mail");
211        return true;
212}
213
214std::vector<wxString> CThemeProvider::GetThemeSizes(const wxString& themePath)
215{
216        std::vector<wxString> sizes;
217
218        wxString const file(wxGetApp().GetResourceDir().GetPath() + themePath + _T("theme.xml"));
219        CXmlFile xml(file);
220        auto theme = xml.Load().child("Theme");
221        if (!theme)
222                return sizes;
223
224        for (auto xSize = theme.child("size"); xSize; xSize = xSize.next_sibling("size")) {
225                wxString size = GetTextElement(xSize);
226                if (size.empty())
227                        continue;
228                sizes.push_back(size);
229        }
230
231        return sizes;
232}
233
234wxIconBundle CThemeProvider::GetIconBundle(const wxArtID& id, const wxArtClient&)
235{
236        wxIconBundle iconBundle;
237
238        if (id.Left(4) != _T("ART_"))
239                return iconBundle;
240
241        wxString name = fz::str_tolower_ascii(id.Mid(4));
242
243        const wxChar* dirs[] = { _T("16x16/"), _T("32x32/"), _T("48x48/") };
244
245        CLocalPath const resourcePath = wxGetApp().GetResourceDir();
246
247        for (auto const& dir : dirs ) {
248                wxString file = resourcePath.GetPath() + dir + name + _T(".png");
249                if (!wxFileName::FileExists(file))
250                        continue;
251
252                iconBundle.AddIcon(wxIcon(file, wxBITMAP_TYPE_PNG));
253        }
254
255        return iconBundle;
256}
257
258bool CThemeProvider::ThemeHasSize(const wxString& themePath, const wxString& size)
259{
260        wxString const file(wxGetApp().GetResourceDir().GetPath() + themePath + _T("theme.xml"));
261        CXmlFile xml(file);
262        auto theme = xml.Load().child("Theme");
263        if (!theme) {
264                return false;
265        }
266
267        for (auto xSize = theme.child("size"); xSize; xSize = xSize.next_sibling("size")) {
268                wxString s = GetTextElement(xSize);
269                if (size == s) {
270                        return true;
271                }
272        }
273
274        return false;
275}
276
277wxString CThemeProvider::GetThemePath()
278{
279        CLocalPath const resourceDir = wxGetApp().GetResourceDir();
280        wxString themePath = resourceDir.GetPath() + COptions::Get()->GetOption(OPTION_THEME);
281        if (wxFile::Exists(themePath + _T("theme.xml")))
282                return themePath;
283
284        themePath = resourceDir.GetPath() + _T("opencrystal/");
285        if (wxFile::Exists(themePath + _T("theme.xml")))
286                return themePath;
287
288        wxASSERT(wxFile::Exists(resourceDir.GetPath() + _T("theme.xml")));
289        return resourceDir.GetPath();
290}
291
292void CThemeProvider::OnOptionsChanged(changed_options_t const&)
293{
294        m_themePath = GetThemePath();
295
296        wxArtProvider::Remove(this);
297        wxArtProvider::Push(this);
298}
299
300wxSize CThemeProvider::GetIconSize(enum iconSize size)
301{
302        int s;
303        if (size == iconSizeSmall) {
304                s = wxSystemSettings::GetMetric(wxSYS_SMALLICON_X);
305                if (s <= 0)
306                        s = 16;
307        }
308        else if (size == iconSize24) {
309                s = wxSystemSettings::GetMetric(wxSYS_SMALLICON_X);
310                if (s <= 0) {
311                        s = 24;
312                }
313                else {
314                        s += s/2;
315                }
316        }
317        else if (size == iconSizeLarge) {
318                s = wxSystemSettings::GetMetric(wxSYS_ICON_X);
319                if (s <= 0)
320                        s = 48;
321                else
322                        s += s/2;
323        }
324        else {
325                s = wxSystemSettings::GetMetric(wxSYS_ICON_X);
326                if (s <= 0)
327                        s = 32;
328        }
329
330        return wxSize(s, s);
331}
332
333wxSize CThemeProvider::GetIconSize(wxString const& str)
334{
335        wxSize iconSize;
336        if (str == _T("24x24"))
337                return CThemeProvider::GetIconSize(iconSize24);
338        else if (str == _T("32x32"))
339                iconSize = CThemeProvider::GetIconSize(iconSizeNormal);
340        else if (str == _T("48x48"))
341                iconSize = CThemeProvider::GetIconSize(iconSizeLarge);
342        else
343                iconSize = CThemeProvider::GetIconSize(iconSizeSmall);
344
345        return iconSize;
346}
Note: See TracBrowser for help on using the repository browser.