mirror of
https://github.com/nishiowo/nishbox
synced 2025-04-21 20:24:39 +00:00
do safer way to manage gui
This commit is contained in:
parent
c1c5d47f92
commit
db496582a6
@ -111,4 +111,13 @@ GF_EXPORT void gf_gui_draw_box(gf_gui_t* gui, int mul, double x, double y, doubl
|
||||
*/
|
||||
GF_EXPORT void gf_gui_set_callback(gf_gui_t* gui, gf_gui_id_t id, gf_gui_callback_t callback);
|
||||
|
||||
/**
|
||||
* @~english
|
||||
* @brief Set parent component
|
||||
* @param gui GUI
|
||||
* @param id Component ID
|
||||
* @param parent Parent component ID
|
||||
*/
|
||||
GF_EXPORT void gf_gui_set_parent(gf_gui_t* gui, gf_gui_id_t id, gf_gui_id_t parent);
|
||||
|
||||
#endif
|
||||
|
@ -41,19 +41,12 @@ typedef union gf_gui_union_t gf_gui_union_t;
|
||||
|
||||
typedef void (*gf_gui_callback_t)(gf_engine_t* engine, gf_draw_t* draw, gf_gui_id_t id, int type);
|
||||
|
||||
/**
|
||||
* @~english
|
||||
* @brief Max components GUI can handle
|
||||
*/
|
||||
#define GF_GUI_MAX_COMPONENTS 64
|
||||
|
||||
/**
|
||||
* @~english
|
||||
* @brief GUI component types
|
||||
*/
|
||||
enum GF_GUI_COMPONENT_TYPES {
|
||||
GF_GUI_UNUSED = -1,
|
||||
GF_GUI_BUTTON
|
||||
GF_GUI_BUTTON = 0
|
||||
};
|
||||
|
||||
/**
|
||||
@ -83,6 +76,9 @@ typedef union gf_gui_union_t {
|
||||
* @~english
|
||||
* @brief Component
|
||||
*
|
||||
* @var gf_gui_component_t::key
|
||||
* @brief Component ID
|
||||
*
|
||||
* @var gf_gui_component_t::type
|
||||
* @brief Component type
|
||||
* @see GF_GUI_COMPONENT_TYPES
|
||||
@ -107,14 +103,19 @@ typedef union gf_gui_union_t {
|
||||
*
|
||||
* @var gf_gui_component_t::u
|
||||
* @brief Component union
|
||||
*
|
||||
* @var gf_gui_component_t::parent
|
||||
* @brief Parent GUI component
|
||||
*/
|
||||
GF_DECLARE_TYPE(gui_component, {
|
||||
gf_gui_id_t key;
|
||||
int type;
|
||||
double x;
|
||||
double y;
|
||||
double width;
|
||||
double height;
|
||||
int pressed;
|
||||
gf_gui_id_t parent;
|
||||
gf_gui_callback_t callback;
|
||||
gf_gui_union_t u;
|
||||
});
|
||||
@ -137,10 +138,10 @@ GF_DECLARE_TYPE(gui_component, {
|
||||
* @brief Created components
|
||||
*/
|
||||
GF_DECLARE_TYPE(gui, {
|
||||
gf_engine_t* engine;
|
||||
gf_draw_t* draw;
|
||||
gf_gui_id_t pressed;
|
||||
gf_gui_component_t area[GF_GUI_MAX_COMPONENTS];
|
||||
gf_engine_t* engine;
|
||||
gf_draw_t* draw;
|
||||
gf_gui_id_t pressed;
|
||||
gf_gui_component_t* area;
|
||||
});
|
||||
#else
|
||||
typedef void* gf_gui_callback_t;
|
||||
|
@ -78,8 +78,7 @@ gf_draw_t* gf_draw_create(gf_engine_t* engine, const char* title) {
|
||||
|
||||
void gf_draw_reshape(gf_draw_t* draw) { gf_draw_driver_reshape(draw); }
|
||||
|
||||
gf_gui_id_t button1 = -1;
|
||||
gf_gui_id_t button2 = -1;
|
||||
int made = 0;
|
||||
|
||||
void gf_button_callback(gf_engine_t* engine, gf_draw_t* draw, gf_gui_id_t id, int type) {
|
||||
if(type == GF_GUI_PRESS_EVENT) {
|
||||
@ -91,13 +90,23 @@ void gf_button_callback(gf_engine_t* engine, gf_draw_t* draw, gf_gui_id_t id, in
|
||||
void gf_draw_frame(gf_draw_t* draw) {
|
||||
gf_graphic_color_t color;
|
||||
color.r = color.g = color.b = color.a = 255;
|
||||
if(button1 == -1) {
|
||||
button1 = gf_gui_create_button(draw->gui, 0, 0, 200, 50, "\"Test\" text");
|
||||
gf_gui_set_callback(draw->gui, button1, gf_button_callback);
|
||||
}
|
||||
if(button2 == -1) {
|
||||
button2 = gf_gui_create_button(draw->gui, 100, 25, 200, 50, "\"Test\" text");
|
||||
gf_gui_set_callback(draw->gui, button2, gf_button_callback);
|
||||
if(made == 0) {
|
||||
int i;
|
||||
made = 1;
|
||||
for(i = 0; i < 5; i++) {
|
||||
double p = 50;
|
||||
double s = 300 - i * p;
|
||||
gf_gui_id_t id;
|
||||
|
||||
if(i > 0) {
|
||||
p = (s + p) / 2 - (s / 2);
|
||||
}
|
||||
|
||||
id = gf_gui_create_button(draw->gui, p, p, s, s, "");
|
||||
if(i > 0) {
|
||||
gf_gui_set_parent(draw->gui, id, id - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(draw->draw_3d) {
|
||||
gf_graphic_draw_texture_polygon(draw, test_texture, color, GF_GRAPHIC_3D, 4,
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <gf_pre.h>
|
||||
|
||||
/* External library */
|
||||
#include <stb_ds.h>
|
||||
|
||||
/* Interface */
|
||||
#include <gf_gui.h>
|
||||
@ -24,40 +25,44 @@ gf_graphic_color_t gf_gui_base_color;
|
||||
gf_graphic_color_t gf_gui_font_color;
|
||||
|
||||
gf_gui_t* gf_gui_create(gf_engine_t* engine, gf_draw_t* draw) {
|
||||
gf_gui_t* gui = malloc(sizeof(*gui));
|
||||
gf_gui_id_t i;
|
||||
gf_gui_t* gui = malloc(sizeof(*gui));
|
||||
memset(gui, 0, sizeof(*gui));
|
||||
gui->engine = engine;
|
||||
gui->draw = draw;
|
||||
gui->area = NULL;
|
||||
|
||||
gui->pressed = -1;
|
||||
|
||||
GF_SET_COLOR(gf_gui_base_color, 48, 96, 48, 255);
|
||||
GF_SET_COLOR(gf_gui_font_color, 256 - 32, 256 - 32, 256 - 32, 255);
|
||||
|
||||
for(i = 0; i < GF_GUI_MAX_COMPONENTS; i++) gui->area[i].type = -1;
|
||||
|
||||
return gui;
|
||||
}
|
||||
|
||||
void gf_gui_destroy(gf_gui_t* gui) {
|
||||
gf_gui_id_t i;
|
||||
for(i = 0; i < GF_GUI_MAX_COMPONENTS; i++) {
|
||||
gf_gui_destroy_id(gui, i);
|
||||
int i;
|
||||
if(gui->area != NULL) {
|
||||
for(i = 0; i < hmlen(gui->area); i++) {
|
||||
gf_gui_destroy_id(gui, gui->area[i].key);
|
||||
}
|
||||
}
|
||||
gf_log_function(gui->engine, "Destroyed GUI", "");
|
||||
free(gui);
|
||||
}
|
||||
|
||||
void gf_gui_destroy_id(gf_gui_t* gui, gf_gui_id_t id) {
|
||||
gf_gui_component_t* c = &gui->area[id];
|
||||
switch(c->type) {
|
||||
case GF_GUI_BUTTON: {
|
||||
if(c->u.button.text != NULL) free(c->u.button.text);
|
||||
c->u.button.text = NULL;
|
||||
int ind = hmgeti(gui->area, id);
|
||||
gf_gui_component_t* c;
|
||||
if(ind != -1) {
|
||||
c = &gui->area[ind];
|
||||
switch(c->type) {
|
||||
case GF_GUI_BUTTON: {
|
||||
if(c->u.button.text != NULL) free(c->u.button.text);
|
||||
c->u.button.text = NULL;
|
||||
}
|
||||
}
|
||||
hmdel(gui->area, id);
|
||||
}
|
||||
}
|
||||
c->type = GF_GUI_UNUSED;
|
||||
}
|
||||
|
||||
/* note... left top should be the lightest in the border */
|
||||
@ -84,48 +89,101 @@ void gf_gui_draw_box(gf_gui_t* gui, int mul, double x, double y, double w, doubl
|
||||
gf_graphic_fill_rect(gui->draw, x + gf_gui_border_width, y + gf_gui_border_width, w - gf_gui_border_width * 2, h - gf_gui_border_width * 2, col);
|
||||
}
|
||||
|
||||
gf_gui_component_t* gf_gui_first_unused(gf_gui_t* gui, gf_gui_id_t* id) {
|
||||
gf_gui_id_t i;
|
||||
for(i = 0; i < GF_GUI_MAX_COMPONENTS; i++) {
|
||||
if(gui->area[i].type == GF_GUI_UNUSED) {
|
||||
*id = i;
|
||||
return &gui->area[i];
|
||||
}
|
||||
void gf_gui_create_component(gf_gui_t* gui, gf_gui_component_t* c, double x, double y, double w, double h) {
|
||||
if(gui->area == NULL) {
|
||||
c->key = 0;
|
||||
} else {
|
||||
c->key = hmlen(gui->area);
|
||||
}
|
||||
return NULL;
|
||||
c->x = x;
|
||||
c->y = y;
|
||||
c->width = w;
|
||||
c->height = h;
|
||||
c->parent = -1;
|
||||
c->pressed = 0;
|
||||
c->callback = NULL;
|
||||
}
|
||||
|
||||
gf_gui_id_t gf_gui_create_button(gf_gui_t* gui, double x, double y, double w, double h, const char* text) {
|
||||
gf_gui_id_t id;
|
||||
gf_gui_component_t* c = gf_gui_first_unused(gui, &id);
|
||||
gf_gui_component_t c;
|
||||
|
||||
c->type = GF_GUI_BUTTON;
|
||||
c->x = x;
|
||||
c->y = y;
|
||||
c->width = w;
|
||||
c->height = h;
|
||||
gf_gui_create_component(gui, &c, x, y, w, h);
|
||||
|
||||
c->pressed = 0;
|
||||
c->callback = NULL;
|
||||
c.type = GF_GUI_BUTTON;
|
||||
c.u.button.text = malloc(strlen(text) + 1);
|
||||
strcpy(c.u.button.text, text);
|
||||
|
||||
c->u.button.text = malloc(strlen(text) + 1);
|
||||
strcpy(c->u.button.text, text);
|
||||
return id;
|
||||
hmputs(gui->area, c);
|
||||
|
||||
return c.key;
|
||||
}
|
||||
|
||||
void gf_gui_calc_xywh_noset(gf_gui_t* gui, gf_gui_component_t* c, double* x, double* y, double* w, double* h) {
|
||||
double pw = gui->draw->width;
|
||||
double ph = gui->draw->height;
|
||||
double bx = 0;
|
||||
double by = 0;
|
||||
|
||||
if(c->parent != -1) {
|
||||
double x2 = 0;
|
||||
double y2 = 0;
|
||||
double w2 = 0;
|
||||
double h2 = 0;
|
||||
int ind = hmgeti(gui->area, c->parent);
|
||||
if(ind != -1) {
|
||||
gf_gui_calc_xywh_noset(gui, &gui->area[ind], &x2, &y2, &w2, &h2);
|
||||
}
|
||||
|
||||
pw = w2;
|
||||
ph = h2;
|
||||
|
||||
bx = x2;
|
||||
by = y2;
|
||||
}
|
||||
|
||||
*x += bx;
|
||||
if(c->x < 0) {
|
||||
*x += pw;
|
||||
}
|
||||
*x += c->x;
|
||||
|
||||
*y += by;
|
||||
if(c->y < 0) {
|
||||
*y += ph;
|
||||
}
|
||||
*y += c->y;
|
||||
|
||||
if((*w) < c->width) {
|
||||
*w = c->width;
|
||||
}
|
||||
|
||||
if((*h) < c->height) {
|
||||
*h = c->height;
|
||||
}
|
||||
}
|
||||
|
||||
void gf_gui_calc_xywh(gf_gui_t* gui, gf_gui_component_t* c, double* x, double* y, double* w, double* h) {
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
*w = 0;
|
||||
*h = 0;
|
||||
gf_gui_calc_xywh_noset(gui, c, x, y, w, h);
|
||||
}
|
||||
|
||||
void gf_gui_render(gf_gui_t* gui) {
|
||||
gf_gui_id_t i;
|
||||
int i;
|
||||
gf_input_t* input = gui->draw->input;
|
||||
for(i = GF_GUI_MAX_COMPONENTS - 1; i >= 0; i--) {
|
||||
gf_gui_component_t* c = &gui->area[i];
|
||||
double cx = c->x;
|
||||
double cy = c->y;
|
||||
double cw = c->width;
|
||||
double ch = c->height;
|
||||
double cx;
|
||||
double cy;
|
||||
double cw;
|
||||
double ch;
|
||||
for(i = hmlen(gui->area) - 1; i >= 0; i--) {
|
||||
gf_gui_component_t* c = &gui->area[i];
|
||||
gf_gui_calc_xywh(gui, c, &cx, &cy, &cw, &ch);
|
||||
switch(c->type) {
|
||||
case GF_GUI_BUTTON: {
|
||||
if(input->mouse_x != -1 && input->mouse_y != -1 && gui->pressed == -1 && (input->mouse_flag & GF_INPUT_MOUSE_LEFT_MASK) && (cx <= input->mouse_x && input->mouse_x <= cx + cw) && (cy <= input->mouse_y && input->mouse_y <= cy + ch)) {
|
||||
gui->pressed = i;
|
||||
gui->pressed = c->key;
|
||||
} else if(gui->pressed == -1) {
|
||||
c->pressed = 0;
|
||||
}
|
||||
@ -133,33 +191,46 @@ void gf_gui_render(gf_gui_t* gui) {
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i = 0; i < GF_GUI_MAX_COMPONENTS; i++) {
|
||||
gf_gui_component_t* c = &gui->area[i];
|
||||
double cx = c->x;
|
||||
double cy = c->y;
|
||||
double cw = c->width;
|
||||
double ch = c->height;
|
||||
for(i = 0; i < hmlen(gui->area); i++) {
|
||||
gf_gui_component_t* c = &gui->area[i];
|
||||
gf_gui_calc_xywh(gui, c, &cx, &cy, &cw, &ch);
|
||||
switch(c->type) {
|
||||
case GF_GUI_BUTTON: {
|
||||
double x = cx + cw / 2 - gf_graphic_text_width(gui->draw, GF_GUI_FONT_SIZE, c->u.button.text) / 2;
|
||||
double y = cy + ch / 2 - GF_GUI_FONT_SIZE / 2;
|
||||
if(gui->pressed == i) {
|
||||
if(gui->pressed == c->key) {
|
||||
x += gf_gui_border_width / 1;
|
||||
y += gf_gui_border_width / 1;
|
||||
}
|
||||
gf_gui_draw_box(gui, (gui->pressed == i) ? GF_GUI_INVERT : GF_GUI_NORMAL, cx, cy, cw, ch);
|
||||
gf_gui_draw_box(gui, (gui->pressed == c->key) ? GF_GUI_INVERT : GF_GUI_NORMAL, cx, cy, cw, ch);
|
||||
gf_graphic_text(gui->draw, x, y, GF_GUI_FONT_SIZE, c->u.button.text, gf_gui_font_color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if((gui->pressed != -1) && !(input->mouse_flag & GF_INPUT_MOUSE_LEFT_MASK)) {
|
||||
int ind;
|
||||
if(gui->area[gui->pressed].callback != NULL) {
|
||||
gui->area[gui->pressed].callback(gui->engine, gui->draw, gui->pressed, GF_GUI_PRESS_EVENT);
|
||||
}
|
||||
gui->area[gui->pressed].pressed = 1;
|
||||
gui->pressed = -1;
|
||||
ind = hmgeti(gui->area, gui->pressed);
|
||||
if(ind != -1) {
|
||||
gui->area[ind].pressed = 1;
|
||||
}
|
||||
gui->pressed = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void gf_gui_set_callback(gf_gui_t* gui, gf_gui_id_t id, gf_gui_callback_t callback) { gui->area[id].callback = callback; }
|
||||
void gf_gui_set_callback(gf_gui_t* gui, gf_gui_id_t id, gf_gui_callback_t callback) {
|
||||
int ind = hmgeti(gui->area, id);
|
||||
if(ind != -1) {
|
||||
gui->area[ind].callback = callback;
|
||||
}
|
||||
}
|
||||
|
||||
void gf_gui_set_parent(gf_gui_t* gui, gf_gui_id_t id, gf_gui_id_t parent) {
|
||||
int ind = hmgeti(gui->area, id);
|
||||
if(ind != -1) {
|
||||
gui->area[ind].parent = parent;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user