use std::cell::RefCell;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use crate::menu::MenuEntry;
use crate::popup::Adjust;
use crate::region::Region;
use crate::screencopy::CaptureSource;
use crate::style::Style;
use crate::widgets::{Align, Fit, IconSource, Justify};
use crate::window::{Anchors, Edge, KeyboardFocus, Layer, Margins};
pub struct Prop<T>(pub(crate) PropKind<T>);
impl<T: Clone + 'static> Prop<T> {
pub fn shared(self) -> Rc<dyn Fn() -> T> {
match self.0 {
PropKind::Value(value) => Rc::new(move || value.clone()),
PropKind::Binding(compute) => {
let compute = RefCell::new(compute);
Rc::new(move || (compute.borrow_mut())())
}
}
}
}
pub(crate) enum PropKind<T> {
Value(T),
Binding(Box<dyn FnMut() -> T>),
}
pub trait IntoProp<T> {
fn into_prop(self) -> Prop<T>;
}
impl<T, F> IntoProp<T> for F
where
F: FnMut() -> T + 'static,
{
fn into_prop(self) -> Prop<T> {
Prop(PropKind::Binding(Box::new(self)))
}
}
macro_rules! value_props {
($($ty:ty),* $(,)?) => {
$(
impl IntoProp<$ty> for $ty {
fn into_prop(self) -> Prop<$ty> {
Prop(PropKind::Value(self))
}
}
)*
};
}
value_props!(
bool,
u32,
i32,
f32,
String,
Style,
Align,
Justify,
Anchors,
Layer,
Margins,
KeyboardFocus,
Option<Region>,
PathBuf,
Fit,
Option<usize>,
(u32, u32),
Adjust,
IconSource,
CaptureSource,
Vec<MenuEntry>,
);
impl IntoProp<String> for &str {
fn into_prop(self) -> Prop<String> {
Prop(PropKind::Value(self.to_owned()))
}
}
impl IntoProp<Option<Region>> for Region {
fn into_prop(self) -> Prop<Option<Region>> {
Prop(PropKind::Value(Some(self)))
}
}
impl IntoProp<Anchors> for Edge {
fn into_prop(self) -> Prop<Anchors> {
Prop(PropKind::Value(Anchors::from(self)))
}
}
impl IntoProp<IconSource> for &str {
fn into_prop(self) -> Prop<IconSource> {
Prop(PropKind::Value(IconSource::Name(self.to_owned())))
}
}
impl IntoProp<IconSource> for String {
fn into_prop(self) -> Prop<IconSource> {
Prop(PropKind::Value(IconSource::Name(self)))
}
}
impl IntoProp<PathBuf> for &Path {
fn into_prop(self) -> Prop<PathBuf> {
Prop(PropKind::Value(self.to_owned()))
}
}
impl IntoProp<PathBuf> for &str {
fn into_prop(self) -> Prop<PathBuf> {
Prop(PropKind::Value(PathBuf::from(self)))
}
}
impl IntoProp<PathBuf> for String {
fn into_prop(self) -> Prop<PathBuf> {
Prop(PropKind::Value(PathBuf::from(self)))
}
}
impl IntoProp<IconSource> for &Path {
fn into_prop(self) -> Prop<IconSource> {
Prop(PropKind::Value(IconSource::File(self.to_owned())))
}
}
impl IntoProp<IconSource> for PathBuf {
fn into_prop(self) -> Prop<IconSource> {
Prop(PropKind::Value(IconSource::File(self)))
}
}