From 486ca3846b46dc229e5807968578809766ec1991 Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 23 Mar 2022 19:41:31 +0100 Subject: feat: implement generations & multithreading --- README.md | 1 - src/CMakeLists.txt | 5 +- src/bootstrap.cpp | 45 ++++++++++++++- src/commands/toggle_pause.cpp | 22 ++++++++ src/commands/toggle_pause.hpp | 20 +++++++ src/engine/engine.cpp | 12 +++- src/engine/graphics/scene.cpp | 20 ------- src/engine/graphics/scene.hpp | 6 -- src/engine/user/input.hpp | 4 +- src/game/cursor_listener.cpp | 14 ----- src/game/cursor_listener.hpp | 19 ------- src/game/game.cpp | 26 ++++++--- src/game/game.hpp | 21 +++++-- src/game/generation_tracker.cpp | 18 ++++++ src/game/generation_tracker.hpp | 22 ++++++++ src/game/status_updater.cpp | 25 +++++++++ src/game/status_updater.hpp | 24 ++++++++ src/game/statusline.cpp | 102 ++++++++++++++++++++++++++++++++++ src/game/statusline.hpp | 41 ++++++++++++++ src/interfaces/game.hpp | 6 +- src/interfaces/generation_tracker.hpp | 18 ++++++ src/interfaces/scene.hpp | 2 - src/interfaces/status_updater.hpp | 19 +++++++ src/interfaces/statusline.hpp | 27 +++++++++ 24 files changed, 437 insertions(+), 82 deletions(-) create mode 100644 src/commands/toggle_pause.cpp create mode 100644 src/commands/toggle_pause.hpp delete mode 100644 src/game/cursor_listener.cpp delete mode 100644 src/game/cursor_listener.hpp create mode 100644 src/game/generation_tracker.cpp create mode 100644 src/game/generation_tracker.hpp create mode 100644 src/game/status_updater.cpp create mode 100644 src/game/status_updater.hpp create mode 100644 src/game/statusline.cpp create mode 100644 src/game/statusline.hpp create mode 100644 src/interfaces/generation_tracker.hpp create mode 100644 src/interfaces/status_updater.hpp create mode 100644 src/interfaces/statusline.hpp diff --git a/README.md b/README.md index 6dc2bea..083f4f4 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ This is a c++ Linux CLI implementation of John Conway's game of life. # Todo - Implement the actual game -- Multithreading - Dynamic terminal window size. Redraw everything when the window size changes - Cells can be eaten by other cells twice as large - Creatures with different abilities. Speed for example diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c603b37..4aa4a40 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,7 +15,9 @@ file(GLOB SOURCES argument_parser.cpp util/color.cpp game/game.cpp - game/cursor_listener.cpp + game/status_updater.cpp + game/generation_tracker.cpp + game/statusline.cpp engine/engine.cpp engine/data/vector2.cpp engine/data/bounds.cpp @@ -29,6 +31,7 @@ file(GLOB SOURCES commands/insert_cell.cpp commands/move_cursor.cpp commands/quit.cpp + commands/toggle_pause.cpp DI/object_type.cpp) add_executable(${PROJECT_NAME} ${SOURCES}) diff --git a/src/bootstrap.cpp b/src/bootstrap.cpp index 713991d..8dec609 100644 --- a/src/bootstrap.cpp +++ b/src/bootstrap.cpp @@ -5,10 +5,13 @@ #include "interfaces/cursor.hpp" #include "interfaces/engine.hpp" #include "interfaces/game.hpp" +#include "interfaces/generation_tracker.hpp" #include "interfaces/input.hpp" #include "interfaces/matrix.hpp" #include "interfaces/randomization.hpp" #include "interfaces/scene.hpp" +#include "interfaces/status_updater.hpp" +#include "interfaces/statusline.hpp" #include "interfaces/window.hpp" // Implementations @@ -22,6 +25,9 @@ #include "engine/user/cursor.hpp" #include "engine/user/input.hpp" #include "game/game.hpp" +#include "game/generation_tracker.hpp" +#include "game/status_updater.hpp" +#include "game/statusline.hpp" #include "randomization/generator.hpp" #include "randomization/seed_generator.hpp" @@ -42,11 +48,21 @@ Container bootstrap() noexcept container.bind().to(); container.bind().to_factory(normalize_lambda( - [](const std::shared_ptr &window, const std::shared_ptr &scene, - const std::shared_ptr &cursor_controller) + [&container](const std::shared_ptr &window, + const std::shared_ptr &scene, + const std::shared_ptr &cursor_controller) { + auto statusline = + container.get()(cursor_controller, window); + + auto generation_tracker = container.get()(true); + + auto status_updater = + container.get()(statusline, generation_tracker); + return std::dynamic_pointer_cast( - std::make_shared(window, scene, cursor_controller)); + std::make_shared(window, scene, cursor_controller, statusline, + generation_tracker, status_updater)); })); container.bind().to_factory( @@ -79,5 +95,28 @@ Container bootstrap() noexcept cursor_controller, window)); })); + container.bind().to_factory( + [](const std::shared_ptr &cursor_controller, + const std::shared_ptr &window) + { + return std::dynamic_pointer_cast( + std::make_shared(cursor_controller, window)); + }); + + container.bind().to_factory( + [](const std::shared_ptr &status_line, + const std::shared_ptr &generation_tracker) + { + return std::dynamic_pointer_cast( + std::make_shared(status_line, generation_tracker)); + }); + + container.bind().to_factory( + [](bool is_paused) + { + return std::dynamic_pointer_cast( + std::make_shared(is_paused)); + }); + return container; } diff --git a/src/commands/toggle_pause.cpp b/src/commands/toggle_pause.cpp new file mode 100644 index 0000000..8a3f44c --- /dev/null +++ b/src/commands/toggle_pause.cpp @@ -0,0 +1,22 @@ +#include "toggle_pause.hpp" + +#include +#include + +TogglePauseCommand::TogglePauseCommand( + std::shared_ptr generation_tracker, + std::shared_ptr statusline) noexcept + : _generation_tracker(std::move(generation_tracker)), + _statusline(std::move(statusline)) +{ +} + +void TogglePauseCommand::execute() noexcept +{ + auto onoff = !_generation_tracker->get_is_paused(); + + _generation_tracker->set_is_paused(onoff); + + _statusline->set_status(StatusLineSection::B, + fmt::format("Paused: {}", onoff ? "yes" : "no")); +} diff --git a/src/commands/toggle_pause.hpp b/src/commands/toggle_pause.hpp new file mode 100644 index 0000000..4e05323 --- /dev/null +++ b/src/commands/toggle_pause.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "interfaces/command.hpp" +#include "interfaces/generation_tracker.hpp" +#include "interfaces/statusline.hpp" + +#include + +class TogglePauseCommand : public ICommand +{ +public: + explicit TogglePauseCommand(std::shared_ptr generation_tracker, + std::shared_ptr statusline) noexcept; + + void execute() noexcept override; + +private: + std::shared_ptr _generation_tracker; + std::shared_ptr _statusline; +}; diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index e463f28..c988c33 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -2,6 +2,7 @@ #include "util/function.hpp" +#include #include CLIGameEngine::CLIGameEngine(IGameFactory game_factory, ISceneFactory scene_factory, @@ -38,7 +39,16 @@ void CLIGameEngine::start() noexcept _configure_input(game->get_input_config()); - _input_handler->listen(); + std::thread listen_input_thread(normalize_lambda( + [this]() + { + _input_handler->listen(); + })); + + while (true) + { + game->on_update(); + } } void CLIGameEngine::_configure_input( diff --git a/src/engine/graphics/scene.cpp b/src/engine/graphics/scene.cpp index 4e382fe..24c174f 100644 --- a/src/engine/graphics/scene.cpp +++ b/src/engine/graphics/scene.cpp @@ -45,26 +45,6 @@ void Scene::leave() noexcept _is_shown = false; } -void Scene::write_status(const std::string_view &str) noexcept -{ - const auto previous_position = _cursor_controller->where(); - - const auto window_size = _window->size(); - - _cursor_controller->move_to( - Vector2({.x = 2, .y = static_cast(window_size.get_height())}), - true); - - auto background_color = get_background_esc_seq(STATUSBAR_COLOR); - - fmt::print("{}", background_color); - fmt::print(ERASE_ENTIRE_LINE, fmt::arg("esc", ESC)); - fmt::print(fmt::runtime(str.data())); - fmt::print(RESET_ALL_MODES, fmt::arg("esc", ESC)); - - _cursor_controller->move_to(previous_position, true); -} - const std::shared_ptr> &Scene::get_matrix() const noexcept { return _matrix; diff --git a/src/engine/graphics/scene.hpp b/src/engine/graphics/scene.hpp index 1f1c51c..c4f6d67 100644 --- a/src/engine/graphics/scene.hpp +++ b/src/engine/graphics/scene.hpp @@ -12,10 +12,6 @@ constexpr fmt::string_view ENABLE_ALT_BUFFER = "{esc}[?1049h"; constexpr fmt::string_view DISABLE_ALT_BUFFER = "{esc}[?1049l"; -constexpr fmt::string_view ERASE_ENTIRE_LINE = "{esc}[2K"; - -constexpr uint32_t STATUSBAR_COLOR = 0x1A1A1AU; - class Scene : public IScene { public: @@ -27,8 +23,6 @@ public: void leave() noexcept override; - void write_status(const std::string_view &str) noexcept override; - [[nodiscard]] const std::shared_ptr> & get_matrix() const noexcept override; diff --git a/src/engine/user/input.hpp b/src/engine/user/input.hpp index 6a9edfd..51f3fcb 100644 --- a/src/engine/user/input.hpp +++ b/src/engine/user/input.hpp @@ -29,7 +29,9 @@ public: void leave_raw_mode() noexcept override; private: - std::array>>, CHAR_MAX> _subscribers; + std::array>>, + static_cast(CHAR_MAX * 2U)> + _subscribers; std::shared_ptr _original_termios = nullptr; diff --git a/src/game/cursor_listener.cpp b/src/game/cursor_listener.cpp deleted file mode 100644 index c815f08..0000000 --- a/src/game/cursor_listener.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "cursor_listener.hpp" - -#include -#include - -CursorListener::CursorListener(std::shared_ptr scene) noexcept - : _scene(std::move(scene)) -{ -} - -void CursorListener::update(const Vector2 &context) noexcept -{ - _scene->write_status(fmt::format("X: {} Y {}", context.get_x(), context.get_y())); -} diff --git a/src/game/cursor_listener.hpp b/src/game/cursor_listener.hpp deleted file mode 100644 index c74bb3d..0000000 --- a/src/game/cursor_listener.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "interfaces/scene.hpp" -#include "interfaces/subscriber.hpp" - -#include "engine/data/vector2.hpp" - -#include - -class CursorListener : public ISubscriber -{ -public: - explicit CursorListener(std::shared_ptr scene) noexcept; - - void update(const Vector2 &context) noexcept override; - -private: - std::shared_ptr _scene; -}; diff --git a/src/game/game.cpp b/src/game/game.cpp index f788d15..6632c08 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -3,22 +3,31 @@ #include "commands/insert_cell.hpp" #include "commands/move_cursor.hpp" #include "commands/quit.hpp" -#include "game/cursor_listener.hpp" +#include "commands/toggle_pause.hpp" #include #include +#include -Game::Game(const std::shared_ptr &window, const std::shared_ptr &scene, - const std::shared_ptr &cursor_controller) noexcept - : _window(window), _scene(scene), _cursor_controller(cursor_controller) +Game::Game(std::shared_ptr window, std::shared_ptr scene, + std::shared_ptr cursor_controller, + std::shared_ptr statusline, + std::shared_ptr generation_tracker, + std::shared_ptr status_updater) noexcept + : _window(std::move(window)), + _scene(std::move(scene)), + _cursor_controller(std::move(cursor_controller)), + _statusline(std::move(statusline)), + _generation_tracker(std::move(generation_tracker)), + _status_updater(std::move(status_updater)) { } void Game::on_start() noexcept { - auto cursor_listener = std::make_shared(_scene); + _statusline->initialize_background(); - _cursor_controller->subscribe(CursorEvent::POSITION_CHANGE, cursor_listener); + _cursor_controller->subscribe(CursorEvent::POSITION_CHANGE, _status_updater); const auto window_size = _window->size(); @@ -28,9 +37,11 @@ void Game::on_start() noexcept _cursor_controller->move_to(center_position); - cursor_listener->update(center_position); + _status_updater->update(center_position); } +void Game::on_update() noexcept {} + void Game::on_exit() const noexcept { for (auto row : *_scene->get_matrix()) @@ -51,6 +62,7 @@ Game::get_input_config() const noexcept { return {{'q', std::make_shared()}, {'i', std::make_shared(_cursor_controller, _scene)}, + {'p', std::make_shared(_generation_tracker, _statusline)}, {'k', std::make_shared(Vector2::up(), _cursor_controller, _window)}, {'j', std::make_shared(Vector2::down(), _cursor_controller, diff --git a/src/game/game.hpp b/src/game/game.hpp index 2493a42..5894a01 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -2,7 +2,10 @@ #include "interfaces/cursor.hpp" #include "interfaces/game.hpp" +#include "interfaces/generation_tracker.hpp" #include "interfaces/scene.hpp" +#include "interfaces/status_updater.hpp" +#include "interfaces/statusline.hpp" #include "interfaces/window.hpp" #include @@ -10,18 +13,26 @@ class Game : public IGame { public: - Game(const std::shared_ptr &window, const std::shared_ptr &scene, - const std::shared_ptr &cursor_controller) noexcept; + Game(std::shared_ptr window, std::shared_ptr scene, + std::shared_ptr cursor_controller, + std::shared_ptr statusline, + std::shared_ptr generation_tracker, + std::shared_ptr status_updater) noexcept; void on_start() noexcept override; + void on_update() noexcept override; + void on_exit() const noexcept override; [[nodiscard]] std::unordered_map> get_input_config() const noexcept override; private: - const std::shared_ptr &_window; - const std::shared_ptr &_scene; - const std::shared_ptr &_cursor_controller; + std::shared_ptr _window; + std::shared_ptr _scene; + std::shared_ptr _cursor_controller; + std::shared_ptr _statusline; + std::shared_ptr _generation_tracker; + std::shared_ptr _status_updater; }; diff --git a/src/game/generation_tracker.cpp b/src/game/generation_tracker.cpp new file mode 100644 index 0000000..0e137cb --- /dev/null +++ b/src/game/generation_tracker.cpp @@ -0,0 +1,18 @@ +#include "generation_tracker.hpp" + +GenerationTracker::GenerationTracker(bool is_paused) noexcept : _is_paused(is_paused) {} + +uint32_t GenerationTracker::get_current_generation() const noexcept +{ + return _current_generation; +} + +bool GenerationTracker::get_is_paused() const noexcept +{ + return _is_paused; +} + +void GenerationTracker::set_is_paused(bool is_paused) noexcept +{ + _is_paused = is_paused; +} diff --git a/src/game/generation_tracker.hpp b/src/game/generation_tracker.hpp new file mode 100644 index 0000000..0e59751 --- /dev/null +++ b/src/game/generation_tracker.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "interfaces/generation_tracker.hpp" + +#include + +class GenerationTracker : public IGenerationTracker +{ +public: + explicit GenerationTracker(bool is_paused) noexcept; + + [[nodiscard]] uint32_t get_current_generation() const noexcept override; + + [[nodiscard]] bool get_is_paused() const noexcept override; + + void set_is_paused(bool is_paused) noexcept override; + +private: + uint32_t _current_generation = 0U; + + bool _is_paused; +}; diff --git a/src/game/status_updater.cpp b/src/game/status_updater.cpp new file mode 100644 index 0000000..18c535e --- /dev/null +++ b/src/game/status_updater.cpp @@ -0,0 +1,25 @@ +#include "status_updater.hpp" + +#include +#include + +StatusUpdater::StatusUpdater( + std::shared_ptr statusline, + std::shared_ptr generation_tracker) noexcept + : _statusline(std::move(statusline)), + _generation_tracker(std::move(generation_tracker)) +{ +} + +void StatusUpdater::update(const Vector2 &context) noexcept +{ + _statusline->set_status( + StatusLineSection::A, + fmt::format("X: {} Y {}", context.get_x(), context.get_y())); + + _statusline->set_status( + StatusLineSection::B, + fmt::format("Paused: {} Generation: {}", + _generation_tracker->get_is_paused() ? "yes" : "no", + _generation_tracker->get_current_generation())); +} diff --git a/src/game/status_updater.hpp b/src/game/status_updater.hpp new file mode 100644 index 0000000..3b76d3b --- /dev/null +++ b/src/game/status_updater.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "interfaces/generation_tracker.hpp" +#include "interfaces/status_updater.hpp" +#include "interfaces/statusline.hpp" +#include "interfaces/subscriber.hpp" + +#include "engine/data/vector2.hpp" + +#include + +class StatusUpdater : public IStatusUpdater +{ +public: + explicit StatusUpdater( + std::shared_ptr statusline, + std::shared_ptr generation_tracker) noexcept; + + void update(const Vector2 &context) noexcept override; + +private: + std::shared_ptr _statusline; + std::shared_ptr _generation_tracker; +}; diff --git a/src/game/statusline.cpp b/src/game/statusline.cpp new file mode 100644 index 0000000..377fa75 --- /dev/null +++ b/src/game/statusline.cpp @@ -0,0 +1,102 @@ +#include "statusline.hpp" + +#include "engine/escape.hpp" +#include "util/color.hpp" + +#include +#include +#include + +StatusLine::StatusLine(std::shared_ptr cursor_controller, + std::shared_ptr window) noexcept + : _cursor_controller(std::move(cursor_controller)), _window(std::move(window)) +{ + constexpr uint32_t SECTION_A_LENGTH = 20; + constexpr uint32_t SECTION_B_LENGTH = 15; + + _sections_lengths[StatusLineSection::A] = SECTION_A_LENGTH; + _sections_lengths[StatusLineSection::B] = SECTION_B_LENGTH; +} + +void StatusLine::initialize_background() noexcept +{ + const auto previous_position = _move_to_statusline(0); + + auto background_color = get_background_esc_seq(STATUSBAR_COLOR); + + fmt::print("{}{}", background_color, std::string(_window->size().get_width(), ' ')); + fmt::print(RESET_ALL_MODES, fmt::arg("esc", ESC)); + + _move_back(previous_position); +} + +void StatusLine::set_status(StatusLineSection section, + const std::string_view &str) noexcept +{ + _clear_section(section); + + int32_t section_start = _get_section_start_x(section); + + const auto previous_position = _move_to_statusline(section_start); + + auto background_color = get_background_esc_seq(STATUSBAR_COLOR); + + fmt::print("{}{}", background_color, str); + fmt::print(RESET_ALL_MODES, fmt::arg("esc", ESC)); + + _move_back(previous_position); +} + +Vector2 StatusLine::_move_to_statusline(int32_t x) noexcept +{ + const auto previous_position = _cursor_controller->where(); + + const auto window_size = _window->size(); + + _cursor_controller->hide(); + + auto window_height = static_cast(window_size.get_height()); + + _cursor_controller->move_to(Vector2({.x = x, .y = window_height}), true); + + return previous_position; +} + +void StatusLine::_move_back(Vector2 previous_position) noexcept +{ + _cursor_controller->move_to(previous_position, true); + _cursor_controller->show(); +} + +int32_t StatusLine::_get_section_start_x(StatusLineSection section) const noexcept +{ + int32_t section_start = 0; + + auto section_index = static_cast(section); + + while (section_index > 0) + { + section_start += static_cast( + _sections_lengths.at(StatusLineSection(section_index - 1))); + + section_index--; + } + + return section_start; +} + +void StatusLine::_clear_section(StatusLineSection section) noexcept +{ + auto section_start = _get_section_start_x(section); + + const auto previous_position = _move_to_statusline(section_start); + + auto background_color = get_background_esc_seq(STATUSBAR_COLOR); + + auto section_length = _sections_lengths.at(section); + + fmt::print("{}{}", background_color, std::string(section_length, ' ')); + fmt::print(RESET_ALL_MODES, fmt::arg("esc", ESC)); + + _move_back(previous_position); +} diff --git a/src/game/statusline.hpp b/src/game/statusline.hpp new file mode 100644 index 0000000..7db1e0b --- /dev/null +++ b/src/game/statusline.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "interfaces/cursor.hpp" +#include "interfaces/statusline.hpp" +#include "interfaces/window.hpp" + +#include "engine/data/vector2.hpp" + +#include +#include +#include +#include +#include + +constexpr uint32_t STATUSBAR_COLOR = 0x1A1A1AU; + +class StatusLine : public IStatusLine +{ +public: + StatusLine(std::shared_ptr cursor_controller, + std::shared_ptr window) noexcept; + + void initialize_background() noexcept override; + + void set_status(StatusLineSection section, + const std::string_view &str) noexcept override; + +private: + std::unordered_map _sections_lengths; + + std::shared_ptr _cursor_controller; + std::shared_ptr _window; + + Vector2 _move_to_statusline(int32_t x) noexcept; + + void _move_back(Vector2 previous_position) noexcept; + + int32_t _get_section_start_x(StatusLineSection section) const noexcept; + + void _clear_section(StatusLineSection section) noexcept; +}; diff --git a/src/interfaces/game.hpp b/src/interfaces/game.hpp index c99c01f..6836dbd 100644 --- a/src/interfaces/game.hpp +++ b/src/interfaces/game.hpp @@ -11,9 +11,11 @@ class IGame { public: - virtual ~IGame() = default; + virtual ~IGame() noexcept = default; - virtual void on_start() = 0; + virtual void on_start() noexcept = 0; + + virtual void on_update() noexcept = 0; virtual void on_exit() const noexcept = 0; diff --git a/src/interfaces/generation_tracker.hpp b/src/interfaces/generation_tracker.hpp new file mode 100644 index 0000000..135af00 --- /dev/null +++ b/src/interfaces/generation_tracker.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +class IGenerationTracker +{ +public: + virtual ~IGenerationTracker() noexcept = default; + + [[nodiscard]] virtual uint32_t get_current_generation() const noexcept = 0; + + [[nodiscard]] virtual bool get_is_paused() const noexcept = 0; + + virtual void set_is_paused(bool is_paused) noexcept = 0; +}; + +using IGenerationTrackerFactory = std::shared_ptr (*)(bool is_paused); diff --git a/src/interfaces/scene.hpp b/src/interfaces/scene.hpp index 0443d41..3b5e037 100644 --- a/src/interfaces/scene.hpp +++ b/src/interfaces/scene.hpp @@ -15,8 +15,6 @@ public: virtual void leave() noexcept = 0; - virtual void write_status(const std::string_view &str) noexcept = 0; - [[nodiscard]] virtual const std::shared_ptr> & get_matrix() const noexcept = 0; }; diff --git a/src/interfaces/status_updater.hpp b/src/interfaces/status_updater.hpp new file mode 100644 index 0000000..ccfb2db --- /dev/null +++ b/src/interfaces/status_updater.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include "interfaces/generation_tracker.hpp" +#include "interfaces/statusline.hpp" +#include "interfaces/subscriber.hpp" + +#include "engine/data/vector2.hpp" + +#include + +class IStatusUpdater : public ISubscriber +{ +public: + void update(const Vector2 &context) noexcept override = 0; +}; + +using IStatusUpdaterFactory = std::shared_ptr (*)( + const std::shared_ptr &statusline, + const std::shared_ptr &generation_tracker); diff --git a/src/interfaces/statusline.hpp b/src/interfaces/statusline.hpp new file mode 100644 index 0000000..00da99b --- /dev/null +++ b/src/interfaces/statusline.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "interfaces/cursor.hpp" +#include "interfaces/window.hpp" + +#include + +enum StatusLineSection +{ + A, + B +}; + +class IStatusLine +{ +public: + virtual ~IStatusLine() noexcept = default; + + virtual void initialize_background() noexcept = 0; + + virtual void set_status(StatusLineSection section, + const std::string_view &str) noexcept = 0; +}; + +using IStatusLineFactory = std::shared_ptr (*)( + const std::shared_ptr &cursor_controller, + const std::shared_ptr &window); -- cgit v1.2.3-18-g5258