displayLayout and Rendering TUI library |
git clone git://git.dimitrijedobrota.com/display.git |
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | de1902c7b94dae6042963b6eee1bb79dd9a3f891 |
parent | e6af90c90ead078a849819036ea5a91775caf259 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Wed, 19 Feb 2025 00:04:40 +0100 |
Great simplification by cutting out BS * padd_t with all 4 directions * No more WindowPadding and WindowTypes * Every windows specifies it's own padding * Window::render() draws it to screen * Opionaly Window::render_border() draws a border around everything * No need for WindowPivot to be a template
Diffstat:M | CMakeLists.txt | | | +-- |
M | example/example.cpp | | | ++-- |
M | example/navig/navig.cpp | | | +++++----- |
M | include/display/types.hpp | | | +++++++++++++++++++++++++++++++++++++ |
M | include/display/window.hpp | | | +++++++++++++++++++----------- |
D | include/display/window_padd.hpp | | | ---------------------------------------------------------------------------- |
M | include/display/window_pivot.hpp | | | ++++++----------- |
M | source/window.cpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++----- |
D | source/window_padd.cpp | | | ------------------------------------------------------------------------ |
M | source/window_pivot.cpp | | | +++-- |
10 files changed, 122 insertions(+), 186 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
display
VERSION 0.1.31
VERSION 0.1.32
DESCRIPTION "TUI library"
HOMEPAGE_URL "git://git.dimitrijedobrota.com/display.git"
LANGUAGES CXX
@@ -21,7 +21,6 @@ add_library(
display_display
source/display.cpp
source/window.cpp
source/window_padd.cpp
source/window_pivot.cpp
)
target_link_libraries(display_display PUBLIC alec::alec)
diff --git a/example/example.cpp b/example/example.cpp
@@ -12,11 +12,11 @@ namespace
using display::PvtX, display::PvtY;
using display::sz_t, display::dim_t, display::piv_t, display::place_t;
class WindowCustom : public display::WindowPivot<display::Window>
class WindowCustom : public display::WindowPivot
{
public:
explicit WindowCustom(place_t aplc, piv_t piv, dim_t dim)
: WindowPivot(aplc, piv, dim)
: WindowPivot(aplc, {0, 0}, piv, dim)
{
}
diff --git a/example/navig/navig.cpp b/example/navig/navig.cpp
@@ -6,7 +6,6 @@
#include "display/display.hpp"
#include "display/layout.hpp"
#include "display/window_padd.hpp"
#include "display/window_pivot.hpp"
#include "menu.hpp"
@@ -15,15 +14,15 @@ namespace
bool is_finished = false; // NOLINT
using display::WindowPivot, display::WindowPadd, display::WindowType;
using display::WindowPivot;
class WindowCustom : public WindowPivot<WindowPadd<WindowType::BorderBox>>
class WindowCustom : public WindowPivot
{
public:
WindowCustom(display::place_t aplc,
display::piv_t piv,
const example::menu_t& menu)
: WindowPivot(aplc, piv, calc_dim(menu))
: WindowPivot(aplc, {4, 5, 2, 4}, piv, calc_dim(menu))
, m_menu(menu)
{
}
@@ -47,7 +46,8 @@ public:
}
}
WindowPadd<WindowType::BorderBox>::render();
WindowPivot::render();
Window::render_border();
std::cout << alec::background_v<alec::Color::DEFAULT>;
std::cout << std::flush;
diff --git a/include/display/types.hpp b/include/display/types.hpp
@@ -12,6 +12,35 @@ using event = alec::event;
using sz_t = std::uint16_t;
struct padd_t
{
padd_t()
: padd_t(0, 0, 0, 0)
{
}
padd_t(sz_t width, sz_t height) // NOLINT
: padd_t(width, width, height, height)
{
}
padd_t(sz_t leftpos, sz_t rightpos, sz_t toppos, sz_t bottompos) // NOLINT
: left(leftpos)
, right(rightpos)
, top(toppos)
, bottom(bottompos)
{
}
sz_t width() const { return left + right; }
sz_t height() const { return top + bottom; }
sz_t left;
sz_t right;
sz_t top;
sz_t bottom;
};
struct dim_t
{
dim_t()
@@ -39,6 +68,14 @@ struct dim_t
};
}
dim_t operator+(padd_t rhs) const
{
return {
static_cast<sz_t>(width + rhs.width()),
static_cast<sz_t>(height + rhs.height()),
};
}
sz_t width;
sz_t height;
};
diff --git a/include/display/window.hpp b/include/display/window.hpp
@@ -5,23 +5,23 @@
namespace display
{
class Window : public Element
{
public:
using ustring = std::basic_string<unsigned char>;
explicit Window(place_t aplc, dim_t padding = {0, 0})
explicit Window(place_t aplc, padd_t padd)
: Element(aplc)
, m_padding(padding)
, m_padd(padd)
{
}
void render() const override;
void clear() const override;
void input(event& /* unused */) override {}
void render_border() const;
protected:
static dim_t padding() { return {0, 0}; }
padd_t padd() const { return m_padd; }
static std::ostream& set_cursor(sz_t posy, sz_t posx);
std::ostream& line_next() const;
@@ -35,13 +35,21 @@ protected:
place_t plc() const { return {pos(), dim()}; }
pos_t pos() const { return {xpos(), ypos()}; }
dim_t dim() const { return {wth(), hgt()}; }
sz_t xpos() const { return axpos() + (m_padding.width / 2); }
sz_t ypos() const { return aypos() + (m_padding.height / 2); }
sz_t wth() const { return awth() - m_padding.width; }
sz_t hgt() const { return ahgt() - m_padding.height; }
sz_t xpos() const { return axpos() + m_padd.left; }
sz_t ypos() const { return aypos() + m_padd.top; }
sz_t wth() const { return awth() - m_padd.width(); }
sz_t hgt() const { return ahgt() - m_padd.height(); }
private:
dim_t m_padding;
using Element::adim;
using Element::ahgt;
using Element::aplc;
using Element::apos;
using Element::awth;
using Element::axpos;
using Element::aypos;
padd_t m_padd;
mutable display::sz_t m_ypos = 0;
};
diff --git a/include/display/window_padd.hpp b/include/display/window_padd.hpp
@@ -1,76 +0,0 @@
#pragma once
#include "display/window.hpp"
namespace display
{
enum class WindowType : std::uint8_t
{
Bare,
Border,
Box,
BorderBox,
};
template<WindowType T>
class WindowPadd : public Window
{
public:
explicit WindowPadd(place_t aplc)
: Window(aplc, padding())
{
}
void render() const override;
protected:
static dim_t padding();
private:
using Element::adim;
using Element::ahgt;
using Element::aplc;
using Element::apos;
using Element::awth;
using Element::axpos;
using Element::aypos;
};
template<>
inline dim_t WindowPadd<WindowType::Bare>::padding()
{
return {0, 0};
}
template<>
inline dim_t WindowPadd<WindowType::Border>::padding()
{
return {2, 2};
}
template<>
inline dim_t WindowPadd<WindowType::Box>::padding()
{
return {2, 2};
}
template<>
inline dim_t WindowPadd<WindowType::BorderBox>::padding()
{
return {4, 2};
}
template<>
void WindowPadd<WindowType::Bare>::render() const;
template<>
void WindowPadd<WindowType::Border>::render() const;
template<>
void WindowPadd<WindowType::Box>::render() const;
template<>
void WindowPadd<WindowType::BorderBox>::render() const;
} // namespace display
diff --git a/include/display/window_pivot.hpp b/include/display/window_pivot.hpp
@@ -5,18 +5,11 @@
namespace display
{
place_t WindowPivot_place(place_t aplc, // NOLINT
piv_t piv,
dim_t dim,
dim_t padding);
template<typename T>
requires(std::is_base_of_v<Window, T>)
class WindowPivot : public T
class WindowPivot : public Window
{
public:
WindowPivot(place_t aplc, piv_t piv, dim_t dim)
: T(WindowPivot_place(aplc, piv, dim, T::padding()))
WindowPivot(place_t aplc, padd_t padd, piv_t piv, dim_t dim)
: Window(place(aplc, piv, dim + padd), padd)
, m_piv(piv)
, m_dim(dim)
{
@@ -24,10 +17,12 @@ public:
void resize(place_t aplc) override
{
T::resize(WindowPivot_place(aplc, m_piv, m_dim, T::padding()));
Window::resize(place(aplc, m_piv, m_dim + padd()));
}
private:
static place_t place(place_t aplc, piv_t piv, dim_t dim);
piv_t m_piv;
dim_t m_dim;
};
diff --git a/source/window.cpp b/source/window.cpp
@@ -7,6 +7,41 @@
namespace display
{
void Window::render() const
{
const auto space = std::string(awth(), ' ');
for (sz_t i = aypos(); i < aypos() + m_padd.top; i++) {
set_cursor(i, axpos()) << space;
}
for (sz_t i = aypos() + ahgt() - m_padd.bottom; i < aypos() + ahgt(); i++) {
set_cursor(i, axpos()) << space;
}
}
void Window::render_border() const
{
set_cursor(aypos(), axpos());
std::cout << "┌";
for (sz_t i = 2; i < awth(); i++) {
std::cout << "─";
}
std::cout << "┐";
for (sz_t i = aypos() + 1; i < aypos() + ahgt(); i++) {
set_cursor(i, axpos()) << "│";
set_cursor(i, axpos() + awth() - 1) << "│";
}
set_cursor(aypos() + ahgt() - 1, axpos());
std::cout << "└";
for (sz_t i = 2; i < awth(); i++) {
std::cout << "─";
}
std::cout << "┘";
}
void Window::clear() const
{
std::cout << alec::background_v<alec::Color::DEFAULT>;
@@ -37,27 +72,36 @@ std::ostream& Window::line_next() const
return null;
}
return set_cursor(m_ypos++, xpos());
return set_cursor(m_ypos++, axpos());
}
void Window::line_empty() const
{
line_next() << std::string(wth(), ' ');
line_next() << std::string(awth(), ' ');
}
void Window::line_left(const std::string& text) const
{
line_next() << std::format("{:<{}}", text, wth());
const auto left = std::string(m_padd.left, ' ');
const auto right = std::string(m_padd.right, ' ');
line_next() << left << std::format("{:<{}}", text, wth()) << right;
}
void Window::line_center(const std::string& text) const
{
line_next() << std::format("{:^{}}", text, wth());
const auto left = std::string(m_padd.left, ' ');
const auto right = std::string(m_padd.right, ' ');
line_next() << left << std::format("{:^{}}", text, wth()) << right;
}
void Window::line_right(const std::string& text) const
{
line_next() << std::format("{:>{}}", text, wth());
const auto left = std::string(m_padd.left, ' ');
const auto right = std::string(m_padd.right, ' ');
line_next() << left << std::format("{:>{}}", text, wth()) << right;
}
} // namespace display
diff --git a/source/window_padd.cpp b/source/window_padd.cpp
@@ -1,72 +0,0 @@
#include <iostream>
#include "display/window_padd.hpp"
namespace display
{
template<>
void WindowPadd<WindowType::Bare>::render() const
{
}
template<>
void WindowPadd<WindowType::Border>::render() const
{
set_cursor(aypos(), axpos()) << std::string(awth(), ' ');
for (sz_t i = ypos(); i < ypos() + hgt(); i++) {
set_cursor(i, axpos()) << ' ';
set_cursor(i, axpos() + awth() - 1) << ' ';
}
set_cursor(aypos() + ahgt() - 1, axpos()) << std::string(awth(), ' ');
}
template<>
void WindowPadd<WindowType::Box>::render() const
{
set_cursor(aypos(), axpos());
std::cout << "┌";
for (sz_t i = 0; i < wth(); i++) {
std::cout << "─";
}
std::cout << "┐";
for (sz_t i = ypos(); i < ypos() + hgt(); i++) {
set_cursor(i, axpos()) << "│";
set_cursor(i, axpos() + awth() - 1) << "│";
}
set_cursor(aypos() + ahgt() - 1, axpos());
std::cout << "└";
for (sz_t i = 0; i < wth(); i++) {
std::cout << "─";
}
std::cout << "┘";
}
template<>
void WindowPadd<WindowType::BorderBox>::render() const
{
set_cursor(aypos(), axpos());
std::cout << "┌─";
for (sz_t i = 0; i < wth(); i++) {
std::cout << "─";
}
std::cout << "─┐";
for (sz_t i = ypos(); i < ypos() + hgt(); i++) {
set_cursor(i, axpos()) << "│ ";
set_cursor(i, axpos() + awth() - 2) << " │";
}
set_cursor(aypos() + ahgt() - 1, axpos());
std::cout << "└─";
for (sz_t i = 0; i < wth(); i++) {
std::cout << "─";
}
std::cout << "─┘";
}
} // namespace display
diff --git a/source/window_pivot.cpp b/source/window_pivot.cpp
@@ -1,16 +1,17 @@
#include "display/window_pivot.hpp"
#include "display/utility.hpp"
namespace display
{
place_t WindowPivot_place(place_t aplc, piv_t piv, dim_t dim, dim_t padding)
place_t WindowPivot::place(place_t aplc, piv_t piv, dim_t dim)
{
const auto [cols, rows] = aplc.dim;
const sz_t colsh = cols / 2;
const sz_t rowsh = rows / 2;
const auto [wdth, hght] = dim + padding;
const auto [wdth, hght] = dim;
const sz_t wdthm = wdth / 2;
const sz_t hghtm = hght / 2;