From 5622cb9c5c2ce15ca36fdeab3c8d69c93b496708 Mon Sep 17 00:00:00 2001 From: philmoz Date: Sun, 26 Mar 2023 20:10:56 +1100 Subject: [PATCH] chore(color): Replace StaticText with LVGL labels on GVARS page (#3310) * chore(ui): speedup gvars page * Replace StaticText with LVGL labels. * Further performance improvements. * Remove diagnostics. * Fix portrait layout. * Refactor style to a separate class and use CHECKED state to control color of selected flight mode. * Remove duplicate lines. * User LVGL state and style for GV value font size selection. Reduce the number of times the style_refresh state is changed. * Center align name without needing hard wired offsets. * Speed up page build time. * chore: Bump libopenui gagarinlg chore(ui): improve static text and window base speed (#88) --------- Co-authored-by: gagarinlg --- radio/src/gui/colorlcd/model_gvars.cpp | 248 +++++++++++++++++-------- radio/src/thirdparty/libopenui | 2 +- 2 files changed, 172 insertions(+), 78 deletions(-) diff --git a/radio/src/gui/colorlcd/model_gvars.cpp b/radio/src/gui/colorlcd/model_gvars.cpp index f6dff8b04..0b6793e84 100644 --- a/radio/src/gui/colorlcd/model_gvars.cpp +++ b/radio/src/gui/colorlcd/model_gvars.cpp @@ -27,117 +27,216 @@ #define SET_DIRTY() storageDirty(EE_MODEL) -#define TEXT_LEFT_MARGIN 2 #define GVAR_NAME_SIZE 44 +#define GVAR_VAL_H (PAGE_LINE_HEIGHT * 2 - 6) #if LCD_W > LCD_H -#define GVAR_VAL_SIZE 45 -#define GVAR_TTL_OFST 6 +#define BTN_H 38 +#define GVAR_VAL_W 45 +#define GVAR_COLS MAX_FLIGHT_MODES +#define GVAR_H GVAR_VAL_H #else -#define GVAR_VAL_SIZE 50 -#define GVAR_TTL_OFST 24 +#define BTN_H 72 +#define GVAR_VAL_W 50 +#define GVAR_COLS 5 +#define GVAR_H (GVAR_VAL_H * 2) #endif +class GVarStyle +{ + public: + GVarStyle() {} + + void init() + { + if(!styleInitDone) + { + styleInitDone=true; + + lv_style_init(&fmContStyle); + lv_style_set_pad_all(&fmContStyle, 0); + lv_style_set_width(&fmContStyle, GVAR_VAL_W); + lv_style_set_height(&fmContStyle, GVAR_VAL_H); + lv_style_set_bg_color(&fmContStyle, makeLvColor(COLOR_THEME_PRIMARY2)); + lv_style_set_bg_opa(&fmContStyle, LV_OPA_COVER); + + lv_style_init(&fmContStyleChecked); + lv_style_set_bg_color(&fmContStyleChecked, makeLvColor(COLOR_THEME_SECONDARY3)); + + lv_style_init(&fmLabelStyle); + lv_style_set_height(&fmLabelStyle, PAGE_LINE_HEIGHT - 6); + lv_style_set_width(&fmLabelStyle, GVAR_VAL_W); + lv_style_set_text_font(&fmLabelStyle, getFont(FONT(XS))); + lv_style_set_text_color(&fmLabelStyle, makeLvColor(COLOR_THEME_SECONDARY1)); + lv_style_set_text_align(&fmLabelStyle, LV_TEXT_ALIGN_CENTER); + + lv_style_init(&fmValueStyle); + lv_style_set_height(&fmValueStyle, PAGE_LINE_HEIGHT); + lv_style_set_width(&fmValueStyle, GVAR_VAL_W); + lv_style_set_text_font(&fmValueStyle, getFont(FONT(STD))); + lv_style_set_text_color(&fmValueStyle, makeLvColor(COLOR_THEME_SECONDARY1)); + lv_style_set_text_align(&fmValueStyle, LV_TEXT_ALIGN_CENTER); + + lv_style_init(&fmValueStyleSmall); + lv_style_set_text_font(&fmValueStyleSmall, getFont(FONT(XS))); + lv_style_set_pad_top(&fmValueStyleSmall, 3); + + lv_style_init(&fmNameStyle); + lv_style_set_width(&fmNameStyle, GVAR_NAME_SIZE); + lv_style_set_text_font(&fmNameStyle, getFont(FONT(STD))); + lv_style_set_text_color(&fmNameStyle, makeLvColor(COLOR_THEME_SECONDARY1)); + lv_style_set_text_align(&fmNameStyle, LV_TEXT_ALIGN_LEFT); + lv_style_set_pad_left(&fmNameStyle, 2); + } + } + + void setContStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmContStyle, LV_PART_MAIN); + lv_obj_add_style(obj, &fmContStyleChecked, LV_PART_MAIN|LV_STATE_CHECKED); + } + + void setLabelStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmLabelStyle, LV_PART_MAIN); + } + + void setValueStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmValueStyle, LV_PART_MAIN); + lv_obj_add_style(obj, &fmValueStyleSmall, LV_PART_MAIN|LV_STATE_USER_1); + } + + void setNameStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmNameStyle, LV_PART_MAIN); + } + + private: + lv_style_t fmNameStyle; + lv_style_t fmContStyle; + lv_style_t fmContStyleChecked; + lv_style_t fmLabelStyle; + lv_style_t fmValueStyle; + lv_style_t fmValueStyleSmall; + bool styleInitDone; +}; + +static GVarStyle gvarStyle; + class GVarButton : public Button { public: - GVarButton(FormGroup* parent, const rect_t& rect, uint8_t gvar) : + GVarButton(Window* parent, const rect_t& rect, uint8_t gvar) : Button(parent, rect, nullptr, 0, 0, input_mix_line_create), gvarIdx(gvar) { - setHeight(LV_SIZE_CONTENT); - setWidth(LV_PCT(100)); + setHeight(BTN_H); + lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_ROW); + lv_obj_set_style_pad_all(lvobj, 0, LV_PART_MAIN); + lv_obj_set_flex_align(lvobj, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_AROUND); - build(); + lv_obj_add_event_cb(lvobj, GVarButton::on_draw, + LV_EVENT_DRAW_MAIN_BEGIN, nullptr); + } + + static void on_draw(lv_event_t* e) + { + lv_obj_t* target = lv_event_get_target(e); + auto line = (GVarButton*)lv_obj_get_user_data(target); + if (line) + line->build(); + + if (e) { + auto param = lv_event_get_param(e); + lv_event_send(line->getLvObj(), LV_EVENT_DRAW_MAIN, param); + } } protected: void checkEvents() { Button::checkEvents(); - uint8_t newFM = getFlightMode(); - if (currentFlightMode != newFM) { - uint8_t lastFM = currentFlightMode; - currentFlightMode = newFM; + if (init) { + uint8_t newFM = getFlightMode(); + if (currentFlightMode != newFM) { + lv_obj_add_state(fmCont[newFM], LV_STATE_CHECKED); + lv_obj_clear_state(fmCont[currentFlightMode], LV_STATE_CHECKED); - labels[lastFM]->setBackgroundColor(COLOR_THEME_PRIMARY2); - labels[currentFlightMode]->setBackgroundColor(COLOR_THEME_SECONDARY3); - updateValueText(lastFM); - updateValueText(currentFlightMode); - } - for (int flightMode = 0; flightMode < MAX_FLIGHT_MODES; flightMode++) { - FlightModeData* fmData = &g_model.flightModeData[flightMode]; - if (values[flightMode] != fmData->gvars[gvarIdx]) { - updateValueText(flightMode); + currentFlightMode = newFM; + } + for (int flightMode = 0; flightMode < MAX_FLIGHT_MODES; flightMode++) { + FlightModeData* fmData = &g_model.flightModeData[flightMode]; + if (values[flightMode] != fmData->gvars[gvarIdx]) { + updateValueText(flightMode); + } } } } protected: + bool init = false; uint8_t gvarIdx; - int lines; - int32_t gvarSum = 0; // used for invalidation uint8_t currentFlightMode = 0; // used for invalidation - StaticText* labels[MAX_FLIGHT_MODES]; - StaticText* valueTexts[MAX_FLIGHT_MODES]; + lv_obj_t* fmCont[MAX_FLIGHT_MODES]; + lv_obj_t* valueTexts[MAX_FLIGHT_MODES]; gvar_t values[MAX_FLIGHT_MODES]; void build() { - lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_ROW); - lv_obj_set_style_pad_all(lvobj, 0, LV_PART_MAIN); + if (init) return; - auto t = - new StaticText(this, rect_t{0, 0, GVAR_NAME_SIZE, PAGE_LINE_HEIGHT}, - getGVarString(gvarIdx), 0, COLOR_THEME_SECONDARY1); - t->padLeft(1); - t->padTop(GVAR_TTL_OFST); + currentFlightMode = getFlightMode(); - Window* container = new Window(this, rect_t{}); - lv_obj_set_style_pad_all(container->getLvObj(), 0, LV_PART_MAIN); - lv_obj_set_style_flex_grow(container->getLvObj(), 2, LV_PART_MAIN); - lv_obj_set_height(container->getLvObj(), LV_SIZE_CONTENT); - lv_obj_set_flex_flow(container->getLvObj(), LV_FLEX_FLOW_ROW_WRAP); + lv_obj_enable_style_refresh(false); + + auto lbl = lv_label_create(lvobj); + gvarStyle.setNameStyle(lbl); + lv_label_set_text(lbl, getGVarString(gvarIdx)); + + lv_obj_t* container = lv_obj_create(lvobj); + lv_obj_set_width(container, GVAR_VAL_W * GVAR_COLS); + lv_obj_set_height(container, GVAR_H); + lv_obj_set_style_pad_all(container, 0, LV_PART_MAIN); + lv_obj_add_flag(container, LV_OBJ_FLAG_EVENT_BUBBLE); for (int flightMode = 0; flightMode < MAX_FLIGHT_MODES; flightMode++) { - Window* fmCont = new Window(container, rect_t{}); - fmCont->padAll(0); - - lv_obj_set_width(fmCont->getLvObj(), GVAR_VAL_SIZE); - lv_obj_set_height(fmCont->getLvObj(), PAGE_LINE_HEIGHT * 2 - 6); - lv_obj_set_flex_flow(fmCont->getLvObj(), LV_FLEX_FLOW_COLUMN); + fmCont[flightMode] = lv_obj_create(container); + gvarStyle.setContStyle(fmCont[flightMode]); + lv_obj_set_pos(fmCont[flightMode], (flightMode%GVAR_COLS)*GVAR_VAL_W, (flightMode/GVAR_COLS)*GVAR_VAL_H); + lv_obj_set_user_data(fmCont[flightMode], this); + lv_obj_add_flag(fmCont[flightMode], LV_OBJ_FLAG_EVENT_BUBBLE); + if (flightMode == currentFlightMode) { + lv_obj_add_state(fmCont[flightMode], LV_STATE_CHECKED); + } char label[16] = {}; getFlightModeString(label, flightMode + 1); - labels[flightMode] = new StaticText(fmCont, rect_t{}, label, 0, - COLOR_THEME_SECONDARY1 | CENTERED); - labels[flightMode]->setHeight(PAGE_LINE_HEIGHT - 6); - labels[flightMode]->setWidth(GVAR_VAL_SIZE); - labels[flightMode]->setFont(FONT(XS)); - labels[flightMode]->setBackgroundColor(COLOR_THEME_PRIMARY2); - labels[flightMode]->setBackgroudOpacity(LV_OPA_COVER); + lbl = lv_label_create(fmCont[flightMode]); + gvarStyle.setLabelStyle(lbl); + lv_label_set_text(lbl, label); + lv_obj_set_pos(lbl, 0, 0); - valueTexts[flightMode] = new StaticText( - fmCont, rect_t{}, "", 0, COLOR_THEME_SECONDARY1 | CENTERED); - StaticText* valText = valueTexts[flightMode]; - if (flightMode == currentFlightMode) { - labels[flightMode]->setBackgroundColor(COLOR_THEME_SECONDARY3); - } - - lv_obj_set_style_flex_track_place(valText->getLvObj(), LV_FLEX_ALIGN_END, - LV_PART_MAIN); - valText->setWidth(GVAR_VAL_SIZE); - valText->setBackgroundColor(COLOR_THEME_PRIMARY2); - valText->setBackgroudOpacity(LV_OPA_COVER); - valText->setHeight(PAGE_LINE_HEIGHT); - valText->setFont(FONT(STD)); + valueTexts[flightMode] = lv_label_create(fmCont[flightMode]); + gvarStyle.setValueStyle(valueTexts[flightMode]); + lv_obj_set_pos(valueTexts[flightMode], 0, PAGE_LINE_HEIGHT - 6); updateValueText(flightMode); } + + lv_obj_enable_style_refresh(true); + + lv_obj_update_layout(lvobj); + + init = true; } void updateValueText(uint8_t flightMode) { - StaticText* field = valueTexts[flightMode]; + lv_obj_t* field = valueTexts[flightMode]; gvar_t value = g_model.flightModeData[flightMode].gvars[gvarIdx]; values[flightMode] = value; @@ -147,28 +246,24 @@ class GVarButton : public Button char label[16] = {}; getFlightModeString(label, fm + 1); - lv_label_set_text(field->getLvObj(), label); + lv_label_set_text(field, label); } else { uint8_t unit = g_model.gvars[gvarIdx].unit; const char* suffix = (unit == 1) ? "%" : ""; uint8_t prec = g_model.gvars[gvarIdx].prec; if (prec) - lv_label_set_text_fmt(field->getLvObj(), "%d.%01u%s", value / 10, + lv_label_set_text_fmt(field, "%d.%01u%s", value / 10, (value < 0) ? (-value) % 10 : value % 10, suffix); else - lv_label_set_text_fmt(field->getLvObj(), "%d%s", value, suffix); + lv_label_set_text_fmt(field, "%d%s", value, suffix); if (unit) { if (value <= -1000 || value >= 1000 || (prec && (value <= -100))) { - field->setFont(FONT(XS)); - } else if (value <= -100) { - field->setFont(FONT(STD)); + lv_obj_add_state(field, LV_STATE_USER_1); + } else { + lv_obj_clear_state(field, LV_STATE_USER_1); } } } - if (flightMode == currentFlightMode) - field->setBackgroundColor(COLOR_THEME_SECONDARY3); - else - field->setBackgroundColor(COLOR_THEME_PRIMARY2); } }; @@ -229,7 +324,6 @@ class GVarEditWindow : public Page int32_t maxValue = GVAR_MAX - gvar->max; const char* suffix = gvar->unit ? "%" : ""; - LcdFlags prec = gvar->prec ? PREC1 : 0; if (min && max) { min->setMax(maxValue); max->setMin(minValue); diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 2a0990c93..9a6378fe8 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 2a0990c932b54cb36fdb95a737fd8aac22688d40 +Subproject commit 9a6378fe8c2af57ab47c25eb93cbd1d76bf15e78