v2.2: Custom Unicode font for accented characters (DE/TR/FR/ES/IT), 4-category menu reorganization, black/green UI theme, header layout improvements
This commit is contained in:
@@ -14,11 +14,12 @@ namespace {
|
||||
}
|
||||
};
|
||||
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, uint16_t bg = TFT_NAVY) {
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, bg);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_DARKGREY);
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, bool danger = false) {
|
||||
uint16_t accent = danger ? TFT_RED : TFT_GREEN;
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, TFT_BLACK);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, accent);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, bg);
|
||||
tft.setTextColor(accent, TFT_BLACK);
|
||||
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
@@ -59,14 +60,14 @@ namespace {
|
||||
|
||||
auto redraw = [&]() {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 10);
|
||||
tft.println(I18n::t(StringId::AIRLINE_ADD_TITLE));
|
||||
|
||||
tft.fillRect(8, 40, Config::SCREEN_WIDTH - 16, 30, TFT_NAVY);
|
||||
tft.drawRect(8, 40, Config::SCREEN_WIDTH - 16, 30, TFT_DARKGREY);
|
||||
tft.fillRect(8, 40, Config::SCREEN_WIDTH - 16, 30, TFT_BLACK);
|
||||
tft.drawRect(8, 40, Config::SCREEN_WIDTH - 16, 30, TFT_GREEN);
|
||||
tft.setTextSize(2);
|
||||
tft.setTextColor(TFT_WHITE, TFT_NAVY);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(14, 47);
|
||||
tft.print(buf);
|
||||
tft.setTextSize(1);
|
||||
@@ -76,7 +77,7 @@ namespace {
|
||||
for (uint8_t i = 0; i < 7; i++) drawButton(tft, row3Rects[i], String(ROW3[i]));
|
||||
|
||||
drawButton(tft, backspaceBtn, "<-");
|
||||
drawButton(tft, cancelBtn, I18n::t(StringId::CANCEL), TFT_MAROON);
|
||||
drawButton(tft, cancelBtn, I18n::t(StringId::CANCEL), true);
|
||||
drawButton(tft, confirmBtn, I18n::t(StringId::ADD));
|
||||
};
|
||||
|
||||
@@ -126,10 +127,10 @@ void run(TFT_eSPI& tft) {
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 8);
|
||||
tft.println(I18n::t(StringId::AIRLINE_FILTER_TITLE));
|
||||
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 26);
|
||||
tft.println(I18n::t(StringId::AIRLINE_FILTER_DESC1));
|
||||
tft.setCursor(10, 38);
|
||||
@@ -147,13 +148,13 @@ void run(TFT_eSPI& tft) {
|
||||
rowRects[i] = rowRect;
|
||||
removeRects[i] = removeRect;
|
||||
|
||||
tft.fillRoundRect(rowRect.x, rowRect.y, rowRect.w, rowRect.h, 4, TFT_NAVY);
|
||||
tft.drawRoundRect(rowRect.x, rowRect.y, rowRect.w, rowRect.h, 4, TFT_DARKGREY);
|
||||
tft.fillRoundRect(rowRect.x, rowRect.y, rowRect.w, rowRect.h, 4, TFT_BLACK);
|
||||
tft.drawRoundRect(rowRect.x, rowRect.y, rowRect.w, rowRect.h, 4, TFT_GREEN);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, TFT_NAVY);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.drawString(AirlineFilter::icaoAt(i), rowRect.x + rowRect.w / 2, rowRect.y + rowRect.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
drawButton(tft, removeRect, "X", TFT_MAROON);
|
||||
drawButton(tft, removeRect, "X", true);
|
||||
|
||||
y += ROW_H + ROW_GAP;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ void run(TFT_eSPI& tft) {
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setTextSize(1);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.drawString(I18n::t(StringId::CALIB_TITLE), W / 2, H / 2 - 12);
|
||||
@@ -88,7 +88,7 @@ void run(TFT_eSPI& tft) {
|
||||
TouchInput::saveCalibration();
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 10);
|
||||
tft.println(I18n::t(StringId::CALIB_SAVED));
|
||||
delay(800);
|
||||
|
||||
23
src/i18n.h
23
src/i18n.h
@@ -1,12 +1,6 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
// Zentrales Uebersetzungssystem: jeder feste UI-Text der App hat eine
|
||||
// StringId. Die eigentlichen Uebersetzungen liegen in je einer Datei pro
|
||||
// Sprache (i18n_en.h, i18n_de.h, i18n_fr.h, i18n_tr.h, i18n_es.h, i18n_it.h) -
|
||||
// jede Datei enthaelt ein Array in GENAU derselben Reihenfolge wie dieses
|
||||
// Enum. Neue Menuepunkte/Texte: hier eine neue StringId VOR COUNT einfuegen,
|
||||
// dann in ALLEN 6 Sprachdateien an derselben Position ergaenzen.
|
||||
enum class StringId : uint8_t {
|
||||
OK = 0,
|
||||
CANCEL,
|
||||
@@ -139,17 +133,20 @@ enum class StringId : uint8_t {
|
||||
|
||||
LANGUAGE_TITLE,
|
||||
|
||||
COUNT // IMMER als letztes Element - markiert die Gesamtanzahl
|
||||
MENU_CATEGORY_REGION,
|
||||
MENU_CATEGORY_WIFI,
|
||||
MENU_CATEGORY_SYSTEM,
|
||||
MENU_CATEGORY_FLIGHT,
|
||||
|
||||
WIFI_NETWORKS_TITLE,
|
||||
WIFI_ADD_NETWORK,
|
||||
WIFI_EMPTY_SLOT,
|
||||
|
||||
COUNT
|
||||
};
|
||||
|
||||
namespace I18n {
|
||||
constexpr uint8_t LANG_COUNT = 6;
|
||||
|
||||
// Liefert den uebersetzten Text fuer 'id' in der aktuell in den
|
||||
// Einstellungen gewaehlten Sprache (SettingsStore::language()).
|
||||
const char* t(StringId id);
|
||||
|
||||
// Eigennamen der Sprachen (fuer das Sprachauswahl-Menue), IMMER im
|
||||
// jeweiligen Idiom selbst geschrieben (z.B. "Deutsch", nicht "German").
|
||||
const char* languageName(uint8_t index);
|
||||
}
|
||||
@@ -4,10 +4,10 @@
|
||||
static const char* const I18N_DE[] = {
|
||||
"OK",
|
||||
"Abbrechen",
|
||||
"Zurueck",
|
||||
"< Zurueck",
|
||||
"Laedt...",
|
||||
"Hinzufuegen",
|
||||
"Zurück",
|
||||
"< Zurück",
|
||||
"Lädt...",
|
||||
"Hinzufügen",
|
||||
|
||||
"AN",
|
||||
"AUS",
|
||||
@@ -20,13 +20,13 @@ static const char* const I18N_DE[] = {
|
||||
"Ermittle Standort...",
|
||||
"Bereit!",
|
||||
|
||||
"Fuer diese App wird",
|
||||
"Für diese App wird",
|
||||
"eine SD-Karte",
|
||||
"benoetigt",
|
||||
"SD-Karte einlegen und Geraet neu starten",
|
||||
"benötigt",
|
||||
"SD-Karte einlegen und Gerät neu starten",
|
||||
|
||||
"Touch-Kalibrierung",
|
||||
"Bitte den Kreis beruehren:",
|
||||
"Bitte den Kreis berühren:",
|
||||
"Oben links",
|
||||
"Oben rechts",
|
||||
"Unten rechts",
|
||||
@@ -35,14 +35,14 @@ static const char* const I18N_DE[] = {
|
||||
|
||||
"Suche WLAN...",
|
||||
"Keine Netzwerke gefunden",
|
||||
"WLAN waehlen:",
|
||||
"WLAN wählen:",
|
||||
"Verbunden!",
|
||||
"Verbindung fehlgeschlagen.",
|
||||
"Zurueck zur Netzwerkliste...",
|
||||
"Zurück zur Netzwerkliste...",
|
||||
"Passwort:",
|
||||
"Leerzeichen",
|
||||
"Verbinden",
|
||||
"Zurueck zur Liste",
|
||||
"Zurück zur Liste",
|
||||
"Bereits 3 Netzwerke gespeichert.",
|
||||
"Erst eins entfernen.",
|
||||
"Verbinde...",
|
||||
@@ -60,7 +60,7 @@ static const char* const I18N_DE[] = {
|
||||
"Logbuch-Dateien",
|
||||
"Weitere Einstellungen >",
|
||||
"Notfall-Alarm: ",
|
||||
"Naeherungs-LED: ",
|
||||
"Näherungs-LED: ",
|
||||
"LED-Herzschlag: ",
|
||||
"Flugbuch: ",
|
||||
"Bodenfahrzeuge ausblenden: ",
|
||||
@@ -69,7 +69,7 @@ static const char* const I18N_DE[] = {
|
||||
"Einstellungen wiederherstellen",
|
||||
"Backup gespeichert.",
|
||||
"Backup fehlgeschlagen.",
|
||||
"Wiederhergestellt. Geraet neu starten!",
|
||||
"Wiederhergestellt. Gerät neu starten!",
|
||||
"Wiederherstellung fehlgeschlagen.",
|
||||
"Sprache",
|
||||
"Einheiten",
|
||||
@@ -77,46 +77,46 @@ static const char* const I18N_DE[] = {
|
||||
"Ausgeblendete Airlines",
|
||||
"Flugzeuge dieser Airlines werden",
|
||||
"im Radar ausgeblendet.",
|
||||
"Airline hinzufuegen",
|
||||
"Airline hinzufuegen (ICAO-Code)",
|
||||
"Airline hinzufügen",
|
||||
"Airline hinzufügen (ICAO-Code)",
|
||||
|
||||
"Standort-Presets",
|
||||
"Automatisch (GPS/IP)",
|
||||
"Preset",
|
||||
"(leer)",
|
||||
"Preset hinzufuegen",
|
||||
"Preset hinzufügen",
|
||||
"Breitengrad (z.B. 48.6833)",
|
||||
"Laengengrad (z.B. 9.8333)",
|
||||
"Längengrad (z.B. 9.8333)",
|
||||
|
||||
"Statistik",
|
||||
"Heute geloggte Flugzeuge",
|
||||
"Insgesamt geloggte Flugzeuge",
|
||||
"Tage mit Sichtungen",
|
||||
"Durchschnitt pro Tag",
|
||||
"Flugbuch zuruecksetzen",
|
||||
"Nochmal tippen zum Bestaetigen!",
|
||||
"Flugbuch-Daten zurueckgesetzt.",
|
||||
"Flugbuch zurücksetzen",
|
||||
"Nochmal tippen zum Bestätigen!",
|
||||
"Flugbuch-Daten zurückgesetzt.",
|
||||
"Laufzeit: ",
|
||||
|
||||
"Logbuch-Dateien",
|
||||
"Noch keine Flugbuch-Eintraege.",
|
||||
"Noch keine Flugbuch-Einträge.",
|
||||
"Zeige die letzten ",
|
||||
" von ",
|
||||
" Tagen",
|
||||
" Flugzeuge",
|
||||
|
||||
"Fuer Details antippen",
|
||||
"Für Details antippen",
|
||||
|
||||
"Modell: ",
|
||||
"Typ: ",
|
||||
"laedt...",
|
||||
"lädt...",
|
||||
"unbekannt",
|
||||
"Hoehe: ",
|
||||
"Höhe: ",
|
||||
"Geschw.: ",
|
||||
"Distanz: ",
|
||||
"Kurs: ",
|
||||
"Sitzplaetze (geschaetzt): ",
|
||||
"Sitzplaetze: unbekannt",
|
||||
"Sitzplätze (geschätzt): ",
|
||||
"Sitzplätze: unbekannt",
|
||||
"Woanders antippen zum Schliessen",
|
||||
"Steigen: ",
|
||||
"Sinken: ",
|
||||
@@ -132,6 +132,15 @@ static const char* const I18N_DE[] = {
|
||||
"Imperial (ft, kt, nm)",
|
||||
|
||||
"Sprache",
|
||||
|
||||
"Land/Region",
|
||||
"WLAN/Netzwerk",
|
||||
"System",
|
||||
"Flugoptionen",
|
||||
|
||||
"WLAN-Netzwerke",
|
||||
"Netzwerk hinzufügen",
|
||||
"(leer)",
|
||||
};
|
||||
|
||||
static_assert(sizeof(I18N_DE) / sizeof(I18N_DE[0]) == (size_t)StringId::COUNT,
|
||||
|
||||
@@ -132,6 +132,15 @@ static const char* const I18N_EN[] = {
|
||||
"Imperial (ft, kt, nm)",
|
||||
|
||||
"Language",
|
||||
|
||||
"Region & Language",
|
||||
"WiFi / Network",
|
||||
"System",
|
||||
"Flight Options",
|
||||
|
||||
"WiFi networks",
|
||||
"Add network",
|
||||
"(empty)",
|
||||
};
|
||||
|
||||
static_assert(sizeof(I18N_EN) / sizeof(I18N_EN[0]) == (size_t)StringId::COUNT,
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
static const char* const I18N_ES[] = {
|
||||
"OK",
|
||||
"Cancelar",
|
||||
"Atras",
|
||||
"< Atras",
|
||||
"Atrás",
|
||||
"< Atrás",
|
||||
"Cargando...",
|
||||
"Anadir",
|
||||
"Añadir",
|
||||
|
||||
"ON",
|
||||
"OFF",
|
||||
@@ -16,30 +16,30 @@ static const char* const I18N_ES[] = {
|
||||
"Tarjeta SD: OK",
|
||||
"Conectando WiFi...",
|
||||
"WiFi OK: ",
|
||||
"WiFi FALLO",
|
||||
"Obteniendo ubicacion...",
|
||||
"Listo!",
|
||||
"WiFi FALLÓ",
|
||||
"Obteniendo ubicación...",
|
||||
"¡Listo!",
|
||||
|
||||
"Esta app necesita",
|
||||
"una tarjeta SD",
|
||||
"requerida",
|
||||
"Inserte una tarjeta y reinicie el dispositivo",
|
||||
|
||||
"Calibracion tactil",
|
||||
"Toque el circulo:",
|
||||
"Calibración táctil",
|
||||
"Toque el círculo:",
|
||||
"Arriba izquierda",
|
||||
"Arriba derecha",
|
||||
"Abajo derecha",
|
||||
"Abajo izquierda",
|
||||
"Calibracion guardada!",
|
||||
"¡Calibración guardada!",
|
||||
|
||||
"Buscando WiFi...",
|
||||
"No se encontraron redes",
|
||||
"Elegir WiFi:",
|
||||
"Conectado!",
|
||||
"Conexion fallida.",
|
||||
"¡Conectado!",
|
||||
"Conexión fallida.",
|
||||
"Volviendo a la lista...",
|
||||
"Contrasena:",
|
||||
"Contraseña:",
|
||||
"Espacio",
|
||||
"Conectar",
|
||||
"Volver a la lista",
|
||||
@@ -50,59 +50,59 @@ static const char* const I18N_ES[] = {
|
||||
|
||||
"Ajustes",
|
||||
"Ajustes (2/2)",
|
||||
"Calibrar tactil",
|
||||
"Calibrar táctil",
|
||||
"Pantalla: invertida (toque)",
|
||||
"Pantalla: normal (toque)",
|
||||
"Gestionar redes WiFi",
|
||||
"Ubicaciones guardadas",
|
||||
"Apagado de pantalla: ",
|
||||
"Estadisticas",
|
||||
"Estadísticas",
|
||||
"Archivos del registro",
|
||||
"Mas ajustes >",
|
||||
"Más ajustes >",
|
||||
"Alerta de emergencia: ",
|
||||
"LED de proximidad: ",
|
||||
"Latido LED: ",
|
||||
"Registro de vuelos: ",
|
||||
"Ocultar vehiculos terrestres: ",
|
||||
"Filtro de aerolineas",
|
||||
"Ocultar vehículos terrestres: ",
|
||||
"Filtro de aerolíneas",
|
||||
"Copia de seguridad",
|
||||
"Restaurar ajustes",
|
||||
"Copia guardada.",
|
||||
"Fallo la copia de seguridad.",
|
||||
"Restaurado. Reinicie el dispositivo!",
|
||||
"Fallo la restauracion.",
|
||||
"Falló la copia de seguridad.",
|
||||
"¡Restaurado. Reinicie el dispositivo!",
|
||||
"Falló la restauración.",
|
||||
"Idioma",
|
||||
"Unidades",
|
||||
|
||||
"Aerolineas ocultas",
|
||||
"Los aviones de estas aerolineas",
|
||||
"Aerolíneas ocultas",
|
||||
"Los aviones de estas aerolíneas",
|
||||
"se ocultan del radar.",
|
||||
"Anadir aerolinea",
|
||||
"Anadir aerolinea (codigo OACI)",
|
||||
"Añadir aerolínea",
|
||||
"Añadir aerolínea (código OACI)",
|
||||
|
||||
"Ubicaciones guardadas",
|
||||
"Auto (GPS/IP)",
|
||||
"Ubicacion",
|
||||
"(vacio)",
|
||||
"Anadir ubicacion",
|
||||
"Ubicación",
|
||||
"(vacío)",
|
||||
"Añadir ubicación",
|
||||
"Latitud (ej. 48.6833)",
|
||||
"Longitud (ej. 9.8333)",
|
||||
|
||||
"Estadisticas",
|
||||
"Estadísticas",
|
||||
"Aviones registrados hoy",
|
||||
"Aviones registrados en total",
|
||||
"Dias con avistamientos",
|
||||
"Promedio por dia",
|
||||
"Días con avistamientos",
|
||||
"Promedio por día",
|
||||
"Reiniciar registro",
|
||||
"Toque de nuevo para confirmar!",
|
||||
"¡Toque de nuevo para confirmar!",
|
||||
"Registro reiniciado.",
|
||||
"Tiempo activo: ",
|
||||
|
||||
"Archivos del registro",
|
||||
"Aun no hay registros.",
|
||||
"Mostrando los ultimos ",
|
||||
"Aún no hay registros.",
|
||||
"Mostrando los últimos ",
|
||||
" de ",
|
||||
" dias",
|
||||
" días",
|
||||
" aviones",
|
||||
|
||||
"Toque para ver detalles",
|
||||
@@ -124,14 +124,23 @@ static const char* const I18N_ES[] = {
|
||||
"Squawk: ",
|
||||
|
||||
"Guardado: ",
|
||||
"Fallo la captura de pantalla",
|
||||
"Falló la captura de pantalla",
|
||||
|
||||
"Unidades",
|
||||
"Auto (segun ubicacion)",
|
||||
"Metrico (km, m, km/h)",
|
||||
"Auto (según ubicación)",
|
||||
"Métrico (km, m, km/h)",
|
||||
"Imperial (ft, kt, nm)",
|
||||
|
||||
"Idioma",
|
||||
|
||||
"Región e idioma",
|
||||
"WiFi / Red",
|
||||
"Sistema",
|
||||
"Opciones de vuelo",
|
||||
|
||||
"Redes WiFi",
|
||||
"Añadir red",
|
||||
"(vacío)",
|
||||
};
|
||||
|
||||
static_assert(sizeof(I18N_ES) / sizeof(I18N_ES[0]) == (size_t)StringId::COUNT,
|
||||
|
||||
105
src/i18n_fr.h
105
src/i18n_fr.h
@@ -16,71 +16,71 @@ static const char* const I18N_FR[] = {
|
||||
"Carte SD: OK",
|
||||
"Connexion WiFi...",
|
||||
"WiFi OK: ",
|
||||
"ECHEC WiFi",
|
||||
"ÉCHEC WiFi",
|
||||
"Localisation...",
|
||||
"Pret !",
|
||||
"Prêt !",
|
||||
|
||||
"Pour cette appli une",
|
||||
"carte SD est",
|
||||
"requise",
|
||||
"Inserez une carte et redemarrez l'appareil",
|
||||
"Insérez une carte et redémarrez l'appareil",
|
||||
|
||||
"Etalonnage tactile",
|
||||
"Étalonnage tactile",
|
||||
"Touchez le cercle :",
|
||||
"Haut gauche",
|
||||
"Haut droite",
|
||||
"Bas droite",
|
||||
"Bas gauche",
|
||||
"Etalonnage enregistre !",
|
||||
"Étalonnage enregistré !",
|
||||
|
||||
"Recherche WiFi...",
|
||||
"Aucun reseau trouve",
|
||||
"Aucun réseau trouvé",
|
||||
"Choisir WiFi :",
|
||||
"Connecte !",
|
||||
"Echec de connexion.",
|
||||
"Retour a la liste...",
|
||||
"Connecté !",
|
||||
"Échec de connexion.",
|
||||
"Retour à la liste...",
|
||||
"Mot de passe :",
|
||||
"Espace",
|
||||
"Connecter",
|
||||
"Retour a la liste",
|
||||
"Deja 3 reseaux enregistres.",
|
||||
"Retour à la liste",
|
||||
"Déjà 3 réseaux enregistrés.",
|
||||
"Supprimez-en un d'abord.",
|
||||
"Connexion...",
|
||||
"WiFi : ",
|
||||
|
||||
"Reglages",
|
||||
"Reglages (2/2)",
|
||||
"Etalonner le tactile",
|
||||
"Ecran : inverse (touchez)",
|
||||
"Ecran : normal (touchez)",
|
||||
"Gerer les reseaux WiFi",
|
||||
"Positions enregistrees",
|
||||
"Extinction ecran : ",
|
||||
"Réglages",
|
||||
"Réglages (2/2)",
|
||||
"Étalonner le tactile",
|
||||
"Écran : inversé (touchez)",
|
||||
"Écran : normal (touchez)",
|
||||
"Gérer les réseaux WiFi",
|
||||
"Positions enregistrées",
|
||||
"Extinction écran : ",
|
||||
"Statistiques",
|
||||
"Fichiers du journal",
|
||||
"Plus de reglages >",
|
||||
"Plus de réglages >",
|
||||
"Alerte urgence : ",
|
||||
"LED de proximite : ",
|
||||
"LED de proximité : ",
|
||||
"Battement LED : ",
|
||||
"Journal de vol : ",
|
||||
"Masquer vehicules au sol : ",
|
||||
"Masquer véhicules au sol : ",
|
||||
"Filtre compagnies",
|
||||
"Sauvegarder reglages",
|
||||
"Restaurer reglages",
|
||||
"Sauvegarde enregistree.",
|
||||
"Echec de la sauvegarde.",
|
||||
"Restaure. Redemarrez l'appareil !",
|
||||
"Echec de la restauration.",
|
||||
"Sauvegarder réglages",
|
||||
"Restaurer réglages",
|
||||
"Sauvegarde enregistrée.",
|
||||
"Échec de la sauvegarde.",
|
||||
"Restauré. Redémarrez l'appareil !",
|
||||
"Échec de la restauration.",
|
||||
"Langue",
|
||||
"Unites",
|
||||
"Unités",
|
||||
|
||||
"Compagnies masquees",
|
||||
"Compagnies masquées",
|
||||
"Les avions de ces compagnies sont",
|
||||
"masques du radar.",
|
||||
"masqués du radar.",
|
||||
"Ajouter une compagnie",
|
||||
"Ajouter (code OACI)",
|
||||
|
||||
"Positions enregistrees",
|
||||
"Positions enregistrées",
|
||||
"Auto (GPS/IP)",
|
||||
"Position",
|
||||
"(vide)",
|
||||
@@ -89,25 +89,25 @@ static const char* const I18N_FR[] = {
|
||||
"Longitude (ex. 9.8333)",
|
||||
|
||||
"Statistiques",
|
||||
"Avions enregistres aujourd'hui",
|
||||
"Avions enregistres au total",
|
||||
"Avions enregistrés aujourd'hui",
|
||||
"Avions enregistrés au total",
|
||||
"Jours avec observations",
|
||||
"Moyenne par jour",
|
||||
"Reinitialiser le journal",
|
||||
"Réinitialiser le journal",
|
||||
"Retouchez pour confirmer !",
|
||||
"Journal reinitialise.",
|
||||
"Duree de fonctionnement : ",
|
||||
"Journal réinitialisé.",
|
||||
"Durée de fonctionnement : ",
|
||||
|
||||
"Fichiers du journal",
|
||||
"Aucune entree pour le moment.",
|
||||
"Aucune entrée pour le moment.",
|
||||
"Affichage des ",
|
||||
" derniers sur ",
|
||||
" jours",
|
||||
" avions",
|
||||
|
||||
"Touchez pour les details",
|
||||
"Touchez pour les détails",
|
||||
|
||||
"Modele : ",
|
||||
"Modèle : ",
|
||||
"Type : ",
|
||||
"chargement...",
|
||||
"inconnu",
|
||||
@@ -115,23 +115,32 @@ static const char* const I18N_FR[] = {
|
||||
"Vitesse : ",
|
||||
"Dist. : ",
|
||||
"Cap : ",
|
||||
"Sieges (estime) : ",
|
||||
"Sieges : inconnu",
|
||||
"Sièges (estimé) : ",
|
||||
"Sièges : inconnu",
|
||||
"Touchez ailleurs pour fermer",
|
||||
"Montee : ",
|
||||
"Montée : ",
|
||||
"Descente : ",
|
||||
"Vol en palier",
|
||||
"Squawk : ",
|
||||
|
||||
"Enregistre : ",
|
||||
"Echec de la capture d'ecran",
|
||||
"Enregistré : ",
|
||||
"Échec de la capture d'écran",
|
||||
|
||||
"Unites",
|
||||
"Unités",
|
||||
"Auto (selon la position)",
|
||||
"Metrique (km, m, km/h)",
|
||||
"Imperial (ft, kt, nm)",
|
||||
"Métrique (km, m, km/h)",
|
||||
"Impérial (ft, kt, nm)",
|
||||
|
||||
"Langue",
|
||||
|
||||
"Région et langue",
|
||||
"WiFi / Réseau",
|
||||
"Système",
|
||||
"Options de vol",
|
||||
|
||||
"Réseaux WiFi",
|
||||
"Ajouter un réseau",
|
||||
"(vide)",
|
||||
};
|
||||
|
||||
static_assert(sizeof(I18N_FR) / sizeof(I18N_FR[0]) == (size_t)StringId::COUNT,
|
||||
|
||||
@@ -43,7 +43,7 @@ static const char* const I18N_IT[] = {
|
||||
"Spazio",
|
||||
"Connetti",
|
||||
"Torna alla lista",
|
||||
"Gia 3 reti salvate.",
|
||||
"Già 3 reti salvate.",
|
||||
"Rimuovine una prima.",
|
||||
"Connessione...",
|
||||
"WiFi: ",
|
||||
@@ -60,7 +60,7 @@ static const char* const I18N_IT[] = {
|
||||
"File del registro",
|
||||
"Altre impostazioni >",
|
||||
"Allarme emergenza: ",
|
||||
"LED di prossimita: ",
|
||||
"LED di prossimità: ",
|
||||
"Battito LED: ",
|
||||
"Diario di volo: ",
|
||||
"Nascondi veicoli a terra: ",
|
||||
@@ -72,7 +72,7 @@ static const char* const I18N_IT[] = {
|
||||
"Ripristinato. Riavviare il dispositivo!",
|
||||
"Ripristino fallito.",
|
||||
"Lingua",
|
||||
"Unita",
|
||||
"Unità",
|
||||
|
||||
"Compagnie nascoste",
|
||||
"Gli aerei di queste compagnie",
|
||||
@@ -96,7 +96,7 @@ static const char* const I18N_IT[] = {
|
||||
"Reimposta registro",
|
||||
"Tocca di nuovo per confermare!",
|
||||
"Registro reimpostato.",
|
||||
"Tempo di attivita: ",
|
||||
"Tempo di attività: ",
|
||||
|
||||
"File del registro",
|
||||
"Ancora nessun dato.",
|
||||
@@ -126,12 +126,21 @@ static const char* const I18N_IT[] = {
|
||||
"Salvato: ",
|
||||
"Screenshot fallito",
|
||||
|
||||
"Unita",
|
||||
"Unità",
|
||||
"Auto (in base alla posizione)",
|
||||
"Metrico (km, m, km/h)",
|
||||
"Imperiale (ft, kt, nm)",
|
||||
|
||||
"Lingua",
|
||||
|
||||
"Regione e lingua",
|
||||
"WiFi / Rete",
|
||||
"Sistema",
|
||||
"Opzioni di volo",
|
||||
|
||||
"Reti WiFi",
|
||||
"Aggiungi rete",
|
||||
"(vuoto)",
|
||||
};
|
||||
|
||||
static_assert(sizeof(I18N_IT) / sizeof(I18N_IT[0]) == (size_t)StringId::COUNT,
|
||||
|
||||
161
src/i18n_tr.h
161
src/i18n_tr.h
@@ -3,135 +3,144 @@
|
||||
|
||||
static const char* const I18N_TR[] = {
|
||||
"Tamam",
|
||||
"Iptal",
|
||||
"İptal",
|
||||
"Geri",
|
||||
"< Geri",
|
||||
"Yukleniyor...",
|
||||
"Yükleniyor...",
|
||||
"Ekle",
|
||||
|
||||
"ACIK",
|
||||
"AÇIK",
|
||||
"KAPALI",
|
||||
"Asla",
|
||||
|
||||
"SD Kart: OK",
|
||||
"WiFi'ye baglaniyor...",
|
||||
"WiFi'ye bağlanıyor...",
|
||||
"WiFi OK: ",
|
||||
"WiFi BASARISIZ",
|
||||
"Konum aliniyor...",
|
||||
"Hazir!",
|
||||
"WiFi BAŞARISIZ",
|
||||
"Konum alınıyor...",
|
||||
"Hazır!",
|
||||
|
||||
"Bu uygulama icin bir",
|
||||
"Bu uygulama için bir",
|
||||
"SD kart",
|
||||
"gereklidir",
|
||||
"Bir kart takin ve cihazi yeniden baslatin",
|
||||
"Bir kart takın ve cihazı yeniden başlatın",
|
||||
|
||||
"Dokunmatik Kalibrasyon",
|
||||
"Lutfen daireye dokunun:",
|
||||
"Sol ust",
|
||||
"Sag ust",
|
||||
"Sag alt",
|
||||
"Lütfen daireye dokunun:",
|
||||
"Sol üst",
|
||||
"Sağ üst",
|
||||
"Sağ alt",
|
||||
"Sol alt",
|
||||
"Kalibrasyon kaydedildi!",
|
||||
|
||||
"WiFi taraniyor...",
|
||||
"Ag bulunamadi",
|
||||
"WiFi secin:",
|
||||
"Baglandi!",
|
||||
"Baglanti basarisiz.",
|
||||
"Ag listesine donuluyor...",
|
||||
"Sifre:",
|
||||
"Bosluk",
|
||||
"Baglan",
|
||||
"Listeye don",
|
||||
"Zaten 3 ag kayitli.",
|
||||
"Once birini kaldirin.",
|
||||
"Baglaniyor...",
|
||||
"WiFi taranıyor...",
|
||||
"Ağ bulunamadı",
|
||||
"WiFi seçin:",
|
||||
"Bağlandı!",
|
||||
"Bağlantı başarısız.",
|
||||
"Ağ listesine dönülüyor...",
|
||||
"Şifre:",
|
||||
"Boşluk",
|
||||
"Bağlan",
|
||||
"Listeye dön",
|
||||
"Zaten 3 ağ kayıtlı.",
|
||||
"Önce birini kaldırın.",
|
||||
"Bağlanıyor...",
|
||||
"WiFi: ",
|
||||
|
||||
"Ayarlar",
|
||||
"Ayarlar (2/2)",
|
||||
"Dokunmatigi kalibre et",
|
||||
"Dokunmatiği kalibre et",
|
||||
"Ekran: ters (dokun)",
|
||||
"Ekran: normal (dokun)",
|
||||
"WiFi aglarini yonet",
|
||||
"Konum on ayarlari",
|
||||
"Ekran zaman asimi: ",
|
||||
"Istatistikler",
|
||||
"Kayit defteri dosyalari",
|
||||
"Diger ayarlar >",
|
||||
"Acil durum alarmi: ",
|
||||
"Yakinlik LED'i: ",
|
||||
"LED kalp atisi: ",
|
||||
"Ucus kayit defteri: ",
|
||||
"Kara araclarini gizle: ",
|
||||
"WiFi ağlarını yönet",
|
||||
"Konum ön ayarları",
|
||||
"Ekran zaman aşımı: ",
|
||||
"İstatistikler",
|
||||
"Kayıt defteri dosyaları",
|
||||
"Diğer ayarlar >",
|
||||
"Acil durum alarmı: ",
|
||||
"Yakınlık LED'i: ",
|
||||
"LED kalp atışı: ",
|
||||
"Uçuş kayıt defteri: ",
|
||||
"Kara araçlarını gizle: ",
|
||||
"Havayolu filtresi",
|
||||
"Ayarlari yedekle",
|
||||
"Ayarlari geri yukle",
|
||||
"Ayarları yedekle",
|
||||
"Ayarları geri yükle",
|
||||
"Yedekleme kaydedildi.",
|
||||
"Yedekleme basarisiz.",
|
||||
"Geri yuklendi. Cihazi yeniden baslatin!",
|
||||
"Geri yukleme basarisiz.",
|
||||
"Yedekleme başarısız.",
|
||||
"Geri yüklendi. Cihazı yeniden başlatın!",
|
||||
"Geri yükleme başarısız.",
|
||||
"Dil",
|
||||
"Birimler",
|
||||
|
||||
"Gizli havayollari",
|
||||
"Bu havayollarina ait ucaklar",
|
||||
"Gizli havayolları",
|
||||
"Bu havayollarına ait uçaklar",
|
||||
"radarda gizlenir.",
|
||||
"Havayolu ekle",
|
||||
"Havayolu ekle (ICAO kodu)",
|
||||
|
||||
"Konum on ayarlari",
|
||||
"Konum ön ayarları",
|
||||
"Otomatik (GPS/IP)",
|
||||
"On ayar",
|
||||
"(bos)",
|
||||
"On ayar ekle",
|
||||
"Enlem (orn. 48.6833)",
|
||||
"Boylam (orn. 9.8333)",
|
||||
"Ön ayar",
|
||||
"(boş)",
|
||||
"Ön ayar ekle",
|
||||
"Enlem (örn. 48.6833)",
|
||||
"Boylam (örn. 9.8333)",
|
||||
|
||||
"Istatistikler",
|
||||
"Bugun kaydedilen ucaklar",
|
||||
"Toplam kaydedilen ucaklar",
|
||||
"Gozlem yapilan gunler",
|
||||
"Gunluk ortalama",
|
||||
"Kayit defterini sifirla",
|
||||
"Onaylamak icin tekrar dokunun!",
|
||||
"Kayit defteri sifirlandi.",
|
||||
"Calisma suresi: ",
|
||||
"İstatistikler",
|
||||
"Bugün kaydedilen uçaklar",
|
||||
"Toplam kaydedilen uçaklar",
|
||||
"Gözlem yapılan günler",
|
||||
"Günlük ortalama",
|
||||
"Kayıt defterini sıfırla",
|
||||
"Onaylamak için tekrar dokunun!",
|
||||
"Kayıt defteri sıfırlandı.",
|
||||
"Çalışma süresi: ",
|
||||
|
||||
"Kayit defteri dosyalari",
|
||||
"Henuz kayit yok.",
|
||||
"Kayıt defteri dosyaları",
|
||||
"Henüz kayıt yok.",
|
||||
"Son ",
|
||||
" / ",
|
||||
" gun gosteriliyor",
|
||||
" ucak",
|
||||
" gün gösteriliyor",
|
||||
" uçak",
|
||||
|
||||
"Detaylar icin dokunun",
|
||||
"Detaylar için dokunun",
|
||||
|
||||
"Model: ",
|
||||
"Tip: ",
|
||||
"yukleniyor...",
|
||||
"yükleniyor...",
|
||||
"bilinmiyor",
|
||||
"Yuk.: ",
|
||||
"Hiz: ",
|
||||
"Yük.: ",
|
||||
"Hız: ",
|
||||
"Mesafe: ",
|
||||
"Yon: ",
|
||||
"Yön: ",
|
||||
"Koltuk (tahmini): ",
|
||||
"Koltuk: bilinmiyor",
|
||||
"Kapatmak icin baska yere dokunun",
|
||||
"Tirmanis: ",
|
||||
"Alcalma: ",
|
||||
"Duz ucus",
|
||||
"Kapatmak için başka yere dokunun",
|
||||
"Tırmanış: ",
|
||||
"Alçalma: ",
|
||||
"Düz uçuş",
|
||||
"Squawk: ",
|
||||
|
||||
"Kaydedildi: ",
|
||||
"Ekran goruntusu basarisiz",
|
||||
"Ekran görüntüsü başarısız",
|
||||
|
||||
"Birimler",
|
||||
"Otomatik (konuma gore)",
|
||||
"Otomatik (konuma göre)",
|
||||
"Metrik (km, m, km/sa)",
|
||||
"Imperyal (ft, kt, nm)",
|
||||
"İmperyal (ft, kt, nm)",
|
||||
|
||||
"Dil",
|
||||
|
||||
"Bölge ve Dil",
|
||||
"WiFi / Ağ",
|
||||
"Sistem",
|
||||
"Uçuş Seçenekleri",
|
||||
|
||||
"WiFi ağları",
|
||||
"Ağ ekle",
|
||||
"(boş)",
|
||||
};
|
||||
|
||||
static_assert(sizeof(I18N_TR) / sizeof(I18N_TR[0]) == (size_t)StringId::COUNT,
|
||||
|
||||
@@ -14,11 +14,13 @@ namespace {
|
||||
}
|
||||
};
|
||||
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, uint16_t bg = TFT_NAVY) {
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, bool active = false) {
|
||||
uint16_t bg = active ? TFT_GREEN : TFT_BLACK;
|
||||
uint16_t fg = active ? TFT_BLACK : TFT_GREEN;
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, bg);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_DARKGREY);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_GREEN);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, bg);
|
||||
tft.setTextColor(fg, bg);
|
||||
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
@@ -37,7 +39,7 @@ void run(TFT_eSPI& tft) {
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 6);
|
||||
tft.println(I18n::t(StringId::LANGUAGE_TITLE));
|
||||
|
||||
@@ -46,8 +48,7 @@ void run(TFT_eSPI& tft) {
|
||||
|
||||
for (uint8_t i = 0; i < I18n::LANG_COUNT; i++) {
|
||||
langRects[i] = rowRect(i);
|
||||
drawButton(tft, langRects[i], I18n::languageName(i),
|
||||
(i == current) ? TFT_DARKGREEN : TFT_NAVY);
|
||||
drawButton(tft, langRects[i], I18n::languageName(i), i == current);
|
||||
}
|
||||
|
||||
Rect backBtn = rowRect(I18n::LANG_COUNT);
|
||||
|
||||
@@ -14,11 +14,15 @@ namespace {
|
||||
}
|
||||
};
|
||||
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, uint16_t bg = TFT_NAVY) {
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label,
|
||||
bool active = false, bool danger = false) {
|
||||
uint16_t accent = danger ? TFT_RED : TFT_GREEN;
|
||||
uint16_t bg = active ? accent : TFT_BLACK;
|
||||
uint16_t fg = active ? TFT_BLACK : accent;
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, bg);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_DARKGREY);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, accent);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, bg);
|
||||
tft.setTextColor(fg, bg);
|
||||
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
@@ -43,10 +47,6 @@ namespace {
|
||||
KEY_W, KEY_H};
|
||||
}
|
||||
|
||||
// WICHTIG: Backspace muss VOR den Cancel/OK-Buttons enden (mit
|
||||
// Abstand), sonst ueberlappen sich die Tap-Flaechen - Backspace wird
|
||||
// in der Pruef-Reihenfolge zuerst getestet, wuerde also faelschlich
|
||||
// jeden Tap auf "Cancel" abfangen (Bug: Cancel-Button reagierte nicht).
|
||||
Rect backspaceBtn = {(int16_t)GRID_LEFT, (int16_t)(GRID_TOP + 4 * (KEY_H + KEY_GAP)),
|
||||
(int16_t)(3 * KEY_W + 2 * KEY_GAP), 30};
|
||||
Rect cancelBtn = {10, (int16_t)(Config::SCREEN_HEIGHT - 50), 110, 40};
|
||||
@@ -57,21 +57,21 @@ namespace {
|
||||
|
||||
auto redraw = [&]() {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 10);
|
||||
tft.println(title);
|
||||
|
||||
tft.fillRect(8, 40, Config::SCREEN_WIDTH - 16, 34, TFT_NAVY);
|
||||
tft.drawRect(8, 40, Config::SCREEN_WIDTH - 16, 34, TFT_DARKGREY);
|
||||
tft.fillRect(8, 40, Config::SCREEN_WIDTH - 16, 34, TFT_BLACK);
|
||||
tft.drawRect(8, 40, Config::SCREEN_WIDTH - 16, 34, TFT_GREEN);
|
||||
tft.setTextSize(2);
|
||||
tft.setTextColor(TFT_WHITE, TFT_NAVY);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(14, 49);
|
||||
tft.print(buf);
|
||||
tft.setTextSize(1);
|
||||
|
||||
for (uint8_t i = 0; i < 12; i++) drawButton(tft, keyRects[i], keys[i]);
|
||||
drawButton(tft, backspaceBtn, "<- Backspace");
|
||||
drawButton(tft, cancelBtn, I18n::t(StringId::CANCEL), TFT_MAROON);
|
||||
drawButton(tft, cancelBtn, I18n::t(StringId::CANCEL), false, true);
|
||||
drawButton(tft, confirmBtn, I18n::t(StringId::OK));
|
||||
};
|
||||
|
||||
@@ -133,7 +133,7 @@ void run(TFT_eSPI& tft) {
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 8);
|
||||
tft.println(I18n::t(StringId::LOCATION_TITLE));
|
||||
|
||||
@@ -143,8 +143,7 @@ void run(TFT_eSPI& tft) {
|
||||
|
||||
Rect autoRect = {10, y, (int16_t)(Config::SCREEN_WIDTH - 20), ROW_H};
|
||||
String autoLabel = I18n::t(StringId::LOCATION_AUTO);
|
||||
drawButton(tft, autoRect, active < 0 ? ("> " + autoLabel) : autoLabel,
|
||||
active < 0 ? TFT_DARKGREEN : TFT_NAVY);
|
||||
drawButton(tft, autoRect, active < 0 ? ("> " + autoLabel) : autoLabel, active < 0);
|
||||
y += ROW_H + ROW_GAP;
|
||||
|
||||
Rect rowRects[LocationPresets::MAX_PRESETS];
|
||||
@@ -163,13 +162,13 @@ void run(TFT_eSPI& tft) {
|
||||
char coords[24];
|
||||
snprintf(coords, sizeof(coords), "%d: %.3f, %.3f", i + 1, lat, lon);
|
||||
String label = (active == (int8_t)i ? "> " : "") + presetWord + " " + coords;
|
||||
drawButton(tft, rowRect, label, (active == (int8_t)i) ? TFT_DARKGREEN : TFT_NAVY);
|
||||
drawButton(tft, removeRect, "X", TFT_MAROON);
|
||||
drawButton(tft, rowRect, label, active == (int8_t)i);
|
||||
drawButton(tft, removeRect, "X", false, true);
|
||||
} else {
|
||||
tft.fillRoundRect(rowRect.x, rowRect.y, rowRect.w, rowRect.h, 4, TFT_BLACK);
|
||||
tft.drawRoundRect(rowRect.x, rowRect.y, rowRect.w, rowRect.h, 4, TFT_DARKGREY);
|
||||
tft.drawRoundRect(rowRect.x, rowRect.y, rowRect.w, rowRect.h, 4, TFT_DARKGREEN);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
|
||||
tft.setTextColor(TFT_DARKGREEN, TFT_BLACK);
|
||||
String label = presetWord + " " + String(i + 1) + " " + I18n::t(StringId::LOCATION_PRESET_EMPTY);
|
||||
tft.drawString(label, rowRect.x + rowRect.w / 2, rowRect.y + rowRect.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
|
||||
@@ -15,10 +15,10 @@ namespace {
|
||||
};
|
||||
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label) {
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, TFT_NAVY);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_DARKGREY);
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, TFT_BLACK);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_GREEN);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, TFT_NAVY);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
@@ -29,10 +29,10 @@ namespace {
|
||||
|
||||
void run(TFT_eSPI& tft) {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 8);
|
||||
tft.println(I18n::t(StringId::LOGFILES_TITLE));
|
||||
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
|
||||
tft.setTextColor(TFT_DARKGREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 30);
|
||||
tft.print(I18n::t(StringId::LOADING));
|
||||
|
||||
@@ -42,12 +42,12 @@ void run(TFT_eSPI& tft) {
|
||||
Rect backBtn = {10, (int16_t)(Config::SCREEN_HEIGHT - 50), (int16_t)(Config::SCREEN_WIDTH - 20), 40};
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 8);
|
||||
tft.println(I18n::t(StringId::LOGFILES_TITLE));
|
||||
|
||||
if (count == 0) {
|
||||
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
|
||||
tft.setTextColor(TFT_DARKGREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 40);
|
||||
tft.println(I18n::t(StringId::LOGFILES_EMPTY));
|
||||
} else {
|
||||
@@ -55,7 +55,7 @@ void run(TFT_eSPI& tft) {
|
||||
int16_t y = 30;
|
||||
|
||||
if (count > VISIBLE_ROWS) {
|
||||
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
|
||||
tft.setTextColor(TFT_DARKGREEN, TFT_BLACK);
|
||||
tft.setCursor(10, y);
|
||||
tft.print(String(I18n::t(StringId::LOGFILES_SHOWING_PREFIX)) + VISIBLE_ROWS +
|
||||
I18n::t(StringId::LOGFILES_OF) + count + I18n::t(StringId::LOGFILES_DAYS_SUFFIX));
|
||||
@@ -66,7 +66,7 @@ void run(TFT_eSPI& tft) {
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, y);
|
||||
tft.print(days[i].date);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(110, y);
|
||||
tft.print(String(days[i].count) + I18n::t(StringId::LOGFILES_AIRCRAFT_SUFFIX));
|
||||
y += 20;
|
||||
|
||||
68
src/main.cpp
68
src/main.cpp
@@ -29,6 +29,7 @@
|
||||
#include "screenshot.h"
|
||||
#include "i18n.h"
|
||||
#include "first_run_language_screen.h"
|
||||
#include "ui_font.h"
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
@@ -59,35 +60,70 @@ struct Rect {
|
||||
}
|
||||
};
|
||||
|
||||
Rect menuBtn = {Config::SCREEN_WIDTH - 60, 3, 54, 22};
|
||||
Rect menuBtn = {Config::SCREEN_WIDTH - 90, 3, 54, 22};
|
||||
Rect camBtn = {(int16_t)(menuBtn.x - 46), 3, 42, 22};
|
||||
|
||||
void drawMenuButton() {
|
||||
tft.fillRoundRect(menuBtn.x, menuBtn.y, menuBtn.w, menuBtn.h, 4, TFT_NAVY);
|
||||
tft.drawRoundRect(menuBtn.x, menuBtn.y, menuBtn.w, menuBtn.h, 4, TFT_DARKGREY);
|
||||
tft.fillRoundRect(menuBtn.x, menuBtn.y, menuBtn.w, menuBtn.h, 4, TFT_BLACK);
|
||||
tft.drawRoundRect(menuBtn.x, menuBtn.y, menuBtn.w, menuBtn.h, 4, TFT_GREEN);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, TFT_NAVY);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.drawString("Menu", menuBtn.x + menuBtn.w / 2, menuBtn.y + menuBtn.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
|
||||
void drawCamButton() {
|
||||
tft.fillRoundRect(camBtn.x, camBtn.y, camBtn.w, camBtn.h, 4, TFT_NAVY);
|
||||
tft.drawRoundRect(camBtn.x, camBtn.y, camBtn.w, camBtn.h, 4, TFT_DARKGREY);
|
||||
tft.fillRoundRect(camBtn.x, camBtn.y, camBtn.w, camBtn.h, 4, TFT_BLACK);
|
||||
tft.drawRoundRect(camBtn.x, camBtn.y, camBtn.w, camBtn.h, 4, TFT_GREEN);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, TFT_NAVY);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.drawString("Cam", camBtn.x + camBtn.w / 2, camBtn.y + camBtn.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
|
||||
void drawWifiIcon(int16_t rightX, int16_t rowTop, int16_t rowH, int8_t rssi) {
|
||||
uint8_t level;
|
||||
if (rssi >= -55) level = 4;
|
||||
else if (rssi >= -65) level = 3;
|
||||
else if (rssi >= -75) level = 2;
|
||||
else if (rssi >= -85) level = 1;
|
||||
else level = 0;
|
||||
|
||||
constexpr uint8_t BAR_W = 3;
|
||||
constexpr uint8_t BAR_GAP = 2;
|
||||
constexpr uint8_t BAR_COUNT = 4;
|
||||
int16_t baseline = rowTop + rowH - 1;
|
||||
int16_t x = rightX - BAR_COUNT * (BAR_W + BAR_GAP);
|
||||
|
||||
for (uint8_t i = 0; i < BAR_COUNT; i++) {
|
||||
int16_t barH = 3 + i * 2;
|
||||
uint16_t color = (i < level) ? TFT_GREEN : TFT_DARKGREY;
|
||||
tft.fillRect(x, baseline - barH, BAR_W, barH, color);
|
||||
x += BAR_W + BAR_GAP;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr int16_t WIFI_ICON_W = 22;
|
||||
constexpr int16_t WIFI_ICON_H = 14;
|
||||
|
||||
void updateWifiIcon() {
|
||||
int16_t iconX = Config::SCREEN_WIDTH - WIFI_ICON_W - 2;
|
||||
int16_t iconY = 2;
|
||||
tft.fillRect(iconX, iconY, WIFI_ICON_W, WIFI_ICON_H, TFT_BLACK);
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
drawWifiIcon(Config::SCREEN_WIDTH - 4, iconY, WIFI_ICON_H, WiFi.RSSI());
|
||||
}
|
||||
}
|
||||
|
||||
void drawHeader() {
|
||||
tft.fillRect(0, 0, Config::SCREEN_WIDTH, CONTENT_TOP, TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(6, 10);
|
||||
tft.println("Eiswolfs Flightradar");
|
||||
tft.println("Eiswolfs FR");
|
||||
drawCamButton();
|
||||
drawMenuButton();
|
||||
updateWifiIcon();
|
||||
}
|
||||
|
||||
void updateStatusLine() {
|
||||
@@ -106,13 +142,7 @@ void updateStatusLine() {
|
||||
tft.print(timeBuf);
|
||||
}
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
char rssiBuf[14];
|
||||
snprintf(rssiBuf, sizeof(rssiBuf), "WiFi %ddBm", WiFi.RSSI());
|
||||
tft.setTextDatum(TR_DATUM);
|
||||
tft.drawString(rssiBuf, Config::SCREEN_WIDTH - 4, HEADER_TITLE_H + 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
updateWifiIcon();
|
||||
}
|
||||
|
||||
void takeScreenshotWithFeedback() {
|
||||
@@ -183,6 +213,7 @@ void setup() {
|
||||
|
||||
tft.init();
|
||||
tft.setRotation(0);
|
||||
tft.setFreeFont(&UiFont11pt);
|
||||
tft.invertDisplay(true);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
@@ -200,10 +231,6 @@ void setup() {
|
||||
}
|
||||
SdStorage::seedDefaultDataFiles();
|
||||
|
||||
// "Allererster Start" erkennen: config.txt existiert noch nicht (wird
|
||||
// erst beim ersten SettingsStore::save()-Aufruf angelegt). Muss VOR
|
||||
// SettingsStore::load() geprueft werden, da load() die Datei nicht
|
||||
// erzeugt, nur liest.
|
||||
bool isFirstRun = !SD.exists(Config::SD_SETTINGS_FILE);
|
||||
|
||||
SettingsStore::load();
|
||||
@@ -239,9 +266,6 @@ void setup() {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Sprachauswahl: NUR beim allerersten Start, direkt nach Touch-
|
||||
// Kalibrierung und WLAN-Ersteinrichtung, bevor irgendwelche weiteren
|
||||
// Texte in (falscher) Standardsprache gezeigt werden. ---
|
||||
if (isFirstRun) {
|
||||
FirstRunLanguageScreen::run(tft);
|
||||
SplashScreen::begin(tft);
|
||||
|
||||
@@ -23,20 +23,33 @@ namespace {
|
||||
}
|
||||
};
|
||||
|
||||
constexpr int16_t ROW_H = 26;
|
||||
constexpr int16_t ROW_GAP = 3;
|
||||
constexpr int16_t ROW_START_Y = 20;
|
||||
constexpr int16_t ROW_H = 24;
|
||||
constexpr int16_t ROW_GAP = 2;
|
||||
constexpr int16_t ROW_START_Y = 18;
|
||||
|
||||
Rect rowRect(uint8_t index) {
|
||||
return {10, (int16_t)(ROW_START_Y + index * (ROW_H + ROW_GAP)),
|
||||
(int16_t)(Config::SCREEN_WIDTH - 20), ROW_H};
|
||||
}
|
||||
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, uint16_t bg = TFT_NAVY) {
|
||||
constexpr int16_t CAT_ROW_H = 50;
|
||||
constexpr int16_t CAT_ROW_GAP = 10;
|
||||
constexpr int16_t CAT_START_Y = 30;
|
||||
|
||||
Rect catRowRect(uint8_t index) {
|
||||
return {10, (int16_t)(CAT_START_Y + index * (CAT_ROW_H + CAT_ROW_GAP)),
|
||||
(int16_t)(Config::SCREEN_WIDTH - 20), CAT_ROW_H};
|
||||
}
|
||||
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label,
|
||||
bool active = false, bool danger = false) {
|
||||
uint16_t accent = danger ? TFT_RED : TFT_GREEN;
|
||||
uint16_t bg = active ? accent : TFT_BLACK;
|
||||
uint16_t fg = active ? TFT_BLACK : accent;
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, bg);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_DARKGREY);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, accent);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, bg);
|
||||
tft.setTextColor(fg, bg);
|
||||
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
@@ -57,28 +70,113 @@ namespace {
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
delay(1200);
|
||||
}
|
||||
|
||||
enum class Page { Main, Region, Wifi, System, Flight };
|
||||
}
|
||||
|
||||
void run(TFT_eSPI& tft) {
|
||||
uint8_t page = 0;
|
||||
Page page = Page::Main;
|
||||
bool done = false;
|
||||
|
||||
while (!done) {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setCursor(10, 2);
|
||||
tft.println(page == 0 ? I18n::t(StringId::MENU_SETTINGS) : I18n::t(StringId::MENU_SETTINGS_PAGE2));
|
||||
|
||||
if (page == 0) {
|
||||
Rect calibBtn = rowRect(0);
|
||||
Rect invertBtn = rowRect(1);
|
||||
Rect wifiBtn = rowRect(2);
|
||||
Rect locationBtn = rowRect(3);
|
||||
Rect timeoutBtn = rowRect(4);
|
||||
Rect statsBtn = rowRect(5);
|
||||
Rect logFilesBtn = rowRect(6);
|
||||
Rect moreBtn = rowRect(7);
|
||||
Rect backBtn = rowRect(8);
|
||||
if (page == Page::Main) {
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 6);
|
||||
tft.println(I18n::t(StringId::MENU_SETTINGS));
|
||||
|
||||
Rect regionBtn = catRowRect(0);
|
||||
Rect wifiBtn = catRowRect(1);
|
||||
Rect systemBtn = catRowRect(2);
|
||||
Rect flightBtn = catRowRect(3);
|
||||
Rect backBtn = catRowRect(4);
|
||||
|
||||
drawButton(tft, regionBtn, I18n::t(StringId::MENU_CATEGORY_REGION));
|
||||
drawButton(tft, wifiBtn, I18n::t(StringId::MENU_CATEGORY_WIFI));
|
||||
drawButton(tft, systemBtn, I18n::t(StringId::MENU_CATEGORY_SYSTEM));
|
||||
drawButton(tft, flightBtn, I18n::t(StringId::MENU_CATEGORY_FLIGHT));
|
||||
drawButton(tft, backBtn, I18n::t(StringId::BACK));
|
||||
|
||||
TouchInput::Point tap;
|
||||
while (true) {
|
||||
if (TouchInput::wasTapped(tap)) break;
|
||||
delay(20);
|
||||
}
|
||||
|
||||
if (regionBtn.contains(tap.x, tap.y)) {
|
||||
page = Page::Region;
|
||||
} else if (wifiBtn.contains(tap.x, tap.y)) {
|
||||
page = Page::Wifi;
|
||||
} else if (systemBtn.contains(tap.x, tap.y)) {
|
||||
page = Page::System;
|
||||
} else if (flightBtn.contains(tap.x, tap.y)) {
|
||||
page = Page::Flight;
|
||||
} else if (backBtn.contains(tap.x, tap.y)) {
|
||||
done = true;
|
||||
}
|
||||
|
||||
} else if (page == Page::Region) {
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 2);
|
||||
tft.println(I18n::t(StringId::MENU_CATEGORY_REGION));
|
||||
|
||||
Rect languageBtn = rowRect(0);
|
||||
Rect unitsBtn = rowRect(1);
|
||||
Rect backBtn = rowRect(2);
|
||||
|
||||
drawButton(tft, languageBtn, String(I18n::t(StringId::MENU_LANGUAGE)) + ": " + I18n::languageName(SettingsStore::language()));
|
||||
drawButton(tft, unitsBtn, I18n::t(StringId::MENU_UNITS));
|
||||
drawButton(tft, backBtn, I18n::t(StringId::BACK_ARROW));
|
||||
|
||||
TouchInput::Point tap;
|
||||
while (true) {
|
||||
if (TouchInput::wasTapped(tap)) break;
|
||||
delay(20);
|
||||
}
|
||||
|
||||
if (languageBtn.contains(tap.x, tap.y)) {
|
||||
LanguageScreen::run(tft);
|
||||
} else if (unitsBtn.contains(tap.x, tap.y)) {
|
||||
UnitsScreen::run(tft);
|
||||
} else if (backBtn.contains(tap.x, tap.y)) {
|
||||
page = Page::Main;
|
||||
}
|
||||
|
||||
} else if (page == Page::Wifi) {
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 2);
|
||||
tft.println(I18n::t(StringId::MENU_CATEGORY_WIFI));
|
||||
|
||||
Rect wifiManageBtn = rowRect(0);
|
||||
Rect backBtn = rowRect(1);
|
||||
|
||||
drawButton(tft, wifiManageBtn, I18n::t(StringId::MENU_MANAGE_WIFI));
|
||||
drawButton(tft, backBtn, I18n::t(StringId::BACK_ARROW));
|
||||
|
||||
TouchInput::Point tap;
|
||||
while (true) {
|
||||
if (TouchInput::wasTapped(tap)) break;
|
||||
delay(20);
|
||||
}
|
||||
|
||||
if (wifiManageBtn.contains(tap.x, tap.y)) {
|
||||
WifiManageScreen::run(tft);
|
||||
} else if (backBtn.contains(tap.x, tap.y)) {
|
||||
page = Page::Main;
|
||||
}
|
||||
|
||||
} else if (page == Page::System) {
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 2);
|
||||
tft.println(I18n::t(StringId::MENU_CATEGORY_SYSTEM));
|
||||
|
||||
Rect calibBtn = rowRect(0);
|
||||
Rect invertBtn = rowRect(1);
|
||||
Rect timeoutBtn = rowRect(2);
|
||||
Rect backupBtn = rowRect(3);
|
||||
Rect restoreBtn = rowRect(4);
|
||||
Rect backBtn = rowRect(5);
|
||||
|
||||
drawButton(tft, calibBtn, I18n::t(StringId::MENU_CALIBRATE));
|
||||
|
||||
@@ -87,13 +185,10 @@ void run(TFT_eSPI& tft) {
|
||||
: I18n::t(StringId::MENU_DISPLAY_NORMAL);
|
||||
drawButton(tft, invertBtn, invertLabel);
|
||||
|
||||
drawButton(tft, wifiBtn, I18n::t(StringId::MENU_MANAGE_WIFI));
|
||||
drawButton(tft, locationBtn, I18n::t(StringId::MENU_LOCATION_PRESETS));
|
||||
drawButton(tft, timeoutBtn, screenTimeoutLabel(SettingsStore::screenTimeoutMinutes()));
|
||||
drawButton(tft, statsBtn, I18n::t(StringId::MENU_STATISTICS));
|
||||
drawButton(tft, logFilesBtn, I18n::t(StringId::MENU_LOGBOOK_FILES));
|
||||
drawButton(tft, moreBtn, I18n::t(StringId::MENU_MORE_SETTINGS));
|
||||
drawButton(tft, backBtn, I18n::t(StringId::BACK));
|
||||
drawButton(tft, backupBtn, I18n::t(StringId::MENU_BACKUP));
|
||||
drawButton(tft, restoreBtn, I18n::t(StringId::MENU_RESTORE));
|
||||
drawButton(tft, backBtn, I18n::t(StringId::BACK_ARROW));
|
||||
|
||||
TouchInput::Point tap;
|
||||
while (true) {
|
||||
@@ -107,89 +202,10 @@ void run(TFT_eSPI& tft) {
|
||||
bool newState = !SettingsStore::displayInverted();
|
||||
SettingsStore::setDisplayInverted(newState);
|
||||
tft.invertDisplay(newState);
|
||||
} else if (wifiBtn.contains(tap.x, tap.y)) {
|
||||
WifiManageScreen::run(tft);
|
||||
} else if (locationBtn.contains(tap.x, tap.y)) {
|
||||
LocationPresetsScreen::run(tft);
|
||||
} else if (timeoutBtn.contains(tap.x, tap.y)) {
|
||||
uint8_t current = SettingsStore::screenTimeoutMinutes();
|
||||
uint8_t next = (current >= 10) ? 0 : (current + 1);
|
||||
SettingsStore::setScreenTimeoutMinutes(next);
|
||||
} else if (statsBtn.contains(tap.x, tap.y)) {
|
||||
StatsScreen::run(tft);
|
||||
} else if (logFilesBtn.contains(tap.x, tap.y)) {
|
||||
LogbookFilesScreen::run(tft);
|
||||
} else if (moreBtn.contains(tap.x, tap.y)) {
|
||||
page = 1;
|
||||
} else if (backBtn.contains(tap.x, tap.y)) {
|
||||
done = true;
|
||||
}
|
||||
} else if (page == 1) {
|
||||
Rect emergencyBtn = rowRect(0);
|
||||
Rect proximityBtn = rowRect(1);
|
||||
Rect heartbeatBtn = rowRect(2);
|
||||
Rect logbookBtn = rowRect(3);
|
||||
Rect groundBtn = rowRect(4);
|
||||
Rect airlineBtn = rowRect(5);
|
||||
Rect moreBtn = rowRect(6);
|
||||
Rect backBtn = rowRect(7);
|
||||
|
||||
drawButton(tft, emergencyBtn, I18n::t(StringId::MENU_EMERGENCY_ALERT) + onOff(SettingsStore::emergencyAlertEnabled()));
|
||||
drawButton(tft, proximityBtn, I18n::t(StringId::MENU_PROXIMITY_LED) + onOff(SettingsStore::proximityAlertEnabled()));
|
||||
drawButton(tft, heartbeatBtn, I18n::t(StringId::MENU_LED_HEARTBEAT) + onOff(SettingsStore::ledHeartbeatEnabled()));
|
||||
drawButton(tft, logbookBtn, I18n::t(StringId::MENU_FLIGHT_LOGBOOK) + onOff(SettingsStore::flightLogbookEnabled()));
|
||||
drawButton(tft, groundBtn, I18n::t(StringId::MENU_HIDE_GROUND) + onOff(SettingsStore::hideGroundVehicles()));
|
||||
drawButton(tft, airlineBtn, I18n::t(StringId::MENU_AIRLINE_FILTER));
|
||||
drawButton(tft, moreBtn, I18n::t(StringId::MENU_MORE_SETTINGS));
|
||||
drawButton(tft, backBtn, I18n::t(StringId::BACK_ARROW));
|
||||
|
||||
TouchInput::Point tap;
|
||||
while (true) {
|
||||
if (TouchInput::wasTapped(tap)) break;
|
||||
delay(20);
|
||||
}
|
||||
|
||||
if (emergencyBtn.contains(tap.x, tap.y)) {
|
||||
SettingsStore::setEmergencyAlertEnabled(!SettingsStore::emergencyAlertEnabled());
|
||||
} else if (proximityBtn.contains(tap.x, tap.y)) {
|
||||
SettingsStore::setProximityAlertEnabled(!SettingsStore::proximityAlertEnabled());
|
||||
} else if (heartbeatBtn.contains(tap.x, tap.y)) {
|
||||
SettingsStore::setLedHeartbeatEnabled(!SettingsStore::ledHeartbeatEnabled());
|
||||
} else if (logbookBtn.contains(tap.x, tap.y)) {
|
||||
SettingsStore::setFlightLogbookEnabled(!SettingsStore::flightLogbookEnabled());
|
||||
} else if (groundBtn.contains(tap.x, tap.y)) {
|
||||
SettingsStore::setHideGroundVehicles(!SettingsStore::hideGroundVehicles());
|
||||
} else if (airlineBtn.contains(tap.x, tap.y)) {
|
||||
AirlineFilterScreen::run(tft);
|
||||
} else if (moreBtn.contains(tap.x, tap.y)) {
|
||||
page = 2;
|
||||
} else if (backBtn.contains(tap.x, tap.y)) {
|
||||
page = 0;
|
||||
}
|
||||
} else {
|
||||
Rect languageBtn = rowRect(0);
|
||||
Rect unitsBtn = rowRect(1);
|
||||
Rect backupBtn = rowRect(2);
|
||||
Rect restoreBtn = rowRect(3);
|
||||
Rect backBtn = rowRect(4);
|
||||
|
||||
drawButton(tft, languageBtn, String(I18n::t(StringId::MENU_LANGUAGE)) + ": " + I18n::languageName(SettingsStore::language()));
|
||||
drawButton(tft, unitsBtn, I18n::t(StringId::MENU_UNITS));
|
||||
drawButton(tft, backupBtn, I18n::t(StringId::MENU_BACKUP));
|
||||
drawButton(tft, restoreBtn, I18n::t(StringId::MENU_RESTORE),
|
||||
SettingsBackup::hasBackup() ? TFT_NAVY : TFT_DARKGREY);
|
||||
drawButton(tft, backBtn, I18n::t(StringId::BACK_ARROW));
|
||||
|
||||
TouchInput::Point tap;
|
||||
while (true) {
|
||||
if (TouchInput::wasTapped(tap)) break;
|
||||
delay(20);
|
||||
}
|
||||
|
||||
if (languageBtn.contains(tap.x, tap.y)) {
|
||||
LanguageScreen::run(tft);
|
||||
} else if (unitsBtn.contains(tap.x, tap.y)) {
|
||||
UnitsScreen::run(tft);
|
||||
} else if (backupBtn.contains(tap.x, tap.y)) {
|
||||
bool ok = SettingsBackup::backup();
|
||||
showBriefMessage(tft, I18n::t(ok ? StringId::MENU_BACKUP_SAVED : StringId::MENU_BACKUP_FAILED),
|
||||
@@ -201,7 +217,62 @@ void run(TFT_eSPI& tft) {
|
||||
ok ? TFT_GREEN : TFT_RED);
|
||||
}
|
||||
} else if (backBtn.contains(tap.x, tap.y)) {
|
||||
page = 1;
|
||||
page = Page::Main;
|
||||
}
|
||||
|
||||
} else { // Page::Flight
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 2);
|
||||
tft.println(I18n::t(StringId::MENU_CATEGORY_FLIGHT));
|
||||
|
||||
Rect statsBtn = rowRect(0);
|
||||
Rect logFilesBtn = rowRect(1);
|
||||
Rect logbookBtn = rowRect(2);
|
||||
Rect heartbeatBtn = rowRect(3);
|
||||
Rect proximityBtn = rowRect(4);
|
||||
Rect emergencyBtn = rowRect(5);
|
||||
Rect locationBtn = rowRect(6);
|
||||
Rect airlineBtn = rowRect(7);
|
||||
Rect groundBtn = rowRect(8);
|
||||
Rect backBtn = rowRect(9);
|
||||
|
||||
drawButton(tft, statsBtn, I18n::t(StringId::MENU_STATISTICS));
|
||||
drawButton(tft, logFilesBtn, I18n::t(StringId::MENU_LOGBOOK_FILES));
|
||||
drawButton(tft, logbookBtn, I18n::t(StringId::MENU_FLIGHT_LOGBOOK) + onOff(SettingsStore::flightLogbookEnabled()));
|
||||
drawButton(tft, heartbeatBtn, I18n::t(StringId::MENU_LED_HEARTBEAT) + onOff(SettingsStore::ledHeartbeatEnabled()));
|
||||
drawButton(tft, proximityBtn, I18n::t(StringId::MENU_PROXIMITY_LED) + onOff(SettingsStore::proximityAlertEnabled()));
|
||||
drawButton(tft, emergencyBtn, I18n::t(StringId::MENU_EMERGENCY_ALERT) + onOff(SettingsStore::emergencyAlertEnabled()));
|
||||
drawButton(tft, locationBtn, I18n::t(StringId::MENU_LOCATION_PRESETS));
|
||||
drawButton(tft, airlineBtn, I18n::t(StringId::MENU_AIRLINE_FILTER));
|
||||
drawButton(tft, groundBtn, I18n::t(StringId::MENU_HIDE_GROUND) + onOff(SettingsStore::hideGroundVehicles()));
|
||||
drawButton(tft, backBtn, I18n::t(StringId::BACK_ARROW));
|
||||
|
||||
TouchInput::Point tap;
|
||||
while (true) {
|
||||
if (TouchInput::wasTapped(tap)) break;
|
||||
delay(20);
|
||||
}
|
||||
|
||||
if (statsBtn.contains(tap.x, tap.y)) {
|
||||
StatsScreen::run(tft);
|
||||
} else if (logFilesBtn.contains(tap.x, tap.y)) {
|
||||
LogbookFilesScreen::run(tft);
|
||||
} else if (logbookBtn.contains(tap.x, tap.y)) {
|
||||
SettingsStore::setFlightLogbookEnabled(!SettingsStore::flightLogbookEnabled());
|
||||
} else if (heartbeatBtn.contains(tap.x, tap.y)) {
|
||||
SettingsStore::setLedHeartbeatEnabled(!SettingsStore::ledHeartbeatEnabled());
|
||||
} else if (proximityBtn.contains(tap.x, tap.y)) {
|
||||
SettingsStore::setProximityAlertEnabled(!SettingsStore::proximityAlertEnabled());
|
||||
} else if (emergencyBtn.contains(tap.x, tap.y)) {
|
||||
SettingsStore::setEmergencyAlertEnabled(!SettingsStore::emergencyAlertEnabled());
|
||||
} else if (locationBtn.contains(tap.x, tap.y)) {
|
||||
LocationPresetsScreen::run(tft);
|
||||
} else if (airlineBtn.contains(tap.x, tap.y)) {
|
||||
AirlineFilterScreen::run(tft);
|
||||
} else if (groundBtn.contains(tap.x, tap.y)) {
|
||||
SettingsStore::setHideGroundVehicles(!SettingsStore::hideGroundVehicles());
|
||||
} else if (backBtn.contains(tap.x, tap.y)) {
|
||||
page = Page::Main;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace {
|
||||
int16_t infoTop;
|
||||
};
|
||||
|
||||
constexpr int16_t INFO_BAR_H = 50;
|
||||
constexpr int16_t INFO_BAR_H = 64;
|
||||
|
||||
Layout computeLayout(int16_t top) {
|
||||
Layout L;
|
||||
@@ -45,7 +45,7 @@ namespace {
|
||||
return L;
|
||||
}
|
||||
|
||||
constexpr int16_t DETAIL_PANEL_H = 190;
|
||||
constexpr int16_t DETAIL_PANEL_H = 264;
|
||||
|
||||
struct HitPoint {
|
||||
int16_t x, y;
|
||||
@@ -177,10 +177,10 @@ namespace {
|
||||
}
|
||||
|
||||
void drawButton(TFT_eSPI& gfx, const Rect& r, const String& label) {
|
||||
gfx.fillRoundRect(r.x, r.y, r.w, r.h, 4, TFT_NAVY);
|
||||
gfx.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_DARKGREY);
|
||||
gfx.fillRoundRect(r.x, r.y, r.w, r.h, 4, TFT_BLACK);
|
||||
gfx.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_GREEN);
|
||||
gfx.setTextDatum(MC_DATUM);
|
||||
gfx.setTextColor(TFT_WHITE, TFT_NAVY);
|
||||
gfx.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
gfx.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||
gfx.setTextDatum(TL_DATUM);
|
||||
}
|
||||
@@ -210,7 +210,7 @@ namespace {
|
||||
gfx.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
int16_t x0 = i * segW + 6;
|
||||
gfx.fillCircle(x0, y + 4, 3, items[i].color);
|
||||
gfx.fillCircle(x0, y - 5, 3, items[i].color);
|
||||
gfx.setCursor(x0 + 7, y);
|
||||
gfx.print(items[i].label);
|
||||
}
|
||||
@@ -279,8 +279,8 @@ namespace {
|
||||
void updateLine(TFT_eSPI& gfx, int16_t y, int16_t h, int16_t maxWidth,
|
||||
uint16_t fg, String& cached, const String& newText, bool forceFull) {
|
||||
if (!forceFull && cached == newText) return;
|
||||
gfx.fillRect(0, y - 2, Config::SCREEN_WIDTH, h, TFT_NAVY);
|
||||
gfx.setTextColor(fg, TFT_NAVY);
|
||||
gfx.fillRect(0, y - 14, Config::SCREEN_WIDTH, h, TFT_BLACK);
|
||||
gfx.setTextColor(fg, TFT_BLACK);
|
||||
printLineTruncated(gfx, 8, y, maxWidth, newText);
|
||||
cached = newText;
|
||||
}
|
||||
@@ -291,54 +291,55 @@ namespace {
|
||||
|
||||
int16_t panelTop = Config::SCREEN_HEIGHT - DETAIL_PANEL_H;
|
||||
constexpr int16_t textMaxWidth = Config::SCREEN_WIDTH - 16;
|
||||
constexpr int16_t LINE_H = 22;
|
||||
|
||||
bool forceFull = !lastPanel.valid || strcmp(lastPanel.hex, a.hex) != 0;
|
||||
if (forceFull) {
|
||||
gfx.fillRect(0, panelTop, Config::SCREEN_WIDTH, DETAIL_PANEL_H, TFT_NAVY);
|
||||
gfx.drawRect(0, panelTop, Config::SCREEN_WIDTH, DETAIL_PANEL_H, TFT_DARKGREY);
|
||||
gfx.fillRect(0, panelTop, Config::SCREEN_WIDTH, DETAIL_PANEL_H, TFT_BLACK);
|
||||
gfx.drawRect(0, panelTop, Config::SCREEN_WIDTH, DETAIL_PANEL_H, TFT_GREEN);
|
||||
lastPanel = PanelState{};
|
||||
strncpy(lastPanel.hex, a.hex, sizeof(lastPanel.hex) - 1);
|
||||
}
|
||||
|
||||
int16_t y = panelTop + 6;
|
||||
int16_t y = panelTop + 26;
|
||||
|
||||
{
|
||||
String txt = a.callsign[0] ? a.callsign : a.hex;
|
||||
if (forceFull || lastPanel.callsignText != txt) {
|
||||
gfx.fillRect(0, y - 2, Config::SCREEN_WIDTH, 20, TFT_NAVY);
|
||||
gfx.setTextColor(TFT_WHITE, TFT_NAVY);
|
||||
gfx.fillRect(0, y - 22, Config::SCREEN_WIDTH, 28, TFT_BLACK);
|
||||
gfx.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
gfx.setTextSize(2);
|
||||
printLineTruncated(gfx, 8, y, textMaxWidth, txt);
|
||||
gfx.setTextSize(1);
|
||||
lastPanel.callsignText = txt;
|
||||
}
|
||||
}
|
||||
y += 22;
|
||||
y += 30;
|
||||
|
||||
updateLine(gfx, y, 15, textMaxWidth, TFT_GREEN, lastPanel.airlineText,
|
||||
updateLine(gfx, y, LINE_H, textMaxWidth, TFT_GREEN, lastPanel.airlineText,
|
||||
String(a.airlineName), forceFull);
|
||||
y += 15;
|
||||
y += LINE_H;
|
||||
|
||||
String modelLine = details.loading
|
||||
? String(I18n::t(StringId::DETAIL_MODEL)) + I18n::t(StringId::DETAIL_LOADING_DOTS)
|
||||
: String(I18n::t(StringId::DETAIL_MODEL)) + (details.model[0] ? details.model : I18n::t(StringId::DETAIL_UNKNOWN));
|
||||
updateLine(gfx, y, 15, textMaxWidth, TFT_WHITE, lastPanel.modelText, modelLine, forceFull);
|
||||
y += 15;
|
||||
updateLine(gfx, y, LINE_H, textMaxWidth, TFT_GREEN, lastPanel.modelText, modelLine, forceFull);
|
||||
y += LINE_H;
|
||||
|
||||
String typeLine = String(I18n::t(StringId::DETAIL_TYPE)) + (a.typeCode[0] ? a.typeCode : I18n::t(StringId::DETAIL_UNKNOWN));
|
||||
updateLine(gfx, y, 15, textMaxWidth, TFT_WHITE, lastPanel.typeText, typeLine, forceFull);
|
||||
y += 15;
|
||||
updateLine(gfx, y, LINE_H, textMaxWidth, TFT_GREEN, lastPanel.typeText, typeLine, forceFull);
|
||||
y += LINE_H;
|
||||
|
||||
char buf[48];
|
||||
snprintf(buf, sizeof(buf), "%s%.0fm / %.0fft", I18n::t(StringId::DETAIL_ALT),
|
||||
Units::feetToMeters((float)a.altBaroFt), (float)a.altBaroFt);
|
||||
updateLine(gfx, y, 15, textMaxWidth, TFT_WHITE, lastPanel.altText, String(buf), forceFull);
|
||||
y += 15;
|
||||
updateLine(gfx, y, LINE_H, textMaxWidth, TFT_GREEN, lastPanel.altText, String(buf), forceFull);
|
||||
y += LINE_H;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s%.0fkm/h / %.0fkt", I18n::t(StringId::DETAIL_SPEED),
|
||||
Units::ktToKmh(a.groundSpeedKt), a.groundSpeedKt);
|
||||
updateLine(gfx, y, 15, textMaxWidth, TFT_WHITE, lastPanel.speedText, String(buf), forceFull);
|
||||
y += 15;
|
||||
updateLine(gfx, y, LINE_H, textMaxWidth, TFT_GREEN, lastPanel.speedText, String(buf), forceFull);
|
||||
y += LINE_H;
|
||||
|
||||
String climbLine;
|
||||
if (a.vertRateFtMin > 100) {
|
||||
@@ -350,32 +351,66 @@ namespace {
|
||||
} else {
|
||||
climbLine = I18n::t(StringId::DETAIL_LEVEL);
|
||||
}
|
||||
updateLine(gfx, y, 15, textMaxWidth, TFT_WHITE, lastPanel.climbText, climbLine, forceFull);
|
||||
y += 15;
|
||||
updateLine(gfx, y, LINE_H, textMaxWidth, TFT_GREEN, lastPanel.climbText, climbLine, forceFull);
|
||||
y += LINE_H;
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s%.0fkm / %.0fnm %s%.0f", I18n::t(StringId::DETAIL_DIST),
|
||||
a.distanceKm, Units::kmToNm(a.distanceKm), I18n::t(StringId::DETAIL_HDG), a.headingDeg);
|
||||
updateLine(gfx, y, 15, textMaxWidth, TFT_WHITE, lastPanel.distHeadingText, String(buf), forceFull);
|
||||
y += 15;
|
||||
updateLine(gfx, y, LINE_H, textMaxWidth, TFT_GREEN, lastPanel.distHeadingText, String(buf), forceFull);
|
||||
y += LINE_H;
|
||||
|
||||
String squawkLine = String(I18n::t(StringId::DETAIL_SQUAWK)) + (a.squawk[0] ? a.squawk : I18n::t(StringId::DETAIL_UNKNOWN));
|
||||
updateLine(gfx, y, 15, textMaxWidth, TFT_WHITE, lastPanel.squawkText, squawkLine, forceFull);
|
||||
y += 15;
|
||||
updateLine(gfx, y, LINE_H, textMaxWidth, TFT_GREEN, lastPanel.squawkText, squawkLine, forceFull);
|
||||
y += LINE_H;
|
||||
|
||||
String seatsLine = a.estSeats > 0
|
||||
? String(I18n::t(StringId::DETAIL_SEATS_EST)) + a.estSeats
|
||||
: String(I18n::t(StringId::DETAIL_SEATS_UNKNOWN));
|
||||
updateLine(gfx, y, 15, textMaxWidth, TFT_WHITE, lastPanel.seatsText, seatsLine, forceFull);
|
||||
y += 18;
|
||||
updateLine(gfx, y, LINE_H, textMaxWidth, TFT_GREEN, lastPanel.seatsText, seatsLine, forceFull);
|
||||
y += 22;
|
||||
|
||||
if (forceFull) {
|
||||
gfx.setTextColor(TFT_DARKGREY, TFT_NAVY);
|
||||
gfx.setTextColor(TFT_DARKGREEN, TFT_BLACK);
|
||||
gfx.setCursor(8, y);
|
||||
gfx.print(I18n::t(StringId::DETAIL_TAP_CLOSE));
|
||||
}
|
||||
|
||||
lastPanel.valid = true;
|
||||
}
|
||||
|
||||
constexpr uint8_t STAR_COUNT = 28;
|
||||
struct Star {
|
||||
int16_t x, y;
|
||||
uint8_t phase;
|
||||
uint8_t speed;
|
||||
};
|
||||
Star stars[STAR_COUNT];
|
||||
bool starsInitialized = false;
|
||||
|
||||
void initStarsIfNeeded() {
|
||||
if (starsInitialized) return;
|
||||
int16_t panelTop = Config::SCREEN_HEIGHT - DETAIL_PANEL_H;
|
||||
randomSeed((uint32_t)esp_random());
|
||||
for (uint8_t i = 0; i < STAR_COUNT; i++) {
|
||||
stars[i].x = 6 + random(0, Config::SCREEN_WIDTH - 12);
|
||||
stars[i].y = panelTop + 10 + random(0, DETAIL_PANEL_H - 20);
|
||||
stars[i].phase = (uint8_t)random(0, 256);
|
||||
stars[i].speed = 1 + random(0, 3);
|
||||
}
|
||||
starsInitialized = true;
|
||||
}
|
||||
|
||||
void updateDetailPanelStars(TFT_eSPI& gfx) {
|
||||
initStarsIfNeeded();
|
||||
for (uint8_t i = 0; i < STAR_COUNT; i++) {
|
||||
stars[i].phase += stars[i].speed;
|
||||
uint8_t bright = (stars[i].phase < 128)
|
||||
? (uint8_t)(stars[i].phase * 2)
|
||||
: (uint8_t)((255 - stars[i].phase) * 2);
|
||||
uint16_t color = gfx.color565(0, bright, 0);
|
||||
gfx.drawPixel(stars[i].x, stars[i].y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render(TFT_eSPI& tft, int16_t top) {
|
||||
@@ -470,12 +505,6 @@ void render(TFT_eSPI& tft, int16_t top) {
|
||||
tft.drawCircle(pt.x, pt.y, 12, TFT_RED);
|
||||
}
|
||||
|
||||
// Rufzeichen als kleines farbiges Label ueber dem Punkt
|
||||
// Transparent zeichnen (KEIN schwarzer Hintergrund-Kasten) - sonst
|
||||
// "beisst" der Label-Hintergrund ein Stueck der Ring-/Fadenkreuz-
|
||||
// Linie weg, wenn sich beides ueberschneidet. Da das Label bei jedem
|
||||
// Sweep-Tick am selben Fleck neu gezeichnet wird, sah das wie
|
||||
// Dauerflackern genau an den Beschriftungen aus.
|
||||
tft.setTextColor(color);
|
||||
tft.setTextDatum(BC_DATUM);
|
||||
const char* label = a.callsign[0] ? a.callsign : a.hex;
|
||||
@@ -506,21 +535,26 @@ void render(TFT_eSPI& tft, int16_t top) {
|
||||
int16_t infoTop = L.infoTop;
|
||||
tft.drawFastHLine(0, infoTop, Config::SCREEN_WIDTH, TFT_DARKGREY);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setCursor(8, infoTop + 6);
|
||||
tft.setCursor(8, infoTop + 20);
|
||||
tft.print(I18n::t(StringId::RADAR_TAP_FOR_DETAILS));
|
||||
|
||||
char rangeLabel[8];
|
||||
snprintf(rangeLabel, sizeof(rangeLabel), "%.0fkm", rangeKm);
|
||||
drawButton(tft, L.rangeBtn, rangeLabel);
|
||||
|
||||
drawLegend(tft, infoTop + 30);
|
||||
drawLegend(tft, infoTop + 44);
|
||||
}
|
||||
|
||||
tft.endWrite();
|
||||
}
|
||||
|
||||
void tick(TFT_eSPI& tft, int16_t top, uint32_t deltaMs) {
|
||||
if (selectedHex[0]) return;
|
||||
if (selectedHex[0]) {
|
||||
tft.startWrite();
|
||||
updateDetailPanelStars(tft);
|
||||
tft.endWrite();
|
||||
return;
|
||||
}
|
||||
|
||||
Layout L = computeLayout(top);
|
||||
float rangeKm = Config::RANGE_STEPS_KM[SettingsStore::rangeIndex()];
|
||||
|
||||
@@ -14,17 +14,18 @@ namespace {
|
||||
}
|
||||
};
|
||||
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, uint16_t bg = TFT_NAVY) {
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, bg);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_DARKGREY);
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, bool danger = false) {
|
||||
uint16_t accent = danger ? TFT_RED : TFT_GREEN;
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, TFT_BLACK);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, accent);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, bg);
|
||||
tft.setTextColor(accent, TFT_BLACK);
|
||||
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
|
||||
void drawStatRow(TFT_eSPI& tft, int16_t y, const String& label, const String& value) {
|
||||
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
|
||||
tft.setTextColor(TFT_DARKGREEN, TFT_BLACK);
|
||||
tft.setCursor(10, y);
|
||||
tft.print(label);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
@@ -39,10 +40,10 @@ namespace {
|
||||
|
||||
void run(TFT_eSPI& tft) {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 10);
|
||||
tft.println(I18n::t(StringId::STATS_TITLE));
|
||||
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
|
||||
tft.setTextColor(TFT_DARKGREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 44);
|
||||
tft.print(I18n::t(StringId::LOADING));
|
||||
|
||||
@@ -60,7 +61,7 @@ void run(TFT_eSPI& tft) {
|
||||
|
||||
auto redraw = [&]() {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 10);
|
||||
tft.println(I18n::t(StringId::STATS_TITLE));
|
||||
|
||||
@@ -84,12 +85,12 @@ void run(TFT_eSPI& tft) {
|
||||
uint32_t upM = (upSec % 3600) / 60;
|
||||
char upBuf[8];
|
||||
snprintf(upBuf, sizeof(upBuf), "%luh %lum", (unsigned long)upH, (unsigned long)upM);
|
||||
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
|
||||
tft.setTextColor(TFT_DARKGREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 210);
|
||||
tft.print(String(I18n::t(StringId::STATS_UPTIME_PREFIX)) + upBuf);
|
||||
|
||||
if (confirmPending) {
|
||||
drawButton(tft, resetBtn, I18n::t(StringId::STATS_RESET_CONFIRM), TFT_MAROON);
|
||||
drawButton(tft, resetBtn, I18n::t(StringId::STATS_RESET_CONFIRM), true);
|
||||
} else {
|
||||
drawButton(tft, resetBtn, I18n::t(StringId::STATS_RESET_BTN));
|
||||
}
|
||||
|
||||
461
src/ui_font.h
Normal file
461
src/ui_font.h
Normal file
@@ -0,0 +1,461 @@
|
||||
#pragma once
|
||||
// Automatisch generierter Font (DejaVu Sans Mono, 11px) fuer TFT_eSPI GFXFF.
|
||||
// Deckt Basis-ASCII + Umlaute/Akzente fuer DE/TR/FR/ES/IT ab (U+0020-U+015F).
|
||||
// NICHT von Hand bearbeiten - siehe Kommentar in i18n.h fuer den Generator-Hinweis.
|
||||
#include <pgmspace.h>
|
||||
|
||||
const uint8_t UiFont11ptBitmaps[] PROGMEM = {
|
||||
0x00, 0xFD, 0xB6, 0x80, 0x14, 0x49, 0xF9, 0x42, 0x9F, 0x92, 0x28, 0x23, 0xE9, 0x47, 0x14, 0xBE,
|
||||
0x21, 0x00, 0xE2, 0x8E, 0x46, 0x23, 0x71, 0x47, 0x71, 0x04, 0x18, 0xB6, 0x58, 0x9F, 0xE0, 0x6A,
|
||||
0xAA, 0x90, 0xA5, 0x55, 0xA0, 0x25, 0x5C, 0xEA, 0x90, 0x21, 0x3E, 0x42, 0x00, 0x58, 0xE0, 0xC0,
|
||||
0x08, 0x84, 0x42, 0x11, 0x08, 0x80, 0x7B, 0x38, 0x65, 0x86, 0x1C, 0xDE, 0xE1, 0x08, 0x42, 0x10,
|
||||
0x9F, 0x7A, 0x10, 0x43, 0x18, 0xC4, 0x3F, 0x7A, 0x10, 0x5E, 0x0C, 0x18, 0x5E, 0x18, 0x62, 0x92,
|
||||
0xCB, 0xF0, 0x82, 0xFA, 0x08, 0x3E, 0x0C, 0x10, 0x7E, 0x3D, 0x08, 0x2E, 0xC6, 0x18, 0x5E, 0xFC,
|
||||
0x20, 0x84, 0x10, 0x82, 0x10, 0x7A, 0x18, 0x5E, 0x86, 0x18, 0x5E, 0x7A, 0x18, 0x61, 0x7C, 0x10,
|
||||
0xBC, 0xCC, 0x50, 0x58, 0x04, 0xEC, 0x1C, 0x0C, 0xFC, 0x0F, 0xC0, 0x81, 0xC0, 0xCE, 0xC0, 0xE1,
|
||||
0x36, 0x44, 0x04, 0x39, 0x38, 0x67, 0xA6, 0x99, 0xF0, 0x40, 0xE0, 0x30, 0xC3, 0x12, 0x49, 0xE8,
|
||||
0x61, 0xFA, 0x18, 0x7E, 0x86, 0x18, 0x7E, 0x39, 0x18, 0x20, 0x82, 0x04, 0x4E, 0xF2, 0x28, 0x61,
|
||||
0x86, 0x18, 0xBC, 0xFE, 0x08, 0x3F, 0x82, 0x08, 0x3F, 0xFE, 0x08, 0x3F, 0x82, 0x08, 0x20, 0x39,
|
||||
0x18, 0x20, 0x8E, 0x14, 0x4E, 0x86, 0x18, 0x7F, 0x86, 0x18, 0x61, 0xF9, 0x08, 0x42, 0x10, 0x9F,
|
||||
0x38, 0x42, 0x10, 0x86, 0x2E, 0x8A, 0x4A, 0x30, 0xA2, 0x48, 0xA1, 0x82, 0x08, 0x20, 0x82, 0x08,
|
||||
0x3F, 0x87, 0x3C, 0xED, 0xB6, 0x18, 0x61, 0x87, 0x1A, 0x69, 0x96, 0x58, 0xE1, 0x7B, 0x38, 0x61,
|
||||
0x86, 0x1C, 0xDE, 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x7B, 0x38, 0x61, 0x86, 0x1C, 0xDE, 0x0C,
|
||||
0xF9, 0x0A, 0x14, 0x2F, 0x91, 0x21, 0x41, 0x7A, 0x18, 0x3C, 0x0C, 0x18, 0x5E, 0xFE, 0x20, 0x40,
|
||||
0x81, 0x02, 0x04, 0x08, 0x86, 0x18, 0x61, 0x86, 0x18, 0x5E, 0x86, 0x14, 0x92, 0x48, 0xC3, 0x0C,
|
||||
0x83, 0x26, 0x4D, 0x56, 0xCD, 0x91, 0x22, 0x85, 0x24, 0x8C, 0x31, 0x24, 0xA1, 0xC6, 0x88, 0xA1,
|
||||
0xC1, 0x02, 0x04, 0x08, 0xFC, 0x20, 0x84, 0x21, 0x84, 0x3F, 0xEA, 0xAA, 0xB0, 0x82, 0x10, 0x42,
|
||||
0x10, 0x42, 0x08, 0xD5, 0x55, 0x70, 0x31, 0x28, 0x40, 0xFE, 0x44, 0xF0, 0x5F, 0x18, 0xBC, 0x84,
|
||||
0x21, 0xE8, 0xC6, 0x31, 0xF0, 0x7E, 0x21, 0x0C, 0x3C, 0x08, 0x42, 0xF8, 0xC6, 0x31, 0x78, 0x74,
|
||||
0x7F, 0x08, 0x3C, 0x19, 0x09, 0xF2, 0x10, 0x84, 0x20, 0x7C, 0x63, 0x18, 0xBC, 0x2E, 0x84, 0x21,
|
||||
0x6C, 0xC6, 0x31, 0x88, 0x20, 0x01, 0xC2, 0x10, 0x84, 0xF8, 0x20, 0x72, 0x49, 0x27, 0x00, 0x84,
|
||||
0x21, 0x2A, 0x62, 0x92, 0x88, 0xE1, 0x08, 0x42, 0x10, 0x84, 0x18, 0xFD, 0x6B, 0x5A, 0xD4, 0xB6,
|
||||
0x63, 0x18, 0xC4, 0x74, 0x63, 0x18, 0xB8, 0xF4, 0x63, 0x18, 0xFA, 0x10, 0x7C, 0x63, 0x18, 0xBC,
|
||||
0x21, 0xF9, 0x88, 0x88, 0x7C, 0x38, 0x30, 0xF8, 0x21, 0x3E, 0x42, 0x10, 0x87, 0x8C, 0x63, 0x18,
|
||||
0xBC, 0x8C, 0x54, 0xA5, 0x10, 0x83, 0x05, 0x52, 0xA2, 0x85, 0x00, 0xDA, 0x88, 0x45, 0x6C, 0x8C,
|
||||
0x94, 0xA6, 0x11, 0x18, 0xF8, 0x8C, 0xC4, 0x7C, 0x39, 0x08, 0x4C, 0x10, 0x84, 0x21, 0xC0, 0xFF,
|
||||
0xE0, 0xE1, 0x08, 0x41, 0x90, 0x84, 0x27, 0x00, 0xE0, 0x70, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0x00, 0xBF, 0x10, 0x9F, 0xA9, 0x4B, 0x4F, 0x10, 0x80, 0x3A, 0x10, 0x8F, 0x21, 0x1F,
|
||||
0x85, 0xE4, 0x92, 0x7A, 0x10, 0x82, 0x88, 0xA3, 0x61, 0x0F, 0x84, 0x08, 0xF7, 0x80, 0x7C, 0x19,
|
||||
0x68, 0xB4, 0x41, 0xF0, 0xA0, 0x38, 0xBA, 0x8D, 0x19, 0xE8, 0x8E, 0x00, 0xFF, 0x9F, 0x0F, 0x25,
|
||||
0x29, 0x12, 0x24, 0xFC, 0x10, 0x40, 0xE0, 0x38, 0xFA, 0xFD, 0x5A, 0x68, 0x8E, 0x00, 0xE0, 0xF7,
|
||||
0x80, 0x21, 0x3E, 0x42, 0x03, 0xE0, 0xE5, 0x70, 0xE8, 0xF0, 0x50, 0x8A, 0x28, 0xA2, 0x8B, 0xF8,
|
||||
0x20, 0x7F, 0xDF, 0x7D, 0x74, 0x51, 0x45, 0x14, 0xC0, 0x70, 0xC9, 0x70, 0x69, 0x96, 0x0F, 0x91,
|
||||
0x22, 0x52, 0x90, 0x60, 0x82, 0x1C, 0x1F, 0x80, 0x8E, 0x3C, 0x20, 0x60, 0x82, 0x1C, 0x1F, 0x81,
|
||||
0xC1, 0x08, 0x70, 0x70, 0x81, 0x18, 0x1F, 0x80, 0x8E, 0x3C, 0x20, 0x20, 0x22, 0x6C, 0x87, 0x40,
|
||||
0x80, 0x0C, 0x30, 0xC4, 0x92, 0x7A, 0x18, 0x40, 0x08, 0x40, 0x0C, 0x30, 0xC4, 0x92, 0x7A, 0x18,
|
||||
0x40, 0x31, 0x20, 0x0C, 0x30, 0xC4, 0x92, 0x7A, 0x18, 0x40, 0x69, 0x60, 0x0C, 0x30, 0xC4, 0x92,
|
||||
0x7A, 0x18, 0x40, 0x48, 0x03, 0x0C, 0x31, 0x24, 0x9E, 0x86, 0x10, 0x30, 0xC2, 0x08, 0x30, 0xC4,
|
||||
0x9E, 0x4A, 0x10, 0x3C, 0xC5, 0x17, 0x51, 0xC9, 0x27, 0x39, 0x18, 0x20, 0x82, 0x04, 0x4E, 0x20,
|
||||
0x80, 0x40, 0x80, 0x3F, 0x82, 0x0F, 0xE0, 0x82, 0x0F, 0xC0, 0x08, 0x40, 0x3F, 0x82, 0x0F, 0xE0,
|
||||
0x82, 0x0F, 0xC0, 0x21, 0x40, 0x3F, 0x82, 0x0F, 0xE0, 0x82, 0x0F, 0xC0, 0x50, 0x0F, 0xE0, 0x83,
|
||||
0xF8, 0x20, 0x83, 0xF0, 0x41, 0x01, 0xF2, 0x10, 0x84, 0x21, 0x3E, 0x08, 0x81, 0xF2, 0x10, 0x84,
|
||||
0x21, 0x3E, 0x22, 0x81, 0xF2, 0x10, 0x84, 0x21, 0x3E, 0x50, 0x3E, 0x42, 0x10, 0x84, 0x27, 0xC0,
|
||||
0x78, 0x89, 0x0F, 0x14, 0x28, 0x51, 0x3C, 0x69, 0x60, 0x21, 0xC6, 0x9A, 0x65, 0x96, 0x38, 0x40,
|
||||
0x40, 0x80, 0x1E, 0xCE, 0x18, 0x61, 0x87, 0x37, 0x80, 0x08, 0x40, 0x1E, 0xCE, 0x18, 0x61, 0x87,
|
||||
0x37, 0x80, 0x31, 0x20, 0x1E, 0xCE, 0x18, 0x61, 0x87, 0x37, 0x80, 0x69, 0x60, 0x1E, 0xCE, 0x18,
|
||||
0x61, 0x87, 0x37, 0x80, 0x48, 0x07, 0xB3, 0x86, 0x18, 0x61, 0xCD, 0xE0, 0x8A, 0x88, 0xA8, 0x80,
|
||||
0x3E, 0xCD, 0x1A, 0x55, 0x2C, 0x59, 0xDE, 0x40, 0x80, 0x21, 0x86, 0x18, 0x61, 0x86, 0x17, 0x80,
|
||||
0x08, 0x40, 0x21, 0x86, 0x18, 0x61, 0x86, 0x17, 0x80, 0x31, 0x20, 0x21, 0x86, 0x18, 0x61, 0x86,
|
||||
0x17, 0x80, 0x48, 0x08, 0x61, 0x86, 0x18, 0x61, 0x85, 0xE0, 0x08, 0x20, 0x06, 0x34, 0x45, 0x0E,
|
||||
0x08, 0x10, 0x20, 0x40, 0x83, 0xE8, 0x61, 0x87, 0xE8, 0x20, 0x64, 0xA5, 0x4A, 0x4A, 0x31, 0xB8,
|
||||
0x20, 0x81, 0xE0, 0xBE, 0x31, 0x78, 0x11, 0x01, 0xE0, 0xBE, 0x31, 0x78, 0x22, 0x81, 0xE0, 0xBE,
|
||||
0x31, 0x78, 0x6A, 0xC1, 0xE0, 0xBE, 0x31, 0x78, 0x50, 0x3C, 0x17, 0xC6, 0x2F, 0x72, 0x9C, 0x0F,
|
||||
0x05, 0xF1, 0x8B, 0xC0, 0xD9, 0x7F, 0x4A, 0x6C, 0x7E, 0x21, 0x0C, 0x3C, 0x84, 0x20, 0x80, 0xE8,
|
||||
0xFE, 0x10, 0x78, 0x18, 0x80, 0xE8, 0xFE, 0x10, 0x78, 0x22, 0x80, 0xE8, 0xFE, 0x10, 0x78, 0x50,
|
||||
0x1D, 0x1F, 0xC2, 0x0F, 0x20, 0x81, 0xC2, 0x10, 0x84, 0xF8, 0x11, 0x01, 0xC2, 0x10, 0x84, 0xF8,
|
||||
0x22, 0x81, 0xC2, 0x10, 0x84, 0xF8, 0x50, 0x38, 0x42, 0x10, 0x9F, 0x43, 0x84, 0xE8, 0xC6, 0x31,
|
||||
0x70, 0x6A, 0xC1, 0x6C, 0xC6, 0x31, 0x88, 0x20, 0x80, 0xE8, 0xC6, 0x31, 0x70, 0x11, 0x00, 0xE8,
|
||||
0xC6, 0x31, 0x70, 0x22, 0x80, 0xE8, 0xC6, 0x31, 0x70, 0xED, 0xC0, 0xE8, 0xC6, 0x31, 0x70, 0x50,
|
||||
0x1D, 0x18, 0xC6, 0x2E, 0x20, 0x3E, 0x02, 0x00, 0x3D, 0x15, 0xD9, 0x65, 0xE0, 0x20, 0x81, 0x18,
|
||||
0xC6, 0x31, 0x78, 0x11, 0x01, 0x18, 0xC6, 0x31, 0x78, 0x22, 0x81, 0x18, 0xC6, 0x31, 0x78, 0x50,
|
||||
0x23, 0x18, 0xC6, 0x2F, 0x11, 0x01, 0x19, 0x29, 0x4C, 0x22, 0x30, 0x84, 0x21, 0xE8, 0xC6, 0x31,
|
||||
0xF4, 0x20, 0x50, 0x23, 0x25, 0x29, 0x84, 0x46, 0x00, 0x78, 0x03, 0x0C, 0x31, 0x24, 0x9E, 0x86,
|
||||
0x10, 0x70, 0x3C, 0x17, 0xC6, 0x2F, 0x48, 0xC0, 0x0C, 0x30, 0xC4, 0x92, 0x7A, 0x18, 0x40, 0x53,
|
||||
0x81, 0xE0, 0xBE, 0x31, 0x78, 0x30, 0xC3, 0x12, 0x49, 0xE8, 0x61, 0x08, 0x20, 0xF0, 0x5F, 0x18,
|
||||
0xBC, 0x43, 0x08, 0x20, 0x0E, 0x46, 0x08, 0x20, 0x81, 0x13, 0x80, 0x08, 0x80, 0xFC, 0x42, 0x18,
|
||||
0x78, 0x30, 0xC0, 0x0E, 0x46, 0x08, 0x20, 0x81, 0x13, 0x80, 0x32, 0x80, 0xFC, 0x42, 0x18, 0x78,
|
||||
0x20, 0x03, 0x91, 0x82, 0x08, 0x20, 0x44, 0xE0, 0x20, 0x1F, 0x88, 0x43, 0x0F, 0x50, 0xC0, 0x0E,
|
||||
0x46, 0x08, 0x20, 0x81, 0x13, 0x80, 0x51, 0x80, 0xFC, 0x42, 0x18, 0x78, 0x61, 0x80, 0x3C, 0x8A,
|
||||
0x18, 0x61, 0x86, 0x2F, 0x00, 0x0A, 0x14, 0x23, 0xC8, 0x91, 0x22, 0x44, 0x78, 0x78, 0x89, 0x0F,
|
||||
0x14, 0x28, 0x51, 0x3C, 0x08, 0xF0, 0x9E, 0x8A, 0x28, 0xA2, 0x78, 0x70, 0x0F, 0xE0, 0x83, 0xF8,
|
||||
0x20, 0x83, 0xF0, 0x70, 0x1D, 0x1F, 0xC2, 0x0F, 0x50, 0xC0, 0x3F, 0x82, 0x0F, 0xE0, 0x82, 0x0F,
|
||||
0xC0, 0x51, 0x80, 0xE8, 0xFE, 0x10, 0x78, 0x20, 0x0F, 0xE0, 0x83, 0xF8, 0x20, 0x83, 0xF0, 0x20,
|
||||
0x1D, 0x1F, 0xC2, 0x0F, 0xFE, 0x08, 0x3F, 0x82, 0x08, 0x3F, 0x10, 0x60, 0x74, 0x7F, 0x08, 0x3C,
|
||||
0x86, 0x50, 0x80, 0x3F, 0x82, 0x0F, 0xE0, 0x82, 0x0F, 0xC0, 0x51, 0x00, 0xE8, 0xFE, 0x10, 0x78,
|
||||
0x21, 0x40, 0x0E, 0x46, 0x08, 0x23, 0x85, 0x13, 0x80, 0x22, 0x80, 0xF8, 0xC6, 0x31, 0x78, 0x5C,
|
||||
0x50, 0xC0, 0x0E, 0x46, 0x08, 0x23, 0x85, 0x13, 0x80, 0x53, 0x80, 0xF8, 0xC6, 0x31, 0x78, 0x5C,
|
||||
0x20, 0x03, 0x91, 0x82, 0x08, 0xE1, 0x44, 0xE0, 0x20, 0x1F, 0x18, 0xC6, 0x2F, 0x0B, 0x80, 0x39,
|
||||
0x18, 0x20, 0x8E, 0x14, 0x4E, 0x00, 0x82, 0x00, 0x21, 0x00, 0xF8, 0xC6, 0x31, 0x78, 0x5C, 0x31,
|
||||
0x20, 0x21, 0x86, 0x1F, 0xE1, 0x86, 0x18, 0x40, 0x22, 0x81, 0x08, 0x42, 0xD9, 0x8C, 0x63, 0x10,
|
||||
0x42, 0xFF, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x43, 0xC4, 0x1E, 0x45, 0x14, 0x51, 0x44, 0xED,
|
||||
0xC1, 0xF2, 0x10, 0x84, 0x21, 0x3E, 0x6A, 0xC1, 0xC2, 0x10, 0x84, 0xF8, 0x70, 0x3E, 0x42, 0x10,
|
||||
0x84, 0x27, 0xC0, 0x70, 0x38, 0x42, 0x10, 0x9F, 0x53, 0x81, 0xF2, 0x10, 0x84, 0x21, 0x3E, 0x53,
|
||||
0x81, 0xC2, 0x10, 0x84, 0xF8, 0xF9, 0x08, 0x42, 0x10, 0x9F, 0x43, 0x00, 0x20, 0x01, 0xC2, 0x10,
|
||||
0x84, 0xF9, 0x08, 0x20, 0x3E, 0x42, 0x10, 0x84, 0x27, 0xC0, 0xE1, 0x08, 0x42, 0x7C, 0xE6, 0x85,
|
||||
0x0A, 0x14, 0x28, 0x50, 0xF7, 0x24, 0x00, 0x1F, 0x24, 0x92, 0x49, 0xFC, 0x11, 0xC0, 0x22, 0x80,
|
||||
0x70, 0x84, 0x21, 0x0C, 0x5C, 0x25, 0x0E, 0x22, 0x22, 0x22, 0xC0, 0x8A, 0x4A, 0x30, 0xA2, 0x48,
|
||||
0xA1, 0x00, 0x82, 0x00, 0x84, 0x21, 0x2A, 0x62, 0x92, 0x88, 0x0C, 0x40, 0x95, 0x31, 0x49, 0x44,
|
||||
0x41, 0x00, 0x20, 0x82, 0x08, 0x20, 0x82, 0x0F, 0xC0, 0x08, 0x41, 0xC2, 0x10, 0x84, 0x21, 0x08,
|
||||
0x30, 0x82, 0x08, 0x20, 0x82, 0x08, 0x3F, 0x00, 0x82, 0x00, 0xE1, 0x08, 0x42, 0x10, 0x84, 0x18,
|
||||
0x0C, 0x40, 0x92, 0x48, 0x20, 0x82, 0x08, 0x3F, 0xE4, 0x92, 0x08, 0x20, 0x82, 0x08, 0x18, 0x82,
|
||||
0x08, 0xA2, 0x82, 0x08, 0x3F, 0xE0, 0x40, 0x81, 0x12, 0x24, 0x08, 0x10, 0x18, 0x40, 0x81, 0x63,
|
||||
0x0C, 0x08, 0x10, 0x3F, 0xE1, 0x0A, 0x66, 0x50, 0x84, 0x18, 0x08, 0x40, 0x21, 0xC6, 0x9A, 0x65,
|
||||
0x96, 0x38, 0x40, 0x18, 0x81, 0x6C, 0xC6, 0x31, 0x88, 0x87, 0x1A, 0x69, 0x96, 0x58, 0xE1, 0x00,
|
||||
0x84, 0x00, 0xB6, 0x63, 0x18, 0xC4, 0x04, 0x40, 0x50, 0x80, 0x21, 0xC6, 0x9A, 0x65, 0x96, 0x38,
|
||||
0x40, 0x51, 0x01, 0x6C, 0xC6, 0x31, 0x88, 0x41, 0x02, 0x01, 0xE2, 0x64, 0x48, 0x91, 0x22, 0xBB,
|
||||
0x18, 0x61, 0x86, 0x18, 0x61, 0x04, 0x60, 0xB6, 0x63, 0x18, 0xC4, 0x27, 0x78, 0x07, 0xB3, 0x86,
|
||||
0x18, 0x61, 0xCD, 0xE0, 0x70, 0x1D, 0x18, 0xC6, 0x2E, 0x48, 0xC0, 0x1E, 0xCE, 0x18, 0x61, 0x87,
|
||||
0x37, 0x80, 0x53, 0x80, 0xE8, 0xC6, 0x31, 0x70, 0x50, 0x07, 0xB3, 0x86, 0x18, 0x61, 0xCD, 0xE0,
|
||||
0x2A, 0x80, 0xE8, 0xC6, 0x31, 0x70, 0x7E, 0x49, 0x27, 0x92, 0x49, 0x1F, 0xDD, 0x6F, 0x4A, 0x6C,
|
||||
0x10, 0x20, 0x07, 0xC8, 0x50, 0xA1, 0x7C, 0x89, 0x0A, 0x08, 0x18, 0x81, 0xE9, 0x42, 0x10, 0x80,
|
||||
0xF9, 0x0A, 0x14, 0x2F, 0x91, 0x21, 0x41, 0x00, 0x40, 0x80, 0x7A, 0x50, 0x84, 0x20, 0x08, 0xC0,
|
||||
0x60, 0xC0, 0x07, 0xC8, 0x50, 0xA1, 0x7C, 0x89, 0x0A, 0x08, 0xA6, 0x0F, 0x98, 0x88, 0x80, 0x08,
|
||||
0x40, 0x1E, 0x86, 0x0F, 0x03, 0x06, 0x17, 0x80, 0x18, 0x80, 0xF8, 0x70, 0x61, 0xF0, 0x21, 0x40,
|
||||
0x1E, 0x86, 0x0F, 0x03, 0x06, 0x17, 0x80, 0x22, 0x80, 0xF8, 0x70, 0x61, 0xF0, 0x7A, 0x18, 0x3C,
|
||||
0x0C, 0x18, 0x5E, 0x21, 0x80, 0x7C, 0x38, 0x30, 0xF8, 0x8C,
|
||||
};
|
||||
|
||||
const GFXglyph UiFont11ptGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 7, 0, -1 }, // 0x0020
|
||||
{ 1, 1, 8, 7, 3, -8 }, // 0x0021
|
||||
{ 2, 3, 3, 7, 2, -8 }, // 0x0022
|
||||
{ 4, 7, 8, 7, 0, -8 }, // 0x0023
|
||||
{ 11, 5, 10, 7, 1, -8 }, // 0x0024
|
||||
{ 18, 6, 8, 7, 0, -8 }, // 0x0025
|
||||
{ 24, 6, 8, 7, 1, -8 }, // 0x0026
|
||||
{ 30, 1, 3, 7, 3, -8 }, // 0x0027
|
||||
{ 31, 2, 10, 7, 2, -9 }, // 0x0028
|
||||
{ 34, 2, 10, 7, 2, -9 }, // 0x0029
|
||||
{ 37, 5, 6, 7, 1, -8 }, // 0x002A
|
||||
{ 41, 5, 5, 7, 1, -6 }, // 0x002B
|
||||
{ 45, 2, 3, 7, 2, -2 }, // 0x002C
|
||||
{ 46, 3, 1, 7, 2, -4 }, // 0x002D
|
||||
{ 47, 1, 2, 7, 3, -2 }, // 0x002E
|
||||
{ 48, 5, 9, 7, 1, -8 }, // 0x002F
|
||||
{ 54, 6, 8, 7, 1, -8 }, // 0x0030
|
||||
{ 60, 5, 8, 7, 1, -8 }, // 0x0031
|
||||
{ 65, 6, 8, 7, 1, -8 }, // 0x0032
|
||||
{ 71, 6, 8, 7, 1, -8 }, // 0x0033
|
||||
{ 77, 6, 8, 7, 1, -8 }, // 0x0034
|
||||
{ 83, 6, 8, 7, 1, -8 }, // 0x0035
|
||||
{ 89, 6, 8, 7, 1, -8 }, // 0x0036
|
||||
{ 95, 6, 8, 7, 1, -8 }, // 0x0037
|
||||
{ 101, 6, 8, 7, 1, -8 }, // 0x0038
|
||||
{ 107, 6, 8, 7, 1, -8 }, // 0x0039
|
||||
{ 113, 1, 6, 7, 3, -6 }, // 0x003A
|
||||
{ 114, 2, 7, 7, 2, -6 }, // 0x003B
|
||||
{ 116, 6, 5, 7, 1, -6 }, // 0x003C
|
||||
{ 120, 6, 3, 7, 0, -5 }, // 0x003D
|
||||
{ 123, 6, 5, 7, 1, -6 }, // 0x003E
|
||||
{ 127, 4, 8, 7, 2, -8 }, // 0x003F
|
||||
{ 131, 6, 10, 7, 1, -8 }, // 0x0040
|
||||
{ 139, 6, 8, 7, 1, -8 }, // 0x0041
|
||||
{ 145, 6, 8, 7, 1, -8 }, // 0x0042
|
||||
{ 151, 6, 8, 7, 1, -8 }, // 0x0043
|
||||
{ 157, 6, 8, 7, 1, -8 }, // 0x0044
|
||||
{ 163, 6, 8, 7, 1, -8 }, // 0x0045
|
||||
{ 169, 6, 8, 7, 1, -8 }, // 0x0046
|
||||
{ 175, 6, 8, 7, 1, -8 }, // 0x0047
|
||||
{ 181, 6, 8, 7, 1, -8 }, // 0x0048
|
||||
{ 187, 5, 8, 7, 1, -8 }, // 0x0049
|
||||
{ 192, 5, 8, 7, 1, -8 }, // 0x004A
|
||||
{ 197, 6, 8, 7, 1, -8 }, // 0x004B
|
||||
{ 203, 6, 8, 7, 1, -8 }, // 0x004C
|
||||
{ 209, 6, 8, 7, 1, -8 }, // 0x004D
|
||||
{ 215, 6, 8, 7, 1, -8 }, // 0x004E
|
||||
{ 221, 6, 8, 7, 1, -8 }, // 0x004F
|
||||
{ 227, 6, 8, 7, 1, -8 }, // 0x0050
|
||||
{ 233, 6, 9, 7, 1, -8 }, // 0x0051
|
||||
{ 240, 7, 8, 7, 1, -8 }, // 0x0052
|
||||
{ 247, 6, 8, 7, 1, -8 }, // 0x0053
|
||||
{ 253, 7, 8, 7, 0, -8 }, // 0x0054
|
||||
{ 260, 6, 8, 7, 1, -8 }, // 0x0055
|
||||
{ 266, 6, 8, 7, 1, -8 }, // 0x0056
|
||||
{ 272, 7, 8, 7, 0, -8 }, // 0x0057
|
||||
{ 279, 6, 8, 7, 1, -8 }, // 0x0058
|
||||
{ 285, 7, 8, 7, 0, -8 }, // 0x0059
|
||||
{ 292, 6, 8, 7, 1, -8 }, // 0x005A
|
||||
{ 298, 2, 10, 7, 2, -9 }, // 0x005B
|
||||
{ 301, 5, 9, 7, 1, -8 }, // 0x005C
|
||||
{ 307, 2, 10, 7, 2, -9 }, // 0x005D
|
||||
{ 310, 6, 3, 7, 0, -8 }, // 0x005E
|
||||
{ 313, 7, 1, 7, 0, 2 }, // 0x005F
|
||||
{ 314, 3, 2, 7, 2, -9 }, // 0x0060
|
||||
{ 315, 5, 6, 7, 1, -6 }, // 0x0061
|
||||
{ 319, 5, 9, 7, 1, -9 }, // 0x0062
|
||||
{ 325, 5, 6, 7, 1, -6 }, // 0x0063
|
||||
{ 329, 5, 9, 7, 1, -9 }, // 0x0064
|
||||
{ 335, 5, 6, 7, 1, -6 }, // 0x0065
|
||||
{ 339, 5, 9, 7, 1, -9 }, // 0x0066
|
||||
{ 345, 5, 8, 7, 1, -6 }, // 0x0067
|
||||
{ 350, 5, 9, 7, 1, -9 }, // 0x0068
|
||||
{ 356, 5, 9, 7, 1, -9 }, // 0x0069
|
||||
{ 362, 3, 11, 7, 1, -9 }, // 0x006A
|
||||
{ 367, 5, 9, 7, 1, -9 }, // 0x006B
|
||||
{ 373, 5, 9, 7, 0, -9 }, // 0x006C
|
||||
{ 379, 5, 6, 7, 1, -6 }, // 0x006D
|
||||
{ 383, 5, 6, 7, 1, -6 }, // 0x006E
|
||||
{ 387, 5, 6, 7, 1, -6 }, // 0x006F
|
||||
{ 391, 5, 8, 7, 1, -6 }, // 0x0070
|
||||
{ 396, 5, 8, 7, 1, -6 }, // 0x0071
|
||||
{ 401, 4, 6, 7, 2, -6 }, // 0x0072
|
||||
{ 404, 5, 6, 7, 1, -6 }, // 0x0073
|
||||
{ 408, 5, 8, 7, 0, -8 }, // 0x0074
|
||||
{ 413, 5, 6, 7, 1, -6 }, // 0x0075
|
||||
{ 417, 5, 6, 7, 1, -6 }, // 0x0076
|
||||
{ 421, 7, 6, 7, 0, -6 }, // 0x0077
|
||||
{ 427, 5, 6, 7, 1, -6 }, // 0x0078
|
||||
{ 431, 5, 8, 7, 1, -6 }, // 0x0079
|
||||
{ 436, 5, 6, 7, 1, -6 }, // 0x007A
|
||||
{ 440, 5, 10, 7, 1, -9 }, // 0x007B
|
||||
{ 447, 1, 11, 7, 3, -9 }, // 0x007C
|
||||
{ 449, 5, 10, 7, 1, -9 }, // 0x007D
|
||||
{ 456, 6, 2, 7, 1, -4 }, // 0x007E
|
||||
{ 458, 6, 10, 7, 1, -8 }, // 0x007F
|
||||
{ 466, 6, 10, 7, 1, -8 }, // 0x0080
|
||||
{ 474, 6, 10, 7, 1, -8 }, // 0x0081
|
||||
{ 482, 6, 10, 7, 1, -8 }, // 0x0082
|
||||
{ 490, 6, 10, 7, 1, -8 }, // 0x0083
|
||||
{ 498, 6, 10, 7, 1, -8 }, // 0x0084
|
||||
{ 506, 6, 10, 7, 1, -8 }, // 0x0085
|
||||
{ 514, 6, 10, 7, 1, -8 }, // 0x0086
|
||||
{ 522, 6, 10, 7, 1, -8 }, // 0x0087
|
||||
{ 530, 6, 10, 7, 1, -8 }, // 0x0088
|
||||
{ 538, 6, 10, 7, 1, -8 }, // 0x0089
|
||||
{ 546, 6, 10, 7, 1, -8 }, // 0x008A
|
||||
{ 554, 6, 10, 7, 1, -8 }, // 0x008B
|
||||
{ 562, 6, 10, 7, 1, -8 }, // 0x008C
|
||||
{ 570, 6, 10, 7, 1, -8 }, // 0x008D
|
||||
{ 578, 6, 10, 7, 1, -8 }, // 0x008E
|
||||
{ 586, 6, 10, 7, 1, -8 }, // 0x008F
|
||||
{ 594, 6, 10, 7, 1, -8 }, // 0x0090
|
||||
{ 602, 6, 10, 7, 1, -8 }, // 0x0091
|
||||
{ 610, 6, 10, 7, 1, -8 }, // 0x0092
|
||||
{ 618, 6, 10, 7, 1, -8 }, // 0x0093
|
||||
{ 626, 6, 10, 7, 1, -8 }, // 0x0094
|
||||
{ 634, 6, 10, 7, 1, -8 }, // 0x0095
|
||||
{ 642, 6, 10, 7, 1, -8 }, // 0x0096
|
||||
{ 650, 6, 10, 7, 1, -8 }, // 0x0097
|
||||
{ 658, 6, 10, 7, 1, -8 }, // 0x0098
|
||||
{ 666, 6, 10, 7, 1, -8 }, // 0x0099
|
||||
{ 674, 6, 10, 7, 1, -8 }, // 0x009A
|
||||
{ 682, 6, 10, 7, 1, -8 }, // 0x009B
|
||||
{ 690, 6, 10, 7, 1, -8 }, // 0x009C
|
||||
{ 698, 6, 10, 7, 1, -8 }, // 0x009D
|
||||
{ 706, 6, 10, 7, 1, -8 }, // 0x009E
|
||||
{ 714, 6, 10, 7, 1, -8 }, // 0x009F
|
||||
{ 722, 1, 1, 7, 0, -1 }, // 0x00A0
|
||||
{ 723, 1, 8, 7, 3, -6 }, // 0x00A1
|
||||
{ 724, 5, 10, 7, 1, -8 }, // 0x00A2
|
||||
{ 731, 5, 8, 7, 1, -8 }, // 0x00A3
|
||||
{ 736, 6, 6, 7, 1, -6 }, // 0x00A4
|
||||
{ 741, 7, 8, 7, 0, -8 }, // 0x00A5
|
||||
{ 748, 1, 9, 7, 3, -8 }, // 0x00A6
|
||||
{ 750, 5, 9, 7, 1, -8 }, // 0x00A7
|
||||
{ 756, 3, 1, 7, 2, -8 }, // 0x00A8
|
||||
{ 757, 7, 7, 7, 0, -7 }, // 0x00A9
|
||||
{ 764, 4, 6, 7, 1, -8 }, // 0x00AA
|
||||
{ 767, 6, 5, 7, 1, -6 }, // 0x00AB
|
||||
{ 771, 6, 3, 7, 1, -5 }, // 0x00AC
|
||||
{ 774, 3, 1, 7, 2, -4 }, // 0x00AD
|
||||
{ 775, 7, 7, 7, 0, -7 }, // 0x00AE
|
||||
{ 782, 3, 1, 7, 2, -8 }, // 0x00AF
|
||||
{ 783, 3, 3, 7, 2, -8 }, // 0x00B0
|
||||
{ 785, 5, 7, 7, 1, -7 }, // 0x00B1
|
||||
{ 790, 3, 4, 7, 2, -8 }, // 0x00B2
|
||||
{ 792, 3, 4, 7, 2, -8 }, // 0x00B3
|
||||
{ 794, 3, 2, 7, 3, -9 }, // 0x00B4
|
||||
{ 795, 6, 8, 7, 1, -6 }, // 0x00B5
|
||||
{ 801, 6, 9, 7, 1, -8 }, // 0x00B6
|
||||
{ 808, 1, 2, 7, 3, -5 }, // 0x00B7
|
||||
{ 809, 2, 2, 7, 2, 0 }, // 0x00B8
|
||||
{ 810, 3, 4, 7, 2, -8 }, // 0x00B9
|
||||
{ 812, 4, 6, 7, 1, -8 }, // 0x00BA
|
||||
{ 815, 6, 5, 7, 1, -6 }, // 0x00BB
|
||||
{ 819, 6, 10, 7, 0, -9 }, // 0x00BC
|
||||
{ 827, 6, 10, 7, 0, -9 }, // 0x00BD
|
||||
{ 835, 6, 10, 7, 0, -9 }, // 0x00BE
|
||||
{ 843, 4, 8, 7, 1, -6 }, // 0x00BF
|
||||
{ 847, 6, 11, 7, 1, -11 }, // 0x00C0
|
||||
{ 856, 6, 11, 7, 1, -11 }, // 0x00C1
|
||||
{ 865, 6, 11, 7, 1, -11 }, // 0x00C2
|
||||
{ 874, 6, 11, 7, 1, -11 }, // 0x00C3
|
||||
{ 883, 6, 10, 7, 1, -10 }, // 0x00C4
|
||||
{ 891, 6, 10, 7, 1, -10 }, // 0x00C5
|
||||
{ 899, 6, 8, 7, 0, -8 }, // 0x00C6
|
||||
{ 905, 6, 10, 7, 1, -8 }, // 0x00C7
|
||||
{ 913, 6, 11, 7, 1, -11 }, // 0x00C8
|
||||
{ 922, 6, 11, 7, 1, -11 }, // 0x00C9
|
||||
{ 931, 6, 11, 7, 1, -11 }, // 0x00CA
|
||||
{ 940, 6, 10, 7, 1, -10 }, // 0x00CB
|
||||
{ 948, 5, 11, 7, 1, -11 }, // 0x00CC
|
||||
{ 955, 5, 11, 7, 1, -11 }, // 0x00CD
|
||||
{ 962, 5, 11, 7, 1, -11 }, // 0x00CE
|
||||
{ 969, 5, 10, 7, 1, -10 }, // 0x00CF
|
||||
{ 976, 7, 8, 7, 0, -8 }, // 0x00D0
|
||||
{ 983, 6, 11, 7, 1, -11 }, // 0x00D1
|
||||
{ 992, 6, 11, 7, 1, -11 }, // 0x00D2
|
||||
{ 1001, 6, 11, 7, 1, -11 }, // 0x00D3
|
||||
{ 1010, 6, 11, 7, 1, -11 }, // 0x00D4
|
||||
{ 1019, 6, 11, 7, 1, -11 }, // 0x00D5
|
||||
{ 1028, 6, 10, 7, 1, -10 }, // 0x00D6
|
||||
{ 1036, 5, 5, 7, 1, -6 }, // 0x00D7
|
||||
{ 1040, 7, 8, 7, 0, -8 }, // 0x00D8
|
||||
{ 1047, 6, 11, 7, 1, -11 }, // 0x00D9
|
||||
{ 1056, 6, 11, 7, 1, -11 }, // 0x00DA
|
||||
{ 1065, 6, 11, 7, 1, -11 }, // 0x00DB
|
||||
{ 1074, 6, 10, 7, 1, -10 }, // 0x00DC
|
||||
{ 1082, 7, 11, 7, 0, -11 }, // 0x00DD
|
||||
{ 1092, 6, 8, 7, 1, -8 }, // 0x00DE
|
||||
{ 1098, 5, 9, 7, 1, -9 }, // 0x00DF
|
||||
{ 1104, 5, 9, 7, 1, -9 }, // 0x00E0
|
||||
{ 1110, 5, 9, 7, 1, -9 }, // 0x00E1
|
||||
{ 1116, 5, 9, 7, 1, -9 }, // 0x00E2
|
||||
{ 1122, 5, 9, 7, 1, -9 }, // 0x00E3
|
||||
{ 1128, 5, 8, 7, 1, -8 }, // 0x00E4
|
||||
{ 1133, 5, 10, 7, 1, -10 }, // 0x00E5
|
||||
{ 1140, 5, 6, 7, 1, -6 }, // 0x00E6
|
||||
{ 1144, 5, 8, 7, 1, -6 }, // 0x00E7
|
||||
{ 1149, 5, 9, 7, 1, -9 }, // 0x00E8
|
||||
{ 1155, 5, 9, 7, 1, -9 }, // 0x00E9
|
||||
{ 1161, 5, 9, 7, 1, -9 }, // 0x00EA
|
||||
{ 1167, 5, 8, 7, 1, -8 }, // 0x00EB
|
||||
{ 1172, 5, 9, 7, 1, -9 }, // 0x00EC
|
||||
{ 1178, 5, 9, 7, 1, -9 }, // 0x00ED
|
||||
{ 1184, 5, 9, 7, 1, -9 }, // 0x00EE
|
||||
{ 1190, 5, 8, 7, 1, -8 }, // 0x00EF
|
||||
{ 1195, 5, 9, 7, 1, -9 }, // 0x00F0
|
||||
{ 1201, 5, 9, 7, 1, -9 }, // 0x00F1
|
||||
{ 1207, 5, 9, 7, 1, -9 }, // 0x00F2
|
||||
{ 1213, 5, 9, 7, 1, -9 }, // 0x00F3
|
||||
{ 1219, 5, 9, 7, 1, -9 }, // 0x00F4
|
||||
{ 1225, 5, 9, 7, 1, -9 }, // 0x00F5
|
||||
{ 1231, 5, 8, 7, 1, -8 }, // 0x00F6
|
||||
{ 1236, 5, 5, 7, 1, -6 }, // 0x00F7
|
||||
{ 1240, 6, 6, 7, 0, -6 }, // 0x00F8
|
||||
{ 1245, 5, 9, 7, 1, -9 }, // 0x00F9
|
||||
{ 1251, 5, 9, 7, 1, -9 }, // 0x00FA
|
||||
{ 1257, 5, 9, 7, 1, -9 }, // 0x00FB
|
||||
{ 1263, 5, 8, 7, 1, -8 }, // 0x00FC
|
||||
{ 1268, 5, 11, 7, 1, -9 }, // 0x00FD
|
||||
{ 1275, 5, 11, 7, 1, -9 }, // 0x00FE
|
||||
{ 1282, 5, 10, 7, 1, -8 }, // 0x00FF
|
||||
{ 1289, 6, 10, 7, 1, -10 }, // 0x0100
|
||||
{ 1297, 5, 8, 7, 1, -8 }, // 0x0101
|
||||
{ 1302, 6, 11, 7, 1, -11 }, // 0x0102
|
||||
{ 1311, 5, 9, 7, 1, -9 }, // 0x0103
|
||||
{ 1317, 6, 10, 7, 1, -8 }, // 0x0104
|
||||
{ 1325, 5, 8, 7, 1, -6 }, // 0x0105
|
||||
{ 1330, 6, 11, 7, 1, -11 }, // 0x0106
|
||||
{ 1339, 5, 9, 7, 1, -9 }, // 0x0107
|
||||
{ 1345, 6, 11, 7, 1, -11 }, // 0x0108
|
||||
{ 1354, 5, 9, 7, 1, -9 }, // 0x0109
|
||||
{ 1360, 6, 10, 7, 1, -10 }, // 0x010A
|
||||
{ 1368, 5, 8, 7, 1, -8 }, // 0x010B
|
||||
{ 1373, 6, 11, 7, 1, -11 }, // 0x010C
|
||||
{ 1382, 5, 9, 7, 1, -9 }, // 0x010D
|
||||
{ 1388, 6, 11, 7, 1, -11 }, // 0x010E
|
||||
{ 1397, 7, 9, 7, 1, -9 }, // 0x010F
|
||||
{ 1405, 7, 8, 7, 0, -8 }, // 0x0110
|
||||
{ 1412, 6, 9, 7, 1, -9 }, // 0x0111
|
||||
{ 1419, 6, 10, 7, 1, -10 }, // 0x0112
|
||||
{ 1427, 5, 8, 7, 1, -8 }, // 0x0113
|
||||
{ 1432, 6, 11, 7, 1, -11 }, // 0x0114
|
||||
{ 1441, 5, 9, 7, 1, -9 }, // 0x0115
|
||||
{ 1447, 6, 10, 7, 1, -10 }, // 0x0116
|
||||
{ 1455, 5, 8, 7, 1, -8 }, // 0x0117
|
||||
{ 1460, 6, 10, 7, 1, -8 }, // 0x0118
|
||||
{ 1468, 5, 8, 7, 1, -6 }, // 0x0119
|
||||
{ 1473, 6, 11, 7, 1, -11 }, // 0x011A
|
||||
{ 1482, 5, 9, 7, 1, -9 }, // 0x011B
|
||||
{ 1488, 6, 11, 7, 1, -11 }, // 0x011C
|
||||
{ 1497, 5, 11, 7, 1, -9 }, // 0x011D
|
||||
{ 1504, 6, 11, 7, 1, -11 }, // 0x011E
|
||||
{ 1513, 5, 11, 7, 1, -9 }, // 0x011F
|
||||
{ 1520, 6, 10, 7, 1, -10 }, // 0x0120
|
||||
{ 1528, 5, 10, 7, 1, -8 }, // 0x0121
|
||||
{ 1535, 6, 11, 7, 1, -8 }, // 0x0122
|
||||
{ 1544, 5, 11, 7, 1, -9 }, // 0x0123
|
||||
{ 1551, 6, 11, 7, 1, -11 }, // 0x0124
|
||||
{ 1560, 5, 12, 7, 1, -12 }, // 0x0125
|
||||
{ 1568, 8, 8, 7, 0, -8 }, // 0x0126
|
||||
{ 1576, 6, 9, 7, 0, -9 }, // 0x0127
|
||||
{ 1583, 5, 11, 7, 1, -11 }, // 0x0128
|
||||
{ 1590, 5, 9, 7, 1, -9 }, // 0x0129
|
||||
{ 1596, 5, 10, 7, 1, -10 }, // 0x012A
|
||||
{ 1603, 5, 8, 7, 1, -8 }, // 0x012B
|
||||
{ 1608, 5, 11, 7, 1, -11 }, // 0x012C
|
||||
{ 1615, 5, 9, 7, 1, -9 }, // 0x012D
|
||||
{ 1621, 5, 10, 7, 1, -8 }, // 0x012E
|
||||
{ 1628, 5, 11, 7, 1, -9 }, // 0x012F
|
||||
{ 1635, 5, 10, 7, 1, -10 }, // 0x0130
|
||||
{ 1642, 5, 6, 7, 1, -6 }, // 0x0131
|
||||
{ 1646, 7, 8, 7, 0, -8 }, // 0x0132
|
||||
{ 1653, 6, 11, 7, 0, -9 }, // 0x0133
|
||||
{ 1662, 5, 11, 7, 1, -11 }, // 0x0134
|
||||
{ 1669, 4, 11, 7, 1, -9 }, // 0x0135
|
||||
{ 1675, 6, 11, 7, 1, -8 }, // 0x0136
|
||||
{ 1684, 5, 12, 7, 1, -9 }, // 0x0137
|
||||
{ 1692, 5, 6, 7, 1, -6 }, // 0x0138
|
||||
{ 1696, 6, 11, 7, 1, -11 }, // 0x0139
|
||||
{ 1705, 5, 12, 7, 0, -12 }, // 0x013A
|
||||
{ 1713, 6, 11, 7, 1, -8 }, // 0x013B
|
||||
{ 1722, 5, 12, 7, 0, -9 }, // 0x013C
|
||||
{ 1730, 6, 8, 7, 1, -8 }, // 0x013D
|
||||
{ 1736, 6, 9, 7, 0, -9 }, // 0x013E
|
||||
{ 1743, 6, 8, 7, 1, -8 }, // 0x013F
|
||||
{ 1749, 7, 9, 7, 0, -9 }, // 0x0140
|
||||
{ 1757, 7, 8, 7, 0, -8 }, // 0x0141
|
||||
{ 1764, 5, 9, 7, 0, -9 }, // 0x0142
|
||||
{ 1770, 6, 11, 7, 1, -11 }, // 0x0143
|
||||
{ 1779, 5, 9, 7, 1, -9 }, // 0x0144
|
||||
{ 1785, 6, 11, 7, 1, -8 }, // 0x0145
|
||||
{ 1794, 5, 9, 7, 1, -6 }, // 0x0146
|
||||
{ 1800, 6, 11, 7, 1, -11 }, // 0x0147
|
||||
{ 1809, 5, 9, 7, 1, -9 }, // 0x0148
|
||||
{ 1815, 7, 9, 7, 0, -9 }, // 0x0149
|
||||
{ 1823, 6, 10, 7, 1, -8 }, // 0x014A
|
||||
{ 1831, 5, 8, 7, 1, -6 }, // 0x014B
|
||||
{ 1836, 6, 10, 7, 1, -10 }, // 0x014C
|
||||
{ 1844, 5, 8, 7, 1, -8 }, // 0x014D
|
||||
{ 1849, 6, 11, 7, 1, -11 }, // 0x014E
|
||||
{ 1858, 5, 9, 7, 1, -9 }, // 0x014F
|
||||
{ 1864, 6, 10, 7, 1, -10 }, // 0x0150
|
||||
{ 1872, 5, 9, 7, 1, -9 }, // 0x0151
|
||||
{ 1878, 6, 8, 7, 1, -8 }, // 0x0152
|
||||
{ 1884, 5, 6, 7, 1, -6 }, // 0x0153
|
||||
{ 1888, 7, 11, 7, 1, -11 }, // 0x0154
|
||||
{ 1898, 5, 9, 7, 2, -9 }, // 0x0155
|
||||
{ 1904, 7, 11, 7, 1, -8 }, // 0x0156
|
||||
{ 1914, 5, 9, 7, 1, -6 }, // 0x0157
|
||||
{ 1920, 7, 11, 7, 1, -11 }, // 0x0158
|
||||
{ 1930, 4, 9, 7, 2, -9 }, // 0x0159
|
||||
{ 1935, 6, 11, 7, 1, -11 }, // 0x015A
|
||||
{ 1944, 5, 9, 7, 1, -9 }, // 0x015B
|
||||
{ 1950, 6, 11, 7, 1, -11 }, // 0x015C
|
||||
{ 1959, 5, 9, 7, 1, -9 }, // 0x015D
|
||||
{ 1965, 6, 10, 7, 1, -8 }, // 0x015E
|
||||
{ 1973, 5, 8, 7, 1, -6 }, // 0x015F
|
||||
};
|
||||
|
||||
const GFXfont UiFont11pt PROGMEM = {
|
||||
(uint8_t *)UiFont11ptBitmaps,
|
||||
(GFXglyph *)UiFont11ptGlyphs,
|
||||
0x0020, 0x015F, 17
|
||||
};
|
||||
@@ -14,11 +14,13 @@ namespace {
|
||||
}
|
||||
};
|
||||
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, uint16_t bg = TFT_NAVY) {
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, bool active = false) {
|
||||
uint16_t bg = active ? TFT_GREEN : TFT_BLACK;
|
||||
uint16_t fg = active ? TFT_BLACK : TFT_GREEN;
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, bg);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_DARKGREY);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_GREEN);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, bg);
|
||||
tft.setTextColor(fg, bg);
|
||||
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
@@ -40,7 +42,7 @@ void run(TFT_eSPI& tft) {
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 10);
|
||||
tft.println(I18n::t(StringId::UNITS_TITLE));
|
||||
|
||||
@@ -49,8 +51,7 @@ void run(TFT_eSPI& tft) {
|
||||
|
||||
for (uint8_t i = 0; i < MODE_COUNT; i++) {
|
||||
modeRects[i] = rowRect(i);
|
||||
drawButton(tft, modeRects[i], I18n::t(labels[i]),
|
||||
(i == current) ? TFT_DARKGREEN : TFT_NAVY);
|
||||
drawButton(tft, modeRects[i], I18n::t(labels[i]), i == current);
|
||||
}
|
||||
|
||||
Rect backBtn = rowRect(MODE_COUNT);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "wifi_setup_screen.h"
|
||||
#include "touch_input.h"
|
||||
#include "config.h"
|
||||
#include "i18n.h"
|
||||
|
||||
namespace WifiManageScreen {
|
||||
|
||||
@@ -14,11 +15,12 @@ namespace {
|
||||
}
|
||||
};
|
||||
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, uint16_t bg = TFT_NAVY) {
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, bg);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_DARKGREY);
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, bool danger = false) {
|
||||
uint16_t accent = danger ? TFT_RED : TFT_GREEN;
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, TFT_BLACK);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, accent);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, bg);
|
||||
tft.setTextColor(accent, TFT_BLACK);
|
||||
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
@@ -32,9 +34,9 @@ void run(TFT_eSPI& tft) {
|
||||
bool done = false;
|
||||
while (!done) {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 10);
|
||||
tft.println("WiFi networks");
|
||||
tft.println(I18n::t(StringId::WIFI_NETWORKS_TITLE));
|
||||
|
||||
uint8_t count = WifiMgr::networkCount();
|
||||
int16_t y = 40;
|
||||
@@ -50,13 +52,13 @@ void run(TFT_eSPI& tft) {
|
||||
|
||||
if (i < count) {
|
||||
drawButton(tft, rowRect, WifiMgr::networkSsid(i));
|
||||
drawButton(tft, removeRect, "X", TFT_MAROON);
|
||||
drawButton(tft, removeRect, "X", true);
|
||||
} else {
|
||||
tft.fillRoundRect(rowRect.x, rowRect.y, rowRect.w, rowRect.h, 4, TFT_BLACK);
|
||||
tft.drawRoundRect(rowRect.x, rowRect.y, rowRect.w, rowRect.h, 4, TFT_DARKGREY);
|
||||
tft.drawRoundRect(rowRect.x, rowRect.y, rowRect.w, rowRect.h, 4, TFT_DARKGREEN);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
|
||||
tft.drawString("(empty)", rowRect.x + rowRect.w / 2, rowRect.y + rowRect.h / 2);
|
||||
tft.setTextColor(TFT_DARKGREEN, TFT_BLACK);
|
||||
tft.drawString(I18n::t(StringId::WIFI_EMPTY_SLOT), rowRect.x + rowRect.w / 2, rowRect.y + rowRect.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
y += ROW_H + ROW_GAP;
|
||||
@@ -65,12 +67,12 @@ void run(TFT_eSPI& tft) {
|
||||
Rect addBtn = {10, y, (int16_t)(Config::SCREEN_WIDTH - 20), 40};
|
||||
bool canAdd = count < Config::MAX_WIFI_NETWORKS;
|
||||
if (canAdd) {
|
||||
drawButton(tft, addBtn, "Add network");
|
||||
drawButton(tft, addBtn, I18n::t(StringId::WIFI_ADD_NETWORK));
|
||||
}
|
||||
y += 48;
|
||||
|
||||
Rect backBtn = {10, (int16_t)(Config::SCREEN_HEIGHT - 50), (int16_t)(Config::SCREEN_WIDTH - 20), 40};
|
||||
drawButton(tft, backBtn, "Back");
|
||||
drawButton(tft, backBtn, I18n::t(StringId::BACK));
|
||||
|
||||
TouchInput::Point tap;
|
||||
while (true) {
|
||||
|
||||
@@ -78,10 +78,6 @@ namespace {
|
||||
char passwordBuf[64] = {0};
|
||||
uint8_t passwordLen = 0;
|
||||
|
||||
// Shift-Verhalten wie am Handy: einmal antippen = NUR der naechste
|
||||
// Buchstabe wird gross geschrieben, danach automatisch wieder klein.
|
||||
// Zweimal schnell hintereinander antippen (Doppeltipp) = Feststelltaste
|
||||
// (bleibt an, bis erneut einmal angetippt wird).
|
||||
enum class ShiftState { Off, OneShot, Locked };
|
||||
ShiftState shiftState = ShiftState::Off;
|
||||
uint32_t lastShiftTapMs = 0;
|
||||
@@ -95,11 +91,12 @@ namespace {
|
||||
Rect cancelBtn = {Config::SCREEN_WIDTH - 34, 4, 30, 24};
|
||||
|
||||
void drawButton(TFT_eSPI& tft, const Rect& r, const String& label, bool highlighted = false) {
|
||||
uint16_t bg = highlighted ? TFT_DARKGREEN : TFT_NAVY;
|
||||
uint16_t bg = highlighted ? TFT_GREEN : TFT_BLACK;
|
||||
uint16_t fg = highlighted ? TFT_BLACK : TFT_GREEN;
|
||||
tft.fillRoundRect(r.x, r.y, r.w, r.h, 4, bg);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_DARKGREY);
|
||||
tft.drawRoundRect(r.x, r.y, r.w, r.h, 4, TFT_GREEN);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, bg);
|
||||
tft.setTextColor(fg, bg);
|
||||
tft.drawString(label, r.x + r.w / 2, r.y + r.h / 2);
|
||||
tft.setTextDatum(TL_DATUM);
|
||||
}
|
||||
@@ -134,9 +131,6 @@ namespace {
|
||||
bool upper = (shiftState != ShiftState::Off);
|
||||
passwordBuf[passwordLen++] = upper ? (char)toupper(k.ch) : k.ch;
|
||||
passwordBuf[passwordLen] = 0;
|
||||
// Nach genau einem Buchstaben automatisch wieder auf
|
||||
// klein zurueckfallen - AUSSER die Feststelltaste
|
||||
// (Doppeltipp) ist aktiv, die bleibt an.
|
||||
if (shiftState == ShiftState::OneShot) shiftState = ShiftState::Off;
|
||||
}
|
||||
break;
|
||||
@@ -145,13 +139,10 @@ namespace {
|
||||
bool isDoubleTap = (nowMs - lastShiftTapMs) <= SHIFT_DOUBLE_TAP_MS;
|
||||
lastShiftTapMs = nowMs;
|
||||
if (isDoubleTap) {
|
||||
// Doppeltipp: Feststelltaste an-/ausschalten.
|
||||
shiftState = (shiftState == ShiftState::Locked) ? ShiftState::Off : ShiftState::Locked;
|
||||
} else if (shiftState == ShiftState::Off) {
|
||||
// Einfacher Tipp: nur der naechste Buchstabe wird gross.
|
||||
shiftState = ShiftState::OneShot;
|
||||
} else {
|
||||
// Einfacher Tipp waehrend OneShot/Locked schaltet ab.
|
||||
shiftState = ShiftState::Off;
|
||||
}
|
||||
break;
|
||||
@@ -208,7 +199,7 @@ bool run(TFT_eSPI& tft) {
|
||||
WifiMgr::beginScan();
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setTextSize(1);
|
||||
tft.setCursor(10, 10);
|
||||
tft.println(I18n::t(StringId::WIFI_SCANNING));
|
||||
@@ -231,7 +222,7 @@ bool run(TFT_eSPI& tft) {
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setCursor(10, 10);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.println(ssidCount == 0 ? I18n::t(StringId::WIFI_NO_NETWORKS) : I18n::t(StringId::WIFI_SELECT));
|
||||
drawCancelButton(tft);
|
||||
}
|
||||
@@ -244,7 +235,7 @@ bool run(TFT_eSPI& tft) {
|
||||
stage = Stage::Done;
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setCursor(10, 10);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.println(I18n::t(StringId::WIFI_CONNECTED_BANG));
|
||||
delay(900);
|
||||
return true;
|
||||
@@ -254,7 +245,7 @@ bool run(TFT_eSPI& tft) {
|
||||
tft.setCursor(10, 10);
|
||||
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
tft.println(I18n::t(StringId::WIFI_CONNECTION_FAILED));
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 30);
|
||||
tft.println(I18n::t(StringId::WIFI_BACK_TO_LIST_MSG));
|
||||
delay(1400);
|
||||
@@ -319,7 +310,7 @@ bool run(TFT_eSPI& tft) {
|
||||
tft.setCursor(10, 10);
|
||||
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
tft.println(I18n::t(StringId::WIFI_ALREADY_3));
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 30);
|
||||
tft.println(I18n::t(StringId::WIFI_REMOVE_ONE_FIRST));
|
||||
delay(1600);
|
||||
@@ -330,7 +321,7 @@ bool run(TFT_eSPI& tft) {
|
||||
stage = Stage::Connecting;
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setCursor(10, 10);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.println(I18n::t(StringId::WIFI_CONNECTING));
|
||||
} else if (backBtn.contains(tap.x, tap.y)) {
|
||||
stage = Stage::PickSsid;
|
||||
@@ -363,16 +354,16 @@ bool run(TFT_eSPI& tft) {
|
||||
drawCancelButton(tft);
|
||||
} else if (stage == Stage::EnterPassword) {
|
||||
tft.fillRect(0, 0, Config::SCREEN_WIDTH, KB_TOP - 4, TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.setCursor(10, 6);
|
||||
tft.printf("%s%s", I18n::t(StringId::WIFI_LABEL_PREFIX), ssidList[selectedIndex].c_str());
|
||||
tft.setCursor(10, 22);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.println(I18n::t(StringId::WIFI_PASSWORD_LABEL));
|
||||
tft.fillRect(8, 38, Config::SCREEN_WIDTH - 16, 22, TFT_NAVY);
|
||||
tft.drawRect(8, 38, Config::SCREEN_WIDTH - 16, 22, TFT_DARKGREY);
|
||||
tft.fillRect(8, 38, Config::SCREEN_WIDTH - 16, 22, TFT_BLACK);
|
||||
tft.drawRect(8, 38, Config::SCREEN_WIDTH - 16, 22, TFT_GREEN);
|
||||
tft.setCursor(12, 44);
|
||||
tft.setTextColor(TFT_WHITE, TFT_NAVY);
|
||||
tft.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
tft.print(passwordBuf);
|
||||
|
||||
int16_t rowY0 = KB_TOP;
|
||||
|
||||
Reference in New Issue
Block a user