limn_text_layout/
types.rs

1use euclid;
2
3// in logical pixels
4pub type Size = euclid::Size2D<f32>;
5pub type Point = euclid::Point2D<f32>;
6pub type Vector = euclid::Vector2D<f32>;
7pub type Rect = euclid::Rect<f32>;
8
9pub trait RectExt<T> {
10    fn left(&self) -> T;
11    fn top(&self) -> T;
12    fn right(&self) -> T;
13    fn bottom(&self) -> T;
14    fn width(&self) -> T;
15    fn height(&self) -> T;
16    fn from_ranges(x: Range, y: Range) -> Self;
17    fn x_range(&self) -> Range;
18    fn y_range(&self) -> Range;
19}
20impl RectExt<f32> for Rect {
21    fn left(&self) -> f32 {
22        self.origin.x
23    }
24    fn top(&self) -> f32 {
25        self.origin.y
26    }
27    fn right(&self) -> f32 {
28        self.origin.x + self.size.width
29    }
30    fn bottom(&self) -> f32 {
31        self.origin.y + self.size.height
32    }
33    fn width(&self) -> f32 {
34        self.size.width
35    }
36    fn height(&self) -> f32 {
37        self.size.height
38    }
39    fn from_ranges(x: Range, y: Range) -> Self {
40        Rect::new(Point::new(x.start, y.start), Size::new(x.end - x.start, y.end - y.start))
41    }
42    fn x_range(&self) -> Range {
43        Range::new(self.left(), self.right())
44    }
45    fn y_range(&self) -> Range {
46        Range::new(self.top(), self.bottom())
47    }
48}
49
50/// The orientation of **Align**ment along some **Axis**.
51#[derive(Copy, Clone, Debug, PartialEq, Eq)]
52pub enum Align {
53    /// **Align** our **Start** with the **Start** of some other widget along the **Axis**.
54    Start,
55    /// **Align** our **Middle** with the **Middle** of some other widget along the **Axis**.
56    Middle,
57    /// **Align** our **End** with the **End** of some other widget along the **Axis**.
58    End,
59}
60
61#[derive(Copy, Clone, Debug, PartialEq)]
62pub struct Range {
63    /// The start of some `Range` along an axis.
64    pub start: f32,
65    /// The end of some `Range` along an axis.
66    pub end: f32,
67}
68
69impl Range {
70    pub fn new(start: f32, end: f32) -> Range {
71        Range {
72            start: start,
73            end: end,
74        }
75    }
76    pub fn from_pos_and_len(pos: f32, len: f32) -> Range {
77        let half_len = len / 2.0;
78        let start = pos - half_len;
79        let end = pos + half_len;
80        Range::new(start, end)
81    }
82    pub fn middle(&self) -> f32 {
83        (self.end + self.start) / 2.0
84    }
85    pub fn is_over(&self, pos: f32) -> bool {
86        let Range { start, end } = self.undirected();
87        pos >= start && pos <= end
88    }
89    pub fn has_same_direction(self, other: Self) -> bool {
90        let self_direction = self.start <= self.end;
91        let other_direction = other.start <= other.end;
92        self_direction == other_direction
93    }
94    pub fn shift(self, amount: f32) -> Range {
95        Range {
96            start: self.start + amount,
97            end: self.end + amount,
98        }
99    }
100    pub fn undirected(self) -> Range {
101        if self.start > self.end {
102            self.invert()
103        } else {
104            self
105        }
106    }
107    pub fn invert(self) -> Range {
108        Range {
109            start: self.end,
110            end: self.start,
111        }
112    }
113    pub fn align_start_of(self, other: Self) -> Self {
114        let diff = if self.has_same_direction(other) {
115            other.start - self.start
116        } else {
117            other.start - self.end
118        };
119        self.shift(diff)
120    }
121    pub fn align_middle_of(self, other: Self) -> Self {
122        let diff = other.middle() - self.middle();
123        self.shift(diff)
124    }
125    pub fn align_end_of(self, other: Self) -> Self {
126        let diff = if self.has_same_direction(other) {
127            other.end - self.end
128        } else {
129            other.end - self.start
130        };
131        self.shift(diff)
132    }
133}