changed api
This commit is contained in:
parent
2c6428552a
commit
098dc82f1b
2
Makefile
2
Makefile
|
@ -8,7 +8,7 @@ DCC = clang
|
||||||
# Flags
|
# Flags
|
||||||
CFLAGS = -std=c89 -pedantic-errors -Wno-deprecated-declarations -D_POSIX_C_SOURCE=200809L
|
CFLAGS = -std=c89 -pedantic-errors -Wno-deprecated-declarations -D_POSIX_C_SOURCE=200809L
|
||||||
CFLAGS += -g -Wall -Wextra -Werror -Wformat -Wunreachable-code
|
CFLAGS += -g -Wall -Wextra -Werror -Wformat -Wunreachable-code
|
||||||
CFLAGS += -Winline -Wshadow -Wwrite-strings -Wno-unused-variable -Wno-unused-parameter -Wno-unused-function
|
CFLAGS += -Winline -Wshadow -Wwrite-strings
|
||||||
CFLAGS += -Wstrict-prototypes -Wold-style-definition
|
CFLAGS += -Wstrict-prototypes -Wold-style-definition
|
||||||
CFLAGS += -Wredundant-decls -Wnested-externs -Wmissing-include-dirs
|
CFLAGS += -Wredundant-decls -Wnested-externs -Wmissing-include-dirs
|
||||||
CFLAGS += -Wshadow -Wpointer-arith -Wcast-qual -Wmissing-prototypes
|
CFLAGS += -Wshadow -Wpointer-arith -Wcast-qual -Wmissing-prototypes
|
||||||
|
|
485
gui.c
485
gui.c
|
@ -126,10 +126,13 @@ utf_encode(gui_long u, gui_char *c, gui_size clen)
|
||||||
void
|
void
|
||||||
gui_input_begin(struct gui_input *in)
|
gui_input_begin(struct gui_input *in)
|
||||||
{
|
{
|
||||||
|
gui_size i;
|
||||||
if (!in) return;
|
if (!in) return;
|
||||||
in->mouse_clicked = 0;
|
in->mouse_clicked = 0;
|
||||||
in->text_len = 0;
|
in->text_len = 0;
|
||||||
vec2_mov(in->mouse_prev, in->mouse_pos);
|
vec2_mov(in->mouse_prev, in->mouse_pos);
|
||||||
|
for (i = 0; i < GUI_KEY_MAX; i++)
|
||||||
|
in->keys[i].clicked = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -142,7 +145,9 @@ void
|
||||||
gui_input_key(struct gui_input *in, enum gui_keys key, gui_int down)
|
gui_input_key(struct gui_input *in, enum gui_keys key, gui_int down)
|
||||||
{
|
{
|
||||||
if (!in) return;
|
if (!in) return;
|
||||||
in->keys[key] = down;
|
if (in->keys[key].down == down) return;
|
||||||
|
in->keys[key].down = down;
|
||||||
|
in->keys[key].clicked++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -328,14 +333,13 @@ gui_rectf(struct gui_draw_queue *que, gui_float x, gui_float y,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gui_text(struct gui_draw_queue *que, const struct gui_font *font, gui_float x,
|
gui_string(struct gui_draw_queue *que, const struct gui_font *font, gui_float x,
|
||||||
gui_float y, gui_float w, gui_float h,
|
gui_float y, gui_float w, gui_float h,
|
||||||
struct gui_color col, const gui_char *t, gui_size len)
|
struct gui_color col, const gui_char *t, gui_size len)
|
||||||
{
|
{
|
||||||
struct gui_draw_command *cmd;
|
struct gui_draw_command *cmd;
|
||||||
struct gui_rect clip;
|
struct gui_rect clip;
|
||||||
gui_size text_len;
|
gui_size text_len;
|
||||||
gui_float off = 0;
|
|
||||||
gui_long unicode;
|
gui_long unicode;
|
||||||
const struct gui_font_glyph *g;
|
const struct gui_font_glyph *g;
|
||||||
|
|
||||||
|
@ -411,64 +415,85 @@ gui_end(struct gui_draw_queue *que)
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_int
|
gui_int
|
||||||
gui_button(struct gui_draw_queue *que, const struct gui_input *in,
|
gui_button(struct gui_draw_queue *que, const struct gui_button *button,
|
||||||
const struct gui_font *font, struct gui_color bg, struct gui_color fg,
|
const struct gui_font *font, const struct gui_input *in)
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
|
|
||||||
const char *str, gui_int l)
|
|
||||||
{
|
{
|
||||||
gui_int text_width;
|
gui_int text_width;
|
||||||
gui_int label_x, label_y;
|
gui_int label_x, label_y;
|
||||||
gui_int label_w, label_h;
|
gui_int label_w, label_h;
|
||||||
gui_int ret = gui_false;
|
gui_int ret = gui_false;
|
||||||
const gui_char *t = (const gui_char*)str;
|
gui_int mouse_x, mouse_y;
|
||||||
|
gui_int clicked_x, clicked_y;
|
||||||
|
struct gui_color fc, bg, hc;
|
||||||
|
gui_int x, y, w, h;
|
||||||
|
const gui_char *t;
|
||||||
|
|
||||||
if (!que || !in) return gui_false;
|
if (!que || !in || !button)
|
||||||
if (!in->mouse_down && in->mouse_clicked) {
|
return gui_false;
|
||||||
const gui_int clicked_x = in->mouse_clicked_pos.x;
|
|
||||||
const gui_int clicked_y = in->mouse_clicked_pos.y;
|
x = button->x, y = button->y;
|
||||||
|
w = button->w, h = button->h;
|
||||||
|
t = (const gui_char*)button->text;
|
||||||
|
mouse_x = in->mouse_pos.x;
|
||||||
|
mouse_y = in->mouse_pos.y;
|
||||||
|
clicked_x = in->mouse_clicked_pos.x;
|
||||||
|
clicked_y = in->mouse_clicked_pos.y;
|
||||||
|
fc = button->font;
|
||||||
|
bg = button->background;
|
||||||
|
hc = button->highlight;
|
||||||
|
|
||||||
|
if (INBOX(mouse_x, mouse_y, x, y, x+w, y+h)) {
|
||||||
if (INBOX(clicked_x, clicked_y, x, y, x+w, y+h))
|
if (INBOX(clicked_x, clicked_y, x, y, x+w, y+h))
|
||||||
ret = gui_true;
|
ret = (in->mouse_down && in->mouse_clicked);
|
||||||
|
fc = bg; bg = hc;
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_rectf(que, x, y, w, h, bg);
|
gui_rectf(que, x, y, w, h, bg);
|
||||||
gui_rect(que, x+1, y+1, w-1, h-1, fg);
|
gui_rect(que, x+1, y+1, w-1, h-1, button->foreground);
|
||||||
if (!font || !str || !l) return ret;
|
if (!font || !button->text || !button->length) return ret;
|
||||||
|
|
||||||
text_width = gui_font_text_width(font, t, l);
|
text_width = gui_font_text_width(font, t, button->length);
|
||||||
if (text_width > (w - 2 * pad)) {
|
if (text_width > (w - 2 * button->pad_x)) {
|
||||||
label_x = x + pad;
|
label_x = x + button->pad_x;
|
||||||
label_y = y + pad;
|
label_y = y + button->pad_y;
|
||||||
label_w = w - 2 * pad;
|
label_w = w - 2 * button->pad_x;
|
||||||
label_h = h - 2 * pad;
|
label_h = h - 2 * button->pad_y;
|
||||||
} else {
|
} else {
|
||||||
label_w = w - 2 * pad;
|
label_w = w - 2 * button->pad_x;
|
||||||
label_h = h - 2 * pad;
|
label_h = h - 2 * button->pad_y;
|
||||||
label_x = x + (label_w - text_width) / 2;
|
label_x = x + (label_w - text_width) / 2;
|
||||||
label_y = y + (label_h - font->height) / 2;
|
label_y = y + (label_h - font->height) / 2;
|
||||||
}
|
}
|
||||||
gui_text(que, font, label_x, label_y, label_w, label_h, fg, t, l);
|
gui_string(que, font, label_x, label_y, label_w, label_h, fc, t, button->length);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_int
|
gui_int
|
||||||
gui_toggle(struct gui_draw_queue *que, const struct gui_input *in,
|
gui_toggle(struct gui_draw_queue *que, const struct gui_toggle *toggle,
|
||||||
const struct gui_font *font, struct gui_color bg, struct gui_color fg,
|
const struct gui_font *font, const struct gui_input *in)
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
|
|
||||||
const char *str, gui_int len, gui_int active)
|
|
||||||
{
|
{
|
||||||
gui_int select_size;
|
gui_int select_size;
|
||||||
|
gui_int x, y, w, h;
|
||||||
|
gui_int active;
|
||||||
gui_int select_x, select_y;
|
gui_int select_x, select_y;
|
||||||
gui_int cursor_x, cursor_y;
|
gui_int cursor_x, cursor_y;
|
||||||
gui_int cursor_pad, cursor_size;
|
gui_int cursor_pad, cursor_size;
|
||||||
gui_int label_x, label_w;
|
gui_int label_x, label_w;
|
||||||
const struct gui_color white = {255, 255, 255, 255};
|
struct gui_color fg, bg;
|
||||||
const gui_char *t = (const gui_char*)str;
|
const gui_char *t;
|
||||||
|
|
||||||
w = MAX(w, font->height + 2 * pad);
|
if (!que || !toggle || !font || !in) return 0;
|
||||||
h = MAX(h, font->height + 2 * pad);
|
active = toggle->active;
|
||||||
|
t = (const gui_char*)toggle->text;
|
||||||
|
x = toggle->x, y = toggle->y;
|
||||||
|
w = toggle->w, h = toggle->h;
|
||||||
|
w = MAX(w, font->height + 2 * toggle->pad_x);
|
||||||
|
h = MAX(h, font->height + 2 * toggle->pad_y);
|
||||||
|
fg = toggle->foreground;
|
||||||
|
bg = toggle->background;
|
||||||
|
|
||||||
select_x = x + pad;
|
select_x = x + toggle->pad_x;
|
||||||
select_y = y + pad;
|
select_y = y + toggle->pad_y;
|
||||||
select_size = font->height;
|
select_size = font->height;
|
||||||
|
|
||||||
cursor_pad = select_size / 8;
|
cursor_pad = select_size / 8;
|
||||||
|
@ -476,8 +501,8 @@ gui_toggle(struct gui_draw_queue *que, const struct gui_input *in,
|
||||||
cursor_y = select_y + cursor_pad;
|
cursor_y = select_y + cursor_pad;
|
||||||
cursor_size = select_size - 2 * cursor_pad;
|
cursor_size = select_size - 2 * cursor_pad;
|
||||||
|
|
||||||
label_x = x + select_size + pad * 2;
|
label_x = x + select_size + toggle->pad_x * 2;
|
||||||
label_w = w - select_size + 3 * pad;
|
label_w = w - select_size + 3 * toggle->pad_x;
|
||||||
|
|
||||||
if (!in->mouse_down && in->mouse_clicked) {
|
if (!in->mouse_down && in->mouse_clicked) {
|
||||||
const gui_int clicked_x = in->mouse_clicked_pos.x;
|
const gui_int clicked_x = in->mouse_clicked_pos.x;
|
||||||
|
@ -490,34 +515,37 @@ gui_toggle(struct gui_draw_queue *que, const struct gui_input *in,
|
||||||
|
|
||||||
gui_rectf(que, select_x, select_y, select_size, select_size, bg);
|
gui_rectf(que, select_x, select_y, select_size, select_size, bg);
|
||||||
if (active) gui_rectf(que, cursor_x, cursor_y, cursor_size, cursor_size, fg);
|
if (active) gui_rectf(que, cursor_x, cursor_y, cursor_size, cursor_size, fg);
|
||||||
gui_text(que, font, label_x, y + pad, label_w, h - 2 * pad, white, t, len);
|
gui_string(que, font, label_x, y + toggle->pad_y, label_w,
|
||||||
|
h - 2 * toggle->pad_y, toggle->font, t, toggle->length);
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_float
|
gui_float
|
||||||
gui_slider(struct gui_draw_queue *que, const struct gui_input *in,
|
gui_slider(struct gui_draw_queue *que, const struct gui_slider *slider,
|
||||||
struct gui_color bg, struct gui_color fg,
|
const struct gui_input *in)
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
|
|
||||||
gui_float min, gui_float value, gui_float max, gui_float step)
|
|
||||||
{
|
{
|
||||||
|
gui_float min, max, value, step;
|
||||||
|
gui_int x, y, w, h;
|
||||||
gui_int mouse_x, mouse_y;
|
gui_int mouse_x, mouse_y;
|
||||||
gui_int clicked_x, clicked_y;
|
gui_int clicked_x, clicked_y;
|
||||||
gui_int cursor_x;
|
gui_int cursor_x, cursor_y, cursor_h;
|
||||||
gui_int cursor_y;
|
|
||||||
gui_float cursor_w;
|
gui_float cursor_w;
|
||||||
gui_int cursor_h;
|
|
||||||
|
|
||||||
if (step == 0.0f) return value;
|
if (!que || !slider || !in) return 0;
|
||||||
w = MAX(w, 2 * pad);
|
if (slider->step == 0.0f) return slider->value;
|
||||||
h = MAX(h, 2 * pad);
|
x = slider->x, y = slider->y;
|
||||||
max = MAX(min, max);
|
w = slider->w, h = slider->h;
|
||||||
min = MIN(min, max);
|
w = MAX(slider->w, 2 * slider->pad_x);
|
||||||
value = CLAMP(min, value, max);
|
h = MAX(slider->h, 2 * slider->pad_y);
|
||||||
|
max = MAX(slider->min, slider->max);
|
||||||
|
min = MIN(slider->min, slider->max);
|
||||||
|
value = CLAMP(min, slider->value, max);
|
||||||
|
step = slider->step;
|
||||||
|
|
||||||
cursor_w = (w - 2 * pad) / (((max - min) + step) / step);
|
cursor_w = (w - 2 * slider->pad_x) / (((max - min) + step) / step);
|
||||||
cursor_h = h - 2 * pad;
|
cursor_h = h - 2 * slider->pad_y;
|
||||||
cursor_x = x + pad + (cursor_w * (value - min));
|
cursor_x = x + slider->pad_x + (cursor_w * (value - min));
|
||||||
cursor_y = y + pad;
|
cursor_y = y + slider->pad_y;
|
||||||
|
|
||||||
if (!que || !in) return 0;
|
if (!que || !in) return 0;
|
||||||
mouse_x = in->mouse_pos.x;
|
mouse_x = in->mouse_pos.x;
|
||||||
|
@ -533,7 +561,7 @@ gui_slider(struct gui_draw_queue *que, const struct gui_input *in,
|
||||||
const gui_float tmp = mouse_x - cursor_x + (cursor_w / 2);
|
const gui_float tmp = mouse_x - cursor_x + (cursor_w / 2);
|
||||||
gui_float next_value = value + step * ((tmp < 0) ? -1.0f : 1.0f);
|
gui_float next_value = value + step * ((tmp < 0) ? -1.0f : 1.0f);
|
||||||
next_value = CLAMP(min, next_value, max);
|
next_value = CLAMP(min, next_value, max);
|
||||||
cursor_next_x = x + pad + (cursor_w * (next_value - min));
|
cursor_next_x = x + slider->pad_x + (cursor_w * (next_value - min));
|
||||||
if (INBOX(mouse_x, mouse_y, cursor_next_x, cursor_y,
|
if (INBOX(mouse_x, mouse_y, cursor_next_x, cursor_y,
|
||||||
cursor_next_x + cursor_w, cursor_y + cursor_h))
|
cursor_next_x + cursor_w, cursor_y + cursor_h))
|
||||||
{
|
{
|
||||||
|
@ -541,59 +569,228 @@ gui_slider(struct gui_draw_queue *que, const struct gui_input *in,
|
||||||
cursor_x = cursor_next_x;
|
cursor_x = cursor_next_x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gui_rectf(que, x, y, w, h, bg);
|
gui_rectf(que, x, y, w, h, slider->background);
|
||||||
gui_rectf(que, cursor_x, cursor_y, cursor_w, cursor_h, fg);
|
gui_rectf(que, cursor_x, cursor_y, cursor_w, cursor_h, slider->foreground);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_int
|
gui_int
|
||||||
gui_progress(struct gui_draw_queue *que, const struct gui_input *in,
|
gui_progress(struct gui_draw_queue *que, const struct gui_progress *prog,
|
||||||
struct gui_color bg, struct gui_color fg,
|
const struct gui_input *in)
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
|
|
||||||
gui_size value, gui_size max, gui_bool modifyable)
|
|
||||||
{
|
{
|
||||||
gui_float scale;
|
gui_float scale;
|
||||||
gui_int mouse_x, mouse_y;
|
gui_int mouse_x, mouse_y;
|
||||||
gui_int cursor_x, cursor_y;
|
gui_int cursor_x, cursor_y;
|
||||||
gui_int cursor_w, cursor_h;
|
gui_int cursor_w, cursor_h;
|
||||||
|
gui_int x, y, w, h;
|
||||||
|
gui_size value;
|
||||||
|
|
||||||
if (!que || !in) return 0;
|
if (!que || !in || !prog) return 0;
|
||||||
mouse_x = in->mouse_pos.x;
|
mouse_x = in->mouse_pos.x;
|
||||||
mouse_y = in->mouse_pos.y;
|
mouse_y = in->mouse_pos.y;
|
||||||
|
|
||||||
w = MAX(w, 2 * pad + 1);
|
x = prog->x, y = prog->y;
|
||||||
h = MAX(h, 2 * pad + 1);
|
w = prog->w, h = prog->h;
|
||||||
value = MIN(value, max);
|
w = MAX(prog->w, 2 * prog->pad_x + 1);
|
||||||
|
h = MAX(prog->h, 2 * prog->pad_y + 1);
|
||||||
|
value = MIN(prog->current, prog->max);
|
||||||
|
|
||||||
if (modifyable && in->mouse_down && INBOX(mouse_x, mouse_y, x, y, x+w, y+h)) {
|
if (prog->modifyable && in->mouse_down && INBOX(mouse_x, mouse_y, x, y, x+w, y+h)) {
|
||||||
gui_float ratio = (gui_float)(mouse_x - x) / (gui_float)w;
|
gui_float ratio = (gui_float)(mouse_x - x) / (gui_float)w;
|
||||||
value = (gui_size)((gui_float)max * ratio);
|
value = (gui_size)((gui_float)prog->max * ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!max) return value;
|
if (!prog->max) return value;
|
||||||
value = MIN(value, max);
|
value = MIN(value, prog->max);
|
||||||
scale = (gui_float)value / (gui_float)max;
|
scale = (gui_float)value / (gui_float)prog->max;
|
||||||
cursor_h = h - 2 * pad;
|
cursor_h = h - 2 * prog->pad_y;
|
||||||
cursor_w = (w - 2 * pad) * scale;
|
cursor_w = (w - 2 * prog->pad_x) * scale;
|
||||||
cursor_x = x + pad;
|
cursor_x = x + prog->pad_x;
|
||||||
cursor_y = y + pad;
|
cursor_y = y + prog->pad_y;
|
||||||
gui_rectf(que, x, y, w, h, bg);
|
gui_rectf(que, x, y, w, h, prog->background);
|
||||||
gui_rectf(que, cursor_x, cursor_y, cursor_w, cursor_h, fg);
|
gui_rectf(que, cursor_x, cursor_y, cursor_w, cursor_h, prog->foreground);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_int
|
gui_int
|
||||||
gui_scroll(struct gui_draw_queue *que, const struct gui_input *in,
|
gui_input(struct gui_draw_queue *que, const struct gui_input_field *input,
|
||||||
struct gui_color bg, struct gui_color fg,
|
const struct gui_font *font, const struct gui_input *in)
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h,
|
{
|
||||||
gui_int offset, gui_int dst)
|
gui_int offset = 0;
|
||||||
|
gui_int label_x, label_y;
|
||||||
|
gui_int label_w, label_h;
|
||||||
|
gui_int x, y, w, h;
|
||||||
|
gui_int active;
|
||||||
|
const gui_char *t;
|
||||||
|
gui_int mouse_x, mouse_y;
|
||||||
|
gui_int text_width;
|
||||||
|
|
||||||
|
if (!que || !in || !font || !input)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mouse_x = in->mouse_clicked_pos.x;
|
||||||
|
mouse_y = in->mouse_clicked_pos.y;
|
||||||
|
x = input->x, y = input->y;
|
||||||
|
w = MAX(input->w, 2 * input->pad_x);
|
||||||
|
h = MAX(input->h, font->height);
|
||||||
|
active = input->active;
|
||||||
|
t = input->buffer;
|
||||||
|
|
||||||
|
if (in->mouse_clicked && in->mouse_down)
|
||||||
|
active = INBOX(mouse_x, mouse_y, x, y, x + w, y + h);
|
||||||
|
if (active) {
|
||||||
|
const struct gui_key *del = &in->keys[GUI_KEY_DEL];
|
||||||
|
const struct gui_key *bs = &in->keys[GUI_KEY_BACKSPACE];
|
||||||
|
const struct gui_key *enter = &in->keys[GUI_KEY_ENTER];
|
||||||
|
const struct gui_key *esc = &in->keys[GUI_KEY_ESCAPE];
|
||||||
|
if (in->text_len && *input->length < input->max) {
|
||||||
|
gui_long unicode;
|
||||||
|
gui_size i = 0, l = 0;
|
||||||
|
gui_size ulen = utf_decode(in->text, &unicode, in->text_len);
|
||||||
|
while (ulen && (l + ulen) <= in->text_len && *input->length < input->max) {
|
||||||
|
for (i = 0; i < ulen; i++)
|
||||||
|
input->buffer[(*input->length)++] = in->text[l + i];
|
||||||
|
l = l + ulen;
|
||||||
|
ulen = utf_decode(in->text + l, &unicode, in->text_len - l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((del->down && del->clicked) || (bs->down && bs->clicked))
|
||||||
|
if (*input->length > 0) *input->length = *input->length - 1;
|
||||||
|
if ((enter->down && enter->clicked) || (esc->down && esc->clicked))
|
||||||
|
active = gui_false;
|
||||||
|
}
|
||||||
|
|
||||||
|
label_x = x + input->pad_x;
|
||||||
|
label_y = y + input->pad_y;
|
||||||
|
label_w = w - 2 * input->pad_x;
|
||||||
|
label_h = h - 2 * input->pad_y;
|
||||||
|
text_width = gui_font_text_width(font, t, *input->length);
|
||||||
|
while (text_width > label_w) {
|
||||||
|
offset += 1;
|
||||||
|
text_width = gui_font_text_width(font, &t[offset], *input->length - offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_rectf(que, x, y, w, h, input->background);
|
||||||
|
gui_rect(que, x + 1, y, w - 1, h, input->foreground);
|
||||||
|
gui_string(que, font, label_x, label_y, label_w, label_h, input->font,
|
||||||
|
&t[offset], *input->length);
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gui_plot(struct gui_draw_queue *que, const struct gui_plot *plot)
|
||||||
|
{
|
||||||
|
gui_int i;
|
||||||
|
gui_int last_x;
|
||||||
|
gui_int last_y;
|
||||||
|
gui_float max, min;
|
||||||
|
gui_float range, ratio;
|
||||||
|
gui_int step;
|
||||||
|
gui_int canvas_x, canvas_y;
|
||||||
|
gui_int canvas_w, canvas_h;
|
||||||
|
gui_int x, y, w, h;
|
||||||
|
|
||||||
|
if (!que || !plot) return;
|
||||||
|
|
||||||
|
x = plot->x, y = plot->y;
|
||||||
|
w = plot->w, h = plot->h;
|
||||||
|
gui_rectf(que, x, y, w, h, plot->background);
|
||||||
|
max = plot->values[0], min = plot->values[0];
|
||||||
|
for (i = 0; i < plot->value_count; ++i) {
|
||||||
|
if (plot->values[i] > max)
|
||||||
|
max = plot->values[i];
|
||||||
|
if (plot->values[i] < min)
|
||||||
|
min = plot->values[i];
|
||||||
|
}
|
||||||
|
range = max - min;
|
||||||
|
|
||||||
|
canvas_x = x + plot->pad_x;
|
||||||
|
canvas_y = y + plot->pad_y;
|
||||||
|
canvas_w = w - 2 * plot->pad_x;
|
||||||
|
canvas_h = h - 2 * plot->pad_y;
|
||||||
|
step = canvas_w / plot->value_count;
|
||||||
|
|
||||||
|
ratio = (plot->values[0] - min) / range;
|
||||||
|
last_x = canvas_x;
|
||||||
|
last_y = (canvas_y + canvas_h) - ratio * (gui_float)canvas_h;
|
||||||
|
gui_rectf(que, last_x - 3, last_y - 3, 6, 6, plot->foreground);
|
||||||
|
for (i = 1; i < plot->value_count; i++) {
|
||||||
|
gui_int cur_x, cur_y;
|
||||||
|
ratio = (plot->values[i] - min) / range;
|
||||||
|
cur_x = canvas_x + step * i;
|
||||||
|
cur_y = (canvas_y + canvas_h) - (ratio * (gui_float)canvas_h);
|
||||||
|
gui_line(que, last_x, last_y, cur_x, cur_y, plot->foreground);
|
||||||
|
gui_rectf(que, cur_x - 3, cur_y - 3, 6, 6, plot->foreground);
|
||||||
|
last_x = cur_x;
|
||||||
|
last_y = cur_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_int
|
||||||
|
gui_histo(struct gui_draw_queue *que, const struct gui_histo *histo,
|
||||||
|
const struct gui_input *in)
|
||||||
|
{
|
||||||
|
gui_int i;
|
||||||
|
gui_float max;
|
||||||
|
gui_int canvas_x, canvas_y;
|
||||||
|
gui_int canvas_w, canvas_h;
|
||||||
|
gui_int item_w;
|
||||||
|
gui_int selected = -1;
|
||||||
|
gui_int x, y, w, h;
|
||||||
|
struct gui_color fg, nc;
|
||||||
|
|
||||||
|
if (!que || !histo || !in)
|
||||||
|
return selected;
|
||||||
|
|
||||||
|
x = histo->x, y = histo->y;
|
||||||
|
w = histo->w, h = histo->h;
|
||||||
|
fg = histo->foreground;
|
||||||
|
nc = histo->negative;
|
||||||
|
max = histo->values[0];
|
||||||
|
for (i = 0; i < histo->value_count; ++i) {
|
||||||
|
if (ABS(histo->values[i]) > max)
|
||||||
|
max = histo->values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_rectf(que, x, y, w, h, histo->background);
|
||||||
|
canvas_x = x + histo->pad_x;
|
||||||
|
canvas_y = y + histo->pad_y;
|
||||||
|
canvas_w = w - 2 * histo->pad_x;
|
||||||
|
canvas_h = h - 2 * histo->pad_y;
|
||||||
|
item_w = (canvas_w - (histo->value_count-1) * histo->pad_x) / (histo->value_count);
|
||||||
|
|
||||||
|
for (i = 0; i < histo->value_count; i++) {
|
||||||
|
const gui_int mouse_x = in->mouse_pos.x;
|
||||||
|
const gui_int mouse_y = in->mouse_pos.y;
|
||||||
|
const gui_float ratio = ABS(histo->values[i]) / max;
|
||||||
|
const gui_int item_h = (gui_int)((gui_float)canvas_h * ratio);
|
||||||
|
const gui_int item_x = canvas_x + (i * item_w) + (i * histo->pad_y);
|
||||||
|
const gui_int item_y = (canvas_y + canvas_h) - item_h;
|
||||||
|
struct gui_color col = (histo->values[i] < 0) ? nc: fg;
|
||||||
|
if (INBOX(mouse_x, mouse_y, item_x, item_y, item_x + item_w, item_y + item_h)) {
|
||||||
|
selected = (in->mouse_down && in->mouse_clicked) ? i : -1;
|
||||||
|
col = histo->highlight;
|
||||||
|
}
|
||||||
|
gui_rectf(que, item_x, item_y, item_w, item_h, col);
|
||||||
|
}
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_int
|
||||||
|
gui_scroll(struct gui_draw_queue *que, const struct gui_scroll *scroll,
|
||||||
|
const struct gui_input *in)
|
||||||
{
|
{
|
||||||
gui_int mouse_x, mouse_y;
|
gui_int mouse_x, mouse_y;
|
||||||
gui_int prev_x, prev_y;
|
gui_int prev_x, prev_y;
|
||||||
|
gui_int x, y, w, h;
|
||||||
|
gui_int step, offset;
|
||||||
|
|
||||||
gui_bool up, down;
|
gui_bool u, d;
|
||||||
gui_int button_size, button_half, button_y;
|
gui_int button_size, button_half, button_y;
|
||||||
gui_int bar_h, bar_y;
|
gui_int bar_h, bar_y;
|
||||||
|
struct gui_button up, down;
|
||||||
|
struct gui_color fg, bg;
|
||||||
|
gui_int target;
|
||||||
|
|
||||||
gui_float ratio;
|
gui_float ratio;
|
||||||
gui_float off;
|
gui_float off;
|
||||||
|
@ -607,8 +804,13 @@ gui_scroll(struct gui_draw_queue *que, const struct gui_input *in,
|
||||||
gui_int xpad, ypad, xmid;
|
gui_int xpad, ypad, xmid;
|
||||||
|
|
||||||
if (!que || !in) return 0;
|
if (!que || !in) return 0;
|
||||||
gui_rectf(que, x, y, w, h, bg);
|
x = scroll->x, y = scroll->y;
|
||||||
if (dst <= h) return 0;
|
w = scroll->w, h = scroll->h;
|
||||||
|
target = scroll->target;
|
||||||
|
fg = scroll->foreground;
|
||||||
|
bg = scroll->background;
|
||||||
|
gui_rectf(que, x, y, w, h, scroll->background);
|
||||||
|
if (scroll->target <= h) return 0;
|
||||||
|
|
||||||
mouse_x = in->mouse_pos.x;
|
mouse_x = in->mouse_pos.x;
|
||||||
mouse_y = in->mouse_pos.y;
|
mouse_y = in->mouse_pos.y;
|
||||||
|
@ -617,6 +819,7 @@ gui_scroll(struct gui_draw_queue *que, const struct gui_input *in,
|
||||||
|
|
||||||
w = MAX(w, 0);
|
w = MAX(w, 0);
|
||||||
h = MAX(h, 2 * w);
|
h = MAX(h, 2 * w);
|
||||||
|
step = CLAMP(0, scroll->step, h);
|
||||||
|
|
||||||
pad = w / 4;
|
pad = w / 4;
|
||||||
button_size = w;
|
button_size = w;
|
||||||
|
@ -624,14 +827,32 @@ gui_scroll(struct gui_draw_queue *que, const struct gui_input *in,
|
||||||
button_y = y + h - button_size;
|
button_y = y + h - button_size;
|
||||||
bar_h = h - 2 * button_size;
|
bar_h = h - 2 * button_size;
|
||||||
bar_y = y + button_size;
|
bar_y = y + button_size;
|
||||||
|
offset = CLAMP(0, scroll->offset, scroll->target - bar_h);
|
||||||
|
|
||||||
ratio = (gui_float)bar_h/(gui_float)dst;
|
ratio = (gui_float)bar_h/(gui_float)scroll->target;
|
||||||
off = (gui_float)offset/(gui_float)dst;
|
off = (gui_float)offset/(gui_float)scroll->target;
|
||||||
cursor_h = (gui_int)(ratio * (gui_float)bar_h);
|
cursor_h = (gui_int)(ratio * (gui_float)bar_h);
|
||||||
cursor_y = bar_y + (gui_int)(off * bar_h);
|
cursor_y = bar_y + (gui_int)(off * bar_h);
|
||||||
cursor_w = w;
|
cursor_w = w;
|
||||||
cursor_x = x;
|
cursor_x = x;
|
||||||
|
|
||||||
|
up.x = x, up.y = y;
|
||||||
|
up.w = button_size, up.h = button_size;
|
||||||
|
up.pad_y = 0, up.pad_x = 0;
|
||||||
|
up.text = NULL, up.length = 0;
|
||||||
|
up.font = fg, up.background = fg;
|
||||||
|
up.foreground = bg, up.highlight = fg;
|
||||||
|
|
||||||
|
down.x = x, down.y = y + h - button_size;
|
||||||
|
down.w = button_size, down.h = button_size;
|
||||||
|
down.pad_y = 0, down.pad_x = 0;
|
||||||
|
down.text = NULL, down.length = 0;
|
||||||
|
down.font = fg, down.background = fg;
|
||||||
|
down.foreground = bg, down.highlight = fg;
|
||||||
|
|
||||||
|
u = gui_button(que, &up, NULL, in);
|
||||||
|
d = gui_button(que, &down, NULL, in);
|
||||||
|
|
||||||
xpad = x + pad;
|
xpad = x + pad;
|
||||||
ypad = button_y + pad;
|
ypad = button_y + pad;
|
||||||
xmid = x + button_half;
|
xmid = x + button_half;
|
||||||
|
@ -639,10 +860,8 @@ gui_scroll(struct gui_draw_queue *que, const struct gui_input *in,
|
||||||
yoff = y + (button_size - pad);
|
yoff = y + (button_size - pad);
|
||||||
boff = button_y + (button_size - pad);
|
boff = button_y + (button_size - pad);
|
||||||
|
|
||||||
up = gui_button(que, in, NULL, fg, bg, x, y, button_size, button_size, 0, NULL, 0);
|
gui_trianglef(que, xmid, y + pad, xoff, yoff, xpad, yoff, scroll->background);
|
||||||
down = gui_button(que, in, NULL, fg, bg, x, button_y, button_size, button_size, 0,NULL, 0);
|
gui_trianglef(que, xpad, ypad, xoff, ypad, xmid, boff, scroll->background);
|
||||||
gui_trianglef(que, xmid, y + pad, xoff, yoff, xpad, yoff, bg);
|
|
||||||
gui_trianglef(que, xpad, ypad, xoff, ypad, xmid, boff, bg);
|
|
||||||
|
|
||||||
cursor_px = cursor_x + cursor_w;
|
cursor_px = cursor_x + cursor_w;
|
||||||
cursor_py = cursor_y + cursor_h;
|
cursor_py = cursor_y + cursor_h;
|
||||||
|
@ -651,13 +870,12 @@ gui_scroll(struct gui_draw_queue *que, const struct gui_input *in,
|
||||||
|
|
||||||
if (in->mouse_down && inscroll && incursor) {
|
if (in->mouse_down && inscroll && incursor) {
|
||||||
const gui_float pixel = in->mouse_delta.y;
|
const gui_float pixel = in->mouse_delta.y;
|
||||||
const gui_float delta = (pixel / (gui_float)bar_h) * (gui_float)dst;
|
const gui_float delta = (pixel / (gui_float)bar_h) * (gui_float)target;
|
||||||
offset = CLAMP(0, offset + delta, dst - bar_h);
|
offset = CLAMP(0, offset + delta, target - bar_h);
|
||||||
cursor_y += pixel;
|
cursor_y += pixel;
|
||||||
} else if (up || down) {
|
} else if (u || d) {
|
||||||
const gui_int h2 = h/2;
|
offset = (d) ? MIN(offset + step, target - bar_h): MAX(0, offset - step);
|
||||||
offset = (down) ? MIN(offset + h2, dst - bar_h) : MAX(0, offset - h2);
|
off = (gui_float)offset / (gui_float)scroll->target;
|
||||||
off = (gui_float)offset / (gui_float)dst;
|
|
||||||
cursor_y = bar_y + (gui_int)(off * bar_h);
|
cursor_y = bar_y + (gui_int)(off * bar_h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,11 +884,78 @@ gui_scroll(struct gui_draw_queue *que, const struct gui_input *in,
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_int gui_input(struct gui_draw_queue *que, const struct gui_input *in,
|
void gui_panel_init(struct gui_panel *panel, const struct gui_config *config,
|
||||||
const struct gui_font *font, struct gui_color bg, struct gui_color fg,
|
const struct gui_font *font, const struct gui_input *input)
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h,
|
|
||||||
gui_char *buffer, gui_int *len, gui_bool active)
|
|
||||||
{
|
{
|
||||||
return active;
|
panel->config = config;
|
||||||
|
panel->font = font;
|
||||||
|
panel->input = input;
|
||||||
|
panel->x = 0; panel->y = 0;
|
||||||
|
panel->at_x = 0; panel->at_y = 0;
|
||||||
|
panel->width = 0;
|
||||||
|
panel->flags = 0;
|
||||||
|
panel->index = 0;
|
||||||
|
panel->row_columns = 0;
|
||||||
|
panel->row_height = 0;
|
||||||
|
panel->queue = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_int gui_panel_begin(struct gui_panel *panel, struct gui_draw_queue *q,
|
||||||
|
const char *t, gui_flags f, gui_int x, gui_int y, gui_int w)
|
||||||
|
{
|
||||||
|
panel->x = x; panel->y = y;
|
||||||
|
panel->at_x = x; panel->at_y = y;
|
||||||
|
panel->width = w;
|
||||||
|
panel->flags = f;
|
||||||
|
panel->index = 0;
|
||||||
|
panel->row_columns = 0;
|
||||||
|
panel->row_height = 0;
|
||||||
|
panel->queue = q;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gui_panel_row(struct gui_panel *panel, gui_int height, gui_int cols)
|
||||||
|
{
|
||||||
|
panel->at_y += panel->row_height;
|
||||||
|
panel->at_x = panel->x;
|
||||||
|
panel->index = 0;
|
||||||
|
panel->row_columns = cols;
|
||||||
|
panel->row_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gui_panel_bounds(struct gui_rect *bounds, const struct gui_panel *panel)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_int
|
||||||
|
gui_panel_button(struct gui_panel *panel, const char *str, gui_int len)
|
||||||
|
{
|
||||||
|
struct gui_rect bounds;
|
||||||
|
struct gui_button button;
|
||||||
|
const struct gui_config *config = panel->config;
|
||||||
|
gui_panel_bounds(&bounds, panel);
|
||||||
|
panel->at_x += button.w;
|
||||||
|
|
||||||
|
button.text = str;
|
||||||
|
button.length = len;
|
||||||
|
button.x = bounds.x;
|
||||||
|
button.y = bounds.y;
|
||||||
|
button.w = bounds.w;
|
||||||
|
button.h = bounds.h;
|
||||||
|
button.pad_x = config->item_padding.x;
|
||||||
|
button.pad_y = config->item_padding.y;
|
||||||
|
button.background = config->colors[GUI_COLOR_BUTTON];
|
||||||
|
button.foreground = config->colors[GUI_COLOR_BUTTON_BORDER];
|
||||||
|
button.font = config->colors[GUI_COLOR_TEXT];
|
||||||
|
button.highlight = config->colors[GUI_COLOR_BUTTON_HOVER];
|
||||||
|
return gui_button(panel->queue, &button, panel->font, panel->input);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_panel_end(struct gui_panel *panel)
|
||||||
|
{
|
||||||
|
panel->height = panel->at_y - panel->y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
175
gui.h
175
gui.h
|
@ -3,8 +3,8 @@
|
||||||
vurtun <polygone@gmx.net>
|
vurtun <polygone@gmx.net>
|
||||||
MIT licence
|
MIT licence
|
||||||
*/
|
*/
|
||||||
#ifndef TINY_GUI_H_
|
#ifndef GUI_H_
|
||||||
#define TINY_GUI_H_
|
#define GUI_H_
|
||||||
|
|
||||||
#define GUI_UTF_SIZE 4
|
#define GUI_UTF_SIZE 4
|
||||||
#define GUI_INPUT_MAX 16
|
#define GUI_INPUT_MAX 16
|
||||||
|
@ -27,6 +27,7 @@ struct gui_color {gui_byte r,g,b,a;};
|
||||||
struct gui_texCoord {gui_float u,v;};
|
struct gui_texCoord {gui_float u,v;};
|
||||||
struct gui_vec2 {gui_float x,y;};
|
struct gui_vec2 {gui_float x,y;};
|
||||||
struct gui_rect {gui_float x,y,w,h;};
|
struct gui_rect {gui_float x,y,w,h;};
|
||||||
|
struct gui_key {gui_int down, clicked;};
|
||||||
|
|
||||||
struct gui_vertex {
|
struct gui_vertex {
|
||||||
struct gui_vec2 pos;
|
struct gui_vec2 pos;
|
||||||
|
@ -63,7 +64,7 @@ enum gui_keys {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gui_input {
|
struct gui_input {
|
||||||
gui_bool keys[GUI_KEY_MAX];
|
struct gui_key keys[GUI_KEY_MAX];
|
||||||
gui_char text[GUI_INPUT_MAX];
|
gui_char text[GUI_INPUT_MAX];
|
||||||
gui_size text_len;
|
gui_size text_len;
|
||||||
struct gui_vec2 mouse_pos;
|
struct gui_vec2 mouse_pos;
|
||||||
|
@ -92,6 +93,103 @@ struct gui_font {
|
||||||
const struct gui_font_glyph *fallback;
|
const struct gui_font_glyph *fallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct gui_button {
|
||||||
|
gui_int x, y;
|
||||||
|
gui_int w, h;
|
||||||
|
gui_int pad_x, pad_y;
|
||||||
|
const char *text;
|
||||||
|
gui_int length;
|
||||||
|
struct gui_color font;
|
||||||
|
struct gui_color background;
|
||||||
|
struct gui_color foreground;
|
||||||
|
struct gui_color highlight;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gui_toggle {
|
||||||
|
gui_int x, y;
|
||||||
|
gui_int w, h;
|
||||||
|
gui_int pad_x, pad_y;
|
||||||
|
gui_int active;
|
||||||
|
const char *text;
|
||||||
|
gui_int length;
|
||||||
|
struct gui_color font;
|
||||||
|
struct gui_color background;
|
||||||
|
struct gui_color foreground;
|
||||||
|
struct gui_color highlight;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gui_slider {
|
||||||
|
gui_int x, y;
|
||||||
|
gui_int w, h;
|
||||||
|
gui_int pad_x;
|
||||||
|
gui_int pad_y;
|
||||||
|
gui_float min, max;
|
||||||
|
gui_float value;
|
||||||
|
gui_float step;
|
||||||
|
struct gui_color background;
|
||||||
|
struct gui_color foreground;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gui_progress {
|
||||||
|
gui_int x, y;
|
||||||
|
gui_int w, h;
|
||||||
|
gui_int pad_x;
|
||||||
|
gui_int pad_y;
|
||||||
|
gui_size current;
|
||||||
|
gui_size max;
|
||||||
|
gui_bool modifyable;
|
||||||
|
struct gui_color background;
|
||||||
|
struct gui_color foreground;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gui_scroll {
|
||||||
|
gui_int x, y;
|
||||||
|
gui_int w, h;
|
||||||
|
gui_int offset;
|
||||||
|
gui_int target;
|
||||||
|
gui_int step;
|
||||||
|
struct gui_color background;
|
||||||
|
struct gui_color foreground;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gui_input_field {
|
||||||
|
gui_int x, y;
|
||||||
|
gui_int w, h;
|
||||||
|
gui_int pad_x;
|
||||||
|
gui_int pad_y;
|
||||||
|
gui_char *buffer;
|
||||||
|
gui_int *length;
|
||||||
|
gui_int max;
|
||||||
|
gui_bool active;
|
||||||
|
struct gui_color background;
|
||||||
|
struct gui_color foreground;
|
||||||
|
struct gui_color font;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gui_plot {
|
||||||
|
gui_int x, y;
|
||||||
|
gui_int w, h;
|
||||||
|
gui_int pad_x;
|
||||||
|
gui_int pad_y;
|
||||||
|
gui_int value_count;
|
||||||
|
const gui_float *values;
|
||||||
|
struct gui_color background;
|
||||||
|
struct gui_color foreground;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gui_histo {
|
||||||
|
gui_int x, y;
|
||||||
|
gui_int w, h;
|
||||||
|
gui_int pad_x;
|
||||||
|
gui_int pad_y;
|
||||||
|
gui_int value_count;
|
||||||
|
const gui_float *values;
|
||||||
|
struct gui_color background;
|
||||||
|
struct gui_color foreground;
|
||||||
|
struct gui_color negative;
|
||||||
|
struct gui_color highlight;
|
||||||
|
};
|
||||||
|
|
||||||
enum gui_panel_flags {
|
enum gui_panel_flags {
|
||||||
GUI_PANEL_BORDER = 0x01,
|
GUI_PANEL_BORDER = 0x01,
|
||||||
GUI_PANEL_TITLEBAR = 0x02,
|
GUI_PANEL_TITLEBAR = 0x02,
|
||||||
|
@ -136,9 +234,17 @@ struct gui_panel {
|
||||||
gui_flags flags;
|
gui_flags flags;
|
||||||
gui_int x, y;
|
gui_int x, y;
|
||||||
gui_int at_x, at_y;
|
gui_int at_x, at_y;
|
||||||
gui_int width;
|
gui_int width, height;
|
||||||
|
gui_int index;
|
||||||
|
gui_int row_height;
|
||||||
|
gui_int row_columns;
|
||||||
|
struct gui_draw_queue *queue;
|
||||||
|
const struct gui_font *font;
|
||||||
|
const struct gui_input *input;
|
||||||
|
const struct gui_config *config;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Input */
|
||||||
void gui_input_begin(struct gui_input *in);
|
void gui_input_begin(struct gui_input *in);
|
||||||
void gui_input_motion(struct gui_input *in, gui_int x, gui_int y);
|
void gui_input_motion(struct gui_input *in, gui_int x, gui_int y);
|
||||||
void gui_input_key(struct gui_input *in, enum gui_keys key, gui_int down);
|
void gui_input_key(struct gui_input *in, enum gui_keys key, gui_int down);
|
||||||
|
@ -146,41 +252,38 @@ void gui_input_button(struct gui_input *in, gui_int x, gui_int y, gui_int down);
|
||||||
void gui_input_char(struct gui_input *in, gui_glyph glyph);
|
void gui_input_char(struct gui_input *in, gui_glyph glyph);
|
||||||
void gui_input_end(struct gui_input *in);
|
void gui_input_end(struct gui_input *in);
|
||||||
|
|
||||||
|
/* Output */
|
||||||
void gui_begin(struct gui_draw_queue *que, gui_byte *memory, gui_size size);
|
void gui_begin(struct gui_draw_queue *que, gui_byte *memory, gui_size size);
|
||||||
gui_size gui_end(struct gui_draw_queue *que);
|
gui_size gui_end(struct gui_draw_queue *que);
|
||||||
const struct gui_draw_command *gui_next(const struct gui_draw_queue *que,
|
const struct gui_draw_command *gui_next(const struct gui_draw_queue *que,
|
||||||
const struct gui_draw_command *cmd);
|
const struct gui_draw_command *cmd);
|
||||||
|
|
||||||
gui_int gui_button(struct gui_draw_queue *que, const struct gui_input *in,
|
|
||||||
const struct gui_font *font,
|
|
||||||
struct gui_color bg, struct gui_color fg,
|
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
|
|
||||||
const char *str, gui_int len);
|
|
||||||
gui_int gui_toggle(struct gui_draw_queue *que, const struct gui_input *in,
|
|
||||||
const struct gui_font *font,
|
|
||||||
struct gui_color bg, struct gui_color fg,
|
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
|
|
||||||
const char *str, gui_int len, gui_int active);
|
|
||||||
gui_float gui_slider(struct gui_draw_queue *que, const struct gui_input *in,
|
|
||||||
struct gui_color bg, struct gui_color fg,
|
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
|
|
||||||
gui_float min, gui_float v, gui_float max, gui_float step);
|
|
||||||
gui_int gui_progress(struct gui_draw_queue *que, const struct gui_input *in,
|
|
||||||
struct gui_color bg, struct gui_color fg,
|
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h, gui_int pad,
|
|
||||||
gui_size cur, gui_size max, gui_bool modifyable);
|
|
||||||
gui_int gui_scroll(struct gui_draw_queue *que, const struct gui_input *in,
|
|
||||||
struct gui_color bg, struct gui_color fg,
|
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h,
|
|
||||||
gui_int offset, gui_int dst);
|
|
||||||
gui_int gui_input(struct gui_draw_queue *que, const struct gui_input *in,
|
|
||||||
const struct gui_font *font,
|
|
||||||
struct gui_color bg, struct gui_color fg,
|
|
||||||
gui_int x, gui_int y, gui_int w, gui_int h,
|
|
||||||
gui_char *buffer, gui_int *len, gui_bool active);
|
|
||||||
|
|
||||||
gui_int gui_panel_begin(struct gui_panel *panel, const char *title, gui_flags f,
|
/* Widgets */
|
||||||
const struct gui_config *c, const struct gui_input *i);
|
gui_int gui_button(struct gui_draw_queue *que, const struct gui_button *button,
|
||||||
|
const struct gui_font *font, const struct gui_input *in);
|
||||||
|
gui_int gui_toggle(struct gui_draw_queue *que, const struct gui_toggle *toggle,
|
||||||
|
const struct gui_font *font, const struct gui_input *in);
|
||||||
|
gui_float gui_slider(struct gui_draw_queue *que, const struct gui_slider *slider,
|
||||||
|
const struct gui_input *in);
|
||||||
|
gui_int gui_progress(struct gui_draw_queue *que, const struct gui_progress *prog,
|
||||||
|
const struct gui_input *in);
|
||||||
|
gui_int gui_scroll(struct gui_draw_queue *que, const struct gui_scroll *scroll,
|
||||||
|
const struct gui_input *in);
|
||||||
|
gui_int gui_input(struct gui_draw_queue *que, const struct gui_input_field *f,
|
||||||
|
const struct gui_font *font, const struct gui_input *in);
|
||||||
|
gui_int gui_histo(struct gui_draw_queue *que, const struct gui_histo *histo,
|
||||||
|
const struct gui_input *in);
|
||||||
|
void gui_plot(struct gui_draw_queue *que, const struct gui_plot *plot);
|
||||||
|
|
||||||
|
|
||||||
|
/* Panel */
|
||||||
|
void gui_panel_init(struct gui_panel *panel, const struct gui_config *config,
|
||||||
|
const struct gui_font *font, const struct gui_input *input);
|
||||||
|
gui_int gui_panel_begin(struct gui_panel *panel, struct gui_draw_queue *q,
|
||||||
|
const char *t, gui_flags f, gui_int x, gui_int y, gui_int w);
|
||||||
|
void gui_panel_row(struct gui_panel *panel, gui_int height, gui_int cols);
|
||||||
|
void gui_panel_space(struct gui_panel *panel, gui_int cols);
|
||||||
gui_int gui_panel_button(struct gui_panel *panel, const char *str, gui_int len);
|
gui_int gui_panel_button(struct gui_panel *panel, const char *str, gui_int len);
|
||||||
gui_int gui_panel_toggle(struct gui_panel *panel, const char *str, gui_int len,
|
gui_int gui_panel_toggle(struct gui_panel *panel, const char *str, gui_int len,
|
||||||
gui_int active);
|
gui_int active);
|
||||||
|
@ -189,7 +292,11 @@ gui_float gui_panel_slider(struct gui_panel *panel, gui_float min, gui_float v,
|
||||||
gui_float gui_panel_progress(struct gui_panel *panel, gui_size cur, gui_size max,
|
gui_float 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_int *len,
|
gui_int gui_panel_input(struct gui_panel *panel, gui_char *buffer, gui_int *len,
|
||||||
gui_bool active);
|
gui_int max, gui_bool active);
|
||||||
|
void gui_panel_plot(struct gui_panel *panel, const gui_float *values,
|
||||||
|
gui_int value_count, gui_int offset, const char *text);
|
||||||
|
void gui_panel_histo(struct gui_panel *panel, const gui_float *values,
|
||||||
|
gui_int value_count, gui_int offset, const char *text);
|
||||||
void gui_panel_end(struct gui_panel *panel);
|
void gui_panel_end(struct gui_panel *panel);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
157
opengl.c
157
opengl.c
|
@ -32,6 +32,7 @@
|
||||||
#define WIN_HEIGHT 600
|
#define WIN_HEIGHT 600
|
||||||
#define DTIME 33
|
#define DTIME 33
|
||||||
#define MAX_VERTEX_BUFFER (16 * 1024)
|
#define MAX_VERTEX_BUFFER (16 * 1024)
|
||||||
|
#define INPUT_MAX 64
|
||||||
|
|
||||||
#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))
|
||||||
|
@ -133,6 +134,9 @@ kpress(struct GUI *gui, XEvent* e)
|
||||||
gui_input_key(&gui->in, GUI_KEY_ENTER, gui_true);
|
gui_input_key(&gui->in, GUI_KEY_ENTER, gui_true);
|
||||||
else if (*keysym == XK_BackSpace)
|
else if (*keysym == XK_BackSpace)
|
||||||
gui_input_key(&gui->in, GUI_KEY_BACKSPACE, gui_true);
|
gui_input_key(&gui->in, GUI_KEY_BACKSPACE, gui_true);
|
||||||
|
else if ((*keysym >= 'a' && *keysym <= 'z') ||
|
||||||
|
(*keysym >= '0' && *keysym <= '9'))
|
||||||
|
gui_input_char(&gui->in, (unsigned char*)keysym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -167,7 +171,7 @@ brelease(struct GUI *con, XEvent *evt)
|
||||||
{
|
{
|
||||||
const float x = evt->xbutton.x;
|
const float x = evt->xbutton.x;
|
||||||
const float y = evt->xbutton.y;
|
const float y = evt->xbutton.y;
|
||||||
struct XWindow *xw = con->win;
|
UNUSED(evt);
|
||||||
if (evt->xbutton.button == Button1)
|
if (evt->xbutton.button == Button1)
|
||||||
gui_input_button(&con->in, x, y, gui_false);
|
gui_input_button(&con->in, x, y, gui_false);
|
||||||
}
|
}
|
||||||
|
@ -177,7 +181,7 @@ bmotion(struct GUI *gui, XEvent *evt)
|
||||||
{
|
{
|
||||||
const gui_int x = evt->xbutton.x;
|
const gui_int x = evt->xbutton.x;
|
||||||
const gui_int y = evt->xbutton.y;
|
const gui_int y = evt->xbutton.y;
|
||||||
struct XWindow *xw = gui->win;
|
UNUSED(evt);
|
||||||
gui_input_motion(&gui->in, x, y);
|
gui_input_motion(&gui->in, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +189,7 @@ static void
|
||||||
resize(struct GUI *con, XEvent* evt)
|
resize(struct GUI *con, XEvent* evt)
|
||||||
{
|
{
|
||||||
struct XWindow *xw = con->win;
|
struct XWindow *xw = con->win;
|
||||||
|
UNUSED(evt);
|
||||||
XGetWindowAttributes(xw->dpy, xw->win, &xw->gwa);
|
XGetWindowAttributes(xw->dpy, xw->win, &xw->gwa);
|
||||||
glViewport(0, 0, xw->gwa.width, xw->gwa.height);
|
glViewport(0, 0, xw->gwa.width, xw->gwa.height);
|
||||||
}
|
}
|
||||||
|
@ -223,12 +228,16 @@ ldbmp(gui_byte *data, uint32_t *width, uint32_t *height)
|
||||||
int32_t i;
|
int32_t i;
|
||||||
|
|
||||||
header = data;
|
header = data;
|
||||||
if (!width || !height) die("[BMP]: width or height is NULL!");
|
if (!width || !height)
|
||||||
if (header[0] != 'B' || header[1] != 'M') die("[BMP]: invalid file");
|
die("[BMP]: width or height is NULL!");
|
||||||
|
if (header[0] != 'B' || header[1] != 'M')
|
||||||
|
die("[BMP]: invalid file");
|
||||||
|
|
||||||
*width = *(uint32_t*)&(header[0x12]);
|
*width = *(uint32_t*)&(header[0x12]);
|
||||||
*height = *(uint32_t*)&(header[0x12]);
|
*height = *(uint32_t*)&(header[0x12]);
|
||||||
ioff = *(uint32_t*)(&header[0x0A]);
|
ioff = *(uint32_t*)(&header[0x0A]);
|
||||||
|
if (*width <= 0 || *height <= 0)
|
||||||
|
die("[BMP]: invalid image size");
|
||||||
|
|
||||||
data = data + ioff;
|
data = data + ioff;
|
||||||
reader = data;
|
reader = data;
|
||||||
|
@ -237,15 +246,10 @@ ldbmp(gui_byte *data, uint32_t *width, uint32_t *height)
|
||||||
for (i = *height-1; i >= 0; i--) {
|
for (i = *height-1; i >= 0; i--) {
|
||||||
writer = target + (i * *width * 4);
|
writer = target + (i * *width * 4);
|
||||||
for (j = 0; j < *width; j++) {
|
for (j = 0; j < *width; j++) {
|
||||||
gui_byte a = *(reader + (j * 4) + 0);
|
*writer++ = *(reader + (j * 4) + 1);
|
||||||
gui_byte r = *(reader + (j * 4) + 1);
|
*writer++ = *(reader + (j * 4) + 2);
|
||||||
gui_byte g = *(reader + (j * 4) + 2);
|
*writer++ = *(reader + (j * 4) + 3);
|
||||||
gui_byte b = *(reader + (j * 4) + 3);
|
*writer++ = *(reader + (j * 4) + 0);
|
||||||
|
|
||||||
*writer++ = r;
|
|
||||||
*writer++ = g;
|
|
||||||
*writer++ = b;
|
|
||||||
*writer++ = a;
|
|
||||||
*writer += 4;
|
*writer += 4;
|
||||||
}
|
}
|
||||||
reader += *width * 4;
|
reader += *width * 4;
|
||||||
|
@ -395,23 +399,111 @@ draw(int width, int height, const struct gui_draw_queue *que)
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
GLenum err;
|
|
||||||
struct XWindow xw;
|
struct XWindow xw;
|
||||||
struct GUI gui;
|
struct GUI gui;
|
||||||
long dt, started;
|
long dt, started;
|
||||||
gui_byte *buffer;
|
gui_byte *buffer;
|
||||||
gui_size buffer_size = MAX_VERTEX_BUFFER;
|
const gui_size buffer_size = MAX_VERTEX_BUFFER;
|
||||||
const struct gui_color colorA = {100, 100, 100, 255};
|
const struct gui_color colorA = {100, 100, 100, 255};
|
||||||
const struct gui_color colorB = {45, 45, 45, 255};
|
const struct gui_color colorB = {45, 45, 45, 255};
|
||||||
|
const struct gui_color colorC = {255, 255, 255, 255};
|
||||||
|
const struct gui_color colorD = {255, 0, 0, 255};
|
||||||
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_float slider = 5.0f;
|
struct gui_button button;
|
||||||
gui_float prog = 60.0f;
|
struct gui_slider slider;
|
||||||
gui_float offset = 300;
|
struct gui_progress prog;
|
||||||
gui_int select = gui_false;
|
struct gui_toggle toggle;
|
||||||
const char *selection[] = {"Inactive", "Active"};
|
struct gui_input_field field;
|
||||||
|
struct gui_plot plot;
|
||||||
|
struct gui_histo histo;
|
||||||
|
struct gui_scroll scroll;
|
||||||
|
|
||||||
/* x11 */
|
const char *selection[] = {"Inactive", "Active"};
|
||||||
|
gui_char input[INPUT_MAX];
|
||||||
|
gui_int input_len = 0;
|
||||||
|
const gui_float values[] = {10.0f, 12.0f, 25.0f, 15.0f, 18.0f, 30.0f, 32.0f, 15.0f};
|
||||||
|
strcpy((char*)input, "input");
|
||||||
|
input_len = strlen((char*)input);
|
||||||
|
|
||||||
|
button.x = 50, button.y = 50;
|
||||||
|
button.w = 150, button.h = 30;
|
||||||
|
button.pad_x = 5, button.pad_y = 5;
|
||||||
|
button.text = "button";
|
||||||
|
button.length = 6;
|
||||||
|
button.background = colorB;
|
||||||
|
button.foreground = colorA;
|
||||||
|
button.font = colorC;
|
||||||
|
button.highlight = colorA;
|
||||||
|
|
||||||
|
slider.x = 50, slider.y = 100;
|
||||||
|
slider.w = 150, slider.h = 30;
|
||||||
|
slider.pad_x = 2, slider.pad_y = 2;
|
||||||
|
slider.min = 0.0f;
|
||||||
|
slider.value = 5.0f;
|
||||||
|
slider.max = 10.0f;
|
||||||
|
slider.step = 1.0f;
|
||||||
|
slider.foreground = colorB;
|
||||||
|
slider.background = colorA;
|
||||||
|
|
||||||
|
prog.x = 50, prog.y = 150;
|
||||||
|
prog.w = 150, prog.h = 30;
|
||||||
|
prog.pad_x = 2, prog.pad_y = 2;
|
||||||
|
prog.current = 60.0f;
|
||||||
|
prog.max = 100.0f;
|
||||||
|
prog.modifyable = gui_true;
|
||||||
|
prog.foreground = colorB;
|
||||||
|
prog.background = colorA;
|
||||||
|
|
||||||
|
toggle.x = 50, toggle.y = 200;
|
||||||
|
toggle.w = 150, toggle.h = 30;
|
||||||
|
toggle.pad_x = 2, toggle.pad_y = 2;
|
||||||
|
toggle.active = gui_false;
|
||||||
|
toggle.text = selection[toggle.active];
|
||||||
|
toggle.length = strlen(selection[toggle.active]);
|
||||||
|
toggle.foreground = colorB;
|
||||||
|
toggle.background = colorA;
|
||||||
|
toggle.font = colorC;
|
||||||
|
toggle.highlight = colorA;
|
||||||
|
|
||||||
|
field.x = 50, field.y = 250;
|
||||||
|
field.w = 150, field.h = 30;
|
||||||
|
field.pad_x = 5, field.pad_y = 5;
|
||||||
|
field.buffer = input;
|
||||||
|
field.length = &input_len;
|
||||||
|
field.max = INPUT_MAX;
|
||||||
|
field.active = gui_false;
|
||||||
|
field.foreground = colorA;
|
||||||
|
field.background = colorB;
|
||||||
|
field.font = colorC;
|
||||||
|
|
||||||
|
plot.x = 50, plot.y = 300;
|
||||||
|
plot.w = 150, plot.h = 100;
|
||||||
|
plot.pad_x = 5, plot.pad_y = 5;
|
||||||
|
plot.values = values;
|
||||||
|
plot.value_count = LEN(values);
|
||||||
|
plot.foreground = colorB;
|
||||||
|
plot.background = colorA;
|
||||||
|
|
||||||
|
histo.x = 50, histo.y = 430;
|
||||||
|
histo.w = 150, histo.h = 100;
|
||||||
|
histo.pad_x = 5, histo.pad_y = 5;
|
||||||
|
histo.values = values;
|
||||||
|
histo.value_count = LEN(values);
|
||||||
|
histo.foreground = colorB;
|
||||||
|
histo.background = colorA;
|
||||||
|
histo.negative = colorC;
|
||||||
|
histo.highlight = colorD;
|
||||||
|
|
||||||
|
scroll.x = 250, scroll.y = 50;
|
||||||
|
scroll.w = 16, scroll.h = 300;
|
||||||
|
scroll.offset = 300;
|
||||||
|
scroll.target = 600;
|
||||||
|
scroll.step = 150;
|
||||||
|
scroll.foreground = colorB;
|
||||||
|
scroll.background = colorA;
|
||||||
|
|
||||||
|
/* Window */
|
||||||
UNUSED(argc); UNUSED(argv);
|
UNUSED(argc); UNUSED(argv);
|
||||||
memset(&xw, 0, sizeof xw);
|
memset(&xw, 0, sizeof xw);
|
||||||
memset(&gui, 0, sizeof gui);
|
memset(&gui, 0, sizeof gui);
|
||||||
|
@ -441,7 +533,7 @@ main(int argc, char *argv[])
|
||||||
/* OpenGL */
|
/* OpenGL */
|
||||||
xw.glc = glXCreateContext(xw.dpy, xw.vi, NULL, GL_TRUE);
|
xw.glc = glXCreateContext(xw.dpy, xw.vi, NULL, GL_TRUE);
|
||||||
glXMakeCurrent(xw.dpy, xw.win, xw.glc);
|
glXMakeCurrent(xw.dpy, xw.win, xw.glc);
|
||||||
buffer = xcalloc(MAX_VERTEX_BUFFER, 1);
|
buffer = xcalloc(buffer_size, 1);
|
||||||
|
|
||||||
xw.running = 1;
|
xw.running = 1;
|
||||||
gui.win = &xw;
|
gui.win = &xw;
|
||||||
|
@ -462,17 +554,16 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
/* ------------------------- GUI --------------------------*/
|
/* ------------------------- GUI --------------------------*/
|
||||||
gui_begin(&gui.out, buffer, MAX_VERTEX_BUFFER);
|
gui_begin(&gui.out, buffer, MAX_VERTEX_BUFFER);
|
||||||
if (gui_button(&gui.out, &gui.in, gui.font, colorA, colorB, 50,50,150,30,5,"button",6))
|
if (gui_button(&gui.out, &button, gui.font, &gui.in))
|
||||||
fprintf(stdout, "Button pressed!\n");
|
fprintf(stdout, "button pressed!\n");
|
||||||
slider = gui_slider(&gui.out, &gui.in, colorA, colorB,
|
slider.value = gui_slider(&gui.out, &slider, &gui.in);
|
||||||
50, 100, 150, 30, 2, 0.0f, slider, 10.0f, 1.0f);
|
prog.current = gui_progress(&gui.out, &prog, &gui.in);
|
||||||
prog = gui_progress(&gui.out, &gui.in, colorA, colorB,
|
toggle.active = gui_toggle(&gui.out, &toggle, gui.font, &gui.in);
|
||||||
50, 150, 150, 30, 2, prog, 100.0f, gui_true);
|
toggle.text = selection[toggle.active];
|
||||||
select = gui_toggle(&gui.out, &gui.in, gui.font, colorA, colorB,
|
field.active = gui_input(&gui.out, &field, gui.font, &gui.in);
|
||||||
50, 200, 150, 30, 2, selection[select],
|
gui_plot(&gui.out, &plot);
|
||||||
strlen(selection[select]), select);
|
gui_histo(&gui.out, &histo, &gui.in);
|
||||||
offset = gui_scroll(&gui.out, &gui.in, colorA, colorB,
|
scroll.offset = gui_scroll(&gui.out, &scroll, &gui.in);
|
||||||
250, 50, 16, 300, offset, 600);
|
|
||||||
gui_end(&gui.out);
|
gui_end(&gui.out);
|
||||||
/* ---------------------------------------------------------*/
|
/* ---------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue