displayLayout and Rendering TUI library |
git clone git://git.dimitrijedobrota.com/display.git |
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | ef565de7fa473b6bff7980e0a675cc362e891d05 |
parent | 71668e6f08aea9bf597a67acffb6ae933620f078 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Sat, 15 Feb 2025 15:45:21 +0100 |
Enforce elems having apos and dim on construction * Experiment with widget render on construction * Enforce construtor param order as it will be automatically filled by parent calsses on insertion * Windows behave like other elements
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/window.hpp | | | +++++++++++++++++---- |
M | include/display/window_pivot.hpp | | | ++++-------------- |
M | source/display.cpp | | | +++++++++-- |
M | source/layout_rigid.cpp | | | ++++-- |
M | source/window_pivot.cpp | | | +++++++-------- |
12 files changed, 84 insertions(+), 55 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
display
VERSION 0.1.21
VERSION 0.1.22
DESCRIPTION "TUI library"
HOMEPAGE_URL "https://example.com/"
LANGUAGES CXX
diff --git a/example/example.cpp b/example/example.cpp
@@ -14,9 +14,14 @@ namespace
class WindowCustom : public display::WindowPivot
{
public:
WindowCustom(display::dim_t dim, display::piv_t piv)
: WindowPivot(display::pos_t(), dim, piv)
WindowCustom(display::apos_t apos,
display::dim_t adim,
display::pos_t pos,
display::dim_t dim,
display::piv_t piv)
: WindowPivot(apos, adim, pos, dim, piv)
{
render();
}
void render() const override
@@ -24,8 +29,9 @@ public:
static int color_red = 0;
color_red = (color_red + 25) % 256;
const auto [x, y] = apos();
const auto [w, h] = apos();
const auto [apos, adim] = place();
const auto [x, y] = apos;
const auto [w, h] = adim;
std::cout << alec::background(color_red, 65, 65);
@@ -42,20 +48,27 @@ public:
class LayoutCustom : public display::LayoutFree
{
public:
LayoutCustom()
LayoutCustom(display::apos_t apos, display::dim_t dim)
: LayoutFree(apos, dim)
{
using display::dim_t, display::piv_t;
using display::pos_t, display::dim_t, display::piv_t;
using display::PvtX, display::PvtY;
append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Left, PvtY::Top));
append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Center, PvtY::Top));
append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Right, PvtY::Top));
append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Right, PvtY::Center));
append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Right, PvtY::Bottom));
append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Center, PvtY::Bottom));
append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Left, PvtY::Bottom));
append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Left, PvtY::Center));
append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Center, PvtY::Center));
const auto [width, height] = dim;
const display::sz_t midw = width / 2;
const display::sz_t midh = height / 2;
// clang-format off
append<WindowCustom>(pos_t( 0, 0), dim_t(12, 4), piv_t( PvtX::Left, PvtY::Top));
append<WindowCustom>(pos_t(midw, 0), dim_t(12, 4), piv_t(PvtX::Center, PvtY::Top));
append<WindowCustom>(pos_t(width, 0), dim_t(12, 4), piv_t( PvtX::Right, PvtY::Top));
append<WindowCustom>(pos_t(width, midh), dim_t(12, 4), piv_t( PvtX::Right, PvtY::Center));
append<WindowCustom>(pos_t(width, height), dim_t(12, 4), piv_t (PvtX::Right, PvtY::Bottom));
append<WindowCustom>(pos_t(midw, height), dim_t(12, 4), piv_t(PvtX::Center, PvtY::Bottom));
append<WindowCustom>(pos_t( 0, height), dim_t(12, 4), piv_t( PvtX::Left, PvtY::Bottom));
append<WindowCustom>(pos_t( 0, midh), dim_t(12, 4), piv_t( PvtX::Left, PvtY::Center));
append<WindowCustom>(pos_t(midw, midh), dim_t(12, 4), piv_t(PvtX::Center, PvtY::Center));
// clang-format on
}
void resize(display::apos_t apos, display::dim_t dim) override
@@ -102,7 +115,7 @@ int main()
layout[3].set_layout<LayoutCustom>();
layout[4].set_layout<LayoutCustom>();
for (display.set_resized(); true;) {
while (true) {
const auto evnt = display.get_event();
if (evnt.type() == event::Type::RESIZE) {
std::cout << alec::erase_display_v<alec::Motion::WHOLE>;
diff --git a/include/display/display.hpp b/include/display/display.hpp
@@ -31,6 +31,8 @@ private:
Display();
~Display();
void resize();
static void handle_sigwinch(int /* unused */);
static bool is_resize_track;
diff --git a/include/display/layout.hpp b/include/display/layout.hpp
@@ -8,8 +8,9 @@ namespace display
class Layout
{
public:
explicit Layout(apos_t apos)
explicit Layout(apos_t apos, dim_t dim)
: m_apos(apos)
, m_dim(dim)
{
}
diff --git a/include/display/layout_free.hpp b/include/display/layout_free.hpp
@@ -12,8 +12,8 @@ namespace display
class LayoutFree : public Layout
{
public:
LayoutFree()
: Layout({0, 0})
LayoutFree(apos_t apos, dim_t dim)
: Layout(apos, dim)
{
}
@@ -23,7 +23,8 @@ public:
template<typename T, class... Args>
T& append(Args&&... args)
{
m_wins.emplace_back(std::make_unique<T>(std::forward<Args>(args)...));
m_wins.emplace_back(
std::make_unique<T>(apos(), dim(), std::forward<Args>(args)...));
return get<T>(m_wins.size() - 1);
}
diff --git a/include/display/layout_rigid.hpp b/include/display/layout_rigid.hpp
@@ -13,7 +13,7 @@ class LayoutRigid : public Layout
public:
using layout_t = std::vector<std::vector<std::uint8_t>>;
LayoutRigid(layout_t layout); // NOLINT
LayoutRigid(apos_t apos, dim_t dim, layout_t layout); // NOLINT
const auto& operator[](std::size_t idx) const { return m_recs[idx].screen; }
auto& operator[](std::size_t idx) { return m_recs[idx].screen; }
@@ -33,7 +33,7 @@ private:
struct record_t
{
record_t()
: screen(apos_t(0, 0))
: screen(apos_t(0, 0), dim_t(0, 0))
{
}
diff --git a/include/display/screen.hpp b/include/display/screen.hpp
@@ -11,8 +11,9 @@ namespace display
class Screen
{
public:
explicit Screen(apos_t apos)
explicit Screen(apos_t apos, dim_t dim)
: m_apos(apos)
, m_dim(dim)
{
}
@@ -27,7 +28,7 @@ public:
template<typename T, class... Args>
T& set_layout(Args&&... args)
{
m_layout = std::make_unique<T>(std::forward<Args>(args)...);
m_layout = std::make_unique<T>(m_apos, m_dim, std::forward<Args>(args)...);
return get_layout<T>();
}
diff --git a/include/display/window.hpp b/include/display/window.hpp
@@ -1,7 +1,5 @@
#pragma once
#include <optional>
#include "display/types.hpp"
namespace display
@@ -10,7 +8,11 @@ namespace display
class Window
{
public:
Window() = default;
Window(apos_t apos, dim_t dim)
: m_apos(apos)
, m_adim(dim)
{
}
Window(const Window&) = delete;
Window& operator=(const Window&) = delete;
@@ -20,9 +22,20 @@ public:
virtual ~Window() = default;
virtual void resize(apos_t apos, dim_t dim) = 0;
virtual void resize(apos_t apos, dim_t adim) { m_apos = apos, m_adim = adim; }
virtual void render() const = 0;
virtual void input(event& /* unused */) {}
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:
apos_t m_apos;
dim_t m_adim;
};
} // namespace display
diff --git a/include/display/window_pivot.hpp b/include/display/window_pivot.hpp
@@ -9,12 +9,11 @@ namespace display
class WindowPivot : public Window
{
public:
WindowPivot(pos_t pos, dim_t dim, piv_t piv = {})
: m_pos(pos)
WindowPivot(apos_t apos, dim_t adim, pos_t pos, dim_t dim, piv_t piv = {})
: Window(apos, adim)
, m_pos(pos)
, m_dim(dim)
, m_piv(piv)
, m_apos(0, 0)
, m_adim(0, 0)
{
}
@@ -27,22 +26,13 @@ public:
const auto& piv() const { return m_piv; }
auto& piv() { return m_piv; }
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; }
std::tuple<apos_t, dim_t> place() const;
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/display.cpp b/source/display.cpp
@@ -28,7 +28,7 @@ Display& Display::display()
}
Display::Display()
: m_screen(apos_t(0, 0))
: m_screen(apos_t(0, 0), alec::get_screen_size())
{
struct sigaction old_sig_action = {};
sigaction(SIGWINCH, nullptr, &old_sig_action);
@@ -46,6 +46,8 @@ Display::Display()
alec::init_buffer(STDIN_FILENO);
write<alec::abuf_enable_v>();
write<alec::cursor_hide_v>();
resize();
}
Display::~Display()
@@ -72,8 +74,8 @@ event Display::get_event() // NOLINT
void Display::set_resized()
{
m_screen.resize(apos_t(0, 0), alec::get_screen_size());
m_is_resized = true;
resize();
}
void Display::reset_resized()
@@ -86,6 +88,11 @@ bool Display::get_resized() const
return m_is_resized;
}
void Display::resize()
{
m_screen.resize(apos_t(0, 0), alec::get_screen_size());
}
void Display::render()
{
m_screen.render();
diff --git a/source/layout_rigid.cpp b/source/layout_rigid.cpp
@@ -6,8 +6,8 @@
namespace display
{
LayoutRigid::LayoutRigid(layout_t layout)
: Layout(apos_t(0, 0))
LayoutRigid::LayoutRigid(apos_t apos, dim_t dim, layout_t layout)
: Layout(apos, dim)
, m_grid(static_cast<sz_t>(layout[0].size()),
static_cast<sz_t>(layout.size()))
, m_recs(count_and_pad(layout))
@@ -58,6 +58,8 @@ LayoutRigid::LayoutRigid(layout_t layout)
total += cnt, cnt = 0;
}
}
LayoutRigid::resize(apos, dim);
}
std::size_t LayoutRigid::count_and_pad(layout_t& layout) const
diff --git a/source/window_pivot.cpp b/source/window_pivot.cpp
@@ -5,16 +5,16 @@
namespace display
{
void WindowPivot::resize(apos_t apos, dim_t dim)
std::tuple<apos_t, dim_t> WindowPivot::place() const
{
const auto [cols, rows] = dim;
const auto [cols, rows] = adim();
const auto [posx, posy] = pos();
if (posx > cols || posy > rows) {
return;
return {{0, 0}, {0, 0}};
}
const auto [wdth, hght] = this->dim();
const auto [wdth, hght] = dim();
const display::sz_t zero = 0;
const sz_t wdthm = wdth / 2;
const sz_t hghtm = hght / 2;
@@ -29,7 +29,7 @@ void WindowPivot::resize(apos_t apos, dim_t dim)
break;
case PvtX::Center:
start.x = sub_lim(posx, wdthm, zero);
end.x = add_lim(posx, wdthm, cols);
end.x = add_lim(start.x, wdth, cols);
break;
case PvtX::Right:
end.x = posx;
@@ -44,7 +44,7 @@ void WindowPivot::resize(apos_t apos, dim_t dim)
break;
case PvtY::Center:
start.y = sub_lim(posy, hghtm, zero);
end.y = add_lim(posy, hghtm, rows);
end.y = add_lim(start.y, hght, rows);
break;
case PvtY::Bottom:
end.y = posy;
@@ -52,8 +52,7 @@ void WindowPivot::resize(apos_t apos, dim_t dim)
break;
}
m_apos = apos + start;
m_adim = end - start;
return {apos() + start, end - start};
}
} // namespace display