overlay.rs

 1use serde_json::json;
 2
 3use crate::{
 4    geometry::{rect::RectF, vector::Vector2F},
 5    json::ToJson,
 6    DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, MouseRegion,
 7    PaintContext, SizeConstraint,
 8};
 9
10pub struct Overlay {
11    child: ElementBox,
12    abs_position: Option<Vector2F>,
13}
14
15impl Overlay {
16    pub fn new(child: ElementBox) -> Self {
17        Self {
18            child,
19            abs_position: None,
20        }
21    }
22
23    pub fn with_abs_position(mut self, position: Vector2F) -> Self {
24        self.abs_position = Some(position);
25        self
26    }
27}
28
29impl Element for Overlay {
30    type LayoutState = Vector2F;
31    type PaintState = ();
32
33    fn layout(
34        &mut self,
35        constraint: SizeConstraint,
36        cx: &mut LayoutContext,
37    ) -> (Vector2F, Self::LayoutState) {
38        let constraint = if self.abs_position.is_some() {
39            SizeConstraint::new(Vector2F::zero(), cx.window_size)
40        } else {
41            constraint
42        };
43        let size = self.child.layout(constraint, cx);
44        (Vector2F::zero(), size)
45    }
46
47    fn paint(
48        &mut self,
49        bounds: RectF,
50        _: RectF,
51        size: &mut Self::LayoutState,
52        cx: &mut PaintContext,
53    ) {
54        let origin = self.abs_position.unwrap_or(bounds.origin());
55        let visible_bounds = RectF::new(origin, *size);
56        cx.scene.push_stacking_context(None);
57        cx.scene.push_mouse_region(MouseRegion {
58            view_id: cx.current_view_id(),
59            bounds: visible_bounds,
60            ..Default::default()
61        });
62        self.child.paint(origin, visible_bounds, cx);
63        cx.scene.pop_stacking_context();
64    }
65
66    fn dispatch_event(
67        &mut self,
68        event: &Event,
69        _: RectF,
70        _: RectF,
71        _: &mut Self::LayoutState,
72        _: &mut Self::PaintState,
73        cx: &mut EventContext,
74    ) -> bool {
75        self.child.dispatch_event(event, cx)
76    }
77
78    fn debug(
79        &self,
80        _: RectF,
81        _: &Self::LayoutState,
82        _: &Self::PaintState,
83        cx: &DebugContext,
84    ) -> serde_json::Value {
85        json!({
86            "type": "Overlay",
87            "abs_position": self.abs_position.to_json(),
88            "child": self.child.debug(cx),
89        })
90    }
91}