//! Distribute content horizontally. use crate::event::{self, Event}; use crate::layout::{self, Layout}; use crate::mouse; use crate::overlay; use crate::renderer; use crate::widget::{self, Operation, Tree}; use crate::{ Alignment, Clipboard, Element, Length, Padding, Point, Rectangle, Shell, Widget, }; /// A container that distributes its contents horizontally. #[allow(missing_debug_implementations)] pub struct Row<'a, Message, Renderer> { id: Option, spacing: u16, padding: Padding, width: Length, height: Length, align_items: Alignment, children: Vec>, } impl<'a, Message, Renderer> Row<'a, Message, Renderer> { /// Creates an empty [`Row`]. pub fn new() -> Self { Self::with_children(Vec::new()) } /// Creates a [`Row`] with the given elements. pub fn with_children( children: Vec>, ) -> Self { Row { id: None, spacing: 0, padding: Padding::ZERO, width: Length::Shrink, height: Length::Shrink, align_items: Alignment::Start, children, } } /// Sets the [`Id`] of the [`Row`]. pub fn id(mut self, id: Id) -> Self { self.id = Some(id); self } /// Sets the horizontal spacing _between_ elements. /// /// Custom margins per element do not exist in iced. You should use this /// method instead! While less flexible, it helps you keep spacing between /// elements consistent. pub fn spacing(mut self, units: u16) -> Self { self.spacing = units; self } /// Sets the [`Padding`] of the [`Row`]. pub fn padding>(mut self, padding: P) -> Self { self.padding = padding.into(); self } /// Sets the width of the [`Row`]. pub fn width(mut self, width: Length) -> Self { self.width = width; self } /// Sets the height of the [`Row`]. pub fn height(mut self, height: Length) -> Self { self.height = height; self } /// Sets the vertical alignment of the contents of the [`Row`] . pub fn align_items(mut self, align: Alignment) -> Self { self.align_items = align; self } /// Adds an [`Element`] to the [`Row`]. pub fn push( mut self, child: impl Into>, ) -> Self { self.children.push(child.into()); self } } impl<'a, Message, Renderer> Default for Row<'a, Message, Renderer> { fn default() -> Self { Self::new() } } impl<'a, Message, Renderer> Widget for Row<'a, Message, Renderer> where Renderer: crate::Renderer, { fn children(&self) -> Vec { self.children.iter().map(Tree::new).collect() } fn diff(&self, tree: &mut Tree) { tree.diff_children(&self.children) } fn width(&self) -> Length { self.width } fn height(&self) -> Length { self.height } fn layout( &self, renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { let limits = limits.width(self.width).height(self.height); layout::flex::resolve( layout::flex::Axis::Horizontal, renderer, &limits, self.padding, self.spacing as f32, self.align_items, &self.children, ) } fn operate( &self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn Operation, ) { operation.container( self.id.as_ref().map(|id| &id.0), &mut |operation| { self.children .iter() .zip(&mut tree.children) .zip(layout.children()) .for_each(|((child, state), layout)| { child .as_widget() .operate(state, layout, renderer, operation); }) }, ); } fn on_event( &mut self, tree: &mut Tree, event: Event, layout: Layout<'_>, cursor_position: Point, renderer: &Renderer, clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { self.children .iter_mut() .zip(&mut tree.children) .zip(layout.children()) .map(|((child, state), layout)| { child.as_widget_mut().on_event( state, event.clone(), layout, cursor_position, renderer, clipboard, shell, ) }) .fold(event::Status::Ignored, event::Status::merge) } fn mouse_interaction( &self, tree: &Tree, layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, renderer: &Renderer, ) -> mouse::Interaction { self.children .iter() .zip(&tree.children) .zip(layout.children()) .map(|((child, state), layout)| { child.as_widget().mouse_interaction( state, layout, cursor_position, viewport, renderer, ) }) .max() .unwrap_or_default() } fn draw( &self, tree: &Tree, renderer: &mut Renderer, theme: &Renderer::Theme, style: &renderer::Style, layout: Layout<'_>, cursor_position: Point, viewport: &Rectangle, ) { for ((child, state), layout) in self .children .iter() .zip(&tree.children) .zip(layout.children()) { child.as_widget().draw( state, renderer, theme, style, layout, cursor_position, viewport, ); } } fn overlay<'b>( &'b mut self, tree: &'b mut Tree, layout: Layout<'_>, renderer: &Renderer, ) -> Option> { overlay::from_children(&mut self.children, tree, layout, renderer) } } impl<'a, Message, Renderer> From> for Element<'a, Message, Renderer> where Message: 'a, Renderer: crate::Renderer + 'a, { fn from(row: Row<'a, Message, Renderer>) -> Self { Self::new(row) } } /// The identifier of a [`Row`]. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Id(widget::Id); impl Id { /// Creates a custom [`Id`]. pub fn new(id: impl Into>) -> Self { Self(widget::Id::new(id)) } /// Creates a unique [`Id`]. /// /// This function produces a different [`Id`] every time it is called. pub fn unique() -> Self { Self(widget::Id::unique()) } } impl From for widget::Id { fn from(id: Id) -> Self { id.0 } }