display

Layout and Rendering TUI library
git clone git://git.dimitrijedobrota.com/display.git
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING |

commit0a2055e0d50fb99f07a402275c0bab779453f22c
parent3af9fe76afbf1bfe6f67d7125327dfb2899ce0e7
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateMon, 17 Feb 2025 12:23:22 +0100

Window line drawing methods * Windows's aplace represents the rendering area * Layout gives entirety of it's space to window. * Window figures out which part it'll occupy * This happens during construction and resize * This method has to be static so it can be called during construction

Diffstat:
MCMakeLists.txt|+++--
Mexample/example.cpp|++++---------
Mexample/navig/navig.cpp|+++++++++-----------------------------
Minclude/display/element.hpp|+---
Minclude/display/window.hpp|++++++++++
Minclude/display/window_pivot.hpp|+++++++++++++--------
Asource/window.cpp|+++++++++++++++++++++++++++++++++++++

7 files changed, 77 insertions(+), 51 deletions(-)


diff --git a/CMakeLists.txt b/CMakeLists.txt

@@ -4,9 +4,9 @@ include(cmake/prelude.cmake)

project(
display
VERSION 0.1.25
VERSION 0.1.26
DESCRIPTION "TUI library"
HOMEPAGE_URL "https://example.com/"
HOMEPAGE_URL "git://git.dimitrijedobrota.com/display.git"
LANGUAGES CXX
)

@@ -20,6 +20,7 @@ find_package(alec 0.1.13 CONFIG REQUIRED)

add_library(
display_display
source/display.cpp
source/window.cpp
)
target_link_libraries(display_display PUBLIC alec::alec)
add_library(display::display ALIAS display_display)

diff --git a/example/example.cpp b/example/example.cpp

@@ -1,5 +1,4 @@

#include <iostream>
#include <string>
#include <alec/alec.hpp>

@@ -24,17 +23,13 @@ public:

void render() const override
{
static int color_red = 0;
color_red = (color_red + 25) % 256;
const auto [pos, dim] = place();
const auto [x, y] = pos;
const auto [w, h] = dim;
color_red = (color_red + 25) % 256;
std::cout << alec::background(color_red, 65, 65);
for (auto ypos = y; ypos < y + h; ypos++) {
std::cout << alec::cursor_position(ypos + 1, x + 1);
std::cout << std::string(w, ' ');
line_empty(/* reset = */ true);
for (std::size_t i = 1; i < ahgt(); i++) {
line_empty();
}
std::cout << alec::background_v<alec::Color::DEFAULT>;

diff --git a/example/navig/navig.cpp b/example/navig/navig.cpp

@@ -1,4 +1,3 @@

#include <format>
#include <iostream>
#include <stack>
#include <string>

@@ -37,51 +36,32 @@ public:

std::cout << alec::background_v<alec::Color::DEFAULT>;
std::cout << alec::foreground_v<alec::Color::DEFAULT>;
const auto [apos, adim] = place();
const auto [x, y] = apos;
const auto [w, h] = adim;
display::sz_t ypos = y;
const auto cursor = [&]() { return alec::cursor_position(++ypos, x + 1); };
for (std::size_t i = 0; i < h; i++) {
std::cout << cursor() << std::string(w, ' ');
line_empty(/* reset = */ true);
for (std::size_t i = 1; i < ahgt(); i++) {
line_empty();
}
std::cout << std::flush;
}
void render() const override
{
const auto [apos, adim] = place();
const auto [x, y] = apos;
const auto [w, h] = adim;
display::sz_t ypos = y;
auto cursor = [&]() { return alec::cursor_position(++ypos, x + 1); };
auto empty = [&]() { std::cout << cursor() << std::string(w, ' '); };
auto center = [&](const std::string& value)
{ std::cout << cursor() << std::format("{:^{}}", value, w); };
auto right = [&](const std::string& value)
{ std::cout << cursor() << std::format("{:>{}} ", value, w - 1); };
std::cout << alec::background_v<alec::Color::BLUE>;
empty(), center(m_menu.title), empty();
line_empty(/* reset = */ true);
line_center(m_menu.title);
line_empty();
for (std::size_t i = 0; i < m_menu.items.size(); i++) {
if (m_selected == i) {
std::cout << alec::foreground_v<alec::Color::GREEN>;
}
right(m_menu.items[i].prompt);
line_right(m_menu.items[i].prompt);
if (m_selected == i) {
std::cout << alec::foreground_v<alec::Color::DEFAULT>;
}
}
empty();
line_empty();
std::cout << alec::background_v<alec::Color::DEFAULT>;
std::cout << std::flush;

diff --git a/include/display/element.hpp b/include/display/element.hpp

@@ -3,9 +3,7 @@

#include "display/types.hpp"
namespace display
{
class Element
{ class Element
{
public:
explicit Element(aplace_t aplc)

diff --git a/include/display/window.hpp b/include/display/window.hpp

@@ -15,6 +15,16 @@ public:

}
void input(event& /* unused */) override {}
protected:
std::ostream& next_line(bool reset = false) const;
void line_empty(bool reset = false) const;
void line_left(const std::string& text) const;
void line_center(const std::string& text) const;
void line_right(const std::string& text) const;
private:
mutable display::sz_t m_ypos = 0;
};
} // namespace display

diff --git a/include/display/window_pivot.hpp b/include/display/window_pivot.hpp

@@ -1,7 +1,7 @@

#pragma once
#include "display/window.hpp"
#include "display/utility.hpp"
#include "display/window.hpp"
namespace display
{

@@ -10,20 +10,25 @@ class WindowPivot : public Window

{
public:
WindowPivot(aplace_t aplc, piv_t piv, dim_t dim)
: Window(aplc)
: Window(place(aplc, piv, dim))
, m_piv(piv)
, m_dim(dim)
{
}
void resize(aplace_t aplc) override
{
Window::resize(place(aplc, m_piv, m_dim));
}
protected:
aplace_t place() const
static aplace_t place(aplace_t aplc, piv_t piv, dim_t dim)
{
const auto [cols, rows] = adim();
const auto [cols, rows] = aplc.adim;
const sz_t colsh = cols / 2;
const sz_t rowsh = rows / 2;
const auto [wdth, hght] = m_dim;
const auto [wdth, hght] = dim;
const sz_t wdthm = wdth / 2;
const sz_t hghtm = hght / 2;

@@ -34,7 +39,7 @@ protected:

using display::add_lim, display::sub_lim;
switch (m_piv.x) {
switch (piv.x) {
case PvtX::Left:
start.x = 0;
end.x = add_lim(start.x, wdth, cols);

@@ -49,7 +54,7 @@ protected:

break;
}
switch (m_piv.y) {
switch (piv.y) {
case PvtY::Top:
start.y = 0;
end.y = add_lim(start.y, hght, rows);

@@ -64,7 +69,7 @@ protected:

break;
}
return {apos() + start, end - start};
return {aplc.apos + start, end - start};
}
private:

diff --git a/source/window.cpp b/source/window.cpp

@@ -0,0 +1,37 @@

#include <format>
#include <iostream>
#include "display/window.hpp"
namespace display
{
std::ostream& Window::next_line(bool reset) const
{
if (reset) {
m_ypos = aypos();
}
return std::cout << alec::cursor_position(++m_ypos, axpos() + 1);
}
void Window::line_empty(bool reset) const
{
next_line(reset) << std::string(awth(), ' ');
}
void Window::line_left(const std::string& text) const
{
next_line() << std::format(" {:<{}} ", text, awth() - 2);
}
void Window::line_center(const std::string& text) const
{
next_line() << std::format("{:^{}}", text, awth());
}
void Window::line_right(const std::string& text) const
{
next_line() << std::format(" {:>{}} ", text, awth() - 2);
}
} // namespace display