summaryrefslogtreecommitdiff
path: root/src/pardes.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-23 02:00:00 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commitf6738c7edfff2249e0b13f2a76962f45d02c86bb (patch)
tree3f255da736fb0a6f4b926c72054d83091f941d21 /src/pardes.zig
parent9695cb098c784792af79c22d46a17f7bc7247d33 (diff)
downloadpardes-f6738c7edfff2249e0b13f2a76962f45d02c86bb.tar.gz
pardes-f6738c7edfff2249e0b13f2a76962f45d02c86bb.zip
Center tagline bands, frame anchors evenly, fill to the window edge, and resize columns from their grip
Every tag band (workspace, column, pane) is centred in its row, so text sits at one baseline offset. Anchors are inset from the column rule by that same margin, so they are square and the band frames them on the left, top and bottom; the pane mark moves to stay centred. When the window is not a whole number of cells, the bands, rules, spines and scroll thumbs at the right and bottom edges run on through the leftover pixels. A column grip dropped short of another column's place now moves the column's left edge, with a dashed rail preview, sharing setColumnPairWidth with the border drag. A release still on the grip changes nothing, and a pair too narrow for two MINW columns is left alone. PARDES_TEST_PAD adds leftover pixels to a test-mode window and capture.
Diffstat (limited to 'src/pardes.zig')
-rw-r--r--src/pardes.zig60
1 files changed, 30 insertions, 30 deletions
diff --git a/src/pardes.zig b/src/pardes.zig
index fae14f47..ca2c34a4 100644
--- a/src/pardes.zig
+++ b/src/pardes.zig
@@ -232,19 +232,12 @@ pub const BOX_H: u16 = 1;
pub const TAG_GAP: u16 = 1;
pub const TAG_TEXT_INSET: u16 = config.GUTTER + TAG_GAP;
-pub fn taglineBandOffset(row: u16, canvas_h: f32, cell_h: u32, tagline_h: u32, workspace: bool) u32 {
+pub fn taglineBandOffset(row: u16, canvas_h: f32, cell_h: u32, tagline_h: u32) u32 {
const spare = cell_h -| tagline_h;
- const border = topbarPaneBorderPixels(cell_h, tagline_h);
const rows: u32 = @max(1, @as(u32, @intFromFloat(@floor(canvas_h / @as(f32, @floatFromInt(cell_h))))));
- if (!workspace) {
- // No workspace row: nothing above row 0 to share a rule with, so
- // every band centers in its cell the way the middle rows always
- // have. The anchor boxes this lets the hosts draw stay symmetric.
- if (@as(u32, row) + 1 >= rows) return spare;
- return spare / 2;
- }
- if (row == 0) return spare - border / 2;
- if (row == TOPBAR_H) return border - border / 2;
+ // Every band centers in its cell, so text and anchors sit at the same
+ // height in the workspace, column and pane tags alike. Only the last row
+ // faces the window edge (Tagbottom).
if (@as(u32, row) + 1 >= rows) return spare;
return spare / 2;
}
@@ -5160,7 +5153,9 @@ const Drag = union(enum) {
border_v: struct { left_col: usize, cur_x: u16, corner: ?struct { col: usize, idx: usize } = null, cur_y: u16 = 0 },
border_h: struct { col: usize, top_idx: usize, cur_y: u16 },
move: struct { id: usize, cur_x: u16, cur_y: u16 },
- column_move: struct { column: usize, serial: u32, cur_x: u16 },
+ /// `grab`: how far into the grip it was pressed, so the column's left
+ /// edge lands at `cur_x - grab`. A release still on the grip moves nothing.
+ column_move: struct { column: usize, serial: u32, cur_x: u16, grab: u16 = 0 },
tag: struct { id: usize },
/// chorded: a 1-2/1-3 cut/paste chord fired during this left drag —
/// the drag's own release is then inert
@@ -12022,7 +12017,7 @@ pub const Pardes = struct {
if (mcol < p.col_x[column] or mcol >= p.col_x[column] + @min(config.GUTTER, p.col_w[column])) continue;
if (m.button == config.select_button) {
p.header_drag = false;
- p.drag = .{ .column_move = .{ .column = column, .serial = p.col_serial[column], .cur_x = mcol } };
+ p.drag = .{ .column_move = .{ .column = column, .serial = p.col_serial[column], .cur_x = mcol, .grab = mcol - p.col_x[column] } };
}
return;
}
@@ -12482,20 +12477,10 @@ pub const Pardes = struct {
.border_v => |d| {
const c = d.left_col;
const old_seam = p.col_x[c] + p.col_w[c] -| 1;
- if (c + 1 < p.ncol and d.cur_x != old_seam) {
- const combined: u64 = p.col_w[c] + p.col_w[c + 1];
- // the handle is the left pane's LAST column (inclusive), so
- // the new width includes it — a no-drag click changes nothing
- var nl: u64 = (d.cur_x + 1) -| p.col_x[c];
- nl = std.math.clamp(nl, config.MINW, @max(@as(u64, config.MINW), combined -| config.MINW));
- const pair = p.col_weight[c] + p.col_weight[c + 1];
- if (pair > 1 and combined > 0) {
- const numerator = @as(u128, pair) * nl + combined / 2;
- const left = std.math.clamp(@as(u64, @intCast(numerator / combined)), 1, pair - 1);
- p.col_weight[c] = left;
- p.col_weight[c + 1] = pair - left;
- }
- }
+ // the handle is the left pane's LAST column (inclusive), so
+ // the new width includes it — a no-drag click changes nothing
+ if (c + 1 < p.ncol and d.cur_x != old_seam)
+ layout.setColumnPairWidth(p, c, (d.cur_x + 1) -| p.col_x[c]);
if (d.corner) |k| {
if (d.cur_y != seamRowOf(p, k.col, k.idx))
layout.applyRowSplit(p, k.col, k.idx, d.cur_y);
@@ -12503,9 +12488,15 @@ pub const Pardes = struct {
},
.border_h => |d| if (d.cur_y != seamRowOf(p, d.col, d.top_idx))
layout.applyRowSplit(p, d.col, d.top_idx, d.cur_y),
- .column_move => |d| {
- if (layout.columnBySerial(p, d.serial)) |column|
- layout.reorderColumn(p, column, layout.columnMoveTarget(p, column, d.cur_x));
+ .column_move => |d| if (layout.columnBySerial(p, d.serial)) |column| {
+ const target = layout.columnMoveTarget(p, column, d.cur_x);
+ if (target != column) {
+ layout.reorderColumn(p, column, target);
+ } else if (column > 0 and (d.cur_x < p.col_x[column] or d.cur_x >= p.col_x[column] + config.GUTTER)) {
+ // Dropped short of another column's place: as in acme,
+ // the column's left edge moves to where it was dropped.
+ layout.setColumnPairWidth(p, column - 1, (d.cur_x -| d.grab) -| p.col_x[column - 1]);
+ }
},
.move => |d| {
layout.movePane(p, d.id, d.cur_x, d.cur_y);
@@ -14181,6 +14172,15 @@ pub const Pardes = struct {
}
var row: u16 = p.topBarHeight();
while (row < s.rows) : (row += 1) s.overlayDash(x, row, "╎");
+ } else if (source > 0 and source < p.ncol and (d.cur_x < p.col_x[source] or d.cur_x >= p.col_x[source] + config.GUTTER) and
+ p.col_w[source - 1] + p.col_w[source] >= 2 * config.MINW)
+ {
+ // Where the left edge would land: the border drag's rail.
+ const lo = p.col_x[source - 1] + config.MINW;
+ const hi = (p.col_x[source] + p.col_w[source]) -| config.MINW;
+ const x = @min(std.math.clamp(d.cur_x -| d.grab, lo, @max(lo, hi)), s.cols -| 1);
+ var row: u16 = p.topBarHeight();
+ while (row < s.rows) : (row += 1) s.overlayDash(x, row, "╎");
}
},
.move => |d| if (d.cur_x < s.cols) {