diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index 6a81da9d8..6a39ed74d 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -169,6 +169,7 @@ add_gui_src(switchchoice.cpp) add_gui_src(curveedit.cpp) add_gui_src(input_edit.cpp) add_gui_src(mixer_edit.cpp) +add_gui_src(output_edit.cpp) add_gui_src(input_mix_group.cpp) add_gui_src(input_mix_button.cpp) add_gui_src(lvgl_widgets/input_mix_line.c) diff --git a/radio/src/gui/colorlcd/channel_bar.h b/radio/src/gui/colorlcd/channel_bar.h index 8e915d3e4..2e864e724 100644 --- a/radio/src/gui/colorlcd/channel_bar.h +++ b/radio/src/gui/colorlcd/channel_bar.h @@ -84,7 +84,7 @@ class MixerChannelBar : public ChannelBar divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2), height(), COLOR_THEME_FOCUS); - dc->drawNumber(width() / 2 - 10, 0, displayVal, + dc->drawNumber(width() / 2 - 10, -2, displayVal, FONT(XS) | COLOR_THEME_SECONDARY1 | RIGHT, 0, nullptr, "%"); } else if (chanVal < 0) { @@ -96,7 +96,7 @@ class MixerChannelBar : public ChannelBar dc->drawSolidFilledRect(endpoint - size, 0, size, height(), COLOR_THEME_FOCUS); - dc->drawNumber(10 + width() / 2, 0, displayVal, + dc->drawNumber(10 + width() / 2, -2, displayVal, FONT(XS) | COLOR_THEME_SECONDARY1, 0, nullptr, "%"); } @@ -149,7 +149,7 @@ class OutputChannelBar : public ChannelBar divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2), height(), COLOR_THEME_ACTIVE); - dc->drawNumber(width() / 2 - 10, 0, displayVal, + dc->drawNumber(width() / 2 - 10, -2, displayVal, FONT(XS) | COLOR_THEME_SECONDARY1 | RIGHT, 0, nullptr, "%"); } else if (chanVal < 0) { @@ -160,7 +160,7 @@ class OutputChannelBar : public ChannelBar dc->drawSolidFilledRect(endpoint - size, 0, size, height(), COLOR_THEME_ACTIVE); - dc->drawNumber(width() / 2 + 10, 0, displayVal, + dc->drawNumber(width() / 2 + 10, -2, displayVal, FONT(XS) | COLOR_THEME_SECONDARY1, 0, nullptr, "%"); } diff --git a/radio/src/gui/colorlcd/input_mix_button.cpp b/radio/src/gui/colorlcd/input_mix_button.cpp index baac29058..ba3fd56fd 100644 --- a/radio/src/gui/colorlcd/input_mix_button.cpp +++ b/radio/src/gui/colorlcd/input_mix_button.cpp @@ -42,7 +42,7 @@ void InputMixButton::value_changed(lv_event_t* e) } InputMixButton::InputMixButton(Window* parent, uint8_t index) : - Button(parent, rect_t{}, nullptr, 0, COLOR_THEME_PRIMARY1, + Button(parent, rect_t{}, nullptr, 0, COLOR_THEME_PRIMARY1, input_mix_line_create), index(index) { diff --git a/radio/src/gui/colorlcd/input_mix_group.cpp b/radio/src/gui/colorlcd/input_mix_group.cpp index 2a3057cef..5bd4e7a10 100644 --- a/radio/src/gui/colorlcd/input_mix_group.cpp +++ b/radio/src/gui/colorlcd/input_mix_group.cpp @@ -22,6 +22,8 @@ #include "input_mix_group.h" #include "opentx.h" +#include + static const lv_coord_t col_dsc[] = { LV_DPI_DEF / 2, LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST, }; diff --git a/radio/src/gui/colorlcd/model_inputs.cpp b/radio/src/gui/colorlcd/model_inputs.cpp index fd9145c1b..3ae09cab0 100644 --- a/radio/src/gui/colorlcd/model_inputs.cpp +++ b/radio/src/gui/colorlcd/model_inputs.cpp @@ -29,6 +29,8 @@ #include "input_mix_group.h" #include "input_mix_button.h" +#include + #define SET_DIRTY() storageDirty(EE_MODEL) uint8_t getExposCount() @@ -156,27 +158,26 @@ class InputLineButton : public InputMixButton } // second line ... - y += line_h; - - if (line.swtch) { - dc->drawMask(x, y, mixerSetupSwitchIcon, textColor); - drawSwitch(dc, x + 21, y, line.swtch, textColor); + if (line.swtch || line.curve.value) { + y += line_h; + if (line.swtch) { + dc->drawMask(x, y, mixerSetupSwitchIcon, textColor); + drawSwitch(dc, x + 21, y, line.swtch, textColor); + } + if (line.curve.value != 0) { + dc->drawMask(x + 65, y, mixerSetupCurveIcon, textColor); + drawCurveRef(dc, x + 85, y, line.curve, textColor); + } } - if (line.curve.value != 0) { - dc->drawMask(x + 65, y, mixerSetupCurveIcon, textColor); - drawCurveRef(dc, x + 85, y, line.curve, textColor); - } - -#if LCD_H > LCD_W - // third line ... - y += line_h; - x = left; -#else - x = 146; -#endif - if (line.flightModes) { +#if LCD_H > LCD_W + // third line ... + y += line_h; + x = left; +#else + x = 146; +#endif drawFlightModes(dc, line.flightModes, textColor, x, y); } } diff --git a/radio/src/gui/colorlcd/model_mixes.cpp b/radio/src/gui/colorlcd/model_mixes.cpp index 527dfce4e..44ca9b35f 100644 --- a/radio/src/gui/colorlcd/model_mixes.cpp +++ b/radio/src/gui/colorlcd/model_mixes.cpp @@ -310,27 +310,26 @@ void MixLineButton::paint(BitmapBuffer* dc) } // second line ... - y += line_h; - - if (line.swtch) { - dc->drawMask(x, y, mixerSetupSwitchIcon, textColor); - drawSwitch(dc, x + 21, y, line.swtch, textColor); + if (line.swtch || line.curve.value) { + y += line_h; + if (line.swtch) { + dc->drawMask(x, y, mixerSetupSwitchIcon, textColor); + drawSwitch(dc, x + 21, y, line.swtch, textColor); + } + if (line.curve.value) { + dc->drawMask(x + 65, y, mixerSetupCurveIcon, textColor); + drawCurveRef(dc, x + 85, y, line.curve, textColor); + } } - if (line.curve.value) { - dc->drawMask(x + 65, y, mixerSetupCurveIcon, textColor); - drawCurveRef(dc, x + 85, y, line.curve, textColor); - } - -#if LCD_H > LCD_W - // third line ... - y += line_h; - x = left; -#else - x = 146; -#endif - if (line.flightModes) { +#if LCD_H > LCD_W + // third line ... + y += line_h; + x = left; +#else + x = 146; +#endif drawFlightModes(dc, line.flightModes, textColor, x, y); } } diff --git a/radio/src/gui/colorlcd/model_outputs.cpp b/radio/src/gui/colorlcd/model_outputs.cpp index c480e7f07..432c6aab0 100644 --- a/radio/src/gui/colorlcd/model_outputs.cpp +++ b/radio/src/gui/colorlcd/model_outputs.cpp @@ -20,322 +20,160 @@ */ #include "model_outputs.h" - +#include "output_edit.h" +#include "input_mix_button.h" #include "channel_bar.h" -#include "gvar_numberedit.h" -#include "libopenui.h" + #include "opentx.h" #define SET_DIRTY() storageDirty(EE_MODEL) -#if (LCD_W > LCD_H) - #define OUTPUT_EDIT_STATUS_BAR_WIDTH 250 - #define OUTPUT_EDIT_STATUS_BAR_MARGIN 3 - #define OUTPUT_EDIT_RIGHT_MARGIN 0 +#if LCD_W > LCD_H +static const coord_t btn_cols[] = { + 92, 142, 192, 234, 272, 312 +}; #else - #define OUTPUT_EDIT_STATUS_BAR_WIDTH 180 - #define OUTPUT_EDIT_STATUS_BAR_MARGIN 0 - #define OUTPUT_EDIT_RIGHT_MARGIN 3 +static const coord_t btn_cols[] = { + 102, 162, 222, 268, 222, 268 +}; #endif -class OutputEditStatusBar : public Window +class OutputLineButton : public InputMixButton { public: - OutputEditStatusBar(Window *parent, const rect_t &rect, int8_t channel) : - Window(parent, rect), _channel(channel) + OutputLineButton(Window* parent, uint8_t channel) : + InputMixButton(parent, channel) { - channelBar = new ComboChannelBar(this, {OUTPUT_EDIT_STATUS_BAR_MARGIN, 0, rect.w - (OUTPUT_EDIT_STATUS_BAR_MARGIN * 2), rect.h}, channel); - channelBar->setLeftMargin(0); - channelBar->setTextColor(COLOR_THEME_PRIMARY2); - channelBar->setOutputChannelBarLimitColor(COLOR_THEME_EDIT); - } +#if LCD_H > LCD_W + auto w = (btn_cols[1] - btn_cols[0]) * 2; + auto font_h = getFontHeight(FONT(STD)); - void paint(BitmapBuffer *dc) override - { - // dc->clear(COLOR_THEME_SECONDARY2); - } + auto x = btn_cols[1] - w; + auto y = lv_obj_get_style_text_line_space(lvobj, LV_PART_MAIN) + font_h; - protected: - ComboChannelBar *channelBar; - int8_t _channel; -}; + rect_t r{ x, y + (font_h - 14) / 2, w, 14 }; +#else + lv_obj_update_layout(lvobj); + auto font_h = getFontHeight(FONT(STD)); + auto x = lv_obj_get_content_width(lvobj) - 100; + auto y = (font_h - 14) / 2; -class OutputEditWindow : public Page -{ - public: - explicit OutputEditWindow(uint8_t channel) : - Page(ICON_MODEL_OUTPUTS), channel(channel) - { - chanZero = calcRESXto100(channelOutputs[channel]); - buildBody(&body); - buildHeader(&header); - } - - protected: - uint8_t channel; - int value = 0; - int chanZero = 0; - StaticText *minText; - StaticText *maxText; - OutputEditStatusBar *statusBar = nullptr; - - void checkEvents() override - { - int newValue = channelOutputs[channel]; - if (value != newValue) { - value = newValue; - - int chanVal = calcRESXto100(channelOutputs[channel]); - minText->setBackgroundColor(chanVal < chanZero - 1 ? COLOR_THEME_ACTIVE - : 0U); - minText->invalidate(); - maxText->setBackgroundColor(chanVal > chanZero + 1 ? COLOR_THEME_ACTIVE - : 0U); - maxText->invalidate(); - } - Window::checkEvents(); - } - - void buildHeader(Window *window) - { - new StaticText(window, - {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, - PAGE_LINE_HEIGHT}, - STR_MENULIMITS, 0, COLOR_THEME_PRIMARY2); - new StaticText(window, - {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, - LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, - getSourceString(MIXSRC_CH1 + channel), 0, - COLOR_THEME_PRIMARY2); - - statusBar = new OutputEditStatusBar( - window, {window->getRect().w - OUTPUT_EDIT_STATUS_BAR_WIDTH - OUTPUT_EDIT_RIGHT_MARGIN, 0, OUTPUT_EDIT_STATUS_BAR_WIDTH, MENU_HEADER_HEIGHT + 3}, - channel); - } - - void buildBody(FormWindow *window) - { - FormGridLayout grid; - grid.spacer(8); - - int limit = (g_model.extendedLimits ? LIMIT_EXT_MAX : LIMIT_STD_MAX); - - LimitData *output = limitAddress(channel); - - // Name - new StaticText(window, grid.getLabelSlot(), STR_NAME, 0, - COLOR_THEME_PRIMARY1); - new ModelTextEdit(window, grid.getFieldSlot(), output->name, - sizeof(output->name)); - grid.nextLine(); - - // Offset - new StaticText(window, grid.getLabelSlot(), TR_LIMITS_HEADERS_SUBTRIM, 0, - COLOR_THEME_PRIMARY1); - new GVarNumberEdit(window, grid.getFieldSlot(), -LIMIT_STD_MAX, - +LIMIT_STD_MAX, GET_SET_DEFAULT(output->offset), 0, - PREC1); - grid.nextLine(); - - // TRACE("ch=%d cV=%d zero=%d", channel, chanVal, chanZero); - - // Min - minText = new StaticText(window, grid.getLabelSlot(), TR_MIN, 0, - COLOR_THEME_PRIMARY1); - new GVarNumberEdit(window, grid.getFieldSlot(), -limit, 0, - GET_SET_DEFAULT(output->min), 0, PREC1, -LIMIT_STD_MAX); - grid.nextLine(); - - // Max - maxText = new StaticText(window, grid.getLabelSlot(), TR_MAX, 0, - COLOR_THEME_PRIMARY1); - new GVarNumberEdit(window, grid.getFieldSlot(), 0, +limit, - GET_SET_DEFAULT(output->max), 0, PREC1, +LIMIT_STD_MAX); - grid.nextLine(); - - // Direction - new StaticText(window, grid.getLabelSlot(), STR_INVERTED, 0, - COLOR_THEME_PRIMARY1); - new CheckBox(window, grid.getFieldSlot(), GET_DEFAULT(output->revert), - [output, this](uint8_t newValue) { - if (newValue != output->revert) chanZero = -chanZero; - output->revert = newValue; - SET_DIRTY(); - }); - grid.nextLine(); - - // Curve - new StaticText(window, grid.getLabelSlot(), TR_CURVE, 0, - COLOR_THEME_PRIMARY1); - auto edit = new NumberEdit(window, grid.getFieldSlot(), -MAX_CURVES, - +MAX_CURVES, GET_SET_DEFAULT(output->curve)); - edit->setDisplayHandler( - [](int32_t value) { - return std::string(getCurveString(value)); - }); - grid.nextLine(); - - // PPM center - new StaticText(window, grid.getLabelSlot(), TR_LIMITS_HEADERS_PPMCENTER, 0, - COLOR_THEME_PRIMARY1); - new NumberEdit(window, grid.getFieldSlot(), PPM_CENTER - PPM_CENTER_MAX, - PPM_CENTER + PPM_CENTER_MAX, - GET_VALUE(output->ppmCenter + PPM_CENTER), - SET_VALUE(output->ppmCenter, newValue - PPM_CENTER)); - grid.nextLine(); - - // Subtrims mode - new StaticText(window, grid.getLabelSlot(), TR_LIMITS_HEADERS_SUBTRIMMODE, - 0, COLOR_THEME_PRIMARY1); - new Choice(window, grid.getFieldSlot(), STR_SUBTRIMMODES, 0, 1, - GET_SET_DEFAULT(output->symetrical)); - grid.nextLine(); - - } -}; - -class OutputLineButton : public Button -{ - public: - OutputLineButton(FormGroup *parent, const rect_t &rect, LimitData *output, - int ch) : - Button(parent, rect), output(output), channel(ch) - { - if (output->revert || output->curve || output->name[0]) { - setHeight(height() + PAGE_LINE_HEIGHT + FIELD_PADDING_TOP); - } - chanZero = calcRESXto100(channelOutputs[channel]); + rect_t r{ x, y, 100, 14 }; +#endif + new OutputChannelBar(this, r, channel); } void paint(BitmapBuffer *dc) override { LcdFlags textColor = COLOR_THEME_SECONDARY1; - LcdFlags bgColor = COLOR_THEME_PRIMARY2; - LcdFlags textColorActive = COLOR_THEME_ACTIVE; - LcdFlags textFlag; - int chanVal = calcRESXto100(channelOutputs[channel]); - dc->drawSolidFilledRect(0, 0, width(), height(), bgColor); + const LimitData* output = limitAddress(index); + int chanZero = output->ppmCenter; - // TRACE("ch=%d cV=%d zero=%d", channel, chanVal, chanZero); - // first line + coord_t border = lv_obj_get_style_border_width(lvobj, LV_PART_MAIN); + coord_t pad_left = lv_obj_get_style_pad_left(lvobj, LV_PART_MAIN); + coord_t left = pad_left + border; + // first line ... + coord_t x = left; + coord_t y = border + lv_obj_get_style_pad_top(lvobj, LV_PART_MAIN); + + dc->drawText(x, y, getSourceString(MIXSRC_CH1 + index), FONT(BOLD) | textColor); + // Min - textFlag = (chanVal < chanZero - 1) ? textColorActive : textColor; - drawValueOrGVar(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, output->min, - -GV_RANGELARGE, 0, PREC1 | textFlag, nullptr, - -LIMITS_MIN_MAX_OFFSET); + LcdFlags txtFlags = (value < chanZero - 5) ? FONT(BOLD) | textColor : textColor; + x = left + btn_cols[0]; + drawValueOrGVar(dc, x, y, output->min, -GV_RANGELARGE, 0, RIGHT | PREC1 | txtFlags, + nullptr, -LIMITS_MIN_MAX_OFFSET); // Max - textFlag = (chanVal > chanZero + 1) ? textColorActive : textColor; - drawValueOrGVar(dc, 68, FIELD_PADDING_TOP, output->max, 0, GV_RANGELARGE, - PREC1 | textFlag, nullptr, +LIMITS_MIN_MAX_OFFSET); + txtFlags = (value > chanZero + 5) ? FONT(BOLD) | textColor : textColor; + x = left + btn_cols[1]; + drawValueOrGVar(dc, x, y, output->max, 0, GV_RANGELARGE, + RIGHT | PREC1 | txtFlags, nullptr, +LIMITS_MIN_MAX_OFFSET); // Offset - drawValueOrGVar(dc, 132, FIELD_PADDING_TOP, output->offset, -LIMIT_STD_MAX, - +LIMIT_STD_MAX, PREC1 | textColor, nullptr); + x = left + btn_cols[2]; + drawValueOrGVar(dc, x, y, output->offset, -LIMIT_STD_MAX, + +LIMIT_STD_MAX, RIGHT | PREC1 | textColor, nullptr); // PPM center - dc->drawNumber(226, FIELD_PADDING_TOP, PPM_CENTER + output->ppmCenter, - RIGHT | textColor); - dc->drawText(228, FIELD_PADDING_TOP, output->symetrical ? "=" : "\210", - textColor); - -#if LCD_W > LCD_H - char chval[10]; -// #if defined(PPM_UNIT_US) - snprintf(chval, sizeof(chval), "%d%s", PPM_CH_CENTER(channel) + channelOutputs[channel] / 2, STR_US); -// #else -// snprintf(chval, sizeof(chval), "%d%s", calcRESXto100(channelOutputs[channel]), "%"); -// #endif - dc->drawText(260, FIELD_PADDING_TOP, chval, LEFT | textColor); -#endif + x = left + btn_cols[3]; + dc->drawNumber(x, y, PPM_CENTER + output->ppmCenter, RIGHT | textColor); + dc->drawText(x, y, output->symetrical ? "=" : STR_CHAR_DELTA, textColor); // second line - if (output->revert) { - dc->drawTextAtIndex(4, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, STR_MMMINV, - output->revert, textColor); + if (output->revert || output->curve) { +#if LCD_H > LCD_W + y += lv_obj_get_style_text_line_space(lvobj, LV_PART_MAIN) + + getFontHeight(FONT(STD)); +#endif + if (output->revert) { + x = left + btn_cols[4]; + dc->drawText(x, y, LV_SYMBOL_SHUFFLE, RIGHT | textColor); + } + if (output->curve) { + x = left + btn_cols[5]; + dc->drawText(x, y, getCurveString(output->curve), RIGHT | textColor); + dc->drawMask(x + 2, y, mixerSetupCurveIcon, textColor); + } } - if (output->curve) { - dc->drawMask(68, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, - mixerSetupCurveIcon, textColor); - dc->drawText(88, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, - getCurveString(output->curve), textColor); - } - if (output->name[0]) { - dc->drawMask(146, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, - mixerSetupLabelIcon, textColor); - dc->drawSizedText(166, PAGE_LINE_HEIGHT + FIELD_PADDING_TOP, output->name, - sizeof(output->name), textColor); - } - - // bounding rect - if (hasFocus()) - dc->drawSolidRect(0, 0, rect.w, rect.h, 2, COLOR_THEME_FOCUS); - else - dc->drawSolidRect(0, 0, rect.w, rect.h, 1, COLOR_THEME_SECONDARY2); } protected: + int value = 0; + + bool isActive() const override { return false; } + size_t getLines() const override + { +#if LCD_H > LCD_W + return 2; +#else + return 1; +#endif + } + void checkEvents() override { Window::checkEvents(); - int newValue = channelOutputs[channel]; + int newValue = channelOutputs[index]; if (value != newValue) { value = newValue; invalidate(); } } - LimitData *output; - int channel; - int chanZero; - int value = 0; }; ModelOutputsPage::ModelOutputsPage() : - PageTab(STR_MENULIMITS, ICON_MODEL_OUTPUTS) + PageTab(STR_MENULIMITS, ICON_MODEL_OUTPUTS) { } -void ModelOutputsPage::rebuild(FormWindow *window, int8_t focusChannel) +void ModelOutputsPage::build(FormWindow *window) { - auto scroll_y = lv_obj_get_scroll_y(window->getLvObj()); - window->clear(); - build(window, focusChannel); - lv_obj_scroll_to_y(window->getLvObj(), scroll_y, LV_ANIM_OFF); -} + window->setFlexLayout(LV_FLEX_FLOW_COLUMN, 8); + lv_obj_set_style_pad_all(window->getLvObj(), 8, 0); -void ModelOutputsPage::build(FormWindow *window, int8_t focusChannel) -{ - FormGridLayout grid; - grid.spacer(PAGE_PADDING); - grid.setLabelWidth(66); - - new TextButton( - window, grid.getLineSlot(), STR_ADD_ALL_TRIMS_TO_SUBTRIMS, + auto btn = new TextButton(window, rect_t{}, STR_ADD_ALL_TRIMS_TO_SUBTRIMS, [=]() { - moveTrimsToOffsets(); // if highlighted and menu pressed - move trims - // to offsets - rebuild(window, 0); + moveTrimsToOffsets(); + // TODO: mass invalidate return 0; - }, - 0, COLOR_THEME_PRIMARY1); - grid.nextLine(); + }); + auto btn_obj = btn->getLvObj(); + lv_obj_set_width(btn_obj, lv_pct(100)); for (uint8_t ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) { - LimitData *output = limitAddress(ch); - - // Channel label - auto txt = new StaticText( - window, grid.getLabelSlot(), getSourceString(MIXSRC_CH1 + ch), - BUTTON_BACKGROUND, CENTERED | COLOR_THEME_PRIMARY1); // Channel settings - Button *button = - new OutputLineButton(window, grid.getFieldSlot(), output, ch); - button->setPressHandler([=]() -> uint8_t { + auto btn = new OutputLineButton(window, ch); + + LimitData* output = limitAddress(ch); + btn->setPressHandler([=]() -> uint8_t { Menu *menu = new Menu(window); - menu->addLine(STR_EDIT, [=]() { editOutput(window, ch); }); + menu->addLine(STR_EDIT, [=]() { + editOutput(btn, ch); + }); menu->addLine(STR_RESET, [=]() { output->min = 0; output->max = 0; @@ -345,49 +183,28 @@ void ModelOutputsPage::build(FormWindow *window, int8_t focusChannel) output->curve = 0; output->symetrical = 0; storageDirty(EE_MODEL); - rebuild(window, ch); + btn->invalidate(); }); menu->addLine(STR_COPY_STICKS_TO_OFS, [=]() { copySticksToOffset(ch); storageDirty(EE_MODEL); - button->invalidate(); + btn->invalidate(); }); menu->addLine(STR_COPY_TRIMS_TO_OFS, [=]() { copyTrimsToOffset(ch); storageDirty(EE_MODEL); - button->invalidate(); + btn->invalidate(); }); return 0; }); - button->setFocusHandler([=](bool focus) { - if (focus) { - txt->setBackgroundColor(COLOR_THEME_FOCUS); - txt->setTextFlags(COLOR_THEME_PRIMARY2 | CENTERED); - } else { - txt->setBackgroundColor(COLOR_THEME_SECONDARY2); - txt->setTextFlags(COLOR_THEME_PRIMARY1 | CENTERED); - } - txt->invalidate(); - }); - - // if (focusChannel == ch) { - // button->setFocus(SET_FOCUS_DEFAULT); - // txt->setBackgroundColor(COLOR_THEME_FOCUS); - // txt->setTextFlags(COLOR_THEME_PRIMARY2 | CENTERED); - // txt->invalidate(); - // } - - txt->setHeight(button->height()); - grid.spacer(button->height() + 5); } - - grid.nextLine(); - } -void ModelOutputsPage::editOutput(FormWindow *window, uint8_t channel) +void ModelOutputsPage::editOutput(OutputLineButton *btn, uint8_t channel) { - // Window::clearFocus(); - Window *editWindow = new OutputEditWindow(channel); - editWindow->setCloseHandler([=]() { rebuild(window, channel); }); + // auto btn_obj = btn->getLvObj(); + // Window *edit = + new OutputEditWindow(channel); + // edit->setCloseHandler( + // [=]() { lv_event_send(btn_obj, LV_EVENT_VALUE_CHANGED, nullptr); }); } diff --git a/radio/src/gui/colorlcd/model_outputs.h b/radio/src/gui/colorlcd/model_outputs.h index 05362c185..101f732c6 100644 --- a/radio/src/gui/colorlcd/model_outputs.h +++ b/radio/src/gui/colorlcd/model_outputs.h @@ -24,19 +24,16 @@ #include "tabsgroup.h" -class ModelOutputsPage: public PageTab { - public: - ModelOutputsPage(); +class OutputLineButton; - virtual void build(FormWindow * window) override - { - build(window, 0); - } +class ModelOutputsPage : public PageTab +{ + public: + ModelOutputsPage(); + void build(FormWindow* window) override; - protected: - void build(FormWindow * window, int8_t focusChannel); - void rebuild(FormWindow * window, int8_t focusChannel); - void editOutput(FormWindow * window, uint8_t channel); + protected: + void editOutput(OutputLineButton* btn, uint8_t channel); }; #endif // _MODEL_OUTPUTS_H_ diff --git a/radio/src/gui/colorlcd/output_edit.cpp b/radio/src/gui/colorlcd/output_edit.cpp new file mode 100644 index 000000000..ef5b07ef3 --- /dev/null +++ b/radio/src/gui/colorlcd/output_edit.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "output_edit.h" +#include "channel_bar.h" +#include "gvar_numberedit.h" + +#include "opentx.h" + +#define SET_DIRTY() storageDirty(EE_MODEL) + +#if (LCD_W > LCD_H) + #define OUTPUT_EDIT_STATUS_BAR_WIDTH 250 + #define OUTPUT_EDIT_STATUS_BAR_MARGIN 3 + #define OUTPUT_EDIT_RIGHT_MARGIN 0 +#else + #define OUTPUT_EDIT_STATUS_BAR_WIDTH 180 + #define OUTPUT_EDIT_STATUS_BAR_MARGIN 0 + #define OUTPUT_EDIT_RIGHT_MARGIN 3 +#endif + +class OutputEditStatusBar : public Window +{ + public: + OutputEditStatusBar(Window *parent, const rect_t &rect, int8_t channel) : + Window(parent, rect), _channel(channel) + { + channelBar = new ComboChannelBar(this, {OUTPUT_EDIT_STATUS_BAR_MARGIN, 0, rect.w - (OUTPUT_EDIT_STATUS_BAR_MARGIN * 2), rect.h}, channel); + channelBar->setLeftMargin(0); + channelBar->setTextColor(COLOR_THEME_PRIMARY2); + channelBar->setOutputChannelBarLimitColor(COLOR_THEME_EDIT); + } + + void paint(BitmapBuffer *dc) override + { + // dc->clear(COLOR_THEME_SECONDARY2); + } + + protected: + ComboChannelBar *channelBar; + int8_t _channel; +}; + +OutputEditWindow::OutputEditWindow(uint8_t channel) : + Page(ICON_MODEL_OUTPUTS), channel(channel) +{ + chanZero = calcRESXto100(channelOutputs[channel]); + buildBody(&body); + buildHeader(&header); +} + +void OutputEditWindow::checkEvents() +{ + int newValue = channelOutputs[channel]; + if (value != newValue) { + value = newValue; + + int chanVal = calcRESXto100(channelOutputs[channel]); + minText->setBackgroundColor(chanVal < chanZero - 1 ? COLOR_THEME_ACTIVE + : 0U); + minText->invalidate(); + maxText->setBackgroundColor(chanVal > chanZero + 1 ? COLOR_THEME_ACTIVE + : 0U); + maxText->invalidate(); + } + Window::checkEvents(); +} + +void OutputEditWindow::buildHeader(Window *window) +{ + new StaticText(window, + {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, + PAGE_LINE_HEIGHT}, + STR_MENULIMITS, 0, COLOR_THEME_PRIMARY2); + new StaticText(window, + {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, + LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, + getSourceString(MIXSRC_CH1 + channel), 0, + COLOR_THEME_PRIMARY2); + + statusBar = new OutputEditStatusBar( + window, + {window->getRect().w - OUTPUT_EDIT_STATUS_BAR_WIDTH - + OUTPUT_EDIT_RIGHT_MARGIN, + 0, OUTPUT_EDIT_STATUS_BAR_WIDTH, MENU_HEADER_HEIGHT + 3}, + channel); +} + +void OutputEditWindow::buildBody(FormWindow *window) +{ + FormGridLayout grid; + grid.spacer(8); + + int limit = (g_model.extendedLimits ? LIMIT_EXT_MAX : LIMIT_STD_MAX); + + LimitData *output = limitAddress(channel); + + // Name + new StaticText(window, grid.getLabelSlot(), STR_NAME, 0, + COLOR_THEME_PRIMARY1); + new ModelTextEdit(window, grid.getFieldSlot(), output->name, + sizeof(output->name)); + grid.nextLine(); + + // Offset + new StaticText(window, grid.getLabelSlot(), TR_LIMITS_HEADERS_SUBTRIM, 0, + COLOR_THEME_PRIMARY1); + new GVarNumberEdit(window, grid.getFieldSlot(), -LIMIT_STD_MAX, + +LIMIT_STD_MAX, GET_SET_DEFAULT(output->offset), 0, PREC1); + grid.nextLine(); + + // TRACE("ch=%d cV=%d zero=%d", channel, chanVal, chanZero); + + // Min + minText = new StaticText(window, grid.getLabelSlot(), TR_MIN, 0, + COLOR_THEME_PRIMARY1); + new GVarNumberEdit(window, grid.getFieldSlot(), -limit, 0, + GET_SET_DEFAULT(output->min), 0, PREC1, -LIMIT_STD_MAX); + grid.nextLine(); + + // Max + maxText = new StaticText(window, grid.getLabelSlot(), TR_MAX, 0, + COLOR_THEME_PRIMARY1); + new GVarNumberEdit(window, grid.getFieldSlot(), 0, +limit, + GET_SET_DEFAULT(output->max), 0, PREC1, +LIMIT_STD_MAX); + grid.nextLine(); + + // Direction + new StaticText(window, grid.getLabelSlot(), STR_INVERTED, 0, + COLOR_THEME_PRIMARY1); + new CheckBox(window, grid.getFieldSlot(), GET_DEFAULT(output->revert), + [output, this](uint8_t newValue) { + if (newValue != output->revert) chanZero = -chanZero; + output->revert = newValue; + SET_DIRTY(); + }); + grid.nextLine(); + + // Curve + new StaticText(window, grid.getLabelSlot(), TR_CURVE, 0, + COLOR_THEME_PRIMARY1); + auto edit = new NumberEdit(window, grid.getFieldSlot(), -MAX_CURVES, + +MAX_CURVES, GET_SET_DEFAULT(output->curve)); + edit->setDisplayHandler( + [](int32_t value) { return std::string(getCurveString(value)); }); + grid.nextLine(); + + // PPM center + new StaticText(window, grid.getLabelSlot(), TR_LIMITS_HEADERS_PPMCENTER, 0, + COLOR_THEME_PRIMARY1); + new NumberEdit(window, grid.getFieldSlot(), PPM_CENTER - PPM_CENTER_MAX, + PPM_CENTER + PPM_CENTER_MAX, + GET_VALUE(output->ppmCenter + PPM_CENTER), + SET_VALUE(output->ppmCenter, newValue - PPM_CENTER)); + grid.nextLine(); + + // Subtrims mode + new StaticText(window, grid.getLabelSlot(), TR_LIMITS_HEADERS_SUBTRIMMODE, 0, + COLOR_THEME_PRIMARY1); + new Choice(window, grid.getFieldSlot(), STR_SUBTRIMMODES, 0, 1, + GET_SET_DEFAULT(output->symetrical)); + grid.nextLine(); +} diff --git a/radio/src/gui/colorlcd/output_edit.h b/radio/src/gui/colorlcd/output_edit.h new file mode 100644 index 000000000..ab10ab08f --- /dev/null +++ b/radio/src/gui/colorlcd/output_edit.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) EdgeTX + * + * Based on code named + * opentx - https://github.com/opentx/opentx + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include "page.h" +#include "form.h" +#include "static.h" + +class OutputEditStatusBar; + +class OutputEditWindow : public Page +{ + public: + explicit OutputEditWindow(uint8_t channel); + + protected: + uint8_t channel; + int value = 0; + int chanZero = 0; + StaticText *minText; + StaticText *maxText; + OutputEditStatusBar *statusBar = nullptr; + + void checkEvents() override; + void buildHeader(Window *window); + void buildBody(FormWindow *window); +};