CYD-UI
A C++ library for building native graphic user interfaces
Loading...
Searching...
No Matches
stylesheet.cppm
Go to the documentation of this file.
1
5
6export module cydui.styling;
7
8import std;
9import reflect;
10
11import fabric.logging;
13
14export import cydui.styling.selectors;
15export import cydui.styling.rules;
16
17
18namespace cydui {
19 template<typename O>
20 void print_ast_node(O &o, const fabric::node_t *node, int indent = 0) {
21 for (int i = 0; i < indent; ++i) {
22 o << ' ';
23 }
24 if (node->is_type<syntax::tss::tss_decl_color_literal>()) {
25 auto* c = node->as<syntax::tss::tss_decl_color_literal>();
26 o << "<color hex=" << std::format("{:?}", c->data.to_string()) << "/>" << std::endl;
27 return;
28 }
29 if (node->is_text) {
30 o << "<text text=" << std::format("{:?}", node->text) << "/>" << std::endl;
31 return;
32 }
33
34 o << "<" << node->text;
35 if (node->children.empty()) {
36 o << "/>" << std::endl;
37 } else {
38 if (node->children.size() == 1 && node->children[0]->is_text) {
39 o << " text=" << std::format("{:?}", node->children[0]->text) << "/>" << std::endl;
40 return;
41 }
42
43 o << ">" << std::endl;
44 for (const auto &child: node->children) {
45 print_ast_node(o, child.get(), indent + 1);
46 }
47
48 for (int i = 0; i < indent; ++i) {
49 o << ' ';
50 }
51
52 o << "</" << node->text << ">" << std::endl;
53 }
54 }
55
56 export class ast_visitor {
57 void visit(const syntax::tss::tss_decl_color_literal::sptr& c) {
58 // c->color;
59 }
60 };
61
62 export class StyleSheet {
63 public:
64 using sptr = std::shared_ptr<StyleSheet>;
65
66 static sptr make() {
67 return std::make_shared<StyleSheet>();
68 }
69
70 static sptr parse(auto input) {
71 auto [ok, ast, log] = lang::tss::parse(input);
72
73 if (not ok) {
74 LOG::print {ERROR}("Couldn't parse stylesheet");
75 for (const auto & line: log) {
76 LOG::print {ERROR}("{}: {}", line.first, line.second);
77 }
78 return std::make_shared<StyleSheet>();
79 }
80 // print_ast_node(std::cout, ast.get(), 0);
81
82 sptr ptr = std::make_shared<StyleSheet>();
83 for (const auto& rule : ast->data.rules) {
84 for (const auto& key : rule->relevant_components_) {
85 ptr->rule_map_[key].push_back(rule);
86 }
87 }
88
89 return ptr;
90 }
91
92 auto& rules_by_component(const std::string& component_name) const {
93 if (rule_map_.contains(component_name)) {
94 return rule_map_.at(component_name);
95 }
96 return empty_list_;
97 }
98
99 auto& any_rules() const {
100 return any_rules_;
101 }
102 private:
103 std::unordered_map<std::string, std::list<StyleRule::sptr>> rule_map_{};
104 std::list<StyleRule::sptr> any_rules_{};
105 std::list<StyleRule::sptr> empty_list_{};
106 };
107
108 export class StyleArchive {
109 public:
110 using sptr = std::shared_ptr<StyleArchive>;
111
112 static sptr make() {
113 return std::make_shared<StyleArchive>();
114 }
115
116 void add_stylesheet(const StyleSheet::sptr& sheet) {
117 style_sheets_.emplace_back(sheet);
118 }
119
120 void for_each_rule(const std::string& component_name, auto&& func) const {
121 for (const auto & style_sheet : style_sheets_) {
122 for (const auto& rule: style_sheet->any_rules()) {
123 func(rule);
124 }
125 for (const auto& rule: style_sheet->rules_by_component(component_name)) {
126 func(rule);
127 }
128 }
129 }
130
131 private:
132 std::vector<StyleSheet::sptr> style_sheets_{};
133 };
134}
void add_stylesheet(const StyleSheet::sptr &sheet)
std::shared_ptr< StyleArchive > sptr
void for_each_rule(const std::string &component_name, auto &&func) const
auto & rules_by_component(const std::string &component_name) const
std::shared_ptr< StyleSheet > sptr
static sptr make()
auto & any_rules() const
static sptr parse(auto input)
void print_ast_node(O &o, const fabric::node_t *node, int indent=0)