vizia_core/systems/
layout.rs
1use morphorm::Node;
2use vizia_storage::LayoutTreeIterator;
3
4use crate::layout::node::SubLayout;
5use crate::prelude::*;
6
7use super::{text_layout_system, text_system};
8
9pub(crate) fn layout_system(cx: &mut Context) {
15 text_system(cx);
16
17 if cx.style.system_flags.contains(SystemFlags::RELAYOUT) {
18 Entity::root().layout(
20 &mut cx.cache,
21 &cx.tree,
22 &cx.style,
23 &mut SubLayout {
24 text_context: &mut cx.text_context,
25 resource_manager: &cx.resource_manager,
26 },
27 );
28
29 let cx = &mut EventContext::new(cx);
30
31 let iter = LayoutTreeIterator::full(cx.tree);
32
33 for entity in iter {
34 cx.current = entity;
35 if cx.style.display.get(entity).copied().unwrap_or_default() == Display::None {
36 continue;
37 }
38 if let Some(parent) = cx.tree.get_layout_parent(entity) {
40 let parent_bounds = cx.cache.get_bounds(parent);
41 if let Some(bounds) = cx.cache.bounds.get_mut(entity) {
42 if let Some(relative_bounds) = cx.cache.relative_bounds.get(entity) {
43 let x = relative_bounds.x + parent_bounds.x;
44 let y = relative_bounds.y + parent_bounds.y;
45 let w = relative_bounds.w;
46 let h = relative_bounds.h;
47
48 let mut geo_changed = GeoChanged::empty();
49
50 if x != bounds.x {
51 geo_changed.set(GeoChanged::POSX_CHANGED, true);
52 }
53
54 if y != bounds.y {
55 geo_changed.set(GeoChanged::POSY_CHANGED, true);
56 }
57
58 if w != bounds.w {
59 geo_changed.set(GeoChanged::WIDTH_CHANGED, true);
60 cx.cache.path.remove(entity);
61 }
62
63 if h != bounds.h {
64 geo_changed.set(GeoChanged::HEIGHT_CHANGED, true);
65 cx.cache.path.remove(entity);
66 }
67
68 if let Some(geo) = cx.cache.geo_changed.get_mut(entity) {
69 *geo = geo_changed;
70 }
71
72 let new_bounds = BoundingBox { x, y, w, h };
73
74 *bounds = new_bounds;
79 }
80 }
81 }
82
83 if let Some(geo) = cx.cache.geo_changed.get(entity).copied() {
84 if !geo.is_empty()
85 {
87 cx.needs_redraw();
88 cx.style.needs_text_layout(entity);
89 }
90
91 if !geo.is_empty() {
94 let mut event = Event::new(WindowEvent::GeometryChanged(geo))
95 .target(entity)
96 .origin(entity)
97 .propagate(Propagation::Direct);
98 visit_entity(cx, entity, &mut event);
99 }
100 }
101
102 if let Some(geo) = cx.cache.geo_changed.get_mut(entity) {
103 *geo = GeoChanged::empty();
104 }
105 }
106
107 if let Some(proxy) = &cx.event_proxy {
110 let event = Event::new(WindowEvent::MouseMove(cx.mouse.cursor_x, cx.mouse.cursor_y))
111 .target(Entity::root())
112 .origin(Entity::root())
113 .propagate(Propagation::Up);
114
115 proxy.send(event).expect("Failed to send event");
116 }
117
118 cx.style.system_flags.set(SystemFlags::RELAYOUT, false);
119 }
120
121 text_layout_system(cx);
122}
123
124fn visit_entity(cx: &mut EventContext, entity: Entity, event: &mut Event) {
125 if let Some(ids) =
127 cx.models.get(&entity).map(|models| models.keys().cloned().collect::<Vec<_>>())
128 {
129 for id in ids {
130 if let Some(mut model) =
131 cx.models.get_mut(&entity).and_then(|models| models.remove(&id))
132 {
133 cx.current = entity;
134
135 model.event(cx, event);
136
137 cx.models.get_mut(&entity).and_then(|models| models.insert(id, model));
138 }
139 }
140 }
141
142 if event.meta.consumed {
144 return;
145 }
146
147 if let Some(mut view) = cx.views.remove(&entity) {
149 cx.current = entity;
150 view.event(cx, event);
151
152 cx.views.insert(entity, view);
153 }
154}