1use super::{AdaptConfigCx, AdaptEventCx};
9use kas::prelude::*;
10use linear_map::LinearMap;
11use std::fmt::Debug;
12use std::marker::PhantomData;
13
14impl_scope! {
15 #[autoimpl(Deref, DerefMut using self.inner)]
21 #[autoimpl(Scrollable using self.inner where W: trait)]
22 #[widget {
23 layout = self.inner;
24 }]
25 pub struct Adapt<A, W: Widget<Data = S>, S: Debug> {
26 core: widget_core!(),
27 state: S,
28 #[widget(&self.state)]
29 inner: W,
30 configure_handler: Option<Box<dyn Fn(&mut AdaptConfigCx, &mut S)>>,
31 update_handler: Option<Box<dyn Fn(&mut AdaptConfigCx, &mut S, &A)>>,
32 timer_handlers: LinearMap<u64, Box<dyn Fn(&mut AdaptEventCx, &mut S, &A)>>,
33 message_handlers: Vec<Box<dyn Fn(&mut AdaptEventCx, &mut S, &A)>>,
34 }
35
36 impl Self {
37 #[inline]
39 pub fn new(inner: W, state: S) -> Self {
40 Adapt {
41 core: Default::default(),
42 state,
43 inner,
44 configure_handler: None,
45 update_handler: None,
46 timer_handlers: LinearMap::new(),
47 message_handlers: vec![],
48 }
49 }
50
51 pub fn on_configure<F>(mut self, handler: F) -> Self
53 where
54 F: Fn(&mut AdaptConfigCx, &mut S) + 'static,
55 {
56 debug_assert!(self.configure_handler.is_none());
57 self.configure_handler = Some(Box::new(handler));
58 self
59 }
60
61 pub fn on_update<F>(mut self, handler: F) -> Self
65 where
66 F: Fn(&mut AdaptConfigCx, &mut S, &A) + 'static,
67 {
68 debug_assert!(self.update_handler.is_none());
69 self.update_handler = Some(Box::new(handler));
70 self
71 }
72
73 pub fn on_timer<H>(mut self, timer_id: u64, handler: H) -> Self
79 where
80 H: Fn(&mut AdaptEventCx, &mut S, &A) + 'static,
81 {
82 debug_assert!(self.timer_handlers.get(&timer_id).is_none());
83 self.timer_handlers.insert(timer_id, Box::new(handler));
84 self
85 }
86
87 pub fn on_message<M, H>(self, handler: H) -> Self
94 where
95 M: Debug + 'static,
96 H: Fn(&mut AdaptEventCx, &mut S, M) + 'static,
97 {
98 self.on_messages(move |cx, state, _data| {
99 if let Some(m) = cx.try_pop() {
100 handler(cx, state, m);
101 }
102 })
103 }
104
105 pub fn on_messages<H>(mut self, handler: H) -> Self
107 where
108 H: Fn(&mut AdaptEventCx, &mut S, &A) + 'static,
109 {
110 self.message_handlers.push(Box::new(handler));
111 self
112 }
113 }
114
115 impl Events for Self {
116 type Data = A;
117
118 fn configure(&mut self, cx: &mut ConfigCx) {
119 if let Some(handler) = self.configure_handler.as_ref() {
120 let mut cx = AdaptConfigCx::new(cx, self.id());
121 handler(&mut cx, &mut self.state);
122 }
123 }
124
125 fn update(&mut self, cx: &mut ConfigCx, data: &A) {
126 if let Some(handler) = self.update_handler.as_ref() {
127 let mut cx = AdaptConfigCx::new(cx, self.id());
128 handler(&mut cx, &mut self.state, data);
129 }
130 }
131
132 fn handle_event(&mut self, cx: &mut EventCx, data: &Self::Data, event: Event) -> IsUsed {
133 match event {
134 Event::Timer(timer_id) => {
135 if let Some(handler) = self.timer_handlers.get(&timer_id) {
136 let mut cx = AdaptEventCx::new(cx, self.id());
137 handler(&mut cx, &mut self.state, data);
138 cx.update(self.as_node(data));
139 Used
140 } else {
141 Unused
142 }
143 }
144 _ => Unused,
145 }
146 }
147
148 fn handle_messages(&mut self, cx: &mut EventCx, data: &A) {
149 let count = cx.msg_op_count();
150 let mut cx = AdaptEventCx::new(cx, self.id());
151 for handler in self.message_handlers.iter() {
152 handler(&mut cx, &mut self.state, data);
153 }
154 if cx.msg_op_count() != count {
155 cx.update(self.as_node(data));
156 }
157 }
158 }
159}
160
161impl_scope! {
162 #[autoimpl(Deref, DerefMut using self.inner)]
166 #[autoimpl(Scrollable using self.inner where W: trait)]
167 #[widget {
168 Data = A;
169 layout = self.inner;
170 }]
171 pub struct Map<A, W: Widget, F>
172 where
173 F: for<'a> Fn(&'a A) -> &'a W::Data,
174 {
175 core: widget_core!(),
176 #[widget((self.map_fn)(data))]
177 inner: W,
178 map_fn: F,
179 _data: PhantomData<A>,
180 }
181
182 impl Self {
183 pub fn new(inner: W, map_fn: F) -> Self {
188 Map {
189 core: Default::default(),
190 inner,
191 map_fn,
192 _data: PhantomData,
193 }
194 }
195 }
196}