#ifndef TILING_DECL_H #define TILING_DECL_H #include "io/sysio.h" #include "utils/utils.h" struct Tile { bool hidden = false; uint32_t weight = 100; virtual void render(std::vector &buffer, Coord size, Coord pos) = 0; virtual void handle_click(KeyEvent event, Coord size) = 0; virtual ~Tile() = default; }; struct Window : Tile { virtual ~Window() = default; virtual void handle_event(KeyEvent){}; virtual void handle_command(std::string &) {}; virtual void work() {}; virtual std::array bar_info() { return {}; }; }; struct Popup : Window { Coord pos; Coord size; virtual ~Popup() = default; }; struct TileBlock : Tile { bool vertical; std::vector> tiles; void render(std::vector &buffer, Coord size, Coord pos) override { uint32_t total_weight = 0; for (auto &t : tiles) { if (!t->hidden) total_weight += t->weight; } if (total_weight == 0) return; for (auto &t : tiles) { if (t->hidden) continue; uint32_t proportion = t->weight * (vertical ? size.row : size.col) / total_weight; Coord tile_size = vertical ? Coord{.row = proportion, .col = size.col} : Coord{.row = size.row, .col = proportion}; t->render(buffer, tile_size, pos); if (vertical) pos.row += tile_size.row; else pos.col += tile_size.col; } } void handle_click(KeyEvent event, Coord size) override { uint32_t total_weight = 0; for (auto &t : tiles) if (!t->hidden) total_weight += t->weight; if (total_weight == 0) return; uint32_t i = 0; for (auto &t : tiles) { if (t->hidden) continue; uint32_t proportion = t->weight * (vertical ? size.row : size.col) / total_weight; Coord tile_size = vertical ? Coord{.row = proportion, .col = size.col} : Coord{.row = size.row, .col = proportion}; if (vertical) { if (event.mouse_y < i + proportion) { event.mouse_y -= i; t->handle_click(event, tile_size); return; } } else { if (event.mouse_x < i + proportion) { event.mouse_x -= i; t->handle_click(event, tile_size); return; } } i += proportion; } } }; struct TileBase { std::unique_ptr tile; Coord pos; Coord size; inline bool hidden() { return this->tile->hidden; } void render(std::vector &buffer) { if (this->tile->hidden) return; this->tile->render(buffer, size, pos); } void handle_click(KeyEvent event) { event.mouse_x -= this->pos.col; event.mouse_y -= this->pos.row; this->tile->handle_click(event, size); } }; namespace layout { extern TileBase root_tile; extern Window *focused_window; extern std::vector> popups; extern std::vector> floating_tiles; } // namespace layout inline void close(Popup *handle) { std::erase_if(layout::popups, [handle](const auto &p) { return p.get() == handle; }); } inline void close(TileBase *handle) { std::erase_if(layout::floating_tiles, [handle](const auto &p) { return p.get() == handle; }); } void render(); void handle_click(KeyEvent event); #endif