[wip, ui] re-integrating UI subsystem and completing text box

This commit is contained in:
Martin Fouilleul 2023-03-03 20:09:44 +01:00
parent d21e737733
commit c04e8639ab
3 changed files with 109 additions and 35 deletions

View File

@ -139,11 +139,13 @@ static void mp_update_key_state(mp_key_state* key, bool down)
key->doubleClicked = false; key->doubleClicked = false;
key->lastUpdate = frameCounter; key->lastUpdate = frameCounter;
} }
if(key->down == down) if(key->down != down)
{ {
key->transitionCounter++; key->transitionCounter++;
} }
key->down = down; key->down = down;
} }
static void mp_update_mouse_move(f32 x, f32 y, f32 deltaX, f32 deltaY) static void mp_update_mouse_move(f32 x, f32 y, f32 deltaX, f32 deltaY)

View File

@ -401,6 +401,8 @@ mg_canvas_backend* mg_mtl_canvas_create(mg_surface surface)
mg_mtl_surface* metalSurface = (mg_mtl_surface*)surfaceData; mg_mtl_surface* metalSurface = (mg_mtl_surface*)surfaceData;
backend = malloc_type(mg_mtl_canvas_backend); backend = malloc_type(mg_mtl_canvas_backend);
memset(backend, 0, sizeof(mg_mtl_canvas_backend));
backend->surface = surface; backend->surface = surface;
//NOTE(martin): setup interface functions //NOTE(martin): setup interface functions

116
src/ui.c
View File

@ -642,6 +642,10 @@ ui_sig ui_box_sig(ui_box* box)
{ {
if(sig.hovering) if(sig.hovering)
{ {
if(mp_input_mouse_clicked(MP_MOUSE_LEFT))
{
printf("clicked while hovering!\n");
}
sig.pressed = mp_input_mouse_pressed(MP_MOUSE_LEFT); sig.pressed = mp_input_mouse_pressed(MP_MOUSE_LEFT);
if(sig.pressed) if(sig.pressed)
{ {
@ -1724,6 +1728,8 @@ void ui_edit_copy_selection_to_clipboard(ui_context* ui, str32 codepoints)
str8 string = utf8_push_from_codepoints(&ui->frameArena, selection); str8 string = utf8_push_from_codepoints(&ui->frameArena, selection);
printf("copying '%.*s' to clipboard\n", (int)string.len, string.ptr);
mp_clipboard_clear(); mp_clipboard_clear();
mp_clipboard_set_string(string); mp_clipboard_set_string(string);
} }
@ -1731,6 +1737,9 @@ void ui_edit_copy_selection_to_clipboard(ui_context* ui, str32 codepoints)
str32 ui_edit_replace_selection_with_clipboard(ui_context* ui, str32 codepoints) str32 ui_edit_replace_selection_with_clipboard(ui_context* ui, str32 codepoints)
{ {
str8 string = mp_clipboard_get_string(&ui->frameArena); str8 string = mp_clipboard_get_string(&ui->frameArena);
printf("pasting '%.*s' from clipboard\n", (int)string.len, string.ptr);
str32 input = utf8_push_to_codepoints(&ui->frameArena, string); str32 input = utf8_push_to_codepoints(&ui->frameArena, string);
str32 result = ui_edit_replace_selection_with_codepoints(ui, codepoints, input); str32 result = ui_edit_replace_selection_with_codepoints(ui, codepoints, input);
return(result); return(result);
@ -1898,7 +1907,7 @@ const ui_edit_command UI_EDIT_COMMANDS[] = {
const u32 UI_EDIT_COMMAND_COUNT = sizeof(UI_EDIT_COMMANDS)/sizeof(ui_edit_command); const u32 UI_EDIT_COMMAND_COUNT = sizeof(UI_EDIT_COMMANDS)/sizeof(ui_edit_command);
void ui_edit_perform_move(ui_context* ui, ui_edit_move move, int direction, u32 textLen, u32 cursor) void ui_edit_perform_move(ui_context* ui, ui_edit_move move, int direction, u32 textLen)
{ {
switch(move) switch(move)
{ {
@ -1907,13 +1916,13 @@ void ui_edit_perform_move(ui_context* ui, ui_edit_move move, int direction, u32
case UI_EDIT_MOVE_ONE: case UI_EDIT_MOVE_ONE:
{ {
if(direction < 0 && cursor > 0) if(direction < 0 && ui->editCursor > 0)
{ {
cursor--; ui->editCursor--;
} }
else if(direction > 0 && cursor < textLen) else if(direction > 0 && ui->editCursor < textLen)
{ {
cursor++; ui->editCursor++;
} }
} break; } break;
@ -1921,11 +1930,11 @@ void ui_edit_perform_move(ui_context* ui, ui_edit_move move, int direction, u32
{ {
if(direction < 0) if(direction < 0)
{ {
cursor = 0; ui->editCursor = 0;
} }
else if(direction > 0) else if(direction > 0)
{ {
cursor = textLen; ui->editCursor = textLen;
} }
} break; } break;
@ -1933,7 +1942,6 @@ void ui_edit_perform_move(ui_context* ui, ui_edit_move move, int direction, u32
DEBUG_ASSERT(0, "not implemented yet"); DEBUG_ASSERT(0, "not implemented yet");
break; break;
} }
ui->editCursor = cursor;
} }
str32 ui_edit_perform_operation(ui_context* ui, ui_edit_op operation, ui_edit_move move, int direction, str32 codepoints) str32 ui_edit_perform_operation(ui_context* ui, ui_edit_op operation, ui_edit_move move, int direction, str32 codepoints)
@ -1947,35 +1955,38 @@ str32 ui_edit_perform_operation(ui_context* ui, ui_edit_op operation, ui_edit_mo
u32 cursor = direction < 0 ? u32 cursor = direction < 0 ?
minimum(ui->editCursor, ui->editMark) : minimum(ui->editCursor, ui->editMark) :
maximum(ui->editCursor, ui->editMark); maximum(ui->editCursor, ui->editMark);
ui->editCursor = cursor;
if(ui->editCursor == ui->editMark || move != UI_EDIT_MOVE_ONE) if(ui->editCursor == ui->editMark || move != UI_EDIT_MOVE_ONE)
{ {
//NOTE: we special case move-one when there is a selection //NOTE: we special case move-one when there is a selection
// (just place the cursor at begining/end of selection) // (just place the cursor at begining/end of selection)
ui_edit_perform_move(ui, move, direction, codepoints.len, cursor); ui_edit_perform_move(ui, move, direction, codepoints.len);
} }
ui->editMark = ui->editCursor; ui->editMark = ui->editCursor;
} break; } break;
case UI_EDIT_SELECT: case UI_EDIT_SELECT:
{ {
ui_edit_perform_move(ui, move, direction, codepoints.len, ui->editCursor); ui_edit_perform_move(ui, move, direction, codepoints.len);
} break; } break;
case UI_EDIT_SELECT_EXTEND: case UI_EDIT_SELECT_EXTEND:
{ {
u32 cursor = direction > 0 ? if((direction > 0) != (ui->editCursor > ui->editMark))
(ui->editCursor > ui->editMark ? ui->editCursor : ui->editMark) : {
(ui->editCursor < ui->editMark ? ui->editCursor : ui->editMark); u32 tmp = ui->editCursor;
ui->editCursor = ui->editMark;
ui_edit_perform_move(ui, move, direction, codepoints.len, cursor); ui->editMark = tmp;
}
ui_edit_perform_move(ui, move, direction, codepoints.len);
} break; } break;
case UI_EDIT_DELETE: case UI_EDIT_DELETE:
{ {
if(ui->editCursor == ui->editMark) if(ui->editCursor == ui->editMark)
{ {
ui_edit_perform_move(ui, move, direction, codepoints.len, ui->editCursor); ui_edit_perform_move(ui, move, direction, codepoints.len);
} }
codepoints = ui_edit_delete_selection(ui, codepoints); codepoints = ui_edit_delete_selection(ui, codepoints);
ui->editMark = ui->editCursor; ui->editMark = ui->editCursor;
@ -2032,18 +2043,54 @@ void ui_text_box_render(ui_box* box, void* data)
f32 textTop = box->rect.y + 0.5*(box->rect.h - lineHeight); f32 textTop = box->rect.y + 0.5*(box->rect.h - lineHeight);
f32 textY = textTop + extents.ascent ; f32 textY = textTop + extents.ascent ;
if(box->active && !((u64)(2*(ui->frameTime - ui->editCursorBlinkStart)) & 1)) if(box->active)
{ {
str32 beforeCaret = str32_slice(codepoints, 0, ui->editCursor); u32 selectStart = minimum(ui->editCursor, ui->editMark);
mp_rect beforeCaretBox = mg_text_bounding_box_utf32(style->font, style->fontSize, beforeCaret); u32 selectEnd = maximum(ui->editCursor, ui->editMark);
f32 caretX = box->rect.x + textMargin - beforeBox.w + beforeCaretBox.w; str32 beforeSelect = str32_slice(codepoints, 0, selectStart);
mp_rect beforeSelectBox = mg_text_bounding_box_utf32(style->font, style->fontSize, beforeSelect);
beforeSelectBox.x += textX + beforeBox.x + beforeBox.w;
beforeSelectBox.y += textY;
if(selectStart != selectEnd)
{
str32 select = str32_slice(codepoints, selectStart, selectEnd);
str32 afterSelect = str32_slice(codepoints, selectEnd, codepoints.len);
mp_rect selectBox = mg_text_bounding_box_utf32(style->font, style->fontSize, select);
mp_rect afterSelectBox = mg_text_bounding_box_utf32(style->font, style->fontSize, afterSelect);
selectBox.x += beforeSelectBox.x + beforeSelectBox.w;
selectBox.y += textY;
mg_set_color_rgba(0, 0, 1, 1);
mg_rectangle_fill(selectBox.x, selectBox.y, selectBox.w, lineHeight);
mg_set_font(style->font);
mg_set_font_size(style->fontSize);
mg_set_color(style->fontColor);
mg_move_to(textX, textY);
mg_codepoints_outlines(beforeSelect);
mg_fill();
mg_set_color_rgba(1, 1, 1, 1);
mg_codepoints_outlines(select);
mg_fill();
mg_set_color(style->fontColor);
mg_codepoints_outlines(afterSelect);
mg_fill();
}
else
{
if(!((u64)(2*(ui->frameTime - ui->editCursorBlinkStart)) & 1))
{
f32 caretX = box->rect.x + textMargin - beforeBox.w + beforeSelectBox.w;
f32 caretY = textTop; f32 caretY = textTop;
mg_set_color_rgba(0, 0, 0, 1); mg_set_color_rgba(0, 0, 0, 1);
mg_rectangle_fill(caretX, caretY, 2, lineHeight); mg_rectangle_fill(caretX, caretY, 2, lineHeight);
} }
mg_set_font(style->font); mg_set_font(style->font);
mg_set_font_size(style->fontSize); mg_set_font_size(style->fontSize);
mg_set_color(style->fontColor); mg_set_color(style->fontColor);
@ -2051,6 +2098,18 @@ void ui_text_box_render(ui_box* box, void* data)
mg_move_to(textX, textY); mg_move_to(textX, textY);
mg_codepoints_outlines(codepoints); mg_codepoints_outlines(codepoints);
mg_fill(); mg_fill();
}
}
else
{
mg_set_font(style->font);
mg_set_font_size(style->fontSize);
mg_set_color(style->fontColor);
mg_move_to(textX, textY);
mg_codepoints_outlines(codepoints);
mg_fill();
}
} }
ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text) ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text)
@ -2113,7 +2172,8 @@ ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text)
if(ui_box_active(frame)) if(ui_box_active(frame))
{ {
str32 codepoints = utf8_push_to_codepoints(&ui->frameArena, text); str32 oldCodepoints = utf8_push_to_codepoints(&ui->frameArena, text);
str32 codepoints = oldCodepoints;
ui->editCursor = Clamp(ui->editCursor, 0, codepoints.len); ui->editCursor = Clamp(ui->editCursor, 0, codepoints.len);
ui->editMark = Clamp(ui->editMark, 0, codepoints.len); ui->editMark = Clamp(ui->editMark, 0, codepoints.len);
@ -2131,6 +2191,12 @@ ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text)
for(int i=0; i<UI_EDIT_COMMAND_COUNT; i++) for(int i=0; i<UI_EDIT_COMMAND_COUNT; i++)
{ {
const ui_edit_command* command = &(UI_EDIT_COMMANDS[i]); const ui_edit_command* command = &(UI_EDIT_COMMANDS[i]);
if(mp_input_key_pressed(MP_KEY_C))
{
printf("press C!\n");
}
if(mp_input_key_pressed(command->key) && mods == command->mods) if(mp_input_key_pressed(command->key) && mods == command->mods)
{ {
codepoints = ui_edit_perform_operation(ui, command->operation, command->move, command->direction, codepoints); codepoints = ui_edit_perform_operation(ui, command->operation, command->move, command->direction, codepoints);
@ -2146,7 +2212,11 @@ ui_text_box_result ui_text_box(const char* name, mem_arena* arena, str8 text)
ui->focus = 0; ui->focus = 0;
} }
if(oldCodepoints.ptr != codepoints.ptr)
{
result.changed = true;
result.text = utf8_push_from_codepoints(arena, codepoints); result.text = utf8_push_from_codepoints(arena, codepoints);
}
//TODO slide contents //TODO slide contents