Skip to main content

ferroui_xaml_interactivity/triggers/
disposing_trigger.rs

1//! Port of `Triggers/DisposingTrigger.cs` (`DisposingTrigger<T>`).
2
3use crate::{StyledElementBehaviorImpl, StyledElementBehaviorImplExt, StyledElementTriggerOfT};
4use ferroui_base::reactive::IDisposable;
5use ferroui_base::{ferro_class, FerroObjectImpl, StyledElementImpl, TypeInfo};
6use std::cell::RefCell;
7use std::rc::Rc;
8
9/// A base class for triggers that require a disposable resource: the resource
10/// [`on_attached_override`](DisposingTriggerImpl::on_attached_override) creates is disposed when
11/// the trigger is detached.
12///
13/// The class is abstract. The type argument `T` of the reference is the runtime type passed to
14/// [`construct`](Self::construct) (see [`BehaviorOfT`](crate::BehaviorOfT)).
15#[repr(C)]
16pub struct DisposingTrigger {
17    base: StyledElementTriggerOfT,
18    disposable: RefCell<Option<Rc<dyn IDisposable>>>,
19}
20
21ferro_class! {
22    DisposingTrigger: StyledElementTriggerOfT, virtuals DisposingTriggerImpl: StyledElementBehaviorImpl {
23        /// Called after the trigger is attached to the associated object.
24        ///
25        /// Returns a disposable resource to be disposed when the trigger is detached.
26        fn on_attached_override(this) -> Rc<dyn IDisposable>;
27    }
28}
29
30ferroui_base::ferro_impl_classes!(DisposingTrigger: FerroObjectImpl, StyledElementImpl);
31
32impl DisposingTriggerImpl for DisposingTrigger {
33    fn on_attached_override(_this: &Self) -> Rc<dyn IDisposable> {
34        panic!("DisposingTrigger is abstract: 'on_attached_override' must be implemented by the deriving class")
35    }
36}
37
38ferroui_base::ferro_overrides! {
39    impl StyledElementBehaviorImpl for DisposingTrigger {
40        fn on_attached(this: &Self) {
41            Self::parent_on_attached(this);
42
43            let previous = this.disposable.borrow_mut().take();
44            if let Some(previous) = previous {
45                previous.dispose();
46            }
47            let disposable = this.on_attached_override();
48            *this.disposable.borrow_mut() = Some(disposable);
49        }
50
51        fn on_detaching(this: &Self) {
52            Self::parent_on_detaching(this);
53
54            let disposable = this.disposable.borrow().clone();
55            if let Some(disposable) = disposable {
56                disposable.dispose();
57            }
58        }
59    }
60}
61
62impl DisposingTrigger {
63    /// Creates the class data for triggers attached to objects of `associated_type`; see
64    /// [`ferroui_base::FerroObject::construct`].
65    pub fn construct(associated_type: &'static TypeInfo) -> Self {
66        Self { base: StyledElementTriggerOfT::construct(associated_type), disposable: RefCell::new(None) }
67    }
68}