1use zng_layout::{
2 context::{InlineConstraints, InlineConstraintsLayout, InlineConstraintsMeasure, InlineSegment, InlineSegmentPos, LAYOUT, LayoutMask},
3 unit::{Factor, Px, PxBox, PxPoint, PxRect, PxSize, PxVector},
4};
5use zng_state_map::{OwnedStateMap, StateId, StateMapMut, StateValue};
6use zng_task::parking_lot::Mutex;
7use zng_unique_id::IdMap;
8
9use crate::{
10 DInstant, INSTANT,
11 render::TransformStyle,
12 update::{InfoUpdates, LayoutUpdates, UPDATES, UpdateFlags},
13 widget::{WIDGET, WidgetId, WidgetUpdateMode, border::BORDER, node::UiNode},
14 window::{WINDOW, WindowId},
15};
16
17use super::{hit::ParallelSegmentOffsets, *};
18
19pub enum WidgetInfoMeta {}
21
22pub struct WidgetInfoBuilder {
26 info_widgets: Arc<InfoUpdates>,
27 window_id: WindowId,
28 pub(super) access_enabled: access::AccessEnabled,
29 started_access: bool,
30
31 node: tree::NodeId,
32 widget_id: WidgetId,
33 meta: Arc<Mutex<OwnedStateMap<WidgetInfoMeta>>>,
34
35 tree: Tree<WidgetInfoData>,
36 interactivity_filters: InteractivityFilters,
37
38 scale_factor: Factor,
39
40 build_meta: Arc<Mutex<OwnedStateMap<WidgetInfoMeta>>>,
41
42 build_start: DInstant,
43 pushed_widgets: u32,
44}
45impl WidgetInfoBuilder {
46 pub fn new(
48 info_widgets: Arc<InfoUpdates>,
49 window_id: WindowId,
50 access_enabled: access::AccessEnabled,
51 root_id: WidgetId,
52 root_bounds_info: WidgetBoundsInfo,
53 root_border_info: WidgetBorderInfo,
54 scale_factor: Factor,
55 ) -> Self {
56 let tree = Tree::new(WidgetInfoData {
57 id: root_id,
58 is_reused: false,
59 bounds_info: root_bounds_info,
60 border_info: root_border_info,
61 meta: Arc::new(OwnedStateMap::new()),
62 interactivity_filters: vec![],
63 local_interactivity: Interactivity::ENABLED,
64 cache: Mutex::new(WidgetInfoCache { interactivity: None }),
65 });
66 let mut lookup = IdMap::default();
67 let root_node = tree.root().id();
68 lookup.insert(root_id, root_node);
69
70 let mut builder = WidgetInfoBuilder {
71 info_widgets,
72 window_id,
73 access_enabled,
74 started_access: access_enabled.is_enabled() && WINDOW.info().access_enabled().is_disabled(),
75 node: root_node,
76 tree,
77 interactivity_filters: vec![],
78 meta: Arc::default(),
79 widget_id: root_id,
80 scale_factor,
81 build_meta: Arc::default(),
82 build_start: INSTANT.now(),
83 pushed_widgets: 1, };
85
86 if let Some(mut b) = builder.access() {
87 b.set_role(super::access::AccessRole::Application);
88 }
89
90 builder
91 }
92
93 fn node(&mut self, id: tree::NodeId) -> tree::NodeMut<'_, WidgetInfoData> {
94 self.tree.index_mut(id)
95 }
96
97 pub fn widget_id(&self) -> WidgetId {
99 self.widget_id
100 }
101
102 pub fn with_build_meta<R>(&mut self, visitor: impl FnOnce(StateMapMut<WidgetInfoMeta>) -> R) -> R {
106 visitor(self.build_meta.lock().borrow_mut())
107 }
108 pub fn set_build_meta<T: StateValue>(&mut self, id: impl Into<StateId<T>>, value: impl Into<T>) {
110 let id = id.into();
111 let value = value.into();
112 self.with_build_meta(|mut s| s.set(id, value));
113 }
114 pub fn flag_build_meta(&mut self, id: impl Into<StateId<()>>) {
116 let id = id.into();
117 self.with_build_meta(|mut s| s.flag(id));
118 }
119
120 pub fn with_meta<R>(&mut self, visitor: impl FnOnce(StateMapMut<WidgetInfoMeta>) -> R) -> R {
122 visitor(self.meta.lock().borrow_mut())
123 }
124 pub fn set_meta<T: StateValue>(&mut self, id: impl Into<StateId<T>>, value: impl Into<T>) {
128 let id = id.into();
129 let value = value.into();
130 self.with_meta(|mut s| s.set(id, value));
131 }
132 pub fn flag_meta(&mut self, id: impl Into<StateId<()>>) {
134 let id = id.into();
135 self.with_meta(|mut s| s.flag(id));
136 }
137
138 pub fn push_widget(&mut self, f: impl FnOnce(&mut Self)) {
142 let id = WIDGET.id();
143 if !WIDGET.take_update(UpdateFlags::INFO) && !self.info_widgets.delivery_list().enter_widget(id) && !self.started_access {
144 let tree = WINDOW.info();
146 if let Some(wgt) = tree.get(id) {
147 self.tree.index_mut(self.node).push_reuse(wgt.node(), &mut |old_data| {
148 let mut r = old_data.clone();
149 r.is_reused = true;
150 r.cache.get_mut().interactivity = None;
151 for filter in &r.interactivity_filters {
152 self.interactivity_filters.push(filter.clone());
153 }
154 r
155 });
156 return;
157 }
158 }
159
160 let parent_node = self.node;
161 let parent_widget_id = self.widget_id;
162 let parent_meta = mem::take(&mut self.meta);
163
164 let bounds_info = WIDGET.bounds();
165 let border_info = WIDGET.border();
166
167 self.widget_id = id;
168 self.node = self
169 .node(parent_node)
170 .push_child(WidgetInfoData {
171 id,
172 is_reused: false,
173 bounds_info,
174 border_info,
175 meta: Arc::new(OwnedStateMap::new()),
176 interactivity_filters: vec![],
177 local_interactivity: Interactivity::ENABLED,
178 cache: Mutex::new(WidgetInfoCache { interactivity: None }),
179 })
180 .id();
181
182 self.pushed_widgets += 1;
183
184 f(self);
185
186 let meta = mem::replace(&mut self.meta, parent_meta);
187 let mut node = self.node(self.node);
188 node.value().meta = Arc::new(Arc::try_unwrap(meta).unwrap().into_inner());
189 node.close();
190
191 self.node = parent_node;
192 self.widget_id = parent_widget_id;
193 }
194
195 pub fn push_interactivity(&mut self, interactivity: Interactivity) {
201 let mut node = self.node(self.node);
202 let v = node.value();
203 v.local_interactivity |= interactivity;
204 }
205
206 pub fn push_interactivity_filter(&mut self, filter: impl Fn(&InteractivityFilterArgs) -> Interactivity + Send + Sync + 'static) {
217 let filter = Arc::new(filter);
218 self.interactivity_filters.push(filter.clone());
219 self.node(self.node).value().interactivity_filters.push(filter);
220 }
221
222 pub fn with_children_range(&mut self, info: impl FnOnce(&mut Self)) -> ops::Range<usize> {
224 let before_count = self.tree.index(self.node).children_count();
225 info(self);
226 before_count..self.tree.index(self.node).children_count()
227 }
228
229 pub fn parallel_split(&self) -> ParallelBuilder<Self> {
234 let node = self.tree.index(self.node).value();
235 let tree = Tree::new(WidgetInfoData {
236 id: node.id,
237 is_reused: node.is_reused,
238 bounds_info: node.bounds_info.clone(),
239 border_info: node.border_info.clone(),
240 meta: node.meta.clone(),
241 interactivity_filters: vec![],
242 local_interactivity: node.local_interactivity,
243 cache: Mutex::new(WidgetInfoCache { interactivity: None }),
244 });
245 ParallelBuilder(Some(Self {
246 info_widgets: self.info_widgets.clone(),
247 window_id: self.window_id,
248 access_enabled: self.access_enabled,
249 started_access: self.started_access,
250 widget_id: self.widget_id,
251 meta: self.meta.clone(),
252 node: tree.root().id(),
253 tree,
254 interactivity_filters: vec![],
255 scale_factor: self.scale_factor,
256 build_meta: self.build_meta.clone(),
257 build_start: self.build_start,
258 pushed_widgets: 0,
259 }))
260 }
261
262 pub fn parallel_fold(&mut self, mut split: ParallelBuilder<Self>) {
264 let mut split = split.take();
265
266 self.interactivity_filters.append(&mut split.interactivity_filters);
267 self.pushed_widgets += split.pushed_widgets;
268 {
269 debug_assert!(Arc::ptr_eq(&self.meta, &split.meta));
270
271 let mut split_node = split.tree.root_mut();
272 let mut node = self.node(self.node);
273 let split_node = split_node.value();
274 let node = node.value();
275
276 node.interactivity_filters.append(&mut split_node.interactivity_filters);
277 node.local_interactivity |= split_node.local_interactivity;
278 }
279
280 self.tree.index_mut(self.node).parallel_fold(split.tree, &mut |d| WidgetInfoData {
281 id: d.id,
282 is_reused: d.is_reused,
283 bounds_info: d.bounds_info.clone(),
284 border_info: d.border_info.clone(),
285 meta: d.meta.clone(),
286 interactivity_filters: mem::take(&mut d.interactivity_filters),
287 local_interactivity: d.local_interactivity,
288 cache: Mutex::new(d.cache.get_mut().clone()),
289 });
290 }
291
292 pub fn finalize(mut self, previous_tree: Option<WidgetInfoTree>, notify: bool) -> WidgetInfoTree {
296 let mut node = self.tree.root_mut();
297 let meta = Arc::new(Arc::try_unwrap(self.meta).unwrap().into_inner());
298 node.value().meta = meta;
299 node.close();
300
301 let generation;
302 let widget_count_offsets;
303 let spatial_bounds;
304 let transform_changed_subs;
305 let visibility_changed_subs;
306
307 if let Some(t) = &previous_tree {
308 let t = t.0.frame.read();
309 generation = t.stats.generation.wrapping_add(1);
310 widget_count_offsets = t.widget_count_offsets.clone();
311 spatial_bounds = t.spatial_bounds;
312 transform_changed_subs = t.transform_changed_subs.clone();
313 visibility_changed_subs = t.visibility_changed_subs.clone();
314 } else {
315 generation = 0;
316 widget_count_offsets = ParallelSegmentOffsets::default();
317 spatial_bounds = PxBox::zero();
318 transform_changed_subs = IdMap::new();
319 visibility_changed_subs = IdMap::new();
320 }
321
322 let mut lookup = IdMap::new();
323 lookup.reserve(self.tree.len());
324 let mut out_of_bounds = vec![];
325
326 for (id, data) in self.tree.iter() {
327 if lookup.insert(data.id, id).is_some() {
328 tracing::error!("widget `{}` repeated in info tree", data.id);
329 }
330 if data.bounds_info.is_actually_out_of_bounds() {
331 out_of_bounds.push(id);
332 }
333 }
334 out_of_bounds.shrink_to_fit();
335
336 let tree = WidgetInfoTree(Arc::new(WidgetInfoTreeInner {
337 window_id: self.window_id,
338 access_enabled: self.access_enabled,
339 lookup,
340 interactivity_filters: self.interactivity_filters,
341 build_meta: Arc::new(mem::take(&mut self.build_meta.lock())),
342
343 frame: RwLock::new(WidgetInfoTreeFrame {
344 stats: WidgetInfoTreeStats::new(self.build_start, self.tree.len() as u32 - self.pushed_widgets, generation),
345 stats_update: Default::default(),
346 out_of_bounds: Arc::new(out_of_bounds),
347 out_of_bounds_update: Default::default(),
348 scale_factor: self.scale_factor,
349 spatial_bounds,
350 widget_count_offsets,
351 transform_changed_subs,
352 visibility_changed_subs,
353 view_process_gen: ViewProcessGen::INVALID,
354 }),
355
356 tree: self.tree,
357 }));
358
359 if notify {
360 let mut prev_tree = WeakWidgetInfoTree::new();
361 if let Some(t) = previous_tree {
362 prev_tree = t.downgrade();
363 UPDATES.once_next_update("", move || {
364 let _hold_once = &t;
365 });
366 }
367 let args = WidgetTreeChangedArgs::now(prev_tree, tree.clone(), false);
368 WIDGET_TREE_CHANGED_EVENT.notify(args);
369 }
370
371 tree
372 }
373}
374
375crate::event::event! {
376 pub static WIDGET_TREE_CHANGED_EVENT: WidgetTreeChangedArgs;
381}
382
383crate::event::event_args! {
384 pub struct WidgetTreeChangedArgs {
386 pub prev_tree: WeakWidgetInfoTree,
393
394 pub tree: WidgetInfoTree,
396
397 pub is_update: bool,
404
405 ..
406
407 fn is_in_target(&self, _id: WidgetId) -> bool {
409 true
410 }
411 }
412}
413
414#[derive(Clone, Debug, Default, PartialEq)]
416#[non_exhaustive]
417pub struct WidgetInlineMeasure {
418 pub first: PxSize,
422
423 pub first_wrapped: bool,
425
426 pub first_segs: Arc<Vec<InlineSegment>>,
430
431 pub last: PxSize,
440
441 pub last_wrapped: bool,
443
444 pub last_segs: Arc<Vec<InlineSegment>>,
448}
449impl WidgetInlineMeasure {
450 pub fn with_first_segs(&mut self, f: impl FnOnce(&mut Vec<InlineSegment>)) {
455 Self::with_segs(&mut self.first_segs, f)
456 }
457
458 pub fn with_last_segs(&mut self, f: impl FnOnce(&mut Vec<InlineSegment>)) {
463 Self::with_segs(&mut self.last_segs, f)
464 }
465
466 fn with_segs(items: &mut Arc<Vec<InlineSegment>>, f: impl FnOnce(&mut Vec<InlineSegment>)) {
467 match Arc::get_mut(items) {
468 Some(items) => {
469 items.clear();
470 f(items);
471 }
472 None => {
473 let mut new = vec![];
474 f(&mut new);
475 *items = Arc::new(new);
476 }
477 }
478 }
479
480 pub fn is_default(&self) -> bool {
484 self.first.is_empty()
485 && !self.first_wrapped
486 && self.first_segs.is_empty()
487 && self.last.is_empty()
488 && !self.last_wrapped
489 && self.last_segs.is_empty()
490 }
491}
492
493#[derive(Clone, Copy, Debug, PartialEq, Eq)]
497#[non_exhaustive]
498pub struct InlineSegmentInfo {
499 pub x: Px,
501 pub width: Px,
505}
506
507impl InlineSegmentInfo {
508 pub fn new(x: Px, width: Px) -> Self {
510 Self { x, width }
511 }
512}
513
514#[derive(Debug, Default)]
516#[non_exhaustive]
517pub struct WidgetInlineInfo {
518 pub rows: Vec<PxRect>,
522
523 pub first_segs: Vec<InlineSegmentInfo>,
533
534 pub last_segs: Vec<InlineSegmentInfo>,
536
537 pub inner_size: PxSize,
539
540 negative_space: Mutex<(Arc<Vec<PxRect>>, bool)>,
541}
542impl WidgetInlineInfo {
543 pub fn set_first_segs(&mut self, segs: impl Iterator<Item = InlineSegmentInfo>) {
551 Self::set_segs(&mut self.first_segs, segs);
552 self.invalidate_negative_space();
553 }
554
555 pub fn set_last_segs(&mut self, segs: impl Iterator<Item = InlineSegmentInfo>) {
563 Self::set_segs(&mut self.last_segs, segs);
564 self.invalidate_negative_space();
565 }
566
567 fn set_segs(vec: &mut Vec<InlineSegmentInfo>, segs: impl Iterator<Item = InlineSegmentInfo>) {
568 vec.clear();
569
570 let mut needs_sort = false;
571
572 for seg in segs {
573 if seg.width <= 0 {
574 continue;
575 }
576
577 if let Some(last) = vec.last_mut() {
578 let la = last.x;
579 let lb = last.x + last.width;
580
581 let a = seg.x;
582 let b = seg.x + seg.width;
583
584 if la.max(a) <= lb.min(b) {
585 last.x = a.min(la);
587 last.width = b.max(lb) - last.x;
588 continue;
589 }
590
591 needs_sort |= a < la;
592 }
593 vec.push(seg);
594 }
595
596 if needs_sort {
597 vec.sort_unstable_by_key(|s| s.x);
598 }
599 }
600
601 pub fn union(&self) -> PxRect {
603 self.rows.iter().fold(PxRect::zero(), |union, row| union.union(row))
604 }
605
606 pub fn negative_space(&self) -> Arc<Vec<PxRect>> {
614 let mut space = self.negative_space.lock();
615 if space.1 {
616 return space.0.clone();
617 }
618
619 let mut vec = Arc::try_unwrap(mem::take(&mut space.0)).unwrap_or_default();
620 vec.clear();
621
622 self.negative_enveloped(&mut vec, PxRect::from_size(self.inner_size));
623
624 let r = Arc::new(vec);
625 *space = (r.clone(), true);
626 r
627 }
628
629 pub fn invalidate_negative_space(&mut self) {
633 self.negative_space.get_mut().1 = false;
634 }
635
636 fn negative_enveloped(&self, space: &mut Vec<PxRect>, bounds: PxRect) {
637 let bounds_max_x = bounds.max_x();
638 let mut last_max_y = bounds.origin.y;
639
640 for r in &self.rows {
641 let spacing_y = r.origin.y - last_max_y;
642 if spacing_y > Px(0) {
643 space.push(PxRect::new(
644 PxPoint::new(bounds.origin.x, last_max_y),
645 PxSize::new(bounds.size.width, spacing_y),
646 ));
647 }
648 last_max_y = r.max_y();
649
650 let left = r.origin.x - bounds.origin.x;
651 if left > Px(0) {
652 space.push(PxRect::new(
653 PxPoint::new(bounds.origin.x, r.origin.y),
654 PxSize::new(left, r.size.height),
655 ));
656 }
657 let max_x = r.max_x();
658 let right = bounds_max_x - max_x;
659 if right > Px(0) {
660 space.push(PxRect::new(PxPoint::new(max_x, r.origin.y), PxSize::new(right, r.size.height)));
661 }
662 }
663 let spacing_y = bounds.max_y() - last_max_y;
664 if spacing_y > Px(0) {
665 space.push(PxRect::new(
666 PxPoint::new(bounds.origin.x, last_max_y),
667 PxSize::new(bounds.size.width, spacing_y),
668 ));
669 }
670
671 if let Some(r) = self.rows.first()
672 && !self.first_segs.is_empty()
673 {
674 let mut x = r.origin.x;
675 for seg in self.first_segs.iter() {
676 let blank = seg.x - x;
677 if blank > Px(0) {
678 space.push(PxRect::new(PxPoint::new(x, r.origin.y), PxSize::new(blank, r.size.height)));
679 }
680 x = seg.x + seg.width;
681 }
682 let blank = r.max_x() - x;
683 if blank > Px(0) {
684 space.push(PxRect::new(PxPoint::new(x, r.origin.y), PxSize::new(blank, r.size.height)));
685 }
686 }
687 if let Some(r) = self.rows.last()
688 && !self.last_segs.is_empty()
689 {
690 let mut x = r.origin.x;
691 for seg in self.last_segs.iter() {
692 let blank = seg.x - x;
693 if blank > Px(0) {
694 space.push(PxRect::new(PxPoint::new(x, r.origin.y), PxSize::new(blank, r.size.height)));
695 }
696 x = seg.x + seg.width;
697 }
698 let blank = r.max_x() - x;
699 if blank > Px(0) {
700 space.push(PxRect::new(PxPoint::new(x, r.origin.y), PxSize::new(blank, r.size.height)));
701 }
702 }
703 }
704
705 pub fn clear(&mut self) {
707 self.first_segs.clear();
708 self.last_segs.clear();
709 self.rows.clear();
710 self.inner_size = PxSize::zero();
711 self.invalidate_negative_space();
712 }
713
714 pub fn is_default(&self) -> bool {
718 self.rows.is_empty() && self.first_segs.is_empty() && self.last_segs.is_empty() && self.inner_size.is_empty()
719 }
720}
721impl Clone for WidgetInlineInfo {
722 fn clone(&self) -> Self {
723 Self {
724 rows: self.rows.clone(),
725 first_segs: self.first_segs.clone(),
726 last_segs: self.last_segs.clone(),
727 inner_size: self.inner_size,
728 negative_space: Mutex::new((Arc::new(vec![]), false)),
729 }
730 }
731
732 fn clone_from(&mut self, source: &Self) {
733 self.clear();
734 self.rows.extend_from_slice(&source.rows);
735 self.first_segs.extend_from_slice(&source.first_segs);
736 self.last_segs.extend_from_slice(&source.last_segs);
737 self.inner_size = source.inner_size;
738 }
739}
740impl PartialEq for WidgetInlineInfo {
741 fn eq(&self, other: &Self) -> bool {
742 self.rows == other.rows
743 && self.first_segs == other.first_segs
744 && self.last_segs == other.last_segs
745 && self.inner_size == other.inner_size
746 }
747}
748
749pub struct WidgetMeasure {
753 layout_widgets: Arc<LayoutUpdates>,
754 inline: Option<WidgetInlineMeasure>,
755 inline_locked: bool,
756}
757impl WidgetMeasure {
758 pub(crate) fn new(layout_widgets: Arc<LayoutUpdates>) -> Self {
759 Self {
760 layout_widgets,
761 inline: None,
762 inline_locked: false,
763 }
764 }
765
766 pub fn new_reuse(inline: Option<WidgetInlineMeasure>) -> Self {
770 let mut r = Self::new(Arc::default());
771 r.inline = inline;
772 r
773 }
774
775 pub fn is_inline(&self) -> bool {
777 self.inline.is_some()
778 }
779
780 pub fn inline(&mut self) -> Option<&mut WidgetInlineMeasure> {
786 self.inline.as_mut()
787 }
788
789 pub fn disable_inline(&mut self) {
802 if !self.inline_locked {
803 self.inline = None;
804 }
805 }
806
807 pub fn measure_block(&mut self, child: &mut UiNode) -> PxSize {
809 self.disable_inline();
810 LAYOUT.with_no_inline(|| child.measure(self))
811 }
812
813 pub fn measure_inline(&mut self, first_max: Px, mid_clear_min: Px, child: &mut UiNode) -> (Option<WidgetInlineMeasure>, PxSize) {
826 let constraints = InlineConstraints::Measure(InlineConstraintsMeasure::new(first_max, mid_clear_min));
827 let metrics = LAYOUT.metrics().with_inline_constraints(Some(constraints));
828 let size = LAYOUT.with_context(metrics, || child.measure(self));
829 let inline = child
830 .as_widget()
831 .and_then(|mut w| w.with_context(WidgetUpdateMode::Ignore, || WIDGET.bounds().measure_inline()));
832 (inline, size)
833 }
834
835 pub fn with_widget(&mut self, measure: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
837 let metrics = LAYOUT.metrics();
838 let bounds = WIDGET.bounds();
839
840 let snap = metrics.snapshot();
841 if !WIDGET.layout_is_pending(&self.layout_widgets) {
842 let measure_uses = bounds.measure_metrics_used();
843 if bounds.measure_metrics().map(|m| m.masked_eq(&snap, measure_uses)).unwrap_or(false) {
844 let mut reused = false;
845 if let Some(inline) = self.inline() {
846 if let Some(prev) = bounds.measure_inline() {
847 *inline = prev;
848 reused = true;
849 }
850 } else {
851 reused = bounds.measure_inline().is_none();
852 }
853
854 if reused {
855 LAYOUT.register_metrics_use(measure_uses); return bounds.measure_outer_size();
857 }
858 }
859 }
860
861 let parent_inline = self.inline.take();
862 if LAYOUT.inline_constraints().is_some() {
863 self.inline = Some(Default::default());
864 }
865
866 let (measure_uses, size) = LAYOUT.capture_metrics_use(|| measure(self));
867
868 LAYOUT.register_metrics_use(measure_uses);
869 bounds.set_measure_metrics(Some(snap), measure_uses);
870 bounds.set_measure_outer_size(size);
871
872 if let Some(inline) = self.inline.take() {
873 if inline.is_default() && !size.is_empty() {
874 bounds.set_measure_inline(None);
876 } else {
877 #[cfg(debug_assertions)]
878 if !inline.last_wrapped && inline.first != inline.last {
879 tracing::error!(
880 "widget {:?} invalid inline measure, last {:?} != first {:?} but last did not wrap",
881 WIDGET.id(),
882 inline.last,
883 inline.first
884 );
885 }
886
887 bounds.set_measure_inline(Some(inline));
888 }
889 } else {
890 bounds.set_measure_inline(None);
891 }
892 self.inline = parent_inline;
893
894 size
895 }
896
897 pub fn with_inline_visual(&mut self, measure: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
904 self.inline_locked = true;
905 if self.inline.is_none() {
906 self.inline = Some(Default::default());
907 }
908 let metrics = LAYOUT.metrics();
909 let size = if metrics.inline_constraints().is_none() {
910 let constraints = InlineConstraints::Measure(InlineConstraintsMeasure::new(metrics.constraints().x.max_or(Px::MAX), Px(0)));
911 let metrics = metrics.with_inline_constraints(Some(constraints));
912 LAYOUT.with_context(metrics, || measure(self))
913 } else {
914 measure(self)
915 };
916 self.inline_locked = false;
917
918 let inline = self.inline.clone().unwrap();
919 let bounds = WIDGET.bounds();
920 if inline.is_default() && !size.is_empty() {
921 bounds.set_measure_inline(None);
923 } else {
924 bounds.set_measure_inline(Some(inline));
925 }
926 bounds.set_measure_outer_size(size);
927
928 size
929 }
930
931 pub fn parallel_split(&self) -> ParallelBuilder<WidgetMeasure> {
938 ParallelBuilder(Some(Self {
939 layout_widgets: self.layout_widgets.clone(),
940 inline: self.inline.clone(),
941 inline_locked: self.inline_locked,
942 }))
943 }
944
945 pub fn parallel_fold(&mut self, mut split: ParallelBuilder<WidgetMeasure>) {
947 let _ = split.take();
948 }
949}
950
951pub struct WidgetLayout {
953 layout_widgets: Arc<LayoutUpdates>,
954 bounds: WidgetBoundsInfo,
955 nest_group: LayoutNestGroup,
956 inline: Option<WidgetInlineInfo>,
957 needs_ref_count: Option<u32>,
958}
959impl WidgetLayout {
960 pub fn with_root_widget(layout_widgets: Arc<LayoutUpdates>, layout: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
964 Self {
965 layout_widgets,
966 bounds: WIDGET.bounds(),
967 nest_group: LayoutNestGroup::Inner,
968 inline: None,
969 needs_ref_count: None,
970 }
971 .with_widget(layout)
972 }
973
974 pub fn parallel_split(&self) -> ParallelBuilder<WidgetLayout> {
984 if self.nest_group != LayoutNestGroup::Child && WIDGET.parent_id().is_some() {
985 tracing::error!("called `parallel_split` outside child scope");
986 }
987 ParallelBuilder(Some(WidgetLayout {
988 layout_widgets: self.layout_widgets.clone(),
989 bounds: self.bounds.clone(),
990 nest_group: LayoutNestGroup::Child,
991 inline: None,
992 needs_ref_count: None,
993 }))
994 }
995
996 pub fn parallel_fold(&mut self, mut split: ParallelBuilder<WidgetLayout>) {
998 let folded = split.take();
999 assert_eq!(self.bounds, folded.bounds);
1000
1001 let count = self.needs_ref_count.unwrap_or(0) + folded.needs_ref_count.unwrap_or(0);
1002 self.needs_ref_count = Some(count);
1003 }
1004
1005 pub fn with_widget(&mut self, layout: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
1014 let metrics = LAYOUT.metrics();
1015 let bounds = WIDGET.bounds();
1016
1017 let snap = metrics.snapshot();
1018 if let Some(c) = &mut self.needs_ref_count {
1019 *c += 1;
1020 }
1021
1022 if !WIDGET.take_update(UpdateFlags::LAYOUT) && !self.layout_widgets.delivery_list().enter_widget(WIDGET.id()) {
1023 let uses = bounds.metrics_used();
1025 if bounds.metrics().map(|m| m.masked_eq(&snap, uses)).unwrap_or(false) {
1026 LAYOUT.register_metrics_use(uses); return bounds.outer_size();
1029 }
1030 }
1031
1032 let parent_needs_ref_count = self.needs_ref_count.take();
1033 let parent_inline = self.inline.take();
1034 if LAYOUT.inline_constraints().is_some() && bounds.measure_inline().is_some() {
1035 self.inline = bounds.take_inline();
1037 if let Some(inline) = self.inline.as_mut() {
1038 inline.clear();
1039 } else {
1040 self.inline = Some(Default::default());
1041 }
1042 }
1043 let parent_bounds = mem::replace(&mut self.bounds, bounds);
1044 self.nest_group = LayoutNestGroup::Inner;
1045 let prev_inner_offset = self.bounds.inner_offset();
1046 let prev_child_offset = self.bounds.child_offset();
1047 let prev_baseline = self.bounds.baseline();
1048 let prev_inner_offset_baseline = self.bounds.inner_offset_baseline();
1049 let prev_can_auto_hide = self.bounds.can_auto_hide();
1050 let prev_transform_style = self.bounds.transform_style();
1051 let prev_perspective = self.bounds.raw_perspective();
1052 let prev_perspective_origin = self.bounds.raw_perspective_origin();
1053 self.bounds.set_inner_offset(PxVector::zero());
1054 self.bounds.set_child_offset(PxVector::zero());
1055 self.bounds.set_baseline(Px(0));
1056 self.bounds.set_inner_offset_baseline(false);
1057 self.bounds.set_can_auto_hide(true);
1058 self.bounds.set_transform_style(TransformStyle::Flat);
1059 self.bounds.set_perspective(f32::INFINITY);
1060 self.bounds.set_perspective_origin(None);
1061
1062 let (uses, size) = LAYOUT.capture_metrics_use(|| layout(self));
1064
1065 LAYOUT.register_metrics_use(uses);
1066 self.bounds.set_outer_size(size);
1067 self.bounds.set_metrics(Some(snap), uses);
1068 if let Some(inline) = &mut self.inline {
1069 inline.inner_size = self.bounds.inner_size();
1070 inline.invalidate_negative_space();
1071 }
1072 self.bounds.set_inline(self.inline.take());
1073
1074 if prev_can_auto_hide != self.bounds.can_auto_hide() || prev_transform_style != self.bounds.transform_style() {
1075 WIDGET.render();
1076 } else if prev_inner_offset != self.bounds.inner_offset()
1077 || prev_child_offset != self.bounds.child_offset()
1078 || prev_inner_offset_baseline != self.bounds.inner_offset_baseline()
1079 || prev_perspective != self.bounds.raw_perspective()
1080 || prev_perspective_origin != self.bounds.raw_perspective_origin()
1081 || (self.bounds.inner_offset_baseline() && prev_baseline != self.bounds.baseline())
1082 {
1083 WIDGET.render_update();
1084 }
1085
1086 self.needs_ref_count = parent_needs_ref_count;
1087 self.inline = parent_inline;
1088 self.bounds = parent_bounds;
1089 self.nest_group = LayoutNestGroup::Child;
1090
1091 size
1092 }
1093
1094 pub fn with_inline_visual(&mut self, layout: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
1099 if self.is_inline() {
1100 let size = layout(self);
1101 WIDGET.bounds().set_inline(self.inline.clone());
1102 size
1103 } else {
1104 let bounds = WIDGET.bounds();
1105 if let Some(measure) = bounds.measure_inline() {
1106 let constraints = InlineConstraintsLayout::new(
1107 PxRect::from_size(measure.first),
1108 Px(0),
1109 {
1110 let mut r = PxRect::from_size(measure.last);
1111 r.origin.y = bounds.measure_outer_size().height - measure.last.height;
1112 r
1113 },
1114 Arc::new(vec![]),
1115 Arc::new(vec![]),
1116 );
1117
1118 self.inline = Some(Default::default());
1119
1120 let metrics = LAYOUT
1121 .metrics()
1122 .with_inline_constraints(Some(InlineConstraints::Layout(constraints)));
1123 let size = LAYOUT.with_context(metrics, || layout(self));
1124
1125 bounds.set_inline(self.inline.clone());
1126 size
1127 } else {
1128 layout(self)
1129 }
1130 }
1131 }
1132
1133 pub fn with_inner(&mut self, layout: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
1141 self.nest_group = LayoutNestGroup::Child;
1142 let size = BORDER.with_inner(|| layout(self));
1143 WIDGET.bounds().set_inner_size(size);
1144 self.nest_group = LayoutNestGroup::Inner;
1145 size
1146 }
1147
1148 pub fn with_child(&mut self, layout: impl FnOnce(&mut Self) -> PxSize) -> (PxSize, bool) {
1158 let parent_needs_ref_count = self.needs_ref_count.replace(0);
1159
1160 self.nest_group = LayoutNestGroup::Child;
1161 let child_size = layout(self);
1162 self.nest_group = LayoutNestGroup::Child;
1163
1164 let need_ref_frame = self.needs_ref_count != Some(1);
1165 self.needs_ref_count = parent_needs_ref_count;
1166 (child_size, need_ref_frame)
1167 }
1168
1169 pub fn require_child_ref_frame(&mut self) {
1176 if let Some(c) = &mut self.needs_ref_count {
1177 *c += 2;
1178 }
1179 }
1180
1181 pub fn with_branch_child(&mut self, layout: impl FnOnce(&mut Self) -> PxSize) -> (PxSize, PxVector) {
1188 let parent_needs_ref_count = self.needs_ref_count;
1189 let parent_translate = self.bounds.child_offset();
1190 let parent_inner_offset_baseline = self.bounds.inner_offset_baseline();
1191 self.bounds.set_child_offset(PxVector::zero());
1192 let parent_group = self.nest_group;
1193
1194 self.nest_group = LayoutNestGroup::Child;
1195 let child_size = layout(self);
1196
1197 let translate = self.bounds.child_offset();
1198 self.bounds.set_child_offset(parent_translate);
1199 self.bounds.set_inner_offset_baseline(parent_inner_offset_baseline);
1200 self.nest_group = parent_group;
1201 self.needs_ref_count = parent_needs_ref_count;
1202
1203 (child_size, translate)
1204 }
1205
1206 pub fn translate(&mut self, offset: PxVector) {
1211 match self.nest_group {
1212 LayoutNestGroup::Inner => {
1213 let mut o = self.bounds.inner_offset();
1214 o += offset;
1215 self.bounds.set_inner_offset(o);
1216 }
1217 LayoutNestGroup::Child => {
1218 let mut o = self.bounds.child_offset();
1219 o += offset;
1220 self.bounds.set_child_offset(o);
1221 }
1222 }
1223 }
1224
1225 pub fn set_baseline(&mut self, baseline: Px) {
1227 self.bounds.set_baseline(baseline);
1228 }
1229
1230 pub fn translate_baseline(&mut self, enabled: bool) {
1232 self.bounds.set_inner_offset_baseline(enabled);
1233 }
1234
1235 pub fn set_transform_style(&mut self, style: TransformStyle) {
1237 self.bounds.set_transform_style(style);
1238 }
1239
1240 pub fn set_perspective(&mut self, d: f32) {
1244 self.bounds.set_perspective(d)
1245 }
1246
1247 pub fn set_perspective_origin(&mut self, origin: PxPoint) {
1249 self.bounds.set_perspective_origin(Some(origin))
1250 }
1251
1252 pub fn allow_auto_hide(&mut self, enabled: bool) {
1259 self.bounds.set_can_auto_hide(enabled);
1260 }
1261
1262 pub fn collapse(&mut self) {
1272 WIDGET.take_update(UpdateFlags::LAYOUT);
1273 let tree = WINDOW.info();
1274 let id = WIDGET.id();
1275 if let Some(w) = tree.get(id) {
1276 for w in w.self_and_descendants() {
1277 let info = w.info();
1278 info.bounds_info.set_outer_size(PxSize::zero());
1279 info.bounds_info.set_inner_size(PxSize::zero());
1280 info.bounds_info.set_baseline(Px(0));
1281 info.bounds_info.set_inner_offset_baseline(false);
1282 info.bounds_info.set_can_auto_hide(true);
1283 info.bounds_info.set_inner_offset(PxVector::zero());
1284 info.bounds_info.set_child_offset(PxVector::zero());
1285 info.bounds_info.set_measure_metrics(None, LayoutMask::empty());
1286 info.bounds_info.set_metrics(None, LayoutMask::empty());
1287 info.bounds_info.set_is_collapsed(true);
1288 info.bounds_info.set_rendered(None, &tree);
1289 }
1290 } else {
1291 tracing::error!("collapse did not find `{}` in the info tree", id)
1292 }
1293 }
1294
1295 pub fn collapse_descendants(&mut self) {
1304 let tree = WINDOW.info();
1305 let id = WIDGET.id();
1306 if let Some(w) = tree.get(id) {
1307 for w in w.descendants() {
1308 let info = w.info();
1309 info.bounds_info.set_outer_size(PxSize::zero());
1310 info.bounds_info.set_inner_size(PxSize::zero());
1311 info.bounds_info.set_baseline(Px(0));
1312 info.bounds_info.set_inner_offset_baseline(false);
1313 info.bounds_info.set_can_auto_hide(true);
1314 info.bounds_info.set_inner_offset(PxVector::zero());
1315 info.bounds_info.set_child_offset(PxVector::zero());
1316 info.bounds_info.set_measure_metrics(None, LayoutMask::empty());
1317 info.bounds_info.set_metrics(None, LayoutMask::empty());
1318 info.bounds_info.set_is_collapsed(true);
1319 }
1320 } else {
1321 tracing::error!("collapse_descendants did not find `{}` in the info tree", id)
1322 }
1323 }
1324
1325 pub fn collapse_child(&mut self, index: usize) {
1334 let tree = WINDOW.info();
1335 let id = WIDGET.id();
1336 if let Some(w) = tree.get(id) {
1337 if let Some(w) = w.children().nth(index) {
1338 for w in w.self_and_descendants() {
1339 let info = w.info();
1340 info.bounds_info.set_outer_size(PxSize::zero());
1341 info.bounds_info.set_inner_size(PxSize::zero());
1342 info.bounds_info.set_baseline(Px(0));
1343 info.bounds_info.set_inner_offset_baseline(false);
1344 info.bounds_info.set_can_auto_hide(true);
1345 info.bounds_info.set_inner_offset(PxVector::zero());
1346 info.bounds_info.set_child_offset(PxVector::zero());
1347 info.bounds_info.set_measure_metrics(None, LayoutMask::empty());
1348 info.bounds_info.set_metrics(None, LayoutMask::empty());
1349 info.bounds_info.set_is_collapsed(true);
1350 }
1351 } else {
1352 tracing::error!(
1353 "collapse_child out-of-bounds for `{}` in the children of `{}` in the info tree",
1354 index,
1355 id
1356 )
1357 }
1358 } else {
1359 tracing::error!("collapse_child did not find `{}` in the info tree", id)
1360 }
1361 }
1362
1363 pub fn is_inline(&self) -> bool {
1368 self.inline.is_some()
1369 }
1370
1371 pub fn inline(&mut self) -> Option<&mut WidgetInlineInfo> {
1386 self.inline.as_mut()
1387 }
1388
1389 pub fn to_measure(&self, inline: Option<WidgetInlineMeasure>) -> WidgetMeasure {
1393 WidgetMeasure {
1394 layout_widgets: self.layout_widgets.clone(),
1395 inline,
1396 inline_locked: false,
1397 }
1398 }
1399
1400 pub fn layout_block(&mut self, child: &mut UiNode) -> PxSize {
1405 LAYOUT.with_no_inline(|| child.layout(self))
1406 }
1407
1408 pub fn layout_inline(
1417 &mut self,
1418 first: PxRect,
1419 mid_clear: Px,
1420 last: PxRect,
1421 first_segs: Arc<Vec<InlineSegmentPos>>,
1422 last_segs: Arc<Vec<InlineSegmentPos>>,
1423 child: &mut UiNode,
1424 ) -> PxSize {
1425 let constraints = InlineConstraints::Layout(InlineConstraintsLayout::new(first, mid_clear, last, first_segs, last_segs));
1426 let metrics = LAYOUT.metrics().with_inline_constraints(Some(constraints));
1427 LAYOUT.with_context(metrics, || child.layout(self))
1428 }
1429
1430 pub fn with_layout_updates(&mut self, layout_updates: Arc<LayoutUpdates>, layout: impl FnOnce(&mut WidgetLayout) -> PxSize) -> PxSize {
1434 let parent_layout_widgets = mem::replace(&mut self.layout_widgets, layout_updates);
1435 let r = layout(self);
1436 self.layout_widgets = parent_layout_widgets;
1437 r
1438 }
1439}
1440
1441#[derive(Debug, Clone, Copy, PartialEq)]
1442enum LayoutNestGroup {
1443 Inner,
1445 Child,
1447}
1448
1449#[must_use = "use in parallel task, then move it to `B::parallel_fold`"]
1456pub struct ParallelBuilder<B>(pub(crate) Option<B>);
1457impl<B> ParallelBuilder<B> {
1458 pub(crate) fn take(&mut self) -> B {
1459 self.0.take().expect("parallel builder finished")
1460 }
1461}
1462impl<B> ops::Deref for ParallelBuilder<B> {
1463 type Target = B;
1464
1465 fn deref(&self) -> &Self::Target {
1466 self.0.as_ref().expect("parallel builder finished")
1467 }
1468}
1469impl<B> ops::DerefMut for ParallelBuilder<B> {
1470 fn deref_mut(&mut self) -> &mut Self::Target {
1471 self.0.as_mut().expect("parallel builder finished")
1472 }
1473}
1474impl<B> Drop for ParallelBuilder<B> {
1475 fn drop(&mut self) {
1476 if self.0.is_some() && !std::thread::panicking() {
1477 tracing::error!("builder dropped without calling `{}::parallel_fold`", std::any::type_name::<B>())
1478 }
1479 }
1480}