/// FlexLayout — the underlying flex engine for VStack, HStack. /// /// This is the power behind the stacks. Most developers use VStack/HStack /// directly; FlexLayout is available when you need full control. /// Direction of the flex axis. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum FlexDirection { /// Children arranged top-to-bottom (VStack). Column, /// Children arranged left-to-right (HStack) — respects RTL automatically. Row, /// Like Column, but children wrap to new columns when they overflow. ColumnWrap, /// Like Row, but children wrap to new rows when they overflow. RowWrap, } impl FlexDirection { pub fn is_horizontal(&self) -> bool { matches!(self, FlexDirection::Row | FlexDirection::RowWrap) } pub fn is_vertical(&self) -> bool { matches!(self, FlexDirection::Column | FlexDirection::ColumnWrap) } pub fn wraps(&self) -> bool { matches!( self, FlexDirection::ColumnWrap | FlexDirection::RowWrap ) } } /// Alignment along the cross axis. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum CrossAxisAlignment { /// Stretch children to fill the cross axis. Stretch, /// Align children to the start of the cross axis. Start, /// Center children on the cross axis. Center, /// Align children to the end of the cross axis. End, /// Align text baselines (horizontal stacks only). Baseline, } /// Alignment along the main axis. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MainAxisAlignment { /// Pack children toward the start. Start, /// Center children. Center, /// Pack children toward the end. End, /// Distribute space between children. SpaceBetween, /// Distribute space around children. SpaceAround, /// Distribute space evenly around children. SpaceEvenly, } /// How much space the main axis should occupy. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MainAxisSize { /// Shrink to minimum size needed. Min, /// Expand to fill all available space. Max, } /// Logical horizontal alignment (RTL-aware). #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum HAlign { /// Toward the reading-start (left in LTR, right in RTL). Leading, Center, /// Toward the reading-end (right in LTR, left in RTL). Trailing, } /// Vertical alignment. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum VAlign { Top, Center, Bottom, Baseline, } /// Full flex layout specification. #[derive(Debug, Clone)] pub struct FlexLayout { pub direction: FlexDirection, pub main_axis_alignment: MainAxisAlignment, pub cross_axis_alignment: CrossAxisAlignment, pub main_axis_size: MainAxisSize, /// Gap between children in dp. pub gap: u32, } impl FlexLayout { /// VStack defaults (column, wrapping, leading-aligned). pub fn vstack(spacing: u32, wrap: bool) -> Self { Self { direction: if wrap { FlexDirection::ColumnWrap } else { FlexDirection::Column }, main_axis_alignment: MainAxisAlignment::Start, cross_axis_alignment: CrossAxisAlignment::Stretch, main_axis_size: MainAxisSize::Max, gap: spacing, } } /// HStack defaults (row, wrapping, center-aligned vertically). pub fn hstack(spacing: u32, wrap: bool) -> Self { Self { direction: if wrap { FlexDirection::RowWrap } else { FlexDirection::Row }, main_axis_alignment: MainAxisAlignment::Start, cross_axis_alignment: CrossAxisAlignment::Center, main_axis_size: MainAxisSize::Max, gap: spacing, } } } #[cfg(test)] mod tests { use super::*; #[test] fn flex_direction_horizontal() { assert!(FlexDirection::Row.is_horizontal()); assert!(FlexDirection::RowWrap.is_horizontal()); assert!(!FlexDirection::Column.is_horizontal()); } #[test] fn flex_direction_vertical() { assert!(FlexDirection::Column.is_vertical()); assert!(!FlexDirection::Row.is_vertical()); } #[test] fn flex_direction_wraps() { assert!(FlexDirection::RowWrap.wraps()); assert!(!FlexDirection::Row.wraps()); } #[test] fn vstack_layout_defaults() { let layout = FlexLayout::vstack(8, true); assert!(layout.direction.is_vertical()); assert!(layout.direction.wraps()); assert_eq!(layout.gap, 8); } #[test] fn hstack_layout_defaults() { let layout = FlexLayout::hstack(16, false); assert!(layout.direction.is_horizontal()); assert!(!layout.direction.wraps()); assert_eq!(layout.gap, 16); assert_eq!(layout.cross_axis_alignment, CrossAxisAlignment::Center); } }