1use std::{
2 fmt::Debug,
3 ops::{Deref, DerefMut},
4};
5
6#[cfg(feature = "primitive")]
7use inherit_methods_macro::inherit_methods;
8use smallvec::SmallVec;
9#[cfg(feature = "handle")]
10use winio_handle::{
11 AsContainer, AsWidget, AsWindow, BorrowedContainer, BorrowedWidget, BorrowedWindow,
12};
13#[cfg(feature = "primitive")]
14use winio_primitive::{Failable, Layoutable, Point, Rect, Size};
15
16use super::ComponentMessage;
17use crate::{BoxComponent, Component, ComponentSender, Root};
18
19pub struct Child<T: Component> {
22 model: T,
23 sender: ComponentSender<T>,
24 msg_cache: SmallVec<[T::Message; 1]>,
25}
26
27impl<T: Component> Child<T> {
28 pub async fn init<'a>(init: impl Into<T::Init<'a>>) -> Result<Self, T::Error> {
30 let sender = ComponentSender::new();
31 let model = T::init(init.into(), &sender).await?;
32 Ok(Self::new(model, sender))
33 }
34
35 pub(crate) fn new(model: T, sender: ComponentSender<T>) -> Self {
36 Self {
37 model,
38 sender,
39 msg_cache: SmallVec::new(),
40 }
41 }
42
43 pub async fn start<C: Component>(
83 &mut self,
84 sender: &ComponentSender<C>,
85 mut f: impl FnMut(T::Event) -> Option<C::Message>,
86 mut propagate: impl FnMut() -> C::Message,
87 ) -> ! {
88 let fut_start = self.model.start(&self.sender);
89 let fut_forward = async {
90 loop {
91 self.sender.wait().await;
92 for msg in self.sender.fetch_all() {
93 match msg {
94 ComponentMessage::Message(msg) => {
95 self.msg_cache.push(msg);
96 sender.post(propagate());
97 }
98 ComponentMessage::Event(e) => {
99 if let Some(m) = f(e) {
100 sender.post(m);
101 }
102 }
103 }
104 }
105 }
106 };
107 futures_util::future::join(fut_start, fut_forward).await.0
108 }
109
110 pub fn post(&mut self, message: T::Message) {
112 self.sender.post(message);
113 }
114
115 pub async fn emit(&mut self, message: T::Message) -> Result<bool, T::Error> {
117 self.model.update(message, &self.sender).await
118 }
119
120 pub async fn update(&mut self) -> Result<bool, T::Error> {
122 let mut need_render = self.model.update_children().await?;
123 for message in self.msg_cache.drain(..) {
124 need_render |= self.model.update(message, &self.sender).await?;
125 }
126 Ok(need_render)
127 }
128
129 pub fn render(&mut self) -> Result<(), T::Error> {
131 self.model.render(&self.sender)?;
132 self.model.render_children()
133 }
134
135 pub fn sender(&self) -> &ComponentSender<T> {
137 &self.sender
138 }
139
140 pub async fn try_into_root(mut self) -> Result<Root<T>, T::Error> {
145 if self.update().await? {
146 self.render()?;
147 }
148 Ok(Root::new(self.model, self.sender))
149 }
150}
151
152impl<T: Component + 'static> Child<T> {
153 pub fn into_boxed(self) -> Child<BoxComponent<T::Message, T::Event, T::Error>> {
155 let sender = ComponentSender(self.sender.0);
156 Child {
157 model: BoxComponent::new(self.model),
158 sender,
159 msg_cache: self.msg_cache,
160 }
161 }
162}
163
164impl<T: Component> Deref for Child<T> {
165 type Target = T;
166
167 fn deref(&self) -> &Self::Target {
168 &self.model
169 }
170}
171
172impl<T: Component> DerefMut for Child<T> {
173 fn deref_mut(&mut self) -> &mut Self::Target {
174 &mut self.model
175 }
176}
177
178#[cfg(feature = "handle")]
179impl<T: AsWindow + Component> AsWindow for Child<T> {
180 fn as_window(&self) -> BorrowedWindow<'_> {
181 self.model.as_window()
182 }
183}
184
185#[cfg(feature = "handle")]
186impl<T: AsWidget + Component> AsWidget for Child<T> {
187 fn as_widget(&self) -> BorrowedWidget<'_> {
188 self.model.as_widget()
189 }
190}
191
192#[cfg(feature = "handle")]
193impl<T: AsContainer + Component> AsContainer for Child<T> {
194 fn as_container(&self) -> BorrowedContainer<'_> {
195 self.model.as_container()
196 }
197}
198
199impl<T: Component + Debug> Debug for Child<T> {
200 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
201 f.debug_struct("Child").field("model", &self.model).finish()
202 }
203}
204
205#[cfg(feature = "primitive")]
206impl<T: Component + Failable> Failable for Child<T> {
207 type Error = <T as Failable>::Error;
208}
209
210#[cfg(feature = "primitive")]
211#[inherit_methods(from = "self.model")]
212impl<T: Component + Layoutable> Layoutable for Child<T> {
213 fn loc(&self) -> Result<Point, Self::Error>;
214
215 fn set_loc(&mut self, p: Point) -> Result<(), Self::Error>;
216
217 fn size(&self) -> Result<Size, Self::Error>;
218
219 fn set_size(&mut self, s: Size) -> Result<(), Self::Error>;
220
221 fn rect(&self) -> Result<Rect, Self::Error>;
222
223 fn set_rect(&mut self, r: Rect) -> Result<(), Self::Error>;
224
225 fn preferred_size(&self) -> Result<Size, Self::Error>;
226
227 fn min_size(&self) -> Result<Size, Self::Error>;
228}