tangled
alpha
login
or
join now
rockorager.dev
/
comlink
2
fork
atom
an experimental irc client
2
fork
atom
overview
issues
pulls
pipelines
ui: draw scrollbar
rockorager.dev
1 year ago
2e738aa8
334db4d4
+60
-10
2 changed files
expand all
collapse all
unified
split
src
Scrollbar.zig
irc.zig
+40
-9
src/Scrollbar.zig
···
1
1
const std = @import("std");
2
2
const vaxis = @import("vaxis");
3
3
+
const vxfw = vaxis.vxfw;
3
4
4
5
const Scrollbar = @This();
5
6
···
10
11
style: vaxis.Style = .{},
11
12
12
13
/// The index of the bottom-most item, with 0 being "at the bottom"
13
13
-
bottom: usize = 0,
14
14
+
bottom: u16 = 0,
14
15
15
16
/// total items in the list
16
16
-
total: usize,
17
17
+
total: u16,
17
18
18
19
/// total items that fit within the view area
19
19
-
view_size: usize,
20
20
+
view_size: u16,
21
21
+
22
22
+
fn widget(self: *Scrollbar) vxfw.Widget {
23
23
+
return .{
24
24
+
.userdata = self,
25
25
+
.drawFn = drawFn,
26
26
+
};
27
27
+
}
28
28
+
29
29
+
fn drawFn(ptr: *anyopaque, ctx: vxfw.DrawContext) std.mem.Allocator.Error!vxfw.Surface {
30
30
+
const self: *Scrollbar = @ptrCast(@alignCast(ptr));
31
31
+
return self.draw(ctx);
32
32
+
}
33
33
+
34
34
+
pub fn draw(self: *Scrollbar, ctx: vxfw.DrawContext) std.mem.Allocator.Error!vxfw.Surface {
35
35
+
const max = ctx.max.size();
36
36
+
if (max.width == 0 or max.height == 0) {
37
37
+
return .{
38
38
+
.size = .{ .width = 0, .height = 0 },
39
39
+
.widget = self.widget(),
40
40
+
.buffer = &.{},
41
41
+
.children = &.{},
42
42
+
};
43
43
+
}
20
44
21
21
-
pub fn draw(self: Scrollbar, win: vaxis.Window) void {
45
45
+
const surface = try vxfw.Surface.init(
46
46
+
ctx.arena,
47
47
+
self.widget(),
48
48
+
.{ .width = 2, .height = max.height },
49
49
+
);
50
50
+
22
51
// don't draw when 0 items
23
23
-
if (self.total < 1) return;
52
52
+
if (self.total < 1) return surface;
24
53
25
54
// don't draw when all items can be shown
26
26
-
if (self.view_size >= self.total) return;
55
55
+
if (self.view_size >= self.total) return surface;
27
56
28
57
// (view_size / total) * window height = size of the scroll bar
29
29
-
const bar_height = @max(std.math.divCeil(usize, self.view_size * win.height, self.total) catch unreachable, 1);
58
58
+
const bar_height = @max(std.math.divCeil(usize, self.view_size * max.height, self.total) catch unreachable, 1);
30
59
31
60
// The row of the last cell of the bottom of the bar
32
32
-
const bar_bottom = (win.height - 1) -| (std.math.divCeil(usize, self.bottom * win.height, self.total) catch unreachable);
61
61
+
const bar_bottom = (max.height - 1) -| (std.math.divCeil(usize, self.bottom * max.height, self.total) catch unreachable);
33
62
34
63
var i: usize = 0;
35
64
while (i <= bar_height) : (i += 1)
36
36
-
win.writeCell(0, bar_bottom -| i, .{ .char = self.character, .style = self.style });
65
65
+
surface.writeCell(0, @intCast(bar_bottom -| i), .{ .char = self.character, .style = self.style });
66
66
+
67
67
+
return surface;
37
68
}
+20
-1
src/irc.zig
···
6
6
const zeit = @import("zeit");
7
7
const bytepool = @import("pool.zig");
8
8
9
9
+
const Scrollbar = @import("Scrollbar.zig");
9
10
const testing = std.testing;
10
11
const mem = std.mem;
11
12
const vxfw = vaxis.vxfw;
···
463
464
464
465
const msg_view_ctx = ctx.withConstraints(.{ .height = 0, .width = 0 }, .{
465
466
.height = max.height - 4,
466
466
-
.width = max.width,
467
467
+
.width = max.width - 1,
467
468
});
468
469
const message_view = try self.drawMessageView(msg_view_ctx);
469
470
try children.append(.{
470
471
.origin = .{ .row = 2, .col = 0 },
471
472
.surface = message_view,
473
473
+
});
474
474
+
475
475
+
const scrollbar_ctx = ctx.withConstraints(
476
476
+
ctx.min,
477
477
+
.{ .width = 1, .height = max.height - 4 },
478
478
+
);
479
479
+
480
480
+
var scrollbars: Scrollbar = .{
481
481
+
// Estimate number of lines per message
482
482
+
.total = @intCast(self.messages.items.len * 3),
483
483
+
.view_size = max.height - 4,
484
484
+
.bottom = self.scroll.offset,
485
485
+
};
486
486
+
const scrollbar_surface = try scrollbars.draw(scrollbar_ctx);
487
487
+
// Draw the text field
488
488
+
try children.append(.{
489
489
+
.origin = .{ .col = max.width - 1, .row = 2 },
490
490
+
.surface = scrollbar_surface,
472
491
});
473
492
474
493
// Draw the text field