diff --git a/src/main.c3 b/src/main.c3 index 42f38a9..2a1a5d9 100644 --- a/src/main.c3 +++ b/src/main.c3 @@ -122,7 +122,7 @@ fn int main(String[] args) ui.div_begin("main", ugui::Rect{.w=ui.width/2})!!; {| - ui.layout_set_row()!!; + ui.layout_set_column()!!; if (ui.button("button0", ugui::Rect{0,0,30,30}, toggle)!!.mouse_press) { io::printn("press button0"); toggle = !toggle; diff --git a/src/ugui_button.c3 b/src/ugui_button.c3 index e1d9fb6..598389a 100644 --- a/src/ugui_button.c3 +++ b/src/ugui_button.c3 @@ -4,8 +4,7 @@ import std::io; // button element struct ElemButton { - Color color; - bool active; + int filler; } // draw a button, return the events on that button @@ -20,7 +19,6 @@ 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?; } @@ -31,22 +29,16 @@ 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) { - elem.button.color = uint_to_rgba(0xff00ffff); + col = uint_to_rgba(0xff0000ff); + } else if (ctx.elem_focus(elem) || elem.events.mouse_hover) { + col = uint_to_rgba(0xff00ffff); } // Draw the button - ctx.push_rect(elem.bounds, elem.button.color, do_border: true, do_radius: true)!; + ctx.push_rect(elem.bounds, col, do_border: true, do_radius: true)!; return elem.events; } diff --git a/src/ugui_core.c3 b/src/ugui_core.c3 index 0a34627..065af5d 100644 --- a/src/ugui_core.c3 +++ b/src/ugui_core.c3 @@ -32,8 +32,7 @@ enum ElemType { bitstruct ElemFlags : uint { bool updated : 0; - bool has_focus : 1; - bool is_new : 2; + bool is_new : 1; } bitstruct ElemEvents : uint { @@ -134,6 +133,9 @@ 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 } @@ -195,13 +197,15 @@ macro Ctx.get_elem(&ctx, 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 = label.hash(); - return ctx.cache.search(id); -} +//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_tree_idx(&ctx, isz idx) @private { @@ -252,7 +256,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, @@ -317,8 +321,39 @@ $endif <* * @ensure elem != null - *> -fn bool Ctx.is_hovered(&ctx, Elem *elem) +*> +macro 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; +} + diff --git a/src/ugui_div.c3 b/src/ugui_div.c3 index 9647a84..a59d37d 100644 --- a/src/ugui_div.c3 +++ b/src/ugui_div.c3 @@ -23,9 +23,6 @@ struct ElemDiv { 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) @@ -71,13 +68,6 @@ 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) @@ -87,7 +77,9 @@ fn void! Ctx.div_end(&ctx) Elem* elem = ctx.get_elem_by_tree_idx(ctx.active_div)!; elem.div.pcb = elem.div.children_bounds; - elem.events = ctx.get_elem_events(elem); + // 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); Rect cb = elem.div.pcb; // children bounds bottom-right corner diff --git a/src/ugui_input.c3 b/src/ugui_input.c3 index 0c4421e..a82240b 100644 --- a/src/ugui_input.c3 +++ b/src/ugui_input.c3 @@ -59,20 +59,6 @@ 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) { diff --git a/src/ugui_slider.c3 b/src/ugui_slider.c3 index 81671db..e078103 100644 --- a/src/ugui_slider.c3 +++ b/src/ugui_slider.c3 @@ -54,8 +54,7 @@ fn ElemEvents! Ctx.slider_hor(&ctx, Point m = ctx.input.mouse.pos; elem.events = ctx.get_elem_events(elem); - if (parent.flags.has_focus && elem.events.mouse_hover && - point_in_rect(m, handle) && elem.events.mouse_hold) { + if (ctx.elem_focus(elem) && 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; @@ -117,10 +116,8 @@ fn ElemEvents! Ctx.slider_ver(&ctx, Point m = ctx.input.mouse.pos; elem.events = ctx.get_elem_events(elem); - - if (parent.flags.has_focus && elem.events.mouse_hover && - point_in_rect(m, handle) && - elem.events.mouse_hold) { + + if (ctx.elem_focus(elem) && 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;