feat: add procedural pin and calendar icons to metadata badges

Draw pin icon on the location badge and calendar icon on the
datetime badge when displaying a single photo (not side-by-side).
Icons are rendered using M5GFX shape primitives (fillCircle,
fillTriangle, drawRect, fillRect, drawLine) - no bitmap data needed.

Icons only appear when regionW == DISPLAY_WIDTH to avoid cluttering
the narrower badges used for portrait-pair layouts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-03 21:03:46 -04:00
parent c28b8efcb5
commit 839805906d
2 changed files with 53 additions and 4 deletions

View File

@@ -185,6 +185,10 @@ void DisplayManager::showMetadataInRegion(const AssetInfo& info, uint8_t metaFla
static constexpr uint16_t PAD_X = 8;
static constexpr uint16_t PAD_Y = 5;
static constexpr uint16_t TEXT_H = 20;
static constexpr uint16_t ICON_SIZE = 12;
static constexpr uint16_t ICON_GAP = 4;
bool showIcons = (regionW == DISPLAY_WIDTH);
_display->setTextSize(1.5f);
_display->setTextColor(TFT_WHITE);
@@ -211,7 +215,8 @@ void DisplayManager::showMetadataInRegion(const AssetInfo& info, uint8_t metaFla
case MetaPosition::OverlayBottomLeft:
case MetaPosition::OverlayBottomRight: {
uint16_t textW = _display->textWidth(metaText.c_str());
uint16_t badgeW = min((uint16_t)(textW + PAD_X * 2), regionW);
uint16_t iconExtra = showIcons ? (ICON_SIZE + ICON_GAP) : 0;
uint16_t badgeW = min((uint16_t)(textW + iconExtra + PAD_X * 2), regionW);
uint16_t badgeH = TEXT_H + PAD_Y * 2;
uint16_t bx, by;
@@ -240,7 +245,12 @@ void DisplayManager::showMetadataInRegion(const AssetInfo& info, uint8_t metaFla
drawOverlayBadge(bx, by, badgeW, badgeH);
_display->setTextDatum(middle_left);
_display->drawString(metaText.c_str(), bx + PAD_X, by + badgeH / 2);
uint16_t textX = bx + PAD_X;
if (showIcons) {
drawCalendarIcon(bx + PAD_X, by + (badgeH - ICON_SIZE) / 2, ICON_SIZE);
textX += ICON_SIZE + ICON_GAP;
}
_display->drawString(metaText.c_str(), textX, by + badgeH / 2);
mainBadgeBottomY = by + badgeH;
break;
}
@@ -250,7 +260,8 @@ void DisplayManager::showMetadataInRegion(const AssetInfo& info, uint8_t metaFla
// Draw location badge in lower-left corner (separate from main badge)
if (locationText.length() > 0) {
uint16_t locTextW = _display->textWidth(locationText.c_str());
uint16_t locBadgeW = min((uint16_t)(locTextW + PAD_X * 2), regionW);
uint16_t iconExtra = showIcons ? (ICON_SIZE + ICON_GAP) : 0;
uint16_t locBadgeW = min((uint16_t)(locTextW + iconExtra + PAD_X * 2), regionW);
uint16_t locBadgeH = TEXT_H + PAD_Y * 2;
uint16_t lx = regionX + MARGIN;
@@ -264,7 +275,12 @@ void DisplayManager::showMetadataInRegion(const AssetInfo& info, uint8_t metaFla
drawOverlayBadge(lx, ly, locBadgeW, locBadgeH);
_display->setTextColor(TFT_WHITE);
_display->setTextDatum(middle_left);
_display->drawString(locationText.c_str(), lx + PAD_X, ly + locBadgeH / 2);
uint16_t locTextX = lx + PAD_X;
if (showIcons) {
drawPinIcon(lx + PAD_X, ly + (locBadgeH - ICON_SIZE) / 2, ICON_SIZE);
locTextX += ICON_SIZE + ICON_GAP;
}
_display->drawString(locationText.c_str(), locTextX, ly + locBadgeH / 2);
}
}
@@ -320,6 +336,37 @@ void DisplayManager::drawOverlayBadge(uint16_t x, uint16_t y, uint16_t w, uint16
}
}
void DisplayManager::drawPinIcon(int32_t x, int32_t y, int32_t size) {
int32_t r = size * 2 / 5;
int32_t cx = x + size / 2;
int32_t cy = y + r + 1;
_display->fillCircle(cx, cy, r, TFT_WHITE);
_display->fillTriangle(cx - r + 1, cy + r / 2, cx + r - 1, cy + r / 2,
cx, y + size - 1, TFT_WHITE);
_display->fillCircle(cx, cy, r / 3, TFT_BLACK);
}
void DisplayManager::drawCalendarIcon(int32_t x, int32_t y, int32_t size) {
int32_t bodyY = y + size / 4;
int32_t bodyH = size - size / 4;
int32_t bodyW = size;
_display->drawRect(x, bodyY, bodyW, bodyH, TFT_WHITE);
int32_t headerH = bodyH / 3;
_display->drawLine(x, bodyY + headerH, x + bodyW - 1, bodyY + headerH, TFT_WHITE);
int32_t tabW = 2, tabH = size / 4 + 1;
_display->fillRect(x + bodyW / 4, y, tabW, tabH, TFT_WHITE);
_display->fillRect(x + bodyW * 3 / 4 - tabW, y, tabW, tabH, TFT_WHITE);
int32_t dotSize = max((int32_t)1, size / 6);
int32_t gridY = bodyY + headerH + 2;
int32_t gridX = x + 2;
int32_t gapX = (bodyW - 4) / 3;
int32_t gapY = (bodyH - headerH - 3) / 2;
for (int row = 0; row < 2; row++)
for (int col = 0; col < 3; col++)
_display->fillRect(gridX + col * gapX, gridY + row * gapY,
dotSize, dotSize, TFT_WHITE);
}
void DisplayManager::showSleepIndicator(MetaPosition metaPos) {
_power->enableEPDPower();

View File

@@ -33,5 +33,7 @@ private:
bool _translucent = false;
void drawOverlayBadge(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
void drawPinIcon(int32_t x, int32_t y, int32_t size);
void drawCalendarIcon(int32_t x, int32_t y, int32_t size);
void triggerRefresh();
};