Compare commits

..

No commits in common. "ca691d1294f6df3046abfd07fb9c344d97c81e2a" and "d31b4eab538d28efa361b2b1e62cff068e63d002" have entirely different histories.

6 changed files with 60 additions and 65 deletions

View File

@ -122,7 +122,7 @@ fn int main(String[] args)
ui.div_begin("main", ugui::Rect{.w=ui.width/2})!!;
{|
ui.layout_set_column()!!;
ui.layout_set_row()!!;
if (ui.button("button0", ugui::Rect{0,0,30,30}, toggle)!!.mouse_press) {
io::printn("press button0");
toggle = !toggle;

View File

@ -4,7 +4,8 @@ import std::io;
// button element
struct ElemButton {
int filler;
Color color;
bool active;
}
// draw a button, return the events on that button
@ -19,6 +20,7 @@ fn ElemEvents! Ctx.button(&ctx, String label, Rect size, bool state = false)
if (elem.flags.is_new) {
elem.type = ETYPE_BUTTON;
elem.button.color = uint_to_rgba(0x0000ffff);
} else if (elem.type != ETYPE_BUTTON) {
return UgError.WRONG_ELEMENT_TYPE?;
}
@ -29,16 +31,22 @@ fn ElemEvents! Ctx.button(&ctx, String label, Rect size, bool state = false)
// no interaction should occur so just return
if (elem.bounds.is_null()) { return ElemEvents{}; }
Color col = uint_to_rgba(0x0000ffff);
elem.events = ctx.get_elem_events(elem);
if (elem.events.mouse_hover) {
if (parent.flags.has_focus) {
elem.flags.has_focus = true;
elem.button.color = uint_to_rgba(0x00ff00ff);
}
} else {
elem.button.color = uint_to_rgba(0x0000ffff);
}
if (state) {
col = uint_to_rgba(0xff0000ff);
} else if (ctx.elem_focus(elem) || elem.events.mouse_hover) {
col = uint_to_rgba(0xff00ffff);
elem.button.color = uint_to_rgba(0xff00ffff);
}
// Draw the button
ctx.push_rect(elem.bounds, col, do_border: true, do_radius: true)!;
ctx.push_rect(elem.bounds, elem.button.color, do_border: true, do_radius: true)!;
return elem.events;
}

View File

@ -32,7 +32,8 @@ enum ElemType {
bitstruct ElemFlags : uint {
bool updated : 0;
bool is_new : 1;
bool has_focus : 1;
bool is_new : 2;
}
bitstruct ElemEvents : uint {
@ -133,9 +134,6 @@ struct Ctx {
}
}
Id hover_id;
Id focus_id;
Rect div_scissor; // the current div bounds used for scissor test
isz active_div; // tree node indicating the current active div
}
@ -192,20 +190,16 @@ macro Ctx.get_elem(&ctx, Id id)
elem = ctx.cache.get_or_insert(&empty_elem, id, &is_new)!;
elem.flags = (ElemFlags)0;
elem.flags.is_new = is_new;
// FIXME: should this be here? or is it better to have the elements set the id?
elem.id = id;
return elem;
}
// FIXME: Since ids are now keyed with the element's parent id, this function does not work
// outside of the element's div block.
// 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 = ctx.get_id(label);
// return ctx.cache.search(id);
//}
macro Ctx.get_elem_by_label(&ctx, String label)
{
Id id = label.hash();
return ctx.cache.search(id);
}
macro Ctx.get_elem_by_tree_idx(&ctx, isz idx) @private
{
@ -256,7 +250,7 @@ fn void! Ctx.frame_begin(&ctx)
// 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
//elem.flags.has_focus = ctx.has_focus;
elem.flags.has_focus = ctx.has_focus;
Elem def_root = {
.id = ROOT_ID,
@ -321,39 +315,8 @@ $endif
<*
* @ensure elem != null
*>
macro bool Ctx.is_hovered(&ctx, Elem *elem)
*>
fn bool Ctx.is_hovered(&ctx, Elem *elem)
{
return point_in_rect(ctx.input.mouse.pos, 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
macro ElemEvents Ctx.get_elem_events(&ctx, Elem *elem)
{
//io::printfn("id %x, focus id %x", elem.id, ctx.focus_id);
bool hover = ctx.is_hovered(elem);
bool focus = ctx.focus_id == elem.id || (hover && ctx.is_mouse_pressed(BTN_LEFT));
if (hover) {
ctx.hover_id = elem.id;
}
if (focus) {
ctx.focus_id = elem.id;
}
ElemEvents ev = {
.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),
};
return ev;
}

View File

@ -11,16 +11,21 @@ struct ElemDiv {
struct scroll_x {
bool enabled;
bool on;
bool focus;
float value;
}
struct scroll_y {
bool enabled;
bool on;
bool focus;
float value;
}
Rect children_bounds; // current frame children bounds
Rect pcb; // previous frame children bounds
Point origin_r, origin_c;
// the id of the active element, this field is set and reset by the elements themselves and it is
// used to keep track of which element should handle some input events between frames
Id active_id;
}
fn void! Ctx.div_begin(&ctx, String label, Rect size, bool scroll_x = false, bool scroll_y = false)
@ -66,6 +71,13 @@ fn void! Ctx.div_begin(&ctx, String label, Rect size, bool scroll_x = false, boo
// TODO: check active
// TODO: check resizeable
if (parent.flags.has_focus) {
if (point_in_rect(ctx.input.mouse.pos, elem.bounds)) {
elem.flags.has_focus = true;
}
}
}
fn void! Ctx.div_end(&ctx)
@ -75,9 +87,7 @@ fn void! Ctx.div_end(&ctx)
Elem* elem = ctx.get_elem_by_tree_idx(ctx.active_div)!;
elem.div.pcb = elem.div.children_bounds;
// FIXME: this causes all elements inside the div to loose focus since the mouse press happens
// both inside the element and inside the div bounds
//elem.events = ctx.get_elem_events(elem);
elem.events = ctx.get_elem_events(elem);
Rect cb = elem.div.pcb;
// children bounds bottom-right corner
@ -97,11 +107,8 @@ fn void! Ctx.div_end(&ctx)
// vertical overflow
elem.div.scroll_y.on = cbc.y > bc.y && elem.div.scroll_y.enabled;
Id hsid = ctx.gen_id("div_scrollbar_horizontal")!;
Id vsid = ctx.gen_id("div_scrollbar_vertical")!;
short wdim = elem.div.scroll_y.on ? (ctx.focus_id == vsid ? SCROLLBAR_DIM*3 : SCROLLBAR_DIM) : 0;
short hdim = elem.div.scroll_x.on ? (ctx.focus_id == hsid ? SCROLLBAR_DIM*3 : SCROLLBAR_DIM) : 0;
short wdim = elem.div.scroll_y.on ? (elem.div.scroll_y.focus ? SCROLLBAR_DIM*3 : SCROLLBAR_DIM) : 0;
short hdim = elem.div.scroll_x.on ? (elem.div.scroll_x.focus ? SCROLLBAR_DIM*3 : SCROLLBAR_DIM) : 0;
if (elem.div.scroll_y.on) {
Rect vslider = {

View File

@ -59,6 +59,20 @@ macro Ctx.is_mouse_pressed(&ctx, MouseButtons btn) => (ctx.mouse_pressed() & btn
macro Ctx.is_mouse_released(&ctx, MouseButtons btn) => (ctx.mouse_released() & btn) != BTN_NONE;
macro Ctx.is_mouse_down(&ctx, MouseButtons btn) => (ctx.mouse_down() & btn) != BTN_NONE;
macro ElemEvents Ctx.get_elem_events(&ctx, Elem *elem)
{
// TODO: add the other events
// FIXME: active should be elsewhere
bool active = ctx.is_hovered(elem);
ElemEvents ev = {
.mouse_hover = ctx.is_hovered(elem),
.mouse_press = active & ctx.is_mouse_pressed(BTN_ANY),
.mouse_release = active & ctx.is_mouse_released(BTN_ANY),
.mouse_hold = active & ctx.is_mouse_down(BTN_ANY),
};
return ev;
}
// Mouse Button moved
fn void Ctx.input_mouse_button(&ctx, MouseButtons buttons)
{

View File

@ -54,7 +54,8 @@ fn ElemEvents! Ctx.slider_hor(&ctx,
Point m = ctx.input.mouse.pos;
elem.events = ctx.get_elem_events(elem);
if (ctx.elem_focus(elem) && ctx.is_mouse_down(BTN_LEFT)) {
if (parent.flags.has_focus && elem.events.mouse_hover &&
point_in_rect(m, handle) && elem.events.mouse_hold) {
*value = calc_value(elem.bounds.x, m.x, elem.bounds.w, hw);
elem.slider.handle.x = calc_slider(elem.bounds.x, elem.bounds.w-hw, *value);
elem.events.update = true;
@ -116,8 +117,10 @@ fn ElemEvents! Ctx.slider_ver(&ctx,
Point m = ctx.input.mouse.pos;
elem.events = ctx.get_elem_events(elem);
if (ctx.elem_focus(elem) && ctx.is_mouse_down(BTN_LEFT)) {
if (parent.flags.has_focus && elem.events.mouse_hover &&
point_in_rect(m, handle) &&
elem.events.mouse_hold) {
*value = calc_value(elem.bounds.y, m.y, elem.bounds.h, hh);
elem.slider.handle.y = calc_slider(elem.bounds.y, elem.bounds.h-hh, *value);
elem.events.update = true;