From 575bd706fd4cc2f8b21e1e2cf78c9cb33fd6f93f Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Sat, 10 Dec 2022 14:10:11 +0100 Subject: [PATCH] bring floating containers to the top --- test/main.c | 16 ++++++----- ugui.c | 77 ++++++++++++++++++++++++++++++++++++++++++----------- ugui.h | 15 ++++++----- 3 files changed, 80 insertions(+), 28 deletions(-) diff --git a/test/main.c b/test/main.c index 8671612..79758b0 100644 --- a/test/main.c +++ b/test/main.c @@ -175,17 +175,21 @@ int main(void) ug_frame_begin(ctx); -// 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_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_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_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_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, "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_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_frame_end(ctx); // fill background diff --git a/ugui.c b/ugui.c index 655d804..f30d572 100644 --- a/ugui.c +++ b/ugui.c @@ -29,6 +29,7 @@ ) #define CNT_STATE_ALL ( \ + CNT_STATE_NONE | \ CNT_STATE_MOVING | \ CNT_STATE_RESIZE_T | \ CNT_STATE_RESIZE_B | \ @@ -280,13 +281,49 @@ static ug_container_t *get_container(ug_ctx_t *ctx, ug_id_t id) } } // if the container was not already there allocate a new one - if (!c) + if (!c) { GET_FROM_STACK(ctx->cnt_stack, c); + // the stack is not sorted + ctx->cnt_stack.sorted = 0; + } return c; } +// sort the conatiner stack so that floating conatiners always stay on top and +// the active floating conatiner i son top of everything +static void sort_containers(ug_ctx_t *ctx) +{ + if (ctx->cnt_stack.sorted) + return; + + int tot = ctx->cnt_stack.idx; + if (!tot) + return; + for (int i = 0; i < tot; i++) { + ug_container_t *cnt = &ctx->cnt_stack.items[i]; + // move floating containers to the top + // FIXME: this is really shit + if (TEST(cnt->flags, UG_CNT_FLOATING)) { + int y = tot; + + ug_container_t *s = ctx->cnt_stack.items; + ug_container_t c = *cnt; + + if (ctx->active.cnt != c.id) + for (; y > 0 && TEST(s[y-1].flags, UG_CNT_FLOATING); y--); + + if (i >= y) + break; + + memmove(&s[i], &s[i+1], (y - i) * sizeof(ug_container_t)); + s[y-1] = c; + } + } + ctx->cnt_stack.sorted = 1; +} + // update the container dimensions and position according to the context information, // also handle resizing, moving, ect. if allowed by the container static void position_container(ug_ctx_t *ctx, ug_container_t *cnt) @@ -351,14 +388,14 @@ static void position_container(ug_ctx_t *ctx, ug_container_t *cnt) if (rect->w == 0) rca->w = cw; else rca->w += bl + br; 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_FLOATING)) rca->h += hh + 2*bt + bb; else rca->h += bt + bb; // if the container is not fixed than it can have positions outside of the // main window, thus negative - if (!TEST(cnt->flags, UG_CNT_MOVABLE)) { - printf("origin: x=%d y=%d w=%d h=%d\t", ctx->origin.x, ctx->origin.y, ctx->origin.w, ctx->origin.h); + if (!TEST(cnt->flags, UG_CNT_FLOATING)) { + //printf("origin: x=%d y=%d w=%d h=%d\t", ctx->origin.x, ctx->origin.y, ctx->origin.w, ctx->origin.h); // <0 -> relative to the right margin if (rect->x < 0) rca->x = cx + cw - rca->w + rca->x + 1; else rca->x = cx; @@ -384,7 +421,7 @@ static void position_container(ug_ctx_t *ctx, ug_container_t *cnt) ctx->origin.y -= rca->h; } } - printf("new origin: x=%d y=%d w=%d h=%d\n", ctx->origin.x, ctx->origin.y, ctx->origin.w, ctx->origin.h); + //printf("new origin: x=%d y=%d w=%d h=%d\n", ctx->origin.x, ctx->origin.y, ctx->origin.w, ctx->origin.h); } } @@ -402,7 +439,7 @@ void handle_container(ug_ctx_t *ctx, ug_container_t *cnt) // be resized from the bottom and right border // TODO: bring selected container to the top of the stack if (!HELD(ctx, UG_BTN_LEFT) || - !TEST(cnt->flags, (RESIZEALL | UG_CNT_MOVABLE))) + !TEST(cnt->flags, (RESIZEALL | UG_CNT_FLOATING))) return; ug_rect_t *rect, *rca; @@ -420,7 +457,7 @@ void handle_container(ug_ctx_t *ctx, ug_container_t *cnt) int minx, maxx, miny, maxy; // handle movable windows - if (TEST(cnt->flags, UG_CNT_MOVABLE)) { + if (TEST(cnt->flags, UG_CNT_FLOATING)) { minx = rca->x + bl; maxx = rca->x + rca->w - br; miny = rca->y + bt; @@ -467,7 +504,7 @@ void handle_container(ug_ctx_t *ctx, ug_container_t *cnt) if (rect->w - ctx->mouse.delta.x >= 10) { rect->w -= ctx->mouse.delta.x; - if (TEST(cnt->flags, UG_CNT_MOVABLE)) + if (TEST(cnt->flags, UG_CNT_FLOATING)) rect->x += ctx->mouse.delta.x; } if (rca->w - ctx->mouse.delta.x >= 10) { @@ -505,7 +542,7 @@ void handle_container(ug_ctx_t *ctx, ug_container_t *cnt) if (rect->h - ctx->mouse.delta.y >= 10) { rect->h -= ctx->mouse.delta.y; - if (TEST(cnt->flags, UG_CNT_MOVABLE)) + if (TEST(cnt->flags, UG_CNT_FLOATING)) rect->y += ctx->mouse.delta.y; } if (rca->h - ctx->mouse.delta.y >= 10) { @@ -515,6 +552,11 @@ void handle_container(ug_ctx_t *ctx, ug_container_t *cnt) } } + // if we were not resized but we are still active it means we are doing + // something to the contained elements, as such set state to none + if ((cnt->flags & CNT_STATE_ALL) == 0) + cnt->flags |= CNT_STATE_NONE; + // TODO: what if I want to close a floating container? // Maybe add a UG_CNT_CLOSABLE flag? @@ -541,7 +583,7 @@ void draw_container(ug_ctx_t *ctx, ug_container_t *cnt) push_rect_command(ctx, &draw_rect, s->cnt.border.color); // titlebar - if (cnt->flags & UG_CNT_MOVABLE) { + if (cnt->flags & UG_CNT_FLOATING) { draw_rect.x += bl; draw_rect.y += bt; draw_rect.w -= bl + br; @@ -555,7 +597,7 @@ void draw_container(ug_ctx_t *ctx, ug_container_t *cnt) draw_rect.y += bt; draw_rect.w -= bl + br; draw_rect.h -= bt + bb; - if (cnt->flags & UG_CNT_MOVABLE) { + if (cnt->flags & UG_CNT_FLOATING) { draw_rect.y += bt + hh; draw_rect.h -= bt + hh; } @@ -580,14 +622,12 @@ int ug_container_floating(ug_ctx_t *ctx, const char *name, ug_div_t div) cnt->id = id; cnt->max_size = max_size; cnt->rect = div_to_rect(ctx, &div); - cnt->flags = UG_CNT_MOVABLE | RESIZEALL | + cnt->flags = UG_CNT_FLOATING | RESIZEALL | UG_CNT_SCROLL_X | UG_CNT_SCROLL_Y ; } - // FIXME: floating containers should always stay on top position_container(ctx, cnt); handle_container(ctx, cnt); - draw_container(ctx, cnt); return 0; } @@ -641,7 +681,6 @@ int ug_container_sidebar(ug_ctx_t *ctx, const char *name, ug_size_t size, int si position_container(ctx, cnt); handle_container(ctx, cnt); - draw_container(ctx, cnt); // TODO: change available context space to reflect adding a sidebar @@ -717,6 +756,7 @@ int ug_frame_begin(ug_ctx_t *ctx) // update hover index ug_vec2_t v = ctx->mouse.pos; for (int i = 0; i < ctx->cnt_stack.idx; i++) { + printf("[%d]: %x\n", i, ctx->cnt_stack.items[i].id); ug_rect_t r = ctx->cnt_stack.items[i].rca; if (INTERSECTS(v, r)) { ctx->hover.cnt = ctx->cnt_stack.items[i].id; @@ -742,6 +782,13 @@ int ug_frame_end(ug_ctx_t *ctx) { TEST_CTX(ctx); + // before drawing floating contaners need to be drawn on top of the others + printf("sorted %d\n", ctx->cnt_stack.sorted); + sort_containers(ctx); + for (int i = 0; i < ctx->cnt_stack.idx; i++) + draw_container(ctx, &ctx->cnt_stack.items[i]); + + ctx->input_text[0] = '\0'; ctx->key.update = 0; ctx->mouse.hold ^= ctx->mouse.update; diff --git a/ugui.h b/ugui.h index e051705..540ba89 100644 --- a/ugui.h +++ b/ugui.h @@ -1,7 +1,7 @@ #ifndef _UG_HEADER #define _UG_HEADER -#define UG_STACK(T) struct { T *items; int idx; int size; } +#define UG_STACK(T) struct { T *items; int idx, size, sorted } #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 RGB_FORMAT(x) { .a=0xff, .b=x&0xff, .g=(x>>8)&0xff, .r=(x>>16)&0xff } @@ -39,7 +39,7 @@ typedef struct { // the container flags enum { - UG_CNT_MOVABLE = BIT(0), // can be moved + UG_CNT_FLOATING = BIT(0), // can be moved UG_CNT_RESIZE_RIGHT = BIT(1), // can be resized UG_CNT_RESIZE_BOTTOM = BIT(2), // can be resized UG_CNT_RESIZE_LEFT = BIT(3), // can be resized @@ -47,11 +47,12 @@ enum { UG_CNT_SCROLL_X = BIT(5), // can have horizontal scrolling UG_CNT_SCROLL_Y = BIT(6), // can have vertical scrolling // container state - CNT_STATE_MOVING = BIT(30), - CNT_STATE_RESIZE_T = BIT(29), - CNT_STATE_RESIZE_B = BIT(28), - CNT_STATE_RESIZE_L = BIT(27), - CNT_STATE_RESIZE_R = BIT(26), + CNT_STATE_NONE = BIT(30), + CNT_STATE_MOVING = BIT(29), + CNT_STATE_RESIZE_T = BIT(28), + CNT_STATE_RESIZE_B = BIT(27), + CNT_STATE_RESIZE_L = BIT(26), + CNT_STATE_RESIZE_R = BIT(25), }; // style, defines default height, width, color, margins, borders, etc