1use std::{fmt::Display, marker::PhantomData};
19
20use super::Reader;
21use crate::{
22 data::{DataMap, RwData},
23 text::{AlignCenter, AlignLeft, AlignRight, Builder, BuilderPart, Ghost, Spacer, Text},
24 ui::Ui,
25 widgets::Widget,
26};
27
28enum Appender<U: Ui, _T: Clone = (), D: Display + Send + Clone = String, W = ()> {
30 NoArgs(Box<dyn FnMut(&mut Builder) + Send + 'static>),
31 FromWidget(WidgetAreaFn<W, U>),
32 Part(BuilderPart<D, _T>),
33}
34
35pub struct State<U: Ui, _T: Clone = (), D: Display + Send + Clone = String, W: 'static = ()> {
45 appender: Appender<U, _T, D, W>,
46 checker: Option<Box<dyn Fn() -> bool + Send + Sync>>,
47 ghost: PhantomData<_T>,
48}
49
50impl<U, _T, D, W> State<U, _T, D, W>
51where
52 U: Ui,
53 _T: Send + Clone + 'static,
54 D: Display + Send + Clone + 'static,
55 W: 'static,
56{
57 pub fn fns(self) -> (ReaderFn<U>, Box<dyn Fn() -> bool + Send + Sync>) {
58 (
59 match self.appender {
60 Appender::NoArgs(mut f) => Box::new(move |b, _| f(b)),
61 Appender::FromWidget(mut f) => Box::new(move |b, reader| {
62 reader.inspect_related(|w, a| f(b, w, a));
63 }),
64 Appender::Part(builder_part) => Box::new(move |b, _| b.push(builder_part.clone())),
65 },
66 Box::new(move || self.checker.as_ref().is_some_and(|check| check())),
67 )
68 }
69}
70
71impl<D: Display + Send + Clone + 'static, U: Ui> From<D> for State<U, D, D> {
72 fn from(value: D) -> Self {
73 Self {
74 appender: Appender::Part(BuilderPart::from(value)),
75 checker: None,
76 ghost: PhantomData,
77 }
78 }
79}
80
81impl<U: Ui> From<Text> for State<U, Text> {
82 fn from(value: Text) -> Self {
83 Self {
84 appender: Appender::Part(BuilderPart::from(value)),
85 checker: None,
86 ghost: PhantomData,
87 }
88 }
89}
90
91impl<D: Display + Send + Clone, U: Ui> From<RwData<D>> for State<U, DataArg<D>> {
92 fn from(value: RwData<D>) -> Self {
93 Self {
94 appender: Appender::NoArgs({
95 let value = value.clone();
96 Box::new(move |b| b.push(value.read().clone()))
97 }),
98 checker: Some(Box::new(value.checker())),
99 ghost: PhantomData,
100 }
101 }
102}
103
104impl<U: Ui> From<RwData<Text>> for State<U, DataArg<Text>> {
105 fn from(value: RwData<Text>) -> Self {
106 Self {
107 appender: Appender::NoArgs({
108 let value = value.clone();
109 Box::new(move |b| b.push(value.read().clone()))
110 }),
111 checker: Some(Box::new(value.checker())),
112 ghost: PhantomData,
113 }
114 }
115}
116
117impl<U, I, O> From<DataMap<I, O>> for State<U, DataArg<String>>
118where
119 U: Ui,
120 I: ?Sized + Send,
121 O: Display + 'static,
122{
123 fn from(value: DataMap<I, O>) -> Self {
124 let (mut reader, checker) = value.fns();
125 State {
126 appender: Appender::NoArgs(Box::new(move |b| b.push(reader()))),
127 checker: Some(checker),
128 ghost: PhantomData,
129 }
130 }
131}
132
133impl<U: Ui, I: ?Sized + Send> From<DataMap<I, Text>> for State<U, DataArg<Text>> {
134 fn from(value: DataMap<I, Text>) -> Self {
135 let (mut reader, checker) = value.fns();
136 State {
137 appender: Appender::NoArgs(Box::new(move |b| b.push(reader()))),
138 checker: Some(checker),
139 ghost: PhantomData,
140 }
141 }
142}
143
144impl<U, F, I, O> From<F> for State<U, IntoDataArg<String>>
145where
146 U: Ui,
147 F: FnOnce() -> DataMap<I, O>,
148 I: ?Sized + Send + 'static,
149 O: Display + 'static,
150{
151 fn from(value: F) -> Self {
152 let (mut reader, checker) = value().fns();
153 State {
154 appender: Appender::NoArgs(Box::new(move |b| b.push(reader()))),
155 checker: Some(checker),
156 ghost: PhantomData,
157 }
158 }
159}
160
161impl<U, F, I> From<F> for State<U, IntoDataArg<Text>>
162where
163 U: Ui,
164 F: FnOnce() -> DataMap<I, Text>,
165 I: ?Sized + Send + 'static,
166{
167 fn from(value: F) -> Self {
168 let (mut reader, checker) = value().fns();
169 State {
170 appender: Appender::NoArgs(Box::new(move |b| b.push(reader()))),
171 checker: Some(checker),
172 ghost: PhantomData,
173 }
174 }
175}
176
177impl<D, Reader, Checker, U> From<(Reader, Checker)> for State<U, NoArg<String>>
178where
179 D: Display,
180 Reader: Fn() -> D + Send + 'static,
181 Checker: Fn() -> bool + Send + Sync + 'static,
182 U: Ui,
183{
184 fn from((reader, checker): (Reader, Checker)) -> Self {
185 State {
186 appender: Appender::NoArgs(Box::new(move |b| b.push(reader()))),
187 checker: Some(Box::new(checker)),
188 ghost: PhantomData,
189 }
190 }
191}
192
193impl<Reader, Checker, U> From<(Reader, Checker)> for State<U, NoArg<Text>>
194where
195 Reader: Fn() -> Text + Send + 'static,
196 Checker: Fn() -> bool + Send + Sync + 'static,
197 U: Ui,
198{
199 fn from((reader, checker): (Reader, Checker)) -> Self {
200 State {
201 appender: Appender::NoArgs(Box::new(move |b| b.push(reader()))),
202 checker: Some(Box::new(checker)),
203 ghost: PhantomData,
204 }
205 }
206}
207
208impl<D, W, ReadFn, U> From<ReadFn> for State<U, WidgetArg<String>, String, W>
209where
210 D: Display + Send + 'static,
211 W: Widget<U> + Sized,
212 ReadFn: Fn(&W) -> D + Send + 'static,
213 U: Ui,
214{
215 fn from(value: ReadFn) -> Self {
216 State {
217 appender: Appender::FromWidget(Box::new(move |b, widget, _| b.push(value(widget)))),
218 checker: None,
219 ghost: PhantomData,
220 }
221 }
222}
223
224impl<W, ReadFn, U> From<ReadFn> for State<U, WidgetArg<Text>, String, W>
225where
226 W: Widget<U> + Sized,
227 ReadFn: Fn(&W) -> Text + Send + 'static,
228 U: Ui,
229{
230 fn from(value: ReadFn) -> Self {
231 State {
232 appender: Appender::FromWidget(Box::new(move |b, widget, _| b.push(value(widget)))),
233 checker: None,
234 ghost: PhantomData,
235 }
236 }
237}
238
239impl<D, W, ReadFn, U> From<ReadFn> for State<U, WidgetAreaArg<String>, String, W>
240where
241 D: Display + Send + 'static,
242 W: Widget<U> + Sized,
243 ReadFn: Fn(&W, &U::Area) -> D + Send + 'static,
244 U: Ui,
245{
246 fn from(value: ReadFn) -> Self {
247 State {
248 appender: Appender::FromWidget(Box::new(move |b, widget, area| {
249 b.push(value(widget, area))
250 })),
251 checker: None,
252 ghost: PhantomData,
253 }
254 }
255}
256
257impl<W, ReadFn, U> From<ReadFn> for State<U, WidgetAreaArg<Text>, String, W>
258where
259 W: Widget<U> + Sized,
260 ReadFn: Fn(&W, &U::Area) -> Text + Send + 'static,
261 U: Ui,
262{
263 fn from(value: ReadFn) -> Self {
264 State {
265 appender: Appender::FromWidget(Box::new(move |b, widget, area| {
266 b.push(value(widget, area))
267 })),
268 checker: None,
269 ghost: PhantomData,
270 }
271 }
272}
273
274impl<U: Ui> From<AlignLeft> for State<U, AlignLeft> {
275 fn from(_: AlignLeft) -> Self {
276 Self {
277 appender: Appender::Part(BuilderPart::AlignLeft),
278 checker: None,
279 ghost: PhantomData,
280 }
281 }
282}
283
284impl<U: Ui> From<AlignCenter> for State<U, AlignCenter> {
285 fn from(_: AlignCenter) -> Self {
286 Self {
287 appender: Appender::Part(BuilderPart::AlignCenter),
288 checker: None,
289 ghost: PhantomData,
290 }
291 }
292}
293
294impl<U: Ui> From<AlignRight> for State<U, AlignRight> {
295 fn from(_: AlignRight) -> Self {
296 Self {
297 appender: Appender::Part(BuilderPart::AlignRight),
298 checker: None,
299 ghost: PhantomData,
300 }
301 }
302}
303
304impl<U: Ui> From<Spacer> for State<U, Spacer> {
305 fn from(_: Spacer) -> Self {
306 Self {
307 appender: Appender::Part(BuilderPart::from(Spacer)),
308 checker: None,
309 ghost: PhantomData,
310 }
311 }
312}
313
314impl<U: Ui> From<Ghost> for State<U, Ghost> {
315 fn from(value: Ghost) -> Self {
316 Self {
317 appender: Appender::Part(BuilderPart::from(value)),
318 checker: None,
319 ghost: PhantomData,
320 }
321 }
322}
323
324#[doc(hidden)]
326#[derive(Clone)]
327pub struct DataArg<T>(PhantomData<T>);
328#[doc(hidden)]
329#[derive(Clone)]
330pub struct IntoDataArg<T>(PhantomData<T>);
331#[doc(hidden)]
332#[derive(Clone)]
333pub struct NoArg<T>(PhantomData<T>);
334#[doc(hidden)]
335#[derive(Clone)]
336pub struct WidgetArg<W>(PhantomData<W>);
337#[doc(hidden)]
338#[derive(Clone)]
339pub struct WidgetAreaArg<W>(PhantomData<W>);
340
341type WidgetAreaFn<W, U> = Box<dyn FnMut(&mut Builder, &W, &<U as Ui>::Area) + Send + 'static>;
343type ReaderFn<U> = Box<dyn FnMut(&mut Builder, &mut Reader<U>) + Send>;