ferroui_controls/embedding/
embeddable_control_root.rs1use crate::platform::{ITopLevelImpl, PlatformManager};
2use crate::primitives::TemplatedControlImpl;
3use crate::{ContentControlImpl, ControlImpl, TopLevel, TopLevelImpl};
4use ferroui_base::input::{IFocusScope, InputElementImpl};
5use ferroui_base::interactivity::InteractiveImpl;
6use ferroui_base::layout::{ILayoutManager, LayoutableImpl, LayoutableImplExt};
7use ferroui_base::{
8 ferro_class, ferro_impl_classes, instantiate, FerroObjectImpl, Ref, Size, StaticType, StyledElementImpl, TypeInfo,
9 VisualImpl,
10};
11use std::cell::Cell;
12use std::rc::Rc;
13
14#[repr(C)]
18pub struct EmbeddableControlRoot {
19 base: TopLevel,
20 enforce_client_size: Cell<bool>,
21}
22
23ferro_class! {
24 EmbeddableControlRoot: TopLevel, virtuals EmbeddableControlRootImpl: TopLevelImpl {
25 fn dispose(this);
27 }
28}
29ferroui_base::ferro_class_info!(EmbeddableControlRoot { new: EmbeddableControlRoot::new });
30
31ferro_impl_classes!(
32 EmbeddableControlRoot: FerroObjectImpl,
33 VisualImpl,
34 InteractiveImpl,
35 ContentControlImpl,
36 TopLevelImpl
37);
38
39impl ControlImpl for EmbeddableControlRoot {
40 fn on_create_automation_peer(this: &Self) -> Ref<crate::automation::peers::AutomationPeer> {
41 crate::automation::peers::EmbeddableControlRootAutomationPeer::new(this).upcast()
42 }
43}
44
45impl TemplatedControlImpl for EmbeddableControlRoot {
46 fn on_apply_template(this: &Self, e: &crate::primitives::TemplateAppliedEventArgs) {
47 use crate::primitives::TemplatedControlImplExt;
48 Self::parent_on_apply_template(this, e);
49 this.enable_visual_layer_manager_layers();
50 }
51}
52
53impl IFocusScope for EmbeddableControlRoot {}
54
55impl InputElementImpl for EmbeddableControlRoot {
56 fn is_focus_scope(_this: &Self) -> bool {
57 true
58 }
59}
60
61impl StyledElementImpl for EmbeddableControlRoot {
62 fn style_key_override(_this: &Self) -> &'static TypeInfo {
63 <EmbeddableControlRoot as StaticType>::TYPE
64 }
65}
66
67impl LayoutableImpl for EmbeddableControlRoot {
68 fn measure_override(this: &Self, mut available_size: Size) -> Size {
69 if this.enforce_client_size.get() {
70 available_size = this.platform_impl().map(|platform_impl| platform_impl.client_size()).unwrap_or_default();
71 }
72 let rv = Self::parent_measure_override(this, available_size);
73 if this.enforce_client_size.get() {
74 return available_size;
75 }
76 rv
77 }
78}
79
80impl EmbeddableControlRootImpl for EmbeddableControlRoot {
81 fn dispose(this: &Self) {
82 if let Some(platform_impl) = this.platform_impl() {
83 platform_impl.dispose();
84 }
85 this.ensure_closed();
86 }
87}
88
89impl EmbeddableControlRoot {
90 pub fn construct(platform_impl: Rc<dyn ITopLevelImpl>) -> Self {
92 Self { base: TopLevel::construct(platform_impl), enforce_client_size: Cell::new(true) }
93 }
94
95 pub fn with_impl(platform_impl: Rc<dyn ITopLevelImpl>) -> Ref<Self> {
97 instantiate(Self::construct(platform_impl))
98 }
99
100 pub fn new() -> Ref<Self> {
103 Self::with_impl(PlatformManager::create_embeddable_top_level())
104 }
105
106 pub fn enforce_client_size(&self) -> bool {
110 self.enforce_client_size.get()
111 }
112
113 pub fn set_enforce_client_size(&self, value: bool) {
114 self.enforce_client_size.set(value)
115 }
116
117 pub fn prepare(&self) {
120 self.ensure_initialized();
121 self.apply_template();
122 self.layout_manager().execute_initial_layout_pass();
123 }
124
125 fn ensure_initialized(&self) {
126 if !self.is_initialized() {
127 self.begin_init();
128 self.end_init();
129 }
130 }
131}