orbtk_utils/
alignment.rs

1use crate::Value;
2
3/// Used to align a widget vertical or horizontal.
4#[derive(Copy, Clone, PartialEq, Debug)]
5pub enum Alignment {
6    Start,
7    Center,
8    End,
9    Stretch,
10}
11
12impl Default for Alignment {
13    fn default() -> Self {
14        Alignment::Stretch
15    }
16}
17
18impl Alignment {
19    /// Calculates and returns an aligned position.
20    ///
21    /// The returned measure value represents a placement value
22    /// (either a `x` or `y` coordinate). You may use this alignment
23    /// value, so the given widget can consume the maximum available
24    /// size inside the render, while respecting its `alignment
25    /// specification` as well as its `margins` bounds.
26    pub fn align_position(
27        self,
28        available_measure: f64,
29        measure: f64,
30        margin_start: f64,
31        margin_end: f64,
32    ) -> f64 {
33        match self {
34            Alignment::End => available_measure - measure - margin_end,
35            Alignment::Center => (available_measure - measure) / 2.0,
36            _ => margin_start,
37        }
38    }
39
40    /// Calculates and returns a measure.
41    ///
42    /// The returned measure value represents a placement value
43    /// (either a `x` or `y` coordinate). You may use this alignment
44    /// value, so the given widget can consume the maximum
45    /// available size inside the render, while respecting its `margin`
46    /// bounds.
47    pub fn align_measure(
48        self,
49        available_measure: f64,
50        measure: f64,
51        margin_start: f64,
52        margin_end: f64,
53    ) -> f64 {
54        match self {
55            Alignment::Stretch => available_measure - margin_start - margin_end,
56            _ => measure,
57        }
58    }
59}
60
61impl From<&str> for Alignment {
62    fn from(t: &str) -> Self {
63        match t {
64            "End" | "end" => Alignment::End,
65            "Center" | "center" => Alignment::Center,
66            "Start" | "start" => Alignment::Start,
67            _ => Alignment::Stretch,
68        }
69    }
70}
71
72impl From<String> for Alignment {
73    fn from(s: String) -> Alignment {
74        Self::from(&s[..])
75    }
76}
77
78impl From<Value> for Alignment {
79    fn from(v: Value) -> Self {
80        let value = v.get::<String>();
81        Alignment::from(value)
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use crate::prelude::*;
88
89    #[test]
90    fn test_align_position() {
91        let available_measure = 100.0;
92        let measure = 50.0;
93
94        let alignment = Alignment::Stretch;
95        assert!(crate::f64_cmp(
96            alignment.align_position(available_measure, measure, 0.0, 0.0),
97            0.0,
98        ));
99
100        let alignment = Alignment::Center;
101        assert!(crate::f64_cmp(
102            alignment.align_position(available_measure, measure, 0.0, 0.0),
103            25.0,
104        ));
105
106        let alignment = Alignment::Start;
107        assert!(crate::f64_cmp(
108            alignment.align_position(available_measure, measure, 0.0, 0.0),
109            0.0,
110        ));
111
112        let alignment = Alignment::End;
113        assert!(crate::f64_cmp(
114            alignment.align_position(available_measure, measure, 0.0, 0.0),
115            50.0,
116        ));
117    }
118
119    #[test]
120    fn test_align_measure() {
121        let available_measure = 100.0;
122        let measure = 50.0;
123
124        let alignment = Alignment::Stretch;
125        assert!(crate::f64_cmp(
126            alignment.align_measure(available_measure, measure, 0.0, 0.0),
127            available_measure,
128        ));
129
130        let alignment = Alignment::Center;
131        assert!(crate::f64_cmp(
132            alignment.align_measure(available_measure, measure, 0.0, 0.0),
133            measure,
134        ));
135
136        let alignment = Alignment::Start;
137        assert!(crate::f64_cmp(
138            alignment.align_measure(available_measure, measure, 0.0, 0.0),
139            measure,
140        ));
141
142        let alignment = Alignment::End;
143        assert!(crate::f64_cmp(
144            alignment.align_measure(available_measure, measure, 0.0, 0.0),
145            measure,
146        ));
147    }
148
149    macro_rules! value {
150        ( $e:expr ) => {
151            Value(ron::Value::String(($e).to_string()))
152        };
153    }
154
155    #[test]
156    fn test_into() {
157        let alignment: Alignment = "Start".into();
158        assert_eq!(alignment, Alignment::Start);
159
160        let alignment: Alignment = "start".into();
161        assert_eq!(alignment, Alignment::Start);
162
163        let alignment: Alignment = "Center".into();
164        assert_eq!(alignment, Alignment::Center);
165
166        let alignment: Alignment = "center".into();
167        assert_eq!(alignment, Alignment::Center);
168
169        let alignment: Alignment = "End".into();
170        assert_eq!(alignment, Alignment::End);
171
172        let alignment: Alignment = "end".into();
173        assert_eq!(alignment, Alignment::End);
174
175        let alignment: Alignment = "Stretch".into();
176        assert_eq!(alignment, Alignment::Stretch);
177
178        let alignment: Alignment = "stretch".into();
179        assert_eq!(alignment, Alignment::Stretch);
180
181        let alignment: Alignment = "other".into();
182        assert_eq!(alignment, Alignment::Stretch);
183
184        let alignment: Alignment = value!("Start").into();
185        assert_eq!(alignment, Alignment::Start);
186
187        let alignment: Alignment = value!("start").into();
188        assert_eq!(alignment, Alignment::Start);
189
190        let alignment: Alignment = value!("Center").into();
191        assert_eq!(alignment, Alignment::Center);
192
193        let alignment: Alignment = value!("center").into();
194        assert_eq!(alignment, Alignment::Center);
195
196        let alignment: Alignment = value!("End").into();
197        assert_eq!(alignment, Alignment::End);
198
199        let alignment: Alignment = value!("end").into();
200        assert_eq!(alignment, Alignment::End);
201
202        let alignment: Alignment = value!("Stretch").into();
203        assert_eq!(alignment, Alignment::Stretch);
204
205        let alignment: Alignment = value!("stretch").into();
206        assert_eq!(alignment, Alignment::Stretch);
207
208        let alignment: Alignment = value!("other").into();
209        assert_eq!(alignment, Alignment::Stretch);
210    }
211}