[ui] Allow styling overlay boxes (e.g. menu and drop-down list panels) locally.
- Added an UI_FLAG_OVERLAY flag. When we make a box with that flag set, it is added the an overlayList in the ui context. - After styling and static size pass, we reparent boxes in the overlayList to an overlay node just below the root node. - Layout and drawing works uniformly on the whole tree. Overlay boxes get drawn last and steal mouse hover from boxes underneath them.
This commit is contained in:
parent
9e41d2b6fc
commit
5455c2a52b
|
@ -518,6 +518,10 @@ int main()
|
||||||
UI_STYLE_SIZE);
|
UI_STYLE_SIZE);
|
||||||
widget_view("Test")
|
widget_view("Test")
|
||||||
{
|
{
|
||||||
|
ui_pattern pattern = {};
|
||||||
|
ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = STR8("panel")});
|
||||||
|
ui_style_match_after(pattern, &(ui_style){.bgColor = {0.3, 0.3, 1, 1}}, UI_STYLE_BG_COLOR);
|
||||||
|
|
||||||
static int selected = 0;
|
static int selected = 0;
|
||||||
str8 options[] = {STR8("option 1"),
|
str8 options[] = {STR8("option 1"),
|
||||||
STR8("option 2"),
|
STR8("option 2"),
|
||||||
|
|
50
src/ui.c
50
src/ui.c
|
@ -77,6 +77,7 @@ typedef struct ui_context
|
||||||
|
|
||||||
ui_box* root;
|
ui_box* root;
|
||||||
ui_box* overlay;
|
ui_box* overlay;
|
||||||
|
list_info overlayList;
|
||||||
ui_stack_elt* boxStack;
|
ui_stack_elt* boxStack;
|
||||||
ui_stack_elt* clipStack;
|
ui_stack_elt* clipStack;
|
||||||
|
|
||||||
|
@ -463,6 +464,11 @@ ui_box* ui_box_make_str8(str8 string, ui_flags flags)
|
||||||
list_append(&box->parent->children, &box->listElt);
|
list_append(&box->parent->children, &box->listElt);
|
||||||
box->parentClosed = box->parent->closed || box->parent->parentClosed;
|
box->parentClosed = box->parent->closed || box->parent->parentClosed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(box->flags & UI_FLAG_OVERLAY)
|
||||||
|
{
|
||||||
|
list_append(&ui->overlayList, &box->overlayElt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1269,8 +1275,20 @@ void ui_solve_layout(ui_context* ui)
|
||||||
list_info beforeRules = {0};
|
list_info beforeRules = {0};
|
||||||
list_info afterRules = {0};
|
list_info afterRules = {0};
|
||||||
|
|
||||||
|
//NOTE: style and compute static sizes
|
||||||
ui_styling_prepass(ui, ui->root, &beforeRules, &afterRules);
|
ui_styling_prepass(ui, ui->root, &beforeRules, &afterRules);
|
||||||
|
|
||||||
|
//NOTE: reparent overlay boxes
|
||||||
|
for_list(&ui->overlayList, box, ui_box, overlayElt)
|
||||||
|
{
|
||||||
|
if(box->parent)
|
||||||
|
{
|
||||||
|
list_remove(&box->parent->children, &box->listElt);
|
||||||
|
list_append(&ui->overlay->children, &box->listElt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//NOTE: compute layout
|
||||||
for(int axis=0; axis<UI_AXIS_COUNT; axis++)
|
for(int axis=0; axis<UI_AXIS_COUNT; axis++)
|
||||||
{
|
{
|
||||||
ui_layout_downward_dependent_size(ui, ui->root, axis);
|
ui_layout_downward_dependent_size(ui, ui->root, axis);
|
||||||
|
@ -1463,6 +1481,7 @@ void ui_begin_frame(ui_style* defaultStyle, ui_style_mask defaultMask)
|
||||||
UI_STYLE_LAYOUT | UI_STYLE_FLOAT_X | UI_STYLE_FLOAT_Y);
|
UI_STYLE_LAYOUT | UI_STYLE_FLOAT_X | UI_STYLE_FLOAT_Y);
|
||||||
|
|
||||||
ui->overlay = ui_box_make("_overlay_", 0);
|
ui->overlay = ui_box_make("_overlay_", 0);
|
||||||
|
ui->overlayList = (list_info){0};
|
||||||
|
|
||||||
ui->nextBoxBeforeRules = (list_info){0};
|
ui->nextBoxBeforeRules = (list_info){0};
|
||||||
ui->nextBoxAfterRules = (list_info){0};
|
ui->nextBoxAfterRules = (list_info){0};
|
||||||
|
@ -1980,21 +1999,22 @@ void ui_menu_bar_end(void)
|
||||||
ui_box_end(); // menu bar
|
ui_box_end(); // menu bar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ui_menu_begin(const char* label)
|
void ui_menu_begin(const char* label)
|
||||||
{
|
{
|
||||||
|
ui_box* container = ui_box_make(label, 0);
|
||||||
|
ui_box_push(container);
|
||||||
|
|
||||||
ui_style_next(&(ui_style){.size.width = {UI_SIZE_TEXT},
|
ui_style_next(&(ui_style){.size.width = {UI_SIZE_TEXT},
|
||||||
.size.height = {UI_SIZE_TEXT}},
|
.size.height = {UI_SIZE_TEXT}},
|
||||||
UI_STYLE_SIZE);
|
UI_STYLE_SIZE);
|
||||||
|
|
||||||
ui_box* button = ui_box_make(label, UI_FLAG_CLICKABLE | UI_FLAG_DRAW_TEXT);
|
ui_box* button = ui_box_make(label, UI_FLAG_CLICKABLE | UI_FLAG_DRAW_TEXT);
|
||||||
ui_box* bar = button->parent;
|
ui_box* bar = container->parent;
|
||||||
|
|
||||||
ui_sig sig = ui_box_sig(button);
|
ui_sig sig = ui_box_sig(button);
|
||||||
ui_sig barSig = ui_box_sig(bar);
|
ui_sig barSig = ui_box_sig(bar);
|
||||||
|
|
||||||
ui_context* ui = ui_get_context();
|
ui_context* ui = ui_get_context();
|
||||||
ui_box_push(ui->overlay);
|
|
||||||
|
|
||||||
ui_style style = {.size.width = {UI_SIZE_CHILDREN},
|
ui_style style = {.size.width = {UI_SIZE_CHILDREN},
|
||||||
.size.height = {UI_SIZE_CHILDREN},
|
.size.height = {UI_SIZE_CHILDREN},
|
||||||
|
@ -2013,11 +2033,12 @@ void ui_menu_begin(const char* label)
|
||||||
| UI_STYLE_LAYOUT
|
| UI_STYLE_LAYOUT
|
||||||
| UI_STYLE_BG_COLOR;
|
| UI_STYLE_BG_COLOR;
|
||||||
|
|
||||||
ui_flags flags = UI_FLAG_DRAW_BACKGROUND
|
ui_flags flags = UI_FLAG_OVERLAY
|
||||||
|
| UI_FLAG_DRAW_BACKGROUND
|
||||||
| UI_FLAG_DRAW_BORDER;
|
| UI_FLAG_DRAW_BORDER;
|
||||||
|
|
||||||
ui_style_next(&style, mask);
|
ui_style_next(&style, mask);
|
||||||
ui_box* menu = ui_box_make(label, flags);
|
ui_box* menu = ui_box_make("panel", flags);
|
||||||
|
|
||||||
if(ui_box_active(bar))
|
if(ui_box_active(bar))
|
||||||
{
|
{
|
||||||
|
@ -2047,7 +2068,7 @@ void ui_menu_begin(const char* label)
|
||||||
void ui_menu_end(void)
|
void ui_menu_end(void)
|
||||||
{
|
{
|
||||||
ui_box_pop(); // menu
|
ui_box_pop(); // menu
|
||||||
ui_box_pop(); // overlay;
|
ui_box_pop(); // container
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_sig ui_menu_button(const char* name)
|
ui_sig ui_menu_button(const char* name)
|
||||||
|
@ -2095,7 +2116,9 @@ ui_select_popup_info ui_select_popup(const char* name, ui_select_popup_info* inf
|
||||||
|
|
||||||
ui_context* ui = ui_get_context();
|
ui_context* ui = ui_get_context();
|
||||||
|
|
||||||
ui_box* button = ui_box_make(name,
|
ui_container(name, 0)
|
||||||
|
{
|
||||||
|
ui_box* button = ui_box_make("button",
|
||||||
UI_FLAG_CLICKABLE
|
UI_FLAG_CLICKABLE
|
||||||
|UI_FLAG_DRAW_BACKGROUND
|
|UI_FLAG_DRAW_BACKGROUND
|
||||||
|UI_FLAG_DRAW_BORDER
|
|UI_FLAG_DRAW_BORDER
|
||||||
|
@ -2143,12 +2166,14 @@ ui_select_popup_info ui_select_popup(const char* name, ui_select_popup_info* inf
|
||||||
|
|
||||||
ui_box* arrow = ui_box_make("arrow", UI_FLAG_DRAW_BACKGROUND|UI_FLAG_DRAW_PROC);
|
ui_box* arrow = ui_box_make("arrow", UI_FLAG_DRAW_BACKGROUND|UI_FLAG_DRAW_PROC);
|
||||||
ui_box_set_draw_proc(arrow, ui_select_popup_draw_arrow, 0);
|
ui_box_set_draw_proc(arrow, ui_select_popup_draw_arrow, 0);
|
||||||
|
|
||||||
} ui_box_pop();
|
} ui_box_pop();
|
||||||
|
|
||||||
ui_box_push(ui->overlay);
|
//panel
|
||||||
ui_box* panel = ui_box_make(name,
|
ui_box* panel = ui_box_make("panel",
|
||||||
UI_FLAG_DRAW_BACKGROUND
|
UI_FLAG_DRAW_BACKGROUND
|
||||||
|UI_FLAG_BLOCK_MOUSE);
|
|UI_FLAG_BLOCK_MOUSE
|
||||||
|
|UI_FLAG_OVERLAY);
|
||||||
|
|
||||||
//TODO: set width to max(button.w, max child...)
|
//TODO: set width to max(button.w, max child...)
|
||||||
f32 containerWidth = maximum(maxOptionWidth + 2*panel->style.layout.margin.x,
|
f32 containerWidth = maximum(maxOptionWidth + 2*panel->style.layout.margin.x,
|
||||||
|
@ -2204,7 +2229,6 @@ ui_select_popup_info ui_select_popup(const char* name, ui_select_popup_info* inf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui_box_pop();
|
ui_box_pop();
|
||||||
ui_box_pop();
|
|
||||||
|
|
||||||
if(ui_box_active(panel) && mp_mouse_pressed(MP_MOUSE_LEFT))
|
if(ui_box_active(panel) && mp_mouse_pressed(MP_MOUSE_LEFT))
|
||||||
{
|
{
|
||||||
|
@ -2214,10 +2238,8 @@ ui_select_popup_info ui_select_popup(const char* name, ui_select_popup_info* inf
|
||||||
{
|
{
|
||||||
ui_box_activate(panel);
|
ui_box_activate(panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
ui_box_set_closed(panel, !ui_box_active(panel));
|
ui_box_set_closed(panel, !ui_box_active(panel));
|
||||||
|
}
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
3
src/ui.h
3
src/ui.h
|
@ -263,6 +263,7 @@ typedef enum
|
||||||
UI_FLAG_DRAW_TEXT = (1<<11),
|
UI_FLAG_DRAW_TEXT = (1<<11),
|
||||||
UI_FLAG_DRAW_PROC = (1<<12),
|
UI_FLAG_DRAW_PROC = (1<<12),
|
||||||
|
|
||||||
|
UI_FLAG_OVERLAY = (1<<13),
|
||||||
} ui_flags;
|
} ui_flags;
|
||||||
|
|
||||||
struct ui_box
|
struct ui_box
|
||||||
|
@ -272,6 +273,8 @@ struct ui_box
|
||||||
list_info children;
|
list_info children;
|
||||||
ui_box* parent;
|
ui_box* parent;
|
||||||
|
|
||||||
|
list_elt overlayElt;
|
||||||
|
|
||||||
// keying and caching
|
// keying and caching
|
||||||
list_elt bucketElt;
|
list_elt bucketElt;
|
||||||
ui_key key;
|
ui_key key;
|
||||||
|
|
Loading…
Reference in New Issue