diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 16d37f8b..c46c9bfe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,3 +75,18 @@ jobs: - name: Run Unit Tests run: | ctest --test-dir build + + # Step 7: Same again with the optional runtime-rotation feature enabled, + # which links both generated layouts. X11 is not LGFX, so this covers + # compiling, linking and the state tests -- not the panel rotation itself. + - name: Configure CMake (runtime rotation) + run: | + cmake -S . -B build-rotation -G Ninja -DMUI_RUNTIME_ROTATION=ON + + - name: Build Project (runtime rotation) + run: | + cmake --build build-rotation + + - name: Run Unit Tests (runtime rotation) + run: | + ctest --test-dir build-rotation diff --git a/CMakeLists.txt b/CMakeLists.txt index 74f2f3cc..4a488d1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ endif() option(ENABLE_DOCTESTS "Include tests in the library. Setting this to OFF will remove all doctest related code. Tests in tests/*.cpp will still be enabled." ${MAIN_PROJECT}) option(ENABLE_DEBUG_LOG "Enable debug log" OFF) +option(MUI_RUNTIME_ROTATION "Link both perpendicular UI layouts and select the screen rotation at runtime" OFF) set_property(GLOBAL PROPERTY USE_FOLDERS ON) set(CMAKE_FIND_PACKAGE_TARGETS_GLOBAL ON) # with newer cmake versions put all find_package in global scope @@ -24,14 +25,18 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin") -set(GENERATED_VIEW ${VIEW} "ui_320x240") +if(NOT VIEW) + set(VIEW "ui_320x240") +endif() +set(GENERATED_VIEW ${VIEW}) message(STATUS "Using C++${CMAKE_CXX_STANDARD}") message(STATUS "Using Generated View: " ${GENERATED_VIEW}) add_compile_definitions(ARCH_PORTDUINO) add_compile_definitions(ARDUINO) -add_compile_definitions(VIEW_320x240) +string(REGEX REPLACE "^ui_" "VIEW_" GENERATED_VIEW_MACRO ${GENERATED_VIEW}) +add_compile_definitions(${GENERATED_VIEW_MACRO}) add_compile_definitions(USE_X11=1) include(FetchContent) @@ -48,9 +53,18 @@ find_package(CURL REQUIRED) file(GLOB_RECURSE sources source/* generated/* portduino/* locale/* generated/${GENERATED_VIEW}/*) file(GLOB_RECURSE sources_test tests/*.cpp) +if(MUI_RUNTIME_ROTATION) + include(MuiRuntimeRotation) + mui_runtime_rotation_sources(sources) +endif() + add_library(DeviceUI ${sources}) target_link_libraries(DeviceUI PRIVATE lvgl::lvgl LovyanGFX Portduino Protobufs CURL::libcurl) +if(MUI_RUNTIME_ROTATION) + mui_runtime_rotation_configure(DeviceUI) +endif() + # Handle Windows Static linking dependencies if applicable if(WIN32) target_compile_definitions(DeviceUI PRIVATE CURL_STATICLIB) @@ -91,4 +105,11 @@ if(ENABLE_DOCTESTS) ) set_target_properties(tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) add_test(NAME tests COMMAND tests) + + if(MUI_RUNTIME_ROTATION) + target_include_directories(tests PRIVATE ${MUI_GLUE_DIR}) + add_test(NAME dual_ui_glue + COMMAND ${Python_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/gen_dual_ui.py + --check ${MUI_PRIMARY_VIEW}) + endif() endif() \ No newline at end of file diff --git a/cmake/MuiRuntimeRotation.cmake b/cmake/MuiRuntimeRotation.cmake new file mode 100644 index 00000000..fda3febf --- /dev/null +++ b/cmake/MuiRuntimeRotation.cmake @@ -0,0 +1,103 @@ +# Dual-layout build support for MUI_RUNTIME_ROTATION. +# +# Links both perpendicular generated layouts into one binary so the screen +# rotation becomes a runtime setting. The primary tree (this build's VIEW_*) +# keeps its symbols and supplies every shared asset; the secondary tree is +# compiled with its colliding globals renamed via a generated forced include. +# +# mui_runtime_rotation_sources() rewrites the caller's source list. +# mui_runtime_rotation_configure() applies the target settings. + +set(MUI_DUAL_VIEWS ui_320x240 ui_240x320) +set(MUI_GLUE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tools/generated/dual) +set(MUI_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/tools/gen_dual_ui.py) + +function(mui_runtime_rotation_sources sources_var) + list(GET MUI_DUAL_VIEWS 0 _first) + list(GET MUI_DUAL_VIEWS 1 _second) + if(GENERATED_VIEW STREQUAL _first) + set(_primary ${_first}) + set(_secondary ${_second}) + elseif(GENERATED_VIEW STREQUAL _second) + set(_primary ${_second}) + set(_secondary ${_first}) + else() + message(FATAL_ERROR + "MUI_RUNTIME_ROTATION supports only ${_first} and ${_second}, not '${GENERATED_VIEW}': " + "it links the two perpendicular layouts and no other generated tree has a counterpart.") + endif() + + find_package(Python COMPONENTS Interpreter REQUIRED) + execute_process(COMMAND ${Python_EXECUTABLE} ${MUI_GENERATOR} --check ${_primary} + RESULT_VARIABLE _rc OUTPUT_VARIABLE _out ERROR_VARIABLE _err) + if(NOT _rc EQUAL 0) + message(FATAL_ERROR "MUI_RUNTIME_ROTATION: ${_out}${_err}") + endif() + + # The build reads the source inventory from the manifest so it cannot drift + # from the generator. + file(STRINGS ${MUI_GLUE_DIR}/manifest.txt _manifest) + set(_secondary_names "") + set(_glue_names "") + foreach(_line IN LISTS _manifest) + if(_line MATCHES "^core_source (.+)$") + list(APPEND _secondary_names ${CMAKE_MATCH_1}) + elseif(_line MATCHES "^secondary_asset ${_secondary} (.+)$") + # only the secondary tree's unique assets need compiling + list(APPEND _secondary_names ${CMAKE_MATCH_1}) + elseif(_line MATCHES "^glue_source (.+)$") + list(APPEND _glue_names ${CMAKE_MATCH_1}) + endif() + endforeach() + + # Drop every generated tree from the catch-all glob, then add each tree + # exactly once. Without this both trees enter the target and their + # identically named globals collide. + set(_sources ${${sources_var}}) + list(FILTER _sources EXCLUDE REGEX "/generated/ui_[0-9]+x[0-9]+/") + + file(GLOB_RECURSE _primary_sources ${CMAKE_CURRENT_SOURCE_DIR}/generated/${_primary}/*) + list(APPEND _sources ${_primary_sources}) + + set(_secondary_sources "") + foreach(_name IN LISTS _secondary_names) + set(_path ${CMAKE_CURRENT_SOURCE_DIR}/generated/${_secondary}/${_name}) + if(EXISTS ${_path}) + list(APPEND _secondary_sources ${_path}) + endif() + endforeach() + + # from the manifest, not a glob: a stale .c left in the directory must not + # silently enter the build + set(_glue_sources "") + foreach(_name IN LISTS _glue_names) + list(APPEND _glue_sources ${MUI_GLUE_DIR}/${_name}) + endforeach() + list(APPEND _sources ${_secondary_sources} ${_glue_sources}) + + # The secondary tree and the secondary-side bridge must see the renames and + # the secondary headers; the primary-side bridge must see the primary tree + # untouched. + set(_rename_flags + -include ${MUI_GLUE_DIR}/ui_secondary_rename.h + -I${CMAKE_CURRENT_SOURCE_DIR}/generated/${_secondary}) + set_source_files_properties( + ${_secondary_sources} ${MUI_GLUE_DIR}/bridge_secondary.c + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + PROPERTIES COMPILE_OPTIONS "${_rename_flags}") + + # C++ sources referencing generated styles dispatch them to the active tree. + set_source_files_properties( + ${CMAKE_CURRENT_SOURCE_DIR}/source/graphics/TFT/Themes.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/source/graphics/TFT/TFTView_320x240.cpp + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + PROPERTIES COMPILE_OPTIONS "-include;${MUI_GLUE_DIR}/style_routing.h") + + set(MUI_PRIMARY_VIEW ${_primary} PARENT_SCOPE) + set(${sources_var} ${_sources} PARENT_SCOPE) +endfunction() + +function(mui_runtime_rotation_configure target) + target_compile_definitions(${target} PUBLIC MUI_RUNTIME_ROTATION) + target_include_directories(${target} PUBLIC ${MUI_GLUE_DIR}) +endfunction() diff --git a/extra_script.py b/extra_script.py index e8269abd..ddae87dc 100644 --- a/extra_script.py +++ b/extra_script.py @@ -1,6 +1,9 @@ # See https://docs.platformio.org/en/latest/manifests/library-json/fields/build/extrascript.html Import("env") -from os.path import join, realpath +import os +import subprocess +from os.path import basename, join, realpath + # Base srcFilter. Cannot be set in library.json. src_filter = [ "+", @@ -8,17 +11,96 @@ "+" ] +DUAL_UI_VIEWS = ("ui_320x240", "ui_240x320") + + +def define_name(item): + # CPPDEFINES entries are either "NAME" or a ("NAME", value) pair + if isinstance(item, str): + return item + if isinstance(item, (list, tuple)) and item: + return str(item[0]) + return "" + + +view = None +runtime_rotation = False for item in env.get("CPPDEFINES", []): + name = define_name(item) # Add generated view directory to include path dependending on VIEW_* macro - if isinstance(item,str) and item.startswith("VIEW_"): - view = f"ui_{item[5:]}".lower() # Ex value: "ui_320x240" + if name.startswith("VIEW_"): + view = f"ui_{name[5:]}".lower() # Ex value: "ui_320x240" env.Append(CPPPATH=[realpath(join("generated", view))]) src_filter.append(f"+") + elif name == "MUI_RUNTIME_ROTATION": + runtime_rotation = True # Add portduino directory to include path dependending on ARCH_PORTDUINO macro - elif item == "ARCH_PORTDUINO": + elif name == "ARCH_PORTDUINO": env.Append(CPPPATH=[realpath("portduino")]) src_filter.append("+") +if runtime_rotation: + # Link both perpendicular layouts so the rotation becomes a runtime setting. + # The primary tree (this build's VIEW_*) supplies every shared asset; the + # secondary tree is compiled with its colliding globals renamed through a + # generated forced include. + if view not in DUAL_UI_VIEWS: + raise Exception("MUI_RUNTIME_ROTATION supports only %s, not %r" + % (" and ".join(DUAL_UI_VIEWS), view)) + secondary = DUAL_UI_VIEWS[1] if view == DUAL_UI_VIEWS[0] else DUAL_UI_VIEWS[0] + + lib_root = realpath(".") + generated = join(lib_root, "tools", "generated", "dual") + generator = join(lib_root, "tools", "gen_dual_ui.py") + + # Fails the build when the committed glue no longer matches the UI trees. + check = subprocess.run([env.subst("$PYTHONEXE"), generator, "--check", view], + capture_output=True, text=True) + if check.returncode != 0: + raise Exception("MUI_RUNTIME_ROTATION: %s%s" % (check.stdout, check.stderr)) + + core_sources, secondary_assets, glue_sources = [], [], [] + with open(join(generated, "manifest.txt")) as f: + for line in f: + key, _, value = line.strip().partition(" ") + if key == "core_source": + core_sources.append(value) + elif key == "glue_source": + glue_sources.append(value) + elif key == "secondary_asset": + # "secondary_asset ": only when is the + # secondary tree does its unique asset have to be compiled + view_name, _, asset = value.partition(" ") + if view_name == secondary: + secondary_assets.append(asset) + + for src_name in core_sources + secondary_assets: + if os.path.exists(join(lib_root, "generated", secondary, src_name)): + src_filter.append(f"+") + # listed rather than globbed, so a stale .c cannot enter the build + for src_name in glue_sources: + src_filter.append(f"+") + env.Append(CPPPATH=[generated]) + + rename_flags = ["-include", join(generated, "ui_secondary_rename.h"), + "-I", realpath(join("generated", secondary))] + routing_flags = ["-include", join(generated, "style_routing.h")] + STYLE_ROUTED_CXX = ("Themes.cpp", "TFTView_320x240.cpp") + + def apply_dual_ui_flags(env, node): + path = realpath(node.srcnode().get_abspath()) + name = basename(path) + secondary_tu = os.sep + secondary + os.sep in path and name not in secondary_assets + # the secondary-side bridge needs the secondary screens.h and the + # renames; the primary-side bridge must see the primary tree untouched + if secondary_tu or name == "bridge_secondary.c": + return env.Object(node, CPPFLAGS=env.get("CPPFLAGS", []) + rename_flags) + if name in STYLE_ROUTED_CXX: + return env.Object(node, CXXFLAGS=env.get("CXXFLAGS", []) + routing_flags) + return node + + env.AddBuildMiddleware(apply_dual_ui_flags, "*") + # Only `Replace` is supported for SRC_FILTER, not `Append` or `Prepend` env.Replace(SRC_FILTER=src_filter) diff --git a/include/graphics/ScreenRotation.h b/include/graphics/ScreenRotation.h new file mode 100644 index 00000000..bad549c6 --- /dev/null +++ b/include/graphics/ScreenRotation.h @@ -0,0 +1,69 @@ +#pragma once + +#ifdef MUI_RUNTIME_ROTATION + +// Only these two layouts are perpendicular counterparts of each other. +#if !defined(VIEW_320x240) && !defined(VIEW_240x320) +#error "MUI_RUNTIME_ROTATION requires VIEW_320x240 or VIEW_240x320" +#endif + +// Those drivers apply a fixed rotation to touch coordinates and would +// desynchronize from a rotated panel. +#ifdef CUSTOM_TOUCH_DRIVER +#error "MUI_RUNTIME_ROTATION is not supported with CUSTOM_TOUCH_DRIVER" +#endif + +#include + +/** + * Runtime screen rotation for builds that link both generated UI layouts. + * + * The stored value is a quarter-turn count applied on top of the board's + * compile-time LGFX_ROTATION offset, so value 0 reproduces the board's default. + * Even values keep the compile-time VIEW_* layout, odd values select the + * perpendicular one. Applied at boot only: an LVGL layout tree cannot be + * rebuilt in place once the view has cached its object pointers. + */ +class ScreenRotation +{ + public: + enum Value : uint8_t { + Rotation0 = 0, + Rotation90 = 1, + Rotation180 = 2, + Rotation270 = 3, + }; + + /// Supplied by the integrator before the display is created. Out-of-range + /// values fall back to the build default. Ignored after the first call. + static void setLoaded(uint8_t raw); + static void load(void); + static Value get(void) { return current; } + + /// Odd quarter turns swap the aspect, so they need the perpendicular tree. + static bool usesSecondaryTree(Value v) { return ((uint8_t)v & 1) != 0; } + + /// Nominal size of the layout, for seeding DisplayDriver. NOT the panel + /// resolution -- the driver reads that from the rotated panel. + static uint16_t width(Value v); + static uint16_t height(Value v); + + /// Value passed to setRotation(); LovyanGFX composes it with the board's + /// offset_rotation. The quarter turns run opposite to the panel's own + /// numbering so that a rotation reads upright to the user: hardware-checked + /// on a 320x240 panel with offset_rotation 3, where upright portrait is + /// panel rotation 2, i.e. one step back from upright landscape, not one + /// step on. Parity is preserved, so tree selection is unaffected. + static uint8_t panelRotation(Value v) { return (uint8_t)((4 - (uint8_t)v) & 3); } + + static bool usesSecondaryTree(void) { return usesSecondaryTree(current); } + static uint16_t width(void) { return width(current); } + static uint16_t height(void) { return height(current); } + static uint8_t panelRotation(void) { return panelRotation(current); } + + private: + static Value current; + static bool loaded; +}; + +#endif // MUI_RUNTIME_ROTATION diff --git a/include/graphics/driver/LGFXDriver.h b/include/graphics/driver/LGFXDriver.h index 2255d2f9..486b6424 100644 --- a/include/graphics/driver/LGFXDriver.h +++ b/include/graphics/driver/LGFXDriver.h @@ -1,6 +1,9 @@ #pragma once #include "LovyanGFX.h" +#ifdef MUI_RUNTIME_ROTATION +#include "graphics/ScreenRotation.h" +#endif #include "graphics/driver/DisplayDriverConfig.h" #include "graphics/driver/TFTDriver.h" #include "input/InputDriver.h" @@ -321,7 +324,19 @@ template void LGFXDriver::init(DeviceGUI *gui) lv_display_add_event_cb(this->display, rounder_cb, LV_EVENT_INVALIDATE_AREA, this->display); #endif -#if defined(DISPLAY_SET_RESOLUTION) +#if defined(MUI_RUNTIME_ROTATION) + // Rotate before any layout exists, then take the resolution from the + // rotated panel itself: the layout's nominal size must not be substituted + // here, or panels larger than the layout (e.g. 320x480) would be told the + // wrong size. + ScreenRotation::load(); + { + ISpiLock::Guard bus; // setRotation talks to the panel + lgfx->setRotation(ScreenRotation::panelRotation()); + } + ILOG_DEBUG("Set display resolution: %dx%d, rotation %d", lgfx->width(), lgfx->height(), ScreenRotation::panelRotation()); + lv_display_set_resolution(this->display, lgfx->width(), lgfx->height()); +#elif defined(DISPLAY_SET_RESOLUTION) ILOG_DEBUG("Set display resolution: %dx%d", lgfx->screenWidth, lgfx->screenHeight); lv_display_set_resolution(this->display, lgfx->screenWidth, lgfx->screenHeight); #endif diff --git a/include/graphics/view/TFT/TFTView_320x240.h b/include/graphics/view/TFT/TFTView_320x240.h index 1730f308..00b4472e 100644 --- a/include/graphics/view/TFT/TFTView_320x240.h +++ b/include/graphics/view/TFT/TFTView_320x240.h @@ -106,7 +106,10 @@ class TFTView_320x240 : public MeshtasticView eReset, eReboot, eDisplayMode, - eModifyChannel + eModifyChannel, +#ifdef MUI_RUNTIME_ROTATION + eScreenRotation +#endif }; protected: @@ -368,6 +371,20 @@ class TFTView_320x240 : public MeshtasticView static void ui_event_cancel(lv_event_t *e); static void ui_event_backup_restore_radio_button(lv_event_t *e); +#ifdef MUI_RUNTIME_ROTATION + static void ui_event_screen_rotation_button(lv_event_t *e); + void showScreenRotationDialog(void); + void applyScreenRotationDialog(void); + void closeScreenRotationDialog(void); + void updateScreenRotationLabel(void); + // the generated ok_cancel_widget writes into the objects struct by index, + // so the row is rebuilt here instead of reused + void addOkCancelRow(lv_obj_t *parent); + lv_obj_t *screenRotationLabel = nullptr; + lv_obj_t *screenRotationPanel = nullptr; + lv_obj_t *screenRotationDropdown = nullptr; +#endif + // map navigation static void ui_screen_event_cb(lv_event_t *e); static void ui_event_arrow(lv_event_t *e); diff --git a/locale/bg.yml b/locale/bg.yml index b56ee124..18040506 100644 --- a/locale/bg.yml +++ b/locale/bg.yml @@ -144,3 +144,11 @@ bg: Sound only: Само звук no signal: ~ Restoring messages ...: ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/cs.yml b/locale/cs.yml index b87c2ef0..60b795f5 100644 --- a/locale/cs.yml +++ b/locale/cs.yml @@ -144,3 +144,11 @@ cs: region unset: region nenastaven no signal: bez signálu Restoring messages ...: Obnovuji zprávy... + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/da.yml b/locale/da.yml index bfd47794..155c7fb5 100644 --- a/locale/da.yml +++ b/locale/da.yml @@ -165,3 +165,11 @@ da: SD card error: SD-kort fejl SD unknown error: Ukendt SD-kort-fejl "Heap: %d (%d%%)\nLVGL: %d (%d%%)": "Heap: %d (%d%%)\nLVGL: %d (%d%%)" + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/de.yml b/locale/de.yml index e939bd56..29d17de1 100644 --- a/locale/de.yml +++ b/locale/de.yml @@ -154,3 +154,11 @@ de: region unset: keine Region no signal: kein Signal Restoring messages ...: Lade Nachrichten... + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/el.yml b/locale/el.yml index 72ad621a..05c1d001 100644 --- a/locale/el.yml +++ b/locale/el.yml @@ -167,3 +167,11 @@ el: SD card error: SD σφάλμα κάρτας SD unknown error: SD άγνωστο σφάλμα "Heap: %d (%d%%)\nLVGL: %d (%d%%)": ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/en.yml b/locale/en.yml index 8c0a27bb..9fe78563 100644 --- a/locale/en.yml +++ b/locale/en.yml @@ -167,3 +167,11 @@ en: SD card error: ~ SD unknown error: ~ "Heap: %d (%d%%)\nLVGL: %d (%d%%)": ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/es.yml b/locale/es.yml index bc83677b..e81556f9 100644 --- a/locale/es.yml +++ b/locale/es.yml @@ -162,3 +162,11 @@ es: 'Failed to parse keys!': Error procesando claves! 'Failed to retrieve keys!': Error obteniendo ficheros! "%s (%0.1f GB)\nUsed: %d MB (%d%%)": "%s (%0.1f GB)\nUsado: %d MB (%d%%)" + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/fi.yml b/locale/fi.yml index a980c9b9..21ebb5ea 100644 --- a/locale/fi.yml +++ b/locale/fi.yml @@ -150,3 +150,11 @@ fi: Sound only: ~ no signal: ~ Restoring messages ...: ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/fr.yml b/locale/fr.yml index c28a9594..990793fe 100644 --- a/locale/fr.yml +++ b/locale/fr.yml @@ -157,3 +157,11 @@ fr: Failed to parse keys!: Erreur de lecture! Failed to retrieve keys!: Erreur de lecture! "%s (%0.1f GB)\nUsed: %d MB (%d%%)": "%s (%0.1f GB)\nUtilisé: %d MB (%d%%)" + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/hu.yml b/locale/hu.yml index d37a5242..3302cb49 100644 --- a/locale/hu.yml +++ b/locale/hu.yml @@ -167,3 +167,11 @@ hu: SD card error: SD-kártya hiba SD unknown error: Ismeretlen SD-hiba "Heap: %d (%d%%)\nLVGL: %d (%d%%)": ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/it.yml b/locale/it.yml index 37f2e232..84284380 100644 --- a/locale/it.yml +++ b/locale/it.yml @@ -144,3 +144,11 @@ it: Sound only: Solo Suono no signal: nessun segnale Restoring messages ...: ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/nl.yml b/locale/nl.yml index 3ad3ffd3..3a4a34dd 100644 --- a/locale/nl.yml +++ b/locale/nl.yml @@ -187,3 +187,11 @@ nl: Failed to parse keys!: Keys verwerken mislukt! Failed to retrieve keys!: Keys ophalen mislukt! "%s (%0.1f GB)\nUsed: %d MB (%d%%)": "%s (%0.1f GB)\nGebruikt: %d MB (%d%%)" + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/no.yml b/locale/no.yml index 7e61e19e..325bcd86 100644 --- a/locale/no.yml +++ b/locale/no.yml @@ -189,3 +189,11 @@ no: Failed to parse keys!: Analysering av nøkler feilet! Failed to retrieve keys!: Mottak av nøkler feilet! "%s: %d GB (%s)\nUsed: %0.2f GB (%d%%)": "%s: %d GB (%s)\nBrukt: %0.2f GB (%d%%)" + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/pl.yml b/locale/pl.yml index 8c052896..430e819b 100644 --- a/locale/pl.yml +++ b/locale/pl.yml @@ -152,3 +152,11 @@ pl: Sound only: ~ no signal: ~ Restoring messages ...: ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/pt.yml b/locale/pt.yml index 7ad8027f..db3fa6b9 100644 --- a/locale/pt.yml +++ b/locale/pt.yml @@ -172,3 +172,11 @@ pt: Sound only: ~ no signal: ~ Restoring messages ...: ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/ro.yml b/locale/ro.yml index 30b450dc..dcddd3dc 100644 --- a/locale/ro.yml +++ b/locale/ro.yml @@ -141,3 +141,11 @@ ro: Sound only: ~ no signal: ~ Restoring messages ...: ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/ru.yml b/locale/ru.yml index d6c1d141..fa8ef1ab 100644 --- a/locale/ru.yml +++ b/locale/ru.yml @@ -140,3 +140,11 @@ ru: Sound only: Только звук no signal: ~ Restoring messages ...: ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/se.yml b/locale/se.yml index 3bb8b7e4..1048afd8 100644 --- a/locale/se.yml +++ b/locale/se.yml @@ -196,3 +196,11 @@ se: Client Hidden Lost & Found TAK Tracker + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/sl.yml b/locale/sl.yml index d65deb96..f859cd3b 100644 --- a/locale/sl.yml +++ b/locale/sl.yml @@ -154,3 +154,11 @@ sl: region unset: regija ni nastavljena no signal: ni signala Restoring messages ...: ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/sr.yml b/locale/sr.yml index 7df6c736..7e17ef08 100644 --- a/locale/sr.yml +++ b/locale/sr.yml @@ -153,3 +153,11 @@ sr: region unset: ~ no signal: ~ Restoring messages ...: ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/tr.yml b/locale/tr.yml index 195e9cae..a6c3713a 100644 --- a/locale/tr.yml +++ b/locale/tr.yml @@ -143,3 +143,11 @@ tr: Sound only: Sadece ses no signal: Sinyal yok Restoring messages ...: Mesajlar kurtarılıyor... + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/uk.yml b/locale/uk.yml index 34f71b41..8307330d 100644 --- a/locale/uk.yml +++ b/locale/uk.yml @@ -157,3 +157,11 @@ uk: 'uptime: %02d:%02d:%02d': 'час роботи: %02d:%02d:%02d' "%s (%0.1f GB)\nUsed: %d MB (%d%%)": "%s (%0.1f GB)\nВикорист.: %d MB (%d%%)" "Heap: %d (%d%%)\nLVGL: %d (%d%%)": ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/locale/zh-CN.yml b/locale/zh-CN.yml index 946d496c..f37fdd00 100644 --- a/locale/zh-CN.yml +++ b/locale/zh-CN.yml @@ -131,3 +131,11 @@ zh-CN: region unset: 区域未设置 no signal: 无信号 Restoring messages ...: ~ + Orientation: ~ + Landscape: ~ + Portrait: ~ + Landscape flipped: ~ + Portrait flipped: ~ + Restarting to apply: ~ + Save failed: ~ + Restart required: ~ diff --git a/source/graphics/ScreenRotation.cpp b/source/graphics/ScreenRotation.cpp new file mode 100644 index 00000000..20733351 --- /dev/null +++ b/source/graphics/ScreenRotation.cpp @@ -0,0 +1,48 @@ +#ifdef MUI_RUNTIME_ROTATION + +#include "graphics/ScreenRotation.h" +#include "util/ILog.h" + +#if defined(VIEW_240x320) +static const uint16_t kPrimaryWidth = 240; +static const uint16_t kPrimaryHeight = 320; +#else +static const uint16_t kPrimaryWidth = 320; +static const uint16_t kPrimaryHeight = 240; +#endif + +ScreenRotation::Value ScreenRotation::current = ScreenRotation::Rotation0; +bool ScreenRotation::loaded = false; + +void ScreenRotation::setLoaded(uint8_t raw) +{ + if (loaded) + return; + loaded = true; + if (raw > (uint8_t)Rotation270) { + ILOG_WARN("invalid stored screen rotation %u, using %u", raw, (unsigned)current); + return; + } + current = (Value)raw; + ILOG_INFO("screen rotation %u restored", (unsigned)current); +} + +void ScreenRotation::load(void) +{ + if (!loaded) { + loaded = true; + ILOG_WARN("screen rotation not supplied, using %u", (unsigned)current); + } +} + +uint16_t ScreenRotation::width(Value v) +{ + return usesSecondaryTree(v) ? kPrimaryHeight : kPrimaryWidth; +} + +uint16_t ScreenRotation::height(Value v) +{ + return usesSecondaryTree(v) ? kPrimaryWidth : kPrimaryHeight; +} + +#endif // MUI_RUNTIME_ROTATION diff --git a/source/graphics/TFT/TFTView_320x240.cpp b/source/graphics/TFT/TFTView_320x240.cpp index e572a936..d7e17366 100644 --- a/source/graphics/TFT/TFTView_320x240.cpp +++ b/source/graphics/TFT/TFTView_320x240.cpp @@ -22,6 +22,15 @@ #include "util/FileLoader.h" #include "util/ILog.h" #include "util/ISpiLock.h" +#ifdef MUI_RUNTIME_ROTATION +#include "graphics/ScreenRotation.h" +// secondary (renamed) generated tree plus the generated field-wise bridge +extern "C" { +void MUI2_ui_init_boot(void); +void MUI2_ui_init(void); +void mui_bridge_publish_secondary(void); +} +#endif #include #include #include @@ -126,7 +135,14 @@ bool TFTView_320x240::screenUnlockRequest = false; TFTView_320x240 *TFTView_320x240::instance(void) { if (!gui) { +#ifdef MUI_RUNTIME_ROTATION + // the driver applies the stored rotation during init(); these sizes + // only seed DisplayDriver's members, so they come from the same source + ScreenRotation::load(); + gui = new TFTView_320x240(nullptr, DisplayDriverFactory::create(ScreenRotation::width(), ScreenRotation::height())); +#else gui = new TFTView_320x240(nullptr, DisplayDriverFactory::create(320, 240)); +#endif } return gui; } @@ -171,7 +187,16 @@ void TFTView_320x240::init(IClientBase *client) MeshtasticView::init(client); +#ifdef MUI_RUNTIME_ROTATION + if (ScreenRotation::usesSecondaryTree()) { + MUI2_ui_init_boot(); + mui_bridge_publish_secondary(); // must precede any objects.* deref + } else { + ui_init_boot(); + } +#else ui_init_boot(); +#endif FileLoader::init(&fileSystem); if (!FileLoader::loadBootImage(objects.boot_logo)) lv_image_set_src(objects.boot_logo, &img_meshtastic_boot_logo_image); @@ -356,7 +381,16 @@ void TFTView_320x240::init_screens(void) { ILOG_DEBUG("init screens..."); state = MeshtasticView::eInitScreens; +#ifdef MUI_RUNTIME_ROTATION + if (ScreenRotation::usesSecondaryTree()) { + MUI2_ui_init(); + mui_bridge_publish_secondary(); // before apply_hotfix caches pointers + } else { + ui_init(); + } +#else ui_init(); +#endif apply_hotfix(); activeMsgContainer = objects.messages_container; @@ -625,6 +659,10 @@ void TFTView_320x240::apply_hotfix(void) int32_t rows = 12; if (h > 320) { width = (h - 48 - 57) / 6; + } else if (h < 320) { + // narrow screens (240 px portrait): the default 57 + 6*36 = 273 does + // not fit, so shrink the six data columns instead of overflowing + width = (h - 57 - 6) / 6; } if (v > 240) { rows = (v - 32) / 18; @@ -787,6 +825,21 @@ void TFTView_320x240::ui_events_init(void) lv_obj_add_event_cb(objects.basic_settings_reset_button, ui_event_reset_button, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(objects.basic_settings_reboot_button, ui_event_reboot_button, LV_EVENT_CLICKED, NULL); +#ifdef MUI_RUNTIME_ROTATION + { + // the feature is build-time optional, so no generated entry exists for + // it; the row is created here with the generated button style + lv_obj_t *rotationButton = lv_button_create(lv_obj_get_parent(objects.basic_settings_timezone_button)); + lv_obj_set_size(rotationButton, LV_PCT(95), 30); + add_style_settings_button_style(rotationButton); + lv_obj_set_style_shadow_width(rotationButton, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + screenRotationLabel = lv_label_create(rotationButton); + lv_obj_set_align(screenRotationLabel, LV_ALIGN_LEFT_MID); + updateScreenRotationLabel(); + lv_obj_add_event_cb(rotationButton, ui_event_screen_rotation_button, LV_EVENT_CLICKED, NULL); + } +#endif + lv_obj_add_event_cb(objects.reboot_button, ui_event_device_reboot_button, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(objects.progmode_button, ui_event_device_progmode_button, LV_EVENT_ALL, NULL); lv_obj_add_event_cb(objects.shutdown_button, ui_event_device_shutdown_button, LV_EVENT_CLICKED, NULL); @@ -4253,6 +4306,12 @@ void TFTView_320x240::ui_event_ok(lv_event_t *e) } return; } +#ifdef MUI_RUNTIME_ROTATION + case eScreenRotation: + // apply/close own the panel state, so skip the common tail + THIS->applyScreenRotationDialog(); + return; +#endif default: ILOG_ERROR("Unhandled ok event"); break; @@ -4371,6 +4430,11 @@ void TFTView_320x240::ui_event_cancel(lv_event_t *e) THIS->activeSettings = eChannel; return; } +#ifdef MUI_RUNTIME_ROTATION + case eScreenRotation: + THIS->closeScreenRotationDialog(); // owns the panel state + return; +#endif default: ILOG_ERROR("Unhandled cancel event"); break; @@ -5891,6 +5955,186 @@ bool TFTView_320x240::isScreenLocked(void) return screenLocked && !screenUnlockRequest; } +#ifdef MUI_RUNTIME_ROTATION + +// Even values keep the primary layout's aspect, odd values use the +// perpendicular one, so which label a value carries depends on which tree this +// build compiled as primary. +static const char *rotationValueName(uint8_t value) +{ + switch (value & 3) { +#if defined(VIEW_240x320) + case ScreenRotation::Rotation0: + return _("Portrait"); + case ScreenRotation::Rotation90: + return _("Landscape"); + case ScreenRotation::Rotation180: + return _("Portrait flipped"); + default: + return _("Landscape flipped"); +#else + case ScreenRotation::Rotation0: + return _("Landscape"); + case ScreenRotation::Rotation90: + return _("Portrait"); + case ScreenRotation::Rotation180: + return _("Landscape flipped"); + default: + return _("Portrait flipped"); +#endif + } +} + +void TFTView_320x240::updateScreenRotationLabel(void) +{ + if (!screenRotationLabel) + return; + char buf[64]; + lv_snprintf(buf, sizeof(buf), "%s: %s", _("Orientation"), rotationValueName((uint8_t)ScreenRotation::get())); + lv_label_set_text(screenRotationLabel, buf); +} + +void TFTView_320x240::ui_event_screen_rotation_button(lv_event_t *e) +{ + if (lv_event_get_code(e) == LV_EVENT_CLICKED && THIS->activeSettings == eNone) + THIS->showScreenRotationDialog(); +} + +void TFTView_320x240::showScreenRotationDialog(void) +{ + if (screenRotationPanel || activeSettings != eNone) + return; + + // copies the generated dropdown-panel idiom (SettingsDeviceRolePanel) + screenRotationPanel = lv_obj_create(objects.main_screen); + lv_obj_set_pos(screenRotationPanel, LV_PCT(3), LV_PCT(25)); + lv_obj_set_size(screenRotationPanel, 220, 120); + lv_obj_clear_flag(screenRotationPanel, LV_OBJ_FLAG_SCROLLABLE); + add_style_settings_panel_style(screenRotationPanel); + lv_obj_set_style_pad_all(screenRotationPanel, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(screenRotationPanel, 2, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_radius(screenRotationPanel, 12, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(screenRotationPanel, lv_color_hex(0xff216ad8), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_align(screenRotationPanel, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_opa(screenRotationPanel, 255, LV_PART_MAIN | LV_STATE_DEFAULT); + + screenRotationDropdown = lv_dropdown_create(screenRotationPanel); + lv_obj_set_pos(screenRotationDropdown, 0, 8); + lv_obj_set_size(screenRotationDropdown, 150, 30); + char options[128]; // option order is the stored value order (0..3) + lv_snprintf(options, sizeof(options), "%s\n%s\n%s\n%s", rotationValueName(ScreenRotation::Rotation0), + rotationValueName(ScreenRotation::Rotation90), rotationValueName(ScreenRotation::Rotation180), + rotationValueName(ScreenRotation::Rotation270)); + lv_dropdown_set_options(screenRotationDropdown, options); + add_style_drop_down_style(screenRotationDropdown); + lv_obj_set_style_align(screenRotationDropdown, LV_ALIGN_TOP_MID, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_color(screenRotationDropdown, lv_color_hex(0xffe0e0e0), LV_PART_MAIN | LV_STATE_DEFAULT); + // the persisted value, which is what the next boot will use + lv_dropdown_set_selected(screenRotationDropdown, (uint8_t)db.uiConfig.screen_rotation); + + addOkCancelRow(screenRotationPanel); + lv_group_focus_obj(screenRotationDropdown); + disablePanel(objects.controller_panel); + disablePanel(objects.tab_page_basic_settings); + activeSettings = eScreenRotation; +} + +void TFTView_320x240::applyScreenRotationDialog(void) +{ + // Compare against the persisted value, not the active one: a change saved + // earlier may still be waiting for the restart, and re-picking the active + // value then has to be treated as a real change back. + const uint8_t persisted = (uint8_t)db.uiConfig.screen_rotation; + const uint8_t choice = screenRotationDropdown ? (uint8_t)lv_dropdown_get_selected(screenRotationDropdown) : persisted; + if (choice > (uint8_t)ScreenRotation::Rotation270 || choice == persisted) { + closeScreenRotationDialog(); + if (persisted != (uint8_t)ScreenRotation::get()) + messageAlert(_("Restart required"), true); + return; + } + + // Submit a copy: a failed store must not leave the new value in db.uiConfig, + // where an unrelated save would later persist it behind the user's back. + meshtastic_DeviceUIConfig cfg = db.uiConfig; + cfg.screen_rotation = (meshtastic_DeviceUIConfig_ScreenRotation)choice; + if (!controller->storeUIConfig(cfg)) { + messageAlert(_("Save failed"), true); + return; // dialog stays open so OK can be retried + } + db.uiConfig = cfg; // persisted, keep the in-memory copy in sync + + // The value is only read at boot, and the firmware keeps serving the + // pre-change config until it reloads, so the reboot is part of applying it + // (same pattern as the language setting). + if (!controller->requestReboot(5)) { + messageAlert(_("Restart required"), true); + return; + } + closeScreenRotationDialog(); + messageAlert(_("Restarting to apply"), true); +} + +void TFTView_320x240::closeScreenRotationDialog(void) +{ + if (activeSettings == eScreenRotation) { + activeSettings = eNone; + enablePanel(objects.controller_panel); + enablePanel(objects.tab_page_basic_settings); + if (screenRotationLabel) + lv_group_focus_obj(lv_obj_get_parent(screenRotationLabel)); // back to the opener + } + if (screenRotationPanel) { + lv_obj_delete(screenRotationPanel); + screenRotationPanel = nullptr; + screenRotationDropdown = nullptr; // child of the panel + } +} + +void TFTView_320x240::addOkCancelRow(lv_obj_t *parent) +{ + // visual copy of the generated ok_cancel_widget: the generated function + // cannot be reused because it writes its objects into the objects struct + // by index + lv_obj_t *row = lv_obj_create(parent); + lv_obj_set_size(row, 160, 50); + lv_obj_clear_flag(row, (lv_obj_flag_t)(LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | + LV_OBJ_FLAG_SCROLL_WITH_ARROW)); // C++ needs the explicit cast + lv_obj_set_scrollbar_mode(row, LV_SCROLLBAR_MODE_OFF); + lv_obj_set_scroll_dir(row, LV_DIR_NONE); + add_style_panel_style(row); + lv_obj_set_style_align(row, LV_ALIGN_BOTTOM_MID, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_border_width(row, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_layout(row, LV_LAYOUT_FLEX, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_top(row, 8, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_left(row, 4, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(row, 4, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_flex_main_place(row, LV_FLEX_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT); + + struct { + const char *text; + lv_align_t align; + lv_event_cb_t cb; + bool pad; + } spec[2] = {{_("OK"), LV_ALIGN_LEFT_MID, ui_event_ok, false}, {_("Cancel"), LV_ALIGN_RIGHT_MID, ui_event_cancel, true}}; + for (auto &b : spec) { + lv_obj_t *btn = lv_btn_create(row); + lv_obj_set_size(btn, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_obj_set_style_bg_color(btn, lv_color_hex(0xff216ad8), LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_radius(btn, 7, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_clip_corner(btn, true, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_align(btn, b.align, LV_PART_MAIN | LV_STATE_DEFAULT); + if (b.pad) { + lv_obj_set_style_pad_left(btn, 10, LV_PART_MAIN | LV_STATE_DEFAULT); + lv_obj_set_style_pad_right(btn, 10, LV_PART_MAIN | LV_STATE_DEFAULT); + } + lv_label_set_text(lv_label_create(btn), b.text); + lv_obj_add_event_cb(btn, b.cb, LV_EVENT_CLICKED, 0); + } +} + +#endif // MUI_RUNTIME_ROTATION + void TFTView_320x240::updateChannelConfig(const meshtastic_Channel &ch) { static lv_obj_t *btn[c_max_channels] = {objects.channel_button0, objects.channel_button1, objects.channel_button2, diff --git a/tests/test_ScreenRotation.cpp b/tests/test_ScreenRotation.cpp new file mode 100644 index 00000000..5fc67de0 --- /dev/null +++ b/tests/test_ScreenRotation.cpp @@ -0,0 +1,69 @@ +#ifdef MUI_RUNTIME_ROTATION + +#include "graphics/ScreenRotation.h" +#include "screens.h" +#include + +// The secondary tree is linked under renamed symbols. Referencing one here +// forces the linker to extract its objects: without this a static-library +// build links green while never pulling in the secondary layout at all. +extern "C" { +extern objects_t MUI2_objects; +void mui_bridge_publish_secondary(void); +} + +TEST_CASE("both generated layouts are linked") +{ + CHECK(&objects != &MUI2_objects); + CHECK(mui_bridge_publish_secondary != nullptr); +} + +TEST_CASE("panel rotation runs opposite to the panel's own numbering") +{ + CHECK(ScreenRotation::panelRotation(ScreenRotation::Rotation0) == 0); + CHECK(ScreenRotation::panelRotation(ScreenRotation::Rotation90) == 3); + CHECK(ScreenRotation::panelRotation(ScreenRotation::Rotation180) == 2); + CHECK(ScreenRotation::panelRotation(ScreenRotation::Rotation270) == 1); + + // parity must survive, or the tree selection would disagree with the size + for (uint8_t v = 0; v <= 3; v++) + CHECK((ScreenRotation::panelRotation((ScreenRotation::Value)v) & 1) == (v & 1)); +} + +TEST_CASE("odd quarter turns select the perpendicular tree") +{ + CHECK_FALSE(ScreenRotation::usesSecondaryTree(ScreenRotation::Rotation0)); + CHECK(ScreenRotation::usesSecondaryTree(ScreenRotation::Rotation90)); + CHECK_FALSE(ScreenRotation::usesSecondaryTree(ScreenRotation::Rotation180)); + CHECK(ScreenRotation::usesSecondaryTree(ScreenRotation::Rotation270)); +} + +TEST_CASE("odd quarter turns swap the layout dimensions") +{ + const uint16_t w = ScreenRotation::width(ScreenRotation::Rotation0); + const uint16_t h = ScreenRotation::height(ScreenRotation::Rotation0); + CHECK(w != h); + + // 180 keeps the aspect, 90/270 transpose it + CHECK(ScreenRotation::width(ScreenRotation::Rotation180) == w); + CHECK(ScreenRotation::height(ScreenRotation::Rotation180) == h); + CHECK(ScreenRotation::width(ScreenRotation::Rotation90) == h); + CHECK(ScreenRotation::height(ScreenRotation::Rotation90) == w); + CHECK(ScreenRotation::width(ScreenRotation::Rotation270) == h); + CHECK(ScreenRotation::height(ScreenRotation::Rotation270) == w); +} + +// The tests above use the pure mapping helpers and never touch the loaded +// state; this is the only one that does, and setLoaded() is deliberately +// one-shot. +TEST_CASE("an out-of-range stored value falls back to the build default") +{ + const ScreenRotation::Value before = ScreenRotation::get(); + ScreenRotation::setLoaded(9); + CHECK(ScreenRotation::get() == before); + + ScreenRotation::setLoaded(ScreenRotation::Rotation90); // ignored, one-shot + CHECK(ScreenRotation::get() == before); +} + +#endif // MUI_RUNTIME_ROTATION diff --git a/tools/gen_dual_ui.py b/tools/gen_dual_ui.py new file mode 100644 index 00000000..b83f9515 --- /dev/null +++ b/tools/gen_dual_ui.py @@ -0,0 +1,406 @@ +#!/usr/bin/env python3 +"""Generate the dual-layout glue used by MUI_RUNTIME_ROTATION builds. + +Both generated UI trees are linked into one binary so the screen rotation +becomes a runtime setting. The primary tree (the build's VIEW_*) keeps its +symbol names; the secondary tree is compiled with its colliding globals renamed +through a generated forced include, and a bridge republishes its widget +pointers into the symbols the C++ view addresses. + +Usage: + python3 tools/gen_dual_ui.py [primary_view] regenerate + python3 tools/gen_dual_ui.py --check [view] verify the committed output +""" + +import hashlib +import os +import re +import sys + +ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) +OUT = os.path.join(ROOT, "tools", "generated", "dual") +VIEWS = ("ui_320x240", "ui_240x320") +DEFAULT_PRIMARY = "ui_320x240" +PREFIX = "MUI2_" + +# Secondary-tree assets the primary tree does not provide and whose image table +# actually references them. Compiled once, never renamed. +SECONDARY_ONLY_ASSETS = ( + "ui_image_top_message_node_images.c", + "ui_image_home_bell_slash_image.c", +) + +# Shared asset definitions, C++-implemented actions, and type/tag tokens that +# are not linker symbols. +NEVER_RENAME = re.compile( + r"^(img_|ui_font_|action_|objects_t|_objects_t|ScreensEnum|SCREEN_ID_|tick_screen_func_t$)" +) + + +def read(path): + with open(path, "r", encoding="utf-8", errors="replace") as f: + return f.read() + + +def core_sources(): + """Every non-asset translation unit, derived from the trees rather than + hardcoded: a newly generated one must not silently enter only one tree. + + Assets are recognised by the ui_image_/ui_font_ filename prefixes, which is + how the UI generator names them. A future asset under a different prefix + would be treated as a core source and compiled into both trees, and its + definition would collide because NEVER_RENAME excludes those symbols from + the rename list. The symmetry assert below cannot see that, so the + prefixes have to stay in sync with the UI generator.""" + per_tree = {} + for view in VIEWS: + d = os.path.join(ROOT, "generated", view) + per_tree[view] = sorted( + n + for n in os.listdir(d) + if n.endswith(".c") and not n.startswith(("ui_image_", "ui_font_")) + ) + a, b = (per_tree[v] for v in VIEWS) + if a != b: + sys.exit( + "ERROR: generated core source sets diverged.\n %s: %s\n %s: %s" + % (VIEWS[0], a, VIEWS[1], b) + ) + return a + + +def objects_members(tree): + src = read(os.path.join(ROOT, "generated", tree, "screens.h")) + m = re.search( + r"typedef\s+struct\s+_objects_t\s*\{(.*?)\}\s*objects_t\s*;", src, re.S + ) + if not m: + sys.exit("ERROR: objects_t definition not found in %s/screens.h" % tree) + return re.findall(r"lv_obj_t\s*\*\s*([A-Za-z_][A-Za-z_0-9]*)\s*;", m.group(1)) + + +def global_symbols(tree, sources): + # Scan the sources, not the headers: styles.h declares only a subset of + # styles.c's globals, so a header-driven rename list would be incomplete. + syms = set() + for src_name in sources: + path = os.path.join(ROOT, "generated", tree, src_name) + if not os.path.exists(path): + continue + src = read(path) + src = re.sub(r"/\*.*?\*/", "", src, flags=re.S) + src = re.sub(r"//[^\n]*", "", src) + for m in re.finditer( + r"^(?!static\b|typedef\b|extern\b|#|\}|\{)" + r"(?:const\s+|unsigned\s+|signed\s+|struct\s+|enum\s+)*" + r"[A-Za-z_][A-Za-z_0-9]*\s+\**\s*" + r"([A-Za-z_][A-Za-z_0-9]*)\s*" + r"(?:\([^;{]*\)\s*\{|\[[^\]]*\]\s*=|=|;)", + src, + re.M, + ): + syms.add(m.group(1)) + return {s for s in syms if not NEVER_RENAME.match(s)} + + +def asset_symbol(name): + """Linker symbol an asset translation unit defines, or None.""" + if name.startswith("ui_image_"): + return "img_" + name[len("ui_image_") : -len(".c")] + if name.startswith("ui_font_"): + return name[: -len(".c")] + return None + + +def tree_sources(tree, name): + path = os.path.join(ROOT, "generated", tree, name) + return read(path) if os.path.exists(path) else "" + + +def asset_inventory(sources): + """Shared assets (present in both trees) must be byte-identical, because + only the primary copy is compiled. Assets unique to one tree have to be + compiled additionally whenever that tree is the secondary one, so the + inventory is computed for both directions.""" + h = hashlib.sha256() + dirs = {v: os.path.join(ROOT, "generated", v) for v in VIEWS} + names = set() + for d in dirs.values(): + names |= { + n + for n in os.listdir(d) + if n.startswith(("ui_image_", "ui_font_")) and n.endswith(".c") + } + + shared, unique = [], {v: [] for v in VIEWS} + for name in sorted(names): + present = [v for v in VIEWS if os.path.exists(os.path.join(dirs[v], name))] + if len(present) == len(VIEWS): + a, b = (read(os.path.join(dirs[v], name)) for v in VIEWS) + if a != b: + sys.exit( + "ERROR: asset %s is no longer identical between trees; the shared-asset " + "deduplication would silently use the primary bytes" % name + ) + shared.append(name) + h.update(name.encode()) + h.update(hashlib.sha256(a.encode()).digest()) + else: + unique[present[0]].append(name) + + # An unlisted unique asset that the tree's own sources reference would be a + # missing definition once that tree is compiled as the secondary one. + for view, extras in unique.items(): + body = "".join(tree_sources(view, s) for s in sources) + for name in extras: + if name in SECONDARY_ONLY_ASSETS: + continue + sym = asset_symbol(name) + if sym and re.search(r"\b%s\b" % re.escape(sym), body): + sys.exit( + "ERROR: %s-only asset %s is now referenced by that tree but is excluded " + "from the build; add it to SECONDARY_ONLY_ASSETS" % (view, name) + ) + + listed = { + v: sorted(n for n in unique[v] if n in SECONDARY_ONLY_ASSETS) for v in VIEWS + } + for view in VIEWS: + for name in listed[view]: + h.update(("%s/%s" % (view, name)).encode()) + h.update( + hashlib.sha256(read(os.path.join(dirs[view], name)).encode()).digest() + ) + return h.hexdigest(), len(shared), listed + + +def build_artifacts(): + """Return {filename: content} for every generated file. + + The output is orientation-neutral: both trees expose the same member and + symbol sets and the bridge copies field-wise in canonical order, so one set + of artifacts serves either tree as the primary one.""" + first, second = VIEWS + sources = core_sources() + a_members, b_members = objects_members(first), objects_members(second) + if set(a_members) != set(b_members): + sys.exit( + "ERROR: objects_t member sets diverged.\n %s-only: %s\n %s-only: %s" + % ( + first, + sorted(set(a_members) - set(b_members)), + second, + sorted(set(b_members) - set(a_members)), + ) + ) + members = sorted(set(a_members)) + + a_syms, b_syms = global_symbols(first, sources), global_symbols(second, sources) + if a_syms != b_syms: + sys.exit( + "ERROR: global symbol sets are not symmetric; the rename list would be wrong.\n" + " %s-only: %s\n %s-only: %s" + % (first, sorted(a_syms - b_syms), second, sorted(b_syms - a_syms)) + ) + syms = sorted(a_syms) + ui_ptrs = sorted( + s + for s in syms + if s.startswith("ui_") and s not in ("ui_init", "ui_tick", "ui_init_boot") + ) + assets_fp, shared_assets, unique_assets = asset_inventory(sources) + fp = hashlib.sha256( + ( + "|".join(sources) + + "#" + + "|".join(members) + + "#" + + "|".join(syms) + + "#" + + "|".join(ui_ptrs) + + "#" + + assets_fp + ).encode() + ).hexdigest() + + banner = "// GENERATED by tools/gen_dual_ui.py - do not edit.\n" + out = {} + + # lvgl.h must come before the defines so the generic names (objects, + # images, add_style, ...) cannot leak into the dependency headers. + rename = [ + banner, + "// Forced include for the secondary generated tree's sources only.\n", + "#pragma once\n#include \n\n", + ] + rename += ["#define %s %s%s\n" % (s, PREFIX, s) for s in syms] + out["ui_secondary_rename.h"] = "".join(rename) + + # The two objects_t structs share member names but not member order, so the + # bridge copies field-wise by name. Neither side may include both trees' + # screens.h (identical include guards), hence the flat intermediate arrays. + sec = [ + banner, + "// Secondary tree (renamed): flatten objects + ui_* pointers into\n", + "// canonical (alphabetical) order.\n", + '#include "screens.h"\n\n', + "lv_obj_t *mui_secondary_objects_flat[%d];\n" % len(members), + "lv_obj_t *mui_secondary_ui_flat[%d];\n\n" % len(ui_ptrs), + "void mui_bridge_collect_secondary(void)\n{\n", + ] + sec += [ + " mui_secondary_objects_flat[%d] = objects.%s;\n" % (i, n) + for i, n in enumerate(members) + ] + sec += [ + " mui_secondary_ui_flat[%d] = %s;\n" % (i, n) for i, n in enumerate(ui_ptrs) + ] + sec.append("}\n") + out["bridge_secondary.c"] = "".join(sec) + + pri = [ + banner, + "// Primary tree: publish the flattened secondary pointers into the\n", + "// symbols the C++ view addresses.\n", + '#include "screens.h"\n\n', + "extern lv_obj_t *mui_secondary_objects_flat[%d];\n" % len(members), + "extern lv_obj_t *mui_secondary_ui_flat[%d];\n" % len(ui_ptrs), + "void mui_bridge_collect_secondary(void);\n\n", + "void mui_bridge_publish_secondary(void)\n{\n", + " mui_bridge_collect_secondary();\n", + ] + pri += [ + " objects.%s = mui_secondary_objects_flat[%d];\n" % (n, i) + for i, n in enumerate(members) + ] + pri += [ + " %s = mui_secondary_ui_flat[%d];\n" % (n, i) for i, n in enumerate(ui_ptrs) + ] + pri.append("}\n") + out["bridge_primary.c"] = "".join(pri) + + # The secondary tree attaches its own renamed style objects, so theme + # mutations and C++ add_style_* calls must reach the active tree or the + # secondary layout renders unthemed. init_style_* is internal to styles.c + # and never called from C++, so it is renamed but not routed. + style_funcs = sorted( + s for s in syms if s.startswith(("get_style_", "add_style_", "remove_style_")) + ) + style_objs = sorted(s for s in syms if s.startswith("style_")) + rt = [ + banner, + "// Force-included into the C++ sources that reference generated styles.\n", + '#pragma once\n#include "graphics/ScreenRotation.h"\n#include "styles.h"\n\n', + 'extern "C" {\n', + ] + for fn in style_funcs: + if fn.startswith("get_style_"): + rt.append("lv_style_t *%s%s(void);\n" % (PREFIX, fn)) + else: + rt.append("void %s%s(lv_obj_t *obj);\n" % (PREFIX, fn)) + rt += ["extern lv_style_t %s%s;\n" % (PREFIX, ob) for ob in style_objs] + rt.append("}\n\n") + for fn in style_funcs: + if fn.startswith("get_style_"): + rt.append( + "static inline lv_style_t *mui_route_%s(void)\n" + "{ return ScreenRotation::usesSecondaryTree() ? %s%s() : %s(); }\n" + "#define %s mui_route_%s\n" % (fn, PREFIX, fn, fn, fn, fn) + ) + else: + rt.append( + "static inline void mui_route_%s(lv_obj_t *obj)\n" + "{ if (ScreenRotation::usesSecondaryTree()) %s%s(obj); else %s(obj); }\n" + "#define %s mui_route_%s\n" % (fn, PREFIX, fn, fn, fn, fn) + ) + for ob in style_objs: + rt.append( + "static inline lv_style_t &mui_route_%s(void)\n" + "{ return ScreenRotation::usesSecondaryTree() ? %s%s : %s; }\n" + "#define %s (mui_route_%s())\n" % (ob, PREFIX, ob, ob, ob, ob) + ) + out["style_routing.h"] = "".join(rt) + + # Single source of truth for the build: which sources each side compiles, + # and which glue files may exist in this directory. + glue_sources = sorted(n for n in out if n.endswith(".c")) + manifest = [ + "members=%d\nrenamed_symbols=%d\nui_pointers=%d\nshared_assets=%d\nfingerprint=%s\n" + % (len(members), len(syms), len(ui_ptrs), shared_assets, fp) + ] + manifest += ["core_source %s\n" % s for s in sources] + manifest += ["glue_source %s\n" % s for s in glue_sources] + # per-direction: extra sources to compile when is the secondary tree + for view in VIEWS: + manifest += ["secondary_asset %s %s\n" % (view, n) for n in unique_assets[view]] + manifest += ["sym %s\n" % s for s in syms] + out["manifest.txt"] = "".join(manifest) + + return out, dict( + members=len(members), + syms=len(syms), + ui_ptrs=len(ui_ptrs), + style_funcs=len(style_funcs), + style_objs=len(style_objs), + fp=fp, + ) + + +def main(): + check_only = "--check" in sys.argv[1:] + args = [a for a in sys.argv[1:] if not a.startswith("--")] + # accepted for symmetry with the build invocation; the output is the same + # for either primary, so it only has to be a supported view + view = args[0] if args else DEFAULT_PRIMARY + if view not in VIEWS: + sys.exit( + "ERROR: MUI_RUNTIME_ROTATION supports only %s; view %r is not one of them" + % (" and ".join(VIEWS), view) + ) + + artifacts, stats = build_artifacts() + + if check_only: + # Regenerate everything and byte-compare: a fingerprint check alone + # would pass on hand-edited output. + for name, want in sorted(artifacts.items()): + path = os.path.join(OUT, name) + if not os.path.exists(path): + sys.exit( + "ERROR: %s is missing; rerun: python3 tools/gen_dual_ui.py" % name + ) + if read(path) != want: + sys.exit( + "ERROR: %s does not match freshly generated output; rerun: " + "python3 tools/gen_dual_ui.py" % name + ) + # the build globs this directory, so a stale file left behind would be + # compiled even though --check never generated it + unexpected = sorted(set(os.listdir(OUT)) - set(artifacts)) + if unexpected: + sys.exit( + "ERROR: unexpected file(s) in %s: %s; remove them and rerun the generator" + % (os.path.relpath(OUT, ROOT), ", ".join(unexpected)) + ) + print("dual-UI glue is current (fingerprint %s)" % stats["fp"][:16]) + return + + os.makedirs(OUT, exist_ok=True) + for name, content in sorted(artifacts.items()): + with open(os.path.join(OUT, name), "w") as f: + f.write(content) + + print("objects_t members: %d (name sets match)" % stats["members"]) + print( + "renamed globals: %d (symmetric across trees), ui_* pointers: %d" + % (stats["syms"], stats["ui_ptrs"]) + ) + print( + "style routing: %d functions + %d objects" + % (stats["style_funcs"], stats["style_objs"]) + ) + print("wrote %s" % OUT) + + +if __name__ == "__main__": + main() diff --git a/tools/generated/dual/bridge_primary.c b/tools/generated/dual/bridge_primary.c new file mode 100644 index 00000000..8488f005 --- /dev/null +++ b/tools/generated/dual/bridge_primary.c @@ -0,0 +1,553 @@ +// GENERATED by tools/gen_dual_ui.py - do not edit. +// Primary tree: publish the flattened secondary pointers into the +// symbols the C++ view addresses. +#include "screens.h" + +extern lv_obj_t *mui_secondary_objects_flat[487]; +extern lv_obj_t *mui_secondary_ui_flat[53]; +void mui_bridge_collect_secondary(void); + +void mui_bridge_publish_secondary(void) +{ + mui_bridge_collect_secondary(); + objects.advanced_settings_panel = mui_secondary_objects_flat[0]; + objects.alert_label = mui_secondary_objects_flat[1]; + objects.alert_panel = mui_secondary_objects_flat[2]; + objects.arrow_down_button = mui_secondary_objects_flat[3]; + objects.arrow_left_button = mui_secondary_objects_flat[4]; + objects.arrow_right_button = mui_secondary_objects_flat[5]; + objects.arrow_up_button = mui_secondary_objects_flat[6]; + objects.basic_settings_alert_button = mui_secondary_objects_flat[7]; + objects.basic_settings_alert_label = mui_secondary_objects_flat[8]; + objects.basic_settings_backup_restore_button = mui_secondary_objects_flat[9]; + objects.basic_settings_backup_restore_label = mui_secondary_objects_flat[10]; + objects.basic_settings_brightness_button = mui_secondary_objects_flat[11]; + objects.basic_settings_brightness_label = mui_secondary_objects_flat[12]; + objects.basic_settings_calibration_button = mui_secondary_objects_flat[13]; + objects.basic_settings_calibration_label = mui_secondary_objects_flat[14]; + objects.basic_settings_channel_button = mui_secondary_objects_flat[15]; + objects.basic_settings_channel_label = mui_secondary_objects_flat[16]; + objects.basic_settings_input_button = mui_secondary_objects_flat[17]; + objects.basic_settings_input_label = mui_secondary_objects_flat[18]; + objects.basic_settings_language_button = mui_secondary_objects_flat[19]; + objects.basic_settings_language_label = mui_secondary_objects_flat[20]; + objects.basic_settings_modem_preset_button = mui_secondary_objects_flat[21]; + objects.basic_settings_modem_preset_label = mui_secondary_objects_flat[22]; + objects.basic_settings_reboot_button = mui_secondary_objects_flat[23]; + objects.basic_settings_reboot_label = mui_secondary_objects_flat[24]; + objects.basic_settings_region_button = mui_secondary_objects_flat[25]; + objects.basic_settings_region_label = mui_secondary_objects_flat[26]; + objects.basic_settings_reset_button = mui_secondary_objects_flat[27]; + objects.basic_settings_reset_label = mui_secondary_objects_flat[28]; + objects.basic_settings_role_button = mui_secondary_objects_flat[29]; + objects.basic_settings_role_label = mui_secondary_objects_flat[30]; + objects.basic_settings_screen_lock_button = mui_secondary_objects_flat[31]; + objects.basic_settings_screen_lock_label = mui_secondary_objects_flat[32]; + objects.basic_settings_theme_button = mui_secondary_objects_flat[33]; + objects.basic_settings_theme_label = mui_secondary_objects_flat[34]; + objects.basic_settings_timeout_button = mui_secondary_objects_flat[35]; + objects.basic_settings_timeout_label = mui_secondary_objects_flat[36]; + objects.basic_settings_timezone_button = mui_secondary_objects_flat[37]; + objects.basic_settings_timezone_label = mui_secondary_objects_flat[38]; + objects.basic_settings_user_button = mui_secondary_objects_flat[39]; + objects.basic_settings_user_label = mui_secondary_objects_flat[40]; + objects.basic_settings_wifi_button = mui_secondary_objects_flat[41]; + objects.basic_settings_wifi_label = mui_secondary_objects_flat[42]; + objects.battery_image = mui_secondary_objects_flat[43]; + objects.battery_label = mui_secondary_objects_flat[44]; + objects.battery_panel = mui_secondary_objects_flat[45]; + objects.battery_percentage_label = mui_secondary_objects_flat[46]; + objects.blank_screen = mui_secondary_objects_flat[47]; + objects.blank_screen_button = mui_secondary_objects_flat[48]; + objects.bluetooth_button = mui_secondary_objects_flat[49]; + objects.boot_logo = mui_secondary_objects_flat[50]; + objects.boot_logo_arc = mui_secondary_objects_flat[51]; + objects.boot_logo_button = mui_secondary_objects_flat[52]; + objects.boot_screen = mui_secondary_objects_flat[53]; + objects.brightness_slider = mui_secondary_objects_flat[54]; + objects.button_panel = mui_secondary_objects_flat[55]; + objects.calibration_screen = mui_secondary_objects_flat[56]; + objects.cancel_reboot_button = mui_secondary_objects_flat[57]; + objects.channel_button0 = mui_secondary_objects_flat[58]; + objects.channel_button1 = mui_secondary_objects_flat[59]; + objects.channel_button2 = mui_secondary_objects_flat[60]; + objects.channel_button3 = mui_secondary_objects_flat[61]; + objects.channel_button4 = mui_secondary_objects_flat[62]; + objects.channel_button5 = mui_secondary_objects_flat[63]; + objects.channel_button6 = mui_secondary_objects_flat[64]; + objects.channel_button7 = mui_secondary_objects_flat[65]; + objects.channel_label0 = mui_secondary_objects_flat[66]; + objects.channel_label1 = mui_secondary_objects_flat[67]; + objects.channel_label2 = mui_secondary_objects_flat[68]; + objects.channel_label3 = mui_secondary_objects_flat[69]; + objects.channel_label4 = mui_secondary_objects_flat[70]; + objects.channel_label5 = mui_secondary_objects_flat[71]; + objects.channel_label6 = mui_secondary_objects_flat[72]; + objects.channel_label7 = mui_secondary_objects_flat[73]; + objects.chat_del_button = mui_secondary_objects_flat[74]; + objects.chats_button = mui_secondary_objects_flat[75]; + objects.chats_button_label = mui_secondary_objects_flat[76]; + objects.chats_panel = mui_secondary_objects_flat[77]; + objects.controller_panel = mui_secondary_objects_flat[78]; + objects.controller_tab_view = mui_secondary_objects_flat[79]; + objects.del_label = mui_secondary_objects_flat[80]; + objects.details_panel = mui_secondary_objects_flat[81]; + objects.detected_node_button = mui_secondary_objects_flat[82]; + objects.detected_node_image = mui_secondary_objects_flat[83]; + objects.detected_node_label = mui_secondary_objects_flat[84]; + objects.detector_contact_button = mui_secondary_objects_flat[85]; + objects.detector_contact_image = mui_secondary_objects_flat[86]; + objects.detector_contact_label = mui_secondary_objects_flat[87]; + objects.detector_heard_label = mui_secondary_objects_flat[88]; + objects.detector_radar_panel = mui_secondary_objects_flat[89]; + objects.detector_start_button = mui_secondary_objects_flat[90]; + objects.detector_start_button_panel = mui_secondary_objects_flat[91]; + objects.detector_start_label = mui_secondary_objects_flat[92]; + objects.firmware_label = mui_secondary_objects_flat[93]; + objects.frequency_slot_label = mui_secondary_objects_flat[94]; + objects.frequency_slot_slider = mui_secondary_objects_flat[95]; + objects.google_logo_image = mui_secondary_objects_flat[96]; + objects.gps_lock_button = mui_secondary_objects_flat[97]; + objects.gps_position_image = mui_secondary_objects_flat[98]; + objects.groups_button = mui_secondary_objects_flat[99]; + objects.groups_panel = mui_secondary_objects_flat[100]; + objects.home_bell_button = mui_secondary_objects_flat[101]; + objects.home_bell_label = mui_secondary_objects_flat[102]; + objects.home_bluetooth_button = mui_secondary_objects_flat[103]; + objects.home_bluetooth_label = mui_secondary_objects_flat[104]; + objects.home_button = mui_secondary_objects_flat[105]; + objects.home_cancel_qr_button = mui_secondary_objects_flat[106]; + objects.home_container = mui_secondary_objects_flat[107]; + objects.home_ethernet_button = mui_secondary_objects_flat[108]; + objects.home_ethernet_label = mui_secondary_objects_flat[109]; + objects.home_location_button = mui_secondary_objects_flat[110]; + objects.home_location_image = mui_secondary_objects_flat[111]; + objects.home_location_label = mui_secondary_objects_flat[112]; + objects.home_lora_button = mui_secondary_objects_flat[113]; + objects.home_lora_label = mui_secondary_objects_flat[114]; + objects.home_mail_button = mui_secondary_objects_flat[115]; + objects.home_mail_label = mui_secondary_objects_flat[116]; + objects.home_memory_button = mui_secondary_objects_flat[117]; + objects.home_memory_label = mui_secondary_objects_flat[118]; + objects.home_mqtt_button = mui_secondary_objects_flat[119]; + objects.home_mqtt_label = mui_secondary_objects_flat[120]; + objects.home_nodes_button = mui_secondary_objects_flat[121]; + objects.home_nodes_label = mui_secondary_objects_flat[122]; + objects.home_panel = mui_secondary_objects_flat[123]; + objects.home_qr_button = mui_secondary_objects_flat[124]; + objects.home_qr_label = mui_secondary_objects_flat[125]; + objects.home_sd_card_button = mui_secondary_objects_flat[126]; + objects.home_sd_card_label = mui_secondary_objects_flat[127]; + objects.home_show_qr_panel = mui_secondary_objects_flat[128]; + objects.home_signal_button = mui_secondary_objects_flat[129]; + objects.home_signal_label = mui_secondary_objects_flat[130]; + objects.home_signal_pct_label = mui_secondary_objects_flat[131]; + objects.home_time_button = mui_secondary_objects_flat[132]; + objects.home_time_label = mui_secondary_objects_flat[133]; + objects.home_wlan_button = mui_secondary_objects_flat[134]; + objects.home_wlan_label = mui_secondary_objects_flat[135]; + objects.hop_routes_panel = mui_secondary_objects_flat[136]; + objects.initial_setup_panel = mui_secondary_objects_flat[137]; + objects.keyboard = mui_secondary_objects_flat[138]; + objects.keyboard_button_0 = mui_secondary_objects_flat[139]; + objects.keyboard_button_1 = mui_secondary_objects_flat[140]; + objects.keyboard_button_10 = mui_secondary_objects_flat[141]; + objects.keyboard_button_11 = mui_secondary_objects_flat[142]; + objects.keyboard_button_2 = mui_secondary_objects_flat[143]; + objects.keyboard_button_3 = mui_secondary_objects_flat[144]; + objects.keyboard_button_4 = mui_secondary_objects_flat[145]; + objects.keyboard_button_5 = mui_secondary_objects_flat[146]; + objects.keyboard_button_6 = mui_secondary_objects_flat[147]; + objects.keyboard_button_7 = mui_secondary_objects_flat[148]; + objects.keyboard_button_8 = mui_secondary_objects_flat[149]; + objects.keyboard_button_9 = mui_secondary_objects_flat[150]; + objects.last_heard_label = mui_secondary_objects_flat[151]; + objects.lock_screen = mui_secondary_objects_flat[152]; + objects.lock_screen_digits_label = mui_secondary_objects_flat[153]; + objects.main_screen = mui_secondary_objects_flat[154]; + objects.map_brightness_slider = mui_secondary_objects_flat[155]; + objects.map_button = mui_secondary_objects_flat[156]; + objects.map_contrast_slider = mui_secondary_objects_flat[157]; + objects.map_location_label = mui_secondary_objects_flat[158]; + objects.map_osd_panel = mui_secondary_objects_flat[159]; + objects.map_panel = mui_secondary_objects_flat[160]; + objects.map_style_dropdown = mui_secondary_objects_flat[161]; + objects.map_url_dropdown = mui_secondary_objects_flat[162]; + objects.mesh_detector_panel = mui_secondary_objects_flat[163]; + objects.meshtastic_image = mui_secondary_objects_flat[164]; + objects.meshtastic_label = mui_secondary_objects_flat[165]; + objects.meshtastic_url = mui_secondary_objects_flat[166]; + objects.message_input_area = mui_secondary_objects_flat[167]; + objects.message_restore_bar = mui_secondary_objects_flat[168]; + objects.messages_button = mui_secondary_objects_flat[169]; + objects.messages_container = mui_secondary_objects_flat[170]; + objects.messages_panel = mui_secondary_objects_flat[171]; + objects.msg_popup_button = mui_secondary_objects_flat[172]; + objects.msg_popup_label = mui_secondary_objects_flat[173]; + objects.msg_popup_panel = mui_secondary_objects_flat[174]; + objects.msg_restore_button = mui_secondary_objects_flat[175]; + objects.msg_restore_label = mui_secondary_objects_flat[176]; + objects.msg_restore_panel = mui_secondary_objects_flat[177]; + objects.nav_button = mui_secondary_objects_flat[178]; + objects.navigation_panel = mui_secondary_objects_flat[179]; + objects.node_button = mui_secondary_objects_flat[180]; + objects.node_details_battery_label = mui_secondary_objects_flat[181]; + objects.node_details_image = mui_secondary_objects_flat[182]; + objects.node_details_last_heard_label = mui_secondary_objects_flat[183]; + objects.node_details_name_label = mui_secondary_objects_flat[184]; + objects.node_details_name_short_label = mui_secondary_objects_flat[185]; + objects.node_details_panel = mui_secondary_objects_flat[186]; + objects.node_details_signal_label = mui_secondary_objects_flat[187]; + objects.node_image = mui_secondary_objects_flat[188]; + objects.node_options_panel = mui_secondary_objects_flat[189]; + objects.node_options_tab_view = mui_secondary_objects_flat[190]; + objects.node_panel = mui_secondary_objects_flat[191]; + objects.nodes_button = mui_secondary_objects_flat[192]; + objects.nodes_filter_channel_dropdown = mui_secondary_objects_flat[193]; + objects.nodes_filter_channel_label = mui_secondary_objects_flat[194]; + objects.nodes_filter_hops_away_label = mui_secondary_objects_flat[195]; + objects.nodes_filter_hops_dropdown = mui_secondary_objects_flat[196]; + objects.nodes_filter_mqtt_label = mui_secondary_objects_flat[197]; + objects.nodes_filter_mqtt_switch = mui_secondary_objects_flat[198]; + objects.nodes_filter_name_area = mui_secondary_objects_flat[199]; + objects.nodes_filter_name_label = mui_secondary_objects_flat[200]; + objects.nodes_filter_offline_label = mui_secondary_objects_flat[201]; + objects.nodes_filter_offline_switch = mui_secondary_objects_flat[202]; + objects.nodes_filter_position_label = mui_secondary_objects_flat[203]; + objects.nodes_filter_position_switch = mui_secondary_objects_flat[204]; + objects.nodes_filter_public_key_label = mui_secondary_objects_flat[205]; + objects.nodes_filter_public_key_switch = mui_secondary_objects_flat[206]; + objects.nodes_filter_unknown_label = mui_secondary_objects_flat[207]; + objects.nodes_filter_unknown_switch = mui_secondary_objects_flat[208]; + objects.nodes_hl_active_chat_label = mui_secondary_objects_flat[209]; + objects.nodes_hl_active_chat_switch = mui_secondary_objects_flat[210]; + objects.nodes_hl_name_area = mui_secondary_objects_flat[211]; + objects.nodes_hl_name_label = mui_secondary_objects_flat[212]; + objects.nodes_hl_position_label = mui_secondary_objects_flat[213]; + objects.nodes_hl_position_switch = mui_secondary_objects_flat[214]; + objects.nodes_hl_telemetry_label = mui_secondary_objects_flat[215]; + objects.nodes_hl_telemetry_switch = mui_secondary_objects_flat[216]; + objects.nodes_hliaq_label = mui_secondary_objects_flat[217]; + objects.nodes_hliaq_switch = mui_secondary_objects_flat[218]; + objects.nodes_panel = mui_secondary_objects_flat[219]; + objects.obj0 = mui_secondary_objects_flat[220]; + objects.obj1 = mui_secondary_objects_flat[221]; + objects.obj10 = mui_secondary_objects_flat[222]; + objects.obj10__cancel_button_w = mui_secondary_objects_flat[223]; + objects.obj10__ok_button_w = mui_secondary_objects_flat[224]; + objects.obj10__ok_cancel_panel_w = mui_secondary_objects_flat[225]; + objects.obj11 = mui_secondary_objects_flat[226]; + objects.obj11__cancel_button_w = mui_secondary_objects_flat[227]; + objects.obj11__ok_button_w = mui_secondary_objects_flat[228]; + objects.obj11__ok_cancel_panel_w = mui_secondary_objects_flat[229]; + objects.obj12 = mui_secondary_objects_flat[230]; + objects.obj12__cancel_button_w = mui_secondary_objects_flat[231]; + objects.obj12__ok_button_w = mui_secondary_objects_flat[232]; + objects.obj12__ok_cancel_panel_w = mui_secondary_objects_flat[233]; + objects.obj13 = mui_secondary_objects_flat[234]; + objects.obj13__cancel_button_w = mui_secondary_objects_flat[235]; + objects.obj13__ok_button_w = mui_secondary_objects_flat[236]; + objects.obj13__ok_cancel_panel_w = mui_secondary_objects_flat[237]; + objects.obj14 = mui_secondary_objects_flat[238]; + objects.obj14__cancel_button_w = mui_secondary_objects_flat[239]; + objects.obj14__ok_button_w = mui_secondary_objects_flat[240]; + objects.obj14__ok_cancel_panel_w = mui_secondary_objects_flat[241]; + objects.obj15 = mui_secondary_objects_flat[242]; + objects.obj15__cancel_button_w = mui_secondary_objects_flat[243]; + objects.obj15__ok_button_w = mui_secondary_objects_flat[244]; + objects.obj15__ok_cancel_panel_w = mui_secondary_objects_flat[245]; + objects.obj16 = mui_secondary_objects_flat[246]; + objects.obj16__cancel_button_w = mui_secondary_objects_flat[247]; + objects.obj16__ok_button_w = mui_secondary_objects_flat[248]; + objects.obj16__ok_cancel_panel_w = mui_secondary_objects_flat[249]; + objects.obj17 = mui_secondary_objects_flat[250]; + objects.obj17__cancel_button_w = mui_secondary_objects_flat[251]; + objects.obj17__ok_button_w = mui_secondary_objects_flat[252]; + objects.obj17__ok_cancel_panel_w = mui_secondary_objects_flat[253]; + objects.obj18 = mui_secondary_objects_flat[254]; + objects.obj18__cancel_button_w = mui_secondary_objects_flat[255]; + objects.obj18__ok_button_w = mui_secondary_objects_flat[256]; + objects.obj18__ok_cancel_panel_w = mui_secondary_objects_flat[257]; + objects.obj19 = mui_secondary_objects_flat[258]; + objects.obj2 = mui_secondary_objects_flat[259]; + objects.obj20 = mui_secondary_objects_flat[260]; + objects.obj21 = mui_secondary_objects_flat[261]; + objects.obj21__cancel_button_w = mui_secondary_objects_flat[262]; + objects.obj21__ok_button_w = mui_secondary_objects_flat[263]; + objects.obj21__ok_cancel_panel_w = mui_secondary_objects_flat[264]; + objects.obj22 = mui_secondary_objects_flat[265]; + objects.obj23 = mui_secondary_objects_flat[266]; + objects.obj24 = mui_secondary_objects_flat[267]; + objects.obj25 = mui_secondary_objects_flat[268]; + objects.obj26 = mui_secondary_objects_flat[269]; + objects.obj27 = mui_secondary_objects_flat[270]; + objects.obj27__cancel_button_w = mui_secondary_objects_flat[271]; + objects.obj27__ok_button_w = mui_secondary_objects_flat[272]; + objects.obj27__ok_cancel_panel_w = mui_secondary_objects_flat[273]; + objects.obj2__cancel_button_w = mui_secondary_objects_flat[274]; + objects.obj2__ok_button_w = mui_secondary_objects_flat[275]; + objects.obj2__ok_cancel_panel_w = mui_secondary_objects_flat[276]; + objects.obj3 = mui_secondary_objects_flat[277]; + objects.obj3__cancel_button_w = mui_secondary_objects_flat[278]; + objects.obj3__ok_button_w = mui_secondary_objects_flat[279]; + objects.obj3__ok_cancel_panel_w = mui_secondary_objects_flat[280]; + objects.obj4 = mui_secondary_objects_flat[281]; + objects.obj4__cancel_button_w = mui_secondary_objects_flat[282]; + objects.obj4__ok_button_w = mui_secondary_objects_flat[283]; + objects.obj4__ok_cancel_panel_w = mui_secondary_objects_flat[284]; + objects.obj5 = mui_secondary_objects_flat[285]; + objects.obj5__cancel_button_w = mui_secondary_objects_flat[286]; + objects.obj5__ok_button_w = mui_secondary_objects_flat[287]; + objects.obj5__ok_cancel_panel_w = mui_secondary_objects_flat[288]; + objects.obj6 = mui_secondary_objects_flat[289]; + objects.obj6__cancel_button_w = mui_secondary_objects_flat[290]; + objects.obj6__ok_button_w = mui_secondary_objects_flat[291]; + objects.obj6__ok_cancel_panel_w = mui_secondary_objects_flat[292]; + objects.obj7 = mui_secondary_objects_flat[293]; + objects.obj7__cancel_button_w = mui_secondary_objects_flat[294]; + objects.obj7__ok_button_w = mui_secondary_objects_flat[295]; + objects.obj7__ok_cancel_panel_w = mui_secondary_objects_flat[296]; + objects.obj8 = mui_secondary_objects_flat[297]; + objects.obj8__cancel_button_w = mui_secondary_objects_flat[298]; + objects.obj8__ok_button_w = mui_secondary_objects_flat[299]; + objects.obj8__ok_cancel_panel_w = mui_secondary_objects_flat[300]; + objects.obj9 = mui_secondary_objects_flat[301]; + objects.obj9__cancel_button_w = mui_secondary_objects_flat[302]; + objects.obj9__ok_button_w = mui_secondary_objects_flat[303]; + objects.obj9__ok_cancel_panel_w = mui_secondary_objects_flat[304]; + objects.position2_label = mui_secondary_objects_flat[305]; + objects.position_label = mui_secondary_objects_flat[306]; + objects.progmode_button = mui_secondary_objects_flat[307]; + objects.radar_beam = mui_secondary_objects_flat[308]; + objects.raw_map_panel = mui_secondary_objects_flat[309]; + objects.reboot_button = mui_secondary_objects_flat[310]; + objects.reboot_panel = mui_secondary_objects_flat[311]; + objects.route_back_panel = mui_secondary_objects_flat[312]; + objects.route_towards_panel = mui_secondary_objects_flat[313]; + objects.rssi_slider = mui_secondary_objects_flat[314]; + objects.screen_lock_button_matrix = mui_secondary_objects_flat[315]; + objects.screen_timeout_slider = mui_secondary_objects_flat[316]; + objects.settings_alert_buzzer_panel = mui_secondary_objects_flat[317]; + objects.settings_alert_buzzer_switch = mui_secondary_objects_flat[318]; + objects.settings_backup_checkbox = mui_secondary_objects_flat[319]; + objects.settings_backup_restore_dropdown = mui_secondary_objects_flat[320]; + objects.settings_backup_restore_panel = mui_secondary_objects_flat[321]; + objects.settings_brightness_label = mui_secondary_objects_flat[322]; + objects.settings_brightness_panel = mui_secondary_objects_flat[323]; + objects.settings_button = mui_secondary_objects_flat[324]; + objects.settings_channel0_button = mui_secondary_objects_flat[325]; + objects.settings_channel0_label = mui_secondary_objects_flat[326]; + objects.settings_channel1_button = mui_secondary_objects_flat[327]; + objects.settings_channel1_label = mui_secondary_objects_flat[328]; + objects.settings_channel2_button = mui_secondary_objects_flat[329]; + objects.settings_channel2_label = mui_secondary_objects_flat[330]; + objects.settings_channel3_button = mui_secondary_objects_flat[331]; + objects.settings_channel3_label = mui_secondary_objects_flat[332]; + objects.settings_channel4_button = mui_secondary_objects_flat[333]; + objects.settings_channel4_label = mui_secondary_objects_flat[334]; + objects.settings_channel5_button = mui_secondary_objects_flat[335]; + objects.settings_channel5_label = mui_secondary_objects_flat[336]; + objects.settings_channel6_button = mui_secondary_objects_flat[337]; + objects.settings_channel6_label = mui_secondary_objects_flat[338]; + objects.settings_channel7_button = mui_secondary_objects_flat[339]; + objects.settings_channel7_label = mui_secondary_objects_flat[340]; + objects.settings_channel_panel = mui_secondary_objects_flat[341]; + objects.settings_device_role_dropdown = mui_secondary_objects_flat[342]; + objects.settings_device_role_panel = mui_secondary_objects_flat[343]; + objects.settings_input_control_panel = mui_secondary_objects_flat[344]; + objects.settings_keyboard_input_dropdown = mui_secondary_objects_flat[345]; + objects.settings_language_dropdown = mui_secondary_objects_flat[346]; + objects.settings_language_panel = mui_secondary_objects_flat[347]; + objects.settings_modem_preset_dropdown = mui_secondary_objects_flat[348]; + objects.settings_modem_preset_panel = mui_secondary_objects_flat[349]; + objects.settings_modify_channel_key_generate_button = mui_secondary_objects_flat[350]; + objects.settings_modify_channel_name_textarea = mui_secondary_objects_flat[351]; + objects.settings_modify_channel_panel = mui_secondary_objects_flat[352]; + objects.settings_modify_channel_psk_textarea = mui_secondary_objects_flat[353]; + objects.settings_modify_channel_qr_button = mui_secondary_objects_flat[354]; + objects.settings_modify_channel_qr_panel = mui_secondary_objects_flat[355]; + objects.settings_modify_trash_button = mui_secondary_objects_flat[356]; + objects.settings_mouse_input_dropdown = mui_secondary_objects_flat[357]; + objects.settings_reboot_panel = mui_secondary_objects_flat[358]; + objects.settings_region_dropdown = mui_secondary_objects_flat[359]; + objects.settings_region_panel = mui_secondary_objects_flat[360]; + objects.settings_reset_dropdown = mui_secondary_objects_flat[361]; + objects.settings_reset_panel = mui_secondary_objects_flat[362]; + objects.settings_restore_checkbox = mui_secondary_objects_flat[363]; + objects.settings_ringtone_dropdown = mui_secondary_objects_flat[364]; + objects.settings_screen_lock_panel = mui_secondary_objects_flat[365]; + objects.settings_screen_lock_password_textarea = mui_secondary_objects_flat[366]; + objects.settings_screen_lock_switch = mui_secondary_objects_flat[367]; + objects.settings_screen_timeout_label = mui_secondary_objects_flat[368]; + objects.settings_screen_timeout_panel = mui_secondary_objects_flat[369]; + objects.settings_settings_lock_switch = mui_secondary_objects_flat[370]; + objects.settings_theme_dropdown = mui_secondary_objects_flat[371]; + objects.settings_theme_panel = mui_secondary_objects_flat[372]; + objects.settings_timezone = mui_secondary_objects_flat[373]; + objects.settings_tzcity = mui_secondary_objects_flat[374]; + objects.settings_tzzone = mui_secondary_objects_flat[375]; + objects.settings_user_long_textarea = mui_secondary_objects_flat[376]; + objects.settings_user_short_textarea = mui_secondary_objects_flat[377]; + objects.settings_username_panel = mui_secondary_objects_flat[378]; + objects.settings_wifi_panel = mui_secondary_objects_flat[379]; + objects.settings_wifi_password_textarea = mui_secondary_objects_flat[380]; + objects.settings_wifi_ssid_textarea = mui_secondary_objects_flat[381]; + objects.setup_panel = mui_secondary_objects_flat[382]; + objects.setup_region_dropdown = mui_secondary_objects_flat[383]; + objects.setup_user_long_textarea = mui_secondary_objects_flat[384]; + objects.setup_user_short_textarea = mui_secondary_objects_flat[385]; + objects.shutdown_button = mui_secondary_objects_flat[386]; + objects.signal_label = mui_secondary_objects_flat[387]; + objects.signal_scanner_node_button = mui_secondary_objects_flat[388]; + objects.signal_scanner_node_button_label = mui_secondary_objects_flat[389]; + objects.signal_scanner_node_image = mui_secondary_objects_flat[390]; + objects.signal_scanner_panel = mui_secondary_objects_flat[391]; + objects.signal_scanner_rssi_label = mui_secondary_objects_flat[392]; + objects.signal_scanner_rssi_scale_label = mui_secondary_objects_flat[393]; + objects.signal_scanner_snr_label = mui_secondary_objects_flat[394]; + objects.signal_scanner_snr_scale_label = mui_secondary_objects_flat[395]; + objects.signal_scanner_start_button = mui_secondary_objects_flat[396]; + objects.signal_scanner_start_label = mui_secondary_objects_flat[397]; + objects.snr_slider = mui_secondary_objects_flat[398]; + objects.start_button_panel = mui_secondary_objects_flat[399]; + objects.statistics_table = mui_secondary_objects_flat[400]; + objects.tab_page_basic_settings = mui_secondary_objects_flat[401]; + objects.tab_page_filter = mui_secondary_objects_flat[402]; + objects.tab_page_highlight = mui_secondary_objects_flat[403]; + objects.tab_page_tools = mui_secondary_objects_flat[404]; + objects.telemetry1_label = mui_secondary_objects_flat[405]; + objects.telemetry2_label = mui_secondary_objects_flat[406]; + objects.tools_mesh_detector_button = mui_secondary_objects_flat[407]; + objects.tools_mesh_detector_label = mui_secondary_objects_flat[408]; + objects.tools_neighbors_button = mui_secondary_objects_flat[409]; + objects.tools_neighbors_label = mui_secondary_objects_flat[410]; + objects.tools_packet_log_button = mui_secondary_objects_flat[411]; + objects.tools_packet_log_label = mui_secondary_objects_flat[412]; + objects.tools_packet_log_panel = mui_secondary_objects_flat[413]; + objects.tools_signal_scanner_button = mui_secondary_objects_flat[414]; + objects.tools_signal_scanner_label = mui_secondary_objects_flat[415]; + objects.tools_statistics_button = mui_secondary_objects_flat[416]; + objects.tools_statistics_label = mui_secondary_objects_flat[417]; + objects.tools_statistics_panel = mui_secondary_objects_flat[418]; + objects.tools_trace_route_button = mui_secondary_objects_flat[419]; + objects.tools_trace_route_label = mui_secondary_objects_flat[420]; + objects.top_advanced_settings_image = mui_secondary_objects_flat[421]; + objects.top_advanced_settings_label = mui_secondary_objects_flat[422]; + objects.top_advanced_settings_panel = mui_secondary_objects_flat[423]; + objects.top_basic_settings_image = mui_secondary_objects_flat[424]; + objects.top_basic_settings_label = mui_secondary_objects_flat[425]; + objects.top_chats_image = mui_secondary_objects_flat[426]; + objects.top_chats_label = mui_secondary_objects_flat[427]; + objects.top_chats_panel = mui_secondary_objects_flat[428]; + objects.top_group_chat_image = mui_secondary_objects_flat[429]; + objects.top_group_chat_label = mui_secondary_objects_flat[430]; + objects.top_group_chat_panel = mui_secondary_objects_flat[431]; + objects.top_group_image = mui_secondary_objects_flat[432]; + objects.top_groups_panel = mui_secondary_objects_flat[433]; + objects.top_lora_tx_image = mui_secondary_objects_flat[434]; + objects.top_lora_tx_label = mui_secondary_objects_flat[435]; + objects.top_lora_tx_panel = mui_secondary_objects_flat[436]; + objects.top_map_image = mui_secondary_objects_flat[437]; + objects.top_map_label = mui_secondary_objects_flat[438]; + objects.top_map_panel = mui_secondary_objects_flat[439]; + objects.top_mesh_detector_image = mui_secondary_objects_flat[440]; + objects.top_mesh_detector_label = mui_secondary_objects_flat[441]; + objects.top_mesh_detector_panel = mui_secondary_objects_flat[442]; + objects.top_messages_node_image = mui_secondary_objects_flat[443]; + objects.top_messages_node_label = mui_secondary_objects_flat[444]; + objects.top_messages_panel = mui_secondary_objects_flat[445]; + objects.top_neighbors_image = mui_secondary_objects_flat[446]; + objects.top_neighbors_label = mui_secondary_objects_flat[447]; + objects.top_neighbors_panel = mui_secondary_objects_flat[448]; + objects.top_node_options_image = mui_secondary_objects_flat[449]; + objects.top_node_options_label = mui_secondary_objects_flat[450]; + objects.top_node_options_panel = mui_secondary_objects_flat[451]; + objects.top_node_search_image = mui_secondary_objects_flat[452]; + objects.top_node_search_label = mui_secondary_objects_flat[453]; + objects.top_node_search_panel = mui_secondary_objects_flat[454]; + objects.top_nodes_image = mui_secondary_objects_flat[455]; + objects.top_nodes_online_label = mui_secondary_objects_flat[456]; + objects.top_nodes_panel = mui_secondary_objects_flat[457]; + objects.top_packet_log_image = mui_secondary_objects_flat[458]; + objects.top_packet_log_label = mui_secondary_objects_flat[459]; + objects.top_packet_log_panel = mui_secondary_objects_flat[460]; + objects.top_panel = mui_secondary_objects_flat[461]; + objects.top_settings_panel = mui_secondary_objects_flat[462]; + objects.top_setup_image = mui_secondary_objects_flat[463]; + objects.top_setup_label = mui_secondary_objects_flat[464]; + objects.top_setup_panel = mui_secondary_objects_flat[465]; + objects.top_signal_scanner_image = mui_secondary_objects_flat[466]; + objects.top_signal_scanner_label = mui_secondary_objects_flat[467]; + objects.top_signal_scanner_panel = mui_secondary_objects_flat[468]; + objects.top_statistics_image = mui_secondary_objects_flat[469]; + objects.top_statistics_label = mui_secondary_objects_flat[470]; + objects.top_statistics_panel = mui_secondary_objects_flat[471]; + objects.top_trace_route_image = mui_secondary_objects_flat[472]; + objects.top_trace_route_label = mui_secondary_objects_flat[473]; + objects.top_trace_route_panel = mui_secondary_objects_flat[474]; + objects.top_user_group_label = mui_secondary_objects_flat[475]; + objects.trace_route_panel = mui_secondary_objects_flat[476]; + objects.trace_route_start_button = mui_secondary_objects_flat[477]; + objects.trace_route_start_label = mui_secondary_objects_flat[478]; + objects.trace_route_to_button = mui_secondary_objects_flat[479]; + objects.trace_route_to_button_label = mui_secondary_objects_flat[480]; + objects.trace_route_to_image = mui_secondary_objects_flat[481]; + objects.user_name_label = mui_secondary_objects_flat[482]; + objects.user_name_short_label = mui_secondary_objects_flat[483]; + objects.zoom_in_button = mui_secondary_objects_flat[484]; + objects.zoom_out_button = mui_secondary_objects_flat[485]; + objects.zoom_slider = mui_secondary_objects_flat[486]; + ui_AdvancedSettingsPanel = mui_secondary_ui_flat[0]; + ui_AmbientLightingLabel = mui_secondary_ui_flat[1]; + ui_AudioLabel = mui_secondary_ui_flat[2]; + ui_AudioLabel1 = mui_secondary_ui_flat[3]; + ui_BluetoothLabel = mui_secondary_ui_flat[4]; + ui_CannedMsgLabel = mui_secondary_ui_flat[5]; + ui_DetectionSensorLabel = mui_secondary_ui_flat[6]; + ui_DeviceLabel = mui_secondary_ui_flat[7]; + ui_DisplayLabel = mui_secondary_ui_flat[8]; + ui_ExtNotificationLabel = mui_secondary_ui_flat[9]; + ui_GeneralAudioButton = mui_secondary_ui_flat[10]; + ui_GeneralLanguageButton = mui_secondary_ui_flat[11]; + ui_GeneralMapsButton = mui_secondary_ui_flat[12]; + ui_GeneralScreenButton = mui_secondary_ui_flat[13]; + ui_GeneralTimezoneButton = mui_secondary_ui_flat[14]; + ui_LanguageLabel = mui_secondary_ui_flat[15]; + ui_LoRaLabel = mui_secondary_ui_flat[16]; + ui_MQTTLabel = mui_secondary_ui_flat[17]; + ui_MapsLabel = mui_secondary_ui_flat[18]; + ui_ModuleAmbientLightingButton = mui_secondary_ui_flat[19]; + ui_ModuleAudioButton = mui_secondary_ui_flat[20]; + ui_ModuleCannedMsgButton = mui_secondary_ui_flat[21]; + ui_ModuleDetectionSensorButton = mui_secondary_ui_flat[22]; + ui_ModuleExtNotificationButton = mui_secondary_ui_flat[23]; + ui_ModuleMQTTButton = mui_secondary_ui_flat[24]; + ui_ModuleNeighborInfoButton = mui_secondary_ui_flat[25]; + ui_ModuleRangeTestButton = mui_secondary_ui_flat[26]; + ui_ModuleRemoteHardwareButton = mui_secondary_ui_flat[27]; + ui_ModuleSaFButton = mui_secondary_ui_flat[28]; + ui_ModuleSerialButton = mui_secondary_ui_flat[29]; + ui_ModuleTelemetryButton = mui_secondary_ui_flat[30]; + ui_NeighborInfoLabel = mui_secondary_ui_flat[31]; + ui_NetworkLabel = mui_secondary_ui_flat[32]; + ui_PositionLabel = mui_secondary_ui_flat[33]; + ui_PowerLabel = mui_secondary_ui_flat[34]; + ui_RadioBluetoothButton = mui_secondary_ui_flat[35]; + ui_RadioDeviceButton = mui_secondary_ui_flat[36]; + ui_RadioDisplayButton = mui_secondary_ui_flat[37]; + ui_RadioLoRaButton = mui_secondary_ui_flat[38]; + ui_RadioNetworkButton = mui_secondary_ui_flat[39]; + ui_RadioPositionButton = mui_secondary_ui_flat[40]; + ui_RadioPowerButton = mui_secondary_ui_flat[41]; + ui_RangeTestLabel = mui_secondary_ui_flat[42]; + ui_RemoteHardwareLabel = mui_secondary_ui_flat[43]; + ui_ScreenLabel = mui_secondary_ui_flat[44]; + ui_SerialLabel = mui_secondary_ui_flat[45]; + ui_SettingsTabView = mui_secondary_ui_flat[46]; + ui_StoreAndForwardLabel = mui_secondary_ui_flat[47]; + ui_TabPageGeneral = mui_secondary_ui_flat[48]; + ui_TabPageModules = mui_secondary_ui_flat[49]; + ui_TabPageRadio = mui_secondary_ui_flat[50]; + ui_TelemetryLabel = mui_secondary_ui_flat[51]; + ui_TimezoneLabel = mui_secondary_ui_flat[52]; +} diff --git a/tools/generated/dual/bridge_secondary.c b/tools/generated/dual/bridge_secondary.c new file mode 100644 index 00000000..218ad18f --- /dev/null +++ b/tools/generated/dual/bridge_secondary.c @@ -0,0 +1,551 @@ +// GENERATED by tools/gen_dual_ui.py - do not edit. +// Secondary tree (renamed): flatten objects + ui_* pointers into +// canonical (alphabetical) order. +#include "screens.h" + +lv_obj_t *mui_secondary_objects_flat[487]; +lv_obj_t *mui_secondary_ui_flat[53]; + +void mui_bridge_collect_secondary(void) +{ + mui_secondary_objects_flat[0] = objects.advanced_settings_panel; + mui_secondary_objects_flat[1] = objects.alert_label; + mui_secondary_objects_flat[2] = objects.alert_panel; + mui_secondary_objects_flat[3] = objects.arrow_down_button; + mui_secondary_objects_flat[4] = objects.arrow_left_button; + mui_secondary_objects_flat[5] = objects.arrow_right_button; + mui_secondary_objects_flat[6] = objects.arrow_up_button; + mui_secondary_objects_flat[7] = objects.basic_settings_alert_button; + mui_secondary_objects_flat[8] = objects.basic_settings_alert_label; + mui_secondary_objects_flat[9] = objects.basic_settings_backup_restore_button; + mui_secondary_objects_flat[10] = objects.basic_settings_backup_restore_label; + mui_secondary_objects_flat[11] = objects.basic_settings_brightness_button; + mui_secondary_objects_flat[12] = objects.basic_settings_brightness_label; + mui_secondary_objects_flat[13] = objects.basic_settings_calibration_button; + mui_secondary_objects_flat[14] = objects.basic_settings_calibration_label; + mui_secondary_objects_flat[15] = objects.basic_settings_channel_button; + mui_secondary_objects_flat[16] = objects.basic_settings_channel_label; + mui_secondary_objects_flat[17] = objects.basic_settings_input_button; + mui_secondary_objects_flat[18] = objects.basic_settings_input_label; + mui_secondary_objects_flat[19] = objects.basic_settings_language_button; + mui_secondary_objects_flat[20] = objects.basic_settings_language_label; + mui_secondary_objects_flat[21] = objects.basic_settings_modem_preset_button; + mui_secondary_objects_flat[22] = objects.basic_settings_modem_preset_label; + mui_secondary_objects_flat[23] = objects.basic_settings_reboot_button; + mui_secondary_objects_flat[24] = objects.basic_settings_reboot_label; + mui_secondary_objects_flat[25] = objects.basic_settings_region_button; + mui_secondary_objects_flat[26] = objects.basic_settings_region_label; + mui_secondary_objects_flat[27] = objects.basic_settings_reset_button; + mui_secondary_objects_flat[28] = objects.basic_settings_reset_label; + mui_secondary_objects_flat[29] = objects.basic_settings_role_button; + mui_secondary_objects_flat[30] = objects.basic_settings_role_label; + mui_secondary_objects_flat[31] = objects.basic_settings_screen_lock_button; + mui_secondary_objects_flat[32] = objects.basic_settings_screen_lock_label; + mui_secondary_objects_flat[33] = objects.basic_settings_theme_button; + mui_secondary_objects_flat[34] = objects.basic_settings_theme_label; + mui_secondary_objects_flat[35] = objects.basic_settings_timeout_button; + mui_secondary_objects_flat[36] = objects.basic_settings_timeout_label; + mui_secondary_objects_flat[37] = objects.basic_settings_timezone_button; + mui_secondary_objects_flat[38] = objects.basic_settings_timezone_label; + mui_secondary_objects_flat[39] = objects.basic_settings_user_button; + mui_secondary_objects_flat[40] = objects.basic_settings_user_label; + mui_secondary_objects_flat[41] = objects.basic_settings_wifi_button; + mui_secondary_objects_flat[42] = objects.basic_settings_wifi_label; + mui_secondary_objects_flat[43] = objects.battery_image; + mui_secondary_objects_flat[44] = objects.battery_label; + mui_secondary_objects_flat[45] = objects.battery_panel; + mui_secondary_objects_flat[46] = objects.battery_percentage_label; + mui_secondary_objects_flat[47] = objects.blank_screen; + mui_secondary_objects_flat[48] = objects.blank_screen_button; + mui_secondary_objects_flat[49] = objects.bluetooth_button; + mui_secondary_objects_flat[50] = objects.boot_logo; + mui_secondary_objects_flat[51] = objects.boot_logo_arc; + mui_secondary_objects_flat[52] = objects.boot_logo_button; + mui_secondary_objects_flat[53] = objects.boot_screen; + mui_secondary_objects_flat[54] = objects.brightness_slider; + mui_secondary_objects_flat[55] = objects.button_panel; + mui_secondary_objects_flat[56] = objects.calibration_screen; + mui_secondary_objects_flat[57] = objects.cancel_reboot_button; + mui_secondary_objects_flat[58] = objects.channel_button0; + mui_secondary_objects_flat[59] = objects.channel_button1; + mui_secondary_objects_flat[60] = objects.channel_button2; + mui_secondary_objects_flat[61] = objects.channel_button3; + mui_secondary_objects_flat[62] = objects.channel_button4; + mui_secondary_objects_flat[63] = objects.channel_button5; + mui_secondary_objects_flat[64] = objects.channel_button6; + mui_secondary_objects_flat[65] = objects.channel_button7; + mui_secondary_objects_flat[66] = objects.channel_label0; + mui_secondary_objects_flat[67] = objects.channel_label1; + mui_secondary_objects_flat[68] = objects.channel_label2; + mui_secondary_objects_flat[69] = objects.channel_label3; + mui_secondary_objects_flat[70] = objects.channel_label4; + mui_secondary_objects_flat[71] = objects.channel_label5; + mui_secondary_objects_flat[72] = objects.channel_label6; + mui_secondary_objects_flat[73] = objects.channel_label7; + mui_secondary_objects_flat[74] = objects.chat_del_button; + mui_secondary_objects_flat[75] = objects.chats_button; + mui_secondary_objects_flat[76] = objects.chats_button_label; + mui_secondary_objects_flat[77] = objects.chats_panel; + mui_secondary_objects_flat[78] = objects.controller_panel; + mui_secondary_objects_flat[79] = objects.controller_tab_view; + mui_secondary_objects_flat[80] = objects.del_label; + mui_secondary_objects_flat[81] = objects.details_panel; + mui_secondary_objects_flat[82] = objects.detected_node_button; + mui_secondary_objects_flat[83] = objects.detected_node_image; + mui_secondary_objects_flat[84] = objects.detected_node_label; + mui_secondary_objects_flat[85] = objects.detector_contact_button; + mui_secondary_objects_flat[86] = objects.detector_contact_image; + mui_secondary_objects_flat[87] = objects.detector_contact_label; + mui_secondary_objects_flat[88] = objects.detector_heard_label; + mui_secondary_objects_flat[89] = objects.detector_radar_panel; + mui_secondary_objects_flat[90] = objects.detector_start_button; + mui_secondary_objects_flat[91] = objects.detector_start_button_panel; + mui_secondary_objects_flat[92] = objects.detector_start_label; + mui_secondary_objects_flat[93] = objects.firmware_label; + mui_secondary_objects_flat[94] = objects.frequency_slot_label; + mui_secondary_objects_flat[95] = objects.frequency_slot_slider; + mui_secondary_objects_flat[96] = objects.google_logo_image; + mui_secondary_objects_flat[97] = objects.gps_lock_button; + mui_secondary_objects_flat[98] = objects.gps_position_image; + mui_secondary_objects_flat[99] = objects.groups_button; + mui_secondary_objects_flat[100] = objects.groups_panel; + mui_secondary_objects_flat[101] = objects.home_bell_button; + mui_secondary_objects_flat[102] = objects.home_bell_label; + mui_secondary_objects_flat[103] = objects.home_bluetooth_button; + mui_secondary_objects_flat[104] = objects.home_bluetooth_label; + mui_secondary_objects_flat[105] = objects.home_button; + mui_secondary_objects_flat[106] = objects.home_cancel_qr_button; + mui_secondary_objects_flat[107] = objects.home_container; + mui_secondary_objects_flat[108] = objects.home_ethernet_button; + mui_secondary_objects_flat[109] = objects.home_ethernet_label; + mui_secondary_objects_flat[110] = objects.home_location_button; + mui_secondary_objects_flat[111] = objects.home_location_image; + mui_secondary_objects_flat[112] = objects.home_location_label; + mui_secondary_objects_flat[113] = objects.home_lora_button; + mui_secondary_objects_flat[114] = objects.home_lora_label; + mui_secondary_objects_flat[115] = objects.home_mail_button; + mui_secondary_objects_flat[116] = objects.home_mail_label; + mui_secondary_objects_flat[117] = objects.home_memory_button; + mui_secondary_objects_flat[118] = objects.home_memory_label; + mui_secondary_objects_flat[119] = objects.home_mqtt_button; + mui_secondary_objects_flat[120] = objects.home_mqtt_label; + mui_secondary_objects_flat[121] = objects.home_nodes_button; + mui_secondary_objects_flat[122] = objects.home_nodes_label; + mui_secondary_objects_flat[123] = objects.home_panel; + mui_secondary_objects_flat[124] = objects.home_qr_button; + mui_secondary_objects_flat[125] = objects.home_qr_label; + mui_secondary_objects_flat[126] = objects.home_sd_card_button; + mui_secondary_objects_flat[127] = objects.home_sd_card_label; + mui_secondary_objects_flat[128] = objects.home_show_qr_panel; + mui_secondary_objects_flat[129] = objects.home_signal_button; + mui_secondary_objects_flat[130] = objects.home_signal_label; + mui_secondary_objects_flat[131] = objects.home_signal_pct_label; + mui_secondary_objects_flat[132] = objects.home_time_button; + mui_secondary_objects_flat[133] = objects.home_time_label; + mui_secondary_objects_flat[134] = objects.home_wlan_button; + mui_secondary_objects_flat[135] = objects.home_wlan_label; + mui_secondary_objects_flat[136] = objects.hop_routes_panel; + mui_secondary_objects_flat[137] = objects.initial_setup_panel; + mui_secondary_objects_flat[138] = objects.keyboard; + mui_secondary_objects_flat[139] = objects.keyboard_button_0; + mui_secondary_objects_flat[140] = objects.keyboard_button_1; + mui_secondary_objects_flat[141] = objects.keyboard_button_10; + mui_secondary_objects_flat[142] = objects.keyboard_button_11; + mui_secondary_objects_flat[143] = objects.keyboard_button_2; + mui_secondary_objects_flat[144] = objects.keyboard_button_3; + mui_secondary_objects_flat[145] = objects.keyboard_button_4; + mui_secondary_objects_flat[146] = objects.keyboard_button_5; + mui_secondary_objects_flat[147] = objects.keyboard_button_6; + mui_secondary_objects_flat[148] = objects.keyboard_button_7; + mui_secondary_objects_flat[149] = objects.keyboard_button_8; + mui_secondary_objects_flat[150] = objects.keyboard_button_9; + mui_secondary_objects_flat[151] = objects.last_heard_label; + mui_secondary_objects_flat[152] = objects.lock_screen; + mui_secondary_objects_flat[153] = objects.lock_screen_digits_label; + mui_secondary_objects_flat[154] = objects.main_screen; + mui_secondary_objects_flat[155] = objects.map_brightness_slider; + mui_secondary_objects_flat[156] = objects.map_button; + mui_secondary_objects_flat[157] = objects.map_contrast_slider; + mui_secondary_objects_flat[158] = objects.map_location_label; + mui_secondary_objects_flat[159] = objects.map_osd_panel; + mui_secondary_objects_flat[160] = objects.map_panel; + mui_secondary_objects_flat[161] = objects.map_style_dropdown; + mui_secondary_objects_flat[162] = objects.map_url_dropdown; + mui_secondary_objects_flat[163] = objects.mesh_detector_panel; + mui_secondary_objects_flat[164] = objects.meshtastic_image; + mui_secondary_objects_flat[165] = objects.meshtastic_label; + mui_secondary_objects_flat[166] = objects.meshtastic_url; + mui_secondary_objects_flat[167] = objects.message_input_area; + mui_secondary_objects_flat[168] = objects.message_restore_bar; + mui_secondary_objects_flat[169] = objects.messages_button; + mui_secondary_objects_flat[170] = objects.messages_container; + mui_secondary_objects_flat[171] = objects.messages_panel; + mui_secondary_objects_flat[172] = objects.msg_popup_button; + mui_secondary_objects_flat[173] = objects.msg_popup_label; + mui_secondary_objects_flat[174] = objects.msg_popup_panel; + mui_secondary_objects_flat[175] = objects.msg_restore_button; + mui_secondary_objects_flat[176] = objects.msg_restore_label; + mui_secondary_objects_flat[177] = objects.msg_restore_panel; + mui_secondary_objects_flat[178] = objects.nav_button; + mui_secondary_objects_flat[179] = objects.navigation_panel; + mui_secondary_objects_flat[180] = objects.node_button; + mui_secondary_objects_flat[181] = objects.node_details_battery_label; + mui_secondary_objects_flat[182] = objects.node_details_image; + mui_secondary_objects_flat[183] = objects.node_details_last_heard_label; + mui_secondary_objects_flat[184] = objects.node_details_name_label; + mui_secondary_objects_flat[185] = objects.node_details_name_short_label; + mui_secondary_objects_flat[186] = objects.node_details_panel; + mui_secondary_objects_flat[187] = objects.node_details_signal_label; + mui_secondary_objects_flat[188] = objects.node_image; + mui_secondary_objects_flat[189] = objects.node_options_panel; + mui_secondary_objects_flat[190] = objects.node_options_tab_view; + mui_secondary_objects_flat[191] = objects.node_panel; + mui_secondary_objects_flat[192] = objects.nodes_button; + mui_secondary_objects_flat[193] = objects.nodes_filter_channel_dropdown; + mui_secondary_objects_flat[194] = objects.nodes_filter_channel_label; + mui_secondary_objects_flat[195] = objects.nodes_filter_hops_away_label; + mui_secondary_objects_flat[196] = objects.nodes_filter_hops_dropdown; + mui_secondary_objects_flat[197] = objects.nodes_filter_mqtt_label; + mui_secondary_objects_flat[198] = objects.nodes_filter_mqtt_switch; + mui_secondary_objects_flat[199] = objects.nodes_filter_name_area; + mui_secondary_objects_flat[200] = objects.nodes_filter_name_label; + mui_secondary_objects_flat[201] = objects.nodes_filter_offline_label; + mui_secondary_objects_flat[202] = objects.nodes_filter_offline_switch; + mui_secondary_objects_flat[203] = objects.nodes_filter_position_label; + mui_secondary_objects_flat[204] = objects.nodes_filter_position_switch; + mui_secondary_objects_flat[205] = objects.nodes_filter_public_key_label; + mui_secondary_objects_flat[206] = objects.nodes_filter_public_key_switch; + mui_secondary_objects_flat[207] = objects.nodes_filter_unknown_label; + mui_secondary_objects_flat[208] = objects.nodes_filter_unknown_switch; + mui_secondary_objects_flat[209] = objects.nodes_hl_active_chat_label; + mui_secondary_objects_flat[210] = objects.nodes_hl_active_chat_switch; + mui_secondary_objects_flat[211] = objects.nodes_hl_name_area; + mui_secondary_objects_flat[212] = objects.nodes_hl_name_label; + mui_secondary_objects_flat[213] = objects.nodes_hl_position_label; + mui_secondary_objects_flat[214] = objects.nodes_hl_position_switch; + mui_secondary_objects_flat[215] = objects.nodes_hl_telemetry_label; + mui_secondary_objects_flat[216] = objects.nodes_hl_telemetry_switch; + mui_secondary_objects_flat[217] = objects.nodes_hliaq_label; + mui_secondary_objects_flat[218] = objects.nodes_hliaq_switch; + mui_secondary_objects_flat[219] = objects.nodes_panel; + mui_secondary_objects_flat[220] = objects.obj0; + mui_secondary_objects_flat[221] = objects.obj1; + mui_secondary_objects_flat[222] = objects.obj10; + mui_secondary_objects_flat[223] = objects.obj10__cancel_button_w; + mui_secondary_objects_flat[224] = objects.obj10__ok_button_w; + mui_secondary_objects_flat[225] = objects.obj10__ok_cancel_panel_w; + mui_secondary_objects_flat[226] = objects.obj11; + mui_secondary_objects_flat[227] = objects.obj11__cancel_button_w; + mui_secondary_objects_flat[228] = objects.obj11__ok_button_w; + mui_secondary_objects_flat[229] = objects.obj11__ok_cancel_panel_w; + mui_secondary_objects_flat[230] = objects.obj12; + mui_secondary_objects_flat[231] = objects.obj12__cancel_button_w; + mui_secondary_objects_flat[232] = objects.obj12__ok_button_w; + mui_secondary_objects_flat[233] = objects.obj12__ok_cancel_panel_w; + mui_secondary_objects_flat[234] = objects.obj13; + mui_secondary_objects_flat[235] = objects.obj13__cancel_button_w; + mui_secondary_objects_flat[236] = objects.obj13__ok_button_w; + mui_secondary_objects_flat[237] = objects.obj13__ok_cancel_panel_w; + mui_secondary_objects_flat[238] = objects.obj14; + mui_secondary_objects_flat[239] = objects.obj14__cancel_button_w; + mui_secondary_objects_flat[240] = objects.obj14__ok_button_w; + mui_secondary_objects_flat[241] = objects.obj14__ok_cancel_panel_w; + mui_secondary_objects_flat[242] = objects.obj15; + mui_secondary_objects_flat[243] = objects.obj15__cancel_button_w; + mui_secondary_objects_flat[244] = objects.obj15__ok_button_w; + mui_secondary_objects_flat[245] = objects.obj15__ok_cancel_panel_w; + mui_secondary_objects_flat[246] = objects.obj16; + mui_secondary_objects_flat[247] = objects.obj16__cancel_button_w; + mui_secondary_objects_flat[248] = objects.obj16__ok_button_w; + mui_secondary_objects_flat[249] = objects.obj16__ok_cancel_panel_w; + mui_secondary_objects_flat[250] = objects.obj17; + mui_secondary_objects_flat[251] = objects.obj17__cancel_button_w; + mui_secondary_objects_flat[252] = objects.obj17__ok_button_w; + mui_secondary_objects_flat[253] = objects.obj17__ok_cancel_panel_w; + mui_secondary_objects_flat[254] = objects.obj18; + mui_secondary_objects_flat[255] = objects.obj18__cancel_button_w; + mui_secondary_objects_flat[256] = objects.obj18__ok_button_w; + mui_secondary_objects_flat[257] = objects.obj18__ok_cancel_panel_w; + mui_secondary_objects_flat[258] = objects.obj19; + mui_secondary_objects_flat[259] = objects.obj2; + mui_secondary_objects_flat[260] = objects.obj20; + mui_secondary_objects_flat[261] = objects.obj21; + mui_secondary_objects_flat[262] = objects.obj21__cancel_button_w; + mui_secondary_objects_flat[263] = objects.obj21__ok_button_w; + mui_secondary_objects_flat[264] = objects.obj21__ok_cancel_panel_w; + mui_secondary_objects_flat[265] = objects.obj22; + mui_secondary_objects_flat[266] = objects.obj23; + mui_secondary_objects_flat[267] = objects.obj24; + mui_secondary_objects_flat[268] = objects.obj25; + mui_secondary_objects_flat[269] = objects.obj26; + mui_secondary_objects_flat[270] = objects.obj27; + mui_secondary_objects_flat[271] = objects.obj27__cancel_button_w; + mui_secondary_objects_flat[272] = objects.obj27__ok_button_w; + mui_secondary_objects_flat[273] = objects.obj27__ok_cancel_panel_w; + mui_secondary_objects_flat[274] = objects.obj2__cancel_button_w; + mui_secondary_objects_flat[275] = objects.obj2__ok_button_w; + mui_secondary_objects_flat[276] = objects.obj2__ok_cancel_panel_w; + mui_secondary_objects_flat[277] = objects.obj3; + mui_secondary_objects_flat[278] = objects.obj3__cancel_button_w; + mui_secondary_objects_flat[279] = objects.obj3__ok_button_w; + mui_secondary_objects_flat[280] = objects.obj3__ok_cancel_panel_w; + mui_secondary_objects_flat[281] = objects.obj4; + mui_secondary_objects_flat[282] = objects.obj4__cancel_button_w; + mui_secondary_objects_flat[283] = objects.obj4__ok_button_w; + mui_secondary_objects_flat[284] = objects.obj4__ok_cancel_panel_w; + mui_secondary_objects_flat[285] = objects.obj5; + mui_secondary_objects_flat[286] = objects.obj5__cancel_button_w; + mui_secondary_objects_flat[287] = objects.obj5__ok_button_w; + mui_secondary_objects_flat[288] = objects.obj5__ok_cancel_panel_w; + mui_secondary_objects_flat[289] = objects.obj6; + mui_secondary_objects_flat[290] = objects.obj6__cancel_button_w; + mui_secondary_objects_flat[291] = objects.obj6__ok_button_w; + mui_secondary_objects_flat[292] = objects.obj6__ok_cancel_panel_w; + mui_secondary_objects_flat[293] = objects.obj7; + mui_secondary_objects_flat[294] = objects.obj7__cancel_button_w; + mui_secondary_objects_flat[295] = objects.obj7__ok_button_w; + mui_secondary_objects_flat[296] = objects.obj7__ok_cancel_panel_w; + mui_secondary_objects_flat[297] = objects.obj8; + mui_secondary_objects_flat[298] = objects.obj8__cancel_button_w; + mui_secondary_objects_flat[299] = objects.obj8__ok_button_w; + mui_secondary_objects_flat[300] = objects.obj8__ok_cancel_panel_w; + mui_secondary_objects_flat[301] = objects.obj9; + mui_secondary_objects_flat[302] = objects.obj9__cancel_button_w; + mui_secondary_objects_flat[303] = objects.obj9__ok_button_w; + mui_secondary_objects_flat[304] = objects.obj9__ok_cancel_panel_w; + mui_secondary_objects_flat[305] = objects.position2_label; + mui_secondary_objects_flat[306] = objects.position_label; + mui_secondary_objects_flat[307] = objects.progmode_button; + mui_secondary_objects_flat[308] = objects.radar_beam; + mui_secondary_objects_flat[309] = objects.raw_map_panel; + mui_secondary_objects_flat[310] = objects.reboot_button; + mui_secondary_objects_flat[311] = objects.reboot_panel; + mui_secondary_objects_flat[312] = objects.route_back_panel; + mui_secondary_objects_flat[313] = objects.route_towards_panel; + mui_secondary_objects_flat[314] = objects.rssi_slider; + mui_secondary_objects_flat[315] = objects.screen_lock_button_matrix; + mui_secondary_objects_flat[316] = objects.screen_timeout_slider; + mui_secondary_objects_flat[317] = objects.settings_alert_buzzer_panel; + mui_secondary_objects_flat[318] = objects.settings_alert_buzzer_switch; + mui_secondary_objects_flat[319] = objects.settings_backup_checkbox; + mui_secondary_objects_flat[320] = objects.settings_backup_restore_dropdown; + mui_secondary_objects_flat[321] = objects.settings_backup_restore_panel; + mui_secondary_objects_flat[322] = objects.settings_brightness_label; + mui_secondary_objects_flat[323] = objects.settings_brightness_panel; + mui_secondary_objects_flat[324] = objects.settings_button; + mui_secondary_objects_flat[325] = objects.settings_channel0_button; + mui_secondary_objects_flat[326] = objects.settings_channel0_label; + mui_secondary_objects_flat[327] = objects.settings_channel1_button; + mui_secondary_objects_flat[328] = objects.settings_channel1_label; + mui_secondary_objects_flat[329] = objects.settings_channel2_button; + mui_secondary_objects_flat[330] = objects.settings_channel2_label; + mui_secondary_objects_flat[331] = objects.settings_channel3_button; + mui_secondary_objects_flat[332] = objects.settings_channel3_label; + mui_secondary_objects_flat[333] = objects.settings_channel4_button; + mui_secondary_objects_flat[334] = objects.settings_channel4_label; + mui_secondary_objects_flat[335] = objects.settings_channel5_button; + mui_secondary_objects_flat[336] = objects.settings_channel5_label; + mui_secondary_objects_flat[337] = objects.settings_channel6_button; + mui_secondary_objects_flat[338] = objects.settings_channel6_label; + mui_secondary_objects_flat[339] = objects.settings_channel7_button; + mui_secondary_objects_flat[340] = objects.settings_channel7_label; + mui_secondary_objects_flat[341] = objects.settings_channel_panel; + mui_secondary_objects_flat[342] = objects.settings_device_role_dropdown; + mui_secondary_objects_flat[343] = objects.settings_device_role_panel; + mui_secondary_objects_flat[344] = objects.settings_input_control_panel; + mui_secondary_objects_flat[345] = objects.settings_keyboard_input_dropdown; + mui_secondary_objects_flat[346] = objects.settings_language_dropdown; + mui_secondary_objects_flat[347] = objects.settings_language_panel; + mui_secondary_objects_flat[348] = objects.settings_modem_preset_dropdown; + mui_secondary_objects_flat[349] = objects.settings_modem_preset_panel; + mui_secondary_objects_flat[350] = objects.settings_modify_channel_key_generate_button; + mui_secondary_objects_flat[351] = objects.settings_modify_channel_name_textarea; + mui_secondary_objects_flat[352] = objects.settings_modify_channel_panel; + mui_secondary_objects_flat[353] = objects.settings_modify_channel_psk_textarea; + mui_secondary_objects_flat[354] = objects.settings_modify_channel_qr_button; + mui_secondary_objects_flat[355] = objects.settings_modify_channel_qr_panel; + mui_secondary_objects_flat[356] = objects.settings_modify_trash_button; + mui_secondary_objects_flat[357] = objects.settings_mouse_input_dropdown; + mui_secondary_objects_flat[358] = objects.settings_reboot_panel; + mui_secondary_objects_flat[359] = objects.settings_region_dropdown; + mui_secondary_objects_flat[360] = objects.settings_region_panel; + mui_secondary_objects_flat[361] = objects.settings_reset_dropdown; + mui_secondary_objects_flat[362] = objects.settings_reset_panel; + mui_secondary_objects_flat[363] = objects.settings_restore_checkbox; + mui_secondary_objects_flat[364] = objects.settings_ringtone_dropdown; + mui_secondary_objects_flat[365] = objects.settings_screen_lock_panel; + mui_secondary_objects_flat[366] = objects.settings_screen_lock_password_textarea; + mui_secondary_objects_flat[367] = objects.settings_screen_lock_switch; + mui_secondary_objects_flat[368] = objects.settings_screen_timeout_label; + mui_secondary_objects_flat[369] = objects.settings_screen_timeout_panel; + mui_secondary_objects_flat[370] = objects.settings_settings_lock_switch; + mui_secondary_objects_flat[371] = objects.settings_theme_dropdown; + mui_secondary_objects_flat[372] = objects.settings_theme_panel; + mui_secondary_objects_flat[373] = objects.settings_timezone; + mui_secondary_objects_flat[374] = objects.settings_tzcity; + mui_secondary_objects_flat[375] = objects.settings_tzzone; + mui_secondary_objects_flat[376] = objects.settings_user_long_textarea; + mui_secondary_objects_flat[377] = objects.settings_user_short_textarea; + mui_secondary_objects_flat[378] = objects.settings_username_panel; + mui_secondary_objects_flat[379] = objects.settings_wifi_panel; + mui_secondary_objects_flat[380] = objects.settings_wifi_password_textarea; + mui_secondary_objects_flat[381] = objects.settings_wifi_ssid_textarea; + mui_secondary_objects_flat[382] = objects.setup_panel; + mui_secondary_objects_flat[383] = objects.setup_region_dropdown; + mui_secondary_objects_flat[384] = objects.setup_user_long_textarea; + mui_secondary_objects_flat[385] = objects.setup_user_short_textarea; + mui_secondary_objects_flat[386] = objects.shutdown_button; + mui_secondary_objects_flat[387] = objects.signal_label; + mui_secondary_objects_flat[388] = objects.signal_scanner_node_button; + mui_secondary_objects_flat[389] = objects.signal_scanner_node_button_label; + mui_secondary_objects_flat[390] = objects.signal_scanner_node_image; + mui_secondary_objects_flat[391] = objects.signal_scanner_panel; + mui_secondary_objects_flat[392] = objects.signal_scanner_rssi_label; + mui_secondary_objects_flat[393] = objects.signal_scanner_rssi_scale_label; + mui_secondary_objects_flat[394] = objects.signal_scanner_snr_label; + mui_secondary_objects_flat[395] = objects.signal_scanner_snr_scale_label; + mui_secondary_objects_flat[396] = objects.signal_scanner_start_button; + mui_secondary_objects_flat[397] = objects.signal_scanner_start_label; + mui_secondary_objects_flat[398] = objects.snr_slider; + mui_secondary_objects_flat[399] = objects.start_button_panel; + mui_secondary_objects_flat[400] = objects.statistics_table; + mui_secondary_objects_flat[401] = objects.tab_page_basic_settings; + mui_secondary_objects_flat[402] = objects.tab_page_filter; + mui_secondary_objects_flat[403] = objects.tab_page_highlight; + mui_secondary_objects_flat[404] = objects.tab_page_tools; + mui_secondary_objects_flat[405] = objects.telemetry1_label; + mui_secondary_objects_flat[406] = objects.telemetry2_label; + mui_secondary_objects_flat[407] = objects.tools_mesh_detector_button; + mui_secondary_objects_flat[408] = objects.tools_mesh_detector_label; + mui_secondary_objects_flat[409] = objects.tools_neighbors_button; + mui_secondary_objects_flat[410] = objects.tools_neighbors_label; + mui_secondary_objects_flat[411] = objects.tools_packet_log_button; + mui_secondary_objects_flat[412] = objects.tools_packet_log_label; + mui_secondary_objects_flat[413] = objects.tools_packet_log_panel; + mui_secondary_objects_flat[414] = objects.tools_signal_scanner_button; + mui_secondary_objects_flat[415] = objects.tools_signal_scanner_label; + mui_secondary_objects_flat[416] = objects.tools_statistics_button; + mui_secondary_objects_flat[417] = objects.tools_statistics_label; + mui_secondary_objects_flat[418] = objects.tools_statistics_panel; + mui_secondary_objects_flat[419] = objects.tools_trace_route_button; + mui_secondary_objects_flat[420] = objects.tools_trace_route_label; + mui_secondary_objects_flat[421] = objects.top_advanced_settings_image; + mui_secondary_objects_flat[422] = objects.top_advanced_settings_label; + mui_secondary_objects_flat[423] = objects.top_advanced_settings_panel; + mui_secondary_objects_flat[424] = objects.top_basic_settings_image; + mui_secondary_objects_flat[425] = objects.top_basic_settings_label; + mui_secondary_objects_flat[426] = objects.top_chats_image; + mui_secondary_objects_flat[427] = objects.top_chats_label; + mui_secondary_objects_flat[428] = objects.top_chats_panel; + mui_secondary_objects_flat[429] = objects.top_group_chat_image; + mui_secondary_objects_flat[430] = objects.top_group_chat_label; + mui_secondary_objects_flat[431] = objects.top_group_chat_panel; + mui_secondary_objects_flat[432] = objects.top_group_image; + mui_secondary_objects_flat[433] = objects.top_groups_panel; + mui_secondary_objects_flat[434] = objects.top_lora_tx_image; + mui_secondary_objects_flat[435] = objects.top_lora_tx_label; + mui_secondary_objects_flat[436] = objects.top_lora_tx_panel; + mui_secondary_objects_flat[437] = objects.top_map_image; + mui_secondary_objects_flat[438] = objects.top_map_label; + mui_secondary_objects_flat[439] = objects.top_map_panel; + mui_secondary_objects_flat[440] = objects.top_mesh_detector_image; + mui_secondary_objects_flat[441] = objects.top_mesh_detector_label; + mui_secondary_objects_flat[442] = objects.top_mesh_detector_panel; + mui_secondary_objects_flat[443] = objects.top_messages_node_image; + mui_secondary_objects_flat[444] = objects.top_messages_node_label; + mui_secondary_objects_flat[445] = objects.top_messages_panel; + mui_secondary_objects_flat[446] = objects.top_neighbors_image; + mui_secondary_objects_flat[447] = objects.top_neighbors_label; + mui_secondary_objects_flat[448] = objects.top_neighbors_panel; + mui_secondary_objects_flat[449] = objects.top_node_options_image; + mui_secondary_objects_flat[450] = objects.top_node_options_label; + mui_secondary_objects_flat[451] = objects.top_node_options_panel; + mui_secondary_objects_flat[452] = objects.top_node_search_image; + mui_secondary_objects_flat[453] = objects.top_node_search_label; + mui_secondary_objects_flat[454] = objects.top_node_search_panel; + mui_secondary_objects_flat[455] = objects.top_nodes_image; + mui_secondary_objects_flat[456] = objects.top_nodes_online_label; + mui_secondary_objects_flat[457] = objects.top_nodes_panel; + mui_secondary_objects_flat[458] = objects.top_packet_log_image; + mui_secondary_objects_flat[459] = objects.top_packet_log_label; + mui_secondary_objects_flat[460] = objects.top_packet_log_panel; + mui_secondary_objects_flat[461] = objects.top_panel; + mui_secondary_objects_flat[462] = objects.top_settings_panel; + mui_secondary_objects_flat[463] = objects.top_setup_image; + mui_secondary_objects_flat[464] = objects.top_setup_label; + mui_secondary_objects_flat[465] = objects.top_setup_panel; + mui_secondary_objects_flat[466] = objects.top_signal_scanner_image; + mui_secondary_objects_flat[467] = objects.top_signal_scanner_label; + mui_secondary_objects_flat[468] = objects.top_signal_scanner_panel; + mui_secondary_objects_flat[469] = objects.top_statistics_image; + mui_secondary_objects_flat[470] = objects.top_statistics_label; + mui_secondary_objects_flat[471] = objects.top_statistics_panel; + mui_secondary_objects_flat[472] = objects.top_trace_route_image; + mui_secondary_objects_flat[473] = objects.top_trace_route_label; + mui_secondary_objects_flat[474] = objects.top_trace_route_panel; + mui_secondary_objects_flat[475] = objects.top_user_group_label; + mui_secondary_objects_flat[476] = objects.trace_route_panel; + mui_secondary_objects_flat[477] = objects.trace_route_start_button; + mui_secondary_objects_flat[478] = objects.trace_route_start_label; + mui_secondary_objects_flat[479] = objects.trace_route_to_button; + mui_secondary_objects_flat[480] = objects.trace_route_to_button_label; + mui_secondary_objects_flat[481] = objects.trace_route_to_image; + mui_secondary_objects_flat[482] = objects.user_name_label; + mui_secondary_objects_flat[483] = objects.user_name_short_label; + mui_secondary_objects_flat[484] = objects.zoom_in_button; + mui_secondary_objects_flat[485] = objects.zoom_out_button; + mui_secondary_objects_flat[486] = objects.zoom_slider; + mui_secondary_ui_flat[0] = ui_AdvancedSettingsPanel; + mui_secondary_ui_flat[1] = ui_AmbientLightingLabel; + mui_secondary_ui_flat[2] = ui_AudioLabel; + mui_secondary_ui_flat[3] = ui_AudioLabel1; + mui_secondary_ui_flat[4] = ui_BluetoothLabel; + mui_secondary_ui_flat[5] = ui_CannedMsgLabel; + mui_secondary_ui_flat[6] = ui_DetectionSensorLabel; + mui_secondary_ui_flat[7] = ui_DeviceLabel; + mui_secondary_ui_flat[8] = ui_DisplayLabel; + mui_secondary_ui_flat[9] = ui_ExtNotificationLabel; + mui_secondary_ui_flat[10] = ui_GeneralAudioButton; + mui_secondary_ui_flat[11] = ui_GeneralLanguageButton; + mui_secondary_ui_flat[12] = ui_GeneralMapsButton; + mui_secondary_ui_flat[13] = ui_GeneralScreenButton; + mui_secondary_ui_flat[14] = ui_GeneralTimezoneButton; + mui_secondary_ui_flat[15] = ui_LanguageLabel; + mui_secondary_ui_flat[16] = ui_LoRaLabel; + mui_secondary_ui_flat[17] = ui_MQTTLabel; + mui_secondary_ui_flat[18] = ui_MapsLabel; + mui_secondary_ui_flat[19] = ui_ModuleAmbientLightingButton; + mui_secondary_ui_flat[20] = ui_ModuleAudioButton; + mui_secondary_ui_flat[21] = ui_ModuleCannedMsgButton; + mui_secondary_ui_flat[22] = ui_ModuleDetectionSensorButton; + mui_secondary_ui_flat[23] = ui_ModuleExtNotificationButton; + mui_secondary_ui_flat[24] = ui_ModuleMQTTButton; + mui_secondary_ui_flat[25] = ui_ModuleNeighborInfoButton; + mui_secondary_ui_flat[26] = ui_ModuleRangeTestButton; + mui_secondary_ui_flat[27] = ui_ModuleRemoteHardwareButton; + mui_secondary_ui_flat[28] = ui_ModuleSaFButton; + mui_secondary_ui_flat[29] = ui_ModuleSerialButton; + mui_secondary_ui_flat[30] = ui_ModuleTelemetryButton; + mui_secondary_ui_flat[31] = ui_NeighborInfoLabel; + mui_secondary_ui_flat[32] = ui_NetworkLabel; + mui_secondary_ui_flat[33] = ui_PositionLabel; + mui_secondary_ui_flat[34] = ui_PowerLabel; + mui_secondary_ui_flat[35] = ui_RadioBluetoothButton; + mui_secondary_ui_flat[36] = ui_RadioDeviceButton; + mui_secondary_ui_flat[37] = ui_RadioDisplayButton; + mui_secondary_ui_flat[38] = ui_RadioLoRaButton; + mui_secondary_ui_flat[39] = ui_RadioNetworkButton; + mui_secondary_ui_flat[40] = ui_RadioPositionButton; + mui_secondary_ui_flat[41] = ui_RadioPowerButton; + mui_secondary_ui_flat[42] = ui_RangeTestLabel; + mui_secondary_ui_flat[43] = ui_RemoteHardwareLabel; + mui_secondary_ui_flat[44] = ui_ScreenLabel; + mui_secondary_ui_flat[45] = ui_SerialLabel; + mui_secondary_ui_flat[46] = ui_SettingsTabView; + mui_secondary_ui_flat[47] = ui_StoreAndForwardLabel; + mui_secondary_ui_flat[48] = ui_TabPageGeneral; + mui_secondary_ui_flat[49] = ui_TabPageModules; + mui_secondary_ui_flat[50] = ui_TabPageRadio; + mui_secondary_ui_flat[51] = ui_TelemetryLabel; + mui_secondary_ui_flat[52] = ui_TimezoneLabel; +} diff --git a/tools/generated/dual/manifest.txt b/tools/generated/dual/manifest.txt new file mode 100644 index 00000000..6d467e21 --- /dev/null +++ b/tools/generated/dual/manifest.txt @@ -0,0 +1,212 @@ +members=487 +renamed_symbols=198 +ui_pointers=53 +shared_assets=93 +fingerprint=4311c2ae048d6318567e8de8bcc465a19db25a381358a8597539c397c8242ab9 +core_source images.c +core_source screens.c +core_source styles.c +core_source ui.c +core_source ui_tabview_settings.c +glue_source bridge_primary.c +glue_source bridge_secondary.c +secondary_asset ui_320x240 ui_image_home_bell_slash_image.c +secondary_asset ui_320x240 ui_image_top_message_node_images.c +sym active_theme_index +sym add_style +sym add_style_alert_panel_style +sym add_style_button_matrix_style +sym add_style_button_panel_style +sym add_style_bw_label_style +sym add_style_channel_button_style +sym add_style_chat_message_style +sym add_style_color_label_style +sym add_style_drop_down_style +sym add_style_home_button_style +sym add_style_home_container_style +sym add_style_main_button_style +sym add_style_main_screen_style +sym add_style_map_arrow_style +sym add_style_new_message_style +sym add_style_node_button_style +sym add_style_node_panel_style +sym add_style_panel_style +sym add_style_positive_image_style +sym add_style_settings_button_style +sym add_style_settings_label_style +sym add_style_settings_panel_style +sym add_style_spinner_style +sym add_style_statistics_table_style +sym add_style_tab_view_style +sym add_style_top_image_style +sym add_style_top_panel_style +sym create_screen_blank_screen +sym create_screen_boot_screen +sym create_screen_calibration_screen +sym create_screen_lock_screen +sym create_screen_main_screen +sym create_screens +sym create_tabview_settings +sym create_user_widget_ok_cancel_widget +sym fonts +sym get_style_alert_panel_style_MAIN_DEFAULT +sym get_style_button_matrix_style_ITEMS_DEFAULT +sym get_style_button_matrix_style_MAIN_DEFAULT +sym get_style_button_panel_style_MAIN_DEFAULT +sym get_style_bw_label_style_MAIN_DEFAULT +sym get_style_channel_button_style_MAIN_DEFAULT +sym get_style_chat_message_style_MAIN_DEFAULT +sym get_style_color_label_style_MAIN_DEFAULT +sym get_style_home_button_style_MAIN_DEFAULT +sym get_style_home_container_style_MAIN_DEFAULT +sym get_style_main_button_style_MAIN_DEFAULT +sym get_style_main_screen_style_MAIN_DEFAULT +sym get_style_main_screen_style_MAIN_PRESSED +sym get_style_map_arrow_style_MAIN_DEFAULT +sym get_style_map_arrow_style_MAIN_PRESSED +sym get_style_new_message_style_MAIN_DEFAULT +sym get_style_node_button_style_MAIN_DEFAULT +sym get_style_node_panel_style_MAIN_DEFAULT +sym get_style_panel_style_MAIN_DEFAULT +sym get_style_panel_style_MAIN_PRESSED +sym get_style_positive_image_style_MAIN_DEFAULT +sym get_style_settings_button_style_MAIN_DEFAULT +sym get_style_settings_label_style_MAIN_DEFAULT +sym get_style_settings_panel_style_MAIN_DEFAULT +sym get_style_spinner_style_INDICATOR_DEFAULT +sym get_style_spinner_style_MAIN_DEFAULT +sym get_style_statistics_table_style_ITEMS_DEFAULT +sym get_style_statistics_table_style_MAIN_DEFAULT +sym get_style_tab_view_style_MAIN_DEFAULT +sym get_style_top_image_style_MAIN_DEFAULT +sym get_style_top_panel_style_MAIN_DEFAULT +sym images +sym init_style_alert_panel_style_MAIN_DEFAULT +sym init_style_button_matrix_style_ITEMS_DEFAULT +sym init_style_button_matrix_style_MAIN_DEFAULT +sym init_style_button_panel_style_MAIN_DEFAULT +sym init_style_bw_label_style_MAIN_DEFAULT +sym init_style_channel_button_style_MAIN_DEFAULT +sym init_style_chat_message_style_MAIN_DEFAULT +sym init_style_color_label_style_MAIN_DEFAULT +sym init_style_home_button_style_MAIN_DEFAULT +sym init_style_home_container_style_MAIN_DEFAULT +sym init_style_main_button_style_MAIN_DEFAULT +sym init_style_main_screen_style_MAIN_DEFAULT +sym init_style_main_screen_style_MAIN_PRESSED +sym init_style_map_arrow_style_MAIN_DEFAULT +sym init_style_map_arrow_style_MAIN_PRESSED +sym init_style_new_message_style_MAIN_DEFAULT +sym init_style_node_button_style_MAIN_DEFAULT +sym init_style_node_panel_style_MAIN_DEFAULT +sym init_style_panel_style_MAIN_DEFAULT +sym init_style_panel_style_MAIN_PRESSED +sym init_style_positive_image_style_MAIN_DEFAULT +sym init_style_settings_button_style_MAIN_DEFAULT +sym init_style_settings_label_style_MAIN_DEFAULT +sym init_style_settings_panel_style_MAIN_DEFAULT +sym init_style_spinner_style_INDICATOR_DEFAULT +sym init_style_spinner_style_MAIN_DEFAULT +sym init_style_statistics_table_style_ITEMS_DEFAULT +sym init_style_statistics_table_style_MAIN_DEFAULT +sym init_style_tab_view_style_MAIN_DEFAULT +sym init_style_top_image_style_MAIN_DEFAULT +sym init_style_top_panel_style_MAIN_DEFAULT +sym loadScreen +sym objects +sym remove_style +sym remove_style_alert_panel_style +sym remove_style_button_matrix_style +sym remove_style_button_panel_style +sym remove_style_bw_label_style +sym remove_style_channel_button_style +sym remove_style_chat_message_style +sym remove_style_color_label_style +sym remove_style_drop_down_style +sym remove_style_home_button_style +sym remove_style_home_container_style +sym remove_style_main_button_style +sym remove_style_main_screen_style +sym remove_style_map_arrow_style +sym remove_style_new_message_style +sym remove_style_node_button_style +sym remove_style_node_panel_style +sym remove_style_panel_style +sym remove_style_positive_image_style +sym remove_style_settings_button_style +sym remove_style_settings_label_style +sym remove_style_settings_panel_style +sym remove_style_spinner_style +sym remove_style_statistics_table_style +sym remove_style_tab_view_style +sym remove_style_top_image_style +sym remove_style_top_panel_style +sym style_btn_active +sym style_btn_default +sym style_btn_pressed +sym tick_screen +sym tick_screen_blank_screen +sym tick_screen_boot_screen +sym tick_screen_by_id +sym tick_screen_calibration_screen +sym tick_screen_funcs +sym tick_screen_lock_screen +sym tick_screen_main_screen +sym tick_user_widget_ok_cancel_widget +sym tick_value_change_obj +sym ui_AdvancedSettingsPanel +sym ui_AmbientLightingLabel +sym ui_AudioLabel +sym ui_AudioLabel1 +sym ui_BluetoothLabel +sym ui_CannedMsgLabel +sym ui_DetectionSensorLabel +sym ui_DeviceLabel +sym ui_DisplayLabel +sym ui_ExtNotificationLabel +sym ui_GeneralAudioButton +sym ui_GeneralLanguageButton +sym ui_GeneralMapsButton +sym ui_GeneralScreenButton +sym ui_GeneralTimezoneButton +sym ui_LanguageLabel +sym ui_LoRaLabel +sym ui_MQTTLabel +sym ui_MapsLabel +sym ui_ModuleAmbientLightingButton +sym ui_ModuleAudioButton +sym ui_ModuleCannedMsgButton +sym ui_ModuleDetectionSensorButton +sym ui_ModuleExtNotificationButton +sym ui_ModuleMQTTButton +sym ui_ModuleNeighborInfoButton +sym ui_ModuleRangeTestButton +sym ui_ModuleRemoteHardwareButton +sym ui_ModuleSaFButton +sym ui_ModuleSerialButton +sym ui_ModuleTelemetryButton +sym ui_NeighborInfoLabel +sym ui_NetworkLabel +sym ui_PositionLabel +sym ui_PowerLabel +sym ui_RadioBluetoothButton +sym ui_RadioDeviceButton +sym ui_RadioDisplayButton +sym ui_RadioLoRaButton +sym ui_RadioNetworkButton +sym ui_RadioPositionButton +sym ui_RadioPowerButton +sym ui_RangeTestLabel +sym ui_RemoteHardwareLabel +sym ui_ScreenLabel +sym ui_SerialLabel +sym ui_SettingsTabView +sym ui_StoreAndForwardLabel +sym ui_TabPageGeneral +sym ui_TabPageModules +sym ui_TabPageRadio +sym ui_TelemetryLabel +sym ui_TimezoneLabel +sym ui_init +sym ui_init_boot +sym ui_tick diff --git a/tools/generated/dual/style_routing.h b/tools/generated/dual/style_routing.h new file mode 100644 index 00000000..10a219bb --- /dev/null +++ b/tools/generated/dual/style_routing.h @@ -0,0 +1,353 @@ +// GENERATED by tools/gen_dual_ui.py - do not edit. +// Force-included into the C++ sources that reference generated styles. +#pragma once +#include "graphics/ScreenRotation.h" +#include "styles.h" + +extern "C" { +void MUI2_add_style_alert_panel_style(lv_obj_t *obj); +void MUI2_add_style_button_matrix_style(lv_obj_t *obj); +void MUI2_add_style_button_panel_style(lv_obj_t *obj); +void MUI2_add_style_bw_label_style(lv_obj_t *obj); +void MUI2_add_style_channel_button_style(lv_obj_t *obj); +void MUI2_add_style_chat_message_style(lv_obj_t *obj); +void MUI2_add_style_color_label_style(lv_obj_t *obj); +void MUI2_add_style_drop_down_style(lv_obj_t *obj); +void MUI2_add_style_home_button_style(lv_obj_t *obj); +void MUI2_add_style_home_container_style(lv_obj_t *obj); +void MUI2_add_style_main_button_style(lv_obj_t *obj); +void MUI2_add_style_main_screen_style(lv_obj_t *obj); +void MUI2_add_style_map_arrow_style(lv_obj_t *obj); +void MUI2_add_style_new_message_style(lv_obj_t *obj); +void MUI2_add_style_node_button_style(lv_obj_t *obj); +void MUI2_add_style_node_panel_style(lv_obj_t *obj); +void MUI2_add_style_panel_style(lv_obj_t *obj); +void MUI2_add_style_positive_image_style(lv_obj_t *obj); +void MUI2_add_style_settings_button_style(lv_obj_t *obj); +void MUI2_add_style_settings_label_style(lv_obj_t *obj); +void MUI2_add_style_settings_panel_style(lv_obj_t *obj); +void MUI2_add_style_spinner_style(lv_obj_t *obj); +void MUI2_add_style_statistics_table_style(lv_obj_t *obj); +void MUI2_add_style_tab_view_style(lv_obj_t *obj); +void MUI2_add_style_top_image_style(lv_obj_t *obj); +void MUI2_add_style_top_panel_style(lv_obj_t *obj); +lv_style_t *MUI2_get_style_alert_panel_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_button_matrix_style_ITEMS_DEFAULT(void); +lv_style_t *MUI2_get_style_button_matrix_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_button_panel_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_bw_label_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_channel_button_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_chat_message_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_color_label_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_home_button_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_home_container_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_main_button_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_main_screen_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_main_screen_style_MAIN_PRESSED(void); +lv_style_t *MUI2_get_style_map_arrow_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_map_arrow_style_MAIN_PRESSED(void); +lv_style_t *MUI2_get_style_new_message_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_node_button_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_node_panel_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_panel_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_panel_style_MAIN_PRESSED(void); +lv_style_t *MUI2_get_style_positive_image_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_settings_button_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_settings_label_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_settings_panel_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_spinner_style_INDICATOR_DEFAULT(void); +lv_style_t *MUI2_get_style_spinner_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_statistics_table_style_ITEMS_DEFAULT(void); +lv_style_t *MUI2_get_style_statistics_table_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_tab_view_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_top_image_style_MAIN_DEFAULT(void); +lv_style_t *MUI2_get_style_top_panel_style_MAIN_DEFAULT(void); +void MUI2_remove_style_alert_panel_style(lv_obj_t *obj); +void MUI2_remove_style_button_matrix_style(lv_obj_t *obj); +void MUI2_remove_style_button_panel_style(lv_obj_t *obj); +void MUI2_remove_style_bw_label_style(lv_obj_t *obj); +void MUI2_remove_style_channel_button_style(lv_obj_t *obj); +void MUI2_remove_style_chat_message_style(lv_obj_t *obj); +void MUI2_remove_style_color_label_style(lv_obj_t *obj); +void MUI2_remove_style_drop_down_style(lv_obj_t *obj); +void MUI2_remove_style_home_button_style(lv_obj_t *obj); +void MUI2_remove_style_home_container_style(lv_obj_t *obj); +void MUI2_remove_style_main_button_style(lv_obj_t *obj); +void MUI2_remove_style_main_screen_style(lv_obj_t *obj); +void MUI2_remove_style_map_arrow_style(lv_obj_t *obj); +void MUI2_remove_style_new_message_style(lv_obj_t *obj); +void MUI2_remove_style_node_button_style(lv_obj_t *obj); +void MUI2_remove_style_node_panel_style(lv_obj_t *obj); +void MUI2_remove_style_panel_style(lv_obj_t *obj); +void MUI2_remove_style_positive_image_style(lv_obj_t *obj); +void MUI2_remove_style_settings_button_style(lv_obj_t *obj); +void MUI2_remove_style_settings_label_style(lv_obj_t *obj); +void MUI2_remove_style_settings_panel_style(lv_obj_t *obj); +void MUI2_remove_style_spinner_style(lv_obj_t *obj); +void MUI2_remove_style_statistics_table_style(lv_obj_t *obj); +void MUI2_remove_style_tab_view_style(lv_obj_t *obj); +void MUI2_remove_style_top_image_style(lv_obj_t *obj); +void MUI2_remove_style_top_panel_style(lv_obj_t *obj); +extern lv_style_t MUI2_style_btn_active; +extern lv_style_t MUI2_style_btn_default; +extern lv_style_t MUI2_style_btn_pressed; +} + +static inline void mui_route_add_style_alert_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_alert_panel_style(obj); else add_style_alert_panel_style(obj); } +#define add_style_alert_panel_style mui_route_add_style_alert_panel_style +static inline void mui_route_add_style_button_matrix_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_button_matrix_style(obj); else add_style_button_matrix_style(obj); } +#define add_style_button_matrix_style mui_route_add_style_button_matrix_style +static inline void mui_route_add_style_button_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_button_panel_style(obj); else add_style_button_panel_style(obj); } +#define add_style_button_panel_style mui_route_add_style_button_panel_style +static inline void mui_route_add_style_bw_label_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_bw_label_style(obj); else add_style_bw_label_style(obj); } +#define add_style_bw_label_style mui_route_add_style_bw_label_style +static inline void mui_route_add_style_channel_button_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_channel_button_style(obj); else add_style_channel_button_style(obj); } +#define add_style_channel_button_style mui_route_add_style_channel_button_style +static inline void mui_route_add_style_chat_message_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_chat_message_style(obj); else add_style_chat_message_style(obj); } +#define add_style_chat_message_style mui_route_add_style_chat_message_style +static inline void mui_route_add_style_color_label_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_color_label_style(obj); else add_style_color_label_style(obj); } +#define add_style_color_label_style mui_route_add_style_color_label_style +static inline void mui_route_add_style_drop_down_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_drop_down_style(obj); else add_style_drop_down_style(obj); } +#define add_style_drop_down_style mui_route_add_style_drop_down_style +static inline void mui_route_add_style_home_button_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_home_button_style(obj); else add_style_home_button_style(obj); } +#define add_style_home_button_style mui_route_add_style_home_button_style +static inline void mui_route_add_style_home_container_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_home_container_style(obj); else add_style_home_container_style(obj); } +#define add_style_home_container_style mui_route_add_style_home_container_style +static inline void mui_route_add_style_main_button_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_main_button_style(obj); else add_style_main_button_style(obj); } +#define add_style_main_button_style mui_route_add_style_main_button_style +static inline void mui_route_add_style_main_screen_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_main_screen_style(obj); else add_style_main_screen_style(obj); } +#define add_style_main_screen_style mui_route_add_style_main_screen_style +static inline void mui_route_add_style_map_arrow_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_map_arrow_style(obj); else add_style_map_arrow_style(obj); } +#define add_style_map_arrow_style mui_route_add_style_map_arrow_style +static inline void mui_route_add_style_new_message_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_new_message_style(obj); else add_style_new_message_style(obj); } +#define add_style_new_message_style mui_route_add_style_new_message_style +static inline void mui_route_add_style_node_button_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_node_button_style(obj); else add_style_node_button_style(obj); } +#define add_style_node_button_style mui_route_add_style_node_button_style +static inline void mui_route_add_style_node_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_node_panel_style(obj); else add_style_node_panel_style(obj); } +#define add_style_node_panel_style mui_route_add_style_node_panel_style +static inline void mui_route_add_style_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_panel_style(obj); else add_style_panel_style(obj); } +#define add_style_panel_style mui_route_add_style_panel_style +static inline void mui_route_add_style_positive_image_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_positive_image_style(obj); else add_style_positive_image_style(obj); } +#define add_style_positive_image_style mui_route_add_style_positive_image_style +static inline void mui_route_add_style_settings_button_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_settings_button_style(obj); else add_style_settings_button_style(obj); } +#define add_style_settings_button_style mui_route_add_style_settings_button_style +static inline void mui_route_add_style_settings_label_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_settings_label_style(obj); else add_style_settings_label_style(obj); } +#define add_style_settings_label_style mui_route_add_style_settings_label_style +static inline void mui_route_add_style_settings_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_settings_panel_style(obj); else add_style_settings_panel_style(obj); } +#define add_style_settings_panel_style mui_route_add_style_settings_panel_style +static inline void mui_route_add_style_spinner_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_spinner_style(obj); else add_style_spinner_style(obj); } +#define add_style_spinner_style mui_route_add_style_spinner_style +static inline void mui_route_add_style_statistics_table_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_statistics_table_style(obj); else add_style_statistics_table_style(obj); } +#define add_style_statistics_table_style mui_route_add_style_statistics_table_style +static inline void mui_route_add_style_tab_view_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_tab_view_style(obj); else add_style_tab_view_style(obj); } +#define add_style_tab_view_style mui_route_add_style_tab_view_style +static inline void mui_route_add_style_top_image_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_top_image_style(obj); else add_style_top_image_style(obj); } +#define add_style_top_image_style mui_route_add_style_top_image_style +static inline void mui_route_add_style_top_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_add_style_top_panel_style(obj); else add_style_top_panel_style(obj); } +#define add_style_top_panel_style mui_route_add_style_top_panel_style +static inline lv_style_t *mui_route_get_style_alert_panel_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_alert_panel_style_MAIN_DEFAULT() : get_style_alert_panel_style_MAIN_DEFAULT(); } +#define get_style_alert_panel_style_MAIN_DEFAULT mui_route_get_style_alert_panel_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_button_matrix_style_ITEMS_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_button_matrix_style_ITEMS_DEFAULT() : get_style_button_matrix_style_ITEMS_DEFAULT(); } +#define get_style_button_matrix_style_ITEMS_DEFAULT mui_route_get_style_button_matrix_style_ITEMS_DEFAULT +static inline lv_style_t *mui_route_get_style_button_matrix_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_button_matrix_style_MAIN_DEFAULT() : get_style_button_matrix_style_MAIN_DEFAULT(); } +#define get_style_button_matrix_style_MAIN_DEFAULT mui_route_get_style_button_matrix_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_button_panel_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_button_panel_style_MAIN_DEFAULT() : get_style_button_panel_style_MAIN_DEFAULT(); } +#define get_style_button_panel_style_MAIN_DEFAULT mui_route_get_style_button_panel_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_bw_label_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_bw_label_style_MAIN_DEFAULT() : get_style_bw_label_style_MAIN_DEFAULT(); } +#define get_style_bw_label_style_MAIN_DEFAULT mui_route_get_style_bw_label_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_channel_button_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_channel_button_style_MAIN_DEFAULT() : get_style_channel_button_style_MAIN_DEFAULT(); } +#define get_style_channel_button_style_MAIN_DEFAULT mui_route_get_style_channel_button_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_chat_message_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_chat_message_style_MAIN_DEFAULT() : get_style_chat_message_style_MAIN_DEFAULT(); } +#define get_style_chat_message_style_MAIN_DEFAULT mui_route_get_style_chat_message_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_color_label_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_color_label_style_MAIN_DEFAULT() : get_style_color_label_style_MAIN_DEFAULT(); } +#define get_style_color_label_style_MAIN_DEFAULT mui_route_get_style_color_label_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_home_button_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_home_button_style_MAIN_DEFAULT() : get_style_home_button_style_MAIN_DEFAULT(); } +#define get_style_home_button_style_MAIN_DEFAULT mui_route_get_style_home_button_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_home_container_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_home_container_style_MAIN_DEFAULT() : get_style_home_container_style_MAIN_DEFAULT(); } +#define get_style_home_container_style_MAIN_DEFAULT mui_route_get_style_home_container_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_main_button_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_main_button_style_MAIN_DEFAULT() : get_style_main_button_style_MAIN_DEFAULT(); } +#define get_style_main_button_style_MAIN_DEFAULT mui_route_get_style_main_button_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_main_screen_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_main_screen_style_MAIN_DEFAULT() : get_style_main_screen_style_MAIN_DEFAULT(); } +#define get_style_main_screen_style_MAIN_DEFAULT mui_route_get_style_main_screen_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_main_screen_style_MAIN_PRESSED(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_main_screen_style_MAIN_PRESSED() : get_style_main_screen_style_MAIN_PRESSED(); } +#define get_style_main_screen_style_MAIN_PRESSED mui_route_get_style_main_screen_style_MAIN_PRESSED +static inline lv_style_t *mui_route_get_style_map_arrow_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_map_arrow_style_MAIN_DEFAULT() : get_style_map_arrow_style_MAIN_DEFAULT(); } +#define get_style_map_arrow_style_MAIN_DEFAULT mui_route_get_style_map_arrow_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_map_arrow_style_MAIN_PRESSED(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_map_arrow_style_MAIN_PRESSED() : get_style_map_arrow_style_MAIN_PRESSED(); } +#define get_style_map_arrow_style_MAIN_PRESSED mui_route_get_style_map_arrow_style_MAIN_PRESSED +static inline lv_style_t *mui_route_get_style_new_message_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_new_message_style_MAIN_DEFAULT() : get_style_new_message_style_MAIN_DEFAULT(); } +#define get_style_new_message_style_MAIN_DEFAULT mui_route_get_style_new_message_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_node_button_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_node_button_style_MAIN_DEFAULT() : get_style_node_button_style_MAIN_DEFAULT(); } +#define get_style_node_button_style_MAIN_DEFAULT mui_route_get_style_node_button_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_node_panel_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_node_panel_style_MAIN_DEFAULT() : get_style_node_panel_style_MAIN_DEFAULT(); } +#define get_style_node_panel_style_MAIN_DEFAULT mui_route_get_style_node_panel_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_panel_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_panel_style_MAIN_DEFAULT() : get_style_panel_style_MAIN_DEFAULT(); } +#define get_style_panel_style_MAIN_DEFAULT mui_route_get_style_panel_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_panel_style_MAIN_PRESSED(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_panel_style_MAIN_PRESSED() : get_style_panel_style_MAIN_PRESSED(); } +#define get_style_panel_style_MAIN_PRESSED mui_route_get_style_panel_style_MAIN_PRESSED +static inline lv_style_t *mui_route_get_style_positive_image_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_positive_image_style_MAIN_DEFAULT() : get_style_positive_image_style_MAIN_DEFAULT(); } +#define get_style_positive_image_style_MAIN_DEFAULT mui_route_get_style_positive_image_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_settings_button_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_settings_button_style_MAIN_DEFAULT() : get_style_settings_button_style_MAIN_DEFAULT(); } +#define get_style_settings_button_style_MAIN_DEFAULT mui_route_get_style_settings_button_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_settings_label_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_settings_label_style_MAIN_DEFAULT() : get_style_settings_label_style_MAIN_DEFAULT(); } +#define get_style_settings_label_style_MAIN_DEFAULT mui_route_get_style_settings_label_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_settings_panel_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_settings_panel_style_MAIN_DEFAULT() : get_style_settings_panel_style_MAIN_DEFAULT(); } +#define get_style_settings_panel_style_MAIN_DEFAULT mui_route_get_style_settings_panel_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_spinner_style_INDICATOR_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_spinner_style_INDICATOR_DEFAULT() : get_style_spinner_style_INDICATOR_DEFAULT(); } +#define get_style_spinner_style_INDICATOR_DEFAULT mui_route_get_style_spinner_style_INDICATOR_DEFAULT +static inline lv_style_t *mui_route_get_style_spinner_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_spinner_style_MAIN_DEFAULT() : get_style_spinner_style_MAIN_DEFAULT(); } +#define get_style_spinner_style_MAIN_DEFAULT mui_route_get_style_spinner_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_statistics_table_style_ITEMS_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_statistics_table_style_ITEMS_DEFAULT() : get_style_statistics_table_style_ITEMS_DEFAULT(); } +#define get_style_statistics_table_style_ITEMS_DEFAULT mui_route_get_style_statistics_table_style_ITEMS_DEFAULT +static inline lv_style_t *mui_route_get_style_statistics_table_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_statistics_table_style_MAIN_DEFAULT() : get_style_statistics_table_style_MAIN_DEFAULT(); } +#define get_style_statistics_table_style_MAIN_DEFAULT mui_route_get_style_statistics_table_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_tab_view_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_tab_view_style_MAIN_DEFAULT() : get_style_tab_view_style_MAIN_DEFAULT(); } +#define get_style_tab_view_style_MAIN_DEFAULT mui_route_get_style_tab_view_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_top_image_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_top_image_style_MAIN_DEFAULT() : get_style_top_image_style_MAIN_DEFAULT(); } +#define get_style_top_image_style_MAIN_DEFAULT mui_route_get_style_top_image_style_MAIN_DEFAULT +static inline lv_style_t *mui_route_get_style_top_panel_style_MAIN_DEFAULT(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_get_style_top_panel_style_MAIN_DEFAULT() : get_style_top_panel_style_MAIN_DEFAULT(); } +#define get_style_top_panel_style_MAIN_DEFAULT mui_route_get_style_top_panel_style_MAIN_DEFAULT +static inline void mui_route_remove_style_alert_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_alert_panel_style(obj); else remove_style_alert_panel_style(obj); } +#define remove_style_alert_panel_style mui_route_remove_style_alert_panel_style +static inline void mui_route_remove_style_button_matrix_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_button_matrix_style(obj); else remove_style_button_matrix_style(obj); } +#define remove_style_button_matrix_style mui_route_remove_style_button_matrix_style +static inline void mui_route_remove_style_button_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_button_panel_style(obj); else remove_style_button_panel_style(obj); } +#define remove_style_button_panel_style mui_route_remove_style_button_panel_style +static inline void mui_route_remove_style_bw_label_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_bw_label_style(obj); else remove_style_bw_label_style(obj); } +#define remove_style_bw_label_style mui_route_remove_style_bw_label_style +static inline void mui_route_remove_style_channel_button_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_channel_button_style(obj); else remove_style_channel_button_style(obj); } +#define remove_style_channel_button_style mui_route_remove_style_channel_button_style +static inline void mui_route_remove_style_chat_message_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_chat_message_style(obj); else remove_style_chat_message_style(obj); } +#define remove_style_chat_message_style mui_route_remove_style_chat_message_style +static inline void mui_route_remove_style_color_label_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_color_label_style(obj); else remove_style_color_label_style(obj); } +#define remove_style_color_label_style mui_route_remove_style_color_label_style +static inline void mui_route_remove_style_drop_down_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_drop_down_style(obj); else remove_style_drop_down_style(obj); } +#define remove_style_drop_down_style mui_route_remove_style_drop_down_style +static inline void mui_route_remove_style_home_button_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_home_button_style(obj); else remove_style_home_button_style(obj); } +#define remove_style_home_button_style mui_route_remove_style_home_button_style +static inline void mui_route_remove_style_home_container_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_home_container_style(obj); else remove_style_home_container_style(obj); } +#define remove_style_home_container_style mui_route_remove_style_home_container_style +static inline void mui_route_remove_style_main_button_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_main_button_style(obj); else remove_style_main_button_style(obj); } +#define remove_style_main_button_style mui_route_remove_style_main_button_style +static inline void mui_route_remove_style_main_screen_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_main_screen_style(obj); else remove_style_main_screen_style(obj); } +#define remove_style_main_screen_style mui_route_remove_style_main_screen_style +static inline void mui_route_remove_style_map_arrow_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_map_arrow_style(obj); else remove_style_map_arrow_style(obj); } +#define remove_style_map_arrow_style mui_route_remove_style_map_arrow_style +static inline void mui_route_remove_style_new_message_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_new_message_style(obj); else remove_style_new_message_style(obj); } +#define remove_style_new_message_style mui_route_remove_style_new_message_style +static inline void mui_route_remove_style_node_button_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_node_button_style(obj); else remove_style_node_button_style(obj); } +#define remove_style_node_button_style mui_route_remove_style_node_button_style +static inline void mui_route_remove_style_node_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_node_panel_style(obj); else remove_style_node_panel_style(obj); } +#define remove_style_node_panel_style mui_route_remove_style_node_panel_style +static inline void mui_route_remove_style_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_panel_style(obj); else remove_style_panel_style(obj); } +#define remove_style_panel_style mui_route_remove_style_panel_style +static inline void mui_route_remove_style_positive_image_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_positive_image_style(obj); else remove_style_positive_image_style(obj); } +#define remove_style_positive_image_style mui_route_remove_style_positive_image_style +static inline void mui_route_remove_style_settings_button_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_settings_button_style(obj); else remove_style_settings_button_style(obj); } +#define remove_style_settings_button_style mui_route_remove_style_settings_button_style +static inline void mui_route_remove_style_settings_label_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_settings_label_style(obj); else remove_style_settings_label_style(obj); } +#define remove_style_settings_label_style mui_route_remove_style_settings_label_style +static inline void mui_route_remove_style_settings_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_settings_panel_style(obj); else remove_style_settings_panel_style(obj); } +#define remove_style_settings_panel_style mui_route_remove_style_settings_panel_style +static inline void mui_route_remove_style_spinner_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_spinner_style(obj); else remove_style_spinner_style(obj); } +#define remove_style_spinner_style mui_route_remove_style_spinner_style +static inline void mui_route_remove_style_statistics_table_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_statistics_table_style(obj); else remove_style_statistics_table_style(obj); } +#define remove_style_statistics_table_style mui_route_remove_style_statistics_table_style +static inline void mui_route_remove_style_tab_view_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_tab_view_style(obj); else remove_style_tab_view_style(obj); } +#define remove_style_tab_view_style mui_route_remove_style_tab_view_style +static inline void mui_route_remove_style_top_image_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_top_image_style(obj); else remove_style_top_image_style(obj); } +#define remove_style_top_image_style mui_route_remove_style_top_image_style +static inline void mui_route_remove_style_top_panel_style(lv_obj_t *obj) +{ if (ScreenRotation::usesSecondaryTree()) MUI2_remove_style_top_panel_style(obj); else remove_style_top_panel_style(obj); } +#define remove_style_top_panel_style mui_route_remove_style_top_panel_style +static inline lv_style_t &mui_route_style_btn_active(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_style_btn_active : style_btn_active; } +#define style_btn_active (mui_route_style_btn_active()) +static inline lv_style_t &mui_route_style_btn_default(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_style_btn_default : style_btn_default; } +#define style_btn_default (mui_route_style_btn_default()) +static inline lv_style_t &mui_route_style_btn_pressed(void) +{ return ScreenRotation::usesSecondaryTree() ? MUI2_style_btn_pressed : style_btn_pressed; } +#define style_btn_pressed (mui_route_style_btn_pressed()) diff --git a/tools/generated/dual/ui_secondary_rename.h b/tools/generated/dual/ui_secondary_rename.h new file mode 100644 index 00000000..202cc4a0 --- /dev/null +++ b/tools/generated/dual/ui_secondary_rename.h @@ -0,0 +1,203 @@ +// GENERATED by tools/gen_dual_ui.py - do not edit. +// Forced include for the secondary generated tree's sources only. +#pragma once +#include + +#define active_theme_index MUI2_active_theme_index +#define add_style MUI2_add_style +#define add_style_alert_panel_style MUI2_add_style_alert_panel_style +#define add_style_button_matrix_style MUI2_add_style_button_matrix_style +#define add_style_button_panel_style MUI2_add_style_button_panel_style +#define add_style_bw_label_style MUI2_add_style_bw_label_style +#define add_style_channel_button_style MUI2_add_style_channel_button_style +#define add_style_chat_message_style MUI2_add_style_chat_message_style +#define add_style_color_label_style MUI2_add_style_color_label_style +#define add_style_drop_down_style MUI2_add_style_drop_down_style +#define add_style_home_button_style MUI2_add_style_home_button_style +#define add_style_home_container_style MUI2_add_style_home_container_style +#define add_style_main_button_style MUI2_add_style_main_button_style +#define add_style_main_screen_style MUI2_add_style_main_screen_style +#define add_style_map_arrow_style MUI2_add_style_map_arrow_style +#define add_style_new_message_style MUI2_add_style_new_message_style +#define add_style_node_button_style MUI2_add_style_node_button_style +#define add_style_node_panel_style MUI2_add_style_node_panel_style +#define add_style_panel_style MUI2_add_style_panel_style +#define add_style_positive_image_style MUI2_add_style_positive_image_style +#define add_style_settings_button_style MUI2_add_style_settings_button_style +#define add_style_settings_label_style MUI2_add_style_settings_label_style +#define add_style_settings_panel_style MUI2_add_style_settings_panel_style +#define add_style_spinner_style MUI2_add_style_spinner_style +#define add_style_statistics_table_style MUI2_add_style_statistics_table_style +#define add_style_tab_view_style MUI2_add_style_tab_view_style +#define add_style_top_image_style MUI2_add_style_top_image_style +#define add_style_top_panel_style MUI2_add_style_top_panel_style +#define create_screen_blank_screen MUI2_create_screen_blank_screen +#define create_screen_boot_screen MUI2_create_screen_boot_screen +#define create_screen_calibration_screen MUI2_create_screen_calibration_screen +#define create_screen_lock_screen MUI2_create_screen_lock_screen +#define create_screen_main_screen MUI2_create_screen_main_screen +#define create_screens MUI2_create_screens +#define create_tabview_settings MUI2_create_tabview_settings +#define create_user_widget_ok_cancel_widget MUI2_create_user_widget_ok_cancel_widget +#define fonts MUI2_fonts +#define get_style_alert_panel_style_MAIN_DEFAULT MUI2_get_style_alert_panel_style_MAIN_DEFAULT +#define get_style_button_matrix_style_ITEMS_DEFAULT MUI2_get_style_button_matrix_style_ITEMS_DEFAULT +#define get_style_button_matrix_style_MAIN_DEFAULT MUI2_get_style_button_matrix_style_MAIN_DEFAULT +#define get_style_button_panel_style_MAIN_DEFAULT MUI2_get_style_button_panel_style_MAIN_DEFAULT +#define get_style_bw_label_style_MAIN_DEFAULT MUI2_get_style_bw_label_style_MAIN_DEFAULT +#define get_style_channel_button_style_MAIN_DEFAULT MUI2_get_style_channel_button_style_MAIN_DEFAULT +#define get_style_chat_message_style_MAIN_DEFAULT MUI2_get_style_chat_message_style_MAIN_DEFAULT +#define get_style_color_label_style_MAIN_DEFAULT MUI2_get_style_color_label_style_MAIN_DEFAULT +#define get_style_home_button_style_MAIN_DEFAULT MUI2_get_style_home_button_style_MAIN_DEFAULT +#define get_style_home_container_style_MAIN_DEFAULT MUI2_get_style_home_container_style_MAIN_DEFAULT +#define get_style_main_button_style_MAIN_DEFAULT MUI2_get_style_main_button_style_MAIN_DEFAULT +#define get_style_main_screen_style_MAIN_DEFAULT MUI2_get_style_main_screen_style_MAIN_DEFAULT +#define get_style_main_screen_style_MAIN_PRESSED MUI2_get_style_main_screen_style_MAIN_PRESSED +#define get_style_map_arrow_style_MAIN_DEFAULT MUI2_get_style_map_arrow_style_MAIN_DEFAULT +#define get_style_map_arrow_style_MAIN_PRESSED MUI2_get_style_map_arrow_style_MAIN_PRESSED +#define get_style_new_message_style_MAIN_DEFAULT MUI2_get_style_new_message_style_MAIN_DEFAULT +#define get_style_node_button_style_MAIN_DEFAULT MUI2_get_style_node_button_style_MAIN_DEFAULT +#define get_style_node_panel_style_MAIN_DEFAULT MUI2_get_style_node_panel_style_MAIN_DEFAULT +#define get_style_panel_style_MAIN_DEFAULT MUI2_get_style_panel_style_MAIN_DEFAULT +#define get_style_panel_style_MAIN_PRESSED MUI2_get_style_panel_style_MAIN_PRESSED +#define get_style_positive_image_style_MAIN_DEFAULT MUI2_get_style_positive_image_style_MAIN_DEFAULT +#define get_style_settings_button_style_MAIN_DEFAULT MUI2_get_style_settings_button_style_MAIN_DEFAULT +#define get_style_settings_label_style_MAIN_DEFAULT MUI2_get_style_settings_label_style_MAIN_DEFAULT +#define get_style_settings_panel_style_MAIN_DEFAULT MUI2_get_style_settings_panel_style_MAIN_DEFAULT +#define get_style_spinner_style_INDICATOR_DEFAULT MUI2_get_style_spinner_style_INDICATOR_DEFAULT +#define get_style_spinner_style_MAIN_DEFAULT MUI2_get_style_spinner_style_MAIN_DEFAULT +#define get_style_statistics_table_style_ITEMS_DEFAULT MUI2_get_style_statistics_table_style_ITEMS_DEFAULT +#define get_style_statistics_table_style_MAIN_DEFAULT MUI2_get_style_statistics_table_style_MAIN_DEFAULT +#define get_style_tab_view_style_MAIN_DEFAULT MUI2_get_style_tab_view_style_MAIN_DEFAULT +#define get_style_top_image_style_MAIN_DEFAULT MUI2_get_style_top_image_style_MAIN_DEFAULT +#define get_style_top_panel_style_MAIN_DEFAULT MUI2_get_style_top_panel_style_MAIN_DEFAULT +#define images MUI2_images +#define init_style_alert_panel_style_MAIN_DEFAULT MUI2_init_style_alert_panel_style_MAIN_DEFAULT +#define init_style_button_matrix_style_ITEMS_DEFAULT MUI2_init_style_button_matrix_style_ITEMS_DEFAULT +#define init_style_button_matrix_style_MAIN_DEFAULT MUI2_init_style_button_matrix_style_MAIN_DEFAULT +#define init_style_button_panel_style_MAIN_DEFAULT MUI2_init_style_button_panel_style_MAIN_DEFAULT +#define init_style_bw_label_style_MAIN_DEFAULT MUI2_init_style_bw_label_style_MAIN_DEFAULT +#define init_style_channel_button_style_MAIN_DEFAULT MUI2_init_style_channel_button_style_MAIN_DEFAULT +#define init_style_chat_message_style_MAIN_DEFAULT MUI2_init_style_chat_message_style_MAIN_DEFAULT +#define init_style_color_label_style_MAIN_DEFAULT MUI2_init_style_color_label_style_MAIN_DEFAULT +#define init_style_home_button_style_MAIN_DEFAULT MUI2_init_style_home_button_style_MAIN_DEFAULT +#define init_style_home_container_style_MAIN_DEFAULT MUI2_init_style_home_container_style_MAIN_DEFAULT +#define init_style_main_button_style_MAIN_DEFAULT MUI2_init_style_main_button_style_MAIN_DEFAULT +#define init_style_main_screen_style_MAIN_DEFAULT MUI2_init_style_main_screen_style_MAIN_DEFAULT +#define init_style_main_screen_style_MAIN_PRESSED MUI2_init_style_main_screen_style_MAIN_PRESSED +#define init_style_map_arrow_style_MAIN_DEFAULT MUI2_init_style_map_arrow_style_MAIN_DEFAULT +#define init_style_map_arrow_style_MAIN_PRESSED MUI2_init_style_map_arrow_style_MAIN_PRESSED +#define init_style_new_message_style_MAIN_DEFAULT MUI2_init_style_new_message_style_MAIN_DEFAULT +#define init_style_node_button_style_MAIN_DEFAULT MUI2_init_style_node_button_style_MAIN_DEFAULT +#define init_style_node_panel_style_MAIN_DEFAULT MUI2_init_style_node_panel_style_MAIN_DEFAULT +#define init_style_panel_style_MAIN_DEFAULT MUI2_init_style_panel_style_MAIN_DEFAULT +#define init_style_panel_style_MAIN_PRESSED MUI2_init_style_panel_style_MAIN_PRESSED +#define init_style_positive_image_style_MAIN_DEFAULT MUI2_init_style_positive_image_style_MAIN_DEFAULT +#define init_style_settings_button_style_MAIN_DEFAULT MUI2_init_style_settings_button_style_MAIN_DEFAULT +#define init_style_settings_label_style_MAIN_DEFAULT MUI2_init_style_settings_label_style_MAIN_DEFAULT +#define init_style_settings_panel_style_MAIN_DEFAULT MUI2_init_style_settings_panel_style_MAIN_DEFAULT +#define init_style_spinner_style_INDICATOR_DEFAULT MUI2_init_style_spinner_style_INDICATOR_DEFAULT +#define init_style_spinner_style_MAIN_DEFAULT MUI2_init_style_spinner_style_MAIN_DEFAULT +#define init_style_statistics_table_style_ITEMS_DEFAULT MUI2_init_style_statistics_table_style_ITEMS_DEFAULT +#define init_style_statistics_table_style_MAIN_DEFAULT MUI2_init_style_statistics_table_style_MAIN_DEFAULT +#define init_style_tab_view_style_MAIN_DEFAULT MUI2_init_style_tab_view_style_MAIN_DEFAULT +#define init_style_top_image_style_MAIN_DEFAULT MUI2_init_style_top_image_style_MAIN_DEFAULT +#define init_style_top_panel_style_MAIN_DEFAULT MUI2_init_style_top_panel_style_MAIN_DEFAULT +#define loadScreen MUI2_loadScreen +#define objects MUI2_objects +#define remove_style MUI2_remove_style +#define remove_style_alert_panel_style MUI2_remove_style_alert_panel_style +#define remove_style_button_matrix_style MUI2_remove_style_button_matrix_style +#define remove_style_button_panel_style MUI2_remove_style_button_panel_style +#define remove_style_bw_label_style MUI2_remove_style_bw_label_style +#define remove_style_channel_button_style MUI2_remove_style_channel_button_style +#define remove_style_chat_message_style MUI2_remove_style_chat_message_style +#define remove_style_color_label_style MUI2_remove_style_color_label_style +#define remove_style_drop_down_style MUI2_remove_style_drop_down_style +#define remove_style_home_button_style MUI2_remove_style_home_button_style +#define remove_style_home_container_style MUI2_remove_style_home_container_style +#define remove_style_main_button_style MUI2_remove_style_main_button_style +#define remove_style_main_screen_style MUI2_remove_style_main_screen_style +#define remove_style_map_arrow_style MUI2_remove_style_map_arrow_style +#define remove_style_new_message_style MUI2_remove_style_new_message_style +#define remove_style_node_button_style MUI2_remove_style_node_button_style +#define remove_style_node_panel_style MUI2_remove_style_node_panel_style +#define remove_style_panel_style MUI2_remove_style_panel_style +#define remove_style_positive_image_style MUI2_remove_style_positive_image_style +#define remove_style_settings_button_style MUI2_remove_style_settings_button_style +#define remove_style_settings_label_style MUI2_remove_style_settings_label_style +#define remove_style_settings_panel_style MUI2_remove_style_settings_panel_style +#define remove_style_spinner_style MUI2_remove_style_spinner_style +#define remove_style_statistics_table_style MUI2_remove_style_statistics_table_style +#define remove_style_tab_view_style MUI2_remove_style_tab_view_style +#define remove_style_top_image_style MUI2_remove_style_top_image_style +#define remove_style_top_panel_style MUI2_remove_style_top_panel_style +#define style_btn_active MUI2_style_btn_active +#define style_btn_default MUI2_style_btn_default +#define style_btn_pressed MUI2_style_btn_pressed +#define tick_screen MUI2_tick_screen +#define tick_screen_blank_screen MUI2_tick_screen_blank_screen +#define tick_screen_boot_screen MUI2_tick_screen_boot_screen +#define tick_screen_by_id MUI2_tick_screen_by_id +#define tick_screen_calibration_screen MUI2_tick_screen_calibration_screen +#define tick_screen_funcs MUI2_tick_screen_funcs +#define tick_screen_lock_screen MUI2_tick_screen_lock_screen +#define tick_screen_main_screen MUI2_tick_screen_main_screen +#define tick_user_widget_ok_cancel_widget MUI2_tick_user_widget_ok_cancel_widget +#define tick_value_change_obj MUI2_tick_value_change_obj +#define ui_AdvancedSettingsPanel MUI2_ui_AdvancedSettingsPanel +#define ui_AmbientLightingLabel MUI2_ui_AmbientLightingLabel +#define ui_AudioLabel MUI2_ui_AudioLabel +#define ui_AudioLabel1 MUI2_ui_AudioLabel1 +#define ui_BluetoothLabel MUI2_ui_BluetoothLabel +#define ui_CannedMsgLabel MUI2_ui_CannedMsgLabel +#define ui_DetectionSensorLabel MUI2_ui_DetectionSensorLabel +#define ui_DeviceLabel MUI2_ui_DeviceLabel +#define ui_DisplayLabel MUI2_ui_DisplayLabel +#define ui_ExtNotificationLabel MUI2_ui_ExtNotificationLabel +#define ui_GeneralAudioButton MUI2_ui_GeneralAudioButton +#define ui_GeneralLanguageButton MUI2_ui_GeneralLanguageButton +#define ui_GeneralMapsButton MUI2_ui_GeneralMapsButton +#define ui_GeneralScreenButton MUI2_ui_GeneralScreenButton +#define ui_GeneralTimezoneButton MUI2_ui_GeneralTimezoneButton +#define ui_LanguageLabel MUI2_ui_LanguageLabel +#define ui_LoRaLabel MUI2_ui_LoRaLabel +#define ui_MQTTLabel MUI2_ui_MQTTLabel +#define ui_MapsLabel MUI2_ui_MapsLabel +#define ui_ModuleAmbientLightingButton MUI2_ui_ModuleAmbientLightingButton +#define ui_ModuleAudioButton MUI2_ui_ModuleAudioButton +#define ui_ModuleCannedMsgButton MUI2_ui_ModuleCannedMsgButton +#define ui_ModuleDetectionSensorButton MUI2_ui_ModuleDetectionSensorButton +#define ui_ModuleExtNotificationButton MUI2_ui_ModuleExtNotificationButton +#define ui_ModuleMQTTButton MUI2_ui_ModuleMQTTButton +#define ui_ModuleNeighborInfoButton MUI2_ui_ModuleNeighborInfoButton +#define ui_ModuleRangeTestButton MUI2_ui_ModuleRangeTestButton +#define ui_ModuleRemoteHardwareButton MUI2_ui_ModuleRemoteHardwareButton +#define ui_ModuleSaFButton MUI2_ui_ModuleSaFButton +#define ui_ModuleSerialButton MUI2_ui_ModuleSerialButton +#define ui_ModuleTelemetryButton MUI2_ui_ModuleTelemetryButton +#define ui_NeighborInfoLabel MUI2_ui_NeighborInfoLabel +#define ui_NetworkLabel MUI2_ui_NetworkLabel +#define ui_PositionLabel MUI2_ui_PositionLabel +#define ui_PowerLabel MUI2_ui_PowerLabel +#define ui_RadioBluetoothButton MUI2_ui_RadioBluetoothButton +#define ui_RadioDeviceButton MUI2_ui_RadioDeviceButton +#define ui_RadioDisplayButton MUI2_ui_RadioDisplayButton +#define ui_RadioLoRaButton MUI2_ui_RadioLoRaButton +#define ui_RadioNetworkButton MUI2_ui_RadioNetworkButton +#define ui_RadioPositionButton MUI2_ui_RadioPositionButton +#define ui_RadioPowerButton MUI2_ui_RadioPowerButton +#define ui_RangeTestLabel MUI2_ui_RangeTestLabel +#define ui_RemoteHardwareLabel MUI2_ui_RemoteHardwareLabel +#define ui_ScreenLabel MUI2_ui_ScreenLabel +#define ui_SerialLabel MUI2_ui_SerialLabel +#define ui_SettingsTabView MUI2_ui_SettingsTabView +#define ui_StoreAndForwardLabel MUI2_ui_StoreAndForwardLabel +#define ui_TabPageGeneral MUI2_ui_TabPageGeneral +#define ui_TabPageModules MUI2_ui_TabPageModules +#define ui_TabPageRadio MUI2_ui_TabPageRadio +#define ui_TelemetryLabel MUI2_ui_TelemetryLabel +#define ui_TimezoneLabel MUI2_ui_TimezoneLabel +#define ui_init MUI2_ui_init +#define ui_init_boot MUI2_ui_init_boot +#define ui_tick MUI2_ui_tick