diff options
author | 2022-02-11 23:39:41 +0700 | |
---|---|---|
committer | 2022-02-11 23:39:41 +0700 | |
commit | af122265f6663e429a3732ecdbbf2356688702b5 (patch) | |
tree | 2b612156421bd8657bc2c52de7e376fd4e9e58b9 /pure/src/widget/row.rs | |
parent | dd3e74e74de3a416d9d2dcfee051d78ba03dc540 (diff) | |
download | iced-af122265f6663e429a3732ecdbbf2356688702b5.tar.gz iced-af122265f6663e429a3732ecdbbf2356688702b5.tar.bz2 iced-af122265f6663e429a3732ecdbbf2356688702b5.zip |
Implement `Row` in `iced_pure`
Diffstat (limited to 'pure/src/widget/row.rs')
-rw-r--r-- | pure/src/widget/row.rs | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/pure/src/widget/row.rs b/pure/src/widget/row.rs new file mode 100644 index 00000000..2581b38a --- /dev/null +++ b/pure/src/widget/row.rs @@ -0,0 +1,223 @@ +use crate::flex; +use crate::widget::{Element, Tree, Widget}; + +use iced_native::event::{self, Event}; +use iced_native::layout::{self, Layout}; +use iced_native::mouse; +use iced_native::renderer; +use iced_native::{ + Alignment, Clipboard, Hasher, Length, Padding, Point, Rectangle, Shell, +}; + +use std::any::{self, Any}; + +pub struct Row<'a, Message, Renderer> { + spacing: u16, + padding: Padding, + width: Length, + height: Length, + align_items: Alignment, + children: Vec<Element<'a, Message, Renderer>>, +} + +impl<'a, Message, Renderer> Row<'a, Message, Renderer> { + pub fn new() -> Self { + Self::with_children(Vec::new()) + } + + pub fn with_children( + children: Vec<Element<'a, Message, Renderer>>, + ) -> Self { + Row { + spacing: 0, + padding: Padding::ZERO, + width: Length::Shrink, + height: Length::Shrink, + align_items: Alignment::Start, + children, + } + } + + pub fn spacing(mut self, units: u16) -> Self { + self.spacing = units; + self + } + + pub fn padding<P: Into<Padding>>(mut self, padding: P) -> Self { + self.padding = padding.into(); + self + } + + pub fn width(mut self, width: Length) -> Self { + self.width = width; + self + } + + pub fn height(mut self, height: Length) -> Self { + self.height = height; + self + } + + pub fn align_items(mut self, align: Alignment) -> Self { + self.align_items = align; + self + } + + pub fn push( + mut self, + child: impl Into<Element<'a, Message, Renderer>>, + ) -> Self { + self.children.push(child.into()); + self + } +} + +impl<'a, Message, Renderer> Widget<Message, Renderer> + for Row<'a, Message, Renderer> +where + Renderer: iced_native::Renderer, +{ + fn tag(&self) -> any::TypeId { + struct Marker; + any::TypeId::of::<Marker>() + } + + fn state(&self) -> Box<dyn Any> { + Box::new(()) + } + + fn children(&self) -> &[Element<Message, Renderer>] { + &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); + + flex::resolve( + flex::Axis::Horizontal, + renderer, + &limits, + self.padding, + self.spacing as f32, + self.align_items, + &self.children, + ) + } + + 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, + 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, + style, + layout, + cursor_position, + viewport, + ); + } + } + + fn hash_layout(&self, state: &mut Hasher) { + use std::hash::Hash; + + self.tag().hash(state); + self.width.hash(state); + self.height.hash(state); + self.align_items.hash(state); + self.spacing.hash(state); + self.padding.hash(state); + + for child in &self.children { + child.as_widget().hash_layout(state); + } + } +} + +impl<'a, Message, Renderer> Into<Element<'a, Message, Renderer>> + for Row<'a, Message, Renderer> +where + Message: 'static, + Renderer: iced_native::Renderer + 'static, +{ + fn into(self) -> Element<'a, Message, Renderer> { + Element::new(self) + } +} |