mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-11-01 10:21:59 +00:00
feat(eink): 9px icon set, 5x10 hop digits and roomier bubbles on the 4.2"
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -569,7 +569,9 @@ struct KeyboardWidget {
|
||||
// lines: cursor_mode's own 3-line hint (drawn in this same region,
|
||||
// regardless of Compact, for a physical-button user) already relies on
|
||||
// that floor and would otherwise get clipped.
|
||||
const int kb_h = compact_ui ? (KB_T9_ROWS + 1) * lh : (rows + 1) * lh;
|
||||
// A tall screen (the 4.2" panel: 20 lines) gives the keys half a line more each.
|
||||
const int key_lh = display.height() >= 18 * lh ? lh * 3 / 2 : lh;
|
||||
const int kb_h = compact_ui ? (KB_T9_ROWS + 1) * lh : (rows + 1) * key_lh;
|
||||
const int preview_h = display.height() - kb_h - display.sepH();
|
||||
const int prev_lines = (preview_h / lh) > 1 ? (preview_h / lh) : 1;
|
||||
const int sep_y = prev_lines * lh;
|
||||
@@ -577,6 +579,11 @@ struct KeyboardWidget {
|
||||
const int cell_h = (display.height() - chars_y) / (rows + 1);
|
||||
const int spec_y = chars_y + rows * cell_h;
|
||||
const int spec_w = display.width() / KB_SPECIAL;
|
||||
const int key_ty = key_lh > lh ? (cell_h - lh) / 2 : 0; // a key's text, centred in a tall cell
|
||||
// A special key's icon top: by the text line as ever, by its own height in a tall cell.
|
||||
auto iconY = [&](const MiniIcon& ic) {
|
||||
return spec_y + (key_lh > lh ? (cell_h - ic.h * miniIconScale(display)) / 2 : (cell_h - lh) / 2);
|
||||
};
|
||||
|
||||
// Multi-line text preview: the view follows cursor_pos (normally == len,
|
||||
// i.e. the end — so this is identical to the old "always the last line"
|
||||
@@ -706,13 +713,12 @@ struct KeyboardWidget {
|
||||
ch_buf[0] = ch;
|
||||
ch_buf[1] = '\0';
|
||||
int tw = display.getTextWidth(ch_buf);
|
||||
display.setCursor(cx + (cell_w - tw) / 2, y);
|
||||
display.setCursor(cx + (cell_w - tw) / 2, y + key_ty);
|
||||
display.print(ch_buf);
|
||||
}
|
||||
}
|
||||
// special row with backspace, abc kb switch & submit
|
||||
const int psw = display.width() / KB_PIN_SPECIAL;
|
||||
const int icy = spec_y + (cell_h - lh) / 2;
|
||||
for (int i = 0; i < KB_PIN_SPECIAL; i++) {
|
||||
bool sel = (row == rows && col == i);
|
||||
int sx = i * psw;
|
||||
@@ -721,7 +727,7 @@ struct KeyboardWidget {
|
||||
: (i == 1) ? ICON_KEYBOARD
|
||||
: ICON_CHECK;
|
||||
int ix = sx + (psw - ic.w * s) / 2;
|
||||
miniIconDraw(display, ix, icy, ic);
|
||||
miniIconDraw(display, ix, iconY(ic), ic);
|
||||
}
|
||||
return 50;
|
||||
}
|
||||
@@ -763,7 +769,7 @@ struct KeyboardWidget {
|
||||
int cx = c * cell_w;
|
||||
display.drawSelectionRow(cx, y - 1, cell_w - 1, cell_h, sel);
|
||||
int tw = display.getTextWidth(label);
|
||||
display.setCursor(cx + (cell_w - tw) / 2, y);
|
||||
display.setCursor(cx + (cell_w - tw) / 2, y + key_ty);
|
||||
display.print(label);
|
||||
}
|
||||
}
|
||||
@@ -778,7 +784,7 @@ struct KeyboardWidget {
|
||||
int cx = c * cell_w;
|
||||
display.drawSelectionRow(cx, y - 1, cell_w - 1, cell_h, sel);
|
||||
int tw = display.getTextWidth(ch_buf);
|
||||
display.setCursor(cx + (cell_w - tw) / 2, y);
|
||||
display.setCursor(cx + (cell_w - tw) / 2, y + key_ty);
|
||||
display.print(ch_buf);
|
||||
}
|
||||
}
|
||||
@@ -786,7 +792,6 @@ struct KeyboardWidget {
|
||||
|
||||
// special row: caps ⇧ · space ⎵ · delete ⌫ · placeholders {} (text) · OK ✓
|
||||
const int s = miniIconScale(display);
|
||||
const int icy = spec_y + (cell_h - lh) / 2; // centre icons within the cell
|
||||
for (int i = 0; i < KB_SPECIAL; i++) {
|
||||
bool sel = (row == rows && col == i);
|
||||
bool active = (i == 0 && caps);
|
||||
@@ -804,19 +809,19 @@ struct KeyboardWidget {
|
||||
lbl = pageIsSymbols(next) ? "#@" : scriptHint(scriptAt(next));
|
||||
}
|
||||
int tw = display.getTextWidth(lbl);
|
||||
display.setCursor(sx + (spec_w - tw) / 2, spec_y);
|
||||
display.setCursor(sx + (spec_w - tw) / 2, spec_y + key_ty);
|
||||
display.print(lbl);
|
||||
} else if (i == 1) { // space ⎵ — two halves side by side
|
||||
int icw = (ICON_SPACE_L.w + ICON_SPACE_R.w) * s;
|
||||
int ix = sx + (spec_w - icw) / 2;
|
||||
miniIconDraw(display, ix, icy, ICON_SPACE_L);
|
||||
miniIconDraw(display, ix + ICON_SPACE_L.w * s, icy, ICON_SPACE_R);
|
||||
miniIconDraw(display, ix, iconY(ICON_SPACE_L), ICON_SPACE_L);
|
||||
miniIconDraw(display, ix + ICON_SPACE_L.w * s, iconY(ICON_SPACE_R), ICON_SPACE_R);
|
||||
} else {
|
||||
const MiniIcon& ic = (i == 0) ? ICON_SHIFT
|
||||
: (i == 2) ? ICON_BACKSPACE
|
||||
: ICON_CHECK; // i == 5 → OK
|
||||
int ix = sx + (spec_w - ic.w * s) / 2;
|
||||
miniIconDraw(display, ix, icy, ic);
|
||||
miniIconDraw(display, ix, iconY(ic), ic);
|
||||
// Underline the ⇧ icon while caps_lock is held. Without it the two
|
||||
// Shift states are indistinguishable -- caps_lock sets caps too, so
|
||||
// the highlight above is identical -- even though they behave
|
||||
|
||||
@@ -519,7 +519,7 @@ class MessagesScreen : public UIScreen {
|
||||
static int ackGlyphWidth(DisplayDriver& d, AckState s, int sends, int relay_count = 0) {
|
||||
const int sc = miniIconScale(d);
|
||||
switch (s) {
|
||||
case ACK_PENDING: return sends * 3 * sc; // dot+gap pitch (icons.h), slightly generous
|
||||
case ACK_PENDING: return miniIconDotRowWidth(d, sends);
|
||||
case ACK_OK: return relay_count > 0 ? miniIconNumberWidth(d, relay_count) : ICON_CHECK.w * sc;
|
||||
case ACK_FAIL: return ICON_CROSS.w * sc;
|
||||
default: return 0;
|
||||
@@ -553,7 +553,7 @@ class MessagesScreen : public UIScreen {
|
||||
static int expandedBoxH(DisplayDriver& d, const char* body, int full_avail) {
|
||||
d.translateUTF8ToBlocks(s_wrap_trans, body, sizeof(s_wrap_trans));
|
||||
int nl = FullscreenMsgView::wrapLines(d, s_wrap_trans, bubbleMaxW(d, full_avail) - 6, s_wrap_lines, 8);
|
||||
return (1 + (nl > 0 ? nl : 1)) * d.getLineHeight() + 1;
|
||||
return (1 + (nl > 0 ? nl : 1)) * d.getLineHeight() + 3; // 2 px under the descenders
|
||||
}
|
||||
static BubbleBox computeBubbleBox(int full_avail, int max_w, bool outgoing, int header_w, int body_w) {
|
||||
int w = header_w > body_w ? header_w : body_w;
|
||||
@@ -593,7 +593,10 @@ class MessagesScreen : public UIScreen {
|
||||
const int ack_w = mark.width(display);
|
||||
// A little air between a marker and the age, so "12" + "1s" doesn't read as "121s".
|
||||
const int mk_gap = (ack_w > 0 && age_w > 0) ? 2 : 0;
|
||||
const int header_w = 3 + (sender[0] ? display.getTextWidth(sender) : -3) + ack_w + mk_gap + age_w + 3;
|
||||
// The marker after the name: a character's gap beside the larger icons,
|
||||
// whose digits stand as tall as the text and would read as part of it.
|
||||
const int nm_gap = MINI_ICONS_LARGE ? display.getCharWidth() : 3;
|
||||
const int header_w = 3 + (sender[0] ? display.getTextWidth(sender) + (ack_w ? nm_gap - 3 : 0) : -3) + ack_w + mk_gap + age_w + 3;
|
||||
int body_w, nl = 0;
|
||||
if (expand) {
|
||||
display.translateUTF8ToBlocks(s_wrap_trans, body, sizeof(s_wrap_trans));
|
||||
@@ -614,12 +617,12 @@ class MessagesScreen : public UIScreen {
|
||||
// The name gives way to the marker and the age (a long name is
|
||||
// ellipsized), and the marker sits right after whatever width the name
|
||||
// actually got -- not after its full width, which would run it into the age.
|
||||
int name_avail = box.w - 6 - age_w - ack_w - mk_gap;
|
||||
int name_avail = box.w - 6 - age_w - ack_w - mk_gap - (ack_w ? nm_gap - 3 : 0);
|
||||
if (name_avail < display.getCharWidth()) name_avail = display.getCharWidth();
|
||||
int name_w = sender[0] ? display.getTextWidth(sender) : 0;
|
||||
if (name_w > name_avail) name_w = name_avail;
|
||||
if (sender[0]) display.drawTextEllipsized(box.x + 3, y + 1, name_avail, sender);
|
||||
int gx = box.x + 3 + (name_w ? name_w + 3 : 0);
|
||||
int gx = box.x + 3 + (name_w ? name_w + nm_gap : 0);
|
||||
if (mark.kind == BubbleMark::ACK) drawAckGlyph(display, gx, y + 1, mark.status, mark.sends, mark.relay);
|
||||
else if (mark.kind == BubbleMark::HOPS) miniIconDrawNumber(display, gx, y + 1, mark.hops);
|
||||
if (age[0]) { display.setCursor(box.x + box.w - age_w, y + 1); display.print(age); }
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
// (e.g. landscape e-ink renders text at 2×).
|
||||
//
|
||||
// To add a mini-icon:
|
||||
// 1. Draw it as ASCII-art rows, one string per row (width ≤ 8): any char
|
||||
// 1. Draw it as ASCII-art rows, one string per row (width ≤ 16): any char
|
||||
// other than ' ' or '.' is a filled pixel. packRow() packs each string
|
||||
// into one byte at compile time, so the strings never reach flash — the
|
||||
// binary holds only the packed bytes, identical to hand-written hex.
|
||||
// into a 16-bit word at compile time, so the strings never reach flash —
|
||||
// the binary holds only the packed words, identical to hand-written hex.
|
||||
// 2. Wrap the rows in a MINI_ICON(name, width, ...) — width and row count are
|
||||
// bundled with the data, so the draw site carries no magic numbers.
|
||||
// 3. Draw it with miniIconDraw(display, x, topY, name).
|
||||
@@ -22,33 +22,34 @@
|
||||
// packRow() is written as a single-expression recursion so it stays a valid
|
||||
// constant expression on any C++ standard the firmware targets (≥ C++11), not
|
||||
// just the relaxed C++14 constexpr with loops. It packs up to the string's NUL
|
||||
// (capped at 8 cols), so width lives once in MINI_ICON, not in every row.
|
||||
constexpr uint8_t packBit(const char* s, int x) {
|
||||
return (s[x] && s[x] != ' ' && s[x] != '.') ? (uint8_t)(1u << x) : 0;
|
||||
// (capped at 16 cols), so width lives once in MINI_ICON, not in every row.
|
||||
constexpr uint16_t packBit(const char* s, int x) {
|
||||
return (s[x] && s[x] != ' ' && s[x] != '.') ? (uint16_t)(1u << x) : 0;
|
||||
}
|
||||
constexpr uint8_t packRow(const char* s, int x = 0) {
|
||||
return (!s[x] || x >= 8) ? 0 : (uint8_t)(packBit(s, x) | packRow(s, x + 1));
|
||||
constexpr uint16_t packRow(const char* s, int x = 0) {
|
||||
return (!s[x] || x >= 16) ? 0 : (uint16_t)(packBit(s, x) | packRow(s, x + 1));
|
||||
}
|
||||
|
||||
// A mini-icon bundles its pixel data with its dimensions, so call sites can't
|
||||
// pass a stale width/height. Built via the MINI_ICON macro below.
|
||||
struct MiniIcon { uint8_t w, h; const uint8_t* rows; };
|
||||
struct MiniIcon { uint8_t w, h; const uint16_t* rows; };
|
||||
|
||||
// Define a mini-icon: the row count (height) is derived from the initializer,
|
||||
// the width is stated once. Emits a packed byte array plus a MiniIcon view.
|
||||
// the width is stated once. Emits a packed word array plus a MiniIcon view.
|
||||
#define MINI_ICON(name, width, ...) \
|
||||
static constexpr uint8_t name##_rows[] = { __VA_ARGS__ }; \
|
||||
static constexpr uint16_t name##_rows[] = { __VA_ARGS__ }; \
|
||||
static constexpr MiniIcon name = { (uint8_t)(width), \
|
||||
(uint8_t)sizeof(name##_rows), name##_rows }
|
||||
(uint8_t)(sizeof(name##_rows) / sizeof(name##_rows[0])), name##_rows }
|
||||
|
||||
// The landscape e-ink build writes in the 8x13, whose digits stand 9 px:
|
||||
// there the status, page and check glyphs come in a 7 px set instead of 5.
|
||||
// The 4.2" build's 9x15 (digits 10 px) takes a 9 px set: MINI_ICONS_LARGE 2.
|
||||
#if defined(EINK_LARGE_FONT) && EINK_LARGE_FONT
|
||||
#define MINI_ICONS_LARGE 1
|
||||
#define MINI_ICONS_LARGE EINK_LARGE_FONT
|
||||
#else
|
||||
#define MINI_ICONS_LARGE 0
|
||||
#endif
|
||||
static constexpr int PAGE_ICON_PX = MINI_ICONS_LARGE ? 7 : 5; // the page glyphs' box
|
||||
static constexpr int PAGE_ICON_PX = MINI_ICONS_LARGE == 2 ? 9 : MINI_ICONS_LARGE ? 7 : 5; // the page glyphs' box
|
||||
|
||||
// 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.
|
||||
@@ -57,10 +58,10 @@ inline int miniIconScale(DisplayDriver& d) {
|
||||
return s < 1 ? 1 : s;
|
||||
}
|
||||
|
||||
// Draw a w×h (w ≤ 8) bitmap with the current ink colour, scaled by the font and
|
||||
// Draw a w×h (w ≤ 16) 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 uint16_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;
|
||||
@@ -104,16 +105,35 @@ inline void drawSlotIcon(DisplayDriver& d, int x, int box_w, int box_h, const Mi
|
||||
|
||||
// Horizontal row of `count` square dots (scaled, vertically centred). Used by
|
||||
// the "awaiting ACK" marker, where the dot count = number of send attempts.
|
||||
// The dots are 3 px beside the larger icon sets.
|
||||
static constexpr int DOT_ROW_PX = MINI_ICONS_LARGE ? 3 : 2;
|
||||
inline int miniIconDotRowWidth(DisplayDriver& d, int count) { return count * (DOT_ROW_PX + 1) * miniIconScale(d); }
|
||||
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
|
||||
const int dot = DOT_ROW_PX * s, pitch = (DOT_ROW_PX + 1) * s; // 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 as ASCII-art; see packRow above).
|
||||
#if MINI_ICONS_LARGE
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_CHECK, 9, // ✓
|
||||
packRow("........#"),
|
||||
packRow(".......#."),
|
||||
packRow("#.....#.."),
|
||||
packRow(".#...#..."),
|
||||
packRow("..#.#...."),
|
||||
packRow("...#....."));
|
||||
MINI_ICON(ICON_CROSS, 7, // ✗
|
||||
packRow("#.....#"),
|
||||
packRow(".#...#."),
|
||||
packRow("..#.#.."),
|
||||
packRow("...#..."),
|
||||
packRow("..#.#.."),
|
||||
packRow(".#...#."),
|
||||
packRow("#.....#"));
|
||||
#elif MINI_ICONS_LARGE
|
||||
MINI_ICON(ICON_CHECK, 7, // ✓
|
||||
packRow("......#"),
|
||||
packRow(".....#."),
|
||||
@@ -139,9 +159,202 @@ MINI_ICON(ICON_CROSS, 4, // ✗
|
||||
packRow("#..#"));
|
||||
#endif
|
||||
|
||||
// Tiny 3×5 digits — for a small count that needs to sit in an icon-sized slot
|
||||
// Tiny 3×5 digits (5x7 and 5x10 in the large sets) — for a small count that needs to sit in an icon-sized slot
|
||||
// (e.g. next to ICON_CHECK) where the normal font is too tall to fit. See
|
||||
// miniIconDrawNumber/miniIconNumberWidth below.
|
||||
#if MINI_ICONS_LARGE == 2 // 5x10, as tall as the 9x15's own digits
|
||||
MINI_ICON(ICON_DIGIT_0, 5,
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_1, 5,
|
||||
packRow("..#.."),
|
||||
packRow(".##.."),
|
||||
packRow("#.#.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("#####"));
|
||||
MINI_ICON(ICON_DIGIT_2, 5,
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("....#"),
|
||||
packRow("....#"),
|
||||
packRow("...#."),
|
||||
packRow("..#.."),
|
||||
packRow(".#..."),
|
||||
packRow("#...."),
|
||||
packRow("#...."),
|
||||
packRow("#####"));
|
||||
MINI_ICON(ICON_DIGIT_3, 5,
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("....#"),
|
||||
packRow("....#"),
|
||||
packRow("..##."),
|
||||
packRow("....#"),
|
||||
packRow("....#"),
|
||||
packRow("....#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_4, 5,
|
||||
packRow("...#."),
|
||||
packRow("..##."),
|
||||
packRow(".#.#."),
|
||||
packRow("#..#."),
|
||||
packRow("#..#."),
|
||||
packRow("#..#."),
|
||||
packRow("#####"),
|
||||
packRow("...#."),
|
||||
packRow("...#."),
|
||||
packRow("...#."));
|
||||
MINI_ICON(ICON_DIGIT_5, 5,
|
||||
packRow("#####"),
|
||||
packRow("#...."),
|
||||
packRow("#...."),
|
||||
packRow("#...."),
|
||||
packRow("####."),
|
||||
packRow("....#"),
|
||||
packRow("....#"),
|
||||
packRow("....#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_6, 5,
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("#...."),
|
||||
packRow("#...."),
|
||||
packRow("####."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_7, 5,
|
||||
packRow("#####"),
|
||||
packRow("....#"),
|
||||
packRow("....#"),
|
||||
packRow("...#."),
|
||||
packRow("...#."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."));
|
||||
MINI_ICON(ICON_DIGIT_8, 5,
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_9, 5,
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".####"),
|
||||
packRow("....#"),
|
||||
packRow("....#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
#elif MINI_ICONS_LARGE // 5x7 beside the 7 px ones
|
||||
MINI_ICON(ICON_DIGIT_0, 5,
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_1, 5,
|
||||
packRow("..#.."),
|
||||
packRow(".##.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_2, 5,
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("....#"),
|
||||
packRow("...#."),
|
||||
packRow("..#.."),
|
||||
packRow(".#..."),
|
||||
packRow("#####"));
|
||||
MINI_ICON(ICON_DIGIT_3, 5,
|
||||
packRow("#####"),
|
||||
packRow("...#."),
|
||||
packRow("..#.."),
|
||||
packRow("...#."),
|
||||
packRow("....#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_4, 5,
|
||||
packRow("...#."),
|
||||
packRow("..##."),
|
||||
packRow(".#.#."),
|
||||
packRow("#..#."),
|
||||
packRow("#####"),
|
||||
packRow("...#."),
|
||||
packRow("...#."));
|
||||
MINI_ICON(ICON_DIGIT_5, 5,
|
||||
packRow("#####"),
|
||||
packRow("#...."),
|
||||
packRow("####."),
|
||||
packRow("....#"),
|
||||
packRow("....#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_6, 5,
|
||||
packRow("..##."),
|
||||
packRow(".#..."),
|
||||
packRow("#...."),
|
||||
packRow("####."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_7, 5,
|
||||
packRow("#####"),
|
||||
packRow("....#"),
|
||||
packRow("...#."),
|
||||
packRow("..#.."),
|
||||
packRow(".#..."),
|
||||
packRow(".#..."),
|
||||
packRow(".#..."));
|
||||
MINI_ICON(ICON_DIGIT_8, 5,
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
MINI_ICON(ICON_DIGIT_9, 5,
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".####"),
|
||||
packRow("....#"),
|
||||
packRow("...#."),
|
||||
packRow(".##.."));
|
||||
#else
|
||||
MINI_ICON(ICON_DIGIT_0, 3,
|
||||
packRow("###"),
|
||||
packRow("#.#"),
|
||||
@@ -203,6 +416,8 @@ MINI_ICON(ICON_DIGIT_9, 3,
|
||||
packRow("..#"),
|
||||
packRow("###"));
|
||||
|
||||
#endif
|
||||
|
||||
static constexpr const MiniIcon* MINI_ICON_DIGITS[10] = {
|
||||
&ICON_DIGIT_0, &ICON_DIGIT_1, &ICON_DIGIT_2, &ICON_DIGIT_3, &ICON_DIGIT_4,
|
||||
&ICON_DIGIT_5, &ICON_DIGIT_6, &ICON_DIGIT_7, &ICON_DIGIT_8, &ICON_DIGIT_9,
|
||||
@@ -215,7 +430,7 @@ static constexpr const MiniIcon* MINI_ICON_DIGITS[10] = {
|
||||
inline int miniIconNumberWidth(DisplayDriver& d, int n) {
|
||||
const int s = miniIconScale(d);
|
||||
int digits = (n >= 10) ? 2 : 1;
|
||||
return digits * 3 * s + (digits - 1) * s;
|
||||
return digits * ICON_DIGIT_0.w * s + (digits - 1) * s;
|
||||
}
|
||||
|
||||
// Draws `n` (clamped to 0-99) as a left-to-right run of tiny digit icons —
|
||||
@@ -223,14 +438,108 @@ inline int miniIconNumberWidth(DisplayDriver& d, int n) {
|
||||
// legibly. Vertically centred in the text line the same way miniIconDraw is.
|
||||
inline void miniIconDrawNumber(DisplayDriver& d, int x, int top_y, int n) {
|
||||
const int s = miniIconScale(d);
|
||||
// The 9x15's digits stand on its baseline a pixel below the centred box.
|
||||
if (MINI_ICONS_LARGE == 2) top_y += 1;
|
||||
if (n < 0) n = 0;
|
||||
if (n > 99) n = 99;
|
||||
if (n >= 10) { miniIconDraw(d, x, top_y, *MINI_ICON_DIGITS[n / 10]); x += 3 * s + s; }
|
||||
if (n >= 10) { miniIconDraw(d, x, top_y, *MINI_ICON_DIGITS[n / 10]); x += ICON_DIGIT_0.w * s + s; }
|
||||
miniIconDraw(d, x, top_y, *MINI_ICON_DIGITS[n % 10]);
|
||||
}
|
||||
|
||||
// Top-bar status glyphs (replace the single-letter M / B / A indicators).
|
||||
#if MINI_ICONS_LARGE
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_MUTE, 10, // speaker + cross (sound off)
|
||||
packRow("...#......"),
|
||||
packRow("..##......"),
|
||||
packRow("####.#...#"),
|
||||
packRow("####..#.#."),
|
||||
packRow("####...#.."),
|
||||
packRow("####..#.#."),
|
||||
packRow("####.#...#"),
|
||||
packRow("..##......"),
|
||||
packRow("...#......"));
|
||||
MINI_ICON(ICON_BLUETOOTH, 7, // ᛒ bluetooth rune
|
||||
packRow("...#..."),
|
||||
packRow("...##.."),
|
||||
packRow("#..#.#."),
|
||||
packRow(".#.##.."),
|
||||
packRow("..##..."),
|
||||
packRow(".#.##.."),
|
||||
packRow("#..#.#."),
|
||||
packRow("...##.."),
|
||||
packRow("...#..."));
|
||||
MINI_ICON(ICON_ADVERT, 9, // ((•)) advert
|
||||
packRow(".#.....#."),
|
||||
packRow("#.......#"),
|
||||
packRow("#..###..#"),
|
||||
packRow("#.#####.#"),
|
||||
packRow("#.#####.#"),
|
||||
packRow("#.#####.#"),
|
||||
packRow("#..###..#"),
|
||||
packRow("#.......#"),
|
||||
packRow(".#.....#."));
|
||||
MINI_ICON(ICON_ALARM, 9, // bell — an alarm is armed
|
||||
packRow("....#...."),
|
||||
packRow("...###..."),
|
||||
packRow("..#####.."),
|
||||
packRow("..#####.."),
|
||||
packRow("..#####.."),
|
||||
packRow(".#######."),
|
||||
packRow("#########"),
|
||||
packRow("........."),
|
||||
packRow("...###..."));
|
||||
MINI_ICON(ICON_TRAIL, 7, // map pin (GPS trail logging)
|
||||
packRow("..###.."),
|
||||
packRow(".#####."),
|
||||
packRow("##...##"),
|
||||
packRow("##...##"),
|
||||
packRow("##...##"),
|
||||
packRow(".#####."),
|
||||
packRow("..###.."),
|
||||
packRow("...#..."),
|
||||
packRow("...#..."));
|
||||
MINI_ICON(ICON_REPEATER, 9, // » relaying (repeater active)
|
||||
packRow("#...#...."),
|
||||
packRow(".#...#..."),
|
||||
packRow("..#...#.."),
|
||||
packRow("...#...#."),
|
||||
packRow("....#...#"),
|
||||
packRow("...#...#."),
|
||||
packRow("..#...#.."),
|
||||
packRow(".#...#..."),
|
||||
packRow("#...#...."));
|
||||
MINI_ICON(ICON_GPS, 9, // reticle with its dot: GPS has a fix
|
||||
packRow("...###..."),
|
||||
packRow(".##...##."),
|
||||
packRow(".#.....#."),
|
||||
packRow("#...#...#"),
|
||||
packRow("#..###..#"),
|
||||
packRow("#...#...#"),
|
||||
packRow(".#.....#."),
|
||||
packRow(".##...##."),
|
||||
packRow("...###..."));
|
||||
MINI_ICON(ICON_GPS_SEARCH, 9, // the reticle broken: still searching
|
||||
packRow("...#.#..."),
|
||||
packRow(".##...##."),
|
||||
packRow(".#.....#."),
|
||||
packRow("#.......#"),
|
||||
packRow("........."),
|
||||
packRow("#.......#"),
|
||||
packRow(".#.....#."),
|
||||
packRow(".##...##."),
|
||||
packRow("...#.#..."));
|
||||
|
||||
MINI_ICON(ICON_CHART, 9, // ascending bars — Home › Status
|
||||
packRow("........#"),
|
||||
packRow("......#.#"),
|
||||
packRow("......#.#"),
|
||||
packRow("....#.#.#"),
|
||||
packRow("....#.#.#"),
|
||||
packRow("..#.#.#.#"),
|
||||
packRow("..#.#.#.#"),
|
||||
packRow("#.#.#.#.#"),
|
||||
packRow("#########"));
|
||||
#elif MINI_ICONS_LARGE
|
||||
MINI_ICON(ICON_MUTE, 8, // speaker + cross (sound off)
|
||||
packRow("...#...."),
|
||||
packRow("..##...."),
|
||||
@@ -377,7 +686,106 @@ MINI_ICON(ICON_CHART, 5, // ascending bars — Home › Status
|
||||
// Home-carousel page glyphs — a uniform 5x5 set, deliberately smaller than the
|
||||
// menu/status icons above, used in place of the page-indicator dots. One per
|
||||
// HomePage; see UITask HomeScreen::pageIcon().
|
||||
#if MINI_ICONS_LARGE
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_PG_CLOCK, 9, // clock face + hands
|
||||
packRow("...###..."),
|
||||
packRow(".##.#.##."),
|
||||
packRow(".#..#..#."),
|
||||
packRow("#...#...#"),
|
||||
packRow("#...###.#"),
|
||||
packRow("#.......#"),
|
||||
packRow(".#.....#."),
|
||||
packRow(".##...##."),
|
||||
packRow("...###..."));
|
||||
MINI_ICON(ICON_PG_STAR, 9, // favourites
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("...###..."),
|
||||
packRow("#########"),
|
||||
packRow(".#######."),
|
||||
packRow("..#####.."),
|
||||
packRow("..##.##.."),
|
||||
packRow(".##...##."),
|
||||
packRow(".#.....#."));
|
||||
MINI_ICON(ICON_PG_RADIO, 9, // antenna with waves — radio
|
||||
packRow(".#.....#."),
|
||||
packRow("#...#...#"),
|
||||
packRow("#..###..#"),
|
||||
packRow("#...#...#"),
|
||||
packRow(".#..#..#."),
|
||||
packRow("....#...."),
|
||||
packRow("...#.#..."),
|
||||
packRow("..#...#.."),
|
||||
packRow(".#.....#."));
|
||||
MINI_ICON(ICON_PG_BT, 7, // bluetooth
|
||||
packRow("...#..."),
|
||||
packRow("...##.."),
|
||||
packRow("#..#.#."),
|
||||
packRow(".#.##.."),
|
||||
packRow("..##..."),
|
||||
packRow(".#.##.."),
|
||||
packRow("#..#.#."),
|
||||
packRow("...##.."),
|
||||
packRow("...#..."));
|
||||
MINI_ICON(ICON_PG_ADVERT, 9, // advert page: the same waves
|
||||
packRow(".#.....#."),
|
||||
packRow("#.......#"),
|
||||
packRow("#..###..#"),
|
||||
packRow("#.#####.#"),
|
||||
packRow("#.#####.#"),
|
||||
packRow("#.#####.#"),
|
||||
packRow("#..###..#"),
|
||||
packRow("#.......#"),
|
||||
packRow(".#.....#."));
|
||||
MINI_ICON(ICON_PG_SETTINGS, 9, // cog with a hub hole
|
||||
packRow("...#.#..."),
|
||||
packRow(".#######."),
|
||||
packRow(".##...##."),
|
||||
packRow("##.....##"),
|
||||
packRow(".#.....#."),
|
||||
packRow("##.....##"),
|
||||
packRow(".##...##."),
|
||||
packRow(".#######."),
|
||||
packRow("...#.#..."));
|
||||
MINI_ICON(ICON_PG_MAP, 10, // folded map
|
||||
packRow("##########"),
|
||||
packRow("#..#..#..#"),
|
||||
packRow("#..#..#..#"),
|
||||
packRow("#..#..#..#"),
|
||||
packRow("#..#..#..#"),
|
||||
packRow("#..#..#..#"),
|
||||
packRow("#..#..#..#"),
|
||||
packRow("#..#..#..#"),
|
||||
packRow("##########"));
|
||||
MINI_ICON(ICON_PG_TOOLS, 9, // wrench, open jaw top right
|
||||
packRow("......#.#"),
|
||||
packRow("......#.#"),
|
||||
packRow("......###"),
|
||||
packRow(".....##.."),
|
||||
packRow("....##..."),
|
||||
packRow("...##...."),
|
||||
packRow("..##....."),
|
||||
packRow(".##......"),
|
||||
packRow("##......."));
|
||||
MINI_ICON(ICON_PG_MSG, 9, // speech bubble with three dots
|
||||
packRow("#########"),
|
||||
packRow("#.......#"),
|
||||
packRow("#.#.#.#.#"),
|
||||
packRow("#.......#"),
|
||||
packRow("#########"),
|
||||
packRow("##......."),
|
||||
packRow("#........"));
|
||||
MINI_ICON(ICON_PG_POWER, 9, // power symbol
|
||||
packRow("....#...."),
|
||||
packRow("..#.#.#.."),
|
||||
packRow(".#..#..#."),
|
||||
packRow("#...#...#"),
|
||||
packRow("#.......#"),
|
||||
packRow("#.......#"),
|
||||
packRow(".#.....#."),
|
||||
packRow("..#...#.."),
|
||||
packRow("...###..."));
|
||||
#elif MINI_ICONS_LARGE
|
||||
MINI_ICON(ICON_PG_CLOCK, 7, // clock face + hands
|
||||
packRow("..###.."),
|
||||
packRow(".#.#.#."),
|
||||
@@ -522,15 +930,44 @@ MINI_ICON(ICON_PG_POWER, 5, // power symbol — shutdown
|
||||
|
||||
// Trail-map markers — centred on a point (see miniIconDrawCentered) rather
|
||||
// than anchored to a text line.
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_MAP_DOT, 5, // ● filled trail point
|
||||
packRow("..#.."),
|
||||
packRow(".###."),
|
||||
packRow("#####"),
|
||||
packRow(".###."),
|
||||
packRow("..#.."));
|
||||
#else
|
||||
MINI_ICON(ICON_MAP_DOT, 3, // ● filled trail point
|
||||
packRow("###"),
|
||||
packRow("###"),
|
||||
packRow("###"));
|
||||
#endif
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_MAP_RING, 5, // ○ hollow ring — a new trail segment start
|
||||
packRow(".###."),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow("#...#"),
|
||||
packRow(".###."));
|
||||
#else
|
||||
MINI_ICON(ICON_MAP_RING, 3, // ○ hollow ring — marks a new trail segment start
|
||||
packRow("###"),
|
||||
packRow("#.#"),
|
||||
packRow("###"));
|
||||
#if MINI_ICONS_LARGE // the markers that also head rows of text
|
||||
#endif
|
||||
#if MINI_ICONS_LARGE == 2 // the markers that also head rows of text
|
||||
MINI_ICON(ICON_MAP_WAYPOINT, 9, // ◇ hollow diamond — saved waypoint
|
||||
packRow("....#...."),
|
||||
packRow("...#.#..."),
|
||||
packRow("..#...#.."),
|
||||
packRow(".#.....#."),
|
||||
packRow("#.......#"),
|
||||
packRow(".#.....#."),
|
||||
packRow("..#...#.."),
|
||||
packRow("...#.#..."),
|
||||
packRow("....#...."));
|
||||
#elif MINI_ICONS_LARGE
|
||||
MINI_ICON(ICON_MAP_WAYPOINT, 7, // ◇ hollow diamond — saved waypoint
|
||||
packRow("...#..."),
|
||||
packRow("..#.#.."),
|
||||
@@ -547,19 +984,56 @@ MINI_ICON(ICON_MAP_WAYPOINT, 5, // ◇ hollow diamond — saved waypoint
|
||||
packRow(".#.#."),
|
||||
packRow("..#.."));
|
||||
#endif
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_MAP_START, 9, // + trail start marker
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("#########"),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."));
|
||||
#else
|
||||
MINI_ICON(ICON_MAP_START, 5, // + trail start marker
|
||||
packRow("..#.."),
|
||||
packRow("..#.."),
|
||||
packRow("#####"),
|
||||
packRow("..#.."),
|
||||
packRow("..#.."));
|
||||
#endif
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_MAP_CURRENT, 9, // ✕ live position / last trail point
|
||||
packRow("##.....##"),
|
||||
packRow("###...###"),
|
||||
packRow(".###.###."),
|
||||
packRow("..#####.."),
|
||||
packRow("...###..."),
|
||||
packRow("..#####.."),
|
||||
packRow(".###.###."),
|
||||
packRow("###...###"),
|
||||
packRow("##.....##"));
|
||||
#else
|
||||
MINI_ICON(ICON_MAP_CURRENT, 5, // ✕ live position / last trail point
|
||||
packRow("#...#"),
|
||||
packRow(".#.#."),
|
||||
packRow("..#.."),
|
||||
packRow(".#.#."),
|
||||
packRow("#...#"));
|
||||
#if MINI_ICONS_LARGE
|
||||
#endif
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_MAP_CONTACT, 9, // ◆ filled diamond — a live-tracked contact
|
||||
packRow("....#...."),
|
||||
packRow("...###..."),
|
||||
packRow("..#####.."),
|
||||
packRow(".#######."),
|
||||
packRow("#########"),
|
||||
packRow(".#######."),
|
||||
packRow("..#####.."),
|
||||
packRow("...###..."),
|
||||
packRow("....#...."));
|
||||
#elif MINI_ICONS_LARGE
|
||||
MINI_ICON(ICON_MAP_CONTACT, 7, // ◆ filled diamond — a live-tracked contact
|
||||
packRow("...#..."),
|
||||
packRow("..###.."),
|
||||
@@ -576,6 +1050,19 @@ MINI_ICON(ICON_MAP_CONTACT, 5, // ◆ filled diamond — a live-tracked conta
|
||||
packRow(".###."),
|
||||
packRow("..#.."));
|
||||
#endif
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_MAP_NORTH, 7, // "N" with a peaked roof — compass north marker
|
||||
packRow("...#..."),
|
||||
packRow("..###.."),
|
||||
packRow(".#...#."),
|
||||
packRow("#.....#"),
|
||||
packRow("##....#"),
|
||||
packRow("#.#...#"),
|
||||
packRow("#..#..#"),
|
||||
packRow("#...#.#"),
|
||||
packRow("#....##"),
|
||||
packRow("#.....#"));
|
||||
#else
|
||||
MINI_ICON(ICON_MAP_NORTH, 5, // "N" with a peaked roof — compass north marker
|
||||
packRow("..#.."),
|
||||
packRow(".###."),
|
||||
@@ -584,15 +1071,111 @@ MINI_ICON(ICON_MAP_NORTH, 5, // "N" with a peaked roof — compass north ma
|
||||
packRow("#.#.#"),
|
||||
packRow("#..##"),
|
||||
packRow("#...#"));
|
||||
#endif
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_MAP_TARGET, 7, // ⚑ flag on a pole — the active Locator/Nav target
|
||||
packRow("#######"),
|
||||
packRow("#.....#"),
|
||||
packRow("#.....#"),
|
||||
packRow("#######"),
|
||||
packRow("#......"),
|
||||
packRow("#......"),
|
||||
packRow("#......"),
|
||||
packRow("#......"),
|
||||
packRow("#......"));
|
||||
#else
|
||||
MINI_ICON(ICON_MAP_TARGET, 5, // ⚑ flag on a pole — the active Locator/Nav target
|
||||
packRow("####."),
|
||||
packRow("#..#."),
|
||||
packRow("####."),
|
||||
packRow("#...."),
|
||||
packRow("#...."));
|
||||
#endif
|
||||
|
||||
// Arrows towards the eight compass points (north up), for a bearing beside
|
||||
// a distance: ICON_ARROWS[((deg + 22) % 360) / 45].
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_ARROW_N, 9,
|
||||
packRow("....#...."),
|
||||
packRow("...###..."),
|
||||
packRow("..#.#.#.."),
|
||||
packRow(".#..#..#."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."));
|
||||
MINI_ICON(ICON_ARROW_NE, 9,
|
||||
packRow("....#####"),
|
||||
packRow(".......##"),
|
||||
packRow("......#.#"),
|
||||
packRow(".....#..#"),
|
||||
packRow("....#...#"),
|
||||
packRow("...#....."),
|
||||
packRow("..#......"),
|
||||
packRow(".#......."),
|
||||
packRow("#........"));
|
||||
MINI_ICON(ICON_ARROW_E, 9,
|
||||
packRow("........."),
|
||||
packRow(".....#..."),
|
||||
packRow("......#.."),
|
||||
packRow(".......#."),
|
||||
packRow("#########"),
|
||||
packRow(".......#."),
|
||||
packRow("......#.."),
|
||||
packRow(".....#..."),
|
||||
packRow("........."));
|
||||
MINI_ICON(ICON_ARROW_SE, 9,
|
||||
packRow("#........"),
|
||||
packRow(".#......."),
|
||||
packRow("..#......"),
|
||||
packRow("...#....."),
|
||||
packRow("....#...#"),
|
||||
packRow(".....#..#"),
|
||||
packRow("......#.#"),
|
||||
packRow(".......##"),
|
||||
packRow("....#####"));
|
||||
MINI_ICON(ICON_ARROW_S, 9,
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow("....#...."),
|
||||
packRow(".#..#..#."),
|
||||
packRow("..#.#.#.."),
|
||||
packRow("...###..."),
|
||||
packRow("....#...."));
|
||||
MINI_ICON(ICON_ARROW_SW, 9,
|
||||
packRow("........#"),
|
||||
packRow(".......#."),
|
||||
packRow("......#.."),
|
||||
packRow(".....#..."),
|
||||
packRow("#...#...."),
|
||||
packRow("#..#....."),
|
||||
packRow("#.#......"),
|
||||
packRow("##......."),
|
||||
packRow("#####...."));
|
||||
MINI_ICON(ICON_ARROW_W, 9,
|
||||
packRow("........."),
|
||||
packRow("...#....."),
|
||||
packRow("..#......"),
|
||||
packRow(".#......."),
|
||||
packRow("#########"),
|
||||
packRow(".#......."),
|
||||
packRow("..#......"),
|
||||
packRow("...#....."),
|
||||
packRow("........."));
|
||||
MINI_ICON(ICON_ARROW_NW, 9,
|
||||
packRow("#####...."),
|
||||
packRow("##......."),
|
||||
packRow("#.#......"),
|
||||
packRow("#..#....."),
|
||||
packRow("#...#...."),
|
||||
packRow(".....#..."),
|
||||
packRow("......#.."),
|
||||
packRow(".......#."),
|
||||
packRow("........#"));
|
||||
#else
|
||||
MINI_ICON(ICON_ARROW_N, 7,
|
||||
packRow("...#..."),
|
||||
packRow("..###.."),
|
||||
@@ -657,10 +1240,51 @@ MINI_ICON(ICON_ARROW_NW, 7,
|
||||
packRow("....#.."),
|
||||
packRow(".....#."),
|
||||
packRow("......#"));
|
||||
#endif
|
||||
static constexpr const MiniIcon* ICON_ARROWS[8] = { &ICON_ARROW_N, &ICON_ARROW_NE, &ICON_ARROW_E, &ICON_ARROW_SE,
|
||||
&ICON_ARROW_S, &ICON_ARROW_SW, &ICON_ARROW_W, &ICON_ARROW_NW };
|
||||
|
||||
// Keyboard special-key glyphs.
|
||||
#if MINI_ICONS_LARGE == 2
|
||||
MINI_ICON(ICON_KEYBOARD, 9, // PIN keyboard to ABC keyboard switch icon
|
||||
packRow("#.#.#.#.#"),
|
||||
packRow("#########"),
|
||||
packRow("#.#.#.#.#"),
|
||||
packRow("#########"),
|
||||
packRow("#.#.#.#.#"));
|
||||
MINI_ICON(ICON_SHIFT, 9, // ⇧ caps
|
||||
packRow("....#...."),
|
||||
packRow("...###..."),
|
||||
packRow("..#####.."),
|
||||
packRow(".#######."),
|
||||
packRow("#########"),
|
||||
packRow("...###..."),
|
||||
packRow("...###..."),
|
||||
packRow("...###..."),
|
||||
packRow("...###..."));
|
||||
MINI_ICON(ICON_BACKSPACE, 11, // ⌫ delete-left (× knocked out of the arrow body)
|
||||
packRow("....#######"),
|
||||
packRow("...########"),
|
||||
packRow("..###.###.#"),
|
||||
packRow(".#####.#.##"),
|
||||
packRow("#######.###"),
|
||||
packRow(".#####.#.##"),
|
||||
packRow("..###.###.#"),
|
||||
packRow("...########"),
|
||||
packRow("....#######"));
|
||||
MINI_ICON(ICON_SPACE_L, 7,
|
||||
packRow("#......"),
|
||||
packRow("#......"),
|
||||
packRow("#......"),
|
||||
packRow("#......"),
|
||||
packRow("#######"));
|
||||
MINI_ICON(ICON_SPACE_R, 7,
|
||||
packRow("......#"),
|
||||
packRow("......#"),
|
||||
packRow("......#"),
|
||||
packRow("......#"),
|
||||
packRow("#######"));
|
||||
#else
|
||||
MINI_ICON(ICON_KEYBOARD, 7, // PIN keyboard to ABC keyboard switch icon
|
||||
packRow("#.#.#.#"),
|
||||
packRow("#######"),
|
||||
@@ -682,7 +1306,7 @@ MINI_ICON(ICON_BACKSPACE, 8, // ⌫ delete-left (× knocked out of the arrow
|
||||
packRow(".###.#.#"),
|
||||
packRow("..######"),
|
||||
packRow("...#####"));
|
||||
// Space ⎵ is wider than the 8-px mini-icon limit, so it is two halves drawn
|
||||
// Space ⎵ is two halves drawn
|
||||
// side by side (offset by ICON_SPACE_L.w * scale): ticks at both far ends + bar.
|
||||
MINI_ICON(ICON_SPACE_L, 8,
|
||||
packRow("#......."),
|
||||
@@ -695,6 +1319,7 @@ MINI_ICON(ICON_SPACE_R, 8,
|
||||
packRow(".......#"),
|
||||
packRow("########"));
|
||||
|
||||
#endif
|
||||
|
||||
// Width of the right-edge column drawScrollIndicator occupies, or 0 when the
|
||||
// list fits and no indicator is drawn. Subtract from a row's content width so
|
||||
@@ -784,8 +1409,10 @@ inline void drawScrollIndicator(DisplayDriver& d, int right_x, int top_y, int tr
|
||||
// `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).
|
||||
// right_x narrows the list to a left column (a list beside a detail pane).
|
||||
template <class RenderRow>
|
||||
inline int drawList(DisplayDriver& d, int total, int sel, int& scroll, RenderRow row) {
|
||||
inline int drawList(DisplayDriver& d, int total, int sel, int& scroll, RenderRow row, int right_x = -1) {
|
||||
if (right_x < 0) right_x = d.width();
|
||||
const int item_h = d.lineStep();
|
||||
const int start_y = d.listStart();
|
||||
int visible = d.listVisible(item_h);
|
||||
@@ -796,7 +1423,7 @@ inline int drawList(DisplayDriver& d, int total, int sel, int& scroll, RenderRow
|
||||
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);
|
||||
drawScrollIndicator(d, right_x, start_y, visible * item_h, total, visible, scroll);
|
||||
return visible;
|
||||
}
|
||||
|
||||
@@ -852,8 +1479,8 @@ inline int drawLoadingDots(DisplayDriver& d, int cx, int y_bottom) {
|
||||
// row callback, then draw content over it. Captures the geometry every list row
|
||||
// repeated by hand; rows that intentionally differ (full-width, custom height)
|
||||
// still call display.drawSelectionRow() directly.
|
||||
inline void drawRowSelection(DisplayDriver& d, int y, bool sel, int reserve) {
|
||||
d.drawSelectionRow(0, y - 1, d.width() - reserve, d.lineStep() - 1, sel);
|
||||
inline void drawRowSelection(DisplayDriver& d, int y, bool sel, int reserve, int right_x = -1) {
|
||||
d.drawSelectionRow(0, y - 1, (right_x < 0 ? d.width() : right_x) - reserve, d.lineStep() - 1, sel);
|
||||
}
|
||||
|
||||
// Favourite marker for a list row, on every screen that lists something
|
||||
|
||||
Reference in New Issue
Block a user