1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
use crate::preludes::widget_creation::*;
/// All widgets implement this trait.
/// You can also create your own widgets by
/// implementing this trait yourself!
pub trait Widget {
/// Logic for drawing to a canvas
fn draw(&mut self, canvas: &mut Canvas, state_frame: Option<&EventStateFrame>);
/// Information about the widget, such as the size information like,
/// does your widget require a fixed size? Or is it dynamic with a
/// minumum and maximum size?
fn widget_info(&self) -> WidgetInfo;
/// Returns a mutable reference to the widget's internal special data
fn widget_data(&mut self) -> &mut WidgetData;
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
/// Widget data for internal use of the library
pub struct WidgetData {
/// Animation data
pub animation_data: AnimationData,
}
impl WidgetData {
pub fn new() -> Self {
Self {
animation_data: AnimationData::new(),
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
/// Animation data for widgets
pub struct AnimationData {
creation_time: std::time::Instant,
}
impl AnimationData {
pub fn new() -> Self {
Self {
creation_time: std::time::Instant::now(),
}
}
/// Reset animation data
pub fn reset(&mut self) {
*self = Self::new();
}
/// The time the animation data was created
pub fn creation_time(&self) -> std::time::Instant {
return self.creation_time;
}
/// How long the animation data has existed for
pub fn duration(&self) -> std::time::Duration {
return std::time::Instant::now() - self.creation_time();
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
/// Widget information
pub struct WidgetInfo {
/// Size information dictating whether or not
/// the widget is fixed size or dynamic
pub size_info: WidgetSizeInfo,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
/// Information on how a widget's size can be changed
pub enum WidgetSizeInfoCanChange {
/// The widget size cannot grow or shrink
CannotChange,
/// The widget size can be bigger
CanGrow {
cols: bool,
rows: bool,
},
/// The widget size can be smaller
CanShrink {
cols: bool,
rows: bool,
},
/// The widget size is invalid to begin with
Invalid,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
/// Widget size information
pub enum WidgetSizeInfo {
Dynamic {
min: Option<Size>,
max: Option<Size>,
},
Fixed(Size),
}
impl WidgetSizeInfo {
/// Get minimum size
pub fn get_min(&self) -> Size {
match self {
Self::Dynamic { min, .. } => min.unwrap_or(Size::zero()),
Self::Fixed(fixed) => *fixed,
}
}
/// Get maximum size
pub fn get_max(&self) -> Size {
match self {
Self::Dynamic { max, .. } => max.unwrap_or(Size::new(u16::MAX, u16::MAX)),
Self::Fixed(fixed) => *fixed,
}
}
/// Assuming the passed in size is for something such as the canvas
/// that the widget will be drawn to, this function will return
/// information on how that size can be potentially changed while
/// still being valid
pub fn can_change_size(&self, size: Size) -> Vec<WidgetSizeInfoCanChange> {
if self.correct_size(size) != size {
return vec![WidgetSizeInfoCanChange::Invalid];
}
match self {
Self::Dynamic { min, max } => {
let mut potentials: Vec<WidgetSizeInfoCanChange> = Vec::new();
let min_size = min.unwrap_or(Size::zero());
let max_size = max.unwrap_or(Size::same(u16::MAX));
if min_size.area() < size.area() {
let cols: bool = min_size.cols < size.cols;
let rows: bool = min_size.rows < size.rows;
potentials.push(WidgetSizeInfoCanChange::CanShrink {
cols,
rows,
});
}
if max_size.area() > size.area() {
let cols: bool = max_size.cols > size.cols;
let rows: bool = max_size.rows > size.rows;
potentials.push(WidgetSizeInfoCanChange::CanGrow {
cols,
rows,
});
}
if potentials.is_empty() {
potentials.push(WidgetSizeInfoCanChange::CannotChange);
}
potentials
},
Self::Fixed(_) => vec![WidgetSizeInfoCanChange::CannotChange],
}
}
/// Correct a size, this is used for things like correcting
/// a canvas in a parent container widget. If the child's canvas is too
/// small or too big, this function will correct the size according
/// to the method owner's widget size information
pub fn correct_size(&self, size: Size) -> Size {
let mut new_size = size;
match self {
Self::Dynamic { min, max } => {
let min = min.unwrap_or(Size::new(0, 0));
let mut check_max = true;
if new_size.cols < min.cols {
new_size.cols = min.cols;
check_max = false;
}
if new_size.rows < min.rows {
new_size.rows = min.rows;
check_max = false;
}
if check_max {
if let Some(max) = max {
if new_size.cols > max.cols {
new_size.cols = max.cols;
}
if new_size.rows > max.rows {
new_size.rows = max.rows;
}
}
}
},
Self::Fixed(fixed_size) => new_size = *fixed_size,
};
return new_size;
}
}