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#[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 pub fn fixed_size(width: u32, height: u32) -> ComponentSize {
155 ComponentSize {
156 width: ValueRange::fixed(width),
157 height: ValueRange::fixed(height),
158 }
159 }
160 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}