Skip to main content

ferroui_base/data/core/plugins/
data_validation_base.rs

1use super::{AccessorListener, IPropertyAccessor, PropertyAccessorBase};
2use crate::data::BindingNotification;
3use crate::BoxedValue;
4use std::rc::Rc;
5
6/// The state shared by data validators: property accessors returned from an
7/// [`IDataValidationPlugin`](super::IDataValidationPlugin) that wrap an inner
8/// accessor and convert the values received from it into
9/// [`BindingNotification`]s.
10pub struct DataValidationBase {
11    pub base: PropertyAccessorBase,
12    pub inner: Rc<dyn IPropertyAccessor>,
13}
14
15impl DataValidationBase {
16    pub fn new(inner: Rc<dyn IPropertyAccessor>) -> Self {
17        Self { base: PropertyAccessorBase::new(), inner }
18    }
19
20    /// Begins listening to the inner accessor.
21    pub fn subscribe_core(&self, inner_value_changed: AccessorListener) {
22        self.inner.subscribe(inner_value_changed);
23    }
24
25    /// Stops listening to the inner accessor.
26    pub fn unsubscribe_core(&self) {
27        self.inner.dispose();
28    }
29
30    /// The default handling of a value from the inner accessor: wraps it in a
31    /// notification unless it already is one, and publishes it.
32    pub fn inner_value_changed(&self, value: Option<BoxedValue>) {
33        let notification = wrap_notification(value);
34        self.base.publish_value(Some(notification));
35    }
36}
37
38/// Wraps a value into a boxed notification unless it already is one.
39pub(crate) fn wrap_notification(value: Option<BoxedValue>) -> BoxedValue {
40    match value {
41        Some(v) if v.is::<BindingNotification>() => v,
42        other => Rc::new(BindingNotification::new(other)),
43    }
44}