Skip to content

Instantly share code, notes, and snippets.

@PsichiX
Created October 9, 2023 17:19
Show Gist options
  • Save PsichiX/0c7a99f80afd8827baeab42b968b206c to your computer and use it in GitHub Desktop.
Save PsichiX/0c7a99f80afd8827baeab42b968b206c to your computer and use it in GitHub Desktop.
View-Model usage test
const FOO_VIEW_MODEL: &str = "foo";
const COUNTER_PROPERTY: &str = "counter";
const FLAG_PROPERTY: &str = "flag";
// view-model data type
struct Foo {
// can hold view-model value wrapper that implicitly notifies on mutation.
counter: ViewModelValue<usize>,
// or can hold raw notifiers to explicitly notify.
flag: bool,
flag_notifier: ViewModelNotifier,
}
impl Foo {
fn toggle(&mut self) {
self.flag = !self.flag;
self.flag_notifier.notify();
}
}
#[test]
fn test_view_model() {
let a = WidgetId::from_str("a:root/a").unwrap();
let b = WidgetId::from_str("b:root/b").unwrap();
let mut collection = ViewModelCollection::default();
// create new view-model and add it to collection.
// `produce` method allows to setup notifiers as we construct view-model.
let mut view_model = ViewModel::produce(|properties| Foo {
counter: ViewModelValue::new(0, properties.notifier(COUNTER_PROPERTY)),
flag: false,
flag_notifier: properties.notifier(FLAG_PROPERTY),
});
// handle to view-model data we can use to share around.
// it stays alive as long as its view-model object.
let mut handle = view_model.lazy::<Foo>().unwrap();
collection.insert(FOO_VIEW_MODEL.to_owned(), view_model);
// unbound properties won't trigger notification until we bind widgets to them.
assert_eq!(collection.consume_notified_common_root().is_valid(), false);
handle.write().unwrap().toggle();
assert_eq!(collection.consume_notified_common_root().is_valid(), false);
assert!(collection
.get_mut(FOO_VIEW_MODEL)
.unwrap()
.properties
.bindings(COUNTER_PROPERTY)
.unwrap()
.is_notified());
assert!(collection
.get_mut(FOO_VIEW_MODEL)
.unwrap()
.properties
.bindings(FLAG_PROPERTY)
.unwrap()
.is_notified());
// bind widget to properties.
// whenever property gets notified, its widgets will rebuild.
collection
.get_mut(FOO_VIEW_MODEL)
.unwrap()
.properties
.bindings(COUNTER_PROPERTY)
.unwrap()
.bind(a);
collection
.get_mut(FOO_VIEW_MODEL)
.unwrap()
.properties
.bindings(FLAG_PROPERTY)
.unwrap()
.bind(b);
// once we bind properties, notification will be triggered.
assert_eq!(
collection.consume_notified_common_root().path(),
Some("root")
);
// automatically notify on view-model value mutation.
*handle.write().unwrap().counter += 1;
assert_eq!(
collection.consume_notified_common_root().path(),
Some("root/a"),
);
// proxy notify via view-model method call.
handle.write().unwrap().toggle();
assert_eq!(
collection.consume_notified_common_root().path(),
Some("root/b"),
);
// rebuilding widgets tree will occur always from common root of notified widgets.
*handle.write().unwrap().counter += 1;
handle.write().unwrap().toggle();
assert_eq!(
collection.consume_notified_common_root().path(),
Some("root"),
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment