2024-11-07 18:35:20 +01:00
|
|
|
module ugui;
|
|
|
|
|
|
2024-11-17 21:36:46 +01:00
|
|
|
import std::io;
|
2024-12-18 14:58:40 +01:00
|
|
|
import std::math;
|
2024-11-07 18:35:20 +01:00
|
|
|
|
2024-12-17 11:26:59 +01:00
|
|
|
// div element
|
|
|
|
|
struct ElemDiv {
|
2024-12-19 00:29:30 +01:00
|
|
|
struct scroll_x {
|
|
|
|
|
bool enabled;
|
|
|
|
|
bool on;
|
|
|
|
|
float value;
|
|
|
|
|
}
|
|
|
|
|
struct scroll_y {
|
|
|
|
|
bool enabled;
|
|
|
|
|
bool on;
|
|
|
|
|
float value;
|
2024-12-17 11:26:59 +01:00
|
|
|
}
|
2025-07-06 23:13:16 +02:00
|
|
|
ushort scroll_size;
|
2025-06-03 18:15:46 +02:00
|
|
|
int z_index;
|
2024-12-17 11:26:59 +01:00
|
|
|
}
|
|
|
|
|
|
2025-08-14 22:16:54 +02:00
|
|
|
|
|
|
|
|
// useful macro to start and end a div, capturing the trailing block
|
2025-09-05 13:10:16 +02:00
|
|
|
macro Ctx.@div(&ctx,
|
|
|
|
|
Size width = @grow, Size height = @grow,
|
|
|
|
|
LayoutDirection dir = ROW,
|
|
|
|
|
Anchor anchor = TOP_LEFT,
|
|
|
|
|
bool scroll_x = false, bool scroll_y = false,
|
2025-09-12 22:32:47 +02:00
|
|
|
...;
|
2025-09-05 13:10:16 +02:00
|
|
|
@body()
|
|
|
|
|
)
|
2025-08-14 22:16:54 +02:00
|
|
|
{
|
2025-09-05 13:10:16 +02:00
|
|
|
ctx.div_begin(width, height, dir, anchor, scroll_x, scroll_y, $vasplat)!;
|
2025-08-14 22:16:54 +02:00
|
|
|
@body();
|
|
|
|
|
ctx.div_end()!;
|
|
|
|
|
}
|
|
|
|
|
|
2025-09-05 13:10:16 +02:00
|
|
|
macro Ctx.div_begin(&ctx,
|
|
|
|
|
Size width = @grow(), Size height = @grow(),
|
|
|
|
|
LayoutDirection dir = ROW,
|
|
|
|
|
Anchor anchor = TOP_LEFT,
|
|
|
|
|
bool scroll_x = false, bool scroll_y = false,
|
|
|
|
|
...
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
return ctx.div_begin_id(@compute_id($vasplat), width, height, dir, anchor, scroll_x, scroll_y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn void? Ctx.div_begin_id(&ctx,
|
|
|
|
|
Id id,
|
|
|
|
|
Size width, Size height,
|
|
|
|
|
LayoutDirection dir,
|
|
|
|
|
Anchor anchor,
|
|
|
|
|
bool scroll_x, bool scroll_y
|
|
|
|
|
)
|
2024-11-07 18:35:20 +01:00
|
|
|
{
|
2025-06-30 18:24:50 +02:00
|
|
|
id = ctx.gen_id(id)!;
|
2024-11-07 18:35:20 +01:00
|
|
|
|
2025-07-01 16:03:11 +02:00
|
|
|
Elem* elem = ctx.get_elem(id, ETYPE_DIV)!;
|
2025-07-14 12:57:29 +02:00
|
|
|
Elem* parent = ctx.get_parent()!;
|
2025-07-01 16:03:11 +02:00
|
|
|
ctx.active_div = elem.tree_idx;
|
2025-07-06 01:41:57 +02:00
|
|
|
|
2025-07-06 23:13:16 +02:00
|
|
|
Style* style = ctx.styles.get_style(@str_hash("default"));
|
|
|
|
|
Style* slider_style = ctx.styles.get_style(@str_hash("slider"));
|
2024-11-07 18:35:20 +01:00
|
|
|
|
2024-12-19 15:24:39 +01:00
|
|
|
elem.div.scroll_x.enabled = scroll_x;
|
|
|
|
|
elem.div.scroll_y.enabled = scroll_y;
|
2025-07-06 23:13:16 +02:00
|
|
|
elem.div.scroll_size = slider_style.size ? slider_style.size : (style.size ? style.size : DEFAULT_STYLE.size);
|
2025-06-03 18:15:46 +02:00
|
|
|
elem.div.z_index = parent.div.z_index + 1;
|
2024-11-07 18:35:20 +01:00
|
|
|
|
2024-12-18 20:04:23 +01:00
|
|
|
// update the ctx scissor
|
2024-12-19 15:24:39 +01:00
|
|
|
ctx.div_scissor = elem.bounds;
|
2025-06-03 18:15:46 +02:00
|
|
|
ctx.push_scissor(elem.bounds, elem.div.z_index)!;
|
2024-12-18 20:04:23 +01:00
|
|
|
|
2025-09-05 13:10:16 +02:00
|
|
|
// update layout with correct info
|
|
|
|
|
elem.layout = {
|
|
|
|
|
.w = width,
|
|
|
|
|
.h = height,
|
|
|
|
|
.dir = dir,
|
|
|
|
|
.anchor = anchor,
|
2025-09-05 19:56:59 +02:00
|
|
|
.content_offset = style.margin + style.border + style.padding,
|
2024-12-18 14:58:40 +01:00
|
|
|
};
|
2025-09-12 22:32:47 +02:00
|
|
|
|
2025-09-05 13:10:16 +02:00
|
|
|
// update parent grow children
|
|
|
|
|
update_parent_grow(elem, parent);
|
2024-11-07 18:35:20 +01:00
|
|
|
|
2025-09-05 18:53:47 +02:00
|
|
|
ctx.push_rect(elem.bounds.pad(style.margin), elem.div.z_index, style)!;
|
2024-11-07 18:35:20 +01:00
|
|
|
|
2024-12-19 15:24:39 +01:00
|
|
|
elem.events = ctx.get_elem_events(elem);
|
2024-12-18 14:58:40 +01:00
|
|
|
|
2024-11-07 18:35:20 +01:00
|
|
|
// TODO: check active
|
|
|
|
|
// TODO: check resizeable
|
2024-12-18 20:04:23 +01:00
|
|
|
}
|
|
|
|
|
|
2025-05-05 16:23:26 +02:00
|
|
|
fn void? Ctx.div_end(&ctx)
|
2024-12-18 20:04:23 +01:00
|
|
|
{
|
2025-07-01 15:33:22 +02:00
|
|
|
Elem* elem = ctx.get_active_div()!;
|
2025-02-01 01:01:13 +01:00
|
|
|
|
2025-09-12 22:32:47 +02:00
|
|
|
/* FIXME: this needs the absolute positioning to work
|
2024-12-18 14:58:40 +01:00
|
|
|
// set the scrollbar flag, is used in layout
|
2025-09-12 22:32:47 +02:00
|
|
|
Point cbc = elem.children_bounds.bottom_right();
|
|
|
|
|
Point bc = elem.bounds.bottom_right();
|
2024-12-18 14:58:40 +01:00
|
|
|
// horizontal overflow
|
2024-12-19 15:24:39 +01:00
|
|
|
elem.div.scroll_x.on = cbc.x > bc.x && elem.div.scroll_x.enabled;
|
2024-12-19 00:29:30 +01:00
|
|
|
// vertical overflow
|
2024-12-19 15:24:39 +01:00
|
|
|
elem.div.scroll_y.on = cbc.y > bc.y && elem.div.scroll_y.enabled;
|
2024-12-19 00:29:30 +01:00
|
|
|
|
2025-07-06 01:41:57 +02:00
|
|
|
Id hsid_raw = @str_hash("div_scrollbar_horizontal");
|
|
|
|
|
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"))!;
|
2025-07-06 23:13:16 +02:00
|
|
|
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;
|
2024-12-18 14:58:40 +01:00
|
|
|
|
2024-12-19 15:24:39 +01:00
|
|
|
if (elem.div.scroll_y.on) {
|
2024-12-25 12:30:35 +01:00
|
|
|
if (ctx.input.events.mouse_scroll && ctx.hover_id == elem.id) {
|
|
|
|
|
elem.div.scroll_y.value += ctx.input.mouse.scroll.y * 0.07f;
|
|
|
|
|
elem.div.scroll_y.value = math::clamp(elem.div.scroll_y.value, 0.0f, 1.0f);
|
|
|
|
|
}
|
2025-09-12 22:32:47 +02:00
|
|
|
ctx.slider_ver_id(vsid_raw, @exact(wdim), @exact(elem.bounds.h - hdim), &elem.div.scroll_y.value, max((float)bc.y / cbc.y, (float)0.15))!;
|
2024-11-17 21:36:46 +01:00
|
|
|
}
|
|
|
|
|
|
2024-12-19 15:24:39 +01:00
|
|
|
if (elem.div.scroll_x.on) {
|
2024-12-25 12:30:35 +01:00
|
|
|
if (ctx.input.events.mouse_scroll && ctx.hover_id == elem.id) {
|
|
|
|
|
elem.div.scroll_x.value += ctx.input.mouse.scroll.x * 0.07f;
|
|
|
|
|
elem.div.scroll_x.value = math::clamp(elem.div.scroll_x.value, 0.0f, 1.0f);
|
|
|
|
|
}
|
2025-09-12 22:32:47 +02:00
|
|
|
ctx.slider_hor_id(hsid_raw, @exact(elem.bounds.w - wdim), @exact(hdim), &elem.div.scroll_x.value, max((float)bc.x / cbc.x, (float)0.15))!;
|
2024-12-18 14:58:40 +01:00
|
|
|
}
|
2025-09-05 13:10:16 +02:00
|
|
|
*/
|
2024-11-07 18:35:20 +01:00
|
|
|
|
|
|
|
|
// the active_div returns to the parent of the current one
|
|
|
|
|
ctx.active_div = ctx.tree.parentof(ctx.active_div)!;
|
2025-07-14 12:57:29 +02:00
|
|
|
Elem* parent = ctx.get_parent()!;
|
|
|
|
|
ctx.div_scissor = parent.bounds;
|
2025-09-12 12:48:29 +02:00
|
|
|
ctx.reset_scissor(elem.div.z_index)!;
|
2025-09-05 13:10:16 +02:00
|
|
|
|
|
|
|
|
update_parent_size(elem, parent);
|
2024-11-07 18:35:20 +01:00
|
|
|
}
|