diff --git a/radio/src/gui/colorlcd/layout.h b/radio/src/gui/colorlcd/layout.h index 4d409357e..2d93297f2 100644 --- a/radio/src/gui/colorlcd/layout.h +++ b/radio/src/gui/colorlcd/layout.h @@ -130,6 +130,4 @@ void loadDefaultLayout(); // intended for existing models void loadCustomScreens(); -void drawTrimsAndSliders(Layout::PersistentData * persistentData); - std::list & getRegisteredLayouts(); diff --git a/radio/src/gui/colorlcd/layouts/layout2+1.cpp b/radio/src/gui/colorlcd/layouts/layout2+1.cpp index 6e68d8e2e..9320ae624 100644 --- a/radio/src/gui/colorlcd/layouts/layout2+1.cpp +++ b/radio/src/gui/colorlcd/layouts/layout2+1.cpp @@ -73,7 +73,6 @@ class Layout2P1: public Layout Layout::decorate(HAS_TOPBAR(), HAS_SLIDERS(), HAS_TRIMS(), HAS_FM()); } - unsigned int getZonesCount() const override { return DIM(ZONES_LAYOUT_2P1); @@ -92,7 +91,6 @@ class Layout2P1: public Layout if (value != newValue) { value = newValue; // TODO call this from the Layout config window - this->clear(); decorate(); } } diff --git a/radio/src/gui/colorlcd/screen_setup.cpp b/radio/src/gui/colorlcd/screen_setup.cpp index d5e60bf57..1423557b5 100644 --- a/radio/src/gui/colorlcd/screen_setup.cpp +++ b/radio/src/gui/colorlcd/screen_setup.cpp @@ -21,6 +21,7 @@ #include #include "screen_setup.h" #include "opentx.h" +#include "view_main.h" #define SET_DIRTY() storageDirty(EE_MODEL) @@ -133,6 +134,108 @@ ScreenSetupPage::ScreenSetupPage(ScreenMenu * menu, uint8_t pageIndex): setTitle(title); } +class SetupWidgetsPageSlot: public Button +{ + public: + SetupWidgetsPageSlot(FormGroup * parent, const rect_t & rect, uint8_t pageIndex, uint8_t slotIndex): + Button(parent, rect), + pageIndex(pageIndex), + slotIndex(slotIndex) + { + setPressHandler([=](){ + Menu * menu = new Menu(this); + menu->addLine("Select a widget", [=]() { + Menu * menu = new Menu(this); + for (auto factory: getRegisteredWidgets()) { + menu->addLine(factory->getName(), [=]() { + if (widget) { + widget->deleteLater(); + } + // widget = factory->create(this, {1, 1, width() - 2, height() - 2}, &g_model.screenData[pageIndex].layoutData.zones[slotIndex].widgetData, true); + customScreens[pageIndex]->createWidget(slotIndex, factory); + return 0; + }); + } + return 0; + }); + if (widget /*g_model.screenData[pageIndex].layoutData.zones[slotIndex].widgetName[0]*/) { + menu->addLine(STR_DELETE, [=]() { + widget->deleteLater(); + widget = nullptr; + return 0; + }); + } + 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); + } + } + + protected: + uint8_t pageIndex; + uint8_t slotIndex; + Window * widget = nullptr; +}; + +class SetupWidgetsPage: public FormWindow +{ + public: + SetupWidgetsPage(uint8_t pageIndex): + FormWindow(MainWindow::instance(), {0, 0, LCD_W, LCD_H}, OPAQUE | FORM_FORWARD_FOCUS), + pageIndex(pageIndex) + { + Layer::push(this); + clearFocus(); + + auto & customScreen = customScreens[pageIndex]; + + for (unsigned i = 0; i < customScreen->getZonesCount(); i++) { + auto rect = customScreen->getZone(i); + new SetupWidgetsPageSlot(this, {rect.x - 1, rect.y - 1, rect.w + 2, rect.h + 2}, pageIndex, i); + } + } + + void deleteLater(bool detach = true, bool trash = true) override + { + Layer::pop(this); + +#if defined(HARDWARE_TOUCH) + Keyboard::hide(); +#endif + + Window::deleteLater(detach, trash); + } + +#if defined(HARDWARE_KEYS) + void onEvent(event_t event) override + { + TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event); + + if (event == EVT_KEY_LONG(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT)) { + killEvents(event); + deleteLater(); + SET_DIRTY(); + } + } +#endif + + void paint(BitmapBuffer * dc) override + { + dc->clear(DEFAULT_BGCOLOR); + } + + protected: + uint8_t pageIndex; +}; + void ScreenSetupPage::build(FormWindow * window) { FormGridLayout grid; @@ -154,10 +257,7 @@ void ScreenSetupPage::build(FormWindow * window) // Setup widgets button... setupWidgetsButton = new TextButton(window, grid.getFieldSlot(), STR_SETUP_WIDGETS); setupWidgetsButton->setPressHandler([=]() { -// auto setupWidgetsPage = new SetupWidgetsPage(); -// setupWidgetsPage->setCloseHandler([=]() { -// setupWidgetsButton->setFocus(); -// }); + new SetupWidgetsPage(pageIndex); return 0; }); grid.nextLine(); diff --git a/radio/src/gui/colorlcd/theme.cpp b/radio/src/gui/colorlcd/theme.cpp index 1b2f33a3c..1a9ba857c 100644 --- a/radio/src/gui/colorlcd/theme.cpp +++ b/radio/src/gui/colorlcd/theme.cpp @@ -242,5 +242,6 @@ MenuWindowContent * createMenuWindow(Menu * menu) DialogWindowContent * createDialogWindow(Dialog * dialog, const rect_t & rect) { + TRACE("createDialogWindow [%d, %d, %d, %d]", rect.x, rect.y, rect.w, rect.h); return new DialogWindowContent(dialog, rect); } diff --git a/radio/src/gui/colorlcd/widget.cpp b/radio/src/gui/colorlcd/widget.cpp index f377be0b6..a99a0f477 100644 --- a/radio/src/gui/colorlcd/widget.cpp +++ b/radio/src/gui/colorlcd/widget.cpp @@ -43,7 +43,7 @@ const WidgetFactory * getWidgetFactory(const char * name) return nullptr; } -Widget * loadWidget(const char * name, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData) +Widget * loadWidget(const char * name, FormGroup * parent, const rect_t & rect, Widget::PersistentData * 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 2014c3990..ca2196f0e 100644 --- a/radio/src/gui/colorlcd/widget.h +++ b/radio/src/gui/colorlcd/widget.h @@ -18,11 +18,11 @@ * GNU General Public License for more details. */ -#ifndef _WIDGET_H_ -#define _WIDGET_H_ +#pragma once #include #include +#include "form.h" #include "zone.h" #include "debug.h" @@ -34,15 +34,15 @@ #endif class WidgetFactory; -class Widget : public Window +class Widget : public FormField { public: struct PersistentData { ZoneOptionValueTyped options[MAX_WIDGET_OPTIONS] USE_IDX; }; - Widget(const WidgetFactory * factory, Window * parent, const rect_t & rect, PersistentData * persistentData): - Window(parent, rect), + Widget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, PersistentData * persistentData): + FormField(parent, rect), factory(factory), persistentData(persistentData) { @@ -116,7 +116,7 @@ class WidgetFactory } } - virtual Widget * create(Window * parent, const rect_t & rect, Widget::PersistentData * persistentData, bool init = true) const = 0; + virtual Widget * create(FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData, bool init = true) const = 0; protected: const char * name; @@ -132,7 +132,7 @@ class BaseWidgetFactory: public WidgetFactory { } - Widget * create(Window * parent, const rect_t & rect, Widget::PersistentData * persistentData, bool init = true) const override + Widget * create(FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData, bool init = true) const override { if (init) { initPersistentData(persistentData); @@ -147,8 +147,6 @@ inline const ZoneOption * Widget::getOptions() const return getFactory()->getOptions(); } -Widget * loadWidget(const char * name, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData); +Widget * loadWidget(const char * name, FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData); std::list & getRegisteredWidgets(); - -#endif // _WIDGET_H_ diff --git a/radio/src/gui/colorlcd/widgets/gauge.cpp b/radio/src/gui/colorlcd/widgets/gauge.cpp index b358db0e6..f69978467 100644 --- a/radio/src/gui/colorlcd/widgets/gauge.cpp +++ b/radio/src/gui/colorlcd/widgets/gauge.cpp @@ -23,7 +23,7 @@ class GaugeWidget: public Widget { public: - GaugeWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData): + GaugeWidget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData): Widget(factory, parent, rect, persistentData) { } @@ -55,15 +55,26 @@ class GaugeWidget: public Widget dc->drawSolidFilledRect(0, 16, width(), 16, FOCUS_COLOR); dc->drawNumber(0+width()/2, 17, percent, FONT(XS) | CUSTOM_COLOR | CENTERED, 0, nullptr, "%"); dc->invertRect(w, 16, width() - w, 16, CUSTOM_COLOR); + + if (hasFocus()) { + dc->clear(HIGHLIGHT_COLOR); + } } void checkEvents() override { + Widget::checkEvents(); + auto newValue = getValue(persistentData->options[0].value.unsignedValue); if (lastValue != newValue) { lastValue = newValue; invalidate(); } + + if (!hasFocus() && g_tmr10ms < 100) { + TRACE("ICI"); + setFocus(SET_FOCUS_FIRST); + } } static const ZoneOption options[]; diff --git a/radio/src/gui/colorlcd/widgets/modelbmp.cpp b/radio/src/gui/colorlcd/widgets/modelbmp.cpp index a7ee84117..43bd75ccc 100644 --- a/radio/src/gui/colorlcd/widgets/modelbmp.cpp +++ b/radio/src/gui/colorlcd/widgets/modelbmp.cpp @@ -23,7 +23,7 @@ class ModelBitmapWidget: public Widget { public: - ModelBitmapWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData): + ModelBitmapWidget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData): Widget(factory, parent, rect, persistentData), buffer(nullptr), deps_hash(0) @@ -65,6 +65,8 @@ class ModelBitmapWidget: public Widget void checkEvents() override { + Widget::checkEvents(); + uint32_t new_hash = hash(g_model.header.bitmap, sizeof(g_model.header.bitmap)); new_hash ^= hash(g_model.header.name, sizeof(g_model.header.name)); new_hash ^= hash(g_eeGeneral.themeName, sizeof(g_eeGeneral.themeName)); diff --git a/radio/src/gui/colorlcd/widgets/outputs.cpp b/radio/src/gui/colorlcd/widgets/outputs.cpp index bd223601b..97efed9b2 100644 --- a/radio/src/gui/colorlcd/widgets/outputs.cpp +++ b/radio/src/gui/colorlcd/widgets/outputs.cpp @@ -28,7 +28,7 @@ class OutputsWidget: public Widget { public: - OutputsWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData): + OutputsWidget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData): Widget(factory, parent, rect, persistentData) { } @@ -99,6 +99,7 @@ class OutputsWidget: public Widget void checkEvents() override { + Widget::checkEvents(); invalidate(); } diff --git a/radio/src/gui/colorlcd/widgets/text.cpp b/radio/src/gui/colorlcd/widgets/text.cpp index b1068bd78..7fecda88a 100644 --- a/radio/src/gui/colorlcd/widgets/text.cpp +++ b/radio/src/gui/colorlcd/widgets/text.cpp @@ -25,7 +25,7 @@ class TextWidget: public Widget { public: - TextWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData): + TextWidget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData): Widget(factory, parent, rect, persistentData) { } diff --git a/radio/src/gui/colorlcd/widgets/timer.cpp b/radio/src/gui/colorlcd/widgets/timer.cpp index cb570a675..ffc0f850e 100644 --- a/radio/src/gui/colorlcd/widgets/timer.cpp +++ b/radio/src/gui/colorlcd/widgets/timer.cpp @@ -23,7 +23,7 @@ class TimerWidget: public Widget { public: - TimerWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData): + TimerWidget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData): Widget(factory, parent, rect, persistentData) { } @@ -88,6 +88,7 @@ class TimerWidget: public Widget void checkEvents() override { + Widget::checkEvents(); auto newValue = timersStates[persistentData->options[0].value.unsignedValue].val; if (lastValue != newValue) { lastValue = newValue; diff --git a/radio/src/gui/colorlcd/widgets/value.cpp b/radio/src/gui/colorlcd/widgets/value.cpp index 8f3fa148b..99312d125 100644 --- a/radio/src/gui/colorlcd/widgets/value.cpp +++ b/radio/src/gui/colorlcd/widgets/value.cpp @@ -25,7 +25,7 @@ const coord_t NUMBERS_PADDING = 4; class ValueWidget: public Widget { public: - ValueWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData): + ValueWidget(const WidgetFactory * factory, FormGroup * parent, const rect_t & rect, Widget::PersistentData * persistentData): Widget(factory, parent, rect, persistentData) { } @@ -112,6 +112,8 @@ class ValueWidget: public Widget void checkEvents() override { + Widget::checkEvents(); + auto newValue = getValue(persistentData->options[0].value.unsignedValue); if (lastValue != newValue) { lastValue = newValue; diff --git a/radio/src/gui/colorlcd/widgets_container.h b/radio/src/gui/colorlcd/widgets_container.h index 341be934b..aefc22aa9 100644 --- a/radio/src/gui/colorlcd/widgets_container.h +++ b/radio/src/gui/colorlcd/widgets_container.h @@ -29,29 +29,14 @@ class WidgetsContainerInterface { public: virtual unsigned int getZonesCount() const = 0; - virtual rect_t getZone(unsigned int index) const = 0; - - inline Widget * getWidget(unsigned int index) - { - return widgets[index]; - } - - inline void setWidget(unsigned int index, Widget * widget) - { - widgets[index] = widget; - } - virtual void createWidget(unsigned int index, const WidgetFactory * factory) = 0; - - protected: - Widget ** widgets; }; #define WIDGET_NAME_LEN 10 template -class WidgetsContainer: public Window, public WidgetsContainerInterface +class WidgetsContainer: public FormGroup, public WidgetsContainerInterface { public: struct ZonePersistentData { @@ -65,7 +50,7 @@ class WidgetsContainer: public Window, public WidgetsContainerInterface }; WidgetsContainer(const rect_t & rect, PersistentData * persistentData): - Window(nullptr, rect), + FormGroup(nullptr, rect, FORM_FORWARD_FOCUS), persistentData(persistentData) { } @@ -96,7 +81,7 @@ class WidgetsContainer: public Window, public WidgetsContainerInterface char name[WIDGET_NAME_LEN + 1]; memset(name, 0, sizeof(name)); strncpy(name, persistentData->zones[i].widgetName, WIDGET_NAME_LEN); - // TODO widgets[i] = loadWidget(name, getZone(i), &persistentData->zones[i].widgetData); + widgets[i] = loadWidget(name, this, getZone(i), &persistentData->zones[i].widgetData); } else { widgets[i] = nullptr; @@ -115,11 +100,9 @@ class WidgetsContainer: public Window, public WidgetsContainerInterface virtual void background() { - if (widgets) { - for (int i = 0; i < N; i++) { - if (widgets[i]) { - widgets[i]->background(); - } + for (int i = 0; i < N; i++) { + if (widgets[i]) { + widgets[i]->background(); } } }