CYD-UI
A C++ library for building native graphic user interfaces
Loading...
Searching...
No Matches
component_base.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
4module;
5#include <__stddef_offsetof.h>
6#include "cyd_fabric_modules/headers/macros/async_events.h"
8#define STYLE_SETTER_RETURN_TYPE void
9#define STYLE_SETTER_RETURN_EXPR
11
12export module cydui.components.base;
14import std;
15
16import fabric.logging;
17import fabric.async;
18import fabric.templates.functor_arguments;
20export import cydui.graphics;
21export import cydui.styling;
24
25export import :type;
26export import :event_dispatcher;
27export import :attributes;
28export import :contexts;
29export import :state;
30
31namespace cydui::components {
32 export class component_base_t {
33 public:
34 using sptr = std::shared_ptr<component_base_t>;
35 using wptr = std::weak_ptr<component_base_t>;
37 public:
38 explicit component_base_t(identifier_t identifier = {})
39 : id_(identifier) { }
40
41 virtual ~component_base_t() = default; //{
42 // ! All of this is done in the `component_t` class destructor
43 // clear_subscribed_listeners();
44 // if (state.has_value()) {
45 // state.value()->component_instance = std::nullopt;
46 // }
47 //}
48 virtual void* get_props() = 0;
55 virtual const refl::type_info& get_style_type_info() const = 0;
56
57 virtual attrs_component<>* attrs() = 0;
58 virtual std::string name() const = 0;
60 private:
61 virtual std::shared_ptr<component_state_t> create_state_instance() = 0;
62
68 virtual bool update_with(std::shared_ptr<component_base_t> other) = 0;
69
70 virtual void mount() = 0;
71 virtual void dismount() = 0;
72
73 public:
75 if (state_.has_value()) {
76 return state_.value().lock();
77 } else {
78 return {nullptr};
79 }
80 }
81
82 template <typename T>
83 auto& get_data() {
84 using type = std::remove_const_t<std::remove_reference_t<T>>;
85 static auto tid = refl::type_id<type>;
86
87 if (not data_map_.contains(tid)) {
88 data_map_[tid] = refl::any::make<type>();
89 }
90
91 return data_map_.at(tid).template as<type>();
92 }
93
94 template <typename T>
95 bool remove_data() {
96 using type = std::remove_const_t<std::remove_reference_t<T>>;
97 static auto tid = refl::type_id<type>;
98
99 if (data_map_.contains(tid)) {
100 data_map_.erase(tid);
101 return true;
102 }
103 return false;
104 }
105
106 template<typename ContextType>
108 context_store_.add_context<ContextType>(ptr);
109 }
110
111 template<typename ContextType>
112 std::optional<ContextType*> find_context() {
113 if (not context_store_.empty()) {
114 auto context = context_store_.find_context<ContextType>();
115 if (context.has_value()) {
116 return context;
117 }
118 }
119
120 if (parent.has_value()) {
121 return parent.value()->find_context<ContextType>();
122 }
123
124 return std::nullopt;
125 }
126
130
132 return event_dispatcher.has_value()? event_dispatcher.value().get(): nullptr;
133 }
134
136 return style_data->as_base();
137 }
138
140 return *(style_data.get());
141 }
142
143
145 children.clear();
146 }
147
148 void set_id(const std::string& id) {
149 id_.set_id(id);
150 }
151
152 std::string get_id() {
153 return id_.str();
154 }
155
156 std::string get_id() const {
157 return id_.str();
158 }
159
160 void tag(const std::string& tag_) {
161 style_data->tags.insert(tag_);
162 }
163
164 void untag(const std::string& tag_) {
165 style_data->tags.erase(tag_);
166 }
167
168 bool has_tag(const std::string& tag_) const {
169 return style_data->tags.contains(tag_);
170 }
171
172 std::optional<sptr> find_child(const std::string& id) {
173 for (const auto & child : children) {
174 if (child->get_id() == id) {
175 return child;
176 }
177 auto descendant = child->find_child(id);
178 if (descendant.has_value()) {
179 return descendant;
180 }
181 }
182 return std::nullopt;
183 }
184
185 std::list<sptr> find_children(const std::string& id) {
186 std::list<sptr> result{};
187 for (const auto & child : children) {
188 if (child->get_id() == id) {
189 result.push_back(child);
190 }
191 auto descendants = child->find_children(id);
192 for (const auto & d : descendants) {
193 result.push_back(d);
194 }
195 }
196 return result;
197 }
198
199#include "../style_setters.inc"
200
201 protected:
203 state_ = state;
204 }
205
206 private:
207 friend class ::with_context;
208
209 template<typename ContextType>
211
212 template<typename ContextType>
213 void add_context(const std::shared_ptr<ContextType> &ptr) {
214 context_store_.add_context<ContextType>(ptr);
215 }
216
217 auto& get_context_store() {
218 return context_store_;
219 }
220
221 public:
222 friend struct component_actor_t;
223
224 std::optional<component_base_t*> parent = std::nullopt;
225 std::list<std::shared_ptr<component_base_t>> children{};
226
227 protected:
229 [[refl::ignore]]
230 std::optional<std::shared_ptr<event_dispatcher_base_t>> event_dispatcher{std::nullopt};
231 std::shared_ptr<style_data_base_t> style_data{};
232
233 private:
234 std::optional<std::weak_ptr<component_state_t>> state_ = std::nullopt;
235 context_store_t context_store_{};
236 std::unordered_map<refl::type_id_t, refl::any> data_map_ { };
237
238 identifier_t id_{};
239 };
240
243 component->set_state(state);
244 }
245 static std::shared_ptr<component_state_t> create_state_instance(component_base_t* component) {
246 return component->create_state_instance();
247 }
248
249 static bool update_component_with(component_base_t* component, std::shared_ptr<component_base_t> other) {
250 return component->update_with(other);
251 }
252
253 static void mount_component(component_base_t* component) {
254 component->mount();
255 }
256 static void dismount_component(component_base_t* component) {
257 component->dismount();
258 }
259 };
260}
261
262template<typename ContextType>
264 auto holder = components.build();
265
266 for (auto &c: holder.get_components()) {
267 if (not c->get_context_store().find_context<ContextType>().has_value()) {
268 c->add_context(context_);
269 }
270 }
271
272 return holder;
273}
void set_id(const std::string &id)
std::shared_ptr< style_data_base_t > style_data
component_base_t(identifier_t identifier={})
void set_state(const component_state_ref &state)
std::list< std::shared_ptr< component_base_t > > children
component_state_ref state() const
std::optional< sptr > find_child(const std::string &id)
std::weak_ptr< component_base_t > wptr
virtual component_dimensional_relations_t get_dimensional_relations()=0
internal_relations_t & get_internal_relations()
void y(const dimension_t &value)
virtual component_base_t * find_by_coords(dimension_t::value_type x, dimension_t::value_type y)=0
void add_context(provide_context< ContextType > &ptr)
virtual attrs_component * attrs()=0
std::optional< std::shared_ptr< event_dispatcher_base_t > > event_dispatcher
void untag(const std::string &tag_)
std::list< sptr > find_children(const std::string &id)
virtual std::shared_ptr< dimension_ctx_t > get_dimensional_context()=0
bool has_tag(const std::string &tag_) const
void tag(const std::string &tag_)
virtual const refl::type_info & get_style_type_info() const =0
std::optional< component_base_t * > parent
void x(const dimension_t &value)
std::shared_ptr< component_base_t > sptr
virtual std::string name() const =0
event_dispatcher_base_t * get_event_dispatcher()
std::optional< ContextType * > find_context()
std::shared_ptr< component_state_t > component_state_ref
static void dismount_component(component_base_t *component)
static void set_component_state(component_base_t *component, component_state_ref state)
static void mount_component(component_base_t *component)
static bool update_component_with(component_base_t *component, std::shared_ptr< component_base_t > other)
static std::shared_ptr< component_state_t > create_state_instance(component_base_t *component)
components::component_holder_t operator>(with_context &&components)