#ifndef NDSUI_HPP #define NDSUI_HPP #include "basic-coro/AwaitableTask.hpp" #include "basic-coro/SingleEvent.hpp" #include #include #include #include #include class LineWrappedString { unsigned maxCharsPerLine; std::vector lines; void split(std::string_view, unsigned maxCharsPerLine); public: LineWrappedString(std::string_view str, unsigned maxCharsPerLine) : maxCharsPerLine(maxCharsPerLine) { split(str, maxCharsPerLine); } LineWrappedString(const LineWrappedString& o) : maxCharsPerLine(o.maxCharsPerLine), lines(o.lines) {} LineWrappedString(LineWrappedString&& o) : maxCharsPerLine(o.maxCharsPerLine), lines(std::move(o.lines)) {} auto& operator=(LineWrappedString&& o) { maxCharsPerLine = o.maxCharsPerLine; lines = std::move(o.lines); return *this; } auto& operator=(const LineWrappedString& o) { maxCharsPerLine = o.maxCharsPerLine; lines = o.lines; return *this; } const std::vector& getLines() const { return lines; } }; struct Position2D { unsigned x, y; }; struct Box2D { Position2D topLeft, bottomRight; constexpr unsigned height() const { return bottomRight.y - topLeft.y; } constexpr unsigned width() const { return bottomRight.x - topLeft.x; } }; class NDSUI { static NDSUI *currentInstance; // Currently updating instance std::array inputLineBuf; unsigned inputLineBufHead = 0; std::vector messages; std::unique_ptr> userInputHandler = nullptr; unsigned boxesRendered; unsigned scrollOff = 0; static void kbCallback(int key); static consteval Box2D calcInputLineDimensions(); static consteval Box2D calcMessageLogDimensions(); void renderMessageLog(); void renderInputLine(); static consteval unsigned calcMaxCharsInLine(unsigned width); static consteval unsigned calcMaxLinesInRow(unsigned height); bool printChar(const char character, Position2D *topleftpos, const int color, bool bold = false); void print(std::string_view str, Position2D topleftpos, const int color, bool bold = false); void handleInput(char); void scanButtons(); void resetInputLine() { inputLineBufHead = 0; inputLineBuf[0] = '\0'; } public: NDSUI(); bool shouldRun() const { return userInputHandler != nullptr; } void run(); auto& addLogMessage(LineWrappedString &&msg) { return messages.emplace_back(std::move(msg)); } basiccoro::AwaitableTask readLine() { userInputHandler = std::make_unique::type>(); co_return co_await *userInputHandler; } static LineWrappedString createLogMessage(const char *username, std::string_view message); }; #endif // NDSUI_HPP