CYD-UI
A C++ library for building native graphic user interfaces
Loading...
Searching...
No Matches
component_style.cppm
Go to the documentation of this file.
1// Copyright (c) 2024, Víctor Castillo Agüero.
2// SPDX-License-Identifier: GPL-3.0-or-later
3
5
6import std;
7
8export import reflect;
9export import quantify;
10
11export import cydui.graphics;
12export import cydui.styling;
13
15
16namespace cydui {
17 export struct custom_style_parser {
18 explicit constexpr custom_style_parser(refl::any (*fun)(const std::string&))
19 : parser_function(fun) {}
20
21 refl::any (*parser_function)(const std::string&);
22 };
23} // namespace cydui
24
25export namespace cydui::components {
26 template <typename T>
28 public:
29 T top{}, right{}, bottom{}, left{};
30 };
31 template <typename T>
33 public:
35 };
36
37 struct style_base_t {
38 public:
45
48
58 [[meta(
61
62 [[meta(AnimationComplexity::COMPOSE)]] la::scalar opacity{1.0f};
63 [[meta(AnimationComplexity::COMPOSE)]] la::scalar translate_x{0.0f};
64 [[meta(AnimationComplexity::COMPOSE)]] la::scalar translate_y{0.0f};
65 [[meta(AnimationComplexity::COMPOSE)]] la::scalar scale_x{1.0f};
66 [[meta(AnimationComplexity::COMPOSE)]] la::scalar scale_y{1.0f};
67
70 };
72
74 std::size_t specificity;
76 bool active{false};
77 std::unordered_set<const refl::field_info*> active_base_properties{};
78 std::unordered_set<const refl::field_info*> active_properties{};
79 };
80
82 void clear() {
83 base_fields.clear();
84 fields.clear();
85 }
86
87 bool operator==(const style_override_data_t& other) const {
88 return base_fields == other.base_fields and fields == other.fields;
89 }
90
91 std::unordered_map<refl::field_path, refl::any> base_fields{};
92 std::unordered_map<refl::field_path, refl::any> fields{};
93 };
94
96 public:
97 virtual ~style_data_base_t() = default;
98
99 virtual void reset() = 0;
100 virtual void reset_field(const refl::field_info* field, bool is_base_field) = 0;
101 virtual style_base_t& as_base() = 0;
102 virtual void* as_raw() = 0;
103 virtual void apply_override() = 0;
104 virtual void apply_transform() = 0;
105
106 virtual const std::shared_ptr<dimension_ctx_t>& get_dimensional_ctx() = 0;
107
108 virtual void set_base_field_override(refl::field_path field_path, refl::any value) = 0;
109 virtual void set_field_override(refl::field_path field_path, refl::any value) = 0;
110 virtual bool has_base_field_override(refl::field_path field_path) = 0;
111 virtual bool has_field_override(refl::field_path field_path) = 0;
112 virtual void clear_style_override() = 0;
113
114 bool update_override_with(const style_override_data_t& override_data) {
115 bool something_changed = false;
116 for (const auto& base_field: override_data.base_fields) {
117 if ((not style_override_data.base_fields.contains(base_field.first))//
118 or (style_override_data.base_fields.contains(base_field.first)
119 and base_field.second != style_override_data.base_fields.at(base_field.first))) {
120 something_changed = true;
121 }
122 style_override_data.base_fields.insert(base_field);
123 }
124 for (const auto& field: override_data.fields) {
125 if ((not style_override_data.fields.contains(field.first))//
126 or (style_override_data.fields.contains(field.first)
127 and field.second != style_override_data.fields.at(field.first))) {
128 something_changed = true;
129 }
130 style_override_data.fields.insert(field);
131 }
132 return something_changed;
133 }
134
135 std::shared_ptr<dimension_ctx_t> get_dimension_ctx() {
136 return dimension_ctx_;
137 };
138
139 std::unordered_set<std::string> tags{};
140 std::vector<style_rule_instance_t> rules{};
142 std::shared_ptr<dimension_ctx_t> dimension_ctx_{std::make_shared<dimension_ctx_t>()};
143 };
144
145 template <typename Style>
146 class style_data_t final: public style_data_base_t {
147 public:
148 style_data_t(const std::string& ctx_name)
149 : ptr_(std::make_shared<Style>()) {
150 dimension_ctx_->set_name(ctx_name);
151
152 auto& base = as_base();
153 base.x.set_context(dimension_ctx_, "x");
154 base.y.set_context(dimension_ctx_, "y");
155 base.width.set_context(dimension_ctx_, "width");
156 base.height.set_context(dimension_ctx_, "height");
157
158 base.margin.top.set_context(dimension_ctx_, "margin_top");
159 base.margin.right.set_context(dimension_ctx_, "margin_right");
160 base.margin.bottom.set_context(dimension_ctx_, "margin_bottom");
161 base.margin.left.set_context(dimension_ctx_, "margin_left");
162
163 base.padding.top.set_context(dimension_ctx_, "padding_top");
164 base.padding.right.set_context(dimension_ctx_, "padding_right");
165 base.padding.bottom.set_context(dimension_ctx_, "padding_bottom");
166 base.padding.left.set_context(dimension_ctx_, "padding_left");
167 }
168
169 void reset() override {
170 get_style() = {};
171 }
172
173 void reset_field(const refl::field_info* field, bool is_base_field) override {
174 const refl::type_info& ti = field->type();
175 if (is_base_field) {
176 static style_base_t default_value{};
177 ti.assign_copy_of(field->get_ptr(&default_value), field->get_ptr(&as_base()));
178 } else {
179 static Style default_value{};
180 ti.assign_copy_of(field->get_ptr(&default_value), field->get_ptr(&get_style()));
181 }
182 }
183
184 auto& get_style() {
185 return *static_cast<Style*>(ptr_.get());
186 }
187
189 return style_override_data;
190 }
191
192 void set_base_field_override(refl::field_path field_info, refl::any value) override {
193 style_override_data.base_fields[field_info] = value;
194 }
195 void set_field_override(refl::field_path field_info, refl::any value) override {
196 style_override_data.fields[field_info] = value;
197 }
198 bool has_base_field_override(refl::field_path field_info) override {
199 return style_override_data.base_fields.contains(field_info);
200 }
201 bool has_field_override(refl::field_path field_info) override {
202 return style_override_data.fields.contains(field_info);
203 }
204 void clear_style_override() override {
205 style_override_data.clear();
206 }
207
208 const std::shared_ptr<dimension_ctx_t>& get_dimensional_ctx() override {
209 return dimension_ctx_;
210 }
211
212 void set_style_transform(auto&& transform_func) {
213 style_transform = [=](std::shared_ptr<void>& ptr) {
214 transform_func(*static_cast<Style*>(ptr.get()));
215 };
216 }
218 style_transform = [](std::shared_ptr<void>&) {};
219 }
220
221 style_base_t& as_base() override {
222 return *static_cast<style_base_t*>(ptr_.get());
223 }
224
225 void* as_raw() override {
226 return &get_style();
227 }
228
229 void apply_override() override {
230 auto& s = get_style();
231 style_base_t& base_s = as_base();
232
233 for (const auto& [field_info, value]: style_override_data.base_fields) {
234 field_info.type().assign_copy_of(value.data(), field_info.get_ptr(&base_s));
235 }
236 for (const auto& [field_info, value]: style_override_data.fields) {
237 field_info.type().assign_copy_of(value.data(), field_info.get_ptr(&s));
238 }
239 }
240
241 void apply_transform() override {
242 style_transform(ptr_);
243 }
244
245 private:
246 std::shared_ptr<void> ptr_{};
247 std::function<void(std::shared_ptr<void>&)> style_transform{[](std::shared_ptr<void>&) {}};
248 };
249} // namespace cydui::components
virtual bool has_field_override(refl::field_path field_path)=0
std::vector< style_rule_instance_t > rules
bool update_override_with(const style_override_data_t &override_data)
std::shared_ptr< dimension_ctx_t > dimension_ctx_
virtual const std::shared_ptr< dimension_ctx_t > & get_dimensional_ctx()=0
std::shared_ptr< dimension_ctx_t > get_dimension_ctx()
virtual void set_base_field_override(refl::field_path field_path, refl::any value)=0
std::unordered_set< std::string > tags
virtual void reset_field(const refl::field_info *field, bool is_base_field)=0
virtual void set_field_override(refl::field_path field_path, refl::any value)=0
virtual bool has_base_field_override(refl::field_path field_path)=0
virtual style_base_t & as_base()=0
style_base_t & as_base() override
void set_style_transform(auto &&transform_func)
bool has_field_override(refl::field_path field_info) override
void reset_field(const refl::field_info *field, bool is_base_field) override
void set_base_field_override(refl::field_path field_info, refl::any value) override
const std::shared_ptr< dimension_ctx_t > & get_dimensional_ctx() override
void set_field_override(refl::field_path field_info, refl::any value) override
bool has_base_field_override(refl::field_path field_info) override
style_data_t(const std::string &ctx_name)
dimensions::dimension< dimensions::screen_measure > dimension_t
quantify::Q< quantify::angle::degrees, la::scalar > angle_type
Definition @index.cppm:20
std::shared_ptr< StyleRule > sptr
Definition rule.cppm:16
four_sided_property< vg::paint::type > border
four_cornered_property< int > border_radius
four_sided_property< int > border_width
four_sided_property< dimension_t > margin
four_sided_property< std::valarray< double > > border_dasharray
four_sided_property< dimension_t > padding
std::unordered_map< refl::field_path, refl::any > fields
bool operator==(const style_override_data_t &other) const
std::unordered_map< refl::field_path, refl::any > base_fields
std::unordered_set< const refl::field_info * > active_properties
std::unordered_set< const refl::field_info * > active_base_properties
refl::any(* parser_function)(const std::string &)
constexpr custom_style_parser(refl::any(*fun)(const std::string &))
static type make(Paint paint_data_)