fixed some stuff + created extensive demo
This commit is contained in:
parent
5f9b1aef0f
commit
24380a2dcf
64
Readme.md
64
Readme.md
@ -18,48 +18,12 @@ possible with fast streamlined development speed in mind.
|
|||||||
- Configurable
|
- Configurable
|
||||||
- UTF-8 support
|
- UTF-8 support
|
||||||
|
|
||||||
## Functionality
|
|
||||||
+ Label
|
|
||||||
+ Buttons
|
|
||||||
+ Slider
|
|
||||||
+ Progressbar
|
|
||||||
+ Checkbox
|
|
||||||
+ Radiobutton
|
|
||||||
+ Input
|
|
||||||
+ Shell
|
|
||||||
+ Spinner
|
|
||||||
+ Selector
|
|
||||||
+ Linegraph
|
|
||||||
+ Histogram
|
|
||||||
+ Table
|
|
||||||
+ Panel
|
|
||||||
+ Tab
|
|
||||||
+ Group
|
|
||||||
+ Shelf
|
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
- Does NOT provide os window/input management
|
- Does NOT provide os window/input management
|
||||||
- Does NOT provide a renderer backend
|
- Does NOT provide a renderer backend
|
||||||
- Does NOT implement a font library
|
- Does NOT implement a font library
|
||||||
Summary: It is only responsible for the actual user interface
|
Summary: It is only responsible for the actual user interface
|
||||||
|
|
||||||
## IMGUIs
|
|
||||||
Immediate mode in contrast to classical retained mode GUIs store as little state as possible
|
|
||||||
by using procedural function calls as "widgets" instead of storing objects.
|
|
||||||
Each "widget" function call takes hereby all its necessary data and immediately returns
|
|
||||||
the through the user modified state back to the caller. Immediate mode graphical
|
|
||||||
user interfaces therefore combine drawing and input handling into one unit
|
|
||||||
instead of separating them like retain mode GUIs.
|
|
||||||
|
|
||||||
Since there is no to minimal internal state in immediate mode user interfaces,
|
|
||||||
updates have to occur every frame which on one hand is more drawing expensive than classic
|
|
||||||
retained GUI implementations but on the other hand grants a lot more flexibility and
|
|
||||||
support for overall layout changes. In addition without any state there is no
|
|
||||||
duplicated state between your program, the gui and the user which greatly
|
|
||||||
simplifies code. Further traits of immediate mode graphic user interfaces are a
|
|
||||||
code driven style, centralized flow control, easy extensibility and
|
|
||||||
understandability.
|
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
```c
|
```c
|
||||||
struct gui_input input = {0};
|
struct gui_input input = {0};
|
||||||
@ -111,14 +75,22 @@ while (1) {
|
|||||||
```
|
```
|
||||||

|

|
||||||
|
|
||||||
## API
|
## IMGUIs
|
||||||
The API for this gui toolkit is divided into two different layers. There
|
Immediate mode in contrast to classical retained mode GUIs store as little state as possible
|
||||||
is the widget layer and the panel layer. The widget layer provides a number of
|
by using procedural function calls as "widgets" instead of storing objects.
|
||||||
classical widgets in functional immediate mode form without any kind of internal
|
Each "widget" function call takes hereby all its necessary data and immediately returns
|
||||||
state. Each widget can be placed anywhere on the screen but there is no direct
|
the through the user modified state back to the caller. Immediate mode graphical
|
||||||
way provided to group widgets together. For this to change there is the panel
|
user interfaces therefore combine drawing and input handling into one unit
|
||||||
layer which is build on top of the widget layer and uses most of the widget API
|
instead of separating them like retain mode GUIs.
|
||||||
internally to form groups of widgets into a layout.
|
|
||||||
|
Since there is no to minimal internal state in immediate mode user interfaces,
|
||||||
|
updates have to occur every frame which on one hand is more drawing expensive than classic
|
||||||
|
retained GUI implementations but on the other hand grants a lot more flexibility and
|
||||||
|
support for overall layout changes. In addition without any state there is no
|
||||||
|
duplicated state between your program, the gui and the user which greatly
|
||||||
|
simplifies code. Further traits of immediate mode graphic user interfaces are a
|
||||||
|
code driven style, centralized flow control, easy extensibility and
|
||||||
|
understandability.
|
||||||
|
|
||||||
### Input
|
### Input
|
||||||
The `gui_input` struct holds the user input over the course of the frame and
|
The `gui_input` struct holds the user input over the course of the frame and
|
||||||
@ -198,9 +170,9 @@ while (1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
For the purpose of implementing overlapping panels sub buffers were implemented.
|
For the purpose of implementing multible panels, sub buffers were implemented.
|
||||||
With sub buffers you can create one global buffer which owns the allocated memory
|
With sub buffers you can create one global buffer which owns the allocated memory
|
||||||
and sub buffers which directly reference the global buffer. Biggest
|
and sub buffers which directly reference the global buffer. The biggest
|
||||||
advantage is that you do not have to allocate a buffer for each panel and boil
|
advantage is that you do not have to allocate a buffer for each panel and boil
|
||||||
down the memory management to a single buffer.
|
down the memory management to a single buffer.
|
||||||
|
|
||||||
|
127
demo/xlib.c
127
demo/xlib.c
@ -12,9 +12,6 @@
|
|||||||
#include "../gui.h"
|
#include "../gui.h"
|
||||||
|
|
||||||
/* macros */
|
/* macros */
|
||||||
#define MAX_BUFFER 64
|
|
||||||
#define MAX_MEMORY (8 * 1024)
|
|
||||||
#define MAX_PANELS 4
|
|
||||||
#define WIN_WIDTH 800
|
#define WIN_WIDTH 800
|
||||||
#define WIN_HEIGHT 600
|
#define WIN_HEIGHT 600
|
||||||
#define DTIME 16
|
#define DTIME 16
|
||||||
@ -25,6 +22,8 @@
|
|||||||
#define LEN(a) (sizeof(a)/sizeof(a)[0])
|
#define LEN(a) (sizeof(a)/sizeof(a)[0])
|
||||||
#define UNUSED(a) ((void)(a))
|
#define UNUSED(a) ((void)(a))
|
||||||
|
|
||||||
|
#include "demo.c"
|
||||||
|
|
||||||
typedef struct XFont XFont;
|
typedef struct XFont XFont;
|
||||||
typedef struct XSurface XSurface;
|
typedef struct XSurface XSurface;
|
||||||
typedef struct XWindow XWindow;
|
typedef struct XWindow XWindow;
|
||||||
@ -62,27 +61,6 @@ struct XWindow {
|
|||||||
unsigned int height;
|
unsigned int height;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct demo {
|
|
||||||
gui_char in_buf[MAX_BUFFER];
|
|
||||||
gui_size in_len;
|
|
||||||
gui_bool in_act;
|
|
||||||
gui_char cmd_buf[MAX_BUFFER];
|
|
||||||
gui_size cmd_len;
|
|
||||||
gui_bool cmd_act;
|
|
||||||
gui_bool check;
|
|
||||||
gui_int option;
|
|
||||||
gui_float slider;
|
|
||||||
gui_size prog;
|
|
||||||
gui_int spinner;
|
|
||||||
gui_bool spin_act;
|
|
||||||
gui_size item_cur;
|
|
||||||
gui_size cur;
|
|
||||||
gui_bool tab_min;
|
|
||||||
gui_float group_off;
|
|
||||||
gui_float shelf_off;
|
|
||||||
gui_bool toggle;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
die(const char *fmt, ...)
|
die(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
@ -320,7 +298,7 @@ surface_del(XSurface *surf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
draw(XSurface *surf, struct gui_command_list *list)
|
execute(XSurface *surf, struct gui_command_list *list)
|
||||||
{
|
{
|
||||||
const struct gui_command *cmd;
|
const struct gui_command *cmd;
|
||||||
if (!list->count) return;
|
if (!list->count) return;
|
||||||
@ -355,12 +333,26 @@ draw(XSurface *surf, struct gui_command_list *list)
|
|||||||
surface_draw_text(surf, t->x, t->y, t->w, t->h, (const char*)t->string,
|
surface_draw_text(surf, t->x, t->y, t->w, t->h, (const char*)t->string,
|
||||||
t->length, t->font, t->bg, t->fg);
|
t->length, t->font, t->bg, t->fg);
|
||||||
} break;
|
} break;
|
||||||
|
case GUI_COMMAND_IMAGE:
|
||||||
|
case GUI_COMMAND_MAX:
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
cmd = gui_list_next(list, cmd);
|
cmd = gui_list_next(list, cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw(XSurface *surf, struct gui_panel_stack *stack)
|
||||||
|
{
|
||||||
|
struct gui_panel *iter = stack->begin;
|
||||||
|
if (!stack->count) return;
|
||||||
|
while (iter) {
|
||||||
|
struct gui_window *win = (void*)iter;
|
||||||
|
execute(surf, &win->list);
|
||||||
|
iter = iter->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
key(struct XWindow *xw, struct gui_input *in, XEvent *evt, gui_bool down)
|
key(struct XWindow *xw, struct gui_input *in, XEvent *evt, gui_bool down)
|
||||||
{
|
{
|
||||||
@ -412,55 +404,6 @@ resize(struct XWindow *xw, XSurface *surf)
|
|||||||
surface_resize(surf, xw->width, xw->height);
|
surface_resize(surf, xw->width, xw->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
demo_panel(struct gui_panel_layout *panel, struct demo *demo)
|
|
||||||
{
|
|
||||||
gui_int i = 0;
|
|
||||||
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"};
|
|
||||||
const char *options[] = {"easy", "normal", "hard", "hell", "doom", "godlike"};
|
|
||||||
struct gui_panel_layout tab;
|
|
||||||
|
|
||||||
/* Tabs */
|
|
||||||
demo->tab_min = gui_panel_tab_begin(panel, &tab, "Difficulty", demo->tab_min);
|
|
||||||
gui_panel_row(&tab, 30, 3);
|
|
||||||
for (i = 0; i < (gui_int)LEN(options); i++) {
|
|
||||||
if (gui_panel_option(&tab, options[i], demo->option == i))
|
|
||||||
demo->option = i;
|
|
||||||
}
|
|
||||||
gui_panel_tab_end(panel, &tab);
|
|
||||||
|
|
||||||
/* Shelf */
|
|
||||||
gui_panel_row(panel, 200, 2);
|
|
||||||
demo->cur = gui_panel_shelf_begin(panel,&tab,shelfs,LEN(shelfs),demo->cur,demo->shelf_off);
|
|
||||||
gui_panel_row(&tab, 100, 1);
|
|
||||||
if (demo->cur == HISTO) {
|
|
||||||
gui_panel_graph(&tab, GUI_GRAPH_HISTO, values, LEN(values));
|
|
||||||
} else {
|
|
||||||
gui_panel_graph(&tab, GUI_GRAPH_LINES, values, LEN(values));
|
|
||||||
}
|
|
||||||
demo->shelf_off = gui_panel_shelf_end(panel, &tab);
|
|
||||||
|
|
||||||
/* Group */
|
|
||||||
gui_panel_group_begin(panel, &tab, "Options", demo->group_off);
|
|
||||||
gui_panel_row(&tab, 30, 1);
|
|
||||||
if (gui_panel_button_text(&tab, "button", GUI_BUTTON_DEFAULT))
|
|
||||||
fprintf(stdout, "button pressed!\n");
|
|
||||||
demo->toggle = gui_panel_button_toggle(&tab, "toggle", demo->toggle);
|
|
||||||
demo->check = gui_panel_check(&tab, "advanced", demo->check);
|
|
||||||
demo->slider = gui_panel_slider(&tab, 0, demo->slider, 10, 1.0f);
|
|
||||||
demo->prog = gui_panel_progress(&tab, demo->prog, 100, gui_true);
|
|
||||||
demo->item_cur = gui_panel_selector(&tab, items, LEN(items), demo->item_cur);
|
|
||||||
demo->spinner = gui_panel_spinner(&tab, 0, demo->spinner, 250, 10, &demo->spin_act);
|
|
||||||
if (gui_panel_shell(&tab, demo->cmd_buf, &demo->cmd_len, MAX_BUFFER, &demo->cmd_act))
|
|
||||||
demo->cmd_len = 0;
|
|
||||||
demo->in_len = gui_panel_edit(&tab, demo->in_buf, demo->in_len,
|
|
||||||
MAX_BUFFER, &demo->in_act, GUI_INPUT_DEFAULT);
|
|
||||||
demo->group_off = gui_panel_group_end(panel, &tab);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -469,24 +412,16 @@ main(int argc, char *argv[])
|
|||||||
long started;
|
long started;
|
||||||
XWindow xw;
|
XWindow xw;
|
||||||
gui_bool running = gui_true;
|
gui_bool running = gui_true;
|
||||||
struct demo demo;
|
|
||||||
|
|
||||||
/* GUI */
|
/* GUI */
|
||||||
struct gui_input in;
|
struct gui_input in;
|
||||||
struct gui_font font;
|
struct gui_font font;
|
||||||
struct gui_memory memory;
|
struct gui_memory memory;
|
||||||
struct gui_memory_status status;
|
|
||||||
struct gui_config config;
|
struct gui_config config;
|
||||||
struct gui_canvas canvas;
|
|
||||||
struct gui_command_buffer buffer;
|
struct gui_command_buffer buffer;
|
||||||
struct gui_command_list list;
|
struct gui_panel_stack stack;
|
||||||
struct gui_panel_layout layout;
|
struct show_window show;
|
||||||
struct gui_panel panel;
|
struct control_window control;
|
||||||
|
|
||||||
gui_size option = 0;
|
|
||||||
gui_char buf[256];
|
|
||||||
gui_size len = 0;
|
|
||||||
gui_bool active;
|
|
||||||
|
|
||||||
/* Window */
|
/* Window */
|
||||||
UNUSED(argc); UNUSED(argv);
|
UNUSED(argc); UNUSED(argv);
|
||||||
@ -521,18 +456,8 @@ main(int argc, char *argv[])
|
|||||||
font.height = (gui_float)xw.font->height;
|
font.height = (gui_float)xw.font->height;
|
||||||
font.width = font_get_text_width;
|
font.width = font_get_text_width;
|
||||||
gui_default_config(&config);
|
gui_default_config(&config);
|
||||||
gui_panel_init(&panel, 50, 50, 400, 320,
|
gui_stack_clear(&stack);
|
||||||
GUI_PANEL_BORDER|GUI_PANEL_MOVEABLE|
|
init_demo(&show, &control, &stack, &config, &font);
|
||||||
GUI_PANEL_CLOSEABLE|GUI_PANEL_SCALEABLE|
|
|
||||||
GUI_PANEL_MINIMIZABLE, &config, &font);
|
|
||||||
|
|
||||||
/* Demo */
|
|
||||||
memset(&demo, 0, sizeof(demo));
|
|
||||||
demo.tab_min = gui_true;
|
|
||||||
demo.spinner = 100;
|
|
||||||
demo.slider = 2.0f;
|
|
||||||
demo.prog = 60;
|
|
||||||
demo.cur = 1;
|
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
/* Input */
|
/* Input */
|
||||||
@ -551,16 +476,12 @@ main(int argc, char *argv[])
|
|||||||
gui_input_end(&in);
|
gui_input_end(&in);
|
||||||
|
|
||||||
/* GUI */
|
/* GUI */
|
||||||
gui_buffer_begin(&canvas, &buffer, xw.width, xw.height);
|
running = run_demo(&show, &control, &stack, &config, &in, &buffer, xw.width, xw.height);
|
||||||
running = gui_panel_begin(&layout, &panel, "Demo", &canvas, &in);
|
|
||||||
demo_panel(&layout, &demo);
|
|
||||||
gui_panel_end(&layout, &panel);
|
|
||||||
gui_buffer_end(&list, &buffer, &canvas, &status);
|
|
||||||
|
|
||||||
/* Draw */
|
/* Draw */
|
||||||
XClearWindow(xw.dpy, xw.win);
|
XClearWindow(xw.dpy, xw.win);
|
||||||
surface_clear(xw.surf, 0x00646464);
|
surface_clear(xw.surf, 0x00646464);
|
||||||
draw(xw.surf, &list);
|
draw(xw.surf, &stack);
|
||||||
surface_blit(xw.win, xw.surf, xw.width, xw.height);
|
surface_blit(xw.win, xw.surf, xw.width, xw.height);
|
||||||
XFlush(xw.dpy);
|
XFlush(xw.dpy);
|
||||||
|
|
||||||
|
55
gui.c
55
gui.c
@ -843,6 +843,7 @@ gui_buffer_push(struct gui_command_buffer* buffer,
|
|||||||
cap = (gui_size)((gui_float)buffer->capacity * buffer->grow_factor);
|
cap = (gui_size)((gui_float)buffer->capacity * buffer->grow_factor);
|
||||||
buffer->memory = buffer->allocator.realloc(buffer->allocator.userdata,buffer->memory, cap);
|
buffer->memory = buffer->allocator.realloc(buffer->allocator.userdata,buffer->memory, cap);
|
||||||
if (!buffer->memory) return NULL;
|
if (!buffer->memory) return NULL;
|
||||||
|
|
||||||
buffer->capacity = cap;
|
buffer->capacity = cap;
|
||||||
buffer->begin = buffer->memory;
|
buffer->begin = buffer->memory;
|
||||||
buffer->end = (void*)((gui_byte*)buffer->begin + buffer->allocated);
|
buffer->end = (void*)((gui_byte*)buffer->begin + buffer->allocated);
|
||||||
@ -1006,7 +1007,8 @@ gui_buffer_push_image(struct gui_command_buffer *buffer, gui_float x, gui_float
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmd = gui_buffer_push(buffer, GUI_COMMAND_RECT, sizeof(*cmd));
|
|
||||||
|
cmd = gui_buffer_push(buffer, GUI_COMMAND_IMAGE, sizeof(*cmd));
|
||||||
if (!cmd) return;
|
if (!cmd) return;
|
||||||
cmd->x = (gui_short)x;
|
cmd->x = (gui_short)x;
|
||||||
cmd->y = (gui_short)y;
|
cmd->y = (gui_short)y;
|
||||||
@ -1035,6 +1037,7 @@ gui_buffer_push_text(struct gui_command_buffer *buffer, gui_float x, gui_float y
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = gui_buffer_push(buffer, GUI_COMMAND_TEXT, sizeof(*cmd) + length + 1);
|
cmd = gui_buffer_push(buffer, GUI_COMMAND_TEXT, sizeof(*cmd) + length + 1);
|
||||||
if (!cmd) return;
|
if (!cmd) return;
|
||||||
cmd->x = (gui_short)x;
|
cmd->x = (gui_short)x;
|
||||||
@ -1285,7 +1288,6 @@ gui_panel_init(struct gui_panel *panel, gui_float x, gui_float y, gui_float w,
|
|||||||
panel->y = y;
|
panel->y = y;
|
||||||
panel->w = w;
|
panel->w = w;
|
||||||
panel->h = h;
|
panel->h = h;
|
||||||
panel->flags = 0;
|
|
||||||
panel->flags = flags;
|
panel->flags = flags;
|
||||||
panel->config = config;
|
panel->config = config;
|
||||||
panel->font = *font;
|
panel->font = *font;
|
||||||
@ -1312,8 +1314,13 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
|
|||||||
|
|
||||||
if (!panel || !canvas || !layout)
|
if (!panel || !canvas || !layout)
|
||||||
return gui_false;
|
return gui_false;
|
||||||
if (panel->flags & GUI_PANEL_HIDDEN)
|
if (panel->flags & GUI_PANEL_HIDDEN) {
|
||||||
|
zero(layout, sizeof(*layout));
|
||||||
|
layout->valid = gui_false;
|
||||||
|
layout->config = panel->config;
|
||||||
|
layout->canvas = canvas;
|
||||||
return gui_false;
|
return gui_false;
|
||||||
|
}
|
||||||
|
|
||||||
config = panel->config;
|
config = panel->config;
|
||||||
layout->header_height = panel->font.height + 3 * config->item_padding.y;
|
layout->header_height = panel->font.height + 3 * config->item_padding.y;
|
||||||
@ -1323,7 +1330,6 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
|
|||||||
mouse_y = (in) ? in->mouse_pos.y : -1;
|
mouse_y = (in) ? in->mouse_pos.y : -1;
|
||||||
prev_x = (in) ? in->mouse_prev.x : -1;
|
prev_x = (in) ? in->mouse_prev.x : -1;
|
||||||
prev_y = (in) ? in->mouse_prev.y : -1;
|
prev_y = (in) ? in->mouse_prev.y : -1;
|
||||||
|
|
||||||
clicked_x = (in) ? in->mouse_clicked_pos.x : -1;
|
clicked_x = (in) ? in->mouse_clicked_pos.x : -1;
|
||||||
clicked_y = (in) ? in->mouse_clicked_pos.y : -1;
|
clicked_y = (in) ? in->mouse_clicked_pos.y : -1;
|
||||||
|
|
||||||
@ -1345,8 +1351,8 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
|
|||||||
gui_bool incursor;
|
gui_bool incursor;
|
||||||
gui_float scaler_w = MAX(0, config->scaler_size.x - config->item_padding.x);
|
gui_float scaler_w = MAX(0, config->scaler_size.x - config->item_padding.x);
|
||||||
gui_float scaler_h = MAX(0, config->scaler_size.y - config->item_padding.y);
|
gui_float scaler_h = MAX(0, config->scaler_size.y - config->item_padding.y);
|
||||||
gui_float scaler_x = (layout->x + layout->w) - (config->item_padding.x + scaler_w);
|
gui_float scaler_x = (panel->x + panel->w) - (config->item_padding.x + scaler_w);
|
||||||
gui_float scaler_y = layout->y + layout->h - config->scaler_size.y;
|
gui_float scaler_y = panel->y + panel->h - config->scaler_size.y;
|
||||||
|
|
||||||
incursor = in && INBOX(prev_x, prev_y, scaler_x, scaler_y, scaler_w, scaler_h);
|
incursor = in && INBOX(prev_x, prev_y, scaler_x, scaler_y, scaler_w, scaler_h);
|
||||||
if (in && in->mouse_down && incursor) {
|
if (in && in->mouse_down && incursor) {
|
||||||
@ -1423,7 +1429,7 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel,
|
|||||||
if (INBOX(mouse_x, mouse_y, close_x, close_y, close_w, close_h)) {
|
if (INBOX(mouse_x, mouse_y, close_x, close_y, close_w, close_h)) {
|
||||||
if (INBOX(clicked_x, clicked_y, close_x, close_y, close_w, close_h)) {
|
if (INBOX(clicked_x, clicked_y, close_x, close_y, close_w, close_h)) {
|
||||||
ret = !(in->mouse_down && in->mouse_clicked);
|
ret = !(in->mouse_down && in->mouse_clicked);
|
||||||
if (ret) panel->flags |= GUI_PANEL_HIDDEN;
|
if (!ret) panel->flags |= GUI_PANEL_HIDDEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1509,9 +1515,8 @@ gui_panel_begin_stacked(struct gui_panel_layout *layout, struct gui_panel *panel
|
|||||||
if (in->mouse_down && in->mouse_clicked && inpanel && panel != stack->end) {
|
if (in->mouse_down && in->mouse_clicked && inpanel && panel != stack->end) {
|
||||||
struct gui_panel *iter = panel->next;
|
struct gui_panel *iter = panel->next;
|
||||||
while (iter) {
|
while (iter) {
|
||||||
if (!iter->minimized)
|
if (INBOX(in->mouse_prev.x, in->mouse_prev.y, iter->x, iter->y, iter->w, iter->h) &&
|
||||||
if (INBOX(in->mouse_prev.x, in->mouse_prev.y, iter->x, iter->y,
|
!iter->minimized) break;
|
||||||
iter->w, iter->h)) break;
|
|
||||||
iter = iter->next;
|
iter = iter->next;
|
||||||
}
|
}
|
||||||
if (!iter) {
|
if (!iter) {
|
||||||
@ -1574,6 +1579,8 @@ gui_panel_alloc_space(struct gui_rect *bounds, struct gui_panel_layout *layout)
|
|||||||
ASSERT(layout);
|
ASSERT(layout);
|
||||||
ASSERT(layout->config);
|
ASSERT(layout->config);
|
||||||
ASSERT(bounds);
|
ASSERT(bounds);
|
||||||
|
if (!layout || !layout->config || !bounds)
|
||||||
|
return;
|
||||||
|
|
||||||
config = layout->config;
|
config = layout->config;
|
||||||
if (layout->index >= layout->row_columns) {
|
if (layout->index >= layout->row_columns) {
|
||||||
@ -1644,7 +1651,6 @@ gui_panel_label(struct gui_panel_layout *layout, const char *text, enum gui_text
|
|||||||
gui_panel_text(layout, text, len, align);
|
gui_panel_text(layout, text, len, align);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gui_bool
|
gui_bool
|
||||||
gui_panel_button_text(struct gui_panel_layout *layout, const char *str,
|
gui_panel_button_text(struct gui_panel_layout *layout, const char *str,
|
||||||
enum gui_button_behavior behavior)
|
enum gui_button_behavior behavior)
|
||||||
@ -1704,7 +1710,7 @@ gui_bool gui_panel_button_color(struct gui_panel_layout *layout,
|
|||||||
button.background = color;
|
button.background = color;
|
||||||
button.foreground = color;
|
button.foreground = color;
|
||||||
button.highlight = color;
|
button.highlight = color;
|
||||||
button.highlight_content = config->colors[GUI_COLOR_BUTTON_HOVER_FONT];
|
button.highlight_content = color;
|
||||||
return gui_do_button(layout->canvas, bounds.x, bounds.y, bounds.w, bounds.h,
|
return gui_do_button(layout->canvas, bounds.x, bounds.y, bounds.w, bounds.h,
|
||||||
&button, layout->input, behavior);
|
&button, layout->input, behavior);
|
||||||
}
|
}
|
||||||
@ -2054,18 +2060,18 @@ gui_panel_spinner(struct gui_panel_layout *layout, gui_int min, gui_int value,
|
|||||||
ASSERT(layout->config);
|
ASSERT(layout->config);
|
||||||
ASSERT(layout->canvas);
|
ASSERT(layout->canvas);
|
||||||
|
|
||||||
if (!layout || !layout->config || !layout->canvas) return 0;
|
if (!layout || !layout->config || !layout->canvas) return value;
|
||||||
if (!layout->valid) return 0;
|
if (!layout->valid) return value;
|
||||||
gui_panel_alloc_space(&bounds, layout);
|
gui_panel_alloc_space(&bounds, layout);
|
||||||
config = layout->config;
|
config = layout->config;
|
||||||
canvas = layout->canvas;
|
canvas = layout->canvas;
|
||||||
c = &layout->clip;
|
c = &layout->clip;
|
||||||
if (!INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h))
|
if (!INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h))
|
||||||
return 0;
|
return value;
|
||||||
|
|
||||||
value = CLAMP(min, value, max);
|
value = CLAMP(min, value, max);
|
||||||
len = itos(string, value);
|
len = itos(string, value);
|
||||||
is_active = *active;
|
is_active = (active) ? *active : gui_false;
|
||||||
old_len = len;
|
old_len = len;
|
||||||
|
|
||||||
button.border = 1;
|
button.border = 1;
|
||||||
@ -2105,7 +2111,7 @@ gui_panel_spinner(struct gui_panel_layout *layout, gui_int min, gui_int value,
|
|||||||
len, MAX_NUMBER_BUFFER, &is_active, &field, layout->input, &layout->font);
|
len, MAX_NUMBER_BUFFER, &is_active, &field, layout->input, &layout->font);
|
||||||
if (old_len != len)
|
if (old_len != len)
|
||||||
strtoi(&value, string, len);
|
strtoi(&value, string, len);
|
||||||
*active = is_active;
|
if (active) *active = is_active;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2160,11 +2166,11 @@ gui_panel_selector(struct gui_panel_layout *layout, const char *items[],
|
|||||||
button.content = config->colors[GUI_COLOR_TEXT];
|
button.content = config->colors[GUI_COLOR_TEXT];
|
||||||
button.highlight = config->colors[GUI_COLOR_BUTTON];
|
button.highlight = config->colors[GUI_COLOR_BUTTON];
|
||||||
button.highlight_content = config->colors[GUI_COLOR_TEXT];
|
button.highlight_content = config->colors[GUI_COLOR_TEXT];
|
||||||
button_up_clicked = gui_button_triangle(canvas, button_x, button_y, button_w,
|
button_down_clicked = gui_button_triangle(canvas, button_x, button_y, button_w,
|
||||||
button_h, GUI_UP, GUI_BUTTON_DEFAULT, &button, layout->input);
|
button_h, GUI_UP, GUI_BUTTON_DEFAULT, &button, layout->input);
|
||||||
|
|
||||||
button_y = bounds.y + button_h;
|
button_y = bounds.y + button_h;
|
||||||
button_down_clicked = gui_button_triangle(canvas, button_x, button_y, button_w,
|
button_up_clicked = gui_button_triangle(canvas, button_x, button_y, button_w,
|
||||||
button_h, GUI_DOWN, GUI_BUTTON_DEFAULT, &button, layout->input);
|
button_h, GUI_DOWN, GUI_BUTTON_DEFAULT, &button, layout->input);
|
||||||
item_current = (button_down_clicked && item_current < item_count-1) ?
|
item_current = (button_down_clicked && item_current < item_count-1) ?
|
||||||
item_current+1 : (button_up_clicked && item_current > 0) ? item_current-1 : item_current;
|
item_current+1 : (button_up_clicked && item_current > 0) ? item_current-1 : item_current;
|
||||||
@ -2342,14 +2348,13 @@ gui_panel_graph(struct gui_panel_layout *layout, enum gui_graph_type type,
|
|||||||
struct gui_rect bounds;
|
struct gui_rect bounds;
|
||||||
gui_float min_value;
|
gui_float min_value;
|
||||||
gui_float max_value;
|
gui_float max_value;
|
||||||
const struct gui_config *config;
|
|
||||||
struct gui_graph graph;
|
struct gui_graph graph;
|
||||||
|
|
||||||
ASSERT(layout);
|
ASSERT(layout);
|
||||||
ASSERT(layout->config);
|
|
||||||
ASSERT(layout->canvas);
|
|
||||||
ASSERT(values);
|
ASSERT(values);
|
||||||
ASSERT(count);
|
ASSERT(count);
|
||||||
|
if (!layout || !values || !count)
|
||||||
|
return -1;
|
||||||
|
|
||||||
max_value = values[0];
|
max_value = values[0];
|
||||||
min_value = values[0];
|
min_value = values[0];
|
||||||
@ -2378,13 +2383,13 @@ gui_panel_graph_ex(struct gui_panel_layout *layout, enum gui_graph_type type,
|
|||||||
struct gui_rect bounds;
|
struct gui_rect bounds;
|
||||||
gui_float min_value;
|
gui_float min_value;
|
||||||
gui_float max_value;
|
gui_float max_value;
|
||||||
const struct gui_config *config;
|
|
||||||
struct gui_graph graph;
|
struct gui_graph graph;
|
||||||
|
|
||||||
ASSERT(layout);
|
ASSERT(layout);
|
||||||
ASSERT(layout->config);
|
|
||||||
ASSERT(layout->canvas);
|
|
||||||
ASSERT(get_value);
|
ASSERT(get_value);
|
||||||
|
ASSERT(count);
|
||||||
|
if (!layout || !get_value || !count)
|
||||||
|
return -1;
|
||||||
|
|
||||||
max_value = get_value(userdata, 0);
|
max_value = get_value(userdata, 0);
|
||||||
min_value = max_value;
|
min_value = max_value;
|
||||||
|
14
gui.h
14
gui.h
@ -228,7 +228,9 @@ enum gui_command_type {
|
|||||||
GUI_COMMAND_RECT,
|
GUI_COMMAND_RECT,
|
||||||
GUI_COMMAND_CIRCLE,
|
GUI_COMMAND_CIRCLE,
|
||||||
GUI_COMMAND_TRIANGLE,
|
GUI_COMMAND_TRIANGLE,
|
||||||
GUI_COMMAND_TEXT
|
GUI_COMMAND_TEXT,
|
||||||
|
GUI_COMMAND_IMAGE,
|
||||||
|
GUI_COMMAND_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gui_command {
|
struct gui_command {
|
||||||
@ -399,11 +401,6 @@ struct gui_panel {
|
|||||||
struct gui_panel *prev;
|
struct gui_panel *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gui_window {
|
|
||||||
struct gui_panel panel;
|
|
||||||
struct gui_command_list list;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gui_panel_layout {
|
struct gui_panel_layout {
|
||||||
gui_float x, y, w, h;
|
gui_float x, y, w, h;
|
||||||
gui_float offset;
|
gui_float offset;
|
||||||
@ -430,6 +427,11 @@ struct gui_panel_stack {
|
|||||||
struct gui_panel *end;
|
struct gui_panel *end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct gui_window {
|
||||||
|
struct gui_panel panel;
|
||||||
|
struct gui_command_list list;
|
||||||
|
};
|
||||||
|
|
||||||
/* Input */
|
/* Input */
|
||||||
gui_size gui_utf_decode(const gui_char*, gui_long*, gui_size);
|
gui_size gui_utf_decode(const gui_char*, gui_long*, gui_size);
|
||||||
gui_size gui_utf_encode(gui_long, gui_char*, gui_size);
|
gui_size gui_utf_encode(gui_long, gui_char*, gui_size);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user