displayLayout and Rendering TUI library |
git clone git://git.dimitrijedobrota.com/display.git |
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | 33f7aed76a00f28a19d54178ac2e8609203a1708 |
parent | 6bd6730d2f34d6a588603fa618e21fe4080a04e6 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Fri, 14 Feb 2025 13:32:33 +0100 |
Render function should not take parameters * Render should be callable from any place * Add absolute position (a_pos) for type safety * Resize now needs to take and remember apos
Diffstat:M | CMakeLists.txt | | | +- |
M | example/example.cpp | | | ++++----- |
M | include/display/layout.hpp | | | +++++++++++++----- |
M | include/display/layout_free.hpp | | | ++++++--- |
M | include/display/layout_rigid.hpp | | | +++++++-- |
D | include/display/pane.hpp | | | --------------- |
M | include/display/screen.hpp | | | +++++++------ |
M | include/display/types.hpp | | | ++++++++++++++++++++++++++++++++++++++- |
D | include/display/widget.hpp | | | ---------------- |
M | include/display/window.hpp | | | +- |
M | include/display/window_pivot.hpp | | | +- |
M | source/display.cpp | | | +++--- |
M | source/layout_free.cpp | | | +++--- |
M | source/layout_rigid.cpp | | | +++++++++++---------- |
M | source/screen.cpp | | | ++++++++------ |
15 files changed, 103 insertions(+), 78 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
display
VERSION 0.1.19
VERSION 0.1.20
DESCRIPTION "TUI library"
HOMEPAGE_URL "https://example.com/"
LANGUAGES CXX
diff --git a/example/example.cpp b/example/example.cpp
@@ -18,12 +18,12 @@ public:
{
}
void render(display::place_t plc) const override
void render(display::aplace_t aplc) const override
{
static int color_red = 0;
color_red = (color_red + 25) % 256;
const auto [start, end] = plc;
const auto [start, end] = aplc;
std::cout << alec::background(color_red, 65, 65);
for (auto ypos = start.y; ypos < end.y; ypos++) {
@@ -54,9 +54,9 @@ public:
append<WindowCustom>(dim_t(12, 4), piv_t(PvtX::Center, PvtY::Center));
}
void resize(display::dim_t dim) override
void resize(display::apos_t apos, display::dim_t dim) override
{
LayoutFree::resize(dim);
LayoutFree::resize(apos, dim);
const auto [width, height] = dim;
const display::sz_t midw = width / 2;
@@ -79,7 +79,6 @@ public:
int main()
{
try {
using namespace std::placeholders; // NOLINT
using namespace display; // NOLINT
auto& display = Display::display();
diff --git a/include/display/layout.hpp b/include/display/layout.hpp
@@ -8,23 +8,31 @@ namespace display
class Layout
{
public:
Layout() = default;
explicit Layout(apos_t apos)
: m_apos(apos)
{
}
Layout(const Layout&) = delete;
Layout& operator=(const Layout&) = delete;
Layout(Layout&&) = delete;
Layout& operator=(Layout&&) = delete;
Layout(Layout&&) = default;
Layout& operator=(Layout&&) = default;
virtual ~Layout() = default;
virtual void resize(apos_t apos, dim_t dim) { m_apos = apos, m_dim = dim; }
virtual void render() const = 0;
protected:
const dim_t& dim() const { return m_dim; }
dim_t& dim() { return m_dim; }
virtual void resize(dim_t dim) { m_dim = dim; }
virtual void render(pos_t pos) const = 0;
const apos_t& apos() const { return m_apos; }
apos_t& apos() { return m_apos; }
private:
apos_t m_apos;
dim_t m_dim;
};
diff --git a/include/display/layout_free.hpp b/include/display/layout_free.hpp
@@ -1,11 +1,9 @@
#pragma once
#include <functional>
#include <memory>
#include <vector>
#include "display/layout.hpp"
#include "display/types.hpp"
#include "display/window.hpp"
namespace display
@@ -14,6 +12,11 @@ namespace display
class LayoutFree : public Layout
{
public:
LayoutFree()
: Layout({0, 0})
{
}
Window* operator[](std::size_t idx) { return m_wins[idx].get(); }
const Window* operator[](std::size_t idx) const { return m_wins[idx].get(); }
@@ -36,7 +39,7 @@ public:
return *dynamic_cast<T*>(m_wins[idx].get());
}
void render(pos_t pos) const override;
void render() const override;
private:
std::vector<std::unique_ptr<Window>> m_wins;
diff --git a/include/display/layout_rigid.hpp b/include/display/layout_rigid.hpp
@@ -18,8 +18,8 @@ public:
const auto& operator[](std::size_t idx) const { return m_recs[idx].screen; }
auto& operator[](std::size_t idx) { return m_recs[idx].screen; }
void resize(dim_t dim) override;
void render(pos_t pos) const override;
void resize(apos_t apos, dim_t dim) override;
void render() const override;
private:
auto calc_width(dim_t share) const;
@@ -31,6 +31,11 @@ private:
struct record_t
{
record_t()
: screen(apos_t(0, 0))
{
}
Screen screen;
dim_t start = {0xFFFF, 0xFFFF};
dim_t dim;
diff --git a/include/display/pane.hpp b/include/display/pane.hpp
@@ -1,15 +0,0 @@
#pragma once
#include "display/display_export.hpp"
namespace display
{
class DISPLAY_EXPORT pane
{
public:
private:
};
} // namespace display
diff --git a/include/display/screen.hpp b/include/display/screen.hpp
@@ -11,8 +11,8 @@ namespace display
class Screen
{
public:
Screen(dim_t dim = {}) // NOLINT
: m_dim(dim)
explicit Screen(apos_t apos)
: m_apos(apos)
{
}
@@ -24,8 +24,6 @@ public:
~Screen() = default;
const auto& dim() const { return m_dim; }
template<typename T, class... Args>
T& set_layout(Args&&... args)
{
@@ -45,10 +43,13 @@ public:
return *dynamic_cast<T*>(m_layout.get());
}
void resize(dim_t dim);
void render(pos_t pos) const;
bool has_layout() const { return m_layout != nullptr; }
void resize(apos_t apos, dim_t dim);
void render() const;
private:
apos_t m_apos;
dim_t m_dim;
std::unique_ptr<Layout> m_layout;
diff --git a/include/display/types.hpp b/include/display/types.hpp
@@ -46,6 +46,26 @@ struct pos_t
sz_t y;
};
struct apos_t
{
apos_t(sz_t xpos, sz_t ypos)
: x(xpos)
, y(ypos)
{
}
apos_t operator+(pos_t rhs) const
{
return {
static_cast<std::uint16_t>(x + rhs.x),
static_cast<std::uint16_t>(y + rhs.y),
};
}
sz_t x;
sz_t y;
};
struct place_t
{
place_t(pos_t pstart = {}, pos_t pend = {}) // NOLINT
@@ -54,12 +74,29 @@ struct place_t
{
}
place_t operator+(pos_t rhs) const { return {start + rhs, end + rhs}; }
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;
};
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/widget.hpp b/include/display/widget.hpp
@@ -1,16 +0,0 @@
#pragma once
#include "display/display_export.hpp"
namespace display
{
class DISPLAY_EXPORT widget
{
public:
private:
};
} // namespace display
diff --git a/include/display/window.hpp b/include/display/window.hpp
@@ -21,7 +21,7 @@ public:
virtual ~Window() = default;
virtual std::optional<place_t> place(dim_t bounds) = 0;
virtual void render(place_t place) const = 0;
virtual void render(aplace_t place) const = 0;
};
} // namespace display
diff --git a/include/display/window_pivot.hpp b/include/display/window_pivot.hpp
@@ -26,7 +26,7 @@ public:
auto& piv() { return m_piv; }
std::optional<place_t> place(dim_t bounds) override;
void render(place_t place) const override = 0;
void render(aplace_t place) const override = 0;
private:
pos_t m_pos;
diff --git a/source/display.cpp b/source/display.cpp
@@ -28,7 +28,7 @@ Display& Display::display()
}
Display::Display()
: m_screen(alec::get_screen_size())
: m_screen(apos_t(0, 0))
{
struct sigaction old_sig_action = {};
sigaction(SIGWINCH, nullptr, &old_sig_action);
@@ -72,7 +72,7 @@ event Display::get_event() // NOLINT
void Display::set_resized()
{
m_screen.resize(alec::get_screen_size());
m_screen.resize(apos_t(0, 0), alec::get_screen_size());
m_is_resized = true;
}
@@ -88,7 +88,7 @@ bool Display::get_resized() const
void Display::render()
{
m_screen.render({0, 0});
m_screen.render();
}
} // namespace display
diff --git a/source/layout_free.cpp b/source/layout_free.cpp
@@ -3,16 +3,16 @@
namespace display
{
void LayoutFree::render(pos_t pos) const
void LayoutFree::render() const
{
for (const auto& win : m_wins) {
const auto plc = win->place(this->dim());
const auto plc = win->place(dim());
if (!plc.has_value()) {
continue;
}
win->render(plc.value() + pos);
win->render(apos() + plc.value());
}
}
diff --git a/source/layout_rigid.cpp b/source/layout_rigid.cpp
@@ -7,7 +7,8 @@ namespace display
{
LayoutRigid::LayoutRigid(layout_t layout)
: m_grid(static_cast<sz_t>(layout[0].size()),
: Layout(apos_t(0, 0))
, m_grid(static_cast<sz_t>(layout[0].size()),
static_cast<sz_t>(layout.size()))
, m_recs(count_and_pad(layout))
{
@@ -92,22 +93,22 @@ auto LayoutRigid::calc_height(dim_t share) const
return static_cast<sz_t>(dim().height / m_grid.height * share.height);
}
void LayoutRigid::resize(dim_t dim)
void LayoutRigid::resize(apos_t apos, dim_t dim)
{
Layout::resize(dim);
Layout::resize(apos, dim);
for (auto& [screen, _, rdim] : m_recs) {
for (auto& [screen, start, rdim] : m_recs) {
const dim_t size = {calc_width(rdim), calc_height(rdim)};
screen.resize(size);
const pos_t rel = {calc_width(start), calc_height(start)};
const apos_t abs = this->apos() + rel;
screen.resize(abs, size);
}
}
void LayoutRigid::render(pos_t pos) const
void LayoutRigid::render() const
{
for (const auto& [screen, start, _] : m_recs) {
const pos_t rel = {calc_width(start), calc_height(start)};
const pos_t abs = pos + rel;
screen.render(abs);
for (const auto& [screen, _, __] : m_recs) {
screen.render();
}
}
diff --git a/source/screen.cpp b/source/screen.cpp
@@ -3,18 +3,20 @@
namespace display
{
void Screen::resize(dim_t dim)
void Screen::resize(apos_t apos, dim_t dim)
{
m_apos = apos;
m_dim = dim;
if (m_layout != nullptr) {
m_layout->resize(m_dim);
if (has_layout()) {
m_layout->resize(apos, m_dim);
}
}
void Screen::render(pos_t pos) const
void Screen::render() const
{
if (m_layout != nullptr) {
m_layout->render(pos);
if (has_layout()) {
m_layout->render();
}
}