Compare commits
10 Commits
933b515fad
...
d7f8e7303d
| Author | SHA1 | Date | |
|---|---|---|---|
| d7f8e7303d | |||
| b19c020235 | |||
| 729888b9d9 | |||
| e48f7cd6b5 | |||
| 4e2376f251 | |||
| 03f9f889cc | |||
| abc14336d4 | |||
| bb66d841f3 | |||
| 9febbe1de0 | |||
| 768c55af4a |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
# build results
|
# build results
|
||||||
bin/
|
bin/
|
||||||
obj/
|
obj/
|
||||||
|
src/generated/
|
||||||
*.log
|
*.log
|
||||||
*.tmp
|
*.tmp
|
||||||
|
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -10,3 +10,6 @@
|
|||||||
path = utf8proc
|
path = utf8proc
|
||||||
url = https://github.com/Timerix22/utf8proc.git
|
url = https://github.com/Timerix22/utf8proc.git
|
||||||
branch = my_branch
|
branch = my_branch
|
||||||
|
[submodule "resource_embedder"]
|
||||||
|
path = resource_embedder
|
||||||
|
url = https://github.com/Timerix22/resource_embedder.git
|
||||||
|
|||||||
15
Makefile
15
Makefile
@ -12,12 +12,12 @@ build_exec: profile
|
|||||||
build_exec_dbg:
|
build_exec_dbg:
|
||||||
@cbuild/call_task.sh build_exec_dbg 2>&1 | tee make_raw.log
|
@cbuild/call_task.sh build_exec_dbg 2>&1 | tee make_raw.log
|
||||||
|
|
||||||
# recompile kerep.a in the next build task
|
# recompile libkerep.a in the next build task
|
||||||
rebuild_kerep:
|
rebuild_kerep:
|
||||||
@tasks/rebuild_lib.sh kerep
|
@cbuild/rebuild_dep.sh libkerep.a 2>&1 | tee make_raw.log
|
||||||
# recompile utf8proc.a in the next build task
|
# recompile libutf8proc.a in the next build task
|
||||||
rebuild_utf8proc:
|
rebuild_utf8proc:
|
||||||
@tasks/rebuild_lib.sh utf8proc
|
@cbuild/rebuild_dep.sh libutf8proc.a 2>&1 | tee make_raw.log
|
||||||
|
|
||||||
rebuild_all: rebuild_kerep rebuild_utf8proc
|
rebuild_all: rebuild_kerep rebuild_utf8proc
|
||||||
|
|
||||||
@ -46,6 +46,13 @@ profile:
|
|||||||
gprof:
|
gprof:
|
||||||
@cbuild/call_task.sh gprof 2>&1 | tee make_raw.log
|
@cbuild/call_task.sh gprof 2>&1 | tee make_raw.log
|
||||||
|
|
||||||
|
# compiles program and runs it with callgrind (part of valgrind)
|
||||||
|
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
||||||
|
# requires graphviz (https://www.graphviz.org/download/source/)
|
||||||
|
# P.S. detailed rezults can be viewed in KCacheGrind
|
||||||
|
callgrind:
|
||||||
|
@cbuild/call_task.sh callgrind 2>&1 | tee make_raw.log
|
||||||
|
|
||||||
# compiles executable with sanitizers and executes it to find errors and warnings
|
# compiles executable with sanitizers and executes it to find errors and warnings
|
||||||
sanitize:
|
sanitize:
|
||||||
@cbuild/call_task.sh sanitize 2>&1 | tee make_raw.log
|
@cbuild/call_task.sh sanitize 2>&1 | tee make_raw.log
|
||||||
|
|||||||
@ -1,2 +1,9 @@
|
|||||||
# SCoLTE - Simple Command-Line Text Editor
|
# SCoLTE - Simple Command-Line Text Editor
|
||||||
I just wanted to edit text files from terminal, not to memorize a ton of weird shortcuts for nano or vim. So here it is - easy to use text editor.
|
I just wanted to edit text files from terminal, not to memorize a ton of weird shortcuts for nano or vim. So here it is - easy to use text editor.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
Included as git submodules:
|
||||||
|
+ [cbuild](https://github.com/Timerix22/cbuild) - my build system written in shell scripts
|
||||||
|
+ [kerep](https://github.com/Timerix22/kerep) - library with code i use in all my projects
|
||||||
|
+ [utf8proc](https://github.com/Timerix22/utf8proc/tree/my_branch) - unicode processing library
|
||||||
|
+ [resource_embedder](https://github.com/Timerix22/resource_embedder) - program that transforms files to array definitions in C
|
||||||
|
|||||||
2
cbuild
2
cbuild
@ -1 +1 @@
|
|||||||
Subproject commit e8e42424d329ef1e75fb827ddf85d55b4cd89169
|
Subproject commit ef6a3f82c429ec232e1b910eecbdece76de933b3
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
CBUILD_VERSION=6
|
CBUILD_VERSION=7
|
||||||
CONFIG_VERSION=3
|
CONFIG_VERSION=4
|
||||||
|
|
||||||
PROJECT="scolte"
|
PROJECT="scolte"
|
||||||
CMP_C="gcc"
|
CMP_C="gcc"
|
||||||
@ -14,6 +14,17 @@ SRC_CPP="$( find src -name '*.cpp')"
|
|||||||
#TESTS_C="$( find tests -name '*.c')"
|
#TESTS_C="$( find tests -name '*.c')"
|
||||||
#TESTS_CPP="$(find tests -name '*.cpp')"
|
#TESTS_CPP="$(find tests -name '*.cpp')"
|
||||||
|
|
||||||
|
# dir with dependeicy dirs
|
||||||
|
DEPS_BASEDIR="."
|
||||||
|
# EXAMPLE: "dependency_dir='build_task out_dir lib_file'
|
||||||
|
# other_depndency_dir=..."
|
||||||
|
# Dependencies must be declared on separate lines
|
||||||
|
# Values can be override by resetting one of dependencies:
|
||||||
|
# DEPS="$DEPS
|
||||||
|
# dependency_dir='...'"
|
||||||
|
DEPS="kerep='build_static_lib bin libkerep.a'
|
||||||
|
utf8proc='libutf8proc.a . libutf8proc.a'"
|
||||||
|
|
||||||
# OBJDIR structure:
|
# OBJDIR structure:
|
||||||
# ├── objects/ - dir where compiled *.o files are stored. cleans every call of build task
|
# ├── objects/ - dir where compiled *.o files are stored. cleans every call of build task
|
||||||
# ├── profile/ - dir where gcc *.gcda profiling info files stored
|
# ├── profile/ - dir where gcc *.gcda profiling info files stored
|
||||||
@ -41,12 +52,12 @@ case "$TASK" in
|
|||||||
# -flto applies more optimizations across object files
|
# -flto applies more optimizations across object files
|
||||||
# -flto=auto is needed to multithreaded copilation
|
# -flto=auto is needed to multithreaded copilation
|
||||||
# -fuse-linker-plugin is required to use static libs with lto, it strips away all
|
# -fuse-linker-plugin is required to use static libs with lto, it strips away all
|
||||||
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects"
|
# -fdata-sections -ffunction-sections -Wl,--gc-sections removes unused code
|
||||||
|
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects -fdata-sections -ffunction-sections -Wl,--gc-sections"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS"
|
LINKER_ARGS="$CPP_ARGS"
|
||||||
PRE_TASK_SCRIPT=tasks/pre_build.sh
|
PRE_TASK_SCRIPT=tasks/pre_build.sh
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
DEPS_BUILD_TASK=build_static_lib
|
|
||||||
;;
|
;;
|
||||||
# creates executable with debug info and no optimizations
|
# creates executable with debug info and no optimizations
|
||||||
build_exec_dbg)
|
build_exec_dbg)
|
||||||
@ -55,7 +66,8 @@ case "$TASK" in
|
|||||||
LINKER_ARGS="$CPP_ARGS"
|
LINKER_ARGS="$CPP_ARGS"
|
||||||
PRE_TASK_SCRIPT=tasks/pre_build.sh
|
PRE_TASK_SCRIPT=tasks/pre_build.sh
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
DEPS_BUILD_TASK=build_static_lib_dbg
|
DEPS="$DEPS
|
||||||
|
kerep='build_static_lib_dbg bin libkerep.a'"
|
||||||
;;
|
;;
|
||||||
# executes $EXEC_FILE
|
# executes $EXEC_FILE
|
||||||
exec)
|
exec)
|
||||||
@ -63,7 +75,7 @@ case "$TASK" in
|
|||||||
;;
|
;;
|
||||||
# executes $EXEC_FILE with valgrind memory checker
|
# executes $EXEC_FILE with valgrind memory checker
|
||||||
valgrind)
|
valgrind)
|
||||||
VALGRIND_ARGS="-s --log-file=valgrind.log --read-var-info=yes --track-origins=yes --fullpath-after=$PROJECT/ --leak-check=full --show-leak-kinds=all"
|
VALGRIND_ARGS="-s --read-var-info=yes --track-origins=yes --fullpath-after=$PROJECT/ --leak-check=full --show-leak-kinds=all"
|
||||||
TASK_SCRIPT=cbuild/default_tasks/valgrind.sh
|
TASK_SCRIPT=cbuild/default_tasks/valgrind.sh
|
||||||
;;
|
;;
|
||||||
# generates profiling info
|
# generates profiling info
|
||||||
@ -95,6 +107,20 @@ case "$TASK" in
|
|||||||
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
POST_TASK_SCRIPT=cbuild/default_tasks/gprof.sh
|
POST_TASK_SCRIPT=cbuild/default_tasks/gprof.sh
|
||||||
;;
|
;;
|
||||||
|
# compiles program and runs it with callgrind (part of valgrind)
|
||||||
|
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
||||||
|
# requires graphviz (https://www.graphviz.org/download/source/)
|
||||||
|
# P.S. detailed rezults can be viewed in KCacheGrind
|
||||||
|
callgrind)
|
||||||
|
OUTDIR="$OUTDIR/callgrind"
|
||||||
|
# -pg adds code to executable, that generates file containing function call info (gmon.out)
|
||||||
|
C_ARGS="-O2 -flto=auto -fuse-linker-plugin"
|
||||||
|
CPP_ARGS="$C_ARGS"
|
||||||
|
LINKER_ARGS="$CPP_ARGS"
|
||||||
|
PRE_TASK_SCRIPT=tasks/pre_build.sh
|
||||||
|
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
||||||
|
POST_TASK_SCRIPT=cbuild/default_tasks/callgrind.sh
|
||||||
|
;;
|
||||||
# compiles executable with sanitizers and executes it to find errors and warnings
|
# compiles executable with sanitizers and executes it to find errors and warnings
|
||||||
sanitize)
|
sanitize)
|
||||||
OUTDIR="$OUTDIR/sanitize"
|
OUTDIR="$OUTDIR/sanitize"
|
||||||
@ -110,6 +136,9 @@ case "$TASK" in
|
|||||||
TASK_SCRIPT=cbuild/default_tasks/clean.sh
|
TASK_SCRIPT=cbuild/default_tasks/clean.sh
|
||||||
POST_TASK_SCRIPT=tasks/clean_additions.sh
|
POST_TASK_SCRIPT=tasks/clean_additions.sh
|
||||||
;;
|
;;
|
||||||
|
# nothing to do
|
||||||
|
no_task)
|
||||||
|
;;
|
||||||
# unknown task
|
# unknown task
|
||||||
*)
|
*)
|
||||||
error "task <$TASK> not found"
|
error "task <$TASK> not found"
|
||||||
|
|||||||
2
kerep
2
kerep
@ -1 +1 @@
|
|||||||
Subproject commit 26b69f9b7bb7a816b8f048557efe0641428b9e80
|
Subproject commit aba67710c70c779fcf04af2bd01fb348ce75135d
|
||||||
1
resource_embedder
Submodule
1
resource_embedder
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 1708415900b0d5caed72c5e0aab3c5039517ee41
|
||||||
@ -1,31 +0,0 @@
|
|||||||
#include "tui_internal.h"
|
|
||||||
|
|
||||||
void Canvas_freeMembers(void* _self){
|
|
||||||
Canvas* self=(Canvas*)_self;
|
|
||||||
Autoarr_foreach(self->children, ch,
|
|
||||||
UIElement_destroy((UIElement*)ch));
|
|
||||||
Autoarr_freeWithoutMembers(self->children, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
UI_Maybe Canvas_draw(Renderer* renderer, UIElement* _self, const DrawingArea area){
|
|
||||||
Canvas* self=(Canvas*)_self;
|
|
||||||
Autoarr_foreach(self->children, ch, ({
|
|
||||||
if(ch==NULL)
|
|
||||||
UI_safethrow(UIError_NullPtr,;);
|
|
||||||
UI_try(UIElement_draw(renderer, (UIElement*)ch, area),_,;);
|
|
||||||
}));
|
|
||||||
return MaybeNull;
|
|
||||||
}
|
|
||||||
|
|
||||||
kt_define(Canvas, Canvas_freeMembers, NULL);
|
|
||||||
|
|
||||||
Canvas* Canvas_create(){
|
|
||||||
Canvas* canvas=malloc(sizeof(Canvas));
|
|
||||||
canvas->base=__UIElement_createDefault(ktid_name(Canvas), Canvas_draw);
|
|
||||||
canvas->children=Autoarr_create(Pointer, 32, 64);
|
|
||||||
return canvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Canvas_addChild(Canvas* self, UIElement* child){
|
|
||||||
Autoarr_add(self->children, child);
|
|
||||||
}
|
|
||||||
164
src/TUI/Dtsod/tui_dtsod.c
Normal file
164
src/TUI/Dtsod/tui_dtsod.c
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
#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<void>
|
||||||
|
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=file_name_placeholder,
|
||||||
|
.dtsod_text=text,
|
||||||
|
.dtsod=_m_dtsod.value.VoidPtr
|
||||||
|
};
|
||||||
|
Autoarr_add(parser->file_models, fm);
|
||||||
|
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){
|
||||||
|
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 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,
|
||||||
|
i32 file_parser_version;
|
||||||
|
Dtsod_tryGet_i64(fm.dtsod, "parser_version", file_parser_version, true);
|
||||||
|
if(file_parser_version!=UIDtsodParser_version){
|
||||||
|
UI_safethrow(UIError_InvalidVersion,;);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* file_namespace;
|
||||||
|
Dtsod_tryGet_cptr(fm.dtsod, "namespace", file_namespace, true);
|
||||||
|
Hashtable_foreach(fm.dtsod, dtsod_elem,
|
||||||
|
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_foreach(ui_ar, ui_el_dtsod,
|
||||||
|
UI_try(UIElement_deserialize(ui_el_dtsod.VoidPtr),_m_ui,;);
|
||||||
|
UIElement_Ptr new_el=_m_ui.value.VoidPtr;
|
||||||
|
// kprintf("[UIDtsodParser_constructUIContext] %s : %s\n", new_el->name, new_el->type->kt->name);
|
||||||
|
if(new_el->type->onBuild){
|
||||||
|
UI_try(new_el->type->onBuild(new_el, parser->context),_15151,;);
|
||||||
|
}
|
||||||
|
UI_try( UIContext_add(parser->context, file_namespace, new_el), _a76515, ;);
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
);
|
||||||
|
|
||||||
|
Autoarr_free(parser->file_models,true);
|
||||||
|
parser->file_models=Autoarr_create(UIDtsodFileModel, 64, 32);
|
||||||
|
parser->returned_context=true;
|
||||||
|
return SUCCESS(UniHeapPtr(UIContext, parser->context));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UI_Maybe UIContext_getAny(UIContext* context, char* name){
|
||||||
|
Unitype val;
|
||||||
|
// check name
|
||||||
|
if(!Hashtable_tryGet(context->ui_elements, name, &val))
|
||||||
|
UI_safethrow_msg(cptr_concat("can't get <", name, "> from context"), ;);
|
||||||
|
return SUCCESS(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe _UIContext_get(UIContext* context, char* name, ktid type_id){
|
||||||
|
UI_try(UIContext_getAny(context, name), _m_ui, ;);
|
||||||
|
UIElement* ptr=_m_ui.value.VoidPtr;
|
||||||
|
if(ptr->type->kt->id != type_id)
|
||||||
|
UI_safethrow_msg(cptr_concat(
|
||||||
|
"tried to get ",ktDescriptor_get(type_id)->name, " <",name,"> but it is of type ", ptr->type->kt->name
|
||||||
|
), ;);
|
||||||
|
return _m_ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe UIContext_add(UIContext* context, char* namespace, _UIElement_Ptr _new_el){
|
||||||
|
UIElement_Ptr new_el=_new_el;
|
||||||
|
Unitype u=UniPtr(new_el->type->kt->id, new_el, true);
|
||||||
|
char* namespace_and_name=cptr_concat(namespace, "_", new_el->name);
|
||||||
|
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"),
|
||||||
|
free(namespace_and_name));
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
127
src/TUI/Dtsod/tui_dtsod.h
Normal file
127
src/TUI/Dtsod/tui_dtsod.h
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#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 //
|
||||||
|
//////////////////////////////////////
|
||||||
|
#define UIDtsodParser_version 1
|
||||||
|
|
||||||
|
typedef struct UIDtsodParser UIDtsodParser;
|
||||||
|
|
||||||
|
UIDtsodParser* UIDtsodParser_create();
|
||||||
|
void UIDtsodParser_destroy(UIDtsodParser* p);
|
||||||
|
|
||||||
|
///@return UI_Maybe<void>
|
||||||
|
UI_THROWING_FUNC_DECL(UIDtsodParser_parseFile(UIDtsodParser* parser, char* file_name));
|
||||||
|
|
||||||
|
///@return UI_Maybe<void>
|
||||||
|
UI_THROWING_FUNC_DECL(UIDtsodParser_parseText(UIDtsodParser* parser, char* file_name_placeholder, char* text));
|
||||||
|
|
||||||
|
///@return UI_Maybe<UIContext*>
|
||||||
|
UI_THROWING_FUNC_DECL(UIDtsodParser_constructUIContext(UIDtsodParser* parser));
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// UIContext //
|
||||||
|
//////////////////////////////////////
|
||||||
|
STRUCT(UIContext,
|
||||||
|
Hashtable* ui_elements;
|
||||||
|
)
|
||||||
|
|
||||||
|
void UIContext_destroy(UIContext* u);
|
||||||
|
|
||||||
|
|
||||||
|
UI_Maybe UIContext_getAny(UIContext* context, char* name);
|
||||||
|
|
||||||
|
///@return UI_Maybe<UIElement*>
|
||||||
|
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_ptrName(TYPE)), \
|
||||||
|
_m_##NAMESPACE##_##NAME, \
|
||||||
|
FREECALLS_ON_ERROR); \
|
||||||
|
TYPE* NAMESPACE##_##NAME=_m_##NAMESPACE##_##NAME.value.VoidPtr;
|
||||||
|
|
||||||
|
///@return Maybe<void>
|
||||||
|
UI_THROWING_FUNC_DECL(UIContext_add(UIContext* context, char* _namespace, _UIElement_Ptr new_el));
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// Deserialization //
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
/// universal function for UIElement ancestors deserializing
|
||||||
|
/// @return Maybe<UIElement_Ptr>
|
||||||
|
UI_THROWING_FUNC_DECL( UIElement_deserialize(Dtsod* dtsod) );
|
||||||
|
|
||||||
|
|
||||||
|
#define _Dtsod_tryGet(dtsod, key, var_name, is_necessary, TYPE, TYPE_ID, UNI_FIELD, code...) { \
|
||||||
|
Unitype uni; \
|
||||||
|
if(Hashtable_tryGet(dtsod, key, &uni)) { \
|
||||||
|
if(!UniCheckTypeId(uni, TYPE_ID)) \
|
||||||
|
UI_safethrow_msg(cptr_concat("tried to get '",key,"' of type '",#TYPE, \
|
||||||
|
"', but got invalid type id '",toString_i64(uni.typeId),"'"), ;); \
|
||||||
|
var_name=uni.UNI_FIELD; \
|
||||||
|
{ code; } \
|
||||||
|
} \
|
||||||
|
else if(is_necessary) \
|
||||||
|
UI_safethrow_msg(cptr_concat("can't find key '", key, "'"), ;); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Dtsod_tryGet_i64(dtsod, key, var_name, is_necessary, code...) \
|
||||||
|
_Dtsod_tryGet(dtsod, key, var_name, is_necessary, i64, ktid_name(i64), Int64, code)
|
||||||
|
|
||||||
|
#define Dtsod_tryGet_u64(dtsod, key, var_name, is_necessary, code...) \
|
||||||
|
_Dtsod_tryGet(dtsod, key, var_name, is_necessary, u64, ktid_name(u64), UInt64, code)
|
||||||
|
|
||||||
|
#define Dtsod_tryGet_f64(dtsod, key, var_name, is_necessary, code...) \
|
||||||
|
_Dtsod_tryGet(dtsod, key, var_name, is_necessary, f64, ktid_name(f64), Float64, code)
|
||||||
|
|
||||||
|
#define Dtsod_tryGet_bool(dtsod, key, var_name, is_necessary, 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_necessary, code...) \
|
||||||
|
_Dtsod_tryGet(dtsod, key, var_name, is_necessary, type*, ktid_ptrName(type), VoidPtr, code)
|
||||||
|
|
||||||
|
#define Dtsod_tryGet_cptr(dtsod, key, var_name, is_necessary, code...) \
|
||||||
|
Dtsod_tryGet_ptr(dtsod, key, char, var_name, is_necessary, code)
|
||||||
|
|
||||||
|
#define Dtsod_tryGet_Hashtable(dtsod, key, var_name, is_necessary, code...) \
|
||||||
|
Dtsod_tryGet_ptr(dtsod, key, Hashtable, var_name, is_necessary, 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
|
||||||
|
}
|
||||||
|
#endif
|
||||||
17
src/TUI/Dtsod/tui_dtsod_internal.h
Normal file
17
src/TUI/Dtsod/tui_dtsod_internal.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#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;
|
||||||
|
)
|
||||||
217
src/TUI/Grid.c
Normal file
217
src/TUI/Grid.c
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
#include "tui_internal.h"
|
||||||
|
|
||||||
|
#define grid_validate() \
|
||||||
|
if(row >= grid->rows) UI_safethrow(UIError_InvalidY,;); \
|
||||||
|
if(column >= grid->columns) UI_safethrow(UIError_InvalidX,;);
|
||||||
|
|
||||||
|
UI_Maybe Grid_set(Grid* grid, u16 column, u16 row, UIElement_Ptr value){
|
||||||
|
grid_validate();
|
||||||
|
UIElement_Ptr* ptr_ptr = grid->content + grid->columns*row + column;
|
||||||
|
*ptr_ptr=value;
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe Grid_get(Grid* grid, u16 column, u16 row){
|
||||||
|
grid_validate();
|
||||||
|
UIElement_Ptr* ptr_ptr = grid->content + grid->columns*row + column;
|
||||||
|
return SUCCESS(UniHeapPtr(UIElement, *ptr_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe _Grid_getName(Grid* grid, u16 column, u16 row) {
|
||||||
|
grid_validate();
|
||||||
|
char** str_ptr = grid->content_names + grid->columns*row + column;
|
||||||
|
return SUCCESS(UniHeapPtr(char, *str_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe Grid_onBuildUIContext(UIElement* _grid, UIContext* context) {
|
||||||
|
Grid* grid=(Grid*)_grid;
|
||||||
|
Autoarr(UIElement_Ptr)* content=Autoarr_create(UIElement_Ptr, 64, 16);
|
||||||
|
Grid_foreachName(grid, name,
|
||||||
|
UI_try(UIContext_getAny(context, name), m_uie, Autoarr_freeWithoutMembers(content,true));
|
||||||
|
UIElement_Ptr uie=m_uie.value.VoidPtr;
|
||||||
|
Autoarr_add(content, uie);
|
||||||
|
);
|
||||||
|
free(grid->content_names);
|
||||||
|
grid->content_names=NULL;
|
||||||
|
grid->content=Autoarr_toArray(content);
|
||||||
|
Autoarr_freeWithoutMembers(content, true);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Grid_freeMembers(void* _self){
|
||||||
|
Grid* self=(Grid*)_self;
|
||||||
|
free(self->column_widths);
|
||||||
|
free(self->row_heights);
|
||||||
|
if(self->content_names){
|
||||||
|
for(u16 r = 0; r < self->rows; r++){
|
||||||
|
for(u16 c = 0; c < self->columns; c++){
|
||||||
|
tryLast(Grid_get(self, c, r), m_el,
|
||||||
|
free(self->content);
|
||||||
|
free(self->content_names));
|
||||||
|
UIElement_Ptr el=m_el.value.VoidPtr;
|
||||||
|
UIElement_destroy(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(self->content_names);
|
||||||
|
}
|
||||||
|
else free(self->content);
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe Grid_draw(Renderer* renderer, UIElement_Ptr _self, const DrawingArea area){
|
||||||
|
Grid* self=(Grid*)_self;
|
||||||
|
Grid_foreach(self, el,
|
||||||
|
if(el==NULL)
|
||||||
|
UI_safethrow(UIError_NullPtr,;);
|
||||||
|
UI_try(UIElement_draw(renderer, el, area),_,;);
|
||||||
|
);
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|
||||||
|
UI_Maybe Grid_deserialize(Dtsod* dtsod){
|
||||||
|
Grid gr;
|
||||||
|
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, ;);
|
||||||
|
|
||||||
|
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;
|
||||||
|
Dtsod_tryGet_Autoarr(dtsod, "content", _content, true);
|
||||||
|
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,
|
||||||
|
if(!UniCheckTypePtr(_row, Autoarr(Unitype)))
|
||||||
|
UI_safethrow_msg(
|
||||||
|
cptr_concat("expected type Autoarr(Unitype), but has got type id '",
|
||||||
|
toString_i64(_row.typeId), "'"),
|
||||||
|
Autoarr_freeWithoutMembers(content_names, true);
|
||||||
|
Autoarr_freeWithoutMembers(column_widths, true);
|
||||||
|
Autoarr_freeWithoutMembers(row_heights, true);
|
||||||
|
);
|
||||||
|
|
||||||
|
Autoarr(Unitype)* row=_row.VoidPtr;
|
||||||
|
if(columns != Autoarr_length(row))
|
||||||
|
UI_safethrow(UIError_InvalidGrid,
|
||||||
|
Autoarr_freeWithoutMembers(content_names, true);
|
||||||
|
Autoarr_freeWithoutMembers(column_widths, true);
|
||||||
|
Autoarr_freeWithoutMembers(row_heights, true);
|
||||||
|
);
|
||||||
|
|
||||||
|
Autoarr_foreach(row, _elem_d,
|
||||||
|
if(!UniCheckTypePtr(_elem_d, char))
|
||||||
|
UI_safethrow_msg(
|
||||||
|
cptr_concat("expected type char*, but has got type id '",
|
||||||
|
toString_i64(_elem_d.typeId),"'"),
|
||||||
|
Autoarr_freeWithoutMembers(content_names, true);
|
||||||
|
Autoarr_freeWithoutMembers(column_widths, true);
|
||||||
|
Autoarr_freeWithoutMembers(row_heights, true);
|
||||||
|
);
|
||||||
|
|
||||||
|
char* elem_name=_elem_d.VoidPtr;
|
||||||
|
Autoarr_add(content_names, elem_name);
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
gr.content_names=(char**)Autoarr_toArray(content_names);
|
||||||
|
Autoarr_freeWithoutMembers(content_names, true);
|
||||||
|
gr.columns=columns;
|
||||||
|
gr.rows=rows;
|
||||||
|
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;
|
||||||
|
|
||||||
|
Grid* ptr=malloc(sizeof(*ptr));
|
||||||
|
*ptr=gr;
|
||||||
|
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, Grid_toString, Grid_draw, Grid_deserialize, Grid_onBuildUIContext);
|
||||||
|
|
||||||
|
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){
|
||||||
|
.base=_UIElement_initBaseDefault(name, &UITDescriptor_Grid),
|
||||||
|
.columns=columns,
|
||||||
|
.rows=rows,
|
||||||
|
.column_widths=column_widths,
|
||||||
|
.row_heights=row_heights,
|
||||||
|
.content=content,
|
||||||
|
.content_names=NULL
|
||||||
|
};
|
||||||
|
return grid;
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,10 +1,5 @@
|
|||||||
#include "tui_internal.h"
|
#include "tui_internal.h"
|
||||||
|
|
||||||
int TCI_fwrite(FILE* file, TermCharInfo tci){
|
|
||||||
kprint_setColor(tci.color);
|
|
||||||
return termchar_fwrite(file, tci.ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// FrameBuffer //
|
// FrameBuffer //
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
@ -17,8 +12,7 @@ void FrameBuffer_freeMembers(void* _self){
|
|||||||
kt_define(FrameBuffer, FrameBuffer_freeMembers, NULL);
|
kt_define(FrameBuffer, FrameBuffer_freeMembers, NULL);
|
||||||
|
|
||||||
/// creates new frame buffer and fills it with spaces
|
/// creates new frame buffer and fills it with spaces
|
||||||
UI_THROWING_FUNC_DECL(FrameBuffer_create(FrameBuffer* fb));
|
void FrameBuffer_recreate(FrameBuffer* fb){
|
||||||
Maybe FrameBuffer_create(FrameBuffer* fb){
|
|
||||||
if(!term_getSize(&fb->size)){
|
if(!term_getSize(&fb->size)){
|
||||||
fb->size=term_default_size;
|
fb->size=term_default_size;
|
||||||
//TODO log error
|
//TODO log error
|
||||||
@ -31,8 +25,6 @@ Maybe FrameBuffer_create(FrameBuffer* fb){
|
|||||||
|
|
||||||
for(u32 i=0; i<length; i++)
|
for(u32 i=0; i<length; i++)
|
||||||
fb->data[i]=TCI(TERMCHAR(' '), kp_bgGray|kp_fgGray);
|
fb->data[i]=TCI(TERMCHAR(' '), kp_bgGray|kp_fgGray);
|
||||||
|
|
||||||
return MaybeNull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer_freeMembers(void * _self){
|
void Renderer_freeMembers(void * _self){
|
||||||
@ -59,7 +51,7 @@ UI_Maybe __Renderer_drawFrame(Renderer* self){
|
|||||||
// save current buffer
|
// save current buffer
|
||||||
FrameBuffer buf=self->frameBuffer;
|
FrameBuffer buf=self->frameBuffer;
|
||||||
// recreate frame buffer
|
// recreate frame buffer
|
||||||
UI_try(FrameBuffer_create(&self->frameBuffer),_,;);
|
FrameBuffer_recreate(&self->frameBuffer);
|
||||||
|
|
||||||
for(u16 y=0; y<buf.size.rows; y++){
|
for(u16 y=0; y<buf.size.rows; y++){
|
||||||
for(u16 x=0; x<buf.size.cols; x++){
|
for(u16 x=0; x<buf.size.cols; x++){
|
||||||
@ -91,7 +83,7 @@ kt_define(Renderer, Renderer_freeMembers, NULL);
|
|||||||
|
|
||||||
Renderer* Renderer_create(){
|
Renderer* Renderer_create(){
|
||||||
Renderer* renderer=malloc(sizeof(Renderer));
|
Renderer* renderer=malloc(sizeof(Renderer));
|
||||||
tryLast(FrameBuffer_create(&renderer->frameBuffer),_);
|
FrameBuffer_recreate(&renderer->frameBuffer);
|
||||||
renderer->set=__Renderer_set;
|
renderer->set=__Renderer_set;
|
||||||
renderer->drawFrame=__Renderer_drawFrame;
|
renderer->drawFrame=__Renderer_drawFrame;
|
||||||
return renderer;
|
return renderer;
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
#include "tui_internal.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
UI_Maybe TextBlock_draw(Renderer* renderer, UIElement* _self, const DrawingArea area){
|
UI_Maybe TextBlock_draw(Renderer* renderer, UIElement_Ptr _self, const DrawingArea area){
|
||||||
TextBlock* self=(TextBlock*)_self;
|
TextBlock* self=(TextBlock*)_self;
|
||||||
UI_try(UIElement_validate((UIElement*)self, area),_0,;);
|
UI_try(UIElement_validate((UIElement_Ptr)self, area),_0,;);
|
||||||
UI_try(Renderer_fill(renderer, TCI(TERMCHAR(' '), kp_bgBlack|kp_fgGray), area),_2,;);
|
UI_try(Renderer_fill(renderer, TCI(TERMCHAR(' '), kp_bgBlack|kp_fgGray), area),_2,;);
|
||||||
UI_try(Renderer_drawBorder(renderer, self->base.border, area),_1,;);
|
UI_try(Renderer_drawBorder(renderer, self->base.border, area),_1,;);
|
||||||
for(u16 i=0; i<area.w-2 && i<self->text.length; i++){
|
for(u16 i=0; i<area.w-2 && i<self->text.length; i++){
|
||||||
@ -18,11 +18,34 @@ UI_Maybe TextBlock_draw(Renderer* renderer, UIElement* _self, const DrawingArea
|
|||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
kt_define(TextBlock, TextBlock_freeMembers, NULL);
|
UI_Maybe TextBlock_deserialize(Dtsod* dtsod){
|
||||||
|
TextBlock tb;
|
||||||
|
|
||||||
TextBlock* TextBlock_create(string text){
|
UI_try(UIElement_deserializeBase(dtsod, &tb.base), _8751, ;);
|
||||||
|
char* _text;
|
||||||
|
Dtsod_tryGet_cptr(dtsod, "text", _text, true);
|
||||||
|
tb.text=string_fromCptr(_text);
|
||||||
|
TextBlock* ptr=malloc(sizeof(*ptr));
|
||||||
|
|
||||||
|
*ptr=tb;
|
||||||
|
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, TextBlock_toString, TextBlock_draw, TextBlock_deserialize, NULL);
|
||||||
|
|
||||||
|
TextBlock* TextBlock_create(char* name, string text){
|
||||||
TextBlock* textBlock=malloc(sizeof(TextBlock));
|
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);
|
textBlock->text=text;
|
||||||
return textBlock;
|
return textBlock;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,50 +1,118 @@
|
|||||||
#include "tui_internal.h"
|
#include "tui_internal.h"
|
||||||
|
|
||||||
kt_define(UIElement, NULL, NULL);
|
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);
|
||||||
|
Autoarr_define(UIElement_Ptr, true);
|
||||||
|
Array_define(UIElement);
|
||||||
|
|
||||||
// ktid is needed to check if it is uninitilized by calling ktDescriptor_get
|
// 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){
|
return (UIElement){
|
||||||
.type=ktDescriptor_get(typeId),
|
.name=name,
|
||||||
|
.type=uit,
|
||||||
.min_width=2,
|
.min_width=2,
|
||||||
.max_width=UIElement_stretch,
|
|
||||||
.min_height=2,
|
.min_height=2,
|
||||||
.max_height=UIElement_stretch,
|
.width=size_enable_scaling(1),
|
||||||
.fgColor=kp_fgWhite,
|
.height=size_enable_scaling(1),
|
||||||
.bgColor=kp_bgBlack,
|
.color=kp_bgBlack|kp_fgGray,
|
||||||
.anchor=UIAnchor_Center,
|
|
||||||
.border={
|
.border={
|
||||||
.left=UIBorder_Thin, .right=UIBorder_Thin,
|
.left=UIBorder_Thin, .right=UIBorder_Thin,
|
||||||
.top=UIBorder_Thin, .bottom=UIBorder_Thin,
|
.top=UIBorder_Thin, .bottom=UIBorder_Thin,
|
||||||
.color=kp_bgBlack|kp_fgGray
|
.color=kp_bgBlack|kp_fgGray
|
||||||
},
|
},
|
||||||
.draw=drawFunc
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIElement_destroy(UIElement* self){
|
void UIElement_destroy(UIElement_Ptr self){
|
||||||
if(self->type->freeMembers)
|
if(self->type->kt->freeMembers)
|
||||||
self->type->freeMembers(self);
|
self->type->kt->freeMembers(self);
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UI_Maybe DrawingArea_validate(DrawingArea a){
|
UI_Maybe DrawingArea_validate(DrawingArea a){
|
||||||
if(a.h<1) UI_safethrow(UIError_InvalidWidth,;);
|
if(a.h<1) UI_safethrow(UIError_InvalidWidth,;);
|
||||||
if(a.w<1) UI_safethrow(UIError_InvalidHeight,;);
|
if(a.w<1) UI_safethrow(UIError_InvalidHeight,;);
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
UI_Maybe UIElement_validate(UIElement* u, DrawingArea a){
|
UI_Maybe UIElement_validate(UIElement_Ptr u, DrawingArea a){
|
||||||
UI_try(DrawingArea_validate(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)
|
if(u->min_height>a.h)
|
||||||
UI_safethrow(UIError_InvalidHeight,;);
|
UI_safethrow(UIError_InvalidHeight,;);
|
||||||
if(u->min_width>a.w)
|
if(u->min_width>a.w)
|
||||||
UI_safethrow(UIError_InvalidWidth,;);
|
UI_safethrow(UIError_InvalidWidth,;);
|
||||||
return MaybeNull;
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UI_Maybe UIElement_deserializeBase(Dtsod* dtsod, UIElement* base){
|
||||||
|
char* name;
|
||||||
|
Dtsod_tryGet_cptr(dtsod, "name", name, true);
|
||||||
|
|
||||||
|
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, "'"), ;);
|
||||||
|
|
||||||
|
*base=_UIElement_initBaseDefault(cptr_copy(name), type);
|
||||||
|
|
||||||
|
Dtsod_tryGet_i64(dtsod, "min_width", base->min_width, false);
|
||||||
|
Dtsod_tryGet_i64(dtsod, "min_height", base->min_height, false);
|
||||||
|
Dtsod_tryGet_ScalingSize(dtsod, "width", base->width, false);
|
||||||
|
Dtsod_tryGet_ScalingSize(dtsod, "height", base->height, false);
|
||||||
|
char *bg_color_name, *fg_color_name;
|
||||||
|
Dtsod_tryGet_cptr(dtsod, "bg_color", bg_color_name, false,
|
||||||
|
set_color(bg_color_name, base->color);
|
||||||
|
);
|
||||||
|
Dtsod_tryGet_cptr(dtsod, "fg_color", fg_color_name, false,
|
||||||
|
set_color(fg_color_name, base->color);
|
||||||
|
);
|
||||||
|
base->border.color=base->color;
|
||||||
|
|
||||||
|
Dtsod* border_dtsod;
|
||||||
|
Dtsod_tryGet_Hashtable(dtsod, "border", border_dtsod, false, {
|
||||||
|
char* border_thickness_str;
|
||||||
|
Dtsod_tryGet_cptr(border_dtsod, "top", border_thickness_str, false,
|
||||||
|
set_border_thickness(border_thickness_str, base->border.top);
|
||||||
|
);
|
||||||
|
Dtsod_tryGet_cptr(border_dtsod, "bottom", border_thickness_str, false,
|
||||||
|
set_border_thickness(border_thickness_str, base->border.bottom);
|
||||||
|
);
|
||||||
|
Dtsod_tryGet_cptr(border_dtsod, "left", border_thickness_str, false,
|
||||||
|
set_border_thickness(border_thickness_str, base->border.left);
|
||||||
|
);
|
||||||
|
Dtsod_tryGet_cptr(border_dtsod, "right", border_thickness_str, false,
|
||||||
|
set_border_thickness(border_thickness_str, base->border.right);
|
||||||
|
);
|
||||||
|
char *bg_color_name, *fg_color_name;
|
||||||
|
Dtsod_tryGet_cptr(dtsod, "bg_color", bg_color_name, false,
|
||||||
|
set_color(bg_color_name, base->border.color);
|
||||||
|
);
|
||||||
|
Dtsod_tryGet_cptr(dtsod, "fg_color", fg_color_name, false,
|
||||||
|
set_color(fg_color_name, base->border.color);
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return MaybeNull;
|
||||||
|
}
|
||||||
|
|||||||
@ -7,11 +7,15 @@ extern "C" {
|
|||||||
#include "../../kerep/src/base/base.h"
|
#include "../../kerep/src/base/base.h"
|
||||||
|
|
||||||
PACKED_ENUM(UIError,
|
PACKED_ENUM(UIError,
|
||||||
UIError_Success=0,
|
UIError_Success=ERR_IO_EOF+1,
|
||||||
|
UIError_NotImplemented,
|
||||||
UIError_NullPtr,
|
UIError_NullPtr,
|
||||||
UIError_InvalidHeight, UIError_InvalidWidth,
|
UIError_InvalidHeight, UIError_InvalidWidth,
|
||||||
UIError_InvalidX, UIError_InvalidY,
|
UIError_InvalidX, UIError_InvalidY,
|
||||||
UIError_PrintError
|
UIError_PrintError,
|
||||||
|
UIError_InvalidVersion,
|
||||||
|
UIError_InvalidGrid,
|
||||||
|
UIError_InvalidFormat
|
||||||
)
|
)
|
||||||
|
|
||||||
// this macros can be changed later to improve debugging
|
// this macros can be changed later to improve debugging
|
||||||
|
|||||||
109
src/TUI/enums_getByName.c
Normal file
109
src/TUI/enums_getByName.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#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));
|
||||||
|
}
|
||||||
|
|
||||||
|
Hashtable* _border_t_table=NULL;
|
||||||
|
|
||||||
|
void UIBorderThickness_table_init(){
|
||||||
|
_border_t_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(_border_t_table, pairs, sizeof(pairs)/sizeof(KVPair));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI_enum_tables_init(){
|
||||||
|
termcolor_table_init();
|
||||||
|
UIBorderThickness_table_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UI_enum_tables_free(){
|
||||||
|
Hashtable_free(_colors_table);
|
||||||
|
Hashtable_free(_border_t_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
int enum_getByName(Hashtable* table, char* name){
|
||||||
|
char* name_lower=cptr_toLower(name);
|
||||||
|
Unitype uni;
|
||||||
|
if(!Hashtable_tryGet(table, name_lower, &uni))
|
||||||
|
return -1;
|
||||||
|
free(name_lower);
|
||||||
|
return uni.UInt64;
|
||||||
|
}
|
||||||
|
|
||||||
|
int termcolor_getByName(char* name){ return enum_getByName(_colors_table, name); }
|
||||||
|
int UIBorderThickness_getByName(char* name){ return enum_getByName(_border_t_table, name); }
|
||||||
124
src/TUI/tui.c
124
src/TUI/tui.c
@ -1,12 +1,130 @@
|
|||||||
#include "tui.h"
|
#include "tui_internal.h"
|
||||||
|
#include "Dtsod/tui_dtsod_internal.h"
|
||||||
|
|
||||||
kt_define(DrawingArea, NULL, NULL);
|
kt_define(DrawingArea, NULL, NULL);
|
||||||
kt_define(UIBorder, NULL, NULL);
|
kt_define(UIBorder, 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;
|
||||||
|
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->kt=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);
|
||||||
|
if(Unitype_isUniNull(val)){
|
||||||
|
char* name_ptr=cptr_concat(name,"_Ptr");
|
||||||
|
val=Hashtable_get(_uit_hashtable, name_ptr);
|
||||||
|
free(name_ptr);
|
||||||
|
}
|
||||||
|
return val.VoidPtr;
|
||||||
|
}
|
||||||
|
|
||||||
void kt_initScolteTypes(){
|
void kt_initScolteTypes(){
|
||||||
|
// term.h
|
||||||
|
kt_register(TerminalSize);
|
||||||
|
kt_register(TermCharInfo);
|
||||||
|
// tui.h
|
||||||
|
kt_register(UITDescriptor)
|
||||||
kt_register(DrawingArea);
|
kt_register(DrawingArea);
|
||||||
kt_register(UIBorder);
|
kt_register(UIBorder);
|
||||||
|
kt_register(FrameBuffer);
|
||||||
|
kt_register(Renderer);
|
||||||
kt_register(UIElement);
|
kt_register(UIElement);
|
||||||
kt_register(Canvas);
|
uit_register(Grid);
|
||||||
kt_register(TextBlock);
|
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();
|
||||||
}
|
}
|
||||||
160
src/TUI/tui.h
160
src/TUI/tui.h
@ -5,33 +5,65 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../kerep/src/String/string.h"
|
#include "../../kerep/src/String/string.h"
|
||||||
#include "../../kerep/src/kprint/kprint_format.h"
|
|
||||||
#include "../../kerep/src/Array/Array.h"
|
#include "../../kerep/src/Array/Array.h"
|
||||||
#include "../term/term.h"
|
#include "../term/term.h"
|
||||||
#include "../encoding/encoding.h"
|
#include "../encoding/encoding.h"
|
||||||
|
#include "Dtsod/tui_dtsod.h"
|
||||||
#include "UIError.h"
|
#include "UIError.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// Prototypes //
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
/// initializes type descriptors for this project's types
|
typedef struct UIElement UIElement;
|
||||||
/// call this function between kt_beginInit() and kt_endInit()
|
typedef UIElement* UIElement_Ptr;
|
||||||
void kt_initScolteTypes();
|
typedef struct Renderer Renderer;
|
||||||
|
typedef struct DrawingArea DrawingArea;
|
||||||
|
|
||||||
|
///@return Maybe<void>
|
||||||
|
typedef UI_THROWING_FUNC_DECL( (*UIElement_draw_t)(Renderer* renderer, UIElement_Ptr self, const DrawingArea area) );
|
||||||
|
///@return Maybe<UIElement_Ptr>
|
||||||
|
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) );
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////
|
||||||
|
// UI Type System //
|
||||||
|
//////////////////////////////////////
|
||||||
|
|
||||||
|
STRUCT(UITDescriptor,
|
||||||
|
ktDescriptor* kt;
|
||||||
|
UIElement_draw_t draw;
|
||||||
|
UIElement_deserialize_t deserialize;
|
||||||
|
UIElement_onBuildUIContext_t onBuild;
|
||||||
|
)
|
||||||
|
|
||||||
|
#define uit_declare(TYPE) extern UITDescriptor UITDescriptor_##TYPE;
|
||||||
|
|
||||||
|
#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={ \
|
||||||
|
.draw=DRAW_F, \
|
||||||
|
.deserialize=DESERIALIZE_F, \
|
||||||
|
.onBuild=ON_BUILD_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 //
|
// Enums //
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
PACKED_ENUM(UIAnchor,
|
|
||||||
UIAnchor_Center=0,
|
|
||||||
UIAnchor_Left=1,
|
|
||||||
UIAnchor_Right=2,
|
|
||||||
UIAnchor_Top=4,
|
|
||||||
UIAnchor_Bottom=8,
|
|
||||||
UIAnchor_RightTop=UIAnchor_Right|UIAnchor_Top,
|
|
||||||
UIAnchor_RightBottom=UIAnchor_Right|UIAnchor_Bottom,
|
|
||||||
UIAnchor_LeftTop=UIAnchor_Left|UIAnchor_Top,
|
|
||||||
UIAnchor_LeftBottom=UIAnchor_Left|UIAnchor_Bottom
|
|
||||||
)
|
|
||||||
|
|
||||||
PACKED_ENUM(UIBorderThickness,
|
PACKED_ENUM(UIBorderThickness,
|
||||||
UIBorder_Hidden, /* blank space */
|
UIBorder_Hidden, /* blank space */
|
||||||
UIBorder_Thin,
|
UIBorder_Thin,
|
||||||
@ -40,10 +72,19 @@ PACKED_ENUM(UIBorderThickness,
|
|||||||
UiBorder_NoBorder /* no space */
|
UiBorder_NoBorder /* no space */
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// 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;
|
||||||
@ -55,17 +96,9 @@ STRUCT(UIBorder,
|
|||||||
UIBorderThickness left;
|
UIBorderThickness left;
|
||||||
UIBorderThickness top;
|
UIBorderThickness top;
|
||||||
UIBorderThickness bottom;
|
UIBorderThickness bottom;
|
||||||
kp_fmt color;
|
termcolor color;
|
||||||
)
|
)
|
||||||
|
|
||||||
STRUCT(TermCharInfo,
|
|
||||||
termchar ch;
|
|
||||||
kp_fmt color; /* background + foreground */
|
|
||||||
)
|
|
||||||
|
|
||||||
#define TCI(CH,COLOR)(TermCharInfo){.ch=CH, .color=COLOR}
|
|
||||||
int TCI_fwrite(FILE* file, TermCharInfo tci);
|
|
||||||
#define TCI_print(tci) TCI_fwrite(stdout, tci);
|
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// Renderer //
|
// Renderer //
|
||||||
@ -95,49 +128,81 @@ 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_drawLineY(Renderer* renderer, TermCharInfo tci, u16 x, u16 y, u16 length));
|
||||||
UI_THROWING_FUNC_DECL(Renderer_drawBorder(Renderer* renderer, UIBorder border, const DrawingArea area));
|
UI_THROWING_FUNC_DECL(Renderer_drawBorder(Renderer* renderer, UIBorder border, const DrawingArea area));
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// UIElement abstract struct //
|
// UIElement abstract struct //
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
typedef struct UIElement UIElement;
|
|
||||||
typedef UIElement* UIElementPtr;
|
|
||||||
typedef UI_THROWING_FUNC_DECL((*UIElement_draw_t)(Renderer* renderer, UIElement* self, const DrawingArea area));
|
|
||||||
|
|
||||||
#define UIElement_stretch (u16)-1
|
|
||||||
|
|
||||||
STRUCT(UIElement,
|
STRUCT(UIElement,
|
||||||
ktDescriptor* type;
|
UITDescriptor* type;
|
||||||
|
char* name;
|
||||||
u16 min_width;
|
u16 min_width;
|
||||||
u16 max_width;
|
|
||||||
u16 min_height;
|
u16 min_height;
|
||||||
u16 max_height;
|
ScalingSize width;
|
||||||
kp_fgColor fgColor;
|
ScalingSize height;
|
||||||
kp_bgColor bgColor;
|
termcolor color;
|
||||||
UIAnchor anchor;
|
|
||||||
UIBorder border;
|
UIBorder border;
|
||||||
UIElement_draw_t draw;
|
|
||||||
)
|
)
|
||||||
|
Autoarr_declare(UIElement_Ptr)
|
||||||
|
Array_declare(UIElement)
|
||||||
|
|
||||||
/// 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_Ptr self);
|
||||||
|
|
||||||
#define UIElement_draw(RENDERER, UIE_PTR, PLACE_RECT) \
|
#define UIElement_draw(RENDERER, UIE_PTR, PLACE_RECT) \
|
||||||
((UIElement*)UIE_PTR)->draw(RENDERER, UIE_PTR, PLACE_RECT)
|
(UIE_PTR)->type->draw(RENDERER, UIE_PTR, PLACE_RECT)
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
// UIElement derivatives //
|
// UIElement derivatives //
|
||||||
//////////////////////////////////////
|
//////////////////////////////////////
|
||||||
|
|
||||||
////// Canvas //////
|
////// Grid //////
|
||||||
|
|
||||||
STRUCT(Canvas,
|
STRUCT(Grid,
|
||||||
UIElement base;
|
UIElement base;
|
||||||
/* Autoarr(UIElementPtr) */
|
u16 columns;
|
||||||
Autoarr(Pointer)* children;
|
u16 rows;
|
||||||
|
ScalingSize* row_heights;
|
||||||
|
ScalingSize* column_widths;
|
||||||
|
char** content_names;
|
||||||
|
UIElement_Ptr* content; /* UIElement[rows][columns] */
|
||||||
)
|
)
|
||||||
|
uit_declare(Grid);
|
||||||
|
|
||||||
Canvas* Canvas_create();
|
Grid* Grid_create(char* name, u16 columns, u16 rows, ScalingSize* column_widths, ScalingSize* row_heights, UIElement_Ptr* content);
|
||||||
void Canvas_addChild(Canvas* self, UIElement* child);
|
///@return Maybe<UIElement*>
|
||||||
|
UI_THROWING_FUNC_DECL( Grid_get(Grid* grid, u16 column, u16 row) );
|
||||||
|
///@return maybe<void>
|
||||||
|
UI_THROWING_FUNC_DECL( Grid_set(Grid* grid, u16 column, u16 row, UIElement_Ptr value));
|
||||||
|
///@return Maybe<char*>
|
||||||
|
UI_THROWING_FUNC_DECL( _Grid_getName(Grid* grid, u16 column, u16 row) );
|
||||||
|
|
||||||
|
#define Grid_foreach(GRID, ELEM_VAR_NAME, CODE...) { \
|
||||||
|
if(!GRID->content) \
|
||||||
|
UI_safethrow_msg(cptr_concat("grid '", GRID->base.type->kt->name, \
|
||||||
|
"' content has not been bound"),;); \
|
||||||
|
for(u16 _g_r = 0; _g_r < GRID->rows; _g_r++){ \
|
||||||
|
for(u16 _g_c = 0; _g_c < GRID->columns; _g_c++){ \
|
||||||
|
UI_try(Grid_get(GRID, _g_c, _g_r), _m_g_el,;); \
|
||||||
|
UIElement_Ptr ELEM_VAR_NAME=_m_g_el.value.VoidPtr; \
|
||||||
|
{ CODE; } \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Grid_foreachName(GRID, ELEM_VAR_NAME, CODE...) { \
|
||||||
|
if(!GRID->content_names) \
|
||||||
|
UI_safethrow_msg(cptr_concat("grid '", GRID->base.type->kt->name, \
|
||||||
|
"' content has been already bound"),;); \
|
||||||
|
for(u16 _g_r = 0; _g_r < GRID->rows; _g_r++){ \
|
||||||
|
for(u16 _g_c = 0; _g_c < GRID->columns; _g_c++){ \
|
||||||
|
UI_try(_Grid_getName(GRID, _g_c, _g_r), _m_g_nm,;); \
|
||||||
|
char* ELEM_VAR_NAME=_m_g_nm.value.VoidPtr; \
|
||||||
|
{ CODE; } \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
////// TextBlock //////
|
////// TextBlock //////
|
||||||
|
|
||||||
@ -145,9 +210,10 @@ STRUCT(TextBlock,
|
|||||||
UIElement base;
|
UIElement base;
|
||||||
string text;
|
string text;
|
||||||
)
|
)
|
||||||
|
uit_declare(TextBlock);
|
||||||
|
|
||||||
/// creates a TextBlock with a copy of text
|
/// creates a TextBlock with a copy of text
|
||||||
TextBlock* TextBlock_create(string text);
|
TextBlock* TextBlock_create(char* name, string text);
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,10 +5,14 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "tui.h"
|
#include "tui.h"
|
||||||
|
#include "../../kerep/src/String/StringBuilder.h"
|
||||||
|
|
||||||
UIElement __UIElement_createDefault(ktid typeId, UIElement_draw_t drawFunc);
|
extern UIElement _UIElement_initBaseDefault(char* name, UITDescriptor* type);
|
||||||
UI_THROWING_FUNC_DECL(DrawingArea_validate(DrawingArea a));
|
|
||||||
UI_THROWING_FUNC_DECL(UIElement_validate(UIElement* u, DrawingArea a));
|
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_h[4];
|
||||||
extern termchar UIBorder_char_v[4];
|
extern termchar UIBorder_char_v[4];
|
||||||
@ -17,6 +21,48 @@ extern termchar UIBorder_char_rt[4][4];
|
|||||||
extern termchar UIBorder_char_rb[4][4];
|
extern termchar UIBorder_char_rb[4][4];
|
||||||
extern termchar UIBorder_char_lb[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##_Ptr, &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; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
||||||
|
|||||||
@ -15,11 +15,6 @@ typedef u32 utf32char;
|
|||||||
///@returns <0 error code of fputc
|
///@returns <0 error code of fputc
|
||||||
int utf32char_fwrite(FILE* file, utf32char ch);
|
int utf32char_fwrite(FILE* file, utf32char ch);
|
||||||
|
|
||||||
typedef utf32char termchar;
|
|
||||||
#define TERMCHAR(CHAR) U##CHAR
|
|
||||||
#define TERMSTR(STR) U##STR
|
|
||||||
#define termchar_fwrite utf32char_fwrite
|
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
109
src/main.c
109
src/main.c
@ -1,20 +1,64 @@
|
|||||||
#include "../kerep/src/Filesystem/filesystem.h"
|
|
||||||
#include "TUI/tui.h"
|
#include "TUI/tui.h"
|
||||||
|
#include "TUI/Dtsod/tui_dtsod.h"
|
||||||
|
#include "../kerep/src/Filesystem/filesystem.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#if _WIN32 || _WIN64
|
#if _WIN32 || _WIN64
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Maybe tryReadFile(char* filePath){
|
#define EMBEDDED_RESOURCE_POSTFIX view
|
||||||
if(!file_exists(filePath))
|
#include "generated/view.h"
|
||||||
kprintf("file doesnt exist, creating new\n");
|
|
||||||
try(file_open(filePath, FileOpenMode_ReadAppend), _m_file,;);
|
void on_exit(){
|
||||||
FileHandle file=_m_file.value.VoidPtr;
|
Scolte_free();
|
||||||
char* fileContent=NULL;
|
kt_free();
|
||||||
try(file_readAll(file, &fileContent), _m_bcount,;)
|
term_resetColors();
|
||||||
try(file_close(file),_m_,;);
|
term_cursorHide(false);
|
||||||
return SUCCESS(UniHeapPtr(char,fileContent));
|
}
|
||||||
|
|
||||||
|
// 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(unsigned int i=0; i<EmbeddedResourceFile_table_view_count; i++){
|
||||||
|
EmbeddedResourceFile rs=EmbeddedResourceFile_table_view[i];
|
||||||
|
UI_try(UIDtsodParser_parseText(p, rs.path, rs.data),
|
||||||
|
_91624, 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, textblock, TextBlock, UIContext_destroy(ui_context));
|
||||||
|
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);
|
||||||
|
return MaybeNull;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 main(const i32 argc, const char* const* argv){
|
i32 main(const i32 argc, const char* const* argv){
|
||||||
@ -27,31 +71,50 @@ i32 main(const i32 argc, const char* const* argv){
|
|||||||
kprintf("\e[93msetlocale failed! (%i)\n", errno);
|
kprintf("\e[93msetlocale failed! (%i)\n", errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
term_cursorHide(true);
|
||||||
|
term_clear();
|
||||||
|
|
||||||
|
// kerep type system
|
||||||
kt_beginInit();
|
kt_beginInit();
|
||||||
kt_initKerepTypes();
|
kt_initKerepTypes();
|
||||||
kt_initScolteTypes();
|
kt_beginInitTUI();
|
||||||
|
Scolte_init();
|
||||||
|
kt_endInitTUI();
|
||||||
kt_endInit();
|
kt_endInit();
|
||||||
|
|
||||||
|
// print command line arguments
|
||||||
kprintf("\e[37margs:");
|
kprintf("\e[37margs:");
|
||||||
for(i32 i=0; i<argc; i++)
|
for(i32 i=0; i<argc; i++)
|
||||||
kprintf(" %s", argv[i]);
|
kprintf(" %s", argv[i]);
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
|
|
||||||
/*char* filePath= argc>1 ? argv[argc-1] : "new_file.txt";
|
// create file
|
||||||
tryLast(tryReadFile(filePath), _m_text);
|
/* char* filePath= argc>1 ? argv[argc-1] : "new_file.txt";
|
||||||
|
tryLast(tryReadFile(filePath), _m_text, on_exit());
|
||||||
char* text=(char*)_m_text.value.VoidPtr;
|
char* text=(char*)_m_text.value.VoidPtr;
|
||||||
fputs(text,stdout);*/
|
fputs(text,stdout); */
|
||||||
|
|
||||||
Renderer* renderer=Renderer_create();
|
// render ui
|
||||||
Canvas* mainCanvas=Canvas_create();
|
// Renderer* renderer=Renderer_create();
|
||||||
TextBlock* testTextBlock=TextBlock_create(string_fromCptr("some example text"));
|
// TextBlock* testTextBlock=TextBlock_create("TextBlock1", string_fromCptr("some example text"));
|
||||||
Canvas_addChild(mainCanvas, (UIElement*)testTextBlock);
|
// Autoarr(UIElement_Ptr)* grid_content=Autoarr_create(UIElement_Ptr, 1, 64);
|
||||||
tryLast(UIElement_draw(renderer, (UIElement*)mainCanvas, ((DrawingArea){.x=10, .y=4, .h=7, .w=24})),_);
|
// Autoarr_add(grid_content, (UIElement_Ptr)testTextBlock);
|
||||||
tryLast(Renderer_drawFrame(renderer),_2);
|
// 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})),
|
||||||
|
// _, on_exit());
|
||||||
|
// tryLast(Renderer_drawFrame(renderer),_2);
|
||||||
|
// // free ui memory
|
||||||
|
// UIElement_destroy((UIElement_Ptr)mainGrid);
|
||||||
|
// Renderer_destroy(renderer);
|
||||||
|
|
||||||
UIElement_destroy((UIElement*)mainCanvas);
|
// TODO signal( SIGWINCH, redraw );
|
||||||
Renderer_destroy(renderer);
|
|
||||||
|
|
||||||
kt_free();
|
for(u32 n=0; n<1; n++){
|
||||||
|
tryLast(test_example_ui_build(), _6981751, on_exit());
|
||||||
|
}
|
||||||
|
|
||||||
|
on_exit();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/term/TermCharInfo.c
Normal file
8
src/term/TermCharInfo.c
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "term.h"
|
||||||
|
|
||||||
|
kt_define(TermCharInfo, NULL, NULL);
|
||||||
|
|
||||||
|
int TCI_fwrite(FILE* file, TermCharInfo tci){
|
||||||
|
kprint_setColor(tci.color);
|
||||||
|
return termchar_fwrite(file, tci.ch);
|
||||||
|
}
|
||||||
@ -3,13 +3,23 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include IFWIN("windows.h", "sys/ioctl.h")
|
#include IFWIN("windows.h", "sys/ioctl.h")
|
||||||
|
|
||||||
void term_moveCursor(u16 row, u16 column){
|
char* TerminalSize_toString(TerminalSize t){
|
||||||
printf("\e[%u;%uf",row,column);
|
char buf[64];
|
||||||
|
sprintf_s(buf, sizeof(buf), "(%ux%u)", t.cols, t.rows);
|
||||||
|
return cptr_copy(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void term_clear() {
|
char* __TerminalSize_toString(void* _t, u32 fmt){ return TerminalSize_toString(*(TerminalSize*)_t); }
|
||||||
printf("\e[2j");
|
|
||||||
|
kt_define(TerminalSize, NULL, __TerminalSize_toString);
|
||||||
|
|
||||||
|
TerminalSize term_default_size={.cols=80, .rows=16};
|
||||||
|
|
||||||
|
int getenv_int(const char* var_name){
|
||||||
|
char* str=getenv(var_name);
|
||||||
|
if(str==NULL)
|
||||||
|
return -1;
|
||||||
|
return strtol(str, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool term_getSize(TerminalSize* out) {
|
bool term_getSize(TerminalSize* out) {
|
||||||
@ -24,15 +34,30 @@ bool term_getSize(TerminalSize* out) {
|
|||||||
.rows=consoleInfo.srWindow.Bottom-consoleInfo.srWindow.Top+1
|
.rows=consoleInfo.srWindow.Bottom-consoleInfo.srWindow.Top+1
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
struct winsize w={0,0,0,0};
|
struct winsize ws={0,0,0,0};
|
||||||
if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w)!=0)
|
// tries to get terminal size from stdin, stdout, stderr
|
||||||
return false;
|
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)==0 ||
|
||||||
*out=(TerminalSize){
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws)==0 ||
|
||||||
.cols=w.ws_col,
|
ioctl(STDERR_FILENO, TIOCGWINSZ, &ws)==0 ){
|
||||||
.rows=w.ws_row
|
out->cols=ws.ws_col;
|
||||||
};
|
out->rows=ws.ws_row;
|
||||||
|
}
|
||||||
|
// tries to get size from environtent variables
|
||||||
|
else{
|
||||||
|
out->cols=getenv_int("COLUMNS");
|
||||||
|
out->rows=getenv_int("LINES");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return out->cols > 0 && out->cols < 720 && out->rows > 0 && out->rows < 480;
|
||||||
}
|
}
|
||||||
|
|
||||||
TerminalSize term_default_size={.cols=80, .rows=16};
|
/*
|
||||||
|
Most of escape sequences can be found at:
|
||||||
|
https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
|
||||||
|
*/
|
||||||
|
|
||||||
|
void term_resetCursor() { printf("\e[H"); }
|
||||||
|
void term_resetColors() { printf("\e[0m"); }
|
||||||
|
void term_clear() { printf("\e[0m\e[H\e[2J"); }
|
||||||
|
void term_cursorMove(u16 row, u16 column) { printf("\e[%u;%uH",row,column); }
|
||||||
|
void term_cursorHide(bool hide) { printf( hide ? "\e[?25l" : "\e[?25h"); }
|
||||||
@ -5,13 +5,18 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../kerep/src/base/base.h"
|
#include "../../kerep/src/base/base.h"
|
||||||
|
#include "../../kerep/src/kprint/kprint_format.h"
|
||||||
|
#include "../encoding/encoding.h"
|
||||||
|
|
||||||
void term_moveCursor(u16 row, u16 column);
|
void term_resetCursor();
|
||||||
|
void term_resetColors();
|
||||||
void term_clear();
|
void term_clear();
|
||||||
|
void term_cursorMove(u16 row, u16 column);
|
||||||
|
void term_cursorHide(bool hide);
|
||||||
|
|
||||||
STRUCT(TerminalSize,
|
STRUCT(TerminalSize,
|
||||||
u16 rows;
|
|
||||||
u16 cols;
|
u16 cols;
|
||||||
|
u16 rows;
|
||||||
)
|
)
|
||||||
|
|
||||||
///@return TRUE if have got terminal size, otherwise FALSE
|
///@return TRUE if have got terminal size, otherwise FALSE
|
||||||
@ -20,6 +25,21 @@ bool term_getSize(TerminalSize* out) WARN_UNUSED_REZULT;
|
|||||||
/// can be used if term_getSize() fails
|
/// can be used if term_getSize() fails
|
||||||
extern TerminalSize term_default_size;
|
extern TerminalSize term_default_size;
|
||||||
|
|
||||||
|
typedef kp_fmt termcolor;
|
||||||
|
typedef utf32char termchar;
|
||||||
|
#define TERMCHAR(CHAR) U##CHAR
|
||||||
|
#define TERMSTR(STR) U##STR
|
||||||
|
#define termchar_fwrite utf32char_fwrite
|
||||||
|
|
||||||
|
STRUCT(TermCharInfo,
|
||||||
|
termchar ch;
|
||||||
|
termcolor color; /* background + foreground */
|
||||||
|
)
|
||||||
|
|
||||||
|
#define TCI(CH,COLOR)(TermCharInfo){.ch=CH, .color=COLOR}
|
||||||
|
int TCI_fwrite(FILE* file, TermCharInfo tci);
|
||||||
|
#define TCI_print(tci) TCI_fwrite(stdout, tci);
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
17
tasks/build_view.sh
Normal file
17
tasks/build_view.sh
Normal file
@ -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
|
||||||
@ -1,10 +1,4 @@
|
|||||||
#!/usr/bin/bash
|
#!/usr/bin/bash
|
||||||
for tmpfile in $(ls -a | grep -e '\.rebuild.*\.tmp'); do
|
set -eo pipefail
|
||||||
try_delete_dir_or_file "$tmpfile"
|
|
||||||
done
|
|
||||||
|
|
||||||
for submodule in kerep utf8proc; do
|
try_delete_dir_or_file src/generated
|
||||||
cd "$submodule"
|
|
||||||
make clean
|
|
||||||
cd ..
|
|
||||||
done
|
|
||||||
|
|||||||
@ -1,25 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
# if $lib_project.a doesn't exist or rebuild_* task was executed, builds static lib
|
# generate source code for views/*.tui.dtsod
|
||||||
function handle_static_dependency {
|
source tasks/build_view.sh
|
||||||
local lib_project="$1"
|
|
||||||
local lib_build_task="$2"
|
|
||||||
local lib_build_rezults="$3"
|
|
||||||
if [ ! -f "$OBJDIR/libs/$lib_project.a" ] || [ -f .rebuild_$lib_project.tmp ]; then
|
|
||||||
[[ -z "$lib_build_task" ]] && error "lib_build_task is empty"
|
|
||||||
myprint "${BLUE}making $lib_project task <$lib_build_task>"
|
|
||||||
|
|
||||||
cd $lib_project
|
|
||||||
if ! make "$lib_build_task"; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
cp $lib_build_rezults $OBJDIR/libs/
|
|
||||||
myprint "${GREEN}copied ${CYAN}$lib_project.a"
|
|
||||||
rm -f .rebuild_$lib_project.tmp
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_static_dependency kerep "$DEPS_BUILD_TASK" kerep/bin/kerep.a
|
|
||||||
handle_static_dependency utf8proc libutf8proc.a utf8proc/libutf8proc.a
|
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
source cbuild/colors.sh
|
|
||||||
source cbuild/functions.sh
|
|
||||||
touch ".rebuild_$1.tmp"
|
|
||||||
rm -fv "obj/libs/$1.a"
|
|
||||||
myprint "${YELLOW}$1.a will be rebuilt in the next build task"
|
|
||||||
37
view/example.tui.dtsod
Normal file
37
view/example.tui.dtsod
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
parser_version: 1;
|
||||||
|
namespace: "example";
|
||||||
|
|
||||||
|
$ui: {
|
||||||
|
name: "textblock",
|
||||||
|
type: "TextBlock",
|
||||||
|
min_width: 4,
|
||||||
|
max_width: 4,
|
||||||
|
width: 20,
|
||||||
|
height: "3",
|
||||||
|
bg_color: "black",
|
||||||
|
fg_color: "white",
|
||||||
|
border: {
|
||||||
|
top: "hidden",
|
||||||
|
bottom: "no",
|
||||||
|
left: "thick",
|
||||||
|
right: "double",
|
||||||
|
fg_color: "dark_cyan",
|
||||||
|
bg_color: "gray";
|
||||||
|
},
|
||||||
|
text: "UwU",
|
||||||
|
};
|
||||||
|
|
||||||
|
$ui: {
|
||||||
|
name: "Grid",
|
||||||
|
type: "Grid",
|
||||||
|
row_heights: [
|
||||||
|
"1*",
|
||||||
|
-1,
|
||||||
|
],
|
||||||
|
column_widths: [ "-8*" ],
|
||||||
|
content: [
|
||||||
|
# column
|
||||||
|
[ "example_textblock" ], # row
|
||||||
|
[ "example_textblock" ], # row
|
||||||
|
];
|
||||||
|
};
|
||||||
17
view/main.tui.dtsod
Normal file
17
view/main.tui.dtsod
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
parser_version: 1;
|
||||||
|
namespace: "main";
|
||||||
|
|
||||||
|
# $ui: {
|
||||||
|
# name: "main_grid",
|
||||||
|
# type: "Grid",
|
||||||
|
# row_heights: [
|
||||||
|
# "1*",
|
||||||
|
# # -1,
|
||||||
|
# # ],
|
||||||
|
# # column_widths: [ "-8*" ],
|
||||||
|
# content: [
|
||||||
|
# # column
|
||||||
|
# # [ "namespace.element0" ], # row
|
||||||
|
# # [ "namespace.element1" ], # row
|
||||||
|
# ];
|
||||||
|
# };
|
||||||
Loading…
Reference in New Issue
Block a user