From f6c6e77219f6cafa2e6fbb9f724dea7e4f80dee3 Mon Sep 17 00:00:00 2001 From: philmoz Date: Fri, 3 Feb 2023 21:45:03 +1100 Subject: [PATCH] chore(color): LVGLify statistics and debug screens (#3072) * LVGL flex conversion for statistics and debug pages. * Replace empty text box with call to grid.nextCell(). * chore: Formatting --- radio/src/gui/colorlcd/view_statistics.cpp | 327 ++++++++++++++------- radio/src/gui/colorlcd/view_statistics.h | 25 -- 2 files changed, 215 insertions(+), 137 deletions(-) diff --git a/radio/src/gui/colorlcd/view_statistics.cpp b/radio/src/gui/colorlcd/view_statistics.cpp index 14671cdf7..49614524a 100644 --- a/radio/src/gui/colorlcd/view_statistics.cpp +++ b/radio/src/gui/colorlcd/view_statistics.cpp @@ -20,9 +20,62 @@ */ #include "view_statistics.h" + #include "opentx.h" #include "draw_functions.h" +static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), + LV_GRID_FR(1), LV_GRID_FR(1), + LV_GRID_TEMPLATE_LAST}; + +#if LCD_W > LCD_H +static const lv_coord_t dbg_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), + LV_GRID_FR(1), LV_GRID_FR(1), + LV_GRID_TEMPLATE_LAST}; +#define DBG_COL_CNT 4 +#else +static const lv_coord_t dbg_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), + LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; +#define DBG_COL_CNT 3 +#endif + +static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; + +#if LCD_W > LCD_H +#define CV_SCALE 3 +#else +#define CV_SCALE 4 +#endif +#define CV_WIDTH MAXTRACE +#define CV_HEIGHT (CV_SCALE * 32 + 5) + +#define DBG_B_WIDTH (LCD_W - 20) / 4 +#define DBG_B_HEIGHT 24 + +template +class DebugInfoNumber : public Window +{ + public: + DebugInfoNumber(Window* parent, const rect_t& rect, + std::function numberHandler, LcdFlags textFlags = 0, + const char* prefix = nullptr, const char* suffix = nullptr) : + Window(parent, rect, 0, textFlags), prefix(prefix), suffix(suffix) + { + coord_t prefixSize = 0; + if (prefix != nullptr) { + prefixSize = getTextWidth(prefix, 0, COLOR_THEME_PRIMARY1 | FONT(XS)); + new StaticText(this, {0, 1, prefixSize, rect.h}, prefix, 0, + COLOR_THEME_PRIMARY1 | FONT(XS)); + } + new DynamicNumber(this, + {prefixSize, 0, rect.w - prefixSize, rect.h}, + numberHandler, COLOR_THEME_PRIMARY1); + } + + protected: + const char* prefix; + const char* suffix; +}; StatisticsViewPageGroup::StatisticsViewPageGroup() : TabsGroup(ICON_STATS) { @@ -33,7 +86,7 @@ StatisticsViewPageGroup::StatisticsViewPageGroup() : TabsGroup(ICON_STATS) class ThrottleCurveWindow : public Window { public: - ThrottleCurveWindow(Window *parent, const rect_t &rect) : Window(parent, rect) + ThrottleCurveWindow(Window* parent, const rect_t& rect) : Window(parent, rect) { } @@ -46,14 +99,14 @@ class ThrottleCurveWindow : public Window } } - void paint(BitmapBuffer *dc) override + void paint(BitmapBuffer* dc) override { // Axis - dc->drawHorizontalLine(0, height() - 2, width(), - SOLID | COLOR_THEME_SECONDARY1); - dc->drawVerticalLine(0, 0, height(), SOLID, COLOR_THEME_SECONDARY1); + dc->drawHorizontalLine(0, height() - 3, width(), SOLID, + COLOR_THEME_SECONDARY1); + dc->drawVerticalLine(0, 0, height() - 3, SOLID, COLOR_THEME_SECONDARY1); for (coord_t i = 0; i < width(); i += 6) { - dc->drawVerticalLine(i, height() - 4, 3, SOLID | COLOR_THEME_SECONDARY1); + dc->drawVerticalLine(i, height() - 6, 3, SOLID, COLOR_THEME_SECONDARY1); } // Curve @@ -61,7 +114,7 @@ class ThrottleCurveWindow : public Window coord_t prev_yv = (coord_t)-1; for (coord_t i = 1; i <= width() && traceRd < s_traceWr; i++, traceRd++) { uint8_t h = s_traceBuf[traceRd % width()]; - coord_t yv = height() - 2 - 3 * h; + coord_t yv = height() - 5 - CV_SCALE * h; if (prev_yv != (coord_t)-1) { if (prev_yv < yv) { for (int y = prev_yv; y <= yv; y++) { @@ -83,191 +136,241 @@ class ThrottleCurveWindow : public Window unsigned previousTraceWr = 0; }; -void StatisticsViewPage::build(FormWindow *window) +void StatisticsViewPage::build(FormWindow* window) { - FormGridLayout grid; - grid.spacer(PAGE_PADDING); - grid.setLabelWidth(LCD_W / 4); + window->padAll(0); + + auto form = new FormWindow(window, rect_t{}); + form->setFlexLayout(); + form->padAll(0); + form->padLeft(4); + form->padRight(4); + + FlexGridLayout grid(col_dsc, row_dsc, 0); + + auto line = form->newLine(&grid); + line->padAll(0); // Session data - new StaticText(window, grid.getLabelSlot(), STR_SESSION, 0, - COLOR_THEME_PRIMARY1); + new StaticText(line, rect_t{}, STR_SESSION, 0, COLOR_THEME_PRIMARY1); new DynamicText( - window, grid.getFieldSlot(3, 0), - [] { return getTimerString(sessionTimer); }, + line, rect_t{}, [] { return getTimerString(sessionTimer); }, COLOR_THEME_PRIMARY1); // Battery data - new StaticText(window, grid.getFieldSlot(3, 1), STR_BATT_LABEL, 0, - COLOR_THEME_PRIMARY1); + new StaticText(line, rect_t{}, STR_BATT_LABEL, 0, COLOR_THEME_PRIMARY1); new DynamicText( - window, grid.getFieldSlot(3, 2), - [] { - return getTimerString(g_eeGeneral.globalTimer + sessionTimer); - }, + line, rect_t{}, + [] { return getTimerString(g_eeGeneral.globalTimer + sessionTimer); }, COLOR_THEME_PRIMARY1); - grid.nextLine(); + + line = form->newLine(&grid); + line->padAll(0); // Throttle - new StaticText(window, grid.getLabelSlot(), STR_THROTTLE_LABEL, 0, - COLOR_THEME_PRIMARY1); + new StaticText(line, rect_t{}, STR_THROTTLE_LABEL, 0, COLOR_THEME_PRIMARY1); new DynamicText( - window, grid.getFieldSlot(3, 0), - [] { return getTimerString(s_timeCumThr); }, + line, rect_t{}, [] { return getTimerString(s_timeCumThr); }, COLOR_THEME_PRIMARY1); // Throttle % data - new StaticText(window, grid.getFieldSlot(3, 1), STR_THROTTLE_PERCENT_LABEL, 0, + new StaticText(line, rect_t{}, STR_THROTTLE_PERCENT_LABEL, 0, COLOR_THEME_PRIMARY1); new DynamicText( - window, grid.getFieldSlot(3, 2), - [] { return getTimerString(s_timeCum16ThrP / 16); }, + line, rect_t{}, [] { return getTimerString(s_timeCum16ThrP / 16); }, COLOR_THEME_PRIMARY1); - grid.nextLine(); + + line = form->newLine(&grid); + line->padAll(0); // Timers - new StaticText(window, grid.getLabelSlot(), STR_TIMER_LABEL, 0, - COLOR_THEME_PRIMARY1); + new StaticText(line, rect_t{}, STR_TIMER_LABEL, 0, COLOR_THEME_PRIMARY1); new DynamicText( - window, grid.getFieldSlot(3, 0), - [] { return getTimerString(timersStates[0].val); }, + line, rect_t{}, [] { return getTimerString(timersStates[0].val); }, COLOR_THEME_PRIMARY1); new DynamicText( - window, grid.getFieldSlot(3, 1), - [] { return getTimerString(timersStates[1].val); }, + line, rect_t{}, [] { return getTimerString(timersStates[1].val); }, COLOR_THEME_PRIMARY1); new DynamicText( - window, grid.getFieldSlot(3, 2), - [] { return getTimerString(timersStates[2].val); }, + line, rect_t{}, [] { return getTimerString(timersStates[2].val); }, COLOR_THEME_PRIMARY1); - grid.nextLine(); + + line = form->newLine(&grid); + line->padAll(0); + line->padTop(4); // Throttle curve - auto curve = new ThrottleCurveWindow( - window, - {5, grid.getWindowHeight(), window->width() - 10, window->height() / 2}); - grid.spacer(curve->height() + 3); + auto curve = new ThrottleCurveWindow(line, {0, 0, CV_WIDTH, CV_HEIGHT}); + + lv_obj_set_grid_cell(curve->getLvObj(), LV_GRID_ALIGN_CENTER, 0, 4, + LV_GRID_ALIGN_CENTER, 0, 1); + + line = form->newLine(&grid); + line->padAll(0); + line->padTop(8); // Reset - new TextButton( - window, grid.getLineSlot(), STR_MENUTORESET, - [=]() -> uint8_t { - g_eeGeneral.globalTimer = 0; - storageDirty(EE_GENERAL); - sessionTimer = 0; - s_timeCumThr = 0; - s_timeCum16ThrP = 0; - s_traceWr = 0; - curve->invalidate(); - return 0; - }, - BUTTON_BACKGROUND); + auto btn = new TextButton(line, rect_t{0, 0, 0, 24}, STR_MENUTORESET, + [=]() -> uint8_t { + g_eeGeneral.globalTimer = 0; + storageDirty(EE_GENERAL); + sessionTimer = 0; + s_timeCumThr = 0; + s_timeCum16ThrP = 0; + s_traceWr = 0; + curve->invalidate(); + return 0; + }); + + lv_obj_set_grid_cell(btn->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, 4, + LV_GRID_ALIGN_CENTER, 0, 1); } -void DebugViewPage::build(FormWindow *window) +void DebugViewPage::build(FormWindow* window) { - FormGridLayout grid; - grid.spacer(PAGE_PADDING); - grid.setLabelWidth(LCD_W / 4); + window->padAll(4); + + auto form = new FormWindow(window, rect_t{}); + form->setFlexLayout(); + form->padAll(0); + + FlexGridLayout grid(dbg_col_dsc, row_dsc, 0); + + auto line = form->newLine(&grid); + line->padAll(4); // Mixer data - new StaticText(window, grid.getLabelSlot(), STR_TMIXMAXMS, 0, - COLOR_THEME_PRIMARY1); + new StaticText(line, rect_t{}, STR_TMIXMAXMS, 0, COLOR_THEME_PRIMARY1); new DynamicNumber( - window, grid.getFieldSlot(), - [] { return DURATION_MS_PREC2(maxMixerDuration); }, + line, rect_t{}, [] { return DURATION_MS_PREC2(maxMixerDuration); }, PREC2 | COLOR_THEME_PRIMARY1, nullptr, "ms"); - grid.nextLine(); + + line = form->newLine(&grid); + line->padAll(4); // Free mem - new StaticText(window, grid.getLabelSlot(), STR_FREE_MEM_LABEL, 0, - COLOR_THEME_PRIMARY1); + new StaticText(line, rect_t{}, STR_FREE_MEM_LABEL, 0, COLOR_THEME_PRIMARY1); new DynamicNumber( - window, grid.getFieldSlot(), [] { return availableMemory(); }, - COLOR_THEME_PRIMARY1, nullptr, "b"); - grid.nextLine(); + line, rect_t{}, [] { return availableMemory(); }, COLOR_THEME_PRIMARY1, + nullptr, "b"); #if defined(LUA) + line = form->newLine(&grid); + line->padAll(4); + // LUA timing data - new StaticText(window, grid.getLabelSlot(), STR_LUA_SCRIPTS_LABEL, 0, + new StaticText(line, rect_t{}, STR_LUA_SCRIPTS_LABEL, 0, COLOR_THEME_PRIMARY1); +#if LCD_H > LCD_W + line = form->newLine(&grid); + line->padAll(4); + line->padLeft(10); +#endif new DebugInfoNumber( - window, grid.getFieldSlot(3, 0), [] { return 10 * maxLuaDuration; }, - COLOR_THEME_PRIMARY1, "[Dur] ", "ms"); + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, + [] { return 10 * maxLuaDuration; }, COLOR_THEME_PRIMARY1, "[Dur] ", "ms"); new DebugInfoNumber( - window, grid.getFieldSlot(3, 1), [] { return 10 * maxLuaInterval; }, - COLOR_THEME_PRIMARY1, "[Int] ", "ms"); - grid.nextLine(); + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, + [] { return 10 * maxLuaInterval; }, COLOR_THEME_PRIMARY1, "[Int] ", "ms"); + + line = form->newLine(&grid); + line->padAll(4); +#if LCD_H > LCD_W + line->padLeft(10); +#else + grid.nextCell(); +#endif // lUA memory data new DebugInfoNumber( - window, grid.getFieldSlot(3, 0), + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, [] { return 10 * luaGetMemUsed(lsScripts); }, COLOR_THEME_PRIMARY1, "[S] ", nullptr); new DebugInfoNumber( - window, grid.getFieldSlot(3, 1), + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, [] { return 10 * luaGetMemUsed(lsWidgets); }, COLOR_THEME_PRIMARY1, "[W] ", nullptr); new DebugInfoNumber( - window, grid.getFieldSlot(3, 2), [] { return luaExtraMemoryUsage; }, - COLOR_THEME_PRIMARY1, "[B] ", nullptr); - grid.nextLine(); + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, + [] { return luaExtraMemoryUsage; }, COLOR_THEME_PRIMARY1, "[B] ", + nullptr); #endif + line = form->newLine(&grid); + line->padAll(4); + // Stacks data - new StaticText(window, grid.getLabelSlot(), STR_FREE_STACK, 0, - COLOR_THEME_PRIMARY1); + new StaticText(line, rect_t{}, STR_FREE_STACK, 0, COLOR_THEME_PRIMARY1); +#if LCD_H > LCD_W + line = form->newLine(&grid); + line->padAll(4); + line->padLeft(10); +#endif new DebugInfoNumber( - window, grid.getFieldSlot(3, 0), [] { return menusStack.available(); }, - COLOR_THEME_PRIMARY1, "[Menu] ", nullptr); + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, + [] { return menusStack.available(); }, COLOR_THEME_PRIMARY1, "[Menu] ", + nullptr); new DebugInfoNumber( - window, grid.getFieldSlot(3, 1), [] { return mixerStack.available(); }, - COLOR_THEME_PRIMARY1, "[Mix] ", nullptr); + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, + [] { return mixerStack.available(); }, COLOR_THEME_PRIMARY1, "[Mix] ", + nullptr); new DebugInfoNumber( - window, grid.getFieldSlot(3, 2), [] { return audioStack.available(); }, - COLOR_THEME_PRIMARY1, "[Audio] ", nullptr); - grid.nextLine(); + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, + [] { return audioStack.available(); }, COLOR_THEME_PRIMARY1, "[Audio] ", + nullptr); #if defined(DEBUG_LATENCY) - new StaticText(window, grid.getLabelSlot(), STR_HEARTBEAT_LABEL, 0, - COLOR_THEME_PRIMARY1); + line = form->newLine(&grid); + line->padAll(4); + + new StaticText(line, rect_t{}, STR_HEARTBEAT_LABEL, 0, COLOR_THEME_PRIMARY1); if (heartbeatCapture.valid) new DebugInfoNumber( - window, grid.getFieldSlot(3, 0), [] { return heartbeatCapture.count; }, - COLOR_THEME_PRIMARY1); + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, + [] { return heartbeatCapture.count; }, COLOR_THEME_PRIMARY1); else new StaticText(window, grid.getFieldSlot(), "---", 0, COLOR_THEME_PRIMARY1); #endif #if defined(INTERNAL_GPS) if (hasSerialMode(UART_MODE_GPS) != -1) { - new StaticText(window, grid.getLabelSlot(), STR_INT_GPS_LABEL, 0, - COLOR_THEME_PRIMARY1); + line = form->newLine(&grid); + line->padAll(4); + + new StaticText(line, rect_t{}, STR_INT_GPS_LABEL, 0, COLOR_THEME_PRIMARY1); +#if LCD_H > LCD_W + line = form->newLine(&grid); + line->padAll(4); + line->padLeft(10); +#endif new DynamicText( - window, grid.getFieldSlot(3, 0), + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, [] { return std::string(gpsData.fix ? "[Fix] Yes" : "[Fix] No"); }, COLOR_THEME_PRIMARY1); new DebugInfoNumber( - window, grid.getFieldSlot(3, 1), [] { return gpsData.numSat; }, - COLOR_THEME_PRIMARY1, "[Sats] ", nullptr); + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, + [] { return gpsData.numSat; }, COLOR_THEME_PRIMARY1, "[Sats] ", + nullptr); new DebugInfoNumber( - window, grid.getFieldSlot(3, 2), [] { return gpsData.hdop; }, - COLOR_THEME_PRIMARY1, "[Hdop] ", nullptr); - grid.nextLine(); + line, rect_t{0, 0, DBG_B_WIDTH, DBG_B_HEIGHT}, + [] { return gpsData.hdop; }, COLOR_THEME_PRIMARY1, "[Hdop] ", nullptr); } #endif + line = form->newLine(&grid); + line->padAll(4); + // Reset - grid.nextLine(); - new TextButton( - window, grid.getLineSlot(), STR_MENUTORESET, - [=]() -> uint8_t { - maxMixerDuration = 0; + auto btn = new TextButton(line, rect_t{0, 0, 0, 24}, STR_MENUTORESET, + [=]() -> uint8_t { + maxMixerDuration = 0; #if defined(LUA) - maxLuaInterval = 0; - maxLuaDuration = 0; + maxLuaInterval = 0; + maxLuaDuration = 0; #endif - return 0; - }, - BUTTON_BACKGROUND); + return 0; + }); + + lv_obj_set_grid_cell(btn->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, DBG_COL_CNT, + LV_GRID_ALIGN_CENTER, 0, 1); } diff --git a/radio/src/gui/colorlcd/view_statistics.h b/radio/src/gui/colorlcd/view_statistics.h index 428e9f5a2..e2e3fe4b3 100644 --- a/radio/src/gui/colorlcd/view_statistics.h +++ b/radio/src/gui/colorlcd/view_statistics.h @@ -27,31 +27,6 @@ #include "tabsgroup.h" #include "window.h" -template -class DebugInfoNumber : public Window -{ - public: - DebugInfoNumber(Window* parent, const rect_t& rect, - std::function numberHandler, LcdFlags textFlags = 0, - const char* prefix = nullptr, const char* suffix = nullptr) : - Window(parent, rect, 0, textFlags), prefix(prefix), suffix(suffix) - { - coord_t prefixSize = 0; - if (prefix != nullptr) { - prefixSize = getTextWidth(prefix, 0, COLOR_THEME_PRIMARY1 | FONT(XS)); - new StaticText(this, {0, 0, prefixSize, rect.h}, prefix, 0, - COLOR_THEME_PRIMARY1 | FONT(XS)); - } - new DynamicNumber(this, - {prefixSize, 0, rect.w - prefixSize, rect.h}, - numberHandler, COLOR_THEME_PRIMARY1); - } - - protected: - const char* prefix; - const char* suffix; -}; - class StatisticsViewPage : public PageTab { public: