1use super::flex::{Axis, Flex};
4use super::{Align, Container, Key, Length, Node, Widget};
5use crate::env::Env;
6use crate::geometry::Padding;
7
8pub struct View<'a, Msg> {
10 nodes: &'a mut Vec<Node<Msg>>,
11 env: &'a Env,
12}
13
14impl<'a, Msg: 'static> View<'a, Msg> {
15 pub(crate) fn new(nodes: &'a mut Vec<Node<Msg>>, env: &'a Env) -> Self {
16 Self { nodes, env }
17 }
18
19 #[must_use]
21 pub fn env(&self) -> &Env {
22 self.env
23 }
24
25 pub fn add<W: Widget<Msg>>(&mut self, widget: W) -> NodeMut<'_, Msg> {
27 let index = self.nodes.len();
28 self.nodes.push(Node::new(widget, index));
29 NodeMut { node: self.nodes.last_mut().expect("a node was just pushed") }
30 }
31
32 pub fn add_with<W: Container<Msg>>(
34 &mut self,
35 mut widget: W,
36 build: impl FnOnce(&mut View<'_, Msg>),
37 ) -> NodeMut<'_, Msg> {
38 let mut children = Vec::new();
39 build(&mut View::new(&mut children, self.env));
40 widget.set_children(children);
41 self.add(widget)
42 }
43
44 pub fn column(&mut self, build: impl FnOnce(&mut View<'_, Msg>)) -> NodeMut<'_, Msg> {
46 self.container(Axis::Column, build)
47 }
48
49 pub fn row(&mut self, build: impl FnOnce(&mut View<'_, Msg>)) -> NodeMut<'_, Msg> {
51 self.container(Axis::Row, build)
52 }
53
54 pub fn stack(&mut self, build: impl FnOnce(&mut View<'_, Msg>)) -> NodeMut<'_, Msg> {
56 self.container(Axis::Stack, build)
57 }
58
59 pub fn page(&mut self, key: impl Into<String>, build: impl FnOnce(&mut View<'_, Msg>)) -> NodeMut<'_, Msg> {
62 let node = self.container(Axis::Column, build);
63 node.node.persistent = true;
64 node.node.key = Key::Named(key.into());
65 node.fill()
66 }
67
68 pub fn spacer(&mut self) -> NodeMut<'_, Msg> {
70 self.container(Axis::Stack, |_| {}).fill()
71 }
72
73 fn container(&mut self, axis: Axis, build: impl FnOnce(&mut View<'_, Msg>)) -> NodeMut<'_, Msg> {
74 let mut children = Vec::new();
75 build(&mut View::new(&mut children, self.env));
76 self.add(Flex::new(axis, children))
77 }
78}
79
80pub struct NodeMut<'a, Msg> {
83 node: &'a mut Node<Msg>,
84}
85
86impl<'a, Msg> NodeMut<'a, Msg> {
87 pub fn id(self, name: impl Into<String>) -> Self {
90 self.node.key = Key::Named(name.into());
91 self
92 }
93
94 pub fn width(self, width: Length) -> Self {
96 self.node.layout.width = width;
97 self
98 }
99
100 pub fn height(self, height: Length) -> Self {
102 self.node.layout.height = height;
103 self
104 }
105
106 pub fn fill(self) -> Self {
108 self.width(Length::Fill(1)).height(Length::Fill(1))
109 }
110
111 pub fn fill_width(self) -> Self {
113 self.width(Length::Fill(1))
114 }
115
116 pub fn fill_height(self) -> Self {
118 self.height(Length::Fill(1))
119 }
120
121 pub fn padding(self, padding: Padding) -> Self {
123 self.node.layout.padding = padding;
124 self
125 }
126
127 pub fn gap(self, cells: u16) -> Self {
129 self.node.layout.gap = cells;
130 self
131 }
132
133 pub fn justify(self, align: Align) -> Self {
135 self.node.layout.justify = align;
136 self
137 }
138
139 pub fn selectable(self, selectable: bool) -> Self {
145 self.node.selectable = Some(selectable);
146 self
147 }
148
149 pub fn align(self, align: Align) -> Self {
151 self.node.layout.align = align;
152 self
153 }
154}