raui_core/
messenger.rs

1//! Widget messaging
2
3use crate::widget::WidgetId;
4use std::{any::Any, sync::mpsc::Sender};
5
6pub trait MessageData: std::fmt::Debug + Send + Sync {
7    fn clone_message(&self) -> Box<dyn MessageData>;
8    fn as_any(&self) -> &dyn Any;
9}
10
11impl Clone for Box<dyn MessageData> {
12    fn clone(&self) -> Self {
13        self.clone_message()
14    }
15}
16
17pub type Message = Box<dyn MessageData>;
18pub type Messages = Vec<Message>;
19
20#[derive(Clone)]
21pub struct MessageSender(Sender<(WidgetId, Message)>);
22
23impl MessageSender {
24    pub fn new(sender: Sender<(WidgetId, Message)>) -> Self {
25        Self(sender)
26    }
27
28    pub fn write<T>(&self, id: WidgetId, message: T) -> bool
29    where
30        T: 'static + MessageData,
31    {
32        self.0.send((id, Box::new(message))).is_ok()
33    }
34
35    pub fn write_raw(&self, id: WidgetId, message: Message) -> bool {
36        self.0.send((id, message)).is_ok()
37    }
38
39    pub fn write_raw_all<I>(&self, messages: I)
40    where
41        I: IntoIterator<Item = (WidgetId, Message)>,
42    {
43        for data in messages {
44            let _ = self.0.send(data);
45        }
46    }
47}
48
49pub struct Messenger<'a> {
50    sender: MessageSender,
51    pub messages: &'a [Message],
52}
53
54impl<'a> Messenger<'a> {
55    pub fn new(sender: MessageSender, messages: &'a [Message]) -> Self {
56        Self { sender, messages }
57    }
58
59    pub fn write<T>(&self, id: WidgetId, message: T) -> bool
60    where
61        T: 'static + MessageData,
62    {
63        self.sender.write(id, message)
64    }
65
66    pub fn write_raw(&self, id: WidgetId, message: Message) -> bool {
67        self.sender.write_raw(id, message)
68    }
69
70    pub fn write_raw_all<I>(&self, messages: I)
71    where
72        I: IntoIterator<Item = (WidgetId, Message)>,
73    {
74        self.sender.write_raw_all(messages);
75    }
76}
77
78/// Macro for implementing [`MessageData`].
79///
80/// You may prefer to use the [derive macro][`macro@crate::MessageData`] instead, but in case of
81/// auto-implementing MessageData for remote or std types, this might be the macro you find useful.
82#[macro_export]
83macro_rules! implement_message_data {
84    ($type_name:ty) => {
85        impl $crate::messenger::MessageData for $type_name
86        where
87            Self: Clone,
88        {
89            fn clone_message(&self) -> Box<dyn $crate::messenger::MessageData> {
90                Box::new(self.clone())
91            }
92
93            fn as_any(&self) -> &dyn Any {
94                self
95            }
96        }
97    };
98}
99
100implement_message_data!(());
101implement_message_data!(i8);
102implement_message_data!(i16);
103implement_message_data!(i32);
104implement_message_data!(i64);
105implement_message_data!(i128);
106implement_message_data!(u8);
107implement_message_data!(u16);
108implement_message_data!(u32);
109implement_message_data!(u64);
110implement_message_data!(u128);
111implement_message_data!(f32);
112implement_message_data!(f64);
113implement_message_data!(bool);
114implement_message_data!(String);