mirror of
https://github.com/nicbarker/clay.git
synced 2026-02-06 12:48:49 +00:00
feat(ncurses): overhaul renderer with UTF-8, 256-colors, and visual improvements
Significantly enhances the Ncurses renderer capabilities and updates the example application.
Renderer Changes:
- Unicode Support:
- Implemented automatic UTF-8 locale detection and initialization.
- Switched to wide-character handling (`wchar_t`, `mvaddnwstr`) for correct rendering of multi-byte characters (e.g., Emojis).
- Used `wcwidth` for accurate string width measurement.
- Color Support:
- Upgraded from 3-bit (8 colors) to 256-color support (xterm-256color).
- Added `Clay_Ncurses_MatchColor` to map arbitrary RGB values to the nearest color in the standard 6x6x6 color cube.
- Added capability detection to fallback gracefully on simpler terminals.
- Visual Fidelity:
- Implemented background color inheritance (`Clay_Ncurses_GetBackgroundAt`) to simulate transparency.
- Text and borders now render on top of existing background colors instead of resetting to the terminal default.
- Build & POSIX:
- Added `_XOPEN_SOURCE_EXTENDED` and `_XOPEN_SOURCE=700` definitions for standard compliance.
Example Application (clay-ncurses-example):
- Theme:
- Updated to a modern dark theme (Uniform `{20, 20, 20}` background).
- Switched to saturated/bright foreground colors for better contrast.
- Fixes:
- Replaced obsolete `usleep` with POSIX-compliant `nanosleep`.
- Build:
- Updated CMakeLists.txt to enforce linking against `ncursesw` (wide version).
Verified with `clay-ncurses-example` on Linux (xterm-256color).
This commit is contained in:
parent
840606d0c1
commit
d4a48a07fc
3 changed files with 229 additions and 48 deletions
|
|
@ -1,8 +1,11 @@
|
|||
cmake_minimum_required(VERSION 3.27)
|
||||
project(clay-ncurses-example C)
|
||||
|
||||
set(CURSES_NEED_WIDE TRUE)
|
||||
find_package(Curses REQUIRED)
|
||||
|
||||
add_compile_definitions(_XOPEN_SOURCE_EXTENDED _XOPEN_SOURCE=700)
|
||||
|
||||
add_executable(clay-ncurses-example main.c)
|
||||
|
||||
target_link_libraries(clay-ncurses-example PRIVATE ${CURSES_LIBRARIES})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#define CLAY_IMPLEMENTATION
|
||||
#include "../../clay.h"
|
||||
#include "../../renderers/ncurses/clay_renderer_ncurses.c"
|
||||
#include <unistd.h> // for usleep
|
||||
#include <time.h> // for nanosleep
|
||||
|
||||
#define DEFAULT_SCROLL_DELTA 3.0f
|
||||
|
||||
|
|
@ -45,25 +45,25 @@ void RenderSidebar() {
|
|||
.childGap = 16,
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
},
|
||||
.backgroundColor = {30, 30, 30, 255}, // Dark Gray
|
||||
.border = { .color = {255, 255, 255, 255}, .width = { .right = 2 } } // White Border Right
|
||||
.backgroundColor = {20, 20, 20, 255}, // Uniform Dark BG
|
||||
.border = { .color = {100, 100, 100, 255}, .width = { .right = 2 } } // Lighter Grey Border
|
||||
}) {
|
||||
CLAY_TEXT(CLAY_STRING("SIDEBAR"), CLAY_TEXT_CONFIG({
|
||||
.textColor = {255, 255, 0, 255}
|
||||
.textColor = {255, 255, 0, 255} // Bright Yellow
|
||||
}));
|
||||
|
||||
CLAY(CLAY_ID("SidebarItem1"), {
|
||||
.layout = { .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIXED(32) } },
|
||||
.backgroundColor = {60, 60, 60, 255}
|
||||
.backgroundColor = {20, 20, 20, 255} // Uniform BG
|
||||
}) {
|
||||
CLAY_TEXT(CLAY_STRING(" > Item 1"), CLAY_TEXT_CONFIG({ .textColor = {255, 255, 255, 255} }));
|
||||
CLAY_TEXT(CLAY_STRING(" > Item 1 (Hello 🌍)"), CLAY_TEXT_CONFIG({ .textColor = {0, 255, 255, 255} })); // Cyan
|
||||
}
|
||||
|
||||
CLAY(CLAY_ID("SidebarItem2"), {
|
||||
.layout = { .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIXED(32) } },
|
||||
.backgroundColor = {60, 60, 60, 255}
|
||||
.backgroundColor = {20, 20, 20, 255} // Uniform BG
|
||||
}) {
|
||||
CLAY_TEXT(CLAY_STRING(" > Item 2"), CLAY_TEXT_CONFIG({ .textColor = {255, 255, 255, 255} }));
|
||||
CLAY_TEXT(CLAY_STRING(" > Item 2"), CLAY_TEXT_CONFIG({ .textColor = {255, 255, 255, 255} })); // White
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -105,9 +105,9 @@ void RenderPost(int index) {
|
|||
.childGap = 8,
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
},
|
||||
.backgroundColor = {25, 25, 25, 255},
|
||||
.backgroundColor = {20, 20, 20, 255}, // Uniform BG
|
||||
.cornerRadius = {8}, // Rounded corners (will render as square in TUI usually unless ACS handled)
|
||||
.border = { .color = {60, 60, 60, 255}, .width = { .left = 1, .right = 1, .top = 1, .bottom = 1 } }
|
||||
.border = { .color = {80, 80, 80, 255}, .width = { .left = 1, .right = 1, .top = 1, .bottom = 1 } }
|
||||
}) {
|
||||
// Post Header: Avatar + Name + Time
|
||||
CLAY(CLAY_IDI("PostHeader", index), {
|
||||
|
|
@ -148,9 +148,9 @@ void RenderPost(int index) {
|
|||
CLAY(CLAY_IDI("PostActions", index), {
|
||||
.layout = { .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_FIT(0) }, .childGap = 16, .layoutDirection = CLAY_LEFT_TO_RIGHT }
|
||||
}) {
|
||||
CLAY_TEXT(CLAY_STRING("[ Like ]"), CLAY_TEXT_CONFIG({ .textColor = {100, 200, 100, 255} }));
|
||||
CLAY_TEXT(CLAY_STRING("[ Comment ]"), CLAY_TEXT_CONFIG({ .textColor = {100, 150, 255, 255} }));
|
||||
CLAY_TEXT(CLAY_STRING("[ Share ]"), CLAY_TEXT_CONFIG({ .textColor = {200, 100, 100, 255} }));
|
||||
CLAY_TEXT(CLAY_STRING("[ Like ]"), CLAY_TEXT_CONFIG({ .textColor = {0, 255, 0, 255} })); // Bright Green
|
||||
CLAY_TEXT(CLAY_STRING("[ Comment ]"), CLAY_TEXT_CONFIG({ .textColor = {0, 100, 255, 255} })); // Bright Blue
|
||||
CLAY_TEXT(CLAY_STRING("[ Share ]"), CLAY_TEXT_CONFIG({ .textColor = {255, 0, 0, 255} })); // Bright Red
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -163,7 +163,7 @@ void RenderContent() {
|
|||
.childGap = 16,
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM
|
||||
},
|
||||
.backgroundColor = {10, 10, 10, 255}
|
||||
.backgroundColor = {20, 20, 20, 255} // Uniform BG
|
||||
}) {
|
||||
// Sticky Header
|
||||
CLAY(CLAY_ID("Header"), {
|
||||
|
|
@ -172,7 +172,7 @@ void RenderContent() {
|
|||
.padding = { .left = 16, .right=16 },
|
||||
.childAlignment = { .y = CLAY_ALIGN_Y_CENTER }
|
||||
},
|
||||
.backgroundColor = {0, 0, 80, 255},
|
||||
.backgroundColor = {20, 20, 20, 255}, // Uniform BG
|
||||
.border = { .color = {0, 100, 255, 255}, .width = { .bottom = 1 } }
|
||||
}) {
|
||||
CLAY_TEXT(CLAY_STRING("Clay Social Feed"), CLAY_TEXT_CONFIG({ .textColor = {255, 255, 255, 255} }));
|
||||
|
|
@ -186,7 +186,7 @@ void RenderContent() {
|
|||
.padding = { .top = 8, .bottom = 8 }
|
||||
},
|
||||
.clip = { .vertical = true, .childOffset = Clay_GetScrollOffset() },
|
||||
.backgroundColor = {15, 15, 15, 255}
|
||||
.backgroundColor = {20, 20, 20, 255} // Uniform BG
|
||||
}) {
|
||||
CLAY(CLAY_ID("FeedList"), {
|
||||
.layout = {
|
||||
|
|
@ -213,7 +213,7 @@ void RenderContent() {
|
|||
void RenderMainLayout() {
|
||||
CLAY(CLAY_ID("Root"), {
|
||||
.layout = { .sizing = { CLAY_SIZING_GROW(), CLAY_SIZING_GROW() }, .layoutDirection = CLAY_LEFT_TO_RIGHT },
|
||||
.backgroundColor = {0, 0, 0, 255}
|
||||
.backgroundColor = {20, 20, 20, 255} // Uniform BG
|
||||
}) {
|
||||
RenderSidebar();
|
||||
RenderContent();
|
||||
|
|
@ -257,7 +257,8 @@ int main() {
|
|||
|
||||
Clay_Ncurses_Render(commands);
|
||||
|
||||
usleep(32000);
|
||||
struct timespec ts = { .tv_sec = 0, .tv_nsec = 32000 * 1000 };
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
Clay_Ncurses_Terminate();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue