displayLayout and Rendering TUI library |
git clone git://git.dimitrijedobrota.com/display.git |
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | e6af90c90ead078a849819036ea5a91775caf259 |
parent | 8f7a83b9741e3012294f7f4d4876c6be54514213 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Tue, 18 Feb 2025 23:00:09 +0100 |
Consolidate Window types unser WindowPadd template * Hide aplace from derivatives * WindowPivot::place not free function to avoid template inicialization
Diffstat:M | CMakeLists.txt | | | +++- |
M | example/navig/navig.cpp | | | +++++-- |
M | include/display/window.hpp | | | +-------------------------------------------------------- |
A | include/display/window_padd.hpp | | | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | include/display/window_pivot.hpp | | | +++++++------------------------------------------------------ |
M | source/window.cpp | | | +----------------------------------------------------------- |
A | source/window_padd.cpp | | | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | source/window_pivot.cpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
8 files changed, 222 insertions(+), 172 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
display
VERSION 0.1.30
VERSION 0.1.31
DESCRIPTION "TUI library"
HOMEPAGE_URL "git://git.dimitrijedobrota.com/display.git"
LANGUAGES CXX
@@ -21,6 +21,8 @@ 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)
add_library(display::display ALIAS display_display)
diff --git a/example/navig/navig.cpp b/example/navig/navig.cpp
@@ -6,6 +6,7 @@
#include "display/display.hpp"
#include "display/layout.hpp"
#include "display/window_padd.hpp"
#include "display/window_pivot.hpp"
#include "menu.hpp"
@@ -14,7 +15,9 @@ namespace
bool is_finished = false; // NOLINT
class WindowCustom : public display::WindowPivot<display::WindowBorderBox>
using display::WindowPivot, display::WindowPadd, display::WindowType;
class WindowCustom : public WindowPivot<WindowPadd<WindowType::BorderBox>>
{
public:
WindowCustom(display::place_t aplc,
@@ -44,7 +47,7 @@ public:
}
}
display::WindowBorderBox::render();
WindowPadd<WindowType::BorderBox>::render();
std::cout << alec::background_v<alec::Color::DEFAULT>;
std::cout << std::flush;
diff --git a/include/display/window.hpp b/include/display/window.hpp
@@ -17,14 +17,13 @@ public:
{
}
void render() const override {}
void clear() const override;
void input(event& /* unused */) override {}
protected:
static dim_t padding() { return {0, 0}; }
std::ostream& set_cursor(sz_t posy, sz_t posx) const;
static std::ostream& set_cursor(sz_t posy, sz_t posx);
std::ostream& line_next() const;
void line_reset() const;
@@ -42,63 +41,9 @@ protected:
sz_t hgt() const { return ahgt() - m_padding.height; }
private:
friend class WindowBorder;
friend class WindowBox;
friend class WindowBorderBox;
using Element::adim;
using Element::ahgt;
using Element::aplc;
using Element::apos;
using Element::awth;
using Element::axpos;
using Element::aypos;
dim_t m_padding;
mutable display::sz_t m_ypos = 0;
};
class WindowBorder : public Window
{
public:
explicit WindowBorder(place_t aplc)
: Window(aplc, padding())
{
}
void render() const override;
protected:
static dim_t padding() { return {2, 2}; }
};
class WindowBox : public Window
{
public:
explicit WindowBox(place_t aplc)
: Window(aplc, padding())
{
}
void render() const override;
protected:
static dim_t padding() { return {2, 2}; }
};
class WindowBorderBox : public Window
{
public:
explicit WindowBorderBox(place_t aplc)
: Window(aplc, padding())
{
}
void render() const override;
protected:
static dim_t padding() { return {4, 2}; }
};
} // namespace display
diff --git a/include/display/window_padd.hpp b/include/display/window_padd.hpp
@@ -0,0 +1,76 @@
#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
@@ -1,18 +1,22 @@
#pragma once
#include "display/utility.hpp"
#include "display/window.hpp"
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
{
public:
WindowPivot(place_t aplc, piv_t piv, dim_t dim)
: T(place(aplc, piv, dim, T::padding()))
: T(WindowPivot_place(aplc, piv, dim, T::padding()))
, m_piv(piv)
, m_dim(dim)
{
@@ -20,58 +24,7 @@ public:
void resize(place_t aplc) override
{
T::resize(place(aplc, m_piv, m_dim, T::padding()));
}
protected:
static place_t place(place_t aplc, piv_t piv, dim_t dim, dim_t padding)
{
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 sz_t wdthm = wdth / 2;
const sz_t hghtm = hght / 2;
const sz_t zero = 0;
pos_t start;
pos_t end;
using display::add_lim, display::sub_lim;
switch (piv.x) {
case PvtX::Left:
start.x = 0;
end.x = add_lim(start.x, wdth, cols);
break;
case PvtX::Center:
start.x = sub_lim(colsh, wdthm, zero);
end.x = add_lim(start.x, wdth, cols);
break;
case PvtX::Right:
end.x = cols;
start.x = sub_lim(end.x, wdth, zero);
break;
}
switch (piv.y) {
case PvtY::Top:
start.y = 0;
end.y = add_lim(start.y, hght, rows);
break;
case PvtY::Center:
start.y = sub_lim(rowsh, hghtm, zero);
end.y = add_lim(start.y, hght, rows);
break;
case PvtY::Bottom:
end.y = rows;
start.y = sub_lim(end.y, hght, zero);
break;
}
return {aplc.pos + start, end - start};
T::resize(WindowPivot_place(aplc, m_piv, m_dim, T::padding()));
}
private:
diff --git a/source/window.cpp b/source/window.cpp
@@ -19,14 +19,12 @@ void Window::clear() const
std::cout << std::flush;
}
// Window
void Window::line_reset() const
{
m_ypos = ypos();
}
std::ostream& Window::set_cursor(sz_t posy, sz_t posx) const
std::ostream& Window::set_cursor(sz_t posy, sz_t posx)
{
return std::cout << alec::cursor_position(posy + 1, posx + 1);
}
@@ -62,60 +60,4 @@ void Window::line_right(const std::string& text) const
line_next() << std::format("{:>{}}", text, wth());
}
void WindowBorder::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(), ' ');
}
void WindowBox::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 << "┘";
}
void WindowBorderBox::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_padd.cpp b/source/window_padd.cpp
@@ -0,0 +1,72 @@
#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
@@ -0,0 +1,57 @@
#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)
{
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 sz_t wdthm = wdth / 2;
const sz_t hghtm = hght / 2;
const sz_t zero = 0;
pos_t start;
pos_t end;
using display::add_lim, display::sub_lim;
switch (piv.x) {
case PvtX::Left:
start.x = 0;
end.x = add_lim(start.x, wdth, cols);
break;
case PvtX::Center:
start.x = sub_lim(colsh, wdthm, zero);
end.x = add_lim(start.x, wdth, cols);
break;
case PvtX::Right:
end.x = cols;
start.x = sub_lim(end.x, wdth, zero);
break;
}
switch (piv.y) {
case PvtY::Top:
start.y = 0;
end.y = add_lim(start.y, hght, rows);
break;
case PvtY::Center:
start.y = sub_lim(rowsh, hghtm, zero);
end.y = add_lim(start.y, hght, rows);
break;
case PvtY::Bottom:
end.y = rows;
start.y = sub_lim(end.y, hght, zero);
break;
}
return {aplc.pos + start, end - start};
}
} // namespace display