mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
feat(ui): scalable mini-icons; delivery markers scale with font
Landscape e-ink renders text at 2×, but the delivery markers were drawn at a fixed ~5px and looked tiny. Standardise small procedural glyphs into a reusable mini-icon facility in icons.h: - miniIconScale() derives 1×/2×/… from getLineHeight() (8px line = 1×). - miniIconDraw() renders a compact bitmap (1 byte/row, bit=pixel) scaled and vertically centred; miniIconDotRow() draws the scaled pending-dots row. - ICON_CHECK / ICON_CROSS bitmaps; adding a new status icon is now a bitmap + one draw call. drawAckGlyph() routes through these, so ✓ / ✗ / dots scale with the font on all displays. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
// Included by UITask.cpp after SettingsScreen.h is defined.
|
||||
|
||||
#include "NavView.h" // navigate to a location shared inside a message
|
||||
#include "icons.h" // scalable mini-icons (delivery markers)
|
||||
|
||||
class QuickMsgScreen : public UIScreen {
|
||||
UITask* _task;
|
||||
@@ -283,31 +284,14 @@ class QuickMsgScreen : public UIScreen {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Small font-independent delivery marker, drawn with the current ink colour
|
||||
// in a ~5px box. No font has a usable check/cross glyph, so draw them.
|
||||
// `sends` (pending only) = how many times the DM has been transmitted: one dot
|
||||
// per send, so the row grows by a dot with each auto-resend.
|
||||
// Delivery marker, drawn with the current ink colour and auto-scaled to the
|
||||
// font (see icons.h). Pending = a row of dots, one per send (so it grows with
|
||||
// each auto-resend); delivered = ✓; failed = ✗; ACK_NONE = nothing.
|
||||
static void drawAckGlyph(DisplayDriver& d, int x, int top_y, AckState s, int sends = 1) {
|
||||
int lh = d.getLineHeight();
|
||||
int y = top_y + (lh - 5) / 2;
|
||||
if (y < top_y) y = top_y;
|
||||
switch (s) {
|
||||
case ACK_PENDING: // "·· …" awaiting ACK, one dot per send
|
||||
for (int i = 0; i < sends; i++) d.fillRect(x + i * 3, y + 3, 2, 2);
|
||||
break;
|
||||
case ACK_OK: // "✓" delivered / relayed
|
||||
d.fillRect(x, y + 2, 1, 1);
|
||||
d.fillRect(x + 1, y + 3, 1, 1);
|
||||
d.fillRect(x + 2, y + 2, 1, 1);
|
||||
d.fillRect(x + 3, y + 1, 1, 1);
|
||||
d.fillRect(x + 4, y, 1, 1);
|
||||
break;
|
||||
case ACK_FAIL: // "✗" no confirmation
|
||||
for (int i = 0; i < 4; i++) {
|
||||
d.fillRect(x + i, y + i, 1, 1);
|
||||
d.fillRect(x + 3 - i, y + i, 1, 1);
|
||||
}
|
||||
break;
|
||||
case ACK_PENDING: miniIconDotRow(d, x, top_y, sends); break;
|
||||
case ACK_OK: miniIconDraw(d, x, top_y, ICON_CHECK, 5, 4); break;
|
||||
case ACK_FAIL: miniIconDraw(d, x, top_y, ICON_CROSS, 4, 4); break;
|
||||
default: break; // ACK_NONE → nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <helpers/ui/DisplayDriver.h>
|
||||
|
||||
// ── Scalable mini-icons ──────────────────────────────────────────────────────
|
||||
// Small procedural glyphs (delivery markers, etc.) authored on a 1× pixel grid
|
||||
// and scaled to the current font, so they stay legible on large-font layouts
|
||||
// (e.g. landscape e-ink renders text at 2×). Distinct from the XBM page icons
|
||||
// further down, which are fixed-size full bitmaps drawn via drawXbm().
|
||||
//
|
||||
// To add a mini-icon:
|
||||
// 1. Define a bitmap: H rows top→bottom, one byte per row, bit (1<<col) set =
|
||||
// filled pixel (width must be ≤ 8).
|
||||
// 2. Draw it with miniIconDraw(display, x, topY, BITMAP, width, height).
|
||||
// Scaling is automatic — no per-display handling needed.
|
||||
|
||||
// Pixel scale from the font: 1× on an 8px OLED line, 2× on a 16px landscape
|
||||
// e-ink line, etc. Bitmaps are authored on the 1× grid.
|
||||
inline int miniIconScale(DisplayDriver& d) {
|
||||
int s = d.getLineHeight() / 8;
|
||||
return s < 1 ? 1 : s;
|
||||
}
|
||||
|
||||
// Draw a w×h (w ≤ 8) bitmap with the current ink colour, scaled by the font and
|
||||
// vertically centred in the text line that starts at top_y.
|
||||
inline void miniIconDraw(DisplayDriver& d, int x, int top_y,
|
||||
const uint8_t* rows, int w, int h) {
|
||||
const int s = miniIconScale(d);
|
||||
int y = top_y + (d.getLineHeight() - h * s) / 2;
|
||||
if (y < top_y) y = top_y;
|
||||
for (int r = 0; r < h; r++)
|
||||
for (int c = 0; c < w; c++)
|
||||
if (rows[r] & (1 << c)) d.fillRect(x + c * s, y + r * s, s, s);
|
||||
}
|
||||
|
||||
// Horizontal row of `count` square dots (scaled, vertically centred). Used by
|
||||
// the "awaiting ACK" marker, where the dot count = number of send attempts.
|
||||
inline void miniIconDotRow(DisplayDriver& d, int x, int top_y, int count) {
|
||||
const int s = miniIconScale(d);
|
||||
const int dot = 2 * s, pitch = 3 * s; // 2px dot + 1px gap, scaled
|
||||
int y = top_y + (d.getLineHeight() - dot) / 2;
|
||||
if (y < top_y) y = top_y;
|
||||
for (int i = 0; i < count; i++) d.fillRect(x + i * pitch, y, dot, dot);
|
||||
}
|
||||
|
||||
// Mini-icon bitmaps (authored on the 1× grid).
|
||||
static const uint8_t ICON_CHECK[4] = { 0x10, 0x08, 0x05, 0x02 }; // ✓ 5×4
|
||||
static const uint8_t ICON_CROSS[4] = { 0x09, 0x06, 0x06, 0x09 }; // ✗ 4×4
|
||||
|
||||
// 'meshcore', 128x13px
|
||||
static const uint8_t meshcore_logo [] = {
|
||||
|
||||
Reference in New Issue
Block a user