Skip to main content

ferroui_controls/flyouts/
flyout.rs

1use super::{
2    FlyoutBaseImpl, FlyoutPresenter, PopupFlyoutBase, PopupFlyoutBaseImpl, PopupFlyoutBaseImplExt,
3};
4use crate::templates::IDataTemplate;
5use crate::{ContentControl, Control};
6use ferroui_base::controls::Classes;
7use ferroui_base::styling::ControlTheme;
8use ferroui_base::utilities::CancelEventArgs;
9use ferroui_base::{
10    ferro_class, ferro_impl_classes, ferro_property, instantiate, BoxedValue, FerroObjectImpl, FerroProperty,
11    Nullable, Ref, StyledElement, StyledProperty,
12};
13use std::cell::OnceCell;
14use std::rc::Rc;
15
16/// A flyout that displays arbitrary content.
17#[repr(C)]
18pub struct Flyout {
19    base: PopupFlyoutBase,
20    classes: OnceCell<Classes>,
21}
22
23ferro_class!(Flyout: PopupFlyoutBase);
24ferroui_base::ferro_class_info!(Flyout { new: Flyout::new });
25ferro_impl_classes!(Flyout: FerroObjectImpl, FlyoutBaseImpl);
26
27impl PopupFlyoutBaseImpl for Flyout {
28    fn create_presenter(this: &Self) -> Ref<Control> {
29        let presenter = FlyoutPresenter::new();
30        presenter.bind_indexer(
31            &ContentControl::content_property().bind(),
32            &this.indexer(&Self::content_property().bind()),
33        );
34        presenter.bind_indexer(
35            &ContentControl::content_template_property().bind(),
36            &this.indexer(&Self::content_template_property().bind()),
37        );
38        presenter.upcast()
39    }
40
41    fn on_opening(this: &Self, args: &CancelEventArgs) {
42        if let Some(presenter) = this.popup().child() {
43            if let Some(classes) = this.classes.get() {
44                PopupFlyoutBase::set_presenter_classes(Some(&presenter), classes);
45            }
46
47            if let Some(theme) = this.flyout_presenter_theme() {
48                presenter.set_value(StyledElement::theme_property(), Some(theme));
49            }
50        }
51
52        Self::parent_on_opening(this, args);
53    }
54}
55
56ferroui_base::ferro_properties! { impl Flyout {
57    ferro_property!(
58        /// Defines the `Content` property.
59        pub fn content_property() -> StyledProperty<Option<BoxedValue>> {
60            FerroProperty::register::<Flyout, _>("Content", None)
61        }
62    );
63
64    ferro_property!(
65        /// Defines the `ContentTemplate` property.
66        pub fn content_template_property() -> StyledProperty<Option<Rc<dyn IDataTemplate>>> {
67            FerroProperty::register::<Flyout, _>("ContentTemplate", None)
68        }
69    );
70
71    ferro_property!(
72        /// Defines the `FlyoutPresenterTheme` property.
73        pub fn flyout_presenter_theme_property() -> StyledProperty<Option<Ref<ControlTheme>>> {
74            FerroProperty::register::<Flyout, _>("FlyoutPresenterTheme", None)
75        }
76    );
77} }
78
79impl Flyout {
80    /// Creates the class data; see [`ferroui_base::FerroObject::construct`].
81    pub fn construct() -> Self {
82        Self { base: PopupFlyoutBase::construct(), classes: OnceCell::new() }
83    }
84
85    /// Creates a flyout.
86    pub fn new() -> Ref<Self> {
87        instantiate(Self::construct())
88    }
89
90    /// The classes collection to apply to the flyout presenter this flyout
91    /// is hosting.
92    pub fn flyout_presenter_classes(&self) -> Classes {
93        self.classes.get_or_init(Classes::new).clone()
94    }
95
96    /// The control theme that is applied to the container element generated
97    /// for the flyout presenter.
98    pub fn flyout_presenter_theme(&self) -> Option<Ref<ControlTheme>> {
99        self.get_value(Self::flyout_presenter_theme_property())
100    }
101
102    pub fn set_flyout_presenter_theme(&self, value: impl Into<Nullable<ControlTheme>>) {
103        self.set_value(Self::flyout_presenter_theme_property(), value.into().0)
104    }
105
106    /// The content to display in this flyout.
107    pub fn content(&self) -> Option<BoxedValue> {
108        self.get_value(Self::content_property())
109    }
110
111    pub fn set_content(&self, value: Option<BoxedValue>) {
112        self.set_value(Self::content_property(), value)
113    }
114
115    /// The data template used to display the content of the flyout.
116    pub fn content_template(&self) -> Option<Rc<dyn IDataTemplate>> {
117        self.get_value(Self::content_template_property())
118    }
119
120    pub fn set_content_template(&self, value: Option<Rc<dyn IDataTemplate>>) {
121        self.set_value(Self::content_template_property(), value)
122    }
123}