better default style handling

This commit is contained in:
Alessandro Mauri 2025-07-06 23:13:16 +02:00
parent c1bf8e891b
commit 9afb0d2acd
9 changed files with 45 additions and 24 deletions

View File

@ -115,7 +115,6 @@ fn ElemEvents? Ctx.button_icon_id(&ctx, Id id, String icon, String on_icon, bool
}
// FIXME: this should be inside the style
const ushort DEFAULT_CHECKBOX_SIZE = 16;
macro Ctx.checkbox(&ctx, String desc, Point off, bool* active, String tick_sprite = {}, ...)
=> ctx.checkbox_id(@compute_id($vasplat), desc, off, active, tick_sprite);
fn void? Ctx.checkbox_id(&ctx, Id id, String description, Point off, bool* active, String tick_sprite)
@ -126,7 +125,7 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, Point off, bool* activ
Elem *elem = ctx.get_elem(id, ETYPE_BUTTON)!;
Style* style = ctx.styles.get_style(@str_hash("checkbox"));
Rect size = {off.x, off.y, DEFAULT_CHECKBOX_SIZE, DEFAULT_CHECKBOX_SIZE};
Rect size = {off.x, off.y, style.size, style.size};
elem.bounds = ctx.position_element(parent, size, style);
// if the bounds are null the element is outside the div view,
@ -144,7 +143,7 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, Point off, bool* activ
} else {
ctx.push_rect(elem.bounds, parent.div.z_index, style)!;
if (*active) {
ushort x = DEFAULT_CHECKBOX_SIZE / 4;
ushort x = style.size / 4;
Rect check = elem.bounds.add({x, x, -x*2, -x*2});
Style s = *style;
s.bg = s.primary;
@ -155,7 +154,6 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, Point off, bool* activ
}
// FIXME: this should be inside the style
const short DEFAULT_SWITCH_SIZE = 16;
macro Ctx.toggle(&ctx, String desc, Point off, bool* active)
=> ctx.toggle_id(@compute_id($vasplat), desc, off, active);
fn void? Ctx.toggle_id(&ctx, Id id, String description, Point off, bool* active)
@ -166,7 +164,7 @@ fn void? Ctx.toggle_id(&ctx, Id id, String description, Point off, bool* active)
Elem *elem = ctx.get_elem(id, ETYPE_BUTTON)!;
Style* style = ctx.styles.get_style(@str_hash("toggle"));
Rect size = {off.x, off.y, DEFAULT_SWITCH_SIZE*2, DEFAULT_SWITCH_SIZE};
Rect size = {off.x, off.y, style.size*2, style.size};
elem.bounds = ctx.position_element(parent, size, style);
// if the bounds are null the element is outside the div view,
@ -179,7 +177,7 @@ fn void? Ctx.toggle_id(&ctx, Id id, String description, Point off, bool* active)
// Draw the button
// FIXME: THIS IS SHIT
ctx.push_rect(elem.bounds, parent.div.z_index, style)!;
Rect t = elem.bounds.add({*active ? (DEFAULT_SWITCH_SIZE+3) : +3, +3, -DEFAULT_SWITCH_SIZE-6, -6});
Rect t = elem.bounds.add({*active ? (style.size+3) : +3, +3, -style.size-6, -6});
Style s = *style;
s.bg = s.primary;
s.margin = s.border = s.padding = {};

View File

@ -196,6 +196,7 @@ fn void? Ctx.init(&ctx)
defer catch { (void)ctx.cmd_queue.free(); }
ctx.styles.init(allocator::heap());
ctx.styles.register_style(&DEFAULT_STYLE, @str_hash("default"));
defer catch { ctx.styles.free(); }
ctx.active_div = 0;

View File

@ -3,8 +3,6 @@ module ugui;
import std::io;
import std::math;
const short SCROLLBAR_DIM = 5;
// div element
struct ElemDiv {
Layout layout;
@ -18,6 +16,7 @@ struct ElemDiv {
bool on;
float value;
}
ushort scroll_size;
int z_index;
Rect children_bounds; // current frame children bounds
Rect pcb; // previous frame children bounds
@ -39,10 +38,12 @@ fn void? Ctx.div_begin_id(&ctx, Id id, Rect size, bool scroll_x, bool scroll_y)
Elem* elem = ctx.get_elem(id, ETYPE_DIV)!;
ctx.active_div = elem.tree_idx;
Style* style = ctx.styles.get_style(0);
Style* style = ctx.styles.get_style(@str_hash("default"));
Style* slider_style = ctx.styles.get_style(@str_hash("slider"));
elem.div.scroll_x.enabled = scroll_x;
elem.div.scroll_y.enabled = scroll_y;
elem.div.scroll_size = slider_style.size ? slider_style.size : (style.size ? style.size : DEFAULT_STYLE.size);
elem.div.z_index = parent.div.z_index + 1;
// 2. layout the element
@ -110,8 +111,8 @@ fn void? Ctx.div_end(&ctx)
Id vsid_raw = @str_hash("div_scrollbar_vertical");
Id hsid_real = ctx.gen_id(@str_hash("div_scrollbar_horizontal"))!;
Id vsid_real = ctx.gen_id(@str_hash("div_scrollbar_vertical"))!;
short wdim = elem.div.scroll_y.on ? (ctx.focus_id == vsid_real || ctx.is_hovered(ctx.find_elem(vsid_real)) ? SCROLLBAR_DIM*3 : SCROLLBAR_DIM) : 0;
short hdim = elem.div.scroll_x.on ? (ctx.focus_id == hsid_real || ctx.is_hovered(ctx.find_elem(hsid_real)) ? SCROLLBAR_DIM*3 : SCROLLBAR_DIM) : 0;
short wdim = elem.div.scroll_y.on ? (ctx.focus_id == vsid_real || ctx.is_hovered(ctx.find_elem(vsid_real)) ? elem.div.scroll_size*2 : elem.div.scroll_size) : 0;
short hdim = elem.div.scroll_x.on ? (ctx.focus_id == hsid_real || ctx.is_hovered(ctx.find_elem(hsid_real)) ? elem.div.scroll_size*2 : elem.div.scroll_size) : 0;
if (elem.div.scroll_y.on) {
if (ctx.input.events.mouse_scroll && ctx.hover_id == elem.id) {

View File

@ -84,11 +84,11 @@ macro Rect Elem.get_view(&elem)
Rect off;
if (elem.div.scroll_x.enabled && elem.div.scroll_x.on) {
off.x = (short)((float)(elem.div.pcb.w - elem.bounds.w) * elem.div.scroll_x.value);
off.w = -SCROLLBAR_DIM;
off.w = -elem.div.scroll_size;
}
if (elem.div.scroll_y.enabled && elem.div.scroll_y.on) {
off.y = (short)((float)(elem.div.pcb.h - elem.bounds.h) * elem.div.scroll_y.value);
off.h = -SCROLLBAR_DIM;
off.h = -elem.div.scroll_size;
}
return elem.bounds.add(off);
}

View File

@ -50,9 +50,12 @@ fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Rect size, float* value, float hpe
}
// Draw the slider background and handle
ctx.push_rect(elem.bounds, parent.div.z_index, style)!;
Style s = *style;
Rect padding = s.padding;
s.padding = {};
ctx.push_rect(elem.bounds, parent.div.z_index, &s)!;
s.bg = s.primary;
s.padding = padding;
ctx.push_rect(elem.slider.handle, parent.div.z_index, &s)!;
return elem.events;
@ -111,9 +114,12 @@ fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Rect size, float* value, float hpe
}
// Draw the slider background and handle
ctx.push_rect(elem.bounds, parent.div.z_index, style)!;
Style s = *style;
Rect padding = s.padding;
s.padding = {};
ctx.push_rect(elem.bounds, parent.div.z_index, &s)!;
s.bg = s.primary;
s.padding = padding;
ctx.push_rect(elem.slider.handle, parent.div.z_index, &s)!;
return elem.events;

View File

@ -120,7 +120,7 @@ fn void? Ctx.sprite_id(&ctx, Id id, String name, Point off)
Elem *parent = ctx.get_parent()!;
Elem *elem = ctx.get_elem(id, ETYPE_SPRITE)!;
Style* style = ctx.styles.get_style(0);
Style* style = ctx.styles.get_style(@str_hash("sprite"));
Sprite* sprite = ctx.sprite_atlas.get(name)!;
Rect uv = { sprite.u, sprite.v, sprite.w, sprite.h };

View File

@ -17,6 +17,7 @@ struct Style { // css box model
Color accent; // accent color
ushort radius;
short size;
}
const Style DEFAULT_STYLE = {
@ -24,6 +25,7 @@ const Style DEFAULT_STYLE = {
.border = {2, 2, 2, 2},
.padding = {1, 1, 1, 1},
.radius = 12,
.size = 16,
.bg = 0x282828ffu.@to_rgba(),
.fg = 0xfbf1c7ffu.@to_rgba(),
@ -46,7 +48,8 @@ fn void StyleMap.register_style(&map, Style* style, Id id)
fn Style* StyleMap.get_style(&map, Id id)
{
Style*? s = map.get_ref(id);
if (catch e = s) {
if (catch s) {
// io::eprintfn("WARNING: style %x not found, using default style", id);
return &DEFAULT_STYLE;
}
return s;
@ -61,7 +64,6 @@ fn int StyleMap.import_style_string(&map, String text)
while (p.parse_style() == true) {
added++;
// set the default style correctly
if (p.style_id == @str_hash("default")) p.style_id = 0;
map.register_style(&p.style, p.style_id);
if (p.lex.peep_token().type == EOF) break;
}
@ -83,7 +85,6 @@ fn int Ctx.import_style_from_file(&ctx, String path)
}
// TODO: add a "size" property that controls the size of elements like checkboxes
/*
* Style can be serialized and deserialized with a subset of CSS
* <style name> {
@ -91,6 +92,7 @@ fn int Ctx.import_style_from_file(&ctx, String path)
* border: left right top bottom;
* margin: left right top bottoms;
* radius: uint;
* size: uint;
* Color: #RRGGBBAA;
* Color: #RRGGBBAA;
* Color: #RRGGBBAA;
@ -368,10 +370,20 @@ fn bool Parser.parse_property(&p)
short r;
if (p.parse_number(&r) == false) return false;
if (r < 0) {
io::eprintfn("CSS parsing error at %d:%d: radius must be a positive number, got %d", t.line, t.col, r);
io::eprintfn("CSS parsing error at %d:%d: 'radius' must be a positive number, got %d", t.line, t.col, r);
return false;
}
p.style.radius = (ushort)r;
case "size":
short s;
if (p.parse_number(&s) == false) return false;
if (s < 0) {
io::eprintfn("CSS parsing error at %d:%d: 'size' must be a positive number, got %d", t.line, t.col, s);
return false;
}
p.style.size = (ushort)s;
default:
io::eprintfn("CSS parsing error at %d:%d: '%s' is not a valid property", prop.line, prop.col, prop.text);

View File

@ -15,7 +15,7 @@ fn void? Ctx.text_unbounded_id(&ctx, Id id, String text)
Elem *parent = ctx.get_parent()!;
Elem *elem = ctx.get_elem(id, ETYPE_TEXT)!;
Style* style = ctx.styles.get_style(0);
Style* style = ctx.styles.get_style(@str_hash("text"));
elem.text.str = text;
@ -36,7 +36,7 @@ fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Rect size, char[] text, usz* text_le
Elem *parent = ctx.get_parent()!;
Elem *elem = ctx.get_elem(id, ETYPE_TEXT)!;
Style* style = ctx.styles.get_style(0);
Style* style = ctx.styles.get_style(@str_hash("text-box"));
elem.text.str = text;

View File

@ -94,7 +94,7 @@ checkbox {
border: 2 2 2 2;
padding: 1 1 1 1;
radius: 10;
size: 16;
bg: #3c3836ff;
fg: #fbf1c7ff;
primary: #cc241dff;
@ -107,7 +107,7 @@ toggle {
border: 2 2 2 2;
padding: 1 1 1 1;
radius: 10;
size: 16;
bg: #3c3836ff;
fg: #fbf1c7ff;
primary: #cc241dff;
@ -117,6 +117,9 @@ toggle {
slider {
margin: 2 2 2 2;
padding: 2 2 2 2;
radius: 4;
size: 8;
bg: #3c3836ff;
fg: #fbf1c7ff;
primary: #cc241dff;