const std = @import("std"); pub const default_max_picker_rows: u16 = 6; pub const Window = struct { start: usize, end: usize, }; pub fn centered(count: usize, selected: usize, max_rows: u16) Window { if (count == 0 or max_rows == 0) return .{ .start = 0, .end = 0 }; const rows: usize = max_rows; if (count <= rows) return .{ .start = 0, .end = count }; var start = if (selected >= rows / 2) selected - rows / 2 else 0; if (start + rows > count) start = count - rows; return .{ .start = start, .end = start + rows }; } pub fn edgeFromSelection(count: usize, selected: usize, max_rows: u16) Window { if (count == 0 or max_rows == 0) return .{ .start = 0, .end = 0 }; const rows: usize = max_rows; if (count <= rows) return .{ .start = 0, .end = count }; const start = if (selected >= rows) selected - rows + 1 else 0; return .{ .start = start, .end = @min(start + rows, count) }; } pub fn edgeFromStart(count: usize, start: usize, max_rows: u16) Window { if (count == 0 or max_rows == 0) return .{ .start = 0, .end = 0 }; const rows: usize = max_rows; if (count <= rows) return .{ .start = 0, .end = count }; const clamped_start = @min(start, count - rows); return .{ .start = clamped_start, .end = clamped_start + rows }; } pub fn updateEdgeStart(current_start: usize, count: usize, selected: usize, max_rows: u16) usize { if (count == 0 or max_rows == 0) return 0; const rows: usize = max_rows; if (count <= rows) return 0; const clamped_selected = @min(selected, count - 1); var start = @min(current_start, count - rows); if (clamped_selected < start) { start = clamped_selected; } else if (clamped_selected >= start + rows) { start = clamped_selected - rows + 1; } return start; } test "edge window start lets selection move back up before reverse scrolling" { const rows: u16 = 6; var start = updateEdgeStart(0, 11, 5, rows); try std.testing.expectEqual(@as(usize, 0), start); try std.testing.expectEqual(@as(usize, 5), 5 - start); start = updateEdgeStart(start, 11, 6, rows); try std.testing.expectEqual(@as(usize, 1), start); try std.testing.expectEqual(@as(usize, 5), 6 - start); start = updateEdgeStart(start, 11, 5, rows); try std.testing.expectEqual(@as(usize, 1), start); try std.testing.expectEqual(@as(usize, 4), 5 - start); }