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; - } } }