some stuff
- remove containers from stack when there is no space - handle containers now returns nonzero when the conatiner is in focus - container names are now required
This commit is contained in:
parent
46c5de8dcb
commit
7fb9d225a0
@ -180,16 +180,17 @@ int main(void)
|
||||
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_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_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_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");
|
||||
if (ug_container_body(ctx, "Other Body"))
|
||||
|
152
ugui.c
152
ugui.c
@ -60,7 +60,7 @@ static const ug_style_t default_style = {
|
||||
.bg_color = RGB_FORMAT(0x0000ff),
|
||||
.border.t = SIZE_PX(3),
|
||||
.border.b = SIZE_PX(3),
|
||||
.border.l = SIZE_PX(10),
|
||||
.border.l = SIZE_PX(3),
|
||||
.border.r = SIZE_PX(3),
|
||||
.border.color = RGB_FORMAT(0x00ff00),
|
||||
.titlebar.height = SIZE_PX(20),
|
||||
@ -97,6 +97,17 @@ static ug_style_t style_cache = {0};
|
||||
}
|
||||
|
||||
|
||||
#define DELETE_FROM_STACK(S, c) \
|
||||
{ \
|
||||
for (int i = 0; i < S.idx; i++) { \
|
||||
if (c->id != S.items[i].id) \
|
||||
continue; \
|
||||
memmove(&S.items[i], &S.items[i+1], (S.idx-i)*sizeof(S.items[0])); \
|
||||
memset(&S.items[S.idx--], 0, sizeof(S.items[0])); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define RESET_STACK(S) \
|
||||
{ \
|
||||
memset(S.items, 0, S.idx*sizeof(*(S.items))); \
|
||||
@ -140,7 +151,6 @@ int size_to_px(ug_ctx_t *ctx, ug_size_t s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ug_rect_t div_to_rect(ug_ctx_t *ctx, ug_div_t *div)
|
||||
{
|
||||
ug_rect_t r;
|
||||
@ -211,12 +221,15 @@ void ug_ctx_free(ug_ctx_t *ctx)
|
||||
|
||||
free(ctx);
|
||||
|
||||
// NOTE: do not free style since the default is statically allocated, let
|
||||
// the user take care of it instead
|
||||
// NOTE: do not free style since the default style is statically allocated,
|
||||
// let the user take care of it instead
|
||||
}
|
||||
|
||||
|
||||
// TODO: add error codes
|
||||
#define TEST_CTX(ctx) { if (!ctx) return -1; }
|
||||
#define TEST_STR(s) { if (!s || !s[0]) return -1; }
|
||||
|
||||
|
||||
int ug_ctx_set_displayinfo(ug_ctx_t *ctx, float scale, float ppi)
|
||||
{
|
||||
@ -327,6 +340,11 @@ static void sort_containers(ug_ctx_t *ctx)
|
||||
// update the container position in the context area
|
||||
static int position_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
||||
{
|
||||
if (!TEST(cnt->flags, UG_CNT_FLOATING))
|
||||
// if there is no space left propagate the error
|
||||
if (ctx->origin.w <= 0 || ctx->origin.h <= 0)
|
||||
return -1;
|
||||
|
||||
ug_rect_t *rect, *rca;
|
||||
rect = &cnt->rect;
|
||||
rca = &cnt->rca;
|
||||
@ -387,16 +405,13 @@ static int 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_FLOATING)) 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;
|
||||
|
||||
|
||||
// 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)) {
|
||||
// if there is no space left propagate the error
|
||||
if (!ctx->origin.w || !ctx->origin.h)
|
||||
return -1;
|
||||
// <0 -> relative to the right margin
|
||||
if (rect->x < 0) rca->x = cx + cw - rca->w + rca->x + 1;
|
||||
else rca->x = cx;
|
||||
@ -420,21 +435,24 @@ static int position_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
||||
}
|
||||
|
||||
|
||||
void handle_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
||||
// TODO: make a set of fixed return values for the different states
|
||||
// handle moving and resizing, return 1 if it had focus, 0 otherwise, negative
|
||||
// return values represent errors
|
||||
static int handle_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
||||
{
|
||||
// if we are not the currently active container than definately we are not
|
||||
// being moved or resized
|
||||
if (ctx->active.cnt != cnt->id) {
|
||||
cnt->flags &= ~CNT_STATE_ALL;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// mouse pressed handle resize, for simplicity containers can only
|
||||
// be resized from the bottom and right border
|
||||
// TODO: bring selected container to the top of the stack
|
||||
// TODO: change return value to indicate this case
|
||||
if (!HELD(ctx, UG_BTN_LEFT) ||
|
||||
!TEST(cnt->flags, (RESIZEALL | UG_CNT_FLOATING)))
|
||||
return;
|
||||
!TEST(cnt->flags, (RESIZEALL | UG_CNT_MOVABLE)))
|
||||
return 1;
|
||||
|
||||
ug_rect_t *rect, *rca;
|
||||
rect = &cnt->rect;
|
||||
@ -451,7 +469,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_FLOATING)) {
|
||||
if (TEST(cnt->flags, UG_CNT_MOVABLE)) {
|
||||
minx = rca->x + bl;
|
||||
maxx = rca->x + rca->w - br;
|
||||
miny = rca->y + bt;
|
||||
@ -498,7 +516,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_FLOATING))
|
||||
if (TEST(cnt->flags, UG_CNT_MOVABLE))
|
||||
rect->x += ctx->mouse.delta.x;
|
||||
}
|
||||
if (rca->w - ctx->mouse.delta.x >= 10) {
|
||||
@ -538,7 +556,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_FLOATING))
|
||||
if (TEST(cnt->flags, UG_CNT_MOVABLE))
|
||||
rect->y += ctx->mouse.delta.y;
|
||||
}
|
||||
if (rca->h - ctx->mouse.delta.y >= 10) {
|
||||
@ -559,8 +577,7 @@ void handle_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
||||
// TODO: what about scrolling? how do we know if we need to draw
|
||||
// a scroll bar? Maybe add that information inside the
|
||||
// container structure
|
||||
|
||||
// push the appropriate rectangles to the drawing stack
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -579,7 +596,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_FLOATING) {
|
||||
if (TEST(cnt->flags, UG_CNT_MOVABLE)) {
|
||||
draw_rect.x += bl;
|
||||
draw_rect.y += bt;
|
||||
draw_rect.w -= bl + br;
|
||||
@ -593,7 +610,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_FLOATING) {
|
||||
if (TEST(cnt->flags, UG_CNT_MOVABLE)) {
|
||||
draw_rect.y += bt + hh;
|
||||
draw_rect.h -= bt + hh;
|
||||
}
|
||||
@ -607,9 +624,10 @@ void draw_container(ug_ctx_t *ctx, ug_container_t *cnt)
|
||||
int ug_container_floating(ug_ctx_t *ctx, const char *name, ug_div_t div)
|
||||
{
|
||||
TEST_CTX(ctx);
|
||||
TEST_STR(name);
|
||||
// TODO: verify div
|
||||
|
||||
ug_id_t id = name ? hash(name, strlen(name)) : hash(&div, sizeof(ug_div_t));
|
||||
ug_id_t id = hash(name, strlen(name));
|
||||
ug_container_t *cnt = get_container(ctx, id);
|
||||
|
||||
if (cnt->id) {
|
||||
@ -618,33 +636,55 @@ 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_FLOATING | RESIZEALL |
|
||||
UG_CNT_SCROLL_X | UG_CNT_SCROLL_Y ;
|
||||
cnt->flags = UG_CNT_FLOATING | RESIZEALL | UG_CNT_MOVABLE |
|
||||
UG_CNT_SCROLL_X | UG_CNT_SCROLL_Y;
|
||||
}
|
||||
|
||||
// TODO: what about error codes and meaning?
|
||||
if (position_container(ctx, cnt))
|
||||
if (position_container(ctx, cnt)) {
|
||||
DELETE_FROM_STACK(ctx->cnt_stack, cnt);
|
||||
return -1;
|
||||
handle_container(ctx, cnt);
|
||||
}
|
||||
return handle_container(ctx, cnt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
int ug_container_popup(ug_ctx_t *ctx, const char *name, ug_div_t div)
|
||||
{
|
||||
TEST_CTX(ctx);
|
||||
TEST_STR(name);
|
||||
// TODO: verify div
|
||||
|
||||
ug_id_t id = hash(name, strlen(name));
|
||||
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->rect = div_to_rect(ctx, &div);
|
||||
cnt->flags = UG_CNT_FLOATING;
|
||||
}
|
||||
|
||||
// TODO: what about error codes and meaning?
|
||||
if (position_container(ctx, cnt)) {
|
||||
DELETE_FROM_STACK(ctx->cnt_stack, cnt);
|
||||
return -1;
|
||||
}
|
||||
return handle_container(ctx, cnt);
|
||||
}
|
||||
|
||||
|
||||
int ug_container_sidebar(ug_ctx_t *ctx, const char *name, ug_size_t size, int side)
|
||||
{
|
||||
TEST_CTX(ctx);
|
||||
TEST_STR(name);
|
||||
|
||||
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_id_t id = hash(name, strlen(name));
|
||||
ug_container_t *cnt = get_container(ctx, id);
|
||||
|
||||
|
||||
if (cnt->id) {
|
||||
// nothing? maybe we can skip updating all dimensions and stuff
|
||||
} else {
|
||||
@ -677,25 +717,19 @@ int ug_container_sidebar(ug_ctx_t *ctx, const char *name, ug_size_t size, int si
|
||||
cnt->rect = rect;
|
||||
}
|
||||
|
||||
if (position_container(ctx, cnt))
|
||||
if (position_container(ctx, cnt)) {
|
||||
DELETE_FROM_STACK(ctx->cnt_stack, cnt);
|
||||
return -1;
|
||||
handle_container(ctx, cnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return handle_container(ctx, cnt);
|
||||
}
|
||||
|
||||
int ug_container_menu_bar(ug_ctx_t *ctx, const char *name, ug_size_t height)
|
||||
{
|
||||
TEST_CTX(ctx);
|
||||
TEST_STR(name);
|
||||
|
||||
ug_id_t id = 0;
|
||||
if (name) {
|
||||
id = hash(name, strlen(name));
|
||||
} else {
|
||||
int blob[2] = { height.size.i, height.unit};
|
||||
id = hash(blob, sizeof(blob));
|
||||
}
|
||||
|
||||
ug_id_t id = hash(name, strlen(name));
|
||||
ug_container_t *cnt = get_container(ctx, id);
|
||||
|
||||
if (cnt->id) {
|
||||
@ -711,26 +745,20 @@ int ug_container_menu_bar(ug_ctx_t *ctx, const char *name, ug_size_t height)
|
||||
cnt->rect = rect;
|
||||
}
|
||||
|
||||
if (position_container(ctx, cnt))
|
||||
if (position_container(ctx, cnt)) {
|
||||
DELETE_FROM_STACK(ctx->cnt_stack, cnt);
|
||||
return -1;
|
||||
handle_container(ctx, cnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return handle_container(ctx, cnt);
|
||||
}
|
||||
|
||||
|
||||
int ug_container_body(ug_ctx_t *ctx, const char *name)
|
||||
{
|
||||
TEST_CTX(ctx);
|
||||
TEST_STR(name);
|
||||
|
||||
ug_id_t id = 0;
|
||||
if (name) {
|
||||
id = hash(name, strlen(name));
|
||||
} else {
|
||||
// sorry but body must have a name
|
||||
return -1;
|
||||
}
|
||||
|
||||
ug_id_t id = hash(name, strlen(name));
|
||||
ug_container_t *cnt = get_container(ctx, id);
|
||||
|
||||
if (cnt->id) {
|
||||
@ -742,11 +770,11 @@ int ug_container_body(ug_ctx_t *ctx, const char *name)
|
||||
cnt->rect = (ug_rect_t){0};
|
||||
}
|
||||
|
||||
if (position_container(ctx, cnt))
|
||||
if (position_container(ctx, cnt)) {
|
||||
DELETE_FROM_STACK(ctx->cnt_stack, cnt);
|
||||
return -1;
|
||||
handle_container(ctx, cnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return handle_container(ctx, cnt);
|
||||
}
|
||||
|
||||
|
||||
|
14
ugui.h
14
ugui.h
@ -39,13 +39,14 @@ typedef struct {
|
||||
|
||||
// the container flags
|
||||
enum {
|
||||
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
|
||||
UG_CNT_RESIZE_TOP = BIT(4), // can be resized
|
||||
UG_CNT_FLOATING = BIT(0), // is on top of everything else
|
||||
UG_CNT_RESIZE_RIGHT = BIT(1), // can be resized from the right border
|
||||
UG_CNT_RESIZE_BOTTOM = BIT(2), // can be resized from the bottom border
|
||||
UG_CNT_RESIZE_LEFT = BIT(3), // can be resized from the left border
|
||||
UG_CNT_RESIZE_TOP = BIT(4), // can be resized from the top border
|
||||
UG_CNT_SCROLL_X = BIT(5), // can have horizontal scrolling
|
||||
UG_CNT_SCROLL_Y = BIT(6), // can have vertical scrolling
|
||||
UG_CNT_MOVABLE = BIT(7), // can be moved around
|
||||
// container state
|
||||
CNT_STATE_NONE = BIT(30),
|
||||
CNT_STATE_MOVING = BIT(29),
|
||||
@ -53,6 +54,7 @@ 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
|
||||
};
|
||||
|
||||
// style, defines default height, width, color, margins, borders, etc
|
||||
@ -210,7 +212,7 @@ int ug_ctx_set_style(ug_ctx_t *ctx, const ug_style_t *style);
|
||||
// window inside another window
|
||||
int ug_container_floating(ug_ctx_t *ctx, const char *name, ug_div_t div);
|
||||
// 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_div_t div);
|
||||
// a menu bar is a container of fixed height, cannot be resized and sits at the
|
||||
// top of the window
|
||||
int ug_container_menu_bar(ug_ctx_t *ctx, const char *name, ug_size_t height);
|
||||
|
Loading…
Reference in New Issue
Block a user