# Экранная клавиатура ## Назначение Владелец автомата может полностью редактировать настройки с тач-экрана без физической клавиатуры. Тап по `LineEdit` открывает текстовую клавиатуру, тап по внутреннему полю `SpinBox` — цифровую. Существующие полноэкранные клавиатуры PIN и произвольной суммы оплаты остаются отдельными сценариями и не используют этот компонент. ## Возможности Текстовая клавиатура поддерживает: - русскую раскладку по умолчанию, включая `Ё`; - английскую раскладку; - Shift для регистра букв; - страницу из 33 цифр и спецсимволов, в том числе знаки для локальных путей; - пробел, очистку, удаление и перемещение каретки; - скрытие кнопкой в правом верхнем углу. Цифровая клавиатура содержит цифры 0–9, очистку, удаление и отдельную кнопку скрытия. Для текущих `SpinBox` не показываются минус и десятичный разделитель: все доступные владельцу числовые настройки являются неотрицательными целыми значениями. При открытии нижней панели `ScrollContainer` поднимает активное поле выше клавиатуры. Смена раздела, повторное нажатие сервисной кнопки и выход из Settings применяют введённое значение `SpinBox`, скрывают клавиатуру и освобождают фокус. Валидные изменения продолжают использовать обычное автосохранение с задержкой 0,5 секунды. ## Архитектура Логика находится в `src/ui/OnScreenKeyboard/`: - `OnScreenKeyboardState` хранит RU/EN/symbols/numeric и Shift без зависимости от Godot; - `OnScreenKeyboardView` описывает обязательные ссылки на уже готовые узлы темы; - `OnScreenKeyboardController` связывает поля, кнопки и прокрутку. Контроллер использует `LineEdit.InsertTextAtCaret`, `DeleteText`, выделение и составные Unicode- символы. Для числового поля после изменения вызывается `SpinBox.Apply()`. Синтетические `InputEventKey` не отправляются, поэтому `TextChanged`/`ValueChanged`, валидация и автосохранение работают обычным путём. У обслуживаемых полей отключены `VirtualKeyboardEnabled` и `VirtualKeyboardShowOnFocus`. В fallback-сцене панели находятся в `SafeMargin/KeyboardOverlay`. Внешняя тема может располагать их иначе, но обязана предоставить все 57 metadata binding-id из каталога v2. Приложение не создаёт, не перемещает и не стилизует визуальные узлы внешней сцены; их внешний вид полностью принадлежит теме и совпадает с её preview. ## Проверка Перед выпуском необходимо проверить на 720×1280: 1. ввод русского и английского текста, Shift и возврат со страницы `?123`; 2. вставку в середину строки, выделение, удаление и `MaxLength`; 3. ввод цены, бонусов и карточных сумм через цифровую панель; 4. повторное открытие после кнопки «Скрыть»; 5. переключение между полями и вкладками; 6. закрытие Settings повторным нажатием `IN8` и сохранение последнего числа; 7. одинаковую композицию fallback, preview и установленной DLC-темы. Чистое состояние раскладок покрыто NUnit-тестами. Наличие панелей, отсутствие runtime-создания визуальных узлов и интеграционные маркеры сцены проверяются smoke-тестами. Автоматический Godot smoke запускается из корня проекта сначала с установленной темой, затем с fallback: ```powershell $godot = "D:\Applications\Godot\Godot_v4.7.1-stable_mono_win64\Godot_v4.7.1-stable_mono_win64_console.exe" & $godot --headless --path . tests/runtime/OnScreenKeyboardSmoke.tscn -- --mock-hardware=true & $godot --headless --path . tests/runtime/OnScreenKeyboardSmoke.tscn -- --no-theme-dlc --mock-hardware=true ``` Оба запуска обязаны вывести `ON_SCREEN_KEYBOARD_RUNTIME_SMOKE_OK` и завершиться с кодом 0.