popups
This commit is contained in:
parent
e7cfa3517f
commit
32a57d5293
@ -58,6 +58,7 @@ struct Elem {
|
|||||||
Rect children_bounds;
|
Rect children_bounds;
|
||||||
ElemType type;
|
ElemType type;
|
||||||
Layout layout;
|
Layout layout;
|
||||||
|
int z_index;
|
||||||
union {
|
union {
|
||||||
ElemDiv div;
|
ElemDiv div;
|
||||||
ElemButton button;
|
ElemButton button;
|
||||||
@ -100,6 +101,7 @@ struct Ctx {
|
|||||||
bool has_focus;
|
bool has_focus;
|
||||||
struct input {
|
struct input {
|
||||||
InputEvents events;
|
InputEvents events;
|
||||||
|
int z_index; // the layer the input events need to be propageted to
|
||||||
struct mouse {
|
struct mouse {
|
||||||
Point pos, delta;
|
Point pos, delta;
|
||||||
// mouse_down: bitmap of mouse buttons that are held
|
// mouse_down: bitmap of mouse buttons that are held
|
||||||
@ -178,6 +180,11 @@ fn Elem*? Ctx.get_elem(&ctx, Id id, ElemType type)
|
|||||||
} else {
|
} else {
|
||||||
elem.type = type;
|
elem.type = type;
|
||||||
}
|
}
|
||||||
|
// FIXME: this is crap
|
||||||
|
if (ctx.tree.is_used(ctx.active_div)) {
|
||||||
|
elem.z_index = ctx.get_active_div()!.z_index;
|
||||||
|
}
|
||||||
|
|
||||||
elem.tree_idx = ctx.tree.add(ctx.active_div, id);
|
elem.tree_idx = ctx.tree.add(ctx.active_div, id);
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
@ -242,10 +249,11 @@ fn void? Ctx.frame_begin(&ctx)
|
|||||||
// if the window has focus then the root element also has focus, no other
|
// 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
|
// computation needed, child elements need to check the mouse positon and
|
||||||
// other stuff
|
// other stuff
|
||||||
|
ctx.input.z_index = 0;
|
||||||
//elem.flags.has_focus = ctx.has_focus;
|
//elem.flags.has_focus = ctx.has_focus;
|
||||||
|
|
||||||
elem.bounds = {0, 0, ctx.width, ctx.height};
|
elem.bounds = {0, 0, ctx.width, ctx.height};
|
||||||
elem.div.z_index = 0;
|
elem.z_index = 0;
|
||||||
elem.div.scroll_x.enabled = false;
|
elem.div.scroll_x.enabled = false;
|
||||||
elem.div.scroll_y.enabled = false;
|
elem.div.scroll_y.enabled = false;
|
||||||
elem.layout.dir = ROW;
|
elem.layout.dir = ROW;
|
||||||
@ -309,7 +317,8 @@ $endif
|
|||||||
|
|
||||||
// sort the command buffer by the z-index
|
// sort the command buffer by the z-index
|
||||||
// FIXME: sorting the buffer fucks with scissor commands that have to be kept in place
|
// FIXME: sorting the buffer fucks with scissor commands that have to be kept in place
|
||||||
//ctx.cmd_queue.sort()!;
|
// TODO: instead of sorting at the end perform ordered inserts into the command buffer
|
||||||
|
ctx.cmd_queue.sort()!;
|
||||||
|
|
||||||
// foreach (i, c: ctx.cmd_queue) {
|
// foreach (i, c: ctx.cmd_queue) {
|
||||||
// io::printf("[%d]: ", i);
|
// io::printf("[%d]: ", i);
|
||||||
@ -335,6 +344,8 @@ macro bool Ctx.elem_focus(&ctx, Elem *elem)
|
|||||||
// FIXME: hacked together, please do better
|
// FIXME: hacked together, please do better
|
||||||
fn ElemEvents Ctx.get_elem_events(&ctx, Elem *elem)
|
fn ElemEvents Ctx.get_elem_events(&ctx, Elem *elem)
|
||||||
{
|
{
|
||||||
|
if (ctx.input.z_index != elem.z_index) return {};
|
||||||
|
|
||||||
bool hover = ctx.is_hovered(elem);
|
bool hover = ctx.is_hovered(elem);
|
||||||
bool focus = ctx.elem_focus(elem) || (hover && ctx.is_mouse_pressed(BTN_LEFT));
|
bool focus = ctx.elem_focus(elem) || (hover && ctx.is_mouse_pressed(BTN_LEFT));
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
|||||||
update_parent_size(elem, parent);
|
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();
|
Rect content_bounds = elem.content_bounds();
|
||||||
|
|
||||||
Rect icon_bounds = {
|
Rect icon_bounds = {
|
||||||
@ -72,12 +73,12 @@ fn ElemEvents? Ctx.button_id(&ctx, Id id, String label, String icon)
|
|||||||
s.bg = s.accent;
|
s.bg = s.accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.push_rect(elem.bounds.pad(style.margin), parent.div.z_index, &s)!;
|
ctx.push_rect(elem.bounds.pad(style.margin), parent.z_index, &s)!;
|
||||||
if (icon != "") {
|
if (icon != "") {
|
||||||
ctx.push_sprite(icon_bounds, sprite.uv(), ctx.sprite_atlas.id, parent.div.z_index, type: sprite.type)!;
|
ctx.push_sprite(icon_bounds, sprite.uv(), ctx.sprite_atlas.id, parent.z_index, type: sprite.type)!;
|
||||||
}
|
}
|
||||||
if (label != "") {
|
if (label != "") {
|
||||||
ctx.layout_string(label, text_bounds, CENTER, parent.div.z_index, style.fg)!;
|
ctx.layout_string(label, text_bounds, CENTER, parent.z_index, style.fg)!;
|
||||||
}
|
}
|
||||||
return elem.events;
|
return elem.events;
|
||||||
}
|
}
|
||||||
@ -138,20 +139,20 @@ fn void? Ctx.checkbox_id(&ctx, Id id, String description, bool* active, String t
|
|||||||
s.border = style.border;
|
s.border = style.border;
|
||||||
s.radius = style.radius;
|
s.radius = style.radius;
|
||||||
|
|
||||||
ctx.layout_string(description, text_bounds, CENTER, parent.div.z_index, style.fg)!;
|
ctx.layout_string(description, text_bounds, CENTER, parent.z_index, style.fg)!;
|
||||||
if (tick_sprite != "") {
|
if (tick_sprite != "") {
|
||||||
ctx.push_rect(check_bounds, parent.div.z_index, &s)!;
|
ctx.push_rect(check_bounds, parent.z_index, &s)!;
|
||||||
if (*active) {
|
if (*active) {
|
||||||
Sprite* sprite = ctx.sprite_atlas.get(tick_sprite)!;
|
Sprite* sprite = ctx.sprite_atlas.get(tick_sprite)!;
|
||||||
Id tex_id = ctx.sprite_atlas.id;
|
Id tex_id = ctx.sprite_atlas.id;
|
||||||
ctx.push_sprite(sprite.rect().center_to(check_bounds), sprite.uv(), tex_id, parent.div.z_index, type: sprite.type)!;
|
ctx.push_sprite(sprite.rect().center_to(check_bounds), sprite.uv(), tex_id, parent.z_index, type: sprite.type)!;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (*active) {
|
if (*active) {
|
||||||
s.bg = style.primary;
|
s.bg = style.primary;
|
||||||
ctx.push_rect(check_bounds, parent.div.z_index, &s)!;
|
ctx.push_rect(check_bounds, parent.z_index, &s)!;
|
||||||
} else {
|
} else {
|
||||||
ctx.push_rect(check_bounds, parent.div.z_index, &s)!;
|
ctx.push_rect(check_bounds, parent.z_index, &s)!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,10 +217,10 @@ fn void? Ctx.toggle_id(&ctx, Id id, String description, bool* active)
|
|||||||
s.secondary = style.secondary;
|
s.secondary = style.secondary;
|
||||||
s.border = style.border;
|
s.border = style.border;
|
||||||
s.radius = style.radius;
|
s.radius = style.radius;
|
||||||
ctx.layout_string(description, text_bounds, CENTER, parent.div.z_index, style.fg)!;
|
ctx.layout_string(description, text_bounds, CENTER, parent.z_index, style.fg)!;
|
||||||
ctx.push_rect(toggle_bounds, parent.div.z_index, &s)!;
|
ctx.push_rect(toggle_bounds, parent.z_index, &s)!;
|
||||||
s.bg = style.primary;
|
s.bg = style.primary;
|
||||||
s.border = {};
|
s.border = {};
|
||||||
ctx.push_rect(toggle.pad(style.border), parent.div.z_index, &s)!;
|
ctx.push_rect(toggle.pad(style.border), parent.z_index, &s)!;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ struct ElemDiv {
|
|||||||
bool on;
|
bool on;
|
||||||
float value;
|
float value;
|
||||||
}
|
}
|
||||||
int z_index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -81,7 +80,7 @@ fn void? Ctx.div_begin_id(&ctx,
|
|||||||
|
|
||||||
elem.div.scroll_x.enabled = scroll_x;
|
elem.div.scroll_x.enabled = scroll_x;
|
||||||
elem.div.scroll_y.enabled = scroll_y;
|
elem.div.scroll_y.enabled = scroll_y;
|
||||||
elem.div.z_index = parent.div.z_index + 1;
|
if (ctx.input.z_index < elem.z_index) ctx.input.z_index = elem.z_index;
|
||||||
|
|
||||||
// update layout with correct info
|
// update layout with correct info
|
||||||
elem.layout = {
|
elem.layout = {
|
||||||
@ -97,11 +96,11 @@ fn void? Ctx.div_begin_id(&ctx,
|
|||||||
elem.layout.origin.y = off.y;
|
elem.layout.origin.y = off.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.push_rect(elem.bounds.pad(style.margin), elem.div.z_index, style)!;
|
ctx.push_rect(elem.bounds.pad(style.margin), elem.z_index, style)!;
|
||||||
|
|
||||||
// update the ctx scissor, it HAS to be after drawing the background
|
// update the ctx scissor, it HAS to be after drawing the background
|
||||||
ctx.div_scissor = elem.bounds.pad(elem.layout.content_offset);
|
ctx.div_scissor = elem.bounds.pad(elem.layout.content_offset);
|
||||||
ctx.push_scissor(elem.bounds.pad(elem.layout.content_offset), elem.div.z_index)!;
|
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);
|
||||||
|
|
||||||
@ -160,9 +159,67 @@ fn Id? Ctx.div_end(&ctx)
|
|||||||
ctx.active_div = ctx.tree.parentof(ctx.active_div);
|
ctx.active_div = ctx.tree.parentof(ctx.active_div);
|
||||||
Elem* parent = ctx.get_parent()!;
|
Elem* parent = ctx.get_parent()!;
|
||||||
ctx.div_scissor = parent.bounds.pad(parent.layout.content_offset);
|
ctx.div_scissor = parent.bounds.pad(parent.layout.content_offset);
|
||||||
ctx.reset_scissor(elem.div.z_index)!;
|
ctx.reset_scissor(elem.z_index)!;
|
||||||
|
|
||||||
update_parent_size(elem, parent);
|
update_parent_size(elem, parent);
|
||||||
|
|
||||||
return elem.id;
|
return elem.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro bool? Ctx.popup_begin(&ctx, Point pos,
|
||||||
|
Size width, Size height,
|
||||||
|
LayoutDirection dir = ROW, Anchor anchor = TOP_LEFT,
|
||||||
|
bool scroll_x = false, bool scroll_y = false,
|
||||||
|
...
|
||||||
|
)
|
||||||
|
=> ctx.popup_begin_id(@compute_id($vasplat), pos, width, height, dir, anchor, scroll_x, scroll_y);
|
||||||
|
fn bool? Ctx.popup_begin_id(&ctx,
|
||||||
|
Id id,
|
||||||
|
Point pos,
|
||||||
|
Size width, Size height,
|
||||||
|
LayoutDirection dir, Anchor anchor,
|
||||||
|
bool scroll_x, bool scroll_y
|
||||||
|
)
|
||||||
|
{
|
||||||
|
id = ctx.gen_id(id)!;
|
||||||
|
|
||||||
|
Elem* elem = ctx.get_elem(id, ETYPE_DIV)!;
|
||||||
|
Elem* parent = ctx.find_elem(ctx.active_div); // pop-up parent is always root
|
||||||
|
ctx.active_div = elem.tree_idx;
|
||||||
|
|
||||||
|
Style* style = ctx.styles.get_style(@str_hash("popup"));
|
||||||
|
|
||||||
|
elem.div.scroll_x.enabled = scroll_x;
|
||||||
|
elem.div.scroll_y.enabled = scroll_y;
|
||||||
|
elem.z_index++;
|
||||||
|
if (ctx.input.z_index < elem.z_index) ctx.input.z_index = elem.z_index;
|
||||||
|
|
||||||
|
// update layout with correct info
|
||||||
|
elem.layout = {
|
||||||
|
.w = width,
|
||||||
|
.h = height,
|
||||||
|
.dir = dir,
|
||||||
|
.anchor = anchor,
|
||||||
|
.content_offset = style.margin + style.border + style.padding,
|
||||||
|
.absolute = true,
|
||||||
|
.origin.x = pos.x - parent.bounds.x,
|
||||||
|
.origin.y = pos.y - parent.bounds.y,
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.push_rect(elem.bounds.pad(style.margin), elem.z_index, style)!;
|
||||||
|
|
||||||
|
// update the ctx scissor, it HAS to be after drawing the background
|
||||||
|
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);
|
||||||
|
|
||||||
|
// check close condition, mouse release anywhere outside the div bounds
|
||||||
|
if ((ctx.mouse_released() & BTN_ANY) && !elem.events.mouse_hover) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: check active
|
||||||
|
// TODO: check resizeable
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -57,11 +57,11 @@ fn ElemEvents? Ctx.slider_hor_id(&ctx, Id id, Size w, Size h, float* value, floa
|
|||||||
Style s = *style;
|
Style s = *style;
|
||||||
Rect padding = s.padding;
|
Rect padding = s.padding;
|
||||||
s.padding = {};
|
s.padding = {};
|
||||||
ctx.push_rect(bg_bounds, parent.div.z_index, &s)!;
|
ctx.push_rect(bg_bounds, parent.z_index, &s)!;
|
||||||
s.bg = s.primary;
|
s.bg = s.primary;
|
||||||
s.padding = padding;
|
s.padding = padding;
|
||||||
s.border = {};
|
s.border = {};
|
||||||
ctx.push_rect(elem.slider.handle, parent.div.z_index, &s)!;
|
ctx.push_rect(elem.slider.handle, parent.z_index, &s)!;
|
||||||
|
|
||||||
return elem.events;
|
return elem.events;
|
||||||
}
|
}
|
||||||
@ -121,11 +121,11 @@ fn ElemEvents? Ctx.slider_ver_id(&ctx, Id id, Size w, Size h, float* value, floa
|
|||||||
Style s = *style;
|
Style s = *style;
|
||||||
Rect padding = s.padding;
|
Rect padding = s.padding;
|
||||||
s.padding = {};
|
s.padding = {};
|
||||||
ctx.push_rect(bg_bounds, parent.div.z_index, &s)!;
|
ctx.push_rect(bg_bounds, parent.z_index, &s)!;
|
||||||
s.bg = s.primary;
|
s.bg = s.primary;
|
||||||
s.padding = padding;
|
s.padding = padding;
|
||||||
s.border = {};
|
s.border = {};
|
||||||
ctx.push_rect(elem.slider.handle, parent.div.z_index, &s)!;
|
ctx.push_rect(elem.slider.handle, parent.z_index, &s)!;
|
||||||
|
|
||||||
return elem.events;
|
return elem.events;
|
||||||
}
|
}
|
||||||
@ -177,8 +177,8 @@ fn void? Ctx.scrollbar(&ctx, Id id, float *value, float handle_percent, bool ver
|
|||||||
|
|
||||||
|
|
||||||
Rect bg_bounds = elem.bounds.pad(style.margin);
|
Rect bg_bounds = elem.bounds.pad(style.margin);
|
||||||
ctx.push_rect(bg_bounds, parent.div.z_index, style)!;
|
ctx.push_rect(bg_bounds, parent.z_index, style)!;
|
||||||
ctx.push_rect(elem.slider.handle, parent.div.z_index, &&(Style){.bg = style.primary, .radius = style.radius})!;
|
ctx.push_rect(elem.slider.handle, parent.z_index, &&(Style){.bg = style.primary, .radius = style.radius})!;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro short calc_slider(short off, short dim, float value) => (short)off + (short)(dim * value);
|
macro short calc_slider(short off, short dim, float value) => (short)off + (short)(dim * value);
|
||||||
|
@ -22,5 +22,5 @@ fn void? Ctx.sprite_id(&ctx, Id id, String name)
|
|||||||
update_parent_size(elem, parent);
|
update_parent_size(elem, parent);
|
||||||
|
|
||||||
Id tex_id = ctx.sprite_atlas.id;
|
Id tex_id = ctx.sprite_atlas.id;
|
||||||
return ctx.push_sprite(elem.bounds, sprite.uv(), tex_id, parent.div.z_index, type: sprite.type)!;
|
return ctx.push_sprite(elem.bounds, sprite.uv(), tex_id, parent.z_index, type: sprite.type)!;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ fn void? Ctx.text_id(&ctx, Id id, String text)
|
|||||||
|
|
||||||
update_parent_size(elem, parent);
|
update_parent_size(elem, parent);
|
||||||
|
|
||||||
ctx.layout_string(text, elem.bounds.pad(elem.layout.content_offset), TOP_LEFT, parent.div.z_index, style.fg)!;
|
ctx.layout_string(text, elem.bounds.pad(elem.layout.content_offset), TOP_LEFT, parent.z_index, style.fg)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -75,17 +75,17 @@ fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te, Anchor
|
|||||||
|
|
||||||
Rect bg_bounds = elem.bounds.pad(style.margin);
|
Rect bg_bounds = elem.bounds.pad(style.margin);
|
||||||
Rect text_bounds = elem.bounds.pad(elem.layout.content_offset);
|
Rect text_bounds = elem.bounds.pad(elem.layout.content_offset);
|
||||||
ctx.push_rect(bg_bounds, parent.div.z_index, style)!;
|
ctx.push_rect(bg_bounds, parent.z_index, style)!;
|
||||||
Rect cur;
|
Rect cur;
|
||||||
cur = ctx.layout_string(elem.text.te.to_string(), text_bounds, text_alignment, parent.div.z_index, style.fg, elem.text.te.cursor)!;
|
cur = ctx.layout_string(elem.text.te.to_string(), text_bounds, text_alignment, parent.z_index, style.fg, elem.text.te.cursor)!;
|
||||||
|
|
||||||
// draw the cursor if the element has focus
|
// draw the cursor if the element has focus
|
||||||
cur.w = 2;
|
cur.w = 2;
|
||||||
cur.x -= 2;
|
cur.x -= 2;
|
||||||
if (elem.events.has_focus) {
|
if (elem.events.has_focus) {
|
||||||
ctx.push_scissor(text_bounds, parent.div.z_index)!;
|
ctx.push_scissor(text_bounds, parent.z_index)!;
|
||||||
ctx.push_rect(cur, parent.div.z_index, &&(Style){.bg = style.fg})!;
|
ctx.push_rect(cur, parent.z_index, &&(Style){.bg = style.fg})!;
|
||||||
ctx.reset_scissor(parent.div.z_index)!;
|
ctx.reset_scissor(parent.z_index)!;
|
||||||
}
|
}
|
||||||
return elem.events;
|
return elem.events;
|
||||||
}
|
}
|
17
src/main.c3
17
src/main.c3
@ -209,7 +209,7 @@ fn int main(String[] args)
|
|||||||
|
|
||||||
if (ui.check_key_combo(ugui::KMOD_CTRL, "q")) quit = true;
|
if (ui.check_key_combo(ugui::KMOD_CTRL, "q")) quit = true;
|
||||||
|
|
||||||
const String APPLICATION = "debug";
|
const String APPLICATION = "calculator";
|
||||||
$switch APPLICATION:
|
$switch APPLICATION:
|
||||||
$case "debug":
|
$case "debug":
|
||||||
debug_app(&ui);
|
debug_app(&ui);
|
||||||
@ -382,6 +382,20 @@ fn void calculator(ugui::Ctx* ui, TextEdit* te)
|
|||||||
if (len > 0) len--;
|
if (len > 0) len--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool toggle;
|
||||||
|
static ugui::Point pos;
|
||||||
|
if (ui.is_mouse_released(ugui::BTN_RIGHT)) {
|
||||||
|
pos = ui.input.mouse.pos;
|
||||||
|
toggle = !toggle;
|
||||||
|
}
|
||||||
|
if (toggle) {
|
||||||
|
toggle = ui.popup_begin(pos, ugui::@fit(50), ugui::@fit(100), COLUMN)!!;
|
||||||
|
ui.button("Uno")!!;
|
||||||
|
ui.button("Due")!!;
|
||||||
|
ui.button("Tre")!!;
|
||||||
|
ui.button("Quattro")!!;
|
||||||
|
ui.div_end()!!;
|
||||||
|
}
|
||||||
// ui input/output
|
// ui input/output
|
||||||
ui.@div(ugui::@grow(), ugui::@grow(), ROW, CENTER) { // center everything on the screen
|
ui.@div(ugui::@grow(), ugui::@grow(), ROW, CENTER) { // center everything on the screen
|
||||||
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN, TOP_LEFT) {
|
ui.@div(ugui::@fit(), ugui::@fit(), COLUMN, TOP_LEFT) {
|
||||||
@ -446,4 +460,5 @@ fn void calculator(ugui::Ctx* ui, TextEdit* te)
|
|||||||
ui.text_box(ugui::@grow(), ugui::@exact(100), te, RIGHT)!!;
|
ui.text_box(ugui::@grow(), ugui::@exact(100), te, RIGHT)!!;
|
||||||
}!!;
|
}!!;
|
||||||
}!!; }!!;
|
}!!; }!!;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user