Skip to main content

ferroui_controls/primitives/
overlay_layer.rs

1use super::{AdornerLayer, VisualLayerManager};
2use crate::{Canvas, CanvasImpl, ControlImpl, PanelImpl, TopLevel};
3use ferroui_base::input::InputElementImpl;
4use ferroui_base::interactivity::InteractiveImpl;
5use ferroui_base::layout::{LayoutableImpl, LayoutableImplExt};
6use ferroui_base::{
7    ferro_class, ferro_impl_classes, instantiate, FerroObjectImpl, Ref, Size, StyledElementImpl, Visual, VisualImpl,
8};
9use std::cell::{Cell, RefCell};
10
11/// Represents a surface for showing overlays.
12/// Overlays are displayed on top of other elements, but behind popups.
13#[repr(C)]
14pub struct OverlayLayer {
15    base: Canvas,
16    available_size: Cell<Size>,
17    adorner_layer: RefCell<Option<Ref<AdornerLayer>>>,
18}
19
20ferro_class!(OverlayLayer: Canvas);
21ferro_impl_classes!(
22    OverlayLayer: FerroObjectImpl,
23    StyledElementImpl,
24    InteractiveImpl,
25    InputElementImpl,
26    ControlImpl,
27    PanelImpl,
28    CanvasImpl
29);
30
31impl VisualImpl for OverlayLayer {
32    fn bypass_flow_direction_policies(_this: &Self) -> bool {
33        true
34    }
35}
36
37impl LayoutableImpl for OverlayLayer {
38    fn measure_override(this: &Self, available_size: Size) -> Size {
39        for child in this.children().snapshot().iter() {
40            child.measure(available_size);
41        }
42        available_size
43    }
44
45    fn arrange_override(this: &Self, final_size: Size) -> Size {
46        // We are saving it here since child controls might need to know the entire size of the overlay
47        // and Bounds won't be updated in time
48        this.available_size.set(final_size);
49        Self::parent_arrange_override(this, final_size)
50    }
51}
52
53impl OverlayLayer {
54    /// Creates the layer (internal upstream: the layer is created by its
55    /// [`VisualLayerManager`]).
56    pub(crate) fn new() -> Ref<Self> {
57        instantiate(Self {
58            base: Canvas::construct(),
59            available_size: Cell::new(Size::default()),
60            adorner_layer: RefCell::new(None),
61        })
62    }
63
64    /// The size the layer was last arranged with.
65    pub fn available_size(&self) -> Size {
66        self.available_size.get()
67    }
68
69    /// The dedicated adorner layer for this overlay layer (internal
70    /// upstream).
71    pub fn adorner_layer(&self) -> Option<Ref<AdornerLayer>> {
72        self.adorner_layer.borrow().clone()
73    }
74
75    pub(crate) fn set_adorner_layer(&self, value: Option<Ref<AdornerLayer>>) {
76        *self.adorner_layer.borrow_mut() = value;
77    }
78
79    /// Retrieves the overlay layer associated with the specified visual, if
80    /// any.
81    pub fn get_overlay_layer(visual: &Visual) -> Option<Ref<OverlayLayer>> {
82        for v in visual.get_self_and_visual_ancestors() {
83            if let Some(layer) = v.cast::<VisualLayerManager>().and_then(|manager| manager.overlay_layer()) {
84                return Some(layer);
85            }
86        }
87
88        if let Some(tl) = TopLevel::get_top_level(Some(visual)) {
89            let layers = tl.get_visual_descendants().find_map(|v| v.cast::<VisualLayerManager>());
90            return layers.and_then(|layers| layers.overlay_layer());
91        }
92
93        None
94    }
95}