winio_elm/
lib.rs

1//! ELM primitives for winio.
2
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![cfg_attr(feature = "gen_blocks", feature(async_iterator, gen_blocks))]
5#![warn(missing_docs)]
6
7use smallvec::SmallVec;
8
9/// Foundamental GUI component.
10#[allow(async_fn_in_trait)]
11pub trait Component: Sized {
12    /// Initial parameter type.
13    type Init<'a>;
14    /// The input message type to update.
15    type Message;
16    /// The output event type to the parent.
17    type Event;
18    /// The error type.
19    type Error: std::fmt::Debug;
20
21    /// Create the initial component.
22    async fn init(
23        init: Self::Init<'_>,
24        sender: &ComponentSender<Self>,
25    ) -> Result<Self, Self::Error>;
26
27    /// Start the event listening.
28    async fn start(&mut self, sender: &ComponentSender<Self>) -> ! {
29        let _ = sender;
30        std::future::pending().await
31    }
32
33    /// Respond to the message. Return true if need render.
34    async fn update(
35        &mut self,
36        message: Self::Message,
37        sender: &ComponentSender<Self>,
38    ) -> Result<bool, Self::Error> {
39        let _ = message;
40        let _ = sender;
41        Ok(false)
42    }
43
44    /// Render the widgets.
45    fn render(&mut self, sender: &ComponentSender<Self>) -> Result<(), Self::Error> {
46        let _ = sender;
47        Ok(())
48    }
49
50    /// Update the children components. Return true if any child needs render.
51    async fn update_children(&mut self) -> Result<bool, Self::Error> {
52        Ok(false)
53    }
54
55    /// Render the children components. It will be called if any child or self
56    /// needs render.
57    fn render_children(&mut self) -> Result<(), Self::Error> {
58        Ok(())
59    }
60}
61
62#[derive(Debug)]
63pub(crate) enum ComponentMessage<M, E> {
64    Message(M),
65    Event(E),
66}
67
68/// Sender of input messages and output events.
69#[derive(Debug)]
70#[repr(transparent)]
71pub struct ComponentSender<T: Component>(Channel<ComponentMessage<T::Message, T::Event>>);
72
73impl<T: Component> ComponentSender<T> {
74    pub(crate) fn new() -> Self {
75        Self(Channel::new())
76    }
77
78    pub(crate) fn from_ref(c: &Channel<ComponentMessage<T::Message, T::Event>>) -> &Self {
79        // Safety: repr(transparent)
80        unsafe { std::mem::transmute(c) }
81    }
82
83    /// Post the message to the queue.
84    pub fn post(&self, message: T::Message) {
85        self.0.send(ComponentMessage::Message(message))
86    }
87
88    /// Post the event to the queue.
89    pub fn output(&self, event: T::Event) {
90        self.0.send(ComponentMessage::Event(event))
91    }
92
93    pub(crate) async fn wait(&self) {
94        self.0.wait().await
95    }
96
97    pub(crate) fn fetch_all(&self) -> SmallVec<[ComponentMessage<T::Message, T::Event>; 1]> {
98        self.0.fetch_all()
99    }
100
101    /// Cast the sender for a different component type with the same message and
102    /// event types.
103    pub fn cast<U: Component<Message = T::Message, Event = T::Event>>(
104        &self,
105    ) -> &ComponentSender<U> {
106        ComponentSender::from_ref(&self.0)
107    }
108}
109
110impl<T: Component> Clone for ComponentSender<T> {
111    fn clone(&self) -> Self {
112        Self(self.0.clone())
113    }
114}
115
116mod channel;
117use channel::*;
118
119mod child;
120pub use child::*;
121
122mod collection;
123pub use collection::*;
124
125mod macros;
126pub use macros::*;
127
128mod run;
129pub use run::*;
130
131mod boxed;
132pub use boxed::*;
133
134#[cfg(feature = "gen_blocks")]
135mod stream;