diff --git a/radio/src/audio.cpp b/radio/src/audio.cpp index bbe59ff34..fb8714fda 100644 --- a/radio/src/audio.cpp +++ b/radio/src/audio.cpp @@ -303,7 +303,7 @@ char * getModelAudioPath(char * path) { strcpy(path, SOUNDS_PATH "/"); strncpy(path+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - char * result = strcat_currentmodelname(path+sizeof(SOUNDS_PATH)); + char * result = strcat_currentmodelname(path+sizeof(SOUNDS_PATH), 0); *result++ = '/'; *result = '\0'; return result; diff --git a/radio/src/gui/colorlcd/draw_functions.cpp b/radio/src/gui/colorlcd/draw_functions.cpp index 82536ddde..148b2ae9a 100644 --- a/radio/src/gui/colorlcd/draw_functions.cpp +++ b/radio/src/gui/colorlcd/draw_functions.cpp @@ -504,15 +504,15 @@ void drawHexNumber(BitmapBuffer * dc, coord_t x, coord_t y, uint32_t val, LcdFla } } -void drawTextLines(BitmapBuffer * dc, coord_t left, coord_t top, coord_t width, coord_t height, char * str, LcdFlags flags) +void drawTextLines(BitmapBuffer * dc, coord_t left, coord_t top, coord_t width, coord_t height, const char * str, LcdFlags flags) { coord_t x = left; coord_t y = top; coord_t line = getFontHeight(flags & 0xFFFF); coord_t space = getTextWidth(" ", 1, flags); coord_t word; - char * eos = str + strlen(str); - char * nxt; + const char * eos = str + strlen(str); + const char * nxt; while (str < eos) { nxt = strstr(str, " "); diff --git a/radio/src/gui/colorlcd/draw_functions.h b/radio/src/gui/colorlcd/draw_functions.h index 802310be2..3262bdcf8 100644 --- a/radio/src/gui/colorlcd/draw_functions.h +++ b/radio/src/gui/colorlcd/draw_functions.h @@ -72,7 +72,7 @@ void drawGPSPosition(BitmapBuffer * dc, coord_t x, coord_t y, int32_t longitude, void drawDate(BitmapBuffer * dc, coord_t x, coord_t y, TelemetryItem & telemetryItem, LcdFlags flags = 0); void drawValueWithUnit(BitmapBuffer * dc, coord_t x, coord_t y, int val, uint8_t unit, LcdFlags flags = 0); void drawHexNumber(BitmapBuffer * dc, coord_t x, coord_t y, uint32_t val, LcdFlags flags = 0); -void drawTextLines(BitmapBuffer * dc, coord_t left, coord_t top, coord_t width, coord_t height, char * str, LcdFlags flags); +void drawTextLines(BitmapBuffer * dc, coord_t left, coord_t top, coord_t width, coord_t height, const char * str, LcdFlags flags); inline void drawChn(BitmapBuffer * dc, coord_t x, coord_t y, uint8_t idx, LcdFlags flags) { drawSource(dc, x, y, MIXSRC_CH1 + idx - 1, flags); diff --git a/radio/src/gui/colorlcd/model_mixes.cpp b/radio/src/gui/colorlcd/model_mixes.cpp index 65a4e82b8..9541b6c46 100644 --- a/radio/src/gui/colorlcd/model_mixes.cpp +++ b/radio/src/gui/colorlcd/model_mixes.cpp @@ -26,6 +26,7 @@ #include "model_inputs.h" #include "gvar_numberedit.h" #include "model_curves.h" +#include "dataconstants.h" #define SET_DIRTY() storageDirty(EE_MODEL) @@ -383,7 +384,7 @@ void ModelMixesPage::build(FormWindow * window, int8_t focusMixIndex) int mixIndex = 0; MixData * mix = g_model.mixData; for (uint8_t ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) { - if (mixIndex < MAX_MIXERS && mix->srcRaw > 0 && mix->destCh == ch) { + if (mixIndex < MAX_MIXERS && mix->destCh == ch) { coord_t h = grid.getWindowHeight(); auto txt = new MixLineTitle(window, grid.getLabelSlot(), @@ -391,7 +392,9 @@ void ModelMixesPage::build(FormWindow * window, int8_t focusMixIndex) BUTTON_BACKGROUND, COLOR_THEME_PRIMARY1 | CENTERED); uint8_t count = 0; - while (mixIndex < MAX_MIXERS && mix->srcRaw > 0 && mix->destCh == ch) { + while (mixIndex < MAX_MIXERS && mix->destCh == ch) { + // First mix cannot be empty + if(!mixIndex && !mix->srcRaw) break; Button * button = new MixLineButton(window, grid.getFieldSlot(), mixIndex); button->setPressHandler([=]() -> uint8_t { button->bringToTop(); diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index f601fb88b..a5aea3cf7 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -592,6 +592,9 @@ class TrainerModuleWindow : public FormGroup { new Choice(this, grid.getFieldSlot(3, 2), STR_PPM_POL, 0, 1, GET_SET_DEFAULT(g_model.trainerData.pulsePol )); grid.nextLine(); } +#if defined(PCBNV14) + new StaticText(this, grid.getLabelSlot(true) ); +#endif getParent()->moveWindowsTop(top() + 1, adjustHeight()); } @@ -1432,8 +1435,89 @@ void ModelSetupPage::build(FormWindow * window) } } grid.addWindow(group); + + // Pots and sliders warning +#if NUM_POTS + NUM_SLIDERS + { + new StaticText(window, grid.getLabelSlot(true), STR_POTWARNINGSTATE); + new Choice(window, grid.getFieldSlot(), {"OFF", "ON", "AUTO"}, 0, 2, + GET_SET_DEFAULT(g_model.potsWarnMode)); + grid.nextLine(); + +#if (NUM_POTS) + { + new StaticText(window, grid.getLabelSlot(true), STR_POTWARNING); + auto group = + new FormGroup(window, grid.getFieldSlot(), + FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST); + GridLayout centerGrid(group); + for (int i = POT_FIRST, j = 0; i <= POT_LAST; i++) { + char s[8]; + if ((IS_POT(i) || IS_POT_MULTIPOS(i))) { + if (j > 0 && ((j % 4) == 0)) centerGrid.nextLine(); + + auto button = new TextButton( + group, centerGrid.getSlot(4, j % 4), + getStringAtIndex(s, STR_VSRCRAW, i + 1), nullptr, + OPAQUE | ((g_model.potsWarnEnabled & (1 << j)) ? BUTTON_CHECKED + : 0)); + button->setPressHandler([button, j] { + g_model.potsWarnEnabled ^= (1 << j); + if ((g_model.potsWarnMode == POTS_WARN_MANUAL) && + (g_model.potsWarnEnabled & (1 << j))) { + SAVE_POT_POSITION(j); + } + button->check(g_model.potsWarnEnabled & (1 << j)); + SET_DIRTY(); + return (g_model.potsWarnEnabled & (1 << j)); + }); + j++; + } + } + grid.addWindow(group); + } +#endif + +#if (NUM_SLIDERS) + { + new StaticText(window, grid.getLabelSlot(true), STR_SLIDERWARNING); + auto group = + new FormGroup(window, grid.getFieldSlot(), + FORM_BORDER_FOCUS_ONLY | PAINT_CHILDREN_FIRST); + GridLayout centerGrid(group); + for (int i = SLIDER_FIRST, j = 0; i <= SLIDER_LAST; i++) { + char s[8]; + if ((IS_SLIDER(i))) { + if (j > 0 && ((j % 4) == 0)) centerGrid.nextLine(); + + auto *button = new TextButton( + group, centerGrid.getSlot(4, j % 4), + getStringAtIndex(s, STR_VSRCRAW, i + 1), nullptr, + OPAQUE | ((g_model.potsWarnEnabled & (1 << (j + NUM_POTS))) + ? BUTTON_CHECKED + : 0)); + button->setPressHandler([button, j] { + g_model.potsWarnEnabled ^= (1 << (j + NUM_POTS)); + if ((g_model.potsWarnMode == POTS_WARN_MANUAL) && + (g_model.potsWarnEnabled & (1 << (j + NUM_POTS)))) { + SAVE_POT_POSITION(j + NUM_POTS); + } + button->check(g_model.potsWarnEnabled & (1 << (j + NUM_POTS))); + SET_DIRTY(); + return (g_model.potsWarnEnabled & (1 << (j + NUM_POTS))); + }); + j++; + } + } + grid.addWindow(group); + } +#endif + } + #endif } + grid.nextLine(); + // Center beeps { new StaticText(window, grid.getLabelSlot(false), STR_BEEPCTR, 0, COLOR_THEME_PRIMARY1); @@ -1484,9 +1568,6 @@ void ModelSetupPage::build(FormWindow * window) grid.addWindow(new TrainerModuleWindow(window, {0, grid.getWindowHeight(), LCD_W, 0})); } -#if defined(PCBNV14) - grid.nextLine(); -#endif window->setInnerHeight(grid.getWindowHeight()); } diff --git a/radio/src/gui/colorlcd/switch_warn_dialog.cpp b/radio/src/gui/colorlcd/switch_warn_dialog.cpp index 3c28e7c0d..1520b8298 100644 --- a/radio/src/gui/colorlcd/switch_warn_dialog.cpp +++ b/radio/src/gui/colorlcd/switch_warn_dialog.cpp @@ -42,7 +42,7 @@ bool SwitchWarnDialog::warningInactive() if (!IS_POT_SLIDER_AVAILABLE(POT1 + i)) { continue; } - if (!(g_model.potsWarnEnabled & (1 << i)) && (abs(g_model.potsWarnPosition[i] - GET_LOWRES_POT_POSITION(i)) > 1)) { + if ( (g_model.potsWarnEnabled & (1 << i)) && (abs(g_model.potsWarnPosition[i] - GET_LOWRES_POT_POSITION(i)) > 1)) { warn = true; bad_pots |= (1 << i); } @@ -80,11 +80,11 @@ void SwitchWarnDialog::paint(BitmapBuffer * dc) unsigned int state = ((g_model.switchWarningState >> (3 * i)) & 0x07); if (state && state - 1 != ((switches_states >> (i * 2)) & 0x03)) { if (y < LCD_H) { - x = drawSwitch(dc, x, y, SWSRC_FIRST_SWITCH + i * 3 + state - 1, FONT(BOLD)); + x = drawSwitch(dc, x, y, SWSRC_FIRST_SWITCH + i * 3 + state - 1, COLOR_THEME_PRIMARY1 | FONT(BOLD)); x += 5; } else { - dc->drawText(x, y, "...", FONT(BOLD)); + dc->drawText(x, y, "...", COLOR_THEME_PRIMARY1 | FONT(BOLD)); break; } } @@ -92,22 +92,24 @@ void SwitchWarnDialog::paint(BitmapBuffer * dc) } if (g_model.potsWarnMode) { + x = ALERT_MESSAGE_LEFT; + y += 20; for (int i = 0; i < NUM_POTS + NUM_SLIDERS; i++) { if (!IS_POT_SLIDER_AVAILABLE(POT1 + i)) { continue; } - if (!(g_model.potsWarnEnabled & (1 << i))) { + if ( (g_model.potsWarnEnabled & (1 << i))) { if (abs(g_model.potsWarnPosition[i] - GET_LOWRES_POT_POSITION(i)) > 1) { if (y < LCD_H) { char s[8]; // TODO add an helper strncpy(s, &STR_VSRCRAW[1 + (NUM_STICKS + 1 + i) * STR_VSRCRAW[0]], STR_VSRCRAW[0]); s[int(STR_VSRCRAW[0])] = '\0'; - dc->drawText(x, y, s, COLOR_THEME_WARNING | FONT(XL)); - y += 35; + dc->drawText(x, y, s, COLOR_THEME_PRIMARY1 | FONT(BOLD)); + x += 40; } else { - dc->drawText(x, y, "...", COLOR_THEME_WARNING | FONT(XL)); + dc->drawText(x, y, "...", COLOR_THEME_PRIMARY1 | FONT(BOLD)); } } } diff --git a/radio/src/gui/colorlcd/theme.h b/radio/src/gui/colorlcd/theme.h index 9645a3084..58e262424 100644 --- a/radio/src/gui/colorlcd/theme.h +++ b/radio/src/gui/colorlcd/theme.h @@ -75,7 +75,7 @@ class OpenTxTheme: public Theme void init() const; - virtual void update() const + virtual void update(bool reload = true) const { } diff --git a/radio/src/gui/colorlcd/themes/480_default.cpp b/radio/src/gui/colorlcd/themes/480_default.cpp index 8a09c1eda..234372c8b 100644 --- a/radio/src/gui/colorlcd/themes/480_default.cpp +++ b/radio/src/gui/colorlcd/themes/480_default.cpp @@ -57,85 +57,92 @@ class Theme480: public OpenTxTheme lcdColorTable[CUSTOM_COLOR_INDEX] = RGB(170, 85, 0); } - void loadMenuIcon(uint8_t index, const uint8_t * lbm) const + void loadMenuIcon(uint8_t index, const uint8_t * lbm, bool reload) const { - BitmapBuffer * mask = BitmapBuffer::load8bitMask(lbm); - if (mask) { - delete iconMask[index]; - iconMask[index] = mask; + BitmapBuffer * mask; + + if (reload) { + mask = BitmapBuffer::load8bitMask(lbm); + if (mask) { + delete iconMask[index]; + iconMask[index] = mask; - delete menuIconNormal[index]; - menuIconNormal[index] = new BitmapBuffer(BMP_RGB565, mask->width(), mask->height()); - if (menuIconNormal[index]) { - menuIconNormal[index]->clear(COLOR_THEME_SECONDARY1); - menuIconNormal[index]->drawMask(0, 0, mask, COLOR_THEME_PRIMARY2); - } + delete menuIconNormal[index]; + menuIconNormal[index] = new BitmapBuffer(BMP_RGB565, mask->width(), mask->height()); - delete menuIconSelected[index]; - menuIconSelected[index] = new BitmapBuffer(BMP_RGB565, mask->width(), mask->height()); - if (menuIconSelected[index]) { - menuIconSelected[index]->clear(COLOR_THEME_FOCUS); - menuIconSelected[index]->drawMask(0, 0, mask, COLOR_THEME_PRIMARY2); + delete menuIconSelected[index]; + menuIconSelected[index] = new BitmapBuffer(BMP_RGB565, mask->width(), mask->height()); } + } else + mask = iconMask[index]; + + if (menuIconNormal[index]) { + menuIconNormal[index]->clear(COLOR_THEME_SECONDARY1); + menuIconNormal[index]->drawMask(0, 0, mask, COLOR_THEME_PRIMARY2); + } + + if (menuIconSelected[index]) { + menuIconSelected[index]->clear(COLOR_THEME_FOCUS); + menuIconSelected[index]->drawMask(0, 0, mask, COLOR_THEME_PRIMARY2); } } - void loadIcons() const + void loadIcons(bool reload) const { #if defined(LOG_TELEMETRY) || !defined(WATCHDOG) - loadMenuIcon(ICON_OPENTX, mask_opentx_testmode); + loadMenuIcon(ICON_OPENTX, mask_opentx_testmode, reload); #else - loadMenuIcon(ICON_OPENTX, mask_edgetx); + loadMenuIcon(ICON_OPENTX, mask_edgetx, reload); #endif #if defined(HARDWARE_TOUCH) //TODO: get rid of, and use a real hitbox instead... - loadMenuIcon(ICON_NEXT, mask_next); - loadMenuIcon(ICON_BACK, mask_back); + loadMenuIcon(ICON_NEXT, mask_next, reload); + loadMenuIcon(ICON_BACK, mask_back, reload); #endif - loadMenuIcon(ICON_RADIO, mask_menu_radio); - loadMenuIcon(ICON_RADIO_SETUP, mask_radio_setup); - loadMenuIcon(ICON_RADIO_SD_MANAGER, mask_radio_sd_browser); - loadMenuIcon(ICON_RADIO_TOOLS, mask_radio_tools); - //loadMenuIcon(ICON_RADIO_SPECTRUM_ANALYSER, mask_radio_spectrum_analyser); - loadMenuIcon(ICON_RADIO_GLOBAL_FUNCTIONS, mask_radio_global_functions); - loadMenuIcon(ICON_RADIO_TRAINER, mask_radio_trainer); - loadMenuIcon(ICON_RADIO_HARDWARE, mask_radio_hardware); - loadMenuIcon(ICON_RADIO_CALIBRATION, mask_radio_calibration); - loadMenuIcon(ICON_RADIO_VERSION, mask_radio_version); - loadMenuIcon(ICON_MODEL, mask_menu_model); - loadMenuIcon(ICON_MODEL_SETUP, mask_model_setup); - loadMenuIcon(ICON_MODEL_HELI, mask_model_heli); - loadMenuIcon(ICON_MODEL_FLIGHT_MODES, mask_model_flight_modes); - loadMenuIcon(ICON_MODEL_INPUTS, mask_model_inputs); - loadMenuIcon(ICON_MODEL_MIXER, mask_model_mixer); - loadMenuIcon(ICON_MODEL_NOTES, mask_menu_notes); - loadMenuIcon(ICON_MODEL_OUTPUTS, mask_model_outputs); - loadMenuIcon(ICON_MODEL_CURVES, mask_model_curves); - loadMenuIcon(ICON_MODEL_GVARS, mask_model_gvars); - loadMenuIcon(ICON_MODEL_LOGICAL_SWITCHES, mask_model_logical_switches); - loadMenuIcon(ICON_MODEL_SPECIAL_FUNCTIONS, mask_model_special_functions); - loadMenuIcon(ICON_MODEL_LUA_SCRIPTS, mask_model_lua_scripts); - loadMenuIcon(ICON_MODEL_TELEMETRY, mask_model_telemetry); - loadMenuIcon(ICON_MODEL_SELECT, mask_menu_model_select); - loadMenuIcon(ICON_MODEL_SELECT_CATEGORY, mask_model_select_category); - loadMenuIcon(ICON_STATS, mask_menu_stats); - loadMenuIcon(ICON_STATS_THROTTLE_GRAPH, mask_stats_throttle_graph); - loadMenuIcon(ICON_STATS_TIMERS, mask_stats_timers); - loadMenuIcon(ICON_STATS_ANALOGS, mask_stats_analogs); - loadMenuIcon(ICON_STATS_DEBUG, mask_stats_debug); - loadMenuIcon(ICON_THEME, mask_menu_theme); - loadMenuIcon(ICON_THEME_SETUP, mask_theme_setup); - loadMenuIcon(ICON_THEME_VIEW1, mask_theme_view1); - loadMenuIcon(ICON_THEME_VIEW2, mask_theme_view2); - loadMenuIcon(ICON_THEME_VIEW3, mask_theme_view3); - loadMenuIcon(ICON_THEME_VIEW4, mask_theme_view4); - loadMenuIcon(ICON_THEME_VIEW5, mask_theme_view5); - loadMenuIcon(ICON_THEME_ADD_VIEW, mask_theme_add_view); - loadMenuIcon(ICON_MONITOR, mask_monitor); - loadMenuIcon(ICON_MONITOR_CHANNELS1, mask_monitor_channels1); - loadMenuIcon(ICON_MONITOR_CHANNELS2, mask_monitor_channels2); - loadMenuIcon(ICON_MONITOR_CHANNELS3, mask_monitor_channels3); - loadMenuIcon(ICON_MONITOR_CHANNELS4, mask_monitor_channels4); - loadMenuIcon(ICON_MONITOR_LOGICAL_SWITCHES, mask_monitor_logsw); + loadMenuIcon(ICON_RADIO, mask_menu_radio, reload); + loadMenuIcon(ICON_RADIO_SETUP, mask_radio_setup, reload); + loadMenuIcon(ICON_RADIO_SD_MANAGER, mask_radio_sd_browser, reload); + loadMenuIcon(ICON_RADIO_TOOLS, mask_radio_tools, reload); + //loadMenuIcon(ICON_RADIO_SPECTRUM_ANALYSER, mask_radio_spectrum_analyser, reload); + loadMenuIcon(ICON_RADIO_GLOBAL_FUNCTIONS, mask_radio_global_functions, reload); + loadMenuIcon(ICON_RADIO_TRAINER, mask_radio_trainer, reload); + loadMenuIcon(ICON_RADIO_HARDWARE, mask_radio_hardware, reload); + loadMenuIcon(ICON_RADIO_CALIBRATION, mask_radio_calibration, reload); + loadMenuIcon(ICON_RADIO_VERSION, mask_radio_version, reload); + loadMenuIcon(ICON_MODEL, mask_menu_model, reload); + loadMenuIcon(ICON_MODEL_SETUP, mask_model_setup, reload); + loadMenuIcon(ICON_MODEL_HELI, mask_model_heli, reload); + loadMenuIcon(ICON_MODEL_FLIGHT_MODES, mask_model_flight_modes, reload); + loadMenuIcon(ICON_MODEL_INPUTS, mask_model_inputs, reload); + loadMenuIcon(ICON_MODEL_MIXER, mask_model_mixer, reload); + loadMenuIcon(ICON_MODEL_NOTES, mask_menu_notes, reload); + loadMenuIcon(ICON_MODEL_OUTPUTS, mask_model_outputs, reload); + loadMenuIcon(ICON_MODEL_CURVES, mask_model_curves, reload); + loadMenuIcon(ICON_MODEL_GVARS, mask_model_gvars, reload); + loadMenuIcon(ICON_MODEL_LOGICAL_SWITCHES, mask_model_logical_switches, reload); + loadMenuIcon(ICON_MODEL_SPECIAL_FUNCTIONS, mask_model_special_functions, reload); + loadMenuIcon(ICON_MODEL_LUA_SCRIPTS, mask_model_lua_scripts, reload); + loadMenuIcon(ICON_MODEL_TELEMETRY, mask_model_telemetry, reload); + loadMenuIcon(ICON_MODEL_SELECT, mask_menu_model_select, reload); + loadMenuIcon(ICON_MODEL_SELECT_CATEGORY, mask_model_select_category, reload); + loadMenuIcon(ICON_STATS, mask_menu_stats, reload); + loadMenuIcon(ICON_STATS_THROTTLE_GRAPH, mask_stats_throttle_graph, reload); + loadMenuIcon(ICON_STATS_TIMERS, mask_stats_timers, reload); + loadMenuIcon(ICON_STATS_ANALOGS, mask_stats_analogs, reload); + loadMenuIcon(ICON_STATS_DEBUG, mask_stats_debug, reload); + loadMenuIcon(ICON_THEME, mask_menu_theme, reload); + loadMenuIcon(ICON_THEME_SETUP, mask_theme_setup, reload); + loadMenuIcon(ICON_THEME_VIEW1, mask_theme_view1, reload); + loadMenuIcon(ICON_THEME_VIEW2, mask_theme_view2, reload); + loadMenuIcon(ICON_THEME_VIEW3, mask_theme_view3, reload); + loadMenuIcon(ICON_THEME_VIEW4, mask_theme_view4, reload); + loadMenuIcon(ICON_THEME_VIEW5, mask_theme_view5, reload); + loadMenuIcon(ICON_THEME_ADD_VIEW, mask_theme_add_view, reload); + loadMenuIcon(ICON_MONITOR, mask_monitor, reload); + loadMenuIcon(ICON_MONITOR_CHANNELS1, mask_monitor_channels1, reload); + loadMenuIcon(ICON_MONITOR_CHANNELS2, mask_monitor_channels2, reload); + loadMenuIcon(ICON_MONITOR_CHANNELS3, mask_monitor_channels3, reload); + loadMenuIcon(ICON_MONITOR_CHANNELS4, mask_monitor_channels4, reload); + loadMenuIcon(ICON_MONITOR_LOGICAL_SWITCHES, mask_monitor_logsw, reload); BitmapBuffer * background = BitmapBuffer::load8bitMask(mask_currentmenu_bg); BitmapBuffer * shadow = BitmapBuffer::load8bitMask(mask_currentmenu_shadow); @@ -280,10 +287,11 @@ class Theme480: public OpenTxTheme update(); } - void update() const override + void update(bool reload = true) const override { - loadIcons(); - loadThemeBitmaps(); + loadIcons(reload); + if (reload) + loadThemeBitmaps(); } void drawBackground(BitmapBuffer * dc) const override diff --git a/radio/src/gui/colorlcd/themes/flysky.cpp b/radio/src/gui/colorlcd/themes/flysky.cpp index cb5a8de55..9f91eca05 100644 --- a/radio/src/gui/colorlcd/themes/flysky.cpp +++ b/radio/src/gui/colorlcd/themes/flysky.cpp @@ -278,7 +278,7 @@ class FlyskyTheme: public OpenTxTheme update(); } - virtual void update() const override + virtual void update(bool reload = true) const override { TRACE("TODO THEME::UPDATE()"); diff --git a/radio/src/gui/colorlcd/view_text.cpp b/radio/src/gui/colorlcd/view_text.cpp index 68e8e02cd..4c8fedc1c 100644 --- a/radio/src/gui/colorlcd/view_text.cpp +++ b/radio/src/gui/colorlcd/view_text.cpp @@ -428,15 +428,57 @@ void ViewTextWindow::drawVerticalScrollbar(BitmapBuffer *dc) #include "datastructs.h" +static void replaceSpaceWithUnderscore(std::string& name) +{ + size_t index; + do { + index = name.find(' '); + if(index != std::string::npos) + name[index] = '_'; + } while (index != std::string::npos); +} + +bool openNotes(const char buf[], std::string modelNotesName) +{ + if(isFileAvailable(modelNotesName.c_str())) { + new ViewTextWindow(std::string(buf), modelNotesName, ICON_MODEL); + return true; + } else { + return false; + } +} void readModelNotes() { + bool notesFound = false; LED_ERROR_BEGIN(); std::string modelNotesName(g_model.header.name); modelNotesName.append(TEXT_EXT); const char buf[] = {MODELS_PATH}; f_chdir((TCHAR*)buf); - new ViewTextWindow(std::string(buf), modelNotesName, ICON_MODEL); + + notesFound = openNotes(buf, modelNotesName); + if(!notesFound) { + replaceSpaceWithUnderscore(modelNotesName); + notesFound = openNotes(buf, modelNotesName); + } + +#if !defined(EEPROM) + if(!notesFound) { + modelNotesName.assign(g_eeGeneral.currModelFilename); + size_t index = modelNotesName.find(".bin"); + if(index != std::string::npos) + { + modelNotesName.erase(index); + modelNotesName.append(TEXT_EXT); + notesFound = openNotes(buf, modelNotesName); + } + if(!notesFound) { + replaceSpaceWithUnderscore(modelNotesName); + notesFound = openNotes(buf, modelNotesName); + } + } +#endif LED_ERROR_END(); } \ No newline at end of file diff --git a/radio/src/gui/gui_common.cpp b/radio/src/gui/gui_common.cpp index 4c15aecfa..969e0e623 100644 --- a/radio/src/gui/gui_common.cpp +++ b/radio/src/gui/gui_common.cpp @@ -830,7 +830,13 @@ bool isTrainerModeAvailable(int mode) bool modelHasNotes() { char filename[sizeof(MODELS_PATH)+1+sizeof(g_model.header.name)+sizeof(TEXT_EXT)] = MODELS_PATH "/"; - char *buf = strcat_currentmodelname(&filename[sizeof(MODELS_PATH)]); + char *buf = strcat_currentmodelname(&filename[sizeof(MODELS_PATH)], 0); + strcpy(buf, TEXT_EXT); + if (isFileAvailable(filename)) { + return true; + } + + buf = strcat_currentmodelname(&filename[sizeof(MODELS_PATH)], ' '); strcpy(buf, TEXT_EXT); if (isFileAvailable(filename)) { return true; diff --git a/radio/src/lua/api_colorlcd.cpp b/radio/src/lua/api_colorlcd.cpp index b15adbceb..5213ac6cf 100644 --- a/radio/src/lua/api_colorlcd.cpp +++ b/radio/src/lua/api_colorlcd.cpp @@ -289,6 +289,41 @@ static int luaLcdSizeText(lua_State *L) return 2; } +/*luadoc +@function lcd.drawTextLines(x, y, w, h, text [, flags]) + +Draw text inside rectangle (x,y,w,h) with line breaks + +@param x,y (positive numbers) starting coordinate + +@param w,h (positive numbers) width and height of bounding rectangle + +@param text (string) text to display + +@param flags (optional) please see [Lcd functions overview](../lcd-functions-less-than-greater-than-luadoc-begin-lcd/lcd_functions-overview.html) for drawing flags and colors, and [Appendix](../../part_vii_-_appendix/fonts.md) for available characters in each font set. INVERS and BLINK are not implemented. + +@status current Introduced in 2.5.0 +*/ +static int luaLcdDrawTextLines(lua_State *L) +{ + if (!luaLcdAllowed || !luaLcdBuffer) + return 0; + + int x = luaL_checkinteger(L, 1); + int y = luaL_checkinteger(L, 2); + int w = luaL_checkinteger(L, 3); + int h = luaL_checkinteger(L, 4); + const char * s = luaL_checkstring(L, 5); + LcdFlags flags = luaL_optunsigned(L, 6, 0); + + // apply text offsets, needed to align 2.4.x to 2.3.x font baselines + x += getTextHorizontalOffset(flags); + y += getTextVerticalOffset(flags); + + drawTextLines(luaLcdBuffer, x, y, w, h, s, flags); + return 0; +} + /*luadoc @function lcd.drawTimer(x, y, value [, flags [, inversColor]]) @@ -726,11 +761,12 @@ Please notice that changing theme colors affects not only other Lua widgets, but static int luaLcdSetColor(lua_State *L) { unsigned int index = COLOR_VAL(luaL_checkunsigned(L, 1)); - LcdFlags flags = luaL_checkunsigned(L, 2); + uint16_t color = COLOR_VAL(flagsRGB(luaL_checkunsigned(L, 2))); - if (index < LCD_COLOR_COUNT) { - lcdColorTable[index] = COLOR_VAL(flagsRGB(flags)); - OpenTxTheme::instance()->update(); + if (index < LCD_COLOR_COUNT && lcdColorTable[index] != color) { + lcdColorTable[index] = color; + if (index != CUSTOM_COLOR_INDEX) + OpenTxTheme::instance()->update(false); } return 0; } @@ -1158,6 +1194,7 @@ const luaL_Reg lcdLib[] = { { "drawRectangle", luaLcdDrawRectangle }, { "drawFilledRectangle", luaLcdDrawFilledRectangle }, { "drawText", luaLcdDrawText }, + { "drawTextLines", luaLcdDrawTextLines }, { "sizeText", luaLcdSizeText }, { "drawTimer", luaLcdDrawTimer }, { "drawNumber", luaLcdDrawNumber }, diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp index 118305c4a..1960c4bba 100644 --- a/radio/src/mixer.cpp +++ b/radio/src/mixer.cpp @@ -648,7 +648,11 @@ void evalFlightModeMixes(uint8_t mode, uint8_t tick10ms) MixData * md = mixAddress(i); if (md->srcRaw == 0) +#if defined(COLORLCD) + continue; +#else break; +#endif mixsrc_t stickIndex = md->srcRaw - MIXSRC_Rud; diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 26b7cfe05..1da964969 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1182,13 +1182,13 @@ extern ReusableBuffer reusableBuffer; uint8_t zlen(const char *str, uint8_t size); bool zexist(const char *str, uint8_t size); unsigned int effectiveLen(const char * str, unsigned int size); -char * strcat_zchar(char *dest, const char *name, uint8_t size, const char *defaultName=nullptr, uint8_t defaultNameSize=0, uint8_t defaultIdx=0); -#define strcatFlightmodeName(dest, idx) strcat_zchar(dest, g_model.flightModeData[idx].name, LEN_FLIGHT_MODE_NAME, STR_FM, PSIZE(TR_FM), idx+1) +char * strcat_zchar(char *dest, const char *name, uint8_t size, const char spaceSym = 0, const char *defaultName=nullptr, uint8_t defaultNameSize=0, uint8_t defaultIdx=0); +#define strcatFlightmodeName(dest, idx) strcat_zchar(dest, g_model.flightModeData[idx].name, LEN_FLIGHT_MODE_NAME, 0, STR_FM, PSIZE(TR_FM), idx+1) #if defined(EEPROM) -#define strcat_modelname(dest, idx) strcat_zchar(dest, modelHeaders[idx].name, LEN_MODEL_NAME, STR_MODEL, PSIZE(TR_MODEL), idx+1) -#define strcat_currentmodelname(dest) strcat_modelname(dest, g_eeGeneral.currModel) +#define strcat_modelname(dest, idx) strcat_zchar(dest, modelHeaders[idx].name, LEN_MODEL_NAME, 0, STR_MODEL, PSIZE(TR_MODEL), idx+1) +#define strcat_currentmodelname(dest, foo) strcat_modelname(dest, g_eeGeneral.currModel) #else -#define strcat_currentmodelname(dest) strcat_zchar(dest, g_model.header.name, LEN_MODEL_NAME) +#define strcat_currentmodelname(dest, spaceSym) strcat_zchar(dest, g_model.header.name, LEN_MODEL_NAME, spaceSym) #endif #define ZLEN(s) zlen(s, sizeof(s)) #define ZEXIST(s) zexist(s, sizeof(s)) diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index f5d1d5917..33541282b 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -128,7 +128,7 @@ uint8_t zlen(const char * str, uint8_t size) return 0; } -char * strcat_zchar(char * dest, const char * name, uint8_t size, const char * defaultName, uint8_t defaultNameSize, uint8_t defaultIdx) +char * strcat_zchar(char * dest, const char * name, uint8_t size, const char spaceSym, const char * defaultName, uint8_t defaultNameSize, uint8_t defaultIdx) { int8_t len = 0; @@ -142,7 +142,7 @@ char * strcat_zchar(char * dest, const char * name, uint8_t size, const char * d if (!len && dest[i]) len = i+1; if (len) { - if (!dest[i]) + if (dest[i] == spaceSym) dest[i] = '_'; } i--; diff --git a/radio/src/targets/nv14/board.h b/radio/src/targets/nv14/board.h index 3209b7270..c08564422 100644 --- a/radio/src/targets/nv14/board.h +++ b/radio/src/targets/nv14/board.h @@ -309,6 +309,9 @@ enum Analogs { NUM_ANALOGS }; +#define SLIDER_FIRST 0 +#define SLIDER_LAST -1 + #define DEFAULT_POTS_CONFIG (POT_WITHOUT_DETENT << 0) + (POT_WITHOUT_DETENT << 2) // 2 pots without detent enum CalibratedAnalogs { diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 88ff6b8e7..4d9234835 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 88ff6b8e7152537804497f86202a2b92c17187ad +Subproject commit 4d9234835a4735ab1ff274f3bbdcb59efe8c4e7a