diff options
Diffstat (limited to 'src/draw.zig')
| -rw-r--r-- | src/draw.zig | 90 |
1 files changed, 68 insertions, 22 deletions
diff --git a/src/draw.zig b/src/draw.zig index b596fc22..7d91ad31 100644 --- a/src/draw.zig +++ b/src/draw.zig @@ -192,7 +192,6 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { pane.context_row_limit = null; s.body_layers[id].rows = 0; try renderPane(p, s, arena, pane, p.rects[id], id, id == p.active); - try body_layer.renderBodyLayer(p, arena, pane, p.rects[id], id); } // Each notice once, as a tag layer, and the grid's chip a copy of it. for (s.regionList()) |region| { @@ -494,7 +493,7 @@ fn renderPane(p: *Pardes, s: *Surface, arena: std.mem.Allocator, pane: *Pane, r: return; } - try body_layer.renderBody(p, s, arena, pane, r, id, active, rail.*); + try body_layer.joinBody(p, s, arena, pane, r, id, active, rail.*); } /// The workspace and column tags: each line a tag layer, and the grid's @@ -716,25 +715,6 @@ fn joinPaneTag(p: *Pardes, s: *Surface, arena: std.mem.Allocator, pane: *Pane, r if (temporary.cursor) |cursor| if (cursor.x - TAG_TEXT_INSET < r.w - TAG_TEXT_INSET) { s.cursor = .{ .x = r.x + cursor.x, .y = region.rect.y + cursor.y, .bar = cursor.bar }; }; - // A sweep begun on the tag and dragged into the body shows on the body - // rows it crossed, which only the grid has. - const th = p.theme(); - const tx = r.x + TAG_TEXT_INSET; - const tw = r.w - TAG_TEXT_INSET; - const tag_y = region.rect.y; - const body_y = p.bodyTop(pane, r); - if (p.look_hover_preview) |preview| { - if (preview.pane == id and preview.serial == pane.serial) if (preview.sel) |sel| if (@min(sel.r0, sel.r1) < rows) { - const page_rgb = th.bg orelse th.tag_bg; - const preview_bg = colors.mix(page_rgb, colors.mix(page_rgb, th.sel_bg)); - body_layer.paintPointerSelection(p, s, pane, r, tx, tw, tag_y, body_y, sel, rows, preview_bg, null); - }; - } - for (pane.sel, 0..) |selection, button| { - if (selection.state == .none or (selection.state == .done and button != 0)) continue; - if (@min(selection.r0, selection.r1) >= rows) continue; - body_layer.paintPointerSelection(p, s, pane, r, tx, tw, tag_y, body_y, selection, rows, th.sel_bg, th.sel_fg); - } } /// A notice chip, painted once as a tag layer at the tagline's pitch, and the @@ -924,11 +904,27 @@ pub fn paintPaneTag(p: *Pardes, s: *Surface, arena: std.mem.Allocator, pane: *Pa if (col < tw) s.cursor = .{ .x = tx + @as(u16, @intCast(col)), .y = tag_y + @as(u16, @intCast(at.row)), .bar = mode == .insert }; } + // Pointer sweeps over the tag rows. A select sweep is the tag's own, in + // its selection colours; the look-hover affordance goes over it, and a + // middle or right sweep over both, tinted by its button the way the + // body tints it. for (pane.sel, 0..) |selection, button| { if (selection.state == .none or (selection.state == .done and button != 0)) continue; - if (@min(selection.r0, selection.r1) >= rows) continue; + if (button != pardes.sel_slot or @min(selection.r0, selection.r1) >= rows) continue; body_layer.paintPointerSelection(p, s, pane, r, tx, tw, tag_y, body_y, selection, 0, th.sel_bg, th.sel_fg); } + if (p.look_hover_preview) |preview| { + if (preview.pane == id and preview.serial == pane.serial) if (preview.sel) |sel| if (@min(sel.r0, sel.r1) < rows) { + const preview_bg = colors.mix(page_rgb, colors.mix(page_rgb, th.sel_bg)); + body_layer.paintPointerSelection(p, s, pane, r, tx, tw, tag_y, body_y, sel, 0, preview_bg, null); + }; + } + const sel_btn = body_layer.buttonTints(th); + for (pane.sel, 0..) |selection, button| { + if (selection.state == .none or (selection.state == .done and button != 0)) continue; + if (button == pardes.sel_slot or @min(selection.r0, selection.r1) >= rows) continue; + body_layer.paintPointerSelection(p, s, pane, r, tx, tw, tag_y, body_y, selection, 0, sel_btn[button], th.sel_fg); + } } test "place puts every part where the painters and layers put it, in every layout" { @@ -1036,3 +1032,53 @@ test "a wide glyph cut by a tag's or a notice's edge is joined into the grid as } } } + +test "a body with context rows is painted once, and the grid's rows are what a plain paint of it gives" { + if (comptime !@import("syntax.zig").enabled) return error.SkipZigTest; + const p = try Pardes.init(std.testing.allocator, .{ .tty_only = true, .cols = 60, .rows = 16 }); + defer p.deinit(); + const pane = try p.setTestFile("pub const Box = struct {\n pub fn run() void {\n" ++ (" // body line\n" ** 30) ++ " }\n};\n"); + p.gpa.free(pane.file.?.path); + pane.file.?.path = try p.gpa.dupe(u8, "/test.zig"); + if (!panes.File.supportsContext(pane)) return error.SkipZigTest; + pane.file.?.tree_context = true; + pane.file.?.scroll = 8; + var arena: std.heap.ArenaAllocator = .init(std.testing.allocator); + defer arena.deinit(); + for ([_]bool{ false, true }) |bottom| { + p.settings.tag_bottom = bottom; + // A selection and the cursor on body rows, painted in the one pass. + pane.body.cur_row = 12; + pane.body.cur_col = 3; + pane.body.vsel = .{ .active = true, .row = 10, .col = 2 }; + pane.body.mode = .normal; + p.sync(); + _ = arena.reset(.retain_capacity); + const s = try p.render(arena.allocator()); + const layer = &s.body_layers[0]; + try std.testing.expect(layer.context_rows > 0); + const body = s.region(.body, 0).?; + // The plain paint the grid used to take, of the same frame. + const cells = try arena.allocator().alloc(Cell, s.cells.len); + @memset(cells, .{}); + var plain: Surface = .{ .cols = s.cols, .rows = s.rows, .cells = cells }; + const saved = .{ pane.body_rows, pane.body_visible_rows, pane.context_row_limit }; + pane.body_rows = 0; + pane.body_visible_rows = 0; + pane.context_row_limit = null; + try body_layer.renderBody(p, &plain, arena.allocator(), pane, p.rects[0], 0, true, null, null); + pane.body_rows, pane.body_visible_rows, pane.context_row_limit = saved; + for (0..body.rect.h) |row| { + const y = body.rect.y + row; + for (0..body.rect.w) |col| { + const x = body.rect.x + col; + const got = s.cells[y * s.cols + x]; + const want = plain.cells[y * s.cols + x]; + try std.testing.expect(got.visuallyEqual(&want)); + } + } + try std.testing.expectEqual(plain.cursor, s.cursor); + // The layer's own rows run past the grid's. + try std.testing.expect(layer.rows > body.rect.h); + } +} |
