mirror of https://git.sr.ht/~kikoodx/kble
123 lines
3.4 KiB
Zig
123 lines
3.4 KiB
Zig
// SPDX-License-Identifier: MIT
|
|
// Copyright (c) 2021 KikooDX
|
|
// This file is part of [KBLE](https://sr.ht/~kikoodx/kble), which is
|
|
// MIT licensed. The MIT license requires this copyright notice to be
|
|
// included in all copies and substantial portions of the software.
|
|
//! Movement functions.
|
|
const std = @import("std");
|
|
const expect = std.testing.expect;
|
|
const maxInt = std.math.maxInt;
|
|
|
|
const conf = @import("conf.zig");
|
|
const Vec2 = @import("vec2.zig");
|
|
const Rect = @import("rect.zig");
|
|
|
|
const maxIntVec2 = comptime maxInt(Vec2.int_type);
|
|
|
|
/// Describe changes to make on selection.
|
|
pub const SelectionUpdate = struct {
|
|
active: bool,
|
|
area: Rect,
|
|
state: bool,
|
|
};
|
|
|
|
/// Universal move system, prefer direction wrappers.
|
|
fn move(cursor: *Vec2, arg: conf.arg_type, dx: i2, dy: i2) SelectionUpdate {
|
|
const before: Vec2 = cursor.*;
|
|
|
|
if (dx > 0) {
|
|
var i: conf.arg_type = 0;
|
|
while (i != arg and cursor.x < maxIntVec2) : (i += 1) {
|
|
cursor.x += 1;
|
|
}
|
|
} else if (dx < 0) {
|
|
var i: conf.arg_type = 0;
|
|
while (i != arg and cursor.x > 0) : (i += 1) {
|
|
cursor.x -= 1;
|
|
}
|
|
}
|
|
if (dy > 0) {
|
|
var i: conf.arg_type = 0;
|
|
while (i != arg and cursor.y < maxIntVec2) : (i += 1) {
|
|
cursor.y += 1;
|
|
}
|
|
} else if (dy < 0) {
|
|
var i: conf.arg_type = 0;
|
|
while (i != arg and cursor.y > 0) : (i += 1) {
|
|
cursor.y -= 1;
|
|
}
|
|
}
|
|
|
|
return SelectionUpdate{
|
|
.active = true,
|
|
.area = Rect.init_from_vec2(before, cursor.*),
|
|
.state = true,
|
|
};
|
|
}
|
|
|
|
/// Just don't move.
|
|
pub fn move_but_dont(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
|
|
return move(cursor, arg, 0, 0);
|
|
}
|
|
|
|
/// Try to move the cursor `n` times left.
|
|
pub fn move_left(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
|
|
return move(cursor, arg, -1, 0);
|
|
}
|
|
|
|
/// Try to move the cursor `n` times right.
|
|
pub fn move_right(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
|
|
return move(cursor, arg, 1, 0);
|
|
}
|
|
|
|
/// Try to move the cursor `n` times up.
|
|
pub fn move_up(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
|
|
return move(cursor, arg, 0, -1);
|
|
}
|
|
|
|
/// Try to move the cursor `n` times down.
|
|
pub fn move_down(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
|
|
return move(cursor, arg, 0, 1);
|
|
}
|
|
|
|
/// Try to move the cursor `n` times up and left.
|
|
pub fn move_up_left(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
|
|
return move(cursor, arg, -1, -1);
|
|
}
|
|
|
|
/// Try to move the cursor `n` times up and right.
|
|
pub fn move_up_right(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
|
|
return move(cursor, arg, 1, -1);
|
|
}
|
|
|
|
/// Try to move the cursor `n` times down and left.
|
|
pub fn move_down_left(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
|
|
return move(cursor, arg, -1, 1);
|
|
}
|
|
|
|
/// Try to move the cursor `n` times down and right.
|
|
pub fn move_down_right(cursor: *Vec2, arg: conf.arg_type) SelectionUpdate {
|
|
return move(cursor, arg, 1, 1);
|
|
}
|
|
|
|
test "move left" {
|
|
var cursor = Vec2.init(42, 51);
|
|
_ = move_left(&cursor, 2, false);
|
|
expect(cursor.x == 40);
|
|
|
|
_ = move_left(&cursor, 38, false);
|
|
expect(cursor.x == 2);
|
|
|
|
_ = move_left(&cursor, maxIntVec2, false);
|
|
expect(cursor.x == 0);
|
|
}
|
|
|
|
test "move right" {
|
|
var cursor = Vec2.init(564, 42);
|
|
_ = move_right(&cursor, 51, false);
|
|
expect(cursor.x == 615);
|
|
|
|
_ = move_right(&cursor, maxIntVec2, false);
|
|
expect(cursor.x == maxIntVec2);
|
|
}
|