added spinner + command input

This commit is contained in:
vurtun 2015-03-14 17:05:30 +01:00
parent a80f80c141
commit cbc25a5d5f
4 changed files with 373 additions and 60 deletions

View File

@ -1,4 +1,27 @@
# GUI # 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 # License
(The MIT License) (The MIT License)

327
gui.c
View File

@ -7,6 +7,7 @@
#define NULL (void*)0 #define NULL (void*)0
#define UTF_INVALID 0xFFFD #define UTF_INVALID 0xFFFD
#define MAX_NUMBER_BUFFER 64
#define PASTE(a,b) a##b #define PASTE(a,b) a##b
#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) < (b) ? (b) : (a)) #define MAX(a,b) ((a) < (b) ? (b) : (a))
@ -31,10 +32,10 @@
static const gui_texture null_tex = (void*)0; static const gui_texture null_tex = (void*)0;
static const struct gui_rect null_rect = {-9999, -9999, 9999 * 2, 9999 * 2}; 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 const 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 const 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 const 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 long utfmax[GUI_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
static gui_float static gui_float
fsqrt(float x) fsqrt(float x)
@ -42,7 +43,6 @@ fsqrt(float x)
float xhalf = 0.5f*x; float xhalf = 0.5f*x;
union {float f; int i;} val; union {float f; int i;} val;
ASSERT(sizeof(int) == sizeof(float)); ASSERT(sizeof(int) == sizeof(float));
val.f = x; val.f = x;
val.i = 0x5f375a86 - (val.i >> 1); val.i = 0x5f375a86 - (val.i >> 1);
val.f = val.f * (1.5f - xhalf * val.f * val.f); 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; 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 static gui_size
utf_validate(long *u, gui_size i) 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_font_chars_in_space(const struct gui_font *font, const gui_char *text, gui_size len,
gui_float space) gui_float space)
{ {
const struct gui_font_glyph *glyph;
gui_size chars = 0; gui_size chars = 0;
gui_long unicode; gui_long unicode;
gui_size text_width = 0; gui_size text_width = 0;
const struct gui_font_glyph *glyph;
gui_size text_len = 0; gui_size text_len = 0;
gui_size glyph_len; 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; struct gui_draw_command *cmd;
if (!buffer) return; if (!buffer) return;
if (col.a == 0) 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, y, x + w, y, col);
gui_vertex_line(buffer, x + w, y, x + w, y + h, 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); 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; font_color = button->font;
background = button->background; background = button->background;
highlight = button->highlight;
button_w = MAX(button->w, 2 * button->pad_x); button_w = MAX(button->w, 2 * button->pad_x);
button_h = MAX(button->h, 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; font_color = button->background;
background = button->highlight; background = button->highlight;
if (INBOX(in->mouse_clicked_pos.x, in->mouse_clicked_pos.y, if (INBOX(in->mouse_clicked_pos.x, in->mouse_clicked_pos.y,
button->x, button->y, button_w, button_h)) button->x, button->y, button_w, button_h)) {
if (button->behavior == GUI_BUTTON_SWITCH)
ret = (in->mouse_down && in->mouse_clicked); 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_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); 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; 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_int
gui_input(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length, gui_input(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length,
const struct gui_input_field *input, const struct gui_input_field *input,
const struct gui_font *font, const struct gui_input *in) const struct gui_font *font, const struct gui_input *in)
{ {
gui_size offset = 0;
gui_float input_w, input_h; gui_float input_w, input_h;
gui_int input_active; gui_int input_active;
if (!buffer || !in || !font || !input) 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; input_active = gui_false;
if ((space->down && space->clicked) && (*length < input->max)) if ((space->down && space->clicked) && (*length < input->max))
buffer[(*length)++] = ' '; buffer[(*length)++] = ' ';
if (in->text_len && *length < input->max)
if (in->text_len && *length < input->max) { gui_buffer_input(buffer, length, input->max, input->filter, in);
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 (font && buffer && length && *length) { if (font && buffer && length && *length) {
gui_size offset = 0;
gui_float label_x = input->x + input->pad_x; gui_float label_x = input->x + input->pad_x;
gui_float label_y = input->y + input->pad_y; gui_float label_y = input->y + input->pad_y;
gui_float label_w = input_w - 2 * input->pad_x; gui_float label_w = input_w - 2 * input->pad_x;
@ -873,16 +967,113 @@ gui_input(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length,
return input_active; 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_int
gui_plot(struct gui_draw_buffer *buffer, const struct gui_plot *plot, gui_plot(struct gui_draw_buffer *buffer, const struct gui_plot *plot,
const struct gui_input *in) const struct gui_input *in)
{ {
gui_size i; gui_size i;
gui_size plot_step;
gui_float plot_w, plot_h;
gui_int plot_selected = -1; gui_int plot_selected = -1;
gui_float plot_max_value, plot_min_value; gui_float plot_max_value, plot_min_value;
gui_float plot_value_range, plot_value_ratio; 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_x, canvas_y;
gui_float canvas_w, canvas_h; gui_float canvas_w, canvas_h;
gui_float last_x; gui_float last_x;
@ -1008,7 +1199,6 @@ gui_scroll(struct gui_draw_buffer *buffer, const struct gui_scroll *scroll,
gui_bool inscroll, incursor; gui_bool inscroll, incursor;
if (!buffer || !in || !scroll) return 0; if (!buffer || !in || !scroll) return 0;
scroll_y = scroll->y;
scroll_w = MAX(scroll->w, 0); scroll_w = MAX(scroll->w, 0);
scroll_h = MAX(scroll->h, 2 * scroll_w); scroll_h = MAX(scroll->h, 2 * scroll_w);
gui_draw_rectf(buffer, scroll->x, scroll->y, scroll_w, scroll_h, scroll->background); 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.background = scroll->foreground;
button.foreground = scroll->background; button.foreground = scroll->background;
button.highlight = scroll->foreground; button.highlight = scroll->foreground;
button.behavior = GUI_BUTTON_SWITCH;
button_up_pressed = gui_button_triangle(buffer, &button, GUI_UP, in); button_up_pressed = gui_button_triangle(buffer, &button, GUI_UP, in);
button.y = scroll->y + scroll_h - button.h; button.y = scroll->y + scroll_h - button.h;
button_down_pressed = gui_button_triangle(buffer, &button, GUI_DOWN, in); 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_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] = gui_make_color(100, 100, 100, 255);
config->colors[GUI_COLOR_PROGRESS_CURSOR] = gui_make_color(45, 45, 45, 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] = gui_make_color(45, 45, 45, 255);
config->colors[GUI_COLOR_INPUT_BORDER] = gui_make_color(100, 100, 100, 100); 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] = 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_BARS] = gui_make_color(45, 45, 45, 255);
config->colors[GUI_COLOR_HISTO_NEGATIVE] = gui_make_color(255, 255, 255, 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_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_rect bounds;
struct gui_button button; 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.y = bounds.y;
button.w = bounds.w; button.w = bounds.w;
button.h = bounds.h; button.h = bounds.h;
button.behavior = behavior;
button.pad_x = config->item_padding.x; button.pad_x = config->item_padding.x;
button.pad_y = config->item_padding.y; button.pad_y = config->item_padding.y;
button.background = config->colors[GUI_COLOR_BUTTON]; 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_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_rect bounds;
struct gui_button button; 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.y = bounds.y;
button.w = bounds.w; button.w = bounds.w;
button.h = bounds.h; button.h = bounds.h;
button.behavior = behavior;
button.pad_x = config->item_padding.x; button.pad_x = config->item_padding.x;
button.pad_y = config->item_padding.y; button.pad_y = config->item_padding.y;
button.background = config->colors[GUI_COLOR_BUTTON]; 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_int
gui_panel_button_image(struct gui_panel *panel, gui_texture tex, 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_rect bounds;
struct gui_button button; struct gui_button button;
@ -1372,6 +1571,7 @@ gui_panel_button_image(struct gui_panel *panel, gui_texture tex,
button.y = bounds.y; button.y = bounds.y;
button.w = bounds.w; button.w = bounds.w;
button.h = bounds.h; button.h = bounds.h;
button.behavior = behavior;
button.pad_x = config->item_padding.x; button.pad_x = config->item_padding.x;
button.pad_y = config->item_padding.y; button.pad_y = config->item_padding.y;
button.background = config->colors[GUI_COLOR_BUTTON]; 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_int
gui_panel_input(struct gui_panel *panel, gui_char *buffer, gui_size *length, 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_rect bounds;
struct gui_input_field field; struct gui_input_field field;
const struct gui_config *config; const struct gui_config *config;
if (!panel || !panel->config || !panel->in || !panel->out) return is_active; if (!panel || !panel->config || !panel->in || !panel->out) return 0;
if (!panel->font || panel->minimized) return is_active; if (!panel->font || panel->minimized) return 0;
gui_panel_alloc_space(&bounds, panel); gui_panel_alloc_space(&bounds, panel);
config = panel->config; 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_x = config->item_padding.x;
field.pad_y = config->item_padding.y; field.pad_y = config->item_padding.y;
field.max = max_length; field.max = max_length;
field.filter = filter;
field.active = is_active; field.active = is_active;
field.font = config->colors[GUI_COLOR_TEXT]; field.font = config->colors[GUI_COLOR_TEXT];
field.background = config->colors[GUI_COLOR_INPUT]; 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); 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_int
gui_panel_plot(struct gui_panel *panel, const gui_float *values, gui_size count) gui_panel_plot(struct gui_panel *panel, const gui_float *values, gui_size count)
{ {

64
gui.h
View File

@ -9,18 +9,17 @@
/* /*
* ------------- TODO-List ------------ * ------------- TODO-List ------------
* - widgets * - widgets
* o Input (1) * o Input cursor
* o Counter
* - panel * - panel
* o Group (4) * o Group (3)
* o Border (3) * o Border (2)
* o Moveable * o Moveable
* o Scaleable * o Scaleable
* o Scrollbar (2) * o Scrollbar (1)
* o Tabs * o Tabs
* o Icon * o Icon
* o combobox * o combobox
* o listView (5) * o listView (4)
* o treeView * o treeView
* o textBox * o textBox
* --------------------------------------- * ---------------------------------------
@ -133,14 +132,20 @@ struct gui_image {
struct gui_color background; struct gui_color background;
}; };
enum gui_button_behavior {
GUI_BUTTON_SWITCH,
GUI_BUTTON_REPEATER
};
struct gui_button { struct gui_button {
gui_float x, y; gui_float x, y;
gui_float w, h; gui_float w, h;
gui_float pad_x, pad_y; gui_float pad_x, pad_y;
struct gui_color font; enum gui_button_behavior behavior;
struct gui_color background; struct gui_color background;
struct gui_color foreground; struct gui_color foreground;
struct gui_color highlight; struct gui_color highlight;
struct gui_color font;
}; };
struct gui_toggle { struct gui_toggle {
@ -187,11 +192,13 @@ struct gui_scroll {
struct gui_color foreground; struct gui_color foreground;
}; };
enum gui_input_flags { enum gui_input_filter {
GUI_INPUT_ALL = -1, GUI_INPUT_DEFAULT,
GUI_INPUT_INTEGER = 0x01, GUI_INPUT_FLOAT,
GUI_INPUT_FLOAT = 0x02, GUI_INPUT_DEC,
GUI_INPUT_LITERALS = 0x04, GUI_INPUT_HEX,
GUI_INPUT_OCT,
GUI_INPUT_BIN,
}; };
struct gui_input_field { struct gui_input_field {
@ -200,7 +207,7 @@ struct gui_input_field {
gui_float pad_x, pad_y; gui_float pad_x, pad_y;
gui_size max; gui_size max;
gui_bool active; gui_bool active;
gui_flags flags; enum gui_input_filter filter;
gui_bool password; gui_bool password;
struct gui_color background; struct gui_color background;
struct gui_color foreground; struct gui_color foreground;
@ -212,10 +219,12 @@ struct gui_spinner {
gui_float w, h; gui_float w, h;
gui_float pad_x, pad_y; gui_float pad_x, pad_y;
gui_bool active; gui_bool active;
gui_float max; gui_int step;
gui_float min; gui_int max;
gui_int min;
struct gui_color background; struct gui_color background;
struct gui_color foreground; struct gui_color foreground;
struct gui_color button;
struct gui_color font; struct gui_color font;
}; };
@ -261,6 +270,9 @@ enum gui_colors {
GUI_COLOR_PROGRESS_CURSOR, GUI_COLOR_PROGRESS_CURSOR,
GUI_COLOR_INPUT, GUI_COLOR_INPUT,
GUI_COLOR_INPUT_BORDER, GUI_COLOR_INPUT_BORDER,
GUI_COLOR_SPINNER,
GUI_COLOR_SPINNER_BORDER,
GUI_COLOR_SPINNER_BUTTON,
GUI_COLOR_HISTO, GUI_COLOR_HISTO,
GUI_COLOR_HISTO_BARS, GUI_COLOR_HISTO_BARS,
GUI_COLOR_HISTO_NEGATIVE, 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, gui_int gui_input(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length,
const struct gui_input_field *input, const struct gui_input_field *input,
const struct gui_font *font, const struct gui_input *in); 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_size gui_command(struct gui_draw_buffer *buf, gui_char *buffer, gui_size *length,
gui_float *value, gui_float *step, gui_int *active, const struct gui_input_field *input,
const struct gui_font *font, const struct gui_input *in); 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, gui_size gui_scroll(struct gui_draw_buffer *buf, const struct gui_scroll *scroll,
const struct gui_input *in); const struct gui_input *in);
gui_int gui_histo(struct gui_draw_buffer *buf, const struct gui_histo *histo, 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_seperator(struct gui_panel *panel, gui_size cols);
void gui_panel_text(struct gui_panel *panel, const char *str, gui_size len); 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_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_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); 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, 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 gui_panel_toggle(struct gui_panel *panel, const char *str, gui_size len,
gui_int active); gui_int active);
gui_float gui_panel_slider(struct gui_panel *panel, gui_float min, gui_float v, 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_size gui_panel_progress(struct gui_panel *panel, gui_size cur, gui_size max,
gui_bool modifyable); gui_bool modifyable);
gui_int gui_panel_input(struct gui_panel *panel, gui_char *buffer, gui_size *len, 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_int gui_panel_plot(struct gui_panel *panel, const gui_float *values,
gui_size value_count); gui_size value_count);
gui_int gui_panel_histo(struct gui_panel *panel, const gui_float *values, gui_int gui_panel_histo(struct gui_panel *panel, const gui_float *values,

View File

@ -425,11 +425,17 @@ main(int argc, char *argv[])
static GLint att[] = {GLX_RGBA, GLX_DEPTH_SIZE,24, GLX_DOUBLEBUFFER, None}; static GLint att[] = {GLX_RGBA, GLX_DEPTH_SIZE,24, GLX_DOUBLEBUFFER, None};
gui_char input_text[INPUT_MAX]; gui_char input_text[INPUT_MAX];
gui_char cmd_input[INPUT_MAX];
gui_size input_len = 0; gui_size input_len = 0;
gui_size cmd_len = 0;
gui_int typing = 0; gui_int typing = 0;
gui_float slider = 5.0f; gui_float slider = 5.0f;
gui_size prog = 60; gui_size prog = 60;
gui_int spinner = 100;
gui_int selected = gui_false; gui_int selected = gui_false;
gui_int spinning = gui_false;
gui_size submit = 0;
gui_int submitting = 0;
const char *s[] = {"inactive", "active"}; const char *s[] = {"inactive", "active"};
const gui_float values[] = {10.0f, 12.5f, 18.0f, 15.0f, 25.0f, 30.0f}; 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, GUI_PANEL_HEADER|GUI_PANEL_CLOSEABLE|GUI_PANEL_MINIMIZABLE,
20, 20, 200, 0); 20, 20, 200, 0);
gui_panel_row(&gui.panel, 30, 1); gui_panel_row(&gui.panel, 30, 1);
gui_panel_text(&gui.panel, "Text", 4); if (gui_panel_button_text(&gui.panel, "button", 6, GUI_BUTTON_SWITCH))
if (gui_panel_button_text(&gui.panel, "button", 6))
fprintf(stdout, "button pressed!\n"); fprintf(stdout, "button pressed!\n");
slider = gui_panel_slider(&gui.panel, 0.0f, slider, 10.0f, 1.0f); slider = gui_panel_slider(&gui.panel, 0.0f, slider, 10.0f, 1.0f);
prog = gui_panel_progress(&gui.panel, prog, 100, gui_true); prog = gui_panel_progress(&gui.panel, prog, 100, gui_true);
selected = gui_panel_toggle(&gui.panel, s[selected], strlen(s[selected]), selected); 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_row(&gui.panel, 100, 1);
gui_panel_plot(&gui.panel, values, LEN(values)); gui_panel_plot(&gui.panel, values, LEN(values));
gui_panel_histo(&gui.panel, values, LEN(values)); gui_panel_histo(&gui.panel, values, LEN(values));