fix: dynamic layout and pixel-accurate word-wrap in companion radio UI

- All menu screens (Tools, Bot, Settings) now derive item height from
  display.getLineHeight() instead of hardcoded constants, preventing
  item overflow on 64px OLED displays
- ToolsScreen caps rendered items to screen height so Char Test is visible
- FullscreenMsgView word-wrap now uses display.getTextWidth() per candidate
  line instead of fixed char count, correctly handles variable-width and
  multi-byte UTF-8 glyphs; FS_CHARS_MAX increased 32→80
- CharTestScreen: fix v-arrow y-position; remove stale "→ blocks █" comments

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-05-18 09:26:11 +02:00
co-authored by Claude Sonnet 4.6
parent 50eb58c276
commit acc062718f
5 changed files with 80 additions and 40 deletions
@@ -18,19 +18,23 @@ public:
display.drawTextCentered(display.width() / 2, 0, "TOOLS");
display.fillRect(0, 10, display.width(), 1);
for (int i = 0; i < ITEM_COUNT; i++) {
int y = 12 + i * 12;
const int lineH = display.getLineHeight();
const int itemH = lineH + 1;
const int startY = 12;
const int visible = (display.height() - startY) / itemH;
for (int i = 0; i < ITEM_COUNT && i < visible; i++) {
int y = startY + i * itemH;
bool sel = (i == _sel);
if (sel) {
display.setColor(DisplayDriver::LIGHT);
display.fillRect(0, y - 1, display.width(), 11);
display.fillRect(0, y - 1, display.width(), itemH);
display.setColor(DisplayDriver::DARK);
} else {
display.setColor(DisplayDriver::LIGHT);
}
display.setCursor(0, y);
display.print(sel ? ">" : " ");
display.setCursor(8, y);
display.setCursor(display.getCharWidth() + 3, y);
display.print(ITEMS[i]);
}
display.setColor(DisplayDriver::LIGHT);