Shortens the first-run location screen's body text in all 6 languages and makes its buttons follow the text's actual height instead of a fixed screen position - the longer German translation previously ran underneath the "Enter Address"/"Skip" buttons, making it unreadable. Adds a new info paragraph to the Location Presets "?" screen (all 6 languages) pointing to the native "Search by address" option added in the previous commit, plus the same tip to the README's Getting Started section. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
100 lines
3.7 KiB
C++
100 lines
3.7 KiB
C++
#include "first_run_location_screen.h"
|
|
#include "address_search_screen.h"
|
|
#include "location_presets.h"
|
|
#include "touch_input.h"
|
|
#include "menu_stars.h"
|
|
#include "config.h"
|
|
#include "i18n.h"
|
|
|
|
namespace FirstRunLocationScreen {
|
|
|
|
namespace {
|
|
struct Rect {
|
|
int16_t x, y, w, h;
|
|
bool contains(int16_t px, int16_t py) const {
|
|
return px >= x && px < x + w && py >= y && py < y + h;
|
|
}
|
|
};
|
|
|
|
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label) {
|
|
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_GREEN);
|
|
tft.setTextDatum(MC_DATUM);
|
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
|
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
|
tft.setTextDatum(TL_DATUM);
|
|
}
|
|
|
|
// Lokale Kopie, siehe Konvention in location_presets_screen.cpp.
|
|
int16_t layoutWrapped(TFT_eSPI& tft, int16_t x, int16_t startY, int16_t maxWidth,
|
|
int16_t lineHeight, const String& text) {
|
|
int16_t y = startY;
|
|
int32_t start = 0;
|
|
int32_t len = text.length();
|
|
while (start < len) {
|
|
while (start < len && text[start] == ' ') start++;
|
|
if (start >= len) break;
|
|
String line = text.substring(start, len);
|
|
while (tft.textWidth(line) > maxWidth) {
|
|
int32_t lastSpace = line.lastIndexOf(' ');
|
|
if (lastSpace <= 0) break;
|
|
line = line.substring(0, lastSpace);
|
|
}
|
|
tft.setCursor(x, y);
|
|
tft.print(line);
|
|
y += lineHeight;
|
|
start += line.length();
|
|
}
|
|
return y;
|
|
}
|
|
}
|
|
|
|
void run(TFT_eSPI& tft) {
|
|
MenuStars::reset();
|
|
tft.fillScreen(TFT_BLACK);
|
|
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
|
tft.setCursor(10, 14);
|
|
tft.println(I18n::t(StringId::FIRST_RUN_LOCATION_TITLE));
|
|
|
|
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
|
int16_t textEndY = layoutWrapped(tft, 10, 40, (int16_t)(Config::SCREEN_WIDTH - 20), 18,
|
|
I18n::t(StringId::FIRST_RUN_LOCATION_BODY));
|
|
|
|
// Buttons folgen direkt unter dem Text (mit etwas Abstand) statt an
|
|
// einer fest einprogrammierten Position - eine laengere Uebersetzung
|
|
// hat sonst den Text bis unter/hinter die Buttons laufen lassen
|
|
// (auf Deutsch beobachtet: Text unlesbar hinter "Adresse eingeben"/
|
|
// "Ueberspringen"). Nach unten hin trotzdem an den Bildschirmrand
|
|
// geklemmt, falls ein Text ausnahmsweise doch sehr lang waere.
|
|
constexpr int16_t BTN_H = 40;
|
|
constexpr int16_t BTN_GAP = 8;
|
|
int16_t setY = textEndY + 14;
|
|
int16_t maxSetY = (int16_t)(Config::SCREEN_HEIGHT - (2 * BTN_H + BTN_GAP + 10));
|
|
if (setY > maxSetY) setY = maxSetY;
|
|
|
|
Rect setBtn = {10, setY, (int16_t)(Config::SCREEN_WIDTH - 20), BTN_H};
|
|
Rect skipBtn = {10, (int16_t)(setY + BTN_H + BTN_GAP), (int16_t)(Config::SCREEN_WIDTH - 20), BTN_H};
|
|
drawButton(tft, setBtn, I18n::t(StringId::FIRST_RUN_LOCATION_SET_BTN));
|
|
drawButton(tft, skipBtn, I18n::t(StringId::FIRST_RUN_LOCATION_SKIP_BTN));
|
|
|
|
while (true) {
|
|
TouchInput::Point tap;
|
|
if (!TouchInput::wasTapped(tap)) { MenuStars::update(tft); delay(20); continue; }
|
|
|
|
if (setBtn.contains(tap.x, tap.y)) {
|
|
if (AddressSearchScreen::run(tft)) {
|
|
// Direkt aktivieren - das ist der ganze Sinn dieses
|
|
// Screens (sofort beim ersten Start den praezisen
|
|
// Standort nutzen, statt weiter auf Auto/IP zu bleiben).
|
|
uint8_t idx = LocationPresets::count();
|
|
if (idx > 0) LocationPresets::setActiveIndex((int8_t)(idx - 1));
|
|
}
|
|
return;
|
|
}
|
|
if (skipBtn.contains(tap.x, tap.y)) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|