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 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 _;