diff --git a/src/desktoplib/terminal/ui/MenuMap.cpp b/src/desktoplib/terminal/ui/MenuMap.cpp new file mode 100644 index 0000000..a419bb9 --- /dev/null +++ b/src/desktoplib/terminal/ui/MenuMap.cpp @@ -0,0 +1,81 @@ +#include "MenuMap.hpp" + +#include + +namespace ckitty::terminal { + + MenuMap::MenuMap(int width, int height) + : _w(width), _h(height), _grid(width* height, 0) { + } + + void MenuMap::set(int x, int y, int id) { + if (x >= 0 && x < _w && y >= 0 && y < _h) { + _grid[y * _w + x] = id; + } + } + + void MenuMap::fill(int x, int y, int w, int h, int id) { + for (int i = y; i < y + h; ++i) { + for (int j = x; j < x + w; ++j) { + set(j, i, id); + } + } + } + + int MenuMap::get(int x, int y) const { + if (x < 0 || x >= _w || y < 0 || y >= _h) return 0; + return _grid[y * _w + x]; + } + + void MenuMap::setWrap(bool x, bool y) { + _wrapX = x; _wrapY = y; + } + + void MenuMap::setCursor(int x, int y) { + _cursorX = std::clamp(x, 0, _w - 1); + _cursorY = std::clamp(y, 0, _h - 1); + } + + MenuMap::Result MenuMap::getCursor() const { + return { get(_cursorX, _cursorY), _cursorX, _cursorY }; + } + + std::optional MenuMap::findNext(int dx, int dy) { + int startX = _cursorX; + int startY = _cursorY; + int curX = _cursorX; + int curY = _cursorY; + + while (true) { + curX += dx; + curY += dy; + + // Handle Wrap or Bounds + if (_wrapX) { + if (curX < 0) curX = _w - 1; + else if (curX >= _w) curX = 0; + } else if (curX < 0 || curX >= _w) return std::nullopt; + + if (_wrapY) { + if (curY < 0) curY = _h - 1; + else if (curY >= _h) curY = 0; + } else if (curY < 0 || curY >= _h) return std::nullopt; + + // Check if we looped back to start (fail condition for wrap) + if (curX == startX && curY == startY) return std::nullopt; + + int val = get(curX, curY); + if (val != 0 && val != get(startX, startY)) { + _cursorX = curX; + _cursorY = curY; + return Result{ val, curX, curY }; + } + } + } + + std::optional MenuMap::moveUp() { return findNext(0, -1); } + std::optional MenuMap::moveDown() { return findNext(0, 1); } + std::optional MenuMap::moveLeft() { return findNext(-1, 0); } + std::optional MenuMap::moveRight() { return findNext(1, 0); } + +} \ No newline at end of file diff --git a/src/desktoplib/terminal/ui/MenuMap.hpp b/src/desktoplib/terminal/ui/MenuMap.hpp index e69de29..67173f0 100644 --- a/src/desktoplib/terminal/ui/MenuMap.hpp +++ b/src/desktoplib/terminal/ui/MenuMap.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include +#include + +namespace ckitty::terminal { + + class MenuMap { + public: + + struct Result { + int id; + int x, y; + }; + + private: + int _w, _h; + int _cursorX = 0; + int _cursorY = 0; + bool _wrapX = false; + bool _wrapY = false; + std::vector _grid; + + public: + + MenuMap(int width, int height); + + // Grid Management + void set(int x, int y, int id); + void fill(int x, int y, int w, int h, int id); + int get(int x, int y) const; + + // Configuration + void setWrap(bool x, bool y); + + // Navigation - Returns the new ID if movement was successful + std::optional moveUp(); + std::optional moveDown(); + std::optional moveLeft(); + std::optional moveRight(); + + // Cursor Management + void setCursor(int x, int y); + Result getCursor() const; + + private: + + // The core search engine + std::optional findNext(int dx, int dy); + }; + +} \ No newline at end of file