lib/arrange/src/axis.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const types = @import("types.zig");
  2 
  3 const FlexDirection = types.FlexDirection;
  4 const Insets = types.Insets;
  5 const Node = types.Node;
  6 const Rect = types.Rect;
  7 const Size = types.Size;
  8 
  9 pub const Axis = enum {
 10     horizontal,
 11     vertical,
 12 };
 13 
 14 pub const AxisLimits = struct {
 15     min: f32 = 0,
 16     max: ?f32 = null,
 17 };
 18 
 19 pub const ResolvedInsets = struct {
 20     top: f32 = 0,
 21     left: f32 = 0,
 22     right: f32 = 0,
 23     bottom: f32 = 0,
 24 };
 25 
 26 pub fn constrainSize(node: *const Node, size: Size) Size {
 27     return .{
 28         .width = clampSize(node, .horizontal, size.width),
 29         .height = clampSize(node, .vertical, size.height),
 30     };
 31 }
 32 
 33 pub fn clampSize(node: *const Node, axis: Axis, value: f32) f32 {
 34     const limits = axisLimits(node, axis);
 35     var result = @max(nonNegative(value), limits.min);
 36     if (limits.max) |max_value| result = @min(result, max_value);
 37     return result;
 38 }
 39 
 40 pub fn axisLimits(node: *const Node, axis: Axis) AxisLimits {
 41     const constraints = node.style.constraints;
 42     const raw_min = switch (axis) {
 43         .horizontal => constraints.min_width,
 44         .vertical => constraints.min_height,
 45     };
 46     const raw_max = switch (axis) {
 47         .horizontal => constraints.max_width,
 48         .vertical => constraints.max_height,
 49     };
 50     const min = if (raw_min) |value| nonNegative(value) else 0;
 51     const max = if (raw_max) |value| @max(nonNegative(value), min) else null;
 52     return .{ .min = min, .max = max };
 53 }
 54 
 55 pub fn mainAxis(direction: FlexDirection) Axis {
 56     return switch (direction) {
 57         .row => .horizontal,
 58         .column => .vertical,
 59     };
 60 }
 61 
 62 pub fn crossAxis(direction: FlexDirection) Axis {
 63     return switch (direction) {
 64         .row => .vertical,
 65         .column => .horizontal,
 66     };
 67 }
 68 
 69 pub fn rectFromAxes(container: Rect, direction: FlexDirection, main_offset: f32, cross_offset: f32, main_size: f32, cross_size: f32) Rect {
 70     return switch (direction) {
 71         .row => .{
 72             .x = container.x + main_offset,
 73             .y = container.y + cross_offset,
 74             .width = main_size,
 75             .height = cross_size,
 76         },
 77         .column => .{
 78             .x = container.x + cross_offset,
 79             .y = container.y + main_offset,
 80             .width = cross_size,
 81             .height = main_size,
 82         },
 83     };
 84 }
 85 
 86 pub fn contentRect(rect: Rect, padding: Insets) Rect {
 87     const resolved = resolvedInsets(padding);
 88     return .{
 89         .x = rect.x + resolved.left,
 90         .y = rect.y + resolved.top,
 91         .width = @max(rect.width - resolved.left - resolved.right, 0),
 92         .height = @max(rect.height - resolved.top - resolved.bottom, 0),
 93     };
 94 }
 95 
 96 pub fn resolvedInsets(insets: Insets) ResolvedInsets {
 97     return .{
 98         .top = if (insets.top) |value| nonNegative(value) else 0,
 99         .left = if (insets.left) |value| nonNegative(value) else 0,
100         .right = if (insets.right) |value| nonNegative(value) else 0,
101         .bottom = if (insets.bottom) |value| nonNegative(value) else 0,
102     };
103 }
104 
105 pub fn mainSize(rect: Rect, direction: FlexDirection) f32 {
106     return switch (direction) {
107         .row => rect.width,
108         .column => rect.height,
109     };
110 }
111 
112 pub fn crossSize(rect: Rect, direction: FlexDirection) f32 {
113     return switch (direction) {
114         .row => rect.height,
115         .column => rect.width,
116     };
117 }
118 
119 pub fn nonNegative(value: f32) f32 {
120     return @max(value, 0);
121 }