summaryrefslogtreecommitdiff
path: root/src/tag_layer.zig
blob: 213ebc07e1ee20a403f565b1181b634df2012663 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//! 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;
}