1use parking_lot::Mutex;
2use zng_layout::{
3 context::{InlineConstraints, InlineConstraintsLayout, InlineConstraintsMeasure, InlineSegment, InlineSegmentPos, LAYOUT, LayoutMask},
4 unit::{Factor, Px, PxBox, PxPoint, PxRect, PxSize, PxVector},
5};
6use zng_state_map::{OwnedStateMap, StateId, StateMapMut, StateValue};
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 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 bounds.set_measure_metrics(Some(snap), measure_uses);
869 bounds.set_measure_outer_size(size);
870
871 if let Some(inline) = self.inline.take() {
872 if inline.is_default() && !size.is_empty() {
873 bounds.set_measure_inline(None);
875 } else {
876 #[cfg(debug_assertions)]
877 if !inline.last_wrapped && inline.first != inline.last {
878 tracing::error!(
879 "widget {:?} invalid inline measure, last {:?} != first {:?} but last did not wrap",
880 WIDGET.id(),
881 inline.last,
882 inline.first
883 );
884 }
885
886 bounds.set_measure_inline(Some(inline));
887 }
888 } else {
889 bounds.set_measure_inline(None);
890 }
891 self.inline = parent_inline;
892
893 size
894 }
895
896 pub fn with_inline_visual(&mut self, measure: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
903 self.inline_locked = true;
904 if self.inline.is_none() {
905 self.inline = Some(Default::default());
906 }
907 let metrics = LAYOUT.metrics();
908 let size = if metrics.inline_constraints().is_none() {
909 let constraints = InlineConstraints::Measure(InlineConstraintsMeasure::new(metrics.constraints().x.max_or(Px::MAX), Px(0)));
910 let metrics = metrics.with_inline_constraints(Some(constraints));
911 LAYOUT.with_context(metrics, || measure(self))
912 } else {
913 measure(self)
914 };
915 self.inline_locked = false;
916
917 let inline = self.inline.clone().unwrap();
918 let bounds = WIDGET.bounds();
919 if inline.is_default() && !size.is_empty() {
920 bounds.set_measure_inline(None);
922 } else {
923 bounds.set_measure_inline(Some(inline));
924 }
925 bounds.set_measure_outer_size(size);
926
927 size
928 }
929
930 pub fn parallel_split(&self) -> ParallelBuilder<WidgetMeasure> {
937 ParallelBuilder(Some(Self {
938 layout_widgets: self.layout_widgets.clone(),
939 inline: self.inline.clone(),
940 inline_locked: self.inline_locked,
941 }))
942 }
943
944 pub fn parallel_fold(&mut self, mut split: ParallelBuilder<WidgetMeasure>) {
946 let _ = split.take();
947 }
948}
949
950pub struct WidgetLayout {
952 layout_widgets: Arc<LayoutUpdates>,
953 bounds: WidgetBoundsInfo,
954 nest_group: LayoutNestGroup,
955 inline: Option<WidgetInlineInfo>,
956 needs_ref_count: Option<u32>,
957}
958impl WidgetLayout {
959 pub fn with_root_widget(layout_widgets: Arc<LayoutUpdates>, layout: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
963 Self {
964 layout_widgets,
965 bounds: WIDGET.bounds(),
966 nest_group: LayoutNestGroup::Inner,
967 inline: None,
968 needs_ref_count: None,
969 }
970 .with_widget(layout)
971 }
972
973 pub fn parallel_split(&self) -> ParallelBuilder<WidgetLayout> {
983 if self.nest_group != LayoutNestGroup::Child && WIDGET.parent_id().is_some() {
984 tracing::error!("called `parallel_split` outside child scope");
985 }
986 ParallelBuilder(Some(WidgetLayout {
987 layout_widgets: self.layout_widgets.clone(),
988 bounds: self.bounds.clone(),
989 nest_group: LayoutNestGroup::Child,
990 inline: None,
991 needs_ref_count: None,
992 }))
993 }
994
995 pub fn parallel_fold(&mut self, mut split: ParallelBuilder<WidgetLayout>) {
997 let folded = split.take();
998 assert_eq!(self.bounds, folded.bounds);
999
1000 let count = self.needs_ref_count.unwrap_or(0) + folded.needs_ref_count.unwrap_or(0);
1001 self.needs_ref_count = Some(count);
1002 }
1003
1004 pub fn with_widget(&mut self, layout: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
1013 let metrics = LAYOUT.metrics();
1014 let bounds = WIDGET.bounds();
1015
1016 let snap = metrics.snapshot();
1017 if let Some(c) = &mut self.needs_ref_count {
1018 *c += 1;
1019 }
1020
1021 if !WIDGET.take_update(UpdateFlags::LAYOUT) && !self.layout_widgets.delivery_list().enter_widget(WIDGET.id()) {
1022 let uses = bounds.metrics_used();
1024 if bounds.metrics().map(|m| m.masked_eq(&snap, uses)).unwrap_or(false) {
1025 LAYOUT.register_metrics_use(uses); return bounds.outer_size();
1028 }
1029 }
1030
1031 let parent_needs_ref_count = self.needs_ref_count.take();
1032 let parent_inline = self.inline.take();
1033 if LAYOUT.inline_constraints().is_some() && bounds.measure_inline().is_some() {
1034 self.inline = bounds.take_inline();
1036 if let Some(inline) = self.inline.as_mut() {
1037 inline.clear();
1038 } else {
1039 self.inline = Some(Default::default());
1040 }
1041 }
1042 let parent_bounds = mem::replace(&mut self.bounds, bounds);
1043 self.nest_group = LayoutNestGroup::Inner;
1044 let prev_inner_offset = self.bounds.inner_offset();
1045 let prev_child_offset = self.bounds.child_offset();
1046 let prev_baseline = self.bounds.baseline();
1047 let prev_inner_offset_baseline = self.bounds.inner_offset_baseline();
1048 let prev_can_auto_hide = self.bounds.can_auto_hide();
1049 let prev_transform_style = self.bounds.transform_style();
1050 let prev_perspective = self.bounds.raw_perspective();
1051 let prev_perspective_origin = self.bounds.raw_perspective_origin();
1052 self.bounds.set_inner_offset(PxVector::zero());
1053 self.bounds.set_child_offset(PxVector::zero());
1054 self.bounds.set_baseline(Px(0));
1055 self.bounds.set_inner_offset_baseline(false);
1056 self.bounds.set_can_auto_hide(true);
1057 self.bounds.set_transform_style(TransformStyle::Flat);
1058 self.bounds.set_perspective(f32::INFINITY);
1059 self.bounds.set_perspective_origin(None);
1060
1061 let (uses, size) = LAYOUT.capture_metrics_use(|| layout(self));
1063
1064 LAYOUT.register_metrics_use(uses);
1065 self.bounds.set_outer_size(size);
1066 self.bounds.set_metrics(Some(snap), uses);
1067 if let Some(inline) = &mut self.inline {
1068 inline.inner_size = self.bounds.inner_size();
1069 inline.invalidate_negative_space();
1070 }
1071 self.bounds.set_inline(self.inline.take());
1072
1073 if prev_can_auto_hide != self.bounds.can_auto_hide() || prev_transform_style != self.bounds.transform_style() {
1074 WIDGET.render();
1075 } else if prev_inner_offset != self.bounds.inner_offset()
1076 || prev_child_offset != self.bounds.child_offset()
1077 || prev_inner_offset_baseline != self.bounds.inner_offset_baseline()
1078 || prev_perspective != self.bounds.raw_perspective()
1079 || prev_perspective_origin != self.bounds.raw_perspective_origin()
1080 || (self.bounds.inner_offset_baseline() && prev_baseline != self.bounds.baseline())
1081 {
1082 WIDGET.render_update();
1083 }
1084
1085 self.needs_ref_count = parent_needs_ref_count;
1086 self.inline = parent_inline;
1087 self.bounds = parent_bounds;
1088 self.nest_group = LayoutNestGroup::Child;
1089
1090 size
1091 }
1092
1093 pub fn with_inline_visual(&mut self, layout: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
1098 if self.is_inline() {
1099 let size = layout(self);
1100 WIDGET.bounds().set_inline(self.inline.clone());
1101 size
1102 } else {
1103 let bounds = WIDGET.bounds();
1104 if let Some(measure) = bounds.measure_inline() {
1105 let constraints = InlineConstraintsLayout::new(
1106 PxRect::from_size(measure.first),
1107 Px(0),
1108 {
1109 let mut r = PxRect::from_size(measure.last);
1110 r.origin.y = bounds.measure_outer_size().height - measure.last.height;
1111 r
1112 },
1113 Arc::new(vec![]),
1114 Arc::new(vec![]),
1115 );
1116
1117 self.inline = Some(Default::default());
1118
1119 let metrics = LAYOUT
1120 .metrics()
1121 .with_inline_constraints(Some(InlineConstraints::Layout(constraints)));
1122 let size = LAYOUT.with_context(metrics, || layout(self));
1123
1124 bounds.set_inline(self.inline.clone());
1125 size
1126 } else {
1127 layout(self)
1128 }
1129 }
1130 }
1131
1132 pub fn with_inner(&mut self, layout: impl FnOnce(&mut Self) -> PxSize) -> PxSize {
1140 self.nest_group = LayoutNestGroup::Child;
1141 let size = BORDER.with_inner(|| layout(self));
1142 WIDGET.bounds().set_inner_size(size);
1143 self.nest_group = LayoutNestGroup::Inner;
1144 size
1145 }
1146
1147 pub fn with_child(&mut self, layout: impl FnOnce(&mut Self) -> PxSize) -> (PxSize, bool) {
1157 let parent_needs_ref_count = self.needs_ref_count.replace(0);
1158
1159 self.nest_group = LayoutNestGroup::Child;
1160 let child_size = layout(self);
1161 self.nest_group = LayoutNestGroup::Child;
1162
1163 let need_ref_frame = self.needs_ref_count != Some(1);
1164 self.needs_ref_count = parent_needs_ref_count;
1165 (child_size, need_ref_frame)
1166 }
1167
1168 pub fn require_child_ref_frame(&mut self) {
1175 if let Some(c) = &mut self.needs_ref_count {
1176 *c += 2;
1177 }
1178 }
1179
1180 pub fn with_branch_child(&mut self, layout: impl FnOnce(&mut Self) -> PxSize) -> (PxSize, PxVector) {
1187 let parent_needs_ref_count = self.needs_ref_count;
1188 let parent_translate = self.bounds.child_offset();
1189 let parent_inner_offset_baseline = self.bounds.inner_offset_baseline();
1190 self.bounds.set_child_offset(PxVector::zero());
1191 let parent_group = self.nest_group;
1192
1193 self.nest_group = LayoutNestGroup::Child;
1194 let child_size = layout(self);
1195
1196 let translate = self.bounds.child_offset();
1197 self.bounds.set_child_offset(parent_translate);
1198 self.bounds.set_inner_offset_baseline(parent_inner_offset_baseline);
1199 self.nest_group = parent_group;
1200 self.needs_ref_count = parent_needs_ref_count;
1201
1202 (child_size, translate)
1203 }
1204
1205 pub fn translate(&mut self, offset: PxVector) {
1210 match self.nest_group {
1211 LayoutNestGroup::Inner => {
1212 let mut o = self.bounds.inner_offset();
1213 o += offset;
1214 self.bounds.set_inner_offset(o);
1215 }
1216 LayoutNestGroup::Child => {
1217 let mut o = self.bounds.child_offset();
1218 o += offset;
1219 self.bounds.set_child_offset(o);
1220 }
1221 }
1222 }
1223
1224 pub fn set_baseline(&mut self, baseline: Px) {
1226 self.bounds.set_baseline(baseline);
1227 }
1228
1229 pub fn translate_baseline(&mut self, enabled: bool) {
1231 self.bounds.set_inner_offset_baseline(enabled);
1232 }
1233
1234 pub fn set_transform_style(&mut self, style: TransformStyle) {
1236 self.bounds.set_transform_style(style);
1237 }
1238
1239 pub fn set_perspective(&mut self, d: f32) {
1243 self.bounds.set_perspective(d)
1244 }
1245
1246 pub fn set_perspective_origin(&mut self, origin: PxPoint) {
1248 self.bounds.set_perspective_origin(Some(origin))
1249 }
1250
1251 pub fn allow_auto_hide(&mut self, enabled: bool) {
1258 self.bounds.set_can_auto_hide(enabled);
1259 }
1260
1261 pub fn collapse(&mut self) {
1271 WIDGET.take_update(UpdateFlags::LAYOUT);
1272 let tree = WINDOW.info();
1273 let id = WIDGET.id();
1274 if let Some(w) = tree.get(id) {
1275 for w in w.self_and_descendants() {
1276 let info = w.info();
1277 info.bounds_info.set_outer_size(PxSize::zero());
1278 info.bounds_info.set_inner_size(PxSize::zero());
1279 info.bounds_info.set_baseline(Px(0));
1280 info.bounds_info.set_inner_offset_baseline(false);
1281 info.bounds_info.set_can_auto_hide(true);
1282 info.bounds_info.set_inner_offset(PxVector::zero());
1283 info.bounds_info.set_child_offset(PxVector::zero());
1284 info.bounds_info.set_measure_metrics(None, LayoutMask::empty());
1285 info.bounds_info.set_metrics(None, LayoutMask::empty());
1286 info.bounds_info.set_is_collapsed(true);
1287 info.bounds_info.set_rendered(None, &tree);
1288 }
1289 } else {
1290 tracing::error!("collapse did not find `{}` in the info tree", id)
1291 }
1292 }
1293
1294 pub fn collapse_descendants(&mut self) {
1303 let tree = WINDOW.info();
1304 let id = WIDGET.id();
1305 if let Some(w) = tree.get(id) {
1306 for w in w.descendants() {
1307 let info = w.info();
1308 info.bounds_info.set_outer_size(PxSize::zero());
1309 info.bounds_info.set_inner_size(PxSize::zero());
1310 info.bounds_info.set_baseline(Px(0));
1311 info.bounds_info.set_inner_offset_baseline(false);
1312 info.bounds_info.set_can_auto_hide(true);
1313 info.bounds_info.set_inner_offset(PxVector::zero());
1314 info.bounds_info.set_child_offset(PxVector::zero());
1315 info.bounds_info.set_measure_metrics(None, LayoutMask::empty());
1316 info.bounds_info.set_metrics(None, LayoutMask::empty());
1317 info.bounds_info.set_is_collapsed(true);
1318 }
1319 } else {
1320 tracing::error!("collapse_descendants did not find `{}` in the info tree", id)
1321 }
1322 }
1323
1324 pub fn collapse_child(&mut self, index: usize) {
1333 let tree = WINDOW.info();
1334 let id = WIDGET.id();
1335 if let Some(w) = tree.get(id) {
1336 if let Some(w) = w.children().nth(index) {
1337 for w in w.self_and_descendants() {
1338 let info = w.info();
1339 info.bounds_info.set_outer_size(PxSize::zero());
1340 info.bounds_info.set_inner_size(PxSize::zero());
1341 info.bounds_info.set_baseline(Px(0));
1342 info.bounds_info.set_inner_offset_baseline(false);
1343 info.bounds_info.set_can_auto_hide(true);
1344 info.bounds_info.set_inner_offset(PxVector::zero());
1345 info.bounds_info.set_child_offset(PxVector::zero());
1346 info.bounds_info.set_measure_metrics(None, LayoutMask::empty());
1347 info.bounds_info.set_metrics(None, LayoutMask::empty());
1348 info.bounds_info.set_is_collapsed(true);
1349 }
1350 } else {
1351 tracing::error!(
1352 "collapse_child out-of-bounds for `{}` in the children of `{}` in the info tree",
1353 index,
1354 id
1355 )
1356 }
1357 } else {
1358 tracing::error!("collapse_child did not find `{}` in the info tree", id)
1359 }
1360 }
1361
1362 pub fn is_inline(&self) -> bool {
1367 self.inline.is_some()
1368 }
1369
1370 pub fn inline(&mut self) -> Option<&mut WidgetInlineInfo> {
1385 self.inline.as_mut()
1386 }
1387
1388 pub fn to_measure(&self, inline: Option<WidgetInlineMeasure>) -> WidgetMeasure {
1392 WidgetMeasure {
1393 layout_widgets: self.layout_widgets.clone(),
1394 inline,
1395 inline_locked: false,
1396 }
1397 }
1398
1399 pub fn layout_block(&mut self, child: &mut UiNode) -> PxSize {
1404 LAYOUT.with_no_inline(|| child.layout(self))
1405 }
1406
1407 pub fn layout_inline(
1416 &mut self,
1417 first: PxRect,
1418 mid_clear: Px,
1419 last: PxRect,
1420 first_segs: Arc<Vec<InlineSegmentPos>>,
1421 last_segs: Arc<Vec<InlineSegmentPos>>,
1422 child: &mut UiNode,
1423 ) -> PxSize {
1424 let constraints = InlineConstraints::Layout(InlineConstraintsLayout::new(first, mid_clear, last, first_segs, last_segs));
1425 let metrics = LAYOUT.metrics().with_inline_constraints(Some(constraints));
1426 LAYOUT.with_context(metrics, || child.layout(self))
1427 }
1428
1429 pub fn with_layout_updates(&mut self, layout_updates: Arc<LayoutUpdates>, layout: impl FnOnce(&mut WidgetLayout) -> PxSize) -> PxSize {
1433 let parent_layout_widgets = mem::replace(&mut self.layout_widgets, layout_updates);
1434 let r = layout(self);
1435 self.layout_widgets = parent_layout_widgets;
1436 r
1437 }
1438}
1439
1440#[derive(Debug, Clone, Copy, PartialEq)]
1441enum LayoutNestGroup {
1442 Inner,
1444 Child,
1446}
1447
1448#[must_use = "use in parallel task, then move it to `B::parallel_fold`"]
1455pub struct ParallelBuilder<B>(pub(crate) Option<B>);
1456impl<B> ParallelBuilder<B> {
1457 pub(crate) fn take(&mut self) -> B {
1458 self.0.take().expect("parallel builder finished")
1459 }
1460}
1461impl<B> ops::Deref for ParallelBuilder<B> {
1462 type Target = B;
1463
1464 fn deref(&self) -> &Self::Target {
1465 self.0.as_ref().expect("parallel builder finished")
1466 }
1467}
1468impl<B> ops::DerefMut for ParallelBuilder<B> {
1469 fn deref_mut(&mut self) -> &mut Self::Target {
1470 self.0.as_mut().expect("parallel builder finished")
1471 }
1472}
1473impl<B> Drop for ParallelBuilder<B> {
1474 fn drop(&mut self) {
1475 if self.0.is_some() && !std::thread::panicking() {
1476 tracing::error!("builder dropped without calling `{}::parallel_fold`", std::any::type_name::<B>())
1477 }
1478 }
1479}