added Editbox + removed c++ compile erros under gcc and clang

This commit is contained in:
vurtun 2015-07-04 23:36:01 +02:00
parent 30ff356b73
commit 18f27e91a5
3 changed files with 436 additions and 155 deletions

View File

@ -6,7 +6,7 @@ application and does not have any direct dependencies.
## Features ## Features
- Immediate mode graphical user interface toolkit - Immediate mode graphical user interface toolkit
- Written in C89 (ANSI C) - Written in C89 (ANSI C)
- Small codebase (~3kLOC) - Small codebase (~4kLOC)
- Focus on portability, efficiency, simplicity and minimal internal state - Focus on portability, efficiency, simplicity and minimal internal state
- Suited for embedding into graphical applications - Suited for embedding into graphical applications
- No global or hidden state - No global or hidden state

485
gui.c
View File

@ -5,9 +5,6 @@
*/ */
#include "gui.h" #include "gui.h"
#ifndef NULL
#define NULL ((void*)0)
#endif
#ifndef MIN #ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif #endif
@ -33,7 +30,18 @@
#define gui_color_to_array(ar, c)\ #define gui_color_to_array(ar, c)\
(ar)[0] = (c).r, (ar)[1] = (c).g, (ar)[2] = (c).b, (ar)[3] = (c).a (ar)[0] = (c).r, (ar)[1] = (c).g, (ar)[2] = (c).b, (ar)[3] = (c).a
#ifdef __cplusplus
template<typename T> struct gui_alignof;
template<typename T, int size_diff> struct gui_helper{enum {value = size_diff};};
template<typename T> struct gui_helper<T,0>{enum {value = gui_alignof<T>::value};};
template<typename T> struct gui_alignof{struct Big {T x; char c;}; enum {
diff = sizeof(Big) - sizeof(T), value = gui_helper<Big, diff>::value};};
#define GUI_ALIGNOF(t) (gui_alignof<t>::value);
#else
#define GUI_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0) #define GUI_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
#endif
#define GUI_ALIGN_PTR(x, mask) (void*)((gui_size)((gui_byte*)(x) + (mask-1)) & ~(mask-1)) #define GUI_ALIGN_PTR(x, mask) (void*)((gui_size)((gui_byte*)(x) + (mask-1)) & ~(mask-1))
#define GUI_ALIGN(x, mask) ((x) + (mask-1)) & ~(mask-1) #define GUI_ALIGN(x, mask) ((x) + (mask-1)) & ~(mask-1)
#define GUI_OFFSETOF(st, m) ((gui_size)(&((st *)0)->m)) #define GUI_OFFSETOF(st, m) ((gui_size)(&((st *)0)->m))
@ -78,8 +86,8 @@ static void*
gui_memcopy(void *dst, const void *src, gui_size size) gui_memcopy(void *dst, const void *src, gui_size size)
{ {
gui_size i = 0; gui_size i = 0;
char *d = dst; char *d = (char*)dst;
const char *s = src; const char *s = (const char*)src;
for (i = 0; i < size; ++i) for (i = 0; i < size; ++i)
d[i] = s[i]; d[i] = s[i];
return dst; return dst;
@ -158,7 +166,7 @@ static void
gui_zero(void *dst, gui_size size) gui_zero(void *dst, gui_size size)
{ {
gui_size i; gui_size i;
char *d = dst; char *d = (char*)dst;
for (i = 0; i < size; ++i) d[i] = 0; for (i = 0; i < size; ++i) d[i] = 0;
} }
@ -467,32 +475,42 @@ gui_buffer_alloc(struct gui_buffer *b, gui_size size, gui_size align)
void *memory; void *memory;
GUI_ASSERT(b); GUI_ASSERT(b);
if (!b || !size) return NULL; if (!b || !size) return 0;
b->needed += size; b->needed += size;
/* calculate total size with needed alignment + size */ /* calculate total size with needed alignment + size */
unaligned = gui_ptr_add(void, b->memory.ptr, b->allocated); unaligned = gui_ptr_add(void, b->memory.ptr, b->allocated);
if (align) {
memory = GUI_ALIGN_PTR(unaligned, align); memory = GUI_ALIGN_PTR(unaligned, align);
alignment = (gui_size)((gui_byte*)memory - (gui_byte*)unaligned); alignment = (gui_size)((gui_byte*)memory - (gui_byte*)unaligned);
} else {
memory = unaligned;
alignment = 0;
}
/* check if buffer has enough memory*/ /* check if buffer has enough memory*/
if ((b->allocated + size + alignment) >= b->memory.size) { if ((b->allocated + size + alignment) >= b->memory.size) {
void *temp; void *temp;
if (b->type != GUI_BUFFER_DYNAMIC || !b->pool.realloc) if (b->type != GUI_BUFFER_DYNAMIC || !b->pool.realloc)
return NULL; return 0;
/* allocated new bigger block of memory if the buffer is dynamic */ /* allocated new bigger block of memory if the buffer is dynamic */
cap = (gui_size)((gui_float)b->memory.size * b->grow_factor); cap = (gui_size)((gui_float)b->memory.size * b->grow_factor);
temp = b->pool.realloc(b->pool.userdata, b->memory.ptr, cap); temp = b->pool.realloc(b->pool.userdata, b->memory.ptr, cap);
if (!temp) return NULL; if (!temp) return 0;
b->memory.ptr = temp; b->memory.ptr = temp;
b->memory.size = cap; b->memory.size = cap;
/* align newly allocated pointer to memory */ /* align newly allocated pointer to memory */
unaligned = gui_ptr_add(gui_byte, b->memory.ptr, b->allocated); unaligned = gui_ptr_add(gui_byte, b->memory.ptr, b->allocated);
if (align) {
memory = GUI_ALIGN_PTR(unaligned, align); memory = GUI_ALIGN_PTR(unaligned, align);
alignment = (gui_size)((gui_byte*)memory - (gui_byte*)unaligned); alignment = (gui_size)((gui_byte*)memory - (gui_byte*)unaligned);
} else {
memory = unaligned;
alignment = 0;
}
} }
b->allocated += size + alignment; b->allocated += size + alignment;
@ -549,10 +567,10 @@ gui_command_buffer_push(struct gui_command_buffer* b,
void *unaligned; void *unaligned;
void *memory; void *memory;
GUI_ASSERT(b); GUI_ASSERT(b);
if (!b) return NULL; if (!b) return 0;
cmd = gui_buffer_alloc(&b->base, size, align); cmd = (struct gui_command*)gui_buffer_alloc(&b->base, size, align);
if (!cmd) return NULL; if (!cmd) return 0;
/* make sure the offset to the next command is aligned */ /* make sure the offset to the next command is aligned */
unaligned = (gui_byte*)cmd + size; unaligned = (gui_byte*)cmd + size;
@ -577,7 +595,8 @@ gui_command_buffer_push_scissor(struct gui_command_buffer *b, gui_float x, gui_f
b->clip.w = w; b->clip.w = w;
b->clip.h = h; b->clip.h = h;
cmd = gui_command_buffer_push(b, GUI_COMMAND_SCISSOR, sizeof(*cmd)); cmd = (struct gui_command_scissor*)
gui_command_buffer_push(b, GUI_COMMAND_SCISSOR, sizeof(*cmd));
if (!cmd) return; if (!cmd) return;
cmd->x = (gui_short)x; cmd->x = (gui_short)x;
cmd->y = (gui_short)y; cmd->y = (gui_short)y;
@ -593,7 +612,8 @@ gui_command_buffer_push_line(struct gui_command_buffer *b, gui_float x0, gui_flo
GUI_ASSERT(buffer); GUI_ASSERT(buffer);
if (!b) return; if (!b) return;
cmd = gui_command_buffer_push(b, GUI_COMMAND_LINE, sizeof(*cmd)); cmd = (struct gui_command_line*)
gui_command_buffer_push(b, GUI_COMMAND_LINE, sizeof(*cmd));
if (!cmd) return; if (!cmd) return;
cmd->begin[0] = (gui_short)x0; cmd->begin[0] = (gui_short)x0;
cmd->begin[1] = (gui_short)y0; cmd->begin[1] = (gui_short)y0;
@ -616,7 +636,8 @@ gui_command_buffer_push_rect(struct gui_command_buffer *b, gui_float x, gui_floa
return; return;
} }
cmd = gui_command_buffer_push(b, GUI_COMMAND_RECT, sizeof(*cmd)); cmd = (struct gui_command_rect*)
gui_command_buffer_push(b, GUI_COMMAND_RECT, sizeof(*cmd));
if (!cmd) return; if (!cmd) return;
cmd->r = (gui_uint)rounding; cmd->r = (gui_uint)rounding;
cmd->x = (gui_short)x; cmd->x = (gui_short)x;
@ -640,7 +661,8 @@ gui_command_buffer_push_circle(struct gui_command_buffer *b, gui_float x, gui_fl
return; return;
} }
cmd = gui_command_buffer_push(b, GUI_COMMAND_CIRCLE, sizeof(*cmd)); cmd = (struct gui_command_circle*)
gui_command_buffer_push(b, GUI_COMMAND_CIRCLE, sizeof(*cmd));
if (!cmd) return; if (!cmd) return;
cmd->x = (gui_short)x; cmd->x = (gui_short)x;
cmd->y = (gui_short)y; cmd->y = (gui_short)y;
@ -665,7 +687,8 @@ gui_command_buffer_push_triangle(struct gui_command_buffer *b, gui_float x0, gui
return; return;
} }
cmd = gui_command_buffer_push(b, GUI_COMMAND_TRIANGLE, sizeof(*cmd)); cmd = (struct gui_command_triangle*)
gui_command_buffer_push(b, GUI_COMMAND_TRIANGLE, sizeof(*cmd));
if (!cmd) return; if (!cmd) return;
cmd->a[0] = (gui_short)x0; cmd->a[0] = (gui_short)x0;
cmd->a[1] = (gui_short)y0; cmd->a[1] = (gui_short)y0;
@ -690,7 +713,8 @@ gui_command_buffer_push_image(struct gui_command_buffer *b, gui_float x, gui_flo
return; return;
} }
cmd = gui_command_buffer_push(b, GUI_COMMAND_IMAGE, sizeof(*cmd)); cmd = (struct gui_command_image*)
gui_command_buffer_push(b, GUI_COMMAND_IMAGE, sizeof(*cmd));
if (!cmd) return; if (!cmd) return;
cmd->x = (gui_short)x; cmd->x = (gui_short)x;
cmd->y = (gui_short)y; cmd->y = (gui_short)y;
@ -715,7 +739,8 @@ gui_command_buffer_push_text(struct gui_command_buffer *b, gui_float x, gui_floa
return; return;
} }
cmd = gui_command_buffer_push(b, GUI_COMMAND_TEXT, sizeof(*cmd) + length + 1); cmd = (struct gui_command_text*)
gui_command_buffer_push(b, GUI_COMMAND_TEXT, sizeof(*cmd) + length + 1);
if (!cmd) return; if (!cmd) return;
cmd->x = (gui_short)x; cmd->x = (gui_short)x;
cmd->y = (gui_short)y; cmd->y = (gui_short)y;
@ -729,6 +754,166 @@ gui_command_buffer_push_text(struct gui_command_buffer *b, gui_float x, gui_floa
cmd->string[length] = '\0'; cmd->string[length] = '\0';
} }
/*
* ==============================================================
*
* Edit Box
*
* ===============================================================
*/
void
gui_edit_buffer_append(gui_edit_buffer *buffer, const char *str, gui_size len)
{
char *mem;
GUI_ASSERT(buffer);
if (!buffer || !str || !len) return;
mem = (char*)gui_buffer_alloc(buffer, len * sizeof(char), 0);
if (!mem) return;
gui_memcopy(mem, str, len * sizeof(char));
}
void
gui_edit_buffer_insert(gui_edit_buffer *buffer, gui_size pos, const char *str, gui_size len)
{
void *mem;
gui_size i;
char *src, *dst;
gui_size copylen;
GUI_ASSERT(buffer);
if (!buffer || !str || !len || pos > buffer->allocated) return;
copylen = buffer->allocated - pos;
if (!copylen) {
gui_edit_buffer_append(buffer, str, len);
return;
}
/* memmove */
mem = gui_buffer_alloc(buffer, len * sizeof(char), 0);
if (!mem) return;
dst = gui_ptr_add(char, buffer->memory.ptr, pos + len + copylen);
src = gui_ptr_add(char, buffer->memory.ptr, pos + copylen);
for (i = 0; i < len; ++i)
*dst-- = *src--;
mem = gui_ptr_add(void, buffer->memory.ptr, pos);
gui_memcopy(mem, str, len * sizeof(char));
}
void
gui_edit_buffer_remove(gui_edit_buffer *buffer, gui_size len)
{
GUI_ASSERT(buffer);
if (!buffer || len > buffer->allocated) return;
buffer->allocated -= len;
}
void
gui_edit_buffer_del(gui_edit_buffer *buffer, gui_size pos, gui_size len)
{
char *src, *dst;
GUI_ASSERT(buffer);
if (!buffer || !len || pos > buffer->allocated ||
pos + len > buffer->allocated) return;
/* memmove */
dst = gui_ptr_add(char, buffer->memory.ptr, pos);
src = gui_ptr_add(char, buffer->memory.ptr, pos + len);
gui_memcopy(dst, src, len * sizeof(char));
}
char*
gui_edit_buffer_at(gui_edit_buffer *buffer, gui_size pos)
{
GUI_ASSERT(buffer);
if (!buffer || pos > buffer->allocated) return 0;
return gui_ptr_add(char, buffer->memory.ptr, pos);
}
void
gui_edit_box_init(struct gui_edit_box *eb, struct gui_allocator *a, gui_size initial_size,
gui_float grow_fac, const struct gui_clipboard *clip, gui_filter f)
{
GUI_ASSERT(eb);
GUI_ASSERT(a);
GUI_ASSERT(grow_fac);
if (!eb || !a) return;
gui_zero(eb, sizeof(*eb));
gui_buffer_init(&eb->buffer, a, initial_size, grow_fac);
if (clip) eb->clip = *clip;
eb->filter = f;
}
void
gui_edit_box_init_fixed(struct gui_edit_box *eb, void *memory, gui_size size,
const struct gui_clipboard *clip, gui_filter f)
{
GUI_ASSERT(eb);
GUI_ASSERT(a);
GUI_ASSERT(grow_fac);
GUI_ASSERT(clip);
if (!eb) return;
gui_zero(eb, sizeof(*eb));
gui_buffer_init_fixed(&eb->buffer, memory, size);
if (clip) eb->clip = *clip;
eb->filter = f;
}
void
gui_edit_box_add(struct gui_edit_box *eb, const char *str, gui_size len)
{
GUI_ASSERT(eb);
if (!eb || !str || !len) return;
gui_edit_buffer_insert(&eb->buffer, eb->buffer.allocated, str, len);
}
static void
gui_edit_box_buffer_input(struct gui_edit_box *box, const struct gui_input *i)
{
gui_long unicode;
gui_size src_len = 0;
gui_size text_len = 0, glyph_len = 0;
GUI_ASSERT(buffer);
GUI_ASSERT(i);
/* add user provided text to buffer until either no input or buffer space left*/
glyph_len = gui_utf_decode(i->text, &unicode, i->text_len);
while (glyph_len && ((text_len+glyph_len) <= i->text_len)) {
/* filter value to make sure the value is correct */
if (box->filter(unicode)) {
gui_size n = 0;
for (n = 0; n < glyph_len; n++)
gui_edit_box_add(box, &i->text[text_len + n], glyph_len);
text_len += glyph_len;
}
src_len = src_len + glyph_len;
glyph_len = gui_utf_decode(i->text + src_len, &unicode, i->text_len - src_len);
}
}
void
gui_edit_box_remove(struct gui_edit_box *eb)
{
GUI_ASSERT(eb);
gui_edit_buffer_remove(&eb->buffer, 1);
}
gui_char*
gui_edit_box_get(struct gui_edit_box *eb)
{
GUI_ASSERT(eb);
return (gui_char*)eb->buffer.memory.ptr;
}
gui_size
gui_edit_box_len(struct gui_edit_box *eb)
{
GUI_ASSERT(eb);
return eb->buffer.allocated;
}
/* /*
* ============================================================== * ==============================================================
* *
@ -1158,107 +1343,22 @@ gui_progress(struct gui_command_buffer *out, gui_float x, gui_float y,
return prog_value; return prog_value;
} }
static gui_bool void
gui_filter_input_default(gui_long unicode) gui_editbox(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float w,
{ gui_float h, struct gui_edit_box *box, const struct gui_edit *field,
(void)unicode; const struct gui_input *in, const struct gui_font *font)
return gui_true;
}
static gui_bool
gui_filter_input_ascii(gui_long unicode)
{
if (unicode < 0 || unicode > 128)
return gui_false;
return gui_true;
}
static gui_bool
gui_filter_input_float(gui_long unicode)
{
if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
return gui_false;
return gui_true;
}
static gui_bool
gui_filter_input_decimal(gui_long unicode)
{
if (unicode < '0' || unicode > '9')
return gui_false;
return gui_true;
}
static gui_bool
gui_filter_input_hex(gui_long unicode)
{
if ((unicode < '0' || unicode > '9') &&
(unicode < 'a' || unicode > 'f') &&
(unicode < 'A' || unicode > 'B'))
return gui_false;
return gui_true;
}
static gui_bool
gui_filter_input_oct(gui_long unicode)
{
if (unicode < '0' || unicode > '7')
return gui_false;
return gui_true;
}
static gui_bool
gui_filter_input_binary(gui_long unicode)
{
if (unicode < '0' || unicode > '1')
return gui_false;
return gui_true;
}
static gui_size
gui_buffer_input(gui_char *buffer, gui_size length, gui_size max,
gui_filter filter, const struct gui_input *i)
{
gui_long unicode;
gui_size src_len = 0;
gui_size text_len = 0, glyph_len = 0;
GUI_ASSERT(buffer);
GUI_ASSERT(i);
/* add user provided text to buffer until either no input or buffer space left*/
glyph_len = gui_utf_decode(i->text, &unicode, i->text_len);
while (glyph_len && ((text_len+glyph_len) <= i->text_len) && (length+src_len)<max) {
/* filter value to make sure the value is correct */
if (filter(unicode)) {
gui_size n = 0;
for (n = 0; n < glyph_len; n++)
buffer[length++] = i->text[text_len + n];
text_len += glyph_len;
}
src_len = src_len + glyph_len;
glyph_len = gui_utf_decode(i->text + src_len, &unicode, i->text_len - src_len);
}
return text_len;
}
gui_size
gui_edit_filtered(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float w,
gui_float h, gui_char *buffer, gui_size len, gui_size max, gui_bool *active,
const struct gui_edit *field, gui_filter filter, const struct gui_input *in,
const struct gui_font *font)
{ {
gui_float input_w, input_h; gui_float input_w, input_h;
gui_bool input_active; gui_char *buffer;
gui_size len, max;
GUI_ASSERT(out); GUI_ASSERT(out);
GUI_ASSERT(buffer); GUI_ASSERT(buffer);
GUI_ASSERT(field); GUI_ASSERT(field);
if (!out || !buffer || !field) if (!out || !box || !field)
return 0; return;
input_w = MAX(w, 2 * field->padding.x); input_w = MAX(w, 2 * field->padding.x);
input_h = MAX(h, font->height); input_h = MAX(h, font->height);
input_active = *active;
/* draw editbox background and border */ /* draw editbox background and border */
gui_command_buffer_push_rect(out, x, y, input_w, input_h,field->rounding, field->border); gui_command_buffer_push_rect(out, x, y, input_w, input_h,field->rounding, field->border);
@ -1266,38 +1366,47 @@ gui_edit_filtered(struct gui_command_buffer *out, gui_float x, gui_float y, gui_
input_w - 2 * field->border_size, input_h - 2 * field->border_size, input_w - 2 * field->border_size, input_h - 2 * field->border_size,
field->rounding, field->background); field->rounding, field->background);
/* check if editbox is not active */ /* check if editbox was activated/deactivated */
if (in && in->mouse_clicked && in->mouse_down) if (in && in->mouse_clicked && in->mouse_down)
input_active = GUI_INBOX(in->mouse_pos.x, in->mouse_pos.y, x, y, input_w, input_h); box->active = GUI_INBOX(in->mouse_pos.x, in->mouse_pos.y, x, y, input_w, input_h);
if (input_active && in) { max = box->buffer.memory.size;
len = gui_edit_box_len(box);
buffer = gui_edit_box_get(box);
if (box->active && in) {
const struct gui_key *bs = &in->keys[GUI_KEY_BACKSPACE]; const struct gui_key *bs = &in->keys[GUI_KEY_BACKSPACE];
const struct gui_key *del = &in->keys[GUI_KEY_DEL]; const struct gui_key *del = &in->keys[GUI_KEY_DEL];
const struct gui_key *esc = &in->keys[GUI_KEY_ESCAPE];
const struct gui_key *enter = &in->keys[GUI_KEY_ENTER]; const struct gui_key *enter = &in->keys[GUI_KEY_ENTER];
const struct gui_key *space = &in->keys[GUI_KEY_SPACE]; const struct gui_key *space = &in->keys[GUI_KEY_SPACE];
const struct gui_key *copy = &in->keys[GUI_KEY_COPY];
const struct gui_key *paste = &in->keys[GUI_KEY_PASTE];
/* update input buffer by user input */ /* update input buffer by user input */
if ((del->down && del->clicked) || (bs->down && bs->clicked)) if ((del->down && del->clicked) || (bs->down && bs->clicked))
if (len > 0) len = len - 1; gui_edit_box_remove(box);
if ((enter->down && enter->clicked) || (esc->down && esc->clicked)) if (enter->down && enter->clicked)
input_active = gui_false; box->active = gui_false;
if ((space->down && space->clicked) && (len < max)) if (copy->down && copy->clicked && box->clip.copy)
buffer[len++] = ' '; box->clip.copy(box->clip.userdata, buffer, len);
if (in->text_len && len < max) if (paste->down && paste->clicked && box->clip.paste)
len += gui_buffer_input(buffer, len, max, filter, in); box->buffer.allocated = box->clip.paste(box->clip.userdata, buffer, max);
if (space->down && space->clicked)
gui_edit_box_add(box, " ", 1);
if (in->text_len)
gui_edit_box_buffer_input(box, in);
} }
if (font && buffer) { if (font) {
gui_size offset = 0; gui_size offset = 0;
gui_float label_x, label_y, label_h; gui_float label_x, label_y, label_h;
gui_float label_w = input_w - 2 * field->padding.x - 2 * field->border_size; gui_float label_w = input_w - 2 * field->padding.x - 2 * field->border_size;
gui_size cursor_w =(gui_size)font->width(font->userdata,(const gui_char*)"X", 1); gui_size cursor_w = font->width(font->userdata,(const gui_char*)"X", 1);
/* calculate the visible text range */ /* calculate the visible text range */
gui_size text_len = len; gui_size text_len = len;
gui_float space = label_w - (gui_float)cursor_w;
gui_size text_width = font->width(font->userdata, buffer, text_len); gui_size text_width = font->width(font->userdata, buffer, text_len);
while (text_len && (text_width + cursor_w) > (gui_size)label_w) { while (text_len && (text_width > space)) {
gui_long unicode; gui_long unicode;
offset += gui_utf_decode(&buffer[offset], &unicode, text_len); offset += gui_utf_decode(&buffer[offset], &unicode, text_len);
text_len = len - offset; text_len = len - offset;
@ -1312,14 +1421,83 @@ gui_edit_filtered(struct gui_command_buffer *out, gui_float x, gui_float y, gui_
&buffer[offset], text_len, font, field->background, field->text); &buffer[offset], text_len, font, field->background, field->text);
/* if wanted draw the cursor at the end of the text input */ /* if wanted draw the cursor at the end of the text input */
if (input_active && field->show_cursor) { if (box->active && field->show_cursor) {
gui_command_buffer_push_rect(out, label_x + (gui_float)text_width, label_y, gui_command_buffer_push_rect(out, label_x + (gui_float)text_width, label_y,
(gui_float)cursor_w, label_h,0, field->cursor); (gui_float)cursor_w, label_h, 0, field->cursor);
} }
} }
*active = input_active; }
return len;
gui_bool
gui_filter_input_default(gui_long unicode)
{
(void)unicode;
return gui_true;
}
gui_bool
gui_filter_input_ascii(gui_long unicode)
{
if (unicode < 0 || unicode > 128)
return gui_false;
return gui_true;
}
gui_bool
gui_filter_input_float(gui_long unicode)
{
if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
return gui_false;
return gui_true;
}
gui_bool
gui_filter_input_decimal(gui_long unicode)
{
if (unicode < '0' || unicode > '9')
return gui_false;
return gui_true;
}
gui_bool
gui_filter_input_hex(gui_long unicode)
{
if ((unicode < '0' || unicode > '9') &&
(unicode < 'a' || unicode > 'f') &&
(unicode < 'A' || unicode > 'B'))
return gui_false;
return gui_true;
}
gui_bool
gui_filter_input_oct(gui_long unicode)
{
if (unicode < '0' || unicode > '7')
return gui_false;
return gui_true;
}
gui_bool
gui_filter_input_binary(gui_long unicode)
{
if (unicode < '0' || unicode > '1')
return gui_false;
return gui_true;
}
gui_size
gui_edit_filtered(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float w,
gui_float h, gui_char *buffer, gui_size len, gui_size max, gui_bool *active,
const struct gui_edit *field, gui_filter filter, const struct gui_input *in,
const struct gui_font *font)
{
struct gui_edit_box box;
gui_edit_box_init_fixed(&box, buffer, max, 0, filter);
box.buffer.allocated = len;
box.active = *active;
gui_editbox(out, x, y, w, h, &box, field, in, font);
*active = box.active;
return gui_edit_box_len(&box);
} }
gui_size gui_size
@ -1338,7 +1516,7 @@ gui_edit(struct gui_command_buffer *out, gui_float x, gui_float y, gui_float w,
gui_filter_input_binary, gui_filter_input_binary,
}; };
return gui_edit_filtered(out, x, y, w, h, buffer, len, max, active, return gui_edit_filtered(out, x, y, w, h, buffer, len, max, active,
field,filter[f], in, font); field, filter[f], in, font);
} }
gui_float gui_float
@ -1921,7 +2099,7 @@ gui_panel_begin(struct gui_panel_layout *l, struct gui_panel *p,
l->buffer = p->buffer; l->buffer = p->buffer;
l->row.columns = 0; l->row.columns = 0;
l->row.height = 0; l->row.height = 0;
l->row.ratio = NULL; l->row.ratio = 0;
l->row.item_ratio = 0; l->row.item_ratio = 0;
l->offset = p->offset; l->offset = p->offset;
out = p->buffer; out = p->buffer;
@ -1985,8 +2163,8 @@ gui_panel_begin(struct gui_panel_layout *l, struct gui_panel *p,
/* check if the close icon has been pressed and set the panel to hidden */ /* check if the close icon has been pressed and set the panel to hidden */
header_w -= close_w; header_w -= close_w;
header_x += close_h - item_padding.x; header_x += close_h - item_padding.x;
if (i && GUI_INBOX(mouse_x, mouse_y, close_x, close_y, text_width, close_h)) { if (i && GUI_INBOX(mouse_x, mouse_y, close_x, close_y, (gui_float)text_width, close_h)) {
if (GUI_INBOX(clicked_x, clicked_y, close_x, close_y, text_width, close_h)) { if (GUI_INBOX(clicked_x, clicked_y, close_x, close_y, (gui_float)text_width, close_h)) {
ret = !(i->mouse_down && i->mouse_clicked); ret = !(i->mouse_down && i->mouse_clicked);
if (!ret) p->flags |= GUI_PANEL_HIDDEN; if (!ret) p->flags |= GUI_PANEL_HIDDEN;
} }
@ -2014,8 +2192,8 @@ gui_panel_begin(struct gui_panel_layout *l, struct gui_panel *p,
/* minize the panel if the minimize icon has been pressed */ /* minize the panel if the minimize icon has been pressed */
header_w -= min_w; header_w -= min_w;
header_x += min_w - item_padding.x; header_x += min_w - item_padding.x;
if (i && GUI_INBOX(mouse_x, mouse_y, min_x, min_y, text_width, min_h)) { if (i && GUI_INBOX(mouse_x, mouse_y, min_x, min_y, (gui_float)text_width, min_h)) {
if (GUI_INBOX(clicked_x, clicked_y, min_x, min_y, min_w, min_h)) if (GUI_INBOX(clicked_x, clicked_y, min_x, min_y, (gui_float)text_width, min_h))
if (i->mouse_down && i->mouse_clicked) if (i->mouse_down && i->mouse_clicked)
p->minimized = !p->minimized; p->minimized = !p->minimized;
} }
@ -2093,7 +2271,7 @@ gui_panel_begin_stacked(struct gui_panel_layout *l, struct gui_panel* p,
gui_stack_push(s, p); gui_stack_push(s, p);
} }
} }
return gui_panel_begin(l, p, title, (s->end == p) ? i : NULL); return gui_panel_begin(l, p, title, (s->end == p) ? i : 0);
} }
gui_bool gui_bool
@ -2269,7 +2447,7 @@ gui_panel_begin_tiled(struct gui_panel_layout *tile, struct gui_panel *panel,
} }
gui_stack_push(&layout->stack, panel); gui_stack_push(&layout->stack, panel);
res = gui_panel_begin(tile,panel,title,(layout->flags&GUI_LAYOUT_INACTIVE)?NULL:in); res = gui_panel_begin(tile,panel,title,(layout->flags&GUI_LAYOUT_INACTIVE)?0:in);
panel->flags &= ~(gui_flags)GUI_PANEL_DO_NOT_RESET; panel->flags &= ~(gui_flags)GUI_PANEL_DO_NOT_RESET;
return res; return res;
} }
@ -2299,7 +2477,7 @@ gui_panel_row(struct gui_panel_layout *layout, gui_float height, gui_size cols)
/* draw the current row and set the current row layout */ /* draw the current row and set the current row layout */
layout->index = 0; layout->index = 0;
layout->at_y += layout->row.height; layout->at_y += layout->row.height;
layout->row.ratio = NULL; layout->row.ratio = 0;
layout->row.columns = cols; layout->row.columns = cols;
layout->row.height = height + item_spacing.y; layout->row.height = height + item_spacing.y;
gui_command_buffer_push_rect(out, layout->at_x, layout->at_y, gui_command_buffer_push_rect(out, layout->at_x, layout->at_y,
@ -2445,7 +2623,7 @@ gui_panel_spacing(struct gui_panel_layout *l, gui_size cols)
gui_bool gui_bool
gui_panel_widget(struct gui_rect *bounds, struct gui_panel_layout *layout) gui_panel_widget(struct gui_rect *bounds, struct gui_panel_layout *layout)
{ {
struct gui_rect *c = NULL; struct gui_rect *c = 0;
GUI_ASSERT(layout); GUI_ASSERT(layout);
GUI_ASSERT(layout->config); GUI_ASSERT(layout->config);
GUI_ASSERT(layout->buffer); GUI_ASSERT(layout->buffer);
@ -2817,6 +2995,17 @@ gui_panel_edit_base(struct gui_rect *bounds, struct gui_edit *field,
return gui_true; return gui_true;
} }
void
gui_panel_editbox(struct gui_panel_layout *layout, struct gui_edit_box *box)
{
struct gui_rect bounds;
struct gui_edit field;
const struct gui_config *config = layout->config;
if (!gui_panel_edit_base(&bounds, &field, layout)) return;
gui_editbox(layout->buffer, bounds.x, bounds.y, bounds.w, bounds.h,
box, &field, layout->input, &config->font);
}
gui_size gui_size
gui_panel_edit(struct gui_panel_layout *layout, gui_char *buffer, gui_size len, gui_panel_edit(struct gui_panel_layout *layout, gui_char *buffer, gui_size len,
gui_size max, gui_bool *active, enum gui_input_filter filter) gui_size max, gui_bool *active, enum gui_input_filter filter)
@ -3471,7 +3660,7 @@ gui_panel_shelf_begin(struct gui_panel_layout *parent, struct gui_panel_layout *
/* setup fake panel to create a panel layout from */ /* setup fake panel to create a panel layout from */
flags = GUI_PANEL_BORDER|GUI_PANEL_SCROLLBAR|GUI_PANEL_TAB|GUI_PANEL_NO_HEADER; flags = GUI_PANEL_BORDER|GUI_PANEL_SCROLLBAR|GUI_PANEL_TAB|GUI_PANEL_NO_HEADER;
gui_panel_init(&panel, bounds.x, bounds.y, bounds.w, bounds.h, flags, out, config); gui_panel_init(&panel, bounds.x, bounds.y, bounds.w, bounds.h, flags, out, config);
gui_panel_begin(shelf, &panel, NULL, parent->input); gui_panel_begin(shelf, &panel, 0, parent->input);
shelf->offset = offset; shelf->offset = offset;
/* setup clip rect for the shelf panel */ /* setup clip rect for the shelf panel */
@ -3608,8 +3797,8 @@ gui_panel_end(struct gui_panel_layout *layout, struct gui_panel *panel)
void void
gui_stack_clear(struct gui_stack *stack) gui_stack_clear(struct gui_stack *stack)
{ {
stack->begin = NULL; stack->begin = 0;
stack->end = NULL; stack->end = 0;
stack->count = 0; stack->count = 0;
} }
@ -3624,8 +3813,8 @@ gui_stack_push(struct gui_stack *stack, struct gui_panel *panel)
if (iter == panel) return; if (iter == panel) return;
if (!stack->begin) { if (!stack->begin) {
panel->next = NULL; panel->next = 0;
panel->prev = NULL; panel->prev = 0;
stack->begin = panel; stack->begin = panel;
stack->end = panel; stack->end = panel;
stack->count = 1; stack->count = 1;
@ -3634,7 +3823,7 @@ gui_stack_push(struct gui_stack *stack, struct gui_panel *panel)
stack->end->next = panel; stack->end->next = panel;
panel->prev = stack->end; panel->prev = stack->end;
panel->next = NULL; panel->next = 0;
stack->end = panel; stack->end = panel;
stack->count++; stack->count++;
} }
@ -3655,8 +3844,8 @@ gui_stack_pop(struct gui_stack *stack, struct gui_panel*panel)
if (stack->end == panel) if (stack->end == panel)
stack->end = panel->prev; stack->end = panel->prev;
panel->next = NULL; panel->next = 0;
panel->prev = NULL; panel->prev = 0;
} }
/* /*

96
gui.h
View File

@ -86,6 +86,9 @@ struct gui_image {gui_handle handle; struct gui_rect region;};
struct gui_font; struct gui_font;
typedef gui_bool(*gui_filter)(gui_long unicode); typedef gui_bool(*gui_filter)(gui_long unicode);
typedef gui_size(*gui_text_width_f)(gui_handle, const gui_char*, gui_size); typedef gui_size(*gui_text_width_f)(gui_handle, const gui_char*, gui_size);
typedef gui_size(*gui_paste_f)(gui_handle, char *buffer, gui_size max);
typedef void(*gui_copy_f)(gui_handle, const char*, gui_size size);
/* /*
* ============================================================== * ==============================================================
* *
@ -93,6 +96,27 @@ typedef gui_size(*gui_text_width_f)(gui_handle, const gui_char*, gui_size);
* *
* =============================================================== * ===============================================================
*/ */
/* Utility
----------------------------
The utility API provides mainly a number of object construction function
for some gui specific objects like image handle, vector, color and rectangle.
USAGE
----------------------------
Utility function API
gui_get_null_rect() -- returns a default clipping rectangle
gui_utf_decode() -- decodes a utf-8 glyph into u32 unicode glyph and len
gui_utf_encode() -- encodes a u32 unicode glyph into a utf-8 glyph
gui_image_ptr() -- create a image handle from pointer
gui_image_id() -- create a image handle from integer id
gui_subimage_ptr() -- create a sub-image handle from pointer and region
gui_subimage_id() -- create a sub-image handle from integer id and region
gui_rect_is_valid() -- check if a rectangle inside the image command is valid
gui_rect() -- creates a rectangle from x,y-Position and width and height
gui_vec2() -- creates a 2D vector, in the best case should not be needed by the user
gui_rgba() -- create a gui color struct from rgba color code
gui_rgb() -- create a gui color struct from rgb color code
*/
struct gui_rect gui_get_null_rect(void); struct gui_rect gui_get_null_rect(void);
gui_size gui_utf_decode(const gui_char*, gui_long*, gui_size); gui_size gui_utf_decode(const gui_char*, gui_long*, gui_size);
gui_size gui_utf_encode(gui_long, gui_char*, gui_size); gui_size gui_utf_encode(gui_long, gui_char*, gui_size);
@ -174,8 +198,9 @@ enum gui_keys {
GUI_KEY_DEL, GUI_KEY_DEL,
GUI_KEY_ENTER, GUI_KEY_ENTER,
GUI_KEY_BACKSPACE, GUI_KEY_BACKSPACE,
GUI_KEY_ESCAPE,
GUI_KEY_SPACE, GUI_KEY_SPACE,
GUI_KEY_COPY,
GUI_KEY_PASTE,
GUI_KEY_MAX GUI_KEY_MAX
}; };
@ -679,6 +704,58 @@ void gui_command_buffer_push_text(struct gui_command_buffer*, gui_float, gui_flo
#define gui_foreach_command(i, b)\ #define gui_foreach_command(i, b)\
for((i)=gui_command_buffer_begin(b); (i)!=NULL; (i)=gui_command_buffer_next(b,i)) for((i)=gui_command_buffer_begin(b); (i)!=NULL; (i)=gui_command_buffer_next(b,i))
/*
* ==============================================================
*
* Edit Buffer
*
* ===============================================================
*/
typedef struct gui_buffer gui_edit_buffer;
void gui_edit_buffer_append(gui_edit_buffer*, const char*, gui_size);
void gui_edit_buffer_insert(gui_edit_buffer*, gui_size pos, const char*, gui_size);
void gui_edit_buffer_remove(gui_edit_buffer*, gui_size);
void gui_edit_buffer_del(gui_edit_buffer*, gui_size pos, gui_size len);
char *gui_edit_buffer_at(gui_edit_buffer*, gui_size pos);
/*
* ==============================================================
*
* Edit Box
*
* ===============================================================
*/
struct gui_clipboard {
gui_handle userdata;
gui_paste_f paste;
gui_copy_f copy;
};
struct gui_edit_box {
gui_edit_buffer buffer;
gui_bool active;
struct gui_clipboard clip;
gui_filter filter;
};
gui_bool gui_filter_input_default(gui_long unicode);
gui_bool gui_filter_input_ascii(gui_long unicode);
gui_bool gui_filter_input_float(gui_long unicode);
gui_bool gui_filter_input_decimal(gui_long unicode);
gui_bool gui_filter_input_hex(gui_long unicode);
gui_bool gui_filter_input_oct(gui_long unicode);
gui_bool gui_filter_input_binary(gui_long unicode);
void gui_edit_box_init(struct gui_edit_box*, struct gui_allocator*, gui_size initial,
gui_float grow_fac, const struct gui_clipboard*, gui_filter);
void gui_edit_box_init_fixed(struct gui_edit_box*, void *memory, gui_size size,
const struct gui_clipboard*, gui_filter);
#define gui_edit_box_reset(b) gui_buffer_reset(&(b)->buffer)
#define gui_edit_box_clear(b) gui_buffer_clear(&(b)->buffer)
void gui_edit_box_add(struct gui_edit_box*, const char*, gui_size);
void gui_edit_box_remove(struct gui_edit_box*);
gui_char *gui_edit_box_get(struct gui_edit_box*);
gui_size gui_edit_box_len(struct gui_edit_box*);
/* /*
* ============================================================== * ==============================================================
* *
@ -1086,6 +1163,19 @@ gui_size gui_progress(struct gui_command_buffer*, gui_float x, gui_float y,
Output: Output:
- returns the from the user input updated value - returns the from the user input updated value
*/ */
void gui_editbox(struct gui_command_buffer*, gui_float x, gui_float y, gui_float w,
gui_float h, struct gui_edit_box*, const struct gui_edit*,
const struct gui_input*, const struct gui_font*);
/* this function executes a editbox widget
Input:
- output command buffer for drawing
- (x,y) position
- (width, height) size
- edit box structure containing the state to update
- visual widget style structure describing the editbox
- input structure to update the editbox with
- font structure for text drawing
*/
gui_size gui_edit(struct gui_command_buffer*, gui_float x, gui_float y, gui_float w, gui_size gui_edit(struct gui_command_buffer*, gui_float x, gui_float y, gui_float w,
gui_float h, gui_char*, gui_size, gui_size max, gui_bool*, gui_float h, gui_char*, gui_size, gui_size max, gui_bool*,
const struct gui_edit*, enum gui_input_filter filter, const struct gui_edit*, enum gui_input_filter filter,
@ -1942,6 +2032,8 @@ gui_size gui_panel_progress(struct gui_panel_layout*, gui_size cur, gui_size max
Output: Output:
- the from user input updated progressbar value if modifyable progressbar - the from user input updated progressbar value if modifyable progressbar
*/ */
void gui_panel_editbox(struct gui_panel_layout*, struct gui_edit_box*);
/* this function creates an editbox with copy & paste functionality and text buffering */
gui_size gui_panel_edit(struct gui_panel_layout*, gui_char *buffer, gui_size len, gui_size gui_panel_edit(struct gui_panel_layout*, gui_char *buffer, gui_size len,
gui_size max, gui_bool *active, enum gui_input_filter); gui_size max, gui_bool *active, enum gui_input_filter);
/* this function creates an editbox to updated/insert user text input /* this function creates an editbox to updated/insert user text input
@ -2123,7 +2215,7 @@ void gui_stack_push(struct gui_stack*, struct gui_panel*);
* the stack */ * the stack */
void gui_stack_pop(struct gui_stack*, struct gui_panel*); void gui_stack_pop(struct gui_stack*, struct gui_panel*);
/* this function removes a panel from the stack */ /* this function removes a panel from the stack */
#define gui_foreach_panel(i, s) for (i = (s)->begin; i != NULL; i = (i)->next) #define gui_foreach_panel(i, s) for (i = (s)->begin; i != 0; i = (i)->next)
/* iterates over each panel inside the stack */ /* iterates over each panel inside the stack */
/* /*