diff options
| -rw-r--r-- | docs/design.typ | 2 | ||||
| -rw-r--r-- | src/Layer.zig | 28 | ||||
| -rw-r--r-- | src/edit.zig | 4 | ||||
| -rw-r--r-- | src/look.zig | 8 | ||||
| -rw-r--r-- | src/mouse.zig | 8 | ||||
| -rw-r--r-- | src/pardes.zig | 1 | ||||
| -rw-r--r-- | src/tag_layer.zig | 32 |
7 files changed, 39 insertions, 44 deletions
diff --git a/docs/design.typ b/docs/design.typ index 20085706..ebbf213a 100644 --- a/docs/design.typ +++ b/docs/design.typ @@ -532,7 +532,7 @@ image pane in `image.zig`), reached through `panes.zig` beside `Pane`. and cross-pane state directly, without a pane vtable; the rest of the editor is split by thing as acme is: `Text.zig`, `edit.zig`, `normal.zig`, `tagline.zig`, `look.zig`, `exec.zig`, `mouse.zig`, `Messages.zig`, `Pipe.zig`, `colors.zig`, -`surface.zig`, `body_layer.zig`, `tag_layer.zig` and `dump.zig`. Integration fixtures live +`surface.zig`, `body_layer.zig`, `Layer.zig` and `dump.zig`. Integration fixtures live in `test/panes.zig`, `test/output.zig`, and `test/pdf.zig`. = State diff --git a/src/Layer.zig b/src/Layer.zig index a9827304..7a5fcf7e 100644 --- a/src/Layer.zig +++ b/src/Layer.zig @@ -199,3 +199,31 @@ test "a taller tag's rows are grid rows, each hit on its own line" { try std.testing.expect(layer.tagHit(120, 140, 10, 20, 6, 12) == null); try std.testing.expect(layer.bodyHit(120, 100, 10, 20, 6, 12) == null); } + +// Pointer hits on tag bands: comparing two, and bringing one that left +// its band back onto it. + +/// Whether two pointer hits name the same cell of the same tag line. +pub fn sameCell(a: ?TagHit, b: ?TagHit) bool { + const first = a orelse return b == null; + const second = b orelse return false; + return first.kind == second.kind and first.id == second.id and first.serial == second.serial and first.line == second.line and first.col == second.col; +} + +/// The tag column a host's pointer is at. Clamped, a point off the tag is +/// brought back onto line `line` of it, for a drag that leaves it. +pub fn columnAt(p: *const pardes.Pardes, kind: Kind, id: usize, supplied: ?TagHit, clamp: bool, line: u16) ?u16 { + var point = supplied orelse return null; + if (point.kind != kind or point.id != id) return null; + if (clamp) for (p.surface.tagLayers()) |*layer| { + if (layer.rows == 0 or layer.kind != kind or layer.id != id or layer.serial != point.serial or line >= layer.rows) continue; + const bw: f32 = @floatFromInt(point.metrics.body_w); + const bh: f32 = @floatFromInt(point.metrics.body_h); + const left = @as(f32, @floatFromInt(layer.viewport.x)) * bw; + const right = @as(f32, @floatFromInt(layer.viewport.x + layer.viewport.w)) * bw; + point.pixel_x = std.math.clamp(point.pixel_x, left, @max(left, right - 0.001)); + point.pixel_y = (@as(f32, @floatFromInt(layer.viewport.y + line)) + 0.5) * bh; + break; + }; + return if (p.reprojectTagHit(point)) |mapped| mapped.col else null; +} diff --git a/src/edit.zig b/src/edit.zig index 183d6325..26062029 100644 --- a/src/edit.zig +++ b/src/edit.zig @@ -17,7 +17,7 @@ const syntax = @import("syntax.zig"); const platform = pardes.platform; const Pane = panes.Pane; const Text = panes.Text; -const tag_layer = @import("tag_layer.zig"); +const Layer = @import("Layer.zig"); const TagHit = pardes.TagHit; const BOX_H = pardes.BOX_H; const TAG_TEXT_INSET = pardes.TAG_TEXT_INSET; @@ -2108,7 +2108,7 @@ pub fn pointerTextSelection(p: *const Pardes, id: usize, col: u16, row: u16, bod const v = @as(i32, mapped_hit.row) + pane.tag_rows; return .{ .sel = .{ .state = .dragging, .c0 = c, .c1 = c, .r0 = v, .r1 = v }, .on_tag = false }; }; - const tag_col = if (on_tag) tag_layer.columnAt(p, .pane, id, tag_hit, false, row - tag_y) else null; + const tag_col = if (on_tag) Layer.columnAt(p, .pane, id, tag_hit, false, row - tag_y) else null; const c: i32 = (if (tag_col) |value| @as(i32, value) else @as(i32, col) - @as(i32, r.x + (if (on_tag) TAG_TEXT_INSET else config.GUTTER))) + (if (on_tag) @as(i32, pane.tag_scroll) else 0); const v: i32 = if (on_tag) @as(i32, row) - @as(i32, tag_y) else @as(i32, row) - @as(i32, body_y) + @as(i32, pane.tag_rows); diff --git a/src/look.zig b/src/look.zig index fe5a3ac1..65d001a9 100644 --- a/src/look.zig +++ b/src/look.zig @@ -21,7 +21,7 @@ const Color = @import("surface.zig").Color; const pdf = panes.Pdf.pdf; const Pane = panes.Pane; const MAX_PANES = pardes.MAX_PANES; -const tag_layer = @import("tag_layer.zig"); +const Layer = @import("Layer.zig"); const TagHit = pardes.TagHit; const BOX_H = pardes.BOX_H; const TAG_TEXT_INSET = pardes.TAG_TEXT_INSET; @@ -946,14 +946,14 @@ fn noteLookHover(p: *Pardes, col: u16, row: u16, body_hit: ?Mouse.BodyHit, tag_h if (comptime pdf_enabled) if (p.pdf_hover_preview) |shown| if (shown.col == col and shown.row == row and shown.pane == id and shown.serial == pane.serial) return; if (p.look_hover_preview) |shown| - if (shown.col == col and shown.row == row and shown.pane == id and shown.serial == pane.serial and mouse.sameBodyCell(shown.body_hit, body_hit) and tag_layer.sameCell(shown.tag_hit, tag_hit)) return; + if (shown.col == col and shown.row == row and shown.pane == id and shown.serial == pane.serial and mouse.sameBodyCell(shown.body_hit, body_hit) and Layer.sameCell(shown.tag_hit, tag_hit)) return; if (p.look_hover_wait) |waiting| - if (waiting.col == col and waiting.row == row and waiting.pane == id and waiting.serial == pane.serial and mouse.sameBodyCell(waiting.body_hit, body_hit) and tag_layer.sameCell(waiting.tag_hit, tag_hit)) return; + if (waiting.col == col and waiting.row == row and waiting.pane == id and waiting.serial == pane.serial and mouse.sameBodyCell(waiting.body_hit, body_hit) and Layer.sameCell(waiting.tag_hit, tag_hit)) return; // Found nothing to open here a moment ago: the pointer resting on it // does not start another wait (and another frame) every frame. if (p.look_hover_refused) |refused| - if (refused.col == col and refused.row == row and refused.pane == id and refused.serial == pane.serial and mouse.sameBodyCell(refused.body_hit, body_hit) and tag_layer.sameCell(refused.tag_hit, tag_hit)) return; + if (refused.col == col and refused.row == row and refused.pane == id and refused.serial == pane.serial and mouse.sameBodyCell(refused.body_hit, body_hit) and Layer.sameCell(refused.tag_hit, tag_hit)) return; p.look_hover_refused = null; cancelLookHover(p); diff --git a/src/mouse.zig b/src/mouse.zig index 5bfd92ee..1f2648b0 100644 --- a/src/mouse.zig +++ b/src/mouse.zig @@ -22,7 +22,7 @@ const pdf = panes.Pdf.pdf; const platform = pardes.platform; const Pane = panes.Pane; const MAX_PANES = pardes.MAX_PANES; -const tag_layer = @import("tag_layer.zig"); +const Layer = @import("Layer.zig"); const TOPBAR_H = pardes.TOPBAR_H; const BOX_H = pardes.BOX_H; const TAG_GAP = pardes.TAG_GAP; @@ -332,7 +332,7 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void { const row: u16 = @intCast(@min(mrow -| base, (if (p.header_column != null) p.columnBarHeight() else p.topBarHeight()) -| 1)); const line: u16 = @intCast(@min(row + p.header_top, modal.lineCount(text) -| 1)); const bar = modal.lineSlice(text, line); - const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tag_layer.columnAt(p, if (p.header_column != null) .column else .workspace, p.header_column orelse 0, p.pointer_tag_hit, p.header_drag, row) orelse (mcol -| x)) + p.header_scroll)); + const at = @min(bar.len, panes.File.rawAtDisplay(bar, (Layer.columnAt(p, if (p.header_column != null) .column else .workspace, p.header_column orelse 0, p.pointer_tag_hit, p.header_drag, row) orelse (mcol -| x)) + p.header_scroll)); // the anchor stays where the press put it t.cur_row = line; t.cur_col = @intCast(at); @@ -368,7 +368,7 @@ pub fn handleMouse(p: *Pardes, m: Mouse) void { if (line > 0 and line >= modal.lineCount(text)) return; const bar = modal.lineSlice(text, line); const scroll = if (focused) p.header_scroll else 0; - const at = @min(bar.len, panes.File.rawAtDisplay(bar, (tag_layer.columnAt(p, if (column != null) .column else .workspace, column orelse 0, p.pointer_tag_hit, p.header_drag, row) orelse (mcol -| x)) + scroll)); + const at = @min(bar.len, panes.File.rawAtDisplay(bar, (Layer.columnAt(p, if (column != null) .column else .workspace, column orelse 0, p.pointer_tag_hit, p.header_drag, row) orelse (mcol -| x)) + scroll)); if (m.button == config.select_button) { // A clicked header is typed straight into, as a clicked tag is. if (!focused) tagline.enterHeader(p, column); @@ -668,7 +668,7 @@ pub fn dragUpdate(p: *Pardes, mcol: u16, mrow: u16, body_hit: ?Mouse.BodyHit) vo // nearest the pointer. const tag_y = p.tagTop(pane, r); const tag_line: u16 = @intCast(std.math.clamp(@as(i32, mrow) - @as(i32, tag_y), 0, tag_rows - 1)); - if (pane.sel[b].r0 < tag_rows) if (tag_layer.columnAt(p, .pane, s.id, p.pointer_tag_hit, true, tag_line)) |value| { + if (pane.sel[b].r0 < tag_rows) if (Layer.columnAt(p, .pane, s.id, p.pointer_tag_hit, true, tag_line)) |value| { pane.sel[b].c1 = @as(i32, value) + pane.tag_scroll; pane.sel[b].r1 = tag_line; return; diff --git a/src/pardes.zig b/src/pardes.zig index 22d5f7a1..90095556 100644 --- a/src/pardes.zig +++ b/src/pardes.zig @@ -492,7 +492,6 @@ test { _ = @import("surface.zig"); _ = @import("body_layer.zig"); _ = @import("draw.zig"); - _ = @import("tag_layer.zig"); _ = @import("dump.zig"); // its tests ran nowhere before _ = @import("recent.zig"); _ = @import("Presentation.zig"); diff --git a/src/tag_layer.zig b/src/tag_layer.zig deleted file mode 100644 index 213ebc07..00000000 --- a/src/tag_layer.zig +++ /dev/null @@ -1,32 +0,0 @@ -//! Pointer hits on tag bands (Layer.TagHit): comparing two, and bringing one -//! that left its band back onto it. -const std = @import("std"); -const pardes = @import("pardes.zig"); -const Layer = @import("Layer.zig"); -const Hit = Layer.TagHit; -const Kind = Layer.Kind; - -/// Whether two pointer hits name the same cell of the same tag line. -pub fn sameCell(a: ?Hit, b: ?Hit) bool { - const first = a orelse return b == null; - const second = b orelse return false; - return first.kind == second.kind and first.id == second.id and first.serial == second.serial and first.line == second.line and first.col == second.col; -} - -/// The tag column a host's pointer is at. Clamped, a point off the tag is -/// brought back onto line `line` of it, for a drag that leaves it. -pub fn columnAt(p: *const pardes.Pardes, kind: Kind, id: usize, supplied: ?Hit, clamp: bool, line: u16) ?u16 { - var point = supplied orelse return null; - if (point.kind != kind or point.id != id) return null; - if (clamp) for (p.surface.tagLayers()) |*layer| { - if (layer.rows == 0 or layer.kind != kind or layer.id != id or layer.serial != point.serial or line >= layer.rows) continue; - const bw: f32 = @floatFromInt(point.metrics.body_w); - const bh: f32 = @floatFromInt(point.metrics.body_h); - const left = @as(f32, @floatFromInt(layer.viewport.x)) * bw; - const right = @as(f32, @floatFromInt(layer.viewport.x + layer.viewport.w)) * bw; - point.pixel_x = std.math.clamp(point.pixel_x, left, @max(left, right - 0.001)); - point.pixel_y = (@as(f32, @floatFromInt(layer.viewport.y + line)) + 0.5) * bh; - break; - }; - return if (p.reprojectTagHit(point)) |mapped| mapped.col else null; -} |
