1use taffy::style::FlexDirection;
2
3use crate::{
4 context::UpdateCx,
5 style::{Style, StyleClassRef},
6 view::ViewId,
7 view::{IntoView, IntoViewIter, View, ViewTuple},
8};
9
10pub struct Stack {
14 id: ViewId,
15 direction: Option<FlexDirection>,
16}
17
18pub(crate) fn create_stack(
19 children: Vec<Box<dyn View>>,
20 direction: Option<FlexDirection>,
21) -> Stack {
22 create_stack_with_id(ViewId::new(), children, direction)
23}
24
25pub(crate) fn create_stack_with_id(
26 id: ViewId,
27 children: Vec<Box<dyn View>>,
28 direction: Option<FlexDirection>,
29) -> Stack {
30 id.set_children_vec(children);
31 Stack { id, direction }
32}
33
34#[deprecated(since = "0.2.0", note = "Use Stack::new() instead")]
51pub fn stack<VT: ViewTuple + 'static>(children: VT) -> Stack {
52 create_stack(children.into_views(), None)
53}
54
55#[deprecated(since = "0.2.0", note = "Use Stack::horizontal() instead")]
57pub fn h_stack<VT: ViewTuple + 'static>(children: VT) -> Stack {
58 create_stack(children.into_views(), Some(FlexDirection::Row))
59}
60
61#[deprecated(since = "0.2.0", note = "Use Stack::vertical() instead")]
63pub fn v_stack<VT: ViewTuple + 'static>(children: VT) -> Stack {
64 create_stack(children.into_views(), Some(FlexDirection::Column))
65}
66
67fn from_iter<V>(iterator: impl IntoIterator<Item = V>, direction: Option<FlexDirection>) -> Stack
68where
69 V: IntoView + 'static,
70{
71 create_stack(
72 iterator
73 .into_iter()
74 .map(|v| -> Box<dyn View> { v.into_any() })
75 .collect(),
76 direction,
77 )
78}
79
80pub(crate) fn from_iter_with_id<V>(
81 id: ViewId,
82 iterator: impl IntoIterator<Item = V>,
83 direction: Option<FlexDirection>,
84) -> Stack
85where
86 V: IntoView + 'static,
87{
88 create_stack_with_id(
89 id,
90 iterator
91 .into_iter()
92 .map(|v| -> Box<dyn View> { v.into_any() })
93 .collect(),
94 direction,
95 )
96}
97
98#[deprecated(since = "0.2.0", note = "Use Stack::from_iter() instead")]
106pub fn stack_from_iter<V>(iterator: impl IntoIterator<Item = V>) -> Stack
107where
108 V: IntoView + 'static,
109{
110 from_iter(iterator, None)
111}
112
113#[deprecated(since = "0.2.0", note = "Use Stack::horizontal_from_iter() instead")]
115pub fn h_stack_from_iter<V>(iterator: impl IntoIterator<Item = V>) -> Stack
116where
117 V: IntoView + 'static,
118{
119 from_iter(iterator, Some(FlexDirection::Row))
120}
121
122#[deprecated(since = "0.2.0", note = "Use Stack::vertical_from_iter() instead")]
124pub fn v_stack_from_iter<V>(iterator: impl IntoIterator<Item = V>) -> Stack
125where
126 V: IntoView + 'static,
127{
128 from_iter(iterator, Some(FlexDirection::Column))
129}
130
131impl View for Stack {
132 fn id(&self) -> ViewId {
133 self.id
134 }
135
136 fn view_style(&self) -> Option<crate::style::Style> {
137 self.direction
138 .map(|direction| Style::new().flex_direction(direction))
139 }
140
141 fn debug_name(&self) -> std::borrow::Cow<'static, str> {
142 match self.direction {
143 Some(FlexDirection::Column) => "Vertical Stack".into(),
144 Some(FlexDirection::Row) => "Horizontal Stack".into(),
145 _ => "Stack".into(),
146 }
147 }
148
149 fn update(&mut self, _cx: &mut UpdateCx, state: Box<dyn std::any::Any>) {
150 if let Ok(state) = state.downcast::<Vec<Box<dyn View>>>() {
151 self.id.set_children_vec(*state);
152 self.id.request_all();
153 }
154 }
155}
156
157impl Stack {
158 pub fn new(children: impl IntoViewIter) -> Self {
179 let id = ViewId::new();
180 id.set_children_iter(children.into_view_iter());
181 Stack {
182 id,
183 direction: None,
184 }
185 }
186
187 pub fn with_id(id: ViewId, children: impl IntoViewIter) -> Self {
200 id.set_children_iter(children.into_view_iter());
201 Stack {
202 id,
203 direction: None,
204 }
205 }
206
207 #[allow(clippy::should_implement_trait)]
216 pub fn from_iter<V: IntoView + 'static>(children: impl IntoIterator<Item = V>) -> Self {
217 let id = ViewId::new();
218 id.set_children_vec(
219 children
220 .into_iter()
221 .map(|v| -> Box<dyn View> { v.into_any() })
222 .collect(),
223 );
224 Stack {
225 id,
226 direction: None,
227 }
228 }
229
230 pub fn from_iter_with_id<V: IntoView + 'static>(
244 id: ViewId,
245 children: impl IntoIterator<Item = V>,
246 direction: Option<FlexDirection>,
247 ) -> Self {
248 id.set_children_vec(
249 children
250 .into_iter()
251 .map(|v| -> Box<dyn View> { v.into_any() })
252 .collect(),
253 );
254 Stack { id, direction }
255 }
256
257 pub fn horizontal(children: impl IntoViewIter) -> Self {
266 let id = ViewId::new();
267 id.set_children_iter(children.into_view_iter());
268 Stack {
269 id,
270 direction: Some(FlexDirection::Row),
271 }
272 }
273
274 pub fn vertical(children: impl IntoViewIter) -> Self {
283 let id = ViewId::new();
284 id.set_children_iter(children.into_view_iter());
285 Stack {
286 id,
287 direction: Some(FlexDirection::Column),
288 }
289 }
290
291 pub fn horizontal_from_iter<V: IntoView + 'static>(
300 children: impl IntoIterator<Item = V>,
301 ) -> Self {
302 let id = ViewId::new();
303 id.set_children_vec(
304 children
305 .into_iter()
306 .map(|v| -> Box<dyn View> { v.into_any() })
307 .collect(),
308 );
309 Stack {
310 id,
311 direction: Some(FlexDirection::Row),
312 }
313 }
314
315 pub fn vertical_from_iter<V: IntoView + 'static>(
324 children: impl IntoIterator<Item = V>,
325 ) -> Self {
326 let id = ViewId::new();
327 id.set_children_vec(
328 children
329 .into_iter()
330 .map(|v| -> Box<dyn View> { v.into_any() })
331 .collect(),
332 );
333 Stack {
334 id,
335 direction: Some(FlexDirection::Column),
336 }
337 }
338
339 pub fn add_class_by_idx(self, class: impl Fn(usize) -> StyleClassRef) -> Self {
340 for (index, child) in self.id.children().into_iter().enumerate() {
341 let style_class = class(index);
342 child.add_class(style_class);
343 }
344 self
345 }
346}
347
348pub trait StackExt {
349 fn stack(self, direction: FlexDirection) -> Stack;
350 fn v_stack(self) -> Stack
351 where
352 Self: Sized,
353 {
354 StackExt::stack(self, FlexDirection::Column)
355 }
356 fn h_stack(self) -> Stack
357 where
358 Self: Sized,
359 {
360 StackExt::stack(self, FlexDirection::Row)
361 }
362}
363impl<V: IntoView + 'static, T: IntoIterator<Item = V> + 'static> StackExt for T {
364 fn stack(self, direction: FlexDirection) -> Stack {
365 from_iter(self, Some(direction))
366 }
367}