Skip to main content

ferroui_base/
i_support_initialize.rs

1use crate::styling::DuplicateSetterError;
2use crate::{ObjectType, Ref, StyledElement, Upcast};
3use std::rc::Rc;
4
5/// Why the initialization of an object could not be completed
6/// ([`ISupportInitialize::try_end_init`]): what `EndInit` throws in the
7/// managed original.
8#[derive(Clone, Debug, PartialEq, Eq)]
9pub enum InitializationError {
10    /// A style or control theme that applies to the element has two setters
11    /// for the same property (an invalid operation).
12    DuplicateSetter(DuplicateSetterError),
13}
14
15impl std::fmt::Display for InitializationError {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        match self {
18            Self::DuplicateSetter(error) => error.fmt(f),
19        }
20    }
21}
22
23impl std::error::Error for InitializationError {}
24
25impl From<DuplicateSetterError> for InitializationError {
26    fn from(error: DuplicateSetterError) -> Self {
27        Self::DuplicateSetter(error)
28    }
29}
30
31/// Specifies that an object supports a simple, transacted notification for
32/// batch initialization: the counterpart of the component model contract of
33/// the same name, which markup calls around the initialization of an
34/// object.
35pub trait ISupportInitialize {
36    /// Signals the object that initialization is starting.
37    fn begin_init(&self);
38
39    /// Signals the object that initialization is complete.
40    fn end_init(&self);
41
42    /// Signals the object that initialization is complete, reporting a
43    /// failure of the initialization (the exception `EndInit` raises in the
44    /// managed original) instead of panicking. Markup calls this form. By
45    /// default initialization cannot fail.
46    fn try_end_init(&self) -> Result<(), InitializationError> {
47        self.end_init();
48        Ok(())
49    }
50
51    /// The identity of the object, used for reference equality.
52    #[doc(hidden)]
53    fn reference_id(&self) -> *const () {
54        self as *const Self as *const ()
55    }
56}
57
58/// Handles compare by identity (reference equality): two handles are equal
59/// when they refer to the same object, whichever adapter they were made
60/// from.
61impl PartialEq for dyn ISupportInitialize {
62    #[inline]
63    fn eq(&self, other: &Self) -> bool {
64        self.reference_id() == other.reference_id()
65    }
66}
67
68/// Implements the contract for the styled element behind a class handle.
69struct StyledElementInitialize(Ref<StyledElement>);
70
71impl ISupportInitialize for StyledElementInitialize {
72    fn begin_init(&self) {
73        self.0.begin_init()
74    }
75
76    fn end_init(&self) {
77        self.0.end_init()
78    }
79
80    fn try_end_init(&self) -> Result<(), InitializationError> {
81        self.0.try_end_init()
82    }
83
84    fn reference_id(&self) -> *const () {
85        &*self.0 as *const StyledElement as *const ()
86    }
87}
88
89impl<T: ObjectType + Upcast<StyledElement>> From<Ref<T>> for Rc<dyn ISupportInitialize> {
90    fn from(value: Ref<T>) -> Self {
91        Rc::new(StyledElementInitialize(value.upcast()))
92    }
93}
94
95impl<T: ObjectType + Upcast<StyledElement>> From<&Ref<T>> for Rc<dyn ISupportInitialize> {
96    fn from(value: &Ref<T>) -> Self {
97        Rc::new(StyledElementInitialize(value.clone().upcast()))
98    }
99}