zng_app/widget/info/
builder.rs

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
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); // measure does not propagate uses.
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        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                // widget did not handle inline
874                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    /// Calls `measure` with inline force enabled on the widget.
897    ///
898    /// The widget will be inlining even if the parent widget is not inlining, if properties request [`disable_inline`]
899    /// these requests are ignored.
900    ///
901    /// [`disable_inline`]: crate::widget::info::WidgetMeasure::disable_inline
902    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            // widget did not handle inline
921            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    /// Start a parallel measure.
931    ///
932    /// Returns an instance that can be used to acquire multiple mutable [`WidgetMeasure`] during measure.
933    /// The [`parallel_fold`] method must be called after the parallel processing is done.
934    ///
935    /// [`parallel_fold`]: Self::parallel_fold
936    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    /// Collect the parallel changes back.
945    pub fn parallel_fold(&mut self, mut split: ParallelBuilder<WidgetMeasure>) {
946        let _ = split.take();
947    }
948}
949
950/// Represents the in-progress layout pass for a widget tree.
951pub 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    /// Defines the root widget outer-bounds scope.
960    ///
961    /// The default window implementation calls this inside the root widget context.
962    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    /// Start a parallel layout.
974    ///
975    /// Returns an instance that can be used to acquire multiple mutable [`WidgetLayout`] during layout.
976    /// The [`parallel_fold`] method must be called after the parallel processing is done.
977    ///
978    /// Must be called outside of the [child] scope.
979    ///
980    /// [child]: Self::with_child
981    /// [`parallel_fold`]: Self::parallel_fold
982    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    /// Collect the parallel changes back.
996    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    /// Defines a widget scope, translations inside `layout` target the widget's inner offset.
1005    ///
1006    /// If the widget layout is not invalidated and none of the used metrics have changed skips calling
1007    /// `layout` and returns the current outer-size, the outer transform is still updated.
1008    ///
1009    /// The default widget constructor calls this, see [`base::node::widget`].
1010    ///
1011    /// [`base::node::widget`]: crate::widget::base::node::widget
1012    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            // layout not invalidated by request
1023            let uses = bounds.metrics_used();
1024            if bounds.metrics().map(|m| m.masked_eq(&snap, uses)).unwrap_or(false) {
1025                // layout not invalidated by used metrics
1026                LAYOUT.register_metrics_use(uses); // propagate to parent
1027                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            // inline enabled by parent and widget
1035            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        // layout
1062        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    /// Calls `layout` with inline force enabled on the widget.
1094    ///
1095    /// The widget will use the inline visual even if the parent did not inline it, but it will not
1096    /// inline if it has properties that disable inlining.
1097    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    /// Defines the widget's inner scope, translations inside `layout` target the widget's child offset.
1133    ///
1134    /// This method also updates the border info.
1135    ///
1136    /// The default widget borders constructor calls this, see [`base::node::widget_inner`].
1137    ///
1138    /// [`base::node::widget_inner`]: crate::widget::base::node::widget_inner
1139    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    /// Defines the widget's child scope, translations inside `layout` target the widget's child offset.
1148    ///
1149    /// Returns the child size and if a reference frame is required to offset the child.
1150    ///
1151    /// The default widget child layout constructor implements this, see [`base::node::widget_child`].
1152    ///
1153    /// [`base::node::widget_child`]: crate::widget::base::node::widget_child
1154    /// [`child_offset`]: WidgetBoundsInfo::child_offset
1155    /// [`with_branch_child`]: Self::with_branch_child
1156    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    /// Ensure that the parent [`with_child`] will receive a reference frame request.
1169    ///
1170    /// Nodes that branch out children inside the widget's child scope must call this to ensure that the offsets
1171    /// are not given to the only widget child among other nodes.
1172    ///
1173    /// [`with_child`]: Self::with_child
1174    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    /// Defines a custom scope that does not affect the widget's offsets, only any widget inside `layout`.
1181    ///
1182    /// Nodes that branch out children outside widget's child scope must use this method.
1183    ///
1184    /// Returns the output of `layout` and a translate vector if any translations inside `layout` where not handled
1185    /// by child widgets.
1186    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    /// Adds the `offset` to the closest *inner* bounds offset.
1206    ///
1207    /// This affects the inner offset if called from a node inside the widget and before the `BORDER` group, or it affects
1208    /// the child offset if called inside the widget and inside the `BORDER` group.
1209    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    /// Set the baseline offset of the widget. The value is up from the bottom of the inner bounds.
1225    pub fn set_baseline(&mut self, baseline: Px) {
1226        self.bounds.set_baseline(baseline);
1227    }
1228
1229    /// Set if the baseline is added to the inner offset *y* axis.
1230    pub fn translate_baseline(&mut self, enabled: bool) {
1231        self.bounds.set_inner_offset_baseline(enabled);
1232    }
1233
1234    /// Set if the widget preserved 3D perspective form the parent.
1235    pub fn set_transform_style(&mut self, style: TransformStyle) {
1236        self.bounds.set_transform_style(style);
1237    }
1238
1239    /// Set the 3D perspective that defines the children 3D space.
1240    ///
1241    /// This is the distance from the Z-plane to the viewer.
1242    pub fn set_perspective(&mut self, d: f32) {
1243        self.bounds.set_perspective(d)
1244    }
1245
1246    /// Sets the vanishing point of the children 3D space as a point in the inner bounds of this widget.
1247    pub fn set_perspective_origin(&mut self, origin: PxPoint) {
1248        self.bounds.set_perspective_origin(Some(origin))
1249    }
1250
1251    /// Sets if the widget only renders if [`outer_bounds`] intersects with the [`FrameBuilder::auto_hide_rect`].
1252    ///
1253    /// This is `true` by default.
1254    ///
1255    /// [`outer_bounds`]: WidgetBoundsInfo::outer_bounds
1256    /// [`FrameBuilder::auto_hide_rect`]: crate::render::FrameBuilder::auto_hide_rect
1257    pub fn allow_auto_hide(&mut self, enabled: bool) {
1258        self.bounds.set_can_auto_hide(enabled);
1259    }
1260
1261    /// Collapse the layout of `self` and descendants, the size and offsets are set to zero.
1262    ///
1263    /// Nodes that set the visibility to the equivalent of [`Collapsed`] must skip layout and return `PxSize::zero` as
1264    /// the size, ignoring the min-size constraints, and call this method to update all the descendant
1265    /// bounds information to be a zero-sized point.
1266    ///
1267    /// Note that the widget will automatically not be rendered when collapsed.
1268    ///
1269    /// [`Collapsed`]: Visibility::Collapsed
1270    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    /// Collapse layout of all descendants, the size and offsets are set to zero.
1295    ///
1296    /// Widgets that control the visibility of their children can use this method and then, in the same layout pass, layout
1297    /// the children that should be visible.
1298    ///
1299    /// Note that the widgets will automatically not be rendered when collapsed.
1300    ///
1301    /// [`Collapsed`]: Visibility::Collapsed
1302    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    /// Collapse layout of the child and all its descendants, the size and offsets are set to zero.
1325    ///
1326    /// Widgets that control the visibility of their children can use this method and then, in the same layout pass, layout
1327    /// the children that should be visible.
1328    ///
1329    /// Note that the widgets will automatically not be rendered when collapsed.
1330    ///
1331    /// [`Collapsed`]: Visibility::Collapsed
1332    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    /// If the parent widget is doing inline layout and this widget signaled that it can support this
1363    /// during measure.
1364    ///
1365    /// See [`WidgetMeasure::inline`] for more details.
1366    pub fn is_inline(&self) -> bool {
1367        self.inline.is_some()
1368    }
1369
1370    /// Mutable reference to the current widget's inline info.
1371    ///
1372    /// This is `Some(_)` if the parent widget is doing inline layout and this widget signaled that it can be inlined
1373    /// in the previous measure pass. You can use [`WidgetMeasure::disable_inline`] in the measure pass to disable
1374    /// inline in both passes, measure and layout.
1375    ///
1376    /// The rows and negative space are already reset when widget layout started, and the inner size will be updated when
1377    /// the widget layout ends, the inline layout node only needs to push rows.
1378    ///
1379    /// When this is `Some(_)` the [`LayoutMetrics::inline_constraints`] is also `Some(_)`.
1380    ///
1381    /// See [`WidgetInlineInfo`] for more details.
1382    ///
1383    /// [`LayoutMetrics::inline_constraints`]: zng_layout::context::LayoutMetrics::inline_constraints
1384    pub fn inline(&mut self) -> Option<&mut WidgetInlineInfo> {
1385        self.inline.as_mut()
1386    }
1387
1388    /// Create an [`WidgetMeasure`] for an [`UiNode::measure`] call.
1389    ///
1390    /// [`UiNode::measure`]: crate::widget::node::UiNode::measure
1391    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    /// Layout the child node in a context without inline constraints.
1400    ///
1401    /// This must be called inside inlining widgets to layout block child nodes, otherwise the inline constraints from
1402    /// the calling widget propagate to the child.
1403    pub fn layout_block(&mut self, child: &mut UiNode) -> PxSize {
1404        LAYOUT.with_no_inline(|| child.layout(self))
1405    }
1406
1407    /// Layout the child node with inline enabled in the `child` node context.
1408    ///
1409    /// The `mid_clear`, `last`, `first_segs` and `last_segs` parameters match the [`InlineConstraintsLayout`] members, and will be set in
1410    /// the `child` context.
1411    ///
1412    /// Returns the child final size.
1413    ///
1414    /// [`InlineConstraintsLayout`]: zng_layout::context::InlineConstraintsLayout
1415    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    /// Call `layout` with a different set of `layout_updates`.
1430    ///
1431    /// This is usually managed by the window implementer, nested windows can use this to override the updates.
1432    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    /// Inside widget, outside `BORDER`.
1443    Inner,
1444    /// Inside `BORDER`.
1445    Child,
1446}
1447
1448/// Represents a builder split from the main builder that can be used in parallel and then folded
1449/// back onto the main builder.
1450///
1451/// # Error
1452///
1453/// Logs an error on drop if it was not moved to the `B::parallel_fold` method.
1454#[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}