1use std::cell::RefCell;
4use std::path::{Path, PathBuf};
5use std::rc::Rc;
6
7use crate::menu::MenuEntry;
8use crate::style::Style;
9use crate::widgets::{Align, IconSource, Justify};
10use crate::window::{Anchors, Edge, Layer};
11
12pub struct Prop<T>(pub(crate) PropKind<T>);
18
19impl<T: Clone + 'static> Prop<T> {
20 pub fn shared(self) -> Rc<dyn Fn() -> T> {
25 match self.0 {
26 PropKind::Value(value) => Rc::new(move || value.clone()),
27 PropKind::Binding(compute) => {
28 let compute = RefCell::new(compute);
29 Rc::new(move || (compute.borrow_mut())())
30 }
31 }
32 }
33}
34
35pub(crate) enum PropKind<T> {
36 Value(T),
37 Binding(Box<dyn FnMut() -> T>),
38}
39
40pub trait IntoProp<T> {
48 fn into_prop(self) -> Prop<T>;
50}
51
52impl<T, F> IntoProp<T> for F
55where
56 F: FnMut() -> T + 'static,
57{
58 fn into_prop(self) -> Prop<T> {
59 Prop(PropKind::Binding(Box::new(self)))
60 }
61}
62
63macro_rules! value_props {
65 ($($ty:ty),* $(,)?) => {
66 $(
67 impl IntoProp<$ty> for $ty {
68 fn into_prop(self) -> Prop<$ty> {
69 Prop(PropKind::Value(self))
70 }
71 }
72 )*
73 };
74}
75
76value_props!(
77 bool,
78 u32,
79 i32,
80 String,
81 Style,
82 Align,
83 Justify,
84 Anchors,
85 Layer,
86 IconSource,
87 Vec<MenuEntry>,
88);
89
90impl IntoProp<String> for &str {
91 fn into_prop(self) -> Prop<String> {
92 Prop(PropKind::Value(self.to_owned()))
93 }
94}
95
96impl IntoProp<Anchors> for Edge {
97 fn into_prop(self) -> Prop<Anchors> {
98 Prop(PropKind::Value(Anchors::from(self)))
99 }
100}
101
102impl IntoProp<IconSource> for &str {
104 fn into_prop(self) -> Prop<IconSource> {
105 Prop(PropKind::Value(IconSource::Name(self.to_owned())))
106 }
107}
108
109impl IntoProp<IconSource> for String {
111 fn into_prop(self) -> Prop<IconSource> {
112 Prop(PropKind::Value(IconSource::Name(self)))
113 }
114}
115
116impl IntoProp<IconSource> for &Path {
118 fn into_prop(self) -> Prop<IconSource> {
119 Prop(PropKind::Value(IconSource::File(self.to_owned())))
120 }
121}
122
123impl IntoProp<IconSource> for PathBuf {
125 fn into_prop(self) -> Prop<IconSource> {
126 Prop(PropKind::Value(IconSource::File(self)))
127 }
128}