rate_ui/widget/
lazy_bridge.rs1use super::{Context, Msg, Widget, WidgetRuntime};
2use anyhow::{anyhow, Error};
3use yew::worker::Agent;
4use yew::{Bridge, Bridged, ComponentLink};
5
6pub trait OnBridgeEvent<T: Agent>: Widget {
7 fn on_event(&mut self, _response: T::Output, _ctx: &mut Context<Self>) -> Result<(), Error> {
8 let self_type_name = std::any::type_name::<Self>();
9 let type_name = std::any::type_name::<T>();
10 Err(anyhow!(
11 "No implementation for incoming event from the agent: {} of {}.",
12 type_name,
13 self_type_name
14 ))
15 }
16}
17
18pub type Handler<E, W> = &'static dyn Fn(&mut W, E, &mut Context<W>) -> Result<(), Error>;
19
20pub struct LazyBridge<T: Agent, W: Widget> {
21 link: Option<Box<dyn Bridge<T>>>,
22 handler: Option<Handler<T::Output, W>>,
24}
25
26impl<T: Agent, W: Widget> Default for LazyBridge<T, W> {
27 fn default() -> Self {
28 Self {
29 link: None,
30 handler: None,
31 }
32 }
33}
34
35impl<T: Agent, W: Widget> LazyBridge<T, W> {
36 pub fn activate_link(
37 &mut self,
38 widget_link: &ComponentLink<WidgetRuntime<W>>,
39 ) -> &mut dyn Bridge<T>
40 where
41 Msg<W>: From<T::Output>,
42 {
43 if self.link.is_none() {
44 let callback = widget_link.callback(Msg::from);
45 let link = T::bridge(callback);
46 self.link = Some(link);
47 }
48 self.link.as_deref_mut().unwrap()
49 }
50
51 pub fn activate_handler(&mut self)
52 where
53 W: OnBridgeEvent<T>,
54 {
55 if self.handler.is_none() {
56 let handler = &<W as OnBridgeEvent<T>>::on_event;
57 self.handler = Some(handler);
58 }
59 }
60
61 pub fn get_mut_linked(
62 &mut self,
63 widget_link: &ComponentLink<WidgetRuntime<W>>,
64 ) -> &mut dyn Bridge<T>
65 where
66 Msg<W>: From<T::Output>,
67 W: OnBridgeEvent<T>,
68 {
69 self.activate_handler();
70 self.activate_link(widget_link)
71 }
72
73 pub fn handler(&self) -> Option<Handler<T::Output, W>> {
74 self.handler
75 }
76}