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 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