From 6fe3ce8787e10821b0cf8b037f4f986590aaa590 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Mon, 16 Jan 2023 16:53:37 +0100 Subject: [PATCH] reworked layout --- def_style.h | 4 +- test/main.c | 22 ++-- ugui.c | 363 ++++++++++++++++++++++++++++++---------------------- ugui.h | 12 +- 4 files changed, 231 insertions(+), 170 deletions(-) diff --git a/def_style.h b/def_style.h index 97c35b7..75ab6f6 100644 --- a/def_style.h +++ b/def_style.h @@ -13,7 +13,7 @@ static const ug_style_t default_style = { .margin = SIZE_PX(3), .border = { .color = RGB_FORMAT(0xf50a00), - .size = SIZE_PX(2), + .size = SIZE_PX(10), }, .title = { .color = { @@ -32,7 +32,7 @@ static const ug_style_t default_style = { .br = RGB_FORMAT(0xff00ff), }, .font_size = SIZE_PX(10), - .border = SIZE_PX(1), + .border = SIZE_PX(5), }, }; diff --git a/test/main.c b/test/main.c index 727ee2b..1939caf 100644 --- a/test/main.c +++ b/test/main.c @@ -191,33 +191,35 @@ int main(void) // ug_container_remove(ctx, "Menu fichissimo"); //} - //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 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_sidebar(ctx, "Top Sidebar", (ug_size_t)SIZE_MM(40), UG_SIDE_TOP); // 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")) // printf("No space!\n"); ug_layout_row(ctx); - ug_layout_row(ctx); + ug_layout_column(ctx); ug_element_button(ctx, "button 1", "hey", (ug_div_t){SQUARE(SIZE_MM(10))}); - ug_element_button(ctx, "button 2", "lol", (ug_div_t){SQUARE(SIZE_MM(10))}); - ug_layout_next_row(ctx); - ug_element_button(ctx, "button 3", "L", (ug_div_t){SQUARE(SIZE_MM(10))}); - ug_element_button(ctx, "button 4", "69", (ug_div_t){SQUARE(SIZE_MM(10))}); - ug_layout_next_row(ctx); + //ug_element_button(ctx, "button 2", "lol", (ug_div_t){SQUARE(SIZE_MM(10))}); + //ug_layout_next_row(ctx); + //ug_element_button(ctx, "button 3", "L", (ug_div_t){SQUARE(SIZE_MM(10))}); + //ug_element_button(ctx, "button 4", "69", (ug_div_t){SQUARE(SIZE_MM(10))}); + ug_layout_next_column(ctx); ug_element_button(ctx, "button 5", "lmao", (ug_div_t){SQUARE(SIZE_MM(10))}); - ug_element_textbtn(ctx, "text button 1", "foo", (ug_div_t){SQUARE(SIZE_MM(10))}); + //ug_element_textbtn(ctx, "text button 1", "foo", (ug_div_t){.w = 0, .h = SIZE_PX(30)}); //ug_element_button(ctx, "button 6", "", (ug_div_t){SQUARE(SIZE_MM(10)),.x=SIZE_PX(-10)}); + + ug_container_body(ctx, "fill body"); ug_frame_end(ctx); diff --git a/ugui.c b/ugui.c index 18d702f..5c25d26 100644 --- a/ugui.c +++ b/ugui.c @@ -36,7 +36,8 @@ CNT_STATE_RESIZE_T | \ CNT_STATE_RESIZE_B | \ CNT_STATE_RESIZE_L | \ - CNT_STATE_RESIZE_R \ + CNT_STATE_RESIZE_R | \ + CNT_STATE_RESIZE_D \ ) #define PPI_PPM(ppi, scale) (ppi * scale * 0.03937008) @@ -45,7 +46,7 @@ #define UG_ERR(...) err(errno, "__FUNCTION__: " __VA_ARGS__) #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 TEST(f, b) (f & b) +#define TEST(f, b) (f & (b)) #define MAX(a, b) (a > b ? a : b) #define R_MARGIN(r, b) (r.x + r.w - b) #define L_MARGIN(r, b) (r.x + b) @@ -173,6 +174,31 @@ void scale_rect(ug_ctx_t *ctx, ug_rect_t *rect) } +int crop_rect(ug_rect_t *ra, ug_rect_t *rb) +{ + int cropped = 0; + if (L_MARGIN((*ra), 0) < L_MARGIN((*rb), 0)) { + ra->w -= L_MARGIN((*rb), 0) - L_MARGIN((*ra), 0); + ra->x = rb->x; + cropped = 1; + } + if (R_MARGIN((*ra), 0) > R_MARGIN((*rb), 0)) { + ra->w -= R_MARGIN((*ra), 0) - R_MARGIN((*rb), 0); + cropped = 1; + } + if (T_MARGIN((*ra), 0) < T_MARGIN((*rb), 0)) { + ra->h -= T_MARGIN((*rb), 0) - T_MARGIN((*ra), 0); + ra->y = rb->y; + cropped = 1; + } + if (B_MARGIN((*ra), 0) > B_MARGIN((*rb), 0)) { + ra->h -= B_MARGIN((*ra), 0)- B_MARGIN((*rb), 0); + cropped = 1; + } + return cropped; +} + + /*=============================================================================* * Command Operations * *=============================================================================*/ @@ -317,44 +343,44 @@ int ug_ctx_set_style(ug_ctx_t *ctx, const ug_style_t *style) #define STATEIS(cnt, f) ((cnt->flags & CNT_STATE_ALL) == f) /* -* Container style: -* -* rca -* v v Border Top v -* +--------------------------------------------------------+ -* +--------------------------------------------------------+ -* | Titlebar | -* +--------------------------------------------------------+ -* |+------------------------------------------------------+| -* || .................................................... || -* || .\ ^ Border Top ^ . || -* || . \_ rect(0,0) . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . < Border Left . || -* || . + Margin Border Right >. || -* || . + Margin . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . . || -* || . . || -* || .................................................... || -* |+------------------------------------------------------+| -* +--------------------------------------------------------+ -* ^ Border Bottom ^ -*/ + * Container style: rca stands for absolute rectangle, it delimits the total + * drawable area, as such it does not include borders + * + * rca v Border Top v + * +-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 @@ -422,7 +448,6 @@ static void sort_containers(ug_ctx_t *ctx) // 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) { if (!TEST(cnt->flags, UG_CNT_FLOATING)) { @@ -439,51 +464,55 @@ static int position_container(ug_ctx_t *ctx, ug_container_t *cnt) *rca = *rect; const ug_style_t *s = ctx->style_px; - int b = SZ_INT(s->border.size) + SZ_INT(s->margin); + int b = SZ_INT(s->border.size); int hh = SZ_INT(s->title.height); - int cx = ctx->origin.x; - int cy = ctx->origin.y; - int cw = ctx->origin.w; - int ch = ctx->origin.h; + ug_rect_t c = { + .x = ctx->origin.x + b, + .y = ctx->origin.y + b, + .w = ctx->origin.w - 2*b, + .h = ctx->origin.h - 2*b + }; // handle relative sizes - if (rect->w == 0) rca->w = cw; - if (rect->h == 0) rca->h = ch; - else if (TEST(cnt->flags, UG_CNT_MOVABLE)) rca->h += hh; + if (rect->w == 0) rca->w = c.w; + if (rect->h == 0) rca->h = c.h; + else if (TEST(cnt->flags, UG_CNT_MOVABLE)) rca->h += hh + b; // 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 (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 // main window, thus negative if (!TEST(cnt->flags, UG_CNT_FLOATING)) { // <0 -> relative to the right margin - if (rect->x < 0) rca->x = cx + cw - rca->w + rca->x + 1; - else rca->x = cx; - if (rect->y < 0) rca->y = cy + ch - rca->h + rca->y + 1; - else rca->y = cy; + if (rect->x < 0) rca->x = R_MARGIN(c, 0) - R_MARGIN((*rca), -1); + else rca->x = L_MARGIN(c, 0); + if (rect->y < 0) rca->y = B_MARGIN(c, 0) - B_MARGIN((*rca), -1); + else rca->y = T_MARGIN(c, 0); // if the container is fixed than update the available space in // the context if (rect->w) { - ctx->origin.x = rect->x >= 0 ? rca->x + rca->w : ctx->origin.x; + if (rect->x >= 0) + ctx->origin.x = R_MARGIN((*rca), -b); ctx->origin.w -= rca->w; } else if (rect->h) { - ctx->origin.y = rect->y >= 0 ? rca->y + rca->h : ctx->origin.y; + if (rect->y >= 0) + ctx->origin.y = B_MARGIN((*rca), -b); ctx->origin.h -= rca->h; } else { // width and height zero means fill everything @@ -492,8 +521,8 @@ static int position_container(ug_ctx_t *ctx, ug_container_t *cnt) } // set the correct element origin - cnt->c_orig.x = cnt->r_orig.x = cnt->space.x = L_MARGIN((*rca), b); - cnt->c_orig.y = cnt->r_orig.y = cnt->space.y = T_MARGIN((*rca),b); + cnt->c_orig.x = cnt->r_orig.x = cnt->space.x = L_MARGIN((*rca), 0); + cnt->c_orig.y = cnt->r_orig.y = cnt->space.y = T_MARGIN((*rca), 0); 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); @@ -528,7 +557,8 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt) rca = &cnt->rca; const ug_style_t *s = ctx->style_px; - int b = SZ_INT(s->border.size) + SZ_INT(s->margin); + int b = SZ_INT(s->border.size); + int m = SZ_INT(s->margin); int hh = SZ_INT(s->title.height); ug_vec2_t mpos = ctx->mouse.pos; @@ -537,9 +567,9 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt) // handle movable windows if (TEST(cnt->flags, UG_CNT_MOVABLE)) { clip = (ug_rect_t){ - .x = L_MARGIN((*rca), b), - .y = T_MARGIN((*rca), b), - .w = rca->w - 2*b, + .x = L_MARGIN((*rca), 0), + .y = T_MARGIN((*rca), 0), + .w = rca->w, .h = hh, }; if (STATEIS(cnt, CNT_STATE_MOVING) || @@ -552,13 +582,12 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt) } } - // FIXME: allow for corner resize // right border resize if (TEST(cnt->flags, UG_CNT_RESIZE_RIGHT)) { clip = (ug_rect_t){ - .x = R_MARGIN((*rca), b), - .y = rca->y, - .w = b, + .x = R_MARGIN((*rca), m), + .y = T_MARGIN((*rca), 0), + .w = b + m, .h = rca->h, }; if (STATEIS(cnt, CNT_STATE_RESIZE_R) || @@ -572,9 +601,9 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt) // left border resize if (TEST(cnt->flags, UG_CNT_RESIZE_LEFT)) { clip = (ug_rect_t){ - .x = L_MARGIN((*rca), 0), - .y = rca->y, - .w = b, + .x = L_MARGIN((*rca), -b), + .y = T_MARGIN((*rca), 0), + .w = b + m, .h = rca->h, }; if (STATEIS(cnt, CNT_STATE_RESIZE_L) || @@ -596,10 +625,10 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt) // bottom border resize if (TEST(cnt->flags, UG_CNT_RESIZE_BOTTOM)) { clip = (ug_rect_t){ - .x = rca->x, - .y = B_MARGIN((*rca), b), + .x = L_MARGIN((*rca), 0), + .y = B_MARGIN((*rca), m), .w = rca->w, - .h = b, + .h = b + m, }; if (STATEIS(cnt, CNT_STATE_RESIZE_B) || (STATEIS(cnt, 0) && INTERSECTS(mpos, clip))) { @@ -612,10 +641,10 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt) // top border resize if (TEST(cnt->flags, UG_CNT_RESIZE_TOP)) { clip = (ug_rect_t){ - .x = rca->x, - .y = rca->y, + .x = L_MARGIN((*rca), 0), + .y = T_MARGIN((*rca), -b), .w = rca->w, - .h = b, + .h = b + m, }; if (STATEIS(cnt, CNT_STATE_RESIZE_T) || (STATEIS(cnt, 0) && INTERSECTS(mpos, clip))) { @@ -633,6 +662,24 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt) } } + // lower diagonal resize + if (TEST(cnt->flags, UG_CNT_RESIZE_BOTTOM | UG_CNT_RESIZE_RIGHT)) { + clip = (ug_rect_t){ + .x = R_MARGIN((*rca), -m), + .y = B_MARGIN((*rca), m), + .w = b + m, + .h = b + m, + }; + if (STATEIS(cnt, CNT_STATE_RESIZE_D) || + (STATEIS(cnt, 0) && INTERSECTS(mpos, clip))) { + cnt->flags |= CNT_STATE_RESIZE_D; + rect->h = MAX(10, rect->h + ctx->mouse.delta.y); + rca->h = MAX(10, rca->h + ctx->mouse.delta.y); + rect->w = MAX(10, rect->w + ctx->mouse.delta.x); + rca->w = MAX(10, rca->w + ctx->mouse.delta.x); + } + } + // 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 (STATEIS(cnt, 0)) @@ -647,6 +694,7 @@ static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt) return 1; } +#define EXPAND(r, b) {r.x-=b,r.y-=b,r.w+=2*b,r.h+=2*b;} static void draw_container(ug_ctx_t *ctx, ug_container_t *cnt, const char *text) { @@ -658,39 +706,47 @@ static void draw_container(ug_ctx_t *ctx, ug_container_t *cnt, const char *text) // push main body rect = cnt->rca; + EXPAND(rect, b); push_rect_command(ctx, &rect, s->color.bg); // push outline if (TEST(cnt->flags, UG_CNT_RESIZE_LEFT)) { rect = cnt->rca; + rect.x -= b; + rect.y -= b, + rect.h += 2*b; rect.w = b; 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.x += rect.w; + rect.y -= b; + rect.h += 2*b; rect.w = b; push_rect_command(ctx, &rect, s->border.color); } if (TEST(cnt->flags, UG_CNT_RESIZE_TOP)) { rect = cnt->rca; + rect.y -= b; + rect.x -= b; rect.h = b; + rect.w += 2*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.x -= b; + rect.y += rect.h; rect.h = b; + rect.w += 2*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; + rect.h = hh; push_rect_command(ctx, &rect, s->title.color.bg); // titlebar border rect.y += hh; @@ -792,7 +848,6 @@ int ug_container_sidebar(ug_ctx_t *ctx, const char *name, ug_size_t size, int si switch (side) { case UG_SIDE_BOTTOM: cnt->flags |= UG_CNT_RESIZE_TOP; - // FIXME: we do not support relative zero position yet rect.y = -1; rect.h = size_to_px(ctx, size); break; @@ -962,6 +1017,7 @@ int ug_frame_begin(ug_ctx_t *ctx) } ug_rect_t r = c->rca; + EXPAND(r, SZ_INT(ctx->style_px->border.size)); if (INTERSECTS(v, r)) ctx->hover.cnt = c->id; } @@ -1048,7 +1104,7 @@ int ug_frame_end(ug_ctx_t *ctx) * +--------------------------------------------------------+ * | .<- r_orig | * | . | - * | prev "partition" . | + * | previous element . | * | . | * |.............................. | * |^ | @@ -1058,18 +1114,20 @@ int ug_frame_end(ug_ctx_t *ctx) * | | * | | * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | * +--------------------------------------------------------+ * + * Element Style: + * + * rca margin + * +-v--------------+<--->+----------------+ + * | +------------+ | | +------------+ | + * | | | | | | | | + * | | | | | | | | + * | | | | | | | | + * | +------------+ | | +------------+ | + * +----------------+ +----------------+ + * <-> + * border */ @@ -1113,7 +1171,7 @@ int ug_layout_next_row(ug_ctx_t *ctx) GET_SELECTED_CONTAINER(ctx, cp); cp->c_orig.x = cp->r_orig.x = L_MARGIN(cp->space, 0); - cp->c_orig.y = cp->r_orig.y = B_MARGIN(cp->space, -SZ_INT(ctx->style_px->margin)); + cp->c_orig.y = cp->r_orig.y = B_MARGIN(cp->space, 0); return 0; } @@ -1126,7 +1184,7 @@ int ug_layout_next_column(ug_ctx_t *ctx) ug_container_t *cp; GET_SELECTED_CONTAINER(ctx, cp); - cp->c_orig.x = cp->r_orig.x = R_MARGIN(cp->space, -SZ_INT(ctx->style_px->margin)); + cp->c_orig.x = cp->r_orig.x = R_MARGIN(cp->space, 0); cp->c_orig.y = cp->r_orig.y = T_MARGIN(cp->space, 0); return 0; @@ -1169,10 +1227,10 @@ static int position_element(ug_ctx_t *ctx, ug_container_t *cnt, ug_element_t *el // if there is no space then return if (TEST(cnt->flags, CNT_LAYOUT_COLUMN)) { - if (cnt->space.h >= cnt->rca.h) + if (cnt->space.w >= cnt->rca.w) return -1; } else { - if (cnt->space.w >= cnt->rca.w) + if (cnt->space.h >= cnt->rca.h) return -1; } @@ -1187,7 +1245,6 @@ static int position_element(ug_ctx_t *ctx, ug_container_t *cnt, ug_element_t *el const ug_style_t *s = ctx->style_px; int b = SZ_INT(s->border.size); int m = SZ_INT(s->margin); - // TODO: different element borders int cx, cy, cw, ch; int eb = 0; @@ -1196,7 +1253,7 @@ static int position_element(ug_ctx_t *ctx, ug_container_t *cnt, ug_element_t *el default: break; } - // FIXME: this may not work + // FIXME: this does 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)) { @@ -1208,50 +1265,37 @@ static int position_element(ug_ctx_t *ctx, ug_container_t *cnt, ug_element_t *el } // handle relative sizes - if (rect->w == 0) rca->w = cw; - else rca->w += 2*eb; - if (rect->h == 0) rca->h = ch; - else rca->h += 2*eb; + if (rect->w == 0) rca->w = cw - 2*eb; + if (rect->h == 0) rca->h = ch - 2*eb; // for elements x and y are offsets - rca->x = cx + rect->x; - rca->y = cy + rect->y; + rca->x = cx + rect->x + eb + m; + rca->y = cy + rect->y + eb + m; // if the element was put outside of the container return, this can happen // because of the element offset if (OUTSIDE((*rca), 0, cnt->rca, b)) return -1; - if (R_MARGIN((*rca), 0) > R_MARGIN(cnt->rca, b)) - rca->w = R_MARGIN(cnt->rca, b) - L_MARGIN((*rca), 0); - - if (L_MARGIN((*rca), 0) < L_MARGIN(cnt->rca, b)) { - rca->x = L_MARGIN(cnt->rca, b); - rca->w -= L_MARGIN(cnt->rca, b) - L_MARGIN((*rca), 0); - } - - if (T_MARGIN((*rca), 0) < T_MARGIN(cnt->rca, b)) { - rca->y = T_MARGIN(cnt->rca, b); - rca->h -= T_MARGIN(cnt->rca, b) - T_MARGIN((*rca), 0); - } - - if (B_MARGIN((*rca), 0) > B_MARGIN(cnt->rca, b)) - rca->h = B_MARGIN(cnt->rca, b) - T_MARGIN((*rca), 0); - + elem->flags &= ~(ELEM_CLIPPED); + if (crop_rect(rca, &cnt->rca)) + elem->flags |= ELEM_CLIPPED; if (TEST(cnt->flags, CNT_LAYOUT_COLUMN)) { - cnt->c_orig.y += rca->h + m; - cnt->r_orig.x = R_MARGIN((*rca), 0) + m; - cnt->r_orig.y = T_MARGIN((*rca), 0); + cnt->c_orig.y = B_MARGIN((*rca), 0) + eb; + cnt->r_orig.x = R_MARGIN((*rca), 0) + eb; + cnt->r_orig.y = T_MARGIN((*rca), 0) + eb; } else { - cnt->r_orig.x += rca->w + m; - cnt->c_orig.x = L_MARGIN((*rca), 0); - cnt->c_orig.y = B_MARGIN((*rca), 0) + m; + cnt->r_orig.x = R_MARGIN((*rca), 0) + eb; + cnt->c_orig.x = L_MARGIN((*rca), 0) + eb; + cnt->c_orig.y = B_MARGIN((*rca), 0) + eb; } - if (B_MARGIN(cnt->space, 0) < B_MARGIN((*rca), 0)) - cnt->space.h = B_MARGIN((*rca), 0) - T_MARGIN(cnt->space, 0); - if (R_MARGIN(cnt->space, 0) < R_MARGIN((*rca), 0)) - cnt->space.w = R_MARGIN((*rca), 0) - L_MARGIN(cnt->space, 0); + + // expand used space + if (R_MARGIN(cnt->space, 0) < R_MARGIN((*rca), -eb)) + cnt->space.w = R_MARGIN((*rca), -eb) - L_MARGIN(cnt->space, 0); + if (B_MARGIN(cnt->space, 0) < B_MARGIN((*rca), -eb)) + cnt->space.h = B_MARGIN((*rca), -eb) - T_MARGIN(cnt->space, 0); return 0; } @@ -1261,6 +1305,11 @@ static int position_element(ug_ctx_t *ctx, ug_container_t *cnt, ug_element_t *el // generic function int handle_element(ug_ctx_t *ctx, ug_container_t *cnt, ug_element_t *elem) { + // if the contaniner is not the current hover then do nothing, think about + // floating cont. over bodies + if (ctx->hover.cnt != cnt->id) + return 0; + if (INTERSECTS(ctx->mouse.pos, elem->rca)) { cnt->hover_elem = elem->id; if (MOUSEDOWN(ctx, BTN_ANY)) @@ -1286,17 +1335,16 @@ void draw_elements(ug_ctx_t *ctx, ug_container_t *cnt) ug_color_t txtcol = RGB_FORMAT(0); ug_rect_t r = e->rca; int eb = 0, ts = 0; - unsigned char draw_bg = 0, draw_fg = 0, draw_txt = 0; + unsigned char draw_br = 0, draw_fg = 0, draw_txt = 0; switch (e->type) { case UG_ELEM_BUTTON: - // TODO: draw borders, different color for selected element col = cnt->hover_elem == e->id ? s->btn.color.act : s->btn.color.bg; bcol = cnt->selected_elem == e->id ? s->btn.color.sel : s->btn.color.br; txtcol = s->btn.color.fg; ts = SZ_INT(s->btn.font_size); eb = SZ_INT(ctx->style_px->btn.border); - draw_bg = draw_fg = draw_txt = 1; + draw_br = draw_fg = draw_txt = 1; break; case UG_ELEM_TXTBTN: ts = SZ_INT(s->btn.font_size); @@ -1305,21 +1353,26 @@ void draw_elements(ug_ctx_t *ctx, ug_container_t *cnt) default: break; } - if (draw_bg) + if (draw_br) { + r = (ug_rect_t){ + .x = e->rca.x - eb, + .y = e->rca.y - eb, + .w = e->rca.w + 2*eb, + .h = e->rca.h + 2*eb, + }; + if (TEST(e->flags, ELEM_CLIPPED)) + crop_rect(&r, &cnt->rca); push_rect_command(ctx, &r, bcol); + } if (draw_fg) { r = e->rca; - r.x += eb; - r.y += eb; - r.w -= 2*eb; - r.h -= 2*eb; push_rect_command(ctx, &r, col); } if (draw_txt) { push_text_command(ctx, (ug_vec2_t){ - .x = e->rca.x, - .y = e->rca.y+e->rca.h/2 + .x = e->rca.x+eb, + .y = e->rca.y+eb+e->rca.h/2 }, ts, txtcol, diff --git a/ugui.h b/ugui.h index f24d0a3..2a3f06e 100644 --- a/ugui.h +++ b/ugui.h @@ -29,7 +29,8 @@ typedef enum { // element type typedef struct { ug_id_t id; - unsigned int type; + unsigned short int type; + unsigned short int flags; ug_rect_t rect, rca; const char *name; union { @@ -53,6 +54,10 @@ enum { UG_ELEM_SPACE, // takes up space }; +enum { + ELEM_CLIPPED = BIT(0), +}; + // container type, a container is an entity that contains layouts, a container has // a haight a width and their maximum values, in essence a container is a rectangular @@ -92,9 +97,10 @@ enum { CNT_STATE_RESIZE_B = BIT(27), CNT_STATE_RESIZE_L = BIT(26), CNT_STATE_RESIZE_R = BIT(25), - CNT_STATE_DELETE = BIT(24), // The container is marked for removal + CNT_STATE_RESIZE_D = BIT(24), + CNT_STATE_DELETE = BIT(23), // The container is marked for removal // layouting - CNT_LAYOUT_COLUMN = BIT(23), + CNT_LAYOUT_COLUMN = BIT(22), }; // style, defines default height, width, color, margins, borders, etc