Skip to main content

ferroui_base/data/
binding_expression_base.rs

1use crate::data::core::SinkRef;
2use crate::data::BindingPriority;
3use crate::property_store::{ImmediateValueFrame, IValueEntry};
4use crate::reactive::IDisposable;
5use crate::{FerroObject, FerroProperty};
6use std::any::Any;
7use std::rc::Weak;
8
9/// The base of binding expressions: an instantiated binding on a target
10/// object. It is also the value entry through which the target's value store
11/// reads the binding's value.
12#[allow(private_bounds, private_interfaces)]
13pub trait BindingExpressionBase: IDisposable + IValueEntry + Any {
14    /// The priority of the binding expression.
15    fn priority(&self) -> BindingPriority;
16
17    /// The property that the binding expression is targeting.
18    fn target_property(&self) -> Option<&'static FerroProperty>;
19
20    /// The preferred priority of the binding expression; the priority passed
21    /// to [`attach`](Self::attach) may differ if the binding targets a direct
22    /// property, in which case it is elevated to local value priority.
23    fn default_priority(&self) -> BindingPriority;
24
25    /// Whether data validation is enabled for the binding expression.
26    fn is_data_validation_enabled(&self) -> bool;
27
28    /// Sends the current binding target value to the binding source property
29    /// in two-way or one-way-to-source bindings. Does nothing for other
30    /// modes. If the update source trigger of the binding is explicit, this
31    /// must be called for changes to propagate back to the source.
32    fn update_source(&self) {}
33
34    /// Forces a data transfer from the binding source to the binding target.
35    fn update_target(&self) {}
36
37    /// Attaches the binding expression to a sink but does not start it.
38    #[doc(hidden)]
39    fn attach(
40        &self,
41        sink: SinkRef,
42        frame: Option<Weak<ImmediateValueFrame>>,
43        target: &FerroObject,
44        target_property: &'static FerroProperty,
45        priority: BindingPriority,
46    );
47
48    /// Starts the binding expression. `produce_value` indicates whether it
49    /// should produce an initial value.
50    #[doc(hidden)]
51    fn start(&self, produce_value: bool);
52
53    /// The expression as an untyped binding expression, if it is one.
54    #[doc(hidden)]
55    fn as_untyped(&self) -> Option<&dyn crate::data::core::UntypedBindingExpression> {
56        None
57    }
58
59    /// Whether this expression can participate in a synchronous reload transaction.
60    #[cfg(all(debug_assertions, feature = "hot-reload"))]
61    #[doc(hidden)]
62    fn can_pause_for_reload(&self) -> bool {
63        false
64    }
65
66    /// Suppresses target publication and target-to-source writes without stopping
67    /// source subscriptions. Returns false for unsupported or already paused bindings.
68    #[cfg(all(debug_assertions, feature = "hot-reload"))]
69    #[doc(hidden)]
70    fn pause_for_reload(&self) -> bool {
71        false
72    }
73
74    /// Publishes source changes received while paused, then resumes ordinary writes.
75    #[cfg(all(debug_assertions, feature = "hot-reload"))]
76    #[doc(hidden)]
77    fn resume_after_reload(&self) {}
78
79    fn as_any(&self) -> &dyn Any;
80}
81
82/// Handles compare by identity (reference equality), so that the expression
83/// a binding returns can be held in untyped values.
84impl PartialEq for dyn BindingExpressionBase {
85    #[inline]
86    fn eq(&self, other: &Self) -> bool {
87        std::ptr::addr_eq(self as *const Self, other as *const Self)
88    }
89}