1// Aseprite Code Generator
2// Copyright (c) 2015-2017 David Capello
3//
4// This file is released under the terms of the MIT license.
5// Read LICENSE.txt for more information.
6
7#include "gen/theme_class.h"
8
9#include "base/string.h"
10#include "gen/common.h"
11
12#include <cstring>
13#include <iostream>
14#include <vector>
15
16void gen_theme_class(TiXmlDocument* doc, const std::string& inputFn)
17{
18 std::vector<std::string> dimensions;
19 std::vector<std::string> colors;
20 std::vector<std::string> parts;
21 std::vector<std::string> cursors;
22 std::vector<std::string> styles;
23
24 TiXmlHandle handle(doc);
25 TiXmlElement* elem = handle
26 .FirstChild("theme")
27 .FirstChild("dimensions")
28 .FirstChild("dim").ToElement();
29 while (elem) {
30 const char* id = elem->Attribute("id");
31 dimensions.push_back(id);
32 elem = elem->NextSiblingElement();
33 }
34
35 elem = handle
36 .FirstChild("theme")
37 .FirstChild("colors")
38 .FirstChild("color").ToElement();
39 while (elem) {
40 const char* id = elem->Attribute("id");
41 colors.push_back(id);
42 elem = elem->NextSiblingElement();
43 }
44
45 elem = handle
46 .FirstChild("theme")
47 .FirstChild("parts")
48 .FirstChild("part").ToElement();
49 while (elem) {
50 const char* id = elem->Attribute("id");
51 if (std::strncmp(id, "cursor_", 7) == 0) {
52 cursors.push_back(std::string(id).substr(7));
53 }
54 else if (!std::strchr(id, ':'))
55 parts.push_back(id);
56 elem = elem->NextSiblingElement();
57 }
58
59 elem = handle
60 .FirstChild("theme")
61 .FirstChild("styles")
62 .FirstChild("style").ToElement();
63 while (elem) {
64 const char* id = elem->Attribute("id");
65 styles.push_back(id);
66 elem = elem->NextSiblingElement();
67 }
68
69 std::cout
70 << "// Don't modify, generated file from " << inputFn << "\n"
71 << "\n"
72 << "#ifndef GENERATED_THEME_H_INCLUDED\n"
73 << "#define GENERATED_THEME_H_INCLUDED\n"
74 << "#pragma once\n"
75 << "\n"
76 << "namespace app {\n"
77 << "namespace gen {\n"
78 << "\n"
79 << " template<typename T>\n"
80 << " class ThemeFile {\n"
81 << " public:\n"
82 << "\n";
83
84 // Dimensions sub class
85 std::cout
86 << " class Dimensions {\n"
87 << " template<typename> friend class ThemeFile;\n"
88 << " public:\n";
89 for (auto dimension : dimensions) {
90 std::string id = convert_xmlid_to_cppid(dimension, false);
91 std::cout
92 << " int " << id << "() const { return m_" << id << "; }\n";
93 }
94 std::cout
95 << " private:\n";
96 for (auto dimension : dimensions) {
97 std::string id = convert_xmlid_to_cppid(dimension, false);
98 std::cout
99 << " int m_" << id << ";\n";
100 }
101 std::cout
102 << " };\n";
103
104 // Colors sub class
105 std::cout
106 << " class Colors {\n"
107 << " template<typename> friend class ThemeFile;\n"
108 << " public:\n";
109 for (auto color : colors) {
110 std::string id = convert_xmlid_to_cppid(color, false);
111 std::cout
112 << " gfx::Color " << id << "() const { return m_" << id << "; }\n";
113 }
114 std::cout
115 << " private:\n";
116 for (auto color : colors) {
117 std::string id = convert_xmlid_to_cppid(color, false);
118 std::cout
119 << " gfx::Color m_" << id << ";\n";
120 }
121 std::cout
122 << " };\n";
123
124 // Parts sub class
125 std::cout
126 << " class Parts {\n"
127 << " template<typename> friend class ThemeFile;\n"
128 << " public:\n";
129 for (auto part : parts) {
130 std::string id = convert_xmlid_to_cppid(part, false);
131 std::cout
132 << " const skin::SkinPartPtr& " << id << "() const { return m_" << id << "; }\n";
133 }
134 std::cout
135 << " private:\n";
136 for (auto part : parts) {
137 std::string id = convert_xmlid_to_cppid(part, false);
138 std::cout
139 << " skin::SkinPartPtr m_" << id << ";\n";
140 }
141 std::cout
142 << " };\n";
143
144 // Cursors sub class
145 std::cout
146 << " class Cursors {\n"
147 << " template<typename> friend class ThemeFile;\n"
148 << " public:\n";
149 for (auto cursor : cursors) {
150 std::string id = convert_xmlid_to_cppid(cursor, false);
151 std::cout
152 << " const ui::Cursor* " << id << "() const { return m_" << id << "; }\n";
153 }
154 std::cout
155 << " private:\n";
156 for (auto cursor : cursors) {
157 std::string id = convert_xmlid_to_cppid(cursor, false);
158 std::cout
159 << " ui::Cursor* m_" << id << ";\n";
160 }
161 std::cout
162 << " };\n";
163
164 // Styles sub class
165 std::cout
166 << "\n"
167 << " class Styles {\n"
168 << " template<typename> friend class ThemeFile;\n"
169 << " public:\n";
170 for (auto style : styles) {
171 std::string id = convert_xmlid_to_cppid(style, false);
172 std::cout
173 << " ui::Style* " << id << "() const { return m_" << id << "; }\n";
174 }
175 std::cout
176 << " private:\n";
177 for (auto style : styles) {
178 std::string id = convert_xmlid_to_cppid(style, false);
179 std::cout
180 << " ui::Style* m_" << id << ";\n";
181 }
182 std::cout
183 << " };\n";
184
185 std::cout
186 << "\n"
187 << " Dimensions dimensions;\n"
188 << " Colors colors;\n"
189 << " Parts parts;\n"
190 << " Cursors cursors;\n"
191 << " Styles styles;\n"
192 << "\n"
193 << " protected:\n"
194 << " void updateInternals() {\n";
195 for (auto dimension : dimensions) {
196 std::string id = convert_xmlid_to_cppid(dimension, false);
197 std::cout << " byId(dimensions.m_" << id
198 << ", \"" << dimension << "\");\n";
199 }
200 for (auto color : colors) {
201 std::string id = convert_xmlid_to_cppid(color, false);
202 std::cout << " byId(colors.m_" << id
203 << ", \"" << color << "\");\n";
204 }
205 for (auto part : parts) {
206 std::string id = convert_xmlid_to_cppid(part, false);
207 std::cout << " byId(parts.m_" << id
208 << ", \"" << part << "\");\n";
209 }
210 for (auto cursor : cursors) {
211 std::string id = convert_xmlid_to_cppid(cursor, false);
212 std::cout << " byId(cursors.m_" << id
213 << ", \"" << cursor << "\");\n";
214 }
215 for (auto style : styles) {
216 std::string id = convert_xmlid_to_cppid(style, false);
217 std::cout << " byId(styles.m_" << id
218 << ", \"" << style << "\");\n";
219 }
220 std::cout
221 << " }\n"
222 << "\n"
223 << " private:\n"
224 << " void byId(int& dimension, const std::string& id) {\n"
225 << " dimension = static_cast<T*>(this)->getDimensionById(id);\n"
226 << " }\n"
227 << " void byId(gfx::Color& color, const std::string& id) {\n"
228 << " color = static_cast<T*>(this)->getColorById(id);\n"
229 << " }\n"
230 << " void byId(skin::SkinPartPtr& part, const std::string& id) {\n"
231 << " part = static_cast<T*>(this)->getPartById(id);\n"
232 << " }\n"
233 << " void byId(ui::Cursor*& cursor, const std::string& id) {\n"
234 << " cursor = static_cast<T*>(this)->getCursorById(id);\n"
235 << " }\n"
236 << " void byId(ui::Style*& style, const std::string& id) {\n"
237 << " style = static_cast<T*>(this)->getStyleById(id);\n"
238 << " }\n";
239
240 std::cout
241 << " };\n"
242 << "\n"
243 << "} // namespace gen\n"
244 << "} // namespace app\n"
245 << "\n"
246 << "#endif\n";
247}
248