diff options
Diffstat (limited to 'src/draw.zig')
| -rw-r--r-- | src/draw.zig | 63 |
1 files changed, 45 insertions, 18 deletions
diff --git a/src/draw.zig b/src/draw.zig index 7cfe7554..4242a6e7 100644 --- a/src/draw.zig +++ b/src/draw.zig @@ -47,14 +47,7 @@ const NOTICE_LAYER_BASE = pardes.NOTICE_LAYER_BASE; /// painters below and every shell read these rectangles. pub fn place(p: *Pardes, s: *Surface) void { s.nregions = 0; - const add = struct { - fn region(surface: *Surface, r: Region) void { - std.debug.assert(surface.nregions < surface.regions.len); - surface.regions[surface.nregions] = r; - surface.nregions += 1; - } - }.region; - add(s, .{ .kind = .page, .rect = .{ .x = 0, .y = 0, .w = s.cols, .h = s.rows } }); + s.addRegion(.{ .kind = .page, .rect = .{ .x = 0, .y = 0, .w = s.cols, .h = s.rows } }); for (&p.panes, 0..) |*slot, id| { const pane = slot.* orelse continue; Messages.collectNotices(p, pane, p.rects[id], id); @@ -64,12 +57,12 @@ pub fn place(p: *Pardes, s: *Surface) void { const active = id == p.active; const tag_y = p.tagTop(pane, r); const body_y = p.bodyTop(pane, r); - add(s, .{ .kind = .grip, .owner = owner, .serial = pane.serial, .active = active, .rect = .{ .x = r.x, .y = tag_y, .w = config.GUTTER, .h = pane.tag_rows } }); - add(s, .{ .kind = .tag, .owner = owner, .serial = pane.serial, .active = active, .rect = .{ .x = r.x + config.GUTTER, .y = tag_y, .w = r.w - config.GUTTER, .h = pane.tag_rows } }); + s.addRegion(.{ .kind = .grip, .owner = owner, .serial = pane.serial, .active = active, .rect = .{ .x = r.x, .y = tag_y, .w = config.GUTTER, .h = pane.tag_rows } }); + s.addRegion(.{ .kind = .tag, .owner = owner, .serial = pane.serial, .active = active, .rect = .{ .x = r.x + config.GUTTER, .y = tag_y, .w = r.w - config.GUTTER, .h = pane.tag_rows } }); // A folded pane is its tag rows and nothing else. if (pane.collapsed) continue; const body_h = r.h -| pane.tag_rows; - add(s, .{ .kind = .body, .owner = owner, .serial = pane.serial, .active = active, .rect = .{ .x = r.x + config.GUTTER, .y = body_y, .w = r.w - config.GUTTER, .h = body_h } }); + s.addRegion(.{ .kind = .body, .owner = owner, .serial = pane.serial, .active = active, .rect = .{ .x = r.x + config.GUTTER, .y = body_y, .w = r.w - config.GUTTER, .h = body_h } }); var rail: Region = .{ .kind = .rail, .owner = owner, .serial = pane.serial, .active = active, .rect = .{ .x = r.x, .y = body_y, .w = config.GUTTER, .h = body_h } }; // An image's rail has no thumb; a native PDF's is measured as its // pages are placed (Pdf.draw); every other pane's is here. @@ -93,7 +86,7 @@ pub fn place(p: *Pardes, s: *Surface) void { rail.thumb_y = @intCast(@min(pos, track_h)); rail.thumb_h = @intCast(@min(len, track_h - rail.thumb_y)); } - add(s, rail); + s.addRegion(rail); // Each notice a chip at the right edge, one to a row in the order // collectNotices chose, as wide as its own message and no wider, so // the text beneath the rest of the row keeps reading as the file. @@ -106,7 +99,7 @@ pub fn place(p: *Pardes, s: *Surface) void { const chip = Messages.noticeCols(p, text, tw); if (chip == 0) continue; pane.notices.left[i] = tx + tw - chip; - add(s, .{ .kind = .notice, .owner = owner, .serial = pane.serial, .active = active, .notice = @intCast(i), .rect = .{ .x = tx + tw - chip, .y = body_y + @as(u16, pane.notices.row[i]), .w = chip, .h = BOX_H } }); + s.addRegion(.{ .kind = .notice, .owner = owner, .serial = pane.serial, .active = active, .notice = @intCast(i), .rect = .{ .x = tx + tw - chip, .y = body_y + @as(u16, pane.notices.row[i]), .w = chip, .h = BOX_H } }); } } const column_rows = p.columnBarHeight(); @@ -114,11 +107,16 @@ pub fn place(p: *Pardes, s: *Surface) void { if (p.col_w[c] == 0) continue; const active = if (layout.findPane(p, p.active)) |found| found.col == c else false; const inset = @min(TAG_TEXT_INSET, p.col_w[c]); - add(s, .{ .kind = .column_grip, .owner = @intCast(c), .serial = p.col_serial[c], .active = active, .rect = .{ .x = p.col_x[c], .y = p.topBarHeight(), .w = @min(config.GUTTER, p.col_w[c]), .h = column_rows } }); - add(s, .{ .kind = .column_tag, .owner = @intCast(c), .serial = p.col_serial[c], .active = active, .rect = .{ .x = p.col_x[c] + inset, .y = p.topBarHeight(), .w = p.col_w[c] - inset, .h = column_rows } }); + s.addRegion(.{ .kind = .column_grip, .owner = @intCast(c), .serial = p.col_serial[c], .active = active, .rect = .{ .x = p.col_x[c], .y = p.topBarHeight(), .w = @min(config.GUTTER, p.col_w[c]), .h = column_rows } }); + s.addRegion(.{ .kind = .column_tag, .owner = @intCast(c), .serial = p.col_serial[c], .active = active, .rect = .{ .x = p.col_x[c] + inset, .y = p.topBarHeight(), .w = p.col_w[c] - inset, .h = column_rows } }); }; + const active_col = if (layout.findPane(p, p.active)) |found| found.col else null; + for (0..p.ncol) |c| { + if (p.col_w[c] == 0) continue; + s.addRegion(.{ .kind = .column, .owner = @intCast(c), .serial = p.col_serial[c], .active = active_col == c, .rect = .{ .x = p.col_x[c], .y = p.topBarHeight(), .w = p.col_w[c], .h = s.rows -| p.topBarHeight() } }); + } if (p.settings.workspace_tag) - add(s, .{ .kind = .workspace_tag, .rect = .{ .x = 0, .y = 0, .w = s.cols, .h = p.topBarHeight() } }); + s.addRegion(.{ .kind = .workspace_tag, .rect = .{ .x = 0, .y = 0, .w = s.cols, .h = p.topBarHeight() } }); // A column carried to the window's right edge shows where it lands as a // rail in the last cell: the layers under it stop a cell short. if (p.drag == .column_move) rail: { @@ -176,8 +174,20 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { s.previous_cells = &.{}; s.previous_body_layers = &.{}; s.previous_tag_layers = &.{}; + s.previous_regions = &.{}; s.cell_diffs = &.{}; const chrome = p.chromeTheme(); + s.chrome = .{ + .page = p.theme().bg, + .fg = p.theme().fg, + .border = chrome.border, + .topbar_rule = config.gui_topbar_pane_border_rgb orelse chrome.border, + .tag_bg = chrome.tag_bg, + .tag_focus_bg = if (p.settings.focus_tint) chrome.tag_active_bg else chrome.tag_bg, + .tag_fg = chrome.tag_fg, + .scroll_track = chrome.scroll_track, + .scroll_thumb = chrome.scroll_thumb, + }; place(p, s); // Separators have their own role; a scrollbar need not frame the page. const whole = s.regions[0].rect; @@ -203,16 +213,20 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { if (d.cur_x < s.cols) { var row: u16 = p.topBarHeight(); while (row < s.rows) : (row += 1) s.overlayDash(d.cur_x, row, "╎"); + s.addRegion(.{ .kind = .guide, .rect = .{ .x = d.cur_x, .y = p.topBarHeight(), .w = 1, .h = s.rows -| p.topBarHeight() } }); } if (d.corner) |k| if (d.cur_y < s.rows) { - var col = if (k.col == d.left_col) p.col_x[k.col] else d.cur_x +| 1; + const first = if (k.col == d.left_col) p.col_x[k.col] else d.cur_x +| 1; const end = if (k.col == d.left_col) d.cur_x else p.col_x[k.col] +| p.col_w[k.col] -| 1; + var col = first; while (col <= end and col < s.cols) : (col += 1) s.overlayDash(col, d.cur_y, "╌"); + if (col > first) s.addRegion(.{ .kind = .guide, .rect = .{ .x = first, .y = d.cur_y, .w = col - first, .h = 1 } }); }; }, .border_h => |d| if (d.cur_y < s.rows) { var col = p.col_x[d.col]; while (col < p.col_x[d.col] + p.col_w[d.col]) : (col += 1) s.overlayDash(col, d.cur_y, "╌"); + s.addRegion(.{ .kind = .guide, .rect = .{ .x = p.col_x[d.col], .y = d.cur_y, .w = p.col_w[d.col], .h = 1 } }); }, .column_move => |d| rail: { const source = layout.columnBySerial(p, d.serial) orelse break :rail; @@ -232,13 +246,20 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { // color: this is where the grabbed column lands. const x = @min(if (edge == 0) config.GUTTER - 1 else edge - 1, s.cols -| 1); var row: u16 = p.topBarHeight(); + // A guide region for each run of it the tags do not break. + var run: u16 = row; while (row < s.rows) : (row += 1) { // Past the left edge's scroll rail the rail would cut // through column 0's grip and pane boxes: leave them whole. - if (edge == 0 and s.at(x, row).style.font_role == .tagline) continue; + if (edge == 0 and s.at(x, row).style.font_role == .tagline) { + if (row > run) s.addRegion(.{ .kind = .guide, .rect = .{ .x = x, .y = run, .w = 1, .h = row - run } }); + run = row + 1; + continue; + } s.overlayDash(x, row, "╎"); s.at(x, row).style.fg = .{ .rgb = chrome.column_box }; } + if (row > run) s.addRegion(.{ .kind = .guide, .rect = .{ .x = x, .y = run, .w = 1, .h = row - run } }); }, .move => |d| if (d.cur_x < s.cols) { if (layout.movePlacement(p, d.id, d.cur_x, d.cur_y)) |placement| { @@ -247,6 +268,8 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { s.set(col, placement.row, "╌", .{ .fg = .{ .rgb = chrome.lineno } }); } s.set(d.cur_x, placement.row, "▌", .{ .fg = .{ .rgb = chrome.lineno } }); + s.addRegion(.{ .kind = .guide, .rect = .{ .x = p.col_x[placement.preview_col], .y = placement.row, .w = p.col_w[placement.preview_col], .h = 1 } }); + s.addRegion(.{ .kind = .guide, .rect = .{ .x = d.cur_x, .y = placement.row, .w = 1, .h = 1 } }); } }, .none, .select => if (p.pointer_inside) { @@ -256,6 +279,7 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { if (p.hover_col == p.col_x[c] + p.col_w[c] -| 1) { var row: u16 = p.topBarHeight(); while (row < s.rows) : (row += 1) s.overlayDash(p.hover_col, row, "╎"); + s.addRegion(.{ .kind = .guide, .rect = .{ .x = p.hover_col, .y = p.topBarHeight(), .w = 1, .h = s.rows -| p.topBarHeight() } }); } } for (0..p.ncol) |cc| { @@ -264,6 +288,7 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { if (mouse.seamIdxAt(p, cc, p.hover_row) != null) { var col = p.col_x[cc]; while (col < p.col_x[cc] + p.col_w[cc]) : (col += 1) s.overlayDash(col, p.hover_row, "╌"); + s.addRegion(.{ .kind = .guide, .rect = .{ .x = p.col_x[cc], .y = p.hover_row, .w = p.col_w[cc], .h = 1 } }); } } for (0..p.ncol -| 1) |cn| { @@ -272,6 +297,7 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { if (mouse.seamIdxAt(p, cn + 1, p.hover_row) == null) continue; var col = p.col_x[cn + 1]; while (col < p.col_x[cn + 1] + p.col_w[cn + 1]) : (col += 1) s.overlayDash(col, p.hover_row, "╌"); + s.addRegion(.{ .kind = .guide, .rect = .{ .x = p.col_x[cn + 1], .y = p.hover_row, .w = p.col_w[cn + 1], .h = 1 } }); } }, } @@ -309,6 +335,7 @@ pub fn render(p: *Pardes, arena: std.mem.Allocator) !*Surface { const oh: u16 = 10; const ox: u16 = if (s.cols > ow) s.cols - ow else 0; if (ox + ow <= s.cols and p.topBarHeight() + oh <= s.rows) { + s.addRegion(.{ .kind = .debug, .rect = .{ .x = ox, .y = p.topBarHeight(), .w = ow, .h = oh } }); // vaxis single_rounded border ring, default style s.set(ox, p.topBarHeight(), "╭", .{}); s.set(ox + ow - 1, p.topBarHeight(), "╮", .{}); |
