displayLayout and Rendering TUI library |
git clone git://git.dimitrijedobrota.com/display.git |
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | 0a2055e0d50fb99f07a402275c0bab779453f22c |
parent | 3af9fe76afbf1bfe6f67d7125327dfb2899ce0e7 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Mon, 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:M | CMakeLists.txt | | | +++-- |
M | example/example.cpp | | | ++++--------- |
M | example/navig/navig.cpp | | | +++++++++----------------------------- |
M | include/display/element.hpp | | | +--- |
M | include/display/window.hpp | | | ++++++++++ |
M | include/display/window_pivot.hpp | | | +++++++++++++-------- |
A | source/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