summaryrefslogtreecommitdiff
path: root/src/body_layer.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 13:42:03 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit29e734cf91ffe5f4cca8b40a54aad91fff464a82 (patch)
tree384056b816943fcff95a45d42cd1fd4be1fe6f1d /src/body_layer.zig
parente11048c20a50b67841e648a4d5ddd7490bc9c9b7 (diff)
downloadpardes-29e734cf91ffe5f4cca8b40a54aad91fff464a82.tar.gz
pardes-29e734cf91ffe5f4cca8b40a54aad91fff464a82.zip
Place every part of the frame once, before painting it
draw.place builds the Surface's region list at the head of render: the page; each pane's grip, tag rows, body, rail with its thumb, and notice chips; each column's grip and tag; the workspace tag. The painters read their geometry from it instead of working it out again: the grid's notice chips and the notice layers share one chip rectangle, the rails (file, terminal, image, PDF page) paint the placed thumb (a native PDF measures its own into the region as it places its pages), and the body, tag, notice and column layers take their viewports from their regions. A collapsed pane places only its grip and tag. The column-move rail's one-cell clip of the layers under it is now a region field set in place, not a mutation of the built layers. No behaviour change; a test checks every region against the old geometry, the painted rail and the layer viewports across tag bottom, column tags, notices, a collapsed pane and a multi-line tag.
Diffstat (limited to 'src/body_layer.zig')
-rw-r--r--src/body_layer.zig37
1 files changed, 9 insertions, 28 deletions
diff --git a/src/body_layer.zig b/src/body_layer.zig
index db4d9524..2b6ae773 100644
--- a/src/body_layer.zig
+++ b/src/body_layer.zig
@@ -279,7 +279,7 @@ pub fn renderBodyLayer(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rec
@memset(temporary_cells, .{});
var temporary: Surface = .{ .cols = r.w, .rows = @intCast(logical_rows + pane.tag_rows), .cells = temporary_cells };
const synthetic: Rect = .{ .x = 0, .y = 0, .w = r.w, .h = @intCast(logical_rows + pane.tag_rows) };
- try renderBody(p, &temporary, arena, pane, synthetic, id, id == p.active, false);
+ try renderBody(p, &temporary, arena, pane, synthetic, id, id == p.active, null);
const first_row: usize = if (p.settings.tag_bottom) 0 else pane.tag_rows;
for (0..logical_rows) |row| {
const start = (row + first_row) * r.w + config.GUTTER;
@@ -287,7 +287,8 @@ pub fn renderBodyLayer(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rec
}
layer.pane = @intCast(id);
layer.serial = pane.serial;
- layer.viewport = .{ .x = r.x + config.GUTTER, .y = p.bodyTop(pane, r), .w = width, .h = viewport_rows };
+ const body = p.surface.region(.body, id).?;
+ layer.viewport = .{ .x = body.rect.x, .y = body.rect.y, .w = body.rect.w - body.clip, .h = body.rect.h };
layer.cols = width;
layer.rows = @intCast(logical_rows);
layer.context_rows = pane.context_rows;
@@ -299,7 +300,7 @@ pub fn renderBodyLayer(p: *Pardes, arena: std.mem.Allocator, pane: *Pane, r: Rec
}
}
-pub fn renderBody(p: *Pardes, s: *Surface, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: usize, active: bool, scrollbar: bool) !void {
+pub fn renderBody(p: *Pardes, s: *Surface, arena: std.mem.Allocator, pane: *Pane, r: Rect, id: usize, active: bool, rail: ?pardes.Region) !void {
const th = p.theme();
const chrome = p.chromeTheme();
const tx = r.x + config.GUTTER;
@@ -501,34 +502,14 @@ pub fn renderBody(p: *Pardes, s: *Surface, arena: std.mem.Allocator, pane: *Pane
}
}
- if (scrollbar and body_h > 0) {
+ if (rail) |bar| if (bar.rect.h > 0) {
// The rail covers the notice bands too: nothing else paints those
// two gutter columns, so a gap there keeps the frame-wide border
// fill and reads as a notch cut out of the scrollbar.
- const rail_h = r.h -| pane.tag_rows;
- s.fill(r.x, body_y, 1, rail_h, .{ .bg = .{ .rgb = chrome.scroll_track } });
- s.fill(r.x + 1, body_y, 1, rail_h, .{ .bg = pane_bg });
- const sb: struct { total: usize, offset: usize, len: usize } = if (pane.file) |*f| .{
- .total = panes.File.nlines(p.gpa, f),
- .offset = f.scroll,
- .len = pane.rows,
- } else if (pane.pdfPage()) |page| .{
- .total = if (comptime pdf_enabled) pane.pdf.?.page_count else 1,
- .offset = page,
- .len = 1,
- } else blk: {
- const gsb = panes.Terminal.scrollbar(pane);
- break :blk .{ .total = gsb.total, .offset = gsb.offset, .len = gsb.len };
- };
- const track_h: usize = body_h;
- const total = if (sb.total == 0) 1 else sb.total;
- const len = @max(1, (track_h * @max(1, sb.len)) / total);
- const pos = (track_h * sb.offset) / total;
- var sy: usize = pos;
- while (sy < track_h and sy < pos + len) : (sy += 1) {
- s.fill(r.x, body_y + @as(u16, @intCast(sy)), 1, 1, .{ .bg = .{ .rgb = chrome.scroll_thumb } });
- }
- }
+ s.fill(bar.rect.x, bar.rect.y, 1, bar.rect.h, .{ .bg = .{ .rgb = chrome.scroll_track } });
+ s.fill(bar.rect.x + 1, bar.rect.y, 1, bar.rect.h, .{ .bg = pane_bg });
+ s.fill(bar.rect.x, bar.rect.y + bar.thumb_y, 1, bar.thumb_h, .{ .bg = .{ .rgb = chrome.scroll_thumb } });
+ };
}
pub fn bodyText(p: *Pardes, arena: std.mem.Allocator, pane: *Pane) ![]const u8 {