You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ugui/src/ugui_impl.c3

140 lines
3.1 KiB

module ugui;
import std::io;
// return a pointer to the parent of the current active div
fn Elem*! Ctx.get_parent(&ctx)
{
// FIXME: if the tree held pointers to the elements then no more
// redundant cache search
Id parent_id = ctx.tree.get(ctx.active_div)!;
return ctx.cache.search(parent_id);
}
3 weeks ago
// get or push an element from the cache, return a pointer to it
// resets all flags except is_new which is set accordingly
macro Ctx.get_elem(&ctx, Id id)
{
Elem empty_elem;
bool is_new;
Elem* c_elem;
c_elem = ctx.cache.get_or_insert(&empty_elem, id, &is_new)!;
c_elem.flags = (ElemFlags)0;
c_elem.flags.is_new = is_new;
return c_elem;
}
3 weeks ago
// this searches an element in the cache by label, it does not create a new element
// if it does't find one
macro Ctx.get_elem_by_label(&ctx, String label)
{
Id id = label.hash();
3 weeks ago
return ctx.cache.search(id);
}
macro Ctx.get_elem_by_tree_idx(&ctx, isz idx) @private
{
Id id = ctx.tree.get(ctx.active_div)!;
return ctx.cache.search(id);
}
fn void! Ctx.init(&ctx)
{
ctx.tree.init(MAX_ELEMENTS)!;
defer catch { (void)ctx.tree.free(); }
//ug_fifo_init(&ctx.fifo, MAX_CMDS);
ctx.cache.init()!;
defer catch { (void)ctx.cache.free(); }
ctx.cmd_queue.init(MAX_ELEMENTS)!;
defer catch { (void)ctx.cmd_queue.free(); }
ctx.layout = Layout.ROW;
ctx.active_div = 0;
// TODO: add style config
ctx.style.margin = Rect{1, 1, 1, 1};
}
fn void Ctx.free(&ctx)
{
(void)ctx.tree.free();
(void)ctx.cache.free();
(void)ctx.cmd_queue.free();
}
fn void! Ctx.frame_begin(&ctx)
{
3 weeks ago
// 2. Get the root element from the cache and update it
Elem* c_elem = ctx.get_elem(ROOT_ID)!;
// The root should have the updated flag only if the size of the window
// was changed between frames, this propagates an element size recalculation
// down the element tree
3 weeks ago
c_elem.flags.updated = ctx.input.events.resize;
// if the window has focus then the root element also has focus, no other
// computation needed, child elements need to check the mouse positon and
// other stuff
3 weeks ago
c_elem.flags.has_focus = ctx.has_focus;
if (c_elem.flags.is_new || c_elem.flags.updated) {
Elem def_root = {
.id = ROOT_ID,
.type = ETYPE_DIV,
.bounds = {
.w = ctx.width,
.h = ctx.height,
},
.div = {
.layout = LAYOUT_ROW,
.children_bounds = {
.w = ctx.width,
.h = ctx.height,
}
},
.flags = c_elem.flags,
};
*c_elem = def_root;
}
// 3. Push the root element into the element tree
3 weeks ago
ctx.active_div = ctx.tree.add(ROOT_ID, 0)!;
// The root element does not push anything to the stack
// TODO: add a background color taken from a theme or config
}
fn void! Ctx.frame_end(&ctx)
{
// 1. clear the tree
ctx.tree.prune(0)!;
// 2. clear input fields
ctx.input.events = (InputEvents)0;
// draw mouse position
$if 1:
Cmd cmd = {
.type = CMD_RECT,
.rect.rect = {
.x = ctx.input.mouse.pos.x - 2,
.y = ctx.input.mouse.pos.y - 2,
.w = 4,
.h = 4,
},
.rect.color = uint_to_rgba(0xff00ffff)
};
ctx.cmd_queue.enqueue(&cmd)!;
$endif
}
3 weeks ago
/**
* @ensure elem != null
**/
fn bool Ctx.is_hovered(&ctx, Elem *elem)
{
return point_in_rect(ctx.input.mouse.pos, elem.bounds);
}