1use crate::core::layout;
3use crate::core::mouse;
4use crate::core::overlay;
5use crate::core::renderer;
6use crate::core::widget::tree::{self, Tree};
7use crate::core::widget::{Meta, Operation};
8use crate::core::{
9 Alignment, Event, Layout, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, Widget,
10};
11
12pub struct Column<Key, W>
32where
33 Key: Copy + PartialEq,
34{
35 spacing: f32,
36 padding: Padding,
37 width: Length,
38 height: Length,
39 align_items: Alignment,
40 keys: Vec<Key>,
41 children: Vec<W>,
42}
43
44impl<Key, W> Column<Key, W>
45where
46 Key: Copy + PartialEq,
47{
48 pub fn new() -> Self {
50 Self::from_vecs(Vec::new(), Vec::new())
51 }
52
53 pub fn from_vecs(keys: Vec<Key>, children: Vec<W>) -> Self {
61 Self {
62 spacing: 0.0,
63 padding: Padding::ZERO,
64 width: Length::Fit,
65 height: Length::Fit,
66 align_items: Alignment::Start,
67 keys,
68 children,
69 }
70 }
71
72 pub fn with_capacity(capacity: usize) -> Self {
74 Self::from_vecs(Vec::with_capacity(capacity), Vec::with_capacity(capacity))
75 }
76
77 pub fn with_children(children: impl IntoIterator<Item = (Key, W)>) -> Self
79 where
80 W: Meta,
81 {
82 let iterator = children.into_iter();
83
84 Self::with_capacity(iterator.size_hint().0).extend(iterator)
85 }
86
87 pub fn spacing(mut self, amount: impl Into<Pixels>) -> Self {
93 self.spacing = amount.into().0;
94 self
95 }
96
97 pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
99 self.padding = padding.into();
100 self
101 }
102
103 pub fn width(mut self, width: impl Into<Length>) -> Self {
105 self.width = width.into();
106 self
107 }
108
109 pub fn height(mut self, height: impl Into<Length>) -> Self {
111 self.height = height.into();
112 self
113 }
114
115 pub fn align_items(mut self, align: Alignment) -> Self {
117 self.align_items = align;
118 self
119 }
120
121 pub fn push(mut self, key: Key, child: impl Into<W>) -> Self
123 where
124 W: Meta,
125 {
126 let child = child.into();
127
128 if !child.is_void() {
129 self.keys.push(key);
130 self.children.push(child);
131 }
132
133 self
134 }
135
136 pub fn push_maybe(self, key: Key, child: Option<impl Into<W>>) -> Self
138 where
139 W: Meta,
140 {
141 if let Some(child) = child {
142 self.push(key, child)
143 } else {
144 self
145 }
146 }
147
148 pub fn extend(self, children: impl IntoIterator<Item = (Key, W)>) -> Self
150 where
151 W: Meta,
152 {
153 children
154 .into_iter()
155 .fold(self, |column, (key, child)| column.push(key, child))
156 }
157}
158
159impl<Key, W> Default for Column<Key, W>
160where
161 Key: Copy + PartialEq,
162{
163 fn default() -> Self {
164 Self::new()
165 }
166}
167
168struct State<Key>
169where
170 Key: Copy + PartialEq,
171{
172 keys: Vec<Key>,
173 cache: layout::flex::Cache,
174}
175
176impl<Key, W> Meta for Column<Key, W> where Key: Copy + PartialEq {}
177
178impl<Key, W, Message, Theme, Renderer> Widget<Message, Theme, Renderer> for Column<Key, W>
179where
180 Renderer: crate::core::Renderer,
181 Key: Copy + PartialEq + 'static,
182 W: Widget<Message, Theme, Renderer>,
183{
184 fn tag(&self) -> tree::Tag {
185 tree::Tag::of::<State<Key>>()
186 }
187
188 fn state(&self) -> tree::State {
189 tree::State::new(State {
190 keys: self.keys.clone(),
191 cache: layout::flex::Cache::default(),
192 })
193 }
194
195 fn diff(&mut self, tree: &mut Tree) {
196 let Tree {
197 state, children, ..
198 } = tree;
199
200 let state = state.downcast_mut::<State<Key>>();
201
202 tree::diff_children_custom_with_search(
203 children,
204 &mut self.children,
205 Tree::diff,
206 |index| {
207 self.keys.get(index).or_else(|| self.keys.last()).copied()
208 != Some(state.keys[index])
209 },
210 |child| Tree::new(child),
211 );
212
213 if state.keys != self.keys {
214 state.keys.clone_from(&self.keys);
215 }
216
217 if self.width.is_fit() || self.height.is_fit() {
218 for child in &self.children {
219 let size = child.size();
220
221 self.width = self.width.cross(size.width);
222 self.height = self.height.stack(size.height);
223 }
224 }
225 }
226
227 fn size(&self) -> Size<Length> {
228 Size {
229 width: self.width,
230 height: self.height,
231 }
232 }
233
234 fn layout(&mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits) {
235 let state = tree.state.downcast_mut::<State<Key>>();
236
237 tree.size = layout::flex::resolve(
238 layout::flex::Axis::Vertical,
239 renderer,
240 limits,
241 self.width,
242 self.height,
243 self.padding,
244 self.spacing,
245 self.align_items,
246 &mut tree.children,
247 &mut self.children,
248 &mut state.cache,
249 );
250 }
251
252 fn operate(
253 &mut self,
254 tree: &mut Tree,
255 layout: Layout,
256 viewport: &Rectangle,
257 renderer: &Renderer,
258 operation: &mut dyn Operation,
259 ) {
260 operation.container(None, layout.bounds(), viewport);
261 operation.traverse(&mut |operation| {
262 self.children
263 .iter_mut()
264 .zip(layout.iter_mut(&mut tree.children))
265 .for_each(|(child, (layout, state))| {
266 child.operate(state, layout, viewport, renderer, operation);
267 });
268 });
269 }
270
271 fn update(
272 &mut self,
273 tree: &mut Tree,
274 event: &Event,
275 layout: Layout,
276 cursor: mouse::Cursor,
277 renderer: &Renderer,
278 shell: &mut Shell<'_, Message>,
279 viewport: &Rectangle,
280 ) {
281 for (child, (layout, tree)) in self
282 .children
283 .iter_mut()
284 .zip(layout.iter_mut(&mut tree.children))
285 {
286 child.update(tree, event, layout, cursor, renderer, shell, viewport);
287 }
288 }
289
290 fn mouse_interaction(
291 &self,
292 tree: &Tree,
293 layout: Layout,
294 cursor: mouse::Cursor,
295 viewport: &Rectangle,
296 renderer: &Renderer,
297 ) -> mouse::Interaction {
298 self.children
299 .iter()
300 .zip(layout.iter(&tree.children))
301 .map(|(child, (layout, tree))| {
302 child.mouse_interaction(tree, layout, cursor, viewport, renderer)
303 })
304 .max()
305 .unwrap_or_default()
306 }
307
308 fn draw(
309 &self,
310 tree: &Tree,
311 renderer: &mut Renderer,
312 theme: &Theme,
313 style: &renderer::Style,
314 layout: Layout,
315 cursor: mouse::Cursor,
316 viewport: &Rectangle,
317 ) {
318 for (child, (layout, state)) in self.children.iter().zip(layout.iter(&tree.children)) {
319 child.draw(state, renderer, theme, style, layout, cursor, viewport);
320 }
321 }
322
323 fn overlay<'b>(
324 &'b mut self,
325 tree: &'b mut Tree,
326 layout: Layout,
327 renderer: &Renderer,
328 viewport: &Rectangle,
329 translation: Vector,
330 window: Size,
331 ) -> Vec<overlay::Element<'b, Message, Theme, Renderer>> {
332 overlay::from_children(
333 &mut self.children,
334 tree,
335 layout,
336 renderer,
337 viewport,
338 translation,
339 window,
340 )
341 }
342}