1use super::{AdaptConfigCx, AdaptEventCx};
9use kas::autoimpl;
10use kas::event::{ConfigCx, Event, EventCx, IsUsed};
11use kas::geom::{Coord, Offset, Rect};
12use kas::layout::{AlignHints, AxisInfo, SizeRules};
13use kas::theme::{DrawCx, SizeCx};
14#[allow(unused)] use kas::Events;
15use kas::{Id, Layout, LayoutExt, NavAdvance, Node, Widget};
16use std::fmt::Debug;
17
18#[autoimpl(Deref, DerefMut using self.inner)]
22#[autoimpl(Scrollable using self.inner where W: trait)]
23pub struct AdaptEvents<W: Widget> {
24 pub inner: W,
25 on_configure: Option<Box<dyn Fn(&mut AdaptConfigCx, &mut W)>>,
26 on_update: Option<Box<dyn Fn(&mut AdaptConfigCx, &mut W, &W::Data)>>,
27 message_handlers: Vec<Box<dyn Fn(&mut AdaptEventCx, &mut W, &W::Data)>>,
28}
29
30impl<W: Widget> AdaptEvents<W> {
31 #[inline]
33 pub fn new(inner: W) -> Self {
34 AdaptEvents {
35 inner,
36 on_configure: None,
37 on_update: None,
38 message_handlers: vec![],
39 }
40 }
41
42 #[must_use]
44 pub fn on_configure<F>(mut self, f: F) -> Self
45 where
46 F: Fn(&mut AdaptConfigCx, &mut W) + 'static,
47 {
48 self.on_configure = Some(Box::new(f));
49 self
50 }
51
52 #[must_use]
54 pub fn on_update<F>(mut self, f: F) -> Self
55 where
56 F: Fn(&mut AdaptConfigCx, &mut W, &W::Data) + 'static,
57 {
58 self.on_update = Some(Box::new(f));
59 self
60 }
61
62 #[must_use]
69 pub fn on_message<M, H>(self, handler: H) -> Self
70 where
71 M: Debug + 'static,
72 H: Fn(&mut AdaptEventCx, &mut W, M) + 'static,
73 {
74 self.on_messages(move |cx, w, _data| {
75 if let Some(m) = cx.try_pop() {
76 handler(cx, w, m);
77 }
78 })
79 }
80
81 pub fn map_message<M, N, H>(self, handler: H) -> Self
96 where
97 M: Debug + 'static,
98 N: Debug + 'static,
99 H: Fn(usize, M) -> N + 'static,
100 {
101 self.on_messages(move |cx, _, _| {
102 if let Some(index) = cx.last_child() {
103 if let Some(m) = cx.try_pop() {
104 cx.push(handler(index, m));
105 }
106 }
107 })
108 }
109
110 #[must_use]
115 pub fn on_messages<H>(mut self, handler: H) -> Self
116 where
117 H: Fn(&mut AdaptEventCx, &mut W, &W::Data) + 'static,
118 {
119 self.message_handlers.push(Box::new(handler));
120 self
121 }
122}
123
124impl<W: Widget> Widget for AdaptEvents<W> {
125 type Data = W::Data;
126
127 #[inline]
128 fn as_node<'a>(&'a mut self, data: &'a Self::Data) -> Node<'a> {
129 Node::new(self, data)
130 }
131
132 #[inline]
133 fn for_child_node(
134 &mut self,
135 data: &Self::Data,
136 index: usize,
137 closure: Box<dyn FnOnce(Node<'_>) + '_>,
138 ) {
139 self.inner.for_child_node(data, index, closure);
140 }
141
142 #[inline]
143 fn _configure(&mut self, cx: &mut ConfigCx, data: &Self::Data, id: Id) {
144 self.inner._configure(cx, data, id);
145
146 if let Some(ref f) = self.on_configure {
147 let mut cx = AdaptConfigCx::new(cx, self.inner.id());
148 f(&mut cx, &mut self.inner);
149 }
150 if let Some(ref f) = self.on_update {
151 let mut cx = AdaptConfigCx::new(cx, self.inner.id());
152 f(&mut cx, &mut self.inner, data);
153 }
154 }
155
156 fn _update(&mut self, cx: &mut ConfigCx, data: &Self::Data) {
157 self.inner._update(cx, data);
158
159 if let Some(ref f) = self.on_update {
160 let mut cx = AdaptConfigCx::new(cx, self.inner.id());
161 f(&mut cx, &mut self.inner, data);
162 }
163 }
164
165 #[inline]
166 fn _send(&mut self, cx: &mut EventCx, data: &Self::Data, id: Id, event: Event) -> IsUsed {
167 let is_used = self.inner._send(cx, data, id, event);
168
169 if cx.has_msg() {
170 let mut cx = AdaptEventCx::new(cx, self.inner.id());
171 for handler in self.message_handlers.iter() {
172 handler(&mut cx, &mut self.inner, data);
173 }
174 }
175
176 is_used
177 }
178
179 #[inline]
180 fn _replay(&mut self, cx: &mut EventCx, data: &Self::Data, id: Id) {
181 self.inner._replay(cx, data, id);
182
183 if cx.has_msg() {
184 let mut cx = AdaptEventCx::new(cx, self.inner.id());
185 for handler in self.message_handlers.iter() {
186 handler(&mut cx, &mut self.inner, data);
187 }
188 }
189 }
190
191 #[inline]
192 fn _nav_next(
193 &mut self,
194 cx: &mut ConfigCx,
195 data: &Self::Data,
196 focus: Option<&Id>,
197 advance: NavAdvance,
198 ) -> Option<Id> {
199 self.inner._nav_next(cx, data, focus, advance)
200 }
201}
202
203impl<W: Widget> Layout for AdaptEvents<W> {
204 #[inline]
205 fn as_layout(&self) -> &dyn Layout {
206 self
207 }
208
209 #[inline]
210 fn id_ref(&self) -> &Id {
211 self.inner.id_ref()
212 }
213
214 #[inline]
215 fn rect(&self) -> Rect {
216 self.inner.rect()
217 }
218
219 #[inline]
220 fn widget_name(&self) -> &'static str {
221 "AdaptEvents"
222 }
223
224 #[inline]
225 fn num_children(&self) -> usize {
226 self.inner.num_children()
227 }
228
229 #[inline]
230 fn get_child(&self, index: usize) -> Option<&dyn Layout> {
231 self.inner.get_child(index)
232 }
233
234 #[inline]
235 fn find_child_index(&self, id: &Id) -> Option<usize> {
236 self.inner.find_child_index(id)
237 }
238
239 #[inline]
240 fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
241 self.inner.size_rules(sizer, axis)
242 }
243
244 #[inline]
245 fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints) {
246 self.inner.set_rect(cx, rect, hints);
247 }
248
249 #[inline]
250 fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize> {
251 self.inner.nav_next(reverse, from)
252 }
253
254 #[inline]
255 fn translation(&self) -> Offset {
256 self.inner.translation()
257 }
258
259 #[inline]
260 fn find_id(&mut self, coord: Coord) -> Option<Id> {
261 self.inner.find_id(coord)
262 }
263
264 #[inline]
265 fn draw(&mut self, draw: DrawCx) {
266 self.inner.draw(draw);
267 }
268}