Add example-name hint to the preset-name keyboard
The preset-name keypad (used both when adding a preset via manual coordinates and after an address search) only showed "Name (optional):" with no indication of what kind of name was expected. Adds a localized hint line with example names (e.g. "Home, Work, Holiday home") under the title in both runPresetNameKeypad() (location_presets_screen.cpp) and runNameKeypad() (address_search_screen.cpp), measuring the header height dynamically via getCursorY() the same way runAddressKeyboard() already does, so the input field and keyboard shift down to make room regardless of translation length. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -296,7 +296,19 @@ namespace {
|
|||||||
|
|
||||||
constexpr int16_t KEY_H = 30;
|
constexpr int16_t KEY_H = 30;
|
||||||
constexpr int16_t KEY_GAP = 3;
|
constexpr int16_t KEY_GAP = 3;
|
||||||
constexpr int16_t ROW0_Y = 78;
|
constexpr int16_t FIELD_H = 34;
|
||||||
|
|
||||||
|
// Kopfbereich (Titel + Namens-Hinweis) einmal zeichnen, um seine
|
||||||
|
// tatsaechliche Hoehe per getCursorY() zu messen - selbes Muster wie
|
||||||
|
// in runAddressKeyboard() oben.
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||||
|
tft.setCursor(10, 14);
|
||||||
|
tft.println(I18n::t(StringId::LOCATION_NAME_PROMPT));
|
||||||
|
tft.setTextColor(TFT_CYAN, TFT_BLACK);
|
||||||
|
tft.println(I18n::t(StringId::LOCATION_NAME_HINT));
|
||||||
|
int16_t fieldY = (int16_t)(tft.getCursorY() + 4);
|
||||||
|
int16_t ROW0_Y = (int16_t)(fieldY + FIELD_H + 8);
|
||||||
|
|
||||||
auto layoutRow = [&](const char* row, int16_t y, Rect* outRects, uint8_t n) {
|
auto layoutRow = [&](const char* row, int16_t y, Rect* outRects, uint8_t n) {
|
||||||
int16_t usableW = Config::SCREEN_WIDTH - 8;
|
int16_t usableW = Config::SCREEN_WIDTH - 8;
|
||||||
@@ -326,12 +338,14 @@ namespace {
|
|||||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||||
tft.setCursor(10, 14);
|
tft.setCursor(10, 14);
|
||||||
tft.println(I18n::t(StringId::LOCATION_NAME_PROMPT));
|
tft.println(I18n::t(StringId::LOCATION_NAME_PROMPT));
|
||||||
|
tft.setTextColor(TFT_CYAN, TFT_BLACK);
|
||||||
|
tft.println(I18n::t(StringId::LOCATION_NAME_HINT));
|
||||||
|
|
||||||
tft.fillRect(8, 40, Config::SCREEN_WIDTH - 16, 34, TFT_BLACK);
|
tft.fillRect(8, fieldY, Config::SCREEN_WIDTH - 16, FIELD_H, TFT_BLACK);
|
||||||
tft.drawRect(8, 40, Config::SCREEN_WIDTH - 16, 34, TFT_GREEN);
|
tft.drawRect(8, fieldY, Config::SCREEN_WIDTH - 16, FIELD_H, TFT_GREEN);
|
||||||
tft.setTextSize(2);
|
tft.setTextSize(2);
|
||||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||||
tft.setCursor(14, 66);
|
tft.setCursor(14, (int16_t)(fieldY + 26));
|
||||||
tft.print(buf);
|
tft.print(buf);
|
||||||
tft.setTextSize(1);
|
tft.setTextSize(1);
|
||||||
|
|
||||||
|
|||||||
@@ -268,6 +268,13 @@ enum class StringId : uint8_t {
|
|||||||
FIRST_RUN_COMPLETE_BODY1,
|
FIRST_RUN_COMPLETE_BODY1,
|
||||||
FIRST_RUN_COMPLETE_BODY2,
|
FIRST_RUN_COMPLETE_BODY2,
|
||||||
|
|
||||||
|
// Hinweis mit Beispielnamen unter dem Titel der Namens-Tastatur
|
||||||
|
// (location_presets_screen.cpp::runPresetNameKeypad UND
|
||||||
|
// address_search_screen.cpp::runNameKeypad, beide spiegeln sich) -
|
||||||
|
// ohne jeden Hinweis wussten Einsteiger nicht, was fuer ein Name hier
|
||||||
|
// gemeint ist (Preset-Name wie "Zuhause", nicht z.B. ein Ort/Adresse).
|
||||||
|
LOCATION_NAME_HINT,
|
||||||
|
|
||||||
COUNT
|
COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -227,6 +227,8 @@ static const char* const I18N_DE[] = {
|
|||||||
"Einrichtung abgeschlossen",
|
"Einrichtung abgeschlossen",
|
||||||
"Der Einrichtungsprozess ist jetzt abgeschlossen. Alle Daten wurden auf der SD-Karte im Ordner ",
|
"Der Einrichtungsprozess ist jetzt abgeschlossen. Alle Daten wurden auf der SD-Karte im Ordner ",
|
||||||
" abgespeichert. Ab dem nächsten Start verbindet sich das WLAN automatisch.",
|
" abgespeichert. Ab dem nächsten Start verbindet sich das WLAN automatisch.",
|
||||||
|
|
||||||
|
"z.B. Zuhause, Arbeit, Ferienhaus",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_DE) / sizeof(I18N_DE[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_DE) / sizeof(I18N_DE[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -228,6 +228,8 @@ static const char* const I18N_EN[] = {
|
|||||||
"Setup Complete",
|
"Setup Complete",
|
||||||
"The setup process is now complete. All data has been saved to the SD card in the folder ",
|
"The setup process is now complete. All data has been saved to the SD card in the folder ",
|
||||||
". From the next boot, WiFi will connect automatically.",
|
". From the next boot, WiFi will connect automatically.",
|
||||||
|
|
||||||
|
"e.g. Home, Work, Holiday home",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_EN) / sizeof(I18N_EN[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_EN) / sizeof(I18N_EN[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -227,6 +227,8 @@ static const char* const I18N_ES[] = {
|
|||||||
"Configuración completada",
|
"Configuración completada",
|
||||||
"El proceso de configuración ya ha finalizado. Todos los datos se han guardado en la tarjeta SD, en la carpeta ",
|
"El proceso de configuración ya ha finalizado. Todos los datos se han guardado en la tarjeta SD, en la carpeta ",
|
||||||
". A partir del próximo inicio, el WiFi se conectará automáticamente.",
|
". A partir del próximo inicio, el WiFi se conectará automáticamente.",
|
||||||
|
|
||||||
|
"ej. Casa, Trabajo, Casa de vacaciones",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_ES) / sizeof(I18N_ES[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_ES) / sizeof(I18N_ES[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -227,6 +227,8 @@ static const char* const I18N_FR[] = {
|
|||||||
"Configuration terminée",
|
"Configuration terminée",
|
||||||
"Le processus de configuration est maintenant terminé. Toutes les données ont été enregistrées sur la carte SD dans le dossier ",
|
"Le processus de configuration est maintenant terminé. Toutes les données ont été enregistrées sur la carte SD dans le dossier ",
|
||||||
". À partir du prochain démarrage, le WiFi se connectera automatiquement.",
|
". À partir du prochain démarrage, le WiFi se connectera automatiquement.",
|
||||||
|
|
||||||
|
"ex. Maison, Travail, Maison de vacances",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_FR) / sizeof(I18N_FR[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_FR) / sizeof(I18N_FR[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -227,6 +227,8 @@ static const char* const I18N_IT[] = {
|
|||||||
"Configurazione completata",
|
"Configurazione completata",
|
||||||
"Il processo di configurazione è ora completato. Tutti i dati sono stati salvati sulla scheda SD nella cartella ",
|
"Il processo di configurazione è ora completato. Tutti i dati sono stati salvati sulla scheda SD nella cartella ",
|
||||||
". Dal prossimo avvio, il WiFi si connetterà automaticamente.",
|
". Dal prossimo avvio, il WiFi si connetterà automaticamente.",
|
||||||
|
|
||||||
|
"es. Casa, Lavoro, Casa vacanze",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_IT) / sizeof(I18N_IT[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_IT) / sizeof(I18N_IT[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -227,6 +227,8 @@ static const char* const I18N_TR[] = {
|
|||||||
"Kurulum Tamamlandı",
|
"Kurulum Tamamlandı",
|
||||||
"Kurulum işlemi artık tamamlandı. Tüm veriler SD karttaki şu klasöre kaydedildi: ",
|
"Kurulum işlemi artık tamamlandı. Tüm veriler SD karttaki şu klasöre kaydedildi: ",
|
||||||
". Bir sonraki başlatmadan itibaren WiFi otomatik olarak bağlanacak.",
|
". Bir sonraki başlatmadan itibaren WiFi otomatik olarak bağlanacak.",
|
||||||
|
|
||||||
|
"örn. Ev, İş, Tatil evi",
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(I18N_TR) / sizeof(I18N_TR[0]) == (size_t)StringId::COUNT,
|
static_assert(sizeof(I18N_TR) / sizeof(I18N_TR[0]) == (size_t)StringId::COUNT,
|
||||||
|
|||||||
@@ -132,7 +132,19 @@ namespace {
|
|||||||
|
|
||||||
constexpr int16_t KEY_H = 30;
|
constexpr int16_t KEY_H = 30;
|
||||||
constexpr int16_t KEY_GAP = 3;
|
constexpr int16_t KEY_GAP = 3;
|
||||||
constexpr int16_t ROW0_Y = 78;
|
constexpr int16_t FIELD_H = 34;
|
||||||
|
|
||||||
|
// Kopfbereich (Titel + Namens-Hinweis) einmal zeichnen, um seine
|
||||||
|
// tatsaechliche Hoehe per getCursorY() zu messen - selbes Muster wie
|
||||||
|
// in address_search_screen.cpp::runAddressKeyboard().
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||||
|
tft.setCursor(10, 14);
|
||||||
|
tft.println(I18n::t(StringId::LOCATION_NAME_PROMPT));
|
||||||
|
tft.setTextColor(TFT_CYAN, TFT_BLACK);
|
||||||
|
tft.println(I18n::t(StringId::LOCATION_NAME_HINT));
|
||||||
|
int16_t fieldY = (int16_t)(tft.getCursorY() + 4);
|
||||||
|
int16_t ROW0_Y = (int16_t)(fieldY + FIELD_H + 8);
|
||||||
|
|
||||||
auto layoutRow = [&](const char* row, int16_t y, Rect* outRects, uint8_t n) {
|
auto layoutRow = [&](const char* row, int16_t y, Rect* outRects, uint8_t n) {
|
||||||
int16_t usableW = Config::SCREEN_WIDTH - 8;
|
int16_t usableW = Config::SCREEN_WIDTH - 8;
|
||||||
@@ -146,9 +158,9 @@ namespace {
|
|||||||
|
|
||||||
Rect digitRects[10], row1Rects[10], row2Rects[9], row3Rects[7];
|
Rect digitRects[10], row1Rects[10], row2Rects[9], row3Rects[7];
|
||||||
layoutRow(DIGITS, ROW0_Y, digitRects, 10);
|
layoutRow(DIGITS, ROW0_Y, digitRects, 10);
|
||||||
layoutRow(ROW1, ROW0_Y + (KEY_H + KEY_GAP), row1Rects, 10);
|
layoutRow(ROW1, (int16_t)(ROW0_Y + (KEY_H + KEY_GAP)), row1Rects, 10);
|
||||||
layoutRow(ROW2, ROW0_Y + 2 * (KEY_H + KEY_GAP), row2Rects, 9);
|
layoutRow(ROW2, (int16_t)(ROW0_Y + 2 * (KEY_H + KEY_GAP)), row2Rects, 9);
|
||||||
layoutRow(ROW3, ROW0_Y + 3 * (KEY_H + KEY_GAP), row3Rects, 7);
|
layoutRow(ROW3, (int16_t)(ROW0_Y + 3 * (KEY_H + KEY_GAP)), row3Rects, 7);
|
||||||
|
|
||||||
Rect spaceBtn = {4, (int16_t)(ROW0_Y + 4 * (KEY_H + KEY_GAP)), 150, KEY_H};
|
Rect spaceBtn = {4, (int16_t)(ROW0_Y + 4 * (KEY_H + KEY_GAP)), 150, KEY_H};
|
||||||
Rect backspaceBtn = {158, (int16_t)(ROW0_Y + 4 * (KEY_H + KEY_GAP)), (int16_t)(Config::SCREEN_WIDTH - 8 - 154), KEY_H};
|
Rect backspaceBtn = {158, (int16_t)(ROW0_Y + 4 * (KEY_H + KEY_GAP)), (int16_t)(Config::SCREEN_WIDTH - 8 - 154), KEY_H};
|
||||||
@@ -163,12 +175,14 @@ namespace {
|
|||||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||||
tft.setCursor(10, 14);
|
tft.setCursor(10, 14);
|
||||||
tft.println(I18n::t(StringId::LOCATION_NAME_PROMPT));
|
tft.println(I18n::t(StringId::LOCATION_NAME_PROMPT));
|
||||||
|
tft.setTextColor(TFT_CYAN, TFT_BLACK);
|
||||||
|
tft.println(I18n::t(StringId::LOCATION_NAME_HINT));
|
||||||
|
|
||||||
tft.fillRect(8, 40, Config::SCREEN_WIDTH - 16, 34, TFT_BLACK);
|
tft.fillRect(8, fieldY, Config::SCREEN_WIDTH - 16, FIELD_H, TFT_BLACK);
|
||||||
tft.drawRect(8, 40, Config::SCREEN_WIDTH - 16, 34, TFT_GREEN);
|
tft.drawRect(8, fieldY, Config::SCREEN_WIDTH - 16, FIELD_H, TFT_GREEN);
|
||||||
tft.setTextSize(2);
|
tft.setTextSize(2);
|
||||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||||
tft.setCursor(14, 66);
|
tft.setCursor(14, (int16_t)(fieldY + 26));
|
||||||
tft.print(buf);
|
tft.print(buf);
|
||||||
tft.setTextSize(1);
|
tft.setTextSize(1);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user