refactor(Format code): Improve readability and structure

This commit is contained in:
2026-02-18 17:57:54 -08:00
parent c81e23f7cd
commit e4609c6978
11 changed files with 120 additions and 136 deletions

View File

@@ -2,6 +2,7 @@
#include "IDisplayDriver.h"
#include "ScreenState.h"
#include <cmath>
/// Layout helper for dashboard tiles - computes positions based on constraints
@@ -10,50 +11,45 @@ public:
/// Calculate tile layouts for the given display dimensions
/// Returns array of TileLayout (must have capacity for DASHBOARD_TILE_COUNT)
/// Returns the number of columns and rows used
static int calculateLayouts(
int displayW,
int displayH,
int headerH,
int margin,
TileLayout* outLayouts,
int* outCols,
int* outRows
) {
static int calculateLayouts(int displayW, int displayH, int headerH, int margin,
TileLayout* outLayouts, int* outCols, int* outRows) {
int contentH = displayH - headerH;
int tileCount = DASHBOARD_TILE_COUNT;
// Determine base grid based on display aspect ratio
int cols, rows;
calculateGrid(tileCount, displayW, contentH, &cols, &rows);
// Calculate base cell sizes
int cellW = displayW / cols;
int cellH = contentH / rows;
// Simple first-fit: place tiles in order, respecting min sizes
// For more complex layouts, tiles could specify preferred positions
for(int i = 0; i < tileCount; i++) {
const DashboardTile& tile = DASHBOARD_TILES[i];
int tileCols = tile.constraint.minCols;
int tileRows = tile.constraint.minRows;
// Find next available position
int col = 0, row = 0;
findNextPosition(outLayouts, i, cols, rows, &col, &row);
// Ensure tile fits within grid
if(col + tileCols > cols) tileCols = cols - col;
if(row + tileRows > rows) tileRows = rows - row;
if(col + tileCols > cols)
tileCols = cols - col;
if(row + tileRows > rows)
tileRows = rows - row;
// Calculate pixel position
int x = col * cellW + margin;
int y = headerH + row * cellH + margin;
int w = tileCols * cellW - 2 * margin;
int h = tileRows * cellH - 2 * margin;
outLayouts[i] = {x, y, w, h, col, row, tileCols, tileRows};
outLayouts[i] = { x, y, w, h, col, row, tileCols, tileRows };
}
*outCols = cols;
*outRows = rows;
return tileCount;
@@ -61,17 +57,20 @@ public:
private:
/// Calculate optimal grid dimensions based on display and tile constraints
static void calculateGrid(int tileCount, int displayW, int contentH, int* outCols, int* outRows) {
static void calculateGrid(
int tileCount, int displayW, int contentH, int* outCols, int* outRows) {
// Calculate aspect ratio to determine preferred layout
float aspectRatio = (float)displayW / contentH;
// Start with simple square-ish grid
int cols = (int)std::sqrt(tileCount * aspectRatio);
if(cols < 1) cols = 1;
if(cols > tileCount) cols = tileCount;
if(cols < 1)
cols = 1;
if(cols > tileCount)
cols = tileCount;
int rows = (tileCount + cols - 1) / cols;
// For wide displays (landscape), prefer more columns
if(aspectRatio > 1.5f && tileCount <= 6) {
cols = tileCount;
@@ -82,21 +81,22 @@ private:
rows = tileCount;
cols = 1;
}
*outCols = cols;
*outRows = rows;
}
/// Find next available grid position
static void findNextPosition(const TileLayout* layouts, int count, int gridCols, int gridRows, int* outCol, int* outRow) {
static void findNextPosition(const TileLayout* layouts, int count, int gridCols, int gridRows,
int* outCol, int* outRow) {
// Simple: find first empty cell
// Could be enhanced to pack tightly based on tile sizes
for(int r = 0; r < gridRows; r++) {
for(int c = 0; c < gridCols; c++) {
bool occupied = false;
for(int i = 0; i < count; i++) {
if(layouts[i].col <= c && c < layouts[i].col + layouts[i].cols &&
layouts[i].row <= r && r < layouts[i].row + layouts[i].rows) {
if(layouts[i].col <= c && c < layouts[i].col + layouts[i].cols
&& layouts[i].row <= r && r < layouts[i].row + layouts[i].rows) {
occupied = true;
break;
}
@@ -130,7 +130,8 @@ public:
}
void render(const ScreenState& st) {
if(!_drv) return;
if(!_drv)
return;
_drv->render(st);
}
@@ -146,62 +147,65 @@ public:
/// Show touch feedback - highlights the tile at given coordinates
/// Returns true if a valid tile is being touched
bool showTouchFeedback(int x, int y) {
if(!_drv || _gridCols <= 0) return false;
if(!_drv || _gridCols <= 0)
return false;
// Transform touch coordinates
_drv->transformTouch(&x, &y);
int headerH = 30;
if(y < headerH) return false;
if(y < headerH)
return false;
// Calculate which cell
int cellW = _drv->width() / _gridCols;
int cellH = (_drv->height() - headerH) / _gridRows;
int col = x / cellW;
int row = (y - headerH) / cellH;
if(col < 0 || col >= _gridCols || row < 0 || row >= _gridRows)
return false;
// Find which tile is at this position
for(int i = 0; i < _tileCount; i++) {
const TileLayout& lay = _layouts[i];
if(lay.col <= col && col < lay.col + lay.cols &&
lay.row <= row && lay.row + lay.rows > row) {
if(lay.col <= col && col < lay.col + lay.cols && lay.row <= row
&& lay.row + lay.rows > row) {
// Found the tile - draw highlight via driver
_drv->updateHint(lay.x, lay.y, true); // active=true means show feedback
_drv->updateHint(lay.x, lay.y, true); // active=true means show feedback
return true;
}
}
return false;
}
/// Clear touch feedback
void clearTouchFeedback() {
if(_drv)
_drv->updateHint(0, 0, false); // active=false means clear
_drv->updateHint(0, 0, false); // active=false means clear
}
/// Check if current position is still in same tile as touch-down
bool isSameTile(int downX, int downY, int currentX, int currentY) const {
if(!_drv || _gridCols <= 0 || downX < 0) return false;
if(!_drv || _gridCols <= 0 || downX < 0)
return false;
int dx = downX, dy = downY;
int cx = currentX, cy = currentY;
_drv->transformTouch(&dx, &dy);
_drv->transformTouch(&cx, &cy);
int headerH = 30;
int cellW = _drv->width() / _gridCols;
int cellH = (_drv->height() - headerH) / _gridRows;
int downCol = dx / cellW;
int downRow = (dy - headerH) / cellH;
int curCol = cx / cellW;
int curRow = (cy - headerH) / cellH;
return downCol == curCol && downRow == curRow;
}
@@ -210,59 +214,55 @@ public:
/// Handle dashboard touch - returns action for tapped tile, or NONE
TileAction handleDashboardTouch(int x, int y) const {
if(!_drv || _gridCols <= 0) return TileAction::NONE;
if(!_drv || _gridCols <= 0)
return TileAction::NONE;
// Transform touch coordinates (handles rotated touch panels)
_drv->transformTouch(&x, &y);
int dispW = _drv->width();
int dispH = _drv->height();
int headerH = 30;
// Check if in header area
if(y < headerH) return TileAction::NONE;
if(y < headerH)
return TileAction::NONE;
// Calculate which tile was touched using grid
int cellW = dispW / _gridCols;
int cellH = (dispH - headerH) / _gridRows;
int col = x / cellW;
int row = (y - headerH) / cellH;
// Bounds check
if(col < 0 || col >= _gridCols || row < 0 || row >= _gridRows) {
return TileAction::NONE;
}
// Find which tile occupies this cell
for(int i = 0; i < _tileCount; i++) {
const TileLayout& layout = _layouts[i];
if(layout.col <= col && col < layout.col + layout.cols &&
layout.row <= row && row < layout.row + layout.rows) {
if(layout.col <= col && col < layout.col + layout.cols && layout.row <= row
&& row < layout.row + layout.rows) {
return DASHBOARD_TILES[i].action;
}
}
return TileAction::NONE;
}
/// Calculate and store layouts for dashboard tiles
/// Called by drivers who want to use the layout helper
int calculateDashboardLayouts(int headerH = 30, int margin = 8) {
if(!_drv) return 0;
if(!_drv)
return 0;
_tileCount = TileLayoutHelper::calculateLayouts(
_drv->width(),
_drv->height(),
headerH,
margin,
_layouts,
&_gridCols,
&_gridRows
);
_drv->width(), _drv->height(), headerH, margin, _layouts, &_gridCols, &_gridRows);
return _tileCount;
}
/// Get calculated layout for a specific tile
const TileLayout* getTileLayouts() const { return _layouts; }
int getGridCols() const { return _gridCols; }

View File

@@ -133,8 +133,8 @@ void DoorbellLogic::update() {
default:
// Inactivity timeout: turn off screen after no activity
if(_state.screen != ScreenID::OFF && now - _lastActivityMs > INACTIVITY_TIMEOUT_MS) {
Serial.printf("[%lu] [STATE] Inactivity timeout (%lu ms) → OFF\n",
millis(), now - _lastActivityMs);
Serial.printf("[%lu] [STATE] Inactivity timeout (%lu ms) → OFF\n", millis(),
now - _lastActivityMs);
_state.screen = ScreenID::OFF;
_display->setBacklight(false);
_state.backlightOn = false;
@@ -231,13 +231,13 @@ void DoorbellLogic::onAdmin(const String& cmd) {
ESP.restart();
} else if(cmd == "dashboard") {
Serial.printf("[%lu] [ADMIN] dashboard\n", millis());
_lastActivityMs = millis(); // Reset inactivity timer
_lastActivityMs = millis(); // Reset inactivity timer
_state.screen = ScreenID::DASHBOARD;
_display->setBacklight(true);
_state.backlightOn = true;
} else if(cmd == "off") {
Serial.printf("[%lu] [ADMIN] off\n", millis());
_lastActivityMs = millis(); // Reset inactivity timer
_lastActivityMs = millis(); // Reset inactivity timer
_state.screen = ScreenID::OFF;
_display->setBacklight(false);
_state.backlightOn = false;

View File

@@ -2,12 +2,12 @@
#include "ScreenState.h"
struct TouchEvent {
bool pressed = false; // finger just touched down
bool released = false; // finger just lifted (after being pressed)
int x = 0; // current x position
int y = 0; // current y position
int downX = -1; // x position where touch started
int downY = -1; // y position where touch started
bool pressed = false; // finger just touched down
bool released = false; // finger just lifted (after being pressed)
int x = 0; // current x position
int y = 0; // current y position
int downX = -1; // x position where touch started
int downY = -1; // y position where touch started
};
struct HoldState {

View File

@@ -10,24 +10,24 @@ enum class BootStage { SPLASH, INIT_DISPLAY, INIT_NETWORK, CONNECTING_WIFI, READ
/// Dashboard tile action handlers
enum class TileAction {
NONE,
ALERT, // Trigger alert
SILENCE, // Silence alert
STATUS, // Send heartbeat/status
REBOOT, // Reboot device
ALERT, // Trigger alert
SILENCE, // Silence alert
STATUS, // Send heartbeat/status
REBOOT, // Reboot device
};
/// Dashboard tile layout constraints for flexible grid
struct TileConstraint {
uint8_t minCols = 1; // minimum columns this tile needs
uint8_t minRows = 1; // minimum rows this tile needs
uint8_t weight = 1; // priority for growing/shrinking (higher = more flexible)
uint8_t minCols = 1; // minimum columns this tile needs
uint8_t minRows = 1; // minimum rows this tile needs
uint8_t weight = 1; // priority for growing/shrinking (higher = more flexible)
};
/// Computed tile position in the grid
struct TileLayout {
int x, y; // pixel position
int w, h; // pixel size
int col, row; // grid position
int x, y; // pixel position
int w, h; // pixel size
int col, row; // grid position
int cols, rows; // grid span
};
@@ -41,10 +41,10 @@ struct DashboardTile {
/// Standard dashboard tiles (auto-gridded based on count and constraints)
static constexpr DashboardTile DASHBOARD_TILES[] = {
{ "Alert", 0x0280, TileAction::ALERT, {1, 1, 1} },
{ "Silent", 0x0400, TileAction::SILENCE, {1, 1, 1} },
{ "Status", 0x0440, TileAction::STATUS, {1, 1, 1} },
{ "Reboot", 0x0100, TileAction::REBOOT, {1, 1, 1} },
{ "Alert", 0x0280, TileAction::ALERT, { 1, 1, 1 } },
{ "Silent", 0x0400, TileAction::SILENCE, { 1, 1, 1 } },
{ "Status", 0x0440, TileAction::STATUS, { 1, 1, 1 } },
{ "Reboot", 0x0100, TileAction::REBOOT, { 1, 1, 1 } },
};
static constexpr int DASHBOARD_TILE_COUNT = sizeof(DASHBOARD_TILES) / sizeof(DASHBOARD_TILES[0]);