/** * @file InputField.cpp * @author apio (cloudapio.eu) * @brief Single line text input widget. * * @copyright Copyright (c) 2024, the Luna authors. * */ #include #include #include #include #include namespace ui { InputField::InputField(SharedPtr font) : ui::TextInput(), m_font(font) { } Result InputField::handle_key_event(const ui::KeyEventRequest& request) { // Avoid handling "key released" events if (!request.pressed) return ui::EventResult::DidNotHandle; if (request.code == moon::K_LeftArrow) { if (m_cursor > 0) m_cursor--; else return ui::EventResult::DidNotHandle; update_cursor(); return ui::EventResult::DidHandle; } if (request.code == moon::K_RightArrow) { if (m_cursor < m_data.size()) m_cursor++; else return ui::EventResult::DidNotHandle; update_cursor(); return ui::EventResult::DidHandle; } if (request.code == moon::K_Backspace) { if (m_cursor == 0) return ui::EventResult::DidNotHandle; m_cursor--; delete_current_character(); update_cursor(); return ui::EventResult::DidHandle; } if (request.letter == '\n') { if (m_has_on_submit_action) { m_on_submit_action(data()); return ui::EventResult::DidHandle; } return ui::EventResult::DidNotHandle; } if (iscntrl(request.letter)) return ui::EventResult::DidNotHandle; if (m_cursor == m_data.size()) TRY(m_data.append_data((const u8*)&request.letter, 1)); else TRY(insert_character(request.letter)); m_cursor++; update_cursor(); return ui::EventResult::DidHandle; } Result InputField::draw(ui::Canvas& canvas) { int visible_characters = canvas.width / m_font->width(); auto string = data(); Utf8StringDecoder decoder(string.chars()); wchar_t buf[4096]; decoder.decode(buf, sizeof(buf)).release_value(); int characters_to_render = (int)wcslen(buf); for (int j = 0; j < visible_characters && j < characters_to_render; j++) { auto subcanvas = canvas.subcanvas({ j * m_font->width(), 0, m_font->width(), m_font->height() }); m_font->render(buf[j], ui::WHITE, subcanvas); } // Draw the cursor if ((int)m_cursor < visible_characters && m_cursor_activated) { canvas.subcanvas({ (int)m_cursor * m_font->width(), 0, 1, m_font->height() }).fill(ui::WHITE); } return {}; } StringView InputField::data() { return StringView { (const char*)m_data.data(), m_data.size() }; } }