diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt index e55e354b5..ca2fd8d74 100644 --- a/radio/src/CMakeLists.txt +++ b/radio/src/CMakeLists.txt @@ -80,6 +80,7 @@ if(PCB STREQUAL HORUS) view_text.cpp screens_setup.cpp theme.cpp + topbar.cpp layout.cpp widget.cpp ${THEMES_SRC} @@ -256,6 +257,7 @@ if(CPU_TYPE STREQUAL STM32F4) include_directories(${STM32LIB_DIR}/STM32F4xx_StdPeriph_Driver/inc) include_directories(${STM32LIB_DIR}/CMSIS/Device/ST/STM32F4xx/Include) include_directories(${STM32LIB_DIR}/CMSIS/include) + # add_definitions(-DSTM32F4) set(STM32LIB_SRC ${STM32LIB_SRC} CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc_ride7/startup_stm32f40_41xxx.s diff --git a/radio/src/audio_arm.cpp b/radio/src/audio_arm.cpp index e5246a63c..b96c60190 100644 --- a/radio/src/audio_arm.cpp +++ b/radio/src/audio_arm.cpp @@ -249,8 +249,6 @@ void referenceSystemAudioFiles() fn = *fno.lfname ? fno.lfname : fno.fname; uint8_t len = strlen(fn); - TRACE("%s", fn); - // Eliminates directories / non wav files if (len < 5 || strcasecmp(fn+len-4, SOUNDS_EXT) || (fno.fattrib & AM_DIR)) continue; @@ -509,7 +507,7 @@ void audioTask(void * pdata) AUDIO_TADA(); #elif defined(SDCARD) if (!unexpectedShutdown) { - sdInit(); + // sdInit(); AUDIO_TADA(); } #endif diff --git a/radio/src/bitmaps/horus/alpha_sleep.png b/radio/src/bitmaps/horus/alpha_sleep.png deleted file mode 100644 index ee8b30216..000000000 Binary files a/radio/src/bitmaps/horus/alpha_sleep.png and /dev/null differ diff --git a/radio/src/bitmaps/horus/bmp_asterisk.png b/radio/src/bitmaps/horus/bmp_asterisk.png new file mode 100644 index 000000000..1e12a2492 Binary files /dev/null and b/radio/src/bitmaps/horus/bmp_asterisk.png differ diff --git a/radio/src/bitmaps/horus/bmp_sleep.png b/radio/src/bitmaps/horus/bmp_sleep.png new file mode 100644 index 000000000..70e163272 Binary files /dev/null and b/radio/src/bitmaps/horus/bmp_sleep.png differ diff --git a/radio/src/gui/horus/bitmaps.cpp b/radio/src/gui/horus/bitmaps.cpp index 6aaa1fccc..3bf6fe79b 100644 --- a/radio/src/gui/horus/bitmaps.cpp +++ b/radio/src/gui/horus/bitmaps.cpp @@ -204,22 +204,36 @@ const uint8_t LBM_MAINVIEWS_TOPBAR_ICON[] = { #include "mask_mainviews_topbar.lbm" }; -const uint8_t LBM_MAINVIEWS_ITEM_OUT_ICON[] = { -#include "mask_mainviews_item_out.lbm" +const uint8_t LBM_MAINVIEWS_1_ICON[] = { +#include "mask_mainviews_1.lbm" +}; + +const uint8_t LBM_MAINVIEWS_2_ICON[] = { +#include "mask_mainviews_2.lbm" +}; + +const uint8_t LBM_MAINVIEWS_3_ICON[] = { +#include "mask_mainviews_3.lbm" +}; + +const uint8_t LBM_MAINVIEWS_4_ICON[] = { +#include "mask_mainviews_4.lbm" +}; + +const uint8_t LBM_MAINVIEWS_5_ICON[] = { +#include "mask_mainviews_5.lbm" }; const uint8_t LBM_MAINVIEWS_ADD_ICON[] = { #include "mask_mainviews_add.lbm" }; -const uint8_t * LBM_MAINVIEWS_ICONS[] = { - LBM_MAINVIEWS_ICON, - LBM_MAINVIEWS_TOPBAR_ICON, - LBM_MAINVIEWS_ITEM_OUT_ICON, - LBM_MAINVIEWS_ITEM_OUT_ICON, - LBM_MAINVIEWS_ITEM_OUT_ICON, - LBM_MAINVIEWS_ITEM_OUT_ICON, - LBM_MAINVIEWS_ITEM_OUT_ICON +const uint8_t * const LBM_MAINVIEWS_ICONS[] = { + LBM_MAINVIEWS_1_ICON, + LBM_MAINVIEWS_2_ICON, + LBM_MAINVIEWS_3_ICON, + LBM_MAINVIEWS_4_ICON, + LBM_MAINVIEWS_5_ICON }; /* @@ -299,7 +313,7 @@ const uint8_t LBM_SHUTDOWN[] __DMA = { }; const uint8_t LBM_SLEEP[] __DMA = { -#include "alpha_sleep.lbm" +#include "bmp_sleep.lbm" }; const uint8_t LBM_SHUTDOWN_CIRCLE[] __DMA = { @@ -346,7 +360,7 @@ const uint8_t LBM_SWIPE_CIRCLE[] __DMA = { #include "mask_swipe_circle.lbm" }; -const uint8_t LBM_SWIPE_LEFT[] __DMA = { +const uint8_t LBM_SWIPE_LEFT[] __DMA = { #include "mask_swipe_left.lbm" }; diff --git a/radio/src/gui/horus/bitmaps.h b/radio/src/gui/horus/bitmaps.h index c48f6506e..bcb4d9f25 100644 --- a/radio/src/gui/horus/bitmaps.h +++ b/radio/src/gui/horus/bitmaps.h @@ -53,9 +53,8 @@ extern const uint8_t LBM_TELEMETRY_ICON[]; // UI (theme / layout / widgets bitmaps extern const uint8_t LBM_MAINVIEWS_ICON[]; extern const uint8_t LBM_MAINVIEWS_TOPBAR_ICON[]; -extern const uint8_t LBM_MAINVIEWS_ITEM_OUT_ICON[]; extern const uint8_t LBM_MAINVIEWS_ADD_ICON[]; -extern const uint8_t * LBM_MAINVIEWS_ICONS[]; +extern const uint8_t * const LBM_MAINVIEWS_ICONS[]; // Model selection icons extern const uint8_t LBM_LIBRARY_ICON[]; diff --git a/radio/src/gui/horus/gui.h b/radio/src/gui/horus/gui.h index 703bef4bc..23b7c2c87 100644 --- a/radio/src/gui/horus/gui.h +++ b/radio/src/gui/horus/gui.h @@ -81,5 +81,5 @@ void drawCurveHorizontalScale(); void drawCurveCoord(int x, int y, const char * text, bool active=false); void drawCurvePoint(int x, int y, LcdFlags color); -// TODO one screen for now extern Layout * customScreens[MAX_CUSTOM_SCREENS]; +extern Topbar * topbar; diff --git a/radio/src/gui/horus/layout.cpp b/radio/src/gui/horus/layout.cpp index d7d1b596a..45216948e 100644 --- a/radio/src/gui/horus/layout.cpp +++ b/radio/src/gui/horus/layout.cpp @@ -20,40 +20,12 @@ #include "opentx.h" -void Layout::createWidget(unsigned int index, const WidgetFactory * factory) -{ - memset(persistentData->zones[index].widgetName, 0, sizeof(persistentData->zones[index].widgetName)); - strncpy(persistentData->zones[index].widgetName, factory->getName(), sizeof(persistentData->zones[index].widgetName)); - widgets[index] = factory->create(getZone(index), &persistentData->zones[index].widgetData); -} - -void Layout::load() -{ - unsigned int count = getZonesCount(); - for (unsigned int i=0; izones[i].widgetName[0]) { - char name[sizeof(persistentData->zones[i].widgetName)+1]; - memset(name, 0, sizeof(name)); - strncpy(name, persistentData->zones[i].widgetName, sizeof(persistentData->zones[i].widgetName)); - widgets[i] = loadWidget(name, getZone(i), &persistentData->zones[i].widgetData); - } - } -} - -void Layout::refresh(bool setup) -{ - for (int i = 0; i < MAX_LAYOUT_ZONES; i++) { - if (widgets[i]) { - widgets[i]->refresh(); - } - } -} - const LayoutFactory * registeredLayouts[MAX_REGISTERED_LAYOUTS]; // TODO dynamic unsigned int countRegisteredLayouts = 0; void registerLayout(const LayoutFactory * factory) { if (countRegisteredLayouts < MAX_REGISTERED_LAYOUTS) { + TRACE("register layout %s", factory->getName()); registeredLayouts[countRegisteredLayouts++] = factory; } } @@ -90,4 +62,6 @@ void loadCustomScreens() if (customScreens[0] == NULL) { customScreens[0] = registeredLayouts[0]->create(&g_model.screenData[0].layoutData); } + + topbar->load(); } diff --git a/radio/src/gui/horus/layout.h b/radio/src/gui/horus/layout.h index 147586c1e..eb2e3e675 100644 --- a/radio/src/gui/horus/layout.h +++ b/radio/src/gui/horus/layout.h @@ -21,86 +21,31 @@ #ifndef _LAYOUT_H_ #define _LAYOUT_H_ -#include "widget.h" +#include "widgets_container.h" #define MAX_LAYOUT_ZONES 10 #define MAX_LAYOUT_OPTIONS 10 class LayoutFactory; -class Layout + +class Layout: public WidgetsContainer { friend class LayoutFactory; - public: - struct ZonePersistentData { - char widgetName[10]; - Widget::PersistentData widgetData; - }; - - struct PersistentData { - ZonePersistentData zones[MAX_LAYOUT_ZONES]; - ZoneOptionValue options[MAX_LAYOUT_OPTIONS]; - }; - public: Layout(const LayoutFactory * factory, PersistentData * persistentData): - factory(factory), - persistentData(persistentData) + WidgetsContainer(persistentData), + factory(factory) { - memset(widgets, 0, sizeof(widgets)); } - virtual ~Layout() - { - for (uint8_t i=0; ioptions[index]; - } - - void setOptionValue(unsigned int index, ZoneOptionValue value) const - { - persistentData->options[index] = value; - } - - virtual unsigned int getZonesCount() const = 0; - virtual Zone getZone(unsigned int index) const = 0; - - virtual void refresh(bool setup=false); - protected: const LayoutFactory * factory; - Widget * widgets[MAX_LAYOUT_ZONES]; - PersistentData * persistentData; }; void registerLayout(const LayoutFactory * factory); diff --git a/radio/src/gui/horus/layouts/layout1x1.cpp b/radio/src/gui/horus/layouts/layout1x1.cpp index 525b0f946..a83abc269 100644 --- a/radio/src/gui/horus/layouts/layout1x1.cpp +++ b/radio/src/gui/horus/layouts/layout1x1.cpp @@ -20,6 +20,16 @@ #include "opentx.h" +const uint8_t LBM_LAYOUT_1x1[] = { +#include "mask_layout1x1.lbm" +}; + +const ZoneOption OPTIONS_LAYOUT_1x1[] = { + { "Top bar", ZoneOption::Bool }, + { "Sliders+Trims", ZoneOption::Bool }, + { NULL, ZoneOption::Bool } +}; + class Layout1x1: public Layout { public: @@ -55,25 +65,15 @@ class Layout1x1: public Layout return zone; } - virtual void refresh(bool setup=false); - - static const ZoneOption options[]; - + virtual void refresh(); }; -const ZoneOption Layout1x1::options[] = { - { "Top bar", ZoneOption::Bool }, - { "Sliders+Trims", ZoneOption::Bool }, - { NULL, ZoneOption::Bool } -}; - -void Layout1x1::refresh(bool setup) +void Layout1x1::refresh() { theme->drawBackground(); if (persistentData->options[0].boolValue) { - // Top Bar - drawMainViewTopBar(); + drawTopBar(); } if (persistentData->options[1].boolValue) { @@ -86,11 +86,7 @@ void Layout1x1::refresh(bool setup) drawTrims(mixerCurrentFlightMode); } - Layout::refresh(setup); + Layout::refresh(); } -const uint8_t LBM_LAYOUT_1x1[] __DMA = { -#include "mask_layout1x1.lbm" -}; - -BaseLayoutFactory layout1x1("Layout1x1", LBM_LAYOUT_1x1, Layout1x1::options); +BaseLayoutFactory layout1x1("Layout1x1", LBM_LAYOUT_1x1, OPTIONS_LAYOUT_1x1); diff --git a/radio/src/gui/horus/layouts/layout2+1.cpp b/radio/src/gui/horus/layouts/layout2+1.cpp index 625140894..039ee2a90 100644 --- a/radio/src/gui/horus/layouts/layout2+1.cpp +++ b/radio/src/gui/horus/layouts/layout2+1.cpp @@ -20,6 +20,24 @@ #include "opentx.h" +const uint8_t LBM_LAYOUT_2P1[] = { +#include "mask_layout2+1.lbm" +}; + +const ZoneOption OPTIONS_LAYOUT_2P1[] = { + { "Top bar", ZoneOption::Bool }, + { "Flight mode", ZoneOption::Bool }, + { "Sliders", ZoneOption::Bool }, + { "Trims", ZoneOption::Bool }, + { NULL, ZoneOption::Bool } +}; + +const Zone ZONES_LAYOUT_2P1[3] = { + { 240, 60, 192, 152 }, + { 48, 60, 180, 70 }, + { 48, 142, 180, 70 } +}; + class Layout2P1: public Layout { public: @@ -39,43 +57,23 @@ class Layout2P1: public Layout virtual unsigned int getZonesCount() const { - return 3; + return DIM(ZONES_LAYOUT_2P1); } virtual Zone getZone(unsigned int index) const { - return zones[index]; + return ZONES_LAYOUT_2P1[index]; } - virtual void refresh(bool setup=false); - - static const ZoneOption options[]; - - protected: - static const Zone zones[3]; + virtual void refresh(); }; -const Zone Layout2P1::zones[3] = { - { 240, 60, 192, 145 }, - { 46, 60, 182, 66 }, - { 46, 139, 182, 66 } -}; - -const ZoneOption Layout2P1::options[] = { - { "Top bar", ZoneOption::Bool }, - { "Flight mode", ZoneOption::Bool }, - { "Sliders", ZoneOption::Bool }, - { "Trims", ZoneOption::Bool }, - { NULL, ZoneOption::Bool } -}; - -void Layout2P1::refresh(bool setup) +void Layout2P1::refresh() { theme->drawBackground(); if (persistentData->options[0].boolValue) { - // Top Bar - drawMainViewTopBar(); + drawTopBar(); } if (persistentData->options[1].boolValue) { @@ -98,11 +96,7 @@ void Layout2P1::refresh(bool setup) drawTrims(mixerCurrentFlightMode); } - Layout::refresh(setup); + Layout::refresh(); } -const uint8_t LBM_LAYOUT_2P1[] __DMA = { -#include "mask_layout2+1.lbm" -}; - -BaseLayoutFactory layout2P1("Layout2P1", LBM_LAYOUT_2P1, Layout2P1::options); +BaseLayoutFactory layout2P1("Layout2P1", LBM_LAYOUT_2P1, OPTIONS_LAYOUT_2P1); diff --git a/radio/src/gui/horus/layouts/layout2x1.cpp b/radio/src/gui/horus/layouts/layout2x1.cpp index b7433f63e..a96fc7006 100644 --- a/radio/src/gui/horus/layouts/layout2x1.cpp +++ b/radio/src/gui/horus/layouts/layout2x1.cpp @@ -20,6 +20,15 @@ #include "opentx.h" +const uint8_t LBM_LAYOUT_2x1[] = { +#include "mask_layout2x1.lbm" +}; + +const ZoneOption OPTIONS_LAYOUT_2x1[] = { + { "Top bar", ZoneOption::Bool }, + { NULL, ZoneOption::Bool } +}; + class Layout2x1: public Layout { public: @@ -55,31 +64,18 @@ class Layout2x1: public Layout return zone; } - virtual void refresh(bool setup=false); - - static const ZoneOption options[]; - + virtual void refresh(); }; -const ZoneOption Layout2x1::options[] = { - { "Top bar", ZoneOption::Bool }, - { NULL, ZoneOption::Bool } -}; - -void Layout2x1::refresh(bool setup) +void Layout2x1::refresh() { theme->drawBackground(); if (persistentData->options[0].boolValue) { - // Top Bar - drawMainViewTopBar(); + drawTopBar(); } - Layout::refresh(setup); + Layout::refresh(); } -const uint8_t LBM_LAYOUT_2x1[] __DMA = { -#include "mask_layout2x1.lbm" -}; - -BaseLayoutFactory Layout2x1("Layout2x1", LBM_LAYOUT_2x1, Layout2x1::options); +BaseLayoutFactory Layout2x1("Layout2x1", LBM_LAYOUT_2x1, OPTIONS_LAYOUT_2x1); diff --git a/radio/src/gui/horus/layouts/layout2x2.cpp b/radio/src/gui/horus/layouts/layout2x2.cpp index b10c55e64..0efa2df62 100644 --- a/radio/src/gui/horus/layouts/layout2x2.cpp +++ b/radio/src/gui/horus/layouts/layout2x2.cpp @@ -20,6 +20,15 @@ #include "opentx.h" +const uint8_t LBM_LAYOUT_2x2[] = { +#include "mask_layout2x2.lbm" +}; + +const ZoneOption OPTIONS_LAYOUT_2x2[] = { + { "Top bar", ZoneOption::Bool }, + { NULL, ZoneOption::Bool } +}; + class Layout2x2: public Layout { public: @@ -58,31 +67,18 @@ class Layout2x2: public Layout return zone; } - virtual void refresh(bool setup=false); - - static const ZoneOption options[]; - + virtual void refresh(); }; -const ZoneOption Layout2x2::options[] = { - { "Top bar", ZoneOption::Bool }, - { NULL, ZoneOption::Bool } -}; - -void Layout2x2::refresh(bool setup) +void Layout2x2::refresh() { theme->drawBackground(); if (persistentData->options[0].boolValue) { - // Top Bar - drawMainViewTopBar(); + drawTopBar(); } - Layout::refresh(setup); + Layout::refresh(); } -const uint8_t LBM_LAYOUT_2x2[] __DMA = { -#include "mask_layout2x2.lbm" -}; - -BaseLayoutFactory layout2x2("Layout2x2", LBM_LAYOUT_2x2, Layout2x2::options); +BaseLayoutFactory layout2x2("Layout2x2", LBM_LAYOUT_2x2, OPTIONS_LAYOUT_2x2); diff --git a/radio/src/gui/horus/layouts/layout2x4.cpp b/radio/src/gui/horus/layouts/layout2x4.cpp index 1c6f441a2..b5bd79861 100644 --- a/radio/src/gui/horus/layouts/layout2x4.cpp +++ b/radio/src/gui/horus/layouts/layout2x4.cpp @@ -20,6 +20,22 @@ #include "opentx.h" +const uint8_t LBM_LAYOUT_2x4[] = { +#include "mask_layout2x4.lbm" +}; + +const ZoneOption OPTIONS_LAYOUT_2x4[] = { + { "Top bar", ZoneOption::Bool }, + { "Flight mode", ZoneOption::Bool }, + { "Sliders", ZoneOption::Bool }, + { "Trims", ZoneOption::Bool }, + { "Panel1 background", ZoneOption::Bool }, + { " Color", ZoneOption::Color }, + { "Panel2 background", ZoneOption::Bool }, + { " Color", ZoneOption::Color }, + { NULL, ZoneOption::Bool } +}; + class Layout2x4: public Layout { public: @@ -56,31 +72,15 @@ class Layout2x4: public Layout return zone; } - virtual void refresh(bool setup=false); - - static const ZoneOption options[]; - + virtual void refresh(); }; -const ZoneOption Layout2x4::options[] = { - { "Top bar", ZoneOption::Bool }, - { "Flight mode", ZoneOption::Bool }, - { "Sliders", ZoneOption::Bool }, - { "Trims", ZoneOption::Bool }, - { "Panel1 background", ZoneOption::Bool }, - { " Color", ZoneOption::Color }, - { "Panel2 background", ZoneOption::Bool }, - { " Color", ZoneOption::Color }, - { NULL, ZoneOption::Bool } -}; - -void Layout2x4::refresh(bool setup) +void Layout2x4::refresh() { theme->drawBackground(); if (persistentData->options[0].boolValue) { - // Top Bar - drawMainViewTopBar(); + drawTopBar(); } if (persistentData->options[1].boolValue) { @@ -113,11 +113,7 @@ void Layout2x4::refresh(bool setup) lcdDrawSolidFilledRect(250, 50, 180, 170, CUSTOM_COLOR); } - Layout::refresh(setup); + Layout::refresh(); } -const uint8_t LBM_LAYOUT_2x4[] __DMA = { -#include "mask_layout2x4.lbm" -}; - -BaseLayoutFactory layout2x4("Layout2x4", LBM_LAYOUT_2x4, Layout2x4::options); +BaseLayoutFactory layout2x4("Layout2x4", LBM_LAYOUT_2x4, OPTIONS_LAYOUT_2x4); diff --git a/radio/src/gui/horus/lcd.cpp b/radio/src/gui/horus/lcd.cpp index 69c39b261..46cb8382d 100644 --- a/radio/src/gui/horus/lcd.cpp +++ b/radio/src/gui/horus/lcd.cpp @@ -109,24 +109,17 @@ int getFontHeight(LcdFlags flags) return heightTable[FONTSIZE(flags) >> 8]; } -int getBitmapScale(const uint8_t * bmp, int dstWidth, int dstHeight) +float getBitmapScale(const uint8_t * bmp, int dstWidth, int dstHeight) { - int widthScale, heightScale; - int bmpWidth = getBitmapWidth(bmp); int bmpHeight = getBitmapHeight(bmp); if (bmpWidth == 0 || bmpHeight == 0) return 0; - if (bmpWidth > dstWidth) - widthScale = -((bmpWidth+dstWidth-1) / dstWidth); - else - widthScale = (dstWidth / bmpWidth); - if (bmpHeight > dstHeight) - heightScale = -((bmpHeight+dstHeight-1) / dstHeight); - else - heightScale = (dstHeight / bmpHeight); + float widthScale = float(dstWidth) / bmpWidth; + float heightScale = float(dstHeight) / bmpHeight; + return min(widthScale, heightScale); } @@ -882,7 +875,7 @@ void lcdDrawVerticalLine(coord_t x, coord_t y, coord_t h, uint8_t pat, LcdFlags #if defined(SIMU) inline void lcdDrawBitmapDMA(coord_t x, coord_t y, coord_t width, coord_t height, const uint8_t * img) { - lcdDrawBitmap(x, y, img-4, 0, 0, -1); + lcdDrawBitmap(x, y, img-4, 0, 0, 1.0); } #endif @@ -906,7 +899,7 @@ void lcdDrawAlphaBitmap(coord_t x, coord_t y, const uint8_t * bmp) } } -void lcdDrawBitmap(coord_t x, coord_t y, const uint8_t * bmp, coord_t offset, coord_t height, int scale) +void lcdDrawBitmap(coord_t x, coord_t y, const uint8_t * bmp, coord_t offset, coord_t height, float scale) { int width = getBitmapWidth(bmp); int h = getBitmapHeight(bmp); @@ -926,28 +919,16 @@ void lcdDrawBitmap(coord_t x, coord_t y, const uint8_t * bmp, coord_t offset, co if (scale == 0) { lcdDrawBitmapDMA(x, y, width, height, bmp + 4 + offset * width * 2); } - else if (scale < 0) { - for (coord_t i=0, row=0; row= -1 && scale <= 1) + if (scale == 0.0) return size; - else if (scale < 0) - return -(size / scale); else return size * scale; } -int getBitmapScale(const uint8_t * bmp, int dstWidth, int dstHeight); +float getBitmapScale(const uint8_t * bmp, int dstWidth, int dstHeight); int getTextWidth(const pm_char *s, int len=0, LcdFlags flags=0); -void lcdDrawBitmap(coord_t x, coord_t y, const uint8_t * img, coord_t offset=0, coord_t height=0, int scale=0); +void lcdDrawBitmap(coord_t x, coord_t y, const uint8_t * img, coord_t offset=0, coord_t height=0, float scale=0); void lcdDrawBitmapPattern(coord_t x, coord_t y, const uint8_t * img, LcdFlags flags=0, coord_t offset=0, coord_t width=0); void lcdDrawAlphaBitmap(coord_t x, coord_t y, const uint8_t * bmp); diff --git a/radio/src/gui/horus/menu_model_custom_functions.cpp b/radio/src/gui/horus/menu_model_custom_functions.cpp index 46b7997eb..ebda017f3 100644 --- a/radio/src/gui/horus/menu_model_custom_functions.cpp +++ b/radio/src/gui/horus/menu_model_custom_functions.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -27,7 +27,7 @@ #define MODEL_CUSTOM_FUNC_4TH_COLUMN 440 #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF 450 -void onCustomFunctionsFileSelectionMenu(const char *result) +void onCustomFunctionsFileSelectionMenu(const char * result) { int sub = menuVerticalPosition; CustomFunctionData * cf = &g_model.customFn[sub]; diff --git a/radio/src/gui/horus/menu_model_setup.cpp b/radio/src/gui/horus/menu_model_setup.cpp index 06d726d86..5b895d1e5 100644 --- a/radio/src/gui/horus/menu_model_setup.cpp +++ b/radio/src/gui/horus/menu_model_setup.cpp @@ -544,9 +544,9 @@ bool menuModelSetup(evt_t event) lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODE); lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_TARANIS_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].type, (menuHorizontalPosition==0 ? attr : 0)); if (IS_MODULE_XJT(EXTERNAL_MODULE)) - lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+40, y, STR_XJT_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, (menuHorizontalPosition==1 ? attr : 0)); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+70, y, STR_XJT_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, (menuHorizontalPosition==1 ? attr : 0)); else if (IS_MODULE_DSM2(EXTERNAL_MODULE)) - lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+40, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, (menuHorizontalPosition==1 ? attr : 0)); + lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+70, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, (menuHorizontalPosition==1 ? attr : 0)); if (attr && s_editMode>0) { switch (menuHorizontalPosition) { case 0: @@ -672,7 +672,9 @@ bool menuModelSetup(evt_t event) lcdDrawText(MENUS_MARGIN_LEFT, y, TR_FAILSAFE); if (IS_MODULE_XJT(moduleIdx)) { lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VFAILSAFE, moduleData.failsafeMode, menuHorizontalPosition==0 ? attr : 0); - if (moduleData.failsafeMode == FAILSAFE_CUSTOM) lcdDrawText(MODEL_SETUP_2ND_COLUMN + MODEL_SETUP_SET_FAILSAFE_OFS, y, STR_SET, menuHorizontalPosition==1 ? attr : 0); + if (moduleData.failsafeMode == FAILSAFE_CUSTOM) { + drawButton(MODEL_SETUP_2ND_COLUMN + MODEL_SETUP_SET_FAILSAFE_OFS, y, STR_SET, menuHorizontalPosition==1 ? attr : 0); + } if (attr) { if (moduleData.failsafeMode != FAILSAFE_CUSTOM) menuHorizontalPosition = 0; @@ -700,7 +702,7 @@ bool menuModelSetup(evt_t event) } if (IS_RANGECHECK_ENABLE()) { - displayPopup("RSSI :"); + theme->drawMessageBox("RSSI :", NULL, NULL, 0); lcdDrawNumber(WARNING_LINE_X, WARNING_INFOLINE_Y, TELEMETRY_RSSI(), DBLSIZE|LEFT); } diff --git a/radio/src/gui/horus/menus.h b/radio/src/gui/horus/menus.h index 73c85bf94..cc6860b5e 100644 --- a/radio/src/gui/horus/menus.h +++ b/radio/src/gui/horus/menus.h @@ -144,7 +144,7 @@ static const MenuHandlerFunc menuTabGeneral[] PROGMEM = { menuGeneralVersion, }; -extern MenuHandlerFunc menuTabMainviews[1+MAX_CUSTOM_SCREENS]; +extern const MenuHandlerFunc menuTabScreensSetup[1+MAX_CUSTOM_SCREENS] PROGMEM; bool menuFirstCalib(evt_t event); bool menuMainView(evt_t event); @@ -274,10 +274,13 @@ bool check_submenu_simple(check_event_t event, uint8_t maxrow); #define MENU(title, icons, tab, menu, lines_count, ...) \ MENU_WITH_OPTIONS(title, icons, tab, DIM(tab), menu, lines_count, __VA_ARGS__) -#define SIMPLE_MENU(title, icons, tab, menu, lines_count) \ +#define SIMPLE_MENU_WITH_OPTIONS(title, icons, tab, tabCount, menu, lines_count) \ if (event == EVT_ENTRY || event == EVT_ENTRY_UP) TRACE("Menu %s displayed ...", title); \ - if (!check_simple(event, menu, tab, DIM(tab), lines_count)) return false; \ - drawMenuTemplate(title, icons); \ + if (!check_simple(event, menu, tab, tabCount, lines_count)) return false; \ + drawMenuTemplate(title, icons); + +#define SIMPLE_MENU(title, icons, tab, menu, lines_count) \ + SIMPLE_MENU_WITH_OPTIONS(title, icons, tab, DIM(tab), menu, lines_count) #define SUBMENU(title, icon, lines_count, ...) \ MENU_TAB(__VA_ARGS__); \ diff --git a/radio/src/gui/horus/popups.cpp b/radio/src/gui/horus/popups.cpp index 08bf862a8..ca7fd331b 100644 --- a/radio/src/gui/horus/popups.cpp +++ b/radio/src/gui/horus/popups.cpp @@ -53,7 +53,7 @@ void displayMessageBox() void drawAlertBox(const char * title, const char * text, const char * action) { - theme->drawAlertBox(title, text, action); + theme->drawMessageBox(title, text, action, MESSAGEBOX_TYPE_ALERT); } void message(const pm_char * title, const pm_char * text, const char * action, uint8_t sound) diff --git a/radio/src/gui/horus/screens_setup.cpp b/radio/src/gui/horus/screens_setup.cpp index 397ad0824..c0d8dab15 100644 --- a/radio/src/gui/horus/screens_setup.cpp +++ b/radio/src/gui/horus/screens_setup.cpp @@ -20,66 +20,120 @@ #include "opentx.h" +const uint8_t * LBM_SCREENS_SETUP_ICONS[] = { + LBM_MAINVIEWS_ICON, + LBM_MAINVIEWS_TOPBAR_ICON, + LBM_MAINVIEWS_ICONS[0], + LBM_MAINVIEWS_ICONS[1], + LBM_MAINVIEWS_ICONS[2], + LBM_MAINVIEWS_ICONS[3], + LBM_MAINVIEWS_ICONS[4] +}; + Layout * currentScreen; +WidgetsContainerInterface * currentContainer; Widget * currentWidget; uint8_t currentZone; #define SCREENS_SETUP_2ND_COLUMN 200 -ZoneOptionValue editZoneOption(coord_t y, const ZoneOption * option, ZoneOptionValue value, LcdFlags attr, evt_t event) +char fileSelection[sizeof(ZoneOptionValue::stringValue)]; +uint8_t fileSelectionDone; + +int updateMainviewsMenu(); +bool menuScreenAdd(evt_t event); +void onScreenSetupMenu(const char * result); + +void onZoneOptionFileSelectionMenu(const char * result) +{ + if (result == STR_UPDATE_LIST) { + if (!sdListFiles(BITMAPS_PATH, BITMAPS_EXT, sizeof(ZoneOptionValue::stringValue), NULL)) { + POPUP_WARNING(STR_NO_BITMAPS_ON_SD); + } + } + else { + fileSelectionDone = true; + memcpy(fileSelection, result, sizeof(fileSelection)); + } +} + +void editZoneOption(coord_t y, const ZoneOption * option, ZoneOptionValue * value, LcdFlags attr, uint32_t i_flags, evt_t event) { lcdDrawText(MENUS_MARGIN_LEFT, y, option->name); if (option->type == ZoneOption::Bool) { - value.boolValue = editCheckBox(value.boolValue, SCREENS_SETUP_2ND_COLUMN, y, attr, event); + value->boolValue = editCheckBox(value->boolValue, SCREENS_SETUP_2ND_COLUMN, y, attr, event); // TODO always does storageDirty(EE_MODEL) } else if (option->type == ZoneOption::Integer) { - lcdDrawNumber(SCREENS_SETUP_2ND_COLUMN, y, value.signedValue, attr | LEFT); + lcdDrawNumber(SCREENS_SETUP_2ND_COLUMN, y, value->signedValue, attr | LEFT); if (attr) { - CHECK_INCDEC_MODELVAR(event, value.signedValue, -30000, 30000); + CHECK_INCDEC_MODELVAR(event, value->signedValue, -30000, 30000); // TODO i_flags } } else if (option->type == ZoneOption::String) { - editName(SCREENS_SETUP_2ND_COLUMN, y, value.stringValue, sizeof(value.stringValue), event, attr); + editName(SCREENS_SETUP_2ND_COLUMN, y, value->stringValue, sizeof(value->stringValue), event, attr); // TODO i_flags? + } + else if (option->type == ZoneOption::File) { + if (ZEXIST(value->stringValue)) + lcdDrawSizedText(SCREENS_SETUP_2ND_COLUMN, y, value->stringValue, sizeof(value->stringValue), attr); + else + lcdDrawTextAtIndex(SCREENS_SETUP_2ND_COLUMN, y, STR_VCSWFUNC, 0, attr); // TODO define + if (attr) { + if (event==EVT_KEY_BREAK(KEY_ENTER)) { + s_editMode = 0; + if (sdListFiles(BITMAPS_PATH, BITMAPS_EXT, sizeof(value->stringValue), value->stringValue, LIST_NONE_SD_FILE)) { + fileSelectionDone = false; + popupMenuHandler = onZoneOptionFileSelectionMenu; + } + else { + POPUP_WARNING(STR_NO_BITMAPS_ON_SD); + } + } + else if (fileSelectionDone) { + memcpy(value->stringValue, fileSelection, sizeof(fileSelection)); + fileSelectionDone = false; + storageDirty(i_flags); + } + } } else if (option->type == ZoneOption::TextSize) { - lcdDrawTextAtIndex(SCREENS_SETUP_2ND_COLUMN, y, "\010StandardTiny\0 Small\0 Mid\0 Double", value.unsignedValue, attr); + lcdDrawTextAtIndex(SCREENS_SETUP_2ND_COLUMN, y, "\010StandardTiny\0 Small\0 Mid\0 Double", value->unsignedValue, attr); if (attr) { - value.unsignedValue = checkIncDec(event, value.unsignedValue, 0, 4, EE_MODEL); + value->unsignedValue = checkIncDec(event, value->unsignedValue, 0, 4, i_flags); } } else if (option->type == ZoneOption::Timer) { - drawStringWithIndex(SCREENS_SETUP_2ND_COLUMN, y, STR_TIMER, value.unsignedValue + 1, attr); + drawStringWithIndex(SCREENS_SETUP_2ND_COLUMN, y, STR_TIMER, value->unsignedValue + 1, attr); if (attr) { - value.unsignedValue = checkIncDec(event, value.unsignedValue, 0, MAX_TIMERS - 1, EE_MODEL); + value->unsignedValue = checkIncDec(event, value->unsignedValue, 0, MAX_TIMERS - 1, i_flags); } } else if (option->type == ZoneOption::Source) { - putsMixerSource(SCREENS_SETUP_2ND_COLUMN, y, value.unsignedValue, attr); + putsMixerSource(SCREENS_SETUP_2ND_COLUMN, y, value->unsignedValue, attr); if (attr) { - CHECK_INCDEC_MODELSOURCE(event, value.unsignedValue, 1, MIXSRC_LAST); + CHECK_INCDEC_MODELSOURCE(event, value->unsignedValue, 1, MIXSRC_LAST); } } else if (option->type == ZoneOption::Color) { - lcdSetColor(value.unsignedValue); + lcdSetColor(value->unsignedValue); lcdDrawSolidRect(SCREENS_SETUP_2ND_COLUMN, y, 40, 15, 1, attr ? TEXT_INVERTED_BGCOLOR : TEXT_COLOR); lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN + 1, y + 1, 38, 13, CUSTOM_COLOR); if (attr) { - CHECK_INCDEC_MODELVAR(event, value.unsignedValue, 0, 65535); + value->unsignedValue = checkIncDec(event, value->unsignedValue, i_flags, 65535, 0); } } - return value; } -bool menuWidgetSettings(evt_t event) +template +bool menuSettings(const char * title, const T * object, uint32_t i_flags, evt_t event) { linesCount = 0; - const ZoneOption * options = currentWidget->getFactory()->getOptions(); + const ZoneOption * options = object->getOptions(); for (const ZoneOption * option = options; option->name; option++) { linesCount++; } - SUBMENU_WITH_OPTIONS("Widget settings", LBM_MAINVIEWS_ICON, linesCount, OPTION_MENU_TITLE_BAR, { 0, 0, 0 }); + SUBMENU_WITH_OPTIONS(title, LBM_MAINVIEWS_ICON, linesCount, OPTION_MENU_TITLE_BAR, { 0, 0, 0 }); for (int i=0; igetOptionValue(k); - value = editZoneOption(y, option, value, attr, event); - if (attr) { - currentWidget->setOptionValue(k, value); - } + ZoneOptionValue * value = object->getOptionValue(k); + editZoneOption(y, option, value, attr, i_flags, event); } } return true; } +bool menuWidgetSettings(evt_t event) +{ + return menuSettings("Widget settings", currentWidget, EE_MODEL, event); +} + +bool menuThemeSettings(evt_t event) +{ + return menuSettings("Theme settings", theme, EE_GENERAL, event); +} + bool menuWidgetChoice(evt_t event) { static Widget * previousWidget; @@ -108,8 +169,8 @@ bool menuWidgetChoice(evt_t event) case EVT_ENTRY: { const WidgetFactory * factory; - previousWidget = currentScreen->getWidget(currentZone); - currentScreen->setWidget(currentZone, NULL); + previousWidget = currentContainer->getWidget(currentZone); + currentContainer->setWidget(currentZone, NULL); menuHorizontalPosition = 0; if (previousWidget) { factory = previousWidget->getFactory(); @@ -123,19 +184,19 @@ bool menuWidgetChoice(evt_t event) else { factory = registeredWidgets[0]; } - currentWidget = factory->create(currentScreen->getZone(currentZone), &tempData); + currentWidget = factory->create(currentContainer->getZone(currentZone), &tempData); break; } case EVT_KEY_BREAK(KEY_EXIT): delete currentWidget; - currentScreen->setWidget(currentZone, previousWidget); + currentContainer->setWidget(currentZone, previousWidget); popMenu(); return false; case EVT_KEY_BREAK(KEY_ENTER): delete previousWidget; - currentScreen->createWidget(currentZone, registeredWidgets[menuHorizontalPosition]); + currentContainer->createWidget(currentZone, registeredWidgets[menuHorizontalPosition]); storageDirty(EE_MODEL); popMenu(); return false; @@ -143,21 +204,21 @@ bool menuWidgetChoice(evt_t event) case EVT_ROTARY_RIGHT: if (menuHorizontalPosition < int(countRegisteredWidgets-1)) { delete currentWidget; - currentWidget = registeredWidgets[++menuHorizontalPosition]->create(currentScreen->getZone(currentZone), &tempData); + currentWidget = registeredWidgets[++menuHorizontalPosition]->create(currentContainer->getZone(currentZone), &tempData); } break; case EVT_ROTARY_LEFT: if (menuHorizontalPosition > 0) { delete currentWidget; - currentWidget = registeredWidgets[--menuHorizontalPosition]->create(currentScreen->getZone(currentZone), &tempData); + currentWidget = registeredWidgets[--menuHorizontalPosition]->create(currentContainer->getZone(currentZone), &tempData); } break; } currentScreen->refresh(); - Zone zone = currentScreen->getZone(currentZone); + Zone zone = currentContainer->getZone(currentZone); lcdDrawFilledRect(0, 0, zone.x-2, LCD_H, SOLID, OVERLAY_COLOR | (8<<24)); lcdDrawFilledRect(zone.x+zone.w+2, 0, LCD_W-zone.x-zone.w-2, LCD_H, SOLID, OVERLAY_COLOR | (8<<24)); lcdDrawFilledRect(zone.x-2, 0, zone.w+4, zone.y-2, SOLID, OVERLAY_COLOR | (8<<24)); @@ -176,20 +237,18 @@ bool menuWidgetChoice(evt_t event) void onZoneMenu(const char * result) { if (result == STR_SELECT_WIDGET) { - currentZone = menuVerticalPosition; pushMenu(menuWidgetChoice); } else if (result == STR_WIDGET_SETTINGS) { - currentWidget = currentScreen->getWidget(menuVerticalPosition); pushMenu(menuWidgetSettings); } else if (result == STR_REMOVE_WIDGET) { - currentScreen->setWidget(menuVerticalPosition, NULL); + currentContainer->setWidget(currentZone, NULL); storageDirty(EE_MODEL); } } -bool menuSetupWidgets(evt_t event) +bool menuWidgetsSetup(evt_t event) { switch (event) { case EVT_ENTRY: @@ -200,17 +259,30 @@ bool menuSetupWidgets(evt_t event) return false; } - currentScreen->refresh(true); + currentScreen->refresh(); - for (int i=currentScreen->getZonesCount()-1; i>=0; i--) { - Zone zone = currentScreen->getZone(i); + for (int i=currentContainer->getZonesCount()-1; i>=0; i--) { + Zone zone = currentContainer->getZone(i); + LcdFlags color; + int padding, thickness; + if (currentContainer == topbar) { + color = MENU_TITLE_COLOR; + padding = 2; + thickness = 1; + } + else { + color = TEXT_INVERTED_BGCOLOR; + padding = 4; + thickness = 2; + } if (menuVerticalPosition == i) { - lcdDrawSolidRect(zone.x-4, zone.y-4, zone.w+8, zone.h+8, 2, TEXT_INVERTED_BGCOLOR); + lcdDrawSolidRect(zone.x-padding, zone.y-padding, zone.w+2*padding, zone.h+2*padding, thickness, color); if (event == EVT_KEY_BREAK(KEY_ENTER)) { - Widget * widget = currentScreen->getWidget(i); - if (widget) { + currentZone = menuVerticalPosition; + currentWidget = currentContainer->getWidget(menuVerticalPosition); + if (currentWidget) { POPUP_MENU_ADD_ITEM(STR_SELECT_WIDGET); - if (widget->getFactory()->getOptions()) + if (currentWidget->getFactory()->getOptions()) POPUP_MENU_ADD_ITEM(STR_WIDGET_SETTINGS); POPUP_MENU_ADD_ITEM(STR_REMOVE_WIDGET); popupMenuHandler = onZoneMenu; @@ -221,15 +293,13 @@ bool menuSetupWidgets(evt_t event) } } else { - lcdDrawRect(zone.x-4, zone.y-4, zone.w+8, zone.h+8, 2, 0x3F, TEXT_INVERTED_BGCOLOR); + lcdDrawRect(zone.x-padding, zone.y-padding, zone.w+2*padding, zone.h+2*padding, thickness, 0x3F, color); } } - navigate(event, currentScreen->getZonesCount(), currentScreen->getZonesCount(), 1); + navigate(event, currentContainer->getZonesCount(), currentContainer->getZonesCount(), 1); return true; } -extern int updateMainviewsMenu(); - template T * editThemeChoice(coord_t x, coord_t y, T * array[], uint8_t count, T * current, bool needsOffsetCheck, LcdFlags attr, evt_t event) { @@ -291,12 +361,19 @@ T * editThemeChoice(coord_t x, coord_t y, T * array[], uint8_t count, T * curren return NULL; } +enum menuScreensThemeItems { + ITEM_SCREEN_SETUP_THEME, + ITEM_SCREEN_SETUP_THEME_SETTINGS = ITEM_SCREEN_SETUP_THEME+2, + ITEM_SCREEN_SETUP_TOPBAR, + ITEM_SCREEN_SETUP_MAX +}; + bool menuScreensTheme(evt_t event) { bool needsOffsetCheck = (menuVerticalPosition != 0 || menuHorizontalPosition < 0); menuPageCount = updateMainviewsMenu(); - MENU_WITH_OPTIONS("User interface", LBM_MAINVIEWS_ICONS, menuTabMainviews, menuPageCount, 0, 1, { uint8_t(NAVIGATION_LINE_BY_LINE|uint8_t(countRegisteredThemes-1)), ORPHAN_ROW, 0, 0, 0, 0 }); + MENU_WITH_OPTIONS("User interface", LBM_SCREENS_SETUP_ICONS, menuTabScreensSetup, menuPageCount, 0, ITEM_SCREEN_SETUP_MAX, { uint8_t(NAVIGATION_LINE_BY_LINE|uint8_t(countRegisteredThemes-1)), ORPHAN_ROW, 0, 0, 0, 0 }); for (int i=0; i 0) ? BLINK | INVERS : INVERS); LcdFlags attr = (menuVerticalPosition == k ? blink : 0); switch (k) { - case 0: { + case ITEM_SCREEN_SETUP_THEME: { lcdDrawText(MENUS_MARGIN_LEFT, y + FH / 2, "Theme"); const Theme * new_theme = editThemeChoice(SCREENS_SETUP_2ND_COLUMN, y, registeredThemes, countRegisteredThemes, theme, needsOffsetCheck, attr, event); if (new_theme) { + new_theme->init(); loadTheme(new_theme); strncpy(g_eeGeneral.themeName, new_theme->getName(), sizeof(g_eeGeneral.themeName)); storageDirty(EE_GENERAL); @@ -315,34 +393,56 @@ bool menuScreensTheme(evt_t event) break; } - case 1: + case ITEM_SCREEN_SETUP_THEME_SETTINGS: + drawButton(SCREENS_SETUP_2ND_COLUMN, y, "Theme settings", attr); + if (attr && event == EVT_KEY_BREAK(KEY_ENTER) && theme->getOptions()) { + s_editMode = 0; + pushMenu(menuThemeSettings); + } break; + + case ITEM_SCREEN_SETUP_TOPBAR: + lcdDrawText(MENUS_MARGIN_LEFT, y, "Top bar"); + drawButton(SCREENS_SETUP_2ND_COLUMN, y, "Setup", attr); + if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) { + currentScreen = customScreens[0]; + currentContainer = topbar; + pushMenu(menuWidgetsSetup); + } + break; + } } return true; } -bool menuScreenAdd(evt_t event); -void onScreenSetupMenu(const char * result); +enum menuScreenSetup { + ITEM_SCREEN_SETUP_LAYOUT, + ITEM_SCREEN_SETUP_WIDGETS_SETUP = ITEM_SCREEN_SETUP_LAYOUT+2, + ITEM_SCREEN_SETUP_LAYOUT_OPTION1, +}; -template -bool menuScreenSetup(evt_t event) +bool menuScreenSetup(int index, evt_t event) { - currentScreen = customScreens[T]; + if (customScreens[index] == NULL) { + return menuScreenAdd(event); + } + currentScreen = customScreens[index]; + currentContainer = currentScreen; bool needsOffsetCheck = (menuVerticalPosition != 0 || menuHorizontalPosition < 0); - linesCount = 3; + linesCount = ITEM_SCREEN_SETUP_LAYOUT_OPTION1; const ZoneOption * options = currentScreen->getFactory()->getOptions(); for (const ZoneOption * option = options; option->name; option++) { linesCount++; } char title[] = "Main view X"; - title[sizeof(title)-2] = '1' + T; + title[sizeof(title)-2] = '1' + index; menuPageCount = updateMainviewsMenu(); - MENU_WITH_OPTIONS(title, LBM_MAINVIEWS_ICONS, menuTabMainviews, menuPageCount, T+1, linesCount, { uint8_t(NAVIGATION_LINE_BY_LINE|uint8_t(countRegisteredLayouts-1)), ORPHAN_ROW, 0, 0, 0, 0 }); + MENU_WITH_OPTIONS(title, LBM_SCREENS_SETUP_ICONS, menuTabScreensSetup, menuPageCount, index+1, linesCount, { uint8_t(NAVIGATION_LINE_BY_LINE|uint8_t(countRegisteredLayouts-1)), ORPHAN_ROW, 0, 0, 0, 0 }); for (int i=0; i0) ? BLINK|INVERS : INVERS); LcdFlags attr = (menuVerticalPosition == k ? blink : 0); switch(k) { - case 0: + case ITEM_SCREEN_SETUP_LAYOUT: { lcdDrawText(MENUS_MARGIN_LEFT, y + FH / 2, "Layout"); const LayoutFactory * factory = editThemeChoice(SCREENS_SETUP_2ND_COLUMN, y, registeredLayouts, countRegisteredLayouts, currentScreen->getFactory(), needsOffsetCheck, attr, event); if (factory) { - delete customScreens[T]; - customScreens[T] = factory->create(&g_model.screenData[T].layoutData); - strncpy(g_model.screenData[T].layoutName, factory->getName(), sizeof(g_model.screenData[T].layoutName)); + delete customScreens[index]; + customScreens[index] = factory->create(&g_model.screenData[index].layoutData); + strncpy(g_model.screenData[index].layoutName, factory->getName(), sizeof(g_model.screenData[index].layoutName)); storageDirty(EE_MODEL); } break; } - case 1: + case ITEM_SCREEN_SETUP_LAYOUT+1: break; - case 2: + case ITEM_SCREEN_SETUP_WIDGETS_SETUP: drawButton(SCREENS_SETUP_2ND_COLUMN, y, "Setup widgets", attr); if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) { - pushMenu(menuSetupWidgets); + pushMenu(menuWidgetsSetup); } break; default: if (k < linesCount) { - uint8_t index = k - 3; + uint8_t index = k - ITEM_SCREEN_SETUP_LAYOUT_OPTION1; const ZoneOption * option = &options[index]; - ZoneOptionValue value = currentScreen->getOptionValue(index); - value = editZoneOption(y, option, value, attr, event); - if (attr) { - currentScreen->setOptionValue(index, value); - } + ZoneOptionValue * value = currentScreen->getOptionValue(index); + editZoneOption(y, option, value, attr, EE_MODEL, event); } break; } } - if (menuVerticalPosition == -1 && T > 0 && event == EVT_KEY_LONG(KEY_ENTER)) { + if (menuVerticalPosition == -1 && index > 0 && event == EVT_KEY_LONG(KEY_ENTER)) { killEvents(KEY_ENTER); - menuHorizontalPosition = T; + menuHorizontalPosition = index; POPUP_MENU_ADD_ITEM(STR_REMOVE_SCREEN); popupMenuHandler = onScreenSetupMenu; } @@ -397,33 +494,29 @@ bool menuScreenSetup(evt_t event) return true; } -MenuHandlerFunc menuTabMainviews[1+MAX_CUSTOM_SCREENS] = { - menuScreensTheme, - menuScreenSetup<0>, - menuScreenSetup<1>, - menuScreenSetup<2>, - menuScreenSetup<3>, - menuScreenSetup<4> -}; +template +bool menuCustomScreenSetup(evt_t event) +{ + return menuScreenSetup(N, event); +} -const MenuHandlerFunc menuMainviews[MAX_CUSTOM_SCREENS] = { - menuScreenSetup<0>, - menuScreenSetup<1>, - menuScreenSetup<2>, - menuScreenSetup<3>, - menuScreenSetup<4> +const MenuHandlerFunc menuTabScreensSetup[1+MAX_CUSTOM_SCREENS] = { + menuScreensTheme, + menuCustomScreenSetup<0>, + menuCustomScreenSetup<1>, + menuCustomScreenSetup<2>, + menuCustomScreenSetup<3>, + menuCustomScreenSetup<4> }; int updateMainviewsMenu() { for (int index=1; indexcreate(&g_model.screenData[menuPageCount-2].layoutData); - chainMenu(menuMainviews[menuPageCount-2]); + s_editMode = 0; return false; } - MENU_WITH_OPTIONS("Add main view", LBM_MAINVIEWS_ICONS, menuTabMainviews, menuPageCount, menuPageCount-1, 0, { uint8_t(NAVIGATION_LINE_BY_LINE|uint8_t(countRegisteredLayouts-1)), ORPHAN_ROW, 0, 0, 0, 0 }); - + SIMPLE_MENU_WITH_OPTIONS("Add main view", LBM_SCREENS_SETUP_ICONS, menuTabScreensSetup, menuPageCount, menuPageCount-1, 0); return true; } @@ -455,6 +547,6 @@ void onScreenSetupMenu(const char * result) } memset(&g_model.screenData[MAX_CUSTOM_SCREENS-1], 0, sizeof(CustomScreenData)); customScreens[MAX_CUSTOM_SCREENS-1] = NULL; - chainMenu(menuMainviews[menuHorizontalPosition > 0 ? menuHorizontalPosition-1 : 0]); + // chainMenu(menuMainviews[menuHorizontalPosition > 0 ? menuHorizontalPosition-1 : 0]); } } diff --git a/radio/src/gui/horus/theme.cpp b/radio/src/gui/horus/theme.cpp index e23832796..b503c7226 100644 --- a/radio/src/gui/horus/theme.cpp +++ b/radio/src/gui/horus/theme.cpp @@ -20,23 +20,54 @@ #include "opentx.h" +void Theme::init() const +{ + memset(&g_eeGeneral.themeData, 0, sizeof(Theme::PersistentData)); + if (options) { + int i = 0; + for (const ZoneOption * option = options; option->name; option++, i++) { + // TODO compiler bug? The CPU freezes ... g_eeGeneral.themeData.options[i] = &option->deflt; + memcpy(&g_eeGeneral.themeData.options[i], &option->deflt, sizeof(ZoneOptionValue)); + } + } +} + +ZoneOptionValue * Theme::getOptionValue(unsigned int index) const +{ + return &g_eeGeneral.themeData.options[index]; +} + +void Theme::drawThumb(uint16_t x, uint16_t y, uint32_t flags) const +{ + lcdDrawBitmap(x, y, bitmap); +} + void Theme::drawBackground() const { lcdDrawSolidFilledRect(0, 0, LCD_W, LCD_H, TEXT_BGCOLOR); } -void Theme::drawAlertBox(const char * title, const char * text, const char * action) const +void Theme::drawMessageBox(const char * title, const char * text, const char * action, uint32_t flags) const { - drawBackground(); - lcdDrawFilledRect(0, POPUP_Y, LCD_W, POPUP_H, SOLID, TEXT_INVERTED_COLOR | OPACITY(8)); - lcdDrawAlphaBitmap(POPUP_X-80, POPUP_Y+12, LBM_ASTERISK); + //if (flags & MESSAGEBOX_TYPE_ALERT) { + drawBackground(); + lcdDrawFilledRect(0, POPUP_Y, LCD_W, POPUP_H, SOLID, TEXT_INVERTED_COLOR | OPACITY(8)); + //} + + if ((flags & MESSAGEBOX_TYPE_ALERT) || (flags & MESSAGEBOX_TYPE_WARNING)) { + lcdDrawAlphaBitmap(POPUP_X-80, POPUP_Y+12, LBM_ASTERISK); + } #if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ) - lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y, STR_WARNING, ALARM_COLOR|DBLSIZE); - lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+28, title, ALARM_COLOR|DBLSIZE); + if ((flags & MESSAGEBOX_TYPE_ALERT) || (flags & MESSAGEBOX_TYPE_WARNING)) { + lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y, STR_WARNING, ALARM_COLOR|DBLSIZE); + } + lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+28, title, ALARM_COLOR|DBLSIZE); #else lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y, title, ALARM_COLOR|DBLSIZE); - lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+28, STR_WARNING, ALARM_COLOR|DBLSIZE); + if ((flags & MESSAGEBOX_TYPE_ALERT) || (flags & MESSAGEBOX_TYPE_WARNING)) { + lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+28, STR_WARNING, ALARM_COLOR|DBLSIZE); + } #endif if (text) { @@ -53,6 +84,7 @@ unsigned int countRegisteredThemes = 0; void registerTheme(const Theme * theme) { if (countRegisteredThemes < MAX_REGISTERED_THEMES) { + TRACE("register theme %s", theme->getName()); registeredThemes[countRegisteredThemes++] = theme; } } @@ -70,6 +102,7 @@ const Theme * getTheme(const char * name) void loadTheme(const Theme * new_theme) { + TRACE("load theme %s", new_theme->getName()); theme = new_theme; theme->load(); } @@ -80,5 +113,11 @@ void loadTheme() memset(name, 0, sizeof(name)); strncpy(name, g_eeGeneral.themeName, sizeof(g_eeGeneral.themeName)); const Theme * new_theme = getTheme(name); - loadTheme(new_theme ? new_theme : theme); -} \ No newline at end of file + if (new_theme) { + loadTheme(new_theme); + } + else { + theme->init(); + theme->load(); + } +} diff --git a/radio/src/gui/horus/theme.h b/radio/src/gui/horus/theme.h index 3af0f2c5a..cc50a4ad1 100644 --- a/radio/src/gui/horus/theme.h +++ b/radio/src/gui/horus/theme.h @@ -21,42 +21,59 @@ #ifndef _THEME_H_ #define _THEME_H_ -class Theme; +#define MAX_THEME_OPTIONS 5 +class Theme; void registerTheme(const Theme * theme); +#define MESSAGEBOX_TYPE_INFO 0 +#define MESSAGEBOX_TYPE_QUESTION 1 +#define MESSAGEBOX_TYPE_WARNING 2 +#define MESSAGEBOX_TYPE_ALERT 4 + class Theme { public: - Theme(const char * name, const uint8_t * bitmap): + struct PersistentData { + ZoneOptionValue options[MAX_THEME_OPTIONS]; + }; + + Theme(const char * name, const uint8_t * bitmap, const ZoneOption * options=NULL): name(name), - bitmap(bitmap) + bitmap(bitmap), + options(options) { registerTheme(this); } - const char * getName() const + inline const char * getName() const { return name; } - virtual void drawThumb(uint16_t x, uint16_t y, uint32_t flags) const + inline const ZoneOption * getOptions() const { - extern void lcdDrawBitmap(int x, int y, const uint8_t * bitmap, int offset=0, int height=0, int scale=0); - lcdDrawBitmap(x, y, bitmap); + return options; } + void init() const; + + ZoneOptionValue * getOptionValue(unsigned int index) const; + + virtual void drawThumb(uint16_t x, uint16_t y, uint32_t flags) const; + virtual void load() const = 0; virtual void drawBackground() const; virtual void drawTopbarBackground(const uint8_t * icon) const = 0; - virtual void drawAlertBox(const char * title, const char * text, const char * action) const; + virtual void drawMessageBox(const char * title, const char * text, const char * action, uint32_t flags) const; protected: const char * name; const uint8_t * bitmap; + const ZoneOption * options; }; extern const Theme * theme; diff --git a/radio/src/gui/horus/themes/darkblue.cpp b/radio/src/gui/horus/themes/darkblue.cpp index 59a1ac679..44caf5ef1 100644 --- a/radio/src/gui/horus/themes/darkblue.cpp +++ b/radio/src/gui/horus/themes/darkblue.cpp @@ -20,15 +20,19 @@ #include "opentx.h" -const uint8_t LBM_TOPMENU_BMP_OPENTX[] = { +const uint8_t LBM_TOPMENU_BMP_OPENTX[] __DMA = { #include "bmp_topmenu_opentx.lbm" }; +const uint8_t LBM_THEME_DARKBLUE[] __DMA = { +#include "bmp_darkblue.lbm" +}; + class DarkblueTheme: public Theme { public: - DarkblueTheme(const char * name, const uint8_t * bitmap): - Theme(name, bitmap) + DarkblueTheme(): + Theme("Darkblue", LBM_THEME_DARKBLUE) { } @@ -77,8 +81,4 @@ class DarkblueTheme: public Theme } }; -const uint8_t LBM_THEME_DARKBLUE[] __DMA = { -#include "bmp_darkblue.lbm" -}; - -DarkblueTheme darkblueTheme("Darkblue", LBM_THEME_DARKBLUE); \ No newline at end of file +DarkblueTheme darkblueTheme; diff --git a/radio/src/gui/horus/topbar.cpp b/radio/src/gui/horus/topbar.cpp new file mode 100644 index 000000000..4a4519106 --- /dev/null +++ b/radio/src/gui/horus/topbar.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "opentx.h" + +unsigned int Topbar::getZonesCount() const +{ + return MAX_TOPBAR_ZONES; +} + +Zone Topbar::getZone(unsigned int index) const +{ + Zone zone; + zone.x = 50 + (TOPBAR_ZONE_WIDTH + 2*TOPBAR_ZONE_MARGIN) * index; + zone.y = TOPBAR_ZONE_MARGIN; + zone.w = TOPBAR_ZONE_WIDTH; + zone.h = MENU_HEADER_HEIGHT - 2*TOPBAR_ZONE_MARGIN; + return zone; +} + +void drawTopBar() +{ + theme->drawTopbarBackground(NULL); + + // USB icon + if (usbPlugged()) { + lcdDrawBitmapPattern(378, 8, LBM_TOPMENU_USB, MENU_TITLE_COLOR); + } + + // RSSI + const uint8_t rssiBarsValue[] = {30, 40, 50, 60, 80}; + const uint8_t rssiBarsHeight[] = {5, 10, 15, 21, 31}; + for (unsigned int i = 0; i < DIM(rssiBarsHeight); i++) { + uint8_t height = rssiBarsHeight[i]; + lcdDrawSolidFilledRect(390 + i * 6, 38 - height, 4, height, TELEMETRY_RSSI() >= rssiBarsValue[i] ? MENU_TITLE_COLOR : MENU_TITLE_DISABLE_COLOR); + } + + topbar->refresh(); + +#if 0 + // Radio battery - TODO + // putsValueWithUnit(370, 8, g_vbat100mV, UNIT_VOLTS, PREC1|SMLSIZE|MENU_TITLE_COLOR); + // lcdDrawSolidRect(300, 3, 20, 50, MENU_TITLE_COLOR); + // lcdDrawRect(batt_icon_x+FW, BAR_Y+1, 13, 7); + // lcdDrawSolidVerticalLine(batt_icon_x+FW+13, BAR_Y+2, 5); + + // Rx battery + if (g_model.frsky.voltsSource) { // TODO should not be in frsky struct + TelemetryItem & item = telemetryItems[g_model.frsky.voltsSource-1]; + if (item.isAvailable()) { + int32_t value = item.value; + TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1]; + LcdFlags att = 0; + if (sensor.prec == 2) { + att |= PREC1; + value /= 10; + } + else if (sensor.prec == 1) { + att |= PREC1; + } + att |= (item.isOld() ? ALARM_COLOR : TEXT_COLOR); + lcdDrawSolidFilledRect(ALTITUDE_X, VOLTS_Y, ALTITUDE_W, ALTITUDE_H, TEXT_BGCOLOR); + lcdDrawText(ALTITUDE_X+PADDING, VOLTS_Y+2, "Voltage", att); + putsValueWithUnit(ALTITUDE_X+PADDING, VOLTS_Y+12, value, UNIT_VOLTS, DBLSIZE|LEFT|att); + } + } + + // Model altitude + if (g_model.frsky.altitudeSource) { + TelemetryItem & item = telemetryItems[g_model.frsky.altitudeSource-1]; + if (item.isAvailable()) { + int32_t value = item.value; + TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1]; + if (sensor.prec) value /= sensor.prec == 2 ? 100 : 10; + LcdFlags att = (item.isOld() ? ALARM_COLOR : TEXT_COLOR); + lcdDrawSolidFilledRect(ALTITUDE_X, ALTITUDE_Y, ALTITUDE_W, ALTITUDE_H, TEXT_BGCOLOR); + lcdDrawText(ALTITUDE_X+PADDING, ALTITUDE_Y+2, "Alt", att); + putsValueWithUnit(ALTITUDE_X+PADDING, ALTITUDE_Y+12, value, UNIT_METERS, DBLSIZE|LEFT|att); + } + } +#endif + +} diff --git a/radio/src/gui/horus/topbar.h b/radio/src/gui/horus/topbar.h new file mode 100644 index 000000000..93d8aaadf --- /dev/null +++ b/radio/src/gui/horus/topbar.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _TOPBAR_H_ +#define _TOPBAR_H_ + +#include "widgets_container.h" + +#define MAX_TOPBAR_ZONES 5 +#define MAX_TOPBAR_OPTIONS 0 +#define TOPBAR_ZONE_WIDTH 60 +#define TOPBAR_ZONE_MARGIN 3 + +class Topbar: public WidgetsContainer +{ + public: + explicit Topbar(PersistentData * persistentData): + WidgetsContainer(persistentData) + { + } + + virtual unsigned int getZonesCount() const; + + virtual Zone getZone(unsigned int index) const; +}; + +#endif // _TOPBAR_H_ diff --git a/radio/src/gui/horus/view_main.cpp b/radio/src/gui/horus/view_main.cpp index 52b16c717..6dcf2346d 100644 --- a/radio/src/gui/horus/view_main.cpp +++ b/radio/src/gui/horus/view_main.cpp @@ -30,6 +30,7 @@ #define POTS_LINE_Y 252 Layout * customScreens[MAX_CUSTOM_SCREENS]; +Topbar * topbar; void drawMainPots() { @@ -79,72 +80,6 @@ void drawTrims(uint8_t flightMode) } } -void drawMainViewTopBar() -{ - const int ALTITUDE_Y = 16; - const int VOLTS_Y = 16+16+30; - const int ALTITUDE_W = 56; - const int ALTITUDE_X = LCD_W-ALTITUDE_Y-ALTITUDE_W; - const int ALTITUDE_H = 30; - const int PADDING = 4; - - theme->drawTopbarBackground(NULL); - - // USB icon - if (usbPlugged()) { - lcdDrawBitmapPattern(378, 8, LBM_TOPMENU_USB, MENU_TITLE_COLOR); - } - - // RSSI - const uint8_t rssiBarsValue[] = { 30, 40, 50, 60, 80 }; - const uint8_t rssiBarsHeight[] = { 5, 10, 15, 21, 31 }; - for (unsigned int i=0; i= rssiBarsValue[i] ? MENU_TITLE_COLOR : MENU_TITLE_DISABLE_COLOR); - } - - // Radio battery - TODO - // putsValueWithUnit(370, 8, g_vbat100mV, UNIT_VOLTS, PREC1|SMLSIZE|MENU_TITLE_COLOR); - // lcdDrawSolidRect(300, 3, 20, 50, MENU_TITLE_COLOR); - // lcdDrawRect(batt_icon_x+FW, BAR_Y+1, 13, 7); - // lcdDrawSolidVerticalLine(batt_icon_x+FW+13, BAR_Y+2, 5); - - // Rx battery - if (g_model.frsky.voltsSource) { // TODO should not be in frsky struct - TelemetryItem & item = telemetryItems[g_model.frsky.voltsSource-1]; - if (item.isAvailable()) { - int32_t value = item.value; - TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1]; - LcdFlags att = 0; - if (sensor.prec == 2) { - att |= PREC1; - value /= 10; - } - else if (sensor.prec == 1) { - att |= PREC1; - } - att |= (item.isOld() ? ALARM_COLOR : TEXT_COLOR); - lcdDrawSolidFilledRect(ALTITUDE_X, VOLTS_Y, ALTITUDE_W, ALTITUDE_H, TEXT_BGCOLOR); - lcdDrawText(ALTITUDE_X+PADDING, VOLTS_Y+2, "Voltage", att); - putsValueWithUnit(ALTITUDE_X+PADDING, VOLTS_Y+12, value, UNIT_VOLTS, DBLSIZE|LEFT|att); - } - } - - // Model altitude - if (g_model.frsky.altitudeSource) { - TelemetryItem & item = telemetryItems[g_model.frsky.altitudeSource-1]; - if (item.isAvailable()) { - int32_t value = item.value; - TelemetrySensor & sensor = g_model.telemetrySensors[g_model.frsky.altitudeSource-1]; - if (sensor.prec) value /= sensor.prec == 2 ? 100 : 10; - LcdFlags att = (item.isOld() ? ALARM_COLOR : TEXT_COLOR); - lcdDrawSolidFilledRect(ALTITUDE_X, ALTITUDE_Y, ALTITUDE_W, ALTITUDE_H, TEXT_BGCOLOR); - lcdDrawText(ALTITUDE_X+PADDING, ALTITUDE_Y+2, "Alt", att); - putsValueWithUnit(ALTITUDE_X+PADDING, ALTITUDE_Y+12, value, UNIT_METERS, DBLSIZE|LEFT|att); - } - } -} - bool isViewAvailable(int index) { if (index <= VIEW_CHANNELS) @@ -187,7 +122,7 @@ void onMainViewMenu(const char *result) chainMenu(menuStatisticsView); } else if (result == STR_SETUP_SCREENS) { - pushMenu(menuTabMainviews[1]); + pushMenu(menuTabScreensSetup[1]); } else if (result == STR_ABOUT_US) { chainMenu(menuAboutView); diff --git a/radio/src/gui/horus/widget.cpp b/radio/src/gui/horus/widget.cpp index 0b73b5bf5..441e85477 100644 --- a/radio/src/gui/horus/widget.cpp +++ b/radio/src/gui/horus/widget.cpp @@ -25,6 +25,7 @@ unsigned int countRegisteredWidgets = 0; void registerWidget(const WidgetFactory * factory) { if (countRegisteredWidgets < MAX_REGISTERED_WIDGETS) { + TRACE("register widget %s", factory->getName()); registeredWidgets[countRegisteredWidgets++] = factory; } } diff --git a/radio/src/gui/horus/widget.h b/radio/src/gui/horus/widget.h index 1f98d7b9c..da75647ce 100644 --- a/radio/src/gui/horus/widget.h +++ b/radio/src/gui/horus/widget.h @@ -23,7 +23,7 @@ #include -#define MAX_WIDGET_OPTIONS 4 +#define MAX_WIDGET_OPTIONS 5 struct Zone { @@ -45,6 +45,7 @@ struct ZoneOption Source, Bool, String, + File, TextSize, Timer, Switch, @@ -75,19 +76,16 @@ class Widget { } - const WidgetFactory * getFactory() const + inline const WidgetFactory * getFactory() const { return factory; } - virtual ZoneOptionValue getOptionValue(unsigned int index) const - { - return persistentData->options[index]; - } + inline const ZoneOption * getOptions() const; - virtual void setOptionValue(unsigned int index, ZoneOptionValue value) const + inline ZoneOptionValue * getOptionValue(unsigned int index) const { - persistentData->options[index] = value; + return &persistentData->options[index]; } virtual void refresh() = 0; @@ -103,7 +101,7 @@ void registerWidget(const WidgetFactory * factory); class WidgetFactory { public: - WidgetFactory(const char * name, const ZoneOption * options): + WidgetFactory(const char * name, const ZoneOption * options=NULL): name(name), options(options) { @@ -126,11 +124,12 @@ class WidgetFactory if (options) { int i = 0; for (const ZoneOption * option = options; option->name; option++) { - persistentData->options[i++] = option->deflt; + // TODO compiler bug? The CPU freezes ... persistentData->options[i++] = option->deflt; + memcpy(&persistentData->options[i++], &option->deflt, sizeof(ZoneOptionValue)); } } } - + virtual Widget * create(const Zone & zone, Widget::PersistentData * persistentData, bool init=true) const = 0; protected: @@ -157,6 +156,11 @@ class BaseWidgetFactory: public WidgetFactory } }; +inline const ZoneOption * Widget::getOptions() const +{ + return getFactory()->getOptions(); +} + #define MAX_REGISTERED_WIDGETS 10 extern unsigned int countRegisteredWidgets; extern const WidgetFactory * registeredWidgets[MAX_REGISTERED_WIDGETS]; diff --git a/radio/src/gui/horus/widgets.cpp b/radio/src/gui/horus/widgets.cpp index 131b4fb67..c83ac5635 100644 --- a/radio/src/gui/horus/widgets.cpp +++ b/radio/src/gui/horus/widgets.cpp @@ -426,7 +426,7 @@ int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int void drawSleepBitmap() { lcdClear(); - lcdDrawAlphaBitmap((LCD_W-SLEEP_BITMAP_WIDTH)/2, (LCD_H-SLEEP_BITMAP_HEIGHT)/2, LBM_SLEEP); + lcdDrawBitmap((LCD_W-SLEEP_BITMAP_WIDTH)/2, (LCD_H-SLEEP_BITMAP_HEIGHT)/2, LBM_SLEEP); lcdRefresh(); } diff --git a/radio/src/gui/horus/widgets.h b/radio/src/gui/horus/widgets.h index 123e011bb..ef1daf95b 100644 --- a/radio/src/gui/horus/widgets.h +++ b/radio/src/gui/horus/widgets.h @@ -78,7 +78,7 @@ void drawSleepBitmap(); void drawShutdownBitmap(uint32_t index); // Main view standard widgets -void drawMainViewTopBar(); +void drawTopBar(); void drawMainPots(); void drawTrims(uint8_t flightMode); diff --git a/radio/src/gui/horus/widgets/gauge.cpp b/radio/src/gui/horus/widgets/gauge.cpp index 58b3c845b..d33896c20 100644 --- a/radio/src/gui/horus/widgets/gauge.cpp +++ b/radio/src/gui/horus/widgets/gauge.cpp @@ -63,9 +63,9 @@ void GaugeWidget::refresh() // Gauge lcdSetColor(color); - lcdDrawSolidFilledRect(zone.x, zone.y + 15, zone.w, 16, TEXT_INVERTED_COLOR); - lcdDrawNumber((percent >= 100 ? 20 : (percent >= 10 ? 10 : 0)) + zone.x+zone.w/2, zone.y + 16, percent, SMLSIZE | CUSTOM_COLOR, 0, NULL, "%"); - lcdInvertRect(zone.x + w, zone.y + 15, zone.w - w, 16, CUSTOM_COLOR); + lcdDrawSolidFilledRect(zone.x, zone.y + 16, zone.w, 16, TEXT_INVERTED_COLOR); + lcdDrawNumber((percent >= 100 ? 20 : (percent >= 10 ? 10 : 0)) + zone.x+zone.w/2, zone.y + 17, percent, SMLSIZE | CUSTOM_COLOR, 0, NULL, "%"); + lcdInvertRect(zone.x + w, zone.y + 16, zone.w - w, 16, CUSTOM_COLOR); } BaseWidgetFactory gaugeWidget("Gauge", GaugeWidget::options); diff --git a/radio/src/gui/horus/widgets/modelpanel.cpp b/radio/src/gui/horus/widgets/modelbmp.cpp similarity index 72% rename from radio/src/gui/horus/widgets/modelpanel.cpp rename to radio/src/gui/horus/widgets/modelbmp.cpp index 2d247a4d8..18bb47084 100644 --- a/radio/src/gui/horus/widgets/modelpanel.cpp +++ b/radio/src/gui/horus/widgets/modelbmp.cpp @@ -20,10 +20,10 @@ #include "opentx.h" -class ModelPanelWidget: public Widget +class ModelBitmapWidget: public Widget { public: - ModelPanelWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData): + ModelBitmapWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData): Widget(factory, zone, persistentData) { } @@ -31,26 +31,24 @@ class ModelPanelWidget: public Widget virtual void refresh(); }; -void ModelPanelWidget::refresh() +void ModelBitmapWidget::refresh() { if (zone.h >= MODEL_BITMAP_HEIGHT) { lcdDrawFilledRect(zone.x, zone.y, zone.w, zone.h, SOLID, MAINVIEW_PANES_COLOR | OPACITY(5)); lcdDrawBitmapPattern(zone.x + 6, zone.y + 4, LBM_MODEL_ICON, MAINVIEW_GRAPHICS_COLOR); lcdDrawSizedText(zone.x + 45, zone.y + 10, g_model.header.name, LEN_MODEL_NAME, ZCHAR | SMLSIZE); lcdDrawSolidFilledRect(zone.x + 39, zone.y + 27, zone.w - 48, 2, MAINVIEW_GRAPHICS_COLOR); - int scale = getBitmapScale(modelBitmap, zone.w, zone.h - 25); + float scale = getBitmapScale(modelBitmap, zone.w, zone.h - 25); int width = getBitmapScaledSize(getBitmapWidth(modelBitmap), scale); int height = getBitmapScaledSize(getBitmapHeight(modelBitmap), scale); lcdDrawBitmap(zone.x + (zone.w - width) / 2, zone.y + zone.h - height / 2 - height / 2, modelBitmap, 0, 0, scale); } else { - int scale = getBitmapScale(modelBitmap, zone.w, zone.h); + float scale = getBitmapScale(modelBitmap, 1000, zone.h); int width = getBitmapScaledSize(getBitmapWidth(modelBitmap), scale); int height = getBitmapScaledSize(getBitmapHeight(modelBitmap), scale); - lcdDrawFilledRect(zone.x, zone.y, zone.w, height, SOLID, MAINVIEW_PANES_COLOR | OPACITY(5)); - lcdDrawSizedText(zone.x + 5, zone.y + 10, g_model.header.name, LEN_MODEL_NAME, ZCHAR | SMLSIZE); - lcdDrawBitmap(zone.x + zone.w - width, zone.y, modelBitmap, 0, 0, scale); + lcdDrawBitmap(zone.x + (zone.w - width) / 2, zone.y + (zone.h - height) / 2, modelBitmap, 0, 0, scale); } } -BaseWidgetFactory modelPanelWidget("ModelPanel", NULL); +BaseWidgetFactory modelBitmapWidget("ModelBmp", NULL); diff --git a/radio/src/gui/horus/widgets/timer.cpp b/radio/src/gui/horus/widgets/timer.cpp index 86d76d451..ad5602837 100644 --- a/radio/src/gui/horus/widgets/timer.cpp +++ b/radio/src/gui/horus/widgets/timer.cpp @@ -41,21 +41,35 @@ const ZoneOption TimerWidget::options[] = { void TimerWidget::refresh() { uint32_t index = persistentData->options[0].unsignedValue; - TimerData & timerData = g_model.timers[index]; TimerState & timerState = timersStates[index]; - lcdDrawBitmapPattern(zone.x, zone.y, LBM_TIMER_BACKGROUND, MAINVIEW_PANES_COLOR); - if (timerData.start) { - lcdDrawBitmapPatternPie(zone.x+2, zone.y+3, LBM_RSCALE, MAINVIEW_GRAPHICS_COLOR, 0, timerState.val <= 0 ? 360 : 360*(timerData.start-timerState.val)/timerData.start); + + if (zone.w >= 180 && zone.h >= 70) { + lcdDrawBitmapPattern(zone.x, zone.y, LBM_TIMER_BACKGROUND, MAINVIEW_PANES_COLOR); + if (timerData.start) { + lcdDrawBitmapPatternPie( + zone.x + 2, + zone.y + 3, LBM_RSCALE, MAINVIEW_GRAPHICS_COLOR, 0, + timerState.val <= 0 ? 360 : 360 * (timerData.start - timerState.val) / timerData.start); + } + else { + lcdDrawBitmapPattern(zone.x + 3, zone.y + 4, LBM_TIMER, MAINVIEW_GRAPHICS_COLOR); + } + putsTimer(zone.x + 76, zone.y + 31, abs(timerState.val), TEXT_COLOR | DBLSIZE | LEFT); + if (ZLEN(timerData.name) > 0) { + lcdDrawSizedText(zone.x + 78, zone.y + 20, timerData.name, LEN_TIMER_NAME, ZCHAR | SMLSIZE | TEXT_COLOR); + } + drawStringWithIndex(zone.x + 137, zone.y + 17, "TMR", index + 1, SMLSIZE | TEXT_COLOR); } else { - lcdDrawBitmapPattern(zone.x+3, zone.y+4, LBM_TIMER, MAINVIEW_GRAPHICS_COLOR); + drawStringWithIndex(zone.x, zone.y, "TMR", index + 1, SMLSIZE | TEXT_INVERTED_COLOR); + if (zone.w > 100) { + putsTimer(zone.x, zone.y + 16, abs(timerState.val), TEXT_INVERTED_COLOR | LEFT | MIDSIZE); + } + else { + putsTimer(zone.x, zone.y + 14, abs(timerState.val), TEXT_INVERTED_COLOR | LEFT); + } } - putsTimer(zone.x+76, zone.y+31, abs(timerState.val), TEXT_COLOR|DBLSIZE|LEFT); - if (ZLEN(timerData.name) > 0) { - lcdDrawSizedText(zone.x+78, zone.y+20, timerData.name, LEN_TIMER_NAME, ZCHAR|SMLSIZE|TEXT_COLOR); - } - drawStringWithIndex(zone.x+137, zone.y+17, "TMR", index+1, SMLSIZE|TEXT_COLOR); } BaseWidgetFactory timerWidget("Timer", TimerWidget::options); diff --git a/radio/src/gui/horus/widgets/value.cpp b/radio/src/gui/horus/widgets/value.cpp index 8c679484a..9ac868cc5 100644 --- a/radio/src/gui/horus/widgets/value.cpp +++ b/radio/src/gui/horus/widgets/value.cpp @@ -44,23 +44,35 @@ void ValueWidget::refresh() mixsrc_t field = persistentData->options[0].unsignedValue; - LcdFlags color = TEXT_COLOR; + LcdFlags color = TEXT_INVERTED_COLOR; int x = zone.x; int y = zone.y; - lcdDrawFilledRect(zone.x, zone.y, zone.w, zone.h, SOLID, MAINVIEW_PANES_COLOR | OPACITY(5)); + // lcdDrawFilledRect(zone.x, zone.y, zone.w, zone.h, SOLID, MAINVIEW_PANES_COLOR | OPACITY(5)); - int xValue, yValue; - LcdFlags attr; - if (zone.h < 50) { + int xValue, yValue, xLabel, yLabel; + LcdFlags attrValue, attrLabel=0; + if (zone.w < 120 && zone.h < 50) { + xValue = x; + yValue = y+14; + xLabel = x; + yLabel = y; + attrValue = LEFT | NO_UNIT | MIDSIZE; + attrLabel = SMLSIZE; + } + else if (zone.h < 50) { xValue = x+zone.w-NUMBERS_PADDING; yValue = y-2; - attr = NO_UNIT; + xLabel = x+NUMBERS_PADDING; + yLabel = y+2; + attrValue = NO_UNIT | DBLSIZE; } else { xValue = x+NUMBERS_PADDING; yValue = y+16; - attr = LEFT; + xLabel = x+NUMBERS_PADDING; + yLabel = y+2; + attrValue = LEFT | DBLSIZE; } if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER) { @@ -69,7 +81,7 @@ void ValueWidget::refresh() color = ALARM_COLOR; } putsMixerSource(x+NUMBERS_PADDING, y+2, field, color); - putsTimer(xValue, yValue, abs(timerState.val), attr|DBLSIZE|color); + putsTimer(xValue, yValue, abs(timerState.val), attrValue|DBLSIZE|color); return; } @@ -83,8 +95,8 @@ void ValueWidget::refresh() } } - putsMixerSource(x+NUMBERS_PADDING, y+2, field, color); - putsChannel(xValue, yValue, field, attr|DBLSIZE|color); + putsMixerSource(xLabel, yLabel, field, attrLabel|color); + putsChannel(xValue, yValue, field, attrValue|color); } BaseWidgetFactory ValueWidget("Value", ValueWidget::options); diff --git a/radio/src/gui/horus/widgets_container.h b/radio/src/gui/horus/widgets_container.h new file mode 100644 index 000000000..d12b61b24 --- /dev/null +++ b/radio/src/gui/horus/widgets_container.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _WIDGETS_CONTAINER_H_ +#define _WIDGETS_CONTAINER_H_ + +#include "widget.h" + +class WidgetsContainerInterface +{ + public: + virtual unsigned int getZonesCount() const = 0; + + virtual Zone getZone(unsigned int index) const = 0; + + inline Widget * getWidget(unsigned int index) + { + return widgets[index]; + } + + inline void setWidget(unsigned int index, Widget * widget) + { + widgets[index] = widget; + } + + virtual void createWidget(unsigned int index, const WidgetFactory * factory) = 0; + + protected: + Widget ** widgets; +}; + +template +class WidgetsContainer: public WidgetsContainerInterface +{ + public: + struct ZonePersistentData { + char widgetName[10]; + Widget::PersistentData widgetData; + }; + + struct PersistentData { + ZonePersistentData zones[N]; + ZoneOptionValue options[O]; + }; + + public: + WidgetsContainer(PersistentData * persistentData): + persistentData(persistentData) + { + widgets = (Widget **)calloc(N, sizeof(Widget *)); + } + + virtual ~WidgetsContainer() + { + if (widgets) { + for (uint8_t i=0; izones[index].widgetName, 0, sizeof(persistentData->zones[index].widgetName)); + strncpy(persistentData->zones[index].widgetName, factory->getName(), sizeof(persistentData->zones[index].widgetName)); + widgets[index] = factory->create(getZone(index), &persistentData->zones[index].widgetData); + } + } + + virtual void create() + { + memset(persistentData, 0, sizeof(PersistentData)); + } + + virtual void load() + { + if (widgets) { + unsigned int count = getZonesCount(); + for (unsigned int i=0; izones[i].widgetName[0]) { + char name[sizeof(persistentData->zones[i].widgetName)+1]; + memset(name, 0, sizeof(name)); + strncpy(name, persistentData->zones[i].widgetName, sizeof(persistentData->zones[i].widgetName)); + widgets[i] = loadWidget(name, getZone(i), &persistentData->zones[i].widgetData); + } + } + } + } + + inline ZoneOptionValue * getOptionValue(unsigned int index) const + { + return &persistentData->options[index]; + } + + virtual unsigned int getZonesCount() const = 0; + + virtual Zone getZone(unsigned int index) const = 0; + + virtual void refresh() + { + if (widgets) { + for (int i=0; irefresh(); + } + } + } + } + + protected: + PersistentData * persistentData; +}; + +#endif // _WIDGETS_CONTAINER_H_ diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index c8045f727..15c3c9a1f 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -776,13 +776,61 @@ void exec(int function, int nresults=0) } } +ZoneOption * createOptionsArray(int reference) +{ + if (reference == 0) { + return NULL; + } + + int count = 0; + lua_rawgeti(L, LUA_REGISTRYINDEX, reference); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + count++; + } + + ZoneOption * options = (ZoneOption *)malloc(sizeof(ZoneOption) * (count+1)); + + lua_rawgeti(L, LUA_REGISTRYINDEX, reference); + ZoneOption * option = options; + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + luaL_checktype(L, -2, LUA_TNUMBER); // key is number + luaL_checktype(L, -1, LUA_TTABLE); // value is table + uint8_t field = 0; + for (lua_pushnil(L); lua_next(L, -2) && field<3; lua_pop(L, 1), field++) { + switch (field) { + case 0: + luaL_checktype(L, -2, LUA_TNUMBER); // key is number + luaL_checktype(L, -1, LUA_TSTRING); // value is string + option->name = lua_tostring(L, -1); + break; + case 1: + luaL_checktype(L, -2, LUA_TNUMBER); // key is number + luaL_checktype(L, -1, LUA_TNUMBER); // value is number + option->type = (ZoneOption::Type)lua_tointeger(L, -1); + break; + case 2: + luaL_checktype(L, -2, LUA_TNUMBER); // key is number + luaL_checktype(L, -1, LUA_TNUMBER); // value is number + option->deflt.signedValue = lua_tointeger(L, -1); + break; + } + } + TRACE("option %s %d %d", option->name, option->type, option->deflt.signedValue); + option++; + } + + option->name = NULL; // sentinel + + return options; +} + class LuaTheme: public Theme { friend void luaLoadThemeCallback(); public: - LuaTheme(const char * name, const uint8_t * bitmap): - Theme(name, bitmap), + LuaTheme(const char * name, const uint8_t * bitmap, int options): + Theme(name, bitmap, createOptionsArray(options)), loadFunction(0), drawBackgroundFunction(0), drawTopbarBackgroundFunction(0), @@ -823,7 +871,7 @@ class LuaTheme: public Theme void luaLoadThemeCallback() { const char * name=NULL, * bitmap=NULL; - int loadFunction=0, drawBackgroundFunction=0, drawTopbarBackgroundFunction=0; + int themeOptions=0, loadFunction=0, drawBackgroundFunction=0, drawTopbarBackgroundFunction=0; luaL_checktype(L, -1, LUA_TTABLE); @@ -835,6 +883,10 @@ void luaLoadThemeCallback() else if (!strcmp(key, "bitmap")) { bitmap = luaL_checkstring(L, -1); } + else if (!strcmp(key, "options")) { + themeOptions = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pushnil(L); + } else if (!strcmp(key, "load")) { loadFunction = luaL_ref(L, LUA_REGISTRYINDEX); lua_pushnil(L); @@ -854,8 +906,9 @@ void luaLoadThemeCallback() strcpy(path, THEMES_PATH "/"); strcpy(path+sizeof(THEMES_PATH), bitmap); uint8_t * bitmapData = (uint8_t *)malloc(BITMAP_BUFFER_SIZE(51, 31)); + TRACE("path=%s bitmapData=%p %d %p", path, bitmapData, BITMAP_BUFFER_SIZE(51, 31), path); bmpLoad(bitmapData, path, 51, 31); - LuaTheme * theme = new LuaTheme(name, bitmapData); + LuaTheme * theme = new LuaTheme(name, bitmapData, themeOptions); theme->loadFunction = loadFunction; theme->drawBackgroundFunction = drawBackgroundFunction; theme->drawTopbarBackgroundFunction = drawTopbarBackgroundFunction; @@ -882,55 +935,6 @@ class LuaWidget: public Widget int widgetData; }; -ZoneOption * createOptionsArray(int reference) -{ - int count = 0; - lua_rawgeti(L, LUA_REGISTRYINDEX, reference); - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - count++; - } - - ZoneOption * options = (ZoneOption *)malloc(sizeof(ZoneOption) * (count+1)); - - lua_rawgeti(L, LUA_REGISTRYINDEX, reference); - ZoneOption * option = options; - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - luaL_checktype(L, -2, LUA_TNUMBER); // key is number - luaL_checktype(L, -1, LUA_TTABLE); // value is table - // const char * key = NULL; - // ZoneOption::Type type = ZoneOption::Integer; - // int val = 0; - uint8_t field = 0; - for (lua_pushnil(L); lua_next(L, -2) && field<3; lua_pop(L, 1), field++) { - switch (field) { - case 0: - luaL_checktype(L, -2, LUA_TNUMBER); // key is number - luaL_checktype(L, -1, LUA_TSTRING); // value is string - option->name = lua_tostring(L, -1); - break; - case 1: - luaL_checktype(L, -2, LUA_TNUMBER); // key is number - luaL_checktype(L, -1, LUA_TNUMBER); // value is number - option->type = (ZoneOption::Type)lua_tointeger(L, -1); - break; - case 2: - luaL_checktype(L, -2, LUA_TNUMBER); // key is number - luaL_checktype(L, -1, LUA_TNUMBER); // value is number - option->deflt.signedValue = lua_tointeger(L, -1); - break; - } - } - - // TRACE("option[%d] = %s %d %d", i, key, type, val); - option++; - // options[i++]. = (ZoneOption) { key, type, { .signedValue = val } }; - } - - option->name = NULL; // sentinel - - return options; -} - void l_pushtableint(const char * key, int value) { lua_pushstring(L, key); @@ -998,7 +1002,7 @@ void LuaWidget::refresh() void luaLoadWidgetCallback() { - const char * name=NULL, * options=NULL; + const char * name=NULL; int widgetOptions=0, createFunction=0, refreshFunction=0; luaL_checktype(L, -1, LUA_TTABLE); @@ -1071,6 +1075,7 @@ void luaLoadFiles(const char * directory, void (*callback)()) int pathlen = strlen(path); FRESULT res = f_opendir(&dir, path); /* Open the directory */ + if (res == FR_OK) { path[pathlen++] = '/'; for (;;) { @@ -1078,12 +1083,15 @@ void luaLoadFiles(const char * directory, void (*callback)()) if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ fn = * fno.lfname ? fno.lfname : fno.fname; uint8_t len = strlen(fn); - // Eliminates directories / non wav files + // Eliminates directories / non scripts files if (len < 5 || strcasecmp(fn+len-4, SCRIPTS_EXT) || (fno.fattrib & AM_DIR)) continue; strcpy(&path[pathlen], fn); luaLoadFile(path, callback); } } + else { + TRACE("f_opendir(%s) failed, code=%d", path, res); + } } #endif diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 24bce8ee8..ec1cb8431 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -440,8 +440,7 @@ enum UartModes { char anaNames[NUM_STICKS+NUM_POTS][LEN_ANA_NAME]; \ char currModelFilename[LEN_MODEL_FILENAME+1]; \ uint8_t bluetoothEnable; \ - char bluetoothName[LEN_BLUETOOTH_NAME]; \ - char themeName[8]; + char bluetoothName[LEN_BLUETOOTH_NAME]; #elif defined(PCBFLAMENCO) #define LEN_SWITCH_NAME 3 #define LEN_ANA_NAME 3 @@ -839,7 +838,32 @@ PACK(typedef struct { #define SWITCH_EXISTS(x) true #endif -#define ALTERNATE_VIEW 0x10 +#define ALTERNATE_VIEW 0x10 + +#if defined(COLORLCD) + #include "layout.h" + #include "theme.h" + #include "topbar.h" + #define SWITCHES_WARNING_DATA \ + swarnstate_t switchWarningState; + PACK(typedef struct { + char layoutName[10]; + Layout::PersistentData layoutData; + }) CustomScreenData; + #define CUSTOM_SCREENS_DATA \ + CustomScreenData screenData[MAX_CUSTOM_SCREENS]; \ + Topbar::PersistentData topbarData; + #define THEME_DATA \ + char themeName[8]; \ + Theme::PersistentData themeData; +#else + #define SWITCHES_WARNING_DATA \ + swarnstate_t switchWarningState; \ + swarnenable_t switchWarningEnable; + #define CUSTOM_SCREENS_DATA + #define THEME_DATA +#endif + PACK(typedef struct { uint8_t version; uint16_t variant; @@ -885,6 +909,8 @@ PACK(typedef struct { EXTRA_GENERAL_FIELDS + THEME_DATA + }) EEGeneral; #define SWITCHES_DELAY() uint8_t(15+g_eeGeneral.switchesDelay) @@ -2288,23 +2314,6 @@ enum DisplayTrims DISPLAY_TRIMS_ALWAYS }; -#if defined(COLORLCD) - #include "layout.h" - #define SWITCHES_WARNING_DATA \ - swarnstate_t switchWarningState; - PACK(typedef struct { - char layoutName[10]; - Layout::PersistentData layoutData; - }) CustomScreenData; - #define CUSTOM_SCREENS_DATA \ - CustomScreenData screenData[MAX_CUSTOM_SCREENS]; -#else - #define SWITCHES_WARNING_DATA \ - swarnstate_t switchWarningState; \ - swarnenable_t switchWarningEnable; - #define CUSTOM_SCREENS_DATA -#endif - PACK(typedef struct { ModelHeader header; TimerData timers[MAX_TIMERS]; diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 735a00e0f..e3296cb33 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2469,15 +2469,25 @@ uint16_t stackAvailable() void opentxInit(OPENTX_INIT_ARGS) { +#if defined(DEBUG) && defined(USB_SERIAL) + CoTickDelay(5000); // 10s +#endif + TRACE("opentxInit()"); + sdInit(); + #if defined(COLORLCD) + topbar = new Topbar(&g_model.topbarData); luaInit(); - loadTheme(); #endif storageReadAll(); +#if defined(COLORLCD) + loadTheme(); +#endif + #if defined(CPUARM) if (UNEXPECTED_SHUTDOWN()) { unexpectedShutdown = 1; diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index d45c38de5..db2a904a6 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -352,7 +352,6 @@ long Open9xSim::onTimeout(FXObject*, FXSelector, void*) updateKeysAndSwitches(); #if defined(PCBHORUS) - extern rotenc_t rotencValue; #define ROTENC_VALUE rotencValue #else #define ROTENC_VALUE g_rotenc[0] diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index c865eff4d..1e1bde4e5 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -337,12 +337,17 @@ void * main_thread(void *) menuHandlers[1] = menuModelSelect; #if defined(COLORLCD) + topbar = new Topbar(&g_model.topbarData); luaInit(); - loadTheme(); + // TODO the theme is not initialized, in case of sdcard error, we should have something strange #endif storageReadAll(); // load general setup and selected model +#if defined(COLORLCD) + loadTheme(); +#endif + #if defined(SIMU_DISKIO) f_mount(&g_FATFS_Obj, "", 1); // call sdGetFreeSectors() now because f_getfree() takes a long time first time it's called diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index 0146e2ac4..3d9657fc2 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -222,6 +222,7 @@ uint32_t readTrims(void); #if defined(REV9E) // Rotary Encoder driver +extern int32_t rotencValue; void rotencInit(void); void rotencEnd(void); void checkRotaryEncoder(void); diff --git a/radio/src/tasks_arm.h b/radio/src/tasks_arm.h index b07b5f4d7..d01a516b7 100644 --- a/radio/src/tasks_arm.h +++ b/radio/src/tasks_arm.h @@ -1,25 +1,25 @@ -/* - * Copyright (C) OpenTX - * - * Based on code named - * th9x - http://code.google.com/p/th9x - * er9x - http://code.google.com/p/er9x - * gruvin9x - http://code.google.com/p/gruvin9x - * - * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _TASKS_ARM_H_ -#define _TASKS_ARM_H_ +/* + * Copyright (C) OpenTX + * + * Based on code named + * th9x - http://code.google.com/p/th9x + * er9x - http://code.google.com/p/er9x + * gruvin9x - http://code.google.com/p/gruvin9x + * + * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _TASKS_ARM_H_ +#define _TASKS_ARM_H_ #if !defined(SIMU) extern "C" { @@ -73,4 +73,4 @@ extern TaskStack audioStack; void tasksStart(); -#endif // _TASKS_ARM_H_ +#endif // _TASKS_ARM_H_ diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt index 206019a9e..f17745855 100644 --- a/radio/src/translations/en.h.txt +++ b/radio/src/translations/en.h.txt @@ -942,7 +942,7 @@ #define TR_RESET_TELEMETRY "Reset Telemetry" #define TR_STATISTICS "Statistics" #define TR_ABOUT_US "About" -#define TR_SETUP_SCREENS "Setup screens" +#define TR_SETUP_SCREENS "Setup screens" #define TR_AND_SWITCH "AND Switch" #define TR_SF "SF" #define TR_GF "GF" @@ -951,8 +951,8 @@ #define TR_BYTES "bytes" #define TR_MODULE_BIND BUTTON(TR("Bnd", "Bind")) #define TR_MODULE_RANGE BUTTON(TR("Rng", "Range")) -#define TR_RESET_BTN "[Reset]" -#define TR_SET "[Set]" +#define TR_RESET_BTN BUTTON("Reset") +#define TR_SET BUTTON("Set") #define TR_TRAINER "Trainer Port" #define TR_ANTENNAPROBLEM CENTER "TX Antenna problem!" #define TR_MODELIDUSED TR("ID already used","Model ID already used")