1use std::cell::RefCell;
4use std::path::{Path, PathBuf};
5use std::rc::Rc;
6
7use crate::menu::MenuEntry;
8use crate::popup::Adjust;
9use crate::region::Region;
10use crate::screencopy::CaptureSource;
11use crate::style::Style;
12use crate::widgets::{Align, Fit, IconSource, Justify};
13use crate::window::{Anchors, Edge, KeyboardFocus, Layer, Margins};
14
15pub struct Prop<T>(pub(crate) PropKind<T>);
21
22impl<T: Clone + 'static> Prop<T> {
23 pub fn shared(self) -> Rc<dyn Fn() -> T> {
28 match self.0 {
29 PropKind::Value(value) => Rc::new(move || value.clone()),
30 PropKind::Binding(compute) => {
31 let compute = RefCell::new(compute);
32 Rc::new(move || (compute.borrow_mut())())
33 }
34 }
35 }
36}
37
38pub(crate) enum PropKind<T> {
39 Value(T),
40 Binding(Box<dyn FnMut() -> T>),
41}
42
43pub trait IntoProp<T> {
51 fn into_prop(self) -> Prop<T>;
53}
54
55impl<T, F> IntoProp<T> for F
58where
59 F: FnMut() -> T + 'static,
60{
61 fn into_prop(self) -> Prop<T> {
62 Prop(PropKind::Binding(Box::new(self)))
63 }
64}
65
66macro_rules! value_props {
68 ($($ty:ty),* $(,)?) => {
69 $(
70 impl IntoProp<$ty> for $ty {
71 fn into_prop(self) -> Prop<$ty> {
72 Prop(PropKind::Value(self))
73 }
74 }
75 )*
76 };
77}
78
79value_props!(
80 bool,
81 u32,
82 i32,
83 f32,
84 String,
85 Style,
86 Align,
87 Justify,
88 Anchors,
89 Layer,
90 Margins,
91 KeyboardFocus,
92 Option<Region>,
93 PathBuf,
94 Fit,
95 Option<usize>,
96 (u32, u32),
97 Adjust,
98 IconSource,
99 CaptureSource,
100 Vec<MenuEntry>,
101);
102
103impl IntoProp<String> for &str {
104 fn into_prop(self) -> Prop<String> {
105 Prop(PropKind::Value(self.to_owned()))
106 }
107}
108
109impl IntoProp<Option<Region>> for Region {
110 fn into_prop(self) -> Prop<Option<Region>> {
111 Prop(PropKind::Value(Some(self)))
112 }
113}
114
115impl IntoProp<Anchors> for Edge {
116 fn into_prop(self) -> Prop<Anchors> {
117 Prop(PropKind::Value(Anchors::from(self)))
118 }
119}
120
121impl IntoProp<IconSource> for &str {
123 fn into_prop(self) -> Prop<IconSource> {
124 Prop(PropKind::Value(IconSource::Name(self.to_owned())))
125 }
126}
127
128impl IntoProp<IconSource> for String {
130 fn into_prop(self) -> Prop<IconSource> {
131 Prop(PropKind::Value(IconSource::Name(self)))
132 }
133}
134
135impl IntoProp<PathBuf> for &Path {
136 fn into_prop(self) -> Prop<PathBuf> {
137 Prop(PropKind::Value(self.to_owned()))
138 }
139}
140
141impl IntoProp<PathBuf> for &str {
142 fn into_prop(self) -> Prop<PathBuf> {
143 Prop(PropKind::Value(PathBuf::from(self)))
144 }
145}
146
147impl IntoProp<PathBuf> for String {
148 fn into_prop(self) -> Prop<PathBuf> {
149 Prop(PropKind::Value(PathBuf::from(self)))
150 }
151}
152
153impl IntoProp<IconSource> for &Path {
155 fn into_prop(self) -> Prop<IconSource> {
156 Prop(PropKind::Value(IconSource::File(self.to_owned())))
157 }
158}
159
160impl IntoProp<IconSource> for PathBuf {
162 fn into_prop(self) -> Prop<IconSource> {
163 Prop(PropKind::Value(IconSource::File(self)))
164 }
165}