Open ryuukk opened 2 years ago
I have a version without changing the function arguments, isntead i just have a new field in the Context I also have some basic mouse functionality
That's in D, it's a WIP, i'll port it to C when the PR is ready:
TODO:
BONUS:
textedit
?int textbox_raw(Context *ctx, char *buf, int bufsz, Id id, Rect r, int opt)
{
Id lastFocus = ctx.focus;
int res = 0;
update_control(ctx, id, r, OPT_HOLDFOCUS);
if (ctx.focus != lastFocus && ctx.focus == id)
{
int len = cast(int) str_len(buf);
ctx.textbox_index = len;
ctx.textbox_select_min = 0;
ctx.textbox_select_max = 0;
}
if (ctx.focus == id)
{
scope(exit) (ctx.textbox_index)+=ctx.input_text_written;
/* handle text input */
int len = cast(int) str_len(buf);
int n = min(bufsz - len - 1, cast(int) str_len(ctx.input_text.ptr));
int i = ctx.textbox_index;
int needMove = len - i;
if (n > 0)
{
if (needMove > 0)
{
memmove(buf + i + n, buf + i, needMove);
}
memcpy(buf + i, ctx.input_text.ptr, n);
len += n;
buf[len] = '\0';
res |= RES_CHANGE;
}
/* handle backspace */
if ((ctx.key_pressed & KEY_BACKSPACE || ctx.key_repeated & KEY_BACKSPACE) && len > 0)
{
/* skip utf-8 continuation bytes */
while ((buf[--len] & 0xc0) == 0x80 && len > 0)
{
}
if (i > 0)
{
ctx.textbox_index --;
memmove(buf + (ctx.textbox_index), buf + (ctx.textbox_index) + 1, len - (ctx.textbox_index) + 1);
buf[len] = '\0';
res |= RES_CHANGE;
}
}
/* handle backspace */
if ((ctx.key_pressed & KEY_DELETE || ctx.key_repeated & KEY_DELETE) && len > 0)
{
if (len == 0 || i == (len+1)) goto skip;
memmove(buf + (ctx.textbox_index), buf + (ctx.textbox_index) + 1, len - (ctx.textbox_index) + 1);
buf[len] = '\0';
res |= RES_CHANGE;
}
skip:{}
if (ctx.mouse_pressed & MOUSE_LEFT && len > 0)
{
Font font = ctx.style.font;
int offsetX = ctx.mouse_pos.x - r.x;
int textw = ctx.text_width(font, buf, len);
int textwIndex = ctx.text_width(font, &buf[ctx.textbox_index], len);
int w = max(textw, textwIndex);
// click too far, set index to len
if (offsetX > textw)
{
LINFO("sup {} {} {}", offsetX, w, len);
ctx.textbox_index = len;
}
else
{
// TODO: doesn't work when text has scrolled..
// need to figure out a better way to handle this
// for now i guess that'll do...
// aaaaa[aaaaaaaaaaa]aaaaaa
int num = cast(int) (offsetX / cast(float) w * len);
// LINFO("les {} {} {}", offsetX, textw, num);
ctx.textbox_index = num;
}
}
/* handle return */
if (ctx.key_pressed & KEY_RETURN)
{
set_focus(ctx, 0);
res |= RES_SUBMIT;
}
else if (ctx.key_pressed & KEY_LEFT)
{
ctx.textbox_index--;
}
else if (ctx.key_pressed & KEY_RIGHT)
{
ctx.textbox_index ++;
}
if ((ctx.textbox_index) < 0) ctx.textbox_index = 0;
if (ctx.textbox_index >= len) ctx.textbox_index = len;
}
/* draw */
draw_control_frame(ctx, id, r, COLOR_BASE, 0);
if (ctx.focus == id)
{
Color color = ctx.style.colors[COLOR_TEXT];
Font font = ctx.style.font;
int textw = ctx.text_width(font, buf, ctx.textbox_index);
int texth = ctx.text_height(font);
int ofx = r.w - ctx.style.padding - textw - 1;
int textx = r.x + min(ofx, ctx.style.padding);
int texty = r.y + (r.h - texth) / 2;
push_clip_rect(ctx, r);
// text
draw_text(ctx, font, buf, -1, vec2(textx, texty), color);
// cursor
draw_rect(ctx, rect(textx + textw, texty, 1, texth), color);
// draw selection
if (ctx.textbox_select_min != ctx.textbox_select_max)
{
}
pop_clip_rect(ctx);
}
else
{
draw_control_text(ctx, buf, r, COLOR_TEXT, 0);
}
return res;
}
Hi @ryuukk did you ever finish this work to submit a PR? It would be very useful to have a standard solution for all microui users.
@ryuukk , I am curious about this as well, since I could then port these changes to my port :P
Hi, thanks for this awesome lib!
One thing that i felt was missing was proper textbox navigation, being able to correct a character without having to delete the entire thing
So i spent some time and managed to come up with something:
https://user-images.githubusercontent.com/44361234/147188029-caad8964-5768-4e6c-869c-dee355282a0b.mp4
Please let me know if you want to see more improvement to the code, so i can submit a PR!
Changes:
And here is how the new function looks like:
We basically introduce a new argument to the textbox_raw function A pointer to an int so we can track the index, and user can specific where the index should start