State-mode GUI, single header ANSI C library
bzt 2d5023a029 Allow to specify font on command line in widgets.c | 4 months ago | |
---|---|---|
docs | 4 months ago | |
examples | 4 months ago | |
mods | 4 months ago | |
public | 4 months ago | |
.gitignore | 5 months ago | |
.gitlab-ci.yml | 5 months ago | |
LICENSE | 5 months ago | |
README.md | 5 months ago | |
ui.h | 4 months ago |
The SMGUI is minimal-state graphical user interface toolkit written in ANSI C, which is neither callback-driven nor immediate-mode, rather state-mode. I've created it because I've tried Nuklear and I was extremely disappointed with it (huge, inefficient and extremely hard to integrate).
The main concept of a state-mode UI is, that you already have your variables, so you reference those from a layout, which has no callbacks neither requires immediate-mode calls, it is just uses those already existing variables for rendering the GUI states.
gcc -ansi
)This library is self-contained in one single header file and can be used either in header-only mode or in
implementation mode. The header-only mode is used by default when included and allows including this header
in other headers and does not contain the actual implementation. The implementation mode requires defining
the preprocessor macro UI_IMPLEMENTATION
in exactly one .c/.cpp file before including this file.
The base library is entirely platform and backend agnostic. You can select which backend and font driver module to use just by including them before ui.h.
#include "ui_glfw.h"
#include "ui_psf2.h"
#define UI_IMPLEMENTATION
#include "ui.h"
By default, if no other modules included beforehand, then ui.h includes the GLFW3 backend and PSF2 fonts and also embeds a minimal ASCII-only font (2080 bytes compiled).
NOTE this is the entire, fully working example, no hidden integration requirements!
#define UI_IMPLEMENTATION
#include <ui.h>
int main(int argc, char **argv)
{
/* localized strings array */
enum { WINDOW_TITLE, POPUP_TITLE, BUTTON_TITLE, EASY_TITLE, HARD_TITLE, VOLUME_TITLE };
char *lang[] = { "Basic demo", "Show", "Button", "easy", "hard", "Volume:" };
/* variables to store game states */
int button = 0, difficulty = 0, volume = 25;
/* form referencing those variables, you use a HTML flow like layout */
ui_t ctx;
ui_form_t popup[] = {
{ .ptr = &button, .value = 1, .type = UI_BUTTON, .flags = UI_FORCEBR,
.label = BUTTON_TITLE },
{ .ptr = &difficulty, .value = 0, .type = UI_RADIO, .flags = UI_NOBR, .y = 5,
.label = EASY_TITLE },
{ .ptr = &difficulty, .value = 1, .type = UI_RADIO, .flags = UI_FORCEBR, .x = 20,
.label = HARD_TITLE },
{ .label = VOLUME_TITLE, .type = UI_LABEL, .flags = UI_NOBR, .y = 5 },
{ .ptr = &volume, .min = 0, .max = 100, .type = UI_SLIDER },
{ .type = UI_END }
};
ui_form_t form[] = {
{ .ptr = &popup, .type = UI_POPUP, .m = 10, .label = POPUP_TITLE,
.x = UI_PERCENT(50), .y = UI_PERCENT(50), .align = UI_CENTER | UI_MIDDLE },
{ .type = UI_END }
};
/* initialize the UI context */
ui_init(&ctx, sizeof(lang)/sizeof(lang[0]), lang, 640, 480, NULL);
/* wait until user closes the window */
while(ui_event(&ctx, form)) {
/* handle button, you can do this from another thread if you want */
if(button) {
printf("button clicked\n");
button = 0;
ui_refresh(&ctx);
}
}
/* destroy window, free resources */
ui_free(&ctx);
return 0;
}
Licensed under the terms of the permissive MIT license, see LICENSE.
Cheers, bzt