diff --git a/Readme.md b/Readme.md index cb16e15..77b843a 100644 --- a/Readme.md +++ b/Readme.md @@ -59,6 +59,7 @@ gui_panel_init(&panel, 50, 50, 220, 170, &buffer, &config); /* setup widget data */ +enum {EASY, HARD}; gui_size len = 0; gui_char buffer[256]; gui_bool active = gui_false; @@ -74,14 +75,14 @@ while (1) { /* GUI */ struct gui_panel_layout layout; gui_panel_begin(&layout, &panel, &input); - gui_panel_header(&layout, "Demo", GUI_CLOSEABLE, 0, GUI_HEADER_RIGHT); - gui_panel_layout_flux_fixed(&layout, 30, 1); + gui_panel_header(&layout, "Demo", GUI_CLOSEABLE, 0, GUI_HEADER_LEFT); + gui_panel_row_dynamic(&layout, 30, 1); if (gui_panel_button_text(&layout, "button", GUI_BUTTON_DEFAULT)) { /* event handling */ } - gui_panel_layout_flux_fixed(&layout, 30, 2); - if (gui_panel_option(&layout, "easy", option == 0)) option = 0; - if (gui_panel_option(&layout, "hard", option == 1)) option = 1; + gui_panel_row_dynamic(&layout, 30, 2); + if (gui_panel_option(&layout, "easy", option == EASY)) option = EASY; + if (gui_panel_option(&layout, "hard", option == HARD)) option = HARD; gui_panel_label(&layout, "input:", GUI_TEXT_LEFT); len = gui_panel_edit(&layout, buffer, len, 256, &active, &cursor, GUI_INPUT_DEFAULT); gui_panel_end(&layout, &panel); @@ -303,7 +304,7 @@ while (1) { struct gui_panel_layout layout; gui_panel_begin_stacked(&layout, &panel, &stack, &input); gui_panel_header(&layout, "Demo", GUI_CLOSEABLE, 0, GUI_HEADER_RIGHT); - gui_panel_layout_flux_fixed(&layout, 30, 1); + gui_panel_row_dynamic(&layout, 30, 1); if (gui_panel_button_text(&layout, "button", GUI_BUTTON_DEFAULT)) fprintf(stdout, "button pressed!\n"); gui_panel_end(&layout, &panel); @@ -354,7 +355,7 @@ while (1) { /* GUI */ struct gui_panel_layout layout; gui_panel_begin_tiled(&layout, &panel, &tiled, GUI_SLOT_LEFT, 0, "Demo", &input); - gui_panel_layout_flux_fixed(&layout, 30, 1); + gui_panel_row_dynamic(&layout, 30, 1); if (gui_panel_button_text(&layout, "button", GUI_BUTTON_DEFAULT)) fprintf(stdout, "button pressed!\n"); gui_panel_end(&layout, &panel); diff --git a/demo/demo.c b/demo/demo.c index 2df0f77..3c1d4b1 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -31,7 +31,8 @@ struct state { gui_bool checkbox; gui_float slider; gui_size progressbar; - gui_int spinner; + gui_int spinner_int; + gui_float spinner_float; gui_bool spinner_active; gui_size item_current; gui_size shelf_selection; @@ -163,10 +164,11 @@ widget_panel(struct gui_panel_layout *panel, struct state *demo) const char *items[] = {"Fist", "Pistol", "Shotgun", "Railgun", "BFG"}; /* Labels */ - gui_panel_layout_flux_fixed(panel, 30, 1); + gui_panel_row_dynamic(panel, 30, 1); demo->scaleable = gui_panel_check(panel, "Scaleable Layout", demo->scaleable); + if (!demo->scaleable) - gui_panel_layout_static_fixed(panel, 30, 150, 1); + gui_panel_row_static(panel, 30, 150, 1); gui_panel_label(panel, "text left", GUI_TEXT_LEFT); gui_panel_label(panel, "text center", GUI_TEXT_CENTERED); gui_panel_label(panel, "text right", GUI_TEXT_RIGHT); @@ -183,8 +185,8 @@ widget_panel(struct gui_panel_layout *panel, struct state *demo) demo->checkbox = gui_panel_check(panel, "checkbox", demo->checkbox); if (!demo->scaleable) - gui_panel_layout_static_fixed(panel, 30, 75, 2); - else gui_panel_layout_flux_fixed(panel, 30, 2); + gui_panel_row_static(panel, 30, 75, 1); + else gui_panel_row_dynamic(panel, 30, 2); if (gui_panel_option(panel, "option 0", demo->option == 0)) demo->option = 0; if (gui_panel_option(panel, "option 1", demo->option == 1)) demo->option = 1; @@ -194,7 +196,7 @@ widget_panel(struct gui_panel_layout *panel, struct state *demo) char buffer[MAX_BUFFER]; if (demo->scaleable) { const gui_float ratio[] = {0.8f, 0.2f}; - gui_panel_layout_flux_row(panel, 30, 2, ratio); + gui_panel_row(panel, GUI_DYNAMIC, 30, 2, ratio); demo->slider = gui_panel_slider(panel, 0, demo->slider, 10, 1.0f); sprintf(buffer, "%.2f", demo->slider); gui_panel_label(panel, buffer, GUI_TEXT_LEFT); @@ -203,7 +205,7 @@ widget_panel(struct gui_panel_layout *panel, struct state *demo) gui_panel_label(panel, buffer, GUI_TEXT_LEFT); } else { const gui_float ratio[] = {150.0f, 30.0f}; - gui_panel_layout_static_row(panel, 30, 2, ratio); + gui_panel_row(panel, GUI_STATIC, 30, 2, ratio); demo->slider = gui_panel_slider(panel, 0, demo->slider, 10, 1.0f); sprintf(buffer, "%.2f", demo->slider); gui_panel_label(panel, buffer, GUI_TEXT_LEFT); @@ -214,38 +216,40 @@ widget_panel(struct gui_panel_layout *panel, struct state *demo) } if (!demo->scaleable) - gui_panel_layout_static_fixed(panel, 30, 150, 1); - else gui_panel_layout_flux_fixed(panel, 30, 1); + gui_panel_row_static(panel, 30, 150, 1); + else gui_panel_row_dynamic(panel, 30, 1); demo->item_current = gui_panel_selector(panel, items, LEN(items), demo->item_current); - demo->spinner = gui_panel_spinner(panel, 0, demo->spinner, 250, 10, &demo->spinner_active); + demo->spinner_int = gui_panel_spinner_int(panel, 0, demo->spinner_int, 250, 10, &demo->spinner_active); + demo->spinner_float = gui_panel_spinner_float(panel, 0.0f, demo->spinner_float, + 1.0f, 0.1f, &demo->spinner_active); demo->in_len = gui_panel_edit(panel, demo->in_buf, demo->in_len, MAX_BUFFER, &demo->in_active, NULL, GUI_INPUT_DEFAULT); if (demo->scaleable) { - gui_panel_layout_flux_row_begin(panel, 30, 2); + gui_panel_row_begin(panel, GUI_DYNAMIC, 30, 2); { - gui_panel_layout_flux_row_push(panel, 0.7f); + gui_panel_row_push(panel, 0.7f); gui_panel_editbox(panel, &demo->input); - gui_panel_layout_flux_row_push(panel, 0.3f); + gui_panel_row_push(panel, 0.3f); if (gui_panel_button_text(panel, "submit", GUI_BUTTON_DEFAULT)) { gui_edit_box_reset(&demo->input); fprintf(stdout, "command executed!\n"); } } - gui_panel_layout_flux_row_end(panel); + gui_panel_row_end(panel); } else { - gui_panel_layout_static_row_begin(panel, 30, 2); + gui_panel_row_begin(panel, GUI_STATIC, 30, 2); { - gui_panel_layout_static_row_push(panel, 100); + gui_panel_row_push(panel, 100); gui_panel_editbox(panel, &demo->input); - gui_panel_layout_static_row_push(panel, 80); + gui_panel_row_push(panel, 80); if (gui_panel_button_text(panel, "submit", GUI_BUTTON_DEFAULT)) { gui_edit_box_reset(&demo->input); fprintf(stdout, "command executed!\n"); } } - gui_panel_layout_static_row_end(panel); + gui_panel_row_end(panel); } } @@ -254,7 +258,7 @@ graph_panel(struct gui_panel_layout *panel, gui_size current) { enum {COL, PLOT}; static const gui_float values[]={8.0f,15.0f,20.0f,12.0f,30.0f,12.0f,35.0f,40.0f,20.0f}; - gui_panel_layout_flux_fixed(panel, 100, 1); + gui_panel_row_dynamic(panel, 100, 1); if (current == COL) { gui_panel_graph(panel, GUI_GRAPH_COLUMN, values, LEN(values), 0); } else { @@ -347,7 +351,7 @@ update_menu(struct gui_panel_layout *layout, struct state *win, struct gui_confi if (levels[0].items > max) max = levels[0].items; } - gui_panel_layout_flux_fixed(layout, 18, 5); + gui_panel_row_dynamic(layout, 18, 5); } /* output current menu level entries */ @@ -394,7 +398,7 @@ update_flags(struct gui_panel_layout *panel) gui_flags res = 0; gui_flags i = 0x01; const char *options[]={"Hidden","Border","Header Border", "Moveable","Scaleable", "Minimized"}; - gui_panel_layout_flux_fixed(panel, 30, 2); + gui_panel_row_dynamic(panel, 30, 2); do { if (gui_panel_check(panel,options[n++],(panel->flags & i)?gui_true:gui_false)) res |= i; @@ -410,12 +414,12 @@ properties_tab(struct gui_panel_layout *panel, struct gui_config *config) const char *properties[] = {"item spacing:", "item padding:", "panel padding:", "scaler size:", "scrollbar:"}; - gui_panel_layout_flux_fixed(panel, 30, 3); + gui_panel_row_dynamic(panel, 30, 3); for (i = 0; i <= GUI_PROPERTY_SCROLLBAR_SIZE; ++i) { gui_int tx, ty; gui_panel_label(panel, properties[i], GUI_TEXT_LEFT); - tx = gui_panel_spinner(panel,0,(gui_int)config->properties[i].x, 20, 1, NULL); - ty = gui_panel_spinner(panel,0,(gui_int)config->properties[i].y, 20, 1, NULL); + tx = gui_panel_spinner_int(panel,0,(gui_int)config->properties[i].x, 20, 1, NULL); + ty = gui_panel_spinner_int(panel,0,(gui_int)config->properties[i].y, 20, 1, NULL); config->properties[i].x = (float)tx; config->properties[i].y = (float)ty; } @@ -428,11 +432,11 @@ round_tab(struct gui_panel_layout *panel, struct gui_config *config) const char *rounding[] = {"panel:", "button:", "checkbox:", "progress:", "input: ", "graph:", "scrollbar:"}; - gui_panel_layout_flux_fixed(panel, 30, 2); + gui_panel_row_dynamic(panel, 30, 2); for (i = 0; i < GUI_ROUNDING_MAX; ++i) { gui_int t; gui_panel_label(panel, rounding[i], GUI_TEXT_LEFT); - t = gui_panel_spinner(panel,0,(gui_int)config->rounding[i], 20, 1, NULL); + t = gui_panel_spinner_int(panel,0,(gui_int)config->rounding[i], 20, 1, NULL); config->rounding[i] = (float)t; } } @@ -450,17 +454,17 @@ color_picker(struct gui_panel_layout *panel, struct state *control, active[2] = &control->spinner_b_active; active[3] = &control->spinner_a_active; - gui_panel_layout_flux_fixed(panel, 30, 2); + gui_panel_row_dynamic(panel, 30, 2); gui_panel_label(panel, name, GUI_TEXT_LEFT); gui_panel_button_color(panel, color, GUI_BUTTON_DEFAULT); iter = &color.r; - gui_panel_layout_flux_fixed(panel, 30, 2); + gui_panel_row_dynamic(panel, 30, 2); for (i = 0; i < 4; ++i, iter++) { gui_float t = *iter; t = gui_panel_slider(panel, 0, t, 255, 10); *iter = (gui_byte)t; - *iter = (gui_byte)gui_panel_spinner(panel, 0, *iter, 255, 1, active[i]); + *iter = (gui_byte)gui_panel_spinner_int(panel, 0, *iter, 255, 1, active[i]); } return color; } @@ -485,7 +489,7 @@ color_tab(struct gui_panel_layout *panel, struct state *control, struct gui_conf if (control->picker_active) { control->color = color_picker(panel,control,labels[control->current_color], control->color); - gui_panel_layout_flux_fixed(panel, 30, 3); + gui_panel_row_dynamic(panel, 30, 3); gui_panel_spacing(panel, 1); if (gui_panel_button_text(panel, "ok", GUI_BUTTON_DEFAULT)) { config->colors[control->current_color] = control->color; @@ -494,7 +498,7 @@ color_tab(struct gui_panel_layout *panel, struct state *control, struct gui_conf if (gui_panel_button_text(panel, "cancel", GUI_BUTTON_DEFAULT)) control->picker_active = gui_false; } else { - gui_panel_layout_flux_fixed(panel, 30, 2); + gui_panel_row_dynamic(panel, 30, 2); for (i = 0; i < GUI_COLOR_COUNT; ++i) { struct gui_color c = config->colors[i]; gui_panel_label(panel, labels[i], GUI_TEXT_LEFT); @@ -561,7 +565,8 @@ init_demo(struct demo_gui *gui, struct gui_font *font) win->slider = 2.0f; win->progressbar = 50; - win->spinner = 100; + win->spinner_int = 100; + win->spinner_float = 0.5f; { struct test_tree *tree = &win->tree; @@ -653,14 +658,14 @@ run_demo(struct demo_gui *gui, struct gui_input *input) } /* Shelf + Graphes */ - gui_panel_layout_flux_fixed(&layout, 180, 1); + gui_panel_row_dynamic(&layout, 180, 1); state->shelf_selection = gui_panel_shelf_begin(&layout, &tab, shelfs, LEN(shelfs), state->shelf_selection, state->shelf_scrollbar); graph_panel(&tab, state->shelf_selection); state->shelf_scrollbar = gui_panel_shelf_end(&layout, &tab); /* Tables */ - gui_panel_layout_flux_fixed(&layout, 180, 1); + gui_panel_row_dynamic(&layout, 180, 1); gui_panel_group_begin(&layout, &tab, "Table", state->table_scrollbar); table_panel(&tab); state->table_scrollbar = gui_panel_group_end(&layout, &tab); @@ -668,7 +673,7 @@ run_demo(struct demo_gui *gui, struct gui_input *input) { /* Tree */ struct gui_tree tree; - gui_panel_layout_flux_fixed(&layout, 250, 1); + gui_panel_row_dynamic(&layout, 250, 1); gui_panel_tree_begin(&layout, &tree, "Tree", 20, state->tree_scrollbar); upload_tree(&state->tree, &tree, &state->tree.root); state->tree_scrollbar = gui_panel_tree_end(&layout, &tree); diff --git a/gui.c b/gui.c index f735db8..3683ca1 100644 --- a/gui.c +++ b/gui.c @@ -59,6 +59,7 @@ static const gui_byte gui_utfbyte[GUI_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; static const gui_byte gui_utfmask[GUI_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; static const long gui_utfmin[GUI_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x100000}; static const long gui_utfmax[GUI_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; +static const double GUI_DOUBLE_PRECISION = 0.00000000000001; /* * ============================================================== @@ -67,44 +68,6 @@ static const long gui_utfmax[GUI_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0 * * =============================================================== */ -gui_float -gui_sin(gui_float x) -{ - gui_float rsin = 0; - if (x < -GUI_PI) x += GUI_PI2; - else if (x > GUI_PI) x -= GUI_PI2; - if (x < 0) { - rsin = GUI_4_DIV_PI * x + GUI_4_DIV_PI_SQRT * x * x; - if (rsin < 0) rsin = 0.225f * (rsin *-rsin - rsin) + rsin; - else rsin = 0.225f * (rsin * rsin - rsin) + rsin; - } else { - rsin = GUI_4_DIV_PI * x - GUI_4_DIV_PI_SQRT * x * x; - if (rsin < 0) rsin = 0.225f * (rsin *-rsin - rsin) + rsin; - else rsin = 0.225f * (rsin * rsin - rsin) + rsin; - } - return rsin; -} - -gui_float -gui_cos(gui_float x) -{ - gui_float rcos = 0; - x += 1.57079632f; - if (x > GUI_PI) - x -= GUI_PI2; - - if (x < 0) { - rcos = GUI_4_DIV_PI * x + GUI_4_DIV_PI_SQRT * x * x; - if (rcos < 0) rcos = 0.225f * (rcos *-rcos - rcos) + rcos; - else rcos = 0.225f * (rcos * rcos - rcos) + rcos; - } else { - rcos = GUI_4_DIV_PI * x - GUI_4_DIV_PI_SQRT * x * x; - if (rcos < 0) rcos = 0.225f * (rcos *-rcos - rcos) + rcos; - else rcos = 0.225f * (rcos * rcos - rcos) + rcos; - } - return rcos; -} - struct gui_rect gui_get_null_rect(void) { @@ -210,6 +173,45 @@ gui_image_is_subimage(const struct gui_image* img) return gui_rect_is_valid(img->region); } +static gui_float +gui_sin(gui_float x) +{ + gui_float rsin = 0; + if (x < -GUI_PI) x += GUI_PI2; + else if (x > GUI_PI) x -= GUI_PI2; + if (x < 0) { + rsin = GUI_4_DIV_PI * x + GUI_4_DIV_PI_SQRT * x * x; + if (rsin < 0) rsin = 0.225f * (rsin *-rsin - rsin) + rsin; + else rsin = 0.225f * (rsin * rsin - rsin) + rsin; + } else { + rsin = GUI_4_DIV_PI * x - GUI_4_DIV_PI_SQRT * x * x; + if (rsin < 0) rsin = 0.225f * (rsin *-rsin - rsin) + rsin; + else rsin = 0.225f * (rsin * rsin - rsin) + rsin; + } + return rsin; +} + + +static gui_float +gui_cos(gui_float x) +{ + gui_float rcos = 0; + x += 1.57079632f; + if (x > GUI_PI) + x -= GUI_PI2; + + if (x < 0) { + rcos = GUI_4_DIV_PI * x + GUI_4_DIV_PI_SQRT * x * x; + if (rcos < 0) rcos = 0.225f * (rcos *-rcos - rcos) + rcos; + else rcos = 0.225f * (rcos * rcos - rcos) + rcos; + } else { + rcos = GUI_4_DIV_PI * x - GUI_4_DIV_PI_SQRT * x * x; + if (rcos < 0) rcos = 0.225f * (rcos *-rcos - rcos) + rcos; + else rcos = 0.225f * (rcos * rcos - rcos) + rcos; + } + return rcos; +} + static void gui_zero(void *dst, gui_size size) { @@ -234,14 +236,66 @@ gui_strtoi(gui_int *number, const char *buffer, gui_size len) gui_size i; GUI_ASSERT(number); GUI_ASSERT(buffer); - if (!number || !buffer) - return 0; + if (!number || !buffer) return 0; *number = 0; for (i = 0; i < len; ++i) *number = *number * 10 + (buffer[i] - '0'); return 1; } +static gui_int +gui_strtof(gui_float *number, const char *buffer) +{ + gui_int i; + gui_float m; + gui_bool div; + gui_int pow; + const gui_char *p = buffer; + gui_float floatvalue = 0; + + GUI_ASSERT(number); + GUI_ASSERT(buffer); + if (!number || !buffer) return 0; + *number = 0; + + while( *p && *p != '.' && *p != 'e' ) { + floatvalue = floatvalue * 10.0f + (gui_float) (*p - '0'); + p++; + } + + if ( *p == '.' ) { + p++; + for(m = 0.1f; *p && *p != 'e'; p++ ) { + floatvalue = floatvalue + (gui_float) (*p - '0') * m; + m *= 0.1f; + } + } + if ( *p == 'e' ) { + p++; + if ( *p == '-' ) { + div = gui_true; + p++; + } + else if ( *p == '+' ) { + div = gui_false; + p++; + } + else div = gui_false; + + for ( pow = 0; *p; p++ ) + pow = pow * 10 + (int) (*p - '0'); + + for ( m = 1.0, i = 0; i < pow; i++ ) + m *= 10.0f; + + if ( div ) + floatvalue /= m; + else floatvalue *= m; + } + *number = floatvalue; + return 1; +} + static gui_size gui_itos(char *buffer, gui_int num) { @@ -274,6 +328,154 @@ gui_itos(char *buffer, gui_int num) return len; } +static gui_double +gui_pow(double x, int n) +{ + /* check the sign of n */ + gui_double r = 1; + int plus = n >= 0; + n = (plus) ? n : -n; + while (n > 0) { + if ((n & 1) == 1) + r *= x; + n /= 2; + x *= x; + } + return plus ? r : 1.0 / r; +} + +static int +gui_isinf(double x) +{ + union {gui_ulong u; double f;} ieee754; + ieee754.f = x; + return ( (unsigned)(ieee754.u >> 32) & 0x7fffffff ) == 0x7ff00000 && + ( (unsigned)ieee754.u == 0 ); +} + +static int +gui_isnan(double x) +{ + union {gui_ulong u; double f;} ieee754; + ieee754.f = x; + return ( (unsigned)(ieee754.u >> 32) & 0x7fffffff ) + + ( (unsigned)ieee754.u != 0 ) > 0x7ff00000; +} + +static gui_double +gui_fabs(gui_double x) +{ + if (x < 0) return -x; + return x; +} + +static gui_double +gui_floor(gui_double x) +{ + return (gui_double)((gui_int)x - ((x < 0.0) ? 1 : 0)); +} + +static gui_int +gui_log10(gui_double n) +{ + gui_int neg; + gui_int ret; + gui_int exp = 0; + + neg = (n < 0) ? 1 : 0; + ret = (neg) ? (gui_int)-n : (gui_int)n; + while ((ret / 10) > 0) { + ret /= 10; + exp++; + } + if (neg) exp = -exp; + return exp; +} + +static gui_size +gui_dtos(char *s, gui_double n) +{ + gui_int useExp; + gui_int digit, m, m1; + gui_char *c = s; + gui_int neg; + + if (gui_isnan(n)) { + s[0] = 'n'; s[1] = 'a'; s[2] = 'n'; s[3] = '\0'; + return 3; + } else if (gui_isinf(n)) { + s[0] = 'i'; s[1] = 'n'; s[2] = 'f'; s[3] = '\0'; + return 3; + } else if (n == 0.0) { + s[0] = '0'; s[1] = '\0'; + return 1; + } + + neg = (n < 0); + if (neg) n = -n; + + /* calculate magnitude */ + m = gui_log10(n); + useExp = (m >= 14 || (neg && m >= 9) || m <= -9); + if (neg) *(c++) = '-'; + + /* set up for scientific notation */ + if (useExp) { + if (m < 0) + m -= 1; + n = n / gui_pow(10.0, m); + m1 = m; + m = 0; + } + if (m < 1.0) { + m = 0; + } + + /* convert the number */ + while (n > GUI_DOUBLE_PRECISION || m >= 0) { + gui_double tmp; + gui_double weight = gui_pow(10.0, m); + if (weight > 0 && !gui_isinf(weight)) { + gui_double t = (gui_double)n / weight; + tmp = gui_floor(t); + digit = (gui_int)tmp; + n -= (digit * weight); + *(c++) = (gui_char)('0' + (gui_char)digit); + } + if (m == 0 && n > 0) + *(c++) = '.'; + m--; + } + + if (useExp) { + /* convert the exponent */ + int i, j; + *(c++) = 'e'; + if (m1 > 0) { + *(c++) = '+'; + } else { + *(c++) = '-'; + m1 = -m1; + } + m = 0; + while (m1 > 0) { + *(c++) = (gui_char)('0' + (gui_char)(m1 % 10)); + m1 /= 10; + m++; + } + c -= m; + for (i = 0, j = m-1; ibuffer, (gui_int)min, &unicode, &len); end = gui_edit_buffer_at(&box->buffer, (gui_int)maxi, &unicode, &len); len = (gui_size)(end - begin); @@ -1112,6 +1315,7 @@ gui_edit_box_remove(struct gui_edit_box *box) gui_char *glyph; gui_size offset; + /* remove last glyph */ cursor = (gui_int)box->cursor - 1; glyph = gui_edit_buffer_at(&box->buffer, cursor, &unicode, &len); if (!glyph || !len) return; @@ -1411,9 +1615,10 @@ gui_button_text_triangle(struct gui_command_buffer *out, gui_float x, gui_float if (!out || !button) return gui_false; - /* make sure correct values */ h = MAX(1, h); pressed = gui_button_text(out, x, y, w, h, text, behavior, button, i, f); + + /* calculate triangle bounds */ tri.y = y + (h/2) - f->height/2; tri.w = tri.h = f->height; if (align == GUI_TEXT_LEFT) { @@ -1518,7 +1723,7 @@ gui_toggle(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float w cursor_size, cursor_size, toggle->cursor); } - /* draw describing toggle text */ + /* draw toggle text */ if (font && string) { struct gui_text text; gui_float inner_x, inner_y; @@ -1661,7 +1866,6 @@ gui_progress(struct gui_command_buffer *out, gui_float x, gui_float y, return prog_value; } - static gui_size gui_font_glyph_index_at_pos(const struct gui_font *font, const char *text, gui_size text_len, gui_float xoff) @@ -2206,16 +2410,13 @@ gui_scrollbar_horizontal(struct gui_command_buffer *out, gui_float x, gui_float } -gui_int +static gui_int gui_spinner(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float w, - gui_float h, const struct gui_spinner *s, gui_int min, gui_int value, - gui_int max, gui_int step, gui_bool *active, const struct gui_input *in, - const struct gui_font *font) + gui_float h, const struct gui_spinner *s, gui_char *buffer, gui_size *len, + enum gui_input_filter filter, gui_bool *active, + const struct gui_input *in, const struct gui_font *font) { - char string[GUI_MAX_NUMBER_BUFFER]; - gui_size len, old_len; - gui_bool is_active; - + gui_int ret = 0; struct gui_button button; gui_float button_x, button_y; gui_float button_w, button_h; @@ -2225,17 +2426,6 @@ gui_spinner(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float gui_float field_x, field_y; gui_float field_w, field_h; - GUI_ASSERT(out); - GUI_ASSERT(s); - GUI_ASSERT(font); - if (!out || !s || !font) return value; - - /* make sure given values are correct */ - value = CLAMP(min, value, max); - len = gui_itos(string, value); - is_active = (active) ? *active : gui_false; - old_len = len; - h = MAX(h, font->height + 2 * s->padding.x); w = MAX(w, h - s->padding.x + (gui_float)s->border_button * 2); @@ -2255,14 +2445,13 @@ gui_spinner(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float button.highlight_content = s->button_triangle; button_up_clicked = gui_button_triangle(out, button_x, button_y, button_w, button_h, GUI_UP, GUI_BUTTON_DEFAULT, &button, in); + if (button_up_clicked) ret = 1; button_y = y + button_h; button_down_clicked = gui_button_triangle(out, button_x,button_y,button_w,button_h, GUI_DOWN, GUI_BUTTON_DEFAULT, &button, in); - if (button_up_clicked || button_down_clicked) { - value += (button_up_clicked) ? step : -step; - value = CLAMP(min, value, max); - } + if (button_down_clicked) ret = -1; + /* editbox setup and execution */ field_x = x; @@ -2277,9 +2466,39 @@ gui_spinner(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float field.background = s->color; field.border = s->border; field.text = s->text; - len = gui_edit(out, field_x, field_y, field_w, field_h, (gui_char*)string, - len, GUI_MAX_NUMBER_BUFFER, &is_active, 0, - &field,GUI_INPUT_FLOAT, in, font); + *len = gui_edit(out, field_x, field_y, field_w, field_h, buffer, + *len, GUI_MAX_NUMBER_BUFFER, active, 0, + &field, filter, in, font); + return ret; +} + +gui_int +gui_spinner_int(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float w, + gui_float h, const struct gui_spinner *s, gui_int min, gui_int value, + gui_int max, gui_int step, gui_bool *active, const struct gui_input *in, + const struct gui_font *font) +{ + gui_int res; + gui_char string[GUI_MAX_NUMBER_BUFFER]; + gui_size len, old_len; + gui_bool is_active; + + GUI_ASSERT(out); + GUI_ASSERT(s); + GUI_ASSERT(font); + if (!out || !s || !font) return value; + + /* make sure given values are correct */ + value = CLAMP(min, value, max); + len = gui_itos(string, value); + is_active = (active) ? *active : gui_false; + old_len = len; + + res = gui_spinner(out, x, y, w, h, s, string, &len, GUI_INPUT_DEC, active, in, font); + if (res) { + value += (res > 0) ? step : -step; + value = CLAMP(min, value, max); + } if (old_len != len) gui_strtoi(&value, string, len); @@ -2287,6 +2506,40 @@ gui_spinner(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float return value; } +gui_float +gui_spinner_float(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float w, + gui_float h, const struct gui_spinner *s, gui_float min, gui_float value, + gui_float max, gui_float step, gui_bool *active, + const struct gui_input *in, const struct gui_font *font) +{ + gui_int res; + char string[GUI_MAX_NUMBER_BUFFER]; + gui_size len, old_len; + gui_bool is_active; + + GUI_ASSERT(out); + GUI_ASSERT(s); + GUI_ASSERT(font); + if (!out || !s || !font) return value; + + /* make sure given values are correct */ + value = CLAMP(min, value, max); + len = gui_dtos(string, value); + is_active = (active) ? *active : gui_false; + old_len = len; + + res = gui_spinner(out, x, y, w, h, s, string, &len, GUI_INPUT_FLOAT, active, in, font); + if (res) { + value += (res > 0) ? step : -step; + value = CLAMP(min, value, max); + } + + if (old_len != len) + gui_strtof(&value, string); + if (active) *active = is_active; + return value; +} + gui_size gui_selector(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float w, gui_float h, const struct gui_selector *s, const char *items[], @@ -3268,7 +3521,7 @@ gui_panel_header_icon(struct gui_panel_layout *layout, gui_command_buffer_push_rect(out, sym_x+1, sym_y+1, sym_w-2, sym_h-2, 0, c->colors[GUI_COLOR_HEADER]); } else { - /* rectangle circle */ + /* circle shape */ gui_command_buffer_push_circle(out, sym_x, sym_y, sym_w, sym_h, c->colors[GUI_COLOR_TEXT]); if (symbol == GUI_SYMBOL_CIRCLE_FILLED) @@ -3306,7 +3559,7 @@ gui_panel_header_icon(struct gui_panel_layout *layout, sym_w = c->font.height + 2 * item_padding.x; } break; case GUI_SYMBOL_IMAGE: { - /* image icon bounds */ + /* image icon */ sym_bw = sym_w = c->font.height; sym_h = c->font.height; sym_y = sym_y + c->font.height/2; @@ -3321,7 +3574,7 @@ gui_panel_header_icon(struct gui_panel_layout *layout, default: return ret; } - /* check if the icon has been pressed and set/remove the panel flag */ + /* check if the icon has been pressed */ if (layout->input) { gui_float clicked_x = layout->input->mouse_clicked_pos.x; gui_float clicked_y = layout->input->mouse_clicked_pos.y; @@ -3445,8 +3698,8 @@ gui_panel_header_end(struct gui_panel_layout *layout) panel_padding = gui_config_property(c, GUI_PROPERTY_PADDING); item_padding = gui_config_property(c, GUI_PROPERTY_ITEM_PADDING); - /* draw scrollbar panel footer */ { + /* draw scrollbar panel footer */ const struct gui_color *color = &c->colors[GUI_COLOR_PANEL]; if (layout->valid) gui_command_buffer_push_rect(out, layout->x, layout->y + layout->header.h, @@ -3475,7 +3728,6 @@ gui_panel_header_end(struct gui_panel_layout *layout) layout->clip.y = layout->y + layout->header.h; layout->clip.h = layout->h - (layout->footer_h + layout->header.h); layout->clip.h -= (panel_padding.y + item_padding.y); - gui_command_buffer_push_scissor(out, layout->clip.x, layout->clip.y, layout->clip.w, layout->clip.h); } @@ -3603,8 +3855,10 @@ gui_panel_layout(struct gui_panel_layout *layout, gui_float height, gui_size col layout->width, height + panel_padding.y, 0, *color); } -void -gui_panel_layout_flux_fixed(struct gui_panel_layout *layout, gui_float height, gui_size cols) +static void +gui_panel_row_layout(struct gui_panel_layout *layout, + enum gui_panel_row_layout_format fmt, gui_float height, gui_size cols, + gui_size width) { GUI_ASSERT(layout); GUI_ASSERT(layout->config); @@ -3615,16 +3869,28 @@ gui_panel_layout_flux_fixed(struct gui_panel_layout *layout, gui_float height, g /* draw the current row and set the current row layout */ gui_panel_layout(layout, height, cols); - layout->row.type = GUI_PANEL_LAYOUT_FLUX_FIXED; + if (fmt == GUI_DYNAMIC) + layout->row.type = GUI_PANEL_LAYOUT_DYNAMIC_FIXED; + else layout->row.type = GUI_PANEL_LAYOUT_STATIC_FIXED; + + layout->row.item_width = width; layout->row.ratio = 0; - layout->row.item_width = 0; layout->row.item_offset = 0; layout->row.filled = 0; } void -gui_panel_layout_flux_row_begin(struct gui_panel_layout *layout, - gui_float height, gui_size cols) +gui_panel_row_dynamic(struct gui_panel_layout *layout, gui_float height, gui_size cols) +{gui_panel_row_layout(layout, GUI_DYNAMIC, height, cols, 0);} + +void +gui_panel_row_static(struct gui_panel_layout *layout, gui_float height, + gui_size item_width, gui_size cols) +{gui_panel_row_layout(layout, GUI_STATIC, height, cols, item_width);} + +void +gui_panel_row_begin(struct gui_panel_layout *layout, + enum gui_panel_row_layout_format fmt, gui_float row_height, gui_size cols) { GUI_ASSERT(layout); GUI_ASSERT(layout->config); @@ -3633,8 +3899,10 @@ gui_panel_layout_flux_row_begin(struct gui_panel_layout *layout, if (!layout) return; if (!layout->valid) return; - gui_panel_layout(layout, height, 0); - layout->row.type = GUI_PANEL_LAYOUT_FLUX_ROW; + gui_panel_layout(layout, row_height, cols); + if (fmt == GUI_DYNAMIC) + layout->row.type = GUI_PANEL_LAYOUT_DYNAMIC_ROW; + else layout->row.type = GUI_PANEL_LAYOUT_STATIC_ROW; layout->row.ratio = 0; layout->row.item_width = 0; layout->row.item_offset = 0; @@ -3643,23 +3911,23 @@ gui_panel_layout_flux_row_begin(struct gui_panel_layout *layout, } void -gui_panel_layout_flux_row_push(struct gui_panel_layout *layout, gui_float ratio) +gui_panel_row_push(struct gui_panel_layout *layout, gui_float ratio_or_width) { GUI_ASSERT(layout); GUI_ASSERT(layout->config); - GUI_ASSERT((ratio + layout->row.filled) <= 1.0f); + if (!layout || !layout->valid) return; - if (!layout) return; - if (!layout->valid) return; - if ((ratio + layout->row.filled) > 1.0f) return; - - if (ratio > 0.0f) - layout->row.item_width = GUI_SATURATE(ratio); - else layout->row.item_width = 1.0f - layout->row.filled; + if (layout->row.type == GUI_PANEL_LAYOUT_DYNAMIC_ROW) { + gui_float ratio = ratio_or_width; + if ((ratio + layout->row.filled) > 1.0f) return; + if (ratio > 0.0f) + layout->row.item_width = GUI_SATURATE(ratio); + else layout->row.item_width = 1.0f - layout->row.filled; + } else layout->row.item_width = ratio_or_width; } void -gui_panel_layout_flux_row_end(struct gui_panel_layout *layout) +gui_panel_row_end(struct gui_panel_layout *layout) { GUI_ASSERT(layout); GUI_ASSERT(layout->config); @@ -3670,8 +3938,8 @@ gui_panel_layout_flux_row_end(struct gui_panel_layout *layout) } void -gui_panel_layout_flux_row(struct gui_panel_layout *layout, gui_float height, - gui_size cols, const gui_float *ratio) +gui_panel_row(struct gui_panel_layout *layout, enum gui_panel_row_layout_format fmt, + gui_float height, gui_size cols, const gui_float *ratio) { gui_size i; gui_size n_undef = 0; @@ -3684,26 +3952,32 @@ gui_panel_layout_flux_row(struct gui_panel_layout *layout, gui_float height, if (!layout) return; if (!layout->valid) return; - /* calculate width of undefined widget ratios */ gui_panel_layout(layout, height, cols); - layout->row.ratio = ratio; - for (i = 0; i < cols; ++i) { - if (ratio[i] < 0.0f) - n_undef++; - else r += ratio[i]; + if (fmt == GUI_DYNAMIC) { + /* calculate width of undefined widget ratios */ + layout->row.ratio = ratio; + for (i = 0; i < cols; ++i) { + if (ratio[i] < 0.0f) + n_undef++; + else r += ratio[i]; + } + r = GUI_SATURATE(1.0f - r); + layout->row.type = GUI_PANEL_LAYOUT_DYNAMIC; + layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (gui_float)n_undef):0; + } else { + layout->row.ratio = ratio; + layout->row.type = GUI_PANEL_LAYOUT_STATIC; + layout->row.item_width = 0; + layout->row.item_offset = 0; } - /* setup panel row layout */ - r = GUI_SATURATE(1.0f - r); - layout->row.type = GUI_PANEL_LAYOUT_FLUX; - layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (gui_float)n_undef):0; layout->row.item_offset = 0; layout->row.filled = 0; } void -gui_panel_layout_flux_begin(struct gui_panel_layout *layout, gui_float height, - gui_size count) +gui_panel_row_space_begin(struct gui_panel_layout *layout, + enum gui_panel_row_layout_format fmt, gui_float height, gui_size widget_count) { GUI_ASSERT(layout); GUI_ASSERT(layout->config); @@ -3712,174 +3986,53 @@ gui_panel_layout_flux_begin(struct gui_panel_layout *layout, gui_float height, if (!layout) return; if (!layout->valid) return; - /* draw the current row and set the current row layout */ - gui_panel_layout(layout, height, 0); - layout->row.type = GUI_PANEL_LAYOUT_FLUX_FREE; - layout->row.ratio = 0; - layout->row.item_width = 0; - layout->row.item_offset = 0; - layout->row.columns = count; - layout->row.filled = 0; -} - -void -gui_panel_layout_flux_widget(struct gui_panel_layout *layout, - struct gui_rect ratios) -{ - GUI_ASSERT(layout); - GUI_ASSERT(layout->config); - GUI_ASSERT(layout->buffer); - if (!layout) return; - if (!layout->valid) return; - layout->row.item = ratios; -} - -void -gui_panel_layout_flux_end(struct gui_panel_layout *layout) -{ - GUI_ASSERT(layout); - GUI_ASSERT(layout->config); - if (!layout) return; - if (!layout->valid) return; - layout->row.item_width = 0; - layout->row.item_height = 0; - layout->row.item_offset = 0; -} - -void -gui_panel_layout_static_fixed(struct gui_panel_layout *layout, gui_float row_height, - gui_float item_width, gui_size cols) -{ - GUI_ASSERT(layout); - GUI_ASSERT(layout->config); - GUI_ASSERT(layout->buffer); - - if (!layout) return; - if (!layout->valid) return; - gui_panel_layout(layout, row_height, cols); - layout->row.type = GUI_PANEL_LAYOUT_STATIC_FIXED; - layout->row.item_width = item_width; - layout->row.item_offset = 0; - layout->row.ratio = 0; - layout->row.filled = 0; -} - -void -gui_panel_layout_static_row_begin(struct gui_panel_layout *layout, gui_float row_height, - gui_size cols) -{ - GUI_ASSERT(layout); - GUI_ASSERT(layout->config); - GUI_ASSERT(layout->buffer); - - if (!layout) return; - if (!layout->valid) return; - - gui_panel_layout(layout, row_height, 0); - layout->row.type = GUI_PANEL_LAYOUT_STATIC_ROW; - layout->row.ratio = 0; - layout->row.item_width = 0; - layout->row.item_offset = 0; - layout->row.filled = 0; - layout->row.columns = cols; -} - -void -gui_panel_layout_static_row_push(struct gui_panel_layout *layout, gui_float width) -{ - GUI_ASSERT(layout); - GUI_ASSERT(layout->config); - if (!layout) return; - if (!layout->valid) return; - layout->row.item_width = width; -} - -void -gui_panel_layout_static_row_end(struct gui_panel_layout *layout) -{ - GUI_ASSERT(layout); - GUI_ASSERT(layout->config); - if (!layout) return; - if (!layout->valid) return; - layout->row.item_width = 0; - layout->row.item_offset = 0; -} - -void -gui_panel_layout_static_row(struct gui_panel_layout *layout, gui_float height, - gui_size cols, const gui_float *ratio) -{ - GUI_ASSERT(layout); - GUI_ASSERT(layout->config); - GUI_ASSERT(layout->buffer); - - if (!layout) return; - if (!layout->valid) return; - - gui_panel_layout(layout, height, cols); - layout->row.ratio = ratio; - layout->row.type = GUI_PANEL_LAYOUT_STATIC; - layout->row.item_width = 0; - layout->row.item_offset = 0; - layout->row.filled = 0; -} - -void -gui_panel_layout_static_begin(struct gui_panel_layout *layout, gui_float height, - gui_size widget_count) -{ - struct gui_rect clip, space; - GUI_ASSERT(layout); - GUI_ASSERT(layout->config); - GUI_ASSERT(layout->buffer); - - if (!layout) return; - if (!layout->valid) return; - - /* draw the current row and set the current row layout */ gui_panel_layout(layout, height, widget_count); - layout->row.type = GUI_PANEL_LAYOUT_STATIC_FREE; + if (fmt == GUI_STATIC) { + struct gui_rect clip, space; + space.x = layout->at_x; + space.y = layout->at_y; + space.w = layout->width; + space.h = layout->row.height; + gui_unify(&clip, &layout->clip, space.x, space.y, space.x + space.w, space.y + space.h); + gui_command_buffer_push_scissor(layout->buffer, clip.x, clip.y, clip.w, clip.h); + + layout->row.type = GUI_PANEL_LAYOUT_STATIC_FREE; + layout->row.clip = layout->clip; + layout->clip = clip; + + } else layout->row.type = GUI_PANEL_LAYOUT_DYNAMIC_FREE; + layout->row.ratio = 0; layout->row.item_width = 0; layout->row.item_offset = 0; layout->row.filled = 0; - - space.x = layout->at_x; - space.y = layout->at_y; - space.w = layout->width; - space.h = layout->row.height; - - gui_unify(&clip, &layout->clip, space.x, space.y, space.x + space.w, space.y + space.h); - gui_command_buffer_push_scissor(layout->buffer, clip.x, clip.y, clip.w, clip.h); - layout->row.clip = layout->clip; - layout->clip = clip; } void -gui_panel_layout_static_widget(struct gui_panel_layout *layout, - struct gui_rect ratios) +gui_panel_row_space_push(struct gui_panel_layout *layout, struct gui_rect rect) { GUI_ASSERT(layout); GUI_ASSERT(layout->config); GUI_ASSERT(layout->buffer); if (!layout) return; if (!layout->valid) return; - layout->row.item = ratios; + layout->row.item = rect; } void -gui_panel_layout_static_end(struct gui_panel_layout *layout) +gui_panel_row_space_end(struct gui_panel_layout *layout) { GUI_ASSERT(layout); GUI_ASSERT(layout->config); if (!layout) return; if (!layout->valid) return; + layout->row.item_width = 0; layout->row.item_height = 0; layout->row.item_offset = 0; - layout->clip = layout->row.clip; - gui_command_buffer_push_scissor(layout->buffer, layout->clip.x, - layout->clip.y, layout->clip.w, layout->clip.h); + if (layout->row.type == GUI_PANEL_LAYOUT_STATIC_FREE) + gui_command_buffer_push_scissor(layout->buffer, layout->clip.x, + layout->clip.y, layout->clip.w, layout->clip.h); } static void @@ -3922,13 +4075,13 @@ gui_panel_alloc_space(struct gui_rect *bounds, struct gui_panel_layout *layout) /* calculate the width of one item inside the panel row */ switch (layout->row.type) { - case GUI_PANEL_LAYOUT_FLUX_FIXED: { + case GUI_PANEL_LAYOUT_DYNAMIC_FIXED: { /* scaling fixed size widgets item width */ item_width = panel_space / (gui_float)layout->row.columns; item_offset = (gui_float)layout->row.index * item_width; item_spacing = (gui_float)layout->row.index * spacing.x; } break; - case GUI_PANEL_LAYOUT_FLUX_ROW: { + case GUI_PANEL_LAYOUT_DYNAMIC_ROW: { /* scaling single ratio widget width */ item_width = layout->row.item_width * panel_space; item_offset = layout->row.item_offset; @@ -3938,7 +4091,7 @@ gui_panel_alloc_space(struct gui_rect *bounds, struct gui_panel_layout *layout) layout->row.filled += layout->row.item_width; layout->row.index = 0; } break; - case GUI_PANEL_LAYOUT_FLUX_FREE: { + case GUI_PANEL_LAYOUT_DYNAMIC_FREE: { /*panel width depended free widget placing */ bounds->x = layout->at_x + (layout->width * layout->row.item.x); bounds->x -= layout->offset.x; @@ -3947,7 +4100,7 @@ gui_panel_alloc_space(struct gui_rect *bounds, struct gui_panel_layout *layout) bounds->h = layout->row.height * layout->row.item.h; return; } break; - case GUI_PANEL_LAYOUT_FLUX: { + case GUI_PANEL_LAYOUT_DYNAMIC: { /* scaling arrays of panel width ratios for every widget */ gui_float ratio; GUI_ASSERT(layout->row.ratio); @@ -4052,11 +4205,12 @@ gui_panel_layout_push(struct gui_panel_layout *layout, struct gui_vec2 points[3]; heading = (*state == GUI_MAXIMIZED) ? GUI_DOWN : GUI_RIGHT; + /* calculate the triangle bounds */ sym.w = sym.h = config->font.height; sym.y = header.y + item_padding.y + config->font.height/2; sym.x = header.x + panel_padding.x; - /* calculate the triangle point positions and draw triangle */ + /* calculate the triangle vertexes and draw triangle */ gui_triangle_from_direction(points, sym.x, sym.y, sym.w, sym.h, 0, 0, heading); gui_command_buffer_push_triangle(layout->buffer, points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y, config->colors[GUI_COLOR_TEXT]); @@ -4170,7 +4324,7 @@ gui_panel_spacing(struct gui_panel_layout *l, gui_size cols) } /* non table layout need to allocate space */ - if (l->row.type != GUI_PANEL_LAYOUT_FLUX_FIXED && + if (l->row.type != GUI_PANEL_LAYOUT_DYNAMIC_FIXED && l->row.type != GUI_PANEL_LAYOUT_STATIC_FIXED) { for (i = 0; i < n; ++i) gui_panel_alloc_space(&nil, l); @@ -4229,25 +4383,17 @@ gui_panel_text_colored(struct gui_panel_layout *layout, const char *str, gui_siz void gui_panel_text(struct gui_panel_layout *l, const char *str, gui_size len, enum gui_text_align alignment) -{ - gui_panel_text_colored(l, str, len, alignment,l->config->colors[GUI_COLOR_TEXT]); -} +{gui_panel_text_colored(l, str, len, alignment,l->config->colors[GUI_COLOR_TEXT]);} void gui_panel_label_colored(struct gui_panel_layout *layout, const char *text, enum gui_text_align align, struct gui_color color) -{ - gui_size len = gui_strsiz(text); - gui_panel_text_colored(layout, text, len, align, color); -} +{gui_panel_text_colored(layout, text, gui_strsiz(text), align, color);} void gui_panel_label(struct gui_panel_layout *layout, const char *text, enum gui_text_align align) -{ - gui_size len = gui_strsiz(text); - gui_panel_text(layout, text, len, align); -} +{gui_panel_text(layout, text, gui_strsiz(text), align);} void gui_panel_image(struct gui_panel_layout *layout, struct gui_image img) @@ -4651,7 +4797,7 @@ gui_panel_edit(struct gui_panel_layout *layout, gui_char *buffer, gui_size len, if (!state) return len; i = (state == GUI_ROM) ? 0 : layout->input; return gui_edit(layout->buffer, bounds.x, bounds.y, bounds.w, bounds.h, - buffer, len, max, active, cursor, &field, filter, i, &config->font); + buffer, len, max, active, cursor, &field, filter, i, &config->font); } gui_size @@ -4668,11 +4814,12 @@ gui_panel_edit_filtered(struct gui_panel_layout *layout, gui_char *buffer, gui_s if (!state) return len; i = (state == GUI_ROM) ? 0 : layout->input; return gui_edit_filtered(layout->buffer, bounds.x, bounds.y, bounds.w, bounds.h, - buffer, len, max, active, cursor, &field, filter, i, &config->font); + buffer, len, max, active, cursor, &field, + filter, i, &config->font); } gui_int -gui_panel_spinner(struct gui_panel_layout *layout, gui_int min, gui_int value, +gui_panel_spinner_int(struct gui_panel_layout *layout, gui_int min, gui_int value, gui_int max, gui_int step, gui_bool *active) { struct gui_rect bounds; @@ -4701,8 +4848,42 @@ gui_panel_spinner(struct gui_panel_layout *layout, gui_int min, gui_int value, spinner.border = config->colors[GUI_COLOR_SPINNER_BORDER]; spinner.text = config->colors[GUI_COLOR_SPINNER_TEXT]; spinner.show_cursor = gui_false; - return gui_spinner(out, bounds.x, bounds.y, bounds.w, bounds.h, &spinner, - min, value, max, step, active, i, &layout->config->font); + return gui_spinner_int(out, bounds.x, bounds.y, bounds.w, bounds.h, &spinner, + min, value, max, step, active, i, &layout->config->font); +} + +gui_float +gui_panel_spinner_float(struct gui_panel_layout *layout, gui_float min, gui_float value, + gui_float max, gui_float step, gui_bool *active) +{ + struct gui_rect bounds; + struct gui_spinner spinner; + const struct gui_config *config; + struct gui_command_buffer *out; + struct gui_vec2 item_padding; + + const struct gui_input *i; + enum gui_widget_state state; + state = gui_panel_widget(&bounds, layout); + if (!state) return value; + i = (state == GUI_ROM) ? 0 : layout->input; + + config = layout->config; + out = layout->buffer; + item_padding = gui_config_property(config, GUI_PROPERTY_ITEM_PADDING); + + spinner.border_button = 1; + spinner.button_color = config->colors[GUI_COLOR_BUTTON]; + spinner.button_border = config->colors[GUI_COLOR_BUTTON_BORDER]; + spinner.button_triangle = config->colors[GUI_COLOR_SPINNER_TRIANGLE]; + spinner.padding.x = item_padding.x; + spinner.padding.y = item_padding.y; + spinner.color = config->colors[GUI_COLOR_SPINNER]; + spinner.border = config->colors[GUI_COLOR_SPINNER_BORDER]; + spinner.text = config->colors[GUI_COLOR_SPINNER_TEXT]; + spinner.show_cursor = gui_false; + return gui_spinner_float(out, bounds.x, bounds.y, bounds.w, bounds.h, &spinner, + min, value, max, step, active, i, &layout->config->font); } gui_size @@ -4737,9 +4918,16 @@ gui_panel_selector(struct gui_panel_layout *layout, const char *items[], selector.text_bg = config->colors[GUI_COLOR_PANEL]; selector.padding = gui_config_property(config, GUI_PROPERTY_ITEM_PADDING); return gui_selector(out, bounds.x, bounds.y, bounds.w, bounds.h, &selector, - items, item_count, item_current, i, &layout->config->font); + items, item_count, item_current, i, &layout->config->font); } +/* + * ------------------------------------------------------------- + * + * GRAPH + * + * -------------------------------------------------------------- + */ void gui_panel_graph_begin(struct gui_panel_layout *layout, struct gui_graph *graph, enum gui_graph_type type, gui_size count, gui_float min_value, gui_float max_value) @@ -4878,13 +5066,6 @@ gui_panel_graph_push_column(struct gui_panel_layout *layout, return selected; } -/* - * ------------------------------------------------------------- - * - * GRAPH - * - * -------------------------------------------------------------- - */ gui_bool gui_panel_graph_push(struct gui_panel_layout *layout, struct gui_graph *graph, gui_float value) @@ -5055,7 +5236,7 @@ gui_panel_table_begin(struct gui_panel_layout *layout, gui_flags flags, layout->is_table = gui_true; layout->tbl_flags = flags; - gui_panel_layout_flux_fixed(layout, (gui_float)row_height, cols); + gui_panel_row_dynamic(layout, (gui_float)row_height, cols); if (layout->tbl_flags & GUI_TABLE_HHEADER) gui_panel_table_horizontal_line(layout, row_height); if (layout->tbl_flags & GUI_TABLE_VHEADER) @@ -5073,7 +5254,7 @@ gui_panel_table_row(struct gui_panel_layout *layout) config = layout->config; item_spacing = gui_config_property(config, GUI_PROPERTY_ITEM_SPACING); - gui_panel_layout_flux_fixed(layout,layout->row.height-item_spacing.y,layout->row.columns); + gui_panel_row_dynamic(layout, layout->row.height-item_spacing.y,layout->row.columns); if (layout->tbl_flags & GUI_TABLE_HBODY) gui_panel_table_horizontal_line(layout, (gui_size)(layout->row.height - item_spacing.y)); if (layout->tbl_flags & GUI_TABLE_VBODY) @@ -5652,15 +5833,16 @@ gui_layout_end(struct gui_layout *layout) left = &layout->slots[GUI_SLOT_LEFT]; right = &layout->slots[GUI_SLOT_RIGHT]; + /* calucalate the slot ratio size */ centerh = MAX(0.0f, 1.0f - (left->value + right->value)); centerv = MAX(0.0f, 1.0f - (top->value + bottom->value)); layout->slots[GUI_SLOT_CENTER].ratio = gui_vec2(centerh, centerv); - layout->slots[GUI_SLOT_TOP].ratio = gui_vec2(1.0f, top->value); layout->slots[GUI_SLOT_LEFT].ratio = gui_vec2(left->value, centerv); layout->slots[GUI_SLOT_BOTTOM].ratio = gui_vec2(1.0f, bottom->value); layout->slots[GUI_SLOT_RIGHT].ratio = gui_vec2(right->value, centerv); + /* calucalate the slot screen position ratio */ layout->slots[GUI_SLOT_TOP].offset = gui_vec2(0.0f, 0.0f); layout->slots[GUI_SLOT_LEFT].offset = gui_vec2(0.0f, top->value); layout->slots[GUI_SLOT_BOTTOM].offset = gui_vec2(0.0f, top->value + centerv); diff --git a/gui.h b/gui.h index f5649e7..d81cbc6 100644 --- a/gui.h +++ b/gui.h @@ -50,6 +50,7 @@ typedef int32_t gui_bool; typedef int16_t gui_short; typedef int64_t gui_long; typedef float gui_float; +typedef double gui_double; typedef uint16_t gui_ushort; typedef uint32_t gui_uint; typedef uint64_t gui_ulong; @@ -65,6 +66,7 @@ typedef char gui_char; typedef short gui_short; typedef long gui_long; typedef float gui_float; +typedef double gui_double; typedef unsigned short gui_ushort; typedef unsigned int gui_uint; typedef unsigned long gui_ulong; @@ -122,8 +124,6 @@ typedef void(*gui_copy_f)(gui_handle, const char*, gui_size size); gui_rgba -- create a gui color struct from rgba color code gui_rgb -- create a gui color struct from rgb color code */ -gui_float gui_sin(gui_float); -gui_float gui_cos(gui_float); struct gui_rect gui_get_null_rect(void); gui_size gui_utf_decode(const gui_char*, gui_long*, gui_size); gui_size gui_utf_encode(gui_long, gui_char*, gui_size); @@ -401,7 +401,7 @@ void gui_buffer_clear(struct gui_buffer*); * * =============================================================== */ -/* COMMAND BUFFER +/* COMMANDS ---------------------------- The command buffer API enqueues draw calls as commands in to a buffer and therefore abstracts over drawing routines and enables defered drawing. @@ -1255,11 +1255,11 @@ gui_size gui_edit_filtered(struct gui_command_buffer*, gui_float x, gui_float y, - state of the editbox with either active or inactive - returns the size of the buffer in bytes after the modification */ -gui_int gui_spinner(struct gui_command_buffer*, gui_float x, gui_float y, gui_float w, - gui_float h, const struct gui_spinner*, gui_int min, gui_int value, - gui_int max, gui_int step, gui_bool *active, - const struct gui_input*, const struct gui_font*); -/* this function executes a spinner widget +gui_int gui_spinner_int(struct gui_command_buffer*, gui_float x, gui_float y, gui_float w, + gui_float h, const struct gui_spinner*, gui_int min, gui_int value, + gui_int max, gui_int step, gui_bool *active, + const struct gui_input*, const struct gui_font*); +/* this function executes a integer spinner widget Input: - output command buffer for draw commands - (x,y) position @@ -1274,6 +1274,26 @@ gui_int gui_spinner(struct gui_command_buffer*, gui_float x, gui_float y, gui_fl Output: - returns the from the user input updated spinner value */ +gui_float gui_spinner_float(struct gui_command_buffer*, gui_float x, gui_float y, gui_float w, + gui_float h, const struct gui_spinner*, gui_float min, gui_float value, + gui_float max, gui_float step, gui_bool *active, + const struct gui_input*, const struct gui_font*); +/* this function executes a float point spinner widget + Input: + - output command buffer for draw commands + - (x,y) position + - (width, height) size + - visual widget style structure describing the spinner + - minimal spinner value that will no be underflown + - spinner value that will be updated + - maximal spinner value that will no be overflown + - spinner input state with either active or inactive + - input structure to update the slider with + - font structure for text drawing + Output: + - returns the from the user input updated spinner value +*/ + gui_size gui_selector(struct gui_command_buffer*, gui_float x, gui_float y, gui_float w, gui_float h, const struct gui_selector*, const char *items[], gui_size item_count, @@ -1457,9 +1477,13 @@ struct gui_saved_color { enum gui_config_components { GUI_DEFAULT_COLOR = 0x01, + /* default all colors inside the configuration struct */ GUI_DEFAULT_PROPERTIES = 0x02, + /* default all properites inside the configuration struct */ GUI_DEFAULT_ROUNDING = 0x04, + /* default all rounding values inside the configuration struct */ GUI_DEFAULT_ALL = 0xFFFF + /* default the complete configuration struct */ }; struct gui_config_stack { @@ -1664,13 +1688,13 @@ struct gui_panel { }; enum gui_panel_row_layout_type { - GUI_PANEL_LAYOUT_FLUX_FIXED, + GUI_PANEL_LAYOUT_DYNAMIC_FIXED, /* fixed widget ratio width panel layout */ - GUI_PANEL_LAYOUT_FLUX_ROW, + GUI_PANEL_LAYOUT_DYNAMIC_ROW, /* immediate mode widget specific widget width ratio layout */ - GUI_PANEL_LAYOUT_FLUX_FREE, + GUI_PANEL_LAYOUT_DYNAMIC_FREE, /* free ratio based placing of widget in a local space */ - GUI_PANEL_LAYOUT_FLUX, + GUI_PANEL_LAYOUT_DYNAMIC, /* retain mode widget specific widget ratio width*/ GUI_PANEL_LAYOUT_STATIC_FIXED, /* fixed widget pixel width panel layout */ @@ -1689,7 +1713,9 @@ enum gui_node_state { enum gui_panel_layout_node_type { GUI_LAYOUT_NODE, + /* a node is a space which can be minimized or maximized */ GUI_LAYOUT_TAB + /* a tab is a node with a header */ }; #define GUI_UNDEFINED (-1.0f) @@ -1900,7 +1926,7 @@ void gui_panel_end(struct gui_panel_layout*, struct gui_panel*); gui_panel_header_button -- adds a button into the header gui_panel_header_button_icon -- adds a image button into the header gui_panel_header_toggle -- adds a toggle button into the header - gui_panel_header_flag -- adds a panel flag toggle button + gui_panel_header_flag -- adds a panel flag toggle button gui_panel_header_title -- adds the title of the panel into the header gui_panel_header_end -- finishes the header build up process gui_panel_header -- short cut version of the header build up process @@ -1965,8 +1991,7 @@ gui_bool gui_panel_header_button_icon(struct gui_panel_layout*, struct gui_image gui_bool gui_panel_header_toggle(struct gui_panel_layout*, enum gui_panel_header_symbol inactive, enum gui_panel_header_symbol active, - enum gui_panel_header_align, - gui_bool state); + enum gui_panel_header_align, gui_bool state); /* this function adds a header toggle button Input: - symbol that will be drawn if the toggle is inactive @@ -2012,17 +2037,17 @@ void gui_panel_menu_end(struct gui_panel_layout*); /* this function ends the panel menubar build up process */ /* * -------------------------------------------------------------- - * LAYOUT + * ROW LAYOUT * -------------------------------------------------------------- - HEADER + ROW LAYOUT The layout API is for positioning of widget inside a panel. In general there are three different ways to position widget. The first one is a table with fixed size columns. This like the other three comes in two flavors. First the scaleable with as a ration of the panel width and the other is a non-scaleable fixed pixel value for static panels. Since sometimes widgets with different size in a row is needed another set - of row layout has been added. The first API for dynamically size widgets - is an immediate mode API which sets each size of a widget directly before + of row layout has been added. The first set is for dynamically size widgets + in an immediate mode API which sets each size of a widget directly before it is called or a retain mode API which stores the size of every widget as an array. The final way to position widgets is by allocating a fixed space from @@ -2030,45 +2055,87 @@ void gui_panel_menu_end(struct gui_panel_layout*); This requires the least amount of work for the API and the most for the user, but offers the most positioning freedom. - USAGE - The first layout type with a fixed size table layout only needs to be set once - and works over row boundaries this includes `gui_panel_layout_flux_fixed` - as well as `gui_panel_layout_static_fixed`. - The second layout type with functions `gui_panel_layout_flux_row_xxx` and - `gui_panel_layout_static_row_xxx` only works for one row and - has to be set for each row. In addition the `gui_panel_layout_xxx_row_push` - function has to be called for each widget. - The free position API works completly on the allocated space and the - `gui_panel_layout_xxxx_widget` functions need to be called for each widget - seperatly and only between the begin and end sequence points. - panel scaling layout function API - gui_panel_layout_flux_fixed -- scaleable fixed ratio size widget row layout - gui_panel_layout_flux_row -- scaleable user defined widget row layout - gui_panel_layout_flux_row_begin -- begins the row build up process - gui_panel_layout_flux_row_push -- pushes the next widget width ratio - gui_panel_layout_flux_row_end -- ends the row build up process - gui_panel_layout_flux_begin -- creates a free drawing space in the panel - gui_panel_layout_flux_widget -- pushes a widget into the space - gui_panel_layout_flux_end -- finishes the free drawingp process - - panel fixed layout function API - gui_panel_layout_static_fixed -- fixed pixel size widget row layout - gui_panel_layout_static_row -- fixed size user defined widget row layout - gui_panel_layout_static_row_begin -- begins the row build up process - gui_panel_layout_static_row_push -- pushes the next widget pixel width - gui_panel_layout_static_row_end -- ends the row build up process - gui_panel_layout_static_begin -- creates a free drawing space in the panel - gui_panel_layout_static_widget -- pushes a widget into the space - gui_panel_layout_static_end -- finishes the free drawingp process + gui_panel_row -- user defined widget row layout + gui_panel_row_dynamic -- scaling fixed column row layout + gui_panel_row_static -- fixed width fixed column row layout + gui_panel_row_begin -- begins the row build up process + gui_panel_row_push -- pushes the next widget width + gui_panel_row_end -- ends the row build up process + gui_panel_row_space_begin -- creates a free placing space in the panel + gui_panel_row_space_widget -- pushes a widget into the space + gui_panel_row_space_end -- finishes the free drawingp process panel tree layout function API - gui_panel_layout_push -- pushes a new node/collapseable header/tab - gui_panel_layout_pop -- pops the the previously added node + gui_panel_layout_push -- pushes a new node/collapseable header/tab + gui_panel_layout_pop -- pops the the previously added node */ -gui_bool gui_panel_layout_push(struct gui_panel_layout*, - enum gui_panel_layout_node_type, +enum gui_panel_row_layout_format { + GUI_DYNAMIC, /* row layout which scales with the panel */ + GUI_STATIC /* row layout with fixed pixel width */ +}; + +void gui_panel_row_dynamic(struct gui_panel_layout*, gui_float height, gui_size cols); +/* this function sets the row layout to dynamically fixed size widget + Input: + - height of the row that will be filled + - number of widget inside the row that will divide the space +*/ +void gui_panel_row_static(struct gui_panel_layout*, gui_float row_height, + gui_size item_width, gui_size cols); +/* this function sets the row layout to static fixed size widget + Input: + - height of the row that will be filled + - width in pixel measurement of each widget in the row + - number of widget inside the row that will divide the space +*/ +void gui_panel_row_begin(struct gui_panel_layout*, + enum gui_panel_row_layout_format, + gui_float row_height, gui_size cols); +/* this function start a new scaleable row that can be filled with different + sized widget + Input: + - scaleable or fixed row format + - height of the row that will be filled + - number of widget inside the row that will divide the space +*/ +void gui_panel_row_push(struct gui_panel_layout*, gui_float value); +/* this function pushes a widget into the previously start row with the given + panel width ratio or pixel width + Input: + - value with either a ratio for GUI_DYNAMIC or a pixel width for GUI_STATIC layout +*/ +void gui_panel_row_end(struct gui_panel_layout*); +/* this function ends the previously started scaleable row */ +void gui_panel_row(struct gui_panel_layout*, enum gui_panel_row_layout_format, + gui_float height, gui_size cols, const gui_float *ratio); +/* this function sets the row layout as an array of ratios/width for + every widget that will be inserted into that row + Input: + - scaleable or fixed row format + - height of the row and there each widget inside + - number of widget inside the row + - panel ratio/pixel width array for each widget +*/ +void gui_panel_row_space_begin(struct gui_panel_layout*, + enum gui_panel_row_layout_format, + gui_float height, gui_size widget_count); +/* this functions starts a space where widgets can be added + at any given position and the user has to make sure no overlap occures + Input: + - height of the row and therefore each widget inside + - number of widget that will be added into that space +*/ +void gui_panel_row_space_push(struct gui_panel_layout*, struct gui_rect); +/* this functions pushes the position and size of the next widget that will + be added into the previously allocated panel space + Input: + - rectangle with position and size as a ratio of the next widget to add +*/ +void gui_panel_row_space_end(struct gui_panel_layout*); +/* this functions finishes the scaleable space filling process */ +gui_bool gui_panel_layout_push(struct gui_panel_layout*, enum gui_panel_layout_node_type, const char *title, enum gui_node_state*); /* this functions pushes either a tree node, collapseable header or tab into * the current panel layout @@ -2082,102 +2149,6 @@ gui_bool gui_panel_layout_push(struct gui_panel_layout*, */ void gui_panel_layout_pop(struct gui_panel_layout*); /* this functions ends the previously added node */ -void gui_panel_layout_flux_fixed(struct gui_panel_layout*, gui_float row_height, gui_size cols); -/* this function sets the current row layout to a scaleable table like layout where each - widget occupies a fixed ratio of the panel width - Input: - - height of the row that will be filled - - number of widget inside the row that will divide the space -*/ -void gui_panel_layout_flux_row_begin(struct gui_panel_layout*, gui_float row_height, gui_size cols); -/* this function start a new scaleable row that can be filled with different - sized widget - Input: - - height of the row that will be filled - - number of widget inside the row that will divide the space -*/ -void gui_panel_layout_flux_row_push(struct gui_panel_layout*, gui_float ratio); -/* this function pushes a widget into the previously start row with the given - panel width ratio - Input: - - ratio of the complete width of the panel row that the next widget should take -*/ -void gui_panel_layout_flux_row_end(struct gui_panel_layout*); -/* this function ends the previously started scaleable row */ -void gui_panel_layout_flux_row(struct gui_panel_layout*, gui_float height, - gui_size cols, const gui_float *ratio); -/* this function sets the scaleable row layout as an array of ratios for - every widget that will be inserted into that row - Input: - - height of the row and there each widget inside - - number of widget inside the row - - panel width ratio array for each widget -*/ -void gui_panel_layout_flux_begin(struct gui_panel_layout*, gui_float height, - gui_size widget_count); -/* this functions starts a scaling space where widgets can be added - at any given position and the user has to make sure no overlap occures - Input: - - height of the row and therefore each widget inside - - number of widget that will be added into that space -*/ -void gui_panel_layout_flux_widget(struct gui_panel_layout*, struct gui_rect); -/* this functions pushes the position and size of the next widget that will - be added into the previously allocated panel space - Input: - - rectangle with position and size as a ratio of the next widget to add -*/ -void gui_panel_layout_flux_end(struct gui_panel_layout*); -/* this functions finishes the scaleable space filling process */ -void gui_panel_layout_static_fixed(struct gui_panel_layout*, gui_float row_height, - gui_float width, gui_size cols); -/* this function sets the current row layout to a table like layout where each - widget has a fixed pixel width - Input: - - height of the row that will be filled - - number of widget inside the row that will divide the space -*/ -void gui_panel_layout_static_row_begin(struct gui_panel_layout*, gui_float row_height, - gui_size cols); -/* this function start a new non scaleable row that can be filled with different - pixel sized widget - Input: - - height of the row that will be filled - - number of widget inside the row that will share the space -*/ -void gui_panel_layout_static_row_push(struct gui_panel_layout*, gui_float width); -/* this function pushes a widget into the previously start row with a given - pixel width - Input: - - non-scaleable widget pixel width -*/ -void gui_panel_layout_static_row_end(struct gui_panel_layout*); -/* this functions finishes the non-scaleable space filling process */ -void gui_panel_layout_static_row(struct gui_panel_layout*, gui_float height, - gui_size cols, const gui_float *ratio); -/* this function sets the non-scaleable row layout as an array of pixel width for - every widget that will be inserted into that row - Input: - - height of the row and there each widget inside - - number of widget inside the row - - pixel width array with a value for each widget -*/ -void gui_panel_layout_static_begin(struct gui_panel_layout*, gui_float height, - gui_size widget_count); -/* this functions starts a non-scaling space where widgets can be freely added - at any given position and the user has to make sure no overlap occures - Input: - - height of the row and therefore each widget inside - - number of widget that will be added into that space -*/ -void gui_panel_layout_static_widget(struct gui_panel_layout*, struct gui_rect); -/* this functions pushes the position and size of the next widget that will - be added into the previously allocated panel space - Input: - - rectangle with position and size of the next widget to add -*/ -void gui_panel_layout_static_end(struct gui_panel_layout*); -/* this functions finishes the non-scaleable space filling process */ /* * -------------------------------------------------------------- * WIDGETS @@ -2185,7 +2156,7 @@ void gui_panel_layout_static_end(struct gui_panel_layout*); WIDGET The layout API uses the layout API to provide and add widget to the panel. IMPORTANT: the widget API does NOT work without a layout so if you have - visual glitches that the problem probably comes from not using the layout + visual glitches that the problem probably comes from not using the layout correctly. The panel widget API does not implement any widget itself, instead it uses the general Widget API under the hood and is only responsible for calling the correct widget API function with correct position, size and style. @@ -2208,7 +2179,7 @@ void gui_panel_layout_static_end(struct gui_panel_layout*); gui_panle_image -- image widget for outputing a image to a panel gui_panel_check -- add a checkbox widget with either active or inactive state gui_panel_option -- radiobutton widget with either active or inactive state - gui_panel_option_group -- radiobutton group with automates the process of having only one active + gui_panel_option_group -- radiobutton group for automatic single selection gui_panel_button_text -- button widget with text content gui_panel_button_color -- colored button widget without content gui_panel_button_triangle -- button with triangle pointing either up-/down-/left- or right @@ -2221,7 +2192,8 @@ void gui_panel_layout_static_end(struct gui_panel_layout*); gui_panel_edit -- edit textbox widget for text input gui_panel_edit_filtered -- edit textbox widget for text input with filter input gui_panel_editbox -- edit textbox with cursor, clipboard and filter - gui_panel_spinner -- spinner widget with either keyboard or mouse modification + gui_panel_spinner_int -- spinner widget with either keyboard or mouse modification + gui_panel_spinner_float -- spinner widget with either keyboard or mouse modification gui_panel_selector -- selector widget for combobox like selection of types */ enum gui_widget_state gui_panel_widget(struct gui_rect*, struct gui_panel_layout*); @@ -2427,9 +2399,9 @@ gui_size gui_panel_edit_filtered(struct gui_panel_layout*, gui_char *buffer, - length of the buffer after user input update - current state of the editbox with active(gui_true) or inactive(gui_false) */ -gui_int gui_panel_spinner(struct gui_panel_layout*, gui_int min, gui_int value, - gui_int max, gui_int step, gui_bool *active); -/* this function creates a spinner widget +gui_int gui_panel_spinner_int(struct gui_panel_layout*, gui_int min, gui_int value, + gui_int max, gui_int step, gui_bool *active); +/* this function creates a integer spinner widget Input: - min value that will not be underflown - current spinner value to be updated by user input @@ -2440,6 +2412,20 @@ gui_int gui_panel_spinner(struct gui_panel_layout*, gui_int min, gui_int value, - the from user input updated spinner value - current state of the editbox with active(gui_true) or inactive(gui_false) */ +gui_float gui_panel_spinner_float(struct gui_panel_layout*, gui_float min, gui_float value, + gui_float max, gui_float step, gui_bool *active); +/* this function creates a float point spinner widget + Input: + - min value that will not be underflown + - current spinner value to be updated by user input + - max value that will not be overflown + - spinner value modificaton stepping intervall + - current state of the spinner with active as currently modfied by user input + Output: + - the from user input updated spinner value + - current state of the editbox with active(gui_true) or inactive(gui_false) +*/ + gui_size gui_panel_selector(struct gui_panel_layout*, const char *items[], gui_size item_count, gui_size item_current); /* this function creates a string selector widget @@ -2864,8 +2850,9 @@ void gui_layout_begin(struct gui_layout*, struct gui_rect bounds, - size (width/height) of the layout in the window - layout state with either active as user updateable or inactive for blocked */ -void gui_layout_slot_locked(struct gui_layout*, enum gui_layout_slot_index, gui_float ratio, - enum gui_layout_format, gui_size entry_count); +void gui_layout_slot_locked(struct gui_layout*, enum gui_layout_slot_index, + gui_float ratio, enum gui_layout_format, + gui_size entry_count); /* this function activates a non scaleable slot inside a scaleable layout Input: - index of the slot to be activated