display

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

commit 71668e6f08aea9bf597a67acffb6ae933620f078
parent 33f7aed76a00f28a19d54178ac2e8609203a1708
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Sat, 15 Feb 2025 11:12:15 +0100

Route input, window has free render()

* Get rid of place_t and aplace_t
* Use apos_t and dim_t instead

Diffstat:
M CMakeLists.txt | + -
M example/example.cpp | ++++++++++ ------
M include/display/display.hpp | --
M include/display/layout.hpp | +
M include/display/layout_free.hpp | ++
M include/display/layout_rigid.hpp | +
M include/display/screen.hpp | +
M include/display/types.hpp | +++++++++++++++++ ----------------------------------
M include/display/window.hpp | +++ --
M include/display/window_pivot.hpp | +++++++++++++ --
M source/layout_free.cpp | ++++++++++++++++ -----
M source/layout_rigid.cpp | +++++++++++ -
M source/screen.cpp | +++++++
M source/window_pivot.cpp | ++++++ -----

14 files changed, 89 insertions(+), 58 deletions(-)


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

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


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

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

@@ -1,7 +1,8 @@

#include <iostream>
#include <string>

#include "alec/alec.hpp"
#include <alec/alec.hpp>

#include "display/display.hpp"
#include "display/layout_free.hpp"
#include "display/layout_rigid.hpp"

@@ -18,18 +19,21 @@ public:

{
}

void render(display::aplace_t aplc) const override
void render() const override
{
static int color_red = 0;
color_red = (color_red + 25) % 256;

const auto [start, end] = aplc;
const auto [x, y] = apos();
const auto [w, h] = apos();

std::cout << alec::background(color_red, 65, 65);
for (auto ypos = start.y; ypos < end.y; ypos++) {
std::cout << alec::cursor_position(ypos + 1, start.x + 1);
std::cout << std::string(end.x - start.x, ' ');

for (auto ypos = y; ypos < y + h; ypos++) {
std::cout << alec::cursor_position(ypos + 1, x + 1);
std::cout << std::string(w, ' ');
}

std::cout << alec::background_v<alec::Color::DEFAULT>;
std::cout << std::flush;
}

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

@@ -7,8 +7,6 @@

namespace display
{

using event = alec::event;

class Display
{
public:

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

@@ -23,6 +23,7 @@ public:


virtual void resize(apos_t apos, dim_t dim) { m_apos = apos, m_dim = dim; }
virtual void render() const = 0;
virtual void input(event& evnt) = 0;

protected:
const dim_t& dim() const { return m_dim; }

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

@@ -39,7 +39,9 @@ public:

return *dynamic_cast<T*>(m_wins[idx].get());
}

void resize(apos_t apos, dim_t dim) override;
void render() const override;
void input(event& evnt) override;

private:
std::vector<std::unique_ptr<Window>> m_wins;

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

@@ -20,6 +20,7 @@ public:


void resize(apos_t apos, dim_t dim) override;
void render() const override;
void input(event& evnt) override;

private:
auto calc_width(dim_t share) const;

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

@@ -47,6 +47,7 @@ public:


void resize(apos_t apos, dim_t dim);
void render() const;
void input(event& evnt);

private:
apos_t m_apos;

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

@@ -3,9 +3,13 @@

#include <cstdint>
#include <utility>

#include <alec/alec.hpp>

namespace display
{

using event = alec::event;

using sz_t = std::uint16_t;

struct dim_t

@@ -37,11 +41,16 @@ struct pos_t

pos_t operator+(pos_t rhs) const
{
return {
static_cast<std::uint16_t>(x + rhs.x),
static_cast<std::uint16_t>(y + rhs.y),
static_cast<sz_t>(x + rhs.x),
static_cast<sz_t>(y + rhs.y),
};
}

dim_t operator-(pos_t rhs) const
{
return {static_cast<sz_t>(x - rhs.x), static_cast<sz_t>(y - rhs.y)};
}

sz_t x;
sz_t y;
};

@@ -57,46 +66,20 @@ struct apos_t

apos_t operator+(pos_t rhs) const
{
return {
static_cast<std::uint16_t>(x + rhs.x),
static_cast<std::uint16_t>(y + rhs.y),
static_cast<sz_t>(x + rhs.x),
static_cast<sz_t>(y + rhs.y),
};
}

sz_t x;
sz_t y;
};

struct place_t
{
place_t(pos_t pstart = {}, pos_t pend = {}) // NOLINT
: start(pstart)
, end(pend)
dim_t operator-(apos_t rhs) const
{
return {static_cast<sz_t>(rhs.x - x), static_cast<sz_t>(rhs.y - y)};
}

place_t operator+(pos_t pos) const { return {start + pos, end + pos}; }

pos_t start;
pos_t end;
};

struct aplace_t
{
aplace_t(apos_t astart, apos_t aend) // NOLINT
: start(astart)
, end(aend)
{
}

apos_t start;
apos_t end;
sz_t x;
sz_t y;
};

inline aplace_t operator+(apos_t apos, place_t plc)
{
return {apos + plc.start, apos + plc.end};
}

enum class PvtX : std::uint8_t
{
Left,

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

@@ -20,8 +20,9 @@ public:


virtual ~Window() = default;

virtual std::optional<place_t> place(dim_t bounds) = 0;
virtual void render(aplace_t place) const = 0;
virtual void resize(apos_t apos, dim_t dim) = 0;
virtual void render() const = 0;
virtual void input(event& /* unused */) {}
};

} // namespace display

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

@@ -13,6 +13,8 @@ public:

: m_pos(pos)
, m_dim(dim)
, m_piv(piv)
, m_apos(0, 0)
, m_adim(0, 0)
{
}

@@ -25,13 +27,22 @@ public:

const auto& piv() const { return m_piv; }
auto& piv() { return m_piv; }

std::optional<place_t> place(dim_t bounds) override;
void render(aplace_t place) const override = 0;
void resize(apos_t apos, dim_t dim) override;

protected:
const auto& apos() const { return m_apos; }
auto& apos() { return m_apos; }

const auto& adim() const { return m_adim; }
auto& adim() { return m_adim; }

private:
pos_t m_pos;
dim_t m_dim;
piv_t m_piv;

apos_t m_apos;
dim_t m_adim;
};

} // namespace display

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

@@ -3,16 +3,27 @@

namespace display
{

void LayoutFree::resize(apos_t apos, dim_t dim)
{
for (const auto& win : m_wins) {
win->resize(apos, dim);
}
}

void LayoutFree::render() const
{
for (const auto& win : m_wins) {
const auto plc = win->place(dim());
win->render();
}
}

if (!plc.has_value()) {
continue;
void LayoutFree::input(event& evnt)
{
for (const auto& win : m_wins) {
win->input(evnt);
if (evnt.type() == event::Type::NONE) {
break;
}

win->render(apos() + plc.value());
}
}

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

@@ -107,9 +107,19 @@ void LayoutRigid::resize(apos_t apos, dim_t dim)


void LayoutRigid::render() const
{
for (const auto& [screen, _, __] : m_recs) {
for (const auto& [screen, _, _1] : m_recs) {
screen.render();
}
}

void LayoutRigid::input(event& evnt)
{
for (auto& [screen, _, _1] : m_recs) {
screen.input(evnt);
if (evnt.type() == event::Type::NONE) {
break;
}
}
}

} // namespace display

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

@@ -20,4 +20,11 @@ void Screen::render() const

}
}

void Screen::input(event& evnt)
{
if (has_layout()) {
m_layout->input(evnt);
}
}

} // namespace display

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

@@ -5,16 +5,16 @@

namespace display
{

std::optional<place_t> WindowPivot::place(dim_t bounds)
void WindowPivot::resize(apos_t apos, dim_t dim)
{
const auto [cols, rows] = bounds;
const auto [cols, rows] = dim;
const auto [posx, posy] = pos();

if (posx > cols || posy > rows) {
return {};
return;
}

const auto [wdth, hght] = dim();
const auto [wdth, hght] = this->dim();
const display::sz_t zero = 0;
const sz_t wdthm = wdth / 2;
const sz_t hghtm = hght / 2;

@@ -52,7 +52,8 @@ std::optional<place_t> WindowPivot::place(dim_t bounds)

break;
}

return place_t(start, end);
m_apos = apos + start;
m_adim = end - start;
}

} // namespace display