From 3eafb061ef3a83d1e10247ba79d36f6c1f2c6ff4 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Fri, 13 Jun 2025 12:16:17 -0500 Subject: [PATCH] Unify tft lineheights (#7033) * Create variable line heights based upon SCREEN_HEIGHT * Refactor textPositions into method -> getTextPositions * Update SharedUIDisplay.h --------- Co-authored-by: Jason P --- src/graphics/SharedUIDisplay.cpp | 32 ++++++++++ src/graphics/SharedUIDisplay.h | 20 +++++- src/graphics/draw/DebugRenderer.cpp | 52 ++++++++------- src/graphics/draw/NodeListRenderer.cpp | 18 +++--- src/graphics/draw/UIRenderer.cpp | 64 +++++++++---------- .../Telemetry/EnvironmentTelemetry.cpp | 6 +- src/modules/Telemetry/PowerTelemetry.cpp | 9 +-- src/modules/esp32/PaxcounterModule.cpp | 5 +- 8 files changed, 121 insertions(+), 85 deletions(-) diff --git a/src/graphics/SharedUIDisplay.cpp b/src/graphics/SharedUIDisplay.cpp index af79aadd5..8933be8c4 100644 --- a/src/graphics/SharedUIDisplay.cpp +++ b/src/graphics/SharedUIDisplay.cpp @@ -293,4 +293,36 @@ void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *ti display->setColor(WHITE); // Reset for other UI } +const int *getTextPositions(OLEDDisplay *display) +{ + static int textPositions[7]; // Static array that persists beyond function scope + + if (display->getHeight() >= 170) { + textPositions[0] = textZeroLine; + textPositions[1] = textFirstLine_large; + textPositions[2] = textSecondLine_large; + textPositions[3] = textThirdLine_large; + textPositions[4] = textFourthLine_large; + textPositions[5] = textFifthLine_large; + textPositions[6] = textSixthLine_large; + } else if (display->getHeight() > 64) { + textPositions[0] = textZeroLine; + textPositions[1] = textFirstLine_medium; + textPositions[2] = textSecondLine_medium; + textPositions[3] = textThirdLine_medium; + textPositions[4] = textFourthLine_medium; + textPositions[5] = textFifthLine_medium; + textPositions[6] = textSixthLine_medium; + } else { + textPositions[0] = textZeroLine; + textPositions[1] = textFirstLine; + textPositions[2] = textSecondLine; + textPositions[3] = textThirdLine; + textPositions[4] = textFourthLine; + textPositions[5] = textFifthLine; + textPositions[6] = textSixthLine; + } + return textPositions; +} + } // namespace graphics diff --git a/src/graphics/SharedUIDisplay.h b/src/graphics/SharedUIDisplay.h index b18bb1c4f..d98c22a7f 100644 --- a/src/graphics/SharedUIDisplay.h +++ b/src/graphics/SharedUIDisplay.h @@ -9,8 +9,8 @@ namespace graphics // Shared UI Helpers // ======================= -// Consistent Line Spacing #define textZeroLine 0 +// Consistent Line Spacing - this is standard for all display and the fall-back spacing #define textFirstLine ((FONT_HEIGHT_SMALL - 1) * 1) #define textSecondLine (textFirstLine + (FONT_HEIGHT_SMALL - 5)) #define textThirdLine (textSecondLine + (FONT_HEIGHT_SMALL - 5)) @@ -18,6 +18,22 @@ namespace graphics #define textFifthLine (textFourthLine + (FONT_HEIGHT_SMALL - 5)) #define textSixthLine (textFifthLine + (FONT_HEIGHT_SMALL - 5)) +// Consistent Line Spacing for devices like T114 and TEcho/ThinkNode M1 of devices +#define textFirstLine_medium ((FONT_HEIGHT_SMALL - 1) * 1) +#define textSecondLine_medium (textFirstLine_medium + FONT_HEIGHT_SMALL) +#define textThirdLine_medium (textSecondLine_medium + FONT_HEIGHT_SMALL) +#define textFourthLine_medium (textThirdLine_medium + FONT_HEIGHT_SMALL) +#define textFifthLine_medium (textFourthLine_medium + FONT_HEIGHT_SMALL) +#define textSixthLine_medium (textFifthLine_medium + FONT_HEIGHT_SMALL) + +// Consistent Line Spacing for devices like VisionMaster T190 +#define textFirstLine_large ((FONT_HEIGHT_SMALL - 1) * 1) +#define textSecondLine_large (textFirstLine_large + (FONT_HEIGHT_SMALL + 5)) +#define textThirdLine_large (textSecondLine_large + (FONT_HEIGHT_SMALL + 5)) +#define textFourthLine_large (textThirdLine_large + (FONT_HEIGHT_SMALL + 5)) +#define textFifthLine_large (textFourthLine_large + (FONT_HEIGHT_SMALL + 5)) +#define textSixthLine_large (textFifthLine_large + (FONT_HEIGHT_SMALL + 5)) + // Quick screen access #define SCREEN_WIDTH display->getWidth() #define SCREEN_HEIGHT display->getHeight() @@ -32,4 +48,6 @@ void drawRoundedHighlight(OLEDDisplay *display, int16_t x, int16_t y, int16_t w, // Shared battery/time/mail header void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const char *titleStr = ""); +const int *getTextPositions(OLEDDisplay *display); + } // namespace graphics diff --git a/src/graphics/draw/DebugRenderer.cpp b/src/graphics/draw/DebugRenderer.cpp index 4b9effb4c..ee8f12b3f 100644 --- a/src/graphics/draw/DebugRenderer.cpp +++ b/src/graphics/draw/DebugRenderer.cpp @@ -16,9 +16,6 @@ #include "mesh/generated/meshtastic/deviceonly.pb.h" #include "sleep.h" -const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, - textFourthLine, textFifthLine, textSixthLine}; - #if HAS_WIFI && !defined(ARCH_PORTDUINO) #include "mesh/wifi/WiFiAPClient.h" #include @@ -184,13 +181,13 @@ void drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, i const char *wifiName = config.network.wifi_ssid; if (WiFi.status() != WL_CONNECTED) { - display->drawString(x, textPositions[line++], "WiFi: Not Connected"); + display->drawString(x, getTextPositions(display)[line++], "WiFi: Not Connected"); } else { - display->drawString(x, textPositions[line++], "WiFi: Connected"); + display->drawString(x, getTextPositions(display)[line++], "WiFi: Connected"); char rssiStr[32]; snprintf(rssiStr, sizeof(rssiStr), "RSSI: %d", WiFi.RSSI()); - display->drawString(x, textPositions[line++], rssiStr); + display->drawString(x, getTextPositions(display)[line++], rssiStr); } /* @@ -208,36 +205,36 @@ void drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, i if (WiFi.status() == WL_CONNECTED) { char ipStr[64]; snprintf(ipStr, sizeof(ipStr), "IP: %s", WiFi.localIP().toString().c_str()); - display->drawString(x, textPositions[line++], ipStr); + display->drawString(x, getTextPositions(display)[line++], ipStr); } else if (WiFi.status() == WL_NO_SSID_AVAIL) { - display->drawString(x, textPositions[line++], "SSID Not Found"); + display->drawString(x, getTextPositions(display)[line++], "SSID Not Found"); } else if (WiFi.status() == WL_CONNECTION_LOST) { - display->drawString(x, textPositions[line++], "Connection Lost"); + display->drawString(x, getTextPositions(display)[line++], "Connection Lost"); } else if (WiFi.status() == WL_IDLE_STATUS) { - display->drawString(x, textPositions[line++], "Idle ... Reconnecting"); + display->drawString(x, getTextPositions(display)[line++], "Idle ... Reconnecting"); } else if (WiFi.status() == WL_CONNECT_FAILED) { - display->drawString(x, textPositions[line++], "Connection Failed"); + display->drawString(x, getTextPositions(display)[line++], "Connection Failed"); } #ifdef ARCH_ESP32 else { // Codes: // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html#wi-fi-reason-code - display->drawString(x, textPositions[line++], + display->drawString(x, getTextPositions(display)[line++], WiFi.disconnectReasonName(static_cast(getWifiDisconnectReason()))); } #else else { char statusStr[32]; snprintf(statusStr, sizeof(statusStr), "Unknown status: %d", WiFi.status()); - display->drawString(x, textPositions[line++], statusStr); + display->drawString(x, getTextPositions(display)[line++], statusStr); } #endif char ssidStr[64]; snprintf(ssidStr, sizeof(ssidStr), "SSID: %s", wifiName); - display->drawString(x, textPositions[line++], ssidStr); + display->drawString(x, getTextPositions(display)[line++], ssidStr); - display->drawString(x, textPositions[line++], "URL: http://meshtastic.local"); + display->drawString(x, getTextPositions(display)[line++], "URL: http://meshtastic.local"); /* Display a heartbeat pixel that blinks every time the frame is redrawn */ #ifdef SHOW_REDRAWS @@ -402,7 +399,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, graphics::drawCommonHeader(display, x, y, titleStr); // === First Row: Region / BLE Name === - graphics::UIRenderer::drawNodes(display, x, textPositions[line] + 2, nodeStatus, 0, true, ""); + graphics::UIRenderer::drawNodes(display, x, getTextPositions(display)[line] + 2, nodeStatus, 0, true, ""); uint8_t dmac[6]; char shortnameble[35]; @@ -411,7 +408,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, snprintf(shortnameble, sizeof(shortnameble), "BLE: %s", screen->ourId); int textWidth = display->getStringWidth(shortnameble); int nameX = (SCREEN_WIDTH - textWidth); - display->drawString(nameX, textPositions[line++], shortnameble); + display->drawString(nameX, getTextPositions(display)[line++], shortnameble); // === Second Row: Radio Preset === auto mode = DisplayFormatters::getModemPresetDisplayName(config.lora.modem_preset, false); @@ -422,7 +419,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, } textWidth = display->getStringWidth(regionradiopreset); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, textPositions[line++], regionradiopreset); + display->drawString(nameX, getTextPositions(display)[line++], regionradiopreset); // === Third Row: Frequency / ChanNum === char frequencyslot[35]; @@ -440,7 +437,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, } textWidth = display->getStringWidth(frequencyslot); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, textPositions[line++], frequencyslot); + display->drawString(nameX, getTextPositions(display)[line++], frequencyslot); // === Fourth Row: Channel Utilization === const char *chUtil = "ChUtil:"; @@ -448,7 +445,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, snprintf(chUtilPercentage, sizeof(chUtilPercentage), "%2.0f%%", airTime->channelUtilizationPercent()); int chUtil_x = (SCREEN_WIDTH > 128) ? display->getStringWidth(chUtil) + 10 : display->getStringWidth(chUtil) + 5; - int chUtil_y = textPositions[line] + 3; + int chUtil_y = getTextPositions(display)[line] + 3; int chutil_bar_width = (SCREEN_WIDTH > 128) ? 100 : 50; int chutil_bar_height = (SCREEN_WIDTH > 128) ? 12 : 7; @@ -459,7 +456,7 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int total_line_content_width = (chUtil_x + chutil_bar_width + display->getStringWidth(chUtilPercentage) + extraoffset) / 2; int starting_position = centerofscreen - total_line_content_width; - display->drawString(starting_position, textPositions[line++], chUtil); + display->drawString(starting_position, getTextPositions(display)[line++], chUtil); // Force 56% or higher to show a full 100% bar, text would still show related percent. if (chutil_percent >= 61) { @@ -496,7 +493,8 @@ void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, display->fillRect(starting_position + chUtil_x, chUtil_y, fillRight, chutil_bar_height); } - display->drawString(starting_position + chUtil_x + chutil_bar_width + extraoffset, textPositions[4], chUtilPercentage); + display->drawString(starting_position + chUtil_x + chutil_bar_width + extraoffset, getTextPositions(display)[4], + chUtilPercentage); } // **************************** @@ -544,10 +542,10 @@ void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, // Label display->setTextAlignment(TEXT_ALIGN_LEFT); - display->drawString(labelX, textPositions[line], label); + display->drawString(labelX, getTextPositions(display)[line], label); // Bar - int barY = textPositions[line] + (FONT_HEIGHT_SMALL - barHeight) / 2; + int barY = getTextPositions(display)[line] + (FONT_HEIGHT_SMALL - barHeight) / 2; display->setColor(WHITE); display->drawRect(barX, barY, adjustedBarWidth, barHeight); @@ -556,7 +554,7 @@ void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, // Value string display->setTextAlignment(TEXT_ALIGN_RIGHT); - display->drawString(SCREEN_WIDTH - 2, textPositions[line], combinedStr); + display->drawString(SCREEN_WIDTH - 2, getTextPositions(display)[line], combinedStr); }; // === Memory values === @@ -610,7 +608,7 @@ void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, snprintf(appversionstr, sizeof(appversionstr), "Ver.: %s", optstr(APP_VERSION)); int textWidth = display->getStringWidth(appversionstr); int nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, textPositions[line], appversionstr); + display->drawString(nameX, getTextPositions(display)[line], appversionstr); if (SCREEN_HEIGHT > 64 || (SCREEN_HEIGHT <= 64 && line < 4)) { // Only show uptime if the screen can show it line += 1; @@ -628,7 +626,7 @@ void drawMemoryUsage(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %um", mins); textWidth = display->getStringWidth(uptimeStr); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, textPositions[line], uptimeStr); + display->drawString(nameX, getTextPositions(display)[line], uptimeStr); } } } // namespace DebugRenderer diff --git a/src/graphics/draw/NodeListRenderer.cpp b/src/graphics/draw/NodeListRenderer.cpp index 070497198..a32ad6a29 100644 --- a/src/graphics/draw/NodeListRenderer.cpp +++ b/src/graphics/draw/NodeListRenderer.cpp @@ -12,9 +12,6 @@ #include "meshUtils.h" #include -const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, - textFourthLine, textFifthLine, textSixthLine}; - // Forward declarations for functions defined in Screen.cpp namespace graphics { @@ -620,7 +617,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t // 1. Long Name (always try to show first) const char *username = (node->has_user && node->user.long_name[0]) ? node->user.long_name : nullptr; if (username && line < 5) { - display->drawString(x, textPositions[line++], username); + display->drawString(x, getTextPositions(display)[line++], username); } // 2. Signal and Hops (combined on one line, if available) @@ -645,7 +642,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t } } if (signalHopsStr[0] && line < 5) { - display->drawString(x, textPositions[line++], signalHopsStr); + display->drawString(x, getTextPositions(display)[line++], signalHopsStr); } // 3. Heard (last seen, skip if node never seen) @@ -662,7 +659,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t : 'm')); } if (seenStr[0] && line < 5) { - display->drawString(x, textPositions[line++], seenStr); + display->drawString(x, getTextPositions(display)[line++], seenStr); } // 4. Uptime (only show if metric is present) @@ -682,7 +679,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t } } if (uptimeStr[0] && line < 5) { - display->drawString(x, textPositions[line++], uptimeStr); + display->drawString(x, getTextPositions(display)[line++], uptimeStr); } // 5. Distance (only if both nodes have GPS position) @@ -734,7 +731,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t } // Only display if we actually have a value! if (haveDistance && distStr[0] && line < 5) { - display->drawString(x, textPositions[line++], distStr); + display->drawString(x, getTextPositions(display)[line++], distStr); } // Compass rendering for different screen orientations @@ -745,7 +742,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t showCompass = true; } if (showCompass) { - const int16_t topY = textPositions[1]; + const int16_t topY = getTextPositions(display)[1]; const int16_t bottomY = SCREEN_HEIGHT - (FONT_HEIGHT_SMALL - 1); const int16_t usableHeight = bottomY - topY - 5; int16_t compassRadius = usableHeight / 2; @@ -775,7 +772,8 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t showCompass = true; } if (showCompass) { - int yBelowContent = (line > 1 && line <= 6) ? (textPositions[line - 1] + FONT_HEIGHT_SMALL + 2) : textPositions[1]; + int yBelowContent = (line > 1 && line <= 6) ? (getTextPositions(display)[line - 1] + FONT_HEIGHT_SMALL + 2) + : getTextPositions(display)[1]; const int margin = 4; #if defined(USE_EINK) diff --git a/src/graphics/draw/UIRenderer.cpp b/src/graphics/draw/UIRenderer.cpp index 14046e95b..00a1e40ce 100644 --- a/src/graphics/draw/UIRenderer.cpp +++ b/src/graphics/draw/UIRenderer.cpp @@ -18,9 +18,6 @@ #include #include -const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, - textFourthLine, textFifthLine, textSixthLine}; - #if !MESHTASTIC_EXCLUDE_GPS // External variables @@ -290,7 +287,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t const char *username = (node->has_user && node->user.long_name[0]) ? node->user.long_name : nullptr; if (username && line < 5) { // Print node's long name (e.g. "Backpack Node") - display->drawString(x, textPositions[line++], username); + display->drawString(x, getTextPositions(display)[line++], username); } // === 2. Signal and Hops (combined on one line, if available) === @@ -321,7 +318,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t } } if (signalHopsStr[0] && line < 5) { - display->drawString(x, textPositions[line++], signalHopsStr); + display->drawString(x, getTextPositions(display)[line++], signalHopsStr); } // === 3. Heard (last seen, skip if node never seen) === @@ -339,7 +336,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t : 'm')); } if (seenStr[0] && line < 5) { - display->drawString(x, textPositions[line++], seenStr); + display->drawString(x, getTextPositions(display)[line++], seenStr); } // === 4. Uptime (only show if metric is present) === @@ -358,7 +355,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t snprintf(uptimeStr, sizeof(uptimeStr), " Uptime: %um", mins); } if (uptimeStr[0] && line < 5) { - display->drawString(x, textPositions[line++], uptimeStr); + display->drawString(x, getTextPositions(display)[line++], uptimeStr); } // === 5. Distance (only if both nodes have GPS position) === @@ -418,7 +415,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t } // Only display if we actually have a value! if (haveDistance && distStr[0] && line < 5) { - display->drawString(x, textPositions[line++], distStr); + display->drawString(x, getTextPositions(display)[line++], distStr); } // --- Compass Rendering: landscape (wide) screens use the original side-aligned logic --- @@ -428,7 +425,7 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t showCompass = true; } if (showCompass) { - const int16_t topY = textPositions[1]; + const int16_t topY = getTextPositions(display)[1]; const int16_t bottomY = SCREEN_HEIGHT - (FONT_HEIGHT_SMALL - 1); const int16_t usableHeight = bottomY - topY - 5; int16_t compassRadius = usableHeight / 2; @@ -463,7 +460,8 @@ void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t showCompass = true; } if (showCompass) { - int yBelowContent = (line > 0 && line <= 5) ? (textPositions[line - 1] + FONT_HEIGHT_SMALL + 2) : textPositions[1]; + int yBelowContent = (line > 0 && line <= 5) ? (getTextPositions(display)[line - 1] + FONT_HEIGHT_SMALL + 2) + : getTextPositions(display)[1]; const int margin = 4; // --------- PATCH FOR EINK NAV BAR (ONLY CHANGE BELOW) ----------- #if defined(USE_EINK) @@ -534,7 +532,7 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t config.display.heading_bold = false; // Display Region and Channel Utilization - drawNodes(display, x + 1, textPositions[line] + 2, nodeStatus, -1, false, "online"); + drawNodes(display, x + 1, getTextPositions(display)[line] + 2, nodeStatus, -1, false, "online"); char uptimeStr[32] = ""; uint32_t uptime = millis() / 1000; @@ -548,7 +546,7 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t snprintf(uptimeStr, sizeof(uptimeStr), "Up: %uh %um", hours, mins); else snprintf(uptimeStr, sizeof(uptimeStr), "Up: %um", mins); - display->drawString(SCREEN_WIDTH - display->getStringWidth(uptimeStr), textPositions[line++], uptimeStr); + display->drawString(SCREEN_WIDTH - display->getStringWidth(uptimeStr), getTextPositions(display)[line++], uptimeStr); // === Second Row: Satellites and Voltage === config.display.heading_bold = false; @@ -561,9 +559,9 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t } else { displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off"; } - display->drawString(0, textPositions[line], displayLine); + display->drawString(0, getTextPositions(display)[line], displayLine); } else { - UIRenderer::drawGps(display, 0, textPositions[line], gpsStatus); + UIRenderer::drawGps(display, 0, getTextPositions(display)[line], gpsStatus); } #endif @@ -572,9 +570,9 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t int batV = powerStatus->getBatteryVoltageMv() / 1000; int batCv = (powerStatus->getBatteryVoltageMv() % 1000) / 10; snprintf(batStr, sizeof(batStr), "%01d.%02dV", batV, batCv); - display->drawString(x + SCREEN_WIDTH - display->getStringWidth(batStr), textPositions[line++], batStr); + display->drawString(x + SCREEN_WIDTH - display->getStringWidth(batStr), getTextPositions(display)[line++], batStr); } else { - display->drawString(x + SCREEN_WIDTH - display->getStringWidth("USB"), textPositions[line++], "USB"); + display->drawString(x + SCREEN_WIDTH - display->getStringWidth("USB"), getTextPositions(display)[line++], "USB"); } config.display.heading_bold = origBold; @@ -585,7 +583,7 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t snprintf(chUtilPercentage, sizeof(chUtilPercentage), "%2.0f%%", airTime->channelUtilizationPercent()); int chUtil_x = (SCREEN_WIDTH > 128) ? display->getStringWidth(chUtil) + 10 : display->getStringWidth(chUtil) + 5; - int chUtil_y = textPositions[line] + 3; + int chUtil_y = getTextPositions(display)[line] + 3; int chutil_bar_width = (SCREEN_WIDTH > 128) ? 100 : 50; if (!config.bluetooth.enabled) { @@ -605,7 +603,7 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t starting_position = 0; } - display->drawString(starting_position, textPositions[line], chUtil); + display->drawString(starting_position, getTextPositions(display)[line], chUtil); // Force 56% or higher to show a full 100% bar, text would still show related percent. if (chutil_percent >= 61) { @@ -642,10 +640,11 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t display->fillRect(starting_position + chUtil_x, chUtil_y, fillRight, chutil_bar_height); } - display->drawString(starting_position + chUtil_x + chutil_bar_width + extraoffset, textPositions[line], chUtilPercentage); + display->drawString(starting_position + chUtil_x + chutil_bar_width + extraoffset, getTextPositions(display)[line], + chUtilPercentage); if (!config.bluetooth.enabled) { - display->drawString(SCREEN_WIDTH - display->getStringWidth("BT off"), textPositions[line], "BT off"); + display->drawString(SCREEN_WIDTH - display->getStringWidth("BT off"), getTextPositions(display)[line], "BT off"); } line += 1; @@ -675,17 +674,18 @@ void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t } textWidth = display->getStringWidth(combinedName); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, ((rows == 4) ? textPositions[line++] : textPositions[line++]) + yOffset, combinedName); + display->drawString( + nameX, ((rows == 4) ? getTextPositions(display)[line++] : getTextPositions(display)[line++]) + yOffset, combinedName); } else { // === LongName Centered === textWidth = display->getStringWidth(longName); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, textPositions[line++], longName); + display->drawString(nameX, getTextPositions(display)[line++], longName); // === ShortName Centered === textWidth = display->getStringWidth(shortnameble); nameX = (SCREEN_WIDTH - textWidth) / 2; - display->drawString(nameX, textPositions[line++], shortnameble); + display->drawString(nameX, getTextPositions(display)[line++], shortnameble); } } @@ -952,10 +952,10 @@ void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *stat displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off"; } int yOffset = (SCREEN_WIDTH > 128) ? 3 : 1; - display->drawXbm(x + 1, textPositions[line] + yOffset, imgSatellite_width, imgSatellite_height, imgSatellite); - display->drawString(x + 11, textPositions[line++], displayLine); + display->drawXbm(x + 1, getTextPositions(display)[line] + yOffset, imgSatellite_width, imgSatellite_height, imgSatellite); + display->drawString(x + 11, getTextPositions(display)[line++], displayLine); } else { - UIRenderer::drawGps(display, 0, textPositions[line++], gpsStatus); + UIRenderer::drawGps(display, 0, getTextPositions(display)[line++], gpsStatus); } config.display.heading_bold = origBold; @@ -986,17 +986,17 @@ void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *stat } else { snprintf(DisplayLineTwo, sizeof(DisplayLineTwo), " Alt: %.0im", geoCoord.getAltitude()); } - display->drawString(x, textPositions[line++], DisplayLineTwo); + display->drawString(x, getTextPositions(display)[line++], DisplayLineTwo); // === Third Row: Latitude === char latStr[32]; snprintf(latStr, sizeof(latStr), " Lat: %.5f", geoCoord.getLatitude() * 1e-7); - display->drawString(x, textPositions[line++], latStr); + display->drawString(x, getTextPositions(display)[line++], latStr); // === Fourth Row: Longitude === char lonStr[32]; snprintf(lonStr, sizeof(lonStr), " Lon: %.5f", geoCoord.getLongitude() * 1e-7); - display->drawString(x, textPositions[line++], lonStr); + display->drawString(x, getTextPositions(display)[line++], lonStr); // === Fifth Row: Date === uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); @@ -1005,14 +1005,14 @@ void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *stat UIRenderer::formatDateTime(datetimeStr, sizeof(datetimeStr), rtc_sec, display, showTime); char fullLine[40]; snprintf(fullLine, sizeof(fullLine), " Date: %s", datetimeStr); - display->drawString(0, textPositions[line++], fullLine); + display->drawString(0, getTextPositions(display)[line++], fullLine); } // === Draw Compass if heading is valid === if (validHeading) { // --- Compass Rendering: landscape (wide) screens use original side-aligned logic --- if (SCREEN_WIDTH > SCREEN_HEIGHT) { - const int16_t topY = textPositions[1]; + const int16_t topY = getTextPositions(display)[1]; const int16_t bottomY = SCREEN_HEIGHT - (FONT_HEIGHT_SMALL - 1); // nav row height const int16_t usableHeight = bottomY - topY - 5; @@ -1045,7 +1045,7 @@ void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *stat } else { // Portrait or square: put compass at the bottom and centered, scaled to fit available space // For E-Ink screens, account for navigation bar at the bottom! - int yBelowContent = textPositions[5] + FONT_HEIGHT_SMALL + 2; + int yBelowContent = getTextPositions(display)[5] + FONT_HEIGHT_SMALL + 2; const int margin = 4; int availableHeight = #if defined(USE_EINK) diff --git a/src/modules/Telemetry/EnvironmentTelemetry.cpp b/src/modules/Telemetry/EnvironmentTelemetry.cpp index 33bc98392..846767ab0 100644 --- a/src/modules/Telemetry/EnvironmentTelemetry.cpp +++ b/src/modules/Telemetry/EnvironmentTelemetry.cpp @@ -20,10 +20,6 @@ #include "sleep.h" #include "target_specific.h" #include -#include - -const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, - textFourthLine, textFifthLine, textSixthLine}; #if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR_EXTERNAL @@ -356,7 +352,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt // === Row spacing setup === const int rowHeight = FONT_HEIGHT_SMALL - 4; - int currentY = textPositions[line++]; + int currentY = graphics::getTextPositions(display)[line++]; // === Show "No Telemetry" if no data available === if (!lastMeasurementPacket) { diff --git a/src/modules/Telemetry/PowerTelemetry.cpp b/src/modules/Telemetry/PowerTelemetry.cpp index 86869007a..df1505226 100644 --- a/src/modules/Telemetry/PowerTelemetry.cpp +++ b/src/modules/Telemetry/PowerTelemetry.cpp @@ -16,9 +16,6 @@ #include "sleep.h" #include "target_specific.h" -const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, - textFourthLine, textFifthLine, textSixthLine}; - #define FAILED_STATE_SENSOR_READ_MULTIPLIER 10 #define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true @@ -125,7 +122,7 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s if (lastMeasurementPacket == nullptr) { // In case of no valid packet, display "Power Telemetry", "No measurement" - display->drawString(x, textPositions[line++], "No measurement"); + display->drawString(x, graphics::getTextPositions(display)[line++], "No measurement"); return; } @@ -136,7 +133,7 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s const meshtastic_Data &p = lastMeasurementPacket->decoded; if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, &meshtastic_Telemetry_msg, &lastMeasurement)) { - display->drawString(x, textPositions[line++], "Measurement Error"); + display->drawString(x, graphics::getTextPositions(display)[line++], "Measurement Error"); LOG_ERROR("Unable to decode last packet"); return; } @@ -144,7 +141,7 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s // Display "Pow. From: ..." char fromStr[64]; snprintf(fromStr, sizeof(fromStr), "Pow. From: %s (%us)", lastSender, agoSecs); - display->drawString(x, textPositions[line++], fromStr); + display->drawString(x, graphics::getTextPositions(display)[line++], fromStr); // Display current and voltage based on ...power_metrics.has_[channel/voltage/current]... flags const auto &m = lastMeasurement.variant.power_metrics; diff --git a/src/modules/esp32/PaxcounterModule.cpp b/src/modules/esp32/PaxcounterModule.cpp index dd9ab195d..df566ee28 100644 --- a/src/modules/esp32/PaxcounterModule.cpp +++ b/src/modules/esp32/PaxcounterModule.cpp @@ -117,9 +117,6 @@ int32_t PaxcounterModule::runOnce() #include "graphics/ScreenFonts.h" #include "graphics/SharedUIDisplay.h" -const int textPositions[7] = {textZeroLine, textFirstLine, textSecondLine, textThirdLine, - textFourthLine, textFifthLine, textSixthLine}; - void PaxcounterModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { display->clear(); @@ -141,7 +138,7 @@ void PaxcounterModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(FONT_SMALL); - display->drawStringf(display->getWidth() / 2 + x, textPositions[line++], buffer, "WiFi: %d\nBLE: %d\nUptime: %ds", + display->drawStringf(display->getWidth() / 2 + x, getTextPositions(display)[line++], buffer, "WiFi: %d\nBLE: %d\nUptime: %ds", count_from_libpax.wifi_count, count_from_libpax.ble_count, millis() / 1000); } #endif // HAS_SCREEN