From 894b2763c088f02253b2f766e1a719cc3f620888 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Mon, 5 Dec 2022 23:19:37 +0100 Subject: [PATCH] rewrite --- renderer.c | 0 ugui.c | 341 ++++++++++++++++++++++--------------- ugui.h | 487 ++++++++++++++--------------------------------------- 3 files changed, 330 insertions(+), 498 deletions(-) delete mode 100644 renderer.c diff --git a/renderer.c b/renderer.c deleted file mode 100644 index e69de29..0000000 diff --git a/ugui.c b/ugui.c index e4e6a98..72c9193 100644 --- a/ugui.c +++ b/ugui.c @@ -1,23 +1,59 @@ #include #include -#include #include +#include #include "ugui.h" + #define SALT 0xbabb0cac #define DEF_SCALE 1.0 -#define DEF_DPI 96.0 -#define E_STACK_STEP (1024 * 128) +#define DEF_PPI 96.0 +#define STACK_STEP 64 + +#define PPI_PPM(ppi, scale) (ppi * scale * 0.03937008) +#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 UG_ERR(...) err(errno, "__FUNCTION__: " __VA_ARGS__) + +// 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), + }, +}; + +static const ug_vec2_t max_size = {10e6, 10e6}; + +static ug_style_t style_cache = {0}; + + +/*=============================================================================* + * Common Functions * + *=============================================================================*/ + + +// grow a stack +#define grow(S) \ +{ \ + S.items = realloc(S.items, (S.size+STACK_STEP)*sizeof(*(S.items))); \ + if(!S.items) \ + UG_ERR("Could not allocate stack #S: %s", strerror(errno)); \ + memset(&(S.items[S.size]), 0, STACK_STEP*sizeof(*(S.items))); \ + S.size += STACK_STEP; \ +} -#define TO_PPM(dpi, scale) (dpi * scale * 0.03937008) // https://en.wikipedia.org/wiki/Jenkins_hash_function -unsigned int hash(void *data, unsigned int size) +static ug_id_t hash(const void *data, unsigned int size) { if (!size) return 0; - unsigned int hash = SALT; + ug_id_t hash = SALT; unsigned char *v = (unsigned char *)data; for (; size; size--) { @@ -33,17 +69,44 @@ unsigned int hash(void *data, unsigned int size) } -static void grow_stack(ug_ctx_t *ctx) +// update the style cache with the correct sizes in pixels and colors +static void update_style_cache(ug_ctx_t *ctx) { - if (!ctx) - err(EXIT_FAILURE, "__FUNCTION__:" "Cannot grow null context"); - ctx->e_size += E_STACK_STEP; - ctx->e_stack = realloc(ctx->e_stack, ctx->e_size); - if (!ctx->e_stack) - err(errno, "__FUNCTION__:" "Could not grow stack: %s", strerror(errno)); + const ug_style_t *s = ctx->style; + // TODO: do this shit + (void)s; +} + + +ug_rect_t rect_to_px(ug_ctx_t *ctx, ug_rect_t rect) +{ + float scale = 1.0; + + switch (ctx->unit) { + case UG_UNIT_PX: + return rect; + case UG_UNIT_MM: + scale = ctx->ppm; + break; + case UG_UNIT_PT: + scale = ctx->ppd; + break; + } + + rect.x *= scale; + rect.y *= scale; + rect.w *= scale; + rect.h *= scale; + + return rect; } +/*=============================================================================* + * Context Operations * + *=============================================================================*/ + + // creates a new context, fills with default values, ctx is ready for ug_start() ug_ctx_t *ug_new_ctx(void) { @@ -53,9 +116,15 @@ ug_ctx_t *ug_new_ctx(void) memset(ctx, 0, sizeof(ug_ctx_t)); ctx->scale = DEF_SCALE; - ctx->dpi = DEF_DPI; - ctx->ppm = TO_PPM(DEF_SCALE, DEF_DPI); + ctx->ppi = DEF_PPI; + ctx->ppm = PPI_PPM(DEF_SCALE, DEF_PPI); + ctx->ppd = PPI_PPD(DEF_SCALE, DEF_PPI); + ctx->unit = UG_UNIT_PX; + ctx->style = &default_style; + ctx->style_px = &style_cache; + + // TODO: allocate stacks return ctx; } @@ -66,173 +135,165 @@ void ug_free_ctx(ug_ctx_t *ctx) warn("__FUNCTION__:" "Trying to free a null context"); return; } - - if (!ctx->e_stack) { - warn("__FUNCTION__:" "Context has null element stack"); - return; - } - free(ctx->e_stack); + // TODO: free stacks free(ctx); -} - -// updates the context with user information -int ug_update_ctx(ug_ctx_t *ctx, - unsigned int window_id, - float scale, - float dpi, - float ppm - ) -{ - if (!ctx) - return -1; - ctx->window_id = window_id; - - if (scale) - ctx->scale = scale; - if (dpi) - ctx->dpi = dpi; - if (!ppm) - ctx->ppm = TO_PPM(ctx->dpi, ctx->scale); - else - ctx->ppm = ppm; - - return 0; + // NOTE: do not free style since the default is statically allocated, let + // the user take care of it instead } -/*=============================================================================* - * INPUT FUNCTIONS * - *=============================================================================*/ +#define TEST_CTX(ctx) { if (!ctx) return -1; } -#define TEST_CTX(ctx) { \ - if (!ctx) { \ - warn("__FUNCTION__:" "trying to use a null context"); \ - return; \ - } \ -} - -void ug_input_mousemove(ug_ctx_t *ctx, int x, int y) +int ug_ctx_set_displayinfo(ug_ctx_t *ctx, float scale, float ppi) { TEST_CTX(ctx); - ctx->mouse.pos = (struct ug_vec2){ .x = x, .y = y }; -} + if (scale <= 0 || ppi < 20.0) + return -1; + + ctx->ppm = PPI_PPM(scale, ppi); + ctx->ppd = PPI_PPM(scale, ppi); + ctx->scale = scale; + ctx->ppi = ppi; + + update_style_cache(ctx); -void ug_input_mousedown(ug_ctx_t *ctx, int x, int y, unsigned char btn) -{ - TEST_CTX(ctx); - ug_input_mousemove(ctx, x, y); - ctx->mouse.down_mask |= btn; - ctx->mouse.press_mask |= btn; + return 0; } -void ug_input_mouseup(ug_ctx_t *ctx, int x, int y, unsigned char btn) +int ug_ctx_set_drawableregion(ug_ctx_t *ctx, ug_vec2_t size) { TEST_CTX(ctx); - ug_input_mousemove(ctx, x, y); - ctx->mouse.down_mask &= ~btn; -} - + if (size.w <= 0 || size.h <= 0) + return -1; + + ctx->size.w = size.w; + ctx->size.h = size.h; -void ug_input_scroll(ug_ctx_t *ctx, int x, int y) -{ - TEST_CTX(ctx); - ctx->mouse.scroll_delta.x += x; - ctx->mouse.scroll_delta.y += y; + // FIXME: do I need to do something like update_container_size() here? + // maybe it is redundant since each frame not every conatiner is + // re-added + return 0; } -void ug_input_keydown(ug_ctx_t *ctx, int key) +int ug_ctx_set_style(ug_ctx_t *ctx, const ug_style_t *style) { TEST_CTX(ctx); - ctx->key.down_mask |= key; - ctx->key.press_mask |= key; -} - + if (!style) + return -1; + // TODO: validate style -void ug_input_keyup(ug_ctx_t *ctx, int key) -{ - TEST_CTX(ctx); - ctx->key.down_mask &= ~key; + ctx->style = style; + update_style_cache(ctx); + + return 0; } -// append in input text -void ug_input_text(ug_ctx_t *ctx, const char *text) +int ug_ctx_set_unit(ug_ctx_t *ctx, ug_unit_t unit) { TEST_CTX(ctx); - int size = strlen(ctx->input_text); - int len = strlen(text); - if ((unsigned long)(size+len) >= sizeof(ctx->input_text)) { - warn("__FUNCTION__" "Input text exceeds context buffer"); - return; - } - memcpy(ctx->input_text + size, text, len); + if (!IS_VALID_UNIT(unit)) + return -1; + + ctx->unit = unit; + + return 0; } /*=============================================================================* - * BEGIN AND END * + * Container Operations * *=============================================================================*/ -#undef TEST_CTX -#define TEST_CTX(ctx) { \ - if (!ctx) { \ - warn("__FUNCTION__:" "trying to use a null context"); \ - return -1; \ - } \ -} -int ug_begin(ug_ctx_t *ctx) +// get a new or existing container handle +static ug_container_t *get_container(ug_ctx_t *ctx, ug_id_t id) { - // it is the beginning of a new frame - TEST_CTX(ctx); + ug_container_t *c = NULL; + for (int i = 0; i < ctx->container_stack.idx; i++) { + if (ctx->container_stack.items[i].id == id) { + c = &(ctx->container_stack.items[i]); + break; + } + } + // if the container was not already there allocate a new one + if (!c) { + if(ctx->container_stack.idx >= ctx->container_stack.size) + grow(ctx->container_stack); + c = &(ctx->container_stack.items[ctx->container_stack.idx++]); + } - // reset the command stack - ctx->e_idx = 0; - // next frame - ctx->frame++; - // update the mouse delta - ctx->mouse.delta.x = ctx->mouse.pos.x - ctx->mouse.last_pos.x; - ctx->mouse.delta.y = ctx->mouse.pos.y - ctx->mouse.last_pos.y; - // TODO: other stuff - return 0; + return c; } -int ug_end(ug_ctx_t *ctx) +// update the container dimensions and position according to the context information, +// also handle resizing, moving, ect. if allowed by the container +static void update_container(ug_ctx_t *ctx, ug_container_t *cnt) { - // end of a frame, check that all went well - TEST_CTX(ctx); - - // reset the inputs - ctx->mouse.press_mask = 0; - ctx->mouse.scroll_delta = (struct ug_vec2){0}; - ctx->mouse.last_pos = ctx->mouse.pos; - ctx->key.press_mask = 0; - ctx->input_text[0] = '\0'; - return 0; -} + // if the container was just initialized the unit might not be pixels, this + // is a problem since all mouse events are in pixels and convering back + // and forth accumulates error and in heavy on the cpu + if (cnt->unit != UG_UNIT_PX) { + // FIXME: this takes the unit from the context but it should be fine + cnt->rect = rect_to_px(ctx, cnt->rect); + cnt->unit = UG_UNIT_PX; + } -/*=============================================================================* - * UI ELEMENTS * - *=============================================================================*/ + // recalculate position + // FIXME: this is the right place to do some optimization, what if the + // context didn't change? + // the absoulute position of the container + ug_rect_t rect_abs = cnt->rect; + + // 0 -> take all the space, <0 -> take absolute + if (rect_abs.w == 0) rect_abs.w = ctx->size.w; + else if (rect_abs.w < 0) rect_abs.w = -rect_abs.w; + if (rect_abs.h == 0) rect_abs.h = ctx->size.h; + else if (rect_abs.h < 0) rect_abs.h = -rect_abs.h; + + // <0 -> relative to the right margin + if (rect_abs.x < 0) rect_abs.x = ctx->size.x - rect_abs.w + rect_abs.x; + if (rect_abs.y < 0) rect_abs.y = ctx->size.y - rect_abs.h + rect_abs.y; + + // if we had focus the frame before, then do shit + if (ctx->hover.cnt == cnt->id) { + // TODO: do stuff + } -#undef TEST_CTX -#define TEST_CTX(ctx) { \ - if (!ctx) { \ - warn("__FUNCTION__:" "trying to use a null context"); \ - return 0; \ - } \ + // push the appropriate rectangles to the drawing stack + // TODO: ^ This ^ } -// Slider element, a rectangle with some text and another rectangle inside -// When used with a mouse the slider moves to the clicked area and stat gets -// updated, in that case a non-zero value gets returned -int ug_slider(ug_ctx_t *ctx, float *stat, float min, float max) -{ + +// a floating container can be placed anywhere and can be resized, acts like a +// window inside another window +int ug_container_floating(ug_ctx_t *ctx, const char *name, ug_rect_t rect) +{ TEST_CTX(ctx); - ug_draw_rect(ctx) -} + // TODO: verify rect + + ug_id_t id = name ? hash(name, strlen(name)) : hash(&rect, sizeof(ug_rect_t)); + 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 = rect; + cnt->unit = ctx->unit; + cnt->flags = UG_CNT_MOVABLE | + UG_CNT_RESIZABLE | + UG_CNT_SCROLL_X | + UG_CNT_SCROLL_Y ; + } + + update_container(ctx, cnt); + + return 0; +} \ No newline at end of file diff --git a/ugui.h b/ugui.h index bcb2353..e7e60c0 100644 --- a/ugui.h +++ b/ugui.h @@ -1,243 +1,121 @@ -#ifndef _UGUI_H -#define _UGUI_H - - -// Macros -#define UG_STACK(T) struct { T *items; int idx; int size; } - -/* Point Coordinate */ -// coordinate type, or how it is measured -enum { - UG_CTYPE_PX = 0x0, - UG_CTYPE_MM = 0x1, - UG_CTYPE_REL = 0x2, -}; +#ifndef _UG_HEADER +#define _UG_HEADER + +#define UG_STACK(T) struct { T *items; int idx; int size; } +#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 } +#define SIZE_PX(x) { .size=x, .unit=UG_UNIT_PX } +#define SIZE_MM(x) { .size=x, .unit=UG_UNIT_MM } +#define SIZE_PT(x) { .size=x, .unit=UG_UNIT_PT } + +// basic types +typedef unsigned int ug_id_t; +typedef struct { union {int x, w;}; union {int y, h;}; } ug_vec2_t; +typedef struct { int x, y, w, h; } ug_rect_t; +typedef struct { unsigned char a, b, g, r; } ug_color_t; +typedef struct { int size, unit; } ug_size_t; + +typedef enum { + UG_UNIT_PX = 0, + UG_UNIT_MM, + UG_UNIT_PT, +} ug_unit_t; + +// 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 +// area that can be resized and sits somewhere on the drawable region +// the z index of a container is determined by it's position on the stack +typedef struct { + ug_id_t id; + ug_unit_t unit; + ug_rect_t rect; + ug_vec2_t max_size; + unsigned int flags; +} ug_container_t; -// coordinate anchor, or where it refers +// the container flags enum { - UG_CANCHOR_TOP = 0x0, // x coordinates - UG_CANCHOR_LEFT = 0x0, - UG_CANCHOR_BOTTOM = 0x1, // y coordinates - UG_CANCHOR_RIGHT = 0x1, - UG_CANCHOR_VCENTER = 0x2, // for positions it should be centered - UG_CANCHOR_HCENTER = 0x2, + UG_CNT_MOVABLE = BIT(0), // can be moved + UG_CNT_RESIZABLE = BIT(1), // can be resized + UG_CNT_SCROLL_X = BIT(2), // can have horizontal scrolling + UG_CNT_SCROLL_Y = BIT(3), // can have vertical scrolling }; -struct _ug_pt_flags { - unsigned long int _:56; - unsigned long int t:4; - unsigned long int a:4; -}; - -typedef struct { - // first coordinate - union { - union { - int x; - struct _ug_pt_flags fx; - }; - union { - int w; - struct _ug_pt_flags fw; - }; - union { - int m; - struct _ug_pt_flags fm; - }; - }; - // second coordinate - union { - union { - int y; - struct _ug_pt_flags fy; - }; - union { - int h; - struct _ug_pt_flags fh; - }; - union { - int a; - struct _ug_pt_flags fa; - }; - }; -} ug_coord_t; - -// TODO: define stroke style (f.s) +// style, defines default height, width, color, margins, borders, etc +// all dimensions should be taken as a reference when doing the layout since +// ultimately it's the layout that decides them. For example when deciding how to +// 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 typedef struct { - int size; + struct { + ug_color_t color, alt_color; + ug_size_t size, alt_size; + } text; + ug_color_t bg_color; + // base sizes for all elements, some elements should be different, like + // buttons and other things that need to stand out struct { - // type of size - unsigned char t:4; - // stroke style - unsigned char s:4; - } f; -} ug_stroke_t; -//---// - -/* RGBA Color type */ -typedef struct { - unsigned char a; - unsigned char b; - unsigned char g; - unsigned char r; -} ug_color_t; -//---// - -/* simple position structure */ -struct ug_vec2 { - int x, y; -}; - -typedef struct { - int x, y; - int w, h; -} ug_rect_t; -//---// - -/* Mouse button mask */ -enum ug_mouse_btn { - UG_MOUSEBTN_LEFT = 1, - UG_MOUSEBTN_MIDDLE = 2, - UG_MOUSEBTN_RIGHT = 4, - UG_MOUSEBTN_4 = 8, - UG_MOUSEBTN_5 = 16, -}; -//---// - -/* event structure */ -typedef enum { - UG_EV_WINDOWMOVE, - UG_EV_WINDOWRESIZE, - UG_EV_WINDOWSHOW, - UG_EV_MOUSEMOVE, - UG_EV_MOUSEDOWN, - UG_EV_MOUSEUP, - UG_EV_KEYDOWN, - UG_EV_KEYUP, -} ug_event_type_t; - -typedef struct { - ug_event_type_t type; - union { - int x; - int w; - unsigned int code; - }; - union { - int y; - int h; - unsigned int mask; - }; -} ug_event_t; -//---// - -/* Primitive element type */ -typedef enum { - UG_E_RECT = 0, - UG_E_TRIANGLE, - UG_E_DOT, - UG_E_LINE, - UG_E_ARC, - UG_E_TEXT, - UG_E_SPRITE, -} ug_element_type_t; - -typedef struct { - ug_coord_t size; - ug_coord_t pos; - ug_color_t color; -} ug_rect_t; + ug_size_t width, height, border_width; + ug_color_t color, hover_color, active_color; + } base; -typedef struct { - ug_coord_t size; - ug_coord_t pos; - ug_color_t color; -} ug_triangle_t; - -typedef struct { - ug_stroke_t stroke; - ug_coord_t pos; - ug_color_t color; -} ug_dot_t; - -typedef struct { - ug_stroke_t stroke; - ug_coord_t vert[2]; - ug_color_t color; -} ug_line_t; - -typedef struct { - ug_stroke_t stroke; - ug_coord_t vert[3]; - ug_color_t color; -} ug_arc_t; - -// draw text from view[start] to view[end] -typedef struct { - ug_stroke_t stroke; - ug_coord_t pos; - ug_color_t color; - const char *view; - int start; - int end; -} ug_text_t; + // a button should stand out, hence the different colors + struct { + ug_color_t bg_color, hover_color, active_color; + } button; -// all sprites have to be mapped into memory, map is an array of width x height -// bytes, the type is specified by the user -typedef struct { - ug_coord_t pos; - void *map; - int width; - int height; -} ug_sprite_t; + // a checkbox should be smaller than a button + struct { + ug_size_t width, height, tick_size; + ug_color_t tick_color; + } checkbox; + // a slider can be thinner and generally wider than a button + struct { + ug_size_t width, height; + } slider; -// data is the actual element data, it has to be cast to the right element specified -// by type and is variable size so that no memory is wasted, size is the size in -// bytes of data + id + size + type -typedef struct { - ug_element_type_t type; - unsigned int size; - unsigned int id; - unsigned char data[]; -} ug_element_t; -//---// + // 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; -/* Layout region */ -typedef struct { - ug_rect_t rect; - // FIXME: is this needed? - unsigned int id; - // indentation level, used in trees - // FIXME: is this needed? - unsigned int indent; -} ug_layout_region_t; -//---//s +} ug_style_t; -/* Global context */ -// one context per phisical window -// a phisical window can be anything, but here it basically represents the true -// surface where things are drawn into, a window has a scale, dpi and ppm -// (pixel per mm), only the latter is truly needed, the user sets these variables -// and has to take care of updating them when needed +// context typedef struct { - unsigned int window_id; - float scale, dpi, ppm; - // the user pushes the things that he wants to draw onto the element stack, - // which contains all the primitives needed to draw the wanted element - UG_STACK(unsigned char) e_stack; - // the element which has focus - unsigned int focus_id; - // the element that we are hovering - unsigned int hover_id; + // some style information + const ug_style_t *style; + // style_px is a style cache where all measurements are already in pixels + const ug_style_t *style_px; + // ppi: pixels per inch + // ppm: pixels per millimeter + // ppd: pixels per dot + float scale, ppi, ppm, ppd; + // containers need to know how big the "main container" is so that all + // the relative positioning work + ug_vec2_t size; + // which context and element we are hovering + struct { + ug_id_t cnt, elem; + } hover; + // the id of the "active" element, active means different things for + // different elements, for exaple active for a button means to be pressed, + // and for a text box it means to be focused + ug_id_t active; // count the frames for fun unsigned long int frame; + // current measurement unit + ug_unit_t unit; // mouse data struct { - struct ug_vec2 pos; - struct ug_vec2 last_pos; - struct ug_vec2 delta; - struct ug_vec2 scroll_delta; + ug_vec2_t pos; + ug_vec2_t last_pos; + ug_vec2_t delta; + ug_vec2_t scroll_delta; // down/pressed masks get updated on mousedown, whereas down_mask // only on mouseup, so the masks differ by the buttons that were // released @@ -252,146 +130,39 @@ typedef struct { } key; // input text buffer char input_text[32]; + // stacks + UG_STACK(ug_container_t) container_stack; } ug_ctx_t; -//---// -// creates a new context, fills with default values, ctx is ready for ug_start() + +// context initialization ug_ctx_t *ug_new_ctx(void); void ug_free_ctx(ug_ctx_t *ctx); // updates the context with user information -int ug_update_ctx(ug_ctx_t *ctx, - unsigned int window_id, - float scale, - float dpi, - float ppm - ); - -// register inputs -void ug_input_mousedown(ug_ctx_t *ctx, int x, int y, unsigned char btn); -void ug_input_mouseup(ug_ctx_t *ctx, int x, int y, unsigned char btn); -void ug_input_mousemove(ug_ctx_t *ctx, int x, int y); -void ug_input_scroll(ug_ctx_t *ctx, int x, int y); -void ug_input_keydown(ug_ctx_t *ctx, int key); -void ug_input_keyup(ug_ctx_t *ctx, int key); -void ug_input_text(ug_ctx_t *ctx, const char *text); - -// between begin and end the user draws -int ug_begin(ug_ctx_t *ctx); -int ug_end(ug_ctx_t *ctx); - -// layout control -// Split the layout vertically and horizontally, n times each time with the -// supplied width/height - -/* Window space - * +-----------------------------+ - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * +-----------------------------+ - * - * ug_layout_vsplit(ctx, 2, (int[]){10, 20}); - * create two vertical zones - * +-----------------------------+ - * | } 10px | - * +-----------------------------+ - * | |> 20px | - * | | | - * +-----------------------------+ - * | | - * | | - * | remainder | - * | | - * | | - * | | - * +-----------------------------+ - * - * ug_layout_hsplit(ctx, 3, NULL); - * equally spaced divisions - * +-----------------------------+ - * | | | | - * +-----------------------------+ - * | |> 20px | - * | | | - * +-----------------------------+ - * | | - * | | - * | remainder | - * | | - * | | - * | | - * +-----------------------------+ - * - * ug_button(ctx, "ciao"); - * ug_layout_next(ctx); // skip second square - * ug_button(ctx, "quit"); - * float val = 0.3 - * ug_slider(ctx, &val, 0, 1); - * ug_text(ctx, "lorem ipsum\ndolor et"); - * - * +-----------------------------+ - * | ciao | | quit | - * +-----------------------------+ - * | # 0.3 | - * | # | - * +-----------------------------+ - * | lorem ipsum | - * | dolor et | - * | | - * | | - * | | - * | | - * +-----------------------------+ - * - * ug_layout_popup(ctx, {100x50, centrato}); - * ug_layout_vsplit(ctx, 1, NULL); - * ug_button(ctx, "btn1"); - * ug_button(ctx, "btn2"); - * - * +-----------------------------+ - * | ciao | | quit | - * +-----------------------------+ - * | # 0.3 | - * | # +----------+ | - * +--------| btn1 |---------+ - * | lorem i| | | - * | dolor e+----------+ | - * | | btn2 | | - * | | | | - * | +----------+ | - * | | - * | | - * +-----------------------------+ - */ -int ug_layout_vsplit(ug_ctx_t *ctx, int n, const int *heights); -int ug_layout_hsplit(ug_ctx_t *ctx, int n, const int *widths); -// popup layout, create a rectangle that sits over the view and has a higher -// z-index, this allows it to have any position and have focus priority -// creating a popup selects it as current layout -int ug_layout_popup(ug_ctx_t *ctx, ug_rect_t rect); -// get the next rectangular region in the layout context -ug_rect_t ug_layout_next(ug_ctx_t *ctx); -// get the current layout rectangle area, but do not pop it (select the next) -// this is useful to get information about the area's width height and position -ug_rect_t ug_layout_get_current(ug_ctx_t *ctx); -// set the unit of the dimensions, in the context all units are pixels but -// when regions are defined units can be in pixels, millimiters, etc -int ui_layout_set_mm(ug_ctx_t *ctx); -int ui_layout_set_px(ug_ctx_t *ctx); - -// ui elements -int ug_slider(ug_ctx_t *ctx, float *stat, float min, float max); - +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_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 +// the default ones, resizing is done automagically with internal state + +// a floating container can be placed anywhere and can be resized, acts like a +// window inside another window +int ug_container_floating(ug_ctx_t *ctx, const char *name, ug_rect_t rect); +// like a floating container but cannot be resized +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 +// top of the window +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 +int ug_container_sidebar(ug_ctx_t *ctx, const char *name, int width); +// a body is a container that scales with the window, sits at it's center and cannot +// be resized +int ug_container_body(ug_ctx_t *ctx, const char *name); -// un-define macros that we don't want the user to access #undef UG_STACK +#undef BIT -#endif +#endif \ No newline at end of file