text input box
This commit is contained in:
parent
6d2594db2d
commit
972c9b581d
@ -138,7 +138,7 @@ fn void? Ctx.push_sprite(&ctx, Rect bounds, Rect texture, Id texture_id, int z_i
|
||||
ctx.push_cmd(&cmd, z_index)!;
|
||||
}
|
||||
|
||||
fn void? Ctx.push_string(&ctx, Rect bounds, String text, int z_index, Color hue = 0xffffffffu.to_rgba())
|
||||
fn void? Ctx.push_string(&ctx, Rect bounds, char[] text, int z_index, Color hue = 0xffffffffu.to_rgba())
|
||||
{
|
||||
if (text.len == 0) {
|
||||
return;
|
||||
@ -158,7 +158,7 @@ fn void? Ctx.push_string(&ctx, Rect bounds, String text, int z_index, Color hue
|
||||
short line_len;
|
||||
Codepoint cp;
|
||||
usz off, x;
|
||||
while ((cp = str_to_codepoint(text[off..], &x)) != 0) {
|
||||
while (off < text.len && (cp = str_to_codepoint(text[off..], &x)) != 0) {
|
||||
off += x;
|
||||
Glyph* gp;
|
||||
if (!ascii::is_cntrl((char)cp)) {
|
||||
|
@ -34,6 +34,7 @@ bitstruct ElemEvents : uint {
|
||||
bool mouse_release : 5;
|
||||
bool mouse_hold : 6;
|
||||
bool update : 7;
|
||||
bool text_input : 8;
|
||||
}
|
||||
|
||||
// element structure
|
||||
@ -111,7 +112,7 @@ struct Ctx {
|
||||
struct keyboard {
|
||||
char[TEXT_MAX] text;
|
||||
usz text_len;
|
||||
ModKeys down;
|
||||
ModKeys modkeys;
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,6 +344,7 @@ fn ElemEvents Ctx.get_elem_events(&ctx, Elem *elem)
|
||||
.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),
|
||||
.text_input = focus && (ctx.input.keyboard.text_len || ctx.input.keyboard.modkeys & KMOD_TXT),
|
||||
};
|
||||
return ev;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ bitstruct MouseButtons : uint {
|
||||
|
||||
// FIXME: all of these names were prefixed with key_ idk if this is better,
|
||||
// if it is remove the prefix on MouseButtons as well
|
||||
// Modifier Keys, same as SDL
|
||||
// Modifier Keys, intended as any key that is not text
|
||||
bitstruct ModKeys : uint {
|
||||
bool lshift : 0;
|
||||
bool rshift : 1;
|
||||
@ -39,12 +39,20 @@ bitstruct ModKeys : uint {
|
||||
bool caps : 9;
|
||||
bool mode : 10;
|
||||
bool scroll : 11;
|
||||
bool bkspc : 12;
|
||||
bool del : 13;
|
||||
// arrow keys
|
||||
bool up : 14;
|
||||
bool down : 15;
|
||||
bool left : 16;
|
||||
bool right : 17;
|
||||
}
|
||||
|
||||
const ModKeys KMOD_CTRL = {.lctrl = true, .rctrl = true};
|
||||
const ModKeys KMOD_SHIFT = {.lshift = true, .rshift = true};
|
||||
const ModKeys KMOD_ALT = {.lalt = true, .ralt = true};
|
||||
const ModKeys KMOD_GUI = {.lgui = true, .rgui = true};
|
||||
const ModKeys KMOD_TXT = {.bkspc = true, .del = true}; // modkeys that act like text input
|
||||
const ModKeys KMOD_NONE = {};
|
||||
const ModKeys KMOD_ANY = (ModKeys)(ModKeys.inner.max);
|
||||
|
||||
@ -60,7 +68,7 @@ const ModKeys KEY_ANY = (ModKeys)(ModKeys.inner.max);
|
||||
|
||||
fn bool Ctx.check_key_combo(&ctx, ModKeys mod, String keys)
|
||||
{
|
||||
bool is_mod = (bool)(ctx.input.keyboard.down & mod);
|
||||
bool is_mod = (bool)(ctx.input.keyboard.modkeys & mod);
|
||||
bool is_keys = true;
|
||||
String haystack = (String)ctx.input.keyboard.text[0..ctx.input.keyboard.text_len];
|
||||
char[2] needle;
|
||||
@ -187,9 +195,10 @@ fn void Ctx.input_char(&ctx, char c)
|
||||
ctx.input_text_utf8(b[..]);
|
||||
}
|
||||
|
||||
// Mouse Buttons down
|
||||
// Modifier keys, like control or backspace
|
||||
// TODO: make this call repetible to input modkeys one by one
|
||||
fn void Ctx.input_mod_keys(&ctx, ModKeys modkeys)
|
||||
{
|
||||
ctx.input.keyboard.down = modkeys;
|
||||
ctx.input.events.mod_key = (uint)ctx.input.keyboard.down != 0;
|
||||
ctx.input.keyboard.modkeys = modkeys;
|
||||
ctx.input.events.mod_key = (uint)ctx.input.keyboard.modkeys != 0;
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ module ugui;
|
||||
import std::io;
|
||||
|
||||
struct ElemText {
|
||||
char* str;
|
||||
char[] str;
|
||||
usz cursor; // cursor offset
|
||||
}
|
||||
|
||||
fn void? Ctx.text_unbounded(&ctx, String label, String text)
|
||||
@ -28,3 +29,66 @@ fn void? Ctx.text_unbounded(&ctx, String label, String text)
|
||||
|
||||
ctx.push_string(elem.bounds, text, parent.div.z_index)!;
|
||||
}
|
||||
|
||||
fn ElemEvents? Ctx.text_box(&ctx, String label, Rect size, char[] text, usz* text_len)
|
||||
{
|
||||
Id id = ctx.gen_id(label)!;
|
||||
|
||||
Elem *parent = ctx.get_parent()!;
|
||||
Elem *elem = ctx.get_elem(id)!;
|
||||
// add it to the tree
|
||||
ctx.tree.add(id, ctx.active_div)!;
|
||||
|
||||
// 1. Fill the element fields
|
||||
// this resets the flags
|
||||
elem.type = ETYPE_TEXT;
|
||||
elem.text.str = text;
|
||||
|
||||
// layout the text box
|
||||
elem.bounds = ctx.position_element(parent, size, true);
|
||||
|
||||
// check input and update the text
|
||||
elem.events = ctx.get_elem_events(elem);
|
||||
|
||||
if (elem.events.text_input) {
|
||||
usz l = ctx.input.keyboard.text_len;
|
||||
char[] t = ctx.input.keyboard.text[..l];
|
||||
|
||||
if (l != 0 && l < text.len - *text_len) {
|
||||
text[*text_len..*text_len+l] = t[..];
|
||||
*text_len += l;
|
||||
}
|
||||
|
||||
if (ctx.input.keyboard.modkeys.bkspc) {
|
||||
*text_len = *text_len > 0 ? *text_len-1 : 0;
|
||||
}
|
||||
|
||||
}
|
||||
elem.text.cursor = *text_len;
|
||||
|
||||
// draw the box
|
||||
short line_height = (short)ctx.font.line_height();
|
||||
Rect text_box = elem.bounds.sub({0,0,0,line_height});
|
||||
Rect input_box = {
|
||||
.x = elem.bounds.x,
|
||||
.y = elem.bounds.y + elem.bounds.h - line_height,
|
||||
.w = elem.bounds.w,
|
||||
.h = line_height,
|
||||
};
|
||||
Rect cursor;
|
||||
Point b = ctx.get_cursor_position((String)text[:elem.text.cursor])!;
|
||||
cursor = {
|
||||
.x = b.x,
|
||||
.y = b.y,
|
||||
.w = 3,
|
||||
.h = line_height,
|
||||
};
|
||||
cursor = cursor.off(elem.bounds.position());
|
||||
|
||||
ctx.push_rect(text_box, 0xabababffu.to_rgba(), parent.div.z_index, do_border: true)!;
|
||||
ctx.push_string(text_box, text[:*text_len], parent.div.z_index)!;
|
||||
ctx.push_rect(input_box, 0x424242ffu.to_rgba(), parent.div.z_index)!;
|
||||
ctx.push_rect(cursor, 0x00000042u.to_rgba(), parent.div.z_index)!;
|
||||
|
||||
return elem.events;
|
||||
}
|
||||
|
24
src/main.c3
24
src/main.c3
@ -62,9 +62,9 @@ fn int main(String[] args)
|
||||
defer ui.free();
|
||||
|
||||
ren::Renderer ren;
|
||||
ren.init("Ugui Test", 640, 480, true);
|
||||
ren.init("Ugui Test", 800, 600, true);
|
||||
defer ren.free();
|
||||
ui.input_window_size(640, 480)!!;
|
||||
ui.input_window_size(800, 600)!!;
|
||||
|
||||
//
|
||||
// FONT LOADING
|
||||
@ -145,6 +145,7 @@ fn int main(String[] args)
|
||||
case EVENT_KEY_DOWN:
|
||||
mod.rctrl = e.key.key == K_RCTRL ? !!(e.type == EVENT_KEY_DOWN) : mod.rctrl;
|
||||
mod.lctrl = e.key.key == K_LCTRL ? !!(e.type == EVENT_KEY_DOWN) : mod.lctrl;
|
||||
mod.bkspc = e.key.key == K_BACKSPACE ? !!(e.type == EVENT_KEY_DOWN) : mod.bkspc;
|
||||
|
||||
// pressing ctrl+key or alt+key does not generate a character as such no
|
||||
// TEXT_INPUT event is generated. When those keys are pressed we have to
|
||||
@ -154,6 +155,8 @@ fn int main(String[] args)
|
||||
ui.input_char((char)e.key.key);
|
||||
}
|
||||
}
|
||||
|
||||
if (e.type == EVENT_KEY_DOWN && e.key.key == K_RETURN) ui.input_char('\n');
|
||||
|
||||
case EVENT_TEXT_INPUT:
|
||||
ui.input_text_utf8(e.text.text.str_view());
|
||||
@ -226,19 +229,13 @@ fn int main(String[] args)
|
||||
static bool check;
|
||||
ui.checkbox("check1", "", {}, &check, "tick")!!;
|
||||
ui.toggle("toggle1", "", {}, &toggle)!!;
|
||||
|
||||
/*
|
||||
ui.layout_set_column()!!;
|
||||
ui.button_label(" A ")!!;
|
||||
ui.button_label(" B ")!!;
|
||||
ui.layout_next_column()!!;
|
||||
ui.button_label(" C ")!!;
|
||||
ui.button_label(" D ")!!;
|
||||
ui.layout_next_row()!!;
|
||||
ui.button_label(" E ")!!;
|
||||
*/
|
||||
};
|
||||
ui.draw_sprite("sprite1", "tux")!!;
|
||||
|
||||
static char[128] text_box = "ciao mamma";
|
||||
static usz text_len = "ciao mamma".len;
|
||||
ui.text_box("text input", {0,0,200,200}, text_box[..], &text_len)!!;
|
||||
|
||||
ui.div_end()!!;
|
||||
|
||||
ui.div_begin("second", ugui::DIV_FILL, scroll_x: true, scroll_y: true)!!;
|
||||
@ -280,7 +277,6 @@ fn int main(String[] args)
|
||||
};
|
||||
ui.div_end()!!;
|
||||
|
||||
|
||||
ui.frame_end()!!;
|
||||
/* End UI Handling */
|
||||
ui_times.push(clock.mark());
|
||||
|
Loading…
Reference in New Issue
Block a user