From 8b06cb31ba3820f81100a6bd0c11301b0777c5c5 Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Wed, 8 Mar 2023 11:09:28 +0100 Subject: [PATCH] [ui, styling] - Put all styling calls _before_ the styled box. - Renamed full pattern matching API to ui_style_match_next_before/after - Helper to style next box only (ui_style_next()) --- examples/ui_style_test/main.c | 78 +++++++------- src/ui.c | 187 +++++++++++++++------------------- src/ui.h | 24 ++--- 3 files changed, 129 insertions(+), 160 deletions(-) diff --git a/examples/ui_style_test/main.c b/examples/ui_style_test/main.c index 9f3fd80..95db83b 100644 --- a/examples/ui_style_test/main.c +++ b/examples/ui_style_test/main.c @@ -262,34 +262,43 @@ int main() { root = ui_box_top(); -// ui_label("Hello, world!"); - - ui_pattern pattern = {0}; ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = str8_lit("b")}); ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("foo")}); - ui_style_next(pattern, - &(ui_style){.fontSize = 36}, - UI_STYLE_FONT_SIZE); + ui_style_match_next_before(pattern, &(ui_style){.fontSize = 36}, UI_STYLE_FONT_SIZE); - ui_style_next(ui_pattern_all(), - &defaultStyle, - UI_STYLE_FONT - |UI_STYLE_FONT_SIZE - |UI_STYLE_COLOR - |UI_STYLE_BORDER_SIZE - |UI_STYLE_BORDER_COLOR - |UI_STYLE_SIZE_X - |UI_STYLE_SIZE_Y - |UI_STYLE_LAYOUT); + ui_style_match_next_before(ui_pattern_all(), + &defaultStyle, + UI_STYLE_FONT + |UI_STYLE_FONT_SIZE + |UI_STYLE_COLOR + |UI_STYLE_BORDER_SIZE + |UI_STYLE_BORDER_COLOR + |UI_STYLE_SIZE_WIDTH + |UI_STYLE_SIZE_HEIGHT + |UI_STYLE_LAYOUT); + + + pattern = (ui_pattern){0}; + ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = str8_lit("c")}); + ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("button")}); + ui_style_match_next_after(pattern, + &(ui_style){.bgColor = {1, 0.5, 0.5, 1}}, + UI_STYLE_BG_COLOR); + + pattern = (ui_pattern){0}; + ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = str8_lit("c")}); + ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("button")}); + ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_STATUS, .op = UI_SEL_AND, .status = UI_ACTIVE|UI_HOVER}); + ui_style_match_next_after(pattern, + &(ui_style){.bgColor = {0.5, 1, 0.5, 1}}, + UI_STYLE_BG_COLOR); ui_container("a", defaultFlags) { ui_pattern pattern = {0}; ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = str8_lit("b")}); - ui_style_next(pattern, - &(ui_style){.fontSize = 22}, - UI_STYLE_FONT_SIZE); + ui_style_match_next_before(pattern, &(ui_style){.fontSize = 22}, UI_STYLE_FONT_SIZE); ui_container("b", defaultFlags) { @@ -309,25 +318,22 @@ int main() printf("clicked button f\n"); } - ui_style_next(ui_pattern_owner(), - &(ui_style){.size.width = {UI_SIZE_PARENT, 1}, + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, .size.height = {UI_SIZE_PIXELS, 20, 0}}, - UI_STYLE_SIZE_X|UI_STYLE_SIZE_Y); + UI_STYLE_SIZE); static f32 slider1 = 0; ui_slider("slider1", 0.3, &slider1); - ui_style_next(ui_pattern_owner(), - &(ui_style){.size.width = {UI_SIZE_PARENT, 1}, + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, .size.height = {UI_SIZE_PIXELS, 20, 0}}, - UI_STYLE_SIZE_X|UI_STYLE_SIZE_Y); + UI_STYLE_SIZE); static f32 slider2 = 0; ui_slider("slider2", 0.3, &slider2); - ui_style_next(ui_pattern_owner(), - &(ui_style){.size.width = {UI_SIZE_PARENT, 1}, + ui_style_next(&(ui_style){.size.width = {UI_SIZE_PARENT, 1}, .size.height = {UI_SIZE_PIXELS, 20}}, - UI_STYLE_SIZE_X|UI_STYLE_SIZE_Y); + UI_STYLE_SIZE); static f32 slider3 = 0; ui_slider("slider3", 0.3, &slider3); @@ -336,22 +342,6 @@ int main() ui_tag_next("foo"); ui_label("label d"); } - - pattern = (ui_pattern){0}; - ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = str8_lit("c")}); - ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("button")}); - ui_style_prev(pattern, - &(ui_style){.bgColor = {1, 0.5, 0.5, 1}}, - UI_STYLE_BG_COLOR); - - pattern = (ui_pattern){0}; - ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TEXT, .text = str8_lit("c")}); - ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_TAG, .tag = ui_tag_make("button")}); - ui_pattern_push(mem_scratch(), &pattern, (ui_selector){.kind = UI_SEL_STATUS, .op = UI_SEL_AND, .status = UI_ACTIVE|UI_HOVER}); - ui_style_prev(pattern, - &(ui_style){.bgColor = {0.5, 1, 0.5, 1}}, - UI_STYLE_BG_COLOR); - } if(printDebugStyle) { diff --git a/src/ui.c b/src/ui.c index 576fec1..396d40c 100644 --- a/src/ui.c +++ b/src/ui.c @@ -82,9 +82,8 @@ typedef struct ui_context ui_stack_elt* boxStack; ui_stack_elt* clipStack; - list_info nextBoxRules; - ui_box* lastBox; - + list_info nextBoxBeforeRules; + list_info nextBoxAfterRules; list_info nextBoxTags; u32 z; @@ -309,53 +308,6 @@ void ui_pattern_push(mem_arena* arena, ui_pattern* pattern, ui_selector selector ListAppend(&pattern->l, ©->listElt); } -void ui_style_next(ui_pattern pattern, ui_style* style, ui_style_mask mask) -{ - ui_context* ui = ui_get_context(); - if(ui) - { - ui_style_rule* rule = mem_arena_alloc_type(&ui->frameArena, ui_style_rule); - rule->pattern = pattern; - rule->mask = mask; - rule->style = mem_arena_alloc_type(&ui->frameArena, ui_style); - *rule->style = *style; - - ListAppend(&ui->nextBoxRules, &rule->boxElt); - } -} - -void ui_style_prev(ui_pattern pattern, ui_style* style, ui_style_mask mask) -{ - ui_context* ui = ui_get_context(); - if(ui && ui->lastBox) - { - ui_style_rule* rule = mem_arena_alloc_type(&ui->frameArena, ui_style_rule); - rule->pattern = pattern; - rule->mask = mask; - rule->style = mem_arena_alloc_type(&ui->frameArena, ui_style); - *rule->style = *style; - - ListAppend(&ui->lastBox->afterRules, &rule->boxElt); - rule->owner = ui->lastBox; - } -} - -void ui_style_box_before(ui_box* box, ui_pattern pattern, ui_style* style, ui_style_mask mask) -{ - ui_context* ui = ui_get_context(); - if(ui) - { - ui_style_rule* rule = mem_arena_alloc_type(&ui->frameArena, ui_style_rule); - rule->pattern = pattern; - rule->mask = mask; - rule->style = mem_arena_alloc_type(&ui->frameArena, ui_style); - *rule->style = *style; - - ListAppend(&box->beforeRules, &rule->boxElt); - rule->owner = box; - } -} - ui_pattern ui_pattern_all(void) { ui_context* ui = ui_get_context(); @@ -372,21 +324,40 @@ ui_pattern ui_pattern_owner(void) return(pattern); } -void ui_box_set_size(ui_box* box, ui_axis axis, ui_size_kind kind, f32 value, f32 strictness) +void ui_style_match_next_before(ui_pattern pattern, ui_style* style, ui_style_mask mask) { - ui_style style = {0}; - style.size.s[axis] = (ui_size){kind, value, strictness}; - ui_style_mask mask = (axis == UI_AXIS_X) ? UI_STYLE_SIZE_X : UI_STYLE_SIZE_Y; - ui_style_box_before(box, ui_pattern_owner(), &style, mask); + ui_context* ui = ui_get_context(); + if(ui) + { + ui_style_rule* rule = mem_arena_alloc_type(&ui->frameArena, ui_style_rule); + rule->pattern = pattern; + rule->mask = mask; + rule->style = mem_arena_alloc_type(&ui->frameArena, ui_style); + *rule->style = *style; + + ListAppend(&ui->nextBoxBeforeRules, &rule->boxElt); + } } -void ui_box_set_layout(ui_box* box, ui_axis axis, ui_align alignX, ui_align alignY) +void ui_style_match_next_after(ui_pattern pattern, ui_style* style, ui_style_mask mask) { - ui_style style = {.layout = {axis, .align.x = alignX, .align.y = alignY}}; - ui_style_box_before(box, ui_pattern_owner(), &style, UI_STYLE_LAYOUT); + ui_context* ui = ui_get_context(); + if(ui) + { + ui_style_rule* rule = mem_arena_alloc_type(&ui->frameArena, ui_style_rule); + rule->pattern = pattern; + rule->mask = mask; + rule->style = mem_arena_alloc_type(&ui->frameArena, ui_style); + *rule->style = *style; + + ListAppend(&ui->nextBoxAfterRules, &rule->boxElt); + } } -void ui_apply_style_with_mask(ui_style* dst, ui_style* src, ui_style_mask mask); +void ui_style_next(ui_style* style, ui_style_mask mask) +{ + ui_style_match_next_before(ui_pattern_owner(), style, mask); +} //----------------------------------------------------------------------------- // ui boxes @@ -487,16 +458,19 @@ ui_box* ui_box_make_str8(str8 string, ui_flags flags) box->tags = ui->nextBoxTags; ui->nextBoxTags = (list_info){0}; - box->beforeRules = ui->nextBoxRules; + box->beforeRules = ui->nextBoxBeforeRules; for_each_in_list(&box->beforeRules, rule, ui_style_rule, boxElt) { rule->owner = box; } - ui->nextBoxRules = (list_info){0}; + ui->nextBoxBeforeRules = (list_info){0}; - box->afterRules = (list_info){0}; - - ui->lastBox = box; + box->afterRules = ui->nextBoxAfterRules; + for_each_in_list(&box->afterRules, rule, ui_style_rule, boxElt) + { + rule->owner = box; + } + ui->nextBoxAfterRules = (list_info){0}; return(box); } @@ -517,9 +491,6 @@ ui_box* ui_box_end(void) ui_box_pop(); - //NOTE: set last box so that subsequent ui_style_prev() targets this box - ui->lastBox = box; - return(box); } @@ -678,7 +649,7 @@ void ui_box_compute_styling(ui_context* ui, ui_box* box) } else { - if(flags & UI_STYLE_ANIMATE_SIZE_X) + if(flags & UI_STYLE_ANIMATE_SIZE_WIDTH) { ui_animate_ui_size(ui, &box->style.size.s[UI_AXIS_X], targetStyle->size.s[UI_AXIS_X], animationTime); } @@ -687,7 +658,7 @@ void ui_box_compute_styling(ui_context* ui, ui_box* box) box->style.size.s[UI_AXIS_X] = targetStyle->size.s[UI_AXIS_X]; } - if(flags & UI_STYLE_ANIMATE_SIZE_Y) + if(flags & UI_STYLE_ANIMATE_SIZE_HEIGHT) { ui_animate_ui_size(ui, &box->style.size.s[UI_AXIS_Y], targetStyle->size.s[UI_AXIS_Y], animationTime); } @@ -759,11 +730,11 @@ void ui_box_compute_styling(ui_context* ui, ui_box* box) void ui_apply_style_with_mask(ui_style* dst, ui_style* src, ui_style_mask mask) { - if(mask & UI_STYLE_SIZE_X) + if(mask & UI_STYLE_SIZE_WIDTH) { dst->size.s[UI_AXIS_X] = src->size.s[UI_AXIS_X]; } - if(mask & UI_STYLE_SIZE_Y) + if(mask & UI_STYLE_SIZE_HEIGHT) { dst->size.s[UI_AXIS_Y] = src->size.s[UI_AXIS_Y]; } @@ -1349,23 +1320,22 @@ void ui_begin_frame(u32 width, u32 height) ui->root = ui_box_begin("_root_", 0); *ui->root->targetStyle = defaultStyle; - ui_style_next(ui_pattern_owner(), - &(ui_style){.layout = {UI_AXIS_Y, UI_ALIGN_START, UI_ALIGN_START}, + ui_style_next(&(ui_style){.layout = {UI_AXIS_Y, UI_ALIGN_START, UI_ALIGN_START}, .floating = {true, true}, .floatTarget = {0, 0}}, UI_STYLE_LAYOUT | UI_STYLE_FLOAT_X | UI_STYLE_FLOAT_Y); ui_box* contents = ui_box_make("_contents_", 0); - ui_style_next(ui_pattern_owner(), - &(ui_style){.layout = {UI_AXIS_Y, UI_ALIGN_START, UI_ALIGN_START}, + ui_style_next(&(ui_style){.layout = {UI_AXIS_Y, UI_ALIGN_START, UI_ALIGN_START}, .floating = {true, true}, .floatTarget = {0, 0}}, UI_STYLE_LAYOUT | UI_STYLE_FLOAT_X | UI_STYLE_FLOAT_Y); ui->overlay = ui_box_make("_overlay_", 0); - ui->nextBoxRules = (list_info){0}; + ui->nextBoxBeforeRules = (list_info){0}; + ui->nextBoxAfterRules = (list_info){0}; ui->nextBoxTags = (list_info){0}; ui_box_push(contents); @@ -1430,10 +1400,9 @@ void ui_cleanup(void) ui_sig ui_label_str8(str8 label) { - ui_style_next(ui_pattern_all(), - &(ui_style){.size.width = {UI_SIZE_TEXT, 0, 0}, + ui_style_next(&(ui_style){.size.width = {UI_SIZE_TEXT, 0, 0}, .size.height = {UI_SIZE_TEXT, 0, 0}}, - UI_STYLE_SIZE_X | UI_STYLE_SIZE_Y); + UI_STYLE_SIZE_WIDTH | UI_STYLE_SIZE_HEIGHT); ui_flags flags = UI_FLAG_CLIP | UI_FLAG_DRAW_TEXT; @@ -1459,14 +1428,14 @@ ui_sig ui_button_str8(str8 label) .borderSize = 2, .roundness = 10}; - ui_style_mask defaultMask = UI_STYLE_SIZE_X - | UI_STYLE_SIZE_Y + ui_style_mask defaultMask = UI_STYLE_SIZE_WIDTH + | UI_STYLE_SIZE_HEIGHT | UI_STYLE_BG_COLOR | UI_STYLE_BORDER_COLOR | UI_STYLE_BORDER_SIZE | UI_STYLE_ROUNDNESS; - ui_style_next(ui_pattern_all(), &defaultStyle, defaultMask); + ui_style_next(&defaultStyle, defaultMask); ui_style activeStyle = {.bgColor = {0.3, 0.3, 0.3, 1}, .borderColor = {0.2, 0.2, 0.2, 1}, @@ -1479,7 +1448,7 @@ ui_sig ui_button_str8(str8 label) &activePattern, (ui_selector){.kind = UI_SEL_STATUS, .status = UI_ACTIVE|UI_HOVER}); - ui_style_next(activePattern, &activeStyle, activeMask); + ui_style_match_next_before(activePattern, &activeStyle, activeMask); ui_flags flags = UI_FLAG_CLICKABLE | UI_FLAG_CLIP @@ -1522,55 +1491,65 @@ ui_sig ui_button(const char* label) ui_box* ui_slider(const char* label, f32 thumbRatio, f32* scrollValue) { + ui_style_match_next_before(ui_pattern_all(), &(ui_style){0}, UI_STYLE_LAYOUT); ui_box* frame = ui_box_begin(label, 0); { - ui_style_box_before(frame, ui_pattern_all(), &(ui_style){0}, UI_STYLE_LAYOUT); + f32 beforeRatio = (*scrollValue) * (1. - thumbRatio); + f32 afterRatio = (1. - *scrollValue) * (1. - thumbRatio); ui_axis trackAxis = (frame->rect.w > frame->rect.h) ? UI_AXIS_X : UI_AXIS_Y; ui_axis secondAxis = (trackAxis == UI_AXIS_Y) ? UI_AXIS_X : UI_AXIS_Y; - f32 roundness = 0.5*frame->rect.c[2+secondAxis]; f32 animationTime = 0.5; - ui_style trackStyle = {.bgColor = {0.5, 0.5, 0.5, 1}, - .roundness = roundness}; - ui_style thumbStyle = {.bgColor = {0.3, 0.3, 0.3, 1}, + ui_style trackStyle = {.size.width = {UI_SIZE_PARENT, 1}, + .size.height = {UI_SIZE_PARENT, 1}, + .layout.axis = trackAxis, + .layout.align.x = UI_ALIGN_START, + .layout.align.y = UI_ALIGN_START, + .bgColor = {0.5, 0.5, 0.5, 1}, .roundness = roundness}; - ui_style_mask styleMask = UI_STYLE_BG_COLOR | UI_STYLE_ROUNDNESS; + ui_style beforeStyle = trackStyle; + beforeStyle.size.s[trackAxis] = (ui_size){UI_SIZE_PARENT, beforeRatio}; + + ui_style afterStyle = trackStyle; + afterStyle.size.s[trackAxis] = (ui_size){UI_SIZE_PARENT, afterRatio}; + + ui_style thumbStyle = trackStyle; + thumbStyle.size.s[trackAxis] = (ui_size){UI_SIZE_PARENT, thumbRatio}; + thumbStyle.bgColor = (mg_color){0.3, 0.3, 0.3, 1}; + + ui_style_mask styleMask = UI_STYLE_SIZE_WIDTH + | UI_STYLE_SIZE_HEIGHT + | UI_STYLE_LAYOUT + | UI_STYLE_BG_COLOR + | UI_STYLE_ROUNDNESS; ui_flags trackFlags = UI_FLAG_CLIP | UI_FLAG_DRAW_BACKGROUND | UI_FLAG_HOT_ANIMATION | UI_FLAG_ACTIVE_ANIMATION; + ui_style_next(&trackStyle, styleMask); ui_box* track = ui_box_begin("track", trackFlags); - ui_style_box_before(track, ui_pattern_owner(), &trackStyle, styleMask); - - ui_box_set_size(track, trackAxis, UI_SIZE_PARENT, 1., 0); - ui_box_set_size(track, secondAxis, UI_SIZE_PARENT, 1., 0); - ui_box_set_layout(track, trackAxis, UI_ALIGN_START, UI_ALIGN_START); - - f32 beforeRatio = (*scrollValue) * (1. - thumbRatio); - f32 afterRatio = (1. - *scrollValue) * (1. - thumbRatio); + ui_style_next(&beforeStyle, UI_STYLE_SIZE_WIDTH|UI_STYLE_SIZE_HEIGHT); ui_box* beforeSpacer = ui_box_make("before", 0); - ui_box_set_size(beforeSpacer, trackAxis, UI_SIZE_PARENT, beforeRatio, 0); - ui_box_set_size(beforeSpacer, secondAxis, UI_SIZE_PARENT, 1., 0); + ui_flags thumbFlags = UI_FLAG_CLICKABLE | UI_FLAG_DRAW_BACKGROUND | UI_FLAG_HOT_ANIMATION | UI_FLAG_ACTIVE_ANIMATION; + ui_style_next(&thumbStyle, styleMask); ui_box* thumb = ui_box_make("thumb", thumbFlags); - ui_style_box_before(thumb, ui_pattern_owner(), &thumbStyle, styleMask); - ui_box_set_size(thumb, trackAxis, UI_SIZE_PARENT, thumbRatio, 0); - ui_box_set_size(thumb, secondAxis, UI_SIZE_PARENT, 1., 0); + + ui_style_next(&afterStyle, UI_STYLE_SIZE_WIDTH|UI_STYLE_SIZE_HEIGHT); ui_box* afterSpacer = ui_box_make("after", 0); - ui_box_set_size(afterSpacer, trackAxis, UI_SIZE_PARENT, afterRatio, 0); - ui_box_set_size(afterSpacer, secondAxis, UI_SIZE_PARENT, 1., 0); + ui_box_end(); //NOTE: interaction diff --git a/src/ui.h b/src/ui.h index f2baf48..26ffaa5 100644 --- a/src/ui.h +++ b/src/ui.h @@ -105,8 +105,8 @@ typedef union ui_box_size ui_size s[UI_AXIS_COUNT]; } ui_box_size; -typedef enum { UI_STYLE_ANIMATE_SIZE_X = 1<<1, - UI_STYLE_ANIMATE_SIZE_Y = 1<<2, +typedef enum { UI_STYLE_ANIMATE_SIZE_WIDTH = 1<<1, + UI_STYLE_ANIMATE_SIZE_HEIGHT = 1<<2, UI_STYLE_ANIMATE_COLOR = 1<<3, UI_STYLE_ANIMATE_BG_COLOR = 1<<4, UI_STYLE_ANIMATE_BORDER_COLOR = 1<<5, @@ -137,8 +137,8 @@ typedef u64 ui_style_mask; enum { UI_STYLE_NONE = 0, - UI_STYLE_SIZE_X = 1<<1, - UI_STYLE_SIZE_Y = 1<<2, + UI_STYLE_SIZE_WIDTH = 1<<1, + UI_STYLE_SIZE_HEIGHT = 1<<2, UI_STYLE_LAYOUT_AXIS = 1<<3, UI_STYLE_LAYOUT_ALIGN_X = 1<<4, UI_STYLE_LAYOUT_ALIGN_Y = 1<<5, @@ -158,6 +158,9 @@ enum UI_STYLE_ANIMATION_FLAGS = 1<<19, //masks + UI_STYLE_SIZE = UI_STYLE_SIZE_WIDTH + | UI_STYLE_SIZE_HEIGHT, + UI_STYLE_LAYOUT = UI_STYLE_LAYOUT_AXIS | UI_STYLE_LAYOUT_ALIGN_X | UI_STYLE_LAYOUT_ALIGN_Y @@ -385,18 +388,15 @@ void ui_tag_next_str8(str8 string); //NOTE: styling API //WARN: You can use a pattern in multiple rules, but be aware that a pattern is references an underlying list of selectors, // hence pushing to a pattern also modifies rules in which the pattern was previously used! -void ui_pattern_push(mem_arena* arena, ui_pattern* pattern, ui_selector selector); -void ui_style_next(ui_pattern pattern, ui_style* style, ui_style_mask mask); -void ui_style_prev(ui_pattern pattern, ui_style* style, ui_style_mask mask); +void ui_apply_style_with_mask(ui_style* dst, ui_style* src, ui_style_mask mask); -// common patterns helpers +void ui_pattern_push(mem_arena* arena, ui_pattern* pattern, ui_selector selector); ui_pattern ui_pattern_all(void); ui_pattern ui_pattern_owner(void); -// single box styling helpers -void ui_box_set_size(ui_box* box, ui_axis axis, ui_size_kind kind, f32 value, f32 stricness); -void ui_box_set_layout(ui_box* box, ui_axis axis, ui_align alignX, ui_align alignY); -//... +void ui_style_next(ui_style* style, ui_style_mask mask); +void ui_style_match_next_before(ui_pattern pattern, ui_style* style, ui_style_mask mask); +void ui_style_match_next_after(ui_pattern pattern, ui_style* style, ui_style_mask mask); //------------------------------------------------------------------------- // Basic widget helpers