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
//! Component trait for UI building blocks.
use crate::{Event, Rect, Size, Surface};
/// Component trait - all UI elements implement this.
pub trait Component: Send {
/// Get the component's name for debugging.
fn name(&self) -> &str {
std::any::type_name::<Self>()
}
/// Request a render on the next frame.
fn request_render(&mut self);
/// Check if this component has pending render requests.
fn is_dirty(&self) -> bool;
/// Clear the dirty flag.
fn clear_dirty(&mut self);
/// Handle an input event.
/// Returns true if the event was consumed.
fn handle_event(&mut self, event: &Event) -> bool;
/// Render this component into the given surface area.
fn render(&mut self, surface: &mut Surface, area: Rect);
/// Get the component's minimum size.
fn min_size(&self) -> Size;
/// Get desired size, may be larger than min_size.
fn desired_size(&self) -> Option<Size> {
None
}
/// Called when this component gains focus.
fn on_focus(&mut self) {}
/// Called when this component loses focus.
fn on_unfocus(&mut self) {}
/// Check if this component is currently focused.
fn is_focused(&self) -> bool {
false
}
/// Request focus for this component.
fn focus(&mut self) {
self.on_focus();
}
/// Remove focus from this component.
fn unfocus(&mut self) {
self.on_unfocus();
}
}
/// Blanket implementation for Box<dyn Component>.
impl Component for Box<dyn Component> {
fn name(&self) -> &str {
self.as_ref().name()
}
fn request_render(&mut self) {
self.as_mut().request_render()
}
fn is_dirty(&self) -> bool {
self.as_ref().is_dirty()
}
fn clear_dirty(&mut self) {
self.as_mut().clear_dirty()
}
fn handle_event(&mut self, event: &Event) -> bool {
self.as_mut().handle_event(event)
}
fn render(&mut self, surface: &mut Surface, area: Rect) {
self.as_mut().render(surface, area)
}
fn min_size(&self) -> Size {
self.as_ref().min_size()
}
fn desired_size(&self) -> Option<Size> {
self.as_ref().desired_size()
}
fn on_focus(&mut self) {
self.as_mut().on_focus()
}
fn on_unfocus(&mut self) {
self.as_mut().on_unfocus()
}
fn is_focused(&self) -> bool {
self.as_ref().is_focused()
}
}