boxes now available

This commit is contained in:
2026-04-20 19:50:51 -06:00
parent e8881f3a76
commit fa519d937f
7 changed files with 148 additions and 15 deletions

View File

@@ -1,4 +1,5 @@
#include <desktoplib/terminal/Terminal.hpp>
#include <desktoplib/terminal/ui/Box.hpp>
#include <iostream>
#include <string>
#include <thread>
@@ -12,27 +13,27 @@ int main() {
term.altbuff(true) // Use alternative buffer (clean exit)
.cursor(false) // Hide cursor for cleaner UI
.cls() // Clear screen
.fill("\033[48;2;20;20;20m"); // Fill background with dark grey (RGB)
.fill(color::B_BLACK); // Fill background with dark grey (RGB)
// 2. Draw a Header using subprint and center
term << pos{1, 1} << backg::BLUE << color::WHITE << style::BOLD;
term << pos{ 1, 1 } << backg::BLUE << color::WHITE << style::BOLD;
term.center(term.getSize().x, " TERMINAL LIBRARY TEST SUITE ");
term << style::RESET;
// 3. Demonstrate Cartesian Positioning and Colors
pos center = { term.getSize().x / 2, term.getSize().y / 2 };
term << pos{center.x - 10, 5} << color::GREEN << "Green Text at (x-10, 5)"
<< pos{center.x - 10, 6} << color::B_RED << style::ITALIC << "Bright Red Italic"
term << pos{ center.x - 10, 5 } << color::GREEN << "Green Text at (x-10, 5)"
<< pos{ center.x - 10, 6 } << color::B_RED << style::ITALIC << "Bright Red Italic"
<< style::RESET;
// 4. Test RGB and HSL colors
term << pos{2, 10} << "RGB Test: ";
term << pos{ 2, 10 } << "RGB Test: ";
for (int i = 0; i < 5; ++i) {
term << color::rgb(50 * i, 255 - (50 * i), 150) << "";
}
term << pos{2, 11} << "HSL Test: ";
term << pos{ 2, 11 } << "HSL Test: ";
for (float h = 0.0f; h < 1.0f; h += 0.2f) {
term << color::hsl(h, 0.8f, 0.5f) << "";
}
@@ -40,15 +41,22 @@ int main() {
// 5. Test subprint_center
std::string long_msg = "This is a very long string that we will slice and center.";
term << pos{1, 15} << color::YELLOW;
term << pos{ 1, 15 } << color::YELLOW;
// Centers only the word "long string" in a width of 40
term.subprint_center(10, 21, long_msg);
term << style::RESET;
// 6. Interaction Loop
term << pos{2, term.getSize().y - 2} << style::FAINT
term << pos{ 2, term.getSize().y - 2 } << style::FAINT
<< "Press 'q' to quit, or any arrow key to move the cursor..." << style::RESET;
Box myBox({ 5, 5 }, 30, 10, "System Logs");
myBox.charset = BoxSet::THICK; // Switch to rounded corners
myBox.borderFg = color::CYAN;
term << myBox;
term.flush();
pos player = center;
bool running = true;

View File

@@ -5,6 +5,8 @@
#include <desktoplib/os/common.hpp>
#include <desktoplib/terminal/UI.hpp>
namespace ckitty {
namespace terminal {
@@ -307,9 +309,7 @@ namespace ckitty {
// Fill padding using a string constructor or a loop
// Standard strings are easiest for repeated characters
(*_os) << std::string(left_padding, ' ')
<< msg
<< std::string(right_padding, ' ');
(*_os) << std::string(left_padding, ' ') << msg << std::string(right_padding, ' ');
}
return *this;
}

View File

@@ -6,6 +6,8 @@
#include <sstream>
#include <optional>
#include <desktoplib/terminal/UI.hpp>
namespace ckitty {
namespace terminal {
@@ -229,7 +231,11 @@ namespace ckitty {
template <typename T>
Terminal& operator<<(const T& msg) {
if constexpr (std::is_base_of_v<UI, T>) {
msg.render(*this);
} else {
(*_os) << msg;
}
return *this;
}

View File

@@ -0,0 +1,16 @@
#pragma once
namespace ckitty {
namespace terminal {
class Terminal;
class UI {
public:
virtual ~UI() = default;
virtual void render(Terminal& t) const = 0;
};
}
}

View File

@@ -0,0 +1,52 @@
#include "Box.hpp"
namespace ckitty::terminal {
// --- Curated Selection of Charsets ---
const BoxSet BoxSet::SINGLE = { "", "", "", "", "", "" };
const BoxSet BoxSet::DOUBLE = { "", "", "", "", "", "" };
const BoxSet BoxSet::ROUNDED = { "", "", "", "", "", "" };
const BoxSet BoxSet::ASCII = { "+", "+", "+", "+", "-", "|" };
const BoxSet BoxSet::THICK = { "", "", "", "", "", "" };
Box::Box(pos p, int w, int h, std::string t)
: position(p), width(w), height(h), title(t) {
}
void Box::render(Terminal& t) const {
// 1. Set Style
t << (selected ? selectedStyle : normalStyle);
t << borderBg << borderFg;
// 2. Top Border
t << position << charset.tl;
for (int i = 0; i < width - 2; ++i) t << charset.h;
t << charset.tr;
// 3. Sides
for (int y = 1; y < height - 1; ++y) {
t << pos{ position.x, position.y + y } << charset.v;
t << pos{ position.x + width - 1, position.y + y } << charset.v;
}
// 4. Bottom Border
t << pos{ position.x, position.y + height - 1 } << charset.bl;
for (int i = 0; i < width - 2; ++i) t << charset.h;
t << charset.br;
// 5. Title Overlay
if (!title.empty()) {
// Ensure title doesn't overflow box width
std::string_view displayTitle = title;
if (title.length() > static_cast<size_t>(width - 4)) {
displayTitle = std::string_view(title).substr(0, size_t(width - 4));
}
t << pos{ position.x + 2, position.y }
<< " " << displayTitle << " ";
}
t << style::RESET;
}
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include <desktoplib/terminal/Terminal.hpp>
#include <desktoplib/terminal/UI.hpp>
#include <string>
namespace ckitty::terminal {
struct BoxSet {
std::string_view tl, tr, bl, br, h, v; // top-left, top-right, etc.
static const BoxSet SINGLE;
static const BoxSet DOUBLE;
static const BoxSet ROUNDED;
static const BoxSet ASCII;
static const BoxSet THICK;
};
class Box : public UI {
public:
pos position;
int width, height;
std::string title;
bool selected = false;
// Visual Configuration
style normalStyle = style::RESET;
style selectedStyle = style::BOLD;
backg borderBg = backg::BLACK;
color borderFg = color::WHITE;
// The line character set
BoxSet charset = BoxSet::SINGLE;
Box(pos p, int w, int h, std::string t = "");
void render(Terminal& t) const override;
};
}

View File

@@ -0,0 +1,9 @@
#pragma once
namespace ckitty {
namespace terminal {
}
}