2026-04-06 13:11:15 +02:00

153 lines
6.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <Arduino.h>
#include <ArduinoJson.h>
#include <GxEPD2_BW.h>
#include "icons.h"
// ── Font size helper ──────────────────────────────────────────────────────────
/**
* Map an API font_size value (typically 840) to GFX setTextSize(15).
* font_size / 8, clamped to [1, 5].
*/
static inline uint8_t mapFontSize(int fontSize) {
int s = fontSize / 8;
if (s < 1) s = 1;
if (s > 5) s = 5;
return static_cast<uint8_t>(s);
}
// ── Render all elements from JSON array ───────────────────────────────────────
/**
* Iterates every element in the JsonArray and draws it onto `display`.
* Must be called inside a firstPage/nextPage loop so that display is
* already prepared for drawing.
*/
template <typename GxEPD2_Type>
void renderElements(GxEPD2_Type& display, JsonArray elements) {
for (JsonObject el : elements) {
const char* type = el["type"] | "";
int x = el["x"] | 0;
int y = el["y"] | 0;
int w = el["w"] | 0;
int h = el["h"] | 0;
// ── line ─────────────────────────────────────────────────────────────
if (strcmp(type, "line") == 0) {
// Use fillRect: height==1 → horizontal, width==1 → vertical
int thickness = el["thickness"] | 1;
if (h <= 1 && w > 1) {
// horizontal line
display.fillRect(x, y, w, (thickness > 0 ? thickness : 1), GxEPD_BLACK);
} else if (w <= 1 && h > 1) {
// vertical line
display.fillRect(x, y, (thickness > 0 ? thickness : 1), h, GxEPD_BLACK);
} else {
// generic: draw as thin rect
display.fillRect(x, y, w, h, GxEPD_BLACK);
}
}
// ── rect ─────────────────────────────────────────────────────────────
else if (strcmp(type, "rect") == 0) {
display.drawRect(x, y, w, h, GxEPD_BLACK);
}
// ── label ────────────────────────────────────────────────────────────
else if (strcmp(type, "label") == 0) {
const char* text = el["text"] | "";
int fontSize = el["font_size"] | 8;
const char* textAlign = el["text_align"] | "left";
uint8_t sz = mapFontSize(fontSize);
display.setTextColor(GxEPD_BLACK);
display.setTextSize(sz);
if (strcmp(textAlign, "center") == 0) {
// Calculate approximate text width: each char is 6px wide at size 1
int charWidth = 6 * sz;
int textLen = strlen(text);
int textWidth = charWidth * textLen;
int textHeight = 8 * sz;
display.setCursor(x - textWidth / 2, y - textHeight / 2);
} else if (strcmp(textAlign, "right") == 0) {
int charWidth = 6 * sz;
int textLen = strlen(text);
int textWidth = charWidth * textLen;
display.setCursor(x - textWidth, y);
} else {
// left (default)
display.setCursor(x, y);
}
display.print(text);
}
// ── value ─────────────────────────────────────────────────────────────
else if (strcmp(type, "value") == 0) {
const char* style = el["style"] | "plain";
const char* label = el["label"] | "";
const char* value = el["value"] | "";
const char* unit = el["unit"] | "";
const char* iconName = el["icon"] | "";
int fontSize = el["font_size"] | 16;
if (strcmp(style, "card") == 0) {
// ── card style ─────────────────────────────────────────────
// Border
display.drawRoundRect(x, y, w, h, 4, GxEPD_BLACK);
// Icon top-left (24x24), with small padding
const unsigned char* iconData = getIcon(iconName);
if (iconData != nullptr) {
display.drawBitmap(x + 4, y + 4, iconData, 24, 24, GxEPD_BLACK);
}
// Label text (small, below icon)
display.setTextColor(GxEPD_BLACK);
display.setTextSize(1);
display.setCursor(x + 4, y + 32);
display.print(label);
// Value + unit (large, bottom-right)
uint8_t valSize = mapFontSize(fontSize);
display.setTextSize(valSize);
// Build value string with unit
String valStr = String(value);
if (strlen(unit) > 0) {
valStr += " ";
valStr += unit;
}
// Right-align inside card
int charWidth = 6 * valSize;
int valWidth = charWidth * valStr.length();
int valX = x + w - valWidth - 4;
int valY = y + h - 8 * valSize - 4;
if (valX < x + 4) valX = x + 4;
display.setCursor(valX, valY);
display.print(valStr);
} else {
// ── plain style ─────────────────────────────────────────────
uint8_t sz = mapFontSize(fontSize);
display.setTextColor(GxEPD_BLACK);
display.setTextSize(sz);
display.setCursor(x, y);
// "Label: value unit"
String line;
if (strlen(label) > 0) {
line += label;
line += ": ";
}
line += value;
if (strlen(unit) > 0) {
line += " ";
line += unit;
}
display.print(line);
}
}
}
}