[ui] menus widgets first draft

This commit is contained in:
Martin Fouilleul 2023-03-09 16:02:46 +01:00
parent feca7d1026
commit c362751c23
3 changed files with 128 additions and 68 deletions

View File

@ -289,10 +289,9 @@ int main()
ui_flags debugFlags = UI_FLAG_DRAW_BORDER; ui_flags debugFlags = UI_FLAG_DRAW_BORDER;
ui_box* root = 0; ui_box* root = 0;
ui_frame() ui_frame(&defaultStyle, defaultMask)
{ {
root = ui_box_top(); root = ui_box_top();
ui_style_match_before(ui_pattern_all(), &defaultStyle, defaultMask); ui_style_match_before(ui_pattern_all(), &defaultStyle, defaultMask);
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
@ -456,7 +455,29 @@ int main()
.size.height = {UI_SIZE_PARENT, 0.33}}, .size.height = {UI_SIZE_PARENT, 0.33}},
UI_STYLE_SIZE); UI_STYLE_SIZE);
widget_view("Menus") widget_view("Menus")
{} {
ui_menu_bar("Menu bar")
{
ui_menu("Menu 1")
{
if(ui_menu_button("Option 1.1").pressed)
{
printf("Pressed option 1.1\n");
}
ui_menu_button("Option 1.2");
ui_menu_button("Option 1.3");
ui_menu_button("Option 1.4");
}
ui_menu("Menu 2")
{
ui_menu_button("Option 2.1");
ui_menu_button("Option 2.2");
ui_menu_button("Option 2.3");
ui_menu_button("Option 2.4");
}
}
}
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1},
.size.height = {UI_SIZE_PARENT, 0.33}}, .size.height = {UI_SIZE_PARENT, 0.33}},

163
src/ui.c
View File

@ -625,7 +625,7 @@ void ui_animate_ui_size(ui_context* ui, ui_size* size, ui_size target, f32 anima
ui_animate_f32(ui, &size->relax, target.relax, animationTime); ui_animate_f32(ui, &size->relax, target.relax, animationTime);
} }
void ui_box_compute_styling(ui_context* ui, ui_box* box) void ui_box_animate_style(ui_context* ui, ui_box* box)
{ {
ui_style* targetStyle = box->targetStyle; ui_style* targetStyle = box->targetStyle;
DEBUG_ASSERT(targetStyle); DEBUG_ASSERT(targetStyle);
@ -751,7 +751,7 @@ void ui_apply_style_with_mask(ui_style* dst, ui_style* src, ui_style_mask mask)
} }
if(mask & UI_STYLE_LAYOUT_MARGIN_X) if(mask & UI_STYLE_LAYOUT_MARGIN_X)
{ {
dst->layout.margin.x = src->layout.margin.y; dst->layout.margin.x = src->layout.margin.x;
} }
if(mask & UI_STYLE_LAYOUT_MARGIN_Y) if(mask & UI_STYLE_LAYOUT_MARGIN_Y)
{ {
@ -840,7 +840,7 @@ bool ui_style_selector_match(ui_box* box, ui_style_rule* rule, ui_selector* sele
res = true; res = true;
if(selector->status & UI_HOVER) if(selector->status & UI_HOVER)
{ {
res = res && box->hot; res = res && ui_box_hovering(box, ui_mouse_position());
} }
if(selector->status & UI_ACTIVE) if(selector->status & UI_ACTIVE)
{ {
@ -928,7 +928,7 @@ void ui_styling_prepass(ui_context* ui, ui_box* box, list_info* before, list_inf
} }
//NOTE: compute static sizes //NOTE: compute static sizes
ui_box_compute_styling(ui, box); ui_box_animate_style(ui, box);
if(ui_box_hidden(box)) if(ui_box_hidden(box))
{ {
@ -937,7 +937,7 @@ void ui_styling_prepass(ui_context* ui, ui_box* box, list_info* before, list_inf
ui_style* style = &box->style; ui_style* style = &box->style;
mp_rect textBox = {}; mp_rect textBox = {0};
ui_size desiredSize[2] = {box->style.size.c[UI_AXIS_X], ui_size desiredSize[2] = {box->style.size.c[UI_AXIS_X],
box->style.size.c[UI_AXIS_Y]}; box->style.size.c[UI_AXIS_Y]};
@ -1345,7 +1345,7 @@ void ui_draw()
// frame begin/end // frame begin/end
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ui_begin_frame() void ui_begin_frame(ui_style* defaultStyle, ui_style_mask defaultMask)
{ {
ui_context* ui = ui_get_context(); ui_context* ui = ui_get_context();
@ -1361,12 +1361,18 @@ void ui_begin_frame()
vec2 size = mg_canvas_size(); vec2 size = mg_canvas_size();
ui_style defaultStyle = {0}; defaultMask &= UI_STYLE_COLOR
defaultStyle.size.c[UI_AXIS_X] = (ui_size){UI_SIZE_PIXELS, size.x}; | UI_STYLE_BG_COLOR
defaultStyle.size.c[UI_AXIS_Y] = (ui_size){UI_SIZE_PIXELS, size.y}; | UI_STYLE_BORDER_COLOR
| UI_STYLE_FONT
| UI_STYLE_FONT_SIZE;
ui_style_match_before(ui_pattern_all(), defaultStyle, defaultMask);
ui_style_next(&(ui_style){.size.width = {UI_SIZE_PIXELS, size.x},
.size.height = {UI_SIZE_PIXELS, size.y}},
UI_STYLE_SIZE);
ui->root = ui_box_begin("_root_", 0); ui->root = ui_box_begin("_root_", 0);
*ui->root->targetStyle = defaultStyle;
ui_style_mask contentStyleMask = UI_STYLE_SIZE ui_style_mask contentStyleMask = UI_STYLE_SIZE
| UI_STYLE_LAYOUT | UI_STYLE_LAYOUT
@ -1449,7 +1455,7 @@ void ui_cleanup(void)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Basic helpers // label
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
ui_sig ui_label_str8(str8 label) ui_sig ui_label_str8(str8 label)
@ -1471,6 +1477,9 @@ ui_sig ui_label(const char* label)
return(ui_label_str8(STR8((char*)label))); return(ui_label_str8(STR8((char*)label)));
} }
//------------------------------------------------------------------------------
// button
//------------------------------------------------------------------------------
ui_sig ui_button_str8(str8 label) ui_sig ui_button_str8(str8 label)
{ {
ui_context* ui = ui_get_context(); ui_context* ui = ui_get_context();
@ -1546,7 +1555,9 @@ ui_sig ui_button(const char* label)
return(ui_button_str8(STR8((char*)label))); return(ui_button_str8(STR8((char*)label)));
} }
//------------------------------------------------------------------------------
// slider / scrollbar
//------------------------------------------------------------------------------
ui_box* ui_slider(const char* label, f32 thumbRatio, f32* scrollValue) ui_box* ui_slider(const char* label, f32 thumbRatio, f32* scrollValue)
{ {
ui_style_match_before(ui_pattern_all(), &(ui_style){0}, UI_STYLE_LAYOUT); ui_style_match_before(ui_pattern_all(), &(ui_style){0}, UI_STYLE_LAYOUT);
@ -1661,6 +1672,9 @@ ui_box* ui_slider(const char* label, f32 thumbRatio, f32* scrollValue)
return(frame); return(frame);
} }
//------------------------------------------------------------------------------
// panels
//------------------------------------------------------------------------------
void ui_panel_begin(const char* str, ui_flags flags) void ui_panel_begin(const char* str, ui_flags flags)
{ {
ui_box* box = ui_box_begin(str, flags | UI_FLAG_CLIP | UI_FLAG_BLOCK_MOUSE); ui_box* box = ui_box_begin(str, flags | UI_FLAG_CLIP | UI_FLAG_BLOCK_MOUSE);
@ -1749,8 +1763,10 @@ void ui_panel_end(void)
ui_box_end(); ui_box_end();
} }
//------------------------------------------------------------------------------
// tooltips
//------------------------------------------------------------------------------
/* /*
ui_sig ui_tooltip_begin(const char* name) ui_sig ui_tooltip_begin(const char* name)
{ {
ui_context* ui = ui_get_context(); ui_context* ui = ui_get_context();
@ -1758,14 +1774,19 @@ ui_sig ui_tooltip_begin(const char* name)
vec2 p = ui_mouse_position(); vec2 p = ui_mouse_position();
ui_style style = {.size.width = {UI_SIZE_CHILDREN},
.size.height = {UI_SIZE_CHILDREN},
.floating.x = true,
.floating.y = true,
.floatTarget = {p.x, p.y}};
ui_style_mask mask = UI_STYLE_SIZE | UI_STYLE_FLOAT;
ui_style_next(&style, mask);
ui_flags flags = UI_FLAG_DRAW_BACKGROUND ui_flags flags = UI_FLAG_DRAW_BACKGROUND
| UI_FLAG_DRAW_BORDER; | UI_FLAG_DRAW_BORDER;
ui_box* tooltip = ui_box_make(name, flags); ui_box* tooltip = ui_box_make(name, flags);
// ui_box_set_size(tooltip, UI_AXIS_X, UI_SIZE_CHILDREN, 0, 0);
// ui_box_set_size(tooltip, UI_AXIS_Y, UI_SIZE_CHILDREN, 0, 0);
// ui_box_set_floating(tooltip, UI_AXIS_X, p.x);
// ui_box_set_floating(tooltip, UI_AXIS_Y, p.y);
ui_box_push(tooltip); ui_box_push(tooltip);
return(ui_box_sig(tooltip)); return(ui_box_sig(tooltip));
@ -1776,16 +1797,24 @@ void ui_tooltip_end(void)
ui_box_pop(); // tooltip ui_box_pop(); // tooltip
ui_box_pop(); // ui->overlay ui_box_pop(); // ui->overlay
} }
*/
//------------------------------------------------------------------------------
// Menus
//------------------------------------------------------------------------------
void ui_menu_bar_begin(const char* name) void ui_menu_bar_begin(const char* name)
{ {
ui_box* bar = ui_box_begin(name, UI_FLAG_DRAW_BACKGROUND); ui_style style = {.size.width = {UI_SIZE_PARENT, 1, 0},
// ui_box_set_size(bar, UI_AXIS_X, UI_SIZE_PARENT, 1., 0); .size.height = {UI_SIZE_CHILDREN},
// ui_box_set_size(bar, UI_AXIS_Y, UI_SIZE_CHILDREN, 0, 0); .layout.axis = UI_AXIS_X,
//ui_box_set_layout(bar, UI_AXIS_X, UI_ALIGN_START, UI_ALIGN_START); .layout.spacing = 20,};
ui_style_mask mask = UI_STYLE_SIZE
| UI_STYLE_LAYOUT_AXIS
| UI_STYLE_LAYOUT_SPACING;
// ui_push_size(UI_AXIS_X, UI_SIZE_TEXT, 0, 0); ui_style_next(&style, mask);
// ui_push_size(UI_AXIS_Y, UI_SIZE_TEXT, 0, 0); ui_box* bar = ui_box_begin(name, UI_FLAG_DRAW_BACKGROUND);
ui_sig sig = ui_box_sig(bar); ui_sig sig = ui_box_sig(bar);
if(!sig.hovering && mp_mouse_released(MP_MOUSE_LEFT)) if(!sig.hovering && mp_mouse_released(MP_MOUSE_LEFT))
@ -1793,18 +1822,19 @@ void ui_menu_bar_begin(const char* name)
ui_box_deactivate(bar); ui_box_deactivate(bar);
} }
} }
*/
void ui_menu_bar_end(void) void ui_menu_bar_end(void)
{ {
/*
ui_pop_size(UI_AXIS_X);
ui_pop_size(UI_AXIS_Y);
*/
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_style_next(&(ui_style){.size.width = {UI_SIZE_TEXT},
.size.height = {UI_SIZE_TEXT}},
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 = button->parent;
@ -1814,15 +1844,28 @@ void ui_menu_begin(const char* label)
ui_context* ui = ui_get_context(); ui_context* ui = ui_get_context();
ui_box_push(ui->overlay); ui_box_push(ui->overlay);
ui_style style = {.size.width = {UI_SIZE_CHILDREN},
.size.height = {UI_SIZE_CHILDREN},
.floating.x = true,
.floating.y = true,
.floatTarget = {button->rect.x,
button->rect.y + button->rect.h},
.layout.axis = UI_AXIS_Y,
.layout.spacing = 5,
.layout.margin.x = 0,
.layout.margin.y = 5,
.bgColor = {0.2, 0.2, 0.2, 1}};
ui_style_mask mask = UI_STYLE_SIZE
| UI_STYLE_FLOAT
| UI_STYLE_LAYOUT
| UI_STYLE_BG_COLOR;
ui_flags flags = UI_FLAG_DRAW_BACKGROUND ui_flags flags = UI_FLAG_DRAW_BACKGROUND
| UI_FLAG_DRAW_BORDER; | UI_FLAG_DRAW_BORDER;
ui_style_next(&style, mask);
ui_box* menu = ui_box_make(label, flags); ui_box* menu = ui_box_make(label, flags);
// ui_box_set_size(menu, UI_AXIS_X, UI_SIZE_CHILDREN, 0, 0);
// ui_box_set_size(menu, UI_AXIS_Y, UI_SIZE_CHILDREN, 0, 0);
// ui_box_set_floating(menu, UI_AXIS_X, button->rect.x);
// ui_box_set_floating(menu, UI_AXIS_Y, button->rect.y + button->rect.h);
//ui_box_set_layout(menu, UI_AXIS_Y, UI_ALIGN_START, UI_ALIGN_START);
if(ui_box_active(bar)) if(ui_box_active(bar))
{ {
@ -1855,43 +1898,38 @@ void ui_menu_end(void)
ui_box_pop(); // overlay; ui_box_pop(); // overlay;
} }
//////////////////////////////////////////////////////////////////////////////////////////////// ui_sig ui_menu_button(const char* name)
/*
void ui_edit_set_cursor_from_mouse(ui_context* gui, ui_style* style, f32 textStartX)
{ {
mp_graphics_font_extents fontExtents; ui_context* ui = ui_get_context();
mp_graphics_font_get_extents(gui->graphics, style->font, &fontExtents);
f32 fontScale = mp_graphics_font_get_scale_for_em_pixels(gui->graphics, style->font, style->fontSize);
//NOTE(martin): find cursor position from mouse position ui_style_next(&(ui_style){.size.width = {UI_SIZE_TEXT},
gui->editCursor = gui->editBufferSize; .size.height = {UI_SIZE_TEXT},
.layout.margin.x = 5,
.bgColor = {0, 0, 0, 0}},
UI_STYLE_SIZE
|UI_STYLE_LAYOUT_MARGIN_X
|UI_STYLE_BG_COLOR);
mp_graphics_text_extents glyphExtents[UI_EDIT_BUFFER_MAX_SIZE]; ui_pattern pattern = {};
mp_string32 codePoints = {gui->editBufferSize, gui->editBuffer}; ui_pattern_push(&ui->frameArena, &pattern, (ui_selector){.kind = UI_SEL_STATUS, .status = UI_HOVER});
mp_string32 glyphs = mp_graphics_font_push_glyph_indices(gui->graphics, style->font, mem_scratch(), codePoints);
mp_graphics_font_get_glyph_extents(gui->graphics, style->font, glyphs, glyphExtents);
mp_graphics_set_font(gui->graphics, style->font); ui_style style = {.bgColor = {0, 0, 1, 1}};
vec2 dimToFirst = mp_graphics_get_glyphs_dimensions(gui->graphics, mp_string32_slice(glyphs, 0, gui->firstDisplayedChar)); ui_style_mask mask = UI_STYLE_BG_COLOR;
ui_style_match_before(pattern, &style, mask);
ui_transform tr = ui_transform_top(gui); ui_flags flags = UI_FLAG_CLICKABLE
f32 x = gui->input.mouse.x + tr.x - textStartX; | UI_FLAG_CLIP
f32 glyphX = -dimToFirst.x; | UI_FLAG_DRAW_TEXT
| UI_FLAG_DRAW_BACKGROUND;
for(int i=0; i<gui->editBufferSize; i++) ui_box* box = ui_box_make(name, flags);
{ ui_sig sig = ui_box_sig(box);
if(x < glyphX + glyphExtents[i].xAdvance*fontScale/2) return(sig);
{
gui->editCursor = i;
return;
}
glyphX += glyphExtents[i].xAdvance*fontScale;
}
return;
} }
*/
//------------------------------------------------------------------------------
// text box
//------------------------------------------------------------------------------
str32 ui_edit_replace_selection_with_codepoints(ui_context* ui, str32 codepoints, str32 input) str32 ui_edit_replace_selection_with_codepoints(ui_context* ui, str32 codepoints, str32 input)
{ {
u32 start = minimum(ui->editCursor, ui->editMark); u32 start = minimum(ui->editCursor, ui->editMark);
@ -2325,7 +2363,6 @@ ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text)
f32 textMargin = 5; //TODO parameterize this margin! must be the same as in ui_text_box_render f32 textMargin = 5; //TODO parameterize this margin! must be the same as in ui_text_box_render
mg_font_extents extents = mg_font_get_scaled_extents(style->font, style->fontSize); mg_font_extents extents = mg_font_get_scaled_extents(style->font, style->fontSize);
// ui_box_set_size(frame, UI_AXIS_Y, UI_SIZE_PIXELS, extents.ascent+extents.descent+10, 1);
ui_sig sig = ui_box_sig(frame); ui_sig sig = ui_box_sig(frame);

View File

@ -331,11 +331,11 @@ void ui_init(void);
ui_context* ui_get_context(void); ui_context* ui_get_context(void);
void ui_set_context(ui_context* context); void ui_set_context(ui_context* context);
void ui_begin_frame(void); void ui_begin_frame(ui_style* defaultStyle, ui_style_mask mask);
void ui_end_frame(void); void ui_end_frame(void);
void ui_draw(void); void ui_draw(void);
#define ui_frame() defer_loop(ui_begin_frame(), ui_end_frame()) #define ui_frame(s, m) defer_loop(ui_begin_frame((s), (m)), ui_end_frame())
//------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------
// Box keys // Box keys
@ -449,6 +449,8 @@ void ui_menu_begin(const char* label);
void ui_menu_end(void); void ui_menu_end(void);
#define ui_menu(name) defer_loop(ui_menu_begin(name), ui_menu_end()) #define ui_menu(name) defer_loop(ui_menu_begin(name), ui_menu_end())
ui_sig ui_menu_button(const char* name);
typedef struct ui_text_box_result typedef struct ui_text_box_result
{ {
bool changed; bool changed;