renderer
This commit is contained in:
parent
44fb1750ec
commit
edd5730ebd
25
.vscode/launch.json
vendored
25
.vscode/launch.json
vendored
@ -2,7 +2,7 @@
|
|||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "(gdb) Debug",
|
"name": "gdb_debug_unix",
|
||||||
"type": "cppdbg",
|
"type": "cppdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/bin/scolte",
|
"program": "${workspaceFolder}/bin/scolte",
|
||||||
@ -22,6 +22,29 @@
|
|||||||
"ignoreFailures": true
|
"ignoreFailures": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
// the only difference is .exe
|
||||||
|
{
|
||||||
|
"name": "gdb_debug_win",
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/bin/scolte.exe",
|
||||||
|
"preLaunchTask": "build_exec_dbg",
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"cwd": "${workspaceFolder}/bin",
|
||||||
|
"externalConsole": false,
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"miDebuggerPath": "gdb",
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "-gdb-set disassembly-flavor intel",
|
||||||
|
"ignoreFailures": true
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
2
kerep
2
kerep
@ -1 +1 @@
|
|||||||
Subproject commit 5391862d029e64fa41c888a0db3ee83979a3954f
|
Subproject commit 430b6267d19a04b725b19d01ec04d587d000405d
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "tui.h"
|
#include "tui_internal.h"
|
||||||
|
|
||||||
void Canvas_freeMembers(void* _self){
|
void Canvas_freeMembers(void* _self){
|
||||||
Canvas* self=(Canvas*)_self;
|
Canvas* self=(Canvas*)_self;
|
||||||
@ -7,12 +7,14 @@ void Canvas_freeMembers(void* _self){
|
|||||||
Autoarr_freeWithoutMembers(self->children, true);
|
Autoarr_freeWithoutMembers(self->children, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas_draw(UIElement* _self, DrawingArea place){
|
UI_Maybe Canvas_draw(Renderer* renderer, UIElement* _self, DrawingArea area){
|
||||||
Canvas* self=(Canvas*)_self;
|
Canvas* self=(Canvas*)_self;
|
||||||
Autoarr_foreach(self->children, ch, ({
|
Autoarr_foreach(self->children, ch, ({
|
||||||
UIElement_draw((UIElement*)ch,place);
|
if(ch==NULL)
|
||||||
fputc('\n', stdout);
|
UI_safethrow(UIError_NullPtr,;);
|
||||||
|
UI_try(UIElement_draw(renderer, (UIElement*)ch, area),_,;);
|
||||||
}));
|
}));
|
||||||
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
kt_define(Canvas, Canvas_freeMembers, NULL);
|
kt_define(Canvas, Canvas_freeMembers, NULL);
|
||||||
@ -25,7 +27,5 @@ Canvas* Canvas_create(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Canvas_addChild(Canvas* self, UIElement* child){
|
void Canvas_addChild(Canvas* self, UIElement* child){
|
||||||
if (child == NULL)
|
|
||||||
throw(ERR_NULLPTR);
|
|
||||||
Autoarr_add(self->children, child);
|
Autoarr_add(self->children, child);
|
||||||
}
|
}
|
||||||
158
src/TUI/Renderer.c
Normal file
158
src/TUI/Renderer.c
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#include "tui_internal.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// FrameBuffer //
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
void FrameBuffer_freeMembers(void* _self){
|
||||||
|
FrameBuffer* self=(FrameBuffer*)_self;
|
||||||
|
free(self->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
kt_define(FrameBuffer, FrameBuffer_freeMembers, NULL);
|
||||||
|
|
||||||
|
/// creates new frame buffer and fills it with spaces
|
||||||
|
UI_THROWING_FUNC_DECL(FrameBuffer_create(FrameBuffer* fb));
|
||||||
|
Maybe FrameBuffer_create(FrameBuffer* fb){
|
||||||
|
if(!term_getSize(&fb->size)){
|
||||||
|
fb->size=term_default_size;
|
||||||
|
//TODO log error
|
||||||
|
kprintf("can't get terminal size, fallback to default (%ux%u)\n",
|
||||||
|
term_default_size.cols, term_default_size.rows);
|
||||||
|
}
|
||||||
|
u32 length=fb->size.cols * fb->size.rows;
|
||||||
|
fb->data=malloc(sizeof(*fb->data) * length);
|
||||||
|
|
||||||
|
for(u32 i=0; i<length; i++)
|
||||||
|
fb->data[i]=UTFCHAR('#');
|
||||||
|
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer_freeMembers(void * _self){
|
||||||
|
Renderer* self=(Renderer*)_self;
|
||||||
|
FrameBuffer_freeMembers(&self->frameBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// Renderer //
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
UI_Maybe __Renderer_set(Renderer* self, utfchar c, u16 x, u16 y) {
|
||||||
|
if(x >= self->frameBuffer.size.cols)
|
||||||
|
UI_safethrow(UIError_InvalidX,;);
|
||||||
|
if(y >= self->frameBuffer.size.rows)
|
||||||
|
UI_safethrow(UIError_InvalidY,;);
|
||||||
|
self->frameBuffer.data[self->frameBuffer.size.cols * y + x] = c;
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
UI_Maybe __Renderer_drawFrame(Renderer* self){
|
||||||
|
// save current buffer
|
||||||
|
FrameBuffer buf=self->frameBuffer;
|
||||||
|
// recreate frame buffer
|
||||||
|
UI_try(FrameBuffer_create(&self->frameBuffer),_,;);
|
||||||
|
|
||||||
|
for(u16 y=0; y<buf.size.rows; y++){
|
||||||
|
for(u16 x=0; x<buf.size.cols; x++){
|
||||||
|
utfchar c=buf.data[buf.size.cols*y + x];
|
||||||
|
int rez=utfchar_print(c);
|
||||||
|
if(rez<0){
|
||||||
|
char* chex=toString_hex(&c, sizeof(c), true, true, true);
|
||||||
|
char* errnostr=toString_i64(errno);
|
||||||
|
char* errmsg=cptr_concat(nameof(UIError_PrintError)," (errno: ",errnostr,"): can't print char ",chex);
|
||||||
|
free(errnostr);
|
||||||
|
free(chex);
|
||||||
|
UI_safethrow_msg(errmsg,FrameBuffer_freeMembers(&buf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
// free saved frame buffer
|
||||||
|
FrameBuffer_freeMembers(&buf);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer_destroy(Renderer* self){
|
||||||
|
Renderer_freeMembers(self);
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
kt_define(Renderer, Renderer_freeMembers, NULL);
|
||||||
|
|
||||||
|
Renderer* Renderer_create(){
|
||||||
|
Renderer* renderer=malloc(sizeof(Renderer));
|
||||||
|
tryLast(FrameBuffer_create(&renderer->frameBuffer),_);
|
||||||
|
renderer->set=__Renderer_set;
|
||||||
|
renderer->drawFrame=__Renderer_drawFrame;
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// drawing functions //
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
UI_Maybe Renderer_fill(Renderer* renderer, utfchar c, DrawingArea area){
|
||||||
|
UI_try(DrawingArea_validate(area),_,;);
|
||||||
|
for(u16 y=area.y; y<area.y+area.h; y++)
|
||||||
|
for(u16 x=area.x; x<area.x+area.w; x++){
|
||||||
|
UI_try(Renderer_set(renderer, c, x, y),_,;);
|
||||||
|
}
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe Renderer_drawLineX(Renderer* renderer, utfchar c, u16 x, u16 y, u16 length){
|
||||||
|
while(length>0){
|
||||||
|
UI_try(Renderer_set(renderer, c, x, y),_,;);
|
||||||
|
x++; length--;
|
||||||
|
}
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe Renderer_drawLineY(Renderer* renderer, utfchar c, u16 x, u16 y, u16 length){
|
||||||
|
while(length>0){
|
||||||
|
UI_try(Renderer_set(renderer, c, x, y),_,;);
|
||||||
|
y++; length--;
|
||||||
|
}
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe Renderer_drawBorder(Renderer* renderer, UIBorder border, DrawingArea area){
|
||||||
|
UI_try(DrawingArea_validate(area),_0,;);
|
||||||
|
|
||||||
|
//lines
|
||||||
|
utfchar topChar = UIBorder_char_h[border.top ];
|
||||||
|
utfchar bottomChar = UIBorder_char_h[border.bottom];
|
||||||
|
utfchar leftChar = UIBorder_char_v[border.left ];
|
||||||
|
utfchar rightChar = UIBorder_char_v[border.right ];
|
||||||
|
// top
|
||||||
|
|
||||||
|
// TODO check neighbor borders and insert crossing chars like '╄'
|
||||||
|
|
||||||
|
UI_try(Renderer_drawLineX(renderer, topChar, area.x+1, area.y, area.w-2),_1,;)
|
||||||
|
// bottom
|
||||||
|
UI_try(Renderer_drawLineX(renderer, bottomChar, area.x+1, area.y+area.h-1, area.w-2),_2,;)
|
||||||
|
// left
|
||||||
|
UI_try(Renderer_drawLineY(renderer, leftChar, area.x, area.y+1, area.h-2),_3,;)
|
||||||
|
// right
|
||||||
|
UI_try(Renderer_drawLineY(renderer, rightChar, area.x+area.w-1, area.y+1, area.h-2),_4,;)
|
||||||
|
|
||||||
|
// corners
|
||||||
|
utfchar ltCornerChar = UIBorder_char_lt[border.left ][border.top ];
|
||||||
|
utfchar rtCornerChar = UIBorder_char_rt[border.right][border.top ];
|
||||||
|
utfchar rbCornerChar = UIBorder_char_rb[border.right][border.bottom];
|
||||||
|
utfchar lbCornerChar = UIBorder_char_lb[border.left ][border.bottom];
|
||||||
|
// left top corner
|
||||||
|
UI_try(Renderer_set(renderer, ltCornerChar, area.x, area.y),_5,;);
|
||||||
|
// right top corner
|
||||||
|
UI_try(Renderer_set(renderer, rtCornerChar, area.x+area.w-1, area.y),_6,;);
|
||||||
|
// right bottom corner
|
||||||
|
UI_try(Renderer_set(renderer, rbCornerChar, area.x+area.w-1, area.y+area.h-1),_7,;);
|
||||||
|
// left bottom corner
|
||||||
|
UI_try(Renderer_set(renderer, lbCornerChar, area.x, area.y+area.h-1),_8,;);
|
||||||
|
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
@ -1,14 +1,16 @@
|
|||||||
#include "tui.h"
|
#include "tui_internal.h"
|
||||||
|
|
||||||
|
|
||||||
void TextBlock_freeMembers(void* _self){
|
void TextBlock_freeMembers(void* _self){
|
||||||
TextBlock* self=(TextBlock*)_self;
|
TextBlock* self=(TextBlock*)_self;
|
||||||
free(self->text.ptr);
|
free(self->text.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextBlock_draw(UIElement* _self, DrawingArea place){
|
UI_Maybe TextBlock_draw(Renderer* renderer, UIElement* _self, DrawingArea area){
|
||||||
TextBlock* self=(TextBlock*)_self;
|
TextBlock* self=(TextBlock*)_self;
|
||||||
fputs(self->text.ptr, stdout);
|
UI_try(UIElement_validate((UIElement*)self, area),_0,;);
|
||||||
|
UI_try(Renderer_fill(renderer, UTFCHAR(' '), area),_2,;);
|
||||||
|
UI_try(Renderer_drawBorder(renderer, self->base.borders, area),_1,;);
|
||||||
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
kt_define(TextBlock, TextBlock_freeMembers, NULL);
|
kt_define(TextBlock, TextBlock_freeMembers, NULL);
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "tui.h"
|
#include "tui_internal.h"
|
||||||
|
|
||||||
kt_define(UIElement, NULL, NULL);
|
kt_define(UIElement, NULL, NULL);
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ UIElement __UIElement_createDefault(ktid typeId, UIElement_draw_t drawFunc){
|
|||||||
.anchor=UIAnchor_Center,
|
.anchor=UIAnchor_Center,
|
||||||
.borders={
|
.borders={
|
||||||
.left=UIBorder_Thin, .right=UIBorder_Thin,
|
.left=UIBorder_Thin, .right=UIBorder_Thin,
|
||||||
.top=UIBorder_Thick, .bottom=UIBorder_Thin
|
.top=UIBorder_Thin, .bottom=UIBorder_Thin
|
||||||
},
|
},
|
||||||
.draw=drawFunc
|
.draw=drawFunc
|
||||||
};
|
};
|
||||||
@ -27,3 +27,23 @@ void UIElement_destroy(UIElement* self){
|
|||||||
self->type->freeMembers(self);
|
self->type->freeMembers(self);
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UI_Maybe DrawingArea_validate(DrawingArea a){
|
||||||
|
if(a.h<1) UI_safethrow(UIError_InvalidWidth,;);
|
||||||
|
if(a.w<1) UI_safethrow(UIError_InvalidHeight,;);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe UIElement_validate(UIElement* u, DrawingArea a){
|
||||||
|
UI_try(DrawingArea_validate(a),_,;);
|
||||||
|
if(u->max_height<u->min_height)
|
||||||
|
UI_safethrow(UIError_InvalidHeight,;);
|
||||||
|
if(u->max_width<u->min_width)
|
||||||
|
UI_safethrow(UIError_InvalidWidth,;);
|
||||||
|
if(u->min_height>a.h)
|
||||||
|
UI_safethrow(UIError_InvalidHeight,;);
|
||||||
|
if(u->min_width>a.w)
|
||||||
|
UI_safethrow(UIError_InvalidWidth,;);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
26
src/TUI/UIError.h
Normal file
26
src/TUI/UIError.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../../kerep/src/base/base.h"
|
||||||
|
|
||||||
|
PACKED_ENUM(UIError,
|
||||||
|
UIError_Success=0,
|
||||||
|
UIError_NullPtr,
|
||||||
|
UIError_InvalidHeight, UIError_InvalidWidth,
|
||||||
|
UIError_InvalidX, UIError_InvalidY,
|
||||||
|
UIError_PrintError
|
||||||
|
)
|
||||||
|
|
||||||
|
// this macros can be changed later to improve debugging
|
||||||
|
#define UI_safethrow(ERRCODE, FREEMEM) safethrow(nameof(ERRCODE), FREEMEM)
|
||||||
|
#define UI_safethrow_msg(ERRMSG, FREEMEM) safethrow(ERRMSG, FREEMEM)
|
||||||
|
#define UI_try(CALL,RZLT,FREEMEM) try(CALL,RZLT,FREEMEM)
|
||||||
|
#define UI_Maybe Maybe
|
||||||
|
#define UI_THROWING_FUNC_DECL(NAME_AND_ARGS) UI_Maybe NAME_AND_ARGS WARN_UNUSED_REZULT
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -1,11 +1,11 @@
|
|||||||
#include "tui.h"
|
#include "tui.h"
|
||||||
|
|
||||||
kt_define(DrawingArea, NULL, NULL);
|
kt_define(DrawingArea, NULL, NULL);
|
||||||
kt_define(UIBorderParams, NULL, NULL);
|
kt_define(UIBorder, NULL, NULL);
|
||||||
|
|
||||||
void kt_initScolteTypes(){
|
void kt_initScolteTypes(){
|
||||||
kt_register(DrawingArea);
|
kt_register(DrawingArea);
|
||||||
kt_register(UIBorderParams);
|
kt_register(UIBorder);
|
||||||
kt_register(UIElement);
|
kt_register(UIElement);
|
||||||
kt_register(Canvas);
|
kt_register(Canvas);
|
||||||
kt_register(TextBlock);
|
kt_register(TextBlock);
|
||||||
@ -4,18 +4,18 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../kerep/src/base/base.h"
|
#include "../../kerep/src/String/string.h"
|
||||||
#include "../kerep/src/String/string.h"
|
#include "../../kerep/src/kprint/kprint_colors.h"
|
||||||
#include "../kerep/src/kprint/kprint_colors.h"
|
#include "../../kerep/src/Array/Array.h"
|
||||||
#include "../kerep/src/Array/Array.h"
|
#include "../term/term.h"
|
||||||
#include "terminal.h"
|
#include "unicode.h"
|
||||||
|
#include "UIError.h"
|
||||||
|
|
||||||
|
|
||||||
/// initializes type descriptors for this project's types
|
/// initializes type descriptors for this project's types
|
||||||
/// call this function between kt_beginInit() and kt_endInit()
|
/// call this function between kt_beginInit() and kt_endInit()
|
||||||
void kt_initScolteTypes();
|
void kt_initScolteTypes();
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// Enums //
|
// Enums //
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
@ -32,11 +32,12 @@ PACKED_ENUM(UIAnchor,
|
|||||||
UIAnchor_LeftBottom=UIAnchor_Left|UIAnchor_Bottom
|
UIAnchor_LeftBottom=UIAnchor_Left|UIAnchor_Bottom
|
||||||
)
|
)
|
||||||
|
|
||||||
PACKED_ENUM(UIBorderType,
|
PACKED_ENUM(UIBorderThickness,
|
||||||
UIBorder_NoBorder,
|
UIBorder_Hidden, /* blank space */
|
||||||
UIBorder_Thin,
|
UIBorder_Thin,
|
||||||
UIBorder_Thick,
|
UIBorder_Thick,
|
||||||
UIBorder_Double
|
UIBorder_Double,
|
||||||
|
UiBorder_NoBorder /* no space */
|
||||||
)
|
)
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
@ -49,20 +50,48 @@ STRUCT(DrawingArea,
|
|||||||
u16 w; u16 h;
|
u16 w; u16 h;
|
||||||
)
|
)
|
||||||
|
|
||||||
STRUCT(UIBorderParams,
|
STRUCT(UIBorder,
|
||||||
UIBorderType right;
|
UIBorderThickness right;
|
||||||
UIBorderType left;
|
UIBorderThickness left;
|
||||||
UIBorderType top;
|
UIBorderThickness top;
|
||||||
UIBorderType bottom;
|
UIBorderThickness bottom;
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// Renderer //
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
STRUCT(FrameBuffer,
|
||||||
|
utfchar* data;
|
||||||
|
TerminalSize size;
|
||||||
|
)
|
||||||
|
|
||||||
|
typedef struct Renderer Renderer;
|
||||||
|
|
||||||
|
STRUCT(Renderer,
|
||||||
|
FrameBuffer frameBuffer;
|
||||||
|
UI_THROWING_FUNC_DECL((*drawFrame)(Renderer*));
|
||||||
|
UI_THROWING_FUNC_DECL((*set)(Renderer*, utfchar c, u16 x, u16 y));
|
||||||
|
)
|
||||||
|
|
||||||
|
#define Renderer_drawFrame(RENDERER) RENDERER->drawFrame(RENDERER)
|
||||||
|
#define Renderer_set(RENDERER, CH, X, Y) RENDERER->set(RENDERER, CH, X, Y)
|
||||||
|
|
||||||
|
Renderer* Renderer_create();
|
||||||
|
void Renderer_destroy(Renderer* self);
|
||||||
|
|
||||||
|
UI_THROWING_FUNC_DECL(Renderer_fill(Renderer* renderer, utfchar c, DrawingArea area));
|
||||||
|
UI_THROWING_FUNC_DECL(Renderer_drawLineX(Renderer* renderer, utfchar c, u16 x, u16 y, u16 length));
|
||||||
|
UI_THROWING_FUNC_DECL(Renderer_drawLineY(Renderer* renderer, utfchar c, u16 x, u16 y, u16 length));
|
||||||
|
UI_THROWING_FUNC_DECL(Renderer_drawBorder(Renderer* renderer, UIBorder border, DrawingArea area));
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// UIElement abstract struct //
|
// UIElement abstract struct //
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
typedef struct UIElement UIElement;
|
typedef struct UIElement UIElement;
|
||||||
typedef UIElement* UIElementPtr;
|
typedef UIElement* UIElementPtr;
|
||||||
typedef void (*UIElement_draw_t)(UIElement* self,DrawingArea place);
|
typedef UI_THROWING_FUNC_DECL((*UIElement_draw_t)(Renderer* renderer, UIElement* self, DrawingArea area));
|
||||||
|
|
||||||
#define UIElement_stretch (u16)-1
|
#define UIElement_stretch (u16)-1
|
||||||
|
|
||||||
@ -75,14 +104,14 @@ STRUCT(UIElement,
|
|||||||
kp_fgColor fgColor;
|
kp_fgColor fgColor;
|
||||||
kp_bgColor bgColor;
|
kp_bgColor bgColor;
|
||||||
UIAnchor anchor;
|
UIAnchor anchor;
|
||||||
UIBorderParams borders;
|
UIBorder borders;
|
||||||
UIElement_draw_t draw;
|
UIElement_draw_t draw;
|
||||||
)
|
)
|
||||||
|
|
||||||
UIElement __UIElement_createDefault(ktid typeId, UIElement_draw_t drawFunc);
|
|
||||||
/// proper way to free UIElement and all its members
|
/// proper way to free UIElement and all its members
|
||||||
void UIElement_destroy(UIElement* self);
|
void UIElement_destroy(UIElement* self);
|
||||||
#define UIElement_draw(UIE_PTR, PLACE_RECT) ((UIElement*)UIE_PTR)->draw((UIElement*)UIE_PTR, PLACE_RECT)
|
#define UIElement_draw(RENDERER, UIE_PTR, PLACE_RECT) \
|
||||||
|
((UIElement*)UIE_PTR)->draw(RENDERER, UIE_PTR, PLACE_RECT)
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// UIElement derivatives //
|
// UIElement derivatives //
|
||||||
22
src/TUI/tui_internal.h
Normal file
22
src/TUI/tui_internal.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "tui.h"
|
||||||
|
|
||||||
|
UIElement __UIElement_createDefault(ktid typeId, UIElement_draw_t drawFunc);
|
||||||
|
UI_THROWING_FUNC_DECL(DrawingArea_validate(DrawingArea a));
|
||||||
|
UI_THROWING_FUNC_DECL(UIElement_validate(UIElement* u, DrawingArea a));
|
||||||
|
|
||||||
|
extern utfchar UIBorder_char_h[4];
|
||||||
|
extern utfchar UIBorder_char_v[4];
|
||||||
|
extern utfchar UIBorder_char_lt[4][4];
|
||||||
|
extern utfchar UIBorder_char_rt[4][4];
|
||||||
|
extern utfchar UIBorder_char_rb[4][4];
|
||||||
|
extern utfchar UIBorder_char_lb[4][4];
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
108
src/TUI/uiBorder_charTables.c
Normal file
108
src/TUI/uiBorder_charTables.c
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "tui_internal.h"
|
||||||
|
|
||||||
|
utfchar UIBorder_char_h[4]={
|
||||||
|
[UIBorder_Hidden]=UTFCHAR(' '),
|
||||||
|
[UIBorder_Thin ]=UTFCHAR('─'),
|
||||||
|
[UIBorder_Thick ]=UTFCHAR('━'),
|
||||||
|
[UIBorder_Double]=UTFCHAR('═')
|
||||||
|
};
|
||||||
|
|
||||||
|
utfchar UIBorder_char_v[4]={
|
||||||
|
[UIBorder_Hidden]=UTFCHAR(' '),
|
||||||
|
[UIBorder_Thin ]=UTFCHAR('│'),
|
||||||
|
[UIBorder_Thick ]=UTFCHAR('┃'),
|
||||||
|
[UIBorder_Double]=UTFCHAR('║')
|
||||||
|
};
|
||||||
|
|
||||||
|
/// [left_border][top_border]
|
||||||
|
utfchar UIBorder_char_lt[4][4]={
|
||||||
|
[UIBorder_Hidden][UIBorder_Hidden]=UTFCHAR(' '),
|
||||||
|
[UIBorder_Hidden][UIBorder_Thin ]=UTFCHAR('─'),
|
||||||
|
[UIBorder_Hidden][UIBorder_Thick ]=UTFCHAR('━'),
|
||||||
|
[UIBorder_Hidden][UIBorder_Double]=UTFCHAR('═'),
|
||||||
|
|
||||||
|
[UIBorder_Thin ][UIBorder_Hidden]=UTFCHAR('│'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Thin ]=UTFCHAR('┌'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Thick ]=UTFCHAR('┍'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Double]=UTFCHAR('╒'),
|
||||||
|
|
||||||
|
[UIBorder_Thick ][UIBorder_Hidden]=UTFCHAR('┃'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Thin ]=UTFCHAR('┎'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Thick ]=UTFCHAR('┏'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Double]=UTFCHAR('╒'),
|
||||||
|
|
||||||
|
[UIBorder_Double][UIBorder_Hidden]=UTFCHAR('║'),
|
||||||
|
[UIBorder_Double][UIBorder_Thin ]=UTFCHAR('╓'),
|
||||||
|
[UIBorder_Double][UIBorder_Thick ]=UTFCHAR('╓'),
|
||||||
|
[UIBorder_Double][UIBorder_Double]=UTFCHAR('╔')
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// [right_border][top_border]
|
||||||
|
utfchar UIBorder_char_rt[4][4]={
|
||||||
|
[UIBorder_Hidden][UIBorder_Hidden]=UTFCHAR(' '),
|
||||||
|
[UIBorder_Hidden][UIBorder_Thin ]=UTFCHAR('─'),
|
||||||
|
[UIBorder_Hidden][UIBorder_Thick ]=UTFCHAR('━'),
|
||||||
|
[UIBorder_Hidden][UIBorder_Double]=UTFCHAR('═'),
|
||||||
|
|
||||||
|
[UIBorder_Thin ][UIBorder_Hidden]=UTFCHAR('│'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Thin ]=UTFCHAR('┐'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Thick ]=UTFCHAR('┑'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Double]=UTFCHAR('╕'),
|
||||||
|
|
||||||
|
[UIBorder_Thick ][UIBorder_Hidden]=UTFCHAR('┃'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Thin ]=UTFCHAR('┒'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Thick ]=UTFCHAR('┓'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Double]=UTFCHAR('╕'),
|
||||||
|
|
||||||
|
[UIBorder_Double][UIBorder_Hidden]=UTFCHAR('║'),
|
||||||
|
[UIBorder_Double][UIBorder_Thin ]=UTFCHAR('╖'),
|
||||||
|
[UIBorder_Double][UIBorder_Thick ]=UTFCHAR('╖'),
|
||||||
|
[UIBorder_Double][UIBorder_Double]=UTFCHAR('╗')
|
||||||
|
};
|
||||||
|
|
||||||
|
/// [right_border][bottom_border]
|
||||||
|
utfchar UIBorder_char_rb[4][4]={
|
||||||
|
[UIBorder_Hidden][UIBorder_Hidden]=UTFCHAR(' '),
|
||||||
|
[UIBorder_Hidden][UIBorder_Thin ]=UTFCHAR('─'),
|
||||||
|
[UIBorder_Hidden][UIBorder_Thick ]=UTFCHAR('━'),
|
||||||
|
[UIBorder_Hidden][UIBorder_Double]=UTFCHAR('═'),
|
||||||
|
|
||||||
|
[UIBorder_Thin ][UIBorder_Hidden]=UTFCHAR('│'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Thin ]=UTFCHAR('┘'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Thick ]=UTFCHAR('┙'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Double]=UTFCHAR('╛'),
|
||||||
|
|
||||||
|
[UIBorder_Thick ][UIBorder_Hidden]=UTFCHAR('┃'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Thin ]=UTFCHAR('┚'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Thick ]=UTFCHAR('┛'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Double]=UTFCHAR('╛'),
|
||||||
|
|
||||||
|
[UIBorder_Double][UIBorder_Hidden]=UTFCHAR('║'),
|
||||||
|
[UIBorder_Double][UIBorder_Thin ]=UTFCHAR('╜'),
|
||||||
|
[UIBorder_Double][UIBorder_Thick ]=UTFCHAR('╜'),
|
||||||
|
[UIBorder_Double][UIBorder_Double]=UTFCHAR('╝')
|
||||||
|
};
|
||||||
|
|
||||||
|
/// [left_border][bottom_border]
|
||||||
|
utfchar UIBorder_char_lb[4][4]={
|
||||||
|
[UIBorder_Hidden][UIBorder_Hidden]=UTFCHAR(' '),
|
||||||
|
[UIBorder_Hidden][UIBorder_Thin ]=UTFCHAR('─'),
|
||||||
|
[UIBorder_Hidden][UIBorder_Thick ]=UTFCHAR('━'),
|
||||||
|
[UIBorder_Hidden][UIBorder_Double]=UTFCHAR('═'),
|
||||||
|
|
||||||
|
[UIBorder_Thin ][UIBorder_Hidden]=UTFCHAR('│'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Thin ]=UTFCHAR('└'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Thick ]=UTFCHAR('┕'),
|
||||||
|
[UIBorder_Thin ][UIBorder_Double]=UTFCHAR('╘'),
|
||||||
|
|
||||||
|
[UIBorder_Thick ][UIBorder_Hidden]=UTFCHAR('┃'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Thin ]=UTFCHAR('┖'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Thick ]=UTFCHAR('┗'),
|
||||||
|
[UIBorder_Thick ][UIBorder_Double]=UTFCHAR('╘'),
|
||||||
|
|
||||||
|
[UIBorder_Double][UIBorder_Hidden]=UTFCHAR('║'),
|
||||||
|
[UIBorder_Double][UIBorder_Thin ]=UTFCHAR('╙'),
|
||||||
|
[UIBorder_Double][UIBorder_Thick ]=UTFCHAR('╙'),
|
||||||
|
[UIBorder_Double][UIBorder_Double]=UTFCHAR('╚')
|
||||||
|
};
|
||||||
31
src/TUI/unicode.h
Normal file
31
src/TUI/unicode.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// #include <wchar.h>
|
||||||
|
#include <uchar.h>
|
||||||
|
|
||||||
|
typedef char16_t utfchar;
|
||||||
|
#define UTFCHAR(CHAR) u##CHAR
|
||||||
|
#define UTFSTR(STR) u##STR
|
||||||
|
|
||||||
|
// returns length of written bytes or error code
|
||||||
|
static inline size_t utfchar_write(utfchar ch, FILE* file){
|
||||||
|
char multibyteUtf8[8]={0};
|
||||||
|
mbstate_t mbs={0};
|
||||||
|
size_t length=c16rtomb(multibyteUtf8, ch, &mbs);
|
||||||
|
if(length!=-1)
|
||||||
|
for(u8 i=0; i<length; i++){
|
||||||
|
int rez=fputc(multibyteUtf8[i], file);
|
||||||
|
if(rez<0)
|
||||||
|
return rez;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
#define utfchar_print(CH) utfchar_write(CH, stdout)
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
15
src/main.c
15
src/main.c
@ -1,5 +1,5 @@
|
|||||||
#include "../kerep/src/Filesystem/filesystem.h"
|
#include "../kerep/src/Filesystem/filesystem.h"
|
||||||
#include "tui.h"
|
#include "TUI/tui.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
Maybe tryReadFile(char* filePath){
|
Maybe tryReadFile(char* filePath){
|
||||||
@ -14,6 +14,9 @@ Maybe tryReadFile(char* filePath){
|
|||||||
}
|
}
|
||||||
|
|
||||||
i32 main(const i32 argc, const char* const* argv){
|
i32 main(const i32 argc, const char* const* argv){
|
||||||
|
if(setlocale(LC_CTYPE, "C.UTF-8")!=0)
|
||||||
|
kprintf("\e[93msetlocale failed!\n");
|
||||||
|
|
||||||
kt_beginInit();
|
kt_beginInit();
|
||||||
kt_initKerepTypes();
|
kt_initKerepTypes();
|
||||||
kt_initScolteTypes();
|
kt_initScolteTypes();
|
||||||
@ -29,15 +32,15 @@ i32 main(const i32 argc, const char* const* argv){
|
|||||||
char* text=(char*)_m_text.value.VoidPtr;
|
char* text=(char*)_m_text.value.VoidPtr;
|
||||||
fputs(text,stdout);*/
|
fputs(text,stdout);*/
|
||||||
|
|
||||||
|
Renderer* renderer=Renderer_create();
|
||||||
Canvas* mainCanvas=Canvas_create();
|
Canvas* mainCanvas=Canvas_create();
|
||||||
TextBlock* testTextBlock=TextBlock_create(string_fromCptr("some example text"));
|
TextBlock* testTextBlock=TextBlock_create(string_fromCptr("some example text"));
|
||||||
Canvas_addChild(mainCanvas, (UIElement*)testTextBlock);
|
Canvas_addChild(mainCanvas, (UIElement*)testTextBlock);
|
||||||
UIElement_draw(mainCanvas, ((DrawingArea){.x=-1, .y=-1, .h=-1, .w=-1}));
|
tryLast(UIElement_draw(renderer, (UIElement*)mainCanvas, ((DrawingArea){.x=4, .y=4, .h=4, .w=4})),_);
|
||||||
UIElement_destroy((UIElement*)mainCanvas);
|
tryLast(Renderer_drawFrame(renderer),_2);
|
||||||
|
|
||||||
TerminalSize tsize=terminal_getSize();
|
UIElement_destroy((UIElement*)mainCanvas);
|
||||||
kprintf("rows: %u culumns: %u\n", tsize.rows, tsize.cols);
|
Renderer_destroy(renderer);
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
kt_free();
|
kt_free();
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
38
src/term/term.c
Normal file
38
src/term/term.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "term.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include IFWIN("windows.h", "sys/ioctl.h")
|
||||||
|
|
||||||
|
void term_moveCursor(u16 row, u16 column){
|
||||||
|
printf("\e[%u;%uf",row,column);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void term_clear() {
|
||||||
|
printf("\e[2j");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool term_getSize(TerminalSize* out) {
|
||||||
|
#if defined(_WIN64) || defined(_WIN32)
|
||||||
|
// helps when STD_OUT is redirected to a file
|
||||||
|
HANDLE hConsoleErr = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
|
||||||
|
if(!GetConsoleScreenBufferInfo(hConsoleErr, &consoleInfo))
|
||||||
|
return false;
|
||||||
|
*out=(TerminalSize){
|
||||||
|
.cols=consoleInfo.srWindow.Right-consoleInfo.srWindow.Left+1,
|
||||||
|
.rows=consoleInfo.srWindow.Bottom-consoleInfo.srWindow.Top+1
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
struct winsize w={0,0,0,0};
|
||||||
|
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w)!=0)
|
||||||
|
return false;
|
||||||
|
*out=(TerminalSize){
|
||||||
|
.cols=w.ws_col,
|
||||||
|
.rows=w.ws_row
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TerminalSize term_default_size={.cols=80, .rows=16};
|
||||||
25
src/term/term.h
Normal file
25
src/term/term.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../../kerep/src/base/base.h"
|
||||||
|
|
||||||
|
void term_moveCursor(u16 row, u16 column);
|
||||||
|
void term_clear();
|
||||||
|
|
||||||
|
STRUCT(TerminalSize,
|
||||||
|
u16 rows;
|
||||||
|
u16 cols;
|
||||||
|
)
|
||||||
|
|
||||||
|
///@return TRUE if have got terminal size, otherwise FALSE
|
||||||
|
bool term_getSize(TerminalSize* out) WARN_UNUSED_REZULT;
|
||||||
|
|
||||||
|
/// can be used if term_getSize() fails
|
||||||
|
extern TerminalSize term_default_size;
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -1,23 +0,0 @@
|
|||||||
#include "terminal.h"
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
void terminal_moveCursor(u16 row, u16 column){
|
|
||||||
printf("\e[%u;%uf",row,column);
|
|
||||||
}
|
|
||||||
|
|
||||||
void terminal_clear() {
|
|
||||||
printf("\e[2j");
|
|
||||||
}
|
|
||||||
|
|
||||||
TerminalSize terminal_getSize(){
|
|
||||||
struct winsize w={0,0,0,0};
|
|
||||||
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w)!=0)
|
|
||||||
kprintf("\e[93mterminal_getSize() error\n");
|
|
||||||
TerminalSize tsize={
|
|
||||||
.cols=w.ws_col,
|
|
||||||
.rows=w.ws_row
|
|
||||||
};
|
|
||||||
return tsize;
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#if __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../kerep/src/base/base.h"
|
|
||||||
|
|
||||||
void terminal_moveCursor(u16 row, u16 column);
|
|
||||||
void terminal_clear();
|
|
||||||
|
|
||||||
STRUCT(TerminalSize,
|
|
||||||
u16 rows;
|
|
||||||
u16 cols;
|
|
||||||
)
|
|
||||||
|
|
||||||
TerminalSize terminal_getSize();
|
|
||||||
|
|
||||||
#if __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
Loading…
Reference in New Issue
Block a user