Compare commits
4 Commits
6d01741426
...
05b6f9eae8
Author | SHA1 | Date | |
---|---|---|---|
05b6f9eae8 | |||
c930520cbd | |||
46e6e378d0 | |||
e998b6c287 |
12
test/main.c
12
test/main.c
@ -175,12 +175,14 @@ int main(void)
|
|||||||
|
|
||||||
ug_frame_begin(ctx);
|
ug_frame_begin(ctx);
|
||||||
|
|
||||||
ug_ctx_set_unit(ctx, UG_UNIT_MM);
|
|
||||||
ug_container_floating(ctx, "stupid name",
|
ug_container_floating(ctx, "stupid name",
|
||||||
(ug_rect_t){.fx = 0, .fy = 0, .fw = 50, .fh = 50});
|
(ug_div_t){.x=SIZE_PX(0), .y=SIZE_PX(0), .w=SIZE_PX(100), .h=SIZE_MM(75.0)});
|
||||||
ug_container_floating(ctx, "better name",
|
|
||||||
(ug_rect_t){.fx = -20, .fy = -10, .fw = 100, .fh = 30});
|
|
||||||
|
|
||||||
|
ug_container_floating(ctx, "stupid er",
|
||||||
|
(ug_div_t){.x=SIZE_PX(150), .y=SIZE_PX(-100), .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, "Bottom Sidebar", (ug_size_t)SIZE_MM(10), UG_SIDE_BOTTOM);
|
||||||
ug_frame_end(ctx);
|
ug_frame_end(ctx);
|
||||||
|
|
||||||
// fill background
|
// fill background
|
||||||
@ -202,8 +204,6 @@ int main(void)
|
|||||||
}
|
}
|
||||||
SDL_RenderPresent(r);
|
SDL_RenderPresent(r);
|
||||||
|
|
||||||
printf("-------------------FRAME DONE--------------------\n");
|
|
||||||
|
|
||||||
} while (event.type != SDL_QUIT);
|
} while (event.type != SDL_QUIT);
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
|
288
ugui.c
288
ugui.c
@ -13,13 +13,20 @@
|
|||||||
#define DEF_PPI 96.0
|
#define DEF_PPI 96.0
|
||||||
#define STACK_STEP 64
|
#define STACK_STEP 64
|
||||||
|
|
||||||
|
#define RESIZEALL UG_CNT_RESIZE_RIGHT | \
|
||||||
|
UG_CNT_RESIZE_BOTTOM | \
|
||||||
|
UG_CNT_RESIZE_LEFT | \
|
||||||
|
UG_CNT_RESIZE_TOP
|
||||||
|
#define BTN_ANY UG_BTN_LEFT | UG_BTN_RIGHT | UG_BTN_MIDDLE | UG_BTN_4 | UG_BTN_5
|
||||||
|
|
||||||
#define PPI_PPM(ppi, scale) (ppi * scale * 0.03937008)
|
#define PPI_PPM(ppi, scale) (ppi * scale * 0.03937008)
|
||||||
#define PPI_PPD(ppi, scale) (PPI_PPM(ppi, scale) * 0.3528)
|
#define PPI_PPD(ppi, scale) (PPI_PPM(ppi, scale) * 0.3528)
|
||||||
#define IS_VALID_UNIT(u) (u==UG_UNIT_PX||u==UG_UNIT_MM||u==UG_UNIT_PT)
|
#define IS_VALID_UNIT(u) (u==UG_UNIT_PX||u==UG_UNIT_MM||u==UG_UNIT_PT)
|
||||||
#define UG_ERR(...) err(errno, "__FUNCTION__: " __VA_ARGS__)
|
#define UG_ERR(...) err(errno, "__FUNCTION__: " __VA_ARGS__)
|
||||||
#define BETWEEN(x, min, max) (x <= max && x >= min)
|
#define BETWEEN(x, min, max) (x <= max && x >= min)
|
||||||
#define INTERSECTS(v, r) (BETWEEN(v.x, r.x, r.x+r.w) && BETWEEN(v.y, r.y, r.y+r.h))
|
#define INTERSECTS(v, r) (BETWEEN(v.x, r.x, r.x+r.w) && BETWEEN(v.y, r.y, r.y+r.h))
|
||||||
#define CAP(x, s) { if (x < s) x = s; }
|
#define TEST(f, b) (f & b)
|
||||||
|
#define MAX(a, b) (a > b ? a : b)
|
||||||
|
|
||||||
|
|
||||||
// default style
|
// default style
|
||||||
@ -35,7 +42,7 @@ static const ug_style_t default_style = {
|
|||||||
.bg_color = RGB_FORMAT(0x0000ff),
|
.bg_color = RGB_FORMAT(0x0000ff),
|
||||||
.border.t = SIZE_PX(3),
|
.border.t = SIZE_PX(3),
|
||||||
.border.b = SIZE_PX(3),
|
.border.b = SIZE_PX(3),
|
||||||
.border.l = SIZE_PX(3),
|
.border.l = SIZE_PX(10),
|
||||||
.border.r = SIZE_PX(3),
|
.border.r = SIZE_PX(3),
|
||||||
.border.color = RGB_FORMAT(0x00ff00),
|
.border.color = RGB_FORMAT(0x00ff00),
|
||||||
.titlebar.height = SIZE_PX(20),
|
.titlebar.height = SIZE_PX(20),
|
||||||
@ -104,6 +111,28 @@ static ug_id_t hash(const void *data, unsigned int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int size_to_px(ug_ctx_t *ctx, ug_size_t s)
|
||||||
|
{
|
||||||
|
switch (s.unit) {
|
||||||
|
case UG_UNIT_MM: return roundf(s.size.f * ctx->ppm);
|
||||||
|
case UG_UNIT_PT: return roundf(s.size.f * ctx->ppd);
|
||||||
|
case UG_UNIT_PX: return s.size.i;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ug_rect_t div_to_rect(ug_ctx_t *ctx, ug_div_t *div)
|
||||||
|
{
|
||||||
|
ug_rect_t r;
|
||||||
|
r.x = size_to_px(ctx, div->x);
|
||||||
|
r.y = size_to_px(ctx, div->y);
|
||||||
|
r.w = size_to_px(ctx, div->w);
|
||||||
|
r.h = size_to_px(ctx, div->h);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// update the style cache with the correct sizes in pixels and colors
|
// update the style cache with the correct sizes in pixels and colors
|
||||||
static void update_style_cache(ug_ctx_t *ctx)
|
static void update_style_cache(ug_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
@ -139,7 +168,6 @@ ug_ctx_t *ug_ctx_new(void)
|
|||||||
err(errno, "__FUNCTION__:" "Could not allocate context: %s", strerror(errno));
|
err(errno, "__FUNCTION__:" "Could not allocate context: %s", strerror(errno));
|
||||||
memset(ctx, 0, sizeof(ug_ctx_t));
|
memset(ctx, 0, sizeof(ug_ctx_t));
|
||||||
|
|
||||||
ctx->unit = UG_UNIT_PX;
|
|
||||||
ctx->style = &default_style;
|
ctx->style = &default_style;
|
||||||
ctx->style_px = &style_cache;
|
ctx->style_px = &style_cache;
|
||||||
ug_ctx_set_displayinfo(ctx, DEF_SCALE, DEF_PPI);
|
ug_ctx_set_displayinfo(ctx, DEF_SCALE, DEF_PPI);
|
||||||
@ -218,18 +246,6 @@ int ug_ctx_set_style(ug_ctx_t *ctx, const ug_style_t *style)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ug_ctx_set_unit(ug_ctx_t *ctx, ug_unit_t unit)
|
|
||||||
{
|
|
||||||
TEST_CTX(ctx);
|
|
||||||
if (!IS_VALID_UNIT(unit))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
ctx->unit = unit;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*=============================================================================*
|
/*=============================================================================*
|
||||||
* Container Operations *
|
* Container Operations *
|
||||||
*=============================================================================*/
|
*=============================================================================*/
|
||||||
@ -255,27 +271,13 @@ static ug_container_t *get_container(ug_ctx_t *ctx, ug_id_t id)
|
|||||||
|
|
||||||
// update the container dimensions and position according to the context information,
|
// update the container dimensions and position according to the context information,
|
||||||
// also handle resizing, moving, ect. if allowed by the container
|
// also handle resizing, moving, ect. if allowed by the container
|
||||||
static void update_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
static void position_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
||||||
{
|
{
|
||||||
ug_rect_t *rect, *rca;
|
ug_rect_t *rect, *rca;
|
||||||
rect = &cnt->rect;
|
rect = &cnt->rect;
|
||||||
rca = &cnt->rca;
|
rca = &cnt->rca;
|
||||||
|
|
||||||
// if the container is new it has never been converted to pixels
|
if (ctx->ppi != ctx->last_ppi) {
|
||||||
if (cnt->unit != UG_UNIT_PX) {
|
|
||||||
float scale = 1.0;
|
|
||||||
switch (ctx->unit) {
|
|
||||||
case UG_UNIT_MM: scale = ctx->ppm; break;
|
|
||||||
case UG_UNIT_PT: scale = ctx->ppd; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
rect->x = roundf(rect->fx * scale);
|
|
||||||
rect->y = roundf(rect->fy * scale);
|
|
||||||
rect->w = roundf(rect->fw * scale);
|
|
||||||
rect->h = roundf(rect->fh * scale);
|
|
||||||
|
|
||||||
cnt->unit = UG_UNIT_PX;
|
|
||||||
} else if (ctx->ppi != ctx->last_ppi) {
|
|
||||||
// if the scale has been updated than we need to scale the container
|
// if the scale has been updated than we need to scale the container
|
||||||
// as well
|
// as well
|
||||||
float scale = ctx->ppi / ctx->last_ppi;
|
float scale = ctx->ppi / ctx->last_ppi;
|
||||||
@ -317,84 +319,131 @@ static void update_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const ug_style_t *s = ctx->style_px;
|
const ug_style_t *s = ctx->style_px;
|
||||||
int bl = s->cnt.border.l.size;
|
int bl = s->cnt.border.l.size.i;
|
||||||
int br = s->cnt.border.r.size;
|
int br = s->cnt.border.r.size.i;
|
||||||
int bt = s->cnt.border.t.size;
|
int bt = s->cnt.border.t.size.i;
|
||||||
int bb = s->cnt.border.b.size;
|
int bb = s->cnt.border.b.size.i;
|
||||||
int hh = s->cnt.titlebar.height.size;
|
int hh = s->cnt.titlebar.height.size.i;
|
||||||
int cw = ctx->size.w;
|
int cw = ctx->size.w;
|
||||||
int ch = ctx->size.h;
|
int ch = ctx->size.h;
|
||||||
|
|
||||||
// 0 -> take all the space, <0 -> take absolute
|
// handle relative sizes
|
||||||
if (rect->w < 0) rca->w = -rect->w;
|
if (rect->w == 0) rca->w = cw;
|
||||||
if (rect->h < 0) rca->h = -rect->h;
|
|
||||||
|
|
||||||
// handle relative position
|
|
||||||
// and move to fit borders
|
|
||||||
if (rect->w == 0) rca->w = cw - br - bl;
|
|
||||||
else rca->w += bl + br;
|
else rca->w += bl + br;
|
||||||
if (rect->h == 0) rca->h = ch - bt - bb;
|
if (rect->h == 0) rca->h = ch;
|
||||||
else if (cnt->flags & UG_CNT_MOVABLE) rca->h += hh + 2*bt + bb;
|
else if (TEST(cnt->flags, UG_CNT_MOVABLE)) rca->h += hh + 2*bt + bb;
|
||||||
else rca->h += bt + bb;
|
else rca->h += bt + bb;
|
||||||
|
|
||||||
// <0 -> relative to the right margin
|
// if the container is not fixed than it can have positions outside of the
|
||||||
if (rect->x < 0) rca->x = cw - rca->w + rca->x;
|
// main window, thus negative
|
||||||
if (rect->y < 0) rca->y = ch - rca->h + rca->y;
|
if (!TEST(cnt->flags, UG_CNT_MOVABLE)) {
|
||||||
|
// <0 -> relative to the right margin
|
||||||
|
if (rect->x <= 0) rca->x = cw - rca->w + rca->x;
|
||||||
|
if (rect->y <= 0) rca->y = ch - rca->h + rca->y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handle_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
||||||
|
{
|
||||||
// if we had focus the frame before, then do shit
|
// if we had focus the frame before, then do shit
|
||||||
if (ctx->hover.cnt_last != cnt->id)
|
if (ctx->active.cnt != cnt->id)
|
||||||
goto cnt_draw;
|
return;
|
||||||
|
|
||||||
// mouse pressed handle resize, for simplicity containers can only
|
// mouse pressed handle resize, for simplicity containers can only
|
||||||
// be resized from the bottom and right border
|
// be resized from the bottom and right border
|
||||||
// TODO: bring selected container to the top of the stack
|
// TODO: bring selected container to the top of the stack
|
||||||
if (!(ctx->mouse.down_mask & UG_BTN_LEFT) ||
|
if (!TEST(ctx->mouse.down_mask, UG_BTN_LEFT) ||
|
||||||
!(cnt->flags & (UG_CNT_RESIZABLE | UG_CNT_MOVABLE)))
|
!TEST(cnt->flags, (RESIZEALL | UG_CNT_MOVABLE)))
|
||||||
goto cnt_draw;
|
return;
|
||||||
|
|
||||||
|
ug_rect_t *rect, *rca;
|
||||||
|
rect = &cnt->rect;
|
||||||
|
rca = &cnt->rca;
|
||||||
|
|
||||||
|
const ug_style_t *s = ctx->style_px;
|
||||||
|
int bl = s->cnt.border.l.size.i;
|
||||||
|
int br = s->cnt.border.r.size.i;
|
||||||
|
int bt = s->cnt.border.t.size.i;
|
||||||
|
int bb = s->cnt.border.b.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 (cnt->flags & UG_CNT_MOVABLE) {
|
if (TEST(cnt->flags, UG_CNT_MOVABLE)) {
|
||||||
minx = rca->x;
|
minx = rca->x + bl;
|
||||||
maxx = rca->x + rca->w - br;
|
maxx = rca->x + rca->w - br;
|
||||||
miny = rca->y;
|
miny = rca->y + bt;
|
||||||
maxy = rca->y + bt + hh;
|
maxy = rca->y + bt + hh;
|
||||||
if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) {
|
if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) {
|
||||||
// if a relative container has been moved consider it no
|
|
||||||
// longer relative
|
|
||||||
if (rect->x < 0)
|
|
||||||
rect->x = cw + rect->x - rect->w - bl - br;
|
|
||||||
if (rect->y < 0)
|
|
||||||
rect->y = ch + rect->y - rect->h - 2*bt - bb - hh;
|
|
||||||
|
|
||||||
rect->x += ctx->mouse.delta.x;
|
rect->x += ctx->mouse.delta.x;
|
||||||
rect->y += ctx->mouse.delta.y;
|
rect->y += ctx->mouse.delta.y;
|
||||||
rca->x += ctx->mouse.delta.x;
|
rca->x += ctx->mouse.delta.x;
|
||||||
rca->y += ctx->mouse.delta.y;
|
rca->y += ctx->mouse.delta.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cnt->flags & UG_CNT_RESIZABLE) {
|
// right border resize
|
||||||
// right border resize
|
if (TEST(cnt->flags, UG_CNT_RESIZE_RIGHT)) {
|
||||||
minx = rca->x + rca->w - br;
|
minx = rca->x + rca->w - br;
|
||||||
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;
|
||||||
if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) {
|
if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) {
|
||||||
rect->w += ctx->mouse.delta.x;
|
rect->w = MAX(10, rect->w + ctx->mouse.delta.x);
|
||||||
rca->w += ctx->mouse.delta.x;
|
rca->w = MAX(10, rca->w + ctx->mouse.delta.x);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// bottom border resize
|
// left border resize
|
||||||
|
if (TEST(cnt->flags, UG_CNT_RESIZE_LEFT)) {
|
||||||
|
minx = rca->x;
|
||||||
|
maxx = rca->x + bl;
|
||||||
|
miny = rca->y;
|
||||||
|
maxy = rca->y + rca->h;
|
||||||
|
if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) {
|
||||||
|
if (rect->w - ctx->mouse.delta.x >= 10) {
|
||||||
|
rect->w -= ctx->mouse.delta.x;
|
||||||
|
if (TEST(cnt->flags, UG_CNT_MOVABLE))
|
||||||
|
rect->x += ctx->mouse.delta.x;
|
||||||
|
}
|
||||||
|
if (rca->w - ctx->mouse.delta.x >= 10) {
|
||||||
|
rca->w -= ctx->mouse.delta.x;
|
||||||
|
rca->x += ctx->mouse.delta.x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottom border resize
|
||||||
|
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 - bb;
|
||||||
maxy = rca->y + rca->h;
|
maxy = rca->y + rca->h;
|
||||||
if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) {
|
if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) {
|
||||||
rect->h += ctx->mouse.delta.y;
|
rect->h += ctx->mouse.delta.y;
|
||||||
rca->h += ctx->mouse.delta.y;
|
rca->h += ctx->mouse.delta.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// top border resize
|
||||||
|
if (TEST(cnt->flags, UG_CNT_RESIZE_TOP)) {
|
||||||
|
minx = rca->x;
|
||||||
|
maxx = rca->x + rca->w;
|
||||||
|
miny = rca->y;
|
||||||
|
maxy = rca->y + bt;
|
||||||
|
if (BETWEEN(mpos.x, minx, maxx) && BETWEEN(mpos.y, miny, maxy)) {
|
||||||
|
if (rect->h - ctx->mouse.delta.y >= 10) {
|
||||||
|
rect->h -= ctx->mouse.delta.y;
|
||||||
|
if (TEST(cnt->flags, UG_CNT_MOVABLE))
|
||||||
|
rect->y += ctx->mouse.delta.y;
|
||||||
|
}
|
||||||
|
if (rca->h - ctx->mouse.delta.y >= 10) {
|
||||||
|
rca->h -= ctx->mouse.delta.y;
|
||||||
|
rca->y += ctx->mouse.delta.y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,11 +455,21 @@ static void update_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
|||||||
// container structure
|
// container structure
|
||||||
|
|
||||||
// push the appropriate rectangles to the drawing stack
|
// push the appropriate rectangles to the drawing stack
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void draw_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
||||||
|
{
|
||||||
ug_rect_t draw_rect;
|
ug_rect_t draw_rect;
|
||||||
cnt_draw:
|
const ug_style_t *s = ctx->style_px;
|
||||||
|
int bl = s->cnt.border.l.size.i;
|
||||||
|
int br = s->cnt.border.r.size.i;
|
||||||
|
int bt = s->cnt.border.t.size.i;
|
||||||
|
int bb = s->cnt.border.b.size.i;
|
||||||
|
int hh = s->cnt.titlebar.height.size.i;
|
||||||
|
|
||||||
// push outline
|
// push outline
|
||||||
draw_rect = *rca;
|
draw_rect = cnt->rca;
|
||||||
push_rect_command(ctx, &draw_rect, s->cnt.border.color);
|
push_rect_command(ctx, &draw_rect, s->cnt.border.color);
|
||||||
|
|
||||||
// titlebar
|
// titlebar
|
||||||
@ -423,7 +482,7 @@ static void update_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// push main body
|
// push main body
|
||||||
draw_rect = *rca;
|
draw_rect = cnt->rca;
|
||||||
draw_rect.x += bl;
|
draw_rect.x += bl;
|
||||||
draw_rect.y += bt;
|
draw_rect.y += bt;
|
||||||
draw_rect.w -= bl + br;
|
draw_rect.w -= bl + br;
|
||||||
@ -439,12 +498,12 @@ static void update_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
|||||||
|
|
||||||
// a floating container can be placed anywhere and can be resized, acts like a
|
// a floating container can be placed anywhere and can be resized, acts like a
|
||||||
// window inside another window
|
// window inside another window
|
||||||
int ug_container_floating(ug_ctx_t *ctx, const char *name, ug_rect_t rect)
|
int ug_container_floating(ug_ctx_t *ctx, const char *name, ug_div_t div)
|
||||||
{
|
{
|
||||||
TEST_CTX(ctx);
|
TEST_CTX(ctx);
|
||||||
// TODO: verify rect
|
// TODO: verify div
|
||||||
|
|
||||||
ug_id_t id = name ? hash(name, strlen(name)) : hash(&rect, sizeof(ug_rect_t));
|
ug_id_t id = name ? hash(name, strlen(name)) : hash(&div, sizeof(ug_div_t));
|
||||||
ug_container_t *cnt = get_container(ctx, id);
|
ug_container_t *cnt = get_container(ctx, id);
|
||||||
|
|
||||||
if (cnt->id) {
|
if (cnt->id) {
|
||||||
@ -452,13 +511,71 @@ int ug_container_floating(ug_ctx_t *ctx, const char *name, ug_rect_t rect)
|
|||||||
} else {
|
} else {
|
||||||
cnt->id = id;
|
cnt->id = id;
|
||||||
cnt->max_size = max_size;
|
cnt->max_size = max_size;
|
||||||
cnt->rect = rect;
|
cnt->rect = div_to_rect(ctx, &div);
|
||||||
cnt->unit = ctx->unit;
|
cnt->flags = UG_CNT_MOVABLE | RESIZEALL |
|
||||||
cnt->flags = UG_CNT_MOVABLE | UG_CNT_RESIZABLE |
|
|
||||||
UG_CNT_SCROLL_X | UG_CNT_SCROLL_Y ;
|
UG_CNT_SCROLL_X | UG_CNT_SCROLL_Y ;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_container(ctx, cnt);
|
// FIXME: floating containers should always stay on top
|
||||||
|
position_container(ctx, cnt);
|
||||||
|
handle_container(ctx, cnt);
|
||||||
|
draw_container(ctx, cnt);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ug_container_sidebar(ug_ctx_t *ctx, const char *name, ug_size_t size, int side)
|
||||||
|
{
|
||||||
|
TEST_CTX(ctx);
|
||||||
|
|
||||||
|
ug_id_t id = 0;
|
||||||
|
if (name) {
|
||||||
|
id = hash(name, strlen(name));
|
||||||
|
} else {
|
||||||
|
int blob[3] = { size.size.i, size.unit, side};
|
||||||
|
id = hash(blob, sizeof(blob));
|
||||||
|
}
|
||||||
|
|
||||||
|
ug_container_t *cnt = get_container(ctx, id);
|
||||||
|
|
||||||
|
if (cnt->id) {
|
||||||
|
// nothing? maybe we can skip updating all dimensions and stuff
|
||||||
|
} else {
|
||||||
|
cnt->id = id;
|
||||||
|
cnt->max_size = max_size;
|
||||||
|
cnt->flags = UG_CNT_SCROLL_X | UG_CNT_SCROLL_Y;
|
||||||
|
ug_rect_t rect = {0};
|
||||||
|
switch (side) {
|
||||||
|
case UG_SIDE_BOTTOM:
|
||||||
|
cnt->flags |= UG_CNT_RESIZE_TOP;
|
||||||
|
// FIXME: we do not support relative zero position yet
|
||||||
|
rect.y = 0;
|
||||||
|
rect.h = size_to_px(ctx, size);
|
||||||
|
break;
|
||||||
|
case UG_SIDE_TOP:
|
||||||
|
cnt->flags |= UG_CNT_RESIZE_BOTTOM;
|
||||||
|
rect.h = size_to_px(ctx, size);
|
||||||
|
break;
|
||||||
|
case UG_SIDE_RIGHT:
|
||||||
|
cnt->flags |= UG_CNT_RESIZE_LEFT;
|
||||||
|
rect.x = 0;
|
||||||
|
rect.w = size_to_px(ctx, size);
|
||||||
|
break;
|
||||||
|
case UG_SIDE_LEFT:
|
||||||
|
cnt->flags |= UG_CNT_RESIZE_RIGHT;
|
||||||
|
rect.w = size_to_px(ctx, size);
|
||||||
|
break;
|
||||||
|
default: return -1;
|
||||||
|
}
|
||||||
|
cnt->rect = rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
position_container(ctx, cnt);
|
||||||
|
handle_container(ctx, cnt);
|
||||||
|
draw_container(ctx, cnt);
|
||||||
|
|
||||||
|
// TODO: change available context space to reflect adding a sidebar
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -526,15 +643,20 @@ int ug_frame_begin(ug_ctx_t *ctx)
|
|||||||
|
|
||||||
// update hover index
|
// update hover index
|
||||||
ug_vec2_t v = ctx->mouse.pos;
|
ug_vec2_t v = ctx->mouse.pos;
|
||||||
// printf("mouse: x=%d, y=%d\n", ctx->mouse.pos.x, ctx->mouse.pos.x);
|
|
||||||
for (int i = 0; i < ctx->cnt_stack.idx; i++) {
|
for (int i = 0; i < ctx->cnt_stack.idx; i++) {
|
||||||
ug_rect_t r = ctx->cnt_stack.items[i].rca;
|
ug_rect_t r = ctx->cnt_stack.items[i].rca;
|
||||||
if (INTERSECTS(v, r)) {
|
if (INTERSECTS(v, r)) {
|
||||||
ctx->hover.cnt = ctx->cnt_stack.items[i].id;
|
ctx->hover.cnt = ctx->cnt_stack.items[i].id;
|
||||||
// printf("intersects! %.8x\n", ctx->hover.cnt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update active container
|
||||||
|
if (MOUSEDOWN(ctx, UG_BTN_LEFT)) {
|
||||||
|
ctx->active.cnt = ctx->hover.cnt;
|
||||||
|
} else if (MOUSEUP(ctx, UG_BTN_LEFT)) {
|
||||||
|
ctx->active.cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
55
ugui.h
55
ugui.h
@ -5,22 +5,18 @@
|
|||||||
#define BIT(n) (1 << n)
|
#define BIT(n) (1 << n)
|
||||||
#define RGBA_FORMAT(x) { .a=x&0xff, .b=(x>>8)&0xff, .g=(x>>16)&0xff, .r=(x>>24)&0xff }
|
#define RGBA_FORMAT(x) { .a=x&0xff, .b=(x>>8)&0xff, .g=(x>>16)&0xff, .r=(x>>24)&0xff }
|
||||||
#define RGB_FORMAT(x) { .a=0xff, .b=x&0xff, .g=(x>>8)&0xff, .r=(x>>16)&0xff }
|
#define RGB_FORMAT(x) { .a=0xff, .b=x&0xff, .g=(x>>8)&0xff, .r=(x>>16)&0xff }
|
||||||
#define SIZE_PX(x) { .size=x, .unit=UG_UNIT_PX }
|
#define SIZE_PX(x) { .size.i=x, .unit=UG_UNIT_PX }
|
||||||
#define SIZE_MM(x) { .size=x, .unit=UG_UNIT_MM }
|
#define SIZE_MM(x) { .size.f=x, .unit=UG_UNIT_MM }
|
||||||
#define SIZE_PT(x) { .size=x, .unit=UG_UNIT_PT }
|
#define SIZE_PT(x) { .size.f=x, .unit=UG_UNIT_PT }
|
||||||
|
|
||||||
// basic types
|
// basic types
|
||||||
typedef unsigned int ug_id_t;
|
typedef unsigned int ug_id_t;
|
||||||
typedef struct { union {int x, w;}; union {int y, h;}; } ug_vec2_t;
|
typedef struct { union {int x, w;}; union {int y, h;}; } ug_vec2_t;
|
||||||
typedef struct { unsigned char a, b, g, r; } ug_color_t;
|
typedef struct { unsigned char a, b, g, r; } ug_color_t;
|
||||||
typedef struct { int size, unit; } ug_size_t;
|
typedef struct { int x, y, w, h; } ug_rect_t;
|
||||||
|
typedef struct { union {int i; float f;} size; int unit; } ug_size_t;
|
||||||
typedef struct {
|
// div has information about the phisical dimension
|
||||||
union { int x; float fx; };
|
typedef struct { ug_size_t x, y, w, h;} ug_div_t;
|
||||||
union { int y; float fy; };
|
|
||||||
union { int w; float fw; };
|
|
||||||
union { int h; float fh; };
|
|
||||||
} ug_rect_t;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UG_UNIT_PX = 0,
|
UG_UNIT_PX = 0,
|
||||||
@ -34,7 +30,6 @@ typedef enum {
|
|||||||
// the z index of a container is determined by it's position on the stack
|
// the z index of a container is determined by it's position on the stack
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ug_id_t id;
|
ug_id_t id;
|
||||||
ug_unit_t unit;
|
|
||||||
ug_rect_t rect;
|
ug_rect_t rect;
|
||||||
// absolute position rect
|
// absolute position rect
|
||||||
ug_rect_t rca;
|
ug_rect_t rca;
|
||||||
@ -44,10 +39,13 @@ typedef struct {
|
|||||||
|
|
||||||
// the container flags
|
// the container flags
|
||||||
enum {
|
enum {
|
||||||
UG_CNT_MOVABLE = BIT(0), // can be moved
|
UG_CNT_MOVABLE = BIT(0), // can be moved
|
||||||
UG_CNT_RESIZABLE = BIT(1), // can be resized
|
UG_CNT_RESIZE_RIGHT = BIT(1), // can be resized
|
||||||
UG_CNT_SCROLL_X = BIT(2), // can have horizontal scrolling
|
UG_CNT_RESIZE_BOTTOM = BIT(2), // can be resized
|
||||||
UG_CNT_SCROLL_Y = BIT(3), // can have vertical scrolling
|
UG_CNT_RESIZE_LEFT = BIT(3), // can be resized
|
||||||
|
UG_CNT_RESIZE_TOP = BIT(4), // can be resized
|
||||||
|
UG_CNT_SCROLL_X = BIT(5), // can have horizontal scrolling
|
||||||
|
UG_CNT_SCROLL_Y = BIT(6), // can have vertical scrolling
|
||||||
};
|
};
|
||||||
|
|
||||||
// style, defines default height, width, color, margins, borders, etc
|
// style, defines default height, width, color, margins, borders, etc
|
||||||
@ -116,6 +114,13 @@ typedef enum {
|
|||||||
UG_CMD_RECT,
|
UG_CMD_RECT,
|
||||||
} ug_cmd_type_t;
|
} ug_cmd_type_t;
|
||||||
|
|
||||||
|
// window side
|
||||||
|
enum {
|
||||||
|
UG_SIDE_TOP = 0,
|
||||||
|
UG_SIDE_BOTTOM,
|
||||||
|
UG_SIDE_LEFT,
|
||||||
|
UG_SIDE_RIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
// mouse buttons
|
// mouse buttons
|
||||||
enum {
|
enum {
|
||||||
@ -145,14 +150,15 @@ typedef struct {
|
|||||||
ug_id_t cnt, elem;
|
ug_id_t cnt, elem;
|
||||||
ug_id_t cnt_last, elem_last;
|
ug_id_t cnt_last, elem_last;
|
||||||
} hover;
|
} hover;
|
||||||
|
// active is updated on mousedown and released on mouseup
|
||||||
// the id of the "active" element, active means different things for
|
// the id of the "active" element, active means different things for
|
||||||
// different elements, for exaple active for a button means to be pressed,
|
// different elements, for exaple active for a button means to be pressed,
|
||||||
// and for a text box it means to be focused
|
// and for a text box it means to be focused
|
||||||
ug_id_t active;
|
struct {
|
||||||
|
ug_id_t cnt, elem;
|
||||||
|
} active;
|
||||||
// count the frames for fun
|
// count the frames for fun
|
||||||
unsigned long int frame;
|
unsigned long int frame;
|
||||||
// current measurement unit
|
|
||||||
ug_unit_t unit;
|
|
||||||
// mouse data
|
// mouse data
|
||||||
struct {
|
struct {
|
||||||
ug_vec2_t pos;
|
ug_vec2_t pos;
|
||||||
@ -186,7 +192,6 @@ void ug_ctx_free(ug_ctx_t *ctx);
|
|||||||
int ug_ctx_set_displayinfo(ug_ctx_t *ctx, float scale, float ppi);
|
int ug_ctx_set_displayinfo(ug_ctx_t *ctx, float scale, float ppi);
|
||||||
int ug_ctx_set_drawableregion(ug_ctx_t *ctx, ug_vec2_t size);
|
int ug_ctx_set_drawableregion(ug_ctx_t *ctx, ug_vec2_t size);
|
||||||
int ug_ctx_set_style(ug_ctx_t *ctx, const ug_style_t *style);
|
int ug_ctx_set_style(ug_ctx_t *ctx, const ug_style_t *style);
|
||||||
int ug_ctx_set_unit(ug_ctx_t *ctx, ug_unit_t unit);
|
|
||||||
|
|
||||||
|
|
||||||
// define containers, name is used as a salt for the container id, all sizes are
|
// define containers, name is used as a salt for the container id, all sizes are
|
||||||
@ -194,14 +199,14 @@ int ug_ctx_set_unit(ug_ctx_t *ctx, ug_unit_t unit);
|
|||||||
|
|
||||||
// a floating container can be placed anywhere and can be resized, acts like a
|
// a floating container can be placed anywhere and can be resized, acts like a
|
||||||
// window inside another window
|
// window inside another window
|
||||||
int ug_container_floating(ug_ctx_t *ctx, const char *name, ug_rect_t rect);
|
int ug_container_floating(ug_ctx_t *ctx, const char *name, ug_div_t div);
|
||||||
// like a floating container but cannot be resized
|
// like a floating container but cannot be resized
|
||||||
int ug_container_popup(ug_ctx_t *ctx, const char *name, ug_rect_t rect);
|
int ug_container_popup(ug_ctx_t *ctx, const char *name, ug_rect_t rect);
|
||||||
// a menu bar is a container of fixed height, cannot be resized and sits at the
|
// a menu bar is a container of fixed height, cannot be resized and sits at the
|
||||||
// top of the window
|
// top of the window
|
||||||
int ug_container_menu_bar(ug_ctx_t *ctx, const char *name, int height);
|
int ug_container_menu_bar(ug_ctx_t *ctx, const char *name, int height);
|
||||||
// a sidebar is a variable size container anchored to one side of the window
|
// a sidebar is a variable size container anchored to one side of the window
|
||||||
int ug_container_sidebar(ug_ctx_t *ctx, const char *name, int width);
|
int ug_container_sidebar(ug_ctx_t *ctx, const char *name, ug_size_t size, int side);
|
||||||
// a body is a container that scales with the window, sits at it's center and cannot
|
// a body is a container that scales with the window, sits at it's center and cannot
|
||||||
// be resized
|
// be resized
|
||||||
int ug_container_body(ug_ctx_t *ctx, const char *name);
|
int ug_container_body(ug_ctx_t *ctx, const char *name);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user