simple_layout/
lib.rs

1use std::num::Saturating;
2use std::ops::{Add, AddAssign, Range, Sub};
3
4mod draw;
5
6mod align;
7mod border;
8mod expand;
9mod layoutable;
10mod linear;
11mod padding;
12mod placement;
13mod scale;
14
15pub mod prelude {
16    pub use crate::{
17        align::{center, east, north, south, west},
18        border::{bordered, DashedLine, RoundedLine},
19        expand::{expand, expand_horizontal, expand_vertical},
20        layoutable::{owned_text, Layoutable},
21        linear::{horizontal_layout, vertical_layout},
22        padding::padding,
23        placement::{callback_placement, optional_placement},
24        scale::scale,
25    };
26}
27
28///
29/// Defined preferred size of a Layoutable
30///
31#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
32pub struct ComponentSize {
33    width: ValueRange<Saturating<u32>>,
34    height: ValueRange<Saturating<u32>>,
35}
36
37#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
38pub struct ValueRange<V> {
39    preferred_value: V,
40    min_value: V,
41    max_value: V,
42}
43
44impl<V> Add<V> for ValueRange<V>
45where
46    V: Add<V, Output = V> + Clone,
47{
48    type Output = ValueRange<V>;
49
50    fn add(self, rhs: V) -> Self::Output {
51        ValueRange {
52            preferred_value: self.preferred_value + rhs.clone(),
53            min_value: self.min_value + rhs.clone(),
54            max_value: self.max_value + rhs,
55        }
56    }
57}
58impl Add<i32> for ValueRange<Saturating<u32>> {
59    type Output = ValueRange<Saturating<u32>>;
60
61    fn add(self, rhs: i32) -> Self::Output {
62        if rhs.is_negative() {
63            let offset = Saturating(-rhs as u32);
64            ValueRange {
65                preferred_value: self.preferred_value - offset,
66                min_value: self.min_value - offset,
67                max_value: self.max_value - offset,
68            }
69        } else {
70            let offset = Saturating(rhs as u32);
71            ValueRange {
72                preferred_value: self.preferred_value + offset,
73                min_value: self.min_value + offset,
74                max_value: self.max_value + offset,
75            }
76        }
77    }
78}
79impl<V> Sub<V> for ValueRange<V>
80where
81    V: Sub<V, Output = V> + Clone,
82{
83    type Output = ValueRange<V>;
84
85    fn sub(self, rhs: V) -> Self::Output {
86        ValueRange {
87            preferred_value: self.preferred_value - rhs.clone(),
88            min_value: self.min_value - rhs.clone(),
89            max_value: self.max_value - rhs,
90        }
91    }
92}
93
94impl<V: PartialOrd + Clone> ValueRange<V> {
95    fn expand(&mut self, rhs: &Self) {
96        if self.preferred_value < rhs.preferred_value {
97            self.preferred_value = rhs.preferred_value.clone();
98        }
99        if self.min_value < rhs.min_value {
100            self.min_value = rhs.min_value.clone()
101        }
102        if self.max_value < rhs.max_value {
103            self.max_value = rhs.max_value.clone()
104        }
105    }
106}
107
108impl<V: AddAssign> AddAssign for ValueRange<V> {
109    fn add_assign(&mut self, rhs: Self) {
110        self.preferred_value += rhs.preferred_value;
111        self.min_value += rhs.min_value;
112        self.max_value += rhs.max_value;
113    }
114}
115
116impl<V: Clone> ValueRange<Saturating<V>> {
117    fn fixed(value: V) -> Self {
118        Self {
119            preferred_value: Saturating(value.clone()),
120            min_value: Saturating(value.clone()),
121            max_value: Saturating(value),
122        }
123    }
124}
125
126impl ValueRange<Saturating<u32>> {
127    fn expand_max(&self) -> Self {
128        Self {
129            preferred_value: self.preferred_value,
130            min_value: self.min_value,
131            max_value: Saturating(u32::MAX),
132        }
133    }
134}
135
136impl ComponentSize {
137    ///
138    /// Create a fixed sized constraint
139    ///
140    /// # Arguments
141    ///
142    /// * `width`: fixed width
143    /// * `height`: fixed height
144    ///
145    /// returns: ComponentSize
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// use simple_layout::ComponentSize;
151    /// //defined  a 8x8 fixed size
152    /// let fixed = ComponentSize::fixed_size(8,8);
153    /// ```
154    pub fn fixed_size(width: u32, height: u32) -> ComponentSize {
155        ComponentSize {
156            width: ValueRange::fixed(width),
157            height: ValueRange::fixed(height),
158        }
159    }
160    ///
161    /// Defines a fully customizeable component size
162    ///
163    /// # Arguments
164    ///
165    /// * `preferred_width`: optimal width of the component
166    /// * `preferred_height`: optimal height of the component
167    /// * `width_range`: minimum and maximum width, allows the layout algorithm to arrange and place that element
168    /// * `height_range`: minimum and maximum height, allows the layout algorithm to arrange and place that element
169    ///
170    /// returns: ComponentSize
171    ///
172    pub fn new(
173        preferred_width: u32,
174        preferred_height: u32,
175        width_range: Range<u32>,
176        height_range: Range<u32>,
177    ) -> Self {
178        Self {
179            width: ValueRange {
180                preferred_value: Saturating(preferred_width),
181                min_value: Saturating(width_range.start),
182                max_value: Saturating(width_range.end),
183            },
184            height: ValueRange {
185                preferred_value: Saturating(preferred_height),
186                min_value: Saturating(height_range.start),
187                max_value: Saturating(height_range.end),
188            },
189        }
190    }
191}