rate_ui/widget/
lazy_bridge.rs

1use 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    // This filled only if subscribe method called
23    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}