major rewrite
This commit is contained in:
parent
6297aeac68
commit
075925a66c
127
Readme.md
127
Readme.md
@ -5,143 +5,60 @@ WORK IN PROGRESS: I do not garantee that everything works right now
|
||||
## Features
|
||||
- Immediate mode graphical user interface toolkit
|
||||
- Written in C89 (ANSI C)
|
||||
- Small (~2.5kLOC)
|
||||
- Small codebase with roughly 2kLOC
|
||||
- Focus on portability and minimal internal state
|
||||
- Suited for embedding into graphical applications
|
||||
- No global hidden state
|
||||
- No direct dependencies (not even libc!)
|
||||
- No memory allocation
|
||||
- Renderer and platform independent
|
||||
- Configurable
|
||||
- UTF-8 supported
|
||||
|
||||
## Limitations
|
||||
- Does NOT provide platform independent window management
|
||||
- Does NOT provide platform independent input handling
|
||||
- Does NOT provide window management
|
||||
- Does NOT provide input handling
|
||||
- Does NOT provide a renderer backend
|
||||
- Does NOT implement a font library
|
||||
Summary: It is only responsible for the actual user interface
|
||||
|
||||
## Layer
|
||||
The gui toolkit consists of three levels of abstraction. First the basic widget layer
|
||||
for a as pure functional as possible set of widgets functions without
|
||||
any kind of internal state, with the tradeoff off of a lot of boilerplate code.
|
||||
Second the panel layer for a static grouping of widgets into a panel with a reduced need for
|
||||
a lot of the boilerplate code but takes away some freedom of widget placing and
|
||||
introduces the state of the panel.
|
||||
Finally there is the context layer which represent the complete window and
|
||||
enables moveable, scaleable and overlapping panels, but needs complete control
|
||||
over the panel management and therefore needs the most amount of internal state.
|
||||
Each higher level of abstraction uses the lower level(s) internally to build
|
||||
on but offers a little bit different API.
|
||||
|
||||
#### Widgets
|
||||
The widget layer provides the most basic way of creating graphical user interface
|
||||
elements. It consist only of functions and only operates on the given data. Each
|
||||
widgets takes in the current input state, font and the basic element configuration
|
||||
and returns an updated draw buffer and the state of the element.
|
||||
With each widget the buffer gets filled with a number of primitives that need be
|
||||
drawn to screen. The main reason for the command buffer to queue up the draw
|
||||
calls instead of just using a callback to directly draw the primitive lies in
|
||||
the context which needs control over the drawing order. For a more limited scope
|
||||
of functionality it would have been better to just use draw callbacks and to not
|
||||
rely on memory allocation at all. The API will change if I find a way to
|
||||
combine the buffer needed by the context with the drawing callbacks.
|
||||
|
||||
```c
|
||||
struct gui_input input = {0};
|
||||
struct gui_command_buffer buffer;
|
||||
struct gui_command_list list;
|
||||
struct gui_memory_status status;
|
||||
const struct gui_font font = {...};
|
||||
const struct gui_buffer button = {...};
|
||||
struct gui_memory memory = {...};
|
||||
struct gui_input in = {0};
|
||||
struct gui_canvas canvas = {...};
|
||||
struct gui_button style = {...};
|
||||
gui_default_config(&config);
|
||||
|
||||
while (1) {
|
||||
gui_input_begin(&input);
|
||||
/* record input */
|
||||
gui_input_end(&input);
|
||||
|
||||
gui_output_begin(&buffer, &memory);
|
||||
if (gui_widget_button(&buffer, &button, "button", &font, &input))
|
||||
if (gui_button_text(&canvas, 50, 50, 100, 30, &style, "button", GUI_BUTTON_DEFAULT, &input))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
gui_output_end(&buffer, &status, &list);
|
||||
/* execute command list */
|
||||
}
|
||||
```
|
||||
|
||||
#### Panels
|
||||
Panels provide an easy way to group together a number of widgets and reduce
|
||||
some of the boilerplate code of the widget layer. Most of the boilerplate code
|
||||
gets reduced by introducing a configration structure to provide a common look.
|
||||
Instead of having a fixed layout and owning and holding widgets like in classic
|
||||
graphical user interfaces, panels use an immediate mode approach of just setting
|
||||
the layout of one row of the panel at a time and filling each row with widgets.
|
||||
Therefore the only state that is being modfied over the course of setting up the
|
||||
panel is an index descriping the current position of the next widget and the
|
||||
current height and number of columns of the current row. In addition panels
|
||||
provide a number of grouping functionality for widgets with groups, tabs and
|
||||
shelfs and provide a minimizing and closing functionality.
|
||||
|
||||
```c
|
||||
struct gui_input in = {0};
|
||||
struct gui_config config;
|
||||
struct gui_command_buffer buffer;
|
||||
struct gui_command_list list;
|
||||
struct gui_memory_status status;
|
||||
const struct gui_font font = {...};
|
||||
struct gui_memory memory = {...};
|
||||
struct gui_panel panel = {0};
|
||||
struct gui_canvas canvas = {...};
|
||||
gui_default_config(&config);
|
||||
gui_panel_init(&panel, &config, &font);
|
||||
|
||||
while (1) {
|
||||
gui_input_begin(&input);
|
||||
/* record input */
|
||||
gui_input_end(&input);
|
||||
|
||||
gui_output_begin(&buffer, &memory);
|
||||
gui_panel_begin(&panel, &buffer, &input, "Demo", 50, 50, 400, 300, 0);
|
||||
gui_panel_begin(&panel, "Demo", panel.x, panel.y, panel.width, panel.height,
|
||||
GUI_PANEL_CLOSEABLE|GUI_PANEL_MINIMIZABLE|GUI_PANEL_BORDER|
|
||||
GUI_PANEL_MOVEABLE|GUI_PANEL_SCALEABLE, &config, &canvas, &in);
|
||||
gui_panel_layout(&panel, 30, 1);
|
||||
if (gui_panel_button_text(&panel, "button", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
gui_panel_end(&panel);
|
||||
gui_output_end(&buffer, &status, &list);
|
||||
/* execute command list */
|
||||
}
|
||||
```
|
||||
|
||||
#### Context
|
||||
The context extends the panel functionality with moving, scaling and overlapping
|
||||
panels which are quite a bit more complicated than just minimzing and closing of
|
||||
panels. For panel overlapping to work as intented the context needs complete control
|
||||
over all created panels to control the drawing order. OVerall the expense to
|
||||
provide overlapping panels is quite hight since draw calls, the context and
|
||||
all panels need to be managed and allocated.
|
||||
|
||||
```c
|
||||
struct gui_config config;
|
||||
struct gui_output output;
|
||||
struct gui_memory_status status;
|
||||
const struct gui_font font = {...};
|
||||
struct gui_memory memory = {...};
|
||||
struct gui_panel *panel;
|
||||
struct gui_context *ctx;
|
||||
gui_default_config(&config);
|
||||
ctx = gui_new(&memory, &input);
|
||||
panel = gui_new_panel(ctx, 50, 50, 400, 300, &config, &font);
|
||||
|
||||
while (1) {
|
||||
gui_input_begin(&input);
|
||||
/* record input */
|
||||
gui_input_end(&input);
|
||||
|
||||
gui_begin(ctx, 800, 600);
|
||||
gui_begin_panel(ctx, panel, "demo", 0);
|
||||
gui_panel_layout(&panel, 30, 1);
|
||||
if (gui_panel_button_text(&panel, "button", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
gui_end_panel(ctx, &panel, NULL);
|
||||
gui_end(ctx, &output, NULL);
|
||||
/* execute output lists */
|
||||
}
|
||||
```
|
||||
|
||||
@ -198,22 +115,6 @@ question is not as easy. In the end the project does not have font handling
|
||||
since there are already a number of font handling libraries in existence or even the
|
||||
platform (Xlib, Win32) itself already provides a solution.
|
||||
|
||||
#### Why do you use fixed size memory management
|
||||
This is one of the more controversial decision in the toolkit and it comes down
|
||||
to some preference that I personally build up. There are two general
|
||||
ways to allocate memory, the standard way of callbacks and preallocation.
|
||||
Personally I am not a big fan of callbacks even though they have their use cases
|
||||
for abstraction purposes but are greatly overused in my experience.
|
||||
Memory callbacks are an edge case for me and definitly shine in cases where a lot
|
||||
of unpredictable allocation with varying life cycles take place. This toolkit on
|
||||
the other hand has a relative stable memory allocation behavior. In the worse
|
||||
case on the highst abstraction layer only the context, panels and the command
|
||||
buffer need memory. In addition the general memory consumption is not that high
|
||||
and could even be described as insignificant for the modern memory size. For a
|
||||
system with a low amount of memory it is even better since there is only a small
|
||||
limited amount of memory which is easier to optimize for as a fixed amount of memory than
|
||||
a number of unrelated allocation calls.
|
||||
|
||||
## References
|
||||
- [Tutorial from Jari Komppa about imgui libraries](http://www.johno.se/book/imgui.html)
|
||||
- [Johannes 'johno' Norneby's article](http://iki.fi/sol/imgui/)
|
||||
|
523
demo/xlib.c
523
demo/xlib.c
@ -1,3 +1,4 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
@ -11,10 +12,8 @@
|
||||
#include "../gui.h"
|
||||
|
||||
/* macros */
|
||||
#define MAX_BUFFER 64
|
||||
#define MAX_MEMORY (16 * 1024)
|
||||
#define MAX_DEPTH 8
|
||||
#define MAX_PANEL 4
|
||||
#define MAX_BUFFER 64
|
||||
#define MAX_DEPTH 4
|
||||
#define WIN_WIDTH 800
|
||||
#define WIN_HEIGHT 600
|
||||
#define DTIME 16
|
||||
@ -29,38 +28,6 @@ typedef struct XFont XFont;
|
||||
typedef struct XSurface XSurface;
|
||||
typedef struct XWindow XWindow;
|
||||
|
||||
struct XFont {
|
||||
int ascent;
|
||||
int descent;
|
||||
int height;
|
||||
XFontSet set;
|
||||
XFontStruct *xfont;
|
||||
};
|
||||
|
||||
struct XSurface {
|
||||
GC gc;
|
||||
Display *dpy;
|
||||
int screen;
|
||||
Window root;
|
||||
Drawable drawable;
|
||||
unsigned int w, h;
|
||||
};
|
||||
|
||||
struct XWindow {
|
||||
Display *dpy;
|
||||
Window root;
|
||||
Visual *vis;
|
||||
Colormap cmap;
|
||||
XWindowAttributes attr;
|
||||
XSetWindowAttributes swa;
|
||||
Window win;
|
||||
GC gc;
|
||||
int screen;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
XSurface surface;
|
||||
};
|
||||
|
||||
struct demo {
|
||||
gui_char in_buf[MAX_BUFFER];
|
||||
gui_size in_len;
|
||||
@ -78,6 +45,38 @@ struct demo {
|
||||
gui_size current;
|
||||
};
|
||||
|
||||
struct XFont {
|
||||
int ascent;
|
||||
int descent;
|
||||
int height;
|
||||
XFontSet set;
|
||||
XFontStruct *xfont;
|
||||
};
|
||||
|
||||
struct XSurface {
|
||||
GC gc;
|
||||
Display *dpy;
|
||||
int screen;
|
||||
Window root;
|
||||
Drawable drawable;
|
||||
unsigned int w, h;
|
||||
gui_size clip_depth;
|
||||
struct gui_rect clips[MAX_DEPTH];
|
||||
};
|
||||
|
||||
struct XWindow {
|
||||
Display *dpy;
|
||||
Window root;
|
||||
Visual *vis;
|
||||
Colormap cmap;
|
||||
XWindowAttributes attr;
|
||||
XSetWindowAttributes swa;
|
||||
Window win;
|
||||
int screen;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
};
|
||||
|
||||
static void
|
||||
die(const char *fmt, ...)
|
||||
{
|
||||
@ -115,122 +114,6 @@ sleep_for(long t)
|
||||
while(-1 == nanosleep(&req, &req));
|
||||
}
|
||||
|
||||
static XSurface*
|
||||
surface_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
|
||||
{
|
||||
XSurface *surface = xcalloc(1, sizeof(XSurface));
|
||||
surface->w = w;
|
||||
surface->h = h;
|
||||
surface->dpy = dpy;
|
||||
surface->screen = screen;
|
||||
surface->root = root;
|
||||
surface->gc = XCreateGC(dpy, root, 0, NULL);
|
||||
XSetLineAttributes(dpy, surface->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
surface->drawable = XCreatePixmap(dpy, root, w, h, (unsigned int)DefaultDepth(dpy, screen));
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
surface_resize(XSurface *surf, unsigned int w, unsigned int h) {
|
||||
if(!surf) return;
|
||||
surf->w = w; surf->h = h;
|
||||
if(surf->drawable) XFreePixmap(surf->dpy, surf->drawable);
|
||||
surf->drawable = XCreatePixmap(surf->dpy, surf->root, w, h,
|
||||
(unsigned int)DefaultDepth(surf->dpy, surf->screen));
|
||||
}
|
||||
|
||||
static void
|
||||
surface_scissor(XSurface *surf, int x, int y, unsigned int w, unsigned int h)
|
||||
{
|
||||
XRectangle clip_rect;
|
||||
clip_rect.x = (short)x;
|
||||
clip_rect.y = (short)y;
|
||||
clip_rect.width = (unsigned short)w;
|
||||
clip_rect.height = (unsigned short)h;
|
||||
clip_rect.width = (unsigned short)MIN(surf->w, clip_rect.width);
|
||||
clip_rect.height = (unsigned short)MIN(surf->h, clip_rect.height);
|
||||
XSetClipRectangles(surf->dpy, surf->gc, 0, 0, &clip_rect, 1, Unsorted);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_line(XSurface *surf, int x0, int y0, int x1, int y1, unsigned long c)
|
||||
{
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, x0, y0, x1, y1);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_rect(XSurface *surf, int x, int y, unsigned int w, unsigned int h, unsigned long c)
|
||||
{
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_triangle(XSurface *surf, int x0, int y0, int x1, int y1, int x2, int y2,
|
||||
unsigned long c)
|
||||
{
|
||||
XPoint pnts[3];
|
||||
pnts[0].x = (short)x0;
|
||||
pnts[0].y = (short)y0;
|
||||
pnts[1].x = (short)x1;
|
||||
pnts[1].y = (short)y1;
|
||||
pnts[2].x = (short)x2;
|
||||
pnts[2].y = (short)y2;
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 3, Convex, CoordModeOrigin);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_circle(XSurface *surf, int x, int y, unsigned int radius, unsigned long c)
|
||||
{
|
||||
unsigned int d = radius * 2;
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
x -= (int)radius;
|
||||
y -= (int)radius;
|
||||
XFillArc(surf->dpy, surf->drawable, surf->gc, x, y, d, d, 0, 360 * 64);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_text(XSurface *surf, XFont *font, int x, int y, unsigned int w, unsigned int h,
|
||||
const char *text, unsigned int len, unsigned long bg, unsigned long fg)
|
||||
{
|
||||
int i, tx, ty, th, olen;
|
||||
XSetForeground(surf->dpy, surf->gc, bg);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);
|
||||
if(!text || !font || !len) return;
|
||||
|
||||
th = font->ascent + font->descent;
|
||||
ty = y + ((int)h / 2) - (th / 2) + font->ascent;
|
||||
tx = x;/* + ((int)h / 2);*/
|
||||
XSetForeground(surf->dpy, surf->gc, fg);
|
||||
if(font->set)
|
||||
XmbDrawString(surf->dpy, surf->drawable, font->set, surf->gc, tx, ty, text, (int)len);
|
||||
else
|
||||
XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, text, (int)len);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_clear(XSurface *surf, unsigned long color)
|
||||
{
|
||||
XSetForeground(surf->dpy, surf->gc, color);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, 0, 0, surf->w, surf->h);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_blit(Drawable target, XSurface *surf, unsigned int width, unsigned int height)
|
||||
{
|
||||
XCopyArea(surf->dpy, surf->drawable, target, surf->gc, 0, 0, width, height, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_del(XSurface *surf)
|
||||
{
|
||||
XFreePixmap(surf->dpy, surf->drawable);
|
||||
XFreeGC(surf->dpy, surf->gc);
|
||||
free(surf);
|
||||
}
|
||||
|
||||
static XFont*
|
||||
font_create(Display *dpy, const char *name)
|
||||
{
|
||||
@ -295,6 +178,153 @@ font_del(Display *dpy, XFont *font)
|
||||
free(font);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
color_from_byte(struct gui_color col)
|
||||
{
|
||||
unsigned long res = 0;
|
||||
res |= (unsigned long)col.r << 16;
|
||||
res |= (unsigned long)col.g << 8;
|
||||
res |= (unsigned long)col.b << 0;
|
||||
return (res);
|
||||
}
|
||||
|
||||
static XSurface*
|
||||
surface_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
|
||||
{
|
||||
XSurface *surface = xcalloc(1, sizeof(XSurface));
|
||||
surface->w = w;
|
||||
surface->h = h;
|
||||
surface->dpy = dpy;
|
||||
surface->screen = screen;
|
||||
surface->root = root;
|
||||
surface->gc = XCreateGC(dpy, root, 0, NULL);
|
||||
XSetLineAttributes(dpy, surface->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
surface->drawable = XCreatePixmap(dpy, root, w, h, (unsigned int)DefaultDepth(dpy, screen));
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
surface_resize(XSurface *surf, unsigned int w, unsigned int h) {
|
||||
if(!surf) return;
|
||||
if (surf->w == w && surf->h == h) return;
|
||||
surf->w = w; surf->h = h;
|
||||
if(surf->drawable) XFreePixmap(surf->dpy, surf->drawable);
|
||||
surf->drawable = XCreatePixmap(surf->dpy, surf->root, w, h,
|
||||
(unsigned int)DefaultDepth(surf->dpy, surf->screen));
|
||||
}
|
||||
|
||||
static void
|
||||
unify(struct gui_rect *clip, const struct gui_rect *a, const struct gui_rect *b)
|
||||
{
|
||||
clip->x = MAX(a->x, b->x);
|
||||
clip->y = MAX(a->y, b->y);
|
||||
clip->w = MIN(a->x + a->w, b->x + b->w) - clip->x;
|
||||
clip->h = MIN(a->y + a->h, b->y + b->h) - clip->y;
|
||||
}
|
||||
|
||||
static void
|
||||
surface_scissor(void *handle, gui_float x, gui_float y, gui_float w, gui_float h)
|
||||
{
|
||||
XSurface *surf = handle;
|
||||
XRectangle clip_rect;
|
||||
clip_rect.x = (short)x;
|
||||
clip_rect.y = (short)y;
|
||||
clip_rect.width = (unsigned short)w;
|
||||
clip_rect.height = (unsigned short)h;
|
||||
clip_rect.width = (unsigned short)MIN(surf->w, clip_rect.width);
|
||||
clip_rect.height = (unsigned short)MIN(surf->h, clip_rect.height);
|
||||
XSetClipRectangles(surf->dpy, surf->gc, 0, 0, &clip_rect, 1, Unsorted);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_line(void *handle, gui_float x0, gui_float y0, gui_float x1, gui_float y1, struct gui_color col)
|
||||
{
|
||||
XSurface *surf = handle;
|
||||
unsigned long c = color_from_byte(col);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, (int)x0, (int)y0, (int)x1, (int)y1);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_rect(void *handle, gui_float x, gui_float y, gui_float w, gui_float h, struct gui_color col)
|
||||
{
|
||||
XSurface *surf = handle;
|
||||
unsigned long c = color_from_byte(col);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, (unsigned)w, (unsigned)h);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_triangle(void *handle, const struct gui_vec2 *src, struct gui_color col)
|
||||
{
|
||||
XPoint pnts[3];
|
||||
XSurface *surf = handle;
|
||||
unsigned long c = color_from_byte(col);
|
||||
pnts[0].x = (short)src[0].x;
|
||||
pnts[0].y = (short)src[0].y;
|
||||
pnts[1].x = (short)src[1].x;
|
||||
pnts[1].y = (short)src[1].y;
|
||||
pnts[2].x = (short)src[2].x;
|
||||
pnts[2].y = (short)src[2].y;
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 3, Convex, CoordModeOrigin);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_circle(void *handle, gui_float x, gui_float y, gui_float w, gui_float h, struct gui_color col)
|
||||
{
|
||||
XSurface *surf = handle;
|
||||
unsigned long c = color_from_byte(col);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XFillArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y,
|
||||
(unsigned)w, (unsigned)h, 0, 360 * 64);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_text(void *handle, gui_float x, gui_float y, gui_float w, gui_float h, const gui_char *text,
|
||||
gui_size len, const struct gui_font *f, struct gui_color cbg, struct gui_color cfg)
|
||||
{
|
||||
int i, tx, ty, th, olen;
|
||||
XSurface *surf = handle;
|
||||
XFont *font = f->userdata;
|
||||
unsigned long bg = color_from_byte(cbg);
|
||||
unsigned long fg = color_from_byte(cfg);
|
||||
|
||||
XSetForeground(surf->dpy, surf->gc, bg);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, (unsigned)w, (unsigned)h);
|
||||
if(!text || !font || !len) return;
|
||||
|
||||
tx = (int)x;
|
||||
th = font->ascent + font->descent;
|
||||
ty = (int)y + ((int)h / 2) - (th / 2) + font->ascent;
|
||||
XSetForeground(surf->dpy, surf->gc, fg);
|
||||
if(font->set)
|
||||
XmbDrawString(surf->dpy, surf->drawable, font->set, surf->gc, tx, ty, (const char*)text, (int)len);
|
||||
else
|
||||
XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, (const char*)text, (int)len);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_clear(XSurface *surf, unsigned long color)
|
||||
{
|
||||
XSetForeground(surf->dpy, surf->gc, color);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, 0, 0, surf->w, surf->h);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_blit(Drawable target, XSurface *surf, unsigned int width, unsigned int height)
|
||||
{
|
||||
XCopyArea(surf->dpy, surf->drawable, target, surf->gc, 0, 0, width, height, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_del(XSurface *surf)
|
||||
{
|
||||
XFreePixmap(surf->dpy, surf->drawable);
|
||||
XFreeGC(surf->dpy, surf->gc);
|
||||
free(surf);
|
||||
}
|
||||
|
||||
static void
|
||||
key(struct XWindow *xw, struct gui_input *in, XEvent *evt, gui_bool down)
|
||||
{
|
||||
@ -329,7 +359,7 @@ motion(struct gui_input *in, XEvent *evt)
|
||||
}
|
||||
|
||||
static void
|
||||
button(struct gui_input *in, XEvent *evt, gui_bool down)
|
||||
btn(struct gui_input *in, XEvent *evt, gui_bool down)
|
||||
{
|
||||
const gui_int x = evt->xbutton.x;
|
||||
const gui_int y = evt->xbutton.y;
|
||||
@ -346,103 +376,24 @@ resize(struct XWindow *xw, XSurface *surf)
|
||||
surface_resize(surf, xw->width, xw->height);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
color_from_byte(struct gui_color col)
|
||||
{
|
||||
unsigned long res = 0;
|
||||
res |= (unsigned long)col.r << 16;
|
||||
res |= (unsigned long)col.g << 8;
|
||||
res |= (unsigned long)col.b << 0;
|
||||
return (res);
|
||||
}
|
||||
|
||||
static void
|
||||
execute(XSurface *surf, const struct gui_command_list *list)
|
||||
{
|
||||
const struct gui_command *iter = NULL;
|
||||
if (!list->count) return;
|
||||
iter = list->begin;
|
||||
while (iter != list->end) {
|
||||
switch (iter->type) {
|
||||
case GUI_COMMAND_NOP: break;
|
||||
case GUI_COMMAND_CLIP: {
|
||||
const struct gui_command_clip *clip = (const struct gui_command_clip*)iter;
|
||||
surface_scissor(surf, (int)clip->x, (int)clip->y,
|
||||
(unsigned int)clip->w, (unsigned int)clip->h);
|
||||
} break;
|
||||
case GUI_COMMAND_LINE: {
|
||||
const struct gui_command_line *line = (const struct gui_command_line*)iter;
|
||||
const unsigned long color = color_from_byte(line->color);
|
||||
surface_draw_line(surf, (int)line->from.x, (int)line->from.y,
|
||||
(int)line->to.x, (int)line->to.y, color);
|
||||
} break;
|
||||
case GUI_COMMAND_RECT: {
|
||||
const struct gui_command_rect *rect = (const struct gui_command_rect*)iter;
|
||||
const unsigned long color = color_from_byte(rect->color);
|
||||
surface_draw_rect(surf, (int)rect->x, (int)rect->y,
|
||||
(unsigned int)rect->w, (unsigned int)rect->h, color);
|
||||
} break;
|
||||
case GUI_COMMAND_CIRCLE: {
|
||||
const struct gui_command_circle *circle = (const struct gui_command_circle*)iter;
|
||||
const unsigned long color = color_from_byte(circle->color);
|
||||
surface_draw_circle(surf, (int)circle->x, (int)circle->y,
|
||||
(unsigned int)circle->radius, color);
|
||||
} break;
|
||||
case GUI_COMMAND_BITMAP: {
|
||||
const struct gui_command_bitmap *bitmap = (const struct gui_command_bitmap*)iter;
|
||||
} break;
|
||||
case GUI_COMMAND_TRIANGLE: {
|
||||
const struct gui_command_triangle *triangle = (const struct gui_command_triangle*)iter;
|
||||
const unsigned long color = color_from_byte(triangle->color);
|
||||
surface_draw_triangle(surf, (int)triangle->pnt[0].x, (int)triangle->pnt[0].y,
|
||||
(int)triangle->pnt[1].x, (int)triangle->pnt[1].y, (int)triangle->pnt[2].x,
|
||||
(int)triangle->pnt[2].y, color);
|
||||
} break;
|
||||
case GUI_COMMAND_TEXT: {
|
||||
const struct gui_command_text *text = (const struct gui_command_text*)iter;
|
||||
const unsigned long bg = color_from_byte(text->background);
|
||||
const unsigned long fg = color_from_byte(text->foreground);
|
||||
surface_draw_text(surf, text->font, (int)text->x, (int)text->y,
|
||||
(unsigned int)text->w, (unsigned int)text->h,
|
||||
(const char*)text->string, (unsigned int)text->length, bg, fg);
|
||||
} break;
|
||||
case GUI_COMMAND_MAX: break;
|
||||
default: break;
|
||||
}
|
||||
iter = iter->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gui_draw(XSurface *surf, const struct gui_output *out)
|
||||
{
|
||||
gui_size i = 0;
|
||||
if (!out->list_size) return;
|
||||
for (i = 0; i < out->list_size; i++)
|
||||
execute(surf, out->list[i]);
|
||||
}
|
||||
|
||||
static gui_bool
|
||||
demo_panel(struct gui_context *ctx, struct gui_panel *panel, struct demo *demo)
|
||||
demo_panel(struct gui_panel *panel, struct demo *demo)
|
||||
{
|
||||
enum {HISTO, PLOT};
|
||||
const char *shelfs[] = {"Histogram", "Lines"};
|
||||
const gui_float values[] = {8.0f, 15.0f, 20.0f, 12.0f, 30.0f};
|
||||
const char *items[] = {"Fist", "Pistol", "Shotgun", "Railgun", "BFG"};
|
||||
gui_bool running;
|
||||
|
||||
running = gui_begin_panel(ctx, panel, "Demo",
|
||||
GUI_PANEL_CLOSEABLE|GUI_PANEL_MINIMIZABLE|GUI_PANEL_SCALEABLE|
|
||||
GUI_PANEL_MOVEABLE|GUI_PANEL_BORDER);
|
||||
|
||||
/* Tabs */
|
||||
gui_panel_layout(panel, 100, 1);
|
||||
gui_panel_tab_begin(panel, &demo->tab, "Difficulty");
|
||||
gui_panel_layout(&demo->tab, 30, 1);
|
||||
gui_panel_layout(&demo->tab, 30, 3);
|
||||
if (gui_panel_option(&demo->tab, "easy", demo->option == 0)) demo->option = 0;
|
||||
if (gui_panel_option(&demo->tab, "hard", demo->option == 1)) demo->option = 1;
|
||||
if (gui_panel_option(&demo->tab, "normal", demo->option == 2)) demo->option = 2;
|
||||
if (gui_panel_option(&demo->tab, "godlike", demo->option == 3)) demo->option = 3;
|
||||
if (gui_panel_option(&demo->tab, "normal", demo->option == 1)) demo->option = 1;
|
||||
if (gui_panel_option(&demo->tab, "hard", demo->option == 2)) demo->option = 2;
|
||||
if (gui_panel_option(&demo->tab, "hell", demo->option == 3)) demo->option = 3;
|
||||
if (gui_panel_option(&demo->tab, "doom", demo->option == 4)) demo->option = 4;
|
||||
if (gui_panel_option(&demo->tab, "godlike", demo->option == 5)) demo->option = 5;
|
||||
gui_panel_tab_end(panel, &demo->tab);
|
||||
|
||||
/* Shelf */
|
||||
@ -466,23 +417,7 @@ demo_panel(struct gui_context *ctx, struct gui_panel *panel, struct demo *demo)
|
||||
demo->prog = gui_panel_progress(&demo->group, demo->prog, 100, gui_true);
|
||||
demo->item_cur = gui_panel_selector(&demo->group, items, LEN(items), demo->item_cur);
|
||||
demo->spin_act = gui_panel_spinner(&demo->group, 0, &demo->spinner, 250, 10, demo->spin_act);
|
||||
demo->in_act = gui_panel_input(&demo->group, demo->in_buf, &demo->in_len,
|
||||
MAX_BUFFER, GUI_INPUT_DEFAULT, demo->in_act);
|
||||
gui_panel_group_end(panel, &demo->group);
|
||||
|
||||
gui_end_panel(ctx, panel, NULL);
|
||||
return running;
|
||||
}
|
||||
|
||||
static void
|
||||
message_panel(struct gui_context *ctx, struct gui_panel *panel)
|
||||
{
|
||||
gui_int ret = -1;
|
||||
gui_begin_panel(ctx, panel, "Error", GUI_PANEL_MOVEABLE|GUI_PANEL_BORDER);
|
||||
gui_panel_layout(panel, 30, 2);
|
||||
gui_panel_button_text(panel, "ok", GUI_BUTTON_DEFAULT);
|
||||
gui_panel_button_text(panel, "cancel", GUI_BUTTON_DEFAULT);
|
||||
gui_end_panel(ctx, panel, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
@ -491,23 +426,19 @@ main(int argc, char *argv[])
|
||||
long dt;
|
||||
long started;
|
||||
gui_bool running = gui_true;
|
||||
XWindow xw;
|
||||
|
||||
/* GUI */
|
||||
struct demo demo;
|
||||
gui_bool checked = gui_false;
|
||||
gui_float value = 5.0f;
|
||||
gui_size done = 20;
|
||||
struct gui_input in;
|
||||
struct gui_config config;
|
||||
struct gui_memory memory;
|
||||
struct gui_font font;
|
||||
struct gui_panel *panel;
|
||||
struct gui_panel *message;
|
||||
struct gui_context *ctx;
|
||||
struct gui_output output;
|
||||
struct gui_canvas canvas;
|
||||
struct gui_panel panel;
|
||||
struct demo demo;
|
||||
|
||||
/* Window */
|
||||
XWindow xw;
|
||||
XSurface *surf;
|
||||
XFont *xfont;
|
||||
|
||||
UNUSED(argc); UNUSED(argv);
|
||||
memset(&xw, 0, sizeof xw);
|
||||
xw.dpy = XOpenDisplay(NULL);
|
||||
@ -527,22 +458,26 @@ main(int argc, char *argv[])
|
||||
XGetWindowAttributes(xw.dpy, xw.win, &xw.attr);
|
||||
xw.width = (unsigned int)xw.attr.width;
|
||||
xw.height = (unsigned int)xw.attr.height;
|
||||
xfont = font_create(xw.dpy, "fixed");
|
||||
surf = surface_create(xw.dpy, xw.screen, xw.win, xw.width, xw.height);
|
||||
|
||||
/* GUI */
|
||||
memory.size = MAX_MEMORY;
|
||||
memory.memory = calloc(1, memory.size);
|
||||
memory.max_depth = MAX_DEPTH;
|
||||
memory.max_panels = MAX_PANEL;
|
||||
ctx = gui_new(&memory, &in);
|
||||
|
||||
font.user = xfont;
|
||||
font.height = (gui_float)xfont->height;
|
||||
font.width = font_get_text_width;
|
||||
canvas.userdata = surface_create(xw.dpy, xw.screen, xw.win, xw.width, xw.height);
|
||||
canvas.width = xw.width;
|
||||
canvas.height = xw.height;
|
||||
canvas.scissor = surface_scissor;
|
||||
canvas.draw_line = surface_draw_line;
|
||||
canvas.draw_rect = surface_draw_rect;
|
||||
canvas.draw_circle = surface_draw_circle;
|
||||
canvas.draw_triangle = surface_draw_triangle;
|
||||
canvas.draw_text = surface_draw_text;
|
||||
canvas.font.userdata = font_create(xw.dpy, "fixed");
|
||||
canvas.font.height = (gui_float)((XFont*)canvas.font.userdata)->height;
|
||||
canvas.font.width = font_get_text_width;
|
||||
gui_default_config(&config);
|
||||
panel = gui_new_panel(ctx, 50, 50, 400, 300, &config, &font);
|
||||
message = gui_new_panel(ctx, 150, 150, 200, 100, &config, &font);
|
||||
memset(&in, 0, sizeof in);
|
||||
memset(&panel, 0, sizeof panel);
|
||||
panel.x = 50; panel.y = 50;
|
||||
/*panel.w = 420; panel.h = 300;*/
|
||||
panel.w = 420; panel.h = 200;
|
||||
|
||||
memset(&demo, 0, sizeof(demo));
|
||||
demo.tab.minimized = gui_true;
|
||||
@ -559,25 +494,24 @@ main(int argc, char *argv[])
|
||||
while (XCheckWindowEvent(xw.dpy, xw.win, xw.swa.event_mask, &evt)) {
|
||||
if (evt.type == KeyPress) key(&xw, &in, &evt, gui_true);
|
||||
else if (evt.type == KeyRelease) key(&xw, &in, &evt, gui_false);
|
||||
else if (evt.type == ButtonPress) button(&in, &evt, gui_true);
|
||||
else if (evt.type == ButtonRelease) button(&in, &evt, gui_false);
|
||||
else if (evt.type == ButtonPress) btn(&in, &evt, gui_true);
|
||||
else if (evt.type == ButtonRelease) btn(&in, &evt, gui_false);
|
||||
else if (evt.type == MotionNotify) motion(&in, &evt);
|
||||
else if (evt.type == Expose || evt.type == ConfigureNotify)
|
||||
resize(&xw, surf);
|
||||
resize(&xw, canvas.userdata);
|
||||
}
|
||||
gui_input_end(&in);
|
||||
|
||||
/* GUI */
|
||||
gui_begin(ctx, (gui_float)xw.width, (gui_float)xw.height);
|
||||
running = demo_panel(ctx, panel, &demo);
|
||||
message_panel(ctx, message);
|
||||
gui_end(ctx, &output, NULL);
|
||||
|
||||
/* Draw */
|
||||
XClearWindow(xw.dpy, xw.win);
|
||||
surface_clear(surf, 0x00646464);
|
||||
gui_draw(surf, &output);
|
||||
surface_blit(xw.win, surf, xw.width, xw.height);
|
||||
surface_clear(canvas.userdata, 0x002D2D2D);
|
||||
canvas.width = xw.width; canvas.height = xw.height;
|
||||
running = gui_panel_begin(&panel, "Demo", panel.x, panel.y, panel.w, panel.h,
|
||||
GUI_PANEL_CLOSEABLE|GUI_PANEL_MINIMIZABLE|GUI_PANEL_BORDER|
|
||||
GUI_PANEL_MOVEABLE|GUI_PANEL_SCALEABLE, &config, &canvas, &in);
|
||||
demo_panel(&panel, &demo);
|
||||
gui_panel_end(&panel);
|
||||
surface_blit(xw.win, canvas.userdata, xw.width, xw.height);
|
||||
XFlush(xw.dpy);
|
||||
|
||||
/* Timing */
|
||||
@ -586,9 +520,10 @@ main(int argc, char *argv[])
|
||||
sleep_for(DTIME - dt);
|
||||
}
|
||||
|
||||
free(memory.memory);
|
||||
font_del(xw.dpy, xfont);
|
||||
surface_del(surf);
|
||||
font_del(xw.dpy, canvas.font.userdata);
|
||||
surface_del(canvas.userdata);
|
||||
XUnmapWindow(xw.dpy, xw.win);
|
||||
XFreeColormap(xw.dpy, xw.cmap);
|
||||
XDestroyWindow(xw.dpy, xw.win);
|
||||
XCloseDisplay(xw.dpy);
|
||||
return 0;
|
||||
|
293
gui.h
293
gui.h
@ -42,13 +42,6 @@ typedef unsigned int gui_flag;
|
||||
typedef unsigned long gui_size;
|
||||
#endif
|
||||
|
||||
typedef struct gui_panel gui_tab;
|
||||
typedef struct gui_panel gui_group;
|
||||
typedef struct gui_panel gui_shelf;
|
||||
typedef gui_char gui_glyph[GUI_UTF_SIZE];
|
||||
typedef union {void* handle; gui_uint id;} gui_texture;
|
||||
typedef gui_size(*gui_text_width_f)(void*,const gui_char*, gui_size);
|
||||
|
||||
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;};
|
||||
@ -56,9 +49,24 @@ struct gui_colorf {gui_float r,g,b,a;};
|
||||
struct gui_vec2 {gui_float x,y;};
|
||||
struct gui_rect {gui_float x,y,w,h;};
|
||||
struct gui_key {gui_bool down, clicked;};
|
||||
struct gui_font;
|
||||
|
||||
typedef struct gui_panel gui_tab;
|
||||
typedef struct gui_panel gui_group;
|
||||
typedef struct gui_panel gui_shelf;
|
||||
typedef gui_char gui_glyph[GUI_UTF_SIZE];
|
||||
typedef union {void* handle; gui_uint id;} gui_texture;
|
||||
typedef gui_size(*gui_text_width_f)(void*,const gui_char*, gui_size);
|
||||
typedef void(*gui_scissor)(void*, gui_float, gui_float, gui_float, gui_float);
|
||||
typedef void(*gui_draw_line)(void*, gui_float, gui_float, gui_float, gui_float, struct gui_color);
|
||||
typedef void(*gui_draw_rect)(void*, gui_float, gui_float, gui_float, gui_float, struct gui_color);
|
||||
typedef void(*gui_draw_circle)(void*, gui_float, gui_float, gui_float, gui_float, struct gui_color);
|
||||
typedef void(*gui_draw_triangle)(void*, const struct gui_vec2*, struct gui_color);
|
||||
typedef void(*gui_draw_text)(void*, gui_float, gui_float, gui_float, gui_float,
|
||||
const gui_char*, gui_size, const struct gui_font*,
|
||||
struct gui_color, struct gui_color);
|
||||
struct gui_font {
|
||||
void *user;
|
||||
void *userdata;
|
||||
gui_float height;
|
||||
gui_text_width_f width;
|
||||
};
|
||||
@ -86,105 +94,17 @@ struct gui_input {
|
||||
struct gui_vec2 mouse_clicked_pos;
|
||||
};
|
||||
|
||||
struct gui_memory {
|
||||
void *memory;
|
||||
gui_size size;
|
||||
gui_size max_panels;
|
||||
gui_size max_depth;
|
||||
};
|
||||
|
||||
struct gui_memory_status {
|
||||
gui_size allocated;
|
||||
gui_size needed;
|
||||
};
|
||||
|
||||
enum gui_command_type {
|
||||
GUI_COMMAND_NOP = 0,
|
||||
GUI_COMMAND_CLIP,
|
||||
GUI_COMMAND_LINE,
|
||||
GUI_COMMAND_RECT,
|
||||
GUI_COMMAND_CIRCLE,
|
||||
GUI_COMMAND_BITMAP,
|
||||
GUI_COMMAND_TRIANGLE,
|
||||
GUI_COMMAND_TEXT,
|
||||
GUI_COMMAND_MAX
|
||||
};
|
||||
|
||||
struct gui_command {
|
||||
enum gui_command_type type;
|
||||
struct gui_command *next;
|
||||
};
|
||||
|
||||
struct gui_command_clip {
|
||||
struct gui_command header;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
};
|
||||
|
||||
struct gui_command_line {
|
||||
struct gui_command header;
|
||||
struct gui_color color;
|
||||
struct gui_vec2 from;
|
||||
struct gui_vec2 to;
|
||||
};
|
||||
|
||||
struct gui_command_rect {
|
||||
struct gui_command header;
|
||||
struct gui_color color;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
};
|
||||
|
||||
struct gui_command_circle {
|
||||
struct gui_command header;
|
||||
struct gui_color color;
|
||||
gui_float radius;
|
||||
gui_float x, y;
|
||||
};
|
||||
|
||||
struct gui_command_bitmap {
|
||||
struct gui_command header;
|
||||
gui_texture texture;
|
||||
struct gui_rect src;
|
||||
struct gui_rect dst;
|
||||
};
|
||||
|
||||
struct gui_command_triangle {
|
||||
struct gui_command header;
|
||||
struct gui_vec2 pnt[3];
|
||||
struct gui_color color;
|
||||
};
|
||||
|
||||
struct gui_command_text {
|
||||
struct gui_command header;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
void *font;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_size length;
|
||||
gui_byte string[1];
|
||||
};
|
||||
|
||||
struct gui_command_list{
|
||||
struct gui_command *begin;
|
||||
struct gui_command *end;
|
||||
gui_size count;
|
||||
gui_size capacity;
|
||||
gui_size needed;
|
||||
gui_size size;
|
||||
};
|
||||
|
||||
struct gui_command_buffer {
|
||||
struct gui_command_list cmds;
|
||||
struct gui_rect *clips;
|
||||
gui_size clip_capacity;
|
||||
gui_size clip_size;
|
||||
};
|
||||
|
||||
struct gui_output {
|
||||
struct gui_command_list **list;
|
||||
gui_size list_size;
|
||||
struct gui_canvas {
|
||||
void *userdata;
|
||||
gui_size width;
|
||||
gui_size height;
|
||||
struct gui_font font;
|
||||
gui_scissor scissor;
|
||||
gui_draw_line draw_line;
|
||||
gui_draw_rect draw_rect;
|
||||
gui_draw_circle draw_circle;
|
||||
gui_draw_triangle draw_triangle;
|
||||
gui_draw_text draw_text;
|
||||
};
|
||||
|
||||
enum gui_text_align {
|
||||
@ -194,23 +114,14 @@ enum gui_text_align {
|
||||
};
|
||||
|
||||
struct gui_text {
|
||||
void *font;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x, pad_y;
|
||||
const char *string;
|
||||
gui_size length;
|
||||
struct gui_vec2 padding;
|
||||
enum gui_text_align align;
|
||||
struct gui_color foreground;
|
||||
struct gui_color background;
|
||||
};
|
||||
|
||||
struct gui_image {
|
||||
struct gui_rect src;
|
||||
struct gui_rect dst;
|
||||
gui_float pad_x, pad_y;
|
||||
struct gui_color color;
|
||||
gui_texture texture;
|
||||
struct gui_vec2 padding;
|
||||
struct gui_color background;
|
||||
};
|
||||
|
||||
@ -220,11 +131,8 @@ enum gui_button_behavior {
|
||||
};
|
||||
|
||||
struct gui_button {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x, pad_y;
|
||||
gui_float border;
|
||||
enum gui_button_behavior behavior;
|
||||
struct gui_vec2 padding;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
struct gui_color content;
|
||||
@ -238,45 +146,19 @@ enum gui_toggle_type {
|
||||
};
|
||||
|
||||
struct gui_toggle {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x, pad_y;
|
||||
const gui_char *text;
|
||||
gui_size length;
|
||||
enum gui_toggle_type type;
|
||||
struct gui_vec2 padding;
|
||||
struct gui_color font;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
};
|
||||
|
||||
struct gui_slider {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x, pad_y;
|
||||
gui_float min, max;
|
||||
gui_float value;
|
||||
gui_float step;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
};
|
||||
|
||||
struct gui_progress {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x, pad_y;
|
||||
gui_size current;
|
||||
gui_size max;
|
||||
gui_bool modifyable;
|
||||
struct gui_vec2 padding;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
};
|
||||
|
||||
struct gui_scroll {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float offset;
|
||||
gui_float target;
|
||||
gui_float step;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
struct gui_color border;
|
||||
@ -292,37 +174,23 @@ enum gui_input_filter {
|
||||
};
|
||||
|
||||
struct gui_input_field {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x, pad_y;
|
||||
gui_size max;
|
||||
gui_bool active;
|
||||
struct gui_vec2 padding;
|
||||
gui_bool show_cursor;
|
||||
enum gui_input_filter filter;
|
||||
gui_bool password;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
struct gui_color font;
|
||||
};
|
||||
|
||||
struct gui_plot {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x;
|
||||
gui_float pad_y;
|
||||
gui_size value_count;
|
||||
const gui_float *values;
|
||||
struct gui_vec2 padding;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
struct gui_color highlight;
|
||||
};
|
||||
|
||||
struct gui_histo {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x, pad_y;
|
||||
gui_size value_count;
|
||||
const gui_float *values;
|
||||
struct gui_vec2 padding;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
struct gui_color negative;
|
||||
@ -393,6 +261,7 @@ enum gui_panel_flags {
|
||||
struct gui_panel {
|
||||
gui_flags flags;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float at_y;
|
||||
gui_float width, height;
|
||||
gui_size index;
|
||||
@ -401,10 +270,10 @@ struct gui_panel {
|
||||
gui_size row_columns;
|
||||
gui_float offset;
|
||||
gui_bool minimized;
|
||||
struct gui_command_buffer *out;
|
||||
struct gui_font font;
|
||||
struct gui_rect clip;
|
||||
const struct gui_input *in;
|
||||
const struct gui_config *config;
|
||||
const struct gui_canvas *canvas;
|
||||
};
|
||||
|
||||
/* Input */
|
||||
@ -415,46 +284,43 @@ void gui_input_button(struct gui_input*, gui_int x, gui_int y, gui_bool down);
|
||||
void gui_input_char(struct gui_input*, const gui_glyph);
|
||||
void gui_input_end(struct gui_input*);
|
||||
|
||||
/* Output */
|
||||
void gui_output_begin(struct gui_command_buffer*, const struct gui_memory*);
|
||||
void gui_output_end(struct gui_command_buffer*, struct gui_command_list*,
|
||||
struct gui_memory_status*);
|
||||
|
||||
/* Widgets */
|
||||
void gui_widget_text(struct gui_command_buffer*, const struct gui_text*,
|
||||
const struct gui_font*);
|
||||
void gui_widget_image(struct gui_command_buffer*, const struct gui_image*);
|
||||
gui_bool gui_widget_button_text(struct gui_command_buffer*, const struct gui_button*,
|
||||
const char *text, const struct gui_font*, const struct gui_input*);
|
||||
gui_bool gui_widget_button_triangle(struct gui_command_buffer*, struct gui_button*,
|
||||
enum gui_heading, const struct gui_input*);
|
||||
gui_bool gui_widget_button_icon(struct gui_command_buffer*, struct gui_button*,
|
||||
gui_texture, const struct gui_rect *source, const struct gui_input*);
|
||||
gui_bool gui_widget_toggle(struct gui_command_buffer*, const struct gui_toggle*,
|
||||
gui_bool active, const struct gui_font*, const struct gui_input*);
|
||||
gui_float gui_widget_slider(struct gui_command_buffer*, const struct gui_slider*,
|
||||
const struct gui_input*);
|
||||
gui_size gui_widget_progress(struct gui_command_buffer*, const struct gui_progress*,
|
||||
const struct gui_input*);
|
||||
gui_bool gui_widget_input(struct gui_command_buffer*, gui_char*, gui_size*,
|
||||
const struct gui_input_field*, const struct gui_font*,
|
||||
const struct gui_input*);
|
||||
gui_float gui_widget_scroll(struct gui_command_buffer*, const struct gui_scroll*,
|
||||
const struct gui_input*);
|
||||
gui_int gui_widget_histo(struct gui_command_buffer*, const struct gui_histo*,
|
||||
const struct gui_input*);
|
||||
gui_int gui_widget_plot(struct gui_command_buffer*, const struct gui_plot*,
|
||||
const struct gui_input*);
|
||||
void gui_text(const struct gui_canvas*, gui_float x, gui_float y, gui_float w, gui_float h,
|
||||
const struct gui_text*, const char *text, gui_size len);
|
||||
gui_bool gui_button_text(const struct gui_canvas*, gui_float x, gui_float y,
|
||||
gui_float w, gui_float h, const struct gui_button*, const char*,
|
||||
enum gui_button_behavior, const struct gui_input*);
|
||||
gui_bool gui_button_triangle(const struct gui_canvas*, gui_float x, gui_float y,
|
||||
gui_float w, gui_float h, const struct gui_button*, enum gui_heading,
|
||||
enum gui_button_behavior, const struct gui_input*);
|
||||
gui_bool gui_toggle(const struct gui_canvas*, gui_float x, gui_float y, gui_float w,
|
||||
gui_float h, gui_bool, const char*, const struct gui_toggle*,
|
||||
enum gui_toggle_type, const struct gui_input*);
|
||||
gui_float gui_slider(const struct gui_canvas*, gui_float x, gui_float y, gui_float w,
|
||||
gui_float h, gui_float min, gui_float val, gui_float max, gui_float step,
|
||||
const struct gui_slider*, const struct gui_input*);
|
||||
gui_size gui_progress(const struct gui_canvas*, gui_float x, gui_float y, gui_float w,
|
||||
gui_float h, gui_size value, gui_size max, gui_bool modifyable,
|
||||
const struct gui_slider*, const struct gui_input*);
|
||||
gui_size gui_input(const struct gui_canvas*, gui_float x, gui_float y, gui_float w,
|
||||
gui_float h, gui_char*, gui_size, gui_size max, gui_bool*,
|
||||
const struct gui_input_field*, const struct gui_input*);
|
||||
gui_int gui_histo(const struct gui_canvas*, gui_float x, gui_float y, gui_float w,
|
||||
gui_float h, const gui_float*, gui_size,
|
||||
const struct gui_histo*, const struct gui_input*);
|
||||
gui_int gui_plot(const struct gui_canvas*, gui_float x, gui_float y, gui_float w,
|
||||
gui_float h, const gui_float*, gui_size,
|
||||
const struct gui_plot*, const struct gui_input*);
|
||||
gui_float gui_scroll(const struct gui_canvas*, gui_float x, gui_float y,
|
||||
gui_float w, gui_float h, gui_float offset, gui_float target,
|
||||
gui_float step, const struct gui_scroll*, const struct gui_input*);
|
||||
|
||||
/* Panel */
|
||||
void gui_default_config(struct gui_config*);
|
||||
void gui_panel_show(struct gui_panel*);
|
||||
void gui_panel_hide(struct gui_panel*);
|
||||
void gui_panel_init(struct gui_panel*, const struct gui_config*, const struct gui_font*);
|
||||
gui_bool gui_panel_is_hidden(const struct gui_panel*);
|
||||
gui_bool gui_panel_begin(struct gui_panel*, struct gui_command_buffer*,
|
||||
const struct gui_input*, const char*,
|
||||
gui_float x, gui_float y, gui_float w, gui_float h, gui_flags);
|
||||
gui_bool gui_panel_begin(struct gui_panel*, const char*, gui_float x, gui_float y,
|
||||
gui_float w, gui_float h, gui_flags, const struct gui_config*,
|
||||
const struct gui_canvas*, const struct gui_input*);
|
||||
void gui_panel_end(struct gui_panel*);
|
||||
void gui_panel_layout(struct gui_panel*, gui_float height, gui_size cols);
|
||||
void gui_panel_seperator(struct gui_panel*, gui_size cols);
|
||||
@ -465,14 +331,12 @@ gui_bool gui_panel_button_text(struct gui_panel*, const char*, enum gui_button_b
|
||||
gui_bool gui_panel_button_color(struct gui_panel*, const struct gui_color, enum gui_button_behavior);
|
||||
gui_bool gui_panel_button_triangle(struct gui_panel*, enum gui_heading, enum gui_button_behavior);
|
||||
gui_bool gui_panel_button_toggle(struct gui_panel*, const char*, gui_bool value);
|
||||
gui_bool gui_panel_button_icon(struct gui_panel*, gui_texture, const struct gui_rect*,
|
||||
enum gui_button_behavior);
|
||||
gui_float gui_panel_slider(struct gui_panel*, gui_float min, gui_float val,
|
||||
gui_float max, gui_float step);
|
||||
gui_size gui_panel_progress(struct gui_panel*, gui_size cur, gui_size max,
|
||||
gui_bool modifyable);
|
||||
gui_bool gui_panel_input(struct gui_panel*, gui_char *buffer, gui_size *len,
|
||||
gui_size max, enum gui_input_filter, gui_bool active);
|
||||
gui_size gui_panel_input(struct gui_panel*, gui_char *buffer, gui_size len,
|
||||
gui_size max, gui_bool *active, enum gui_input_filter);
|
||||
gui_bool gui_panel_spinner(struct gui_panel*, gui_int min, gui_int *value,
|
||||
gui_int max, gui_int step, gui_bool active);
|
||||
gui_size gui_panel_selector(struct gui_panel*, const char *items[],
|
||||
@ -487,19 +351,6 @@ gui_size gui_panel_shelf_begin(gui_shelf*, gui_shelf *shelf, const char *tabs[],
|
||||
gui_size size, gui_size active);
|
||||
void gui_panel_shelf_end(struct gui_panel*, gui_shelf *shelf);
|
||||
|
||||
/* Context */
|
||||
struct gui_context;
|
||||
struct gui_context *gui_new(const struct gui_memory*, const struct gui_input*);
|
||||
void gui_begin(struct gui_context*, gui_float width, gui_float height);
|
||||
void gui_end(struct gui_context*, struct gui_output*, struct gui_memory_status*);
|
||||
struct gui_panel *gui_new_panel(struct gui_context*, gui_float x, gui_float y, gui_float w,
|
||||
gui_float h, const struct gui_config* , const struct gui_font*);
|
||||
void gui_del_panel(struct gui_context*, struct gui_panel*);
|
||||
struct gui_vec2 gui_get_panel_position(const struct gui_context*, const struct gui_panel*);
|
||||
struct gui_vec2 gui_get_panel_size(const struct gui_context*, const struct gui_panel*);
|
||||
gui_bool gui_begin_panel(struct gui_context*, struct gui_panel*, const char *title, gui_flags flags);
|
||||
void gui_end_panel(struct gui_context*, struct gui_panel*, struct gui_memory_status*);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user