add a .clang-format file (#9154)

This commit is contained in:
Jorropo
2026-01-03 21:19:24 +01:00
committed by GitHub
parent abab6ce815
commit 0d11331d18
771 changed files with 77752 additions and 83184 deletions

View File

@@ -12,11 +12,9 @@
#include "nimble/NimbleBluetooth.h"
#endif
namespace graphics
{
namespace graphics {
namespace ClockRenderer
{
namespace ClockRenderer {
// Segment bitmaps for numerals 0-9 stored in flash to save RAM.
// Each row is a digit, each column is a segment state (1 = on, 0 = off).
@@ -43,436 +41,426 @@ static const uint8_t PROGMEM digitSegments[10][7] = {
{1, 1, 1, 1, 0, 1, 1} // 9
};
void drawSegmentedDisplayColon(OLEDDisplay *display, int x, int y, float scale)
{
uint16_t segmentWidth = SEGMENT_WIDTH * scale;
uint16_t segmentHeight = SEGMENT_HEIGHT * scale;
void drawSegmentedDisplayColon(OLEDDisplay *display, int x, int y, float scale) {
uint16_t segmentWidth = SEGMENT_WIDTH * scale;
uint16_t segmentHeight = SEGMENT_HEIGHT * scale;
uint16_t cellHeight = (segmentWidth * 2) + (segmentHeight * 3) + 8;
uint16_t cellHeight = (segmentWidth * 2) + (segmentHeight * 3) + 8;
uint16_t topAndBottomX = x + static_cast<uint16_t>(4 * scale);
uint16_t topAndBottomX = x + static_cast<uint16_t>(4 * scale);
uint16_t quarterCellHeight = cellHeight / 4;
uint16_t quarterCellHeight = cellHeight / 4;
uint16_t topY = y + quarterCellHeight;
uint16_t bottomY = y + (quarterCellHeight * 3);
uint16_t topY = y + quarterCellHeight;
uint16_t bottomY = y + (quarterCellHeight * 3);
display->fillRect(topAndBottomX, topY, segmentHeight, segmentHeight);
display->fillRect(topAndBottomX, bottomY, segmentHeight, segmentHeight);
display->fillRect(topAndBottomX, topY, segmentHeight, segmentHeight);
display->fillRect(topAndBottomX, bottomY, segmentHeight, segmentHeight);
}
void drawSegmentedDisplayCharacter(OLEDDisplay *display, int x, int y, uint8_t number, float scale)
{
// Read 7-segment pattern for the digit from flash
uint8_t seg[7];
for (uint8_t i = 0; i < 7; i++) {
seg[i] = pgm_read_byte(&digitSegments[number][i]);
void drawSegmentedDisplayCharacter(OLEDDisplay *display, int x, int y, uint8_t number, float scale) {
// Read 7-segment pattern for the digit from flash
uint8_t seg[7];
for (uint8_t i = 0; i < 7; i++) {
seg[i] = pgm_read_byte(&digitSegments[number][i]);
}
uint16_t segmentWidth = SEGMENT_WIDTH * scale;
uint16_t segmentHeight = SEGMENT_HEIGHT * scale;
// Precompute segment positions
uint16_t segmentOneX = x + segmentHeight + 2;
uint16_t segmentOneY = y;
uint16_t segmentTwoX = segmentOneX + segmentWidth + 2;
uint16_t segmentTwoY = segmentOneY + segmentHeight + 2;
uint16_t segmentThreeX = segmentTwoX;
uint16_t segmentThreeY = segmentTwoY + segmentWidth + 2 + segmentHeight + 2;
uint16_t segmentFourX = segmentOneX;
uint16_t segmentFourY = segmentThreeY + segmentWidth + 2;
uint16_t segmentFiveX = x;
uint16_t segmentFiveY = segmentThreeY;
uint16_t segmentSixX = x;
uint16_t segmentSixY = segmentTwoY;
uint16_t segmentSevenX = segmentOneX;
uint16_t segmentSevenY = segmentTwoY + segmentWidth + 2;
// Draw only the active segments
if (seg[0])
drawHorizontalSegment(display, segmentOneX, segmentOneY, segmentWidth, segmentHeight);
if (seg[1])
drawVerticalSegment(display, segmentTwoX, segmentTwoY, segmentWidth, segmentHeight);
if (seg[2])
drawVerticalSegment(display, segmentThreeX, segmentThreeY, segmentWidth, segmentHeight);
if (seg[3])
drawHorizontalSegment(display, segmentFourX, segmentFourY, segmentWidth, segmentHeight);
if (seg[4])
drawVerticalSegment(display, segmentFiveX, segmentFiveY, segmentWidth, segmentHeight);
if (seg[5])
drawVerticalSegment(display, segmentSixX, segmentSixY, segmentWidth, segmentHeight);
if (seg[6])
drawHorizontalSegment(display, segmentSevenX, segmentSevenY, segmentWidth, segmentHeight);
}
void drawHorizontalSegment(OLEDDisplay *display, int x, int y, int width, int height) {
int halfHeight = height / 2;
// draw central rectangle
display->fillRect(x, y, width, height);
// draw end triangles
display->fillTriangle(x, y, x, y + height - 1, x - halfHeight, y + halfHeight);
display->fillTriangle(x + width, y, x + width + halfHeight, y + halfHeight, x + width, y + height - 1);
}
void drawVerticalSegment(OLEDDisplay *display, int x, int y, int width, int height) {
int halfHeight = height / 2;
// draw central rectangle
display->fillRect(x, y, height, width);
// draw end triangles
display->fillTriangle(x + halfHeight, y - halfHeight, x + height - 1, y, x, y);
display->fillTriangle(x, y + width, x + height - 1, y + width, x + halfHeight, y + width + halfHeight);
}
void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
display->clear();
display->setTextAlignment(TEXT_ALIGN_LEFT);
// === Set Title, Blank for Clock
const char *titleStr = "";
// === Header ===
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // Display local timezone
char timeString[16];
int hour = 0;
int minute = 0;
int second = 0;
if (rtc_sec > 0) {
long hms = rtc_sec % SEC_PER_DAY;
hms = (hms + SEC_PER_DAY) % SEC_PER_DAY;
hour = hms / SEC_PER_HOUR;
minute = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
second = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
}
bool isPM = hour >= 12;
if (config.display.use_12h_clock) {
hour %= 12;
if (hour == 0) {
hour = 12;
}
snprintf(timeString, sizeof(timeString), "%d:%02d", hour, minute);
} else {
snprintf(timeString, sizeof(timeString), "%02d:%02d", hour, minute);
}
// Format seconds string
char secondString[8];
snprintf(secondString, sizeof(secondString), "%02d", second);
static bool scaleInitialized = false;
static float scale = 0.75f;
static float segmentWidth = SEGMENT_WIDTH * 0.75f;
static float segmentHeight = SEGMENT_HEIGHT * 0.75f;
if (!scaleInitialized) {
float screenwidth_target_ratio = 0.80f; // Target 80% of display width (adjustable)
float max_scale = 3.5f; // Safety limit to avoid runaway scaling
float step = 0.05f; // Step increment per iteration
float target_width = display->getWidth() * screenwidth_target_ratio;
float target_height =
display->getHeight() - ((currentResolution == ScreenResolution::High)
? 46
: 33); // Be careful adjusting this number, we have to account for header and the text under the time
float calculated_width_size = 0.0f;
float calculated_height_size = 0.0f;
while (true) {
segmentWidth = SEGMENT_WIDTH * scale;
segmentHeight = SEGMENT_HEIGHT * scale;
calculated_width_size = segmentHeight + ((segmentWidth + (segmentHeight * 2) + 4) * 4);
calculated_height_size = segmentHeight + ((segmentHeight + (segmentHeight * 2) + 4) * 2);
if (calculated_width_size >= target_width || calculated_height_size >= target_height || scale >= max_scale) {
break;
}
scale += step;
}
uint16_t segmentWidth = SEGMENT_WIDTH * scale;
uint16_t segmentHeight = SEGMENT_HEIGHT * scale;
// Precompute segment positions
uint16_t segmentOneX = x + segmentHeight + 2;
uint16_t segmentOneY = y;
uint16_t segmentTwoX = segmentOneX + segmentWidth + 2;
uint16_t segmentTwoY = segmentOneY + segmentHeight + 2;
uint16_t segmentThreeX = segmentTwoX;
uint16_t segmentThreeY = segmentTwoY + segmentWidth + 2 + segmentHeight + 2;
uint16_t segmentFourX = segmentOneX;
uint16_t segmentFourY = segmentThreeY + segmentWidth + 2;
uint16_t segmentFiveX = x;
uint16_t segmentFiveY = segmentThreeY;
uint16_t segmentSixX = x;
uint16_t segmentSixY = segmentTwoY;
uint16_t segmentSevenX = segmentOneX;
uint16_t segmentSevenY = segmentTwoY + segmentWidth + 2;
// Draw only the active segments
if (seg[0])
drawHorizontalSegment(display, segmentOneX, segmentOneY, segmentWidth, segmentHeight);
if (seg[1])
drawVerticalSegment(display, segmentTwoX, segmentTwoY, segmentWidth, segmentHeight);
if (seg[2])
drawVerticalSegment(display, segmentThreeX, segmentThreeY, segmentWidth, segmentHeight);
if (seg[3])
drawHorizontalSegment(display, segmentFourX, segmentFourY, segmentWidth, segmentHeight);
if (seg[4])
drawVerticalSegment(display, segmentFiveX, segmentFiveY, segmentWidth, segmentHeight);
if (seg[5])
drawVerticalSegment(display, segmentSixX, segmentSixY, segmentWidth, segmentHeight);
if (seg[6])
drawHorizontalSegment(display, segmentSevenX, segmentSevenY, segmentWidth, segmentHeight);
}
void drawHorizontalSegment(OLEDDisplay *display, int x, int y, int width, int height)
{
int halfHeight = height / 2;
// draw central rectangle
display->fillRect(x, y, width, height);
// draw end triangles
display->fillTriangle(x, y, x, y + height - 1, x - halfHeight, y + halfHeight);
display->fillTriangle(x + width, y, x + width + halfHeight, y + halfHeight, x + width, y + height - 1);
}
void drawVerticalSegment(OLEDDisplay *display, int x, int y, int width, int height)
{
int halfHeight = height / 2;
// draw central rectangle
display->fillRect(x, y, height, width);
// draw end triangles
display->fillTriangle(x + halfHeight, y - halfHeight, x + height - 1, y, x, y);
display->fillTriangle(x, y + width, x + height - 1, y + width, x + halfHeight, y + width + halfHeight);
}
void drawDigitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
display->clear();
display->setTextAlignment(TEXT_ALIGN_LEFT);
// === Set Title, Blank for Clock
const char *titleStr = "";
// === Header ===
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // Display local timezone
char timeString[16];
int hour = 0;
int minute = 0;
int second = 0;
if (rtc_sec > 0) {
long hms = rtc_sec % SEC_PER_DAY;
hms = (hms + SEC_PER_DAY) % SEC_PER_DAY;
hour = hms / SEC_PER_HOUR;
minute = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
second = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
// If we overshot width, back off one step and recompute segment sizes
if (calculated_width_size > target_width || calculated_height_size > target_height) {
scale -= step;
segmentWidth = SEGMENT_WIDTH * scale;
segmentHeight = SEGMENT_HEIGHT * scale;
}
bool isPM = hour >= 12;
if (config.display.use_12h_clock) {
hour %= 12;
if (hour == 0) {
hour = 12;
}
snprintf(timeString, sizeof(timeString), "%d:%02d", hour, minute);
scaleInitialized = true;
}
// calculate hours:minutes string width
size_t len = strlen(timeString);
uint16_t timeStringWidth = len * 5;
for (size_t i = 0; i < len; i++) {
char character = timeString[i];
if (character == ':') {
timeStringWidth += segmentHeight;
} else {
snprintf(timeString, sizeof(timeString), "%02d:%02d", hour, minute);
timeStringWidth += segmentWidth + (segmentHeight * 2) + 4;
}
}
uint16_t hourMinuteTextX = (display->getWidth() / 2) - (timeStringWidth / 2);
uint16_t startingHourMinuteTextX = hourMinuteTextX;
uint16_t hourMinuteTextY = (display->getHeight() / 2) - (((segmentWidth * 2) + (segmentHeight * 3) + 8) / 2) + 2;
// iterate over characters in hours:minutes string and draw segmented characters
for (size_t i = 0; i < len; i++) {
char character = timeString[i];
if (character == ':') {
drawSegmentedDisplayColon(display, hourMinuteTextX, hourMinuteTextY, scale);
hourMinuteTextX += segmentHeight + 6;
if (scale >= 2.0f) {
hourMinuteTextX += (uint16_t)(4.5f * scale);
}
} else {
drawSegmentedDisplayCharacter(display, hourMinuteTextX, hourMinuteTextY, character - '0', scale);
hourMinuteTextX += segmentWidth + (segmentHeight * 2) + 4;
}
// Format seconds string
char secondString[8];
snprintf(secondString, sizeof(secondString), "%02d", second);
hourMinuteTextX += 5;
}
static bool scaleInitialized = false;
static float scale = 0.75f;
static float segmentWidth = SEGMENT_WIDTH * 0.75f;
static float segmentHeight = SEGMENT_HEIGHT * 0.75f;
if (!scaleInitialized) {
float screenwidth_target_ratio = 0.80f; // Target 80% of display width (adjustable)
float max_scale = 3.5f; // Safety limit to avoid runaway scaling
float step = 0.05f; // Step increment per iteration
float target_width = display->getWidth() * screenwidth_target_ratio;
float target_height =
display->getHeight() -
((currentResolution == ScreenResolution::High)
? 46
: 33); // Be careful adjusting this number, we have to account for header and the text under the time
float calculated_width_size = 0.0f;
float calculated_height_size = 0.0f;
while (true) {
segmentWidth = SEGMENT_WIDTH * scale;
segmentHeight = SEGMENT_HEIGHT * scale;
calculated_width_size = segmentHeight + ((segmentWidth + (segmentHeight * 2) + 4) * 4);
calculated_height_size = segmentHeight + ((segmentHeight + (segmentHeight * 2) + 4) * 2);
if (calculated_width_size >= target_width || calculated_height_size >= target_height || scale >= max_scale) {
break;
}
scale += step;
}
// If we overshot width, back off one step and recompute segment sizes
if (calculated_width_size > target_width || calculated_height_size > target_height) {
scale -= step;
segmentWidth = SEGMENT_WIDTH * scale;
segmentHeight = SEGMENT_HEIGHT * scale;
}
scaleInitialized = true;
}
// calculate hours:minutes string width
size_t len = strlen(timeString);
uint16_t timeStringWidth = len * 5;
for (size_t i = 0; i < len; i++) {
char character = timeString[i];
if (character == ':') {
timeStringWidth += segmentHeight;
} else {
timeStringWidth += segmentWidth + (segmentHeight * 2) + 4;
}
}
uint16_t hourMinuteTextX = (display->getWidth() / 2) - (timeStringWidth / 2);
uint16_t startingHourMinuteTextX = hourMinuteTextX;
uint16_t hourMinuteTextY = (display->getHeight() / 2) - (((segmentWidth * 2) + (segmentHeight * 3) + 8) / 2) + 2;
// iterate over characters in hours:minutes string and draw segmented characters
for (size_t i = 0; i < len; i++) {
char character = timeString[i];
if (character == ':') {
drawSegmentedDisplayColon(display, hourMinuteTextX, hourMinuteTextY, scale);
hourMinuteTextX += segmentHeight + 6;
if (scale >= 2.0f) {
hourMinuteTextX += (uint16_t)(4.5f * scale);
}
} else {
drawSegmentedDisplayCharacter(display, hourMinuteTextX, hourMinuteTextY, character - '0', scale);
hourMinuteTextX += segmentWidth + (segmentHeight * 2) + 4;
}
hourMinuteTextX += 5;
}
// draw seconds string + AM/PM
display->setFont(FONT_SMALL);
int xOffset = -1;
// draw seconds string + AM/PM
display->setFont(FONT_SMALL);
int xOffset = -1;
if (currentResolution == ScreenResolution::High) {
xOffset = 0;
}
if (hour >= 10) {
if (currentResolution == ScreenResolution::High) {
xOffset = 0;
}
if (hour >= 10) {
if (currentResolution == ScreenResolution::High) {
xOffset += 32;
} else {
xOffset += 18;
}
xOffset += 32;
} else {
xOffset += 18;
}
}
if (config.display.use_12h_clock) {
display->drawString(startingHourMinuteTextX + xOffset, (display->getHeight() - hourMinuteTextY) - 1, isPM ? "pm" : "am");
}
if (config.display.use_12h_clock) {
display->drawString(startingHourMinuteTextX + xOffset, (display->getHeight() - hourMinuteTextY) - 1, isPM ? "pm" : "am");
}
#ifndef USE_EINK
xOffset = (currentResolution == ScreenResolution::High) ? 18 : 10;
if (scale >= 2.0f) {
xOffset -= (int)(4.5f * scale);
}
display->drawString(startingHourMinuteTextX + timeStringWidth - xOffset, (display->getHeight() - hourMinuteTextY) - 1,
secondString);
xOffset = (currentResolution == ScreenResolution::High) ? 18 : 10;
if (scale >= 2.0f) {
xOffset -= (int)(4.5f * scale);
}
display->drawString(startingHourMinuteTextX + timeStringWidth - xOffset, (display->getHeight() - hourMinuteTextY) - 1, secondString);
#endif
graphics::drawCommonFooter(display, x, y);
graphics::drawCommonFooter(display, x, y);
}
// Draw an analog clock
void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{
display->setTextAlignment(TEXT_ALIGN_LEFT);
// === Set Title, Blank for Clock
const char *titleStr = "";
// === Header ===
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) {
display->setTextAlignment(TEXT_ALIGN_LEFT);
// === Set Title, Blank for Clock
const char *titleStr = "";
// === Header ===
graphics::drawCommonHeader(display, x, y, titleStr, true, true);
// clock face center coordinates
int16_t centerX = display->getWidth() / 2;
int16_t centerY = display->getHeight() / 2;
// clock face center coordinates
int16_t centerX = display->getWidth() / 2;
int16_t centerY = display->getHeight() / 2;
// clock face radius
int16_t radius = (std::min(display->getWidth(), display->getHeight()) / 2) * 0.9;
// clock face radius
int16_t radius = (std::min(display->getWidth(), display->getHeight()) / 2) * 0.9;
#ifdef T_WATCH_S3
radius = (display->getWidth() / 2) * 0.8;
radius = (display->getWidth() / 2) * 0.8;
#endif
// noon (0 deg) coordinates (outermost circle)
int16_t noonX = centerX;
int16_t noonY = centerY - radius;
// noon (0 deg) coordinates (outermost circle)
int16_t noonX = centerX;
int16_t noonY = centerY - radius;
// second hand radius and y coordinate (outermost circle)
int16_t secondHandNoonY = noonY + 1;
// second hand radius and y coordinate (outermost circle)
int16_t secondHandNoonY = noonY + 1;
// tick mark outer y coordinate; (first nested circle)
int16_t tickMarkOuterNoonY = secondHandNoonY;
// tick mark outer y coordinate; (first nested circle)
int16_t tickMarkOuterNoonY = secondHandNoonY;
double secondsTickMarkInnerNoonY = noonY + ((currentResolution == ScreenResolution::High) ? 8 : 4);
double hoursTickMarkInnerNoonY = noonY + ((currentResolution == ScreenResolution::High) ? 16 : 6);
double secondsTickMarkInnerNoonY = noonY + ((currentResolution == ScreenResolution::High) ? 8 : 4);
double hoursTickMarkInnerNoonY = noonY + ((currentResolution == ScreenResolution::High) ? 16 : 6);
// minute hand y coordinate
int16_t minuteHandNoonY = secondsTickMarkInnerNoonY + 4;
// minute hand y coordinate
int16_t minuteHandNoonY = secondsTickMarkInnerNoonY + 4;
// hour string y coordinate
int16_t hourStringNoonY = minuteHandNoonY + 18;
// hour string y coordinate
int16_t hourStringNoonY = minuteHandNoonY + 18;
// hour hand radius and y coordinate
int16_t hourHandRadius = radius * 0.35;
if (currentResolution == ScreenResolution::High) {
hourHandRadius = radius * 0.55;
// hour hand radius and y coordinate
int16_t hourHandRadius = radius * 0.35;
if (currentResolution == ScreenResolution::High) {
hourHandRadius = radius * 0.55;
}
int16_t hourHandNoonY = centerY - hourHandRadius;
display->setColor(OLEDDISPLAY_COLOR::WHITE);
display->drawCircle(centerX, centerY, radius);
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // Display local timezone
if (rtc_sec > 0) {
int hour, minute, second;
decomposeTime(rtc_sec, hour, minute, second);
if (config.display.use_12h_clock) {
bool isPM = hour >= 12;
display->setFont(FONT_SMALL);
int yOffset = (currentResolution == ScreenResolution::High) ? 1 : 0;
#ifdef USE_EINK
yOffset += 3;
#endif
display->drawString(centerX - (display->getStringWidth(isPM ? "pm" : "am") / 2), centerY + yOffset, isPM ? "pm" : "am");
}
int16_t hourHandNoonY = centerY - hourHandRadius;
hour %= 12;
if (hour == 0)
hour = 12;
display->setColor(OLEDDISPLAY_COLOR::WHITE);
display->drawCircle(centerX, centerY, radius);
int16_t degreesPerHour = 30;
int16_t degreesPerMinuteOrSecond = 6;
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // Display local timezone
if (rtc_sec > 0) {
int hour, minute, second;
decomposeTime(rtc_sec, hour, minute, second);
double hourBaseAngle = hour * degreesPerHour;
double hourAngleOffset = ((double)minute / 60) * degreesPerHour;
double hourAngle = radians(hourBaseAngle + hourAngleOffset);
if (config.display.use_12h_clock) {
bool isPM = hour >= 12;
display->setFont(FONT_SMALL);
int yOffset = (currentResolution == ScreenResolution::High) ? 1 : 0;
#ifdef USE_EINK
yOffset += 3;
#endif
display->drawString(centerX - (display->getStringWidth(isPM ? "pm" : "am") / 2), centerY + yOffset,
isPM ? "pm" : "am");
double minuteBaseAngle = minute * degreesPerMinuteOrSecond;
double minuteAngleOffset = ((double)second / 60) * degreesPerMinuteOrSecond;
double minuteAngle = radians(minuteBaseAngle + minuteAngleOffset);
double secondAngle = radians(second * degreesPerMinuteOrSecond);
double hourX = sin(-hourAngle) * (hourHandNoonY - centerY) + noonX;
double hourY = cos(-hourAngle) * (hourHandNoonY - centerY) + centerY;
double minuteX = sin(-minuteAngle) * (minuteHandNoonY - centerY) + noonX;
double minuteY = cos(-minuteAngle) * (minuteHandNoonY - centerY) + centerY;
double secondX = sin(-secondAngle) * (secondHandNoonY - centerY) + noonX;
double secondY = cos(-secondAngle) * (secondHandNoonY - centerY) + centerY;
display->setFont(FONT_MEDIUM);
// draw minute and hour tick marks and hour numbers
for (uint16_t angle = 0; angle < 360; angle += 6) {
double angleInRadians = radians(angle);
double sineAngleInRadians = sin(-angleInRadians);
double cosineAngleInRadians = cos(-angleInRadians);
double endX = sineAngleInRadians * (tickMarkOuterNoonY - centerY) + noonX;
double endY = cosineAngleInRadians * (tickMarkOuterNoonY - centerY) + centerY;
if (angle % degreesPerHour == 0) {
double startX = sineAngleInRadians * (hoursTickMarkInnerNoonY - centerY) + noonX;
double startY = cosineAngleInRadians * (hoursTickMarkInnerNoonY - centerY) + centerY;
// draw hour tick mark
display->drawLine(startX, startY, endX, endY);
static char buffer[2];
uint8_t hourInt = (angle / 30);
if (hourInt == 0) {
hourInt = 12;
}
hour %= 12;
if (hour == 0)
hour = 12;
int16_t degreesPerHour = 30;
int16_t degreesPerMinuteOrSecond = 6;
// hour number x offset needs to be adjusted for some cases
int8_t hourStringXOffset;
int8_t hourStringYOffset = 13;
double hourBaseAngle = hour * degreesPerHour;
double hourAngleOffset = ((double)minute / 60) * degreesPerHour;
double hourAngle = radians(hourBaseAngle + hourAngleOffset);
switch (hourInt) {
case 3:
hourStringXOffset = 5;
break;
case 9:
hourStringXOffset = 7;
break;
case 10:
case 11:
hourStringXOffset = 8;
break;
case 12:
hourStringXOffset = 13;
break;
default:
hourStringXOffset = 6;
break;
}
double minuteBaseAngle = minute * degreesPerMinuteOrSecond;
double minuteAngleOffset = ((double)second / 60) * degreesPerMinuteOrSecond;
double minuteAngle = radians(minuteBaseAngle + minuteAngleOffset);
double secondAngle = radians(second * degreesPerMinuteOrSecond);
double hourX = sin(-hourAngle) * (hourHandNoonY - centerY) + noonX;
double hourY = cos(-hourAngle) * (hourHandNoonY - centerY) + centerY;
double minuteX = sin(-minuteAngle) * (minuteHandNoonY - centerY) + noonX;
double minuteY = cos(-minuteAngle) * (minuteHandNoonY - centerY) + centerY;
double secondX = sin(-secondAngle) * (secondHandNoonY - centerY) + noonX;
double secondY = cos(-secondAngle) * (secondHandNoonY - centerY) + centerY;
display->setFont(FONT_MEDIUM);
// draw minute and hour tick marks and hour numbers
for (uint16_t angle = 0; angle < 360; angle += 6) {
double angleInRadians = radians(angle);
double sineAngleInRadians = sin(-angleInRadians);
double cosineAngleInRadians = cos(-angleInRadians);
double endX = sineAngleInRadians * (tickMarkOuterNoonY - centerY) + noonX;
double endY = cosineAngleInRadians * (tickMarkOuterNoonY - centerY) + centerY;
if (angle % degreesPerHour == 0) {
double startX = sineAngleInRadians * (hoursTickMarkInnerNoonY - centerY) + noonX;
double startY = cosineAngleInRadians * (hoursTickMarkInnerNoonY - centerY) + centerY;
// draw hour tick mark
display->drawLine(startX, startY, endX, endY);
static char buffer[2];
uint8_t hourInt = (angle / 30);
if (hourInt == 0) {
hourInt = 12;
}
// hour number x offset needs to be adjusted for some cases
int8_t hourStringXOffset;
int8_t hourStringYOffset = 13;
switch (hourInt) {
case 3:
hourStringXOffset = 5;
break;
case 9:
hourStringXOffset = 7;
break;
case 10:
case 11:
hourStringXOffset = 8;
break;
case 12:
hourStringXOffset = 13;
break;
default:
hourStringXOffset = 6;
break;
}
double hourStringX = (sineAngleInRadians * (hourStringNoonY - centerY) + noonX) - hourStringXOffset;
double hourStringY = (cosineAngleInRadians * (hourStringNoonY - centerY) + centerY) - hourStringYOffset;
double hourStringX = (sineAngleInRadians * (hourStringNoonY - centerY) + noonX) - hourStringXOffset;
double hourStringY = (cosineAngleInRadians * (hourStringNoonY - centerY) + centerY) - hourStringYOffset;
#ifdef T_WATCH_S3
// draw hour number
display->drawStringf(hourStringX, hourStringY, buffer, "%d", hourInt);
// draw hour number
display->drawStringf(hourStringX, hourStringY, buffer, "%d", hourInt);
#else
#ifdef USE_EINK
if (currentResolution == ScreenResolution::High) {
// draw hour number
display->drawStringf(hourStringX, hourStringY, buffer, "%d", hourInt);
}
#else
if (currentResolution == ScreenResolution::High &&
(hourInt == 3 || hourInt == 6 || hourInt == 9 || hourInt == 12)) {
// draw hour number
display->drawStringf(hourStringX, hourStringY, buffer, "%d", hourInt);
}
#endif
#endif
}
if (angle % degreesPerMinuteOrSecond == 0) {
double startX = sineAngleInRadians * (secondsTickMarkInnerNoonY - centerY) + noonX;
double startY = cosineAngleInRadians * (secondsTickMarkInnerNoonY - centerY) + centerY;
if (currentResolution == ScreenResolution::High) {
// draw minute tick mark
display->drawLine(startX, startY, endX, endY);
}
}
if (currentResolution == ScreenResolution::High) {
// draw hour number
display->drawStringf(hourStringX, hourStringY, buffer, "%d", hourInt);
}
#else
if (currentResolution == ScreenResolution::High && (hourInt == 3 || hourInt == 6 || hourInt == 9 || hourInt == 12)) {
// draw hour number
display->drawStringf(hourStringX, hourStringY, buffer, "%d", hourInt);
}
#endif
#endif
}
// draw hour hand
display->drawLine(centerX, centerY, hourX, hourY);
if (angle % degreesPerMinuteOrSecond == 0) {
double startX = sineAngleInRadians * (secondsTickMarkInnerNoonY - centerY) + noonX;
double startY = cosineAngleInRadians * (secondsTickMarkInnerNoonY - centerY) + centerY;
// draw minute hand
display->drawLine(centerX, centerY, minuteX, minuteY);
if (currentResolution == ScreenResolution::High) {
// draw minute tick mark
display->drawLine(startX, startY, endX, endY);
}
}
}
// draw hour hand
display->drawLine(centerX, centerY, hourX, hourY);
// draw minute hand
display->drawLine(centerX, centerY, minuteX, minuteY);
#ifndef USE_EINK
// draw second hand
display->drawLine(centerX, centerY, secondX, secondY);
// draw second hand
display->drawLine(centerX, centerY, secondX, secondY);
#endif
}
graphics::drawCommonFooter(display, x, y);
}
graphics::drawCommonFooter(display, x, y);
}
} // namespace ClockRenderer

View File

@@ -3,14 +3,12 @@
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
namespace graphics
{
namespace graphics {
/// Forward declarations
class Screen;
namespace ClockRenderer
{
namespace ClockRenderer {
// Clock frame functions
void drawAnalogClockFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);

View File

@@ -9,130 +9,120 @@
#include "graphics/SharedUIDisplay.h"
#include <cmath>
namespace graphics
{
namespace CompassRenderer
{
namespace graphics {
namespace CompassRenderer {
// Point helper class for compass calculations
struct Point {
float x, y;
Point(float x, float y) : x(x), y(y) {}
float x, y;
Point(float x, float y) : x(x), y(y) {}
void rotate(float angle)
{
float cos_a = cos(angle);
float sin_a = sin(angle);
float new_x = x * cos_a - y * sin_a;
float new_y = x * sin_a + y * cos_a;
x = new_x;
y = new_y;
}
void rotate(float angle) {
float cos_a = cos(angle);
float sin_a = sin(angle);
float new_x = x * cos_a - y * sin_a;
float new_y = x * sin_a + y * cos_a;
x = new_x;
y = new_y;
}
void scale(float factor)
{
x *= factor;
y *= factor;
}
void scale(float factor) {
x *= factor;
y *= factor;
}
void translate(float dx, float dy)
{
x += dx;
y += dy;
}
void translate(float dx, float dy) {
x += dx;
y += dy;
}
};
void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading, int16_t radius)
{
// Show the compass heading (not implemented in original)
// This could draw a "N" indicator or north arrow
// For now, we'll draw a simple north indicator
// const float radius = 17.0f;
if (currentResolution == ScreenResolution::High) {
radius += 4;
}
Point north(0, -radius);
if (uiconfig.compass_mode != meshtastic_CompassMode_FIXED_RING)
north.rotate(-myHeading);
north.translate(compassX, compassY);
void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading, int16_t radius) {
// Show the compass heading (not implemented in original)
// This could draw a "N" indicator or north arrow
// For now, we'll draw a simple north indicator
// const float radius = 17.0f;
if (currentResolution == ScreenResolution::High) {
radius += 4;
}
Point north(0, -radius);
if (uiconfig.compass_mode != meshtastic_CompassMode_FIXED_RING)
north.rotate(-myHeading);
north.translate(compassX, compassY);
display->setFont(FONT_SMALL);
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setColor(BLACK);
if (currentResolution == ScreenResolution::High) {
display->fillRect(north.x - 8, north.y - 1, display->getStringWidth("N") + 3, FONT_HEIGHT_SMALL - 6);
} else {
display->fillRect(north.x - 4, north.y - 1, display->getStringWidth("N") + 2, FONT_HEIGHT_SMALL - 6);
}
display->setColor(WHITE);
display->drawString(north.x, north.y - 3, "N");
display->setFont(FONT_SMALL);
display->setTextAlignment(TEXT_ALIGN_CENTER);
display->setColor(BLACK);
if (currentResolution == ScreenResolution::High) {
display->fillRect(north.x - 8, north.y - 1, display->getStringWidth("N") + 3, FONT_HEIGHT_SMALL - 6);
} else {
display->fillRect(north.x - 4, north.y - 1, display->getStringWidth("N") + 2, FONT_HEIGHT_SMALL - 6);
}
display->setColor(WHITE);
display->drawString(north.x, north.y - 3, "N");
}
void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t compassY, uint16_t compassDiam, float headingRadian)
{
Point tip(0.0f, -0.5f), tail(0.0f, 0.35f); // pointing up initially
float arrowOffsetX = 0.14f, arrowOffsetY = 0.9f;
Point leftArrow(tip.x - arrowOffsetX, tip.y + arrowOffsetY), rightArrow(tip.x + arrowOffsetX, tip.y + arrowOffsetY);
void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t compassY, uint16_t compassDiam, float headingRadian) {
Point tip(0.0f, -0.5f), tail(0.0f, 0.35f); // pointing up initially
float arrowOffsetX = 0.14f, arrowOffsetY = 0.9f;
Point leftArrow(tip.x - arrowOffsetX, tip.y + arrowOffsetY), rightArrow(tip.x + arrowOffsetX, tip.y + arrowOffsetY);
Point *arrowPoints[] = {&tip, &tail, &leftArrow, &rightArrow};
Point *arrowPoints[] = {&tip, &tail, &leftArrow, &rightArrow};
for (int i = 0; i < 4; i++) {
arrowPoints[i]->rotate(headingRadian);
arrowPoints[i]->scale(compassDiam * 0.6);
arrowPoints[i]->translate(compassX, compassY);
}
for (int i = 0; i < 4; i++) {
arrowPoints[i]->rotate(headingRadian);
arrowPoints[i]->scale(compassDiam * 0.6);
arrowPoints[i]->translate(compassX, compassY);
}
#ifdef USE_EINK
display->drawTriangle(tip.x, tip.y, rightArrow.x, rightArrow.y, tail.x, tail.y);
display->drawTriangle(tip.x, tip.y, rightArrow.x, rightArrow.y, tail.x, tail.y);
#else
display->fillTriangle(tip.x, tip.y, rightArrow.x, rightArrow.y, tail.x, tail.y);
display->fillTriangle(tip.x, tip.y, rightArrow.x, rightArrow.y, tail.x, tail.y);
#endif
display->drawTriangle(tip.x, tip.y, leftArrow.x, leftArrow.y, tail.x, tail.y);
display->drawTriangle(tip.x, tip.y, leftArrow.x, leftArrow.y, tail.x, tail.y);
}
void drawArrowToNode(OLEDDisplay *display, int16_t x, int16_t y, int16_t size, float bearing)
{
float radians = bearing * DEG_TO_RAD;
void drawArrowToNode(OLEDDisplay *display, int16_t x, int16_t y, int16_t size, float bearing) {
float radians = bearing * DEG_TO_RAD;
Point tip(0, -size / 2);
Point left(-size / 6, size / 4);
Point right(size / 6, size / 4);
Point tail(0, size / 4.5);
Point tip(0, -size / 2);
Point left(-size / 6, size / 4);
Point right(size / 6, size / 4);
Point tail(0, size / 4.5);
tip.rotate(radians);
left.rotate(radians);
right.rotate(radians);
tail.rotate(radians);
tip.rotate(radians);
left.rotate(radians);
right.rotate(radians);
tail.rotate(radians);
tip.translate(x, y);
left.translate(x, y);
right.translate(x, y);
tail.translate(x, y);
tip.translate(x, y);
left.translate(x, y);
right.translate(x, y);
tail.translate(x, y);
display->fillTriangle(tip.x, tip.y, left.x, left.y, tail.x, tail.y);
display->fillTriangle(tip.x, tip.y, right.x, right.y, tail.x, tail.y);
display->fillTriangle(tip.x, tip.y, left.x, left.y, tail.x, tail.y);
display->fillTriangle(tip.x, tip.y, right.x, right.y, tail.x, tail.y);
}
float estimatedHeading(double lat, double lon)
{
// Simple magnetic declination estimation
// This is a very basic implementation - the original might be more sophisticated
return 0.0f; // Return 0 for now, indicating no heading available
float estimatedHeading(double lat, double lon) {
// Simple magnetic declination estimation
// This is a very basic implementation - the original might be more sophisticated
return 0.0f; // Return 0 for now, indicating no heading available
}
uint16_t getCompassDiam(uint32_t displayWidth, uint32_t displayHeight)
{
// Calculate appropriate compass diameter based on display size
uint16_t minDimension = (displayWidth < displayHeight) ? displayWidth : displayHeight;
uint16_t maxDiam = minDimension / 3; // Use 1/3 of the smaller dimension
uint16_t getCompassDiam(uint32_t displayWidth, uint32_t displayHeight) {
// Calculate appropriate compass diameter based on display size
uint16_t minDimension = (displayWidth < displayHeight) ? displayWidth : displayHeight;
uint16_t maxDiam = minDimension / 3; // Use 1/3 of the smaller dimension
// Ensure minimum and maximum bounds
if (maxDiam < 16)
maxDiam = 16;
if (maxDiam > 64)
maxDiam = 64;
// Ensure minimum and maximum bounds
if (maxDiam < 16)
maxDiam = 16;
if (maxDiam > 64)
maxDiam = 64;
return maxDiam;
return maxDiam;
}
} // namespace CompassRenderer

View File

@@ -5,8 +5,7 @@
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
namespace graphics
{
namespace graphics {
/// Forward declarations
class Screen;
@@ -17,8 +16,7 @@ class Screen;
* Contains all functions related to drawing compass elements, headings,
* navigation arrows, and location-based UI components.
*/
namespace CompassRenderer
{
namespace CompassRenderer {
// Compass drawing functions
void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading, int16_t radius);
void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t compassY, uint16_t compassDiam, float headingRadian);

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,7 @@
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
namespace graphics
{
namespace graphics {
/// Forward declarations
class Screen;
@@ -16,8 +15,7 @@ class DebugInfo;
* Contains all functions related to drawing debug information,
* WiFi status, settings screens, and diagnostic data.
*/
namespace DebugRenderer
{
namespace DebugRenderer {
// Debug frame functions
void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
void drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);

View File

@@ -13,8 +13,7 @@
#include "graphics/draw/NodeListRenderer.h"
#include "graphics/draw/UIRenderer.h"
namespace graphics
{
namespace graphics {
/**
* @brief Collection of all draw renderers
@@ -22,8 +21,7 @@ namespace graphics
* This namespace provides access to all the specialized rendering
* functions organized by category.
*/
namespace DrawRenderers
{
namespace DrawRenderers {
// Re-export all renderer namespaces for convenience
using namespace ClockRenderer;
using namespace CompassRenderer;

File diff suppressed because it is too large Load Diff

View File

@@ -1,143 +1,135 @@
#pragma once
#if HAS_SCREEN
#include "configuration.h"
namespace graphics
{
namespace graphics {
class menuHandler
{
public:
enum screenMenus {
menu_none,
lora_Menu,
lora_picker,
device_role_picker,
radio_preset_picker,
no_timeout_lora_picker,
TZ_picker,
twelve_hour_picker,
clock_face_picker,
clock_menu,
position_base_menu,
node_base_menu,
gps_toggle_menu,
gps_format_menu,
gps_smart_position_menu,
gps_update_interval_menu,
gps_position_broadcast_menu,
compass_point_north_menu,
reset_node_db_menu,
buzzermodemenupicker,
mui_picker,
tftcolormenupicker,
brightness_picker,
reboot_menu,
shutdown_menu,
add_favorite,
remove_favorite,
test_menu,
number_test,
wifi_toggle_menu,
bluetooth_toggle_menu,
screen_options_menu,
power_menu,
system_base_menu,
key_verification_init,
key_verification_final_prompt,
trace_route_menu,
throttle_message,
message_response_menu,
message_viewmode_menu,
reply_menu,
delete_messages_menu,
node_name_length_menu,
FrameToggles,
DisplayUnits
};
static screenMenus menuQueue;
class menuHandler {
public:
enum screenMenus {
menu_none,
lora_Menu,
lora_picker,
device_role_picker,
radio_preset_picker,
no_timeout_lora_picker,
TZ_picker,
twelve_hour_picker,
clock_face_picker,
clock_menu,
position_base_menu,
node_base_menu,
gps_toggle_menu,
gps_format_menu,
gps_smart_position_menu,
gps_update_interval_menu,
gps_position_broadcast_menu,
compass_point_north_menu,
reset_node_db_menu,
buzzermodemenupicker,
mui_picker,
tftcolormenupicker,
brightness_picker,
reboot_menu,
shutdown_menu,
add_favorite,
remove_favorite,
test_menu,
number_test,
wifi_toggle_menu,
bluetooth_toggle_menu,
screen_options_menu,
power_menu,
system_base_menu,
key_verification_init,
key_verification_final_prompt,
trace_route_menu,
throttle_message,
message_response_menu,
message_viewmode_menu,
reply_menu,
delete_messages_menu,
node_name_length_menu,
FrameToggles,
DisplayUnits
};
static screenMenus menuQueue;
static void OnboardMessage();
static void LoraRegionPicker(uint32_t duration = 30000);
static void loraMenu();
static void DeviceRolePicker();
static void RadioPresetPicker();
static void handleMenuSwitch(OLEDDisplay *display);
static void showConfirmationBanner(const char *message, std::function<void()> onConfirm);
static void clockMenu();
static void TZPicker();
static void TwelveHourPicker();
static void ClockFacePicker();
static void messageResponseMenu();
static void messageViewModeMenu();
static void replyMenu();
static void deleteMessagesMenu();
static void homeBaseMenu();
static void textMessageBaseMenu();
static void systemBaseMenu();
static void favoriteBaseMenu();
static void positionBaseMenu();
static void compassNorthMenu();
static void GPSToggleMenu();
static void GPSFormatMenu();
static void GPSSmartPositionMenu();
static void GPSUpdateIntervalMenu();
static void GPSPositionBroadcastMenu();
static void BuzzerModeMenu();
static void switchToMUIMenu();
static void TFTColorPickerMenu(OLEDDisplay *display);
static void nodeListMenu();
static void resetNodeDBMenu();
static void BrightnessPickerMenu();
static void rebootMenu();
static void shutdownMenu();
static void addFavoriteMenu();
static void removeFavoriteMenu();
static void traceRouteMenu();
static void testMenu();
static void numberTest();
static void wifiBaseMenu();
static void wifiToggleMenu();
static void screenOptionsMenu();
static void powerMenu();
static void nodeNameLengthMenu();
static void FrameToggles_menu();
static void DisplayUnits_menu();
static void textMessageMenu();
static void OnboardMessage();
static void LoraRegionPicker(uint32_t duration = 30000);
static void loraMenu();
static void DeviceRolePicker();
static void RadioPresetPicker();
static void handleMenuSwitch(OLEDDisplay *display);
static void showConfirmationBanner(const char *message, std::function<void()> onConfirm);
static void clockMenu();
static void TZPicker();
static void TwelveHourPicker();
static void ClockFacePicker();
static void messageResponseMenu();
static void messageViewModeMenu();
static void replyMenu();
static void deleteMessagesMenu();
static void homeBaseMenu();
static void textMessageBaseMenu();
static void systemBaseMenu();
static void favoriteBaseMenu();
static void positionBaseMenu();
static void compassNorthMenu();
static void GPSToggleMenu();
static void GPSFormatMenu();
static void GPSSmartPositionMenu();
static void GPSUpdateIntervalMenu();
static void GPSPositionBroadcastMenu();
static void BuzzerModeMenu();
static void switchToMUIMenu();
static void TFTColorPickerMenu(OLEDDisplay *display);
static void nodeListMenu();
static void resetNodeDBMenu();
static void BrightnessPickerMenu();
static void rebootMenu();
static void shutdownMenu();
static void addFavoriteMenu();
static void removeFavoriteMenu();
static void traceRouteMenu();
static void testMenu();
static void numberTest();
static void wifiBaseMenu();
static void wifiToggleMenu();
static void screenOptionsMenu();
static void powerMenu();
static void nodeNameLengthMenu();
static void FrameToggles_menu();
static void DisplayUnits_menu();
static void textMessageMenu();
private:
static void saveUIConfig();
static void keyVerificationInitMenu();
static void keyVerificationFinalPrompt();
static void BluetoothToggleMenu();
private:
static void saveUIConfig();
static void keyVerificationInitMenu();
static void keyVerificationFinalPrompt();
static void BluetoothToggleMenu();
};
/* Generic Menu Options designations */
enum class OptionsAction { Back, Select };
template <typename T> struct MenuOption {
const char *label;
OptionsAction action;
bool hasValue;
T value;
const char *label;
OptionsAction action;
bool hasValue;
T value;
MenuOption(const char *labelIn, OptionsAction actionIn, T valueIn)
: label(labelIn), action(actionIn), hasValue(true), value(valueIn)
{
}
MenuOption(const char *labelIn, OptionsAction actionIn, T valueIn) : label(labelIn), action(actionIn), hasValue(true), value(valueIn) {}
MenuOption(const char *labelIn, OptionsAction actionIn) : label(labelIn), action(actionIn), hasValue(false), value() {}
MenuOption(const char *labelIn, OptionsAction actionIn) : label(labelIn), action(actionIn), hasValue(false), value() {}
};
struct ScreenColor {
uint8_t r;
uint8_t g;
uint8_t b;
bool useVariant;
uint8_t r;
uint8_t g;
uint8_t b;
bool useVariant;
ScreenColor(uint8_t rIn = 0, uint8_t gIn = 0, uint8_t bIn = 0, bool variantIn = false)
: r(rIn), g(gIn), b(bIn), useVariant(variantIn)
{
}
ScreenColor(uint8_t rIn = 0, uint8_t gIn = 0, uint8_t bIn = 0, bool variantIn = false) : r(rIn), g(gIn), b(bIn), useVariant(variantIn) {}
};
using RadioPresetOption = MenuOption<meshtastic_Config_LoRaConfig_ModemPreset>;

File diff suppressed because it is too large Load Diff

View File

@@ -9,10 +9,8 @@
#include <string>
#include <vector>
namespace graphics
{
namespace MessageRenderer
{
namespace graphics {
namespace MessageRenderer {
// Thread filter modes
enum class ThreadMode { ALL, CHANNEL, DIRECT };
@@ -45,8 +43,7 @@ void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
std::vector<std::string> generateLines(OLEDDisplay *display, const char *headerStr, const char *messageBuf, int textWidth);
// Function to calculate heights for each line
std::vector<int> calculateLineHeights(const std::vector<std::string> &lines, const Emote *emotes,
const std::vector<bool> &isHeaderVec);
std::vector<int> calculateLineHeights(const std::vector<std::string> &lines, const Emote *emotes, const std::vector<bool> &isHeaderVec);
// Reset scroll state when new messages arrive
void resetScrollState();

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,7 @@
#include <OLEDDisplay.h>
#include <OLEDDisplayUi.h>
namespace graphics
{
namespace graphics {
/// Forward declarations
class Screen;
@@ -17,8 +16,7 @@ class Screen;
* Contains all functions related to drawing node lists and individual node entries
* including last heard, hop signal, distance, and compass views.
*/
namespace NodeListRenderer
{
namespace NodeListRenderer {
// Entry renderer function types
typedef void (*EntryRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int);
typedef void (*NodeExtrasRenderer)(OLEDDisplay *, meshtastic_NodeInfoLite *, int16_t, int16_t, int, float, double, double);
@@ -30,9 +28,8 @@ enum ListMode_Node { MODE_LAST_HEARD = 0, MODE_HOP_SIGNAL = 1, MODE_COUNT_NODE =
enum ListMode_Location { MODE_DISTANCE = 0, MODE_BEARING = 1, MODE_COUNT_LOCATION = 2 };
// Main node list screen function
void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *title,
EntryRenderer renderer, NodeExtrasRenderer extras = nullptr, float heading = 0, double lat = 0,
double lon = 0);
void drawNodeListScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *title, EntryRenderer renderer,
NodeExtrasRenderer extras = nullptr, float heading = 0, double lat = 0, double lon = 0);
// Entry renderers
void drawEntryLastHeard(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
@@ -42,8 +39,8 @@ void drawEntryDynamic_Nodes(OLEDDisplay *display, meshtastic_NodeInfoLite *node,
void drawEntryCompass(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth);
// Extras renderers
void drawCompassArrow(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth, float myHeading,
double userLat, double userLon);
void drawCompassArrow(OLEDDisplay *display, meshtastic_NodeInfoLite *node, int16_t x, int16_t y, int columnWidth, float myHeading, double userLat,
double userLon);
// Screen frame functions
void drawLastHeardScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);

File diff suppressed because it is too large Load Diff

View File

@@ -9,44 +9,42 @@
#include <string>
#define MAX_LINES 5
namespace graphics
{
namespace graphics {
class NotificationRenderer
{
public:
static InputEvent inEvent;
static char inKeypress;
static int8_t curSelected;
static char alertBannerMessage[256];
static uint32_t alertBannerUntil; // 0 is a special case meaning forever
static const char **optionsArrayPtr;
static const int *optionsEnumPtr;
static uint8_t alertBannerOptions; // last x lines are seelctable options
static std::function<void(int)> alertBannerCallback;
static uint32_t numDigits;
static uint32_t currentNumber;
static VirtualKeyboard *virtualKeyboard;
static std::function<void(const std::string &)> textInputCallback;
class NotificationRenderer {
public:
static InputEvent inEvent;
static char inKeypress;
static int8_t curSelected;
static char alertBannerMessage[256];
static uint32_t alertBannerUntil; // 0 is a special case meaning forever
static const char **optionsArrayPtr;
static const int *optionsEnumPtr;
static uint8_t alertBannerOptions; // last x lines are seelctable options
static std::function<void(int)> alertBannerCallback;
static uint32_t numDigits;
static uint32_t currentNumber;
static VirtualKeyboard *virtualKeyboard;
static std::function<void(const std::string &)> textInputCallback;
static bool pauseBanner;
static bool pauseBanner;
static void resetBanner();
static void showKeyboardMessagePopupWithTitle(const char *title, const char *content, uint32_t durationMs);
static void drawBannercallback(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawNumberPicker(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawNodePicker(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawTextInput(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawNotificationBox(OLEDDisplay *display, OLEDDisplayUiState *state, const char *lines[MAX_LINES + 1],
uint16_t totalLines, uint8_t firstOptionToShow, uint16_t maxWidth = 0);
static void resetBanner();
static void showKeyboardMessagePopupWithTitle(const char *title, const char *content, uint32_t durationMs);
static void drawBannercallback(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawNumberPicker(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawNodePicker(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawTextInput(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawNotificationBox(OLEDDisplay *display, OLEDDisplayUiState *state, const char *lines[MAX_LINES + 1], uint16_t totalLines,
uint8_t firstOptionToShow, uint16_t maxWidth = 0);
static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static bool isOverlayBannerShowing();
static void drawCriticalFaultFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static bool isOverlayBannerShowing();
static graphics::notificationTypeEnum current_notification_type;
static graphics::notificationTypeEnum current_notification_type;
};
} // namespace graphics

File diff suppressed because it is too large Load Diff

View File

@@ -10,15 +10,13 @@
#define HOURS_IN_MONTH 730
// Forward declarations for status types
namespace meshtastic
{
namespace meshtastic {
class PowerStatus;
class NodeStatus;
class GPSStatus;
} // namespace meshtastic
namespace graphics
{
namespace graphics {
/// Forward declarations
class Screen;
@@ -29,59 +27,57 @@ class Screen;
* Contains utility functions for drawing common UI elements, overlays,
* battery indicators, and other shared graphical components.
*/
class UIRenderer
{
public:
// Common UI elements
static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::NodeStatus *nodeStatus,
int node_offset = 0, bool show_total = true, const char *additional_words = "");
class UIRenderer {
public:
// Common UI elements
static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::NodeStatus *nodeStatus, int node_offset = 0,
bool show_total = true, const char *additional_words = "");
// GPS status functions
static void drawGps(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus);
static void drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus,
const char *mode = "line1");
static void drawGpsAltitude(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus);
static void drawGpsPowerStatus(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus);
// GPS status functions
static void drawGps(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus);
static void drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus, const char *mode = "line1");
static void drawGpsAltitude(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus);
static void drawGpsPowerStatus(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus);
// Overlay and special screens
static void drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *text);
// Overlay and special screens
static void drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *text);
// Navigation bar overlay
static void drawNavigationBar(OLEDDisplay *display, OLEDDisplayUiState *state);
// Navigation bar overlay
static void drawNavigationBar(OLEDDisplay *display, OLEDDisplayUiState *state);
static void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawNodeInfo(OLEDDisplay *display, const OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
// Icon and screen drawing functions
static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
// Icon and screen drawing functions
static void drawIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
// Compass and location screen
static void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
// Compass and location screen
static void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static NodeNum currentFavoriteNodeNum;
static std::vector<meshtastic_NodeInfoLite *> favoritedNodes;
static void rebuildFavoritedNodes();
static NodeNum currentFavoriteNodeNum;
static std::vector<meshtastic_NodeInfoLite *> favoritedNodes;
static void rebuildFavoritedNodes();
// OEM screens
#ifdef USERPREFS_OEM_TEXT
static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawOEMIconScreen(const char *upperMsg, OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
#endif
#ifdef USE_EINK
/// Used on eink displays while in deep sleep
static void drawDeepSleepFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
/// Used on eink displays while in deep sleep
static void drawDeepSleepFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
/// Used on eink displays when screen updates are paused
static void drawScreensaverOverlay(OLEDDisplay *display, OLEDDisplayUiState *state);
/// Used on eink displays when screen updates are paused
static void drawScreensaverOverlay(OLEDDisplay *display, OLEDDisplayUiState *state);
#endif
static std::string drawTimeDelta(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds);
static int formatDateTime(char *buffer, size_t bufferSize, uint32_t rtc_sec, OLEDDisplay *display, bool showTime);
static std::string drawTimeDelta(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds);
static int formatDateTime(char *buffer, size_t bufferSize, uint32_t rtc_sec, OLEDDisplay *display, bool showTime);
// Check if the display can render a string (detect special chars; emoji)
static bool haveGlyphs(const char *str);
// Check if the display can render a string (detect special chars; emoji)
static bool haveGlyphs(const char *str);
}; // namespace UIRenderer
} // namespace graphics