first draft
This commit is contained in:
parent
884105a4e2
commit
fb3a964f7f
@ -34,7 +34,8 @@ enum ElemType {
|
||||
|
||||
bitstruct ElemFlags : uint {
|
||||
bool updated : 0;
|
||||
bool is_new : 1;
|
||||
bool is_new : 1; // element is new in the cache
|
||||
bool shown : 2; // element has been shown (drawn) this frame
|
||||
}
|
||||
|
||||
bitstruct ElemEvents : uint {
|
||||
@ -175,6 +176,7 @@ fn PElemTuple? Ctx.get_elem(&ctx, Id id, ElemType type)
|
||||
elem = ctx.cache.get_or_insert(&&(Elem){}, id, &is_new)!;
|
||||
elem.flags = (ElemFlags)0;
|
||||
elem.flags.is_new = is_new;
|
||||
elem.flags.shown = true;
|
||||
elem.id = id;
|
||||
elem.layout = {};
|
||||
if (is_new == false && elem.type != type) {
|
||||
@ -323,24 +325,13 @@ $endif
|
||||
// }
|
||||
}
|
||||
|
||||
<*
|
||||
* @ensure elem != null
|
||||
*>
|
||||
macro bool Ctx.is_hovered(&ctx, Elem *elem)
|
||||
{
|
||||
return ctx.input.mouse.pos.in_rect(elem.bounds);
|
||||
}
|
||||
|
||||
macro bool Ctx.elem_focus(&ctx, Elem *elem)
|
||||
{
|
||||
return ctx.focus_id == elem.id;
|
||||
}
|
||||
|
||||
// TODO: add other events
|
||||
// FIXME: this does not work with touch
|
||||
// FIXME: hacked together, please do better
|
||||
/*
|
||||
fn ElemEvents Ctx.get_elem_events(&ctx, Elem *elem)
|
||||
{
|
||||
// FIXME: gross hack to not leak events under a pop-up
|
||||
if (ctx.input.z_index != elem.z_index) return {};
|
||||
|
||||
bool hover = ctx.is_hovered(elem);
|
||||
@ -367,3 +358,4 @@ fn ElemEvents Ctx.get_elem_events(&ctx, Elem *elem)
|
||||
};
|
||||
return ev;
|
||||
}
|
||||
*/
|
||||
|
@ -297,6 +297,72 @@ fn void resolve_placement(Elem* c, Elem* p)
|
||||
}
|
||||
}
|
||||
|
||||
macro bool Ctx.is_hovered(&ctx, Elem *elem) => ctx.input.mouse.pos.in_rect(elem.bounds);
|
||||
|
||||
fn void Ctx.update_elem_events(&ctx, Elem* elem)
|
||||
{
|
||||
bool hover = ctx.is_hovered(elem);
|
||||
bool focus = ctx.focus_id == elem.id || (hover && ctx.is_mouse_pressed(BTN_ANY));
|
||||
|
||||
if (ctx.is_mouse_pressed(BTN_ANY) && !hover){
|
||||
focus = false;
|
||||
if (ctx.focus_id == elem.id) ctx.focus_id = 0;
|
||||
}
|
||||
|
||||
if (hover) {
|
||||
// TODO: this constant cache lookup could be slow
|
||||
Elem* prev_hover = ctx.find_elem(ctx.hover_id);
|
||||
if (prev_hover.id != elem.id && prev_hover.flags.shown) {
|
||||
if (prev_hover.z_index <= elem.z_index) {
|
||||
// remove hover events from prev_hover
|
||||
prev_hover.events.mouse_hover = false;
|
||||
prev_hover.events.mouse_press = false;
|
||||
prev_hover.events.mouse_release = false;
|
||||
prev_hover.events.mouse_hold = false;
|
||||
} else {
|
||||
hover = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (focus) {
|
||||
// TODO: this constant cache lookup could be slow
|
||||
Elem* prev_focus = ctx.find_elem(ctx.hover_id);
|
||||
// update the focus id and element only if the current element is at the same level
|
||||
// or above the previous element that held focus
|
||||
if (prev_focus.z_index <= elem.z_index) {
|
||||
// remove focus events from prev_focus
|
||||
prev_focus.events.has_focus = false;
|
||||
prev_focus.events.mouse_press = false;
|
||||
prev_focus.events.mouse_release = false;
|
||||
prev_focus.events.mouse_hold = false;
|
||||
prev_focus.events.key_press = false;
|
||||
prev_focus.events.key_release = false;
|
||||
prev_focus.events.key_repeat = false;
|
||||
prev_focus.events.text_input = false;
|
||||
// update the hover id
|
||||
ctx.focus_id = elem.id;
|
||||
} else if (prev_focus.flags.shown) {
|
||||
focus = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hover) ctx.hover_id = elem.id;
|
||||
|
||||
ElemEvents ev = {
|
||||
.has_focus = focus,
|
||||
.mouse_hover = hover,
|
||||
.mouse_press = hover && focus && ctx.is_mouse_pressed(BTN_ANY),
|
||||
.mouse_release = hover && focus && ctx.is_mouse_released(BTN_ANY),
|
||||
.mouse_hold = hover && focus && ctx.is_mouse_down(BTN_ANY),
|
||||
.key_press = focus && ctx.input.events.key_press,
|
||||
.key_release = focus && ctx.input.events.key_release,
|
||||
.key_repeat = focus && ctx.input.events.key_repeat,
|
||||
.text_input = focus && (ctx.input.keyboard.text_len || ctx.input.keyboard.modkeys & KMOD_TXT),
|
||||
};
|
||||
elem.events = ev;
|
||||
}
|
||||
|
||||
fn void? Ctx.layout_element_tree(&ctx)
|
||||
{
|
||||
int current;
|
||||
@ -334,7 +400,11 @@ fn void? Ctx.layout_element_tree(&ctx)
|
||||
} else {
|
||||
resolve_placement(c, p);
|
||||
update_children_bounds(c, p);
|
||||
}
|
||||
|
||||
// reset shown flag
|
||||
}
|
||||
ctx.update_elem_events(c);
|
||||
c.flags.shown = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
||||
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
//elem.events = ctx.get_elem_events(elem);
|
||||
// if (ctx.input.z_index == elem.z_index) println("true ", elem.z_index);
|
||||
Rect content_bounds = elem.content_bounds();
|
||||
|
||||
@ -66,7 +66,7 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
||||
};
|
||||
//text_bounds = text_size.center_to(text_bounds);
|
||||
|
||||
bool is_active = ctx.elem_focus(elem) || elem.events.mouse_hover;
|
||||
bool is_active = elem.events.has_focus || elem.events.mouse_hover;
|
||||
Style s = *style;
|
||||
if (is_active) {
|
||||
s.secondary = s.primary;
|
||||
@ -115,7 +115,7 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String t
|
||||
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
//elem.events = ctx.get_elem_events(elem);
|
||||
if (elem.events.mouse_hover && elem.events.mouse_release) *active = !(*active);
|
||||
|
||||
|
||||
@ -189,7 +189,7 @@ fn void? Ctx.toggle_id(&ctx, Id id, String description, bool* active)
|
||||
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
//elem.events = ctx.get_elem_events(elem);
|
||||
if (elem.events.mouse_hover && elem.events.mouse_release) *active = !(*active);
|
||||
|
||||
Rect content_bounds = elem.bounds.pad(elem.layout.content_offset);
|
||||
|
@ -18,6 +18,13 @@ struct ElemDiv {
|
||||
}
|
||||
|
||||
|
||||
macro Ctx.@center(&ctx, LayoutDirection dir = ROW, ...; @body())
|
||||
{
|
||||
ctx.@div(@grow(), @grow(), dir, CENTER) {
|
||||
@body();
|
||||
}!;
|
||||
}
|
||||
|
||||
macro Ctx.@row(&ctx, Anchor anchor = TOP_LEFT, ...; @body())
|
||||
{
|
||||
ctx.@div(@fit(), @fit(), ROW, anchor: anchor) {
|
||||
@ -102,7 +109,7 @@ fn void? Ctx.div_begin_id(&ctx,
|
||||
ctx.div_scissor = elem.bounds.pad(elem.layout.content_offset);
|
||||
ctx.push_scissor(elem.bounds.pad(elem.layout.content_offset), elem.z_index)!;
|
||||
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
//elem.events = ctx.get_elem_events(elem);
|
||||
|
||||
// TODO: check active
|
||||
// TODO: check resizeable
|
||||
@ -212,7 +219,7 @@ fn bool? Ctx.popup_begin_id(&ctx,
|
||||
ctx.div_scissor = elem.bounds.pad(elem.layout.content_offset);
|
||||
ctx.push_scissor(elem.bounds.pad(elem.layout.content_offset), elem.z_index)!;
|
||||
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
//elem.events = ctx.get_elem_events(elem);
|
||||
|
||||
// check close condition, mouse release anywhere outside the div bounds
|
||||
if ((ctx.mouse_released() & BTN_ANY) && !elem.events.mouse_hover) {
|
||||
|
@ -45,9 +45,9 @@ fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Size w, Size h, float* value, floa
|
||||
elem.slider.handle = handle;
|
||||
|
||||
Point m = ctx.input.mouse.pos;
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
//elem.events = ctx.get_elem_events(elem);
|
||||
|
||||
if (ctx.elem_focus(elem) && ctx.is_mouse_down(BTN_LEFT)) {
|
||||
if (elem.events.has_focus && ctx.is_mouse_down(BTN_LEFT)) {
|
||||
*value = calc_value(content_bounds.x, m.x, content_bounds.w, hw);
|
||||
elem.slider.handle.x = calc_slider(content_bounds.x, content_bounds.w-hw, *value);
|
||||
elem.events.update = true;
|
||||
@ -109,9 +109,9 @@ fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Size w, Size h, float* value, floa
|
||||
elem.slider.handle = handle;
|
||||
|
||||
Point m = ctx.input.mouse.pos;
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
//elem.events = ctx.get_elem_events(elem);
|
||||
|
||||
if (ctx.elem_focus(elem) && ctx.is_mouse_down(BTN_LEFT)) {
|
||||
if (elem.events.has_focus && ctx.is_mouse_down(BTN_LEFT)) {
|
||||
*value = calc_value(content_bounds.y, m.y, content_bounds.h, hh);
|
||||
elem.slider.handle.y = calc_slider(content_bounds.y, content_bounds.h-hh, *value);
|
||||
elem.events.update = true;
|
||||
@ -156,7 +156,7 @@ fn void? Ctx.scrollbar(&ctx, Id id, float *value, float handle_percent, bool ver
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
Rect content_bounds = elem.bounds.pad(elem.layout.content_offset);
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
//elem.events = ctx.get_elem_events(elem);
|
||||
|
||||
short o = vertical ? content_bounds.y : content_bounds.x;
|
||||
short m = vertical ? ctx.input.mouse.pos.y : ctx.input.mouse.pos.x;
|
||||
|
@ -65,7 +65,7 @@ fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te, Anchor
|
||||
update_parent_size(elem, parent);
|
||||
|
||||
// check input and update the text
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
//elem.events = ctx.get_elem_events(elem);
|
||||
|
||||
if (elem.events.text_input || elem.events.key_press) {
|
||||
ctx.text_edit(elem.text.te);
|
||||
|
27
src/main.c3
27
src/main.c3
@ -208,12 +208,14 @@ fn int main(String[] args)
|
||||
|
||||
if (ui.check_key_combo(ugui::KMOD_CTRL, "q")) quit = true;
|
||||
|
||||
const String APPLICATION = "calculator";
|
||||
const String APPLICATION = "popup";
|
||||
$switch APPLICATION:
|
||||
$case "debug":
|
||||
debug_app(&ui);
|
||||
$case "calculator":
|
||||
calculator(&ui, &te);
|
||||
$case "popup":
|
||||
popup(&ui);
|
||||
$endswitch
|
||||
|
||||
// Timings counter
|
||||
@ -459,5 +461,26 @@ fn void calculator(ugui::Ctx* ui, TextEdit* te)
|
||||
ui.text_box(ugui::@grow(), ugui::@exact(100), te, RIGHT)!!;
|
||||
}!!;
|
||||
}!!; }!!;
|
||||
|
||||
}
|
||||
|
||||
fn void popup(ugui::Ctx* ui)
|
||||
{
|
||||
static bool toggle;
|
||||
static ugui::Point pos;
|
||||
|
||||
ui.@center(COLUMN) {
|
||||
if (toggle) {
|
||||
toggle = ui.popup_begin(pos, ugui::@fit(), ugui::@fit(), COLUMN)!!;
|
||||
ui.button("POP")!!;
|
||||
ui.button("UP")!!;
|
||||
ui.div_end()!!;
|
||||
}
|
||||
if (ui.button("ciao")!!.mouse_release) {
|
||||
pos = ui.input.mouse.pos;
|
||||
toggle = ~toggle;
|
||||
}
|
||||
if (ui.button("mamma")!!.mouse_press) ugui::println("pressed!");
|
||||
}!!;
|
||||
|
||||
ugui::println("focus id: ", ui.focus_id, " hover id: ", ui.hover_id);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user