diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp index 3ae4ad902..8962e20c5 100644 --- a/companion/src/firmwares/opentx/opentxinterface.cpp +++ b/companion/src/firmwares/opentx/opentxinterface.cpp @@ -575,9 +575,9 @@ int OpenTxFirmware::getCapability(::Capability capability) case ExtraInputs: return 1; case TrimsRange: - return 125; + return 128; case ExtendedTrimsRange: - return 500; + return 512; case Simulation: return 1; case NumCurves: diff --git a/radio/src/gui/colorlcd/model_flightmodes.cpp b/radio/src/gui/colorlcd/model_flightmodes.cpp index da8894897..4e6a29828 100644 --- a/radio/src/gui/colorlcd/model_flightmodes.cpp +++ b/radio/src/gui/colorlcd/model_flightmodes.cpp @@ -22,309 +22,518 @@ #include "model_flightmodes.h" #include "opentx.h" #include "libopenui.h" +#include "lvgl_widgets/input_mix_line.h" #define SET_DIRTY() storageDirty(EE_MODEL) -#define LABEL_RIGHT_MARGIN 5 - -bool isTrimModeAvailable(int mode) +static std::string getFMTrimStr(uint8_t mode, bool spacer) { - return (mode < 0 || (mode%2) == 0 || (mode/2) != 0); //ToDo menuVerticalPosition + mode &= 0x1F; + if (mode == TRIM_MODE_NONE) + return "-"; + std::string str((mode & 1) ? "+" : "="); + if (spacer) str += " "; + mode >>= 1; + if (mode > MAX_FLIGHT_MODES - 1) + mode = MAX_FLIGHT_MODES - 1; + str += '0'+ mode; + return str; } -struct FlightModeEdit : public Page { - FlightModeEdit(uint8_t index); -}; - static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; -// static const lv_coord_t trims_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), -// LV_GRID_TEMPLATE_LAST}; +#if LCD_W > LCD_H +#define TRIMS_PER_LINE 2 +static const lv_coord_t trims_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), + LV_GRID_TEMPLATE_LAST}; +#else +#define TRIMS_PER_LINE 1 +static const lv_coord_t trims_col_dsc[] = {LV_GRID_FR(1), + LV_GRID_TEMPLATE_LAST}; +#endif -static const lv_coord_t trims_row_dsc[] = {LV_GRID_CONTENT, - LV_GRID_CONTENT, - LV_GRID_CONTENT, - LV_GRID_TEMPLATE_LAST}; - -static void btn_changed(lv_event_t* e) +class FlightModeEdit : public Page { - auto target = lv_event_get_target(e); - auto btn = (Button*)lv_obj_get_user_data(target); - auto obj = (lv_obj_t*)lv_event_get_user_data(e); + public: + FlightModeEdit(uint8_t index) : + Page(ICON_MODEL_FLIGHT_MODES), + index(index) + { + std::string title2 = std::string(STR_FM) + std::to_string(index); + header.setTitle(STR_MENUFLIGHTMODES); + header.setTitle2(title2); - if (!btn->checked()) { - lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN); - } else { - lv_obj_clear_flag(obj, LV_OBJ_FLAG_HIDDEN); - lv_event_send(obj, LV_EVENT_VALUE_CHANGED, nullptr); - } -} + body.padAll(lv_dpx(8)); + lv_obj_set_scrollbar_mode(body.getLvObj(), LV_SCROLLBAR_MODE_AUTO); -static void make_conditional(Window* w, Button* btn) -{ - lv_obj_t* w_obj = w->getLvObj(); - if (!btn->checked()) { lv_obj_add_flag(w_obj, LV_OBJ_FLAG_HIDDEN); } + FlexGridLayout grid(line_col_dsc, line_row_dsc, 2); + auto form = new FormWindow(&body, rect_t{}); + form->setFlexLayout(); - lv_obj_t* btn_obj = btn->getLvObj(); - lv_obj_add_event_cb(btn_obj, btn_changed, LV_EVENT_CLICKED, w_obj); -} + FlightModeData* p_fm = &g_model.flightModeData[index]; + + // Flight mode name + auto line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_NAME, 0, COLOR_THEME_PRIMARY1); + new ModelTextEdit(line, rect_t{}, p_fm->name, LEN_FLIGHT_MODE_NAME); -static std::string getFMTrimStr(uint8_t mode) -{ - char str[4]; + if (index > 0) { + // Switch + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_SWITCH, 0, COLOR_THEME_PRIMARY1); + new SwitchChoice(line, rect_t{}, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, + GET_SET_DEFAULT(p_fm->swtch)); + } - mode &= 0x1F; + // Fade in + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_FADEIN, 0, COLOR_THEME_PRIMARY1); + new NumberEdit(line, rect_t{}, 0, DELAY_MAX, GET_DEFAULT(p_fm->fadeIn), + SET_VALUE(p_fm->fadeIn, newValue), 0, PREC1); - if (mode & 1) str[0] = '+'; - else str[0] = '='; - str[1] = ' '; + // Fade out + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_FADEOUT, 0, COLOR_THEME_PRIMARY1); + new NumberEdit(line, rect_t{}, 0, DELAY_MAX, GET_DEFAULT(p_fm->fadeOut), + SET_VALUE(p_fm->fadeOut, newValue), 0, PREC1); - mode >>= 1; - if (mode > MAX_FLIGHT_MODES - 1) mode = MAX_FLIGHT_MODES - 1; - str[2] = '0' + mode; - str[3] = '\0'; + // Trims + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_TRIMS, 0, COLOR_THEME_PRIMARY1); - return str; -} + FlexGridLayout trim_grid(trims_col_dsc, line_row_dsc); -struct FMTrimSettings : public Dialog { - FMTrimSettings(Window* parent, FlightModeData* p_fm) : - Dialog(parent->getFullScreenWindow(), STR_TRIMS, rect_t{}) - { - setCloseWhenClickOutside(true); - auto form = &content->form; + for (int t = 0; t < NUM_TRIMS; t++) { + lastTrim[t] = p_fm->trim[t].value; - FlexGridLayout trim_grid(line_col_dsc, trims_row_dsc); - auto line = form->newLine(&trim_grid); + if ((t % TRIMS_PER_LINE) == 0) { + line = form->newLine(&trim_grid); + line->padLeft(10); + } - for (int t = 0; t < NUM_TRIMS; t++) { + auto trim = new FormGroup(line, rect_t{}); + trim->setFlexLayout(LV_FLEX_FLOW_ROW, lv_dpx(8)); - auto trim = new FormGroup(line, rect_t{}); - trim->setFlexLayout(LV_FLEX_FLOW_ROW, lv_dpx(8)); + auto trim_obj = trim->getLvObj(); + lv_obj_set_style_pad_column(trim_obj, lv_dpx(8), 0); + lv_obj_set_style_flex_cross_place(trim_obj, LV_FLEX_ALIGN_CENTER, 0); + lv_obj_set_style_grid_cell_x_align(trim_obj, LV_GRID_ALIGN_STRETCH, 0); - auto trim_obj = trim->getLvObj(); - lv_obj_set_style_pad_column(trim_obj, lv_dpx(8), 0); - lv_obj_set_style_flex_cross_place(trim_obj, LV_FLEX_ALIGN_CENTER, 0); - lv_obj_set_style_grid_cell_x_align(trim_obj, LV_GRID_ALIGN_STRETCH, 0); - - trim_t* tr = &p_fm->trim[t]; - auto btn = new TextButton( - trim, rect_t{}, getSourceString(MIXSRC_FIRST_TRIM + t), - [=]() { - if (tr->mode == TRIM_MODE_NONE) { - tr->mode = 0; + trim_t* tr = &p_fm->trim[t]; + auto tr_btn = new TextButton( + trim, rect_t{}, getSourceString(MIXSRC_FIRST_TRIM + t), + [=]() { + tr->mode = (tr->mode == TRIM_MODE_NONE) ? 0 : TRIM_MODE_NONE; + tr_mode[t]->setValue(tr->mode); SET_DIRTY(); - return 1; - } else { - tr->mode = TRIM_MODE_NONE; - SET_DIRTY(); - return 0; - } - }); + showControls(t, tr->mode); + return tr->mode == 0; + }); - if (tr->mode != TRIM_MODE_NONE) btn->check(); - btn->setWidth(LV_DPI_DEF / 2); - btn->setHeight(LV_DPI_DEF / 4); + if (tr->mode != TRIM_MODE_NONE) tr_btn->check(); + tr_btn->setWidth(LV_DPI_DEF / 2); + tr_btn->setHeight(33); - auto tr_mode = new Choice(trim, rect_t{}, 0, 2 * MAX_FLIGHT_MODES - 1, - GET_SET_DEFAULT(tr->mode)); - tr_mode->setTextHandler(getFMTrimStr); + tr_mode[t] = new Choice(trim, rect_t{}, 0, 2 * MAX_FLIGHT_MODES - 1, + GET_DEFAULT(tr->mode), + [=](int val) { + tr->mode = val; + showControls(t, tr->mode); + }); + tr_mode[t]->setTextHandler([=](uint8_t mode) { return getFMTrimStr(mode, true); }); + tr_mode[t]->setAvailableHandler([=](int mode) { + return ((mode & 1) == 0) || ((mode >> 1) != index); + }); - // show trim value choice iff btn->checked() - make_conditional(tr_mode, btn); + tr_value[t] = new NumberEdit(trim, rect_t{}, + g_model.extendedTrims ? -512 : -128, g_model.extendedTrims ? 512 : 128, + GET_SET_DEFAULT(tr->value)); + + // show trim value choice iff btn->checked() + showControls(t, tr->mode); + } } - content->setWidth(LCD_W * 0.8); - content->updateSize(); - } + void checkEvents() override + { + for (int i = 0; i < NUM_TRIMS; i += 1) { + const auto& fm = g_model.flightModeData[index]; + if (lastTrim[i] != fm.trim[i].value) { + lastTrim[i] = fm.trim[i].value; + tr_value[i]->setValue(lastTrim[i]); + } + } + } + + protected: + uint8_t index; + Choice* tr_mode[NUM_TRIMS] = {nullptr}; + NumberEdit* tr_value[NUM_TRIMS] = {nullptr}; + int lastTrim[NUM_TRIMS]; + + void showControls(int trim, uint8_t mode) + { + bool checked = (mode != TRIM_MODE_NONE); + bool showValue = (index == 0) || ((mode & 1) || (mode >> 1 == index)); + + if (checked && (index > 0)) { + lv_obj_clear_flag(tr_mode[trim]->getLvObj(), LV_OBJ_FLAG_HIDDEN); + } else { + lv_obj_add_flag(tr_mode[trim]->getLvObj(), LV_OBJ_FLAG_HIDDEN); + } + if (checked && showValue) { + lv_obj_clear_flag(tr_value[trim]->getLvObj(), LV_OBJ_FLAG_HIDDEN); + } else { + lv_obj_add_flag(tr_value[trim]->getLvObj(), LV_OBJ_FLAG_HIDDEN); + } + } }; -FlightModeEdit::FlightModeEdit(uint8_t index) : - Page(ICON_MODEL_FLIGHT_MODES) +#if LCD_W > LCD_H // Landscape + +#define BTN_H 36 +#define TRIM_W 30 +#define FMID_W 36 +#define NAME_W 95 +#define SWTCH_W 50 +#define FADE_W 45 +#define TRIMC_W 180 +#define FMID_TOP 6 +#define LBL_TOP 6 + +#else // Portrait + +#define BTN_H 58 +#define TRIM_W 40 +#define FMID_W 46 +#define NAME_W 160 +#define SWTCH_W 50 +#define FADE_W 45 +#define TRIMC_W 160 +#define FMID_TOP 24 +#define LBL_TOP 0 + +#endif + +class FMStyle { - std::string title2 = std::string(STR_FM) + std::to_string(index); - header.setTitle(STR_MENUFLIGHTMODES); - header.setTitle2(title2); + public: + FMStyle() {} - FlexGridLayout grid(line_col_dsc, line_row_dsc, 2); - auto form = new FormWindow(&body, rect_t{}); - form->setFlexLayout(); + void init() + { + if(!styleInitDone) + { + styleInitDone=true; - FlightModeData* p_fm = &g_model.flightModeData[index]; - - // Flight mode name - auto line = form->newLine(&grid); - new StaticText(line, rect_t{}, STR_NAME, 0, COLOR_THEME_PRIMARY1); - new ModelTextEdit(line, rect_t{}, p_fm->name, LEN_FLIGHT_MODE_NAME); + lv_style_init(&fmTrimContStyle); + lv_style_set_pad_all(&fmTrimContStyle, 0); + lv_style_set_width(&fmTrimContStyle, TRIMC_W); + lv_style_set_height(&fmTrimContStyle, 32); - if (index > 0) { - // Switch - line = form->newLine(&grid); - new StaticText(line, rect_t{}, STR_SWITCH, 0, COLOR_THEME_PRIMARY1); - new SwitchChoice(line, rect_t{}, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, - GET_SET_DEFAULT(p_fm->swtch)); - } + lv_style_init(&fmIdStyle); + lv_style_set_text_font(&fmIdStyle, getFont(FONT(STD))); + lv_style_set_text_color(&fmIdStyle, makeLvColor(COLOR_THEME_SECONDARY1)); + lv_style_set_text_align(&fmIdStyle, LV_TEXT_ALIGN_LEFT); + lv_style_set_width(&fmIdStyle, FMID_W); + lv_style_set_pad_left(&fmIdStyle, 2); - // Fade in - line = form->newLine(&grid); - new StaticText(line, rect_t{}, STR_FADEIN, 0, COLOR_THEME_PRIMARY1); - new NumberEdit(line, rect_t{}, 0, DELAY_MAX, GET_DEFAULT(p_fm->fadeIn), - SET_VALUE(p_fm->fadeIn, newValue), 0, PREC1); + lv_style_init(&fmNameStyle); + lv_style_set_text_font(&fmNameStyle, getFont(FONT(XS))); + lv_style_set_text_color(&fmNameStyle, makeLvColor(COLOR_THEME_SECONDARY1)); + lv_style_set_text_align(&fmNameStyle, LV_TEXT_ALIGN_LEFT); + lv_style_set_width(&fmNameStyle, NAME_W); - // Fade out - line = form->newLine(&grid); - new StaticText(line, rect_t{}, STR_FADEOUT, 0, COLOR_THEME_PRIMARY1); - new NumberEdit(line, rect_t{}, 0, DELAY_MAX, GET_DEFAULT(p_fm->fadeOut), - SET_VALUE(p_fm->fadeOut, newValue), 0, PREC1); + lv_style_init(&fmSwitchStyle); + lv_style_set_text_font(&fmSwitchStyle, getFont(FONT(STD))); + lv_style_set_text_color(&fmSwitchStyle, makeLvColor(COLOR_THEME_SECONDARY1)); + lv_style_set_text_align(&fmSwitchStyle, LV_TEXT_ALIGN_LEFT); + lv_style_set_width(&fmSwitchStyle, SWTCH_W); - // Trims - line = form->newLine(&grid); - new StaticText(line, rect_t{}, STR_TRIMS, 0, COLOR_THEME_PRIMARY1); - new TextButton(line, rect_t{}, STR_SETUP, [=]() { - new FMTrimSettings(this, p_fm); - return 0; - }); -} + lv_style_init(&fmFadeStyle); + lv_style_set_text_font(&fmFadeStyle, getFont(FONT(STD))); + lv_style_set_text_color(&fmFadeStyle, makeLvColor(COLOR_THEME_SECONDARY1)); + lv_style_set_text_align(&fmFadeStyle, LV_TEXT_ALIGN_RIGHT); + lv_style_set_width(&fmFadeStyle, FADE_W); -class FlightModeBtn: public Button -{ - uint8_t index; - bool active = false; + lv_style_init(&fmTrimModeStyle); + lv_style_set_text_font(&fmTrimModeStyle, getFont(FONT(STD))); + lv_style_set_text_color(&fmTrimModeStyle, makeLvColor(COLOR_THEME_SECONDARY1)); + lv_style_set_text_align(&fmTrimModeStyle, LV_TEXT_ALIGN_CENTER); + lv_style_set_width(&fmTrimModeStyle, TRIM_W); + lv_style_set_height(&fmTrimModeStyle, 16); -public: - FlightModeBtn(Window * parent, uint8_t index); - void checkEvents() override; - void paint(BitmapBuffer* dc) override; + fmTrimValueStyle = fmTrimModeStyle; + lv_style_init(&fmTrimValueStyle); + lv_style_set_text_font(&fmTrimValueStyle, getFont(FONT(XS))); + lv_style_set_text_color(&fmTrimValueStyle, makeLvColor(COLOR_THEME_SECONDARY1)); + lv_style_set_text_align(&fmTrimValueStyle, LV_TEXT_ALIGN_CENTER); + lv_style_set_width(&fmTrimValueStyle, TRIM_W); + lv_style_set_height(&fmTrimValueStyle, 16); + } + } - bool isActive() { return active; } - void onPress() override; + void setTrimContStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmTrimContStyle, LV_PART_MAIN); + } + + void setIdStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmIdStyle, LV_PART_MAIN); + } + + void setNameStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmNameStyle, LV_PART_MAIN); + } + + void setSwitchStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmSwitchStyle, LV_PART_MAIN); + } + + void setFadeStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmFadeStyle, LV_PART_MAIN); + } + + void setTrimModeStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmTrimModeStyle, LV_PART_MAIN); + } + + void setTrimValueStyle(lv_obj_t* obj) + { + init(); + lv_obj_add_style(obj, &fmTrimValueStyle, LV_PART_MAIN); + } + + private: + lv_style_t fmTrimContStyle; + lv_style_t fmIdStyle; + lv_style_t fmNameStyle; + lv_style_t fmSwitchStyle; + lv_style_t fmFadeStyle; + lv_style_t fmTrimModeStyle; + lv_style_t fmTrimValueStyle; + bool styleInitDone; }; -static void fm_draw_begin(lv_event_t *e) -{ - auto fmg = (FlightModeBtn*)lv_event_get_user_data(e); - if (!fmg) return; +static FMStyle fmStyle; - lv_obj_draw_part_dsc_t* dsc = lv_event_get_draw_part_dsc(e); - if (fmg->isActive()) { - dsc->rect_dsc->bg_color = makeLvColor(COLOR_THEME_ACTIVE); - } else { - dsc->rect_dsc->bg_color = makeLvColor(COLOR_THEME_PRIMARY2); +class FlightModeBtn : public Button +{ + public: + FlightModeBtn(Window* parent, int index) : + Button(parent, rect_t{}, nullptr, 0, 0, input_mix_line_create), + index(index) + { + padTop(0); + padBottom(0); + padLeft(3); + padRight(6); + setHeight(BTN_H); + lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_ROW); + lv_obj_set_style_pad_all(lvobj, 0, 0); + lv_obj_set_flex_align(lvobj, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_AROUND); + + check(isActive()); + + lv_obj_add_event_cb(lvobj, FlightModeBtn::on_draw, + LV_EVENT_DRAW_MAIN_BEGIN, nullptr); } -} -FlightModeBtn::FlightModeBtn(Window * parent, uint8_t index) : - Button(parent, rect_t{}, nullptr, 0, 0, lv_btn_create), - index(index) -{ - lv_obj_add_flag(lvobj, LV_OBJ_FLAG_CLICKABLE); - lv_obj_set_style_bg_opa(lvobj, LV_OPA_100, 0); - - lv_obj_set_style_grid_cell_x_align(lvobj, LV_GRID_ALIGN_STRETCH, 0); - lv_obj_set_width(lvobj, lv_pct(100)); - lv_obj_set_height(lvobj, LV_DPI_DEF / 3); - - lv_obj_add_event_cb(lvobj, fm_draw_begin, LV_EVENT_DRAW_PART_BEGIN, this); -} - -void FlightModeBtn::checkEvents() -{ - bool newActive = (getFlightMode() == index); - if (newActive != active) { - active = newActive; - invalidate(); + static void on_draw(lv_event_t* e) + { + lv_obj_t* target = lv_event_get_target(e); + auto line = (FlightModeBtn*)lv_obj_get_user_data(target); + if (line) { + if (!line->init) + line->delayed_init(e); + else + line->refresh(); + } } -} -void FlightModeBtn::paint(BitmapBuffer* dc) -{ - coord_t x=8, y=0; + void delayed_init(lv_event_t* e) + { + lv_obj_enable_style_refresh(false); - LcdFlags txt_flags; - if (active) { - txt_flags = FONT(BOLD) | COLOR_THEME_PRIMARY1; - } else { - txt_flags = FONT(STD) | COLOR_THEME_SECONDARY1; + fmID = lv_label_create(lvobj); + fmStyle.setIdStyle(fmID); + + lv_obj_t* container = lv_obj_create(lvobj); + lv_obj_set_flex_flow(container, LV_FLEX_FLOW_ROW_WRAP); + lv_obj_set_style_flex_grow(container, 2, LV_PART_MAIN); + lv_obj_set_style_pad_all(container, 0, LV_PART_MAIN); + lv_obj_set_height(container, LV_SIZE_CONTENT); + lv_obj_set_user_data(container, this); + lv_obj_add_flag(container, LV_OBJ_FLAG_EVENT_BUBBLE); + lv_obj_set_flex_align(container, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_SPACE_AROUND); + + fmName = lv_label_create(container); + fmStyle.setNameStyle(fmName); + + fmSwitch = lv_label_create(container); + fmStyle.setSwitchStyle(fmSwitch); + + lv_obj_t* trims_cont = lv_obj_create(container); + fmStyle.setTrimContStyle(trims_cont); + lv_obj_set_user_data(trims_cont, this); + lv_obj_add_flag(trims_cont, LV_OBJ_FLAG_EVENT_BUBBLE); + + for (int i = 0; i < NUM_TRIMS; i += 1) { + fmTrimMode[i] = lv_label_create(trims_cont); + fmStyle.setTrimModeStyle(fmTrimMode[i]); + lv_obj_set_pos(fmTrimMode[i], i*TRIM_W, 0); + + fmTrimValue[i] = lv_label_create(trims_cont); + fmStyle.setTrimValueStyle(fmTrimValue[i]); + lv_obj_set_pos(fmTrimValue[i], i*TRIM_W, 16); + } + + fmFadeIn = lv_label_create(container); + fmStyle.setFadeStyle(fmFadeIn); + + fmFadeOut = lv_label_create(container); + fmStyle.setFadeStyle(fmFadeOut); + + init = true; + refresh(); + + lv_obj_enable_style_refresh(true); + + lv_obj_update_layout(lvobj); + + if (e) { + auto param = lv_event_get_param(e); + lv_event_send(lvobj, LV_EVENT_DRAW_MAIN, param); + } } - - auto h = lv_obj_get_height(lvobj); - y = (h - getFontHeight(txt_flags)) / 2; - const auto& fm = g_model.flightModeData[index]; - if (fm.name[0] != '\0') { - dc->drawSizedText(x, y, fm.name, sizeof(fm.name), txt_flags); - } else { + bool isActive() const + { + return (getFlightMode() == index); + } + + void checkEvents() override + { + Button::checkEvents(); + check(isActive()); + if (!refreshing && init) { + refreshing = true; + const auto& fm = g_model.flightModeData[index]; + for (int t = 0; t < NUM_TRIMS; t += 1) { + if (lastTrim[t] != fm.trim[t].value) { + lastTrim[t] = fm.trim[t].value; + + uint8_t mode = fm.trim[t].mode; + bool checked = (mode != TRIM_MODE_NONE); + bool showValue = (index == 0) || ((mode & 1) || (mode >> 1 == index)); + + if (checked && showValue) + lv_label_set_text(fmTrimValue[t], formatNumberAsString(fm.trim[t].value).c_str()); + } + } + refreshing = false; + } + } + + void refresh() + { + if (!init) return; + + const auto& fm = g_model.flightModeData[index]; + char label[8]; getFlightModeString(label, index + 1); - dc->drawSizedText(x, y, label, sizeof(label), txt_flags); + lv_label_set_text(fmID, label); + + if (fm.name[0] != '\0') { + lv_label_set_text(fmName, fm.name); + } else { + lv_label_set_text(fmName, ""); + } + + if ((index > 0) && (fm.swtch != SWSRC_NONE)) { + getSwitchPositionName(label, fm.swtch); + lv_label_set_text(fmSwitch, label); + } else { + lv_label_set_text(fmSwitch, ""); + } + + for (int i = 0; i < NUM_TRIMS; i += 1) { + uint8_t mode = fm.trim[i].mode; + bool checked = (mode != TRIM_MODE_NONE); + bool showValue = (index == 0) || ((mode & 1) || (mode >> 1 == index)); + + lv_label_set_text(fmTrimMode[i], getFMTrimStr(mode, false).c_str()); + + if (checked && showValue) + lv_label_set_text(fmTrimValue[i], formatNumberAsString(fm.trim[i].value).c_str()); + else + lv_label_set_text(fmTrimValue[i], ""); + } + + lv_label_set_text(fmFadeIn, formatNumberAsString(fm.fadeIn, PREC1, 0, nullptr, "s").c_str()); + lv_label_set_text(fmFadeOut, formatNumberAsString(fm.fadeOut, PREC1, 0, nullptr, "s").c_str()); } - if ((index > 0) && (fm.swtch != SWSRC_NONE)) { - char sw[8]; - getSwitchPositionName(sw, fm.swtch); + protected: + bool init = false; + bool refreshing = false; + uint8_t index; - x = lv_obj_get_width(lvobj) - 8; - dc->drawSizedText(x, y, sw, sizeof(sw), txt_flags | RIGHT); - } -} - -void FlightModeBtn::onPress() -{ - new FlightModeEdit(index); -} + lv_obj_t* fmID = nullptr; + lv_obj_t* fmName = nullptr; + lv_obj_t* fmSwitch = nullptr; + lv_obj_t* fmTrimMode[NUM_TRIMS] = {nullptr}; + lv_obj_t* fmTrimValue[NUM_TRIMS] = {nullptr}; + lv_obj_t* fmFadeIn = nullptr; + lv_obj_t* fmFadeOut = nullptr; + int lastTrim[NUM_TRIMS]; +}; ModelFlightModesPage::ModelFlightModesPage(): PageTab(STR_MENUFLIGHTMODES, ICON_MODEL_FLIGHT_MODES) { } -#if LCD_W > LCD_H -// FM table: 3 x 3 static const lv_coord_t fmt_col_dsc[] = {LV_GRID_FR(1), - LV_GRID_FR(1), - LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; static const lv_coord_t fmt_row_dsc[] = {LV_GRID_CONTENT, - LV_GRID_CONTENT, - LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; -#else -// FM table: 2 x 5 -static const lv_coord_t fmt_col_dsc[] = {LV_GRID_FR(1), - LV_GRID_FR(1), - LV_GRID_TEMPLATE_LAST}; - -static const lv_coord_t fmt_row_dsc[] = {LV_GRID_CONTENT, - LV_GRID_CONTENT, - LV_GRID_CONTENT, - LV_GRID_CONTENT, - LV_GRID_CONTENT, - LV_GRID_TEMPLATE_LAST}; -#endif void ModelFlightModesPage::build(FormWindow * window) { - window->setFlexLayout(); - window->padRow(lv_dpx(8)); - - lv_obj_t* obj = window->getLvObj(); - lv_obj_set_style_flex_cross_place(obj, LV_FLEX_ALIGN_CENTER, 0); + window->padAll(4); + lv_obj_set_scrollbar_mode(window->getLvObj(), LV_SCROLLBAR_MODE_AUTO); + + FormWindow* form = new FormWindow(window, rect_t{}); + form->setFlexLayout(LV_FLEX_FLOW_COLUMN, 2); + form->padRow(lv_dpx(4)); - FlexGridLayout grid(fmt_col_dsc, fmt_row_dsc, 0); - auto fm_box = window->newLine(&grid); - fm_box->padRow(lv_dpx(2)); - fm_box->padColumn(lv_dpx(2)); - for (int i = 0; i < MAX_FLIGHT_MODES; i++) { - new FlightModeBtn(fm_box, i); + auto btn = new FlightModeBtn(form, i); + btn->setPressHandler([=]() { + new FlightModeEdit(i); + return 0; + }); } - new TextButton(window, rect_t{}, STR_CHECKTRIMS, [&]() -> uint8_t { + trimCheck = new TextButton(form, rect_t{0, 0, lv_pct(100), 40}, STR_CHECKTRIMS, [&]() -> uint8_t { if (trimsCheckTimer) trimsCheckTimer = 0; else @@ -332,3 +541,8 @@ void ModelFlightModesPage::build(FormWindow * window) return trimsCheckTimer; }); } + +void ModelFlightModesPage::checkEvents() +{ + trimCheck->check(trimsCheckTimer > 0); +} diff --git a/radio/src/gui/colorlcd/model_flightmodes.h b/radio/src/gui/colorlcd/model_flightmodes.h index 850aacc31..ba0be499e 100644 --- a/radio/src/gui/colorlcd/model_flightmodes.h +++ b/radio/src/gui/colorlcd/model_flightmodes.h @@ -25,5 +25,10 @@ class ModelFlightModesPage: public PageTab { public: ModelFlightModesPage(); - void build(FormWindow * window); + void checkEvents() override; + + void build(FormWindow * window) override; + + protected: + TextButton* trimCheck = nullptr; }; diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 01bf27b45..a0d0580f5 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -75,7 +75,6 @@ enum SwitchContext int circularIncDec(int current, int inc, int min, int max, IsValueAvailable isValueAvailable=nullptr); int getFirstAvailable(int min, int max, IsValueAvailable isValueAvailable); -bool isTrimModeAvailable(int mode); bool isInputAvailable(int input); bool isSourceAvailableInInputs(int source); bool isThrottleSourceAvailable(int source);