ferroui_controls/primitives/
visual_layer_manager.rs1use super::{AdornerLayer, LightDismissOverlayLayer, OverlayLayer, PopupOverlayLayer, TextSelectorLayer};
2use crate::{Control, ControlImpl, Decorator, Panel};
3use ferroui_base::controls::ResourcesChangedEventArgs;
4use ferroui_base::input::InputElementImpl;
5use ferroui_base::interactivity::InteractiveImpl;
6use ferroui_base::layout::{LayoutableImpl, LayoutableImplExt};
7use ferroui_base::logical_tree::LogicalTreeAttachmentEventArgs;
8use ferroui_base::{
9 ferro_class, ferro_impl_classes, instantiate, FerroObjectImpl, ObjectType, Rect, Ref, Size, StyledElement,
10 StyledElementImpl, StyledElementImplExt, VisualImpl, WeakRef,
11};
12use std::cell::{Cell, RefCell};
13
14const ADORNER_Z_INDEX: i32 = i32::MAX - 100;
15const OVERLAY_Z_INDEX: i32 = i32::MAX - 98;
16const LIGHT_DISMISS_OVERLAY_Z_INDEX: i32 = i32::MAX - 97;
17const TEXT_SELECTOR_LAYER_Z_INDEX: i32 = i32::MAX - 96;
18const POPUP_OVERLAY_Z_INDEX: i32 = i32::MAX - 95;
19
20#[repr(C)]
23pub struct VisualLayerManager {
24 base: Decorator,
25 logical_root: RefCell<Option<WeakRef<StyledElement>>>,
26 layers: RefCell<Vec<Ref<Control>>>,
27 overlay_layer: RefCell<Option<Ref<OverlayLayer>>>,
28 enable_adorner_layer: Cell<bool>,
29 enable_overlay_layer: Cell<bool>,
30 enable_popup_overlay_layer: Cell<bool>,
31 enable_text_selector_layer: Cell<bool>,
32}
33
34ferro_class!(VisualLayerManager: Decorator);
35ferroui_base::ferro_class_info!(VisualLayerManager { new: VisualLayerManager::new });
36ferro_impl_classes!(VisualLayerManager: FerroObjectImpl, VisualImpl, InteractiveImpl, InputElementImpl, ControlImpl);
37
38impl StyledElementImpl for VisualLayerManager {
39 fn notify_child_resources_changed(this: &Self, e: ResourcesChangedEventArgs) {
40 for layer in this.layers_snapshot() {
41 layer.notify_resources_changed(e, true);
42 }
43
44 Self::parent_notify_child_resources_changed(this, e);
45 }
46
47 fn on_attached_to_logical_tree(this: &Self, e: &LogicalTreeAttachmentEventArgs) {
48 Self::parent_on_attached_to_logical_tree(this, e);
49 *this.logical_root.borrow_mut() = Some(e.root().downgrade());
50
51 for layer in this.layers_snapshot() {
52 layer.notify_attached_to_logical_tree(e);
53 }
54 }
55
56 fn on_detached_from_logical_tree(this: &Self, e: &LogicalTreeAttachmentEventArgs) {
57 *this.logical_root.borrow_mut() = None;
58 Self::parent_on_detached_from_logical_tree(this, e);
59
60 for layer in this.layers_snapshot() {
61 layer.notify_detached_from_logical_tree(e);
62 }
63 }
64}
65
66impl LayoutableImpl for VisualLayerManager {
67 fn measure_override(this: &Self, available_size: Size) -> Size {
68 for layer in this.layers_snapshot() {
69 layer.measure(available_size);
70 }
71
72 Self::parent_measure_override(this, available_size)
73 }
74
75 fn arrange_override(this: &Self, final_size: Size) -> Size {
76 for layer in this.layers_snapshot() {
77 layer.arrange(Rect::from_size(final_size));
78 }
79
80 Self::parent_arrange_override(this, final_size)
81 }
82}
83
84impl VisualLayerManager {
85 pub fn construct() -> Self {
87 Self {
88 base: Decorator::construct(),
89 logical_root: RefCell::new(None),
90 layers: RefCell::new(Vec::new()),
91 overlay_layer: RefCell::new(None),
92 enable_adorner_layer: Cell::new(true),
93 enable_overlay_layer: Cell::new(false),
94 enable_popup_overlay_layer: Cell::new(false),
95 enable_text_selector_layer: Cell::new(false),
96 }
97 }
98
99 pub fn new() -> Ref<Self> {
100 instantiate(Self::construct())
101 }
102
103 pub fn enable_adorner_layer(&self) -> bool {
107 self.enable_adorner_layer.get()
108 }
109
110 pub fn set_enable_adorner_layer(&self, value: bool) {
111 self.enable_adorner_layer.set(value)
112 }
113
114 pub fn enable_overlay_layer(&self) -> bool {
118 self.enable_overlay_layer.get()
119 }
120
121 pub fn set_enable_overlay_layer(&self, value: bool) {
122 self.enable_overlay_layer.set(value)
123 }
124
125 pub fn enable_popup_overlay_layer(&self) -> bool {
129 self.enable_popup_overlay_layer.get()
130 }
131
132 pub fn set_enable_popup_overlay_layer(&self, value: bool) {
133 self.enable_popup_overlay_layer.set(value)
134 }
135
136 pub fn enable_text_selector_layer(&self) -> bool {
140 self.enable_text_selector_layer.get()
141 }
142
143 pub fn set_enable_text_selector_layer(&self, value: bool) {
144 self.enable_text_selector_layer.set(value)
145 }
146
147 pub fn adorner_layer(&self) -> Option<Ref<AdornerLayer>> {
150 if !self.enable_adorner_layer() {
151 return None;
152 }
153
154 let mut rv = self.find_layer::<AdornerLayer>();
155 if rv.is_none() {
156 let layer = AdornerLayer::new();
157 self.add_layer(layer.clone().upcast(), ADORNER_Z_INDEX);
158 rv = Some(layer);
159 }
160 rv
161 }
162
163 pub fn popup_overlay_layer(&self) -> Option<Ref<PopupOverlayLayer>> {
166 if !self.enable_popup_overlay_layer() {
167 return None;
168 }
169
170 let mut rv = self.find_layer::<PopupOverlayLayer>();
171 if rv.is_none() {
172 let layer = PopupOverlayLayer::new();
173 self.add_layer(layer.clone().upcast(), POPUP_OVERLAY_Z_INDEX);
174 rv = Some(layer);
175 }
176 rv
177 }
178
179 pub fn overlay_layer(&self) -> Option<Ref<OverlayLayer>> {
183 if !self.enable_overlay_layer() {
184 return None;
185 }
186
187 let existing = self.overlay_layer.borrow().clone();
188 if existing.is_some() {
189 return existing;
190 }
191
192 let overlay_layer = OverlayLayer::new();
193 *self.overlay_layer.borrow_mut() = Some(overlay_layer.clone());
194 let adorner = AdornerLayer::new();
195 overlay_layer.set_adorner_layer(Some(adorner.clone()));
196
197 let panel = Panel::new();
198 panel.children().add(overlay_layer.clone());
199 panel.children().add(adorner);
200
201 self.add_layer(panel.upcast(), OVERLAY_Z_INDEX);
202
203 Some(overlay_layer)
204 }
205
206 pub fn text_selector_layer(&self) -> Option<Ref<TextSelectorLayer>> {
209 if !self.enable_text_selector_layer() {
210 return None;
211 }
212
213 let mut rv = self.find_layer::<TextSelectorLayer>();
214 if rv.is_none() {
215 let layer = TextSelectorLayer::new();
216 self.add_layer(layer.clone().upcast(), TEXT_SELECTOR_LAYER_Z_INDEX);
217 rv = Some(layer);
218 }
219 rv
220 }
221
222 pub fn light_dismiss_overlay_layer(&self) -> Ref<LightDismissOverlayLayer> {
225 match self.find_layer::<LightDismissOverlayLayer>() {
226 Some(rv) => rv,
227 None => {
228 let rv = LightDismissOverlayLayer::new();
229 self.add_layer(rv.clone().upcast(), LIGHT_DISMISS_OVERLAY_Z_INDEX);
230 rv
231 }
232 }
233 }
234
235 fn layers_snapshot(&self) -> Vec<Ref<Control>> {
236 self.layers.borrow().clone()
237 }
238
239 fn find_layer<T: ObjectType>(&self) -> Option<Ref<T>> {
240 self.layers.borrow().iter().find_map(|layer| layer.cast::<T>())
241 }
242
243 fn add_layer(&self, layer: Ref<Control>, z_index: i32) {
244 self.layers.borrow_mut().push(layer.clone());
245 layer.set_parent(self.to_ref());
246 layer.set_z_index(z_index);
247 self.visual_children().add(layer.clone().upcast());
248 if self.is_attached_to_logical_tree() {
249 let logical_root = self
250 .logical_root
251 .borrow()
252 .as_ref()
253 .and_then(WeakRef::upgrade)
254 .expect("an attached layer manager knows its logical root");
255 layer.notify_attached_to_logical_tree(&LogicalTreeAttachmentEventArgs::new(
256 logical_root,
257 layer.clone().upcast(),
258 Some(self.to_ref().upcast()),
259 ));
260 }
261 self.invalidate_arrange();
262 }
263}