some layout work
This commit is contained in:
parent
59acce1150
commit
d6358944ac
5
cache.c
5
cache.c
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
// hash table (id -> cache index)
|
// hash table (id -> cache index)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UgId id;
|
UgId id;
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
} IdElem;
|
} IdElem;
|
||||||
|
|
||||||
@ -204,9 +204,8 @@ UgElem *ug_cache_insert_at(UgElemCache *cache, const UgElem *g, uint32_t index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert an element in the cache
|
// Insert an element in the cache
|
||||||
UgElem *ug_cache_insert(UgElemCache *cache, const UgElem *g, uint32_t *index)
|
UgElem *ug_cache_insert_new(UgElemCache *cache, const UgElem *g, uint32_t *index)
|
||||||
{
|
{
|
||||||
*index = ug_cache_get_free_spot(cache);
|
*index = ug_cache_get_free_spot(cache);
|
||||||
return ug_cache_insert_at(cache, g, *index);
|
return ug_cache_insert_at(cache, g, *index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
318
ugui.c
318
ugui.c
@ -17,6 +17,13 @@
|
|||||||
#define DIV_FILL \
|
#define DIV_FILL \
|
||||||
(UgRect) { .x = 0, .y = 0, .w = 0, .h = 0 }
|
(UgRect) { .x = 0, .y = 0, .w = 0, .h = 0 }
|
||||||
|
|
||||||
|
#define MARK() \
|
||||||
|
do { \
|
||||||
|
printf("lmao\n"); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define FTEST(e, f) ((e)->flags & (f))
|
||||||
|
|
||||||
#define STACK_STEP 10
|
#define STACK_STEP 10
|
||||||
#define MAX_ELEMS 128
|
#define MAX_ELEMS 128
|
||||||
#define MAX_CMDS 256
|
#define MAX_CMDS 256
|
||||||
@ -162,9 +169,12 @@ int ug_div_begin(UgCtx *ctx, const char *label, UgRect div);
|
|||||||
int ug_div_end(UgCtx *ctx);
|
int ug_div_end(UgCtx *ctx);
|
||||||
int ug_input_window_size(UgCtx *ctx, int width, int height);
|
int ug_input_window_size(UgCtx *ctx, int width, int height);
|
||||||
UgId djb2(const char *str);
|
UgId djb2(const char *str);
|
||||||
|
UgId FNV_1a(const char *str);
|
||||||
|
|
||||||
int ug_button(UgCtx *ctx, const char *label, UgRect size);
|
int ug_button(UgCtx *ctx, const char *label, UgRect size);
|
||||||
|
|
||||||
|
UgRect position_element(UgCtx *ctx, UgElem *parent, UgRect rect);
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
UgCtx ctx;
|
UgCtx ctx;
|
||||||
@ -190,28 +200,43 @@ int main(void)
|
|||||||
|
|
||||||
// main div, fill the whole window
|
// main div, fill the whole window
|
||||||
ug_div_begin(&ctx, "main", DIV_FILL);
|
ug_div_begin(&ctx, "main", DIV_FILL);
|
||||||
|
{
|
||||||
ug_button(&ctx, "button0", (UgRect) {.w = 100, .h = 16});
|
ug_button(
|
||||||
|
&ctx,
|
||||||
|
"batt342353453452wrwea",
|
||||||
|
(UgRect) {.y = 100, .x = 130, .w = 100, .h = 16}
|
||||||
|
);
|
||||||
|
ug_button(
|
||||||
|
&ctx,
|
||||||
|
"arieasd3ree2234tast",
|
||||||
|
(UgRect) {.x = 10, .w = 30, .h = 30}
|
||||||
|
);
|
||||||
|
ug_button(
|
||||||
|
&ctx,
|
||||||
|
"bughsdfsfdstton2",
|
||||||
|
(UgRect) {.x = 10, .w = 30, .h = 30}
|
||||||
|
);
|
||||||
|
}
|
||||||
ug_div_end(&ctx);
|
ug_div_end(&ctx);
|
||||||
|
|
||||||
ug_frame_end(&ctx);
|
ug_frame_end(&ctx);
|
||||||
|
|
||||||
// drawing
|
// drawing
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(BLACK);
|
// ClearBackground(BLACK);
|
||||||
|
|
||||||
|
printf("----- Draw Begin -----\n");
|
||||||
Color c;
|
Color c;
|
||||||
for (UgCmd cmd; ug_fifo_dequeue(&ctx.fifo, &cmd) >= 0;) {
|
for (UgCmd cmd; ug_fifo_dequeue(&ctx.fifo, &cmd) >= 0;) {
|
||||||
switch (cmd.type) {
|
switch (cmd.type) {
|
||||||
case CMD_RECT:
|
case CMD_RECT:
|
||||||
// printf(
|
printf(
|
||||||
// "rect x=%d y=%d w=%d h=%d\n",
|
"draw rect x=%d y=%d w=%d h=%d\n",
|
||||||
// cmd.rect.rect.x,
|
cmd.rect.rect.x,
|
||||||
// cmd.rect.rect.y,
|
cmd.rect.rect.y,
|
||||||
// cmd.rect.rect.w,
|
cmd.rect.rect.w,
|
||||||
// cmd.rect.rect.h
|
cmd.rect.rect.h
|
||||||
//);
|
);
|
||||||
c = (Color) {
|
c = (Color) {
|
||||||
.r = cmd.rect.color.r,
|
.r = cmd.rect.color.r,
|
||||||
.g = cmd.rect.color.g,
|
.g = cmd.rect.color.g,
|
||||||
@ -231,6 +256,7 @@ int main(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
printf("----- Draw End -----\n\n");
|
||||||
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
|
|
||||||
@ -243,6 +269,24 @@ int main(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// search the element of the corresponding id in the cache, if no element is found
|
||||||
|
// insert a new one of that id. Return the pointer to the element
|
||||||
|
int search_or_insert(UgCtx *ctx, UgElem **elem, UgId id)
|
||||||
|
{
|
||||||
|
int is_new = 0;
|
||||||
|
uint32_t cache_idx;
|
||||||
|
|
||||||
|
UgElem *c_elem = ug_cache_search(&ctx->cache, id);
|
||||||
|
if (c_elem == NULL) {
|
||||||
|
UgElem tmp = {.id = id};
|
||||||
|
c_elem = ug_cache_insert_new(&ctx->cache, &tmp, &cache_idx);
|
||||||
|
is_new = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*elem = c_elem;
|
||||||
|
return is_new;
|
||||||
|
}
|
||||||
|
|
||||||
int ug_init(UgCtx *ctx)
|
int ug_init(UgCtx *ctx)
|
||||||
{
|
{
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
@ -276,9 +320,14 @@ void print_tree(UgCtx *ctx)
|
|||||||
{
|
{
|
||||||
printf("ctx->tree: [");
|
printf("ctx->tree: [");
|
||||||
for (int c = -1, x; (x = ug_tree_level_order_it(&ctx->tree, 0, &c)) != -1;) {
|
for (int c = -1, x; (x = ug_tree_level_order_it(&ctx->tree, 0, &c)) != -1;) {
|
||||||
printf("%d, ", x);
|
printf(
|
||||||
|
"[%d:%d,%.4lx], ",
|
||||||
|
x,
|
||||||
|
ug_tree_parentof(&ctx->tree, x),
|
||||||
|
ug_tree_get(&ctx->tree, x) & 0xffff
|
||||||
|
);
|
||||||
}
|
}
|
||||||
printf("-1]\n");
|
printf("[-1]]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int ug_frame_begin(UgCtx *ctx)
|
int ug_frame_begin(UgCtx *ctx)
|
||||||
@ -315,8 +364,12 @@ int ug_frame_begin(UgCtx *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: check errors
|
// FIXME: check errors
|
||||||
uint32_t cache_idx;
|
UgElem *c_elem;
|
||||||
ug_cache_insert(&ctx->cache, &root, &cache_idx);
|
int is_new = search_or_insert(ctx, &c_elem, root.id);
|
||||||
|
if (is_new || FTEST(&root, ELEM_UPDATED)) {
|
||||||
|
*c_elem = root;
|
||||||
|
}
|
||||||
|
|
||||||
ctx->div_using = ug_tree_add(&ctx->tree, root.id, 0);
|
ctx->div_using = ug_tree_add(&ctx->tree, root.id, 0);
|
||||||
|
|
||||||
if (ctx->div_using < 0) {
|
if (ctx->div_using < 0) {
|
||||||
@ -329,6 +382,8 @@ int ug_frame_begin(UgCtx *ctx)
|
|||||||
// The root element does not push anything to the stack
|
// The root element does not push anything to the stack
|
||||||
// TODO: add a background color taken from a theme or config
|
// TODO: add a background color taken from a theme or config
|
||||||
|
|
||||||
|
printf("##### Frame Begin #####\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,6 +399,7 @@ int ug_frame_end(UgCtx *ctx)
|
|||||||
// 2. clear input fields
|
// 2. clear input fields
|
||||||
ctx->input.flags = 0;
|
ctx->input.flags = 0;
|
||||||
|
|
||||||
|
printf("##### Frame End #####\n\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,6 +423,20 @@ int ug_input_window_size(UgCtx *ctx, int width, int height)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UgId FNV_1a(const char *str)
|
||||||
|
{
|
||||||
|
const uint64_t fnv_off = 0xcbf29ce484222325;
|
||||||
|
const uint64_t fnv_prime = 0x100000001b3;
|
||||||
|
|
||||||
|
uint64_t hash = fnv_off;
|
||||||
|
for (uint32_t c; (c = str[0]) != 0; str++) {
|
||||||
|
hash ^= c;
|
||||||
|
hash *= fnv_prime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
UgId djb2(const char *str)
|
UgId djb2(const char *str)
|
||||||
{
|
{
|
||||||
uint64_t hash = 5381;
|
uint64_t hash = 5381;
|
||||||
@ -385,98 +455,55 @@ int ug_div_begin(UgCtx *ctx, const char *label, UgRect div)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
UgId id = djb2(label);
|
UgId id = FNV_1a(label);
|
||||||
|
|
||||||
// TODO: do layouting if the element is new or the parent has updated
|
UgElem *c_elem;
|
||||||
int is_new_elem = 0;
|
int is_new = search_or_insert(ctx, &c_elem, id);
|
||||||
|
|
||||||
// add the element if it does not exist
|
// FIXME: why save the id in the tree and not something more direct like
|
||||||
UgElem *c_elem = ug_cache_search(&ctx->cache, id);
|
// the element pointer or the index into the cache vector?
|
||||||
if (c_elem == NULL) {
|
int div_node = ug_tree_add(&ctx->tree, id, ctx->div_using);
|
||||||
UgElem elem = {0};
|
if (div_node < 0) {
|
||||||
uint32_t c_idx;
|
// do something
|
||||||
c_elem = ug_cache_insert(&ctx->cache, &elem, &c_idx);
|
printf("Error adding to tree\n");
|
||||||
is_new_elem = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// take a reference to the parent
|
// take a reference to the parent
|
||||||
// FIXME: if the tree held pointers to the elements then no more
|
// FIXME: if the tree held pointers to the elements then no more
|
||||||
// redundant cache search
|
// redundant cache search
|
||||||
UgId parent_id = ctx->tree.vector[ctx->div_using];
|
UgId parent_id = ug_tree_get(&ctx->tree, ctx->div_using);
|
||||||
UgElem *parent = ug_cache_search(&ctx->cache, parent_id);
|
UgElem *parent = ug_cache_search(&ctx->cache, parent_id);
|
||||||
if (parent == NULL) {
|
if (parent == NULL) {
|
||||||
// Error, did you forget to do frame_begin()?
|
// Error, did you forget to do frame_begin()?
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: why save the id in the tree and not something more direct like
|
print_tree(ctx);
|
||||||
// the element pointer or the index into the cache vector?
|
|
||||||
int div_node = ug_tree_add(&ctx->tree, c_elem->id, ctx->div_using);
|
// Use the current div
|
||||||
if (div_node < 0) {
|
|
||||||
// do something
|
|
||||||
printf("Error adding to tree\n");
|
|
||||||
}
|
|
||||||
ctx->div_using = div_node;
|
ctx->div_using = div_node;
|
||||||
|
|
||||||
// print_tree(ctx);
|
// 1. Fill the element fields
|
||||||
|
// this resets the flags
|
||||||
|
c_elem->type = ETYPE_DIV;
|
||||||
|
c_elem->flags = 0;
|
||||||
|
|
||||||
// layouting
|
// do layout and update flags only if the element was updated
|
||||||
// TODO: do layout
|
if (is_new || FTEST(parent, ELEM_UPDATED)) {
|
||||||
if (is_new_elem || parent->flags & ELEM_UPDATED) {
|
// 2. layout the element
|
||||||
c_elem->id = id;
|
c_elem->rect = position_element(ctx, parent, div);
|
||||||
c_elem->type = ETYPE_DIV;
|
|
||||||
|
|
||||||
// 1. Select the right origin offset
|
|
||||||
switch (parent->div.layout) {
|
|
||||||
case DIV_LAYOUT_ROW:
|
|
||||||
c_elem->rect = (UgRect) {
|
|
||||||
.x = parent->div.origin_r.x + div.x,
|
|
||||||
.y = parent->div.origin_r.y + div.y,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case DIV_LAYOUT_COLUMN:
|
|
||||||
c_elem->rect = (UgRect) {
|
|
||||||
.x = parent->div.origin_c.x + div.x,
|
|
||||||
.y = parent->div.origin_c.y + div.y,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case DIV_LAYOUT_FLOATING:
|
|
||||||
c_elem->rect = (UgRect) {
|
|
||||||
.x = div.x,
|
|
||||||
.y = div.y,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Error
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Calculate width & height
|
|
||||||
// TODO: what about negative values?
|
|
||||||
c_elem->rect.w = div.w != 0 ? div.w : parent->rect.w;
|
|
||||||
c_elem->rect.h = div.h != 0 ? div.h : parent->rect.h;
|
|
||||||
|
|
||||||
// 3. Mark the element as updated
|
// 3. Mark the element as updated
|
||||||
c_elem->flags |= ELEM_UPDATED;
|
c_elem->flags |= ELEM_UPDATED;
|
||||||
|
|
||||||
// 4. Set div information
|
// 4. Fill the div fields
|
||||||
c_elem->div.layout = parent->div.layout;
|
c_elem->div.layout = parent->div.layout;
|
||||||
c_elem->div.origin_c = (UgPoint) {
|
c_elem->div.origin_c = (UgPoint) {
|
||||||
.x = c_elem->rect.x,
|
.x = c_elem->rect.x,
|
||||||
.y = c_elem->rect.y,
|
.y = c_elem->rect.y,
|
||||||
};
|
};
|
||||||
c_elem->div.origin_r = c_elem->div.origin_c;
|
|
||||||
c_elem->div.color_bg = RGBA(0xff0000ff);
|
c_elem->div.color_bg = RGBA(0xff0000ff);
|
||||||
|
c_elem->div.origin_r = c_elem->div.origin_c;
|
||||||
// 4. Update the origins of the parent
|
|
||||||
parent->div.origin_r = (UgPoint) {
|
|
||||||
.x = c_elem->rect.x + c_elem->rect.w,
|
|
||||||
.y = c_elem->rect.y,
|
|
||||||
};
|
|
||||||
parent->div.origin_c = (UgPoint) {
|
|
||||||
.x = c_elem->rect.x,
|
|
||||||
.y = c_elem->rect.y + c_elem->rect.h,
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: check active
|
// TODO: check active
|
||||||
// TODO: check resizeable
|
// TODO: check resizeable
|
||||||
@ -504,84 +531,99 @@ int ug_div_end(UgCtx *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// position the rectangle inside the parent according to the layout
|
||||||
|
UgRect position_element(UgCtx *ctx, UgElem *parent, UgRect rect)
|
||||||
|
{
|
||||||
|
UgRect elem_rect = {0};
|
||||||
|
UgPoint origin = {0};
|
||||||
|
|
||||||
|
// 1. Select the right origin
|
||||||
|
switch (parent->div.layout) {
|
||||||
|
case DIV_LAYOUT_ROW:
|
||||||
|
origin = parent->div.origin_r;
|
||||||
|
break;
|
||||||
|
case DIV_LAYOUT_COLUMN:
|
||||||
|
origin = parent->div.origin_c;
|
||||||
|
break;
|
||||||
|
case DIV_LAYOUT_FLOATING: // none
|
||||||
|
default:
|
||||||
|
// Error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Position the rect
|
||||||
|
elem_rect.x = origin.x + rect.x;
|
||||||
|
elem_rect.y = origin.y + rect.y;
|
||||||
|
|
||||||
|
// 3. Calculate width & height
|
||||||
|
// TODO: what about negative values?
|
||||||
|
// FIXME: account for origin offset!!
|
||||||
|
elem_rect.w = rect.w > 0 ? rect.w : parent->rect.w;
|
||||||
|
elem_rect.h = rect.h > 0 ? rect.h : parent->rect.h;
|
||||||
|
|
||||||
|
// 4. Update the origins of the parent
|
||||||
|
parent->div.origin_r = (UgPoint) {
|
||||||
|
.x = elem_rect.x + elem_rect.w,
|
||||||
|
.y = elem_rect.y,
|
||||||
|
};
|
||||||
|
parent->div.origin_c = (UgPoint) {
|
||||||
|
.x = elem_rect.x,
|
||||||
|
.y = elem_rect.y + elem_rect.h,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
printf(
|
||||||
|
"positioning rect: %lx {%d %d %d %d}(%d %d %d %d) -> {%d %d %d
|
||||||
|
%d}\n", parent->id, rect.x, rect.y, rect.w, rect.h, parent->rect.x,
|
||||||
|
parent->rect.y,
|
||||||
|
parent->rect.w,
|
||||||
|
parent->rect.h,
|
||||||
|
elem_rect.x,
|
||||||
|
elem_rect.y,
|
||||||
|
elem_rect.w,
|
||||||
|
elem_rect.h
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
return elem_rect;
|
||||||
|
}
|
||||||
|
|
||||||
int ug_button(UgCtx *ctx, const char *label, UgRect size)
|
int ug_button(UgCtx *ctx, const char *label, UgRect size)
|
||||||
{
|
{
|
||||||
if (ctx == NULL || label == NULL) {
|
if (ctx == NULL || label == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
UgId id = djb2(label);
|
UgId id = FNV_1a(label);
|
||||||
|
|
||||||
// TODO: do layouting if the element is new or the parent has updated
|
// TODO: do layouting if the element is new or the parent has updated
|
||||||
int is_new_elem = 0;
|
UgElem *c_elem;
|
||||||
|
int is_new = search_or_insert(ctx, &c_elem, id);
|
||||||
|
|
||||||
// add the element if it does not exist
|
// add it to the tree
|
||||||
UgElem *c_elem = ug_cache_search(&ctx->cache, id);
|
ug_tree_add(&ctx->tree, id, ctx->div_using);
|
||||||
if (c_elem == NULL) {
|
print_tree(ctx);
|
||||||
UgElem elem = {0};
|
|
||||||
uint32_t c_idx;
|
|
||||||
c_elem = ug_cache_insert(&ctx->cache, &elem, &c_idx);
|
|
||||||
is_new_elem = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// take a reference to the parent
|
// take a reference to the parent
|
||||||
// FIXME: if the tree held pointers to the elements then no more
|
// FIXME: if the tree held pointers to the elements then no more
|
||||||
// redundant cache search
|
// redundant cache search
|
||||||
UgId parent_id = ctx->tree.vector[ctx->div_using];
|
UgId parent_id = ug_tree_get(&ctx->tree, ctx->div_using);
|
||||||
UgElem *parent = ug_cache_search(&ctx->cache, parent_id);
|
UgElem *parent = ug_cache_search(&ctx->cache, parent_id);
|
||||||
if (parent == NULL) {
|
if (parent == NULL) {
|
||||||
// Error, did you forget to do frame_begin()?
|
// Error, did you forget to do frame_begin()?
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1. Fill the element fields
|
||||||
|
// this resets the flags
|
||||||
|
c_elem->type = ETYPE_BUTTON;
|
||||||
|
c_elem->flags = 0;
|
||||||
|
|
||||||
// if the element is new or the parent was updated then redo layout
|
// if the element is new or the parent was updated then redo layout
|
||||||
if (is_new_elem || parent->flags & ELEM_UPDATED) {
|
if (is_new || parent->flags & ELEM_UPDATED) {
|
||||||
c_elem->id = id;
|
// 2. Layout
|
||||||
c_elem->type = ETYPE_BUTTON;
|
c_elem->rect = position_element(ctx, parent, size);
|
||||||
|
|
||||||
// 1. Select the right origin offset
|
// 3. TODO: Fill the button specific fields
|
||||||
switch (parent->div.layout) {
|
|
||||||
case DIV_LAYOUT_ROW:
|
|
||||||
c_elem->rect = (UgRect) {
|
|
||||||
.x = parent->div.origin_r.x + size.x,
|
|
||||||
.y = parent->div.origin_r.y + size.y,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case DIV_LAYOUT_COLUMN:
|
|
||||||
c_elem->rect = (UgRect) {
|
|
||||||
.x = parent->div.origin_c.x + size.x,
|
|
||||||
.y = parent->div.origin_c.y + size.y,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case DIV_LAYOUT_FLOATING:
|
|
||||||
c_elem->rect = (UgRect) {
|
|
||||||
.x = size.x,
|
|
||||||
.y = size.y,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Error
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Calculate width & height
|
|
||||||
// TODO: what about negative values?
|
|
||||||
c_elem->rect.w = size.w != 0 ? size.w : parent->rect.w;
|
|
||||||
c_elem->rect.h = size.h != 0 ? size.h : parent->rect.h;
|
|
||||||
|
|
||||||
/// Not a div, so not needed
|
|
||||||
// 3. Mark the element as updated
|
|
||||||
// 4. Set div information
|
|
||||||
|
|
||||||
// 4. Update the origins of the parent
|
|
||||||
parent->div.origin_r = (UgPoint) {
|
|
||||||
.x = c_elem->rect.x + c_elem->rect.w,
|
|
||||||
.y = c_elem->rect.y,
|
|
||||||
};
|
|
||||||
parent->div.origin_c = (UgPoint) {
|
|
||||||
.x = c_elem->rect.x,
|
|
||||||
.y = c_elem->rect.y + c_elem->rect.h,
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: Check for interactions
|
// TODO: Check for interactions
|
||||||
}
|
}
|
||||||
|
38
ugui.h
38
ugui.h
@ -28,23 +28,20 @@ enum UgElemFlags {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UgId id;
|
UgId id;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
UgRect rect;
|
UgRect rect;
|
||||||
|
UgElemType type;
|
||||||
union {
|
|
||||||
uint32_t type_int;
|
|
||||||
UgElemType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
// type-specific fields
|
// type-specific fields
|
||||||
union {
|
union {
|
||||||
struct {
|
struct UgDiv {
|
||||||
enum {
|
enum {
|
||||||
DIV_LAYOUT_ROW = 0,
|
DIV_LAYOUT_ROW = 0,
|
||||||
DIV_LAYOUT_COLUMN,
|
DIV_LAYOUT_COLUMN,
|
||||||
DIV_LAYOUT_FLOATING,
|
DIV_LAYOUT_FLOATING,
|
||||||
} layout;
|
} layout;
|
||||||
|
|
||||||
UgPoint origin_r, origin_c;
|
UgPoint origin_r, origin_c;
|
||||||
UgColor color_bg;
|
UgColor color_bg;
|
||||||
} div; // Div
|
} div; // Div
|
||||||
@ -70,22 +67,23 @@ typedef struct {
|
|||||||
typedef struct _UgCtx UgCtx;
|
typedef struct _UgCtx UgCtx;
|
||||||
|
|
||||||
// tree implementation
|
// tree implementation
|
||||||
int ug_tree_init(UgTree *tree, unsigned int size);
|
int ug_tree_init(UgTree *tree, unsigned int size);
|
||||||
int ug_tree_pack(UgTree *tree);
|
int ug_tree_pack(UgTree *tree);
|
||||||
int ug_tree_resize(UgTree *tree, unsigned int newsize);
|
int ug_tree_resize(UgTree *tree, unsigned int newsize);
|
||||||
int ug_tree_add(UgTree *tree, UgId elem, int parent);
|
int ug_tree_add(UgTree *tree, UgId elem, int parent);
|
||||||
int ug_tree_prune(UgTree *tree, int ref);
|
int ug_tree_prune(UgTree *tree, int ref);
|
||||||
int ug_tree_subtree_size(UgTree *tree, int ref);
|
int ug_tree_subtree_size(UgTree *tree, int ref);
|
||||||
int ug_tree_children_it(UgTree *tree, int parent, int *cursor);
|
int ug_tree_children_it(UgTree *tree, int parent, int *cursor);
|
||||||
int ug_tree_level_order_it(UgTree *tree, int ref, int *cursor);
|
int ug_tree_level_order_it(UgTree *tree, int ref, int *cursor);
|
||||||
int ug_tree_parentof(UgTree *tree, int node);
|
int ug_tree_parentof(UgTree *tree, int node);
|
||||||
int ug_tree_destroy(UgTree *tree);
|
int ug_tree_destroy(UgTree *tree);
|
||||||
|
UgId ug_tree_get(UgTree *tree, int node);
|
||||||
|
|
||||||
// cache implementation
|
// cache implementation
|
||||||
UgElemCache ug_cache_init(void);
|
UgElemCache ug_cache_init(void);
|
||||||
void ug_cache_free(UgElemCache *cache);
|
void ug_cache_free(UgElemCache *cache);
|
||||||
UgElem *ug_cache_search(UgElemCache *cache, UgId id);
|
UgElem *ug_cache_search(UgElemCache *cache, UgId id);
|
||||||
UgElem *ug_cache_insert(UgElemCache *cache, const UgElem *g, uint32_t *index);
|
UgElem *ug_cache_insert_new(UgElemCache *cache, const UgElem *g, uint32_t *index);
|
||||||
|
|
||||||
int ug_init(UgCtx *ctx);
|
int ug_init(UgCtx *ctx);
|
||||||
int ug_destroy(UgCtx *ctx);
|
int ug_destroy(UgCtx *ctx);
|
||||||
|
12
vectree.c
12
vectree.c
@ -128,7 +128,7 @@ int ug_tree_resize(UgTree *tree, unsigned int newsize)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int *neworrefs = realloc(tree->ordered_refs, (newsize + 1)* sizeof(int));
|
int *neworrefs = realloc(tree->ordered_refs, (newsize + 1) * sizeof(int));
|
||||||
if (neworrefs == NULL) {
|
if (neworrefs == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -319,7 +319,7 @@ int ug_tree_level_order_it(UgTree *tree, int ref, int *cursor)
|
|||||||
|
|
||||||
} while (IS_VALID_REF(tree, ref));
|
} while (IS_VALID_REF(tree, ref));
|
||||||
// This line is why tree->ordered_refs has to be size+1
|
// This line is why tree->ordered_refs has to be size+1
|
||||||
queue[off+1] = -1;
|
queue[off + 1] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PRINT_ARR(queue, tree->size);
|
// PRINT_ARR(queue, tree->size);
|
||||||
@ -345,3 +345,11 @@ int ug_tree_parentof(UgTree *tree, int node)
|
|||||||
}
|
}
|
||||||
return tree->refs[node];
|
return tree->refs[node];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UgId ug_tree_get(UgTree *tree, int node)
|
||||||
|
{
|
||||||
|
if (tree == NULL || !IS_VALID_REF(tree, node)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return tree->vector[node];
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user