mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-23 19:20:41 +00:00
Namespacing and more moved methods
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#include "main.h"
|
||||
#include "target_specific.h"
|
||||
#include <OLEDDisplay.h>
|
||||
#include <RTC.h>
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_GPS
|
||||
|
||||
@@ -739,6 +740,322 @@ bool haveGlyphs(const char *str)
|
||||
// LOG_DEBUG("haveGlyphs=%d", have);
|
||||
return have;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the icon with extra info printed around the corners
|
||||
*/
|
||||
void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
const char *label = "BaseUI";
|
||||
display->setFont(FONT_SMALL);
|
||||
int textWidth = display->getStringWidth(label);
|
||||
int r = 3; // corner radius
|
||||
|
||||
if (SCREEN_WIDTH > 128) {
|
||||
// === ORIGINAL WIDE SCREEN LAYOUT (unchanged) ===
|
||||
int padding = 4;
|
||||
int boxWidth = max(icon_width, textWidth) + (padding * 2) + 16;
|
||||
int boxHeight = icon_height + FONT_HEIGHT_SMALL + (padding * 3) - 8;
|
||||
int boxX = x - 1 + (SCREEN_WIDTH - boxWidth) / 2;
|
||||
int boxY = y - 6 + (SCREEN_HEIGHT - boxHeight) / 2;
|
||||
|
||||
display->setColor(WHITE);
|
||||
display->fillRect(boxX + r, boxY, boxWidth - 2 * r, boxHeight);
|
||||
display->fillRect(boxX, boxY + r, boxWidth - 1, boxHeight - 2 * r);
|
||||
display->fillCircle(boxX + r, boxY + r, r); // Upper Left
|
||||
display->fillCircle(boxX + boxWidth - r - 1, boxY + r, r); // Upper Right
|
||||
display->fillCircle(boxX + r, boxY + boxHeight - r - 1, r); // Lower Left
|
||||
display->fillCircle(boxX + boxWidth - r - 1, boxY + boxHeight - r - 1, r); // Lower Right
|
||||
|
||||
display->setColor(BLACK);
|
||||
int iconX = boxX + (boxWidth - icon_width) / 2;
|
||||
int iconY = boxY + padding - 2;
|
||||
display->drawXbm(iconX, iconY, icon_width, icon_height, icon_bits);
|
||||
|
||||
int labelY = iconY + icon_height + padding;
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(x + SCREEN_WIDTH / 2 - 3, labelY, label);
|
||||
display->drawString(x + SCREEN_WIDTH / 2 - 2, labelY, label); // faux bold
|
||||
|
||||
} else {
|
||||
// === TIGHT SMALL SCREEN LAYOUT ===
|
||||
int iconY = y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - icon_height) / 2 + 2;
|
||||
iconY -= 4;
|
||||
|
||||
int labelY = iconY + icon_height - 2;
|
||||
|
||||
int boxWidth = max(icon_width, textWidth) + 4;
|
||||
int boxX = x + (SCREEN_WIDTH - boxWidth) / 2;
|
||||
int boxY = iconY - 1;
|
||||
int boxBottom = labelY + FONT_HEIGHT_SMALL - 2;
|
||||
int boxHeight = boxBottom - boxY;
|
||||
|
||||
display->setColor(WHITE);
|
||||
display->fillRect(boxX + r, boxY, boxWidth - 2 * r, boxHeight);
|
||||
display->fillRect(boxX, boxY + r, boxWidth - 1, boxHeight - 2 * r);
|
||||
display->fillCircle(boxX + r, boxY + r, r);
|
||||
display->fillCircle(boxX + boxWidth - r - 1, boxY + r, r);
|
||||
display->fillCircle(boxX + r, boxY + boxHeight - r - 1, r);
|
||||
display->fillCircle(boxX + boxWidth - r - 1, boxY + boxHeight - r - 1, r);
|
||||
|
||||
display->setColor(BLACK);
|
||||
int iconX = boxX + (boxWidth - icon_width) / 2;
|
||||
display->drawXbm(iconX, iconY, icon_width, icon_height, icon_bits);
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(x + SCREEN_WIDTH / 2, labelY, label);
|
||||
}
|
||||
|
||||
// === Footer and headers (shared) ===
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->setColor(WHITE);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
const char *title = "meshtastic.org";
|
||||
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
if (upperMsg)
|
||||
display->drawString(x + 0, y + 0, upperMsg);
|
||||
|
||||
char buf[25];
|
||||
snprintf(buf, sizeof(buf), "%s\n%s", xstr(APP_VERSION_SHORT),
|
||||
graphics::UIRenderer::haveGlyphs(owner.short_name) ? owner.short_name : "");
|
||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||
display->drawString(x + SCREEN_WIDTH, y + 0, buf);
|
||||
|
||||
screen->forceDisplay();
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
}
|
||||
|
||||
// ****************************
|
||||
// * My Position Screen *
|
||||
// ****************************
|
||||
void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
display->clear();
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// === Header ===
|
||||
graphics::drawCommonHeader(display, x, y);
|
||||
|
||||
// === Draw title ===
|
||||
const int highlightHeight = FONT_HEIGHT_SMALL - 1;
|
||||
const int textY = y + 1 + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
const char *titleStr = "GPS";
|
||||
const int centerX = x + SCREEN_WIDTH / 2;
|
||||
|
||||
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(centerX, textY, titleStr);
|
||||
if (config.display.heading_bold) {
|
||||
display->drawString(centerX + 1, textY, titleStr);
|
||||
}
|
||||
display->setColor(WHITE);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
// === First Row: My Location ===
|
||||
#if HAS_GPS
|
||||
bool origBold = config.display.heading_bold;
|
||||
config.display.heading_bold = false;
|
||||
|
||||
String Satelite_String = "Sat:";
|
||||
display->drawString(0, ((SCREEN_HEIGHT > 64) ? compactFirstLine : moreCompactFirstLine), Satelite_String);
|
||||
String displayLine = "";
|
||||
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
if (config.position.fixed_position) {
|
||||
displayLine = "Fixed GPS";
|
||||
} else {
|
||||
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
|
||||
}
|
||||
display->drawString(display->getStringWidth(Satelite_String) + 3,
|
||||
((SCREEN_HEIGHT > 64) ? compactFirstLine : moreCompactFirstLine), displayLine);
|
||||
} else {
|
||||
UIRenderer::drawGPS(display, display->getStringWidth(Satelite_String) + 3,
|
||||
((SCREEN_HEIGHT > 64) ? compactFirstLine : moreCompactFirstLine) + 3, gpsStatus);
|
||||
}
|
||||
|
||||
config.display.heading_bold = origBold;
|
||||
|
||||
// === Update GeoCoord ===
|
||||
geoCoord.updateCoords(int32_t(gpsStatus->getLatitude()), int32_t(gpsStatus->getLongitude()),
|
||||
int32_t(gpsStatus->getAltitude()));
|
||||
|
||||
// === Determine Compass Heading ===
|
||||
float heading;
|
||||
bool validHeading = false;
|
||||
|
||||
if (screen->hasHeading()) {
|
||||
heading = radians(screen->getHeading());
|
||||
validHeading = true;
|
||||
} else {
|
||||
heading = screen->estimatedHeading(geoCoord.getLatitude() * 1e-7, geoCoord.getLongitude() * 1e-7);
|
||||
validHeading = !isnan(heading);
|
||||
}
|
||||
|
||||
// If GPS is off, no need to display these parts
|
||||
if (displayLine != "GPS off" && displayLine != "No GPS") {
|
||||
|
||||
// === Second Row: Altitude ===
|
||||
String displayLine;
|
||||
displayLine = " Alt: " + String(geoCoord.getAltitude()) + "m";
|
||||
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL)
|
||||
displayLine = " Alt: " + String(geoCoord.getAltitude() * METERS_TO_FEET) + "ft";
|
||||
display->drawString(x, ((SCREEN_HEIGHT > 64) ? compactSecondLine : moreCompactSecondLine), displayLine);
|
||||
|
||||
// === Third Row: Latitude ===
|
||||
char latStr[32];
|
||||
snprintf(latStr, sizeof(latStr), " Lat: %.5f", geoCoord.getLatitude() * 1e-7);
|
||||
display->drawString(x, ((SCREEN_HEIGHT > 64) ? compactThirdLine : moreCompactThirdLine), latStr);
|
||||
|
||||
// === Fourth Row: Longitude ===
|
||||
char lonStr[32];
|
||||
snprintf(lonStr, sizeof(lonStr), " Lon: %.5f", geoCoord.getLongitude() * 1e-7);
|
||||
display->drawString(x, ((SCREEN_HEIGHT > 64) ? compactFourthLine : moreCompactFourthLine), lonStr);
|
||||
|
||||
// === Fifth Row: Date ===
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true);
|
||||
char datetimeStr[25];
|
||||
bool showTime = false; // set to true for full datetime
|
||||
UIRenderer::formatDateTime(datetimeStr, sizeof(datetimeStr), rtc_sec, display, showTime);
|
||||
char fullLine[40];
|
||||
snprintf(fullLine, sizeof(fullLine), " Date: %s", datetimeStr);
|
||||
display->drawString(0, ((SCREEN_HEIGHT > 64) ? compactFifthLine : moreCompactFifthLine), 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 = compactFirstLine;
|
||||
const int16_t bottomY = SCREEN_HEIGHT - (FONT_HEIGHT_SMALL - 1); // nav row height
|
||||
const int16_t usableHeight = bottomY - topY - 5;
|
||||
|
||||
int16_t compassRadius = usableHeight / 2;
|
||||
if (compassRadius < 8)
|
||||
compassRadius = 8;
|
||||
const int16_t compassDiam = compassRadius * 2;
|
||||
const int16_t compassX = x + SCREEN_WIDTH - compassRadius - 8;
|
||||
|
||||
// Center vertically and nudge down slightly to keep "N" clear of header
|
||||
const int16_t compassY = topY + (usableHeight / 2) + ((FONT_HEIGHT_SMALL - 1) / 2) + 2;
|
||||
|
||||
screen->drawNodeHeading(display, compassX, compassY, compassDiam, -heading);
|
||||
display->drawCircle(compassX, compassY, compassRadius);
|
||||
|
||||
// "N" label
|
||||
float northAngle = -heading;
|
||||
float radius = compassRadius;
|
||||
int16_t nX = compassX + (radius - 1) * sin(northAngle);
|
||||
int16_t nY = compassY - (radius - 1) * cos(northAngle);
|
||||
int16_t nLabelWidth = display->getStringWidth("N") + 2;
|
||||
int16_t nLabelHeightBox = FONT_HEIGHT_SMALL + 1;
|
||||
|
||||
display->setColor(BLACK);
|
||||
display->fillRect(nX - nLabelWidth / 2, nY - nLabelHeightBox / 2, nLabelWidth, nLabelHeightBox);
|
||||
display->setColor(WHITE);
|
||||
display->setFont(FONT_SMALL);
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(nX, nY - FONT_HEIGHT_SMALL / 2, "N");
|
||||
} 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 = ((SCREEN_HEIGHT > 64) ? compactFifthLine : moreCompactFifthLine) + FONT_HEIGHT_SMALL + 2;
|
||||
const int margin = 4;
|
||||
int availableHeight =
|
||||
#if defined(USE_EINK)
|
||||
SCREEN_HEIGHT - yBelowContent - 24; // Leave extra space for nav bar on E-Ink
|
||||
#else
|
||||
SCREEN_HEIGHT - yBelowContent - margin;
|
||||
#endif
|
||||
|
||||
if (availableHeight < FONT_HEIGHT_SMALL * 2)
|
||||
return;
|
||||
|
||||
int compassRadius = availableHeight / 2;
|
||||
if (compassRadius < 8)
|
||||
compassRadius = 8;
|
||||
if (compassRadius * 2 > SCREEN_WIDTH - 16)
|
||||
compassRadius = (SCREEN_WIDTH - 16) / 2;
|
||||
|
||||
int compassX = x + SCREEN_WIDTH / 2;
|
||||
int compassY = yBelowContent + availableHeight / 2;
|
||||
|
||||
screen->drawNodeHeading(display, compassX, compassY, compassRadius * 2, -heading);
|
||||
display->drawCircle(compassX, compassY, compassRadius);
|
||||
|
||||
// "N" label
|
||||
float northAngle = -heading;
|
||||
float radius = compassRadius;
|
||||
int16_t nX = compassX + (radius - 1) * sin(northAngle);
|
||||
int16_t nY = compassY - (radius - 1) * cos(northAngle);
|
||||
int16_t nLabelWidth = display->getStringWidth("N") + 2;
|
||||
int16_t nLabelHeightBox = FONT_HEIGHT_SMALL + 1;
|
||||
|
||||
display->setColor(BLACK);
|
||||
display->fillRect(nX - nLabelWidth / 2, nY - nLabelHeightBox / 2, nLabelWidth, nLabelHeightBox);
|
||||
display->setColor(WHITE);
|
||||
display->setFont(FONT_SMALL);
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(nX, nY - FONT_HEIGHT_SMALL / 2, "N");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USERPREFS_OEM_TEXT
|
||||
|
||||
void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
static const uint8_t xbm[] = USERPREFS_OEM_IMAGE_DATA;
|
||||
display->drawXbm(x + (SCREEN_WIDTH - USERPREFS_OEM_IMAGE_WIDTH) / 2,
|
||||
y + (SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM - USERPREFS_OEM_IMAGE_HEIGHT) / 2 + 2, USERPREFS_OEM_IMAGE_WIDTH,
|
||||
USERPREFS_OEM_IMAGE_HEIGHT, xbm);
|
||||
|
||||
switch (USERPREFS_OEM_FONT_SIZE) {
|
||||
case 0:
|
||||
display->setFont(FONT_SMALL);
|
||||
break;
|
||||
case 2:
|
||||
display->setFont(FONT_LARGE);
|
||||
break;
|
||||
default:
|
||||
display->setFont(FONT_MEDIUM);
|
||||
break;
|
||||
}
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
const char *title = USERPREFS_OEM_TEXT;
|
||||
display->drawString(x + getStringCenteredX(title), y + SCREEN_HEIGHT - FONT_HEIGHT_MEDIUM, title);
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// Draw region in upper left
|
||||
if (upperMsg)
|
||||
display->drawString(x + 0, y + 0, upperMsg);
|
||||
|
||||
// Draw version and shortname in upper right
|
||||
char buf[25];
|
||||
snprintf(buf, sizeof(buf), "%s\n%s", xstr(APP_VERSION_SHORT), haveGlyphs(owner.short_name) ? owner.short_name : "");
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||
display->drawString(x + SCREEN_WIDTH, y + 0, buf);
|
||||
screen->forceDisplay();
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT); // Restore left align, just to be kind to any other unsuspecting code
|
||||
}
|
||||
|
||||
void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
// Draw region in upper left
|
||||
const char *region = myRegion ? myRegion->name : NULL;
|
||||
drawOEMIconScreen(region, display, state, x, y);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace UIRenderer
|
||||
} // namespace graphics
|
||||
|
||||
|
||||
Reference in New Issue
Block a user