Something went wrong. Try again.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475const std = @import("std");const vaxis = @import("vaxis");const vxfw = vaxis.vxfw;
const Scrollbar = @This();
/// character to use for the scrollbarconst character: vaxis.Cell.Character = .{ .grapheme = "▐", .width = 1 };const empty: vaxis.Cell = .{ .char = character, .style = .{ .fg = .{ .index = 8 } } };
/// style to draw the bar character withstyle: vaxis.Style = .{},
/// The index of the bottom-most item, with 0 being "at the bottom"bottom: u16 = 0,
/// total items in the listtotal: u16,
/// total items that fit within the view areaview_size: u16,
fn widget(self: *Scrollbar) vxfw.Widget { return .{ .userdata = self, .drawFn = drawFn, };}
fn drawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) std.mem.Allocator.Error!vxfw.Surface { const self: *Scrollbar = @ptrCast(@alignCast(ptr)); return self.draw(ctx);}
pub fn draw(self: *Scrollbar, ctx: vxfw.DrawContext) std.mem.Allocator.Error!vxfw.Surface { const max = ctx.max.size(); if (max.width == 0 or max.height == 0) { return .{ .size = .{ .width = 0, .height = 0 }, .widget = self.widget(), .buffer = &.{}, .children = &.{}, }; }
const surface = try vxfw.Surface.init( ctx.arena, self.widget(), .{ .width = 2, .height = max.height }, );
// don't draw when 0 items if (self.total < 1) return surface;
// don't draw when all items can be shown if (self.view_size >= self.total) return surface;
@memset(surface.buffer, empty);
// (view_size / total) * window height = size of the scroll bar const premul1 = std.math.mulWide(u16, self.view_size, max.height); const bar_height = @max(std.math.divCeil(usize, premul1, self.total) catch unreachable, 1);
// Premultiply. We use mulWide to ensure we never overflow const premul2 = std.math.mulWide(u16, self.bottom, max.height); // The row of the last cell of the bottom of the bar const bar_bottom = (max.height - 1) -| (std.math.divCeil(usize, premul2, self.total) catch unreachable);
var i: usize = 0; while (i <= bar_height) : (i += 1) surface.writeCell(0, @intCast(bar_bottom -| i), .{ .char = character, .style = self.style });
return surface;}