module ugui; import std::io; struct ElemText { Id hash; TextSize size; TextEdit* te; } /* Layout some text without bounds. * There is a limitation where the current frame bounds are based on the last frame, this is usually * not a problem but it is in the situation where the text changes almost all frames. */ macro Ctx.text(&ctx, String text, ...) => ctx.text_id(@compute_id($vasplat), text); fn void? Ctx.text_id(&ctx, Id id, String text) { id = ctx.gen_id(id)!; Elem *parent = ctx.get_parent()!; Elem *elem = ctx.get_elem(id, ETYPE_TEXT)!; Style* style = ctx.styles.get_style(@str_hash("text")); Id text_hash = text.hash(); if (elem.flags.is_new || elem.text.hash != text_hash) { elem.text.size = ctx.measure_string(text)!; } elem.text.hash = text_hash; elem.layout.w = @fit(style.size); elem.layout.h = @fit(style.size); elem.layout.text = elem.text.size; elem.layout.content_offset = style.margin + style.border + style.padding; update_parent_size(elem, parent); ctx.layout_string(text, elem.bounds.pad(elem.layout.content_offset), TOP_LEFT, parent.div.z_index, style.fg)!; } macro Ctx.text_box(&ctx, Size w, Size h, TextEdit* te, ...) => ctx.text_box_id(@compute_id($vasplat), w, h, te); fn ElemEvents? Ctx.text_box_id(&ctx, Id id, Size w, Size h, TextEdit* te) { id = ctx.gen_id(id)!; Elem *parent = ctx.get_parent()!; Elem *elem = ctx.get_elem(id, ETYPE_TEXT)!; Style* style = ctx.styles.get_style(@str_hash("text-box")); elem.text.te = te; Id text_hash = te.to_string().hash(); if (elem.flags.is_new || elem.text.hash != text_hash) { elem.text.size = ctx.measure_string(te.to_string())!; } elem.text.hash = text_hash; elem.layout.w = w; elem.layout.h = h; elem.layout.text = elem.text.size; elem.layout.content_offset = style.margin + style.border + style.padding; update_parent_size(elem, parent); // check input and update the text elem.events = ctx.get_elem_events(elem); if (elem.events.text_input || elem.events.key_press) { ctx.text_edit(elem.text.te); } // draw the box Rect bg_bounds = elem.bounds.pad(style.margin); Rect text_bounds = elem.bounds.pad(elem.layout.content_offset); ctx.push_rect(bg_bounds, parent.div.z_index, style)!; Rect cur; cur = ctx.layout_string(elem.text.te.to_string(), text_bounds, TOP_LEFT, parent.div.z_index, style.fg, elem.text.te.cursor)!; // draw the cursor if the element has focus cur.w = 2; if (elem.events.has_focus) { ctx.push_scissor(text_bounds, parent.div.z_index)!; ctx.push_rect(cur, parent.div.z_index, &&(Style){.bg = style.fg})!; ctx.reset_scissor(parent.div.z_index)!; } return elem.events; }