1use crate::event::{self, Event};
3use crate::layout::{self, Layout};
4use crate::mouse;
5use crate::overlay;
6use crate::renderer;
7use crate::widget::{Operation, Tree};
8use crate::{
9 Alignment, Clipboard, Element, Length, Padding, Pixels, Point, Rectangle,
10 Shell, Widget,
11};
12
13#[allow(missing_debug_implementations)]
15pub struct Row<'a, Message, Renderer> {
16 spacing: f32,
17 padding: Padding,
18 width: Length,
19 height: Length,
20 align_items: Alignment,
21 children: Vec<Element<'a, Message, Renderer>>,
22}
23
24impl<'a, Message, Renderer> Row<'a, Message, Renderer> {
25 pub fn new() -> Self {
27 Self::with_children(Vec::new())
28 }
29
30 pub fn with_children(
32 children: Vec<Element<'a, Message, Renderer>>,
33 ) -> Self {
34 Row {
35 spacing: 0.0,
36 padding: Padding::ZERO,
37 width: Length::Shrink,
38 height: Length::Shrink,
39 align_items: Alignment::Start,
40 children,
41 }
42 }
43
44 pub fn spacing(mut self, amount: impl Into<Pixels>) -> Self {
50 self.spacing = amount.into().0;
51 self
52 }
53
54 pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self {
56 self.padding = padding.into();
57 self
58 }
59
60 pub fn width(mut self, width: impl Into<Length>) -> Self {
62 self.width = width.into();
63 self
64 }
65
66 pub fn height(mut self, height: impl Into<Length>) -> Self {
68 self.height = height.into();
69 self
70 }
71
72 pub fn align_items(mut self, align: Alignment) -> Self {
74 self.align_items = align;
75 self
76 }
77
78 pub fn push(
80 mut self,
81 child: impl Into<Element<'a, Message, Renderer>>,
82 ) -> Self {
83 self.children.push(child.into());
84 self
85 }
86}
87
88impl<'a, Message, Renderer> Default for Row<'a, Message, Renderer> {
89 fn default() -> Self {
90 Self::new()
91 }
92}
93
94impl<'a, Message, Renderer> Widget<Message, Renderer>
95 for Row<'a, Message, Renderer>
96where
97 Renderer: crate::Renderer,
98{
99 fn children(&self) -> Vec<Tree> {
100 self.children.iter().map(Tree::new).collect()
101 }
102
103 fn diff(&self, tree: &mut Tree) {
104 tree.diff_children(&self.children)
105 }
106
107 fn width(&self) -> Length {
108 self.width
109 }
110
111 fn height(&self) -> Length {
112 self.height
113 }
114
115 fn layout(
116 &self,
117 renderer: &Renderer,
118 limits: &layout::Limits,
119 ) -> layout::Node {
120 let limits = limits.width(self.width).height(self.height);
121
122 layout::flex::resolve(
123 layout::flex::Axis::Horizontal,
124 renderer,
125 &limits,
126 self.padding,
127 self.spacing,
128 self.align_items,
129 &self.children,
130 )
131 }
132
133 fn operate(
134 &self,
135 tree: &mut Tree,
136 layout: Layout<'_>,
137 renderer: &Renderer,
138 operation: &mut dyn Operation<Message>,
139 ) {
140 operation.container(None, &mut |operation| {
141 self.children
142 .iter()
143 .zip(&mut tree.children)
144 .zip(layout.children())
145 .for_each(|((child, state), layout)| {
146 child
147 .as_widget()
148 .operate(state, layout, renderer, operation);
149 })
150 });
151 }
152
153 fn on_event(
154 &mut self,
155 tree: &mut Tree,
156 event: Event,
157 layout: Layout<'_>,
158 cursor_position: Point,
159 renderer: &Renderer,
160 clipboard: &mut dyn Clipboard,
161 shell: &mut Shell<'_, Message>,
162 ) -> event::Status {
163 self.children
164 .iter_mut()
165 .zip(&mut tree.children)
166 .zip(layout.children())
167 .map(|((child, state), layout)| {
168 child.as_widget_mut().on_event(
169 state,
170 event.clone(),
171 layout,
172 cursor_position,
173 renderer,
174 clipboard,
175 shell,
176 )
177 })
178 .fold(event::Status::Ignored, event::Status::merge)
179 }
180
181 fn mouse_interaction(
182 &self,
183 tree: &Tree,
184 layout: Layout<'_>,
185 cursor_position: Point,
186 viewport: &Rectangle,
187 renderer: &Renderer,
188 ) -> mouse::Interaction {
189 self.children
190 .iter()
191 .zip(&tree.children)
192 .zip(layout.children())
193 .map(|((child, state), layout)| {
194 child.as_widget().mouse_interaction(
195 state,
196 layout,
197 cursor_position,
198 viewport,
199 renderer,
200 )
201 })
202 .max()
203 .unwrap_or_default()
204 }
205
206 fn draw(
207 &self,
208 tree: &Tree,
209 renderer: &mut Renderer,
210 theme: &Renderer::Theme,
211 style: &renderer::Style,
212 layout: Layout<'_>,
213 cursor_position: Point,
214 viewport: &Rectangle,
215 ) {
216 for ((child, state), layout) in self
217 .children
218 .iter()
219 .zip(&tree.children)
220 .zip(layout.children())
221 {
222 child.as_widget().draw(
223 state,
224 renderer,
225 theme,
226 style,
227 layout,
228 cursor_position,
229 viewport,
230 );
231 }
232 }
233
234 fn overlay<'b>(
235 &'b mut self,
236 tree: &'b mut Tree,
237 layout: Layout<'_>,
238 renderer: &Renderer,
239 ) -> Option<overlay::Element<'b, Message, Renderer>> {
240 overlay::from_children(&mut self.children, tree, layout, renderer)
241 }
242}
243
244impl<'a, Message, Renderer> From<Row<'a, Message, Renderer>>
245 for Element<'a, Message, Renderer>
246where
247 Message: 'a,
248 Renderer: crate::Renderer + 'a,
249{
250 fn from(row: Row<'a, Message, Renderer>) -> Self {
251 Self::new(row)
252 }
253}