added single depth overlapping menus to panels
This commit is contained in:
parent
1c23f982f5
commit
6709dc8875
141
demo/demo.c
141
demo/demo.c
@ -1,5 +1,5 @@
|
||||
#define MAX_BUFFER 64
|
||||
#define MAX_MEMORY (256 * 1024)
|
||||
#define MAX_MEMORY (16 * 1024)
|
||||
#define WINDOW_WIDTH 800
|
||||
#define WINDOW_HEIGHT 600
|
||||
|
||||
@ -25,6 +25,10 @@ struct state {
|
||||
gui_size in_len;
|
||||
gui_bool in_active;
|
||||
|
||||
/* menubar state */
|
||||
gui_bool file_open;
|
||||
gui_bool edit_open;
|
||||
|
||||
/* widgets state */
|
||||
gui_size menu_item;
|
||||
gui_bool scaleable;
|
||||
@ -238,6 +242,62 @@ widget_panel(struct gui_panel_layout *panel, struct state *demo)
|
||||
|
||||
demo->item_current = gui_panel_selector(panel, items, LEN(items), demo->item_current);
|
||||
gui_panel_combo(panel, items, LEN(items), &demo->sel_item, 30, &demo->sel_act, gui_vec2(0,0));
|
||||
{
|
||||
/* progressbar combobox */
|
||||
gui_char buffer[64];
|
||||
struct gui_panel_layout combo;
|
||||
gui_int sum = (gui_int)(demo->combo_prog[0] + demo->combo_prog[1]);
|
||||
sum += (gui_int)(demo->combo_prog[2] + demo->combo_prog[3]);
|
||||
sprintf(buffer, "%d", sum);
|
||||
gui_panel_combo_begin(panel, &combo, buffer, &demo->prog_act, gui_vec2(0,0));
|
||||
{
|
||||
gui_panel_row_dynamic(&combo, 30, 1);
|
||||
demo->combo_prog[0] = gui_panel_progress(&combo, demo->combo_prog[0], 100, gui_true);
|
||||
demo->combo_prog[1] = gui_panel_progress(&combo, demo->combo_prog[1], 100, gui_true);
|
||||
demo->combo_prog[2] = gui_panel_progress(&combo, demo->combo_prog[2], 100, gui_true);
|
||||
demo->combo_prog[3] = gui_panel_progress(&combo, demo->combo_prog[3], 100, gui_true);
|
||||
}
|
||||
gui_panel_combo_end(panel, &combo);
|
||||
}
|
||||
{
|
||||
/* color slider progressbar */
|
||||
gui_char buffer[32];
|
||||
struct gui_panel_layout combo;
|
||||
sprintf(buffer, "#%02x%02x%02x%02x", demo->combo_color.r, demo->combo_color.g,
|
||||
demo->combo_color.b, demo->combo_color.a);
|
||||
gui_panel_combo_begin(panel, &combo, buffer, &demo->col_act, gui_vec2(0,0));
|
||||
{
|
||||
int i;
|
||||
const char *color_names[] = {"R:", "G:", "B:", "A:"};
|
||||
gui_float ratios[] = {0.15f, 0.85f};
|
||||
gui_byte *iter = &demo->combo_color.r;
|
||||
gui_panel_row(&combo, GUI_DYNAMIC, 30, 2, ratios);
|
||||
for (i = 0; i < 4; ++i, iter++) {
|
||||
gui_float t = *iter;
|
||||
gui_panel_label(&combo, color_names[i], GUI_TEXT_LEFT);
|
||||
t = gui_panel_slider(&combo, 0, t, 255, 5);
|
||||
*iter = (gui_byte)t;
|
||||
}
|
||||
}
|
||||
gui_panel_combo_end(panel, &combo);
|
||||
}
|
||||
{
|
||||
/* checkbox combobox */
|
||||
struct gui_panel_layout combo;
|
||||
gui_char buffer[64];
|
||||
gui_int sum = demo->combo_sel[0] + demo->combo_sel[1];
|
||||
sum += demo->combo_sel[2] + demo->combo_sel[3];
|
||||
sprintf(buffer, "%d", sum);
|
||||
gui_panel_combo_begin(panel, &combo, buffer, &demo->box_act, gui_vec2(0,0));
|
||||
{
|
||||
gui_panel_row_dynamic(&combo, 30, 1);
|
||||
demo->combo_sel[0] = gui_panel_check(&combo, items[0], demo->combo_sel[0]);
|
||||
demo->combo_sel[1] = gui_panel_check(&combo, items[1], demo->combo_sel[1]);
|
||||
demo->combo_sel[2] = gui_panel_check(&combo, items[2], demo->combo_sel[2]);
|
||||
demo->combo_sel[3] = gui_panel_check(&combo, items[3], demo->combo_sel[3]);
|
||||
}
|
||||
gui_panel_combo_end(panel, &combo);
|
||||
}
|
||||
demo->spinner= gui_panel_spinner(panel, 0, demo->spinner, 250, 10, &demo->spinner_active);
|
||||
demo->in_len = gui_panel_edit(panel, demo->in_buf, demo->in_len, MAX_BUFFER,
|
||||
&demo->in_active, NULL, GUI_INPUT_DEFAULT);
|
||||
@ -460,7 +520,7 @@ init_demo(struct demo_gui *gui, struct gui_font *font)
|
||||
gui_panel_init(&gui->panel, 30, 30, 280, 530,
|
||||
GUI_PANEL_BORDER|GUI_PANEL_MOVEABLE|GUI_PANEL_SCALEABLE,
|
||||
&gui->queue, config, gui->input);
|
||||
gui_panel_init(&gui->sub, 400, 50, 220, 400,
|
||||
gui_panel_init(&gui->sub, 400, 50, 220, 180,
|
||||
GUI_PANEL_BORDER|GUI_PANEL_MOVEABLE|GUI_PANEL_SCALEABLE,
|
||||
&gui->queue, config, gui->input);
|
||||
|
||||
@ -544,11 +604,26 @@ run_demo(struct demo_gui *gui)
|
||||
static const char *shelfs[] = {"Histogram", "Lines"};
|
||||
enum {EASY, HARD};
|
||||
|
||||
/* first panel */
|
||||
gui_panel_begin(&layout, &gui->panel);
|
||||
{
|
||||
/* header */
|
||||
/* header + menubar */
|
||||
gui->running = !gui_panel_header(&layout, "Demo",
|
||||
GUI_CLOSEABLE|GUI_MINIMIZABLE, GUI_CLOSEABLE, GUI_HEADER_RIGHT);
|
||||
gui_panel_menubar_begin(&layout);
|
||||
{
|
||||
const gui_char *file_items[] = {"Open", "Close", "Quit"};
|
||||
const gui_char *edit_items[] = {"Copy", "Cut", "Delete", "Paste"};
|
||||
gui_panel_row_begin(&layout, GUI_STATIC, 30, 2);
|
||||
gui_panel_row_push(&layout, config->font.width(config->font.userdata, "_FILE_", 6));
|
||||
gui_panel_menu(&layout, "FILE", file_items, LEN(file_items), 30, 100,
|
||||
&state->file_open, gui_vec2(0,0));
|
||||
gui_panel_row_push(&layout, config->font.width(config->font.userdata, "_EDIT_", 6));
|
||||
gui_panel_menu(&layout, "EDIT", edit_items, LEN(edit_items), 30, 100,
|
||||
&state->edit_open, gui_vec2(0,0));
|
||||
gui_panel_row_end(&layout);
|
||||
}
|
||||
gui_panel_menubar_end(&layout);
|
||||
|
||||
/* panel style configuration */
|
||||
if (gui_panel_layout_push(&layout, GUI_LAYOUT_TAB, "Style", &state->config_tab))
|
||||
@ -602,7 +677,6 @@ run_demo(struct demo_gui *gui)
|
||||
gui_panel_popup_end(&layout, &tab);
|
||||
}
|
||||
|
||||
|
||||
/* shelf + graphes */
|
||||
gui_panel_row_dynamic(&layout, 180, 1);
|
||||
state->shelf_selection = gui_panel_shelf_begin(&layout, &tab, shelfs,
|
||||
@ -627,9 +701,9 @@ run_demo(struct demo_gui *gui)
|
||||
}
|
||||
gui_panel_end(&layout, &gui->panel);
|
||||
|
||||
/* second panel */
|
||||
gui_panel_begin(&layout, &gui->sub);
|
||||
{
|
||||
const char *items[] = {"Fist", "Pistol", "Railgun", "BFG"};
|
||||
gui_panel_header(&layout, "Show", GUI_CLOSEABLE, 0, GUI_HEADER_LEFT);
|
||||
gui_panel_row_static(&layout, 30, 80, 1);
|
||||
if (gui_panel_button_text(&layout, "button", GUI_BUTTON_DEFAULT)) {
|
||||
@ -638,63 +712,6 @@ run_demo(struct demo_gui *gui)
|
||||
gui_panel_row_dynamic(&layout, 30, 2);
|
||||
if (gui_panel_option(&layout, "easy", state->op == EASY)) state->op = EASY;
|
||||
if (gui_panel_option(&layout, "hard", state->op == HARD)) state->op = HARD;
|
||||
gui_panel_row_dynamic(&layout, 30, 3);
|
||||
{
|
||||
/* progressbar combobox */
|
||||
gui_char buffer[64];
|
||||
struct gui_panel_layout combo;
|
||||
gui_int sum = (gui_int)(state->combo_prog[0] + state->combo_prog[1]);
|
||||
sum += (gui_int)(state->combo_prog[2] + state->combo_prog[3]);
|
||||
sprintf(buffer, "%d", sum);
|
||||
gui_panel_combo_begin(&layout, &combo, buffer, &state->prog_act, gui_vec2(0,0));
|
||||
{
|
||||
gui_panel_row_dynamic(&combo, 30, 1);
|
||||
state->combo_prog[0] = gui_panel_progress(&combo, state->combo_prog[0], 100, gui_true);
|
||||
state->combo_prog[1] = gui_panel_progress(&combo, state->combo_prog[1], 100, gui_true);
|
||||
state->combo_prog[2] = gui_panel_progress(&combo, state->combo_prog[2], 100, gui_true);
|
||||
state->combo_prog[3] = gui_panel_progress(&combo, state->combo_prog[3], 100, gui_true);
|
||||
}
|
||||
gui_panel_combo_end(&layout, &combo);
|
||||
}
|
||||
{
|
||||
/* color slider progressbar */
|
||||
gui_char buffer[32];
|
||||
struct gui_panel_layout combo;
|
||||
sprintf(buffer, "#%02x%02x%02x%02x", state->combo_color.r, state->combo_color.g,
|
||||
state->combo_color.b, state->combo_color.a);
|
||||
gui_panel_combo_begin(&layout, &combo, buffer, &state->col_act, gui_vec2(0,0));
|
||||
{
|
||||
int i;
|
||||
const char *color_names[] = {"R:", "G:", "B:", "A:"};
|
||||
gui_float ratios[] = {0.15f, 0.85f};
|
||||
gui_byte *iter = &state->combo_color.r;
|
||||
gui_panel_row(&combo, GUI_DYNAMIC, 30, 2, ratios);
|
||||
for (i = 0; i < 4; ++i, iter++) {
|
||||
gui_float t = *iter;
|
||||
gui_panel_label(&combo, color_names[i], GUI_TEXT_LEFT);
|
||||
t = gui_panel_slider(&combo, 0, t, 255, 5);
|
||||
*iter = (gui_byte)t;
|
||||
}
|
||||
}
|
||||
gui_panel_combo_end(&layout, &combo);
|
||||
}
|
||||
{
|
||||
/* checkbox combobox */
|
||||
struct gui_panel_layout combo;
|
||||
gui_char buffer[64];
|
||||
gui_int sum = state->combo_sel[0] + state->combo_sel[1];
|
||||
sum += state->combo_sel[2] + state->combo_sel[3];
|
||||
sprintf(buffer, "%d", sum);
|
||||
gui_panel_combo_begin(&layout, &combo, buffer, &state->box_act, gui_vec2(0,0));
|
||||
{
|
||||
gui_panel_row_dynamic(&combo, 30, 1);
|
||||
state->combo_sel[0] = gui_panel_check(&combo, items[0], state->combo_sel[0]);
|
||||
state->combo_sel[1] = gui_panel_check(&combo, items[1], state->combo_sel[1]);
|
||||
state->combo_sel[2] = gui_panel_check(&combo, items[2], state->combo_sel[2]);
|
||||
state->combo_sel[3] = gui_panel_check(&combo, items[3], state->combo_sel[3]);
|
||||
}
|
||||
gui_panel_combo_end(&layout, &combo);
|
||||
}
|
||||
}
|
||||
gui_panel_end(&layout, &gui->sub);
|
||||
}
|
||||
|
270
gui.c
270
gui.c
@ -1691,7 +1691,7 @@ gui_button_text(struct gui_command_buffer *o, gui_float x, gui_float y,
|
||||
t.background = bg_color;
|
||||
t.foreground = font_color;
|
||||
gui_text(o, inner.x, inner.y, inner.w, inner.h, string, gui_strsiz(string),
|
||||
&t, GUI_TEXT_CENTERED, f);
|
||||
&t, b->alignment, f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2400,10 +2400,11 @@ gui_scrollbar_vertical(struct gui_command_buffer *out, gui_float x, gui_float y,
|
||||
if (!out || !s) return 0;
|
||||
|
||||
/* scrollbar background */
|
||||
|
||||
scroll_w = MAX(w, 1);
|
||||
scroll_h = MAX(h, 2 * scroll_w);
|
||||
gui_command_buffer_push_rect(out,x,y,scroll_w,scroll_h,s->rounding,s->background);
|
||||
if (target <= scroll_h) return 0;
|
||||
gui_command_buffer_push_rect(out,x,y,scroll_w,scroll_h,s->rounding,s->background);
|
||||
|
||||
/* setup and execute up/down button */
|
||||
button.border = 1;
|
||||
@ -2492,8 +2493,8 @@ gui_scrollbar_horizontal(struct gui_command_buffer *out, gui_float x, gui_float
|
||||
/* scrollbar background */
|
||||
scroll_h = MAX(h, 1);
|
||||
scroll_w = MAX(w, 2 * scroll_h);
|
||||
gui_command_buffer_push_rect(out,x,y,scroll_w,scroll_h,s->rounding,s->background);
|
||||
if (target <= scroll_w) return 0;
|
||||
gui_command_buffer_push_rect(out,x,y,scroll_w,scroll_h,s->rounding,s->background);
|
||||
|
||||
/* setup and execute up/down button */
|
||||
button.border = 1;
|
||||
@ -2754,7 +2755,7 @@ gui_config_default_color(struct gui_config *config)
|
||||
config->colors[GUI_COLOR_TEXT] = gui_rgba(135, 135, 135, 255);
|
||||
config->colors[GUI_COLOR_PANEL] = gui_rgba(45, 45, 45, 255);
|
||||
config->colors[GUI_COLOR_HEADER] = gui_rgba(40, 40, 40, 255);
|
||||
config->colors[GUI_COLOR_BORDER] = gui_rgba(25, 25, 25, 255);
|
||||
config->colors[GUI_COLOR_BORDER] = gui_rgba(65, 65, 65, 255);
|
||||
config->colors[GUI_COLOR_BUTTON] = gui_rgba(50, 50, 50, 255);
|
||||
config->colors[GUI_COLOR_BUTTON_HOVER] = gui_rgba(35, 35, 35, 255);
|
||||
config->colors[GUI_COLOR_BUTTON_TOGGLE] = gui_rgba(35, 35, 35, 255);
|
||||
@ -3111,7 +3112,11 @@ gui_panel_begin(struct gui_panel_layout *layout, struct gui_panel *panel)
|
||||
if (!(layout->flags & GUI_PANEL_DYNAMIC) && layout->valid) {
|
||||
gui_command_buffer_push_rect(out, layout->x, layout->y,
|
||||
layout->w, layout->h, 0, c->colors[GUI_COLOR_PANEL]);
|
||||
} else layout->footer_h = scaler_size.y + item_padding.y;
|
||||
} else{
|
||||
layout->footer_h = scaler_size.y + item_padding.y;
|
||||
gui_command_buffer_push_rect(out, layout->x, layout->y, layout->w,
|
||||
layout->row.height, 0, c->colors[GUI_COLOR_PANEL]);
|
||||
}
|
||||
|
||||
/* draw top header border line */
|
||||
if (layout->flags & GUI_PANEL_BORDER) {
|
||||
@ -3387,24 +3392,27 @@ gui_panel_end(struct gui_panel_layout *layout, struct gui_panel *panel)
|
||||
/* update the current Y-position to point over the last added widget */
|
||||
layout->at_y += layout->row.height;
|
||||
if (layout->valid && layout->flags & GUI_PANEL_DYNAMIC) {
|
||||
struct gui_rect bounds;
|
||||
/* calculate the dynamic panel footer bounds */
|
||||
layout->height = MIN(layout->at_y - layout->y, layout->h);
|
||||
|
||||
/* draw the correct footer */
|
||||
footer_x = panel->x;
|
||||
footer_w = panel->w;
|
||||
footer_y = panel->y + layout->height + layout->footer_h;
|
||||
footer_w = panel->w + scrollbar_size;
|
||||
if (layout->flags & GUI_PANEL_COMBO_MENU)
|
||||
footer_y = panel->y + layout->height;
|
||||
else footer_y = panel->y + layout->height + layout->footer_h;
|
||||
gui_command_buffer_push_rect(out, footer_x, footer_y, footer_w, layout->footer_h,
|
||||
0, config->colors[GUI_COLOR_PANEL]);
|
||||
|
||||
/* draw the space between the last widget and the end of the dynamic panel */
|
||||
bounds.x = layout->x;
|
||||
bounds.y = panel->y + layout->height;
|
||||
bounds.w = layout->width;
|
||||
bounds.h = layout->row.height;
|
||||
gui_command_buffer_push_rect(out, bounds.x, bounds.y, bounds.w, bounds.h,
|
||||
0, config->colors[GUI_COLOR_PANEL]);
|
||||
if (!(layout->flags & GUI_PANEL_COMBO_MENU)) {
|
||||
struct gui_rect bounds;
|
||||
bounds.x = layout->x;
|
||||
bounds.y = panel->y + layout->height;
|
||||
bounds.w = layout->width;
|
||||
bounds.h = layout->row.height;
|
||||
gui_command_buffer_push_rect(out, bounds.x, bounds.y, bounds.w, bounds.h,
|
||||
0, config->colors[GUI_COLOR_PANEL]);
|
||||
}
|
||||
}
|
||||
|
||||
/* scrollbars */
|
||||
@ -3891,7 +3899,7 @@ gui_panel_header(struct gui_panel_layout *layout, const char *title,
|
||||
}
|
||||
|
||||
void
|
||||
gui_panel_menu_begin(struct gui_panel_layout *layout)
|
||||
gui_panel_menubar_begin(struct gui_panel_layout *layout)
|
||||
{
|
||||
GUI_ASSERT(layout);
|
||||
if (!layout || layout->flags & GUI_PANEL_HIDDEN || layout->flags & GUI_PANEL_MINIMIZED)
|
||||
@ -3900,12 +3908,11 @@ gui_panel_menu_begin(struct gui_panel_layout *layout)
|
||||
layout->menu.y = layout->y + layout->header.h;
|
||||
layout->menu.w = layout->width;
|
||||
layout->menu.offset = layout->offset;
|
||||
layout->offset.x = 0;
|
||||
layout->offset.y = 0;
|
||||
}
|
||||
|
||||
void
|
||||
gui_panel_menu_end(struct gui_panel_layout *layout)
|
||||
gui_panel_menubar_end(struct gui_panel_layout *layout)
|
||||
{
|
||||
const struct gui_config *c;
|
||||
struct gui_command_buffer *out;
|
||||
@ -3968,8 +3975,8 @@ gui_panel_layout(struct gui_panel_layout *layout, gui_float height, gui_size col
|
||||
layout->row.height = height + item_spacing.y;
|
||||
layout->row.item_offset = 0;
|
||||
if (layout->flags & GUI_PANEL_DYNAMIC)
|
||||
gui_command_buffer_push_rect(out, layout->at_x, layout->at_y,
|
||||
layout->width, height + panel_padding.y, 0, *color);
|
||||
gui_command_buffer_push_rect(out, layout->x, layout->at_y,
|
||||
layout->w, height + panel_padding.y, 0, *color);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4310,7 +4317,7 @@ gui_panel_layout_push(struct gui_panel_layout *layout,
|
||||
panel_padding = gui_config_property(config, GUI_PROPERTY_PADDING);
|
||||
|
||||
/* calculate header bounds and draw background */
|
||||
gui_panel_layout(layout, config->font.height + 4 * item_padding.y, 1);
|
||||
gui_panel_row_dynamic(layout, config->font.height + 4 * item_padding.y, 1);
|
||||
gui_panel_alloc_space(&header, layout);
|
||||
if (type == GUI_LAYOUT_TAB)
|
||||
gui_command_buffer_push_rect(out, header.x, header.y, header.w, header.h,
|
||||
@ -4543,6 +4550,7 @@ gui_panel_button(struct gui_button *button, struct gui_rect *bounds,
|
||||
config = layout->config;
|
||||
item_padding = gui_config_property(config, GUI_PROPERTY_ITEM_PADDING);
|
||||
button->border = 1;
|
||||
button->alignment = GUI_TEXT_CENTERED;
|
||||
button->rounding = config->rounding[GUI_ROUNDING_BUTTON];
|
||||
button->padding.x = item_padding.x;
|
||||
button->padding.y = item_padding.y;
|
||||
@ -4574,12 +4582,12 @@ gui_panel_button_text(struct gui_panel_layout *layout, const char *str,
|
||||
str, behavior, &button, i, &config->font);
|
||||
}
|
||||
|
||||
static gui_bool
|
||||
gui_panel_button__fitting(struct gui_panel_layout *layout, const char *str,
|
||||
enum gui_button_behavior behavior)
|
||||
gui_bool
|
||||
gui_panel_button_fitting(struct gui_panel_layout *layout, const char *str,
|
||||
enum gui_text_align align, enum gui_button_behavior behavior)
|
||||
{
|
||||
struct gui_rect bounds;
|
||||
struct gui_button button;
|
||||
struct gui_rect bounds;
|
||||
const struct gui_config *config;
|
||||
const struct gui_input *i;
|
||||
enum gui_widget_state state;
|
||||
@ -4591,12 +4599,12 @@ gui_panel_button__fitting(struct gui_panel_layout *layout, const char *str,
|
||||
config = layout->config;
|
||||
padding = gui_config_property(config, GUI_PROPERTY_PADDING);
|
||||
bounds.x -= padding.x;
|
||||
bounds.y -= padding.y;
|
||||
bounds.w += 2 * padding.x;
|
||||
|
||||
button.border = 0;
|
||||
button.padding.x = 0;
|
||||
button.padding.y = 0;
|
||||
button.alignment = align;
|
||||
button.background = config->colors[GUI_COLOR_PANEL];
|
||||
button.foreground = config->colors[GUI_COLOR_PANEL];
|
||||
button.content = config->colors[GUI_COLOR_TEXT];
|
||||
@ -5479,6 +5487,55 @@ gui_panel_popup_end(struct gui_panel_layout *parent, struct gui_panel_layout *po
|
||||
return pan.offset;
|
||||
}
|
||||
|
||||
static gui_bool
|
||||
gui_panel_popup_nonblock_begin(struct gui_panel_layout *parent,
|
||||
struct gui_panel_layout *popup, gui_bool *active, gui_bool is_active,
|
||||
struct gui_rect body, struct gui_vec2 offset)
|
||||
{
|
||||
/* deactivate popup if user clicked outside the popup*/
|
||||
const struct gui_input *in = parent->input;
|
||||
if (in && *active) {
|
||||
gui_bool inbody = GUI_INBOX(in->mouse_clicked_pos.x,
|
||||
in->mouse_clicked_pos.y, body.x, body.y, body.w, body.h);
|
||||
gui_bool inpanel = GUI_INBOX(in->mouse_clicked_pos.x,
|
||||
in->mouse_clicked_pos.y, parent->x, parent->y, parent->w, parent->h);
|
||||
if ((in->mouse_down && in->mouse_clicked) && !inbody && inpanel)
|
||||
is_active = gui_false;
|
||||
}
|
||||
|
||||
/* recalculate body bounds into local panel position */
|
||||
body.x -= (parent->at_x - 2);
|
||||
body.y -= parent->clip.y;
|
||||
body.w -= 4;
|
||||
|
||||
/* if active create popup otherwise deactive the panel layout */
|
||||
if (!is_active && *active) {
|
||||
gui_panel_popup_begin(parent, popup, GUI_POPUP_DYNAMIC, body, offset);
|
||||
gui_panel_popup_close(popup);
|
||||
popup->flags &= ~(gui_flags)GUI_PANEL_MINIMIZED;
|
||||
} else if (!is_active && !*active) {
|
||||
*active = is_active;
|
||||
popup->flags |= GUI_PANEL_MINIMIZED;
|
||||
return gui_false;
|
||||
} else{
|
||||
gui_panel_popup_begin(parent, popup, GUI_POPUP_DYNAMIC, body, offset);
|
||||
popup->flags &= ~(gui_flags)GUI_PANEL_MINIMIZED;
|
||||
}
|
||||
*active = is_active;
|
||||
return gui_true;
|
||||
}
|
||||
|
||||
static void
|
||||
gui_panel_popup_nonblock_end(struct gui_panel_layout *parent, struct gui_panel_layout *popup)
|
||||
{
|
||||
GUI_ASSERT(parent);
|
||||
GUI_ASSERT(popup);
|
||||
if (!parent || !popup) return;
|
||||
if (!parent->valid) return;
|
||||
if (!(popup->flags & GUI_PANEL_MINIMIZED))
|
||||
gui_panel_popup_end(parent, popup);
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------
|
||||
*
|
||||
@ -5490,10 +5547,10 @@ void
|
||||
gui_panel_combo_begin(struct gui_panel_layout *parent, struct gui_panel_layout *combo,
|
||||
const char *selected, gui_bool *active, struct gui_vec2 offset)
|
||||
{
|
||||
const struct gui_input *in;
|
||||
const struct gui_config *config;
|
||||
struct gui_command_buffer *out;
|
||||
struct gui_vec2 item_padding;
|
||||
const struct gui_input *in;
|
||||
struct gui_rect header;
|
||||
gui_float button_w;
|
||||
gui_bool is_active;
|
||||
@ -5506,11 +5563,11 @@ gui_panel_combo_begin(struct gui_panel_layout *parent, struct gui_panel_layout *
|
||||
if (!parent->valid || !gui_panel_widget(&header, parent))
|
||||
goto failed;
|
||||
|
||||
in = (parent->flags & GUI_PANEL_ROM) ? 0 : parent->input;
|
||||
is_active = *active;
|
||||
out = parent->buffer;
|
||||
config = parent->config;
|
||||
item_padding = gui_config_property(config, GUI_PROPERTY_ITEM_PADDING);
|
||||
in = parent->input;
|
||||
|
||||
/* draw combo box header background and border */
|
||||
gui_command_buffer_push_rect(out, header.x, header.y, header.w, header.h, 0,
|
||||
@ -5521,13 +5578,18 @@ gui_panel_combo_begin(struct gui_panel_layout *parent, struct gui_panel_layout *
|
||||
{
|
||||
/* print currently selected item */
|
||||
gui_size text_len;
|
||||
struct gui_rect clip;
|
||||
struct gui_rect label;
|
||||
label.x = header.x + item_padding.x;
|
||||
label.y = header.y + item_padding.y;
|
||||
label.w = header.w - (header.h + 2 * item_padding.x);
|
||||
label.h = header.h - 2 * item_padding.y;
|
||||
text_len = gui_strsiz(selected);
|
||||
gui_command_buffer_push_scissor(out, label.x, label.y, label.w, label.h);
|
||||
|
||||
/* set correct clipping rectangle and draw title */
|
||||
gui_unify(&clip, &parent->clip, label.x, label.y, label.x + label.w,
|
||||
label.y + label.h);
|
||||
gui_command_buffer_push_scissor(out, clip.x, clip.y, clip.w, clip.h);
|
||||
gui_command_buffer_push_text(out, label.x, label.y, label.w, label.h,
|
||||
selected, text_len, &config->font, config->colors[GUI_COLOR_PANEL],
|
||||
config->colors[GUI_COLOR_TEXT]);
|
||||
@ -5567,36 +5629,9 @@ gui_panel_combo_begin(struct gui_panel_layout *parent, struct gui_panel_layout *
|
||||
body.w = header.w;
|
||||
body.y = header.y + header.h;
|
||||
body.h = (parent->y + parent->h) - body.y;
|
||||
|
||||
/* deactivate popup if user clicked outside the popup*/
|
||||
if (in && *active) {
|
||||
gui_bool inbody = GUI_INBOX(in->mouse_clicked_pos.x,
|
||||
in->mouse_clicked_pos.y, body.x, body.y, body.w, body.h);
|
||||
gui_bool inpanel = GUI_INBOX(in->mouse_clicked_pos.x,
|
||||
in->mouse_clicked_pos.y, parent->x, parent->y, parent->w, parent->h);
|
||||
if ((in->mouse_down && in->mouse_clicked) && !inbody && inpanel)
|
||||
is_active = gui_false;
|
||||
}
|
||||
|
||||
/* recalculate body bounds into local panel position */
|
||||
body.x = header.x - (parent->at_x - 2);
|
||||
body.y = (header.y + header.h) - parent->clip.y;
|
||||
body.w -= 4;
|
||||
|
||||
/* if active create popup otherwise deactive the panel layout */
|
||||
if (!is_active && *active) {
|
||||
gui_panel_popup_begin(parent, combo, GUI_POPUP_DYNAMIC, body, offset);
|
||||
gui_panel_popup_close(combo);
|
||||
combo->flags &= ~(gui_flags)GUI_PANEL_MINIMIZED;
|
||||
} else if (!is_active && !*active) {
|
||||
*active = is_active;
|
||||
combo->flags |= GUI_PANEL_MINIMIZED;
|
||||
if (!gui_panel_popup_nonblock_begin(parent, combo, active, is_active, body, offset))
|
||||
goto failed;
|
||||
} else{
|
||||
gui_panel_popup_begin(parent, combo, GUI_POPUP_DYNAMIC, body, offset);
|
||||
combo->flags &= ~(gui_flags)GUI_PANEL_MINIMIZED;
|
||||
}
|
||||
*active = is_active;
|
||||
combo->flags |= GUI_PANEL_COMBO_MENU;
|
||||
}
|
||||
return;
|
||||
|
||||
@ -5616,8 +5651,7 @@ gui_panel_combo_end(struct gui_panel_layout *parent, struct gui_panel_layout *co
|
||||
if (!parent || !combo) return gui_vec2(0,0);
|
||||
if (!parent->valid)
|
||||
return combo->offset;
|
||||
if (!(combo->flags & GUI_PANEL_MINIMIZED))
|
||||
gui_panel_popup_end(parent, combo);
|
||||
gui_panel_popup_nonblock_end(parent, combo);
|
||||
return combo->offset;
|
||||
}
|
||||
|
||||
@ -5636,7 +5670,6 @@ gui_panel_combo(struct gui_panel_layout *layout, const char **entries,
|
||||
{
|
||||
gui_size i;
|
||||
struct gui_panel_layout combo;
|
||||
|
||||
GUI_ASSERT(layout);
|
||||
GUI_ASSERT(entries);
|
||||
GUI_ASSERT(current);
|
||||
@ -5648,7 +5681,7 @@ gui_panel_combo(struct gui_panel_layout *layout, const char **entries,
|
||||
gui_panel_row_dynamic(&combo, row_height, 1);
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (i == *current) continue;
|
||||
if (gui_panel_button__fitting(&combo, entries[i], GUI_BUTTON_DEFAULT)) {
|
||||
if (gui_panel_button_fitting(&combo, entries[i], GUI_TEXT_LEFT, GUI_BUTTON_DEFAULT)) {
|
||||
gui_panel_combo_close(&combo);
|
||||
*active = gui_false;
|
||||
*current = i;
|
||||
@ -5656,6 +5689,117 @@ gui_panel_combo(struct gui_panel_layout *layout, const char **entries,
|
||||
}
|
||||
gui_panel_combo_end(layout, &combo);
|
||||
}
|
||||
/*
|
||||
* -------------------------------------------------------------
|
||||
*
|
||||
* MENU
|
||||
*
|
||||
* --------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
gui_panel_menu_begin(struct gui_panel_layout *parent, struct gui_panel_layout *menu,
|
||||
const char *title, gui_float width, gui_bool *active, struct gui_vec2 offset)
|
||||
{
|
||||
const struct gui_input *in;
|
||||
const struct gui_config *config;
|
||||
struct gui_rect header;
|
||||
gui_bool is_active;
|
||||
|
||||
GUI_ASSERT(parent);
|
||||
GUI_ASSERT(menu);
|
||||
GUI_ASSERT(title);
|
||||
GUI_ASSERT(active);
|
||||
if (!parent || !menu || !title || !active) return;
|
||||
if (!parent->valid) goto failed;
|
||||
|
||||
is_active = *active;
|
||||
in = parent->input;
|
||||
config = parent->config;
|
||||
{
|
||||
struct gui_button button;
|
||||
gui_panel_button(&button, &header, parent);
|
||||
button.background = (is_active) ? config->colors[GUI_COLOR_BUTTON_HOVER]:
|
||||
config->colors[GUI_COLOR_PANEL];
|
||||
button.foreground = (is_active) ? config->colors[GUI_COLOR_BORDER]:
|
||||
config->colors[GUI_COLOR_PANEL];
|
||||
button.content = config->colors[GUI_COLOR_TEXT];
|
||||
button.highlight = (is_active) ? config->colors[GUI_COLOR_BUTTON_HOVER]:
|
||||
config->colors[GUI_COLOR_PANEL];
|
||||
button.highlight_content = config->colors[GUI_COLOR_TEXT];
|
||||
button.rounding = config->rounding[GUI_ROUNDING_BUTTON];
|
||||
if (gui_button_text(parent->buffer, header.x, header.y, header.w, header.h,
|
||||
title, GUI_BUTTON_DEFAULT, &button, in, &config->font))
|
||||
is_active = !is_active;
|
||||
}
|
||||
{
|
||||
/* calculate the maximum height of the menu */
|
||||
struct gui_rect body;
|
||||
body.x = header.x;
|
||||
body.w = width;
|
||||
body.y = header.y + header.h;
|
||||
body.h = (parent->y + parent->h) - body.y;
|
||||
if (!gui_panel_popup_nonblock_begin(parent, menu, active,
|
||||
is_active, body, offset)) goto failed;
|
||||
menu->flags |= GUI_PANEL_COMBO_MENU;
|
||||
}
|
||||
return;
|
||||
|
||||
failed:
|
||||
menu->valid = gui_false;
|
||||
menu->config = parent->config;
|
||||
menu->buffer = parent->buffer;
|
||||
menu->input = parent->input;
|
||||
menu->queue = parent->queue;
|
||||
}
|
||||
|
||||
void
|
||||
gui_panel_menu_close(struct gui_panel_layout *menu)
|
||||
{
|
||||
GUI_ASSERT(menu);
|
||||
if (!menu) return;
|
||||
gui_panel_popup_close(menu);
|
||||
}
|
||||
|
||||
struct gui_vec2
|
||||
gui_panel_menu_end(struct gui_panel_layout *parent, struct gui_panel_layout *menu)
|
||||
{
|
||||
GUI_ASSERT(parent);
|
||||
GUI_ASSERT(menu);
|
||||
if (!parent || !menu) return gui_vec2(0,0);
|
||||
if (!parent->valid)
|
||||
return menu->offset;
|
||||
gui_panel_popup_nonblock_end(parent, menu);
|
||||
return menu->offset;
|
||||
}
|
||||
|
||||
gui_int
|
||||
gui_panel_menu(struct gui_panel_layout *layout, const char *title,
|
||||
const char **entries, gui_size count, gui_size row_height,
|
||||
gui_float width, gui_bool *active, struct gui_vec2 scrollbar)
|
||||
{
|
||||
gui_size i;
|
||||
gui_int sel = -1;
|
||||
struct gui_panel_layout menu;
|
||||
|
||||
GUI_ASSERT(layout);
|
||||
GUI_ASSERT(entries);
|
||||
GUI_ASSERT(title);
|
||||
GUI_ASSERT(active);
|
||||
if (!layout || !layout->valid || !entries || !title || !active) return -1;
|
||||
if (!count) return -1;
|
||||
|
||||
gui_panel_menu_begin(layout, &menu, title, width, active, scrollbar);
|
||||
gui_panel_row_dynamic(&menu, row_height, 1);
|
||||
for (i = 0; i < count; ++i) {
|
||||
if (gui_panel_button_fitting(&menu, entries[i], GUI_TEXT_CENTERED, GUI_BUTTON_DEFAULT)) {
|
||||
gui_panel_combo_close(&menu);
|
||||
*active = gui_false;
|
||||
sel = (gui_int)i;
|
||||
}
|
||||
}
|
||||
gui_panel_menu_end(layout, &menu);
|
||||
return sel;
|
||||
}
|
||||
|
||||
/*
|
||||
* -------------------------------------------------------------
|
||||
@ -5991,7 +6135,6 @@ gui_panel_shelf_begin(struct gui_panel_layout *parent, struct gui_panel_layout *
|
||||
GUI_ASSERT(active < size);
|
||||
if (!parent || !shelf || !tabs || active >= size)
|
||||
return active;
|
||||
|
||||
if (!parent->valid)
|
||||
goto failed;
|
||||
|
||||
@ -6024,6 +6167,7 @@ gui_panel_shelf_begin(struct gui_panel_layout *parent, struct gui_panel_layout *
|
||||
input = (parent->flags & GUI_PANEL_ROM) ? 0 : parent->input;
|
||||
item_width = (header_w - (gui_float)size) / (gui_float)size;
|
||||
button.border = 1;
|
||||
button.alignment = GUI_TEXT_CENTERED;
|
||||
button.rounding = 0;
|
||||
button.padding.x = item_padding.x;
|
||||
button.padding.y = item_padding.y;
|
||||
|
80
gui.h
80
gui.h
@ -1040,6 +1040,8 @@ struct gui_button {
|
||||
/* background color if mouse is over */
|
||||
struct gui_color highlight_content;
|
||||
/* content color if mouse is over */
|
||||
enum gui_text_align alignment;
|
||||
/* text alignment in the button */
|
||||
};
|
||||
|
||||
enum gui_toggle_type {
|
||||
@ -1774,8 +1776,9 @@ enum gui_panel_flags {
|
||||
* used to create perfectly content fitting panels as well */
|
||||
GUI_PANEL_ACTIVE = 0x10000,
|
||||
/* INTERNAL ONLY!: marks the panel as active, used by the panel stack */
|
||||
GUI_PANEL_TAB = 0x20000
|
||||
GUI_PANEL_TAB = 0x20000,
|
||||
/* INTERNAL ONLY!: Marks the panel as an subpanel of another panel(Groups/Tabs/Shelf)*/
|
||||
GUI_PANEL_COMBO_MENU = 0x40000
|
||||
};
|
||||
|
||||
struct gui_panel {
|
||||
@ -2016,8 +2019,8 @@ void gui_panel_end(struct gui_panel_layout*, struct gui_panel*);
|
||||
gui_panel_header_title -- adds the title of the panel into the header
|
||||
gui_panel_header_end -- finishes the header build up process
|
||||
gui_panel_header -- short cut version of the header build up process
|
||||
gui_panel_menu_begin -- marks the beginning of the menubar building process
|
||||
gui_panel_menu_end -- marks the end the menubar build up process
|
||||
gui_panel_menubar_begin -- marks the beginning of the menubar building process
|
||||
gui_panel_menubar_end -- marks the end the menubar build up process
|
||||
*/
|
||||
enum gui_panel_header_flags {
|
||||
GUI_CLOSEABLE = 0x01,
|
||||
@ -2117,9 +2120,9 @@ gui_flags gui_panel_header(struct gui_panel_layout*, const char *title,
|
||||
- flags indicating which icons should be drawn to the header
|
||||
- flags indicating which icons should notify if clicked
|
||||
*/
|
||||
void gui_panel_menu_begin(struct gui_panel_layout*);
|
||||
void gui_panel_menubar_begin(struct gui_panel_layout*);
|
||||
/* this function begins the panel menubar build up process */
|
||||
void gui_panel_menu_end(struct gui_panel_layout*);
|
||||
void gui_panel_menubar_end(struct gui_panel_layout*);
|
||||
/* this function ends the panel menubar build up process */
|
||||
/*
|
||||
* --------------------------------------------------------------
|
||||
@ -2129,9 +2132,9 @@ void gui_panel_menu_end(struct gui_panel_layout*);
|
||||
The layout API is for positioning of widget inside a panel. In general there
|
||||
are three different ways to position widget. The first one is a table with
|
||||
fixed size columns. This like the other three comes in two flavors. First
|
||||
the scaleable with as a ration of the panel width and the other is a
|
||||
the scaleable width as a ratio of the panel width and the other is a
|
||||
non-scaleable fixed pixel value for static panels.
|
||||
Since sometimes widgets with different size in a row is needed another set
|
||||
Since sometimes widgets with different sizes in a row is needed another set
|
||||
of row layout has been added. The first set is for dynamically size widgets
|
||||
in an immediate mode API which sets each size of a widget directly before
|
||||
it is called or a retain mode API which stores the size of every widget as
|
||||
@ -2364,6 +2367,19 @@ gui_bool gui_panel_button_text(struct gui_panel_layout*, const char*,
|
||||
/* this function creates a text button
|
||||
Input:
|
||||
- button label describing the button
|
||||
- string label
|
||||
- button behavior with either default or repeater behavior
|
||||
Output:
|
||||
- gui_true if the button was transistioned from unpressed to pressed with
|
||||
default button behavior or pressed if repeater behavior.
|
||||
*/
|
||||
gui_bool gui_panel_button_fitting(struct gui_panel_layout *layout,
|
||||
const char *str, enum gui_text_align align,
|
||||
enum gui_button_behavior behavior);
|
||||
/* this function creates a fitting text button for combo boxes and menus
|
||||
Input:
|
||||
- button label describing the button
|
||||
- alignment of the text inside the button
|
||||
- button behavior with either default or repeater behavior
|
||||
Output:
|
||||
- gui_true if the button was transistioned from unpressed to pressed with
|
||||
@ -2776,6 +2792,53 @@ void gui_panel_combo_close(struct gui_panel_layout *combo);
|
||||
struct gui_vec2 gui_panel_combo_end(struct gui_panel_layout *parent,
|
||||
struct gui_panel_layout *comob);
|
||||
/* this function ends the combobox build up process */
|
||||
/*
|
||||
* --------------------------------------------------------------
|
||||
* MENU
|
||||
* --------------------------------------------------------------
|
||||
MENU
|
||||
The menu widget provides a overlapping popup panel which can
|
||||
be opened/closed by clicking on the menu button. It is normally
|
||||
placed at the top of the panel and is independent of the parent
|
||||
scrollbar offset. But if needed the menu can even be placed inside the panel.
|
||||
|
||||
menu widget API
|
||||
gui_panel_menu_begin -- begins the menu item build up processs
|
||||
gui_panel_menu_push -- adds a item into the menu
|
||||
gui_panel_menu_end -- ends the menu item build up process
|
||||
gui_panel_menu -- shorthand retain mode array version
|
||||
*/
|
||||
gui_int gui_panel_menu(struct gui_panel_layout*, const gui_char *title,
|
||||
const char **entries, gui_size count, gui_size row_height,
|
||||
gui_float width, gui_bool *active, struct gui_vec2 scrollbar);
|
||||
/* this function creates a standart text based combobox
|
||||
Input:
|
||||
- parent panel layout the combo box will be placed into
|
||||
- string array of all items inside the menu
|
||||
- number of menu items inside the string array
|
||||
- the height of every widget inside the combobox
|
||||
- the current state of the menu
|
||||
- the scrollbar offset of the panel scrollbar
|
||||
Output:
|
||||
- updated state of the menu
|
||||
- index of the selected menu item or -1 otherwise
|
||||
*/
|
||||
void gui_panel_menu_begin(struct gui_panel_layout *parent,
|
||||
struct gui_panel_layout *menu, const char *title,
|
||||
gui_float width, gui_bool *active, struct gui_vec2 offset);
|
||||
/* this function begins the menu build up process
|
||||
Input:
|
||||
- parent panel layout the menu will be placed into
|
||||
- ouput menu panel layout
|
||||
- title of the menu to
|
||||
- the current state of the menu with either gui_true (open) or gui_false else
|
||||
- the current scrollbar offset of the menu popup panel
|
||||
*/
|
||||
void gui_panel_menu_close(struct gui_panel_layout *menu);
|
||||
/* this function closes a opened menu */
|
||||
struct gui_vec2 gui_panel_menu_end(struct gui_panel_layout *parent,
|
||||
struct gui_panel_layout *menu);
|
||||
/* this function ends the menu build up process */
|
||||
/*
|
||||
* --------------------------------------------------------------
|
||||
* TREE
|
||||
@ -2893,8 +2956,7 @@ struct gui_vec2 gui_panel_tree_end(struct gui_panel_layout*, struct gui_tree*);
|
||||
* TABLE
|
||||
* --------------------------------------------------------------
|
||||
TABLE
|
||||
|
||||
USAGE
|
||||
Temporary table widget. Needs to be rewritten to be actually useful.
|
||||
|
||||
Table widget API
|
||||
gui_panel_table_begin -- begin table build up process
|
||||
|
BIN
screen/demo.png
BIN
screen/demo.png
Binary file not shown.
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 58 KiB |
Loading…
Reference in New Issue
Block a user