From d981f93e6e3f2564a27f68ca035cff408fd2f69a Mon Sep 17 00:00:00 2001 From: Jakub <106778416+MarekZegare4@users.noreply.github.com> Date: Sun, 24 May 2026 20:33:02 +0200 Subject: [PATCH] refactor(ui): drawSelectionRow helper for the 5-line invert/restore pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eight screens repeated the same if/else block to invert the row background for selected items. Add DisplayDriver::drawSelectionRow that sets LIGHT, optionally fills the rect, and leaves the colour as DARK when sel (so the caller's text renders inverted). 61 lines removed across SettingsScreen, KeyboardWidget (cells + special row), ToolsScreen, DashboardConfigScreen, BotScreen, RingtoneEditorScreen (note slots + menu), NearbyScreen, QuickMsgScreen (4 list views). Card-style rows (QuickMsg hist, NearbyScreen discover, RingtoneEditor notes display) keep their original drawRect/partial-fill outline for unselected — they don't match the simple-invert pattern. Co-Authored-By: Claude Sonnet 4.6 --- examples/companion_radio/ui-new/BotScreen.h | 5 +-- .../ui-new/DashboardConfigScreen.h | 8 +---- .../companion_radio/ui-new/KeyboardWidget.h | 16 ++-------- .../companion_radio/ui-new/NearbyScreen.h | 8 +---- .../companion_radio/ui-new/QuickMsgScreen.h | 32 +++---------------- .../ui-new/RingtoneEditorScreen.h | 13 ++------ .../companion_radio/ui-new/SettingsScreen.h | 9 +----- examples/companion_radio/ui-new/ToolsScreen.h | 8 +---- src/helpers/ui/DisplayDriver.h | 12 +++++++ 9 files changed, 25 insertions(+), 86 deletions(-) diff --git a/examples/companion_radio/ui-new/BotScreen.h b/examples/companion_radio/ui-new/BotScreen.h index 393d43f6..9be907bb 100644 --- a/examples/companion_radio/ui-new/BotScreen.h +++ b/examples/companion_radio/ui-new/BotScreen.h @@ -68,10 +68,7 @@ public: for (int i = 0; i < ITEM_COUNT; i++) { int y = start_y + i * item_h; bool sel = (i == _sel); - if (sel) { - display.fillRect(0, y - 1, display.width(), item_h); - display.setColor(DisplayDriver::DARK); - } + display.drawSelectionRow(0, y - 1, display.width(), item_h, sel); display.setCursor(2, y); display.print(labels[i]); display.setCursor(val_x, y); diff --git a/examples/companion_radio/ui-new/DashboardConfigScreen.h b/examples/companion_radio/ui-new/DashboardConfigScreen.h index 15957c5d..1029684e 100644 --- a/examples/companion_radio/ui-new/DashboardConfigScreen.h +++ b/examples/companion_radio/ui-new/DashboardConfigScreen.h @@ -52,13 +52,7 @@ public: for (int i = 0; i < FIELD_SLOTS; i++) { int y = start_y + i * item_h; bool sel = (i == _sel); - if (sel) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(0, y - 1, display.width(), item_h); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(0, y - 1, display.width(), item_h, sel); display.setCursor(2, y); display.print(labels[i]); display.setCursor(val_x, y); diff --git a/examples/companion_radio/ui-new/KeyboardWidget.h b/examples/companion_radio/ui-new/KeyboardWidget.h index 2b4f4c8b..c450a953 100644 --- a/examples/companion_radio/ui-new/KeyboardWidget.h +++ b/examples/companion_radio/ui-new/KeyboardWidget.h @@ -109,13 +109,7 @@ struct KeyboardWidget { if (caps && ch >= 'a' && ch <= 'z') ch = ch - 'a' + 'A'; char ch_buf[2] = { ch == ' ' ? '_' : ch, '\0' }; int cx = c * cell_w; - if (sel) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(cx, y - 1, cell_w - 1, cell_h); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(cx, y - 1, cell_w - 1, cell_h, sel); display.setCursor(cx + (cell_w - cw) / 2, y); display.print(ch_buf); } @@ -127,13 +121,7 @@ struct KeyboardWidget { bool sel = (row == KB_ROWS_CHAR && col == i); bool active = (i == 0 && caps); int sx = i * spec_w; - if (sel || active) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(sx, spec_y - 1, spec_w - 1, cell_h); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(sx, spec_y - 1, spec_w - 1, cell_h, sel || active); int tw = display.getTextWidth(spec[i]); display.setCursor(sx + (spec_w - tw) / 2, spec_y); display.print(spec[i]); diff --git a/examples/companion_radio/ui-new/NearbyScreen.h b/examples/companion_radio/ui-new/NearbyScreen.h index 699de8c2..6bb339d5 100644 --- a/examples/companion_radio/ui-new/NearbyScreen.h +++ b/examples/companion_radio/ui-new/NearbyScreen.h @@ -473,13 +473,7 @@ public: int y = start_y + i * item_h; const Entry& e = _entries[idx]; - if (sel) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(0, y - 1, display.width(), item_h - 1); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(0, y - 1, display.width(), item_h - 1, sel); char filt[32]; display.translateUTF8ToBlocks(filt, e.name, sizeof(filt)); diff --git a/examples/companion_radio/ui-new/QuickMsgScreen.h b/examples/companion_radio/ui-new/QuickMsgScreen.h index e9094785..dcd67b1b 100644 --- a/examples/companion_radio/ui-new/QuickMsgScreen.h +++ b/examples/companion_radio/ui-new/QuickMsgScreen.h @@ -491,13 +491,7 @@ public: for (int i = 0; i < 3; i++) { int y = start_y + i * item_h; bool sel = (i == _mode_sel); - if (sel) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(0, y - 1, display.width(), item_h - 1); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(0, y - 1, display.width(), item_h - 1, sel); display.setCursor(0, y); display.print(sel ? ">" : " "); display.setCursor(cw + 2, y); @@ -527,13 +521,7 @@ public: bool sel = (list_idx == _contact_sel); int y = start_y + i * item_h; - if (sel) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(0, y - 1, display.width(), item_h - 1); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(0, y - 1, display.width(), item_h - 1, sel); ContactInfo c; if (the_mesh.getContactByIdx(mesh_idx, c)) { @@ -576,13 +564,7 @@ public: bool sel = (list_idx == _channel_sel); int y = start_y + i * item_h; - if (sel) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(0, y - 1, display.width(), item_h - 1); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(0, y - 1, display.width(), item_h - 1, sel); display.setCursor(0, y); display.print(sel ? ">" : " "); ChannelDetails ch; @@ -855,13 +837,7 @@ public: bool sel = (idx == _msg_sel); int y = start_y + i * item_h; - if (sel) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(0, y - 1, display.width(), item_h - 1); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(0, y - 1, display.width(), item_h - 1, sel); display.setCursor(0, y); display.print(sel ? ">" : " "); diff --git a/examples/companion_radio/ui-new/RingtoneEditorScreen.h b/examples/companion_radio/ui-new/RingtoneEditorScreen.h index c323b53e..9767d30c 100644 --- a/examples/companion_radio/ui-new/RingtoneEditorScreen.h +++ b/examples/companion_radio/ui-new/RingtoneEditorScreen.h @@ -119,13 +119,7 @@ public: display.print(label); display.setColor(DisplayDriver::LIGHT); } else if (ni == _len && _len < MAX_NOTES) { - if (sel) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(cx, notes_y, cell_w - 1, cell_h); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(cx, notes_y, cell_w - 1, cell_h, sel); display.setCursor(cx + (cell_w - cw) / 2, notes_y + 3); display.print("+"); display.setColor(DisplayDriver::LIGHT); @@ -164,10 +158,7 @@ public: if (item >= M_COUNT) break; int iy = my + 2 + i * menu_ih; bool sel = (item == _menu_sel); - if (sel) { - display.fillRect(mx + 1, iy - 1, mw - 2, menu_ih); - display.setColor(DisplayDriver::DARK); - } + display.drawSelectionRow(mx + 1, iy - 1, mw - 2, menu_ih, sel); display.setCursor(mx + 4, iy); if (item == M_PLAY_STOP) display.print(_task->isMelodyPlaying() ? "Stop" : "Play"); diff --git a/examples/companion_radio/ui-new/SettingsScreen.h b/examples/companion_radio/ui-new/SettingsScreen.h index f5591a3a..9e14c4d7 100644 --- a/examples/companion_radio/ui-new/SettingsScreen.h +++ b/examples/companion_radio/ui-new/SettingsScreen.h @@ -316,14 +316,7 @@ class SettingsScreen : public UIScreen { } bool sel = (item == _selected); - - if (sel) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(0, y - 1, display.width(), display.lineStep()); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(0, y - 1, display.width(), display.lineStep(), sel); display.setCursor(0, y); display.print(sel ? ">" : " "); diff --git a/examples/companion_radio/ui-new/ToolsScreen.h b/examples/companion_radio/ui-new/ToolsScreen.h index cde36181..05ffea86 100644 --- a/examples/companion_radio/ui-new/ToolsScreen.h +++ b/examples/companion_radio/ui-new/ToolsScreen.h @@ -25,13 +25,7 @@ public: for (int i = 0; i < ITEM_COUNT; i++) { int y = start_y + i * item_h; bool sel = (i == _sel); - if (sel) { - display.setColor(DisplayDriver::LIGHT); - display.fillRect(0, y - 1, display.width(), item_h); - display.setColor(DisplayDriver::DARK); - } else { - display.setColor(DisplayDriver::LIGHT); - } + display.drawSelectionRow(0, y - 1, display.width(), item_h, sel); display.setCursor(0, y); display.print(sel ? ">" : " "); display.setCursor(cw + 2, y); diff --git a/src/helpers/ui/DisplayDriver.h b/src/helpers/ui/DisplayDriver.h index a00fbbeb..07a53b1b 100644 --- a/src/helpers/ui/DisplayDriver.h +++ b/src/helpers/ui/DisplayDriver.h @@ -150,6 +150,18 @@ public: translateUTF8Static(dest, src, dest_size); } + // Common selection-row pattern: when sel, fills (x,y,w,h) with ink and sets + // colour to DARK so the next text render appears inverted; when not sel, + // just sets ink colour to LIGHT. Replaces the 5-line if/else copy-paste + // present in every list-style screen. + void drawSelectionRow(int x, int y, int w, int h, bool sel) { + setColor(LIGHT); + if (sel) { + fillRect(x, y, w, h); + setColor(DARK); + } + } + // Advance a UTF-8 pointer by one codepoint, returning the decoded value. // Invalid sequences return 0xFFFD and consume trailing continuation bytes. static uint32_t decodeCodepoint(const uint8_t*& p) {