From 46c4095cd249784cac2dd6aedaba514a0a91d05a Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 5 Jun 2022 07:53:18 +0200 Subject: [PATCH] Mixers: add channel bar to mixer groups --- radio/src/gui/colorlcd/CMakeLists.txt | 1 + radio/src/gui/colorlcd/access_settings.cpp | 4 +- radio/src/gui/colorlcd/channel_bar.cpp | 187 +++++++++++++++++ radio/src/gui/colorlcd/channel_bar.h | 225 +++------------------ radio/src/gui/colorlcd/input_mix_group.cpp | 15 ++ radio/src/gui/colorlcd/input_mix_group.h | 2 + radio/src/gui/colorlcd/model_inputs.cpp | 9 +- radio/src/gui/colorlcd/model_inputs.h | 1 + radio/src/gui/colorlcd/model_mixes.cpp | 9 +- radio/src/gui/colorlcd/model_mixes.h | 1 + 10 files changed, 254 insertions(+), 200 deletions(-) create mode 100644 radio/src/gui/colorlcd/channel_bar.cpp diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index 6a39ed74d..b9a0a36a6 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -173,6 +173,7 @@ 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) +add_gui_src(channel_bar.cpp) if(HARDWARE_TOUCH) add_gui_src(keyboard_curve.cpp) diff --git a/radio/src/gui/colorlcd/access_settings.cpp b/radio/src/gui/colorlcd/access_settings.cpp index f48730f70..137dc4d7b 100644 --- a/radio/src/gui/colorlcd/access_settings.cpp +++ b/radio/src/gui/colorlcd/access_settings.cpp @@ -837,9 +837,9 @@ void RxOptions::update() hwSettings.receiverSettings.outputsMapping[i] = val; if (val <= channelsMax) { chBar->setChannel(getShiftedChannel(moduleIdx, val)); - chBar->setEnabled(true); + lv_obj_clear_flag(chBar->getLvObj(), LV_OBJ_FLAG_HIDDEN); } else { - chBar->setEnabled(false); + lv_obj_add_flag(chBar->getLvObj(), LV_OBJ_FLAG_HIDDEN); } }); chDn->setTextHandler( diff --git a/radio/src/gui/colorlcd/channel_bar.cpp b/radio/src/gui/colorlcd/channel_bar.cpp new file mode 100644 index 000000000..bbc6d6569 --- /dev/null +++ b/radio/src/gui/colorlcd/channel_bar.cpp @@ -0,0 +1,187 @@ +/* + * 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 "channel_bar.h" + +#define VIEW_CHANNELS_LIMIT_PCT \ + (g_model.extendedLimits ? LIMIT_EXT_PERCENT : LIMIT_STD_PERCENT) +#define CHANNELS_LIMIT (g_model.extendedLimits ? LIMIT_EXT_MAX : LIMIT_STD_MAX) + +ChannelBar::ChannelBar(Window* parent, const rect_t& rect, uint8_t channel) : + Window(parent, rect), channel(channel) +{ + lv_obj_set_style_bg_color(lvobj, makeLvColor(COLOR_THEME_PRIMARY2), 0); + lv_obj_set_style_bg_opa(lvobj, LV_OPA_COVER, 0); +} + +void MixerChannelBar::paint(BitmapBuffer * dc) +{ + int chanVal = calcRESXto100(ex_chans[channel]); + const int displayVal = chanVal; + + // this could be handled nicer, but slower, by checking actual range for this + // mixer + chanVal = + limit(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT); + + // Draw mixer bar + if (chanVal > 0) { + dc->drawSolidFilledRect( + 0 + width() / 2, 0, + divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2), + height(), COLOR_THEME_FOCUS); + + dc->drawNumber(width() / 2 - 10, -2, displayVal, + FONT(XS) | COLOR_THEME_SECONDARY1 | RIGHT, 0, nullptr, "%"); + + } else if (chanVal < 0) { + const unsigned endpoint = width() / 2; + const unsigned size = + divRoundClosest(-chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2); + + dc->drawSolidFilledRect(endpoint - size, 0, size, height(), + COLOR_THEME_FOCUS); + + dc->drawNumber(10 + width() / 2, -2, displayVal, + FONT(XS) | COLOR_THEME_SECONDARY1, 0, nullptr, "%"); + } + + // Draw middle bar + dc->drawSolidVerticalLine(width() / 2, 0, height(), COLOR_THEME_SECONDARY1); +} + +void MixerChannelBar::checkEvents() +{ + Window::checkEvents(); + int newValue = ex_chans[channel]; + if (value != newValue) { + value = newValue; + invalidate(); + } +} + +static inline unsigned posOnBar(coord_t width, int value_to100) +{ + return divRoundClosest( + (value_to100 + VIEW_CHANNELS_LIMIT_PCT) * (width - 1), + VIEW_CHANNELS_LIMIT_PCT * 2); +} + +static void drawOutputBarLimits(BitmapBuffer* dc, coord_t left, coord_t right, + LcdFlags color) +{ + dc->drawSolidVerticalLine(left, 0, BAR_HEIGHT, color); + dc->drawSolidHorizontalLine(left, 0, 3, color); + dc->drawSolidHorizontalLine(left, BAR_HEIGHT - 1, 3, color); + + dc->drawSolidVerticalLine(right, 0, BAR_HEIGHT, color); + dc->drawSolidHorizontalLine(right - 3, 0, 3, color); + dc->drawSolidHorizontalLine(right - 3, BAR_HEIGHT - 1, 3, color); +} + +void OutputChannelBar::paint(BitmapBuffer* dc) +{ + int chanVal = calcRESXto100(channelOutputs[channel]); + int displayVal = chanVal; + + chanVal = + limit(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT); + + // Draw output bar + if (chanVal > 0) { + dc->drawSolidFilledRect( + width() / 2, 0, + divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2), + height(), COLOR_THEME_ACTIVE); + + dc->drawNumber(width() / 2 - 10, -2, displayVal, + FONT(XS) | COLOR_THEME_SECONDARY1 | RIGHT, 0, nullptr, "%"); + + } else if (chanVal < 0) { + unsigned endpoint = width() / 2; + unsigned size = + divRoundClosest(-chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2); + + dc->drawSolidFilledRect(endpoint - size, 0, size, height(), + COLOR_THEME_ACTIVE); + + dc->drawNumber(width() / 2 + 10, -2, displayVal, + FONT(XS) | COLOR_THEME_SECONDARY1, 0, nullptr, "%"); + } + + // Draw middle bar + dc->drawSolidVerticalLine(width() / 2, 0, height(), COLOR_THEME_SECONDARY1); + + if (drawLimits) { + // Draw output limits bars + int limit = CHANNELS_LIMIT; + LimitData* ld = limitAddress(channel); + int32_t ldMax; + int32_t ldMin; + + if (GV_IS_GV_VALUE(ld->min, -limit, 0)) { + ldMin = limMin; + } else { + ldMin = ld->min; + } + + if (GV_IS_GV_VALUE(ld->max, 0, limit)) { + ldMax = limMax; + } else { + ldMax = ld->max; + } + + if (ld && ld->revert) { + drawOutputBarLimits(dc, posOnBar(width(), -100 - ldMax / 10), + posOnBar(width(), 100 - ldMin / 10), + outputBarLimitsColor); + } else if (ld) { + drawOutputBarLimits(dc, posOnBar(width(), -100 + ldMin / 10), + posOnBar(width(), 100 + ldMax / 10), + outputBarLimitsColor); + } + } +} + +void OutputChannelBar::checkEvents() +{ + Window::checkEvents(); + int newValue = channelOutputs[channel]; + if (value != newValue) { + value = newValue; + invalidate(); + } + int limit = CHANNELS_LIMIT; + LimitData* lim = limitAddress(channel); + + if (GV_IS_GV_VALUE(lim->min, -limit, 0)) { + int ldMin = GET_GVAR_PREC1(lim->min, -limit, 0, mixerCurrentFlightMode) + + LIMIT_STD_MAX; + if (limMin != ldMin) invalidate(); + limMin = ldMin; + } + if (GV_IS_GV_VALUE(lim->max, 0, limit)) { + int ldMax = GET_GVAR_PREC1(lim->max, 0, limit, mixerCurrentFlightMode) - + LIMIT_STD_MAX; + if (limMax != ldMax) invalidate(); + limMax = ldMax; + } +} diff --git a/radio/src/gui/colorlcd/channel_bar.h b/radio/src/gui/colorlcd/channel_bar.h index ee49be659..08067a4dd 100644 --- a/radio/src/gui/colorlcd/channel_bar.h +++ b/radio/src/gui/colorlcd/channel_bar.h @@ -27,20 +27,12 @@ constexpr coord_t ROW_HEIGHT = 42; constexpr coord_t BAR_HEIGHT = 13; -constexpr coord_t COLUMN_SIZE = 200; -constexpr coord_t X_OFFSET = 25; constexpr coord_t LEG_COLORBOX = 15; -#define VIEW_CHANNELS_LIMIT_PCT (g_model.extendedLimits ? LIMIT_EXT_PERCENT : LIMIT_STD_PERCENT) -#define CHANNELS_LIMIT (g_model.extendedLimits ? LIMIT_EXT_MAX : LIMIT_STD_MAX) - class ChannelBar : public Window { public: - ChannelBar(Window* parent, const rect_t& rect, uint8_t channel) : - Window(parent, rect), channel(channel) - { - } + ChannelBar(Window* parent, const rect_t& rect, uint8_t channel); void setChannel(uint8_t ch) { @@ -48,213 +40,57 @@ class ChannelBar : public Window invalidate(); } - void setEnabled(bool en) - { - enabled = en; - } - protected: uint8_t channel = 0; - bool enabled = true; }; class MixerChannelBar : public ChannelBar { - public: - using ChannelBar::ChannelBar; + public: + using ChannelBar::ChannelBar; - void paint(BitmapBuffer * dc) override - { - if (!enabled) return; - - int chanVal = calcRESXto100(ex_chans[channel]); - const int displayVal = chanVal; + void paint(BitmapBuffer* dc) override; + void checkEvents() override; - // this could be handled nicer, but slower, by checking actual range for this mixer - chanVal = limit(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT); - - // Draw Background - dc->drawSolidFilledRect(0, 0, width(), height(), COLOR_THEME_PRIMARY2); - - // Draw mixer bar - if (chanVal > 0) { - - dc->drawSolidFilledRect( - 0 + width() / 2, 0, - divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2), - height(), COLOR_THEME_FOCUS); - - dc->drawNumber(width() / 2 - 10, -2, displayVal, - FONT(XS) | COLOR_THEME_SECONDARY1 | RIGHT, 0, nullptr, "%"); - - } else if (chanVal < 0) { - - const unsigned endpoint = width() / 2; - const unsigned size = - divRoundClosest(-chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2); - - dc->drawSolidFilledRect(endpoint - size, 0, size, height(), - COLOR_THEME_FOCUS); - - dc->drawNumber(10 + width() / 2, -2, displayVal, - FONT(XS) | COLOR_THEME_SECONDARY1, 0, nullptr, "%"); - } - - // Draw middle bar - dc->drawSolidVerticalLine(width() / 2, 0, height(), COLOR_THEME_SECONDARY1); - } - - void checkEvents() override - { - Window::checkEvents(); - int newValue = ex_chans[channel]; - if (value != newValue) { - value = newValue; - invalidate(); - } - } - - protected: - int value = 0; + protected: + int value = 0; }; class OutputChannelBar : public ChannelBar { - public: - using ChannelBar::ChannelBar; + public: + using ChannelBar::ChannelBar; - void setOutputBarLimitColor(uint32_t color) - { - outputBarLimitsColor = color; - } + void setDrawLimits(bool enable) { drawLimits = enable; } + void setOutputBarLimitColor(uint32_t color) { outputBarLimitsColor = color; } - void paint(BitmapBuffer * dc) override - { - if (!enabled) return; - - int chanVal = calcRESXto100(channelOutputs[channel]); - int displayVal = chanVal; + void paint(BitmapBuffer* dc) override; + void checkEvents() override; - chanVal = limit(-VIEW_CHANNELS_LIMIT_PCT, chanVal, - VIEW_CHANNELS_LIMIT_PCT); - - // Draw Background - dc->drawSolidFilledRect(0, 0, width(), height(), COLOR_THEME_PRIMARY2); - - // Draw output bar - if (chanVal > 0) { - - dc->drawSolidFilledRect( - width() / 2, 0, - divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2), - height(), COLOR_THEME_ACTIVE); - - dc->drawNumber(width() / 2 - 10, -2, displayVal, - FONT(XS) | COLOR_THEME_SECONDARY1 | RIGHT, 0, nullptr, "%"); - - } else if (chanVal < 0) { - unsigned endpoint = width() / 2; - unsigned size = - divRoundClosest(-chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2); - - dc->drawSolidFilledRect(endpoint - size, 0, size, height(), - COLOR_THEME_ACTIVE); - - dc->drawNumber(width() / 2 + 10, -2, displayVal, - FONT(XS) | COLOR_THEME_SECONDARY1, 0, nullptr, "%"); - } - - // Draw middle bar - dc->drawSolidVerticalLine(width() / 2, 0, height(), COLOR_THEME_SECONDARY1); - - // Draw output limits bars - int limit = CHANNELS_LIMIT; - LimitData* ld = limitAddress(channel); - int32_t ldMax; - int32_t ldMin; - - if (GV_IS_GV_VALUE(ld->min, -limit, 0)) { - ldMin = limMin; - } else { - ldMin = ld->min; - } - - if (GV_IS_GV_VALUE(ld->max, 0, limit)) { - ldMax = limMax; - } else { - ldMax = ld->max; - } - - if (ld && ld->revert) { - drawOutputBarLimits(dc, posOnBar(-100 - ldMax / 10), - posOnBar(100 - ldMin / 10)); - } else if (ld) { - drawOutputBarLimits(dc, posOnBar(-100 + ldMin / 10), - posOnBar(100 + ldMax / 10)); - } - } - - inline unsigned posOnBar(int value_to100) - { - return divRoundClosest((value_to100 + VIEW_CHANNELS_LIMIT_PCT) * (width() - 1), VIEW_CHANNELS_LIMIT_PCT * 2); - } - - void drawOutputBarLimits(BitmapBuffer * dc, coord_t left, coord_t right) - { - dc->drawSolidVerticalLine(left, 0, BAR_HEIGHT, outputBarLimitsColor); - dc->drawSolidHorizontalLine(left, 0, 3, outputBarLimitsColor); - dc->drawSolidHorizontalLine(left, BAR_HEIGHT - 1, 3, outputBarLimitsColor); - - dc->drawSolidVerticalLine(right, 0, BAR_HEIGHT, outputBarLimitsColor); - dc->drawSolidHorizontalLine(right - 3, 0, 3, outputBarLimitsColor); - dc->drawSolidHorizontalLine(right - 3, BAR_HEIGHT - 1, 3, outputBarLimitsColor); - } - - void checkEvents() override - { - Window::checkEvents(); - int newValue = channelOutputs[channel]; - if (value != newValue) { - value = newValue; - invalidate(); - } - int limit = CHANNELS_LIMIT; - LimitData* lim = limitAddress(channel); - - if (GV_IS_GV_VALUE(lim->min, -limit, 0)) { - int ldMin = - GET_GVAR_PREC1(lim->min, -limit, 0, mixerCurrentFlightMode) - + LIMIT_STD_MAX; - if (limMin != ldMin) invalidate(); - limMin = ldMin; - } - if (GV_IS_GV_VALUE(lim->max, 0, limit)) { - int ldMax = - GET_GVAR_PREC1(lim->max, 0, limit, mixerCurrentFlightMode) - - LIMIT_STD_MAX; - if (limMax != ldMax) invalidate(); - limMax = ldMax; - } - } - - protected: - int value = 0; - int limMax = 0; - int limMin = 0; - uint32_t outputBarLimitsColor = COLOR_THEME_SECONDARY1; + protected: + int value = 0; + int limMax = 0; + int limMin = 0; + bool drawLimits = true; + LcdFlags outputBarLimitsColor = COLOR_THEME_SECONDARY1; }; constexpr coord_t lmargin = 25; -class ComboChannelBar : public ChannelBar +class ComboChannelBar : public Window { public: - using ChannelBar::ChannelBar; + // using ChannelBar::ChannelBar; ComboChannelBar(Window * parent, const rect_t & rect, uint8_t channel): - ChannelBar(parent, rect, channel) + Window(parent, rect), channel(channel) { - outputChannelBar = new OutputChannelBar(this, {leftMargin, BAR_HEIGHT, width() - leftMargin, BAR_HEIGHT}, channel); - new MixerChannelBar(this, {leftMargin, 2 * BAR_HEIGHT + 1, width() - leftMargin, BAR_HEIGHT}, channel); + outputChannelBar = new OutputChannelBar( + this, {leftMargin, BAR_HEIGHT, width() - leftMargin, BAR_HEIGHT}, + channel); + new MixerChannelBar( + this, + {leftMargin, 2 * BAR_HEIGHT + 1, width() - leftMargin, BAR_HEIGHT}, + channel); } void setOutputChannelBarLimitColor(uint32_t color) @@ -277,8 +113,6 @@ class ComboChannelBar : public ChannelBar void paint(BitmapBuffer * dc) override { - if (!enabled) return; - char chanString[] = "CH32 "; int usValue = PPM_CH_CENTER(channel) + channelOutputs[channel] / 2; @@ -324,6 +158,7 @@ class ComboChannelBar : public ChannelBar } protected: + uint8_t channel; OutputChannelBar *outputChannelBar = nullptr; int value = 0; int leftMargin = lmargin; diff --git a/radio/src/gui/colorlcd/input_mix_group.cpp b/radio/src/gui/colorlcd/input_mix_group.cpp index 5bd4e7a10..68d701d6c 100644 --- a/radio/src/gui/colorlcd/input_mix_group.cpp +++ b/radio/src/gui/colorlcd/input_mix_group.cpp @@ -20,6 +20,8 @@ */ #include "input_mix_group.h" +#include "channel_bar.h" + #include "opentx.h" #include @@ -61,9 +63,22 @@ InputMixGroup::InputMixGroup(Window* parent, mixsrc_t idx) : line_container = window_create(box); lv_obj_set_size(line_container, lv_pct(100), LV_SIZE_CONTENT); lv_obj_set_flex_flow(line_container, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_flex_cross_place(line_container, LV_FLEX_ALIGN_END, 0); lv_obj_set_style_pad_row(line_container, lv_dpx(8), LV_PART_MAIN); } +void InputMixGroup::addMixerMonitor(uint8_t channel) +{ + rect_t r{ 0, 0, 100, 14 }; + auto mon = new MixerChannelBar(this, r, channel); + + lv_obj_t* mon_obj = mon->getLvObj(); + lv_obj_set_parent(mon_obj, line_container); + lv_obj_set_style_border_width(mon_obj, lv_dpx(1), 0); + lv_obj_set_style_border_color(mon_obj, makeLvColor(COLOR_THEME_SECONDARY1), 0); + lv_obj_set_style_radius(mon_obj, lv_dpx(8), 0); +} + void InputMixGroup::addLine(Window* line, const uint8_t* symbol) { lines.emplace_back(line, symbol); diff --git a/radio/src/gui/colorlcd/input_mix_group.h b/radio/src/gui/colorlcd/input_mix_group.h index 46b558986..d89777f3c 100644 --- a/radio/src/gui/colorlcd/input_mix_group.h +++ b/radio/src/gui/colorlcd/input_mix_group.h @@ -46,6 +46,8 @@ class InputMixGroup : public Window public: InputMixGroup(Window* parent, mixsrc_t idx); + void addMixerMonitor(uint8_t channel); + mixsrc_t getMixSrc() { return idx; } size_t getLineCount() { return lines.size(); } diff --git a/radio/src/gui/colorlcd/model_inputs.cpp b/radio/src/gui/colorlcd/model_inputs.cpp index 3ae09cab0..5068a74b3 100644 --- a/radio/src/gui/colorlcd/model_inputs.cpp +++ b/radio/src/gui/colorlcd/model_inputs.cpp @@ -264,6 +264,11 @@ void ModelInputsPage::removeLine(InputMixButton* l) } } +InputMixGroup* ModelInputsPage::createGroup(FormGroup* form, mixsrc_t src) +{ + return new InputMixGroup(form, src); +} + InputMixButton* ModelInputsPage::createLineButton(InputMixGroup *group, uint8_t index) { @@ -333,7 +338,7 @@ void ModelInputsPage::addLineButton(mixsrc_t src, uint8_t index) { InputMixGroup* group_w = getGroupBySrc(src); if (!group_w) { - group_w = new InputMixGroup(form, src); + group_w = createGroup(form, src); // insertion sort groups.emplace_back(group_w); auto g = groups.rbegin(); @@ -478,7 +483,7 @@ void ModelInputsPage::build(FormWindow *window) if (line->chn == input && EXPO_VALID(line)) { // one group for the complete input channel - auto group = new InputMixGroup(form, MIXSRC_FIRST_INPUT + input); + auto group = createGroup(form, MIXSRC_FIRST_INPUT + input); groups.emplace_back(group); while (index < MAX_EXPOS && line->chn == input && EXPO_VALID(line)) { // one button per input line diff --git a/radio/src/gui/colorlcd/model_inputs.h b/radio/src/gui/colorlcd/model_inputs.h index d630392db..1e052dbec 100644 --- a/radio/src/gui/colorlcd/model_inputs.h +++ b/radio/src/gui/colorlcd/model_inputs.h @@ -49,6 +49,7 @@ class ModelInputsPage : public PageTab virtual void addLineButton(uint8_t index); virtual void addLineButton(mixsrc_t src, uint8_t index); + virtual InputMixGroup* createGroup(FormGroup* form, mixsrc_t src); virtual InputMixButton* createLineButton(InputMixGroup *group, uint8_t index); void editInput(uint8_t input, uint8_t index); diff --git a/radio/src/gui/colorlcd/model_mixes.cpp b/radio/src/gui/colorlcd/model_mixes.cpp index 6e144bfd8..7a2eb8e50 100644 --- a/radio/src/gui/colorlcd/model_mixes.cpp +++ b/radio/src/gui/colorlcd/model_mixes.cpp @@ -355,6 +355,13 @@ InputMixGroup* ModelMixesPage::getGroupByIndex(uint8_t index) return getGroupBySrc(MIXSRC_CH1 + ch); } +InputMixGroup* ModelMixesPage::createGroup(FormGroup* form, mixsrc_t src) +{ + auto group = new InputMixGroup(form, src); + group->addMixerMonitor(src - MIXSRC_CH1); + return group; +} + InputMixButton* ModelMixesPage::createLineButton(InputMixGroup *group, uint8_t index) { auto button = new MixLineButton(group, index); @@ -555,7 +562,7 @@ void ModelMixesPage::build(FormWindow * window) if (line->destCh == ch && !skip_mix) { // one group for the complete mixer channel - auto group = new InputMixGroup(form, MIXSRC_CH1 + ch); + auto group = createGroup(form, MIXSRC_CH1 + ch); groups.emplace_back(group); while (index < MAX_MIXERS && (line->destCh == ch) && !skip_mix) { // one button per input line diff --git a/radio/src/gui/colorlcd/model_mixes.h b/radio/src/gui/colorlcd/model_mixes.h index 300a70ecb..8107948e6 100644 --- a/radio/src/gui/colorlcd/model_mixes.h +++ b/radio/src/gui/colorlcd/model_mixes.h @@ -36,6 +36,7 @@ class ModelMixesPage : public ModelInputsPage void addLineButton(uint8_t index) override; void addLineButton(mixsrc_t src, uint8_t index) override; + InputMixGroup* createGroup(FormGroup* form, mixsrc_t src) override; InputMixButton* createLineButton(InputMixGroup* group, uint8_t index) override;