display

Layout and Rendering TUI library
git clone git://git.dimitrijedobrota.com/display.git
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |

commit39c67ae3279400b6b07d9659edcc39008f3885b3
parent6bc9907460f1b64a63df06d9088dd9748711d06b
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateMon, 10 Feb 2025 12:22:22 +0100

Decoupling without lose of functionality

Diffstat:
MCMakeLists.txt|+-
Mexample/example.cpp|+++++++++++++++++++++----------------------
Minclude/display/layout.hpp|++++++++------------
Minclude/display/screen.hpp|+++++++------
Minclude/display/window.hpp|+++++++++-----------
Msource/layout.cpp|++++++++++++----------
Msource/screen.cpp|++++++++++++------------
Msource/window.cpp|+++++++---

8 files changed, 77 insertions(+), 77 deletions(-)


diff --git a/CMakeLists.txt b/CMakeLists.txt

@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)

project(
display
VERSION 0.1.12
VERSION 0.1.13
DESCRIPTION "TUI library"
HOMEPAGE_URL "https://example.com/"
LANGUAGES CXX

diff --git a/example/example.cpp b/example/example.cpp

@@ -7,15 +7,14 @@

namespace
{
int renderer(display::Window& win)
int renderer(const display::Window& win, display::place_t plc)
{
using display::place_t;
static int color_red = 0;
color_red = (color_red + 25) % 256;
const auto [start, end] = win.place().value_or(place_t());
const auto [start, end] = plc;
std::cout << alec::background(color_red, 65, 65);
for (auto ypos = start.y; ypos <= end.y; ypos++) {

@@ -25,6 +24,8 @@ int renderer(display::Window& win)

std::cout << alec::background_v<alec::Color::DEFAULT>;
std::cout << std::flush;
(void)win;
return 0;
}

@@ -53,28 +54,27 @@ int main()

using display::Display;
using display::PvtX, display::PvtY;
auto& disp = Display::display();
display::LayoutFree layout(recalculator);
disp.screen().set_layout(&layout);
layout.append({{}, {20, 10}, {PvtX::Left, PvtY::Top}});
layout.append({{}, {20, 10}, {PvtX::Center, PvtY::Top}});
layout.append({{}, {20, 10}, {PvtX::Right, PvtY::Top}});
layout.append({{}, {20, 10}, {PvtX::Right, PvtY::Center}});
layout.append({{}, {20, 10}, {PvtX::Right, PvtY::Bottom}});
layout.append({{}, {20, 10}, {PvtX::Center, PvtY::Bottom}});
layout.append({{}, {20, 10}, {PvtX::Left, PvtY::Bottom}});
layout.append({{}, {20, 10}, {PvtX::Left, PvtY::Center}});
layout.append({{}, {20, 10}, {PvtX::Center, PvtY::Center}});
for (disp.set_resized(); true;) {
auto& display = Display::display();
auto& screen = display.screen();
auto& layout = screen.set_layout({recalculator});
layout.append({renderer, {}, {20, 10}, {PvtX::Left, PvtY::Top}});
layout.append({renderer, {}, {20, 10}, {PvtX::Center, PvtY::Top}});
layout.append({renderer, {}, {20, 10}, {PvtX::Right, PvtY::Top}});
layout.append({renderer, {}, {20, 10}, {PvtX::Right, PvtY::Center}});
layout.append({renderer, {}, {20, 10}, {PvtX::Right, PvtY::Bottom}});
layout.append({renderer, {}, {20, 10}, {PvtX::Center, PvtY::Bottom}});
layout.append({renderer, {}, {20, 10}, {PvtX::Left, PvtY::Bottom}});
layout.append({renderer, {}, {20, 10}, {PvtX::Left, PvtY::Center}});
layout.append({renderer, {}, {20, 10}, {PvtX::Center, PvtY::Center}});
for (display.set_resized(); true;) {
using display::event;
const auto evnt = disp.get_event();
const auto evnt = display.get_event();
if (evnt.type() == event::Type::RESIZE) {
std::cout << alec::erase_display_v<alec::Motion::WHOLE>;
layout.render(renderer);
screen.render();
continue;
}

@@ -82,7 +82,6 @@ int main()

break;
}
}
} catch (std::exception& err) {
std::cout << err.what() << '\n' << std::flush;
}

diff --git a/include/display/layout.hpp b/include/display/layout.hpp

@@ -7,12 +7,9 @@

namespace display
{
class Screen;
class LayoutFree
{
public:
using render_f = int(Window&);
using recalc_f = void(LayoutFree&);
LayoutFree(recalc_f f_recalc) // NOLINT

@@ -20,24 +17,23 @@ public:

{
}
dim_t dim() const;
Screen* get_screen() { return m_screen; }
void set_screen(Screen* screen) { m_screen = screen; }
const pos_t& pos() const { return m_pos; }
const dim_t& dim() const { return m_dim; }
const auto& operator[](std::size_t idx) const { return m_windows[idx]; }
auto& operator[](std::size_t idx) { return m_windows[idx]; }
void append(Window window);
void recalc();
int render(render_f renderer);
void resize(pos_t pos, dim_t dim);
int render() const;
private:
std::vector<Window> m_windows;
bool m_is_sorted = true;
recalc_f* m_recalc;
pos_t m_pos;
dim_t m_dim;
Screen* m_screen = nullptr;
std::vector<Window> m_windows;
mutable bool m_is_sorted = true;
};
class LayoutRigid

diff --git a/include/display/screen.hpp b/include/display/screen.hpp

@@ -1,12 +1,13 @@

#pragma once
#include <optional>
#include "display/layout.hpp"
#include "display/types.hpp"
namespace display
{
class LayoutFree;
class Screen
{
public:

@@ -17,15 +18,15 @@ public:

const auto& dim() const { return m_dim; }
LayoutFree* get_layout() { return m_layout; }
void set_layout(LayoutFree* layout);
LayoutFree& set_layout(LayoutFree layout);
void resize(dim_t dim);
void resize(dim_t new_dim);
void render() const;
private:
dim_t m_dim;
LayoutFree* m_layout = nullptr;
std::optional<LayoutFree> m_layout;
};
} // namespace display

diff --git a/include/display/window.hpp b/include/display/window.hpp

@@ -4,16 +4,16 @@

#include "display/types.hpp"
namespace display
{
class LayoutFree;
namespace display {
class Window
{
public:
Window(pos_t pos, dim_t dim, piv_t piv = {})
: m_pos(pos)
using render_f = int(const Window&, place_t place);
Window(render_f frender, pos_t pos, dim_t dim, piv_t piv = {})
: m_renderer(frender)
, m_pos(pos)
, m_dim(dim)
, m_piv(piv)
{

@@ -28,17 +28,15 @@ public:

const auto& piv() const { return m_piv; }
auto& piv() { return m_piv; }
LayoutFree* get_layout() { return m_layout; }
void set_layout(LayoutFree* layout) { m_layout = layout; }
int render(place_t place) const;
std::optional<place_t> place() const;
std::optional<place_t> place(dim_t bounds) const;
private:
render_f* m_renderer;
pos_t m_pos;
dim_t m_dim;
piv_t m_piv;
LayoutFree* m_layout = nullptr;
};
} // namespace display

diff --git a/source/layout.cpp b/source/layout.cpp

@@ -3,30 +3,25 @@

#include "display/layout.hpp"
#include "display/screen.hpp"
#include "display/window.hpp"
namespace display
{
dim_t LayoutFree::dim() const
{
return m_screen != nullptr ? m_screen->dim() : dim_t();
}
void LayoutFree::append(Window window)
{
m_windows.push_back(window);
m_windows.back().set_layout(this);
m_is_sorted = false;
}
void LayoutFree::recalc()
void LayoutFree::resize(pos_t pos, dim_t dim)
{
m_pos = pos;
m_dim = dim;
m_recalc(*this);
}
int LayoutFree::render(render_f renderer)
int LayoutFree::render() const
{
static std::vector<std::uint8_t> idxs;

@@ -42,7 +37,14 @@ int LayoutFree::render(render_f renderer)

}
for (const auto idx : idxs) {
const auto res = renderer(m_windows[idx]);
const auto win = m_windows[idx];
const auto plc = win.place(m_dim);
if (!plc.has_value()) {
continue;
}
const auto res = win.render(plc.value());
if (res != 0) {
return res;
}

diff --git a/source/screen.cpp b/source/screen.cpp

@@ -5,24 +5,24 @@

namespace display
{
void Screen::set_layout(LayoutFree* layout)
LayoutFree& Screen::set_layout(LayoutFree layout)
{
if (m_layout != nullptr) {
m_layout->set_screen(nullptr);
}
m_layout = layout;
m_layout.emplace(std::move(layout));
return m_layout.value();
}
if (m_layout != nullptr) {
m_layout->set_screen(this);
void Screen::resize(dim_t new_dim)
{
m_dim = new_dim;
if (m_layout.has_value()) {
m_layout->resize({}, m_dim);
}
}
void Screen::resize(dim_t dim)
void Screen::render() const
{
m_dim = dim;
if (m_layout != nullptr) {
m_layout->recalc();
if (m_layout.has_value()) {
m_layout->render();
}
}

diff --git a/source/window.cpp b/source/window.cpp

@@ -1,14 +1,18 @@

#include "display/window.hpp"
#include "display/layout.hpp"
#include "display/utility.hpp"
namespace display
{
std::optional<place_t> Window::place() const
int Window::render(place_t place) const
{
const auto [cols, rows] = m_layout->dim();
return m_renderer(*this, place);
}
std::optional<place_t> Window::place(dim_t bounds) const
{
const auto [cols, rows] = bounds;
const auto [posx, posy, _] = pos();
if (posx > cols || posy > rows) {