geng_ui/
widget.rs

1use super::*;
2
3#[derive(Default)]
4pub struct Sense {
5    pub clicked: bool,
6    pub click_time: Option<f64>,
7    pub hovered_time: Option<f64>,
8    pub captured_time: Option<f64>,
9}
10
11impl Sense {
12    pub fn is_hovered(&self) -> bool {
13        self.hovered_time.is_some()
14    }
15    pub fn is_captured(&self) -> bool {
16        self.captured_time.is_some()
17    }
18    pub fn set_hovered(&mut self, hovered: bool) {
19        if hovered {
20            if self.hovered_time.is_none() {
21                self.hovered_time = Some(0.0);
22            }
23        } else {
24            self.hovered_time = None;
25        }
26    }
27    pub fn set_captured(&mut self, captured: bool) {
28        if captured {
29            if self.captured_time.is_none() {
30                self.captured_time = Some(0.0);
31            }
32        } else {
33            self.captured_time = None;
34        }
35    }
36    pub fn click(&mut self) {
37        self.click_time = Some(0.0);
38        self.clicked = true;
39    }
40    pub fn take_clicked(&mut self) -> bool {
41        std::mem::replace(&mut self.clicked, false)
42    }
43    pub fn update(&mut self, delta_time: f64) {
44        if let Some(time) = &mut self.click_time {
45            *time += delta_time;
46        }
47        if let Some(time) = &mut self.hovered_time {
48            *time += delta_time;
49        }
50        if let Some(time) = &mut self.captured_time {
51            *time += delta_time;
52        }
53    }
54    pub fn handle_event(&mut self, _event: &Event) {
55        // if let Event::Click { .. } = event {
56        //     self.clicked = true;
57        //     self.click_time = Some(0.0);
58        // }
59        todo!()
60    }
61}
62
63#[derive(Debug, Copy, Clone)]
64pub struct Constraints {
65    pub min_size: vec2<f64>,
66    pub flex: vec2<f64>,
67}
68
69impl Constraints {
70    pub fn zero() -> Self {
71        Self {
72            min_size: vec2::ZERO,
73            flex: vec2::ZERO,
74        }
75    }
76}
77
78impl Default for Constraints {
79    fn default() -> Self {
80        Self {
81            min_size: vec2(0.0, 0.0),
82            flex: vec2(1.0, 1.0),
83        }
84    }
85}
86
87pub struct DrawContext<'a, 'b> {
88    pub draw2d: &'a draw2d::Helper,
89    pub theme: &'a Theme,
90    pub position: Aabb2<f64>,
91    pub framebuffer: &'a mut ugli::Framebuffer<'b>,
92}
93
94pub trait Widget {
95    fn sense(&mut self) -> Option<&mut Sense> {
96        None
97    }
98    fn update(&mut self, delta_time: f64) {
99        #![allow(unused_variables)]
100    }
101    fn draw(&mut self, cx: &mut DrawContext) {
102        #![allow(unused_variables)]
103    }
104    fn handle_event(&mut self, event: &Event) {
105        #![allow(unused_variables)]
106    }
107    fn walk_children_mut(&mut self, f: &mut dyn FnMut(&mut dyn Widget)) {
108        #![allow(unused_variables)]
109    }
110    fn calc_constraints(&mut self, children: &ConstraintsContext) -> Constraints;
111    fn layout_children(&mut self, cx: &mut LayoutContext) {
112        self.walk_children_mut(&mut |child| cx.set_position(child, cx.position));
113    }
114}
115
116impl<T: Widget> Widget for Box<T> {
117    fn calc_constraints(&mut self, children: &ConstraintsContext) -> Constraints {
118        children.get_constraints(&**self)
119    }
120    fn walk_children_mut(&mut self, f: &mut dyn FnMut(&mut dyn Widget)) {
121        f(&mut **self);
122    }
123}
124
125impl Widget for Box<dyn Widget + '_> {
126    fn calc_constraints(&mut self, cx: &ConstraintsContext) -> Constraints {
127        cx.get_constraints(&**self)
128    }
129    fn walk_children_mut(&mut self, f: &mut dyn FnMut(&mut dyn Widget)) {
130        f(&mut **self);
131    }
132}
133
134mod ext {
135    use super::*;
136
137    pub trait WidgetExt<'a>: Widget + Sized + 'a {
138        fn boxed(self) -> Box<dyn Widget + 'a> {
139            Box::new(self)
140        }
141    }
142
143    impl<'a, T: Widget + 'a> WidgetExt<'a> for T {}
144}
145
146pub use ext::WidgetExt as _;