added single depth overlapping menus to panels

This commit is contained in:
vurtun 2015-08-13 15:57:28 +02:00
parent 1c23f982f5
commit 6709dc8875
4 changed files with 357 additions and 134 deletions

View File

@ -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
View File

@ -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
View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 58 KiB