fission_core/ui/widgets/
overlay.rs1use crate::lowering::{LoweringContext, NodeBuilder, wrap_zstack_child};
2use crate::ui::traits::Lower;
3use crate::ui::{Node, Text, TextContent};
4use fission_ir::{LayoutOp, NodeId, Op};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct Overlay {
23 pub id: Option<NodeId>,
25 pub content: Box<Node>,
27 pub overlay: Box<Node>,
29}
30
31impl Overlay {
32 pub fn into_node(self) -> Node {
33 Node::Overlay(self)
34 }
35}
36
37impl Default for Overlay {
38 fn default() -> Self {
39 Self {
40 id: None,
41 content: Box::new(Node::Text(Text {
42 content: TextContent::Literal("".into()),
43 ..Default::default()
44 })),
45 overlay: Box::new(Node::Text(Text {
46 content: TextContent::Literal("".into()),
47 ..Default::default()
48 })),
49 }
50 }
51}
52
53impl Lower for Overlay {
54 fn lower(&self, cx: &mut LoweringContext) -> NodeId {
55 let id = self.id.unwrap_or_else(|| cx.next_node_id());
56
57 cx.push_scope(id);
58
59 let overlay_scope = cx.next_node_id();
62 cx.push_scope(overlay_scope);
63 let overlay_child_id = self.overlay.lower(cx);
64 cx.pop_scope();
65 let mut overlay_fill =
66 NodeBuilder::new(cx.next_node_id(), Op::Layout(LayoutOp::AbsoluteFill));
67 overlay_fill.add_child(overlay_child_id);
68 let overlay_fill_id = overlay_fill.build(cx);
69
70 let stack_id = cx.next_node_id();
72 let content_id = self.content.lower(cx);
73 cx.push_scope(stack_id);
74 let content_wrapped = wrap_zstack_child(cx, content_id);
75 let overlay_wrapped = wrap_zstack_child(cx, overlay_fill_id);
76 cx.pop_scope();
77
78 let mut stack = NodeBuilder::new(stack_id, Op::Layout(LayoutOp::ZStack));
79 stack.add_child(content_wrapped);
80 stack.add_child(overlay_wrapped);
81 let stack_id = stack.build(cx);
82
83 let mut stack_wrapper = NodeBuilder::new(
86 cx.next_node_id(),
87 Op::Layout(LayoutOp::Box {
88 width: None,
89 height: None,
90 min_width: None,
91 max_width: None,
92 min_height: None,
93 max_height: None,
94 padding: [0.0; 4],
95 flex_grow: 1.0,
96 flex_shrink: 1.0,
97 aspect_ratio: None,
98 }),
99 );
100 stack_wrapper.add_child(stack_id);
101 let stack_wrapper_id = stack_wrapper.build(cx);
102
103 let mut root = NodeBuilder::new(
106 id,
107 Op::Layout(LayoutOp::Flex {
108 direction: fission_ir::FlexDirection::Column,
109 wrap: fission_ir::FlexWrap::NoWrap,
110 flex_grow: 1.0,
111 flex_shrink: 1.0,
112 padding: [0.0; 4],
113 gap: None,
114 align_items: fission_ir::op::AlignItems::Stretch,
115 justify_content: fission_ir::op::JustifyContent::Start,
116 })
117 );
118 root.add_child(stack_wrapper_id);
119
120 cx.pop_scope();
121
122 root.build(cx)
123 }
124}