#![allow(non_snake_case)]
use std::cell::{Ref, RefCell};
use event_rs::Event;
#[derive(Default)]
pub struct ObservableProperty<'a, T>
where
T: Eq + Default,
{
value: RefCell<T>,
pub PropertyChanged: Event<'a, ObservableProperty<'a, T>>,
pub PropertyChanging: Event<'a, ObservableProperty<'a, T>>,
}
impl<'a, T> ObservableProperty<'a, T>
where
T: Eq + Default,
{
pub fn new(value: T) -> Self {
Self {
value: value.into(),
..Default::default()
}
}
fn OnPropertyChanged(&self) {
self.PropertyChanged.invoke(self)
}
fn OnPropertyChanging(&self) {
self.PropertyChanging.invoke(self)
}
fn SetProperty(&self, value: T) -> bool {
if *self.value.borrow() == value {
return false;
}
self.OnPropertyChanging();
*self.value.borrow_mut() = value;
self.OnPropertyChanged();
true
}
pub fn GetValue(&self) -> Ref<'_, T> {
self.value.borrow()
}
pub fn SetValue(&self, value: T) -> bool {
self.SetProperty(value)
}
pub fn get(&self) -> T
where
T: Clone,
{
self.GetValue().clone()
}
pub fn set(&self, value: T) -> bool {
self.SetValue(value)
}
}
#[cfg(test)]
mod tests {
use std::cell::RefCell;
use super::*;
#[test]
fn test_observable_property() {
let counter = RefCell::new(0);
let prop = ObservableProperty::<i32>::default();
prop.PropertyChanging.add(|p| {
assert_eq!(p.get(), 0);
*counter.borrow_mut() += 1 << p.get();
});
prop.PropertyChanged.add(|p| {
assert_eq!(p.get(), 2);
*counter.borrow_mut() += 1 << p.get();
});
assert_eq!(prop.get(), 0);
prop.set(2);
assert_eq!(prop.get(), 2);
assert_eq!(*counter.borrow(), 0b101);
}
}