7#include <cyd_fabric_modules/headers/macros/async_events.h>
9#include <tracy/Tracy.hpp>
10#define SDL_MAIN_HANDLED
18import fabric.profiling;
33export namespace cydui {
35 std::shared_ptr<cydui::components::component_base_t> component;
38 template <components::ComponentConcept C>
39 Layout* create(C&& root_component);
41 template <components::ComponentConcept C>
42 Layout* create(C& root_component);
49 : root_state(_root_state),
51 focused(_root_state) {
52 focused->focused =
true;
55 this->win->compositor.compose(node);
57 component_updater->queue_render_signal.connect(
60 component_updater->apply_style_signal.connect(
63 component_updater->compile_style_rules_signal.connect(
70 for (
auto& item: listeners) {
94 void update_dimensions();
97 template <components::ComponentConcept C>
100 template <components::ComponentConcept C>
113 std::vector<fabric::async::raw_listener::sptr> make_event_listeners();
124 std::vector<fabric::async::raw_listener::sptr> listeners{};
139 template <components::ComponentConcept C>
141 ZoneScopedN(
"Layout:create");
142 auto root = std::make_shared<C>(std::forward<C>(root_component));
144 root_state->component_instance = root;
145 auto* lay =
new Layout(root_state, root);
149 template <components::ComponentConcept C>
151 ZoneScopedN(
"Layout:create");
152 auto root = std::make_shared<C>(root_component);
154 root_state->component_instance = root;
155 auto* lay =
new Layout(root_state, root);
159#define COMPUTE(DIM) \
161 auto compute_res = cydui::dimensions::compute_dimension(DIM); \
162 if (not compute_res) { \
173 static const refl::field_info* width_fi =
174 refl::type_info::from<components::style_base_t>().field_by_name(
"width").value();
175 static const refl::field_info* height_fi =
176 refl::type_info::from<components::style_base_t>().field_by_name(
"height").value();
199 if (rt->
parent.has_value()) {
200 auto& parent_int_rel = rt->
parent.value()->get_internal_relations();
202 int_rel.cx = parent_int_rel.cx + dim.x + dim.margin_left + dim.padding_left;
203 int_rel.cy = parent_int_rel.cy + dim.y + dim.margin_top + dim.padding_top;
205 int_rel.cx = dim.x + dim.margin_left + dim.padding_left;
206 int_rel.cy = dim.y + dim.margin_top + dim.padding_top;
215 dim.width - dim.padding_left - dim.padding_right - dim.margin_left - dim.margin_right;
221 dim.height - dim.padding_top - dim.padding_bottom - dim.margin_top - dim.margin_bottom;
226 std::vector<std::shared_ptr<components::component_base_t>> pending;
234 auto c_dim = child->get_dimensional_relations();
237 total_w = std::max(total_w, child_max_w);
238 total_h = std::max(total_h, child_max_h);
240 pending.push_back(child);
246 int_rel.cw = total_w;
249 int_rel.cw + dim.padding_left + dim.padding_right + dim.margin_left + dim.margin_right;
255 int_rel.ch = total_h;
258 int_rel.ch + dim.padding_top + dim.padding_bottom + dim.margin_top + dim.margin_bottom;
262 return std::all_of(pending.begin(), pending.end(), [](
const auto& it) {
263 return compute_dimensions(it.get());
269 void Layout::update_dimensions() {
270 ZoneScopedN(
"Dimensions");
275 if (!c->
parent.has_value()) {
276 LOG::print{ERROR}(
"Could not compute dimensions");
285 ZoneScopedN(
"Update Component");
286 std::scoped_lock lock{component_renderer->compositing_mutex()};
287 component_updater->update(target, *style_archive);
288 component_stylist->apply_style(target);
292 if (c->state()->_dirty) {
293 std::scoped_lock lock{component_renderer->compositing_mutex()};
294 component_updater->update(c, *style_archive);
298 for (
auto& item: c->children)
306 ZoneScopedN(
"Render If Dirty");
308 ZoneScopedN(
"Update");
313 component_stylist->apply_style(root);
315 component_renderer->render(*win->native(), root);
321 ZoneScopedN(
"Find by coords");
322 return root->find_by_coords(x, y);
326 style_archive->add_stylesheet(style_sheet);
335 ZoneScopedN(
"Layout:bind_window");
339 root_state->window = this->win;
341 auto [w, h] = win->get_size();
342 auto dim = root->get_dimensional_relations();
343 static const auto* width_field = refl::type_info::from<components::style_base_t>()
346 static const auto* height_field = refl::type_info::from<components::style_base_t>()
349 root->get_style_data().set_base_field_override(
352 root->get_style_data().set_base_field_override(
356 component_stylist->apply_style(root);
359 component_updater->update(root, *style_archive);
361 component_updater->update(root, *style_archive);
365 component_renderer->render(*win->native(), root);
368 listeners = make_event_listeners();
371 *win->get_executor()->get_spawn_context()->get_resource<
AnimationSystem>();
373 component_renderer->repaint_component(component);
375 anim_system.
s_render_all.connect([&](
bool& should_compose) {
376 should_compose = should_compose or component_renderer->render_all(*win->native(), root);
379 component_renderer->compose_all(*win->native(), root);
386 ZoneScopedN(
"Layout:set_hovering_flag");
387 if (clear_children) {
388 for (
const auto& c_state: std::ranges::views::values(state->
children_states)) {
412 if (c_state.get() != state) {
429 ZoneScopedN(
"Layout:clear_hovering_flag");
430 if (state->hovering) {
431 state->hovering =
false;
433 if (state->component_instance.has_value()) {
434 auto& h_int_rel = state->component_instance.value()->get_internal_relations();
437 state->component_instance.value()->get_event_dispatcher()->dispatch_mouse_exit(
438 exit_rel_x, exit_rel_y
441 component_stylist->apply_style(state->component_instance.value());
446 for (
const auto& c_state: std::ranges::views::values(state->children_states)) {
452 template <
typename Component>
454 ZoneScopedN(
"CWindow:make");
465 void CWindow::builder_t::configure_layout_style() {
466 ZoneScopedN(
"CWindow:builder:configure_layout_style");
467 for (
const auto& path: this->stylesheets_) {
470 for (
const auto& str: this->styles_) {
fabric::wiring::output_signal< AnimationSystem, bool & > s_render_all
fabric::wiring::output_signal< AnimationSystem, components::component_base_t::sptr > s_repaint
fabric::wiring::output_signal< AnimationSystem > s_compose_all
std::shared_ptr< CWindow > sptr
static builder_t make(Layout *layout)
bool render_if_dirty(const components::component_base_t::sptr &c)
void bind_window(const CWindow::sptr &_win)
bool set_hovering_flag(components::component_state_t *state, const MotionEvent &ev, bool clear_children=true)
bool update_all_dirty(const components::component_base_t::sptr &c)
void update_component(const components::component_base_t::sptr &target)
void attach_stylesheet(const StyleSheet::sptr &style_sheet)
void clear_hovering_flag(const components::component_state_ref &state, const MotionEvent &ev)
friend Layout * create(C &&root_component)
components::component_state_ref get_root_state() const
components::component_base_t * find_by_coords(dimensions::screen_measure x, dimensions::screen_measure y)
std::shared_ptr< StyleArchive > sptr
std::shared_ptr< StyleSheet > sptr
static sptr parse(auto input)
std::list< std::shared_ptr< component_base_t > > children
virtual component_dimensional_relations_t get_dimensional_relations()=0
internal_relations_t & get_internal_relations()
std::optional< component_base_t * > parent
style_data_base_t & get_style_data()
std::shared_ptr< component_base_t > sptr
std::shared_ptr< component_renderer_t > sptr
void queue_render(const component_base_t::sptr &component)
component_state_t * parent()
std::optional< std::shared_ptr< component_base_t > > component_instance
void mark_dirty()
Marks this component state as needing to be redrawn.
std::unordered_map< std::string, component_state_ref > children_states
void apply_style(const component_base_t::sptr &component)
void compile_style_rule_list(const component_base_t::sptr &component, StyleArchive &style_archive)
std::shared_ptr< component_stylist_t > sptr
std::shared_ptr< component_updater_t > sptr
virtual bool has_base_field_override(refl::field_path field_path)=0
std::shared_ptr< component_state_t > component_state_ref
const S & get_value(dimension< S > &dimension)
quantify::quantity_t< screen::pixel, double > screen_measure
static bool compute_dimensions(cydui::components::component_base_t *rt)
Layout * create(C &&root_component)
void bind_layout(Layout *layout, const CWindow::sptr &window)
dimensions::dimension< dimensions::screen_measure > dimension_t
static void mount_component(component_base_t *component)
static std::shared_ptr< component_state_t > create_state_instance(component_base_t *component)