mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
fix(ui): unified unknown-char block rendering and display layout fixes
- GxEPDDisplay::print() renders '\xDB' as filled rect for Lemon font, matching OLED Lemon block behavior - Remove translateUTF8ToBlocks override (base class passthrough sufficient) - transliterateCodepoint fallback changed '?' → '\xDB' for consistency - drawTextCentered/Right/LeftAlign now call translateUTF8ToBlocks - isLemonFont() added to DisplayDriver, SH1106Display, GxEPDDisplay - isLandscape() guarded by EINK_DISPLAY_MODEL to distinguish OLED vs e-ink - ind_h trims indicator box height only for Lemon font - getTextWidth disables wrap before getTextBounds, restores after - QuickMsgScreen: tighter hist_item padding; 2 messages visible with Lemon - Hibernate hint fits on one line when width allows, splits otherwise - BLE PIN page shows toggle hint on landscape e-ink - Remove unused muted_icon bitmap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,8 +87,9 @@ class QuickMsgScreen : public UIScreen {
|
||||
static const char* skipReplyPrefix(const char* text) {
|
||||
if (text[0] == '@' && text[1] == '[') {
|
||||
const char* close = strchr(text + 2, ']');
|
||||
if (close && close[1] == ' ' && close[2]) return close + 2;
|
||||
if (close && close[1] == ' ' && close[2]) text = close + 2;
|
||||
}
|
||||
while (*text == '\n' || *text == '\r' || *text == ' ') text++;
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -630,13 +631,12 @@ public:
|
||||
return 500;
|
||||
}
|
||||
|
||||
int hist_box_h = 2 * lh + 3;
|
||||
int hist_item_h = hist_box_h + 2;
|
||||
int hist_box_h = 2 * lh + 1;
|
||||
int hist_item_h = hist_box_h + 1;
|
||||
int hist_start_y = display.headerH();
|
||||
int btn_h = lh + 4;
|
||||
_hist_visible = (display.height() - hist_start_y - btn_h) / hist_item_h;
|
||||
if (_hist_visible < 1) _hist_visible = 1;
|
||||
int cby = display.height() - lh - 2;
|
||||
_hist_visible = (cby - 1 - hist_start_y) / hist_item_h;
|
||||
if (_hist_visible < 1) _hist_visible = 1;
|
||||
|
||||
char title[24];
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
@@ -666,7 +666,7 @@ public:
|
||||
display.setColor(DisplayDriver::DARK);
|
||||
display.drawTextEllipsized(3, y + 1, display.width() - cw - 2 - age_w, sender);
|
||||
if (age[0]) { display.setCursor(display.width() - 3 - display.getTextWidth(age), y + 1); display.print(age); }
|
||||
display.drawTextEllipsized(3, y + lh + 2, display.width() - cw - 2, skipReplyPrefix(e.text));
|
||||
display.drawTextEllipsized(3, y + lh + 1, display.width() - cw - 2, skipReplyPrefix(e.text));
|
||||
} else {
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawRect(0, y, display.width(), hist_box_h);
|
||||
@@ -675,7 +675,7 @@ public:
|
||||
display.drawTextEllipsized(3, y + 1, display.width() - cw - 2 - age_w, sender);
|
||||
if (age[0]) { display.setCursor(display.width() - 3 - display.getTextWidth(age), y + 1); display.print(age); }
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawTextEllipsized(3, y + lh + 2, display.width() - cw - 2, skipReplyPrefix(e.text));
|
||||
display.drawTextEllipsized(3, y + lh + 1, display.width() - cw - 2, skipReplyPrefix(e.text));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -733,13 +733,12 @@ public:
|
||||
return 2000;
|
||||
}
|
||||
|
||||
int hist_box_h = 2 * lh + 3;
|
||||
int hist_item_h = hist_box_h + 2;
|
||||
int hist_box_h = 2 * lh + 1;
|
||||
int hist_item_h = hist_box_h + 1;
|
||||
int hist_start_y = display.headerH();
|
||||
int btn_h = lh + 4;
|
||||
_hist_visible = (display.height() - hist_start_y - btn_h) / hist_item_h;
|
||||
if (_hist_visible < 1) _hist_visible = 1;
|
||||
int cby = display.height() - lh - 2;
|
||||
_hist_visible = (cby - 1 - hist_start_y) / hist_item_h;
|
||||
if (_hist_visible < 1) _hist_visible = 1;
|
||||
|
||||
ChannelDetails ch;
|
||||
the_mesh.getChannel(_sel_channel_idx, ch);
|
||||
@@ -781,7 +780,7 @@ public:
|
||||
display.setColor(DisplayDriver::DARK);
|
||||
display.drawTextEllipsized(3, y + 1, display.width() - cw - 2 - age_w, sender);
|
||||
if (age[0]) { display.setCursor(display.width() - 3 - display.getTextWidth(age), y + 1); display.print(age); }
|
||||
display.drawTextEllipsized(3, y + lh + 2, display.width() - cw - 2, skipReplyPrefix(msg_part));
|
||||
display.drawTextEllipsized(3, y + lh + 1, display.width() - cw - 2, skipReplyPrefix(msg_part));
|
||||
} else {
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawRect(0, y, display.width(), hist_box_h);
|
||||
@@ -790,7 +789,7 @@ public:
|
||||
display.drawTextEllipsized(3, y + 1, display.width() - cw - 2 - age_w, sender);
|
||||
if (age[0]) { display.setCursor(display.width() - 3 - display.getTextWidth(age), y + 1); display.print(age); }
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawTextEllipsized(3, y + lh + 2, display.width() - cw - 2, skipReplyPrefix(msg_part));
|
||||
display.drawTextEllipsized(3, y + lh + 1, display.width() - cw - 2, skipReplyPrefix(msg_part));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -291,7 +291,8 @@ class HomeScreen : public UIScreen {
|
||||
const int lh = display.getLineHeight();
|
||||
const int cw = display.getCharWidth();
|
||||
const int ind = cw + 2; // single-char indicator width
|
||||
const int ind_gap = (lh >= 16) ? 3 : 1; // gap between indicator boxes
|
||||
const int ind_h = display.isLemonFont() ? lh - 2 : lh;
|
||||
const int ind_gap = display.isLandscape() ? 3 : 1; // gap between indicator boxes
|
||||
|
||||
int battLeftX;
|
||||
if (mode == 1) { // percent
|
||||
@@ -309,7 +310,7 @@ class HomeScreen : public UIScreen {
|
||||
} else { // icon — scales with lh
|
||||
const int iconH = lh;
|
||||
const int iconW = lh * 2;
|
||||
const int bm = (lh >= 16) ? 3 : 2; // inner margin: 3px on landscape (2px border), 2px on OLED
|
||||
const int bm = display.isLandscape() ? 3 : 2; // inner margin: 3px on landscape e-ink, 2px on OLED/portrait
|
||||
battLeftX = display.width() - iconW - 3;
|
||||
display.drawRect(battLeftX, 0, iconW, iconH);
|
||||
display.fillRect(battLeftX + iconW, iconH / 4, 2, iconH / 2);
|
||||
@@ -321,7 +322,7 @@ class HomeScreen : public UIScreen {
|
||||
if (_task->isBuzzerQuiet()) {
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
int mx = battLeftX - ind - ind_gap;
|
||||
display.fillRect(mx, 0, ind, lh);
|
||||
display.fillRect(mx, 0, ind, ind_h);
|
||||
display.setColor(DisplayDriver::DARK);
|
||||
display.setCursor(mx + 1, 0);
|
||||
display.print("M");
|
||||
@@ -336,7 +337,7 @@ class HomeScreen : public UIScreen {
|
||||
int btX = battLeftX - ind - ind_gap;
|
||||
if (_task->hasConnection()) {
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.fillRect(btX, 0, ind, lh);
|
||||
display.fillRect(btX, 0, ind, ind_h);
|
||||
display.setColor(DisplayDriver::DARK);
|
||||
display.setCursor(btX + 1, 0);
|
||||
display.print("B");
|
||||
@@ -357,7 +358,7 @@ class HomeScreen : public UIScreen {
|
||||
#endif
|
||||
if (show_a) {
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.fillRect(aX, 0, ind, lh);
|
||||
display.fillRect(aX, 0, ind, ind_h);
|
||||
display.setColor(DisplayDriver::DARK);
|
||||
display.setCursor(aX + 1, 0);
|
||||
display.print("A");
|
||||
@@ -435,7 +436,7 @@ public:
|
||||
for (int i = 0; i < n; i++) if (order[i] == _page) { curr_vis = i; break; }
|
||||
int x = display.width() / 2 - 5 * (n - 1);
|
||||
for (int i = 0; i < n; i++) {
|
||||
int ds = (lh >= 16) ? 2 : 1;
|
||||
int ds = display.isLandscape() ? 2 : 1;
|
||||
if (i == curr_vis) display.fillRect(x-ds, dots_y-ds, 2*ds+1, 2*ds+1);
|
||||
else display.fillRect(x-ds+1, dots_y-ds+1, 2*ds-1, 2*ds-1);
|
||||
x += 10;
|
||||
@@ -460,7 +461,11 @@ public:
|
||||
char buf[24];
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.setTextSize(2);
|
||||
#ifdef EINK_DISPLAY_MODEL
|
||||
bool show_sec = false;
|
||||
#else
|
||||
bool show_sec = !_node_prefs || !_node_prefs->clock_hide_seconds;
|
||||
#endif
|
||||
bool h12 = _node_prefs && _node_prefs->clock_12h;
|
||||
if (h12) {
|
||||
int h = ti->tm_hour % 12; if (h == 0) h = 12;
|
||||
@@ -609,19 +614,23 @@ public:
|
||||
display.print(tmp);
|
||||
} else if (_page == HomePage::BLUETOOTH) {
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
int icon_y = content_y;
|
||||
display.drawXbm((display.width() - 32) / 2, icon_y,
|
||||
_task->isSerialEnabled() ? bluetooth_on : bluetooth_off,
|
||||
32, 32);
|
||||
display.setTextSize(1);
|
||||
int pin_y = icon_y + 32 + 3;
|
||||
int hint_y = pin_y + step;
|
||||
if (_task->isSerialEnabled() && !_task->hasConnection() && the_mesh.getBLEPin() != 0) {
|
||||
display.drawXbm((display.width() - 32) / 2, content_y,
|
||||
_task->isSerialEnabled() ? bluetooth_on : bluetooth_off, 32, 32);
|
||||
const int text_y = content_y + 32 + 3;
|
||||
const bool waiting_for_pair = _task->isSerialEnabled() && !_task->hasConnection() && the_mesh.getBLEPin() != 0;
|
||||
if (waiting_for_pair && !display.isLandscape()) {
|
||||
char pin_buf[16];
|
||||
snprintf(pin_buf, sizeof(pin_buf), "PIN: %d", the_mesh.getBLEPin());
|
||||
display.drawTextCentered(display.width() / 2, pin_y, pin_buf);
|
||||
display.drawTextCentered(display.width() / 2, text_y, pin_buf);
|
||||
} else if (waiting_for_pair) {
|
||||
char pin_buf[16];
|
||||
snprintf(pin_buf, sizeof(pin_buf), "PIN: %d", the_mesh.getBLEPin());
|
||||
display.drawTextCentered(display.width() / 2, text_y, pin_buf);
|
||||
display.drawTextCentered(display.width() / 2, text_y + step, "toggle: " PRESS_LABEL);
|
||||
} else {
|
||||
display.drawTextCentered(display.width() / 2, text_y, "toggle: " PRESS_LABEL);
|
||||
}
|
||||
display.drawTextCentered(display.width() / 2, hint_y, "toggle: " PRESS_LABEL);
|
||||
} else if (_page == HomePage::ADVERT) {
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawXbm((display.width() - 32) / 2, content_y, advert_icon, 32, 32);
|
||||
@@ -766,9 +775,19 @@ public:
|
||||
display.drawTextCentered(display.width() / 2, content_y + step, "hibernating...");
|
||||
} else {
|
||||
display.drawXbm((display.width() - 32) / 2, content_y, power_icon, 32, 32);
|
||||
int hint_base = content_y + 32 + 3;
|
||||
display.drawTextCentered(display.width() / 2, hint_base, "hibernate:");
|
||||
display.drawTextCentered(display.width() / 2, hint_base + step, PRESS_LABEL);
|
||||
const int text_y = content_y + 32 + 3;
|
||||
const int lh1 = display.getLineHeight();
|
||||
if (text_y + lh1 <= display.height()) {
|
||||
char hib_hint[32];
|
||||
snprintf(hib_hint, sizeof(hib_hint), "hibernate: %s", PRESS_LABEL);
|
||||
if (display.getTextWidth(hib_hint) < display.width()) {
|
||||
display.drawTextCentered(display.width() / 2, text_y, hib_hint);
|
||||
} else {
|
||||
display.drawTextCentered(display.width() / 2, text_y, "hibernate:");
|
||||
if (text_y + step + lh1 <= display.height())
|
||||
display.drawTextCentered(display.width() / 2, text_y + step, PRESS_LABEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool auto_adv = _node_prefs && _node_prefs->advert_auto_interval_sec > 0;
|
||||
|
||||
@@ -116,7 +116,3 @@ static const uint8_t advert_icon[] = {
|
||||
0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const uint8_t muted_icon[] = {
|
||||
0x20, 0x6a, 0xea, 0xe4, 0xe4, 0xea, 0x6a, 0x20
|
||||
};
|
||||
Reference in New Issue
Block a user