From f2274a042376b768b412edbd1acb5e692c6e4484 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 11 Apr 2021 00:42:36 +0200 Subject: [PATCH 01/54] Moved main screen decoration to ViewMain --- radio/src/gui/colorlcd/layout.cpp | 141 +--- radio/src/gui/colorlcd/layout.h | 10 +- radio/src/gui/colorlcd/layouts/sliders.h | 15 +- radio/src/gui/colorlcd/layouts/trims.cpp | 102 +++ radio/src/gui/colorlcd/layouts/trims.h | 92 +-- radio/src/gui/colorlcd/radio_calibration.cpp | 30 +- radio/src/gui/colorlcd/screens_setup_old.cpp | 690 ------------------- radio/src/gui/colorlcd/topbar.cpp | 5 + radio/src/gui/colorlcd/topbar.h | 2 + radio/src/gui/colorlcd/view_main.cpp | 302 +++++++- radio/src/gui/colorlcd/view_main.h | 43 ++ 11 files changed, 461 insertions(+), 971 deletions(-) create mode 100644 radio/src/gui/colorlcd/layouts/trims.cpp delete mode 100644 radio/src/gui/colorlcd/screens_setup_old.cpp diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index c5bd2f3f9..a56a29684 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -99,7 +99,7 @@ void loadCustomScreens() void Layout::decorate() { - // check if deco setting are still up-to-date + // Check if deco setting are still up-to-date uint8_t checkSettings = (hasTopbar() ? 1 << 0 : 0) | (hasSliders() ? 1 << 1 : 0) | @@ -111,139 +111,20 @@ void Layout::decorate() return; } - // kill all decorations & re-decorate - for (auto deco: decorations) { - deco->deleteLater(); - } - decorations.clear(); - topBar = nullptr; - - // effect a full redraw - invalidate(); - - // save settings + // Save settings decorationSettings = checkSettings; - if (hasTopbar()) { - topBar = new TopBar(this); - topBar->load(); - decorations.push_back(topBar); - } + auto viewMain = ViewMain::instance(); - if (hasSliders()) { -#if defined(HARDWARE_EXT1) || defined(HARDWARE_EXT2) - coord_t yOffset = (hasTrims() ? - TRIM_SQUARE_SIZE : 0) + (hasTopbar() ? TOPBAR_HEIGHT / 2 : 0); -#endif + // Set visible decoration + viewMain->setTopbarVisible(hasTopbar()); + viewMain->setSlidersVisible(hasSliders()); + viewMain->setTrimsVisible(hasTrims()); + viewMain->setFlightModeVisible(hasFlightMode()); - decorations.push_back( - new MainViewHorizontalSlider(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, - [=] { return calibratedAnalogs[CALIBRATED_POT1]; }) - ); - - if (IS_POT_MULTIPOS(POT2)) { - decorations.push_back( - new MainView6POS(this, {LCD_W / 2 - MULTIPOS_W / 2, LCD_H - TRIM_SQUARE_SIZE, MULTIPOS_W + 1, MULTIPOS_H}, - [=] { return (1 + (potsPos[1] & 0x0f)); }) - ); - } - else if (IS_POT(POT2)) { - decorations.push_back( - new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, - [=] { return calibratedAnalogs[CALIBRATED_POT2]; }) - ); - } - -#if defined(HARDWARE_POT3) - decorations.push_back( - new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, - [=] { return calibratedAnalogs[CALIBRATED_POT3]; }) - ); -#endif - -#if defined(HARDWARE_EXT1) - if (IS_POT_SLIDER_AVAILABLE(EXT1)) { - decorations.push_back( - new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(hasTopbar()) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(hasTopbar()) / 2}, - [=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_LEFT]; }) - ); - decorations.push_back( - new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(hasTopbar()) / 2}, - [=] { return calibratedAnalogs[CALIBRATED_POT_EXT1]; }) - ); - } - else { - decorations.push_back( - new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(hasTopbar()) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(hasTopbar())}, - [=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_LEFT]; }) - ); - } -#endif - -#if defined(HARDWARE_EXT2) - if (IS_POT_SLIDER_AVAILABLE(EXT2)) { - decorations.push_back( - new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(hasTopbar()) / 2 + yOffset, TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(hasTopbar()) / 2}, - [=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_RIGHT]; }) - ); - decorations.push_back( - new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(hasTopbar()) / 2}, - [=] { return calibratedAnalogs[CALIBRATED_POT_EXT2]; }) - ); - } - else { - decorations.push_back( - new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(hasTopbar()) / 2 + yOffset, TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(hasTopbar())}, - [=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_RIGHT]; }) - ); - } -#endif - } - - if (hasTrims()) { -#if defined(HARDWARE_POT3) || defined(HARDWARE_EXT1) - coord_t xOffset = hasSliders() ? TRIM_SQUARE_SIZE : 0; -#else - coord_t xOffset = 0; -#endif - coord_t yOffset = (hasTrims() ? - TRIM_SQUARE_SIZE : 0); - - // Trim order TRIM_LH, TRIM_LV, TRIM_RV, TRIM_RH - - // Left - decorations.push_back( - new MainViewHorizontalTrim(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE + yOffset, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, - [=] { return getTrimValue(mixerCurrentFlightMode, 0); }) - ); - - // Right - decorations.push_back( - new MainViewHorizontalTrim(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE + yOffset, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, - [=] { return getTrimValue(mixerCurrentFlightMode, 3); }) - ); - - // Left - decorations.push_back( - new MainViewVerticalTrim(this, {HMARGIN + xOffset, LCD_H /2 - VERTICAL_SLIDERS_HEIGHT(hasTopbar()) / 2 + yOffset + (hasTopbar() ? TOPBAR_HEIGHT / 2 : 0), TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(hasTopbar())}, - [=] { return getTrimValue(mixerCurrentFlightMode, 1); }) - ); - - // Right - decorations.push_back( - new MainViewVerticalTrim(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE - xOffset, LCD_H /2 - VERTICAL_SLIDERS_HEIGHT(hasTopbar()) / 2 + yOffset + (hasTopbar() ? TOPBAR_HEIGHT / 2 : 0), TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(hasTopbar())}, - [=] { return getTrimValue(mixerCurrentFlightMode, 2); }) - ); - } - - if (hasFlightMode()) { - decorations.push_back( - new DynamicText(this, {50, LCD_H - 4 - (hasSliders() ? 2 * TRIM_SQUARE_SIZE: TRIM_SQUARE_SIZE), LCD_W - 100, 20}, [=] { - return g_model.flightModeData[mixerCurrentFlightMode].name; - }, CENTERED) - ); - } + // Re-compute positions + viewMain->adjustDecoration(); + viewMain->invalidate(); } rect_t Layout::getMainZone(rect_t zone) const diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index bdaf18c30..8c0befb1c 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -111,14 +111,14 @@ class Layout: public LayoutBase protected: const LayoutFactory * factory; - TopBar * topBar = nullptr; - uint8_t decorationSettings = 0; - std::list decorations; - // adds trims, sliders, pots, etc... + // Decoration settings bitmask to detect updates + uint8_t decorationSettings = 0; + + // Updates settings for trims, sliders, pots, etc... void decorate(); - // get the Zone rect without decoration + // Get the Zone rect without decoration rect_t getMainZone(rect_t zone) const; }; diff --git a/radio/src/gui/colorlcd/layouts/sliders.h b/radio/src/gui/colorlcd/layouts/sliders.h index 72cc539b4..02857af61 100644 --- a/radio/src/gui/colorlcd/layouts/sliders.h +++ b/radio/src/gui/colorlcd/layouts/sliders.h @@ -32,6 +32,7 @@ constexpr coord_t HMARGIN = 5; constexpr coord_t HORIZONTAL_SLIDERS_WIDTH = SLIDER_TICKS_COUNT * 4 + TRIM_SQUARE_SIZE; constexpr coord_t MULTIPOS_H = 20; constexpr coord_t MULTIPOS_W = 50; + inline coord_t VERTICAL_SLIDERS_HEIGHT(bool topbar) { return topbar ? SLIDER_TICKS_COUNT * 4 + TRIM_SQUARE_SIZE : SLIDER_TICKS_COUNT * 5 + TRIM_SQUARE_SIZE; @@ -40,16 +41,16 @@ inline coord_t VERTICAL_SLIDERS_HEIGHT(bool topbar) class MainViewSlider : public Window { public: - MainViewSlider(Window * parent, const rect_t & rect, std::function getValue): + MainViewSlider(Window * parent, const rect_t & rect, uint8_t idx): Window(parent, rect), - getValue(std::move(getValue)) + idx(idx) { } void checkEvents() override { Window::checkEvents(); - int16_t newValue = getValue(); + int16_t newValue = calibratedAnalogs[idx]; if (value != newValue) { value = newValue; invalidate(); @@ -57,8 +58,8 @@ class MainViewSlider : public Window } protected: - std::function getValue; - int8_t value = 0; + uint8_t idx; + int16_t value = 0; }; class MainViewHorizontalSlider : public MainViewSlider @@ -80,7 +81,6 @@ class MainViewHorizontalSlider : public MainViewSlider } // The square - auto value = - getValue(); x = width() - TRIM_SQUARE_SIZE - divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX); drawTrimSquare(dc, x, 0, TRIM_BGCOLOR); } @@ -102,7 +102,7 @@ class MainView6POS : public MainViewSlider } // The square - auto value = getValue(); + auto value = 1 + (potsPos[idx] & 0x0f); x = TRIM_SQUARE_SIZE / 2 + divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value -1) , 6); drawTrimSquare(dc, x, 0, TRIM_BGCOLOR); dc->drawNumber(x + 1, 0, value, FOCUS_COLOR); @@ -129,7 +129,6 @@ class MainViewVerticalSlider : public MainViewSlider } // The square - auto value = getValue(); y = height() - TRIM_SQUARE_SIZE - divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX); drawTrimSquare(dc, 0, y, TRIM_BGCOLOR); } diff --git a/radio/src/gui/colorlcd/layouts/trims.cpp b/radio/src/gui/colorlcd/layouts/trims.cpp new file mode 100644 index 000000000..013ba9bc6 --- /dev/null +++ b/radio/src/gui/colorlcd/layouts/trims.cpp @@ -0,0 +1,102 @@ +/* + * 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 "trims.h" +#include "opentx.h" + +void MainViewTrim::checkEvents() +{ + Window::checkEvents(); + int8_t newValue = getTrimValue(mixerCurrentFlightMode, idx); + if (value != newValue) { + value = newValue; + invalidate(); + } +} + +void MainViewHorizontalTrim::paint(BitmapBuffer * dc) +{ + int32_t trimMin, trimMax; + if (g_model.extendedTrims) { + trimMin = TRIM_EXTENDED_MIN; + trimMax = TRIM_EXTENDED_MAX; + } + else { + trimMin = TRIM_MIN; + trimMax = TRIM_MAX; + } + + // Trim line + lcdSetColor(GREY); // TODO add a color + dc->drawSolidFilledRect(TRIM_SQUARE_SIZE / 2, (height() - TRIM_LINE_WIDTH - 1) / 2, width() - TRIM_SQUARE_SIZE + 1, TRIM_LINE_WIDTH, CUSTOM_COLOR); + + // Trim square + coord_t x = divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value - trimMin), trimMax - trimMin); + drawTrimSquare(dc, x, 0, (value < TRIM_MIN || value > TRIM_MAX) ? HIGHLIGHT_COLOR /* TODO add a color */ : TRIM_BGCOLOR); + + // Trim value / small lines on the square + if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS) { + // TODO DISPLAY_TRIMS_CHANGE + dc->drawNumber(x + (TRIM_SQUARE_SIZE + 1) / 2, 3, divRoundClosest(value * 100, trimMax), FONT(XXS) | FOCUS_COLOR | CENTERED); + } + else { + if (value >= 0) { + dc->drawSolidVerticalLine(x + 4, 3, 9, FOCUS_COLOR); + } + if (value <= 0) { + dc->drawSolidVerticalLine(x + 10, 3, 9, FOCUS_COLOR); + } + } +} + +void MainViewVerticalTrim::paint(BitmapBuffer * dc) +{ + int32_t trimMin, trimMax; + if (g_model.extendedTrims) { + trimMin = TRIM_EXTENDED_MIN; + trimMax = TRIM_EXTENDED_MAX; + } + else { + trimMin = TRIM_MIN; + trimMax = TRIM_MAX; + } + + // Trim line + lcdSetColor(GREY); // TODO add a color + dc->drawSolidFilledRect((width() - TRIM_LINE_WIDTH) / 2, TRIM_SQUARE_SIZE / 2, TRIM_LINE_WIDTH, height() - TRIM_SQUARE_SIZE + 1, CUSTOM_COLOR); + + // Trim square + coord_t y = height() - TRIM_SQUARE_SIZE - divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value - trimMin), trimMax - trimMin); + drawTrimSquare(dc, 0, y, (value < TRIM_MIN || value > TRIM_MAX) ? HIGHLIGHT_COLOR /* TODO add a color */ : TRIM_BGCOLOR); + + // Trim value / small lines on the square + if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS) { + // TODO DISPLAY_TRIMS_CHANGE + dc->drawNumber((TRIM_SQUARE_SIZE + 1) / 2, y + 3, divRoundClosest(value * 100, trimMax), FONT(XXS) | FOCUS_COLOR | CENTERED); + } + else { + if (value >= 0) { + dc->drawSolidHorizontalLine(3, y + 4, 9, FOCUS_COLOR); + } + if (value <= 0) { + dc->drawSolidHorizontalLine(3, y + 10, 9, FOCUS_COLOR); + } + } +} diff --git a/radio/src/gui/colorlcd/layouts/trims.h b/radio/src/gui/colorlcd/layouts/trims.h index 9d090c498..ba8326f71 100644 --- a/radio/src/gui/colorlcd/layouts/trims.h +++ b/radio/src/gui/colorlcd/layouts/trims.h @@ -25,25 +25,17 @@ class MainViewTrim : public Window { public: - MainViewTrim(Window * parent, const rect_t & rect, std::function getValue): + MainViewTrim(Window * parent, const rect_t & rect, uint8_t idx): Window(parent, rect), - getValue(std::move(getValue)) + idx(idx) { } - void checkEvents() override - { - Window::checkEvents(); - int8_t newValue = getValue(); - if (value != newValue) { - value = newValue; - invalidate(); - } - } + void checkEvents() override; protected: - std::function getValue; - int8_t value = 0; + uint8_t idx; + int value = 0; }; class MainViewHorizontalTrim : public MainViewTrim @@ -51,41 +43,7 @@ class MainViewHorizontalTrim : public MainViewTrim public: using MainViewTrim::MainViewTrim; - void paint(BitmapBuffer * dc) override - { - int32_t trimMin, trimMax; - if (g_model.extendedTrims) { - trimMin = TRIM_EXTENDED_MIN; - trimMax = TRIM_EXTENDED_MAX; - } - else { - trimMin = TRIM_MIN; - trimMax = TRIM_MAX; - } - - // Trim line - lcdSetColor(GREY); // TODO add a color - dc->drawSolidFilledRect(TRIM_SQUARE_SIZE / 2, (height() - TRIM_LINE_WIDTH - 1) / 2, width() - TRIM_SQUARE_SIZE + 1, TRIM_LINE_WIDTH, CUSTOM_COLOR); - - // Trim square - auto value = getValue(); - coord_t x = divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value - trimMin), trimMax - trimMin); - drawTrimSquare(dc, x, 0, (value < TRIM_MIN || value > TRIM_MAX) ? HIGHLIGHT_COLOR /* TODO add a color */ : TRIM_BGCOLOR); - - // Trim value / small lines on the square - if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS) { - // TODO DISPLAY_TRIMS_CHANGE - dc->drawNumber(x + (TRIM_SQUARE_SIZE + 1) / 2, 3, divRoundClosest(value * 100, trimMax), FONT(XXS) | FOCUS_COLOR | CENTERED); - } - else { - if (value >= 0) { - dc->drawSolidVerticalLine(x + 4, 3, 9, FOCUS_COLOR); - } - if (value <= 0) { - dc->drawSolidVerticalLine(x + 10, 3, 9, FOCUS_COLOR); - } - } - } + void paint(BitmapBuffer * dc) override; }; class MainViewVerticalTrim : public MainViewTrim @@ -93,39 +51,5 @@ class MainViewVerticalTrim : public MainViewTrim public: using MainViewTrim::MainViewTrim; - void paint(BitmapBuffer * dc) override - { - int32_t trimMin, trimMax; - if (g_model.extendedTrims) { - trimMin = TRIM_EXTENDED_MIN; - trimMax = TRIM_EXTENDED_MAX; - } - else { - trimMin = TRIM_MIN; - trimMax = TRIM_MAX; - } - - // Trim line - lcdSetColor(GREY); // TODO add a color - dc->drawSolidFilledRect((width() - TRIM_LINE_WIDTH) / 2, TRIM_SQUARE_SIZE / 2, TRIM_LINE_WIDTH, height() - TRIM_SQUARE_SIZE + 1, CUSTOM_COLOR); - - // Trim square - auto value = getValue(); - coord_t y = height() - TRIM_SQUARE_SIZE - divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value - trimMin), trimMax - trimMin); - drawTrimSquare(dc, 0, y, (value < TRIM_MIN || value > TRIM_MAX) ? HIGHLIGHT_COLOR /* TODO add a color */ : TRIM_BGCOLOR); - - // Trim value / small lines on the square - if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS) { - // TODO DISPLAY_TRIMS_CHANGE - dc->drawNumber((TRIM_SQUARE_SIZE + 1) / 2, y + 3, divRoundClosest(value * 100, trimMax), FONT(XXS) | FOCUS_COLOR | CENTERED); - } - else { - if (value >= 0) { - dc->drawSolidHorizontalLine(3, y + 4, 9, FOCUS_COLOR); - } - if (value <= 0) { - dc->drawSolidHorizontalLine(3, y + 10, 9, FOCUS_COLOR); - } - } - } -}; \ No newline at end of file + void paint(BitmapBuffer * dc) override; +}; diff --git a/radio/src/gui/colorlcd/radio_calibration.cpp b/radio/src/gui/colorlcd/radio_calibration.cpp index 527a040f2..b83f5b0a2 100644 --- a/radio/src/gui/colorlcd/radio_calibration.cpp +++ b/radio/src/gui/colorlcd/radio_calibration.cpp @@ -83,28 +83,25 @@ void RadioCalibrationPage::buildBody(FormWindow * window) #if defined(PCBHORUS) - new MainViewHorizontalSlider(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, - [=] { return calibratedAnalogs[CALIBRATED_POT1]; }); + new MainViewHorizontalSlider(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, CALIBRATED_POT1); if (IS_POT_MULTIPOS(POT2)) { - new MainView6POS(this, {LCD_W / 2 - MULTIPOS_W / 2, LCD_H - TRIM_SQUARE_SIZE, MULTIPOS_W + 1, MULTIPOS_H}, - [=] { return (1 + (potsPos[1] & 0x0f)); }); + new MainView6POS(this, {LCD_W / 2 - MULTIPOS_W / 2, LCD_H - TRIM_SQUARE_SIZE, MULTIPOS_W + 1, MULTIPOS_H}, 1); } - new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, - [=] { return calibratedAnalogs[CALIBRATED_POT3]; }); + new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, CALIBRATED_POT3); #if defined(HARDWARE_EXT1) coord_t yOffset = TOPBAR_HEIGHT / 2; if (IS_POT_SLIDER_AVAILABLE(EXT1)) { new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true) / 2}, - [=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_LEFT]; }); + CALIBRATED_SLIDER_REAR_LEFT); new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true) / 2}, - [=] { return calibratedAnalogs[CALIBRATED_POT_EXT1]; }); + CALIBRATED_POT_EXT1); } else { new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true)}, - [=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_LEFT]; }); + CALIBRATED_SLIDER_REAR_LEFT); } #endif @@ -112,23 +109,22 @@ void RadioCalibrationPage::buildBody(FormWindow * window) if (IS_POT_SLIDER_AVAILABLE(EXT2)) { new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true) / 2}, - [=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_RIGHT]; }); + CALIBRATED_SLIDER_REAR_RIGHT); new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true) / 2}, - [=] { return calibratedAnalogs[CALIBRATED_POT_EXT2]; }); + CALIBRATED_POT_EXT2); } else { new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true)}, - [=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_RIGHT]; }); + CALIBRATED_SLIDER_REAR_RIGHT); } #endif -#elif defined(PCBNV14) - new MainViewHorizontalSlider(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, - [=] { return calibratedAnalogs[CALIBRATED_POT1]; }); - new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, - [=] { return calibratedAnalogs[CALIBRATED_POT2]; }); +#elif defined(PCBNV14) + new MainViewHorizontalSlider(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, CALIBRATED_POT1); + + new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, CALIBRATED_POT2); new TextButton(window, {LCD_W - 120, LCD_H - 140, 90, 40}, "Next", [=]() -> uint8_t { diff --git a/radio/src/gui/colorlcd/screens_setup_old.cpp b/radio/src/gui/colorlcd/screens_setup_old.cpp deleted file mode 100644 index cc12cc312..000000000 --- a/radio/src/gui/colorlcd/screens_setup_old.cpp +++ /dev/null @@ -1,690 +0,0 @@ -/* - * 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" - -uint8_t THEME_ICONS[] = { - ICON_THEME, - ICON_THEME_SETUP, - ICON_THEME_VIEW1, - ICON_THEME_VIEW2, - ICON_THEME_VIEW3, - ICON_THEME_VIEW4, - ICON_THEME_VIEW5, - ICON_THEME_ADD_VIEW, -}; - -Layout * currentScreen; -WidgetsContainerInterface * currentContainer; -Widget * currentWidget; -uint8_t currentZone; -bool widgetNeedsSettings; - -#define SCREENS_SETUP_2ND_COLUMN 200 - -char fileSelection[LEN_ZONE_OPTION_STRING]; -uint8_t fileSelectionDone; - -int updateMainviewsMenu(); -bool menuScreenAdd(event_t event); -void onScreenSetupMenu(const char * result); - -void onZoneOptionFileSelectionMenu(const char * result) -{ - if (result == STR_UPDATE_LIST) { - if (!sdListFiles(BITMAPS_PATH, BITMAPS_EXT, LEN_ZONE_OPTION_STRING, nullptr)) { - POPUP_WARNING(STR_NO_BITMAPS_ON_SD); - } - } - else if (result != STR_EXIT) { - fileSelectionDone = true; - memcpy(fileSelection, result, sizeof(fileSelection)); - } -} - -uint8_t getZoneOptionColumns(const ZoneOption * option) -{ - if (option->type == ZoneOption::Color) { - return uint8_t(2 | NAVIGATION_LINE_BY_LINE); - } - else { - return 0; - } -} - -uint8_t editColorPart(coord_t x, coord_t y, event_t event, uint8_t part, uint8_t value, LcdFlags attr, uint32_t i_flags) -{ - const char * STR_COLOR_PARTS = "\002" "R:" "G:" "B:"; - uint8_t PART_BITS[] = { 5, 6, 5 }; - lcdDrawTextAtIndex(x, y, STR_COLOR_PARTS, part, (attr && menuHorizontalPosition < 0) ? FOCUS_COLOR : DEFAULT_COLOR); - lcdDrawNumber(x + 20, y, value << (8-PART_BITS[part]), LEFT|DEFAULT_COLOR|((attr && (menuHorizontalPosition < 0 || menuHorizontalPosition == part)) ? attr : DEFAULT_COLOR)); - if (attr && menuHorizontalPosition == part) { - value = checkIncDec(event, value, 0, (1 << PART_BITS[part])-1, i_flags); - } - return value; -} - -bool editZoneOption(coord_t y, const ZoneOption * option, ZoneOptionValue * value, LcdFlags attr, uint32_t i_flags, event_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); // TODO always does storageDirty(EE_MODEL) - } - else if (option->type == ZoneOption::Integer) { - lcdDrawNumber(SCREENS_SETUP_2ND_COLUMN, y, value->signedValue, attr | LEFT); - if (attr) { - CHECK_INCDEC_MODELVAR(event, value->signedValue, option->min.signedValue, option->max.signedValue); // TODO i_flags - } - } - else if (option->type == ZoneOption::String) { - 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_FIRST(KEY_ENTER)) { - s_editMode = 0; - if (sdListFiles(BITMAPS_PATH, BITMAPS_EXT, sizeof(value->stringValue), value->stringValue, LIST_NONE_SD_FILE)) { - fileSelectionDone = false; - POPUP_MENU_START(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, STR_TEXT_SIZE, value->unsignedValue, attr); - if (attr) { - 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); - if (attr) { - value->unsignedValue = checkIncDec(event, value->unsignedValue, 0, MAX_TIMERS - 1, i_flags); - } - } - else if (option->type == ZoneOption::Source) { - drawSource(SCREENS_SETUP_2ND_COLUMN, y, value->unsignedValue, attr); - if (attr) { - CHECK_INCDEC_MODELSOURCE(event, value->unsignedValue, 1, MIXSRC_LAST_TELEM); - } - } - else if (option->type == ZoneOption::Color) { - RGB_SPLIT(value->unsignedValue, r, g, b); - - if (attr && menuHorizontalPosition < 0) { - lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN-3, y-1, 230, FH+1, FOCUS_BGCOLOR); - } - - lcdSetColor(value->unsignedValue); - lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN-1, y+1, 42, 17, DEFAULT_COLOR); - lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN, y+2, 40, 15, CUSTOM_COLOR); - - r = editColorPart(SCREENS_SETUP_2ND_COLUMN + 50, y, event, 0, r, attr, i_flags); - g = editColorPart(SCREENS_SETUP_2ND_COLUMN + 110, y, event, 1, g, attr, i_flags); - b = editColorPart(SCREENS_SETUP_2ND_COLUMN + 170, y, event, 2, b, attr, i_flags); - - if (attr && checkIncDec_Ret) { - value->unsignedValue = RGB_JOIN(r, g, b); - } - } - - return (attr && checkIncDec_Ret); -} - -int getOptionsCount(const ZoneOption * options) -{ - if (options == nullptr) { - return 0; - } - else { - int count = 0; - for (const ZoneOption * option = options; option->name; option++) { - count++; - } - return count; - } -} - -template -bool menuSettings(const char * title, T * object, uint32_t i_flags, event_t event) -{ - - if (object->getErrorMessage()) { - // display error instead of widget settings - // TODO nicer display (proper word-wrap) - SIMPLE_SUBMENU("Widget Error", ICON_MODEL_LUA_SCRIPTS, 1); - int len = strlen(object->getErrorMessage()); - int y = 3*FH; - const char * p = object->getErrorMessage(); - while (len > 0) { - lcdDrawSizedText(MENUS_MARGIN_LEFT, y, p, 30); - p += 30; - y += FH; - len -= 30; - } - return true; - } - - const ZoneOption * options = object->getOptions(); - linesCount = getOptionsCount(options); - uint8_t mstate_tab[MAX_WIDGET_OPTIONS]; - for (int i=0; i0) ? BLINK|INVERS : INVERS); - LcdFlags attr = (menuVerticalPosition == k ? blink : 0); - if (k < linesCount) { - const ZoneOption * option = &options[k]; - ZoneOptionValue * value = object->getOptionValue(k); - if (editZoneOption(y, option, value, attr, i_flags, event)) { - object->update(); - } - } - } - - return true; -} - -bool menuWidgetSettings(event_t event) -{ - return menuSettings(STR_WIDGET_SETTINGS, currentWidget, EE_MODEL, event); -} - -bool menuWidgetChoice(event_t event) -{ - static Widget * previousWidget = nullptr; - static Widget * currentWidget = nullptr; - static std::list::const_iterator iterator; - static Widget::PersistentData tempData; - - switch (event) { - case EVT_ENTRY: - { - previousWidget = currentContainer->getWidget(currentZone); - currentContainer->setWidget(currentZone, nullptr); - iterator = getRegisteredWidgets().cbegin(); - if (previousWidget) { - const WidgetFactory * factory = previousWidget->getFactory(); - std::list::const_iterator it = getRegisteredWidgets().cbegin(); - for (; it != getRegisteredWidgets().cend(); ++it) { - if (factory->getName() == (*it)->getName()) { - iterator = it; - break; - } - } - } - if (iterator != getRegisteredWidgets().cend()) - currentWidget = (*iterator)->create(currentContainer->getZone(currentZone), &tempData); - break; - } - - case EVT_KEY_FIRST(KEY_EXIT): - if (previousWidget) { - if (currentWidget) - delete currentWidget; - currentContainer->setWidget(currentZone, previousWidget); - } - popMenu(); - return false; - - case EVT_KEY_FIRST(KEY_ENTER): - if (iterator != getRegisteredWidgets().cend()) { - if (previousWidget) - delete previousWidget; - currentContainer->createWidget(currentZone, *iterator); - widgetNeedsSettings = currentContainer->getWidget(currentZone)->getFactory()->getOptions(); - storageDirty(EE_MODEL); - } - popMenu(); - return false; - - case EVT_ROTARY_RIGHT: - if (iterator != getRegisteredWidgets().cend() && iterator != --getRegisteredWidgets().cend()) { - ++iterator; - if (currentWidget) - delete currentWidget; - currentWidget = (*iterator)->create(currentContainer->getZone(currentZone), &tempData); - } - break; - - case EVT_ROTARY_LEFT: - if (iterator != getRegisteredWidgets().cbegin()) { - --iterator; - if (currentWidget) - delete currentWidget; - currentWidget = (*iterator)->create(currentContainer->getZone(currentZone), &tempData); - } - break; - } - - currentScreen->refresh(); - - Zone zone = currentContainer->getZone(currentZone); - lcdDrawFilledRect(0, 0, zone.x-2, LCD_H, SOLID, OVERLAY_COLOR | OPACITY(8)); - lcdDrawFilledRect(zone.x+zone.w+2, 0, LCD_W-zone.x-zone.w-2, LCD_H, SOLID, OVERLAY_COLOR | OPACITY(8)); - lcdDrawFilledRect(zone.x-2, 0, zone.w+4, zone.y-2, SOLID, OVERLAY_COLOR | OPACITY(8)); - lcdDrawFilledRect(zone.x-2, zone.y+zone.h+2, zone.w+4, LCD_H-zone.y-zone.h-2, SOLID, OVERLAY_COLOR | OPACITY(8)); - - if (currentWidget) - currentWidget->refresh(); - - if (iterator != getRegisteredWidgets().cbegin()) { - lcdDrawBitmapPattern(zone.x-10, zone.y+zone.h/2-10, LBM_SWIPE_CIRCLE, FOCUS_BGCOLOR); - lcdDrawBitmapPattern(zone.x-10, zone.y+zone.h/2-10, LBM_SWIPE_LEFT, FOCUS_COLOR); - } - if (iterator != --getRegisteredWidgets().cend()) { - lcdDrawBitmapPattern(zone.x+zone.w-9, zone.y+zone.h/2-10, LBM_SWIPE_CIRCLE, FOCUS_BGCOLOR); - lcdDrawBitmapPattern(zone.x+zone.w-9, zone.y+zone.h/2-10, LBM_SWIPE_RIGHT, FOCUS_COLOR); - } - if (currentWidget) - lcdDrawText(zone.x + zone.w, zone.y-1, currentWidget->getFactory()->getName(), RIGHT | DEFAULT_COLOR | FONT(XS) | INVERS); - - return true; -} - -void onZoneMenu(const char * result) -{ - if (result == STR_SELECT_WIDGET) { - pushMenu(menuWidgetChoice); - } - else if (result == STR_WIDGET_SETTINGS) { - pushMenu(menuWidgetSettings); - } - else if (result == STR_REMOVE_WIDGET) { - currentContainer->createWidget(currentZone, nullptr); - storageDirty(EE_MODEL); - } -} - -bool menuWidgetsSetup(event_t event) -{ - switch (event) { - case EVT_ENTRY: - menuVerticalPosition = 0; - break; - case EVT_KEY_FIRST(KEY_EXIT): - killEvents(KEY_EXIT); - popMenu(); - return false; - } - - currentScreen->refresh(); - - for (int i = currentContainer->getZonesCount() - 1; i >= 0; i--) { - Zone zone = currentContainer->getZone(i); - LcdFlags color; - int padding, thickness; - if (currentContainer == topbar) { - color = MENU_COLOR; - padding = 2; - thickness = 1; - } - else { - color = FOCUS_BGCOLOR; - padding = 4; - thickness = 2; - } - if (menuVerticalPosition == i) { - lcdDrawSolidRect(zone.x-padding, zone.y-padding, zone.w+2*padding, zone.h+2*padding, thickness, color); - if (event == EVT_KEY_FIRST(KEY_ENTER)) { - killEvents(KEY_ENTER); - currentZone = menuVerticalPosition; - currentWidget = currentContainer->getWidget(menuVerticalPosition); - if (currentWidget) { - POPUP_MENU_ADD_ITEM(STR_SELECT_WIDGET); - if (currentWidget->getFactory()->getOptions()) - POPUP_MENU_ADD_ITEM(STR_WIDGET_SETTINGS); - POPUP_MENU_ADD_ITEM(STR_REMOVE_WIDGET); - POPUP_MENU_START(onZoneMenu); - } - else { - onZoneMenu(STR_SELECT_WIDGET); - } - } - } - else { - if (widgetNeedsSettings) { - currentWidget = currentContainer->getWidget(menuVerticalPosition); - if (currentWidget) { - widgetNeedsSettings = false; - onZoneMenu(STR_WIDGET_SETTINGS); - } - } - lcdDrawRect(zone.x-padding, zone.y-padding, zone.w+2*padding, zone.h+2*padding, thickness, 0x3F, color); - } - } - navigate(event, currentContainer->getZonesCount(), currentContainer->getZonesCount(), 1); - return true; -} - -template -T * editThemeChoice(coord_t x, coord_t y, std::list & elList, T * current, bool needsOffsetCheck, LcdFlags attr, event_t event) -{ - static uint8_t menuHorizontalOffset = 0; - uint8_t elCount = elList.size(), last, idx; - coord_t pos; - int currentIndex = 0; - typename std::list::const_iterator elItr = elList.cbegin(); - - if (!elCount) - return nullptr; - - for (; elItr != elList.cend(); ++elItr, ++currentIndex) { - if ((*elItr) == current) - break; - } - - if (event == EVT_ENTRY) { - menuHorizontalOffset = 0; - needsOffsetCheck = true; - } - - if (needsOffsetCheck) { - if (currentIndex < menuHorizontalOffset) { - menuHorizontalOffset = currentIndex; - } - else if (currentIndex > menuHorizontalOffset + 3) { - menuHorizontalOffset = currentIndex - 3; - } - } - if (attr) { - if (menuHorizontalPosition < 0) { - lcdDrawSolidFilledRect(x-3, y-1, min(4, elCount)*56+1, 2*FH-5, FOCUS_BGCOLOR); - } - else { - if (needsOffsetCheck) { - menuHorizontalPosition = currentIndex; - } - else if (menuHorizontalPosition < menuHorizontalOffset) { - menuHorizontalOffset = menuHorizontalPosition; - } - else if (menuHorizontalPosition > menuHorizontalOffset + 3) { - menuHorizontalOffset = menuHorizontalPosition - 3; - } - } - } - last = min(menuHorizontalOffset + 4, elCount); - idx = menuHorizontalOffset; - pos = x; - elItr = elList.cbegin(); - std::advance(elItr, min(menuHorizontalOffset, elCount - 1)); - for (; idx < last && elItr != elList.cend(); ++idx, ++elItr, pos += 56) { - (*elItr)->drawThumb(pos, y+1, current == (*elItr) ? ((attr && menuHorizontalPosition < 0) ? FOCUS_COLOR : FOCUS_BGCOLOR) : LINE_COLOR); - } - if (elCount > 4) { - lcdDrawBitmapPattern(x - 12, y+1, LBM_CARROUSSEL_LEFT, menuHorizontalOffset > 0 ? LINE_COLOR : DISABLE_COLOR); - lcdDrawBitmapPattern(x + 4 * 56, y+1, LBM_CARROUSSEL_RIGHT, last < getRegisteredLayouts().size() ? LINE_COLOR : DISABLE_COLOR); - } - if (attr && menuHorizontalPosition >= 0) { - lcdDrawSolidRect(x + (menuHorizontalPosition - menuHorizontalOffset) * 56 - 3, y - 1, 57, 35, 1, FOCUS_BGCOLOR); - if (event == EVT_KEY_FIRST(KEY_ENTER)) { - s_editMode = 0; - elItr = elList.cbegin(); - if (menuHorizontalPosition < (int)elList.size()) - std::advance(elItr, menuHorizontalPosition); - if (elItr != elList.cend()) - return (*elItr); - else - return nullptr; - } - } - return nullptr; -} - -enum menuScreensThemeItems { - ITEM_SCREEN_SETUP_THEME, - ITEM_SCREEN_SETUP_THEME_OPTION1 = ITEM_SCREEN_SETUP_THEME+2 -}; - -bool menuScreensTheme(event_t event) -{ - bool needsOffsetCheck = (menuVerticalPosition != 0 || menuHorizontalPosition < 0); - const ZoneOption * options = theme->getOptions(); - int optionsCount = getOptionsCount(options); - linesCount = ITEM_SCREEN_SETUP_THEME_OPTION1 + optionsCount + 1; - - menuPageCount = updateMainviewsMenu(); - uint8_t mstate_tab[2 + MAX_THEME_OPTIONS + 1] = { uint8_t(NAVIGATION_LINE_BY_LINE | uint8_t(getRegisteredThemes().size()-1)), ORPHAN_ROW }; - for (int i=0; i 0) ? BLINK | INVERS : INVERS); - LcdFlags attr = (menuVerticalPosition == k ? blink : 0); - switch (k) { - case ITEM_SCREEN_SETUP_THEME: { - lcdDrawText(MENUS_MARGIN_LEFT, y + FH / 2, STR_THEME); - Theme * new_theme = editThemeChoice(SCREENS_SETUP_2ND_COLUMN, y, getRegisteredThemes(), theme, needsOffsetCheck, attr, event); - if (new_theme) { - new_theme->init(); - loadTheme(new_theme); - strncpy(g_eeGeneral.themeName, new_theme->getName(), sizeof(g_eeGeneral.themeName)); - killEvents(KEY_ENTER); - storageDirty(EE_GENERAL); - } - break; - } - - case ITEM_SCREEN_SETUP_THEME+1: - break; - - default: - { - uint8_t index = k - ITEM_SCREEN_SETUP_THEME_OPTION1; - if (index < optionsCount) { - const ZoneOption * option = &options[index]; - ZoneOptionValue * value = theme->getOptionValue(index); - bool ret = editZoneOption(y, option, value, attr, EE_GENERAL, event); - if (option->type == ZoneOption::Color) { - if (attr && event == EVT_KEY_FIRST(KEY_EXIT)) { - theme->update(); - } - } - else if (ret) { - theme->update(); - } - } - else if (index == optionsCount) { - lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TOP_BAR); - drawButton(SCREENS_SETUP_2ND_COLUMN, y, STR_SETUP, attr); - if (attr && event == EVT_KEY_FIRST(KEY_ENTER)) { - currentScreen = customScreens[0]; - currentContainer = topbar; - pushMenu(menuWidgetsSetup); - } - } - break; - } - } - } - - return true; -} - -enum MenuScreenSetupItems { - ITEM_SCREEN_SETUP_LAYOUT, - ITEM_SCREEN_SETUP_WIDGETS_SETUP = ITEM_SCREEN_SETUP_LAYOUT+2, - ITEM_SCREEN_SETUP_LAYOUT_OPTION1, -}; - -bool menuScreenSetup(int index, event_t event) -{ - if (customScreens[index] == nullptr) { - return menuScreenAdd(event); - } - - currentScreen = customScreens[index]; - currentContainer = currentScreen; - bool needsOffsetCheck = (menuVerticalPosition != 0 || menuHorizontalPosition < 0); - - char title[] = TR_MAIN_VIEW_X; - title[sizeof(title)-2] = '1' + index; - menuPageCount = updateMainviewsMenu(); - - const ZoneOption * options = currentScreen->getFactory()->getOptions(); - int optionsCount = getOptionsCount(options); - linesCount = ITEM_SCREEN_SETUP_LAYOUT_OPTION1 + optionsCount; - if (menuPageCount > 3) - ++linesCount; - - uint8_t mstate_tab[2 + MAX_LAYOUT_OPTIONS + 1] = { uint8_t(NAVIGATION_LINE_BY_LINE | uint8_t(getRegisteredLayouts().size()-1)), ORPHAN_ROW }; - for (int i=0; i0) ? BLINK|INVERS : INVERS); - LcdFlags attr = (menuVerticalPosition == k ? blink : 0); - switch(k) { - case ITEM_SCREEN_SETUP_LAYOUT: - { - lcdDrawText(MENUS_MARGIN_LEFT, y + FH / 2, STR_LAYOUT); - const LayoutFactory * factory = editThemeChoice(SCREENS_SETUP_2ND_COLUMN, y, getRegisteredLayouts(), currentScreen->getFactory(), needsOffsetCheck, attr, event); - if (factory) { - delete customScreens[index]; - currentScreen = customScreens[index] = factory->create(&g_model.screenData[index].layoutData); - strncpy(g_model.screenData[index].layoutName, factory->getName(), sizeof(g_model.screenData[index].layoutName)); - killEvents(KEY_ENTER); - storageDirty(EE_MODEL); - } - break; - } - - case ITEM_SCREEN_SETUP_LAYOUT+1: - break; - - case ITEM_SCREEN_SETUP_WIDGETS_SETUP: - drawButton(SCREENS_SETUP_2ND_COLUMN, y, STR_SETUP_WIDGETS, attr); - if (attr && event == EVT_KEY_FIRST(KEY_ENTER)) { - pushMenu(menuWidgetsSetup); - } - break; - - default: - { - uint8_t o = k - ITEM_SCREEN_SETUP_LAYOUT_OPTION1; - if (o < optionsCount) { - const ZoneOption * option = &options[o]; - ZoneOptionValue * value = currentScreen->getOptionValue(o); - if (editZoneOption(y, option, value, attr, EE_MODEL, event)) { - currentScreen->update(); - loadCustomScreens(); - } - } - else if (menuPageCount > 3 && o == optionsCount) { - drawButton(SCREENS_SETUP_2ND_COLUMN, y, STR_REMOVE_SCREEN, attr); - if (attr && event == EVT_KEY_LONG(KEY_ENTER)) { - delete currentScreen; - if (index != MAX_CUSTOM_SCREENS-1) { - memmove(&g_model.screenData[index], &g_model.screenData[index + 1], sizeof(CustomScreenData) * (MAX_CUSTOM_SCREENS - index - 1)); - memmove(&customScreens[index], &customScreens[index + 1], sizeof(Layout *) * (MAX_CUSTOM_SCREENS - index - 1)); - } - memset(&g_model.screenData[MAX_CUSTOM_SCREENS-1], 0, sizeof(CustomScreenData)); - customScreens[MAX_CUSTOM_SCREENS-1] = nullptr; - loadCustomScreens(); - killEvents(KEY_ENTER); - chainMenu(menuTabScreensSetup[index > 0 ? index : 1]); - return false; - } - } - break; - } - } - } - - return true; -} - -template -bool menuCustomScreenSetup(event_t event) -{ - return menuScreenSetup(N, event); -} - -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); - strncpy(g_model.screenData[menuPageCount-2].layoutName, lf->getName(), sizeof(g_model.screenData[menuPageCount-2].layoutName)); - s_editMode = 0; - menuHorizontalPosition = -1; - killEvents(KEY_ENTER); - storageDirty(EE_MODEL); - return false; - } - - SIMPLE_MENU_WITH_OPTIONS(STR_ADD_MAIN_VIEW, THEME_ICONS, menuTabScreensSetup, menuPageCount, menuPageCount-1, 0); - return true; -} diff --git a/radio/src/gui/colorlcd/topbar.cpp b/radio/src/gui/colorlcd/topbar.cpp index cbe773a1e..7224f5e5d 100644 --- a/radio/src/gui/colorlcd/topbar.cpp +++ b/radio/src/gui/colorlcd/topbar.cpp @@ -41,6 +41,11 @@ rect_t TopBar::getZone(unsigned int index) const }; } +void TopBar::setVisible(bool visible) +{ + setHeight(visible ? TOPBAR_HEIGHT : 0); +} + const char * const STR_MONTHS[] = TR_MONTHS; void TopBar::paint(BitmapBuffer * dc) diff --git a/radio/src/gui/colorlcd/topbar.h b/radio/src/gui/colorlcd/topbar.h index 7a566dd0f..34aac2b69 100644 --- a/radio/src/gui/colorlcd/topbar.h +++ b/radio/src/gui/colorlcd/topbar.h @@ -38,6 +38,8 @@ class TopBar: public WidgetsContainer rect_t getZone(unsigned int index) const override; + void setVisible(bool visible); + void paint(BitmapBuffer * dc) override; void checkEvents() override diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index a8c817951..f74fe4ad2 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -22,30 +22,16 @@ #include "menu_model.h" #include "menu_radio.h" #include "menu_screen.h" -// #include "menu_screens.h" #include "model_select.h" #include "view_channels.h" #include "view_statistics.h" +#include "topbar.h" +#include "layouts/sliders.h" +#include "layouts/trims.h" #include "opentx.h" Layout * customScreens[MAX_CUSTOM_SCREENS] = {}; -void onMainViewMenu(const char *result) -{ - /*if (result == STR_VIEW_NOTES) { - pushModelNotes(); - } - else if (result == STR_STATISTICS) { - pushMenu(menuTabStats[0]); - } - else if (result == STR_ABOUT_US) { - chainMenu(menuAboutView); - } - else if (result == STR_MONITOR_SCREENS) { - pushMenu(menuTabMonitors[lastMonitorPage]); - }*/ -} - int getMainViewsCount() { for (int index=1; index uint8_t { @@ -87,7 +72,7 @@ ViewMain::ViewMain(): return 0; }, NO_FOCUS); #endif - + createDecoration(); focusWindow = this; } @@ -95,6 +80,72 @@ ViewMain::~ViewMain() { } +void ViewMain::setTopbarVisible(bool visible) +{ + topbar->setVisible(visible); +} + +void ViewMain::setTrimsVisible(bool visible) +{ + trims[TRIMS_LH]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + trims[TRIMS_RH]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + + trims[TRIMS_LV]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + trims[TRIMS_RV]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); +} + +void ViewMain::setSlidersVisible(bool visible) +{ + // + // Horizontal Sliders + // + sliders[SLIDERS_POT1]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + + //TODO: might change depending on hardware settings + if (IS_POT_MULTIPOS(POT2)) { + sliders[SLIDERS_POT2]->setHeight(visible ? MULTIPOS_H : 0); + } + else if (IS_POT(POT2)) { + sliders[SLIDERS_POT2]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + } + +#if defined(HARDWARE_POT3) + sliders[SLIDERS_POT3]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); +#endif + + // + // Vertical sliders + // + sliders[SLIDERS_REAR_LEFT]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + +#if defined(HARDWARE_EXT1) + //TODO: might change depending on hardware settings + if (IS_POT_SLIDER_AVAILABLE(EXT1)) { + sliders[SLIDERS_EXT1]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + } +#endif + + sliders[SLIDERS_REAR_RIGHT]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + +#if defined(HARDWARE_EXT2) + //TODO: might change depending on hardware settings + if (IS_POT_SLIDER_AVAILABLE(EXT2)) { + sliders[SLIDERS_EXT2]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + } +#endif +} + +void ViewMain::setFlightModeVisible(bool visible) +{ + flightMode->setHeight(visible ? 20 : 0); +} + +void ViewMain::adjustDecoration() +{ + // TODO: + // -> re-compute all the components' positions +} + #if defined(HARDWARE_KEYS) void ViewMain::onEvent(event_t event) { @@ -169,27 +220,204 @@ void ViewMain::paint(BitmapBuffer * dc) if (g_model.view >= getMainViewsCount()) { g_model.view = 0; } -// -// for (uint8_t i=0; irefresh(); } -// else -// customScreens[i]->background(); -// } -// } } -#if 0 -bool menuMainViewChannelsMonitor(event_t event) +void ViewMain::createDecoration() { - switch (event) { - case EVT_KEY_BREAK(KEY_EXIT): - chainMenu(menuMainView); - event = 0; - return false; + createTopbar(); + createSliders(); + createTrims(); + createFlightMode(); +} + +void ViewMain::createTopbar() +{ + topbar = new TopBar(this); + topbar->load(); +} + +void ViewMain::createSliders() +{ + // TODO: + // - layout must become really dynamic (see adjustDecoration()) + // - components should be created in "folded" state + // - it should not be required to call hasXXXX() at all + +#if defined(HARDWARE_EXT1) || defined(HARDWARE_EXT2) + coord_t yOffset = /*(hasTrims() ?*/ - TRIM_SQUARE_SIZE /*: 0)*/ + /*(hasTopbar() ?*/ TOPBAR_HEIGHT / 2 /*: 0)*/; +#endif + + // fixed size array, so that works + memset(sliders, 0, sizeof(sliders)); + + rect_t r = { + HMARGIN, + LCD_H - TRIM_SQUARE_SIZE, + HORIZONTAL_SLIDERS_WIDTH, + TRIM_SQUARE_SIZE + }; + + sliders[SLIDERS_POT1] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT1); + + if (IS_POT_MULTIPOS(POT2)) { + + r = rect_t { + LCD_W / 2 - MULTIPOS_W / 2, + LCD_H - TRIM_SQUARE_SIZE, + MULTIPOS_W + 1, + MULTIPOS_H + }; + + sliders[SLIDERS_POT2] = new MainView6POS(this, r, 1); + } + else if (IS_POT(POT2)) { + + r = { + LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, + LCD_H - TRIM_SQUARE_SIZE, + HORIZONTAL_SLIDERS_WIDTH, + TRIM_SQUARE_SIZE + }; + + sliders[SLIDERS_POT2] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT2); } - return menuChannelsView(event); -} +#if defined(HARDWARE_POT3) + r = rect_t { + LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, + LCD_H - TRIM_SQUARE_SIZE, + HORIZONTAL_SLIDERS_WIDTH, + TRIM_SQUARE_SIZE + }; + + sliders[SLIDERS_POT3] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT3); #endif + +#if defined(HARDWARE_EXT1) + if (IS_POT_SLIDER_AVAILABLE(EXT1)) { + r = rect_t { + HMARGIN, + LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset, + TRIM_SQUARE_SIZE, + VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + }; + + sliders[SLIDERS_REAR_LEFT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_LEFT); + + r = rect_t { + HMARGIN, + LCD_H / 2 + yOffset, + TRIM_SQUARE_SIZE, + VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + }; + + sliders[SLIDERS_EXT1] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT1); + } + else { + r = rect_t { + HMARGIN, + LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset, + TRIM_SQUARE_SIZE, + VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) + }; + + sliders[SLIDERS_REAR_LEFT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_LEFT); + } +#endif + +#if defined(HARDWARE_EXT2) + if (IS_POT_SLIDER_AVAILABLE(EXT2)) { + r = rect_t { + LCD_W - HMARGIN - TRIM_SQUARE_SIZE, + LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset, + TRIM_SQUARE_SIZE, + VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + }; + + sliders[SLIDERS_REAR_RIGHT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_RIGHT); + + r = rect_t { + LCD_W - HMARGIN - TRIM_SQUARE_SIZE, + LCD_H / 2 + yOffset, + TRIM_SQUARE_SIZE, + VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + }; + + sliders[SLIDERS_EXT2] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT2); + } + else { + r = rect_t { + LCD_W - HMARGIN - TRIM_SQUARE_SIZE, + LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset, + TRIM_SQUARE_SIZE, + VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) + }; + + sliders[SLIDERS_REAR_RIGHT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_RIGHT); + } +#endif +} + +void ViewMain::createTrims() +{ +#if defined(HARDWARE_POT3) || defined(HARDWARE_EXT1) + coord_t xOffset = /*hasSliders() ?*/ TRIM_SQUARE_SIZE /*: 0*/; +#else + coord_t xOffset = 0; +#endif + coord_t yOffset = /*hasTrims() ?*/ - TRIM_SQUARE_SIZE /*: 0)*/; + + // Trim order TRIM_LH, TRIM_LV, TRIM_RV, TRIM_RH + + rect_t r = { + HMARGIN, + LCD_H - TRIM_SQUARE_SIZE + yOffset, + HORIZONTAL_SLIDERS_WIDTH, + TRIM_SQUARE_SIZE + }; + + trims[TRIMS_LH] = new MainViewHorizontalTrim(this, r, 0); + + r = rect_t { + LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, + LCD_H - TRIM_SQUARE_SIZE + yOffset, + HORIZONTAL_SLIDERS_WIDTH, + TRIM_SQUARE_SIZE + }; + + trims[TRIMS_RH] = new MainViewHorizontalTrim(this, r, 3); + + r = rect_t { + HMARGIN + xOffset, + LCD_H /2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset + /*(hasTopbar() ?*/ TOPBAR_HEIGHT / 2 /*: 0)*/, + TRIM_SQUARE_SIZE, + VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) + }; + + trims[TRIMS_LV] = new MainViewVerticalTrim(this, r, 1); + + r = rect_t { + LCD_W - HMARGIN - TRIM_SQUARE_SIZE - xOffset, + LCD_H /2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset + /*(hasTopbar() ?*/ TOPBAR_HEIGHT / 2 /*: 0)*/, + TRIM_SQUARE_SIZE, + VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) + }; + + trims[TRIMS_RV] = new MainViewVerticalTrim(this, r, 2); +} + +void ViewMain::createFlightMode() +{ + rect_t r = { + 50, + LCD_H - 4 - /*(hasSliders() ?*/ 2 * TRIM_SQUARE_SIZE /*: TRIM_SQUARE_SIZE)*/, + LCD_W - 100, + 20 + }; + + std::function getFM = []() -> std::string { + return g_model.flightModeData[mixerCurrentFlightMode].name; + }; + + flightMode = new DynamicText(this, r, getFM, CENTERED); +} diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 69243fa48..2f5231a32 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -22,6 +22,9 @@ #define _VIEW_MAIN_H_ #include "form.h" +#include + +class TopBar; class ViewMain: public FormWindow { @@ -46,14 +49,54 @@ class ViewMain: public FormWindow } #endif + // Set decoration visibility + void setTopbarVisible(bool visible); + void setTrimsVisible(bool visible); + void setSlidersVisible(bool visible); + void setFlightModeVisible(bool visible); + + // Re-calculate positions + void adjustDecoration(); + protected: static ViewMain * _instance; + enum { + SLIDERS_POT1 = 0, + SLIDERS_POT2, + SLIDERS_POT3, + SLIDERS_REAR_LEFT, + SLIDERS_EXT1, + SLIDERS_REAR_RIGHT, + SLIDERS_EXT2, + SLIDERS_MAX + }; + + enum { + TRIMS_LH = 0, + TRIMS_LV, + TRIMS_RV, + TRIMS_RH, + TRIMS_MAX + }; + + TopBar* topbar; + Window* sliders[SLIDERS_MAX]; + Window* trims[TRIMS_MAX]; + Window* flightMode; + #if defined(HARDWARE_KEYS) void onEvent(event_t event) override; #endif void paint(BitmapBuffer * dc) override; + void openMenu(); + + void createDecoration(); + void createTopbar(); + void createSliders(); + void createTrims(); + void createFlightMode(); }; #endif // _VIEW_MAIN_H_ From 19ab22e1a4b32603606bbadc47e35feaab231413 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 11 Apr 2021 10:25:16 +0200 Subject: [PATCH 02/54] Dynamic layout for main screen decorations --- radio/src/gui/colorlcd/layouts/sliders.h | 6 +- radio/src/gui/colorlcd/radio_calibration.cpp | 16 +- radio/src/gui/colorlcd/topbar.cpp | 2 +- radio/src/gui/colorlcd/view_main.cpp | 231 +++++++++---------- 4 files changed, 118 insertions(+), 137 deletions(-) diff --git a/radio/src/gui/colorlcd/layouts/sliders.h b/radio/src/gui/colorlcd/layouts/sliders.h index 02857af61..eae8b23bf 100644 --- a/radio/src/gui/colorlcd/layouts/sliders.h +++ b/radio/src/gui/colorlcd/layouts/sliders.h @@ -32,11 +32,7 @@ constexpr coord_t HMARGIN = 5; constexpr coord_t HORIZONTAL_SLIDERS_WIDTH = SLIDER_TICKS_COUNT * 4 + TRIM_SQUARE_SIZE; constexpr coord_t MULTIPOS_H = 20; constexpr coord_t MULTIPOS_W = 50; - -inline coord_t VERTICAL_SLIDERS_HEIGHT(bool topbar) -{ - return topbar ? SLIDER_TICKS_COUNT * 4 + TRIM_SQUARE_SIZE : SLIDER_TICKS_COUNT * 5 + TRIM_SQUARE_SIZE; -} +constexpr coord_t VERTICAL_SLIDERS_HEIGHT = SLIDER_TICKS_COUNT * 4 + TRIM_SQUARE_SIZE; class MainViewSlider : public Window { diff --git a/radio/src/gui/colorlcd/radio_calibration.cpp b/radio/src/gui/colorlcd/radio_calibration.cpp index b83f5b0a2..e7e0d933e 100644 --- a/radio/src/gui/colorlcd/radio_calibration.cpp +++ b/radio/src/gui/colorlcd/radio_calibration.cpp @@ -94,29 +94,29 @@ void RadioCalibrationPage::buildBody(FormWindow * window) coord_t yOffset = TOPBAR_HEIGHT / 2; if (IS_POT_SLIDER_AVAILABLE(EXT1)) { - new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true) / 2}, + new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT / 2}, CALIBRATED_SLIDER_REAR_LEFT); - new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true) / 2}, + new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT / 2}, CALIBRATED_POT_EXT1); } else { - new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true)}, + new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT}, CALIBRATED_SLIDER_REAR_LEFT); } #endif #if defined(HARDWARE_EXT2) if (IS_POT_SLIDER_AVAILABLE(EXT2)) { - new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true) / 2}, + new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT / 2 + yOffset, TRIM_SQUARE_SIZE, + VERTICAL_SLIDERS_HEIGHT / 2}, CALIBRATED_SLIDER_REAR_RIGHT); new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true) / 2}, + VERTICAL_SLIDERS_HEIGHT / 2}, CALIBRATED_POT_EXT2); } else { - new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true)}, + new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT / 2 + yOffset, TRIM_SQUARE_SIZE, + VERTICAL_SLIDERS_HEIGHT}, CALIBRATED_SLIDER_REAR_RIGHT); } #endif diff --git a/radio/src/gui/colorlcd/topbar.cpp b/radio/src/gui/colorlcd/topbar.cpp index 7224f5e5d..ed9d92a7f 100644 --- a/radio/src/gui/colorlcd/topbar.cpp +++ b/radio/src/gui/colorlcd/topbar.cpp @@ -43,7 +43,7 @@ rect_t TopBar::getZone(unsigned int index) const void TopBar::setVisible(bool visible) { - setHeight(visible ? TOPBAR_HEIGHT : 0); + setHeight(visible ? MENU_HEADER_HEIGHT : 0); } const char * const STR_MONTHS[] = TR_MONTHS; diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index f74fe4ad2..c415746d8 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -85,15 +85,6 @@ void ViewMain::setTopbarVisible(bool visible) topbar->setVisible(visible); } -void ViewMain::setTrimsVisible(bool visible) -{ - trims[TRIMS_LH]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); - trims[TRIMS_RH]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); - - trims[TRIMS_LV]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); - trims[TRIMS_RV]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); -} - void ViewMain::setSlidersVisible(bool visible) { // @@ -135,6 +126,15 @@ void ViewMain::setSlidersVisible(bool visible) #endif } +void ViewMain::setTrimsVisible(bool visible) +{ + trims[TRIMS_LH]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + trims[TRIMS_RH]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + + trims[TRIMS_LV]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + trims[TRIMS_RV]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); +} + void ViewMain::setFlightModeVisible(bool visible) { flightMode->setHeight(visible ? 20 : 0); @@ -142,8 +142,84 @@ void ViewMain::setFlightModeVisible(bool visible) void ViewMain::adjustDecoration() { - // TODO: - // -> re-compute all the components' positions + // Topbar does not need any computation + // (height() has been set in setTopbarVisible()) + + // Sliders are closer to the edge and must be computed then + // (vertical sliders depends on topbar) + + // These are located on the bottom + auto pos = height() - sliders[SLIDERS_POT1]->height(); + sliders[SLIDERS_POT1]->setTop(pos); + + if (sliders[SLIDERS_POT2]) { + auto sl = sliders[SLIDERS_POT2]; + sl->setTop(pos); + if (IS_POT_MULTIPOS(POT2)) { + sl->setWidth(MULTIPOS_W); + } + else { // if !IS_POT(POT2) -> sliders[SLIDERS_POT2] == nullptr + sl->setWidth(HORIZONTAL_SLIDERS_WIDTH); + } + sl->setLeft((width() - sl->width()) / 2); + } + +#if defined(HARDWARE_POT3) + sliders[SLIDERS_POT3]->setTop(pos); +#endif + + // Left side (vertical) + pos = left(); + sliders[SLIDERS_REAR_LEFT]->setLeft(pos); + sliders[SLIDERS_REAR_LEFT]->setTop(topbar->bottom()); +#if defined(HARDWARE_EXT1) + sliders[SLIDERS_EXT1]->setLeft(pos); + if (IS_POT_SLIDER_AVAILABLE(EXT1)) { + auto rl = sliders[SLIDERS_REAR_LEFT]; + auto e1 = sliders[SLIDERS_EXT1]; + rl->setHeight(VERTICAL_SLIDERS_HEIGHT / 2); + e1->setTop(topbar->bottom() + rl->height()); + e1->setHeight(rl->height()); + } + else { + auto rl = sliders[SLIDERS_REAR_LEFT]; + auto e1 = sliders[SLIDERS_EXT1]; + rl->setHeight(VERTICAL_SLIDERS_HEIGHT); + e1->setHeight(0); + } +#endif + + // Right side (vertical) + pos = right() - sliders[SLIDERS_REAR_RIGHT]->width(); + sliders[SLIDERS_REAR_RIGHT]->setLeft(pos); + sliders[SLIDERS_REAR_RIGHT]->setTop(topbar->bottom()); +#if defined(HARDWARE_EXT2) + sliders[SLIDERS_EXT2]->setLeft(pos); + if (IS_POT_SLIDER_AVAILABLE(EXT2)) { + auto rr = sliders[SLIDERS_REAR_RIGHT]; + auto e2 = sliders[SLIDERS_EXT2]; + rr->setHeight(VERTICAL_SLIDERS_HEIGHT / 2); + e2->setTop(topbar->bottom() + rr->height()); + e2->setHeight(rr->height()); + } + else { + auto rr = sliders[SLIDERS_REAR_RIGHT]; + auto e2 = sliders[SLIDERS_EXT2]; + rr->setHeight(VERTICAL_SLIDERS_HEIGHT); + e2->setHeight(0); + } +#endif + + // Trims are last as they are located more on the inside + // (depend on everything else) + + pos = sliders[SLIDERS_POT1]->top() - TRIM_SQUARE_SIZE; + trims[TRIMS_LH]->setTop(pos); + trims[TRIMS_RH]->setTop(pos); + trims[TRIMS_LV]->setLeft(sliders[SLIDERS_REAR_LEFT]->right()); + trims[TRIMS_LV]->setTop(topbar->bottom()); + trims[TRIMS_RV]->setLeft(sliders[SLIDERS_REAR_RIGHT]->left() - trims[TRIMS_RV]->width()); + trims[TRIMS_RV]->setTop(topbar->bottom()); } #if defined(HARDWARE_KEYS) @@ -243,166 +319,75 @@ void ViewMain::createSliders() // - components should be created in "folded" state // - it should not be required to call hasXXXX() at all -#if defined(HARDWARE_EXT1) || defined(HARDWARE_EXT2) - coord_t yOffset = /*(hasTrims() ?*/ - TRIM_SQUARE_SIZE /*: 0)*/ + /*(hasTopbar() ?*/ TOPBAR_HEIGHT / 2 /*: 0)*/; -#endif - // fixed size array, so that works memset(sliders, 0, sizeof(sliders)); rect_t r = { - HMARGIN, - LCD_H - TRIM_SQUARE_SIZE, - HORIZONTAL_SLIDERS_WIDTH, - TRIM_SQUARE_SIZE + // left + HMARGIN, 0, + HORIZONTAL_SLIDERS_WIDTH, 0 }; sliders[SLIDERS_POT1] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT1); + r = rect_t { 0, 0, 0, 0 }; if (IS_POT_MULTIPOS(POT2)) { - - r = rect_t { - LCD_W / 2 - MULTIPOS_W / 2, - LCD_H - TRIM_SQUARE_SIZE, - MULTIPOS_W + 1, - MULTIPOS_H - }; - sliders[SLIDERS_POT2] = new MainView6POS(this, r, 1); } else if (IS_POT(POT2)) { - - r = { - LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, - LCD_H - TRIM_SQUARE_SIZE, - HORIZONTAL_SLIDERS_WIDTH, - TRIM_SQUARE_SIZE - }; - sliders[SLIDERS_POT2] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT2); } #if defined(HARDWARE_POT3) r = rect_t { - LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, - LCD_H - TRIM_SQUARE_SIZE, - HORIZONTAL_SLIDERS_WIDTH, - TRIM_SQUARE_SIZE + // right + width() - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, 0, + HORIZONTAL_SLIDERS_WIDTH, 0 }; sliders[SLIDERS_POT3] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT3); #endif + r = rect_t { 0, 0, 0, 0 }; + sliders[SLIDERS_REAR_LEFT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_LEFT); + sliders[SLIDERS_REAR_RIGHT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_RIGHT); + #if defined(HARDWARE_EXT1) - if (IS_POT_SLIDER_AVAILABLE(EXT1)) { - r = rect_t { - HMARGIN, - LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset, - TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 - }; - - sliders[SLIDERS_REAR_LEFT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_LEFT); - - r = rect_t { - HMARGIN, - LCD_H / 2 + yOffset, - TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 - }; - - sliders[SLIDERS_EXT1] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT1); - } - else { - r = rect_t { - HMARGIN, - LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset, - TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) - }; - - sliders[SLIDERS_REAR_LEFT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_LEFT); - } + sliders[SLIDERS_EXT1] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT1); #endif #if defined(HARDWARE_EXT2) - if (IS_POT_SLIDER_AVAILABLE(EXT2)) { - r = rect_t { - LCD_W - HMARGIN - TRIM_SQUARE_SIZE, - LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset, - TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 - }; - - sliders[SLIDERS_REAR_RIGHT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_RIGHT); - - r = rect_t { - LCD_W - HMARGIN - TRIM_SQUARE_SIZE, - LCD_H / 2 + yOffset, - TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 - }; - - sliders[SLIDERS_EXT2] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT2); - } - else { - r = rect_t { - LCD_W - HMARGIN - TRIM_SQUARE_SIZE, - LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset, - TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) - }; - - sliders[SLIDERS_REAR_RIGHT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_RIGHT); - } + sliders[SLIDERS_EXT2] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT2); #endif } void ViewMain::createTrims() { -#if defined(HARDWARE_POT3) || defined(HARDWARE_EXT1) - coord_t xOffset = /*hasSliders() ?*/ TRIM_SQUARE_SIZE /*: 0*/; -#else - coord_t xOffset = 0; -#endif - coord_t yOffset = /*hasTrims() ?*/ - TRIM_SQUARE_SIZE /*: 0)*/; - // Trim order TRIM_LH, TRIM_LV, TRIM_RV, TRIM_RH rect_t r = { - HMARGIN, - LCD_H - TRIM_SQUARE_SIZE + yOffset, - HORIZONTAL_SLIDERS_WIDTH, - TRIM_SQUARE_SIZE + left() + HMARGIN, 0, + HORIZONTAL_SLIDERS_WIDTH, 0 }; trims[TRIMS_LH] = new MainViewHorizontalTrim(this, r, 0); r = rect_t { - LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, - LCD_H - TRIM_SQUARE_SIZE + yOffset, - HORIZONTAL_SLIDERS_WIDTH, - TRIM_SQUARE_SIZE + right() - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, 0, + HORIZONTAL_SLIDERS_WIDTH, 0 }; trims[TRIMS_RH] = new MainViewHorizontalTrim(this, r, 3); r = rect_t { - HMARGIN + xOffset, - LCD_H /2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset + /*(hasTopbar() ?*/ TOPBAR_HEIGHT / 2 /*: 0)*/, - TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) + 0, 0, 0, + VERTICAL_SLIDERS_HEIGHT }; + r.x = left() + HMARGIN + TRIM_SQUARE_SIZE; // DBG trims[TRIMS_LV] = new MainViewVerticalTrim(this, r, 1); - r = rect_t { - LCD_W - HMARGIN - TRIM_SQUARE_SIZE - xOffset, - LCD_H /2 - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) / 2 + yOffset + /*(hasTopbar() ?*/ TOPBAR_HEIGHT / 2 /*: 0)*/, - TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT(true/*hasTopbar()*/) - }; - + r.x = right() - HMARGIN - TRIM_SQUARE_SIZE; // DBG trims[TRIMS_RV] = new MainViewVerticalTrim(this, r, 2); } From ad845a5d6b39114df5e9874333fc8b8e2c9b6c91 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 11 Apr 2021 11:33:38 +0200 Subject: [PATCH 03/54] Main screen deco layout fine tuning / fixes. --- radio/src/gui/colorlcd/CMakeLists.txt | 8 ++++ radio/src/gui/colorlcd/colors.h | 4 ++ radio/src/gui/colorlcd/view_main.cpp | 54 +++++++++++++++++---------- 3 files changed, 47 insertions(+), 19 deletions(-) diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index 9a2c1db3a..e7b0674f9 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -95,10 +95,18 @@ set(SRC storage/modelslist.cpp ) + +option(WINDOWS_INSPECT_BORDERS "Draw bounding boxes around windows" OFF) +if(WINDOWS_INSPECT_BORDERS) + add_definitions(-DWINDOWS_INSPECT_BORDERS) +endif() + # includes libopenui include(${RADIO_SRC_DIR}/thirdparty/libopenui/src/CMakeLists.txt) include_directories(gui/libopenui) + add_definitions(-DLIBOPENUI) + foreach(LIBOPENUI_FILE ${LIBOPENUI_SRC}) set(SRC ${SRC} thirdparty/libopenui/src/${LIBOPENUI_FILE}) endforeach() diff --git a/radio/src/gui/colorlcd/colors.h b/radio/src/gui/colorlcd/colors.h index 0e4156979..eaf1dd473 100644 --- a/radio/src/gui/colorlcd/colors.h +++ b/radio/src/gui/colorlcd/colors.h @@ -67,4 +67,8 @@ #define SCROLLBOX_COLOR COLOR(SCROLLBOX_COLOR_INDEX) #define BATTERY_CHARGE_COLOR COLOR(BATTERY_CHARGE_COLOR_INDEX) +#if defined(WINDOWS_INSPECT_BORDERS) + #define WINDOWS_INSPECT_BORDER_COLOR LINE_COLOR +#endif + #endif // _COLORS_H_ diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index c415746d8..c27536f92 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -145,7 +145,7 @@ void ViewMain::adjustDecoration() // Topbar does not need any computation // (height() has been set in setTopbarVisible()) - // Sliders are closer to the edge and must be computed then + // Sliders are closer to the edge and must be computed first // (vertical sliders depends on topbar) // These are located on the bottom @@ -168,22 +168,36 @@ void ViewMain::adjustDecoration() sliders[SLIDERS_POT3]->setTop(pos); #endif + // Horizontal trims are on top of horizontal sliders + pos -= trims[TRIMS_LH]->height(); + trims[TRIMS_LH]->setTop(pos); + trims[TRIMS_RH]->setTop(pos); + + // Vertical trims/slider are on top of horizontal sliders with a small margin + auto vertTop = pos - HMARGIN - VERTICAL_SLIDERS_HEIGHT; + // Left side (vertical) pos = left(); sliders[SLIDERS_REAR_LEFT]->setLeft(pos); - sliders[SLIDERS_REAR_LEFT]->setTop(topbar->bottom()); + sliders[SLIDERS_REAR_LEFT]->setTop(vertTop); + #if defined(HARDWARE_EXT1) sliders[SLIDERS_EXT1]->setLeft(pos); if (IS_POT_SLIDER_AVAILABLE(EXT1)) { auto rl = sliders[SLIDERS_REAR_LEFT]; auto e1 = sliders[SLIDERS_EXT1]; + + // If EXT1 is configured as a slider, + // place it bellow rear-left slider (and make them smaller) rl->setHeight(VERTICAL_SLIDERS_HEIGHT / 2); - e1->setTop(topbar->bottom() + rl->height()); + e1->setTop(vertTop + rl->height() + HMARGIN/2); e1->setHeight(rl->height()); } else { auto rl = sliders[SLIDERS_REAR_LEFT]; auto e1 = sliders[SLIDERS_EXT1]; + + // Otherwise hide the extra slider and make rear-left fullsize rl->setHeight(VERTICAL_SLIDERS_HEIGHT); e1->setHeight(0); } @@ -192,34 +206,37 @@ void ViewMain::adjustDecoration() // Right side (vertical) pos = right() - sliders[SLIDERS_REAR_RIGHT]->width(); sliders[SLIDERS_REAR_RIGHT]->setLeft(pos); - sliders[SLIDERS_REAR_RIGHT]->setTop(topbar->bottom()); + sliders[SLIDERS_REAR_RIGHT]->setTop(vertTop); + #if defined(HARDWARE_EXT2) sliders[SLIDERS_EXT2]->setLeft(pos); if (IS_POT_SLIDER_AVAILABLE(EXT2)) { auto rr = sliders[SLIDERS_REAR_RIGHT]; auto e2 = sliders[SLIDERS_EXT2]; + + // If EXT2 is configured as a slider, + // place it bellow rear-left slider (and make them smaller) rr->setHeight(VERTICAL_SLIDERS_HEIGHT / 2); - e2->setTop(topbar->bottom() + rr->height()); + e2->setTop(vertTop + rr->height() + HMARGIN/2); e2->setHeight(rr->height()); } else { auto rr = sliders[SLIDERS_REAR_RIGHT]; auto e2 = sliders[SLIDERS_EXT2]; + + // Otherwise hide the extra slider and make rear-left fullsize rr->setHeight(VERTICAL_SLIDERS_HEIGHT); e2->setHeight(0); } #endif - // Trims are last as they are located more on the inside - // (depend on everything else) - - pos = sliders[SLIDERS_POT1]->top() - TRIM_SQUARE_SIZE; - trims[TRIMS_LH]->setTop(pos); - trims[TRIMS_RH]->setTop(pos); + // Finally place the vertical trims further from the edge trims[TRIMS_LV]->setLeft(sliders[SLIDERS_REAR_LEFT]->right()); - trims[TRIMS_LV]->setTop(topbar->bottom()); + trims[TRIMS_LV]->setTop(vertTop); trims[TRIMS_RV]->setLeft(sliders[SLIDERS_REAR_RIGHT]->left() - trims[TRIMS_RV]->width()); - trims[TRIMS_RV]->setTop(topbar->bottom()); + trims[TRIMS_RV]->setTop(vertTop); + + //TODO: find a proper place for the flight-mode text box } #if defined(HARDWARE_KEYS) @@ -384,20 +401,19 @@ void ViewMain::createTrims() VERTICAL_SLIDERS_HEIGHT }; - r.x = left() + HMARGIN + TRIM_SQUARE_SIZE; // DBG + //r.x = left() + HMARGIN + TRIM_SQUARE_SIZE; // DBG trims[TRIMS_LV] = new MainViewVerticalTrim(this, r, 1); - r.x = right() - HMARGIN - TRIM_SQUARE_SIZE; // DBG + //r.x = right() - HMARGIN - TRIM_SQUARE_SIZE; // DBG trims[TRIMS_RV] = new MainViewVerticalTrim(this, r, 2); } void ViewMain::createFlightMode() { rect_t r = { - 50, - LCD_H - 4 - /*(hasSliders() ?*/ 2 * TRIM_SQUARE_SIZE /*: TRIM_SQUARE_SIZE)*/, - LCD_W - 100, - 20 + // centered text box (50 pixels from either edge) + // -> re-size once the other components are set + 50, 0, width() - 100, 0 }; std::function getFM = []() -> std::string { From 9a0f609ff7e8dd0065197351fbfb1d01caae2666 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 11 Apr 2021 12:33:08 +0200 Subject: [PATCH 04/54] Removed duplicated code --- radio/src/gui/colorlcd/layout.cpp | 32 ++------------------ radio/src/gui/colorlcd/layout.h | 4 +-- radio/src/gui/colorlcd/layouts/layout1x1.cpp | 6 +--- radio/src/gui/colorlcd/layouts/layout2+1.cpp | 4 +-- radio/src/gui/colorlcd/layouts/layout2x1.cpp | 4 +-- radio/src/gui/colorlcd/layouts/layout2x2.cpp | 4 +-- radio/src/gui/colorlcd/layouts/layout2x4.cpp | 4 +-- radio/src/gui/colorlcd/view_main.cpp | 16 ++++++++++ radio/src/gui/colorlcd/view_main.h | 4 +++ 9 files changed, 29 insertions(+), 49 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index a56a29684..855e6c28d 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -127,35 +127,7 @@ void Layout::decorate() viewMain->invalidate(); } -rect_t Layout::getMainZone(rect_t zone) const +rect_t Layout::getMainZone() const { - if (hasTopbar()) { - zone.y += MENU_HEADER_HEIGHT; - zone.h -= MENU_HEADER_HEIGHT; - } - - if (hasFlightMode() || hasTrims()) { - zone.h -= TRIM_SQUARE_SIZE; - } - - if (hasSliders()) { -#if NUM_SLIDERS + NUM_POTS > 2 - zone.h -= TRIM_SQUARE_SIZE; -#endif - zone.w -= 2 * TRIM_SQUARE_SIZE; - zone.x += TRIM_SQUARE_SIZE; - } - - if (hasTrims()) { - zone.w -= 2 * TRIM_SQUARE_SIZE; - zone.x += TRIM_SQUARE_SIZE; - } - - if (zone.w % 2 != 0) - zone.w -= 1; - - if (zone.h % 2 != 0) - zone.h -= 1; - - return zone; + return ViewMain::instance()->getMainZone(); } diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index 8c0befb1c..98239f5ec 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -118,8 +118,8 @@ class Layout: public LayoutBase // Updates settings for trims, sliders, pots, etc... void decorate(); - // Get the Zone rect without decoration - rect_t getMainZone(rect_t zone) const; + // Get the available space for widgets + rect_t getMainZone() const; }; void registerLayout(const LayoutFactory * factory); diff --git a/radio/src/gui/colorlcd/layouts/layout1x1.cpp b/radio/src/gui/colorlcd/layouts/layout1x1.cpp index ee641b530..f2fc0524d 100644 --- a/radio/src/gui/colorlcd/layouts/layout1x1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1x1.cpp @@ -21,8 +21,6 @@ #include "opentx.h" #include "trims.h" -constexpr coord_t border = 10; - const uint8_t LBM_LAYOUT_1x1[] = { #include "mask_layout1x1.lbm" }; @@ -47,9 +45,7 @@ class Layout1x1: public Layout rect_t getZone(unsigned int index) const override { - rect_t zone = getMainZone({border, border, LCD_W - 2 * border, LCD_H - 2 * border}); - - return zone; + return getMainZone(); } }; diff --git a/radio/src/gui/colorlcd/layouts/layout2+1.cpp b/radio/src/gui/colorlcd/layouts/layout2+1.cpp index dddd3f5f8..29b8f7d5a 100644 --- a/radio/src/gui/colorlcd/layouts/layout2+1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2+1.cpp @@ -22,8 +22,6 @@ #include "sliders.h" #include "trims.h" -constexpr coord_t border = 10; - const uint8_t LBM_LAYOUT_2P1[] = { #include "mask_layout2+1.lbm" }; @@ -48,7 +46,7 @@ class Layout2P1: public Layout rect_t getZone(unsigned int index) const override { - rect_t zone = getMainZone({border, border, LCD_W - 2 * border, LCD_H - 2 * border}); + rect_t zone = getMainZone(); if (index == 0) { return {isMirrored() ? zone.x : zone.x + zone.w / 2, zone.y,zone.w / 2, zone.h}; diff --git a/radio/src/gui/colorlcd/layouts/layout2x1.cpp b/radio/src/gui/colorlcd/layouts/layout2x1.cpp index 7db4f8c02..c9bd5831b 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x1.cpp @@ -22,8 +22,6 @@ #include "sliders.h" #include "trims.h" -constexpr coord_t border = 10; - const uint8_t LBM_LAYOUT_2x1[] = { #include "mask_layout2x1.lbm" }; @@ -48,7 +46,7 @@ class Layout2x1: public Layout rect_t getZone(unsigned int index) const override { - rect_t zone = getMainZone({border, border, LCD_W - 2 * border, LCD_H - 2 * border}); + rect_t zone = getMainZone(); if (index == 0) { return {isMirrored() ? zone.x + zone.w / 2 : zone.x, zone.y, zone.w / 2, zone.h}; diff --git a/radio/src/gui/colorlcd/layouts/layout2x2.cpp b/radio/src/gui/colorlcd/layouts/layout2x2.cpp index 05d973b62..6e8d78632 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x2.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x2.cpp @@ -22,8 +22,6 @@ #include "sliders.h" #include "trims.h" -constexpr coord_t border = 10; - const uint8_t LBM_LAYOUT_2x2[] = { #include "mask_layout2x2.lbm" }; @@ -48,7 +46,7 @@ class Layout2x2: public Layout rect_t getZone(unsigned int index) const override { - rect_t zone = getMainZone({border, border, LCD_W - 2 * border, LCD_H - 2 * border}); + rect_t zone = getMainZone(); zone.w /= 2; zone.h /= 2; diff --git a/radio/src/gui/colorlcd/layouts/layout2x4.cpp b/radio/src/gui/colorlcd/layouts/layout2x4.cpp index b08009f83..c3e6a0d02 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x4.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x4.cpp @@ -20,8 +20,6 @@ #include "opentx.h" -constexpr coord_t border = 10; - const uint8_t LBM_LAYOUT_2x4[] = { #include "mask_layout2x4.lbm" }; @@ -67,7 +65,7 @@ class Layout2x4: public Layout rect_t getZone(unsigned int index) const override { - rect_t zone = getMainZone({border, border, LCD_W - 2 * border, LCD_H - 2 * border}); + rect_t zone = getMainZone(); zone.w /= 2; zone.h /= 4; diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index c27536f92..55ca35c17 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -30,6 +30,8 @@ #include "layouts/trims.h" #include "opentx.h" +constexpr coord_t MAIN_ZONE_BORDER = 10; + Layout * customScreens[MAX_CUSTOM_SCREENS] = {}; int getMainViewsCount() @@ -239,6 +241,20 @@ void ViewMain::adjustDecoration() //TODO: find a proper place for the flight-mode text box } +rect_t ViewMain::getMainZone() const +{ + rect_t zone = { + trims[TRIMS_LV]->right() + MAIN_ZONE_BORDER, + topbar->bottom() + MAIN_ZONE_BORDER, + 0, 0 // let's compute them! + }; + + zone.w = trims[TRIMS_RV]->left() - MAIN_ZONE_BORDER - zone.x; + zone.h = trims[TRIMS_LH]->top() - MAIN_ZONE_BORDER - zone.y; + + return zone; +} + #if defined(HARDWARE_KEYS) void ViewMain::onEvent(event_t event) { diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 2f5231a32..ee2b0915c 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -57,6 +57,10 @@ class ViewMain: public FormWindow // Re-calculate positions void adjustDecoration(); + + // Get the available space in the middle of the screen + // (without decoration) + rect_t getMainZone() const; protected: static ViewMain * _instance; From 99018ce72643a27fec6aa56b67c4de673da99287 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 11 Apr 2021 12:47:56 +0200 Subject: [PATCH 05/54] Dynamic zones working --- radio/src/gui/colorlcd/layout.cpp | 5 ++++- radio/src/gui/colorlcd/widgets_container.h | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index 855e6c28d..3cdcda72e 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -124,7 +124,10 @@ void Layout::decorate() // Re-compute positions viewMain->adjustDecoration(); - viewMain->invalidate(); + + // and update relevant windows + updateZones(); + invalidate(); } rect_t Layout::getMainZone() const diff --git a/radio/src/gui/colorlcd/widgets_container.h b/radio/src/gui/colorlcd/widgets_container.h index 44302ba57..3ef16b8c6 100644 --- a/radio/src/gui/colorlcd/widgets_container.h +++ b/radio/src/gui/colorlcd/widgets_container.h @@ -122,6 +122,15 @@ class WidgetsContainer: public FormGroup, public WidgetsContainerInterface } } + void updateZones() + { + for (int i = 0; i < N; i++) { + if (widgets[i]) { + widgets[i]->setRect(getZone(i)); + } + } + } + protected: PersistentData * persistentData; Widget * widgets[N] = {}; From bf144290f3bf89a7d56e0ab96574fea86a3ab0a1 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 12 Apr 2021 11:41:50 +0200 Subject: [PATCH 06/54] WiP --- radio/src/gui/colorlcd/layout.cpp | 60 ++- radio/src/gui/colorlcd/layout.h | 15 + radio/src/gui/colorlcd/menu_screen.cpp | 4 +- radio/src/gui/colorlcd/screen_setup.cpp | 401 ++++++++++++--------- radio/src/gui/colorlcd/screen_setup.h | 14 +- radio/src/gui/colorlcd/tabsgroup.cpp | 19 + radio/src/gui/colorlcd/tabsgroup.h | 11 +- radio/src/gui/colorlcd/topbar.h | 7 + radio/src/gui/colorlcd/view_main.h | 3 + radio/src/gui/colorlcd/widgets_container.h | 25 +- 10 files changed, 376 insertions(+), 183 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index 3cdcda72e..71c15f5bb 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -46,6 +46,9 @@ const LayoutFactory * getLayoutFactory(const char * name) return nullptr; } +// +// Loads a layout, but does not attach it to any window +// Layout * loadLayout(const char * name, Layout::PersistentData * persistentData) { const LayoutFactory * factory = getLayoutFactory(name); @@ -55,10 +58,12 @@ Layout * loadLayout(const char * name, Layout::PersistentData * persistentData) return nullptr; } +// +// Detaches and deletes all custom screens +// void deleteCustomScreens() { - for (unsigned int i = 0; i < MAX_CUSTOM_SCREENS; i++) { - auto& screen = customScreens[i]; + for (auto& screen : customScreens) { if (screen) { screen->detach(); delete screen; @@ -75,6 +80,7 @@ void loadDefaultLayout() auto& screenData = g_model.screenData[0]; if (screen == nullptr && defaultLayout != nullptr) { + strcpy(screenData.LayoutId, defaultLayout->getId()); screen = defaultLayout->create(&screenData.layoutData); if (screen) { @@ -83,6 +89,9 @@ void loadDefaultLayout() } } +// +// Loads and attaches all configured custom screens +// void loadCustomScreens() { for (unsigned int i = 0; i < MAX_CUSTOM_SCREENS; i++) { @@ -97,6 +106,53 @@ void loadCustomScreens() } } +// +// Creates a new customer screen from factory: +// - the old screen is detached & deleted (including children) +// - new screen is configured into g_model +// - the new screen is returned (not attached) +// +Layout* createCustomScreen(const LayoutFactory* factory, unsigned customScreenIndex) +{ + if (!factory || (customScreenIndex >= MAX_CUSTOM_SCREENS)) + return nullptr; + + if (customScreens[customScreenIndex]) { + customScreens[customScreenIndex]->deleteLater(true, false); + delete customScreens[customScreenIndex]; + } + + auto screen = factory->create(&g_model.screenData[customScreenIndex].layoutData); + customScreens[customScreenIndex] = screen; + + if (screen) { + auto dst = g_model.screenData[customScreenIndex].LayoutId; + auto src = factory->getId(); + strncpy(dst, src, sizeof(CustomScreenData::LayoutId)); + + return screen; + } + + return nullptr; +} + +void disposeCustomScreen(unsigned idx) +{ + // move custom screen data + if (idx >= MAX_CUSTOM_SCREENS) { + return; + } + + auto dst = &g_model.screenData[idx]; + auto src = dst + 1; + auto len = sizeof(CustomScreenData) * (MAX_CUSTOM_SCREENS - idx - 1); + memmove(dst, src, len); + + dst = &g_model.screenData[MAX_CUSTOM_SCREENS - 1]; + len = sizeof(CustomScreenData); + memset(dst, 0, len); +} + void Layout::decorate() { // Check if deco setting are still up-to-date diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index 98239f5ec..2ec985fd2 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -68,6 +68,13 @@ class Layout: public LayoutBase decorate(); } +#if defined(DEBUG_WINDOWS) + std::string getName() const override + { + return "Layout"; + } +#endif + void create() override { setOptionValue(OPTION_TOPBAR, OPTION_VALUE_BOOL(true)); @@ -197,4 +204,12 @@ void loadDefaultLayout(); // intended for existing models void loadCustomScreens(); +// delete all custom screens from memory +void deleteCustomScreens(); + +Layout* createCustomScreen(const LayoutFactory* factory, unsigned customScreenIndex); + +// Remove custom screen from the model +void disposeCustomScreen(unsigned idx); + std::list & getRegisteredLayouts(); diff --git a/radio/src/gui/colorlcd/menu_screen.cpp b/radio/src/gui/colorlcd/menu_screen.cpp index 5dc29a2c8..0fe64460d 100644 --- a/radio/src/gui/colorlcd/menu_screen.cpp +++ b/radio/src/gui/colorlcd/menu_screen.cpp @@ -36,7 +36,7 @@ void ScreenMenu::updateTabs() for (int index = 0; index < MAX_CUSTOM_SCREENS; index++) { if (customScreens[index]) { - auto tab = new ScreenSetupPage(this, customScreens[index], g_model.screenData[index]); + auto tab = new ScreenSetupPage(this, getTabs(), index); std::string title(STR_MAIN_VIEW_X); title.back() = index + '1'; tab->setTitle(title); @@ -45,7 +45,7 @@ void ScreenMenu::updateTabs() addTab(tab); } else { - addTab(new ScreenAddPage(this, index)); + addTab(new ScreenAddPage(this, getTabs())); break; } } diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 48c6e99a4..59f5e3794 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -26,72 +26,14 @@ #define SET_DIRTY() storageDirty(EE_MODEL) -ScreenUserInterfacePage::ScreenUserInterfacePage(): - PageTab(STR_USER_INTERFACE, ICON_THEME_SETUP) +class LayoutChoice: public FormField { -} - -void ScreenUserInterfacePage::build(FormWindow * window) -{ - FormGridLayout grid; - - // Theme choice - new StaticText(window, grid.getLabelSlot(), STR_THEME, 0, 0); - // TODO: Theme picklist - grid.nextLine(); - - // Theme options ? - - // Top Bar - new StaticText(window, grid.getLabelSlot(), STR_TOP_BAR, 0, 0); - // TODO: enable settings topbar widgets - grid.nextLine(); -} - -ScreenAddPage::ScreenAddPage(ScreenMenu * menu, uint8_t pageIndex): - PageTab(), - menu(menu), - pageIndex(pageIndex) -{ - setTitle(STR_ADD_MAIN_VIEW); - setIcon(ICON_THEME_ADD_VIEW); -} - -void ScreenAddPage::build(FormWindow * window) -{ - rect_t buttonRect = {LCD_W / 2 - 100, (window->height() - 24) / 2, 200, 24}; - auto button = new TextButton(window, buttonRect, STR_ADD_MAIN_VIEW); - button->setPressHandler([=]() -> uint8_t { - - auto& screen = customScreens[pageIndex]; - auto& screenData = g_model.screenData[pageIndex]; - - const LayoutFactory * factory = getRegisteredLayouts().front(); - - screen = factory->create(&screenData.layoutData); - strncpy(screenData.LayoutId, factory->getId(), sizeof(screenData.LayoutId)); - - auto tab = new ScreenSetupPage(menu, screen, screenData); - std::string title(STR_MAIN_VIEW_X); - title.back() = pageIndex + '0'; - tab->setTitle(title); - tab->setIcon(ICON_THEME_VIEW1 + pageIndex); - - menu->removeTab(pageIndex); - menu->addTab(tab); - menu->setCurrentTab(pageIndex); - - if (pageIndex < MAX_CUSTOM_SCREENS - 1) { - menu->addTab(new ScreenAddPage(menu, pageIndex + 1)); - } - storageDirty(EE_MODEL); - return 0; - }); -} - -class LayoutChoice: public FormField { public: - LayoutChoice(Window * parent, const rect_t & rect, std::function getValue, std::function setValue): + + typedef std::function LayoutFactoryGetter; + typedef std::function LayoutFactorySetter; + + LayoutChoice(Window * parent, const rect_t & rect, LayoutFactoryGetter getValue, LayoutFactorySetter setValue): FormField(parent, {rect.x, rect.y, 59, 33}), getValue(std::move(getValue)), setValue(std::move(setValue)) @@ -102,7 +44,9 @@ class LayoutChoice: public FormField { { FormField::paint(dc); auto layout = getValue(); - layout->drawThumb(dc, 4, 4, editMode ? FOCUS_COLOR : LINE_COLOR); + if (layout) { + layout->drawThumb(dc, 4, 4, editMode ? FOCUS_COLOR : LINE_COLOR); + } } #if defined(HARDWARE_KEYS) @@ -162,94 +106,91 @@ class LayoutChoice: public FormField { std::function setValue; }; -ScreenSetupPage::ScreenSetupPage(ScreenMenu * menu, Layout*& screen, CustomScreenData& screenData): - PageTab(), - menu(menu), - screen(screen), - screenData(screenData) -{ -} - class SetupWidgetsPageSlot: public Button { public: SetupWidgetsPageSlot(FormGroup * parent, const rect_t & rect, Layout* screen, uint8_t slotIndex): - Button(parent, rect), - screen(screen), - slotIndex(slotIndex) + Button(parent, rect) { - widget = screen->getWidget(slotIndex); - setPressHandler([=]() -> uint8_t { - if (widget) { - Menu * menu = new Menu(this); - menu->addLine(TR_SELECT_WIDGET, [=]() { - Menu * menu = new Menu(this); - for (auto factory: getRegisteredWidgets()) { - menu->addLine(factory->getName(), [=]() { - if (widget) widget->deleteLater(); - widget = screen->createWidget(slotIndex, factory); - }); - } - }); - menu->addLine(TR_WIDGET_SETTINGS, [=]() { - new WidgetSettings(this, widget); - }); + //auto parent = (Window*)this; + setPressHandler([parent, screen, slotIndex]() -> uint8_t { + Menu * menu = new Menu(parent); + menu->addLine(TR_SELECT_WIDGET, [=]() { + Menu * menu = new Menu(parent); + for (auto factory: getRegisteredWidgets()) { + menu->addLine(factory->getName(), [=]() { + screen->createWidget(slotIndex, factory); + }); + } + }); + + if (screen->getWidget(slotIndex)) { + menu->addLine(TR_WIDGET_SETTINGS, [=]() { + auto widget = screen->getWidget(slotIndex); + new WidgetSettings(parent, widget); + }); menu->addLine(STR_REMOVE_WIDGET, [=]() { - widget->deleteLater(); - widget = nullptr; + screen->removeWidget(slotIndex); }); - return 0; - } - else { - Menu * menu = new Menu(this); - for (auto factory: getRegisteredWidgets()) { - menu->addLine(factory->getName(), [=]() { - if (widget) widget->deleteLater(); - widget = screen->createWidget(slotIndex, factory); - }); - } } + return 0; + // } + // else { + // Menu * menu = new Menu(this); + // for (auto factory: getRegisteredWidgets()) { + // menu->addLine(factory->getName(), [=]() { + // if (widget) widget->deleteLater(); + // widget = screen->createWidget(slotIndex, factory); + // }); + // } + // } + // return 0; }); } void paint(BitmapBuffer * dc) override { if (hasFocus()) { - dc->drawSolidRect(0, 0, width(), height(), 1, DEFAULT_COLOR); - } - else { - dc->drawRect(0, 0, width(), height(), 1, DOTTED, DEFAULT_COLOR); + dc->drawRect(0, 0, width()-2, height()-2, 2, DOTTED, CHECKBOX_COLOR); } } - - protected: - Layout * screen; - uint8_t slotIndex; - Widget * widget = nullptr; }; class SetupWidgetsPage: public FormWindow { public: - SetupWidgetsPage(Layout * screen): - FormWindow(MainWindow::instance(), {0, 0, LCD_W, LCD_H}, OPAQUE | FORM_FORWARD_FOCUS), - screen(screen), - oldParent(screen->getParent()) + SetupWidgetsPage(ScreenMenu* menu, uint8_t customScreenIdx): + FormWindow(ViewMain::instance(), {0, 0, LCD_W, LCD_H}, /*OPAQUE |*/ FORM_FORWARD_FOCUS), + menu(menu), + customScreenIdx(customScreenIdx) { Layer::push(this); - clearFocus(); - // attach this custom screen here so we can display it - screen->attach(this); - + // attach this custom screen here so we can display it + auto screen = customScreens[customScreenIdx]; + if (screen) { + screen->attach(this); + setRect(screen->getRect()); + } + + ViewMain::instance()->bringToTop(); + for (unsigned i = 0; i < screen->getZonesCount(); i++) { auto rect = screen->getZone(i); - new SetupWidgetsPageSlot(this, {rect.x - 1, rect.y - 1, rect.w + 2, rect.h + 2}, screen, i); + auto widget = new SetupWidgetsPageSlot(this, rect, customScreens[customScreenIdx], i); + if (i == 0) widget->setFocus(); } } +#if defined(DEBUG_WINDOWS) + std::string getName() const override + { + return "SetupWidgetPage(idx=" + std::to_string(customScreenIdx) + ")"; + } +#endif + void deleteLater(bool detach = true, bool trash = true) override { Layer::pop(this); @@ -257,12 +198,14 @@ class SetupWidgetsPage: public FormWindow #if defined(HARDWARE_TOUCH) Keyboard::hide(); #endif - if (oldParent) { - // give it back to its old parent before it gets deleted - screen->attach(oldParent); + auto screen = customScreens[customScreenIdx]; + if (screen) { + screen->attach(ViewMain::instance()); } - FormWindow::deleteLater(detach, trash); + + // restore screen setting tab on top + menu->bringToTop(); } #if defined(HARDWARE_KEYS) @@ -279,16 +222,100 @@ class SetupWidgetsPage: public FormWindow #endif protected: - Layout* screen; - Window* oldParent; - - void paint(BitmapBuffer * dc) override - { - dc->clear(DEFAULT_BGCOLOR); - } + ScreenMenu* menu; + uint8_t customScreenIdx; + // void paint(BitmapBuffer * dc) override + // { + // //ViewMain::instance()->fullPaint(dc); + // //dc->clear(DEFAULT_BGCOLOR); + // } }; +ScreenUserInterfacePage::ScreenUserInterfacePage(): + PageTab(STR_USER_INTERFACE, ICON_THEME_SETUP) +{ +} + +void ScreenUserInterfacePage::build(FormWindow * window) +{ + FormGridLayout grid; + + // Theme choice + new StaticText(window, grid.getLabelSlot(), STR_THEME, 0, 0); + // TODO: Theme picklist + grid.nextLine(); + + // Theme options ? + + // Top Bar + new StaticText(window, grid.getLabelSlot(), STR_TOP_BAR, 0, 0); + // TODO: enable settings topbar widgets + grid.nextLine(); +} + +ScreenAddPage::ScreenAddPage(ScreenMenu * menu, uint8_t pageIndex): + PageTab(), + menu(menu), + pageIndex(pageIndex) +{ + setTitle(STR_ADD_MAIN_VIEW); + setIcon(ICON_THEME_ADD_VIEW); +} + +extern const LayoutFactory * defaultLayout; + +void ScreenAddPage::build(FormWindow * window) +{ + rect_t buttonRect = {LCD_W / 2 - 100, (window->height() - 24) / 2, 200, 24}; + auto button = new TextButton(window, buttonRect, STR_ADD_MAIN_VIEW); + + auto pageIndex = this->pageIndex; + auto menu = this->menu; + + button->setPressHandler([menu,pageIndex]() -> uint8_t { + + auto newPageIdx = menu->getTabs(); + auto newIdx = newPageIdx - 2; + + auto& screen = customScreens[newIdx]; + auto& screenData = g_model.screenData[newIdx]; + + const LayoutFactory * factory = defaultLayout; + screen = factory->create(&screenData.layoutData); + strncpy(screenData.LayoutId, factory->getId(), sizeof(screenData.LayoutId)); + + auto tab = new ScreenSetupPage(menu, newPageIdx, newIdx); + std::string title(STR_MAIN_VIEW_X); + title.back() = newIdx + '1'; + tab->setTitle(title); + tab->setIcon(ICON_THEME_VIEW1 + newIdx); + + // remove current tab first + menu->setCurrentTab(0); + menu->removeTab(pageIndex); + + // add the new one + menu->addTab(tab); + menu->setCurrentTab(newPageIdx); + + if (menu->getTabs() < MAX_CUSTOM_SCREENS) { + menu->addTab(new ScreenAddPage(menu, menu->getTabs())); + } + + storageDirty(EE_MODEL); + return 0; + }); +} + +ScreenSetupPage::ScreenSetupPage(ScreenMenu * menu, unsigned pageIndex, unsigned customScreenIndex): + PageTab(), + menu(menu), + pageIndex(pageIndex), + customScreenIndex(customScreenIndex) +{ +} + void ScreenSetupPage::build(FormWindow * window) { FormGridLayout grid; @@ -296,46 +323,95 @@ void ScreenSetupPage::build(FormWindow * window) // Layout choice... new StaticText(window, grid.getLabelSlot(false), STR_LAYOUT); + auto layoutSlot = grid.getFieldSlot(); layoutSlot.h = 2 * PAGE_LINE_HEIGHT - 1; - layoutChoice = new LayoutChoice(window, layoutSlot, GET_VALUE(screen->getFactory()), [=](const LayoutFactory *factory) { - delete screen; - screen = factory->create(&screenData.layoutData); - strncpy(screenData.LayoutId, factory->getId(), sizeof(CustomScreenData::LayoutId)); - SET_DIRTY(); - updateLayoutOptions(); - }); + + auto idx = customScreenIndex; + LayoutChoice::LayoutFactoryGetter getFactory = GET_VALUE(customScreens[idx]->getFactory()); + LayoutChoice::LayoutFactorySetter setLayout = [idx](const LayoutFactory *factory) { + createCustomScreen(factory, idx); + SET_DIRTY(); + }; + + auto layoutChoice = new LayoutChoice(window, layoutSlot, getFactory, setLayout); grid.nextLine(layoutChoice->height()); + TRACE("layoutChoice = %p", layoutChoice); // Setup widgets button... - setupWidgetsButton = new TextButton(window, grid.getFieldSlot(), STR_SETUP_WIDGETS); - setupWidgetsButton->setPressHandler([=]() -> uint8_t { - new SetupWidgetsPage(screen); + auto setupWidgetsButton = new TextButton(window, grid.getFieldSlot(), STR_SETUP_WIDGETS); + TRACE("setupWidgetsButton = %p", setupWidgetsButton); + + auto menu = this->menu; + setupWidgetsButton->setPressHandler([idx,menu]() -> uint8_t { + new SetupWidgetsPage(menu, idx); return 0; }); grid.nextLine(); // Dynamic options window... - optionsWindow = new FormGroup(window, {0, grid.getWindowHeight(), LCD_W, 0}, FORWARD_SCROLL | FORM_FORWARD_FOCUS); - grid.addWindow(optionsWindow); - updateLayoutOptions(); + // rect_t r = {0, grid.getWindowHeight(), LCD_W, 0}; + // auto optionsWindow = new FormGroup(window, r, FORWARD_SCROLL | FORM_FORWARD_FOCUS); + // grid.addWindow(optionsWindow); + // updateLayoutOptions(); + + // Prevent removing the last page + if (customScreens[1] != nullptr) { + auto button = new TextButton(window, grid.getFieldSlot(), STR_REMOVE_SCREEN); + auto menu = this->menu; + button->setPressHandler([menu,idx]() -> uint8_t { + + // Set the current tab to "User interface" to trigger body clearing + menu->setCurrentTab(0); + + // Remove this screen from the model + disposeCustomScreen(idx); + + // Delete all custom screens + deleteCustomScreens(); + + // ... and reload + loadCustomScreens(); + menu->updateTabs(); + + // Let's try to stay on the same page + // (first tab is "User interface") + auto pageIdx = idx + 1; + + // Subtract one more as the last one is "New main screen" + if (pageIdx > menu->getTabs() - 2) { + pageIdx = menu->getTabs() - 2; + } + menu->setCurrentTab(pageIdx); + + // save the changes + storageDirty(EE_MODEL); + return 0; + }); + } + + // optionsWindow->adjustHeight(); + // optionsWindow->getParent()->adjustInnerHeight(); } void ScreenSetupPage::updateLayoutOptions() { +#if 0 FormGridLayout grid; optionsWindow->clear(); // Layout options... int index = 0; - for (auto * option = screen->getFactory()->getOptions(); option->name; option++, index++) { - ZoneOptionValue * value = screen->getOptionValue(index); + auto factory = customScreen[customScreenIndex]->getFactory(); + if (factory) { + for (auto * option = factory->getOptions(); option->name; option++, index++) { + ZoneOptionValue * value = customScreens[customScreenIndex]->getOptionValue(index); - // Option label - new StaticText(optionsWindow, grid.getLabelSlot(false), option->name); + // Option label + new StaticText(optionsWindow, grid.getLabelSlot(false), option->name); - // Option value - switch (option->type) { + // Option value + switch (option->type) { case ZoneOption::Bool: new CheckBox(optionsWindow, grid.getFieldSlot(), GET_SET_DEFAULT(value->boolValue)); break; @@ -346,25 +422,10 @@ void ScreenSetupPage::updateLayoutOptions() default: break; + } + grid.nextLine(); } - grid.nextLine(); } - //if (pageIndex > 0 || customScreens[1]) { - auto button = new TextButton(optionsWindow, grid.getFieldSlot(), STR_REMOVE_SCREEN); - button->setPressHandler([=]() -> uint8_t { - // if (pageIndex < MAX_CUSTOM_SCREENS - 1) { - // memmove(&g_model.screenData[pageIndex], &g_model.screenData[pageIndex + 1], sizeof(CustomScreenData) * (MAX_CUSTOM_SCREENS - pageIndex - 1)); - // } - // memset(&g_model.screenData[MAX_CUSTOM_SCREENS - 1], 0, sizeof(CustomScreenData)); - memset(&screenData, 0, sizeof(CustomScreenData)); - loadCustomScreens(); - menu->updateTabs(); - storageDirty(EE_MODEL); - return 0; - }); - //} - - optionsWindow->adjustHeight(); - optionsWindow->getParent()->adjustInnerHeight(); +#endif } diff --git a/radio/src/gui/colorlcd/screen_setup.h b/radio/src/gui/colorlcd/screen_setup.h index a17f714cc..2d8614672 100644 --- a/radio/src/gui/colorlcd/screen_setup.h +++ b/radio/src/gui/colorlcd/screen_setup.h @@ -44,17 +44,19 @@ class ScreenAddPage: public PageTab { class ScreenSetupPage: public PageTab { public: - ScreenSetupPage(ScreenMenu * menu, Layout*& screen, CustomScreenData& screenData); + ScreenSetupPage(ScreenMenu * menu, unsigned pageIndex, unsigned customScreenIndex); void build(FormWindow * window) override; protected: ScreenMenu * menu; - Layout *& screen; - CustomScreenData& screenData; - FormGroup * optionsWindow = nullptr; - TextButton * setupWidgetsButton = nullptr; - FormField * layoutChoice = nullptr; + unsigned pageIndex; + unsigned customScreenIndex; + + // FormGroup * optionsWindow = nullptr; + // TextButton * setupWidgetsButton = nullptr; + // FormField * layoutChoice = nullptr; void updateLayoutOptions(); + //void disposeCustomScreen(); }; diff --git a/radio/src/gui/colorlcd/tabsgroup.cpp b/radio/src/gui/colorlcd/tabsgroup.cpp index e4e29e7ea..66f73c98c 100644 --- a/radio/src/gui/colorlcd/tabsgroup.cpp +++ b/radio/src/gui/colorlcd/tabsgroup.cpp @@ -94,6 +94,19 @@ void TabsGroup::addTab(PageTab * page) setCurrentTab(0); } header.carousel.updateInnerWidth(); + invalidate(); +} + +int TabsGroup::removeTab(PageTab * page) +{ + auto tabIter = std::find(tabs.begin(), tabs.end(), page); + if (tabIter != tabs.end()) { + auto idx = tabIter - tabs.begin(); + removeTab(idx); + return idx; + } + + return -1; } void TabsGroup::removeTab(unsigned index) @@ -103,6 +116,7 @@ void TabsGroup::removeTab(unsigned index) } tabs.erase(tabs.begin() + index); header.carousel.updateInnerWidth(); + invalidate(); } void TabsGroup::removeAllTabs() @@ -132,6 +146,11 @@ void TabsGroup::setVisibleTab(PageTab * tab) } } +// TODO: add a mechanism to trigger a rebuild of a PageTab +// -> rebuild(): +// - as in setVisibleTab() (clear & build) +// - but without changing tab + void TabsGroup::checkEvents() { Window::checkEvents(); diff --git a/radio/src/gui/colorlcd/tabsgroup.h b/radio/src/gui/colorlcd/tabsgroup.h index ba49076de..a985c111d 100644 --- a/radio/src/gui/colorlcd/tabsgroup.h +++ b/radio/src/gui/colorlcd/tabsgroup.h @@ -193,8 +193,17 @@ class TabsGroup: public Window } #endif + unsigned getTabs() const + { + return tabs.size(); + } + void addTab(PageTab * page); + // Return the index of the found tab + // or -1 if the tab could not be found + int removeTab(PageTab * page); + void removeTab(unsigned index); void removeAllTabs(); @@ -206,7 +215,7 @@ class TabsGroup: public Window setVisibleTab(tabs[index]); } } - + void checkEvents() override; #if defined(HARDWARE_KEYS) diff --git a/radio/src/gui/colorlcd/topbar.h b/radio/src/gui/colorlcd/topbar.h index 34aac2b69..404b0aaac 100644 --- a/radio/src/gui/colorlcd/topbar.h +++ b/radio/src/gui/colorlcd/topbar.h @@ -34,6 +34,13 @@ class TopBar: public WidgetsContainer public: explicit TopBar(Window * parent); +#if defined(DEBUG_WINDOWS) + std::string getName() const override + { + return "TopBar"; + } +#endif + unsigned int getZonesCount() const override; rect_t getZone(unsigned int index) const override; diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index ee2b0915c..1cd241dcf 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -25,6 +25,7 @@ #include class TopBar; +class SetupWidgetsPage; class ViewMain: public FormWindow { @@ -88,6 +89,8 @@ class ViewMain: public FormWindow Window* sliders[SLIDERS_MAX]; Window* trims[TRIMS_MAX]; Window* flightMode; + + friend class SetupWidgetsPage; #if defined(HARDWARE_KEYS) void onEvent(event_t event) override; diff --git a/radio/src/gui/colorlcd/widgets_container.h b/radio/src/gui/colorlcd/widgets_container.h index 3ef16b8c6..c46151fe1 100644 --- a/radio/src/gui/colorlcd/widgets_container.h +++ b/radio/src/gui/colorlcd/widgets_container.h @@ -58,17 +58,38 @@ class WidgetsContainer: public FormGroup, public WidgetsContainerInterface Widget * createWidget(unsigned int index, const WidgetFactory * factory) override { + if (index >= N) + return nullptr; + + // remove old one if existing + removeWidget(index); + Widget * widget = nullptr; - memset(persistentData->zones[index].widgetName, 0, sizeof(persistentData->zones[index].widgetName)); if (factory) { - strncpy(persistentData->zones[index].widgetName, factory->getName(), sizeof(persistentData->zones[index].widgetName)); + strncpy(persistentData->zones[index].widgetName, factory->getName(), sizeof(ZonePersistentData::widgetName)); widget = factory->create(this, getZone(index), &persistentData->zones[index].widgetData); } widgets[index] = widget; + if (widget) + widget->attach(this); + return widget; } + void removeWidget(unsigned int index) + { + if (index >= N) + return; + + if (widgets[index]) + widgets[index]->deleteLater(); + + widgets[index] = nullptr; + memset(persistentData->zones[index].widgetName, 0, sizeof(ZonePersistentData::widgetName)); + memset(&persistentData->zones[index].widgetData, 0, sizeof(Widget::PersistentData)); + } + Widget * getWidget(unsigned int index) override { if (index < N) From 0ad4e6fce11175b897722703379f3c3db876f6e2 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 14 Apr 2021 13:53:52 +0200 Subject: [PATCH 07/54] Layouts properly removed & deleted on model change --- radio/src/gui/colorlcd/layout.cpp | 10 ++++++++-- radio/src/gui/colorlcd/screen_setup.cpp | 2 +- radio/src/gui/colorlcd/view_main.cpp | 3 --- radio/src/gui/colorlcd/widget.h | 7 +++++++ radio/src/storage/storage_common.cpp | 4 ++++ 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index 71c15f5bb..d2731bb76 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -65,8 +65,7 @@ void deleteCustomScreens() { for (auto& screen : customScreens) { if (screen) { - screen->detach(); - delete screen; + screen->deleteLater(); screen = nullptr; } } @@ -83,6 +82,13 @@ void loadDefaultLayout() strcpy(screenData.LayoutId, defaultLayout->getId()); screen = defaultLayout->create(&screenData.layoutData); + // + // TODO: + // -> attach a few default widgets + // - ModelBmp + // - Timer + // - ??? + // if (screen) { screen->attach(ViewMain::instance()); } diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 59f5e3794..ac9d133d5 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -394,7 +394,7 @@ void ScreenSetupPage::build(FormWindow * window) // optionsWindow->getParent()->adjustInnerHeight(); } -void ScreenSetupPage::updateLayoutOptions() +void ScreenSetupPage::updateLayoutOptions() // TODO { #if 0 FormGridLayout grid; diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 55ca35c17..386972f33 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -417,10 +417,7 @@ void ViewMain::createTrims() VERTICAL_SLIDERS_HEIGHT }; - //r.x = left() + HMARGIN + TRIM_SQUARE_SIZE; // DBG trims[TRIMS_LV] = new MainViewVerticalTrim(this, r, 1); - - //r.x = right() - HMARGIN - TRIM_SQUARE_SIZE; // DBG trims[TRIMS_RV] = new MainViewVerticalTrim(this, r, 2); } diff --git a/radio/src/gui/colorlcd/widget.h b/radio/src/gui/colorlcd/widget.h index e1bb59aae..c1a41b6af 100644 --- a/radio/src/gui/colorlcd/widget.h +++ b/radio/src/gui/colorlcd/widget.h @@ -90,6 +90,13 @@ class Widget : public FormField { } +#if defined(DEBUG_WINDOWS) + std::string getName() const override + { + return "Widget"; + } +#endif + protected: const WidgetFactory * factory; PersistentData * persistentData; diff --git a/radio/src/storage/storage_common.cpp b/radio/src/storage/storage_common.cpp index b46ea4134..439032e74 100644 --- a/radio/src/storage/storage_common.cpp +++ b/radio/src/storage/storage_common.cpp @@ -61,6 +61,10 @@ void preModelLoad() #endif stopTrainer(); + +#if defined(COLORLCD) + deleteCustomScreens(); +#endif } void postRadioSettingsLoad() From 587f903bb69f812761cd915d3ff4acf1ed4d6bef Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Wed, 14 Apr 2021 14:02:04 +0200 Subject: [PATCH 08/54] Fixed indexes on ScreenAddPage --- radio/src/gui/colorlcd/screen_setup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index ac9d133d5..883bddb0f 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -285,7 +285,7 @@ void ScreenAddPage::build(FormWindow * window) screen = factory->create(&screenData.layoutData); strncpy(screenData.LayoutId, factory->getId(), sizeof(screenData.LayoutId)); - auto tab = new ScreenSetupPage(menu, newPageIdx, newIdx); + auto tab = new ScreenSetupPage(menu, pageIndex, newIdx); std::string title(STR_MAIN_VIEW_X); title.back() = newIdx + '1'; tab->setTitle(title); @@ -297,7 +297,7 @@ void ScreenAddPage::build(FormWindow * window) // add the new one menu->addTab(tab); - menu->setCurrentTab(newPageIdx); + menu->setCurrentTab(pageIndex); if (menu->getTabs() < MAX_CUSTOM_SCREENS) { menu->addTab(new ScreenAddPage(menu, menu->getTabs())); From 3ed1de1619fc5ad19a33a10318342d88f2edfebe Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 15 Apr 2021 08:02:32 +0200 Subject: [PATCH 09/54] Fixed layout options --- radio/src/gui/colorlcd/screen_setup.cpp | 111 +++++++++++++----------- radio/src/gui/colorlcd/screen_setup.h | 7 -- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 883bddb0f..084155c31 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -273,10 +273,10 @@ void ScreenAddPage::build(FormWindow * window) auto pageIndex = this->pageIndex; auto menu = this->menu; - button->setPressHandler([menu,pageIndex]() -> uint8_t { + button->setPressHandler([menu, pageIndex]() -> uint8_t { - auto newPageIdx = menu->getTabs(); - auto newIdx = newPageIdx - 2; + // First page is "User interface", subtract it + auto newIdx = pageIndex - 1; auto& screen = customScreens[newIdx]; auto& screenData = g_model.screenData[newIdx]; @@ -316,6 +316,40 @@ ScreenSetupPage::ScreenSetupPage(ScreenMenu * menu, unsigned pageIndex, unsigned { } +static void updateLayoutOptions(FormGroup* optionsWindow, unsigned customScreenIndex) // TODO +{ + FormGridLayout grid; + optionsWindow->clear(); + + // Layout options... + int index = 0; + auto factory = customScreens[customScreenIndex]->getFactory(); + if (factory) { + for (auto * option = factory->getOptions(); option->name; option++, index++) { + ZoneOptionValue * value = customScreens[customScreenIndex]->getOptionValue(index); + + // Option label + new StaticText(optionsWindow, grid.getLabelSlot(false), option->name); + + // Option value + switch (option->type) { + case ZoneOption::Bool: + new CheckBox(optionsWindow, grid.getFieldSlot(), GET_SET_DEFAULT(value->boolValue)); + break; + + case ZoneOption::Color: + new ColorEdit(optionsWindow, grid.getFieldSlot(), GET_SET_DEFAULT(value->unsignedValue)); + break; + + default: + break; + } + grid.nextLine(); + } + } + optionsWindow->adjustHeight(); +} + void ScreenSetupPage::build(FormWindow * window) { FormGridLayout grid; @@ -327,39 +361,48 @@ void ScreenSetupPage::build(FormWindow * window) auto layoutSlot = grid.getFieldSlot(); layoutSlot.h = 2 * PAGE_LINE_HEIGHT - 1; + // Dynamic options window... auto idx = customScreenIndex; + rect_t optRect = {0, grid.getWindowHeight(), window->width(), 0}; + auto optionsWindow = new FormGroup(window, optRect, FORWARD_SCROLL | FORM_FORWARD_FOCUS); + LayoutChoice::LayoutFactoryGetter getFactory = GET_VALUE(customScreens[idx]->getFactory()); - LayoutChoice::LayoutFactorySetter setLayout = [idx](const LayoutFactory *factory) { + LayoutChoice::LayoutFactorySetter setLayout = [idx, optionsWindow](const LayoutFactory *factory) { + // delete any options potentially accessing + // the old custom screen + optionsWindow->clear(); createCustomScreen(factory, idx); + updateLayoutOptions(optionsWindow, idx); SET_DIRTY(); }; auto layoutChoice = new LayoutChoice(window, layoutSlot, getFactory, setLayout); grid.nextLine(layoutChoice->height()); - TRACE("layoutChoice = %p", layoutChoice); // Setup widgets button... auto setupWidgetsButton = new TextButton(window, grid.getFieldSlot(), STR_SETUP_WIDGETS); - TRACE("setupWidgetsButton = %p", setupWidgetsButton); auto menu = this->menu; - setupWidgetsButton->setPressHandler([idx,menu]() -> uint8_t { + setupWidgetsButton->setPressHandler([idx, menu]() -> uint8_t { new SetupWidgetsPage(menu, idx); return 0; }); grid.nextLine(); - // Dynamic options window... - // rect_t r = {0, grid.getWindowHeight(), LCD_W, 0}; - // auto optionsWindow = new FormGroup(window, r, FORWARD_SCROLL | FORM_FORWARD_FOCUS); - // grid.addWindow(optionsWindow); - // updateLayoutOptions(); + // place the options window at the right spot + optionsWindow->setTop(grid.getWindowHeight()); + updateLayoutOptions(optionsWindow, idx); + grid.addWindow(optionsWindow); + // fix focus order due to early insertion + FormField::link(setupWidgetsButton, optionsWindow); + window->setLastField(optionsWindow); + // Prevent removing the last page if (customScreens[1] != nullptr) { auto button = new TextButton(window, grid.getFieldSlot(), STR_REMOVE_SCREEN); auto menu = this->menu; - button->setPressHandler([menu,idx]() -> uint8_t { + button->setPressHandler([menu, idx]() -> uint8_t { // Set the current tab to "User interface" to trigger body clearing menu->setCurrentTab(0); @@ -388,44 +431,8 @@ void ScreenSetupPage::build(FormWindow * window) storageDirty(EE_MODEL); return 0; }); + + // fix focus order due to early insertion + FormField::link(button, layoutChoice); } - - // optionsWindow->adjustHeight(); - // optionsWindow->getParent()->adjustInnerHeight(); -} - -void ScreenSetupPage::updateLayoutOptions() // TODO -{ -#if 0 - FormGridLayout grid; - optionsWindow->clear(); - - // Layout options... - int index = 0; - auto factory = customScreen[customScreenIndex]->getFactory(); - if (factory) { - for (auto * option = factory->getOptions(); option->name; option++, index++) { - ZoneOptionValue * value = customScreens[customScreenIndex]->getOptionValue(index); - - // Option label - new StaticText(optionsWindow, grid.getLabelSlot(false), option->name); - - // Option value - switch (option->type) { - case ZoneOption::Bool: - new CheckBox(optionsWindow, grid.getFieldSlot(), GET_SET_DEFAULT(value->boolValue)); - break; - - case ZoneOption::Color: - new ColorEdit(optionsWindow, grid.getFieldSlot(), GET_SET_DEFAULT(value->unsignedValue)); - break; - - default: - break; - } - grid.nextLine(); - } - } - -#endif } diff --git a/radio/src/gui/colorlcd/screen_setup.h b/radio/src/gui/colorlcd/screen_setup.h index 2d8614672..a04c16b0f 100644 --- a/radio/src/gui/colorlcd/screen_setup.h +++ b/radio/src/gui/colorlcd/screen_setup.h @@ -52,11 +52,4 @@ class ScreenSetupPage: public PageTab { ScreenMenu * menu; unsigned pageIndex; unsigned customScreenIndex; - - // FormGroup * optionsWindow = nullptr; - // TextButton * setupWidgetsButton = nullptr; - // FormField * layoutChoice = nullptr; - - void updateLayoutOptions(); - //void disposeCustomScreen(); }; From a1cd234c14a01bf280576546d096d699727f15be Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 15 Apr 2021 09:11:19 +0200 Subject: [PATCH 10/54] Re-use ViewMain decoration in Radio calibration --- radio/src/gui/colorlcd/CMakeLists.txt | 1 + radio/src/gui/colorlcd/layout.h | 1 + radio/src/gui/colorlcd/radio_calibration.cpp | 52 +--- radio/src/gui/colorlcd/view_main.cpp | 257 +--------------- radio/src/gui/colorlcd/view_main.h | 31 +- .../src/gui/colorlcd/view_main_decoration.cpp | 287 ++++++++++++++++++ radio/src/gui/colorlcd/view_main_decoration.h | 83 +++++ 7 files changed, 398 insertions(+), 314 deletions(-) create mode 100644 radio/src/gui/colorlcd/view_main_decoration.cpp create mode 100644 radio/src/gui/colorlcd/view_main_decoration.h diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index e7b0674f9..16dd56461 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -53,6 +53,7 @@ set(GUI_SRC radio_diaganas.cpp radio_calibration.cpp view_main.cpp + view_main_decoration.cpp view_channels.cpp view_logical_switches.cpp view_statistics.cpp diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index 2ec985fd2..48b9e9200 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -29,6 +29,7 @@ #define MAX_LAYOUT_OPTIONS 10 constexpr coord_t TRIM_LINE_WIDTH = 8; constexpr coord_t TRIM_SQUARE_SIZE = 17; +constexpr coord_t MAIN_ZONE_BORDER = 10; class LayoutFactory; diff --git a/radio/src/gui/colorlcd/radio_calibration.cpp b/radio/src/gui/colorlcd/radio_calibration.cpp index e7e0d933e..2cd07317a 100644 --- a/radio/src/gui/colorlcd/radio_calibration.cpp +++ b/radio/src/gui/colorlcd/radio_calibration.cpp @@ -21,6 +21,7 @@ #include "opentx.h" #include "radio_calibration.h" #include "sliders.h" +#include "view_main_decoration.h" #define XPOT_DELTA 10 #define XPOT_DELAY 5 /* cycles */ @@ -81,51 +82,14 @@ void RadioCalibrationPage::buildBody(FormWindow * window) new StickCalibrationWindow(window, {40, 20, 90, 90}, STICK1, STICK2); new StickCalibrationWindow(window, {LCD_W - 130, 20, 90, 90}, STICK4, STICK3); -#if defined(PCBHORUS) - - new MainViewHorizontalSlider(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, CALIBRATED_POT1); - - if (IS_POT_MULTIPOS(POT2)) { - new MainView6POS(this, {LCD_W / 2 - MULTIPOS_W / 2, LCD_H - TRIM_SQUARE_SIZE, MULTIPOS_W + 1, MULTIPOS_H}, 1); - } - - new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, CALIBRATED_POT3); -#if defined(HARDWARE_EXT1) - coord_t yOffset = TOPBAR_HEIGHT / 2; - - if (IS_POT_SLIDER_AVAILABLE(EXT1)) { - new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT / 2}, - CALIBRATED_SLIDER_REAR_LEFT); - new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT / 2}, - CALIBRATED_POT_EXT1); - } - else { - new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT}, - CALIBRATED_SLIDER_REAR_LEFT); - } -#endif - -#if defined(HARDWARE_EXT2) - if (IS_POT_SLIDER_AVAILABLE(EXT2)) { - new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT / 2 + yOffset, TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT / 2}, - CALIBRATED_SLIDER_REAR_RIGHT); - new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT / 2}, - CALIBRATED_POT_EXT2); - } - else { - new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT / 2 + yOffset, TRIM_SQUARE_SIZE, - VERTICAL_SLIDERS_HEIGHT}, - CALIBRATED_SLIDER_REAR_RIGHT); - } -#endif - -#elif defined(PCBNV14) - new MainViewHorizontalSlider(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, CALIBRATED_POT1); - - new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE}, CALIBRATED_POT2); + rect_t r = { 0, 0, window->width(), window->height() }; + auto deco = new ViewMainDecoration(window, r); + deco->setTrimsVisible(false); + deco->setSlidersVisible(true); + deco->setFlightModeVisible(false); + deco->adjustDecoration(); +#if defined(PCBNV14) new TextButton(window, {LCD_W - 120, LCD_H - 140, 90, 40}, "Next", [=]() -> uint8_t { nextStep(); diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 386972f33..74e1ecc2d 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -28,17 +28,16 @@ #include "topbar.h" #include "layouts/sliders.h" #include "layouts/trims.h" +#include "view_main_decoration.h" #include "opentx.h" -constexpr coord_t MAIN_ZONE_BORDER = 10; - Layout * customScreens[MAX_CUSTOM_SCREENS] = {}; int getMainViewsCount() { for (int index=1; indexsetVisible(visible); } -void ViewMain::setSlidersVisible(bool visible) -{ - // - // Horizontal Sliders - // - sliders[SLIDERS_POT1]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); - - //TODO: might change depending on hardware settings - if (IS_POT_MULTIPOS(POT2)) { - sliders[SLIDERS_POT2]->setHeight(visible ? MULTIPOS_H : 0); - } - else if (IS_POT(POT2)) { - sliders[SLIDERS_POT2]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); - } - -#if defined(HARDWARE_POT3) - sliders[SLIDERS_POT3]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); -#endif - - // - // Vertical sliders - // - sliders[SLIDERS_REAR_LEFT]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); - -#if defined(HARDWARE_EXT1) - //TODO: might change depending on hardware settings - if (IS_POT_SLIDER_AVAILABLE(EXT1)) { - sliders[SLIDERS_EXT1]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); - } -#endif - - sliders[SLIDERS_REAR_RIGHT]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); - -#if defined(HARDWARE_EXT2) - //TODO: might change depending on hardware settings - if (IS_POT_SLIDER_AVAILABLE(EXT2)) { - sliders[SLIDERS_EXT2]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); - } -#endif -} - void ViewMain::setTrimsVisible(bool visible) { - trims[TRIMS_LH]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); - trims[TRIMS_RH]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + decoration->setTrimsVisible(visible); +} - trims[TRIMS_LV]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); - trims[TRIMS_RV]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); +void ViewMain::setSlidersVisible(bool visible) +{ + decoration->setSlidersVisible(visible); } void ViewMain::setFlightModeVisible(bool visible) { - flightMode->setHeight(visible ? 20 : 0); + decoration->setFlightModeVisible(visible); } void ViewMain::adjustDecoration() { // Topbar does not need any computation // (height() has been set in setTopbarVisible()) - - // Sliders are closer to the edge and must be computed first - // (vertical sliders depends on topbar) - // These are located on the bottom - auto pos = height() - sliders[SLIDERS_POT1]->height(); - sliders[SLIDERS_POT1]->setTop(pos); - - if (sliders[SLIDERS_POT2]) { - auto sl = sliders[SLIDERS_POT2]; - sl->setTop(pos); - if (IS_POT_MULTIPOS(POT2)) { - sl->setWidth(MULTIPOS_W); - } - else { // if !IS_POT(POT2) -> sliders[SLIDERS_POT2] == nullptr - sl->setWidth(HORIZONTAL_SLIDERS_WIDTH); - } - sl->setLeft((width() - sl->width()) / 2); - } - -#if defined(HARDWARE_POT3) - sliders[SLIDERS_POT3]->setTop(pos); -#endif - - // Horizontal trims are on top of horizontal sliders - pos -= trims[TRIMS_LH]->height(); - trims[TRIMS_LH]->setTop(pos); - trims[TRIMS_RH]->setTop(pos); - - // Vertical trims/slider are on top of horizontal sliders with a small margin - auto vertTop = pos - HMARGIN - VERTICAL_SLIDERS_HEIGHT; - - // Left side (vertical) - pos = left(); - sliders[SLIDERS_REAR_LEFT]->setLeft(pos); - sliders[SLIDERS_REAR_LEFT]->setTop(vertTop); - -#if defined(HARDWARE_EXT1) - sliders[SLIDERS_EXT1]->setLeft(pos); - if (IS_POT_SLIDER_AVAILABLE(EXT1)) { - auto rl = sliders[SLIDERS_REAR_LEFT]; - auto e1 = sliders[SLIDERS_EXT1]; - - // If EXT1 is configured as a slider, - // place it bellow rear-left slider (and make them smaller) - rl->setHeight(VERTICAL_SLIDERS_HEIGHT / 2); - e1->setTop(vertTop + rl->height() + HMARGIN/2); - e1->setHeight(rl->height()); - } - else { - auto rl = sliders[SLIDERS_REAR_LEFT]; - auto e1 = sliders[SLIDERS_EXT1]; - - // Otherwise hide the extra slider and make rear-left fullsize - rl->setHeight(VERTICAL_SLIDERS_HEIGHT); - e1->setHeight(0); - } -#endif - - // Right side (vertical) - pos = right() - sliders[SLIDERS_REAR_RIGHT]->width(); - sliders[SLIDERS_REAR_RIGHT]->setLeft(pos); - sliders[SLIDERS_REAR_RIGHT]->setTop(vertTop); - -#if defined(HARDWARE_EXT2) - sliders[SLIDERS_EXT2]->setLeft(pos); - if (IS_POT_SLIDER_AVAILABLE(EXT2)) { - auto rr = sliders[SLIDERS_REAR_RIGHT]; - auto e2 = sliders[SLIDERS_EXT2]; - - // If EXT2 is configured as a slider, - // place it bellow rear-left slider (and make them smaller) - rr->setHeight(VERTICAL_SLIDERS_HEIGHT / 2); - e2->setTop(vertTop + rr->height() + HMARGIN/2); - e2->setHeight(rr->height()); - } - else { - auto rr = sliders[SLIDERS_REAR_RIGHT]; - auto e2 = sliders[SLIDERS_EXT2]; - - // Otherwise hide the extra slider and make rear-left fullsize - rr->setHeight(VERTICAL_SLIDERS_HEIGHT); - e2->setHeight(0); - } -#endif - - // Finally place the vertical trims further from the edge - trims[TRIMS_LV]->setLeft(sliders[SLIDERS_REAR_LEFT]->right()); - trims[TRIMS_LV]->setTop(vertTop); - trims[TRIMS_RV]->setLeft(sliders[SLIDERS_REAR_RIGHT]->left() - trims[TRIMS_RV]->width()); - trims[TRIMS_RV]->setTop(vertTop); - - //TODO: find a proper place for the flight-mode text box + decoration->adjustDecoration(); } rect_t ViewMain::getMainZone() const { - rect_t zone = { - trims[TRIMS_LV]->right() + MAIN_ZONE_BORDER, - topbar->bottom() + MAIN_ZONE_BORDER, - 0, 0 // let's compute them! - }; - - zone.w = trims[TRIMS_RV]->left() - MAIN_ZONE_BORDER - zone.x; - zone.h = trims[TRIMS_LH]->top() - MAIN_ZONE_BORDER - zone.y; - + rect_t zone = decoration->getMainZone(); + zone.y += topbar->bottom(); + zone.h -= topbar->height(); + return zone; } @@ -334,9 +197,7 @@ void ViewMain::paint(BitmapBuffer * dc) void ViewMain::createDecoration() { createTopbar(); - createSliders(); - createTrims(); - createFlightMode(); + decoration = new ViewMainDecoration(this, getRect()); } void ViewMain::createTopbar() @@ -345,93 +206,3 @@ void ViewMain::createTopbar() topbar->load(); } -void ViewMain::createSliders() -{ - // TODO: - // - layout must become really dynamic (see adjustDecoration()) - // - components should be created in "folded" state - // - it should not be required to call hasXXXX() at all - - // fixed size array, so that works - memset(sliders, 0, sizeof(sliders)); - - rect_t r = { - // left - HMARGIN, 0, - HORIZONTAL_SLIDERS_WIDTH, 0 - }; - - sliders[SLIDERS_POT1] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT1); - - r = rect_t { 0, 0, 0, 0 }; - if (IS_POT_MULTIPOS(POT2)) { - sliders[SLIDERS_POT2] = new MainView6POS(this, r, 1); - } - else if (IS_POT(POT2)) { - sliders[SLIDERS_POT2] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT2); - } - -#if defined(HARDWARE_POT3) - r = rect_t { - // right - width() - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, 0, - HORIZONTAL_SLIDERS_WIDTH, 0 - }; - - sliders[SLIDERS_POT3] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT3); -#endif - - r = rect_t { 0, 0, 0, 0 }; - sliders[SLIDERS_REAR_LEFT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_LEFT); - sliders[SLIDERS_REAR_RIGHT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_RIGHT); - -#if defined(HARDWARE_EXT1) - sliders[SLIDERS_EXT1] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT1); -#endif - -#if defined(HARDWARE_EXT2) - sliders[SLIDERS_EXT2] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT2); -#endif -} - -void ViewMain::createTrims() -{ - // Trim order TRIM_LH, TRIM_LV, TRIM_RV, TRIM_RH - - rect_t r = { - left() + HMARGIN, 0, - HORIZONTAL_SLIDERS_WIDTH, 0 - }; - - trims[TRIMS_LH] = new MainViewHorizontalTrim(this, r, 0); - - r = rect_t { - right() - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, 0, - HORIZONTAL_SLIDERS_WIDTH, 0 - }; - - trims[TRIMS_RH] = new MainViewHorizontalTrim(this, r, 3); - - r = rect_t { - 0, 0, 0, - VERTICAL_SLIDERS_HEIGHT - }; - - trims[TRIMS_LV] = new MainViewVerticalTrim(this, r, 1); - trims[TRIMS_RV] = new MainViewVerticalTrim(this, r, 2); -} - -void ViewMain::createFlightMode() -{ - rect_t r = { - // centered text box (50 pixels from either edge) - // -> re-size once the other components are set - 50, 0, width() - 100, 0 - }; - - std::function getFM = []() -> std::string { - return g_model.flightModeData[mixerCurrentFlightMode].name; - }; - - flightMode = new DynamicText(this, r, getFM, CENTERED); -} diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 1cd241dcf..1c6390181 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -25,6 +25,7 @@ #include class TopBar; +class ViewMainDecoration; class SetupWidgetsPage; class ViewMain: public FormWindow @@ -50,7 +51,7 @@ class ViewMain: public FormWindow } #endif - // Set decoration visibility + // Set topbar & decoration visibility void setTopbarVisible(bool visible); void setTrimsVisible(bool visible); void setSlidersVisible(bool visible); @@ -66,29 +67,8 @@ class ViewMain: public FormWindow protected: static ViewMain * _instance; - enum { - SLIDERS_POT1 = 0, - SLIDERS_POT2, - SLIDERS_POT3, - SLIDERS_REAR_LEFT, - SLIDERS_EXT1, - SLIDERS_REAR_RIGHT, - SLIDERS_EXT2, - SLIDERS_MAX - }; - - enum { - TRIMS_LH = 0, - TRIMS_LV, - TRIMS_RV, - TRIMS_RH, - TRIMS_MAX - }; - - TopBar* topbar; - Window* sliders[SLIDERS_MAX]; - Window* trims[TRIMS_MAX]; - Window* flightMode; + TopBar* topbar; + ViewMainDecoration* decoration; friend class SetupWidgetsPage; @@ -101,9 +81,6 @@ class ViewMain: public FormWindow void createDecoration(); void createTopbar(); - void createSliders(); - void createTrims(); - void createFlightMode(); }; #endif // _VIEW_MAIN_H_ diff --git a/radio/src/gui/colorlcd/view_main_decoration.cpp b/radio/src/gui/colorlcd/view_main_decoration.cpp new file mode 100644 index 000000000..e16a0ed58 --- /dev/null +++ b/radio/src/gui/colorlcd/view_main_decoration.cpp @@ -0,0 +1,287 @@ +/* + * 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 "view_main_decoration.h" +#include "layout.h" + +// because of IS_POT_MULTIPOS() and pal +#include "opentx.h" + +// these 2 need things from opentx.h +#include "layouts/sliders.h" +#include "layouts/trims.h" + +#include "board.h" + +void ViewMainDecoration::setSlidersVisible(bool visible) +{ + // + // Horizontal Sliders + // + sliders[SLIDERS_POT1]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + + //TODO: might change depending on hardware settings + if (IS_POT_MULTIPOS(POT2)) { + sliders[SLIDERS_POT2]->setHeight(visible ? MULTIPOS_H : 0); + } + else if (IS_POT(POT2)) { + sliders[SLIDERS_POT2]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + } + +#if defined(HARDWARE_POT3) + sliders[SLIDERS_POT3]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); +#endif + + // + // Vertical sliders + // + sliders[SLIDERS_REAR_LEFT]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + +#if defined(HARDWARE_EXT1) + //TODO: might change depending on hardware settings + if (IS_POT_SLIDER_AVAILABLE(EXT1)) { + sliders[SLIDERS_EXT1]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + } +#endif + + sliders[SLIDERS_REAR_RIGHT]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + +#if defined(HARDWARE_EXT2) + //TODO: might change depending on hardware settings + if (IS_POT_SLIDER_AVAILABLE(EXT2)) { + sliders[SLIDERS_EXT2]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + } +#endif +} + +void ViewMainDecoration::setTrimsVisible(bool visible) +{ + trims[TRIMS_LH]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + trims[TRIMS_RH]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); + + trims[TRIMS_LV]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); + trims[TRIMS_RV]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); +} + +void ViewMainDecoration::setFlightModeVisible(bool visible) +{ + flightMode->setHeight(visible ? 20 : 0); +} + +void ViewMainDecoration::adjustDecoration() +{ + // Sliders are closer to the edge and must be computed first + + // These are located on the bottom + auto pos = bottom() - sliders[SLIDERS_POT1]->height(); + sliders[SLIDERS_POT1]->setTop(pos); + + if (sliders[SLIDERS_POT2]) { + auto sl = sliders[SLIDERS_POT2]; + sl->setTop(pos); + if (IS_POT_MULTIPOS(POT2)) { + sl->setWidth(MULTIPOS_W); + } + else { // if !IS_POT(POT2) -> sliders[SLIDERS_POT2] == nullptr + sl->setWidth(HORIZONTAL_SLIDERS_WIDTH); + } + sl->setLeft((width() - sl->width()) / 2); + } + +#if defined(HARDWARE_POT3) + sliders[SLIDERS_POT3]->setTop(pos); +#endif + + // Horizontal trims are on top of horizontal sliders + pos -= trims[TRIMS_LH]->height(); + trims[TRIMS_LH]->setTop(pos); + trims[TRIMS_RH]->setTop(pos); + + // Vertical trims/slider are on top of horizontal sliders with a small margin + auto vertTop = pos - HMARGIN - VERTICAL_SLIDERS_HEIGHT; + + // Left side (vertical) + pos = left(); + sliders[SLIDERS_REAR_LEFT]->setLeft(pos); + sliders[SLIDERS_REAR_LEFT]->setTop(vertTop); + +#if defined(HARDWARE_EXT1) + sliders[SLIDERS_EXT1]->setLeft(pos); + if (IS_POT_SLIDER_AVAILABLE(EXT1)) { + auto rl = sliders[SLIDERS_REAR_LEFT]; + auto e1 = sliders[SLIDERS_EXT1]; + + // If EXT1 is configured as a slider, + // place it bellow rear-left slider (and make them smaller) + rl->setHeight(VERTICAL_SLIDERS_HEIGHT / 2); + e1->setTop(vertTop + rl->height() + HMARGIN/2); + e1->setHeight(rl->height()); + } + else { + auto rl = sliders[SLIDERS_REAR_LEFT]; + auto e1 = sliders[SLIDERS_EXT1]; + + // Otherwise hide the extra slider and make rear-left fullsize + rl->setHeight(VERTICAL_SLIDERS_HEIGHT); + e1->setHeight(0); + } +#endif + + // Right side (vertical) + pos = right() - sliders[SLIDERS_REAR_RIGHT]->width(); + sliders[SLIDERS_REAR_RIGHT]->setLeft(pos); + sliders[SLIDERS_REAR_RIGHT]->setTop(vertTop); + +#if defined(HARDWARE_EXT2) + sliders[SLIDERS_EXT2]->setLeft(pos); + if (IS_POT_SLIDER_AVAILABLE(EXT2)) { + auto rr = sliders[SLIDERS_REAR_RIGHT]; + auto e2 = sliders[SLIDERS_EXT2]; + + // If EXT2 is configured as a slider, + // place it bellow rear-left slider (and make them smaller) + rr->setHeight(VERTICAL_SLIDERS_HEIGHT / 2); + e2->setTop(vertTop + rr->height() + HMARGIN/2); + e2->setHeight(rr->height()); + } + else { + auto rr = sliders[SLIDERS_REAR_RIGHT]; + auto e2 = sliders[SLIDERS_EXT2]; + + // Otherwise hide the extra slider and make rear-left fullsize + rr->setHeight(VERTICAL_SLIDERS_HEIGHT); + e2->setHeight(0); + } +#endif + + // Finally place the vertical trims further from the edge + trims[TRIMS_LV]->setLeft(sliders[SLIDERS_REAR_LEFT]->right()); + trims[TRIMS_LV]->setTop(vertTop); + trims[TRIMS_RV]->setLeft(sliders[SLIDERS_REAR_RIGHT]->left() - trims[TRIMS_RV]->width()); + trims[TRIMS_RV]->setTop(vertTop); + + //TODO: find a proper place for the flight-mode text box +} + +rect_t ViewMainDecoration::getMainZone() const +{ + rect_t zone = { + trims[TRIMS_LV]->right() + MAIN_ZONE_BORDER, + /*topbar->bottom() +*/ MAIN_ZONE_BORDER, + 0, 0 // let's compute them! + }; + + zone.w = trims[TRIMS_RV]->left() - MAIN_ZONE_BORDER - zone.x; + zone.h = trims[TRIMS_LH]->top() - MAIN_ZONE_BORDER - zone.y; + + return zone; +} + +void ViewMainDecoration::createSliders() +{ + // TODO: + // - layout must become really dynamic (see adjustDecoration()) + // - components should be created in "folded" state + // - it should not be required to call hasXXXX() at all + + // fixed size array, so that works + memset(sliders, 0, sizeof(sliders)); + + rect_t r = { + // left + HMARGIN, 0, + HORIZONTAL_SLIDERS_WIDTH, 0 + }; + + sliders[SLIDERS_POT1] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT1); + + r = rect_t { 0, 0, 0, 0 }; + if (IS_POT_MULTIPOS(POT2)) { + sliders[SLIDERS_POT2] = new MainView6POS(this, r, 1); + } + else if (IS_POT(POT2)) { + sliders[SLIDERS_POT2] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT2); + } + +#if defined(HARDWARE_POT3) + r = rect_t { + // right + width() - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, 0, + HORIZONTAL_SLIDERS_WIDTH, 0 + }; + + sliders[SLIDERS_POT3] = new MainViewHorizontalSlider(this, r, CALIBRATED_POT3); +#endif + + r = rect_t { 0, 0, 0, 0 }; + sliders[SLIDERS_REAR_LEFT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_LEFT); + sliders[SLIDERS_REAR_RIGHT] = new MainViewVerticalSlider(this, r, CALIBRATED_SLIDER_REAR_RIGHT); + +#if defined(HARDWARE_EXT1) + sliders[SLIDERS_EXT1] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT1); +#endif + +#if defined(HARDWARE_EXT2) + sliders[SLIDERS_EXT2] = new MainViewVerticalSlider(this, r, CALIBRATED_POT_EXT2); +#endif +} + +void ViewMainDecoration::createTrims() +{ + // Trim order TRIM_LH, TRIM_LV, TRIM_RV, TRIM_RH + + rect_t r = { + left() + HMARGIN, 0, + HORIZONTAL_SLIDERS_WIDTH, 0 + }; + + trims[TRIMS_LH] = new MainViewHorizontalTrim(this, r, 0); + + r = rect_t { + right() - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, 0, + HORIZONTAL_SLIDERS_WIDTH, 0 + }; + + trims[TRIMS_RH] = new MainViewHorizontalTrim(this, r, 3); + + r = rect_t { + 0, 0, 0, + VERTICAL_SLIDERS_HEIGHT + }; + + trims[TRIMS_LV] = new MainViewVerticalTrim(this, r, 1); + trims[TRIMS_RV] = new MainViewVerticalTrim(this, r, 2); +} + +void ViewMainDecoration::createFlightMode() +{ + rect_t r = { + // centered text box (50 pixels from either edge) + // -> re-size once the other components are set + 50, 0, width() - 100, 0 + }; + + std::function getFM = []() -> std::string { + return g_model.flightModeData[mixerCurrentFlightMode].name; + }; + + flightMode = new DynamicText(this, r, getFM, CENTERED); +} + diff --git a/radio/src/gui/colorlcd/view_main_decoration.h b/radio/src/gui/colorlcd/view_main_decoration.h new file mode 100644 index 000000000..3a35e1a63 --- /dev/null +++ b/radio/src/gui/colorlcd/view_main_decoration.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + +#pragma once + +#include "window.h" + +class ViewMainDecoration: public Window +{ + public: + ViewMainDecoration(Window * parent, const rect_t & rect): + Window(parent, rect) + { + createSliders(); + createTrims(); + createFlightMode(); + } + + // Set decoration visibility + void setTrimsVisible(bool visible); + void setSlidersVisible(bool visible); + void setFlightModeVisible(bool visible); + + // Re-calculate positions + void adjustDecoration(); + + // Get the available space in the middle of the screen + // (without decoration) + rect_t getMainZone() const; + + protected: + +#if defined(DEBUG_WINDOWS) + virtual std::string getName() const + { + return "ViewMainDecoration"; + } +#endif + + enum { + SLIDERS_POT1 = 0, + SLIDERS_POT2, + SLIDERS_POT3, + SLIDERS_REAR_LEFT, + SLIDERS_EXT1, + SLIDERS_REAR_RIGHT, + SLIDERS_EXT2, + SLIDERS_MAX + }; + + enum { + TRIMS_LH = 0, + TRIMS_LV, + TRIMS_RV, + TRIMS_RH, + TRIMS_MAX + }; + + Window* sliders[SLIDERS_MAX]; + Window* trims[TRIMS_MAX]; + Window* flightMode; + + void createSliders(); + void createTrims(); + void createFlightMode(); +}; From 0a7d4c43f5aebbe73145b8586bf1cbeed3af0f28 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 15 Apr 2021 09:14:52 +0200 Subject: [PATCH 11/54] Fixed missing include --- radio/src/gui/colorlcd/tabsgroup.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio/src/gui/colorlcd/tabsgroup.cpp b/radio/src/gui/colorlcd/tabsgroup.cpp index 66f73c98c..eab15ee3f 100644 --- a/radio/src/gui/colorlcd/tabsgroup.cpp +++ b/radio/src/gui/colorlcd/tabsgroup.cpp @@ -27,6 +27,8 @@ #include "opentx.h" // TODO for constants... +#include + TabsGroupHeader::TabsGroupHeader(TabsGroup * parent, uint8_t icon): FormGroup(parent, { 0, 0, LCD_W, MENU_BODY_TOP }, OPAQUE), #if defined(HARDWARE_TOUCH) From ef6f2d0c57d55fe7cd50e19edb6463edfd637d8e Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 15 Apr 2021 10:44:20 +0200 Subject: [PATCH 12/54] Scrolling from view to view works now And quite some bugs & crashes fixed. --- radio/src/audio.cpp | 4 + radio/src/curves.cpp | 4 + radio/src/gui/colorlcd/curveedit.cpp | 1 + radio/src/gui/colorlcd/fullscreen_dialog.cpp | 1 + radio/src/gui/colorlcd/gvar_numberedit.h | 1 + radio/src/gui/colorlcd/layout.cpp | 52 ++++++++++- radio/src/gui/colorlcd/layout.h | 21 ++--- radio/src/gui/colorlcd/layouts/layout2x4.cpp | 8 +- radio/src/gui/colorlcd/model_flightmodes.cpp | 1 + radio/src/gui/colorlcd/model_inputs.cpp | 3 +- radio/src/gui/colorlcd/model_select.cpp | 1 + radio/src/gui/colorlcd/radio_diaganas.cpp | 1 + radio/src/gui/colorlcd/radio_diagkeys.cpp | 1 + .../colorlcd/radio_ghost_module_config.cpp | 1 + radio/src/gui/colorlcd/radio_hardware.cpp | 1 + radio/src/gui/colorlcd/radio_setup.cpp | 1 + .../gui/colorlcd/radio_spectrum_analyser.cpp | 1 + radio/src/gui/colorlcd/radio_trainer.cpp | 1 + radio/src/gui/colorlcd/screen_setup.cpp | 53 +++++++---- radio/src/gui/colorlcd/special_functions.cpp | 1 + radio/src/gui/colorlcd/theme.cpp | 2 + radio/src/gui/colorlcd/themes/480_default.cpp | 2 +- radio/src/gui/colorlcd/topbar.cpp | 11 +++ radio/src/gui/colorlcd/topbar.h | 8 +- .../gui/colorlcd/view_logical_switches.cpp | 1 + .../src/gui/colorlcd/view_logical_switches.h | 1 + radio/src/gui/colorlcd/view_main.cpp | 92 ++++++++++++++++--- radio/src/gui/colorlcd/view_main.h | 12 ++- .../src/gui/colorlcd/view_main_decoration.cpp | 4 +- radio/src/gui/colorlcd/view_statistics.h | 4 +- radio/src/gui/colorlcd/widget.h | 11 ++- radio/src/gui/colorlcd/widget_settings.cpp | 29 +++--- radio/src/gui/colorlcd/widgets/outputs.cpp | 15 +++ radio/src/gui/colorlcd/zone.h | 8 +- radio/src/io/bootloader_flash.cpp | 1 + radio/src/io/frsky_firmware_update.cpp | 3 +- radio/src/io/multi_firmware_update.cpp | 1 + radio/src/logs.cpp | 4 + radio/src/lua/api_general.cpp | 4 + radio/src/lua/interface.cpp | 5 +- radio/src/main.cpp | 2 +- radio/src/opentx.cpp | 7 +- radio/src/opentx.h | 4 - radio/src/sdcard.cpp | 5 +- radio/src/simu.cpp | 2 +- radio/src/targets/horus/libopenui_config.h | 2 +- radio/src/targets/simu/CMakeLists.txt | 5 +- radio/src/telemetry/frsky_pxx2.cpp | 4 + radio/src/telemetry/telemetry.cpp | 4 + radio/src/telemetry/telemetry_sensors.cpp | 4 + 50 files changed, 315 insertions(+), 100 deletions(-) diff --git a/radio/src/audio.cpp b/radio/src/audio.cpp index 42a8acae1..02fd5acb4 100644 --- a/radio/src/audio.cpp +++ b/radio/src/audio.cpp @@ -21,6 +21,10 @@ #include "opentx.h" #include +#if defined(LIBOPENUI) + #include "libopenui.h" +#endif + extern RTOS_MUTEX_HANDLE audioMutex; const int16_t sineValues[] = diff --git a/radio/src/curves.cpp b/radio/src/curves.cpp index fe1dc377b..0bac367b9 100644 --- a/radio/src/curves.cpp +++ b/radio/src/curves.cpp @@ -20,6 +20,10 @@ #include "opentx.h" +#if defined(LIBOPENUI) + #include "libopenui.h" +#endif + int8_t * curveEnd[MAX_CURVES]; void loadCurves() diff --git a/radio/src/gui/colorlcd/curveedit.cpp b/radio/src/gui/colorlcd/curveedit.cpp index b1760bd32..9eb248083 100644 --- a/radio/src/gui/colorlcd/curveedit.cpp +++ b/radio/src/gui/colorlcd/curveedit.cpp @@ -21,6 +21,7 @@ #include "curveedit.h" #include "keyboard_curve.h" #include "opentx.h" // TODO for applyCustomCurve +#include "libopenui.h" #define SET_DIRTY() storageDirty(EE_MODEL) diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.cpp b/radio/src/gui/colorlcd/fullscreen_dialog.cpp index 49ffaefa0..0a3fd3542 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.cpp +++ b/radio/src/gui/colorlcd/fullscreen_dialog.cpp @@ -21,6 +21,7 @@ #include "fullscreen_dialog.h" #include "mainwindow.h" #include "opentx.h" +#include "libopenui.h" FullScreenDialog::FullScreenDialog(uint8_t type, std::string title, std::string message, std::string action, const std::function & confirmHandler): FormGroup(MainWindow::instance(), {0, 0, LCD_W, LCD_H}, OPAQUE), diff --git a/radio/src/gui/colorlcd/gvar_numberedit.h b/radio/src/gui/colorlcd/gvar_numberedit.h index ac3b3e833..9051b3607 100644 --- a/radio/src/gui/colorlcd/gvar_numberedit.h +++ b/radio/src/gui/colorlcd/gvar_numberedit.h @@ -21,6 +21,7 @@ #define _GVAR_NUMBEREDIT_H_ #include "form.h" +#include "choice.h" #include "numberedit.h" #include "gvars.h" diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index d2731bb76..e15e41d92 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -23,6 +23,10 @@ #include "layouts/trims.h" #include "layouts/sliders.h" +constexpr uint32_t LAYOUT_REFRESH = 1000 / 2; // 2 Hz + +Layout * customScreens[MAX_CUSTOM_SCREENS] = {}; + std::list & getRegisteredLayouts() { static std::list layouts; @@ -100,15 +104,24 @@ void loadDefaultLayout() // void loadCustomScreens() { - for (unsigned int i = 0; i < MAX_CUSTOM_SCREENS; i++) { + unsigned i = 0; + while (i < MAX_CUSTOM_SCREENS) { auto& screen = customScreens[i]; screen = loadLayout(g_model.screenData[i].LayoutId, &g_model.screenData[i].layoutData); - if (screen) { - screen->attach(ViewMain::instance()); + if (!screen) { + // no more layouts + break; } + + // layout is ok, let's add it + auto viewMain = ViewMain::instance(); + screen->attach(viewMain); + viewMain->setMainViewsCount(i + 1); + screen->setLeft(viewMain->getMainViewLeftPos(i)); + i++; } } @@ -159,6 +172,39 @@ void disposeCustomScreen(unsigned idx) memset(dst, 0, len); } +void Layout::create() +{ + memset(persistentData, 0, sizeof(PersistentData)); + + getOptionValue(OPTION_TOPBAR)->boolValue = true; + getOptionValue(OPTION_FM)->boolValue = true; + getOptionValue(OPTION_SLIDERS)->boolValue = true; + getOptionValue(OPTION_TRIMS)->boolValue = true; + getOptionValue(OPTION_MIRRORED)->boolValue = false; +} + +#if defined(DEBUG_WINDOWS) +void Layout::paint(BitmapBuffer * dc) +{ + TRACE("### painting -> %s", getWindowDebugString().c_str()); + //rect_t zone = getMainZone(); + //dc->drawSolidFilledRect( zone.x, zone.y + rect.y, zone.w, zone.h, DEFAULT_BGCOLOR); + LayoutBase::paint(dc); +} +#endif + +void Layout::checkEvents() +{ + LayoutBase::checkEvents(); + decorate(); + + // uint32_t now = RTOS_GET_MS(); + // if (now - lastRefresh >= LAYOUT_REFRESH) { + // lastRefresh = now; + // invalidate(); + // } +} + void Layout::decorate() { // Check if deco setting are still up-to-date diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index 48b9e9200..d96aeef0f 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -74,28 +74,18 @@ class Layout: public LayoutBase { return "Layout"; } + + void paint(BitmapBuffer * dc) override; #endif - void create() override - { - setOptionValue(OPTION_TOPBAR, OPTION_VALUE_BOOL(true)); - setOptionValue(OPTION_FM, OPTION_VALUE_BOOL(true)); - setOptionValue(OPTION_SLIDERS, OPTION_VALUE_BOOL(true)); - setOptionValue(OPTION_TRIMS, OPTION_VALUE_BOOL(true)); - setOptionValue(OPTION_MIRRORED, OPTION_VALUE_BOOL(false)); - decorate(); - } + void create() override; inline const LayoutFactory * getFactory() const { return factory; } - void checkEvents() override - { - LayoutBase::checkEvents(); - decorate(); - } + void checkEvents() override; bool hasTopbar() const { return getOptionValue(OPTION_TOPBAR)->boolValue; @@ -123,6 +113,9 @@ class Layout: public LayoutBase // Decoration settings bitmask to detect updates uint8_t decorationSettings = 0; + // Last time we refreshed the window + uint32_t lastRefresh = 0; + // Updates settings for trims, sliders, pots, etc... void decorate(); diff --git a/radio/src/gui/colorlcd/layouts/layout2x4.cpp b/radio/src/gui/colorlcd/layouts/layout2x4.cpp index c3e6a0d02..618f98a6f 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x4.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x4.cpp @@ -52,10 +52,10 @@ class Layout2x4: public Layout void create() override { Layout::create(); - setOptionValue(OPTION_PANEL1_BACKGROUND, OPTION_VALUE_BOOL(true)); - setOptionValue(OPTION_PANEL1_COLOR, OPTION_VALUE_UNSIGNED( RGB(77,112,203))); - setOptionValue(OPTION_PANEL2_BACKGROUND, OPTION_VALUE_BOOL(true)); - setOptionValue(OPTION_PANEL2_COLOR, OPTION_VALUE_UNSIGNED( RGB(77,112,203))); + getOptionValue(OPTION_PANEL1_BACKGROUND)->boolValue = true; + getOptionValue(OPTION_PANEL1_COLOR)->unsignedValue = RGB(77,112,203); + getOptionValue(OPTION_PANEL2_BACKGROUND)->boolValue = true; + getOptionValue(OPTION_PANEL2_COLOR)->unsignedValue = RGB(77,112,203); } unsigned int getZonesCount() const override diff --git a/radio/src/gui/colorlcd/model_flightmodes.cpp b/radio/src/gui/colorlcd/model_flightmodes.cpp index 841e98d91..b8a70fb9a 100644 --- a/radio/src/gui/colorlcd/model_flightmodes.cpp +++ b/radio/src/gui/colorlcd/model_flightmodes.cpp @@ -20,6 +20,7 @@ #include "model_flightmodes.h" #include "opentx.h" +#include "libopenui.h" #define SET_DIRTY() storageDirty(EE_MODEL) diff --git a/radio/src/gui/colorlcd/model_inputs.cpp b/radio/src/gui/colorlcd/model_inputs.cpp index 78596644d..ce6a797a3 100644 --- a/radio/src/gui/colorlcd/model_inputs.cpp +++ b/radio/src/gui/colorlcd/model_inputs.cpp @@ -21,6 +21,7 @@ #include "model_inputs.h" #include "opentx.h" #include "gvar_numberedit.h" +#include "libopenui.h" #define SET_DIRTY() storageDirty(EE_MODEL) @@ -527,4 +528,4 @@ void insertExpo(uint8_t idx, uint8_t input) expo->weight = 100; resumeMixerCalculations(); storageDirty(EE_MODEL); -} \ No newline at end of file +} diff --git a/radio/src/gui/colorlcd/model_select.cpp b/radio/src/gui/colorlcd/model_select.cpp index 53017aef8..2dbc75c93 100644 --- a/radio/src/gui/colorlcd/model_select.cpp +++ b/radio/src/gui/colorlcd/model_select.cpp @@ -22,6 +22,7 @@ #include "model_select.h" #include "opentx.h" #include "storage/modelslist.h" +#include "libopenui.h" #define CATEGORIES_WIDTH 120 #define MODELS_LEFT 123 diff --git a/radio/src/gui/colorlcd/radio_diaganas.cpp b/radio/src/gui/colorlcd/radio_diaganas.cpp index 23be1e154..f08d848c6 100644 --- a/radio/src/gui/colorlcd/radio_diaganas.cpp +++ b/radio/src/gui/colorlcd/radio_diaganas.cpp @@ -20,6 +20,7 @@ #include "opentx.h" #include "radio_diaganas.h" +#include "libopenui.h" constexpr coord_t ANA_OFFSET = 150; diff --git a/radio/src/gui/colorlcd/radio_diagkeys.cpp b/radio/src/gui/colorlcd/radio_diagkeys.cpp index f4c4e54ff..6f0c5f033 100644 --- a/radio/src/gui/colorlcd/radio_diagkeys.cpp +++ b/radio/src/gui/colorlcd/radio_diagkeys.cpp @@ -20,6 +20,7 @@ #include "opentx.h" #include "radio_diagkeys.h" +#include "libopenui.h" #if defined(KEYS_GPIO_PIN_PGUP) constexpr uint8_t KEY_START = 0; diff --git a/radio/src/gui/colorlcd/radio_ghost_module_config.cpp b/radio/src/gui/colorlcd/radio_ghost_module_config.cpp index e97a211c5..368c0c195 100644 --- a/radio/src/gui/colorlcd/radio_ghost_module_config.cpp +++ b/radio/src/gui/colorlcd/radio_ghost_module_config.cpp @@ -20,6 +20,7 @@ #include "opentx.h" #include "radio_ghost_module_config.h" +#include "libopenui.h" class GhostModuleConfigWindow: public Window { diff --git a/radio/src/gui/colorlcd/radio_hardware.cpp b/radio/src/gui/colorlcd/radio_hardware.cpp index c2839c4b3..0b4132e7b 100644 --- a/radio/src/gui/colorlcd/radio_hardware.cpp +++ b/radio/src/gui/colorlcd/radio_hardware.cpp @@ -23,6 +23,7 @@ #include "radio_diagkeys.h" #include "radio_diaganas.h" #include "opentx.h" +#include "libopenui.h" #define SET_DIRTY() storageDirty(EE_GENERAL) diff --git a/radio/src/gui/colorlcd/radio_setup.cpp b/radio/src/gui/colorlcd/radio_setup.cpp index 3b13677e6..5e40c7f5f 100644 --- a/radio/src/gui/colorlcd/radio_setup.cpp +++ b/radio/src/gui/colorlcd/radio_setup.cpp @@ -22,6 +22,7 @@ #include "radio_setup.h" #include "opentx.h" +#include "libopenui.h" #define SET_DIRTY() storageDirty(EE_GENERAL) diff --git a/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp b/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp index 5df010844..4ea32a864 100644 --- a/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp +++ b/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp @@ -20,6 +20,7 @@ #include "radio_spectrum_analyser.h" #include "opentx.h" +#include "libopenui.h" #define SET_DIRTY() storageDirty(EE_GENERAL) diff --git a/radio/src/gui/colorlcd/radio_trainer.cpp b/radio/src/gui/colorlcd/radio_trainer.cpp index 53edb620c..202a732f9 100644 --- a/radio/src/gui/colorlcd/radio_trainer.cpp +++ b/radio/src/gui/colorlcd/radio_trainer.cpp @@ -20,6 +20,7 @@ #include "radio_trainer.h" #include "opentx.h" +#include "libopenui.h" #define SET_DIRTY() storageDirty(EE_GENERAL) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 084155c31..e33864e18 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -23,6 +23,7 @@ #include "opentx.h" #include "view_main.h" #include "widget_settings.h" +#include "libopenui.h" #define SET_DIRTY() storageDirty(EE_MODEL) @@ -172,6 +173,7 @@ class SetupWidgetsPage: public FormWindow auto screen = customScreens[customScreenIdx]; if (screen) { screen->attach(this); + screen->setLeft(0); setRect(screen->getRect()); } @@ -200,7 +202,9 @@ class SetupWidgetsPage: public FormWindow #endif auto screen = customScreens[customScreenIdx]; if (screen) { - screen->attach(ViewMain::instance()); + auto viewMain = ViewMain::instance(); + screen->setLeft(viewMain->getMainViewLeftPos(customScreenIdx)); + screen->attach(viewMain); } FormWindow::deleteLater(detach, trash); @@ -277,33 +281,44 @@ void ScreenAddPage::build(FormWindow * window) // First page is "User interface", subtract it auto newIdx = pageIndex - 1; - + TRACE("ScreenAddPage: add screen: newIdx = %d", newIdx); + auto& screen = customScreens[newIdx]; auto& screenData = g_model.screenData[newIdx]; + TRACE("ScreenAddPage: add screen: screen = %p", screen); + const LayoutFactory * factory = defaultLayout; - screen = factory->create(&screenData.layoutData); - strncpy(screenData.LayoutId, factory->getId(), sizeof(screenData.LayoutId)); + if (factory) { + TRACE("ScreenAddPage: add screen: factory = %p", factory); + screen = factory->create(&screenData.layoutData); - auto tab = new ScreenSetupPage(menu, pageIndex, newIdx); - std::string title(STR_MAIN_VIEW_X); - title.back() = newIdx + '1'; - tab->setTitle(title); - tab->setIcon(ICON_THEME_VIEW1 + newIdx); + strncpy(screenData.LayoutId, factory->getId(), sizeof(screenData.LayoutId)); + TRACE("ScreenAddPage: add screen: LayoutId = %s", screenData.LayoutId); - // remove current tab first - menu->setCurrentTab(0); - menu->removeTab(pageIndex); + auto tab = new ScreenSetupPage(menu, pageIndex, newIdx); + std::string title(STR_MAIN_VIEW_X); + title.back() = newIdx + '1'; + tab->setTitle(title); + tab->setIcon(ICON_THEME_VIEW1 + newIdx); - // add the new one - menu->addTab(tab); - menu->setCurrentTab(pageIndex); + // remove current tab first + menu->setCurrentTab(0); + menu->removeTab(pageIndex); - if (menu->getTabs() < MAX_CUSTOM_SCREENS) { - menu->addTab(new ScreenAddPage(menu, menu->getTabs())); + // add the new one + menu->addTab(tab); + menu->setCurrentTab(pageIndex); + + if (menu->getTabs() < MAX_CUSTOM_SCREENS) { + menu->addTab(new ScreenAddPage(menu, menu->getTabs())); + } + + storageDirty(EE_MODEL); + } + else { + TRACE("Add main view: factory is NULL"); } - - storageDirty(EE_MODEL); return 0; }); } diff --git a/radio/src/gui/colorlcd/special_functions.cpp b/radio/src/gui/colorlcd/special_functions.cpp index 2b076a32a..5d8f03bae 100644 --- a/radio/src/gui/colorlcd/special_functions.cpp +++ b/radio/src/gui/colorlcd/special_functions.cpp @@ -20,6 +20,7 @@ #include "special_functions.h" #include "opentx.h" +#include "libopenui.h" #define SET_DIRTY() storageDirty(functions == g_model.customFn ? EE_MODEL : EE_GENERAL) diff --git a/radio/src/gui/colorlcd/theme.cpp b/radio/src/gui/colorlcd/theme.cpp index 1a9ba857c..e0fcd422a 100644 --- a/radio/src/gui/colorlcd/theme.cpp +++ b/radio/src/gui/colorlcd/theme.cpp @@ -19,6 +19,8 @@ */ #include "opentx.h" +#include "libopenui.h" + //#include "checkbox.h" //#include "modal_window.h" diff --git a/radio/src/gui/colorlcd/themes/480_default.cpp b/radio/src/gui/colorlcd/themes/480_default.cpp index 8479e3fb5..3e0947282 100644 --- a/radio/src/gui/colorlcd/themes/480_default.cpp +++ b/radio/src/gui/colorlcd/themes/480_default.cpp @@ -316,7 +316,7 @@ class Theme480: public OpenTxTheme void drawBackground(BitmapBuffer * dc) const override { if (backgroundBitmap) { - dc->drawBitmap(0, 0, backgroundBitmap); + dc->drawBitmap(0 - dc->getOffsetX(), 0 - dc->getOffsetY(), backgroundBitmap); } else { lcdSetColor(g_eeGeneral.themeData.options[0].value.unsignedValue); diff --git a/radio/src/gui/colorlcd/topbar.cpp b/radio/src/gui/colorlcd/topbar.cpp index ed9d92a7f..fe3694962 100644 --- a/radio/src/gui/colorlcd/topbar.cpp +++ b/radio/src/gui/colorlcd/topbar.cpp @@ -20,6 +20,8 @@ #include "opentx.h" +constexpr uint32_t TOPBAR_REFRESH = 1000 / 2; // 2 Hz + TopBar::TopBar(Window * parent) : WidgetsContainer({0, 0, LCD_W, MENU_HEADER_HEIGHT}, &g_model.topbarData) { @@ -160,3 +162,12 @@ void TopBar::paint(BitmapBuffer * dc) } #endif } + +void TopBar::checkEvents() +{ + // uint32_t now = RTOS_GET_MS(); + // if (now - lastRefresh >= TOPBAR_REFRESH) { + // lastRefresh = now; + // invalidate(); + // } +} diff --git a/radio/src/gui/colorlcd/topbar.h b/radio/src/gui/colorlcd/topbar.h index 404b0aaac..c0c2596a2 100644 --- a/radio/src/gui/colorlcd/topbar.h +++ b/radio/src/gui/colorlcd/topbar.h @@ -49,10 +49,10 @@ class TopBar: public WidgetsContainer void paint(BitmapBuffer * dc) override; - void checkEvents() override - { - invalidate(); - } + void checkEvents() override; + + protected: + uint32_t lastRefresh = 0; }; #endif // _TOPBAR_H_ diff --git a/radio/src/gui/colorlcd/view_logical_switches.cpp b/radio/src/gui/colorlcd/view_logical_switches.cpp index 233e6439b..d8c5afc3e 100644 --- a/radio/src/gui/colorlcd/view_logical_switches.cpp +++ b/radio/src/gui/colorlcd/view_logical_switches.cpp @@ -20,6 +20,7 @@ #include "opentx.h" #include "view_logical_switches.h" +#include "gridlayout.h" #include diff --git a/radio/src/gui/colorlcd/view_logical_switches.h b/radio/src/gui/colorlcd/view_logical_switches.h index 1f2750288..f7aab6ecf 100644 --- a/radio/src/gui/colorlcd/view_logical_switches.h +++ b/radio/src/gui/colorlcd/view_logical_switches.h @@ -21,6 +21,7 @@ #pragma once #include "opentx.h" +#include "tabsgroup.h" constexpr coord_t CSW_1ST_COLUMN = 50; constexpr coord_t CSW_2ND_COLUMN = 120; diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 74e1ecc2d..2fc3e2294 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -31,22 +31,10 @@ #include "view_main_decoration.h" #include "opentx.h" -Layout * customScreens[MAX_CUSTOM_SCREENS] = {}; - -int getMainViewsCount() -{ - for (int index=1; indexgetRect()) { #if defined(HARDWARE_TOUCH) && !defined(HARDWARE_KEYS) new FabButton(this, 50, 100, ICON_MODEL, @@ -73,7 +61,10 @@ ViewMain::ViewMain(): return 0; }, NO_FOCUS); #endif + createDecoration(); + setPageWidth(getParent()->width()); + focusWindow = this; } @@ -109,6 +100,26 @@ void ViewMain::adjustDecoration() decoration->adjustDecoration(); } +unsigned ViewMain::getMainViewsCount() const +{ + return views; +} + +void ViewMain::setMainViewsCount(unsigned views) +{ + if (views > MAX_CUSTOM_SCREENS) + views = MAX_CUSTOM_SCREENS; + + this->views = views; + setInnerWidth(getParent()->width() * views); + //setWidth(getParent()->width() * views); +} + +coord_t ViewMain::getMainViewLeftPos(unsigned view) const +{ + return getParent()->width() * view; +} + rect_t ViewMain::getMainZone() const { rect_t zone = decoration->getMainZone(); @@ -141,6 +152,33 @@ void ViewMain::onEvent(event_t event) killEvents(event); openMenu(); break; + + case EVT_KEY_BREAK(KEY_PGDN): + killEvents(event); + g_model.view++; + if (g_model.view >= getMainViewsCount()) + g_model.view = 0; + setScrollPositionX(g_model.view * pageWidth); + //customScreens[g_model.view]->setFocus(); + TRACE("### switched to view #%i", g_model.view); + break; + +//TODO: these need to go away! +// -> board code should map the keys as required +#if defined(KEYS_GPIO_REG_UP) + case EVT_KEY_BREAK(KEY_PGUP): +#else + case EVT_KEY_LONG(KEY_PGDN): +#endif + killEvents(event); + if (!g_model.view) + g_model.view = getMainViewsCount() - 1; + else + g_model.view--; + setScrollPositionX(g_model.view * pageWidth); + //customScreens[g_model.view]->setFocus(); + TRACE("### switched to view #%i", g_model.view); + break; } } #endif @@ -187,6 +225,9 @@ void ViewMain::openMenu() void ViewMain::paint(BitmapBuffer * dc) { + TRACE("### ViewMain::paint(offset_x=%d;offset_y=%d) ###", + dc->getOffsetX(), dc->getOffsetY()); + OpenTxTheme::instance()->drawBackground(dc); if (g_model.view >= getMainViewsCount()) { @@ -206,3 +247,28 @@ void ViewMain::createTopbar() topbar->load(); } +#if 0 +FormGroup * setMultiPageForm(uint8_t pages, bool focus = true) +{ + if (mainForm) + mainForm->deleteLater(); + + coord_t height = + bottomToolbarIcon >= 0 ? + MULTI_PAGE_FORM_HEIGHT + : MULTI_PAGE_FORM_WITHOUT_TOOLBAR_HEIGHT; + + mainForm = new FormWindow(this, + {0, MULTI_PAGE_FORM_TOP, LCD_W, height}, + FRSKY_PAGE_FORM_FLAGS); + + mainForm->setPageWidth(LCD_W); + mainForm->setInnerWidth(pages * LCD_W); + + if (focus) { + mainForm->setFocus(SET_FOCUS_DEFAULT); + } + + return mainForm; +} +#endif diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 1c6390181..4a535768a 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -63,12 +63,18 @@ class ViewMain: public FormWindow // Get the available space in the middle of the screen // (without decoration) rect_t getMainZone() const; + + unsigned getMainViewsCount() const; + void setMainViewsCount(unsigned views); + + coord_t getMainViewLeftPos(unsigned view) const; protected: static ViewMain * _instance; - TopBar* topbar; - ViewMainDecoration* decoration; + unsigned views = 0; + TopBar* topbar = nullptr; + ViewMainDecoration* decoration = nullptr; friend class SetupWidgetsPage; @@ -81,6 +87,8 @@ class ViewMain: public FormWindow void createDecoration(); void createTopbar(); + + void nextView(); }; #endif // _VIEW_MAIN_H_ diff --git a/radio/src/gui/colorlcd/view_main_decoration.cpp b/radio/src/gui/colorlcd/view_main_decoration.cpp index e16a0ed58..79f4614fc 100644 --- a/radio/src/gui/colorlcd/view_main_decoration.cpp +++ b/radio/src/gui/colorlcd/view_main_decoration.cpp @@ -266,8 +266,8 @@ void ViewMainDecoration::createTrims() VERTICAL_SLIDERS_HEIGHT }; - trims[TRIMS_LV] = new MainViewVerticalTrim(this, r, 1); - trims[TRIMS_RV] = new MainViewVerticalTrim(this, r, 2); + trims[TRIMS_LV] = new MainViewVerticalTrim(this, r, 2); + trims[TRIMS_RV] = new MainViewVerticalTrim(this, r, 1); } void ViewMainDecoration::createFlightMode() diff --git a/radio/src/gui/colorlcd/view_statistics.h b/radio/src/gui/colorlcd/view_statistics.h index c7568de1b..f9632e628 100644 --- a/radio/src/gui/colorlcd/view_statistics.h +++ b/radio/src/gui/colorlcd/view_statistics.h @@ -23,6 +23,8 @@ #include "opentx.h" #include "tabsgroup.h" #include "static.h" +#include "window.h" +#include "font.h" template class DebugInfoNumber : public Window @@ -34,7 +36,7 @@ class DebugInfoNumber : public Window prefix(prefix), suffix(suffix) { - coord_t prefixSize = getTextWidth(prefix, 0,HEADER_COLOR | FONT(XS)); + coord_t prefixSize = getTextWidth(prefix, 0, HEADER_COLOR | FONT(XS)); new StaticText(this, {0, 0, prefixSize, rect.h}, prefix, 0, HEADER_COLOR | FONT(XS)); new DynamicNumber(this, {prefixSize, 0, rect.w - prefixSize, rect.h}, [] { return menusStack.available(); diff --git a/radio/src/gui/colorlcd/widget.h b/radio/src/gui/colorlcd/widget.h index c1a41b6af..d7a198f59 100644 --- a/radio/src/gui/colorlcd/widget.h +++ b/radio/src/gui/colorlcd/widget.h @@ -71,10 +71,13 @@ class Widget : public FormField return &persistentData->options[index].value; } - inline void setOptionValue(unsigned int index, const ZoneOptionValue& value) - { - persistentData->options[index].value = value; - } + // + // TODO: for some reason, this one crashes on the radio... + // + // inline void setOptionValue(unsigned int index, const ZoneOptionValue& value) + // { + // persistentData->options[index].value = value; + // } inline PersistentData * getPersistentData() { diff --git a/radio/src/gui/colorlcd/widget_settings.cpp b/radio/src/gui/colorlcd/widget_settings.cpp index 510769b3d..1f2f7ee46 100644 --- a/radio/src/gui/colorlcd/widget_settings.cpp +++ b/radio/src/gui/colorlcd/widget_settings.cpp @@ -19,7 +19,9 @@ */ #include "opentx.h" + #include "widget_settings.h" +#include "libopenui.h" static const rect_t widgetSettingsDialogRect = { LCD_W / 10, // x @@ -51,30 +53,30 @@ WidgetSettings::WidgetSettings(Window * parent, Widget * widget) : case ZoneOption::Integer: new NumberEdit(form, grid.getFieldSlot(), option.min.signedValue, option.max.signedValue, [=]() -> int { - return widget->getOptionValue(optIdx)->signedValue; + return widget->getOptionValue(optIdx)->signedValue; }, [=](int32_t newValue) { - widget->setOptionValue(optIdx, OPTION_VALUE_SIGNED(newValue)); + widget->getOptionValue(optIdx)->signedValue = newValue; }); break; case ZoneOption::Source: new SourceChoice(form, grid.getFieldSlot(), 0, MIXSRC_LAST_TELEM, [=]() -> int16_t { - return (int16_t) widget->getOptionValue(optIdx)->unsignedValue; + return (int16_t) widget->getOptionValue(optIdx)->unsignedValue; }, [=](int16_t newValue) { - widget->setOptionValue(optIdx, OPTION_VALUE_UNSIGNED((uint32_t) newValue)); + widget->getOptionValue(optIdx)->unsignedValue = (uint32_t)newValue; }); break; case ZoneOption::Bool: new CheckBox(form, grid.getFieldSlot(), [=]() -> uint8_t { - return (uint8_t) widget->getOptionValue(optIdx)->boolValue; + return (uint8_t) widget->getOptionValue(optIdx)->boolValue; }, [=](int8_t newValue) { - widget->setOptionValue(optIdx, OPTION_VALUE_BOOL((uint32_t) newValue)); + widget->getOptionValue(optIdx)->boolValue = newValue; }); break; @@ -91,10 +93,10 @@ WidgetSettings::WidgetSettings(Window * parent, Widget * widget) : { auto tmChoice = new Choice(form, grid.getFieldSlot(), 0, TIMERS - 1, [=]() -> int { // getValue - return (int) widget->getOptionValue(optIdx)->unsignedValue; + return (int) widget->getOptionValue(optIdx)->unsignedValue; }, [=](int newValue) { // setValue - widget->setOptionValue(optIdx, OPTION_VALUE_UNSIGNED((uint32_t) newValue)); + widget->getOptionValue(optIdx)->unsignedValue = (uint32_t) newValue; }); tmChoice->setTextHandler([](int value) { @@ -108,19 +110,20 @@ WidgetSettings::WidgetSettings(Window * parent, Widget * widget) : option.min.unsignedValue, // min option.max.unsignedValue, // max [=]() -> int16_t { // getValue - return (uint8_t) widget->getOptionValue(optIdx)->unsignedValue; + return (uint8_t) widget->getOptionValue(optIdx)->unsignedValue; }, [=](int16_t newValue) { // setValue - widget->setOptionValue(optIdx, OPTION_VALUE_UNSIGNED((uint32_t) newValue)); + widget->getOptionValue(optIdx)->unsignedValue = (uint32_t) newValue; }); break; case ZoneOption::Color: - new ColorEdit(form, grid.getFieldSlot(), [=]() -> int { // getValue - return (int) widget->getOptionValue(optIdx)->unsignedValue; + new ColorEdit(form, grid.getFieldSlot(), + [=]() -> int { // getValue + return (int) widget->getOptionValue(optIdx)->unsignedValue; }, [=](int newValue) { // setValue - widget->setOptionValue(optIdx, OPTION_VALUE_UNSIGNED((uint32_t) newValue)); + widget->getOptionValue(optIdx)->unsignedValue = (uint32_t) newValue; }); break; } diff --git a/radio/src/gui/colorlcd/widgets/outputs.cpp b/radio/src/gui/colorlcd/widgets/outputs.cpp index 38c6d240a..a6693902d 100644 --- a/radio/src/gui/colorlcd/widgets/outputs.cpp +++ b/radio/src/gui/colorlcd/widgets/outputs.cpp @@ -25,6 +25,9 @@ #define VIEW_CHANNELS_LIMIT_PCT (g_model.extendedLimits ? LIMIT_EXT_PERCENT : 100) +constexpr uint32_t OUTPUTS_REFRESH = 1000 / 5; // 5 Hz + + class OutputsWidget: public Widget { public: @@ -100,11 +103,23 @@ class OutputsWidget: public Widget void checkEvents() override { Widget::checkEvents(); + + // Last time we refreshed the window + uint32_t now = RTOS_GET_MS(); + if (now - lastRefresh >= OUTPUTS_REFRESH) { + lastRefresh = now; + invalidate(); + } + invalidate(); } static const ZoneOption options[]; + + protected: + // Last time we refreshed the window + uint32_t lastRefresh = 0; }; const ZoneOption OutputsWidget::options[] = { diff --git a/radio/src/gui/colorlcd/zone.h b/radio/src/gui/colorlcd/zone.h index 26836b063..bd941433e 100644 --- a/radio/src/gui/colorlcd/zone.h +++ b/radio/src/gui/colorlcd/zone.h @@ -13,10 +13,10 @@ #define OPTION_VALUE_BOOL(x) { bool(x) } #define OPTION_VALUE_STRING(...) { *(ZoneOptionValue *)(const char *) #__VA_ARGS__ } #else - #define OPTION_VALUE_UNSIGNED(x) { .unsignedValue = (x) } - #define OPTION_VALUE_SIGNED(x) { .signedValue = (x) } - #define OPTION_VALUE_BOOL(x) { .boolValue = (x) } - #define OPTION_VALUE_STRING(...) { .stringValue = { __VA_ARGS__ } } + #define OPTION_VALUE_UNSIGNED(x) ZoneOptionValue{ .unsignedValue = (x) } + #define OPTION_VALUE_SIGNED(x) ZoneOptionValue{ .signedValue = (x) } + #define OPTION_VALUE_BOOL(x) ZoneOptionValue{ .boolValue = (x) } + #define OPTION_VALUE_STRING(...) ZoneOptionValue{ .stringValue = { __VA_ARGS__ } } #endif union ZoneOptionValue diff --git a/radio/src/io/bootloader_flash.cpp b/radio/src/io/bootloader_flash.cpp index 33a0ab28d..583262627 100644 --- a/radio/src/io/bootloader_flash.cpp +++ b/radio/src/io/bootloader_flash.cpp @@ -20,6 +20,7 @@ #include "opentx.h" #include "bootloader_flash.h" +#include "libopenui.h" bool isBootloader(const char * filename) { diff --git a/radio/src/io/frsky_firmware_update.cpp b/radio/src/io/frsky_firmware_update.cpp index 5d91c0a1e..2898380ef 100644 --- a/radio/src/io/frsky_firmware_update.cpp +++ b/radio/src/io/frsky_firmware_update.cpp @@ -20,7 +20,8 @@ #include "opentx.h" #include "frsky_firmware_update.h" -#include "libopenui/src/libopenui_file.h" + +#include "libopenui.h" #define PRIM_REQ_POWERUP 0 #define PRIM_REQ_VERSION 1 diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp index bb87a4142..7bf86a63e 100644 --- a/radio/src/io/multi_firmware_update.cpp +++ b/radio/src/io/multi_firmware_update.cpp @@ -24,6 +24,7 @@ #include "multi_firmware_update.h" #include "stk500.h" #include "debug.h" +#include "libopenui.h" #define UPDATE_MULTI_EXT_BIN ".bin" diff --git a/radio/src/logs.cpp b/radio/src/logs.cpp index 13f6f4a3a..bd8767d52 100644 --- a/radio/src/logs.cpp +++ b/radio/src/logs.cpp @@ -21,6 +21,10 @@ #include "opentx.h" #include "ff.h" +#if defined(LIBOPENUI) + #include "libopenui.h" +#endif + FIL g_oLogFile __DMA; const char * g_logError = nullptr; uint8_t logDelay; diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp index 213421411..5ccde6e08 100644 --- a/radio/src/lua/api_general.cpp +++ b/radio/src/lua/api_general.cpp @@ -26,6 +26,10 @@ #include "telemetry/frsky.h" #include "telemetry/multi.h" +#if defined(LIBOPENUI) + #include "libopenui.h" +#endif + #if defined(PCBX12S) #include "lua/lua_exports_x12s.inc" // this line must be after lua headers #elif defined(RADIO_FAMILY_T16) diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index 0cc1d48cc..a3ad5dbc9 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -27,7 +27,10 @@ #include "bin_allocator.h" #include "lua_api.h" #include "sdcard.h" -#include "libopenui/src/libopenui_file.h" + +#if defined(LIBOPENUI) + #include "libopenui.h" +#endif extern "C" { #include diff --git a/radio/src/main.cpp b/radio/src/main.cpp index a43ddd254..c7b0fd8da 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -21,7 +21,7 @@ #include "opentx.h" #if defined(LIBOPENUI) - #include "mainwindow.h" + #include "libopenui.h" #endif uint8_t currentSpeakerVolume = 255; diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 4ad05a801..81f842582 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -22,9 +22,10 @@ #include #if defined(LIBOPENUI) -// #include "shutdown_animation.h" -#include "radio_calibration.h" -#include "view_main.h" + #include "libopenui.h" + // #include "shutdown_animation.h" + #include "radio_calibration.h" + #include "view_main.h" #endif #if defined(PCBSKY9X) diff --git a/radio/src/opentx.h b/radio/src/opentx.h index dbbd9eec8..f60c4ddeb 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -27,10 +27,6 @@ #include "opentx_helpers.h" #include "touch.h" -#if defined(LIBOPENUI) -#include "libopenui.h" -#endif - #if defined(SIMU) #include "targets/simu/simpgmspace.h" #endif diff --git a/radio/src/sdcard.cpp b/radio/src/sdcard.cpp index 1719eff2f..366010d5c 100644 --- a/radio/src/sdcard.cpp +++ b/radio/src/sdcard.cpp @@ -21,7 +21,10 @@ #include #include "opentx.h" #include "diskio.h" -#include "libopenui/src/libopenui_file.h" + +#if defined(LIBOPENUI) + #include "libopenui.h" +#endif bool sdCardFormat() { diff --git a/radio/src/simu.cpp b/radio/src/simu.cpp index ee9c8ae45..adbe4788a 100644 --- a/radio/src/simu.cpp +++ b/radio/src/simu.cpp @@ -383,7 +383,7 @@ void OpenTxSim::updateKeysAndSwitches(bool start) static FXuint trimKeys[] = { KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12 }; #endif - for (unsigned i=0; igetKeyState(trimKeys[i])); } diff --git a/radio/src/targets/horus/libopenui_config.h b/radio/src/targets/horus/libopenui_config.h index b354635a5..77168ca71 100644 --- a/radio/src/targets/horus/libopenui_config.h +++ b/radio/src/targets/horus/libopenui_config.h @@ -29,7 +29,7 @@ typedef uint16_t pixel_t; constexpr bool WRAP_FORM_FIELDS_WITHIN_PAGE = true; -constexpr uint32_t SLIDE_SPEED_REDUCTION = 5; +constexpr short SLIDE_SPEED_REDUCTION = 5; constexpr uint32_t MENU_HEADER_BUTTON_WIDTH = 33; constexpr uint32_t MENU_HEADER_BUTTONS_LEFT = 47; diff --git a/radio/src/targets/simu/CMakeLists.txt b/radio/src/targets/simu/CMakeLists.txt index 523d38c81..beb25cbc6 100644 --- a/radio/src/targets/simu/CMakeLists.txt +++ b/radio/src/targets/simu/CMakeLists.txt @@ -83,8 +83,8 @@ else() # struct packing breaks on MinGW w/out -mno-ms-bitfields: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 & http://stackoverflow.com/questions/24015852/struct-packing-and-alignment-with-mingw set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mno-ms-bitfields") endif() - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -fsanitize=address") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -fsanitize=address") endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS}") @@ -98,6 +98,7 @@ if(FOX_FOUND) endif() add_executable(simu WIN32 ${SIMU_SRC} ${RADIO_SRC_DIR}/simu.cpp) add_dependencies(simu ${RADIO_DEPENDENCIES}) + target_include_directories(simu PUBLIC ${FOX_INCLUDE_DIR} ) target_link_libraries(simu ${FOX_LIBRARY} pthread ${SDL_LIBRARY}) target_compile_definitions(simu PUBLIC -DSIMU) diff --git a/radio/src/telemetry/frsky_pxx2.cpp b/radio/src/telemetry/frsky_pxx2.cpp index 959d0ee43..51943e6f0 100644 --- a/radio/src/telemetry/frsky_pxx2.cpp +++ b/radio/src/telemetry/frsky_pxx2.cpp @@ -20,6 +20,10 @@ #include "opentx.h" +#if defined(LIBOPENUI) + #include "libopenui.h" +#endif + void processGetHardwareInfoFrame(uint8_t module, const uint8_t * frame) { if (moduleState[module].mode != MODULE_MODE_GET_HARDWARE_INFO) { diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index c32cd491c..9fdc6c749 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -23,6 +23,10 @@ #include "pulses/afhds3.h" #include "mixer_scheduler.h" +#if defined(LIBOPENUI) + #include "libopenui.h" +#endif + uint8_t telemetryStreaming = 0; uint8_t telemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1) uint8_t telemetryRxBufferCount = 0; diff --git a/radio/src/telemetry/telemetry_sensors.cpp b/radio/src/telemetry/telemetry_sensors.cpp index b439bd678..92f51e8c4 100644 --- a/radio/src/telemetry/telemetry_sensors.cpp +++ b/radio/src/telemetry/telemetry_sensors.cpp @@ -22,6 +22,10 @@ #define _USE_MATH_DEFINES #include +#if defined(LIBOPENUI) + #include "libopenui.h" +#endif + TelemetryItem telemetryItems[MAX_TELEMETRY_SENSORS]; uint8_t allowNewSensors; From f76ef9312b70c73a4e232600f0aec7912a5b8dbd Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 15 Apr 2021 20:33:47 +0200 Subject: [PATCH 13/54] Fixed includes for BW radios --- radio/src/io/bootloader_flash.cpp | 7 ++++++- radio/src/io/frsky_firmware_update.cpp | 2 +- radio/src/io/multi_firmware_update.cpp | 7 ++++++- radio/src/lua/interface.cpp | 2 ++ radio/src/sdcard.cpp | 2 ++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/radio/src/io/bootloader_flash.cpp b/radio/src/io/bootloader_flash.cpp index 583262627..18ae9b272 100644 --- a/radio/src/io/bootloader_flash.cpp +++ b/radio/src/io/bootloader_flash.cpp @@ -20,7 +20,12 @@ #include "opentx.h" #include "bootloader_flash.h" -#include "libopenui.h" + +#if defined(LIBOPENUI) + #include "libopenui.h" +#else + #include "libopenui/src/libopenui_file.h" +#endif bool isBootloader(const char * filename) { diff --git a/radio/src/io/frsky_firmware_update.cpp b/radio/src/io/frsky_firmware_update.cpp index 2898380ef..09711f6f9 100644 --- a/radio/src/io/frsky_firmware_update.cpp +++ b/radio/src/io/frsky_firmware_update.cpp @@ -21,7 +21,7 @@ #include "opentx.h" #include "frsky_firmware_update.h" -#include "libopenui.h" +#include "libopenui/src/libopenui_file.h" #define PRIM_REQ_POWERUP 0 #define PRIM_REQ_VERSION 1 diff --git a/radio/src/io/multi_firmware_update.cpp b/radio/src/io/multi_firmware_update.cpp index 7bf86a63e..0d8fda028 100644 --- a/radio/src/io/multi_firmware_update.cpp +++ b/radio/src/io/multi_firmware_update.cpp @@ -24,7 +24,12 @@ #include "multi_firmware_update.h" #include "stk500.h" #include "debug.h" -#include "libopenui.h" + +#if defined(LIBOPENUI) + #include "libopenui.h" +#else + #include "libopenui/src/libopenui_file.h" +#endif #define UPDATE_MULTI_EXT_BIN ".bin" diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp index a3ad5dbc9..1b06b0168 100644 --- a/radio/src/lua/interface.cpp +++ b/radio/src/lua/interface.cpp @@ -30,6 +30,8 @@ #if defined(LIBOPENUI) #include "libopenui.h" +#else + #include "libopenui/src/libopenui_file.h" #endif extern "C" { diff --git a/radio/src/sdcard.cpp b/radio/src/sdcard.cpp index 366010d5c..be6370a08 100644 --- a/radio/src/sdcard.cpp +++ b/radio/src/sdcard.cpp @@ -24,6 +24,8 @@ #if defined(LIBOPENUI) #include "libopenui.h" +#else + #include "libopenui/src/libopenui_file.h" #endif bool sdCardFormat() From 1bce22891082667847363663567bb33aa1f1c1f2 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 15 Apr 2021 20:39:49 +0200 Subject: [PATCH 14/54] More header fixes for COLORLCD --- radio/src/bluetooth.cpp | 6 ++++++ radio/src/io/frsky_firmware_update.cpp | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/radio/src/bluetooth.cpp b/radio/src/bluetooth.cpp index 8e50ca6fa..d5669af53 100644 --- a/radio/src/bluetooth.cpp +++ b/radio/src/bluetooth.cpp @@ -21,6 +21,12 @@ #include "opentx.h" #include "io/frsky_firmware_update.h" +#if defined(LIBOPENUI) + #include "libopenui.h" +#else + #include "libopenui/src/libopenui_file.h" +#endif + #if defined(LOG_BLUETOOTH) extern FIL g_bluetoothFile; #endif diff --git a/radio/src/io/frsky_firmware_update.cpp b/radio/src/io/frsky_firmware_update.cpp index 09711f6f9..d46316c98 100644 --- a/radio/src/io/frsky_firmware_update.cpp +++ b/radio/src/io/frsky_firmware_update.cpp @@ -21,7 +21,11 @@ #include "opentx.h" #include "frsky_firmware_update.h" -#include "libopenui/src/libopenui_file.h" +#if defined(LIBOPENUI) + #include "libopenui.h" +#else + #include "libopenui/src/libopenui_file.h" +#endif #define PRIM_REQ_POWERUP 0 #define PRIM_REQ_VERSION 1 From 19cab41034fdbd2aa1f729c1ec6d51569b877c47 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 06:56:35 +0200 Subject: [PATCH 15/54] Re-add periodic refresh on topbar and layout --- radio/src/gui/colorlcd/layout.cpp | 10 +++++----- radio/src/gui/colorlcd/topbar.cpp | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index e15e41d92..b291b16ab 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -198,11 +198,11 @@ void Layout::checkEvents() LayoutBase::checkEvents(); decorate(); - // uint32_t now = RTOS_GET_MS(); - // if (now - lastRefresh >= LAYOUT_REFRESH) { - // lastRefresh = now; - // invalidate(); - // } + uint32_t now = RTOS_GET_MS(); + if (now - lastRefresh >= LAYOUT_REFRESH) { + lastRefresh = now; + invalidate(); + } } void Layout::decorate() diff --git a/radio/src/gui/colorlcd/topbar.cpp b/radio/src/gui/colorlcd/topbar.cpp index fe3694962..daa11a888 100644 --- a/radio/src/gui/colorlcd/topbar.cpp +++ b/radio/src/gui/colorlcd/topbar.cpp @@ -165,9 +165,9 @@ void TopBar::paint(BitmapBuffer * dc) void TopBar::checkEvents() { - // uint32_t now = RTOS_GET_MS(); - // if (now - lastRefresh >= TOPBAR_REFRESH) { - // lastRefresh = now; - // invalidate(); - // } + uint32_t now = RTOS_GET_MS(); + if (now - lastRefresh >= TOPBAR_REFRESH) { + lastRefresh = now; + invalidate(); + } } From d0a14cf2a23f2a3c4cf1f59be1acaa41ebfdf94d Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 09:04:11 +0200 Subject: [PATCH 16/54] Moved ViewMainDecoration back to Layout This allows each custom screen to have its own trims/sliders/etc being displayed properly while scrolling from view to view. --- radio/src/gui/colorlcd/layout.cpp | 53 +++++++++++++--- radio/src/gui/colorlcd/layout.h | 21 ++++--- radio/src/gui/colorlcd/screen_setup.cpp | 24 +++---- radio/src/gui/colorlcd/view_main.cpp | 84 +++++++++++-------------- radio/src/gui/colorlcd/view_main.h | 27 +++----- 5 files changed, 114 insertions(+), 95 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index b291b16ab..d3eb224c1 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -22,6 +22,7 @@ #include "view_main.h" #include "layouts/trims.h" #include "layouts/sliders.h" +#include "view_main_decoration.h" constexpr uint32_t LAYOUT_REFRESH = 1000 / 2; // 2 Hz @@ -172,6 +173,14 @@ void disposeCustomScreen(unsigned idx) memset(dst, 0, len); } +Layout::Layout(const LayoutFactory * factory, PersistentData * persistentData): + LayoutBase({0, 0, LCD_W, LCD_H}, persistentData), + factory(factory), + decoration(new ViewMainDecoration(this, getRect())) +{ + decorate(); +} + void Layout::create() { memset(persistentData, 0, sizeof(PersistentData)); @@ -205,6 +214,26 @@ void Layout::checkEvents() } } +void Layout::setTrimsVisible(bool visible) +{ + decoration->setTrimsVisible(visible); +} + +void Layout::setSlidersVisible(bool visible) +{ + decoration->setSlidersVisible(visible); +} + +void Layout::setFlightModeVisible(bool visible) +{ + decoration->setFlightModeVisible(visible); +} + +void Layout::adjustDecoration() +{ + decoration->adjustDecoration(); +} + void Layout::decorate() { // Check if deco setting are still up-to-date @@ -222,23 +251,29 @@ void Layout::decorate() // Save settings decorationSettings = checkSettings; - auto viewMain = ViewMain::instance(); - // Set visible decoration - viewMain->setTopbarVisible(hasTopbar()); - viewMain->setSlidersVisible(hasSliders()); - viewMain->setTrimsVisible(hasTrims()); - viewMain->setFlightModeVisible(hasFlightMode()); + ViewMain::instance()->setTopbarVisible(hasTopbar()); + setSlidersVisible(hasSliders()); + setTrimsVisible(hasTrims()); + setFlightModeVisible(hasFlightMode()); // Re-compute positions - viewMain->adjustDecoration(); + adjustDecoration(); // and update relevant windows updateZones(); - invalidate(); + + // probably not needed + //invalidate(); +} + +void Layout::createDecoration() +{ } rect_t Layout::getMainZone() const { - return ViewMain::instance()->getMainZone(); + rect_t zone = decoration->getMainZone(); + return ViewMain::instance()->getMainZone(zone); } + diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index d96aeef0f..6ee989802 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -32,6 +32,7 @@ constexpr coord_t TRIM_SQUARE_SIZE = 17; constexpr coord_t MAIN_ZONE_BORDER = 10; class LayoutFactory; +class ViewMainDecoration; #define LAYOUT_COMMON_OPTIONS \ { STR_TOP_BAR, ZoneOption::Bool }, \ @@ -62,12 +63,7 @@ class Layout: public LayoutBase OPTION_LAST_DEFAULT=OPTION_MIRRORED }; - Layout(const LayoutFactory * factory, PersistentData * persistentData): - LayoutBase({0, 0, LCD_W, LCD_H}, persistentData), - factory(factory) - { - decorate(); - } + Layout(const LayoutFactory * factory, PersistentData * persistentData); #if defined(DEBUG_WINDOWS) std::string getName() const override @@ -107,8 +103,17 @@ class Layout: public LayoutBase return getOptionValue(OPTION_MIRRORED)->boolValue; } + // Set decoration visibility + void setTrimsVisible(bool visible); + void setSlidersVisible(bool visible); + void setFlightModeVisible(bool visible); + + // Re-calculate positions + void adjustDecoration(); + protected: - const LayoutFactory * factory; + const LayoutFactory * factory = nullptr; + ViewMainDecoration* decoration = nullptr; // Decoration settings bitmask to detect updates uint8_t decorationSettings = 0; @@ -119,6 +124,8 @@ class Layout: public LayoutBase // Updates settings for trims, sliders, pots, etc... void decorate(); + void createDecoration(); + // Get the available space for widgets rect_t getMainZone() const; }; diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index e33864e18..ba81f0efa 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -137,17 +137,6 @@ class SetupWidgetsPageSlot: public Button } return 0; - // } - // else { - // Menu * menu = new Menu(this); - // for (auto factory: getRegisteredWidgets()) { - // menu->addLine(factory->getName(), [=]() { - // if (widget) widget->deleteLater(); - // widget = screen->createWidget(slotIndex, factory); - // }); - // } - // } - // return 0; }); } @@ -163,7 +152,7 @@ class SetupWidgetsPage: public FormWindow { public: SetupWidgetsPage(ScreenMenu* menu, uint8_t customScreenIdx): - FormWindow(ViewMain::instance(), {0, 0, LCD_W, LCD_H}, /*OPAQUE |*/ FORM_FORWARD_FOCUS), + FormWindow(ViewMain::instance(), {0, 0, 0, 0}, /*OPAQUE |*/ FORM_FORWARD_FOCUS), menu(menu), customScreenIdx(customScreenIdx) { @@ -173,11 +162,13 @@ class SetupWidgetsPage: public FormWindow auto screen = customScreens[customScreenIdx]; if (screen) { screen->attach(this); - screen->setLeft(0); setRect(screen->getRect()); - } - ViewMain::instance()->bringToTop(); + auto viewMain = ViewMain::instance(); + savedView = viewMain->getCurrentMainView(); + viewMain->setCurrentMainView(customScreenIdx); + viewMain->bringToTop(); + } for (unsigned i = 0; i < screen->getZonesCount(); i++) { auto rect = screen->getZone(i); @@ -203,8 +194,8 @@ class SetupWidgetsPage: public FormWindow auto screen = customScreens[customScreenIdx]; if (screen) { auto viewMain = ViewMain::instance(); - screen->setLeft(viewMain->getMainViewLeftPos(customScreenIdx)); screen->attach(viewMain); + viewMain->setCurrentMainView(customScreenIdx); } FormWindow::deleteLater(detach, trash); @@ -228,6 +219,7 @@ class SetupWidgetsPage: public FormWindow protected: ScreenMenu* menu; uint8_t customScreenIdx; + unsigned savedView = 0; // void paint(BitmapBuffer * dc) override // { diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 2fc3e2294..62f1e81e5 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -62,7 +62,7 @@ ViewMain::ViewMain(): }, NO_FOCUS); #endif - createDecoration(); + createTopbar(); setPageWidth(getParent()->width()); focusWindow = this; @@ -77,29 +77,6 @@ void ViewMain::setTopbarVisible(bool visible) topbar->setVisible(visible); } -void ViewMain::setTrimsVisible(bool visible) -{ - decoration->setTrimsVisible(visible); -} - -void ViewMain::setSlidersVisible(bool visible) -{ - decoration->setSlidersVisible(visible); -} - -void ViewMain::setFlightModeVisible(bool visible) -{ - decoration->setFlightModeVisible(visible); -} - -void ViewMain::adjustDecoration() -{ - // Topbar does not need any computation - // (height() has been set in setTopbarVisible()) - - decoration->adjustDecoration(); -} - unsigned ViewMain::getMainViewsCount() const { return views; @@ -112,7 +89,6 @@ void ViewMain::setMainViewsCount(unsigned views) this->views = views; setInnerWidth(getParent()->width() * views); - //setWidth(getParent()->width() * views); } coord_t ViewMain::getMainViewLeftPos(unsigned view) const @@ -120,15 +96,48 @@ coord_t ViewMain::getMainViewLeftPos(unsigned view) const return getParent()->width() * view; } -rect_t ViewMain::getMainZone() const +rect_t ViewMain::getMainZone(rect_t zone) const { - rect_t zone = decoration->getMainZone(); zone.y += topbar->bottom(); zone.h -= topbar->height(); return zone; } +unsigned ViewMain::getCurrentMainView() const +{ + return g_model.view; +} + +void ViewMain::setCurrentMainView(unsigned view) +{ + if (view < getMainViewsCount()) { + g_model.view = view; + setScrollPositionX(g_model.view * pageWidth); + TRACE("### switched to view #%i", g_model.view); + } +} + +void ViewMain::nextMainView() +{ + auto view = getCurrentMainView(); + if (++view >= getMainViewsCount()) + view = 0; + + setCurrentMainView(view); +} + +void ViewMain::previousMainView() +{ + auto view = getCurrentMainView(); + if (view > 0) + view--; + else + view = getMainViewsCount() - 1; + + setCurrentMainView(view); +} + #if defined(HARDWARE_KEYS) void ViewMain::onEvent(event_t event) { @@ -155,12 +164,7 @@ void ViewMain::onEvent(event_t event) case EVT_KEY_BREAK(KEY_PGDN): killEvents(event); - g_model.view++; - if (g_model.view >= getMainViewsCount()) - g_model.view = 0; - setScrollPositionX(g_model.view * pageWidth); - //customScreens[g_model.view]->setFocus(); - TRACE("### switched to view #%i", g_model.view); + nextMainView(); break; //TODO: these need to go away! @@ -171,13 +175,7 @@ void ViewMain::onEvent(event_t event) case EVT_KEY_LONG(KEY_PGDN): #endif killEvents(event); - if (!g_model.view) - g_model.view = getMainViewsCount() - 1; - else - g_model.view--; - setScrollPositionX(g_model.view * pageWidth); - //customScreens[g_model.view]->setFocus(); - TRACE("### switched to view #%i", g_model.view); + previousMainView(); break; } } @@ -235,12 +233,6 @@ void ViewMain::paint(BitmapBuffer * dc) } } -void ViewMain::createDecoration() -{ - createTopbar(); - decoration = new ViewMainDecoration(this, getRect()); -} - void ViewMain::createTopbar() { topbar = new TopBar(this); diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 4a535768a..9eea9367d 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -25,7 +25,6 @@ #include class TopBar; -class ViewMainDecoration; class SetupWidgetsPage; class ViewMain: public FormWindow @@ -51,18 +50,12 @@ class ViewMain: public FormWindow } #endif - // Set topbar & decoration visibility + // Set topbar visibility void setTopbarVisible(bool visible); - void setTrimsVisible(bool visible); - void setSlidersVisible(bool visible); - void setFlightModeVisible(bool visible); - - // Re-calculate positions - void adjustDecoration(); // Get the available space in the middle of the screen - // (without decoration) - rect_t getMainZone() const; + // (without topbar) + rect_t getMainZone(rect_t zone) const; unsigned getMainViewsCount() const; void setMainViewsCount(unsigned views); @@ -72,11 +65,15 @@ class ViewMain: public FormWindow protected: static ViewMain * _instance; - unsigned views = 0; - TopBar* topbar = nullptr; - ViewMainDecoration* decoration = nullptr; + unsigned views = 0; + TopBar* topbar = nullptr; friend class SetupWidgetsPage; + + unsigned getCurrentMainView() const; + void setCurrentMainView(unsigned view); + void nextMainView(); + void previousMainView(); #if defined(HARDWARE_KEYS) void onEvent(event_t event) override; @@ -84,11 +81,7 @@ class ViewMain: public FormWindow void paint(BitmapBuffer * dc) override; void openMenu(); - - void createDecoration(); void createTopbar(); - - void nextView(); }; #endif // _VIEW_MAIN_H_ From d3e340d230b354d48655c63f02044d764bd40abb Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 09:05:47 +0200 Subject: [PATCH 17/54] Work around issue 13 in libopenui --- radio/src/gui/colorlcd/view_main.cpp | 2 +- radio/src/gui/colorlcd/view_main.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 62f1e81e5..e76ba8546 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -34,7 +34,7 @@ ViewMain * ViewMain::_instance = nullptr; ViewMain::ViewMain(): - FormWindow(MainWindow::instance(), MainWindow::instance()->getRect()) + Window(MainWindow::instance(), MainWindow::instance()->getRect()) { #if defined(HARDWARE_TOUCH) && !defined(HARDWARE_KEYS) new FabButton(this, 50, 100, ICON_MODEL, diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 9eea9367d..9518b06c6 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -27,7 +27,7 @@ class TopBar; class SetupWidgetsPage; -class ViewMain: public FormWindow +class ViewMain: public Window { // singleton explicit ViewMain(); From f98d4c65d124a9103bb42f656343f030f89b722e Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 13:32:13 +0200 Subject: [PATCH 18/54] Avoid libopenui issue 13 --- radio/src/gui/colorlcd/widget.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/radio/src/gui/colorlcd/widget.h b/radio/src/gui/colorlcd/widget.h index d7a198f59..c7e3c25a2 100644 --- a/radio/src/gui/colorlcd/widget.h +++ b/radio/src/gui/colorlcd/widget.h @@ -34,7 +34,7 @@ #endif class WidgetFactory; -class Widget : public FormField +class Widget : public Window { public: struct PersistentData { @@ -42,7 +42,7 @@ class Widget : public FormField }; Widget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, PersistentData * persistentData): - FormField(parent, rect), + Window(parent, rect), factory(factory), persistentData(persistentData) { @@ -84,11 +84,6 @@ class Widget : public FormField return persistentData; } - void paint(BitmapBuffer * dc) override - { - FormField::paint(dc); - } - virtual void background() { } From ba3c879f75ddcf59e3e7753ac5154375ebda9fac Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 13:32:49 +0200 Subject: [PATCH 19/54] Let the TopBar follow the scrolling --- radio/src/gui/colorlcd/view_main.cpp | 12 ++++++++++++ radio/src/gui/colorlcd/view_main.h | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index e76ba8546..58f3b1522 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -138,6 +138,18 @@ void ViewMain::previousMainView() setCurrentMainView(view); } +void ViewMain::setScrollPositionX(coord_t value) +{ + Window::setScrollPositionX(value); + topbar->setLeft(getScrollPositionX()); +} + +void ViewMain::setScrollPositionY(coord_t value) +{ + Window::setScrollPositionY(value); + topbar->setTop(getScrollPositionY()); +} + #if defined(HARDWARE_KEYS) void ViewMain::onEvent(event_t event) { diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 9518b06c6..2de2dca53 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -74,7 +74,10 @@ class ViewMain: public Window void setCurrentMainView(unsigned view); void nextMainView(); void previousMainView(); - + + void setScrollPositionX(coord_t value) override; + void setScrollPositionY(coord_t value) override; + #if defined(HARDWARE_KEYS) void onEvent(event_t event) override; #endif From 71dc7f1d04e754b55697b5ec1ea14d36d3e4ff17 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 14:05:21 +0200 Subject: [PATCH 20/54] Fixes issue with widgets not visible on widget config screen --- radio/src/gui/colorlcd/screen_setup.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index ba81f0efa..7f17da553 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -152,7 +152,7 @@ class SetupWidgetsPage: public FormWindow { public: SetupWidgetsPage(ScreenMenu* menu, uint8_t customScreenIdx): - FormWindow(ViewMain::instance(), {0, 0, 0, 0}, /*OPAQUE |*/ FORM_FORWARD_FOCUS), + FormWindow(ViewMain::instance(), {0, 0, 0, 0}, FORM_FORWARD_FOCUS), menu(menu), customScreenIdx(customScreenIdx) { @@ -163,6 +163,7 @@ class SetupWidgetsPage: public FormWindow if (screen) { screen->attach(this); setRect(screen->getRect()); + screen->setLeft(0); auto viewMain = ViewMain::instance(); savedView = viewMain->getCurrentMainView(); @@ -195,6 +196,7 @@ class SetupWidgetsPage: public FormWindow if (screen) { auto viewMain = ViewMain::instance(); screen->attach(viewMain); + screen->setRect(getRect()); viewMain->setCurrentMainView(customScreenIdx); } FormWindow::deleteLater(detach, trash); From 0e230421bfe6198bd435b666a3c84f95800c2462 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 14:09:37 +0200 Subject: [PATCH 21/54] Fixed returning to the same screen after configuring another one --- radio/src/gui/colorlcd/screen_setup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 7f17da553..0f3a0f4ed 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -197,7 +197,7 @@ class SetupWidgetsPage: public FormWindow auto viewMain = ViewMain::instance(); screen->attach(viewMain); screen->setRect(getRect()); - viewMain->setCurrentMainView(customScreenIdx); + viewMain->setCurrentMainView(savedView); } FormWindow::deleteLater(detach, trash); From fe8455e09b1eed62f46b26de8083705f515e56ad Mon Sep 17 00:00:00 2001 From: 3djc Date: Fri, 16 Apr 2021 16:19:18 +0200 Subject: [PATCH 22/54] Fix drawSourceCustomValue() --- radio/src/gui/colorlcd/draw_functions.cpp | 2 +- radio/src/gui/colorlcd/view_main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/draw_functions.cpp b/radio/src/gui/colorlcd/draw_functions.cpp index b5aa5438f..f79c9b0dd 100644 --- a/radio/src/gui/colorlcd/draw_functions.cpp +++ b/radio/src/gui/colorlcd/draw_functions.cpp @@ -374,7 +374,7 @@ void drawSourceCustomValue(BitmapBuffer * dc, coord_t x, coord_t y, source_t sou { if (source >= MIXSRC_FIRST_TELEM) { source = (source-MIXSRC_FIRST_TELEM) / 3; - drawSensorCustomValue(dc, y, source, value, flags); + drawSensorCustomValue(dc, x, y, source, value, flags); } else if (source >= MIXSRC_FIRST_TIMER || source == MIXSRC_TX_TIME) { // TODO if (value < 0) flags |= BLINK|INVERS; diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 58f3b1522..4c02b4dca 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -235,7 +235,7 @@ void ViewMain::openMenu() void ViewMain::paint(BitmapBuffer * dc) { - TRACE("### ViewMain::paint(offset_x=%d;offset_y=%d) ###", + TRACE_WINDOWS("### ViewMain::paint(offset_x=%d;offset_y=%d) ###", dc->getOffsetX(), dc->getOffsetY()); OpenTxTheme::instance()->drawBackground(dc); From 6aef62c94a53b9e0f4d14ad8f1eb6972a70b3715 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 16:24:53 +0200 Subject: [PATCH 23/54] Add border around all widgets when configuring them --- radio/src/gui/colorlcd/screen_setup.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 0f3a0f4ed..5117a0482 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -143,7 +143,10 @@ class SetupWidgetsPageSlot: public Button void paint(BitmapBuffer * dc) override { if (hasFocus()) { - dc->drawRect(0, 0, width()-2, height()-2, 2, DOTTED, CHECKBOX_COLOR); + dc->drawRect(0, 0, width()-1, height()-1, 2, STASHED, CHECKBOX_COLOR); + } + else { + dc->drawSolidRect(0, 0, width()-1, height()-1, 2, LINE_COLOR); } } }; From 1b07e2e76beb3d67c985f5b0d408cc66d8cb12f2 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 17:16:11 +0200 Subject: [PATCH 24/54] Fixed scrolling issue on new main view --- radio/src/gui/colorlcd/screen_setup.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 5117a0482..80d643a03 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -172,6 +172,7 @@ class SetupWidgetsPage: public FormWindow savedView = viewMain->getCurrentMainView(); viewMain->setCurrentMainView(customScreenIdx); viewMain->bringToTop(); + setLeft(viewMain->getMainViewLeftPos(customScreenIdx)); } for (unsigned i = 0; i < screen->getZonesCount(); i++) { @@ -299,6 +300,9 @@ void ScreenAddPage::build(FormWindow * window) tab->setTitle(title); tab->setIcon(ICON_THEME_VIEW1 + newIdx); + auto viewMain = ViewMain::instance(); + viewMain->setMainViewsCount(viewMain->getMainViewsCount() + 1); + // remove current tab first menu->setCurrentTab(0); menu->removeTab(pageIndex); From 4e22bcb64574b1a9f763073db412bb541860bd65 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 17:51:14 +0200 Subject: [PATCH 25/54] Added some more for DEBUG_WINDOWS Allow for tracing when widget get invalidated and painted. --- radio/src/gui/colorlcd/layout.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index d3eb224c1..95b7caa38 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -195,9 +195,7 @@ void Layout::create() #if defined(DEBUG_WINDOWS) void Layout::paint(BitmapBuffer * dc) { - TRACE("### painting -> %s", getWindowDebugString().c_str()); - //rect_t zone = getMainZone(); - //dc->drawSolidFilledRect( zone.x, zone.y + rect.y, zone.w, zone.h, DEFAULT_BGCOLOR); + TRACE_WINDOW("# painting -> %s", getWindowDebugString().c_str()); LayoutBase::paint(dc); } #endif @@ -211,6 +209,8 @@ void Layout::checkEvents() if (now - lastRefresh >= LAYOUT_REFRESH) { lastRefresh = now; invalidate(); + + TRACE_WINDOW(("# %s refresh: %s", factory->getId(), getWindowDebugString().c_str()); } } From fd9f441c8885d81977e04addb72a6389cdadc6c0 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 18:12:29 +0200 Subject: [PATCH 26/54] Fixed typo --- radio/src/gui/colorlcd/layout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index 95b7caa38..b060f4fd6 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -210,7 +210,7 @@ void Layout::checkEvents() lastRefresh = now; invalidate(); - TRACE_WINDOW(("# %s refresh: %s", factory->getId(), getWindowDebugString().c_str()); + TRACE_WINDOW("# %s refresh: %s", factory->getId(), getWindowDebugString().c_str()); } } From dd14fff62820ef15fc679de05090ed7f216a370b Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 18:21:57 +0200 Subject: [PATCH 27/54] omg... --- radio/src/gui/colorlcd/layout.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index b060f4fd6..bd2c4c4e5 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -195,7 +195,7 @@ void Layout::create() #if defined(DEBUG_WINDOWS) void Layout::paint(BitmapBuffer * dc) { - TRACE_WINDOW("# painting -> %s", getWindowDebugString().c_str()); + TRACE_WINDOWS("# painting -> %s", getWindowDebugString().c_str()); LayoutBase::paint(dc); } #endif @@ -210,7 +210,9 @@ void Layout::checkEvents() lastRefresh = now; invalidate(); - TRACE_WINDOW("# %s refresh: %s", factory->getId(), getWindowDebugString().c_str()); +#if defined(DEBUG_WINDOWS) + TRACE_WINDOWS("# %s refresh: %s", factory->getId(), getWindowDebugString().c_str()); +#endif } } From 50d6e113f2ea4fc3d3912c43ec85d98920b8adac Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 20:19:51 +0200 Subject: [PATCH 28/54] Added auto-topbar (dis-)appearance --- radio/src/gui/colorlcd/layout.h | 6 +++--- radio/src/gui/colorlcd/view_main.cpp | 15 +++++++++++++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index 6ee989802..4246b540e 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -111,6 +111,9 @@ class Layout: public LayoutBase // Re-calculate positions void adjustDecoration(); + // Updates settings for trims, sliders, pots, etc... + void decorate(); + protected: const LayoutFactory * factory = nullptr; ViewMainDecoration* decoration = nullptr; @@ -121,9 +124,6 @@ class Layout: public LayoutBase // Last time we refreshed the window uint32_t lastRefresh = 0; - // Updates settings for trims, sliders, pots, etc... - void decorate(); - void createDecoration(); // Get the available space for widgets diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 4c02b4dca..71c4dd069 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -112,8 +112,7 @@ unsigned ViewMain::getCurrentMainView() const void ViewMain::setCurrentMainView(unsigned view) { if (view < getMainViewsCount()) { - g_model.view = view; - setScrollPositionX(g_model.view * pageWidth); + setScrollPositionX(view * pageWidth); TRACE("### switched to view #%i", g_model.view); } } @@ -142,10 +141,22 @@ void ViewMain::setScrollPositionX(coord_t value) { Window::setScrollPositionX(value); topbar->setLeft(getScrollPositionX()); + + auto pageIdx = getPageIndex(); + if (pageIdx != g_model.view) { + g_model.view = pageIdx; + // crude on/off for now + setTopbarVisible(customScreens[pageIdx]->hasTopbar()); + customScreens[pageIdx]->decorate(); + //TODO: compute topbar visibility + //auto relativeScrollPosition = getScrollPositionX() % pageWidth; + } } void ViewMain::setScrollPositionY(coord_t value) { + // this one is not used yet, but could + // usefull to place the screens upwards Window::setScrollPositionY(value); topbar->setTop(getScrollPositionY()); } From e3b1a8434317dda0d684ca24ed1d5746391e7f49 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 20:30:00 +0200 Subject: [PATCH 29/54] Topbar visibility works now on start as well (no matter the configured screens) --- radio/src/gui/colorlcd/layout.cpp | 6 +++++- radio/src/gui/colorlcd/view_main.cpp | 12 +++++++----- radio/src/gui/colorlcd/view_main.h | 10 +++++----- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index bd2c4c4e5..925bc2419 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -106,6 +106,8 @@ void loadDefaultLayout() void loadCustomScreens() { unsigned i = 0; + auto viewMain = ViewMain::instance(); + while (i < MAX_CUSTOM_SCREENS) { auto& screen = customScreens[i]; @@ -118,12 +120,14 @@ void loadCustomScreens() } // layout is ok, let's add it - auto viewMain = ViewMain::instance(); screen->attach(viewMain); viewMain->setMainViewsCount(i + 1); screen->setLeft(viewMain->getMainViewLeftPos(i)); i++; } + + viewMain->setCurrentMainView(0); + viewMain->setTopbarVisible(customScreens[0]->hasTopbar()); } // diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 71c4dd069..c5c8043c7 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -145,11 +145,13 @@ void ViewMain::setScrollPositionX(coord_t value) auto pageIdx = getPageIndex(); if (pageIdx != g_model.view) { g_model.view = pageIdx; - // crude on/off for now - setTopbarVisible(customScreens[pageIdx]->hasTopbar()); - customScreens[pageIdx]->decorate(); - //TODO: compute topbar visibility - //auto relativeScrollPosition = getScrollPositionX() % pageWidth; + if (customScreens[pageIdx]) { + // crude on/off for now + setTopbarVisible(customScreens[pageIdx]->hasTopbar()); + customScreens[pageIdx]->decorate(); + //TODO: compute topbar visibility + //auto relativeScrollPosition = getScrollPositionX() % pageWidth; + } } } diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 2de2dca53..ea0b23748 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -62,6 +62,11 @@ class ViewMain: public Window coord_t getMainViewLeftPos(unsigned view) const; + unsigned getCurrentMainView() const; + void setCurrentMainView(unsigned view); + void nextMainView(); + void previousMainView(); + protected: static ViewMain * _instance; @@ -70,11 +75,6 @@ class ViewMain: public Window friend class SetupWidgetsPage; - unsigned getCurrentMainView() const; - void setCurrentMainView(unsigned view); - void nextMainView(); - void previousMainView(); - void setScrollPositionX(coord_t value) override; void setScrollPositionY(coord_t value) override; From ceb2a50f7646e5ab04c8983b1dd23243e16e2979 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 22:26:23 +0200 Subject: [PATCH 30/54] clean-up --- radio/src/gui/colorlcd/view_main.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index c5c8043c7..d0d7e8453 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -263,29 +263,3 @@ void ViewMain::createTopbar() topbar = new TopBar(this); topbar->load(); } - -#if 0 -FormGroup * setMultiPageForm(uint8_t pages, bool focus = true) -{ - if (mainForm) - mainForm->deleteLater(); - - coord_t height = - bottomToolbarIcon >= 0 ? - MULTI_PAGE_FORM_HEIGHT - : MULTI_PAGE_FORM_WITHOUT_TOOLBAR_HEIGHT; - - mainForm = new FormWindow(this, - {0, MULTI_PAGE_FORM_TOP, LCD_W, height}, - FRSKY_PAGE_FORM_FLAGS); - - mainForm->setPageWidth(LCD_W); - mainForm->setInnerWidth(pages * LCD_W); - - if (focus) { - mainForm->setFocus(SET_FOCUS_DEFAULT); - } - - return mainForm; -} -#endif From e8829d862f9993fbe898a2061cfd996ef42fcc03 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 16 Apr 2021 22:49:00 +0200 Subject: [PATCH 31/54] WiP --- radio/src/gui/colorlcd/topbar.cpp | 13 +++++++++-- radio/src/gui/colorlcd/topbar.h | 2 +- radio/src/gui/colorlcd/view_main.cpp | 33 +++++++++++++++++----------- radio/src/gui/colorlcd/view_main.h | 4 ++-- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/radio/src/gui/colorlcd/topbar.cpp b/radio/src/gui/colorlcd/topbar.cpp index daa11a888..8fee1026d 100644 --- a/radio/src/gui/colorlcd/topbar.cpp +++ b/radio/src/gui/colorlcd/topbar.cpp @@ -43,9 +43,18 @@ rect_t TopBar::getZone(unsigned int index) const }; } -void TopBar::setVisible(bool visible) +void TopBar::setVisible(float visible) // 0.0 -> 1.0 { - setHeight(visible ? MENU_HEADER_HEIGHT : 0); + if (visible == 0.0) { + setTop(-(int)MENU_HEADER_HEIGHT); + } + else if (visible == 1.0) { + setTop(0); + } + else if (visible > 0.0 && visible < 1.0){ + float top = - (float)MENU_HEADER_HEIGHT * (1.0 - visible); + setTop((coord_t)top); + } } const char * const STR_MONTHS[] = TR_MONTHS; diff --git a/radio/src/gui/colorlcd/topbar.h b/radio/src/gui/colorlcd/topbar.h index c0c2596a2..cd6d6c2da 100644 --- a/radio/src/gui/colorlcd/topbar.h +++ b/radio/src/gui/colorlcd/topbar.h @@ -45,7 +45,7 @@ class TopBar: public WidgetsContainer rect_t getZone(unsigned int index) const override; - void setVisible(bool visible); + void setVisible(float visible); void paint(BitmapBuffer * dc) override; diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index d0d7e8453..5e1fc2183 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -72,7 +72,7 @@ ViewMain::~ViewMain() { } -void ViewMain::setTopbarVisible(bool visible) +void ViewMain::setTopbarVisible(float visible) { topbar->setVisible(visible); } @@ -98,8 +98,9 @@ coord_t ViewMain::getMainViewLeftPos(unsigned view) const rect_t ViewMain::getMainZone(rect_t zone) const { - zone.y += topbar->bottom(); - zone.h -= topbar->height(); + auto visibleHeight = topbar->bottom() - zone.y; + zone.y += visibleHeight; + zone.h -= visibleHeight; return zone; } @@ -142,16 +143,22 @@ void ViewMain::setScrollPositionX(coord_t value) Window::setScrollPositionX(value); topbar->setLeft(getScrollPositionX()); - auto pageIdx = getPageIndex(); - if (pageIdx != g_model.view) { - g_model.view = pageIdx; - if (customScreens[pageIdx]) { - // crude on/off for now - setTopbarVisible(customScreens[pageIdx]->hasTopbar()); - customScreens[pageIdx]->decorate(); - //TODO: compute topbar visibility - //auto relativeScrollPosition = getScrollPositionX() % pageWidth; - } + auto newIdx = getPageIndex(); + if (newIdx != g_model.view) { + + auto oldIdx = g_model.view; + // auto hadTopbar = customScreens[oldIdx]->hasTopbar(); + // auto willHaveTopbar = customScreens[newIdx]->hasTopbar(); + + // update current view + g_model.view = newIdx; + + // crude on/off for now + setTopbarVisible(customScreens[pageIdx]->hasTopbar()); + customScreens[pageIdx]->decorate(); + + //TODO: compute topbar visibility + //auto relativeScrollPosition = getScrollPositionX() % pageWidth; } } diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index ea0b23748..92cb3b31f 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -50,8 +50,8 @@ class ViewMain: public Window } #endif - // Set topbar visibility - void setTopbarVisible(bool visible); + // Set topbar visibility [0.0 -> 1.0] + void setTopbarVisible(float visible); // Get the available space in the middle of the screen // (without topbar) From 25ff3fcfc1c893c598599e146a89bfddda5fd97e Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 17 Apr 2021 07:03:02 +0200 Subject: [PATCH 32/54] Do not set the topbar visibility from the layout This is done only from the scroll position. --- radio/src/gui/colorlcd/layout.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index 925bc2419..5709ac81d 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -258,7 +258,6 @@ void Layout::decorate() decorationSettings = checkSettings; // Set visible decoration - ViewMain::instance()->setTopbarVisible(hasTopbar()); setSlidersVisible(hasSliders()); setTrimsVisible(hasTrims()); setFlightModeVisible(hasFlightMode()); From d7ca222eddf8626c231635d2235fd5fb3ae16aaf Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 17 Apr 2021 08:07:30 +0200 Subject: [PATCH 33/54] Fix innerHeight of widgets when topbar is added/removed (in options) --- radio/src/gui/colorlcd/widgets_container.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/radio/src/gui/colorlcd/widgets_container.h b/radio/src/gui/colorlcd/widgets_container.h index c46151fe1..ea4b8a059 100644 --- a/radio/src/gui/colorlcd/widgets_container.h +++ b/radio/src/gui/colorlcd/widgets_container.h @@ -147,7 +147,9 @@ class WidgetsContainer: public FormGroup, public WidgetsContainerInterface { for (int i = 0; i < N; i++) { if (widgets[i]) { - widgets[i]->setRect(getZone(i)); + auto zone = getZone(i); + widgets[i]->setRect(zone); + widgets[i]->setInnerHeight(zone.h); } } } From 256e53a016959da1f89a9dcc862950ba5f60750d Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 17 Apr 2021 08:08:08 +0200 Subject: [PATCH 34/54] Allow for progressive Topbar (dis-)appearance --- radio/src/gui/colorlcd/topbar.cpp | 13 +++++++++++++ radio/src/gui/colorlcd/topbar.h | 1 + 2 files changed, 14 insertions(+) diff --git a/radio/src/gui/colorlcd/topbar.cpp b/radio/src/gui/colorlcd/topbar.cpp index 8fee1026d..083df7ef2 100644 --- a/radio/src/gui/colorlcd/topbar.cpp +++ b/radio/src/gui/colorlcd/topbar.cpp @@ -57,6 +57,19 @@ void TopBar::setVisible(float visible) // 0.0 -> 1.0 } } +coord_t TopBar::getVisibleHeight(float visible) const // 0.0 -> 1.0 +{ + if (visible == 0.0) { + return 0; + } + else if (visible == 1.0) { + return MENU_HEADER_HEIGHT; + } + + float h = (float)MENU_HEADER_HEIGHT * visible; + return (coord_t)h; +} + const char * const STR_MONTHS[] = TR_MONTHS; void TopBar::paint(BitmapBuffer * dc) diff --git a/radio/src/gui/colorlcd/topbar.h b/radio/src/gui/colorlcd/topbar.h index cd6d6c2da..21424f0a2 100644 --- a/radio/src/gui/colorlcd/topbar.h +++ b/radio/src/gui/colorlcd/topbar.h @@ -46,6 +46,7 @@ class TopBar: public WidgetsContainer rect_t getZone(unsigned int index) const override; void setVisible(float visible); + coord_t getVisibleHeight(float visible) const; // 0.0 -> 1.0 void paint(BitmapBuffer * dc) override; From 93b5b1db1bd7264281b3f4922b183e3d27f021e8 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 17 Apr 2021 08:09:01 +0200 Subject: [PATCH 35/54] Fix a couple of bugs related to topbar appearance --- radio/src/gui/colorlcd/layout.cpp | 8 +--- radio/src/gui/colorlcd/layout.h | 2 - radio/src/gui/colorlcd/view_main.cpp | 66 ++++++++++++++++++++-------- radio/src/gui/colorlcd/view_main.h | 9 ++-- 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index 5709ac81d..b9b5cb962 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -127,7 +127,7 @@ void loadCustomScreens() } viewMain->setCurrentMainView(0); - viewMain->setTopbarVisible(customScreens[0]->hasTopbar()); + viewMain->updateTopbarVisibility(); } // @@ -272,13 +272,9 @@ void Layout::decorate() //invalidate(); } -void Layout::createDecoration() -{ -} - rect_t Layout::getMainZone() const { rect_t zone = decoration->getMainZone(); - return ViewMain::instance()->getMainZone(zone); + return ViewMain::instance()->getMainZone(zone, hasTopbar()); } diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index 4246b540e..81b095577 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -124,8 +124,6 @@ class Layout: public LayoutBase // Last time we refreshed the window uint32_t lastRefresh = 0; - void createDecoration(); - // Get the available space for widgets rect_t getMainZone() const; }; diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 5e1fc2183..81db27952 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -86,8 +86,15 @@ void ViewMain::setMainViewsCount(unsigned views) { if (views > MAX_CUSTOM_SCREENS) views = MAX_CUSTOM_SCREENS; - + + // update number of views this->views = views; + + // adjust current screen if needed + if (g_model.view >= views) { + setCurrentMainView(views - 1); + } + setInnerWidth(getParent()->width() * views); } @@ -96,9 +103,9 @@ coord_t ViewMain::getMainViewLeftPos(unsigned view) const return getParent()->width() * view; } -rect_t ViewMain::getMainZone(rect_t zone) const +rect_t ViewMain::getMainZone(rect_t zone, bool hasTopbar) const { - auto visibleHeight = topbar->bottom() - zone.y; + auto visibleHeight = topbar->getVisibleHeight(hasTopbar ? 1.0 : 0.0); zone.y += visibleHeight; zone.h -= visibleHeight; @@ -138,28 +145,49 @@ void ViewMain::previousMainView() setCurrentMainView(view); } +void ViewMain::updateTopbarVisibility() +{ + // relative to left visible page + int leftScroll = getScrollPositionX() % pageWidth; + if (leftScroll == 0) { + setTopbarVisible(customScreens[g_model.view]->hasTopbar()); + customScreens[g_model.view]->decorate(); + } + else { + int leftIdx = getScrollPositionX() / pageWidth; + bool leftTopbar = customScreens[leftIdx]->hasTopbar(); + bool rightTopbar = customScreens[leftIdx+1]->hasTopbar(); + + if (leftTopbar != rightTopbar) { + + float ratio = (float)leftScroll / (float)pageWidth; + + if (leftTopbar) { + // scrolling from a screen with Topbar + ratio = 1.0 - ratio; + } + else { + // scrolling to a screen with Topbar + // -> ratio is ok + } + + setTopbarVisible(ratio); + customScreens[leftIdx]->decorate(); + customScreens[leftIdx+1]->decorate(); + } + } +} + void ViewMain::setScrollPositionX(coord_t value) { Window::setScrollPositionX(value); topbar->setLeft(getScrollPositionX()); - auto newIdx = getPageIndex(); - if (newIdx != g_model.view) { + // update page index + g_model.view = getPageIndex(); - auto oldIdx = g_model.view; - // auto hadTopbar = customScreens[oldIdx]->hasTopbar(); - // auto willHaveTopbar = customScreens[newIdx]->hasTopbar(); - - // update current view - g_model.view = newIdx; - - // crude on/off for now - setTopbarVisible(customScreens[pageIdx]->hasTopbar()); - customScreens[pageIdx]->decorate(); - - //TODO: compute topbar visibility - //auto relativeScrollPosition = getScrollPositionX() % pageWidth; - } + // update Topbar + updateTopbarVisibility(); } void ViewMain::setScrollPositionY(coord_t value) diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 92cb3b31f..07ed08f34 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -50,12 +50,11 @@ class ViewMain: public Window } #endif - // Set topbar visibility [0.0 -> 1.0] - void setTopbarVisible(float visible); + void updateTopbarVisibility(); // Get the available space in the middle of the screen // (without topbar) - rect_t getMainZone(rect_t zone) const; + rect_t getMainZone(rect_t zone, bool hasTopbar) const; unsigned getMainViewsCount() const; void setMainViewsCount(unsigned views); @@ -64,6 +63,7 @@ class ViewMain: public Window unsigned getCurrentMainView() const; void setCurrentMainView(unsigned view); + void nextMainView(); void previousMainView(); @@ -75,6 +75,9 @@ class ViewMain: public Window friend class SetupWidgetsPage; + // Set topbar visibility [0.0 -> 1.0] + void setTopbarVisible(float visible); + void setScrollPositionX(coord_t value) override; void setScrollPositionY(coord_t value) override; From 8897fdbcd004198a9f0f8700a8c8f2d852e7b77c Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 17 Apr 2021 08:12:47 +0200 Subject: [PATCH 36/54] Update topbar visibility when leaving screen setup --- radio/src/gui/colorlcd/menu_screen.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/radio/src/gui/colorlcd/menu_screen.cpp b/radio/src/gui/colorlcd/menu_screen.cpp index 0fe64460d..5781baf2b 100644 --- a/radio/src/gui/colorlcd/menu_screen.cpp +++ b/radio/src/gui/colorlcd/menu_screen.cpp @@ -21,11 +21,16 @@ #include "opentx.h" #include "menu_screen.h" #include "screen_setup.h" +#include "view_main.h" ScreenMenu::ScreenMenu(): TabsGroup(ICON_THEME) { updateTabs(); + + setCloseHandler([]{ + ViewMain::instance()->updateTopbarVisibility(); + }); } void ScreenMenu::updateTabs() From 268327d0f36b4fe9e6a9a0952fb0c75fc8ded6a4 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 17 Apr 2021 09:46:47 +0200 Subject: [PATCH 37/54] Prevent screen sliding while setting up widgets --- radio/src/gui/colorlcd/screen_setup.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 80d643a03..3c60e6f4c 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -209,6 +209,14 @@ class SetupWidgetsPage: public FormWindow menu->bringToTop(); } +#if defined(HARDWARE_TOUCH) + bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override + { + // prevent screen sliding when setting up widgets + return true; + } +#endif + #if defined(HARDWARE_KEYS) void onEvent(event_t event) override { From aab6d7eab1131443f6e67f4280deb76098ad4b41 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 17 Apr 2021 12:11:14 +0200 Subject: [PATCH 38/54] Added slide limit to at most one page on main view --- radio/src/gui/colorlcd/view_main.cpp | 49 ++++++++++++++++++++++++++++ radio/src/gui/colorlcd/view_main.h | 7 ++++ 2 files changed, 56 insertions(+) diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 81db27952..e65f48c9d 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -198,6 +198,55 @@ void ViewMain::setScrollPositionY(coord_t value) topbar->setTop(getScrollPositionY()); } +#if defined(HARDWARE_TOUCH) + +//#define DEBUG_SLIDE + +bool ViewMain::onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) +{ + // prevent screen sliding over the next one (one screen at a time) + if (slidingWindow == this) { + if (prevSlideState != touchState.event) { + if (touchState.event == TE_SLIDE_END) { + startSlidePage = getCurrentMainView(); +#if defined(DEBUG_SLIDE) + TRACE("### startSlidePage = %d ###", startSlidePage); +#endif + } + prevSlideState = touchState.event; + } + else if (prevSlideState == TE_SLIDE_END){ + + // let's check what would be the next position + auto nextPos = (getScrollPositionX() - slideX); + + // if we would get over more than one page counting from slide-start + if (abs(nextPos - getMainViewLeftPos(startSlidePage)) > pageWidth) { + +#if defined(DEBUG_SLIDE) + TRACE("### kill the move ###"); +#endif + // kill the movement and let "snap-to-view" finish the job + prevSlideState = TE_NONE; + touchState.event = TE_NONE; + touchState.lastDeltaX = 0; + touchState.lastDeltaY = 0; + return true; + } + } + } + +#if defined(DEBUG_SLIDE) + TRACE("%sWindow[scrollX=%d, scrollY=%d]->onTouchSlide[x=%d, y=%d, startX=%d, startY=%d, slideX=%d, slideY=%d]", + touchState.event == TE_SLIDE_END && slidingWindow ? "###" : "", + getScrollPositionX(), getScrollPositionY(), + x, y, startX, startY, slideX, slideY); +#endif + + return Window::onTouchSlide(x, y, startX, startY, slideX, slideY); +} +#endif + #if defined(HARDWARE_KEYS) void ViewMain::onEvent(event_t event) { diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 07ed08f34..d2515f82f 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -81,6 +81,13 @@ class ViewMain: public Window void setScrollPositionX(coord_t value) override; void setScrollPositionY(coord_t value) override; +#if defined(HARDWARE_TOUCH) + unsigned char prevSlideState = 0; + unsigned int startSlidePage = 0; + + bool onTouchSlide(coord_t x, coord_t y, coord_t startX, coord_t startY, coord_t slideX, coord_t slideY) override; +#endif + #if defined(HARDWARE_KEYS) void onEvent(event_t event) override; #endif From 3c4047bb8df27f0e6aeb25566202dc8c466ec6d6 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 17 Apr 2021 14:28:23 +0200 Subject: [PATCH 39/54] Added topbar widget settings --- radio/src/gui/colorlcd/layout.cpp | 3 + radio/src/gui/colorlcd/menu_screen.cpp | 2 +- radio/src/gui/colorlcd/screen_setup.cpp | 82 ++++++++++++---------- radio/src/gui/colorlcd/screen_setup.h | 11 ++- radio/src/gui/colorlcd/topbar.cpp | 56 +++++++++++++++ radio/src/gui/colorlcd/topbar.h | 25 +++++++ radio/src/gui/colorlcd/view_main.cpp | 11 +-- radio/src/gui/colorlcd/view_main.h | 9 ++- radio/src/gui/colorlcd/widgets_container.h | 15 ++-- 9 files changed, 158 insertions(+), 56 deletions(-) diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index b9b5cb962..e1d3e1fbe 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -126,6 +126,9 @@ void loadCustomScreens() i++; } + auto topbar = viewMain->getTopbar(); + topbar->load(); + viewMain->setCurrentMainView(0); viewMain->updateTopbarVisibility(); } diff --git a/radio/src/gui/colorlcd/menu_screen.cpp b/radio/src/gui/colorlcd/menu_screen.cpp index 5781baf2b..1013fa5ba 100644 --- a/radio/src/gui/colorlcd/menu_screen.cpp +++ b/radio/src/gui/colorlcd/menu_screen.cpp @@ -37,7 +37,7 @@ void ScreenMenu::updateTabs() { removeAllTabs(); - addTab(new ScreenUserInterfacePage()); + addTab(new ScreenUserInterfacePage(this)); for (int index = 0; index < MAX_CUSTOM_SCREENS; index++) { if (customScreens[index]) { diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 3c60e6f4c..111a74b4c 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -23,6 +23,7 @@ #include "opentx.h" #include "view_main.h" #include "widget_settings.h" +#include "topbar.h" #include "libopenui.h" #define SET_DIRTY() storageDirty(EE_MODEL) @@ -107,55 +108,50 @@ class LayoutChoice: public FormField std::function setValue; }; -class SetupWidgetsPageSlot: public Button +SetupWidgetsPageSlot::SetupWidgetsPageSlot(FormGroup * parent, const rect_t & rect, WidgetsContainerInterface* container, uint8_t slotIndex): + Button(parent, rect) { - public: - SetupWidgetsPageSlot(FormGroup * parent, const rect_t & rect, Layout* screen, uint8_t slotIndex): - Button(parent, rect) - { - //auto parent = (Window*)this; - setPressHandler([parent, screen, slotIndex]() -> uint8_t { + setPressHandler([parent, container, slotIndex]() -> uint8_t { + Menu * menu = new Menu(parent); + menu->addLine(TR_SELECT_WIDGET, [=]() { Menu * menu = new Menu(parent); - menu->addLine(TR_SELECT_WIDGET, [=]() { - Menu * menu = new Menu(parent); - for (auto factory: getRegisteredWidgets()) { - menu->addLine(factory->getName(), [=]() { - screen->createWidget(slotIndex, factory); - }); - } - }); - - if (screen->getWidget(slotIndex)) { - menu->addLine(TR_WIDGET_SETTINGS, [=]() { - auto widget = screen->getWidget(slotIndex); - new WidgetSettings(parent, widget); - }); - menu->addLine(STR_REMOVE_WIDGET, [=]() { - screen->removeWidget(slotIndex); + for (auto factory: getRegisteredWidgets()) { + menu->addLine(factory->getName(), [=]() { + container->createWidget(slotIndex, factory); }); } - - return 0; }); - } - void paint(BitmapBuffer * dc) override - { - if (hasFocus()) { - dc->drawRect(0, 0, width()-1, height()-1, 2, STASHED, CHECKBOX_COLOR); + if (container->getWidget(slotIndex)) { + menu->addLine(TR_WIDGET_SETTINGS, [=]() { + auto widget = container->getWidget(slotIndex); + new WidgetSettings(parent, widget); + }); + menu->addLine(STR_REMOVE_WIDGET, [=]() { + container->removeWidget(slotIndex); + }); } - else { - dc->drawSolidRect(0, 0, width()-1, height()-1, 2, LINE_COLOR); - } - } -}; + + return 0; + }); +} + +void SetupWidgetsPageSlot::paint(BitmapBuffer * dc) +{ + if (hasFocus()) { + dc->drawRect(0, 0, width()-1, height()-1, 2, STASHED, CHECKBOX_COLOR); + } + else { + dc->drawSolidRect(0, 0, width()-1, height()-1, 2, LINE_COLOR); + } +} class SetupWidgetsPage: public FormWindow { public: - SetupWidgetsPage(ScreenMenu* menu, uint8_t customScreenIdx): - FormWindow(ViewMain::instance(), {0, 0, 0, 0}, FORM_FORWARD_FOCUS), + SetupWidgetsPage(ScreenMenu* menu, uint8_t customScreenIdx): + FormWindow(ViewMain::instance(), {0, 0, 0, 0}, FORM_FORWARD_FOCUS), menu(menu), customScreenIdx(customScreenIdx) { @@ -242,8 +238,9 @@ class SetupWidgetsPage: public FormWindow // } }; -ScreenUserInterfacePage::ScreenUserInterfacePage(): - PageTab(STR_USER_INTERFACE, ICON_THEME_SETUP) +ScreenUserInterfacePage::ScreenUserInterfacePage(ScreenMenu* menu): + PageTab(STR_USER_INTERFACE, ICON_THEME_SETUP), + menu(menu) { } @@ -262,6 +259,13 @@ void ScreenUserInterfacePage::build(FormWindow * window) new StaticText(window, grid.getLabelSlot(), STR_TOP_BAR, 0, 0); // TODO: enable settings topbar widgets grid.nextLine(); + + auto menu = this->menu; + auto setupTopbarWidgets = new TextButton(window, grid.getFieldSlot(), STR_SETUP_WIDGETS); + setupTopbarWidgets->setPressHandler([menu]() -> uint8_t { + new SetupTopBarWidgetsPage(menu); + return 0; + }); } ScreenAddPage::ScreenAddPage(ScreenMenu * menu, uint8_t pageIndex): diff --git a/radio/src/gui/colorlcd/screen_setup.h b/radio/src/gui/colorlcd/screen_setup.h index a04c16b0f..50767f3f3 100644 --- a/radio/src/gui/colorlcd/screen_setup.h +++ b/radio/src/gui/colorlcd/screen_setup.h @@ -24,11 +24,12 @@ class ScreenUserInterfacePage: public PageTab { public: - ScreenUserInterfacePage(); + ScreenUserInterfacePage(ScreenMenu* menu); void build(FormWindow * window) override; protected: + ScreenMenu * menu; }; class ScreenAddPage: public PageTab { @@ -53,3 +54,11 @@ class ScreenSetupPage: public PageTab { unsigned pageIndex; unsigned customScreenIndex; }; + +class SetupWidgetsPageSlot: public Button +{ + public: + SetupWidgetsPageSlot(FormGroup * parent, const rect_t & rect, WidgetsContainerInterface* container, uint8_t slotIndex); + + void paint(BitmapBuffer * dc) override; +}; diff --git a/radio/src/gui/colorlcd/topbar.cpp b/radio/src/gui/colorlcd/topbar.cpp index 083df7ef2..38b77befc 100644 --- a/radio/src/gui/colorlcd/topbar.cpp +++ b/radio/src/gui/colorlcd/topbar.cpp @@ -19,6 +19,10 @@ */ #include "opentx.h" +#include "layer.h" +#include "view_main.h" +#include "screen_setup.h" +#include "storage/storage.h" constexpr uint32_t TOPBAR_REFRESH = 1000 / 2; // 2 Hz @@ -193,3 +197,55 @@ void TopBar::checkEvents() invalidate(); } } + + +SetupTopBarWidgetsPage::SetupTopBarWidgetsPage(ScreenMenu* menu): + FormWindow(ViewMain::instance(), {0, 0, 0, 0}, FORM_FORWARD_FOCUS), + menu(menu) +{ + // remember focus + Layer::push(this); + + auto viewMain = ViewMain::instance(); + + // save current view & switch to 1st one + savedView = viewMain->getCurrentMainView(); + viewMain->setCurrentMainView(0); + viewMain->bringToTop(); + + //TODO: force the topbar to be visible? + + // adopt the dimensions of the main view + setRect(viewMain->getRect()); + + auto topbar = viewMain->getTopbar(); + for (unsigned i = 0; i < topbar->getZonesCount(); i++) { + auto rect = topbar->getZone(i); + auto widget = new SetupWidgetsPageSlot(this, rect, topbar, i); + if (i == 0) widget->setFocus(); + } +} + +void SetupTopBarWidgetsPage::deleteLater(bool detach, bool trash) +{ + // restore screen setting tab on top + menu->bringToTop(); + Layer::pop(this); + + // and continue async deletion... + FormWindow::deleteLater(detach, trash); + + storageDirty(EE_MODEL); +} + +#if defined(HARDWARE_KEYS) +void SetupTopBarWidgetsPage::onEvent(event_t event) +{ + switch (event) { + case EVT_KEY_BREAK(KEY_EXIT): + killEvents(event); + deleteLater(); + break; + } +} +#endif diff --git a/radio/src/gui/colorlcd/topbar.h b/radio/src/gui/colorlcd/topbar.h index 21424f0a2..34679be65 100644 --- a/radio/src/gui/colorlcd/topbar.h +++ b/radio/src/gui/colorlcd/topbar.h @@ -56,4 +56,29 @@ class TopBar: public WidgetsContainer uint32_t lastRefresh = 0; }; +class ScreenMenu; + +class SetupTopBarWidgetsPage: public FormWindow +{ + public: + explicit SetupTopBarWidgetsPage(ScreenMenu* menu); + +#if defined(DEBUG_WINDOWS) + std::string getName() const override + { + return "SetupTopBarWidgetsPage"; + } +#endif + + void deleteLater(bool detach = true, bool trash = true) override; + +#if defined(HARDWARE_KEYS) + void onEvent(event_t event) override; +#endif + + protected: + ScreenMenu* menu; + unsigned savedView = 0; +}; + #endif // _TOPBAR_H_ diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index e65f48c9d..18c9b4c7c 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -34,7 +34,8 @@ ViewMain * ViewMain::_instance = nullptr; ViewMain::ViewMain(): - Window(MainWindow::instance(), MainWindow::instance()->getRect()) + Window(MainWindow::instance(), MainWindow::instance()->getRect()), + topbar(new TopBar(this)) { #if defined(HARDWARE_TOUCH) && !defined(HARDWARE_KEYS) new FabButton(this, 50, 100, ICON_MODEL, @@ -62,9 +63,7 @@ ViewMain::ViewMain(): }, NO_FOCUS); #endif - createTopbar(); setPageWidth(getParent()->width()); - focusWindow = this; } @@ -341,9 +340,3 @@ void ViewMain::paint(BitmapBuffer * dc) g_model.view = 0; } } - -void ViewMain::createTopbar() -{ - topbar = new TopBar(this); - topbar->load(); -} diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index d2515f82f..20f5ba610 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -26,6 +26,7 @@ class TopBar; class SetupWidgetsPage; +class SetupTopBarWidgetsPage; class ViewMain: public Window { @@ -67,13 +68,20 @@ class ViewMain: public Window void nextMainView(); void previousMainView(); + TopBar* getTopbar() const + { + return topbar; + } + protected: static ViewMain * _instance; unsigned views = 0; TopBar* topbar = nullptr; + // Widget setup requires special permissions ;-) friend class SetupWidgetsPage; + friend class SetupTopBarWidgetsPage; // Set topbar visibility [0.0 -> 1.0] void setTopbarVisible(float visible); @@ -94,7 +102,6 @@ class ViewMain: public Window void paint(BitmapBuffer * dc) override; void openMenu(); - void createTopbar(); }; #endif // _VIEW_MAIN_H_ diff --git a/radio/src/gui/colorlcd/widgets_container.h b/radio/src/gui/colorlcd/widgets_container.h index ea4b8a059..6276aeeb3 100644 --- a/radio/src/gui/colorlcd/widgets_container.h +++ b/radio/src/gui/colorlcd/widgets_container.h @@ -32,6 +32,7 @@ class WidgetsContainerInterface virtual rect_t getZone(unsigned int index) const = 0; virtual Widget * createWidget(unsigned int index, const WidgetFactory * factory) = 0; virtual Widget * getWidget(unsigned int index) = 0; + virtual void removeWidget(unsigned int index) = 0; }; #define WIDGET_NAME_LEN 10 @@ -77,7 +78,7 @@ class WidgetsContainer: public FormGroup, public WidgetsContainerInterface return widget; } - void removeWidget(unsigned int index) + void removeWidget(unsigned int index) override { if (index >= N) return; @@ -107,16 +108,20 @@ class WidgetsContainer: public FormGroup, public WidgetsContainerInterface { unsigned int count = getZonesCount(); for (unsigned int i = 0; i < count; i++) { - delete widgets[i]; + + // remove old widget + if (widgets[i]) { + widgets[i]->deleteLater(); + widgets[i] = nullptr; + } + + // and load new one if required if (persistentData->zones[i].widgetName[0]) { char name[WIDGET_NAME_LEN + 1]; memset(name, 0, sizeof(name)); strncpy(name, persistentData->zones[i].widgetName, WIDGET_NAME_LEN); widgets[i] = loadWidget(name, this, getZone(i), &persistentData->zones[i].widgetData); } - else { - widgets[i] = nullptr; - } } } From 413b97c9d6594f27193e5c5dcf18354a901905b3 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sat, 17 Apr 2021 19:00:56 +0200 Subject: [PATCH 40/54] Refactor layout / widget interface This allows to cut loose quite some dependencies on headers. --- radio/src/audio.h | 1 + radio/src/datastructs.h | 6 +- radio/src/gui/colorlcd/gui.h | 2 +- radio/src/gui/colorlcd/layout.cpp | 117 +---------- radio/src/gui/colorlcd/layout.h | 166 ++------------- radio/src/gui/colorlcd/layouts/layout1x1.cpp | 4 +- radio/src/gui/colorlcd/layouts/layout2+1.cpp | 5 +- radio/src/gui/colorlcd/layouts/layout2x1.cpp | 5 +- radio/src/gui/colorlcd/layouts/layout2x2.cpp | 5 +- radio/src/gui/colorlcd/layouts/layout2x4.cpp | 5 +- .../layouts/layout_factory_implem.cpp | 127 ++++++++++++ .../colorlcd/layouts/layout_factory_implem.h | 161 +++++++++++++++ radio/src/gui/colorlcd/layouts/sliders.cpp | 76 +++++++ radio/src/gui/colorlcd/layouts/sliders.h | 57 +---- .../src/gui/colorlcd/layouts/topbar_impl.cpp | 195 ++++++++++++++++++ radio/src/gui/colorlcd/layouts/topbar_impl.h | 67 ++++++ radio/src/gui/colorlcd/screen_setup.cpp | 6 +- radio/src/gui/colorlcd/topbar.cpp | 178 +--------------- radio/src/gui/colorlcd/topbar.h | 45 ++-- radio/src/gui/colorlcd/view_main.cpp | 30 ++- radio/src/gui/colorlcd/view_main.h | 14 +- radio/src/gui/colorlcd/widget.cpp | 5 +- radio/src/gui/colorlcd/widget.h | 12 +- radio/src/gui/colorlcd/widgets/gauge.cpp | 1 + radio/src/gui/colorlcd/widgets/modelbmp.cpp | 2 + radio/src/gui/colorlcd/widgets/outputs.cpp | 1 + radio/src/gui/colorlcd/widgets/text.cpp | 1 + radio/src/gui/colorlcd/widgets/timer.cpp | 1 + radio/src/gui/colorlcd/widgets/value.cpp | 1 + .../widgets/widgets_container_implem.h | 156 ++++++++++++++ radio/src/gui/colorlcd/widgets_container.h | 179 +++++----------- .../src/storage/conversions/datastructs_218.h | 4 +- 32 files changed, 942 insertions(+), 693 deletions(-) create mode 100644 radio/src/gui/colorlcd/layouts/layout_factory_implem.cpp create mode 100644 radio/src/gui/colorlcd/layouts/layout_factory_implem.h create mode 100644 radio/src/gui/colorlcd/layouts/sliders.cpp create mode 100644 radio/src/gui/colorlcd/layouts/topbar_impl.cpp create mode 100644 radio/src/gui/colorlcd/layouts/topbar_impl.h create mode 100644 radio/src/gui/colorlcd/widgets/widgets_container_implem.h diff --git a/radio/src/audio.h b/radio/src/audio.h index c6d688434..e47c3cc53 100644 --- a/radio/src/audio.h +++ b/radio/src/audio.h @@ -25,6 +25,7 @@ #include #include "ff.h" #include "opentx_types.h" +#include "dataconstants.h" /* Implements a bit field, number of bits is set by the template, diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index ae07276b3..69bb23166 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -553,11 +553,11 @@ typedef uint8_t swarnenable_t; #define LAYOUT_ID_LEN 10 PACK(struct CustomScreenData { char LayoutId[LAYOUT_ID_LEN]; - Layout::PersistentData layoutData; + LayoutPersistentData layoutData; }); #define CUSTOM_SCREENS_DATA \ NOBACKUP(CustomScreenData screenData[MAX_CUSTOM_SCREENS]); \ - NOBACKUP(TopBar::PersistentData topbarData); \ + NOBACKUP(TopBarPersistentData topbarData); \ NOBACKUP(uint8_t view); #else #define CUSTOM_SCREENS_DATA \ @@ -921,7 +921,7 @@ static inline void check_struct() CHKSIZE(ModelHeader, 31); CHKSIZE(CurveHeader, 4); CHKSIZE(CustomScreenData, 850); - CHKSIZE(TopBar::PersistentData, 300); + CHKTYPE(TopBarPersistentData, 300); #elif defined(PCBNV14) // TODO #elif defined(PCBSKY9X) diff --git a/radio/src/gui/colorlcd/gui.h b/radio/src/gui/colorlcd/gui.h index 12f0e6682..4b38183cc 100644 --- a/radio/src/gui/colorlcd/gui.h +++ b/radio/src/gui/colorlcd/gui.h @@ -47,7 +47,7 @@ void drawCurveHorizontalScale(); void drawCurveCoord(int x, int y, const char * text, bool active=false); void drawCurvePoint(int x, int y, LcdFlags color); -extern Layout * customScreens[MAX_CUSTOM_SCREENS]; +extern WidgetsContainerInterface * customScreens[MAX_CUSTOM_SCREENS]; void drawAlertBox(const char * title, const char * text, const char * action); void showAlertBox(const char * title, const char * text, const char * action, uint8_t sound); diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index e1d3e1fbe..a9441b309 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -20,13 +20,8 @@ #include "opentx.h" #include "view_main.h" -#include "layouts/trims.h" -#include "layouts/sliders.h" -#include "view_main_decoration.h" -constexpr uint32_t LAYOUT_REFRESH = 1000 / 2; // 2 Hz - -Layout * customScreens[MAX_CUSTOM_SCREENS] = {}; +WidgetsContainerInterface * customScreens[MAX_CUSTOM_SCREENS] = {}; std::list & getRegisteredLayouts() { @@ -54,7 +49,8 @@ const LayoutFactory * getLayoutFactory(const char * name) // // Loads a layout, but does not attach it to any window // -Layout * loadLayout(const char * name, Layout::PersistentData * persistentData) +WidgetsContainerInterface * +loadLayout(const char * name, LayoutPersistentData * persistentData) { const LayoutFactory * factory = getLayoutFactory(name); if (factory) { @@ -127,6 +123,8 @@ void loadCustomScreens() } auto topbar = viewMain->getTopbar(); + + // TODO: how to reload this guy? topbar->load(); viewMain->setCurrentMainView(0); @@ -139,7 +137,8 @@ void loadCustomScreens() // - new screen is configured into g_model // - the new screen is returned (not attached) // -Layout* createCustomScreen(const LayoutFactory* factory, unsigned customScreenIndex) +WidgetsContainerInterface * +createCustomScreen(const LayoutFactory* factory, unsigned customScreenIndex) { if (!factory || (customScreenIndex >= MAX_CUSTOM_SCREENS)) return nullptr; @@ -180,104 +179,10 @@ void disposeCustomScreen(unsigned idx) memset(dst, 0, len); } -Layout::Layout(const LayoutFactory * factory, PersistentData * persistentData): - LayoutBase({0, 0, LCD_W, LCD_H}, persistentData), - factory(factory), - decoration(new ViewMainDecoration(this, getRect())) +LayoutFactory::LayoutFactory(const char * id, const char * name): + id(id), + name(name) { - decorate(); + registerLayout(this); } -void Layout::create() -{ - memset(persistentData, 0, sizeof(PersistentData)); - - getOptionValue(OPTION_TOPBAR)->boolValue = true; - getOptionValue(OPTION_FM)->boolValue = true; - getOptionValue(OPTION_SLIDERS)->boolValue = true; - getOptionValue(OPTION_TRIMS)->boolValue = true; - getOptionValue(OPTION_MIRRORED)->boolValue = false; -} - -#if defined(DEBUG_WINDOWS) -void Layout::paint(BitmapBuffer * dc) -{ - TRACE_WINDOWS("# painting -> %s", getWindowDebugString().c_str()); - LayoutBase::paint(dc); -} -#endif - -void Layout::checkEvents() -{ - LayoutBase::checkEvents(); - decorate(); - - uint32_t now = RTOS_GET_MS(); - if (now - lastRefresh >= LAYOUT_REFRESH) { - lastRefresh = now; - invalidate(); - -#if defined(DEBUG_WINDOWS) - TRACE_WINDOWS("# %s refresh: %s", factory->getId(), getWindowDebugString().c_str()); -#endif - } -} - -void Layout::setTrimsVisible(bool visible) -{ - decoration->setTrimsVisible(visible); -} - -void Layout::setSlidersVisible(bool visible) -{ - decoration->setSlidersVisible(visible); -} - -void Layout::setFlightModeVisible(bool visible) -{ - decoration->setFlightModeVisible(visible); -} - -void Layout::adjustDecoration() -{ - decoration->adjustDecoration(); -} - -void Layout::decorate() -{ - // Check if deco setting are still up-to-date - uint8_t checkSettings = - (hasTopbar() ? 1 << 0 : 0) | - (hasSliders() ? 1 << 1 : 0) | - (hasTrims() ? 1 << 2 : 0) | - (hasFlightMode() ? 1 << 3 : 0); - - if (checkSettings == decorationSettings) { - // everything ok, exit! - return; - } - - // Save settings - decorationSettings = checkSettings; - - // Set visible decoration - setSlidersVisible(hasSliders()); - setTrimsVisible(hasTrims()); - setFlightModeVisible(hasFlightMode()); - - // Re-compute positions - adjustDecoration(); - - // and update relevant windows - updateZones(); - - // probably not needed - //invalidate(); -} - -rect_t Layout::getMainZone() const -{ - rect_t zone = decoration->getMainZone(); - return ViewMain::instance()->getMainZone(zone, hasTopbar()); -} - diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index 81b095577..54d9d1b58 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -22,180 +22,35 @@ #include #include "widgets_container.h" -#include "lcd.h" -#include "topbar.h" #define MAX_LAYOUT_ZONES 10 #define MAX_LAYOUT_OPTIONS 10 constexpr coord_t TRIM_LINE_WIDTH = 8; constexpr coord_t TRIM_SQUARE_SIZE = 17; constexpr coord_t MAIN_ZONE_BORDER = 10; +constexpr uint32_t LAYOUT_REFRESH = 1000 / 2; // 2 Hz -class LayoutFactory; -class ViewMainDecoration; +class BitmapBuffer; -#define LAYOUT_COMMON_OPTIONS \ - { STR_TOP_BAR, ZoneOption::Bool }, \ - { STR_FLIGHT_MODE, ZoneOption::Bool }, \ - { STR_SLIDERS, ZoneOption::Bool }, \ - { STR_TRIMS, ZoneOption::Bool }, \ - { STR_MIRROR, ZoneOption::Bool } - -#define LAYOUT_OPTIONS_END \ - { nullptr, ZoneOption::Bool } - -typedef WidgetsContainer LayoutBase; - -class Layout: public LayoutBase -{ - friend class LayoutFactory; - - public: - - // Common 'ZoneOptionValue's among all layouts - enum { - OPTION_TOPBAR = 0, - OPTION_FM, - OPTION_SLIDERS, - OPTION_TRIMS, - OPTION_MIRRORED, - - OPTION_LAST_DEFAULT=OPTION_MIRRORED - }; - - Layout(const LayoutFactory * factory, PersistentData * persistentData); - -#if defined(DEBUG_WINDOWS) - std::string getName() const override - { - return "Layout"; - } - - void paint(BitmapBuffer * dc) override; -#endif - - void create() override; - - inline const LayoutFactory * getFactory() const - { - return factory; - } - - void checkEvents() override; - - bool hasTopbar() const { - return getOptionValue(OPTION_TOPBAR)->boolValue; - } - - bool hasFlightMode() const { - return getOptionValue(OPTION_FM)->boolValue; - } - - bool hasSliders() const { - return getOptionValue(OPTION_SLIDERS)->boolValue; - } - - bool hasTrims() const { - return getOptionValue(OPTION_TRIMS)->boolValue; - } - - bool isMirrored() const { - return getOptionValue(OPTION_MIRRORED)->boolValue; - } - - // Set decoration visibility - void setTrimsVisible(bool visible); - void setSlidersVisible(bool visible); - void setFlightModeVisible(bool visible); - - // Re-calculate positions - void adjustDecoration(); - - // Updates settings for trims, sliders, pots, etc... - void decorate(); - - protected: - const LayoutFactory * factory = nullptr; - ViewMainDecoration* decoration = nullptr; - - // Decoration settings bitmask to detect updates - uint8_t decorationSettings = 0; - - // Last time we refreshed the window - uint32_t lastRefresh = 0; - - // Get the available space for widgets - rect_t getMainZone() const; -}; - -void registerLayout(const LayoutFactory * factory); +typedef WidgetsContainerPersistentData LayoutPersistentData; class LayoutFactory { public: - LayoutFactory(const char * id, const char * name): - id(id), - name(name) - { - registerLayout(this); - } + LayoutFactory(const char * id, const char * name); const char * getId() const { return id; } const char * getName() const { return name; } virtual void drawThumb(BitmapBuffer * dc, uint16_t x, uint16_t y, LcdFlags flags) const = 0; virtual const ZoneOption * getOptions() const = 0; - virtual Layout * create(Layout::PersistentData * persistentData) const = 0; - virtual Layout * load(Layout::PersistentData * persistentData) const = 0; + virtual WidgetsContainerInterface * create(LayoutPersistentData * persistentData) const = 0; + virtual WidgetsContainerInterface * load(LayoutPersistentData * persistentData) const = 0; protected: const char * id; const char * name; }; -template -class BaseLayoutFactory: public LayoutFactory -{ - public: - BaseLayoutFactory(const char * id, const char * name, const uint8_t * bitmap, const ZoneOption * options): - LayoutFactory(id, name), - bitmap(bitmap), - options(options) - { - } - - void drawThumb(BitmapBuffer * dc, uint16_t x, uint16_t y, uint32_t flags) const override - { - dc->drawBitmapPattern(x, y, bitmap, flags); - } - - const ZoneOption * getOptions() const override - { - return options; - } - - Layout * create(Layout::PersistentData * persistentData) const override - { - Layout * layout = new T(this, persistentData); - if (layout) { - layout->create(); - } - return layout; - } - - Layout * load(Layout::PersistentData * persistentData) const override - { - Layout * layout = new T(this, persistentData); - if (layout) { - layout->load(); - } - return layout; - } - - protected: - const uint8_t * bitmap; - const ZoneOption * options; -}; - -Layout * loadLayout(const char * name, Layout::PersistentData * persistentData); +WidgetsContainerInterface * loadLayout(const char * name, LayoutPersistentData * persistentData); // intented for new models void loadDefaultLayout(); @@ -206,9 +61,14 @@ void loadCustomScreens(); // delete all custom screens from memory void deleteCustomScreens(); -Layout* createCustomScreen(const LayoutFactory* factory, unsigned customScreenIndex); +WidgetsContainerInterface * +createCustomScreen(const LayoutFactory* factory, unsigned customScreenIndex); // Remove custom screen from the model void disposeCustomScreen(unsigned idx); +// Layout must register to be found +void registerLayout(const LayoutFactory * factory); + +// List of registered layout factories std::list & getRegisteredLayouts(); diff --git a/radio/src/gui/colorlcd/layouts/layout1x1.cpp b/radio/src/gui/colorlcd/layouts/layout1x1.cpp index f2fc0524d..96296388f 100644 --- a/radio/src/gui/colorlcd/layouts/layout1x1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1x1.cpp @@ -18,8 +18,8 @@ * GNU General Public License for more details. */ -#include "opentx.h" -#include "trims.h" +#include "layout.h" +#include "layout_factory_implem.h" const uint8_t LBM_LAYOUT_1x1[] = { #include "mask_layout1x1.lbm" diff --git a/radio/src/gui/colorlcd/layouts/layout2+1.cpp b/radio/src/gui/colorlcd/layouts/layout2+1.cpp index 29b8f7d5a..3977ecbdd 100644 --- a/radio/src/gui/colorlcd/layouts/layout2+1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2+1.cpp @@ -18,9 +18,8 @@ * GNU General Public License for more details. */ -#include "opentx.h" -#include "sliders.h" -#include "trims.h" +#include "layout.h" +#include "layout_factory_implem.h" const uint8_t LBM_LAYOUT_2P1[] = { #include "mask_layout2+1.lbm" diff --git a/radio/src/gui/colorlcd/layouts/layout2x1.cpp b/radio/src/gui/colorlcd/layouts/layout2x1.cpp index c9bd5831b..db38eaba3 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x1.cpp @@ -18,9 +18,8 @@ * GNU General Public License for more details. */ -#include "opentx.h" -#include "sliders.h" -#include "trims.h" +#include "layout.h" +#include "layout_factory_implem.h" const uint8_t LBM_LAYOUT_2x1[] = { #include "mask_layout2x1.lbm" diff --git a/radio/src/gui/colorlcd/layouts/layout2x2.cpp b/radio/src/gui/colorlcd/layouts/layout2x2.cpp index 6e8d78632..8b48adc46 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x2.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x2.cpp @@ -18,9 +18,8 @@ * GNU General Public License for more details. */ -#include "opentx.h" -#include "sliders.h" -#include "trims.h" +#include "layout.h" +#include "layout_factory_implem.h" const uint8_t LBM_LAYOUT_2x2[] = { #include "mask_layout2x2.lbm" diff --git a/radio/src/gui/colorlcd/layouts/layout2x4.cpp b/radio/src/gui/colorlcd/layouts/layout2x4.cpp index 618f98a6f..4b01e3ae2 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x4.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x4.cpp @@ -18,7 +18,8 @@ * GNU General Public License for more details. */ -#include "opentx.h" +#include "layout.h" +#include "layout_factory_implem.h" const uint8_t LBM_LAYOUT_2x4[] = { #include "mask_layout2x4.lbm" @@ -38,7 +39,7 @@ class Layout2x4: public Layout public: enum { - OPTION_PANEL1_BACKGROUND = OPTION_LAST_DEFAULT + 1, + OPTION_PANEL1_BACKGROUND = LAYOUT_OPTION_LAST_DEFAULT + 1, OPTION_PANEL1_COLOR, OPTION_PANEL2_BACKGROUND, OPTION_PANEL2_COLOR diff --git a/radio/src/gui/colorlcd/layouts/layout_factory_implem.cpp b/radio/src/gui/colorlcd/layouts/layout_factory_implem.cpp new file mode 100644 index 000000000..c173f2524 --- /dev/null +++ b/radio/src/gui/colorlcd/layouts/layout_factory_implem.cpp @@ -0,0 +1,127 @@ +/* + * 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 "layout_factory_implem.h" +#include "layouts/trims.h" +#include "layouts/sliders.h" +#include "view_main_decoration.h" +#include "view_main.h" + +Layout::Layout(const LayoutFactory * factory, PersistentData * persistentData): + LayoutBase({0, 0, LCD_W, LCD_H}, persistentData), + factory(factory), + decoration(new ViewMainDecoration(this, getRect())) +{ + decorate(); +} + +void Layout::create() +{ + memset(persistentData, 0, sizeof(PersistentData)); + + getOptionValue(LAYOUT_OPTION_TOPBAR)->boolValue = true; + getOptionValue(LAYOUT_OPTION_FM)->boolValue = true; + getOptionValue(LAYOUT_OPTION_SLIDERS)->boolValue = true; + getOptionValue(LAYOUT_OPTION_TRIMS)->boolValue = true; + getOptionValue(LAYOUT_OPTION_MIRRORED)->boolValue = false; +} + +#if defined(DEBUG_WINDOWS) +void Layout::paint(BitmapBuffer * dc) +{ + TRACE_WINDOWS("# painting -> %s", getWindowDebugString().c_str()); + LayoutBase::paint(dc); +} +#endif + +void Layout::checkEvents() +{ + LayoutBase::checkEvents(); + decorate(); + + uint32_t now = RTOS_GET_MS(); + if (now - lastRefresh >= LAYOUT_REFRESH) { + lastRefresh = now; + invalidate(); + +#if defined(DEBUG_WINDOWS) + TRACE_WINDOWS("# %s refresh: %s", factory->getId(), getWindowDebugString().c_str()); +#endif + } +} + +void Layout::setTrimsVisible(bool visible) +{ + decoration->setTrimsVisible(visible); +} + +void Layout::setSlidersVisible(bool visible) +{ + decoration->setSlidersVisible(visible); +} + +void Layout::setFlightModeVisible(bool visible) +{ + decoration->setFlightModeVisible(visible); +} + +void Layout::adjustDecoration() +{ + decoration->adjustDecoration(); +} + +void Layout::decorate() +{ + // Check if deco setting are still up-to-date + uint8_t checkSettings = + (hasTopbar() ? 1 << 0 : 0) | + (hasSliders() ? 1 << 1 : 0) | + (hasTrims() ? 1 << 2 : 0) | + (hasFlightMode() ? 1 << 3 : 0); + + if (checkSettings == decorationSettings) { + // everything ok, exit! + return; + } + + // Save settings + decorationSettings = checkSettings; + + // Set visible decoration + setSlidersVisible(hasSliders()); + setTrimsVisible(hasTrims()); + setFlightModeVisible(hasFlightMode()); + + // Re-compute positions + adjustDecoration(); + + // and update relevant windows + updateZones(); + + // probably not needed + //invalidate(); +} + +rect_t Layout::getMainZone() const +{ + rect_t zone = decoration->getMainZone(); + return ViewMain::instance()->getMainZone(zone, hasTopbar()); +} + diff --git a/radio/src/gui/colorlcd/layouts/layout_factory_implem.h b/radio/src/gui/colorlcd/layouts/layout_factory_implem.h new file mode 100644 index 000000000..95a34c7f4 --- /dev/null +++ b/radio/src/gui/colorlcd/layouts/layout_factory_implem.h @@ -0,0 +1,161 @@ +/* + * 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. + */ + +#pragma once + +#include + +//#include "lcd.h" +//#include "topbar.h" + +#include "audio.h" +#include "translations.h" + +#include "layout.h" +#include "widgets/widgets_container_implem.h" + +#define LAYOUT_COMMON_OPTIONS \ + { STR_TOP_BAR, ZoneOption::Bool }, \ + { STR_FLIGHT_MODE, ZoneOption::Bool }, \ + { STR_SLIDERS, ZoneOption::Bool }, \ + { STR_TRIMS, ZoneOption::Bool }, \ + { STR_MIRROR, ZoneOption::Bool } + +#define LAYOUT_OPTIONS_END \ + { nullptr, ZoneOption::Bool } + +class ViewMainDecoration; + +typedef WidgetsContainer LayoutBase; + +class Layout: public LayoutBase +{ + friend class LayoutFactory; + + public: + + Layout(const LayoutFactory * factory, PersistentData * persistentData); + +#if defined(DEBUG_WINDOWS) + std::string getName() const override + { + return "Layout"; + } + + void paint(BitmapBuffer * dc) override; +#endif + + void create() override; + + const LayoutFactory * getFactory() const override + { + return factory; + } + + void checkEvents() override; + + bool hasTopbar() const { + return getOptionValue(LAYOUT_OPTION_TOPBAR)->boolValue; + } + + bool hasFlightMode() const { + return getOptionValue(LAYOUT_OPTION_FM)->boolValue; + } + + bool hasSliders() const { + return getOptionValue(LAYOUT_OPTION_SLIDERS)->boolValue; + } + + bool hasTrims() const { + return getOptionValue(LAYOUT_OPTION_TRIMS)->boolValue; + } + + bool isMirrored() const { + return getOptionValue(LAYOUT_OPTION_MIRRORED)->boolValue; + } + + // Set decoration visibility + void setTrimsVisible(bool visible); + void setSlidersVisible(bool visible); + void setFlightModeVisible(bool visible); + + // Re-calculate positions + void adjustDecoration(); + + // Updates settings for trims, sliders, pots, etc... + void decorate() override; + + protected: + const LayoutFactory * factory = nullptr; + ViewMainDecoration* decoration = nullptr; + + // Decoration settings bitmask to detect updates + uint8_t decorationSettings = 0; + + // Last time we refreshed the window + uint32_t lastRefresh = 0; + + // Get the available space for widgets + rect_t getMainZone() const; +}; + +template +class BaseLayoutFactory: public LayoutFactory +{ + public: + BaseLayoutFactory(const char * id, const char * name, const uint8_t * bitmap, const ZoneOption * options): + LayoutFactory(id, name), + bitmap(bitmap), + options(options) + { + } + + void drawThumb(BitmapBuffer * dc, uint16_t x, uint16_t y, uint32_t flags) const override + { + dc->drawBitmapPattern(x, y, bitmap, flags); + } + + const ZoneOption * getOptions() const override + { + return options; + } + + Layout * create(Layout::PersistentData * persistentData) const override + { + Layout * layout = new T(this, persistentData); + if (layout) { + layout->create(); + } + return layout; + } + + Layout * load(Layout::PersistentData * persistentData) const override + { + Layout * layout = new T(this, persistentData); + if (layout) { + layout->load(); + } + return layout; + } + + protected: + const uint8_t * bitmap; + const ZoneOption * options; +}; diff --git a/radio/src/gui/colorlcd/layouts/sliders.cpp b/radio/src/gui/colorlcd/layouts/sliders.cpp new file mode 100644 index 000000000..08a9fcc8c --- /dev/null +++ b/radio/src/gui/colorlcd/layouts/sliders.cpp @@ -0,0 +1,76 @@ +/* + * 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 "sliders.h" +#include "opentx.h" + +void MainViewHorizontalSlider::paint(BitmapBuffer * dc) +{ + // The ticks + int delta = (width() - TRIM_SQUARE_SIZE) / SLIDER_TICKS_COUNT; + coord_t x = TRIM_SQUARE_SIZE / 2; + for (uint8_t i = 0; i <= SLIDER_TICKS_COUNT; i++) { + if (i == 0 || i == SLIDER_TICKS_COUNT / 2 || i == SLIDER_TICKS_COUNT) + dc->drawSolidVerticalLine(x, 2, 13, DEFAULT_COLOR); + else + dc->drawSolidVerticalLine(x, 4, 9, DEFAULT_COLOR); + x += delta; + } + + // The square + x = width() - TRIM_SQUARE_SIZE - divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX); + drawTrimSquare(dc, x, 0, TRIM_BGCOLOR); +} + +void MainView6POS::paint(BitmapBuffer * dc) +{ + // The ticks + int delta = (width() - TRIM_SQUARE_SIZE) / (XPOTS_MULTIPOS_COUNT - 1); + coord_t x = TRIM_SQUARE_SIZE / 2; + for (uint8_t i = 0; i <= XPOTS_MULTIPOS_COUNT; i++) { + dc->drawSolidVerticalLine(x, 4, 9, DEFAULT_COLOR); + x += delta; + } + + // The square + auto value = 1 + (potsPos[idx] & 0x0f); + x = TRIM_SQUARE_SIZE / 2 + divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value -1) , 6); + drawTrimSquare(dc, x, 0, TRIM_BGCOLOR); + dc->drawNumber(x + 1, 0, value, FOCUS_COLOR); +} + +void MainViewVerticalSlider::paint(BitmapBuffer * dc) +{ + uint8_t slidersTick = height() / 5; + // The ticks + int delta = (height() - TRIM_SQUARE_SIZE) / slidersTick; + coord_t y = TRIM_SQUARE_SIZE / 2; + for (uint8_t i = 0; i <= slidersTick; i++) { + if (i == 0 || i == slidersTick / 2 || i == slidersTick) + dc->drawSolidHorizontalLine(2, y, 13, DEFAULT_COLOR); + else + dc->drawSolidHorizontalLine(4, y, 9, DEFAULT_COLOR); + y += delta; + } + + // The square + y = height() - TRIM_SQUARE_SIZE - divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX); + drawTrimSquare(dc, 0, y, TRIM_BGCOLOR); +} diff --git a/radio/src/gui/colorlcd/layouts/sliders.h b/radio/src/gui/colorlcd/layouts/sliders.h index eae8b23bf..6043ef093 100644 --- a/radio/src/gui/colorlcd/layouts/sliders.h +++ b/radio/src/gui/colorlcd/layouts/sliders.h @@ -62,70 +62,19 @@ class MainViewHorizontalSlider : public MainViewSlider { public: using MainViewSlider::MainViewSlider; - - void paint(BitmapBuffer * dc) override - { - // The ticks - int delta = (width() - TRIM_SQUARE_SIZE) / SLIDER_TICKS_COUNT; - coord_t x = TRIM_SQUARE_SIZE / 2; - for (uint8_t i = 0; i <= SLIDER_TICKS_COUNT; i++) { - if (i == 0 || i == SLIDER_TICKS_COUNT / 2 || i == SLIDER_TICKS_COUNT) - dc->drawSolidVerticalLine(x, 2, 13, DEFAULT_COLOR); - else - dc->drawSolidVerticalLine(x, 4, 9, DEFAULT_COLOR); - x += delta; - } - - // The square - x = width() - TRIM_SQUARE_SIZE - divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX); - drawTrimSquare(dc, x, 0, TRIM_BGCOLOR); - } + void paint(BitmapBuffer * dc) override; }; class MainView6POS : public MainViewSlider { public: using MainViewSlider::MainViewSlider; - - void paint(BitmapBuffer * dc) override - { - // The ticks - int delta = (width() - TRIM_SQUARE_SIZE) / (XPOTS_MULTIPOS_COUNT - 1); - coord_t x = TRIM_SQUARE_SIZE / 2; - for (uint8_t i = 0; i <= XPOTS_MULTIPOS_COUNT; i++) { - dc->drawSolidVerticalLine(x, 4, 9, DEFAULT_COLOR); - x += delta; - } - - // The square - auto value = 1 + (potsPos[idx] & 0x0f); - x = TRIM_SQUARE_SIZE / 2 + divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value -1) , 6); - drawTrimSquare(dc, x, 0, TRIM_BGCOLOR); - dc->drawNumber(x + 1, 0, value, FOCUS_COLOR); - } + void paint(BitmapBuffer * dc) override; }; class MainViewVerticalSlider : public MainViewSlider { public: using MainViewSlider::MainViewSlider; - - void paint(BitmapBuffer * dc) override - { - uint8_t slidersTick = height() / 5; - // The ticks - int delta = (height() - TRIM_SQUARE_SIZE) / slidersTick; - coord_t y = TRIM_SQUARE_SIZE / 2; - for (uint8_t i = 0; i <= slidersTick; i++) { - if (i == 0 || i == slidersTick / 2 || i == slidersTick) - dc->drawSolidHorizontalLine(2, y, 13, DEFAULT_COLOR); - else - dc->drawSolidHorizontalLine(4, y, 9, DEFAULT_COLOR); - y += delta; - } - - // The square - y = height() - TRIM_SQUARE_SIZE - divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX); - drawTrimSquare(dc, 0, y, TRIM_BGCOLOR); - } + void paint(BitmapBuffer * dc) override; }; diff --git a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp new file mode 100644 index 000000000..39d0631a0 --- /dev/null +++ b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp @@ -0,0 +1,195 @@ +/* + * 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 "topbar_impl.h" +#include "opentx.h" + +const char * const STR_MONTHS[] = TR_MONTHS; +constexpr uint32_t TOPBAR_REFRESH = 1000 / 2; // 2 Hz + +TopbarImpl::TopbarImpl(Window * parent) : + WidgetsContainer({0, 0, LCD_W, MENU_HEADER_HEIGHT}, &g_model.topbarData) +{ + attach(parent); +} + +unsigned int TopbarImpl::getZonesCount() const +{ + return MAX_TOPBAR_ZONES; +} + +rect_t TopbarImpl::getZone(unsigned int index) const +{ + return { + coord_t(49 + (TOPBAR_ZONE_WIDTH + 2 * TOPBAR_ZONE_MARGIN) * index), + TOPBAR_ZONE_MARGIN, + TOPBAR_ZONE_WIDTH, + TOPBAR_HEIGHT + }; +} + +void TopbarImpl::setVisible(float visible) // 0.0 -> 1.0 +{ + if (visible == 0.0) { + setTop(-(int)MENU_HEADER_HEIGHT); + } + else if (visible == 1.0) { + setTop(0); + } + else if (visible > 0.0 && visible < 1.0){ + float top = - (float)MENU_HEADER_HEIGHT * (1.0 - visible); + setTop((coord_t)top); + } +} + +coord_t TopbarImpl::getVisibleHeight(float visible) const // 0.0 -> 1.0 +{ + if (visible == 0.0) { + return 0; + } + else if (visible == 1.0) { + return MENU_HEADER_HEIGHT; + } + + float h = (float)MENU_HEADER_HEIGHT * visible; + return (coord_t)h; +} + +void TopbarImpl::paint(BitmapBuffer * dc) +{ + dc->drawSolidFilledRect(0, 0, width(), height(), MENU_BGCOLOR); + OpenTxTheme::instance()->drawTopLeftBitmap(dc); + + struct gtm t; + gettime(&t); + char str[10]; + + sprintf(str, "%d %s", t.tm_mday, STR_MONTHS[t.tm_mon]); + dc->drawSolidVerticalLine(DATETIME_SEPARATOR_X, 7, 31, MENU_COLOR); + dc->drawText(DATETIME_MIDDLE, DATETIME_LINE1, str, FONT(XS) | CENTERED| MENU_COLOR); + + getTimerString(str, getValue(MIXSRC_TX_TIME)); + dc->drawText(DATETIME_MIDDLE, DATETIME_LINE2, str, FONT(XS) | CENTERED | MENU_COLOR); + + // USB icon + if (usbPlugged()) { + dc->drawBitmapPattern(LCD_W - 98, 8, LBM_TOPMENU_USB, MENU_COLOR); + } + + // Logs + if (isFunctionActive(FUNCTION_LOGS) && !usbPlugged() && BLINK_ON_PHASE) { + dc->drawBitmapPattern(LCD_W - 98, 6, LBM_DOT, MENU_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]; + dc->drawSolidFilledRect(LCD_W - 90 + i * 6, 38 - height, 4, height, TELEMETRY_RSSI() >= rssiBarsValue[i] ? MENU_COLOR : MENU_TITLE_DISABLE_COLOR); + } + +#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) + if (isModuleXJT(INTERNAL_MODULE) && isExternalAntennaEnabled()) { + dc->drawBitmapPattern(LCD_W-94, 4, LBM_TOPMENU_ANTENNA, MENU_COLOR); + } +#endif + + /* Audio volume */ + dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_SCALE, MENU_TITLE_DISABLE_COLOR); + if (requiredSpeakerVolume == 0 || g_eeGeneral.beepMode == e_mode_quiet) + dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_0, MENU_COLOR); + else if (requiredSpeakerVolume < 7) + dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_1, MENU_COLOR); + else if (requiredSpeakerVolume < 13) + dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_2, MENU_COLOR); + else if (requiredSpeakerVolume < 19) + dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_3, MENU_COLOR); + else + dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_4, MENU_COLOR); + + /* Tx battery */ + uint8_t bars = GET_TXBATT_BARS(5); +#if defined(USB_CHARGER) + if (usbChargerLed()) { + dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT_CHARGING, MENU_COLOR); + } + else { + dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_COLOR); + } +#else + dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_COLOR); +#endif + for (unsigned int i = 0; i < 5; i++) { + dc->drawSolidFilledRect(LCD_W - 128 + 4 * i, 30, 2, 8, i >= bars ? MENU_TITLE_DISABLE_COLOR : MENU_COLOR); + } + +#if 0 + // Radio battery - TODO + // drawValueWithUnit(370, 8, g_vbat100mV, UNIT_VOLTS, PREC1|FONT(XS)|MENU_COLOR); + // lcdDrawSolidRect(300, 3, 20, 50, MENU_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.voltsSource) { + TelemetryItem & item = telemetryItems[g_model.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 : DEFAULT_COLOR); + lcdDrawSolidFilledRect(ALTITUDE_X, VOLTS_Y, ALTITUDE_W, ALTITUDE_H, DEFAULT_BGCOLOR); + lcdDrawText(ALTITUDE_X+PADDING, VOLTS_Y+2, "Voltage", att); + drawValueWithUnit(ALTITUDE_X+PADDING, VOLTS_Y+12, value, UNIT_VOLTS, FONT(XL)|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 : DEFAULT_COLOR); + lcdDrawSolidFilledRect(ALTITUDE_X, ALTITUDE_Y, ALTITUDE_W, ALTITUDE_H, DEFAULT_BGCOLOR); + lcdDrawText(ALTITUDE_X+PADDING, ALTITUDE_Y+2, "Alt", att); + drawValueWithUnit(ALTITUDE_X+PADDING, ALTITUDE_Y+12, value, UNIT_METERS, FONT(XL)|LEFT|att); + } + } +#endif +} + +void TopbarImpl::checkEvents() +{ + uint32_t now = RTOS_GET_MS(); + if (now - lastRefresh >= TOPBAR_REFRESH) { + lastRefresh = now; + invalidate(); + } +} diff --git a/radio/src/gui/colorlcd/layouts/topbar_impl.h b/radio/src/gui/colorlcd/layouts/topbar_impl.h new file mode 100644 index 000000000..2fb2af95e --- /dev/null +++ b/radio/src/gui/colorlcd/layouts/topbar_impl.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#pragma once + +#include "topbar.h" +#include "widgets/widgets_container_implem.h" + +typedef WidgetsContainer TopbarImplBase; + +class TopbarImpl: + public TopbarImplBase, + public Topbar +{ + public: + explicit TopbarImpl(Window * parent); + +#if defined(DEBUG_WINDOWS) + std::string getName() const override + { + return "TopBar"; + } +#endif + + void load() override + { + TopbarImplBase::load(); + } + + unsigned int getZonesCount() const override; + + rect_t getZone(unsigned int index) const override; + + void setVisible(float visible); + coord_t getVisibleHeight(float visible) const; // 0.0 -> 1.0 + + void paint(BitmapBuffer * dc) override; + + void checkEvents() override; + + // Fake implementation to satisfy WidgetsContainerInterface + // this should probably be get rid of (might be tricky + const LayoutFactory * getFactory() const override + { + return nullptr; + } + + protected: + uint32_t lastRefresh = 0; +}; diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 111a74b4c..0faa8ab82 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -344,6 +344,8 @@ ScreenSetupPage::ScreenSetupPage(ScreenMenu * menu, unsigned pageIndex, unsigned { } + + static void updateLayoutOptions(FormGroup* optionsWindow, unsigned customScreenIndex) // TODO { FormGridLayout grid; @@ -354,7 +356,9 @@ static void updateLayoutOptions(FormGroup* optionsWindow, unsigned customScreenI auto factory = customScreens[customScreenIndex]->getFactory(); if (factory) { for (auto * option = factory->getOptions(); option->name; option++, index++) { - ZoneOptionValue * value = customScreens[customScreenIndex]->getOptionValue(index); + + auto layoutData = g_model.screenData[customScreenIndex].layoutData; + ZoneOptionValue * value = &layoutData.options[index].value; // Option label new StaticText(optionsWindow, grid.getLabelSlot(false), option->name); diff --git a/radio/src/gui/colorlcd/topbar.cpp b/radio/src/gui/colorlcd/topbar.cpp index 38b77befc..172f4f9cf 100644 --- a/radio/src/gui/colorlcd/topbar.cpp +++ b/radio/src/gui/colorlcd/topbar.cpp @@ -23,182 +23,15 @@ #include "view_main.h" #include "screen_setup.h" #include "storage/storage.h" +#include "topbar.h" +#include "topbar_impl.h" -constexpr uint32_t TOPBAR_REFRESH = 1000 / 2; // 2 Hz -TopBar::TopBar(Window * parent) : - WidgetsContainer({0, 0, LCD_W, MENU_HEADER_HEIGHT}, &g_model.topbarData) +Topbar * TopbarFactory::create(Window * parent) { - attach(parent); + return new TopbarImpl(parent); } -unsigned int TopBar::getZonesCount() const -{ - return MAX_TOPBAR_ZONES; -} - -rect_t TopBar::getZone(unsigned int index) const -{ - return { - coord_t(49 + (TOPBAR_ZONE_WIDTH + 2 * TOPBAR_ZONE_MARGIN) * index), - TOPBAR_ZONE_MARGIN, - TOPBAR_ZONE_WIDTH, - TOPBAR_HEIGHT - }; -} - -void TopBar::setVisible(float visible) // 0.0 -> 1.0 -{ - if (visible == 0.0) { - setTop(-(int)MENU_HEADER_HEIGHT); - } - else if (visible == 1.0) { - setTop(0); - } - else if (visible > 0.0 && visible < 1.0){ - float top = - (float)MENU_HEADER_HEIGHT * (1.0 - visible); - setTop((coord_t)top); - } -} - -coord_t TopBar::getVisibleHeight(float visible) const // 0.0 -> 1.0 -{ - if (visible == 0.0) { - return 0; - } - else if (visible == 1.0) { - return MENU_HEADER_HEIGHT; - } - - float h = (float)MENU_HEADER_HEIGHT * visible; - return (coord_t)h; -} - -const char * const STR_MONTHS[] = TR_MONTHS; - -void TopBar::paint(BitmapBuffer * dc) -{ - dc->drawSolidFilledRect(0, 0, width(), height(), MENU_BGCOLOR); - OpenTxTheme::instance()->drawTopLeftBitmap(dc); - - struct gtm t; - gettime(&t); - char str[10]; - - sprintf(str, "%d %s", t.tm_mday, STR_MONTHS[t.tm_mon]); - dc->drawSolidVerticalLine(DATETIME_SEPARATOR_X, 7, 31, MENU_COLOR); - dc->drawText(DATETIME_MIDDLE, DATETIME_LINE1, str, FONT(XS) | CENTERED| MENU_COLOR); - - getTimerString(str, getValue(MIXSRC_TX_TIME)); - dc->drawText(DATETIME_MIDDLE, DATETIME_LINE2, str, FONT(XS) | CENTERED | MENU_COLOR); - - // USB icon - if (usbPlugged()) { - dc->drawBitmapPattern(LCD_W - 98, 8, LBM_TOPMENU_USB, MENU_COLOR); - } - - // Logs - if (isFunctionActive(FUNCTION_LOGS) && !usbPlugged() && BLINK_ON_PHASE) { - dc->drawBitmapPattern(LCD_W - 98, 6, LBM_DOT, MENU_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]; - dc->drawSolidFilledRect(LCD_W - 90 + i * 6, 38 - height, 4, height, TELEMETRY_RSSI() >= rssiBarsValue[i] ? MENU_COLOR : MENU_TITLE_DISABLE_COLOR); - } - -#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA) - if (isModuleXJT(INTERNAL_MODULE) && isExternalAntennaEnabled()) { - dc->drawBitmapPattern(LCD_W-94, 4, LBM_TOPMENU_ANTENNA, MENU_COLOR); - } -#endif - - /* Audio volume */ - dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_SCALE, MENU_TITLE_DISABLE_COLOR); - if (requiredSpeakerVolume == 0 || g_eeGeneral.beepMode == e_mode_quiet) - dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_0, MENU_COLOR); - else if (requiredSpeakerVolume < 7) - dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_1, MENU_COLOR); - else if (requiredSpeakerVolume < 13) - dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_2, MENU_COLOR); - else if (requiredSpeakerVolume < 19) - dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_3, MENU_COLOR); - else - dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_4, MENU_COLOR); - - /* Tx battery */ - uint8_t bars = GET_TXBATT_BARS(5); -#if defined(USB_CHARGER) - if (usbChargerLed()) { - dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT_CHARGING, MENU_COLOR); - } - else { - dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_COLOR); - } -#else - dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_COLOR); -#endif - for (unsigned int i = 0; i < 5; i++) { - dc->drawSolidFilledRect(LCD_W - 128 + 4 * i, 30, 2, 8, i >= bars ? MENU_TITLE_DISABLE_COLOR : MENU_COLOR); - } - -#if 0 - // Radio battery - TODO - // drawValueWithUnit(370, 8, g_vbat100mV, UNIT_VOLTS, PREC1|FONT(XS)|MENU_COLOR); - // lcdDrawSolidRect(300, 3, 20, 50, MENU_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.voltsSource) { - TelemetryItem & item = telemetryItems[g_model.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 : DEFAULT_COLOR); - lcdDrawSolidFilledRect(ALTITUDE_X, VOLTS_Y, ALTITUDE_W, ALTITUDE_H, DEFAULT_BGCOLOR); - lcdDrawText(ALTITUDE_X+PADDING, VOLTS_Y+2, "Voltage", att); - drawValueWithUnit(ALTITUDE_X+PADDING, VOLTS_Y+12, value, UNIT_VOLTS, FONT(XL)|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 : DEFAULT_COLOR); - lcdDrawSolidFilledRect(ALTITUDE_X, ALTITUDE_Y, ALTITUDE_W, ALTITUDE_H, DEFAULT_BGCOLOR); - lcdDrawText(ALTITUDE_X+PADDING, ALTITUDE_Y+2, "Alt", att); - drawValueWithUnit(ALTITUDE_X+PADDING, ALTITUDE_Y+12, value, UNIT_METERS, FONT(XL)|LEFT|att); - } - } -#endif -} - -void TopBar::checkEvents() -{ - uint32_t now = RTOS_GET_MS(); - if (now - lastRefresh >= TOPBAR_REFRESH) { - lastRefresh = now; - invalidate(); - } -} - - SetupTopBarWidgetsPage::SetupTopBarWidgetsPage(ScreenMenu* menu): FormWindow(ViewMain::instance(), {0, 0, 0, 0}, FORM_FORWARD_FOCUS), menu(menu) @@ -218,7 +51,7 @@ SetupTopBarWidgetsPage::SetupTopBarWidgetsPage(ScreenMenu* menu): // adopt the dimensions of the main view setRect(viewMain->getRect()); - auto topbar = viewMain->getTopbar(); + auto topbar = dynamic_cast(viewMain->getTopbar()); for (unsigned i = 0; i < topbar->getZonesCount(); i++) { auto rect = topbar->getZone(i); auto widget = new SetupWidgetsPageSlot(this, rect, topbar, i); @@ -249,3 +82,4 @@ void SetupTopBarWidgetsPage::onEvent(event_t event) } } #endif + diff --git a/radio/src/gui/colorlcd/topbar.h b/radio/src/gui/colorlcd/topbar.h index 34679be65..d7b519b43 100644 --- a/radio/src/gui/colorlcd/topbar.h +++ b/radio/src/gui/colorlcd/topbar.h @@ -18,45 +18,28 @@ * GNU General Public License for more details. */ -#ifndef _TOPBAR_H_ -#define _TOPBAR_H_ +#pragma once -#include "widgets_container.h" +#include "layout.h" -#define MAX_TOPBAR_ZONES 4 -#define MAX_TOPBAR_OPTIONS 1 // just because of VC++ which doesn't like 0-size arrays :( -#define TOPBAR_ZONE_WIDTH 70 +constexpr coord_t TOPBAR_ZONE_WIDTH = 70; constexpr coord_t TOPBAR_ZONE_MARGIN = 3; constexpr coord_t TOPBAR_HEIGHT = MENU_HEADER_HEIGHT - 2 * TOPBAR_ZONE_MARGIN; -class TopBar: public WidgetsContainer +class ScreenMenu; +class TopbarImpl; + +class Topbar { public: - explicit TopBar(Window * parent); - -#if defined(DEBUG_WINDOWS) - std::string getName() const override - { - return "TopBar"; - } -#endif - - unsigned int getZonesCount() const override; - - rect_t getZone(unsigned int index) const override; - - void setVisible(float visible); - coord_t getVisibleHeight(float visible) const; // 0.0 -> 1.0 - - void paint(BitmapBuffer * dc) override; - - void checkEvents() override; - - protected: - uint32_t lastRefresh = 0; + virtual void load() = 0; }; -class ScreenMenu; +class TopbarFactory +{ +public: + static Topbar * create(Window * parent); +}; class SetupTopBarWidgetsPage: public FormWindow { @@ -80,5 +63,3 @@ class SetupTopBarWidgetsPage: public FormWindow ScreenMenu* menu; unsigned savedView = 0; }; - -#endif // _TOPBAR_H_ diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 18c9b4c7c..849294d8b 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -25,17 +25,16 @@ #include "model_select.h" #include "view_channels.h" #include "view_statistics.h" -#include "topbar.h" -#include "layouts/sliders.h" -#include "layouts/trims.h" -#include "view_main_decoration.h" +#include "topbar_impl.h" +#include "menu.h" + #include "opentx.h" ViewMain * ViewMain::_instance = nullptr; ViewMain::ViewMain(): Window(MainWindow::instance(), MainWindow::instance()->getRect()), - topbar(new TopBar(this)) + topbar(dynamic_cast(TopbarFactory::create(this))) { #if defined(HARDWARE_TOUCH) && !defined(HARDWARE_KEYS) new FabButton(this, 50, 100, ICON_MODEL, @@ -144,18 +143,33 @@ void ViewMain::previousMainView() setCurrentMainView(view); } +Topbar* ViewMain::getTopbar() +{ + return topbar; +} + +static bool hasTopbar(unsigned view) +{ + if (view < sizeof(g_model.screenData)) { + const auto& layoutData = g_model.screenData[view].layoutData; + return layoutData.options[LAYOUT_OPTION_TOPBAR].value.boolValue; + } + + return false; +} + void ViewMain::updateTopbarVisibility() { // relative to left visible page int leftScroll = getScrollPositionX() % pageWidth; if (leftScroll == 0) { - setTopbarVisible(customScreens[g_model.view]->hasTopbar()); + setTopbarVisible(hasTopbar(g_model.view)); customScreens[g_model.view]->decorate(); } else { int leftIdx = getScrollPositionX() / pageWidth; - bool leftTopbar = customScreens[leftIdx]->hasTopbar(); - bool rightTopbar = customScreens[leftIdx+1]->hasTopbar(); + bool leftTopbar = hasTopbar(leftIdx); + bool rightTopbar = hasTopbar(leftIdx+1); if (leftTopbar != rightTopbar) { diff --git a/radio/src/gui/colorlcd/view_main.h b/radio/src/gui/colorlcd/view_main.h index 20f5ba610..3b57f611d 100644 --- a/radio/src/gui/colorlcd/view_main.h +++ b/radio/src/gui/colorlcd/view_main.h @@ -21,10 +21,11 @@ #ifndef _VIEW_MAIN_H_ #define _VIEW_MAIN_H_ -#include "form.h" #include +#include "form.h" +#include "topbar.h" + -class TopBar; class SetupWidgetsPage; class SetupTopBarWidgetsPage; @@ -68,16 +69,13 @@ class ViewMain: public Window void nextMainView(); void previousMainView(); - TopBar* getTopbar() const - { - return topbar; - } + Topbar* getTopbar(); protected: static ViewMain * _instance; - unsigned views = 0; - TopBar* topbar = nullptr; + unsigned views = 0; + TopbarImpl* topbar = nullptr; // Widget setup requires special permissions ;-) friend class SetupWidgetsPage; diff --git a/radio/src/gui/colorlcd/widget.cpp b/radio/src/gui/colorlcd/widget.cpp index a99a0f477..a9c9a1647 100644 --- a/radio/src/gui/colorlcd/widget.cpp +++ b/radio/src/gui/colorlcd/widget.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "widget.h" std::list & getRegisteredWidgets() { @@ -34,7 +35,7 @@ void registerWidget(const WidgetFactory * factory) const WidgetFactory * getWidgetFactory(const char * name) { - std::list::const_iterator it = getRegisteredWidgets().cbegin(); + auto it = getRegisteredWidgets().cbegin(); for (; it != getRegisteredWidgets().cend();++it) { if (!strcmp(name, (*it)->getName())) { return (*it); @@ -43,7 +44,7 @@ const WidgetFactory * getWidgetFactory(const char * name) return nullptr; } -Widget * loadWidget(const char * name, FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData) +Widget * loadWidget(const char * name, FormGroup * parent, const rect_t & rect, WidgetPersistentData * persistentData) { const WidgetFactory * factory = getWidgetFactory(name); if (factory) { diff --git a/radio/src/gui/colorlcd/widget.h b/radio/src/gui/colorlcd/widget.h index c7e3c25a2..c7099d3be 100644 --- a/radio/src/gui/colorlcd/widget.h +++ b/radio/src/gui/colorlcd/widget.h @@ -23,25 +23,23 @@ #include #include #include "form.h" -#include "zone.h" +#include "widgets_container.h" #include "debug.h" -#define MAX_WIDGET_OPTIONS 5 - // YAML_GENERATOR defs #if !defined(USE_IDX) #define USE_IDX #endif class WidgetFactory; + class Widget : public Window { public: - struct PersistentData { - ZoneOptionValueTyped options[MAX_WIDGET_OPTIONS] USE_IDX; - }; - Widget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, PersistentData * persistentData): + typedef WidgetPersistentData PersistentData; + + Widget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, WidgetPersistentData * persistentData): Window(parent, rect), factory(factory), persistentData(persistentData) diff --git a/radio/src/gui/colorlcd/widgets/gauge.cpp b/radio/src/gui/colorlcd/widgets/gauge.cpp index f69978467..f5576bd8f 100644 --- a/radio/src/gui/colorlcd/widgets/gauge.cpp +++ b/radio/src/gui/colorlcd/widgets/gauge.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "widgets_container_implem.h" class GaugeWidget: public Widget { diff --git a/radio/src/gui/colorlcd/widgets/modelbmp.cpp b/radio/src/gui/colorlcd/widgets/modelbmp.cpp index fbcffd95c..39826b012 100644 --- a/radio/src/gui/colorlcd/widgets/modelbmp.cpp +++ b/radio/src/gui/colorlcd/widgets/modelbmp.cpp @@ -19,6 +19,8 @@ */ #include "opentx.h" +#include "widgets_container_implem.h" + #include class ModelBitmapWidget: public Widget diff --git a/radio/src/gui/colorlcd/widgets/outputs.cpp b/radio/src/gui/colorlcd/widgets/outputs.cpp index a6693902d..e665aecae 100644 --- a/radio/src/gui/colorlcd/widgets/outputs.cpp +++ b/radio/src/gui/colorlcd/widgets/outputs.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "widgets_container_implem.h" #define RECT_BORDER 1 #define ROW_HEIGHT 17 diff --git a/radio/src/gui/colorlcd/widgets/text.cpp b/radio/src/gui/colorlcd/widgets/text.cpp index 7fecda88a..a97eab9e9 100644 --- a/radio/src/gui/colorlcd/widgets/text.cpp +++ b/radio/src/gui/colorlcd/widgets/text.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "widgets_container_implem.h" #define TEXT_WIDGET_DEFAULT_LABEL 'M', 'y', ' ', 'L', 'a', 'b', 'e', 'l' // "My Label" diff --git a/radio/src/gui/colorlcd/widgets/timer.cpp b/radio/src/gui/colorlcd/widgets/timer.cpp index ffc0f850e..e7a4c5e0e 100644 --- a/radio/src/gui/colorlcd/widgets/timer.cpp +++ b/radio/src/gui/colorlcd/widgets/timer.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "widgets_container_implem.h" class TimerWidget: public Widget { diff --git a/radio/src/gui/colorlcd/widgets/value.cpp b/radio/src/gui/colorlcd/widgets/value.cpp index 99312d125..42921ac23 100644 --- a/radio/src/gui/colorlcd/widgets/value.cpp +++ b/radio/src/gui/colorlcd/widgets/value.cpp @@ -19,6 +19,7 @@ */ #include "opentx.h" +#include "widgets_container_implem.h" const coord_t NUMBERS_PADDING = 4; diff --git a/radio/src/gui/colorlcd/widgets/widgets_container_implem.h b/radio/src/gui/colorlcd/widgets/widgets_container_implem.h new file mode 100644 index 000000000..e0592227b --- /dev/null +++ b/radio/src/gui/colorlcd/widgets/widgets_container_implem.h @@ -0,0 +1,156 @@ +/* + * 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. + */ + +#pragma once + +#include "widget.h" +#include "widgets_container.h" + +template +class WidgetsContainer: public WidgetsContainerInterface +{ + public: + // struct ZonePersistentData { + // char widgetName[WIDGET_NAME_LEN]; + // Widget::PersistentData widgetData; + // }; + + // struct PersistentData { + // ZonePersistentData zones[N]; + // ZoneOptionValueTyped options[O]; + // }; + typedef WidgetsContainerPersistentData PersistentData; + + WidgetsContainer(const rect_t & rect, PersistentData * persistentData): + WidgetsContainerInterface(nullptr, rect, FORM_FORWARD_FOCUS), + persistentData(persistentData) + { + } + + Widget * createWidget(unsigned int index, const WidgetFactory * factory) override + { + if (index >= N) + return nullptr; + + // remove old one if existing + removeWidget(index); + + Widget * widget = nullptr; + if (factory) { + strncpy(persistentData->zones[index].widgetName, factory->getName(), sizeof(ZonePersistentData::widgetName)); + widget = factory->create(this, getZone(index), &persistentData->zones[index].widgetData); + } + widgets[index] = widget; + + if (widget) + widget->attach(this); + + return widget; + } + + void removeWidget(unsigned int index) override + { + if (index >= N) + return; + + if (widgets[index]) + widgets[index]->deleteLater(); + + widgets[index] = nullptr; + memset(persistentData->zones[index].widgetName, 0, sizeof(ZonePersistentData::widgetName)); + memset(&persistentData->zones[index].widgetData, 0, sizeof(Widget::PersistentData)); + } + + Widget * getWidget(unsigned int index) override + { + if (index < N) + return widgets[index]; + + return nullptr; + } + + virtual void create() + { + memset(persistentData, 0, sizeof(PersistentData)); + } + + virtual void load() + { + unsigned int count = getZonesCount(); + for (unsigned int i = 0; i < count; i++) { + + // remove old widget + if (widgets[i]) { + widgets[i]->deleteLater(); + widgets[i] = nullptr; + } + + // and load new one if required + if (persistentData->zones[i].widgetName[0]) { + char name[WIDGET_NAME_LEN + 1]; + memset(name, 0, sizeof(name)); + strncpy(name, persistentData->zones[i].widgetName, WIDGET_NAME_LEN); + widgets[i] = loadWidget(name, this, getZone(i), &persistentData->zones[i].widgetData); + } + } + } + + inline ZoneOptionValue * getOptionValue(unsigned int index) const + { + return &persistentData->options[index].value; + } + + inline void setOptionValue(unsigned int index, const ZoneOptionValue& value) + { + persistentData->options[index].value = value; + } + + unsigned int getZonesCount() const override = 0; + + rect_t getZone(unsigned int index) const override = 0; + + virtual void background() + { + for (int i = 0; i < N; i++) { + if (widgets[i]) { + widgets[i]->background(); + } + } + } + + void updateZones() + { + for (int i = 0; i < N; i++) { + if (widgets[i]) { + auto zone = getZone(i); + widgets[i]->setRect(zone); + widgets[i]->setInnerHeight(zone.h); + } + } + } + + void decorate() override + { + } + + protected: + PersistentData * persistentData; + Widget * widgets[N] = {}; +}; diff --git a/radio/src/gui/colorlcd/widgets_container.h b/radio/src/gui/colorlcd/widgets_container.h index 6276aeeb3..7ba7e1219 100644 --- a/radio/src/gui/colorlcd/widgets_container.h +++ b/radio/src/gui/colorlcd/widgets_container.h @@ -22,146 +22,63 @@ #define _WIDGETS_CONTAINER_H_ #include -#include -#include "widget.h" +#include "libopenui_types.h" +#include "form.h" +#include "zone.h" -class WidgetsContainerInterface +#define WIDGET_NAME_LEN 10 +#define MAX_WIDGET_OPTIONS 5 // Name? + +#define MAX_TOPBAR_ZONES 4 +#define MAX_TOPBAR_OPTIONS 1 // just because of VC++ which doesn't like 0-size arrays :( + +// Common 'ZoneOptionValue's among all layouts +enum { + LAYOUT_OPTION_TOPBAR = 0, + LAYOUT_OPTION_FM, + LAYOUT_OPTION_SLIDERS, + LAYOUT_OPTION_TRIMS, + LAYOUT_OPTION_MIRRORED, + + LAYOUT_OPTION_LAST_DEFAULT=LAYOUT_OPTION_MIRRORED +}; + +class Widget; +class WidgetFactory; +class LayoutFactory; + +struct WidgetPersistentData { + ZoneOptionValueTyped options[MAX_WIDGET_OPTIONS] USE_IDX; +}; + +struct ZonePersistentData { + char widgetName[WIDGET_NAME_LEN]; + WidgetPersistentData widgetData; +}; + +template +struct WidgetsContainerPersistentData { + ZonePersistentData zones[N]; + ZoneOptionValueTyped options[O]; +}; + +typedef WidgetsContainerPersistentData TopBarPersistentData; + +class WidgetsContainerInterface: public FormGroup { public: + using FormGroup::FormGroup; + virtual unsigned int getZonesCount() const = 0; virtual rect_t getZone(unsigned int index) const = 0; virtual Widget * createWidget(unsigned int index, const WidgetFactory * factory) = 0; virtual Widget * getWidget(unsigned int index) = 0; virtual void removeWidget(unsigned int index) = 0; + + // this should go away... + virtual const LayoutFactory * getFactory() const = 0; + virtual void decorate() = 0; }; -#define WIDGET_NAME_LEN 10 - -template -class WidgetsContainer: public FormGroup, public WidgetsContainerInterface -{ - public: - struct ZonePersistentData { - char widgetName[WIDGET_NAME_LEN]; - Widget::PersistentData widgetData; - }; - - struct PersistentData { - ZonePersistentData zones[N]; - ZoneOptionValueTyped options[O]; - }; - - WidgetsContainer(const rect_t & rect, PersistentData * persistentData): - FormGroup(nullptr, rect, FORM_FORWARD_FOCUS), - persistentData(persistentData) - { - } - - Widget * createWidget(unsigned int index, const WidgetFactory * factory) override - { - if (index >= N) - return nullptr; - - // remove old one if existing - removeWidget(index); - - Widget * widget = nullptr; - if (factory) { - strncpy(persistentData->zones[index].widgetName, factory->getName(), sizeof(ZonePersistentData::widgetName)); - widget = factory->create(this, getZone(index), &persistentData->zones[index].widgetData); - } - widgets[index] = widget; - - if (widget) - widget->attach(this); - - return widget; - } - - void removeWidget(unsigned int index) override - { - if (index >= N) - return; - - if (widgets[index]) - widgets[index]->deleteLater(); - - widgets[index] = nullptr; - memset(persistentData->zones[index].widgetName, 0, sizeof(ZonePersistentData::widgetName)); - memset(&persistentData->zones[index].widgetData, 0, sizeof(Widget::PersistentData)); - } - - Widget * getWidget(unsigned int index) override - { - if (index < N) - return widgets[index]; - - return nullptr; - } - - virtual void create() - { - memset(persistentData, 0, sizeof(PersistentData)); - } - - virtual void load() - { - unsigned int count = getZonesCount(); - for (unsigned int i = 0; i < count; i++) { - - // remove old widget - if (widgets[i]) { - widgets[i]->deleteLater(); - widgets[i] = nullptr; - } - - // and load new one if required - if (persistentData->zones[i].widgetName[0]) { - char name[WIDGET_NAME_LEN + 1]; - memset(name, 0, sizeof(name)); - strncpy(name, persistentData->zones[i].widgetName, WIDGET_NAME_LEN); - widgets[i] = loadWidget(name, this, getZone(i), &persistentData->zones[i].widgetData); - } - } - } - - inline ZoneOptionValue * getOptionValue(unsigned int index) const - { - return &persistentData->options[index].value; - } - - inline void setOptionValue(unsigned int index, const ZoneOptionValue& value) - { - persistentData->options[index].value = value; - } - - unsigned int getZonesCount() const override = 0; - - rect_t getZone(unsigned int index) const override = 0; - - virtual void background() - { - for (int i = 0; i < N; i++) { - if (widgets[i]) { - widgets[i]->background(); - } - } - } - - void updateZones() - { - for (int i = 0; i < N; i++) { - if (widgets[i]) { - auto zone = getZone(i); - widgets[i]->setRect(zone); - widgets[i]->setInnerHeight(zone.h); - } - } - } - - protected: - PersistentData * persistentData; - Widget * widgets[N] = {}; -}; #endif // _WIDGETS_CONTAINER_H_ diff --git a/radio/src/storage/conversions/datastructs_218.h b/radio/src/storage/conversions/datastructs_218.h index e21816d40..6a7638feb 100644 --- a/radio/src/storage/conversions/datastructs_218.h +++ b/radio/src/storage/conversions/datastructs_218.h @@ -398,11 +398,11 @@ PACK(struct TelemetrySensor_218 { #if defined(PCBHORUS) PACK(struct CustomScreenData_v218 { char LayoutId[10]; - Layout::PersistentData layoutData; + LayoutPersistentData layoutData; }); #define VIEW_DATA \ CustomScreenData screenData[MAX_CUSTOM_SCREENS]; \ - TopBar::PersistentData topbarData; \ + TopBarPersistentData topbarData; \ uint8_t view; #elif defined(PCBTARANIS) #define VIEW_DATA uint8_t view; From f8029584d8b047376fee73c7c4b463111649c4c9 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Apr 2021 07:25:22 +0200 Subject: [PATCH 41/54] renamed template implementation files to "_impl" instead of "_implem" --- radio/src/gui/colorlcd/layouts/layout1x1.cpp | 2 +- radio/src/gui/colorlcd/layouts/layout2+1.cpp | 2 +- radio/src/gui/colorlcd/layouts/layout2x1.cpp | 2 +- radio/src/gui/colorlcd/layouts/layout2x2.cpp | 2 +- radio/src/gui/colorlcd/layouts/layout2x4.cpp | 2 +- .../{layout_factory_implem.cpp => layout_factory_impl.cpp} | 2 +- .../{layout_factory_implem.h => layout_factory_impl.h} | 5 +---- radio/src/gui/colorlcd/layouts/topbar_impl.h | 2 +- radio/src/gui/colorlcd/widgets/gauge.cpp | 2 +- radio/src/gui/colorlcd/widgets/modelbmp.cpp | 2 +- radio/src/gui/colorlcd/widgets/outputs.cpp | 2 +- radio/src/gui/colorlcd/widgets/text.cpp | 2 +- radio/src/gui/colorlcd/widgets/timer.cpp | 2 +- radio/src/gui/colorlcd/widgets/value.cpp | 2 +- .../{widgets_container_implem.h => widgets_container_impl.h} | 0 15 files changed, 14 insertions(+), 17 deletions(-) rename radio/src/gui/colorlcd/layouts/{layout_factory_implem.cpp => layout_factory_impl.cpp} (98%) rename radio/src/gui/colorlcd/layouts/{layout_factory_implem.h => layout_factory_impl.h} (97%) rename radio/src/gui/colorlcd/widgets/{widgets_container_implem.h => widgets_container_impl.h} (100%) diff --git a/radio/src/gui/colorlcd/layouts/layout1x1.cpp b/radio/src/gui/colorlcd/layouts/layout1x1.cpp index 96296388f..3d469ecc7 100644 --- a/radio/src/gui/colorlcd/layouts/layout1x1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout1x1.cpp @@ -19,7 +19,7 @@ */ #include "layout.h" -#include "layout_factory_implem.h" +#include "layout_factory_impl.h" const uint8_t LBM_LAYOUT_1x1[] = { #include "mask_layout1x1.lbm" diff --git a/radio/src/gui/colorlcd/layouts/layout2+1.cpp b/radio/src/gui/colorlcd/layouts/layout2+1.cpp index 3977ecbdd..6f8d5eb6e 100644 --- a/radio/src/gui/colorlcd/layouts/layout2+1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2+1.cpp @@ -19,7 +19,7 @@ */ #include "layout.h" -#include "layout_factory_implem.h" +#include "layout_factory_impl.h" const uint8_t LBM_LAYOUT_2P1[] = { #include "mask_layout2+1.lbm" diff --git a/radio/src/gui/colorlcd/layouts/layout2x1.cpp b/radio/src/gui/colorlcd/layouts/layout2x1.cpp index db38eaba3..b514662fc 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x1.cpp @@ -19,7 +19,7 @@ */ #include "layout.h" -#include "layout_factory_implem.h" +#include "layout_factory_impl.h" const uint8_t LBM_LAYOUT_2x1[] = { #include "mask_layout2x1.lbm" diff --git a/radio/src/gui/colorlcd/layouts/layout2x2.cpp b/radio/src/gui/colorlcd/layouts/layout2x2.cpp index 8b48adc46..174190cbf 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x2.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x2.cpp @@ -19,7 +19,7 @@ */ #include "layout.h" -#include "layout_factory_implem.h" +#include "layout_factory_impl.h" const uint8_t LBM_LAYOUT_2x2[] = { #include "mask_layout2x2.lbm" diff --git a/radio/src/gui/colorlcd/layouts/layout2x4.cpp b/radio/src/gui/colorlcd/layouts/layout2x4.cpp index 4b01e3ae2..b88c97095 100644 --- a/radio/src/gui/colorlcd/layouts/layout2x4.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2x4.cpp @@ -19,7 +19,7 @@ */ #include "layout.h" -#include "layout_factory_implem.h" +#include "layout_factory_impl.h" const uint8_t LBM_LAYOUT_2x4[] = { #include "mask_layout2x4.lbm" diff --git a/radio/src/gui/colorlcd/layouts/layout_factory_implem.cpp b/radio/src/gui/colorlcd/layouts/layout_factory_impl.cpp similarity index 98% rename from radio/src/gui/colorlcd/layouts/layout_factory_implem.cpp rename to radio/src/gui/colorlcd/layouts/layout_factory_impl.cpp index c173f2524..f9440b443 100644 --- a/radio/src/gui/colorlcd/layouts/layout_factory_implem.cpp +++ b/radio/src/gui/colorlcd/layouts/layout_factory_impl.cpp @@ -18,7 +18,7 @@ * GNU General Public License for more details. */ -#include "layout_factory_implem.h" +#include "layout_factory_impl.h" #include "layouts/trims.h" #include "layouts/sliders.h" #include "view_main_decoration.h" diff --git a/radio/src/gui/colorlcd/layouts/layout_factory_implem.h b/radio/src/gui/colorlcd/layouts/layout_factory_impl.h similarity index 97% rename from radio/src/gui/colorlcd/layouts/layout_factory_implem.h rename to radio/src/gui/colorlcd/layouts/layout_factory_impl.h index 95a34c7f4..a70562804 100644 --- a/radio/src/gui/colorlcd/layouts/layout_factory_implem.h +++ b/radio/src/gui/colorlcd/layouts/layout_factory_impl.h @@ -22,14 +22,11 @@ #include -//#include "lcd.h" -//#include "topbar.h" - #include "audio.h" #include "translations.h" #include "layout.h" -#include "widgets/widgets_container_implem.h" +#include "widgets/widgets_container_impl.h" #define LAYOUT_COMMON_OPTIONS \ { STR_TOP_BAR, ZoneOption::Bool }, \ diff --git a/radio/src/gui/colorlcd/layouts/topbar_impl.h b/radio/src/gui/colorlcd/layouts/topbar_impl.h index 2fb2af95e..8147aa151 100644 --- a/radio/src/gui/colorlcd/layouts/topbar_impl.h +++ b/radio/src/gui/colorlcd/layouts/topbar_impl.h @@ -21,7 +21,7 @@ #pragma once #include "topbar.h" -#include "widgets/widgets_container_implem.h" +#include "layouts/layout_factory_impl.h" typedef WidgetsContainer TopbarImplBase; diff --git a/radio/src/gui/colorlcd/widgets/gauge.cpp b/radio/src/gui/colorlcd/widgets/gauge.cpp index f5576bd8f..3f01aa6f3 100644 --- a/radio/src/gui/colorlcd/widgets/gauge.cpp +++ b/radio/src/gui/colorlcd/widgets/gauge.cpp @@ -19,7 +19,7 @@ */ #include "opentx.h" -#include "widgets_container_implem.h" +#include "widgets_container_impl.h" class GaugeWidget: public Widget { diff --git a/radio/src/gui/colorlcd/widgets/modelbmp.cpp b/radio/src/gui/colorlcd/widgets/modelbmp.cpp index 39826b012..e6f67dbbd 100644 --- a/radio/src/gui/colorlcd/widgets/modelbmp.cpp +++ b/radio/src/gui/colorlcd/widgets/modelbmp.cpp @@ -19,7 +19,7 @@ */ #include "opentx.h" -#include "widgets_container_implem.h" +#include "widgets_container_impl.h" #include diff --git a/radio/src/gui/colorlcd/widgets/outputs.cpp b/radio/src/gui/colorlcd/widgets/outputs.cpp index e665aecae..8f3f11e42 100644 --- a/radio/src/gui/colorlcd/widgets/outputs.cpp +++ b/radio/src/gui/colorlcd/widgets/outputs.cpp @@ -19,7 +19,7 @@ */ #include "opentx.h" -#include "widgets_container_implem.h" +#include "widgets_container_impl.h" #define RECT_BORDER 1 #define ROW_HEIGHT 17 diff --git a/radio/src/gui/colorlcd/widgets/text.cpp b/radio/src/gui/colorlcd/widgets/text.cpp index a97eab9e9..9605d6035 100644 --- a/radio/src/gui/colorlcd/widgets/text.cpp +++ b/radio/src/gui/colorlcd/widgets/text.cpp @@ -19,7 +19,7 @@ */ #include "opentx.h" -#include "widgets_container_implem.h" +#include "widgets_container_impl.h" #define TEXT_WIDGET_DEFAULT_LABEL 'M', 'y', ' ', 'L', 'a', 'b', 'e', 'l' // "My Label" diff --git a/radio/src/gui/colorlcd/widgets/timer.cpp b/radio/src/gui/colorlcd/widgets/timer.cpp index e7a4c5e0e..45336252d 100644 --- a/radio/src/gui/colorlcd/widgets/timer.cpp +++ b/radio/src/gui/colorlcd/widgets/timer.cpp @@ -19,7 +19,7 @@ */ #include "opentx.h" -#include "widgets_container_implem.h" +#include "widgets_container_impl.h" class TimerWidget: public Widget { diff --git a/radio/src/gui/colorlcd/widgets/value.cpp b/radio/src/gui/colorlcd/widgets/value.cpp index 42921ac23..f36dde97f 100644 --- a/radio/src/gui/colorlcd/widgets/value.cpp +++ b/radio/src/gui/colorlcd/widgets/value.cpp @@ -19,7 +19,7 @@ */ #include "opentx.h" -#include "widgets_container_implem.h" +#include "widgets_container_impl.h" const coord_t NUMBERS_PADDING = 4; diff --git a/radio/src/gui/colorlcd/widgets/widgets_container_implem.h b/radio/src/gui/colorlcd/widgets/widgets_container_impl.h similarity index 100% rename from radio/src/gui/colorlcd/widgets/widgets_container_implem.h rename to radio/src/gui/colorlcd/widgets/widgets_container_impl.h From 0ca9e773b26ef2f1863c5812a34ab0808f294a05 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Apr 2021 07:55:48 +0200 Subject: [PATCH 42/54] Refined WidgetsContainer interface and some names --- radio/src/gui/colorlcd/gui.h | 2 +- radio/src/gui/colorlcd/layout.cpp | 6 +- radio/src/gui/colorlcd/layout.h | 8 +-- .../colorlcd/layouts/layout_factory_impl.cpp | 13 ++-- .../colorlcd/layouts/layout_factory_impl.h | 9 +-- .../src/gui/colorlcd/layouts/topbar_impl.cpp | 2 +- radio/src/gui/colorlcd/layouts/topbar_impl.h | 9 +-- radio/src/gui/colorlcd/screen_setup.cpp | 66 +++++++++++-------- radio/src/gui/colorlcd/screen_setup.h | 2 +- radio/src/gui/colorlcd/view_main.cpp | 6 +- .../colorlcd/widgets/widgets_container_impl.h | 17 ++--- radio/src/gui/colorlcd/widgets_container.h | 7 +- 12 files changed, 66 insertions(+), 81 deletions(-) diff --git a/radio/src/gui/colorlcd/gui.h b/radio/src/gui/colorlcd/gui.h index 4b38183cc..f99867164 100644 --- a/radio/src/gui/colorlcd/gui.h +++ b/radio/src/gui/colorlcd/gui.h @@ -47,7 +47,7 @@ void drawCurveHorizontalScale(); void drawCurveCoord(int x, int y, const char * text, bool active=false); void drawCurvePoint(int x, int y, LcdFlags color); -extern WidgetsContainerInterface * customScreens[MAX_CUSTOM_SCREENS]; +extern WidgetsContainer * customScreens[MAX_CUSTOM_SCREENS]; void drawAlertBox(const char * title, const char * text, const char * action); void showAlertBox(const char * title, const char * text, const char * action, uint8_t sound); diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index a9441b309..6e64c7222 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -21,7 +21,7 @@ #include "opentx.h" #include "view_main.h" -WidgetsContainerInterface * customScreens[MAX_CUSTOM_SCREENS] = {}; +WidgetsContainer * customScreens[MAX_CUSTOM_SCREENS] = {}; std::list & getRegisteredLayouts() { @@ -49,7 +49,7 @@ const LayoutFactory * getLayoutFactory(const char * name) // // Loads a layout, but does not attach it to any window // -WidgetsContainerInterface * +WidgetsContainer * loadLayout(const char * name, LayoutPersistentData * persistentData) { const LayoutFactory * factory = getLayoutFactory(name); @@ -137,7 +137,7 @@ void loadCustomScreens() // - new screen is configured into g_model // - the new screen is returned (not attached) // -WidgetsContainerInterface * +WidgetsContainer * createCustomScreen(const LayoutFactory* factory, unsigned customScreenIndex) { if (!factory || (customScreenIndex >= MAX_CUSTOM_SCREENS)) diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index 54d9d1b58..f611dc034 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -42,15 +42,15 @@ class LayoutFactory const char * getName() const { return name; } virtual void drawThumb(BitmapBuffer * dc, uint16_t x, uint16_t y, LcdFlags flags) const = 0; virtual const ZoneOption * getOptions() const = 0; - virtual WidgetsContainerInterface * create(LayoutPersistentData * persistentData) const = 0; - virtual WidgetsContainerInterface * load(LayoutPersistentData * persistentData) const = 0; + virtual WidgetsContainer * create(LayoutPersistentData * persistentData) const = 0; + virtual WidgetsContainer * load(LayoutPersistentData * persistentData) const = 0; protected: const char * id; const char * name; }; -WidgetsContainerInterface * loadLayout(const char * name, LayoutPersistentData * persistentData); +WidgetsContainer * loadLayout(const char * name, LayoutPersistentData * persistentData); // intented for new models void loadDefaultLayout(); @@ -61,7 +61,7 @@ void loadCustomScreens(); // delete all custom screens from memory void deleteCustomScreens(); -WidgetsContainerInterface * +WidgetsContainer * createCustomScreen(const LayoutFactory* factory, unsigned customScreenIndex); // Remove custom screen from the model diff --git a/radio/src/gui/colorlcd/layouts/layout_factory_impl.cpp b/radio/src/gui/colorlcd/layouts/layout_factory_impl.cpp index f9440b443..c3a93ca1b 100644 --- a/radio/src/gui/colorlcd/layouts/layout_factory_impl.cpp +++ b/radio/src/gui/colorlcd/layouts/layout_factory_impl.cpp @@ -29,7 +29,7 @@ Layout::Layout(const LayoutFactory * factory, PersistentData * persistentData): factory(factory), decoration(new ViewMainDecoration(this, getRect())) { - decorate(); + adjustLayout(); } void Layout::create() @@ -54,7 +54,7 @@ void Layout::paint(BitmapBuffer * dc) void Layout::checkEvents() { LayoutBase::checkEvents(); - decorate(); + adjustLayout(); uint32_t now = RTOS_GET_MS(); if (now - lastRefresh >= LAYOUT_REFRESH) { @@ -82,12 +82,7 @@ void Layout::setFlightModeVisible(bool visible) decoration->setFlightModeVisible(visible); } -void Layout::adjustDecoration() -{ - decoration->adjustDecoration(); -} - -void Layout::decorate() +void Layout::adjustLayout() { // Check if deco setting are still up-to-date uint8_t checkSettings = @@ -110,7 +105,7 @@ void Layout::decorate() setFlightModeVisible(hasFlightMode()); // Re-compute positions - adjustDecoration(); + decoration->adjustDecoration(); // and update relevant windows updateZones(); diff --git a/radio/src/gui/colorlcd/layouts/layout_factory_impl.h b/radio/src/gui/colorlcd/layouts/layout_factory_impl.h index a70562804..e858aee51 100644 --- a/radio/src/gui/colorlcd/layouts/layout_factory_impl.h +++ b/radio/src/gui/colorlcd/layouts/layout_factory_impl.h @@ -40,7 +40,7 @@ class ViewMainDecoration; -typedef WidgetsContainer LayoutBase; +typedef WidgetsContainerImpl LayoutBase; class Layout: public LayoutBase { @@ -61,7 +61,7 @@ class Layout: public LayoutBase void create() override; - const LayoutFactory * getFactory() const override + const LayoutFactory * getFactory() const { return factory; } @@ -93,11 +93,8 @@ class Layout: public LayoutBase void setSlidersVisible(bool visible); void setFlightModeVisible(bool visible); - // Re-calculate positions - void adjustDecoration(); - // Updates settings for trims, sliders, pots, etc... - void decorate() override; + void adjustLayout() override; protected: const LayoutFactory * factory = nullptr; diff --git a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp index 39d0631a0..14fe2cdb6 100644 --- a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp +++ b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp @@ -25,7 +25,7 @@ const char * const STR_MONTHS[] = TR_MONTHS; constexpr uint32_t TOPBAR_REFRESH = 1000 / 2; // 2 Hz TopbarImpl::TopbarImpl(Window * parent) : - WidgetsContainer({0, 0, LCD_W, MENU_HEADER_HEIGHT}, &g_model.topbarData) + TopbarImplBase({0, 0, LCD_W, MENU_HEADER_HEIGHT}, &g_model.topbarData) { attach(parent); } diff --git a/radio/src/gui/colorlcd/layouts/topbar_impl.h b/radio/src/gui/colorlcd/layouts/topbar_impl.h index 8147aa151..3315e8b3f 100644 --- a/radio/src/gui/colorlcd/layouts/topbar_impl.h +++ b/radio/src/gui/colorlcd/layouts/topbar_impl.h @@ -23,7 +23,7 @@ #include "topbar.h" #include "layouts/layout_factory_impl.h" -typedef WidgetsContainer TopbarImplBase; +typedef WidgetsContainerImpl TopbarImplBase; class TopbarImpl: public TopbarImplBase, @@ -54,13 +54,6 @@ class TopbarImpl: void paint(BitmapBuffer * dc) override; void checkEvents() override; - - // Fake implementation to satisfy WidgetsContainerInterface - // this should probably be get rid of (might be tricky - const LayoutFactory * getFactory() const override - { - return nullptr; - } protected: uint32_t lastRefresh = 0; diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 0faa8ab82..77bc9ef68 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -25,6 +25,7 @@ #include "widget_settings.h" #include "topbar.h" #include "libopenui.h" +#include "layouts/layout_factory_impl.h" #define SET_DIRTY() storageDirty(EE_MODEL) @@ -108,7 +109,7 @@ class LayoutChoice: public FormField std::function setValue; }; -SetupWidgetsPageSlot::SetupWidgetsPageSlot(FormGroup * parent, const rect_t & rect, WidgetsContainerInterface* container, uint8_t slotIndex): +SetupWidgetsPageSlot::SetupWidgetsPageSlot(FormGroup * parent, const rect_t & rect, WidgetsContainer* container, uint8_t slotIndex): Button(parent, rect) { setPressHandler([parent, container, slotIndex]() -> uint8_t { @@ -353,32 +354,39 @@ static void updateLayoutOptions(FormGroup* optionsWindow, unsigned customScreenI // Layout options... int index = 0; - auto factory = customScreens[customScreenIndex]->getFactory(); - if (factory) { - for (auto * option = factory->getOptions(); option->name; option++, index++) { - - auto layoutData = g_model.screenData[customScreenIndex].layoutData; - ZoneOptionValue * value = &layoutData.options[index].value; - - // Option label - new StaticText(optionsWindow, grid.getLabelSlot(false), option->name); - - // Option value - switch (option->type) { - case ZoneOption::Bool: - new CheckBox(optionsWindow, grid.getFieldSlot(), GET_SET_DEFAULT(value->boolValue)); - break; - - case ZoneOption::Color: - new ColorEdit(optionsWindow, grid.getFieldSlot(), GET_SET_DEFAULT(value->unsignedValue)); - break; - - default: - break; - } - grid.nextLine(); - } + auto layout = dynamic_cast(customScreens[customScreenIndex]); + if (!layout) { + return; } + auto factory = layout->getFactory(); + if (!factory) { + return; + } + + for (auto * option = factory->getOptions(); option->name; option++, index++) { + + auto layoutData = g_model.screenData[customScreenIndex].layoutData; + ZoneOptionValue * value = &layoutData.options[index].value; + + // Option label + new StaticText(optionsWindow, grid.getLabelSlot(false), option->name); + + // Option value + switch (option->type) { + case ZoneOption::Bool: + new CheckBox(optionsWindow, grid.getFieldSlot(), GET_SET_DEFAULT(value->boolValue)); + break; + + case ZoneOption::Color: + new ColorEdit(optionsWindow, grid.getFieldSlot(), GET_SET_DEFAULT(value->unsignedValue)); + break; + + default: + break; + } + grid.nextLine(); + } + optionsWindow->adjustHeight(); } @@ -398,7 +406,11 @@ void ScreenSetupPage::build(FormWindow * window) rect_t optRect = {0, grid.getWindowHeight(), window->width(), 0}; auto optionsWindow = new FormGroup(window, optRect, FORWARD_SCROLL | FORM_FORWARD_FOCUS); - LayoutChoice::LayoutFactoryGetter getFactory = GET_VALUE(customScreens[idx]->getFactory()); + LayoutChoice::LayoutFactoryGetter getFactory = [idx] () -> const LayoutFactory * { + auto layout = dynamic_cast(customScreens[idx]); + if (!layout) return nullptr; + return layout->getFactory(); + }; LayoutChoice::LayoutFactorySetter setLayout = [idx, optionsWindow](const LayoutFactory *factory) { // delete any options potentially accessing // the old custom screen diff --git a/radio/src/gui/colorlcd/screen_setup.h b/radio/src/gui/colorlcd/screen_setup.h index 50767f3f3..051aa70de 100644 --- a/radio/src/gui/colorlcd/screen_setup.h +++ b/radio/src/gui/colorlcd/screen_setup.h @@ -58,7 +58,7 @@ class ScreenSetupPage: public PageTab { class SetupWidgetsPageSlot: public Button { public: - SetupWidgetsPageSlot(FormGroup * parent, const rect_t & rect, WidgetsContainerInterface* container, uint8_t slotIndex); + SetupWidgetsPageSlot(FormGroup * parent, const rect_t & rect, WidgetsContainer* container, uint8_t slotIndex); void paint(BitmapBuffer * dc) override; }; diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 849294d8b..bbd6d2420 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -164,7 +164,7 @@ void ViewMain::updateTopbarVisibility() int leftScroll = getScrollPositionX() % pageWidth; if (leftScroll == 0) { setTopbarVisible(hasTopbar(g_model.view)); - customScreens[g_model.view]->decorate(); + customScreens[g_model.view]->adjustLayout(); } else { int leftIdx = getScrollPositionX() / pageWidth; @@ -185,8 +185,8 @@ void ViewMain::updateTopbarVisibility() } setTopbarVisible(ratio); - customScreens[leftIdx]->decorate(); - customScreens[leftIdx+1]->decorate(); + customScreens[leftIdx]->adjustLayout(); + customScreens[leftIdx+1]->adjustLayout(); } } } diff --git a/radio/src/gui/colorlcd/widgets/widgets_container_impl.h b/radio/src/gui/colorlcd/widgets/widgets_container_impl.h index e0592227b..c91cee3a6 100644 --- a/radio/src/gui/colorlcd/widgets/widgets_container_impl.h +++ b/radio/src/gui/colorlcd/widgets/widgets_container_impl.h @@ -24,22 +24,13 @@ #include "widgets_container.h" template -class WidgetsContainer: public WidgetsContainerInterface +class WidgetsContainerImpl: public WidgetsContainer { public: - // struct ZonePersistentData { - // char widgetName[WIDGET_NAME_LEN]; - // Widget::PersistentData widgetData; - // }; - - // struct PersistentData { - // ZonePersistentData zones[N]; - // ZoneOptionValueTyped options[O]; - // }; typedef WidgetsContainerPersistentData PersistentData; - WidgetsContainer(const rect_t & rect, PersistentData * persistentData): - WidgetsContainerInterface(nullptr, rect, FORM_FORWARD_FOCUS), + WidgetsContainerImpl(const rect_t & rect, PersistentData * persistentData): + WidgetsContainer(nullptr, rect, FORM_FORWARD_FOCUS), persistentData(persistentData) { } @@ -146,7 +137,7 @@ class WidgetsContainer: public WidgetsContainerInterface } } - void decorate() override + void adjustLayout() override { } diff --git a/radio/src/gui/colorlcd/widgets_container.h b/radio/src/gui/colorlcd/widgets_container.h index 7ba7e1219..d02237b87 100644 --- a/radio/src/gui/colorlcd/widgets_container.h +++ b/radio/src/gui/colorlcd/widgets_container.h @@ -64,7 +64,7 @@ struct WidgetsContainerPersistentData { typedef WidgetsContainerPersistentData TopBarPersistentData; -class WidgetsContainerInterface: public FormGroup +class WidgetsContainer: public FormGroup { public: using FormGroup::FormGroup; @@ -74,10 +74,7 @@ class WidgetsContainerInterface: public FormGroup virtual Widget * createWidget(unsigned int index, const WidgetFactory * factory) = 0; virtual Widget * getWidget(unsigned int index) = 0; virtual void removeWidget(unsigned int index) = 0; - - // this should go away... - virtual const LayoutFactory * getFactory() const = 0; - virtual void decorate() = 0; + virtual void adjustLayout() = 0; }; From 3b0a216394ee1d22176f2a968dc1b6088253f33b Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Apr 2021 08:52:15 +0200 Subject: [PATCH 43/54] Finished flight mode label placement And a bit of clean-up / fixes. --- radio/src/gui/colorlcd/screen_setup.cpp | 2 +- .../src/gui/colorlcd/view_main_decoration.cpp | 33 ++++++++++++------- radio/src/gui/colorlcd/view_main_decoration.h | 2 ++ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index 77bc9ef68..a7944bbdc 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -365,7 +365,7 @@ static void updateLayoutOptions(FormGroup* optionsWindow, unsigned customScreenI for (auto * option = factory->getOptions(); option->name; option++, index++) { - auto layoutData = g_model.screenData[customScreenIndex].layoutData; + auto& layoutData = g_model.screenData[customScreenIndex].layoutData; ZoneOptionValue * value = &layoutData.options[index].value; // Option label diff --git a/radio/src/gui/colorlcd/view_main_decoration.cpp b/radio/src/gui/colorlcd/view_main_decoration.cpp index 79f4614fc..0041acb8c 100644 --- a/radio/src/gui/colorlcd/view_main_decoration.cpp +++ b/radio/src/gui/colorlcd/view_main_decoration.cpp @@ -37,7 +37,6 @@ void ViewMainDecoration::setSlidersVisible(bool visible) // sliders[SLIDERS_POT1]->setHeight(visible ? TRIM_SQUARE_SIZE : 0); - //TODO: might change depending on hardware settings if (IS_POT_MULTIPOS(POT2)) { sliders[SLIDERS_POT2]->setHeight(visible ? MULTIPOS_H : 0); } @@ -55,7 +54,6 @@ void ViewMainDecoration::setSlidersVisible(bool visible) sliders[SLIDERS_REAR_LEFT]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); #if defined(HARDWARE_EXT1) - //TODO: might change depending on hardware settings if (IS_POT_SLIDER_AVAILABLE(EXT1)) { sliders[SLIDERS_EXT1]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); } @@ -64,7 +62,6 @@ void ViewMainDecoration::setSlidersVisible(bool visible) sliders[SLIDERS_REAR_RIGHT]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); #if defined(HARDWARE_EXT2) - //TODO: might change depending on hardware settings if (IS_POT_SLIDER_AVAILABLE(EXT2)) { sliders[SLIDERS_EXT2]->setWidth(visible ? TRIM_SQUARE_SIZE : 0); } @@ -82,7 +79,7 @@ void ViewMainDecoration::setTrimsVisible(bool visible) void ViewMainDecoration::setFlightModeVisible(bool visible) { - flightMode->setHeight(visible ? 20 : 0); + flightMode->setHeight(visible ? FM_LABEL_HEIGHT : 0); } void ViewMainDecoration::adjustDecoration() @@ -177,7 +174,19 @@ void ViewMainDecoration::adjustDecoration() trims[TRIMS_RV]->setLeft(sliders[SLIDERS_REAR_RIGHT]->left() - trims[TRIMS_RV]->width()); trims[TRIMS_RV]->setTop(vertTop); - //TODO: find a proper place for the flight-mode text box + // Place the flight-mode text box + // -> between horiz trims (if existing) + // else on top of horiz sliders + // + pos = trims[TRIMS_LH]->right(); + flightMode->setLeft(pos); + + pos = trims[TRIMS_RH]->left() - pos; + flightMode->setWidth(pos); + + pos = sliders[SLIDERS_POT1]->top(); + pos -= flightMode->height(); + flightMode->setTop(pos); } rect_t ViewMainDecoration::getMainZone() const @@ -189,18 +198,20 @@ rect_t ViewMainDecoration::getMainZone() const }; zone.w = trims[TRIMS_RV]->left() - MAIN_ZONE_BORDER - zone.x; - zone.h = trims[TRIMS_LH]->top() - MAIN_ZONE_BORDER - zone.y; + + // min(trims[TRIMS_LH]->top(), flightMode->top()) + if (trims[TRIMS_LH]->top() < flightMode->top()) + zone.h = trims[TRIMS_LH]->top(); + else + zone.h = flightMode->top(); + + zone.h -= MAIN_ZONE_BORDER + zone.y; return zone; } void ViewMainDecoration::createSliders() { - // TODO: - // - layout must become really dynamic (see adjustDecoration()) - // - components should be created in "folded" state - // - it should not be required to call hasXXXX() at all - // fixed size array, so that works memset(sliders, 0, sizeof(sliders)); diff --git a/radio/src/gui/colorlcd/view_main_decoration.h b/radio/src/gui/colorlcd/view_main_decoration.h index 3a35e1a63..d0e951d24 100644 --- a/radio/src/gui/colorlcd/view_main_decoration.h +++ b/radio/src/gui/colorlcd/view_main_decoration.h @@ -22,6 +22,8 @@ #include "window.h" +constexpr coord_t FM_LABEL_HEIGHT = 20; + class ViewMainDecoration: public Window { public: From 0e684058e449a3d67e4b0f9276ddf1703ca60302 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Apr 2021 09:04:26 +0200 Subject: [PATCH 44/54] Make compiler happy (packed structs are a pain....) --- radio/src/gui/colorlcd/screen_setup.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index a7944bbdc..ed43571f9 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -365,8 +365,8 @@ static void updateLayoutOptions(FormGroup* optionsWindow, unsigned customScreenI for (auto * option = factory->getOptions(); option->name; option++, index++) { - auto& layoutData = g_model.screenData[customScreenIndex].layoutData; - ZoneOptionValue * value = &layoutData.options[index].value; + auto layoutData = &g_model.screenData[customScreenIndex].layoutData; + ZoneOptionValue * value = &layoutData->options[index].value; // Option label new StaticText(optionsWindow, grid.getLabelSlot(false), option->name); From b259d0baebdba95da01004b7338eb203809e0542 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Apr 2021 09:41:15 +0200 Subject: [PATCH 45/54] Save screen settings when leaving screen (only) --- radio/src/gui/colorlcd/menu_screen.cpp | 2 ++ radio/src/gui/colorlcd/screen_setup.cpp | 7 ------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/radio/src/gui/colorlcd/menu_screen.cpp b/radio/src/gui/colorlcd/menu_screen.cpp index 1013fa5ba..ad2bd61cd 100644 --- a/radio/src/gui/colorlcd/menu_screen.cpp +++ b/radio/src/gui/colorlcd/menu_screen.cpp @@ -22,6 +22,7 @@ #include "menu_screen.h" #include "screen_setup.h" #include "view_main.h" +#include "storage/storage.h" ScreenMenu::ScreenMenu(): TabsGroup(ICON_THEME) @@ -30,6 +31,7 @@ ScreenMenu::ScreenMenu(): setCloseHandler([]{ ViewMain::instance()->updateTopbarVisibility(); + storageDirty(EE_MODEL); }); } diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index ed43571f9..bbbfcd8dc 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -222,7 +222,6 @@ class SetupWidgetsPage: public FormWindow if (event == EVT_KEY_LONG(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT)) { killEvents(event); deleteLater(); - SET_DIRTY(); } } #endif @@ -327,8 +326,6 @@ void ScreenAddPage::build(FormWindow * window) if (menu->getTabs() < MAX_CUSTOM_SCREENS) { menu->addTab(new ScreenAddPage(menu, menu->getTabs())); } - - storageDirty(EE_MODEL); } else { TRACE("Add main view: factory is NULL"); @@ -417,7 +414,6 @@ void ScreenSetupPage::build(FormWindow * window) optionsWindow->clear(); createCustomScreen(factory, idx); updateLayoutOptions(optionsWindow, idx); - SET_DIRTY(); }; auto layoutChoice = new LayoutChoice(window, layoutSlot, getFactory, setLayout); @@ -470,9 +466,6 @@ void ScreenSetupPage::build(FormWindow * window) pageIdx = menu->getTabs() - 2; } menu->setCurrentTab(pageIdx); - - // save the changes - storageDirty(EE_MODEL); return 0; }); From fc2bb84ee0d776f56e2c21b047d29b6d7a499ebf Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Apr 2021 10:39:16 +0200 Subject: [PATCH 46/54] Fix empty model filename issue --- radio/src/storage/sdcard_common.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/radio/src/storage/sdcard_common.cpp b/radio/src/storage/sdcard_common.cpp index 7abdfdded..b553877c7 100644 --- a/radio/src/storage/sdcard_common.cpp +++ b/radio/src/storage/sdcard_common.cpp @@ -148,6 +148,19 @@ void storageReadAll() } } + // Current model filename is empty... + // Let's fix it! + if (strlen(g_eeGeneral.currModelFilename) == 0) { + + // sizeof(currModelFilename) == LEN_MODEL_FILENAME + 1 + // make sure it is terminated (see doc for strncpy()) + strncpy(g_eeGeneral.currModelFilename, DEFAULT_MODEL_FILENAME, LEN_MODEL_FILENAME); + g_eeGeneral.currModelFilename[LEN_MODEL_FILENAME] = '\0'; + + storageDirty(EE_GENERAL); + storageCheck(true); + } + if (loadModel(g_eeGeneral.currModelFilename, false) != nullptr) { TRACE("No current model or SD card error"); } From 1588d87d4d8ce89c744eeb3adf5aff6685af0890 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Apr 2021 10:54:01 +0200 Subject: [PATCH 47/54] Apply general defaults on storageFormat() (SD card) --- radio/src/storage/sdcard_common.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/radio/src/storage/sdcard_common.cpp b/radio/src/storage/sdcard_common.cpp index b553877c7..b25b76082 100644 --- a/radio/src/storage/sdcard_common.cpp +++ b/radio/src/storage/sdcard_common.cpp @@ -60,6 +60,7 @@ void storageFormat() sdCheckAndCreateDirectory(RADIO_PATH); sdCheckAndCreateDirectory(MODELS_PATH); storageCreateModelsList(); + generalDefault(); } void storageCheck(bool immediately) From 5932c4c5a883b30a959514614d8c6d4b10874c4d Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 18 Apr 2021 11:49:27 +0200 Subject: [PATCH 48/54] Make TextEdit diry storage --- radio/src/gui/colorlcd/libopenui.h | 1 + radio/src/gui/colorlcd/model_curves.cpp | 4 +- radio/src/gui/colorlcd/model_flightmodes.cpp | 2 +- radio/src/gui/colorlcd/model_gvars.cpp | 2 +- radio/src/gui/colorlcd/model_inputs.cpp | 4 +- radio/src/gui/colorlcd/model_mixes.cpp | 2 +- radio/src/gui/colorlcd/model_outputs.cpp | 2 +- radio/src/gui/colorlcd/model_setup.cpp | 8 ++-- radio/src/gui/colorlcd/model_telemetry.cpp | 2 +- radio/src/gui/colorlcd/radio_hardware.cpp | 10 ++-- radio/src/gui/colorlcd/radio_setup.cpp | 2 +- radio/src/gui/colorlcd/textedits.h | 49 ++++++++++++++++++++ 12 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 radio/src/gui/colorlcd/textedits.h diff --git a/radio/src/gui/colorlcd/libopenui.h b/radio/src/gui/colorlcd/libopenui.h index dff106be4..5cb0422bf 100644 --- a/radio/src/gui/colorlcd/libopenui.h +++ b/radio/src/gui/colorlcd/libopenui.h @@ -55,6 +55,7 @@ #include "curveedit.h" #include "coloredit.h" #include "draw_functions.h" +#include "textedits.h" inline MessageDialog * createPopupInformation(const char * message) { diff --git a/radio/src/gui/colorlcd/model_curves.cpp b/radio/src/gui/colorlcd/model_curves.cpp index 40ad7a6d2..fc9cff1d2 100644 --- a/radio/src/gui/colorlcd/model_curves.cpp +++ b/radio/src/gui/colorlcd/model_curves.cpp @@ -67,7 +67,7 @@ class CurveEditWindow : public Page // Name new StaticText(window, grid.getFieldSlot(), STR_NAME); grid.nextLine(); - new TextEdit(window, grid.getFieldSlot(), curve.name, sizeof(curve.name)); + new RadioTextEdit(window, grid.getFieldSlot(), curve.name, sizeof(curve.name)); grid.nextLine(); // Type @@ -149,7 +149,7 @@ class CurveEditWindow : public Page // Name new StaticText(window, grid.getLabelSlot(), STR_NAME); - new TextEdit(window, grid.getFieldSlot(), curve.name, sizeof(curve.name)); + new RadioTextEdit(window, grid.getFieldSlot(), curve.name, sizeof(curve.name)); grid.nextLine(); // Type diff --git a/radio/src/gui/colorlcd/model_flightmodes.cpp b/radio/src/gui/colorlcd/model_flightmodes.cpp index b8a70fb9a..1298828d4 100644 --- a/radio/src/gui/colorlcd/model_flightmodes.cpp +++ b/radio/src/gui/colorlcd/model_flightmodes.cpp @@ -89,7 +89,7 @@ void ModelFlightModesPage::build(FormWindow * window) // Flight mode name new StaticText(group, grid.getLabelSlot(true), STR_NAME); - new TextEdit(group, grid.getFieldSlot(), g_model.flightModeData[i].name, LEN_FLIGHT_MODE_NAME); + new ModelTextEdit(group, grid.getFieldSlot(), g_model.flightModeData[i].name, LEN_FLIGHT_MODE_NAME); grid.nextLine(); // Flight mode switch diff --git a/radio/src/gui/colorlcd/model_gvars.cpp b/radio/src/gui/colorlcd/model_gvars.cpp index 5ab1a2b41..e810d85ed 100644 --- a/radio/src/gui/colorlcd/model_gvars.cpp +++ b/radio/src/gui/colorlcd/model_gvars.cpp @@ -242,7 +242,7 @@ void GVarEditWindow::buildBody(FormWindow * window) grid.spacer(8); new StaticText(window, grid.getLabelSlot(), STR_NAME); - new TextEdit(window, grid.getFieldSlot(), gvar->name, LEN_GVAR_NAME); + new RadioTextEdit(window, grid.getFieldSlot(), gvar->name, LEN_GVAR_NAME); grid.nextLine(); diff --git a/radio/src/gui/colorlcd/model_inputs.cpp b/radio/src/gui/colorlcd/model_inputs.cpp index ce6a797a3..73e7c8718 100644 --- a/radio/src/gui/colorlcd/model_inputs.cpp +++ b/radio/src/gui/colorlcd/model_inputs.cpp @@ -186,7 +186,7 @@ class InputEditWindow: public Page // Input Name new StaticText(window, grid.getLabelSlot(), STR_INPUTNAME); - new TextEdit(window, grid.getFieldSlot(), g_model.inputNames[line->chn], sizeof(g_model.inputNames[line->chn])); + new ModelTextEdit(window, grid.getFieldSlot(), g_model.inputNames[line->chn], sizeof(g_model.inputNames[line->chn])); grid.nextLine(); // Switch @@ -208,7 +208,7 @@ class InputEditWindow: public Page // Name new StaticText(window, grid.getLabelSlot(), STR_EXPONAME); - new TextEdit(window, grid.getFieldSlot(), line->name, sizeof(line->name)); + new ModelTextEdit(window, grid.getFieldSlot(), line->name, sizeof(line->name)); grid.nextLine(); // Source diff --git a/radio/src/gui/colorlcd/model_mixes.cpp b/radio/src/gui/colorlcd/model_mixes.cpp index 4bdc53bba..7bbb7a650 100644 --- a/radio/src/gui/colorlcd/model_mixes.cpp +++ b/radio/src/gui/colorlcd/model_mixes.cpp @@ -84,7 +84,7 @@ class MixEditWindow : public Page { // Mix name new StaticText(window, grid.getLabelSlot(), STR_MIXNAME); - new TextEdit(window, grid.getFieldSlot(), mix->name, sizeof(mix->name)); + new RadioTextEdit(window, grid.getFieldSlot(), mix->name, sizeof(mix->name)); grid.nextLine(); // Source diff --git a/radio/src/gui/colorlcd/model_outputs.cpp b/radio/src/gui/colorlcd/model_outputs.cpp index 02ad75a20..47a735b17 100644 --- a/radio/src/gui/colorlcd/model_outputs.cpp +++ b/radio/src/gui/colorlcd/model_outputs.cpp @@ -54,7 +54,7 @@ class OutputEditWindow : public Page { // Name new StaticText(window, grid.getLabelSlot(), STR_NAME); - new TextEdit(window, grid.getFieldSlot(), output->name, sizeof(output->name)); + new RadioTextEdit(window, grid.getFieldSlot(), output->name, sizeof(output->name)); grid.nextLine(); // Offset diff --git a/radio/src/gui/colorlcd/model_setup.cpp b/radio/src/gui/colorlcd/model_setup.cpp index 58ebebf43..f4057e238 100644 --- a/radio/src/gui/colorlcd/model_setup.cpp +++ b/radio/src/gui/colorlcd/model_setup.cpp @@ -171,7 +171,7 @@ class RegisterDialog: public Dialog { // Register ID new StaticText(form, grid.getLabelSlot(), STR_REG_ID); - auto edit = new TextEdit(form, grid.getFieldSlot(), g_model.modelRegistrationID, sizeof(g_model.modelRegistrationID)); + auto edit = new RadioTextEdit(form, grid.getFieldSlot(), g_model.modelRegistrationID, sizeof(g_model.modelRegistrationID)); grid.nextLine(); // UID @@ -218,7 +218,7 @@ class RegisterDialog: public Dialog { rect_t rect = waiting->getRect(); waiting->deleteLater(); - rxName = new TextEdit(&content->form, rect, reusableBuffer.moduleSetup.pxx2.registerRxName, PXX2_LEN_RX_NAME); + rxName = new RadioTextEdit(&content->form, rect, reusableBuffer.moduleSetup.pxx2.registerRxName, PXX2_LEN_RX_NAME); rect = exitButton->getRect(); auto okButton = new TextButton(&content->form, rect, "OK", [=]() -> int8_t { @@ -998,7 +998,7 @@ void ModelSetupPage::build(FormWindow * window) // Model name new StaticText(window, grid.getLabelSlot(), STR_MODELNAME); - auto text = new TextEdit(window, grid.getFieldSlot(), g_model.header.name, sizeof(g_model.header.name)); + auto text = new RadioTextEdit(window, grid.getFieldSlot(), g_model.header.name, sizeof(g_model.header.name)); text->setChangeHandler([=] { modelslist.load(); auto model = modelslist.getCurrentModel(); @@ -1035,7 +1035,7 @@ void ModelSetupPage::build(FormWindow * window) // Timer name new StaticText(window, grid.getLabelSlot(true), STR_NAME); grid.nextLine(); - new TextEdit(group, timerGrid.getSlot(), timer->name, LEN_TIMER_NAME); + new RadioTextEdit(group, timerGrid.getSlot(), timer->name, LEN_TIMER_NAME); timerGrid.nextLine(); // Timer mode diff --git a/radio/src/gui/colorlcd/model_telemetry.cpp b/radio/src/gui/colorlcd/model_telemetry.cpp index 9c711c39d..45e34a752 100644 --- a/radio/src/gui/colorlcd/model_telemetry.cpp +++ b/radio/src/gui/colorlcd/model_telemetry.cpp @@ -324,7 +324,7 @@ class SensorEditWindow : public Page { // Sensor name new StaticText(window, grid.getLabelSlot(), STR_NAME); - new TextEdit(window, grid.getFieldSlot(), sensor->label, sizeof(sensor->label)); + new RadioTextEdit(window, grid.getFieldSlot(), sensor->label, sizeof(sensor->label)); grid.nextLine(); // Type diff --git a/radio/src/gui/colorlcd/radio_hardware.cpp b/radio/src/gui/colorlcd/radio_hardware.cpp index 0b4132e7b..f2932f9a3 100644 --- a/radio/src/gui/colorlcd/radio_hardware.cpp +++ b/radio/src/gui/colorlcd/radio_hardware.cpp @@ -136,7 +136,7 @@ class BluetoothConfigWindow : public FormGroup // BT radio name new StaticText(this, grid.getLabelSlot(true), STR_NAME); - new TextEdit(this, grid.getFieldSlot(), g_eeGeneral.bluetoothName, LEN_BLUETOOTH_NAME); + new RadioTextEdit(this, grid.getFieldSlot(), g_eeGeneral.bluetoothName, LEN_BLUETOOTH_NAME); grid.nextLine(); } @@ -175,7 +175,7 @@ void RadioHardwarePage::build(FormWindow * window) grid.nextLine(); for (int i = 0; i < NUM_STICKS; i++) { new StaticText(window, grid.getLabelSlot(true), TEXT_AT_INDEX(STR_VSRCRAW, (i + 1))); - new TextEdit(window, grid.getFieldSlot(2,0), g_eeGeneral.anaNames[i], LEN_ANA_NAME); + new RadioTextEdit(window, grid.getFieldSlot(2,0), g_eeGeneral.anaNames[i], LEN_ANA_NAME); grid.nextLine(); } @@ -184,7 +184,7 @@ void RadioHardwarePage::build(FormWindow * window) grid.nextLine(); for (int i = 0; i < NUM_POTS; i++) { new StaticText(window, grid.getLabelSlot(true), TEXT_AT_INDEX(STR_VSRCRAW, (i + NUM_STICKS + 1))); - new TextEdit(window, grid.getFieldSlot(2,0), g_eeGeneral.anaNames[i + NUM_STICKS], LEN_ANA_NAME); + new RadioTextEdit(window, grid.getFieldSlot(2,0), g_eeGeneral.anaNames[i + NUM_STICKS], LEN_ANA_NAME); new Choice(window, grid.getFieldSlot(2,1), STR_POTTYPES, POT_NONE, POT_WITHOUT_DETENT, [=]() -> int { return bfGet(g_eeGeneral.potsConfig, 2*i, 2); @@ -201,7 +201,7 @@ void RadioHardwarePage::build(FormWindow * window) grid.nextLine(); for (int i = 0; i < NUM_SLIDERS; i++) { new StaticText(window, grid.getLabelSlot(true), TEXT_AT_INDEX(STR_VSRCRAW, (i + NUM_STICKS + NUM_POTS + 1))); - new TextEdit(window, grid.getFieldSlot(2,0), g_eeGeneral.anaNames[i + NUM_STICKS], LEN_ANA_NAME); + new RadioTextEdit(window, grid.getFieldSlot(2,0), g_eeGeneral.anaNames[i + NUM_STICKS], LEN_ANA_NAME); new Choice(window, grid.getFieldSlot(2,1), STR_SLIDERTYPES, SLIDER_NONE, SLIDER_WITH_DETENT, [=]() -> int { uint8_t mask = (0x01 << i); @@ -221,7 +221,7 @@ void RadioHardwarePage::build(FormWindow * window) grid.nextLine(); for (int i = 0; i < NUM_SWITCHES; i++) { new SwitchDynamicLabel(window, grid.getLabelSlot(true), i); - new TextEdit(window, grid.getFieldSlot(2, 0), g_eeGeneral.switchNames[i], LEN_SWITCH_NAME); + new RadioTextEdit(window, grid.getFieldSlot(2, 0), g_eeGeneral.switchNames[i], LEN_SWITCH_NAME); new Choice(window, grid.getFieldSlot(2, 1), STR_SWTYPES, SWITCH_NONE, SWITCH_TYPE_MAX(i), [=]() -> int { return SWITCH_CONFIG(i); diff --git a/radio/src/gui/colorlcd/radio_setup.cpp b/radio/src/gui/colorlcd/radio_setup.cpp index 5e40c7f5f..6d8a610ef 100644 --- a/radio/src/gui/colorlcd/radio_setup.cpp +++ b/radio/src/gui/colorlcd/radio_setup.cpp @@ -400,7 +400,7 @@ void RadioSetupPage::build(FormWindow * window) #if defined(PXX2) // Owner ID new StaticText(window, grid.getLabelSlot(), STR_OWNER_ID); - new TextEdit(window, grid.getFieldSlot(), g_eeGeneral.ownerRegistrationID, PXX2_LEN_REGISTRATION_ID); + new RadioTextEdit(window, grid.getFieldSlot(), g_eeGeneral.ownerRegistrationID, PXX2_LEN_REGISTRATION_ID); grid.nextLine(); #endif diff --git a/radio/src/gui/colorlcd/textedits.h b/radio/src/gui/colorlcd/textedits.h new file mode 100644 index 000000000..15e3e2e79 --- /dev/null +++ b/radio/src/gui/colorlcd/textedits.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#pragma once + +#include "libopenui.h" +#include "textedit.h" +#include "storage/storage.h" + +class ModelTextEdit: public TextEdit +{ + public: + ModelTextEdit(Window * parent, const rect_t & rect, char * value, uint8_t length, LcdFlags windowFlags = 0): + TextEdit(parent, rect, value, length, windowFlags) + { + setChangeHandler([](){ + storageDirty(EE_MODEL); + }); + } +}; + +class RadioTextEdit: public TextEdit +{ + public: + RadioTextEdit(Window * parent, const rect_t & rect, char * value, uint8_t length, LcdFlags windowFlags = 0): + TextEdit(parent, rect, value, length, windowFlags) + { + setChangeHandler([](){ + storageDirty(EE_GENERAL); + }); + } +}; \ No newline at end of file From 8c49a072428d2cf740aa94e91891c5c70cd40cba Mon Sep 17 00:00:00 2001 From: 3djc Date: Sun, 18 Apr 2021 14:29:30 +0200 Subject: [PATCH 49/54] Some fixes to value widget --- radio/src/gui/colorlcd/widget_settings.cpp | 4 ++++ radio/src/gui/colorlcd/widgets/value.cpp | 8 ++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/radio/src/gui/colorlcd/widget_settings.cpp b/radio/src/gui/colorlcd/widget_settings.cpp index 1f2f7ee46..a82512ef0 100644 --- a/radio/src/gui/colorlcd/widget_settings.cpp +++ b/radio/src/gui/colorlcd/widget_settings.cpp @@ -23,6 +23,8 @@ #include "widget_settings.h" #include "libopenui.h" +#define SET_DIRTY() storageDirty(EE_MODEL) + static const rect_t widgetSettingsDialogRect = { LCD_W / 10, // x LCD_H / 4, // y @@ -118,12 +120,14 @@ WidgetSettings::WidgetSettings(Window * parent, Widget * widget) : break; case ZoneOption::Color: + for (uint8_t part = 0; part < 3; part++) new ColorEdit(form, grid.getFieldSlot(), [=]() -> int { // getValue return (int) widget->getOptionValue(optIdx)->unsignedValue; }, [=](int newValue) { // setValue widget->getOptionValue(optIdx)->unsignedValue = (uint32_t) newValue; + SET_DIRTY(); }); break; } diff --git a/radio/src/gui/colorlcd/widgets/value.cpp b/radio/src/gui/colorlcd/widgets/value.cpp index f36dde97f..2556a310f 100644 --- a/radio/src/gui/colorlcd/widgets/value.cpp +++ b/radio/src/gui/colorlcd/widgets/value.cpp @@ -33,10 +33,6 @@ class ValueWidget: public Widget void paint(BitmapBuffer * dc) override { - // draw the background and border - dc->clear(DEFAULT_BGCOLOR); - dc->drawFilledRect(0,0, width(), height(), SOLID, MAINVIEW_PANES_COLOR | OPACITY(5)); - // get source from options[0] mixsrc_t field = persistentData->options[0].value.unsignedValue; @@ -51,8 +47,8 @@ class ValueWidget: public Widget yValue = 14; xLabel = 0; yLabel = 0; - attrValue = LEFT | NO_UNIT | FONT(XS); - attrLabel = FONT(XS); + attrValue = LEFT | NO_UNIT | FONT(L); + attrLabel = LEFT; } else if (height() < 50) { xValue = width() - NUMBERS_PADDING; From 85da52db55fdb2478d96fc27da6df6f6b884c90f Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Apr 2021 17:52:05 +0200 Subject: [PATCH 50/54] Fix layout / widget init buffer overflow --- .../colorlcd/layouts/layout_factory_impl.h | 17 ++++++++++++- radio/src/gui/colorlcd/widget.h | 25 +++---------------- .../colorlcd/widgets/widgets_container_impl.h | 19 ++++++++++++++ 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/radio/src/gui/colorlcd/layouts/layout_factory_impl.h b/radio/src/gui/colorlcd/layouts/layout_factory_impl.h index e858aee51..1272b772f 100644 --- a/radio/src/gui/colorlcd/layouts/layout_factory_impl.h +++ b/radio/src/gui/colorlcd/layouts/layout_factory_impl.h @@ -25,8 +25,8 @@ #include "audio.h" #include "translations.h" -#include "layout.h" #include "widgets/widgets_container_impl.h" +#include "layout.h" #define LAYOUT_COMMON_OPTIONS \ { STR_TOP_BAR, ZoneOption::Bool }, \ @@ -133,6 +133,7 @@ class BaseLayoutFactory: public LayoutFactory Layout * create(Layout::PersistentData * persistentData) const override { + initPersistentData(persistentData); Layout * layout = new T(this, persistentData); if (layout) { layout->create(); @@ -149,6 +150,20 @@ class BaseLayoutFactory: public LayoutFactory return layout; } + void initPersistentData(Layout::PersistentData * persistentData) const + { + memset(persistentData, 0, sizeof(Layout::PersistentData)); + if (options) { + int i = 0; + for (const ZoneOption * option = options; option->name; option++, i++) { + TRACE("LayoutFactory::initPersistentData() setting option '%s'", option->name); + // TODO compiler bug? The CPU freezes ... persistentData->options[i++] = option->deflt; + memcpy(&persistentData->options[i].value, &option->deflt, sizeof(ZoneOptionValue)); + persistentData->options[i].type = zoneValueEnumFromType(option->type); + } + } + } + protected: const uint8_t * bitmap; const ZoneOption * options; diff --git a/radio/src/gui/colorlcd/widget.h b/radio/src/gui/colorlcd/widget.h index c7099d3be..279e662c4 100644 --- a/radio/src/gui/colorlcd/widget.h +++ b/radio/src/gui/colorlcd/widget.h @@ -125,11 +125,11 @@ class WidgetFactory memset(persistentData, 0, sizeof(Widget::PersistentData)); if (options) { int i = 0; - for (const ZoneOption * option = options; option->name; option++) { + for (const ZoneOption * option = options; option->name; option++, i++) { TRACE("WidgetFactory::initPersistentData() setting option '%s'", option->name); // TODO compiler bug? The CPU freezes ... persistentData->options[i++] = option->deflt; - memcpy(&persistentData->options[i++].value, &option->deflt, sizeof(ZoneOptionValue)); - persistentData->options[i++].type = zoneValueEnumFromType(option->type); + memcpy(&persistentData->options[i].value, &option->deflt, sizeof(ZoneOptionValue)); + persistentData->options[i].type = zoneValueEnumFromType(option->type); } } } @@ -141,25 +141,6 @@ class WidgetFactory const ZoneOption * options; }; -template -class BaseWidgetFactory: public WidgetFactory -{ - public: - BaseWidgetFactory(const char * name, const ZoneOption * options): - WidgetFactory(name, options) - { - } - - Widget * create(FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData, bool init = true) const override - { - if (init) { - initPersistentData(persistentData); - } - - return new T(this, parent, rect, persistentData); - } -}; - inline const ZoneOption * Widget::getOptions() const { return getFactory()->getOptions(); diff --git a/radio/src/gui/colorlcd/widgets/widgets_container_impl.h b/radio/src/gui/colorlcd/widgets/widgets_container_impl.h index c91cee3a6..1966a0e0a 100644 --- a/radio/src/gui/colorlcd/widgets/widgets_container_impl.h +++ b/radio/src/gui/colorlcd/widgets/widgets_container_impl.h @@ -145,3 +145,22 @@ class WidgetsContainerImpl: public WidgetsContainer PersistentData * persistentData; Widget * widgets[N] = {}; }; + +template +class BaseWidgetFactory: public WidgetFactory +{ + public: + BaseWidgetFactory(const char * name, const ZoneOption * options): + WidgetFactory(name, options) + { + } + + Widget * create(FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData, bool init = true) const override + { + if (init) { + initPersistentData(persistentData); + } + + return new T(this, parent, rect, persistentData); + } +}; From dd76ddd02ec6a0e056447a1046266736c316c586 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Sun, 18 Apr 2021 22:38:05 +0200 Subject: [PATCH 51/54] Try to make Travis use docker as well --- .travis.yml | 41 ++++------------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) diff --git a/.travis.yml b/.travis.yml index 445a27cf8..e0dc48c68 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,29 +1,9 @@ -sudo: required -dist: xenial language: cpp -compiler: gcc -addons: - apt: - sources: - - sourceline: 'ppa:ubuntu-sdk-team/ppa' - - sourceline: 'ppa:ubuntu-toolchain-r/test' - - sourceline: 'ppa:beineri/opt-qt571-xenial' - update: true - packages: - - curl - - libmpfr4 - - libmpc3 - - libfox-1.6-dev - - libgtest-dev - - lib32stdc++6 - - libclang-common-6.0-dev - - clang-6.0 - - python3-pip +services: + - docker env: - global: - - QT_BASE=57 matrix: - FLAVOR=COMPANION - FLAVOR=ARM9X @@ -34,20 +14,7 @@ env: - FLAVOR=COLORLCD before_install: - - wget --quiet https://developer.arm.com/-/media/Files/downloads/gnu-rm/6-2017q2/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 - - tar xjf gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 - - sudo mv gcc-arm-none-eabi-6-2017-q2-update /opt/gcc-arm-none-eabi - - sudo ln -s /opt/gcc-arm-none-eabi/bin/arm-none-eabi-gcc /usr/bin/arm-none-eabi-gcc - - sudo ln -s /opt/gcc-arm-none-eabi/bin/arm-none-eabi-g++ /usr/bin/arm-none-eabi-g++ - - sudo ln -s /opt/gcc-arm-none-eabi/bin/arm-none-eabi-as /usr/bin/arm-none-eabi-as - - sudo ln -s /opt/gcc-arm-none-eabi/bin/arm-none-eabi-objcopy /usr/bin/arm-none-eabi-objcopy - - sudo ln -s /opt/gcc-arm-none-eabi/bin/arm-none-eabi-objdump /usr/bin/arm-none-eabi-objdump - - sudo ln -s /opt/gcc-arm-none-eabi/bin/arm-none-eabi-size /usr/bin/arm-none-eabi-size - - sudo apt-get install --yes --force-yes -qq qt${QT_BASE}base qt${QT_BASE}multimedia qt${QT_BASE}svg qt${QT_BASE}tools; source /opt/qt${QT_BASE}/bin/qt${QT_BASE}-env.sh - - sudo ln -sf /usr/bin/python3 /usr/bin/python - - python3 -m pip install pip==20.3.3 - - sudo apt-get install python3-setuptools - - python3 -m pip install pillow==7.2.0 clang + - docker pull ghcr.io/raphaelcoeffic/opentx-commit-tests script: - - ./tools/commit-tests.sh + - docker run --rm --env FLAVOR=$FLAVOR -v $(pwd):/src ghcr.io/raphaelcoeffic/opentx-commit-tests From 3aa3b5d1d7859846c9ce0b61ed03c1cedc0af00f Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 19 Apr 2021 07:44:42 +0200 Subject: [PATCH 52/54] Cosmetics --- radio/src/gui/colorlcd/screen_setup.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index bbbfcd8dc..7288a662b 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -257,8 +257,6 @@ void ScreenUserInterfacePage::build(FormWindow * window) // Top Bar new StaticText(window, grid.getLabelSlot(), STR_TOP_BAR, 0, 0); - // TODO: enable settings topbar widgets - grid.nextLine(); auto menu = this->menu; auto setupTopbarWidgets = new TextButton(window, grid.getFieldSlot(), STR_SETUP_WIDGETS); From 9b3877681f9169c928b7e5a6614a1696c5108b30 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 19 Apr 2021 10:08:20 +0200 Subject: [PATCH 53/54] Review Radio setup --- radio/src/gui/colorlcd/radio_setup.cpp | 36 +++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/radio/src/gui/colorlcd/radio_setup.cpp b/radio/src/gui/colorlcd/radio_setup.cpp index 6d8a610ef..063805cc7 100644 --- a/radio/src/gui/colorlcd/radio_setup.cpp +++ b/radio/src/gui/colorlcd/radio_setup.cpp @@ -208,16 +208,6 @@ void RadioSetupPage::build(FormWindow * window) new Slider(window, grid.getFieldSlot(), -2, +2, GET_SET_DEFAULT(g_eeGeneral.beepVolume)); grid.nextLine(); - // Wav volume - new StaticText(window, grid.getLabelSlot(true), STR_WAV_VOLUME); - new Slider(window, grid.getFieldSlot(), -2, +2, GET_SET_DEFAULT(g_eeGeneral.wavVolume)); - grid.nextLine(); - - // Background volume - new StaticText(window, grid.getLabelSlot(true), STR_BG_VOLUME); - new Slider(window, grid.getFieldSlot(), -2, +2, GET_SET_DEFAULT(g_eeGeneral.backgroundVolume)); - grid.nextLine(); - // Beeps length new StaticText(window, grid.getLabelSlot(true), STR_BEEP_LENGTH); new Slider(window, grid.getFieldSlot(), -2, +2, GET_SET_DEFAULT(g_eeGeneral.beepLength)); @@ -228,14 +218,24 @@ void RadioSetupPage::build(FormWindow * window) auto edit = new NumberEdit(window, grid.getFieldSlot(), 0, 300, GET_DEFAULT(15 * g_eeGeneral.speakerPitch), [=](int32_t newValue) { - g_eeGeneral.speakerPitch = newValue / 15; - SET_DIRTY(); + g_eeGeneral.speakerPitch = newValue / 15; + SET_DIRTY(); }); edit->setStep(15); edit->setPrefix("+"); edit->setSuffix("Hz"); grid.nextLine(); + // Wav volume + new StaticText(window, grid.getLabelSlot(true), STR_WAV_VOLUME); + new Slider(window, grid.getFieldSlot(), -2, +2, GET_SET_DEFAULT(g_eeGeneral.wavVolume)); + grid.nextLine(); + + // Background volume + new StaticText(window, grid.getLabelSlot(true), STR_BG_VOLUME); + new Slider(window, grid.getFieldSlot(), -2, +2, GET_SET_DEFAULT(g_eeGeneral.backgroundVolume)); + grid.nextLine(); + #if defined(VARIO) { new Subtitle(window, grid.getLabelSlot(), STR_VARIO); @@ -305,6 +305,12 @@ void RadioSetupPage::build(FormWindow * window) edit->setSuffix("v"); grid.nextLine(); + // Inactivity alarm + new StaticText(window, grid.getLabelSlot(true), STR_INACTIVITYALARM); + edit = new NumberEdit(window, grid.getFieldSlot(), 0, 250, GET_SET_DEFAULT(g_eeGeneral.inactivityTimer)); + edit->setSuffix("minutes"); + grid.nextLine(); + // Alarms warning new StaticText(window, grid.getLabelSlot(true), STR_ALARMWARNING); new CheckBox(window, grid.getFieldSlot(), GET_SET_INVERTED(g_eeGeneral.disableAlarmWarning)); @@ -314,12 +320,6 @@ void RadioSetupPage::build(FormWindow * window) new StaticText(window, grid.getLabelSlot(true), STR_RSSI_SHUTDOWN_ALARM); new CheckBox(window, grid.getFieldSlot(), GET_SET_INVERTED(g_eeGeneral.disableRssiPoweroffAlarm)); grid.nextLine(); - - // Inactivity alarm - new StaticText(window, grid.getLabelSlot(true), STR_INACTIVITYALARM); - edit = new NumberEdit(window, grid.getFieldSlot(), 0, 250, GET_SET_DEFAULT(g_eeGeneral.inactivityTimer)); - edit->setSuffix("minutes"); - grid.nextLine(); } // Backlight From 01cc3aa99f1109b9cb7dffb92e55cbfc5b014210 Mon Sep 17 00:00:00 2001 From: 3djc Date: Mon, 19 Apr 2021 11:47:50 +0200 Subject: [PATCH 54/54] Fix test widget --- radio/src/gui/colorlcd/widget_settings.cpp | 12 ++++++++++-- radio/src/gui/colorlcd/widgets/text.cpp | 3 --- radio/src/translations.cpp | 3 +++ radio/src/translations.h | 1 + radio/src/translations/untranslated.h | 10 ++++++++++ 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/radio/src/gui/colorlcd/widget_settings.cpp b/radio/src/gui/colorlcd/widget_settings.cpp index a82512ef0..39756062b 100644 --- a/radio/src/gui/colorlcd/widget_settings.cpp +++ b/radio/src/gui/colorlcd/widget_settings.cpp @@ -83,14 +83,22 @@ WidgetSettings::WidgetSettings(Window * parent, Widget * widget) : break; case ZoneOption::String: + new ModelTextEdit(form, grid.getFieldSlot(), widget->getOptionValue(optIdx)->stringValue, sizeof( widget->getOptionValue(optIdx)->stringValue)); break; case ZoneOption::File: break; - case ZoneOption::TextSize: + case ZoneOption::TextSize: { + new Choice(form, grid.getFieldSlot(), STR_FONT_SIZES, 0, FONTS_COUNT - 1, + [=]() -> int { // getValue + return (int) widget->getOptionValue(optIdx)->unsignedValue; + }, + [=](int newValue) { // setValue + widget->getOptionValue(optIdx)->unsignedValue = (uint32_t) newValue; + }); break; - + } case ZoneOption::Timer: // Unsigned { auto tmChoice = new Choice(form, grid.getFieldSlot(), 0, TIMERS - 1, diff --git a/radio/src/gui/colorlcd/widgets/text.cpp b/radio/src/gui/colorlcd/widgets/text.cpp index 9605d6035..701dfef84 100644 --- a/radio/src/gui/colorlcd/widgets/text.cpp +++ b/radio/src/gui/colorlcd/widgets/text.cpp @@ -33,9 +33,6 @@ class TextWidget: public Widget void paint(BitmapBuffer * dc) override { - // clear the background - dc->clear(DEFAULT_BGCOLOR); - // get font color from options[1] lcdSetColor(persistentData->options[1].value.unsignedValue); diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp index 4d4075bb5..663e1c5bb 100644 --- a/radio/src/translations.cpp +++ b/radio/src/translations.cpp @@ -22,6 +22,9 @@ #define ISTR(x) const char STR_##x[] = LEN_##x TR_##x +#if defined(COLORLCD) +ISTR(FONT_SIZES); +#endif ISTR(OFFON); ISTR(MMMINV); ISTR(VBEEPMODE); diff --git a/radio/src/translations.h b/radio/src/translations.h index 755c6bca4..fa6f69e5c 100644 --- a/radio/src/translations.h +++ b/radio/src/translations.h @@ -152,6 +152,7 @@ extern const char STR_USBMODES[]; extern const char STR_JACK_MODES[]; extern const char STR_VFAILSAFE[]; +extern const char STR_FONT_SIZES[]; extern const char STR_VTRAINERMODES[]; extern const char STR_EXTERNAL_MODULE_PROTOCOLS[]; extern const char STR_INTERNAL_MODULE_PROTOCOLS[]; diff --git a/radio/src/translations/untranslated.h b/radio/src/translations/untranslated.h index bbd753897..b98d5b70e 100644 --- a/radio/src/translations/untranslated.h +++ b/radio/src/translations/untranslated.h @@ -100,6 +100,16 @@ #define TR_MODULE_R9M_LITE "R9MLite\0 " #endif +#if defined(COLORLCD) +#if defined(BOLD) +#define LEN_FONT_SIZES "\003" +#define TR_FONT_SIZES "STD" +#else +#define LEN_FONT_SIZES "\004" +#define TR_FONT_SIZES "STD\0""BOLD""XXS\0""XS\0 ""L\0 ""XL\0 ""XXL\0" +#endif +#endif + #define LEN_EXTERNAL_MODULE_PROTOCOLS "\014" #define TR_EXTERNAL_MODULE_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""ISRM\0 ""DSM2\0 ""CRSF\0 ""MULTI\0 ""R9M\0 ""R9M ACCESS\0 " TR_MODULE_R9M_LITE "R9ML ACCESS\0""GHST\0 ""R9MLP ACCESS""SBUS\0 ""XJT Lite\0 ""AFHDS3\0 "