refactor(display): extract dashboard tile grid logic to DisplayManager
This commit is contained in:
@@ -123,28 +123,51 @@ void DisplayDriverTFT::drawAlert(const ScreenState& st) {
|
||||
|
||||
void DisplayDriverTFT::drawDashboard(const ScreenState& st) {
|
||||
_tft.fillScreen(TFT_BLACK);
|
||||
_tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
|
||||
// Header
|
||||
_tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
_tft.setTextSize(1);
|
||||
_tft.setCursor(5, 5);
|
||||
_tft.printf("KLUBHAUS — %s", deviceStateStr(st.deviceState));
|
||||
_tft.printf("KLUBHAUS");
|
||||
|
||||
int y = 30;
|
||||
_tft.setCursor(5, y);
|
||||
y += 18;
|
||||
_tft.printf("WiFi: %s %ddBm", st.wifiSsid.c_str(), st.wifiRssi);
|
||||
// WiFi indicator
|
||||
_tft.setCursor(DISPLAY_WIDTH - 50, 5);
|
||||
_tft.printf("WiFi:%s", st.wifiSsid.length() > 0 ? "ON" : "OFF");
|
||||
|
||||
_tft.setCursor(5, y);
|
||||
y += 18;
|
||||
_tft.printf("IP: %s", st.ipAddr.c_str());
|
||||
// Render tiles via DisplayManager (abstracted to library)
|
||||
// For now, draw directly using our tile implementation
|
||||
constexpr int cols = 2;
|
||||
constexpr int rows = 2;
|
||||
constexpr int tileW = DISPLAY_WIDTH / cols;
|
||||
constexpr int tileH = (DISPLAY_HEIGHT - 30) / rows;
|
||||
constexpr int margin = 8;
|
||||
|
||||
_tft.setCursor(5, y);
|
||||
y += 18;
|
||||
_tft.printf("Up: %lus Heap: %d", st.uptimeMs / 1000, ESP.getFreeHeap());
|
||||
const char* tileLabels[] = { "Alert", "Silent", "Status", "Reboot" };
|
||||
const uint16_t tileColors[] = { 0x0280, 0x0400, 0x0440, 0x0100 };
|
||||
|
||||
_tft.setCursor(5, y);
|
||||
y += 18;
|
||||
_tft.printf("Last poll: %lus ago", st.lastPollMs > 0 ? (millis() - st.lastPollMs) / 1000 : 0);
|
||||
for(int i = 0; i < 4; i++) {
|
||||
int col = i % cols;
|
||||
int row = i / cols;
|
||||
|
||||
int x = col * tileW + margin;
|
||||
int y = 30 + row * tileH + margin;
|
||||
int w = tileW - 2 * margin;
|
||||
int h = tileH - 2 * margin;
|
||||
|
||||
// Tile background
|
||||
_tft.fillRoundRect(x, y, w, h, 8, tileColors[i]);
|
||||
|
||||
// Tile border
|
||||
_tft.drawRoundRect(x, y, w, h, 8, TFT_WHITE);
|
||||
|
||||
// Tile label
|
||||
_tft.setTextColor(TFT_WHITE);
|
||||
_tft.setTextSize(2);
|
||||
int textLen = strlen(tileLabels[i]);
|
||||
int textW = textLen * 12;
|
||||
_tft.setCursor(x + w/2 - textW/2, y + h/2 - 10);
|
||||
_tft.print(tileLabels[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Touch ───────────────────────────────────────────────────
|
||||
@@ -166,18 +189,27 @@ uint16_t DisplayDriverTFT::getRawTouchZ() {
|
||||
return _tft.getTouchRawZ();
|
||||
}
|
||||
|
||||
int DisplayDriverTFT::dashboardTouch(int x, int y) {
|
||||
// 2x2 grid, accounting for 30px header
|
||||
if(y < 30)
|
||||
return -1;
|
||||
void DisplayDriverTFT::transformTouch(int* x, int* y) {
|
||||
// Resistive touch panel is rotated 90° vs display - swap coordinates
|
||||
int temp = *x;
|
||||
*x = *y;
|
||||
*y = temp;
|
||||
}
|
||||
|
||||
int col = (x * 2) / DISPLAY_WIDTH; // 0 or 1
|
||||
int row = ((y - 30) * 2) / (DISPLAY_HEIGHT - 30); // 0 or 1
|
||||
void DisplayDriverTFT::drawTileAt(int x, int y, int w, int h, const char* label, uint16_t bgColor) {
|
||||
// Tile background
|
||||
_tft.fillRoundRect(x, y, w, h, 8, bgColor);
|
||||
|
||||
if(col < 0 || col > 1 || row < 0 || row > 1)
|
||||
return -1;
|
||||
// Tile border
|
||||
_tft.drawRoundRect(x, y, w, h, 8, TFT_WHITE);
|
||||
|
||||
return row * 2 + col; // 0, 1, 2, or 3
|
||||
// Tile label
|
||||
_tft.setTextColor(TFT_WHITE);
|
||||
_tft.setTextSize(2);
|
||||
int textLen = strlen(label);
|
||||
int textW = textLen * 12; // approx width
|
||||
_tft.setCursor(x + w/2 - textW/2, y + h/2 - 10);
|
||||
_tft.print(label);
|
||||
}
|
||||
|
||||
HoldState DisplayDriverTFT::updateHold(unsigned long holdMs) {
|
||||
|
||||
@@ -12,12 +12,15 @@ public:
|
||||
void render(const ScreenState& state) override;
|
||||
TouchEvent readTouch() override;
|
||||
uint16_t getRawTouchZ();
|
||||
int dashboardTouch(int x, int y) override;
|
||||
HoldState updateHold(unsigned long holdMs) override;
|
||||
void updateHint(int x, int y, bool active) override;
|
||||
int width() override { return DISPLAY_WIDTH; }
|
||||
int height() override { return DISPLAY_HEIGHT; }
|
||||
|
||||
// Dashboard tiles - library handles grid math, we just draw
|
||||
void transformTouch(int* x, int* y) override;
|
||||
void drawTileAt(int x, int y, int w, int h, const char* label, uint16_t bgColor) override;
|
||||
|
||||
private:
|
||||
void drawBoot(const ScreenState& st);
|
||||
void drawAlert(const ScreenState& st);
|
||||
|
||||
@@ -96,6 +96,22 @@ int DisplayDriverGFX::dashboardTouch(int x, int y) {
|
||||
return row * cols + col;
|
||||
}
|
||||
|
||||
void DisplayDriverGFX::drawTileAt(int x, int y, int w, int h, const char* label, uint16_t bgColor) {
|
||||
// Tile background (use fillRect - LovyanGFX may not have fillRoundRect)
|
||||
_gfx->fillRect(x, y, w, h, bgColor);
|
||||
|
||||
// Tile border
|
||||
_gfx->drawRect(x, y, w, h, 0xFFFF);
|
||||
|
||||
// Tile label
|
||||
_gfx->setTextColor(0xFFFF);
|
||||
_gfx->setTextSize(2);
|
||||
int textLen = strlen(label);
|
||||
int textW = textLen * 12;
|
||||
_gfx->setCursor(x + w/2 - textW/2, y + h/2 - 10);
|
||||
_gfx->print(label);
|
||||
}
|
||||
|
||||
HoldState DisplayDriverGFX::updateHold(unsigned long holdMs) {
|
||||
HoldState state;
|
||||
|
||||
|
||||
@@ -12,13 +12,15 @@ public:
|
||||
void render(const ScreenState& state) override;
|
||||
|
||||
TouchEvent readTouch() override;
|
||||
int dashboardTouch(int x, int y) override;
|
||||
HoldState updateHold(unsigned long holdMs) override;
|
||||
void updateHint(int x, int y, bool active) override;
|
||||
|
||||
int width() override;
|
||||
int height() override;
|
||||
|
||||
// Dashboard tiles - library handles grid math, we just draw
|
||||
void drawTileAt(int x, int y, int w, int h, const char* label, uint16_t bgColor) override;
|
||||
|
||||
// ── Internal ──
|
||||
static DisplayDriverGFX& instance();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user