Skip to main content

ferroui_controls/embedding/offscreen/
offscreen_top_level.rs

1use super::OffscreenTopLevelImplBase;
2use crate::embedding::EmbeddableControlRoot;
3use crate::platform::ITopLevelImpl;
4use crate::primitives::TemplatedControlImpl;
5use crate::{ContentControlImpl, ControlImpl, TopLevel, TopLevelImpl};
6use ferroui_base::input::InputElementImpl;
7use ferroui_base::interactivity::InteractiveImpl;
8use ferroui_base::layout::{ILayoutManager, LayoutableImpl};
9use ferroui_base::{
10    ferro_class, ferro_impl_classes, instantiate, FerroObjectImpl, FerroObjectImplExt, Ref, StaticType, StyledElementImpl, TypeInfo,
11    VisualImpl,
12};
13use std::rc::Rc;
14
15/// A top-level over an offscreen implementation: laid out and rendered
16/// without a window of the platform.
17#[repr(C)]
18pub struct OffscreenTopLevel {
19    base: TopLevel,
20    platform_impl: Rc<OffscreenTopLevelImplBase>,
21}
22
23ferro_class!(OffscreenTopLevel: TopLevel);
24ferroui_base::ferro_class_info!(OffscreenTopLevel {});
25
26ferro_impl_classes!(
27    OffscreenTopLevel: VisualImpl,
28    LayoutableImpl,
29    InteractiveImpl,
30    InputElementImpl,
31    ControlImpl,
32    TemplatedControlImpl,
33    ContentControlImpl,
34    TopLevelImpl
35);
36
37impl FerroObjectImpl for OffscreenTopLevel {
38    fn constructed(this: &Self) {
39        Self::parent_constructed(this);
40        this.prepare();
41    }
42}
43
44impl StyledElementImpl for OffscreenTopLevel {
45    fn style_key_override(_this: &Self) -> &'static TypeInfo {
46        <EmbeddableControlRoot as StaticType>::TYPE
47    }
48}
49
50impl OffscreenTopLevel {
51    /// Field initialisation of a top-level over an offscreen implementation.
52    pub fn construct(platform_impl: Rc<OffscreenTopLevelImplBase>) -> Self {
53        let top_level_impl: Rc<dyn ITopLevelImpl> = platform_impl.clone();
54        Self { base: TopLevel::construct(top_level_impl), platform_impl }
55    }
56
57    /// Creates a top-level over an offscreen implementation and prepares
58    /// it.
59    pub fn new(platform_impl: Rc<OffscreenTopLevelImplBase>) -> Ref<Self> {
60        instantiate(Self::construct(platform_impl))
61    }
62
63    /// The offscreen implementation of the top-level (C# `Impl`).
64    pub fn offscreen_impl(&self) -> &Rc<OffscreenTopLevelImplBase> {
65        &self.platform_impl
66    }
67
68    /// Initializes the top-level, applies its template and runs the
69    /// initial layout pass.
70    pub fn prepare(&self) {
71        self.ensure_initialized();
72        self.apply_template();
73        self.layout_manager().execute_initial_layout_pass();
74    }
75
76    fn ensure_initialized(&self) {
77        if !self.is_initialized() {
78            self.begin_init();
79            self.end_init();
80        }
81    }
82
83    /// Releases the platform implementation and tears the top-level down.
84    pub fn dispose(&self) {
85        if let Some(platform_impl) = self.platform_impl() {
86            platform_impl.dispose();
87        }
88        self.ensure_closed();
89    }
90}