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

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

First release to xenial

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        wxString name = id.Mid(4);
85
86        // The ART_* IDs are always given in uppercase ASCII,
87        // all filenames used by FileZilla for the resources
88        // are lowercase ASCII. Locale-independent transformation
89        // needed e.g. if using Turkish locale.
90        MakeLowerAscii(name);
91
92        wxLogNull logNull;
93
94        for (auto const& dir : dirs) {
95                wxString fileName = dir + name + _T(".png");
96
97                // MSW toolbar only greys out disabled buttons in a visually
98                // pleasing way if the bitmap has an alpha channel.
99                wxImage img(fileName, wxBITMAP_TYPE_PNG);
100                if (!img.Ok())
101                        continue;
102
103                if (img.HasMask() && !img.HasAlpha())
104                        img.InitAlpha();
105                if (size.IsFullySpecified())
106                        img.Rescale(size.x, size.y, wxIMAGE_QUALITY_HIGH);
107                return wxBitmap(img);
108        }
109
110        return wxNullBitmap;
111}
112
113wxAnimation CThemeProvider::CreateAnimation(const wxArtID& id, const wxSize& size)
114{
115        if (id.Left(4) != _T("ART_"))
116                return wxAnimation();
117        wxASSERT(size.GetWidth() == size.GetHeight());
118
119        std::list<wxString> dirs = GetSearchDirs(size);
120
121        wxString name = id.Mid(4);
122
123        // The ART_* IDs are always given in uppercase ASCII,
124        // all filenames used by FileZilla for the resources
125        // are lowercase ASCII. Locale-independent transformation
126        // needed e.g. if using Turkish locale.
127        MakeLowerAscii(name);
128
129        wxLogNull logNull;
130
131        for (auto const& dir : dirs) {
132                wxString fileName = dir + name + _T(".gif");
133
134                wxAnimation a(fileName);
135                if( a.IsOk() ) {
136                        return a;
137                }
138        }
139
140        return wxAnimation();
141}
142
143std::vector<wxString> CThemeProvider::GetThemes()
144{
145        std::vector<wxString> themes;
146
147        CLocalPath const resourceDir = wxGetApp().GetResourceDir();
148        if (wxFileName::FileExists(resourceDir.GetPath() + _T("theme.xml")))
149                themes.push_back(wxString());
150
151        wxDir dir(resourceDir.GetPath());
152        bool found;
153        wxString subdir;
154        for (found = dir.GetFirst(&subdir, _T("*"), wxDIR_DIRS); found; found = dir.GetNext(&subdir)) {
155                if (wxFileName::FileExists(resourceDir.GetPath() + subdir + _T("/") + _T("theme.xml")))
156                        themes.push_back(subdir + _T("/"));
157        }
158
159        return themes;
160}
161
162std::vector<std::unique_ptr<wxBitmap>> CThemeProvider::GetAllImages(const wxString& theme, const wxSize& size)
163{
164        wxString path = wxGetApp().GetResourceDir().GetPath() + theme + _T("/");
165
166        wxLogNull log;
167
168        wxString strSize = wxString::Format(_T("%dx%d/"), size.GetWidth(), size.GetHeight());
169        if (wxDir::Exists(path + strSize)) {
170                path += strSize;
171        }
172        else {
173                if (size.GetWidth() > 32)
174                        path += _T("48x48/");
175                else if (size.GetWidth() > 16)
176                        path += _T("32x32/");
177                else
178                        path += _T("16x16/");
179        }
180
181        std::vector<std::unique_ptr<wxBitmap>> bitmaps;
182
183        if (!wxDir::Exists(path))
184                return bitmaps;
185
186        wxDir dir(path);
187        if (!dir.IsOpened())
188                return bitmaps;
189
190        wxString file;
191        for (bool found = dir.GetFirst(&file, _T("*.png")); found; found = dir.GetNext(&file)) {
192                if (file.Right(13) == _T("_disabled.png"))
193                        continue;
194
195                wxFileName fn(path, file);
196                std::unique_ptr<wxBitmap> bmp(new wxBitmap);
197                if (bmp->LoadFile(fn.GetFullPath(), wxBITMAP_TYPE_PNG)) {
198                        bitmaps.push_back(std::move(bmp));
199                }
200        }
201        return bitmaps;
202}
203
204bool CThemeProvider::GetThemeData(const wxString& themePath, wxString& name, wxString& author, wxString& email)
205{
206        wxString const file(wxGetApp().GetResourceDir().GetPath() + themePath + _T("theme.xml"));
207        CXmlFile xml(file);
208        auto theme = xml.Load().child("Theme");
209        if (!theme)
210                return false;
211
212        name = GetTextElement(theme, "Name");
213        author = GetTextElement(theme, "Author");
214        email = GetTextElement(theme, "Mail");
215        return true;
216}
217
218std::vector<wxString> CThemeProvider::GetThemeSizes(const wxString& themePath)
219{
220        std::vector<wxString> sizes;
221
222        wxString const file(wxGetApp().GetResourceDir().GetPath() + themePath + _T("theme.xml"));
223        CXmlFile xml(file);
224        auto theme = xml.Load().child("Theme");
225        if (!theme)
226                return sizes;
227
228        for (auto xSize = theme.child("size"); xSize; xSize = xSize.next_sibling("size")) {
229                wxString size = GetTextElement(xSize);
230                if (size.empty())
231                        continue;
232                sizes.push_back(size);
233        }
234
235        return sizes;
236}
237
238wxIconBundle CThemeProvider::GetIconBundle(const wxArtID& id, const wxArtClient& client /*=wxART_OTHER*/)
239{
240        wxIconBundle iconBundle;
241
242        if (id.Left(4) != _T("ART_"))
243                return iconBundle;
244
245        wxString name = id.Mid(4);
246        MakeLowerAscii(name);
247
248        const wxChar* dirs[] = { _T("16x16/"), _T("32x32/"), _T("48x48/") };
249
250        CLocalPath const resourcePath = wxGetApp().GetResourceDir();
251
252        for (auto const& dir : dirs ) {
253                wxString file = resourcePath.GetPath() + dir + name + _T(".png");
254                if (!wxFileName::FileExists(file))
255                        continue;
256
257                iconBundle.AddIcon(wxIcon(file, wxBITMAP_TYPE_PNG));
258        }
259
260        return iconBundle;
261}
262
263bool CThemeProvider::ThemeHasSize(const wxString& themePath, const wxString& size)
264{
265        wxString const file(wxGetApp().GetResourceDir().GetPath() + themePath + _T("theme.xml"));
266        CXmlFile xml(file);
267        auto theme = xml.Load().child("Theme");
268        if (!theme) {
269                return false;
270        }
271
272        for (auto xSize = theme.child("size"); xSize; xSize = xSize.next_sibling("size")) {
273                wxString s = GetTextElement(xSize);
274                if (size == s) {
275                        return true;
276                }
277        }
278
279        return false;
280}
281
282wxString CThemeProvider::GetThemePath()
283{
284        CLocalPath const resourceDir = wxGetApp().GetResourceDir();
285        wxString themePath = resourceDir.GetPath() + COptions::Get()->GetOption(OPTION_THEME);
286        if (wxFile::Exists(themePath + _T("theme.xml")))
287                return themePath;
288
289        themePath = resourceDir.GetPath() + _T("opencrystal/");
290        if (wxFile::Exists(themePath + _T("theme.xml")))
291                return themePath;
292
293        wxASSERT(wxFile::Exists(resourceDir.GetPath() + _T("theme.xml")));
294        return resourceDir.GetPath();
295}
296
297void CThemeProvider::OnOptionsChanged(changed_options_t const& options)
298{
299        m_themePath = GetThemePath();
300
301        wxArtProvider::Remove(this);
302        wxArtProvider::Push(this);
303}
304
305wxSize CThemeProvider::GetIconSize(enum iconSize size)
306{
307        int s;
308        if (size == iconSizeSmall) {
309                s = wxSystemSettings::GetMetric(wxSYS_SMALLICON_X);
310                if (s <= 0)
311                        s = 16;
312        }
313        else if (size == iconSize24) {
314                s = wxSystemSettings::GetMetric(wxSYS_SMALLICON_X);
315                if (s <= 0) {
316                        s = 24;
317                }
318                else {
319                        s += s/2;
320                }
321        }
322        else if (size == iconSizeLarge) {
323                s = wxSystemSettings::GetMetric(wxSYS_ICON_X);
324                if (s <= 0)
325                        s = 48;
326                else
327                        s += s/2;
328        }
329        else {
330                s = wxSystemSettings::GetMetric(wxSYS_ICON_X);
331                if (s <= 0)
332                        s = 32;
333        }
334
335        return wxSize(s, s);
336}
337
338wxSize CThemeProvider::GetIconSize(wxString const& str)
339{
340        wxSize iconSize;
341        if (str == _T("24x24"))
342                return CThemeProvider::GetIconSize(iconSize24);
343        else if (str == _T("32x32"))
344                iconSize = CThemeProvider::GetIconSize(iconSizeNormal);
345        else if (str == _T("48x48"))
346                iconSize = CThemeProvider::GetIconSize(iconSizeLarge);
347        else
348                iconSize = CThemeProvider::GetIconSize(iconSizeSmall);
349
350        return iconSize;
351}
Note: See TracBrowser for help on using the repository browser.