ferroui_base/data/core/plugins/
exception_validation_plugin.rs1use super::{AccessorListener, DataValidationBase, IDataValidationPlugin, IPropertyAccessor};
2use crate::data::core::{ValueType, WeakValue};
3use crate::data::{BindingError, BindingErrorType, BindingNotification, BindingPriority};
4use crate::reactive::IDisposable;
5use crate::BoxedValue;
6use std::rc::{Rc, Weak};
7
8pub struct ExceptionValidationPlugin;
10
11impl IDataValidationPlugin for ExceptionValidationPlugin {
12 fn match_(&self, _reference: &WeakValue, _member_name: &str) -> bool {
13 true
14 }
15
16 fn start(
17 &self,
18 _reference: &WeakValue,
19 _property_name: &str,
20 inner: Rc<dyn IPropertyAccessor>,
21 ) -> Rc<dyn IPropertyAccessor> {
22 Rc::new_cyclic(|this| Validator { this: this.clone(), validation: DataValidationBase::new(inner) })
23 }
24}
25
26struct Validator {
27 this: Weak<Validator>,
28 validation: DataValidationBase,
29}
30
31impl IDisposable for Validator {
32 fn dispose(&self) {
33 if self.validation.base.is_subscribed() {
34 self.unsubscribe();
35 }
36 }
37}
38
39impl IPropertyAccessor for Validator {
40 fn property_type(&self) -> Option<ValueType> {
41 self.validation.inner.property_type()
42 }
43
44 fn value(&self) -> Option<BoxedValue> {
45 self.validation.inner.value()
46 }
47
48 fn set_value(&self, value: Option<&BoxedValue>, priority: BindingPriority) -> Result<bool, BindingError> {
49 match self.validation.inner.set_value(value, priority) {
50 Ok(result) => Ok(result),
51 Err(error) => {
52 self.validation.base.publish_value(Some(Rc::new(BindingNotification::with_error(
53 error,
54 BindingErrorType::DataValidationError,
55 ))));
56 Ok(false)
57 }
58 }
59 }
60
61 fn subscribe(&self, listener: AccessorListener) {
62 self.validation.base.set_listener(listener);
63 let weak = self.this.clone();
64 self.validation.subscribe_core(Rc::new(move |value| {
65 if let Some(this) = weak.upgrade() {
66 this.validation.inner_value_changed(value);
67 }
68 }));
69 }
70
71 fn unsubscribe(&self) {
72 self.validation.unsubscribe_core();
73 self.validation.base.clear_listener();
74 }
75}