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