fn_test and ui_text_input work
This commit is contained in:
166
src/ui/ui.c
166
src/ui/ui.c
@@ -206,38 +206,147 @@ fn ui_signal_t ui_signal_from_box(ui_box_t *box) {
|
||||
}
|
||||
|
||||
fn void ui_text_input_draw(ui_box_t *box) {
|
||||
r2f32_t rect = box->final_rect;
|
||||
|
||||
v4f32_t background_color = box->background_color;
|
||||
v4f32_t text_color = box->text_color;
|
||||
v4f32_t border_color = box->border_color;
|
||||
r2f32_t rect = box->final_rect; // @todo: this or clipped?
|
||||
if (ui_is_active_box(box)) {
|
||||
f32 active_t = f32_ease_out_n(box->active_t, 50.f);
|
||||
active_t = f32_clamp01(active_t);
|
||||
background_color = v4f32_lerp(background_color, box->bg_active_color, 1.0);
|
||||
text_color = v4f32_lerp(text_color, box->text_active_color, active_t);
|
||||
} else if (ui_is_hot_box(box)) {
|
||||
f32 hot_t = f32_ease_out_n(box->hot_t, 3.f);
|
||||
hot_t = f32_clamp01(hot_t);
|
||||
background_color = v4f32_lerp(background_color, box->bg_hot_color, hot_t);
|
||||
text_color = v4f32_lerp(background_color, box->text_hot_color, hot_t);
|
||||
} else if (ui_is_focused_box(box)) {
|
||||
background_color = v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.6f, 0.95f, 1.0f});
|
||||
text_color = v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.6f, 0.7f, 1.0f});
|
||||
}
|
||||
|
||||
rn_draw_rect(rect, background_color);
|
||||
rn_draw_rect_border(rect, border_color, box->border_thickness);
|
||||
|
||||
s8_t string = s8(box->ti_buffer, box->ti_buffer_len);
|
||||
v2f32_t string_size = rn_measure_string(rn_state.main_font, string);
|
||||
v2f32_t rect_size = r2f32_get_size(rect);
|
||||
v2f32_t rect_string_diff = v2f32_sub(rect_size, string_size);
|
||||
v2f32_t center_pos = v2f32_divs(rect_string_diff, 2);
|
||||
v2f32_t pos_in_rect = v2f32(0, center_pos.y);
|
||||
if (box->text_align == ui_text_align_center) {
|
||||
pos_in_rect = center_pos;
|
||||
ui_text_input_t *ti = &box->text_input;
|
||||
s8_t string = s8(ti->str, ti->len);
|
||||
v2f32_t pos = ui_aligned_text_pos(box->text_align, rect, string);
|
||||
rn_draw_string(rn_state.main_font, pos, text_color, string);
|
||||
|
||||
ti->caret = ui_caret_clamp(ti->caret, 0, (i32)ti->len);
|
||||
{
|
||||
s8_t string_min = s8(ti->str, ti->caret.range.min);
|
||||
s8_t string_max = s8(ti->str, ti->caret.range.max);
|
||||
|
||||
v2f32_t size_min = rn_measure_string(rn_state.main_font, string_min);
|
||||
v2f32_t size_max = rn_measure_string(rn_state.main_font, string_max);
|
||||
r2f32_t selection_rect = r2f32(rect.min.x + size_min.x, rect.min.y, rect.min.x + size_max.x, rect.min.y + ui_em(1));
|
||||
rn_draw_rect(selection_rect, v4f32(1,1,1,0.2f));
|
||||
|
||||
|
||||
v2f32_t size_front = ti->caret.ifront == 0 ? size_min : size_max;
|
||||
r2f32_t caret_rect = r2f32(rect.min.x + size_front.x, rect.min.y, rect.min.x + size_front.x + 1, rect.min.y + ui_em(1));
|
||||
rn_draw_rect(caret_rect, text_color);
|
||||
}
|
||||
v2f32_t pos = v2f32_add(pos_in_rect, rect.min);
|
||||
rn_draw_string(rn_state.main_font, pos, box->text_color, string);
|
||||
}
|
||||
|
||||
fn i32 ui_text_replace(ui_text_input_t *ti, r1i32_t range, s8_t string) {
|
||||
range.min = CLAMP(range.min, 0, (i32)ti->len);
|
||||
range.max = CLAMP(range.max, range.min, (i32)ti->len);
|
||||
assert(range.min >= 0 && range.max <= ti->len);
|
||||
i32 size_to_remove = r1i32_size(range);
|
||||
i32 size_to_add = (i32)string.len;
|
||||
i32 change_size = size_to_add - size_to_remove;
|
||||
if (ti->len + change_size > ti->cap) {
|
||||
i32 rem = ((i32)ti->len + change_size) - ti->cap;
|
||||
size_to_add -= rem;
|
||||
change_size -= rem;
|
||||
assert(change_size >= 0);
|
||||
}
|
||||
|
||||
u8 *begin_remove = ti->str + range.min;
|
||||
u8 *end_remove = begin_remove + size_to_remove;
|
||||
i32 remain_len = (i32)ti->len - (range.min + size_to_remove);
|
||||
|
||||
u8 *begin_add = begin_remove;
|
||||
u8 *end_add = begin_add + size_to_add;
|
||||
memory_move(end_add, end_remove, remain_len);
|
||||
memory_copy(begin_add, string.str, size_to_add);
|
||||
ti->len = ti->len + change_size;
|
||||
return change_size;
|
||||
}
|
||||
|
||||
fn_test void ui_test_text_replace(void) {
|
||||
ui_text_input_t ti = {0};
|
||||
char buff[4] = {0};
|
||||
ti.str = buff;
|
||||
ti.cap = lengthof(buff);
|
||||
ui_text_replace(&ti, r1i32(0,0), s8_lit("astfpo"));
|
||||
assert(s8_are_equal(ti.string, s8_lit("astf")));
|
||||
|
||||
ui_text_replace(&ti, r1i32(0,4), s8_lit("qwer"));
|
||||
assert(s8_are_equal(ti.string, s8_lit("qwer")));
|
||||
|
||||
ui_text_replace(&ti, r1i32(1,2), s8_lit("a"));
|
||||
assert(s8_are_equal(ti.string, s8_lit("qaer")));
|
||||
}
|
||||
|
||||
fn ui_signal_t ui_text_input(ui_code_loc_t loc, char *buffer, i32 buffer_size) {
|
||||
ui_box_t *box = ui_build_box_from_string(loc, (ui_box_flags_t){ .draw_border = true, .draw_rect = true, .draw_text = true }, s8_lit("text_input"));
|
||||
box->custom_draw = ui_text_input_draw;
|
||||
box->ti_buffer = buffer;
|
||||
box->ti_buffer_cap = buffer_size;
|
||||
|
||||
ui_text_input_t *ti = &box->text_input;
|
||||
ti->str = buffer;
|
||||
ti->cap = buffer_size;
|
||||
ui_signal_t signal = ui_signal_from_box(box);
|
||||
if (ui_is_focused_box(box)) {
|
||||
app_event_t *ev = ui->event;
|
||||
i32 sel_size = r1i32_size(ti->caret.range);
|
||||
if (ev->kind == app_event_kind_text) {
|
||||
for (i64 i = 0; i < ev->text.len; i += 1) {
|
||||
box->ti_buffer[box->ti_buffer_len++] = ev->text.str[i];
|
||||
ui_text_replace(ti, ti->caret.range, ev->text);
|
||||
if (sel_size) {
|
||||
ti->caret = ui_carets(ti->caret.range.min);
|
||||
} else {
|
||||
ti->caret = ui_carets(ti->caret.range.min + 1);
|
||||
}
|
||||
} else if (ev->kind == app_event_kind_key_down) {
|
||||
if (ev->key == app_key_backspace) {
|
||||
if (sel_size) {
|
||||
ui_text_replace(ti, ti->caret.range, s8_lit(""));
|
||||
} else {
|
||||
ui_text_replace(ti, r1i32(ti->caret.e[0] - 1, ti->caret.e[0]), s8_null);
|
||||
ti->caret = ui_carets(ti->caret.range.min - 1);
|
||||
}
|
||||
} else if (ev->key == app_key_delete) {
|
||||
if (sel_size) {
|
||||
ui_text_replace(ti, ti->caret.range, s8_lit(""));
|
||||
} else {
|
||||
ui_text_replace(ti, r1i32(ti->caret.e[0], ti->caret.e[0] + 1), s8_null);
|
||||
}
|
||||
} else if (ev->key == app_key_left) {
|
||||
if (ev->shift) {
|
||||
ti->caret = ui_caret_set_front(ti->caret, ui_caret_front(ti->caret) - 1);
|
||||
} else {
|
||||
ti->caret = ui_carets(ui_caret_front(ti->caret) - 1);
|
||||
}
|
||||
} else if (ev->key == app_key_right) {
|
||||
if (ev->shift) {
|
||||
ti->caret = ui_caret_set_front(ti->caret, ui_caret_front(ti->caret) + 1);
|
||||
} else {
|
||||
ti->caret = ui_carets(ui_caret_front(ti->caret) + 1);
|
||||
}
|
||||
}
|
||||
} else if (signal.dragging) {
|
||||
v2f32_t size = rn_measure_string(rn_state.main_font, s8_lit("_"));
|
||||
v2f32_t pos = v2f32_sub(ev->mouse_pos, box->final_rect.min);
|
||||
i32 p = (i32)f32_round(pos.x / size.x);
|
||||
if (ev->kind == app_event_kind_mouse_down && ev->mouse_button == app_mouse_button_left) {
|
||||
ti->caret = ui_carets(p);
|
||||
}
|
||||
ti->caret = ui_caret_set_front(ti->caret, p);
|
||||
}
|
||||
ti->caret = ui_caret_clamp(ti->caret, 0, (i32)ti->len);
|
||||
}
|
||||
return signal;
|
||||
}
|
||||
@@ -336,12 +445,25 @@ fn void ui_end_build(void) {
|
||||
}
|
||||
}
|
||||
|
||||
fn v2f32_t ui_aligned_text_pos(ui_text_align_t text_align, r2f32_t rect, s8_t string) {
|
||||
v2f32_t string_size = rn_measure_string(rn_state.main_font, string);
|
||||
v2f32_t rect_size = r2f32_get_size(rect);
|
||||
v2f32_t rect_string_diff = v2f32_sub(rect_size, string_size);
|
||||
v2f32_t center_pos = v2f32_divs(rect_string_diff, 2);
|
||||
v2f32_t pos_in_rect = v2f32(0, center_pos.y);
|
||||
if (text_align == ui_text_align_center) {
|
||||
pos_in_rect = center_pos;
|
||||
}
|
||||
v2f32_t pos = v2f32_add(pos_in_rect, rect.min);
|
||||
return pos;
|
||||
}
|
||||
|
||||
fn void ui_default_draw_box(ui_box_t *box) {
|
||||
r2f32_t rect = box->final_rect;
|
||||
|
||||
v4f32_t background_color = box->background_color;
|
||||
v4f32_t text_color = box->text_color;
|
||||
v4f32_t border_color = box->border_color;
|
||||
r2f32_t rect = box->final_rect; // @todo: this or clipped?
|
||||
|
||||
if (ui_is_active_box(box)) {
|
||||
f32 active_t = f32_ease_out_n(box->active_t, 50.f);
|
||||
active_t = f32_clamp01(active_t);
|
||||
@@ -365,15 +487,7 @@ fn void ui_default_draw_box(ui_box_t *box) {
|
||||
rn_draw_rect_border(rect, border_color, box->border_thickness);
|
||||
}
|
||||
if (box->flags.draw_text) {
|
||||
v2f32_t string_size = rn_measure_string(rn_state.main_font, box->string);
|
||||
v2f32_t rect_size = r2f32_get_size(rect);
|
||||
v2f32_t rect_string_diff = v2f32_sub(rect_size, string_size);
|
||||
v2f32_t center_pos = v2f32_divs(rect_string_diff, 2);
|
||||
v2f32_t pos_in_rect = v2f32(0, center_pos.y);
|
||||
if (box->text_align == ui_text_align_center) {
|
||||
pos_in_rect = center_pos;
|
||||
}
|
||||
v2f32_t pos = v2f32_add(pos_in_rect, rect.min);
|
||||
v2f32_t pos = ui_aligned_text_pos(box->text_align, rect, box->string);
|
||||
rn_draw_string(rn_state.main_font, pos, text_color, box->string);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user