Skip to main content

zng_app/widget/info/
builder.rs

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
19/// Tag for the [`WidgetInfo::meta`] state-map.
20pub enum WidgetInfoMeta {}
21
22/// Widget info tree builder.
23///
24/// See [`WidgetInfoTree`] for more details.
25pub 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    /// Starts building a info tree with the root information.
47    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, // root is always new.
84        };
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    /// Current widget id.
98    pub fn widget_id(&self) -> WidgetId {
99        self.widget_id
100    }
101
102    /// Widget info tree build metadata.
103    ///
104    /// This metadata can be modified only by pushed widgets, **not** by the reused widgets.
105    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    /// Set the info tree build metadata `id` to `value`.
109    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    /// Sets the info tree build metadata `id` without value.
115    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    /// Current widget info metadata.
121    pub fn with_meta<R>(&mut self, visitor: impl FnOnce(StateMapMut<WidgetInfoMeta>) -> R) -> R {
122        visitor(self.meta.lock().borrow_mut())
123    }
124    /// Set the widget info metadata `id` to `value`.
125    ///
126    /// Returns the previous set value.
127    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    /// Sets the widget info metadata `id` without value.
133    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    /// Calls `f` to build the context widget info.
139    ///
140    /// Note that `f` is only called if the widget info cannot be reused.
141    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            // reuse
145            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    /// Add the `interactivity` bits to the current widget's interactivity, it will affect the widget and all descendants.
196    ///
197    /// Also see [`push_interactivity_filter`] to affect the interactivity of widgets outside the current one.
198    ///
199    /// [`push_interactivity_filter`]: Self::push_interactivity_filter
200    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    /// Register a closure that returns the [`Interactivity`] allowed for each widget.
207    ///
208    /// Widgets [`interactivity`] is computed from all interactivity filters and parents. Interactivity filters are global to the
209    /// widget tree, and are re-registered for the tree if the current widget is reused.
210    ///
211    /// Note that the filter can make the assumption that parent widgets affect all descendants and if the filter is intended to
212    /// affect only the current widget and descendants you can use [`push_interactivity`] instead.
213    ///
214    /// [`interactivity`]: WidgetInfo::interactivity
215    /// [`push_interactivity`]: Self::push_interactivity
216    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    /// Calls the `info` closure and returns the range of children inserted by it.
223    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    /// Create a new info builder that can be built in parallel and merged back onto this one using [`parallel_fold`].
230    ///
231    /// [`parallel_fold`]: Self::parallel_fold
232    /// [`push_widget`]: Self::push_widget
233    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    /// Collect info from `split` into `self`.
263    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    /// Build the info tree.
293    ///
294    /// Also notifies [`WIDGET_TREE_CHANGED_EVENT`] if `notify` is true.
295    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    /// A window widget tree was rebuild.
377    ///
378    /// Note that some widgets values may update internally after render, those changes do not generate an event. To monitor
379    /// those changes use a variable and schedule a modify during each render pass that requery the value.
380    pub static WIDGET_TREE_CHANGED_EVENT: WidgetTreeChangedArgs;
381}
382
383crate::event::event_args! {
384    /// [`WIDGET_TREE_CHANGED_EVENT`] args.
385    pub struct WidgetTreeChangedArgs {
386        /// Previous widget tree.
387        ///
388        /// The strong reference if only held for the duration event update duration, after it is dropped. It will also
389        /// not upgrade if this event is the first for the window.
390        ///
391        /// This is equal to `tree` if `is_update`.
392        pub prev_tree: WeakWidgetInfoTree,
393
394        /// New widget tree.
395        pub tree: WidgetInfoTree,
396
397        /// If it is the same tree, just render info updated.
398        ///
399        /// Note that these changes are applied with interior mutability, so the `tree` shared reference
400        /// will can be modified on the next render. To compare values save a copy.
401        ///
402        /// Some values updated without tree rebuild are, widget transforms, widget visibility.
403        pub is_update: bool,
404
405        ..
406
407        /// Broadcast to all widgets.
408        fn is_in_target(&self, _id: WidgetId) -> bool {
409            true
410        }
411    }
412}
413
414/// Info about the input inline connecting rows of the widget.
415#[derive(Clone, Debug, Default, PartialEq)]
416#[non_exhaustive]
417pub struct WidgetInlineMeasure {
418    /// Preferred first size.
419    ///
420    /// In left-to-right direction the origin is `top_left`, in right-to-left direction the origin is `top_right - first.width`.
421    pub first: PxSize,
422
423    /// Indicates that `first` starts in the next row, not in the *current* row defined by the inline constraints.
424    pub first_wrapped: bool,
425
426    /// Inline segments in the first row.
427    ///
428    /// The sum of segment widths must be less or equal to the `first.width`.
429    pub first_segs: Arc<Vec<InlineSegment>>,
430
431    /// Preferred last size.
432    ///
433    /// In left-to-right direction the origin is `bottom_left - last.height`, in right-to-left direction
434    /// the origin is `bottom_right - last`.
435    ///
436    /// Must be equal to `first` if did not wrap.
437    ///
438    /// Must not be empty if first is not empty, that is, must not wrap if the last item can fit in the previous row.
439    pub last: PxSize,
440
441    /// Indicates that `last` starts in a next row, not in the same row as the first.
442    pub last_wrapped: bool,
443
444    /// Inline segments in the last row.
445    ///
446    /// The sum of segment widths must be less or equal to the `last.width`.
447    pub last_segs: Arc<Vec<InlineSegment>>,
448}
449impl WidgetInlineMeasure {
450    /// Visit a mutable reference to the new [`first_segs`] value, `f` is called with
451    /// an empty vec that can be reused or new.
452    ///
453    /// [`first_segs`]: Self::first_segs
454    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    /// Visit a mutable reference to the new [`last_segs`] value, `f` is called with
459    /// an empty vec that can be reused or new.
460    ///
461    /// [`last_segs`]: Self::last_segs
462    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    /// If all value are not different from initial.
481    ///
482    /// This indicates the widget has not handled the inline config yet.
483    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/// Info about a segment in the first or last row of an inlined widget.
494///
495/// See [`WidgetInlineInfo::first_segs`] for more details.
496#[derive(Clone, Copy, Debug, PartialEq, Eq)]
497#[non_exhaustive]
498pub struct InlineSegmentInfo {
499    /// Segment offset from the row rectangle origin.
500    pub x: Px,
501    /// Segment width.
502    ///
503    /// Note that the segment height is the row rectangle height.
504    pub width: Px,
505}
506
507impl InlineSegmentInfo {
508    /// New from `x` and `width`.
509    pub fn new(x: Px, width: Px) -> Self {
510        Self { x, width }
511    }
512}
513
514/// Info about the inlined rows of the widget.
515#[derive(Debug, Default)]
516#[non_exhaustive]
517pub struct WidgetInlineInfo {
518    /// Last layout rows of the widget.
519    ///
520    /// The rectangles are in the widget's inner space, from top to bottom.
521    pub rows: Vec<PxRect>,
522
523    /// Segments of the first row.
524    ///
525    /// If this is empty the entire row width is a continuous segment, otherwise the row is segmented and
526    /// the widget can be interleaved with sibling widgets due to Unicode bidirectional text sorting algorithm.
527    ///
528    /// Note that the segment count may be less then [`WidgetInlineMeasure::first_segs`] as contiguous segments
529    /// may be merged.
530    ///
531    /// The segments are from left to right.
532    pub first_segs: Vec<InlineSegmentInfo>,
533
534    /// Segments of the last row.
535    pub last_segs: Vec<InlineSegmentInfo>,
536
537    /// Widget inner size when the rows where last updated.
538    pub inner_size: PxSize,
539
540    negative_space: Mutex<(Arc<Vec<PxRect>>, bool)>,
541}
542impl WidgetInlineInfo {
543    /// Replace the [`first_segs`] with `segs`.
544    ///
545    /// The segments are sorted when needed, but prefer inputs that are mostly sorted.
546    ///
547    /// The segments are merged when there is no gap or there is a small one pixel overlap to the previous segment.
548    ///
549    /// [`first_segs`]: Self::first_segs
550    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    /// Replace the [`last_segs`] with `segs`.
556    ///
557    /// The segments are sorted when needed, but prefer inputs that are mostly sorted.
558    ///
559    /// The segments are merged when there is no gap or there is a small one pixel overlap to the previous segment.
560    ///
561    /// [`last_segs`]: Self::last_segs
562    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                    // merge overlap
586                    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    /// Gets the union of all row rectangles.
602    pub fn union(&self) -> PxRect {
603        self.rows.iter().fold(PxRect::zero(), |union, row| union.union(row))
604    }
605
606    /// Gets or computes the negative space of the [`rows`] in the [`inner_size`] space, that is, all the areas that are
607    /// not covered by any row and not covered by the first and last row segments.
608    ///
609    /// This is computed on demand and cached.
610    ///
611    /// [`rows`]: Self::rows
612    /// [`inner_size`]: Self::inner_size
613    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    /// Invalidates the [`negative_space`] cache.
630    ///
631    /// [`negative_space`]: Self::negative_space
632    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    ///Return info to default state, but retain memory for reuse.
706    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    /// If all value are not different from initial.
715    ///
716    /// This indicates the widget has not handled the inline config yet.
717    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
749/// Represents the in-progress measure pass for a widget tree.
750///
751/// Use [`WidgetLayout::to_measure`] to instantiate.
752pub 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    /// New with no widget layouts invalidated.
767    ///
768    /// Prefer [`WidgetLayout::to_measure`] instead of this.
769    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    /// If the parent widget is doing inline flow layout.
776    pub fn is_inline(&self) -> bool {
777        self.inline.is_some()
778    }
779
780    /// Mutable reference to the current widget's inline info.
781    ///
782    /// The widget must configure this to be inlined in parent layout. This is only `Some(_)` if inline is enabled.
783    ///
784    /// See [`WidgetInlineMeasure`] for more details.
785    pub fn inline(&mut self) -> Option<&mut WidgetInlineMeasure> {
786        self.inline.as_mut()
787    }
788
789    /// Sets [`is_inline`] to `false`.
790    ///
791    /// Must be called before child delegation, otherwise children that inline may render expecting to fit in
792    /// the inline flow.
793    ///
794    /// Note that this disables inline for the calling widget's next layout too, every property that affects layout and does
795    /// not support inline layout must propagate measure using this method to correctly configure the widget.
796    ///
797    /// Prefer [`measure_block`] as if also clears the layout constraints.
798    ///
799    /// [`is_inline`]: Self::is_inline
800    /// [`measure_block`]: Self::measure_block
801    pub fn disable_inline(&mut self) {
802        if !self.inline_locked {
803            self.inline = None;
804        }
805    }
806
807    /// Disable inline and measure child with no inline constraints.
808    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    /// Measure the child node with inline enabled for the `child` node context.
814    ///
815    /// The `first_max` and `mid_clear_min` parameters match the [`InlineConstraintsMeasure`] members, and will be set in
816    /// the `child` context.
817    ///
818    /// Note that this does not enabled inline in the calling widget if inlining was disabled by the parent nodes, it creates
819    /// a new inlining context.
820    ///
821    /// Returns the inline requirements of the child and its desired bounds size, returns `None` requirements if the child
822    /// disables inline or is not a full widget.
823    ///
824    /// [`InlineConstraintsMeasure`]: zng_layout::context::InlineConstraintsMeasure
825    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    /// Measure a widget.
836    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); // propagate to parent if it is measuring
856                    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                // widget did not handle inline
875                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    /// Calls `measure` with inline force enabled on the widget.
898    ///
899    /// The widget will be inlining even if the parent widget is not inlining, if properties request [`disable_inline`]
900    /// these requests are ignored.
901    ///
902    /// [`disable_inline`]: crate::widget::info::WidgetMeasure::disable_inline
903    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            // widget did not handle inline
922            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    /// Start a parallel measure.
932    ///
933    /// Returns an instance that can be used to acquire multiple mutable [`WidgetMeasure`] during measure.
934    /// The [`parallel_fold`] method must be called after the parallel processing is done.
935    ///
936    /// [`parallel_fold`]: Self::parallel_fold
937    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    /// Collect the parallel changes back.
946    pub fn parallel_fold(&mut self, mut split: ParallelBuilder<WidgetMeasure>) {
947        let _ = split.take();
948    }
949}
950
951/// Represents the in-progress layout pass for a widget tree.
952pub 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    /// Defines the root widget outer-bounds scope.
961    ///
962    /// The default window implementation calls this inside the root widget context.
963    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    /// Start a parallel layout.
975    ///
976    /// Returns an instance that can be used to acquire multiple mutable [`WidgetLayout`] during layout.
977    /// The [`parallel_fold`] method must be called after the parallel processing is done.
978    ///
979    /// Must be called outside of the [child] scope.
980    ///
981    /// [child]: Self::with_child
982    /// [`parallel_fold`]: Self::parallel_fold
983    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    /// Collect the parallel changes back.
997    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    /// Defines a widget scope, translations inside `layout` target the widget's inner offset.
1006    ///
1007    /// If the widget layout is not invalidated and none of the used metrics have changed skips calling
1008    /// `layout` and returns the current outer-size, the outer transform is still updated.
1009    ///
1010    /// The default widget constructor calls this, see [`base::node::widget`].
1011    ///
1012    /// [`base::node::widget`]: crate::widget::base::node::widget
1013    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            // layout not invalidated by request
1024            let uses = bounds.metrics_used();
1025            if bounds.metrics().map(|m| m.masked_eq(&snap, uses)).unwrap_or(false) {
1026                // layout not invalidated by used metrics
1027                LAYOUT.register_metrics_use(uses); // propagate to parent
1028                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            // inline enabled by parent and widget
1036            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        // layout
1063        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    /// Calls `layout` with inline force enabled on the widget.
1095    ///
1096    /// The widget will use the inline visual even if the parent did not inline it, but it will not
1097    /// inline if it has properties that disable inlining.
1098    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    /// Defines the widget's inner scope, translations inside `layout` target the widget's child offset.
1134    ///
1135    /// This method also updates the border info.
1136    ///
1137    /// The default widget borders constructor calls this, see [`base::node::widget_inner`].
1138    ///
1139    /// [`base::node::widget_inner`]: crate::widget::base::node::widget_inner
1140    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    /// Defines the widget's child scope, translations inside `layout` target the widget's child offset.
1149    ///
1150    /// Returns the child size and if a reference frame is required to offset the child.
1151    ///
1152    /// The default widget child layout constructor implements this, see [`base::node::widget_child`].
1153    ///
1154    /// [`base::node::widget_child`]: crate::widget::base::node::widget_child
1155    /// [`child_offset`]: WidgetBoundsInfo::child_offset
1156    /// [`with_branch_child`]: Self::with_branch_child
1157    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    /// Ensure that the parent [`with_child`] will receive a reference frame request.
1170    ///
1171    /// Nodes that branch out children inside the widget's child scope must call this to ensure that the offsets
1172    /// are not given to the only widget child among other nodes.
1173    ///
1174    /// [`with_child`]: Self::with_child
1175    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    /// Defines a custom scope that does not affect the widget's offsets, only any widget inside `layout`.
1182    ///
1183    /// Nodes that branch out children outside widget's child scope must use this method.
1184    ///
1185    /// Returns the output of `layout` and a translate vector if any translations inside `layout` where not handled
1186    /// by child widgets.
1187    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    /// Adds the `offset` to the closest *inner* bounds offset.
1207    ///
1208    /// This affects the inner offset if called from a node inside the widget and before the `BORDER` group, or it affects
1209    /// the child offset if called inside the widget and inside the `BORDER` group.
1210    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    /// Set the baseline offset of the widget. The value is up from the bottom of the inner bounds.
1226    pub fn set_baseline(&mut self, baseline: Px) {
1227        self.bounds.set_baseline(baseline);
1228    }
1229
1230    /// Set if the baseline is added to the inner offset *y* axis.
1231    pub fn translate_baseline(&mut self, enabled: bool) {
1232        self.bounds.set_inner_offset_baseline(enabled);
1233    }
1234
1235    /// Set if the widget preserved 3D perspective form the parent.
1236    pub fn set_transform_style(&mut self, style: TransformStyle) {
1237        self.bounds.set_transform_style(style);
1238    }
1239
1240    /// Set the 3D perspective that defines the children 3D space.
1241    ///
1242    /// This is the distance from the Z-plane to the viewer.
1243    pub fn set_perspective(&mut self, d: f32) {
1244        self.bounds.set_perspective(d)
1245    }
1246
1247    /// Sets the vanishing point of the children 3D space as a point in the inner bounds of this widget.
1248    pub fn set_perspective_origin(&mut self, origin: PxPoint) {
1249        self.bounds.set_perspective_origin(Some(origin))
1250    }
1251
1252    /// Sets if the widget only renders if [`outer_bounds`] intersects with the [`FrameBuilder::auto_hide_rect`].
1253    ///
1254    /// This is `true` by default.
1255    ///
1256    /// [`outer_bounds`]: WidgetBoundsInfo::outer_bounds
1257    /// [`FrameBuilder::auto_hide_rect`]: crate::render::FrameBuilder::auto_hide_rect
1258    pub fn allow_auto_hide(&mut self, enabled: bool) {
1259        self.bounds.set_can_auto_hide(enabled);
1260    }
1261
1262    /// Collapse the layout of `self` and descendants, the size and offsets are set to zero.
1263    ///
1264    /// Nodes that set the visibility to the equivalent of [`Collapsed`] must skip layout and return `PxSize::zero` as
1265    /// the size, ignoring the min-size constraints, and call this method to update all the descendant
1266    /// bounds information to be a zero-sized point.
1267    ///
1268    /// Note that the widget will automatically not be rendered when collapsed.
1269    ///
1270    /// [`Collapsed`]: Visibility::Collapsed
1271    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    /// Collapse layout of all descendants, the size and offsets are set to zero.
1296    ///
1297    /// Widgets that control the visibility of their children can use this method and then, in the same layout pass, layout
1298    /// the children that should be visible.
1299    ///
1300    /// Note that the widgets will automatically not be rendered when collapsed.
1301    ///
1302    /// [`Collapsed`]: Visibility::Collapsed
1303    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    /// Collapse layout of the child and all its descendants, the size and offsets are set to zero.
1326    ///
1327    /// Widgets that control the visibility of their children can use this method and then, in the same layout pass, layout
1328    /// the children that should be visible.
1329    ///
1330    /// Note that the widgets will automatically not be rendered when collapsed.
1331    ///
1332    /// [`Collapsed`]: Visibility::Collapsed
1333    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    /// If the parent widget is doing inline layout and this widget signaled that it can support this
1364    /// during measure.
1365    ///
1366    /// See [`WidgetMeasure::inline`] for more details.
1367    pub fn is_inline(&self) -> bool {
1368        self.inline.is_some()
1369    }
1370
1371    /// Mutable reference to the current widget's inline info.
1372    ///
1373    /// This is `Some(_)` if the parent widget is doing inline layout and this widget signaled that it can be inlined
1374    /// in the previous measure pass. You can use [`WidgetMeasure::disable_inline`] in the measure pass to disable
1375    /// inline in both passes, measure and layout.
1376    ///
1377    /// The rows and negative space are already reset when widget layout started, and the inner size will be updated when
1378    /// the widget layout ends, the inline layout node only needs to push rows.
1379    ///
1380    /// When this is `Some(_)` the [`LayoutMetrics::inline_constraints`] is also `Some(_)`.
1381    ///
1382    /// See [`WidgetInlineInfo`] for more details.
1383    ///
1384    /// [`LayoutMetrics::inline_constraints`]: zng_layout::context::LayoutMetrics::inline_constraints
1385    pub fn inline(&mut self) -> Option<&mut WidgetInlineInfo> {
1386        self.inline.as_mut()
1387    }
1388
1389    /// Create an [`WidgetMeasure`] for an [`UiNode::measure`] call.
1390    ///
1391    /// [`UiNode::measure`]: crate::widget::node::UiNode::measure
1392    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    /// Layout the child node in a context without inline constraints.
1401    ///
1402    /// This must be called inside inlining widgets to layout block child nodes, otherwise the inline constraints from
1403    /// the calling widget propagate to the child.
1404    pub fn layout_block(&mut self, child: &mut UiNode) -> PxSize {
1405        LAYOUT.with_no_inline(|| child.layout(self))
1406    }
1407
1408    /// Layout the child node with inline enabled in the `child` node context.
1409    ///
1410    /// The `mid_clear`, `last`, `first_segs` and `last_segs` parameters match the [`InlineConstraintsLayout`] members, and will be set in
1411    /// the `child` context.
1412    ///
1413    /// Returns the child final size.
1414    ///
1415    /// [`InlineConstraintsLayout`]: zng_layout::context::InlineConstraintsLayout
1416    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    /// Call `layout` with a different set of `layout_updates`.
1431    ///
1432    /// This is usually managed by the window implementer, nested windows can use this to override the updates.
1433    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    /// Inside widget, outside `BORDER`.
1444    Inner,
1445    /// Inside `BORDER`.
1446    Child,
1447}
1448
1449/// Represents a builder split from the main builder that can be used in parallel and then folded
1450/// back onto the main builder.
1451///
1452/// # Error
1453///
1454/// Logs an error on drop if it was not moved to the `B::parallel_fold` method.
1455#[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}