feat(firmware): add a special function to trigger key lock (#7565)
This commit is contained in:
@@ -203,11 +203,11 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
|
||||
case 0:
|
||||
if (sub==k && menuHorizontalPosition < 1 && CFN_SWITCH(cfn) == SWSRC_NONE) {
|
||||
CFN_ACTIVE(cfn) = 0; // Default is disabled
|
||||
drawSwitch(MODEL_SPECIAL_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | INVERS | ((functionsContext->activeSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0));
|
||||
drawSwitch(MODEL_SPECIAL_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | INVERS | (functionsContext->isFunctionSwitchActive(k) ? BOLD : 0));
|
||||
if (active) CHECK_INCDEC_SWITCH(event, CFN_SWITCH(cfn), SWSRC_FIRST, SWSRC_LAST, eeFlags, isSwitchAvailableInCustomFunctions);
|
||||
}
|
||||
else {
|
||||
drawSwitch(MODEL_SPECIAL_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | ((functionsContext->activeSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0));
|
||||
drawSwitch(MODEL_SPECIAL_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | (functionsContext->isFunctionSwitchActive(k) ? BOLD : 0));
|
||||
if (active || AUTOSWITCH_ENTER_LONG()) {
|
||||
if (event == EVT_KEY_LONG(KEY_ENTER))
|
||||
killEvents(event);
|
||||
|
||||
@@ -197,7 +197,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
|
||||
switch (j) {
|
||||
case ITEM_CUSTOM_FUNCTIONS_SWITCH:
|
||||
if(CFN_SWITCH(cfn) == SWSRC_NONE) CFN_ACTIVE(cfn) = 0; // Disable new function by default
|
||||
drawSwitch(MODEL_SPECIAL_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | ((functionsContext->activeSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0));
|
||||
drawSwitch(MODEL_SPECIAL_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | (functionsContext->isFunctionSwitchActive(k) ? BOLD : 0));
|
||||
if (active || AUTOSWITCH_ENTER_LONG()) {
|
||||
if (event == EVT_KEY_LONG(KEY_ENTER))
|
||||
killEvents(event);
|
||||
|
||||
@@ -199,6 +199,9 @@ extern "C" void touchDriverRead(lv_indev_drv_t *drv, lv_indev_data_t *data)
|
||||
// no touch input if special function is used
|
||||
if (isFunctionActive(FUNCTION_DISABLE_TOUCH)) {
|
||||
lv_indev_reset(touchDevice, nullptr);
|
||||
if (st.event != TE_NONE) {
|
||||
POPUP_BUBBLE(STR_TOUCH_DISABLED, 1500, DEFAULT_BUBBLE_WIDTH, DEFAULT_BUBBLE_Y-BUBBLE_HEIGHT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,8 +116,8 @@ static lv_obj_t* bubble_popup_create(lv_obj_t* parent)
|
||||
class BubbleDialog : public Window
|
||||
{
|
||||
public:
|
||||
BubbleDialog(const char* message, int timeout, coord_t width) :
|
||||
Window(MainWindow::instance(), rect_t{(LCD_W - width) / 2, LCD_H - 100, width, 50},
|
||||
BubbleDialog(const char* message, int timeout, coord_t width, coord_t y) :
|
||||
Window(MainWindow::instance(), rect_t{(LCD_W - width) / 2, y, width, BUBBLE_HEIGHT},
|
||||
bubble_popup_create),
|
||||
startTime(lv_tick_get()), timeout(timeout)
|
||||
{
|
||||
@@ -147,7 +147,7 @@ class BubbleDialog : public Window
|
||||
uint32_t timeout;
|
||||
};
|
||||
|
||||
void POPUP_BUBBLE(const char* message, uint32_t timeout, coord_t width)
|
||||
void POPUP_BUBBLE(const char* message, uint32_t timeout, coord_t width, coord_t y)
|
||||
{
|
||||
new BubbleDialog(message, timeout, width);
|
||||
new BubbleDialog(message, timeout, width, y);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <functional>
|
||||
#include "edgetx_types.h"
|
||||
#include "etx_lv_theme.h"
|
||||
#include "hal.h"
|
||||
|
||||
enum WarningType
|
||||
@@ -38,9 +39,13 @@ enum WarningType
|
||||
typedef std::function<void(const char *, const char *, int, int)>
|
||||
ProgressHandler;
|
||||
|
||||
constexpr coord_t DEFAULT_BUBBLE_WIDTH = LCD_W * 3 / 4;
|
||||
constexpr coord_t DEFAULT_BUBBLE_Y = LCD_H * 7 / 10;
|
||||
LAYOUT_VAL_SCALED(BUBBLE_HEIGHT, 50)
|
||||
|
||||
void POPUP_INFORMATION(const char *message);
|
||||
void POPUP_WARNING(const char *message, const char *info = nullptr);
|
||||
bool POPUP_WARNING_ON_UI_TASK(const char *message, const char *info = nullptr);
|
||||
void POPUP_BUBBLE(const char *message, uint32_t timeout, coord_t width = LCD_W - 100);
|
||||
void POPUP_BUBBLE(const char *message, uint32_t timeout, coord_t width = DEFAULT_BUBBLE_WIDTH, coord_t y = DEFAULT_BUBBLE_Y);
|
||||
|
||||
void show_ui_popup();
|
||||
|
||||
@@ -144,7 +144,14 @@ void ViewMain::setCurrentMainView(unsigned viewId)
|
||||
lv_obj_set_tile_id(tile_view, viewId, 0, LV_ANIM_OFF);
|
||||
}
|
||||
|
||||
void setRequestedMainView(uint8_t view) { g_model.view = view; }
|
||||
void setRequestedMainView(uint8_t view)
|
||||
{
|
||||
auto viewMain = ViewMain::instance();
|
||||
if (view < viewMain->getMainViewsCount()) {
|
||||
viewMain->setCurrentMainView(view);
|
||||
saveViewId(view);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewMain::nextMainView()
|
||||
{
|
||||
|
||||
@@ -290,413 +290,426 @@ static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
|
||||
#define PUSH_CS_DURATION_MIN 0 // 0 no duration : as long as switch is true
|
||||
#define PUSH_CS_DURATION_MAX 255 // 25.5s longest duration
|
||||
|
||||
FunctionEditPage::FunctionEditPage(uint8_t index, EdgeTxIcon icon,
|
||||
const char *title, const char *prefix) :
|
||||
Page(icon), index(index)
|
||||
class FunctionEditPage : public Page
|
||||
{
|
||||
buildHeader(header, title, prefix);
|
||||
|
||||
delayLoad();
|
||||
}
|
||||
|
||||
void FunctionEditPage::delayedInit()
|
||||
{
|
||||
buildBody(body);
|
||||
}
|
||||
|
||||
void FunctionEditPage::checkEvents()
|
||||
{
|
||||
Page::checkEvents();
|
||||
if (active != isActive()) {
|
||||
if (isActive()) {
|
||||
lv_obj_add_state(headerSF->getLvObj(), ETX_STATE_SF_ACTIVE);
|
||||
} else {
|
||||
lv_obj_clear_state(headerSF->getLvObj(), ETX_STATE_SF_ACTIVE);
|
||||
}
|
||||
active = isActive();
|
||||
public:
|
||||
FunctionEditPage(uint8_t index, EdgeTxIcon icon, const char *title,
|
||||
const char *prefix) : Page(icon), index(index)
|
||||
{
|
||||
buildHeader(header, title, prefix);
|
||||
delayLoad();
|
||||
}
|
||||
}
|
||||
|
||||
void FunctionEditPage::buildHeader(Window *window, const char *title,
|
||||
const char *prefix)
|
||||
{
|
||||
header->setTitle(title);
|
||||
headerSF = header->setTitle2(prefix + std::to_string(index + 1));
|
||||
void delayedInit() override
|
||||
{
|
||||
buildBody(body);
|
||||
}
|
||||
|
||||
etx_txt_color(headerSF->getLvObj(), COLOR_THEME_ACTIVE_INDEX,
|
||||
ETX_STATE_SF_ACTIVE);
|
||||
etx_font(headerSF->getLvObj(), FONT_BOLD_INDEX, ETX_STATE_SF_ACTIVE);
|
||||
}
|
||||
protected:
|
||||
uint8_t index;
|
||||
Window *specialFunctionOneWindow = nullptr;
|
||||
StaticText *headerSF = nullptr;
|
||||
bool active = false;
|
||||
bool saveKeyLockState;
|
||||
|
||||
void FunctionEditPage::addSourceChoice(FormLine *line, const char *title,
|
||||
CustomFunctionData *cfn, int16_t vmax)
|
||||
{
|
||||
new StaticText(line, rect_t{}, title);
|
||||
new SourceChoice(line, rect_t{}, 0, vmax, GET_SET_DEFAULT(CFN_PARAM(cfn)), true);
|
||||
}
|
||||
virtual bool isActive() const = 0;
|
||||
virtual bool isSwitchAvailable(int value) const = 0;
|
||||
virtual CustomFunctionData *customFunctionData() const = 0;
|
||||
virtual bool isAssignableFunctionAvailable(int function) const = 0;
|
||||
virtual void setDirty() const = 0;
|
||||
|
||||
NumberEdit *FunctionEditPage::addNumberEdit(FormLine *line, const char *title,
|
||||
CustomFunctionData *cfn,
|
||||
int16_t vmin, int16_t vmax)
|
||||
{
|
||||
new StaticText(line, rect_t{}, title);
|
||||
return new NumberEdit(line, rect_t{}, vmin, vmax,
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
}
|
||||
|
||||
void FunctionEditPage::updateSpecialFunctionOneWindow()
|
||||
{
|
||||
specialFunctionOneWindow->clear();
|
||||
specialFunctionOneWindow->setFlexLayout();
|
||||
FlexGridLayout grid(col_dsc, row_dsc, PAD_TINY);
|
||||
auto line = specialFunctionOneWindow->newLine(grid);
|
||||
|
||||
CustomFunctionData *cfn = customFunctionData();
|
||||
uint8_t func = CFN_FUNC(cfn);
|
||||
|
||||
// Func param
|
||||
switch (func) {
|
||||
case FUNC_OVERRIDE_CHANNEL: {
|
||||
new StaticText(line, rect_t{}, STR_CH);
|
||||
new NumberEdit(line, rect_t{}, 1, MAX_OUTPUT_CHANNELS,
|
||||
GET_SET_VALUE_WITH_OFFSET(CFN_CH_INDEX(cfn), 1));
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
|
||||
int limit =
|
||||
(g_model.extendedLimits ? LIMIT_EXT_PERCENT : LIMIT_STD_PERCENT);
|
||||
addNumberEdit(line, STR_VALUE, cfn, -limit, limit);
|
||||
break;
|
||||
}
|
||||
|
||||
case FUNC_TRAINER: {
|
||||
new StaticText(line, rect_t{}, STR_VALUE);
|
||||
auto max_sticks = adcGetMaxInputs(ADC_INPUT_MAIN);
|
||||
auto choice = new Choice(line, rect_t{}, 0, max_sticks + 1,
|
||||
GET_SET_DEFAULT(CFN_CH_INDEX(cfn)));
|
||||
choice->setTextHandler([=](int32_t value) {
|
||||
if (value == 0)
|
||||
return std::string(STR_STICKS);
|
||||
else if (value == MAX_STICKS + 1)
|
||||
return std::string(STR_CHANS);
|
||||
|
||||
return std::string(getMainControlLabel(value - 1));
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case FUNC_RESET:
|
||||
if (CFN_PARAM(cfn) <= FUNC_RESET_PARAM_LAST) {
|
||||
new StaticText(line, rect_t{}, STR_RESET);
|
||||
auto choice =
|
||||
new Choice(line, rect_t{}, 0,
|
||||
FUNC_RESET_PARAM_FIRST_TELEM + lastUsedTelemetryIndex(),
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
choice->setAvailableHandler(isSourceAvailableInResetSpecialFunction);
|
||||
choice->setTextHandler([=](int32_t value) {
|
||||
if (value < FUNC_RESET_PARAM_FIRST_TELEM)
|
||||
return std::string(STR_VFSWRESET[value]);
|
||||
else
|
||||
return std::string(
|
||||
g_model.telemetrySensors[value - FUNC_RESET_PARAM_FIRST_TELEM]
|
||||
.label,
|
||||
TELEM_LABEL_LEN);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNC_VOLUME:
|
||||
addSourceChoice(line, STR_VOLUME, cfn, MIXSRC_LAST_CH);
|
||||
break;
|
||||
|
||||
case FUNC_BACKLIGHT:
|
||||
addSourceChoice(line, STR_VALUE, cfn, MIXSRC_LAST_CH);
|
||||
break;
|
||||
|
||||
case FUNC_PLAY_SOUND:
|
||||
new StaticText(line, rect_t{}, STR_VALUE);
|
||||
new Choice(line, rect_t{}, STR_FUNCSOUNDS, 0,
|
||||
AU_SPECIAL_SOUND_LAST - AU_SPECIAL_SOUND_FIRST - 1,
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
break;
|
||||
|
||||
case FUNC_PLAY_TRACK:
|
||||
case FUNC_BACKGND_MUSIC:
|
||||
case FUNC_PLAY_SCRIPT:
|
||||
case FUNC_RGB_LED:
|
||||
new StaticText(line, rect_t{}, STR_VALUE);
|
||||
new FileChoice(
|
||||
line, rect_t{},
|
||||
func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED
|
||||
? (func == FUNC_PLAY_SCRIPT ? SCRIPTS_FUNCS_PATH
|
||||
: SCRIPTS_RGB_PATH)
|
||||
: std::string(SOUNDS_PATH, SOUNDS_PATH_LNG_OFS) +
|
||||
std::string(currentLanguagePack->id, 2),
|
||||
(func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED) ? SCRIPTS_EXT
|
||||
: SOUNDS_EXT,
|
||||
sizeof(cfn->play.name),
|
||||
[=]() { return std::string(cfn->play.name, ZLEN(cfn->play.name)); },
|
||||
[=](std::string newValue) {
|
||||
strncpy(cfn->play.name, newValue.c_str(), sizeof(cfn->play.name));
|
||||
SET_DIRTY();
|
||||
if (func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED)
|
||||
LUA_LOAD_MODEL_SCRIPTS();
|
||||
},
|
||||
true, funcGetLabel(func));
|
||||
break;
|
||||
|
||||
case FUNC_SET_TIMER: {
|
||||
new StaticText(line, rect_t{}, STR_TIMER);
|
||||
if (timersSetupCount() > 0) {
|
||||
auto timerchoice = new Choice(line, rect_t{}, 0, TIMERS - 1,
|
||||
GET_SET_DEFAULT(CFN_TIMER_INDEX(cfn)));
|
||||
timerchoice->setTextHandler([](int32_t value) {
|
||||
return std::string(STR_TIMER) + std::to_string(value + 1);
|
||||
});
|
||||
timerchoice->setAvailableHandler(
|
||||
[=](int value) { return isTimerSourceAvailable(value); });
|
||||
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
new StaticText(line, rect_t{}, STR_VALUE);
|
||||
new TimeEdit(line, rect_t{}, 0, 9 * 60 * 60 - 1,
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
void checkEvents() override
|
||||
{
|
||||
Page::checkEvents();
|
||||
if (active != isActive()) {
|
||||
if (isActive()) {
|
||||
lv_obj_add_state(headerSF->getLvObj(), ETX_STATE_SF_ACTIVE);
|
||||
} else {
|
||||
new StaticText(line, rect_t{}, STR_NO_TIMERS);
|
||||
lv_obj_clear_state(headerSF->getLvObj(), ETX_STATE_SF_ACTIVE);
|
||||
}
|
||||
break;
|
||||
active = isActive();
|
||||
}
|
||||
}
|
||||
|
||||
static const char* const strModules[] = { "Int.", "Ext." };
|
||||
case FUNC_SET_FAILSAFE:
|
||||
new StaticText(line, rect_t{}, STR_MODULE);
|
||||
new Choice(line, rect_t{}, strModules, 0, NUM_MODULES - 1,
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
break;
|
||||
void addSourceChoice(FormLine *line, const char *title,
|
||||
CustomFunctionData *cfn, int16_t vmax)
|
||||
{
|
||||
new StaticText(line, rect_t{}, title);
|
||||
new SourceChoice(line, rect_t{}, 0, vmax, GET_SET_DEFAULT(CFN_PARAM(cfn)), true);
|
||||
}
|
||||
|
||||
case FUNC_PLAY_VALUE:
|
||||
addSourceChoice(line, STR_VALUE, cfn, MIXSRC_LAST_TELEM);
|
||||
break;
|
||||
NumberEdit *addNumberEdit(FormLine *line, const char *title,
|
||||
CustomFunctionData *cfn, int16_t vmin, int16_t vmax)
|
||||
{
|
||||
new StaticText(line, rect_t{}, title);
|
||||
return new NumberEdit(line, rect_t{}, vmin, vmax,
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
}
|
||||
|
||||
case FUNC_HAPTIC:
|
||||
addNumberEdit(line, STR_VALUE, cfn, 0, 3);
|
||||
break;
|
||||
void updateSpecialFunctionOneWindow()
|
||||
{
|
||||
specialFunctionOneWindow->clear();
|
||||
specialFunctionOneWindow->setFlexLayout();
|
||||
FlexGridLayout grid(col_dsc, row_dsc, PAD_TINY);
|
||||
auto line = specialFunctionOneWindow->newLine(grid);
|
||||
|
||||
#if defined(FUNCTION_SWITCHES)
|
||||
case FUNC_PUSH_CUST_SWITCH: {
|
||||
new StaticText(line, rect_t{}, STR_SWITCH);
|
||||
auto choice = new Choice(line, rect_t{}, 0, switchGetMaxSwitches() - 1,
|
||||
[=]() { return switchGetSwitchFromCustomIdx(CFN_CS_INDEX(cfn)); },
|
||||
[=](int n) { CFN_CS_INDEX(cfn) = switchGetCustomSwitchIdx(n); },
|
||||
STR_SWITCH);
|
||||
choice->setTextHandler([=](int n) {
|
||||
return std::string(switchGetDefaultName(n));
|
||||
});
|
||||
choice->setAvailableHandler(switchIsCustomSwitch);
|
||||
CustomFunctionData *cfn = customFunctionData();
|
||||
uint8_t func = CFN_FUNC(cfn);
|
||||
|
||||
// Func param
|
||||
switch (func) {
|
||||
case FUNC_OVERRIDE_CHANNEL: {
|
||||
new StaticText(line, rect_t{}, STR_CH);
|
||||
new NumberEdit(line, rect_t{}, 1, MAX_OUTPUT_CHANNELS,
|
||||
GET_SET_VALUE_WITH_OFFSET(CFN_CH_INDEX(cfn), 1));
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
|
||||
auto edit = addNumberEdit(line, STR_INTERVAL, cfn, PUSH_CS_DURATION_MIN,
|
||||
PUSH_CS_DURATION_MAX);
|
||||
int limit =
|
||||
(g_model.extendedLimits ? LIMIT_EXT_PERCENT : LIMIT_STD_PERCENT);
|
||||
addNumberEdit(line, STR_VALUE, cfn, -limit, limit);
|
||||
break;
|
||||
}
|
||||
|
||||
case FUNC_TRAINER: {
|
||||
new StaticText(line, rect_t{}, STR_VALUE);
|
||||
auto max_sticks = adcGetMaxInputs(ADC_INPUT_MAIN);
|
||||
auto choice = new Choice(line, rect_t{}, 0, max_sticks + 1,
|
||||
GET_SET_DEFAULT(CFN_CH_INDEX(cfn)));
|
||||
choice->setTextHandler([=](int32_t value) {
|
||||
if (value == 0)
|
||||
return std::string(STR_STICKS);
|
||||
else if (value == max_sticks + 1)
|
||||
return std::string(STR_CHANS);
|
||||
|
||||
return std::string(getMainControlLabel(value - 1));
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
case FUNC_RESET:
|
||||
if (CFN_PARAM(cfn) <= FUNC_RESET_PARAM_LAST) {
|
||||
new StaticText(line, rect_t{}, STR_RESET);
|
||||
auto choice =
|
||||
new Choice(line, rect_t{}, 0,
|
||||
FUNC_RESET_PARAM_FIRST_TELEM + lastUsedTelemetryIndex(),
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
choice->setAvailableHandler(isSourceAvailableInResetSpecialFunction);
|
||||
choice->setTextHandler([=](int32_t value) {
|
||||
if (value < FUNC_RESET_PARAM_FIRST_TELEM)
|
||||
return std::string(STR_VFSWRESET[value]);
|
||||
else
|
||||
return std::string(
|
||||
g_model.telemetrySensors[value - FUNC_RESET_PARAM_FIRST_TELEM]
|
||||
.label,
|
||||
TELEM_LABEL_LEN);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNC_VOLUME:
|
||||
addSourceChoice(line, STR_VOLUME, cfn, MIXSRC_LAST_CH);
|
||||
break;
|
||||
|
||||
case FUNC_BACKLIGHT:
|
||||
addSourceChoice(line, STR_VALUE, cfn, MIXSRC_LAST_CH);
|
||||
break;
|
||||
|
||||
case FUNC_PLAY_SOUND:
|
||||
new StaticText(line, rect_t{}, STR_VALUE);
|
||||
new Choice(line, rect_t{}, STR_FUNCSOUNDS, 0,
|
||||
AU_SPECIAL_SOUND_LAST - AU_SPECIAL_SOUND_FIRST - 1,
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
break;
|
||||
|
||||
case FUNC_PLAY_TRACK:
|
||||
case FUNC_BACKGND_MUSIC:
|
||||
case FUNC_PLAY_SCRIPT:
|
||||
case FUNC_RGB_LED:
|
||||
new StaticText(line, rect_t{}, STR_VALUE);
|
||||
new FileChoice(
|
||||
line, rect_t{},
|
||||
func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED
|
||||
? (func == FUNC_PLAY_SCRIPT ? SCRIPTS_FUNCS_PATH
|
||||
: SCRIPTS_RGB_PATH)
|
||||
: std::string(SOUNDS_PATH, SOUNDS_PATH_LNG_OFS) +
|
||||
std::string(currentLanguagePack->id, 2),
|
||||
(func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED) ? SCRIPTS_EXT
|
||||
: SOUNDS_EXT,
|
||||
sizeof(cfn->play.name),
|
||||
[=]() { return std::string(cfn->play.name, ZLEN(cfn->play.name)); },
|
||||
[=](std::string newValue) {
|
||||
strncpy(cfn->play.name, newValue.c_str(), sizeof(cfn->play.name));
|
||||
SET_DIRTY();
|
||||
if (func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED)
|
||||
LUA_LOAD_MODEL_SCRIPTS();
|
||||
},
|
||||
true, funcGetLabel(func));
|
||||
break;
|
||||
|
||||
case FUNC_SET_TIMER: {
|
||||
new StaticText(line, rect_t{}, STR_TIMER);
|
||||
if (timersSetupCount() > 0) {
|
||||
auto timerchoice = new Choice(line, rect_t{}, 0, TIMERS - 1,
|
||||
GET_SET_DEFAULT(CFN_TIMER_INDEX(cfn)));
|
||||
timerchoice->setTextHandler([](int32_t value) {
|
||||
return std::string(STR_TIMER) + std::to_string(value + 1);
|
||||
});
|
||||
timerchoice->setAvailableHandler(
|
||||
[=](int value) { return isTimerSourceAvailable(value); });
|
||||
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
new StaticText(line, rect_t{}, STR_VALUE);
|
||||
new TimeEdit(line, rect_t{}, 0, 9 * 60 * 60 - 1,
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
} else {
|
||||
new StaticText(line, rect_t{}, STR_NO_TIMERS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FUNC_SET_FAILSAFE:
|
||||
static const char* const strModules[] = { "Int.", "Ext." };
|
||||
new StaticText(line, rect_t{}, STR_MODULE);
|
||||
new Choice(line, rect_t{}, strModules, 0, NUM_MODULES - 1,
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
break;
|
||||
|
||||
case FUNC_PLAY_VALUE:
|
||||
addSourceChoice(line, STR_VALUE, cfn, MIXSRC_LAST_TELEM);
|
||||
break;
|
||||
|
||||
case FUNC_HAPTIC:
|
||||
addNumberEdit(line, STR_VALUE, cfn, 0, 3);
|
||||
break;
|
||||
|
||||
#if defined(FUNCTION_SWITCHES)
|
||||
case FUNC_PUSH_CUST_SWITCH: {
|
||||
new StaticText(line, rect_t{}, STR_SWITCH);
|
||||
auto choice = new Choice(line, rect_t{}, 0, switchGetMaxSwitches() - 1,
|
||||
[=]() { return switchGetSwitchFromCustomIdx(CFN_CS_INDEX(cfn)); },
|
||||
[=](int n) { CFN_CS_INDEX(cfn) = switchGetCustomSwitchIdx(n); },
|
||||
STR_SWITCH);
|
||||
choice->setTextHandler([=](int n) {
|
||||
return std::string(switchGetDefaultName(n));
|
||||
});
|
||||
choice->setAvailableHandler(switchIsCustomSwitch);
|
||||
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
|
||||
auto edit = addNumberEdit(line, STR_INTERVAL, cfn, PUSH_CS_DURATION_MIN,
|
||||
PUSH_CS_DURATION_MAX);
|
||||
|
||||
edit->setDisplayHandler([=](int32_t value) {
|
||||
return formatNumberAsString(CFN_PARAM(cfn), PREC1, 0, nullptr, "s");
|
||||
});
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FUNC_LOGS: {
|
||||
if (CFN_PARAM(cfn) == 0) // use stored value if SF exists
|
||||
CFN_PARAM(cfn) = SD_LOGS_PERIOD_DEFAULT; // otherwise initialize with
|
||||
// default value
|
||||
|
||||
auto edit = addNumberEdit(line, STR_INTERVAL, cfn, SD_LOGS_PERIOD_MIN,
|
||||
SD_LOGS_PERIOD_MAX);
|
||||
edit->setDefault(
|
||||
SD_LOGS_PERIOD_DEFAULT); // set default period for DEF button
|
||||
edit->setDisplayHandler([=](int32_t value) {
|
||||
return formatNumberAsString(CFN_PARAM(cfn), PREC1, 0, nullptr, "s");
|
||||
});
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case FUNC_LOGS: {
|
||||
if (CFN_PARAM(cfn) == 0) // use stored value if SF exists
|
||||
CFN_PARAM(cfn) = SD_LOGS_PERIOD_DEFAULT; // otherwise initialize with
|
||||
// default value
|
||||
case FUNC_SET_SCREEN:
|
||||
CFN_PARAM(cfn) = (int16_t)max(CFN_PARAM(cfn), (int16_t)1);
|
||||
CFN_PARAM(cfn) = (int16_t)min(
|
||||
CFN_PARAM(cfn), (int16_t)ViewMain::instance()->getMainViewsCount());
|
||||
addNumberEdit(line, STR_VALUE, cfn, 1,
|
||||
ViewMain::instance()->getMainViewsCount());
|
||||
break;
|
||||
|
||||
auto edit = addNumberEdit(line, STR_INTERVAL, cfn, SD_LOGS_PERIOD_MIN,
|
||||
SD_LOGS_PERIOD_MAX);
|
||||
edit->setDefault(
|
||||
SD_LOGS_PERIOD_DEFAULT); // set default period for DEF button
|
||||
edit->setDisplayHandler([=](int32_t value) {
|
||||
return formatNumberAsString(CFN_PARAM(cfn), PREC1, 0, nullptr, "s");
|
||||
});
|
||||
break;
|
||||
}
|
||||
case FUNC_ADJUST_GVAR: {
|
||||
if (validateSFGV(cfn)) SET_DIRTY();
|
||||
new StaticText(line, rect_t{}, STR_GLOBALVAR);
|
||||
auto gvarchoice = new Choice(line, rect_t{}, 0, MAX_GVARS - 1,
|
||||
GET_DEFAULT(CFN_GVAR_INDEX(cfn)),
|
||||
[=](int32_t newValue){
|
||||
CFN_GVAR_INDEX(cfn) = newValue;
|
||||
SET_DIRTY();
|
||||
updateSpecialFunctionOneWindow();
|
||||
});
|
||||
gvarchoice->setTextHandler([](int32_t value) {
|
||||
return std::string(getSourceString(value + MIXSRC_FIRST_GVAR));
|
||||
});
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
|
||||
case FUNC_SET_SCREEN:
|
||||
CFN_PARAM(cfn) = (int16_t)max(CFN_PARAM(cfn), (int16_t)1);
|
||||
CFN_PARAM(cfn) = (int16_t)min(
|
||||
CFN_PARAM(cfn), (int16_t)ViewMain::instance()->getMainViewsCount());
|
||||
addNumberEdit(line, STR_VALUE, cfn, 1,
|
||||
ViewMain::instance()->getMainViewsCount());
|
||||
break;
|
||||
new StaticText(line, rect_t{}, STR_MODE);
|
||||
auto modechoice = new Choice(line, rect_t{}, FUNC_ADJUST_GVAR_CONSTANT,
|
||||
FUNC_ADJUST_GVAR_INCDEC,
|
||||
GET_DEFAULT(CFN_GVAR_MODE(cfn)),
|
||||
[=](int32_t newValue) {
|
||||
CFN_GVAR_MODE(cfn) = newValue;
|
||||
CFN_PARAM(cfn) = 0;
|
||||
SET_DIRTY();
|
||||
updateSpecialFunctionOneWindow();
|
||||
});
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
|
||||
case FUNC_ADJUST_GVAR: {
|
||||
if (validateSFGV(cfn)) SET_DIRTY();
|
||||
new StaticText(line, rect_t{}, STR_GLOBALVAR);
|
||||
auto gvarchoice = new Choice(line, rect_t{}, 0, MAX_GVARS - 1,
|
||||
GET_DEFAULT(CFN_GVAR_INDEX(cfn)),
|
||||
[=](int32_t newValue){
|
||||
CFN_GVAR_INDEX(cfn) = newValue;
|
||||
SET_DIRTY();
|
||||
updateSpecialFunctionOneWindow();
|
||||
});
|
||||
gvarchoice->setTextHandler([](int32_t value) {
|
||||
return std::string(getSourceString(value + MIXSRC_FIRST_GVAR));
|
||||
});
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
modechoice->setTextHandler([](int32_t value) {
|
||||
switch (value) {
|
||||
case FUNC_ADJUST_GVAR_CONSTANT:
|
||||
return std::string(STR_CONSTANT);
|
||||
case FUNC_ADJUST_GVAR_SOURCE:
|
||||
return std::string(STR_MIXSOURCE);
|
||||
case FUNC_ADJUST_GVAR_SOURCERAW:
|
||||
return std::string(STR_MIXSOURCERAW);
|
||||
case FUNC_ADJUST_GVAR_GVAR:
|
||||
return std::string(STR_GLOBALVAR);
|
||||
case FUNC_ADJUST_GVAR_INCDEC:
|
||||
return std::string(STR_INCDEC);
|
||||
}
|
||||
return std::string("---");
|
||||
});
|
||||
|
||||
new StaticText(line, rect_t{}, STR_MODE);
|
||||
auto modechoice = new Choice(line, rect_t{}, FUNC_ADJUST_GVAR_CONSTANT,
|
||||
FUNC_ADJUST_GVAR_INCDEC,
|
||||
GET_DEFAULT(CFN_GVAR_MODE(cfn)),
|
||||
[=](int32_t newValue) {
|
||||
CFN_GVAR_MODE(cfn) = newValue;
|
||||
CFN_PARAM(cfn) = 0;
|
||||
SET_DIRTY();
|
||||
updateSpecialFunctionOneWindow();
|
||||
});
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
|
||||
modechoice->setTextHandler([](int32_t value) {
|
||||
switch (value) {
|
||||
case FUNC_ADJUST_GVAR_CONSTANT:
|
||||
return std::string(STR_CONSTANT);
|
||||
switch (CFN_GVAR_MODE(cfn)) {
|
||||
case FUNC_ADJUST_GVAR_CONSTANT: {
|
||||
int16_t val_min, val_max;
|
||||
getMixSrcRange(CFN_GVAR_INDEX(cfn) + MIXSRC_FIRST_GVAR, val_min,
|
||||
val_max);
|
||||
addNumberEdit(line, STR_CONSTANT, cfn, val_min, val_max);
|
||||
break;
|
||||
}
|
||||
case FUNC_ADJUST_GVAR_SOURCE:
|
||||
return std::string(STR_MIXSOURCE);
|
||||
case FUNC_ADJUST_GVAR_SOURCERAW:
|
||||
return std::string(STR_MIXSOURCERAW);
|
||||
case FUNC_ADJUST_GVAR_GVAR:
|
||||
return std::string(STR_GLOBALVAR);
|
||||
case FUNC_ADJUST_GVAR_INCDEC:
|
||||
return std::string(STR_INCDEC);
|
||||
}
|
||||
return std::string("---");
|
||||
});
|
||||
|
||||
switch (CFN_GVAR_MODE(cfn)) {
|
||||
case FUNC_ADJUST_GVAR_CONSTANT: {
|
||||
int16_t val_min, val_max;
|
||||
getMixSrcRange(CFN_GVAR_INDEX(cfn) + MIXSRC_FIRST_GVAR, val_min,
|
||||
val_max);
|
||||
addNumberEdit(line, STR_CONSTANT, cfn, val_min, val_max);
|
||||
break;
|
||||
}
|
||||
case FUNC_ADJUST_GVAR_SOURCE:
|
||||
case FUNC_ADJUST_GVAR_SOURCERAW:
|
||||
addSourceChoice(line, STR_MIXSOURCE, cfn, MIXSRC_LAST_CH);
|
||||
break;
|
||||
case FUNC_ADJUST_GVAR_GVAR: {
|
||||
new StaticText(line, rect_t{}, STR_GLOBALVAR);
|
||||
auto gvarchoice = new Choice(line, rect_t{}, 0, MAX_GVARS - 1,
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
gvarchoice->setTextHandler([](int32_t value) {
|
||||
return std::string(getSourceString(value + MIXSRC_FIRST_GVAR));
|
||||
});
|
||||
gvarchoice->setAvailableHandler(
|
||||
[=](int value) { return CFN_GVAR_INDEX(cfn) != value; });
|
||||
break;
|
||||
}
|
||||
case FUNC_ADJUST_GVAR_INCDEC: {
|
||||
int16_t val_min, val_max;
|
||||
getMixSrcRange(CFN_GVAR_INDEX(cfn) + MIXSRC_FIRST_GVAR, val_min,
|
||||
val_max);
|
||||
getGVarIncDecRange(val_min, val_max);
|
||||
auto numedit = addNumberEdit(line, STR_INCDEC, cfn, val_min, val_max);
|
||||
numedit->setDisplayHandler([](int value) {
|
||||
return formatNumberAsString(abs(value), 0, 0,
|
||||
value >= 0 ? "+=" : "-=", nullptr);
|
||||
});
|
||||
break;
|
||||
addSourceChoice(line, STR_MIXSOURCE, cfn, MIXSRC_LAST_CH);
|
||||
break;
|
||||
case FUNC_ADJUST_GVAR_GVAR: {
|
||||
new StaticText(line, rect_t{}, STR_GLOBALVAR);
|
||||
auto gvarchoice = new Choice(line, rect_t{}, 0, MAX_GVARS - 1,
|
||||
GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
gvarchoice->setTextHandler([](int32_t value) {
|
||||
return std::string(getSourceString(value + MIXSRC_FIRST_GVAR));
|
||||
});
|
||||
gvarchoice->setAvailableHandler(
|
||||
[=](int value) { return CFN_GVAR_INDEX(cfn) != value; });
|
||||
break;
|
||||
}
|
||||
case FUNC_ADJUST_GVAR_INCDEC: {
|
||||
int16_t val_min, val_max;
|
||||
getMixSrcRange(CFN_GVAR_INDEX(cfn) + MIXSRC_FIRST_GVAR, val_min,
|
||||
val_max);
|
||||
getGVarIncDecRange(val_min, val_max);
|
||||
auto numedit = addNumberEdit(line, STR_INCDEC, cfn, val_min, val_max);
|
||||
numedit->setDisplayHandler([](int value) {
|
||||
return formatNumberAsString(abs(value), 0, 0,
|
||||
value >= 0 ? "+=" : "-=", nullptr);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HAS_REPEAT_PARAM(func)) { // !1x 1x 1s 2s 3s ...
|
||||
if (HAS_REPEAT_PARAM(func)) { // !1x 1x 1s 2s 3s ...
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
new StaticText(line, rect_t{}, STR_REPEAT);
|
||||
if (func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED) {
|
||||
auto repeat = new Choice(line, rect_t{}, 0, 1,
|
||||
GET_DEFAULT((int8_t)CFN_PLAY_REPEAT(cfn)),
|
||||
SET_DEFAULT(CFN_PLAY_REPEAT(cfn)));
|
||||
repeat->setTextHandler([](int32_t value) {
|
||||
// 0 == repeat at 50ms interval for backward compatibility
|
||||
return (value == 0) ? std::string("On") : std::string("1x");
|
||||
});
|
||||
} else {
|
||||
auto repeat = new NumberEdit(line, rect_t{}, -1, 60 / CFN_PLAY_REPEAT_MUL,
|
||||
GET_DEFAULT((int8_t)CFN_PLAY_REPEAT(cfn)),
|
||||
SET_DEFAULT(CFN_PLAY_REPEAT(cfn)));
|
||||
repeat->setDisplayHandler([](int32_t value) {
|
||||
if (value == 0)
|
||||
return std::string("1x");
|
||||
else if (value == (int8_t)CFN_PLAY_REPEAT_NOSTART)
|
||||
return std::string("!1x");
|
||||
else {
|
||||
return formatNumberAsString(value * CFN_PLAY_REPEAT_MUL, 0, 0,
|
||||
nullptr, "s");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
new StaticText(line, rect_t{}, STR_REPEAT);
|
||||
if (func == FUNC_PLAY_SCRIPT || func == FUNC_RGB_LED) {
|
||||
auto repeat = new Choice(line, rect_t{}, 0, 1,
|
||||
GET_DEFAULT((int8_t)CFN_PLAY_REPEAT(cfn)),
|
||||
SET_DEFAULT(CFN_PLAY_REPEAT(cfn)));
|
||||
repeat->setTextHandler([](int32_t value) {
|
||||
// 0 == repeat at 50ms interval for backward compatibility
|
||||
return (value == 0) ? std::string("On") : std::string("1x");
|
||||
});
|
||||
} else {
|
||||
auto repeat = new NumberEdit(line, rect_t{}, -1, 60 / CFN_PLAY_REPEAT_MUL,
|
||||
GET_DEFAULT((int8_t)CFN_PLAY_REPEAT(cfn)),
|
||||
SET_DEFAULT(CFN_PLAY_REPEAT(cfn)));
|
||||
repeat->setDisplayHandler([](int32_t value) {
|
||||
if (value == 0)
|
||||
return std::string("1x");
|
||||
else if (value == (int8_t)CFN_PLAY_REPEAT_NOSTART)
|
||||
return std::string("!1x");
|
||||
else {
|
||||
return formatNumberAsString(value * CFN_PLAY_REPEAT_MUL, 0, 0,
|
||||
nullptr, "s");
|
||||
}
|
||||
});
|
||||
}
|
||||
new StaticText(line, rect_t{}, STR_ENABLE);
|
||||
new ToggleSwitch(line, rect_t{}, GET_DEFAULT(CFN_ACTIVE(cfn)),
|
||||
[=](int newValue) {
|
||||
CFN_ACTIVE(cfn) = newValue;
|
||||
SET_DIRTY();
|
||||
if (CFN_FUNC(cfn) == FUNC_PLAY_SCRIPT || CFN_FUNC(cfn) == FUNC_RGB_LED)
|
||||
LUA_LOAD_MODEL_SCRIPTS();
|
||||
});
|
||||
}
|
||||
|
||||
line = specialFunctionOneWindow->newLine(grid);
|
||||
new StaticText(line, rect_t{}, STR_ENABLE);
|
||||
new ToggleSwitch(line, rect_t{}, GET_DEFAULT(CFN_ACTIVE(cfn)),
|
||||
[=](int newValue) {
|
||||
CFN_ACTIVE(cfn) = newValue;
|
||||
SET_DIRTY();
|
||||
if (CFN_FUNC(cfn) == FUNC_PLAY_SCRIPT || CFN_FUNC(cfn) == FUNC_RGB_LED)
|
||||
LUA_LOAD_MODEL_SCRIPTS();
|
||||
});
|
||||
}
|
||||
void buildHeader(Window *window, const char *title, const char *prefix)
|
||||
{
|
||||
header->setTitle(title);
|
||||
headerSF = header->setTitle2(prefix + std::to_string(index + 1));
|
||||
|
||||
void FunctionEditPage::buildBody(Window *form)
|
||||
{
|
||||
form->setFlexLayout(LV_FLEX_FLOW_COLUMN, PAD_LARGE);
|
||||
|
||||
FlexGridLayout grid(col_dsc, row_dsc, PAD_TINY);
|
||||
|
||||
CustomFunctionData *cfn = customFunctionData();
|
||||
|
||||
// Switch
|
||||
auto line = form->newLine(grid);
|
||||
new StaticText(line, rect_t{}, STR_SF_SWITCH);
|
||||
auto switchChoice = new SwitchChoice(line, rect_t{}, SWSRC_FIRST, SWSRC_LAST,
|
||||
GET_SET_DEFAULT(CFN_SWITCH(cfn)));
|
||||
switchChoice->setAvailableHandler(
|
||||
[=](int value) { return isSwitchAvailable(value); });
|
||||
|
||||
// Patch function in case not available
|
||||
if (!isAssignableFunctionAvailable(CFN_FUNC(cfn))) {
|
||||
auto func = 0;
|
||||
while (!isAssignableFunctionAvailable(func) && (func < FUNC_MAX - 1)) {
|
||||
func++;
|
||||
}
|
||||
if (func < FUNC_MAX - 1) {
|
||||
CFN_FUNC(cfn) = func;
|
||||
}
|
||||
etx_txt_color(headerSF->getLvObj(), COLOR_THEME_ACTIVE_INDEX,
|
||||
ETX_STATE_SF_ACTIVE);
|
||||
etx_font(headerSF->getLvObj(), FONT_BOLD_INDEX, ETX_STATE_SF_ACTIVE);
|
||||
}
|
||||
|
||||
// Function
|
||||
line = form->newLine(grid);
|
||||
new StaticText(line, rect_t{}, STR_FUNC);
|
||||
auto functionChoice =
|
||||
new Choice(line, rect_t{}, 0, FUNC_MAX - 1, GET_DEFAULT(getFuncSortIdx(CFN_FUNC(cfn))),
|
||||
[=](int32_t newValue) {
|
||||
Functions newFunc = cfn_sorted[newValue];
|
||||
// If changing from Lua script then reload to remove old reference
|
||||
if ((CFN_FUNC(cfn) == FUNC_PLAY_SCRIPT || CFN_FUNC(cfn) == FUNC_RGB_LED) && newFunc != FUNC_PLAY_SCRIPT && newFunc != FUNC_RGB_LED)
|
||||
LUA_LOAD_MODEL_SCRIPTS();
|
||||
CFN_FUNC(cfn) = newFunc;
|
||||
CFN_RESET(cfn);
|
||||
SET_DIRTY();
|
||||
updateSpecialFunctionOneWindow();
|
||||
});
|
||||
functionChoice->setTextHandler([=](int val) { return funcGetLabel(cfn_sorted[val]); });
|
||||
functionChoice->setAvailableHandler(
|
||||
[=](int value) { return isAssignableFunctionAvailable(cfn_sorted[value]); });
|
||||
void buildBody(Window *form)
|
||||
{
|
||||
form->setFlexLayout(LV_FLEX_FLOW_COLUMN, PAD_LARGE);
|
||||
|
||||
specialFunctionOneWindow = new Window(form, rect_t{});
|
||||
updateSpecialFunctionOneWindow();
|
||||
}
|
||||
FlexGridLayout grid(col_dsc, row_dsc, PAD_TINY);
|
||||
|
||||
CustomFunctionData *cfn = customFunctionData();
|
||||
|
||||
// Switch
|
||||
auto line = form->newLine(grid);
|
||||
new StaticText(line, rect_t{}, STR_SF_SWITCH);
|
||||
auto switchChoice = new SwitchChoice(line, rect_t{}, SWSRC_FIRST, SWSRC_LAST,
|
||||
GET_SET_DEFAULT(CFN_SWITCH(cfn)));
|
||||
switchChoice->setAvailableHandler(
|
||||
[=](int value) { return isSwitchAvailable(value); });
|
||||
|
||||
// Patch function in case not available
|
||||
if (!isAssignableFunctionAvailable(CFN_FUNC(cfn))) {
|
||||
auto func = 0;
|
||||
while (!isAssignableFunctionAvailable(func) && (func < FUNC_MAX - 1)) {
|
||||
func++;
|
||||
}
|
||||
if (func < FUNC_MAX - 1) {
|
||||
CFN_FUNC(cfn) = func;
|
||||
}
|
||||
}
|
||||
|
||||
// Function
|
||||
line = form->newLine(grid);
|
||||
new StaticText(line, rect_t{}, STR_FUNC);
|
||||
auto functionChoice =
|
||||
new Choice(line, rect_t{}, 0, FUNC_MAX - 1, GET_DEFAULT(getFuncSortIdx(CFN_FUNC(cfn))),
|
||||
[=](int32_t newValue) {
|
||||
Functions newFunc = cfn_sorted[newValue];
|
||||
// If changing from Lua script then reload to remove old reference
|
||||
if ((CFN_FUNC(cfn) == FUNC_PLAY_SCRIPT || CFN_FUNC(cfn) == FUNC_RGB_LED) && newFunc != FUNC_PLAY_SCRIPT && newFunc != FUNC_RGB_LED)
|
||||
LUA_LOAD_MODEL_SCRIPTS();
|
||||
CFN_FUNC(cfn) = newFunc;
|
||||
CFN_RESET(cfn);
|
||||
SET_DIRTY();
|
||||
updateSpecialFunctionOneWindow();
|
||||
});
|
||||
functionChoice->setTextHandler([=](int val) { return funcGetLabel(cfn_sorted[val]); });
|
||||
functionChoice->setAvailableHandler(
|
||||
[=](int value) { return isAssignableFunctionAvailable(cfn_sorted[value]); });
|
||||
|
||||
specialFunctionOneWindow = new Window(form, rect_t{});
|
||||
updateSpecialFunctionOneWindow();
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -929,7 +942,7 @@ class SpecialFunctionLineButton : public FunctionLineButton
|
||||
protected:
|
||||
bool isActive() const override
|
||||
{
|
||||
return modelFunctionsContext.activeSwitches & ((MASK_CFN_TYPE)1 << index);
|
||||
return modelFunctionsContext.isFunctionSwitchActive(index);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -947,7 +960,7 @@ class SpecialFunctionEditPage : public FunctionEditPage
|
||||
protected:
|
||||
bool isActive() const override
|
||||
{
|
||||
return modelFunctionsContext.activeSwitches & ((MASK_CFN_TYPE)1 << index);
|
||||
return modelFunctionsContext.isFunctionSwitchActive(index);
|
||||
}
|
||||
|
||||
bool isSwitchAvailable(int value) const override
|
||||
@@ -1009,7 +1022,7 @@ class GlobalFunctionLineButton : public FunctionLineButton
|
||||
protected:
|
||||
bool isActive() const override
|
||||
{
|
||||
return globalFunctionsContext.activeSwitches & ((MASK_CFN_TYPE)1 << index);
|
||||
return globalFunctionsContext.isFunctionSwitchActive(index);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1027,7 +1040,7 @@ class GlobalFunctionEditPage : public FunctionEditPage
|
||||
protected:
|
||||
bool isActive() const override
|
||||
{
|
||||
return globalFunctionsContext.activeSwitches & ((MASK_CFN_TYPE)1 << index);
|
||||
return globalFunctionsContext.isFunctionSwitchActive(index);
|
||||
}
|
||||
|
||||
bool isSwitchAvailable(int value) const override
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
struct CustomFunctionData;
|
||||
class FunctionEditPage;
|
||||
class FunctionLineButton;
|
||||
class NumberEdit;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -79,43 +78,6 @@ class FunctionLineButton : public ListLineButton
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class FunctionEditPage : public Page
|
||||
{
|
||||
public:
|
||||
FunctionEditPage(uint8_t index, EdgeTxIcon icon, const char *title,
|
||||
const char *prefix);
|
||||
|
||||
void delayedInit() override;
|
||||
|
||||
protected:
|
||||
uint8_t index;
|
||||
Window *specialFunctionOneWindow = nullptr;
|
||||
StaticText *headerSF = nullptr;
|
||||
bool active = false;
|
||||
|
||||
virtual bool isActive() const = 0;
|
||||
virtual bool isSwitchAvailable(int value) const = 0;
|
||||
virtual CustomFunctionData *customFunctionData() const = 0;
|
||||
virtual bool isAssignableFunctionAvailable(int function) const = 0;
|
||||
virtual void setDirty() const = 0;
|
||||
|
||||
void checkEvents() override;
|
||||
|
||||
void buildHeader(Window *window, const char *title, const char *prefix);
|
||||
|
||||
void addSourceChoice(FormLine *line, const char *title,
|
||||
CustomFunctionData *cfn, int16_t vmax);
|
||||
|
||||
NumberEdit *addNumberEdit(FormLine *line, const char *title,
|
||||
CustomFunctionData *cfn, int16_t vmin, int16_t vmax);
|
||||
|
||||
void updateSpecialFunctionOneWindow();
|
||||
|
||||
void buildBody(Window *form);
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class FunctionsPage : public PageGroupItem
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -29,8 +29,6 @@
|
||||
#include "stamp.h"
|
||||
#include "theme_manager.h"
|
||||
|
||||
extern void checkSpeakerVolume();
|
||||
|
||||
constexpr const char* strip_leading_hyphen(const char* str) {
|
||||
return (str[0] == '-') ? str + 1 : str;
|
||||
}
|
||||
|
||||
@@ -250,10 +250,12 @@ void CLEAR_POPUP()
|
||||
popupMenuItemsCount = 0;
|
||||
}
|
||||
|
||||
void POPUP_WAIT(const char * s)
|
||||
void POPUP_WAIT(const char * s, const char * info)
|
||||
{
|
||||
warningText = s;
|
||||
warningInfoText = nullptr;
|
||||
warningInfoText = info;
|
||||
warningInfoLength = info ? strlen(info) : 0;
|
||||
warningInfoFlags = 0;
|
||||
warningType = WARNING_TYPE_WAIT;
|
||||
popupFunc = runPopupWarning;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ typedef void (* ProgressHandler)(const char *, const char *, int, int);
|
||||
|
||||
#if !defined(GUI)
|
||||
#define DISPLAY_WARNING(...)
|
||||
inline void POPUP_WAIT(const char * s) { }
|
||||
inline void POPUP_WAIT(const char * s, const char * = nullptr) { }
|
||||
inline void POPUP_WARNING(const char *, const char * = nullptr) { }
|
||||
inline void POPUP_CONFIRMATION(const char * s, PopupMenuHandler handler) { }
|
||||
inline void POPUP_INPUT(const char * s, PopupFunc func) { }
|
||||
@@ -90,7 +90,7 @@ typedef void (* ProgressHandler)(const char *, const char *, int, int);
|
||||
#else
|
||||
#define DISPLAY_WARNING(evt) (*popupFunc)(evt)
|
||||
extern void CLEAR_POPUP();
|
||||
extern void POPUP_WAIT(const char * s);
|
||||
extern void POPUP_WAIT(const char * s, const char * = nullptr);
|
||||
extern void POPUP_INFORMATION(const char * s);
|
||||
extern void POPUP_WARNING(const char * message, const char * info = nullptr);
|
||||
extern void SET_WARNING_INFO(const char * info, uint8_t length, uint8_t flags);
|
||||
|
||||
@@ -662,6 +662,10 @@ bool isAssignableFunctionAvailable(int function, bool modelFunctions)
|
||||
case FUNC_PUSH_CUST_SWITCH:
|
||||
return modelFunctions;
|
||||
#endif
|
||||
#if defined(KEYS_LOCK_KEY1) && defined(KEYS_LOCK_KEY2)
|
||||
case FUNC_DISABLE_KEYS:
|
||||
return g_eeGeneral.keyLockEnabled;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user