Compare commits

..

2 Commits

Author SHA1 Message Date
82bc7a4d0d
some working elements 2023-01-08 01:37:36 +01:00
e00bd1046a
begin work on elements 2023-01-02 23:49:27 +01:00
6 changed files with 401 additions and 180 deletions

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
microgui microgui
*.o *.o
test/test test/test
**/compile_commands.json
**/.cache

37
def_style.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef _UG_DEF_STYLE_H
#define _UG_DEF_STYLE_H
#include "ugui.h"
#define SZ_INT(x) x.size.i
static const ug_style_t default_style = {
.color = {
.bg = RGB_FORMAT(0x131313),
.fg = RGB_FORMAT(0xffffff),
},
.margin = SIZE_PX(3),
.border = {
.color = RGB_FORMAT(0xf50a00),
.size = SIZE_PX(2),
},
.title = {
.color = {
.bg = RGB_FORMAT(0xbbbbbb),
.fg = RGB_FORMAT(0xffff00),
},
.height = SIZE_PX(20),
.font_size = SIZE_PX(14),
},
.btn = {
.color = {
.active = RGB_FORMAT(0x44ff44),
.bg = RGB_FORMAT(0x00ff00),
.fg = RGB_FORMAT(0xffff00),
},
.font_size = SIZE_PX(10),
},
};
#endif

View File

@ -1,7 +1,7 @@
CFLAGS = -Wall -Wextra -Wpedantic -std=c11 -g CFLAGS = -Wall -Wextra -Wpedantic -std=c11 -g
LDFLAGS = -lSDL2 -lm LDFLAGS = -lSDL2 -lm
test: main.c ../ugui.c ../ugui.h test: main.c ../ugui.c ../ugui.h ../def_style.h
gcc ${CFLAGS} -c ../ugui.c -o ugui.o gcc ${CFLAGS} -c ../ugui.c -o ugui.o
gcc ${CFLAGS} -c main.c -o main.o gcc ${CFLAGS} -c main.c -o main.o
gcc ${LDFLAGS} main.o ugui.o -o test gcc ${LDFLAGS} main.o ugui.o -o test

View File

@ -1,3 +1,5 @@
#define _POSIX_C_SOURCE 200809l
#include <stdio.h> #include <stdio.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
@ -63,7 +65,7 @@ int main(void)
ug_ctx_set_drawableregion(ctx, dsize); ug_ctx_set_drawableregion(ctx, dsize);
// open font // open font
font = STBTTF_OpenFont(r, "monospace.ttf", ctx->style_px->text.size.size.i); font = STBTTF_OpenFont(r, "monospace.ttf", ctx->style_px->title.font_size.size.i);
// atexit(cleanup); // atexit(cleanup);
@ -183,35 +185,44 @@ int main(void)
ug_frame_begin(ctx); ug_frame_begin(ctx);
if (ctx->frame < 5000) { //if (ctx->frame < 5000) {
ug_container_menu_bar(ctx, "Menu fichissimo", (ug_size_t)SIZE_PX(24)); // ug_container_menu_bar(ctx, "Menu fichissimo", (ug_size_t)SIZE_PX(24));
} else if (ctx->frame == 5000) { //} else if (ctx->frame == 5000) {
ug_container_remove(ctx, "Menu fichissimo"); // ug_container_remove(ctx, "Menu fichissimo");
} //}
ug_container_floating(ctx, "stupid name", ug_container_floating(ctx, "stupid name", (ug_div_t){.x=SIZE_PX(0), .y=SIZE_PX(0), .w=SIZE_PX(100), .h=SIZE_MM(75.0)});
(ug_div_t){.x=SIZE_PX(0), .y=SIZE_PX(0), .w=SIZE_PX(100), .h=SIZE_MM(75.0)});
//ug_container_floating(ctx, "floating windoooooooow", //ug_container_floating(ctx, "floating windoooooooow", (ug_div_t){.x=SIZE_PX(100), .y=SIZE_PX(0), .w=SIZE_PX(100), .h=SIZE_MM(75.0)});
// (ug_div_t){.x=SIZE_PX(100), .y=SIZE_PX(0), .w=SIZE_PX(100), .h=SIZE_MM(75.0)});
ug_container_sidebar(ctx, "Right Sidebar", (ug_size_t)SIZE_PX(300), UG_SIDE_RIGHT); ug_container_sidebar(ctx, "Right Sidebar", (ug_size_t)SIZE_PX(300), UG_SIDE_RIGHT);
ug_container_sidebar(ctx, "Left Sidebar", (ug_size_t)SIZE_PX(200), UG_SIDE_LEFT); ug_container_sidebar(ctx, "Left Sidebar", (ug_size_t)SIZE_PX(200), UG_SIDE_LEFT);
ug_container_sidebar(ctx, "Bottom Sidebar", (ug_size_t)SIZE_MM(10), UG_SIDE_BOTTOM); //ug_container_sidebar(ctx, "Bottom Sidebar", (ug_size_t)SIZE_MM(10), UG_SIDE_BOTTOM);
ug_container_sidebar(ctx, "Top Sidebar", (ug_size_t)SIZE_MM(40), UG_SIDE_TOP); //ug_container_sidebar(ctx, "Top Sidebar", (ug_size_t)SIZE_MM(40), UG_SIDE_TOP);
//ug_container_floating(ctx, "stupid er", // ug_container_popup(ctx, "Annoying popup", (ug_div_t){.x=SIZE_MM(150), .y=SIZE_MM(150), .w=SIZE_PX(100), .h=SIZE_MM(75.0)});
// (ug_div_t){.x=SIZE_PX(150), .y=SIZE_PX(-100), .w=SIZE_PX(100), .h=SIZE_MM(75.0)});
ug_container_popup(ctx, "Annoying popup", (ug_div_t){.x=SIZE_MM(150), .y=SIZE_MM(150), .w=SIZE_PX(100), .h=SIZE_MM(75.0)});
ug_container_body(ctx, "Main Body"); ug_container_body(ctx, "Main Body");
if (ug_container_body(ctx, "Other Body")) //if (ug_container_body(ctx, "Other Body"))
printf("No space!\n"); // printf("No space!\n");
ug_layout_row(ctx);
if (ug_element_button(ctx, "button", "btn", (ug_div_t){.w=SIZE_PX(20),.h=SIZE_PX(20)}))
printf("nope\n");
ug_element_button(ctx, "button 1", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)});
ug_element_button(ctx, "button 2", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)});
ug_element_button(ctx, "button 3", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)});
ug_layout_column(ctx);
ug_element_button(ctx, "button 4", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)});
ug_element_button(ctx, "button 5", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10)});
ug_element_button(ctx, "button 6", "", (ug_div_t){.w=SIZE_PX(10),.h=SIZE_PX(10),.x=SIZE_PX(-10)});
ug_frame_end(ctx); ug_frame_end(ctx);
// fill background // fill background
SDL_SetRenderDrawColor(r, 0, 0, 0, 0xff); // solid purple makes it easy to identify, same color as hl missing texture
SDL_SetRenderDrawColor(r, 0xff, 0, 0xdc, 0xff);
SDL_RenderClear(r); SDL_RenderClear(r);
for (ug_cmd_t *cmd = NULL; (cmd = ug_cmd_next(ctx));) { for (ug_cmd_t *cmd = NULL; (cmd = ug_cmd_next(ctx));) {
switch (cmd->type) { switch (cmd->type) {

435
ugui.c
View File

@ -6,6 +6,7 @@
#include <math.h> #include <math.h>
#include "ugui.h" #include "ugui.h"
#include "def_style.h"
#define SALT 0xbabb0cac #define SALT 0xbabb0cac
@ -48,28 +49,6 @@
#define MAX(a, b) (a > b ? a : b) #define MAX(a, b) (a > b ? a : b)
// default style
// TODO: fill default style
static const ug_style_t default_style = {
.text = {
.color = RGB_FORMAT(0xffffff),
.alt_color = RGB_FORMAT(0xbbbbbb),
.size = SIZE_PX(16),
.alt_size = SIZE_PX(12),
},
.cnt = {
.bg_color = RGB_FORMAT(0x0000ff),
.border.t = SIZE_PX(1),
.border.b = SIZE_PX(1),
.border.l = SIZE_PX(1),
.border.r = SIZE_PX(1),
.border.color = RGB_FORMAT(0x00ff00),
.titlebar.height = SIZE_PX(20),
.titlebar.bg_color = RGB_FORMAT(0xbababa),
.margin = SIZE_PX(3),
},
};
static ug_style_t style_cache = {0}; static ug_style_t style_cache = {0};
@ -326,6 +305,46 @@ int ug_ctx_set_style(ug_ctx_t *ctx, const ug_style_t *style)
* Container Operations * * Container Operations *
*=============================================================================*/ *=============================================================================*/
/*
* Container style:
*
* rca
* v v Border Top v
* +--------------------------------------------------------+
* +--------------------------------------------------------+
* | Titlebar |
* +--------------------------------------------------------+
* |+------------------------------------------------------+|
* || .................................................... ||
* || .\ ^ Border Top ^ . ||
* || . \_ rect(0,0) . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . < Border Left . ||
* || . + Margin Border Right >. ||
* || . + Margin . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || .................................................... ||
* |+------------------------------------------------------+|
* +--------------------------------------------------------+
* ^ Border Bottom ^
*/
// search a container by id int the stack and get it's address // search a container by id int the stack and get it's address
static ug_container_t *search_container(ug_ctx_t *ctx, ug_id_t id) static ug_container_t *search_container(ug_ctx_t *ctx, ug_id_t id)
@ -390,6 +409,9 @@ static void sort_containers(ug_ctx_t *ctx)
// update the container position in the context area // update the container position in the context area
// TODO: can we generalize position_container and position_element into one or
// more similar functions
// TODO: containers only have borders from which they can be resized
static int position_container(ug_ctx_t *ctx, ug_container_t *cnt) static int position_container(ug_ctx_t *ctx, ug_container_t *cnt)
{ {
if (!TEST(cnt->flags, UG_CNT_FLOATING)) { if (!TEST(cnt->flags, UG_CNT_FLOATING)) {
@ -405,52 +427,9 @@ static int position_container(ug_ctx_t *ctx, ug_container_t *cnt)
*rca = *rect; *rca = *rect;
/*
* Container style:
*
* rca
* v v Border Top v
* +--------------------------------------------------------+
* +--------------------------------------------------------+
* | Titlebar |
* +--------------------------------------------------------+
* |+------------------------------------------------------+|
* || .................................................... ||
* || .\ ^ Border Top ^ . ||
* || . \_ rect(0,0) . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . < Border Left . ||
* || . + Margin Border Right >. ||
* || . + Margin . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || . . ||
* || .................................................... ||
* |+------------------------------------------------------+|
* +--------------------------------------------------------+
* ^ Border Bottom ^
*/
const ug_style_t *s = ctx->style_px; const ug_style_t *s = ctx->style_px;
int bl = s->cnt.border.l.size.i + s->cnt.margin.size.i; int b = SZ_INT(s->border.size) + SZ_INT(s->margin);
int br = s->cnt.border.r.size.i + s->cnt.margin.size.i; int hh = SZ_INT(s->title.height);
int bt = s->cnt.border.t.size.i + s->cnt.margin.size.i;
int bb = s->cnt.border.b.size.i + s->cnt.margin.size.i;
int hh = s->cnt.titlebar.height.size.i;
int cx = ctx->origin.x; int cx = ctx->origin.x;
int cy = ctx->origin.y; int cy = ctx->origin.y;
int cw = ctx->origin.w; int cw = ctx->origin.w;
@ -458,11 +437,25 @@ static int position_container(ug_ctx_t *ctx, ug_container_t *cnt)
// handle relative sizes // handle relative sizes
if (rect->w == 0) rca->w = cw; if (rect->w == 0) rca->w = cw;
else rca->w += bl + br;
if (rect->h == 0) rca->h = ch; if (rect->h == 0) rca->h = ch;
else if (TEST(cnt->flags, UG_CNT_MOVABLE)) rca->h += hh + 2*bt + bb; else if (TEST(cnt->flags, UG_CNT_MOVABLE)) rca->h += hh;
else rca->h += bt + bb;
// handle borders, only draw borders on sides which can be used to resize
if (TEST(cnt->flags, UG_CNT_RESIZE_LEFT)) {
rca->w += b;
}
if (TEST(cnt->flags, UG_CNT_RESIZE_RIGHT)) {
rca->w += b;
}
if (TEST(cnt->flags, UG_CNT_RESIZE_TOP)) {
rca->h += b;
}
if (TEST(cnt->flags, UG_CNT_RESIZE_BOTTOM)) {
rca->h += b;
}
if (TEST(cnt->flags, UG_CNT_MOVABLE)) {
rca->h += b;
}
// if the container is not fixed than it can have positions outside of the // if the container is not fixed than it can have positions outside of the
// main window, thus negative // main window, thus negative
@ -486,6 +479,16 @@ static int position_container(ug_ctx_t *ctx, ug_container_t *cnt)
ctx->origin.w = ctx->origin.h = 0; ctx->origin.w = ctx->origin.h = 0;
} }
} }
// set the correct element origin
cnt->c_orig.x = cnt->r_orig.x = cnt->space.x = rca->x + b;
cnt->c_orig.y = cnt->r_orig.y = cnt->space.y = rca->y + b;
if (TEST(cnt->flags, UG_CNT_MOVABLE)) {
cnt->c_orig.y += hh + SZ_INT(s->border.size);
cnt->r_orig.y += hh + SZ_INT(s->border.size);
cnt->space.y += hh + SZ_INT(s->border.size);
}
return 0; return 0;
} }
@ -514,21 +517,18 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt)
rca = &cnt->rca; rca = &cnt->rca;
const ug_style_t *s = ctx->style_px; const ug_style_t *s = ctx->style_px;
int bl = s->cnt.border.l.size.i + s->cnt.margin.size.i; int b = SZ_INT(s->border.size) + SZ_INT(s->margin);
int br = s->cnt.border.r.size.i + s->cnt.margin.size.i; int hh = SZ_INT(s->title.height);
int bt = s->cnt.border.t.size.i + s->cnt.margin.size.i;
int bb = s->cnt.border.b.size.i + s->cnt.margin.size.i;
int hh = s->cnt.titlebar.height.size.i;
ug_vec2_t mpos = ctx->mouse.pos; ug_vec2_t mpos = ctx->mouse.pos;
int minx, maxx, miny, maxy; int minx, maxx, miny, maxy;
// handle movable windows // handle movable windows
if (TEST(cnt->flags, UG_CNT_MOVABLE)) { if (TEST(cnt->flags, UG_CNT_MOVABLE)) {
minx = rca->x + bl; minx = rca->x + b;
maxx = rca->x + rca->w - br; maxx = rca->x + rca->w - b;
miny = rca->y + bt; miny = rca->y + b;
maxy = rca->y + bt + hh; maxy = rca->y + b + hh;
if ((cnt->flags & CNT_STATE_ALL) == CNT_STATE_MOVING || if ((cnt->flags & CNT_STATE_ALL) == CNT_STATE_MOVING ||
((cnt->flags & CNT_STATE_ALL) == 0 && ((cnt->flags & CNT_STATE_ALL) == 0 &&
BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.x, minx, maxx) &&
@ -541,9 +541,10 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt)
} }
} }
// FIXME: allow for corner resize
// right border resize // right border resize
if (TEST(cnt->flags, UG_CNT_RESIZE_RIGHT)) { if (TEST(cnt->flags, UG_CNT_RESIZE_RIGHT)) {
minx = rca->x + rca->w - br; minx = rca->x + rca->w - b;
maxx = rca->x + rca->w; maxx = rca->x + rca->w;
miny = rca->y; miny = rca->y;
maxy = rca->y + rca->h; maxy = rca->y + rca->h;
@ -560,7 +561,7 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt)
// left border resize // left border resize
if (TEST(cnt->flags, UG_CNT_RESIZE_LEFT)) { if (TEST(cnt->flags, UG_CNT_RESIZE_LEFT)) {
minx = rca->x; minx = rca->x;
maxx = rca->x + bl; maxx = rca->x + b;
miny = rca->y; miny = rca->y;
maxy = rca->y + rca->h; maxy = rca->y + rca->h;
if ((cnt->flags & CNT_STATE_ALL) == CNT_STATE_RESIZE_L || if ((cnt->flags & CNT_STATE_ALL) == CNT_STATE_RESIZE_L ||
@ -585,7 +586,7 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt)
if (TEST(cnt->flags, UG_CNT_RESIZE_BOTTOM)) { if (TEST(cnt->flags, UG_CNT_RESIZE_BOTTOM)) {
minx = rca->x; minx = rca->x;
maxx = rca->x + rca->w; maxx = rca->x + rca->w;
miny = rca->y + rca->h - bb; miny = rca->y + rca->h - b;
maxy = rca->y + rca->h; maxy = rca->y + rca->h;
if ((cnt->flags & CNT_STATE_ALL) == CNT_STATE_RESIZE_B || if ((cnt->flags & CNT_STATE_ALL) == CNT_STATE_RESIZE_B ||
((cnt->flags & CNT_STATE_ALL) == 0 && ((cnt->flags & CNT_STATE_ALL) == 0 &&
@ -602,7 +603,7 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt)
minx = rca->x; minx = rca->x;
maxx = rca->x + rca->w; maxx = rca->x + rca->w;
miny = rca->y; miny = rca->y;
maxy = rca->y + bt; maxy = rca->y + b;
if ((cnt->flags & CNT_STATE_ALL) == CNT_STATE_RESIZE_T || if ((cnt->flags & CNT_STATE_ALL) == CNT_STATE_RESIZE_T ||
((cnt->flags & CNT_STATE_ALL) == 0 && ((cnt->flags & CNT_STATE_ALL) == 0 &&
BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.x, minx, maxx) &&
@ -638,47 +639,59 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt)
static void draw_container(ug_ctx_t *ctx, ug_container_t *cnt, const char *text) static void draw_container(ug_ctx_t *ctx, ug_container_t *cnt, const char *text)
{ {
ug_rect_t draw_rect; ug_rect_t rect;
const ug_style_t *s = ctx->style_px; const ug_style_t *s = ctx->style_px;
int bl = s->cnt.border.l.size.i; int b = SZ_INT(s->border.size);
int br = s->cnt.border.r.size.i; int hh = SZ_INT(s->title.height);
int bt = s->cnt.border.t.size.i; int ts = SZ_INT(s->title.font_size);
int bb = s->cnt.border.b.size.i;
int hh = s->cnt.titlebar.height.size.i;
int ts = s->text.size.size.i;
// push outline
draw_rect = cnt->rca;
push_rect_command(ctx, &draw_rect, s->cnt.border.color);
// titlebar
if (TEST(cnt->flags, UG_CNT_MOVABLE)) {
draw_rect.x += bl;
draw_rect.y += bt;
draw_rect.w -= bl + br;
draw_rect.h = hh;
push_rect_command(ctx, &draw_rect, s->cnt.titlebar.bg_color);
if (text) {
// TODO: center the text horizontally
push_text_command(ctx,
(ug_vec2_t){.x = draw_rect.x + bl,
.y = draw_rect.y + bt + ts/2},
ts, s->text.color, text);
}
}
// push main body // push main body
draw_rect = cnt->rca; rect = cnt->rca;
draw_rect.x += bl; push_rect_command(ctx, &rect, s->color.bg);
draw_rect.y += bt;
draw_rect.w -= bl + br; // push outline
draw_rect.h -= bt + bb; if (TEST(cnt->flags, UG_CNT_RESIZE_LEFT)) {
if (TEST(cnt->flags, UG_CNT_MOVABLE)) { rect = cnt->rca;
draw_rect.y += bt + hh; rect.w = b;
draw_rect.h -= bt + hh; push_rect_command(ctx, &rect, s->border.color);
}
if (TEST(cnt->flags, UG_CNT_RESIZE_RIGHT)) {
rect = cnt->rca;
rect.x += rect.w - b;
rect.w = b;
push_rect_command(ctx, &rect, s->border.color);
}
if (TEST(cnt->flags, UG_CNT_RESIZE_TOP)) {
rect = cnt->rca;
rect.h = b;
push_rect_command(ctx, &rect, s->border.color);
}
if (TEST(cnt->flags, UG_CNT_RESIZE_BOTTOM)) {
rect = cnt->rca;
rect.y += rect.h - b;
rect.h = b;
push_rect_command(ctx, &rect, s->border.color);
}
// titlebar
if (TEST(cnt->flags, UG_CNT_MOVABLE)) {
// titlebar area
rect = cnt->rca;
rect.x += b;
rect.y += b;
rect.w -= 2*b;
rect.h = hh;
push_rect_command(ctx, &rect, s->title.color.bg);
// titlebar border
rect.y += hh;
rect.h = b;
push_rect_command(ctx, &rect, s->border.color);
if (text) {
// TODO: center text
push_text_command(ctx,
(ug_vec2_t){.x = rect.x, .y = rect.y},
ts, s->title.color.fg, text);
}
} }
push_rect_command(ctx, &draw_rect, s->cnt.bg_color);
// TODO: push other rects
} }
@ -995,6 +1008,8 @@ int ug_frame_begin(ug_ctx_t *ctx)
return 0; return 0;
} }
// FIXME: reoreder code such that this prototype is not needed
void draw_elements(ug_ctx_t *, ug_container_t *);
// At the end of a frame reset inputs // At the end of a frame reset inputs
int ug_frame_end(ug_ctx_t *ctx) int ug_frame_end(ug_ctx_t *ctx)
@ -1005,8 +1020,10 @@ int ug_frame_end(ug_ctx_t *ctx)
sort_containers(ctx); sort_containers(ctx);
for (int i = 0; i < ctx->cnt_stack.idx; i++) { for (int i = 0; i < ctx->cnt_stack.idx; i++) {
ug_container_t *c = &ctx->cnt_stack.items[i]; ug_container_t *c = &ctx->cnt_stack.items[i];
// draw containers
draw_container(ctx, c, c->name); draw_container(ctx, c, c->name);
// TODO: draw elements // draw elements
draw_elements(ctx, c);
// reset the layout to row // reset the layout to row
c->flags &= ~(CNT_LAYOUT_COLUMN); c->flags &= ~(CNT_LAYOUT_COLUMN);
} }
@ -1044,6 +1061,38 @@ int ug_frame_end(ug_ctx_t *ctx)
*=============================================================================*/ *=============================================================================*/
/*
* Container layout:
* A partition in the space taken up by the conglomerate of elements in
* between calls to new_row or new_column (no backing state, just an idea)
* +--------------------------------------------------------+
* | .<- r_orig |
* | . |
* | prev "partition" . |
* | . |
* |.............................. |
* |^ |
* |c_orig |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* +--------------------------------------------------------+
*
*/
#define GET_SELECTED_CONTAINER(ctx, cp) \ #define GET_SELECTED_CONTAINER(ctx, cp) \
{ \ { \
cp = search_container(ctx, ctx->selected_cnt); \ cp = search_container(ctx, ctx->selected_cnt); \
@ -1076,10 +1125,136 @@ int ug_layout_column(ug_ctx_t *ctx)
} }
int ug_layout_next_row(ug_ctx_t *ctx)
{
TEST_CTX(ctx);
ug_container_t *cp;
GET_SELECTED_CONTAINER(ctx, cp);
cp->r_orig = cp->c_orig;
return 0;
}
int ug_layout_next_column(ug_ctx_t *ctx)
{
TEST_CTX(ctx);
ug_container_t *cp;
GET_SELECTED_CONTAINER(ctx, cp);
cp->c_orig = cp->r_orig;
return 0;
}
/*=============================================================================* /*=============================================================================*
* Elements * * Elements *
*=============================================================================*/ *=============================================================================*/
// search an element by id in the container's element stack and get it's address
static ug_element_t *search_element(ug_container_t *cnt, ug_id_t id)
{
ug_element_t *e = NULL;
for (int i = 0; i < cnt->elem_stack.idx; i++) {
if (cnt->elem_stack.items[i].id == id) {
e = &(cnt->elem_stack.items[i]);
break;
}
}
return e;
}
// get a new or existing container handle
static ug_element_t *get_element(ug_container_t *cnt, ug_id_t id)
{
ug_element_t *e = search_element(cnt, id);
if (!e) {
GET_FROM_STACK(cnt->elem_stack, e);
cnt->elem_stack.sorted = 0;
}
return e;
}
// update the element's position in the container area
static int position_element(ug_ctx_t *ctx, ug_container_t *cnt, ug_element_t *elem)
{
ug_rect_t *rect, *rca;
rect = &(elem->rect);
rca = &(elem->rca);
scale_rect(ctx, rect);
*rca = *rect;
// printf("cnt->r_orig: x=%d, y=%d\n", cnt->r_orig.x, cnt->r_orig.y);
// printf("cnt->c_orig: x=%d, y=%d\n", cnt->c_orig.x, cnt->c_orig.y);
// printf("rca: x=%d, y=%d, w=%d, h=%d\n", rca->x, rca->y, rca->w, rca->h);
const ug_style_t *s = ctx->style_px;
// FIXME: different border thickness
int b = SZ_INT(s->border.size);
int m = SZ_INT(s->margin);
int cx, cy, cw, ch;
// FIXME: this may not work
cw = MAX(cnt->rca.w - cnt->space.w, 0);
ch = MAX(cnt->rca.h - cnt->space.h, 0);
if (TEST(cnt->flags, CNT_LAYOUT_COLUMN)) {
cx = cnt->c_orig.x;
cy = cnt->c_orig.y;
} else {
cx = cnt->r_orig.x;
cy = cnt->r_orig.y;
}
// handle relative sizes
if (rect->w == 0) rca->w = cw;
else rca->w += b;
if (rect->h == 0) rca->h = ch;
else rca->h += b;
// for elements x and y are offsets
rca->x = cx + rect->x;
rca->y = cy + rect->y;
// printf("rca: x=%d, y=%d, w=%d, h=%d\n", rca->x, rca->y, rca->w, rca->h);
if (TEST(cnt->flags, CNT_LAYOUT_COLUMN)) {
cnt->c_orig.y += rca->h + m;
cnt->r_orig.y += rca->h + m;
cnt->space.h += rca->h;
if ((cnt->space.x + cnt->space.w) < (rca->x + rca->w))
cnt->space.w += cnt->space.x + cnt->space.w - rca->x - rca->w;
} else {
cnt->r_orig.x += rca->w + m;
cnt->c_orig.x += rca->w + m;
cnt->space.w += rca->w;
if ((cnt->space.y + cnt->space.h) < (rca->y + rca->h))
cnt->space.h += cnt->space.y + cnt->space.h - rca->y - rca->h;
}
return 0;
}
void draw_elements(ug_ctx_t *ctx, ug_container_t *cnt)
{
for (int i = 0; i < cnt->elem_stack.idx; i++) {
ug_element_t *e = &(cnt->elem_stack.items[i]);
switch (e->type) {
case UG_ELEM_BUTTON:
push_rect_command(ctx, &e->rca, ctx->style_px->btn.color.bg);
break;
default: break;
}
}
}
int ug_element_button(ug_ctx_t *ctx, const char *name, const char *txt, ug_div_t dim) int ug_element_button(ug_ctx_t *ctx, const char *name, const char *txt, ug_div_t dim)
{ {
@ -1088,7 +1263,23 @@ int ug_element_button(ug_ctx_t *ctx, const char *name, const char *txt, ug_div_t
ug_container_t *cp; ug_container_t *cp;
GET_SELECTED_CONTAINER(ctx, cp); GET_SELECTED_CONTAINER(ctx, cp);
printf("selected: %x\n", ctx->selected_cnt);
ug_id_t id = hash(name, strlen(name));
ug_element_t *elem = get_element(cp, id);
// FIXME: we don't always need to do everything
elem->id = id;
elem->type = UG_ELEM_BUTTON;
elem->rect = div_to_rect(ctx, &dim);
elem->name = name;
elem->btn.txt = txt;
// FIXME: what about error codes?
if (position_element(ctx, cp, elem)) {
DELETE_FROM_STACK(cp->elem_stack, elem);
return -1;
}
// TODO: this
return 0; return 0;
} }

64
ugui.h
View File

@ -30,7 +30,12 @@ typedef struct {
ug_id_t id; ug_id_t id;
unsigned int type; unsigned int type;
ug_rect_t rect, rca; ug_rect_t rect, rca;
char *name, *content; const char *name;
union {
struct {
const char *txt;
} btn;
};
} ug_element_t; } ug_element_t;
enum { enum {
@ -60,9 +65,12 @@ typedef struct {
ug_rect_t rca; ug_rect_t rca;
unsigned int flags; unsigned int flags;
// layouting and elements // layouting and elements
ug_rect_t orig; // origin and space available // total space used by elements, x and y are the starting coordinates
int r, c; // row and column // for elements
UG_STACK(ug_element_t); ug_rect_t space;
// origin for in-row and in-column elements
ug_vec2_t c_orig, r_orig;
UG_STACK(ug_element_t) elem_stack;
} ug_container_t; } ug_container_t;
// the container flags // the container flags
@ -93,48 +101,20 @@ enum {
// allocate space one can say that the default size of a region that allocates a // allocate space one can say that the default size of a region that allocates a
// slider has the style's default dimensions for a slider // slider has the style's default dimensions for a slider
typedef struct { typedef struct {
struct { struct { ug_color_t bg, fg; } color;
ug_color_t color, alt_color;
ug_size_t size, alt_size;
} text;
struct {
ug_color_t bg_color;
struct {
ug_size_t t, b, l, r;
ug_color_t color;
} border;
ug_size_t margin; ug_size_t margin;
// titlebar only gets applied to movable containers
struct { struct {
ug_size_t height; ug_color_t color;
ug_color_t bg_color; ug_size_t size;
} titlebar; } border;
} cnt;
// a button should stand out, hence the different colors
struct { struct {
ug_color_t bg_color, hover_color, active_color; struct { ug_color_t bg, fg; } color;
} button; ug_size_t height, font_size;
} title;
// a checkbox should be smaller than a button
struct { struct {
ug_size_t width, height, tick_size; struct { ug_color_t active, bg, fg; } color;
ug_color_t tick_color; ug_size_t font_size;
} checkbox; } btn;
// a slider can be thinner and generally wider than a button
struct {
ug_size_t width, height;
} slider;
// the text color, dimension and the background of a text display can be
// different
struct {
ug_color_t text_color, bg_color;
ug_size_t text_size;
} textdisplay;
} ug_style_t; } ug_style_t;