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}