Refactor where Keyboard is

This commit is contained in:
Brendan O'Leary 2025-12-18 21:38:23 -05:00
parent 18527c6bc0
commit 18086ef5ee
4 changed files with 57 additions and 39 deletions

View File

@ -199,11 +199,11 @@ void WifiScreen::selectNetwork(int index) {
if (selectedRequiresPassword) { if (selectedRequiresPassword) {
// Show password entry // Show password entry
state = WifiScreenState::PASSWORD_ENTRY; state = WifiScreenState::PASSWORD_ENTRY;
keyboard.reset(new OnScreenKeyboard(renderer, inputManager, "Enter WiFi Password", keyboard.reset(new KeyboardEntryActivity(renderer, inputManager, "Enter WiFi Password",
"", // No initial text "", // No initial text
64, // Max password length 64, // Max password length
false // Show password by default (hard keyboard to use) false // Show password by default (hard keyboard to use)
)); ));
updateRequired = true; updateRequired = true;
} else { } else {
// Connect directly for open networks // Connect directly for open networks

View File

@ -10,7 +10,7 @@
#include <vector> #include <vector>
#include "../Activity.h" #include "../Activity.h"
#include "OnScreenKeyboard.h" #include "../util/KeyboardEntryActivity.h"
// Structure to hold WiFi network information // Structure to hold WiFi network information
struct WifiNetworkInfo { struct WifiNetworkInfo {
@ -46,7 +46,7 @@ class WifiScreen final : public Activity {
bool selectedRequiresPassword = false; bool selectedRequiresPassword = false;
// On-screen keyboard for password entry // On-screen keyboard for password entry
std::unique_ptr<OnScreenKeyboard> keyboard; std::unique_ptr<KeyboardEntryActivity> keyboard;
// Connection result // Connection result
std::string connectedIP; std::string connectedIP;

View File

@ -1,34 +1,33 @@
#include "OnScreenKeyboard.h" #include "KeyboardEntryActivity.h"
#include "config.h" #include "../../config.h"
// Keyboard layouts - lowercase // Keyboard layouts - lowercase
const char* const OnScreenKeyboard::keyboard[NUM_ROWS] = { const char* const KeyboardEntryActivity::keyboard[NUM_ROWS] = {
"`1234567890-=", "qwertyuiop[]\\", "asdfghjkl;'", "zxcvbnm,./", "`1234567890-=", "qwertyuiop[]\\", "asdfghjkl;'", "zxcvbnm,./",
"^ _____<OK" // ^ = shift, _ = space, < = backspace, OK = done "^ _____<OK" // ^ = shift, _ = space, < = backspace, OK = done
}; };
// Keyboard layouts - uppercase/symbols // Keyboard layouts - uppercase/symbols
const char* const OnScreenKeyboard::keyboardShift[NUM_ROWS] = {"~!@#$%^&*()_+", "QWERTYUIOP{}|", "ASDFGHJKL:\"", const char* const KeyboardEntryActivity::keyboardShift[NUM_ROWS] = {"~!@#$%^&*()_+", "QWERTYUIOP{}|", "ASDFGHJKL:\"",
"ZXCVBNM<>?", "^ _____<OK"}; "ZXCVBNM<>?", "^ _____<OK"};
OnScreenKeyboard::OnScreenKeyboard(GfxRenderer& renderer, InputManager& inputManager, const std::string& title, KeyboardEntryActivity::KeyboardEntryActivity(GfxRenderer& renderer, InputManager& inputManager, const std::string& title,
const std::string& initialText, size_t maxLength, bool isPassword) const std::string& initialText, size_t maxLength, bool isPassword)
: renderer(renderer), : Activity(renderer, inputManager),
inputManager(inputManager),
title(title), title(title),
text(initialText), text(initialText),
maxLength(maxLength), maxLength(maxLength),
isPassword(isPassword) {} isPassword(isPassword) {}
void OnScreenKeyboard::setText(const std::string& newText) { void KeyboardEntryActivity::setText(const std::string& newText) {
text = newText; text = newText;
if (maxLength > 0 && text.length() > maxLength) { if (maxLength > 0 && text.length() > maxLength) {
text = text.substr(0, maxLength); text = text.substr(0, maxLength);
} }
} }
void OnScreenKeyboard::reset(const std::string& newTitle, const std::string& newInitialText) { void KeyboardEntryActivity::reset(const std::string& newTitle, const std::string& newInitialText) {
if (!newTitle.empty()) { if (!newTitle.empty()) {
title = newTitle; title = newTitle;
} }
@ -40,7 +39,22 @@ void OnScreenKeyboard::reset(const std::string& newTitle, const std::string& new
cancelled = false; cancelled = false;
} }
int OnScreenKeyboard::getRowLength(int row) const { void KeyboardEntryActivity::onEnter() {
// Reset state when entering the activity
complete = false;
cancelled = false;
}
void KeyboardEntryActivity::onExit() {
// Clean up if needed
}
void KeyboardEntryActivity::loop() {
handleInput();
render(10);
}
int KeyboardEntryActivity::getRowLength(int row) const {
if (row < 0 || row >= NUM_ROWS) return 0; if (row < 0 || row >= NUM_ROWS) return 0;
// Return actual length of each row based on keyboard layout // Return actual length of each row based on keyboard layout
@ -60,7 +74,7 @@ int OnScreenKeyboard::getRowLength(int row) const {
} }
} }
char OnScreenKeyboard::getSelectedChar() const { char KeyboardEntryActivity::getSelectedChar() const {
const char* const* layout = shiftActive ? keyboardShift : keyboard; const char* const* layout = shiftActive ? keyboardShift : keyboard;
if (selectedRow < 0 || selectedRow >= NUM_ROWS) return '\0'; if (selectedRow < 0 || selectedRow >= NUM_ROWS) return '\0';
@ -69,7 +83,7 @@ char OnScreenKeyboard::getSelectedChar() const {
return layout[selectedRow][selectedCol]; return layout[selectedRow][selectedCol];
} }
void OnScreenKeyboard::handleKeyPress() { void KeyboardEntryActivity::handleKeyPress() {
// Handle special row (bottom row with shift, space, backspace, done) // Handle special row (bottom row with shift, space, backspace, done)
if (selectedRow == SHIFT_ROW) { if (selectedRow == SHIFT_ROW) {
if (selectedCol == SHIFT_COL) { if (selectedCol == SHIFT_COL) {
@ -117,7 +131,7 @@ void OnScreenKeyboard::handleKeyPress() {
} }
} }
bool OnScreenKeyboard::handleInput() { bool KeyboardEntryActivity::handleInput() {
if (complete || cancelled) { if (complete || cancelled) {
return false; return false;
} }
@ -179,7 +193,7 @@ bool OnScreenKeyboard::handleInput() {
return handled; return handled;
} }
void OnScreenKeyboard::render(int startY) const { void KeyboardEntryActivity::render(int startY) const {
const auto pageWidth = GfxRenderer::getScreenWidth(); const auto pageWidth = GfxRenderer::getScreenWidth();
// Draw title // Draw title

View File

@ -5,18 +5,20 @@
#include <functional> #include <functional>
#include <string> #include <string>
#include "../Activity.h"
/** /**
* Reusable on-screen keyboard component for text input. * Reusable keyboard entry activity for text input.
* Can be embedded in any screen that needs text entry. * Can be started from any activity that needs text entry.
* *
* Usage: * Usage:
* 1. Create an OnScreenKeyboard instance * 1. Create a KeyboardEntryActivity instance
* 2. Call render() to draw the keyboard * 2. Set callbacks with setOnComplete() and setOnCancel()
* 3. Call handleInput() to process button presses * 3. Call onEnter() to start the activity
* 4. When isComplete() returns true, get the result from getText() * 4. Call loop() in your main loop
* 5. Call isCancelled() to check if user cancelled input * 5. When complete or cancelled, callbacks will be invoked
*/ */
class OnScreenKeyboard { class KeyboardEntryActivity : public Activity {
public: public:
// Callback types // Callback types
using OnCompleteCallback = std::function<void(const std::string&)>; using OnCompleteCallback = std::function<void(const std::string&)>;
@ -31,20 +33,20 @@ class OnScreenKeyboard {
* @param maxLength Maximum length of input text (0 for unlimited) * @param maxLength Maximum length of input text (0 for unlimited)
* @param isPassword If true, display asterisks instead of actual characters * @param isPassword If true, display asterisks instead of actual characters
*/ */
OnScreenKeyboard(GfxRenderer& renderer, InputManager& inputManager, const std::string& title = "Enter Text", KeyboardEntryActivity(GfxRenderer& renderer, InputManager& inputManager, const std::string& title = "Enter Text",
const std::string& initialText = "", size_t maxLength = 0, bool isPassword = false); const std::string& initialText = "", size_t maxLength = 0, bool isPassword = false);
/** /**
* Handle button input. Call this in your screen's handleInput(). * Handle button input. Call this in your main loop.
* @return true if input was handled, false otherwise * @return true if input was handled, false otherwise
*/ */
bool handleInput(); bool handleInput();
/** /**
* Render the keyboard at the specified Y position. * Render the keyboard at the specified Y position.
* @param startY Y-coordinate where keyboard rendering starts * @param startY Y-coordinate where keyboard rendering starts (default 10)
*/ */
void render(int startY) const; void render(int startY = 10) const;
/** /**
* Get the current text entered by the user. * Get the current text entered by the user.
@ -81,10 +83,12 @@ class OnScreenKeyboard {
*/ */
void setOnCancel(OnCancelCallback callback) { onCancel = callback; } void setOnCancel(OnCancelCallback callback) { onCancel = callback; }
private: // Activity overrides
GfxRenderer& renderer; void onEnter() override;
InputManager& inputManager; void onExit() override;
void loop() override;
private:
std::string title; std::string title;
std::string text; std::string text;
size_t maxLength; size_t maxLength;