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 String,
84 Style,
85 Align,
86 Justify,
87 Anchors,
88 Layer,
89 Margins,
90 KeyboardFocus,
91 Option<Region>,
92 PathBuf,
93 Fit,
94 Option<usize>,
95 (u32, u32),
96 Adjust,
97 IconSource,
98 CaptureSource,
99 Vec<MenuEntry>,
100);
101
102impl IntoProp<String> for &str {
103 fn into_prop(self) -> Prop<String> {
104 Prop(PropKind::Value(self.to_owned()))
105 }
106}
107
108impl IntoProp<Option<Region>> for Region {
109 fn into_prop(self) -> Prop<Option<Region>> {
110 Prop(PropKind::Value(Some(self)))
111 }
112}
113
114impl IntoProp<Anchors> for Edge {
115 fn into_prop(self) -> Prop<Anchors> {
116 Prop(PropKind::Value(Anchors::from(self)))
117 }
118}
119
120impl IntoProp<IconSource> for &str {
122 fn into_prop(self) -> Prop<IconSource> {
123 Prop(PropKind::Value(IconSource::Name(self.to_owned())))
124 }
125}
126
127impl IntoProp<IconSource> for String {
129 fn into_prop(self) -> Prop<IconSource> {
130 Prop(PropKind::Value(IconSource::Name(self)))
131 }
132}
133
134impl IntoProp<PathBuf> for &Path {
135 fn into_prop(self) -> Prop<PathBuf> {
136 Prop(PropKind::Value(self.to_owned()))
137 }
138}
139
140impl IntoProp<PathBuf> for &str {
141 fn into_prop(self) -> Prop<PathBuf> {
142 Prop(PropKind::Value(PathBuf::from(self)))
143 }
144}
145
146impl IntoProp<PathBuf> for String {
147 fn into_prop(self) -> Prop<PathBuf> {
148 Prop(PropKind::Value(PathBuf::from(self)))
149 }
150}
151
152impl IntoProp<IconSource> for &Path {
154 fn into_prop(self) -> Prop<IconSource> {
155 Prop(PropKind::Value(IconSource::File(self.to_owned())))
156 }
157}
158
159impl IntoProp<IconSource> for PathBuf {
161 fn into_prop(self) -> Prop<IconSource> {
162 Prop(PropKind::Value(IconSource::File(self)))
163 }
164}