displayLayout and Rendering TUI library |
git clone git://git.dimitrijedobrota.com/display.git |
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | 6d3a184649746770fac3ca971257c3ee1b326c04 |
parent | c3562086eae3af96eb7920d1da1d16a44cfa6cce |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Sun, 9 Feb 2025 09:52:32 +0100 |
Extract types, Window does place calculation
Diffstat:M | CMakeLists.txt | | | ++- |
M | example/example.cpp | | | ++++++---------------------------------------------------------- |
M | include/display/layout.hpp | | | +++------------------------------------------------------------------------------- |
A | include/display/types.hpp | | | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | include/display/window.hpp | | | +++++++++++++++++++++++++++++++++++++ |
M | source/display.cpp | | | ++--- |
A | source/window.cpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
7 files changed, 182 insertions(+), 143 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
display
VERSION 0.1.8
VERSION 0.1.9
DESCRIPTION "TUI library"
HOMEPAGE_URL "https://example.com/"
LANGUAGES CXX
@@ -21,6 +21,7 @@ add_library(
display_display
source/display.cpp
source/layout.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
@@ -4,75 +4,23 @@
#include "alec/alec.hpp"
#include "display/display.hpp"
#include "display/layout.hpp"
#include "display/utility.hpp"
namespace
{
int renderer(display::Window& win)
{
using display::add_lim, display::sub_lim;
using display::PvtX, display::PvtY;
using display::sz_t;
using display::place_t;
static int color_red = 0;
color_red = (color_red + 25) % 256;
sz_t start_x = 0;
sz_t end_x = 0;
sz_t start_y = 0;
sz_t end_y = 0;
const auto [cols, rows] = alec::get_screen_size();
const auto [posx, posy, _] = win.pos();
const auto [wdth, hght] = win.dim();
const display::sz_t zero = 0;
const sz_t wdthm = wdth / 2;
const sz_t hghtm = hght / 2;
// Skip when pivot is outside the boundary
if (posx < 0 || posx > cols) {
return 0;
}
if (posy < 0 || posy > rows) {
return 0;
}
switch (win.piv().x) {
case PvtX::Left:
start_x = posx;
end_x = add_lim(start_x, wdth, cols);
break;
case PvtX::Center:
start_x = sub_lim(posx, wdthm, zero);
end_x = add_lim(posx, wdthm, cols);
break;
case PvtX::Right:
end_x = posx;
start_x = sub_lim(end_x, wdth, zero);
break;
}
switch (win.piv().y) {
case PvtY::Top:
start_y = posy;
end_y = add_lim(start_y, hght, rows);
break;
case PvtY::Center:
start_y = sub_lim(posy, hghtm, zero);
end_y = add_lim(posy, hghtm, rows);
break;
case PvtY::Bottom:
end_y = posy;
start_y = sub_lim(end_y, hght, zero);
break;
}
const auto [start, end] = win.place().value_or(place_t());
color_red = (color_red + 25) % 256;
std::cout << alec::background(color_red, 65, 65);
for (auto ypos = start_y; ypos <= end_y; ypos++) {
std::cout << alec::cursor_position(ypos, start_x);
std::cout << std::string(end_x - start_x + 1, ' ');
for (auto ypos = start.y; ypos <= end.y; ypos++) {
std::cout << alec::cursor_position(ypos, start.x);
std::cout << std::string(end.x - start.x + 1U, ' ');
}
std::cout << alec::background_v<alec::Color::DEFAULT>;
std::cout << std::flush;
diff --git a/include/display/layout.hpp b/include/display/layout.hpp
@@ -1,90 +1,11 @@
#pragma once
#include <cstdint>
#include <utility>
#include <vector>
namespace display
{
using sz_t = std::uint16_t;
struct dim_t
{
dim_t(sz_t wdth = 0, sz_t hght = 0) // NOLINT
: width(wdth)
, height(hght)
{
}
sz_t width;
sz_t height;
};
#include "display/window.hpp"
struct pos_t
{
pos_t(sz_t xpos = 0, sz_t ypos = 0, sz_t zpos = 0) // NOLINT
: x(xpos)
, y(ypos)
, z(zpos)
{
}
sz_t x;
sz_t y;
sz_t z;
};
enum class PvtX : std::uint8_t
{
Left,
Center,
Right
};
enum class PvtY : std::uint8_t
{
Top,
Center,
Bottom
};
struct piv_t
{
piv_t(PvtX pvtx = PvtX::Left, PvtY pvty = PvtY::Top) // NOLINT
: x(pvtx)
, y(pvty)
{
}
PvtX x;
PvtY y;
};
class Window
namespace display
{
public:
Window(pos_t pos, dim_t dim, piv_t piv = {})
: m_pos(pos)
, m_dim(dim)
, m_piv(piv)
{
}
const auto& pos() const { return m_pos; }
auto& pos() { return m_pos; }
const auto& dim() const { return m_dim; }
auto& dim() { return m_dim; }
const auto& piv() const { return m_piv; }
auto& piv() { return m_piv; }
private:
pos_t m_pos;
dim_t m_dim;
piv_t m_piv;
};
class LayoutFree
{
diff --git a/include/display/types.hpp b/include/display/types.hpp
@@ -0,0 +1,74 @@
#pragma once
#include <cstdint>
namespace display
{
using sz_t = std::uint16_t;
struct dim_t
{
dim_t(sz_t wdth = 0, sz_t hght = 0) // NOLINT
: width(wdth)
, height(hght)
{
}
sz_t width;
sz_t height;
};
struct pos_t
{
pos_t(sz_t xpos = 0, sz_t ypos = 0, sz_t zpos = 0) // NOLINT
: x(xpos)
, y(ypos)
, z(zpos)
{
}
sz_t x;
sz_t y;
sz_t z;
};
struct place_t
{
place_t(pos_t pstart = {}, pos_t pend = {}) // NOLINT
: start(pstart)
, end(pend)
{
}
pos_t start;
pos_t end;
};
enum class PvtX : std::uint8_t
{
Left,
Center,
Right
};
enum class PvtY : std::uint8_t
{
Top,
Center,
Bottom
};
struct piv_t
{
piv_t(PvtX pvtx = PvtX::Left, PvtY pvty = PvtY::Top) // NOLINT
: x(pvtx)
, y(pvty)
{
}
PvtX x;
PvtY y;
};
} // namespace display
diff --git a/include/display/window.hpp b/include/display/window.hpp
@@ -0,0 +1,37 @@
#pragma once
#include <optional>
#include "display/types.hpp"
namespace display
{
class Window
{
public:
Window(pos_t pos, dim_t dim, piv_t piv = {})
: m_pos(pos)
, m_dim(dim)
, m_piv(piv)
{
}
const auto& pos() const { return m_pos; }
auto& pos() { return m_pos; }
const auto& dim() const { return m_dim; }
auto& dim() { return m_dim; }
const auto& piv() const { return m_piv; }
auto& piv() { return m_piv; }
std::optional<place_t> place() const;
private:
pos_t m_pos;
dim_t m_dim;
piv_t m_piv;
};
} // namespace display
diff --git a/source/display.cpp b/source/display.cpp
@@ -1,9 +1,8 @@
#include <iostream>
#include <csignal>
#include <stdexcept>
#include "display/display.hpp"
#include <signal.h>
#include <termios.h>
#include <unistd.h>
@@ -24,7 +23,7 @@ namespace display
static int start_count = 0; // NOLINT
static bool resized = false; // NOLINT
void handle_sigwinch(int)
void handle_sigwinch(int /* unused */) // NOLINT misc-use-internal-linkage
{
resized = true;
}
diff --git a/source/window.cpp b/source/window.cpp
@@ -0,0 +1,59 @@
#include "display/window.hpp"
#include "alec/alec.hpp"
#include "display/utility.hpp"
namespace display
{
std::optional<place_t> Window::place() const
{
const auto [cols, rows] = alec::get_screen_size();
const auto [posx, posy, _] = pos();
if (posx > cols || posy > rows) {
return {};
}
const auto [wdth, hght] = dim();
const display::sz_t zero = 0;
const sz_t wdthm = wdth / 2;
const sz_t hghtm = hght / 2;
pos_t start;
pos_t end;
switch (piv().x) {
case PvtX::Left:
start.x = posx;
end.x = add_lim(start.x, wdth, cols);
break;
case PvtX::Center:
start.x = sub_lim(posx, wdthm, zero);
end.x = add_lim(posx, wdthm, cols);
break;
case PvtX::Right:
end.x = posx;
start.x = sub_lim(end.x, wdth, zero);
break;
}
switch (piv().y) {
case PvtY::Top:
start.y = posy;
end.y = add_lim(start.y, hght, rows);
break;
case PvtY::Center:
start.y = sub_lim(posy, hghtm, zero);
end.y = add_lim(posy, hghtm, rows);
break;
case PvtY::Bottom:
end.y = posy;
start.y = sub_lim(end.y, hght, zero);
break;
}
return place_t(start, end);
}
} // namespace display