diff --git a/companion/src/firmwares/customisation_data.cpp b/companion/src/firmwares/customisation_data.cpp index 887fec5d0..cb19f6976 100644 --- a/companion/src/firmwares/customisation_data.cpp +++ b/companion/src/firmwares/customisation_data.cpp @@ -141,8 +141,7 @@ void RadioLayout::init(const char* layoutId, CustomScreens& customScreens) for (int i = 0; i < MAX_CUSTOM_SCREENS; i++) { if (i == 0) - memcpy(&customScreens.customScreenData[i].layoutId, layoutId, - LAYOUT_ID_LEN); + strncpy(customScreens.customScreenData[i].layoutId, layoutId, LAYOUT_ID_LEN); LayoutPersistentData& persistentData = customScreens.customScreenData[i].layoutPersistentData; diff --git a/companion/src/firmwares/customisation_data.h b/companion/src/firmwares/customisation_data.h index be8be0713..4450d196e 100644 --- a/companion/src/firmwares/customisation_data.h +++ b/companion/src/firmwares/customisation_data.h @@ -33,14 +33,14 @@ constexpr int MAX_CUSTOM_SCREENS {10}; constexpr int MAX_THEME_OPTIONS {5}; -constexpr int LEN_ZONE_OPTION_STRING {12}; +constexpr int LEN_ZONE_OPTION_STRING {255}; // TODO: use std::string instead of fixed length char array constexpr int MAX_LAYOUT_ZONES {10}; constexpr int MAX_LAYOUT_OPTIONS {10}; -constexpr int WIDGET_NAME_LEN {20}; -constexpr int MAX_WIDGET_OPTIONS {10}; +constexpr int WIDGET_NAME_LEN {255}; // TODO: use std::string instead of fixed length char array +constexpr int MAX_WIDGET_OPTIONS {50}; constexpr int MAX_TOPBAR_ZONES {6}; // max 4 used for portrait constexpr int MAX_TOPBAR_OPTIONS {1}; -constexpr int LAYOUT_ID_LEN {12}; +constexpr int LAYOUT_ID_LEN {255}; // TODO: use std::string instead of fixed length char array // Common 'ZoneOptionValue's among all layouts enum { diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index eba600214..c1a92c103 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -427,7 +427,8 @@ endif() set(SRC ${SRC} edgetx.cpp - datastructs_private.cpp + datastructs_model.cpp + datastructs_radio.cpp functions.cpp strhelpers.cpp switches.cpp diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index b9d9150fc..8ffdf29ad 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -72,16 +72,6 @@ static inline void check_struct() CHKSIZE(LimitData, 13); CHKSIZE(TimerData, 17); CHKSIZE(ModelHeader, 131); - CHKSIZE(CustomScreenData, 1972); - #if defined(RADIO_NB4P) || defined(RADIO_NV14_FAMILY) - CHKTYPE(TopBarPersistentData, 736); - #elif defined(PCBPA01) - CHKTYPE(TopBarPersistentData, 916); - #elif defined(RADIO_H7RS) - // TODO - #else - CHKTYPE(TopBarPersistentData, 1096); - #endif #else #error CHKSIZE not set up #endif @@ -100,8 +90,6 @@ static inline void check_struct() #if defined(RADIO_TPRO) || defined(RADIO_TPROV2) || defined(RADIO_BUMBLEBEE) CHKSIZE(ModelData, 6355); -#elif defined(RADIO_T14) || defined(RADIO_T12MAX) - CHKSIZE(ModelData, 6329); #elif defined(RADIO_FAMILY_T20) CHKSIZE(ModelData, 6391); #elif defined(RADIO_GX12) @@ -110,28 +98,24 @@ static inline void check_struct() CHKSIZE(ModelData, 6771); #elif defined(PCBX9D) || defined(PCBX9DP) CHKSIZE(ModelData, 6770); -#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITE) +#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX9LITE) || defined(RADIO_T14) || defined(RADIO_T12MAX) CHKSIZE(ModelData, 6329); #elif defined(PCBPL18) #if defined(RADIO_NB4P) || defined(RADIO_NV14_FAMILY) - CHKSIZE(ModelData, 27331); + CHKSIZE(ModelData, 6875); #else - CHKSIZE(ModelData, 27693); + CHKSIZE(ModelData, 6877); #endif -#elif defined(PCBST16) - CHKSIZE(ModelData, 28457); +#elif defined(PCBST16) || defined(RADIO_T15PRO) || defined(RADIO_TX15) + CHKSIZE(ModelData, 7641); #elif defined(PCBPA01) - CHKSIZE(ModelData, 28218); + CHKSIZE(ModelData, 7582); #elif defined(RADIO_T15) - CHKSIZE(ModelData, 27683); -#elif defined(RADIO_T15PRO) - CHKSIZE(ModelData, 28457); -#elif defined(RADIO_TX15) - CHKSIZE(ModelData, 28457); + CHKSIZE(ModelData, 6867); #elif defined(RADIO_H7RS) // CHKSIZE() #elif defined(PCBHORUS) - CHKSIZE(ModelData, 27657); + CHKSIZE(ModelData, 6841); #else #error CHKSIZE not set up #endif diff --git a/radio/src/datastructs_private.cpp b/radio/src/datastructs_model.cpp similarity index 77% rename from radio/src/datastructs_private.cpp rename to radio/src/datastructs_model.cpp index 1face10a2..68984a11b 100644 --- a/radio/src/datastructs_private.cpp +++ b/radio/src/datastructs_model.cpp @@ -19,8 +19,11 @@ * GNU General Public License for more details. */ - #include "edgetx.h" - #include "hal/switch_driver.h" +#include "edgetx.h" +#include "tasks/mixer_task.h" +#include "hal/adc_driver.h" + +//----------------------------------------------------------------------------- SwitchConfig ModelData::getSwitchType(uint8_t n) { @@ -43,7 +46,7 @@ char* ModelData::getSwitchCustomName(uint8_t n) { #if defined(FUNCTION_SWITCHES) if (switchIsCustomSwitch(n) && cfsType(n) != SWITCH_GLOBAL) - return g_model.cfsName(n); + return cfsName(n); #endif return g_eeGeneral.getSwitchCustomName(n); } @@ -52,7 +55,7 @@ bool ModelData::switchHasCustomName(uint8_t n) { #if defined(FUNCTION_SWITCHES) if (switchIsCustomSwitch(n) && cfsType(n) != SWITCH_GLOBAL) - return g_model.cfsName(n)[0] != 0; + return cfsName(n)[0] != 0; #endif return g_eeGeneral.switchHasCustomName(n); } @@ -68,29 +71,6 @@ uint8_t ModelData::getSwitchStateForWarning(uint8_t n) return (switches_states >> (n * 2)) & 3; } -char* RadioData::getSwitchCustomName(uint8_t n) -{ - return switchConfig[n].name; -} - -bool RadioData::switchHasCustomName(uint8_t n) -{ - return switchConfig[n].name[0] != 0; -} - -SwitchConfig RadioData::switchType(uint8_t n) { - return (SwitchConfig)switchConfig[n].type; -} - -void RadioData::switchSetType(uint8_t n, SwitchConfig v) { - switchConfig[n].type = v; - storageDirty(EE_GENERAL); -} - -char* RadioData::switchName(uint8_t n) { - return switchConfig[n].name; -} - #if defined(FUNCTION_SWITCHES) uint8_t ModelData::getSwitchGroup(uint8_t n) { if (switchIsCustomSwitch(n) && cfsType(n) != SWITCH_GLOBAL) @@ -214,41 +194,67 @@ void ModelData::cfsSetOffColorLuaOverride(uint8_t n, bool v) { storageDirty(EE_MODEL); } #endif +#endif -fsStartPositionType RadioData::switchStart(uint8_t n) { - return (fsStartPositionType)switchConfig[n].start; +#if defined(COLORLCD) +static TopBarPersistentData _topbarData; +static CustomScreenData* _screenData[MAX_CUSTOM_SCREENS]; + +CustomScreenData* ModelData::getScreenData(int screenNum) +{ + if (_screenData[screenNum] == nullptr) { + _screenData[screenNum] = new CustomScreenData(); + _screenData[screenNum]->layoutData.clear(); + } + + return _screenData[screenNum]; } -void RadioData::switchSetStart(uint8_t n, fsStartPositionType v) { - switchConfig[n].start = v; - storageDirty(EE_GENERAL); +const char* ModelData::getScreenLayoutId(int screenNum) +{ + return getScreenData(screenNum)->LayoutId.c_str(); } -#if defined(FUNCTION_SWITCHES_RGB_LEDS) -RGBLedColor& RadioData::switchOnColor(uint8_t n) { - return switchConfig[n].onColor; +void ModelData::setScreenLayoutId(int screenNum, const char* s) +{ + getScreenData(screenNum)->LayoutId = s; } -RGBLedColor& RadioData::switchOffColor(uint8_t n) { - return switchConfig[n].offColor; +TopBarPersistentData* ModelData::getTopbarData() +{ + return &_topbarData; } -bool RadioData::cfsOnColorLuaOverride(uint8_t n) { - return switchConfig[n].onColorLuaOverride; +LayoutPersistentData* ModelData::getScreenLayoutData(int screenNum) +{ + return &getScreenData(screenNum)->layoutData; } -bool RadioData::cfsOffColorLuaOverride(uint8_t n) { - return switchConfig[n].offColorLuaOverride; +WidgetPersistentData* ModelData::getWidgetData(int screenNum, int zoneNum) +{ + if (screenNum == -1) + return getTopbarData()->getWidgetData(zoneNum); + else + return getScreenLayoutData(screenNum)->getWidgetData(zoneNum); } -void RadioData::cfsSetOnColorLuaOverride(uint8_t n, bool v) { - switchConfig[n].onColorLuaOverride = v; - storageDirty(EE_GENERAL); +void ModelData::removeScreenLayout(int idx) +{ + if (_screenData[idx]) delete _screenData[idx]; + + for (; idx < MAX_CUSTOM_SCREENS - 1; idx += 1) + _screenData[idx] = _screenData[idx + 1]; + + _screenData[idx] = nullptr; } -void RadioData::cfsSetOffColorLuaOverride(uint8_t n, bool v) { - switchConfig[n].offColorLuaOverride = v; - storageDirty(EE_GENERAL); +void ModelData::initScreenData() +{ + _topbarData.clear(); + + for (int i = 0; i < MAX_CUSTOM_SCREENS; i += 1) { + if (_screenData[i]) delete _screenData[i]; + _screenData[i] = nullptr; + } } #endif -#endif diff --git a/radio/src/datastructs_private.h b/radio/src/datastructs_private.h index ade7f4a98..eb418d6b9 100644 --- a/radio/src/datastructs_private.h +++ b/radio/src/datastructs_private.h @@ -34,6 +34,10 @@ #include "debug.h" #include "bitfield.h" +#if defined(COLORLCD) +#include "datastructs_screen.h" +#endif + #if defined(PCBTARANIS) #define N_TARANIS_FIELD(x) #define TARANIS_FIELD(x) x; @@ -614,28 +618,6 @@ static_assert(sizeof(potconfig_t) * 8 >= ((MAX_POTS - 1) / 4) + 1, static_assert(sizeof(potwarnen_t) * 8 >= MAX_POTS, "MAX_POTS must fit potwarnen_t"); -#if defined(COLORLCD) && defined(BACKUP) -#define CUSTOM_SCREENS_DATA -#elif defined(COLORLCD) -#include "layout.h" -#include "topbar.h" -#define LAYOUT_ID_LEN 12 -PACK(struct CustomScreenData { - char LayoutId[LAYOUT_ID_LEN]; - LayoutPersistentData layoutData; -}); -#define CUSTOM_SCREENS_DATA \ - NOBACKUP(CustomScreenData screenData[MAX_CUSTOM_SCREENS]); \ - NOBACKUP(TopBarPersistentData topbarData); \ - NOBACKUP(uint8_t topbarWidgetWidth[MAX_TOPBAR_ZONES]); \ - NOBACKUP(uint8_t view); -#else -#define CUSTOM_SCREENS_DATA \ - uint8_t screensType SKIP; /* 2bits per screen (None/Gauges/Numbers/Script) */ \ - TelemetryScreenData screens[MAX_TELEMETRY_SCREENS]; \ - uint8_t view; -#endif - #if defined(PCBX9D) || defined(PCBX9DP) || defined(PCBX9E) // telemetry sensor idx + 1 #define TOPBAR_DATA \ @@ -669,6 +651,11 @@ struct RGBLedColor { }; #if defined(FUNCTION_SWITCHES) +enum booleanEnum { + BOOL_OFF, + BOOL_ON +}; + PACK(struct customSwitch { CUST_IDX(sw, cfs_idx_read, cfs_idx_write); NOBACKUP(char name[LEN_SWITCH_NAME]); @@ -835,7 +822,27 @@ PACK(struct ModelData { TARANIS_PCBX9E_FIELD(uint8_t toplcdTimer) - CUSTOM_SCREENS_DATA +#if defined(COLORLCD) +#if defined(YAML_GENERATOR) + NOBACKUP(CustomScreenData screenData[MAX_CUSTOM_SCREENS]) FUNC(screen_is_active); + NOBACKUP(TopBarPersistentData topbarData) FUNC(isAlwaysActive); +#endif + NOBACKUP(uint8_t topbarWidgetWidth[MAX_TOPBAR_ZONES]); + NOBACKUP(uint8_t view); + + void initScreenData(); + const char* getScreenLayoutId(int screenNum); + void setScreenLayoutId(int screenNum, const char* s); + TopBarPersistentData* getTopbarData(); + CustomScreenData* getScreenData(int screenNum); + LayoutPersistentData* getScreenLayoutData(int screenNum); + WidgetPersistentData* getWidgetData(int screenNum, int zoneNum); + void removeScreenLayout(int idx); +#else + uint8_t screensType SKIP; /* 2bits per screen (None/Gauges/Numbers/Script) */ + TelemetryScreenData screens[MAX_TELEMETRY_SCREENS]; + uint8_t view; +#endif char modelRegistrationID[PXX2_LEN_REGISTRATION_ID]; diff --git a/radio/src/datastructs_radio.cpp b/radio/src/datastructs_radio.cpp new file mode 100644 index 000000000..c54cb2001 --- /dev/null +++ b/radio/src/datastructs_radio.cpp @@ -0,0 +1,87 @@ +/* + * 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 "edgetx.h" +#include "hal/adc_driver.h" +#include "hal/switch_driver.h" +#include "tasks/mixer_task.h" + +char* RadioData::getSwitchCustomName(uint8_t n) +{ + return switchConfig[n].name; +} + +bool RadioData::switchHasCustomName(uint8_t n) +{ + return switchConfig[n].name[0] != 0; +} + +SwitchConfig RadioData::switchType(uint8_t n) { + return (SwitchConfig)switchConfig[n].type; +} + +void RadioData::switchSetType(uint8_t n, SwitchConfig v) { + switchConfig[n].type = v; + storageDirty(EE_GENERAL); +} + +char* RadioData::switchName(uint8_t n) { + return switchConfig[n].name; +} + +#if defined(FUNCTION_SWITCHES) +fsStartPositionType RadioData::switchStart(uint8_t n) { + return (fsStartPositionType)switchConfig[n].start; +} + +void RadioData::switchSetStart(uint8_t n, fsStartPositionType v) { + switchConfig[n].start = v; + storageDirty(EE_GENERAL); +} + +#if defined(FUNCTION_SWITCHES_RGB_LEDS) +RGBLedColor& RadioData::switchOnColor(uint8_t n) { + return switchConfig[n].onColor; +} + +RGBLedColor& RadioData::switchOffColor(uint8_t n) { + return switchConfig[n].offColor; +} + +bool RadioData::cfsOnColorLuaOverride(uint8_t n) { + return switchConfig[n].onColorLuaOverride; +} + +bool RadioData::cfsOffColorLuaOverride(uint8_t n) { + return switchConfig[n].offColorLuaOverride; +} + +void RadioData::cfsSetOnColorLuaOverride(uint8_t n, bool v) { + switchConfig[n].onColorLuaOverride = v; + storageDirty(EE_GENERAL); +} + +void RadioData::cfsSetOffColorLuaOverride(uint8_t n, bool v) { + switchConfig[n].offColorLuaOverride = v; + storageDirty(EE_GENERAL); +} +#endif +#endif diff --git a/radio/src/edgetx_constants.h b/radio/src/edgetx_constants.h index 626e154b5..c6e070469 100644 --- a/radio/src/edgetx_constants.h +++ b/radio/src/edgetx_constants.h @@ -52,11 +52,6 @@ enum fsStartPositionType { FS_START_PREVIOUS }; -enum booleanEnum { - BOOL_OFF, - BOOL_ON -}; - enum CalibrationState { CALIB_START, CALIB_SET_MIDPOINT, diff --git a/radio/src/gui/colorlcd/controls/gvar_numberedit.cpp b/radio/src/gui/colorlcd/controls/gvar_numberedit.cpp index 118010286..13c76e53f 100644 --- a/radio/src/gui/colorlcd/controls/gvar_numberedit.cpp +++ b/radio/src/gui/colorlcd/controls/gvar_numberedit.cpp @@ -88,11 +88,6 @@ void GVarNumberEdit::switchGVarMode() #endif } -void GVarNumberEdit::setSuffix(std::string value) -{ - num_field->setSuffix(value); -} - void GVarNumberEdit::onEvent(event_t event) { if (event == EVT_KEY_LONG(KEY_ENTER)) { diff --git a/radio/src/gui/colorlcd/controls/gvar_numberedit.h b/radio/src/gui/colorlcd/controls/gvar_numberedit.h index 521dc6fa4..2a11d584e 100644 --- a/radio/src/gui/colorlcd/controls/gvar_numberedit.h +++ b/radio/src/gui/colorlcd/controls/gvar_numberedit.h @@ -37,7 +37,6 @@ class GVarNumberEdit : public Window LcdFlags textFlags = 0, int32_t voffset = 0, int32_t vdefault = 0); void switchGVarMode(); - void setSuffix(std::string value); void setFastStep(int value) { num_field->setFastStep(value); } void setAccelFactor(int value) { num_field->setAccelFactor(value); } diff --git a/radio/src/gui/colorlcd/controls/source_numberedit.cpp b/radio/src/gui/colorlcd/controls/source_numberedit.cpp index ccc440a0e..32f28dc73 100644 --- a/radio/src/gui/colorlcd/controls/source_numberedit.cpp +++ b/radio/src/gui/colorlcd/controls/source_numberedit.cpp @@ -103,7 +103,7 @@ void SourceNumberEdit::switchSourceMode() update(); } -void SourceNumberEdit::setSuffix(std::string value) +void SourceNumberEdit::setSuffix(const std::string& value) { num_field->setSuffix(value); } diff --git a/radio/src/gui/colorlcd/controls/source_numberedit.h b/radio/src/gui/colorlcd/controls/source_numberedit.h index 3c339c608..0d4533940 100644 --- a/radio/src/gui/colorlcd/controls/source_numberedit.h +++ b/radio/src/gui/colorlcd/controls/source_numberedit.h @@ -38,7 +38,7 @@ class SourceNumberEdit : public Window int32_t vdefault = 0); void switchSourceMode(); - void setSuffix(std::string value); + void setSuffix(const std::string& value); void setFastStep(int value) { num_field->setFastStep(value); } void setAccelFactor(int value) { num_field->setAccelFactor(value); } diff --git a/radio/src/gui/colorlcd/layouts/layout1+2.cpp b/radio/src/gui/colorlcd/layouts/layout1+2.cpp index c1184529f..b2de73190 100644 --- a/radio/src/gui/colorlcd/layouts/layout1+2.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1+2.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_FULL, LAYOUT_MAP_HALF, @@ -29,5 +28,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory Layout1P2("Layout1P2", "1 + 2", - defaultZoneOptions, + defaultLayoutOptions, 3, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout1+3.cpp b/radio/src/gui/colorlcd/layouts/layout1+3.cpp index d8fe608fd..e086ce546 100644 --- a/radio/src/gui/colorlcd/layouts/layout1+3.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1+3.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_HALF, LAYOUT_MAP_FULL, @@ -30,5 +29,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory Layout1P3("Layout1P3", "1 + 3", - defaultZoneOptions, + defaultLayoutOptions, 4, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout1+4.cpp b/radio/src/gui/colorlcd/layouts/layout1+4.cpp index 29289c2b7..5687824d9 100644 --- a/radio/src/gui/colorlcd/layouts/layout1+4.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1+4.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_HALF, LAYOUT_MAP_FULL, @@ -30,5 +29,5 @@ static const uint8_t zmap[] = { LAYOUT_MAP_HALF, LAYOUT_MAP_3QTR, LAYOUT_MAP_HALF, LAYOUT_MAP_1QTR, }; -BaseLayoutFactory Layout1P4("Layout1P4", "1 + 4", defaultZoneOptions, 5, +BaseLayoutFactory Layout1P4("Layout1P4", "1 + 4", defaultLayoutOptions, 5, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout1x1.cpp b/radio/src/gui/colorlcd/layouts/layout1x1.cpp index 555379b00..1c07010da 100644 --- a/radio/src/gui/colorlcd/layouts/layout1x1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1x1.cpp @@ -20,12 +20,12 @@ */ #include "layout.h" -#include "layout_factory_impl.h" +#include "translations/translations.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_FULL, LAYOUT_MAP_FULL, }; BaseLayoutFactory layout1x1("Layout1x1", STR_WIDGET_FULLSCREEN, - defaultZoneOptions, + defaultLayoutOptions, 1, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout1x1AppMode.cpp b/radio/src/gui/colorlcd/layouts/layout1x1AppMode.cpp index d63632b79..9353eaa3e 100644 --- a/radio/src/gui/colorlcd/layouts/layout1x1AppMode.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1x1AppMode.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" const LayoutOption OPTIONS_LAYOUT_APPMODE[] = {LAYOUT_OPTIONS_END}; @@ -28,9 +27,9 @@ class LayoutAppMode : public Layout { public: LayoutAppMode(Window* parent, const LayoutFactory* factory, - Layout::PersistentData* persistentData, uint8_t zoneCount, + int screenNum, uint8_t zoneCount, uint8_t* zoneMap) : - Layout(parent, factory, persistentData, zoneCount, zoneMap) + Layout(parent, factory, screenNum, zoneCount, zoneMap) { } diff --git a/radio/src/gui/colorlcd/layouts/layout1x2.cpp b/radio/src/gui/colorlcd/layouts/layout1x2.cpp index 01c5964a3..1d355c2cb 100644 --- a/radio/src/gui/colorlcd/layouts/layout1x2.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1x2.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_FULL, LAYOUT_MAP_HALF, @@ -28,5 +27,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory Layout1x2("Layout1x2", "1 x 2", - defaultZoneOptions, + defaultLayoutOptions, 2, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout1x3.cpp b/radio/src/gui/colorlcd/layouts/layout1x3.cpp index d886f2d1a..c8894f6e8 100644 --- a/radio/src/gui/colorlcd/layouts/layout1x3.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1x3.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_FULL, LAYOUT_MAP_1THIRD, @@ -29,5 +28,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory Layout1x3("Layout1x3", "1 x 3", - defaultZoneOptions, + defaultLayoutOptions, 3, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout1x4.cpp b/radio/src/gui/colorlcd/layouts/layout1x4.cpp index 94bc3cac1..6de643e98 100644 --- a/radio/src/gui/colorlcd/layouts/layout1x4.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1x4.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_FULL, LAYOUT_MAP_1QTR, @@ -30,5 +29,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory Layout1x4("Layout1x4", "1 x 4", - defaultZoneOptions, + defaultLayoutOptions, 4, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout2+1.cpp b/radio/src/gui/colorlcd/layouts/layout2+1.cpp index 6c2c5b17a..71e132314 100644 --- a/radio/src/gui/colorlcd/layouts/layout2+1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2+1.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_HALF, LAYOUT_MAP_0, LAYOUT_MAP_HALF, LAYOUT_MAP_FULL, // ordered to match previous implementation @@ -29,7 +28,7 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory layout2P1("Layout2P1", "2 + 1", - defaultZoneOptions, + defaultLayoutOptions, 3, (uint8_t*)zmap); const LayoutFactory* defaultLayout = &layout2P1; diff --git a/radio/src/gui/colorlcd/layouts/layout2+3.cpp b/radio/src/gui/colorlcd/layouts/layout2+3.cpp index b582e5241..81d92755c 100644 --- a/radio/src/gui/colorlcd/layouts/layout2+3.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2+3.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_HALF, LAYOUT_MAP_HALF, @@ -31,5 +30,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory Layout2P3("Layout2P3", "2 + 3", - defaultZoneOptions, + defaultLayoutOptions, 5, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout2x1.cpp b/radio/src/gui/colorlcd/layouts/layout2x1.cpp index 9570999b8..3acc51277 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x1.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_HALF, LAYOUT_MAP_FULL, @@ -28,5 +27,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory Layout2x1("Layout2x1", "2 x 1", - defaultZoneOptions, + defaultLayoutOptions, 2, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout2x2.cpp b/radio/src/gui/colorlcd/layouts/layout2x2.cpp index ffe2574ce..680070669 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x2.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x2.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_HALF, LAYOUT_MAP_HALF, @@ -30,5 +29,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory layout2x2("Layout2x2", "2 x 2", - defaultZoneOptions, + defaultLayoutOptions, 4, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout2x3.cpp b/radio/src/gui/colorlcd/layouts/layout2x3.cpp index 865051418..7fe73e532 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x3.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x3.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_HALF, LAYOUT_MAP_1THIRD, @@ -32,5 +31,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory layout2x3("Layout2x3", "2 x 3", - defaultZoneOptions, + defaultLayoutOptions, 6, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout2x4.cpp b/radio/src/gui/colorlcd/layouts/layout2x4.cpp index 0806c8e23..e0210da0d 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x4.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x4.cpp @@ -20,14 +20,14 @@ */ #include "layout.h" -#include "layout_factory_impl.h" +#include "translations/translations.h" const LayoutOption OPTIONS_LAYOUT_2x4[] = { LAYOUT_COMMON_OPTIONS, - {STR_DEF(STR_PANEL1_BACKGROUND), ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, - {STR_DEF(STR_PANEL_COLOR), ZoneOption::Color, RGB2FLAGS(77, 112, 203)}, - {STR_DEF(STR_PANEL2_BACKGROUND), ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, - {STR_DEF(STR_PANEL_COLOR), ZoneOption::Color, RGB2FLAGS(77, 112, 203)}, + {STR_DEF(STR_PANEL1_BACKGROUND), LayoutOption::Bool, true}, + {STR_DEF(STR_PANEL_COLOR), LayoutOption::Color, RGB2FLAGS(77, 112, 203)}, + {STR_DEF(STR_PANEL2_BACKGROUND), LayoutOption::Bool, true}, + {STR_DEF(STR_PANEL_COLOR), LayoutOption::Color, RGB2FLAGS(77, 112, 203)}, LAYOUT_OPTIONS_END}; class Layout2x4 : public Layout @@ -41,9 +41,9 @@ class Layout2x4 : public Layout }; Layout2x4(Window* parent, const LayoutFactory* factory, - Layout::PersistentData* persistentData, uint8_t zoneCount, + int screenNum, uint8_t zoneCount, uint8_t* zoneMap) : - Layout(parent, factory, persistentData, zoneCount, zoneMap) + Layout(parent, factory, screenNum, zoneCount, zoneMap) { panel1 = lv_obj_create(lvobj); lv_obj_set_style_bg_opa(panel1, LV_OPA_COVER, LV_PART_MAIN); diff --git a/radio/src/gui/colorlcd/layouts/layout4+2.cpp b/radio/src/gui/colorlcd/layouts/layout4+2.cpp index 14396d43d..ebb02ee16 100644 --- a/radio/src/gui/colorlcd/layouts/layout4+2.cpp +++ b/radio/src/gui/colorlcd/layouts/layout4+2.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_HALF, LAYOUT_MAP_1QTR, @@ -32,5 +31,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory layout4P2("Layout4P2", "4 + 2", - defaultZoneOptions, + defaultLayoutOptions, 6, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout4+2b.cpp b/radio/src/gui/colorlcd/layouts/layout4+2b.cpp index d9556ece2..d77f5f3c1 100644 --- a/radio/src/gui/colorlcd/layouts/layout4+2b.cpp +++ b/radio/src/gui/colorlcd/layouts/layout4+2b.cpp @@ -20,7 +20,6 @@ */ #include "layout.h" -#include "layout_factory_impl.h" static const uint8_t zmap[] = { LAYOUT_MAP_0, LAYOUT_MAP_0, LAYOUT_MAP_HALF, LAYOUT_MAP_1QTR, @@ -32,5 +31,5 @@ static const uint8_t zmap[] = { }; BaseLayoutFactory layout4P2B("Layout4P2B", "4 + 2B", - defaultZoneOptions, + defaultLayoutOptions, 6, (uint8_t*)zmap); diff --git a/radio/src/gui/colorlcd/layouts/layout4x2.cpp b/radio/src/gui/colorlcd/layouts/layout4x2.cpp index dd8f40633..d3686eb0b 100644 --- a/radio/src/gui/colorlcd/layouts/layout4x2.cpp +++ b/radio/src/gui/colorlcd/layouts/layout4x2.cpp @@ -20,17 +20,17 @@ */ #include "layout.h" -#include "layout_factory_impl.h" +#include "translations/translations.h" // 4x2 layout: 4 rows, 2 columns // Suitable for portrait screens and vertical screen usage const LayoutOption OPTIONS_LAYOUT_4x2[] = { LAYOUT_COMMON_OPTIONS, - {STR_DEF(STR_PANEL1_BACKGROUND), ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, - {STR_DEF(STR_PANEL_COLOR), ZoneOption::Color, RGB2FLAGS(77, 112, 203)}, - {STR_DEF(STR_PANEL2_BACKGROUND), ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, - {STR_DEF(STR_PANEL_COLOR), ZoneOption::Color, RGB2FLAGS(77, 112, 203)}, + {STR_DEF(STR_PANEL1_BACKGROUND), LayoutOption::Bool, true}, + {STR_DEF(STR_PANEL_COLOR), LayoutOption::Color, RGB2FLAGS(77, 112, 203)}, + {STR_DEF(STR_PANEL2_BACKGROUND), LayoutOption::Bool, true}, + {STR_DEF(STR_PANEL_COLOR), LayoutOption::Color, RGB2FLAGS(77, 112, 203)}, LAYOUT_OPTIONS_END}; class Layout4x2 : public Layout @@ -44,9 +44,9 @@ class Layout4x2 : public Layout }; Layout4x2(Window* parent, const LayoutFactory* factory, - Layout::PersistentData* persistentData, uint8_t zoneCount, + int screenNum, uint8_t zoneCount, uint8_t* zoneMap) : - Layout(parent, factory, persistentData, zoneCount, zoneMap) + Layout(parent, factory, screenNum, zoneCount, zoneMap) { panel1 = lv_obj_create(lvobj); lv_obj_set_style_bg_opa(panel1, LV_OPA_COVER, LV_PART_MAIN); diff --git a/radio/src/gui/colorlcd/layouts/layout6x1.cpp b/radio/src/gui/colorlcd/layouts/layout6x1.cpp index 4255821e2..5ebb7e722 100644 --- a/radio/src/gui/colorlcd/layouts/layout6x1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout6x1.cpp @@ -20,15 +20,15 @@ */ #include "layout.h" -#include "layout_factory_impl.h" +#include "translations/translations.h" // 6x1 layout: 6 rows, 1 column // Single column with 6 vertical zones const LayoutOption OPTIONS_LAYOUT_6x1[] = { LAYOUT_COMMON_OPTIONS, - {STR_DEF(STR_PANEL_BACKGROUND), ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, - {STR_DEF(STR_PANEL_COLOR), ZoneOption::Color, RGB2FLAGS(50, 50, 50)}, + {STR_DEF(STR_PANEL_BACKGROUND), LayoutOption::Bool, true}, + {STR_DEF(STR_PANEL_COLOR), LayoutOption::Color, RGB2FLAGS(50, 50, 50)}, LAYOUT_OPTIONS_END}; class Layout6x1 : public Layout @@ -40,9 +40,9 @@ class Layout6x1 : public Layout }; Layout6x1(Window* parent, const LayoutFactory* factory, - Layout::PersistentData* persistentData, uint8_t zoneCount, + int screenNum, uint8_t zoneCount, uint8_t* zoneMap) : - Layout(parent, factory, persistentData, zoneCount, zoneMap) + Layout(parent, factory, screenNum, zoneCount, zoneMap) { panel = lv_obj_create(lvobj); lv_obj_set_style_bg_opa(panel, LV_OPA_COVER, LV_PART_MAIN); diff --git a/radio/src/gui/colorlcd/libui/numberedit.h b/radio/src/gui/colorlcd/libui/numberedit.h index 95b1e34b2..1f63d50e2 100644 --- a/radio/src/gui/colorlcd/libui/numberedit.h +++ b/radio/src/gui/colorlcd/libui/numberedit.h @@ -50,19 +50,19 @@ class NumberEdit : public TextButton void setAccelFactor(int value) { accelFactor = value; } void setValue(int value); - void setPrefix(std::string value) + void setPrefix(const std::string& value) { prefix = std::move(value); update(); } - void setSuffix(std::string value) + void setSuffix(const std::string& value) { suffix = std::move(value); update(); } - void setZeroText(std::string value) + void setZeroText(const std::string& value) { zeroText = std::move(value); update(); diff --git a/radio/src/gui/colorlcd/libui/textedit.cpp b/radio/src/gui/colorlcd/libui/textedit.cpp index cb14b21c0..f62e00d60 100644 --- a/radio/src/gui/colorlcd/libui/textedit.cpp +++ b/radio/src/gui/colorlcd/libui/textedit.cpp @@ -195,6 +195,18 @@ ModelTextEdit::ModelTextEdit(Window* parent, const rect_t& rect, char* value, { } +ModelStringEdit::ModelStringEdit(Window* parent, const rect_t& rect, std::string value, + std::function updateHandler) : + TextEdit(parent, rect, txt, MAX_STR_EDIT_LEN, + [=]() { + if (updateHandler) updateHandler(txt); + storageDirty(EE_MODEL); + }) +{ + strncpy(txt, value.c_str(), length); + update(); +} + RadioTextEdit::RadioTextEdit(Window* parent, const rect_t& rect, char* value, uint8_t length) : TextEdit(parent, rect, value, length, diff --git a/radio/src/gui/colorlcd/libui/textedit.h b/radio/src/gui/colorlcd/libui/textedit.h index 3133d2e69..937d9733c 100644 --- a/radio/src/gui/colorlcd/libui/textedit.h +++ b/radio/src/gui/colorlcd/libui/textedit.h @@ -52,6 +52,18 @@ class ModelTextEdit : public TextEdit uint8_t length, std::function updateHandler = nullptr); }; +class ModelStringEdit : public TextEdit +{ + public: + ModelStringEdit(Window* parent, const rect_t& rect, std::string value, + std::function updateHandler); + + static constexpr int MAX_STR_EDIT_LEN = 255; + + protected: + char txt[MAX_STR_EDIT_LEN+1]; +}; + class RadioTextEdit : public TextEdit { public: diff --git a/radio/src/gui/colorlcd/mainview/datastructs_screen.h b/radio/src/gui/colorlcd/mainview/datastructs_screen.h new file mode 100644 index 000000000..d5b56b6e5 --- /dev/null +++ b/radio/src/gui/colorlcd/mainview/datastructs_screen.h @@ -0,0 +1,213 @@ +/* + * 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 + +#if !defined(BACKUP) +#include +#include +#endif + +#include "etx_lv_theme.h" + +struct WidgetOption; + +//----------------------------------------------------------------------------- + +enum WidgetOptionAlign +{ + ALIGN_LEFT, + ALIGN_CENTER, + ALIGN_RIGHT, + + // this one MUST be last + ALIGN_COUNT +}; + +enum WidgetOptionValueEnum { + WOV_Unsigned=0, + WOV_Signed, + WOV_Bool, + WOV_String, + WOV_Source, + WOV_Color +}; + +#define WIDGET_OPTION_VALUE_SIGNED(x) WidgetOptionValue{ .signedValue = (x) } +#define WIDGET_OPTION_VALUE_STRING(...) WidgetOptionValue{ .stringValue = { __VA_ARGS__ } } + +struct WidgetOptionValue +{ +#if defined(YAML_GENERATOR) + CUST_ATTR(unsignedValue, r_wov_unsigned, w_wov_unsigned); + CUST_ATTR(signedValue, r_wov_signed, w_wov_signed); + CUST_ATTR(boolValue, r_wov_unsigned, w_wov_unsigned); + CUST_ATTR(stringValue, r_wov_string, w_wov_string); + CUST_ATTR(source, r_wov_source, w_wov_source); + CUST_ATTR(color, r_wov_color, w_wov_color); +#else + union { + uint32_t unsignedValue; + int32_t signedValue; + uint32_t boolValue; + }; +#if !defined(BACKUP) + std::string stringValue; +#endif +#endif +}; + +struct WidgetOptionValueTyped +{ +#if defined(YAML_GENERATOR) + CUST_ATTR(type, r_wov_type, w_wov_type); +#else + WidgetOptionValueEnum type; +#endif + WidgetOptionValue value FUNC(select_wov); +}; + +//----------------------------------------------------------------------------- + +#define MAX_WIDGET_OPTIONS 50 // For YAML parser + +struct WidgetPersistentData { +#if defined(YAML_GENERATOR) + WidgetOptionValueTyped options[MAX_WIDGET_OPTIONS] FUNC(widget_option_is_active); +#else +#if !defined(BACKUP) + std::vector options; + void addEntry(int idx); + bool hasOption(int idx); + void setDefault(int idx, const WidgetOption* opt, bool forced); + void clear(); + WidgetOptionValueEnum getType(int idx); + void setType(int idx, WidgetOptionValueEnum typ); + int32_t getSignedValue(int idx); + void setSignedValue(int idx, int32_t newValue); + uint32_t getUnsignedValue(int idx); + void setUnsignedValue(int idx, uint32_t newValue); + bool getBoolValue(int idx); + void setBoolValue(int idx, bool newValue); + std::string getString(int idx); + void setString(int idx, const char* s); +#endif +#endif +}; + +//----------------------------------------------------------------------------- + +enum LayoutOptionValueEnum { + LOV_None=0, + LOV_Bool, + LOV_Color +}; + +union LayoutOptionValue +{ +#if defined(YAML_GENERATOR) + CUST_ATTR(unsignedValue, r_lov_unsigned, w_lov_unsigned); + CUST_ATTR(boolValue, r_lov_unsigned, w_lov_unsigned); + CUST_ATTR(color, r_lov_color, w_lov_color); +#else + uint32_t unsignedValue; + uint32_t boolValue; +#endif +}; + +struct LayoutOptionValueTyped +{ +#if defined(YAML_GENERATOR) + CUST_ATTR(type, r_lov_type, w_lov_type); +#else + LayoutOptionValueEnum type; +#endif + LayoutOptionValue value FUNC(select_lov); +}; + +#define MAX_LAYOUT_ZONES 10 +#define MAX_LAYOUT_OPTIONS 10 + +struct ZonePersistentData { +#if defined(YAML_GENERATOR) + CUST_ATTR(widgetName, r_widget_name, w_widget_name); +#else +#if !defined(BACKUP) + std::string widgetName; +#endif +#endif + WidgetPersistentData widgetData FUNC(isAlwaysActive); +#if !defined(YAML_GENERATOR) + void clear(); +#endif +}; + +struct LayoutPersistentData { + ZonePersistentData zones[MAX_LAYOUT_ZONES] FUNC(widget_is_active); + LayoutOptionValueTyped options[MAX_LAYOUT_OPTIONS] FUNC(layout_option_is_active); +#if !defined(YAML_GENERATOR) + void clearZone(int idx); + void clear(); + const char* getWidgetName(int idx); + void setWidgetName(int idx, const char* s); + WidgetPersistentData* getWidgetData(int idx); + bool hasWidget(int idx); +#endif +}; + +//----------------------------------------------------------------------------- + +struct CustomScreenData { +#if defined(YAML_GENERATOR) + CUST_ATTR(LayoutId, r_screen_id, w_screen_id); +#else +#if !defined(BACKUP) + std::string LayoutId; +#endif +#endif + LayoutPersistentData layoutData FUNC(isAlwaysActive); +}; + +//----------------------------------------------------------------------------- + +static LAYOUT_VAL_SCALED(MENU_HEADER_BUTTONS_LEFT, 47) + +#if LCD_W == 800 // TODO: handle this better +static constexpr int TOPBAR_ZONE_WIDTH = 102; +#else +static LAYOUT_VAL_SCALED(TOPBAR_ZONE_WIDTH, 70) +#endif +static constexpr int MAX_TOPBAR_ZONES = (LCD_W - MENU_HEADER_BUTTONS_LEFT - 1 + TOPBAR_ZONE_WIDTH / 2) / TOPBAR_ZONE_WIDTH; + +struct TopBarPersistentData { + ZonePersistentData zones[MAX_TOPBAR_ZONES] FUNC(widget_is_active); +#if !defined(YAML_GENERATOR) + void clearZone(int idx); + void clear(); + const char* getWidgetName(int idx); + void setWidgetName(int idx, const char* s); + WidgetPersistentData* getWidgetData(int idx); + bool hasWidget(int idx); + bool isWidget(int idx, const char* s); +#endif +}; + +//----------------------------------------------------------------------------- diff --git a/radio/src/gui/colorlcd/mainview/layout.cpp b/radio/src/gui/colorlcd/mainview/layout.cpp index 6f0732579..c4c1a523a 100644 --- a/radio/src/gui/colorlcd/mainview/layout.cpp +++ b/radio/src/gui/colorlcd/mainview/layout.cpp @@ -20,11 +20,60 @@ */ #include "edgetx.h" -#include "topbar_impl.h" +#include "topbar.h" #include "view_main.h" +#include "widget.h" WidgetsContainer* customScreens[MAX_CUSTOM_SCREENS] = {}; +const LayoutOption defaultLayoutOptions[] = {LAYOUT_COMMON_OPTIONS, + LAYOUT_OPTIONS_END}; + +//----------------------------------------------------------------------------- + +void ZonePersistentData::clear() +{ + widgetName[0] = 0; + widgetData.clear(); +} + +void LayoutPersistentData::clearZone(int idx) +{ + zones[idx].clear(); +} + +void LayoutPersistentData::clear() +{ + for (int i = 0; i < MAX_LAYOUT_ZONES; i += 1) + clearZone(i); + for (int i = 0; i < MAX_LAYOUT_OPTIONS; i += 1) { + options[i].type = LOV_None; + options[i].value.unsignedValue = 0; + } +} + +const char* LayoutPersistentData::getWidgetName(int idx) +{ + return zones[idx].widgetName.c_str(); +} + +void LayoutPersistentData::setWidgetName(int idx, const char* s) +{ + zones[idx].widgetName = s; +} + +WidgetPersistentData* LayoutPersistentData::getWidgetData(int idx) +{ + return &zones[idx].widgetData; +} + +bool LayoutPersistentData::hasWidget(int idx) +{ + return zones[idx].widgetName[0] != 0; +} + +//----------------------------------------------------------------------------- + std::list& LayoutFactory::getRegisteredLayouts() { static std::list layouts; @@ -46,11 +95,11 @@ const LayoutFactory* LayoutFactory::getLayoutFactory(const char* name) // Loads a layout, but does not attach it to any window // WidgetsContainer* LayoutFactory::loadLayout( - Window* parent, const char* name, LayoutPersistentData* persistentData) + Window* parent, int screenNum) { - const LayoutFactory* factory = getLayoutFactory(name); + const LayoutFactory* factory = getLayoutFactory(g_model.getScreenLayoutId(screenNum)); if (factory) { - return factory->load(parent, persistentData); + return factory->load(parent, screenNum); } return nullptr; } @@ -74,13 +123,12 @@ void LayoutFactory::deleteCustomScreens(bool clearTopBar) void LayoutFactory::loadDefaultLayout() { auto& screen = customScreens[0]; - auto& screenData = g_model.screenData[0]; if (screen == nullptr && defaultLayout != nullptr) { - strcpy(screenData.LayoutId, defaultLayout->getId()); + g_model.setScreenLayoutId(0, defaultLayout->getId()); auto viewMain = ViewMain::instance(); - screen = defaultLayout->create(viewMain, &screenData.layoutData); + screen = defaultLayout->create(viewMain, 0); // // TODO: // -> attach a few default widgets @@ -103,8 +151,7 @@ void LayoutFactory::loadCustomScreens() while (i < MAX_CUSTOM_SCREENS) { auto& screen = customScreens[i]; - screen = loadLayout(viewMain, g_model.screenData[i].LayoutId, - &g_model.screenData[i].layoutData); + screen = loadLayout(viewMain, i); if (!screen) { // no more layouts @@ -145,7 +192,6 @@ WidgetsContainer* LayoutFactory::createCustomScreen( if (customScreenIndex >= MAX_CUSTOM_SCREENS) return nullptr; auto& screen = customScreens[customScreenIndex]; - auto& screenData = g_model.screenData[customScreenIndex]; if (screen != nullptr) { screen->deleteLater(true, false); @@ -153,37 +199,265 @@ WidgetsContainer* LayoutFactory::createCustomScreen( } auto viewMain = ViewMain::instance(); - screen = create(viewMain, &screenData.layoutData); + screen = create(viewMain, customScreenIndex); if (!screen) return nullptr; viewMain->addMainView(screen, customScreenIndex); - auto dst = g_model.screenData[customScreenIndex].LayoutId; - auto src = getId(); - strncpy(dst, src, sizeof(CustomScreenData::LayoutId)); + g_model.setScreenLayoutId(customScreenIndex, getId()); return screen; } -void LayoutFactory::disposeCustomScreen(unsigned idx) -{ - // move custom screen data - if (idx >= MAX_CUSTOM_SCREENS) { - return; - } - - auto dst = &g_model.screenData[idx]; - auto src = dst + 1; - auto len = sizeof(CustomScreenData) * (MAX_CUSTOM_SCREENS - idx - 1); - memmove(dst, src, len); - - dst = &g_model.screenData[MAX_CUSTOM_SCREENS - 1]; - len = sizeof(CustomScreenData); - memset(dst, 0, len); -} - -LayoutFactory::LayoutFactory(const char* id, const char* name) : - id(id), name(name) +LayoutFactory::LayoutFactory(const char* id, const char* name, const LayoutOption * options, uint8_t zoneCount, uint8_t* zoneMap) : + id(id), name(name), options(options), zoneCount(zoneCount), zoneMap(zoneMap) { getRegisteredLayouts().push_back(this); + + bitmap = (MaskBitmap*)malloc(align32(BM_W * BM_H + sizeof(MaskBitmap))); + bitmap->width = BM_W; + bitmap->height = BM_H; + + uint8_t* bm = (uint8_t*)bitmap->data; + memset(bm, 0, BM_W * BM_H); + + memset(bm, 0xFF, BM_W); + memset(bm+((BM_H-1)*BM_W), 0xFF, BM_W); + + for (int y = 1; y < BM_H - 1; y += 1) { + bm[y*BM_W] = 0xFF; + bm[y*BM_W+BM_W-1] = 0xFF; + } + + for (int i = 0; i < zoneCount * 4; i += 4) { + uint8_t xo = BM_W * zoneMap[i] / LAYOUT_MAP_DIV; + uint8_t yo = BM_H * zoneMap[i+1] / LAYOUT_MAP_DIV; + uint8_t w = BM_W * zoneMap[i+2] / LAYOUT_MAP_DIV; + uint8_t h = (BM_H * zoneMap[i+3] + LAYOUT_MAP_DIV/2) / LAYOUT_MAP_DIV; + + if (yo > 0) + memset(bm+(yo*BM_W+xo), 0xFF, w); + if (xo > 0) { + for (int y = 0; y < h; y += 1) { + bm[(yo+y)*BM_W+xo] = 0xFF; + } + } + } } + +LayoutFactory::~LayoutFactory() +{ + if (bitmap) { + free((void*)bitmap); + bitmap = nullptr; + } +} + +inline LayoutOptionValueEnum layoutValueEnumFromType(LayoutOption::Type type) +{ + switch(type) { + case LayoutOption::Bool: + return LOV_Bool; + + case LayoutOption::Color: + return LOV_Color; + + default: + return LOV_None; + } +} + +void LayoutFactory::initPersistentData(int screenNum, bool setDefault) const +{ + auto layoutData = g_model.getScreenLayoutData(screenNum); + + if (setDefault) { + layoutData->clear(); + } + if (options) { + int i = 0; + for (const LayoutOption* option = options; option->name; option++, i++) { + // TODO compiler bug? The CPU freezes ... persistentData->options[i++] + // = option->deflt; + auto optVal = &layoutData->options[i]; + if (setDefault) { + memcpy(&optVal->value, &option->deflt, sizeof(LayoutOptionValue)); + } + optVal->type = layoutValueEnumFromType(option->type); + } + } +} + +WidgetsContainer* LayoutFactory::create(Window* parent, int screenNum) const +{ + initPersistentData(screenNum, true); + return createNew(parent, screenNum); +} + +WidgetsContainer* LayoutFactory::load(Window* parent, int screenNum) const +{ + initPersistentData(screenNum, false); + Layout* layout = createNew(parent, screenNum); + if (layout) + layout->load(); + return layout; +} + +//----------------------------------------------------------------------------- + +Layout::Layout(Window* parent, const LayoutFactory* factory, + int screenNum, uint8_t zoneCount, + uint8_t* zoneMap) : + WidgetsContainer(parent, {0, 0, LCD_W, LCD_H}, zoneCount), + factory(factory), + decoration(new ViewMainDecoration(this)), + zoneMap(zoneMap), screenNum(screenNum) +{ + setWindowFlag(NO_FOCUS); + show(true); +} + +void Layout::setTrimsVisible(bool visible) +{ + decoration->setTrimsVisible(visible); +} + +void Layout::setSlidersVisible(bool visible) +{ + decoration->setSlidersVisible(visible); +} + +void Layout::setFlightModeVisible(bool visible) +{ + decoration->setFlightModeVisible(visible); +} + +void Layout::show(bool visible) +{ + // Set visible decoration + setSlidersVisible(visible && hasSliders()); + setTrimsVisible(visible && hasTrims()); + setFlightModeVisible(visible && hasFlightMode()); + + if (visible) { + // and update relevant windows + updateZones(); + } +} + +rect_t Layout::getMainZone() const +{ + rect_t zone = decoration->getMainZone(); + if (hasSliders() || hasTrims() || hasFlightMode()) { + // some decoration activated + zone.x += PAD_LARGE; + zone.y += PAD_LARGE; + zone.w -= 2 * PAD_LARGE; + zone.h -= 2 * PAD_LARGE; + } + return ViewMain::instance()->getMainZone(zone, hasTopbar()); +} + +rect_t Layout::getZone(unsigned int index) const +{ + rect_t z = getMainZone(); + + unsigned int i = index * 4; + + coord_t xo = z.w * zoneMap[i] / LAYOUT_MAP_DIV; + coord_t yo = z.h * zoneMap[i + 1] / LAYOUT_MAP_DIV; + coord_t w = z.w * zoneMap[i + 2] / LAYOUT_MAP_DIV; + coord_t h = z.h * zoneMap[i + 3] / LAYOUT_MAP_DIV; + + if (isMirrored()) xo = z.w - xo - w; + + return {z.x + xo, z.y + yo, w, h}; +} + +void Layout::checkEvents() +{ + Window::checkEvents(); + rect_t z = getMainZone(); + if (z.x != lastMainZone.x || z.y != lastMainZone.y || z.w != lastMainZone.w || z.h != lastMainZone.h) { + lastMainZone = z; + for (int i = 0; i < zoneCount; i++) + if (widgets[i] && widgets[i]->isFullscreen()) + return; + updateZones(); + } +} + +void Layout::removeWidget(unsigned int index) +{ + if (index >= zoneCount) return; + + g_model.getScreenLayoutData(screenNum)->clearZone(index); + + WidgetsContainer::removeWidget(index); +} + +Widget* Layout::createWidget(unsigned int index, + const WidgetFactory* factory) +{ + if (index >= zoneCount) return nullptr; + + // remove old one if existing + removeWidget(index); + + Widget* widget = nullptr; + if (factory) { + g_model.getScreenLayoutData(screenNum)->setWidgetName(index, factory->getName()); + widget = factory->create(this, getZone(index), screenNum, index); + } + widgets[index] = widget; + + if (widget) widget->attach(this); + + return widget; +} + +void Layout::load() +{ + unsigned int count = getZonesCount(); + for (unsigned int i = 0; i < count; i++) { + // remove old widget + if (widgets[i]) { + widgets[i]->deleteLater(); + widgets[i] = nullptr; + } + } + + for (unsigned int i = 0; i < count; i++) { + // and load new one if required + if (g_model.getScreenLayoutData(screenNum)->hasWidget(i)) { + widgets[i] = WidgetFactory::newWidget(g_model.getScreenLayoutData(screenNum)->getWidgetName(i), this, getZone(i), screenNum, i); + } + } +} + +LayoutOptionValue* Layout::getOptionValue(unsigned int index) const +{ + return &g_model.getScreenLayoutData(screenNum)->options[index].value; +} + +bool Layout::hasTopbar() const { + return getOptionValue(LAYOUT_OPTION_TOPBAR)->boolValue; +} + +bool Layout::hasFlightMode() const { + return getOptionValue(LAYOUT_OPTION_FM)->boolValue; +} + +bool Layout::hasSliders() const { + return getOptionValue(LAYOUT_OPTION_SLIDERS)->boolValue; +} + +bool Layout::hasTrims() const { + return getOptionValue(LAYOUT_OPTION_TRIMS)->boolValue; +} + +bool Layout::isMirrored() const { + return getOptionValue(LAYOUT_OPTION_MIRRORED)->boolValue; +} + +//----------------------------------------------------------------------------- diff --git a/radio/src/gui/colorlcd/mainview/layout.h b/radio/src/gui/colorlcd/mainview/layout.h index 90e855ee8..5fa76be9a 100644 --- a/radio/src/gui/colorlcd/mainview/layout.h +++ b/radio/src/gui/colorlcd/mainview/layout.h @@ -21,55 +21,154 @@ #pragma once -#include - #include "definitions.h" #include "dataconstants.h" -#include "widgets_container.h" +#include "widget.h" +#include "view_main_decoration.h" + +#include + +class LayoutFactory; + +//----------------------------------------------------------------------------- struct LayoutOption { + enum Type { + Integer, + Bool, + Color, + }; + STR_TYP name; - ZoneOption::Type type; - ZoneOptionValue deflt; + LayoutOption::Type type; + LayoutOptionValue deflt; }; -#define MAX_LAYOUT_ZONES 10 -#define MAX_LAYOUT_OPTIONS 10 +// Common 'LayoutOptionValue's among all layouts +enum { + LAYOUT_OPTION_TOPBAR = 0, + LAYOUT_OPTION_FM, + LAYOUT_OPTION_SLIDERS, + LAYOUT_OPTION_TRIMS, + LAYOUT_OPTION_MIRRORED, -#if !defined(YAML_GENERATOR) -typedef WidgetsContainerPersistentData - LayoutPersistentData; -#else -struct LayoutPersistentData { - ZonePersistentData zones[MAX_LAYOUT_ZONES]; - ZoneOptionValueTyped options[MAX_LAYOUT_OPTIONS]; + LAYOUT_OPTION_LAST_DEFAULT=LAYOUT_OPTION_MIRRORED }; + +#define LAYOUT_COMMON_OPTIONS \ + {STR_DEF(STR_TOP_BAR), LayoutOption::Bool, true}, \ + {STR_DEF(STR_FLIGHT_MODE), LayoutOption::Bool, true}, \ + {STR_DEF(STR_SLIDERS), LayoutOption::Bool, true}, \ + {STR_DEF(STR_TRIMS), LayoutOption::Bool, true}, \ + {STR_DEF(STR_MIRROR), LayoutOption::Bool, false} + +#define LAYOUT_OPTIONS_END \ + { nullptr, LayoutOption::Bool } + +extern const LayoutOption defaultLayoutOptions[]; + +//----------------------------------------------------------------------------- + +#define LAYOUT_MAP_DIV 60 +#define LAYOUT_MAP_0 0 +#define LAYOUT_MAP_1QTR 15 +#define LAYOUT_MAP_1THIRD 20 +#define LAYOUT_MAP_HALF 30 +#define LAYOUT_MAP_2THIRD 40 +#define LAYOUT_MAP_3QTR 45 +#define LAYOUT_MAP_FULL 60 + +//----------------------------------------------------------------------------- + +class Layout: public WidgetsContainer +{ + friend class LayoutFactory; + + public: + Layout(Window* parent, const LayoutFactory * factory, + int screenNum, uint8_t zoneCount, uint8_t* zoneMap); + +#if defined(DEBUG_WINDOWS) + std::string getName() const override + { + return "Layout"; + } #endif + Widget* createWidget(unsigned int index, + const WidgetFactory* factory) override; + + void load(); + + LayoutOptionValue* getOptionValue(unsigned int index) const; + + const LayoutFactory * getFactory() const + { + return factory; + } + + virtual bool hasTopbar() const; + virtual bool hasFlightMode() const; + virtual bool hasSliders() const; + virtual bool hasTrims() const; + virtual bool isMirrored() const; + + // Set decoration visibility + void setTrimsVisible(bool visible); + void setSlidersVisible(bool visible); + void setFlightModeVisible(bool visible); + + // Updates settings for trims, sliders, pots, etc... + void show(bool visible = true) override; + + bool isLayout() override { return true; } + + void removeWidget(unsigned int index) override; + + protected: + const LayoutFactory * factory = nullptr; + std::unique_ptr decoration; + uint8_t* zoneMap = nullptr; + int screenNum; + rect_t lastMainZone = {0,0,0,0}; + + // Last time we refreshed the window + uint32_t lastRefresh = 0; + + // Get the available space for widgets + rect_t getMainZone() const; + + unsigned int getZonesCount() const override { return zoneCount; } + rect_t getZone(unsigned int index) const override; + + void checkEvents() override; +}; + +//----------------------------------------------------------------------------- + class LayoutFactory { public: - LayoutFactory(const char* id, const char* name); + LayoutFactory(const char* id, const char* name, const LayoutOption * options, uint8_t zoneCount, uint8_t* zoneMap); + ~LayoutFactory(); const char* getId() const { return id; } const char* getName() const { return name; } - virtual const MaskBitmap* getBitmap() const = 0; + const MaskBitmap* getBitmap() const { return bitmap; } - virtual const LayoutOption* getLayoutOptions() const = 0; + const LayoutOption * getLayoutOptions() const + { + return options; + } - virtual WidgetsContainer* create( - Window* parent, LayoutPersistentData* persistentData) const = 0; + virtual Layout* createNew(Window* parent, int screenNum) const = 0; - virtual WidgetsContainer* load( - Window* parent, LayoutPersistentData* persistentData) const = 0; + WidgetsContainer* create(Window* parent, int screenNum) const; + WidgetsContainer* load(Window* parent, int screenNum) const; - virtual void initPersistentData(LayoutPersistentData* persistentData, - bool setDefault) const = 0; - - // Remove custom screen from the model - static void disposeCustomScreen(unsigned idx); + void initPersistentData(int screenNum, bool setDefault) const; // delete all custom screens from memory static void deleteCustomScreens(bool clearTopBar = false); @@ -91,12 +190,35 @@ class LayoutFactory protected: const char* id; const char* name; + const LayoutOption * options; + uint8_t zoneCount; + uint8_t* zoneMap; + MaskBitmap * bitmap = nullptr; - static WidgetsContainer* loadLayout(Window* parent, const char* name, - LayoutPersistentData* persistentData); + static WidgetsContainer* loadLayout(Window* parent, int screenNum); static const LayoutFactory* getLayoutFactory(const char* name); }; +//----------------------------------------------------------------------------- + +template +class BaseLayoutFactory: public LayoutFactory +{ + public: + BaseLayoutFactory(const char * id, const char * name, + const LayoutOption * options, uint8_t zoneCount, uint8_t* zoneMap) : + LayoutFactory(id, name, options, zoneCount, zoneMap) + { + } + + Layout* createNew(Window* parent, int screenNum) const override + { + return new T(parent, this, screenNum, zoneCount, zoneMap); + } +}; + extern const LayoutFactory* defaultLayout; extern WidgetsContainer* customScreens[MAX_CUSTOM_SCREENS]; + +//----------------------------------------------------------------------------- diff --git a/radio/src/gui/colorlcd/mainview/layout_factory_impl.cpp b/radio/src/gui/colorlcd/mainview/layout_factory_impl.cpp deleted file mode 100644 index 62d285fb5..000000000 --- a/radio/src/gui/colorlcd/mainview/layout_factory_impl.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 "layout_factory_impl.h" - -#include "edgetx.h" -#include "sliders.h" -#include "trims.h" -#include "view_main.h" - -Layout::Layout(Window* parent, const LayoutFactory* factory, - PersistentData* persistentData, uint8_t zoneCount, - uint8_t* zoneMap) : - LayoutBase(parent, {0, 0, LCD_W, LCD_H}, persistentData), - factory(factory), - decoration(new ViewMainDecoration(this)), - zoneCount(zoneCount), - zoneMap(zoneMap) -{ - show(true); -} - -void Layout::setTrimsVisible(bool visible) -{ - decoration->setTrimsVisible(visible); -} - -void Layout::setSlidersVisible(bool visible) -{ - decoration->setSlidersVisible(visible); -} - -void Layout::setFlightModeVisible(bool visible) -{ - decoration->setFlightModeVisible(visible); -} - -void Layout::show(bool visible) -{ - // Set visible decoration - setSlidersVisible(visible && hasSliders()); - setTrimsVisible(visible && hasTrims()); - setFlightModeVisible(visible && hasFlightMode()); - - if (visible) { - // and update relevant windows - updateZones(); - } -} - -rect_t Layout::getMainZone() const -{ - rect_t zone = decoration->getMainZone(); - if (hasSliders() || hasTrims() || hasFlightMode()) { - // some decoration activated - zone.x += PAD_LARGE; - zone.y += PAD_LARGE; - zone.w -= 2 * PAD_LARGE; - zone.h -= 2 * PAD_LARGE; - } - return ViewMain::instance()->getMainZone(zone, hasTopbar()); -} - -rect_t Layout::getZone(unsigned int index) const -{ - rect_t z = getMainZone(); - - unsigned int i = index * 4; - - coord_t xo = z.w * zoneMap[i] / LAYOUT_MAP_DIV; - coord_t yo = z.h * zoneMap[i + 1] / LAYOUT_MAP_DIV; - coord_t w = z.w * zoneMap[i + 2] / LAYOUT_MAP_DIV; - coord_t h = z.h * zoneMap[i + 3] / LAYOUT_MAP_DIV; - - if (isMirrored()) xo = z.w - xo - w; - - return {z.x + xo, z.y + yo, w, h}; -} - -void Layout::checkEvents() -{ - Window::checkEvents(); - rect_t z = getMainZone(); - if (z.x != lastMainZone.x || z.y != lastMainZone.y || z.w != lastMainZone.w || z.h != lastMainZone.h) { - lastMainZone = z; - for (int i = 0; i < MAX_LAYOUT_ZONES; i++) - if (widgets[i] && widgets[i]->isFullscreen()) - return; - updateZones(); - } -} - -const LayoutOption defaultZoneOptions[] = {LAYOUT_COMMON_OPTIONS, - LAYOUT_OPTIONS_END}; diff --git a/radio/src/gui/colorlcd/mainview/layout_factory_impl.h b/radio/src/gui/colorlcd/mainview/layout_factory_impl.h deleted file mode 100644 index 4061b1a92..000000000 --- a/radio/src/gui/colorlcd/mainview/layout_factory_impl.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * 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 - -#include "audio.h" -#include "translations/translations.h" - -#include "widgets_container_impl.h" -#include "view_main_decoration.h" -#include "layout.h" - -#include - -#define LAYOUT_COMMON_OPTIONS \ - {STR_DEF(STR_TOP_BAR), ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, \ - {STR_DEF(STR_FLIGHT_MODE), ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, \ - {STR_DEF(STR_SLIDERS), ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, \ - {STR_DEF(STR_TRIMS), ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, \ - {STR_DEF(STR_MIRROR), ZoneOption::Bool, OPTION_VALUE_BOOL(false)} - -#define LAYOUT_OPTIONS_END \ - { nullptr, ZoneOption::Bool } - -typedef WidgetsContainerImpl LayoutBase; - -extern const LayoutOption defaultZoneOptions[]; - -#define LAYOUT_MAP_DIV 60 -#define LAYOUT_MAP_0 0 -#define LAYOUT_MAP_1QTR 15 -#define LAYOUT_MAP_1THIRD 20 -#define LAYOUT_MAP_HALF 30 -#define LAYOUT_MAP_2THIRD 40 -#define LAYOUT_MAP_3QTR 45 -#define LAYOUT_MAP_FULL 60 - -class Layout: public LayoutBase -{ - friend class LayoutFactory; - - public: - - Layout(Window* parent, const LayoutFactory * factory, PersistentData * persistentData, - uint8_t zoneCount, uint8_t* zoneMap); - -#if defined(DEBUG_WINDOWS) - std::string getName() const override - { - return "Layout"; - } -#endif - - void create() override {} - - const LayoutFactory * getFactory() const - { - return factory; - } - - virtual bool hasTopbar() const { - return getOptionValue(LAYOUT_OPTION_TOPBAR)->boolValue; - } - - virtual bool hasFlightMode() const { - return getOptionValue(LAYOUT_OPTION_FM)->boolValue; - } - - virtual bool hasSliders() const { - return getOptionValue(LAYOUT_OPTION_SLIDERS)->boolValue; - } - - virtual bool hasTrims() const { - return getOptionValue(LAYOUT_OPTION_TRIMS)->boolValue; - } - - virtual bool isMirrored() const { - return getOptionValue(LAYOUT_OPTION_MIRRORED)->boolValue; - } - - // Set decoration visibility - void setTrimsVisible(bool visible); - void setSlidersVisible(bool visible); - void setFlightModeVisible(bool visible); - - // Updates settings for trims, sliders, pots, etc... - void show(bool visible = true) override; - - bool isLayout() override { return true; } - - protected: - const LayoutFactory * factory = nullptr; - std::unique_ptr decoration; - uint8_t zoneCount; - uint8_t* zoneMap = nullptr; - rect_t lastMainZone = {0,0,0,0}; - - // Last time we refreshed the window - uint32_t lastRefresh = 0; - - // Get the available space for widgets - rect_t getMainZone() const; - - unsigned int getZonesCount() const override { return zoneCount; } - rect_t getZone(unsigned int index) const override; - - void checkEvents() override; -}; - -template -class BaseLayoutFactory: public LayoutFactory -{ - public: - BaseLayoutFactory(const char * id, const char * name, - const LayoutOption * options, uint8_t zoneCount, uint8_t* zoneMap): - LayoutFactory(id, name), - options(options), - zoneCount(zoneCount), - zoneMap(zoneMap) - { - bitmap = (MaskBitmap*)malloc(align32(BM_W * BM_H + sizeof(MaskBitmap))); - bitmap->width = BM_W; - bitmap->height = BM_H; - - uint8_t* bm = (uint8_t*)bitmap->data; - memset(bm, 0, BM_W * BM_H); - - memset(bm, 0xFF, BM_W); - memset(bm+((BM_H-1)*BM_W), 0xFF, BM_W); - - for (int y = 1; y < BM_H - 1; y += 1) { - bm[y*BM_W] = 0xFF; - bm[y*BM_W+BM_W-1] = 0xFF; - } - - for (int i = 0; i < zoneCount * 4; i += 4) { - uint8_t xo = BM_W * zoneMap[i] / LAYOUT_MAP_DIV; - uint8_t yo = BM_H * zoneMap[i+1] / LAYOUT_MAP_DIV; - uint8_t w = BM_W * zoneMap[i+2] / LAYOUT_MAP_DIV; - uint8_t h = (BM_H * zoneMap[i+3] + LAYOUT_MAP_DIV/2) / LAYOUT_MAP_DIV; - - if (yo > 0) - memset(bm+(yo*BM_W+xo), 0xFF, w); - if (xo > 0) { - for (int y = 0; y < h; y += 1) { - bm[(yo+y)*BM_W+xo] = 0xFF; - } - } - } - } - - ~BaseLayoutFactory() - { - if (bitmap) { - free((void*)bitmap); - bitmap = nullptr; - } - } - - const MaskBitmap* getBitmap() const override { return bitmap; } - - const LayoutOption * getLayoutOptions() const override - { - return options; - } - - Layout * create(Window* parent, Layout::PersistentData * persistentData) const override - { - initPersistentData(persistentData, true); - Layout * layout = new T(parent, this, persistentData, zoneCount, zoneMap); - if (layout) { - layout->create(); - } - return layout; - } - - Layout * load(Window* parent, Layout::PersistentData * persistentData) const override - { - initPersistentData(persistentData, false); - Layout * layout = new T(parent, this, persistentData, zoneCount, zoneMap); - if (layout) { - layout->load(); - } - return layout; - } - - void initPersistentData(Layout::PersistentData* persistentData, - bool setDefault) const override - { - if (setDefault) { - memset(persistentData, 0, sizeof(Layout::PersistentData)); - } - if (options) { - int i = 0; - for (const LayoutOption* option = options; option->name; option++, i++) { - TRACE("LayoutFactory::initPersistentData() setting option '%s'", - STR_VAL(option->name)); - // TODO compiler bug? The CPU freezes ... persistentData->options[i++] - // = option->deflt; - auto optVal = &persistentData->options[i]; - if (setDefault) { - memcpy(&optVal->value, &option->deflt, sizeof(ZoneOptionValue)); - } - optVal->type = zoneValueEnumFromType(option->type); - } - } - } - - protected: - MaskBitmap * bitmap = nullptr; - const LayoutOption * options; - uint8_t zoneCount; - uint8_t* zoneMap; -}; diff --git a/radio/src/gui/colorlcd/mainview/screen_setup.cpp b/radio/src/gui/colorlcd/mainview/screen_setup.cpp index aa1a1d585..2e5ca5e94 100644 --- a/radio/src/gui/colorlcd/mainview/screen_setup.cpp +++ b/radio/src/gui/colorlcd/mainview/screen_setup.cpp @@ -24,7 +24,7 @@ #include #include "color_picker.h" -#include "layout_factory_impl.h" +#include "layout.h" #include "edgetx.h" #include "topbar.h" #include "view_main.h" @@ -150,7 +150,7 @@ void ScreenSetupPage::build(Window* window) clearLayoutOptions(); // If screen is not App Mode then save option values - auto layoutData = &g_model.screenData[customScreenIndex].layoutData; + auto layoutData = g_model.getScreenLayoutData(customScreenIndex); auto layout = (Layout*)customScreens[customScreenIndex]; bool restoreOptions = false; bool hasTopbar = true, hasFM = true, hasSliders = true, hasTrims = true, isMirrored = false; @@ -204,7 +204,7 @@ void ScreenSetupPage::build(Window* window) Window* btn = new TextButton(line, rect_t{}, STR_REMOVE_SCREEN, [=]() -> uint8_t { // Remove this screen from the model - LayoutFactory::disposeCustomScreen(customScreenIndex); + g_model.removeScreenLayout(customScreenIndex); // Delete all custom screens LayoutFactory::deleteCustomScreens(); @@ -247,8 +247,8 @@ void ScreenSetupPage::buildLayoutOptions() int index = 0; for (auto* option = factory->getLayoutOptions(); option->name; option++, index++) { - auto layoutData = &g_model.screenData[customScreenIndex].layoutData; - ZoneOptionValue* value = &layoutData->options[index].value; + auto layoutData = g_model.getScreenLayoutData(customScreenIndex); + LayoutOptionValue* value = &layoutData->options[index].value; // Option label auto line = layoutOptions->newLine(grid); @@ -256,7 +256,7 @@ void ScreenSetupPage::buildLayoutOptions() // Option value switch (option->type) { - case ZoneOption::Bool: + case LayoutOption::Bool: new ToggleSwitch(line, rect_t{}, GET_DEFAULT(value->boolValue), [=](int newValue) { @@ -265,7 +265,7 @@ void ScreenSetupPage::buildLayoutOptions() }); break; - case ZoneOption::Color: + case LayoutOption::Color: new ColorPicker(line, rect_t{}, GET_SET_DEFAULT(value->unsignedValue)); break; diff --git a/radio/src/gui/colorlcd/mainview/screen_user_interface.cpp b/radio/src/gui/colorlcd/mainview/screen_user_interface.cpp index eb3d4b96a..704fc0a65 100644 --- a/radio/src/gui/colorlcd/mainview/screen_user_interface.cpp +++ b/radio/src/gui/colorlcd/mainview/screen_user_interface.cpp @@ -23,7 +23,6 @@ #include "file_preview.h" #include "theme_manager.h" -#include "topbar_impl.h" #include "view_main.h" #if LANDSCAPE diff --git a/radio/src/gui/colorlcd/mainview/screen_user_interface.h b/radio/src/gui/colorlcd/mainview/screen_user_interface.h index c26f6cb7d..dc6c0cd32 100644 --- a/radio/src/gui/colorlcd/mainview/screen_user_interface.h +++ b/radio/src/gui/colorlcd/mainview/screen_user_interface.h @@ -22,7 +22,7 @@ #pragma once #include "pagegroup.h" -#include "widgets_container.h" +#include "topbar.h" class ThemeView; class Choice; diff --git a/radio/src/gui/colorlcd/mainview/topbar.cpp b/radio/src/gui/colorlcd/mainview/topbar.cpp index 4129a00fb..8c964ef08 100644 --- a/radio/src/gui/colorlcd/mainview/topbar.cpp +++ b/radio/src/gui/colorlcd/mainview/topbar.cpp @@ -25,12 +25,52 @@ #include "edgetx.h" #include "storage/storage.h" #include "etx_lv_theme.h" -#include "topbar_impl.h" +#include "topbar.h" #include "view_main.h" #include "widgets_setup.h" #include "pagegroup.h" +#include "theme_manager.h" +#include "widget.h" -TopBar* TopbarFactory::create(Window* parent) { return new TopBar(parent); } +//----------------------------------------------------------------------------- + +void TopBarPersistentData::clearZone(int idx) +{ + zones[idx].clear(); +} + +void TopBarPersistentData::clear() +{ + for (int i = 0; i < MAX_TOPBAR_ZONES; i += 1) + clearZone(i); +} + +const char* TopBarPersistentData::getWidgetName(int idx) +{ + return zones[idx].widgetName.c_str(); +} + +void TopBarPersistentData::setWidgetName(int idx, const char* s) +{ + zones[idx].widgetName = s; +} + +WidgetPersistentData* TopBarPersistentData::getWidgetData(int idx) +{ + return &zones[idx].widgetData; +} + +bool TopBarPersistentData::hasWidget(int idx) +{ + return !zones[idx].widgetName.empty(); +} + +bool TopBarPersistentData::isWidget(int idx, const char* s) +{ + return zones[idx].widgetName == s; +} + +//----------------------------------------------------------------------------- SetupTopBarWidgetsPage::SetupTopBarWidgetsPage() : Window(ViewMain::instance(), rect_t{}) @@ -92,3 +132,154 @@ void SetupTopBarWidgetsPage::onEvent(event_t event) Window::onEvent(event); #endif } + +//----------------------------------------------------------------------------- + +constexpr uint32_t TOPBAR_REFRESH = 1000 / 10; // 10 Hz + +TopBar::TopBar(Window * parent) : + WidgetsContainer(parent, {0, 0, LCD_W, EdgeTxStyles::MENU_HEADER_HEIGHT}, MAX_TOPBAR_ZONES) +{ + setWindowFlag(NO_FOCUS); + etx_solid_bg(lvobj, COLOR_THEME_SECONDARY1_INDEX); + + headerIcon = new HeaderIcon(parent, ICON_EDGETX, [=]() { ViewMain::instance()->openMenu(); }); +} + +unsigned int TopBar::getZonesCount() const +{ + unsigned int zc = 0; + for (int i = 0; i < zoneCount; i += 1) + if (g_model.topbarWidgetWidth[i] > 0) + zc += 1; + return zc; +} + +rect_t TopBar::getZone(unsigned int index) const +{ + coord_t x = MENU_HEADER_BUTTONS_LEFT + 1; + + for (unsigned int i = 0; i < index; i += 1) + x += (g_model.topbarWidgetWidth[i] * (TOPBAR_ZONE_WIDTH + PAD_TINY)); + + coord_t size = ((g_model.topbarWidgetWidth[index] - 1) * (TOPBAR_ZONE_WIDTH + PAD_TINY) + TOPBAR_ZONE_WIDTH); + + if ((x + size) > LCD_W) size = LCD_W - x; + + return {x, PAD_THREE, size, TOPBAR_ZONE_HEIGHT}; +} + +void TopBar::setVisible(float visible) // 0.0 -> 1.0 +{ + coord_t y = 0; + if (visible == 0.0) { + y = -EdgeTxStyles::MENU_HEADER_HEIGHT; + } else if (visible > 0.0 && visible < 1.0){ + y = -(float)EdgeTxStyles::MENU_HEADER_HEIGHT * (1.0 - visible); + } + if (y != top()) setTop(y); +} + +void TopBar::setEdgeTxButtonVisible(float visible) // 0.0 -> 1.0 +{ + coord_t y = 0; + if (visible == 0.0) { + y = -EdgeTxStyles::MENU_HEADER_HEIGHT; + } else if (visible > 0.0 && visible < 1.0){ + y = -(float)EdgeTxStyles::MENU_HEADER_HEIGHT * (1.0 - visible); + } + if (y != headerIcon->top()) headerIcon->setTop(y); +} + +coord_t TopBar::getVisibleHeight(float visible) const // 0.0 -> 1.0 +{ + if (visible == 0.0) { + return 0; + } + else if (visible == 1.0) { + return EdgeTxStyles::MENU_HEADER_HEIGHT; + } + + float h = (float)EdgeTxStyles::MENU_HEADER_HEIGHT * visible; + return (coord_t)h; +} + +void TopBar::checkEvents() +{ + uint32_t now = lv_tick_get(); + if (now - lastRefresh >= TOPBAR_REFRESH) { + lastRefresh = now; + WidgetsContainer::checkEvents(); + } +} + +void TopBar::removeWidget(unsigned int index) +{ + if (index >= zoneCount) return; + + bool mark = false; + + // If user manually removes 'system' widgets, mark name so widget does not get reloaded on restart + if ((index == (unsigned int)(zoneCount - 1)) && g_model.getTopbarData()->isWidget(index, "Date Time")) + mark = true; + if ((index == (unsigned int)(zoneCount - 2)) && g_model.getTopbarData()->isWidget(index, "Radio Info")) + mark = true; +#if defined(INTERNAL_GPS) + if ((index == (unsigned int)(zoneCount - 3)) && g_model.getTopbarData()->isWidget(index, "Internal GPS")) + mark = true; +#endif + + // If user manually removes 'system' widgets, mark name so widget does not get reloaded on restart + if (mark) + g_model.getTopbarData()->setWidgetName(index, "---"); + + g_model.getTopbarData()->clearZone(index); + + WidgetsContainer::removeWidget(index); +} + +void TopBar::load() +{ + unsigned int count = getZonesCount(); + for (unsigned int i = 0; i < count; i++) { + // remove old widget + if (widgets[i]) { + widgets[i]->deleteLater(); + widgets[i] = nullptr; + } + } + + for (unsigned int i = 0; i < count; i++) { + // and load new one if required + if (g_model.getTopbarData()->hasWidget(i)) { + widgets[i] = WidgetFactory::newWidget(g_model.getTopbarData()->getWidgetName(i), this, getZone(i), -1, i); + } + } +} + +Widget* TopBar::createWidget(unsigned int index, + const WidgetFactory* factory) +{ + if (index >= zoneCount) return nullptr; + + // remove old one if existing + removeWidget(index); + + Widget* widget = nullptr; + if (factory) { + g_model.getTopbarData()->setWidgetName(index, factory->getName()); + widget = factory->create(this, getZone(index), -1, index); + } + widgets[index] = widget; + + if (widget) widget->attach(this); + + return widget; +} + +void TopBar::create() +{ + g_model.getTopbarData()->clear(); +} + +//----------------------------------------------------------------------------- diff --git a/radio/src/gui/colorlcd/mainview/topbar.h b/radio/src/gui/colorlcd/mainview/topbar.h index 20ae95694..b04d638d6 100644 --- a/radio/src/gui/colorlcd/mainview/topbar.h +++ b/radio/src/gui/colorlcd/mainview/topbar.h @@ -23,14 +23,9 @@ #include "layout.h" -class ScreenMenu; -class TopBar; +class HeaderIcon; -class TopbarFactory -{ - public: - static TopBar* create(Window* parent); -}; +//----------------------------------------------------------------------------- class SetupTopBarWidgetsPage : public Window { @@ -46,3 +41,48 @@ class SetupTopBarWidgetsPage : public Window void onEvent(event_t event) override; void deleteLater(bool detach = true, bool trash = true) override; }; + +//----------------------------------------------------------------------------- + +class TopBar: public WidgetsContainer +{ + public: + explicit TopBar(Window * parent); + +#if defined(DEBUG_WINDOWS) + std::string getName() const override + { + return "TopBar"; + } +#endif + + unsigned int getZonesCount() const override; + + rect_t getZone(unsigned int index) const override; + + void setVisible(float visible); + void setEdgeTxButtonVisible(float visible); + coord_t getVisibleHeight(float visible) const; // 0.0 -> 1.0 + + void checkEvents() override; + + bool isTopBar() override { return true; } + + void removeWidget(unsigned int index) override; + + Widget* createWidget(unsigned int index, const WidgetFactory* factory) override; + + void create(); + + void load(); + + static LAYOUT_VAL_SCALED(HDR_DATE_XO, 48) + + static constexpr coord_t TOPBAR_ZONE_HEIGHT = EdgeTxStyles::MENU_HEADER_HEIGHT - 2 * PAD_THREE; + + protected: + uint32_t lastRefresh = 0; + HeaderIcon* headerIcon = nullptr; +}; + +//----------------------------------------------------------------------------- diff --git a/radio/src/gui/colorlcd/mainview/topbar_impl.cpp b/radio/src/gui/colorlcd/mainview/topbar_impl.cpp deleted file mode 100644 index 52378f87b..000000000 --- a/radio/src/gui/colorlcd/mainview/topbar_impl.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 "topbar_impl.h" -#include "edgetx.h" -#include "theme_manager.h" -#include "view_main.h" - -constexpr uint32_t TOPBAR_REFRESH = 1000 / 10; // 10 Hz - -TopBar::TopBar(Window * parent) : - TopBarBase(parent, {0, 0, LCD_W, EdgeTxStyles::MENU_HEADER_HEIGHT}, &g_model.topbarData) -{ - etx_solid_bg(lvobj, COLOR_THEME_SECONDARY1_INDEX); - - headerIcon = new HeaderIcon(parent, ICON_EDGETX, [=]() { ViewMain::instance()->openMenu(); }); -} - -unsigned int TopBar::getZonesCount() const -{ - unsigned int zoneCount = 0; - for (int i = 0; i < MAX_TOPBAR_ZONES; i += 1) - if (g_model.topbarWidgetWidth[i] > 0) - zoneCount += 1; - return zoneCount; -} - -rect_t TopBar::getZone(unsigned int index) const -{ - coord_t x = MENU_HEADER_BUTTONS_LEFT + 1; - - for (unsigned int i = 0; i < index; i += 1) - x += (g_model.topbarWidgetWidth[i] * (TOPBAR_ZONE_WIDTH + PAD_TINY)); - - coord_t size = ((g_model.topbarWidgetWidth[index] - 1) * (TOPBAR_ZONE_WIDTH + PAD_TINY) + TOPBAR_ZONE_WIDTH); - - if ((x + size) > LCD_W) size = LCD_W - x; - - return {x, PAD_THREE, size, TOPBAR_ZONE_HEIGHT}; -} - -void TopBar::setVisible(float visible) // 0.0 -> 1.0 -{ - coord_t y = 0; - if (visible == 0.0) { - y = -EdgeTxStyles::MENU_HEADER_HEIGHT; - } else if (visible > 0.0 && visible < 1.0){ - y = -(float)EdgeTxStyles::MENU_HEADER_HEIGHT * (1.0 - visible); - } - if (y != top()) setTop(y); -} - -void TopBar::setEdgeTxButtonVisible(float visible) // 0.0 -> 1.0 -{ - coord_t y = 0; - if (visible == 0.0) { - y = -EdgeTxStyles::MENU_HEADER_HEIGHT; - } else if (visible > 0.0 && visible < 1.0){ - y = -(float)EdgeTxStyles::MENU_HEADER_HEIGHT * (1.0 - visible); - } - if (y != headerIcon->top()) headerIcon->setTop(y); -} - -coord_t TopBar::getVisibleHeight(float visible) const // 0.0 -> 1.0 -{ - if (visible == 0.0) { - return 0; - } - else if (visible == 1.0) { - return EdgeTxStyles::MENU_HEADER_HEIGHT; - } - - float h = (float)EdgeTxStyles::MENU_HEADER_HEIGHT * visible; - return (coord_t)h; -} - -void TopBar::checkEvents() -{ - uint32_t now = lv_tick_get(); - if (now - lastRefresh >= TOPBAR_REFRESH) { - lastRefresh = now; - TopBarBase::checkEvents(); - } -} - -void TopBar::removeWidget(unsigned int index) -{ - bool mark = false; - - // If user manually removes 'system' widgets, mark name so widget does not get reloaded on restart - if ((index == MAX_TOPBAR_ZONES - 1) && (strncmp(persistentData->zones[index].widgetName, "Date Time", WIDGET_NAME_LEN) == 0)) - mark = true; - if ((index == MAX_TOPBAR_ZONES - 2) && (strncmp(persistentData->zones[index].widgetName, "Radio Info", WIDGET_NAME_LEN) == 0)) - mark = true; -#if defined(INTERNAL_GPS) - if ((index == MAX_TOPBAR_ZONES - 3) && (strncmp(persistentData->zones[index].widgetName, "Internal GPS", WIDGET_NAME_LEN) == 0)) - mark = true; -#endif - - WidgetsContainerImpl::removeWidget(index); - - // If user manually removes 'system' widgets, mark name so widget does not get reloaded on restart - if (mark) - strcpy(persistentData->zones[index].widgetName, "--"); -} diff --git a/radio/src/gui/colorlcd/mainview/topbar_impl.h b/radio/src/gui/colorlcd/mainview/topbar_impl.h deleted file mode 100644 index 27a68766e..000000000 --- a/radio/src/gui/colorlcd/mainview/topbar_impl.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 "topbar.h" -#include "layout_factory_impl.h" - -class HeaderIcon; - -typedef WidgetsContainerImpl TopBarBase; - -class TopBar: public TopBarBase -{ - public: - explicit TopBar(Window * parent); - -#if defined(DEBUG_WINDOWS) - std::string getName() const override - { - return "TopBar"; - } -#endif - - void load() override - { - TopBarBase::load(); - } - - unsigned int getZonesCount() const override; - - rect_t getZone(unsigned int index) const override; - - void setVisible(float visible); - void setEdgeTxButtonVisible(float visible); - coord_t getVisibleHeight(float visible) const; // 0.0 -> 1.0 - - void checkEvents() override; - - bool isTopBar() override { return true; } - - void removeWidget(unsigned int index) override; - - static LAYOUT_VAL_SCALED(HDR_DATE_XO, 48) - - static constexpr coord_t TOPBAR_ZONE_HEIGHT = EdgeTxStyles::MENU_HEADER_HEIGHT - 2 * PAD_THREE; - - protected: - uint32_t lastRefresh = 0; - HeaderIcon* headerIcon = nullptr; -}; diff --git a/radio/src/gui/colorlcd/mainview/view_main.cpp b/radio/src/gui/colorlcd/mainview/view_main.cpp index 2decdd7e5..147455d48 100644 --- a/radio/src/gui/colorlcd/mainview/view_main.cpp +++ b/radio/src/gui/colorlcd/mainview/view_main.cpp @@ -23,10 +23,11 @@ #include "model_select.h" #include "edgetx.h" -#include "topbar_impl.h" +#include "topbar.h" #include "quick_menu.h" #include "view_channels.h" #include "screen_setup.h" +#include "widget.h" static void tile_view_deleted_cb(lv_event_t* e) { @@ -94,7 +95,7 @@ ViewMain::ViewMain() : nullptr); // create last to be on top - topbar = TopbarFactory::create(this); + topbar = new TopBar(this); } ViewMain::~ViewMain() { _instance = nullptr; } @@ -408,7 +409,7 @@ bool ViewMain::hasTopbar() bool ViewMain::hasTopbar(unsigned view) { if (view < MAX_CUSTOM_SCREENS) - return g_model.screenData[view].layoutData.options[LAYOUT_OPTION_TOPBAR].value.boolValue; + return g_model.getScreenLayoutData(view)->options[LAYOUT_OPTION_TOPBAR].value.boolValue; return false; } diff --git a/radio/src/gui/colorlcd/mainview/view_main.h b/radio/src/gui/colorlcd/mainview/view_main.h index bef9b4a5d..6f7713d93 100644 --- a/radio/src/gui/colorlcd/mainview/view_main.h +++ b/radio/src/gui/colorlcd/mainview/view_main.h @@ -24,9 +24,10 @@ #include "topbar.h" #include "window.h" +class QuickMenu; class SetupWidgetsPage; class SetupTopBarWidgetsPage; -class QuickMenu; +class TopBar; class ViewMain : public NavWindow { diff --git a/radio/src/gui/colorlcd/mainview/widget.cpp b/radio/src/gui/colorlcd/mainview/widget.cpp index e3a79fa5a..fe107813b 100644 --- a/radio/src/gui/colorlcd/mainview/widget.cpp +++ b/radio/src/gui/colorlcd/mainview/widget.cpp @@ -30,11 +30,131 @@ #include "touch.h" #endif +//----------------------------------------------------------------------------- + +inline WidgetOptionValueEnum widgetValueEnumFromType(WidgetOption::Type type) +{ + switch(type) { + case WidgetOption::String: + case WidgetOption::File: + return WOV_String; + + case WidgetOption::Integer: + return WOV_Signed; + + case WidgetOption::Bool: + return WOV_Bool; + + case WidgetOption::Source: + return WOV_Source; + + case WidgetOption::Color: + return WOV_Color; + + default: + return WOV_Unsigned; + } +} + +void WidgetPersistentData::addEntry(int idx) +{ + if (idx >= (int)options.size()) { + WidgetOptionValueTyped wov; + wov.type = WOV_Unsigned; + wov.value.unsignedValue = 0; + while ((int)options.size() <= idx) + options.push_back(wov); + } +} + +bool WidgetPersistentData::hasOption(int idx) +{ + return idx < (int)options.size(); +} + +void WidgetPersistentData::setDefault(int idx, const WidgetOption* opt, bool forced) +{ + addEntry(idx); + auto optType = widgetValueEnumFromType(opt->type); + if (forced || options[idx].type != optType) { + // reset to default value + options[idx].type = optType; + memcpy((void*)&options[idx].value, (void*)&opt->deflt, sizeof(WidgetOptionValue)); + } +} + +void WidgetPersistentData::clear() +{ + options.clear(); +} + +WidgetOptionValueEnum WidgetPersistentData::getType(int idx) +{ + addEntry(idx); + return options[idx].type; +} + +void WidgetPersistentData::setType(int idx, WidgetOptionValueEnum typ) +{ + addEntry(idx); + options[idx].type = typ; +} + +int32_t WidgetPersistentData::getSignedValue(int idx) +{ + addEntry(idx); + return options[idx].value.signedValue; +} + +void WidgetPersistentData::setSignedValue(int idx, int32_t newValue) +{ + addEntry(idx); + options[idx].value.signedValue = newValue; +} + +uint32_t WidgetPersistentData::getUnsignedValue(int idx) +{ + addEntry(idx); + return options[idx].value.unsignedValue; +} + +void WidgetPersistentData::setUnsignedValue(int idx, uint32_t newValue) +{ + addEntry(idx); + options[idx].value.unsignedValue = newValue; +} + +bool WidgetPersistentData::getBoolValue(int idx) +{ + addEntry(idx); + return options[idx].value.boolValue; +} + +void WidgetPersistentData::setBoolValue(int idx, bool newValue) +{ + addEntry(idx); + options[idx].value.boolValue = newValue; +} + +std::string WidgetPersistentData::getString(int idx) +{ + addEntry(idx); + return options[idx].value.stringValue; +} + +void WidgetPersistentData::setString(int idx, const char* s) +{ + addEntry(idx); + options[idx].value.stringValue = s; +} + +//----------------------------------------------------------------------------- + Widget::Widget(const WidgetFactory* factory, Window* parent, const rect_t& rect, - WidgetPersistentData* persistentData) : + int screenNum, int zoneNum) : ButtonBase(parent, rect, nullptr, window_create), factory(factory), - persistentData(persistentData) + screenNum(screenNum), zoneNum(zoneNum) { lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_SCROLLABLE); lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICK_FOCUSABLE); @@ -146,7 +266,7 @@ bool Widget::onLongPress() return true; } -const ZoneOption* Widget::getOptionDefinitions() const +const WidgetOption* Widget::getOptionDefinitions() const { return getFactory()->getDefaultOptions(); } @@ -196,6 +316,10 @@ void Widget::enableFocus(bool enable) } } +WidgetPersistentData* Widget::getPersistentData() { return g_model.getWidgetData(screenNum, zoneNum); } + +//----------------------------------------------------------------------------- + std::list& WidgetFactory::getRegisteredWidgets() { static std::list widgets; @@ -236,35 +360,32 @@ void WidgetFactory::registerWidget(const WidgetFactory* factory) } Widget* WidgetFactory::newWidget(const char* name, Window* parent, - const rect_t& rect, - WidgetPersistentData* persistentData) + const rect_t& rect, int screenNum, int zoneNum) { const WidgetFactory* factory = getWidgetFactory(name); if (factory) { - return factory->create(parent, rect, persistentData, false); + return factory->create(parent, rect, screenNum, zoneNum, false); } return nullptr; } -void WidgetFactory::initPersistentData(Widget::PersistentData* persistentData, - bool setDefault) const +Widget* WidgetFactory::create(Window* parent, const rect_t& rect, + int screenNum, int zoneNum, + bool init) const { - if (setDefault) { - memset(persistentData, 0, sizeof(Widget::PersistentData)); + auto widgetData = g_model.getWidgetData(screenNum, zoneNum); + + if (init) { + widgetData->clear(); parseOptionDefaults(); } if (options) { int i = 0; - for (const ZoneOption* option = options; option->name; option++, i++) { - TRACE("WidgetFactory::initPersistentData() setting option '%s'", - option->name); - auto optVal = &persistentData->options[i]; - auto optType = zoneValueEnumFromType(option->type); - if (setDefault || optVal->type != optType) { - // reset to default value - memcpy(&optVal->value, &option->deflt, sizeof(ZoneOptionValue)); - optVal->type = optType; - } + for (const WidgetOption* option = options; option->name; option++, i++) { + TRACE("WidgetFactory::create() setting option '%s'", option->name); + widgetData->setDefault(i, option, init); } } + + return createNew(parent, rect, screenNum, zoneNum); } diff --git a/radio/src/gui/colorlcd/mainview/widget.h b/radio/src/gui/colorlcd/mainview/widget.h index 30f45bb01..ac63d0668 100644 --- a/radio/src/gui/colorlcd/mainview/widget.h +++ b/radio/src/gui/colorlcd/mainview/widget.h @@ -22,37 +22,69 @@ #pragma once #include - -#include +#if !defined(BACKUP) +#include +#endif #include "button.h" #include "widgets_container.h" +#include "storage/yaml/yaml_defs.h" +#include "datastructs_screen.h" class WidgetFactory; +//----------------------------------------------------------------------------- + +struct WidgetOption +{ + // First two entries must match luaScriptInputType enum + // TODO: should be cleaned up + enum Type { + Integer, + Source, + Bool, + String, + TextSize, + Timer, + Switch, + Color, + Align, + Slider, + Choice, + File, + }; + + const char * name; + Type type; + WidgetOptionValue deflt; + WidgetOptionValue min; + WidgetOptionValue max; + const char * displayName; + std::string fileSelectPath; +#if !defined(BACKUP) + std::vector choiceValues; +#endif +}; + +//----------------------------------------------------------------------------- + class Widget : public ButtonBase { public: - typedef WidgetPersistentData PersistentData; Widget(const WidgetFactory* factory, Window* parent, const rect_t& rect, - WidgetPersistentData* persistentData); + int screenNum, int zoneNum); ~Widget() override = default; const WidgetFactory* getFactory() const { return factory; } - const ZoneOption* getOptionDefinitions() const; + const WidgetOption* getOptionDefinitions() const; bool hasOptions() const { return getOptionDefinitions() && getOptionDefinitions()->name; } virtual const char* getErrorMessage() const { return nullptr; } - ZoneOptionValue* getOptionValue(unsigned int index) const - { - return &persistentData->options[index].value; - } - - PersistentData* getPersistentData() { return persistentData; } + WidgetPersistentData* getPersistentData(); #if defined(DEBUG_WINDOWS) std::string getName() const override { return "Widget"; } @@ -89,7 +121,8 @@ class Widget : public ButtonBase protected: const WidgetFactory* factory; - PersistentData* persistentData; + int screenNum; + int zoneNum; bool fullscreen = false; bool fsAllowed = true; bool closeFS = false; @@ -104,10 +137,12 @@ class Widget : public ButtonBase void openMenu(); }; +//----------------------------------------------------------------------------- + class WidgetFactory { public: - explicit WidgetFactory(const char* name, const ZoneOption* options = nullptr, + explicit WidgetFactory(const char* name, const WidgetOption* options = nullptr, const char* displayName = nullptr) : name(name), displayName(displayName), options(options) { @@ -118,7 +153,7 @@ class WidgetFactory const char* getName() const { return name; } - const ZoneOption* getDefaultOptions() const { return options; } + const WidgetOption* getDefaultOptions() const { return options; } virtual const void parseOptionDefaults() const {} const char* getDisplayName() const @@ -126,12 +161,11 @@ class WidgetFactory return displayName ? displayName : name; } - void initPersistentData(Widget::PersistentData* persistentData, - bool setDefault) const; + Widget* create(Window* parent, const rect_t& rect, + int screenNum, int zoneNum, + bool init = true) const; - virtual Widget* create(Window* parent, const rect_t& rect, - Widget::PersistentData* persistentData, - bool init = true) const = 0; + virtual Widget* createNew(Window* parent, const rect_t& rect, int screenNum, int zoneNum) const = 0; virtual bool isLuaWidgetFactory() const { return false; } @@ -140,29 +174,31 @@ class WidgetFactory static void unregisterWidget(const WidgetFactory* factory); static const WidgetFactory* getWidgetFactory(const char* name); static Widget* newWidget(const char* name, Window* parent, const rect_t& rect, - Widget::PersistentData* persistentData); + int screenNum, int zoneNum); protected: const char* name = nullptr; const char* displayName = nullptr; - const ZoneOption* options = nullptr; + const WidgetOption* options = nullptr; }; +//----------------------------------------------------------------------------- + template class BaseWidgetFactory : public WidgetFactory { public: - BaseWidgetFactory(const char* name, const ZoneOption* options, + BaseWidgetFactory(const char* name, const WidgetOption* options, const char* displayName = nullptr) : WidgetFactory(name, options, displayName) { } - Widget* create(Window* parent, const rect_t& rect, - Widget::PersistentData* persistentData, - bool init = true) const override + Widget* createNew(Window* parent, const rect_t& rect, + int screenNum, int zoneNum) const override { - initPersistentData(persistentData, init); - return new T(this, parent, rect, persistentData); + return new T(this, parent, rect, screenNum, zoneNum); } }; + +//----------------------------------------------------------------------------- diff --git a/radio/src/gui/colorlcd/mainview/widget_settings.cpp b/radio/src/gui/colorlcd/mainview/widget_settings.cpp index 9d0c17d8f..600cad989 100644 --- a/radio/src/gui/colorlcd/mainview/widget_settings.cpp +++ b/radio/src/gui/colorlcd/mainview/widget_settings.cpp @@ -53,96 +53,93 @@ WidgetSettings::WidgetSettings(Widget* w) : widget->getFactory()->parseOptionDefaults(); auto opt = widget->getOptionDefinitions(); + auto* widgetData = widget->getPersistentData(); + while (opt && opt->name != nullptr) { auto line = form->newLine(grid); new StaticText(line, rect_t{}, opt->displayName ? opt->displayName : opt->name); - auto optVal = widget->getOptionValue(optIdx); - switch (opt->type) { - case ZoneOption::Integer: + case WidgetOption::Integer: (new NumberEdit( line, rect_t{}, opt->min.signedValue, opt->max.signedValue, [=]() -> int { - return optVal->signedValue; + return widgetData->getSignedValue(optIdx); }, [=](int32_t newValue) { - optVal->signedValue = newValue; + widgetData->setSignedValue(optIdx, newValue); SET_DIRTY(); })) ->setDefault(opt->deflt.signedValue); break; - case ZoneOption::Source: + case WidgetOption::Source: new SourceChoice( line, rect_t{}, 0, MIXSRC_LAST_TELEM, [=]() -> int16_t { - return (int16_t)optVal->unsignedValue; + return widgetData->getUnsignedValue(optIdx); }, [=](int16_t newValue) { - optVal->unsignedValue = - (uint32_t)newValue; + widgetData->setUnsignedValue(optIdx, (uint32_t)newValue); SET_DIRTY(); }); break; - case ZoneOption::Bool: + case WidgetOption::Bool: new ToggleSwitch( line, rect_t{}, [=]() -> uint8_t { - return (uint8_t)optVal->boolValue; + return (uint8_t)widgetData->getBoolValue(optIdx); }, [=](int8_t newValue) { - optVal->boolValue = newValue; + widgetData->setBoolValue(optIdx, newValue); SET_DIRTY(); }); break; - case ZoneOption::String: - new ModelTextEdit(line, rect_t{}, - optVal->stringValue, - sizeof(optVal->stringValue)); + case WidgetOption::String: + new ModelStringEdit(line, rect_t{}, widgetData->getString(optIdx), + [=](const char* s) { + widgetData->setString(optIdx, s); + }); break; - case ZoneOption::TextSize: + case WidgetOption::TextSize: new Choice( line, rect_t{}, STR_FONT_SIZES, 0, FONTS_COUNT - 1, [=]() -> int { // getValue - return (int)optVal->unsignedValue; + return widgetData->getUnsignedValue(optIdx); }, [=](int newValue) { // setValue - optVal->unsignedValue = - (uint32_t)newValue; + widgetData->setUnsignedValue(optIdx, (uint32_t)newValue); SET_DIRTY(); }); break; - case ZoneOption::Align: + case WidgetOption::Align: new Choice( line, rect_t{}, STR_ALIGN_OPTS, 0, ALIGN_COUNT - 1, [=]() -> int { // getValue - return (int)optVal->unsignedValue; + return widgetData->getUnsignedValue(optIdx); }, [=](int newValue) { // setValue - optVal->unsignedValue = - (uint32_t)newValue; + widgetData->setUnsignedValue(optIdx, (uint32_t)newValue); SET_DIRTY(); }); break; - case ZoneOption::Timer: // Unsigned + case WidgetOption::Timer: // Unsigned { auto tmChoice = new Choice( line, rect_t{}, 0, TIMERS - 1, [=]() -> int { // getValue - return (int)optVal->unsignedValue; + return widgetData->getUnsignedValue(optIdx); }, [=](int newValue) { // setValue - optVal->unsignedValue = - (uint32_t)newValue; + widgetData->setUnsignedValue(optIdx, (uint32_t)newValue); SET_DIRTY(); }); @@ -151,61 +148,62 @@ WidgetSettings::WidgetSettings(Widget* w) : }); } break; - case ZoneOption::Switch: + case WidgetOption::Switch: new SwitchChoice( line, rect_t{}, opt->min.signedValue, // min opt->max.signedValue, // max [=]() -> int16_t { // getValue - return optVal->signedValue; + return widgetData->getSignedValue(optIdx); }, [=](int16_t newValue) { // setValue - optVal->signedValue = newValue; + widgetData->setSignedValue(optIdx, newValue); SET_DIRTY(); }); break; - case ZoneOption::Color: + case WidgetOption::Color: new ColorPicker( line, rect_t{}, [=]() -> uint32_t { // getValue - return optVal->unsignedValue; + return widgetData->getUnsignedValue(optIdx); }, [=](uint32_t newValue) { // setValue - optVal->unsignedValue = newValue; + widgetData->setUnsignedValue(optIdx, newValue); SET_DIRTY(); }); break; - case ZoneOption::Slider: + case WidgetOption::Slider: new Slider( line, SLIDER_W, opt->min.signedValue, opt->max.signedValue, - [=]() { return optVal->unsignedValue; }, + [=]() { + return widgetData->getUnsignedValue(optIdx); + }, [=](uint32_t newValue) { - optVal->unsignedValue = newValue; + widgetData->setUnsignedValue(optIdx, newValue); SET_DIRTY(); }); break; - case ZoneOption::Choice: + case WidgetOption::Choice: new Choice(line, rect_t{}, opt->choiceValues, 0, opt->choiceValues.size() - 1, - [=]() { return optVal->unsignedValue - 1; }, + [=]() { + return widgetData->getUnsignedValue(optIdx) - 1; + }, [=](uint32_t newValue) { - optVal->unsignedValue = newValue + 1; + widgetData->setUnsignedValue(optIdx, newValue + 1); SET_DIRTY(); }); break; - case ZoneOption::File: - new FileChoice(line, rect_t{}, opt->fileSelectPath, nullptr, LEN_ZONE_OPTION_STRING, + case WidgetOption::File: + new FileChoice(line, rect_t{}, opt->fileSelectPath, nullptr, FF_MAX_LFN, [=]() { - char s[LEN_ZONE_OPTION_STRING + 1]; - strncpy(s, optVal->stringValue, LEN_ZONE_OPTION_STRING); - s[LEN_ZONE_OPTION_STRING] = 0; - return std::string(s); + return widgetData->getString(optIdx); }, [=](std::string s) { - strncpy(optVal->stringValue, s.c_str(), LEN_ZONE_OPTION_STRING); + widgetData->setString(optIdx, s.c_str()); SET_DIRTY(); }); break; diff --git a/radio/src/gui/colorlcd/mainview/widgets_container.cpp b/radio/src/gui/colorlcd/mainview/widgets_container.cpp new file mode 100644 index 000000000..0027add38 --- /dev/null +++ b/radio/src/gui/colorlcd/mainview/widgets_container.cpp @@ -0,0 +1,93 @@ +/* + * 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 "widgets_container.h" +#include "widget.h" + +WidgetsContainer::WidgetsContainer(Window* parent, const rect_t& rect, uint8_t zoneCount) : + Window(parent, rect), zoneCount(zoneCount) +{ + widgets = new Widget*[zoneCount]; + for (int i = 0; i < zoneCount; i += 1) widgets[i] = nullptr; +} + +void WidgetsContainer::deleteLater(bool detach, bool trash) +{ + if (deleted()) return; + for (int i = 0; i < zoneCount; i += 1) + if (widgets[i]) widgets[i]->deleteLater(); + if (widgets) delete[] widgets; + widgets = nullptr; + Window::deleteLater(detach, trash); +} + +Widget* WidgetsContainer::getWidget(unsigned int index) +{ + if (index < zoneCount) return widgets[index]; + + return nullptr; +} + +void WidgetsContainer::removeWidget(unsigned int index) +{ + if (index >= zoneCount) return; + + if (widgets[index]) { + widgets[index]->deleteLater(); + } + + widgets[index] = nullptr; +} + +void WidgetsContainer::removeAllWidgets() +{ + for (unsigned int i = 0; i < zoneCount; i++) + removeWidget(i); +} + +void WidgetsContainer::updateZones() +{ + for (int i = 0; i < zoneCount; i++) { + if (widgets[i]) { + auto zone = getZone(i); + widgets[i]->setRect(zone); + widgets[i]->updateZoneRect(zone); + } + } +} + +void WidgetsContainer::showWidgets(bool visible) +{ + for (int i = 0; i < zoneCount; i++) { + if (widgets[i]) { + widgets[i]->show(visible); + } + } +} + +void WidgetsContainer::runBackground() +{ + for (int i = 0; i < zoneCount; i++) { + if (widgets[i]) { + widgets[i]->background(); + } + } +} diff --git a/radio/src/gui/colorlcd/mainview/widgets_container.h b/radio/src/gui/colorlcd/mainview/widgets_container.h index 02c4c17e4..e3e7a8a65 100644 --- a/radio/src/gui/colorlcd/mainview/widgets_container.h +++ b/radio/src/gui/colorlcd/mainview/widgets_container.h @@ -22,75 +22,34 @@ #pragma once #include "window.h" -#include "zone.h" - -#define WIDGET_NAME_LEN 20 -#define MAX_WIDGET_OPTIONS 10 - -static LAYOUT_VAL_SCALED(MENU_HEADER_BUTTONS_LEFT, 47) -#if LCD_W == 800 // TODO: handle this better -static constexpr int TOPBAR_ZONE_WIDTH = 102; -#else -static LAYOUT_VAL_SCALED(TOPBAR_ZONE_WIDTH, 70) -#endif -static constexpr int MAX_TOPBAR_ZONES = (LCD_W - MENU_HEADER_BUTTONS_LEFT - 1 + TOPBAR_ZONE_WIDTH / 2) / TOPBAR_ZONE_WIDTH; - -#define MAX_TOPBAR_OPTIONS 1 // just because of VC++ which doesn't like 0-size arrays :( - -// Common 'ZoneOptionValue's among all layouts -enum { - LAYOUT_OPTION_TOPBAR = 0, - LAYOUT_OPTION_FM, - LAYOUT_OPTION_SLIDERS, - LAYOUT_OPTION_TRIMS, - LAYOUT_OPTION_MIRRORED, - - LAYOUT_OPTION_LAST_DEFAULT=LAYOUT_OPTION_MIRRORED -}; class Widget; class WidgetFactory; -struct WidgetPersistentData { - ZoneOptionValueTyped options[MAX_WIDGET_OPTIONS] USE_IDX; -}; - -struct ZonePersistentData { - char widgetName[WIDGET_NAME_LEN]; - WidgetPersistentData widgetData; -}; - -template -struct WidgetsContainerPersistentData { - ZonePersistentData zones[N]; - ZoneOptionValueTyped options[O]; -}; - -#if !defined(YAML_GENERATOR) -typedef WidgetsContainerPersistentData TopBarPersistentData; -#else -struct TopBarPersistentData { - ZonePersistentData zones[MAX_TOPBAR_ZONES]; - ZoneOptionValueTyped options[MAX_TOPBAR_OPTIONS]; -}; -#endif - class WidgetsContainer: public Window { - public: - using Window::Window; - - virtual unsigned int getZonesCount() const = 0; - virtual rect_t getZone(unsigned int index) const = 0; - virtual Widget * createWidget(unsigned int index, const WidgetFactory * factory) = 0; - virtual Widget * getWidget(unsigned int index) = 0; - virtual void removeWidget(unsigned int index) = 0; - virtual void updateZones() = 0; - virtual void showWidgets(bool visible = true) = 0; - virtual void hideWidgets() { showWidgets(false); } - virtual void runBackground() = 0; + public: + WidgetsContainer(Window* parent, const rect_t& rect, uint8_t zoneCount); - virtual bool isLayout() { return false; } - virtual bool isAppMode() const { return false; } - bool isWidgetsContainer() override { return true; } + virtual unsigned int getZonesCount() const = 0; + virtual rect_t getZone(unsigned int index) const = 0; + virtual Widget * createWidget(unsigned int index, const WidgetFactory * factory) = 0; + + Widget* getWidget(unsigned int index); + virtual void removeWidget(unsigned int index); + void removeAllWidgets(); + void updateZones(); + void showWidgets(bool visible = true); + void hideWidgets() { showWidgets(false); } + void runBackground(); + + virtual bool isLayout() { return false; } + virtual bool isAppMode() const { return false; } + bool isWidgetsContainer() override { return true; } + + void deleteLater(bool detach = true, bool trash = true) override; + + protected: + uint8_t zoneCount = 0; + Widget** widgets = nullptr; }; diff --git a/radio/src/gui/colorlcd/mainview/widgets_container_impl.h b/radio/src/gui/colorlcd/mainview/widgets_container_impl.h deleted file mode 100644 index 3834dfa42..000000000 --- a/radio/src/gui/colorlcd/mainview/widgets_container_impl.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * 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 "strhelpers.h" -#include "widget.h" - -template -class WidgetsContainerImpl : public WidgetsContainer -{ - public: - typedef WidgetsContainerPersistentData PersistentData; - - WidgetsContainerImpl(Window* parent, const rect_t& rect, - PersistentData* persistentData) : - WidgetsContainer(parent, rect), persistentData(persistentData) - { - setWindowFlag(NO_FOCUS); - } - - Widget* createWidget(unsigned int index, - const WidgetFactory* factory) override - { - if (index >= N) return nullptr; - - // remove old one if existing - removeWidget(index); - - Widget* widget = nullptr; - if (factory) { - strAppend(persistentData->zones[index].widgetName, factory->getName(), - WIDGET_NAME_LEN); - widget = factory->create(this, getZone(index), - &persistentData->zones[index].widgetData); - } - widgets[index] = widget; - - if (widget) widget->attach(this); - - return widget; - } - - void removeWidget(unsigned int index) override - { - if (index >= N) return; - - if (widgets[index]) { - widgets[index]->deleteLater(); - } - - widgets[index] = nullptr; - memset(persistentData->zones[index].widgetName, 0, - sizeof(ZonePersistentData::widgetName)); - memset(&persistentData->zones[index].widgetData, 0, - sizeof(Widget::PersistentData)); - } - - Widget* getWidget(unsigned int index) override - { - if (index < N) return widgets[index]; - - return nullptr; - } - - virtual void create() { memset(persistentData, 0, sizeof(PersistentData)); } - - void removeAllWidgets() - { - for (unsigned int i = 0; i < N; i++) - removeWidget(i); - } - - virtual void load() - { - unsigned int count = getZonesCount(); - for (unsigned int i = 0; i < count; i++) { - // remove old widget - if (widgets[i]) { - widgets[i]->deleteLater(); - widgets[i] = nullptr; - } - } - - for (unsigned int i = 0; i < count; i++) { - // and load new one if required - if (persistentData->zones[i].widgetName[0]) { - char name[WIDGET_NAME_LEN + 1]; - memset(name, 0, sizeof(name)); - strAppend(name, persistentData->zones[i].widgetName, WIDGET_NAME_LEN); - widgets[i] = WidgetFactory::newWidget( - name, this, getZone(i), &persistentData->zones[i].widgetData); - } - } - } - - inline ZoneOptionValue* getOptionValue(unsigned int index) const - { - return &persistentData->options[index].value; - } - - unsigned int getZonesCount() const override = 0; - - rect_t getZone(unsigned int index) const override = 0; - - virtual void background() - { - for (int i = 0; i < N; i++) { - if (widgets[i]) { - widgets[i]->background(); - } - } - } - - void updateZones() override - { - for (int i = 0; i < N; i++) { - if (widgets[i]) { - auto zone = getZone(i); - widgets[i]->setRect(zone); - widgets[i]->updateZoneRect(zone); - } - } - } - - void showWidgets(bool visible = true) override - { - for (int i = 0; i < N; i++) { - if (widgets[i]) { - widgets[i]->show(visible); - } - } - } - - void runBackground() override - { - for (int i = 0; i < N; i++) { - if (widgets[i]) { - widgets[i]->background(); - } - } - } - - protected: - PersistentData* persistentData; - Widget* widgets[N] = {nullptr}; -}; diff --git a/radio/src/gui/colorlcd/mainview/zone.h b/radio/src/gui/colorlcd/mainview/zone.h deleted file mode 100644 index c7bb2390d..000000000 --- a/radio/src/gui/colorlcd/mainview/zone.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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 -#include "storage/yaml/yaml_defs.h" -#include - -#define LEN_ZONE_OPTION_STRING 12 - -#define OPTION_VALUE_UNSIGNED(x) ZoneOptionValue{ .unsignedValue = (x) } -#define OPTION_VALUE_SIGNED(x) ZoneOptionValue{ .signedValue = (x) } -#define OPTION_VALUE_BOOL(x) ZoneOptionValue{ .boolValue = (x) } -#define OPTION_VALUE_STRING(...) ZoneOptionValue{ .stringValue = { __VA_ARGS__ } } - -union ZoneOptionValue -{ - uint32_t unsignedValue; - int32_t signedValue; - uint32_t boolValue; - char stringValue[LEN_ZONE_OPTION_STRING]; - CUST_ATTR(source, r_zov_source, w_zov_source); - CUST_ATTR(color, r_zov_color, w_zov_color); -}; - -enum ZoneOptionValueEnum { - ZOV_Unsigned=0, - ZOV_Signed, - ZOV_Bool, - ZOV_String, - ZOV_Source, - ZOV_Color -}; - -struct ZoneOption -{ - // First two entries must match luaScriptInputType enum - // TODO: should be cleaned up - enum Type { - Integer, - Source, - Bool, - String, - TextSize, - Timer, - Switch, - Color, - Align, - Slider, - Choice, - File, - }; - - const char * name; - Type type; - ZoneOptionValue deflt; - ZoneOptionValue min; - ZoneOptionValue max; - const char * displayName; - std::string fileSelectPath; - std::vector choiceValues; -}; - -enum ZoneOptionAlign -{ - ALIGN_LEFT, - ALIGN_CENTER, - ALIGN_RIGHT, - - // this one MUST be last - ALIGN_COUNT -}; - -struct ZoneOptionValueTyped -{ - ZoneOptionValueEnum type; - ZoneOptionValue value FUNC(select_zov); -}; - -inline ZoneOptionValueEnum zoneValueEnumFromType(ZoneOption::Type type) -{ - switch(type) { - case ZoneOption::String: - case ZoneOption::File: - return ZOV_String; - - case ZoneOption::Integer: - return ZOV_Signed; - - case ZoneOption::Bool: - return ZOV_Bool; - - case ZoneOption::Source: - return ZOV_Source; - - case ZoneOption::Color: - return ZOV_Color; - - default: - return ZOV_Unsigned; - } -} diff --git a/radio/src/gui/colorlcd/radio/preview_window.cpp b/radio/src/gui/colorlcd/radio/preview_window.cpp index 3344b1304..b0ecba375 100644 --- a/radio/src/gui/colorlcd/radio/preview_window.cpp +++ b/radio/src/gui/colorlcd/radio/preview_window.cpp @@ -25,7 +25,7 @@ #include "sliders.h" #include "etx_lv_theme.h" #include "trims.h" -#include "topbar_impl.h" +#include "topbar.h" extern inline tmr10ms_t getTicks() { return g_tmr10ms; } diff --git a/radio/src/gui/colorlcd/radio/radio_trainer.cpp b/radio/src/gui/colorlcd/radio/radio_trainer.cpp index e7a33e1ab..04c420e31 100644 --- a/radio/src/gui/colorlcd/radio/radio_trainer.cpp +++ b/radio/src/gui/colorlcd/radio/radio_trainer.cpp @@ -116,7 +116,7 @@ void RadioTrainerPage::build(Window* form) } // Trainer calibration - auto btn = new TextButton(line, rect_t{}, std::string(STR_MENUCALIBRATION), + auto btn = new TextButton(line, rect_t{}, STR_MENUCALIBRATION, [=]() -> uint8_t { memcpy(g_eeGeneral.trainer.calib, trainerInput, sizeof(g_eeGeneral.trainer.calib)); diff --git a/radio/src/gui/colorlcd/setup_menus/menu_screen.cpp b/radio/src/gui/colorlcd/setup_menus/menu_screen.cpp index b219b75f8..ee5468d5a 100644 --- a/radio/src/gui/colorlcd/setup_menus/menu_screen.cpp +++ b/radio/src/gui/colorlcd/setup_menus/menu_screen.cpp @@ -47,20 +47,17 @@ PageDef screensMenuItems[] = { TRACE("Add screen: add screen: newIdx = %d", newIdx); auto& screen = customScreens[newIdx]; - auto& screenData = g_model.screenData[newIdx]; const LayoutFactory* factory = defaultLayout; if (factory) { TRACE("Add screen: add screen: factory = %p", factory); auto viewMain = ViewMain::instance(); - screen = factory->create(viewMain, &screenData.layoutData); + screen = factory->create(viewMain, newIdx); viewMain->addMainView(screen, newIdx); - strncpy(screenData.LayoutId, factory->getId(), - sizeof(screenData.LayoutId)); - TRACE("Add screen: add screen: LayoutId = %s", - screenData.LayoutId); + g_model.setScreenLayoutId(newIdx, factory->getId()); + TRACE("Add screen: add screen: LayoutId = %s", g_model.getScreenLayoutId(newIdx)); subMenu->onPress(newIdx + ScreenSetupPage::FIRST_SCREEN_OFFSET); diff --git a/radio/src/gui/colorlcd/setup_menus/pagegroup.cpp b/radio/src/gui/colorlcd/setup_menus/pagegroup.cpp index aa47da05c..d095d5fb4 100644 --- a/radio/src/gui/colorlcd/setup_menus/pagegroup.cpp +++ b/radio/src/gui/colorlcd/setup_menus/pagegroup.cpp @@ -24,7 +24,7 @@ #include "theme_manager.h" #include "etx_lv_theme.h" #include "view_main.h" -#include "topbar_impl.h" +#include "topbar.h" #include "model_select.h" #include "os/time.h" #include "view_channels.h" diff --git a/radio/src/gui/colorlcd/setup_menus/pagegroup.h b/radio/src/gui/colorlcd/setup_menus/pagegroup.h index 51edeef38..0b6c4fe12 100644 --- a/radio/src/gui/colorlcd/setup_menus/pagegroup.h +++ b/radio/src/gui/colorlcd/setup_menus/pagegroup.h @@ -56,7 +56,7 @@ extern PageDef toolsMenuItems[]; class PageGroupItem { public: - PageGroupItem(std::string title, QuickMenu::SubMenu subMenu = QuickMenu::NONE) : + PageGroupItem(const std::string& title, QuickMenu::SubMenu subMenu = QuickMenu::NONE) : title(std::move(title)), icon(ICON_EDGETX), quickMenuId(subMenu), padding(PAD_SMALL) {} @@ -73,7 +73,7 @@ class PageGroupItem virtual void checkEvents() {} - void setTitle(std::string value) { title = std::move(value); } + void setTitle(const std::string& value) { title = std::move(value); } std::string getTitle() const { return title; } void setIcon(EdgeTxIcon icon) { this->icon = icon; } diff --git a/radio/src/gui/colorlcd/themes/theme_manager.cpp b/radio/src/gui/colorlcd/themes/theme_manager.cpp index c30c85b52..eea8a01fd 100644 --- a/radio/src/gui/colorlcd/themes/theme_manager.cpp +++ b/radio/src/gui/colorlcd/themes/theme_manager.cpp @@ -25,7 +25,7 @@ #include "../../storage/yaml/yaml_bits.h" #include "../../storage/yaml/yaml_tree_walker.h" #include "etx_lv_theme.h" -#include "topbar_impl.h" +#include "topbar.h" #include "view_main.h" #include "storage/sdcard_yaml.h" #include "lib_file.h" @@ -429,7 +429,7 @@ bool ThemePersistance::deleteThemeByIndex(int index) return false; } -bool ThemePersistance::createNewTheme(std::string name, ThemeFile& theme) +bool ThemePersistance::createNewTheme(const std::string& name, ThemeFile& theme) { char fullPath[FF_MAX_LFN + 1]; char* s = strAppend(fullPath, THEMES_PATH, FF_MAX_LFN); diff --git a/radio/src/gui/colorlcd/themes/theme_manager.h b/radio/src/gui/colorlcd/themes/theme_manager.h index bcd25182f..8cd24ee4e 100644 --- a/radio/src/gui/colorlcd/themes/theme_manager.h +++ b/radio/src/gui/colorlcd/themes/theme_manager.h @@ -64,10 +64,10 @@ class ThemeFile return nullptr; } - void setName(std::string name) { this->name = name; } - void setAuthor(std::string author) { this->author = author; } - void setInfo(std::string info) { this->info = info; } - void setPath(std::string path) { this->path = path; } + void setName(const std::string& name) { this->name = name; } + void setAuthor(const std::string& author) { this->author = author; } + void setInfo(const std::string& info) { this->info = info; } + void setPath(const std::string& path) { this->path = path; } std::vector& getColorList() { return colorList; } void setColor(LcdColorIndex colorIndex, uint32_t color); @@ -107,7 +107,7 @@ class ThemePersistance void setDefaultTheme(int index); static char **getColorNames(); bool deleteThemeByIndex(int index); - bool createNewTheme(std::string name, ThemeFile &theme); + bool createNewTheme(const std::string& name, ThemeFile &theme); std::vector getNames() { diff --git a/radio/src/gui/colorlcd/widgets/gauge.cpp b/radio/src/gui/colorlcd/widgets/gauge.cpp index 135951498..c47e73339 100644 --- a/radio/src/gui/colorlcd/widgets/gauge.cpp +++ b/radio/src/gui/colorlcd/widgets/gauge.cpp @@ -26,8 +26,8 @@ class GaugeWidget : public Widget { public: GaugeWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, - Widget::PersistentData* persistentData) : - Widget(factory, parent, rect, persistentData) + int screenNum, int zoneNum) : + Widget(factory, parent, rect, screenNum, zoneNum) { delayLoad(); } @@ -60,9 +60,11 @@ class GaugeWidget : public Widget int16_t getGuageValue() { - mixsrc_t index = persistentData->options[0].value.unsignedValue; - int32_t min = persistentData->options[1].value.signedValue; - int32_t max = persistentData->options[2].value.signedValue; + auto widgetData = getPersistentData(); + + mixsrc_t index = widgetData->options[0].value.unsignedValue; + int32_t min = widgetData->options[1].value.signedValue; + int32_t max = widgetData->options[2].value.signedValue; int32_t value = getValue(index); @@ -80,7 +82,9 @@ class GaugeWidget : public Widget { if (!loaded) return; - mixsrc_t index = persistentData->options[0].value.unsignedValue; + auto widgetData = getPersistentData(); + + mixsrc_t index = widgetData->options[0].value.unsignedValue; sourceText->setText(getSourceString(index)); if (width() < ALIGN_MAX_W) @@ -88,10 +92,10 @@ class GaugeWidget : public Widget else lv_obj_clear_state(valueText->getLvObj(), LV_STATE_USER_1); - etx_bg_color_from_flags(bar, persistentData->options[3].value.unsignedValue); + etx_bg_color_from_flags(bar, widgetData->options[3].value.unsignedValue); } - static const ZoneOption options[]; + static const WidgetOption options[]; protected: int16_t lastValue = -10000; @@ -118,14 +122,14 @@ class GaugeWidget : public Widget static LAYOUT_VAL_SCALED(ALIGN_MAX_W, 90) }; -const ZoneOption GaugeWidget::options[] = { - {STR_SOURCE, ZoneOption::Source, OPTION_VALUE_UNSIGNED(1)}, - {STR_MIN, ZoneOption::Integer, OPTION_VALUE_SIGNED(-RESX), - OPTION_VALUE_SIGNED(-RESX), OPTION_VALUE_SIGNED(RESX)}, - {STR_MAX, ZoneOption::Integer, OPTION_VALUE_SIGNED(RESX), - OPTION_VALUE_SIGNED(-RESX), OPTION_VALUE_SIGNED(RESX)}, - {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_WARNING_INDEX)}, - {nullptr, ZoneOption::Bool}}; +const WidgetOption GaugeWidget::options[] = { + {STR_SOURCE, WidgetOption::Source, 1}, + {STR_MIN, WidgetOption::Integer, WIDGET_OPTION_VALUE_SIGNED(-RESX), + WIDGET_OPTION_VALUE_SIGNED(-RESX), WIDGET_OPTION_VALUE_SIGNED(RESX)}, + {STR_MAX, WidgetOption::Integer, WIDGET_OPTION_VALUE_SIGNED(RESX), + WIDGET_OPTION_VALUE_SIGNED(-RESX), WIDGET_OPTION_VALUE_SIGNED(RESX)}, + {STR_COLOR, WidgetOption::Color, COLOR2FLAGS(COLOR_THEME_WARNING_INDEX)}, + {nullptr, WidgetOption::Bool}}; BaseWidgetFactory gaugeWidget("Gauge", GaugeWidget::options, STR_WIDGET_GAUGE); diff --git a/radio/src/gui/colorlcd/widgets/modelbmp.cpp b/radio/src/gui/colorlcd/widgets/modelbmp.cpp index 0f3f1fa9d..4f3941cb7 100644 --- a/radio/src/gui/colorlcd/widgets/modelbmp.cpp +++ b/radio/src/gui/colorlcd/widgets/modelbmp.cpp @@ -29,10 +29,9 @@ class ModelBitmapWidget : public Widget { public: - ModelBitmapWidget(const WidgetFactory* factory, Window* parent, - const rect_t& rect, - Widget::PersistentData* persistentData) : - Widget(factory, parent, rect, persistentData) + ModelBitmapWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, + int screenNum, int zoneNum) : + Widget(factory, parent, rect, screenNum, zoneNum) { etx_obj_add_style(lvobj, styles->bg_opacity_transparent, LV_PART_MAIN); etx_obj_add_style(lvobj, styles->bg_opacity_cover, @@ -71,18 +70,20 @@ class ModelBitmapWidget : public Widget { if (!loaded) return; + auto widgetData = getPersistentData(); + isLarge = rect.h >= LARGE_H && rect.w >= LARGE_W; // get font size from options[1] etx_font(label->getLvObj(), - (FontIndex)persistentData->options[1].value.unsignedValue); + (FontIndex)widgetData->options[1].value.unsignedValue); // set font colour from options[0], if use theme color option off - if (persistentData->options[4].value.boolValue) { + if (widgetData->options[4].value.boolValue) { etx_txt_color(label->getLvObj(), COLOR_THEME_SECONDARY1_INDEX, LV_PART_MAIN); } else { - etx_txt_color_from_flags(label->getLvObj(), persistentData->options[0].value.unsignedValue); + etx_txt_color_from_flags(label->getLvObj(), widgetData->options[0].value.unsignedValue); } // Set label position @@ -92,10 +93,10 @@ class ModelBitmapWidget : public Widget lv_obj_set_pos(label->getLvObj(), 0, 0); // get fill color from options[3] - etx_bg_color_from_flags(lvobj, persistentData->options[3].value.unsignedValue); + etx_bg_color_from_flags(lvobj, widgetData->options[3].value.unsignedValue); // Set background opacity from options[2] - if (persistentData->options[2].value.boolValue) + if (widgetData->options[2].value.boolValue) lv_obj_add_state(lvobj, ETX_STATE_BG_FILL); else lv_obj_clear_state(lvobj, ETX_STATE_BG_FILL); @@ -126,7 +127,7 @@ class ModelBitmapWidget : public Widget label->show(isLarge || !image->hasImage()); } - static const ZoneOption options[]; + static const WidgetOption options[]; protected: bool isLarge = false; @@ -143,13 +144,13 @@ class ModelBitmapWidget : public Widget static LAYOUT_VAL_SCALED(LARGE_IMG_H, 38) }; -const ZoneOption ModelBitmapWidget::options[] = { - {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX)}, - {STR_SIZE, ZoneOption::TextSize, OPTION_VALUE_UNSIGNED(FONT_STD_INDEX)}, - {STR_FILL_BACKGROUND, ZoneOption::Bool, OPTION_VALUE_BOOL(false)}, - {STR_BG_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY3_INDEX)}, - {STR_USE_THEME_COLOR, ZoneOption::Bool, OPTION_VALUE_BOOL(true)}, - {nullptr, ZoneOption::Bool}}; +const WidgetOption ModelBitmapWidget::options[] = { + {STR_COLOR, WidgetOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX)}, + {STR_SIZE, WidgetOption::TextSize, FONT_STD_INDEX}, + {STR_FILL_BACKGROUND, WidgetOption::Bool, false}, + {STR_BG_COLOR, WidgetOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY3_INDEX)}, + {STR_USE_THEME_COLOR, WidgetOption::Bool, true}, + {nullptr, WidgetOption::Bool}}; BaseWidgetFactory modelBitmapWidget( "ModelBmp", ModelBitmapWidget::options, STR_WIDGET_MODELBMP); diff --git a/radio/src/gui/colorlcd/widgets/outputs.cpp b/radio/src/gui/colorlcd/widgets/outputs.cpp index 5818402d4..972254cee 100644 --- a/radio/src/gui/colorlcd/widgets/outputs.cpp +++ b/radio/src/gui/colorlcd/widgets/outputs.cpp @@ -162,9 +162,9 @@ class ChannelValue : public Window class OutputsWidget : public Widget { public: - OutputsWidget(const WidgetFactory* factory, Window* parent, - const rect_t& rect, Widget::PersistentData* persistentData) : - Widget(factory, parent, rect, persistentData) + OutputsWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, + int screenNum, int zoneNum) : + Widget(factory, parent, rect, screenNum, zoneNum) { padAll(PAD_ZERO); @@ -180,11 +180,13 @@ class OutputsWidget : public Widget void update() override { + auto widgetData = getPersistentData(); + // get background color from options[2] - etx_bg_color_from_flags(lvobj, persistentData->options[2].value.unsignedValue); + etx_bg_color_from_flags(lvobj, widgetData->options[2].value.unsignedValue); // Set background opacity from options[1] - if (persistentData->options[1].value.boolValue) + if (widgetData->options[1].value.boolValue) lv_obj_add_state(lvobj, ETX_STATE_BG_FILL); else lv_obj_clear_state(lvobj, ETX_STATE_BG_FILL); @@ -195,13 +197,13 @@ class OutputsWidget : public Widget bool changed = false; // Colors - LcdFlags f = persistentData->options[3].value.unsignedValue; + LcdFlags f = widgetData->options[3].value.unsignedValue; if (f != txtColor) { txtColor = f; changed = true; } - f = persistentData->options[4].value.unsignedValue; + f = widgetData->options[4].value.unsignedValue; if (f != barColor) { barColor = f; changed = true; } // Setup channels - uint8_t chan = persistentData->options[0].value.unsignedValue; + uint8_t chan = widgetData->options[0].value.unsignedValue; if (chan != firstChan) { firstChan= chan; changed = true; } // Get size @@ -225,7 +227,7 @@ class OutputsWidget : public Widget } } - static const ZoneOption options[]; + static const WidgetOption options[]; protected: coord_t lastWidth = -1; @@ -242,14 +244,13 @@ class OutputsWidget : public Widget static LAYOUT_VAL_SCALED(COLS_MIN_W, 300) }; -const ZoneOption OutputsWidget::options[] = { - {STR_FIRST_CHANNEL, ZoneOption::Integer, OPTION_VALUE_UNSIGNED(1), - OPTION_VALUE_UNSIGNED(1), OPTION_VALUE_UNSIGNED(32)}, - {STR_FILL_BACKGROUND, ZoneOption::Bool, OPTION_VALUE_BOOL(false)}, - {STR_BG_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY3_INDEX)}, - {STR_TEXT_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_PRIMARY1_INDEX)}, - {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX)}, - {nullptr, ZoneOption::Bool}}; +const WidgetOption OutputsWidget::options[] = { + {STR_FIRST_CHANNEL, WidgetOption::Integer, {1}, {1}, {32}}, + {STR_FILL_BACKGROUND, WidgetOption::Bool, false}, + {STR_BG_COLOR, WidgetOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY3_INDEX)}, + {STR_TEXT_COLOR, WidgetOption::Color, COLOR2FLAGS(COLOR_THEME_PRIMARY1_INDEX)}, + {STR_COLOR, WidgetOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX)}, + {nullptr, WidgetOption::Bool}}; BaseWidgetFactory outputsWidget("Outputs", OutputsWidget::options, diff --git a/radio/src/gui/colorlcd/widgets/radio_info.cpp b/radio/src/gui/colorlcd/widgets/radio_info.cpp index 500cde82c..cf0886785 100644 --- a/radio/src/gui/colorlcd/widgets/radio_info.cpp +++ b/radio/src/gui/colorlcd/widgets/radio_info.cpp @@ -23,14 +23,14 @@ #include "edgetx.h" #include "theme_manager.h" #include "widget.h" -#include "widgets_container_impl.h" +#include "layout.h" class TopBarWidget : public Widget { public: TopBarWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, - Widget::PersistentData* persistentData) : - Widget(factory, parent, rect, persistentData) + int screenNum, int zoneNum) : + Widget(factory, parent, rect, screenNum, zoneNum) { } }; @@ -38,9 +38,9 @@ class TopBarWidget : public Widget class RadioInfoWidget : public TopBarWidget { public: - RadioInfoWidget(const WidgetFactory* factory, Window* parent, - const rect_t& rect, Widget::PersistentData* persistentData) : - TopBarWidget(factory, parent, rect, persistentData) + RadioInfoWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, + int screenNum, int zoneNum) : + TopBarWidget(factory, parent, rect, screenNum, zoneNum) { // Logs logsIcon = new StaticIcon(this, W_LOG_X, PAD_THREE, ICON_DOT, @@ -113,10 +113,12 @@ class RadioInfoWidget : public TopBarWidget void update() override { + auto widgetData = getPersistentData(); + // get colors from options - etx_bg_color_from_flags(batteryFill, persistentData->options[2].value.unsignedValue, LV_PART_MAIN); - etx_bg_color_from_flags(batteryFill, persistentData->options[1].value.unsignedValue, LV_STATE_USER_1); - etx_bg_color_from_flags(batteryFill, persistentData->options[0].value.unsignedValue, LV_STATE_USER_2); + etx_bg_color_from_flags(batteryFill, widgetData->options[2].value.unsignedValue, LV_PART_MAIN); + etx_bg_color_from_flags(batteryFill, widgetData->options[1].value.unsignedValue, LV_STATE_USER_1); + etx_bg_color_from_flags(batteryFill, widgetData->options[0].value.unsignedValue, LV_STATE_USER_2); } void checkEvents() override @@ -189,7 +191,7 @@ class RadioInfoWidget : public TopBarWidget } } - static const ZoneOption options[]; + static const WidgetOption options[]; static constexpr coord_t W_AUDIO_X = 0; static LAYOUT_VAL_SCALED(W_AUDIO_SCALE_X, 15) @@ -229,11 +231,11 @@ class RadioInfoWidget : public TopBarWidget #endif }; -const ZoneOption RadioInfoWidget::options[] = { - {STR_LOW_BATT_COLOR, ZoneOption::Color, RGB2FLAGS(0xF4, 0x43, 0x36)}, - {STR_MID_BATT_COLOR, ZoneOption::Color, RGB2FLAGS(0xFF, 0xC1, 0x07)}, - {STR_HIGH_BATT_COLOR, ZoneOption::Color, RGB2FLAGS(0x4C, 0xAF, 0x50)}, - {nullptr, ZoneOption::Bool}}; +const WidgetOption RadioInfoWidget::options[] = { + {STR_LOW_BATT_COLOR, WidgetOption::Color, RGB2FLAGS(0xF4, 0x43, 0x36)}, + {STR_MID_BATT_COLOR, WidgetOption::Color, RGB2FLAGS(0xFF, 0xC1, 0x07)}, + {STR_HIGH_BATT_COLOR, WidgetOption::Color, RGB2FLAGS(0x4C, 0xAF, 0x50)}, + {nullptr, WidgetOption::Bool}}; BaseWidgetFactory RadioInfoWidget("Radio Info", RadioInfoWidget::options, STR_RADIO_INFO_WIDGET); @@ -241,9 +243,9 @@ BaseWidgetFactory RadioInfoWidget("Radio Info", RadioInfoWidget class DateTimeWidget : public TopBarWidget { public: - DateTimeWidget(const WidgetFactory* factory, Window* parent, - const rect_t& rect, Widget::PersistentData* persistentData) : - TopBarWidget(factory, parent, rect, persistentData) + DateTimeWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, + int screenNum, int zoneNum) : + TopBarWidget(factory, parent, rect, screenNum, zoneNum) { coord_t x = rect.w - HeaderDateTime::HDR_DATE_WIDTH - DT_XO; dateTime = new HeaderDateTime(this, x, PAD_THREE); @@ -252,9 +254,11 @@ class DateTimeWidget : public TopBarWidget void update() override { + auto widgetData = getPersistentData(); + // get color from options uint32_t color; - memcpy(&color, &persistentData->options[0].value.unsignedValue, sizeof(color)); + memcpy(&color, &widgetData->options[0].value.unsignedValue, sizeof(color)); dateTime->setColor(color); coord_t x = width() - HeaderDateTime::HDR_DATE_WIDTH - DT_XO; dateTime->setPos(x, PAD_THREE); @@ -263,15 +267,15 @@ class DateTimeWidget : public TopBarWidget HeaderDateTime* dateTime = nullptr; int8_t lastMinute = -1; - static const ZoneOption options[]; + static const WidgetOption options[]; // Adjustment to make main view date/time align with model/radio settings views static LAYOUT_VAL_SCALED(DT_XO, 1) }; -const ZoneOption DateTimeWidget::options[] = { - {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_PRIMARY2_INDEX)}, - {nullptr, ZoneOption::Bool}}; +const WidgetOption DateTimeWidget::options[] = { + {STR_COLOR, WidgetOption::Color, COLOR2FLAGS(COLOR_THEME_PRIMARY2_INDEX)}, + {nullptr, WidgetOption::Bool}}; BaseWidgetFactory DateTimeWidget("Date Time", DateTimeWidget::options, @@ -282,10 +286,9 @@ BaseWidgetFactory DateTimeWidget("Date Time", class InternalGPSWidget : public TopBarWidget { public: - InternalGPSWidget(const WidgetFactory* factory, Window* parent, - const rect_t& rect, - Widget::PersistentData* persistentData) : - TopBarWidget(factory, parent, rect, persistentData) + InternalGPSWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, + int screenNum, int zoneNum) : + TopBarWidget(factory, parent, rect, screenNum, zoneNum) { icon = new StaticIcon(this, width() / 2 - PAD_LARGE - PAD_TINY, ICON_H, diff --git a/radio/src/gui/colorlcd/widgets/text.cpp b/radio/src/gui/colorlcd/widgets/text.cpp index d60b707f0..894dd0573 100644 --- a/radio/src/gui/colorlcd/widgets/text.cpp +++ b/radio/src/gui/colorlcd/widgets/text.cpp @@ -22,15 +22,14 @@ #include "edgetx.h" #include "widget.h" -#define TEXT_WIDGET_DEFAULT_LABEL \ - 'M', 'y', ' ', 'L', 'a', 'b', 'e', 'l' // "My Label" +#define TEXT_WIDGET_DEFAULT_LABEL "My Label" class TextWidget : public Widget { public: TextWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, - Widget::PersistentData* persistentData) : - Widget(factory, parent, rect, persistentData) + int screenNum, int zoneNum) : + Widget(factory, parent, rect, screenNum, zoneNum) { delayLoad(); } @@ -52,7 +51,7 @@ class TextWidget : public Widget update(); } - static const ZoneOption options[]; + static const WidgetOption options[]; protected: lv_style_t style; @@ -63,38 +62,40 @@ class TextWidget : public Widget { if (!loaded) return; + auto widgetData = getPersistentData(); + // Set text value from options - lv_label_set_text(shadow, persistentData->options[0].value.stringValue); - lv_label_set_text(label, persistentData->options[0].value.stringValue); + lv_label_set_text(shadow, widgetData->options[0].value.stringValue.c_str()); + lv_label_set_text(label, widgetData->options[0].value.stringValue.c_str()); // get font color from options[1] - etx_txt_color_from_flags(label, persistentData->options[1].value.unsignedValue); + etx_txt_color_from_flags(label, widgetData->options[1].value.unsignedValue); // get font size from options[2] lv_style_set_text_font( - &style, getFont(persistentData->options[2].value.unsignedValue << 8)); + &style, getFont(widgetData->options[2].value.unsignedValue << 8)); // get alignment from options[4] - LcdFlags alignment = persistentData->options[4].value.unsignedValue; + LcdFlags alignment = widgetData->options[4].value.unsignedValue; lv_style_set_text_align(&style, (alignment == ALIGN_RIGHT) ? LV_TEXT_ALIGN_RIGHT : (alignment == ALIGN_CENTER) ? LV_TEXT_ALIGN_CENTER : LV_TEXT_ALIGN_LEFT); // Show or hide shadow - if (persistentData->options[3].value.boolValue) + if (widgetData->options[3].value.boolValue) lv_obj_clear_flag(shadow, LV_OBJ_FLAG_HIDDEN); else lv_obj_add_flag(shadow, LV_OBJ_FLAG_HIDDEN); } }; -const ZoneOption TextWidget::options[] = { - {STR_TEXT, ZoneOption::String, - OPTION_VALUE_STRING(TEXT_WIDGET_DEFAULT_LABEL)}, - {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX)}, - {STR_SIZE, ZoneOption::TextSize, OPTION_VALUE_UNSIGNED(0)}, - {STR_SHADOW, ZoneOption::Bool, OPTION_VALUE_BOOL(false)}, - {STR_ALIGNMENT, ZoneOption::Align, OPTION_VALUE_UNSIGNED(ALIGN_LEFT)}, - {nullptr, ZoneOption::Bool}}; +const WidgetOption TextWidget::options[] = { + {STR_TEXT, WidgetOption::String, + WIDGET_OPTION_VALUE_STRING(TEXT_WIDGET_DEFAULT_LABEL)}, + {STR_COLOR, WidgetOption::Color, COLOR2FLAGS(COLOR_THEME_SECONDARY1_INDEX)}, + {STR_SIZE, WidgetOption::TextSize, 0}, + {STR_SHADOW, WidgetOption::Bool, false}, + {STR_ALIGNMENT, WidgetOption::Align, ALIGN_LEFT}, + {nullptr, WidgetOption::Bool}}; BaseWidgetFactory textWidget("Text", TextWidget::options, STR_WIDGET_TEXT); diff --git a/radio/src/gui/colorlcd/widgets/timer.cpp b/radio/src/gui/colorlcd/widgets/timer.cpp index c8f655cb8..d34903476 100644 --- a/radio/src/gui/colorlcd/widgets/timer.cpp +++ b/radio/src/gui/colorlcd/widgets/timer.cpp @@ -33,8 +33,8 @@ class TimerWidget : public Widget { public: TimerWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, - Widget::PersistentData* persistentData) : - Widget(factory, parent, rect, persistentData) + int screenNum, int zoneNum) : + Widget(factory, parent, rect, screenNum, zoneNum) { delayLoad(); } @@ -109,7 +109,9 @@ class TimerWidget : public Widget Widget::checkEvents(); - uint32_t index = persistentData->options[0].value.unsignedValue; + auto widgetData = getPersistentData(); + + uint32_t index = widgetData->options[0].value.unsignedValue; TimerData& timerData = g_model.timers[index]; TimerState& timerState = timersStates[index]; @@ -196,7 +198,7 @@ class TimerWidget : public Widget } } - static const ZoneOption options[]; + static const WidgetOption options[]; static LAYOUT_VAL_SCALED(SMALL_TXT_MAX_W, 100) static LAYOUT_VAL_SCALED(SMALL_TXT_MAX_H, 40) @@ -236,10 +238,12 @@ class TimerWidget : public Widget { if (!loaded) return; + auto widgetData = getPersistentData(); + // Set up widget from options. char s[16]; - uint32_t index = persistentData->options[0].value.unsignedValue; + uint32_t index = widgetData->options[0].value.unsignedValue; TimerData& timerData = g_model.timers[index]; bool hasName = ZLEN(timerData.name) > 0; @@ -304,9 +308,9 @@ class TimerWidget : public Widget } }; -const ZoneOption TimerWidget::options[] = { - {STR_TIMER_SOURCE, ZoneOption::Timer, OPTION_VALUE_UNSIGNED(0)}, - {nullptr, ZoneOption::Bool}}; +const WidgetOption TimerWidget::options[] = { + {STR_TIMER_SOURCE, WidgetOption::Timer, 0}, + {nullptr, WidgetOption::Bool}}; BaseWidgetFactory timerWidget("Timer", TimerWidget::options, STR_WIDGET_TIMER); diff --git a/radio/src/gui/colorlcd/widgets/value.cpp b/radio/src/gui/colorlcd/widgets/value.cpp index 9c937554f..b8ef48dbf 100644 --- a/radio/src/gui/colorlcd/widgets/value.cpp +++ b/radio/src/gui/colorlcd/widgets/value.cpp @@ -30,8 +30,8 @@ class ValueWidget : public Widget { public: ValueWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, - Widget::PersistentData* persistentData) : - Widget(factory, parent, rect, persistentData) + int screenNum, int zoneNum) : + Widget(factory, parent, rect, screenNum, zoneNum) { delayLoad(); } @@ -82,8 +82,10 @@ class ValueWidget : public Widget bool changed = false; + auto widgetData = getPersistentData(); + // get source from options[0] - mixsrc_t field = persistentData->options[0].value.unsignedValue; + mixsrc_t field = widgetData->options[0].value.unsignedValue; // if value changed auto newValue = getValue(field); @@ -166,7 +168,7 @@ class ValueWidget : public Widget } } - static const ZoneOption options[]; + static const WidgetOption options[]; protected: int32_t lastValue = -10000; @@ -188,18 +190,20 @@ class ValueWidget : public Widget { if (!loaded) return; + auto widgetData = getPersistentData(); + // get source from options[0] - mixsrc_t field = persistentData->options[0].value.unsignedValue; + mixsrc_t field = widgetData->options[0].value.unsignedValue; // get color from options[1] - etx_txt_color_from_flags(label, persistentData->options[1].value.unsignedValue); - etx_txt_color_from_flags(value, persistentData->options[1].value.unsignedValue); + etx_txt_color_from_flags(label, widgetData->options[1].value.unsignedValue); + etx_txt_color_from_flags(value, widgetData->options[1].value.unsignedValue); // get label alignment from options[3] - LcdFlags lblAlign = persistentData->options[3].value.unsignedValue; + LcdFlags lblAlign = widgetData->options[3].value.unsignedValue; // get value alignment from options[4] - LcdFlags valAlign = persistentData->options[4].value.unsignedValue; + LcdFlags valAlign = widgetData->options[4].value.unsignedValue; lv_coord_t labelX = 0; lv_coord_t labelY = 0; @@ -270,7 +274,7 @@ class ValueWidget : public Widget lv_obj_set_pos(value, valueX, valueY); // Show / hide shadow - if (persistentData->options[2].value.boolValue) { + if (widgetData->options[2].value.boolValue) { lv_obj_clear_flag(labelShadow, LV_OBJ_FLAG_HIDDEN); lv_obj_clear_flag(valueShadow, LV_OBJ_FLAG_HIDDEN); } else { @@ -280,13 +284,13 @@ class ValueWidget : public Widget } }; -const ZoneOption ValueWidget::options[] = { - {STR_SOURCE, ZoneOption::Source, OPTION_VALUE_UNSIGNED(MIXSRC_FIRST_STICK)}, - {STR_COLOR, ZoneOption::Color, COLOR2FLAGS(COLOR_THEME_PRIMARY2_INDEX)}, - {STR_SHADOW, ZoneOption::Bool, OPTION_VALUE_BOOL(false)}, - {STR_ALIGN_LABEL, ZoneOption::Align, OPTION_VALUE_UNSIGNED(ALIGN_LEFT)}, - {STR_ALIGN_VALUE, ZoneOption::Align, OPTION_VALUE_UNSIGNED(ALIGN_LEFT)}, - {nullptr, ZoneOption::Bool}}; +const WidgetOption ValueWidget::options[] = { + {STR_SOURCE, WidgetOption::Source, MIXSRC_FIRST_STICK}, + {STR_COLOR, WidgetOption::Color, COLOR2FLAGS(COLOR_THEME_PRIMARY2_INDEX)}, + {STR_SHADOW, WidgetOption::Bool, false}, + {STR_ALIGN_LABEL, WidgetOption::Align, ALIGN_LEFT}, + {STR_ALIGN_VALUE, WidgetOption::Align, ALIGN_LEFT}, + {nullptr, WidgetOption::Bool}}; BaseWidgetFactory ValueWidget("Value", ValueWidget::options, STR_WIDGET_VALUE); diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 26117d83c..4d9bef519 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -3244,18 +3244,18 @@ LROT_BEGIN(etxcst, NULL, 0) LROT_NUMENTRY( FUNC_DISABLE_TOUCH, FUNC_DISABLE_TOUCH ) LROT_NUMENTRY( SHADOWED, SHADOWED ) - // ZoneType::Integer == INPUT_TYPE_VALUE - use VALUE in widget options - // ZoneType::Source == INPUT_TYPE_SOURCE - use SOURCE in widget options - LROT_NUMENTRY( COLOR, ZoneOption::Color ) - LROT_NUMENTRY( BOOL, ZoneOption::Bool ) - LROT_NUMENTRY( STRING, ZoneOption::String ) - LROT_NUMENTRY( TIMER, ZoneOption::Timer ) - LROT_NUMENTRY( TEXT_SIZE, ZoneOption::TextSize ) - LROT_NUMENTRY( ALIGNMENT, ZoneOption::Align ) - LROT_NUMENTRY( SWITCH, ZoneOption::Switch ) - LROT_NUMENTRY( SLIDER, ZoneOption::Slider ) - LROT_NUMENTRY( CHOICE, ZoneOption::Choice ) - LROT_NUMENTRY( FILE, ZoneOption::File ) + // WidgetOption::Integer == INPUT_TYPE_VALUE - use VALUE in widget options + // WidgetOption::Source == INPUT_TYPE_SOURCE - use SOURCE in widget options + LROT_NUMENTRY( COLOR, WidgetOption::Color ) + LROT_NUMENTRY( BOOL, WidgetOption::Bool ) + LROT_NUMENTRY( STRING, WidgetOption::String ) + LROT_NUMENTRY( TIMER, WidgetOption::Timer ) + LROT_NUMENTRY( TEXT_SIZE, WidgetOption::TextSize ) + LROT_NUMENTRY( ALIGNMENT, WidgetOption::Align ) + LROT_NUMENTRY( SWITCH, WidgetOption::Switch ) + LROT_NUMENTRY( SLIDER, WidgetOption::Slider ) + LROT_NUMENTRY( CHOICE, WidgetOption::Choice ) + LROT_NUMENTRY( FILE, WidgetOption::File ) LROT_NUMENTRY( MENU_HEADER_HEIGHT, COLOR2FLAGS(EdgeTxStyles::MENU_HEADER_HEIGHT) ) #else LROT_NUMENTRY( FIXEDWIDTH, FIXEDWIDTH ) diff --git a/radio/src/lua/lua_widget.cpp b/radio/src/lua/lua_widget.cpp index 9453cf6e2..d3e9402fb 100644 --- a/radio/src/lua/lua_widget.cpp +++ b/radio/src/lua/lua_widget.cpp @@ -229,10 +229,10 @@ void LuaWidget::redraw_cb(lv_event_t* e) } LuaWidget::LuaWidget(const WidgetFactory* factory, Window* parent, - const rect_t& rect, WidgetPersistentData* persistentData, + const rect_t& rect, int screenNum, int zoneNum, int zoneRectDataRef, int optionsDataRef, - int createFunctionRef, std::string path) : - Widget(factory, parent, rect, persistentData), + int createFunctionRef, const std::string& path) : + Widget(factory, parent, rect, screenNum, zoneNum), zoneRectDataRef(zoneRectDataRef), optionsDataRef(optionsDataRef), errorMessage(nullptr) { @@ -350,26 +350,23 @@ void LuaWidget::update() lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaFactory()->updateFunction); lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, luaScriptContextRef); + auto widgetData = getPersistentData(); + // Get options table and update values lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, optionsDataRef); int i = 0; - for (const ZoneOption* option = getOptionDefinitions(); option->name; option++, i++) { - auto optVal = getOptionValue(i); + for (const WidgetOption* option = getOptionDefinitions(); option->name; option++, i++) { switch (option->type) { - case ZoneOption::String: - case ZoneOption::File: - { - char str[LEN_ZONE_OPTION_STRING + 1] = {0}; - strncpy(str, optVal->stringValue, LEN_ZONE_OPTION_STRING); - lua_pushstring(lsWidgets, str); - } + case WidgetOption::String: + case WidgetOption::File: + lua_pushstring(lsWidgets, widgetData->getString(i).c_str()); break; - case ZoneOption::Integer: - case ZoneOption::Switch: - lua_pushinteger(lsWidgets, optVal->signedValue); + case WidgetOption::Integer: + case WidgetOption::Switch: + lua_pushinteger(lsWidgets, widgetData->getSignedValue(i)); break; default: - lua_pushinteger(lsWidgets, optVal->unsignedValue); + lua_pushinteger(lsWidgets, widgetData->getUnsignedValue(i)); break; } lua_setfield(lsWidgets, -2, option->name); diff --git a/radio/src/lua/lua_widget.h b/radio/src/lua/lua_widget.h index 8efb3f6d9..d88cd937a 100644 --- a/radio/src/lua/lua_widget.h +++ b/radio/src/lua/lua_widget.h @@ -108,8 +108,8 @@ class LuaWidget : public Widget, public LuaScriptManager public: LuaWidget(const WidgetFactory* factory, Window* parent, const rect_t& rect, - WidgetPersistentData* persistentData, int zoneRectDataRef, - int optionsDataRef, int createFunctionRef, std::string path); + int screenNum, int zoneNum, int zoneRectDataRef, + int optionsDataRef, int createFunctionRef, const std::string& path); ~LuaWidget() override; #if defined(DEBUG_WINDOWS) diff --git a/radio/src/lua/lua_widget_factory.cpp b/radio/src/lua/lua_widget_factory.cpp index e4c65ccea..547bce708 100644 --- a/radio/src/lua/lua_widget_factory.cpp +++ b/radio/src/lua/lua_widget_factory.cpp @@ -28,7 +28,7 @@ #define MAX_INSTRUCTIONS (20000/100) -LuaWidgetFactory::LuaWidgetFactory(const char* name, ZoneOption* widgetOptions, int optionDefinitionsReference, +LuaWidgetFactory::LuaWidgetFactory(const char* name, WidgetOption* widgetOptions, int optionDefinitionsReference, int createFunction, int updateFunction, int refreshFunction, int backgroundFunction, int translateFunction, bool lvglLayout, const char* filename) : @@ -61,12 +61,12 @@ LuaWidgetFactory::~LuaWidgetFactory() { } } -Widget* LuaWidgetFactory::create(Window* parent, const rect_t& rect, - Widget::PersistentData* persistentData, - bool init) const +Widget* LuaWidgetFactory::createNew(Window* parent, const rect_t& rect, + int screenNum, int zoneNum) const { if (lsWidgets == 0) return 0; - initPersistentData(persistentData, init); + + auto widgetData = g_model.getWidgetData(screenNum, zoneNum); luaSetInstructionsLimit(lsWidgets, MAX_INSTRUCTIONS); @@ -85,29 +85,25 @@ Widget* LuaWidgetFactory::create(Window* parent, const rect_t& rect, // Create options table lua_newtable(lsWidgets); int i = 0; - for (const ZoneOption* option = options; option->name; option++, i++) { - if (option->type == ZoneOption::String || option->type == ZoneOption::File) { + for (const WidgetOption* option = options; option->name; option++, i++) { + if (option->type == WidgetOption::String || option->type == WidgetOption::File) { lua_pushstring(lsWidgets, option->name); - // Zero-terminated string for Lua - char str[LEN_ZONE_OPTION_STRING + 1] = {0}; - strncpy(str, persistentData->options[i].value.stringValue, - LEN_ZONE_OPTION_STRING); - lua_pushstring(lsWidgets, &str[0]); + lua_pushstring(lsWidgets, widgetData->options[i].value.stringValue.c_str()); lua_settable(lsWidgets, -3); - } else if (option->type == ZoneOption::Integer || option->type == ZoneOption::Switch) { - l_pushtableint(lsWidgets, option->name, persistentData->options[i].value.signedValue); + } else if (option->type == WidgetOption::Integer || option->type == WidgetOption::Switch) { + l_pushtableint(lsWidgets, option->name, widgetData->options[i].value.signedValue); } else { - l_pushtableint(lsWidgets, option->name, persistentData->options[i].value.unsignedValue); + l_pushtableint(lsWidgets, option->name, widgetData->options[i].value.unsignedValue); } } // Store the options data in registry for later updates int optionsDataRef = luaL_ref(lsWidgets, LUA_REGISTRYINDEX); - return new LuaWidget(this, parent, rect, persistentData, zoneRectDataRef, optionsDataRef, createFunction, path); + return new LuaWidget(this, parent, rect, screenNum, zoneNum, zoneRectDataRef, optionsDataRef, createFunction, path); } -void LuaWidgetFactory::translateOptions(ZoneOption * options) +void LuaWidgetFactory::translateOptions(WidgetOption * options) { if (lsWidgets == 0) return; @@ -194,10 +190,10 @@ const void LuaWidgetFactory::parseOptionDefaults() const PROTECT_LUA() { lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, optionDefinitionsReference); - ZoneOption *option = (ZoneOption*)options; + WidgetOption *option = (WidgetOption*)options; for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2), option->name; lua_pop(lsWidgets, 1)) { - // TRACE("parsing option %d", count); + // TRACE("parseOptionDefaults parsing option %s", option->name); luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number luaL_checktype(lsWidgets, -1, LUA_TTABLE); // value is table uint8_t field = 0; @@ -206,44 +202,43 @@ const void LuaWidgetFactory::parseOptionDefaults() const luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number switch (field) { case 2: - if (option->type == ZoneOption::Switch) { + if (option->type == WidgetOption::Switch) { option->deflt.signedValue = switchValue(); - } else if (option->type == ZoneOption::Source) { + } else if (option->type == WidgetOption::Source) { option->deflt.unsignedValue = sourceValue(); - } else if (option->type == ZoneOption::Integer) { + } else if (option->type == WidgetOption::Integer) { option->deflt.signedValue = luaL_checkinteger(lsWidgets, -1); - } else if (option->type == ZoneOption::Bool) { + } else if (option->type == WidgetOption::Bool) { option->deflt.boolValue = (luaL_checkunsigned(lsWidgets, -1) != 0); - } else if (option->type == ZoneOption::String || option->type == ZoneOption::File) { - strncpy(option->deflt.stringValue, luaL_checkstring(lsWidgets, -1), - LEN_ZONE_OPTION_STRING); + } else if (option->type == WidgetOption::String || option->type == WidgetOption::File) { + option->deflt.stringValue = luaL_checkstring(lsWidgets, -1); } else { option->deflt.unsignedValue = luaL_checkunsigned(lsWidgets, -1); } break; case 3: - if (option->type == ZoneOption::Switch) { + if (option->type == WidgetOption::Switch) { option->min.signedValue = switchValue(); - } else if (option->type == ZoneOption::Source) { + } else if (option->type == WidgetOption::Source) { option->min.unsignedValue = sourceValue(); - } else if (option->type == ZoneOption::Integer || option->type == ZoneOption::Slider) { + } else if (option->type == WidgetOption::Integer || option->type == WidgetOption::Slider) { option->min.signedValue = luaL_checkinteger(lsWidgets, -1); - } else if (option->type == ZoneOption::Choice) { + } else if (option->type == WidgetOption::Choice) { luaL_checktype(lsWidgets, -1, LUA_TTABLE); // value is a table option->choiceValues.clear(); for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2); lua_pop(lsWidgets, 1)) { option->choiceValues.push_back(luaL_checkstring(lsWidgets, -1)); } - } else if (option->type == ZoneOption::File) { + } else if (option->type == WidgetOption::File) { option->fileSelectPath = luaL_checkstring(lsWidgets, -1); } break; case 4: - if (option->type == ZoneOption::Switch) { + if (option->type == WidgetOption::Switch) { option->max.signedValue = switchValue(); - } else if (option->type == ZoneOption::Source) { + } else if (option->type == WidgetOption::Source) { option->max.unsignedValue = sourceValue(); - } else if (option->type == ZoneOption::Integer || option->type == ZoneOption::Slider) { + } else if (option->type == WidgetOption::Integer || option->type == WidgetOption::Slider) { option->max.signedValue = luaL_checkinteger(lsWidgets, -1); } break; @@ -264,7 +259,7 @@ const void LuaWidgetFactory::parseOptionDefaults() const // Parse options table to get name and type values. // Called on radio startup to build base data for all widgtes. -ZoneOption* LuaWidgetFactory::parseOptionDefinitions(int reference) +WidgetOption* LuaWidgetFactory::parseOptionDefinitions(int reference) { if (reference == LUA_REFNIL) { // TRACE("parseOptionDefinitions() no options"); @@ -284,7 +279,7 @@ ZoneOption* LuaWidgetFactory::parseOptionDefinitions(int reference) // TRACE("limited to %d options", count); } - ZoneOption *options = new ZoneOption[count + 1]; + WidgetOption *options = new WidgetOption[count + 1]; if (!options) { return NULL; } @@ -292,10 +287,10 @@ ZoneOption* LuaWidgetFactory::parseOptionDefinitions(int reference) PROTECT_LUA() { lua_rawgeti(lsWidgets, LUA_REGISTRYINDEX, reference); - ZoneOption *option = options; + WidgetOption *option = options; for (lua_pushnil(lsWidgets); lua_next(lsWidgets, -2), count-- > 0; lua_pop(lsWidgets, 1)) { - // TRACE("parsing option %d", count); + // TRACE("parseOptionDefinitions parsing option %d", count); luaL_checktype(lsWidgets, -2, LUA_TNUMBER); // key is number luaL_checktype(lsWidgets, -1, LUA_TTABLE); // value is table uint8_t field = 0; @@ -309,24 +304,24 @@ ZoneOption* LuaWidgetFactory::parseOptionDefinitions(int reference) // TRACE("name = %s", option->name); break; case 1: - option->type = (ZoneOption::Type)luaL_checkinteger(lsWidgets, -1); + option->type = (WidgetOption::Type)luaL_checkinteger(lsWidgets, -1); option->deflt.unsignedValue = 0; // set some sensible defaults - if (option->type == ZoneOption::Integer) { + if (option->type == WidgetOption::Integer) { option->min.signedValue = -100; option->max.signedValue = 100; - } else if (option->type == ZoneOption::Switch) { + } else if (option->type == WidgetOption::Switch) { option->min.signedValue = SWSRC_FIRST; option->max.signedValue = SWSRC_LAST; - } else if (option->type == ZoneOption::Timer) { + } else if (option->type == WidgetOption::Timer) { option->min.unsignedValue = 0; option->max.unsignedValue = MAX_TIMERS - 1; - } else if (option->type == ZoneOption::TextSize) { + } else if (option->type == WidgetOption::TextSize) { option->min.unsignedValue = FONT_STD_INDEX; option->max.unsignedValue = FONTS_COUNT - 1; - } else if (option->type == ZoneOption::String || option->type == ZoneOption::File) { - option->deflt.stringValue[0] = 0; - } else if (option->type == ZoneOption::Slider) { + } else if (option->type == WidgetOption::String || option->type == WidgetOption::File) { + option->deflt.stringValue.clear(); + } else if (option->type == WidgetOption::Slider) { option->min.unsignedValue = 0; option->max.unsignedValue = 9; } diff --git a/radio/src/lua/lua_widget_factory.h b/radio/src/lua/lua_widget_factory.h index 77cd70b71..7d4332914 100644 --- a/radio/src/lua/lua_widget_factory.h +++ b/radio/src/lua/lua_widget_factory.h @@ -28,25 +28,24 @@ class LuaWidgetFactory : public WidgetFactory friend class LuaWidget; public: - LuaWidgetFactory(const char* name, ZoneOption* widgetOptions, int optionDefinitionsReference, + LuaWidgetFactory(const char* name, WidgetOption* widgetOptions, int optionDefinitionsReference, int createFunction, int updateFunction, int refreshFunction, int backgroundFunction, int translateFunction, bool lvgllayout, const char* filename); ~LuaWidgetFactory(); - Widget* create(Window* parent, const rect_t& rect, - Widget::PersistentData* persistentData, - bool init = true) const override; + Widget* createNew(Window* parent, const rect_t& rect, + int screenNum, int zoneNum) const override; bool isLuaWidgetFactory() const override { return true; } bool useLvglLayout() const { return lvglLayout; } - static ZoneOption* parseOptionDefinitions(int reference); + static WidgetOption* parseOptionDefinitions(int reference); const void parseOptionDefaults() const override; protected: - void translateOptions(ZoneOption * options); + void translateOptions(WidgetOption * options); int optionDefinitionsReference; int createFunction; diff --git a/radio/src/lua/widgets.cpp b/radio/src/lua/widgets.cpp index 9cb330210..2861789eb 100644 --- a/radio/src/lua/widgets.cpp +++ b/radio/src/lua/widgets.cpp @@ -144,7 +144,7 @@ void luaLoadWidgetCallback(const char* filename) } if (name && createFunction) { - ZoneOption * options = LuaWidgetFactory::parseOptionDefinitions(optionDefinitionsReference); + WidgetOption * options = LuaWidgetFactory::parseOptionDefinitions(optionDefinitionsReference); if (options) { new LuaWidgetFactory(strdup(name), options, optionDefinitionsReference, createFunction, updateFunction, refreshFunction, backgroundFunction, diff --git a/radio/src/model_init.cpp b/radio/src/model_init.cpp index d113ddd5b..dddedab7b 100644 --- a/radio/src/model_init.cpp +++ b/radio/src/model_init.cpp @@ -144,6 +144,7 @@ void applyDefaultTemplate() #endif #if defined(COLORLCD) + g_model.initScreenData(); LayoutFactory::loadDefaultLayout(); #endif diff --git a/radio/src/storage/sdcard_yaml.cpp b/radio/src/storage/sdcard_yaml.cpp index 7388ddc6f..8164989af 100644 --- a/radio/src/storage/sdcard_yaml.cpp +++ b/radio/src/storage/sdcard_yaml.cpp @@ -343,6 +343,9 @@ const char * readModelYaml(const char * filename, uint8_t * buffer, uint32_t siz #if defined(FUNCTION_SWITCHES) extern void initCustomSwitches(); initCustomSwitches(); +#endif +#if defined(COLORLCD) + g_model.initScreenData(); #endif auto md = reinterpret_cast(buffer); #if defined(FLIGHT_MODES) && defined(GVARS) diff --git a/radio/src/storage/storage_common.cpp b/radio/src/storage/storage_common.cpp index 72e3bdc39..75f0f942b 100644 --- a/radio/src/storage/storage_common.cpp +++ b/radio/src/storage/storage_common.cpp @@ -167,19 +167,19 @@ void postModelLoad(bool alarms) g_model.topbarWidgetWidth[i] = 1; // Load 'date time' widget if slot is empty - if (g_model.topbarData.zones[MAX_TOPBAR_ZONES-1].widgetName[0] == 0) { - strAppend(g_model.topbarData.zones[MAX_TOPBAR_ZONES-1].widgetName, "Date Time", WIDGET_NAME_LEN); + if (!g_model.getTopbarData()->hasWidget(MAX_TOPBAR_ZONES-1)) { + g_model.getTopbarData()->setWidgetName(MAX_TOPBAR_ZONES-1, "Date Time"); storageDirty(EE_MODEL); } // Load 'radio info' widget if slot is empty - if (g_model.topbarData.zones[MAX_TOPBAR_ZONES-2].widgetName[0] == 0) { - strAppend(g_model.topbarData.zones[MAX_TOPBAR_ZONES-2].widgetName, "Radio Info", WIDGET_NAME_LEN); + if (!g_model.getTopbarData()->hasWidget(MAX_TOPBAR_ZONES-2)) { + g_model.getTopbarData()->setWidgetName(MAX_TOPBAR_ZONES-2, "Radio Info"); storageDirty(EE_MODEL); } #if defined(INTERNAL_GPS) // Load 'internal gps' widget if slot is empty - if (g_model.topbarData.zones[MAX_TOPBAR_ZONES-3].widgetName[0] == 0) { - strAppend(g_model.topbarData.zones[MAX_TOPBAR_ZONES-3].widgetName, "Internal GPS", WIDGET_NAME_LEN); + if (!g_model.getTopbarData()->hasWidget(MAX_TOPBAR_ZONES-3)) { + g_model.getTopbarData()->setWidgetName(MAX_TOPBAR_ZONES-3, "Internal GPS"); storageDirty(EE_MODEL); } #endif diff --git a/radio/src/storage/yaml/yaml_datastructs.cpp b/radio/src/storage/yaml/yaml_datastructs.cpp index a554db9a6..ed162e462 100644 --- a/radio/src/storage/yaml/yaml_datastructs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs.cpp @@ -83,6 +83,3 @@ #else #error "Board not supported by YAML storage" #endif - -static_assert(MAX_STR > MAX_RADIODATA_MODELDATA_PARTIALMODEL_STR_LEN, - "MAX_STR > MAX_RADIODATA_MODELDATA_PARTIALMODEL_STR_LEN"); diff --git a/radio/src/storage/yaml/yaml_datastructs_f16.cpp b/radio/src/storage/yaml/yaml_datastructs_f16.cpp index d87c66a13..937147c7e 100644 --- a/radio/src/storage/yaml/yaml_datastructs_f16.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_f16.cpp @@ -209,15 +209,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -786,45 +777,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 6, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 6, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_USBJoystickChData[] = { @@ -887,8 +889,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 8768, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 6, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp index 65dd9fa92..7f8eee708 100644 --- a/radio/src/storage/yaml/yaml_datastructs_funcs.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_funcs.cpp @@ -551,65 +551,138 @@ static bool w_vbat_max(const YamlNode* node, uint32_t val, yaml_writer_func wf, } #if defined(COLORLCD) -static uint8_t select_zov(void* user, uint8_t* data, uint32_t bitoffs) +bool screen_is_active(void* user, uint8_t* data, uint32_t bitoffs) { - data += bitoffs >> 3UL; - data -= offsetof(ZoneOptionValueTyped, value); - ZoneOptionValueEnum* p_zovt = (ZoneOptionValueEnum*)data; - if (*p_zovt > ZOV_Color) return 0; - return *p_zovt; + auto tw = reinterpret_cast(user); + auto screenData = g_model.getScreenData(tw->getElmts()); + + return !screenData->LayoutId.empty(); } -void r_zov_source(void* user, uint8_t* data, uint32_t bitoffs, - const char* val, uint8_t val_len) -{ - data += bitoffs >> 3UL; - auto p_val = reinterpret_cast(data); - p_val->unsignedValue = r_mixSrcRaw(nullptr, val, val_len); -} - -bool w_zov_source(void* user, uint8_t* data, uint32_t bitoffs, - yaml_writer_func wf, void* opaque) -{ - data += bitoffs >> 3UL; - auto p_val = reinterpret_cast(data); - return w_mixSrcRaw(nullptr, p_val->unsignedValue, wf, opaque); -} - -void r_zov_color(void* user, uint8_t* data, uint32_t bitoffs, +void r_screen_id(void* user, uint8_t* data, uint32_t bitoffs, const char* val, uint8_t val_len) { - data += bitoffs >> 3UL; + auto tw = reinterpret_cast(user); + auto screenData = g_model.getScreenData(tw->getElmts(1)); - ZoneOptionValue zov; + screenData->LayoutId = val; +} + +bool w_screen_id(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + auto tw = reinterpret_cast(user); + auto screenData = g_model.getScreenData(tw->getElmts(1)); + + return wf(opaque, screenData->LayoutId.c_str(), screenData->LayoutId.size()); +} + +static ZonePersistentData* get_zoneData(void* user) +{ + auto tw = reinterpret_cast(user); + + int lvl = tw->getLevel(); + bool topBar = (lvl == 3) || (lvl == 4); + int o = (lvl == 3) || (lvl == 5) ? 0 : 1; + + uint16_t zone = tw->getElmts(o); + if (topBar) { + // Top Bar + return &g_model.getTopbarData()->zones[zone]; + } else { + // Screen + uint16_t screen = tw->getElmts(o + 3); + return &g_model.getScreenLayoutData(screen)->zones[zone]; + } +} + +bool widget_is_active(void* user, uint8_t* data, uint32_t bitoffs) +{ + auto zoneData = get_zoneData(user); + + return zoneData->widgetName[0] != 0; +} + +void r_widget_name(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + auto zoneData = get_zoneData(user); + + zoneData->widgetName = val; +} + +bool w_widget_name(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + auto zoneData = get_zoneData(user); + + return wf(opaque, zoneData->widgetName.c_str(), zoneData->widgetName.size()); +} + +static WidgetPersistentData* get_widgetData(void* user, uint16_t& option) +{ + auto tw = reinterpret_cast(user); + + int lvl = tw->getLevel(); + bool topBar = (lvl == 7) || (lvl == 8); + int o = ((lvl == 7) || (lvl == 9)) ? 1 : 2; + + option = tw->getElmts(o); + uint16_t zone = tw->getElmts(o + 3); + if (topBar) { + // Top Bar + return g_model.getTopbarData()->getWidgetData(zone); + } else { + // Screen + uint16_t screen = tw->getElmts(o + 6); + return g_model.getScreenLayoutData(screen)->getWidgetData(zone); + } +} + +bool widget_option_is_active(void* user, uint8_t* data, uint32_t bitoffs) +{ + auto tw = reinterpret_cast(user); + + int lvl = tw->getLevel(); + bool topBar = (lvl == 6); + int o = 0; + + WidgetPersistentData* widgetData; + + uint16_t option = tw->getElmts(o); + uint16_t zone = tw->getElmts(o + 3); + if (topBar) { + // Top Bar + widgetData = g_model.getTopbarData()->getWidgetData(zone); + } else { + // Screen + uint16_t screen = tw->getElmts(o + 6); + widgetData = g_model.getScreenLayoutData(screen)->getWidgetData(zone); + } + + return widgetData->hasOption(option); +} + +static uint32_t get_color(const char* val, uint8_t val_len) +{ if (strncmp(val, "COLIDX", 6) == 0) { val += 6; val_len -= 6; - zov.unsignedValue = COLOR2FLAGS(yaml_str2uint(val, val_len)); + return COLOR2FLAGS(yaml_str2uint(val, val_len)); } else { if (val_len < sizeof("0xFFFFFF")-1 || val[0] != '0' || val[1] != 'x') - return; + return 0; val += 2; val_len -= 2; auto rgb24 = yaml_hex2uint(val, val_len); - zov.unsignedValue = RGB2FLAGS((rgb24 & 0xFF0000) >> 16, - (rgb24 & 0xFF00) >> 8, rgb24 & 0xFF); + return RGB2FLAGS((rgb24 & 0xFF0000) >> 16, (rgb24 & 0xFF00) >> 8, rgb24 & 0xFF); } - - memcpy(data, &zov, sizeof(ZoneOptionValue)); } -bool w_zov_color(void* user, uint8_t* data, uint32_t bitoffs, - yaml_writer_func wf, void* opaque) +static bool set_color(uint32_t val, yaml_writer_func wf, void* opaque) { - data += bitoffs >> 3UL; - - ZoneOptionValue zov; - memcpy(&zov, data, sizeof(ZoneOptionValue)); - - uint32_t val = zov.unsignedValue; if (val & RGB_FLAG) { val = COLOR_VAL(val); uint32_t color = (uint32_t)GET_RED(val) << 16 | @@ -623,6 +696,232 @@ bool w_zov_color(void* user, uint8_t* data, uint32_t bitoffs, return wf(opaque, str, strlen(str)); } } + +static uint8_t select_wov(void* user, uint8_t* data, uint32_t bitoffs) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + return widgetData->getType(option); +} + +const struct YamlIdStr enum_WidgetOptionValueEnum[] = { + { WOV_Unsigned, "Unsigned" }, + { WOV_Signed, "Signed" }, + { WOV_Bool, "Bool" }, + { WOV_String, "String" }, + { WOV_Source, "Source" }, + { WOV_Color, "Color" }, + { 0, NULL } +}; + +void r_wov_type(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + widgetData->setType(option, (WidgetOptionValueEnum)yaml_parse_enum(enum_WidgetOptionValueEnum, val, val_len)); +} + +bool w_wov_type(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + const char* str = yaml_output_enum(widgetData->getType(option), enum_WidgetOptionValueEnum); + return wf(opaque, str, strlen(str)); +} + +void r_wov_source(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + widgetData->setUnsignedValue(option, r_mixSrcRaw(nullptr, val, val_len)); +} + +bool w_wov_source(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + return w_mixSrcRaw(nullptr, widgetData->getUnsignedValue(option), wf, opaque); +} + +void r_wov_color(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + widgetData->setUnsignedValue(option, get_color(val, val_len)); +} + +bool w_wov_color(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + return set_color(widgetData->getUnsignedValue(option), wf, opaque); +} + +void r_wov_string(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + widgetData->setString(option, val); +} + +bool w_wov_string(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + return wf(opaque, widgetData->getString(option).c_str(), widgetData->getString(option).size()); +} + +void r_wov_unsigned(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + widgetData->setUnsignedValue(option, yaml_str2uint(val, val_len)); +} + +bool w_wov_unsigned(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + const char* str = yaml_unsigned2str(widgetData->getUnsignedValue(option)); + return wf(opaque, str, strlen(str)); +} + +void r_wov_signed(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + widgetData->setSignedValue(option, yaml_str2int(val, val_len)); +} + +bool w_wov_signed(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + uint16_t option; + auto widgetData = get_widgetData(user, option); + + const char* str = yaml_signed2str(widgetData->getSignedValue(option)); + return wf(opaque, str, strlen(str)); +} + +static LayoutPersistentData* get_LayoutData(void* user, uint16_t& option) +{ + auto tw = reinterpret_cast(user); + + int lvl = tw->getLevel(); + int o = (lvl == 6) ? 1 : 2; + + option = tw->getElmts(o); + // Screen + uint16_t screen = tw->getElmts(o + 3); + return g_model.getScreenLayoutData(screen); +} + +bool layout_option_is_active(void* user, uint8_t* data, uint32_t bitoffs) +{ + auto tw = reinterpret_cast(user); + + int o = 0; + + uint16_t option = tw->getElmts(o); + uint16_t screen = tw->getElmts(o + 3); + auto layoutData = g_model.getScreenLayoutData(screen); + + return layoutData->options[option].type != LOV_None || layoutData->options[option].value.unsignedValue != 0; +} + +static uint8_t select_lov(void* user, uint8_t* data, uint32_t bitoffs) +{ + uint16_t option; + auto layoutData = get_LayoutData(user, option); + + return layoutData->options[option].type; +} + +const struct YamlIdStr enum_LayoutOptionValueEnum[] = { + { LOV_None, "None" }, + { LOV_Bool, "Bool" }, + { LOV_Color, "Color" }, + { 0, NULL } +}; + +void r_lov_type(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + uint16_t option; + auto layoutData = get_LayoutData(user, option); + + layoutData->options[option].type = (LayoutOptionValueEnum)yaml_parse_enum(enum_LayoutOptionValueEnum, val, val_len); +} + +bool w_lov_type(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + uint16_t option; + auto layoutData = get_LayoutData(user, option); + + const char* str = yaml_output_enum(layoutData->options[option].type, enum_LayoutOptionValueEnum); + return wf(opaque, str, strlen(str)); +} + +void r_lov_unsigned(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + uint16_t option; + auto layoutData = get_LayoutData(user, option); + + layoutData->options[option].value.unsignedValue = yaml_str2uint(val, val_len); +} + +bool w_lov_unsigned(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + uint16_t option; + auto layoutData = get_LayoutData(user, option); + + const char* str = yaml_unsigned2str(layoutData->options[option].value.unsignedValue); + return wf(opaque, str, strlen(str)); +} + +void r_lov_color(void* user, uint8_t* data, uint32_t bitoffs, + const char* val, uint8_t val_len) +{ + uint16_t option; + auto layoutData = get_LayoutData(user, option); + + layoutData->options[option].value.unsignedValue = get_color(val, val_len); +} + +bool w_lov_color(void* user, uint8_t* data, uint32_t bitoffs, + yaml_writer_func wf, void* opaque) +{ + uint16_t option; + auto layoutData = get_LayoutData(user, option); + + return set_color(layoutData->options[option].value.unsignedValue, wf, opaque); +} #endif static uint8_t select_mod_type(void* user, uint8_t* data, uint32_t bitoffs) @@ -1004,8 +1303,7 @@ static uint32_t r_swtchSrc(const YamlNode* node, const char* val, uint8_t val_le val_len--; } - if (val_len > 3 - && ((val[0] == 'S' && val[1] >= 'W') + if (val_len > 3 && ((val[0] == 'S' && val[1] >= 'W') || (val[0] == 'F' && val[1] >= 'L')) && val[2] >= '0' && val[2] <= '9' && val[3] >= '0' && val[3] <= '2') { @@ -2496,11 +2794,6 @@ bool cfsGroupIsActive(void* user, uint8_t* data, uint32_t bitoffs) uint16_t idx = tw->getElmts(); return idx > 0 && idx <= NUM_FUNCTIONS_GROUPS; } - -bool isAlwaysActive(void* user, uint8_t* data, uint32_t bitoffs) -{ - return true; -} #endif bool switchIsActive(void* user, uint8_t* data, uint32_t bitoffs) @@ -2509,3 +2802,8 @@ bool switchIsActive(void* user, uint8_t* data, uint32_t bitoffs) uint16_t idx = tw->getElmts(); return idx < switchGetMaxAllSwitches(); } + +bool isAlwaysActive(void* user, uint8_t* data, uint32_t bitoffs) +{ + return true; +} diff --git a/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp b/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp index 268108a96..0deaa5741 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nb4p.cpp @@ -200,15 +200,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -777,45 +768,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 4, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 4, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_USBJoystickChData[] = { @@ -878,8 +880,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 5888, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 4, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp index 52344460a..ff4a68f81 100644 --- a/radio/src/storage/yaml/yaml_datastructs_nv14.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_nv14.cpp @@ -207,15 +207,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -784,45 +775,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 4, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 4, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_USBJoystickChData[] = { @@ -886,8 +888,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 5888, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 4, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_datastructs_pa01.cpp b/radio/src/storage/yaml/yaml_datastructs_pa01.cpp index 1d7ee9833..d7b714cc0 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pa01.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pa01.cpp @@ -221,15 +221,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -809,45 +800,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 5, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 5, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_customSwitch[] = { @@ -924,8 +926,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 99, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 7328, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 5, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp index 0a69538bc..39d396402 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pl18.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pl18.cpp @@ -207,15 +207,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -784,45 +775,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 6, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 6, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_USBJoystickChData[] = { @@ -886,8 +888,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 8768, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 6, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp b/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp index bfbeddbf0..bc688af69 100644 --- a/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_pl18u.cpp @@ -200,15 +200,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -777,45 +768,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 6, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 6, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_USBJoystickChData[] = { @@ -878,8 +880,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 8768, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 6, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_datastructs_st16.cpp b/radio/src/storage/yaml/yaml_datastructs_st16.cpp index 2a4cfd740..a0a99fe95 100644 --- a/radio/src/storage/yaml/yaml_datastructs_st16.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_st16.cpp @@ -221,15 +221,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -809,45 +800,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 6, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 6, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_customSwitch[] = { @@ -924,8 +926,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 99, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 8768, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 6, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_datastructs_t15.cpp b/radio/src/storage/yaml/yaml_datastructs_t15.cpp index 5ee0572d2..a5a39ad88 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t15.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t15.cpp @@ -216,15 +216,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -794,45 +785,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 6, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 6, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_customSwitch[] = { @@ -904,8 +906,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 8768, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 6, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp b/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp index 2a4cfd740..a0a99fe95 100644 --- a/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_t15pro.cpp @@ -221,15 +221,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -809,45 +800,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 6, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 6, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_customSwitch[] = { @@ -924,8 +926,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 99, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 8768, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 6, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_datastructs_tx15.cpp b/radio/src/storage/yaml/yaml_datastructs_tx15.cpp index 2a4cfd740..a0a99fe95 100644 --- a/radio/src/storage/yaml/yaml_datastructs_tx15.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_tx15.cpp @@ -221,15 +221,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -809,45 +800,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 6, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 6, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_customSwitch[] = { @@ -924,8 +926,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 99, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 8768, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 6, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_datastructs_x10.cpp b/radio/src/storage/yaml/yaml_datastructs_x10.cpp index c73bb6ef6..c37be430a 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x10.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x10.cpp @@ -208,15 +208,6 @@ const struct YamlIdStr enum_TelemetrySensorType[] = { { TELEM_TYPE_CALCULATED, "TYPE_CALCULATED" }, { 0, NULL } }; -const struct YamlIdStr enum_ZoneOptionValueEnum[] = { - { ZOV_Unsigned, "Unsigned" }, - { ZOV_Signed, "Signed" }, - { ZOV_Bool, "Bool" }, - { ZOV_String, "String" }, - { ZOV_Source, "Source" }, - { ZOV_Color, "Color" }, - { 0, NULL } -}; const struct YamlIdStr enum_USBJoystickIfMode[] = { { USBJOYS_JOYSTICK, "JOYSTICK" }, { USBJOYS_GAMEPAD, "GAMEPAD" }, @@ -785,45 +776,56 @@ static const struct YamlNode struct_TelemetrySensor[] = { YAML_UNION("cfg", 32, union_anonymous_17_elmts, select_sensor_cfg), YAML_END }; -static const struct YamlNode union_ZoneOptionValue_elmts[] = { - YAML_UNSIGNED( "unsignedValue", 32 ), - YAML_SIGNED( "signedValue", 32 ), - YAML_UNSIGNED( "boolValue", 32 ), - YAML_STRING("stringValue", 12), - YAML_CUSTOM("source",r_zov_source,w_zov_source), - YAML_CUSTOM("color",r_zov_color,w_zov_color), +static const struct YamlNode union_WidgetOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("signedValue",r_wov_signed,w_wov_signed), + YAML_CUSTOM("boolValue",r_wov_unsigned,w_wov_unsigned), + YAML_CUSTOM("stringValue",r_wov_string,w_wov_string), + YAML_CUSTOM("source",r_wov_source,w_wov_source), + YAML_CUSTOM("color",r_wov_color,w_wov_color), YAML_END }; -static const struct YamlNode struct_ZoneOptionValueTyped[] = { +static const struct YamlNode struct_WidgetOptionValueTyped[] = { YAML_IDX, - YAML_ENUM("type", 32, enum_ZoneOptionValueEnum, NULL), - YAML_UNION("value", 96, union_ZoneOptionValue_elmts, select_zov), + YAML_CUSTOM("type",r_wov_type,w_wov_type), + YAML_UNION("value", 0, union_WidgetOptionValue_elmts, select_wov), YAML_END }; static const struct YamlNode struct_WidgetPersistentData[] = { - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("options", 0, 50, struct_WidgetOptionValueTyped, widget_option_is_active), YAML_END }; static const struct YamlNode struct_ZonePersistentData[] = { YAML_IDX, - YAML_STRING("widgetName", 20), - YAML_STRUCT("widgetData", 1280, struct_WidgetPersistentData, NULL), + YAML_CUSTOM("widgetName",r_widget_name,w_widget_name), + YAML_STRUCT("widgetData", 0, struct_WidgetPersistentData, isAlwaysActive), + YAML_END +}; +static const struct YamlNode union_LayoutOptionValue_elmts[] = { + YAML_CUSTOM("unsignedValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("boolValue",r_lov_unsigned,w_lov_unsigned), + YAML_CUSTOM("color",r_lov_color,w_lov_color), + YAML_END +}; +static const struct YamlNode struct_LayoutOptionValueTyped[] = { + YAML_IDX, + YAML_CUSTOM("type",r_lov_type,w_lov_type), + YAML_UNION("value", 0, union_LayoutOptionValue_elmts, select_lov), YAML_END }; static const struct YamlNode struct_LayoutPersistentData[] = { - YAML_ARRAY("zones", 1440, 10, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 10, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 10, struct_ZonePersistentData, widget_is_active), + YAML_ARRAY("options", 0, 10, struct_LayoutOptionValueTyped, layout_option_is_active), YAML_END }; static const struct YamlNode struct_CustomScreenData[] = { YAML_IDX, - YAML_STRING("LayoutId", 12), - YAML_STRUCT("layoutData", 15680, struct_LayoutPersistentData, NULL), + YAML_CUSTOM("LayoutId",r_screen_id,w_screen_id), + YAML_STRUCT("layoutData", 0, struct_LayoutPersistentData, isAlwaysActive), YAML_END }; static const struct YamlNode struct_TopBarPersistentData[] = { - YAML_ARRAY("zones", 1440, 6, struct_ZonePersistentData, NULL), - YAML_ARRAY("options", 128, 1, struct_ZoneOptionValueTyped, NULL), + YAML_ARRAY("zones", 0, 6, struct_ZonePersistentData, widget_is_active), YAML_END }; static const struct YamlNode struct_USBJoystickChData[] = { @@ -886,8 +888,8 @@ static const struct YamlNode struct_ModelData[] = { YAML_UNSIGNED( "potsWarnEnabled", 16 ), YAML_ARRAY("potsWarnPosition", 8, 16, struct_signed_8, NULL), YAML_ARRAY("telemetrySensors", 112, 60, struct_TelemetrySensor, NULL), - YAML_ARRAY("screenData", 15776, 10, struct_CustomScreenData, NULL), - YAML_STRUCT("topbarData", 8768, struct_TopBarPersistentData, NULL), + YAML_ARRAY("screenData", 0, 10, struct_CustomScreenData, screen_is_active), + YAML_STRUCT("topbarData", 0, struct_TopBarPersistentData, isAlwaysActive), YAML_ARRAY("topbarWidgetWidth", 8, 6, struct_unsigned_8, NULL), YAML_UNSIGNED( "view", 8 ), YAML_STRING("modelRegistrationID", 8), diff --git a/radio/src/storage/yaml/yaml_labelslist.cpp b/radio/src/storage/yaml/yaml_labelslist.cpp index 57867bf4d..1a20d208d 100644 --- a/radio/src/storage/yaml/yaml_labelslist.cpp +++ b/radio/src/storage/yaml/yaml_labelslist.cpp @@ -107,7 +107,7 @@ static bool to_next_elmt(void* ctx) return true; } -static bool find_node(void* ctx, char* buf, uint8_t len) +static bool find_node(void* ctx, const char* buf, uint8_t len) { labelslist_iter* mi = (labelslist_iter*)ctx; @@ -170,7 +170,7 @@ static bool find_node(void* ctx, char* buf, uint8_t len) return true; } -static void set_attr(void* ctx, char* buf, uint16_t len) +static void set_attr(void* ctx, const char* buf, uint16_t len) { char value[LABELS_LENGTH + 1]; if(len > LABELS_LENGTH) { diff --git a/radio/src/storage/yaml/yaml_modelslist.cpp b/radio/src/storage/yaml/yaml_modelslist.cpp index 8bb906422..b5c9da619 100644 --- a/radio/src/storage/yaml/yaml_modelslist.cpp +++ b/radio/src/storage/yaml/yaml_modelslist.cpp @@ -82,7 +82,7 @@ static bool to_next_elmt(void* ctx) return true; } -static bool find_node(void* ctx, char* buf, uint8_t len) +static bool find_node(void* ctx, const char* buf, uint8_t len) { modelslist_iter* mi = (modelslist_iter*)ctx; @@ -95,7 +95,7 @@ static bool find_node(void* ctx, char* buf, uint8_t len) return true; } -static void set_attr(void* ctx, char* buf, uint16_t len) +static void set_attr(void* ctx, const char* buf, uint16_t len) { char fnamebuf[LEN_MODEL_FILENAME + 1]; modelslist_iter* mi = (modelslist_iter*)ctx; diff --git a/radio/src/storage/yaml/yaml_parser.cpp b/radio/src/storage/yaml/yaml_parser.cpp index 2c35b0def..c7ea842e9 100644 --- a/radio/src/storage/yaml/yaml_parser.cpp +++ b/radio/src/storage/yaml/yaml_parser.cpp @@ -50,7 +50,8 @@ void YamlParser::reset() indents[level] = indent; state = saved_state = ps_Indent; } - indent = scratch_len = 0; + indent = 0; + scratch_buf.clear(); node_found = false; } @@ -79,17 +80,6 @@ uint8_t YamlParser::getLastIndent() YamlParser::YamlResult YamlParser::parse(const char* buffer, unsigned int size) { - -#define CONCAT_STR(s,s_len,c) \ - { \ - if(s_len < MAX_STR) \ - s[s_len++] = c; \ - else { \ - TRACE_YAML("STRING_OVERFLOW"); \ - return STRING_OVERFLOW; \ - } \ - } - const char* c = buffer; const char* end = c + size; @@ -153,7 +143,7 @@ YamlParser::parse(const char* buffer, unsigned int size) state = ps_AttrQuo; break; } - CONCAT_STR(scratch_buf, scratch_len, *c); + scratch_buf += *c; break; case ps_AttrQuo: @@ -161,7 +151,7 @@ YamlParser::parse(const char* buffer, unsigned int size) state = ps_Attr; break; } - CONCAT_STR(scratch_buf, scratch_len, *c); + scratch_buf += *c; break; case ps_Attr: @@ -170,16 +160,15 @@ YamlParser::parse(const char* buffer, unsigned int size) break; } if ((*c != ':') && (*c != '\r') && (*c != '\n')) - CONCAT_STR(scratch_buf, scratch_len, *c); + scratch_buf += *c; // trap case ps_AttrSP: if (*c == '\r' || *c == '\n') { if (state == ps_Attr) { // TODO: trim spaces at the end? - node_found = calls->find_node(ctx, scratch_buf, scratch_len); + node_found = calls->find_node(ctx, scratch_buf.c_str(), scratch_buf.size()); if (!node_found) { - TRACE_YAML("YAML_PARSER: Could not find node '%.*s' (2)\n", - scratch_len, scratch_buf); + TRACE_YAML("YAML_PARSER: Could not find node '%s' (2)\n", scratch_buf.c_str()); } } saved_state = state; @@ -189,10 +178,9 @@ YamlParser::parse(const char* buffer, unsigned int size) if (*c == ':') { if (state == ps_Attr) { // TODO: trim spaces at the end? - node_found = calls->find_node(ctx, scratch_buf, scratch_len); + node_found = calls->find_node(ctx, scratch_buf.c_str(), scratch_buf.size()); if (!node_found) { - TRACE_YAML("YAML_PARSER: Could not find node '%.*s' (3)\n", - scratch_len, scratch_buf); + TRACE_YAML("YAML_PARSER: Could not find node '%s' (3)\n", scratch_buf.c_str); } } state = ps_Sep; @@ -209,7 +197,7 @@ YamlParser::parse(const char* buffer, unsigned int size) continue; } state = ps_Val; - scratch_len = 0; + scratch_buf.clear(); if (*c == '\"') { state = ps_ValQuo; break; @@ -218,7 +206,7 @@ YamlParser::parse(const char* buffer, unsigned int size) state = ps_ValEsc; break; } - CONCAT_STR(scratch_buf, scratch_len, *c); + scratch_buf += *c; break; case ps_ValQuo: @@ -230,7 +218,7 @@ YamlParser::parse(const char* buffer, unsigned int size) state = ps_ValEsc1; break; } - CONCAT_STR(scratch_buf, scratch_len, *c); + scratch_buf += *c; break; case ps_ValEsc1: @@ -238,22 +226,18 @@ YamlParser::parse(const char* buffer, unsigned int size) state = ps_ValEsc2; break; } - CONCAT_STR(scratch_buf, scratch_len, *c); + scratch_buf += *c; state = ps_ValQuo; break; case ps_ValEsc2: - if(scratch_len >= MAX_STR) { - TRACE_YAML("STRING_OVERFLOW"); - return STRING_OVERFLOW; - } - else if (*c >= '0' && *c <= '9') { - scratch_buf[scratch_len] = (*c - '0') << 4; + if (*c >= '0' && *c <= '9') { + escHexVal = (*c - '0') << 4; state = ps_ValEsc3; break; } else if (*c >= 'A' && *c <= 'F') { - scratch_buf[scratch_len] = (*c - 'A' + 10) << 4; + escHexVal = (*c - 'A' + 10) << 4; state = ps_ValEsc3; break; } @@ -262,12 +246,14 @@ YamlParser::parse(const char* buffer, unsigned int size) case ps_ValEsc3: if (*c >= '0' && *c <= '9') { - scratch_buf[scratch_len++] |= (*c - '0'); + escHexVal |= (*c - '0'); + scratch_buf += escHexVal; state = ps_ValQuo; break; } else if (*c >= 'A' && *c <= 'F') { - scratch_buf[scratch_len++] |= (*c - 'A' + 10); + escHexVal |= (*c - 'A' + 10); + scratch_buf += escHexVal; state = ps_ValQuo; break; } @@ -278,8 +264,7 @@ YamlParser::parse(const char* buffer, unsigned int size) if (*c == '\r' || *c == '\n') { // set attribute if (node_found) { - // TODO: trim spaces at the end? - calls->set_attr(ctx, scratch_buf, scratch_len); + calls->set_attr(ctx, scratch_buf.c_str(), scratch_buf.size()); } saved_state = state; state = ps_CRLF; @@ -289,12 +274,12 @@ YamlParser::parse(const char* buffer, unsigned int size) state = ps_ValEsc; break; } - CONCAT_STR(scratch_buf, scratch_len, *c); + scratch_buf += *c; break; case ps_ValEsc: state = ps_Val; - CONCAT_STR(scratch_buf, scratch_len, *c); + scratch_buf += *c; break; case ps_CRLF: @@ -311,8 +296,7 @@ YamlParser::parse(const char* buffer, unsigned int size) } // for each char if ((state == ps_Val) && eof && node_found) { - // TODO: trim spaces at the end? - calls->set_attr(ctx, scratch_buf, scratch_len); + calls->set_attr(ctx, scratch_buf.c_str(), scratch_buf.size()); } return CONTINUE_PARSING; diff --git a/radio/src/storage/yaml/yaml_parser.h b/radio/src/storage/yaml/yaml_parser.h index bfc01116f..05617cc6f 100644 --- a/radio/src/storage/yaml/yaml_parser.h +++ b/radio/src/storage/yaml/yaml_parser.h @@ -22,8 +22,8 @@ #pragma once #include +#include -#define MAX_STR 256 #define MAX_DEPTH 16 // 12 real + 4 virtual struct YamlParserCalls @@ -31,8 +31,8 @@ struct YamlParserCalls bool (*to_parent) (void* ctx); bool (*to_child) (void* ctx); bool (*to_next_elmt) (void* ctx); - bool (*find_node) (void* ctx, char* buf, uint8_t len); - void (*set_attr) (void* ctx, char* buf, uint16_t len); + bool (*find_node) (void* ctx, const char* buf, uint8_t len); + void (*set_attr) (void* ctx, const char* buf, uint16_t len); }; class YamlParser @@ -65,11 +65,10 @@ class YamlParser // parser state uint8_t state; uint8_t saved_state; + char escHexVal; - // scratch buffer w/ 16 bytes - // used for attribute and values - char scratch_buf[MAX_STR]; - uint16_t scratch_len; + // scratch buffer used for attribute and values + std::string scratch_buf; bool node_found; bool eof; diff --git a/radio/src/storage/yaml/yaml_tree_walker.cpp b/radio/src/storage/yaml/yaml_tree_walker.cpp index b6d1a5554..880690c21 100644 --- a/radio/src/storage/yaml/yaml_tree_walker.cpp +++ b/radio/src/storage/yaml/yaml_tree_walker.cpp @@ -442,7 +442,7 @@ void YamlTreeWalker::toNextAttr() } } -void YamlTreeWalker::setAttrValue(char* buf, uint16_t len) +void YamlTreeWalker::setAttrValue(const char* buf, uint16_t len) { if (!buf || !len || isIdxInvalid()) return; @@ -686,12 +686,12 @@ static bool to_next_elmt(void* ctx) return ((YamlTreeWalker*)ctx)->toNextElmt(); } -static bool find_node(void* ctx, char* buf, uint8_t len) +static bool find_node(void* ctx, const char* buf, uint8_t len) { return ((YamlTreeWalker*)ctx)->findNode(buf,len); } -static void set_attr(void* ctx, char* buf, uint16_t len) +static void set_attr(void* ctx, const char* buf, uint16_t len) { ((YamlTreeWalker*)ctx)->setAttrValue(buf,len); } diff --git a/radio/src/storage/yaml/yaml_tree_walker.h b/radio/src/storage/yaml/yaml_tree_walker.h index 4dfed0e83..1c18db498 100644 --- a/radio/src/storage/yaml/yaml_tree_walker.h +++ b/radio/src/storage/yaml/yaml_tree_walker.h @@ -155,7 +155,7 @@ public: bool isElmtEmpty(uint8_t* data); - void setAttrValue(char* buf, uint16_t len); + void setAttrValue(const char* buf, uint16_t len); bool generate(yaml_writer_func wf, void* opaque);