Skip to content

Commit f77fd15

Browse files
authored
Merge pull request #730 from michaelhart/node-displayname-improvements
Adds name filtering and text truncation for display in HomeScreen
2 parents e35e4bb + bd6aa98 commit f77fd15

File tree

2 files changed

+75
-7
lines changed

2 files changed

+75
-7
lines changed

examples/companion_radio/ui-new/UITask.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class HomeScreen : public UIScreen {
9090
bool _shutdown_init;
9191
AdvertPath recent[UI_RECENT_LIST_SIZE];
9292

93+
9394
void renderBatteryIndicator(DisplayDriver& display, uint16_t batteryMilliVolts) {
9495
// Convert millivolts to percentage
9596
const int minMilliVolts = 3000; // Minimum voltage (e.g., 3.0V)
@@ -157,10 +158,12 @@ class HomeScreen : public UIScreen {
157158
int render(DisplayDriver& display) override {
158159
char tmp[80];
159160
// node name
160-
display.setCursor(0, 0);
161161
display.setTextSize(1);
162162
display.setColor(DisplayDriver::GREEN);
163-
display.print(_node_prefs->node_name);
163+
char filtered_name[sizeof(_node_prefs->node_name)];
164+
display.translateUTF8ToBlocks(filtered_name, _node_prefs->node_name, sizeof(filtered_name));
165+
display.setCursor(0, 0);
166+
display.print(filtered_name);
164167

165168
// battery voltage
166169
renderBatteryIndicator(display, _task->getBattMilliVolts());
@@ -199,8 +202,6 @@ class HomeScreen : public UIScreen {
199202
for (int i = 0; i < UI_RECENT_LIST_SIZE; i++, y += 11) {
200203
auto a = &recent[i];
201204
if (a->name[0] == 0) continue; // empty slot
202-
display.setCursor(0, y);
203-
display.print(a->name);
204205
int secs = _rtc->getCurrentTime() - a->recv_timestamp;
205206
if (secs < 60) {
206207
sprintf(tmp, "%ds", secs);
@@ -209,7 +210,14 @@ class HomeScreen : public UIScreen {
209210
} else {
210211
sprintf(tmp, "%dh", secs / (60*60));
211212
}
212-
display.setCursor(display.width() - display.getTextWidth(tmp) - 1, y);
213+
214+
int timestamp_width = display.getTextWidth(tmp);
215+
int max_name_width = display.width() - timestamp_width - 1;
216+
217+
char filtered_recent_name[sizeof(a->name)];
218+
display.translateUTF8ToBlocks(filtered_recent_name, a->name, sizeof(filtered_recent_name));
219+
display.drawTextEllipsized(0, y, max_name_width, filtered_recent_name);
220+
display.setCursor(display.width() - timestamp_width - 1, y);
213221
display.print(tmp);
214222
}
215223
} else if (_page == HomePage::RADIO) {
@@ -427,11 +435,15 @@ class MsgPreviewScreen : public UIScreen {
427435

428436
display.setCursor(0, 14);
429437
display.setColor(DisplayDriver::YELLOW);
430-
display.print(p->origin);
438+
char filtered_origin[sizeof(p->origin)];
439+
display.translateUTF8ToBlocks(filtered_origin, p->origin, sizeof(filtered_origin));
440+
display.print(filtered_origin);
431441

432442
display.setCursor(0, 25);
433443
display.setColor(DisplayDriver::LIGHT);
434-
display.printWordWrap(p->msg, display.width());
444+
char filtered_msg[sizeof(p->msg)];
445+
display.translateUTF8ToBlocks(filtered_msg, p->msg, sizeof(filtered_msg));
446+
display.printWordWrap(filtered_msg, display.width());
435447

436448
#if AUTO_OFF_MILLIS==0 // probably e-ink
437449
return 10000; // 10 s

src/helpers/ui/DisplayDriver.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <stdint.h>
4+
#include <string.h>
45

56
class DisplayDriver {
67
int _w, _h;
@@ -31,5 +32,60 @@ class DisplayDriver {
3132
setCursor(mid_x - w/2, y);
3233
print(str);
3334
}
35+
36+
// convert UTF-8 characters to displayable block characters for compatibility
37+
virtual void translateUTF8ToBlocks(char* dest, const char* src, size_t dest_size) {
38+
size_t j = 0;
39+
for (size_t i = 0; src[i] != 0 && j < dest_size - 1; i++) {
40+
unsigned char c = (unsigned char)src[i];
41+
if (c >= 32 && c <= 126) {
42+
dest[j++] = c; // ASCII printable
43+
} else if (c >= 0x80) {
44+
dest[j++] = '\xDB'; // CP437 full block █
45+
while (src[i+1] && (src[i+1] & 0xC0) == 0x80)
46+
i++; // skip UTF-8 continuation bytes
47+
}
48+
}
49+
dest[j] = 0;
50+
}
51+
52+
// draw text with ellipsis if it exceeds max_width
53+
virtual void drawTextEllipsized(int x, int y, int max_width, const char* str) {
54+
char temp_str[256]; // reasonable buffer size
55+
size_t len = strlen(str);
56+
if (len >= sizeof(temp_str)) len = sizeof(temp_str) - 1;
57+
memcpy(temp_str, str, len);
58+
temp_str[len] = 0;
59+
60+
if (getTextWidth(temp_str) <= max_width) {
61+
setCursor(x, y);
62+
print(temp_str);
63+
return;
64+
}
65+
66+
// for variable-width fonts (GxEPD), add space after ellipsis
67+
// for fixed-width fonts (OLED), keep tight spacing to save precious characters
68+
const char* ellipsis;
69+
// use a simple heuristic: if 'i' and 'l' have different widths, it's variable-width
70+
int i_width = getTextWidth("i");
71+
int l_width = getTextWidth("l");
72+
if (i_width != l_width) {
73+
ellipsis = "... "; // variable-width fonts: add space
74+
} else {
75+
ellipsis = "..."; // fixed-width fonts: no space
76+
}
77+
78+
int ellipsis_width = getTextWidth(ellipsis);
79+
int str_len = strlen(temp_str);
80+
81+
while (str_len > 0 && getTextWidth(temp_str) > max_width - ellipsis_width) {
82+
temp_str[--str_len] = 0;
83+
}
84+
strcat(temp_str, ellipsis);
85+
86+
setCursor(x, y);
87+
print(temp_str);
88+
}
89+
3490
virtual void endFrame() = 0;
3591
};

0 commit comments

Comments
 (0)