refactor(ui): shared drawList + header + key-decode helpers

- drawList(): scrollable list skeleton (visible window, keep-sel-in-view,
  scroll-column reserve, per-row callback, indicator). Migrate Tools, Bot,
  Nearby, Waypoints list and the three QuickMsg lists onto it; centralises the
  scroll-clamp/reserve/indicator that each had open-coded (and inconsistently).
- drawCenteredHeader(): centred title + separator, replacing the duplicated
  two-liner across ~10 screens (incl. QuickMsg, which used width()/2 spacing and
  was missed before); unifies the separator at headerH()-sepH().
- keyIsPrev()/keyIsNext() in UIScreen.h for the LEFT||PREV / RIGHT||NEXT idiom;
  applied to 6 screens, behaviour-preserving. Cancel/context-menu stay
  per-screen (they mean different things on different screens).
- rotLabel() dedups the 0/90/180/270 array in Settings.
- Unify selection-row height to lineStep()-1 (Tools/Bot matched the rest).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-06-15 21:23:00 +02:00
co-authored by Claude Opus 4.8
parent 98af868e68
commit 9da730e3b6
13 changed files with 89 additions and 123 deletions
+22
View File
@@ -276,6 +276,28 @@ inline void drawScrollIndicator(DisplayDriver& d, int top_y, int track_h,
miniIconDrawHalo(d, x, top_y + track_h - th, ICON_SCROLL_DOWN);
}
// Scrollable item-list skeleton shared by the list screens. Computes the visible
// window from the font metrics, keeps `sel` in view, reserves the scroll-column,
// draws each visible row through `row`, then the indicator. The callback
// `row(idx, y, sel, reserve)` draws one item — including its own selection bar —
// using `reserve` to keep right-aligned content clear of the indicator. Returns
// the visible row count (callers cache it for input handling).
template <class RenderRow>
inline int drawList(DisplayDriver& d, int total, int sel, int& scroll, RenderRow row) {
const int item_h = d.lineStep();
const int start_y = d.listStart();
int visible = d.listVisible(item_h);
if (visible < 1) visible = 1;
if (sel < scroll) scroll = sel;
if (sel >= scroll + visible) scroll = sel - visible + 1;
if (scroll < 0) scroll = 0;
const int reserve = scrollIndicatorReserve(d, total, visible);
for (int i = 0; i < visible && (scroll + i) < total; i++)
row(scroll + i, start_y + i * item_h, scroll + i == sel, reserve);
drawScrollIndicator(d, start_y, visible * item_h, total, visible, scroll);
return visible;
}
// ── Big ASCII-art icons (skeleton, not yet used) ─────────────────────────────
// Same authoring idea as the mini-icons but for full page glyphs up to 32 px
// wide: one uint32_t per row. The existing XBM bitmaps below (logo/bluetooth/…)