ScalingSize, onBuild, toString

This commit is contained in:
Timerix22 2023-05-27 22:40:28 +06:00
parent b19c020235
commit d7f8e7303d
14 changed files with 345 additions and 115 deletions

2
kerep

@ -1 +1 @@
Subproject commit 70807ed22b4c34db247fd8fc1ca1c776dd27ab4c Subproject commit aba67710c70c779fcf04af2bd01fb348ce75135d

View File

@ -66,8 +66,23 @@ UI_Maybe UIDtsodParser_parseText(UIDtsodParser* parser, char* file_name_placehol
return MaybeNull; return MaybeNull;
} }
UI_Maybe UIElement_deserialize(Dtsod* dtsod){
char* type_name;
Dtsod_tryGet_cptr(dtsod, "type", type_name, true);
UITDescriptor* type=UITDescriptor_getByName(type_name);
if(type==NULL)
UI_safethrow_msg(cptr_concat("invalid type '", type_name, "'"), ;);
if(type->deserialize==NULL)
UI_safethrow(UIError_NullPtr, ;);
UI_try(type->deserialize(dtsod), _m_ui, ;);
return _m_ui;
}
//////////////////////////////////////
// UIContext //
//////////////////////////////////////
void _UIContext_freeMembers(void* _u){ void _UIContext_freeMembers(void* _u){
UIContext* u=_u; UIContext* u=_u;
Hashtable_free(u->ui_elements); Hashtable_free(u->ui_elements);
@ -80,17 +95,6 @@ void UIContext_destroy(UIContext* u){
kt_define(UIContext, _UIContext_freeMembers, NULL); kt_define(UIContext, _UIContext_freeMembers, NULL);
UI_Maybe UIElement_deserialize(Dtsod* dtsod){
char* type_name;
Dtsod_tryGet_cptr(dtsod, "type", type_name, true);
UITDescriptor* ui_type=UITDescriptor_getByName(type_name);
if(ui_type==NULL)
UI_safethrow_msg(cptr_concat("invalid type '", type_name, "'"), ;);
UI_try(ui_type->deserialize(dtsod), _m_ui, ;);
return _m_ui;
}
UI_Maybe UIDtsodParser_constructUIContext(UIDtsodParser* parser){ UI_Maybe UIDtsodParser_constructUIContext(UIDtsodParser* parser){
if(parser->context == NULL){ if(parser->context == NULL){
parser->context=malloc(sizeof(UIContext)); parser->context=malloc(sizeof(UIContext));
@ -107,14 +111,16 @@ UI_Maybe UIDtsodParser_constructUIContext(UIDtsodParser* parser){
char* file_namespace; char* file_namespace;
Dtsod_tryGet_cptr(fm.dtsod, "namespace", file_namespace, true); Dtsod_tryGet_cptr(fm.dtsod, "namespace", file_namespace, true);
Hashtable_foreach(fm.dtsod, dtsod_elem, Hashtable_foreach(fm.dtsod, dtsod_elem,
if(cptr_compare(dtsod_elem.key, "ui")) { if(cptr_equals(dtsod_elem.key, "ui")) {
if(!UniCheckTypePtr(dtsod_elem.value, Autoarr(Unitype)))
UI_safethrow(UIError_InvalidFormat, ;);
Autoarr_Unitype* ui_ar=dtsod_elem.value.VoidPtr; Autoarr_Unitype* ui_ar=dtsod_elem.value.VoidPtr;
Autoarr_foreach(ui_ar, ui_el_dtsod, Autoarr_foreach(ui_ar, ui_el_dtsod,
UI_try(UIElement_deserialize(ui_el_dtsod.VoidPtr),_m_ui,;); UI_try(UIElement_deserialize(ui_el_dtsod.VoidPtr),_m_ui,;);
UIElement_Ptr new_el=_m_ui.value.VoidPtr; UIElement_Ptr new_el=_m_ui.value.VoidPtr;
// kprintf("[UIDtsodParser_constructUIContext] %s : %s\n", new_el->name, new_el->ui_type->type->name); // kprintf("[UIDtsodParser_constructUIContext] %s : %s\n", new_el->name, new_el->type->kt->name);
if(new_el->ui_type->type->id==ktid_ptrName(Grid)){ if(new_el->type->onBuild){
UI_try(_Grid_bindContent((Grid*)new_el, parser->context),_15151,;); UI_try(new_el->type->onBuild(new_el, parser->context),_15151,;);
} }
UI_try( UIContext_add(parser->context, file_namespace, new_el), _a76515, ;); UI_try( UIContext_add(parser->context, file_namespace, new_el), _a76515, ;);
); );
@ -140,16 +146,16 @@ UI_Maybe UIContext_getAny(UIContext* context, char* name){
UI_Maybe _UIContext_get(UIContext* context, char* name, ktid type_id){ UI_Maybe _UIContext_get(UIContext* context, char* name, ktid type_id){
UI_try(UIContext_getAny(context, name), _m_ui, ;); UI_try(UIContext_getAny(context, name), _m_ui, ;);
UIElement* ptr=_m_ui.value.VoidPtr; UIElement* ptr=_m_ui.value.VoidPtr;
if(ptr->ui_type->type->id != type_id) if(ptr->type->kt->id != type_id)
UI_safethrow_msg(cptr_concat( UI_safethrow_msg(cptr_concat(
"tried to get ",ktDescriptor_get(type_id)->name, " <",name,"> but it is of type ", ptr->ui_type->type->name "tried to get ",ktDescriptor_get(type_id)->name, " <",name,"> but it is of type ", ptr->type->kt->name
), ;); ), ;);
return _m_ui; return _m_ui;
} }
UI_Maybe UIContext_add(UIContext* context, char* namespace, _UIElement_Ptr _new_el){ UI_Maybe UIContext_add(UIContext* context, char* namespace, _UIElement_Ptr _new_el){
UIElement_Ptr new_el=_new_el; UIElement_Ptr new_el=_new_el;
Unitype u=UniPtr(new_el->ui_type->type->id, new_el, true); Unitype u=UniPtr(new_el->type->kt->id, new_el, true);
char* namespace_and_name=cptr_concat(namespace, "_", new_el->name); char* namespace_and_name=cptr_concat(namespace, "_", new_el->name);
if(!Hashtable_tryAdd(context->ui_elements, namespace_and_name, u)) if(!Hashtable_tryAdd(context->ui_elements, namespace_and_name, u))
UI_safethrow_msg(cptr_concat("element with name <", new_el->name, "> already exists in context"), UI_safethrow_msg(cptr_concat("element with name <", new_el->name, "> already exists in context"),

View File

@ -44,7 +44,9 @@ UI_THROWING_FUNC_DECL(UIDtsodParser_constructUIContext(UIDtsodParser* parser));
////////////////////////////////////// //////////////////////////////////////
// UIContext // // UIContext //
////////////////////////////////////// //////////////////////////////////////
typedef struct UIContext UIContext; STRUCT(UIContext,
Hashtable* ui_elements;
)
void UIContext_destroy(UIContext* u); void UIContext_destroy(UIContext* u);
@ -61,7 +63,7 @@ UI_THROWING_FUNC_DECL(_UIContext_get(UIContext* context, char* name, ktid type_i
TYPE* NAMESPACE##_##NAME=_m_##NAMESPACE##_##NAME.value.VoidPtr; TYPE* NAMESPACE##_##NAME=_m_##NAMESPACE##_##NAME.value.VoidPtr;
///@return Maybe<void> ///@return Maybe<void>
UI_THROWING_FUNC_DECL(UIContext_add(UIContext* context, char* namespace, _UIElement_Ptr new_el)); UI_THROWING_FUNC_DECL(UIContext_add(UIContext* context, char* _namespace, _UIElement_Ptr new_el));
////////////////////////////////////// //////////////////////////////////////
@ -73,7 +75,7 @@ UI_THROWING_FUNC_DECL(UIContext_add(UIContext* context, char* namespace, _UIElem
UI_THROWING_FUNC_DECL( UIElement_deserialize(Dtsod* dtsod) ); UI_THROWING_FUNC_DECL( UIElement_deserialize(Dtsod* dtsod) );
#define __def_Dtsod_tryGet(dtsod, key, var_name, is_neccecary, TYPE, TYPE_ID, UNI_FIELD, code...) { \ #define _Dtsod_tryGet(dtsod, key, var_name, is_necessary, TYPE, TYPE_ID, UNI_FIELD, code...) { \
Unitype uni; \ Unitype uni; \
if(Hashtable_tryGet(dtsod, key, &uni)) { \ if(Hashtable_tryGet(dtsod, key, &uni)) { \
if(!UniCheckTypeId(uni, TYPE_ID)) \ if(!UniCheckTypeId(uni, TYPE_ID)) \
@ -82,35 +84,43 @@ UI_THROWING_FUNC_DECL( UIElement_deserialize(Dtsod* dtsod) );
var_name=uni.UNI_FIELD; \ var_name=uni.UNI_FIELD; \
{ code; } \ { code; } \
} \ } \
else if(is_neccecary) \ else if(is_necessary) \
UI_safethrow_msg(cptr_concat("can't find key '", key, "'"), ;); \ UI_safethrow_msg(cptr_concat("can't find key '", key, "'"), ;); \
} }
#define Dtsod_tryGet_i64(dtsod, key, var_name, is_neccecary, code...) \ #define Dtsod_tryGet_i64(dtsod, key, var_name, is_necessary, code...) \
__def_Dtsod_tryGet(dtsod, key, var_name, is_neccecary, i64, ktid_name(i64), Int64, code) _Dtsod_tryGet(dtsod, key, var_name, is_necessary, i64, ktid_name(i64), Int64, code)
#define Dtsod_tryGet_u64(dtsod, key, var_name, is_neccecary, code...) \ #define Dtsod_tryGet_u64(dtsod, key, var_name, is_necessary, code...) \
__def_Dtsod_tryGet(dtsod, key, var_name, is_neccecary, u64, ktid_name(u64), UInt64, code) _Dtsod_tryGet(dtsod, key, var_name, is_necessary, u64, ktid_name(u64), UInt64, code)
#define Dtsod_tryGet_f64(dtsod, key, var_name, is_neccecary, code...) \ #define Dtsod_tryGet_f64(dtsod, key, var_name, is_necessary, code...) \
__def_Dtsod_tryGet(dtsod, key, var_name, is_neccecary, f64, ktid_name(f64), Float64, code) _Dtsod_tryGet(dtsod, key, var_name, is_necessary, f64, ktid_name(f64), Float64, code)
#define Dtsod_tryGet_bool(dtsod, key, var_name, is_neccecary, code...) \ #define Dtsod_tryGet_bool(dtsod, key, var_name, is_necessary, code...) \
__def_Dtsod_tryGet(dtsod, key, var_name, is_neccecary, bool, ktid_name(bool), Bool, code) _Dtsod_tryGet(dtsod, key, var_name, is_necessary, bool, ktid_name(bool), Bool, code)
#define Dtsod_tryGet_ptr(dtsod, key, type, var_name, is_neccecary, code...) \ #define Dtsod_tryGet_ptr(dtsod, key, type, var_name, is_necessary, code...) \
__def_Dtsod_tryGet(dtsod, key, var_name, is_neccecary, type*, ktid_ptrName(type), VoidPtr, code) _Dtsod_tryGet(dtsod, key, var_name, is_necessary, type*, ktid_ptrName(type), VoidPtr, code)
#define Dtsod_tryGet_cptr(dtsod, key, var_name, is_neccecary, code...) \ #define Dtsod_tryGet_cptr(dtsod, key, var_name, is_necessary, code...) \
Dtsod_tryGet_ptr(dtsod, key, char, var_name, is_neccecary, code) Dtsod_tryGet_ptr(dtsod, key, char, var_name, is_necessary, code)
#define Dtsod_tryGet_Hashtable(dtsod, key, var_name, is_neccecary, code...) \ #define Dtsod_tryGet_Hashtable(dtsod, key, var_name, is_necessary, code...) \
Dtsod_tryGet_ptr(dtsod, key, Hashtable, var_name, is_neccecary, code) Dtsod_tryGet_ptr(dtsod, key, Hashtable, var_name, is_necessary, code)
#define Dtsod_tryGet_Autoarr(dtsod, key, var_name, is_neccecary, code...) \
Dtsod_tryGet_ptr(dtsod, key, Autoarr(Unitype), var_name, is_neccecary, code)
#define Dtsod_tryGet_Autoarr(dtsod, key, var_name, is_necessary, code...) \
Dtsod_tryGet_ptr(dtsod, key, Autoarr(Unitype), var_name, is_necessary, code)
#define Dtsod_tryGet_ScalingSize(dtsod, key, var_name, is_necessary, code...) { \
Unitype uni; \
if(Hashtable_tryGet(dtsod, key, &uni)) { \
UI_try(ScalingSize_fromUnitype(uni, &(var_name)), _195, ;); \
{ code; } \
} \
else if(is_necessary) \
UI_safethrow_msg(cptr_concat("can't find key '", key, "'"), ;); \
}
#if __cplusplus #if __cplusplus
} }

View File

@ -15,7 +15,3 @@ STRUCT(UIDtsodParser,
UIContext* context; UIContext* context;
bool returned_context; bool returned_context;
) )
STRUCT(UIContext,
Hashtable* ui_elements;
)

View File

@ -23,7 +23,8 @@ UI_Maybe _Grid_getName(Grid* grid, u16 column, u16 row) {
return SUCCESS(UniHeapPtr(char, *str_ptr)); return SUCCESS(UniHeapPtr(char, *str_ptr));
} }
UI_Maybe _Grid_bindContent(Grid* grid, UIContext* context) { UI_Maybe Grid_onBuildUIContext(UIElement* _grid, UIContext* context) {
Grid* grid=(Grid*)_grid;
Autoarr(UIElement_Ptr)* content=Autoarr_create(UIElement_Ptr, 64, 16); Autoarr(UIElement_Ptr)* content=Autoarr_create(UIElement_Ptr, 64, 16);
Grid_foreachName(grid, name, Grid_foreachName(grid, name,
UI_try(UIContext_getAny(context, name), m_uie, Autoarr_freeWithoutMembers(content,true)); UI_try(UIContext_getAny(context, name), m_uie, Autoarr_freeWithoutMembers(content,true));
@ -39,7 +40,9 @@ UI_Maybe _Grid_bindContent(Grid* grid, UIContext* context) {
void Grid_freeMembers(void* _self){ void Grid_freeMembers(void* _self){
Grid* self=(Grid*)_self; Grid* self=(Grid*)_self;
if(self->is_bound){ free(self->column_widths);
free(self->row_heights);
if(self->content_names){
for(u16 r = 0; r < self->rows; r++){ for(u16 r = 0; r < self->rows; r++){
for(u16 c = 0; c < self->columns; c++){ for(u16 c = 0; c < self->columns; c++){
tryLast(Grid_get(self, c, r), m_el, tryLast(Grid_get(self, c, r), m_el,
@ -49,11 +52,10 @@ void Grid_freeMembers(void* _self){
UIElement_destroy(el); UIElement_destroy(el);
} }
} }
}
free(self->content);
if(self->content_names)
free(self->content_names); free(self->content_names);
} }
else free(self->content);
}
UI_Maybe Grid_draw(Renderer* renderer, UIElement_Ptr _self, const DrawingArea area){ UI_Maybe Grid_draw(Renderer* renderer, UIElement_Ptr _self, const DrawingArea area){
Grid* self=(Grid*)_self; Grid* self=(Grid*)_self;
@ -67,33 +69,78 @@ UI_Maybe Grid_draw(Renderer* renderer, UIElement_Ptr _self, const DrawingArea ar
UI_Maybe Grid_deserialize(Dtsod* dtsod){ UI_Maybe Grid_deserialize(Dtsod* dtsod){
Grid gr; Grid gr;
Autoarr(Pointer)* content_names=Autoarr_create(Pointer, 64, 16);
u16 columns=0, rows=0; u16 columns=0, rows=0;
Autoarr(i16)* column_widths=Autoarr_create(i16, 16, 64);
Autoarr(i16)* row_heights=Autoarr_create(i16, 16, 64);
Autoarr(Pointer)* content_names=Autoarr_create(Pointer, 64, 16);
UI_try(UIElement_deserializeBase(dtsod, &gr.base), _91875, ;); UI_try(UIElement_deserializeBase(dtsod, &gr.base), _91875, ;);
Autoarr(Unitype)* _column_widths;
Dtsod_tryGet_Autoarr(dtsod, "column_widths", _column_widths, true,
Autoarr_foreach(_column_widths, _cw,
ScalingSize cw;
UI_try(ScalingSize_fromUnitype(_cw, &cw), _18751,
Autoarr_freeWithoutMembers(content_names, true);
Autoarr_freeWithoutMembers(column_widths, true);
Autoarr_freeWithoutMembers(row_heights, true);
);
Autoarr_add(column_widths, cw);
);
);
columns=Autoarr_length(column_widths);
Autoarr(Unitype)* _row_heights;
Dtsod_tryGet_Autoarr(dtsod, "row_heights", _row_heights, true,
Autoarr_foreach(_row_heights, _rh,
ScalingSize rh;
UI_try(ScalingSize_fromUnitype(_rh, &rh), _18751,
Autoarr_freeWithoutMembers(content_names, true);
Autoarr_freeWithoutMembers(row_heights, true);
Autoarr_freeWithoutMembers(row_heights, true);
);
Autoarr_add(row_heights, rh);
);
);
rows=Autoarr_length(row_heights);
Autoarr(Unitype)* _content; Autoarr(Unitype)* _content;
Dtsod_tryGet_Autoarr(dtsod, "content", _content, true); Dtsod_tryGet_Autoarr(dtsod, "content", _content, true);
rows=Autoarr_length(_content); if(rows != Autoarr_length(_content))
UI_safethrow(UIError_InvalidGrid,
Autoarr_freeWithoutMembers(content_names, true);
Autoarr_freeWithoutMembers(column_widths, true);
Autoarr_freeWithoutMembers(row_heights, true);
);
Autoarr_foreach(_content, _row, Autoarr_foreach(_content, _row,
if(!UniCheckTypePtr(_row, Autoarr(Unitype))){ if(!UniCheckTypePtr(_row, Autoarr(Unitype)))
UI_safethrow_msg( UI_safethrow_msg(
cptr_concat("expected Autoarr<Unitype>, but has got type id '", cptr_concat("expected type Autoarr(Unitype), but has got type id '",
toString_i64(_row.typeId), "'"), toString_i64(_row.typeId), "'"),
Autoarr_freeWithoutMembers(content_names, true)); Autoarr_freeWithoutMembers(content_names, true);
} Autoarr_freeWithoutMembers(column_widths, true);
Autoarr_freeWithoutMembers(row_heights, true);
);
Autoarr(Unitype)* row=_row.VoidPtr; Autoarr(Unitype)* row=_row.VoidPtr;
u16 row_len=Autoarr_length(row); if(columns != Autoarr_length(row))
if(columns==0) UI_safethrow(UIError_InvalidGrid,
columns=row_len; Autoarr_freeWithoutMembers(content_names, true);
else if(row_len != columns) Autoarr_freeWithoutMembers(column_widths, true);
UI_safethrow_msg("wrong grid row size",;); Autoarr_freeWithoutMembers(row_heights, true);
);
Autoarr_foreach(row, _elem_d, Autoarr_foreach(row, _elem_d,
if(!UniCheckTypePtr(_elem_d, char)){ if(!UniCheckTypePtr(_elem_d, char))
UI_safethrow_msg( UI_safethrow_msg(
cptr_concat("expected char*, but has got type id '", cptr_concat("expected type char*, but has got type id '",
toString_i64(_elem_d.typeId),"'"), toString_i64(_elem_d.typeId),"'"),
Autoarr_freeWithoutMembers(content_names, true)); Autoarr_freeWithoutMembers(content_names, true);
} Autoarr_freeWithoutMembers(column_widths, true);
Autoarr_freeWithoutMembers(row_heights, true);
);
char* elem_name=_elem_d.VoidPtr; char* elem_name=_elem_d.VoidPtr;
Autoarr_add(content_names, elem_name); Autoarr_add(content_names, elem_name);
) )
@ -103,7 +150,10 @@ UI_Maybe Grid_deserialize(Dtsod* dtsod){
Autoarr_freeWithoutMembers(content_names, true); Autoarr_freeWithoutMembers(content_names, true);
gr.columns=columns; gr.columns=columns;
gr.rows=rows; gr.rows=rows;
gr.is_bound=false; gr.column_widths=Autoarr_toArray(column_widths);
Autoarr_freeWithoutMembers(column_widths, true);
gr.row_heights=Autoarr_toArray(row_heights);
Autoarr_freeWithoutMembers(row_heights, true);
gr.content=NULL; gr.content=NULL;
Grid* ptr=malloc(sizeof(*ptr)); Grid* ptr=malloc(sizeof(*ptr));
@ -111,18 +161,56 @@ UI_Maybe Grid_deserialize(Dtsod* dtsod){
return SUCCESS(UniHeapPtr(Grid, ptr)); return SUCCESS(UniHeapPtr(Grid, ptr));
} }
char* Grid_toString(void* _gr, kp_fmt fmt){
Grid* gr=_gr;
StringBuilder* sb=StringBuilder_create();
adds("Grid {")
UIElement_appendToStringBuilder(sb, &gr->base);
adduf(gr,rows)
adduf(gr,columns)
adds(" row_heights: [ ")
for(u16 r=0; r < gr->rows; r++){
addi(gr->row_heights[r]) addc(' ')
}
adds("]"
" column_widths: [ ")
for(u16 c=0; c < gr->rows; c++){
addi(gr->row_heights[c]) addc(' ')
}
u32 count=gr->rows*gr->columns;
adds("]"
" content: [")
if(gr->content)
for(u32 i=0; i<count; i++){
UIElement_Ptr child=gr->content[i];
addc(' ')adds(child->name)addc(':')adds(child->type->kt->name)
}
else if(gr->content_names)
for(u32 i=0; i<count; i++){
char* child_name=gr->content_names[i];
addc(' ')adds(child_name)
}
adds(" ]"
" }")
return StringBuilder_build(sb).ptr;
}
uit_define(Grid, Grid_freeMembers, NULL, Grid_draw, Grid_deserialize); uit_define(Grid, Grid_freeMembers, Grid_toString, Grid_draw, Grid_deserialize, Grid_onBuildUIContext);
Grid* Grid_create(char* name, u16 columns, u16 rows, UIElement_Ptr* content){ Grid* Grid_create(char* name,
u16 columns, u16 rows,
ScalingSize* column_widths, ScalingSize* row_heights,
UIElement_Ptr* content)
{
Grid* grid=malloc(sizeof(Grid)); Grid* grid=malloc(sizeof(Grid));
*grid=(Grid){ *grid=(Grid){
.base=_UIElement_initBaseDefault(name, &UITDescriptor_Grid), .base=_UIElement_initBaseDefault(name, &UITDescriptor_Grid),
.columns=columns, .columns=columns,
.rows=rows, .rows=rows,
.column_widths=column_widths,
.row_heights=row_heights,
.content=content, .content=content,
.content_names=NULL, .content_names=NULL
.is_bound=true
}; };
return grid; return grid;
} }

View File

@ -31,8 +31,17 @@ UI_Maybe TextBlock_deserialize(Dtsod* dtsod){
return SUCCESS(UniHeapPtr(TextBlock, ptr)); return SUCCESS(UniHeapPtr(TextBlock, ptr));
} }
char* TextBlock_toString(void* _tb, kp_fmt fmt){
TextBlock* tb=_tb;
StringBuilder* sb=StringBuilder_create();
adds("TextBlock {")
UIElement_appendToStringBuilder(sb, &tb->base);
addstrf(tb,text)
adds(" }")
return StringBuilder_build(sb).ptr;
}
uit_define(TextBlock, TextBlock_freeMembers, NULL,TextBlock_draw, TextBlock_deserialize); uit_define(TextBlock, TextBlock_freeMembers, TextBlock_toString, TextBlock_draw, TextBlock_deserialize, NULL);
TextBlock* TextBlock_create(char* name, string text){ TextBlock* TextBlock_create(char* name, string text){
TextBlock* textBlock=malloc(sizeof(TextBlock)); TextBlock* textBlock=malloc(sizeof(TextBlock));

View File

@ -1,5 +1,26 @@
#include "tui_internal.h" #include "tui_internal.h"
void UIElement_appendToStringBuilder(StringBuilder* sb, UIElement_Ptr u){
char *s0;
addsf(u,name) addc(' ')
adds((s0=UITDescriptor_toString(u->type)));
adduf(u,min_width)
adduf(u,min_height)
addif(u,width)
addif(u,height)
adds(" color:") adds(kp_bgColor_toString(u->color))
addc('|') adds(kp_fgColor_toString(u->color))
adds(" border { t:") addu(u->border.top)
adds(" b:") addu(u->border.bottom)
adds(" l:") addu(u->border.left)
adds(" r:") addu(u->border.right)
adds(" color:") adds(kp_bgColor_toString(u->color))
addc('|') adds(kp_fgColor_toString(u->color))
adds(" }")
free(s0);
}
kt_define(UIElement, NULL, NULL); kt_define(UIElement, NULL, NULL);
Autoarr_define(UIElement_Ptr, true); Autoarr_define(UIElement_Ptr, true);
Array_define(UIElement); Array_define(UIElement);
@ -8,11 +29,11 @@ Array_define(UIElement);
inline UIElement _UIElement_initBaseDefault(char* name, UITDescriptor* uit){ inline UIElement _UIElement_initBaseDefault(char* name, UITDescriptor* uit){
return (UIElement){ return (UIElement){
.name=name, .name=name,
.ui_type=uit, .type=uit,
.min_width=2, .min_width=2,
.min_height=2, .min_height=2,
.width_scaling=UIElement_no_scaling, .width=size_enable_scaling(1),
.height_scaling=UIElement_no_scaling, .height=size_enable_scaling(1),
.color=kp_bgBlack|kp_fgGray, .color=kp_bgBlack|kp_fgGray,
.border={ .border={
.left=UIBorder_Thin, .right=UIBorder_Thin, .left=UIBorder_Thin, .right=UIBorder_Thin,
@ -23,8 +44,8 @@ inline UIElement _UIElement_initBaseDefault(char* name, UITDescriptor* uit){
} }
void UIElement_destroy(UIElement_Ptr self){ void UIElement_destroy(UIElement_Ptr self){
if(self->ui_type->type->freeMembers) if(self->type->kt->freeMembers)
self->ui_type->type->freeMembers(self); self->type->kt->freeMembers(self);
free(self); free(self);
} }
@ -50,16 +71,16 @@ UI_Maybe UIElement_deserializeBase(Dtsod* dtsod, UIElement* base){
char* type_name; char* type_name;
Dtsod_tryGet_cptr(dtsod, "type", type_name, true); Dtsod_tryGet_cptr(dtsod, "type", type_name, true);
UITDescriptor* ui_type=UITDescriptor_getByName(type_name); UITDescriptor* type=UITDescriptor_getByName(type_name);
if(ui_type==NULL) if(type==NULL)
UI_safethrow_msg(cptr_concat("invalid type '", type_name, "'"), ;); UI_safethrow_msg(cptr_concat("invalid type '", type_name, "'"), ;);
*base=_UIElement_initBaseDefault(name, ui_type); *base=_UIElement_initBaseDefault(cptr_copy(name), type);
Dtsod_tryGet_i64(dtsod, "min_width", base->min_width, false); Dtsod_tryGet_i64(dtsod, "min_width", base->min_width, false);
Dtsod_tryGet_i64(dtsod, "min_height", base->min_height, false); Dtsod_tryGet_i64(dtsod, "min_height", base->min_height, false);
Dtsod_tryGet_i64(dtsod, "width_scaling", base->width_scaling, false); Dtsod_tryGet_ScalingSize(dtsod, "width", base->width, false);
Dtsod_tryGet_i64(dtsod, "height_scaling", base->height_scaling, false); Dtsod_tryGet_ScalingSize(dtsod, "height", base->height, false);
char *bg_color_name, *fg_color_name; char *bg_color_name, *fg_color_name;
Dtsod_tryGet_cptr(dtsod, "bg_color", bg_color_name, false, Dtsod_tryGet_cptr(dtsod, "bg_color", bg_color_name, false,
set_color(bg_color_name, base->color); set_color(bg_color_name, base->color);

View File

@ -13,7 +13,9 @@ PACKED_ENUM(UIError,
UIError_InvalidHeight, UIError_InvalidWidth, UIError_InvalidHeight, UIError_InvalidWidth,
UIError_InvalidX, UIError_InvalidY, UIError_InvalidX, UIError_InvalidY,
UIError_PrintError, UIError_PrintError,
UIError_InvalidVersion UIError_InvalidVersion,
UIError_InvalidGrid,
UIError_InvalidFormat
) )
// this macros can be changed later to improve debugging // this macros can be changed later to improve debugging

View File

@ -3,7 +3,53 @@
kt_define(DrawingArea, NULL, NULL); kt_define(DrawingArea, NULL, NULL);
kt_define(UIBorder, NULL, NULL); kt_define(UIBorder, NULL, NULL);
kt_define(UITDescriptor, NULL, NULL);
UI_Maybe ScalingSize_fromUnitype(Unitype UNI, ScalingSize* SZ_VAR){
if(UniCheckType(UNI, i64)){
*SZ_VAR=UNI.Int64;
} else if(UniCheckTypePtr(UNI, char)){
char* _sz_str=UNI.VoidPtr;
u32 len=cptr_length(_sz_str);
bool has_asterisk=_sz_str[len-1]=='0';
if(has_asterisk)
_sz_str[len-1]=0;
int _sz=0;
if(sscanf(_sz_str, "%i", &_sz)!=1)
UI_safethrow(UIError_InvalidFormat, ;);
if(has_asterisk)
_sz=size_enable_scaling(_sz);
*SZ_VAR=_sz;
} else UI_safethrow_msg(
cptr_concat("expected type i64 or char*, but has got type id '",
toString_i64(UNI.typeId), "'"),;);
return MaybeNull;
}
//////////////////////////////////////
// TUI type system //
//////////////////////////////////////
char* UITDescriptor_toString(UITDescriptor* d){
const char* n="NULL";
char *s0=ktDescriptor_toString(d->kt);
char *s1= d->draw ? toString_hex(d->draw, sizeof(void*), 0,1,0) : n;
char *s2= d->deserialize ? toString_hex(d->deserialize, sizeof(void*), 0,1,0) : n;
char *s3= d->onBuild ? toString_hex(d->onBuild, sizeof(void*), 0,1,0) : n;
char* rez=cptr_concat("UITDescriptor { ",
s0,
" draw:",s1,
" deserialize:",s2,
" onBuild:",s3,
" }");
if(s0!=n) free(s0);
if(s1!=n) free(s1);
if(s2!=n) free(s2);
if(s3!=n) free(s3);
return rez;
}
char* _UITDescriptor_toString(void* _d, u32 fmt){ return UITDescriptor_toString(_d); }
kt_define(UITDescriptor, NULL, _UITDescriptor_toString);
Hashtable* _uit_hashtable=NULL; Hashtable* _uit_hashtable=NULL;
u32 __kt_id_first=-1; u32 __kt_id_first=-1;
@ -29,7 +75,7 @@ void kt_freeTUI(){
} }
void __uit_register(ktDescriptor* kt, UITDescriptor* uit){ void __uit_register(ktDescriptor* kt, UITDescriptor* uit){
uit->type=kt; uit->kt=kt;
Hashtable_add(_uit_hashtable, cptr_copy(kt->name), UniStackPtr(UITDescriptor, uit)); Hashtable_add(_uit_hashtable, cptr_copy(kt->name), UniStackPtr(UITDescriptor, uit));
} }

View File

@ -20,11 +20,12 @@ typedef UIElement* UIElement_Ptr;
typedef struct Renderer Renderer; typedef struct Renderer Renderer;
typedef struct DrawingArea DrawingArea; typedef struct DrawingArea DrawingArea;
///@return Maybe<UIElement_Ptr> ///@return Maybe<void>
typedef UI_THROWING_FUNC_DECL( (*UIElement_draw_t)(Renderer* renderer, UIElement_Ptr self, const DrawingArea area) ); typedef UI_THROWING_FUNC_DECL( (*UIElement_draw_t)(Renderer* renderer, UIElement_Ptr self, const DrawingArea area) );
///@return Maybe<UIElement_Ptr> ///@return Maybe<UIElement_Ptr>
typedef UI_THROWING_FUNC_DECL( (*UIElement_deserialize_t)(Dtsod* dtsod) ); typedef UI_THROWING_FUNC_DECL( (*UIElement_deserialize_t)(Dtsod* dtsod) );
///@return Maybe<void>
typedef UI_THROWING_FUNC_DECL( (*UIElement_onBuildUIContext_t)(UIElement* self, UIContext* context) );
////////////////////////////////////// //////////////////////////////////////
@ -32,17 +33,19 @@ typedef UI_THROWING_FUNC_DECL( (*UIElement_deserialize_t)(Dtsod* dtsod) );
////////////////////////////////////// //////////////////////////////////////
STRUCT(UITDescriptor, STRUCT(UITDescriptor,
ktDescriptor* type; ktDescriptor* kt;
UIElement_draw_t draw; UIElement_draw_t draw;
UIElement_deserialize_t deserialize; UIElement_deserialize_t deserialize;
UIElement_onBuildUIContext_t onBuild;
) )
#define uit_declare(TYPE) extern UITDescriptor UITDescriptor_##TYPE; #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) \ #define uit_define(TYPE, FREE_F, TOSTRING_F, DRAW_F, DESERIALIZE_F, ON_BUILD_F) kt_define(TYPE, FREE_F, TOSTRING_F) \
UITDescriptor UITDescriptor_##TYPE={ \ UITDescriptor UITDescriptor_##TYPE={ \
.draw=DRAW_F, \ .draw=DRAW_F, \
.deserialize=DESERIALIZE_F \ .deserialize=DESERIALIZE_F, \
.onBuild=ON_BUILD_F \
}; };
/// call this between kt_beginInit() and kt_endInit() /// call this between kt_beginInit() and kt_endInit()
@ -74,6 +77,14 @@ PACKED_ENUM(UIBorderThickness,
// Small structs // // Small structs //
////////////////////////////////////// //////////////////////////////////////
typedef i16 ScalingSize;
#define is_size_scaling(SZ) (SZ<0)
#define size_enable_scaling(SZ) (SZ < 0 ? SZ : (-1*SZ))
#define size_disable_scaling(SZ) (SZ >= 0 ? SZ : (-1*SZ))
///@return Maybe<void>
UI_THROWING_FUNC_DECL( ScalingSize_fromUnitype(Unitype UNI, ScalingSize* SZ_VAR) );
STRUCT(DrawingArea, STRUCT(DrawingArea,
/* right-top corner */ /* right-top corner */
u16 x; u16 y; u16 x; u16 y;
@ -123,25 +134,23 @@ UI_THROWING_FUNC_DECL(Renderer_drawBorder(Renderer* renderer, UIBorder border, c
////////////////////////////////////// //////////////////////////////////////
STRUCT(UIElement, STRUCT(UIElement,
UITDescriptor* ui_type; UITDescriptor* type;
char* name; char* name;
u16 min_width; u16 min_width;
u16 min_height; u16 min_height;
u16 width_scaling; ScalingSize width;
u16 height_scaling; ScalingSize height;
termcolor color; termcolor color;
UIBorder border; UIBorder border;
) )
Autoarr_declare(UIElement_Ptr) Autoarr_declare(UIElement_Ptr)
Array_declare(UIElement) Array_declare(UIElement)
#define UIElement_no_scaling (u16)0
/// proper way to free UIElement and all its members /// proper way to free UIElement and all its members
void UIElement_destroy(UIElement_Ptr self); void UIElement_destroy(UIElement_Ptr self);
#define UIElement_draw(RENDERER, UIE_PTR, PLACE_RECT) \ #define UIElement_draw(RENDERER, UIE_PTR, PLACE_RECT) \
(UIE_PTR)->ui_type->draw(RENDERER, UIE_PTR, PLACE_RECT) (UIE_PTR)->type->draw(RENDERER, UIE_PTR, PLACE_RECT)
////////////////////////////////////// //////////////////////////////////////
@ -154,25 +163,24 @@ STRUCT(Grid,
UIElement base; UIElement base;
u16 columns; u16 columns;
u16 rows; u16 rows;
bool is_bound; ScalingSize* row_heights;
ScalingSize* column_widths;
char** content_names; char** content_names;
UIElement_Ptr* content; /* UIElement[rows][columns] */ UIElement_Ptr* content; /* UIElement[rows][columns] */
) )
uit_declare(Grid); uit_declare(Grid);
Grid* Grid_create(char* name, u16 columns, u16 rows, UIElement_Ptr* content); Grid* Grid_create(char* name, u16 columns, u16 rows, ScalingSize* column_widths, ScalingSize* row_heights, UIElement_Ptr* content);
///@return Maybe<UIElement*> ///@return Maybe<UIElement*>
UI_THROWING_FUNC_DECL( Grid_get(Grid* grid, u16 column, u16 row) ); UI_THROWING_FUNC_DECL( Grid_get(Grid* grid, u16 column, u16 row) );
///@return maybe<void> ///@return maybe<void>
UI_THROWING_FUNC_DECL( Grid_set(Grid* grid, u16 column, u16 row, UIElement_Ptr value)); UI_THROWING_FUNC_DECL( Grid_set(Grid* grid, u16 column, u16 row, UIElement_Ptr value));
///@return Maybe<char*> ///@return Maybe<char*>
UI_THROWING_FUNC_DECL( _Grid_getName(Grid* grid, u16 column, u16 row) ); UI_THROWING_FUNC_DECL( _Grid_getName(Grid* grid, u16 column, u16 row) );
///@return maybe<void>
UI_THROWING_FUNC_DECL( _Grid_bindContent(Grid* grid, UIContext* context) );
#define Grid_foreach(GRID, ELEM_VAR_NAME, CODE...) { \ #define Grid_foreach(GRID, ELEM_VAR_NAME, CODE...) { \
if(!GRID->is_bound) \ if(!GRID->content) \
UI_safethrow_msg(cptr_concat("grid '", GRID->base.ui_type->type->name, \ UI_safethrow_msg(cptr_concat("grid '", GRID->base.type->kt->name, \
"' content has not been bound"),;); \ "' content has not been bound"),;); \
for(u16 _g_r = 0; _g_r < GRID->rows; _g_r++){ \ for(u16 _g_r = 0; _g_r < GRID->rows; _g_r++){ \
for(u16 _g_c = 0; _g_c < GRID->columns; _g_c++){ \ for(u16 _g_c = 0; _g_c < GRID->columns; _g_c++){ \
@ -184,8 +192,8 @@ UI_THROWING_FUNC_DECL( _Grid_bindContent(Grid* grid, UIContext* context) );
} }
#define Grid_foreachName(GRID, ELEM_VAR_NAME, CODE...) { \ #define Grid_foreachName(GRID, ELEM_VAR_NAME, CODE...) { \
if(GRID->is_bound) \ if(!GRID->content_names) \
UI_safethrow_msg(cptr_concat("grid '", GRID->base.ui_type->type->name, \ UI_safethrow_msg(cptr_concat("grid '", GRID->base.type->kt->name, \
"' content has been already bound"),;); \ "' content has been already bound"),;); \
for(u16 _g_r = 0; _g_r < GRID->rows; _g_r++){ \ for(u16 _g_r = 0; _g_r < GRID->rows; _g_r++){ \
for(u16 _g_c = 0; _g_c < GRID->columns; _g_c++){ \ for(u16 _g_c = 0; _g_c < GRID->columns; _g_c++){ \

View File

@ -5,6 +5,7 @@ extern "C" {
#endif #endif
#include "tui.h" #include "tui.h"
#include "../../kerep/src/String/StringBuilder.h"
extern UIElement _UIElement_initBaseDefault(char* name, UITDescriptor* type); extern UIElement _UIElement_initBaseDefault(char* name, UITDescriptor* type);
@ -45,6 +46,23 @@ int UIBorderThickness_getByName(char* name);
var=(UIBorderThickness)th; \ var=(UIBorderThickness)th; \
} }
#define addstr(V) StringBuilder_append_string(sb, V);
#define addstrf(O,F) adds(" "#F":'") addstr(O->F) addc('\'')
#define adds(V) StringBuilder_append_cptr(sb, V);
#define addsf(O,F) adds(" "#F":'") adds(O->F) addc('\'')
#define addc(V) StringBuilder_append_char(sb, V);
#define addcf(O,F) adds(" "#F":") addc(O->F)
#define addi(V) StringBuilder_append_i64(sb, V);
#define addif(O,F) adds(" "#F":") addi(O->F)
#define addu(V) StringBuilder_append_u64(sb, V);
#define adduf(O,F) adds(" "#F":") addu(O->F)
#define addf(V) StringBuilder_append_f64(sb, V);
#define addff(O,F) adds(" "#F":") addf(O->F)
char* UITDescriptor_toString(UITDescriptor* d);
void UIElement_appendToStringBuilder(StringBuilder* sb, UIElement_Ptr u);
#if __cplusplus #if __cplusplus
} }
#endif #endif

View File

@ -43,6 +43,20 @@ UI_Maybe test_example_ui_build() {
UIDtsodParser_destroy(p); UIDtsodParser_destroy(p);
UIContext_get(ui_context, example, textblock, TextBlock, UIContext_destroy(ui_context)); UIContext_get(ui_context, example, textblock, TextBlock, UIContext_destroy(ui_context));
example_textblock->text=string_fromCptr("text replaced"); example_textblock->text=string_fromCptr("text replaced");
u32 n=0;
Hashtable_foreach(ui_context->ui_elements, el_pair,
UIElement* el=el_pair.value.VoidPtr;
toString_t elToString=el->type->kt->toString;
if(elToString){
char* str_tmp=elToString(el,0);
char* str=cptr_replace(str_tmp, " ", "\n");
kprintf("[%u] %s\n", n, str);
free(str_tmp);
free(str);
}
else kprintf("[%u] %s\n", n, el->name);
n++;
);
UIContext_destroy(ui_context); UIContext_destroy(ui_context);
return MaybeNull; return MaybeNull;
} }
@ -97,7 +111,9 @@ i32 main(const i32 argc, const char* const* argv){
// TODO signal( SIGWINCH, redraw ); // TODO signal( SIGWINCH, redraw );
for(u32 n=0; n<1; n++){
tryLast(test_example_ui_build(), _6981751, on_exit()); tryLast(test_example_ui_build(), _6981751, on_exit());
}
on_exit(); on_exit();
return 0; return 0;

View File

@ -6,8 +6,8 @@ $ui: {
type: "TextBlock", type: "TextBlock",
min_width: 4, min_width: 4,
max_width: 4, max_width: 4,
width_scaling: 0, width: 20,
height_scaling: 0, height: "3",
bg_color: "black", bg_color: "black",
fg_color: "white", fg_color: "white",
border: { border: {
@ -24,6 +24,11 @@ $ui: {
$ui: { $ui: {
name: "Grid", name: "Grid",
type: "Grid", type: "Grid",
row_heights: [
"1*",
-1,
],
column_widths: [ "-8*" ],
content: [ content: [
# column # column
[ "example_textblock" ], # row [ "example_textblock" ], # row

View File

@ -1,12 +1,17 @@
parser_version: 1; parser_version: 1;
namespace: "main"; namespace: "main";
$ui: { # $ui: {
name: "main_grid", # name: "main_grid",
type: "Grid", # type: "Grid",
content: [ # row_heights: [
# column # "1*",
# [ "namespace.element0" ], # row # # -1,
# [ "namespace.element1" ], # row # # ],
]; # # column_widths: [ "-8*" ],
}; # content: [
# # column
# # [ "namespace.element0" ], # row
# # [ "namespace.element1" ], # row
# ];
# };