diff --git a/crates/yakui-core/src/types.rs b/crates/yakui-core/src/types.rs index 30fbbc78..c91ec574 100644 --- a/crates/yakui-core/src/types.rs +++ b/crates/yakui-core/src/types.rs @@ -59,9 +59,18 @@ pub enum MainAxisAlignment { /// /// For a top-down list, this is the bottom of the container. End, - // SpaceAround, - // SpaceBetween, - // SpaceEvenly, + + /// Spread the items evenly where the gap at the start and end of the container + /// is half the size of the gap between each adjacent item. + SpaceAround, + + /// Spread the items evenly with no gap at the start and the end of the container. + /// If there is only one item, it will be at the start. + SpaceBetween, + + /// Spread the items evenly where the gap at the start and end of the container + /// is the same size as the gap between each adjacent item. + SpaceEvenly, } /// Defines alignment for items within a container's main axis when there is space left. diff --git a/crates/yakui-widgets/src/widgets/list.rs b/crates/yakui-widgets/src/widgets/list.rs index 22505968..ef9c4d15 100644 --- a/crates/yakui-widgets/src/widgets/list.rs +++ b/crates/yakui-widgets/src/widgets/list.rs @@ -31,6 +31,7 @@ yakui::row(|| { #[non_exhaustive] pub struct List { pub direction: Direction, + /// Added space at the end of each item. pub item_spacing: f32, pub main_axis_size: MainAxisSize, pub main_axis_alignment: MainAxisAlignment, @@ -224,12 +225,41 @@ impl Widget for ListWidget { } // Finally, position all children based on the sizes calculated above. - let mut next_main = match self.props.main_axis_alignment { - MainAxisAlignment::Start => 0.0, - MainAxisAlignment::Center => (main_axis_size - total_main_axis_size) / 2.0, - MainAxisAlignment::End => main_axis_size - total_main_axis_size, + let (leading_space, mut between_space) = match self.props.main_axis_alignment { + MainAxisAlignment::Start => (0.0, 0.0), + MainAxisAlignment::Center => ((main_axis_size - total_main_axis_size) / 2.0, 0.0), + MainAxisAlignment::End => (main_axis_size - total_main_axis_size, 0.0), + MainAxisAlignment::SpaceAround => { + // avoid division by zero + if node.children.is_empty() { + (0.0, 0.0) + } else { + let between_space = + (main_axis_size - total_main_axis_size) / node.children.len() as f32; + (between_space * 0.5, between_space) + } + } + MainAxisAlignment::SpaceBetween => { + if node.children.len() <= 1 { + // We follow CSS spec and Flutter behavior (as the Flutter doc isn't explicit) + // of putting the first child at the start when there is only one + (0.0, 0.0) + } else { + let between_space = (main_axis_size - total_main_axis_size) + / (node.children.len() as f32 - 1.0); + (0.0, between_space) + } + } + MainAxisAlignment::SpaceEvenly => { + let between_space = + (main_axis_size - total_main_axis_size) / (node.children.len() as f32 + 1.0); + (between_space, between_space) + } other => unimplemented!("MainAxisAlignment::{other:?}"), }; + between_space += self.props.item_spacing; + + let mut next_main = leading_space; for &child_index in &node.children { let child = ctx.dom.get(child_index).unwrap(); @@ -251,7 +281,7 @@ impl Widget for ListWidget { child_layout.rect.set_pos(direction.vec2(next_main, cross)); next_main += child_main; - next_main += self.props.item_spacing; + next_main += between_space; } container_size diff --git a/crates/yakui/examples/main_alignment.rs b/crates/yakui/examples/main_alignment.rs index 6e25105f..1f65fea6 100644 --- a/crates/yakui/examples/main_alignment.rs +++ b/crates/yakui/examples/main_alignment.rs @@ -8,6 +8,9 @@ pub fn run(state: &mut ExampleState) { MainAxisAlignment::Start, MainAxisAlignment::Center, MainAxisAlignment::End, + MainAxisAlignment::SpaceBetween, + MainAxisAlignment::SpaceAround, + MainAxisAlignment::SpaceEvenly, ]; let index = (state.time.floor() as usize) % alignments.len();