began simplifying and removing stuff
This commit is contained in:
parent
0a6d40b584
commit
493c16ec34
93
Readme.md
93
Readme.md
@ -2,38 +2,32 @@
|
||||
[![Coverity Status](https://scan.coverity.com/projects/5863/badge.svg)](https://scan.coverity.com/projects/5863)
|
||||
|
||||
This is a bloat free minimal state immediate mode graphical user interface toolkit
|
||||
written in ANSI C. It was designed as a embeddable user interface for graphical
|
||||
application and does not have any direct dependencies.
|
||||
written in ANSI C. It was designed as a simple embeddable user interface for
|
||||
application and does not have any direct dependencies. The toolkit was mainly
|
||||
developed to have a simple GUI for the X11 window system but can be used
|
||||
with other platforms like win32 or libraries like nanovg. The library uses
|
||||
no heap allocation outside of draw commands and as a whole has a low memory
|
||||
footprint.
|
||||
|
||||
## Features
|
||||
- Immediate mode graphical user interface toolkit
|
||||
- Written in C89 (ANSI C)
|
||||
- Small codebase (~6kLOC)
|
||||
- Focus on portability, efficiency, simplicity and minimal internal state
|
||||
- Suited for embedding into graphical applications
|
||||
- No global or hidden state
|
||||
- No direct dependencies (not even libc!)
|
||||
- Full memory management control
|
||||
- Renderer and platform independent
|
||||
- Configurable style and colors
|
||||
- UTF-8 support
|
||||
|
||||
## Limitations
|
||||
- Does NOT provide os window/input management
|
||||
- Does NOT provide a renderer backend
|
||||
- Does NOT implement a render backend
|
||||
- Does NOT implement a font library
|
||||
Summary: It is only responsible for the actual user interface
|
||||
|
||||
## Target applications
|
||||
- Graphical tools/editors
|
||||
- Library testbeds
|
||||
- Game engine debugging UI
|
||||
- Graphical overlay
|
||||
|
||||
## Gallery
|
||||
![gui demo](/screen/demo.png?raw=true)
|
||||
![gui explorer](/screen/explorer.png?raw=true)
|
||||
![gui screenshot](/screen/screenshot.png?raw=true)
|
||||
|
||||
## Example
|
||||
```c
|
||||
@ -89,22 +83,6 @@ while (1) {
|
||||
const struct gui_command *cmd;
|
||||
gui_foreach_command(cmd, &queue) {
|
||||
/* execute draw call command */
|
||||
switch (cmd->type) {
|
||||
case GUI_COMMAND_SCISSOR:
|
||||
/*...*/
|
||||
case GUI_COMMAND_LINE:
|
||||
/*...*/
|
||||
case GUI_COMMAND_RECT:
|
||||
/*...*/
|
||||
case GUI_COMMAND_CIRCLE:
|
||||
/*...*/
|
||||
case GUI_COMMAND_TRIANGLE:
|
||||
/*...*/
|
||||
case GUI_COMMAND_TEXT:
|
||||
/*...*/
|
||||
case GUI_COMMAND_IMAGE:
|
||||
/*...*/
|
||||
}
|
||||
}
|
||||
gui_command_queue_clear(&queue);
|
||||
}
|
||||
@ -248,63 +226,6 @@ const gui_float grow_factor = 2.0f;
|
||||
gui_command_queue_init(&queue, &alloc, initial_size, grow_factor);
|
||||
```
|
||||
|
||||
### Tiling
|
||||
A tiled layout allows to divide the screen into regions called
|
||||
slots in this case the top, left, center, right and bottom slot. Each slot occupies a
|
||||
certain percentage on the screen and can be filled with panels either
|
||||
horizontally or vertically. The combination of slots, ratio and multiple panels
|
||||
per slots support a rich set of vertical, horizontal and mixed layouts.
|
||||
|
||||
```c
|
||||
struct gui_command_queue queue;
|
||||
void *memory = malloc(MEMORY_SIZE);
|
||||
gui_command_queue_init_fixed(&queue, memory, MEMORY_SIZE, GUI_CLIP);
|
||||
|
||||
struct gui_config config;
|
||||
struct gui_font font = {...}
|
||||
gui_config_default(&config, GUI_DEFAULT_ALL, &font);
|
||||
|
||||
/* setup tiled window layout */
|
||||
struct gui_layout tiled;
|
||||
gui_layout_begin(&tiled, gui_rect(0, 0, window_width, window_height), GUI_LAYOUT_ACTIVE);
|
||||
gui_layout_slot(&tiled, GUI_SLOT_LEFT, 0.5f, GUI_LAYOUT_VERTICAL, 1);
|
||||
gui_layout_slot(&tiled, GUI_SLOT_CENTER, 0.5f, GUI_LAYOUT_VERTICAL, 1);
|
||||
gui_layout_end(&tiled);
|
||||
|
||||
/* setup panels */
|
||||
struct gui_input input = {0};
|
||||
struct gui_panel left;
|
||||
struct gui_panel center;
|
||||
gui_panel_init(&left, 0, 0, 0, 0, 0, &config, &queue, &input);
|
||||
gui_panel_init(¢er, 0, 0, 0, 0, 0, &config, &queue, &input);
|
||||
|
||||
while (1) {
|
||||
gui_input_begin(&input);
|
||||
/* record input */
|
||||
gui_input_end(&input);
|
||||
|
||||
/* GUI */
|
||||
struct gui_panel_layout layout;
|
||||
gui_panel_begin_tiled(&layout, &left, &tiled, GUI_SLOT_LEFT, 0);
|
||||
gui_panel_row_dynamic(&layout, 30, 1);
|
||||
if (gui_panel_button_text(&layout, "button0", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
gui_panel_end(&layout, &left);
|
||||
|
||||
gui_panel_begin_tiled(&layout, ¢er, &tiled, GUI_SLOT_CENTER, 0);
|
||||
gui_panel_row_dynamic(&layout, 30, 1);
|
||||
if (gui_panel_button_text(&layout, "button1", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
gui_panel_end(&layout, ¢er);
|
||||
|
||||
/* draw each panel */
|
||||
const struct gui_command *cmd
|
||||
gui_foreach_command(cmd, queue) {
|
||||
/* execute draw call command */
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## FAQ
|
||||
#### Where is the demo/example code?
|
||||
The demo and example code can be found in the demo folder.
|
||||
|
49
demo/demo.c
49
demo/demo.c
@ -291,7 +291,7 @@ color_picker(struct gui_panel_layout *panel, struct color_picker* control,
|
||||
gui_float t = *iter;
|
||||
t = gui_panel_slider(&popup, 0, t, 255, 10);
|
||||
*iter = (gui_byte)t;
|
||||
*iter = (gui_byte)gui_panel_spinner_int(&popup, 0, *iter, 255, 1, NULL);
|
||||
*iter = (gui_byte)gui_panel_spinner(&popup, 0, *iter, 255, 1, NULL);
|
||||
}
|
||||
|
||||
gui_panel_row_dynamic(&popup, 30, 3);
|
||||
@ -519,18 +519,18 @@ widget_panel(struct gui_panel_layout *panel, struct state *demo)
|
||||
fprintf(stdout, "left triangle button pressed!\n");
|
||||
demo->toggle = gui_panel_button_toggle(panel, "toggle", demo->toggle);
|
||||
|
||||
/* checkbox + radio buttons */
|
||||
/* Checkbox + Radio buttons */
|
||||
demo->checkbox = gui_panel_check(panel, "checkbox", demo->checkbox);
|
||||
if (!demo->scaleable)
|
||||
gui_panel_row_static(panel, 30, 75, 2);
|
||||
else gui_panel_row_dynamic(panel, 30, 2);
|
||||
else gui_panel_row_dynamic(panel, 30, 2);
|
||||
if (gui_panel_option(panel, "option 0", demo->option == 0))
|
||||
demo->option = 0;
|
||||
if (gui_panel_option(panel, "option 1", demo->option == 1))
|
||||
demo->option = 1;
|
||||
|
||||
{
|
||||
/* retain mode custom row layout */
|
||||
/* custom row layout by array */
|
||||
const gui_float ratio[] = {0.8f, 0.2f};
|
||||
const gui_float pixel[] = {150.0f, 30.0f};
|
||||
enum gui_panel_row_layout_format fmt = (demo->scaleable) ? GUI_DYNAMIC : GUI_STATIC;
|
||||
@ -545,12 +545,13 @@ widget_panel(struct gui_panel_layout *panel, struct state *demo)
|
||||
if (!demo->scaleable) gui_panel_row_static(panel, 30, 150, 1);
|
||||
else gui_panel_row_dynamic(panel, 30, 1);
|
||||
demo->item_current = gui_panel_selector(panel, weapons, LEN(weapons), demo->item_current);
|
||||
demo->spinner = gui_panel_spinner(panel, 0, demo->spinner, 250, 10, &demo->spinner_active);
|
||||
|
||||
/* combo boxes */
|
||||
combo_box(panel, &demo->combo, weapons, LEN(weapons));
|
||||
prog_combo_box(panel, demo->prog_values, LEN(demo->prog_values), &demo->progcom);
|
||||
color_combo_box(panel, &demo->colcom);
|
||||
check_combo_box(panel, demo->check_values, LEN(demo->check_values), &demo->checkcom);
|
||||
demo->spinner = gui_panel_spinner_int(panel, 0, demo->spinner, 250, 10, &demo->spinner_active);
|
||||
|
||||
{
|
||||
/* immediate mode custom row layout */
|
||||
@ -569,21 +570,6 @@ widget_panel(struct gui_panel_layout *panel, struct state *demo)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
graph_panel(struct gui_panel_layout *panel, gui_size current)
|
||||
{
|
||||
enum {COLUMNS, LINES};
|
||||
static const gui_float values[]={8.0f,15.0f,20.0f,12.0f,30.0f,12.0f,35.0f,40.0f,20.0f};
|
||||
gui_panel_row_dynamic(panel, 100, 1);
|
||||
switch (current) {
|
||||
case COLUMNS:
|
||||
gui_panel_graph(panel, GUI_GRAPH_COLUMN, values, LEN(values), 0); break;
|
||||
case LINES:
|
||||
gui_panel_graph(panel, GUI_GRAPH_LINES, values, LEN(values), 0); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
table_panel(struct gui_panel_layout *panel)
|
||||
{
|
||||
@ -631,8 +617,8 @@ properties_tab(struct gui_panel_layout *panel, struct gui_config *config)
|
||||
for (i = 0; i <= GUI_PROPERTY_SCROLLBAR_SIZE; ++i) {
|
||||
gui_int tx, ty;
|
||||
gui_panel_label(panel, properties[i], GUI_TEXT_LEFT);
|
||||
tx = gui_panel_spinner_int(panel,0,(gui_int)config->properties[i].x, 20, 1, NULL);
|
||||
ty = gui_panel_spinner_int(panel,0,(gui_int)config->properties[i].y, 20, 1, NULL);
|
||||
tx = gui_panel_spinner(panel,0,(gui_int)config->properties[i].x, 20, 1, NULL);
|
||||
ty = gui_panel_spinner(panel,0,(gui_int)config->properties[i].y, 20, 1, NULL);
|
||||
config->properties[i].x = (float)tx;
|
||||
config->properties[i].y = (float)ty;
|
||||
}
|
||||
@ -649,7 +635,7 @@ round_tab(struct gui_panel_layout *panel, struct gui_config *config)
|
||||
for (i = 0; i < GUI_ROUNDING_MAX; ++i) {
|
||||
gui_int t;
|
||||
gui_panel_label(panel, rounding[i], GUI_TEXT_LEFT);
|
||||
t = gui_panel_spinner_int(panel,0,(gui_int)config->rounding[i], 20, 1, NULL);
|
||||
t = gui_panel_spinner(panel,0,(gui_int)config->rounding[i], 20, 1, NULL);
|
||||
config->rounding[i] = (float)t;
|
||||
}
|
||||
}
|
||||
@ -762,9 +748,9 @@ run_demo(struct demo_gui *gui)
|
||||
/* menubar */
|
||||
gui_panel_menubar_begin(&layout);
|
||||
{
|
||||
gui_int sel;
|
||||
gui_panel_row_begin(&layout, GUI_STATIC, 25, 2);
|
||||
{
|
||||
gui_int sel;
|
||||
gui_panel_row_push(&layout, config->font.width(config->font.userdata, "__FILE__", 8));
|
||||
sel = gui_panel_menu(&layout, "FILE", file_items, LEN(file_items), 25, 100,
|
||||
&state->file_open, gui_vec2(0,0));
|
||||
@ -857,11 +843,22 @@ run_demo(struct demo_gui *gui)
|
||||
gui_panel_row_dynamic(&layout, 180, 1);
|
||||
state->shelf_selection = gui_panel_shelf_begin(&layout, &tab, shelfs,
|
||||
LEN(shelfs), state->shelf_selection, state->shelf);
|
||||
graph_panel(&tab, state->shelf_selection);
|
||||
{
|
||||
enum {COLUMNS, LINES};
|
||||
static const gui_float values[]={8.0f,15.0f,20.0f,12.0f,30.0f,12.0f,35.0f,40.0f,20.0f};
|
||||
gui_panel_row_dynamic(&tab, 100, 1);
|
||||
switch (state->shelf_selection) {
|
||||
case COLUMNS:
|
||||
gui_panel_graph(&tab, GUI_GRAPH_COLUMN, values, LEN(values), 0); break;
|
||||
case LINES:
|
||||
gui_panel_graph(&tab, GUI_GRAPH_LINES, values, LEN(values), 0); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
state->shelf = gui_panel_shelf_end(&layout, &tab);
|
||||
}
|
||||
|
||||
/* tables */
|
||||
/* table */
|
||||
gui_panel_row_dynamic(&layout, 180, 1);
|
||||
gui_panel_group_begin(&layout, &tab, "Table", state->table);
|
||||
table_panel(&tab);
|
||||
|
638
demo/opengl.c
638
demo/opengl.c
@ -1,638 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2015
|
||||
vurtun <polygone@gmx.net>
|
||||
MIT licence
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
|
||||
/* macros */
|
||||
#define DTIME 17
|
||||
#define FONT_ATLAS_DEPTH 4
|
||||
#define CIRCLE_SEGMENTS 22
|
||||
|
||||
/* macros */
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) < (b) ? (b) : (a))
|
||||
#define CLAMP(i,v,x) (MAX(MIN(v,x), i))
|
||||
#define LEN(a) (sizeof(a)/sizeof(a)[0])
|
||||
#define UNUSED(a) ((void)(a))
|
||||
|
||||
#include "../gui.h"
|
||||
|
||||
static void
|
||||
clipboard_set(const char *text)
|
||||
{SDL_SetClipboardText(text);}
|
||||
|
||||
static gui_bool
|
||||
clipboard_is_filled(void)
|
||||
{return SDL_HasClipboardText();}
|
||||
|
||||
static const char*
|
||||
clipboard_get(void)
|
||||
{return SDL_GetClipboardText();}
|
||||
|
||||
#include "demo.c"
|
||||
|
||||
struct texCoord {
|
||||
float u;
|
||||
float v;
|
||||
};
|
||||
|
||||
enum font_atlas_dimension {
|
||||
FONT_ATLAS_DIM_64 = 64,
|
||||
FONT_ATLAS_DIM_128 = 128,
|
||||
FONT_ATLAS_DIM_256 = 256,
|
||||
FONT_ATLAS_DIM_512 = 512,
|
||||
FONT_ATLAS_DIM_1024 = 1024,
|
||||
FONT_ATLAS_DIM_2048 = 2048
|
||||
};
|
||||
|
||||
struct font_atlas {
|
||||
enum font_atlas_dimension dim;
|
||||
gui_size range;
|
||||
gui_size size;
|
||||
gui_byte *memory;
|
||||
};
|
||||
|
||||
struct font_glyph {
|
||||
unsigned int code;
|
||||
float xadvance;
|
||||
short width, height;
|
||||
float xoff, yoff;
|
||||
struct texCoord uv[2];
|
||||
};
|
||||
|
||||
struct font {
|
||||
float height;
|
||||
float scale;
|
||||
GLuint texture;
|
||||
unsigned int glyph_count;
|
||||
struct font_glyph *glyphes;
|
||||
const struct font_glyph *fallback;
|
||||
};
|
||||
|
||||
static void
|
||||
die(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
fputs("\n", stderr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static char*
|
||||
file_load(const char* path, size_t* siz)
|
||||
{
|
||||
char *buf;
|
||||
FILE *fd = fopen(path, "rb");
|
||||
if (!fd) die("Failed to open file: %s\n", path);
|
||||
fseek(fd, 0, SEEK_END);
|
||||
*siz = (size_t)ftell(fd);
|
||||
fseek(fd, 0, SEEK_SET);
|
||||
buf = (char*)calloc(*siz, 1);
|
||||
fread(buf, *siz, 1, fd);
|
||||
fclose(fd);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void
|
||||
font_load_glyph(unsigned int code, struct font_glyph *glyph, FT_GlyphSlot slot)
|
||||
{
|
||||
glyph->code = code;
|
||||
glyph->width = (short)slot->bitmap.width;
|
||||
glyph->height = (short)slot->bitmap.rows;
|
||||
glyph->xoff = (float)slot->bitmap_left;
|
||||
glyph->yoff = (float)slot->bitmap_top;
|
||||
glyph->xadvance = (float)(slot->advance.x >> 6);
|
||||
}
|
||||
|
||||
static void
|
||||
font_load_glyphes(FT_Face face, struct font *font, size_t range)
|
||||
{
|
||||
size_t i;
|
||||
int ft_err;
|
||||
for (i = 0; i < range; ++i) {
|
||||
unsigned int index = FT_Get_Char_Index(face, i);
|
||||
if (!index) continue;
|
||||
ft_err = FT_Load_Glyph(face, index, 0);
|
||||
if (ft_err) continue;
|
||||
ft_err = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (ft_err) continue;
|
||||
font_load_glyph(index, &font->glyphes[i], face->glyph);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
font_pack_glyphes(struct font *font, float width, float height, size_t range)
|
||||
{
|
||||
size_t i;
|
||||
float xoff = 0, yoff = 0;
|
||||
float max_height = 0.0f;
|
||||
for (i = 0; i < range; ++i) {
|
||||
struct font_glyph *glyph = &font->glyphes[i];
|
||||
if ((xoff + glyph->width) > width) {
|
||||
yoff += max_height;
|
||||
max_height = 0.0f;
|
||||
xoff = 0.0f;
|
||||
}
|
||||
|
||||
glyph->uv[0].u = xoff / width;
|
||||
glyph->uv[0].v = yoff / height;
|
||||
glyph->uv[1].u = (xoff + glyph->width) / width;
|
||||
glyph->uv[1].v = (yoff + glyph->height) / height;
|
||||
if (glyph->height > max_height)
|
||||
max_height = glyph->height;
|
||||
xoff += glyph->width;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
font_atlas_blit(struct font_atlas *atlas, FT_GlyphSlot glyph,
|
||||
size_t off_x, size_t off_y)
|
||||
{
|
||||
size_t y, x;
|
||||
size_t width = glyph->bitmap.width;
|
||||
size_t height = glyph->bitmap.rows;
|
||||
const size_t pitch = atlas->dim * FONT_ATLAS_DEPTH;
|
||||
for (y = 0; y < height; y++) {
|
||||
size_t x_off = off_x * FONT_ATLAS_DEPTH;
|
||||
size_t y_off = (off_y + y) * pitch;
|
||||
unsigned char *dst = &atlas->memory[y_off + x_off];
|
||||
for (x = 0; x < width; ++x) {
|
||||
dst[0] = 255;
|
||||
dst[1] = 255;
|
||||
dst[2] = 255;
|
||||
dst[3] = glyph->bitmap.buffer[y * width + x];
|
||||
dst += FONT_ATLAS_DEPTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
font_bake_glyphes(FT_Face face, struct font_atlas *atlas,
|
||||
const struct font *font)
|
||||
{
|
||||
size_t i;
|
||||
int ft_err;
|
||||
for (i = 0; i < atlas->range; ++i) {
|
||||
size_t x, y;
|
||||
struct font_glyph *glyph = &font->glyphes[i];
|
||||
unsigned int index = FT_Get_Char_Index(face, i);
|
||||
|
||||
if (!index) continue;
|
||||
ft_err = FT_Load_Glyph(face, index, 0);
|
||||
if (ft_err) continue;
|
||||
ft_err = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (ft_err) continue;
|
||||
|
||||
x = (gui_size)(glyph->uv[0].u * (gui_float)atlas->dim);
|
||||
y = (gui_size)(glyph->uv[0].v * (gui_float)atlas->dim);
|
||||
font_atlas_blit(atlas, face->glyph, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
font_load(struct font *font, struct font_atlas *atlas, unsigned int height,
|
||||
const unsigned char *data, size_t size)
|
||||
{
|
||||
int ret = 1;
|
||||
FT_Library ft_lib;
|
||||
FT_Face ft_face;
|
||||
|
||||
assert(font);
|
||||
assert(atlas);
|
||||
assert(font->glyphes);
|
||||
assert(atlas->memory);
|
||||
|
||||
if (!font || !atlas)
|
||||
return gui_false;
|
||||
if (!font->glyphes || !atlas->memory)
|
||||
return gui_false;
|
||||
if (FT_Init_FreeType(&ft_lib))
|
||||
return gui_false;
|
||||
if (FT_New_Memory_Face(ft_lib, data, (FT_Long)size, 0, &ft_face))
|
||||
goto cleanup;
|
||||
if (FT_Select_Charmap(ft_face, FT_ENCODING_UNICODE))
|
||||
goto failed;
|
||||
if (FT_Set_Char_Size(ft_face, height << 6, height << 6, 96, 96))
|
||||
goto failed;
|
||||
|
||||
font_load_glyphes(ft_face, font, atlas->range);
|
||||
font_pack_glyphes(font, atlas->dim, atlas->dim, atlas->range);
|
||||
font_bake_glyphes(ft_face, atlas, font);
|
||||
|
||||
failed:
|
||||
FT_Done_Face(ft_face);
|
||||
cleanup:
|
||||
FT_Done_FreeType(ft_lib);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gui_size
|
||||
font_get_text_width(gui_handle handle, const gui_char *t, gui_size l)
|
||||
{
|
||||
long unicode;
|
||||
size_t text_width = 0;
|
||||
const struct font_glyph *glyph;
|
||||
size_t text_len = 0;
|
||||
size_t glyph_len;
|
||||
struct font *font = (struct font*)handle.ptr;
|
||||
assert(font);
|
||||
if (!t || !l) return 0;
|
||||
|
||||
glyph_len = gui_utf_decode(t, &unicode, l);
|
||||
while (text_len < l && glyph_len) {
|
||||
if (unicode == GUI_UTF_INVALID) return 0;
|
||||
glyph = (unicode < font->glyph_count) ? &font->glyphes[unicode] : font->fallback;
|
||||
glyph = (glyph->code == 0) ? font->fallback : glyph;
|
||||
|
||||
text_len += glyph_len;
|
||||
text_width += (gui_size)((float)glyph->xadvance * font->scale);
|
||||
glyph_len = gui_utf_decode(t + text_len, &unicode, l - text_len);
|
||||
}
|
||||
return text_width;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_rect(float x, float y, float w, float h, struct gui_color c)
|
||||
{
|
||||
glColor4ub(c.r, c.g, c.b, c.a);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(x, y);
|
||||
glVertex2f(x + w, y);
|
||||
glVertex2f(x + w, y + h);
|
||||
glVertex2f(x, y + h);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void
|
||||
font_draw_text(const struct font *font, float x, float y, float w, float h,
|
||||
struct gui_color bg, struct gui_color color, const char *text, size_t len)
|
||||
{
|
||||
size_t text_len;
|
||||
long unicode;
|
||||
size_t glyph_len;
|
||||
const struct font_glyph *g;
|
||||
if (!len) return;
|
||||
|
||||
draw_rect(x, y, w, h, bg);
|
||||
glyph_len = text_len = gui_utf_decode(text, &unicode, len);
|
||||
if (!glyph_len) return;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, font->texture);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glBegin(GL_QUADS);
|
||||
do {
|
||||
float gx, gy, gh, gw;
|
||||
float char_width = 0;
|
||||
|
||||
if (unicode == GUI_UTF_INVALID) break;
|
||||
g = (unicode < font->glyph_count) ?
|
||||
&font->glyphes[unicode] :
|
||||
font->fallback;
|
||||
g = (g->code == 0) ? font->fallback : g;
|
||||
|
||||
gx = x + (g->xoff * font->scale);
|
||||
gy = y + (font->height/2) + (h/2) - (g->yoff * font->scale);
|
||||
gw = (float)g->width * font->scale;
|
||||
gh = (float)g->height * font->scale;
|
||||
char_width = g->xadvance * font->scale;
|
||||
|
||||
glTexCoord2f(g->uv[0].u, g->uv[0].v);
|
||||
glVertex2f(gx, gy);
|
||||
glTexCoord2f(g->uv[1].u, g->uv[0].v);
|
||||
glVertex2f(gx + gw, gy);
|
||||
glTexCoord2f(g->uv[1].u, g->uv[1].v);
|
||||
glVertex2f(gx + gw, gy + gh);
|
||||
glTexCoord2f(g->uv[0].u, g->uv[1].v);
|
||||
glVertex2f(gx, gy + gh);
|
||||
|
||||
glyph_len = gui_utf_decode(text + text_len, &unicode, len - text_len);
|
||||
text_len += glyph_len;
|
||||
x += char_width;
|
||||
} while (text_len <= len && glyph_len);
|
||||
glEnd();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
font_del(struct font *font)
|
||||
{
|
||||
glDeleteTextures(1, &font->texture);
|
||||
free(font->glyphes);
|
||||
free(font);
|
||||
}
|
||||
|
||||
static struct font*
|
||||
font_new(const char *path, unsigned int font_height, unsigned int bake_height,
|
||||
size_t range, enum font_atlas_dimension dim)
|
||||
{
|
||||
gui_byte *ttf_blob;
|
||||
gui_size ttf_blob_size;
|
||||
struct font_atlas atlas;
|
||||
struct font *font = (struct font*)calloc(sizeof(struct font), 1);
|
||||
|
||||
atlas.dim = dim;
|
||||
atlas.range = range;
|
||||
atlas.size = atlas.dim * atlas.dim * FONT_ATLAS_DEPTH;
|
||||
atlas.memory = (gui_byte*)calloc((gui_size)atlas.size, 1);
|
||||
|
||||
font->glyph_count = (unsigned int)atlas.range;
|
||||
font->glyphes = (struct font_glyph*)calloc(atlas.range, sizeof(struct font_glyph));
|
||||
font->fallback = &font->glyphes['?'];
|
||||
font->scale = (float)font_height / (gui_float)bake_height;
|
||||
font->height = (float)font_height;
|
||||
|
||||
ttf_blob = (unsigned char*)file_load(path, &ttf_blob_size);
|
||||
if (!font_load(font, &atlas, bake_height, ttf_blob, ttf_blob_size))
|
||||
goto failed;
|
||||
|
||||
glGenTextures(1, &font->texture);
|
||||
glBindTexture(GL_TEXTURE_2D, font->texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dim, dim, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, atlas.memory);
|
||||
|
||||
free(atlas.memory);
|
||||
free(ttf_blob);
|
||||
return font;
|
||||
|
||||
failed:
|
||||
free(atlas.memory);
|
||||
free(ttf_blob);
|
||||
font_del(font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_line(float x0, float y0, float x1, float y1, struct gui_color c)
|
||||
{
|
||||
glColor4ub(c.r, c.g, c.b, c.a);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(x0, y0);
|
||||
glVertex2f(x1, y1);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void
|
||||
draw_circle(float x, float y, float r, struct gui_color c)
|
||||
{
|
||||
int i;
|
||||
float a0 = 0.0f;
|
||||
const float a_step = (2 * 3.141592654f)/22.0f;
|
||||
x += r; y += r;
|
||||
glColor4ub(c.r, c.g, c.b, c.a);
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (i = 0; i < CIRCLE_SEGMENTS; i++) {
|
||||
const float a1 = ((i + 1) == CIRCLE_SEGMENTS) ? 0.0f : a0 + a_step;
|
||||
const float p0x = x + (float)cos(a0) * r;
|
||||
const float p0y = y + (float)sin(a0) * r;
|
||||
const float p1x = x + (float)cos(a1) * r;
|
||||
const float p1y = y + (float)sin(a1) * r;
|
||||
|
||||
glVertex2f(p0x, p0y);
|
||||
glVertex2f(p1x, p1y);
|
||||
glVertex2f(x, y);
|
||||
a0 = a1;
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void
|
||||
draw(struct gui_command_queue *queue, int width, int height)
|
||||
{
|
||||
const struct gui_command *cmd;
|
||||
glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0f, width, height, 0.0f, 0.0f, 1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
gui_foreach_command(cmd, queue) {
|
||||
switch (cmd->type) {
|
||||
case GUI_COMMAND_NOP: break;
|
||||
case GUI_COMMAND_SCISSOR: {
|
||||
const struct gui_command_scissor *s = gui_command(scissor, cmd);
|
||||
glScissor(s->x, height - (s->y + s->h), s->w, s->h);
|
||||
} break;
|
||||
case GUI_COMMAND_LINE: {
|
||||
const struct gui_command_line *l = gui_command(line, cmd);
|
||||
draw_line(l->begin.x, l->begin.y, l->end.x, l->end.y, l->color);
|
||||
} break;
|
||||
case GUI_COMMAND_RECT: {
|
||||
const struct gui_command_rect *r = gui_command(rect, cmd);
|
||||
draw_rect(r->x, r->y, r->w, r->h, r->color);
|
||||
} break;
|
||||
case GUI_COMMAND_CIRCLE: {
|
||||
const struct gui_command_circle *c = gui_command(circle, cmd);
|
||||
draw_circle(c->x, c->y, (float)c->w / 2.0f, c->color);
|
||||
} break;
|
||||
case GUI_COMMAND_TRIANGLE: {
|
||||
const struct gui_command_triangle *t = gui_command(triangle, cmd);
|
||||
glColor4ub(t->color.r, t->color.g, t->color.b, t->color.a);
|
||||
glBegin(GL_TRIANGLES);
|
||||
glVertex2f(t->a.x, t->a.y);
|
||||
glVertex2f(t->b.x, t->b.y);
|
||||
glVertex2f(t->c.x, t->c.y);
|
||||
glEnd();
|
||||
} break;
|
||||
case GUI_COMMAND_TEXT: {
|
||||
const struct gui_command_text *t = gui_command(text, cmd);
|
||||
font_draw_text((const struct font*)t->font.ptr, t->x, t->y, t->w, t->h,
|
||||
t->background, t->foreground, t->string, t->length);
|
||||
} break;
|
||||
case GUI_COMMAND_IMAGE:
|
||||
case GUI_COMMAND_MAX:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
gui_command_queue_clear(queue);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
static void
|
||||
key(struct gui_input *in, SDL_Event *evt, gui_bool down)
|
||||
{
|
||||
const Uint8* state = SDL_GetKeyboardState(NULL);
|
||||
SDL_Keycode sym = evt->key.keysym.sym;
|
||||
if (sym == SDLK_RSHIFT || sym == SDLK_LSHIFT)
|
||||
gui_input_key(in, GUI_KEY_SHIFT, down);
|
||||
else if (sym == SDLK_DELETE)
|
||||
gui_input_key(in, GUI_KEY_DEL, down);
|
||||
else if (sym == SDLK_RETURN)
|
||||
gui_input_key(in, GUI_KEY_ENTER, down);
|
||||
else if (sym == SDLK_SPACE)
|
||||
gui_input_key(in, GUI_KEY_SPACE, down);
|
||||
else if (sym == SDLK_BACKSPACE)
|
||||
gui_input_key(in, GUI_KEY_BACKSPACE, down);
|
||||
else if (sym == SDLK_LEFT)
|
||||
gui_input_key(in, GUI_KEY_LEFT, down);
|
||||
else if (sym == SDLK_RIGHT)
|
||||
gui_input_key(in, GUI_KEY_RIGHT, down);
|
||||
else if (sym == SDLK_c)
|
||||
gui_input_key(in, GUI_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]);
|
||||
else if (sym == SDLK_v)
|
||||
gui_input_key(in, GUI_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]);
|
||||
else if (sym == SDLK_x)
|
||||
gui_input_key(in, GUI_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]);
|
||||
}
|
||||
|
||||
static void
|
||||
motion(struct gui_input *in, SDL_Event *evt)
|
||||
{
|
||||
const gui_int x = evt->motion.x;
|
||||
const gui_int y = evt->motion.y;
|
||||
gui_input_motion(in, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
btn(struct gui_input *in, SDL_Event *evt, gui_bool down)
|
||||
{
|
||||
const gui_int x = evt->button.x;
|
||||
const gui_int y = evt->button.y;
|
||||
if (evt->button.button == SDL_BUTTON_LEFT)
|
||||
gui_input_button(in, x, y, down);
|
||||
}
|
||||
|
||||
static void
|
||||
text(struct gui_input *in, SDL_Event *evt)
|
||||
{
|
||||
gui_glyph glyph;
|
||||
memcpy(glyph, evt->text.text, GUI_UTF_SIZE);
|
||||
gui_input_glyph(in, glyph);
|
||||
}
|
||||
|
||||
static void
|
||||
resize(SDL_Event *evt)
|
||||
{
|
||||
if (evt->window.event != SDL_WINDOWEVENT_RESIZED) return;
|
||||
glViewport(0, 0, evt->window.data1, evt->window.data2);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
/* Platform */
|
||||
const char *font_path;
|
||||
SDL_Window *win;
|
||||
SDL_GLContext glContext;
|
||||
struct font *glfont;
|
||||
int win_width, win_height;
|
||||
unsigned int started;
|
||||
unsigned int dt;
|
||||
int width = 0, height = 0;
|
||||
|
||||
/* GUI */
|
||||
struct gui_input in;
|
||||
struct gui_font font;
|
||||
struct demo_gui gui;
|
||||
|
||||
font_path = argv[1];
|
||||
if (argc < 2) {
|
||||
fprintf(stdout, "Missing TTF Font file argument!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* SDL */
|
||||
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
win = SDL_CreateWindow("Demo",
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN);
|
||||
glContext = SDL_GL_CreateContext(win);
|
||||
SDL_GetWindowSize(win, &win_width, &win_height);
|
||||
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
glfont = font_new(font_path, 10, 10, 255, FONT_ATLAS_DIM_256);
|
||||
|
||||
/* GUI */
|
||||
memset(&in, 0, sizeof in);
|
||||
memset(&gui, 0, sizeof gui);
|
||||
gui.memory = malloc(MAX_MEMORY);
|
||||
gui.input = ∈
|
||||
font.userdata.ptr = glfont;
|
||||
font.height = glfont->height;
|
||||
font.width = font_get_text_width;
|
||||
init_demo(&gui, &font);
|
||||
|
||||
while (gui.running) {
|
||||
/* Input */
|
||||
SDL_Event evt;
|
||||
started = SDL_GetTicks();
|
||||
gui_input_begin(&in);
|
||||
while (SDL_PollEvent(&evt)) {
|
||||
if (evt.type == SDL_WINDOWEVENT) resize(&evt);
|
||||
else if (evt.type == SDL_QUIT) goto cleanup;
|
||||
else if (evt.type == SDL_KEYUP) key(&in, &evt, gui_false);
|
||||
else if (evt.type == SDL_KEYDOWN) key(&in, &evt, gui_true);
|
||||
else if (evt.type == SDL_MOUSEBUTTONDOWN) btn(&in, &evt, gui_true);
|
||||
else if (evt.type == SDL_MOUSEBUTTONUP) btn(&in, &evt, gui_false);
|
||||
else if (evt.type == SDL_MOUSEMOTION) motion(&in, &evt);
|
||||
else if (evt.type == SDL_TEXTINPUT) text(&in, &evt);
|
||||
else if (evt.type == SDL_MOUSEWHEEL) gui_input_scroll(&in,(float)evt.wheel.y);
|
||||
}
|
||||
gui_input_end(&in);
|
||||
|
||||
/* GUI */
|
||||
SDL_GetWindowSize(win, &width, &height);
|
||||
gui.w = (gui_size)width;
|
||||
gui.h = (gui_size)height;
|
||||
run_demo(&gui);
|
||||
|
||||
/* Draw */
|
||||
glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
draw(&gui.queue, width, height);
|
||||
SDL_GL_SwapWindow(win);
|
||||
|
||||
/* Timing */
|
||||
dt = SDL_GetTicks() - started;
|
||||
if (dt < DTIME)
|
||||
SDL_Delay(DTIME - dt);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
free(gui.memory);
|
||||
font_del(glfont);
|
||||
SDL_GL_DeleteContext(glContext);
|
||||
SDL_DestroyWindow(win);
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
|
@ -347,9 +347,9 @@ draw(XSurface *surf, struct gui_command_queue *queue)
|
||||
case GUI_COMMAND_RECT: {
|
||||
const struct gui_command_rect *r = gui_command(rect, cmd);
|
||||
if (r->rounding)
|
||||
surface_draw_round_rect(surf, r->x, r->y, r->w, r->h, (gui_ushort)r->rounding, r->color);
|
||||
else
|
||||
surface_draw_rect(surf, r->x, r->y, r->w, r->h, r->color);
|
||||
surface_draw_round_rect(surf,r->x,r->y,r->w,r->h,
|
||||
(gui_ushort)r->rounding, r->color);
|
||||
else surface_draw_rect(surf, r->x, r->y, r->w, r->h, r->color);
|
||||
} break;
|
||||
case GUI_COMMAND_CIRCLE: {
|
||||
const struct gui_command_circle *c = gui_command(circle, cmd);
|
||||
|
475
gui.h
475
gui.h
@ -8,8 +8,7 @@
|
||||
This two file provide both the interface and implementation for a bloat free
|
||||
minimal state immediate mode graphical user interface toolkit. The Toolkit
|
||||
does not have any library or runtine dependencies like libc but does not
|
||||
handle os window/input management, have a render backend or a font library which
|
||||
need to be provided by the user.
|
||||
handle os window/input management or a font library which need to be provided by the user.
|
||||
*/
|
||||
#ifndef GUI_H_
|
||||
#define GUI_H_
|
||||
@ -18,7 +17,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Constants */
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* Constants
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
#define GUI_UTF_INVALID 0xFFFD
|
||||
#define GUI_UTF_SIZE 4
|
||||
/* describes the number of bytes a glyph consists of*/
|
||||
@ -29,14 +34,26 @@ extern "C" {
|
||||
#define GUI_MAX_ATTRIB_STACK 32
|
||||
/* defines the number of temporary configuration attribute changes that can be stored */
|
||||
|
||||
/* Compiler switches */
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* Compiler switches
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
#define GUI_COMPILE_WITH_FIXED_TYPES 1
|
||||
/* setting this define to 1 adds the <stdint.h> header for fixed sized types
|
||||
/* setting this define to 1 adds header <stdint.h> for fixed sized types
|
||||
* if 0 each type has to be set to the correct size*/
|
||||
#define GUI_COMPILE_WITH_STD_ASSERT 1
|
||||
#define GUI_COMPILE_WITH_ASSERT 1
|
||||
/* setting this define to 1 adds the <assert.h> header for the assert macro
|
||||
IMPORTANT: it also adds clib so only use it if wanted */
|
||||
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* Basic Types
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
#if GUI_COMPILE_WITH_FIXED_TYPES
|
||||
#include <stdint.h>
|
||||
typedef char gui_char;
|
||||
@ -74,16 +91,6 @@ typedef unsigned long gui_size;
|
||||
typedef unsigned long gui_ptr;
|
||||
#endif
|
||||
|
||||
#if GUI_COMPILE_WITH_STD_ASSERT
|
||||
#ifndef GUI_ASSERT
|
||||
#include <assert.h>
|
||||
#define GUI_ASSERT(expr) assert(expr)
|
||||
#endif
|
||||
#else
|
||||
#define GUI_ASSERT(expr)
|
||||
#endif
|
||||
|
||||
/* Utilities */
|
||||
enum {gui_false, gui_true};
|
||||
enum gui_heading {GUI_UP, GUI_RIGHT, GUI_DOWN, GUI_LEFT};
|
||||
struct gui_color {gui_byte r,g,b,a;};
|
||||
@ -93,17 +100,18 @@ struct gui_rect {gui_float x,y,w,h;};
|
||||
struct gui_key {gui_bool down, clicked;};
|
||||
typedef gui_char gui_glyph[GUI_UTF_SIZE];
|
||||
typedef union {void *ptr; gui_int id;} gui_handle;
|
||||
struct gui_image {gui_handle handle; struct gui_rect region;};
|
||||
struct gui_image {gui_handle handle; gui_ushort w, h; gui_ushort region[4];};
|
||||
enum gui_widget_states {GUI_INACTIVE = gui_false, GUI_AYOUT_ACTIVE = gui_true};
|
||||
enum gui_collapse_states {GUI_MINIMIZED = gui_false, GUI_MAXIMIZED = gui_true};
|
||||
|
||||
/* Callbacks */
|
||||
struct gui_font;
|
||||
struct gui_edit_box;
|
||||
struct gui_font_glyph;
|
||||
typedef gui_bool(*gui_filter)(gui_long unicode);
|
||||
typedef gui_size(*gui_text_width_f)(gui_handle, const gui_char*, gui_size);
|
||||
typedef void(*gui_paste_f)(gui_handle, struct gui_edit_box*);
|
||||
typedef void(*gui_copy_f)(gui_handle, const char*, gui_size size);
|
||||
typedef gui_size(*gui_text_width_f)(gui_handle, const gui_char*, gui_size);
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
@ -113,7 +121,7 @@ typedef void(*gui_copy_f)(gui_handle, const char*, gui_size size);
|
||||
*/
|
||||
/* Utility
|
||||
----------------------------
|
||||
The utility API provides mainly a number of object construction function
|
||||
The utility API provides a number of object construction function
|
||||
for some gui specific objects like image handle, vector, color and rectangle.
|
||||
|
||||
USAGE
|
||||
@ -128,19 +136,27 @@ typedef void(*gui_copy_f)(gui_handle, const char*, gui_size size);
|
||||
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_vec2 -- creates a 2D floating point vector
|
||||
gui_rgba -- create a gui color struct from rgba color code
|
||||
gui_rgb -- create a gui color struct from rgb color code
|
||||
*/
|
||||
#if GUI_COMPILE_WITH_ASSERT
|
||||
#ifndef GUI_ASSERT
|
||||
#include <assert.h>
|
||||
#define GUI_ASSERT(expr) assert(expr)
|
||||
#endif
|
||||
#else
|
||||
#define GUI_ASSERT(expr)
|
||||
#endif
|
||||
|
||||
struct gui_rect gui_get_null_rect(void);
|
||||
gui_size gui_utf_decode(const gui_char*, gui_long*, gui_size);
|
||||
gui_size gui_utf_encode(gui_long, gui_char*, gui_size);
|
||||
gui_size gui_utf_len(const gui_char*, gui_size len);
|
||||
struct gui_image gui_image_ptr(void*);
|
||||
struct gui_image gui_image_id(gui_int);
|
||||
struct gui_image gui_subimage_ptr(void*, struct gui_rect);
|
||||
struct gui_image gui_subimage_id(gui_int, struct gui_rect);
|
||||
gui_bool gui_rect_is_valid(const struct gui_rect r);
|
||||
struct gui_image gui_subimage_ptr(void*, gui_ushort w, gui_ushort h, struct gui_rect);
|
||||
struct gui_image gui_subimage_id(gui_int, gui_ushort w, gui_ushort h, struct gui_rect);
|
||||
gui_bool gui_image_is_subimage(const struct gui_image* img);
|
||||
struct gui_rect gui_rect(gui_float x, gui_float y, gui_float w, gui_float h);
|
||||
struct gui_vec2 gui_vec2(gui_float x, gui_float y);
|
||||
@ -150,7 +166,6 @@ struct gui_color gui_rgb(gui_byte r, gui_byte g, gui_byte b);
|
||||
#define gui_ptr_sub(t, p, i) ((t*)((void*)((gui_byte*)(p) - (i))))
|
||||
#define gui_ptr_add_const(t, p, i) ((const t*)((const void*)((const gui_byte*)(p) + (i))))
|
||||
#define gui_ptr_sub_const(t, p, i) ((const t*)((const void*)((const gui_byte*)(p) - (i))))
|
||||
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
@ -181,17 +196,17 @@ struct gui_color gui_rgb(gui_byte r, gui_byte g, gui_byte b);
|
||||
Finally to revert back into a read state you have to call gui_input_end.
|
||||
|
||||
Input function API
|
||||
gui_input_begin() -- begins the modification state
|
||||
gui_input_motion() -- notifies of a cursor motion update
|
||||
gui_input_key() -- notifies of a keyboard key update
|
||||
gui_input_button() -- notifies of a action event
|
||||
gui_input_char() -- adds a text glyph to gui_input
|
||||
gui_input_end() -- ends the modification state
|
||||
gui_input_begin -- begins the modification state
|
||||
gui_input_motion -- notifies of a cursor motion update
|
||||
gui_input_key -- notifies of a keyboard key update
|
||||
gui_input_button -- notifies of a action event
|
||||
gui_input_char -- adds a text glyph to gui_input
|
||||
gui_input_end -- ends the modification state
|
||||
|
||||
Input query function API
|
||||
gui_input_is_mouse_click_in_rect - checks for up/down click in a rectangle
|
||||
gui_input_is_mouse_hovering_rect - checks if the mouse hovers over a rectangle
|
||||
gui_input_mouse_clicked - checks if mouse hovers + down + clicked in rectangle
|
||||
gui_input_mouse_clicked - checks if hover + down + clicked in rectangle
|
||||
gui_input_is_mouse_down - checks if the current mouse button is down
|
||||
gui_input_is_mouse_released - checks if mouse button previously released
|
||||
gui_input_is_key_pressed - checks if key was up and now is down
|
||||
@ -301,7 +316,7 @@ gui_bool gui_input_is_key_down(const struct gui_input*, enum gui_keys);
|
||||
*/
|
||||
/* BUFFER
|
||||
----------------------------
|
||||
A basic buffer API with linear allocation and resetting as only freeing policy.
|
||||
A basic (double)-buffer API with linear allocation and resetting as only freeing.
|
||||
The buffer main purpose is to control all memory management inside
|
||||
the GUI toolkit and still leave memory control as much as possible in the hand
|
||||
of the user. The memory is provided in three different ways.
|
||||
@ -316,7 +331,7 @@ gui_bool gui_input_is_key_down(const struct gui_input*, enum gui_keys);
|
||||
since the used memory information is only available at the end of the frame which leads
|
||||
to the last way of handling memory.
|
||||
The last and most complicated way of handling memory is by allocator callbacks.
|
||||
The user herby registers callbacks to be called to allocate, free and reallocate
|
||||
The user hereby registers callbacks to be called to allocate, free and reallocate
|
||||
memory if needed. While this solves most allocation problems it causes some
|
||||
loss of flow control on the user side.
|
||||
|
||||
@ -329,7 +344,8 @@ gui_bool gui_input_is_key_down(const struct gui_input*, enum gui_keys);
|
||||
memory block size aswell as an alignment for the block. Finally to reset the memory
|
||||
at the end of the frame and when the memory buffer inside the buffer is no longer
|
||||
needed you would call gui_buffer_reset. To free all memory that has been allocated
|
||||
by an allocator if the buffer is no longer being used you have to call gui_buffer_clear.
|
||||
by an allocator if the buffer is no longer being used you have to call
|
||||
gui_buffer_clear.
|
||||
|
||||
Buffer function API
|
||||
gui_buffer_init -- initializes a dynamic buffer
|
||||
@ -372,8 +388,25 @@ enum gui_buffer_type {
|
||||
/* dynamically growing buffer */
|
||||
};
|
||||
|
||||
enum gui_buffer_allocation_type {
|
||||
GUI_BUFFER_FRONT,
|
||||
/* allocate memory from the front of the buffer */
|
||||
GUI_BUFFER_BACK,
|
||||
/* allocate memory from the back of the buffer */
|
||||
GUI_BUFFER_MAX
|
||||
};
|
||||
|
||||
struct gui_buffer_marker {
|
||||
gui_bool active;
|
||||
/* flag indiciation if the marker was set */
|
||||
gui_size offset;
|
||||
/* offset of the marker inside the buffer */
|
||||
};
|
||||
|
||||
struct gui_memory {void *ptr;gui_size size;};
|
||||
struct gui_buffer {
|
||||
struct gui_buffer_marker marker[GUI_BUFFER_MAX];
|
||||
/* buffer marker to free a buffer to a certain offset */
|
||||
struct gui_allocator pool;
|
||||
/* allocator callback for dynamic buffers */
|
||||
enum gui_buffer_type type;
|
||||
@ -388,6 +421,8 @@ struct gui_buffer {
|
||||
/* total amount of memory allocated if enough memory would have been present */
|
||||
gui_size calls;
|
||||
/* number of allocation calls */
|
||||
gui_size size;
|
||||
/* current size of the buffer */
|
||||
};
|
||||
|
||||
void gui_buffer_init(struct gui_buffer*, const struct gui_allocator*,
|
||||
@ -415,7 +450,8 @@ void gui_buffer_info(struct gui_memory_status*, struct gui_buffer*);
|
||||
Output:
|
||||
- buffer memory information
|
||||
*/
|
||||
void *gui_buffer_alloc(struct gui_buffer*, gui_size size, gui_size align);
|
||||
void *gui_buffer_alloc(struct gui_buffer*, enum gui_buffer_allocation_type,
|
||||
gui_size size, gui_size align);
|
||||
/* this functions allocated a aligned memory block from a buffer
|
||||
Input:
|
||||
- buffer to allocate memory from
|
||||
@ -424,6 +460,10 @@ void *gui_buffer_alloc(struct gui_buffer*, gui_size size, gui_size align);
|
||||
Output:
|
||||
- memory block with given size and alignment requirement
|
||||
*/
|
||||
void gui_buffer_mark(struct gui_buffer*, enum gui_buffer_allocation_type);
|
||||
/* sets a marker either for the back or front buffer */
|
||||
void gui_buffer_reset(struct gui_buffer*, enum gui_buffer_allocation_type);
|
||||
/* resets the buffer back to the previously set marker or if not set the begining */
|
||||
void gui_buffer_clear(struct gui_buffer*);
|
||||
/* this functions resets the buffer back into an empty state */
|
||||
void gui_buffer_free(struct gui_buffer*);
|
||||
@ -441,7 +481,8 @@ void gui_buffer_free(struct gui_buffer*);
|
||||
therefore abstracts over drawing routines and enables defered drawing.
|
||||
The API offers a number of drawing primitives like lines, rectangles, circles,
|
||||
triangles, images, text and clipping rectangles, that have to be drawn by the user.
|
||||
Therefore the command buffer is the main toolkit output besides the actual widget output.
|
||||
Therefore the command buffer is the main toolkit output besides the actual
|
||||
widget output.
|
||||
The actual draw command execution is done by the user and is build up in a
|
||||
interpreter like fashion by iterating over all commands and executing each
|
||||
command differently depending on the command type.
|
||||
@ -557,6 +598,23 @@ enum gui_command_clipping {
|
||||
GUI_CLIP = gui_true
|
||||
};
|
||||
|
||||
struct gui_command_buffer_stats {
|
||||
gui_uint lines;
|
||||
/* number of lines inside the buffer */
|
||||
gui_uint rectangles;
|
||||
/* number of rectangles in the buffer */
|
||||
gui_uint circles;
|
||||
/* number of circles in the buffer */
|
||||
gui_uint triangles;
|
||||
/* number of triangles in the buffer */
|
||||
gui_uint images;
|
||||
/* number of images in the buffer */
|
||||
gui_uint text;
|
||||
/* number of text commands in the buffer */
|
||||
gui_uint glyphes;
|
||||
/* number of text glyphes in the buffer */
|
||||
};
|
||||
|
||||
struct gui_command_queue;
|
||||
struct gui_command_buffer {
|
||||
struct gui_buffer *base;
|
||||
@ -565,10 +623,13 @@ struct gui_command_buffer {
|
||||
/* current clipping rectangle */
|
||||
gui_bool use_clipping;
|
||||
/* flag if the command buffer should clip commands */
|
||||
struct gui_command_buffer_stats stats;
|
||||
/* stats about the content of the buffer */
|
||||
struct gui_command_queue *queue;
|
||||
struct gui_command_buffer *next;
|
||||
struct gui_command_buffer *prev;
|
||||
gui_size begin, end, last;
|
||||
/* INTERNAL: references into a command queue */
|
||||
};
|
||||
|
||||
void gui_command_buffer_init(struct gui_command_buffer*, struct gui_buffer*,
|
||||
@ -703,9 +764,9 @@ const struct gui_command *gui_command_buffer_next(struct gui_command_buffer*,
|
||||
gui_command_queue_insert_back -- adds a command buffer in the back of the queue
|
||||
gui_command_queue_remove -- removes a command buffer from the queue
|
||||
gui_command_queue_start -- begins the command buffer filling process
|
||||
gui_command_queue_finish -- ends the command buffer filling process
|
||||
gui_command_queue_start_child -- begins the child command buffer filling process
|
||||
gui_command_queue_finish_child -- ends the child command buffer filling process
|
||||
gui_command_queue_finish -- ends the command buffer filling process
|
||||
|
||||
command iterator function API
|
||||
gui_command_queue_begin -- returns the first command in a queue
|
||||
@ -794,7 +855,8 @@ void gui_command_queue_finish(struct gui_command_queue*, struct gui_command_buff
|
||||
Input:
|
||||
- the now filled command buffer
|
||||
*/
|
||||
gui_bool gui_command_queue_start_child(struct gui_command_queue*, struct gui_command_buffer*);
|
||||
gui_bool gui_command_queue_start_child(struct gui_command_queue*,
|
||||
struct gui_command_buffer*);
|
||||
/* this function sets up a child buffer inside a command buffer to be filled up
|
||||
Input:
|
||||
- command buffer to begin the child buffer in
|
||||
@ -1004,22 +1066,22 @@ gui_size gui_edit_box_len(struct gui_edit_box*);
|
||||
the toolkit so everything has to be stored byte the user.
|
||||
|
||||
Widget function API
|
||||
gui_text -- draws a string inside a box
|
||||
gui_button_text -- button widget with text content
|
||||
gui_button_image -- button widget with icon content
|
||||
gui_button_triangle -- button widget with triangle content
|
||||
gui_button_text_triangle-- button widget with triangle and text content
|
||||
gui_button_text_image -- button widget with image and text content
|
||||
gui_toggle -- either a checkbox or radiobutton widget
|
||||
gui_slider -- floating point slider widget
|
||||
gui_progress -- unsigned integer progressbar widget
|
||||
gui_editbox -- Editbox widget for complex user input
|
||||
gui_edit -- Editbox wiget for basic user input
|
||||
gui_edit_filtered -- Editbox with utf8 gylph filter capabilities
|
||||
gui_spinner_int -- integer spinner widget
|
||||
gui_spinner_float -- float spinner widget
|
||||
gui_selector -- string selector widget
|
||||
gui_scroll -- scrollbar widget imeplementation
|
||||
gui_text -- draws a string inside a box
|
||||
gui_button_text -- button widget with text content
|
||||
gui_button_image -- button widget with icon content
|
||||
gui_button_triangle -- button widget with triangle content
|
||||
gui_button_text_triangle -- button widget with triangle and text content
|
||||
gui_button_text_image -- button widget with image and text content
|
||||
gui_toggle -- either a checkbox or radiobutton widget
|
||||
gui_slider -- floating point slider widget
|
||||
gui_progress -- unsigned integer progressbar widget
|
||||
gui_editbox -- Editbox widget for complex user input
|
||||
gui_edit -- Editbox wiget for basic user input
|
||||
gui_edit_filtered -- Editbox with utf8 gylph filter capabilities
|
||||
gui_spinner -- integer spinner widget
|
||||
gui_selector -- string selector widget
|
||||
gui_scrollbar_vertical -- vertical scrollbar widget imeplementation
|
||||
gui_scrollbar_horizontal -- horizontal scrollbar widget imeplementation
|
||||
*/
|
||||
struct gui_font {
|
||||
gui_handle userdata;
|
||||
@ -1391,8 +1453,8 @@ gui_size gui_edit(struct gui_command_buffer*, struct gui_rect, gui_char*, gui_si
|
||||
- returns the size of the buffer in bytes after the modification
|
||||
*/
|
||||
gui_size gui_edit_filtered(struct gui_command_buffer*, struct gui_rect,
|
||||
gui_char*, gui_size, gui_size max, gui_state*, gui_size *cursor,
|
||||
const struct gui_edit*, gui_filter filter,
|
||||
gui_char*, gui_size, gui_size max, gui_state*,
|
||||
gui_size *cursor, const struct gui_edit*, gui_filter filter,
|
||||
const struct gui_input*, const struct gui_font*);
|
||||
/* this function executes a editbox widget
|
||||
Input:
|
||||
@ -1411,28 +1473,10 @@ gui_size gui_edit_filtered(struct gui_command_buffer*, struct gui_rect,
|
||||
- state of the editbox with either active or inactive
|
||||
- returns the size of the buffer in bytes after the modification
|
||||
*/
|
||||
gui_int gui_spinner_int(struct gui_command_buffer*, struct gui_rect,
|
||||
const struct gui_spinner*, gui_int min, gui_int value,
|
||||
gui_int max, gui_int step, gui_state *active,
|
||||
const struct gui_input*, const struct gui_font*);
|
||||
/* this function executes a integer spinner widget
|
||||
Input:
|
||||
- output command buffer for draw commands
|
||||
- bounds of the spinner widget
|
||||
- visual widget style structure describing the spinner
|
||||
- minimal spinner value that will no be underflown
|
||||
- spinner value that will be updated
|
||||
- maximal spinner value that will no be overflown
|
||||
- spinner input state with either active or inactive
|
||||
- input structure to update the slider with
|
||||
- font structure for text drawing
|
||||
Output:
|
||||
- returns the from the user input updated spinner value
|
||||
*/
|
||||
gui_float gui_spinner_float(struct gui_command_buffer*, struct gui_rect,
|
||||
const struct gui_spinner*, gui_float, gui_float,
|
||||
gui_float max, gui_float, gui_state*,
|
||||
const struct gui_input*, const struct gui_font*);
|
||||
gui_int gui_spinner(struct gui_command_buffer*, struct gui_rect,
|
||||
const struct gui_spinner*, gui_int min, gui_int value,
|
||||
gui_int max, gui_int step, gui_state *active,
|
||||
const struct gui_input*, const struct gui_font*);
|
||||
/* this function executes a integer spinner widget
|
||||
Input:
|
||||
- output command buffer for draw commands
|
||||
@ -1523,17 +1567,17 @@ gui_float gui_scrollbar_horizontal(struct gui_command_buffer*, struct gui_rect,
|
||||
were added.
|
||||
|
||||
Configuration function API
|
||||
gui_config_default -- initializes a default panel configuration
|
||||
gui_config_set_font -- changes the used font
|
||||
gui_config_property -- returns the property value from an id
|
||||
gui_config_color -- returns the color value from an id
|
||||
gui_config_push_property -- push an old property onto a interal stack and sets a new value
|
||||
gui_config_push_color -- push an old color onto a internal stack and sets a new value
|
||||
gui_config_pop_color -- resets an old color value from the internal stack
|
||||
gui_config_pop_property -- resets an old property value from the internal stack
|
||||
gui_config_reset_colors -- reverts back all temporary color changes from the config
|
||||
gui_config_reset_properties -- reverts back all temporary property changes from the config
|
||||
gui_config_reset -- reverts back all temporary all changes from the config
|
||||
gui_config_default -- initializes a default panel configuration
|
||||
gui_config_set_font -- changes the used font
|
||||
gui_config_property -- returns the property value from an id
|
||||
gui_config_color -- returns the color value from an id
|
||||
gui_config_push_property -- push old property onto stack and sets a new value
|
||||
gui_config_push_color -- push old color onto stack and sets a new value
|
||||
gui_config_pop_color -- resets an old color value from the internal stack
|
||||
gui_config_pop_property -- resets an old property value from the internal stack
|
||||
gui_config_reset_colors -- reverts back all temporary color changes from the config
|
||||
gui_config_reset_properties -- reverts back all temporary property changes
|
||||
gui_config_reset -- reverts back all temporary all changes from the config
|
||||
*/
|
||||
enum gui_config_colors {
|
||||
GUI_COLOR_TEXT,
|
||||
@ -1656,7 +1700,7 @@ struct gui_config {
|
||||
void gui_config_default(struct gui_config*, gui_flags, const struct gui_font*);
|
||||
/* this function load the panel configuration with default values
|
||||
Input:
|
||||
- configuration flags indicating which part of the configuration should be loaded with default values
|
||||
- config flags which part of the configuration should be loaded with default values
|
||||
- user font reference structure describing the font used inside the panel
|
||||
Output:
|
||||
- configuration structure holding the default panel style
|
||||
@ -1685,7 +1729,7 @@ struct gui_color gui_config_color(const struct gui_config*, enum gui_config_colo
|
||||
*/
|
||||
void gui_config_push_property(struct gui_config*, enum gui_config_properties,
|
||||
struct gui_vec2);
|
||||
/* this function temporarily changes a property in a stack like fashion to be reseted later
|
||||
/* this function temporarily changes a property in a stack to be reseted later
|
||||
Input:
|
||||
- Configuration structure to push the change to
|
||||
- Property idenfifier to change
|
||||
@ -1749,13 +1793,13 @@ void gui_config_reset(struct gui_config*);
|
||||
a easy way to abstract over a big number of platforms, renter backends, font
|
||||
implementations.
|
||||
|
||||
---------- -------------
|
||||
| config | ------------- | |
|
||||
----------
|
||||
| config | ------------- -------------
|
||||
| panel | | | | widget |
|
||||
| memory | ------\ | GUI | -------> |-----------|
|
||||
| widget | ------/ | | | commands |
|
||||
| Input | ------------- | |
|
||||
---------- -------------
|
||||
| Input | ------------- -------------
|
||||
----------
|
||||
|
||||
The panel can be divided into a header, menubar and body. The header
|
||||
provides functionality like closing or minimizing while the menubar
|
||||
@ -1770,13 +1814,17 @@ void gui_config_reset(struct gui_config*);
|
||||
Header functions -- functions to create and setup a panel header and menubar
|
||||
Layout functions -- API that provides different ways to place widgets in the panel
|
||||
Widget functions -- immediate mode widgets functions to till the panel with
|
||||
Complex functions -- Widget with more complex behavior and requirements
|
||||
Graph functions -- graph widget with line and column graph
|
||||
Table functions -- functions to visualize a basic table
|
||||
Group functions -- Widget grouping functions
|
||||
|
||||
Tree functions -- Tree widget API to visual tree datastructures
|
||||
Popup functions -- Panel bounds popups API
|
||||
Shelf functions -- Shelf is a panel with different tabs
|
||||
Menu functions -- Single depth popup menu
|
||||
*/
|
||||
enum gui_widget_state {
|
||||
GUI_WIDGET_INVALID, /* The widget cannot be seen and is completly out of view */
|
||||
GUI_WIDGET_VALID, /* The widget is completly inside the panel and can be updated + drawn */
|
||||
GUI_WIDGET_VALID, /* The widget is completly inside the panel can be updated + drawn */
|
||||
GUI_WIDGET_ROM /* The widget is partially visible and cannot be updated */
|
||||
};
|
||||
|
||||
@ -1833,6 +1881,7 @@ struct gui_panel {
|
||||
};
|
||||
|
||||
enum gui_panel_row_layout_type {
|
||||
/* ----------------- INTERNAL ------------------------------ */
|
||||
GUI_PANEL_LAYOUT_DYNAMIC_FIXED,
|
||||
/* fixed widget ratio width panel layout */
|
||||
GUI_PANEL_LAYOUT_DYNAMIC_ROW,
|
||||
@ -1932,7 +1981,6 @@ struct gui_panel_layout {
|
||||
struct gui_command_queue *queue;
|
||||
/* command draw call output command buffer */
|
||||
};
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------
|
||||
* MAIN
|
||||
@ -1960,13 +2008,13 @@ struct gui_panel_layout {
|
||||
panel function API
|
||||
gui_panel_init -- initializes the panel with position, size and flags
|
||||
gui_panel_begin -- begin sequence point in the panel layout build up process
|
||||
gui_panel_begin_tiled -- extends gui_panel_begin by adding the panel into a tiled layout
|
||||
gui_panel_end -- end squeunce point which finializes the panel build up
|
||||
gui_panel_set_config -- updates the used panel configuration
|
||||
gui_panel_add_flag -- adds a behavior flag to the panel
|
||||
gui_panel_remove_flag -- removes a behavior flag from the panel
|
||||
gui_panel_has_flag -- check if a given behavior flag is set in the panel
|
||||
gui_panel_is_minimized -- return wether the panel is minimized
|
||||
gui_panel_canvas -- returns the command buffer from a panel layout
|
||||
*/
|
||||
void gui_panel_init(struct gui_panel *panel, gui_float x, gui_float y, gui_float w,
|
||||
gui_float h, gui_flags flags, struct gui_command_queue*,
|
||||
@ -2010,6 +2058,8 @@ gui_bool gui_panel_has_flag(struct gui_panel*, gui_flags);
|
||||
*/
|
||||
gui_bool gui_panel_is_minimized(struct gui_panel*);
|
||||
/* this function checks if the panel is minimized */
|
||||
struct gui_command_buffer* gui_panel_canvas(struct gui_panel_layout*);
|
||||
/* this functions returns the currently used draw command buffer */
|
||||
/*
|
||||
* --------------------------------------------------------------
|
||||
* HEADER
|
||||
@ -2025,7 +2075,7 @@ gui_bool gui_panel_is_minimized(struct gui_panel*);
|
||||
To create a header you have to call one of two API after the panel layout
|
||||
has been created with `gui_panel_begin`. The first and easiest way is to
|
||||
just call `gui_panel_header` which provides a basic header with
|
||||
customizable buttons as well as title but notification if a button is pressed.
|
||||
with title and button and buton pressed notification if a button was pressed.
|
||||
The layout supported is hereby limited and custom button and icons cannot be
|
||||
added. To achieve that you have to use the more extensive header API.
|
||||
You start by calling `gui_panel_header_begin` after `gui_panel_begin` and
|
||||
@ -2284,30 +2334,29 @@ void gui_panel_layout_pop(struct gui_panel_layout*);
|
||||
by adding draw command into the panel command buffer.
|
||||
|
||||
Panel widget API
|
||||
gui_panel_widget -- base function for all widgets to allocate space on the panel
|
||||
gui_panel_spacing -- create a column seperator and is basically an empty widget
|
||||
gui_panel_widget -- base function for all widgets to allocate space
|
||||
gui_panel_spacing -- column seperator and is basically an empty widget
|
||||
gui_panel_text -- text widget for printing text with length
|
||||
gui_panel_text_colored -- colored text widget for printing colored text width length
|
||||
gui_panel_text_colored -- colored text widget for printing string by length
|
||||
gui_panel_label -- text widget for printing zero terminated strings
|
||||
gui_panel_label_colored -- text widget for printing colored zero terminiated strings
|
||||
gui_panel_label_colored -- widget for printing colored zero terminiated strings
|
||||
gui_panel_button_text -- button widget with text content
|
||||
gui_panel_button_color -- colored button widget without content
|
||||
gui_panel_button_triangle -- button with triangle pointing either up-/down-/left- or right
|
||||
gui_panel_button_triangle -- button with triangle either up-/down-/left- or right
|
||||
gui_panel_button_image -- button widget width icon content
|
||||
gui_panel_button_toggle -- toggle button with either active or inactive state
|
||||
gui_panel_button_text_image -- button widget with text and icon
|
||||
gui_panel_button_text_triangle -- button widget with text and a triangle
|
||||
gui_panle_image -- image widget for outputing a image to a panel
|
||||
gui_panel_check -- add a checkbox widget with either active or inactive state
|
||||
gui_panel_option -- radiobutton widget with either active or inactive state
|
||||
gui_panel_image -- image widget for outputing a image to a panel
|
||||
gui_panel_check -- add a checkbox widget
|
||||
gui_panel_option -- radiobutton widget
|
||||
gui_panel_option_group -- radiobutton group for automatic single selection
|
||||
gui_panel_slider -- slider widget with min,max,step value
|
||||
gui_panel_progress -- progressbar widget
|
||||
gui_panel_edit -- edit textbox widget for text input
|
||||
gui_panel_edit_filtered -- edit textbox widget for text input with filter input
|
||||
gui_panel_editbox -- edit textbox with cursor, clipboard and filter
|
||||
gui_panel_spinner_int -- spinner widget with either keyboard or mouse modification
|
||||
gui_panel_spinner_float -- spinner widget with either keyboard or mouse modification
|
||||
gui_panel_spinner -- spinner widget with keyboard or mouse modification
|
||||
gui_panel_selector -- selector widget for combobox like selection of types
|
||||
*/
|
||||
enum gui_widget_state gui_panel_widget(struct gui_rect*, struct gui_panel_layout*);
|
||||
@ -2432,7 +2481,7 @@ gui_bool gui_panel_button_image(struct gui_panel_layout*, struct gui_image img,
|
||||
gui_bool gui_panel_button_text_triangle(struct gui_panel_layout*, enum gui_heading,
|
||||
const char*, enum gui_text_align,
|
||||
enum gui_button_behavior);
|
||||
/* this function creates a button with a triangle pointing in one of four directions and text
|
||||
/* this function creates a button with a triangle and text
|
||||
Input:
|
||||
- triangle direction with either up, down, left or right direction
|
||||
- button label describing the button
|
||||
@ -2514,7 +2563,7 @@ gui_size gui_panel_edit_filtered(struct gui_panel_layout*, gui_char *buffer,
|
||||
- length of the buffer after user input update
|
||||
- current state of the editbox with active(gui_true) or inactive(gui_false)
|
||||
*/
|
||||
gui_int gui_panel_spinner_int(struct gui_panel_layout*, gui_int min, gui_int value,
|
||||
gui_int gui_panel_spinner(struct gui_panel_layout*, gui_int min, gui_int value,
|
||||
gui_int max, gui_int step, gui_state *active);
|
||||
/* this function creates a integer spinner widget
|
||||
Input:
|
||||
@ -2527,19 +2576,6 @@ gui_int gui_panel_spinner_int(struct gui_panel_layout*, gui_int min, gui_int val
|
||||
- the from user input updated spinner value
|
||||
- current state of the editbox with active(gui_true) or inactive(gui_false)
|
||||
*/
|
||||
gui_float gui_panel_spinner_float(struct gui_panel_layout*, gui_float min, gui_float value,
|
||||
gui_float max, gui_float step, gui_state *active);
|
||||
/* this function creates a float spinner widget
|
||||
Input:
|
||||
- min value that will not be underflown
|
||||
- current spinner value to be updated by user input
|
||||
- max value that will not be overflown
|
||||
- spinner value modificaton stepping intervall
|
||||
- current state of the spinner with active as currently modfied by user input
|
||||
Output:
|
||||
- the from user input updated spinner value
|
||||
- current state of the editbox with active(gui_true) or inactive(gui_false)
|
||||
*/
|
||||
gui_size gui_panel_selector(struct gui_panel_layout*, const char *items[],
|
||||
gui_size item_count, gui_size item_current);
|
||||
/* this function creates a string selector widget
|
||||
@ -2584,7 +2620,7 @@ void gui_panel_group_begin(struct gui_panel_layout*, struct gui_panel_layout *ta
|
||||
Output:
|
||||
- group layout to fill with widgets
|
||||
*/
|
||||
struct gui_vec2 gui_panel_group_end(struct gui_panel_layout*, struct gui_panel_layout* tab);
|
||||
struct gui_vec2 gui_panel_group_end(struct gui_panel_layout*, struct gui_panel_layout*);
|
||||
/* this function finishes the previously started group layout
|
||||
Output:
|
||||
- The from user input updated group scrollbar pixel offset
|
||||
@ -2658,7 +2694,6 @@ enum gui_popup_type {
|
||||
GUI_POPUP_STATIC, /* static fixed height non growing popup */
|
||||
GUI_POPUP_DYNAMIC /* dynamically growing popup with maximum height */
|
||||
};
|
||||
|
||||
gui_flags gui_panel_popup_begin(struct gui_panel_layout *parent,
|
||||
struct gui_panel_layout *popup,
|
||||
enum gui_popup_type, struct gui_rect bounds,
|
||||
@ -2803,7 +2838,7 @@ void gui_panel_combo(struct gui_panel_layout*, const char **entries,
|
||||
- the scrollbar offset of the panel scrollbar
|
||||
Output:
|
||||
- updated currently selected index
|
||||
- updated state of the combo box
|
||||
- updated state of the combo box
|
||||
*/
|
||||
void gui_panel_combo_begin(struct gui_panel_layout *parent,
|
||||
struct gui_panel_layout *combo, const char *selected,
|
||||
@ -3020,186 +3055,6 @@ void gui_panel_table_end(struct gui_panel_layout*);
|
||||
/* this function finished the table build up process and reverts the panel back
|
||||
to its normal state.
|
||||
*/
|
||||
/*
|
||||
* ==============================================================
|
||||
*
|
||||
* Window Layout
|
||||
*
|
||||
* ===============================================================
|
||||
*/
|
||||
/* LAYOUT
|
||||
----------------------------
|
||||
The tiled layout provides a way to divide the screen into slots which
|
||||
again can be divided into either horizontal or vertical panels or another
|
||||
tiled layout. This is especially usefull for more complex application which
|
||||
need more than just fixed or overlapping panels. There are five slots
|
||||
(Top, Left, Center, Right, Bottom) in the layout which are either be
|
||||
scaleable or static and occupy a certain percentage of the screen.
|
||||
|
||||
USAGE
|
||||
----------------------------
|
||||
To use the tile layout you first have to define the bounds of the layout,
|
||||
which slots of the layout is going to be used, how many panels are contained
|
||||
inside each slot as well as if a slot can be scaled or is static.
|
||||
This is done by calling `gui_layout_slot` for scaleable and `gui_layout_slot_locked`
|
||||
for non-scaleable slot in between the `gui_layout_begin` and `gui_layout_end` call,
|
||||
for each used layout slot. After that each panel will have to take the tiled
|
||||
layout as argument in the `gui_panel_begin_tiled` function call.
|
||||
|
||||
-----------------------------
|
||||
| Top |
|
||||
-----------------------------
|
||||
| | | |
|
||||
| Left | Center | Right |
|
||||
| | | |
|
||||
-----------------------------
|
||||
| Bottom |
|
||||
-----------------------------
|
||||
|
||||
definition function API
|
||||
gui_layout_begin - begins the layout definition process
|
||||
gui_layout_slot_locked - adds a non scaleable slot
|
||||
gui_layout_slot - adds a scaleable slot
|
||||
gui_layout_end - ends the definition process
|
||||
|
||||
update function API
|
||||
gui_layout_set_size - updates the size of the layaout
|
||||
gui_layout_set_pos - updates the position of the layout
|
||||
gui_layout_set_state - activate or deactivate user input
|
||||
gui_layout_load - position a child layout into parent layout slot
|
||||
gui_layout_remove - removes a panel from the layout
|
||||
gui_layout_clear - removes all panels from the layout
|
||||
gui_layout_slot_bounds - queries the space of a given slot
|
||||
gui_layout_slot_panel_bounds - queries the space of a panel in a slot
|
||||
*/
|
||||
enum gui_layout_slot_index {
|
||||
GUI_SLOT_TOP,
|
||||
GUI_SLOT_BOTTOM,
|
||||
GUI_SLOT_LEFT,
|
||||
GUI_SLOT_CENTER,
|
||||
GUI_SLOT_RIGHT,
|
||||
GUI_SLOT_MAX
|
||||
};
|
||||
|
||||
enum gui_layout_format {
|
||||
GUI_LAYOUT_HORIZONTAL,
|
||||
/* panels in slots are added left to right */
|
||||
GUI_LAYOUT_VERTICAL
|
||||
/* panels in slots are added top to bottom */
|
||||
};
|
||||
|
||||
enum gui_layout_slot_state {
|
||||
GUI_UNLOCKED,
|
||||
/* SLOT is scaleable */
|
||||
GUI_LOCKED
|
||||
/* SLOT is static */
|
||||
};
|
||||
|
||||
struct gui_layout_slot {
|
||||
gui_size capacity;
|
||||
/* number of panels inside the slot */
|
||||
gui_float value;
|
||||
/* temporary storage for the layout build up process */
|
||||
struct gui_vec2 ratio;
|
||||
/* horizontal and vertical window ratio */
|
||||
struct gui_vec2 offset;
|
||||
/* position of the slot in the window */
|
||||
enum gui_layout_format format;
|
||||
/* panel filling layout */
|
||||
enum gui_layout_slot_state state;
|
||||
/* scaleable state */
|
||||
};
|
||||
|
||||
struct gui_layout {
|
||||
gui_float scaler_width;
|
||||
/* width of the scaling line between slots */
|
||||
struct gui_rect bounds;
|
||||
/* bounds of the layout inside the window */
|
||||
gui_state active;
|
||||
/* flag indicating if the layout is from the user modifyable */
|
||||
struct gui_layout_slot slots[GUI_SLOT_MAX];
|
||||
/* each slot inside the panel layout */
|
||||
};
|
||||
|
||||
void gui_panel_begin_tiled(struct gui_panel_layout*, struct gui_panel*,
|
||||
struct gui_layout*, enum gui_layout_slot_index, gui_size index);
|
||||
/* this function begins a tiled panel build up process
|
||||
Input:
|
||||
- slot the panel will be placed inside the tiled layout
|
||||
- panel slot index inside the slot
|
||||
- input structure holding all user generated state changes
|
||||
*/
|
||||
void gui_layout_begin(struct gui_layout*, struct gui_rect bounds,
|
||||
gui_state);
|
||||
/* this function start the definition of the layout slots
|
||||
Input:
|
||||
- position (width/height) of the layout in the window
|
||||
- size (width/height) of the layout in the window
|
||||
- layout state with either active as user updateable or inactive for blocked
|
||||
*/
|
||||
void gui_layout_slot_locked(struct gui_layout*, enum gui_layout_slot_index,
|
||||
gui_float ratio, enum gui_layout_format,
|
||||
gui_size entry_count);
|
||||
/* this function activates a non scaleable slot inside a scaleable layout
|
||||
Input:
|
||||
- index of the slot to be activated
|
||||
- percentage of the screen that is being occupied
|
||||
- panel filling format either horizntal or vertical
|
||||
- number of panels the slot will be filled with
|
||||
*/
|
||||
void gui_layout_slot(struct gui_layout*, enum gui_layout_slot_index, gui_float ratio,
|
||||
enum gui_layout_format, gui_size entry_count);
|
||||
/* this function activates a slot inside the layout
|
||||
Input:
|
||||
- index of the slot to be activated
|
||||
- percentage of the screen that is being occupied
|
||||
- panel filling format either horizntal or vertical
|
||||
- number of panels the slot will be filled with
|
||||
*/
|
||||
void gui_layout_end(struct gui_layout*);
|
||||
/* this function ends the definition of the layout slots */
|
||||
void gui_layout_load(struct gui_layout*child, struct gui_layout *parent,
|
||||
enum gui_layout_slot_index, gui_size index);
|
||||
/* this function places a child layout into a parent slot panel index
|
||||
Input:
|
||||
- child layout that will be filled
|
||||
- parent layout that provided the position/size and state for the child
|
||||
- the slot index the child layout will be placed into
|
||||
- the panel index in the slot the child layout will be placed into
|
||||
*/
|
||||
void gui_layout_set_size(struct gui_layout*, gui_size width, gui_size height);
|
||||
/* this function updates the size of the layout
|
||||
Input:
|
||||
- size (width/height) of the layout in the window
|
||||
*/
|
||||
void gui_layout_set_pos(struct gui_layout*, gui_size x, gui_size y);
|
||||
/* this function updates the position of the layout
|
||||
Input:
|
||||
- position (x/y) of the layout in the window
|
||||
*/
|
||||
void gui_layout_set_state(struct gui_layout*, gui_state);
|
||||
/* this function changes the user modifiable layout state
|
||||
Input:
|
||||
- new state of the layout with either active or inactive
|
||||
*/
|
||||
void gui_layout_slot_bounds(struct gui_rect *bounds, const struct gui_layout*,
|
||||
enum gui_layout_slot_index);
|
||||
/* this function returns the complete space occupied by a given slot
|
||||
Input:
|
||||
- index of the slot to be queried
|
||||
Output:
|
||||
- bounds of the slot as a rectangle (x,y,w,h)
|
||||
*/
|
||||
void gui_layout_slot_panel_bounds(struct gui_rect *bounds, const struct gui_layout*,
|
||||
enum gui_layout_slot_index, gui_size entry);
|
||||
/* this function returns the space occupied by a given panel and slot
|
||||
Input:
|
||||
- slot index to be queried
|
||||
- panel index to be queried
|
||||
Output:
|
||||
- bounds of the panel inside the slot as a rectangle (x,y,w,h)
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 75 KiB |
Loading…
Reference in New Issue
Block a user