diff --git a/Readme.md b/Readme.md index fb0f381..7ad2588 100644 --- a/Readme.md +++ b/Readme.md @@ -13,11 +13,11 @@ render backends it only focuses on the actual UI. ## Features - Immediate mode graphical user interface toolkit - Written in C89 (ANSI C) -- Small codebase (~11kLOC) +- Small codebase (~12kLOC) - Focus on portability, efficiency and simplicity - No dependencies (not even the standard library) - No global or hidden state -- Configurable style and colors +- Fully skinnable and customizable - UTF-8 support ## Optional diff --git a/demo/allegro5_complex/Makefile b/demo/allegro5/Makefile similarity index 100% rename from demo/allegro5_complex/Makefile rename to demo/allegro5/Makefile diff --git a/demo/allegro5_complex/allegro.c b/demo/allegro5/allegro.c similarity index 99% rename from demo/allegro5_complex/allegro.c rename to demo/allegro5/allegro.c index 75a585e..c087728 100644 --- a/demo/allegro5_complex/allegro.c +++ b/demo/allegro5/allegro.c @@ -228,7 +228,8 @@ device_draw(struct device *dev, struct zr_context *ctx, enum zr_anti_aliasing AA config.shape_AA = AA; config.line_AA = AA; config.circle_segment_count = 22; - config.line_thickness = 1.0f; + config.arc_segment_count = 22; + config.curve_segment_count = 22; config.null = dev->null; /* convert from command into hardware format */ diff --git a/demo/allegro5_simple/Makefile b/demo/allegro5_simple/Makefile deleted file mode 100644 index b5f0f4d..0000000 --- a/demo/allegro5_simple/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# Install -BIN = demo - -# Compiler -CC = clang -DCC = gcc - -# Flags -CFLAGS = -std=c89 -pedantic - -SRC = ../../zahnrad.c allegro.c -OBJ = $(SRC:.c=.o) - -ifeq ($(OS),Windows_NT) -BIN := $(BIN).exe -LIBS = -lmingw32 -lallegro -lallegro_primitives -lallegro_font -lallegro_ttf -lm -else -LIBS = -lallegro -lallegro_primitives -lallegro_font -lallegro_ttf -lGL -lm -lGLU -lGLEW -endif - -# Modes -.PHONY: gcc -gcc: CC = gcc -gcc: $(BIN) - -.PHONY: clang -clang: CC = clang -clang: $(BIN) - -$(BIN): - @mkdir -p bin - rm -f bin/$(BIN) $(OBJS) - $(CC) $(SRC) $(CFLAGS) -o bin/$(BIN) $(LIBS) diff --git a/demo/allegro5_simple/allegro.c b/demo/allegro5_simple/allegro.c deleted file mode 100644 index f8c2878..0000000 --- a/demo/allegro5_simple/allegro.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - Copyright (c) 2016 Micha Mettke - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* macros */ -#define DEMO_DO_NOT_DRAW_IMAGES -#include "../../zahnrad.h" -#include "../demo.c" - -static void -die(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputs("\n", stderr); - exit(EXIT_FAILURE); -} - -static void -draw(struct zr_context *ctx, int width, int height) -{ - const struct zr_command *cmd; - zr_foreach(cmd, ctx) { - switch (cmd->type) { - case ZR_COMMAND_NOP: break; - case ZR_COMMAND_SCISSOR: { - const struct zr_command_scissor *s = zr_command(scissor, cmd); - al_set_clipping_rectangle(s->x-1,s->y-1,s->w+2, s->h+2); - } break; - case ZR_COMMAND_LINE: { - const struct zr_command_line *l = zr_command(line, cmd); - al_draw_line(l->begin.x, l->begin.y, l->end.x, l->end.y, - al_map_rgba(l->color.r, l->color.g, l->color.b, l->color.a), 1.0f); - } break; - case ZR_COMMAND_RECT: { - const struct zr_command_rect *r = zr_command(rect, cmd); - al_draw_filled_rounded_rectangle(r->x, r->y, r->x + r->w, r->y + r->h, - r->rounding, r->rounding, - al_map_rgba(r->color.r, r->color.g, r->color.b, r->color.a)); - } break; - case ZR_COMMAND_CIRCLE: { - const struct zr_command_circle *c = zr_command(circle, cmd); - al_draw_filled_circle(c->x + c->w/2, c->y + c->w/2, c->w/2, - al_map_rgba(c->color.r, c->color.g, c->color.b, c->color.a)); - } break; - case ZR_COMMAND_TRIANGLE: { - const struct zr_command_triangle *t = zr_command(triangle, cmd); - al_draw_filled_triangle(t->a.x, t->a.y, t->b.x, t->b.y, t->c.x, t->c.y, - al_map_rgba(t->color.r, t->color.g, t->color.b, t->color.a)); - } break; - case ZR_COMMAND_TEXT: { - const struct zr_command_text *t = zr_command(text, cmd); - ALLEGRO_FONT *font = t->font->userdata.ptr; - al_draw_text(font, al_map_rgba(t->foreground.r, t->foreground.g, t->foreground.g, t->foreground.a), - t->x, t->y, ALLEGRO_ALIGN_LEFT, t->string); - } break; - case ZR_COMMAND_CURVE: { - unsigned int i_step; - float t_step; - const struct zr_command_curve *q = zr_command(curve, cmd); - struct zr_vec2i last = q->begin; - struct zr_vec2i p1 = q->begin; - struct zr_vec2i p2 = q->ctrl[0]; - struct zr_vec2i p3 = q->ctrl[1]; - struct zr_vec2i p4 = q->end; - t_step = 1.0f/(float)22.0f; - for (i_step = 1; i_step <= 22.0f; ++i_step) { - float t = t_step * (float)i_step; - float u = 1.0f - t; - float w1 = u*u*u; - float w2 = 3*u*u*t; - float w3 = 3*u*t*t; - float w4 = t * t *t; - float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; - float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; - al_draw_line(last.x, last.y, x, y, - al_map_rgba(q->color.r, q->color.g, q->color.b, q->color.a), 1.0f); - last.x = (short)x; last.y = (short)y; - } - } break; - case ZR_COMMAND_ARC: - case ZR_COMMAND_IMAGE: - default: break; - } - } - zr_clear(ctx); - al_set_clipping_rectangle(0,0,width, height); -} - -static size_t -font_get_width(zr_handle handle, float height, const char *text, size_t len) -{ - /* allegro does not support text width calculation - * for strings that are not zero terminated... Therefore I have to - * allocate a string every time. - * OPT: maybe use a buffer to copy into? */ - const ALLEGRO_FONT *font = handle.ptr; - ALLEGRO_USTR *str = al_ustr_new_from_buffer(text, len); - size_t width = (size_t)al_get_ustr_width(font, str); - UNUSED(height); - al_ustr_free(str); - return width; -} - -static void -input_key(struct zr_context *ctx, ALLEGRO_EVENT *evt, int down) -{ - int sym = evt->keyboard.keycode; - if (sym == ALLEGRO_KEY_RSHIFT || sym == ALLEGRO_KEY_LSHIFT) - zr_input_key(ctx, ZR_KEY_SHIFT, down); - else if (sym == ALLEGRO_KEY_DELETE) - zr_input_key(ctx, ZR_KEY_DEL, down); - else if (sym == ALLEGRO_KEY_ENTER) - zr_input_key(ctx, ZR_KEY_ENTER, down); - else if (sym == ALLEGRO_KEY_TAB) - zr_input_key(ctx, ZR_KEY_TAB, down); - else if (sym == ALLEGRO_KEY_BACKSPACE) - zr_input_key(ctx, ZR_KEY_BACKSPACE, down); - else if (sym == ALLEGRO_KEY_LEFT) - zr_input_key(ctx, ZR_KEY_LEFT, down); - else if (sym == ALLEGRO_KEY_RIGHT) - zr_input_key(ctx, ZR_KEY_RIGHT, down); - else if (sym == ALLEGRO_KEY_C) - zr_input_key(ctx, ZR_KEY_COPY, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL); - else if (sym == ALLEGRO_KEY_V) - zr_input_key(ctx, ZR_KEY_PASTE, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL); - else if (sym == ALLEGRO_KEY_X) - zr_input_key(ctx, ZR_KEY_CUT, down && evt->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL); -} - -static void -input_button(struct zr_context *ctx, ALLEGRO_EVENT *evt, int down) -{ - const int x = evt->mouse.x; - const int y = evt->mouse.y; - if (evt->mouse.button == 1) - zr_input_button(ctx, ZR_BUTTON_LEFT, x, y, down); - if (evt->mouse.button == 2) - zr_input_button(ctx, ZR_BUTTON_RIGHT, x, y, down); -} - -static void* mem_alloc(zr_handle unused, size_t size) -{UNUSED(unused); return calloc(1, size);} -static void mem_free(zr_handle unused, void *ptr) -{UNUSED(unused); free(ptr);} - -int -main(int argc, char *argv[]) -{ - /* Platform */ - const char *font_path; - int width = 0, height = 0; - int running = 1; - - ALLEGRO_DISPLAY *display; - ALLEGRO_EVENT_QUEUE *queue; - ALLEGRO_FONT *font; - struct demo gui; - - font_path = argv[1]; - if (argc < 2) - die("Missing TTF Font file argument!"); - - /* Allegro */ - al_init(); - al_init_font_addon(); - al_init_ttf_addon(); - al_install_keyboard(); - al_install_mouse(); - al_init_primitives_addon(); - display = al_create_display(WINDOW_WIDTH, WINDOW_HEIGHT); - al_set_window_title(display, "Zahnrad"); - queue = al_create_event_queue(); - al_register_event_source(queue, al_get_display_event_source(display)); - al_register_event_source(queue, al_get_keyboard_event_source()); - al_register_event_source(queue, al_get_mouse_event_source()); - font = al_load_ttf_font(font_path, 14, 0); - if (!font) die("Failed to load font: %s\n", font_path); - - { - /* GUI */ - struct zr_user_font usrfnt; - struct zr_allocator alloc; - alloc.userdata.ptr = NULL; - alloc.alloc = mem_alloc; - alloc.free = mem_free; - - usrfnt.userdata = zr_handle_ptr(font); - usrfnt.width = font_get_width; - usrfnt.height = al_get_font_line_height(font); - zr_init(&gui.ctx, &alloc, &usrfnt); - } - - while (running) { - /* Input */ - ALLEGRO_EVENT evt; - zr_input_begin(&gui.ctx); - while (al_get_next_event(queue, &evt)) { - if (evt.type == ALLEGRO_EVENT_DISPLAY_CLOSE) goto cleanup; - else if (evt.type == ALLEGRO_EVENT_KEY_UP && evt.keyboard.display == display) - input_key(&gui.ctx, &evt, zr_false); - else if (evt.type == ALLEGRO_EVENT_KEY_DOWN && evt.keyboard.display == display) - input_key(&gui.ctx, &evt, zr_true); - else if (evt.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) - input_button(&gui.ctx, &evt, zr_true); - else if (evt.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) - input_button(&gui.ctx, &evt, zr_false); - else if (evt.type == ALLEGRO_EVENT_MOUSE_AXES) { - zr_input_motion(&gui.ctx, evt.mouse.x, evt.mouse.y); - } else if (evt.type == ALLEGRO_EVENT_KEY_CHAR) { - if (evt.keyboard.display == display) - if (evt.keyboard.unichar > 0 && evt.keyboard.unichar < 0x10000) - zr_input_unicode(&gui.ctx, (zr_rune)evt.keyboard.unichar); - } - } - zr_input_end(&gui.ctx); - - /* GUI */ - width = al_get_display_width(display); - height = al_get_display_height(display); - running = run_demo(&gui); - - /* Draw */ - al_clear_to_color(al_map_rgba_f(0.2f, 0.2f, 0.2f, 1.0f)); - draw(&gui.ctx, width, height); - al_flip_display(); - } - -cleanup: - /* Cleanup */ - if (queue) al_destroy_event_queue(queue); - if (display) al_destroy_display(display); - zr_free(&gui.ctx); - return 0; -} - diff --git a/demo/apple/ZahnradBackend.m b/demo/apple/ZahnradBackend.m index 468049e..3021c63 100644 --- a/demo/apple/ZahnradBackend.m +++ b/demo/apple/ZahnradBackend.m @@ -459,7 +459,8 @@ static void mem_free(zr_handle unused, void* ptr) config.shape_AA = ZR_ANTI_ALIASING_ON; config.line_AA = ZR_ANTI_ALIASING_ON; config.circle_segment_count = 22; - config.line_thickness = 1.0f; + config.curve_segment_count = 22; + config.arc_segment_count = 22; config.null = nullTexture; // setup buffers to load vertices and elements diff --git a/demo/demo.c b/demo/demo.c index fb5753c..f5662cd 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -55,6 +55,19 @@ struct icons { struct zr_image img_file; struct zr_image movie_file; + /* theme */ + struct zr_image bar; + struct zr_image check; + struct zr_image checkbox; + struct zr_image cursor; + struct zr_image dot; + struct zr_image header; + struct zr_image left; + struct zr_image option; + struct zr_image progress; + struct zr_image right; + struct zr_image slider; + struct zr_image window; }; enum theme {THEME_BLACK, THEME_WHITE, THEME_RED, THEME_BLUE, THEME_DARK}; @@ -75,7 +88,7 @@ struct demo { }; static void -zr_labelf(struct zr_context *ctx, enum zr_text_align align, const char *fmt, ...) +zr_labelf(struct zr_context *ctx, zr_flags align, const char *fmt, ...) { char buffer[1024]; va_list args; @@ -86,338 +99,6 @@ zr_labelf(struct zr_context *ctx, enum zr_text_align align, const char *fmt, ... va_end(args); } -/* =============================================================== - * - * CONTROL WINDOW - * - * ===============================================================*/ -static void -set_style(struct zr_context *ctx, enum theme theme) -{ - if (theme == THEME_WHITE) { - ctx->style.rounding[ZR_ROUNDING_SCROLLBAR] = 0; - ctx->style.rounding[ZR_ROUNDING_PROPERTY] = 0; - ctx->style.rounding[ZR_ROUNDING_BUTTON] = 0; - - ctx->style.colors[ZR_COLOR_TEXT] = zr_rgba(70, 70, 70, 255); - ctx->style.colors[ZR_COLOR_TEXT_HOVERING] = zr_rgba(10, 10, 10, 255); - ctx->style.colors[ZR_COLOR_TEXT_ACTIVE] = zr_rgba(20, 20, 20, 255); - ctx->style.colors[ZR_COLOR_WINDOW] = zr_rgba(175, 175, 175, 255); - ctx->style.colors[ZR_COLOR_HEADER] = zr_rgba(175, 175, 175, 255); - ctx->style.colors[ZR_COLOR_BORDER] = zr_rgba(0, 0, 0, 255); - ctx->style.colors[ZR_COLOR_BUTTON] = zr_rgba(185, 185, 185, 255); - ctx->style.colors[ZR_COLOR_BUTTON_HOVER] = zr_rgba(170, 170, 170, 255); - ctx->style.colors[ZR_COLOR_BUTTON_ACTIVE] = zr_rgba(160, 160, 160, 255); - ctx->style.colors[ZR_COLOR_TOGGLE] = zr_rgba(150, 150, 150, 255); - ctx->style.colors[ZR_COLOR_TOGGLE_HOVER] = zr_rgba(120, 120, 120, 255); - ctx->style.colors[ZR_COLOR_TOGGLE_CURSOR] = zr_rgba(175, 175, 175, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE] = zr_rgba(190, 190, 190, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE_HOVER] = zr_rgba(150, 150, 150, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE_TEXT] = zr_rgba(70, 70, 70, 255); - ctx->style.colors[ZR_COLOR_SLIDER] = zr_rgba(190, 190, 190, 255); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR] = zr_rgba(80, 80, 80, 255); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR_HOVER] = zr_rgba(70, 70, 70, 255); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR_ACTIVE] = zr_rgba(60, 60, 60, 255); - ctx->style.colors[ZR_COLOR_PROGRESS] = zr_rgba(190, 190, 190, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR] = zr_rgba(80, 80, 80, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR_HOVER] = zr_rgba(70, 70, 70, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR_ACTIVE] = zr_rgba(60, 60, 60, 255); - ctx->style.colors[ZR_COLOR_PROPERTY] = zr_rgba(175, 175, 175, 255); - ctx->style.colors[ZR_COLOR_PROPERTY_HOVER] = zr_rgba(160, 160, 160, 255); - ctx->style.colors[ZR_COLOR_PROPERTY_ACTIVE] = zr_rgba(165, 165, 165, 255); - ctx->style.colors[ZR_COLOR_INPUT] = zr_rgba(150, 150, 150, 255); - ctx->style.colors[ZR_COLOR_INPUT_CURSOR] = zr_rgba(0, 0, 0, 255); - ctx->style.colors[ZR_COLOR_INPUT_TEXT] = zr_rgba(0, 0, 0, 255); - ctx->style.colors[ZR_COLOR_COMBO] = zr_rgba(175, 175, 175, 255); - ctx->style.colors[ZR_COLOR_HISTO] = zr_rgba(160, 160, 160, 255); - ctx->style.colors[ZR_COLOR_HISTO_BARS] = zr_rgba(45, 45, 45, 255); - ctx->style.colors[ZR_COLOR_HISTO_HIGHLIGHT] = zr_rgba( 255, 0, 0, 255); - ctx->style.colors[ZR_COLOR_PLOT] = zr_rgba(160, 160, 160, 255); - ctx->style.colors[ZR_COLOR_PLOT_LINES] = zr_rgba(45, 45, 45, 255); - ctx->style.colors[ZR_COLOR_PLOT_HIGHLIGHT] = zr_rgba(255, 0, 0, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR] = zr_rgba(180, 180, 180, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR] = zr_rgba(140, 140, 140, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR_HOVER] = zr_rgba(150, 150, 150, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR_ACTIVE] = zr_rgba(160, 160, 160, 255); - ctx->style.colors[ZR_COLOR_TABLE_LINES] = zr_rgba(100, 100, 100, 255); - ctx->style.colors[ZR_COLOR_TAB_HEADER] = zr_rgba(180, 180, 180, 255); - ctx->style.colors[ZR_COLOR_SCALER] = zr_rgba(100, 100, 100, 255); - } else if (theme == THEME_RED) { - ctx->style.rounding[ZR_ROUNDING_SCROLLBAR] = 0; - ctx->style.rounding[ZR_ROUNDING_PROPERTY] = 0; - ctx->style.properties[ZR_PROPERTY_SCROLLBAR_SIZE] = zr_vec2(10,10); - ctx->style.colors[ZR_COLOR_TEXT] = zr_rgba(190, 190, 190, 255); - ctx->style.colors[ZR_COLOR_TEXT_HOVERING] = zr_rgba(195, 195, 195, 255); - ctx->style.colors[ZR_COLOR_TEXT_ACTIVE] = zr_rgba(200, 200, 200, 255); - ctx->style.colors[ZR_COLOR_WINDOW] = zr_rgba(30, 33, 40, 215); - ctx->style.colors[ZR_COLOR_HEADER] = zr_rgba(181, 45, 69, 220); - ctx->style.colors[ZR_COLOR_BORDER] = zr_rgba(51, 55, 67, 255); - ctx->style.colors[ZR_COLOR_BUTTON] = zr_rgba(181, 45, 69, 255); - ctx->style.colors[ZR_COLOR_BUTTON_HOVER] = zr_rgba(190, 50, 70, 255); - ctx->style.colors[ZR_COLOR_BUTTON_ACTIVE] = zr_rgba(195, 55, 75, 255); - ctx->style.colors[ZR_COLOR_TOGGLE] = zr_rgba(51, 55, 67, 255); - ctx->style.colors[ZR_COLOR_TOGGLE_HOVER] = zr_rgba(45, 60, 60, 255); - ctx->style.colors[ZR_COLOR_TOGGLE_CURSOR] = zr_rgba(181, 45, 69, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE] = zr_rgba(181, 45, 69, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE_HOVER] = zr_rgba(181, 45, 69, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE_TEXT] = zr_rgba(190, 190, 190, 255); - ctx->style.colors[ZR_COLOR_SLIDER] = zr_rgba(51, 55, 67, 255); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR] = zr_rgba(181, 45, 69, 255); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR_HOVER] = zr_rgba(186, 50, 74, 255); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR_ACTIVE] = zr_rgba(191, 55, 79, 255); - ctx->style.colors[ZR_COLOR_PROGRESS] = zr_rgba(51, 55, 67, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR] = zr_rgba(181, 45, 69, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR_HOVER] = zr_rgba(186, 50, 74, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR_ACTIVE] = zr_rgba(191, 55, 79, 255); - ctx->style.colors[ZR_COLOR_PROPERTY] = zr_rgba(51, 55, 67, 255); - ctx->style.colors[ZR_COLOR_PROPERTY_HOVER] = zr_rgba(55, 60, 72, 255); - ctx->style.colors[ZR_COLOR_PROPERTY_ACTIVE] = zr_rgba(60, 65, 77, 255); - ctx->style.colors[ZR_COLOR_INPUT] = zr_rgba(51, 55, 67, 225); - ctx->style.colors[ZR_COLOR_INPUT_CURSOR] = zr_rgba(190, 190, 190, 255); - ctx->style.colors[ZR_COLOR_INPUT_TEXT] = zr_rgba(190, 190, 190, 255); - ctx->style.colors[ZR_COLOR_COMBO] = zr_rgba(51, 55, 67, 255); - ctx->style.colors[ZR_COLOR_HISTO] = zr_rgba(51, 55, 67, 255); - ctx->style.colors[ZR_COLOR_HISTO_BARS] = zr_rgba(170, 40, 60, 255); - ctx->style.colors[ZR_COLOR_HISTO_HIGHLIGHT] = zr_rgba( 255, 0, 0, 255); - ctx->style.colors[ZR_COLOR_PLOT] = zr_rgba(51, 55, 67, 255); - ctx->style.colors[ZR_COLOR_PLOT_LINES] = zr_rgba(170, 40, 60, 255); - ctx->style.colors[ZR_COLOR_PLOT_HIGHLIGHT] = zr_rgba(255, 0, 0, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR] = zr_rgba(30, 33, 40, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR] = zr_rgba(64, 84, 95, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR_HOVER] = zr_rgba(70, 90, 100, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR_ACTIVE] = zr_rgba(75, 95, 105, 255); - ctx->style.colors[ZR_COLOR_TABLE_LINES] = zr_rgba(100, 100, 100, 255); - ctx->style.colors[ZR_COLOR_TAB_HEADER] = zr_rgba(181, 45, 69, 220); - ctx->style.colors[ZR_COLOR_SCALER] = zr_rgba(100, 100, 100, 255); - } else if (theme == THEME_BLUE) { - ctx->style.rounding[ZR_ROUNDING_SCROLLBAR] = 0; - ctx->style.properties[ZR_PROPERTY_SCROLLBAR_SIZE] = zr_vec2(10,10); - ctx->style.colors[ZR_COLOR_TEXT] = zr_rgba(20, 20, 20, 255); - ctx->style.colors[ZR_COLOR_TEXT_HOVERING] = zr_rgba(195, 195, 195, 255); - ctx->style.colors[ZR_COLOR_TEXT_ACTIVE] = zr_rgba(200, 200, 200, 255); - ctx->style.colors[ZR_COLOR_WINDOW] = zr_rgba(202, 212, 214, 215); - ctx->style.colors[ZR_COLOR_HEADER] = zr_rgba(137, 182, 224, 220); - ctx->style.colors[ZR_COLOR_BORDER] = zr_rgba(140, 159, 173, 255); - ctx->style.colors[ZR_COLOR_BUTTON] = zr_rgba(137, 182, 224, 255); - ctx->style.colors[ZR_COLOR_BUTTON_HOVER] = zr_rgba(142, 187, 229, 255); - ctx->style.colors[ZR_COLOR_BUTTON_ACTIVE] = zr_rgba(147, 192, 234, 255); - ctx->style.colors[ZR_COLOR_TOGGLE] = zr_rgba(177, 210, 210, 255); - ctx->style.colors[ZR_COLOR_TOGGLE_HOVER] = zr_rgba(182, 215, 215, 255); - ctx->style.colors[ZR_COLOR_TOGGLE_CURSOR] = zr_rgba(137, 182, 224, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE] = zr_rgba(147, 192, 234, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE_HOVER] = zr_rgba(150, 150, 150, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE_TEXT] = zr_rgba(70, 70, 70, 255); - ctx->style.colors[ZR_COLOR_SLIDER] = zr_rgba(177, 210, 210, 255); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR] = zr_rgba(137, 182, 224, 245); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR_HOVER] = zr_rgba(142, 188, 229, 255); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR_ACTIVE] = zr_rgba(147, 193, 234, 255); - ctx->style.colors[ZR_COLOR_PROGRESS] = zr_rgba(177, 210, 210, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR] = zr_rgba(137, 182, 224, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR_HOVER] = zr_rgba(142, 188, 229, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR_ACTIVE] = zr_rgba(147, 193, 234, 255); - ctx->style.colors[ZR_COLOR_PROPERTY] = zr_rgba(210, 210, 210, 255); - ctx->style.colors[ZR_COLOR_PROPERTY_HOVER] = zr_rgba(235, 235, 235, 255); - ctx->style.colors[ZR_COLOR_PROPERTY_ACTIVE] = zr_rgba(230, 230, 230, 255); - ctx->style.colors[ZR_COLOR_INPUT] = zr_rgba(210, 210, 210, 225); - ctx->style.colors[ZR_COLOR_INPUT_CURSOR] = zr_rgba(20, 20, 20, 255); - ctx->style.colors[ZR_COLOR_INPUT_TEXT] = zr_rgba(20, 20, 20, 255); - ctx->style.colors[ZR_COLOR_COMBO] = zr_rgba(210, 210, 210, 255); - ctx->style.colors[ZR_COLOR_HISTO] = zr_rgba(210, 210, 210, 255); - ctx->style.colors[ZR_COLOR_HISTO_BARS] = zr_rgba(137, 182, 224, 255); - ctx->style.colors[ZR_COLOR_HISTO_HIGHLIGHT] = zr_rgba( 255, 0, 0, 255); - ctx->style.colors[ZR_COLOR_PLOT] = zr_rgba(210, 210, 210, 255); - ctx->style.colors[ZR_COLOR_PLOT_LINES] = zr_rgba(137, 182, 224, 255); - ctx->style.colors[ZR_COLOR_PLOT_HIGHLIGHT] = zr_rgba(255, 0, 0, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR] = zr_rgba(190, 200, 200, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR] = zr_rgba(64, 84, 95, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR_HOVER] = zr_rgba(70, 90, 100, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR_ACTIVE] = zr_rgba(75, 95, 105, 255); - ctx->style.colors[ZR_COLOR_TABLE_LINES] = zr_rgba(100, 100, 100, 255); - ctx->style.colors[ZR_COLOR_TAB_HEADER] = zr_rgba(156, 193, 220, 255); - ctx->style.colors[ZR_COLOR_SCALER] = zr_rgba(100, 100, 100, 255); - } else if (theme == THEME_DARK) { - ctx->style.rounding[ZR_ROUNDING_SCROLLBAR] = 0; - ctx->style.properties[ZR_PROPERTY_SCROLLBAR_SIZE] = zr_vec2(10,10); - ctx->style.colors[ZR_COLOR_TEXT] = zr_rgba(210, 210, 210, 255); - ctx->style.colors[ZR_COLOR_TEXT_HOVERING] = zr_rgba(195, 195, 195, 255); - ctx->style.colors[ZR_COLOR_TEXT_ACTIVE] = zr_rgba(200, 200, 200, 255); - ctx->style.colors[ZR_COLOR_WINDOW] = zr_rgba(57, 67, 71, 215); - ctx->style.colors[ZR_COLOR_HEADER] = zr_rgba(51, 51, 56, 220); - ctx->style.colors[ZR_COLOR_BORDER] = zr_rgba(46, 46, 46, 255); - ctx->style.colors[ZR_COLOR_BUTTON] = zr_rgba(48, 83, 111, 255); - ctx->style.colors[ZR_COLOR_BUTTON_HOVER] = zr_rgba(58, 93, 121, 255); - ctx->style.colors[ZR_COLOR_BUTTON_ACTIVE] = zr_rgba(63, 98, 126, 255); - ctx->style.colors[ZR_COLOR_TOGGLE] = zr_rgba(50, 58, 61, 255); - ctx->style.colors[ZR_COLOR_TOGGLE_HOVER] = zr_rgba(45, 53, 56, 255); - ctx->style.colors[ZR_COLOR_TOGGLE_CURSOR] = zr_rgba(48, 83, 111, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE] = zr_rgba(48, 83, 111, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE_HOVER] = zr_rgba(48, 83, 111, 255); - ctx->style.colors[ZR_COLOR_SELECTABLE_TEXT] = zr_rgba(210, 210, 210, 255); - ctx->style.colors[ZR_COLOR_SLIDER] = zr_rgba(50, 58, 61, 255); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR] = zr_rgba(48, 83, 111, 245); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR_HOVER] = zr_rgba(53, 88, 116, 255); - ctx->style.colors[ZR_COLOR_SLIDER_CURSOR_ACTIVE] = zr_rgba(58, 93, 121, 255); - ctx->style.colors[ZR_COLOR_PROGRESS] = zr_rgba(50, 58, 61, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR] = zr_rgba(48, 83, 111, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR_HOVER] = zr_rgba(53, 88, 116, 255); - ctx->style.colors[ZR_COLOR_PROGRESS_CURSOR_ACTIVE] = zr_rgba(58, 93, 121, 255); - ctx->style.colors[ZR_COLOR_PROPERTY] = zr_rgba(50, 58, 61, 255); - ctx->style.colors[ZR_COLOR_PROPERTY_HOVER] = zr_rgba(55, 63, 66, 255); - ctx->style.colors[ZR_COLOR_PROPERTY_ACTIVE] = zr_rgba(60, 68, 71, 255); - ctx->style.colors[ZR_COLOR_INPUT] = zr_rgba(50, 58, 61, 225); - ctx->style.colors[ZR_COLOR_INPUT_CURSOR] = zr_rgba(210, 210, 210, 255); - ctx->style.colors[ZR_COLOR_INPUT_TEXT] = zr_rgba(210, 210, 210, 255); - ctx->style.colors[ZR_COLOR_COMBO] = zr_rgba(50, 58, 61, 255); - ctx->style.colors[ZR_COLOR_HISTO] = zr_rgba(50, 58, 61, 255); - ctx->style.colors[ZR_COLOR_HISTO_BARS] = zr_rgba(48, 83, 111, 255); - ctx->style.colors[ZR_COLOR_HISTO_HIGHLIGHT] = zr_rgba(255, 0, 0, 255); - ctx->style.colors[ZR_COLOR_PLOT] = zr_rgba(50, 58, 61, 255); - ctx->style.colors[ZR_COLOR_PLOT_LINES] = zr_rgba(48, 83, 111, 255); - ctx->style.colors[ZR_COLOR_PLOT_HIGHLIGHT] = zr_rgba(255, 0, 0, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR] = zr_rgba(50, 58, 61, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR] = zr_rgba(48, 83, 111, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR_HOVER] = zr_rgba(53, 88, 116, 255); - ctx->style.colors[ZR_COLOR_SCROLLBAR_CURSOR_ACTIVE] = zr_rgba(58, 93, 121, 255); - ctx->style.colors[ZR_COLOR_TABLE_LINES] = zr_rgba(100, 100, 100, 255); - ctx->style.colors[ZR_COLOR_TAB_HEADER] = zr_rgba(48, 83, 111, 255); - ctx->style.colors[ZR_COLOR_SCALER] = zr_rgba(100, 100, 100, 255); - } else { - zr_load_default_style(ctx, ZR_DEFAULT_ALL); - } -} - -static int -control_window(struct zr_context *ctx, struct demo *gui) -{ - int i; - struct zr_panel layout; - if (zr_begin(ctx, &layout, "Control", zr_rect(0, 0, 350, 520), - ZR_WINDOW_CLOSABLE|ZR_WINDOW_MINIMIZABLE|ZR_WINDOW_MOVABLE| - ZR_WINDOW_SCALABLE|ZR_WINDOW_BORDER)) - { - if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Windows", ZR_MINIMIZED)) { - zr_layout_row_dynamic(ctx, 25, 2); - gui->show_simple = !zr_window_is_closed(ctx, "Show"); - gui->show_node = !zr_window_is_closed(ctx, "Node Editor"); - gui->show_demo = !zr_window_is_closed(ctx, "Demo"); -#ifndef DEMO_DO_NOT_DRAW_IMAGES - gui->show_filex = !zr_window_is_closed(ctx, "File Browser"); - gui->show_grid = !zr_window_is_closed(ctx, "Grid Demo"); - gui->show_basic = !zr_window_is_closed(ctx, "Basic Demo"); - gui->show_button = !zr_window_is_closed(ctx, "Button Demo"); -#endif - - if (zr_checkbox(ctx, "Show", &gui->show_simple) && !gui->show_simple) - zr_window_close(ctx, "Show"); - if (zr_checkbox(ctx, "Demo", &gui->show_demo) && !gui->show_demo) - zr_window_close(ctx, "Demo"); - if (zr_checkbox(ctx, "Node Editor", &gui->show_node) && !gui->show_node) - zr_window_close(ctx, "Node Editor"); -#ifndef DEMO_DO_NOT_DRAW_IMAGES - if (zr_checkbox(ctx, "Grid", &gui->show_grid) && !gui->show_grid) - zr_window_close(ctx, "Grid Demo"); - if (zr_checkbox(ctx, "Basic", &gui->show_basic) && !gui->show_basic) - zr_window_close(ctx, "Basic Demo"); - if (zr_checkbox(ctx, "Button", &gui->show_button) && !gui->show_button) - zr_window_close(ctx, "Button Demo"); - if (zr_checkbox(ctx, "Filex", &gui->show_filex) && !gui->show_filex) - zr_window_close(ctx, "File Browser"); -#endif - zr_layout_pop(ctx); - } - if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Metrics", ZR_MINIMIZED)) { - zr_layout_row_dynamic(ctx, 20, 2); - zr_label(ctx,"Total:", ZR_TEXT_LEFT); - zr_labelf(ctx, ZR_TEXT_LEFT, "%lu", gui->status.size); - zr_label(ctx,"Used:", ZR_TEXT_LEFT); - zr_labelf(ctx, ZR_TEXT_LEFT, "%lu", gui->status.allocated); - zr_label(ctx,"Required:", ZR_TEXT_LEFT); - zr_labelf(ctx, ZR_TEXT_LEFT, "%lu", gui->status.needed); - zr_label(ctx,"Calls:", ZR_TEXT_LEFT); - zr_labelf(ctx, ZR_TEXT_LEFT, "%lu", gui->status.calls); - zr_layout_pop(ctx); - } - if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Properties", ZR_MINIMIZED)) { - zr_layout_row_dynamic(ctx, 22, 3); - for (i = 0; i <= ZR_PROPERTY_SCROLLBAR_SIZE; ++i) { - zr_label(ctx, zr_get_property_name((enum zr_style_properties)i), ZR_TEXT_LEFT); - zr_property_float(ctx, "#X:", 0, &ctx->style.properties[i].x, 20, 1, 1); - zr_property_float(ctx, "#Y:", 0, &ctx->style.properties[i].y, 20, 1, 1); - } - zr_layout_pop(ctx); - } - if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Rounding", ZR_MINIMIZED)) { - zr_layout_row_dynamic(ctx, 22, 2); - for (i = 0; i < ZR_ROUNDING_MAX; ++i) { - zr_label(ctx, zr_get_rounding_name((enum zr_style_rounding)i), ZR_TEXT_LEFT); - zr_property_float(ctx, "#R:", 0, &ctx->style.rounding[i], 20, 1, 1); - } - zr_layout_pop(ctx); - } - if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Color", ZR_MINIMIZED)) - { - struct zr_panel tab, combo; - enum theme old = gui->theme; - static const char *themes[] = {"Black", "White", "Red", "Blue", "Dark", "Grey"}; - - zr_layout_row_dynamic(ctx, 25, 2); - zr_label(ctx, "THEME:", ZR_TEXT_LEFT); - if (zr_combo_begin_text(ctx, &combo, themes[gui->theme], 300)) { - zr_layout_row_dynamic(ctx, 25, 1); - gui->theme = zr_combo_item(ctx, themes[THEME_BLACK], ZR_TEXT_CENTERED) ? THEME_BLACK : gui->theme; - gui->theme = zr_combo_item(ctx, themes[THEME_WHITE], ZR_TEXT_CENTERED) ? THEME_WHITE : gui->theme; - gui->theme = zr_combo_item(ctx, themes[THEME_RED], ZR_TEXT_CENTERED) ? THEME_RED : gui->theme; - gui->theme = zr_combo_item(ctx, themes[THEME_BLUE], ZR_TEXT_CENTERED) ? THEME_BLUE : gui->theme; - gui->theme = zr_combo_item(ctx, themes[THEME_DARK], ZR_TEXT_CENTERED) ? THEME_DARK : gui->theme; - if (old != gui->theme) set_style(ctx, gui->theme); - zr_combo_end(ctx); - } - - zr_layout_row_dynamic(ctx, 300, 1); - if (zr_group_begin(ctx, &tab, "Colors", 0)) - { - for (i = 0; i < ZR_COLOR_COUNT; ++i) { - zr_layout_row_dynamic(ctx, 25, 2); - zr_label(ctx, zr_get_color_name((enum zr_style_colors)i), ZR_TEXT_LEFT); - - if (zr_combo_begin_color(ctx, &combo, ctx->style.colors[i], 400)) { - enum color_mode {COL_RGB, COL_HSV}; - static int col_mode = COL_RGB; - #ifndef DEMO_DO_NOT_USE_COLOR_PICKER - zr_layout_row_dynamic(ctx, 120, 1); - ctx->style.colors[i] = zr_color_picker(ctx, ctx->style.colors[i], ZR_RGBA); - #endif - - zr_layout_row_dynamic(ctx, 25, 2); - col_mode = zr_option(ctx, "RGB", col_mode == COL_RGB) ? COL_RGB : col_mode; - col_mode = zr_option(ctx, "HSV", col_mode == COL_HSV) ? COL_HSV : col_mode; - zr_layout_row_dynamic(ctx, 25, 1); - if (col_mode == COL_RGB) { - ctx->style.colors[i].r = (zr_byte)zr_propertyi(ctx, "#R:", 0, ctx->style.colors[i].r, 255, 1,1); - ctx->style.colors[i].g = (zr_byte)zr_propertyi(ctx, "#G:", 0, ctx->style.colors[i].g, 255, 1,1); - ctx->style.colors[i].b = (zr_byte)zr_propertyi(ctx, "#B:", 0, ctx->style.colors[i].b, 255, 1,1); - ctx->style.colors[i].a = (zr_byte)zr_propertyi(ctx, "#A:", 0, ctx->style.colors[i].a, 255, 1,1); - } else { - zr_byte tmp[4]; - zr_color_hsva_bv(tmp, ctx->style.colors[i]); - tmp[0] = (zr_byte)zr_propertyi(ctx, "#H:", 0, tmp[0], 255, 1,1); - tmp[1] = (zr_byte)zr_propertyi(ctx, "#S:", 0, tmp[1], 255, 1,1); - tmp[2] = (zr_byte)zr_propertyi(ctx, "#V:", 0, tmp[2], 255, 1,1); - tmp[3] = (zr_byte)zr_propertyi(ctx, "#A:", 0, tmp[3], 255, 1,1); - ctx->style.colors[i] = zr_hsva_bv(tmp); - } - zr_combo_end(ctx); - } - } - zr_group_end(ctx); - } - zr_layout_pop(ctx); - } - } - zr_end(ctx); - return !zr_window_is_closed(ctx, "Control"); -} - /* =============================================================== * * SIMPLE WINDOW @@ -437,12 +118,12 @@ simple_window(struct zr_context *ctx) static int property = 20; zr_layout_row_static(ctx, 30, 80, 1); - if (zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT)) { + if (zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT)) { /* event handling */ } zr_layout_row_dynamic(ctx, 30, 2); - if (zr_option(ctx, "easy", op == EASY)) op = EASY; - if (zr_option(ctx, "hard", op == HARD)) op = HARD; + if (zr_option_label(ctx, "easy", op == EASY)) op = EASY; + if (zr_option_label(ctx, "hard", op == HARD)) op = HARD; zr_layout_row_dynamic(ctx, 22, 1); zr_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); @@ -478,7 +159,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* window flags */ window_flags = 0; - ctx->style.header.align = header_align; + ctx->style.window.header.align = header_align; if (border) window_flags |= ZR_WINDOW_BORDER; if (resize) window_flags |= ZR_WINDOW_SCALABLE; if (moveable) window_flags |= ZR_WINDOW_MOVABLE; @@ -500,7 +181,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_menubar_begin(ctx); zr_layout_row_begin(ctx, ZR_STATIC, 25, 2); zr_layout_row_push(ctx, 45); - if (zr_menu_text_begin(ctx, &menu, "MENU", ZR_TEXT_DEFAULT_LEFT, 120)) + if (zr_menu_begin_label(ctx, &menu, "MENU", ZR_TEXT_LEFT, 120)) { zr_layout_row_dynamic(ctx, 25, 1); if (menu_state == MENU_DEFAULT) { @@ -508,31 +189,31 @@ demo_window(struct demo *gui, struct zr_context *ctx) static int slider = 10; static int check = zr_true; - if (zr_menu_item(ctx, ZR_TEXT_DEFAULT_LEFT, "Hide")) + if (zr_menu_item_label(ctx, "Hide", ZR_TEXT_LEFT)) show_menu = zr_false; - if (zr_menu_item(ctx, ZR_TEXT_DEFAULT_LEFT, "About")) + if (zr_menu_item_label(ctx, "About", ZR_TEXT_LEFT)) show_app_about = zr_true; zr_progress(ctx, &prog, 100, ZR_MODIFIABLE); zr_slider_int(ctx, 0, &slider, 16, 1); - zr_checkbox(ctx, "check", &check); - if (zr_button_text_symbol(ctx, ZR_SYMBOL_TRIANGLE_RIGHT, - "Windows", ZR_TEXT_DEFAULT_LEFT, ZR_BUTTON_DEFAULT)) + zr_checkbox_label(ctx, "check", &check); + if (zr_button_symbol_label(ctx, ZR_SYMBOL_TRIANGLE_RIGHT, + "Windows", ZR_TEXT_LEFT, ZR_BUTTON_DEFAULT)) menu_state = MENU_WINDOWS; } else { - if (zr_selectable(ctx, "Show", ZR_TEXT_DEFAULT_LEFT, &gui->show_simple) && !gui->show_simple) + if (zr_selectable_label(ctx, "Show", ZR_TEXT_LEFT, &gui->show_simple) && !gui->show_simple) zr_window_close(ctx, "Show"); - if (zr_selectable(ctx, "Node Editor", ZR_TEXT_DEFAULT_LEFT, &gui->show_node) && !gui->show_node) + if (zr_selectable_label(ctx, "Node Editor", ZR_TEXT_LEFT, &gui->show_node) && !gui->show_node) zr_window_close(ctx, "Node Editor"); #ifndef DEMO_DO_NOT_DRAW_IMAGES - if (zr_selectable(ctx, "Grid", ZR_TEXT_DEFAULT_LEFT, &gui->show_grid) && !gui->show_grid) + if (zr_selectable_label(ctx, "Grid", ZR_TEXT_LEFT, &gui->show_grid) && !gui->show_grid) zr_window_close(ctx, "Grid Demo"); - if (zr_selectable(ctx, "Basic", ZR_TEXT_DEFAULT_LEFT, &gui->show_basic) && !gui->show_basic) + if (zr_selectable_label(ctx, "Basic", ZR_TEXT_LEFT, &gui->show_basic) && !gui->show_basic) zr_window_close(ctx, "Basic Demo"); - if (zr_selectable(ctx, "Button", ZR_TEXT_DEFAULT_LEFT, &gui->show_button) && !gui->show_button) + if (zr_selectable_label(ctx, "Button", ZR_TEXT_LEFT, &gui->show_button) && !gui->show_button) zr_window_close(ctx, "Button Demo"); #endif - if (zr_button_text_symbol(ctx, ZR_SYMBOL_TRIANGLE_LEFT, - "Back", ZR_TEXT_DEFAULT_RIGHT, ZR_BUTTON_DEFAULT)) + if (zr_button_symbol_label(ctx, ZR_SYMBOL_TRIANGLE_LEFT, + "Back", ZR_TEXT_RIGHT, ZR_BUTTON_DEFAULT)) menu_state = MENU_DEFAULT; } zr_menu_end(ctx); @@ -540,7 +221,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_layout_row_push(ctx, 70); zr_progress(ctx, &mprog, 100, ZR_MODIFIABLE); zr_slider_int(ctx, 0, &mslider, 16, 1); - zr_checkbox(ctx, "check", &mcheck); + zr_checkbox_label(ctx, "check", &mcheck); zr_menubar_end(ctx); } @@ -563,14 +244,14 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* window flags */ if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Window", ZR_MINIMIZED)) { zr_layout_row_dynamic(ctx, 30, 2); - zr_checkbox(ctx, "Titlebar", &titlebar); - zr_checkbox(ctx, "Menu", &show_menu); - zr_checkbox(ctx, "Border", &border); - zr_checkbox(ctx, "Resizable", &resize); - zr_checkbox(ctx, "Moveable", &moveable); - zr_checkbox(ctx, "No Scrollbar", &no_scrollbar); - zr_checkbox(ctx, "Minimizable", &minimizable); - zr_checkbox(ctx, "Closeable", &close); + zr_checkbox_label(ctx, "Titlebar", &titlebar); + zr_checkbox_label(ctx, "Menu", &show_menu); + zr_checkbox_label(ctx, "Border", &border); + zr_checkbox_label(ctx, "Resizable", &resize); + zr_checkbox_label(ctx, "Moveable", &moveable); + zr_checkbox_label(ctx, "No Scrollbar", &no_scrollbar); + zr_checkbox_label(ctx, "Minimizable", &minimizable); + zr_checkbox_label(ctx, "Closeable", &close); zr_layout_pop(ctx); } @@ -601,9 +282,9 @@ demo_window(struct demo *gui, struct zr_context *ctx) { /* Buttons Widgets */ zr_layout_row_static(ctx, 30, 100, 3); - if (zr_button_text(ctx, "Button", ZR_BUTTON_DEFAULT)) + if (zr_button_label(ctx, "Button", ZR_BUTTON_DEFAULT)) fprintf(stdout, "Button pressed!\n"); - if (zr_button_text(ctx, "Repeater", ZR_BUTTON_REPEATER)) + if (zr_button_label(ctx, "Repeater", ZR_BUTTON_REPEATER)) fprintf(stdout, "Repeater is being pressed!\n"); zr_button_color(ctx, zr_rgb(0,0,255), ZR_BUTTON_DEFAULT); @@ -618,8 +299,8 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_button_symbol(ctx, ZR_SYMBOL_TRIANGLE_RIGHT, ZR_BUTTON_DEFAULT); zr_layout_row_static(ctx, 30, 100, 2); - zr_button_text_symbol(ctx, ZR_SYMBOL_TRIANGLE_LEFT, "prev", ZR_TEXT_RIGHT, ZR_BUTTON_DEFAULT); - zr_button_text_symbol(ctx, ZR_SYMBOL_TRIANGLE_RIGHT, "next", ZR_TEXT_LEFT, ZR_BUTTON_DEFAULT); + zr_button_symbol_label(ctx, ZR_SYMBOL_TRIANGLE_LEFT, "prev", ZR_TEXT_RIGHT, ZR_BUTTON_DEFAULT); + zr_button_symbol_label(ctx, ZR_SYMBOL_TRIANGLE_RIGHT, "next", ZR_TEXT_LEFT, ZR_BUTTON_DEFAULT); zr_layout_pop(ctx); } @@ -642,12 +323,12 @@ demo_window(struct demo *gui, struct zr_context *ctx) static const float ratio[] = {120, 150}; zr_layout_row_static(ctx, 30, 100, 1); - zr_checkbox(ctx, "Checkbox", &checkbox); + zr_checkbox_label(ctx, "Checkbox", &checkbox); zr_layout_row_static(ctx, 30, 80, 3); - option = zr_option(ctx, "optionA", option == A) ? A : option; - option = zr_option(ctx, "optionB", option == B) ? B : option; - option = zr_option(ctx, "optionC", option == C) ? C : option; + option = zr_option_label(ctx, "optionA", option == A) ? A : option; + option = zr_option_label(ctx, "optionB", option == B) ? B : option; + option = zr_option_label(ctx, "optionC", option == C) ? C : option; zr_layout_row(ctx, ZR_STATIC, 30, 2, ratio); @@ -687,11 +368,11 @@ demo_window(struct demo *gui, struct zr_context *ctx) { static int selected[4] = {zr_false, zr_false, zr_true, zr_false}; zr_layout_row_static(ctx, 18, 100, 1); - zr_selectable(ctx, "Selectable", ZR_TEXT_LEFT, &selected[0]); - zr_selectable(ctx, "Selectable", ZR_TEXT_LEFT, &selected[1]); + zr_selectable_label(ctx, "Selectable", ZR_TEXT_LEFT, &selected[0]); + zr_selectable_label(ctx, "Selectable", ZR_TEXT_LEFT, &selected[1]); zr_label(ctx, "Not Selectable", ZR_TEXT_LEFT); - zr_selectable(ctx, "Selectable", ZR_TEXT_LEFT, &selected[2]); - zr_selectable(ctx, "Selectable", ZR_TEXT_LEFT, &selected[3]); + zr_selectable_label(ctx, "Selectable", ZR_TEXT_LEFT, &selected[2]); + zr_selectable_label(ctx, "Selectable", ZR_TEXT_LEFT, &selected[3]); zr_layout_pop(ctx); } if (zr_layout_push(ctx, ZR_LAYOUT_NODE, "Grid", ZR_MINIMIZED)) @@ -700,7 +381,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) static int selected[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; zr_layout_row_static(ctx, 50, 50, 4); for (i = 0; i < 16; ++i) { - if (zr_selectable(ctx, "Z", ZR_TEXT_CENTERED, &selected[i])) { + if (zr_selectable_label(ctx, "Z", ZR_TEXT_CENTERED, &selected[i])) { int x = (i % 4), y = i / 4; if (x > 0) selected[i - 1] ^= 1; if (x < 3) selected[i + 1] ^= 1; @@ -784,8 +465,8 @@ demo_window(struct demo *gui, struct zr_context *ctx) #endif zr_layout_row_dynamic(ctx, 25, 2); - col_mode = zr_option(ctx, "RGB", col_mode == COL_RGB) ? COL_RGB : col_mode; - col_mode = zr_option(ctx, "HSV", col_mode == COL_HSV) ? COL_HSV : col_mode; + col_mode = zr_option_label(ctx, "RGB", col_mode == COL_RGB) ? COL_RGB : col_mode; + col_mode = zr_option_label(ctx, "HSV", col_mode == COL_HSV) ? COL_HSV : col_mode; zr_layout_row_dynamic(ctx, 25, 1); if (col_mode == COL_RGB) { @@ -808,7 +489,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* progressbar combobox */ sum = prog_a + prog_b + prog_c + prog_d; sprintf(buffer, "%lu", sum); - if (zr_combo_begin_text(ctx, &combo, buffer, 200)) { + if (zr_combo_begin_label(ctx, &combo, buffer, 200)) { zr_layout_row_dynamic(ctx, 30, 1); zr_progress(ctx, &prog_a, 100, ZR_MODIFIABLE); zr_progress(ctx, &prog_b, 100, ZR_MODIFIABLE); @@ -820,18 +501,18 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* checkbox combobox */ sum = (size_t)(check_values[0] + check_values[1] + check_values[2] + check_values[3] + check_values[4]); sprintf(buffer, "%lu", sum); - if (zr_combo_begin_text(ctx, &combo, buffer, 200)) { + if (zr_combo_begin_label(ctx, &combo, buffer, 200)) { zr_layout_row_dynamic(ctx, 30, 1); - zr_checkbox(ctx, weapons[0], &check_values[0]); - zr_checkbox(ctx, weapons[1], &check_values[1]); - zr_checkbox(ctx, weapons[2], &check_values[2]); - zr_checkbox(ctx, weapons[3], &check_values[3]); + zr_checkbox_label(ctx, weapons[0], &check_values[0]); + zr_checkbox_label(ctx, weapons[1], &check_values[1]); + zr_checkbox_label(ctx, weapons[2], &check_values[2]); + zr_checkbox_label(ctx, weapons[3], &check_values[3]); zr_combo_end(ctx); } /* complex text combobox */ sprintf(buffer, "%.2f, %.2f, %.2f", position[0], position[1],position[2]); - if (zr_combo_begin_text(ctx, &combo, buffer, 200)) { + if (zr_combo_begin_label(ctx, &combo, buffer, 200)) { zr_layout_row_dynamic(ctx, 25, 1); zr_property_float(ctx, "#X:", -1024.0f, &position[0], 1024.0f, 1,0.5f); zr_property_float(ctx, "#Y:", -1024.0f, &position[1], 1024.0f, 1,0.5f); @@ -841,7 +522,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* chart combobox */ sprintf(buffer, "%.1f", chart_selection); - if (zr_combo_begin_text(ctx, &combo, buffer, 250)) { + if (zr_combo_begin_label(ctx, &combo, buffer, 250)) { size_t i = 0; static const float values[]={26.0f,13.0f,30.0f,15.0f,25.0f,10.0f,20.0f,40.0f, 12.0f, 8.0f, 22.0f, 28.0f, 5.0f}; zr_layout_row_dynamic(ctx, 150, 1); @@ -874,7 +555,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* time combobox */ sprintf(buffer, "%02d:%02d:%02d", sel_time.tm_hour, sel_time.tm_min, sel_time.tm_sec); - if (zr_combo_begin_text(ctx, &combo, buffer, 250)) { + if (zr_combo_begin_label(ctx, &combo, buffer, 250)) { time_selected = 1; zr_layout_row_dynamic(ctx, 25, 1); sel_time.tm_sec = zr_propertyi(ctx, "#S:", 0, sel_time.tm_sec, 60, 1, 1); @@ -886,7 +567,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* date combobox */ zr_layout_row_static(ctx, 25, 350, 1); sprintf(buffer, "%02d-%02d-%02d", sel_date.tm_mday, sel_date.tm_mon+1, sel_date.tm_year+1900); - if (zr_combo_begin_text(ctx, &combo, buffer, 400)) { + if (zr_combo_begin_label(ctx, &combo, buffer, 400)) { int i = 0; const char *month[] = {"January", "February", "March", "Apil", "May", "June", "July", "August", "September", "Ocotober", "November", "December"}; const char *week_days[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}; @@ -909,7 +590,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) } zr_layout_row_push(ctx, 0.9f); sprintf(buffer, "%s %d", month[sel_date.tm_mon], year); - zr_label(ctx, buffer, ZR_TEXT_DEFAULT_CENTER); + zr_label(ctx, buffer, ZR_TEXT_CENTERED); zr_layout_row_push(ctx, 0.05f); if (zr_button_symbol(ctx, ZR_SYMBOL_TRIANGLE_RIGHT, ZR_BUTTON_DEFAULT)) { if (sel_date.tm_mon == 11) { @@ -931,13 +612,13 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* weekdays */ zr_layout_row_dynamic(ctx, 35, 7); for (i = 0; i < (int)LEN(week_days); ++i) - zr_label(ctx, week_days[i], ZR_TEXT_DEFAULT_CENTER); + zr_label(ctx, week_days[i], ZR_TEXT_CENTERED); /* days */ if (week_day > 0) zr_spacing(ctx, week_day); for (i = 1; i <= days; ++i) { sprintf(buffer, "%d", i); - if (zr_button_text(ctx, buffer, ZR_BUTTON_DEFAULT)) { + if (zr_button_label(ctx, buffer, ZR_BUTTON_DEFAULT)) { sel_date.tm_mday = i; zr_combo_close(ctx); } @@ -953,11 +634,9 @@ demo_window(struct demo *gui, struct zr_context *ctx) { static const float ratio[] = {120, 150}; static char field_buffer[64]; - static char box_buffer[512]; static char text[9][64]; static size_t text_len[9]; static size_t field_len; - static size_t box_len; zr_flags active; zr_layout_row(ctx, ZR_STATIC, 25, 2, ratio); @@ -989,21 +668,9 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_label(ctx, "Field:", ZR_TEXT_LEFT); zr_edit_string(ctx, ZR_EDIT_FIELD, field_buffer, &field_len, 64, zr_filter_default); - zr_label(ctx, "Box:", ZR_TEXT_LEFT); - zr_layout_row_static(ctx, 180, 278, 1); - zr_edit_string(ctx, ZR_EDIT_BOX, box_buffer, &box_len, 512, zr_filter_default); - zr_layout_row(ctx, ZR_STATIC, 25, 2, ratio); active = zr_edit_string(ctx, ZR_EDIT_FIELD|ZR_EDIT_SIGCOMIT, text[7], &text_len[7], 64, zr_filter_ascii); - if (zr_button_text(ctx, "Submit", ZR_BUTTON_DEFAULT) || - (active & ZR_EDIT_COMMITED)) - { - text[7][text_len[7]] = '\n'; - text_len[7]++; - memcpy(&box_buffer[box_len], &text[7], text_len[7]); - box_len += text_len[7]; - text_len[7] = 0; - } + zr_button_label(ctx, "Submit", ZR_BUTTON_DEFAULT); zr_layout_row_end(ctx); zr_layout_pop(ctx); } @@ -1036,16 +703,17 @@ demo_window(struct demo *gui, struct zr_context *ctx) index = -1; zr_layout_row_dynamic(ctx, 100, 1); bounds = zr_widget_bounds(ctx); - zr_chart_begin(ctx, ZR_CHART_LINES, 32, -1.0f, 1.0f); - for (i = 0; i < 32; ++i) { - zr_flags res = zr_chart_push(ctx, (float)cos(id)); - if (res & ZR_CHART_HOVERING) - index = (int)i; - if (res & ZR_CHART_CLICKED) - line_index = (int)i; - id += step; + if (zr_chart_begin(ctx, ZR_CHART_LINES, 32, -1.0f, 1.0f)) { + for (i = 0; i < 32; ++i) { + zr_flags res = zr_chart_push(ctx, (float)cos(id)); + if (res & ZR_CHART_HOVERING) + index = (int)i; + if (res & ZR_CHART_CLICKED) + line_index = (int)i; + id += step; + } + zr_chart_end(ctx); } - zr_chart_end(ctx); if (index != -1) { char buffer[ZR_MAX_NUMBER_BUFFER]; @@ -1061,17 +729,17 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* column chart */ zr_layout_row_dynamic(ctx, 100, 1); bounds = zr_widget_bounds(ctx); - zr_chart_begin(ctx, ZR_CHART_COLUMN, 32, 0.0f, 1.0f); - for (i = 0; i < 32; ++i) { - zr_flags res = zr_chart_push(ctx, (float)fabs(sin(id))); - if (res & ZR_CHART_HOVERING) - index = (int)i; - if (res & ZR_CHART_CLICKED) - col_index = (int)i; - id += step; + if (zr_chart_begin(ctx, ZR_CHART_COLUMN, 32, 0.0f, 1.0f)) { + for (i = 0; i < 32; ++i) { + zr_flags res = zr_chart_push(ctx, (float)fabs(sin(id))); + if (res & ZR_CHART_HOVERING) + index = (int)i; + if (res & ZR_CHART_CLICKED) + col_index = (int)i; + id += step; + } + zr_chart_end(ctx); } - zr_chart_end(ctx); - if (index != -1) { char buffer[ZR_MAX_NUMBER_BUFFER]; sprintf(buffer, "Value: %.2f", (float)fabs(sin(step * (float)index))); @@ -1102,15 +770,15 @@ demo_window(struct demo *gui, struct zr_context *ctx) static int slider = 10; zr_layout_row_dynamic(ctx, 25, 1); - zr_checkbox(ctx, "Menu", &show_menu); + zr_checkbox_label(ctx, "Menu", &show_menu); zr_progress(ctx, &prog, 100, ZR_MODIFIABLE); zr_slider_int(ctx, 0, &slider, 16, 1); - if (zr_contextual_item(ctx, "About", ZR_TEXT_CENTERED)) + if (zr_contextual_item_label(ctx, "About", ZR_TEXT_CENTERED)) show_app_about = zr_true; - zr_selectable(ctx, select[0]?"Unselect":"Select", ZR_TEXT_LEFT, &select[0]); - zr_selectable(ctx, select[1]?"Unselect":"Select", ZR_TEXT_LEFT, &select[1]); - zr_selectable(ctx, select[2]?"Unselect":"Select", ZR_TEXT_LEFT, &select[2]); - zr_selectable(ctx, select[3]?"Unselect":"Select", ZR_TEXT_LEFT, &select[3]); + zr_selectable_label(ctx, select[0]?"Unselect":"Select", ZR_TEXT_LEFT, &select[0]); + zr_selectable_label(ctx, select[1]?"Unselect":"Select", ZR_TEXT_LEFT, &select[1]); + zr_selectable_label(ctx, select[2]?"Unselect":"Select", ZR_TEXT_LEFT, &select[2]); + zr_selectable_label(ctx, select[3]?"Unselect":"Select", ZR_TEXT_LEFT, &select[3]); zr_contextual_end(ctx); } @@ -1137,7 +805,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_layout_row_push(ctx, 100); zr_label(ctx, "Popup:", ZR_TEXT_LEFT); zr_layout_row_push(ctx, 50); - if (zr_button_text(ctx, "Popup", ZR_BUTTON_DEFAULT)) + if (zr_button_label(ctx, "Popup", ZR_BUTTON_DEFAULT)) popup_active = 1; zr_layout_row_end(ctx); @@ -1149,11 +817,11 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_layout_row_dynamic(ctx, 25, 1); zr_label(ctx, "A terrible error as occured", ZR_TEXT_LEFT); zr_layout_row_dynamic(ctx, 25, 2); - if (zr_button_text(ctx, "OK", ZR_BUTTON_DEFAULT)) { + if (zr_button_label(ctx, "OK", ZR_BUTTON_DEFAULT)) { popup_active = 0; zr_popup_close(ctx); } - if (zr_button_text(ctx, "Cancel", ZR_BUTTON_DEFAULT)) { + if (zr_button_label(ctx, "Cancel", ZR_BUTTON_DEFAULT)) { popup_active = 0; zr_popup_close(ctx); } @@ -1181,64 +849,64 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_layout_row_dynamic(ctx, 30, 1); zr_label(ctx, "Dynamic fixed column layout with generated position and size:", ZR_TEXT_LEFT); zr_layout_row_dynamic(ctx, 30, 3); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_row_dynamic(ctx, 30, 1); zr_label(ctx, "static fixed column layout with generated position and size:", ZR_TEXT_LEFT); zr_layout_row_static(ctx, 30, 100, 3); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_row_dynamic(ctx, 30, 1); zr_label(ctx, "Dynamic array-based custom column layout with generated position and custom size:",ZR_TEXT_LEFT); zr_layout_row(ctx, ZR_DYNAMIC, 30, 3, ratio_two); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_row_dynamic(ctx, 30, 1); zr_label(ctx, "Static array-based custom column layout with generated position and custom size:",ZR_TEXT_LEFT ); zr_layout_row(ctx, ZR_STATIC, 30, 3, width_two); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_row_dynamic(ctx, 30, 1); zr_label(ctx, "Dynamic immediate mode custom column layout with generated position and custom size:",ZR_TEXT_LEFT); zr_layout_row_begin(ctx, ZR_DYNAMIC, 30, 3); zr_layout_row_push(ctx, 0.2f); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_row_push(ctx, 0.6f); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_row_push(ctx, 0.2f); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_row_end(ctx); zr_layout_row_dynamic(ctx, 30, 1); zr_label(ctx, "Static immmediate mode custom column layout with generated position and custom size:", ZR_TEXT_LEFT); zr_layout_row_begin(ctx, ZR_STATIC, 30, 3); zr_layout_row_push(ctx, 100); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_row_push(ctx, 200); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_row_push(ctx, 50); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_row_end(ctx); zr_layout_row_dynamic(ctx, 30, 1); zr_label(ctx, "Static free space with custom position and custom size:", ZR_TEXT_LEFT); zr_layout_space_begin(ctx, ZR_STATIC, 120, 4); zr_layout_space_push(ctx, zr_rect(100, 0, 100, 30)); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_space_push(ctx, zr_rect(0, 15, 100, 30)); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_space_push(ctx, zr_rect(200, 15, 100, 30)); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_space_push(ctx, zr_rect(100, 30, 100, 30)); - zr_button_text(ctx, "button", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "button", ZR_BUTTON_DEFAULT); zr_layout_space_end(ctx); zr_layout_pop(ctx); } @@ -1258,9 +926,9 @@ demo_window(struct demo *gui, struct zr_context *ctx) if (group_titlebar) group_flags |= ZR_WINDOW_TITLE; zr_layout_row_dynamic(ctx, 30, 3); - zr_checkbox(ctx, "Titlebar", &group_titlebar); - zr_checkbox(ctx, "Border", &group_border); - zr_checkbox(ctx, "No Scrollbar", &group_no_scrollbar); + zr_checkbox_label(ctx, "Titlebar", &group_titlebar); + zr_checkbox_label(ctx, "Border", &group_border); + zr_checkbox_label(ctx, "No Scrollbar", &group_no_scrollbar); zr_layout_row_begin(ctx, ZR_STATIC, 22, 2); zr_layout_row_push(ctx, 50); @@ -1277,7 +945,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) static int selected[16]; zr_layout_row_static(ctx, 18, 100, 1); for (i = 0; i < 16; ++i) - zr_selectable(ctx, (selected[i]) ? "Selected": "Unselected", ZR_TEXT_CENTERED, &selected[i]); + zr_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", ZR_TEXT_CENTERED, &selected[i]); zr_group_end(ctx); } zr_layout_pop(ctx); @@ -1303,7 +971,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_layout_row_dynamic(ctx, 25, 2); for (i = 0; i < 64; ++i) { sprintf(buffer, "%08d", ((((i%7)*10)^32))+(64+(i%2)*2)); - zr_button_text(ctx, buffer, ZR_BUTTON_DEFAULT); + zr_button_label(ctx, buffer, ZR_BUTTON_DEFAULT); } zr_group_end(ctx); } @@ -1320,31 +988,31 @@ demo_window(struct demo *gui, struct zr_context *ctx) static int selected[32]; zr_layout_row_static(ctx, 18, 100, 1); for (i = 0; i < 32; ++i) - zr_selectable(ctx, (selected[i]) ? "Selected": "Unselected", ZR_TEXT_CENTERED, &selected[i]); + zr_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", ZR_TEXT_CENTERED, &selected[i]); zr_group_end(ctx); } zr_layout_space_push(ctx, zr_rect(160,0,150,240)); if (zr_group_begin(ctx, &tab, "Group_top", ZR_WINDOW_BORDER)) { zr_layout_row_dynamic(ctx, 25, 1); - zr_button_text(ctx, "#FFAA", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFBB", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFCC", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFDD", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFEE", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFFF", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFAA", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFBB", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFCC", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFDD", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFEE", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFFF", ZR_BUTTON_DEFAULT); zr_group_end(ctx); } zr_layout_space_push(ctx, zr_rect(160,250,150,250)); if (zr_group_begin(ctx, &tab, "Group_buttom", ZR_WINDOW_BORDER)) { zr_layout_row_dynamic(ctx, 25, 1); - zr_button_text(ctx, "#FFAA", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFBB", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFCC", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFDD", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFEE", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFFF", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFAA", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFBB", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFCC", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFDD", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFEE", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFFF", ZR_BUTTON_DEFAULT); zr_group_end(ctx); } @@ -1353,7 +1021,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) static int selected[4]; zr_layout_row_static(ctx, 18, 100, 1); for (i = 0; i < 4; ++i) - zr_selectable(ctx, (selected[i]) ? "Selected": "Unselected", ZR_TEXT_CENTERED, &selected[i]); + zr_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", ZR_TEXT_CENTERED, &selected[i]); zr_group_end(ctx); } @@ -1362,7 +1030,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) static int selected[4]; zr_layout_row_static(ctx, 18, 100, 1); for (i = 0; i < 4; ++i) - zr_selectable(ctx, (selected[i]) ? "Selected": "Unselected", ZR_TEXT_CENTERED, &selected[i]); + zr_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", ZR_TEXT_CENTERED, &selected[i]); zr_group_end(ctx); } @@ -1371,7 +1039,7 @@ demo_window(struct demo *gui, struct zr_context *ctx) static int selected[4]; zr_layout_row_static(ctx, 18, 100, 1); for (i = 0; i < 4; ++i) - zr_selectable(ctx, (selected[i]) ? "Selected": "Unselected", ZR_TEXT_CENTERED, &selected[i]); + zr_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", ZR_TEXT_CENTERED, &selected[i]); zr_group_end(ctx); } zr_layout_space_end(ctx); @@ -1415,12 +1083,12 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* left space */ if (zr_group_begin(ctx, &sub, "left", ZR_WINDOW_NO_SCROLLBAR|ZR_WINDOW_BORDER|ZR_WINDOW_NO_SCROLLBAR)) { zr_layout_row_dynamic(ctx, 25, 1); - zr_button_text(ctx, "#FFAA", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFBB", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFCC", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFDD", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFEE", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFFF", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFAA", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFBB", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFCC", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFDD", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFEE", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFFF", ZR_BUTTON_DEFAULT); zr_group_end(ctx); } @@ -1438,12 +1106,12 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* middle space */ if (zr_group_begin(ctx, &sub, "center", ZR_WINDOW_BORDER|ZR_WINDOW_NO_SCROLLBAR)) { zr_layout_row_dynamic(ctx, 25, 1); - zr_button_text(ctx, "#FFAA", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFBB", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFCC", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFDD", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFEE", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFFF", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFAA", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFBB", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFCC", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFDD", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFEE", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFFF", ZR_BUTTON_DEFAULT); zr_group_end(ctx); } @@ -1461,12 +1129,12 @@ demo_window(struct demo *gui, struct zr_context *ctx) /* right space */ if (zr_group_begin(ctx, &sub, "right", ZR_WINDOW_BORDER|ZR_WINDOW_NO_SCROLLBAR)) { zr_layout_row_dynamic(ctx, 25, 1); - zr_button_text(ctx, "#FFAA", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFBB", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFCC", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFDD", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFEE", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFFF", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFAA", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFBB", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFCC", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFDD", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFEE", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFFF", ZR_BUTTON_DEFAULT); zr_group_end(ctx); } @@ -1494,12 +1162,12 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_layout_row_dynamic(ctx, a, 1); if (zr_group_begin(ctx, &sub, "top", ZR_WINDOW_NO_SCROLLBAR|ZR_WINDOW_BORDER)) { zr_layout_row_dynamic(ctx, 25, 3); - zr_button_text(ctx, "#FFAA", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFBB", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFCC", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFDD", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFEE", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFFF", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFAA", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFBB", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFCC", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFDD", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFEE", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFFF", ZR_BUTTON_DEFAULT); zr_group_end(ctx); } @@ -1519,12 +1187,12 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_layout_row_dynamic(ctx, b, 1); if (zr_group_begin(ctx, &sub, "middle", ZR_WINDOW_NO_SCROLLBAR|ZR_WINDOW_BORDER)) { zr_layout_row_dynamic(ctx, 25, 3); - zr_button_text(ctx, "#FFAA", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFBB", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFCC", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFDD", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFEE", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFFF", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFAA", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFBB", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFCC", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFDD", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFEE", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFFF", ZR_BUTTON_DEFAULT); zr_group_end(ctx); } @@ -1545,12 +1213,12 @@ demo_window(struct demo *gui, struct zr_context *ctx) zr_layout_row_dynamic(ctx, c, 1); if (zr_group_begin(ctx, &sub, "bottom", ZR_WINDOW_NO_SCROLLBAR|ZR_WINDOW_BORDER)) { zr_layout_row_dynamic(ctx, 25, 3); - zr_button_text(ctx, "#FFAA", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFBB", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFCC", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFDD", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFEE", ZR_BUTTON_DEFAULT); - zr_button_text(ctx, "#FFFF", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFAA", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFBB", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFCC", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFDD", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFEE", ZR_BUTTON_DEFAULT); + zr_button_label(ctx, "#FFFF", ZR_BUTTON_DEFAULT); zr_group_end(ctx); } zr_layout_pop(ctx); @@ -1578,12 +1246,6 @@ ui_piemenu(struct zr_context *ctx, struct zr_vec2 pos, float radius, struct zr_rect bounds; int active_item = 0; - /* hide popup background */ - struct zr_color border; - zr_push_color(ctx, ZR_COLOR_WINDOW, zr_rgba(0,0,0,0)); - border = ctx->style.colors[ZR_COLOR_BORDER]; - zr_push_color(ctx, ZR_COLOR_BORDER, zr_rgba(0,0,0,0)); - /* pie menu popup */ total_space = zr_window_get_content_region(ctx); zr_popup_begin(ctx, &popup, ZR_POPUP_STATIC, "piemenu", ZR_WINDOW_NO_SCROLLBAR, @@ -1598,14 +1260,14 @@ ui_piemenu(struct zr_context *ctx, struct zr_vec2 pos, float radius, const struct zr_input *in = &ctx->input; { /* allocate complete popup space for the menu */ - enum zr_widget_state state; + enum zr_widget_layout_states state; total_space = zr_window_get_content_region(ctx); total_space.x = total_space.y = 0; state = zr_widget(&bounds, ctx); } /* outer circle */ - zr_draw_circle(out, ZR_FILLED, bounds, zr_rgb(50,50,50)); + zr_fill_circle(out, bounds, zr_rgb(50,50,50)); { /* circle buttons */ float step = (2 * 3.141592654f) / (float)(MAX(1,item_count)); @@ -1620,15 +1282,15 @@ ui_piemenu(struct zr_context *ctx, struct zr_vec2 pos, float radius, for (i = 0; i < item_count; ++i) { struct zr_rect content; float rx, ry, dx, dy, a; - zr_draw_arc(out, ZR_FILLED, center.x, center.y, (bounds.w/2.0f), + zr_fill_arc(out, center.x, center.y, (bounds.w/2.0f), a_min, a_max, (active_item == i) ? zr_rgb(45,100,255): zr_rgb(60,60,60)); /* seperator line */ rx = bounds.w/2.0f; ry = 0; dx = rx * (float)cos(a_min) - ry * (float)sin(a_min); dy = rx * (float)sin(a_min) + ry * (float)cos(a_min); - zr_draw_line(out, center.x, center.y, - center.x + dx, center.y + dy, zr_rgb(50,50,50)); + zr_stroke_line(out, center.x, center.y, + center.x + dx, center.y + dy, 1.0f, zr_rgb(50,50,50)); /* button content */ a = a_min + (a_max - a_min)/2.0f; @@ -1646,7 +1308,7 @@ ui_piemenu(struct zr_context *ctx, struct zr_vec2 pos, float radius, inner.x = bounds.x + bounds.w/2 - bounds.w/4; inner.y = bounds.y + bounds.h/2 - bounds.h/4; inner.w = bounds.w/2; inner.h = bounds.h/2; - zr_draw_circle(out, ZR_FILLED, inner, zr_rgb(45,45,45)); + zr_fill_circle(out, inner, zr_rgb(45,45,45)); /* active icon content */ bounds.w = inner.w / 2.0f; @@ -1659,9 +1321,6 @@ ui_piemenu(struct zr_context *ctx, struct zr_vec2 pos, float radius, zr_layout_space_end(ctx); zr_popup_end(ctx); - zr_reset_colors(ctx); - zr_reset_properties(ctx); - if (!zr_input_is_mouse_down(&ctx->input, ZR_BUTTON_RIGHT)) return active_item; else return ret; @@ -1698,13 +1357,13 @@ grid_demo(struct zr_context *ctx) zr_label(ctx, "Binary:", ZR_TEXT_RIGHT); zr_edit_string(ctx, ZR_EDIT_FIELD, text[2], &text_len[2], 64, zr_filter_binary); zr_label(ctx, "Checkbox:", ZR_TEXT_RIGHT); - zr_checkbox(ctx, "Check me", &check); + zr_checkbox_label(ctx, "Check me", &check); zr_label(ctx, "Combobox:", ZR_TEXT_RIGHT); - if (zr_combo_begin_text(ctx, &combo, items[selected_item], 200)) { + if (zr_combo_begin_label(ctx, &combo, items[selected_item], 200)) { zr_layout_row_dynamic(ctx, 30, 1); for (i = 0; i < 3; ++i) - if (zr_combo_item(ctx, items[i], ZR_TEXT_LEFT)) + if (zr_combo_item_label(ctx, items[i], ZR_TEXT_LEFT)) selected_item = i; zr_combo_end(ctx); } @@ -1721,8 +1380,7 @@ grid_demo(struct zr_context *ctx) static void ui_header(struct zr_context *ctx, const char *title) { - zr_reset_font_height(ctx); - zr_push_font_height(ctx, 18); + ctx->style.font.height = 18; zr_layout_row_dynamic(ctx, 20, 1); zr_label(ctx, title, ZR_TEXT_LEFT); } @@ -1731,8 +1389,7 @@ static void ui_widget(struct zr_context *ctx, float height, float font_height) { static const float ratio[] = {0.15f, 0.85f}; - zr_reset_font_height(ctx); - zr_push_font_height(ctx, font_height); + ctx->style.font.height = font_height; zr_layout_row(ctx, ZR_DYNAMIC, height, 2, ratio); zr_spacing(ctx, 1); } @@ -1741,8 +1398,7 @@ static void ui_widget_centered(struct zr_context *ctx, float height, float font_height) { static const float ratio[] = {0.15f, 0.50f, 0.35f}; - zr_reset_font_height(ctx); - zr_push_font_height(ctx, font_height); + ctx->style.font.height = font_height; zr_layout_row(ctx, ZR_DYNAMIC, height, 3, ratio); zr_spacing(ctx, 1); } @@ -1768,15 +1424,15 @@ button_demo(struct zr_context *ctx, struct icons *img) { /* toolbar */ zr_layout_row_static(ctx, 40, 40, 4); - if (zr_menu_icon_begin(ctx, &menu, "Music", img->play, 120)) + if (zr_menu_begin_image(ctx, &menu, "Music", img->play, 120)) { /* settings */ zr_layout_row_dynamic(ctx, 25, 1); - zr_menu_item_icon(ctx, img->play, "Play", ZR_TEXT_RIGHT); - zr_menu_item_icon(ctx, img->stop, "Stop", ZR_TEXT_RIGHT); - zr_menu_item_icon(ctx, img->pause, "Pause", ZR_TEXT_RIGHT); - zr_menu_item_icon(ctx, img->next, "Next", ZR_TEXT_RIGHT); - zr_menu_item_icon(ctx, img->prev, "Prev", ZR_TEXT_RIGHT); + zr_menu_item_image_label(ctx, img->play, "Play", ZR_TEXT_RIGHT); + zr_menu_item_image_label(ctx, img->stop, "Stop", ZR_TEXT_RIGHT); + zr_menu_item_image_label(ctx, img->pause, "Pause", ZR_TEXT_RIGHT); + zr_menu_item_image_label(ctx, img->next, "Next", ZR_TEXT_RIGHT); + zr_menu_item_image_label(ctx, img->prev, "Prev", ZR_TEXT_RIGHT); zr_menu_end(ctx); } zr_button_image(ctx, img->tools, ZR_BUTTON_DEFAULT); @@ -1790,10 +1446,10 @@ button_demo(struct zr_context *ctx, struct icons *img) *------------------------------------------------*/ ui_header(ctx, "Push buttons"); ui_widget(ctx, 35, 22); - if (zr_button_text(ctx, "Push me", ZR_BUTTON_DEFAULT)) + if (zr_button_label(ctx, "Push me", ZR_BUTTON_DEFAULT)) fprintf(stdout, "pushed!\n"); ui_widget(ctx, 35, 22); - if (zr_button_text_image(ctx, img->rocket, "Styled", ZR_TEXT_CENTERED, ZR_BUTTON_DEFAULT)) + if (zr_button_image_label(ctx, img->rocket, "Styled", ZR_TEXT_CENTERED, ZR_BUTTON_DEFAULT)) fprintf(stdout, "rocket!\n"); /*------------------------------------------------ @@ -1801,7 +1457,7 @@ button_demo(struct zr_context *ctx, struct icons *img) *------------------------------------------------*/ ui_header(ctx, "Repeater"); ui_widget(ctx, 35, 22); - if (zr_button_text(ctx, "Press me", ZR_BUTTON_REPEATER)) + if (zr_button_label(ctx, "Press me", ZR_BUTTON_REPEATER)) fprintf(stdout, "pressed!\n"); /*------------------------------------------------ @@ -1809,15 +1465,15 @@ button_demo(struct zr_context *ctx, struct icons *img) *------------------------------------------------*/ ui_header(ctx, "Toggle buttons"); ui_widget(ctx, 35, 22); - if (zr_button_text_image(ctx, (toggle0) ? img->checked: img->unchecked, + if (zr_button_image_label(ctx, (toggle0) ? img->checked: img->unchecked, "Toggle", ZR_TEXT_LEFT, ZR_BUTTON_DEFAULT)) toggle0 = !toggle0; ui_widget(ctx, 35, 22); - if (zr_button_text_image(ctx, (toggle1) ? img->checked: img->unchecked, + if (zr_button_image_label(ctx, (toggle1) ? img->checked: img->unchecked, "Toggle", ZR_TEXT_LEFT, ZR_BUTTON_DEFAULT)) toggle1 = !toggle1; ui_widget(ctx, 35, 22); - if (zr_button_text_image(ctx, (toggle2) ? img->checked: img->unchecked, + if (zr_button_image_label(ctx, (toggle2) ? img->checked: img->unchecked, "Toggle", ZR_TEXT_LEFT, ZR_BUTTON_DEFAULT)) toggle2 = !toggle2; /*------------------------------------------------ @@ -1825,13 +1481,13 @@ button_demo(struct zr_context *ctx, struct icons *img) *------------------------------------------------*/ ui_header(ctx, "Radio buttons"); ui_widget(ctx, 35, 22); - if (zr_button_text_symbol(ctx, (option == 0)?ZR_SYMBOL_CIRCLE_FILLED:ZR_SYMBOL_CIRCLE, + if (zr_button_symbol_label(ctx, (option == 0)?ZR_SYMBOL_CIRCLE_FILLED:ZR_SYMBOL_CIRCLE, "Select", ZR_TEXT_LEFT, ZR_BUTTON_DEFAULT)) option = 0; ui_widget(ctx, 35, 22); - if (zr_button_text_symbol(ctx, (option == 1)?ZR_SYMBOL_CIRCLE_FILLED:ZR_SYMBOL_CIRCLE, + if (zr_button_symbol_label(ctx, (option == 1)?ZR_SYMBOL_CIRCLE_FILLED:ZR_SYMBOL_CIRCLE, "Select", ZR_TEXT_LEFT, ZR_BUTTON_DEFAULT)) option = 1; ui_widget(ctx, 35, 22); - if (zr_button_text_symbol(ctx, (option == 2)?ZR_SYMBOL_CIRCLE_FILLED:ZR_SYMBOL_CIRCLE, + if (zr_button_symbol_label(ctx, (option == 2)?ZR_SYMBOL_CIRCLE_FILLED:ZR_SYMBOL_CIRCLE, "Select", ZR_TEXT_LEFT, ZR_BUTTON_DEFAULT)) option = 2; /*------------------------------------------------ @@ -1840,13 +1496,13 @@ button_demo(struct zr_context *ctx, struct icons *img) if (zr_contextual_begin(ctx, &menu, ZR_WINDOW_NO_SCROLLBAR, zr_vec2(120, 200), zr_window_get_bounds(ctx))) { ctx->style.font.height = 18; zr_layout_row_dynamic(ctx, 25, 1); - if (zr_contextual_item_icon(ctx, img->copy, "Clone", ZR_TEXT_RIGHT)) + if (zr_contextual_item_image_label(ctx, img->copy, "Clone", ZR_TEXT_RIGHT)) fprintf(stdout, "pressed clone!\n"); - if (zr_contextual_item_icon(ctx, img->del, "Delete", ZR_TEXT_RIGHT)) + if (zr_contextual_item_image_label(ctx, img->del, "Delete", ZR_TEXT_RIGHT)) fprintf(stdout, "pressed delete!\n"); - if (zr_contextual_item_icon(ctx, img->convert, "Convert", ZR_TEXT_RIGHT)) + if (zr_contextual_item_image_label(ctx, img->convert, "Convert", ZR_TEXT_RIGHT)) fprintf(stdout, "pressed convert!\n"); - if (zr_contextual_item_icon(ctx, img->edit, "Edit", ZR_TEXT_RIGHT)) + if (zr_contextual_item_image_label(ctx, img->edit, "Edit", ZR_TEXT_RIGHT)) fprintf(stdout, "pressed edit!\n"); zr_contextual_end(ctx); } @@ -1872,6 +1528,7 @@ basic_demo(struct zr_context *ctx, struct icons *img) static int selected_icon = 0; static const char *items[] = {"Item 0","item 1","item 2"}; static int piemenu_active = 0; + static struct zr_vec2 piemenu_pos; int i = 0; struct zr_panel layout; @@ -1885,7 +1542,7 @@ basic_demo(struct zr_context *ctx, struct icons *img) *------------------------------------------------*/ ui_header(ctx, "Popup & Scrollbar & Images"); ui_widget(ctx, 35, 22); - if (zr_button_text_image(ctx, img->dir, + if (zr_button_image_label(ctx, img->dir, "Images", ZR_TEXT_CENTERED, ZR_BUTTON_DEFAULT)) image_active = !image_active; @@ -1918,19 +1575,19 @@ basic_demo(struct zr_context *ctx, struct icons *img) *------------------------------------------------*/ ui_header(ctx, "Combo box"); ui_widget(ctx, 40, 22); - if (zr_combo_begin_text(ctx, &combo, items[selected_item], 200)) { + if (zr_combo_begin_label(ctx, &combo, items[selected_item], 200)) { zr_layout_row_dynamic(ctx, 35, 1); for (i = 0; i < 3; ++i) - if (zr_combo_item(ctx, items[i], ZR_TEXT_LEFT)) + if (zr_combo_item_label(ctx, items[i], ZR_TEXT_LEFT)) selected_item = i; zr_combo_end(ctx); } ui_widget(ctx, 40, 22); - if (zr_combo_begin_icon(ctx, &combo, items[selected_icon], img->images[selected_icon], 200)) { + if (zr_combo_begin_image_label(ctx, &combo, items[selected_icon], img->images[selected_icon], 200)) { zr_layout_row_dynamic(ctx, 35, 1); for (i = 0; i < 3; ++i) - if (zr_combo_item_icon(ctx, img->images[i], items[i], ZR_TEXT_RIGHT)) + if (zr_combo_item_image_label(ctx, img->images[i], items[i], ZR_TEXT_RIGHT)) selected_icon = i; zr_combo_end(ctx); } @@ -1940,9 +1597,9 @@ basic_demo(struct zr_context *ctx, struct icons *img) *------------------------------------------------*/ ui_header(ctx, "Checkbox"); ui_widget(ctx, 30, 22); - zr_checkbox(ctx, "Flag 1", &check0); + zr_checkbox_label(ctx, "Flag 1", &check0); ui_widget(ctx, 30, 22); - zr_checkbox(ctx, "Flag 2", &check1); + zr_checkbox_label(ctx, "Flag 2", &check1); /*------------------------------------------------ * PROGRESSBAR @@ -1961,12 +1618,14 @@ basic_demo(struct zr_context *ctx, struct icons *img) /*------------------------------------------------ * PIEMENU *------------------------------------------------*/ - if (zr_input_is_mouse_down(&ctx->input, ZR_BUTTON_RIGHT) && - zr_input_is_mouse_hovering_rect(&ctx->input, layout.bounds)) + if (zr_input_is_mouse_click_down_in_rect(&ctx->input, ZR_BUTTON_RIGHT, + layout.bounds,zr_true)){ + piemenu_pos = ctx->input.mouse.pos; piemenu_active = 1; + } if (piemenu_active) { - int ret = ui_piemenu(ctx, zr_vec2(WINDOW_WIDTH/2-140, WINDOW_HEIGHT/2-140), 140, &img->menu[0], 6); + int ret = ui_piemenu(ctx, piemenu_pos, 140, &img->menu[0], 6); if (ret != -1) { fprintf(stdout, "piemenu selected: %d\n", ret); piemenu_active = 0; @@ -2303,11 +1962,10 @@ file_browser_run(struct file_browser *browser, struct zr_context *ctx) char *d = browser->directory; char *begin = d + 1; zr_layout_row_dynamic(ctx, 25, 6); - zr_push_property(ctx, ZR_PROPERTY_ITEM_SPACING, zr_vec2(0, 0)); while (*d++) { if (*d == '/') { *d = '\0'; - if (zr_button_text(ctx, begin, ZR_BUTTON_DEFAULT)) { + if (zr_button_label(ctx, begin, ZR_BUTTON_DEFAULT)) { *d++ = '/'; *d = '\0'; file_browser_reload_directory_content(browser, browser->directory); break; @@ -2316,7 +1974,6 @@ file_browser_run(struct file_browser *browser, struct zr_context *ctx) begin = d + 1; } } - zr_pop_property(ctx); } zr_menubar_end(ctx); @@ -2330,14 +1987,12 @@ file_browser_run(struct file_browser *browser, struct zr_context *ctx) struct zr_image computer = icons->computer; zr_layout_row_dynamic(ctx, 40, 1); - zr_push_property(ctx, ZR_PROPERTY_ITEM_SPACING, zr_vec2(0, 0)); - if (zr_button_text_image(ctx, home, "home", ZR_TEXT_CENTERED, ZR_BUTTON_DEFAULT)) + if (zr_button_image_label(ctx, home, "home", ZR_TEXT_CENTERED, ZR_BUTTON_DEFAULT)) file_browser_reload_directory_content(browser, browser->home); - if (zr_button_text_image(ctx,desktop,"desktop",ZR_TEXT_CENTERED, ZR_BUTTON_DEFAULT)) + if (zr_button_image_label(ctx,desktop,"desktop",ZR_TEXT_CENTERED, ZR_BUTTON_DEFAULT)) file_browser_reload_directory_content(browser, browser->desktop); - if (zr_button_text_image(ctx,computer,"computer",ZR_TEXT_CENTERED,ZR_BUTTON_DEFAULT)) + if (zr_button_image_label(ctx,computer,"computer",ZR_TEXT_CENTERED,ZR_BUTTON_DEFAULT)) file_browser_reload_directory_content(browser, "/"); - zr_pop_property(ctx); zr_group_end(ctx); } @@ -2568,9 +2223,9 @@ node_editor_demo(struct zr_context *ctx, struct node_editor *nodedit) const float grid_size = 32.0f; const struct zr_color grid_color = zr_rgb(50, 50, 50); for (x = (float)fmod(size.x - nodedit->scrolling.x, grid_size); x < size.w; x += grid_size) - zr_draw_line(canvas, x+size.x, size.y, x+size.x, size.y+size.h, grid_color); + zr_stroke_line(canvas, x+size.x, size.y, x+size.x, size.y+size.h, 1.0f, grid_color); for (y = (float)fmod(size.y - nodedit->scrolling.y, grid_size); y < size.h; y += grid_size) - zr_draw_line(canvas, size.x, y+size.y, size.x+size.w, y+size.y, grid_color); + zr_stroke_line(canvas, size.x, y+size.y, size.x+size.w, y+size.y, 1.0f, grid_color); } /* execute each node as a moveable group */ @@ -2617,7 +2272,7 @@ node_editor_demo(struct zr_context *ctx, struct node_editor *nodedit) circle.x = node.bounds.x + node.bounds.w-4; circle.y = node.bounds.y + space * (float)(n+1); circle.w = 8; circle.h = 8; - zr_draw_circle(canvas, ZR_FILLED, circle, zr_rgb(100, 100, 100)); + zr_fill_circle(canvas, circle, zr_rgb(100, 100, 100)); /* start linking process */ if (zr_input_has_mouse_click_down_in_rect(in, ZR_BUTTON_LEFT, circle, zr_true)) { @@ -2632,8 +2287,8 @@ node_editor_demo(struct zr_context *ctx, struct node_editor *nodedit) nodedit->linking.input_slot == n) { struct zr_vec2 l0 = zr_vec2(circle.x + 3, circle.y + 3); struct zr_vec2 l1 = in->mouse.pos; - zr_draw_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y, - l1.x - 50.0f, l1.y, l1.x, l1.y, zr_rgb(100, 100, 100)); + zr_stroke_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y, + l1.x - 50.0f, l1.y, l1.x, l1.y, 1.0f, zr_rgb(100, 100, 100)); } } @@ -2644,7 +2299,7 @@ node_editor_demo(struct zr_context *ctx, struct node_editor *nodedit) circle.x = node.bounds.x-4; circle.y = node.bounds.y + space * (float)(n+1); circle.w = 8; circle.h = 8; - zr_draw_circle(canvas, ZR_FILLED, circle, zr_rgb(100, 100, 100)); + zr_fill_circle(canvas, circle, zr_rgb(100, 100, 100)); if (zr_input_is_mouse_released(in, ZR_BUTTON_LEFT) && zr_input_is_mouse_hovering_rect(in, circle) && nodedit->linking.active && nodedit->linking.node != it) { @@ -2680,8 +2335,8 @@ node_editor_demo(struct zr_context *ctx, struct node_editor *nodedit) l0.y -= nodedit->scrolling.y; l1.x -= nodedit->scrolling.x; l1.y -= nodedit->scrolling.y; - zr_draw_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y, - l1.x - 50.0f, l1.y, l1.x, l1.y, zr_rgb(100, 100, 100)); + zr_stroke_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y, + l1.x - 50.0f, l1.y, l1.x, l1.y, 1.0f, zr_rgb(100, 100, 100)); } if (updated) { @@ -2709,10 +2364,10 @@ node_editor_demo(struct zr_context *ctx, struct node_editor *nodedit) if (zr_contextual_begin(ctx, &menu, 0, zr_vec2(100, 220), zr_window_get_bounds(ctx))) { const char *grid_option[] = {"Show Grid", "Hide Grid"}; zr_layout_row_dynamic(ctx, 25, 1); - if (zr_contextual_item(ctx, "New", ZR_TEXT_CENTERED)) + if (zr_contextual_item_label(ctx, "New", ZR_TEXT_CENTERED)) node_editor_add(nodedit, "New", zr_rect(400, 260, 180, 220), zr_rgb(255, 255, 255), 1, 2); - if (zr_contextual_item(ctx, grid_option[nodedit->show_grid],ZR_TEXT_CENTERED)) + if (zr_contextual_item_label(ctx, grid_option[nodedit->show_grid],ZR_TEXT_CENTERED)) nodedit->show_grid = !nodedit->show_grid; zr_contextual_end(ctx); } @@ -2743,6 +2398,67 @@ node_editor_init(struct node_editor *editor) editor->show_grid = zr_true; } +/* =============================================================== + * + * CONTROL WINDOW + * + * ===============================================================*/ +static int +control_window(struct zr_context *ctx, struct demo *gui) +{ + struct zr_panel layout; + if (zr_begin(ctx, &layout, "Control", zr_rect(0, 0, 350, 520), + ZR_WINDOW_CLOSABLE|ZR_WINDOW_MINIMIZABLE|ZR_WINDOW_MOVABLE| + ZR_WINDOW_SCALABLE|ZR_WINDOW_BORDER)) + { + if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Windows", ZR_MINIMIZED)) { + zr_layout_row_dynamic(ctx, 25, 2); + gui->show_simple = !zr_window_is_closed(ctx, "Show"); + gui->show_node = !zr_window_is_closed(ctx, "Node Editor"); + gui->show_demo = !zr_window_is_closed(ctx, "Demo"); +#ifndef DEMO_DO_NOT_DRAW_IMAGES + gui->show_filex = !zr_window_is_closed(ctx, "File Browser"); + gui->show_grid = !zr_window_is_closed(ctx, "Grid Demo"); + gui->show_basic = !zr_window_is_closed(ctx, "Basic Demo"); + gui->show_button = !zr_window_is_closed(ctx, "Button Demo"); +#endif + + if (zr_checkbox_label(ctx, "Show", &gui->show_simple) && !gui->show_simple) + zr_window_close(ctx, "Show"); + if (zr_checkbox_label(ctx, "Demo", &gui->show_demo) && !gui->show_demo) + zr_window_close(ctx, "Demo"); + if (zr_checkbox_label(ctx, "Node Editor", &gui->show_node) && !gui->show_node) + zr_window_close(ctx, "Node Editor"); +#ifndef DEMO_DO_NOT_DRAW_IMAGES + if (zr_checkbox_label(ctx, "Grid", &gui->show_grid) && !gui->show_grid) + zr_window_close(ctx, "Grid Demo"); + if (zr_checkbox_label(ctx, "Basic", &gui->show_basic) && !gui->show_basic) + zr_window_close(ctx, "Basic Demo"); + if (zr_checkbox_label(ctx, "Button", &gui->show_button) && !gui->show_button) + zr_window_close(ctx, "Button Demo"); + if (zr_checkbox_label(ctx, "Filex", &gui->show_filex) && !gui->show_filex) + zr_window_close(ctx, "File Browser"); +#endif + zr_layout_pop(ctx); + } + if (zr_layout_push(ctx, ZR_LAYOUT_TAB, "Metrics", ZR_MINIMIZED)) { + zr_layout_row_dynamic(ctx, 20, 2); + zr_label(ctx,"Total:", ZR_TEXT_LEFT); + zr_labelf(ctx, ZR_TEXT_LEFT, "%lu", gui->status.size); + zr_label(ctx,"Used:", ZR_TEXT_LEFT); + zr_labelf(ctx, ZR_TEXT_LEFT, "%lu", gui->status.allocated); + zr_label(ctx,"Required:", ZR_TEXT_LEFT); + zr_labelf(ctx, ZR_TEXT_LEFT, "%lu", gui->status.needed); + zr_label(ctx,"Calls:", ZR_TEXT_LEFT); + zr_labelf(ctx, ZR_TEXT_LEFT, "%lu", gui->status.calls); + zr_layout_pop(ctx); + } + } + zr_end(ctx); + return !zr_window_is_closed(ctx, "Control"); +} + + /* =============================================================== * * DEMO ENTRY @@ -2756,8 +2472,10 @@ run_demo(struct demo *gui) static struct node_editor nodedit; static struct file_browser filex; struct zr_context *ctx = &gui->ctx; + struct zr_style *style = &ctx->style; if (!init) { + init = 1; gui->show_demo = 0; gui->show_node = 0; gui->show_simple = 0; @@ -2773,9 +2491,86 @@ run_demo(struct demo *gui) file_browser_init(&filex, &gui->icons); #endif #endif - init = 1; + +#if 0 + style->text.color = zr_rgb(255,255,255); + style->text.padding = zr_vec2(0,0); + + style->option.normal = zr_style_item_image(gui->icons.option); + style->option.hover = zr_style_item_image(gui->icons.option); + style->option.active = zr_style_item_image(gui->icons.option); + style->option.cursor_normal = zr_style_item_image(gui->icons.dot); + style->option.cursor_hover = zr_style_item_image(gui->icons.dot); + style->option.text_background = zr_rgba(0,0,0,0); + style->option.text_normal = zr_rgb(18,34,39); + style->option.text_hover = zr_rgb(18,34,39); + style->option.text_active = zr_rgb(18,34,39); + + style->checkbox.normal = zr_style_item_image(gui->icons.checkbox); + style->checkbox.hover = zr_style_item_image(gui->icons.checkbox); + style->checkbox.active = zr_style_item_image(gui->icons.checkbox); + style->checkbox.cursor_normal = zr_style_item_image(gui->icons.check); + style->checkbox.cursor_hover = zr_style_item_image(gui->icons.check); + style->checkbox.text_background = zr_rgba(0,0,0,0); + style->checkbox.text_normal = zr_rgb(255,255,255); + style->checkbox.text_hover = zr_rgb(255,255,255); + style->checkbox.text_active = zr_rgb(255,255,255); + + style->progress.normal = zr_style_item_image(gui->icons.progress); + style->progress.hover = zr_style_item_image(gui->icons.progress); + style->progress.active = zr_style_item_image(gui->icons.progress); + style->progress.cursor_normal = zr_style_item_image(gui->icons.bar); + style->progress.cursor_hover = zr_style_item_image(gui->icons.bar); + style->progress.cursor_active = zr_style_item_image(gui->icons.bar); + style->progress.padding = zr_vec2(10,10); + + /* slider */ + style->slider.normal = zr_style_item_image(gui->icons.slider); + style->slider.hover = zr_style_item_image(gui->icons.slider); + style->slider.active = zr_style_item_image(gui->icons.slider); + style->slider.bar_normal = zr_rgba(0,0,0,0); + style->slider.bar_hover = zr_rgba(0,0,0,0); + style->slider.bar_active = zr_rgba(0,0,0,0); + style->slider.bar_filled = zr_rgba(0,0,0,0); + style->slider.cursor_normal = zr_style_item_image(gui->icons.cursor); + style->slider.cursor_hover = zr_style_item_image(gui->icons.cursor); + style->slider.cursor_active = zr_style_item_image(gui->icons.cursor);; + style->slider.inc_symbol = ZR_SYMBOL_NONE; + style->slider.dec_symbol = ZR_SYMBOL_NONE; + style->slider.cursor_size = zr_vec2(30,30); + style->slider.spacing = zr_vec2(16, 0); + style->slider.show_buttons = zr_true; + style->slider.bar_height = 0; + + /* slider buttons */ + style->slider.inc_button.normal = zr_style_item_image(gui->icons.right); + style->slider.inc_button.hover = zr_style_item_image(gui->icons.right); + style->slider.inc_button.active = zr_style_item_image(gui->icons.right); + style->slider.inc_button.padding = zr_vec2(0.0f,0.0f); + + style->slider.dec_button.normal = zr_style_item_image(gui->icons.left); + style->slider.dec_button.hover = zr_style_item_image(gui->icons.left); + style->slider.dec_button.active = zr_style_item_image(gui->icons.left); + style->slider.dec_button.padding = zr_vec2(0.0f,0.0f); + + /* window */ + style->window.header.normal = zr_style_item_image(gui->icons.header); + style->window.header.hover = zr_style_item_image(gui->icons.header); + style->window.header.active = zr_style_item_image(gui->icons.header); + style->window.header.label_normal = zr_rgb(73,40,17); + style->window.header.label_hover = zr_rgb(73,40,17); + style->window.header.label_active = zr_rgb(73,40,17); + style->window.header.label_padding = zr_vec2(4,8); + style->window.header.padding = zr_vec2(60,10); + + style->window.background = zr_rgb(18,39,34); + style->window.fixed_background = zr_style_item_image(gui->icons.window); + style->window.border_color = zr_rgba(104,120,115,255); + style->window.padding = zr_vec2(16,8); +#endif } + ctx->style.font.height = 14; ret = control_window(ctx, gui); if (gui->show_demo) demo_window(gui, ctx); diff --git a/demo/glfw/glfw.c b/demo/glfw/glfw.c index 7bf0a73..f7d3a8e 100644 --- a/demo/glfw/glfw.c +++ b/demo/glfw/glfw.c @@ -396,7 +396,8 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height, config.shape_AA = AA; config.line_AA = AA; config.circle_segment_count = 22; - config.line_thickness = 1.0f; + config.curve_segment_count = 22; + config.arc_segment_count = 22; config.null = dev->null; /* setup buffers to load vertices and elements */ diff --git a/demo/linuxgl/linuxgl.c b/demo/linuxgl/linuxgl.c index 3ab7bf1..ec90550 100644 --- a/demo/linuxgl/linuxgl.c +++ b/demo/linuxgl/linuxgl.c @@ -569,7 +569,8 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height, config.shape_AA = AA; config.line_AA = AA; config.circle_segment_count = 22; - config.line_thickness = 1.0f; + config.arc_segment_count = 22; + config.curve_segment_count = 22; config.null = dev->null; /* setup buffers to load vertices and elements */ diff --git a/demo/sdl/sdl.c b/demo/sdl/sdl.c index 8db7664..56b0d22 100644 --- a/demo/sdl/sdl.c +++ b/demo/sdl/sdl.c @@ -122,8 +122,6 @@ icon_load(const char *filename) glBindTexture(GL_TEXTURE_2D, tex); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glGenerateMipmap(GL_TEXTURE_2D); stbi_image_free(data); @@ -363,7 +361,6 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height, glUseProgram(dev->prog); glUniform1i(dev->uniform_tex, 0); glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); - { /* convert from command queue into draw list and draw to screen */ const struct zr_draw_command *cmd; @@ -387,12 +384,13 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height, /* fill converting configuration */ struct zr_convert_config config; memset(&config, 0, sizeof(config)); + config.circle_segment_count = 22; + config.arc_segment_count = 22; + config.curve_segment_count = 22; config.global_alpha = 1.0f; + config.null = dev->null; config.shape_AA = AA; config.line_AA = AA; - config.circle_segment_count = 22; - config.line_thickness = 1.0f; - config.null = dev->null; /* setup buffers to load vertices and elements */ zr_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY); @@ -414,7 +412,6 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height, } zr_clear(ctx); } - /* restore old state */ glUseProgram((GLuint)last_prog); glBindTexture(GL_TEXTURE_2D, (GLuint)last_tex); @@ -422,6 +419,7 @@ device_draw(struct device *dev, struct zr_context *ctx, int width, int height, glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)last_ebo); glBindVertexArray((GLuint)last_vao); glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); } static void diff --git a/demo/x11/xlib.c b/demo/x11/xlib.c index 7b984c5..88a9d26 100644 --- a/demo/x11/xlib.c +++ b/demo/x11/xlib.c @@ -40,50 +40,6 @@ #define DEMO_DO_NOT_USE_COLOR_PICKER #include "../demo.c" -#if 0 - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wsign-conversion" -#pragma clang diagnostic ignored "-Wfloat-equal" -#pragma clang diagnostic ignored "-Wbad-function-cast" -#pragma clang diagnostic ignored "-Wcast-qual" -#pragma clang diagnostic ignored "-Wshadow" -#pragma clang diagnostic ignored "-Wmissing-field-initializers" -#pragma clang diagnostic ignored "-Wdeclaration-after-statement" -#pragma clang diagnostic ignored "-Wunused-function" -#pragma clang diagnostic ignored "-Wdisabled-macro-expansion" -#elif defined(__GNUC__) || defined(__GNUG__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wfloat-equal" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wbad-function-cast" -#pragma GCC diagnostic ignored "-Wcast-qual" -#pragma GCC diagnostic ignored "-Wshadow" -#pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#pragma GCC diagnostic ignored "-Wdeclaration-after-statement" -#pragma GCC diagnostic ignored "-Wtype-limits" -#pragma GCC diagnostic ignored "-Wswitch-default" -#pragma GCC diagnostic ignored "-Wunused-function" -#elif _MSC_VER -#pragma warning (push) -#pragma warning (disable: 4456) -#endif - -#define STB_IMAGE_IMPLEMENTATION -#include "../stb_image.h" - -#ifdef __clang__ -#pragma clang diagnostic pop -#elif defined(__GNUC__) || defined(__GNUG__) -#pragma GCC diagnostic pop -#elif _MSC_VER -#pragma warning (pop) -#endif - -#endif - typedef struct XFont XFont; typedef struct XSurface XSurface; typedef struct XWindow XWindow; @@ -275,17 +231,51 @@ surface_scissor(XSurface *surf, float x, float y, float w, float h) } static void -surface_draw_line(XSurface *surf, int16_t x0, int16_t y0, int16_t x1, - int16_t y1, struct zr_color col) +surface_stroke_line(XSurface *surf, short x0, short y0, short x1, + short y1, unsigned int line_thickness, struct zr_color col) { unsigned long c = color_from_byte(&col.r); XSetForeground(surf->dpy, surf->gc, c); + XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); XDrawLine(surf->dpy, surf->drawable, surf->gc, (int)x0, (int)y0, (int)x1, (int)y1); + XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); } static void -surface_draw_rect(XSurface* surf, int16_t x, int16_t y, uint16_t w, - uint16_t h, uint16_t r, struct zr_color col) +surface_stroke_rect(XSurface* surf, short x, short y, unsigned short w, + unsigned short h, unsigned short r, unsigned short line_thickness, struct zr_color col) +{ + unsigned long c = color_from_byte(&col.r); + XSetForeground(surf->dpy, surf->gc, c); + XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); + if (r == 0) { + XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h); + } else { + short xc = x + r; + short yc = y + r; + short wc = (short)(w - 2 * r); + short hc = (short)(h - 2 * r); + + XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y, xc+wc, y); + XDrawLine(surf->dpy, surf->drawable, surf->gc, x+w, yc, x+w, yc+wc); + XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y+h, xc+wc, y+h); + XDrawLine(surf->dpy, surf->drawable, surf->gc, x, yc, yc+hc, x); + + XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, y, + (unsigned)r*2, (unsigned)r*2, 0 * 64, 90 * 64); + XFillArc(surf->dpy, surf->drawable, surf->gc, x, y, + (unsigned)r*2, (unsigned)r*2, 90 * 64, 90 * 64); + XFillArc(surf->dpy, surf->drawable, surf->gc, x, yc + hc - r, + (unsigned)r*2, (unsigned)2*r, 180 * 64, 90 * 64); + XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, yc + hc - r, + (unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64); + } + XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); +} + +static void +surface_fill_rect(XSurface* surf, short x, short y, unsigned short w, + unsigned short h, unsigned short r, struct zr_color col) { unsigned long c = color_from_byte(&col.r); XSetForeground(surf->dpy, surf->gc, c); @@ -339,8 +329,8 @@ surface_draw_rect(XSurface* surf, int16_t x, int16_t y, uint16_t w, } static void -surface_draw_triangle(XSurface *surf, int16_t x0, int16_t y0, int16_t x1, - int16_t y1, int16_t x2, int16_t y2, struct zr_color col) +surface_fill_triangle(XSurface *surf, short x0, short y0, short x1, + short y1, short x2, short y2, struct zr_color col) { XPoint pnts[3]; unsigned long c = color_from_byte(&col.r); @@ -355,43 +345,65 @@ surface_draw_triangle(XSurface *surf, int16_t x0, int16_t y0, int16_t x1, } static void -surface_draw_polygon(XSurface *surf, enum zr_command_drawing_mode type, - const struct zr_vec2i *pnts, int count, struct zr_color col) +surface_stroke_triangle(XSurface *surf, short x0, short y0, short x1, + short y1, short x2, short y2, unsigned short line_thickness, struct zr_color col) +{ + XPoint pnts[3]; + unsigned long c = color_from_byte(&col.r); + XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); + XDrawLine(surf->dpy, surf->drawable, surf->gc, x0, y0, x1, y1); + XDrawLine(surf->dpy, surf->drawable, surf->gc, x1, y1, x2, y2); + XDrawLine(surf->dpy, surf->drawable, surf->gc, x2, y2, x0, y0); + XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); +} + +static void +surface_fill_polygon(XSurface *surf, const struct zr_vec2i *pnts, int count, + struct zr_color col) +{ + int i = 0; + #define MAX_POINTS 64 + XPoint xpnts[MAX_POINTS]; + unsigned long c = color_from_byte(&col.r); + XSetForeground(surf->dpy, surf->gc, c); + for (i = 0; i < count && i < MAX_POINTS; ++i) { + xpnts[i].x = pnts[i].x; + xpnts[i].y = pnts[i].y; + } + XFillPolygon(surf->dpy, surf->drawable, surf->gc, xpnts, count, Convex, CoordModeOrigin); + #undef MAX_POINTS +} + +static void +surface_stroke_polygon(XSurface *surf, const struct zr_vec2i *pnts, int count, + unsigned short line_thickness, struct zr_color col) { int i = 0; unsigned long c = color_from_byte(&col.r); XSetForeground(surf->dpy, surf->gc, c); - if (type == ZR_FILLED) { - #define MAX_POINTS 64 - XPoint xpnts[MAX_POINTS]; - - for (i = 0; i < count && i < MAX_POINTS; ++i) { - xpnts[i].x = pnts[i].x; - xpnts[i].y = pnts[i].y; - } - XFillPolygon(surf->dpy, surf->drawable, surf->gc, xpnts, count, Convex, CoordModeOrigin); - #undef MAX_POINTS - } else { - for (i = 1; i < count; ++i) - XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y); - XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y); - } + XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); + for (i = 1; i < count; ++i) + XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y); + XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y); + XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); } static void -surface_draw_polyline(XSurface *surf, - const struct zr_vec2i *pnts, int count, struct zr_color col) +surface_stroke_polyline(XSurface *surf, const struct zr_vec2i *pnts, + int count, unsigned short line_thickness, struct zr_color col) { int i = 0; unsigned long c = color_from_byte(&col.r); + XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); XSetForeground(surf->dpy, surf->gc, c); for (i = 0; i < count-1; ++i) XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i].x, pnts[i].y, pnts[i+1].x, pnts[i+1].y); + XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); } static void -surface_draw_circle(XSurface *surf, int16_t x, int16_t y, uint16_t w, - uint16_t h, struct zr_color col) +surface_fill_circle(XSurface *surf, short x, short y, unsigned short w, + unsigned short h, struct zr_color col) { unsigned long c = color_from_byte(&col.r); XSetForeground(surf->dpy, surf->gc, c); @@ -400,14 +412,27 @@ surface_draw_circle(XSurface *surf, int16_t x, int16_t y, uint16_t w, } static void -surface_draw_curve(XSurface *surf, struct zr_vec2i p1, +surface_stroke_circle(XSurface *surf, short x, short y, unsigned short w, + unsigned short h, unsigned short line_thickness, struct zr_color col) +{ + unsigned long c = color_from_byte(&col.r); + XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); + XSetForeground(surf->dpy, surf->gc, c); + XDrawArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, + (unsigned)w, (unsigned)h, 0, 360 * 64); + XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); +} + +static void +surface_stroke_curve(XSurface *surf, struct zr_vec2i p1, struct zr_vec2i p2, struct zr_vec2i p3, struct zr_vec2i p4, - unsigned int num_segments, struct zr_color col) + unsigned int num_segments, unsigned short line_thickness, struct zr_color col) { unsigned int i_step; float t_step; struct zr_vec2i last = p1; + XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); num_segments = MAX(num_segments, 1); t_step = 1.0f/(float)num_segments; for (i_step = 1; i_step <= num_segments; ++i_step) { @@ -419,13 +444,14 @@ surface_draw_curve(XSurface *surf, struct zr_vec2i p1, float w4 = t * t *t; float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; - surface_draw_line(surf, last.x, last.y, (short)x, (short)y, col); + surface_stroke_line(surf, last.x, last.y, (short)x, (short)y, line_thickness,col); last.x = (short)x; last.y = (short)y; } + XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); } static void -surface_draw_text(XSurface *surf, int16_t x, int16_t y, uint16_t w, uint16_t h, +surface_draw_text(XSurface *surf, short x, short y, unsigned short w, unsigned short h, const char *text, size_t len, XFont *font, struct zr_color cbg, struct zr_color cfg) { int tx, ty, th; @@ -523,39 +549,6 @@ surface_del(XSurface *surf) free(surf); } -#if 0 -static XSurface* -surface_load(const char *filename, Display *dpy, int screen, Window root) -{ - GC gc; - int x,y,n; - XSurface *surf; - XImage *xim; - XGCValues gcvalues; - - unsigned char *data = stbi_load(filename, &x, &y, &n, 0); - if (!data) die("[XLIB]: failed to load image: %s", filename); - surf = surface_create(dpy, screen, root, (unsigned int)x, (unsigned int)y); - xim = XCreateImage(dpy, CopyFromParent, 32, ZPixmap, 0, (char*)data, - (unsigned int)x, (unsigned int)y, 32, 0); - if (!xim) die("[XLIB]: failed to create image from file: %s", filename); - - gc = XCreateGC(dpy, surf->drawable, 0, &gcvalues); - XPutImage(dpy, surf->drawable, gc, xim, 0, 0, 0, 0, - (unsigned int)x, (unsigned int)y); - XDestroyImage(xim); - return surf; -} - -static struct zr_image -icon_load(const char *filename, Display *dpy, int screen, Window root) -{ - XSurface* surf = surface_load(filename, dpy, screen, root); - return zr_image_ptr(surf); -} - -#endif - static void input_key(struct XWindow *xw, struct zr_context *ctx, XEvent *evt, int down) { @@ -717,29 +710,48 @@ main(int argc, char *argv[]) } break; case ZR_COMMAND_LINE: { const struct zr_command_line *l = zr_command(line, cmd); - surface_draw_line(xw.surf, l->begin.x, l->begin.y, l->end.x, - l->end.y, l->color); + surface_stroke_line(xw.surf, l->begin.x, l->begin.y, l->end.x, + l->end.y, l->line_thickness, l->color); } break; case ZR_COMMAND_RECT: { const struct zr_command_rect *r = zr_command(rect, cmd); - surface_draw_rect(xw.surf, r->x, r->y, r->w, r->h, (uint16_t)r->rounding, r->color); + surface_stroke_rect(xw.surf, r->x, r->y, r->w, r->h, + (uint16_t)r->rounding, r->line_thickness, r->color); + } break; + case ZR_COMMAND_RECT_FILLED: { + const struct zr_command_rect_filled *r = zr_command(rect_filled, cmd); + surface_fill_rect(xw.surf, r->x, r->y, r->w, r->h, + (uint16_t)r->rounding, r->color); } break; case ZR_COMMAND_CIRCLE: { const struct zr_command_circle *c = zr_command(circle, cmd); - surface_draw_circle(xw.surf, c->x, c->y, c->w, c->h, c->color); + surface_stroke_circle(xw.surf, c->x, c->y, c->w, c->h, c->line_thickness, c->color); + } break; + case ZR_COMMAND_CIRCLE_FILLED: { + const struct zr_command_circle_filled *c = zr_command(circle_filled, cmd); + surface_fill_circle(xw.surf, c->x, c->y, c->w, c->h, c->color); } break; case ZR_COMMAND_TRIANGLE: { - const struct zr_command_triangle *t = zr_command(triangle, cmd); - surface_draw_triangle(xw.surf, t->a.x, t->a.y, t->b.x, t->b.y, + const struct zr_command_triangle*t = zr_command(triangle, cmd); + surface_stroke_triangle(xw.surf, t->a.x, t->a.y, t->b.x, t->b.y, + t->c.x, t->c.y, t->line_thickness, t->color); + } break; + case ZR_COMMAND_TRIANGLE_FILLED: { + const struct zr_command_triangle_filled *t = zr_command(triangle_filled, cmd); + surface_fill_triangle(xw.surf, t->a.x, t->a.y, t->b.x, t->b.y, t->c.x, t->c.y, t->color); } break; case ZR_COMMAND_POLYGON: { const struct zr_command_polygon *p = zr_command(polygon, cmd); - surface_draw_polygon(xw.surf, p->mode, p->points, p->point_count, p->color); + surface_stroke_polygon(xw.surf, p->points, p->point_count, p->line_thickness,p->color); + } break; + case ZR_COMMAND_POLYGON_FILLED: { + const struct zr_command_polygon_filled *p = zr_command(polygon_filled, cmd); + surface_fill_polygon(xw.surf, p->points, p->point_count, p->color); } break; case ZR_COMMAND_POLYLINE: { const struct zr_command_polyline *p = zr_command(polyline, cmd); - surface_draw_polyline(xw.surf, p->points, p->point_count, p->color); + surface_stroke_polyline(xw.surf, p->points, p->point_count, p->line_thickness, p->color); } break; case ZR_COMMAND_TEXT: { const struct zr_command_text *t = zr_command(text, cmd); @@ -748,19 +760,15 @@ main(int argc, char *argv[]) (XFont*)t->font->userdata.ptr, t->background, t->foreground); } break; - case ZR_COMMAND_IMAGE: { - const struct zr_command_image *img = zr_command(image, cmd); - XSurface *surf = (XSurface*)img->img.handle.ptr; - surface_blit(xw.surf, surf, img->x, img->y, img->w, img->h, - 0, 0, (int)surf->w, (int)surf->h); - } break; case ZR_COMMAND_CURVE: { const struct zr_command_curve *q = zr_command(curve, cmd); - surface_draw_curve(xw.surf, q->begin, q->ctrl[0], q->ctrl[1], - q->end, 22, q->color); + surface_stroke_curve(xw.surf, q->begin, q->ctrl[0], q->ctrl[1], + q->end, 22, q->line_thickness, q->color); } break; case ZR_COMMAND_RECT_MULTI_COLOR: + case ZR_COMMAND_IMAGE: case ZR_COMMAND_ARC: + case ZR_COMMAND_ARC_FILLED: default: break; } } diff --git a/zahnrad.c b/zahnrad.c index bad6819..4c4ca00 100644 --- a/zahnrad.c +++ b/zahnrad.c @@ -28,173 +28,6 @@ #define ZR_VALUE_PAGE_CAPACITY 32 #define ZR_DEFAULT_COMMAND_BUFFER_SIZE (4*1024) -/* internal widget state */ -#define ZR_INACTIVE ZR_FLAG(0) -#define ZR_ENTER ZR_FLAG(1) -#define ZR_HOVERED ZR_FLAG(2) -#define ZR_LEAVE ZR_FLAG(3) -#define ZR_ACTIVE ZR_FLAG(4) - -enum zr_draw_list_stroke { - ZR_STROKE_OPEN = zr_false, - /* build up path has no connection back to the beginning */ - ZR_STROKE_CLOSED = zr_true - /* build up path has a connection back to the beginning */ -}; - -struct zr_text_selection { - int active; - /* current selection state */ - zr_size begin; - /* text selection beginning glyph index */ - zr_size end; - /* text selection ending glyph index */ -}; - -struct zr_edit_box { - struct zr_buffer buffer; - /* glyph buffer to add text into */ - int active; - /* flag indicating if the buffer is currently being modified */ - zr_size cursor; - /* current glyph (not byte) cursor position */ - zr_size glyphs; - /* number of glyphs inside the edit box */ - struct zr_clipboard clip; - /* copy paste callbacks */ - zr_filter filter; - /* input filter callback */ - struct zr_text_selection sel; - /* text selection */ - float scrollbar; - /* edit field scrollbar */ - int text_inserted; -}; - -enum zr_internal_window_flags { - ZR_WINDOW_PRIVATE = ZR_FLAG(9), - /* dummy flag which mark the beginning of the private window flag part */ - ZR_WINDOW_ROM = ZR_FLAG(10), - /* sets the window into a read only mode and does not allow input changes */ - ZR_WINDOW_HIDDEN = ZR_FLAG(11), - /* Hiddes the window and stops any window interaction and drawing can be set - * by user input or by closing the window */ - ZR_WINDOW_MINIMIZED = ZR_FLAG(12), - /* marks the window as minimized */ - ZR_WINDOW_SUB = ZR_FLAG(13), - /* Marks the window as subwindow of another window*/ - ZR_WINDOW_GROUP = ZR_FLAG(14), - /* Marks the window as window widget group */ - ZR_WINDOW_POPUP = ZR_FLAG(15), - /* Marks the window as a popup window */ - ZR_WINDOW_NONBLOCK = ZR_FLAG(16), - /* Marks the window as a nonblock popup window */ - ZR_WINDOW_CONTEXTUAL = ZR_FLAG(17), - /* Marks the window as a combo box or menu */ - ZR_WINDOW_COMBO = ZR_FLAG(18), - /* Marks the window as a combo box */ - ZR_WINDOW_MENU = ZR_FLAG(19), - /* Marks the window as a menu */ - ZR_WINDOW_TOOLTIP = ZR_FLAG(20), - /* Marks the window as a menu */ - ZR_WINDOW_REMOVE_ROM = ZR_FLAG(21) - /* Removes the read only mode at the end of the window */ -}; - -struct zr_popup { - struct zr_window *win; - enum zr_internal_window_flags type; - zr_hash name; - int active; - - unsigned combo_count; - unsigned con_count, con_old; - unsigned active_con; -}; - -struct zr_edit_state { - zr_hash name; - zr_size cursor; - struct zr_text_selection sel; - float scrollbar; - unsigned int seq; - unsigned int old; - int active, prev; -}; - -struct zr_value { - int active, prev; - char buffer[ZR_MAX_NUMBER_BUFFER]; - zr_size length; - zr_size cursor; - zr_hash name; - unsigned int seq; - unsigned int old; - int state; -}; - -struct zr_table { - unsigned int seq; - zr_hash keys[ZR_VALUE_PAGE_CAPACITY]; - zr_uint values[ZR_VALUE_PAGE_CAPACITY]; - struct zr_table *next, *prev; -}; - -struct zr_window { - zr_hash name; - /* name of this window */ - unsigned int seq; - /* window lifeline */ - struct zr_rect bounds; - /* window size and position */ - zr_flags flags; - /* window flags modifing its behavior */ - zr_flags old_flags; - /* window flags from the last frame */ - struct zr_scroll scrollbar; - /* scrollbar x- and y-offset */ - struct zr_command_buffer buffer; - /* command buffer for queuing drawing calls */ - - /* frame window state */ - struct zr_panel *layout; - - /* persistent widget state */ - struct zr_value property; - struct zr_popup popup; - struct zr_edit_state edit; - - struct zr_table *tables; - unsigned short table_count; - unsigned short table_size; - - /* window list */ - struct zr_window *next; - struct zr_window *prev; - struct zr_window *parent; -}; - -union zr_page_data { - struct zr_table tbl; - struct zr_window win; -}; - -struct zr_window_page { - unsigned size; - struct zr_window_page *next; - union zr_page_data win[1]; -}; - -struct zr_pool { - struct zr_allocator alloc; - enum zr_allocation_type type; - unsigned int page_count; - struct zr_window_page *pages; - unsigned capacity; - zr_size size; - zr_size cap; -}; - /* ============================================================== * MATH * =============================================================== */ @@ -457,7 +290,6 @@ zr_vec2iv(const int *v) { return zr_vec2i(v[0], v[1]); } - /* * ============================================================== * @@ -1983,7 +1815,7 @@ zr_command_buffer_push(struct zr_command_buffer* b, } void -zr_draw_scissor(struct zr_command_buffer *b, struct zr_rect r) +zr_push_scissor(struct zr_command_buffer *b, struct zr_rect r) { struct zr_command_scissor *cmd; ZR_ASSERT(b); @@ -2004,8 +1836,8 @@ zr_draw_scissor(struct zr_command_buffer *b, struct zr_rect r) } void -zr_draw_line(struct zr_command_buffer *b, float x0, float y0, - float x1, float y1, struct zr_color c) +zr_stroke_line(struct zr_command_buffer *b, float x0, float y0, + float x1, float y1, float line_thickness, struct zr_color c) { struct zr_command_line *cmd; ZR_ASSERT(b); @@ -2013,6 +1845,7 @@ zr_draw_line(struct zr_command_buffer *b, float x0, float y0, cmd = (struct zr_command_line*) zr_command_buffer_push(b, ZR_COMMAND_LINE, sizeof(*cmd)); if (!cmd) return; + cmd->line_thickness = (unsigned short)line_thickness; cmd->begin.x = (short)x0; cmd->begin.y = (short)y0; cmd->end.x = (short)x1; @@ -2021,17 +1854,18 @@ zr_draw_line(struct zr_command_buffer *b, float x0, float y0, } void -zr_draw_curve(struct zr_command_buffer *b, float ax, float ay, +zr_stroke_curve(struct zr_command_buffer *b, float ax, float ay, float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y, - float bx, float by, struct zr_color col) + float bx, float by, float line_thickness, struct zr_color col) { struct zr_command_curve *cmd; ZR_ASSERT(b); - if (!b) return; + if (!b || col.a == 0) return; cmd = (struct zr_command_curve*) zr_command_buffer_push(b, ZR_COMMAND_CURVE, sizeof(*cmd)); if (!cmd) return; + cmd->line_thickness = (unsigned short)line_thickness; cmd->begin.x = (short)ax; cmd->begin.y = (short)ay; cmd->ctrl[0].x = (short)ctrl0x; @@ -2044,12 +1878,12 @@ zr_draw_curve(struct zr_command_buffer *b, float ax, float ay, } void -zr_draw_rect(struct zr_command_buffer *b, enum zr_command_drawing_mode mode, - struct zr_rect rect, float rounding, struct zr_color c) +zr_stroke_rect(struct zr_command_buffer *b, struct zr_rect rect, + float rounding, float line_thickness, struct zr_color c) { struct zr_command_rect *cmd; ZR_ASSERT(b); - if (!b) return; + if (!b || c.a == 0) return; if (b->use_clipping) { const struct zr_rect *clip = &b->clip; if (!ZR_INTERSECT(rect.x, rect.y, rect.w, rect.h, @@ -2059,8 +1893,8 @@ zr_draw_rect(struct zr_command_buffer *b, enum zr_command_drawing_mode mode, cmd = (struct zr_command_rect*) zr_command_buffer_push(b, ZR_COMMAND_RECT, sizeof(*cmd)); if (!cmd) return; - cmd->mode = mode; - cmd->rounding = (unsigned int)rounding; + cmd->rounding = (unsigned short)rounding; + cmd->line_thickness = (unsigned short)line_thickness; cmd->x = (short)rect.x; cmd->y = (short)rect.y; cmd->w = (unsigned short)ZR_MAX(0, rect.w); @@ -2069,7 +1903,31 @@ zr_draw_rect(struct zr_command_buffer *b, enum zr_command_drawing_mode mode, } void -zr_draw_rect_multi_color(struct zr_command_buffer *b, struct zr_rect rect, +zr_fill_rect(struct zr_command_buffer *b, struct zr_rect rect, + float rounding, struct zr_color c) +{ + struct zr_command_rect_filled *cmd; + ZR_ASSERT(b); + if (!b || c.a == 0) return; + if (b->use_clipping) { + const struct zr_rect *clip = &b->clip; + if (!ZR_INTERSECT(rect.x, rect.y, rect.w, rect.h, + clip->x, clip->y, clip->w, clip->h)) return; + } + + cmd = (struct zr_command_rect_filled*) + zr_command_buffer_push(b, ZR_COMMAND_RECT_FILLED, sizeof(*cmd)); + if (!cmd) return; + cmd->rounding = (unsigned short)rounding; + cmd->x = (short)rect.x; + cmd->y = (short)rect.y; + cmd->w = (unsigned short)ZR_MAX(0, rect.w); + cmd->h = (unsigned short)ZR_MAX(0, rect.h); + cmd->color = c; +} + +void +zr_fill_rect_multi_color(struct zr_command_buffer *b, struct zr_rect rect, struct zr_color left, struct zr_color top, struct zr_color right, struct zr_color bottom) { @@ -2095,12 +1953,11 @@ zr_draw_rect_multi_color(struct zr_command_buffer *b, struct zr_rect rect, } void -zr_draw_circle(struct zr_command_buffer *b, enum zr_command_drawing_mode mode, - struct zr_rect r, struct zr_color c) +zr_stroke_circle(struct zr_command_buffer *b, struct zr_rect r, + float line_thickness, struct zr_color c) { struct zr_command_circle *cmd; - ZR_ASSERT(b); - if (!b) return; + if (!b || c.a == 0) return; if (b->use_clipping) { const struct zr_rect *clip = &b->clip; if (!ZR_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) @@ -2110,7 +1967,7 @@ zr_draw_circle(struct zr_command_buffer *b, enum zr_command_drawing_mode mode, cmd = (struct zr_command_circle*) zr_command_buffer_push(b, ZR_COMMAND_CIRCLE, sizeof(*cmd)); if (!cmd) return; - cmd->mode = mode; + cmd->line_thickness = (unsigned short)line_thickness; cmd->x = (short)r.x; cmd->y = (short)r.y; cmd->w = (unsigned short)ZR_MAX(r.w, 0); @@ -2119,14 +1976,37 @@ zr_draw_circle(struct zr_command_buffer *b, enum zr_command_drawing_mode mode, } void -zr_draw_arc(struct zr_command_buffer *b, enum zr_command_drawing_mode mode, - float cx, float cy, float radius, float a_min, float a_max, struct zr_color c) +zr_fill_circle(struct zr_command_buffer *b, struct zr_rect r, struct zr_color c) +{ + struct zr_command_circle_filled *cmd; + ZR_ASSERT(b); + if (!b || c.a == 0) return; + if (b->use_clipping) { + const struct zr_rect *clip = &b->clip; + if (!ZR_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) + return; + } + + cmd = (struct zr_command_circle_filled*) + zr_command_buffer_push(b, ZR_COMMAND_CIRCLE_FILLED, sizeof(*cmd)); + if (!cmd) return; + cmd->x = (short)r.x; + cmd->y = (short)r.y; + cmd->w = (unsigned short)ZR_MAX(r.w, 0); + cmd->h = (unsigned short)ZR_MAX(r.h, 0); + cmd->color = c; +} + +void +zr_stroke_arc(struct zr_command_buffer *b, float cx, float cy, float radius, + float a_min, float a_max, float line_thickness, struct zr_color c) { struct zr_command_arc *cmd; + if (!b || c.a == 0) return; cmd = (struct zr_command_arc*) zr_command_buffer_push(b, ZR_COMMAND_ARC, sizeof(*cmd)); if (!cmd) return; - cmd->mode = mode; + cmd->line_thickness = (unsigned short)line_thickness; cmd->cx = (short)cx; cmd->cy = (short)cy; cmd->r = (unsigned short)radius; @@ -2136,12 +2016,30 @@ zr_draw_arc(struct zr_command_buffer *b, enum zr_command_drawing_mode mode, } void -zr_draw_triangle(struct zr_command_buffer *b,enum zr_command_drawing_mode mode, - float x0, float y0, float x1, float y1, float x2, float y2, struct zr_color c) +zr_fill_arc(struct zr_command_buffer *b, float cx, float cy, float radius, + float a_min, float a_max, struct zr_color c) +{ + struct zr_command_arc_filled *cmd; + ZR_ASSERT(b); + if (!b || c.a == 0) return; + cmd = (struct zr_command_arc_filled*) + zr_command_buffer_push(b, ZR_COMMAND_ARC_FILLED, sizeof(*cmd)); + if (!cmd) return; + cmd->cx = (short)cx; + cmd->cy = (short)cy; + cmd->r = (unsigned short)radius; + cmd->a[0] = a_min; + cmd->a[1] = a_max; + cmd->color = c; +} + +void +zr_stroke_triangle(struct zr_command_buffer *b, float x0, float y0, float x1, + float y1, float x2, float y2, float line_thickness, struct zr_color c) { struct zr_command_triangle *cmd; ZR_ASSERT(b); - if (!b) return; + if (!b || c.a == 0) return; if (b->use_clipping) { const struct zr_rect *clip = &b->clip; if (!ZR_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) || @@ -2153,7 +2051,7 @@ zr_draw_triangle(struct zr_command_buffer *b,enum zr_command_drawing_mode mode, cmd = (struct zr_command_triangle*) zr_command_buffer_push(b, ZR_COMMAND_TRIANGLE, sizeof(*cmd)); if (!cmd) return; - cmd->mode = mode; + cmd->line_thickness = (unsigned short)line_thickness; cmd->a.x = (short)x0; cmd->a.y = (short)y0; cmd->b.x = (short)x1; @@ -2163,9 +2061,102 @@ zr_draw_triangle(struct zr_command_buffer *b,enum zr_command_drawing_mode mode, cmd->color = c; } +void +zr_fill_triangle(struct zr_command_buffer *b, float x0, float y0, float x1, + float y1, float x2, float y2, struct zr_color c) +{ + struct zr_command_triangle_filled *cmd; + ZR_ASSERT(b); + if (!b || c.a == 0) return; + if (!b) return; + if (b->use_clipping) { + const struct zr_rect *clip = &b->clip; + if (!ZR_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) || + !ZR_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) || + !ZR_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) + return; + } + + cmd = (struct zr_command_triangle_filled*) + zr_command_buffer_push(b, ZR_COMMAND_TRIANGLE_FILLED, sizeof(*cmd)); + if (!cmd) return; + cmd->a.x = (short)x0; + cmd->a.y = (short)y0; + cmd->b.x = (short)x1; + cmd->b.y = (short)y1; + cmd->c.x = (short)x2; + cmd->c.y = (short)y2; + cmd->color = c; +} + +void +zr_stroke_polygon(struct zr_command_buffer *b, float *points, int point_count, + float line_thickness, struct zr_color col) +{ + int i; + zr_size size = 0; + struct zr_command_polygon *cmd; + + ZR_ASSERT(b); + if (!b || col.a == 0) return; + size = sizeof(*cmd) + sizeof(short) * 2 * (zr_size)point_count; + cmd = (struct zr_command_polygon*) zr_command_buffer_push(b, ZR_COMMAND_POLYGON, size); + if (!cmd) return; + cmd->line_thickness = (unsigned short)line_thickness; + cmd->color = col; + cmd->point_count = (unsigned short)point_count; + for (i = 0; i < point_count; ++i) { + cmd->points[i].x = (short)points[i*2]; + cmd->points[i].y = (short)points[i*2+1]; + } +} + +void +zr_fill_polygon(struct zr_command_buffer *b, float *points, int point_count, + struct zr_color col) +{ + int i; + zr_size size = 0; + struct zr_command_polygon_filled *cmd; + + ZR_ASSERT(b); + if (!b || col.a == 0) return; + size = sizeof(*cmd) + sizeof(short) * 2 * (zr_size)point_count; + cmd = (struct zr_command_polygon_filled*) + zr_command_buffer_push(b, ZR_COMMAND_POLYGON_FILLED, size); + if (!cmd) return; + cmd->color = col; + cmd->point_count = (unsigned short)point_count; + for (i = 0; i < point_count; ++i) { + cmd->points[i].x = (short)points[i*2]; + cmd->points[i].y = (short)points[i*2+1]; + } +} + +void +zr_stroke_polyline(struct zr_command_buffer *b, + float *points, int point_count, struct zr_color col) +{ + int i; + zr_size size = 0; + struct zr_command_polyline *cmd; + + ZR_ASSERT(b); + if (!b || col.a == 0) return; + size = sizeof(*cmd) + sizeof(short) * 2 * (zr_size)point_count; + cmd = (struct zr_command_polyline*) zr_command_buffer_push(b, ZR_COMMAND_POLYLINE, size); + if (!cmd) return; + cmd->color = col; + cmd->point_count = (unsigned short)point_count; + for (i = 0; i < point_count; ++i) { + cmd->points[i].x = (short)points[i*2]; + cmd->points[i].y = (short)points[i*2+1]; + } +} + void zr_draw_image(struct zr_command_buffer *b, struct zr_rect r, - struct zr_image *img) + const struct zr_image *img) { struct zr_command_image *cmd; ZR_ASSERT(b); @@ -2186,49 +2177,6 @@ zr_draw_image(struct zr_command_buffer *b, struct zr_rect r, cmd->img = *img; } -void -zr_draw_polygon(struct zr_command_buffer *b, enum zr_command_drawing_mode mode, - float *points, int point_count, struct zr_color col) -{ - int i; - zr_size size = 0; - struct zr_command_polygon *cmd; - - ZR_ASSERT(b); - if (!b) return; - size = sizeof(*cmd) + sizeof(short) * 2 * (zr_size)point_count; - cmd = (struct zr_command_polygon*) zr_command_buffer_push(b, ZR_COMMAND_POLYGON, size); - if (!cmd) return; - cmd->color = col; - cmd->mode = mode; - cmd->point_count = (unsigned short)point_count; - for (i = 0; i < point_count; ++i) { - cmd->points[i].x = (short)points[i*2]; - cmd->points[i].y = (short)points[i*2+1]; - } -} - -void -zr_draw_polyline(struct zr_command_buffer *b, - float *points, int point_count, struct zr_color col) -{ - int i; - zr_size size = 0; - struct zr_command_polyline *cmd; - - ZR_ASSERT(b); - if (!b) return; - size = sizeof(*cmd) + sizeof(short) * 2 * (zr_size)point_count; - cmd = (struct zr_command_polyline*) zr_command_buffer_push(b, ZR_COMMAND_POLYLINE, size); - if (!cmd) return; - cmd->color = col; - cmd->point_count = (unsigned short)point_count; - for (i = 0; i < point_count; ++i) { - cmd->points[i].x = (short)points[i*2]; - cmd->points[i].y = (short)points[i*2+1]; - } -} - void zr_draw_text(struct zr_command_buffer *b, struct zr_rect r, const char *string, zr_size length, const struct zr_user_font *font, @@ -2239,7 +2187,7 @@ zr_draw_text(struct zr_command_buffer *b, struct zr_rect r, ZR_ASSERT(b); ZR_ASSERT(font); - if (!b || !string || !length) return; + if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return; if (b->use_clipping) { const struct zr_rect *c = &b->clip; if (!ZR_INTERSECT(r.x, r.y, r.w, r.h, c->x, c->y, c->w, c->h)) @@ -2278,6 +2226,13 @@ zr_draw_text(struct zr_command_buffer *b, struct zr_rect r, * * ===============================================================*/ #if ZR_COMPILE_WITH_VERTEX_BUFFER +enum zr_draw_list_stroke { + ZR_STROKE_OPEN = zr_false, + /* build up path has no connection back to the beginning */ + ZR_STROKE_CLOSED = zr_true + /* build up path has a connection back to the beginning */ +}; + static void zr_canvas_init(struct zr_canvas *list) { @@ -3214,9 +3169,7 @@ zr_convert(struct zr_context *ctx, struct zr_buffer *cmds, struct zr_buffer *vertices, struct zr_buffer *elements, const struct zr_convert_config *config) { - float line_thickness; const struct zr_command *cmd; - ZR_ASSERT(ctx); ZR_ASSERT(cmds); ZR_ASSERT(vertices); @@ -3233,7 +3186,6 @@ zr_convert(struct zr_context *ctx, struct zr_buffer *cmds, ctx->canvas.shape_AA = config->shape_AA; ctx->canvas.global_alpha = config->global_alpha; - line_thickness = ZR_MAX(config->line_thickness, 1.0f); zr_foreach(cmd, ctx) { #if ZR_COMPILE_WITH_COMMAND_USERDATA @@ -3248,24 +3200,24 @@ zr_convert(struct zr_context *ctx, struct zr_buffer *cmds, case ZR_COMMAND_LINE: { const struct zr_command_line *l = zr_command(line, cmd); zr_canvas_stroke_line(&ctx->canvas, zr_vec2(l->begin.x, l->begin.y), - zr_vec2(l->end.x, l->end.y), l->color, line_thickness); + zr_vec2(l->end.x, l->end.y), l->color, l->line_thickness); } break; case ZR_COMMAND_CURVE: { const struct zr_command_curve *q = zr_command(curve, cmd); zr_canvas_add_curve(&ctx->canvas, zr_vec2(q->begin.x, q->begin.y), zr_vec2(q->ctrl[0].x, q->ctrl[0].y), zr_vec2(q->ctrl[1].x, q->ctrl[1].y), zr_vec2(q->end.x, q->end.y), q->color, - config->circle_segment_count, line_thickness); + config->curve_segment_count, q->line_thickness); } break; case ZR_COMMAND_RECT: { const struct zr_command_rect *r = zr_command(rect, cmd); - if (r->mode == ZR_FILLED) { - zr_canvas_fill_rect(&ctx->canvas, zr_rect(r->x, r->y, r->w, r->h), - r->color, (float)r->rounding); - } else { - zr_canvas_stroke_rect(&ctx->canvas, zr_rect(r->x, r->y, r->w, r->h), - r->color, (float)r->rounding, line_thickness); - } + zr_canvas_stroke_rect(&ctx->canvas, zr_rect(r->x, r->y, r->w, r->h), + r->color, (float)r->rounding, r->line_thickness); + } break; + case ZR_COMMAND_RECT_FILLED: { + const struct zr_command_rect_filled *r = zr_command(rect_filled, cmd); + zr_canvas_fill_rect(&ctx->canvas, zr_rect(r->x, r->y, r->w, r->h), + r->color, (float)r->rounding); } break; case ZR_COMMAND_RECT_MULTI_COLOR: { const struct zr_command_rect_multi_color *r = zr_command(rect_multi_color, cmd); @@ -3274,47 +3226,58 @@ zr_convert(struct zr_context *ctx, struct zr_buffer *cmds, } break; case ZR_COMMAND_CIRCLE: { const struct zr_command_circle *c = zr_command(circle, cmd); - if (c->mode == ZR_FILLED) { - zr_canvas_fill_circle(&ctx->canvas, zr_vec2((float)c->x + (float)c->w/2, - (float)c->y + (float)c->h/2), (float)c->w/2, c->color, - config->circle_segment_count); - } else { - zr_canvas_stroke_circle(&ctx->canvas, zr_vec2((float)c->x + (float)c->w/2, - (float)c->y + (float)c->h/2), (float)c->w/2, c->color, - config->circle_segment_count, line_thickness); - } + zr_canvas_stroke_circle(&ctx->canvas, zr_vec2((float)c->x + (float)c->w/2, + (float)c->y + (float)c->h/2), (float)c->w/2, c->color, + config->circle_segment_count, c->line_thickness); + } break; + case ZR_COMMAND_CIRCLE_FILLED: { + const struct zr_command_circle_filled *c = zr_command(circle_filled, cmd); + zr_canvas_fill_circle(&ctx->canvas, zr_vec2((float)c->x + (float)c->w/2, + (float)c->y + (float)c->h/2), (float)c->w/2, c->color, + config->circle_segment_count); } break; case ZR_COMMAND_ARC: { const struct zr_command_arc *c = zr_command(arc, cmd); zr_canvas_path_line_to(&ctx->canvas, zr_vec2(c->cx, c->cy)); zr_canvas_path_arc_to(&ctx->canvas, zr_vec2(c->cx, c->cy), c->r, - c->a[0], c->a[1], config->circle_segment_count); - if (c->mode == ZR_FILLED) - zr_canvas_path_fill(&ctx->canvas, c->color); - if (c->mode == ZR_STROKE) - zr_canvas_path_stroke(&ctx->canvas, c->color, ZR_STROKE_CLOSED, line_thickness); + c->a[0], c->a[1], config->arc_segment_count); + zr_canvas_path_stroke(&ctx->canvas, c->color, ZR_STROKE_CLOSED, c->line_thickness); + } break; + case ZR_COMMAND_ARC_FILLED: { + const struct zr_command_arc_filled *c = zr_command(arc_filled, cmd); + zr_canvas_path_line_to(&ctx->canvas, zr_vec2(c->cx, c->cy)); + zr_canvas_path_arc_to(&ctx->canvas, zr_vec2(c->cx, c->cy), c->r, + c->a[0], c->a[1], config->arc_segment_count); + zr_canvas_path_fill(&ctx->canvas, c->color); } break; case ZR_COMMAND_TRIANGLE: { const struct zr_command_triangle *t = zr_command(triangle, cmd); - if (t->mode == ZR_FILLED) { - zr_canvas_fill_triangle(&ctx->canvas, zr_vec2(t->a.x, t->a.y), - zr_vec2(t->b.x, t->b.y), zr_vec2(t->c.x, t->c.y), t->color); - } else { - zr_canvas_stroke_triangle(&ctx->canvas, zr_vec2(t->a.x, t->a.y), - zr_vec2(t->b.x, t->b.y), zr_vec2(t->c.x, t->c.y), t->color, - line_thickness); - } + zr_canvas_stroke_triangle(&ctx->canvas, zr_vec2(t->a.x, t->a.y), + zr_vec2(t->b.x, t->b.y), zr_vec2(t->c.x, t->c.y), t->color, + t->line_thickness); + } break; + case ZR_COMMAND_TRIANGLE_FILLED: { + const struct zr_command_triangle_filled *t = zr_command(triangle_filled, cmd); + zr_canvas_fill_triangle(&ctx->canvas, zr_vec2(t->a.x, t->a.y), + zr_vec2(t->b.x, t->b.y), zr_vec2(t->c.x, t->c.y), t->color); } break; case ZR_COMMAND_POLYGON: { int i; - const struct zr_command_polygon *p = zr_command(polygon, cmd); + const struct zr_command_polygon*p = zr_command(polygon, cmd); for (i = 0; i < p->point_count; ++i) { struct zr_vec2 pnt = zr_vec2((float)p->points[i].x, (float)p->points[i].y); zr_canvas_path_line_to(&ctx->canvas, pnt); } - if (p->mode == ZR_STROKE) - zr_canvas_path_stroke(&ctx->canvas, p->color, ZR_STROKE_CLOSED, line_thickness); - else zr_canvas_path_fill(&ctx->canvas, p->color); + zr_canvas_path_stroke(&ctx->canvas, p->color, ZR_STROKE_CLOSED, p->line_thickness); + } break; + case ZR_COMMAND_POLYGON_FILLED: { + int i; + const struct zr_command_polygon_filled *p = zr_command(polygon_filled, cmd); + for (i = 0; i < p->point_count; ++i) { + struct zr_vec2 pnt = zr_vec2((float)p->points[i].x, (float)p->points[i].y); + zr_canvas_path_line_to(&ctx->canvas, pnt); + } + zr_canvas_path_fill(&ctx->canvas, p->color); } break; case ZR_COMMAND_POLYLINE: { int i; @@ -3323,7 +3286,7 @@ zr_convert(struct zr_context *ctx, struct zr_buffer *cmds, struct zr_vec2 pnt = zr_vec2((float)p->points[i].x, (float)p->points[i].y); zr_canvas_path_line_to(&ctx->canvas, pnt); } - zr_canvas_path_stroke(&ctx->canvas, p->color, ZR_STROKE_OPEN, line_thickness); + zr_canvas_path_stroke(&ctx->canvas, p->color, ZR_STROKE_OPEN, p->line_thickness); } break; case ZR_COMMAND_TEXT: { const struct zr_command_text *t = zr_command(text, cmd); @@ -4377,2134 +4340,6 @@ zr_edit_box_len(struct zr_edit_box *eb) return eb->glyphs; } -/* =============================================================== - * - * TEXT - * - * ===============================================================*/ -struct zr_text { - struct zr_vec2 padding; - struct zr_color background; - struct zr_color text; -}; - -static void -zr_widget_text(struct zr_command_buffer *o, struct zr_rect b, - const char *string, zr_size len, const struct zr_text *t, - zr_flags a, const struct zr_user_font *f) -{ - struct zr_rect label; - zr_size text_width; - - ZR_ASSERT(o); - ZR_ASSERT(t); - if (!o || !t) return; - - b.h = ZR_MAX(b.h, 2 * t->padding.y); - label.x = 0; label.w = 0; - label.y = b.y + t->padding.y; - label.h = b.h - 2 * t->padding.y; - - text_width = f->width(f->userdata, f->height, (const char*)string, len); - text_width += (zr_size)(2 * t->padding.x); - - /* align in x-axis */ - if (a & ZR_TEXT_LEFT) { - label.x = b.x + t->padding.x; - label.w = ZR_MAX(0, b.w - 2 * t->padding.x); - } else if (a & ZR_TEXT_CENTERED) { - label.w = ZR_MAX(1, 2 * t->padding.x + (float)text_width); - label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2); - label.x = ZR_MAX(b.x + t->padding.x, label.x); - label.w = ZR_MIN(b.x + b.w, label.x + label.w); - if (label.w >= label.x) label.w -= label.x; - } else if (a & ZR_TEXT_RIGHT) { - label.x = ZR_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width)); - label.w = (float)text_width + 2 * t->padding.x; - } else return; - - /* align in y-axis */ - if (a & ZR_TEXT_MIDDLE) { - label.y = b.y + b.h/2.0f - (float)f->height/2.0f; - label.h = b.h - (b.h/2.0f + f->height/2.0f); - } else if (a & ZR_TEXT_BOTTOM) { - label.y = b.y + b.h - f->height; - label.h = f->height; - } - zr_draw_text(o, label, (const char*)string, - len, f, t->background, t->text); -} - -static void -zr_widget_text_wrap(struct zr_command_buffer *o, struct zr_rect b, - const char *string, zr_size len, const struct zr_text *t, - const struct zr_user_font *f) -{ - float width; - zr_size glyphs = 0; - zr_size fitting = 0; - zr_size done = 0; - struct zr_rect line; - struct zr_text text; - - ZR_ASSERT(o); - ZR_ASSERT(t); - if (!o || !t) return; - - text.padding = zr_vec2(0,0); - text.background = t->background; - text.text = t->text; - - b.w = ZR_MAX(b.w, 2 * t->padding.x); - b.h = ZR_MAX(b.h, 2 * t->padding.y); - b.h = b.h - 2 * t->padding.y; - - line.x = b.x + t->padding.x; - line.y = b.y + t->padding.y; - line.w = b.w - 2 * t->padding.x; - line.h = 2 * t->padding.y + f->height; - - fitting = zr_use_font_glyph_clamp(f, string, len, line.w, &glyphs, &width); - while (done < len) { - if (!fitting || line.y + line.h >= (b.y + b.h)) break; - zr_widget_text(o, line, &string[done], fitting, &text, ZR_TEXT_LEFT, f); - done += fitting; - line.y += f->height + 2 * t->padding.y; - fitting = zr_use_font_glyph_clamp(f, &string[done], len - done, - line.w, &glyphs, &width); - } -} - -/* =============================================================== - * - * BUTTON - * - * ===============================================================*/ -struct zr_button { - float border_width; - float rounding; - struct zr_vec2 padding; - struct zr_vec2 touch_pad; - struct zr_color border; - struct zr_color normal; - struct zr_color hover; - struct zr_color active; -}; - -struct zr_button_text { - struct zr_button base; - zr_flags alignment; - struct zr_color normal; - struct zr_color hover; - struct zr_color active; -}; - -struct zr_button_symbol { - struct zr_button base; - struct zr_color normal; - struct zr_color hover; - struct zr_color active; -}; - -struct zr_button_icon { - struct zr_button base; - struct zr_vec2 padding; -}; - -struct zr_symbol { - enum zr_symbol_type type; - struct zr_color background; - struct zr_color foreground; - float border_width; -}; - -static void -zr_draw_symbol(struct zr_command_buffer *out, const struct zr_symbol *sym, - struct zr_rect content, const struct zr_user_font *font) -{ - switch (sym->type) { - case ZR_SYMBOL_X: - case ZR_SYMBOL_UNDERSCORE: - case ZR_SYMBOL_PLUS: - case ZR_SYMBOL_MINUS: { - /* single character text symbol */ - const char *X = (sym->type == ZR_SYMBOL_X) ? "x": - (sym->type == ZR_SYMBOL_UNDERSCORE) ? "_": - (sym->type == ZR_SYMBOL_PLUS) ? "+": "-"; - struct zr_text text; - text.padding = zr_vec2(0,0); - text.background = sym->background; - text.text = sym->foreground; - zr_widget_text(out, content, X, 1, &text, ZR_TEXT_CENTERED, font); - } break; - case ZR_SYMBOL_CIRCLE: - case ZR_SYMBOL_CIRCLE_FILLED: - case ZR_SYMBOL_RECT: - case ZR_SYMBOL_RECT_FILLED: { - /* simple empty/filled shapes */ - if (sym->type == ZR_SYMBOL_RECT || sym->type == ZR_SYMBOL_RECT_FILLED) { - zr_draw_rect(out, ZR_FILLED, content, 0, sym->foreground); - if (sym->type == ZR_SYMBOL_RECT_FILLED) - zr_draw_rect(out, ZR_FILLED, zr_shrink_rect(content, - sym->border_width), 0, sym->background); - } else { - zr_draw_circle(out, ZR_FILLED, content, sym->foreground); - if (sym->type == ZR_SYMBOL_CIRCLE_FILLED) - zr_draw_circle(out, ZR_FILLED, zr_shrink_rect(content, 1), - sym->background); - } - } break; - case ZR_SYMBOL_TRIANGLE_UP: - case ZR_SYMBOL_TRIANGLE_DOWN: - case ZR_SYMBOL_TRIANGLE_LEFT: - case ZR_SYMBOL_TRIANGLE_RIGHT: { - enum zr_heading heading; - struct zr_vec2 points[3]; - heading = (sym->type == ZR_SYMBOL_TRIANGLE_RIGHT) ? ZR_RIGHT : - (sym->type == ZR_SYMBOL_TRIANGLE_LEFT) ? ZR_LEFT: - (sym->type == ZR_SYMBOL_TRIANGLE_UP) ? ZR_UP: ZR_DOWN; - zr_triangle_from_direction(points, content, 0, 0, heading); - zr_draw_triangle(out, ZR_FILLED, points[0].x, points[0].y, - points[1].x, points[1].y, points[2].x, points[2].y, sym->foreground); - } break; - default: - case ZR_SYMBOL_MAX: break; - } -} - -static int -zr_button_behavior(zr_flags *state, struct zr_rect r, - const struct zr_input *i, enum zr_button_behavior behavior) -{ - int ret = 0; - *state = ZR_INACTIVE; - if (!i) return 0; - if (zr_input_is_mouse_hovering_rect(i, r)) { - *state = ZR_HOVERED; - if (zr_input_is_mouse_down(i, ZR_BUTTON_LEFT)) - *state = ZR_ACTIVE; - if (zr_input_has_mouse_click_in_rect(i, ZR_BUTTON_LEFT, r)) { - ret = (behavior != ZR_BUTTON_DEFAULT) ? - zr_input_is_mouse_down(i, ZR_BUTTON_LEFT): - zr_input_is_mouse_released(i, ZR_BUTTON_LEFT); - } - } - if (*state == ZR_HOVERED && !zr_input_is_mouse_prev_hovering_rect(i, r)) - *state |= ZR_ENTER; - else if (zr_input_is_mouse_prev_hovering_rect(i, r)) - *state |= ZR_LEAVE; - return ret; -} - -static void -zr_button_draw(struct zr_command_buffer *o, struct zr_rect r, - const struct zr_button *b, zr_flags state) -{ - struct zr_color background; - if (state & ZR_HOVERED) - background = b->hover; - else if (state & ZR_ACTIVE) - background = b->active; - else background = b->normal; - - zr_draw_rect(o, ZR_FILLED, r, b->rounding, b->border); - zr_draw_rect(o, ZR_FILLED, zr_shrink_rect(r, b->border_width), - b->rounding, background); -} - -static int -zr_do_button(zr_flags *state, - struct zr_command_buffer *o, struct zr_rect r, - const struct zr_button *b, const struct zr_input *i, - enum zr_button_behavior behavior, struct zr_rect *content) -{ - int ret = zr_false; - struct zr_vec2 pad; - struct zr_rect bounds; - ZR_ASSERT(b); - if (!o || !b) - return zr_false; - - /* calculate button content space */ - pad.x = b->padding.x + b->border_width; - pad.y = b->padding.y + b->border_width; - *content = zr_pad_rect(r, pad); - - /* execute and draw button */ - bounds.x = r.x - b->touch_pad.x; - bounds.y = r.y - b->touch_pad.y; - bounds.w = r.w + 2 * b->touch_pad.x; - bounds.h = r.h + 2 * b->touch_pad.y; - ret = zr_button_behavior(state, bounds, i, behavior); - zr_button_draw(o, r, b, *state); - return ret; -} - -static int -zr_do_button_text(zr_flags *state, - struct zr_command_buffer *o, struct zr_rect r, - const char *string, enum zr_button_behavior behavior, - const struct zr_button_text *b, const struct zr_input *i, - const struct zr_user_font *f) -{ - struct zr_text t; - struct zr_rect content; - int ret = zr_false; - - ZR_ASSERT(b); - ZR_ASSERT(o); - ZR_ASSERT(string); - ZR_ASSERT(f); - if (!o || !b || !f) - return zr_false; - - ret = zr_do_button(state, o, r, &b->base, i, behavior, &content); - if (*state & ZR_HOVERED) { - t.background = b->base.hover; - t.text = b->hover; - } else if (*state & ZR_ACTIVE) { - t.background = b->base.active; - t.text = b->active; - } else { - t.background = b->base.normal; - t.text = b->normal; - } - - t.padding = zr_vec2(0,0); - zr_widget_text(o, content, string, zr_strsiz(string), &t, b->alignment, f); - return ret; -} - -static int -zr_do_button_symbol(zr_flags *state, - struct zr_command_buffer *out, struct zr_rect r, - enum zr_symbol_type symbol, enum zr_button_behavior bh, - const struct zr_button_symbol *b, const struct zr_input *in, - const struct zr_user_font *font) -{ - int ret; - struct zr_symbol sym; - struct zr_color background; - struct zr_color color; - struct zr_rect content; - - ZR_ASSERT(b); - ZR_ASSERT(out); - if (!out || !b) - return zr_false; - - ret = zr_do_button(state, out, r, &b->base, in, bh, &content); - if (*state & ZR_HOVERED) { - background = b->base.hover; - color = b->hover; - } else if (*state & ZR_ACTIVE) { - background = b->base.active; - color = b->active; - } else { - background = b->base.normal; - color = b->normal; - } - - sym.type = symbol; - sym.background = background; - sym.foreground = color; - sym.border_width = b->base.border_width; - zr_draw_symbol(out, &sym, content, font); - return ret; -} - -static int -zr_do_button_image(zr_flags *state, - struct zr_command_buffer *out, struct zr_rect r, - struct zr_image img, enum zr_button_behavior b, - const struct zr_button_icon *button, const struct zr_input *in) -{ - int pressed; - struct zr_rect bounds; - - ZR_ASSERT(button); - ZR_ASSERT(out); - if (!out || !button) - return zr_false; - - pressed = zr_do_button(state, out, r, &button->base, in, b, &bounds); - zr_draw_image(out, bounds, &img); - return pressed; -} - -static int -zr_do_button_text_symbol(zr_flags *state, - struct zr_command_buffer *out, struct zr_rect r, - enum zr_symbol_type symbol, const char *text, zr_flags align, - enum zr_button_behavior behavior, const struct zr_button_text *b, - const struct zr_user_font *f, const struct zr_input *i) -{ - int ret; - struct zr_rect tri = {0,0,0,0}; - struct zr_color background; - struct zr_color color; - struct zr_symbol sym; - - ZR_ASSERT(b); - ZR_ASSERT(out); - if (!out || !b) - return zr_false; - - ret = zr_do_button_text(state, out, r, text, behavior, b, i, f); - if (*state & ZR_HOVERED) { - background = b->base.hover; - color = b->hover; - } else if (*state & ZR_ACTIVE) { - background = b->base.active; - color = b->active; - } else { - background = b->base.normal; - color = b->normal; - } - - /* calculate symbol bounds */ - tri.y = r.y + (r.h/2) - f->height/2; - tri.w = f->height; tri.h = f->height; - if (align & ZR_TEXT_LEFT) { - tri.x = (r.x + r.w) - (2 * b->base.padding.x + tri.w); - tri.x = ZR_MAX(tri.x, 0); - } else tri.x = r.x + 2 * b->base.padding.x; - - sym.type = symbol; - sym.background = background; - sym.foreground = color; - sym.border_width = 1.0f; - zr_draw_symbol(out, &sym, tri, f); - return ret; -} - -static int -zr_do_button_text_image(zr_flags *state, - struct zr_command_buffer *out, struct zr_rect r, - struct zr_image img, const char* text, zr_flags align, - enum zr_button_behavior behavior, const struct zr_button_text *b, - const struct zr_user_font *f, const struct zr_input *i) -{ - int pressed; - struct zr_rect icon; - ZR_ASSERT(b); - ZR_ASSERT(out); - if (!out || !b) - return zr_false; - - pressed = zr_do_button_text(state, out, r, text, behavior, b, i, f); - icon.y = r.y + b->base.padding.y; - icon.w = icon.h = r.h - 2 * b->base.padding.y; - if (align & ZR_TEXT_LEFT) { - icon.x = (r.x + r.w) - (2 * b->base.padding.x + icon.w); - icon.x = ZR_MAX(icon.x, 0); - } else icon.x = r.x + 2 * b->base.padding.x; - zr_draw_image(out, icon, &img); - return pressed; -} - -/* =============================================================== - * - * TOGGLE - * - * ===============================================================*/ -enum zr_toggle_type { - ZR_TOGGLE_CHECK, - ZR_TOGGLE_OPTION -}; - -struct zr_toggle { - float rounding; - struct zr_vec2 touch_pad; - struct zr_vec2 padding; - struct zr_color font; - struct zr_color font_background; - struct zr_color background; - struct zr_color normal; - struct zr_color hover; - struct zr_color cursor; -}; - -static int -zr_toggle_behavior(const struct zr_input *in, struct zr_rect select, - zr_flags *state, int active) -{ - *state = ZR_INACTIVE; - if (in && zr_input_is_mouse_hovering_rect(in, select)) - *state = ZR_HOVERED; - if (zr_input_mouse_clicked(in, ZR_BUTTON_LEFT, select)) { - *state = ZR_ACTIVE; - active = !active; - } - if (*state == ZR_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, select)) - *state |= ZR_ENTER; - else if (zr_input_is_mouse_prev_hovering_rect(in, select)) - *state |= ZR_LEAVE; - return active; -} - -static void -zr_toggle_draw(struct zr_command_buffer *out, - zr_flags state, - const struct zr_toggle *toggle, int active, - enum zr_toggle_type type, struct zr_rect r, - const char *string, const struct zr_user_font *font) -{ - float cursor_pad; - struct zr_color col; - struct zr_rect select; - struct zr_rect cursor; - - select.w = ZR_MIN(r.h, font->height + toggle->padding.y); - select.h = select.w; - select.x = r.x + toggle->padding.x; - select.y = (r.y + toggle->padding.y + (select.w / 2)) - (font->height / 2); - cursor_pad = (type == ZR_TOGGLE_OPTION) ? - (float)(int)(select.w / 4): - (float)(int)(select.h / 6); - - /* calculate the bounds of the cursor inside the toggle */ - select.h = ZR_MAX(select.w, cursor_pad * 2); - cursor.h = select.h - cursor_pad * 2; - cursor.w = cursor.h; - cursor.x = select.x + cursor_pad; - cursor.y = select.y + cursor_pad; - - if (state & ZR_HOVERED || state & ZR_ACTIVE) - col = toggle->hover; - else col = toggle->normal; - - /* draw radiobutton/checkbox background */ - if (type == ZR_TOGGLE_CHECK) - zr_draw_rect(out, ZR_FILLED, select , toggle->rounding, col); - else zr_draw_circle(out, ZR_FILLED, select, col); - - /* draw radiobutton/checkbox cursor if active */ - if (active) { - if (type == ZR_TOGGLE_CHECK) - zr_draw_rect(out, ZR_FILLED, cursor, toggle->rounding, toggle->cursor); - else zr_draw_circle(out, ZR_FILLED, cursor, toggle->cursor); - } - - /* draw toggle text */ - if (string) { - struct zr_text text; - struct zr_rect inner; - - /* calculate text bounds */ - inner.x = r.x + select.w + toggle->padding.x * 2; - inner.y = select.y; - inner.w = ZR_MAX(r.x + r.w, inner.x + toggle->padding.x); - inner.w -= (inner.x + toggle->padding.x); - inner.h = select.w; - - /* draw text */ - text.padding.x = 0; - text.padding.y = 0; - text.background = toggle->font_background; - text.text = toggle->font; - zr_widget_text(out, inner, string, zr_strsiz(string), - &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - } -} - -static void -zr_do_toggle(zr_flags *state, - struct zr_command_buffer *out, struct zr_rect r, - int *active, const char *string, enum zr_toggle_type type, - const struct zr_toggle *toggle, const struct zr_input *in, - const struct zr_user_font *font) -{ - struct zr_rect bounds; - ZR_ASSERT(toggle); - ZR_ASSERT(out); - ZR_ASSERT(font); - if (!out || !toggle || !font || !active) - return; - - r.w = ZR_MAX(r.w, font->height + 2 * toggle->padding.x); - r.h = ZR_MAX(r.h, font->height + 2 * toggle->padding.y); - - bounds.x = r.x - toggle->touch_pad.x; - bounds.y = r.y - toggle->touch_pad.y; - bounds.w = r.w + 2 * toggle->touch_pad.x; - bounds.h = r.h + 2 * toggle->touch_pad.y; - - *active = zr_toggle_behavior(in, bounds, state, *active); - zr_toggle_draw(out, *state, toggle, *active, type, r, string, font); -} - -/* =============================================================== - * - * SLIDER - * - * ===============================================================*/ -struct zr_slider { - struct zr_vec2 padding; - struct zr_color border; - struct zr_color bg; - struct zr_color normal; - struct zr_color hover; - struct zr_color active; - float rounding; -}; - -static float -zr_slider_behavior(zr_flags *state, struct zr_rect *cursor, - const struct zr_input *in, const struct zr_slider *s, struct zr_rect slider, - float slider_min, float slider_max, float slider_value, - float slider_step, float slider_steps) -{ - int inslider = in && zr_input_is_mouse_hovering_rect(in, slider); - int incursor = in && zr_input_has_mouse_click_down_in_rect(in, ZR_BUTTON_LEFT, slider, zr_true); - - *state = (inslider) ? ZR_HOVERED: ZR_INACTIVE; - if (in && inslider && incursor) - { - const float d = in->mouse.pos.x - (cursor->x + cursor->w / 2.0f); - const float pxstep = (slider.w - (2 * s->padding.x)) / slider_steps; - - /* only update value if the next slider step is reached */ - *state = ZR_ACTIVE; - if (ZR_ABS(d) >= pxstep) { - float ratio = 0; - const float steps = (float)((int)(ZR_ABS(d) / pxstep)); - slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps); - slider_value = ZR_CLAMP(slider_min, slider_value, slider_max); - ratio = (slider_value - slider_min)/slider_step; - cursor->x = slider.x + (cursor->w * ratio); - } - } - if (*state == ZR_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, slider)) - *state |= ZR_ENTER; - else if (zr_input_is_mouse_prev_hovering_rect(in, slider)) - *state |= ZR_LEAVE; - return slider_value; -} - -static void -zr_slider_draw(struct zr_command_buffer *out, - zr_flags state, const struct zr_slider *s, - struct zr_rect bar, struct zr_rect cursor, - float slider_min, float slider_max, float slider_value) -{ - struct zr_rect fill; - struct zr_color col; - if (state & ZR_HOVERED) - col = s->hover; - else if (state & ZR_ACTIVE) - col = s->active; - else col = s->normal; - - cursor.w = cursor.h; - cursor.x = (slider_value <= slider_min) ? cursor.x: - (slider_value >= slider_max) ? ((bar.x + bar.w) - cursor.w) : - cursor.x - (cursor.w/2); - - fill.x = bar.x; - fill.y = bar.y; - fill.w = (cursor.x + (cursor.w/2.0f)) - bar.x; - fill.h = bar.h; - - zr_draw_rect(out, ZR_FILLED, bar, 0, s->bg); - zr_draw_rect(out, ZR_FILLED, fill, 0, col); - zr_draw_circle(out, ZR_FILLED, cursor, col); -} - -static float -zr_do_slider(zr_flags *state, - struct zr_command_buffer *out, struct zr_rect slider, - float min, float val, float max, float step, - const struct zr_slider *s, const struct zr_input *in) -{ - float slider_range; - float slider_min; - float slider_max; - float slider_value; - float slider_steps; - float cursor_offset; - struct zr_rect cursor; - struct zr_rect bar; - - ZR_ASSERT(s); - ZR_ASSERT(out); - if (!out || !s) - return 0; - - /* make sure the provided values are correct */ - slider.x = slider.x + s->padding.x; - slider.y = slider.y + s->padding.y; - slider.h = ZR_MAX(slider.h, 2 * s->padding.y); - slider.w = ZR_MAX(slider.w, 1 + slider.h + 2 * s->padding.x); - slider.h -= 2 * s->padding.y; - slider.w -= 2 * s->padding.y; - - slider_max = ZR_MAX(min, max); - slider_min = ZR_MIN(min, max); - slider_value = ZR_CLAMP(slider_min, val, slider_max); - slider_range = slider_max - slider_min; - slider_steps = slider_range / step; - - /* calculate slider virtual cursor bounds */ - cursor_offset = (slider_value - slider_min) / step; - cursor.h = slider.h; - cursor.w = slider.w / (slider_steps + 1); - cursor.x = slider.x + (cursor.w * cursor_offset); - cursor.y = slider.y; - - /* calculate slider background bar bounds */ - bar.x = slider.x; - bar.y = (slider.y + cursor.h/2) - cursor.h/8; - bar.w = slider.w; - bar.h = slider.h/4; - - slider_value = zr_slider_behavior(state, &cursor, in, s, slider, - slider_min, slider_max, slider_value, step, slider_steps); - zr_slider_draw(out, *state, s, bar, cursor, slider_min, - slider_max, slider_value); - return slider_value; -} - -/* =============================================================== - * - * PROGRESSBAR - * - * ===============================================================*/ -struct zr_progress { - struct zr_vec2 padding; - struct zr_color border; - struct zr_color background; - struct zr_color normal; - struct zr_color hover; - struct zr_color active; -}; - -static zr_size -zr_progress_behavior(zr_flags *state, const struct zr_input *in, - struct zr_rect r, zr_size max, zr_size value, int modifiable) -{ - *state = ZR_INACTIVE; - if (in && modifiable && zr_input_is_mouse_hovering_rect(in, r)) { - if (zr_input_is_mouse_down(in, ZR_BUTTON_LEFT)) { - float ratio = ZR_MAX(0, (float)(in->mouse.pos.x - r.x)) / (float)r.w; - value = (zr_size)ZR_MAX(0,((float)max * ratio)); - *state = ZR_ACTIVE; - } else *state = ZR_HOVERED; - } - if (*state == ZR_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, r)) - *state |= ZR_ENTER; - else if (zr_input_is_mouse_prev_hovering_rect(in, r)) - *state |= ZR_LEAVE; - - if (!max) return value; - value = ZR_MIN(value, max); - return value; -} - -static void -zr_progress_draw(struct zr_command_buffer *out, const struct zr_progress *p, - zr_flags state, struct zr_rect r, zr_size max, zr_size value) -{ - float prog_scale; - struct zr_color col; - if (state & ZR_HOVERED) - col = p->hover; - else if (state & ZR_ACTIVE) - col = p->active; - else col = p->normal; - - prog_scale = (float)value / (float)max; - zr_draw_rect(out, ZR_FILLED, r, 0, p->background); - r.w = (r.w - 2) * prog_scale; - zr_draw_rect(out, ZR_FILLED, r, 0, col); -} - -static zr_size -zr_do_progress(zr_flags *state, - struct zr_command_buffer *out, struct zr_rect r, - zr_size value, zr_size max, int modifiable, - const struct zr_progress *prog, const struct zr_input *in) -{ - zr_size prog_value; - ZR_ASSERT(prog); - ZR_ASSERT(out); - if (!out || !prog) return 0; - - r.w = ZR_MAX(r.w, 2 * prog->padding.x); - r.h = ZR_MAX(r.h, 2 * prog->padding.y); - r = zr_pad_rect(r, zr_vec2(prog->padding.x, prog->padding.y)); - - prog_value = ZR_MIN(value, max); - prog_value = zr_progress_behavior(state, in, r, max, prog_value, modifiable); - zr_progress_draw(out, prog, *state, r, max, value); - return prog_value; -} - -/* =============================================================== - * - * SCROLLBAR - * - * ===============================================================*/ -struct zr_scrollbar { - float rounding; - struct zr_color border; - struct zr_color background; - struct zr_color normal; - struct zr_color hover; - struct zr_color active; - int has_scrolling; -}; - -static float -zr_scrollbar_behavior(zr_flags *state, struct zr_input *in, - const struct zr_scrollbar *s, struct zr_rect scroll, - struct zr_rect cursor, float scroll_offset, - float target, float scroll_step, enum zr_orientation o) -{ - int left_mouse_down; - int left_mouse_click_in_cursor; - if (!in) return scroll_offset; - - *state = ZR_INACTIVE; - left_mouse_down = in->mouse.buttons[ZR_BUTTON_LEFT].down; - left_mouse_click_in_cursor = zr_input_has_mouse_click_down_in_rect(in, - ZR_BUTTON_LEFT, cursor, zr_true); - if (zr_input_is_mouse_hovering_rect(in, cursor)) - *state = ZR_HOVERED; - - if (left_mouse_down && left_mouse_click_in_cursor) { - /* update cursor by mouse dragging */ - float pixel, delta; - *state = ZR_ACTIVE; - if (o == ZR_VERTICAL) { - pixel = in->mouse.delta.y; - delta = (pixel / scroll.h) * target; - scroll_offset = ZR_CLAMP(0, scroll_offset + delta, target - scroll.h); - /* This is probably one of my most disgusting hacks I have ever done. - * This basically changes the mouse clicked position with the moving - * cursor. This allows for better scroll behavior but resulted into me - * having to remove const correctness for input. But in the end I believe - * it is worth it. */ - in->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y; - } else { - pixel = in->mouse.delta.x; - delta = (pixel / scroll.w) * target; - scroll_offset = ZR_CLAMP(0, scroll_offset + delta, target - scroll.w); - in->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x; - } - } else if (s->has_scrolling && ((in->mouse.scroll_delta<0) || - (in->mouse.scroll_delta>0))) { - /* update cursor by mouse scrolling */ - scroll_offset = scroll_offset + scroll_step * (-in->mouse.scroll_delta); - if (o == ZR_VERTICAL) - scroll_offset = ZR_CLAMP(0, scroll_offset, target - scroll.h); - else scroll_offset = ZR_CLAMP(0, scroll_offset, target - scroll.w); - } - if (*state == ZR_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, scroll)) - *state |= ZR_ENTER; - else if (zr_input_is_mouse_prev_hovering_rect(in, scroll)) - *state |= ZR_LEAVE; - return scroll_offset; -} - -static void -zr_scrollbar_draw(struct zr_command_buffer *out, const struct zr_scrollbar *s, - zr_flags state, struct zr_rect scroll, struct zr_rect cursor) -{ - struct zr_color col; - if (state & ZR_HOVERED) - col = s->hover; - else if (state & ZR_ACTIVE) - col = s->active; - else col = s->normal; - - zr_draw_rect(out, ZR_FILLED, zr_shrink_rect(scroll,1), s->rounding, s->border); - zr_draw_rect(out, ZR_FILLED, scroll, s->rounding, s->background); - zr_draw_rect(out, ZR_FILLED, cursor, s->rounding, col); -} - -static float -zr_do_scrollbarv(zr_flags *state, - struct zr_command_buffer *out, struct zr_rect scroll, - float offset, float target, float step, const struct zr_scrollbar *s, - struct zr_input *i) -{ - struct zr_rect cursor; - float scroll_step; - float scroll_offset; - float scroll_off; - float scroll_ratio; - - ZR_ASSERT(out); - ZR_ASSERT(s); - ZR_ASSERT(state); - if (!out || !s) return 0; - - /* scrollbar background */ - scroll.w = ZR_MAX(scroll.w, 1); - scroll.h = ZR_MAX(scroll.h, 2 * scroll.w); - if (target <= scroll.h) return 0; - - /* calculate scrollbar constants */ - scroll_step = ZR_MIN(step, scroll.h); - scroll_offset = ZR_MIN(offset, target - scroll.h); - scroll_ratio = scroll.h / target; - scroll_off = scroll_offset / target; - - /* calculate scrollbar cursor bounds */ - cursor.h = (scroll_ratio * scroll.h - 2); - cursor.y = scroll.y + (scroll_off * scroll.h) + 1; - cursor.w = scroll.w - 2; - cursor.x = scroll.x + 1; - - /* draw scrollbar */ - scroll_offset = zr_scrollbar_behavior(state, i, s, scroll, cursor, - scroll_offset, target, scroll_step, ZR_VERTICAL); - scroll_off = scroll_offset / target; - cursor.y = scroll.y + (scroll_off * scroll.h); - zr_scrollbar_draw(out, s, *state, scroll, cursor); - return scroll_offset; -} - -static float -zr_do_scrollbarh(zr_flags *state, - struct zr_command_buffer *out, struct zr_rect scroll, - float offset, float target, float step, const struct zr_scrollbar *s, - struct zr_input *i) -{ - struct zr_rect cursor; - float scroll_step; - float scroll_offset; - float scroll_off; - float scroll_ratio; - - ZR_ASSERT(out); - ZR_ASSERT(s); - if (!out || !s) return 0; - - /* scrollbar background */ - scroll.h = ZR_MAX(scroll.h, 1); - scroll.w = ZR_MAX(scroll.w, 2 * scroll.h); - if (target <= scroll.w) return 0; - - /* calculate scrollbar constants */ - scroll_step = ZR_MIN(step, scroll.w); - scroll_offset = ZR_MIN(offset, target - scroll.w); - scroll_ratio = scroll.w / target; - scroll_off = scroll_offset / target; - - /* calculate scrollbar cursor bounds */ - cursor.w = scroll_ratio * scroll.w - 2; - cursor.x = scroll.x + (scroll_off * scroll.w) + 1; - cursor.h = scroll.h - 2; - cursor.y = scroll.y + 1; - - /* draw scrollbar */ - scroll_offset = zr_scrollbar_behavior(state, i, s, scroll, cursor, - scroll_offset, target, scroll_step, ZR_HORIZONTAL); - scroll_off = scroll_offset / target; - cursor.x = scroll.x + (scroll_off * scroll.w); - zr_scrollbar_draw(out, s, *state, scroll, cursor); - return scroll_offset; -} - -/* =============================================================== - * - * EDIT - * - * ===============================================================*/ -struct zr_edit { - int modifiable; - float border_size; - float rounding; - float scrollbar_width; - struct zr_vec2 padding; - int show_cursor; - struct zr_color background; - struct zr_color border; - struct zr_color cursor; - struct zr_color text; - struct zr_scrollbar scroll; -}; - -static void -zr_edit_box_handle_input(struct zr_edit_box *box, const struct zr_input *in, - int has_special) -{ - char *buffer = zr_edit_box_get(box); - zr_size len = zr_edit_box_len_char(box); - zr_size min = ZR_MIN(box->sel.end, box->sel.begin); - zr_size maxi = ZR_MAX(box->sel.end, box->sel.begin); - zr_size diff = maxi - min; - int enter, tab; - - /* text manipulation */ - if (zr_input_is_key_pressed(in,ZR_KEY_DEL)) - zr_edit_box_remove(box, ZR_DELETE); - else if (zr_input_is_key_pressed(in,ZR_KEY_BACKSPACE)) - zr_edit_box_remove(box, ZR_REMOVE); - - enter = has_special && zr_input_is_key_pressed(in, ZR_KEY_ENTER); - tab = has_special && zr_input_is_key_pressed(in, ZR_KEY_TAB); - if (in->keyboard.text_len || enter || tab) { - if (diff && box->cursor != box->glyphs) { - /* replace text selection */ - zr_edit_box_remove(box, ZR_DELETE); - box->cursor = min; - } - if (enter) zr_edit_box_add(box, "\n", 1); - else if (tab) zr_edit_box_add(box, " ", 4); - else zr_edit_box_buffer_input(box, in); - box->sel.begin = box->cursor; - box->sel.end = box->cursor; - } - - /* cursor key movement */ - if (zr_input_is_key_pressed(in, ZR_KEY_LEFT)) { - box->cursor = (zr_size)(ZR_MAX(0, (int)box->cursor - 1)); - box->sel.begin = box->cursor; - box->sel.end = box->cursor; - } - if (zr_input_is_key_pressed(in, ZR_KEY_RIGHT) && box->cursor < box->glyphs) { - box->cursor = ZR_MIN((!box->glyphs) ? 0 : box->glyphs, box->cursor + 1); - box->sel.begin = box->cursor; - box->sel.end = box->cursor; - } - - /* copy & cut & paste functionlity */ - if (zr_input_is_key_pressed(in, ZR_KEY_PASTE) && box->clip.paste) - box->clip.paste(box->clip.userdata, box); - - if ((zr_input_is_key_pressed(in, ZR_KEY_COPY) && box->clip.copy) || - (zr_input_is_key_pressed(in, ZR_KEY_CUT) && box->clip.copy)) { - if (diff && box->cursor != box->glyphs) { - /* copy or cut text selection */ - zr_size l; - zr_rune unicode; - char *begin, *end; - begin = zr_edit_buffer_at(&box->buffer, (int)min, &unicode, &l); - end = zr_edit_buffer_at(&box->buffer, (int)maxi, &unicode, &l); - box->clip.copy(box->clip.userdata, begin, (zr_size)(end - begin)); - if (zr_input_is_key_pressed(in, ZR_KEY_CUT)) - zr_edit_box_remove(box, ZR_DELETE); - } else { - /* copy or cut complete buffer */ - box->clip.copy(box->clip.userdata, buffer, len); - if (zr_input_is_key_pressed(in, ZR_KEY_CUT)) - zr_edit_box_clear(box); - } - } -} - -static void -zr_widget_edit_field(struct zr_command_buffer *out, struct zr_rect r, - struct zr_edit_box *box, const struct zr_edit *field, - const struct zr_input *in, const struct zr_user_font *font) -{ - char *buffer; - zr_size len; - struct zr_text text; - - ZR_ASSERT(out); - ZR_ASSERT(font); - ZR_ASSERT(field); - if (!out || !box || !field) - return; - - r.w = ZR_MAX(r.w, 2 * field->padding.x + 2 * field->border_size); - r.h = ZR_MAX(r.h, font->height + (2 * field->padding.y + 2 * field->border_size)); - - /* draw editbox background and border */ - zr_draw_rect(out, ZR_FILLED, r, field->rounding, field->border); - zr_draw_rect(out, ZR_FILLED, zr_shrink_rect(r, field->border_size), - field->rounding, field->background); - - /* check if the editbox is activated/deactivated */ - if (in && in->mouse.buttons[ZR_BUTTON_LEFT].clicked && - in->mouse.buttons[ZR_BUTTON_LEFT].down) - box->active = ZR_INBOX(in->mouse.pos.x,in->mouse.pos.y,r.x,r.y,r.w,r.h); - - /* input handling */ - if (box->active && in) - zr_edit_box_handle_input(box, in, 0); - - buffer = zr_edit_box_get(box); - len = zr_edit_box_len_char(box); - { - /* text management */ - struct zr_rect label; - zr_size cursor_w = font->width(font->userdata,font->height,"X", 1); - zr_size text_len = len; - zr_size glyph_off = 0; - zr_size glyph_cnt = 0; - zr_size offset = 0; - float text_width = 0; - - /* calculate text frame */ - label.w = ZR_MAX(r.w, - 2 * field->padding.x - 2 * field->border_size); - label.w -= 2 * field->padding.x - 2 * field->border_size; - { - zr_size frames = 0; - zr_size glyphs = 0; - zr_size frame_len = 0; - zr_size row_len = 0; - float space = ZR_MAX(label.w, (float)cursor_w); - space -= (float)cursor_w; - - while (text_len) { - frames++; - offset += frame_len; - frame_len = zr_user_font_glyphs_fitting_in_space(font, - &buffer[offset], text_len, space, &row_len, &glyphs, &text_width, 0); - glyph_off += glyphs; - if (glyph_off > box->cursor || !frame_len) break; - text_len -= frame_len; - } - - text_len = frame_len; - glyph_cnt = glyphs; - glyph_off = (frames <= 1) ? 0 : (glyph_off - glyphs); - offset = (frames <= 1) ? 0 : offset; - } - - /* set cursor by mouse click and handle text selection */ - if (in && field->show_cursor && in->mouse.buttons[ZR_BUTTON_LEFT].down && box->active) { - const char *visible = &buffer[offset]; - float xoff = in->mouse.pos.x - (r.x + field->padding.x + field->border_size); - if (ZR_INBOX(in->mouse.pos.x, in->mouse.pos.y, r.x, r.y, r.w, r.h)) - { - /* text selection in the current text frame */ - zr_size glyph_index; - zr_size glyph_pos=zr_user_font_glyph_index_at_pos(font,visible,text_len,xoff); - if (glyph_cnt + glyph_off >= box->glyphs) - glyph_index = glyph_off + ZR_MIN(glyph_pos, glyph_cnt); - else glyph_index = glyph_off + ZR_MIN(glyph_pos, glyph_cnt-1); - - if (text_len) - zr_edit_box_set_cursor(box, glyph_index); - if (!box->sel.active) { - box->sel.active = zr_true; - box->sel.begin = glyph_index; - box->sel.end = box->sel.begin; - } else { - if (box->sel.begin > glyph_index) { - box->sel.end = glyph_index; - box->sel.active = zr_true; - } - } - } else if (!ZR_INBOX(in->mouse.pos.x,in->mouse.pos.y,r.x,r.y,r.w,r.h) && - ZR_INBOX(in->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.x, - in->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.y,r.x,r.y,r.w,r.h) - && box->cursor != box->glyphs && box->cursor > 0) - { - /* text selection out of the current text frame */ - zr_size glyph = ((in->mouse.pos.x > r.x) && - box->cursor+1 < box->glyphs) ? - box->cursor+1: box->cursor-1; - zr_edit_box_set_cursor(box, glyph); - if (box->sel.active) { - box->sel.end = glyph; - box->sel.active = zr_true; - } - } else box->sel.active = zr_false; - } else box->sel.active = zr_false; - - /* calculate the text bounds */ - label.x = r.x + field->padding.x + field->border_size; - label.y = r.y + field->padding.y + field->border_size; - label.h = r.h - (2 * field->padding.y + 2 * field->border_size); - - text.padding = zr_vec2(0,0); - text.background = field->background; - text.text = field->text; - zr_widget_text(out, label, &buffer[offset], text_len, - &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - - /* draw selected text */ - if (box->active && field->show_cursor) { - if (box->cursor == box->glyphs) { - /* draw the cursor at the end of the string */ - zr_size s = font->width(font->userdata, font->height, - buffer + offset, text_len); - text_width = (float)s; - zr_draw_rect(out, ZR_FILLED, zr_rect(label.x+(float)text_width, - label.y, (float)cursor_w, label.h), 0, field->cursor); - } else { - /* draw text selection */ - zr_size l = 0, s; - zr_rune unicode; - char *begin, *end; - zr_size off_begin, off_end; - zr_size min = ZR_MIN(box->sel.end, box->sel.begin); - zr_size maxi = ZR_MAX(box->sel.end, box->sel.begin); - struct zr_rect clip = out->clip; - - /* calculate selection text range */ - begin = zr_edit_buffer_at(&box->buffer, (int)min, &unicode, &l); - end = zr_edit_buffer_at(&box->buffer, (int)maxi, &unicode, &l); - off_begin = (zr_size)(begin - (char*)box->buffer.memory.ptr); - off_end = (zr_size)(end - (char*)box->buffer.memory.ptr); - - /* calculate selected text width */ - zr_draw_scissor(out, label); - s = font->width(font->userdata, font->height, buffer + offset, off_begin - offset); - label.x += (float)s; - s = font->width(font->userdata, font->height, begin, ZR_MAX(l, off_end - off_begin)); - label.w = (float)s; - - /* draw selected text */ - zr_draw_rect(out, ZR_FILLED, label, 0, field->text); - text.padding = zr_vec2(0,0); - text.background = field->text; - text.text = field->background; - zr_widget_text(out, label, begin, ZR_MAX(l, off_end - off_begin), - &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - zr_draw_scissor(out, clip); - } - } - } -} - -static void -zr_widget_edit_box(struct zr_command_buffer *out, struct zr_rect r, - struct zr_edit_box *box, const struct zr_edit *field, - struct zr_input *in, const struct zr_user_font *font) -{ - char *buffer; - zr_size len; - zr_size visible_rows = 0; - zr_size total_rows = 0; - zr_size cursor_w; - int prev_state; - - float total_width = 0; - float total_height = 0; - zr_size row_height = 0; - - ZR_ASSERT(out); - ZR_ASSERT(font); - ZR_ASSERT(field); - if (!out || !box || !field) - return; - - /* calculate usable field space */ - r.w = ZR_MAX(r.w, 2 * field->padding.x + 2 * field->border_size); - r.h = ZR_MAX(r.h, font->height + (2 * field->padding.y + 2 * field->border_size)); - - total_width = r.w - (2 * field->padding.x + 2 * field->border_size); - total_width -= field->scrollbar_width; - row_height = (zr_size)(font->height + field->padding.y); - - /* draw edit field background and border */ - zr_draw_rect(out, ZR_FILLED, r, field->rounding, field->border); - zr_draw_rect(out, ZR_FILLED, zr_shrink_rect(r, field->border_size), - field->rounding, field->background); - - /* check if edit box is big enough to show even a single row */ - visible_rows = (zr_size)(r.h - (2 * field->border_size + 2 * field->padding.y)); - visible_rows = (zr_size)((float)visible_rows / (font->height + field->padding.y)); - if (!visible_rows) return; - - /* check if editbox is activated/deactivated */ - prev_state = box->active; - if (in && in->mouse.buttons[ZR_BUTTON_LEFT].clicked && - in->mouse.buttons[ZR_BUTTON_LEFT].down) - box->active = ZR_INBOX(in->mouse.pos.x,in->mouse.pos.y,r.x,r.y,r.w,r.h); - - /* text input handling */ - if (box->active && in && field->modifiable) - zr_edit_box_handle_input(box, in, 1); - - buffer = zr_edit_box_get(box); - len = zr_edit_box_len_char(box); - cursor_w = font->width(font->userdata,font->height,(const char*)"X", 1); - { - /* calulate total number of needed rows */ - zr_size glyphs = 0; - zr_size row_off = 0; - zr_size text_len = len; - zr_size offset = 0; - zr_size row_len; - - float space = total_width; - float text_width = 0; - - while (text_len) { - total_rows++; - offset += row_off; - row_off = zr_user_font_glyphs_fitting_in_space(font, - &buffer[offset], text_len, space, &row_len, &glyphs, &text_width, 1); - if (!row_off){ - text_len = 0; - } else text_len -= row_off; - } - total_height = (float)total_rows * (float)row_height; - } - - if (!box->active || (!prev_state && box->active)) { - /* make sure edit box points to the end of the buffer if not active */ - if (total_rows > visible_rows) - box->scrollbar = (float)((total_rows - visible_rows) * row_height); - if (!prev_state && box->active) { - box->cursor = zr_utf_len(buffer, len); - box->sel.begin = box->cursor; - box->sel.end = box->cursor; - } - } - - if ((in && in->keyboard.text_len && total_rows >= visible_rows && box->active) || - box->sel.active || (box->text_inserted && total_rows >= visible_rows)) - { - /* make sure cursor is always in current visible field while writing */ - box->text_inserted = 0; - if (box->cursor == box->glyphs && !box->sel.active) { - /* cursor is at end of text and out of visible frame */ - float row_offset = (float)(total_rows - visible_rows); - box->scrollbar = (font->height + field->padding.x) * row_offset; - } else { - /* cursor is inside text and out of visible frame */ - float text_width; - zr_size cur_row = 0; - zr_size glyphs = 0; - zr_size row_off = 0; - zr_size row_len = 0; - zr_size text_len = len; - zr_size offset = 0, glyph_off = 0; - zr_size cursor = ZR_MIN(box->sel.end, box->sel.begin); - zr_size scroll_offset = (zr_size)(box->scrollbar / (float)row_height); - - /* find cursor row */ - while (text_len) { - offset += row_off; - row_off = zr_user_font_glyphs_fitting_in_space(font, - &buffer[offset], text_len, total_width, &row_len, &glyphs, &text_width, 1); - if ((cursor >= glyph_off && cursor < glyph_off + glyphs) || !row_off) - break; - - glyph_off += glyphs; - text_len -= row_off; - cur_row++; - } - - if (cur_row >= visible_rows && !box->sel.active) { - /* set visible frame to include cursor while writing */ - zr_size row_offset = (cur_row + 1) - visible_rows; - box->scrollbar = (font->height + field->padding.x) * (float)row_offset; - } else if (box->sel.active && scroll_offset > cur_row) { - /* set visible frame to include cursor while selecting */ - zr_size row_offset = (scroll_offset > 0) ? scroll_offset-1: scroll_offset; - box->scrollbar = (font->height + field->padding.x) * (float)row_offset; - } - } - } - if (box->text_inserted) { - /* @NOTE: zr_editbox_add handler: ugly but works */ - box->sel.begin = box->cursor; - box->sel.end = box->cursor; - box->text_inserted = 0; - } - - if (in && field->show_cursor && in->mouse.buttons[ZR_BUTTON_LEFT].down && box->active) - { - /* TEXT SELECTION */ - const char *visible = buffer; - float xoff = in->mouse.pos.x - (r.x + field->padding.x + field->border_size); - float yoff = in->mouse.pos.y - (r.y + field->padding.y + field->border_size); - - int in_space = (xoff >= 0 && xoff < total_width); - int in_region = (box->sel.active && yoff < 0) || - (yoff >= 0 && yoff < total_height); - - if (ZR_INBOX(in->mouse.pos.x, in->mouse.pos.y, r.x, r.y, r.w, r.h) && - in_space && in_region) - { - zr_size row; - zr_size glyph_index = 0, glyph_pos = 0; - zr_size cur_row = 0; - zr_size glyphs = 0; - zr_size row_off = box->glyphs; - zr_size row_len = 0; - zr_size text_len = len; - zr_size offset = 0, glyph_off = 0; - float text_width = 0; - - /* selection beyond the current visible text rows */ - if (yoff < 0 && box->sel.active) { - int off = ((int)yoff + (int)box->scrollbar - (int)row_height); - int next_row = off / (int)row_height; - row = (next_row < 0) ? 0 : (zr_size)next_row; - } else row = (zr_size)((yoff + box->scrollbar)/ - (font->height + field->padding.y)); - - /* find selected row */ - if (text_len) { - while (text_len && cur_row <= row) { - row_off = zr_user_font_glyphs_fitting_in_space(font, - &buffer[offset], text_len, total_width, &row_len, - &glyphs, &text_width, 1); - if (!row_off) break; - - glyph_off += glyphs; - text_len -= row_off; - visible += row_off; - offset += row_off; - cur_row++; - } - glyph_off -= glyphs; - visible -= row_off; - } - - /* find selected glyphs in row */ - if ((text_width + r.x + field->padding.y + field->border_size) > xoff) { - glyph_pos = zr_user_font_glyph_index_at_pos(font, visible, row_len, xoff); - if (glyph_pos + glyph_off >= box->glyphs) - glyph_index = box->glyphs; - else glyph_index = glyph_off + ZR_MIN(glyph_pos, glyphs-1); - - zr_edit_box_set_cursor(box, glyph_index); - if (!box->sel.active) { - box->sel.active = zr_true; - box->sel.begin = glyph_index; - box->sel.end = glyph_index; - } else { - if (box->sel.begin > glyph_index) { - box->sel.end = glyph_index; - box->sel.active = zr_true; - } - } - } - } else box->sel.active = zr_false; - } else box->sel.active = zr_false; - - { - /* SCROLLBAR */ - struct zr_rect bounds; - float scroll_target, scroll_offset, scroll_step; - struct zr_scrollbar scroll = field->scroll; - zr_flags state; - - bounds.x = (r.x + r.w) - (field->scrollbar_width + field->border_size); - bounds.y = r.y + field->border_size + field->padding.y; - bounds.w = field->scrollbar_width; - bounds.h = r.h - (2 * field->border_size + 2 * field->padding.y); - - scroll_offset = box->scrollbar; - scroll_step = total_height * 0.10f; - scroll_target = total_height; - scroll.has_scrolling = box->active; - box->scrollbar = zr_do_scrollbarv(&state, out, bounds, scroll_offset, - scroll_target, scroll_step, &scroll, in); - } - { - /* DRAW TEXT */ - zr_size text_len = len; - zr_size offset = 0; - zr_size row_off = 0; - zr_size row_len = 0; - zr_size glyphs = 0; - zr_size glyph_off = 0; - float text_width = 0; - struct zr_rect scissor; - struct zr_rect clip; - - struct zr_rect label; - struct zr_rect old_clip = out->clip; - - /* calculate clipping rect for scrollbar */ - clip = zr_shrink_rect(r, field->border_size); - clip.x += field->padding.x; - clip.y += field->padding.y; - clip.w -= 2 * field->padding.x; - clip.h -= 2 * field->padding.y; - zr_unify(&scissor, &out->clip, clip.x, clip.y, clip.x + clip.w, clip.y + clip.h); - - /* calculate row text space */ - zr_draw_scissor(out, scissor); - label.x = r.x + field->padding.x + field->border_size; - label.y = (r.y + field->padding.y + field->border_size) - box->scrollbar; - label.h = font->height + field->padding.y; - - /* draw each text row */ - while (text_len) { - /* selection bounds */ - struct zr_text text; - zr_size begin = ZR_MIN(box->sel.end, box->sel.begin); - zr_size end = ZR_MAX(box->sel.end, box->sel.begin); - - offset += row_off; - row_off = zr_user_font_glyphs_fitting_in_space(font, - &buffer[offset], text_len, total_width, &row_len, - &glyphs, &text_width, 1); - label.w = text_width; - if (!row_off || !row_len) break; - - /* draw either unselected or selected row */ - if (glyph_off <= begin && glyph_off + glyphs > begin && - glyph_off + glyphs <= end && box->active) - { - /* 1.) first case with selection beginning in current row */ - zr_size l = 0, sel_begin, sel_len; - zr_size unselected_text_width; - zr_rune unicode; - - /* calculate selection beginning string position */ - const char *from; - from = zr_utf_at(&buffer[offset], row_len, - (int)(begin - glyph_off), &unicode, &l); - sel_begin = (zr_size)(from - (char*)box->buffer.memory.ptr); - sel_begin = sel_begin - offset; - sel_len = row_len - sel_begin; - - /* draw unselected text part */ - unselected_text_width = - font->width(font->userdata, font->height, &buffer[offset], - (row_len >= sel_len) ? row_len - sel_len: 0); - - text.padding = zr_vec2(0,0); - text.background = field->background; - text.text = field->text; - zr_widget_text(out, label, &buffer[offset], - (row_len >= sel_len) ? row_len - sel_len: 0, - &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - - /* draw selected text part */ - label.x += (float)(unselected_text_width); - label.w -= (float)(unselected_text_width); - text.background = field->text; - text.text = field->background; - zr_draw_rect(out, ZR_FILLED, label, 0, field->text); - zr_widget_text(out, label, &buffer[offset+sel_begin], - sel_len, &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - - label.x -= (float)unselected_text_width; - label.w += (float)(unselected_text_width); - } else if (glyph_off > begin && glyph_off + glyphs < end && box->active) { - /* 2.) selection spanning over current row */ - text.padding = zr_vec2(0,0); - text.background = field->text; - text.text = field->background; - zr_draw_rect(out, ZR_FILLED, label, 0, field->text); - zr_widget_text(out, label, &buffer[offset], row_len, - &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - } else if (glyph_off > begin && glyph_off + glyphs >= end && - box->active && end >= glyph_off && end <= glyph_off + glyphs) { - /* 3.) selection ending in current row */ - zr_size l = 0, sel_end, sel_len; - zr_size selected_text_width; - zr_rune unicode; - - /* calculate selection beginning string position */ - const char *to = zr_utf_at(&buffer[offset], row_len, - (int)(end - glyph_off), &unicode, &l); - sel_end = (zr_size)(to - (char*)box->buffer.memory.ptr); - sel_len = (sel_end - offset); - sel_end = sel_end - offset; - - /* draw selected text part */ - selected_text_width = font->width(font->userdata, font->height, - &buffer[offset], sel_len); - text.padding = zr_vec2(0,0); - text.background = field->text; - text.text = field->background; - zr_draw_rect(out, ZR_FILLED, label, 0, field->text); - zr_widget_text(out, label, &buffer[offset], sel_len, - &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - - /* draw unselected text part */ - label.x += (float)selected_text_width; - label.w -= (float)(selected_text_width); - text.background = field->background; - text.text = field->text; - zr_widget_text(out, label, &buffer[offset+sel_end], - (row_len >= sel_len) ? row_len - sel_len: 0, - &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - - label.x -= (float)selected_text_width; - label.w += (float)(selected_text_width); - } - else if (glyph_off <= begin && glyph_off + glyphs >= begin && - box->active && glyph_off <= end && glyph_off + glyphs > end) - { - /* 4.) selection beginning and ending in current row */ - zr_size l = 0; - zr_size cur_text_width; - zr_size cur_len; - zr_size sel_begin, sel_end, sel_len; - zr_rune unicode; - float label_x = label.x; - float label_w = label.w; - float tmp; - - const char *from = zr_utf_at(&buffer[offset], row_len, - (int)(begin - glyph_off), &unicode, &l); - const char *to = zr_utf_at(&buffer[offset], row_len, - (int)(end - glyph_off), &unicode, &l); - - /* calculate selection bounds and length */ - sel_begin = (zr_size)(from - (char*)box->buffer.memory.ptr); - sel_begin = sel_begin - offset; - sel_end = (zr_size)(to - (char*)box->buffer.memory.ptr); - sel_end = sel_end - offset; - sel_len = (sel_end - sel_begin); - if (!sel_len) { - sel_len = zr_utf_decode(&buffer[offset+sel_begin], - &unicode, row_len); - sel_end += zr_utf_decode(&buffer[offset+sel_end], - &unicode, row_len); - } - - /* draw beginning unselected text part */ - cur_text_width = font->width(font->userdata, font->height, - &buffer[offset], sel_begin); - text.padding = zr_vec2(0,0); - text.background = field->background; - text.text = field->text; - zr_widget_text(out, label, &buffer[offset], sel_begin, - &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - - /* draw selected text part */ - label.x += (float)cur_text_width; - label.w -= (float)(cur_text_width); - tmp = label.w; - - text.background = field->text; - text.text = field->background; - cur_len = font->width(font->userdata, font->height, - &buffer[offset+sel_begin], sel_len); - label.w = (float)cur_len; - zr_draw_rect(out, ZR_FILLED, label, 0, field->text); - zr_widget_text(out, label, &buffer[offset+sel_begin], sel_len, - &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - cur_text_width = font->width(font->userdata, font->height, - &buffer[offset+sel_begin], sel_len); - label.w = tmp; - - /* draw ending unselected text part */ - label.x += (float)cur_text_width; - label.w -= (float)(cur_text_width); - text.background = field->background; - text.text = field->text; - zr_widget_text(out, label, &buffer[offset+sel_end], - row_len - (sel_len + sel_begin), - &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - - label.x = (float)label_x; - label.w = (float)label_w; - } else { - /* 5.) no selection */ - label.w = text_width; - text.background = field->background; - text.text = field->text; - zr_widget_text(out, label, &buffer[offset], - row_len, &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - } - - glyph_off += glyphs; - text_len -= row_off; - label.y += font->height + field->padding.y; - } - - /* draw the cursor at the end of the string */ - if (box->active && field->show_cursor) { - if (box->cursor == box->glyphs) { - if (len) label.y -= (font->height + field->padding.y); - zr_draw_rect(out, ZR_FILLED, zr_rect(label.x+(float)text_width, - label.y, (float)cursor_w, label.h), 0, field->cursor); - } - } - zr_draw_scissor(out, old_clip); - } -} - -int zr_filter_default(const struct zr_edit_box *box, zr_rune unicode) -{(void)unicode;ZR_UNUSED(box);return zr_true;} - -int -zr_filter_ascii(const struct zr_edit_box *box, zr_rune unicode) -{ - ZR_UNUSED(box); - if (unicode > 128) return zr_false; - else return zr_true; -} - -int -zr_filter_float(const struct zr_edit_box *box, zr_rune unicode) -{ - ZR_UNUSED(box); - if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-') - return zr_false; - else return zr_true; -} - -int -zr_filter_decimal(const struct zr_edit_box *box, zr_rune unicode) -{ - ZR_UNUSED(box); - if ((unicode < '0' || unicode > '9') && unicode != '-') - return zr_false; - else return zr_true; -} - -int -zr_filter_hex(const struct zr_edit_box *box, zr_rune unicode) -{ - ZR_UNUSED(box); - if ((unicode < '0' || unicode > '9') && - (unicode < 'a' || unicode > 'f') && - (unicode < 'A' || unicode > 'F')) - return zr_false; - else return zr_true; -} - -int -zr_filter_oct(const struct zr_edit_box *box, zr_rune unicode) -{ - ZR_UNUSED(box); - if (unicode < '0' || unicode > '7') - return zr_false; - else return zr_true; -} - -int -zr_filter_binary(const struct zr_edit_box *box, zr_rune unicode) -{ - ZR_UNUSED(box); - if (unicode != '0' && unicode != '1') - return zr_false; - else return zr_true; -} - -static zr_size -zr_widget_edit(struct zr_command_buffer *out, struct zr_rect r, - char *buffer, zr_size len, zr_size max, int *active, - zr_size *cursor, const struct zr_edit *field, zr_filter filter, - const struct zr_input *in, const struct zr_user_font *font) -{ - struct zr_edit_box box; - zr_edit_box_init(&box, buffer, max, 0, filter); - - box.buffer.allocated = len; - box.active = *active; - box.glyphs = zr_utf_len(buffer, len); - if (!cursor) { - box.cursor = box.glyphs; - } else{ - box.cursor = ZR_MIN(*cursor, box.glyphs); - box.sel.begin = box.cursor; - box.sel.end = box.cursor; - } - - zr_widget_edit_field(out, r, &box, field, in, font); - *active = box.active; - if (cursor) - *cursor = box.cursor; - return zr_edit_box_len_char(&box); -} -/* =============================================================== - * - * PROPERTY - * - * ===============================================================*/ -enum zr_property_state { - ZR_PROPERTY_DEFAULT, - ZR_PROPERTY_EDIT, - ZR_PROPERTY_DRAG -}; - -enum zr_property_filter { - ZR_FILTER_INT, - ZR_FILTER_FLOAT -}; - -struct zr_property { - float border_size; - struct zr_vec2 padding; - struct zr_color border; - struct zr_color normal; - struct zr_color hover; - struct zr_color active; - struct zr_color text; - float rounding; -}; - -static float -zr_drag_behavior(zr_flags *state, const struct zr_input *in, - struct zr_rect drag, float min, float val, float max, float inc_per_pixel) -{ - int left_mouse_down = in && in->mouse.buttons[ZR_BUTTON_LEFT].down; - int left_mouse_click_in_cursor = in && - zr_input_has_mouse_click_down_in_rect(in, ZR_BUTTON_LEFT, drag, zr_true); - - *state = ZR_INACTIVE; - if (zr_input_is_mouse_hovering_rect(in, drag)) - *state = ZR_HOVERED; - - if (left_mouse_down && left_mouse_click_in_cursor) { - float delta, pixels; - pixels = in->mouse.delta.x; - delta = pixels * inc_per_pixel; - val += delta; - val = ZR_CLAMP(min, val, max); - *state = ZR_ACTIVE; - } - if (*state == ZR_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, drag)) - *state |= ZR_ENTER; - else if (zr_input_is_mouse_prev_hovering_rect(in, drag)) - *state |= ZR_LEAVE; - return val; -} - -static float -zr_property_behavior(zr_flags *ws, const struct zr_input *in, - struct zr_rect property, struct zr_rect left, struct zr_rect right, - struct zr_rect label, struct zr_rect edit, struct zr_rect empty, - int *state, float min, float value, float max, float step, float inc_per_pixel) -{ - if (in && zr_button_behavior(ws, left, in, ZR_BUTTON_DEFAULT)) - value = ZR_CLAMP(min, value - step, max); - if (in && zr_button_behavior(ws, right, in, ZR_BUTTON_DEFAULT)) - value = ZR_CLAMP(min, value + step, max); - - if (in && *state == ZR_PROPERTY_DEFAULT) { - if (zr_button_behavior(ws, edit, in, ZR_BUTTON_DEFAULT)) - *state = ZR_PROPERTY_EDIT; - else if (zr_input_is_mouse_click_down_in_rect(in, ZR_BUTTON_LEFT, label, zr_true)) - *state = ZR_PROPERTY_DRAG; - else if (zr_input_is_mouse_click_down_in_rect(in, ZR_BUTTON_LEFT, empty, zr_true)) - *state = ZR_PROPERTY_DRAG; - } - if (*state == ZR_PROPERTY_DRAG) { - value = zr_drag_behavior(ws, in, property, min, value, max, inc_per_pixel); - if (!(*ws & ZR_ACTIVE)) *state = ZR_PROPERTY_DEFAULT; - } - return value; -} - -static void -zr_property_draw(struct zr_command_buffer *out, - struct zr_property *p, struct zr_rect property, - struct zr_rect left, struct zr_rect right, - struct zr_rect label, const char *name, zr_size len, - const struct zr_user_font *f) -{ - struct zr_symbol sym; - struct zr_text text; - - /* background */ - zr_draw_rect(out, ZR_FILLED, property, p->rounding, p->border); - zr_draw_rect(out, ZR_FILLED, zr_shrink_rect(property, p->border_size), - p->rounding, p->normal); - - /* buttons */ - sym.type = ZR_SYMBOL_TRIANGLE_LEFT; - sym.background = p->normal; - sym.foreground = p->text; - sym.border_width = 0; - - zr_draw_symbol(out, &sym, left, f); - sym.type = ZR_SYMBOL_TRIANGLE_RIGHT; - zr_draw_symbol(out, &sym, right, f); - - /* label */ - text.padding = zr_vec2(0,0); - text.background = p->normal; - text.text = p->text; - zr_widget_text(out, label, name, len, &text, ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, f); -} - -static float -zr_do_property(zr_flags *ws, - struct zr_command_buffer *out, struct zr_rect property, - const char *name, float min, float val, float max, - float step, float inc_per_pixel, char *buffer, zr_size *len, - int *state, zr_size *cursor, struct zr_property *p, - enum zr_property_filter filter, const struct zr_input *in, - const struct zr_user_font *f) -{ - const zr_filter filters[] = { - zr_filter_decimal, - zr_filter_float - }; - int active, old; - zr_size num_len, name_len; - char string[ZR_MAX_NUMBER_BUFFER]; - zr_size size; - - float property_min; - float property_max; - float property_value; - - char *dst = 0; - zr_size *length; - - struct zr_edit field; - struct zr_rect left; - struct zr_rect right; - struct zr_rect label; - struct zr_rect edit; - struct zr_rect empty; - - /* make sure the provided values are correct */ - property_max = ZR_MAX(min, max); - property_min = ZR_MIN(min, max); - property_value = ZR_CLAMP(property_min, val, property_max); - - /* left decrement button */ - left.h = f->height/2; - left.w = left.h; - left.x = property.x + p->border_size + p->padding.x; - left.y = property.y + p->border_size + property.h/2.0f - left.h/2; - - /* text label */ - name_len = zr_strsiz(name); - size = f->width(f->userdata, f->height, name, name_len); - label.x = left.x + left.w + p->padding.x; - label.w = (float)size + 2 * p->padding.x; - label.y = property.y + p->border_size; - label.h = property.h - 2 * p->border_size; - - /* right increment button */ - right.y = left.y; - right.w = left.w; - right.h = left.h; - right.x = property.x + property.w - (right.w + p->padding.x); - - /* edit */ - if (*state == ZR_PROPERTY_EDIT) { - size = f->width(f->userdata, f->height, buffer, *len); - length = len; - dst = buffer; - } else { - zr_ftos(string, property_value); - num_len = zr_string_float_limit(string, ZR_MAX_FLOAT_PRECISION); - size = f->width(f->userdata, f->height, string, num_len); - dst = string; - length = &num_len; - } - - edit.w = (float)size + 2 * p->padding.x; - edit.x = right.x - (edit.w + p->padding.x); - edit.y = property.y + p->border_size + 1; - edit.h = property.h - (2 * p->border_size + 2); - - /* empty left space activator */ - empty.w = edit.x - (label.x + label.w); - empty.x = label.x + label.w; - empty.y = property.y; - empty.h = property.h; - - old = (*state == ZR_PROPERTY_EDIT); - property_value = zr_property_behavior(ws, in, property, left, right, label, - edit, empty, state, property_min, property_value, - property_max, step, inc_per_pixel); - zr_property_draw(out, p, property, left, right, label, name, name_len, f); - - /* edit field */ - field.border_size = 0; - field.scrollbar_width = 0; - field.rounding = 0; - field.padding.x = 0; - field.padding.y = 0; - field.show_cursor = zr_true; - field.background = p->normal; - field.border = p->normal; - field.cursor = p->text; - field.text = p->text; - - active = (*state == ZR_PROPERTY_EDIT); - if (old != ZR_PROPERTY_EDIT && active) { - /* property has been activated so setup buffer */ - zr_memcopy(buffer, dst, *length); - *cursor = zr_utf_len(buffer, *length); - *len = *length; - length = len; - dst = buffer; - } - - *length = zr_widget_edit(out, edit, dst, *length, - ZR_MAX_NUMBER_BUFFER, &active, cursor, &field, filters[filter], - (*state == ZR_PROPERTY_EDIT) ? in: 0, f); - if (active && zr_input_is_key_pressed(in, ZR_KEY_ENTER)) - active = !active; - - if (old && !active) { - /* property is now not active so convert edit text to value*/ - *state = ZR_PROPERTY_DEFAULT; - buffer[*len] = '\0'; - zr_string_float_limit(buffer, ZR_MAX_FLOAT_PRECISION); - zr_strtof(&property_value, buffer); - property_value = ZR_CLAMP(min, property_value, max); - } - return property_value; -} - -/* =============================================================== - * - * COLOR PICKER - * - * ===============================================================*/ -static int -zr_color_picker_behavior(zr_flags *state, - const struct zr_rect *bounds, const struct zr_rect *matrix, - const struct zr_rect *hue_bar, const struct zr_rect *alpha_bar, - struct zr_color *color, const struct zr_input *in) -{ - float hsva[4]; - int value_changed = 0; - int hsv_changed = 0; - - ZR_ASSERT(state); - ZR_ASSERT(matrix); - ZR_ASSERT(hue_bar); - ZR_ASSERT(color); - - /* color matrix */ - zr_color_hsva_fv(hsva, *color); - if (zr_button_behavior(state, *matrix, in, ZR_BUTTON_REPEATER)) { - hsva[1] = ZR_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1)); - hsva[2] = 1.0f - ZR_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1)); - value_changed = hsv_changed = 1; - } - - /* hue bar */ - if (zr_button_behavior(state, *hue_bar, in, ZR_BUTTON_REPEATER)) { - hsva[0] = ZR_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1)); - value_changed = hsv_changed = 1; - } - /* alpha bar */ - if (alpha_bar) { - if (zr_button_behavior(state, *alpha_bar, in, ZR_BUTTON_REPEATER)) { - hsva[3] = 1.0f - ZR_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1)); - value_changed = 1; - } - } - - if (hsv_changed) { - *color = zr_hsva_fv(hsva); - *state = ZR_ACTIVE; - } - if (value_changed) { - color->a = (zr_byte)(hsva[3] * 255.0f); - *state = ZR_ACTIVE; - } - - *state = ZR_INACTIVE; - if (zr_input_is_mouse_hovering_rect(in, *bounds)) - *state = ZR_HOVERED; - if (*state == ZR_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, *bounds)) - *state |= ZR_ENTER; - else if (zr_input_is_mouse_prev_hovering_rect(in, *bounds)) - *state |= ZR_LEAVE; - return value_changed; -} - -static void -zr_draw_color_picker(struct zr_command_buffer *o, const struct zr_rect *matrix, - const struct zr_rect *hue_bar, const struct zr_rect *alpha_bar, - struct zr_color color) -{ - static const struct zr_color black = {0,0,0,255}; - static const struct zr_color white = {255, 255, 255, 255}; - static const struct zr_color black_trans = {0,0,0,0}; - - const float crosshair_size = 7.0f; - struct zr_color temp; - float hsva[4]; - float line_y; - int i; - - ZR_ASSERT(o); - ZR_ASSERT(matrix); - ZR_ASSERT(hue_bar); - ZR_ASSERT(alpha_bar); - - /* draw hue bar */ - zr_color_hsv_fv(hsva, color); - for (i = 0; i < 6; ++i) { - static const struct zr_color hue_colors[] = { - {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255}, - {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255}}; - zr_draw_rect_multi_color(o, - zr_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f, - hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i], - hue_colors[i+1], hue_colors[i+1]); - } - line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f); - zr_draw_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2, - line_y, zr_rgb(255,255,255)); - - /* draw alpha bar */ - if (alpha_bar) { - float alpha = ZR_SATURATE((float)color.a/255.0f); - line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f); - - zr_draw_rect_multi_color(o, *alpha_bar, white, white, black, black); - zr_draw_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2, - line_y, zr_rgb(255,255,255)); - } - - /* draw color matrix */ - temp = zr_hsv_f(hsva[0], 1.0f, 1.0f); - zr_draw_rect_multi_color(o, *matrix, white, temp, temp, white); - zr_draw_rect_multi_color(o, *matrix, black_trans, black_trans, black, black); - - /* draw cross-hair */ - {struct zr_vec2 p; float S = hsva[1]; float V = hsva[2]; - p.x = (float)(int)(matrix->x + S * matrix->w + 0.5f); - p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h + 0.5f); - zr_draw_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, white); - zr_draw_line(o, p.x + crosshair_size, p.y, p.x+2, p.y, white); - zr_draw_line(o, p.x, p.y + crosshair_size, p.x, p.y+2, zr_rgb(255,255,255)); - zr_draw_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, zr_rgb(255,255,255));} -} - -static int -zr_do_color_picker(zr_flags *state, - struct zr_command_buffer *out, struct zr_color *color, - enum zr_color_picker_format fmt, struct zr_rect bounds, - struct zr_vec2 padding, const struct zr_input *in, - const struct zr_user_font *font) -{ - int ret = 0; - struct zr_rect matrix; - struct zr_rect hue_bar; - struct zr_rect alpha_bar; - float bar_w; - - ZR_ASSERT(out); - ZR_ASSERT(color); - ZR_ASSERT(state); - ZR_ASSERT(font); - if (!out || !color || !state || !font) - return ret; - - bar_w = font->height; - bounds.x += padding.x; - bounds.y += padding.x; - bounds.w -= 2 * padding.x; - bounds.h -= 2 * padding.y; - - matrix.x = bounds.x; - matrix.y = bounds.y; - matrix.h = bounds.h; - matrix.w = bounds.w - (3 * padding.x + 2 * bar_w); - - hue_bar.w = bar_w; - hue_bar.y = bounds.y; - hue_bar.h = matrix.h; - hue_bar.x = matrix.x + matrix.w + padding.x; - - alpha_bar.x = hue_bar.x + hue_bar.w + padding.x; - alpha_bar.y = bounds.y; - alpha_bar.w = bar_w; - alpha_bar.h = matrix.h; - - ret = zr_color_picker_behavior(state, &bounds, &matrix, &hue_bar, - (fmt == ZR_RGBA) ? &alpha_bar:0, color, in); - zr_draw_color_picker(out, &matrix, &hue_bar, (fmt == ZR_RGBA) ? &alpha_bar:0, *color); - return ret; -} - /* ============================================================== * * INPUT @@ -6757,149 +4592,2713 @@ zr_input_is_key_down(const struct zr_input *i, enum zr_keys key) return zr_false; } +/* =============================================================== + * + * TEXT + * + * ===============================================================*/ +struct zr_text { + struct zr_vec2 padding; + struct zr_color background; + struct zr_color text; +}; + +static void +zr_widget_text(struct zr_command_buffer *o, struct zr_rect b, + const char *string, zr_size len, const struct zr_text *t, + zr_flags a, const struct zr_user_font *f) +{ + struct zr_rect label; + zr_size text_width; + + ZR_ASSERT(o); + ZR_ASSERT(t); + if (!o || !t) return; + + b.h = ZR_MAX(b.h, 2 * t->padding.y); + label.x = 0; label.w = 0; + label.y = b.y + t->padding.y; + label.h = b.h - 2 * t->padding.y; + + text_width = f->width(f->userdata, f->height, (const char*)string, len); + text_width += (zr_size)(2 * t->padding.x); + + /* align in x-axis */ + if (a & ZR_TEXT_ALIGN_LEFT) { + label.x = b.x + t->padding.x; + label.w = ZR_MAX(0, b.w - 2 * t->padding.x); + } else if (a & ZR_TEXT_ALIGN_CENTERED) { + label.w = ZR_MAX(1, 2 * t->padding.x + (float)text_width); + label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2); + label.x = ZR_MAX(b.x + t->padding.x, label.x); + label.w = ZR_MIN(b.x + b.w, label.x + label.w); + if (label.w >= label.x) label.w -= label.x; + } else if (a & ZR_TEXT_ALIGN_RIGHT) { + label.x = ZR_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width)); + label.w = (float)text_width + 2 * t->padding.x; + } else return; + + /* align in y-axis */ + if (a & ZR_TEXT_ALIGN_MIDDLE) { + label.y = b.y + b.h/2.0f - (float)f->height/2.0f; + label.h = b.h - (b.h/2.0f + f->height/2.0f); + } else if (a & ZR_TEXT_ALIGN_BOTTOM) { + label.y = b.y + b.h - f->height; + label.h = f->height; + } + zr_draw_text(o, label, (const char*)string, + len, f, t->background, t->text); +} + +static void +zr_widget_text_wrap(struct zr_command_buffer *o, struct zr_rect b, + const char *string, zr_size len, const struct zr_text *t, + const struct zr_user_font *f) +{ + float width; + zr_size glyphs = 0; + zr_size fitting = 0; + zr_size done = 0; + struct zr_rect line; + struct zr_text text; + + ZR_ASSERT(o); + ZR_ASSERT(t); + if (!o || !t) return; + + text.padding = zr_vec2(0,0); + text.background = t->background; + text.text = t->text; + + b.w = ZR_MAX(b.w, 2 * t->padding.x); + b.h = ZR_MAX(b.h, 2 * t->padding.y); + b.h = b.h - 2 * t->padding.y; + + line.x = b.x + t->padding.x; + line.y = b.y + t->padding.y; + line.w = b.w - 2 * t->padding.x; + line.h = 2 * t->padding.y + f->height; + + fitting = zr_use_font_glyph_clamp(f, string, len, line.w, &glyphs, &width); + while (done < len) { + if (!fitting || line.y + line.h >= (b.y + b.h)) break; + zr_widget_text(o, line, &string[done], fitting, &text, ZR_TEXT_LEFT, f); + done += fitting; + line.y += f->height + 2 * t->padding.y; + fitting = zr_use_font_glyph_clamp(f, &string[done], len - done, + line.w, &glyphs, &width); + } +} + +/* =============================================================== + * + * BUTTON + * + * ===============================================================*/ +static void +zr_draw_symbol(struct zr_command_buffer *out, enum zr_symbol_type type, + struct zr_rect content, struct zr_color background, struct zr_color foreground, + float border_width, const struct zr_user_font *font) +{ + switch (type) { + case ZR_SYMBOL_X: + case ZR_SYMBOL_UNDERSCORE: + case ZR_SYMBOL_PLUS: + case ZR_SYMBOL_MINUS: { + /* single character text symbol */ + const char *X = (type == ZR_SYMBOL_X) ? "x": + (type == ZR_SYMBOL_UNDERSCORE) ? "_": + (type == ZR_SYMBOL_PLUS) ? "+": "-"; + struct zr_text text; + text.padding = zr_vec2(0,0); + text.background = background; + text.text = foreground; + zr_widget_text(out, content, X, 1, &text, ZR_TEXT_CENTERED, font); + } break; + case ZR_SYMBOL_CIRCLE: + case ZR_SYMBOL_CIRCLE_FILLED: + case ZR_SYMBOL_RECT: + case ZR_SYMBOL_RECT_FILLED: { + /* simple empty/filled shapes */ + if (type == ZR_SYMBOL_RECT || type == ZR_SYMBOL_RECT_FILLED) { + zr_fill_rect(out, content, 0, foreground); + if (type == ZR_SYMBOL_RECT_FILLED) + zr_fill_rect(out, zr_shrink_rect(content, border_width), 0, background); + } else { + zr_fill_circle(out, content, foreground); + if (type == ZR_SYMBOL_CIRCLE_FILLED) + zr_fill_circle(out, zr_shrink_rect(content, 1), background); + } + } break; + case ZR_SYMBOL_TRIANGLE_UP: + case ZR_SYMBOL_TRIANGLE_DOWN: + case ZR_SYMBOL_TRIANGLE_LEFT: + case ZR_SYMBOL_TRIANGLE_RIGHT: { + enum zr_heading heading; + struct zr_vec2 points[3]; + heading = (type == ZR_SYMBOL_TRIANGLE_RIGHT) ? ZR_RIGHT : + (type == ZR_SYMBOL_TRIANGLE_LEFT) ? ZR_LEFT: + (type == ZR_SYMBOL_TRIANGLE_UP) ? ZR_UP: ZR_DOWN; + zr_triangle_from_direction(points, content, 0, 0, heading); + zr_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y, + points[2].x, points[2].y, foreground); + } break; + default: + case ZR_SYMBOL_NONE: + case ZR_SYMBOL_MAX: break; + } +} + +static int +zr_button_behavior(zr_flags *state, struct zr_rect r, + const struct zr_input *i, enum zr_button_behavior behavior) +{ + int ret = 0; + *state = ZR_WIDGET_STATE_INACTIVE; + if (!i) return 0; + if (zr_input_is_mouse_hovering_rect(i, r)) { + *state = ZR_WIDGET_STATE_HOVERED; + if (zr_input_is_mouse_down(i, ZR_BUTTON_LEFT)) + *state = ZR_WIDGET_STATE_ACTIVE; + if (zr_input_has_mouse_click_in_rect(i, ZR_BUTTON_LEFT, r)) { + ret = (behavior != ZR_BUTTON_DEFAULT) ? + zr_input_is_mouse_down(i, ZR_BUTTON_LEFT): + zr_input_is_mouse_released(i, ZR_BUTTON_LEFT); + } + } + if (*state == ZR_WIDGET_STATE_HOVERED && !zr_input_is_mouse_prev_hovering_rect(i, r)) + *state |= ZR_WIDGET_STATE_ENTERED; + else if (zr_input_is_mouse_prev_hovering_rect(i, r)) + *state |= ZR_WIDGET_STATE_LEFT; + return ret; +} + +static const struct zr_style_item* +zr_draw_button(struct zr_command_buffer *out, + const struct zr_rect *bounds, zr_flags state, + const struct zr_style_button *style) +{ + const struct zr_style_item *background; + if (state & ZR_WIDGET_STATE_HOVERED) + background = &style->hover; + else if (state & ZR_WIDGET_STATE_ACTIVE) + background = &style->active; + else background = &style->normal; + + if (background->type == ZR_STYLE_ITEM_IMAGE) { + zr_draw_image(out, *bounds, &background->data.image); + } else { + zr_fill_rect(out, *bounds, style->rounding, style->border_color); + zr_fill_rect(out, zr_shrink_rect(*bounds, style->border), style->rounding, + background->data.color); + } + return background; +} + +static void +zr_draw_button_text(struct zr_command_buffer *out, + const struct zr_rect *bounds, const struct zr_rect *content, zr_flags state, + const struct zr_style_button *style, const char *txt, zr_size len, + zr_flags text_alignment, const struct zr_user_font *font) +{ + struct zr_text text; + const struct zr_style_item *background; + background = zr_draw_button(out, bounds, state, style); + + if (background->type == ZR_STYLE_ITEM_COLOR) + text.background = background->data.color; + else text.background = style->text_background; + if (state & ZR_WIDGET_STATE_HOVERED) + text.text = style->text_hover; + else if (state & ZR_WIDGET_STATE_ACTIVE) + text.text = style->text_active; + else text.text = style->text_normal; + text.padding = zr_vec2(0,0); + zr_widget_text(out, *content, txt, len, &text, text_alignment, font); +} + +static void +zr_draw_button_symbol(struct zr_command_buffer *out, + const struct zr_rect *bounds, const struct zr_rect *content, + zr_flags state, const struct zr_style_button *style, + enum zr_symbol_type type, const struct zr_user_font *font) +{ + struct zr_color sym, bg; + const struct zr_style_item *background; + background = zr_draw_button(out, bounds, state, style); + if (background->type == ZR_STYLE_ITEM_COLOR) + bg = background->data.color; + else bg = style->text_background; + + if (state & ZR_WIDGET_STATE_HOVERED) + sym = style->text_hover; + else if (state & ZR_WIDGET_STATE_ACTIVE) + sym = style->text_active; + else sym = style->text_normal; + zr_draw_symbol(out, type, *content, bg, sym, 1, font); +} + +static void +zr_draw_button_image(struct zr_command_buffer *out, + const struct zr_rect *bounds, const struct zr_rect *content, + zr_flags state, const struct zr_style_button *style, const struct zr_image *img) +{ + zr_draw_button(out, bounds, state, style); + zr_draw_image(out, *content, img); +} + +static void +zr_draw_button_text_symbol(struct zr_command_buffer *out, + const struct zr_rect *bounds, const struct zr_rect *label, + const struct zr_rect *symbol, zr_flags state, const struct zr_style_button *style, + const char *str, zr_size len, enum zr_symbol_type type, + const struct zr_user_font *font) +{ + struct zr_color sym, bg; + struct zr_text text; + const struct zr_style_item *background; + background = zr_draw_button(out, bounds, state, style); + if (background->type == ZR_STYLE_ITEM_COLOR) { + text.background = background->data.color; + bg = background->data.color; + } else { + text.background = style->text_background; + bg = style->text_background; + } + + if (state & ZR_WIDGET_STATE_HOVERED) { + sym = style->text_hover; + text.text = style->text_hover; + } else if (state & ZR_WIDGET_STATE_ACTIVE) { + sym = style->text_active; + text.text = style->text_active; + } else { + sym = style->text_normal; + text.text = style->text_normal; + } + text.padding = zr_vec2(0,0); + zr_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font); + zr_widget_text(out, *label, str, len, &text, ZR_TEXT_CENTERED, font); +} + +static void +zr_draw_button_text_image(struct zr_command_buffer *out, + const struct zr_rect *bounds, const struct zr_rect *label, + const struct zr_rect *image, zr_flags state, const struct zr_style_button *style, + const char *str, zr_size len, const struct zr_user_font *font, + const struct zr_image *img) +{ + struct zr_text text; + const struct zr_style_item *background; + background = zr_draw_button(out, bounds, state, style); + + if (background->type == ZR_STYLE_ITEM_COLOR) + text.background = background->data.color; + else text.background = style->text_background; + if (state & ZR_WIDGET_STATE_HOVERED) + text.text = style->text_hover; + else if (state & ZR_WIDGET_STATE_ACTIVE) + text.text = style->text_active; + else text.text = style->text_normal; + + text.padding = zr_vec2(0,0); + zr_widget_text(out, *label, str, len, &text, ZR_TEXT_CENTERED, font); + zr_draw_image(out, *image, img); +} + +static int +zr_do_button(zr_flags *state, struct zr_command_buffer *out, struct zr_rect r, + const struct zr_style_button *style, const struct zr_input *in, + enum zr_button_behavior behavior, struct zr_rect *content) +{ + struct zr_vec2 pad; + struct zr_rect bounds; + + ZR_ASSERT(style); + ZR_ASSERT(state); + ZR_ASSERT(out); + if (!out || !style) + return zr_false; + + /* calculate button content space */ + pad.x = style->padding.x + style->border; + pad.y = style->padding.y + style->border; + + content->x = r.x + style->padding.x; + content->y = r.y + style->padding.y; + content->w = r.w - 2 * style->padding.x; + content->h = r.h - 2 * style->padding.y; + + /* execute and draw button */ + bounds.x = r.x - style->touch_padding.x; + bounds.y = r.y - style->touch_padding.y; + bounds.w = r.w + 2 * style->touch_padding.x; + bounds.h = r.h + 2 * style->touch_padding.y; + return zr_button_behavior(state, bounds, in, behavior); +} + +static int +zr_do_button_text(zr_flags *state, + struct zr_command_buffer *out, struct zr_rect bounds, + const char *string, zr_size len, zr_flags align, enum zr_button_behavior behavior, + const struct zr_style_button *style, const struct zr_input *in, + const struct zr_user_font *font) +{ + struct zr_rect content; + int ret = zr_false; + + ZR_ASSERT(state); + ZR_ASSERT(style); + ZR_ASSERT(out); + ZR_ASSERT(string); + ZR_ASSERT(font); + if (!out || !style || !font || !string) + return zr_false; + + ret = zr_do_button(state, out, bounds, style, in, behavior, &content); + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw.button_text) + style->draw.button_text(out, &bounds, &content, *state, style, + string, len, align, font); + else zr_draw_button_text(out, &bounds, &content, *state, style, + string, len, align, font); + if (style->draw_end) + style->draw_begin(out, style->userdata); + return ret; +} + +static int +zr_do_button_symbol(zr_flags *state, + struct zr_command_buffer *out, struct zr_rect bounds, + enum zr_symbol_type symbol, enum zr_button_behavior behavior, + const struct zr_style_button *style, const struct zr_input *in, + const struct zr_user_font *font) +{ + int ret; + struct zr_rect content; + + ZR_ASSERT(state); + ZR_ASSERT(style); + ZR_ASSERT(font); + ZR_ASSERT(out); + if (!out || !style || !font || !state) + return zr_false; + + ret = zr_do_button(state, out, bounds, style, in, behavior, &content); + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw.button_symbol) + style->draw.button_symbol(out, &bounds, &content, *state, style, symbol, font); + else zr_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font); + if (style->draw_end) + style->draw_begin(out, style->userdata); + return ret; +} + +static int +zr_do_button_image(zr_flags *state, + struct zr_command_buffer *out, struct zr_rect bounds, + struct zr_image img, enum zr_button_behavior b, + const struct zr_style_button *style, const struct zr_input *in) +{ + int ret; + struct zr_rect content; + + ZR_ASSERT(state); + ZR_ASSERT(style); + ZR_ASSERT(out); + if (!out || !style || !state) + return zr_false; + + ret = zr_do_button(state, out, bounds, style, in, b, &content); + content.x += style->image_padding.x; + content.y += style->image_padding.y; + content.w -= 2 * style->image_padding.x; + content.h -= 2 * style->image_padding.y; + + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw.button_image) + style->draw.button_image(out, &bounds, &content, *state, style, &img); + else zr_draw_button_image(out, &bounds, &content, *state, style, &img); + if (style->draw_end) + style->draw_begin(out, style->userdata); + return ret; +} + +static int +zr_do_button_text_symbol(zr_flags *state, + struct zr_command_buffer *out, struct zr_rect bounds, + enum zr_symbol_type symbol, const char *str, zr_size len, zr_flags align, + enum zr_button_behavior behavior, const struct zr_style_button *style, + const struct zr_user_font *font, const struct zr_input *in) +{ + int ret; + struct zr_rect tri = {0,0,0,0}; + struct zr_rect content; + + ZR_ASSERT(style); + ZR_ASSERT(out); + ZR_ASSERT(font); + if (!out || !style || !font) + return zr_false; + + ret = zr_do_button(state, out, bounds, style, in, behavior, &content); + tri.y = content.y + (content.h/2) - font->height/2; + tri.w = font->height; tri.h = font->height; + if (align & ZR_TEXT_LEFT) { + tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w); + tri.x = ZR_MAX(tri.x, 0); + } else tri.x = content.x + 2 * style->padding.x; + + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw.button_text_symbol) + zr_draw_button_text_symbol(out, &bounds, &content, &tri, + *state, style, str, len, symbol, font); + else zr_draw_button_text_symbol(out, &bounds, &content, &tri, + *state, style, str, len, symbol, font); + if (style->draw_end) + style->draw_begin(out, style->userdata); + return ret; +} + +static int +zr_do_button_text_image(zr_flags *state, + struct zr_command_buffer *out, struct zr_rect bounds, + struct zr_image img, const char* str, zr_size len, zr_flags align, + enum zr_button_behavior behavior, const struct zr_style_button *style, + const struct zr_user_font *font, const struct zr_input *in) +{ + int ret; + struct zr_rect icon; + struct zr_rect content; + + ZR_ASSERT(style); + ZR_ASSERT(state); + ZR_ASSERT(font); + ZR_ASSERT(out); + if (!out || !font || !style || !str) + return zr_false; + + ret = zr_do_button(state, out, bounds, style, in, behavior, &content); + icon.y = bounds.y + style->padding.y; + icon.w = icon.h = bounds.h - 2 * style->padding.y; + if (align & ZR_TEXT_ALIGN_LEFT) { + icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); + icon.x = ZR_MAX(icon.x, 0); + } else icon.x = bounds.x + 2 * style->padding.x; + + icon.x += style->image_padding.x; + icon.y += style->image_padding.y; + icon.w -= 2 * style->image_padding.x; + icon.h -= 2 * style->image_padding.y; + + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw.button_text_image) + zr_draw_button_text_image(out, &bounds, &content, &icon, + *state, style, str, len, font, &img); + else zr_draw_button_text_image(out, &bounds, &content, &icon, + *state, style, str, len, font, &img); + if (style->draw_end) + style->draw_begin(out, style->userdata); + return ret; +} + +/* =============================================================== + * + * TOGGLE + * + * ===============================================================*/ +enum zr_toggle_type { + ZR_TOGGLE_CHECK, + ZR_TOGGLE_OPTION +}; + +static int +zr_toggle_behavior(const struct zr_input *in, struct zr_rect select, + zr_flags *state, int active) +{ + *state = ZR_WIDGET_STATE_INACTIVE; + if (in && zr_input_is_mouse_hovering_rect(in, select)) + *state = ZR_WIDGET_STATE_HOVERED; + if (zr_input_mouse_clicked(in, ZR_BUTTON_LEFT, select)) { + *state = ZR_WIDGET_STATE_ACTIVE; + active = !active; + } + if (*state == ZR_WIDGET_STATE_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, select)) + *state |= ZR_WIDGET_STATE_ENTERED; + else if (zr_input_is_mouse_prev_hovering_rect(in, select)) + *state |= ZR_WIDGET_STATE_LEFT; + return active; +} + +static void +zr_draw_checkbox(struct zr_command_buffer *out, + zr_flags state, const struct zr_style_toggle *style, int active, + const struct zr_rect *label, const struct zr_rect *selector, + const struct zr_rect *cursors, const char *string, zr_size len, + const struct zr_user_font *font) +{ + const struct zr_style_item *background; + const struct zr_style_item *cursor; + struct zr_text text; + + if (state & ZR_WIDGET_STATE_HOVERED) { + background = &style->hover; + cursor = &style->cursor_hover; + text.text = style->text_hover; + } else if (state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->hover; + cursor = &style->cursor_hover; + text.text = style->text_active; + } else { + background = &style->normal; + cursor = &style->cursor_normal; + text.text = style->text_normal; + } + + if (background->type == ZR_STYLE_ITEM_IMAGE) + zr_draw_image(out, *selector, &background->data.image); + else zr_fill_rect(out, *selector, 0, background->data.color); + if (active) { + if (cursor->type == ZR_STYLE_ITEM_IMAGE) + zr_draw_image(out, *cursors, &cursor->data.image); + else zr_fill_rect(out, *cursors, 0, cursor->data.color); + } + + text.padding.x = 0; + text.padding.y = 0; + text.background = style->text_background; + zr_widget_text(out, *label, string, len, &text, ZR_TEXT_LEFT, font); +} + +static void +zr_draw_option(struct zr_command_buffer *out, + zr_flags state, const struct zr_style_toggle *style, int active, + const struct zr_rect *label, const struct zr_rect *selector, + const struct zr_rect *cursors, const char *string, zr_size len, + const struct zr_user_font *font) +{ + const struct zr_style_item *background; + const struct zr_style_item *cursor; + struct zr_text text; + + if (state & ZR_WIDGET_STATE_HOVERED) { + background = &style->hover; + cursor = &style->cursor_hover; + text.text = style->text_hover; + } else if (state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->hover; + cursor = &style->cursor_hover; + text.text = style->text_active; + } else { + background = &style->normal; + cursor = &style->cursor_normal; + text.text = style->text_normal; + } + + if (background->type == ZR_STYLE_ITEM_IMAGE) + zr_draw_image(out, *selector, &background->data.image); + else zr_fill_circle(out, *selector, background->data.color); + if (active) { + if (cursor->type == ZR_STYLE_ITEM_IMAGE) + zr_draw_image(out, *cursors, &cursor->data.image); + else zr_fill_circle(out, *cursors, cursor->data.color); + } + + text.padding.x = 0; + text.padding.y = 0; + text.background = style->text_background; + zr_widget_text(out, *label, string, len, &text, ZR_TEXT_LEFT, font); +} + +static int +zr_do_toggle(zr_flags *state, + struct zr_command_buffer *out, struct zr_rect r, + int *active, const char *str, zr_size len, enum zr_toggle_type type, + const struct zr_style_toggle *style, const struct zr_input *in, + const struct zr_user_font *font) +{ + int was_active; + struct zr_rect bounds; + struct zr_rect select; + struct zr_rect cursor; + struct zr_rect label; + float cursor_pad; + + ZR_ASSERT(style); + ZR_ASSERT(out); + ZR_ASSERT(font); + if (!out || !style || !font || !active) + return 0; + + r.w = ZR_MAX(r.w, font->height + 2 * style->padding.x); + r.h = ZR_MAX(r.h, font->height + 2 * style->padding.y); + + /* add additional touch padding for touch screen devices */ + bounds.x = r.x - style->touch_padding.x; + bounds.y = r.y - style->touch_padding.y; + bounds.w = r.w + 2 * style->touch_padding.x; + bounds.h = r.h + 2 * style->touch_padding.y; + + /* calculate the selector space */ + select.w = ZR_MIN(r.h, font->height + style->padding.y); + select.h = select.w; + select.x = r.x + style->padding.x; + select.y = (r.y + style->padding.y + (select.w / 2)) - (font->height / 2); + cursor_pad = (type == ZR_TOGGLE_OPTION) ? + (float)(int)(select.w / 4): + (float)(int)(select.h / 6); + + /* calculate the bounds of the cursor inside the selector */ + select.h = ZR_MAX(select.w, cursor_pad * 2); + cursor.h = select.h - cursor_pad * 2; + cursor.w = cursor.h; + cursor.x = select.x + cursor_pad; + cursor.y = select.y + cursor_pad; + + /* label behind the selector */ + label.x = r.x + select.w + style->padding.x * 2; + label.y = select.y; + label.w = ZR_MAX(r.x + r.w, label.x + style->padding.x); + label.w -= (label.x + style->padding.x); + label.h = select.w; + + was_active = *active; + *active = zr_toggle_behavior(in, bounds, state, *active); + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (type == ZR_TOGGLE_CHECK) { + if (style->draw.checkbox) + style->draw.checkbox(out, *state, + style, *active, &label, &select, &cursor, str, len, font); + else zr_draw_checkbox(out, *state, style, *active, &label, + &select, &cursor, str, len, font); + } else { + if (style->draw.radio) + style->draw.radio(out, *state, style, + *active, &label, &select, &cursor, str, len, font); + else zr_draw_option(out, *state, style, *active, &label, + &select, &cursor, str, len, font); + } + if (style->draw_end) + style->draw_begin(out, style->userdata); + return (was_active != *active); +} + +/* =============================================================== + * + * SELECTABLE + * + * ===============================================================*/ +static void +zr_draw_selectable(struct zr_command_buffer *out, + zr_flags state, const struct zr_style_selectable *style, int active, + const struct zr_rect *bounds, const char *string, zr_size len, + zr_flags align, const struct zr_user_font *font) +{ + const struct zr_style_item *background; + struct zr_text text; + text.padding = style->padding; + + if (!active) { + if (state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->pressed; + text.text = style->text_pressed; + } else if (state & ZR_WIDGET_STATE_HOVERED) { + background = &style->hover; + text.text = style->text_hover; + } else { + background = &style->normal; + text.text = style->text_normal; + } + } else { + if (state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->pressed_active; + text.text = style->text_pressed_active; + } else if (state & ZR_WIDGET_STATE_HOVERED) { + background = &style->hover_active; + text.text = style->text_hover_active; + } else { + background = &style->normal_active; + text.text = style->text_normal_active; + } + } + + if (background->type == ZR_STYLE_ITEM_IMAGE) { + zr_draw_image(out, *bounds, &background->data.image); + text.background = zr_rgba(0,0,0,0); + } else { + zr_fill_rect(out, *bounds, style->rounding, background->data.color); + text.background = background->data.color; + } + zr_widget_text(out, *bounds, string, len, &text, align, font); +} + +static int +zr_do_selectable(zr_flags *state, struct zr_command_buffer *out, + struct zr_rect bounds, const char *str, zr_size len, zr_flags align, int *value, + const struct zr_style_selectable *style, const struct zr_input *in, + const struct zr_user_font *font) +{ + int old_value; + struct zr_rect touch; + + ZR_ASSERT(state); + ZR_ASSERT(out); + ZR_ASSERT(str); + ZR_ASSERT(len); + ZR_ASSERT(value); + ZR_ASSERT(style); + ZR_ASSERT(font); + + if (!state || !out || !str || !len || !value || !style || !font) return 0; + old_value = *value; + + touch.x = bounds.x - style->touch_padding.x; + touch.y = bounds.y - style->touch_padding.y; + touch.w = bounds.w + style->touch_padding.x * 2; + touch.h = bounds.h + style->touch_padding.y * 2; + if (zr_button_behavior(state, touch, in, ZR_BUTTON_DEFAULT)) + *value = !(*value); + + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw) + style->draw(out, *state, style, *value, &bounds, + str, len, align, font); + else zr_draw_selectable(out, *state, style, *value, &bounds, + str, len, align, font); + if (style->draw_end) + style->draw_begin(out, style->userdata); + return old_value != *value; +} + +/* =============================================================== + * + * SLIDER + * + * ===============================================================*/ +static float +zr_slider_behavior(zr_flags *state, struct zr_rect *cursor, + const struct zr_input *in, const struct zr_style_slider *style, + struct zr_rect bounds, float slider_min, float slider_max, float slider_value, + float slider_step, float slider_steps) +{ + int inslider = in && zr_input_is_mouse_hovering_rect(in, bounds); + int incursor = in && zr_input_has_mouse_click_down_in_rect(in, ZR_BUTTON_LEFT, bounds, zr_true); + + *state = (inslider) ? ZR_WIDGET_STATE_HOVERED: ZR_WIDGET_STATE_INACTIVE; + if (in && inslider && incursor) + { + const float d = in->mouse.pos.x - (cursor->x + cursor->w / 2.0f); + const float pxstep = (bounds.w - (2 * style->padding.x)) / slider_steps; + + /* only update value if the next slider step is reached */ + *state = ZR_WIDGET_STATE_ACTIVE; + if (ZR_ABS(d) >= pxstep) { + float ratio = 0; + const float steps = (float)((int)(ZR_ABS(d) / pxstep)); + slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps); + slider_value = ZR_CLAMP(slider_min, slider_value, slider_max); + ratio = (slider_value - slider_min)/slider_step; + cursor->x = bounds.x + (cursor->w * ratio); + } + } + if (*state == ZR_WIDGET_STATE_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, bounds)) + *state |= ZR_WIDGET_STATE_ENTERED; + else if (zr_input_is_mouse_prev_hovering_rect(in, bounds)) + *state |= ZR_WIDGET_STATE_LEFT; + return slider_value; +} + +static void +zr_draw_slider(struct zr_command_buffer *out, zr_flags state, + const struct zr_style_slider *style, const struct zr_rect *bounds, + const struct zr_rect *virtual_cursor, float min, float value, float max) +{ + struct zr_rect fill; + struct zr_rect bar; + struct zr_rect scursor; + const struct zr_style_item *background; + + struct zr_color bar_color; + const struct zr_style_item *cursor; + if (state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->active; + bar_color = style->bar_active; + cursor = &style->cursor_active; + } else if (state & ZR_WIDGET_STATE_HOVERED) { + background = &style->hover; + bar_color = style->bar_hover; + cursor = &style->cursor_hover; + } else { + background = &style->normal; + bar_color = style->bar_normal; + cursor = &style->cursor_normal; + } + + bar.x = bounds->x; + bar.y = (bounds->y + virtual_cursor->h/2) - virtual_cursor->h/8; + bar.w = bounds->w; + bar.h = bounds->h/6; + + scursor.h = style->cursor_size.y; + scursor.w = style->cursor_size.x; + scursor.y = (bar.y + bar.h/2.0f) - scursor.h/2.0f; + scursor.x = (value <= min) ? virtual_cursor->x: (value >= max) ? + ((bar.x + bar.w) - virtual_cursor->w): + virtual_cursor->x - (virtual_cursor->w/2); + + fill.w = (scursor.x + (scursor.w/2.0f)) - bar.x; + fill.x = bar.x; + fill.y = bar.y; + fill.h = bar.h; + + /* draw background */ + if (background->type == ZR_STYLE_ITEM_IMAGE) { + zr_draw_image(out, *bounds, &background->data.image); + } else { + zr_fill_rect(out, *bounds, style->rounding, style->border_color); + zr_fill_rect(out, zr_shrink_rect(*bounds, style->border), style->rounding, + background->data.color); + } + + /* draw slider bar */ + zr_fill_rect(out, bar, style->rounding, bar_color); + zr_fill_rect(out, fill, style->rounding, style->bar_filled); + + /* draw cursor */ + if (cursor->type == ZR_STYLE_ITEM_IMAGE) + zr_draw_image(out, scursor, &cursor->data.image); + else zr_fill_circle(out, scursor, cursor->data.color); +} + +static float +zr_do_slider(zr_flags *state, + struct zr_command_buffer *out, struct zr_rect bounds, + float min, float val, float max, float step, + const struct zr_style_slider *style, const struct zr_input *in, + const struct zr_user_font *font) +{ + float slider_range; + float slider_min; + float slider_max; + float slider_value; + float slider_steps; + float cursor_offset; + struct zr_rect cursor; + + ZR_ASSERT(style); + ZR_ASSERT(out); + if (!out || !style) + return 0; + + /* remove padding from slider bounds */ + bounds.x = bounds.x + style->padding.x; + bounds.y = bounds.y + style->padding.y; + bounds.h = ZR_MAX(bounds.h, 2 * style->padding.y); + bounds.w = ZR_MAX(bounds.w, 1 + bounds.h + 2 * style->padding.x); + bounds.h -= 2 * style->padding.y; + bounds.w -= 2 * style->padding.y; + + /* optional buttons */ + if (style->show_buttons) { + zr_flags ws; + struct zr_rect button; + button.y = bounds.y; + button.w = bounds.h; + button.h = bounds.h; + + /* decrement button */ + button.x = bounds.x; + if (zr_do_button_symbol(&ws, out, button, style->dec_symbol, ZR_BUTTON_DEFAULT, + &style->dec_button, in, font)) + val -= step; + + /* increment button */ + button.x = (bounds.x + bounds.w) - button.w; + if (zr_do_button_symbol(&ws, out, button, style->inc_symbol, ZR_BUTTON_DEFAULT, + &style->inc_button, in, font)) + val += step; + + bounds.x = bounds.x + button.w + style->spacing.x; + bounds.w = bounds.w - (2 * button.w + 2 * style->spacing.x); + } + + /* make sure the provided values are correct */ + slider_max = ZR_MAX(min, max); + slider_min = ZR_MIN(min, max); + slider_value = ZR_CLAMP(slider_min, val, slider_max); + slider_range = slider_max - slider_min; + slider_steps = slider_range / step; + + /* calculate slider virtual cursor bounds */ + cursor_offset = (slider_value - slider_min) / step; + cursor.h = bounds.h; + cursor.w = bounds.w / (slider_steps + 1); + cursor.x = bounds.x + (cursor.w * cursor_offset); + cursor.y = bounds.y; + slider_value = zr_slider_behavior(state, &cursor, in, style, bounds, + slider_min, slider_max, slider_value, step, slider_steps); + + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw) + style->draw(out, *state, style, &bounds, &cursor, + slider_min, slider_value, slider_max); + else zr_draw_slider(out, *state, style, &bounds, &cursor, + slider_min, slider_value, slider_max); + if (style->draw_end) + style->draw_begin(out, style->userdata); + return slider_value; +} + +/* =============================================================== + * + * PROGRESSBAR + * + * ===============================================================*/ +static zr_size +zr_progress_behavior(zr_flags *state, const struct zr_input *in, + struct zr_rect r, zr_size max, zr_size value, int modifiable) +{ + *state = ZR_WIDGET_STATE_INACTIVE; + if (in && modifiable && zr_input_is_mouse_hovering_rect(in, r)) { + if (zr_input_is_mouse_down(in, ZR_BUTTON_LEFT)) { + float ratio = ZR_MAX(0, (float)(in->mouse.pos.x - r.x)) / (float)r.w; + value = (zr_size)ZR_MAX(0,((float)max * ratio)); + *state = ZR_WIDGET_STATE_ACTIVE; + } else *state = ZR_WIDGET_STATE_HOVERED; + } + if (*state == ZR_WIDGET_STATE_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, r)) + *state |= ZR_WIDGET_STATE_ENTERED; + else if (zr_input_is_mouse_prev_hovering_rect(in, r)) + *state |= ZR_WIDGET_STATE_LEFT; + + if (!max) return value; + value = ZR_MIN(value, max); + return value; +} + +static void +zr_draw_progress(struct zr_command_buffer *out, zr_flags state, + const struct zr_style_progress *style, const struct zr_rect *bounds, + const struct zr_rect *scursor, zr_size value, zr_size max) +{ + const struct zr_style_item *background; + const struct zr_style_item *cursor; + + ZR_UNUSED(max); + ZR_UNUSED(value); + if (state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->active; + cursor = &style->cursor_active; + } else if (state & ZR_WIDGET_STATE_HOVERED){ + background = &style->hover; + cursor = &style->cursor_hover; + } else { + background = &style->normal; + cursor = &style->cursor_normal; + } + + if (background->type == ZR_STYLE_ITEM_IMAGE) + zr_draw_image(out, *bounds, &background->data.image); + else zr_fill_rect(out, *bounds, style->rounding, background->data.color); + + if (cursor->type == ZR_STYLE_ITEM_IMAGE) + zr_draw_image(out, *scursor, &cursor->data.image); + else zr_fill_rect(out, *scursor, style->rounding, cursor->data.color); +} + +static zr_size +zr_do_progress(zr_flags *state, + struct zr_command_buffer *out, struct zr_rect bounds, + zr_size value, zr_size max, int modifiable, + const struct zr_style_progress *style, const struct zr_input *in) +{ + zr_size prog_value; + float prog_scale; + struct zr_rect cursor; + + ZR_ASSERT(style); + ZR_ASSERT(out); + if (!out || !style) return 0; + + cursor.w = ZR_MAX(bounds.w, 2 * style->padding.x); + cursor.h = ZR_MAX(bounds.h, 2 * style->padding.y); + cursor = zr_pad_rect(bounds, zr_vec2(style->padding.x, style->padding.y)); + + prog_scale = (float)value / (float)max; + cursor.w = (bounds.w - 2) * prog_scale; + + prog_value = ZR_MIN(value, max); + prog_value = zr_progress_behavior(state, in, bounds, max, prog_value, modifiable); + + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw) + style->draw(out, *state, style, &bounds, &cursor, value, max); + else zr_draw_progress(out, *state, style, &bounds, &cursor, value, max); + if (style->draw_end) + style->draw_begin(out, style->userdata); + return prog_value; +} + +/* =============================================================== + * + * SCROLLBAR + * + * ===============================================================*/ +static float +zr_scrollbar_behavior(zr_flags *state, struct zr_input *in, + int has_scrolling, struct zr_rect scroll, + struct zr_rect cursor, float scroll_offset, + float target, float scroll_step, enum zr_orientation o) +{ + int left_mouse_down; + int left_mouse_click_in_cursor; + if (!in) return scroll_offset; + + *state = ZR_WIDGET_STATE_INACTIVE; + left_mouse_down = in->mouse.buttons[ZR_BUTTON_LEFT].down; + left_mouse_click_in_cursor = zr_input_has_mouse_click_down_in_rect(in, + ZR_BUTTON_LEFT, cursor, zr_true); + if (zr_input_is_mouse_hovering_rect(in, scroll)) + *state = ZR_WIDGET_STATE_HOVERED; + + if (left_mouse_down && left_mouse_click_in_cursor) { + /* update cursor by mouse dragging */ + float pixel, delta; + *state = ZR_WIDGET_STATE_ACTIVE; + if (o == ZR_VERTICAL) { + pixel = in->mouse.delta.y; + delta = (pixel / scroll.h) * target; + scroll_offset = ZR_CLAMP(0, scroll_offset + delta, target - scroll.h); + /* This is probably one of my most disgusting hacks I have ever done. + * This basically changes the mouse clicked position with the moving + * cursor. This allows for better scroll behavior but resulted into me + * having to remove const correctness for input. But in the end I believe + * it is worth it. */ + in->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y; + } else { + pixel = in->mouse.delta.x; + delta = (pixel / scroll.w) * target; + scroll_offset = ZR_CLAMP(0, scroll_offset + delta, target - scroll.w); + in->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x; + } + } else if (has_scrolling && ((in->mouse.scroll_delta<0) || + (in->mouse.scroll_delta>0))) { + /* update cursor by mouse scrolling */ + scroll_offset = scroll_offset + scroll_step * (-in->mouse.scroll_delta); + if (o == ZR_VERTICAL) + scroll_offset = ZR_CLAMP(0, scroll_offset, target - scroll.h); + else scroll_offset = ZR_CLAMP(0, scroll_offset, target - scroll.w); + } + if (*state == ZR_WIDGET_STATE_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, scroll)) + *state |= ZR_WIDGET_STATE_ENTERED; + else if (zr_input_is_mouse_prev_hovering_rect(in, scroll)) + *state |= ZR_WIDGET_STATE_LEFT; + return scroll_offset; +} + +static void +zr_draw_scrollbar(struct zr_command_buffer *out, zr_flags state, + const struct zr_style_scrollbar *style, const struct zr_rect *bounds, + const struct zr_rect *scroll) +{ + const struct zr_style_item *background; + const struct zr_style_item *cursor; + + if (state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->active; + cursor = &style->cursor_active; + } else if (state & ZR_WIDGET_STATE_HOVERED) { + background = &style->hover; + cursor = &style->cursor_hover; + } else { + background = &style->normal; + cursor = &style->cursor_normal; + } + + /* draw background */ + if (background->type == ZR_STYLE_ITEM_COLOR) { + zr_fill_rect(out, *bounds, style->rounding, style->border_color); + zr_fill_rect(out, zr_shrink_rect(*bounds,style->border), style->rounding, background->data.color); + } else { + zr_draw_image(out, *bounds, &background->data.image); + } + + /* draw cursor */ + if (cursor->type == ZR_STYLE_ITEM_IMAGE) + zr_draw_image(out, *scroll, &cursor->data.image); + else zr_fill_rect(out, *scroll, style->rounding, cursor->data.color); +} + +static float +zr_do_scrollbarv(zr_flags *state, + struct zr_command_buffer *out, struct zr_rect scroll, int has_scrolling, + float offset, float target, float step, float button_pixel_inc, + const struct zr_style_scrollbar *style, struct zr_input *in, + const struct zr_user_font *font) +{ + struct zr_rect cursor; + float scroll_step; + float scroll_offset; + float scroll_off; + float scroll_ratio; + + ZR_ASSERT(out); + ZR_ASSERT(style); + ZR_ASSERT(state); + if (!out || !style) return 0; + + scroll.w = ZR_MAX(scroll.w, 1); + scroll.h = ZR_MAX(scroll.h, 2 * scroll.w); + if (target <= scroll.h) return 0; + + /* optional scrollbar buttons */ + if (style->show_buttons) { + zr_flags ws; + float scroll_h; + struct zr_rect button; + button.x = scroll.x; + button.w = scroll.w; + button.h = scroll.w; + + scroll_h = scroll.h - 2 * button.h; + scroll_step = ZR_MIN(step, button_pixel_inc); + + /* decrement button */ + button.y = scroll.y; + if (zr_do_button_symbol(&ws, out, button, style->dec_symbol, + ZR_BUTTON_REPEATER, &style->dec_button, in, font)) + offset = offset - scroll_step; + + /* increment button */ + button.y = scroll.y + scroll.h - button.h; + if (zr_do_button_symbol(&ws, out, button, style->inc_symbol, + ZR_BUTTON_REPEATER, &style->inc_button, in, font)) + offset = offset + scroll_step; + + scroll.y = scroll.y + button.h; + scroll.h = scroll_h; + } + + /* calculate scrollbar constants */ + scroll_step = ZR_MIN(step, scroll.h); + scroll_offset = ZR_CLAMP(0, offset, target - scroll.h); + scroll_ratio = scroll.h / target; + scroll_off = scroll_offset / target; + + /* calculate scrollbar cursor bounds */ + cursor.h = (scroll_ratio * scroll.h - 2); + cursor.y = scroll.y + (scroll_off * scroll.h) + 1; + cursor.w = scroll.w - 2; + cursor.x = scroll.x + 1; + + /* update scrollbar */ + scroll_offset = zr_scrollbar_behavior(state, in, has_scrolling, scroll, cursor, + scroll_offset, target, scroll_step, ZR_VERTICAL); + scroll_off = scroll_offset / target; + cursor.y = scroll.y + (scroll_off * scroll.h); + + /* draw scrollbar */ + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw) + style->draw(out, *state, style, &scroll, &cursor); + else zr_draw_scrollbar(out, *state, style, &scroll, &cursor); + if (style->draw_end) + style->draw_begin(out, style->userdata); + return scroll_offset; +} + +static float +zr_do_scrollbarh(zr_flags *state, + struct zr_command_buffer *out, struct zr_rect scroll, int has_scrolling, + float offset, float target, float step, float button_pixel_inc, + const struct zr_style_scrollbar *style, struct zr_input *in, + const struct zr_user_font *font) +{ + struct zr_rect cursor; + float scroll_step; + float scroll_offset; + float scroll_off; + float scroll_ratio; + + ZR_ASSERT(out); + ZR_ASSERT(style); + if (!out || !style) return 0; + + /* scrollbar background */ + scroll.h = ZR_MAX(scroll.h, 1); + scroll.w = ZR_MAX(scroll.w, 2 * scroll.h); + if (target <= scroll.w) return 0; + + /* optional scrollbar buttons */ + if (style->show_buttons) { + zr_flags ws; + float scroll_w; + struct zr_rect button; + button.y = scroll.y; + button.w = scroll.h; + button.h = scroll.h; + + scroll_w = scroll.w - 2 * button.w; + scroll_step = ZR_MIN(step, button_pixel_inc); + + /* decrement button */ + button.x = scroll.x; + if (zr_do_button_symbol(&ws, out, button, style->dec_symbol, + ZR_BUTTON_REPEATER, &style->dec_button, in, font)) + offset = offset - scroll_step; + + /* increment button */ + button.x = scroll.x + scroll.w - button.w; + if (zr_do_button_symbol(&ws, out, button, style->inc_symbol, + ZR_BUTTON_REPEATER, &style->inc_button, in, font)) + offset = offset + scroll_step; + + scroll.x = scroll.x + button.w; + scroll.w = scroll_w; + } + + /* calculate scrollbar constants */ + scroll_step = ZR_MIN(step, scroll.w); + scroll_offset = ZR_CLAMP(0, offset, target - scroll.w); + scroll_ratio = scroll.w / target; + scroll_off = scroll_offset / target; + + /* calculate cursor bounds */ + cursor.w = scroll_ratio * scroll.w - 2; + cursor.x = scroll.x + (scroll_off * scroll.w) + 1; + cursor.h = scroll.h - 2; + cursor.y = scroll.y + 1; + + /* update scrollbar */ + scroll_offset = zr_scrollbar_behavior(state, in, has_scrolling, scroll, cursor, + scroll_offset, target, scroll_step, ZR_HORIZONTAL); + scroll_off = scroll_offset / target; + cursor.x = scroll.x + (scroll_off * scroll.w); + + /* draw scrollbar */ + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw) + style->draw(out, *state, style, &scroll, &cursor); + else zr_draw_scrollbar(out, *state, style, &scroll, &cursor); + if (style->draw_end) + style->draw_begin(out, style->userdata); + return scroll_offset; +} + +/* =============================================================== + * + * FILTER + * + * ===============================================================*/ +int zr_filter_default(const struct zr_edit_box *box, zr_rune unicode) +{(void)unicode;ZR_UNUSED(box);return zr_true;} + +int +zr_filter_ascii(const struct zr_edit_box *box, zr_rune unicode) +{ + ZR_UNUSED(box); + if (unicode > 128) return zr_false; + else return zr_true; +} + +int +zr_filter_float(const struct zr_edit_box *box, zr_rune unicode) +{ + ZR_UNUSED(box); + if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-') + return zr_false; + else return zr_true; +} + +int +zr_filter_decimal(const struct zr_edit_box *box, zr_rune unicode) +{ + ZR_UNUSED(box); + if ((unicode < '0' || unicode > '9') && unicode != '-') + return zr_false; + else return zr_true; +} + +int +zr_filter_hex(const struct zr_edit_box *box, zr_rune unicode) +{ + ZR_UNUSED(box); + if ((unicode < '0' || unicode > '9') && + (unicode < 'a' || unicode > 'f') && + (unicode < 'A' || unicode > 'F')) + return zr_false; + else return zr_true; +} + +int +zr_filter_oct(const struct zr_edit_box *box, zr_rune unicode) +{ + ZR_UNUSED(box); + if (unicode < '0' || unicode > '7') + return zr_false; + else return zr_true; +} + +int +zr_filter_binary(const struct zr_edit_box *box, zr_rune unicode) +{ + ZR_UNUSED(box); + if (unicode != '0' && unicode != '1') + return zr_false; + else return zr_true; +} + +/* =============================================================== + * + * EDIT + * + * ===============================================================*/ +static void +zr_edit_input_behavior(struct zr_edit_box *box, const struct zr_input *in, int has_special) +{ + char *buffer = zr_edit_box_get(box); + zr_size len = zr_edit_box_len_char(box); + zr_size min = ZR_MIN(box->sel.end, box->sel.begin); + zr_size maxi = ZR_MAX(box->sel.end, box->sel.begin); + zr_size diff = maxi - min; + int enter, tab; + + /* text manipulation */ + if (zr_input_is_key_pressed(in,ZR_KEY_DEL)) + zr_edit_box_remove(box, ZR_DELETE); + else if (zr_input_is_key_pressed(in,ZR_KEY_BACKSPACE)) + zr_edit_box_remove(box, ZR_REMOVE); + + enter = has_special && zr_input_is_key_pressed(in, ZR_KEY_ENTER); + tab = has_special && zr_input_is_key_pressed(in, ZR_KEY_TAB); + if (in->keyboard.text_len || enter || tab) { + if (diff && box->cursor != box->glyphs) { + /* replace text selection */ + zr_edit_box_remove(box, ZR_DELETE); + box->cursor = min; + } + if (enter) zr_edit_box_add(box, "\n", 1); + else if (tab) zr_edit_box_add(box, " ", 4); + else zr_edit_box_buffer_input(box, in); + box->sel.begin = box->cursor; + box->sel.end = box->cursor; + } + + /* cursor key movement */ + if (zr_input_is_key_pressed(in, ZR_KEY_LEFT)) { + box->cursor = (zr_size)(ZR_MAX(0, (int)box->cursor - 1)); + box->sel.begin = box->cursor; + box->sel.end = box->cursor; + } + if (zr_input_is_key_pressed(in, ZR_KEY_RIGHT) && box->cursor < box->glyphs) { + box->cursor = ZR_MIN((!box->glyphs) ? 0 : box->glyphs, box->cursor + 1); + box->sel.begin = box->cursor; + box->sel.end = box->cursor; + } + + /* copy & cut & paste functionlity */ + if (zr_input_is_key_pressed(in, ZR_KEY_PASTE) && box->clip.paste) + box->clip.paste(box->clip.userdata, box); + + if ((zr_input_is_key_pressed(in, ZR_KEY_COPY) && box->clip.copy) || + (zr_input_is_key_pressed(in, ZR_KEY_CUT) && box->clip.copy)) { + if (diff && box->cursor != box->glyphs) { + /* copy or cut text selection */ + zr_size l; + zr_rune unicode; + char *begin, *end; + begin = zr_edit_buffer_at(&box->buffer, (int)min, &unicode, &l); + end = zr_edit_buffer_at(&box->buffer, (int)maxi, &unicode, &l); + box->clip.copy(box->clip.userdata, begin, (zr_size)(end - begin)); + if (zr_input_is_key_pressed(in, ZR_KEY_CUT)) + zr_edit_box_remove(box, ZR_DELETE); + } else { + /* copy or cut complete buffer */ + box->clip.copy(box->clip.userdata, buffer, len); + if (zr_input_is_key_pressed(in, ZR_KEY_CUT)) + zr_edit_box_clear(box); + } + } +} + +static void +zr_edit_click_behavior(zr_flags *state, const struct zr_style_edit *style, + struct zr_rect *bounds, int show_cursor, struct zr_edit_box *box, + const struct zr_input *in, const struct zr_user_font *font, const char *text, + /* these three here describe the current text frame */ + zr_size text_len, zr_size glyph_off, zr_size glyph_cnt) +{ + /* check if the editbox is activated/deactivated */ + if (!in) return; + *state = ZR_WIDGET_STATE_INACTIVE; + if (in && in->mouse.buttons[ZR_BUTTON_LEFT].clicked && + in->mouse.buttons[ZR_BUTTON_LEFT].down) { + box->active = ZR_INBOX(in->mouse.pos.x,in->mouse.pos.y,bounds->x,bounds->y,bounds->w,bounds->h); + if (box->active) *state = ZR_WIDGET_STATE_ACTIVE; + } + if (ZR_INBOX(in->mouse.pos.x, in->mouse.pos.y, bounds->x, bounds->y, bounds->w, bounds->h)) + *state |= ZR_WIDGET_STATE_HOVERED; + + /* set cursor by mouse click and handle text selection */ + if (in && show_cursor && in->mouse.buttons[ZR_BUTTON_LEFT].down && box->active) { + const char *visible = text; + float xoff = in->mouse.pos.x - (bounds->x + style->padding.x + style->border); + if (*state & ZR_WIDGET_STATE_HOVERED) + { + /* text selection in current text frame */ + zr_size glyph_index; + zr_size glyph_pos=zr_user_font_glyph_index_at_pos(font,visible,text_len,xoff); + if (glyph_cnt + glyph_off >= box->glyphs) + glyph_index = glyph_off + ZR_MIN(glyph_pos, glyph_cnt); + else glyph_index = glyph_off + ZR_MIN(glyph_pos, glyph_cnt-1); + + if (text_len) + zr_edit_box_set_cursor(box, glyph_index); + if (!box->sel.active) { + box->sel.active = zr_true; + box->sel.begin = glyph_index; + box->sel.end = box->sel.begin; + } else { + if (box->sel.begin > glyph_index) { + box->sel.end = glyph_index; + box->sel.active = zr_true; + } + } + } else if (!ZR_INBOX(in->mouse.pos.x,in->mouse.pos.y,bounds->x,bounds->y,bounds->w,bounds->h) && + ZR_INBOX(in->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.x, + in->mouse.buttons[ZR_BUTTON_LEFT].clicked_pos.y,bounds->x,bounds->y,bounds->w,bounds->h) + && box->cursor != box->glyphs && box->cursor > 0) + { + /* text selection out of the current text frame */ + zr_size glyph = ((in->mouse.pos.x > bounds->x) && + box->cursor+1 < box->glyphs) ? + box->cursor+1: box->cursor-1; + zr_edit_box_set_cursor(box, glyph); + if (box->sel.active) { + box->sel.end = glyph; + box->sel.active = zr_true; + } + } else box->sel.active = zr_false; + } else box->sel.active = zr_false; +} + +static void +zr_draw_edit(struct zr_command_buffer *out, zr_flags state, + const struct zr_style_edit *style, const struct zr_rect *bounds, + const struct zr_rect *label, const struct zr_rect *selection, + int show_cursor, const char *unselected_text, zr_size unselected_len, + const char *selected_text, zr_size selected_len, + const struct zr_edit_box *box, const struct zr_user_font *font) +{ + const struct zr_style_item *background; + const struct zr_style_item *cursor; + struct zr_color selected; + struct zr_color sel_text; + struct zr_color text; + + /* select correct colors */ + struct zr_text txt; + if (state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->active; + cursor = &style->cursor_active; + text = style->text_active; + selected = style->selected_normal; + sel_text = style->selected_text_normal; + } else if (state & ZR_WIDGET_STATE_HOVERED) { + background = &style->hover; + cursor = &style->cursor_hover; + text = style->text_hover; + selected = style->selected_hover; + sel_text = style->selected_hover; + } else { + background = &style->normal; + cursor = &style->cursor_normal; + text = style->text_normal; + selected = style->selected_normal; + sel_text = style->selected_normal; + } + + /* draw background color/image */ + if (background->type == ZR_STYLE_ITEM_IMAGE) { + zr_draw_image(out, *bounds, &background->data.image); + txt.background = zr_rgba(0,0,0,0); + } else { + txt.background = background->data.color; + zr_fill_rect(out, *bounds, style->rounding, style->border_color); + zr_fill_rect(out, zr_shrink_rect(*bounds, style->border), + style->rounding, style->normal.data.color); + } + + /* draw unselected text */ + txt.padding = zr_vec2(0,0); + txt.text = text; + zr_widget_text(out, *label, unselected_text, unselected_len, + &txt, ZR_TEXT_LEFT, font); + + if (box->active && show_cursor) { + if (box->cursor == box->glyphs) { + /* draw cursor at the end of the string */ + float text_width; + zr_size cursor_w = (zr_size)style->cursor_size; + zr_size s = font->width(font->userdata, font->height, + unselected_text, unselected_len); + text_width = (float)s; + if (cursor->type == ZR_STYLE_ITEM_IMAGE) + zr_draw_image(out, zr_rect(label->x+(float)text_width, + label->y, (float)cursor_w, label->h), &cursor->data.image); + else zr_fill_rect(out, zr_rect(label->x+(float)text_width, + label->y, (float)cursor_w, label->h), 0, cursor->data.color); + } else { + /* draw text selection */ + struct zr_rect clip = out->clip; + zr_push_scissor(out, clip); + zr_fill_rect(out, *selection, 0, selected); + + txt.padding = zr_vec2(0,0); + txt.background = selected; + txt.text = sel_text; + zr_widget_text(out, *selection, selected_text, selected_len, + &txt, ZR_TEXT_LEFT, font); + zr_push_scissor(out, clip); + } + } +} + +static void +zr_do_edit_buffer(zr_flags *state, struct zr_command_buffer *out, + struct zr_rect bounds, struct zr_edit_box *box, const struct zr_style_edit *style, + int show_cursor, const struct zr_input *in, const struct zr_user_font *font) +{ + char *buffer; + zr_size len; + + /* text frame */ + zr_size text_len = 0; + zr_size glyph_off = 0; + zr_size glyph_cnt = 0; + zr_size offset = 0; + float text_width = 0; + + /* selection text */ + char *selection_begin = 0, *selection_end = 0; + zr_size off_begin = 0, off_end = 0, off_max = 0; + + struct zr_rect label; + struct zr_rect selection = zr_rect(0,0,0,0); + + ZR_ASSERT(out); + ZR_ASSERT(font); + ZR_ASSERT(style); + ZR_ASSERT(state); + if (!out || !box || !style) + return; + + buffer = zr_edit_box_get(box); + text_len = len = zr_edit_box_len_char(box); + bounds.w = ZR_MAX(bounds.w, 2 * style->padding.x + 2 * style->border); + bounds.h = ZR_MAX(bounds.h, font->height + (2 * style->padding.y + 2 * style->border)); + + /* calculate visible text frame */ + label.w = ZR_MAX(bounds.w, - 2 * style->padding.x - 2 * style->border); + label.w -= 2 * style->padding.x - 2 * style->border; + { + zr_size frames = 0; + zr_size glyphs = 0; + zr_size frame_len = 0; + zr_size row_len = 0; + zr_size cursor_w = (zr_size)style->cursor_size; + float space = ZR_MAX(label.w, (float)cursor_w); + space -= (float)cursor_w; + + while (text_len) { + frames++; + offset += frame_len; + frame_len = zr_user_font_glyphs_fitting_in_space(font, + &buffer[offset], text_len, space, &row_len, &glyphs, &text_width, 0); + glyph_off += glyphs; + if (glyph_off > box->cursor || !frame_len) break; + text_len -= frame_len; + } + + text_len = frame_len; + glyph_cnt = glyphs; + glyph_off = (frames <= 1) ? 0 : (glyph_off - glyphs); + offset = (frames <= 1) ? 0 : offset; + } + + /* update edit state */ + if (box->active && in) + zr_edit_input_behavior(box, in, 0); + zr_edit_click_behavior(state, style, &bounds, show_cursor, box, in, font, + &buffer[offset], text_len, glyph_off, glyph_cnt); + + /* calculate unselected text bounds */ + label.x = bounds.x + style->padding.x + style->border; + label.y = bounds.y + style->padding.y + style->border; + label.h = bounds.h - (2 * style->padding.y + 2 * style->border); + + /* calculate selected text */ + if (box->active && show_cursor && box->cursor < box->glyphs) { + zr_size s; + zr_rune unicode; + + /* calculate selection text range */ + zr_size min = ZR_MIN(box->sel.end, box->sel.begin); + zr_size maxi = ZR_MAX(box->sel.end, box->sel.begin); + selection_begin = zr_edit_buffer_at(&box->buffer, (int)min, &unicode, &off_max); + selection_end = zr_edit_buffer_at(&box->buffer, (int)maxi, &unicode, &off_max); + off_begin = (zr_size)(selection_begin - (char*)box->buffer.memory.ptr); + off_end = (zr_size)(selection_end - (char*)box->buffer.memory.ptr); + + /* calculate selected text bounds */ + selection = label; + s = font->width(font->userdata, font->height, buffer + offset, off_begin - offset); + selection.x += (float)s; + s = font->width(font->userdata, font->height, selection_begin, ZR_MAX(off_max, off_end - off_begin)); + selection.w = (float)s; + } + + /* draw edit */ + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw) + style->draw(out, *state, style, &bounds, &label, &selection, + show_cursor, &buffer[offset], text_len, selection_begin, + ZR_MAX(off_max, off_end - off_begin), box, font); + else zr_draw_edit(out, *state, style, &bounds, &label, &selection, + show_cursor, &buffer[offset], text_len, selection_begin, + ZR_MAX(off_max, off_end - off_begin), box, font); + if (style->draw_end) + style->draw_begin(out, style->userdata); +} + +static zr_size +zr_do_edit_string(zr_flags *state, struct zr_command_buffer *out, struct zr_rect r, + char *buffer, zr_size len, zr_size max, int *active, + zr_size *cursor, int show_cursor, const struct zr_style_edit *style, + zr_filter filter, const struct zr_input *in, const struct zr_user_font *font) +{ + struct zr_edit_box box; + zr_edit_box_init(&box, buffer, max, 0, filter); + box.buffer.allocated = len; + box.active = *active; + box.glyphs = zr_utf_len(buffer, len); + if (!cursor) { + box.cursor = box.glyphs; + } else{ + box.cursor = ZR_MIN(*cursor, box.glyphs); + box.sel.begin = box.cursor; + box.sel.end = box.cursor; + } + zr_do_edit_buffer(state, out, r, &box, style, show_cursor, in, font); + + *active = box.active; + if (cursor) *cursor = box.cursor; + return zr_edit_box_len_char(&box); +} + +/* =============================================================== + * + * PROPERTY + * + * ===============================================================*/ +enum zr_property_status { + ZR_PROPERTY_DEFAULT, + ZR_PROPERTY_EDIT, + ZR_PROPERTY_DRAG +}; + +enum zr_property_filter { + ZR_FILTER_INT, + ZR_FILTER_FLOAT +}; + +static float +zr_drag_behavior(zr_flags *state, const struct zr_input *in, + struct zr_rect drag, float min, float val, float max, float inc_per_pixel) +{ + int left_mouse_down = in && in->mouse.buttons[ZR_BUTTON_LEFT].down; + int left_mouse_click_in_cursor = in && + zr_input_has_mouse_click_down_in_rect(in, ZR_BUTTON_LEFT, drag, zr_true); + + *state = ZR_WIDGET_STATE_INACTIVE; + if (zr_input_is_mouse_hovering_rect(in, drag)) + *state = ZR_WIDGET_STATE_HOVERED; + + if (left_mouse_down && left_mouse_click_in_cursor) { + float delta, pixels; + pixels = in->mouse.delta.x; + delta = pixels * inc_per_pixel; + val += delta; + val = ZR_CLAMP(min, val, max); + *state = ZR_WIDGET_STATE_ACTIVE; + } + if (*state == ZR_WIDGET_STATE_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, drag)) + *state |= ZR_WIDGET_STATE_ENTERED; + else if (zr_input_is_mouse_prev_hovering_rect(in, drag)) + *state |= ZR_WIDGET_STATE_LEFT; + return val; +} + +static float +zr_property_behavior(zr_flags *ws, const struct zr_input *in, + struct zr_rect property, struct zr_rect label, struct zr_rect edit, + struct zr_rect empty, int *state, float min, float value, float max, + float step, float inc_per_pixel) +{ + ZR_UNUSED(step); + if (in && *state == ZR_PROPERTY_DEFAULT) { + if (zr_button_behavior(ws, edit, in, ZR_BUTTON_DEFAULT)) + *state = ZR_PROPERTY_EDIT; + else if (zr_input_is_mouse_click_down_in_rect(in, ZR_BUTTON_LEFT, label, zr_true)) + *state = ZR_PROPERTY_DRAG; + else if (zr_input_is_mouse_click_down_in_rect(in, ZR_BUTTON_LEFT, empty, zr_true)) + *state = ZR_PROPERTY_DRAG; + } + if (*state == ZR_PROPERTY_DRAG) { + value = zr_drag_behavior(ws, in, property, min, value, max, inc_per_pixel); + if (!(*ws & ZR_WIDGET_STATE_ACTIVE)) *state = ZR_PROPERTY_DEFAULT; + } + return value; +} + +static void +zr_draw_property(struct zr_command_buffer *out, const struct zr_style_property *style, + const struct zr_rect *bounds, const struct zr_rect *label, zr_flags state, + const char *name, zr_size len, const struct zr_user_font *font) +{ + struct zr_text text; + const struct zr_style_item *background; + + /* select correct background and text color */ + if (state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->active; + text.text = style->label_active; + } else if (state & ZR_WIDGET_STATE_HOVERED) { + background = &style->hover; + text.text = style->label_hover; + } else { + background = &style->normal; + text.text = style->label_normal; + } + + /* draw background */ + if (background->type == ZR_STYLE_ITEM_IMAGE) { + zr_draw_image(out, *bounds, &background->data.image); + text.background = zr_rgba(0,0,0,0); + } else { + text.background = background->data.color; + zr_fill_rect(out, *bounds, style->rounding, style->border_color); + zr_fill_rect(out, zr_shrink_rect(*bounds,style->border), style->rounding, background->data.color); + } + + /* draw label */ + text.padding = zr_vec2(0,0); + zr_widget_text(out, *label, name, len, &text, ZR_TEXT_CENTERED, font); +} + +static float +zr_do_property(zr_flags *ws, + struct zr_command_buffer *out, struct zr_rect property, + const char *name, float min, float val, float max, + float step, float inc_per_pixel, char *buffer, zr_size *len, + int *state, zr_size *cursor, const struct zr_style_property *style, + enum zr_property_filter filter, const struct zr_input *in, + const struct zr_user_font *font) +{ + const zr_filter filters[] = { + zr_filter_decimal, + zr_filter_float + }; + int active, old; + zr_size num_len, name_len; + char string[ZR_MAX_NUMBER_BUFFER]; + zr_size size; + + float property_min; + float property_max; + float property_value; + + char *dst = 0; + zr_size *length; + + struct zr_rect left; + struct zr_rect right; + struct zr_rect label; + struct zr_rect edit; + struct zr_rect empty; + + /* make sure the provided values are correct */ + property_max = ZR_MAX(min, max); + property_min = ZR_MIN(min, max); + property_value = ZR_CLAMP(property_min, val, property_max); + + /* left decrement button */ + left.h = font->height/2; + left.w = left.h; + left.x = property.x + style->border + style->padding.x; + left.y = property.y + style->border + property.h/2.0f - left.h/2; + + /* text label */ + name_len = zr_strsiz(name); + size = font->width(font->userdata, font->height, name, name_len); + label.x = left.x + left.w + style->padding.x; + label.w = (float)size + 2 * style->padding.x; + label.y = property.y + style->border; + label.h = property.h - 2 * style->border; + + /* right increment button */ + right.y = left.y; + right.w = left.w; + right.h = left.h; + right.x = property.x + property.w - (right.w + style->padding.x); + + /* edit */ + if (*state == ZR_PROPERTY_EDIT) { + size = font->width(font->userdata, font->height, buffer, *len); + length = len; + dst = buffer; + } else { + zr_ftos(string, property_value); + num_len = zr_string_float_limit(string, ZR_MAX_FLOAT_PRECISION); + size = font->width(font->userdata, font->height, string, num_len); + dst = string; + length = &num_len; + } + edit.w = (float)size + 2 * style->padding.x; + edit.x = right.x - (edit.w + style->padding.x); + edit.y = property.y + style->border + 1; + edit.h = property.h - (2 * style->border + 2); + + /* empty left space activator */ + empty.w = edit.x - (label.x + label.w); + empty.x = label.x + label.w; + empty.y = property.y; + empty.h = property.h; + + /* update property */ + old = (*state == ZR_PROPERTY_EDIT); + property_value = zr_property_behavior(ws, in, property, label, edit, empty, + state, property_min, property_value, property_max, + step, inc_per_pixel); + + if (style->draw_begin) + style->draw_begin(out, style->userdata); + if (style->draw) + style->draw(out, style, &property, &label, *ws, name, name_len, font); + else zr_draw_property(out, style, &property, &label, *ws, name, name_len, font); + if (style->draw_end) + style->draw_begin(out, style->userdata); + + /* execute right and left button */ + if (zr_do_button_symbol(ws, out, left, style->sym_left, ZR_BUTTON_DEFAULT, + &style->dec_button, in, font)) + property_value = ZR_CLAMP(min, property_value - step, max); + if (zr_do_button_symbol(ws, out, right, style->sym_right, ZR_BUTTON_DEFAULT, + &style->inc_button, in, font)) + property_value = ZR_CLAMP(min, property_value + step, max); + + active = (*state == ZR_PROPERTY_EDIT); + if (old != ZR_PROPERTY_EDIT && active) { + /* property has been activated so setup buffer */ + zr_memcopy(buffer, dst, *length); + *cursor = zr_utf_len(buffer, *length); + *len = *length; + length = len; + dst = buffer; + } + + *length = zr_do_edit_string(ws, out, edit, dst, *length, ZR_MAX_NUMBER_BUFFER, + &active, cursor, 1, &style->edit, filters[filter], + (*state == ZR_PROPERTY_EDIT) ? in: 0, font); + if (active && zr_input_is_key_pressed(in, ZR_KEY_ENTER)) + active = !active; + + if (old && !active) { + /* property is now not active so convert edit text to value*/ + *state = ZR_PROPERTY_DEFAULT; + buffer[*len] = '\0'; + zr_string_float_limit(buffer, ZR_MAX_FLOAT_PRECISION); + zr_strtof(&property_value, buffer); + property_value = ZR_CLAMP(min, property_value, max); + } + return property_value; +} + +/* =============================================================== + * + * COLOR PICKER + * + * ===============================================================*/ +static int +zr_color_picker_behavior(zr_flags *state, + const struct zr_rect *bounds, const struct zr_rect *matrix, + const struct zr_rect *hue_bar, const struct zr_rect *alpha_bar, + struct zr_color *color, const struct zr_input *in) +{ + float hsva[4]; + int value_changed = 0; + int hsv_changed = 0; + + ZR_ASSERT(state); + ZR_ASSERT(matrix); + ZR_ASSERT(hue_bar); + ZR_ASSERT(color); + + /* color matrix */ + zr_color_hsva_fv(hsva, *color); + if (zr_button_behavior(state, *matrix, in, ZR_BUTTON_REPEATER)) { + hsva[1] = ZR_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1)); + hsva[2] = 1.0f - ZR_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1)); + value_changed = hsv_changed = 1; + } + + /* hue bar */ + if (zr_button_behavior(state, *hue_bar, in, ZR_BUTTON_REPEATER)) { + hsva[0] = ZR_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1)); + value_changed = hsv_changed = 1; + } + /* alpha bar */ + if (alpha_bar) { + if (zr_button_behavior(state, *alpha_bar, in, ZR_BUTTON_REPEATER)) { + hsva[3] = 1.0f - ZR_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1)); + value_changed = 1; + } + } + + *state = ZR_WIDGET_STATE_INACTIVE; + if (hsv_changed) { + *color = zr_hsva_fv(hsva); + *state = ZR_WIDGET_STATE_ACTIVE; + } + if (value_changed) { + color->a = (zr_byte)(hsva[3] * 255.0f); + *state = ZR_WIDGET_STATE_ACTIVE; + } + if (zr_input_is_mouse_hovering_rect(in, *bounds)) + *state = ZR_WIDGET_STATE_HOVERED; + if (*state == ZR_WIDGET_STATE_HOVERED && !zr_input_is_mouse_prev_hovering_rect(in, *bounds)) + *state |= ZR_WIDGET_STATE_ENTERED; + else if (zr_input_is_mouse_prev_hovering_rect(in, *bounds)) + *state |= ZR_WIDGET_STATE_LEFT; + return value_changed; +} + +static void +zr_draw_color_picker(struct zr_command_buffer *o, const struct zr_rect *matrix, + const struct zr_rect *hue_bar, const struct zr_rect *alpha_bar, + struct zr_color color) +{ + static const struct zr_color black = {0,0,0,255}; + static const struct zr_color white = {255, 255, 255, 255}; + static const struct zr_color black_trans = {0,0,0,0}; + + const float crosshair_size = 7.0f; + struct zr_color temp; + float hsva[4]; + float line_y; + int i; + + ZR_ASSERT(o); + ZR_ASSERT(matrix); + ZR_ASSERT(hue_bar); + ZR_ASSERT(alpha_bar); + + /* draw hue bar */ + zr_color_hsv_fv(hsva, color); + for (i = 0; i < 6; ++i) { + static const struct zr_color hue_colors[] = { + {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255}, + {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255}}; + zr_fill_rect_multi_color(o, + zr_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f, + hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i], + hue_colors[i+1], hue_colors[i+1]); + } + line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f); + zr_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2, + line_y, 1, zr_rgb(255,255,255)); + + /* draw alpha bar */ + if (alpha_bar) { + float alpha = ZR_SATURATE((float)color.a/255.0f); + line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f); + + zr_fill_rect_multi_color(o, *alpha_bar, white, white, black, black); + zr_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2, + line_y, 1, zr_rgb(255,255,255)); + } + + /* draw color matrix */ + temp = zr_hsv_f(hsva[0], 1.0f, 1.0f); + zr_fill_rect_multi_color(o, *matrix, white, temp, temp, white); + zr_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black); + + /* draw cross-hair */ + {struct zr_vec2 p; float S = hsva[1]; float V = hsva[2]; + p.x = (float)(int)(matrix->x + S * matrix->w + 0.5f); + p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h + 0.5f); + zr_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white); + zr_stroke_line(o, p.x + crosshair_size, p.y, p.x+2, p.y, 1.0f, white); + zr_stroke_line(o, p.x, p.y + crosshair_size, p.x, p.y+2, 1.0f, zr_rgb(255,255,255)); + zr_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, zr_rgb(255,255,255));} +} + +static int +zr_do_color_picker(zr_flags *state, + struct zr_command_buffer *out, struct zr_color *color, + enum zr_color_picker_format fmt, struct zr_rect bounds, + struct zr_vec2 padding, const struct zr_input *in, + const struct zr_user_font *font) +{ + int ret = 0; + struct zr_rect matrix; + struct zr_rect hue_bar; + struct zr_rect alpha_bar; + float bar_w; + + ZR_ASSERT(out); + ZR_ASSERT(color); + ZR_ASSERT(state); + ZR_ASSERT(font); + if (!out || !color || !state || !font) + return ret; + + bar_w = font->height; + bounds.x += padding.x; + bounds.y += padding.x; + bounds.w -= 2 * padding.x; + bounds.h -= 2 * padding.y; + + matrix.x = bounds.x; + matrix.y = bounds.y; + matrix.h = bounds.h; + matrix.w = bounds.w - (3 * padding.x + 2 * bar_w); + + hue_bar.w = bar_w; + hue_bar.y = bounds.y; + hue_bar.h = matrix.h; + hue_bar.x = matrix.x + matrix.w + padding.x; + + alpha_bar.x = hue_bar.x + hue_bar.w + padding.x; + alpha_bar.y = bounds.y; + alpha_bar.w = bar_w; + alpha_bar.h = matrix.h; + + ret = zr_color_picker_behavior(state, &bounds, &matrix, &hue_bar, + (fmt == ZR_RGBA) ? &alpha_bar:0, color, in); + zr_draw_color_picker(out, &matrix, &hue_bar, (fmt == ZR_RGBA) ? &alpha_bar:0, *color); + return ret; +} + /* ============================================================== * * STYLE * * ===============================================================*/ -#define ZR_STYLE_PROPERTY_MAP(PROPERTY)\ - PROPERTY(ITEM_SPACING, 4.0f, 4.0f)\ - PROPERTY(ITEM_PADDING, 4.0f, 4.0f)\ - PROPERTY(TOUCH_PADDING, 0.0f, 0.0f)\ - PROPERTY(PADDING, 8.0f, 10.0f)\ - PROPERTY(SCALER_SIZE, 16.0f, 16.0f)\ - PROPERTY(SCROLLBAR_SIZE, 10.0f, 10.0f)\ - PROPERTY(SIZE, 64.0f, 64.0f) +struct zr_style_item zr_style_item_image(struct zr_image img) +{struct zr_style_item i; i.type = ZR_STYLE_ITEM_IMAGE; i.data.image = img; return i;} -#define ZR_STYLE_ROUNDING_MAP(ROUNDING)\ - ROUNDING(BUTTON, 4.0f)\ - ROUNDING(SLIDER, 8.0f)\ - ROUNDING(CHECK, 0.0f)\ - ROUNDING(INPUT, 0.0f)\ - ROUNDING(PROPERTY, 10.0f)\ - ROUNDING(CHART, 4.0f)\ - ROUNDING(SCROLLBAR, 3.0f) +struct zr_style_item zr_style_item_color(struct zr_color col) +{struct zr_style_item i; i.type = ZR_STYLE_ITEM_COLOR; i.data.color = col; return i;} -#define ZR_STYLE_COLOR_MAP(COLOR)\ - COLOR(TEXT, 175, 175, 175, 255)\ - COLOR(TEXT_HOVERING, 120, 120, 120, 255)\ - COLOR(TEXT_ACTIVE, 100, 100, 100, 255)\ - COLOR(WINDOW, 45, 45, 45, 255)\ - COLOR(HEADER, 40, 40, 40, 255)\ - COLOR(BORDER, 65, 65, 65, 255)\ - COLOR(BUTTON, 50, 50, 50, 255)\ - COLOR(BUTTON_HOVER, 35, 35, 35, 255)\ - COLOR(BUTTON_ACTIVE, 40, 40, 40, 255)\ - COLOR(TOGGLE, 100, 100, 100, 255)\ - COLOR(TOGGLE_HOVER, 120, 120, 120, 255)\ - COLOR(TOGGLE_CURSOR, 45, 45, 45, 255)\ - COLOR(SELECTABLE, 100, 100, 100, 255)\ - COLOR(SELECTABLE_HOVER, 80, 80, 80, 255)\ - COLOR(SELECTABLE_TEXT, 45, 45, 45, 255)\ - COLOR(SLIDER, 38, 38, 38, 255)\ - COLOR(SLIDER_CURSOR, 100, 100, 100, 255)\ - COLOR(SLIDER_CURSOR_HOVER, 120, 120, 120, 255)\ - COLOR(SLIDER_CURSOR_ACTIVE, 150, 150, 150, 255)\ - COLOR(PROGRESS, 38, 38, 38, 255)\ - COLOR(PROGRESS_CURSOR, 100, 100, 100, 255)\ - COLOR(PROGRESS_CURSOR_HOVER, 120, 120, 120, 255)\ - COLOR(PROGRESS_CURSOR_ACTIVE, 150, 150, 150, 255)\ - COLOR(PROPERTY, 38, 38, 38, 255)\ - COLOR(PROPERTY_HOVER, 50, 50, 50, 255)\ - COLOR(PROPERTY_ACTIVE, 60, 60, 60, 255)\ - COLOR(INPUT, 45, 45, 45, 255)\ - COLOR(INPUT_CURSOR, 100, 100, 100, 255)\ - COLOR(INPUT_TEXT, 135, 135, 135, 255)\ - COLOR(COMBO, 45, 45, 45, 255)\ - COLOR(HISTO, 120, 120, 120, 255)\ - COLOR(HISTO_BARS, 45, 45, 45, 255)\ - COLOR(HISTO_HIGHLIGHT, 255, 0, 0, 255)\ - COLOR(PLOT, 120, 120, 120, 255)\ - COLOR(PLOT_LINES, 45, 45, 45, 255)\ - COLOR(PLOT_HIGHLIGHT, 255, 0, 0, 255)\ - COLOR(SCROLLBAR, 40, 40, 40, 255)\ - COLOR(SCROLLBAR_CURSOR, 100, 100, 100, 255)\ - COLOR(SCROLLBAR_CURSOR_HOVER, 120, 120, 120, 255)\ - COLOR(SCROLLBAR_CURSOR_ACTIVE, 150, 150, 150, 255)\ - COLOR(TABLE_LINES, 100, 100, 100, 255)\ - COLOR(TAB_HEADER, 40, 40, 40, 255)\ - COLOR(SCALER, 100, 100, 100, 255) - -static const char *zr_style_color_names[] = { - #define COLOR(a,b,c,d,e) #a, - ZR_STYLE_COLOR_MAP(COLOR) - #undef COLOR -}; -static const char *zr_style_rounding_names[] = { - #define ROUNDING(a,b) #a, - ZR_STYLE_ROUNDING_MAP(ROUNDING) - #undef ROUNDING -}; -static const char *zr_style_property_names[] = { - #define PROPERTY(a,b,c) #a, - ZR_STYLE_PROPERTY_MAP(PROPERTY) - #undef PROPERTY -}; - -const char* -zr_get_color_name(enum zr_style_colors color) -{return zr_style_color_names[color];} - -const char* -zr_get_rounding_name(enum zr_style_rounding rounding) -{return zr_style_rounding_names[rounding];} - -const char* -zr_get_property_name(enum zr_style_properties property) -{return zr_style_property_names[property];} - -static void -zr_style_default_properties(struct zr_style *style) -{ - #define PROPERTY(a,b,c) style->properties[ZR_PROPERTY_##a] = zr_vec2(b, c); - ZR_STYLE_PROPERTY_MAP(PROPERTY) - #undef PROPERTY -} - -static void -zr_style_default_rounding(struct zr_style *style) -{ - #define ROUNDING(a,b) style->rounding[ZR_ROUNDING_##a] = b; - ZR_STYLE_ROUNDING_MAP(ROUNDING) - #undef ROUNDING -} - -static void -zr_style_default_color(struct zr_style *style) -{ - #define COLOR(a,b,c,d,e) style->colors[ZR_COLOR_##a] = zr_rgba(b,c,d,e); - ZR_STYLE_COLOR_MAP(COLOR) - #undef COLOR -} +struct zr_style_item zr_style_item_hide(void) +{struct zr_style_item i; i.type = ZR_STYLE_ITEM_COLOR; i.data.color = zr_rgba(0,0,0,0); return i;} void -zr_load_default_style(struct zr_context *ctx, zr_flags flags) +zr_style_default(struct zr_context *ctx) { struct zr_style *style; + struct zr_style_text *text; + struct zr_style_button *button; + struct zr_style_toggle *toggle; + struct zr_style_selectable *select; + struct zr_style_slider *slider; + struct zr_style_progress *prog; + struct zr_style_scrollbar *scroll; + struct zr_style_edit *edit; + struct zr_style_property *property; + struct zr_style_combo *combo; + struct zr_style_chart *chart; + struct zr_style_tab *tab; + struct zr_style_window *win; + ZR_ASSERT(ctx); if (!ctx) return; - style = &ctx->style; - if (flags & ZR_DEFAULT_COLOR) - zr_style_default_color(style); - if (flags & ZR_DEFAULT_PROPERTIES) - zr_style_default_properties(style); - if (flags & ZR_DEFAULT_ROUNDING) - zr_style_default_rounding(style); - style->header.align = ZR_HEADER_RIGHT; - style->header.close_symbol = 'x'; - style->header.minimize_symbol = '-'; - style->header.maximize_symbol = '+'; + /* default text */ + text = &style->text; + text->color = zr_rgb(175,175,175); + text->padding = zr_vec2(4,4); + + /* default button */ + button = &style->button; + zr_zero_struct(*button); + button->normal = zr_style_item_color(zr_rgb(50,50,50)); + button->hover = zr_style_item_color(zr_rgb(40,40,40)); + button->active = zr_style_item_color(zr_rgb(35,35,35)); + button->border_color = zr_rgb(65,65,65); + button->text_background = zr_rgb(50,50,50); + button->text_normal = zr_rgb(175, 175, 175); + button->text_hover = zr_rgb(165,165,165); + button->text_active = zr_rgb(155,155,155); + button->padding = zr_vec2(4.0f,4.0f); + button->image_padding = zr_vec2(0.0f,0.0f); + button->touch_padding = zr_vec2(0.0f, 0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 1.0f; + button->rounding = 4.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + + /* contextual button */ + button = &style->contextual_button; + zr_zero_struct(*button); + button->normal = zr_style_item_color(zr_rgb(45,45,45)); + button->hover = zr_style_item_color(zr_rgb(40,40,40)); + button->active = zr_style_item_color(zr_rgb(35,35,35)); + button->border_color = zr_rgb(45,45,45); + button->text_background = zr_rgb(45,45,45); + button->text_normal = zr_rgb(175,175,175); + button->text_hover = zr_rgb(165,165,165); + button->text_active = zr_rgb(155,155,155); + button->padding = zr_vec2(4.0f,4.0f); + button->touch_padding = zr_vec2(0.0f,0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 0.0f; + button->rounding = 0.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + + /* menu button */ + button = &style->menu_button; + zr_zero_struct(*button); + button->normal = zr_style_item_color(zr_rgb(45,45,45)); + button->hover = zr_style_item_color(zr_rgb(40,40,40)); + button->active = zr_style_item_color(zr_rgb(35,35,35)); + button->border_color = zr_rgb(65,65,65); + button->text_background = zr_rgb(40,40,40); + button->text_normal = zr_rgb(175,175,175); + button->text_hover = zr_rgb(175,175,175); + button->text_active = zr_rgb(175,175,175); + button->padding = zr_vec2(4.0f,4.0f); + button->touch_padding = zr_vec2(0.0f,0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 0.0f; + button->rounding = 1.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + + /* checkbox toggle */ + toggle = &style->checkbox; + zr_zero_struct(*toggle); + toggle->normal = zr_style_item_color(zr_rgb(100,100,100)); + toggle->hover = zr_style_item_color(zr_rgb(120,120,120)); + toggle->active = zr_style_item_color(zr_rgb(100,100,100)); + toggle->cursor_normal = zr_style_item_color(zr_rgb(45,45,45)); + toggle->cursor_hover = zr_style_item_color(zr_rgb(45,45,45)); + toggle->userdata = zr_handle_ptr(0); + toggle->text_background = zr_rgb(45,45,45); + toggle->text_normal = zr_rgb(175,175,175); + toggle->text_hover = zr_rgb(175,175,175); + toggle->text_active = zr_rgb(175,175,175); + toggle->padding = zr_vec2(4.0f, 4.0f); + toggle->touch_padding = zr_vec2(0,0); + toggle->fixed_width = 0; + toggle->fixed_height = 0; + toggle->has_fixed_size = 0; + + /* option toggle */ + toggle = &style->option; + zr_zero_struct(*toggle); + toggle->normal = zr_style_item_color(zr_rgb(100,100,100)); + toggle->hover = zr_style_item_color(zr_rgb(120,120,120)); + toggle->active = zr_style_item_color(zr_rgb(100,100,100)); + toggle->cursor_normal = zr_style_item_color(zr_rgb(45,45,45)); + toggle->cursor_hover = zr_style_item_color(zr_rgb(45,45,45)); + toggle->userdata = zr_handle_ptr(0); + toggle->text_background = zr_rgb(45,45,45); + toggle->text_normal = zr_rgb(175,175,175); + toggle->text_hover = zr_rgb(175,175,175); + toggle->text_active = zr_rgb(175,175,175); + toggle->padding = zr_vec2(4.0f, 4.0f); + toggle->touch_padding = zr_vec2(0,0); + toggle->fixed_width = 0; + toggle->fixed_height = 0; + toggle->has_fixed_size = 0; + + /* selectable */ + select = &style->selectable; + zr_zero_struct(*select); + select->normal = zr_style_item_color(zr_rgb(45,45,45)); + select->hover = zr_style_item_color(zr_rgb(45,45,45)); + select->pressed = zr_style_item_color(zr_rgb(45,45,45)); + select->normal_active = zr_style_item_color(zr_rgb(100,100,100)); + select->hover_active = zr_style_item_color(zr_rgb(100,100,100)); + select->pressed_active = zr_style_item_color(zr_rgb(100,100,100)); + select->text_normal = zr_rgb(175,175,175); + select->text_hover = zr_rgb(175,175,175); + select->text_pressed = zr_rgb(175,175,175); + select->text_normal_active = zr_rgb(45,45,45); + select->text_hover_active = zr_rgb(45,45,45); + select->text_pressed_active = zr_rgb(45,45,45); + select->fixed_width = 0; + select->fixed_height = 0; + select->rounding = 0.0f; + select->has_fixed_size = 0; + select->padding = zr_vec2(4.0f,4.0f); + select->touch_padding = zr_vec2(0,0); + select->userdata = zr_handle_ptr(0); + select->draw_begin = 0; + select->draw = 0; + select->draw_end = 0; + + /* slider */ + slider = &style->slider; + zr_zero_struct(*slider); + slider->normal = zr_style_item_hide(); + slider->hover = zr_style_item_hide(); + slider->active = zr_style_item_hide(); + slider->bar_normal = zr_rgb(38,38,38); + slider->bar_hover = zr_rgb(38,38,38); + slider->bar_active = zr_rgb(38,38,38); + slider->bar_filled = zr_rgb(100,100,100); + slider->cursor_normal = zr_style_item_color(zr_rgb(100,100,100)); + slider->cursor_hover = zr_style_item_color(zr_rgb(120,120,120)); + slider->cursor_active = zr_style_item_color(zr_rgb(150,150,150));; + slider->inc_symbol = ZR_SYMBOL_TRIANGLE_RIGHT; + slider->dec_symbol = ZR_SYMBOL_TRIANGLE_LEFT; + slider->cursor_size = zr_vec2(16,16); + slider->padding = zr_vec2(4,4); + slider->spacing = zr_vec2(4,4); + slider->userdata = zr_handle_ptr(0); + slider->show_buttons = zr_false; + slider->bar_height = 8; + slider->rounding = 0; + slider->fixed_width = 0; + slider->fixed_height = 0; + slider->has_fixed_size = 0; + slider->draw_begin = 0; + slider->draw = 0; + slider->draw_end = 0; + + /* slider buttons */ + button = &style->slider.inc_button; + button->normal = zr_style_item_color(zr_rgb(40,40,40)); + button->hover = zr_style_item_color(zr_rgb(42,42,42)); + button->active = zr_style_item_color(zr_rgb(44,44,44)); + button->border_color = zr_rgb(65,65,65); + button->text_background = zr_rgb(40,40,40); + button->text_normal = zr_rgb(175,175,175); + button->text_hover = zr_rgb(175,175,175); + button->text_active = zr_rgb(175,175,175); + button->padding = zr_vec2(8.0f,8.0f); + button->touch_padding = zr_vec2(0.0f,0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 1.0f; + button->rounding = 0.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + style->slider.dec_button = style->slider.inc_button; + + /* progressbar */ + prog = &style->progress; + zr_zero_struct(*prog); + prog->normal = zr_style_item_color(zr_rgb(38,38,38)); + prog->hover = zr_style_item_color(zr_rgb(40,40,40)); + prog->active = zr_style_item_color(zr_rgb(42,42,42)); + prog->cursor_normal = zr_style_item_color(zr_rgb(100,100,100)); + prog->cursor_hover = zr_style_item_color(zr_rgb(120,120,120)); + prog->cursor_active = zr_style_item_color(zr_rgb(150,150,150)); + prog->userdata = zr_handle_ptr(0); + prog->padding = zr_vec2(4,4); + prog->rounding = 0; + prog->fixed_width = 0; + prog->fixed_height = 0; + prog->has_fixed_size = 0; + prog->draw_begin = 0; + prog->draw = 0; + prog->draw_end = 0; + + /* scrollbars */ + scroll = &style->scrollh; + zr_zero_struct(*scroll); + scroll->normal = zr_style_item_color(zr_rgb(40,40,40)); + scroll->hover = zr_style_item_color(zr_rgb(40,40,40)); + scroll->active = zr_style_item_color(zr_rgb(40,40,40)); + scroll->cursor_normal = zr_style_item_color(zr_rgb(100,100,100)); + scroll->cursor_hover = zr_style_item_color(zr_rgb(120,120,120)); + scroll->cursor_active = zr_style_item_color(zr_rgb(150,150,150)); + scroll->dec_symbol = ZR_SYMBOL_CIRCLE_FILLED; + scroll->inc_symbol = ZR_SYMBOL_CIRCLE_FILLED; + scroll->userdata = zr_handle_ptr(0); + scroll->border_color = zr_rgb(65,65,65); + scroll->padding = zr_vec2(4,4); + scroll->show_buttons = zr_false; + scroll->border = 0; + scroll->rounding = 0; + scroll->draw_begin = 0; + scroll->draw = 0; + scroll->draw_end = 0; + style->scrollv = style->scrollh; + + /* scrollbars buttons */ + button = &style->scrollh.inc_button; + button->normal = zr_style_item_color(zr_rgb(40,40,40)); + button->hover = zr_style_item_color(zr_rgb(42,42,42)); + button->active = zr_style_item_color(zr_rgb(44,44,44)); + button->border_color = zr_rgb(65,65,65); + button->text_background = zr_rgb(40,40,40); + button->text_normal = zr_rgb(175,175,175); + button->text_hover = zr_rgb(175,175,175); + button->text_active = zr_rgb(175,175,175); + button->padding = zr_vec2(4.0f,4.0f); + button->touch_padding = zr_vec2(0.0f,0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 1.0f; + button->rounding = 0.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + style->scrollh.dec_button = style->scrollh.inc_button; + style->scrollv.inc_button = style->scrollh.inc_button; + style->scrollv.dec_button = style->scrollh.inc_button; + + /* edit */ + edit = &style->edit; + zr_zero_struct(*edit); + edit->normal = zr_style_item_color(zr_rgb(45,45,45)); + edit->hover = zr_style_item_color(zr_rgb(47,47,47)); + edit->active = zr_style_item_color(zr_rgb(49,49,49)); + edit->cursor_normal = zr_style_item_color(zr_rgb(100,100,100)); + edit->cursor_hover = zr_style_item_color(zr_rgb(102,102,102)); + edit->cursor_active = zr_style_item_color(zr_rgb(104,104,104)); + edit->border_color = zr_rgb(65,65,65);; + edit->text_normal = zr_rgb(135,135,135); + edit->text_hover = zr_rgb(135,135,135); + edit->text_active = zr_rgb(135,135,135); + edit->selected_normal = zr_rgb(135,135,135); + edit->selected_hover = zr_rgb(135,135,135); + edit->selected_text_normal = zr_rgb(45,45,45); + edit->selected_text_hover = zr_rgb(45,45,45); + edit->userdata = zr_handle_ptr(0); + edit->padding = zr_vec2(4,4); + edit->cursor_size = 8; + edit->border = 1; + edit->rounding = 0; + edit->fixed_width = 0; + edit->fixed_height = 0; + edit->has_fixed_size = 0; + edit->draw_begin = 0; + edit->draw = 0; + edit->draw_end = 0; + + /* property */ + property = &style->property; + zr_zero_struct(*property); + property->normal = zr_style_item_color(zr_rgb(38,38,38)); + property->hover = zr_style_item_color(zr_rgb(40,40,40)); + property->active = zr_style_item_color(zr_rgb(42,42,42)); + property->border_color = zr_rgb(65,65,65); + property->label_normal = zr_rgb(175,175,175); + property->label_hover = zr_rgb(175,175,175); + property->label_active = zr_rgb(175,175,175); + property->sym_left = ZR_SYMBOL_TRIANGLE_LEFT; + property->sym_right = ZR_SYMBOL_TRIANGLE_RIGHT; + property->userdata = zr_handle_ptr(0); + property->padding = zr_vec2(4,4); + property->border = 1; + property->rounding = 10; + property->has_fixed_size = 0; + property->fixed_width = 0; + property->fixed_height = 0; + property->draw_begin = 0; + property->draw = 0; + property->draw_end = 0; + + /* property buttons */ + button = &style->property.dec_button; + zr_zero_struct(*button); + button->normal = zr_style_item_color(zr_rgb(38,38,38)); + button->hover = zr_style_item_color(zr_rgb(40,40,40)); + button->active = zr_style_item_color(zr_rgb(42,42,42)); + button->border_color = zr_rgba(0,0,0,0); + button->text_background = zr_rgb(38,38,38); + button->text_normal = zr_rgb(175,175,175); + button->text_hover = zr_rgb(175,175,175); + button->text_active = zr_rgb(175,175,175); + button->padding = zr_vec2(0.0f,0.0f); + button->touch_padding = zr_vec2(0.0f,0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 0.0f; + button->rounding = 0.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + style->property.inc_button = style->property.dec_button; + + /* property edit */ + edit = &style->property.edit; + zr_zero_struct(*edit); + edit->normal = zr_style_item_color(zr_rgb(38,38,38)); + edit->hover = zr_style_item_color(zr_rgb(40,40,40)); + edit->active = zr_style_item_color(zr_rgb(42,42,42)); + edit->cursor_normal = zr_style_item_color(zr_rgb(175,175,175)); + edit->cursor_hover = zr_style_item_color(zr_rgb(175,175,175)); + edit->cursor_active = zr_style_item_color(zr_rgb(175,175,175)); + edit->border_color = zr_rgba(0,0,0,0); + edit->text_normal = zr_rgb(175,175,175); + edit->text_hover = zr_rgb(175,175,175); + edit->text_active = zr_rgb(175,175,175); + edit->selected_normal = zr_rgb(175,175,175); + edit->selected_hover = zr_rgb(175,175,175); + edit->selected_text_normal = zr_rgb(38,38,38); + edit->selected_text_hover = zr_rgb(50,50,50); + edit->userdata = zr_handle_ptr(0); + edit->padding = zr_vec2(0,0); + edit->cursor_size = 8; + edit->border = 0; + edit->rounding = 0; + edit->fixed_width = 0; + edit->fixed_height = 0; + edit->has_fixed_size = 0; + edit->draw_begin = 0; + edit->draw = 0; + edit->draw_end = 0; + + /* chart */ + chart = &style->line_chart; + zr_zero_struct(*chart); + chart->background = zr_style_item_color(zr_rgb(120,120,120)); + chart->border_color = zr_rgb(65,65,65); + chart->selected_color = zr_rgb(256,0,0); + chart->color = zr_rgb(45,45,45); + chart->border = 0; + chart->rounding = 0; + chart->has_fixed_size = 0; + chart->fixed_width = 0; + chart->fixed_height = 0; + chart->padding = zr_vec2(4,4); + style->column_chart = *chart; + + /* combo */ + combo = &style->combo; + combo->normal = zr_style_item_color(zr_rgb(45,45,45)); + combo->hover = zr_style_item_color(zr_rgb(45,45,45)); + combo->active = zr_style_item_color(zr_rgb(45,45,45)); + combo->border_color = zr_rgb(65,65,65); + combo->label_normal = zr_rgb(175,175,175); + combo->label_hover = zr_rgb(175,175,175); + combo->label_active = zr_rgb(175,175,175); + combo->sym_normal = ZR_SYMBOL_TRIANGLE_DOWN; + combo->sym_hover = ZR_SYMBOL_TRIANGLE_DOWN; + combo->sym_active =ZR_SYMBOL_TRIANGLE_DOWN; + combo->content_padding = zr_vec2(4,4); + combo->button_padding = zr_vec2(0,4); + combo->spacing = zr_vec2(4,0); + combo->border = 1; + combo->rounding = 0; + combo->has_fixed_size = 0; + combo->fixed_width = 0; + combo->fixed_height = 0; + + /* combo button */ + button = &style->combo.button; + zr_zero_struct(*button); + button->normal = zr_style_item_color(zr_rgb(45,45,45)); + button->hover = zr_style_item_color(zr_rgb(45,45,45)); + button->active = zr_style_item_color(zr_rgb(45,45,45)); + button->border_color = zr_rgba(0,0,0,0); + button->text_background = zr_rgb(45,45,38); + button->text_normal = zr_rgb(175,175,175); + button->text_hover = zr_rgb(175,175,175); + button->text_active = zr_rgb(175,175,175); + button->padding = zr_vec2(2.0f,2.0f); + button->touch_padding = zr_vec2(0.0f,0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 0.0f; + button->rounding = 0.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + + /* tab */ + tab = &style->tab; + tab->background = zr_style_item_color(zr_rgb(40,40,40)); + tab->border_color = zr_rgb(65,65,65); + tab->text = zr_rgb(175,175,175); + tab->sym_minimize = ZR_SYMBOL_TRIANGLE_DOWN; + tab->sym_maximize = ZR_SYMBOL_TRIANGLE_RIGHT; + tab->border = 1; + tab->rounding = 0; + tab->padding = zr_vec2(4,4); + tab->spacing = zr_vec2(4,4); + + /* tab button */ + button = &style->tab.tab_button; + zr_zero_struct(*button); + button->normal = zr_style_item_color(zr_rgb(40,40,40)); + button->hover = zr_style_item_color(zr_rgb(40,40,40)); + button->active = zr_style_item_color(zr_rgb(40,40,40)); + button->border_color = zr_rgba(0,0,0,0); + button->text_background = zr_rgb(40,40,40); + button->text_normal = zr_rgb(175,175,175); + button->text_hover = zr_rgb(175,175,175); + button->text_active = zr_rgb(175,175,175); + button->padding = zr_vec2(2.0f,2.0f); + button->touch_padding = zr_vec2(0.0f,0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 0.0f; + button->rounding = 0.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + + /* node button */ + button = &style->tab.node_button; + zr_zero_struct(*button); + button->normal = zr_style_item_color(zr_rgb(45,45,45)); + button->hover = zr_style_item_color(zr_rgb(45,45,45)); + button->active = zr_style_item_color(zr_rgb(45,45,45)); + button->border_color = zr_rgba(0,0,0,0); + button->text_background = zr_rgb(40,40,40); + button->text_normal = zr_rgb(175,175,175); + button->text_hover = zr_rgb(175,175,175); + button->text_active = zr_rgb(175,175,175); + button->padding = zr_vec2(2.0f,2.0f); + button->touch_padding = zr_vec2(0.0f,0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 0.0f; + button->rounding = 0.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + + /* window header */ + win = &style->window; + win->header.align = ZR_HEADER_RIGHT; + win->header.close_symbol = ZR_SYMBOL_X; + win->header.minimize_symbol = ZR_SYMBOL_MINUS; + win->header.maximize_symbol = ZR_SYMBOL_PLUS; + win->header.normal = zr_style_item_color(zr_rgb(40,40,40)); + win->header.hover = zr_style_item_color(zr_rgb(40,40,40)); + win->header.active = zr_style_item_color(zr_rgb(40,40,40)); + win->header.label_normal = zr_rgb(175,175,175); + win->header.label_hover = zr_rgb(175,175,175); + win->header.label_active = zr_rgb(175,175,175); + win->header.label_padding = zr_vec2(4,4); + win->header.padding = zr_vec2(4,4); + win->header.spacing = zr_vec2(0,0); + + /* window header close button */ + button = &style->window.header.close_button; + zr_zero_struct(*button); + button->normal = zr_style_item_color(zr_rgb(40,40,40)); + button->hover = zr_style_item_color(zr_rgb(40,40,40)); + button->active = zr_style_item_color(zr_rgb(40,40,40)); + button->border_color = zr_rgba(0,0,0,0); + button->text_background = zr_rgb(40,40,40); + button->text_normal = zr_rgb(175,175,175); + button->text_hover = zr_rgb(175,175,175); + button->text_active = zr_rgb(175,175,175); + button->padding = zr_vec2(0.0f,0.0f); + button->touch_padding = zr_vec2(0.0f,0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 0.0f; + button->rounding = 0.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + + /* window header minimize button */ + button = &style->window.header.minimize_button; + zr_zero_struct(*button); + button->normal = zr_style_item_color(zr_rgb(40,40,40)); + button->hover = zr_style_item_color(zr_rgb(40,40,40)); + button->active = zr_style_item_color(zr_rgb(40,40,40)); + button->border_color = zr_rgba(0,0,0,0); + button->text_background = zr_rgb(40,40,40); + button->text_normal = zr_rgb(175,175,175); + button->text_hover = zr_rgb(175,175,175); + button->text_active = zr_rgb(175,175,175); + button->padding = zr_vec2(0.0f,0.0f); + button->touch_padding = zr_vec2(0.0f,0.0f); + button->userdata = zr_handle_ptr(0); + button->text_alignment = ZR_TEXT_CENTERED; + button->border = 0.0f; + button->rounding = 0.0f; + button->fixed_width = 0; + button->fixed_height = 0; + button->has_fixed_size = 0; + button->draw_begin = 0; + button->draw_end = 0; + + /* window */ + win->background = zr_rgb(45,45,45); + win->fixed_background = zr_style_item_color(zr_rgb(45,45,45)); + win->border_color = zr_rgb(65,65,65); + win->scaler = zr_style_item_color(zr_rgb(175,175,175)); + win->footer_padding = zr_vec2(4,4); + win->border = 1.0f; + win->rounding = 0.0f; + win->has_fixed_size = 0; + win->fixed_width = 0; + win->fixed_height = 0; + win->scaler_size = zr_vec2(16,16); + win->padding = zr_vec2(8,8); + win->spacing = zr_vec2(4,4); + win->scrollbar_size = zr_vec2(10,10); + win->min_size = zr_vec2(64,64); } void -zr_set_font(struct zr_context *ctx, const struct zr_user_font *font) +zr_style_set_font(struct zr_context *ctx, const struct zr_user_font *font) { struct zr_style *style; ZR_ASSERT(ctx); @@ -6908,222 +7307,39 @@ zr_set_font(struct zr_context *ctx, const struct zr_user_font *font) style->font = *font; } -struct zr_vec2 -zr_get_property(const struct zr_context *ctx, enum zr_style_properties index) -{ - const struct zr_style *style; - static const struct zr_vec2 zero = {0,0}; - ZR_ASSERT(ctx); - if (!ctx) return zero; - style = &ctx->style; - return style->properties[index]; -} - -struct zr_color -zr_get_color(const struct zr_context *ctx, enum zr_style_colors index) -{ - const struct zr_style *style; - static const struct zr_color zero = {0,0,0,0}; - ZR_ASSERT(ctx); - if (!ctx) return zero; - style = &ctx->style; - return style->colors[index]; -} - -void -zr_push_color(struct zr_context *ctx, enum zr_style_colors index, - struct zr_color col) -{ - struct zr_style *style; - struct zr_saved_color *c; - - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - if (style->stack.color >= ZR_MAX_COLOR_STACK) return; - - c = &style->stack.colors[style->stack.color++]; - c->value = style->colors[index]; - c->type = index; - style->colors[index] = col; -} - -void -zr_push_property(struct zr_context *ctx, enum zr_style_properties index, - struct zr_vec2 v) -{ - struct zr_style *style; - struct zr_saved_property *property; - - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - if (style->stack.property >= ZR_MAX_ATTRIB_STACK) return; - - property = &style->stack.properties[style->stack.property++]; - property->value = style->properties[index]; - property->type = index; - style->properties[index] = v; -} - -void -zr_push_font(struct zr_context *ctx, struct zr_user_font font) -{ - struct zr_style *style; - struct zr_saved_font *f; - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - if (style->stack.font >= ZR_MAX_FONT_STACK) return; - - f = &style->stack.fonts[style->stack.font++]; - f->font_height_begin = style->stack.font_height; - f->font_height_end = style->stack.font_height; - f->value = style->font; - style->font = font; -} - -void -zr_push_font_height(struct zr_context *ctx, float font_height) -{ - struct zr_style *style; - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - if (style->stack.font >= ZR_MAX_FONT_HEIGHT_STACK) return; - - style->stack.font_heights[style->stack.font_height++] = style->font.height; - if (style->stack.font) - style->stack.fonts[style->stack.font-1].font_height_end++; - style->font.height = font_height; -} - -void -zr_pop_color(struct zr_context *ctx) -{ - struct zr_style *style; - struct zr_saved_color *c; - - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - if (!style->stack.color) return; - - c = &style->stack.colors[--style->stack.color]; - style->colors[c->type] = c->value; -} - -void -zr_pop_property(struct zr_context *ctx) -{ - struct zr_style *style; - struct zr_saved_property *property; - - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - if (!style->stack.property) return; - - property = &style->stack.properties[--style->stack.property]; - style->properties[property->type] = property->value; -} - -void -zr_pop_font(struct zr_context *ctx) -{ - struct zr_style *style; - struct zr_saved_font *f; - - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - if (!style->stack.font) return; - - f = &style->stack.fonts[--style->stack.font]; - style->stack.font_height = f->font_height_begin; - style->font = f->value; - if (style->stack.font_height) - style->font.height = style->stack.font_heights[style->stack.font_height-1]; -} - -void -zr_pop_font_height(struct zr_context *ctx) -{ - struct zr_style *style; - float font_height; - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - if (!style->stack.font_height) return; - - font_height = style->stack.font_heights[--style->stack.font_height]; - style->font.height = font_height; - if (style->stack.font) { - ZR_ASSERT(style->stack.fonts[style->stack.font-1].font_height_end); - style->stack.fonts[style->stack.font-1].font_height_end--; - } -} - -void -zr_reset_colors(struct zr_context *ctx) -{ - struct zr_style *style; - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - while (style->stack.color) - zr_pop_color(ctx); -} - -void -zr_reset_properties(struct zr_context *ctx) -{ - struct zr_style *style; - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - while (style->stack.property) - zr_pop_property(ctx); -} - -void -zr_reset_font(struct zr_context *ctx) -{ - struct zr_style *style; - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - while (style->stack.font) - zr_pop_font(ctx); -} - -void -zr_reset_font_height(struct zr_context *ctx) -{ - struct zr_style *style; - ZR_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - while (style->stack.font_height) - zr_pop_font_height(ctx); -} - -void -zr_reset(struct zr_context *ctx) -{ - ZR_ASSERT(ctx); - if (!ctx) return; - zr_reset_colors(ctx); - zr_reset_properties(ctx); - zr_reset_font(ctx); - zr_reset_font_height(ctx); -} - /* =============================================================== * * POOL * * ===============================================================*/ +struct zr_table { + unsigned int seq; + zr_hash keys[ZR_VALUE_PAGE_CAPACITY]; + zr_uint values[ZR_VALUE_PAGE_CAPACITY]; + struct zr_table *next, *prev; +}; + +union zr_page_data { + struct zr_table tbl; + struct zr_window win; +}; + +struct zr_window_page { + unsigned size; + struct zr_window_page *next; + union zr_page_data win[1]; +}; + +struct zr_pool { + struct zr_allocator alloc; + enum zr_allocation_type type; + unsigned int page_count; + struct zr_window_page *pages; + unsigned capacity; + zr_size size; + zr_size cap; +}; + static void zr_pool_init(struct zr_pool *pool, struct zr_allocator *alloc, unsigned int capacity) @@ -7206,7 +7422,7 @@ zr_setup(struct zr_context *ctx, const struct zr_user_font *font) ZR_ASSERT(font); if (!ctx || !font) return; zr_zero_struct(*ctx); - zr_load_default_style(ctx, ZR_DEFAULT_ALL); + zr_style_default(ctx); ctx->style.font = *font; #if ZR_COMPILE_WITH_VERTEX_BUFFER zr_canvas_init(&ctx->canvas); @@ -7751,6 +7967,7 @@ zr_begin(struct zr_context *ctx, struct zr_panel *layout, const char *title, struct zr_rect bounds, zr_flags flags) { struct zr_window *win; + struct zr_style *style; zr_hash title_hash; int title_len; int ret = 0; @@ -7761,6 +7978,7 @@ zr_begin(struct zr_context *ctx, struct zr_panel *layout, const char *title, return 0; /* find or create window */ + style = &ctx->style; title_len = (int)zr_strsiz(title); title_hash = zr_murmur_hash(title, (int)title_len, ZR_WINDOW_TITLE); win = zr_find_window(ctx, title_hash); @@ -7798,9 +8016,7 @@ zr_begin(struct zr_context *ctx, struct zr_panel *layout, const char *title, * without cheating because you do not have the information at this point. * Even worse this is wrong since windows could have different window heights. * I leave it in for now since I otherwise loose my mind. */ - struct zr_vec2 window_padding = zr_get_property(ctx, ZR_PROPERTY_PADDING); - struct zr_vec2 item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - float h = ctx->style.font.height + 2 * item_padding.y + window_padding.y; + float h = ctx->style.font.height + 2 * style->window.header.padding.y; /* activate window if hovered and no other window is overlapping this window */ zr_start(ctx, win); @@ -7887,6 +8103,7 @@ zr_end(struct zr_context *ctx) } zr_panel_end(ctx); ctx->current = 0; + ctx->last_widget_state = 0; } struct zr_rect @@ -8069,18 +8286,23 @@ zr_window_is_active(struct zr_context *ctx, const char *name) return win == ctx->active; } -void -zr_window_close(struct zr_context *ctx, const char *name) +struct zr_window* +zr_window_find(struct zr_context *ctx, const char *name) { int title_len; zr_hash title_hash; + title_len = (int)zr_strsiz(name); + title_hash = zr_murmur_hash(name, (int)title_len, ZR_WINDOW_TITLE); + return zr_find_window(ctx, title_hash); +} + +void +zr_window_close(struct zr_context *ctx, const char *name) +{ struct zr_window *win; ZR_ASSERT(ctx); if (!ctx) return; - - title_len = (int)zr_strsiz(name); - title_hash = zr_murmur_hash(name, (int)title_len, ZR_WINDOW_TITLE); - win = zr_find_window(ctx, title_hash); + win = zr_window_find(ctx, name); if (!win) return; ZR_ASSERT(ctx->current != win && "You cannot close a current window"); if (ctx->current == win) return; @@ -8192,110 +8414,6 @@ zr_window_set_focus(struct zr_context *ctx, const char *name) * PANEL * * --------------------------------------------------------------*/ -struct zr_window_header { - float x, y, w, h; - float front, back; -}; - -static int -zr_header_button(struct zr_context *ctx, struct zr_window_header *header, - zr_rune symbol, enum zr_style_header_align align) -{ - struct zr_window *win; - struct zr_panel *layout; - const struct zr_style *c; - struct zr_command_buffer *out; - - struct zr_vec2 item_padding; - struct zr_rect sym = {0,0,0,0}; - int ret = zr_false; - float sym_bw = 0; - zr_glyph glyph; - - ZR_ASSERT(ctx); - ZR_ASSERT(ctx->current); - ZR_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return zr_false; - - /* cache configuration data */ - win = ctx->current; - layout = win->layout; - c = &ctx->style; - out = &win->buffer; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - - sym.x = header->front; - sym.y = header->y; - { - /* single unicode rune text icon */ - const char *X = glyph; - const zr_size len = zr_utf_encode(symbol, glyph, sizeof(glyph)); - const zr_size t = c->font.width(c->font.userdata, c->font.height, X, len); - const float text_width = (float)t; - struct zr_text text; - - /* calculate bounds of the icon */ - sym_bw = text_width; - sym.w = (float)text_width + 2 * item_padding.x; - sym.h = c->font.height + 2 * item_padding.y; - if (align == ZR_HEADER_RIGHT) - sym.x = header->back - sym.w; - - /* draw symbol icon */ - text.padding = zr_vec2(0,0); - text.background = c->colors[ZR_COLOR_HEADER]; - text.text = c->colors[ZR_COLOR_TEXT]; - zr_widget_text(out, sym, X, len, &text, - ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, &c->font); - } - - /* check if the icon has been pressed */ - if (!(layout->flags & ZR_WINDOW_ROM)) { - struct zr_rect bounds; - zr_flags status; - bounds.x = sym.x; bounds.y = sym.y; - bounds.w = sym_bw; bounds.h = sym.h; - ret = zr_button_behavior(&status, bounds, &ctx->input, ZR_BUTTON_DEFAULT); - } - - /* update the header space */ - if (align == ZR_HEADER_RIGHT) - header->back -= (sym.w + item_padding.x); - else header->front += sym.w + item_padding.x; - return ret; -} - -static int -zr_header_toggle(struct zr_context *ctx, struct zr_window_header *header, - zr_rune active, zr_rune inactive, enum zr_style_header_align align, int state) -{ - int ret = zr_header_button(ctx, header,(state) ? active : inactive, align); - if (ret) - return !state; - else return state; -} - -static int -zr_header_flag(struct zr_context *ctx, struct zr_window_header *header, - zr_rune inactive, zr_rune active, enum zr_style_header_align align, - zr_flags flag) -{ - struct zr_window *win = ctx->current; - struct zr_panel *layout = win->layout; - - zr_flags flags = win->flags; - int state = (flags & flag) ? zr_true : zr_false; - int ret = zr_header_toggle(ctx, header, inactive, active, align, state); - if (ret != ((flags & flag) ? zr_true : zr_false)) { - /* the state of the toggle icon has been changed */ - if (!ret) layout->flags &= ~flag; - else layout->flags |= flag; - return zr_true; - } - return zr_false; -} - static int zr_panel_begin(struct zr_context *ctx, const char *title) { @@ -8303,12 +8421,11 @@ zr_panel_begin(struct zr_context *ctx, const char *title) struct zr_window *win; struct zr_panel *layout; struct zr_command_buffer *out; - const struct zr_style *config; + const struct zr_style *style; const struct zr_user_font *font; int header_active = 0; - float scrollbar_size; - struct zr_vec2 item_padding; + struct zr_vec2 scrollbar_size; struct zr_vec2 item_spacing; struct zr_vec2 window_padding; struct zr_vec2 scaler_size; @@ -8319,18 +8436,17 @@ zr_panel_begin(struct zr_context *ctx, const char *title) if (!ctx || !ctx->current || !ctx->current->layout) return 0; - config = &ctx->style; - font = &config->font; + style = &ctx->style; + font = &style->font; in = &ctx->input; win = ctx->current; layout = win->layout; /* cache style data */ - scrollbar_size = zr_get_property(ctx, ZR_PROPERTY_SCROLLBAR_SIZE).x; - window_padding = zr_get_property(ctx, ZR_PROPERTY_PADDING); - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - item_spacing = zr_get_property(ctx, ZR_PROPERTY_ITEM_SPACING); - scaler_size = zr_get_property(ctx, ZR_PROPERTY_SCALER_SIZE); + scrollbar_size = style->window.scrollbar_size; + window_padding = style->window.padding; + item_spacing = style->window.spacing; + scaler_size = style->window.scaler_size; /* check arguments */ zr_zero(layout, sizeof(*layout)); @@ -8338,8 +8454,8 @@ zr_panel_begin(struct zr_context *ctx, const char *title) return 0; /* move panel position if requested */ - layout->header_h = font->height + 4 * item_padding.y; - layout->header_h += window_padding.y; + layout->header_h = font->height + 2 * style->window.header.padding.y; + layout->header_h += 2 * style->window.header.label_padding.y; if ((win->flags & ZR_WINDOW_MOVABLE) && !(win->flags & ZR_WINDOW_ROM)) { int incursor; struct zr_rect move; @@ -8365,13 +8481,13 @@ zr_panel_begin(struct zr_context *ctx, const char *title) layout->at_y = win->bounds.y; layout->width = win->bounds.w; layout->height = win->bounds.h; + layout->max_x = 0; layout->row.index = 0; layout->row.columns = 0; layout->row.height = 0; layout->row.ratio = 0; layout->row.item_width = 0; layout->row.tree_depth = 0; - layout->max_x = 0; layout->flags = win->flags; /* calculate window header */ @@ -8379,135 +8495,161 @@ zr_panel_begin(struct zr_context *ctx, const char *title) layout->header_h = 0; layout->row.height = 0; } else { - layout->header_h = 2 * item_spacing.y + 1; - layout->row.height = layout->header_h + 1; + layout->header_h = 0; + layout->row.height = item_spacing.y; } /* calculate window footer height */ if (!(win->flags & ZR_WINDOW_NONBLOCK) && (!(win->flags & ZR_WINDOW_NO_SCROLLBAR) || (win->flags & ZR_WINDOW_SCALABLE))) - layout->footer_h = scaler_size.y + item_padding.y; + layout->footer_h = scaler_size.y + style->window.footer_padding.y; else layout->footer_h = 0; /* calculate the window size */ if (!(win->flags & ZR_WINDOW_NO_SCROLLBAR)) - layout->width = win->bounds.w - scrollbar_size; + layout->width = win->bounds.w - scrollbar_size.x; layout->height = win->bounds.h - (layout->header_h + 2 * item_spacing.y); layout->height -= layout->footer_h; - /* window header */ + /* window header state */ header_active = (win->flags & (ZR_WINDOW_CLOSABLE|ZR_WINDOW_MINIMIZABLE)); header_active = header_active || (win->flags & ZR_WINDOW_TITLE); header_active = header_active && !(win->flags & ZR_WINDOW_HIDDEN) && title; + /* window header */ if (header_active) { - struct zr_rect old_clip = out->clip; - struct zr_window_header header; + struct zr_rect header; + struct zr_rect button; + struct zr_text text; + const struct zr_style_item *background; - /* This is a little bit of a performace hack. To make sure the header - * does not get overdrawn with text you do not have to push a scissor rect. - * This is possible because the command buffer automatically clips text - * by using its clipping rectangle. But since the clipping rect gets - * reused to calculate the window clipping rect the old clipping rect - * has to be stored and reset afterwards. */ - out->clip.x = header.x = layout->bounds.x + window_padding.x; - out->clip.y = header.y = layout->bounds.y + item_padding.y; - out->clip.w = header.w = ZR_MAX(layout->bounds.w, 2 * window_padding.x); - out->clip.h = header.w -= 2 * window_padding.x; + /* calculate header bounds */ + header.x = layout->bounds.x; + header.y = layout->bounds.y; + header.w = layout->bounds.w; - /* update the header height and first row height */ - layout->header_h = font->height + 2 * item_padding.y; - layout->header_h += window_padding.y; + /* set correct header/first row height */ + layout->header_h = font->height + 2.0f * style->window.header.padding.y; + layout->header_h += 2.0f * style->window.header.label_padding.y; layout->row.height += layout->header_h; + header.h = layout->header_h + 0.5f; - header.h = layout->header_h; - header.back = header.x + header.w; - header.front = header.x; - + /* update window height */ layout->height = layout->bounds.h - (header.h + 2 * item_spacing.y); layout->height -= layout->footer_h; /* draw header background */ - if (!(layout->flags & ZR_WINDOW_BORDER)) { - zr_draw_rect(out, ZR_FILLED, zr_rect(layout->bounds.x, layout->bounds.y, - layout->bounds.w, layout->header_h), 0, config->colors[ZR_COLOR_HEADER]); + if (ctx->active == win) { + background = &style->window.header.normal; + text.text = style->window.header.label_active; + } else if (zr_input_is_mouse_hovering_rect(&ctx->input, header)) { + background = &style->window.header.hover; + text.text = style->window.header.label_hover; } else { - zr_draw_rect(out, ZR_FILLED, zr_rect(layout->bounds.x, layout->bounds.y+1, - layout->bounds.w, layout->header_h), 0, config->colors[ZR_COLOR_HEADER]); + background = &style->window.header.normal; + text.text = style->window.header.label_normal; + } + if (background->type == ZR_STYLE_ITEM_IMAGE) { + text.background = zr_rgba(0,0,0,0); + zr_draw_image(&win->buffer, header, &background->data.image); + } else { + text.background = background->data.color; + zr_fill_rect(out, zr_rect(layout->bounds.x, layout->bounds.y, + layout->bounds.w, layout->header_h), 0, background->data.color); } - /* window header icons */ - if (win->flags & ZR_WINDOW_CLOSABLE) - zr_header_flag(ctx, &header, config->header.close_symbol, - config->header.close_symbol, config->header.align, ZR_WINDOW_HIDDEN); - if (win->flags & ZR_WINDOW_MINIMIZABLE) - zr_header_flag(ctx, &header, config->header.maximize_symbol, - config->header.minimize_symbol, config->header.align, ZR_WINDOW_MINIMIZED); + /* window close button */ + button.y = header.y + style->window.header.padding.y; + button.h = layout->header_h - 2 * style->window.header.padding.y; + button.w = button.h; + if (win->flags & ZR_WINDOW_CLOSABLE) { + zr_flags ws; + if (style->window.header.align == ZR_HEADER_RIGHT) { + button.x = (header.w + header.x) - (button.w + style->window.header.padding.x); + header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x; + } else { + button.x = header.x; + header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; + } + if (zr_do_button_symbol(&ws, &win->buffer, button, + style->window.header.close_symbol, ZR_BUTTON_DEFAULT, + &style->window.header.close_button, in, &style->font)) + layout->flags |= ZR_WINDOW_HIDDEN; + } + /* window minimize button */ + if (win->flags & ZR_WINDOW_MINIMIZABLE) { + zr_flags ws; + if (style->window.header.align == ZR_HEADER_RIGHT) { + button.x = (header.w + header.x) - button.w; + if (!(win->flags & ZR_WINDOW_CLOSABLE)) { + button.x -= style->window.header.padding.x; + header.w -= style->window.header.padding.x; + } + header.w -= button.w + style->window.header.spacing.x; + } else { + button.x = header.x; + header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; + } + if (zr_do_button_symbol(&ws, &win->buffer, button, + (layout->flags & ZR_WINDOW_MINIMIZED)? + style->window.header.maximize_symbol: + style->window.header.minimize_symbol, + ZR_BUTTON_DEFAULT, &style->window.header.minimize_button, in, &style->font)) + layout->flags = (layout->flags & ZR_WINDOW_MINIMIZED) ? + layout->flags & (zr_flags)~ZR_WINDOW_MINIMIZED: + layout->flags | ZR_WINDOW_MINIMIZED; + } { /* window header title */ zr_size text_len = zr_strsiz(title); struct zr_rect label = {0,0,0,0}; - - /* calculate and allocate space from the header */ zr_size t = font->width(font->userdata, font->height, title, text_len); - if (config->header.align == ZR_HEADER_LEFT) { - header.back = header.back - (3 * item_padding.x + (float)t); - label.x = header.back; - } else { - label.x = header.front; - header.front += 3 * item_padding.x + (float)t; - } - { - /* calculate label bounds and draw text */ - struct zr_text text; - text.padding = zr_vec2(0,0); - text.background = config->colors[ZR_COLOR_HEADER]; - text.text = config->colors[ZR_COLOR_TEXT]; - - label.y = header.y; - label.h = font->height + 2 * item_padding.y; - label.w = ZR_MAX((float)t + 2 * item_padding.x, 4 * item_padding.x); - zr_widget_text(out, label,(const char*)title, text_len, &text, - ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, font); - } + label.x = header.x + style->window.header.padding.x; + label.x += style->window.header.label_padding.x; + label.y = header.y + style->window.header.label_padding.y; + label.h = font->height + 2 * style->window.header.label_padding.y; + label.w = (float)t + 2 * style->window.header.spacing.x; + text.padding = zr_vec2(0,0); + zr_widget_text(out, label,(const char*)title, text_len, &text, + ZR_TEXT_LEFT, font); } - out->clip = old_clip; } /* fix header height for transistion between minimized and maximized window state */ if (win->flags & ZR_WINDOW_MINIMIZED && !(layout->flags & ZR_WINDOW_MINIMIZED)) - layout->row.height += 2 * item_spacing.y + 1; + layout->row.height += 2 * item_spacing.y + style->window.border; if (layout->flags & ZR_WINDOW_MINIMIZED) { /* draw window background if minimized */ layout->row.height = 0; - zr_draw_rect(out, ZR_FILLED, zr_rect(layout->bounds.x, layout->bounds.y, - layout->bounds.w, layout->row.height), 0, config->colors[ZR_COLOR_WINDOW]); + zr_fill_rect(out, zr_rect(layout->bounds.x, layout->bounds.y, + layout->bounds.w, layout->row.height), 0, style->window.background); } else if (!(layout->flags & ZR_WINDOW_DYNAMIC)) { - /* draw static window body */ + /* draw fixed window body */ struct zr_rect body = layout->bounds; if (header_active) { - body.y += layout->header_h; + body.y += layout->header_h - 0.5f; body.h -= layout->header_h; } - zr_draw_rect(out, ZR_FILLED, body, 0, config->colors[ZR_COLOR_WINDOW]); + if (style->window.fixed_background.type == ZR_STYLE_ITEM_IMAGE) + zr_draw_image(out, body, &style->window.fixed_background.data.image); + else zr_fill_rect(out, body, 0, style->window.fixed_background.data.color); } else { /* draw dynamic window body */ - zr_draw_rect(out, ZR_FILLED, zr_rect(layout->bounds.x, layout->bounds.y, + zr_fill_rect(out, zr_rect(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->row.height + window_padding.y), 0, - config->colors[ZR_COLOR_WINDOW]); + style->window.background); } /* draw top window border line */ if (layout->flags & ZR_WINDOW_BORDER) { - zr_draw_line(out, layout->bounds.x, layout->bounds.y, - layout->bounds.x + layout->bounds.w, layout->bounds.y, - config->colors[ZR_COLOR_BORDER]); + zr_stroke_line(out, layout->bounds.x, layout->bounds.y, + layout->bounds.x + layout->bounds.w, layout->bounds.y, style->window.border, + style->window.border_color); } - { /* calculate and set the window clipping rectangle*/ struct zr_rect clip; @@ -8520,11 +8662,11 @@ zr_panel_begin(struct zr_context *ctx, const char *title) } layout->clip.h = win->bounds.h - (layout->footer_h + layout->header_h); - layout->clip.h -= (window_padding.y + item_padding.y); + layout->clip.h -= (2.0f * window_padding.y); layout->clip.y = win->bounds.y; if (win->flags & ZR_WINDOW_BORDER) { - layout->clip.y += 1; - layout->clip.h -= 2; + layout->clip.y += style->window.border; + layout->clip.h -= 2.0f * style->window.border; } /* combo box and menu do not have header space */ @@ -8533,12 +8675,12 @@ zr_panel_begin(struct zr_context *ctx, const char *title) zr_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y, layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h); - zr_draw_scissor(out, clip); + zr_push_scissor(out, clip); win->buffer.clip.x = layout->bounds.x; win->buffer.clip.w = layout->width; if (!(win->flags & ZR_WINDOW_NO_SCROLLBAR)) - win->buffer.clip.w += scrollbar_size; + win->buffer.clip.w += scrollbar_size.x; } return !(layout->flags & ZR_WINDOW_HIDDEN) && !(layout->flags & ZR_WINDOW_MINIMIZED); } @@ -8549,14 +8691,13 @@ zr_panel_end(struct zr_context *ctx) struct zr_input *in; struct zr_window *window; struct zr_panel *layout; + const struct zr_style *style; struct zr_command_buffer *out; - const struct zr_style *config; - float scrollbar_size; - struct zr_vec2 item_padding; + struct zr_vec2 scrollbar_size; + struct zr_vec2 scaler_size; struct zr_vec2 item_spacing; struct zr_vec2 window_padding; - struct zr_vec2 scaler_size; struct zr_rect footer = {0,0,0,0}; ZR_ASSERT(ctx); @@ -8567,18 +8708,17 @@ zr_panel_end(struct zr_context *ctx) window = ctx->current; layout = window->layout; - config = &ctx->style; + style = &ctx->style; out = &window->buffer; in = (layout->flags & ZR_WINDOW_ROM) ? 0 :&ctx->input; if (!(layout->flags & ZR_WINDOW_SUB)) - zr_draw_scissor(out, zr_null_rect); + zr_push_scissor(out, zr_null_rect); /* cache configuration data */ - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - item_spacing = zr_get_property(ctx, ZR_PROPERTY_ITEM_SPACING); - window_padding = zr_get_property(ctx, ZR_PROPERTY_PADDING); - scrollbar_size = zr_get_property(ctx, ZR_PROPERTY_SCROLLBAR_SIZE).x; - scaler_size = zr_get_property(ctx, ZR_PROPERTY_SCALER_SIZE); + item_spacing = style->window.spacing; + window_padding = style->window.padding; + scrollbar_size = style->window.scrollbar_size; + scaler_size = style->window.scaler_size; /* update the current cursor Y-position to point over the last added widget */ layout->at_y += layout->row.height; @@ -8593,7 +8733,7 @@ zr_panel_end(struct zr_context *ctx) * or hidden scrollbars */ footer.x = window->bounds.x; footer.y = window->bounds.y + layout->height + item_spacing.y; - footer.w = window->bounds.w + scrollbar_size; + footer.w = window->bounds.w + scrollbar_size.x; layout->footer_h = 0; footer.h = 0; @@ -8601,22 +8741,22 @@ zr_panel_end(struct zr_context *ctx) /* special case for windows like combobox, menu require draw call * to fill the empty scrollbar background */ struct zr_rect bounds; - bounds.x = layout->bounds.x + layout->width - item_padding.x; + bounds.x = layout->bounds.x + layout->width; bounds.y = layout->clip.y; - bounds.w = scrollbar_size + item_padding.x; - bounds.h = layout->height + item_padding.y; - zr_draw_rect(out, ZR_FILLED, bounds, 0, config->colors[ZR_COLOR_WINDOW]); + bounds.w = scrollbar_size.x; + bounds.h = layout->height; + zr_fill_rect(out, bounds, 0, style->window.background); } } else { /* dynamic window with visible scrollbars and therefore bigger footer */ footer.x = window->bounds.x; - footer.w = window->bounds.w + scrollbar_size; + footer.w = window->bounds.w + scrollbar_size.x; footer.h = layout->footer_h; if ((layout->flags & ZR_WINDOW_COMBO) || (layout->flags & ZR_WINDOW_MENU) || (layout->flags & ZR_WINDOW_CONTEXTUAL)) footer.y = window->bounds.y + layout->height; else footer.y = window->bounds.y + layout->height + layout->footer_h; - zr_draw_rect(out, ZR_FILLED, footer, 0, config->colors[ZR_COLOR_WINDOW]); + zr_fill_rect(out, footer, 0, style->window.background); if (!(layout->flags & ZR_WINDOW_COMBO) && !(layout->flags & ZR_WINDOW_MENU)) { /* fill empty scrollbar space */ @@ -8625,39 +8765,37 @@ zr_panel_end(struct zr_context *ctx) bounds.y = window->bounds.y + layout->height; bounds.w = layout->bounds.w; bounds.h = layout->row.height; - zr_draw_rect(out, ZR_FILLED, bounds, 0, config->colors[ZR_COLOR_WINDOW]); + zr_fill_rect(out, bounds, 0, style->window.background); } } } /* scrollbars */ - if (!(layout->flags & ZR_WINDOW_NO_SCROLLBAR) && !(layout->flags & ZR_WINDOW_MINIMIZED)) { + if (!(layout->flags & ZR_WINDOW_NO_SCROLLBAR) && !(layout->flags & ZR_WINDOW_MINIMIZED)) + { struct zr_rect bounds; - float scroll_target, scroll_offset, scroll_step; - - /* fill scrollbar style */ - struct zr_scrollbar scroll; - scroll.rounding = config->rounding[ZR_ROUNDING_SCROLLBAR]; - scroll.background = config->colors[ZR_COLOR_SCROLLBAR]; - scroll.normal = config->colors[ZR_COLOR_SCROLLBAR_CURSOR]; - scroll.hover = config->colors[ZR_COLOR_SCROLLBAR_CURSOR_HOVER]; - scroll.active = config->colors[ZR_COLOR_SCROLLBAR_CURSOR_ACTIVE]; - scroll.border = config->colors[ZR_COLOR_BORDER]; + int scroll_has_scrolling; + float scroll_target; + float scroll_offset; + float scroll_step; + float scroll_inc; { /* vertical scollbar */ zr_flags state; bounds.x = layout->bounds.x + layout->width; bounds.y = layout->clip.y; - bounds.w = scrollbar_size; + bounds.w = scrollbar_size.y; bounds.h = layout->clip.h; if (layout->flags & ZR_WINDOW_BORDER) bounds.h -= 1; scroll_offset = layout->offset->y; scroll_step = layout->clip.h * 0.10f; + scroll_inc = layout->clip.h * 0.01f; scroll_target = (float)(int)(layout->at_y - layout->clip.y); - scroll.has_scrolling = (window == ctx->active); - scroll_offset = zr_do_scrollbarv(&state, out, bounds, scroll_offset, - scroll_target, scroll_step, &scroll, in); + scroll_has_scrolling = (window == ctx->active); + scroll_offset = zr_do_scrollbarv(&state, out, bounds, scroll_has_scrolling, + scroll_offset, scroll_target, scroll_step, scroll_inc, + &ctx->style.scrollv, in, &style->font); layout->offset->y = (unsigned short)scroll_offset; } { @@ -8665,50 +8803,61 @@ zr_panel_end(struct zr_context *ctx) zr_flags state; bounds.x = layout->bounds.x + window_padding.x; if (layout->flags & ZR_WINDOW_SUB) { - bounds.h = scrollbar_size; + bounds.h = scrollbar_size.x; bounds.y = (layout->flags & ZR_WINDOW_BORDER) ? layout->bounds.y + 1 : layout->bounds.y; bounds.y += layout->header_h + layout->menu.h + layout->height; bounds.w = layout->clip.w; } else if (layout->flags & ZR_WINDOW_DYNAMIC) { - bounds.h = ZR_MIN(scrollbar_size, layout->footer_h); + bounds.h = ZR_MIN(scrollbar_size.x, layout->footer_h); bounds.w = layout->bounds.w; bounds.y = footer.y; } else { - bounds.h = ZR_MIN(scrollbar_size, layout->footer_h); + bounds.h = ZR_MIN(scrollbar_size.x, layout->footer_h); bounds.y = layout->bounds.y + window->bounds.h; - bounds.y -= ZR_MAX(layout->footer_h, scrollbar_size); + bounds.y -= ZR_MAX(layout->footer_h, scrollbar_size.x); bounds.w = layout->width - 2 * window_padding.x; } scroll_offset = layout->offset->x; scroll_target = (float)(int)(layout->max_x - bounds.x); scroll_step = layout->max_x * 0.05f; - scroll.has_scrolling = zr_false; - scroll_offset = zr_do_scrollbarh(&state, out, bounds, scroll_offset, - scroll_target, scroll_step, &scroll, in); + scroll_inc = layout->max_x * 0.005f; + scroll_has_scrolling = zr_false; + scroll_offset = zr_do_scrollbarh(&state, out, bounds, scroll_has_scrolling, + scroll_offset, scroll_target, scroll_step, scroll_inc, + &ctx->style.scrollh, in, &style->font); layout->offset->x = (unsigned short)scroll_offset; } } - /* draw the panel scaler into the right corner of the panel footer and - * update panel size if user drags the scaler */ + /* scaler */ if ((layout->flags & ZR_WINDOW_SCALABLE) && in && !(layout->flags & ZR_WINDOW_MINIMIZED)) { - struct zr_color col = config->colors[ZR_COLOR_SCALER]; - float scaler_w = ZR_MAX(0, scaler_size.x - item_padding.x); - float scaler_h = ZR_MAX(0, scaler_size.y - item_padding.y); - float scaler_x = (layout->bounds.x + layout->bounds.w) - (item_padding.x + scaler_w); - + /* caluclate scaler bounds */ + const struct zr_style_item *scaler; + float scaler_w = ZR_MAX(0, scaler_size.x - window_padding.x); + float scaler_h = ZR_MAX(0, scaler_size.y - window_padding.y); + float scaler_x = (layout->bounds.x + layout->bounds.w) - (window_padding.x + scaler_w); float scaler_y; if (layout->flags & ZR_WINDOW_DYNAMIC) scaler_y = footer.y + layout->footer_h - scaler_size.y; else scaler_y = layout->bounds.y + layout->bounds.h - scaler_size.y; - zr_draw_triangle(out, ZR_FILLED, scaler_x + scaler_w, scaler_y, - scaler_x + scaler_w, scaler_y + scaler_h, scaler_x, scaler_y + scaler_h, col); + /* draw scaler */ + scaler = &style->window.scaler; + if (scaler->type == ZR_STYLE_ITEM_IMAGE) { + zr_draw_image(out, zr_rect(scaler_x, scaler_y, scaler_w, scaler_h), + &scaler->data.image); + } else { + zr_fill_triangle(out, scaler_x + scaler_w, scaler_y, scaler_x + scaler_w, + scaler_y + scaler_h, scaler_x, scaler_y + scaler_h, + scaler->data.color); + } + + /* do window scaling logic */ if (!(window->flags & ZR_WINDOW_ROM)) { float prev_x = in->mouse.prev.x; float prev_y = in->mouse.prev.y; - struct zr_vec2 window_size = zr_get_property(ctx, ZR_PROPERTY_SIZE); + struct zr_vec2 window_size = style->window.min_size; int incursor = ZR_INBOX(prev_x,prev_y,scaler_x,scaler_y,scaler_w,scaler_h); if (zr_input_is_mouse_down(in, ZR_BUTTON_LEFT) && incursor) { @@ -8720,10 +8869,10 @@ zr_panel_end(struct zr_context *ctx) } } + /* window border */ if (layout->flags & ZR_WINDOW_BORDER) { - /* draw the border around the complete panel */ const float width = (layout->flags & ZR_WINDOW_NO_SCROLLBAR) ? - layout->width: layout->width + scrollbar_size; + layout->width: layout->width + scrollbar_size.x; const float padding_y = (layout->flags & ZR_WINDOW_MINIMIZED) ? window->bounds.y + layout->header_h: (layout->flags & ZR_WINDOW_DYNAMIC)? @@ -8731,15 +8880,16 @@ zr_panel_end(struct zr_context *ctx) layout->bounds.y + layout->bounds.h; if (window->flags & ZR_WINDOW_BORDER_HEADER) - zr_draw_line(out, window->bounds.x, window->bounds.y + layout->header_h, + zr_stroke_line(out, window->bounds.x, window->bounds.y + layout->header_h, window->bounds.x + window->bounds.w, window->bounds.y + layout->header_h, - config->colors[ZR_COLOR_BORDER]); - zr_draw_line(out, window->bounds.x, padding_y, window->bounds.x + width, - padding_y, config->colors[ZR_COLOR_BORDER]); - zr_draw_line(out, window->bounds.x, window->bounds.y, window->bounds.x, - padding_y, config->colors[ZR_COLOR_BORDER]); - zr_draw_line(out, window->bounds.x + width, window->bounds.y, - window->bounds.x + width, padding_y, config->colors[ZR_COLOR_BORDER]); + style->window.border, style->window.border_color); + zr_stroke_line(out, window->bounds.x, padding_y, window->bounds.x + width, + padding_y, style->window.border, style->window.border_color); + zr_stroke_line(out, window->bounds.x, window->bounds.y, window->bounds.x, + padding_y, style->window.border, style->window.border_color); + zr_stroke_line(out, window->bounds.x + width, window->bounds.y, + window->bounds.x + width, padding_y, style->window.border, + style->window.border_color); } if (!(window->flags & ZR_WINDOW_SUB)) { @@ -8838,24 +8988,33 @@ zr_menubar_end(struct zr_context *ctx) *layout->offset = layout->menu.offset; layout->clip.h -= layout->menu.h + layout->row.height; layout->at_y = layout->menu.y + layout->menu.h; - zr_draw_scissor(out, layout->clip); + zr_push_scissor(out, layout->clip); } /* ------------------------------------------------------------- * * LAYOUT * * --------------------------------------------------------------*/ +#define ZR_LAYOUT_DYNAMIC_FIXED 0 +#define ZR_LAYOUT_DYNAMIC_ROW 1 +#define ZR_LAYOUT_DYNAMIC_FREE 2 +#define ZR_LAYOUT_DYNAMIC 3 +#define ZR_LAYOUT_STATIC_FIXED 4 +#define ZR_LAYOUT_STATIC_ROW 5 +#define ZR_LAYOUT_STATIC_FREE 6 +#define ZR_LAYOUT_STATIC 7 + static void zr_panel_layout(const struct zr_context *ctx, struct zr_window *win, float height, int cols) { struct zr_panel *layout; - const struct zr_style *config; + const struct zr_style *style; struct zr_command_buffer *out; struct zr_vec2 item_spacing; struct zr_vec2 panel_padding; - const struct zr_color *color; + struct zr_color color; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -8865,11 +9024,11 @@ zr_panel_layout(const struct zr_context *ctx, struct zr_window *win, /* prefetch some configuration data */ layout = win->layout; - config = &ctx->style; + style = &ctx->style; out = &win->buffer; - color = &config->colors[ZR_COLOR_WINDOW]; - item_spacing = zr_get_property(ctx, ZR_PROPERTY_ITEM_SPACING); - panel_padding = zr_get_property(ctx, ZR_PROPERTY_PADDING); + color = style->window.background; + item_spacing = style->window.spacing; + panel_padding = style->window.padding; /* update the current row and set the current row layout */ layout->row.index = 0; @@ -8878,8 +9037,8 @@ zr_panel_layout(const struct zr_context *ctx, struct zr_window *win, layout->row.height = height + item_spacing.y; layout->row.item_offset = 0; if (layout->flags & ZR_WINDOW_DYNAMIC) - zr_draw_rect(out, ZR_FILLED, zr_rect(layout->bounds.x, layout->at_y, - layout->bounds.w, height + panel_padding.y), 0, *color); + zr_fill_rect(out, zr_rect(layout->bounds.x, layout->at_y, + layout->bounds.w, height + panel_padding.y), 0, color); } static void @@ -9183,7 +9342,7 @@ static void zr_panel_alloc_row(const struct zr_context *ctx, struct zr_window *win) { struct zr_panel *layout = win->layout; - struct zr_vec2 spacing = zr_get_property(ctx, ZR_PROPERTY_ITEM_SPACING); + struct zr_vec2 spacing = ctx->style.window.spacing; const float row_height = layout->row.height - spacing.y; zr_panel_layout(ctx, win, row_height, layout->row.columns); } @@ -9215,8 +9374,8 @@ zr_layout_widget_space(struct zr_rect *bounds, const struct zr_context *ctx, ZR_ASSERT(bounds); /* cache some configuration data */ - spacing = zr_get_property(ctx, ZR_PROPERTY_ITEM_SPACING); - padding = zr_get_property(ctx, ZR_PROPERTY_PADDING); + spacing = ctx->style.window.spacing; + padding = ctx->style.window.padding; /* calculate the useable panel space */ panel_padding = 2 * padding.x; @@ -9370,26 +9529,27 @@ zr_layout_peek(struct zr_rect *bounds, struct zr_context *ctx) } int -zr_layout_push(struct zr_context *ctx, enum zr_layout_node_type type, - const char *title, enum zr_collapse_states initial_state) +zr__layout_push(struct zr_context *ctx, enum zr_layout_node_type type, + const char *title, enum zr_collapse_states initial_state, + const char *file, int line) { struct zr_window *win; struct zr_panel *layout; - const struct zr_style *config; + const struct zr_style *style; struct zr_command_buffer *out; const struct zr_input *in; struct zr_vec2 item_spacing; - struct zr_vec2 item_padding; struct zr_vec2 panel_padding; struct zr_rect header = {0,0,0,0}; struct zr_rect sym = {0,0,0,0}; + struct zr_text text; zr_flags ws; - enum zr_widget_state widget_state; int title_len; zr_hash title_hash; zr_uint *state = 0; + enum zr_widget_layout_states widget_state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -9401,21 +9561,31 @@ zr_layout_push(struct zr_context *ctx, enum zr_layout_node_type type, win = ctx->current; layout = win->layout; out = &win->buffer; - config = &ctx->style; + style = &ctx->style; - item_spacing = zr_get_property(ctx, ZR_PROPERTY_ITEM_SPACING); - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - panel_padding = zr_get_property(ctx, ZR_PROPERTY_PADDING); + item_spacing = style->window.spacing; + panel_padding = style->window.padding; /* calculate header bounds and draw background */ - zr_layout_row_dynamic(ctx, config->font.height + 2 * item_padding.y, 1); + zr_layout_row_dynamic(ctx, style->font.height + 2 * style->tab.padding.y, 1); widget_state = zr_widget(&header, ctx); - if (type == ZR_LAYOUT_TAB) - zr_draw_rect(out, ZR_FILLED, header, 0, config->colors[ZR_COLOR_TAB_HEADER]); + if (type == ZR_LAYOUT_TAB) { + const struct zr_style_item *background = &style->tab.background; + if (background->type == ZR_STYLE_ITEM_IMAGE) { + zr_draw_image(out, header, &background->data.image); + text.background = zr_rgba(0,0,0,0); + } else { + text.background = background->data.color; + zr_fill_rect(out, header, 0, style->tab.border_color); + zr_fill_rect(out, zr_shrink_rect(header, style->tab.border), + style->tab.rounding, background->data.color); + } + } else text.background = style->window.background; /* find or create tab persistent state (open/closed) */ title_len = (int)zr_strsiz(title); - title_hash = zr_murmur_hash(title, (int)title_len, ZR_WINDOW_HIDDEN); + title_hash = zr_murmur_hash(title, (int)title_len, (zr_hash)line); + if (file) title_hash += zr_murmur_hash(file, (int)zr_strsiz(file), (zr_hash)line); state = zr_find_value(win, title_hash); if (!state) { state = zr_add_value(ctx, win, title_hash, 0); @@ -9429,57 +9599,41 @@ zr_layout_push(struct zr_context *ctx, enum zr_layout_node_type type, *state = (*state == ZR_MAXIMIZED) ? ZR_MINIMIZED : ZR_MAXIMIZED; { - /* and draw closing/open icon */ + /* draw closing/open icon */ enum zr_heading heading; - struct zr_vec2 points[3]; heading = (*state == ZR_MAXIMIZED) ? ZR_DOWN : ZR_RIGHT; /* calculate the triangle bounds */ - sym.w = sym.h = config->font.height; - sym.y = header.y + item_padding.y; - sym.x = header.x + panel_padding.x + item_padding.x; + sym.w = sym.h = style->font.height; + sym.y = header.y + style->tab.padding.y; + sym.x = header.x + panel_padding.x + style->tab.padding.x; /* calculate the triangle points and draw triangle */ - zr_triangle_from_direction(points, sym, 0, 0, heading); - zr_draw_triangle(&win->buffer, ZR_FILLED, points[0].x, points[0].y, - points[1].x, points[1].y, points[2].x, points[2].y, config->colors[ZR_COLOR_TEXT]); + zr_do_button_symbol(&ws, &win->buffer, sym, + (*state == ZR_MAXIMIZED)? style->tab.sym_minimize: style->tab.sym_maximize, + ZR_BUTTON_DEFAULT, (type == ZR_LAYOUT_TAB)? + &style->tab.tab_button: &style->tab.node_button, + in, &style->font); /* calculate the space the icon occupied */ - sym.w = config->font.height + 2 * item_padding.x; + sym.w = style->font.height + 2 * style->tab.spacing.x; } { /* draw node label */ - struct zr_color color; struct zr_rect label; - struct zr_text text; - header.w = ZR_MAX(header.w, sym.w + item_spacing.y + panel_padding.x); label.x = sym.x + sym.w + item_spacing.x; label.y = sym.y; label.w = header.w - (sym.w + item_spacing.y + panel_padding.x); - label.h = config->font.height; + label.h = style->font.height; - color = (type == ZR_LAYOUT_TAB) ? - config->colors[ZR_COLOR_TAB_HEADER]: - config->colors[ZR_COLOR_WINDOW]; + text.text = style->tab.text; text.padding = zr_vec2(0,0); - text.background = color; - text.text = config->colors[ZR_COLOR_TEXT]; zr_widget_text(out, label, title, zr_strsiz(title), &text, - ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, &config->font); + ZR_TEXT_LEFT, &style->font); } - if (type == ZR_LAYOUT_TAB) { - /* special node with border around the header */ - zr_draw_line(out, header.x, header.y, - header.x + header.w-1, header.y, config->colors[ZR_COLOR_BORDER]); - zr_draw_line(out, header.x, header.y, - header.x, header.y + header.h, config->colors[ZR_COLOR_BORDER]); - zr_draw_line(out, header.x + header.w-1, header.y, - header.x + header.w-1, header.y + header.h, config->colors[ZR_COLOR_BORDER]); - zr_draw_line(out, header.x, header.y + header.h, - header.x + header.w-1, header.y + header.h, config->colors[ZR_COLOR_BORDER]); - } + /* increase x-axis cursor widget position pointer */ if (*state == ZR_MAXIMIZED) { layout->at_x = header.x + layout->offset->x; layout->width = ZR_MAX(layout->width, 2 * panel_padding.x); @@ -9503,7 +9657,7 @@ void zr_layout_pop(struct zr_context *ctx) win = ctx->current; layout = win->layout; - panel_padding = zr_get_property(ctx, ZR_PROPERTY_PADDING); + panel_padding = ctx->style.window.padding; layout->at_x -= panel_padding.x; layout->width += 2 * panel_padding.x; ZR_ASSERT(layout->row.tree_depth); @@ -9511,7 +9665,7 @@ void zr_layout_pop(struct zr_context *ctx) } /*---------------------------------------------------------------- * - * WIDGETS + * WIDGETS * * --------------------------------------------------------------*/ struct zr_rect @@ -9600,6 +9754,60 @@ zr_widget_has_mouse_click_down(struct zr_context *ctx, enum zr_buttons btn, int return ret; } +enum zr_widget_layout_states +zr_widget(struct zr_rect *bounds, const struct zr_context *ctx) +{ + struct zr_rect *c = 0; + ZR_ASSERT(ctx); + ZR_ASSERT(ctx->current); + ZR_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout) + return ZR_WIDGET_INVALID; + + /* allocate space and check if the widget needs to be updated and drawn */ + zr_panel_alloc_space(bounds, ctx); + c = &ctx->current->layout->clip; + if (!ZR_INTERSECT(c->x, c->y, c->w, c->h, bounds->x, bounds->y, bounds->w, bounds->h)) + return ZR_WIDGET_INVALID; + if (!ZR_CONTAINS(bounds->x, bounds->y, bounds->w, bounds->h, c->x, c->y, c->w, c->h)) + return ZR_WIDGET_ROM; + return ZR_WIDGET_VALID; +} + +enum zr_widget_layout_states +zr_widget_fitting(struct zr_rect *bounds, struct zr_context *ctx, + struct zr_vec2 item_padding) +{ + /* update the bounds to stand without padding */ + struct zr_window *win; + struct zr_style *style; + struct zr_panel *layout; + enum zr_widget_layout_states state; + + ZR_ASSERT(ctx); + ZR_ASSERT(ctx->current); + ZR_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout) + return ZR_WIDGET_INVALID; + + win = ctx->current; + style = &ctx->style; + layout = win->layout; + state = zr_widget(bounds, ctx); + if (layout->row.index == 1) { + bounds->w += style->window.padding.x; + bounds->x -= style->window.padding.x; + } else bounds->x -= item_padding.x; + + if (layout->row.index == layout->row.columns) + bounds->w += style->window.padding.x; + else bounds->w += item_padding.x; + return state; +} + +/*---------------------------------------------------------------- + * MISC + * --------------------------------------------------------------*/ void zr_spacing(struct zr_context *ctx, int cols) { @@ -9634,95 +9842,15 @@ zr_spacing(struct zr_context *ctx, int cols) layout->row.index = index; } -void -zr_seperator(struct zr_context *ctx) -{ - struct zr_window *win; - struct zr_panel *layout; - struct zr_command_buffer *out; - const struct zr_style *config; - - struct zr_vec2 item_padding; - struct zr_vec2 item_spacing; - struct zr_rect bounds; - - ZR_ASSERT(ctx); - ZR_ASSERT(ctx->current); - ZR_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - config = &ctx->style; - layout = win->layout; - out = &win->buffer; - - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - item_spacing = zr_get_property(ctx, ZR_PROPERTY_ITEM_SPACING); - - bounds.h = 1; - bounds.w = ZR_MAX(layout->width, 2 * item_spacing.x + 2 * item_padding.x); - bounds.y = (layout->at_y + layout->row.height + item_padding.y) - layout->offset->y; - bounds.x = layout->at_x + item_spacing.x + item_padding.x - layout->offset->x; - bounds.w = bounds.w - (2 * item_spacing.x + 2 * item_padding.x); - zr_draw_line(out, bounds.x, bounds.y, bounds.x + bounds.w, - bounds.y + bounds.h, config->colors[ZR_COLOR_BORDER]); -} - -enum zr_widget_state -zr_widget(struct zr_rect *bounds, const struct zr_context *ctx) -{ - struct zr_rect *c = 0; - ZR_ASSERT(ctx); - ZR_ASSERT(ctx->current); - ZR_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return ZR_WIDGET_INVALID; - - /* allocate space and check if the widget needs to be updated and drawn */ - zr_panel_alloc_space(bounds, ctx); - c = &ctx->current->layout->clip; - if (!ZR_INTERSECT(c->x, c->y, c->w, c->h, bounds->x, bounds->y, bounds->w, bounds->h)) - return ZR_WIDGET_INVALID; - if (!ZR_CONTAINS(bounds->x, bounds->y, bounds->w, bounds->h, c->x, c->y, c->w, c->h)) - return ZR_WIDGET_ROM; - return ZR_WIDGET_VALID; -} - -enum zr_widget_state -zr_widget_fitting(struct zr_rect *bounds, struct zr_context *ctx) -{ - /* update the bounds to stand without padding */ - struct zr_window *win; - struct zr_panel *layout; - enum zr_widget_state state; - - ZR_ASSERT(ctx); - ZR_ASSERT(ctx->current); - ZR_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return ZR_WIDGET_INVALID; - - win = ctx->current; - layout = win->layout; - state = zr_widget(bounds, ctx); - if (layout->row.index == 1) { - bounds->w += ctx->style.properties[ZR_PROPERTY_PADDING].x; - bounds->x -= ctx->style.properties[ZR_PROPERTY_PADDING].x; - } else bounds->x -= ctx->style.properties[ZR_PROPERTY_ITEM_PADDING].x; - - if (layout->row.index == layout->row.columns) - bounds->w += ctx->style.properties[ZR_PROPERTY_PADDING].x; - else bounds->w += ctx->style.properties[ZR_PROPERTY_ITEM_PADDING].x; - return state; -} - +/*---------------------------------------------------------------- + * TEXT + * --------------------------------------------------------------*/ void zr_text_colored(struct zr_context *ctx, const char *str, zr_size len, zr_flags alignment, struct zr_color color) { struct zr_window *win; - const struct zr_style *config; + const struct zr_style *style; struct zr_vec2 item_padding; struct zr_rect bounds; @@ -9734,24 +9862,23 @@ zr_text_colored(struct zr_context *ctx, const char *str, zr_size len, zr_flags a if (!ctx || !ctx->current || !ctx->current->layout) return; win = ctx->current; - config = &ctx->style; + style = &ctx->style; zr_panel_alloc_space(&bounds, ctx); - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); + item_padding = style->text.padding; text.padding.x = item_padding.x; text.padding.y = item_padding.y; - text.background = config->colors[ZR_COLOR_WINDOW]; + text.background = style->window.background; text.text = color; - zr_widget_text(&win->buffer, bounds, str, len, &text, alignment, &config->font); + zr_widget_text(&win->buffer, bounds, str, len, &text, alignment, &style->font); } - void zr_text_wrap_colored(struct zr_context *ctx, const char *str, zr_size len, struct zr_color color) { struct zr_window *win; - const struct zr_style *config; + const struct zr_style *style; struct zr_vec2 item_padding; struct zr_rect bounds; @@ -9763,15 +9890,16 @@ zr_text_wrap_colored(struct zr_context *ctx, const char *str, if (!ctx || !ctx->current || !ctx->current->layout) return; win = ctx->current; - config = &ctx->style; + style = &ctx->style; zr_panel_alloc_space(&bounds, ctx); - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); + item_padding = style->text.padding; text.padding.x = item_padding.x; text.padding.y = item_padding.y; - text.background = config->colors[ZR_COLOR_WINDOW]; + text.background = style->window.background; text.text = color; - zr_widget_text_wrap(&win->buffer, bounds, str, len, &text, &config->font); + zr_widget_text_wrap(&win->buffer, bounds, str, len, &text, &style->font); + ctx->last_widget_state = 0; } void @@ -9779,7 +9907,7 @@ zr_text(struct zr_context *ctx, const char *str, zr_size len, zr_flags alignment { ZR_ASSERT(ctx); if (!ctx) return; - zr_text_colored(ctx, str, len, alignment, ctx->style.colors[ZR_COLOR_TEXT]); + zr_text_colored(ctx, str, len, alignment, ctx->style.text.color); } void @@ -9787,7 +9915,7 @@ zr_text_wrap(struct zr_context *ctx, const char *str, zr_size len) { ZR_ASSERT(ctx); if (!ctx) return; - zr_text_wrap_colored(ctx, str, len, ctx->style.colors[ZR_COLOR_TEXT]); + zr_text_wrap_colored(ctx, str, len, ctx->style.text.color); } void @@ -9811,7 +9939,6 @@ void zr_image(struct zr_context *ctx, struct zr_image img) { struct zr_window *win; - struct zr_vec2 item_padding; struct zr_rect bounds; ZR_ASSERT(ctx); @@ -9821,55 +9948,24 @@ zr_image(struct zr_context *ctx, struct zr_image img) win = ctx->current; if (!zr_widget(&bounds, ctx)) return; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - bounds.x += item_padding.x; - bounds.y += item_padding.y; - bounds.w -= 2 * item_padding.x; - bounds.h -= 2 * item_padding.y; zr_draw_image(&win->buffer, bounds, &img); + ctx->last_widget_state = 0; } -enum zr_button_alloc {ZR_BUTTON_NORMAL, ZR_BUTTON_FITTING}; -static enum zr_widget_state -zr_button(struct zr_button *button, struct zr_rect *bounds, - struct zr_context *ctx, enum zr_button_alloc type) -{ - const struct zr_style *config = &ctx->style; - enum zr_widget_state state; - struct zr_vec2 item_padding; - - if (type == ZR_BUTTON_NORMAL) - state = zr_widget(bounds, ctx); - else state = zr_widget_fitting(bounds, ctx); - if (!state) return state; - - zr_zero(button, sizeof(*button)); - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - button->touch_pad = zr_get_property(ctx, ZR_PROPERTY_TOUCH_PADDING); - button->rounding = config->rounding[ZR_ROUNDING_BUTTON]; - button->normal = config->colors[ZR_COLOR_BUTTON]; - button->hover = config->colors[ZR_COLOR_BUTTON_HOVER]; - button->active = config->colors[ZR_COLOR_BUTTON_ACTIVE]; - button->border = config->colors[ZR_COLOR_BORDER]; - button->padding.x = item_padding.x; - button->padding.y = item_padding.y; - button->border_width = 1; - return state; -} - +/*---------------------------------------------------------------- + * BUTTON + * --------------------------------------------------------------*/ int -zr_button_text(struct zr_context *ctx, const char *title, +zr_button_text(struct zr_context *ctx, const char *title, zr_size len, enum zr_button_behavior behavior) { struct zr_window *win; struct zr_panel *layout; - const struct zr_input *i; - const struct zr_style *config; + const struct zr_input *in; + const struct zr_style *style; struct zr_rect bounds; - struct zr_button_text button; - enum zr_widget_state state; - zr_flags ws; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -9877,20 +9973,21 @@ zr_button_text(struct zr_context *ctx, const char *title, if (!ctx || !ctx->current || !ctx->current->layout) return 0; win = ctx->current; - config = &ctx->style; + style = &ctx->style; layout = win->layout; - state = zr_button(&button.base, &bounds, ctx, ZR_BUTTON_NORMAL); - if (!state) return 0; - i = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; + state = zr_widget(&bounds, ctx); - button.alignment = ZR_TEXT_CENTERED|ZR_TEXT_MIDDLE; - button.normal = config->colors[ZR_COLOR_TEXT]; - button.hover = config->colors[ZR_COLOR_TEXT_HOVERING]; - button.active = config->colors[ZR_COLOR_TEXT_ACTIVE]; - return zr_do_button_text(&ws, &win->buffer, bounds, title, behavior, - &button, i, &config->font); + if (!state) return 0; + in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; + return zr_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, + title, len, style->button.text_alignment, behavior, + &style->button, in, &style->font); } +int zr_button_label(struct zr_context *ctx, const char *title, + enum zr_button_behavior behavior) +{return zr_button_text(ctx, title, zr_strsiz(title), behavior);} + int zr_button_color(struct zr_context *ctx, struct zr_color color, enum zr_button_behavior behavior) @@ -9898,11 +9995,12 @@ zr_button_color(struct zr_context *ctx, struct zr_color color, struct zr_window *win; struct zr_panel *layout; const struct zr_input *in; + struct zr_style_button button; + const struct zr_style *style; + int ret = 0; struct zr_rect bounds; - struct zr_button button; - enum zr_widget_state state; - zr_flags ws; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -9911,15 +10009,22 @@ zr_button_color(struct zr_context *ctx, struct zr_color color, return 0; win = ctx->current; + style = &ctx->style; layout = win->layout; - state = zr_button(&button, &bounds, ctx, ZR_BUTTON_NORMAL); + + state = zr_widget(&bounds, ctx); if (!state) return 0; in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - button.normal = color; - button.hover = color; - button.active = color; - return zr_do_button(&ws, &win->buffer, bounds, &button, in, behavior, &bounds); + button = ctx->style.button; + button.normal = zr_style_item_color(color); + button.hover = zr_style_item_color(color); + button.active = zr_style_item_color(color); + button.padding = zr_vec2(0,0); + ret = zr_do_button(&ctx->last_widget_state, &win->buffer, bounds, + &button, in, behavior, &bounds); + zr_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button); + return ret; } int @@ -9929,31 +10034,26 @@ zr_button_symbol(struct zr_context *ctx, enum zr_symbol_type symbol, struct zr_window *win; struct zr_panel *layout; const struct zr_input *in; - const struct zr_style *config; + const struct zr_style *style; struct zr_rect bounds; - struct zr_button_symbol button; - enum zr_widget_state state; - zr_flags ws; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); ZR_ASSERT(ctx->current->layout); if (!ctx || !ctx->current || !ctx->current->layout) - return zr_false; + return 0; win = ctx->current; - config = &ctx->style; + style = &ctx->style; layout = win->layout; - state = zr_button(&button.base, &bounds, ctx, ZR_BUTTON_NORMAL); - if (!state) return zr_false; - in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - button.normal = config->colors[ZR_COLOR_TEXT]; - button.hover = config->colors[ZR_COLOR_TEXT_HOVERING]; - button.active = config->colors[ZR_COLOR_TEXT_ACTIVE]; - return zr_do_button_symbol(&ws, &win->buffer, bounds, symbol, - behavior, &button, in, &config->font); + state = zr_widget(&bounds, ctx); + if (!state) return 0; + in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; + return zr_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds, + symbol, behavior, &style->button, in, &style->font); } int @@ -9963,109 +10063,108 @@ zr_button_image(struct zr_context *ctx, struct zr_image img, struct zr_window *win; struct zr_panel *layout; const struct zr_input *in; + const struct zr_style *style; struct zr_rect bounds; - struct zr_button_icon button; - enum zr_widget_state state; - zr_flags ws; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); ZR_ASSERT(ctx->current->layout); if (!ctx || !ctx->current || !ctx->current->layout) - return zr_false; + return 0; win = ctx->current; + style = &ctx->style; layout = win->layout; - state = zr_button(&button.base, &bounds, ctx, ZR_BUTTON_NORMAL); - if (!state) return zr_false; + + state = zr_widget(&bounds, ctx); + if (!state) return 0; in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - button.padding = zr_vec2(0,0); - return zr_do_button_image(&ws, &win->buffer, bounds, img, behavior, &button, in); + return zr_do_button_image(&ctx->last_widget_state, &win->buffer, bounds, + img, behavior, &style->button, in); } int -zr_button_text_symbol(struct zr_context *ctx, enum zr_symbol_type symbol, - const char* text, zr_flags align, enum zr_button_behavior behavior) +zr_button_symbol_text(struct zr_context *ctx, enum zr_symbol_type symbol, + const char* text, zr_size len, zr_flags align, enum zr_button_behavior behavior) { struct zr_window *win; struct zr_panel *layout; const struct zr_input *in; - const struct zr_style *config; + const struct zr_style *style; struct zr_rect bounds; - struct zr_button_text button; - enum zr_widget_state state; - zr_flags ws; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); ZR_ASSERT(ctx->current->layout); if (!ctx || !ctx->current || !ctx->current->layout) - return zr_false; + return 0; win = ctx->current; - config = &ctx->style; + style = &ctx->style; layout = win->layout; - state = zr_button(&button.base, &bounds, ctx, ZR_BUTTON_NORMAL); - if (!state) return zr_false; - in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - button.alignment = ZR_TEXT_CENTERED|ZR_TEXT_MIDDLE; - button.normal = config->colors[ZR_COLOR_TEXT]; - button.hover = config->colors[ZR_COLOR_TEXT_HOVERING]; - button.active = config->colors[ZR_COLOR_TEXT_ACTIVE]; - return zr_do_button_text_symbol(&ws, &win->buffer, bounds, symbol, text, align, - behavior, &button, &config->font, in); + state = zr_widget(&bounds, ctx); + if (!state) return 0; + in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; + return zr_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, + symbol, text, len, align, behavior, &style->button, &style->font, in); } -int zr_button_text_image(struct zr_context *ctx, struct zr_image img, - const char *text, zr_flags align, enum zr_button_behavior behavior) +int zr_button_symbol_label(struct zr_context *ctx, enum zr_symbol_type symbol, + const char *label, zr_flags align, enum zr_button_behavior behavior) +{return zr_button_symbol_text(ctx, symbol, label, zr_strsiz(label), align, behavior);} + +int +zr_button_image_text(struct zr_context *ctx, struct zr_image img, + const char *text, zr_size len, zr_flags align, enum zr_button_behavior behavior) { struct zr_window *win; struct zr_panel *layout; const struct zr_input *in; - const struct zr_style *config; + const struct zr_style *style; struct zr_rect bounds; - zr_flags ws; - enum zr_widget_state state; - struct zr_button_text button; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return zr_false; + ZR_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout) + return 0; win = ctx->current; - config = &ctx->style; + style = &ctx->style; layout = win->layout; - state = zr_button(&button.base, &bounds, ctx, ZR_BUTTON_NORMAL); - if (!state) return zr_false; - in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - button.alignment = ZR_TEXT_CENTERED|ZR_TEXT_MIDDLE; - button.normal = config->colors[ZR_COLOR_TEXT]; - button.hover = config->colors[ZR_COLOR_TEXT_HOVERING]; - button.active = config->colors[ZR_COLOR_TEXT_ACTIVE]; - return zr_do_button_text_image(&ws, &win->buffer, bounds, img, text, align, - behavior, &button, &config->font, in); + state = zr_widget(&bounds, ctx); + if (!state) return 0; + in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; + return zr_do_button_text_image(&ctx->last_widget_state, &win->buffer, + bounds, img, text, len, align, behavior, &style->button, &style->font, in); } +int zr_button_image_label(struct zr_context *ctx, struct zr_image img, + const char *label, zr_flags align, enum zr_button_behavior behavior) +{return zr_button_image_text(ctx, img, label, zr_strsiz(label), align, behavior);} + +/*---------------------------------------------------------------- + * SELECTABLE + * --------------------------------------------------------------*/ int -zr_selectable(struct zr_context *ctx, const char *str, zr_flags align, int *value) +zr_selectable_text(struct zr_context *ctx, const char *str, zr_size len, + zr_flags align, int *value) { struct zr_window *win; struct zr_panel *layout; - const struct zr_style *config; const struct zr_input *in; - enum zr_widget_state state; + const struct zr_style *style; - int old_value; + enum zr_widget_layout_states state; struct zr_rect bounds; - struct zr_text text; - struct zr_color background; - struct zr_vec2 item_padding; ZR_ASSERT(ctx); ZR_ASSERT(value); @@ -10076,77 +10175,37 @@ zr_selectable(struct zr_context *ctx, const char *str, zr_flags align, int *valu win = ctx->current; layout = win->layout; - config = &ctx->style; + style = &ctx->style; state = zr_widget(&bounds, ctx); if (!state) return 0; in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - background = (!*value) ? config->colors[ZR_COLOR_WINDOW]: - config->colors[ZR_COLOR_SELECTABLE]; - - /* update selectable */ - old_value = *value; - if (in && zr_input_is_mouse_click_in_rect(&ctx->input, ZR_BUTTON_LEFT, bounds)) { - background = config->colors[ZR_COLOR_SELECTABLE_HOVER]; - if (zr_input_has_mouse_click_in_rect(&ctx->input, ZR_BUTTON_LEFT, bounds)) { - if (!zr_input_is_mouse_down(&ctx->input, ZR_BUTTON_LEFT)) - *value = !*value; - } - } - - /* draw selectable */ - text.padding.x = item_padding.x; - text.padding.y = item_padding.y; - text.background = background; - text.text = (!*value) ? config->colors[ZR_COLOR_TEXT] : - config->colors[ZR_COLOR_SELECTABLE_TEXT]; - - zr_draw_rect(&win->buffer, ZR_FILLED, bounds, 0, background); - zr_widget_text(&win->buffer, bounds, str, zr_strsiz(str), - &text, align|ZR_TEXT_MIDDLE, &config->font); - return *value != old_value; + return zr_do_selectable(&ctx->last_widget_state, &win->buffer, bounds, + str, len, align, value, &style->selectable, in, &style->font); } +int zr_select_text(struct zr_context *ctx, const char *str, zr_size len, + zr_flags align, int value) +{zr_selectable_text(ctx, str, len, align, &value);return value;} + +int zr_selectable_label(struct zr_context *ctx, const char *str, zr_flags align, int *value) +{return zr_selectable_text(ctx, str, zr_strsiz(str), align, value);} + +int zr_select_label(struct zr_context *ctx, const char *str, zr_flags align, int value) +{zr_selectable_text(ctx, str, zr_strsiz(str), align, &value);return value;} + +/*---------------------------------------------------------------- + * CHECKBOX + * --------------------------------------------------------------*/ int -zr_select(struct zr_context *ctx, const char *str, zr_flags align, int value) -{ - zr_selectable(ctx, str, align, &value); - return value; -} - -static enum zr_widget_state -zr_toggle_base(struct zr_toggle *toggle, struct zr_rect *bounds, - const struct zr_context *ctx) -{ - const struct zr_style *config; - struct zr_vec2 item_padding; - enum zr_widget_state state; - state = zr_widget(bounds, ctx); - if (!state) return state; - - config = &ctx->style; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - toggle->rounding = 0; - toggle->padding.x = item_padding.x; - toggle->padding.y = item_padding.y; - toggle->font = config->colors[ZR_COLOR_TEXT]; - toggle->font_background = config->colors[ZR_COLOR_WINDOW]; - return state; -} - -int -zr_check(struct zr_context *ctx, const char *text, int active) +zr_check_text(struct zr_context *ctx, const char *text, zr_size len, int active) { struct zr_window *win; struct zr_panel *layout; const struct zr_input *in; - const struct zr_style *config; + const struct zr_style *style; struct zr_rect bounds; - struct zr_toggle toggle; - zr_flags ws; - enum zr_widget_state state; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -10155,24 +10214,18 @@ zr_check(struct zr_context *ctx, const char *text, int active) return active; win = ctx->current; - config = &ctx->style; + style = &ctx->style; layout = win->layout; - state = zr_toggle_base(&toggle, &bounds, ctx); + state = zr_widget(&bounds, ctx); if (!state) return active; in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - - toggle.touch_pad = zr_get_property(ctx, ZR_PROPERTY_TOUCH_PADDING); - toggle.rounding = config->rounding[ZR_ROUNDING_CHECK]; - toggle.cursor = config->colors[ZR_COLOR_TOGGLE_CURSOR]; - toggle.normal = config->colors[ZR_COLOR_TOGGLE]; - toggle.hover = config->colors[ZR_COLOR_TOGGLE_HOVER]; - zr_do_toggle(&ws, &win->buffer, bounds, &active, text, ZR_TOGGLE_CHECK, - &toggle, in, &config->font); + zr_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active, + text, len, ZR_TOGGLE_CHECK, &style->checkbox, in, &style->font); return active; } int -zr_checkbox(struct zr_context *ctx, const char *text, int *active) +zr_checkbox_text(struct zr_context *ctx, const char *text, zr_size len, int *active) { int old_val; ZR_ASSERT(ctx); @@ -10180,22 +10233,29 @@ zr_checkbox(struct zr_context *ctx, const char *text, int *active) ZR_ASSERT(active); if (!ctx || !text || !active) return 0; old_val = *active; - *active = zr_check(ctx, text, *active); + *active = zr_check_text(ctx, text, len, *active); return old_val != *active; } +int zr_check_label(struct zr_context *ctx, const char *label, int active) +{return zr_check_text(ctx, label, zr_strsiz(label), active);} + +int zr_checkbox_label(struct zr_context *ctx, const char *label, int *active) +{return zr_checkbox_text(ctx, label, zr_strsiz(label), active);} + +/*---------------------------------------------------------------- + * OPTION + * --------------------------------------------------------------*/ int -zr_option(struct zr_context *ctx, const char *text, int is_active) +zr_option_text(struct zr_context *ctx, const char *text, zr_size len, int is_active) { struct zr_window *win; struct zr_panel *layout; const struct zr_input *in; - const struct zr_style *config; + const struct zr_style *style; struct zr_rect bounds; - struct zr_toggle toggle; - zr_flags ws; - enum zr_widget_state state; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -10204,31 +10264,40 @@ zr_option(struct zr_context *ctx, const char *text, int is_active) return is_active; win = ctx->current; - config = &ctx->style; + style = &ctx->style; layout = win->layout; - state = zr_toggle_base(&toggle, &bounds, ctx); - if (!state) return is_active; + state = zr_widget(&bounds, ctx); + if (!state) return state; in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - - toggle.touch_pad = zr_get_property(ctx, ZR_PROPERTY_TOUCH_PADDING); - toggle.cursor = config->colors[ZR_COLOR_TOGGLE_CURSOR]; - toggle.normal = config->colors[ZR_COLOR_TOGGLE]; - toggle.hover = config->colors[ZR_COLOR_TOGGLE_HOVER]; - zr_do_toggle(&ws, &win->buffer, bounds, &is_active, text, ZR_TOGGLE_OPTION, - &toggle, in, &config->font); + zr_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active, + text, len, ZR_TOGGLE_OPTION, &style->option, in, &style->font); return is_active; } -void -zr_radio(struct zr_context *ctx, const char *text, int *active) +int +zr_radio_text(struct zr_context *ctx, const char *text, zr_size len, int *active) { + int old_value; ZR_ASSERT(ctx); ZR_ASSERT(text); ZR_ASSERT(active); - if (!ctx || !text || !active) return; - *active = zr_option(ctx, text, *active); + if (!ctx || !text || !active) return 0; + old_value = *active; + *active = zr_option_text(ctx, text, len, old_value); + return old_value != *active; } +int +zr_option_label(struct zr_context *ctx, const char *label, int active) +{return zr_option_text(ctx, label, zr_strsiz(label), active);} + +int +zr_radio_label(struct zr_context *ctx, const char *label, int *active) +{return zr_radio_text(ctx, label, zr_strsiz(label), active);} + +/*---------------------------------------------------------------- + * SLIDER + * --------------------------------------------------------------*/ int zr_slider_float(struct zr_context *ctx, float min_value, float *value, float max_value, float value_step) @@ -10236,15 +10305,12 @@ zr_slider_float(struct zr_context *ctx, float min_value, float *value, float max struct zr_window *win; struct zr_panel *layout; const struct zr_input *in; - const struct zr_style *config; + const struct zr_style *style; int ret = 0; float old_value; struct zr_rect bounds; - struct zr_slider slider; - struct zr_vec2 item_padding; - enum zr_widget_state state; - zr_flags ws; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -10254,24 +10320,15 @@ zr_slider_float(struct zr_context *ctx, float min_value, float *value, float max return ret; win = ctx->current; - config = &ctx->style; + style = &ctx->style; layout = win->layout; state = zr_widget(&bounds, ctx); if (!state) return ret; in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; old_value = *value; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - slider.padding.x = item_padding.x; - slider.padding.y = item_padding.y; - slider.bg = config->colors[ZR_COLOR_SLIDER]; - slider.normal = config->colors[ZR_COLOR_SLIDER_CURSOR]; - slider.hover = config->colors[ZR_COLOR_SLIDER_CURSOR_HOVER]; - slider.active = config->colors[ZR_COLOR_SLIDER_CURSOR_ACTIVE]; - slider.border = config->colors[ZR_COLOR_BORDER]; - slider.rounding = config->rounding[ZR_ROUNDING_SLIDER]; - *value = zr_do_slider(&ws, &win->buffer, bounds, min_value, old_value, - max_value, value_step, &slider, in); + *value = zr_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value, + old_value, max_value, value_step, &style->slider, in, &style->font); return (old_value > *value || old_value < *value); } @@ -10299,20 +10356,19 @@ zr_slider_int(struct zr_context *ctx, int min, int *val, int max, int step) return ret; } +/*---------------------------------------------------------------- + * PROGRESSBAR + * --------------------------------------------------------------*/ int zr_progress(struct zr_context *ctx, zr_size *cur, zr_size max, int is_modifyable) { struct zr_window *win; struct zr_panel *layout; - const struct zr_style *config; + const struct zr_style *style; const struct zr_input *in; - int ret = 0; - zr_flags ws; struct zr_rect bounds; - struct zr_progress prog; - struct zr_vec2 item_padding; - enum zr_widget_state state; + enum zr_widget_layout_states state; zr_size old_value; ZR_ASSERT(ctx); @@ -10320,66 +10376,26 @@ zr_progress(struct zr_context *ctx, zr_size *cur, zr_size max, int is_modifyable ZR_ASSERT(ctx->current); ZR_ASSERT(ctx->current->layout); if (!ctx || !ctx->current || !ctx->current->layout || !cur) - return ret; + return 0; win = ctx->current; - config = &ctx->style; + style = &ctx->style; layout = win->layout; state = zr_widget(&bounds, ctx); - if (!state) return ret; + if (!state) return 0; in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); old_value = *cur; - prog.padding.x = item_padding.x; - prog.padding.y = item_padding.y; - prog.border = config->colors[ZR_COLOR_BORDER]; - prog.background = config->colors[ZR_COLOR_PROGRESS]; - prog.normal = config->colors[ZR_COLOR_PROGRESS_CURSOR]; - prog.hover = config->colors[ZR_COLOR_PROGRESS_CURSOR_HOVER]; - prog.active = config->colors[ZR_COLOR_PROGRESS_CURSOR_ACTIVE]; - *cur = zr_do_progress(&ws, &win->buffer, bounds, old_value, max, - is_modifyable, &prog, in); + *cur = zr_do_progress(&ctx->last_widget_state, &win->buffer, bounds, + *cur, max, is_modifyable, &style->progress, in); return (*cur != old_value); } -zr_size -zr_prog(struct zr_context *ctx, zr_size cur, zr_size max, int modifyable) -{ - zr_progress(ctx, &cur, max, modifyable); - return cur; -} - -static enum zr_widget_state -zr_edit_base(struct zr_rect *bounds, struct zr_edit *field, - struct zr_context *ctx) -{ - const struct zr_style *config; - struct zr_vec2 item_padding; - enum zr_widget_state state = zr_widget(bounds, ctx); - if (!state) return state; - - config = &ctx->style; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - field->border_size = 1; - field->scrollbar_width = config->properties[ZR_PROPERTY_SCROLLBAR_SIZE].x; - field->rounding = config->rounding[ZR_ROUNDING_INPUT]; - field->padding.x = item_padding.x; - field->padding.y = item_padding.y; - field->show_cursor = zr_true; - field->background = config->colors[ZR_COLOR_INPUT]; - field->border = config->colors[ZR_COLOR_BORDER]; - field->cursor = config->colors[ZR_COLOR_INPUT_CURSOR]; - field->text = config->colors[ZR_COLOR_INPUT_TEXT]; - field->scroll.rounding = config->rounding[ZR_ROUNDING_SCROLLBAR]; - field->scroll.background = config->colors[ZR_COLOR_SCROLLBAR]; - field->scroll.normal = config->colors[ZR_COLOR_SCROLLBAR_CURSOR]; - field->scroll.hover = config->colors[ZR_COLOR_SCROLLBAR_CURSOR_HOVER]; - field->scroll.active = config->colors[ZR_COLOR_SCROLLBAR_CURSOR_ACTIVE]; - field->scroll.border = config->colors[ZR_COLOR_BORDER]; - return state; -} +zr_size zr_prog(struct zr_context *ctx, zr_size cur, zr_size max, int modifyable) +{zr_progress(ctx, &cur, max, modifyable);return cur;} +/*---------------------------------------------------------------- + * EDIT + * --------------------------------------------------------------*/ zr_flags zr_edit_string(struct zr_context *ctx, zr_flags flags, char *memory, zr_size *len, zr_size max, zr_filter filter) @@ -10401,13 +10417,15 @@ zr_edit_buffer(struct zr_context *ctx, zr_flags flags, struct zr_buffer *buffer, zr_filter filter) { struct zr_window *win; + struct zr_style *style; struct zr_input *in; - enum zr_widget_state state; + enum zr_widget_layout_states state; struct zr_rect bounds; - struct zr_edit field; zr_flags ret_flags = 0; + int modifiable = 0; zr_flags old_flags; + int show_cursor = 0; zr_hash hash; int *active = 0; @@ -10430,14 +10448,15 @@ zr_edit_buffer(struct zr_context *ctx, zr_flags flags, return 0; win = ctx->current; - state = zr_edit_base(&bounds, &field, ctx); - if (!state) return 0; + style = &ctx->style; + state = zr_widget(&bounds, ctx); + if (!state) return state; in = (state == ZR_WIDGET_ROM || win->layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; if ((flags & ZR_EDIT_READ_ONLY)) { - field.modifiable = 0; - field.show_cursor = 0; + modifiable = 0; + show_cursor = 0; } else { - field.modifiable = 1; + modifiable = 1; } /* check if edit is currently hot item */ @@ -10456,20 +10475,23 @@ zr_edit_buffer(struct zr_context *ctx, zr_flags flags, old_flags = (*active) ? ZR_EDIT_ACTIVE: ZR_EDIT_INACTIVE; if (!flags || flags == ZR_EDIT_CURSOR) { + /* edit which only support appending and removing at end of line */ int old = *active; - in = (flags & ZR_EDIT_READ_ONLY) ? 0: in; + in = (flags & ZR_EDIT_READ_ONLY || !(modifiable)) ? 0: in; if (!flags) { /* simple edit field with only appending and removing at the end of the buffer */ - buffer->allocated = zr_widget_edit(&win->buffer, bounds, - (char*)buffer->memory.ptr, buffer->allocated, buffer->memory.size, - active, 0, &field, filter, in, &ctx->style.font); + buffer->allocated = zr_do_edit_string(&ctx->last_widget_state, + &win->buffer, bounds, (char*)buffer->memory.ptr, buffer->allocated, + buffer->memory.size, active, 0, show_cursor, &style->edit, + filter, in, &ctx->style.font); } else { /* simple edit field cursor based movement, inserting and removing */ zr_size glyphs = zr_utf_len((const char*)buffer->memory.ptr, buffer->allocated); *cursor = ZR_MIN(*cursor, glyphs); - buffer->allocated = zr_widget_edit(&win->buffer, bounds, - (char*)buffer->memory.ptr, buffer->allocated , buffer->memory.size, - active, cursor, &field, filter, in, &ctx->style.font); + buffer->allocated = zr_do_edit_string(&ctx->last_widget_state, + &win->buffer, bounds, (char*)buffer->memory.ptr, buffer->allocated, + buffer->memory.size, active, cursor, show_cursor, &style->edit, + filter, in, &ctx->style.font); } if (dummy_active) { @@ -10484,8 +10506,9 @@ zr_edit_buffer(struct zr_context *ctx, zr_flags flags, win->edit.active = 0; } } else { - /* editbox based editing either in single line (edit field) or multiline (edit box) */ + /* edit with cursor and text selection */ struct zr_edit_box box; + in = (flags & ZR_EDIT_READ_ONLY || !(modifiable)) ? 0: in; if (flags & ZR_EDIT_CLIPBOARD) zr_edit_box_init_buffer(&box, buffer, &ctx->clip, filter); else zr_edit_box_init_buffer(&box, buffer, 0, filter); @@ -10507,10 +10530,8 @@ zr_edit_buffer(struct zr_context *ctx, zr_flags flags, box.sel.end = box.cursor; } else box.sel = *sel; } - - if (flags & ZR_EDIT_MULTILINE) - zr_widget_edit_box(&win->buffer, bounds, &box, &field, in, &ctx->style.font); - else zr_widget_edit_field(&win->buffer, bounds, &box, &field, in, &ctx->style.font); + zr_do_edit_buffer(&ctx->last_widget_state, &win->buffer, bounds, &box, + &style->edit, show_cursor, in, &style->font); if (box.active) { /* update hot edit widget state */ @@ -10526,13 +10547,14 @@ zr_edit_buffer(struct zr_context *ctx, zr_flags flags, } } + /* enter deactivates edit and returns SIGCOMIT flag */ if (*active && (flags & ZR_EDIT_SIGCOMIT) && zr_input_is_key_pressed(in, ZR_KEY_ENTER)) { ret_flags |= ZR_EDIT_SIGCOMIT; *active = 0; } - /* compress edit widget state and state changes into flags */ + /* pack edit widget state and state changes into flags */ ret_flags |= (*active) ? ZR_EDIT_ACTIVE: ZR_EDIT_INACTIVE; if (old_flags == ZR_EDIT_INACTIVE && ret_flags & ZR_EDIT_ACTIVE) ret_flags |= ZR_EDIT_ACTIVATED; @@ -10548,20 +10570,17 @@ zr_property(struct zr_context *ctx, const char *name, float min, float val, struct zr_window *win; struct zr_panel *layout; const struct zr_input *in; - const struct zr_style *config; + const struct zr_style *style; struct zr_rect bounds; - enum zr_widget_state s; - zr_flags ws; - struct zr_property prop; - struct zr_vec2 item_padding; + enum zr_widget_layout_states s; int *state = 0; zr_hash hash = 0; char *buffer = 0; zr_size *len = 0; zr_size *cursor = 0; - enum zr_property_state old_state; + int old_state; char dummy_buffer[ZR_MAX_NUMBER_BUFFER]; int dummy_state = ZR_PROPERTY_DEFAULT; @@ -10576,7 +10595,7 @@ zr_property(struct zr_context *ctx, const char *name, float min, float val, win = ctx->current; layout = win->layout; - config = &ctx->style; + style = &ctx->style; s = zr_widget(&bounds, ctx); if (!s) return val; in = (s == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; @@ -10601,18 +10620,10 @@ zr_property(struct zr_context *ctx, const char *name, float min, float val, } /* execute property widget */ - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - prop.border_size = 1; - prop.rounding = config->rounding[ZR_ROUNDING_PROPERTY]; - prop.padding = item_padding; - prop.border = config->colors[ZR_COLOR_BORDER]; - prop.normal = config->colors[ZR_COLOR_PROPERTY]; - prop.hover = config->colors[ZR_COLOR_PROPERTY_HOVER]; - prop.active = config->colors[ZR_COLOR_PROPERTY_ACTIVE]; - prop.text = config->colors[ZR_COLOR_TEXT]; - old_state = (enum zr_property_state)*state; - val = zr_do_property(&ws, &win->buffer, bounds, name, min, val, max, step, - inc_per_pixel, buffer, len, state, cursor, &prop, filter, in, &config->font); + old_state = *state; + val = zr_do_property(&ctx->last_widget_state, &win->buffer, bounds, name, + min, val, max, step, inc_per_pixel, buffer, len, state, cursor, + &style->property, filter, in, &style->font); if (in && *state != ZR_PROPERTY_DEFAULT && !win->property.active) { /* current property is now hot */ @@ -10688,8 +10699,7 @@ zr_color_pick(struct zr_context * ctx, struct zr_color *color, const struct zr_input *in; zr_flags ws; - enum zr_widget_state state; - struct zr_vec2 item_padding; + enum zr_widget_layout_states state; struct zr_rect bounds; ZR_ASSERT(ctx); @@ -10705,9 +10715,8 @@ zr_color_pick(struct zr_context * ctx, struct zr_color *color, state = zr_widget(&bounds, ctx); if (!state) return 0; in = (state == ZR_WIDGET_ROM || layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); return zr_do_color_picker(&ws, &win->buffer, color, fmt, bounds, - item_padding, in, &config->font); + zr_vec2(0,0), in, &config->font); } struct zr_color @@ -10723,7 +10732,7 @@ zr_color_picker(struct zr_context *ctx, struct zr_color color, * CHART * * --------------------------------------------------------------*/ -void +int zr_chart_begin(struct zr_context *ctx, const enum zr_chart_type type, int count, float min_value, float max_value) { @@ -10732,18 +10741,18 @@ zr_chart_begin(struct zr_context *ctx, const enum zr_chart_type type, struct zr_chart *chart; const struct zr_style *config; + const struct zr_style_item *background; struct zr_rect bounds = {0, 0, 0, 0}; - struct zr_vec2 item_padding; - struct zr_color color; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); ZR_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) return; + if (!ctx || !ctx->current || !ctx->current->layout) return 0; if (!zr_widget(&bounds, ctx)) { chart = &ctx->current->layout->chart; + chart->style = 0; zr_zero(chart, sizeof(*chart)); - return; + return 0; } win = ctx->current; @@ -10751,28 +10760,33 @@ zr_chart_begin(struct zr_context *ctx, const enum zr_chart_type type, config = &ctx->style; chart = &win->layout->chart; - /* draw chart background */ - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - color = (type == ZR_CHART_LINES) ? - config->colors[ZR_COLOR_PLOT]: config->colors[ZR_COLOR_HISTO]; - zr_draw_rect(out, ZR_FILLED, bounds, config->rounding[ZR_ROUNDING_CHART], color); - /* setup basic generic chart */ zr_zero(chart, sizeof(*chart)); chart->type = type; + chart->style = (type == ZR_CHART_LINES) ? &config->line_chart: &config->column_chart; chart->index = 0; chart->count = count; chart->min = ZR_MIN(min_value, max_value); chart->max = ZR_MAX(min_value, max_value); chart->range = chart->max - chart->min; - chart->x = bounds.x + item_padding.x; - chart->y = bounds.y + item_padding.y; - chart->w = bounds.w - 2 * item_padding.x; - chart->h = bounds.h - 2 * item_padding.y; - chart->w = ZR_MAX(chart->w, 2 * item_padding.x); - chart->h = ZR_MAX(chart->h, 2 * item_padding.y); + chart->x = bounds.x + chart->style->padding.x; + chart->y = bounds.y + chart->style->padding.y; + chart->w = bounds.w - 2 * chart->style->padding.x; + chart->h = bounds.h - 2 * chart->style->padding.y; + chart->w = ZR_MAX(chart->w, 2 * chart->style->padding.x); + chart->h = ZR_MAX(chart->h, 2 * chart->style->padding.y); chart->last.x = 0; chart->last.y = 0; - return; + + /* draw chart background */ + background = &chart->style->background; + if (background->type == ZR_STYLE_ITEM_IMAGE) { + zr_draw_image(&win->buffer, bounds, &background->data.image); + } else { + zr_fill_rect(&win->buffer, bounds, chart->style->rounding, chart->style->border_color); + zr_fill_rect(&win->buffer, zr_shrink_rect(bounds, chart->style->border), + chart->style->rounding, chart->style->border_color); + } + return 1; } static zr_flags @@ -10781,7 +10795,6 @@ zr_chart_push_line(struct zr_context *ctx, struct zr_window *win, { struct zr_panel *layout = win->layout; const struct zr_input *i = &ctx->input; - const struct zr_style *config = &ctx->style; struct zr_command_buffer *out = &win->buffer; zr_flags ret = 0; @@ -10797,7 +10810,7 @@ zr_chart_push_line(struct zr_context *ctx, struct zr_window *win, ratio = (value - g->min) / range; if (g->index == 0) { - /* special case for the first data point since it does not have a connection */ + /* first data point does not have a connection */ g->last.x = g->x; g->last.y = (g->y + g->h) - ratio * (float)g->h; @@ -10806,15 +10819,15 @@ zr_chart_push_line(struct zr_context *ctx, struct zr_window *win, bounds.w = 4; bounds.h = 4; - color = config->colors[ZR_COLOR_PLOT_LINES]; + color = g->style->color; if (!(layout->flags & ZR_WINDOW_ROM) && ZR_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->last.x-3, g->last.y-3, 6, 6)){ ret = zr_input_is_mouse_hovering_rect(i, bounds) ? ZR_CHART_HOVERING : 0; ret |= (i->mouse.buttons[ZR_BUTTON_LEFT].down && i->mouse.buttons[ZR_BUTTON_LEFT].clicked) ? ZR_CHART_CLICKED: 0; - color = config->colors[ZR_COLOR_PLOT_HIGHLIGHT]; + color = g->style->selected_color; } - zr_draw_rect(out, ZR_FILLED, bounds, 0, color); + zr_fill_rect(out, bounds, 0, color); g->index++; return ret; } @@ -10822,8 +10835,7 @@ zr_chart_push_line(struct zr_context *ctx, struct zr_window *win, /* draw a line between the last data point and the new one */ cur.x = g->x + (float)(step * (float)g->index); cur.y = (g->y + g->h) - (ratio * (float)g->h); - zr_draw_line(out, g->last.x, g->last.y, cur.x, cur.y, - config->colors[ZR_COLOR_PLOT_LINES]); + zr_stroke_line(out, g->last.x, g->last.y, cur.x, cur.y, 1.0f, g->style->color); bounds.x = cur.x - 3; bounds.y = cur.y - 3; @@ -10831,16 +10843,16 @@ zr_chart_push_line(struct zr_context *ctx, struct zr_window *win, bounds.h = 6; /* user selection of current data point */ - color = config->colors[ZR_COLOR_PLOT_LINES]; + color = g->style->color; if (!(layout->flags & ZR_WINDOW_ROM)) { if (zr_input_is_mouse_hovering_rect(i, bounds)) { ret = ZR_CHART_HOVERING; ret |= (!i->mouse.buttons[ZR_BUTTON_LEFT].down && i->mouse.buttons[ZR_BUTTON_LEFT].clicked) ? ZR_CHART_CLICKED: 0; - color = config->colors[ZR_COLOR_PLOT_HIGHLIGHT]; + color = g->style->selected_color; } } - zr_draw_rect(out, ZR_FILLED, zr_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color); + zr_fill_rect(out, zr_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color); /* save current data point position */ g->last.x = cur.x; @@ -10854,7 +10866,6 @@ zr_chart_push_column(const struct zr_context *ctx, struct zr_window *win, struct zr_chart *chart, float value) { struct zr_command_buffer *out = &win->buffer; - const struct zr_style *config = &ctx->style; const struct zr_input *in = &ctx->input; struct zr_panel *layout = win->layout; @@ -10871,7 +10882,7 @@ zr_chart_push_column(const struct zr_context *ctx, struct zr_window *win, } /* calculate bounds of the current bar chart entry */ - color = config->colors[ZR_COLOR_HISTO_BARS]; + color = chart->style->color; item.h = chart->h * ZR_ABS((value/chart->range)); if (value >= 0) { ratio = (value + ZR_ABS(chart->min)) / ZR_ABS(chart->range); @@ -10889,9 +10900,9 @@ zr_chart_push_column(const struct zr_context *ctx, struct zr_window *win, ret = ZR_CHART_HOVERING; ret |= (!in->mouse.buttons[ZR_BUTTON_LEFT].down && in->mouse.buttons[ZR_BUTTON_LEFT].clicked) ? ZR_CHART_CLICKED: 0; - color = config->colors[ZR_COLOR_HISTO_HIGHLIGHT]; + color = chart->style->selected_color; } - zr_draw_rect(out, ZR_FILLED, item, 0, color); + zr_fill_rect(out, item, 0, color); chart->index++; return ret; } @@ -10904,7 +10915,7 @@ zr_chart_push(struct zr_context *ctx, float value) ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); - if (!ctx || !ctx->current) + if (!ctx || !ctx->current || !ctx->current->layout->chart.style) return zr_false; win = ctx->current; @@ -11049,11 +11060,11 @@ zr_group_end(struct zr_context *ctx) g->bounds.x, g->clip.y - g->header_h, g->bounds.x + g->bounds.w+1, g->bounds.y + g->bounds.h + 1); - zr_draw_scissor(&pan.buffer, clip); + zr_push_scissor(&pan.buffer, clip); zr_end(ctx); win->buffer = pan.buffer; - zr_draw_scissor(&win->buffer, parent->clip); + zr_push_scissor(&win->buffer, parent->clip); ctx->current = win; win->layout = parent; win->bounds = parent->bounds; @@ -11122,7 +11133,7 @@ zr_popup_begin(struct zr_context *ctx, struct zr_panel *layout, popup->buffer = win->buffer; zr_start_popup(ctx, win); allocated = ctx->memory.allocated; - zr_draw_scissor(&popup->buffer, zr_null_rect); + zr_push_scissor(&popup->buffer, zr_null_rect); if (zr_panel_begin(ctx, title)) { /* popup is running therefore invalidate parent window */ @@ -11192,7 +11203,7 @@ zr_nonblock_begin(struct zr_panel *layout, struct zr_context *ctx, zr_start_popup(ctx, win); popup->buffer = win->buffer; - zr_draw_scissor(&popup->buffer, zr_null_rect); + zr_push_scissor(&popup->buffer, zr_null_rect); ctx->current = popup; zr_panel_begin(ctx, 0); @@ -11234,13 +11245,13 @@ zr_popup_end(struct zr_context *ctx) win->layout->flags |= ZR_WINDOW_REMOVE_ROM; win->popup.active = 0; } - zr_draw_scissor(&popup->buffer, zr_null_rect); + zr_push_scissor(&popup->buffer, zr_null_rect); zr_end(ctx); win->buffer = popup->buffer; zr_finish_popup(ctx, win); ctx->current = win; - zr_draw_scissor(&win->buffer, win->layout->clip); + zr_push_scissor(&win->buffer, win->layout->clip); } /* ------------------------------------------------------------- * @@ -11292,8 +11303,7 @@ zr_tooltip_end(struct zr_context *ctx) void zr_tooltip(struct zr_context *ctx, const char *text) { - const struct zr_style *config; - struct zr_vec2 item_padding; + const struct zr_style *style; struct zr_vec2 padding; struct zr_panel layout; @@ -11309,16 +11319,15 @@ zr_tooltip(struct zr_context *ctx, const char *text) return; /* fetch configuration data */ - config = &ctx->style; - padding = config->properties[ZR_PROPERTY_PADDING]; - item_padding = config->properties[ZR_PROPERTY_ITEM_PADDING]; + style = &ctx->style; + padding = style->window.padding; /* calculate size of the text and tooltip */ text_len = zr_strsiz(text); - text_width = config->font.width(config->font.userdata, - config->font.height, text, text_len); - text_width += (zr_size)(2 * padding.x + 2 * item_padding.x); - text_height = (zr_size)(config->font.height + 2 * item_padding.y); + text_width = style->font.width(style->font.userdata, + style->font.height, text, text_len); + text_width += (zr_size)(4 * padding.x); + text_height = (zr_size)(style->font.height + 2 * padding.y); /* execute tooltip and fill with text */ if (zr_tooltip_begin(ctx, &layout, (float)text_width)) { @@ -11328,13 +11337,11 @@ zr_tooltip(struct zr_context *ctx, const char *text) } } -/* - * ------------------------------------------------------------- +/* ------------------------------------------------------------- * * CONTEXTUAL * - * -------------------------------------------------------------- - */ + * -------------------------------------------------------------- */ int zr_contextual_begin(struct zr_context *ctx, struct zr_panel *layout, zr_flags flags, struct zr_vec2 size, struct zr_rect trigger_bounds) @@ -11390,18 +11397,17 @@ zr_contextual_begin(struct zr_context *ctx, struct zr_panel *layout, return ret; } -static int -zr_contextual_button(struct zr_context *ctx, const char *text, - zr_flags align, enum zr_button_behavior behavior) +int +zr_contextual_item_text(struct zr_context *ctx, const char *text, zr_size len, + zr_flags alignment) { struct zr_window *win; + struct zr_panel *layout; const struct zr_input *in; - const struct zr_style *config; + const struct zr_style *style; struct zr_rect bounds; - zr_flags ws; - enum zr_widget_state state; - struct zr_button_text button; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -11410,34 +11416,33 @@ zr_contextual_button(struct zr_context *ctx, const char *text, return 0; win = ctx->current; - config = &ctx->style; - state = zr_button(&button.base, &bounds, ctx, ZR_BUTTON_FITTING); + style = &ctx->style; + layout = win->layout; + state = zr_widget_fitting(&bounds, ctx, style->contextual_button.padding); if (!state) return zr_false; in = (state == ZR_WIDGET_ROM || win->layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - - button.base.border_width = 0; - button.base.normal = config->colors[ZR_COLOR_WINDOW]; - button.base.border = config->colors[ZR_COLOR_WINDOW]; - button.normal = config->colors[ZR_COLOR_TEXT]; - button.hover = config->colors[ZR_COLOR_TEXT_HOVERING]; - button.active = config->colors[ZR_COLOR_TEXT_ACTIVE]; - button.alignment = align|ZR_TEXT_MIDDLE; - return zr_do_button_text(&ws, &win->buffer, bounds, text, behavior, - &button, in, &config->font); + if (zr_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, + text, len, alignment, ZR_BUTTON_DEFAULT, &style->contextual_button, in, &style->font)) { + zr_contextual_close(ctx); + return zr_true; + } + return zr_false; } -static int -zr_contextual_button_symbol(struct zr_context *ctx, enum zr_symbol_type symbol, - const char *text, zr_flags align, enum zr_button_behavior behavior) +int zr_contextual_item_label(struct zr_context *ctx, const char *label, zr_flags align) +{return zr_contextual_item_text(ctx, label, zr_strsiz(label), align);} + +int +zr_contextual_item_image_text(struct zr_context *ctx, struct zr_image img, + const char *text, zr_size len, zr_flags align) { struct zr_window *win; - const struct zr_style *config; + struct zr_panel *layout; const struct zr_input *in; + const struct zr_style *style; struct zr_rect bounds; - struct zr_button_text button; - zr_flags ws; - enum zr_widget_state state; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -11446,34 +11451,34 @@ zr_contextual_button_symbol(struct zr_context *ctx, enum zr_symbol_type symbol, return 0; win = ctx->current; - config = &ctx->style; - state = zr_button(&button.base, &bounds, ctx, ZR_BUTTON_FITTING); + style = &ctx->style; + layout = win->layout; + state = zr_widget_fitting(&bounds, ctx, style->contextual_button.padding); if (!state) return zr_false; in = (state == ZR_WIDGET_ROM || win->layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - - button.alignment = ZR_TEXT_CENTERED|ZR_TEXT_MIDDLE; - button.base.border_width = 0; - button.base.normal = config->colors[ZR_COLOR_WINDOW]; - button.base.border = config->colors[ZR_COLOR_WINDOW]; - button.normal = config->colors[ZR_COLOR_TEXT]; - button.hover = config->colors[ZR_COLOR_TEXT_HOVERING]; - button.active = config->colors[ZR_COLOR_TEXT_ACTIVE]; - return zr_do_button_text_symbol(&ws, &win->buffer, bounds, symbol, text, align, - behavior, &button, &config->font, in); + if (zr_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds, + img, text, len, align, ZR_BUTTON_DEFAULT, &style->contextual_button, &style->font, in)){ + zr_contextual_close(ctx); + return zr_true; + } + return zr_false; } -static int -zr_contextual_button_icon(struct zr_context *ctx, struct zr_image img, - const char *text, zr_flags align, enum zr_button_behavior behavior) +int zr_contextual_item_image_label(struct zr_context *ctx, struct zr_image img, + const char *label, zr_flags align) +{return zr_contextual_item_image_text(ctx, img, label, zr_strsiz(label), align);} + +int +zr_contextual_item_symbol_text(struct zr_context *ctx, enum zr_symbol_type symbol, + const char *text, zr_size len, zr_flags align) { struct zr_window *win; + struct zr_panel *layout; const struct zr_input *in; - const struct zr_style *config; + const struct zr_style *style; struct zr_rect bounds; - struct zr_button_text button; - zr_flags ws; - enum zr_widget_state state; + enum zr_widget_layout_states state; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -11482,71 +11487,22 @@ zr_contextual_button_icon(struct zr_context *ctx, struct zr_image img, return 0; win = ctx->current; - config = &ctx->style; - state = zr_button(&button.base, &bounds, ctx, ZR_BUTTON_FITTING); + style = &ctx->style; + layout = win->layout; + state = zr_widget_fitting(&bounds, ctx, style->contextual_button.padding); if (!state) return zr_false; in = (state == ZR_WIDGET_ROM || win->layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; - - button.alignment = ZR_TEXT_CENTERED|ZR_TEXT_MIDDLE; - button.base.border_width = 0; - button.base.normal = config->colors[ZR_COLOR_WINDOW]; - button.base.border = config->colors[ZR_COLOR_WINDOW]; - button.normal = config->colors[ZR_COLOR_TEXT]; - button.hover = config->colors[ZR_COLOR_TEXT_HOVERING]; - button.active = config->colors[ZR_COLOR_TEXT_ACTIVE]; - return zr_do_button_text_image(&ws, &win->buffer, bounds, img, text, align, - behavior, &button, &config->font, in); -} - -int -zr_contextual_item(struct zr_context *ctx, const char *title, zr_flags align) -{ - ZR_ASSERT(ctx); - ZR_ASSERT(ctx->current); - ZR_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - if (zr_contextual_button(ctx, title, align, ZR_BUTTON_DEFAULT)) { + if (zr_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, + symbol, text, len, align, ZR_BUTTON_DEFAULT, &style->contextual_button, &style->font, in)) { zr_contextual_close(ctx); return zr_true; } return zr_false; } -int -zr_contextual_item_icon(struct zr_context *ctx, struct zr_image img, - const char *title, zr_flags align) -{ - ZR_ASSERT(ctx); - ZR_ASSERT(ctx->current); - ZR_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - if (zr_contextual_button_icon(ctx, img, title, align, ZR_BUTTON_DEFAULT)){ - zr_contextual_close(ctx); - return zr_true; - } - return zr_false; -} - -int -zr_contextual_item_symbol(struct zr_context *ctx, enum zr_symbol_type symbol, - const char *title, zr_flags align) -{ - ZR_ASSERT(ctx); - ZR_ASSERT(ctx->current); - ZR_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - if (zr_contextual_button_symbol(ctx, symbol, title, align, ZR_BUTTON_DEFAULT)){ - zr_contextual_close(ctx); - return zr_true; - } - return zr_false; -} +int zr_contextual_item_symbol_label(struct zr_context *ctx, enum zr_symbol_type symbol, + const char *text, zr_flags align) +{return zr_contextual_item_symbol_text(ctx, symbol, text, zr_strsiz(text), align);} void zr_contextual_close(struct zr_context *ctx) @@ -11617,17 +11573,19 @@ zr_combo_begin(struct zr_panel *layout, struct zr_context *ctx, struct zr_window int zr_combo_begin_text(struct zr_context *ctx, struct zr_panel *layout, - const char *selected, int height) + const char *selected, zr_size len, int height) { const struct zr_input *in; struct zr_window *win; + struct zr_style *style; - zr_flags state; - enum zr_widget_state s; - struct zr_vec2 item_padding; + enum zr_widget_layout_states s; int is_active = zr_false; struct zr_rect header; + const struct zr_style_item *background; + struct zr_text text; + ZR_ASSERT(ctx); ZR_ASSERT(selected); ZR_ASSERT(ctx->current); @@ -11636,66 +11594,91 @@ zr_combo_begin_text(struct zr_context *ctx, struct zr_panel *layout, return 0; win = ctx->current; + style = &ctx->style; s = zr_widget(&header, ctx); if (s == ZR_WIDGET_INVALID) return 0; in = (win->layout->flags & ZR_WINDOW_ROM || s == ZR_WIDGET_ROM)? 0: &ctx->input; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - if (zr_button_behavior(&state, header, in, ZR_BUTTON_DEFAULT)) + if (zr_button_behavior(&ctx->last_widget_state, header, in, ZR_BUTTON_DEFAULT)) is_active = zr_true; /* draw combo box header background and border */ - zr_draw_rect(&win->buffer, ZR_FILLED, header, 0, ctx->style.colors[ZR_COLOR_BORDER]); - zr_draw_rect(&win->buffer, ZR_FILLED, zr_shrink_rect(header, 1), 0, - ctx->style.colors[ZR_COLOR_COMBO]); - + if (ctx->last_widget_state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->combo.active; + text.text = style->combo.label_active; + } else if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) { + background = &style->combo.hover; + text.text = style->combo.label_hover; + } else { + background = &style->combo.normal; + text.text = style->combo.label_normal; + } + if (background->type == ZR_STYLE_ITEM_IMAGE) { + text.background = zr_rgba(0,0,0,0); + zr_draw_image(&win->buffer, header, &background->data.image); + } else { + text.background = background->data.color; + zr_fill_rect(&win->buffer, header, style->combo.rounding, style->combo.border_color); + zr_fill_rect(&win->buffer, zr_shrink_rect(header, 1), style->combo.rounding, + background->data.color); + } { /* print currently selected text item */ struct zr_rect label; - struct zr_text text; - struct zr_symbol sym; - struct zr_rect bounds = {0,0,0,0}; - zr_size text_len = zr_strsiz(selected); + struct zr_rect button; + struct zr_rect content; + + enum zr_symbol_type sym; + if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) + sym = style->combo.sym_hover; + else if (is_active) + sym = style->combo.sym_active; + else sym = style->combo.sym_normal; + + /* calculate button */ + button.w = header.h - 2 * style->combo.button_padding.y; + button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; + button.y = header.y + style->combo.button_padding.y; + button.h = button.w; + + content.x = button.x + style->combo.button.padding.x; + content.y = button.y + style->combo.button.padding.y; + content.w = button.w - 2 * style->combo.button.padding.x; + content.h = button.h - 2 * style->combo.button.padding.y; /* draw selected label */ text.padding = zr_vec2(0,0); - text.background = ctx->style.colors[ZR_COLOR_COMBO]; - text.text = ctx->style.colors[ZR_COLOR_TEXT]; + label.x = header.x + style->combo.content_padding.x; + label.y = header.y + style->combo.content_padding.y; + label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;; + label.h = header.h - 2 * style->combo.content_padding.y; + zr_widget_text(&win->buffer, label, selected, len, &text, + ZR_TEXT_LEFT, &ctx->style.font); - label.x = header.x + item_padding.x; - label.y = header.y + item_padding.y; - label.w = header.w - (header.h + 2 * item_padding.x); - label.h = header.h - 2 * item_padding.y; - zr_widget_text(&win->buffer, label, selected, text_len, &text, - ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, &ctx->style.font); - - /* draw open/close symbol */ - bounds.y = label.y + label.h/2 - ctx->style.font.height/2; - bounds.w = bounds.h = ctx->style.font.height; - bounds.x = (header.x + header.w) - (bounds.w + 2 * item_padding.x); - - sym.type = ZR_SYMBOL_TRIANGLE_DOWN; - sym.background = ctx->style.colors[ZR_COLOR_COMBO]; - sym.foreground = ctx->style.colors[ZR_COLOR_TEXT]; - sym.border_width = 1.0f; - zr_draw_symbol(&win->buffer, &sym, bounds, &ctx->style.font); + /* draw open/close button */ + zr_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, + &ctx->style.combo.button, sym, &style->font); } return zr_combo_begin(layout, ctx, win, height, is_active, header); } +int zr_combo_begin_label(struct zr_context *ctx, struct zr_panel *layout, + const char *selected, int max_height) +{return zr_combo_begin_text(ctx, layout, selected, zr_strsiz(selected), max_height);} + int zr_combo_begin_color(struct zr_context *ctx, struct zr_panel *layout, struct zr_color color, int height) { struct zr_window *win; + struct zr_style *style; const struct zr_input *in; - zr_flags state; - enum zr_widget_state s; - struct zr_vec2 item_padding; struct zr_rect header; int is_active = zr_false; + enum zr_widget_layout_states s; + const struct zr_style_item *background; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -11704,60 +11687,267 @@ zr_combo_begin_color(struct zr_context *ctx, struct zr_panel *layout, return 0; win = ctx->current; + style = &ctx->style; s = zr_widget(&header, ctx); if (s == ZR_WIDGET_INVALID) return 0; in = (win->layout->flags & ZR_WINDOW_ROM || s == ZR_WIDGET_ROM)? 0: &ctx->input; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - if (zr_button_behavior(&state, header, in, ZR_BUTTON_DEFAULT)) - is_active = !is_active; + if (zr_button_behavior(&ctx->last_widget_state, header, in, ZR_BUTTON_DEFAULT)) + is_active = zr_true; /* draw combo box header background and border */ - zr_draw_rect(&win->buffer, ZR_FILLED, header, 0, ctx->style.colors[ZR_COLOR_BORDER]); - zr_draw_rect(&win->buffer, ZR_FILLED, zr_shrink_rect(header, 1), 0, - ctx->style.colors[ZR_COLOR_COMBO]); + if (ctx->last_widget_state & ZR_WIDGET_STATE_ACTIVE) + background = &style->combo.active; + else if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) + background = &style->combo.hover; + else background = &style->combo.normal; + if (background->type == ZR_STYLE_ITEM_IMAGE) { + zr_draw_image(&win->buffer, header, &background->data.image); + } else { + zr_fill_rect(&win->buffer, header, 0, style->combo.border_color); + zr_fill_rect(&win->buffer, zr_shrink_rect(header, 1), 0, + background->data.color); + } { - /* print currently selected string */ struct zr_rect content; - struct zr_symbol sym; - struct zr_rect bounds = {0,0,0,0}; + struct zr_rect button; + struct zr_rect bounds; + + enum zr_symbol_type sym; + if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) + sym = style->combo.sym_hover; + else if (is_active) + sym = style->combo.sym_active; + else sym = style->combo.sym_normal; + + /* calculate button */ + button.w = header.h - 2 * style->combo.button_padding.y; + button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; + button.y = header.y + style->combo.button_padding.y; + button.h = button.w; + + content.x = button.x + style->combo.button.padding.x; + content.y = button.y + style->combo.button.padding.y; + content.w = button.w - 2 * style->combo.button.padding.x; + content.h = button.h - 2 * style->combo.button.padding.y; /* draw color */ - content.h = header.h - 4 * item_padding.y; - content.y = header.y + 2 * item_padding.y; - content.x = header.x + 2 * item_padding.x; - content.w = header.w - (header.h + 4 * item_padding.x); - zr_draw_rect(&win->buffer, ZR_FILLED, content, 0, color); + bounds.h = header.h - 4 * style->combo.content_padding.y; + bounds.y = header.y + 2 * style->combo.content_padding.y; + bounds.x = header.x + 2 * style->combo.content_padding.x; + bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x; + zr_fill_rect(&win->buffer, bounds, 0, color); - /* draw open/close symbol */ - bounds.y = (header.y + item_padding.y) + (header.h-2.0f*item_padding.y)/2.0f - -ctx->style.font.height/2; - bounds.w = bounds.h = ctx->style.font.height; - bounds.x = (header.x + header.w) - (bounds.w + 2 * item_padding.x); - - sym.type = ZR_SYMBOL_TRIANGLE_DOWN; - sym.background = ctx->style.colors[ZR_COLOR_COMBO]; - sym.foreground = ctx->style.colors[ZR_COLOR_TEXT]; - sym.border_width = 1.0f; - zr_draw_symbol(&win->buffer, &sym, bounds, &ctx->style.font); + /* draw open/close button */ + zr_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, + &ctx->style.combo.button, sym, &style->font); } return zr_combo_begin(layout, ctx, win, height, is_active, header); } +int +zr_combo_begin_symbol(struct zr_context *ctx, struct zr_panel *layout, + enum zr_symbol_type symbol, int height) +{ + struct zr_window *win; + struct zr_style *style; + const struct zr_input *in; + + struct zr_rect header; + int is_active = zr_false; + enum zr_widget_layout_states s; + const struct zr_style_item *background; + struct zr_color sym_background; + struct zr_color symbol_color; + + ZR_ASSERT(ctx); + ZR_ASSERT(ctx->current); + ZR_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout) + return 0; + + win = ctx->current; + style = &ctx->style; + s = zr_widget(&header, ctx); + if (s == ZR_WIDGET_INVALID) + return 0; + + in = (win->layout->flags & ZR_WINDOW_ROM || s == ZR_WIDGET_ROM)? 0: &ctx->input; + if (zr_button_behavior(&ctx->last_widget_state, header, in, ZR_BUTTON_DEFAULT)) + is_active = zr_true; + + /* draw combo box header background and border */ + if (ctx->last_widget_state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->combo.active; + symbol_color = style->combo.symbol_active; + } else if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) { + background = &style->combo.hover; + symbol_color = style->combo.symbol_hover; + } else { + background = &style->combo.normal; + symbol_color = style->combo.symbol_hover; + } + + if (background->type == ZR_STYLE_ITEM_IMAGE) { + sym_background = zr_rgba(0,0,0,0); + zr_draw_image(&win->buffer, header, &background->data.image); + } else { + sym_background = background->data.color; + zr_fill_rect(&win->buffer, header, 0, style->combo.border_color); + zr_fill_rect(&win->buffer, zr_shrink_rect(header, 1), 0, + background->data.color); + } + { + struct zr_rect bounds = {0,0,0,0}; + struct zr_rect content; + struct zr_rect button; + + enum zr_symbol_type sym; + if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) + sym = style->combo.sym_hover; + else if (is_active) + sym = style->combo.sym_active; + else sym = style->combo.sym_normal; + + /* calculate button */ + button.w = header.h - 2 * style->combo.button_padding.y; + button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; + button.y = header.y + style->combo.button_padding.y; + button.h = button.w; + + content.x = button.x + style->combo.button.padding.x; + content.y = button.y + style->combo.button.padding.y; + content.w = button.w - 2 * style->combo.button.padding.x; + content.h = button.h - 2 * style->combo.button.padding.y; + + /* draw symbol */ + bounds.h = header.h - 2 * style->combo.content_padding.y; + bounds.y = header.y + style->combo.content_padding.y; + bounds.x = header.x + style->combo.content_padding.x; + bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; + zr_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color, + 1.0f, &style->font); + + /* draw open/close button */ + zr_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, + &ctx->style.combo.button, sym, &style->font); + } + return zr_combo_begin(layout, ctx, win, height, is_active, header); +} + +int +zr_combo_begin_symbol_text(struct zr_context *ctx, struct zr_panel *layout, + const char *selected, zr_size len, enum zr_symbol_type symbol, int height) +{ + struct zr_window *win; + struct zr_style *style; + struct zr_input *in; + + struct zr_rect header; + int is_active = zr_false; + enum zr_widget_layout_states s; + const struct zr_style_item *background; + struct zr_color symbol_color; + struct zr_text text; + + ZR_ASSERT(ctx); + ZR_ASSERT(ctx->current); + ZR_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout) + return 0; + + win = ctx->current; + style = &ctx->style; + s = zr_widget(&header, ctx); + if (!s) return 0; + + in = (win->layout->flags & ZR_WINDOW_ROM || s == ZR_WIDGET_ROM)? 0: &ctx->input; + if (zr_button_behavior(&ctx->last_widget_state, header, in, ZR_BUTTON_DEFAULT)) + is_active = zr_true; + + /* draw combo box header background and border */ + if (ctx->last_widget_state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->combo.active; + symbol_color = style->combo.symbol_active; + text.text = style->combo.label_active; + } else if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) { + background = &style->combo.hover; + symbol_color = style->combo.symbol_hover; + text.text = style->combo.label_hover; + } else { + background = &style->combo.normal; + symbol_color = style->combo.symbol_normal; + text.text = style->combo.label_normal; + } + if (background->type == ZR_STYLE_ITEM_IMAGE) { + text.background = zr_rgba(0,0,0,0); + zr_draw_image(&win->buffer, header, &background->data.image); + } else { + text.background = background->data.color; + zr_fill_rect(&win->buffer, header, 0, style->combo.border_color); + zr_fill_rect(&win->buffer, zr_shrink_rect(header, 1), 0, + background->data.color); + } + { + struct zr_rect content; + struct zr_rect button; + struct zr_rect label; + struct zr_rect image; + + enum zr_symbol_type sym; + if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) + sym = style->combo.sym_hover; + else if (is_active) + sym = style->combo.sym_active; + else sym = style->combo.sym_normal; + + /* calculate button */ + button.w = header.h - 2 * style->combo.button_padding.y; + button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; + button.y = header.y + style->combo.button_padding.y; + button.h = button.w; + + content.x = button.x + style->combo.button.padding.x; + content.y = button.y + style->combo.button.padding.y; + content.w = button.w - 2 * style->combo.button.padding.x; + content.h = button.h - 2 * style->combo.button.padding.y; + zr_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, + &ctx->style.combo.button, sym, &style->font); + + /* draw symbol */ + image.x = header.x + style->combo.content_padding.x; + image.y = header.y + style->combo.content_padding.y; + image.h = header.h - 2 * style->combo.content_padding.y; + image.w = image.h; + zr_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color, + 1.0f, &style->font); + + /* draw label */ + text.padding = zr_vec2(0,0); + label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; + label.y = header.y + style->combo.content_padding.y; + label.w = (button.x - style->combo.content_padding.x) - label.x; + label.h = header.h - 2 * style->combo.content_padding.y; + zr_widget_text(&win->buffer, label, selected, len, &text, ZR_TEXT_LEFT, &style->font); + } + return zr_combo_begin(layout, ctx, win, height, is_active, header); +} + + int zr_combo_begin_image(struct zr_context *ctx, struct zr_panel *layout, struct zr_image img, int height) { struct zr_window *win; + struct zr_style *style; const struct zr_input *in; - enum zr_widget_state s; - zr_flags state; - struct zr_vec2 item_padding; struct zr_rect header; int is_active = zr_false; + enum zr_widget_layout_states s; + const struct zr_style_item *background; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -11766,56 +11956,79 @@ zr_combo_begin_image(struct zr_context *ctx, struct zr_panel *layout, return 0; win = ctx->current; + style = &ctx->style; s = zr_widget(&header, ctx); if (s == ZR_WIDGET_INVALID) return 0; in = (win->layout->flags & ZR_WINDOW_ROM || s == ZR_WIDGET_ROM)? 0: &ctx->input; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - if (zr_button_behavior(&state, header, in, ZR_BUTTON_DEFAULT)) - is_active = !is_active; + if (zr_button_behavior(&ctx->last_widget_state, header, in, ZR_BUTTON_DEFAULT)) + is_active = zr_true; /* draw combo box header background and border */ - zr_draw_rect(&win->buffer, ZR_FILLED, header, 0, ctx->style.colors[ZR_COLOR_BORDER]); - zr_draw_rect(&win->buffer, ZR_FILLED, zr_shrink_rect(header, 1), 0, - ctx->style.colors[ZR_COLOR_COMBO]); + if (ctx->last_widget_state & ZR_WIDGET_STATE_ACTIVE) + background = &style->combo.active; + else if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) + background = &style->combo.hover; + else background = &style->combo.normal; + if (background->type == ZR_STYLE_ITEM_IMAGE) { + zr_draw_image(&win->buffer, header, &background->data.image); + } else { + zr_fill_rect(&win->buffer, header, 0, style->combo.border_color); + zr_fill_rect(&win->buffer, zr_shrink_rect(header, 1), 0, + background->data.color); + } { struct zr_rect bounds = {0,0,0,0}; - struct zr_symbol sym; struct zr_rect content; + struct zr_rect button; + + enum zr_symbol_type sym; + if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) + sym = style->combo.sym_hover; + else if (is_active) + sym = style->combo.sym_active; + else sym = style->combo.sym_normal; + + /* calculate button */ + button.w = header.h - 2 * style->combo.button_padding.y; + button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; + button.y = header.y + style->combo.button_padding.y; + button.h = button.w; + + content.x = button.x + style->combo.button.padding.x; + content.y = button.y + style->combo.button.padding.y; + content.w = button.w - 2 * style->combo.button.padding.x; + content.h = button.h - 2 * style->combo.button.padding.y; /* draw image */ - content.h = header.h - 4 * item_padding.y; - content.y = header.y + 2 * item_padding.y; - content.x = header.x + 2 * item_padding.x; - content.w = header.w - (header.h + 4 * item_padding.x); - zr_draw_image(&win->buffer, content, &img); + bounds.h = header.h - 2 * style->combo.content_padding.y; + bounds.y = header.y + style->combo.content_padding.y; + bounds.x = header.x + style->combo.content_padding.x; + bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; + zr_draw_image(&win->buffer, bounds, &img); - /* draw open/close symbol */ - bounds.y = (header.y + item_padding.y) + (header.h-2.0f*item_padding.y)/2.0f - -ctx->style.font.height/2; - bounds.w = bounds.h = ctx->style.font.height; - bounds.x = (header.x + header.w) - (bounds.w + 2 * item_padding.x); - - sym.type = ZR_SYMBOL_TRIANGLE_DOWN; - sym.background = ctx->style.colors[ZR_COLOR_COMBO]; - sym.foreground = ctx->style.colors[ZR_COLOR_TEXT]; - sym.border_width = 1.0f; - zr_draw_symbol(&win->buffer, &sym, bounds, &ctx->style.font); + /* draw open/close button */ + zr_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, + &ctx->style.combo.button, sym, &style->font); } return zr_combo_begin(layout, ctx, win, height, is_active, header); } int -zr_combo_begin_icon(struct zr_context *ctx, struct zr_panel *layout, - const char *selected, struct zr_image img, int height) +zr_combo_begin_image_text(struct zr_context *ctx, struct zr_panel *layout, + const char *selected, zr_size len, struct zr_image img, int height) { struct zr_window *win; - zr_flags state; - struct zr_vec2 item_padding; + struct zr_style *style; + struct zr_input *in; + struct zr_rect header; int is_active = zr_false; + enum zr_widget_layout_states s; + const struct zr_style_item *background; + struct zr_text text; ZR_ASSERT(ctx); ZR_ASSERT(ctx->current); @@ -11824,71 +12037,108 @@ zr_combo_begin_icon(struct zr_context *ctx, struct zr_panel *layout, return 0; win = ctx->current; - if (!zr_widget(&header, ctx)) - return 0; + style = &ctx->style; + s = zr_widget(&header, ctx); + if (!s) return 0; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - if (zr_button_behavior(&state, header, &ctx->input, ZR_BUTTON_DEFAULT)) - is_active = !is_active; + in = (win->layout->flags & ZR_WINDOW_ROM || s == ZR_WIDGET_ROM)? 0: &ctx->input; + if (zr_button_behavior(&ctx->last_widget_state, header, in, ZR_BUTTON_DEFAULT)) + is_active = zr_true; /* draw combo box header background and border */ - zr_draw_rect(&win->buffer, ZR_FILLED, header, 0, ctx->style.colors[ZR_COLOR_BORDER]); - zr_draw_rect(&win->buffer, ZR_FILLED, zr_shrink_rect(header, 1), 0, - ctx->style.colors[ZR_COLOR_COMBO]); + if (ctx->last_widget_state & ZR_WIDGET_STATE_ACTIVE) { + background = &style->combo.active; + text.text = style->combo.label_active; + } else if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) { + background = &style->combo.hover; + text.text = style->combo.label_hover; + } else { + background = &style->combo.normal; + text.text = style->combo.label_normal; + } + if (background->type == ZR_STYLE_ITEM_IMAGE) { + text.background = zr_rgba(0,0,0,0); + zr_draw_image(&win->buffer, header, &background->data.image); + } else { + text.background = background->data.color; + zr_fill_rect(&win->buffer, header, 0, style->combo.border_color); + zr_fill_rect(&win->buffer, zr_shrink_rect(header, 1), 0, + background->data.color); + } { - zr_size text_len; - struct zr_symbol sym; struct zr_rect content; - struct zr_rect label, icon; - struct zr_rect bounds = {0,0,0,0}; + struct zr_rect button; + struct zr_rect label; + struct zr_rect image; - content.h = header.h - 4 * item_padding.y; - content.y = header.y + 2 * item_padding.y; - content.x = header.x + 2 * item_padding.x; - content.w = header.w - (header.h + 4 * item_padding.x); + enum zr_symbol_type sym; + if (ctx->last_widget_state & ZR_WIDGET_STATE_HOVERED) + sym = style->combo.sym_hover; + else if (is_active) + sym = style->combo.sym_active; + else sym = style->combo.sym_normal; - /* draw icon */ - icon.x = content.x; - icon.y = content.y; - icon.h = content.h; - icon.w = icon.h; - zr_draw_image(&win->buffer, icon, &img); + /* calculate button */ + button.w = header.h - 2 * style->combo.button_padding.y; + button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; + button.y = header.y + style->combo.button_padding.y; + button.h = button.w; + + content.x = button.x + style->combo.button.padding.x; + content.y = button.y + style->combo.button.padding.y; + content.w = button.w - 2 * style->combo.button.padding.x; + content.h = button.h - 2 * style->combo.button.padding.y; + zr_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, + &ctx->style.combo.button, sym, &style->font); + + /* draw image */ + image.x = header.x + style->combo.content_padding.x; + image.y = header.y + style->combo.content_padding.y; + image.h = header.h - 2 * style->combo.content_padding.y; + image.w = image.h; + zr_draw_image(&win->buffer, image, &img); /* draw label */ - label.x = icon.x + icon.w + 2 * item_padding.x; - label.y = content.y; - label.w = (content.x + content.w) - (icon.x + icon.w); - label.h = content.h; - text_len = zr_strsiz(selected); - zr_draw_text(&win->buffer, label, selected, text_len, &ctx->style.font, - ctx->style.colors[ZR_COLOR_WINDOW], ctx->style.colors[ZR_COLOR_TEXT]); - - bounds.y = (header.y + item_padding.y) + (header.h-2.0f*item_padding.y)/2.0f - - ctx->style.font.height/2; - bounds.w = bounds.h = ctx->style.font.height; - bounds.x = (header.x + header.w) - (bounds.w + 2 * item_padding.x); - - /* draw open/close symbol */ - sym.type = ZR_SYMBOL_TRIANGLE_DOWN; - sym.background = ctx->style.colors[ZR_COLOR_COMBO]; - sym.foreground = ctx->style.colors[ZR_COLOR_TEXT]; - sym.border_width = 1.0f; - zr_draw_symbol(&win->buffer, &sym, bounds, &ctx->style.font); + text.padding = zr_vec2(0,0); + label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; + label.y = header.y + style->combo.content_padding.y; + label.w = (button.x - style->combo.content_padding.x) - label.x; + label.h = header.h - 2 * style->combo.content_padding.y; + zr_widget_text(&win->buffer, label, selected, len, &text, ZR_TEXT_LEFT, &style->font); } return zr_combo_begin(layout, ctx, win, height, is_active, header); } -int zr_combo_item(struct zr_context *ctx, const char *title, zr_flags align) -{return zr_contextual_item(ctx, title, align);} +int zr_combo_begin_symbol_label(struct zr_context *ctx, struct zr_panel *layout, + const char *selected, enum zr_symbol_type type, int height) +{return zr_combo_begin_symbol_text(ctx, layout, selected, zr_strsiz(selected), type, height);} -int zr_combo_item_icon(struct zr_context *ctx, struct zr_image img, - const char *title, zr_flags align) -{return zr_contextual_item_icon(ctx, img, title, align);} +int zr_combo_begin_image_label(struct zr_context *ctx, struct zr_panel *layout, + const char *selected, struct zr_image img, int height) +{return zr_combo_begin_image_text(ctx, layout, selected, zr_strsiz(selected), img, height);} -int zr_combo_item_symbol(struct zr_context *ctx, enum zr_symbol_type symbol, - const char *title, zr_flags align) -{return zr_contextual_item_symbol(ctx, symbol, title, align);} +int zr_combo_item_text(struct zr_context *ctx, const char *text, zr_size len,zr_flags align) +{return zr_contextual_item_text(ctx, text, len, align);} + +int zr_combo_item_label(struct zr_context *ctx, const char *label, zr_flags align) +{return zr_contextual_item_label(ctx, label, align);} + +int zr_combo_item_image_text(struct zr_context *ctx, struct zr_image img, const char *text, + zr_size len, zr_flags alignment) +{return zr_contextual_item_image_text(ctx, img, text, len, alignment);} + +int zr_combo_item_image_label(struct zr_context *ctx, struct zr_image img, + const char *text, zr_flags alignment) +{return zr_contextual_item_image_label(ctx, img, text, alignment);} + +int zr_combo_item_symbol_text(struct zr_context *ctx, enum zr_symbol_type sym, + const char *text, zr_size len, zr_flags alignment) +{return zr_contextual_item_symbol_text(ctx, sym, text, len, alignment);} + +int zr_combo_item_symbol_label(struct zr_context *ctx, enum zr_symbol_type sym, + const char *label, zr_flags alignment) +{return zr_contextual_item_symbol_label(ctx, sym, label, alignment);} void zr_combo_end(struct zr_context *ctx) {zr_contextual_end(ctx);} @@ -11903,21 +12153,21 @@ zr_combo(struct zr_context *ctx, const char **items, int count, int i = 0; int max_height; struct zr_panel combo; - struct zr_vec2 item_padding; - struct zr_vec2 window_padding; + float item_padding; + float window_padding; ZR_ASSERT(ctx); ZR_ASSERT(items); if (!ctx || !items ||!count) return selected; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - window_padding = zr_get_property(ctx, ZR_PROPERTY_PADDING); - max_height = (count+1) * item_height + (int)item_padding.y * 3 + (int)window_padding.y * 2; - if (zr_combo_begin_text(ctx, &combo, items[selected], max_height)) { + item_padding = ctx->style.combo.button_padding.y; + window_padding = ctx->style.window.padding.y; + max_height = (count+1) * item_height + (int)item_padding * 3 + (int)window_padding * 2; + if (zr_combo_begin_label(ctx, &combo, items[selected], max_height)) { zr_layout_row_dynamic(ctx, (float)item_height, 1); for (i = 0; i < count; ++i) { - if (zr_combo_item(ctx, items[i], ZR_TEXT_LEFT)) + if (zr_combo_item_label(ctx, items[i], ZR_TEXT_LEFT)) selected = i; } zr_combo_end(ctx); @@ -11925,50 +12175,58 @@ zr_combo(struct zr_context *ctx, const char **items, int count, return selected; } +int +zr_combo_seperator(struct zr_context *ctx, const char *items_seperated_by_seperator, + int seperator, int selected, int count, int item_height) +{ + int i; + int max_height; + struct zr_panel combo; + float item_padding; + float window_padding; + const char *current_item; + const char *iter; + zr_size length = 0; + + ZR_ASSERT(ctx); + ZR_ASSERT(items_seperated_by_seperator); + if (!ctx || !items_seperated_by_seperator) + return selected; + + /* calculate popup window */ + item_padding = ctx->style.combo.content_padding.y; + window_padding = ctx->style.window.padding.y; + max_height = (count+1) * item_height + (int)item_padding * 3 + (int)window_padding * 2; + + /* find selected item */ + current_item = items_seperated_by_seperator; + for (i = 0; i < selected; ++i) { + iter = current_item; + while (*iter != seperator) iter++; + length = (zr_size)(iter - current_item); + current_item = iter + 1; + } + + if (zr_combo_begin_text(ctx, &combo, current_item, length, max_height)) { + current_item = items_seperated_by_seperator; + zr_layout_row_dynamic(ctx, (float)item_height, 1); + for (i = 0; i < count; ++i) { + iter = current_item; + while (*iter != seperator) iter++; + length = (zr_size)(iter - current_item); + if (zr_combo_item_text(ctx, current_item, length, ZR_TEXT_LEFT)) + selected = i; + current_item = current_item + length + 1; + } + zr_combo_end(ctx); + } + return selected; +} + int zr_combo_string(struct zr_context *ctx, const char *items_seperated_by_zeros, int selected, int count, int item_height) -{ - int i; - int max_height; - struct zr_panel combo; - struct zr_vec2 item_padding; - struct zr_vec2 window_padding; - const char *current_item; - zr_size length; - - ZR_ASSERT(ctx); - ZR_ASSERT(items_seperated_by_zeros); - if (!ctx || !items_seperated_by_zeros) - return selected; - - /* calculate popup window */ - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - window_padding = zr_get_property(ctx, ZR_PROPERTY_PADDING); - max_height = (count+1) * item_height + (int)item_padding.y * 3 + (int)window_padding.y * 2; - - /* find selected item */ - current_item = items_seperated_by_zeros; - length = zr_strsiz(current_item); - for (i = 0; i < selected; ++i) { - current_item = current_item + length + 1; - length = zr_strsiz(current_item); - } - - current_item = items_seperated_by_zeros; - if (zr_combo_begin_text(ctx, &combo, current_item, max_height)) { - zr_layout_row_dynamic(ctx, (float)item_height, 1); - for (i = 0; i < count; ++i) { - if (zr_combo_item(ctx, current_item, ZR_TEXT_LEFT)) - selected = i; - - length = zr_strsiz(current_item); - current_item = current_item + length + 1; - } - zr_combo_end(ctx); - } - return selected; -} +{return zr_combo_seperator(ctx, items_seperated_by_zeros, '\0', selected, count, item_height);} int zr_combo_callback(struct zr_context *ctx, void(item_getter)(void*, int, const char**), @@ -11977,8 +12235,8 @@ zr_combo_callback(struct zr_context *ctx, void(item_getter)(void*, int, const ch int i; int max_height; struct zr_panel combo; - struct zr_vec2 item_padding; - struct zr_vec2 window_padding; + float item_padding; + float window_padding; const char *item; ZR_ASSERT(ctx); @@ -11986,16 +12244,17 @@ zr_combo_callback(struct zr_context *ctx, void(item_getter)(void*, int, const ch if (!ctx || !item_getter) return selected; - item_padding = zr_get_property(ctx, ZR_PROPERTY_ITEM_PADDING); - window_padding = zr_get_property(ctx, ZR_PROPERTY_PADDING); - max_height = (count+1) * item_height + (int)item_padding.y * 3 + (int)window_padding.y * 2; + /* calculate popup window */ + item_padding = ctx->style.combo.content_padding.y; + window_padding = ctx->style.window.padding.y; + max_height = (count+1) * item_height + (int)item_padding * 3 + (int)window_padding * 2; item_getter(userdata, selected, &item); - if (zr_combo_begin_text(ctx, &combo, item, max_height)) { + if (zr_combo_begin_label(ctx, &combo, item, max_height)) { zr_layout_row_dynamic(ctx, (float)item_height, 1); for (i = 0; i < count; ++i) { item_getter(userdata, i, &item); - if (zr_combo_item(ctx, item, ZR_TEXT_LEFT)) + if (zr_combo_item_label(ctx, item, ZR_TEXT_LEFT)) selected = i; } zr_combo_end(ctx); @@ -12003,39 +12262,23 @@ zr_combo_callback(struct zr_context *ctx, void(item_getter)(void*, int, const ch return selected; } -void -zr_combobox(struct zr_context *ctx, const char **items, int count, int *selected, - int item_height) -{ - ZR_ASSERT(ctx); - ZR_ASSERT(items); - ZR_ASSERT(selected); - if (!ctx || !items || !selected) return; - *selected = zr_combo(ctx, items, count, *selected, item_height); -} +void zr_combobox(struct zr_context *ctx, const char **items, int count, + int *selected, int item_height) +{*selected = zr_combo(ctx, items, count, *selected, item_height);} -void -zr_combobox_string(struct zr_context *ctx, const char *items_seperated_by_zeros, +void zr_combobox_string(struct zr_context *ctx, const char *items_seperated_by_zeros, int *selected, int count, int item_height) -{ - ZR_ASSERT(ctx); - ZR_ASSERT(items_seperated_by_zeros); - ZR_ASSERT(selected); - if (!ctx || !items_seperated_by_zeros || !selected) return; - *selected = zr_combo_string(ctx, items_seperated_by_zeros, *selected, count, item_height); -} +{*selected = zr_combo_string(ctx, items_seperated_by_zeros, *selected, count, item_height);} -void -zr_combobox_callback(struct zr_context *ctx, +void zr_combobox_seperator(struct zr_context *ctx, const char *items_seperated_by_seperator, + int seperator,int *selected, int count, int item_height) +{*selected = zr_combo_seperator(ctx, items_seperated_by_seperator, seperator, + *selected, count, item_height);} + +void zr_combobox_callback(struct zr_context *ctx, void(item_getter)(void* data, int id, const char **out_text), void *userdata, int *selected, int count, int item_height) -{ - ZR_ASSERT(ctx); - ZR_ASSERT(item_getter); - ZR_ASSERT(selected); - if (!ctx || !item_getter || !selected) return; - *selected = zr_combo_callback(ctx, item_getter, userdata, *selected, count, item_height); -} +{*selected = zr_combo_callback(ctx, item_getter, userdata, *selected, count, item_height);} /* * ------------------------------------------------------------- @@ -12078,8 +12321,8 @@ zr_menu_begin(struct zr_panel *layout, struct zr_context *ctx, struct zr_window } int -zr_menu_text_begin(struct zr_context *ctx, struct zr_panel *layout, - const char *title, zr_flags align, float width) +zr_menu_begin_text(struct zr_context *ctx, struct zr_panel *layout, + const char *title, zr_size len, zr_flags align, float width) { struct zr_window *win; const struct zr_input *in; @@ -12093,37 +12336,27 @@ zr_menu_text_begin(struct zr_context *ctx, struct zr_panel *layout, if (!ctx || !ctx->current || !ctx->current->layout) return 0; - { - /* execute menu text button for open/closing the popup */ - struct zr_button_text button; - zr_zero(&button, sizeof(button)); - if (!zr_button(&button.base, &header, ctx, ZR_BUTTON_NORMAL)) - return 0; - - win = ctx->current; - button.base.rounding = 0; - button.base.border_width = 0; - button.base.border = ctx->style.colors[ZR_COLOR_WINDOW]; - button.base.normal = ctx->style.colors[ZR_COLOR_WINDOW]; - button.base.active = ctx->style.colors[ZR_COLOR_WINDOW]; - button.alignment = align; - button.normal = ctx->style.colors[ZR_COLOR_TEXT]; - button.active = ctx->style.colors[ZR_COLOR_TEXT]; - button.hover = ctx->style.colors[ZR_COLOR_TEXT]; - in = (win->layout->flags & ZR_WINDOW_ROM) ? 0: &ctx->input; - if (zr_do_button_text(&state, &win->buffer, header, - title, ZR_BUTTON_DEFAULT, &button, in, &ctx->style.font)) - is_clicked = zr_true; - } + win = ctx->current; + state = zr_widget(&header, ctx); + if (!state) return 0; + in = (state == ZR_WIDGET_ROM || win->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; + if (zr_do_button_text(&ctx->last_widget_state, &win->buffer, header, + title, len, align, ZR_BUTTON_DEFAULT, &ctx->style.menu_button, in, &ctx->style.font)) + is_clicked = zr_true; return zr_menu_begin(layout, ctx, win, title, is_clicked, header, width); } +int zr_menu_begin_label(struct zr_context *ctx, struct zr_panel *layout, + const char *text, zr_flags align, float width) +{return zr_menu_begin_text(ctx, layout, text, zr_strsiz(text), align, width);} + int -zr_menu_icon_begin(struct zr_context *ctx, struct zr_panel *layout, +zr_menu_begin_image(struct zr_context *ctx, struct zr_panel *layout, const char *id, struct zr_image img, float width) { struct zr_window *win; struct zr_rect header; + const struct zr_input *in; int is_clicked = zr_false; zr_flags state; @@ -12134,30 +12367,21 @@ zr_menu_icon_begin(struct zr_context *ctx, struct zr_panel *layout, return 0; win = ctx->current; - { - /* execute menu icon button for open/closing the popup */ - struct zr_button_icon button; - zr_zero(&button, sizeof(button)); - if (!zr_button(&button.base, &header, ctx, ZR_BUTTON_NORMAL)) - return 0; - - button.base.rounding = 1; - button.base.border = ctx->style.colors[ZR_COLOR_BORDER]; - button.base.normal = ctx->style.colors[ZR_COLOR_WINDOW]; - button.base.active = ctx->style.colors[ZR_COLOR_WINDOW]; - button.padding = ctx->style.properties[ZR_PROPERTY_ITEM_PADDING]; - if (zr_do_button_image(&state, &win->buffer, header, img, ZR_BUTTON_DEFAULT, - &button, (win->layout->flags & ZR_WINDOW_ROM)?0:&ctx->input)) - is_clicked = zr_true; - } + state = zr_widget(&header, ctx); + if (!state) return 0; + in = (state == ZR_WIDGET_ROM || win->layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; + if (zr_do_button_image(&ctx->last_widget_state, &win->buffer, header, + img, ZR_BUTTON_DEFAULT, &ctx->style.menu_button, in)) + is_clicked = zr_true; return zr_menu_begin(layout, ctx, win, id, is_clicked, header, width); } int -zr_menu_symbol_begin(struct zr_context *ctx, struct zr_panel *layout, +zr_menu_begin_symbol(struct zr_context *ctx, struct zr_panel *layout, const char *id, enum zr_symbol_type sym, float width) { struct zr_window *win; + const struct zr_input *in; struct zr_rect header; int is_clicked = zr_false; zr_flags state; @@ -12169,37 +12393,98 @@ zr_menu_symbol_begin(struct zr_context *ctx, struct zr_panel *layout, return 0; win = ctx->current; - { - /* execute menu symbol button for open/closing the popup */ - struct zr_button_symbol button; - zr_zero(&button, sizeof(button)); - if (!zr_button(&button.base, &header, ctx, ZR_BUTTON_NORMAL)) - return 0; - - button.base.rounding = 1; - button.base.border = ctx->style.colors[ZR_COLOR_BORDER]; - button.base.normal = ctx->style.colors[ZR_COLOR_WINDOW]; - button.base.active = ctx->style.colors[ZR_COLOR_WINDOW]; - button.normal = ctx->style.colors[ZR_COLOR_TEXT]; - button.active = ctx->style.colors[ZR_COLOR_TEXT]; - button.hover = ctx->style.colors[ZR_COLOR_TEXT]; - if (zr_do_button_symbol(&state, &win->buffer, header, sym, ZR_BUTTON_DEFAULT, - &button, (win->layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input, - &ctx->style.font)) is_clicked = zr_true; - } + state = zr_widget(&header, ctx); + if (!state) return 0; + in = (state == ZR_WIDGET_ROM || win->layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; + if (zr_do_button_symbol(&ctx->last_widget_state, &win->buffer, header, + sym, ZR_BUTTON_DEFAULT, &ctx->style.menu_button, in, &ctx->style.font)) + is_clicked = zr_true; return zr_menu_begin(layout, ctx, win, id, is_clicked, header, width); } -int zr_menu_item(struct zr_context *ctx, zr_flags align, const char *title) -{return zr_contextual_item(ctx, title, align);} +int +zr_menu_begin_image_text(struct zr_context *ctx, struct zr_panel *layout, + const char *title, zr_size len, zr_flags align, struct zr_image img, float width) +{ + struct zr_window *win; + struct zr_rect header; + const struct zr_input *in; + int is_clicked = zr_false; + zr_flags state; -int zr_menu_item_icon(struct zr_context *ctx, struct zr_image img, - const char *title, zr_flags align) -{ return zr_contextual_item_icon(ctx, img, title, align);} + ZR_ASSERT(ctx); + ZR_ASSERT(ctx->current); + ZR_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout) + return 0; -int zr_menu_item_symbol(struct zr_context *ctx, enum zr_symbol_type symbol, - const char *title, zr_flags align) -{return zr_contextual_item_symbol(ctx, symbol, title, align);} + win = ctx->current; + state = zr_widget(&header, ctx); + if (!state) return 0; + in = (state == ZR_WIDGET_ROM || win->layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; + if (zr_do_button_text_image(&ctx->last_widget_state, &win->buffer, + header, img, title, len, align, ZR_BUTTON_DEFAULT, &ctx->style.menu_button, + &ctx->style.font, in)) + is_clicked = zr_true; + return zr_menu_begin(layout, ctx, win, title, is_clicked, header, width); +} + +int zr_menu_begin_image_label(struct zr_context *ctx, struct zr_panel *layout, + const char *title, zr_flags align, struct zr_image img, float width) +{return zr_menu_begin_image_text(ctx, layout, title, zr_strsiz(title), align, img, width);} + +int +zr_menu_begin_symbol_text(struct zr_context *ctx, struct zr_panel *layout, + const char *title, zr_size size, zr_flags align, enum zr_symbol_type sym, float width) +{ + struct zr_window *win; + struct zr_rect header; + const struct zr_input *in; + int is_clicked = zr_false; + zr_flags state; + + ZR_ASSERT(ctx); + ZR_ASSERT(ctx->current); + ZR_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout) + return 0; + + win = ctx->current; + state = zr_widget(&header, ctx); + if (!state) return 0; + in = (state == ZR_WIDGET_ROM || win->layout->flags & ZR_WINDOW_ROM) ? 0 : &ctx->input; + if (zr_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, + header, sym, title, size, align, ZR_BUTTON_DEFAULT, &ctx->style.menu_button, + &ctx->style.font, in)) + is_clicked = zr_true; + return zr_menu_begin(layout, ctx, win, title, is_clicked, header, width); +} + +int zr_menu_begin_symbol_label(struct zr_context *ctx, struct zr_panel *layout, + const char *title, zr_flags align, enum zr_symbol_type sym, float width) +{return zr_menu_begin_symbol_text(ctx, layout, title, zr_strsiz(title), align,sym, width);} + +int zr_menu_item_text(struct zr_context *ctx, const char *title, zr_size len, zr_flags align) +{return zr_contextual_item_text(ctx, title, len, align);} + +int zr_menu_item_label(struct zr_context *ctx, const char *label, zr_flags align) +{return zr_contextual_item_label(ctx, label, align);} + +int zr_menu_item_image_label(struct zr_context *ctx, struct zr_image img, + const char *label, zr_flags align) +{return zr_contextual_item_image_label(ctx, img, label, align);} + +int zr_menu_item_image_text(struct zr_context *ctx, struct zr_image img, + const char *text, zr_size len, zr_flags align) +{return zr_contextual_item_image_text(ctx, img, text, len, align);} + +int zr_menu_item_symbol_text(struct zr_context *ctx, enum zr_symbol_type sym, + const char *text, zr_size len, zr_flags align) +{return zr_contextual_item_symbol_text(ctx, sym, text, len, align);} + +int zr_menu_item_symbol_label(struct zr_context *ctx, enum zr_symbol_type sym, + const char *label, zr_flags align) +{return zr_contextual_item_symbol_label(ctx, sym, label, align);} void zr_menu_close(struct zr_context *ctx) {zr_contextual_close(ctx);} diff --git a/zahnrad.h b/zahnrad.h index 64de067..b67d0d1 100644 --- a/zahnrad.h +++ b/zahnrad.h @@ -44,6 +44,7 @@ extern "C" { #define ZR_MAX_FONT_HEIGHT_STACK 32 /* Number of temporary configuration font height changes that can be stored */ #define ZR_MAX_NUMBER_BUFFER 64 +#define ZR_MAX_COMBO_EDIT_BUFFER 128 #define ZR_MAX_EVENTS 32 /* * ============================================================== @@ -274,34 +275,24 @@ struct zr_memory_status { struct zr_allocator { zr_handle userdata; - /* handle to your own allocator */ void*(*alloc)(zr_handle, zr_size); - /* allocation function pointer */ - /* reallocation pointer of a previously allocated memory block */ void(*free)(zr_handle, void*); - /* callback function pointer to finally free all allocated memory */ }; enum zr_allocation_type { ZR_BUFFER_FIXED, - /* fixed size memory buffer */ ZR_BUFFER_DYNAMIC - /* dynamically growing buffer */ }; enum zr_buffer_allocation_type { ZR_BUFFER_FRONT, - /* allocate memory from the front of the buffer */ ZR_BUFFER_BACK, - /* allocate memory from the back of the buffer */ ZR_BUFFER_MAX }; struct zr_buffer_marker { int active; - /* flag indiciation if the marker was set */ zr_size offset; - /* offset of the marker inside the buffer */ }; struct zr_memory {void *ptr;zr_size size;}; @@ -452,35 +443,21 @@ struct zr_font_config { struct zr_font_glyph { zr_rune codepoint; - /* unicode codepoint */ float xadvance; - /* xoffset to the next character */ float x0, y0, x1, y1, w, h; - /* glyph bounding points in pixel inside the glyph image with top - * left and bottom right */ float u0, v0, u1, v1; - /* texture coordinates either in pixel or clamped (0.0 - 1.0) */ }; struct zr_font { float size; - /* pixel height of the font */ float scale; - /* scale factor for different font size */ float ascent, descent; - /* font ascent and descent */ struct zr_font_glyph *glyphs; - /* font glyph array */ const struct zr_font_glyph *fallback; - /* fallback glyph */ zr_rune fallback_codepoint; - /* fallback glyph codepoint */ zr_rune glyph_count; - /* font glyph array size */ const zr_rune *ranges; - /* glyph unicode ranges in the font */ zr_handle atlas; - /* font image atlas handle */ }; /* some language glyph codepoint ranges */ @@ -492,67 +469,19 @@ const zr_rune *zr_font_korean_glyph_ranges(void); /* font baking functions (need to be called sequentially top to bottom) */ void zr_font_bake_memory(zr_size *temporary_memory, int *glyph_count, struct zr_font_config*, int count); -/* this function calculates the needed memory for the baking process - Input: - - array of configuration for every font that should be baked into one image - - number of configuration fonts in the array - Output: - - amount of memory needed in the baking process - - total number of glyphs that need to be allocated -*/ int zr_font_bake_pack(zr_size *img_memory, int *img_width, int *img_height, struct zr_recti *custom_space, void *temporary_memory, zr_size temporary_size, const struct zr_font_config*, int font_count); -/* this function packs together all glyphs and optional space into one - total image space and returns the needed image width and height. - Input: - - NULL or custom space inside the image (will be modifed to fit!) - - temporary memory block that will be used in the baking process - - size of the temporary memory block - - array of configuration for every font that should be baked into one image - - number of configuration fonts in the array - Output: - - calculated resulting size of the image in bytes - - pixel width of the resulting image - - pixel height of the resulting image - - custom space bounds with position and size inside image which can be - filled by the user -*/ void zr_font_bake(void *image_memory, int image_width, int image_height, void *temporary_memory, zr_size temporary_memory_size, struct zr_font_glyph*, int glyphs_count, const struct zr_font_config*, int font_count); -/* this function bakes all glyphs into the pre-allocated image and - fills a glyph array with information. - Input: - - image memory buffer to bake the glyph into - - pixel width/height of the image - - temporary memory block that will be used in the baking process - - size of the temporary memory block - Output: - - image filled with glyphs - - filled glyph array -*/ void zr_font_bake_custom_data(void *img_memory, int img_width, int img_height, struct zr_recti img_dst, const char *image_data_mask, int tex_width, int tex_height,char white,char black); -/* this function bakes custom data in string format with white, black and zero - alpha pixels into the font image. The zero alpha pixel is represented as - any character beside the black and zero pixel character. - Input: - - image memory buffer to bake the custom data into - - image size (width/height) of the image in pixels - - custom texture data in string format - - texture size (width/height) of the custom image content - - character representing a white pixel in the texture data format - - character representing a black pixel in the texture data format - Output: - - image filled with custom texture data -*/ void zr_font_bake_convert(void *out_memory, int image_width, int image_height, const void *in_memory); -/* this function converts alpha8 baking input image into a rgba8 output image.*/ void zr_font_init(struct zr_font*, float pixel_height, zr_rune fallback_codepoint, struct zr_font_glyph*, const struct zr_baked_font*, zr_handle atlas); @@ -560,491 +489,6 @@ struct zr_user_font zr_font_ref(struct zr_font*); const struct zr_font_glyph* zr_font_find_glyph(struct zr_font*, zr_rune unicode); #endif -/* =============================================================== - * - * RENDERING - * - * ===============================================================*/ -/* This library was designed to be render backend agnostic so it does - not draw anything to the screen. Instead all drawn primitives, widgets - are made of, are buffered into memory and make up a command queue. - Each frame therefore fills the command buffer with draw commands - that then need to be executed by the user and his own render backend. - After that the command buffer needs to be cleared and a new frame can be - started. - - The reason for buffering simple primitives as draw commands instead of - directly buffering a hardware accessible format with vertex and element - buffer was to support native render backends like X11 and Win32. - That being said it is possible to convert the command buffer into a - hardware accessible format to support hardware based rendering as well. -*/ -enum zr_command_type { - ZR_COMMAND_NOP, - ZR_COMMAND_SCISSOR, - ZR_COMMAND_LINE, - ZR_COMMAND_CURVE, - ZR_COMMAND_RECT, - ZR_COMMAND_RECT_MULTI_COLOR, - ZR_COMMAND_CIRCLE, - ZR_COMMAND_ARC, - ZR_COMMAND_TRIANGLE, - ZR_COMMAND_POLYGON, - ZR_COMMAND_POLYLINE, - ZR_COMMAND_TEXT, - ZR_COMMAND_IMAGE -}; - -/* command base and header of every comand inside the buffer */ -struct zr_command { - enum zr_command_type type; - /* the type of the current command */ - zr_size next; - /* absolute base pointer offset to the next command */ -#if ZR_COMPILE_WITH_COMMAND_USERDATA - zr_handle userdata; -#endif -}; - -enum zr_command_drawing_mode { - ZR_STROKE, - ZR_FILLED -}; - -struct zr_command_scissor { - struct zr_command header; - short x, y; - unsigned short w, h; -}; - -struct zr_command_line { - struct zr_command header; - struct zr_vec2i begin; - struct zr_vec2i end; - struct zr_color color; -}; - -struct zr_command_curve { - struct zr_command header; - struct zr_vec2i begin; - struct zr_vec2i end; - struct zr_vec2i ctrl[2]; - struct zr_color color; -}; - -struct zr_command_rect { - struct zr_command header; - enum zr_command_drawing_mode mode; - unsigned int rounding; - short x, y; - unsigned short w, h; - struct zr_color color; -}; - -struct zr_command_rect_multi_color { - struct zr_command header; - short x, y; - unsigned short w, h; - struct zr_color left; - struct zr_color top; - struct zr_color bottom; - struct zr_color right; -}; - -struct zr_command_circle { - struct zr_command header; - enum zr_command_drawing_mode mode; - short x, y; - unsigned short w, h; - struct zr_color color; -}; - -struct zr_command_polygon { - struct zr_command header; - enum zr_command_drawing_mode mode; - struct zr_color color; - unsigned short point_count; - struct zr_vec2i points[1]; -}; - -struct zr_command_polyline { - struct zr_command header; - struct zr_color color; - unsigned short point_count; - struct zr_vec2i points[1]; -}; - -struct zr_command_arc { - struct zr_command header; - enum zr_command_drawing_mode mode; - short cx, cy; - unsigned short r; - float a[2]; - struct zr_color color; -}; - -struct zr_command_triangle { - struct zr_command header; - enum zr_command_drawing_mode mode; - struct zr_vec2i a; - struct zr_vec2i b; - struct zr_vec2i c; - struct zr_color color; -}; - -struct zr_command_image { - struct zr_command header; - short x, y; - unsigned short w, h; - struct zr_image img; -}; - -struct zr_command_text { - struct zr_command header; - const struct zr_user_font *font; - struct zr_color background; - struct zr_color foreground; - short x, y; - unsigned short w, h; - float height; - zr_size length; - char string[1]; -}; - -enum zr_command_clipping { - ZR_CLIPPING_OFF = zr_false, - ZR_CLIPPING_ON = zr_true -}; - -struct zr_command_buffer { - struct zr_buffer *base; - /* memory buffer to store the command */ - struct zr_rect clip; - /* current clipping rectangle */ - int use_clipping; - /* flag if the command buffer should clip commands */ - zr_handle userdata; - /* userdata provided in each command */ - zr_size begin, end, last; -}; - -#if ZR_COMPILE_WITH_VERTEX_BUFFER -typedef unsigned short zr_draw_index; -typedef zr_uint zr_draw_vertex_color; - -enum zr_anti_aliasing { - ZR_ANTI_ALIASING_OFF = zr_false, - /* renderes all primitives without anti-aliasing */ - ZR_ANTI_ALIASING_ON - /* renderes all primitives with anti-aliasing */ -}; - -struct zr_draw_vertex { - struct zr_vec2 position; - struct zr_vec2 uv; - zr_draw_vertex_color col; -}; -#endif - -struct zr_draw_command { - unsigned int elem_count; - /* number of elements in the current draw batch */ - struct zr_rect clip_rect; - /* current screen clipping rectangle */ - zr_handle texture; - /* current texture to set */ -#if ZR_COMPILE_WITH_COMMAND_USERDATA - zr_handle userdata; -#endif -}; - -struct zr_draw_null_texture { - zr_handle texture; - /* texture handle to a texture with a white pixel */ - struct zr_vec2 uv; - /* coordinates to the white pixel in the texture */ -}; - -/* drawing routines for custom widgets */ -void zr_draw_scissor(struct zr_command_buffer*, struct zr_rect); -void zr_draw_line(struct zr_command_buffer*, float, float, float, - float, struct zr_color); -void zr_draw_curve(struct zr_command_buffer*, float, float, float, float, - float, float, float, float, struct zr_color); -void zr_draw_rect(struct zr_command_buffer*, enum zr_command_drawing_mode, - struct zr_rect, float rounding, struct zr_color); -void zr_draw_rect_multi_color(struct zr_command_buffer*, struct zr_rect, - struct zr_color left, struct zr_color top, - struct zr_color right, struct zr_color bottom); -void zr_draw_circle(struct zr_command_buffer*, enum zr_command_drawing_mode, - struct zr_rect, struct zr_color); -void zr_draw_arc(struct zr_command_buffer*, enum zr_command_drawing_mode, - float cx, float cy, float radius, float a_min, float a_max, struct zr_color); -void zr_draw_triangle(struct zr_command_buffer*, enum zr_command_drawing_mode, - float, float, float, float, float, float, struct zr_color); -void zr_draw_image(struct zr_command_buffer*, struct zr_rect, struct zr_image*); -void zr_draw_text(struct zr_command_buffer*, struct zr_rect, - const char *text, zr_size len, const struct zr_user_font*, - struct zr_color, struct zr_color); -void zr_draw_polygon(struct zr_command_buffer*, enum zr_command_drawing_mode, - float*, int point_count, struct zr_color); -void zr_draw_polyline(struct zr_command_buffer*, float *points, int point_count, - struct zr_color col); - -/* =============================================================== - * - * GUI - * - * ===============================================================*/ -enum zr_keys { - ZR_KEY_SHIFT, - ZR_KEY_DEL, - ZR_KEY_ENTER, - ZR_KEY_TAB, - ZR_KEY_BACKSPACE, - ZR_KEY_COPY, - ZR_KEY_CUT, - ZR_KEY_PASTE, - ZR_KEY_UP, - ZR_KEY_DOWN, - ZR_KEY_LEFT, - ZR_KEY_RIGHT, - ZR_KEY_MAX -}; - -/* every used mouse button */ -enum zr_buttons { - ZR_BUTTON_LEFT, - ZR_BUTTON_MIDDLE, - ZR_BUTTON_RIGHT, - ZR_BUTTON_MAX -}; - -struct zr_mouse_button { - int down; - /* current button state */ - unsigned int clicked; - /* button state change */ - struct zr_vec2 clicked_pos; - /* mouse position of last state change */ -}; - -struct zr_mouse { - struct zr_mouse_button buttons[ZR_BUTTON_MAX]; - /* mouse button states */ - struct zr_vec2 pos; - /* current mouse position */ - struct zr_vec2 prev; - /* mouse position in the last frame */ - struct zr_vec2 delta; - /* mouse travelling distance from last to current frame */ - float scroll_delta; - /* number of steps in the up or down scroll direction */ -}; - -struct zr_key { - int down; - unsigned int clicked; -}; - -struct zr_keyboard { - struct zr_key keys[ZR_KEY_MAX]; - /* state of every used key */ - char text[ZR_INPUT_MAX]; - /* utf8 text input frame buffer */ - zr_size text_len; - /* text input frame buffer length in bytes */ -}; - -struct zr_input { - struct zr_keyboard keyboard; - /* current keyboard key + text input state */ - struct zr_mouse mouse; - /* current mouse button and position state */ -}; - -/* query input state */ -int zr_input_has_mouse_click_in_rect(const struct zr_input*, - enum zr_buttons, struct zr_rect); -int zr_input_has_mouse_click_down_in_rect(const struct zr_input*, enum zr_buttons, - struct zr_rect, int down); -int zr_input_is_mouse_click_in_rect(const struct zr_input*, - enum zr_buttons, struct zr_rect); -int zr_input_is_mouse_click_down_in_rect(const struct zr_input *i, enum zr_buttons id, - struct zr_rect b, int down); -int zr_input_any_mouse_click_in_rect(const struct zr_input*, struct zr_rect); -int zr_input_is_mouse_prev_hovering_rect(const struct zr_input*, struct zr_rect); -int zr_input_is_mouse_hovering_rect(const struct zr_input*, struct zr_rect); -int zr_input_mouse_clicked(const struct zr_input*, enum zr_buttons, struct zr_rect); -int zr_input_is_mouse_down(const struct zr_input*, enum zr_buttons); -int zr_input_is_mouse_pressed(const struct zr_input*, enum zr_buttons); -int zr_input_is_mouse_released(const struct zr_input*, enum zr_buttons); -int zr_input_is_key_pressed(const struct zr_input*, enum zr_keys); -int zr_input_is_key_released(const struct zr_input*, enum zr_keys); -int zr_input_is_key_down(const struct zr_input*, enum zr_keys); - -/* ============================================================== - * STYLE - * ===============================================================*/ -enum zr_style_colors { - ZR_COLOR_TEXT, - ZR_COLOR_TEXT_HOVERING, - ZR_COLOR_TEXT_ACTIVE, - ZR_COLOR_WINDOW, - ZR_COLOR_HEADER, - ZR_COLOR_BORDER, - ZR_COLOR_BUTTON, - ZR_COLOR_BUTTON_HOVER, - ZR_COLOR_BUTTON_ACTIVE, - ZR_COLOR_TOGGLE, - ZR_COLOR_TOGGLE_HOVER, - ZR_COLOR_TOGGLE_CURSOR, - ZR_COLOR_SELECTABLE, - ZR_COLOR_SELECTABLE_HOVER, - ZR_COLOR_SELECTABLE_TEXT, - ZR_COLOR_SLIDER, - ZR_COLOR_SLIDER_CURSOR, - ZR_COLOR_SLIDER_CURSOR_HOVER, - ZR_COLOR_SLIDER_CURSOR_ACTIVE, - ZR_COLOR_PROGRESS, - ZR_COLOR_PROGRESS_CURSOR, - ZR_COLOR_PROGRESS_CURSOR_HOVER, - ZR_COLOR_PROGRESS_CURSOR_ACTIVE, - ZR_COLOR_PROPERTY, - ZR_COLOR_PROPERTY_HOVER, - ZR_COLOR_PROPERTY_ACTIVE, - ZR_COLOR_INPUT, - ZR_COLOR_INPUT_CURSOR, - ZR_COLOR_INPUT_TEXT, - ZR_COLOR_COMBO, - ZR_COLOR_HISTO, - ZR_COLOR_HISTO_BARS, - ZR_COLOR_HISTO_HIGHLIGHT, - ZR_COLOR_PLOT, - ZR_COLOR_PLOT_LINES, - ZR_COLOR_PLOT_HIGHLIGHT, - ZR_COLOR_SCROLLBAR, - ZR_COLOR_SCROLLBAR_CURSOR, - ZR_COLOR_SCROLLBAR_CURSOR_HOVER, - ZR_COLOR_SCROLLBAR_CURSOR_ACTIVE, - ZR_COLOR_TABLE_LINES, - ZR_COLOR_TAB_HEADER, - ZR_COLOR_SCALER, - ZR_COLOR_COUNT -}; - -enum zr_style_rounding { - ZR_ROUNDING_BUTTON, - ZR_ROUNDING_SLIDER, - ZR_ROUNDING_CHECK, - ZR_ROUNDING_INPUT, - ZR_ROUNDING_PROPERTY, - ZR_ROUNDING_CHART, - ZR_ROUNDING_SCROLLBAR, - ZR_ROUNDING_MAX -}; - -enum zr_style_properties { - ZR_PROPERTY_ITEM_SPACING, - /* space between widgets */ - ZR_PROPERTY_ITEM_PADDING, - /* padding inside widet between content */ - ZR_PROPERTY_TOUCH_PADDING, - /* extra padding for touch devices */ - ZR_PROPERTY_PADDING, - /* padding between window and widgets */ - ZR_PROPERTY_SCALER_SIZE, - /* width and height of the window scaler */ - ZR_PROPERTY_SCROLLBAR_SIZE, - /* width for vertical scrollbar and height for horizontal scrollbar*/ - ZR_PROPERTY_SIZE, - /* min size of a window that cannot be undercut */ - ZR_PROPERTY_MAX -}; - -enum zr_style_header_align { - ZR_HEADER_LEFT, - ZR_HEADER_RIGHT -}; - -enum zr_style_components { - ZR_DEFAULT_COLOR = 0x01, - /* default all colors inside the configuration struct */ - ZR_DEFAULT_PROPERTIES = 0x02, - /* default all properites inside the configuration struct */ - ZR_DEFAULT_ROUNDING = 0x04, - /* default all rounding values inside the configuration struct */ - ZR_DEFAULT_ALL = ZR_DEFAULT_COLOR|ZR_DEFAULT_PROPERTIES|ZR_DEFAULT_ROUNDING - /* default the complete configuration struct */ -}; - -struct zr_saved_property { - enum zr_style_properties type; - /* identifier of the current modified property */ - struct zr_vec2 value; - /* property value that has been saveed */ -}; - -struct zr_saved_color { - enum zr_style_colors type; - /* identifier of the current modified color */ - struct zr_color value; - /* color value that has been saveed */ -}; - -struct zr_saved_font { - struct zr_user_font value; - /* user font reference */ - int font_height_begin; - /* style font height stack begin */ - int font_height_end; - /* user font height stack end */ -}; - -struct zr_style_mod_stack { - zr_size property; - /* current property stack pushing index */ - struct zr_saved_property properties[ZR_MAX_ATTRIB_STACK]; - /* saved property stack */ - int color; - /* current color stack pushing index */ - struct zr_saved_color colors[ZR_MAX_COLOR_STACK]; - /* saved color stack */ - int font; - /* current font stack pushing index */ - struct zr_saved_font fonts[ZR_MAX_FONT_STACK]; - /* saved user font stack */ - int font_height; - /* current font stack pushing index */ - float font_heights[ZR_MAX_FONT_HEIGHT_STACK]; - /* saved user font stack */ -}; - -struct zr_style_header { - enum zr_style_header_align align; - /* header content alignment */ - zr_rune close_symbol; - /* header close icon unicode rune */ - zr_rune minimize_symbol; - /* header minimize icon unicode rune */ - zr_rune maximize_symbol; - /* header maximize icon unicode rune */ -}; - -struct zr_style { - struct zr_user_font font; - /* the from the user provided font */ - float rounding[ZR_ROUNDING_MAX]; - /* rectangle widget rounding */ - struct zr_style_header header; - /* window header style */ - struct zr_vec2 properties[ZR_PROPERTY_MAX]; - /* configuration properties to modify the style */ - struct zr_color colors[ZR_COLOR_COUNT]; - /* configuration color to modify color */ - struct zr_style_mod_stack stack; - /* modification stack */ -}; /*=============================================================== * EDIT BOX @@ -1077,17 +521,14 @@ enum zr_edit_flags { /* edit widget allows text selection */ ZR_EDIT_CLIPBOARD = ZR_FLAG(3), /* edit widget tries to use the clipbard callback for copy & paste */ - ZR_EDIT_SIGCOMIT = ZR_FLAG(4), + ZR_EDIT_SIGCOMIT = ZR_FLAG(4) /* edit widget generateds ZR_EDIT_COMMITED event on enter */ - ZR_EDIT_MULTILINE = ZR_FLAG(5) - /* edit widget with text wrapping text editing */ }; enum zr_edit_types { ZR_EDIT_SIMPLE = 0, ZR_EDIT_FIELD = (ZR_EDIT_CURSOR|ZR_EDIT_SELECTABLE|ZR_EDIT_CLIPBOARD), - ZR_EDIT_BOX = (ZR_EDIT_CURSOR|ZR_EDIT_SELECTABLE| - ZR_EDIT_CLIPBOARD|ZR_EDIT_MULTILINE) + ZR_EDIT_BOX = (ZR_EDIT_CURSOR|ZR_EDIT_SELECTABLE| ZR_EDIT_CLIPBOARD) }; enum zr_edit_events { @@ -1103,6 +544,30 @@ enum zr_edit_events { /* edit widget has received an enter and lost focus */ }; +struct zr_text_selection { + int active; + zr_size begin; + zr_size end; +}; + +struct zr_clipboard { + zr_handle userdata; + zr_paste_f paste; + zr_copy_f copy; +}; + +struct zr_edit_box { + struct zr_buffer buffer; + int active; + zr_size cursor; + zr_size glyphs; + struct zr_clipboard clip; + zr_filter filter; + struct zr_text_selection sel; + float scrollbar; + int text_inserted; +}; + /* editbox */ void zr_edit_box_clear(struct zr_edit_box*); void zr_edit_box_add(struct zr_edit_box*, const char*, zr_size); @@ -1119,15 +584,362 @@ zr_size zr_edit_box_len(struct zr_edit_box*); int zr_edit_box_has_selection(const struct zr_edit_box*); const char *zr_edit_box_get_selection(zr_size *len, struct zr_edit_box*); -/*============================================================== - * WINDOW - * =============================================================*/ -enum zr_modify { - ZR_FIXED = zr_false, - ZR_MODIFIABLE = zr_true +/* =============================================================== + * + * RENDERING + * + * ===============================================================*/ +/* This library was designed to be render backend agnostic so it does + not draw anything to the screen. Instead all drawn primitives, widgets + are made of, are buffered into memory and make up a command queue. + Each frame therefore fills the command buffer with draw commands + that then need to be executed by the user and his own render backend. + After that the command buffer needs to be cleared and a new frame can be + started. + + The reason for buffering simple primitives as draw commands instead of + directly buffering a hardware accessible format with vertex and element + buffer was to support native render backends like X11 and Win32. + That being said it is possible to convert the command buffer into a + hardware accessible format to support hardware based rendering as well. +*/ +enum zr_command_type { + ZR_COMMAND_NOP, + ZR_COMMAND_SCISSOR, + ZR_COMMAND_LINE, + ZR_COMMAND_CURVE, + ZR_COMMAND_RECT, + ZR_COMMAND_RECT_FILLED, + ZR_COMMAND_RECT_MULTI_COLOR, + ZR_COMMAND_CIRCLE, + ZR_COMMAND_CIRCLE_FILLED, + ZR_COMMAND_ARC, + ZR_COMMAND_ARC_FILLED, + ZR_COMMAND_TRIANGLE, + ZR_COMMAND_TRIANGLE_FILLED, + ZR_COMMAND_POLYGON, + ZR_COMMAND_POLYGON_FILLED, + ZR_COMMAND_POLYLINE, + ZR_COMMAND_TEXT, + ZR_COMMAND_IMAGE }; +/* command base and header of every comand inside the buffer */ +struct zr_command { + enum zr_command_type type; + zr_size next; +#if ZR_COMPILE_WITH_COMMAND_USERDATA + zr_handle userdata; +#endif +}; + +struct zr_command_scissor { + struct zr_command header; + short x, y; + unsigned short w, h; +}; + +struct zr_command_line { + struct zr_command header; + unsigned short line_thickness; + struct zr_vec2i begin; + struct zr_vec2i end; + struct zr_color color; +}; + +struct zr_command_curve { + struct zr_command header; + unsigned short line_thickness; + struct zr_vec2i begin; + struct zr_vec2i end; + struct zr_vec2i ctrl[2]; + struct zr_color color; +}; + +struct zr_command_rect { + struct zr_command header; + unsigned short rounding; + unsigned short line_thickness; + short x, y; + unsigned short w, h; + struct zr_color color; +}; + +struct zr_command_rect_filled { + struct zr_command header; + unsigned short rounding; + short x, y; + unsigned short w, h; + struct zr_color color; +}; + +struct zr_command_rect_multi_color { + struct zr_command header; + short x, y; + unsigned short w, h; + struct zr_color left; + struct zr_color top; + struct zr_color bottom; + struct zr_color right; +}; + +struct zr_command_triangle { + struct zr_command header; + unsigned short line_thickness; + struct zr_vec2i a; + struct zr_vec2i b; + struct zr_vec2i c; + struct zr_color color; +}; + +struct zr_command_triangle_filled { + struct zr_command header; + struct zr_vec2i a; + struct zr_vec2i b; + struct zr_vec2i c; + struct zr_color color; +}; + +struct zr_command_circle { + struct zr_command header; + short x, y; + unsigned short line_thickness; + unsigned short w, h; + struct zr_color color; +}; + +struct zr_command_circle_filled { + struct zr_command header; + short x, y; + unsigned short w, h; + struct zr_color color; +}; + +struct zr_command_arc { + struct zr_command header; + short cx, cy; + unsigned short r; + unsigned short line_thickness; + float a[2]; + struct zr_color color; +}; + +struct zr_command_arc_filled { + struct zr_command header; + short cx, cy; + unsigned short r; + float a[2]; + struct zr_color color; +}; + +struct zr_command_polygon { + struct zr_command header; + struct zr_color color; + unsigned short line_thickness; + unsigned short point_count; + struct zr_vec2i points[1]; +}; + +struct zr_command_polygon_filled { + struct zr_command header; + struct zr_color color; + unsigned short point_count; + struct zr_vec2i points[1]; +}; + +struct zr_command_polyline { + struct zr_command header; + struct zr_color color; + unsigned short line_thickness; + unsigned short point_count; + struct zr_vec2i points[1]; +}; + +struct zr_command_image { + struct zr_command header; + short x, y; + unsigned short w, h; + struct zr_image img; +}; + +struct zr_command_text { + struct zr_command header; + const struct zr_user_font *font; + struct zr_color background; + struct zr_color foreground; + short x, y; + unsigned short w, h; + float height; + zr_size length; + char string[1]; +}; + +enum zr_command_clipping { + ZR_CLIPPING_OFF = zr_false, + ZR_CLIPPING_ON = zr_true +}; + +struct zr_command_buffer { + struct zr_buffer *base; + struct zr_rect clip; + int use_clipping; + zr_handle userdata; + zr_size begin, end, last; +}; + +#if ZR_COMPILE_WITH_VERTEX_BUFFER +typedef unsigned short zr_draw_index; +typedef zr_uint zr_draw_vertex_color; + +enum zr_anti_aliasing { + ZR_ANTI_ALIASING_OFF = zr_false, + ZR_ANTI_ALIASING_ON +}; + +struct zr_draw_vertex { + struct zr_vec2 position; + struct zr_vec2 uv; + zr_draw_vertex_color col; +}; +#endif + +struct zr_draw_command { + unsigned int elem_count; + /* number of elements in the current draw batch */ + struct zr_rect clip_rect; + /* current screen clipping rectangle */ + zr_handle texture; + /* current texture to set */ +#if ZR_COMPILE_WITH_COMMAND_USERDATA + zr_handle userdata; +#endif +}; + +struct zr_draw_null_texture { + zr_handle texture; + /* texture handle to a texture with a white pixel */ + struct zr_vec2 uv; + /* coordinates to a white pixel in the texture */ +}; + +/* stroking routines */ +void zr_push_scissor(struct zr_command_buffer*, struct zr_rect); +void zr_stroke_line(struct zr_command_buffer *b, float x0, float y0, + float x1, float y1, float line_thickness, struct zr_color); +void zr_stroke_curve(struct zr_command_buffer*, float, float, float, float, + float, float, float, float, float line_thickness, struct zr_color); +void zr_stroke_rect(struct zr_command_buffer*, struct zr_rect, float rounding, + float line_thickness, struct zr_color); +void zr_stroke_circle(struct zr_command_buffer*, struct zr_rect, float line_thickness, + struct zr_color); +void zr_stroke_arc(struct zr_command_buffer*, float cx, float cy, float radius, + float a_min, float a_max, float line_thickness, struct zr_color); +void zr_stroke_triangle(struct zr_command_buffer*, float, float, float, float, + float, float, float line_thichness, struct zr_color); +void zr_stroke_polyline(struct zr_command_buffer*, float *points, int point_count, + struct zr_color col); +void zr_stroke_polygon(struct zr_command_buffer*, float*, int point_count, + float line_thickness, struct zr_color); + +/* filling routines */ +void zr_fill_rect(struct zr_command_buffer*, struct zr_rect, float rounding, + struct zr_color); +void zr_fill_rect_multi_color(struct zr_command_buffer*, struct zr_rect, + struct zr_color left, struct zr_color top, + struct zr_color right, struct zr_color bottom); +void zr_fill_circle(struct zr_command_buffer*, struct zr_rect, struct zr_color); +void zr_fill_arc(struct zr_command_buffer*, float cx, float cy, float radius, + float a_min, float a_max, struct zr_color); +void zr_fill_triangle(struct zr_command_buffer*, float x0, float y0, + float x1, float y1, float x2, float y2, struct zr_color); +void zr_fill_polygon(struct zr_command_buffer*, float*, int point_count, struct zr_color); +void zr_draw_image(struct zr_command_buffer*, struct zr_rect, const struct zr_image*); +void zr_draw_text(struct zr_command_buffer*, struct zr_rect, + const char *text, zr_size len, const struct zr_user_font*, + struct zr_color, struct zr_color); + +/* =============================================================== + * + * GUI + * + * ===============================================================*/ +enum zr_keys { + ZR_KEY_SHIFT, + ZR_KEY_DEL, + ZR_KEY_ENTER, + ZR_KEY_TAB, + ZR_KEY_BACKSPACE, + ZR_KEY_COPY, + ZR_KEY_CUT, + ZR_KEY_PASTE, + ZR_KEY_UP, + ZR_KEY_DOWN, + ZR_KEY_LEFT, + ZR_KEY_RIGHT, + ZR_KEY_MAX +}; + +enum zr_buttons { + ZR_BUTTON_LEFT, + ZR_BUTTON_MIDDLE, + ZR_BUTTON_RIGHT, + ZR_BUTTON_MAX +}; + +struct zr_mouse_button { + int down; + unsigned int clicked; + struct zr_vec2 clicked_pos; +}; + +struct zr_mouse { + struct zr_mouse_button buttons[ZR_BUTTON_MAX]; + struct zr_vec2 pos; + struct zr_vec2 prev; + struct zr_vec2 delta; + float scroll_delta; +}; + +struct zr_key { + int down; + unsigned int clicked; +}; + +struct zr_keyboard { + struct zr_key keys[ZR_KEY_MAX]; + char text[ZR_INPUT_MAX]; + zr_size text_len; +}; + +struct zr_input { + struct zr_keyboard keyboard; + struct zr_mouse mouse; +}; + +int zr_input_has_mouse_click_in_rect(const struct zr_input*, + enum zr_buttons, struct zr_rect); +int zr_input_has_mouse_click_down_in_rect(const struct zr_input*, enum zr_buttons, + struct zr_rect, int down); +int zr_input_is_mouse_click_in_rect(const struct zr_input*, + enum zr_buttons, struct zr_rect); +int zr_input_is_mouse_click_down_in_rect(const struct zr_input *i, enum zr_buttons id, + struct zr_rect b, int down); +int zr_input_any_mouse_click_in_rect(const struct zr_input*, struct zr_rect); +int zr_input_is_mouse_prev_hovering_rect(const struct zr_input*, struct zr_rect); +int zr_input_is_mouse_hovering_rect(const struct zr_input*, struct zr_rect); +int zr_input_mouse_clicked(const struct zr_input*, enum zr_buttons, struct zr_rect); +int zr_input_is_mouse_down(const struct zr_input*, enum zr_buttons); +int zr_input_is_mouse_pressed(const struct zr_input*, enum zr_buttons); +int zr_input_is_mouse_released(const struct zr_input*, enum zr_buttons); +int zr_input_is_key_pressed(const struct zr_input*, enum zr_keys); +int zr_input_is_key_released(const struct zr_input*, enum zr_keys); +int zr_input_is_key_down(const struct zr_input*, enum zr_keys); + +/* ============================================================== + * STYLE + * ===============================================================*/ enum zr_symbol_type { + ZR_SYMBOL_NONE, ZR_SYMBOL_X, ZR_SYMBOL_UNDERSCORE, ZR_SYMBOL_CIRCLE, @@ -1143,6 +955,510 @@ enum zr_symbol_type { ZR_SYMBOL_MAX }; +enum zr_style_item_type { + ZR_STYLE_ITEM_COLOR, + ZR_STYLE_ITEM_IMAGE +}; + +union zr_style_item_data { + struct zr_image image; + struct zr_color color; +}; + +struct zr_style_item { + enum zr_style_item_type type; + union zr_style_item_data data; +}; + +struct zr_style_text { + struct zr_color color; + struct zr_vec2 padding; +}; + +struct zr_style_button; +struct zr_style_custom_button_drawing { + void(*button_text)(struct zr_command_buffer*, + const struct zr_rect *background, const struct zr_rect*, + zr_flags state, const struct zr_style_button*, + const char*, zr_size len, zr_flags text_alignment, + const struct zr_user_font*); + void(*button_symbol)(struct zr_command_buffer*, + const struct zr_rect *background, const struct zr_rect*, + zr_flags state, const struct zr_style_button*, + enum zr_symbol_type, const struct zr_user_font*); + void(*button_image)(struct zr_command_buffer*, + const struct zr_rect *background, const struct zr_rect*, + zr_flags state, const struct zr_style_button*, + const struct zr_image *img); + void(*button_text_symbol)(struct zr_command_buffer*, + const struct zr_rect *background, const struct zr_rect*, + const struct zr_rect *symbol, zr_flags state, + const struct zr_style_button*, + const char *text, zr_size len, zr_flags align, + enum zr_symbol_type, const struct zr_user_font*); + void(*button_text_image)(struct zr_command_buffer*, + const struct zr_rect *background, const struct zr_rect*, + const struct zr_rect *image, zr_flags state, + const struct zr_style_button*, + const char *text, zr_size len, zr_flags align, const struct zr_user_font*, + const struct zr_image *img); +}; + +struct zr_style_button { + /* background */ + struct zr_style_item normal; + struct zr_style_item hover; + struct zr_style_item active; + struct zr_color border_color; + + /* text */ + struct zr_color text_background; + struct zr_color text_normal; + struct zr_color text_hover; + struct zr_color text_active; + zr_flags text_alignment; + + /* properties */ + float border; + float rounding; + float fixed_width; + float fixed_height; + int has_fixed_size; + struct zr_vec2 padding; + struct zr_vec2 image_padding; + struct zr_vec2 touch_padding; + + /* optional user callbacks */ + zr_handle userdata; + void(*draw_begin)(struct zr_command_buffer*, zr_handle userdata); + struct zr_style_custom_button_drawing draw; + void(*draw_end)(zr_handle, struct zr_command_buffer*, zr_handle userdata); +}; + +struct zr_style_toggle; +union zr_style_custom_toggle_drawing { + void(*radio)(struct zr_command_buffer*, zr_flags state, + const struct zr_style_toggle *toggle, int active, + const struct zr_rect *label, const struct zr_rect *selector, + const struct zr_rect *cursor, const char *string, zr_size len, + const struct zr_user_font *font); + void(*checkbox)(struct zr_command_buffer*, zr_flags state, + const struct zr_style_toggle *toggle, int active, + const struct zr_rect *label, const struct zr_rect *selector, + const struct zr_rect *cursor, const char *string, zr_size len, + const struct zr_user_font *font); +}; + +struct zr_style_toggle { + /* background */ + struct zr_style_item normal; + struct zr_style_item hover; + struct zr_style_item active; + + /* cursor */ + struct zr_style_item cursor_normal; + struct zr_style_item cursor_hover; + + /* text */ + struct zr_color text_normal; + struct zr_color text_hover; + struct zr_color text_active; + struct zr_color text_background; + zr_flags text_alignment; + + /* properties */ + float fixed_width; + float fixed_height; + int has_fixed_size; + struct zr_vec2 padding; + struct zr_vec2 touch_padding; + + /* optional user callbacks */ + zr_handle userdata; + void(*draw_begin)(struct zr_command_buffer*, zr_handle); + union zr_style_custom_toggle_drawing draw; + void(*draw_end)(struct zr_command_buffer*, zr_handle); +}; + +struct zr_style_selectable { + /* background (inactive) */ + struct zr_style_item normal; + struct zr_style_item hover; + struct zr_style_item pressed; + + /* background (active) */ + struct zr_style_item normal_active; + struct zr_style_item hover_active; + struct zr_style_item pressed_active; + + /* text color (inactive) */ + struct zr_color text_normal; + struct zr_color text_hover; + struct zr_color text_pressed; + + /* text color (active) */ + struct zr_color text_normal_active; + struct zr_color text_hover_active; + struct zr_color text_pressed_active; + struct zr_color text_background; + zr_flags text_alignment; + + /* properties */ + float fixed_width; + float fixed_height; + float rounding; + int has_fixed_size; + struct zr_vec2 padding; + struct zr_vec2 touch_padding; + + /* optional user callbacks */ + zr_handle userdata; + void(*draw_begin)(struct zr_command_buffer*, zr_handle); + void(*draw)(struct zr_command_buffer*, + zr_flags state, const struct zr_style_selectable*, int active, + const struct zr_rect*, const char *string, zr_size len, + zr_flags align, const struct zr_user_font*); + void(*draw_end)(struct zr_command_buffer*, zr_handle); +}; + +struct zr_style_slider { + /* background */ + struct zr_style_item normal; + struct zr_style_item hover; + struct zr_style_item active; + struct zr_color border_color; + + /* background bar */ + struct zr_color bar_normal; + struct zr_color bar_hover; + struct zr_color bar_active; + struct zr_color bar_filled; + + /* cursor */ + struct zr_style_item cursor_normal; + struct zr_style_item cursor_hover; + struct zr_style_item cursor_active; + + /* properties */ + float border; + float rounding; + float bar_height; + struct zr_vec2 padding; + struct zr_vec2 spacing; + struct zr_vec2 cursor_size; + + int has_fixed_size; + float fixed_width; + float fixed_height; + + /* optional buttons */ + int show_buttons; + struct zr_style_button inc_button; + struct zr_style_button dec_button; + enum zr_symbol_type inc_symbol; + enum zr_symbol_type dec_symbol; + + /* optional user callbacks */ + zr_handle userdata; + void(*draw_begin)(struct zr_command_buffer*, zr_handle); + void(*draw)(struct zr_command_buffer*, zr_flags state, + const struct zr_style_slider*, const struct zr_rect *bar, + const struct zr_rect *cursor, float min, float value, float max); + void(*draw_end)(struct zr_command_buffer*); +}; + +struct zr_style_progress { + /* background */ + struct zr_style_item normal; + struct zr_style_item hover; + struct zr_style_item active; + + /* cursor */ + struct zr_style_item cursor_normal; + struct zr_style_item cursor_hover; + struct zr_style_item cursor_active; + + /* properties */ + float rounding; + float fixed_width; + float fixed_height; + int has_fixed_size; + struct zr_vec2 padding; + + /* optional user callbacks */ + zr_handle userdata; + void(*draw_begin)(struct zr_command_buffer*, zr_handle); + void(*draw)(struct zr_command_buffer*, zr_flags state, + const struct zr_style_progress*, const struct zr_rect *bounds, + const struct zr_rect *cursor, zr_size value, zr_size max); + void(*draw_end)(struct zr_command_buffer*); +}; + +struct zr_style_scrollbar { + /* background */ + struct zr_style_item normal; + struct zr_style_item hover; + struct zr_style_item active; + struct zr_color border_color; + + /* cursor */ + struct zr_style_item cursor_normal; + struct zr_style_item cursor_hover; + struct zr_style_item cursor_active; + + /* properties */ + float border; + float rounding; + struct zr_vec2 padding; + + /* optional buttons */ + int show_buttons; + struct zr_style_button inc_button; + struct zr_style_button dec_button; + enum zr_symbol_type inc_symbol; + enum zr_symbol_type dec_symbol; + + /* optional user callbacks */ + zr_handle userdata; + void(*draw_begin)(struct zr_command_buffer*, zr_handle); + void(*draw)(struct zr_command_buffer*, zr_flags state, + const struct zr_style_scrollbar*, const struct zr_rect *scroll, + const struct zr_rect *cursor); + void(*draw_end)(struct zr_command_buffer*, zr_handle); +}; + +struct zr_style_edit { + /* background */ + struct zr_style_item normal; + struct zr_style_item hover; + struct zr_style_item active; + struct zr_color border_color; + + /* cursor */ + struct zr_style_item cursor_normal; + struct zr_style_item cursor_hover; + struct zr_style_item cursor_active; + + /* text (unselected) */ + struct zr_color text_normal; + struct zr_color text_hover; + struct zr_color text_active; + + /* text (selected) */ + struct zr_color selected_normal; + struct zr_color selected_hover; + struct zr_color selected_text_normal; + struct zr_color selected_text_hover; + + /* properties */ + float border; + float rounding; + float cursor_size; + float fixed_width; + float fixed_height; + int has_fixed_size; + struct zr_vec2 padding; + + /* optional user callbacks */ + zr_handle userdata; + void(*draw_begin)(struct zr_command_buffer*,zr_handle); + void(*draw)(struct zr_command_buffer*, zr_flags state, + const struct zr_style_edit*, const struct zr_rect *bounds, + const struct zr_rect *label, const struct zr_rect *selection, + int show_cursor, const char *unselected_text, zr_size unselected_len, + const char *selected_text, zr_size selected_len, + const struct zr_edit_box*, const struct zr_user_font*); + void(*draw_end)(struct zr_command_buffer*,zr_handle); +}; + +struct zr_style_property { + /* background */ + struct zr_style_item normal; + struct zr_style_item hover; + struct zr_style_item active; + struct zr_color border_color; + + /* text */ + struct zr_color label_normal; + struct zr_color label_hover; + struct zr_color label_active; + + /* symbols */ + enum zr_symbol_type sym_left; + enum zr_symbol_type sym_right; + + /* properties */ + float border; + float rounding; + int has_fixed_size; + float fixed_width; + float fixed_height; + struct zr_vec2 padding; + + struct zr_style_edit edit; + struct zr_style_button inc_button; + struct zr_style_button dec_button; + + /* optional user callbacks */ + zr_handle userdata; + void(*draw_begin)(struct zr_command_buffer*, zr_handle); + void(*draw)(struct zr_command_buffer*, const struct zr_style_property*, + const struct zr_rect*, const struct zr_rect *label, zr_flags state, + const char *name, zr_size len, const struct zr_user_font*); + void(*draw_end)(struct zr_command_buffer*, zr_handle); +}; + +struct zr_style_chart { + /* colors */ + struct zr_style_item background; + struct zr_color border_color; + struct zr_color selected_color; + struct zr_color color; + + /* properties */ + float border; + float rounding; + int has_fixed_size; + float fixed_width; + float fixed_height; + struct zr_vec2 padding; +}; + +struct zr_style_combo { + /* background */ + struct zr_style_item normal; + struct zr_style_item hover; + struct zr_style_item active; + struct zr_color border_color; + + /* label */ + struct zr_color label_normal; + struct zr_color label_hover; + struct zr_color label_active; + + /* symbol */ + struct zr_color symbol_normal; + struct zr_color symbol_hover; + struct zr_color symbol_active; + + /* button */ + struct zr_style_button button; + enum zr_symbol_type sym_normal; + enum zr_symbol_type sym_hover; + enum zr_symbol_type sym_active; + + /* properties */ + float border; + float rounding; + int has_fixed_size; + float fixed_width; + float fixed_height; + struct zr_vec2 content_padding; + struct zr_vec2 button_padding; + struct zr_vec2 spacing; +}; + +struct zr_style_tab { + struct zr_style_item background; + struct zr_color border_color; + struct zr_color text; + + struct zr_style_button tab_button; + struct zr_style_button node_button; + enum zr_symbol_type sym_minimize; + enum zr_symbol_type sym_maximize; + + float border; + float rounding; + struct zr_vec2 padding; + struct zr_vec2 spacing; +}; + +enum zr_style_header_align { + ZR_HEADER_LEFT, + ZR_HEADER_RIGHT +}; + +struct zr_style_window_header { + /* background */ + struct zr_style_item normal; + struct zr_style_item hover; + struct zr_style_item active; + + /* button */ + struct zr_style_button close_button; + struct zr_style_button minimize_button; + enum zr_symbol_type close_symbol; + enum zr_symbol_type minimize_symbol; + enum zr_symbol_type maximize_symbol; + + /* title */ + struct zr_color label_normal; + struct zr_color label_hover; + struct zr_color label_active; + + /* properties */ + enum zr_style_header_align align; + struct zr_vec2 padding; + struct zr_vec2 label_padding; + struct zr_vec2 spacing; +}; + +struct zr_style_window { + struct zr_style_window_header header; + struct zr_style_item fixed_background; + struct zr_color background; + struct zr_color border_color; + + struct zr_style_item scaler; + struct zr_vec2 footer_padding; + + float border; + float rounding; + int has_fixed_size; + float fixed_width; + float fixed_height; + struct zr_vec2 scaler_size; + struct zr_vec2 padding; + struct zr_vec2 spacing; + struct zr_vec2 scrollbar_size; + struct zr_vec2 min_size; +}; + +struct zr_style { + struct zr_user_font font; + struct zr_style_text text; + struct zr_style_button button; + struct zr_style_button contextual_button; + struct zr_style_button menu_button; + struct zr_style_toggle option; + struct zr_style_toggle checkbox; + struct zr_style_selectable selectable; + struct zr_style_slider slider; + struct zr_style_progress progress; + struct zr_style_property property; + struct zr_style_edit edit; + struct zr_style_chart line_chart; + struct zr_style_chart column_chart; + struct zr_style_scrollbar scrollh; + struct zr_style_scrollbar scrollv; + struct zr_style_tab tab; + struct zr_style_combo combo; + struct zr_style_window window; +}; + +struct zr_style_item zr_style_item_image(struct zr_image img); +struct zr_style_item zr_style_item_color(struct zr_color); +struct zr_style_item zr_style_item_hide(void); + +/*============================================================== + * PANEL + * =============================================================*/ +enum zr_modify { + ZR_FIXED = zr_false, + ZR_MODIFIABLE = zr_true +}; + enum zr_orientation { ZR_VERTICAL, ZR_HORIZONTAL @@ -1158,148 +1474,91 @@ enum zr_show_states { ZR_SHOWN = zr_true }; -enum zr_widget_state { +/* widget states */ +enum zr_widget_states { + ZR_WIDGET_STATE_INACTIVE = ZR_FLAG(0), + /* widget is neither active nor hovered */ + ZR_WIDGET_STATE_ENTERED = ZR_FLAG(1), + /* widget has been hovered on the current frame */ + ZR_WIDGET_STATE_HOVERED = ZR_FLAG(2), + /* widget is being hovered */ + ZR_WIDGET_STATE_LEFT = ZR_FLAG(3), + /* widget is from this frame on not hovered anymore */ + ZR_WIDGET_STATE_ACTIVE = ZR_FLAG(4) + /* widget is currently activated */ +}; + +enum zr_widget_layout_states { ZR_WIDGET_INVALID, /* The widget cannot be seen and is completly out of view */ ZR_WIDGET_VALID, - /* The widget is completly inside the window can be updated */ + /* The widget is completly inside the window and can be updated and drawn */ ZR_WIDGET_ROM /* The widget is partially visible and cannot be updated */ }; +/* text alignment */ enum zr_text_align { - ZR_TEXT_LEFT = 0x01, - /* text is aligned on the left (X-axis)*/ - ZR_TEXT_CENTERED = 0x02, - /* text is aligned in the center (X-axis)*/ - ZR_TEXT_RIGHT = 0x04, - /* text is aligned on the right (X-axis)*/ - ZR_TEXT_TOP = 0x08, - /* text is aligned to the top (Y-axis)*/ - ZR_TEXT_MIDDLE = 0x10, - /* text is aligned to the middle (Y-axis) */ - ZR_TEXT_BOTTOM = 0x20, - /* text is aligned to the bottom (Y-axis)*/ - ZR_TEXT_DEFAULT_CENTER = ZR_TEXT_CENTERED|ZR_TEXT_MIDDLE, - /* default center alignment with text centered both in X-and Y-axis */ - ZR_TEXT_DEFAULT_LEFT = ZR_TEXT_LEFT|ZR_TEXT_MIDDLE, - /* default left alignment with text centered left in X-and and center Y-axis */ - ZR_TEXT_DEFAULT_RIGHT = ZR_TEXT_RIGHT|ZR_TEXT_MIDDLE - /* default right alignment with text centered right in X-and and center Y-axis */ + ZR_TEXT_ALIGN_LEFT = 0x01, + ZR_TEXT_ALIGN_CENTERED = 0x02, + ZR_TEXT_ALIGN_RIGHT = 0x04, + ZR_TEXT_ALIGN_TOP = 0x08, + ZR_TEXT_ALIGN_MIDDLE = 0x10, + ZR_TEXT_ALIGN_BOTTOM = 0x20 +}; +enum zr_text_alignment { + ZR_TEXT_CENTERED = ZR_TEXT_ALIGN_MIDDLE|ZR_TEXT_ALIGN_CENTERED, + ZR_TEXT_LEFT = ZR_TEXT_ALIGN_MIDDLE|ZR_TEXT_ALIGN_LEFT, + ZR_TEXT_RIGHT = ZR_TEXT_ALIGN_MIDDLE|ZR_TEXT_ALIGN_RIGHT }; enum zr_button_behavior { ZR_BUTTON_DEFAULT, - /* default push button behavior */ ZR_BUTTON_REPEATER - /* repeater behavior will trigger as long as button is down */ }; enum zr_chart_type { ZR_CHART_LINES, - /* Line chart with data points connected by lines */ ZR_CHART_COLUMN, - /* Histogram with value represented as bars */ ZR_CHART_MAX }; enum zr_chart_event { ZR_CHART_HOVERING = 0x01, - /* mouse hoveres over current value */ ZR_CHART_CLICKED = 0x02 - /* mouse click on current value */ }; enum zr_color_picker_format { - ZR_RGB, - ZR_RGBA + ZR_RGB = 0, + ZR_RGBA = 1 }; enum zr_popup_type { ZR_POPUP_STATIC, - /* static fixed height non growing popup */ ZR_POPUP_DYNAMIC - /* dynamically growing popup with maximum height */ }; enum zr_layout_format { - ZR_DYNAMIC, /* row layout which scales with the window */ - ZR_STATIC /* row layout with fixed pixel width */ + ZR_DYNAMIC, + ZR_STATIC }; enum zr_layout_node_type { ZR_LAYOUT_NODE, - /* a node is a space which can be minimized or maximized */ ZR_LAYOUT_TAB - /* a tab is a node with a header */ }; struct zr_chart { + const struct zr_style_chart *style; enum zr_chart_type type; - /* chart type with either line or column chart */ - float x, y; - /* chart canvas space position */ - float w, h; - /* chart canvas space size */ - float min, max, range; - /* min and max value for correct scaling of values */ - struct zr_vec2 last; - /* last line chart point to connect to. Only used by the line chart */ - int index; - /* current chart value index*/ - int count; - /* number of values inside the chart */ -}; - -enum zr_row_layout_type { - ZR_LAYOUT_DYNAMIC_FIXED, - /* fixed widget ratio width window layout */ - ZR_LAYOUT_DYNAMIC_ROW, - /* immediate mode widget specific widget width ratio layout */ - ZR_LAYOUT_DYNAMIC_FREE, - /* free ratio based placing of widget in a local space */ - ZR_LAYOUT_DYNAMIC, - /* retain mode widget specific widget ratio width*/ - ZR_LAYOUT_STATIC_FIXED, - /* fixed widget pixel width window layout */ - ZR_LAYOUT_STATIC_ROW, - /* immediate mode widget specific widget pixel width layout */ - ZR_LAYOUT_STATIC_FREE, - /* free pixel based placing of widget in a local space */ - ZR_LAYOUT_STATIC - /* retain mode widget specific widget pixel width layout */ -}; - -struct zr_row_layout { - enum zr_row_layout_type type; - /* type of the row layout */ - int index; - /* index of the current widget in the current window row */ - float height; - /* height of the current row */ - int columns; - /* number of columns in the current row */ - const float *ratio; - /* row widget width ratio */ - float item_width, item_height; - /* current width of very item */ - float item_offset; - /* x positon offset of the current item */ - float filled; - /* total fill ratio */ - struct zr_rect item; - /* item bounds */ - int tree_depth; -}; - -struct zr_menu { float x, y, w, h; - /* menu bounds */ - struct zr_scroll offset; - /* saved window scrollbar offset */ + float min, max, range; + struct zr_vec2 last; + int index; + int count; }; -enum zr_window_flags { +enum zr_panel_flags { ZR_WINDOW_BORDER = ZR_FLAG(0), /* Draws a border around the window to visually seperate the window * from the background */ @@ -1325,106 +1584,186 @@ enum zr_window_flags { /* Forces a header at the top at the window showing the title */ }; +struct zr_row_layout { + int type; + int index; + float height; + int columns; + const float *ratio; + float item_width, item_height; + float item_offset; + float filled; + struct zr_rect item; + int tree_depth; +}; + struct zr_popup_buffer { zr_size begin; - /* begin of the subbuffer */ zr_size parent; - /* last entry before the sub buffer*/ zr_size last; - /* last entry in the sub buffer*/ zr_size end; - /* end of the subbuffer */ int active; }; +struct zr_menu_state { + float x, y, w, h; + struct zr_scroll offset; +}; + struct zr_panel { zr_flags flags; - /* window flags modifing its behavior */ struct zr_rect bounds; - /* position and size of the window in the os window */ struct zr_scroll *offset; - /* window scrollbar offset */ float at_x, at_y, max_x; - /* index position of the current widget row and column */ float width, height; - /* size of the actual useable space inside the window */ float footer_h; - /* height of the window footer space */ float header_h; - /* height of the window footer space */ struct zr_rect clip; - /* window clipping rect */ - struct zr_menu menu; - /* window menubar bounds */ + struct zr_menu_state menu; struct zr_row_layout row; - /* currently used window row layout */ struct zr_chart chart; - /* chart state */ struct zr_popup_buffer popup_buffer; - /* output command buffer queuing all popup drawing calls */ struct zr_command_buffer *buffer; struct zr_panel *parent; }; /*============================================================== - * CONTEXT + * WINDOW * =============================================================*/ -struct zr_clipboard { - zr_handle userdata; - /* user memory for callback */ - zr_paste_f paste; - /* paste callback for the edit box */ - zr_copy_f copy; - /* copy callback for the edit box */ +enum zr_window_flags { + ZR_WINDOW_PRIVATE = ZR_FLAG(9), + /* dummy flag which mark the beginning of the private window flag part */ + ZR_WINDOW_ROM = ZR_FLAG(10), + /* sets the window into a read only mode and does not allow input changes */ + ZR_WINDOW_HIDDEN = ZR_FLAG(11), + /* Hiddes the window and stops any window interaction and drawing can be set + * by user input or by closing the window */ + ZR_WINDOW_MINIMIZED = ZR_FLAG(12), + /* marks the window as minimized */ + ZR_WINDOW_SUB = ZR_FLAG(13), + /* Marks the window as subwindow of another window*/ + ZR_WINDOW_GROUP = ZR_FLAG(14), + /* Marks the window as window widget group */ + ZR_WINDOW_POPUP = ZR_FLAG(15), + /* Marks the window as a popup window */ + ZR_WINDOW_NONBLOCK = ZR_FLAG(16), + /* Marks the window as a nonblock popup window */ + ZR_WINDOW_CONTEXTUAL = ZR_FLAG(17), + /* Marks the window as a combo box or menu */ + ZR_WINDOW_COMBO = ZR_FLAG(18), + /* Marks the window as a combo box */ + ZR_WINDOW_MENU = ZR_FLAG(19), + /* Marks the window as a menu */ + ZR_WINDOW_TOOLTIP = ZR_FLAG(20), + /* Marks the window as a menu */ + ZR_WINDOW_REMOVE_ROM = ZR_FLAG(21) + /* Removes the read only mode at the end of the window */ }; +struct zr_popup_state { + struct zr_window *win; + enum zr_window_flags type; + zr_hash name; + int active; + unsigned combo_count; + unsigned con_count, con_old; + unsigned active_con; +}; + +struct zr_edit_state { + zr_hash name; + zr_size cursor; + struct zr_text_selection sel; + float scrollbar; + unsigned int seq; + unsigned int old; + int active, prev; +}; + +struct zr_combo_filter_state { + zr_hash name; + char filter[ZR_MAX_COMBO_EDIT_BUFFER]; + zr_size length; + zr_size cursor; + unsigned int seq; + unsigned int old; + int active, prev; +}; + +struct zr_property_state { + int active, prev; + char buffer[ZR_MAX_NUMBER_BUFFER]; + zr_size length; + zr_size cursor; + zr_hash name; + unsigned int seq; + unsigned int old; + int state; +}; + +struct zr_table; +struct zr_window { + zr_hash name; + unsigned int seq; + struct zr_rect bounds; + zr_flags flags; + struct zr_scroll scrollbar; + struct zr_command_buffer buffer; + struct zr_panel *layout; + + /* persistent widget state */ + struct zr_property_state property; + struct zr_popup_state popup; + struct zr_edit_state edit; + struct zr_combo_filter_state combo; + + struct zr_table *tables; + unsigned short table_count; + unsigned short table_size; + + /* window list hooks */ + struct zr_window *next; + struct zr_window *prev; + struct zr_window *parent; +}; + +/*============================================================== + * CONTEXT + * =============================================================*/ #if ZR_COMPILE_WITH_VERTEX_BUFFER struct zr_convert_config { float global_alpha; - /* global alpha modifier */ - float line_thickness; - /* line thickness should generally default to 1*/ + /* line thickness mininum: 1*/ enum zr_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are thight on memory */ enum zr_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are thight on memory */ unsigned int circle_segment_count; - /* number of segments used for circle and curves: default to 22 */ + /* number of segments used for circles: default to 22 */ + unsigned int arc_segment_count; + /* number of segments used for arcs: default to 22 */ + unsigned int curve_segment_count; + /* number of segments used for curves: default to 22 */ struct zr_draw_null_texture null; - /* handle to texture with a white pixel to draw text */ + /* handle to texture with a white pixel to draw shapes */ }; struct zr_canvas { float global_alpha; - /* alpha modifier for all shapes */ enum zr_anti_aliasing shape_AA; - /* flag indicating if anti-aliasing should be used to render shapes */ enum zr_anti_aliasing line_AA; - /* flag indicating if anti-aliasing should be used to render lines */ struct zr_draw_null_texture null; - /* texture with white pixel for easy primitive drawing */ struct zr_rect clip_rect; - /* current clipping rectangle */ struct zr_buffer *buffer; - /* buffer to store draw commands and temporarily store path */ struct zr_buffer *vertices; - /* buffer to store each draw vertex */ struct zr_buffer *elements; - /* buffer to store each draw element index */ unsigned int element_count; - /* total number of elements inside the elements buffer */ unsigned int vertex_count; - /* total number of vertices inside the vertex buffer */ zr_size cmd_offset; - /* offset to the first command in the buffer */ unsigned int cmd_count; - /* number of commands inside the buffer */ unsigned int path_count; - /* current number of points inside the path */ unsigned int path_offset; - /* offset to the first point in the buffer */ struct zr_vec2 circle_vtx[12]; - /* small lookup table for fast circle drawing */ #if ZR_COMPILE_WITH_COMMAND_USERDATA zr_handle userdata; #endif @@ -1432,16 +1771,16 @@ struct zr_canvas { #endif struct zr_context { -/* public: - * can be freely accessed + modified */ +/* public: can be accessed freely */ struct zr_input input; struct zr_style style; struct zr_buffer memory; struct zr_clipboard clip; + zr_flags last_widget_state; /* private: - * should only be modifed if you - * know what you are doing*/ + should only be accessed if you + know what you are doing */ #if ZR_COMPILE_WITH_VERTEX_BUFFER struct zr_canvas canvas; #endif @@ -1449,10 +1788,6 @@ struct zr_context { zr_handle userdata; #endif - /* recording */ - struct zr_buffer *op_buffer; - struct zr_buffer op_memory; - /* windows */ int build; void *pool; @@ -1487,6 +1822,7 @@ int zr_begin(struct zr_context*, struct zr_panel*, const char *title, struct zr_rect bounds, zr_flags flags); void zr_end(struct zr_context*); +struct zr_window* zr_window_find(struct zr_context *ctx, const char *name); struct zr_rect zr_window_get_bounds(const struct zr_context*); struct zr_vec2 zr_window_get_position(const struct zr_context*); struct zr_vec2 zr_window_get_size(const struct zr_context*); @@ -1521,7 +1857,6 @@ void zr_window_show_if(struct zr_context*, const char *name, /*-------------------------------------------------------------- * DRAWING * -------------------------------------------------------------*/ -/* command drawing */ #define zr_command(t, c) ((const struct zr_command_##t*)c) #define zr_foreach(c, ctx) for((c)=zr__begin(ctx); (c)!=0; (c)=zr__next(ctx, c)) const struct zr_command* zr__next(struct zr_context*, const struct zr_command*); @@ -1556,41 +1891,17 @@ void zr_input_end(struct zr_context*); /*-------------------------------------------------------------- * STYLE * -------------------------------------------------------------*/ -void zr_load_default_style(struct zr_context*, zr_flags); -void zr_set_font(struct zr_context*, const struct zr_user_font*); -struct zr_vec2 zr_get_property(const struct zr_context*, enum zr_style_properties); -struct zr_color zr_get_color(const struct zr_context*, enum zr_style_colors); -const char *zr_get_color_name(enum zr_style_colors); -const char *zr_get_rounding_name(enum zr_style_rounding); -const char *zr_get_property_name(enum zr_style_properties); - -/* temporarily modify a style value and save the old value in a stack*/ -void zr_push_property(struct zr_context*, enum zr_style_properties, struct zr_vec2); -void zr_push_color(struct zr_context*, enum zr_style_colors, struct zr_color); -void zr_push_font(struct zr_context*, struct zr_user_font font); -void zr_push_font_height(struct zr_context*, float font_height); - -/* restores a previously saved style value */ -void zr_pop_color(struct zr_context*); -void zr_pop_property(struct zr_context*); -void zr_pop_font(struct zr_context*); -void zr_pop_font_height(struct zr_context*); - -/* resets the style back into the beginning state */ -void zr_reset_colors(struct zr_context*); -void zr_reset_properties(struct zr_context*); -void zr_reset_font(struct zr_context*); -void zr_reset_font_height(struct zr_context*); -void zr_reset(struct zr_context*); +void zr_style_default(struct zr_context*); +void zr_style_set_font(struct zr_context*, const struct zr_user_font*); /*-------------------------------------------------------------- * LAYOUT * -------------------------------------------------------------*/ -/* columns based layouting with generated position and width and fixed height*/ +/* columns layouting with generated position, width and fixed height */ void zr_layout_row_dynamic(struct zr_context*, float height, int cols); void zr_layout_row_static(struct zr_context*, float height, int item_width, int cols); -/* widget layouting with custom widget width and fixed height */ +/* custom widget width and fixed height */ void zr_layout_row_begin(struct zr_context*, enum zr_layout_format, float row_height, int cols); void zr_layout_row_push(struct zr_context*, float value); @@ -1598,12 +1909,13 @@ void zr_layout_row_end(struct zr_context*); void zr_layout_row(struct zr_context*, enum zr_layout_format, float height, int cols, const float *ratio); -/* layouting with custom position and size of widgets */ +/* custom position and size of widgets */ void zr_layout_space_begin(struct zr_context*, enum zr_layout_format, float height, int widget_count); void zr_layout_space_push(struct zr_context*, struct zr_rect); void zr_layout_space_end(struct zr_context*); +/* utility functions */ struct zr_rect zr_layout_space_bounds(struct zr_context*); struct zr_vec2 zr_layout_space_to_screen(struct zr_context*, struct zr_vec2); struct zr_vec2 zr_layout_space_to_local(struct zr_context*, struct zr_vec2); @@ -1615,17 +1927,19 @@ int zr_group_begin(struct zr_context*, struct zr_panel*, const char *title, zr_f void zr_group_end(struct zr_context*); /* tree layout */ -int zr_layout_push(struct zr_context*, enum zr_layout_node_type, const char *title, - enum zr_collapse_states initial_state); +#define zr_layout_push(ctx, type, title, state)\ + zr__layout_push(ctx, type, title, state, __FILE__,__LINE__) +int zr__layout_push(struct zr_context*, enum zr_layout_node_type, const char *title, + enum zr_collapse_states initial_state, const char *file, int line); void zr_layout_pop(struct zr_context*); /*-------------------------------------------------------------- * WIDGETS * -------------------------------------------------------------*/ /* base widget calls for custom widgets */ -enum zr_widget_state zr_widget(struct zr_rect*, const struct zr_context*); -enum zr_widget_state zr_widget_fitting(struct zr_rect*, struct zr_context*); - +enum zr_widget_layout_states zr_widget(struct zr_rect*, const struct zr_context*); +enum zr_widget_layout_states zr_widget_fitting(struct zr_rect*, struct zr_context*, + struct zr_vec2 item_padding); /* utilities (working on the next widget) */ struct zr_rect zr_widget_bounds(struct zr_context*); struct zr_vec2 zr_widget_position(struct zr_context*); @@ -1634,7 +1948,6 @@ int zr_widget_is_hovered(struct zr_context*); int zr_widget_is_mouse_clicked(struct zr_context*, enum zr_buttons); int zr_widget_has_mouse_click_down(struct zr_context*, enum zr_buttons, int down); void zr_spacing(struct zr_context*, int cols); -void zr_seperator(struct zr_context*); /* content output widgets */ void zr_text(struct zr_context*, const char*, zr_size, zr_flags); @@ -1648,39 +1961,56 @@ void zr_label_wrap(struct zr_context*, const char*); void zr_label_colored_wrap(struct zr_context*, const char*, struct zr_color); void zr_image(struct zr_context*, struct zr_image); -/* toggle value */ -int zr_check(struct zr_context*, const char*, int active); -int zr_checkbox(struct zr_context*, const char*, int *active); -void zr_radio(struct zr_context*, const char*, int *active); -int zr_option(struct zr_context*, const char*, int active); -int zr_selectable(struct zr_context*, const char*, zr_flags alignment, int *value); -int zr_select(struct zr_context*, const char*, zr_flags alignment, int value); - /* buttons */ -int zr_button_text(struct zr_context *ctx, const char *title, enum zr_button_behavior); +int zr_button_text(struct zr_context *ctx, const char *title, zr_size len, enum zr_button_behavior); +int zr_button_label(struct zr_context *ctx, const char *title, enum zr_button_behavior); int zr_button_color(struct zr_context*, struct zr_color, enum zr_button_behavior); int zr_button_symbol(struct zr_context*, enum zr_symbol_type, enum zr_button_behavior); int zr_button_image(struct zr_context*, struct zr_image img, enum zr_button_behavior); -int zr_button_text_symbol(struct zr_context*, enum zr_symbol_type, const char*, +int zr_button_symbol_label(struct zr_context*, enum zr_symbol_type, const char*, zr_flags text_alignment, enum zr_button_behavior); -int zr_button_text_image(struct zr_context*, struct zr_image img, const char*, +int zr_button_symbol_text(struct zr_context*, enum zr_symbol_type, const char*, + zr_size, zr_flags alignment, enum zr_button_behavior); +int zr_button_image_label(struct zr_context*, struct zr_image img, const char*, zr_flags text_alignment, enum zr_button_behavior); +int zr_button_image_text(struct zr_context*, struct zr_image img, const char*, + zr_size, zr_flags alignment, enum zr_button_behavior); -/* simple value modifier by sliding */ -int zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable); -zr_size zr_prog(struct zr_context*, zr_size cur, zr_size max, int modifyable); +/* checkbox */ +int zr_check_label(struct zr_context*, const char*, int active); +int zr_check_text(struct zr_context*, const char*, zr_size,int active); +int zr_checkbox_label(struct zr_context*, const char*, int *active); +int zr_checkbox_text(struct zr_context*, const char*, zr_size, int *active); + +/* radio button */ +int zr_radio_label(struct zr_context*, const char*, int *active); +int zr_radio_text(struct zr_context*, const char*, zr_size, int *active); +int zr_option_label(struct zr_context*, const char*, int active); +int zr_option_text(struct zr_context*, const char*, zr_size, int active); + +/* selectable */ +int zr_selectable_label(struct zr_context*, const char*, zr_flags align, int *value); +int zr_selectable_text(struct zr_context*, const char*, zr_size, zr_flags align, int *value); +int zr_select_label(struct zr_context*, const char*, zr_flags align, int value); +int zr_select_text(struct zr_context*, const char*, zr_size, zr_flags align, int value); + +/* slider */ float zr_slide_float(struct zr_context*, float min, float val, float max, float step); int zr_slide_int(struct zr_context*, int min, int val, int max, int step); int zr_slider_float(struct zr_context*, float min, float *val, float max, float step); int zr_slider_int(struct zr_context*, int min, int *val, int max, int step); +/* progressbar */ +int zr_progress(struct zr_context*, zr_size *cur, zr_size max, int modifyable); +zr_size zr_prog(struct zr_context*, zr_size cur, zr_size max, int modifyable); + /* color picker */ struct zr_color zr_color_picker(struct zr_context*, struct zr_color, enum zr_color_picker_format); int zr_color_pick(struct zr_context*, struct zr_color*, enum zr_color_picker_format); -/* extended value (dragging, increment/decrement and text input) */ +/* property (dragging, increment/decrement and text input) */ void zr_property_float(struct zr_context *layout, const char *name, float min, float *val, float max, float step, float inc_per_pixel); @@ -1697,7 +2027,7 @@ zr_flags zr_edit_string(struct zr_context*, zr_flags, char *buffer, zr_size *len zr_flags zr_edit_buffer(struct zr_context*, zr_flags, struct zr_buffer*, zr_filter); /* simple chart */ -void zr_chart_begin(struct zr_context*, enum zr_chart_type, int num, float min, float max); +int zr_chart_begin(struct zr_context*, enum zr_chart_type, int num, float min, float max); zr_flags zr_chart_push(struct zr_context*, float); void zr_chart_end(struct zr_context*); void zr_plot(struct zr_context*, enum zr_chart_type, const float *values, @@ -1717,24 +2047,41 @@ void zr_popup_end(struct zr_context*); /* abstract combo box */ int zr_combo_begin_text(struct zr_context*, struct zr_panel*, + const char *selected, zr_size, int max_height); +int zr_combo_begin_label(struct zr_context*, struct zr_panel*, const char *selected, int max_height); int zr_combo_begin_color(struct zr_context*, struct zr_panel*, struct zr_color color, int max_height); +int zr_combo_begin_symbol(struct zr_context*, struct zr_panel*, + enum zr_symbol_type, int max_height); +int zr_combo_begin_symbol_label(struct zr_context*, struct zr_panel*, + const char *selected, enum zr_symbol_type, int height); +int zr_combo_begin_symbol_text(struct zr_context*, struct zr_panel*, + const char *selected, zr_size, enum zr_symbol_type, int height); int zr_combo_begin_image(struct zr_context*, struct zr_panel*, struct zr_image img, int max_height); -int zr_combo_begin_icon(struct zr_context*, struct zr_panel*, - const char *selected, struct zr_image, int height); -int zr_combo_item(struct zr_context*, const char*, zr_flags alignment); -int zr_combo_item_icon(struct zr_context*, struct zr_image, const char*, - zr_flags alignment); -int zr_combo_item_symbol(struct zr_context*, enum zr_symbol_type, - const char*, zr_flags alignment); +int zr_combo_begin_image_label(struct zr_context*, struct zr_panel*, + const char *selected, struct zr_image, int height); +int zr_combo_begin_image_text(struct zr_context*, struct zr_panel*, + const char *selected, zr_size, struct zr_image, int height); +int zr_combo_item_label(struct zr_context*, const char*, zr_flags alignment); +int zr_combo_item_text(struct zr_context*, const char*,zr_size, zr_flags alignment); +int zr_combo_item_image_label(struct zr_context*, struct zr_image, const char*, + zr_flags alignment); +int zr_combo_item_image_text(struct zr_context*, struct zr_image, const char*, + zr_size,zr_flags alignment); +int zr_combo_item_symbol_label(struct zr_context*, enum zr_symbol_type, + const char*, zr_flags alignment); +int zr_combo_item_symbol_text(struct zr_context*, enum zr_symbol_type, + const char*, zr_size, zr_flags alignment); void zr_combo_close(struct zr_context*); void zr_combo_end(struct zr_context*); /* combobox */ int zr_combo(struct zr_context*, const char **items, int count, int selected, int item_height); +int zr_combo_seperator(struct zr_context*, const char *items_seperated_by_seperator, + int seperator, int selected, int count, int item_height); int zr_combo_string(struct zr_context*, const char *items_seperated_by_zeros, int selected, int count, int item_height); int zr_combo_callback(struct zr_context*, @@ -1745,18 +2092,25 @@ void zr_combobox(struct zr_context*, const char **items, int count, int *selecte int item_height); void zr_combobox_string(struct zr_context*, const char *items_seperated_by_zeros, int *selected, int count, int item_height); +void zr_combobox_seperator(struct zr_context*, const char *items_seperated_by_seperator, + int seperator,int *selected, int count, int item_height); void zr_combobox_callback(struct zr_context*, void(item_getter)(void* data, int id, const char **out_text), void *userdata, int *selected, int count, int item_height); -/* contextual menu */ +/* contextual */ int zr_contextual_begin(struct zr_context*, struct zr_panel*, zr_flags, struct zr_vec2, struct zr_rect trigger_bounds); -int zr_contextual_item(struct zr_context*, const char*, zr_flags alignment); -int zr_contextual_item_icon(struct zr_context*, struct zr_image, - const char*, zr_flags alignment); -int zr_contextual_item_symbol(struct zr_context*, enum zr_symbol_type, - const char*, zr_flags alignment); +int zr_contextual_item_text(struct zr_context*, const char*, zr_size,zr_flags align); +int zr_contextual_item_label(struct zr_context*, const char*, zr_flags align); +int zr_contextual_item_image_label(struct zr_context*, struct zr_image, + const char*, zr_flags alignment); +int zr_contextual_item_image_text(struct zr_context*, struct zr_image, + const char*, zr_size len, zr_flags alignment); +int zr_contextual_item_symbol_label(struct zr_context*, enum zr_symbol_type, + const char*, zr_flags alignment); +int zr_contextual_item_symbol_text(struct zr_context*, enum zr_symbol_type, + const char*, zr_size, zr_flags alignment); void zr_contextual_close(struct zr_context*); void zr_contextual_end(struct zr_context*); @@ -1771,17 +2125,32 @@ void zr_tooltip_end(struct zr_context*); void zr_menubar_begin(struct zr_context*); void zr_menubar_end(struct zr_context*); -int zr_menu_text_begin(struct zr_context*, struct zr_panel*, const char*, - zr_flags, float width); -int zr_menu_icon_begin(struct zr_context*, struct zr_panel*, const char*, +int zr_menu_begin_text(struct zr_context*, struct zr_panel*, const char*, + zr_size, zr_flags align, float width); +int zr_menu_begin_label(struct zr_context*, struct zr_panel*, const char*, + zr_flags align, float width); +int zr_menu_begin_image(struct zr_context*, struct zr_panel*, const char*, struct zr_image, float width); -int zr_menu_symbol_begin(struct zr_context*, struct zr_panel*, const char*, +int zr_menu_begin_image_text(struct zr_context*, struct zr_panel*, const char*, + zr_size,zr_flags align,struct zr_image, float width); +int zr_menu_begin_image_label(struct zr_context*, struct zr_panel*, const char*, + zr_flags align,struct zr_image, float width); +int zr_menu_begin_symbol(struct zr_context*, struct zr_panel*, const char*, enum zr_symbol_type, float width); -int zr_menu_item(struct zr_context*, zr_flags align, const char*); -int zr_menu_item_icon(struct zr_context*, struct zr_image, const char*, - zr_flags align); -int zr_menu_item_symbol(struct zr_context*, enum zr_symbol_type, const char*, - zr_flags align); +int zr_menu_begin_symbol_text(struct zr_context*, struct zr_panel*, const char*, + zr_size,zr_flags align,enum zr_symbol_type, float width); +int zr_menu_begin_symbol_label(struct zr_context*, struct zr_panel*, const char*, + zr_flags align,enum zr_symbol_type, float width); +int zr_menu_item_text(struct zr_context*, const char*, zr_size,zr_flags align); +int zr_menu_item_label(struct zr_context*, const char*, zr_flags alignment); +int zr_menu_item_image_label(struct zr_context*, struct zr_image, + const char*, zr_flags alignment); +int zr_menu_item_image_text(struct zr_context*, struct zr_image, + const char*, zr_size len, zr_flags alignment); +int zr_menu_item_symbol_text(struct zr_context*, enum zr_symbol_type, + const char*, zr_size, zr_flags alignment); +int zr_menu_item_symbol_label(struct zr_context*, enum zr_symbol_type, + const char*, zr_flags alignment); void zr_menu_close(struct zr_context*); void zr_menu_end(struct zr_context*);