Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions examples/companion_radio/ui-new/UITask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class HomeScreen : public UIScreen {
bool _shutdown_init;
AdvertPath recent[UI_RECENT_LIST_SIZE];


void renderBatteryIndicator(DisplayDriver& display, uint16_t batteryMilliVolts) {
// Convert millivolts to percentage
const int minMilliVolts = 3000; // Minimum voltage (e.g., 3.0V)
Expand Down Expand Up @@ -157,10 +158,12 @@ class HomeScreen : public UIScreen {
int render(DisplayDriver& display) override {
char tmp[80];
// node name
display.setCursor(0, 0);
display.setTextSize(1);
display.setColor(DisplayDriver::GREEN);
display.print(_node_prefs->node_name);
char filtered_name[sizeof(_node_prefs->node_name)];
display.translateUTF8ToBlocks(filtered_name, _node_prefs->node_name, sizeof(filtered_name));
display.setCursor(0, 0);
display.print(filtered_name);

// battery voltage
renderBatteryIndicator(display, _task->getBattMilliVolts());
Expand Down Expand Up @@ -199,8 +202,6 @@ class HomeScreen : public UIScreen {
for (int i = 0; i < UI_RECENT_LIST_SIZE; i++, y += 11) {
auto a = &recent[i];
if (a->name[0] == 0) continue; // empty slot
display.setCursor(0, y);
display.print(a->name);
int secs = _rtc->getCurrentTime() - a->recv_timestamp;
if (secs < 60) {
sprintf(tmp, "%ds", secs);
Expand All @@ -209,7 +210,14 @@ class HomeScreen : public UIScreen {
} else {
sprintf(tmp, "%dh", secs / (60*60));
}
display.setCursor(display.width() - display.getTextWidth(tmp) - 1, y);

int timestamp_width = display.getTextWidth(tmp);
int max_name_width = display.width() - timestamp_width - 1;

char filtered_recent_name[sizeof(a->name)];
display.translateUTF8ToBlocks(filtered_recent_name, a->name, sizeof(filtered_recent_name));
display.drawTextEllipsized(0, y, max_name_width, filtered_recent_name);
display.setCursor(display.width() - timestamp_width - 1, y);
display.print(tmp);
}
} else if (_page == HomePage::RADIO) {
Expand Down Expand Up @@ -427,11 +435,15 @@ class MsgPreviewScreen : public UIScreen {

display.setCursor(0, 14);
display.setColor(DisplayDriver::YELLOW);
display.print(p->origin);
char filtered_origin[sizeof(p->origin)];
display.translateUTF8ToBlocks(filtered_origin, p->origin, sizeof(filtered_origin));
display.print(filtered_origin);

display.setCursor(0, 25);
display.setColor(DisplayDriver::LIGHT);
display.printWordWrap(p->msg, display.width());
char filtered_msg[sizeof(p->msg)];
display.translateUTF8ToBlocks(filtered_msg, p->msg, sizeof(filtered_msg));
display.printWordWrap(filtered_msg, display.width());

#if AUTO_OFF_MILLIS==0 // probably e-ink
return 10000; // 10 s
Expand Down
56 changes: 56 additions & 0 deletions src/helpers/ui/DisplayDriver.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <stdint.h>
#include <string.h>

class DisplayDriver {
int _w, _h;
Expand Down Expand Up @@ -31,5 +32,60 @@ class DisplayDriver {
setCursor(mid_x - w/2, y);
print(str);
}

// convert UTF-8 characters to displayable block characters for compatibility
virtual void translateUTF8ToBlocks(char* dest, const char* src, size_t dest_size) {
size_t j = 0;
for (size_t i = 0; src[i] != 0 && j < dest_size - 1; i++) {
unsigned char c = (unsigned char)src[i];
if (c >= 32 && c <= 126) {
dest[j++] = c; // ASCII printable
} else if (c >= 0x80) {
dest[j++] = '\xDB'; // CP437 full block █
while (src[i+1] && (src[i+1] & 0xC0) == 0x80)
i++; // skip UTF-8 continuation bytes
}
}
dest[j] = 0;
}

// draw text with ellipsis if it exceeds max_width
virtual void drawTextEllipsized(int x, int y, int max_width, const char* str) {
char temp_str[256]; // reasonable buffer size
size_t len = strlen(str);
if (len >= sizeof(temp_str)) len = sizeof(temp_str) - 1;
memcpy(temp_str, str, len);
temp_str[len] = 0;

if (getTextWidth(temp_str) <= max_width) {
setCursor(x, y);
print(temp_str);
return;
}

// for variable-width fonts (GxEPD), add space after ellipsis
// for fixed-width fonts (OLED), keep tight spacing to save precious characters
const char* ellipsis;
// use a simple heuristic: if 'i' and 'l' have different widths, it's variable-width
int i_width = getTextWidth("i");
int l_width = getTextWidth("l");
if (i_width != l_width) {
ellipsis = "... "; // variable-width fonts: add space
} else {
ellipsis = "..."; // fixed-width fonts: no space
}

int ellipsis_width = getTextWidth(ellipsis);
int str_len = strlen(temp_str);

while (str_len > 0 && getTextWidth(temp_str) > max_width - ellipsis_width) {
temp_str[--str_len] = 0;
}
strcat(temp_str, ellipsis);

setCursor(x, y);
print(temp_str);
}

virtual void endFrame() = 0;
};