[ui, styling] First draft of rule-based styling to replace old stack-based system
This commit is contained in:
parent
b52a35c753
commit
7b10a99a8c
|
@ -122,7 +122,7 @@ int main()
|
||||||
.font = font,
|
.font = font,
|
||||||
.fontSize = 32};
|
.fontSize = 32};
|
||||||
|
|
||||||
ui_begin_frame(frame.w, frame.h, defaultStyle);
|
ui_frame(frame.w, frame.h, defaultStyle)
|
||||||
{
|
{
|
||||||
ui_push_size(UI_AXIS_X, UI_SIZE_CHILDREN, 10, 0);
|
ui_push_size(UI_AXIS_X, UI_SIZE_CHILDREN, 10, 0);
|
||||||
ui_push_size(UI_AXIS_Y, UI_SIZE_CHILDREN, 10, 0);
|
ui_push_size(UI_AXIS_Y, UI_SIZE_CHILDREN, 10, 0);
|
||||||
|
@ -173,7 +173,7 @@ int main()
|
||||||
ui_pop_size(UI_AXIS_X);
|
ui_pop_size(UI_AXIS_X);
|
||||||
ui_pop_size(UI_AXIS_Y);
|
ui_pop_size(UI_AXIS_Y);
|
||||||
}
|
}
|
||||||
ui_end_frame();
|
|
||||||
ui_draw();
|
ui_draw();
|
||||||
|
|
||||||
mg_flush();
|
mg_flush();
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle_headers
|
||||||
|
|
||||||
|
cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/test_ui.exe
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BINDIR=../../bin
|
||||||
|
RESDIR=../../resources
|
||||||
|
SRCDIR=../../src
|
||||||
|
|
||||||
|
INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app"
|
||||||
|
LIBS="-L$BINDIR -lmilepost"
|
||||||
|
FLAGS="-mmacos-version-min=10.15.4 -DDEBUG -DLOG_COMPILE_DEBUG"
|
||||||
|
|
||||||
|
clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/test_ui main.c
|
|
@ -0,0 +1,177 @@
|
||||||
|
/************************************************************//**
|
||||||
|
*
|
||||||
|
* @file: main.cpp
|
||||||
|
* @author: Martin Fouilleul
|
||||||
|
* @date: 30/07/2022
|
||||||
|
* @revision:
|
||||||
|
*
|
||||||
|
*****************************************************************/
|
||||||
|
#include<stdlib.h>
|
||||||
|
#include<string.h>
|
||||||
|
#include<errno.h>
|
||||||
|
|
||||||
|
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC
|
||||||
|
#include<math.h>
|
||||||
|
|
||||||
|
#include"milepost.h"
|
||||||
|
|
||||||
|
#define LOG_SUBSYSTEM "Main"
|
||||||
|
|
||||||
|
void debug_print_indent(int indent)
|
||||||
|
{
|
||||||
|
for(int i=0; i<indent; i++)
|
||||||
|
{
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug_print_rule(ui_style_rule* rule)
|
||||||
|
{
|
||||||
|
for_each_in_list(&rule->pattern.l, selector, ui_selector, listElt)
|
||||||
|
{
|
||||||
|
switch(selector->kind)
|
||||||
|
{
|
||||||
|
case UI_SEL_TEXT:
|
||||||
|
printf("text='%.*s': ", (int)selector->text.len, selector->text.ptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SEL_TAG:
|
||||||
|
printf("tag=0x%llx: ", selector->tag.hash);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("unknown: ");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("=> font size = %f\n", rule->style->fontSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug_print_styles(ui_box* box, int indent)
|
||||||
|
{
|
||||||
|
debug_print_indent(indent);
|
||||||
|
printf("### box '%.*s'\n", (int)box->string.len, box->string.ptr);
|
||||||
|
indent++;
|
||||||
|
|
||||||
|
debug_print_indent(indent);
|
||||||
|
printf("font size: %f\n", box->targetStyle->fontSize);
|
||||||
|
|
||||||
|
if(!ListEmpty(&box->beforeRules))
|
||||||
|
{
|
||||||
|
debug_print_indent(indent);
|
||||||
|
printf("before rules:\n");
|
||||||
|
for_each_in_list(&box->beforeRules, rule, ui_style_rule, boxElt)
|
||||||
|
{
|
||||||
|
debug_print_indent(indent+1);
|
||||||
|
debug_print_rule(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ListEmpty(&box->afterRules))
|
||||||
|
{
|
||||||
|
debug_print_indent(indent);
|
||||||
|
printf("after rules:\n");
|
||||||
|
for_each_in_list(&box->afterRules, rule, ui_style_rule, boxElt)
|
||||||
|
{
|
||||||
|
debug_print_indent(indent+1);
|
||||||
|
debug_print_rule(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ListEmpty(&box->children))
|
||||||
|
{
|
||||||
|
debug_print_indent(indent);
|
||||||
|
printf("children:\n");
|
||||||
|
indent++;
|
||||||
|
for_each_in_list(&box->children, child, ui_box, listElt)
|
||||||
|
{
|
||||||
|
debug_print_styles(child, indent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
LogLevel(LOG_LEVEL_WARNING);
|
||||||
|
|
||||||
|
mp_init();
|
||||||
|
mp_clock_init(); //TODO put that in mp_init()?
|
||||||
|
|
||||||
|
ui_init();
|
||||||
|
|
||||||
|
mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610};
|
||||||
|
mp_window window = mp_window_create(windowRect, "test", 0);
|
||||||
|
|
||||||
|
mp_rect contentRect = mp_window_get_content_rect(window);
|
||||||
|
|
||||||
|
//NOTE: create surface
|
||||||
|
mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_DEFAULT);
|
||||||
|
mg_surface_swap_interval(surface, 0);
|
||||||
|
|
||||||
|
//TODO: create canvas
|
||||||
|
mg_canvas canvas = mg_canvas_create(surface);
|
||||||
|
|
||||||
|
if(mg_canvas_is_nil(canvas))
|
||||||
|
{
|
||||||
|
printf("Error: couldn't create canvas\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TEST UI
|
||||||
|
ui_style defaultStyle = {.bgColor = {0.9, 0.9, 0.9, 1},
|
||||||
|
.borderSize = 2,
|
||||||
|
.borderColor = {0, 0, 1, 1},
|
||||||
|
.color = {0, 0, 0, 1},
|
||||||
|
.fontSize = 32};
|
||||||
|
|
||||||
|
ui_box* root = 0;
|
||||||
|
ui_frame(800, 800, defaultStyle)
|
||||||
|
{
|
||||||
|
root = ui_box_top();
|
||||||
|
|
||||||
|
ui_pattern pattern = {0};
|
||||||
|
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = str8_lit("b")});
|
||||||
|
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make(str8_lit("foo"))});
|
||||||
|
ui_style_next(pattern,
|
||||||
|
&(ui_style){.fontSize = 12},
|
||||||
|
UI_STYLE_FONT_SIZE);
|
||||||
|
|
||||||
|
ui_container("a", 0)
|
||||||
|
{
|
||||||
|
ui_pattern pattern = {0};
|
||||||
|
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = str8_lit("b")});
|
||||||
|
ui_style_next(pattern,
|
||||||
|
&(ui_style){.fontSize = 20},
|
||||||
|
UI_STYLE_FONT_SIZE);
|
||||||
|
|
||||||
|
ui_container("b", 0)
|
||||||
|
{
|
||||||
|
ui_container("c", 0)
|
||||||
|
{
|
||||||
|
ui_box_make("d", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_container("e", 0)
|
||||||
|
{
|
||||||
|
ui_tag_next(str8_lit("foo"));
|
||||||
|
ui_box_make("f", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui_tag_next(str8_lit("foo"));
|
||||||
|
ui_box_make("d", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern = (ui_pattern){0};
|
||||||
|
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = str8_lit("c")});
|
||||||
|
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = str8_lit("d")});
|
||||||
|
ui_style_prev(pattern,
|
||||||
|
&(ui_style){.fontSize = 30},
|
||||||
|
UI_STYLE_FONT_SIZE);
|
||||||
|
}
|
||||||
|
debug_print_styles(root, 0);
|
||||||
|
|
||||||
|
mp_terminate();
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
557
src/ui.c
557
src/ui.c
|
@ -26,20 +26,6 @@ typedef struct ui_input_text
|
||||||
|
|
||||||
} ui_input_text;
|
} ui_input_text;
|
||||||
|
|
||||||
typedef struct ui_style_attr
|
|
||||||
{
|
|
||||||
ui_style_tag tag;
|
|
||||||
ui_style_selector selector;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
ui_size size;
|
|
||||||
mg_color color;
|
|
||||||
mg_font font;
|
|
||||||
f32 value;
|
|
||||||
u32 flags;
|
|
||||||
};
|
|
||||||
} ui_style_attr;
|
|
||||||
|
|
||||||
typedef struct ui_stack_elt ui_stack_elt;
|
typedef struct ui_stack_elt ui_stack_elt;
|
||||||
struct ui_stack_elt
|
struct ui_stack_elt
|
||||||
{
|
{
|
||||||
|
@ -49,10 +35,15 @@ struct ui_stack_elt
|
||||||
ui_box* box;
|
ui_box* box;
|
||||||
ui_size size;
|
ui_size size;
|
||||||
mp_rect clip;
|
mp_rect clip;
|
||||||
ui_style_attr attr;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct ui_tag_elt
|
||||||
|
{
|
||||||
|
list_elt listElt;
|
||||||
|
ui_tag tag;
|
||||||
|
} ui_tag_elt;
|
||||||
|
|
||||||
const u64 UI_BOX_MAP_BUCKET_COUNT = 1024;
|
const u64 UI_BOX_MAP_BUCKET_COUNT = 1024;
|
||||||
|
|
||||||
typedef struct ui_context
|
typedef struct ui_context
|
||||||
|
@ -75,17 +66,10 @@ typedef struct ui_context
|
||||||
ui_stack_elt* boxStack;
|
ui_stack_elt* boxStack;
|
||||||
ui_stack_elt* clipStack;
|
ui_stack_elt* clipStack;
|
||||||
|
|
||||||
ui_stack_elt* sizeStack[UI_AXIS_COUNT];
|
list_info nextBoxRules;
|
||||||
ui_stack_elt* bgColorStack;
|
ui_box* lastBox;
|
||||||
ui_stack_elt* fgColorStack;
|
|
||||||
ui_stack_elt* borderColorStack;
|
list_info nextBoxTags;
|
||||||
ui_stack_elt* fontColorStack;
|
|
||||||
ui_stack_elt* fontStack;
|
|
||||||
ui_stack_elt* fontSizeStack;
|
|
||||||
ui_stack_elt* borderSizeStack;
|
|
||||||
ui_stack_elt* roundnessStack;
|
|
||||||
ui_stack_elt* animationTimeStack;
|
|
||||||
ui_stack_elt* animationFlagsStack;
|
|
||||||
|
|
||||||
u32 z;
|
u32 z;
|
||||||
ui_box* hovered;
|
ui_box* hovered;
|
||||||
|
@ -205,167 +189,30 @@ void ui_box_pop(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_style_attr* ui_push_style_attr(ui_context* ui, ui_stack_elt** stack)
|
//-----------------------------------------------------------------------------
|
||||||
|
// tagging
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ui_tag ui_tag_make(str8 string)
|
||||||
{
|
{
|
||||||
ui_stack_elt* elt = ui_stack_push(ui, stack);
|
ui_tag tag = {.hash = mp_hash_aes_string(string)};
|
||||||
return(&elt->attr);
|
return(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_push_size(ui_axis axis, ui_size_kind kind, f32 value, f32 strictness)
|
void ui_tag_box(ui_box* box, str8 string)
|
||||||
{
|
|
||||||
ui_push_size_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_ANY, axis, kind, value, strictness);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui_push_size_ext(ui_style_tag tag, ui_style_selector selector, ui_axis axis, ui_size_kind kind, f32 value, f32 strictness)
|
|
||||||
{
|
{
|
||||||
ui_context* ui = ui_get_context();
|
ui_context* ui = ui_get_context();
|
||||||
ui_style_attr* attr = ui_push_style_attr(ui, &ui->sizeStack[axis]);
|
ui_tag_elt* elt = mem_arena_alloc_type(&ui->frameArena, ui_tag_elt);
|
||||||
attr->tag = tag;
|
elt->tag = ui_tag_make(string);
|
||||||
attr->selector = selector;
|
ListAppend(&box->tags, &elt->listElt);
|
||||||
attr->size = (ui_size){kind, value, strictness};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_pop_size(ui_axis axis)
|
void ui_tag_next(str8 string)
|
||||||
{
|
{
|
||||||
ui_context* ui = ui_get_context();
|
ui_context* ui = ui_get_context();
|
||||||
ui_stack_pop(&ui->sizeStack[axis]);
|
ui_tag_elt* elt = mem_arena_alloc_type(&ui->frameArena, ui_tag_elt);
|
||||||
}
|
elt->tag = ui_tag_make(string);
|
||||||
|
ListAppend(&ui->nextBoxTags, &elt->listElt);
|
||||||
#define UI_STYLE_STACK_OP_DEF(name, stack, type, arg) \
|
|
||||||
void _cat3_(ui_push_, name, _ext)(ui_style_tag tag, ui_style_selector selector, type arg) \
|
|
||||||
{ \
|
|
||||||
ui_context* ui = ui_get_context(); \
|
|
||||||
ui_style_attr* attr = ui_push_style_attr(ui, &ui->stack); \
|
|
||||||
attr->tag = tag; \
|
|
||||||
attr->selector = selector; \
|
|
||||||
attr->arg = arg; \
|
|
||||||
} \
|
|
||||||
void _cat2_(ui_push_, name)(type arg) \
|
|
||||||
{ \
|
|
||||||
_cat3_(ui_push_, name, _ext)(UI_STYLE_TAG_ANY, UI_STYLE_SEL_ANY, arg); \
|
|
||||||
} \
|
|
||||||
void _cat2_(ui_pop_, name)(void) \
|
|
||||||
{ \
|
|
||||||
ui_context* ui = ui_get_context(); \
|
|
||||||
ui_stack_pop(&ui->stack); \
|
|
||||||
}
|
|
||||||
|
|
||||||
UI_STYLE_STACK_OP_DEF(bg_color, bgColorStack, mg_color, color)
|
|
||||||
UI_STYLE_STACK_OP_DEF(fg_color, fgColorStack, mg_color, color)
|
|
||||||
UI_STYLE_STACK_OP_DEF(border_color, borderColorStack, mg_color, color)
|
|
||||||
UI_STYLE_STACK_OP_DEF(font_color, fontColorStack, mg_color, color)
|
|
||||||
UI_STYLE_STACK_OP_DEF(font, fontStack, mg_font, font)
|
|
||||||
UI_STYLE_STACK_OP_DEF(font_size, fontSizeStack, f32, value)
|
|
||||||
UI_STYLE_STACK_OP_DEF(border_size, borderSizeStack, f32, value)
|
|
||||||
UI_STYLE_STACK_OP_DEF(roundness, roundnessStack, f32, value)
|
|
||||||
UI_STYLE_STACK_OP_DEF(animation_time, animationTimeStack, f32, value)
|
|
||||||
UI_STYLE_STACK_OP_DEF(animation_flags, animationFlagsStack, u32, flags)
|
|
||||||
|
|
||||||
ui_style_attr* ui_style_attr_query(ui_stack_elt* stack, ui_style_tag tag, ui_style_selector selector)
|
|
||||||
{
|
|
||||||
ui_style_attr* result = 0;
|
|
||||||
while(stack)
|
|
||||||
{
|
|
||||||
ui_style_attr* attr = &stack->attr;
|
|
||||||
bool matchTag = (attr->tag == UI_STYLE_TAG_ANY)
|
|
||||||
||(attr->tag == tag);
|
|
||||||
|
|
||||||
bool matchSel = attr->selector & selector;
|
|
||||||
|
|
||||||
if(matchTag && matchSel)
|
|
||||||
{
|
|
||||||
result = attr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
stack = stack->parent;
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_color ui_style_color_query(ui_stack_elt* stack, ui_style_tag tag, ui_style_selector selector)
|
|
||||||
{
|
|
||||||
ui_style_attr* attr = ui_style_attr_query(stack, tag, selector);
|
|
||||||
if(attr)
|
|
||||||
{
|
|
||||||
return(attr->color);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return((mg_color){});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mg_font ui_style_font_query(ui_stack_elt* stack, ui_style_tag tag, ui_style_selector selector)
|
|
||||||
{
|
|
||||||
ui_style_attr* attr = ui_style_attr_query(stack, tag, selector);
|
|
||||||
if(attr)
|
|
||||||
{
|
|
||||||
return(attr->font);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return(mg_font_nil());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f32 ui_style_float_query(ui_stack_elt* stack, ui_style_tag tag, ui_style_selector selector)
|
|
||||||
{
|
|
||||||
ui_style_attr* attr = ui_style_attr_query(stack, tag, selector);
|
|
||||||
if(attr)
|
|
||||||
{
|
|
||||||
return(attr->value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 ui_style_flags_query(ui_stack_elt* stack, ui_style_tag tag, ui_style_selector selector)
|
|
||||||
{
|
|
||||||
ui_style_attr* attr = ui_style_attr_query(stack, tag, selector);
|
|
||||||
if(attr)
|
|
||||||
{
|
|
||||||
return(attr->flags);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ui_size ui_style_size_query(ui_stack_elt* stack, ui_style_tag tag, ui_style_selector selector)
|
|
||||||
{
|
|
||||||
ui_style_attr* attr = ui_style_attr_query(stack, tag, selector);
|
|
||||||
if(attr)
|
|
||||||
{
|
|
||||||
return(attr->size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return((ui_size){});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_style* ui_collate_style(ui_context* context, ui_style_tag tag, ui_style_selector selector)
|
|
||||||
{
|
|
||||||
ui_style* style = mem_arena_alloc_type(&context->frameArena, ui_style);
|
|
||||||
|
|
||||||
style->size[UI_AXIS_X] = ui_style_size_query(context->sizeStack[UI_AXIS_X], tag, selector);
|
|
||||||
style->size[UI_AXIS_Y] = ui_style_size_query(context->sizeStack[UI_AXIS_Y], tag, selector);
|
|
||||||
style->bgColor = ui_style_color_query(context->bgColorStack, tag, selector);
|
|
||||||
style->fgColor = ui_style_color_query(context->fgColorStack, tag, selector);
|
|
||||||
style->borderColor = ui_style_color_query(context->borderColorStack, tag, selector);
|
|
||||||
style->fontColor = ui_style_color_query(context->fontColorStack, tag, selector);
|
|
||||||
style->font = ui_style_font_query(context->fontStack, tag, selector);
|
|
||||||
style->fontSize = ui_style_float_query(context->fontSizeStack, tag, selector);
|
|
||||||
style->borderSize = ui_style_float_query(context->borderSizeStack, tag, selector);
|
|
||||||
style->roundness = ui_style_float_query(context->roundnessStack, tag, selector);
|
|
||||||
style->animationTime = ui_style_float_query(context->animationTimeStack, tag, selector);
|
|
||||||
style->animationFlags = ui_style_flags_query(context->animationFlagsStack, tag, selector);
|
|
||||||
return(style);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -423,6 +270,47 @@ ui_box* ui_box_lookup(const char* string)
|
||||||
return(ui_box_lookup_str8(str8_from_cstring((char*)string)));
|
return(ui_box_lookup_str8(str8_from_cstring((char*)string)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// styling
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void ui_pattern_push(mem_arena* arena, ui_pattern* pattern, ui_selector selector)
|
||||||
|
{
|
||||||
|
ui_selector* copy = mem_arena_alloc_type(arena, ui_selector);
|
||||||
|
*copy = selector;
|
||||||
|
ListAppend(&pattern->l, ©->listElt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_style_next(ui_pattern pattern, ui_style* style, ui_style_mask mask)
|
||||||
|
{
|
||||||
|
ui_context* ui = ui_get_context();
|
||||||
|
if(ui)
|
||||||
|
{
|
||||||
|
ui_style_rule* rule = mem_arena_alloc_type(&ui->frameArena, ui_style_rule);
|
||||||
|
rule->pattern = pattern;
|
||||||
|
rule->mask = mask;
|
||||||
|
rule->style = mem_arena_alloc_type(&ui->frameArena, ui_style);
|
||||||
|
*rule->style = *style;
|
||||||
|
|
||||||
|
ListAppend(&ui->nextBoxRules, &rule->boxElt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_style_prev(ui_pattern pattern, ui_style* style, ui_style_mask mask)
|
||||||
|
{
|
||||||
|
ui_context* ui = ui_get_context();
|
||||||
|
if(ui && ui->lastBox)
|
||||||
|
{
|
||||||
|
ui_style_rule* rule = mem_arena_alloc_type(&ui->frameArena, ui_style_rule);
|
||||||
|
rule->pattern = pattern;
|
||||||
|
rule->mask = mask;
|
||||||
|
rule->style = mem_arena_alloc_type(&ui->frameArena, ui_style);
|
||||||
|
*rule->style = *style;
|
||||||
|
|
||||||
|
ListAppend(&ui->lastBox->afterRules, &rule->boxElt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// ui boxes
|
// ui boxes
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -518,17 +406,21 @@ ui_box* ui_box_make_str8(str8 string, ui_flags flags)
|
||||||
box->floating[UI_AXIS_Y] = false;
|
box->floating[UI_AXIS_Y] = false;
|
||||||
box->layout = box->parent ? box->parent->layout : (ui_layout){0};
|
box->layout = box->parent ? box->parent->layout : (ui_layout){0};
|
||||||
|
|
||||||
//NOTE: compute style
|
//TODO: inherit style with mask
|
||||||
ui_style_selector selector = UI_STYLE_SEL_NORMAL;
|
box->targetStyle = mem_arena_alloc_type(&ui->frameArena, ui_style);
|
||||||
if(box->hot)
|
if(box->parent)
|
||||||
{
|
{
|
||||||
selector = UI_STYLE_SEL_HOT;
|
*box->targetStyle = *(box->parent->targetStyle);
|
||||||
}
|
}
|
||||||
if(box->active)
|
|
||||||
{
|
//NOTE: set tags, before rules and last box
|
||||||
selector = UI_STYLE_SEL_ACTIVE;
|
box->tags = ui->nextBoxTags;
|
||||||
}
|
ui->nextBoxTags = (list_info){0};
|
||||||
box->targetStyle = ui_collate_style(ui, box->tag, selector);
|
|
||||||
|
box->beforeRules = ui->nextBoxRules;
|
||||||
|
ui->nextBoxRules = (list_info){0};
|
||||||
|
|
||||||
|
ui->lastBox = box;
|
||||||
|
|
||||||
return(box);
|
return(box);
|
||||||
}
|
}
|
||||||
|
@ -560,6 +452,10 @@ ui_box* ui_box_end(void)
|
||||||
DEBUG_ASSERT(box, "box stack underflow");
|
DEBUG_ASSERT(box, "box stack underflow");
|
||||||
|
|
||||||
ui_box_pop();
|
ui_box_pop();
|
||||||
|
|
||||||
|
//NOTE: set last box so that subsequent ui_style_prev() targets this box
|
||||||
|
ui->lastBox = box;
|
||||||
|
|
||||||
return(box);
|
return(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,16 +465,16 @@ void ui_box_set_render_proc(ui_box* box, ui_box_render_proc proc, void* data)
|
||||||
box->renderData = data;
|
box->renderData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_box_set_layout(ui_box* box, ui_axis axis, ui_align alignX, ui_align alignY)
|
|
||||||
{
|
|
||||||
box->layout = (ui_layout){axis, {alignX, alignY}};
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui_box_set_size(ui_box* box, ui_axis axis, ui_size_kind kind, f32 value, f32 strictness)
|
void ui_box_set_size(ui_box* box, ui_axis axis, ui_size_kind kind, f32 value, f32 strictness)
|
||||||
{
|
{
|
||||||
box->targetStyle->size[axis] = (ui_size){kind, value, strictness};
|
box->targetStyle->size[axis] = (ui_size){kind, value, strictness};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ui_box_set_layout(ui_box* box, ui_axis axis, ui_align alignX, ui_align alignY)
|
||||||
|
{
|
||||||
|
box->layout = (ui_layout){axis, {alignX, alignY}};
|
||||||
|
}
|
||||||
|
|
||||||
void ui_box_set_floating(ui_box* box, ui_axis axis, f32 pos)
|
void ui_box_set_floating(ui_box* box, ui_axis axis, f32 pos)
|
||||||
{
|
{
|
||||||
box->floating[axis] = true;
|
box->floating[axis] = true;
|
||||||
|
@ -620,11 +516,6 @@ bool ui_box_hot(ui_box* box)
|
||||||
return(box->hot);
|
return(box->hot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_box_set_tag(ui_box* box, ui_style_tag tag)
|
|
||||||
{
|
|
||||||
box->tag = tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui_sig ui_box_sig(ui_box* box)
|
ui_sig ui_box_sig(ui_box* box)
|
||||||
{
|
{
|
||||||
//NOTE: compute input signals
|
//NOTE: compute input signals
|
||||||
|
@ -757,6 +648,16 @@ void ui_box_compute_styling(ui_context* ui, ui_box* box)
|
||||||
box->computedStyle.size[UI_AXIS_Y] = targetStyle->size[UI_AXIS_Y];
|
box->computedStyle.size[UI_AXIS_Y] = targetStyle->size[UI_AXIS_Y];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(flags & UI_STYLE_ANIMATE_COLOR)
|
||||||
|
{
|
||||||
|
ui_animate_color(ui, &box->computedStyle.color, targetStyle->color, animationTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
box->computedStyle.color = targetStyle->color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(flags & UI_STYLE_ANIMATE_BG_COLOR)
|
if(flags & UI_STYLE_ANIMATE_BG_COLOR)
|
||||||
{
|
{
|
||||||
ui_animate_color(ui, &box->computedStyle.bgColor, targetStyle->bgColor, animationTime);
|
ui_animate_color(ui, &box->computedStyle.bgColor, targetStyle->bgColor, animationTime);
|
||||||
|
@ -766,15 +667,6 @@ void ui_box_compute_styling(ui_context* ui, ui_box* box)
|
||||||
box->computedStyle.bgColor = targetStyle->bgColor;
|
box->computedStyle.bgColor = targetStyle->bgColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(flags & UI_STYLE_ANIMATE_FG_COLOR)
|
|
||||||
{
|
|
||||||
ui_animate_color(ui, &box->computedStyle.fgColor, targetStyle->fgColor, animationTime);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
box->computedStyle.fgColor = targetStyle->fgColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(flags & UI_STYLE_ANIMATE_BORDER_COLOR)
|
if(flags & UI_STYLE_ANIMATE_BORDER_COLOR)
|
||||||
{
|
{
|
||||||
ui_animate_color(ui, &box->computedStyle.borderColor, targetStyle->borderColor, animationTime);
|
ui_animate_color(ui, &box->computedStyle.borderColor, targetStyle->borderColor, animationTime);
|
||||||
|
@ -784,15 +676,6 @@ void ui_box_compute_styling(ui_context* ui, ui_box* box)
|
||||||
box->computedStyle.borderColor = targetStyle->borderColor;
|
box->computedStyle.borderColor = targetStyle->borderColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(flags & UI_STYLE_ANIMATE_FONT_COLOR)
|
|
||||||
{
|
|
||||||
ui_animate_color(ui, &box->computedStyle.fontColor, targetStyle->fontColor, animationTime);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
box->computedStyle.fontColor = targetStyle->fontColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(flags & UI_STYLE_ANIMATE_FONT_SIZE)
|
if(flags & UI_STYLE_ANIMATE_FONT_SIZE)
|
||||||
{
|
{
|
||||||
ui_animate_f32(ui, &box->computedStyle.fontSize, targetStyle->fontSize, animationTime);
|
ui_animate_f32(ui, &box->computedStyle.fontSize, targetStyle->fontSize, animationTime);
|
||||||
|
@ -823,16 +706,158 @@ void ui_box_compute_styling(ui_context* ui, ui_box* box)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_layout_prepass(ui_context* ui, ui_box* box)
|
void ui_apply_style_with_mask(ui_style* dst, ui_style* src, ui_style_mask mask)
|
||||||
{
|
{
|
||||||
|
if(mask & UI_STYLE_SIZE_X)
|
||||||
|
{
|
||||||
|
dst->size[UI_AXIS_X] = src->size[UI_AXIS_X];
|
||||||
|
}
|
||||||
|
if(mask & UI_STYLE_SIZE_Y)
|
||||||
|
{
|
||||||
|
dst->size[UI_AXIS_Y] = src->size[UI_AXIS_Y];
|
||||||
|
}
|
||||||
|
if(mask & UI_STYLE_COLOR)
|
||||||
|
{
|
||||||
|
dst->color = src->color;
|
||||||
|
}
|
||||||
|
if(mask & UI_STYLE_BG_COLOR)
|
||||||
|
{
|
||||||
|
dst->bgColor = src->bgColor;
|
||||||
|
}
|
||||||
|
if(mask & UI_STYLE_BORDER_COLOR)
|
||||||
|
{
|
||||||
|
dst->borderColor = src->borderColor;
|
||||||
|
}
|
||||||
|
if(mask & UI_STYLE_BORDER_SIZE)
|
||||||
|
{
|
||||||
|
dst->borderSize = src->borderSize;
|
||||||
|
}
|
||||||
|
if(mask & UI_STYLE_ROUNDNESS)
|
||||||
|
{
|
||||||
|
dst->roundness = src->roundness;
|
||||||
|
}
|
||||||
|
if(mask & UI_STYLE_FONT)
|
||||||
|
{
|
||||||
|
dst->font = src->font;
|
||||||
|
}
|
||||||
|
if(mask & UI_STYLE_FONT_SIZE)
|
||||||
|
{
|
||||||
|
dst->fontSize = src->fontSize;
|
||||||
|
}
|
||||||
|
if(mask & UI_STYLE_ANIMATION_TIME)
|
||||||
|
{
|
||||||
|
dst->animationTime = src->animationTime;
|
||||||
|
}
|
||||||
|
if(mask & UI_STYLE_ANIMAION_FLAGS)
|
||||||
|
{
|
||||||
|
dst->animationFlags = src->animationFlags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ui_style_selector_match(ui_box* box, ui_selector* selector)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
switch(selector->kind)
|
||||||
|
{
|
||||||
|
case UI_SEL_TEXT:
|
||||||
|
res = !str8_cmp(box->string, selector->text);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SEL_TAG:
|
||||||
|
{
|
||||||
|
for_each_in_list(&box->tags, elt, ui_tag_elt, listElt)
|
||||||
|
{
|
||||||
|
if(elt->tag.hash == selector->tag.hash)
|
||||||
|
{
|
||||||
|
res = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case UI_SEL_HOVER:
|
||||||
|
res = box->hot;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SEL_ACTIVE:
|
||||||
|
res = box->active;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SEL_DRAGGING:
|
||||||
|
res = box->dragging;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UI_SEL_KEY:
|
||||||
|
res = ui_key_equal(box->key, selector->key);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_style_rule_match(ui_context* ui, ui_box* box, ui_style_rule* rule, list_info* buildList, list_info* tmpList)
|
||||||
|
{
|
||||||
|
ui_selector* selector = ListFirstEntry(&rule->pattern.l, ui_selector, listElt);
|
||||||
|
if(ui_style_selector_match(box, selector))
|
||||||
|
{
|
||||||
|
if(!selector->listElt.next)
|
||||||
|
{
|
||||||
|
ui_apply_style_with_mask(box->targetStyle, rule->style, rule->mask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//NOTE create derived rule if there's more than one selector
|
||||||
|
ui_style_rule* derived = mem_arena_alloc_type(&ui->frameArena, ui_style_rule);
|
||||||
|
derived->mask = rule->mask;
|
||||||
|
derived->style = rule->style;
|
||||||
|
derived->pattern.l = (list_info){selector->listElt.next, rule->pattern.l.last};
|
||||||
|
|
||||||
|
ListPush(buildList, &derived->buildElt);
|
||||||
|
ListPush(tmpList, &derived->tmpElt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_styling_prepass(ui_context* ui, ui_box* box, list_info* before, list_info* after)
|
||||||
|
{
|
||||||
|
//NOTE: inherit style from parent
|
||||||
|
if(box->parent)
|
||||||
|
{
|
||||||
|
*box->targetStyle = *box->parent->targetStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
//NOTE: match rules
|
||||||
|
list_info tmpBefore = {0};
|
||||||
|
for_each_in_list(before, rule, ui_style_rule, buildElt)
|
||||||
|
{
|
||||||
|
ui_style_rule_match(ui, box, rule, before, &tmpBefore);
|
||||||
|
}
|
||||||
|
for_each_in_list(&box->beforeRules, rule, ui_style_rule, boxElt)
|
||||||
|
{
|
||||||
|
ListAppend(before, &rule->buildElt);
|
||||||
|
ui_style_rule_match(ui, box, rule, before, &tmpBefore);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_info tmpAfter = {0};
|
||||||
|
for_each_in_list(after, rule, ui_style_rule, buildElt)
|
||||||
|
{
|
||||||
|
ui_style_rule_match(ui, box, rule, after, &tmpAfter);
|
||||||
|
}
|
||||||
|
for_each_in_list(&box->afterRules, rule, ui_style_rule, boxElt)
|
||||||
|
{
|
||||||
|
ListAppend(after, &rule->buildElt);
|
||||||
|
ui_style_rule_match(ui, box, rule, after, &tmpAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
//NOTE: compute static sizes
|
||||||
|
ui_box_compute_styling(ui, box);
|
||||||
|
|
||||||
if(ui_box_hidden(box))
|
if(ui_box_hidden(box))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: compute styling and static sizes
|
|
||||||
ui_box_compute_styling(ui, box);
|
|
||||||
|
|
||||||
ui_style* style = &box->computedStyle;
|
ui_style* style = &box->computedStyle;
|
||||||
|
|
||||||
mp_rect textBox = {};
|
mp_rect textBox = {};
|
||||||
|
@ -859,9 +884,20 @@ void ui_layout_prepass(ui_context* ui, ui_box* box)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//NOTE: descend in children
|
||||||
for_each_in_list(&box->children, child, ui_box, listElt)
|
for_each_in_list(&box->children, child, ui_box, listElt)
|
||||||
{
|
{
|
||||||
ui_layout_prepass(ui, child);
|
ui_styling_prepass(ui, child, before, after);
|
||||||
|
}
|
||||||
|
|
||||||
|
//NOTE: remove temporary rules
|
||||||
|
for_each_in_list(&tmpBefore, rule, ui_style_rule, tmpElt)
|
||||||
|
{
|
||||||
|
ListRemove(before, &rule->buildElt);
|
||||||
|
}
|
||||||
|
for_each_in_list(&tmpAfter, rule, ui_style_rule, tmpElt)
|
||||||
|
{
|
||||||
|
ListRemove(after, &rule->buildElt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1047,7 +1083,10 @@ void ui_layout_find_next_hovered(ui_context* ui, vec2 p)
|
||||||
|
|
||||||
void ui_solve_layout(ui_context* ui)
|
void ui_solve_layout(ui_context* ui)
|
||||||
{
|
{
|
||||||
ui_layout_prepass(ui, ui->root);
|
list_info beforeRules = {0};
|
||||||
|
list_info afterRules = {0};
|
||||||
|
|
||||||
|
ui_styling_prepass(ui, ui->root, &beforeRules, &afterRules);
|
||||||
|
|
||||||
for(int axis=0; axis<UI_AXIS_COUNT; axis++)
|
for(int axis=0; axis<UI_AXIS_COUNT; axis++)
|
||||||
{
|
{
|
||||||
|
@ -1119,12 +1158,6 @@ void ui_draw_box(ui_box* box)
|
||||||
ui_draw_box(child);
|
ui_draw_box(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(box->flags & UI_FLAG_DRAW_FOREGROUND)
|
|
||||||
{
|
|
||||||
mg_set_color(style->fgColor);
|
|
||||||
ui_rectangle_fill(box->rect, style->roundness);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(box->flags & UI_FLAG_DRAW_TEXT)
|
if(box->flags & UI_FLAG_DRAW_TEXT)
|
||||||
{
|
{
|
||||||
mp_rect textBox = mg_text_bounding_box(style->font, style->fontSize, box->string);
|
mp_rect textBox = mg_text_bounding_box(style->font, style->fontSize, box->string);
|
||||||
|
@ -1134,7 +1167,7 @@ void ui_draw_box(ui_box* box)
|
||||||
|
|
||||||
mg_set_font(style->font);
|
mg_set_font(style->font);
|
||||||
mg_set_font_size(style->fontSize);
|
mg_set_font_size(style->fontSize);
|
||||||
mg_set_color(style->fontColor);
|
mg_set_color(style->color);
|
||||||
|
|
||||||
mg_move_to(x, y);
|
mg_move_to(x, y);
|
||||||
mg_text_outlines(box->string);
|
mg_text_outlines(box->string);
|
||||||
|
@ -1191,43 +1224,14 @@ void ui_begin_frame(u32 width, u32 height, ui_style defaultStyle)
|
||||||
ui->lastFrameDuration = time - ui->frameTime;
|
ui->lastFrameDuration = time - ui->frameTime;
|
||||||
ui->frameTime = time;
|
ui->frameTime = time;
|
||||||
|
|
||||||
ui->boxStack = 0;
|
|
||||||
ui->sizeStack[UI_AXIS_X] = 0;
|
|
||||||
ui->sizeStack[UI_AXIS_Y] = 0;
|
|
||||||
ui->bgColorStack = 0;
|
|
||||||
ui->fgColorStack = 0;
|
|
||||||
ui->borderColorStack = 0;
|
|
||||||
ui->fontColorStack = 0;
|
|
||||||
ui->fontStack = 0;
|
|
||||||
ui->fontSizeStack = 0;
|
|
||||||
ui->borderSizeStack = 0;
|
|
||||||
ui->roundnessStack = 0;
|
|
||||||
|
|
||||||
|
|
||||||
ui->clipStack = 0;
|
ui->clipStack = 0;
|
||||||
ui->z = 0;
|
ui->z = 0;
|
||||||
|
|
||||||
for(int i=0; i<UI_AXIS_COUNT; i++)
|
// ui_push_size(UI_AXIS_X, UI_SIZE_PIXELS, width, 0);
|
||||||
{
|
// ui_push_size(UI_AXIS_Y, UI_SIZE_PIXELS, height, 0);
|
||||||
ui_push_size(i,
|
|
||||||
defaultStyle.size[i].kind,
|
|
||||||
defaultStyle.size[i].value,
|
|
||||||
defaultStyle.size[i].strictness);
|
|
||||||
}
|
|
||||||
ui_push_bg_color(defaultStyle.bgColor);
|
|
||||||
ui_push_fg_color(defaultStyle.fgColor);
|
|
||||||
ui_push_border_color(defaultStyle.borderColor);
|
|
||||||
ui_push_font_color(defaultStyle.fontColor);
|
|
||||||
ui_push_font(defaultStyle.font);
|
|
||||||
ui_push_font_size(defaultStyle.fontSize);
|
|
||||||
ui_push_border_size(defaultStyle.borderSize);
|
|
||||||
ui_push_roundness(defaultStyle.roundness);
|
|
||||||
|
|
||||||
|
|
||||||
ui_push_size(UI_AXIS_X, UI_SIZE_PIXELS, width, 0);
|
|
||||||
ui_push_size(UI_AXIS_Y, UI_SIZE_PIXELS, height, 0);
|
|
||||||
|
|
||||||
ui->root = ui_box_begin("_root_", 0);
|
ui->root = ui_box_begin("_root_", 0);
|
||||||
|
*ui->root->targetStyle = defaultStyle;
|
||||||
|
|
||||||
ui_box* contents = ui_box_make("_contents_", 0);
|
ui_box* contents = ui_box_make("_contents_", 0);
|
||||||
ui_box_set_floating(contents, UI_AXIS_X, 0);
|
ui_box_set_floating(contents, UI_AXIS_X, 0);
|
||||||
|
@ -1238,8 +1242,11 @@ void ui_begin_frame(u32 width, u32 height, ui_style defaultStyle)
|
||||||
ui_box_set_floating(ui->overlay, UI_AXIS_X, 0);
|
ui_box_set_floating(ui->overlay, UI_AXIS_X, 0);
|
||||||
ui_box_set_floating(ui->overlay, UI_AXIS_Y, 0);
|
ui_box_set_floating(ui->overlay, UI_AXIS_Y, 0);
|
||||||
|
|
||||||
ui_pop_size(UI_AXIS_X);
|
// ui_pop_size(UI_AXIS_X);
|
||||||
ui_pop_size(UI_AXIS_Y);
|
// ui_pop_size(UI_AXIS_Y);
|
||||||
|
|
||||||
|
ui->nextBoxRules = (list_info){0};
|
||||||
|
ui->nextBoxTags = (list_info){0};
|
||||||
|
|
||||||
ui_box_push(contents);
|
ui_box_push(contents);
|
||||||
}
|
}
|
||||||
|
@ -1329,7 +1336,9 @@ ui_sig ui_button_str8(str8 label)
|
||||||
| UI_FLAG_ACTIVE_ANIMATION;
|
| UI_FLAG_ACTIVE_ANIMATION;
|
||||||
|
|
||||||
ui_box* box = ui_box_make_str8(label, flags);
|
ui_box* box = ui_box_make_str8(label, flags);
|
||||||
ui_box_set_tag(box, UI_STYLE_TAG_BUTTON);
|
|
||||||
|
//TODO
|
||||||
|
// ui_box_set_tag(box, UI_STYLE_TAG_BUTTON);
|
||||||
ui_sig sig = ui_box_sig(box);
|
ui_sig sig = ui_box_sig(box);
|
||||||
|
|
||||||
if(sig.hovering)
|
if(sig.hovering)
|
||||||
|
@ -1367,7 +1376,7 @@ ui_box* ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue)
|
||||||
f32 roundness = 0.5*frame->rect.c[2+secondAxis];
|
f32 roundness = 0.5*frame->rect.c[2+secondAxis];
|
||||||
f32 animationTime = 0.5;
|
f32 animationTime = 0.5;
|
||||||
|
|
||||||
ui_push_bg_color((mg_color){0, 0, 0, 0});
|
/* ui_push_bg_color((mg_color){0, 0, 0, 0});
|
||||||
ui_push_fg_color((mg_color){0, 0, 0, 0});
|
ui_push_fg_color((mg_color){0, 0, 0, 0});
|
||||||
ui_push_roundness(roundness);
|
ui_push_roundness(roundness);
|
||||||
|
|
||||||
|
@ -1376,7 +1385,7 @@ ui_box* ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue)
|
||||||
ui_push_roundness_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_HOT|UI_STYLE_SEL_ACTIVE, roundness);
|
ui_push_roundness_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_HOT|UI_STYLE_SEL_ACTIVE, roundness);
|
||||||
ui_push_animation_time_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_ANY, 1.);
|
ui_push_animation_time_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_ANY, 1.);
|
||||||
ui_push_animation_flags_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_ANY, UI_STYLE_ANIMATE_BG_COLOR|UI_STYLE_ANIMATE_FG_COLOR);
|
ui_push_animation_flags_ext(UI_STYLE_TAG_ANY, UI_STYLE_SEL_ANY, UI_STYLE_ANIMATE_BG_COLOR|UI_STYLE_ANIMATE_FG_COLOR);
|
||||||
|
*/
|
||||||
ui_flags trackFlags = UI_FLAG_CLIP
|
ui_flags trackFlags = UI_FLAG_CLIP
|
||||||
| UI_FLAG_DRAW_BACKGROUND
|
| UI_FLAG_DRAW_BACKGROUND
|
||||||
| UI_FLAG_HOT_ANIMATION
|
| UI_FLAG_HOT_ANIMATION
|
||||||
|
@ -1409,7 +1418,7 @@ ui_box* ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue)
|
||||||
ui_box_set_size(afterSpacer, secondAxis, UI_SIZE_PARENT_RATIO, 1., 0);
|
ui_box_set_size(afterSpacer, secondAxis, UI_SIZE_PARENT_RATIO, 1., 0);
|
||||||
|
|
||||||
ui_box_end();
|
ui_box_end();
|
||||||
|
/*
|
||||||
ui_pop_bg_color();
|
ui_pop_bg_color();
|
||||||
ui_pop_fg_color();
|
ui_pop_fg_color();
|
||||||
ui_pop_roundness();
|
ui_pop_roundness();
|
||||||
|
@ -1418,7 +1427,7 @@ ui_box* ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue)
|
||||||
ui_pop_roundness();
|
ui_pop_roundness();
|
||||||
ui_pop_animation_time();
|
ui_pop_animation_time();
|
||||||
ui_pop_animation_flags();
|
ui_pop_animation_flags();
|
||||||
|
*/
|
||||||
//NOTE: interaction
|
//NOTE: interaction
|
||||||
ui_sig thumbSig = ui_box_sig(thumb);
|
ui_sig thumbSig = ui_box_sig(thumb);
|
||||||
if(thumbSig.dragging)
|
if(thumbSig.dragging)
|
||||||
|
@ -1579,10 +1588,10 @@ void ui_menu_bar_begin(const char* name)
|
||||||
ui_box_set_size(bar, UI_AXIS_X, UI_SIZE_PARENT_RATIO, 1., 0);
|
ui_box_set_size(bar, UI_AXIS_X, UI_SIZE_PARENT_RATIO, 1., 0);
|
||||||
ui_box_set_size(bar, UI_AXIS_Y, UI_SIZE_CHILDREN, 0, 0);
|
ui_box_set_size(bar, UI_AXIS_Y, UI_SIZE_CHILDREN, 0, 0);
|
||||||
ui_box_set_layout(bar, UI_AXIS_X, UI_ALIGN_START, UI_ALIGN_START);
|
ui_box_set_layout(bar, UI_AXIS_X, UI_ALIGN_START, UI_ALIGN_START);
|
||||||
|
/*
|
||||||
ui_push_size(UI_AXIS_X, UI_SIZE_TEXT, 0, 0);
|
ui_push_size(UI_AXIS_X, UI_SIZE_TEXT, 0, 0);
|
||||||
ui_push_size(UI_AXIS_Y, UI_SIZE_TEXT, 0, 0);
|
ui_push_size(UI_AXIS_Y, UI_SIZE_TEXT, 0, 0);
|
||||||
|
*/
|
||||||
ui_sig sig = ui_box_sig(bar);
|
ui_sig sig = ui_box_sig(bar);
|
||||||
if(!sig.hovering && mp_mouse_released(MP_MOUSE_LEFT))
|
if(!sig.hovering && mp_mouse_released(MP_MOUSE_LEFT))
|
||||||
{
|
{
|
||||||
|
@ -1592,8 +1601,10 @@ void ui_menu_bar_begin(const char* name)
|
||||||
|
|
||||||
void ui_menu_bar_end(void)
|
void ui_menu_bar_end(void)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
ui_pop_size(UI_AXIS_X);
|
ui_pop_size(UI_AXIS_X);
|
||||||
ui_pop_size(UI_AXIS_Y);
|
ui_pop_size(UI_AXIS_Y);
|
||||||
|
*/
|
||||||
ui_box_end(); // menu bar
|
ui_box_end(); // menu bar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2057,7 +2068,7 @@ void ui_text_box_render(ui_box* box, void* data)
|
||||||
|
|
||||||
mg_set_font(style->font);
|
mg_set_font(style->font);
|
||||||
mg_set_font_size(style->fontSize);
|
mg_set_font_size(style->fontSize);
|
||||||
mg_set_color(style->fontColor);
|
mg_set_color(style->color);
|
||||||
|
|
||||||
mg_move_to(textX, textY);
|
mg_move_to(textX, textY);
|
||||||
mg_codepoints_outlines(beforeSelect);
|
mg_codepoints_outlines(beforeSelect);
|
||||||
|
@ -2067,7 +2078,7 @@ void ui_text_box_render(ui_box* box, void* data)
|
||||||
mg_codepoints_outlines(select);
|
mg_codepoints_outlines(select);
|
||||||
mg_fill();
|
mg_fill();
|
||||||
|
|
||||||
mg_set_color(style->fontColor);
|
mg_set_color(style->color);
|
||||||
mg_codepoints_outlines(afterSelect);
|
mg_codepoints_outlines(afterSelect);
|
||||||
mg_fill();
|
mg_fill();
|
||||||
}
|
}
|
||||||
|
@ -2082,7 +2093,7 @@ void ui_text_box_render(ui_box* box, void* data)
|
||||||
}
|
}
|
||||||
mg_set_font(style->font);
|
mg_set_font(style->font);
|
||||||
mg_set_font_size(style->fontSize);
|
mg_set_font_size(style->fontSize);
|
||||||
mg_set_color(style->fontColor);
|
mg_set_color(style->color);
|
||||||
|
|
||||||
mg_move_to(textX, textY);
|
mg_move_to(textX, textY);
|
||||||
mg_codepoints_outlines(codepoints);
|
mg_codepoints_outlines(codepoints);
|
||||||
|
@ -2093,7 +2104,7 @@ void ui_text_box_render(ui_box* box, void* data)
|
||||||
{
|
{
|
||||||
mg_set_font(style->font);
|
mg_set_font(style->font);
|
||||||
mg_set_font_size(style->fontSize);
|
mg_set_font_size(style->fontSize);
|
||||||
mg_set_color(style->fontColor);
|
mg_set_color(style->color);
|
||||||
|
|
||||||
mg_move_to(textX, textY);
|
mg_move_to(textX, textY);
|
||||||
mg_codepoints_outlines(codepoints);
|
mg_codepoints_outlines(codepoints);
|
||||||
|
|
145
src/ui.h
145
src/ui.h
|
@ -75,34 +75,23 @@ typedef struct ui_size
|
||||||
f32 strictness;
|
f32 strictness;
|
||||||
} ui_size;
|
} ui_size;
|
||||||
|
|
||||||
typedef enum { UI_STYLE_SEL_NORMAL = 1<<0,
|
|
||||||
UI_STYLE_SEL_HOT = 1<<1,
|
|
||||||
UI_STYLE_SEL_ACTIVE = 1<<2,
|
|
||||||
UI_STYLE_SEL_ANY = UI_STYLE_SEL_NORMAL|UI_STYLE_SEL_HOT|UI_STYLE_SEL_ACTIVE,
|
|
||||||
} ui_style_selector;
|
|
||||||
|
|
||||||
typedef u32 ui_style_tag;
|
|
||||||
#define UI_STYLE_TAG_ANY ((ui_style_tag)0)
|
|
||||||
|
|
||||||
typedef enum { UI_STYLE_ANIMATE_SIZE_X = 1<<1,
|
typedef enum { UI_STYLE_ANIMATE_SIZE_X = 1<<1,
|
||||||
UI_STYLE_ANIMATE_SIZE_Y = 1<<2,
|
UI_STYLE_ANIMATE_SIZE_Y = 1<<2,
|
||||||
UI_STYLE_ANIMATE_BG_COLOR = 1<<3,
|
UI_STYLE_ANIMATE_COLOR = 1<<3,
|
||||||
UI_STYLE_ANIMATE_FG_COLOR = 1<<4,
|
UI_STYLE_ANIMATE_BG_COLOR = 1<<4,
|
||||||
UI_STYLE_ANIMATE_BORDER_COLOR = 1<<5,
|
UI_STYLE_ANIMATE_BORDER_COLOR = 1<<5,
|
||||||
UI_STYLE_ANIMATE_FONT_COLOR = 1<<6,
|
UI_STYLE_ANIMATE_BORDER_SIZE = 1<<6,
|
||||||
UI_STYLE_ANIMATE_FONT_SIZE = 1<<7,
|
UI_STYLE_ANIMATE_FONT_SIZE = 1<<7,
|
||||||
UI_STYLE_ANIMATE_BORDER_SIZE = 1<<8,
|
UI_STYLE_ANIMATE_ROUNDNESS = 1<<8,
|
||||||
UI_STYLE_ANIMATE_ROUNDNESS = 1<<9,
|
UI_STYLE_ANIMATE_POS = 1<<9,
|
||||||
UI_STYLE_ANIMATE_POS = 1<<10,
|
|
||||||
} ui_style_animation_flags;
|
} ui_style_animation_flags;
|
||||||
|
|
||||||
typedef struct ui_style
|
typedef struct ui_style
|
||||||
{
|
{
|
||||||
ui_size size[UI_AXIS_COUNT];
|
ui_size size[UI_AXIS_COUNT];
|
||||||
|
mg_color color;
|
||||||
mg_color bgColor;
|
mg_color bgColor;
|
||||||
mg_color fgColor;
|
|
||||||
mg_color borderColor;
|
mg_color borderColor;
|
||||||
mg_color fontColor;
|
|
||||||
mg_font font;
|
mg_font font;
|
||||||
f32 fontSize;
|
f32 fontSize;
|
||||||
f32 borderSize;
|
f32 borderSize;
|
||||||
|
@ -111,6 +100,64 @@ typedef struct ui_style
|
||||||
ui_style_animation_flags animationFlags;
|
ui_style_animation_flags animationFlags;
|
||||||
} ui_style;
|
} ui_style;
|
||||||
|
|
||||||
|
typedef u64 ui_style_mask;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
UI_STYLE_NONE = 0,
|
||||||
|
UI_STYLE_SIZE_X = 1<<1,
|
||||||
|
UI_STYLE_SIZE_Y = 1<<2,
|
||||||
|
UI_STYLE_COLOR = 1<<3,
|
||||||
|
UI_STYLE_BG_COLOR = 1<<4,
|
||||||
|
UI_STYLE_BORDER_COLOR = 1<<6,
|
||||||
|
UI_STYLE_BORDER_SIZE = 1<<7,
|
||||||
|
UI_STYLE_ROUNDNESS = 1<<8,
|
||||||
|
UI_STYLE_FONT = 1<<9,
|
||||||
|
UI_STYLE_FONT_SIZE = 1<<10,
|
||||||
|
UI_STYLE_ANIMATION_TIME = 1<<11,
|
||||||
|
UI_STYLE_ANIMAION_FLAGS = 1<<12,
|
||||||
|
//...
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ui_tag { u64 hash; } ui_tag;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
UI_SEL_TEXT,
|
||||||
|
UI_SEL_TAG,
|
||||||
|
UI_SEL_HOVER,
|
||||||
|
UI_SEL_ACTIVE,
|
||||||
|
UI_SEL_DRAGGING,
|
||||||
|
UI_SEL_KEY,
|
||||||
|
//...
|
||||||
|
} ui_selector_kind;
|
||||||
|
|
||||||
|
typedef struct ui_selector
|
||||||
|
{
|
||||||
|
list_elt listElt;
|
||||||
|
ui_selector_kind kind;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
str8 text;
|
||||||
|
ui_key key;
|
||||||
|
ui_tag tag;
|
||||||
|
//...
|
||||||
|
};
|
||||||
|
} ui_selector;
|
||||||
|
|
||||||
|
typedef struct ui_pattern { list_info l; } ui_pattern;
|
||||||
|
|
||||||
|
typedef struct ui_style_rule
|
||||||
|
{
|
||||||
|
list_elt boxElt;
|
||||||
|
list_elt buildElt;
|
||||||
|
list_elt tmpElt;
|
||||||
|
|
||||||
|
ui_pattern pattern;
|
||||||
|
ui_style_mask mask;
|
||||||
|
ui_style* style;
|
||||||
|
} ui_style_rule;
|
||||||
|
|
||||||
typedef struct ui_box ui_box;
|
typedef struct ui_box ui_box;
|
||||||
|
|
||||||
typedef struct ui_sig
|
typedef struct ui_sig
|
||||||
|
@ -149,12 +196,16 @@ struct ui_box
|
||||||
// builder-provided info
|
// builder-provided info
|
||||||
ui_flags flags;
|
ui_flags flags;
|
||||||
str8 string;
|
str8 string;
|
||||||
|
list_info tags;
|
||||||
|
|
||||||
// styling and layout
|
|
||||||
ui_box_render_proc renderProc;
|
ui_box_render_proc renderProc;
|
||||||
void* renderData;
|
void* renderData;
|
||||||
|
|
||||||
ui_style_tag tag;
|
// styling and layout
|
||||||
|
list_info beforeRules;
|
||||||
|
list_info afterRules;
|
||||||
|
|
||||||
|
//ui_style_tag tag;
|
||||||
ui_style* targetStyle;
|
ui_style* targetStyle;
|
||||||
ui_style computedStyle;
|
ui_style computedStyle;
|
||||||
u32 z;
|
u32 z;
|
||||||
|
@ -190,6 +241,8 @@ void ui_set_context(ui_context* context);
|
||||||
|
|
||||||
void ui_begin_frame(u32 width, u32 height, ui_style defaultStyle);
|
void ui_begin_frame(u32 width, u32 height, ui_style defaultStyle);
|
||||||
void ui_end_frame(void);
|
void ui_end_frame(void);
|
||||||
|
#define ui_frame(width, height, defaultStyle) defer_loop(ui_begin_frame(width, height, defaultStyle), ui_end_frame())
|
||||||
|
|
||||||
void ui_draw(void);
|
void ui_draw(void);
|
||||||
|
|
||||||
ui_box* ui_box_lookup(const char* string);
|
ui_box* ui_box_lookup(const char* string);
|
||||||
|
@ -205,6 +258,10 @@ void ui_box_push(ui_box* box);
|
||||||
void ui_box_pop(void);
|
void ui_box_pop(void);
|
||||||
ui_box* ui_box_top(void);
|
ui_box* ui_box_top(void);
|
||||||
|
|
||||||
|
ui_tag ui_tag_make(str8 string);
|
||||||
|
void ui_tag_box(ui_box* box, str8 string);
|
||||||
|
void ui_tag_next(str8 string);
|
||||||
|
|
||||||
bool ui_box_closed(ui_box* box);
|
bool ui_box_closed(ui_box* box);
|
||||||
void ui_box_set_closed(ui_box* box, bool closed);
|
void ui_box_set_closed(ui_box* box, bool closed);
|
||||||
|
|
||||||
|
@ -219,46 +276,16 @@ void ui_box_set_render_proc(ui_box* box, ui_box_render_proc proc, void* data);
|
||||||
void ui_box_set_layout(ui_box* box, ui_axis axis, ui_align alignX, ui_align alignY);
|
void ui_box_set_layout(ui_box* box, ui_axis axis, ui_align alignX, ui_align alignY);
|
||||||
void ui_box_set_size(ui_box* box, ui_axis axis, ui_size_kind kind, f32 value, f32 strictness);
|
void ui_box_set_size(ui_box* box, ui_axis axis, ui_size_kind kind, f32 value, f32 strictness);
|
||||||
void ui_box_set_floating(ui_box* box, ui_axis axis, f32 pos);
|
void ui_box_set_floating(ui_box* box, ui_axis axis, f32 pos);
|
||||||
void ui_box_set_style_selector(ui_box* box, ui_style_selector selector);
|
//void ui_box_set_style_selector(ui_box* box, ui_style_selector selector);
|
||||||
|
|
||||||
ui_sig ui_box_sig(ui_box* box);
|
ui_sig ui_box_sig(ui_box* box);
|
||||||
|
|
||||||
void ui_push_size(ui_axis axis, ui_size_kind kind, f32 value, f32 strictness);
|
//NOTE: styling API
|
||||||
void ui_push_size_ext(ui_style_tag tag, ui_style_selector selector, ui_axis axis, ui_size_kind kind, f32 value, f32 strictness);
|
//WARN: You can use a pattern in multiple rules, but be aware that a pattern is references an underlying list of selectors,
|
||||||
void ui_pop_size(ui_axis axis);
|
// hence pushing to a pattern also modifies rules in which the pattern was previously used!
|
||||||
|
void ui_pattern_push(mem_arena* arena, ui_pattern* pattern, ui_selector selector);
|
||||||
void ui_push_bg_color(mg_color color);
|
void ui_style_next(ui_pattern pattern, ui_style* style, ui_style_mask mask);
|
||||||
void ui_push_fg_color(mg_color color);
|
void ui_style_prev(ui_pattern pattern, ui_style* style, ui_style_mask mask);
|
||||||
void ui_push_font(mg_font font);
|
|
||||||
void ui_push_font_size(f32 size);
|
|
||||||
void ui_push_font_color(mg_color color);
|
|
||||||
void ui_push_border_size(f32 size);
|
|
||||||
void ui_push_border_color(mg_color color);
|
|
||||||
void ui_push_roundness(f32 roundness);
|
|
||||||
void ui_push_animation_time(f32 time);
|
|
||||||
void ui_push_animation_flags(u32 flags);
|
|
||||||
|
|
||||||
void ui_push_bg_color_ext(ui_style_tag tag, ui_style_selector selector, mg_color color);
|
|
||||||
void ui_push_fg_color_ext(ui_style_tag tag, ui_style_selector selector, mg_color color);
|
|
||||||
void ui_push_font_ext(ui_style_tag tag, ui_style_selector selector, mg_font font);
|
|
||||||
void ui_push_font_size_ext(ui_style_tag tag, ui_style_selector selector, f32 size);
|
|
||||||
void ui_push_font_color_ext(ui_style_tag tag, ui_style_selector selector, mg_color color);
|
|
||||||
void ui_push_border_size_ext(ui_style_tag tag, ui_style_selector selector, f32 size);
|
|
||||||
void ui_push_border_color_ext(ui_style_tag tag, ui_style_selector selector, mg_color color);
|
|
||||||
void ui_push_roundness_ext(ui_style_tag tag, ui_style_selector selector, f32 roundness);
|
|
||||||
void ui_push_animation_time_ext(ui_style_tag tag, ui_style_selector selector, f32 time);
|
|
||||||
void ui_push_animation_flags_ext(ui_style_tag tag, ui_style_selector selector, u32 flags);
|
|
||||||
|
|
||||||
void ui_pop_bg_color(void);
|
|
||||||
void ui_pop_fg_color(void);
|
|
||||||
void ui_pop_font(void);
|
|
||||||
void ui_pop_font_size(void);
|
|
||||||
void ui_pop_font_color(void);
|
|
||||||
void ui_pop_border_size(void);
|
|
||||||
void ui_pop_border_color(void);
|
|
||||||
void ui_pop_roundness(void);
|
|
||||||
void ui_pop_animation_time(void);
|
|
||||||
void ui_pop_animation_flags(void);
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// Basic widget helpers
|
// Basic widget helpers
|
||||||
|
@ -306,6 +333,12 @@ typedef struct ui_text_box_result
|
||||||
|
|
||||||
ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text);
|
ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text);
|
||||||
|
|
||||||
|
////////////////////////////////////////// WIP styling //////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue