summaryrefslogtreecommitdiff
path: root/src/gui/gui.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 00:30:46 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit232bfbbc4371a1fe9df210874118b4450dce7f9d (patch)
tree6af9cfcc6e741082b15a270a6d80d3d182301ce5 /src/gui/gui.zig
parent42748f92b77367db415c8b4d0f2e537a9e1ddde7 (diff)
downloadpardes-232bfbbc4371a1fe9df210874118b4450dce7f9d.tar.gz
pardes-232bfbbc4371a1fe9df210874118b4450dce7f9d.zip
Let a pane's tag take a row for each line it holds
A tag that is a text can hold a newline, and the tagline, the body under it and the pointer all assumed one row. The pane's tag now takes a row per line (up to eight, and never the body's last row); the body starts below it, the rows a pointer counts start the body after the tag's lines, a click on any line puts the tag's cursor there, and a pixel shell gets a tag layer per line. A tag of one line draws exactly as before. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/gui/gui.zig')
-rw-r--r--src/gui/gui.zig34
1 files changed, 19 insertions, 15 deletions
diff --git a/src/gui/gui.zig b/src/gui/gui.zig
index dfd528a3..140ca1db 100644
--- a/src/gui/gui.zig
+++ b/src/gui/gui.zig
@@ -1842,6 +1842,7 @@ const Gui = struct {
scroll_pane: ?usize = null,
scroll_rect: pardes.Rect = .{ .x = 0, .y = 0, .w = 0, .h = 0 },
scroll_body_y: u16 = 0, // that rect's first BODY row (Tagbottom moves it)
+ scroll_body_h: u16 = 0, // and its BODY rows, which a taller tag leaves fewer of
scroll_col: u16 = 0, // where the wheel turned: crossed rows are delivered
scroll_row: u16 = 0, // THERE, not wherever the pointer has drifted to since
scroll_delta: f32 = 0, // finite raw distance waiting for the render batch
@@ -4460,11 +4461,11 @@ fn stepScroll(g: *Gui, core: *pardes.Pardes, gpa: std.mem.Allocator) void {
return;
}
const r = core.rects[id];
- if (r.h <= pardes.BOX_H) {
+ if (r.h <= pane.tag_rows) {
resetScroll(g);
return;
}
- const delta = boundScrollDelta(g.scroll_lag, queued_delta, r.h - pardes.BOX_H);
+ const delta = boundScrollDelta(g.scroll_lag, queued_delta, r.h - pane.tag_rows);
const st = applyScrollDelta(g.scroll_lag, delta);
var left = st.rows;
while (left != 0) {
@@ -4484,14 +4485,15 @@ fn stepScroll(g: *Gui, core: *pardes.Pardes, gpa: std.mem.Allocator) void {
}
g.scroll_lag = st.lag;
g.scroll_rect = r;
- const body_y = core.bodyTop(r);
+ const body_y = core.bodyTop(pane, r);
g.scroll_body_y = body_y;
+ g.scroll_body_h = r.h -| pane.tag_rows;
if (st.rows != 0) {
const s = &core.surface;
g.scroll_edge_len = 0;
- if (r.w > config.GUTTER and r.h > pardes.BOX_H and r.x + r.w <= s.cols) {
+ if (r.w > config.GUTTER and r.h > pane.tag_rows and r.x + r.w <= s.cols) {
const bw = r.w - config.GUTTER;
- const bh = r.h - pardes.BOX_H;
+ const bh = g.scroll_body_h;
const k: u16 = @intCast(@min(@abs(st.rows), @as(i32, bh)));
const srow = body_y + (if (st.rows > 0) k - 1 else bh - k);
if (srow < s.rows) {
@@ -4515,11 +4517,11 @@ fn emitScrollRows(g: *Gui, instances: [*]CellInstance, base: u32, surface: *pard
for (surface.panelTracks()) |track|
if (track.active() and track.pane == scroll_pane) return 0;
const r = g.scroll_rect;
- if (r.w <= config.GUTTER or r.h <= pardes.BOX_H) return 0;
+ const bh = g.scroll_body_h;
+ if (r.w <= config.GUTTER or bh == 0) return 0;
const x0 = r.x + config.GUTTER;
const y0 = g.scroll_body_y;
const bw = r.w - config.GUTTER;
- const bh = r.h - pardes.BOX_H;
if (x0 + bw > surface.cols or y0 + bh > surface.rows) return 0; // resized under us
var shifted = layout;
shifted.y_off -= g.scroll_lag * layout.h;
@@ -4553,7 +4555,7 @@ fn scrollScissor(g: *const Gui, layout: CellLayout, sw: u32, sh: u32) c.SDL_Rect
const px = layout.x_off + @as(f32, @floatFromInt(r.x + config.GUTTER)) * layout.w;
const py = layout.y_off + @as(f32, @floatFromInt(g.scroll_body_y)) * layout.h;
const pw = @as(f32, @floatFromInt(r.w - config.GUTTER)) * layout.w;
- const ph = @as(f32, @floatFromInt(r.h - pardes.BOX_H)) * layout.h;
+ const ph = @as(f32, @floatFromInt(g.scroll_body_h)) * layout.h;
const x0 = std.math.clamp(@as(i32, @intFromFloat(@floor(px))), 0, @as(i32, @intCast(sw)));
const y0 = std.math.clamp(@as(i32, @intFromFloat(@floor(py))), 0, @as(i32, @intCast(sh)));
const x1 = std.math.clamp(@as(i32, @intFromFloat(@ceil(px + pw))), x0, @as(i32, @intCast(sw)));
@@ -5617,8 +5619,9 @@ fn taglineBaseRgb(core: *const pardes.Pardes, col: u16, row: u16) [3]u8 {
};
}
const r = core.rects[core.active];
- const tag_y = if (core.settings.tag_bottom) r.y + r.h -| pardes.BOX_H else r.y;
- return if (r.h > 0 and row == tag_y and col >= r.x and col - r.x < r.w) chrome.tag_active_bg else chrome.tag_bg;
+ const pane = core.panes[core.active] orelse return chrome.tag_bg;
+ const tag_y = core.tagTop(pane, r);
+ return if (r.h > 0 and row >= tag_y and row < tag_y + pane.tag_rows and col >= r.x and col - r.x < r.w) chrome.tag_active_bg else chrome.tag_bg;
}
test "compact column and pane underlays share focus tint without tinting the global tag" {
@@ -7474,11 +7477,12 @@ fn appendPaneChrome(
const chrome = core.chromeTheme();
const page = overlayRgb(core.theme().bg orelse bg_default);
for (core.panes, core.rects) |slot, r| {
- if (slot == null or r.w <= config.GUTTER or r.h <= pardes.BOX_H) continue;
+ const pane = slot orelse continue;
+ if (r.w <= config.GUTTER or r.h <= pane.tag_rows) continue;
if (@as(u32, r.x) + r.w > surface.cols or @as(u32, r.y) + r.h > surface.rows) continue;
- const tag_y = if (core.settings.tag_bottom) r.y + r.h - pardes.BOX_H else r.y;
- const body_y = core.bodyTop(r);
- const body_end = body_y + (r.h -| pardes.BOX_H);
+ const tag_y = core.tagTop(pane, r);
+ const body_y = core.bodyTop(pane, r);
+ const body_end = body_y + (r.h -| pane.tag_rows);
const x0 = @as(f32, @floatFromInt(r.x)) * layout.w;
const x1 = x0 + @as(f32, @floatFromInt(r.w)) * layout.w;
const tag_cells = surface.cells[@as(usize, tag_y) * surface.cols + r.x + pardes.TAG_TEXT_INSET ..][0 .. r.w - pardes.TAG_TEXT_INSET];
@@ -7486,7 +7490,7 @@ fn appendPaneChrome(
if (cellFontRole(cell) != .tagline) break false;
} else true;
if (tag_visible) {
- const rule_y = @as(f32, @floatFromInt(tag_y + @as(u16, if (core.settings.tag_bottom) 0 else 1))) * layout.h;
+ const rule_y = @as(f32, @floatFromInt(tag_y + (if (core.settings.tag_bottom) 0 else pane.tag_rows))) * layout.h;
// Like the band above it, the rule of a pane at the right edge
// runs on through the pixels past the last whole cell.
const rule_x1 = if (builder.win_w - x1 < layout.w) @max(x1, builder.win_w) else x1;