From 4e2376f25159f2e458a4696edea54e4b77bad5e1 Mon Sep 17 00:00:00 2001 From: Timerix22 Date: Mon, 22 May 2023 04:06:55 +0600 Subject: [PATCH] started implementing dtsod parsing --- .gitignore | 1 + kerep | 2 +- resource_embedder | 2 +- src/TUI/Dtsod/tui_dtsod.c | 141 +++++++++++++++++++++++++++++ src/TUI/Dtsod/tui_dtsod.h | 81 +++++++++++++++++ src/TUI/Dtsod/tui_dtsod_internal.h | 21 +++++ src/TUI/Grid.c | 39 +++++--- src/TUI/TextBlock.c | 22 ++++- src/TUI/UIElement.c | 54 +++++++++-- src/TUI/UIError.h | 3 +- src/TUI/enums_getByName.c | 113 +++++++++++++++++++++++ src/TUI/tui.c | 71 ++++++++++++++- src/TUI/tui.h | 85 +++++++++++++---- src/TUI/tui_internal.h | 34 ++++++- src/main.c | 51 ++++++++--- tasks/build_view.sh | 17 ++++ tasks/clean_additions.sh | 4 + tasks/pre_build.sh | 3 + tasks/rebuild_lib.sh | 2 + view/example.tui.dtsod | 31 +++++++ view/main.tui.dtsod | 10 ++ 21 files changed, 724 insertions(+), 63 deletions(-) create mode 100644 src/TUI/Dtsod/tui_dtsod.c create mode 100644 src/TUI/Dtsod/tui_dtsod.h create mode 100644 src/TUI/Dtsod/tui_dtsod_internal.h create mode 100644 src/TUI/enums_getByName.c create mode 100644 tasks/build_view.sh create mode 100644 view/example.tui.dtsod create mode 100644 view/main.tui.dtsod diff --git a/.gitignore b/.gitignore index 4be6400..8fa8d75 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # build results bin/ obj/ +src/generated/ *.log *.tmp diff --git a/kerep b/kerep index d713605..27be5be 160000 --- a/kerep +++ b/kerep @@ -1 +1 @@ -Subproject commit d7136055d92e90070b947f1662b3fa6981eecdc0 +Subproject commit 27be5beacdfda586f518ab05de050775ce7b5f54 diff --git a/resource_embedder b/resource_embedder index 81df594..1708415 160000 --- a/resource_embedder +++ b/resource_embedder @@ -1 +1 @@ -Subproject commit 81df5940827fa4347d112d3f81c926ef3a6acb80 +Subproject commit 1708415900b0d5caed72c5e0aab3c5039517ee41 diff --git a/src/TUI/Dtsod/tui_dtsod.c b/src/TUI/Dtsod/tui_dtsod.c new file mode 100644 index 0000000..4ca742a --- /dev/null +++ b/src/TUI/Dtsod/tui_dtsod.c @@ -0,0 +1,141 @@ +#include "../tui_internal.h" +#include "tui_dtsod_internal.h" +#include "../../../kerep/src/Filesystem/filesystem.h" + +////////////////////////////////////// +// UIDtsodFileModel // +////////////////////////////////////// + +void UIDtsodFileModel_freeMembers(void* _fm){ + UIDtsodFileModel* fm=_fm; + DtsodV24_free(fm->dtsod); + free(fm->dtsod_text); + free(fm->file_name); +} + +kt_define(UIDtsodFileModel, UIDtsodFileModel_freeMembers, NULL); +Autoarr_define(UIDtsodFileModel, false); + +////////////////////////////////////// +// UIDtsodParser // +////////////////////////////////////// + +void _UIDtsodParser_freeMembers(void* _p){ + UIDtsodParser* p=_p; + Autoarr_free(p->file_models, true); + if(!p->returned_context && p->context!=NULL){ + UIContext_destroy(p->context); + } +} + +void UIDtsodParser_destroy(UIDtsodParser* p){ + _UIDtsodParser_freeMembers(p); + free(p); +} + +kt_define(UIDtsodParser, _UIDtsodParser_freeMembers, NULL); + +UIDtsodParser* UIDtsodParser_create(){ + UIDtsodParser* parser=malloc(sizeof(UIDtsodParser)); + parser->context=NULL; + parser->returned_context=false; + parser->file_models=Autoarr_create(UIDtsodFileModel, 64, 32); + return parser; +} + + +///@return UI_Maybe +UI_Maybe UIDtsodParser_parseFile(UIDtsodParser* parser, char* file_path){ + UI_try(file_open(file_path, FileOpenMode_Read), _m_file, ;); + FileHandle file=_m_file.value.VoidPtr; + char* file_content=NULL; + UI_try(file_readAll(file, &file_content), _m_bcount, ;) + UI_try(file_close(file), _m_1563, free(file_content)); + UI_try(UIDtsodParser_parseText(parser, file_path, file_content), _6561, free(file_content)); + return MaybeNull; +} + +UI_Maybe UIDtsodParser_parseText(UIDtsodParser* parser, char* file_name_placeholder, char* text){ + UI_try(DtsodV24_deserialize(text), _m_dtsod, ;); + UIDtsodFileModel fm={ + .file_name=cptr_copy(file_name_placeholder), + .dtsod_text=text, + .dtsod=_m_dtsod.value.VoidPtr + }; + Autoarr_add(parser->file_models, fm); + return MaybeNull; +} + + + +void _UIContext_freeMembers(void* _u){ + UIContext* u=_u; + Hashtable_free(u->ui_elements); +} + +void UIContext_destroy(UIContext* u){ + _UIContext_freeMembers(u); + free(u); +} + +kt_define(UIContext, _UIContext_freeMembers, NULL); + + +UI_Maybe UIElement_deserialize(Dtsod* dtsod){ + Unitype uni; + Dtsod_get_necessary(dtsod, "type"); + UITDescriptor* ui_type=uni.VoidPtr; + UI_try(ui_type->deserialize(dtsod), _m_ui, ;); + return _m_ui; +} + +UI_Maybe UIDtsodParser_constructUIContext(UIDtsodParser* parser){ + if(parser->context == NULL){ + parser->context=malloc(sizeof(UIContext)); + parser->context->ui_elements=Hashtable_create(); + } + + Autoarr_foreach(parser->file_models, fm, + Hashtable_foreach(fm.dtsod, dtsod_elem, + if(cptr_compare(dtsod_elem.key, "tui_dtsod_version")){ + + } + else if(cptr_compare(dtsod_elem.key, "ui")) { + Autoarr_Unitype* ui_ar=dtsod_elem.value.VoidPtr; + Autoarr_foreach(ui_ar, ui_el_dtsod, + UI_try(UIElement_deserialize(ui_el_dtsod.VoidPtr),_m_ui,;); + UIElement_Ptr new_el=_m_ui.value.VoidPtr; + UI_try( UIContext_add(parser->context, new_el), _a76515, ;); + ); + } + ); + ); + + parser->returned_context=true; + return SUCCESS(UniHeapPtr(UIContext, parser->context)); +} + + +UI_Maybe _UIContext_get(UIContext* context, char* name, ktid type_id){ + Unitype val; + // check name + if(!Hashtable_tryGet(context->ui_elements, name, &val)){ + UI_safethrow_msg(cptr_concat("can't get <", name, "> from context"), ;); + } + // check type + UIElement* ptr=val.VoidPtr; + if(val.typeId != type_id) + UI_safethrow_msg(cptr_concat( + "tried to get ",ktDescriptor_get(type_id)->name, " <",name,"> but it is of type ", ptr->ui_type->type->name + ), ;); + + return SUCCESS(val); +} + +UI_Maybe UIContext_add(UIContext* context, _UIElement_Ptr _new_el){ + UIElement_Ptr new_el=_new_el; + Unitype u=UniPtr(new_el->ui_type->type->id, new_el, true); + if(!Hashtable_tryAdd(context->ui_elements, new_el->name, u)) + UI_safethrow_msg(cptr_concat("element with name <", new_el->name, "> already exists in context"), ;); + return MaybeNull; +} diff --git a/src/TUI/Dtsod/tui_dtsod.h b/src/TUI/Dtsod/tui_dtsod.h new file mode 100644 index 0000000..4a4703e --- /dev/null +++ b/src/TUI/Dtsod/tui_dtsod.h @@ -0,0 +1,81 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../../../kerep/src/DtsodParser/DtsodV24.h" +#include "../UIError.h" + +typedef Hashtable Dtsod; +typedef void* _UIElement_Ptr; + +/* +HOW TO USE: +UIDtsodParser* p=UIDtsodParser_create(); +UI_try(UIDtsodParser_parseFile("some_file.tui.dtsod"), _91624, UIDtsodParser_destroy(p)); +UI_try(UIDtsodParser_parseFile("another_file.tui.dtsod"), _95927, UIDtsodParser_destroy(p)); +UI_try(UIDtsodParser_constructUIContext(p), _m_ui_context, UIDtsodParser_destroy(p)); +UIContext* ui_context=_m_ui_context.value.VoidPtr; +UIDtsodParser_destroy(p); +UIContext_get(ui_context, example_namespace, text_box, TextBlock, UIContext_destroy(ui_context)); +example_namespace_text_box->text=string_fromCptr("text replaced"); +*/ + +////////////////////////////////////// +// UIDtsodParser // +////////////////////////////////////// +typedef struct UIDtsodParser UIDtsodParser; + +UIDtsodParser* UIDtsodParser_create(); +void UIDtsodParser_destroy(UIDtsodParser* p); + +///@return UI_Maybe +UI_THROWING_FUNC_DECL(UIDtsodParser_parseFile(UIDtsodParser* parser, char* file_name)); + +///@return UI_Maybe +UI_THROWING_FUNC_DECL(UIDtsodParser_parseText(UIDtsodParser* parser, char* file_name_placeholder, char* text)); + +///@return UI_Maybe +UI_THROWING_FUNC_DECL(UIDtsodParser_constructUIContext(UIDtsodParser* parser)); + +////////////////////////////////////// +// UIContext // +////////////////////////////////////// +typedef struct UIContext UIContext; + +void UIContext_destroy(UIContext* u); + +///@return UI_Maybe +UI_THROWING_FUNC_DECL(_UIContext_get(UIContext* context, char* name, ktid type_id)); +#define UIContext_get(CONTEXT, NAMESPACE, NAME, TYPE, FREECALLS_ON_ERROR) \ + UI_try( \ + _UIContext_get(CONTEXT, #NAMESPACE "_" #NAME, ktid_name(TYPE)), \ + _m_##NAMESPACE##_##NAME, \ + FREECALLS_ON_ERROR); \ + TYPE* NAMESPACE##_##NAME=_m_##NAMESPACE##_##NAME.value.VoidPtr; + +///@return Maybe +UI_THROWING_FUNC_DECL(UIContext_add(UIContext* context, _UIElement_Ptr new_el)); + + +////////////////////////////////////// +// Deserialization // +////////////////////////////////////// + +/// universal function for UIElement ancestors deserializing +/// @return Maybe +UI_THROWING_FUNC_DECL( UIElement_deserialize(Dtsod* dtsod) ); + + +#define Dtsod_get_necessary(dtsod, key) \ + if(!Hashtable_tryGet(dtsod, key, &uni)) \ + UI_safethrow(UIError_NullPtr, ;); + +#define Dtsod_get_optional(dtsod, key) \ + if(Hashtable_tryGet(dtsod, key, &uni)) + + +#if __cplusplus +} +#endif \ No newline at end of file diff --git a/src/TUI/Dtsod/tui_dtsod_internal.h b/src/TUI/Dtsod/tui_dtsod_internal.h new file mode 100644 index 0000000..7d8cbe4 --- /dev/null +++ b/src/TUI/Dtsod/tui_dtsod_internal.h @@ -0,0 +1,21 @@ +#pragma once + +#include "tui_dtsod.h" + + +STRUCT(UIDtsodFileModel, + char* file_name; + char* dtsod_text; + Dtsod* dtsod; +) +Autoarr_declare(UIDtsodFileModel) + +STRUCT(UIDtsodParser, + Autoarr(UIDtsodFileModel)* file_models; + UIContext* context; + bool returned_context; +) + +STRUCT(UIContext, + Hashtable* ui_elements; +) \ No newline at end of file diff --git a/src/TUI/Grid.c b/src/TUI/Grid.c index 30def85..d9c6dc4 100644 --- a/src/TUI/Grid.c +++ b/src/TUI/Grid.c @@ -16,15 +16,6 @@ void Grid_set(Grid* grid, u16 column, u16 row, UIElement_Ptr value){ *_Grid_getPtr(grid, column, row)=value; } -#define Grid_foreach(GRID_PTR, ELEM_VAR_NAME, CODE...){ \ - for(u16 _g_r = 0; _g_r < GRID_PTR->rows; _g_r++){ \ - for(u16 _g_c = 0; _g_c < GRID_PTR->columns; _g_c++){ \ - UIElement_Ptr ELEM_VAR_NAME = Grid_get(GRID_PTR, _g_c, _g_r); \ - { CODE } \ - } \ - } \ -} - void Grid_freeMembers(void* _self){ Grid* self=(Grid*)_self; Grid_foreach(self, el, @@ -45,12 +36,36 @@ UI_Maybe Grid_draw(Renderer* renderer, UIElement_Ptr _self, const DrawingArea ar return MaybeNull; } -kt_define(Grid, Grid_freeMembers, NULL); +UI_Maybe Grid_deserialize(Dtsod* dtsod){ + Grid gr; + Unitype uni; + Autoarr(UIElement_Ptr)* content=Autoarr_create(UIElement_Ptr, 64, 8); -Grid* Grid_create(u16 columns, u16 rows, UIElement_Ptr* ui_elements){ + UI_try(UIElement_deserializeBase(dtsod, &gr.base), _91875, ;); + Dtsod_get_necessary(dtsod, "content"){ + Autoarr(Unitype)* _content=uni.VoidPtr; + Autoarr_foreach(_content, _row, + Autoarr(Unitype)* row=_row.VoidPtr; + Autoarr_foreach(row, _elem_d, + Dtsod* elem_dtsod=_elem_d.VoidPtr; + UI_try(UIElement_deserialize(elem_dtsod), _m_uie, ;); + Autoarr_add(content, (UIElement_Ptr)_m_uie.value.VoidPtr); + ) + ); + } + + Grid* ptr=malloc(sizeof(*ptr)); + *ptr=gr; + return SUCCESS(UniHeapPtr(TextBlock, ptr)); +} + + +uit_define(Grid, Grid_freeMembers, NULL, Grid_draw, Grid_deserialize); + +Grid* Grid_create(char* name, u16 columns, u16 rows, UIElement_Ptr* ui_elements){ Grid* grid=malloc(sizeof(Grid)); *grid=(Grid){ - .base=__UIElement_createDefault(ktid_name(Grid), Grid_draw), + .base=_UIElement_initBaseDefault(name, &UITDescriptor_Grid), .columns=columns, .rows=rows, .ui_elements=ui_elements diff --git a/src/TUI/TextBlock.c b/src/TUI/TextBlock.c index 44ec5f4..29154a2 100644 --- a/src/TUI/TextBlock.c +++ b/src/TUI/TextBlock.c @@ -18,11 +18,27 @@ UI_Maybe TextBlock_draw(Renderer* renderer, UIElement_Ptr _self, const DrawingAr return MaybeNull; } -kt_define(TextBlock, TextBlock_freeMembers, NULL); +UI_Maybe TextBlock_deserialize(Dtsod* dtsod){ + TextBlock tb; + Unitype uni; -TextBlock* TextBlock_create(string text){ + UI_try(UIElement_deserializeBase(dtsod, &tb.base), _8751, ;); + Dtsod_get_necessary(dtsod, "text"){ + char* cptr=uni.VoidPtr; + tb.text=(string){.ptr=cptr, .length=cptr_length(cptr)}; + } + + TextBlock* ptr=malloc(sizeof(*ptr)); + *ptr=tb; + return SUCCESS(UniHeapPtr(TextBlock, ptr)); +} + + +uit_define(TextBlock, TextBlock_freeMembers, NULL,TextBlock_draw, TextBlock_deserialize); + +TextBlock* TextBlock_create(char* name, string text){ TextBlock* textBlock=malloc(sizeof(TextBlock)); - textBlock->base=__UIElement_createDefault(ktid_name(TextBlock), TextBlock_draw); + textBlock->base=_UIElement_initBaseDefault(name, &UITDescriptor_TextBlock); textBlock->text=string_copy(text); return textBlock; } diff --git a/src/TUI/UIElement.c b/src/TUI/UIElement.c index ccc6700..d0b38d8 100644 --- a/src/TUI/UIElement.c +++ b/src/TUI/UIElement.c @@ -4,32 +4,30 @@ kt_define(UIElement, NULL, NULL); Autoarr_define(UIElement_Ptr, true); Array_define(UIElement); - // ktid is needed to check if it is uninitilized by calling ktDescriptor_get -UIElement __UIElement_createDefault(ktid typeId, UIElement_draw_t drawFunc){ +inline UIElement _UIElement_initBaseDefault(char* name, UITDescriptor* uit){ return (UIElement){ - .type=ktDescriptor_get(typeId), + .name=name, + .ui_type=uit, .min_width=2, .min_height=2, .width_scaling=UIElement_no_scaling, .height_scaling=UIElement_no_scaling, - .color=kp_fgWhite|kp_bgBlack, + .color=kp_bgBlack|kp_fgGray, .border={ .left=UIBorder_Thin, .right=UIBorder_Thin, .top=UIBorder_Thin, .bottom=UIBorder_Thin, .color=kp_bgBlack|kp_fgGray }, - .draw=drawFunc }; } void UIElement_destroy(UIElement_Ptr self){ - if(self->type->freeMembers) - self->type->freeMembers(self); + if(self->ui_type->type->freeMembers) + self->ui_type->type->freeMembers(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,;); @@ -44,3 +42,43 @@ UI_Maybe UIElement_validate(UIElement_Ptr u, DrawingArea a){ UI_safethrow(UIError_InvalidWidth,;); return MaybeNull; } + + +UI_Maybe UIElement_deserializeBase(Dtsod* dtsod, UIElement* base){ + Unitype uni; + Dtsod_get_necessary(dtsod, "name"); + char* name=uni.VoidPtr; + Dtsod_get_necessary(dtsod, "type"); + UITDescriptor* ui_type=uni.VoidPtr; + *base=_UIElement_initBaseDefault(name, ui_type); + Dtsod_get_optional(dtsod, "min_width") + base->min_width=uni.UInt64; + Dtsod_get_optional(dtsod, "min_height") + base->min_height=uni.UInt64; + Dtsod_get_optional(dtsod, "width_scaling") + base->width_scaling=uni.UInt64; + Dtsod_get_optional(dtsod, "height_scaling") + base->height_scaling=uni.UInt64; + Dtsod_get_optional(dtsod, "bg_color") + set_color(uni.VoidPtr, base->color); + Dtsod_get_optional(dtsod, "fg_color") + set_color(uni.VoidPtr, base->color); + base->border.color=base->color; + Dtsod_get_optional(dtsod, "border"){ + Dtsod* border_dtsod=uni.VoidPtr; + Dtsod_get_optional(border_dtsod, "top") + set_border_thickness(uni.VoidPtr, base->border.top); + Dtsod_get_optional(border_dtsod, "bottom") + set_border_thickness(uni.VoidPtr, base->border.bottom); + Dtsod_get_optional(border_dtsod, "left") + set_border_thickness(uni.VoidPtr, base->border.left); + Dtsod_get_optional(border_dtsod, "right") + set_border_thickness(uni.VoidPtr, base->border.right); + Dtsod_get_optional(dtsod, "bg_color") + set_color(uni.VoidPtr, base->border.color); + Dtsod_get_optional(dtsod, "fg_color") + set_color(uni.VoidPtr, base->border.color); + } + + return MaybeNull; +} diff --git a/src/TUI/UIError.h b/src/TUI/UIError.h index d1e1124..9bc1555 100644 --- a/src/TUI/UIError.h +++ b/src/TUI/UIError.h @@ -7,7 +7,8 @@ extern "C" { #include "../../kerep/src/base/base.h" PACKED_ENUM(UIError, - UIError_Success=0, + UIError_Success=ERR_IO_EOF+1, + UIError_NotImplemented, UIError_NullPtr, UIError_InvalidHeight, UIError_InvalidWidth, UIError_InvalidX, UIError_InvalidY, diff --git a/src/TUI/enums_getByName.c b/src/TUI/enums_getByName.c new file mode 100644 index 0000000..c8ad4bb --- /dev/null +++ b/src/TUI/enums_getByName.c @@ -0,0 +1,113 @@ +#include "tui_internal.h" + +#define enum_pair(name, value) { cptr_copy(name), UniUInt64(value) } + +Hashtable* _colors_table=NULL; +void termcolor_table_init(){ + _colors_table=Hashtable_create(); + KVPair pairs[]={ + enum_pair("black", kp_bgBlack|kp_fgBlack), + enum_pair("white", kp_bgWhite|kp_fgWhite), + enum_pair("gray", kp_bgGray|kp_fgGray), + enum_pair("red", kp_bgRed|kp_fgRed), + enum_pair("green", kp_bgGreen|kp_fgGreen), + enum_pair("yellow", kp_bgYellow|kp_fgYellow), + enum_pair("blue", kp_bgBlue|kp_fgBlue), + enum_pair("magenta", kp_bgMagenta|kp_fgMagenta), + enum_pair("cyan", kp_bgCyan|kp_fgCyan), + + enum_pair("gray_dark", kp_bgGrayD|kp_fgGrayD), + enum_pair("red_dark", kp_bgRedD|kp_fgRedD), + enum_pair("green_dark", kp_bgGreenD|kp_fgGreenD), + enum_pair("yellow_dark", kp_bgYellowD|kp_fgYellowD), + enum_pair("blue_dark", kp_bgBlueD|kp_fgBlueD), + enum_pair("magenta_dark", kp_bgMagentaD|kp_fgMagentaD), + enum_pair("cyan_dark", kp_bgCyanD|kp_fgCyanD), + + enum_pair("dark_gray", kp_bgGrayD|kp_fgGrayD), + enum_pair("dark_red", kp_bgRedD|kp_fgRedD), + enum_pair("dark_green", kp_bgGreenD|kp_fgGreenD), + enum_pair("dark_yellow", kp_bgYellowD|kp_fgYellowD), + enum_pair("dark_blue", kp_bgBlueD|kp_fgBlueD), + enum_pair("dark_magenta", kp_bgMagentaD|kp_fgMagentaD), + enum_pair("dark_cyan", kp_bgCyanD|kp_fgCyanD), + + enum_pair("gray_d", kp_bgGrayD|kp_fgGrayD), + enum_pair("red_d", kp_bgRedD|kp_fgRedD), + enum_pair("green_d", kp_bgGreenD|kp_fgGreenD), + enum_pair("yellow_d", kp_bgYellowD|kp_fgYellowD), + enum_pair("blue_d", kp_bgBlueD|kp_fgBlueD), + enum_pair("magenta_d", kp_bgMagentaD|kp_fgMagentaD), + enum_pair("cyan_d", kp_bgCyanD|kp_fgCyanD), + + enum_pair("d_gray", kp_bgGrayD|kp_fgGrayD), + enum_pair("d_red", kp_bgRedD|kp_fgRedD), + enum_pair("d_green", kp_bgGreenD|kp_fgGreenD), + enum_pair("d_yellow", kp_bgYellowD|kp_fgYellowD), + enum_pair("d_blue", kp_bgBlueD|kp_fgBlueD), + enum_pair("d_magenta", kp_bgMagentaD|kp_fgMagentaD), + enum_pair("d_cyan", kp_bgCyanD|kp_fgCyanD), + + enum_pair("gray_d", kp_bgGrayD|kp_fgGrayD), + enum_pair("red_d", kp_bgRedD|kp_fgRedD), + enum_pair("green_d", kp_bgGreenD|kp_fgGreenD), + enum_pair("yellow_d", kp_bgYellowD|kp_fgYellowD), + enum_pair("blue_d", kp_bgBlueD|kp_fgBlueD), + enum_pair("magenta_d", kp_bgMagentaD|kp_fgMagentaD), + enum_pair("cyan_d", kp_bgCyanD|kp_fgCyanD), + + enum_pair("dgray", kp_bgGrayD|kp_fgGrayD), + enum_pair("dred", kp_bgRedD|kp_fgRedD), + enum_pair("dgreen", kp_bgGreenD|kp_fgGreenD), + enum_pair("dyellow", kp_bgYellowD|kp_fgYellowD), + enum_pair("dblue", kp_bgBlueD|kp_fgBlueD), + enum_pair("dmagenta", kp_bgMagentaD|kp_fgMagentaD), + enum_pair("dcyan", kp_bgCyanD|kp_fgCyanD), + }; + Hashtable_addMany(_colors_table, pairs, sizeof(pairs)/sizeof(KVPair)); +} + +int termcolor_getByName(char* color_name){ + char* color_name_lower=cptr_toLower(color_name); + Unitype uni; + if(!Hashtable_tryGet(_colors_table, color_name_lower, &uni)) + return -1; + return uni.UInt64; +} + +Hashtable* _UIBorderThickness_table=NULL; + +void UIBorderThickness_table_init(){ + _UIBorderThickness_table=Hashtable_create(); + KVPair pairs[]={ + enum_pair("hidden", UIBorder_Hidden), + enum_pair("0", UIBorder_Hidden), + enum_pair("thin", UIBorder_Thin), + enum_pair("0.5", UIBorder_Thin), + enum_pair("thick", UIBorder_Thick), + enum_pair("1", UIBorder_Thick), + enum_pair("double", UIBorder_Double), + enum_pair("2", UIBorder_Double), + enum_pair("noborder", UiBorder_NoBorder), + enum_pair("no", UiBorder_NoBorder) + }; + Hashtable_addMany(_UIBorderThickness_table, pairs, sizeof(pairs)/sizeof(KVPair)); +} + +int UIBorderThickness_getByName(char* name){ + char* name_lower=cptr_toLower(name); + Unitype uni; + if(!Hashtable_tryGet(_UIBorderThickness_table, name_lower, &uni)) + return -1; + return uni.UInt64; +} + +void UI_enum_tables_init(){ + termcolor_table_init(); + UIBorderThickness_table_init(); +} + +void UI_enum_tables_free(){ + Hashtable_free(_colors_table); + Hashtable_free(_UIBorderThickness_table); +} \ No newline at end of file diff --git a/src/TUI/tui.c b/src/TUI/tui.c index 74ce8a7..667da72 100644 --- a/src/TUI/tui.c +++ b/src/TUI/tui.c @@ -1,18 +1,79 @@ -#include "tui.h" +#include "tui_internal.h" +#include "Dtsod/tui_dtsod_internal.h" kt_define(DrawingArea, NULL, NULL); kt_define(UIBorder, NULL, NULL); +kt_define(UITDescriptor, NULL, NULL); + +Hashtable* __uit_hashtable=NULL; +u32 __kt_id_first=-1; +Autoarr(Pointer)* __uit_temp_arr=NULL; +UITDescriptor** __uit_descriptors=NULL; + +/// call this between kt_beginInit() and kt_endInit() +void kt_beginInitTUI(){ + __uit_hashtable=Hashtable_create(); + __kt_id_first=ktid_last; + __uit_temp_arr=Autoarr_create(Pointer, 32, 32); +} + +/// call this between kt_beginInit() and kt_endInit() +void kt_endInitTUI(){ + __uit_descriptors=(UITDescriptor**)Autoarr_toArray(__uit_temp_arr); + Autoarr_free(__uit_temp_arr, true); +} + +void kt_freeTUI(){ + free(__uit_descriptors); + Hashtable_free(__uit_hashtable); +} + +void __uit_register(ktDescriptor* kt, UITDescriptor* uit){ + uit->type=kt; + Hashtable_add(__uit_hashtable, cptr_copy(kt->name), UniStackPtr(UITDescriptor, uit)); +} + +UITDescriptor* UITDescriptor_getById(ktid id){ + if(id > ktid_last) + throw(ERR_WRONGINDEX); + if(__uit_descriptors==NULL) + throw(ERR_NULLPTR); + return __uit_descriptors[id - __kt_id_first]; +} + +///@return NULL if not found +UITDescriptor* UITDescriptor_getByName(char* name){ + Unitype val=Hashtable_get(__uit_hashtable, name); + return val.VoidPtr; +} void kt_initScolteTypes(){ - // term + // term.h kt_register(TerminalSize); kt_register(TermCharInfo); - // tui + // tui.h + kt_register(UITDescriptor) kt_register(DrawingArea); kt_register(UIBorder); kt_register(FrameBuffer); kt_register(Renderer); kt_register(UIElement); - kt_register(Grid); - kt_register(TextBlock); + uit_register(Grid); + uit_register(TextBlock); + // tui_dtsod.h + kt_register(UIDtsodFileModel); + kt_register(UIDtsodParser); + kt_register(UIContext); } + +/// call this between kt_beginInitTUI() and kt_endInitTUI() +void Scolte_init(){ + kt_initScolteTypes(); + UI_enum_tables_init(); +} + +// call this before kt_free() +void Scolte_free(){ + UI_enum_tables_free(); + kt_freeTUI(); +} \ No newline at end of file diff --git a/src/TUI/tui.h b/src/TUI/tui.h index 6be3c9d..6817b22 100644 --- a/src/TUI/tui.h +++ b/src/TUI/tui.h @@ -8,12 +8,54 @@ extern "C" { #include "../../kerep/src/Array/Array.h" #include "../term/term.h" #include "../encoding/encoding.h" +#include "Dtsod/tui_dtsod.h" #include "UIError.h" +////////////////////////////////////// +// Prototypes // +////////////////////////////////////// -/// initializes type descriptors for this project's types -/// call this function between kt_beginInit() and kt_endInit() -void kt_initScolteTypes(); +typedef struct UIElement UIElement; +typedef UIElement* UIElement_Ptr; +typedef struct Renderer Renderer; +typedef struct DrawingArea DrawingArea; + +///@return Maybe +typedef UI_THROWING_FUNC_DECL( (*UIElement_draw_t)(Renderer* renderer, UIElement_Ptr self, const DrawingArea area) ); + +///@return Maybe +typedef UI_THROWING_FUNC_DECL( (*UIElement_deserialize_t)(Dtsod* dtsod) ); + + +////////////////////////////////////// +// UI Type System // +////////////////////////////////////// + +STRUCT(UITDescriptor, + ktDescriptor* type; + UIElement_draw_t draw; + UIElement_deserialize_t deserialize; +) + +#define uit_declare(TYPE) extern UITDescriptor UITDescriptor_##TYPE; + +#define uit_define(TYPE, FREE_F, TOSTRING_F, DRAW_F, DESERIALIZE_F) kt_define(TYPE, FREE_F, TOSTRING_F) \ + UITDescriptor UITDescriptor_##TYPE={ \ + .draw=DRAW_F, \ + .deserialize=DESERIALIZE_F \ + }; + +/// call this between kt_beginInit() and kt_endInit() +void kt_beginInitTUI(); +/// call this between kt_beginInitTUI() and kt_endInitTUI() +void Scolte_init(); +/// call this between kt_beginInit() and kt_endInit() +void kt_endInitTUI(); +// call this before kt_free() +void Scolte_free(); + +UITDescriptor* UITDescriptor_getById(ktid i); +UITDescriptor* UITDescriptor_getByName(char* name); ////////////////////////////////////// // Enums // @@ -27,6 +69,7 @@ PACKED_ENUM(UIBorderThickness, UiBorder_NoBorder /* no space */ ) + ////////////////////////////////////// // Small structs // ////////////////////////////////////// @@ -74,34 +117,32 @@ UI_THROWING_FUNC_DECL(Renderer_drawLineX(Renderer* renderer, TermCharInfo tci, u UI_THROWING_FUNC_DECL(Renderer_drawLineY(Renderer* renderer, TermCharInfo tci, u16 x, u16 y, u16 length)); UI_THROWING_FUNC_DECL(Renderer_drawBorder(Renderer* renderer, UIBorder border, const DrawingArea area)); + ////////////////////////////////////// // UIElement abstract struct // ////////////////////////////////////// -typedef struct UIElement UIElement; -typedef UIElement* UIElement_Ptr; -typedef UI_THROWING_FUNC_DECL((*UIElement_draw_t)(Renderer* renderer, UIElement_Ptr self, const DrawingArea area)); - -#define UIElement_no_scaling (u16)0 - STRUCT(UIElement, - ktDescriptor* type; + UITDescriptor* ui_type; + char* name; u16 min_width; u16 min_height; u16 width_scaling; u16 height_scaling; termcolor color; UIBorder border; - UIElement_draw_t draw; ) +Autoarr_declare(UIElement_Ptr) +Array_declare(UIElement) + +#define UIElement_no_scaling (u16)0 /// proper way to free UIElement and all its members void UIElement_destroy(UIElement_Ptr self); -#define UIElement_draw(RENDERER, UIE_PTR, PLACE_RECT) \ - ((UIElement_Ptr)UIE_PTR)->draw(RENDERER, UIE_PTR, PLACE_RECT) -Autoarr_declare(UIElement_Ptr) -Array_declare(UIElement) +#define UIElement_draw(RENDERER, UIE_PTR, PLACE_RECT) \ + (UIE_PTR)->ui_type->draw(RENDERER, UIE_PTR, PLACE_RECT) + ////////////////////////////////////// // UIElement derivatives // @@ -115,11 +156,20 @@ STRUCT(Grid, u16 rows; UIElement_Ptr* ui_elements; /* UIElement[rows][columns] */ ) +uit_declare(Grid); -Grid* Grid_create(u16 columns, u16 rows, UIElement_Ptr* ui_elements); +Grid* Grid_create(char* name, u16 columns, u16 rows, UIElement_Ptr* ui_elements); UIElement_Ptr Grid_get(Grid* grid, u16 column, u16 row); void Grid_set(Grid* grid, u16 column, u16 row, UIElement_Ptr value); +#define Grid_foreach(GRID_PTR, ELEM_VAR_NAME, CODE...) { \ + for(u16 _g_r = 0; _g_r < GRID_PTR->rows; _g_r++){ \ + for(u16 _g_c = 0; _g_c < GRID_PTR->columns; _g_c++){ \ + UIElement_Ptr ELEM_VAR_NAME = Grid_get(GRID_PTR, _g_c, _g_r); \ + { CODE; } \ + } \ + } \ +} ////// TextBlock ////// @@ -127,9 +177,10 @@ STRUCT(TextBlock, UIElement base; string text; ) +uit_declare(TextBlock); /// creates a TextBlock with a copy of text -TextBlock* TextBlock_create(string text); +TextBlock* TextBlock_create(char* name, string text); #if __cplusplus } diff --git a/src/TUI/tui_internal.h b/src/TUI/tui_internal.h index e555ab6..044645b 100644 --- a/src/TUI/tui_internal.h +++ b/src/TUI/tui_internal.h @@ -6,9 +6,12 @@ extern "C" { #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_Ptr u, DrawingArea a)); +extern UIElement _UIElement_initBaseDefault(char* name, UITDescriptor* type); + +UI_THROWING_FUNC_DECL( DrawingArea_validate(DrawingArea a) ); +UI_THROWING_FUNC_DECL( UIElement_validate(UIElement_Ptr u, DrawingArea a) ); + +UI_THROWING_FUNC_DECL( UIElement_deserializeBase(Dtsod* dtsod, UIElement* base) ); extern termchar UIBorder_char_h[4]; extern termchar UIBorder_char_v[4]; @@ -17,6 +20,31 @@ extern termchar UIBorder_char_rt[4][4]; extern termchar UIBorder_char_rb[4][4]; extern termchar UIBorder_char_lb[4][4]; +/// extended kt_register +void __uit_register(ktDescriptor* kt, UITDescriptor* uit); +#define uit_register(TYPE) kt_register(TYPE); __uit_register(&ktDescriptor_##TYPE, &UITDescriptor_##TYPE) + + +void UI_enum_tables_init(); +void UI_enum_tables_free(); + +int termcolor_getByName(char* color_name); +int UIBorderThickness_getByName(char* name); + +#define set_color(name, var){ \ + int color=termcolor_getByName(name); \ + if(color==-1) \ + UI_safethrow(cptr_concat("incorrect color name: ", name), ;); \ + var|=(termcolor)color; \ +} + +#define set_border_thickness(name, var){ \ + int th=UIBorderThickness_getByName(name); \ + if(th==-1) \ + UI_safethrow(cptr_concat("incorrect UIBorderThickness name: ", name), ;); \ + var=(UIBorderThickness)th; \ +} + #if __cplusplus } #endif diff --git a/src/main.c b/src/main.c index 1792286..9418736 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,5 @@ #include "TUI/tui.h" +#include "TUI/Dtsod/tui_dtsod.h" #include "../kerep/src/Filesystem/filesystem.h" #include #include @@ -6,15 +7,36 @@ #include #endif -Maybe tryReadFile(char* filePath){ - if(!file_exists(filePath)) - kprintf("file doesnt exist, creating new\n"); - try(file_open(filePath, FileOpenMode_ReadAppend), _m_file,;); - FileHandle file=_m_file.value.VoidPtr; - char* fileContent=NULL; - try(file_readAll(file, &fileContent), _m_bcount,;) - try(file_close(file),_m_,;); - return SUCCESS(UniHeapPtr(char,fileContent)); +#define EMBEDDED_RESOURCE_POSTFIX view +#include "generated/view.h" + +// Maybe tryReadFile(char* filePath){ +// if(!file_exists(filePath)) +// kprintf("file doesnt exist, creating new\n"); +// try(file_open(filePath, FileOpenMode_ReadAppend), _m_file,;); +// FileHandle file=_m_file.value.VoidPtr; +// char* fileContent=NULL; +// try(file_readAll(file, &fileContent), _m_bcount,;) +// try(file_close(file),_m_,;); +// return SUCCESS(UniHeapPtr(char,fileContent)); +// } + +UI_THROWING_FUNC_DECL(test_example_ui_build()); +UI_Maybe test_example_ui_build() { + + // ui from dtsod build example + UIDtsodParser* p=UIDtsodParser_create(); + for(int i=0; itext=string_fromCptr("text replaced"); + return MaybeNull; } i32 main(const i32 argc, const char* const* argv){ @@ -33,7 +55,9 @@ i32 main(const i32 argc, const char* const* argv){ // kerep type system kt_beginInit(); kt_initKerepTypes(); - kt_initScolteTypes(); + kt_beginInitTUI(); + Scolte_init(); + kt_endInitTUI(); kt_endInit(); // print command line arguments @@ -50,10 +74,10 @@ i32 main(const i32 argc, const char* const* argv){ // render ui Renderer* renderer=Renderer_create(); - TextBlock* testTextBlock=TextBlock_create(string_fromCptr("some example text")); + TextBlock* testTextBlock=TextBlock_create("TextBlock1", string_fromCptr("some example text")); Autoarr(UIElement_Ptr)* grid_content=Autoarr_create(UIElement_Ptr, 1, 64); Autoarr_add(grid_content, (UIElement_Ptr)testTextBlock); - Grid* mainGrid=Grid_create(1,1, Autoarr_toArray(grid_content)); + Grid* mainGrid=Grid_create("MainGrid", 1,1, Autoarr_toArray(grid_content)); Autoarr_free(grid_content, true); tryLast(UIElement_draw(renderer, (UIElement_Ptr)mainGrid, ((DrawingArea){.x=10, .y=4, .h=7, .w=24})),_); tryLast(Renderer_drawFrame(renderer),_2); @@ -63,7 +87,10 @@ i32 main(const i32 argc, const char* const* argv){ // TODO signal( SIGWINCH, redraw ); + // tryLast(test_example_ui_build(), _6981751); + // exit + Scolte_free(); kt_free(); term_resetColors(); term_cursorHide(false); diff --git a/tasks/build_view.sh b/tasks/build_view.sh new file mode 100644 index 0000000..96e69ff --- /dev/null +++ b/tasks/build_view.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -eo pipefail + +mkdir -p "obj" +clean_dir "obj/objects" +mkdir -p "src" +mkdir -p "src/generated" + +cd resource_embedder +./build.sh +cd .. + +embedder_args="-o src/generated/view.h" +for guifile in $(find "view" -name '*.tui.dtsod'); do + embedder_args="$embedder_args -i $guifile" +done +resource_embedder/resource_embedder $embedder_args diff --git a/tasks/clean_additions.sh b/tasks/clean_additions.sh index 7ba80ee..3b4ee55 100644 --- a/tasks/clean_additions.sh +++ b/tasks/clean_additions.sh @@ -1,4 +1,6 @@ #!/usr/bin/bash +set -eo pipefail + for tmpfile in $(ls -a | grep -e '\.rebuild.*\.tmp'); do try_delete_dir_or_file "$tmpfile" done @@ -8,3 +10,5 @@ for submodule in kerep utf8proc; do make clean cd .. done + +try_delete_dir_or_file src/generated diff --git a/tasks/pre_build.sh b/tasks/pre_build.sh index 19ed999..b193cea 100644 --- a/tasks/pre_build.sh +++ b/tasks/pre_build.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -eo pipefail # if $lib_project.a doesn't exist or rebuild_* task was executed, builds static lib function handle_static_dependency { @@ -23,3 +24,5 @@ function handle_static_dependency { handle_static_dependency kerep "$DEPS_BUILD_TASK" kerep/bin/kerep.a handle_static_dependency utf8proc libutf8proc.a utf8proc/libutf8proc.a + +source tasks/build_view.sh diff --git a/tasks/rebuild_lib.sh b/tasks/rebuild_lib.sh index 7e2928a..407ec56 100644 --- a/tasks/rebuild_lib.sh +++ b/tasks/rebuild_lib.sh @@ -1,4 +1,6 @@ #!/bin/bash +set -eo pipefail + source cbuild/colors.sh source cbuild/functions.sh touch ".rebuild_$1.tmp" diff --git a/view/example.tui.dtsod b/view/example.tui.dtsod new file mode 100644 index 0000000..5b5523d --- /dev/null +++ b/view/example.tui.dtsod @@ -0,0 +1,31 @@ +TUI_version: 1; +namespace: "example_namespace" + +$ui: { + name: "UIElement", + type: "UIElement", + min_width: 4, + max_width: 4, + width_scaling: 0, + height_scaling: 0, + bg_color: "black", + fg_color: "white", + border: { + top: "hidden", + bottom: "no", + left: "thick", + right: "double", + fg_color: "dark_cyan", + bg_color: "gray"; + }; +}; + +$ui: [ + name: "Grid", + type: "Grid", + content: [ + // column + [ "@UIElement" ], // row + [ "@namespace.element1" ], // row + ]; +]; diff --git a/view/main.tui.dtsod b/view/main.tui.dtsod new file mode 100644 index 0000000..abe2af0 --- /dev/null +++ b/view/main.tui.dtsod @@ -0,0 +1,10 @@ +TUI_version: 1; +namespace: "main"; + +grid: [ + name: "Grid", + type: "Grid", + // column + [ "@namespace.element0" ], // row + [ "@namespace.element1" ], // row +];