#include "cursor.hpp" #include "engine/escape.hpp" #include #include CursorController::CursorController() noexcept : _position({.x = 0, .y = 0}) {} void CursorController::move(const Vector2 &direction, const uint32_t &amount) noexcept { auto direction_format = direction_format_map.at(direction); fmt::print( fmt::runtime(direction_format.data()), fmt::arg("esc", ESC), fmt::arg("amount", amount)); std::cout.flush(); _position = _position.to_direction(direction, static_cast(amount)); notify_subscribers(CursorEvent::POSITION_CHANGE, _position); } void CursorController::move_to(const Vector2 &position, bool silent) noexcept { fmt::print( MOVE_CURSOR_TO, fmt::arg("esc", ESC), fmt::arg("row", position.get_y()), fmt::arg("column", position.get_x())); std::cout.flush(); _position = position; if (!silent) { notify_subscribers(CursorEvent::POSITION_CHANGE, position); } } auto CursorController::where() const noexcept -> Vector2 { return _position; } void CursorController::ensure_position() noexcept { fmt::print(REQUEST_CURSOR_POSITION, fmt::arg("esc", ESC)); std::cout.flush(); Vector2Options vector2_options = {}; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) scanf("\033[%u;%uR", &vector2_options.y, &vector2_options.x); _position = Vector2(vector2_options); notify_subscribers(CursorEvent::POSITION_CHANGE, _position); } void CursorController::hide() noexcept { fmt::print(CURSOR_INVISIBLE, fmt::arg("esc", ESC)); std::cout.flush(); } void CursorController::show() noexcept { fmt::print(CURSOR_VISIBLE, fmt::arg("esc", ESC)); std::cout.flush(); } void CursorController::subscribe( const Event &event, const Subscriber &subscriber) noexcept { if (_subscribers.count(event) == 0) { _subscribers.insert({event, std::vector()}); } _subscribers.at(event).push_back(subscriber); } void CursorController::notify_subscribers(const Event &event, const Context &context) const noexcept { if (_subscribers.count(event) == 0) { return; } for (const auto &subscriber : _subscribers.at(event)) { subscriber->update(context); } }