relm4/component/sync/
connector.rs

1// Copyright 2021-2022 Aaron Erhardt <aaron.erhardt@t-online.de>
2// Copyright 2022 System76 <info@system76.com>
3// SPDX-License-Identifier: MIT or Apache-2.0
4
5use super::stream::ComponentStream;
6use super::{Component, ComponentController, Controller, StateWatcher};
7use crate::{Receiver, Sender};
8use std::fmt::{self, Debug};
9
10/// Contains the post-launch input sender and output receivers with the root widget.
11///
12/// The receiver can be separated from the [`Connector`] by choosing a method for handling it.
13pub struct Connector<C: Component> {
14    /// The models and widgets maintained by the component.
15    pub(super) state: StateWatcher<C>,
16
17    /// The widget that this component manages.
18    pub(super) widget: C::Root,
19
20    /// Used for emitting events to the component.
21    pub(super) sender: Sender<C::Input>,
22
23    /// The outputs being received by the component.
24    pub(super) receiver: Receiver<C::Output>,
25}
26
27impl<C: Component> Connector<C> {
28    /// Forwards output events to the designated sender.
29    pub fn forward<X: 'static, F: (Fn(C::Output) -> X) + 'static>(
30        self,
31        sender_: &Sender<X>,
32        transform: F,
33    ) -> Controller<C> {
34        let Self {
35            state,
36            widget,
37            sender,
38            receiver,
39        } = self;
40
41        crate::spawn_local(receiver.forward(sender_.clone(), transform));
42
43        Controller {
44            state,
45            widget,
46            sender,
47        }
48    }
49
50    /// Given a mutable closure, captures the receiver for handling.
51    pub fn connect_receiver<F: FnMut(&mut Sender<C::Input>, C::Output) + 'static>(
52        self,
53        mut func: F,
54    ) -> Controller<C> {
55        let Self {
56            state,
57            widget,
58            sender,
59            receiver,
60        } = self;
61
62        let mut sender_ = sender.clone();
63        crate::spawn_local(async move {
64            while let Some(event) = receiver.recv().await {
65                func(&mut sender_, event);
66            }
67        });
68
69        Controller {
70            state,
71            widget,
72            sender,
73        }
74    }
75
76    /// Ignore outputs from the component and finish the builder.
77    pub fn detach(self) -> Controller<C> {
78        let Self {
79            state,
80            widget,
81            sender,
82            ..
83        } = self;
84
85        Controller {
86            state,
87            widget,
88            sender,
89        }
90    }
91
92    /// Convert his type into a [`Stream`](futures::Stream) that yields output events
93    /// as futures.
94    pub fn into_stream(self) -> ComponentStream<C> {
95        let Self {
96            receiver, state, ..
97        } = self;
98
99        ComponentStream {
100            stream: receiver.into_stream(),
101            shutdown_on_drop: state.shutdown_on_drop,
102        }
103    }
104}
105
106impl<C: Component> ComponentController<C> for Connector<C> {
107    fn sender(&self) -> &Sender<C::Input> {
108        &self.sender
109    }
110
111    fn state(&self) -> &StateWatcher<C> {
112        &self.state
113    }
114
115    fn widget(&self) -> &C::Root {
116        &self.widget
117    }
118
119    fn detach_runtime(&mut self) {
120        self.state.detach_runtime();
121    }
122}
123
124impl<C> Debug for Connector<C>
125where
126    C: Component + Debug,
127    C::Widgets: Debug,
128{
129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        f.debug_struct("Connector")
131            .field("state", &self.state)
132            .field("widget", &self.widget)
133            .field("sender", &self.sender)
134            .field("receiver", &self.receiver)
135            .finish()
136    }
137}