Skip to main content

cranpose_ui_layout/
alignment_lines.rs

1/// Text baselines measured down from a layout's top edge.
2///
3/// Containers inherit the smallest first baseline and largest last baseline of
4/// their placed children. A missing line remains unspecified through translation.
5#[derive(Clone, Copy, Debug)]
6pub struct AlignmentLines {
7    first: f32,
8    last: f32,
9}
10
11impl AlignmentLines {
12    /// Creates alignment lines. Non-finite coordinates are treated as unspecified.
13    pub fn new(first: Option<f32>, last: Option<f32>) -> Self {
14        Self {
15            first: first.filter(|value| value.is_finite()).unwrap_or(f32::NAN),
16            last: last.filter(|value| value.is_finite()).unwrap_or(f32::NAN),
17        }
18    }
19
20    /// The first drawn text baseline, when this layout provides one.
21    pub fn first_baseline(self) -> Option<f32> {
22        self.first.is_finite().then_some(self.first)
23    }
24
25    /// The last drawn text baseline, when this layout provides one.
26    pub fn last_baseline(self) -> Option<f32> {
27        self.last.is_finite().then_some(self.last)
28    }
29
30    /// Translates specified lines by a child's vertical placement.
31    pub fn translated(self, y: f32) -> Self {
32        Self {
33            first: self.first + y,
34            last: self.last + y,
35        }
36    }
37
38    /// Inherits the first and last lines of another placed child.
39    pub fn merge(&mut self, other: Self) {
40        self.first = self.first.min(other.first);
41        self.last = self.last.max(other.last);
42    }
43
44    /// Replaces inherited lines with the lines explicitly provided by a layout.
45    pub fn with_overrides(self, explicit: Self) -> Self {
46        Self::new(
47            explicit.first_baseline().or_else(|| self.first_baseline()),
48            explicit.last_baseline().or_else(|| self.last_baseline()),
49        )
50    }
51}
52
53impl Default for AlignmentLines {
54    fn default() -> Self {
55        Self {
56            first: f32::NAN,
57            last: f32::NAN,
58        }
59    }
60}
61
62impl PartialEq for AlignmentLines {
63    fn eq(&self, other: &Self) -> bool {
64        self.first_baseline() == other.first_baseline()
65            && self.last_baseline() == other.last_baseline()
66    }
67}