From cbc25a5d5f75067cac6480531164fc00ccf22262 Mon Sep 17 00:00:00 2001 From: vurtun Date: Sat, 14 Mar 2015 17:05:30 +0100 Subject: [PATCH] added spinner + command input --- Readme.md | 23 ++++ gui.c | 331 ++++++++++++++++++++++++++++++++++++++++++++++++------ gui.h | 64 +++++++---- opengl.c | 15 ++- 4 files changed, 373 insertions(+), 60 deletions(-) diff --git a/Readme.md b/Readme.md index 0babdb7..7ff7249 100644 --- a/Readme.md +++ b/Readme.md @@ -1,4 +1,27 @@ # GUI +## Features +- Immediate graphical user interface +- Suited for embedding into graphical applications +- Written in C89 (ANSI C) +- Small (~1.5kLOC) +- Focus on portability and ease of use +- Simplicity over extensive features +- no hidden states or global variables +- Renderer independent +- No direct dependencies (not even libc) +- Configurable +- UTF-8 support + +## Example + +## Gallery + +## Font + +## Configuration + +## References + # License (The MIT License) diff --git a/gui.c b/gui.c index 4a1ed2d..b7eda42 100644 --- a/gui.c +++ b/gui.c @@ -7,6 +7,7 @@ #define NULL (void*)0 #define UTF_INVALID 0xFFFD +#define MAX_NUMBER_BUFFER 64 #define PASTE(a,b) a##b #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) < (b) ? (b) : (a)) @@ -31,10 +32,10 @@ static const gui_texture null_tex = (void*)0; static const struct gui_rect null_rect = {-9999, -9999, 9999 * 2, 9999 * 2}; -static gui_char utfbyte[GUI_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -static gui_char utfmask[GUI_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -static long utfmin[GUI_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x100000}; -static long utfmax[GUI_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; +static const gui_char utfbyte[GUI_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; +static const gui_char utfmask[GUI_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; +static const long utfmin[GUI_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x100000}; +static const long utfmax[GUI_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; static gui_float fsqrt(float x) @@ -42,7 +43,6 @@ fsqrt(float x) float xhalf = 0.5f*x; union {float f; int i;} val; ASSERT(sizeof(int) == sizeof(float)); - val.f = x; val.i = 0x5f375a86 - (val.i >> 1); val.f = val.f * (1.5f - xhalf * val.f * val.f); @@ -60,6 +60,47 @@ memcopy(void *dst, const void *src, gui_size size) return dst; } +static gui_int +strtoi(gui_int *number, const char *buffer, gui_size len) +{ + gui_size i; + if (!number || !buffer | !len) { + *number = 0; + return 0; + } + *number = 0; + for (i = 0;i < len; ++i) + *number = *number * 10 + (buffer[i] - '0'); + return 1; +} + +static gui_size +itos(char *buffer, gui_int num) +{ + gui_int shifter; + gui_size len = 0; + const char digit[] = "0123456789"; + char *p = buffer; + if (!buffer) + return 0; + if (num < 0) { + num = ABS(num); + *p++ = '-'; + } + shifter = num; + do { + ++p; + shifter = shifter/10; + } while (shifter); + *p = '\0'; + len = (gui_size)(p - buffer); + do { + *--p = digit[num % 10]; + num = num / 10; + } while (num); + return len; +} + static gui_size utf_validate(long *u, gui_size i) { @@ -273,10 +314,10 @@ static gui_size gui_font_chars_in_space(const struct gui_font *font, const gui_char *text, gui_size len, gui_float space) { + const struct gui_font_glyph *glyph; gui_size chars = 0; gui_long unicode; gui_size text_width = 0; - const struct gui_font_glyph *glyph; gui_size text_len = 0; gui_size glyph_len; @@ -435,7 +476,9 @@ gui_draw_rect(struct gui_draw_buffer *buffer, gui_float x, gui_float y, struct gui_draw_command *cmd; if (!buffer) return; if (col.a == 0) return; - if (!gui_push_command(buffer, 6 * 4, &null_rect, null_tex)) return; + if (!gui_push_command(buffer, 6 * 4, &null_rect, null_tex)) + return; + gui_vertex_line(buffer, x, y, x + w, y, col); gui_vertex_line(buffer, x + w, y, x + w, y + h, col); gui_vertex_line(buffer, x + w, y + h, x, y + h, col); @@ -609,7 +652,6 @@ gui_button_text(struct gui_draw_buffer *buffer, const struct gui_button *button, font_color = button->font; background = button->background; - highlight = button->highlight; button_w = MAX(button->w, 2 * button->pad_x); button_h = MAX(button->h, 2 * button->pad_x); @@ -617,8 +659,12 @@ gui_button_text(struct gui_draw_buffer *buffer, const struct gui_button *button, font_color = button->background; background = button->highlight; if (INBOX(in->mouse_clicked_pos.x, in->mouse_clicked_pos.y, - button->x, button->y, button_w, button_h)) - ret = (in->mouse_down && in->mouse_clicked); + button->x, button->y, button_w, button_h)) { + if (button->behavior == GUI_BUTTON_SWITCH) + ret = (in->mouse_down && in->mouse_clicked); + else + ret = in->mouse_down; + } } gui_draw_rectf(buffer, button->x, button->y, button_w, button_h, background); gui_draw_rect(buffer, button->x+1, button->y+1, button_w-1, button_h-1, button->foreground); @@ -808,12 +854,70 @@ gui_progress(struct gui_draw_buffer *buffer, const struct gui_progress *prog, return prog_value; } +static gui_bool +gui_filter_input(gui_long unicode, gui_size len, enum gui_input_filter filter) +{ + if (filter == GUI_INPUT_DEFAULT) { + return gui_true; + } else if (filter == GUI_INPUT_FLOAT) { + if (len > 1) + return gui_false; + if ((unicode < '0' || unicode > '9') && unicode != '.') + return gui_false; + return gui_true; + } else if (filter == GUI_INPUT_DEC) { + if (len > 1) + return gui_false; + if (unicode < '0' || unicode > '9') + return gui_false; + return gui_true; + } else if (filter == GUI_INPUT_HEX) { + if (len > 1) + return gui_false; + if ((unicode < '0' || unicode > '9') && + (unicode < 'a' || unicode > 'f') && + (unicode < 'A' || unicode > 'B')) + return gui_false; + return gui_true; + } else if (filter == GUI_INPUT_OCT) { + if (len > 1) + return gui_false; + if (unicode < '0' || unicode > '7') + return gui_false; + return gui_true; + } else if (filter == GUI_INPUT_BIN) { + if (len > 1) + return gui_false; + if (unicode < '0' || unicode > '1') + return gui_false; + return gui_true; + } + return gui_false; +} + +static void +gui_buffer_input(gui_char *buffer, gui_size *length, gui_size max, + enum gui_input_filter filter, const struct gui_input *in) +{ + gui_size text_len = 0, glyph_len = 0; + gui_long unicode; + glyph_len = utf_decode(in->text, &unicode, in->text_len); + while (glyph_len && (text_len + glyph_len) <= in->text_len && *length < max) { + if (gui_filter_input(unicode, glyph_len, filter)) { + gui_size i = 0; + for (i = 0; i < glyph_len; i++) + buffer[(*length)++] = in->text[text_len + i]; + } + text_len = text_len + glyph_len; + glyph_len = utf_decode(in->text + text_len, &unicode, in->text_len - text_len); + } +} + gui_int gui_input(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length, const struct gui_input_field *input, const struct gui_font *font, const struct gui_input *in) { - gui_size offset = 0; gui_float input_w, input_h; gui_int input_active; if (!buffer || !in || !font || !input) @@ -842,22 +946,12 @@ gui_input(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length, input_active = gui_false; if ((space->down && space->clicked) && (*length < input->max)) buffer[(*length)++] = ' '; - - if (in->text_len && *length < input->max) { - gui_size text_len = 0, glyph_len = 0; - gui_long unicode; - gui_size i = 0; - glyph_len = utf_decode(in->text, &unicode, in->text_len); - while (glyph_len && (text_len + glyph_len) <= in->text_len && *length < input->max) { - for (i = 0; i < glyph_len; i++) - buffer[(*length)++] = in->text[text_len + i]; - text_len = text_len + glyph_len; - glyph_len = utf_decode(in->text + text_len, &unicode, in->text_len - text_len); - } - } + if (in->text_len && *length < input->max) + gui_buffer_input(buffer, length, input->max, input->filter, in); } if (font && buffer && length && *length) { + gui_size offset = 0; gui_float label_x = input->x + input->pad_x; gui_float label_y = input->y + input->pad_y; gui_float label_w = input_w - 2 * input->pad_x; @@ -868,21 +962,118 @@ gui_input(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length, text_width = gui_font_text_width(font, &buffer[offset], *length - offset); } gui_draw_string(buf, font, label_x, label_y, label_w, label_h, input->font, - &buffer[offset], *length); + &buffer[offset], *length); } return input_active; } +gui_size +gui_command(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length, + gui_int *active, const struct gui_input_field *input, + const struct gui_font *font, const struct gui_input *in) +{ + gui_size submit = 0; + gui_size space = 0; + struct gui_button button; + struct gui_input_field field; + if (!buf|| !buffer || !length || !font || !in || !input || !active) + return 0; + + memcopy(&field, input, sizeof(struct gui_input_field)); + space = gui_font_text_width(font, (const gui_char*)"Submit", 6); + + button.y = field.y; + button.h = field.h; + button.w = (gui_float)space + 2 * field.pad_x - 1; + button.x = field.x + field.w - button.w + 1; + button.pad_x = field.pad_x; + button.pad_y = field.pad_y; + button.behavior = GUI_BUTTON_SWITCH; + button.font = field.font; + button.background = field.background; + button.foreground = field.foreground; + button.highlight = field.foreground; + if (gui_button_text(buf, &button, "Submit", 6, font, in )) { + submit = *length; + *length = 0; + } + + field.w = field.w - button.w; + *active = gui_input(buf, (gui_char*)buffer, length, &field, font, in); + if (!submit && active) { + const struct gui_key *enter = &in->keys[GUI_KEY_ENTER]; + if ((enter->down && enter->clicked)) { + submit = *length; + *length = 0; + } + } + return submit; +} + +gui_int +gui_spinner(struct gui_draw_buffer *buffer, const struct gui_spinner *spinner, + gui_int *value, const struct gui_font *font, const struct gui_input *in) +{ + struct gui_button button; + struct gui_input_field field; + char string[MAX_NUMBER_BUFFER]; + gui_bool is_active, updated = gui_false; + gui_bool button_up_clicked, button_down_clicked; + gui_size len, old_len; + + if (!buffer || !spinner || !value || !font) return 0; + *value = CLAMP(spinner->min, *value, spinner->max); + is_active = spinner->active; + len = itos(string, *value); + old_len = len; + + button.y = spinner->y; + button.h = spinner->h / 2; + button.w = spinner->h - spinner->pad_x; + button.x = spinner->x + spinner->w - button.w; + button.pad_x = MAX(3, button.h - font->height); + button.pad_y = MAX(3, button.h - font->height); + button.behavior = GUI_BUTTON_SWITCH; + button.background = spinner->foreground; + button.foreground = spinner->button; + button.highlight = spinner->foreground; + button_up_clicked = gui_button_triangle(buffer, &button, GUI_UP, in); + button.y = spinner->y + button.h; + button_down_clicked = gui_button_triangle(buffer, &button, GUI_DOWN, in); + if (button_up_clicked || button_down_clicked) { + *value += (button_up_clicked) ? spinner->step : -spinner->step; + *value = CLAMP(spinner->min, *value, spinner->max); + } + + field.x = spinner->x; + field.y = spinner->y; + field.w = spinner->w - button.w; + field.h = spinner->h; + field.pad_x = spinner->pad_x; + field.pad_y = spinner->pad_y; + field.max = MAX_NUMBER_BUFFER; + field.filter = GUI_INPUT_FLOAT; + field.active = is_active; + field.font = spinner->font; + field.background = spinner->background; + field.foreground = spinner->foreground; + + is_active = gui_input(buffer, (gui_char*)string, &len, &field, font, in); + if (old_len != len) + strtoi(value, string, len); + return is_active; +} + gui_int gui_plot(struct gui_draw_buffer *buffer, const struct gui_plot *plot, const struct gui_input *in) { gui_size i; + gui_size plot_step; + gui_float plot_w, plot_h; gui_int plot_selected = -1; gui_float plot_max_value, plot_min_value; gui_float plot_value_range, plot_value_ratio; - gui_size plot_step; - gui_float plot_w, plot_h; gui_float canvas_x, canvas_y; gui_float canvas_w, canvas_h; gui_float last_x; @@ -1008,7 +1199,6 @@ gui_scroll(struct gui_draw_buffer *buffer, const struct gui_scroll *scroll, gui_bool inscroll, incursor; if (!buffer || !in || !scroll) return 0; - scroll_y = scroll->y; scroll_w = MAX(scroll->w, 0); scroll_h = MAX(scroll->h, 2 * scroll_w); gui_draw_rectf(buffer, scroll->x, scroll->y, scroll_w, scroll_h, scroll->background); @@ -1023,6 +1213,7 @@ gui_scroll(struct gui_draw_buffer *buffer, const struct gui_scroll *scroll, button.background = scroll->foreground; button.foreground = scroll->background; button.highlight = scroll->foreground; + button.behavior = GUI_BUTTON_SWITCH; button_up_pressed = gui_button_triangle(buffer, &button, GUI_UP, in); button.y = scroll->y + scroll_h - button.h; button_down_pressed = gui_button_triangle(buffer, &button, GUI_DOWN, in); @@ -1085,8 +1276,11 @@ gui_default_config(struct gui_config *config) config->colors[GUI_COLOR_SLIDER_CURSOR] = gui_make_color(45, 45, 45, 255); config->colors[GUI_COLOR_PROGRESS] = gui_make_color(100, 100, 100, 255); config->colors[GUI_COLOR_PROGRESS_CURSOR] = gui_make_color(45, 45, 45, 255); - config->colors[GUI_COLOR_INPUT] = gui_make_color(45, 45, 45, 45); - config->colors[GUI_COLOR_INPUT_BORDER] = gui_make_color(100, 100, 100, 100); + config->colors[GUI_COLOR_INPUT] = gui_make_color(45, 45, 45, 255); + config->colors[GUI_COLOR_INPUT_BORDER] = gui_make_color(100, 100, 100, 255); + config->colors[GUI_COLOR_SPINNER] = gui_make_color(45, 45, 45, 255); + config->colors[GUI_COLOR_SPINNER_BORDER] = gui_make_color(100, 100, 100, 255); + config->colors[GUI_COLOR_SPINNER_BUTTON] = gui_make_color(45, 45, 45, 255); config->colors[GUI_COLOR_HISTO] = gui_make_color(100, 100, 100, 255); config->colors[GUI_COLOR_HISTO_BARS] = gui_make_color(45, 45, 45, 255); config->colors[GUI_COLOR_HISTO_NEGATIVE] = gui_make_color(255, 255, 255, 255); @@ -1307,7 +1501,8 @@ gui_panel_text_wrap(struct gui_panel *panel, const char *str, gui_size len) } gui_int -gui_panel_button_text(struct gui_panel *panel, const char *str, gui_size len) +gui_panel_button_text(struct gui_panel *panel, const char *str, gui_size len, + enum gui_button_behavior behavior) { struct gui_rect bounds; struct gui_button button; @@ -1322,6 +1517,7 @@ gui_panel_button_text(struct gui_panel *panel, const char *str, gui_size len) button.y = bounds.y; button.w = bounds.w; button.h = bounds.h; + button.behavior = behavior; button.pad_x = config->item_padding.x; button.pad_y = config->item_padding.y; button.background = config->colors[GUI_COLOR_BUTTON]; @@ -1332,7 +1528,8 @@ gui_panel_button_text(struct gui_panel *panel, const char *str, gui_size len) } gui_int -gui_panel_button_triangle(struct gui_panel *panel, enum gui_direction d) +gui_panel_button_triangle(struct gui_panel *panel, enum gui_direction d, + enum gui_button_behavior behavior) { struct gui_rect bounds; struct gui_button button; @@ -1347,6 +1544,7 @@ gui_panel_button_triangle(struct gui_panel *panel, enum gui_direction d) button.y = bounds.y; button.w = bounds.w; button.h = bounds.h; + button.behavior = behavior; button.pad_x = config->item_padding.x; button.pad_y = config->item_padding.y; button.background = config->colors[GUI_COLOR_BUTTON]; @@ -1358,7 +1556,8 @@ gui_panel_button_triangle(struct gui_panel *panel, enum gui_direction d) gui_int gui_panel_button_image(struct gui_panel *panel, gui_texture tex, - struct gui_texCoord from, struct gui_texCoord to) + struct gui_texCoord from, struct gui_texCoord to, + enum gui_button_behavior behavior) { struct gui_rect bounds; struct gui_button button; @@ -1372,6 +1571,7 @@ gui_panel_button_image(struct gui_panel *panel, gui_texture tex, button.y = bounds.y; button.w = bounds.w; button.h = bounds.h; + button.behavior = behavior; button.pad_x = config->item_padding.x; button.pad_y = config->item_padding.y; button.background = config->colors[GUI_COLOR_BUTTON]; @@ -1466,14 +1666,14 @@ gui_panel_progress(struct gui_panel *panel, gui_size cur_value, gui_size max_val gui_int gui_panel_input(struct gui_panel *panel, gui_char *buffer, gui_size *length, - gui_size max_length, gui_bool is_active) + gui_size max_length, enum gui_input_filter filter, gui_bool is_active) { struct gui_rect bounds; struct gui_input_field field; const struct gui_config *config; - if (!panel || !panel->config || !panel->in || !panel->out) return is_active; - if (!panel->font || panel->minimized) return is_active; + if (!panel || !panel->config || !panel->in || !panel->out) return 0; + if (!panel->font || panel->minimized) return 0; gui_panel_alloc_space(&bounds, panel); config = panel->config; @@ -1484,6 +1684,7 @@ gui_panel_input(struct gui_panel *panel, gui_char *buffer, gui_size *length, field.pad_x = config->item_padding.x; field.pad_y = config->item_padding.y; field.max = max_length; + field.filter = filter; field.active = is_active; field.font = config->colors[GUI_COLOR_TEXT]; field.background = config->colors[GUI_COLOR_INPUT]; @@ -1491,6 +1692,64 @@ gui_panel_input(struct gui_panel *panel, gui_char *buffer, gui_size *length, return gui_input(panel->out, buffer, length, &field, panel->font, panel->in); } +gui_size +gui_panel_command(struct gui_panel *panel, gui_char *buffer, gui_size *length, + gui_size max, gui_int *active) +{ + struct gui_rect bounds; + struct gui_input_field field; + const struct gui_config *config; + + if (!panel || !panel->config || !panel->in || !panel->out) return 0; + if (!panel->font || panel->minimized || !active) return 0; + gui_panel_alloc_space(&bounds, panel); + config = panel->config; + + field.x = bounds.x; + field.y = bounds.y; + field.w = bounds.w; + field.h = bounds.h; + field.pad_x = config->item_padding.x; + field.pad_y = config->item_padding.y; + field.max = max; + field.filter = GUI_INPUT_DEFAULT; + field.active = *active; + field.font = config->colors[GUI_COLOR_TEXT]; + field.background = config->colors[GUI_COLOR_INPUT]; + field.foreground = config->colors[GUI_COLOR_INPUT_BORDER]; + return gui_command(panel->out, buffer, length, active, &field, panel->font, panel->in); +} + +gui_int +gui_panel_spinner(struct gui_panel *panel, gui_int min, gui_int *value, + gui_int max, gui_int step, gui_int active) +{ + struct gui_rect bounds; + struct gui_spinner spinner; + const struct gui_config *config; + + if (!panel || !panel->config || !panel->in || !panel->out) return 0; + if (!panel->font || panel->minimized) return 0; + gui_panel_alloc_space(&bounds, panel); + config = panel->config; + + spinner.x = bounds.x; + spinner.y = bounds.y; + spinner.w = bounds.w; + spinner.h = bounds.h; + spinner.pad_x = config->item_padding.x; + spinner.pad_y = config->item_padding.y; + spinner.min = min; + spinner.max = max; + spinner.step = step; + spinner.active = active; + spinner.background = config->colors[GUI_COLOR_SPINNER]; + spinner.foreground = config->colors[GUI_COLOR_SPINNER_BORDER]; + spinner.button = config->colors[GUI_COLOR_SPINNER_BUTTON]; + spinner.font = config->colors[GUI_COLOR_TEXT]; + return gui_spinner(panel->out, &spinner, value, panel->font, panel->in); +} + gui_int gui_panel_plot(struct gui_panel *panel, const gui_float *values, gui_size count) { diff --git a/gui.h b/gui.h index 4684b11..9049ac1 100644 --- a/gui.h +++ b/gui.h @@ -9,18 +9,17 @@ /* * ------------- TODO-List ------------ * - widgets - * o Input (1) - * o Counter + * o Input cursor * - panel - * o Group (4) - * o Border (3) + * o Group (3) + * o Border (2) * o Moveable * o Scaleable - * o Scrollbar (2) + * o Scrollbar (1) * o Tabs * o Icon * o combobox - * o listView (5) + * o listView (4) * o treeView * o textBox * --------------------------------------- @@ -133,14 +132,20 @@ struct gui_image { struct gui_color background; }; +enum gui_button_behavior { + GUI_BUTTON_SWITCH, + GUI_BUTTON_REPEATER +}; + struct gui_button { gui_float x, y; gui_float w, h; gui_float pad_x, pad_y; - struct gui_color font; + enum gui_button_behavior behavior; struct gui_color background; struct gui_color foreground; struct gui_color highlight; + struct gui_color font; }; struct gui_toggle { @@ -187,11 +192,13 @@ struct gui_scroll { struct gui_color foreground; }; -enum gui_input_flags { - GUI_INPUT_ALL = -1, - GUI_INPUT_INTEGER = 0x01, - GUI_INPUT_FLOAT = 0x02, - GUI_INPUT_LITERALS = 0x04, +enum gui_input_filter { + GUI_INPUT_DEFAULT, + GUI_INPUT_FLOAT, + GUI_INPUT_DEC, + GUI_INPUT_HEX, + GUI_INPUT_OCT, + GUI_INPUT_BIN, }; struct gui_input_field { @@ -200,7 +207,7 @@ struct gui_input_field { gui_float pad_x, pad_y; gui_size max; gui_bool active; - gui_flags flags; + enum gui_input_filter filter; gui_bool password; struct gui_color background; struct gui_color foreground; @@ -212,10 +219,12 @@ struct gui_spinner { gui_float w, h; gui_float pad_x, pad_y; gui_bool active; - gui_float max; - gui_float min; + gui_int step; + gui_int max; + gui_int min; struct gui_color background; struct gui_color foreground; + struct gui_color button; struct gui_color font; }; @@ -261,6 +270,9 @@ enum gui_colors { GUI_COLOR_PROGRESS_CURSOR, GUI_COLOR_INPUT, GUI_COLOR_INPUT_BORDER, + GUI_COLOR_SPINNER, + GUI_COLOR_SPINNER_BORDER, + GUI_COLOR_SPINNER_BUTTON, GUI_COLOR_HISTO, GUI_COLOR_HISTO_BARS, GUI_COLOR_HISTO_NEGATIVE, @@ -341,9 +353,12 @@ gui_size gui_progress(struct gui_draw_buffer *buf, const struct gui_progress *pr gui_int gui_input(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length, const struct gui_input_field *input, const struct gui_font *font, const struct gui_input *in); -gui_int gui_spinner(struct gui_draw_buffer *buf, const struct gui_spinner *spinner, - gui_float *value, gui_float *step, +gui_size gui_command(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length, + gui_int *active, const struct gui_input_field *input, const struct gui_font *font, const struct gui_input *in); +gui_int gui_spinner(struct gui_draw_buffer *buf, const struct gui_spinner *spinner, + gui_int *value, const struct gui_font *font, + const struct gui_input *in); gui_size gui_scroll(struct gui_draw_buffer *buf, const struct gui_scroll *scroll, const struct gui_input *in); gui_int gui_histo(struct gui_draw_buffer *buf, const struct gui_histo *histo, @@ -362,10 +377,13 @@ void gui_panel_row(struct gui_panel *panel, gui_float height, gui_size cols); void gui_panel_seperator(struct gui_panel *panel, gui_size cols); void gui_panel_text(struct gui_panel *panel, const char *str, gui_size len); gui_size gui_panel_text_wrap(struct gui_panel *panel, const char *str, gui_size len); -gui_int gui_panel_button_text(struct gui_panel *panel, const char *str, gui_size len); -gui_int gui_panel_button_triangle(struct gui_panel *panel, enum gui_direction d); +gui_int gui_panel_button_text(struct gui_panel *panel, const char *str, gui_size len, + enum gui_button_behavior behavior); +gui_int gui_panel_button_triangle(struct gui_panel *panel, enum gui_direction d, + enum gui_button_behavior behavior); gui_int gui_panel_button_image(struct gui_panel *panel, gui_texture tex, - struct gui_texCoord from, struct gui_texCoord to); + struct gui_texCoord from, struct gui_texCoord to, + enum gui_button_behavior behavior); gui_int gui_panel_toggle(struct gui_panel *panel, const char *str, gui_size len, gui_int active); gui_float gui_panel_slider(struct gui_panel *panel, gui_float min, gui_float v, @@ -373,7 +391,11 @@ gui_float gui_panel_slider(struct gui_panel *panel, gui_float min, gui_float v, gui_size gui_panel_progress(struct gui_panel *panel, gui_size cur, gui_size max, gui_bool modifyable); gui_int gui_panel_input(struct gui_panel *panel, gui_char *buffer, gui_size *len, - gui_size max, gui_bool active); + gui_size max, enum gui_input_filter filter, gui_bool active); +gui_size gui_panel_command(struct gui_panel *panel, gui_char *buffer, gui_size *length, + gui_size max, gui_int *active); +gui_int gui_panel_spinner(struct gui_panel *panel, gui_int min, gui_int *value, + gui_int max, gui_int step, gui_int active); gui_int gui_panel_plot(struct gui_panel *panel, const gui_float *values, gui_size value_count); gui_int gui_panel_histo(struct gui_panel *panel, const gui_float *values, diff --git a/opengl.c b/opengl.c index 14728bb..9c8950a 100644 --- a/opengl.c +++ b/opengl.c @@ -425,11 +425,17 @@ main(int argc, char *argv[]) static GLint att[] = {GLX_RGBA, GLX_DEPTH_SIZE,24, GLX_DOUBLEBUFFER, None}; gui_char input_text[INPUT_MAX]; + gui_char cmd_input[INPUT_MAX]; gui_size input_len = 0; + gui_size cmd_len = 0; gui_int typing = 0; gui_float slider = 5.0f; gui_size prog = 60; + gui_int spinner = 100; gui_int selected = gui_false; + gui_int spinning = gui_false; + gui_size submit = 0; + gui_int submitting = 0; const char *s[] = {"inactive", "active"}; const gui_float values[] = {10.0f, 12.5f, 18.0f, 15.0f, 25.0f, 30.0f}; @@ -490,13 +496,16 @@ main(int argc, char *argv[]) GUI_PANEL_HEADER|GUI_PANEL_CLOSEABLE|GUI_PANEL_MINIMIZABLE, 20, 20, 200, 0); gui_panel_row(&gui.panel, 30, 1); - gui_panel_text(&gui.panel, "Text", 4); - if (gui_panel_button_text(&gui.panel, "button", 6)) + if (gui_panel_button_text(&gui.panel, "button", 6, GUI_BUTTON_SWITCH)) fprintf(stdout, "button pressed!\n"); slider = gui_panel_slider(&gui.panel, 0.0f, slider, 10.0f, 1.0f); prog = gui_panel_progress(&gui.panel, prog, 100, gui_true); selected = gui_panel_toggle(&gui.panel, s[selected], strlen(s[selected]), selected); - typing = gui_panel_input(&gui.panel, input_text, &input_len, INPUT_MAX, typing); + typing = gui_panel_input(&gui.panel, input_text, &input_len, INPUT_MAX, + GUI_INPUT_DEFAULT, typing); + submit = gui_panel_command(&gui.panel, cmd_input, &cmd_len, INPUT_MAX, + &submitting); + spinning = gui_panel_spinner(&gui.panel, 0, &spinner, 250, 10, spinning); gui_panel_row(&gui.panel, 100, 1); gui_panel_plot(&gui.panel, values, LEN(values)); gui_panel_histo(&gui.panel, values, LEN(values));