#import "modules/std.sx"; #import "modules/math"; #import "ui/types.sx"; #import "ui/view.sx"; // VStack layout: measure all children, stack vertically // Width is constrained from parent; height is unspecified (children choose) layout_vstack :: (children: *List(ViewChild), bounds: Frame, spacing: f32, alignment: HAlignment) { n := children.len; if n == 0 { return; } content_width := bounds.size.width; y := bounds.origin.y; i := 0; while i < n { child := @children.items[i]; child_size := child.view.size_that_fits(ProposedSize.{ width = content_width, height = null }); x_offset := align_h(alignment, child_size.width, content_width); child.computed_frame = Frame.{ origin = Point.{ x = bounds.origin.x + x_offset, y = y }, size = child_size }; child.view.layout(child.computed_frame); y = y + child_size.height + spacing; i += 1; } } // HStack layout: measure all children, stack horizontally // Height is constrained from parent; width is unspecified (children choose) layout_hstack :: (children: *List(ViewChild), bounds: Frame, spacing: f32, alignment: VAlignment) { n := children.len; if n == 0 { return; } content_height := bounds.size.height; x := bounds.origin.x; i := 0; while i < n { child := @children.items[i]; child_size := child.view.size_that_fits(ProposedSize.{ width = null, height = content_height }); y_offset := align_v(alignment, child_size.height, content_height); child.computed_frame = Frame.{ origin = Point.{ x = x, y = bounds.origin.y + y_offset }, size = child_size }; child.view.layout(child.computed_frame); x = x + child_size.width + spacing; i += 1; } } // ZStack layout: all children get same bounds, aligned layout_zstack :: (children: *List(ViewChild), bounds: Frame, alignment: Alignment) { n := children.len; if n == 0 { return; } proposal := ProposedSize.{ width = bounds.size.width, height = bounds.size.height }; i := 0; while i < n { child := @children.items[i]; child_size := child.view.size_that_fits(proposal); x_offset := align_h(alignment.h, child_size.width, bounds.size.width); y_offset := align_v(alignment.v, child_size.height, bounds.size.height); child.computed_frame = Frame.{ origin = Point.{ x = bounds.origin.x + x_offset, y = bounds.origin.y + y_offset }, size = child_size }; child.view.layout(child.computed_frame); i += 1; } } // Measure helpers — compute stack size from children measure_vstack :: (children: *List(ViewChild), proposal: ProposedSize, spacing: f32) -> Size { n := children.len; if n == 0 { return Size.zero(); } max_width : f32 = 0.0; total_height : f32 = 0.0; // Measure children: constrain width, leave height unspecified child_proposal := ProposedSize.{ width = proposal.width, height = null }; i := 0; while i < n { child_size := children.items[i].view.size_that_fits(child_proposal); children.items[i].computed_frame.size = child_size; if child_size.width > max_width { max_width = child_size.width; } total_height = total_height + child_size.height; i += 1; } total_height = total_height + spacing * xx (n - 1); result_width := min(proposal.width ?? max_width, max_width); Size.{ width = result_width, height = total_height }; } measure_hstack :: (children: *List(ViewChild), proposal: ProposedSize, spacing: f32) -> Size { n := children.len; if n == 0 { return Size.zero(); } total_width : f32 = 0.0; max_height : f32 = 0.0; // Measure children: constrain height, leave width unspecified child_proposal := ProposedSize.{ width = null, height = proposal.height }; i := 0; while i < n { child_size := children.items[i].view.size_that_fits(child_proposal); children.items[i].computed_frame.size = child_size; total_width = total_width + child_size.width; if child_size.height > max_height { max_height = child_size.height; } i += 1; } total_width = total_width + spacing * xx (n - 1); result_height := min(proposal.height ?? max_height, max_height); Size.{ width = total_width, height = result_height }; } measure_zstack :: (children: *List(ViewChild), proposal: ProposedSize) -> Size { n := children.len; if n == 0 { return Size.zero(); } max_width : f32 = 0.0; max_height : f32 = 0.0; i := 0; while i < n { child_size := children.items[i].view.size_that_fits(proposal); children.items[i].computed_frame.size = child_size; if child_size.width > max_width { max_width = child_size.width; } if child_size.height > max_height { max_height = child_size.height; } i += 1; } Size.{ width = max_width, height = max_height }; }