1// Aseprite
2// Copyright (C) 2020-2022 Igara Studio S.A.
3// Copyright (C) 2001-2017 David Capello
4//
5// This program is distributed under the terms of
6// the End-User License Agreement for Aseprite.
7
8#ifndef APP_UI_SKIN_SKIN_THEME_H_INCLUDED
9#define APP_UI_SKIN_SKIN_THEME_H_INCLUDED
10#pragma once
11
12#include "app/ui/skin/skin_part.h"
13#include "gfx/color.h"
14#include "gfx/fwd.h"
15#include "ui/cursor.h"
16#include "ui/cursor_type.h"
17#include "ui/manager.h"
18#include "ui/scale.h"
19#include "ui/theme.h"
20
21#include "theme.xml.h"
22
23#include <array>
24#include <map>
25#include <string>
26
27namespace ui {
28 class Entry;
29 class Graphics;
30}
31
32namespace app {
33 namespace skin {
34
35 class FontData;
36
37 // This is the GUI theme used by Aseprite (which use images from
38 // data/skins directory).
39 class SkinTheme : public ui::Theme
40 , public app::gen::ThemeFile<SkinTheme> {
41 public:
42 static const char* kThemesFolderName;
43
44 static SkinTheme* instance();
45 static SkinTheme* get(const ui::Widget* widget);
46
47 SkinTheme();
48 ~SkinTheme();
49
50 const std::string& path() { return m_path; }
51 int preferredScreenScaling() { return m_preferredScreenScaling; }
52 int preferredUIScaling() { return m_preferredUIScaling; }
53
54 os::Font* getDefaultFont() const override { return m_defaultFont.get(); }
55 os::Font* getWidgetFont(const ui::Widget* widget) const override;
56 os::Font* getMiniFont() const { return m_miniFont.get(); }
57
58 ui::Cursor* getStandardCursor(ui::CursorType type) override;
59 void initWidget(ui::Widget* widget) override;
60 void getWindowMask(ui::Widget* widget, gfx::Region& region) override;
61 int getScrollbarSize() override;
62 gfx::Size getEntryCaretSize(ui::Widget* widget) override;
63
64 void paintEntry(ui::PaintEvent& ev) override;
65 void paintListBox(ui::PaintEvent& ev) override;
66 void paintMenu(ui::PaintEvent& ev) override;
67 void paintMenuItem(ui::PaintEvent& ev) override;
68 void paintSlider(ui::PaintEvent& ev) override;
69 void paintComboBoxEntry(ui::PaintEvent& ev) override;
70 void paintTextBox(ui::PaintEvent& ev) override;
71 void paintViewViewport(ui::PaintEvent& ev) override;
72
73 SkinPartPtr getToolPart(const char* toolId) const;
74 os::Surface* getToolIcon(const char* toolId) const;
75
76 // Helper functions to draw bounds/hlines with sheet parts
77 void drawRect(ui::Graphics* g, const gfx::Rect& rc,
78 os::Surface* nw, os::Surface* n, os::Surface* ne,
79 os::Surface* e, os::Surface* se, os::Surface* s,
80 os::Surface* sw, os::Surface* w);
81 void drawRect(ui::Graphics* g, const gfx::Rect& rc, SkinPart* skinPart, const bool drawCenter = true);
82 void drawRect2(ui::Graphics* g, const gfx::Rect& rc, int x_mid, SkinPart* nw1, SkinPart* nw2);
83 void drawHline(ui::Graphics* g, const gfx::Rect& rc, SkinPart* skinPart);
84 void drawVline(ui::Graphics* g, const gfx::Rect& rc, SkinPart* skinPart);
85 void paintProgressBar(ui::Graphics* g, const gfx::Rect& rc, double progress);
86
87 ui::Style* getStyleById(const std::string& id) const {
88 auto it = m_styles.find(id);
89 if (it != m_styles.end())
90 return it->second;
91 else
92 return nullptr;
93 }
94
95 SkinPartPtr getPartById(const std::string& id) const {
96 auto it = m_parts_by_id.find(id);
97 if (it != m_parts_by_id.end())
98 return it->second;
99 else
100 return SkinPartPtr(nullptr);
101 }
102
103 ui::Cursor* getCursorById(const std::string& id) const {
104 auto it = m_cursors.find(id);
105 if (it != m_cursors.end())
106 return it->second;
107 else
108 return nullptr;
109 }
110
111 int getDimensionById(const std::string& id) const {
112 auto it = m_dimensions_by_id.find(id);
113 if (it != m_dimensions_by_id.end())
114 return it->second * ui::guiscale();
115 else
116 return 0;
117 }
118
119 gfx::Color getColorById(const std::string& id) const {
120 auto it = m_colors_by_id.find(id);
121 if (it != m_colors_by_id.end())
122 return it->second;
123 else
124 return gfx::ColorNone;
125 }
126
127 void drawEntryCaret(ui::Graphics* g, ui::Entry* widget, int x, int y);
128
129 protected:
130 void onRegenerateTheme() override;
131
132 private:
133 struct BackwardCompatibility;
134
135 void loadFontData();
136 void loadAll(const std::string& themeId,
137 BackwardCompatibility* backward = nullptr);
138 void loadSheet();
139 void loadXml(BackwardCompatibility* backward);
140
141 os::SurfaceRef sliceSheet(os::SurfaceRef sur, const gfx::Rect& bounds);
142 gfx::Color getWidgetBgColor(ui::Widget* widget);
143 void drawText(ui::Graphics* g,
144 const char* t,
145 const gfx::Color fgColor,
146 const gfx::Color bgColor,
147 const ui::Widget* widget,
148 const gfx::Rect& rc,
149 const int textAlign,
150 const int mnemonic);
151 void drawEntryText(ui::Graphics* g, ui::Entry* widget);
152
153 std::string findThemePath(const std::string& themeId) const;
154
155 std::string m_path;
156 os::SurfaceRef m_sheet;
157 std::map<std::string, SkinPartPtr> m_parts_by_id;
158 std::map<std::string, gfx::Color> m_colors_by_id;
159 std::map<std::string, int> m_dimensions_by_id;
160 std::map<std::string, ui::Cursor*> m_cursors;
161 std::array<ui::Cursor*, ui::kCursorTypes> m_standardCursors;
162 std::map<std::string, ui::Style*> m_styles;
163 std::map<std::string, FontData*> m_fonts;
164 std::map<std::string, os::FontRef> m_themeFonts;
165 os::FontRef m_defaultFont;
166 os::FontRef m_miniFont;
167 int m_preferredScreenScaling;
168 int m_preferredUIScaling;
169 };
170
171 } // namespace skin
172} // namespace app
173
174#endif
175