mirror of
https://github.com/meshtastic/firmware.git
synced 2025-10-28 07:13:25 +00:00
fix for notification renderer
This commit is contained in:
parent
784e71f2fa
commit
163d8e0540
@ -461,9 +461,9 @@ void NotificationRenderer::drawAlertBannerOverlay(OLEDDisplay *display, OLEDDisp
|
|||||||
void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplayUiState *state, const char *lines[],
|
void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplayUiState *state, const char *lines[],
|
||||||
uint16_t totalLines, uint8_t firstOptionToShow, uint16_t maxWidth)
|
uint16_t totalLines, uint8_t firstOptionToShow, uint16_t maxWidth)
|
||||||
{
|
{
|
||||||
|
|
||||||
bool is_picker = false;
|
bool is_picker = false;
|
||||||
uint16_t lineCount = 0;
|
uint16_t lineCount = 0;
|
||||||
|
|
||||||
// Layout Configuration
|
// Layout Configuration
|
||||||
constexpr uint16_t hPadding = 5;
|
constexpr uint16_t hPadding = 5;
|
||||||
constexpr uint16_t vPadding = 2;
|
constexpr uint16_t vPadding = 2;
|
||||||
@ -478,25 +478,26 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
|||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
|
||||||
// Measure all lines and calculate widest width
|
// Track widest line INCLUDING bars (but don't change per-line widths)
|
||||||
uint16_t widestLineWithBars = 0;
|
uint16_t widestLineWithBars = 0;
|
||||||
|
|
||||||
while (lines[lineCount] != nullptr) {
|
while (lines[lineCount] != nullptr) {
|
||||||
auto newlinePointer = strchr(lines[lineCount], '\n');
|
auto newlinePointer = strchr(lines[lineCount], '\n');
|
||||||
if (newlinePointer)
|
if (newlinePointer)
|
||||||
lineLengths[lineCount] = (newlinePointer - lines[lineCount]); // Check for newlines first
|
lineLengths[lineCount] = (newlinePointer - lines[lineCount]); // Check for newlines first
|
||||||
else
|
else // if the newline wasn't found, then pull string length from strlen
|
||||||
lineLengths[lineCount] = strlen(lines[lineCount]); // Fallback to strlen if no newline
|
lineLengths[lineCount] = strlen(lines[lineCount]);
|
||||||
|
|
||||||
lineWidths[lineCount] = display->getStringWidth(lines[lineCount], lineLengths[lineCount], true);
|
lineWidths[lineCount] = display->getStringWidth(lines[lineCount], lineLengths[lineCount], true);
|
||||||
|
|
||||||
// Calculate potential width including signal bars (without altering per-line widths)
|
// Consider extra width for signal bars on lines that contain "Signal:"
|
||||||
uint16_t potentialWidth = lineWidths[lineCount];
|
uint16_t potentialWidth = lineWidths[lineCount];
|
||||||
if (bannerSignalBars >= 0 && strstr(lines[lineCount], "Signal:") != nullptr) {
|
if (graphics::bannerSignalBars >= 0 && strstr(lines[lineCount], "Signal:") != nullptr) {
|
||||||
const int totalBars = 5;
|
const int totalBars = 5;
|
||||||
const int barWidth = 3;
|
const int barWidth = 3;
|
||||||
const int barSpacing = 2;
|
const int barSpacing = 2;
|
||||||
int barsWidth = totalBars * barWidth + (totalBars - 1) * barSpacing + 6;
|
const int gap = 6; // space between text and bars
|
||||||
|
int barsWidth = totalBars * barWidth + (totalBars - 1) * barSpacing + gap;
|
||||||
potentialWidth += barsWidth;
|
potentialWidth += barsWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,8 +511,9 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
|||||||
}
|
}
|
||||||
lineCount++;
|
lineCount++;
|
||||||
}
|
}
|
||||||
|
// count lines
|
||||||
|
|
||||||
// Use widestLineWithBars to size the box if signal bars exist
|
// Ensure box accounts for signal bars if present
|
||||||
if (widestLineWithBars > maxWidth)
|
if (widestLineWithBars > maxWidth)
|
||||||
maxWidth = widestLineWithBars;
|
maxWidth = widestLineWithBars;
|
||||||
|
|
||||||
@ -567,48 +569,111 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
|||||||
|
|
||||||
// Draw Content
|
// Draw Content
|
||||||
int16_t lineY = boxTop + vPadding;
|
int16_t lineY = boxTop + vPadding;
|
||||||
|
int swingRange = 8;
|
||||||
|
static int swingOffset = 0;
|
||||||
|
static bool swingRight = true;
|
||||||
|
static unsigned long lastSwingTime = 0;
|
||||||
|
unsigned long now = millis();
|
||||||
|
int swingSpeedMs = 10 / (swingRange * 2);
|
||||||
|
if (now - lastSwingTime >= (unsigned long)swingSpeedMs) {
|
||||||
|
lastSwingTime = now;
|
||||||
|
if (swingRight) {
|
||||||
|
swingOffset++;
|
||||||
|
if (swingOffset >= swingRange)
|
||||||
|
swingRight = false;
|
||||||
|
} else {
|
||||||
|
swingOffset--;
|
||||||
|
if (swingOffset <= 0)
|
||||||
|
swingRight = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
for (int i = 0; i < lineCount; i++) {
|
for (int i = 0; i < lineCount; i++) {
|
||||||
|
bool isTitle = (i == 0);
|
||||||
|
int globalOptionIndex = (i - 1) + firstOptionToShow;
|
||||||
|
bool isSelectedOption = (!isTitle && globalOptionIndex >= 0 && globalOptionIndex == curSelected);
|
||||||
|
|
||||||
|
uint16_t visibleWidth = 64 - hPadding * 2;
|
||||||
|
if (totalLines > visibleTotalLines)
|
||||||
|
visibleWidth -= 6;
|
||||||
char lineBuffer[lineLengths[i] + 1];
|
char lineBuffer[lineLengths[i] + 1];
|
||||||
strncpy(lineBuffer, lines[i], lineLengths[i]);
|
strncpy(lineBuffer, lines[i], lineLengths[i]);
|
||||||
lineBuffer[lineLengths[i]] = '\0';
|
lineBuffer[lineLengths[i]] = '\0';
|
||||||
|
|
||||||
bool isSignalLine = (bannerSignalBars >= 0 && strstr(lineBuffer, "Signal:") != nullptr);
|
if (isTitle) {
|
||||||
|
if (visibleTotalLines == 1) {
|
||||||
if (isSignalLine) {
|
display->setColor(BLACK);
|
||||||
// Center text + signal bars as a single group
|
display->fillRect(boxLeft, boxTop, boxWidth, effectiveLineHeight);
|
||||||
const int totalBars = 5;
|
display->setColor(WHITE);
|
||||||
const int barWidth = 3;
|
display->drawString(boxLeft + (boxWidth - lineWidths[i]) / 2, boxTop, lineBuffer);
|
||||||
const int barSpacing = 2;
|
} else {
|
||||||
const int barHeightStep = 2;
|
display->setColor(WHITE);
|
||||||
|
display->fillRect(boxLeft, boxTop, boxWidth, effectiveLineHeight);
|
||||||
int textWidth = display->getStringWidth(lineBuffer, strlen(lineBuffer), true);
|
display->setColor(BLACK);
|
||||||
int barsWidth = totalBars * barWidth + (totalBars - 1) * barSpacing + 6;
|
display->drawString(boxLeft + (boxWidth - lineWidths[i]) / 2, boxTop, lineBuffer);
|
||||||
int totalWidth = textWidth + barsWidth;
|
display->setColor(WHITE);
|
||||||
|
if (needs_bell) {
|
||||||
int groupStartX = boxLeft + (boxWidth - totalWidth) / 2;
|
int bellY = boxTop + (FONT_HEIGHT_SMALL - 8) / 2;
|
||||||
|
display->drawXbm(boxLeft + (boxWidth - lineWidths[i]) / 2 - 10, bellY, 8, 8, bell_alert);
|
||||||
display->drawString(groupStartX, lineY, lineBuffer);
|
display->drawXbm(boxLeft + (boxWidth + lineWidths[i]) / 2 + 2, bellY, 8, 8, bell_alert);
|
||||||
|
|
||||||
int baseX = groupStartX + textWidth + 6;
|
|
||||||
int baseY = lineY + effectiveLineHeight - 1;
|
|
||||||
|
|
||||||
for (int b = 0; b < totalBars; b++) {
|
|
||||||
int barHeight = (b + 1) * barHeightStep;
|
|
||||||
int x = baseX + b * (barWidth + barSpacing);
|
|
||||||
int y = baseY - barHeight;
|
|
||||||
|
|
||||||
if (b < bannerSignalBars) {
|
|
||||||
display->fillRect(x, y, barWidth, barHeight);
|
|
||||||
} else {
|
|
||||||
display->drawRect(x, y, barWidth, barHeight);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lineY = boxTop + effectiveLineHeight + 1;
|
||||||
|
} else if (isSelectedOption) {
|
||||||
|
display->setColor(WHITE);
|
||||||
|
display->fillRect(boxLeft, lineY, boxWidth, effectiveLineHeight);
|
||||||
|
display->setColor(BLACK);
|
||||||
|
if (lineLengths[i] > 15 && lineWidths[i] > visibleWidth) {
|
||||||
|
int textX = boxLeft + hPadding + swingOffset;
|
||||||
|
display->drawString(textX, lineY - 1, lineBuffer);
|
||||||
|
} else {
|
||||||
|
display->drawString(boxLeft + (boxWidth - lineWidths[i]) / 2, lineY - 1, lineBuffer);
|
||||||
|
}
|
||||||
|
display->setColor(WHITE);
|
||||||
|
lineY += effectiveLineHeight;
|
||||||
} else {
|
} else {
|
||||||
int16_t textX = boxLeft + (boxWidth - lineWidths[i]) / 2;
|
// Draw non-selected, non-title lines
|
||||||
display->drawString(textX, lineY, lineBuffer);
|
display->setColor(BLACK);
|
||||||
}
|
display->fillRect(boxLeft, lineY, boxWidth, effectiveLineHeight);
|
||||||
|
display->setColor(WHITE);
|
||||||
|
|
||||||
lineY += effectiveLineHeight;
|
// If this is the Signal line, center text + bars as one group
|
||||||
|
bool isSignalLine = (graphics::bannerSignalBars >= 0 && strstr(lineBuffer, "Signal:") != nullptr);
|
||||||
|
if (isSignalLine) {
|
||||||
|
const int totalBars = 5;
|
||||||
|
const int barWidth = 3;
|
||||||
|
const int barSpacing = 2;
|
||||||
|
const int barHeightStep = 2;
|
||||||
|
const int gap = 6;
|
||||||
|
|
||||||
|
int textWidth = display->getStringWidth(lineBuffer, strlen(lineBuffer), true);
|
||||||
|
int barsWidth = totalBars * barWidth + (totalBars - 1) * barSpacing + gap;
|
||||||
|
int totalWidth = textWidth + barsWidth;
|
||||||
|
int groupStartX = boxLeft + (boxWidth - totalWidth) / 2;
|
||||||
|
|
||||||
|
// Draw the "Signal: ..." text
|
||||||
|
display->drawString(groupStartX, lineY, lineBuffer);
|
||||||
|
|
||||||
|
// Draw the bars
|
||||||
|
int baseX = groupStartX + textWidth + gap;
|
||||||
|
int baseY = lineY + effectiveLineHeight - 1;
|
||||||
|
for (int b = 0; b < totalBars; b++) {
|
||||||
|
int barHeight = (b + 1) * barHeightStep;
|
||||||
|
int x = baseX + b * (barWidth + barSpacing);
|
||||||
|
int y = baseY - barHeight;
|
||||||
|
|
||||||
|
if (b < graphics::bannerSignalBars) {
|
||||||
|
display->fillRect(x, y, barWidth, barHeight);
|
||||||
|
} else {
|
||||||
|
display->drawRect(x, y, barWidth, barHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal centered line
|
||||||
|
display->drawString(boxLeft + (boxWidth - lineWidths[i]) / 2, lineY, lineBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
lineY += effectiveLineHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll Bar (Thicker, inside box, not over title)
|
// Scroll Bar (Thicker, inside box, not over title)
|
||||||
@ -671,47 +736,66 @@ void NotificationRenderer::drawNotificationBox(OLEDDisplay *display, OLEDDisplay
|
|||||||
// Draw Content
|
// Draw Content
|
||||||
int16_t lineY = boxTop + vPadding;
|
int16_t lineY = boxTop + vPadding;
|
||||||
for (int i = 0; i < lineCount; i++) {
|
for (int i = 0; i < lineCount; i++) {
|
||||||
|
int16_t textX = boxLeft + (boxWidth - lineWidths[i]) / 2;
|
||||||
|
if (needs_bell && i == 0) {
|
||||||
|
int bellY = lineY + (FONT_HEIGHT_SMALL - 8) / 2;
|
||||||
|
display->drawXbm(textX - 10, bellY, 8, 8, bell_alert);
|
||||||
|
display->drawXbm(textX + lineWidths[i] + 2, bellY, 8, 8, bell_alert);
|
||||||
|
}
|
||||||
char lineBuffer[lineLengths[i] + 1];
|
char lineBuffer[lineLengths[i] + 1];
|
||||||
strncpy(lineBuffer, lines[i], lineLengths[i]);
|
strncpy(lineBuffer, lines[i], lineLengths[i]);
|
||||||
lineBuffer[lineLengths[i]] = '\0';
|
lineBuffer[lineLengths[i]] = '\0';
|
||||||
|
// Determine if this is a pop-up or a pick list
|
||||||
bool isSignalLine = (bannerSignalBars >= 0 && strstr(lineBuffer, "Signal:") != nullptr);
|
if (alertBannerOptions > 0 && i == 0) {
|
||||||
|
// Pick List
|
||||||
if (isSignalLine) {
|
display->setColor(WHITE);
|
||||||
// Center text + signal bars as a single group
|
int background_yOffset = 1;
|
||||||
const int totalBars = 5;
|
// Determine if we have low hanging characters
|
||||||
const int barWidth = 3;
|
if (strchr(lineBuffer, 'p') || strchr(lineBuffer, 'g') || strchr(lineBuffer, 'y') || strchr(lineBuffer, 'j')) {
|
||||||
const int barSpacing = 2;
|
background_yOffset = -1;
|
||||||
const int barHeightStep = 2;
|
|
||||||
|
|
||||||
int textWidth = display->getStringWidth(lineBuffer, strlen(lineBuffer), true);
|
|
||||||
int barsWidth = totalBars * barWidth + (totalBars - 1) * barSpacing + 6;
|
|
||||||
int totalWidth = textWidth + barsWidth;
|
|
||||||
|
|
||||||
int groupStartX = boxLeft + (boxWidth - totalWidth) / 2;
|
|
||||||
|
|
||||||
display->drawString(groupStartX, lineY, lineBuffer);
|
|
||||||
|
|
||||||
int baseX = groupStartX + textWidth + 6;
|
|
||||||
int baseY = lineY + effectiveLineHeight - 1;
|
|
||||||
|
|
||||||
for (int b = 0; b < totalBars; b++) {
|
|
||||||
int barHeight = (b + 1) * barHeightStep;
|
|
||||||
int x = baseX + b * (barWidth + barSpacing);
|
|
||||||
int y = baseY - barHeight;
|
|
||||||
|
|
||||||
if (b < bannerSignalBars) {
|
|
||||||
display->fillRect(x, y, barWidth, barHeight);
|
|
||||||
} else {
|
|
||||||
display->drawRect(x, y, barWidth, barHeight);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
display->fillRect(boxLeft, boxTop + 1, boxWidth, effectiveLineHeight - background_yOffset);
|
||||||
|
display->setColor(BLACK);
|
||||||
|
int yOffset = 3;
|
||||||
|
display->drawString(textX, lineY - yOffset, lineBuffer);
|
||||||
|
display->setColor(WHITE);
|
||||||
|
lineY += (effectiveLineHeight - 2 - background_yOffset);
|
||||||
} else {
|
} else {
|
||||||
int16_t textX = boxLeft + (boxWidth - lineWidths[i]) / 2;
|
// Pop-up
|
||||||
display->drawString(textX, lineY, lineBuffer);
|
// If this is the Signal line, center text + bars as one group
|
||||||
}
|
bool isSignalLine = (graphics::bannerSignalBars >= 0 && strstr(lineBuffer, "Signal:") != nullptr);
|
||||||
|
if (isSignalLine) {
|
||||||
|
const int totalBars = 5;
|
||||||
|
const int barWidth = 3;
|
||||||
|
const int barSpacing = 2;
|
||||||
|
const int barHeightStep = 2;
|
||||||
|
const int gap = 6;
|
||||||
|
|
||||||
lineY += effectiveLineHeight;
|
int textWidth = display->getStringWidth(lineBuffer, strlen(lineBuffer), true);
|
||||||
|
int barsWidth = totalBars * barWidth + (totalBars - 1) * barSpacing + gap;
|
||||||
|
int totalWidth = textWidth + barsWidth;
|
||||||
|
int groupStartX = boxLeft + (boxWidth - totalWidth) / 2;
|
||||||
|
|
||||||
|
display->drawString(groupStartX, lineY, lineBuffer);
|
||||||
|
|
||||||
|
int baseX = groupStartX + textWidth + gap;
|
||||||
|
int baseY = lineY + effectiveLineHeight - 1;
|
||||||
|
for (int b = 0; b < totalBars; b++) {
|
||||||
|
int barHeight = (b + 1) * barHeightStep;
|
||||||
|
int x = baseX + b * (barWidth + barSpacing);
|
||||||
|
int y = baseY - barHeight;
|
||||||
|
|
||||||
|
if (b < graphics::bannerSignalBars) {
|
||||||
|
display->fillRect(x, y, barWidth, barHeight);
|
||||||
|
} else {
|
||||||
|
display->drawRect(x, y, barWidth, barHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
display->drawString(textX, lineY, lineBuffer);
|
||||||
|
}
|
||||||
|
lineY += (effectiveLineHeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scroll Bar (Thicker, inside box, not over title)
|
// Scroll Bar (Thicker, inside box, not over title)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user