Skip to main content

telar_ui_core/
layout_leaf.rs

1use geometry_core::Rect;
2use layout_core::{LayoutError, LayoutStyle, NodeId};
3use reactive_core::RwSignal;
4use ui_tree::{NodeVec, RenderNode};
5
6use crate::context;
7
8pub struct LayoutLeaf {
9    pub node: NodeId,
10    pub rect: RwSignal<Rect>,
11}
12
13impl LayoutLeaf {
14    pub fn register(layout_style: LayoutStyle) -> Result<Self, LayoutError> {
15        let (node, rect) = context::new_leaf(layout_style)?;
16        Ok(Self { node, rect })
17    }
18
19    pub(crate) fn at_layout_position(&self, content: RenderNode) -> RenderNode {
20        let r = self.rect.get();
21        RenderNode::Transform {
22            matrix: [1.0, 0.0, 0.0, 1.0, r.x, r.y],
23            children: NodeVec::collect([content]),
24        }
25    }
26}
27
28/// Resolves the `auto` sides of a media leaf (img/svg) against an intrinsic size: both auto → the
29/// intrinsic size; one auto with the other a px length → derive the auto side from the intrinsic
30/// aspect ratio; a percent side is left untouched. `intrinsic` is only evaluated when needed.
31pub(crate) fn resolve_intrinsic_size(
32    style: LayoutStyle,
33    intrinsic: impl FnOnce() -> (f32, f32),
34) -> LayoutStyle {
35    match (style.is_width_auto(), style.is_height_auto()) {
36        (true, true) => {
37            let (iw, ih) = intrinsic();
38            style.width(iw).height(ih)
39        }
40        (true, false) => match style.height_px() {
41            Some(h) => {
42                let (iw, ih) = intrinsic();
43                if ih > 0.0 {
44                    style.width(h * iw / ih)
45                } else {
46                    style
47                }
48            }
49            None => style,
50        },
51        (false, true) => match style.width_px() {
52            Some(w) => {
53                let (iw, ih) = intrinsic();
54                if iw > 0.0 {
55                    style.height(w * ih / iw)
56                } else {
57                    style
58                }
59            }
60            None => style,
61        },
62        (false, false) => style,
63    }
64}