Merge pull request #8415 from opentx/raphaelcoeffic/fix-confirm-dialog

2.4 Pot-pourri
This commit is contained in:
Bertrand Songis
2021-04-05 10:22:32 +02:00
committed by GitHub
41 changed files with 495 additions and 122 deletions
+3 -1
View File
@@ -21,6 +21,8 @@
// No include guards here, this file may be included many times in different namespaces
// i.e. BACKUP RAM Backup/Restore functions
#pragma once
#include <inttypes.h>
#include "board.h"
#include "dataconstants.h"
@@ -986,4 +988,4 @@ static inline void check_struct()
#undef CHKSIZE
}
#endif /* BACKUP */
#endif /* BACKUP */
+1
View File
@@ -23,6 +23,7 @@ set(GUI_SRC
topbar.cpp
layout.cpp
widget.cpp
widget_settings.cpp
${THEMES_SRC}
${LAYOUTS_SRC}
${WIDGETS_SRC}
+23 -15
View File
@@ -18,27 +18,35 @@
* GNU General Public License for more details.
*/
#include "opentx.h"
#include "confirm_dialog.h"
#include "static.h"
#include "gridlayout.h"
ConfirmDialog::ConfirmDialog(Window * parent, const char * title, const char * message, std::function<void(void)> confirmHandler) :
Dialog(parent, title, {50, 73, LCD_W - 100, LCD_H - 146}),
Dialog(parent, title, {LCD_W / 10 , LCD_H / 4, LCD_W - 2 * LCD_W / 10, LCD_H - 2 * LCD_H / 4}),
confirmHandler(std::move(confirmHandler))
{
new StaticText(this, {0, height() / 2, width(), PAGE_LINE_HEIGHT}, message, CENTERED);
}
auto form = &content->form;
FormGridLayout grid(content->form.width());
form->clear();
#if defined(HARDWARE_KEYS)
void ConfirmDialog::onEvent(event_t event)
{
TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event);
new StaticText(form, grid.getCenteredSlot(), message);
grid.setLabelWidth(15);
grid.setMarginRight(15);
grid.nextLine();
grid.nextLine();
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
deleteLater(); // this restore the focus (it can be changed then in confirmHandler)
confirmHandler();
}
else if (event == EVT_KEY_BREAK(KEY_EXIT)) {
deleteLater();
}
auto noButton = new TextButton(form, grid.getFieldSlot(2, 0), STR_NO, [=]() -> int8_t {
this->deleteLater();
return 0;
});
new TextButton(form, grid.getFieldSlot(2, 1), STR_YES, [=]() -> int8_t {
this->deleteLater();
this->confirmHandler();
return 0;
});
noButton->setFocus(SET_FOCUS_DEFAULT);
}
#endif
-4
View File
@@ -27,10 +27,6 @@ class ConfirmDialog: public Dialog {
public:
ConfirmDialog(Window * parent, const char * title, const char * message, std::function<void(void)> confirmHandler);
#if defined(HARDWARE_KEYS)
void onEvent(event_t event) override;
#endif
protected:
std::function<void(void)> confirmHandler;
};
-2
View File
@@ -130,6 +130,4 @@ void loadDefaultLayout();
// intended for existing models
void loadCustomScreens();
void drawTrimsAndSliders(Layout::PersistentData * persistentData);
std::list<const LayoutFactory *> & getRegisteredLayouts();
@@ -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();
}
}
+8 -1
View File
@@ -34,7 +34,14 @@ void ScreenMenu::updateTabs()
for (int index = 0; index < MAX_CUSTOM_SCREENS; index++) {
if (customScreens[index]) {
addTab(new ScreenSetupPage(this, index));
auto tab = new ScreenSetupPage(this, customScreens[index], g_model.screenData[index]);
std::string title(STR_MAIN_VIEW_X);
title.back() = index + '1';
tab->setTitle(title);
tab->setIcon(ICON_THEME_VIEW1 + index);
addTab(tab);
}
else {
addTab(new ScreenAddPage(this, index));
+1 -1
View File
@@ -31,7 +31,7 @@ class PageHeader: public FormGroup
PageHeader(Page * parent, uint8_t icon);
#if defined(HARDWARE_TOUCH)
void deleteLater(bool detach = true, bool trash = true)
void deleteLater(bool detach = true, bool trash = true) override
{
if (_deleted)
return;
+1 -1
View File
@@ -52,7 +52,7 @@ class FilePreview : public Window
}
#if defined(DEBUG_WINDOWS)
virtual std::string getName()
std::string getName() const override
{
return "FilePreview";
}
+148 -30
View File
@@ -21,27 +21,44 @@
#include <algorithm>
#include "screen_setup.h"
#include "opentx.h"
#include "view_main.h"
#include "widget_settings.h"
#define SET_DIRTY() storageDirty(EE_MODEL)
ScreenAddPage::ScreenAddPage(ScreenMenu * menu, uint8_t pageIndex):
PageTab("", ICON_THEME_ADD_VIEW),
PageTab(),
menu(menu),
pageIndex(pageIndex)
{
setTitle(STR_ADD_MAIN_VIEW);
setIcon(ICON_THEME_ADD_VIEW);
}
void ScreenAddPage::build(FormWindow * window)
{
auto button = new TextButton(window, {LCD_W / 2 - 100, (window->height() - 24) / 2, 200, 24}, STR_ADD_MAIN_VIEW);
button->setPressHandler([=]() {
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();
customScreens[pageIndex] = factory->create(&g_model.screenData[pageIndex].layoutData);
strncpy(g_model.screenData[pageIndex].layoutName, factory->getId(), sizeof(g_model.screenData[pageIndex].layoutName));
screen = factory->create(&screenData.layoutData);
strncpy(screenData.layoutName, factory->getId(), sizeof(screenData.layoutName));
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(new ScreenSetupPage(menu, pageIndex));
menu->addTab(tab);
menu->setCurrentTab(pageIndex);
if (pageIndex < MAX_CUSTOM_SCREENS - 1) {
menu->addTab(new ScreenAddPage(menu, pageIndex + 1));
}
@@ -123,16 +140,121 @@ class LayoutChoice: public FormField {
std::function<void(const LayoutFactory *)> setValue;
};
ScreenSetupPage::ScreenSetupPage(ScreenMenu * menu, uint8_t pageIndex):
PageTab("", ICON_THEME_VIEW1 + pageIndex),
ScreenSetupPage::ScreenSetupPage(ScreenMenu * menu, Layout*& screen, CustomScreenData& screenData):
PageTab(),
menu(menu),
pageIndex(pageIndex)
screen(screen),
screenData(screenData)
{
char title[] = "Main view X";
title[sizeof(title) - 2] = '1' + pageIndex;
setTitle(title);
}
class SetupWidgetsPageSlot: public Button
{
public:
SetupWidgetsPageSlot(FormGroup * parent, const rect_t & rect, Layout* screen, uint8_t slotIndex):
Button(parent, rect),
screen(screen),
slotIndex(slotIndex)
{
widget = screen->getWidget(slotIndex);
setPressHandler([=]() -> uint8_t {
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);
});
}
});
if (widget) {
menu->addLine(TR_WIDGET_SETTINGS, [=]() {
new WidgetSettings(this, widget);
});
menu->addLine(STR_REMOVE_WIDGET, [=]() {
widget->deleteLater();
widget = nullptr;
});
}
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:
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())
{
Layer::push(this);
clearFocus();
// attach this custom screen here so we can display it
screen->attach(this);
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);
}
}
void deleteLater(bool detach = true, bool trash = true) override
{
Layer::pop(this);
#if defined(HARDWARE_TOUCH)
Keyboard::hide();
#endif
// give it back to its old parent before it gets deleted
screen->attach(oldParent);
FormWindow::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
protected:
Layout* screen;
Window* oldParent;
void paint(BitmapBuffer * dc) override
{
dc->clear(DEFAULT_BGCOLOR);
}
};
void ScreenSetupPage::build(FormWindow * window)
{
FormGridLayout grid;
@@ -142,10 +264,10 @@ void ScreenSetupPage::build(FormWindow * window)
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(customScreens[pageIndex]->getFactory()), [=](const LayoutFactory *factory) {
delete customScreens[pageIndex];
customScreens[pageIndex] = factory->create(&g_model.screenData[pageIndex].layoutData);
strncpy(g_model.screenData[pageIndex].layoutName, factory->getId(), sizeof(g_model.screenData[pageIndex].layoutName));
layoutChoice = new LayoutChoice(window, layoutSlot, GET_VALUE(screen->getFactory()), [=](const LayoutFactory *factory) {
delete screen;
screen = factory->create(&screenData.layoutData);
strncpy(screenData.layoutName, factory->getId(), sizeof(CustomScreenData::layoutName));
SET_DIRTY();
updateLayoutOptions();
});
@@ -153,11 +275,8 @@ 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();
// });
setupWidgetsButton->setPressHandler([=]() -> uint8_t {
new SetupWidgetsPage(screen);
return 0;
});
grid.nextLine();
@@ -173,8 +292,6 @@ void ScreenSetupPage::updateLayoutOptions()
FormGridLayout grid;
optionsWindow->clear();
auto screen = customScreens[pageIndex];
// Layout options...
int index = 0;
for (auto * option = screen->getFactory()->getOptions(); option->name; option++, index++) {
@@ -199,19 +316,20 @@ void ScreenSetupPage::updateLayoutOptions()
grid.nextLine();
}
if (pageIndex > 0 || customScreens[1]) {
//if (pageIndex > 0 || customScreens[1]) {
auto button = new TextButton(optionsWindow, grid.getFieldSlot(), STR_REMOVE_SCREEN);
button->setPressHandler([=]() {
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));
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();
+5 -2
View File
@@ -19,6 +19,8 @@
*/
#include "menu_screen.h"
#include "layout.h"
#include "datastructs.h"
class ScreenAddPage: public PageTab {
public:
@@ -33,13 +35,14 @@ class ScreenAddPage: public PageTab {
class ScreenSetupPage: public PageTab {
public:
ScreenSetupPage(ScreenMenu * menu, uint8_t pageIndex);
ScreenSetupPage(ScreenMenu * menu, Layout*& screen, CustomScreenData& screenData);
void build(FormWindow * window) override;
protected:
ScreenMenu * menu;
uint8_t pageIndex;
Layout *& screen;
CustomScreenData& screenData;
FormGroup * optionsWindow = nullptr;
TextButton * setupWidgetsButton = nullptr;
FormField * layoutChoice = nullptr;
+12 -3
View File
@@ -82,11 +82,20 @@ class SpecialFunctionEditPage : public Page {
grid.nextLine();
break;
case FUNC_TRAINER:
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_TIMER);
new SourceChoice(specialFunctionOneWindow, grid.getFieldSlot(), 0, 4, GET_SET_DEFAULT(CFN_TIMER_INDEX(cfn)));
case FUNC_TRAINER: {
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
auto choice = new Choice(specialFunctionOneWindow, grid.getFieldSlot(), 0,NUM_STICKS + 1,GET_SET_DEFAULT(CFN_PARAM(cfn)));
choice->setTextHandler([=](int32_t value) {
if (value == 0)
return std::string(STR_STICKS);
else if (value == NUM_STICKS + 1)
return std::string(STR_CHANS);
else
return TEXT_AT_INDEX(STR_VSRCRAW, value);;
});
grid.nextLine();
break;
}
case FUNC_RESET:
if (CFN_PARAM(cfn) < FUNC_RESET_PARAM_FIRST_TELEM) {
+10 -1
View File
@@ -32,6 +32,10 @@ class PageTab {
friend class TabsGroup;
public:
PageTab()
{
}
PageTab(std::string title, unsigned icon):
title(std::move(title)),
icon(icon)
@@ -64,6 +68,11 @@ class PageTab {
title = std::move(value);
}
void setIcon(unsigned icon)
{
this->icon = icon;
}
unsigned getIcon() const
{
return icon;
@@ -71,7 +80,7 @@ class PageTab {
protected:
std::string title;
unsigned icon;
unsigned icon = 0;
std::function<void()> onPageDestroyed;
};
+1
View File
@@ -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);
}
+1 -1
View File
@@ -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) {
+23 -10
View File
@@ -18,11 +18,11 @@
* GNU General Public License for more details.
*/
#ifndef _WIDGET_H_
#define _WIDGET_H_
#pragma once
#include <list>
#include <string.h>
#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)
{
@@ -71,6 +71,21 @@ class Widget : public Window
return &persistentData->options[index].value;
}
inline void setOptionValue(unsigned int index, const ZoneOptionValue& value)
{
persistentData->options[index].value = value;
}
inline PersistentData * getPersistentData()
{
return persistentData;
}
void paint(BitmapBuffer * dc) override
{
FormField::paint(dc);
}
virtual void background()
{
}
@@ -116,7 +131,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 +147,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 +162,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<const WidgetFactory *> & getRegisteredWidgets();
#endif // _WIDGET_H_
+146
View File
@@ -0,0 +1,146 @@
/*
* 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"
#include "widget_settings.h"
static const rect_t widgetSettingsDialogRect = {
LCD_W / 10, // x
LCD_H / 4, // y
LCD_W - 2 * LCD_W / 10, // width
LCD_H - 2 * LCD_H / 4 // height
};
WidgetSettings::WidgetSettings(Window * parent, Widget * widget) :
Dialog(parent, TR_WIDGET_SETTINGS, widgetSettingsDialogRect)
{
setCloseWhenClickOutside(true);
auto form = &content->form;
FormGridLayout grid(content->form.width());
grid.setLabelWidth(width() / 3);
form->clear();
uint8_t optIdx = 0;
auto optPtr = widget->getOptions();
while (optPtr->name != nullptr) {
auto option = *optPtr;
new StaticText(form, grid.getLabelSlot(), option.name);
switch (option.type) {
case ZoneOption::Integer:
new NumberEdit(form, grid.getFieldSlot(), option.min.signedValue, option.max.signedValue,
[=]() -> int {
return widget->getOptionValue(optIdx)->signedValue;
},
[=](int32_t newValue) {
widget->setOptionValue(optIdx, OPTION_VALUE_SIGNED(newValue));
});
break;
case ZoneOption::Source:
new SourceChoice(form, grid.getFieldSlot(), 0, MIXSRC_LAST_TELEM,
[=]() -> int16_t {
return (int16_t) widget->getOptionValue(optIdx)->unsignedValue;
},
[=](int16_t newValue) {
widget->setOptionValue(optIdx, OPTION_VALUE_UNSIGNED((uint32_t) newValue));
});
break;
case ZoneOption::Bool:
new CheckBox(form, grid.getFieldSlot(),
[=]() -> uint8_t {
return (uint8_t) widget->getOptionValue(optIdx)->boolValue;
},
[=](int8_t newValue) {
widget->setOptionValue(optIdx, OPTION_VALUE_BOOL((uint32_t) newValue));
});
break;
case ZoneOption::String:
break;
case ZoneOption::File:
break;
case ZoneOption::TextSize:
break;
case ZoneOption::Timer: // Unsigned
{
auto tmChoice = new Choice(form, grid.getFieldSlot(), 0, TIMERS - 1,
[=]() -> int { // getValue
return (int) widget->getOptionValue(optIdx)->unsignedValue;
},
[=](int newValue) { // setValue
widget->setOptionValue(optIdx, OPTION_VALUE_UNSIGNED((uint32_t) newValue));
});
tmChoice->setTextHandler([](int value) {
return std::string(STR_TIMER) + std::to_string(value + 1);
});
}
break;
case ZoneOption::Switch:
new SwitchChoice(form, grid.getFieldSlot(),
option.min.unsignedValue, // min
option.max.unsignedValue, // max
[=]() -> int16_t { // getValue
return (uint8_t) widget->getOptionValue(optIdx)->unsignedValue;
},
[=](int16_t newValue) { // setValue
widget->setOptionValue(optIdx, OPTION_VALUE_UNSIGNED((uint32_t) newValue));
});
break;
case ZoneOption::Color:
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));
});
break;
}
optIdx++;
optPtr++;
grid.nextLine();
}
}
#if defined(HARDWARE_KEYS)
void WidgetSettings::onEvent(event_t event)
{
TRACE_WINDOWS("%s received event 0x%X", getWindowDebugString().c_str(), event);
if (event == EVT_KEY_LONG(KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT)) {
deleteLater();
}
}
#endif
+36
View File
@@ -0,0 +1,36 @@
/*
* 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 "dialog.h"
#include "widget.h"
class WidgetSettings: public Dialog
{
std::function<void(void)> confirmHandler;
public:
WidgetSettings(Window * parent, Widget * widget);
#if defined(HARDWARE_KEYS)
void onEvent(event_t event) override;
#endif
};
+12 -1
View File
@@ -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[];
+3 -1
View File
@@ -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));
+2 -1
View File
@@ -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();
}
+1 -1
View File
@@ -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)
{
}
+2 -1
View File
@@ -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;
+3 -1
View File
@@ -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;
+22 -29
View File
@@ -29,29 +29,15 @@ 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;
virtual Widget * createWidget(unsigned int index, const WidgetFactory * factory) = 0;
virtual Widget * getWidget(unsigned int index) = 0;
};
#define WIDGET_NAME_LEN 10
template<int N, int O>
class WidgetsContainer: public Window, public WidgetsContainerInterface
class WidgetsContainer: public FormGroup, public WidgetsContainerInterface
{
public:
struct ZonePersistentData {
@@ -65,21 +51,30 @@ class WidgetsContainer: public Window, public WidgetsContainerInterface
};
WidgetsContainer(const rect_t & rect, PersistentData * persistentData):
Window(nullptr, rect),
FormGroup(nullptr, rect, FORM_FORWARD_FOCUS),
persistentData(persistentData)
{
}
void createWidget(unsigned int index, const WidgetFactory * factory) override
Widget * createWidget(unsigned int index, const WidgetFactory * factory) override
{
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));
widgets[index] = factory->create(this, getZone(index), &persistentData->zones[index].widgetData);
}
else {
widgets[index] = nullptr;
widget = factory->create(this, getZone(index), &persistentData->zones[index].widgetData);
}
widgets[index] = widget;
return widget;
}
Widget * getWidget(unsigned int index) override
{
if (index < N)
return widgets[index];
return nullptr;
}
virtual void create()
@@ -96,7 +91,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 +110,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();
}
}
}
+1 -1
View File
@@ -328,7 +328,7 @@ if(PYTHONINTERP_FOUND)
add_custom_command(
OUTPUT ${PROJECT_BINARY_DIR}/radio/src/datacopy.cpp
WORKING_DIRECTORY ${RADIO_DIRECTORY}/src
COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/generate_datacopy.py datastructs.h -DPCBHORUS -DPCBX10 -DCPUARM -DSTM32F4 -DSTM32F429_439xx -DCOLORLCD -DBACKUP -DSIMU -I. -Igui/colorlcd -Itargets/horus -Itargets/common/arm/stm32 -I${THIRDPARTY_DIR} -I${THIRDPARTY_DIR}/libopenui/src -I${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries/STM32F4xx_StdPeriph_Driver/inc -I${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries/CMSIS/Device/ST/STM32F4xx/Include -I${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries/CMSIS/Include ${arm_gcc_include_path} > ${PROJECT_BINARY_DIR}/radio/src/datacopy.cpp
COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/generate_datacopy.py datastructs.h -DPCBHORUS -DPCBX10 -DCPUARM -DSTM32F4 -DSTM32F429_439xx -DCOLORLCD -DBACKUP -DSIMU -I. -Igui/colorlcd -Itargets/horus -Itargets/common/arm/stm32 -I${THIRDPARTY_DIR} -I${THIRDPARTY_DIR}/libopenui/src -I${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries/STM32F4xx_StdPeriph_Driver/inc -I${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries/CMSIS/Device/ST/STM32F4xx/Include -I${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries/CMSIS/Include ${arm_gcc_include_path} -Wno-pragma-once-outside-header > ${PROJECT_BINARY_DIR}/radio/src/datacopy.cpp
DEPENDS ${RADIO_DIRECTORY}/src/datastructs.h ${RADIO_DIRECTORY}/util/generate_datacopy.py
)
+2
View File
@@ -110,6 +110,8 @@ ISTR(SUBTRIMMODES);
const char STR_POPUPS_ENTER_EXIT[] = TR_POPUPS_ENTER_EXIT;
const char STR_OK[] = TR_OK;
const char STR_FREE[] = TR_FREE;
const char STR_YES[] = TR_YES;
const char STR_NO[] = TR_NO;
const char STR_DELETEMODEL[] = TR_DELETEMODEL;
const char STR_COPYINGMODEL[] = TR_COPYINGMODEL;
const char STR_MOVINGMODEL[] = TR_MOVINGMODEL;
+2
View File
@@ -207,6 +207,8 @@ extern const char STR_NO_TELEMETRY_SCREENS[];
#endif
extern const char STR_FREE[];
extern const char STR_YES[];
extern const char STR_NO[];
#define LEN_FREE PSIZE(TR_FREE)
extern const char STR_DELETEMODEL[];
extern const char STR_COPYINGMODEL[];
+2 -1
View File
@@ -348,6 +348,8 @@
#define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define TR_FREE "空闲"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "删除" BREAKSPACE "模型"
#define TR_COPYINGMODEL "复制模型..."
#define TR_MOVINGMODEL "移动模型..."
@@ -1124,7 +1126,6 @@
#define TR_USER_INTERFACE "用户界面"
#define TR_THEME "主题"
#define TR_SETUP "设置"
#define TR_MAINVIEWX "Main view X"
#define TR_LAYOUT "布局"
#define TR_ADD_MAIN_VIEW "添加主视图"
#define TR_BACKGROUND_COLOR "背景颜色"
+2 -1
View File
@@ -423,6 +423,8 @@
#define TR_MENUWHENDONE CENTER "\011" TR_ENTER " > DALŠÍ"
#define TR_FREE TR("volné:", "volných")
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "SMAZAT" BREAKSPACE "MODEL"
#define TR_COPYINGMODEL "Kopíruji model.."
#define TR_MOVINGMODEL "Přesouvám model."
@@ -1224,7 +1226,6 @@
#define TR_USER_INTERFACE "Uživatelké rozhraní"
#define TR_THEME "Téma"
#define TR_SETUP "Nastavení"
#define TR_MAINVIEWX "Hlavní panel X"
#define TR_LAYOUT "Rozložení"
#define TR_ADD_MAIN_VIEW "Přidat hlavní panel"
#define TR_BACKGROUND_COLOR "Barva pozadí"
+2 -1
View File
@@ -428,6 +428,8 @@
#endif
#define TR_FREE "frei"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "Modell löschen?"
#define TR_COPYINGMODEL "Kopiere Modell"
#define TR_MOVINGMODEL "Schiebe Modell"
@@ -1233,7 +1235,6 @@
#define TR_USER_INTERFACE "User interface"
#define TR_THEME "Theme"
#define TR_SETUP "Setup"
#define TR_MAINVIEWX "Ansicht X"
#define TR_LAYOUT "Layout"
#define TR_ADD_MAIN_VIEW "Ansicht hinzufügen"
#define TR_BACKGROUND_COLOR "Hintergrundfarbe"
+2 -1
View File
@@ -427,6 +427,8 @@
#endif
#define TR_FREE "free"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "DELETE" BREAKSPACE "MODEL"
#define TR_COPYINGMODEL "Copying model..."
#define TR_MOVINGMODEL "Moving model..."
@@ -1239,7 +1241,6 @@
#define TR_USER_INTERFACE "User interface"
#define TR_THEME "Theme"
#define TR_SETUP "Setup"
#define TR_MAINVIEWX "Main view X"
#define TR_LAYOUT "Layout"
#define TR_ADD_MAIN_VIEW "Add main view"
#define TR_BACKGROUND_COLOR "Background color"
+2 -1
View File
@@ -426,6 +426,8 @@
#define TR_MENUWHENDONE CENTER "\007" TR_ENTER " AL ACABAR "
#define TR_FREE "libre"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "BORRAR MODELO"
#define TR_COPYINGMODEL "Copiando modelo.."
#define TR_MOVINGMODEL "Moviendo modelo..."
@@ -1232,7 +1234,6 @@
#define TR_USER_INTERFACE "Interfaz"
#define TR_THEME "Tema"
#define TR_SETUP "Configuración"
#define TR_MAINVIEWX "Vista pral. X"
#define TR_LAYOUT "Diseño"
#define TR_ADD_MAIN_VIEW "Añadir vista pral."
#define TR_BACKGROUND_COLOR "Color de fondo"
+2
View File
@@ -436,6 +436,8 @@
#define TR_MENUWHENDONE CENTER "\006" TR_ENTER " WHEN DONE"
#define TR_FREE "free"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "DELETE MODEL"
#define TR_COPYINGMODEL "Copying model..."
#define TR_MOVINGMODEL "Moving model..."
+2 -1
View File
@@ -446,6 +446,8 @@
#define TR_MENUWHENDONE CENTER "\006" TR_ENTER " QUAND PRET"
#define TR_FREE "disp"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "SUPPRIMER" BREAKSPACE "MODELE"
#define TR_COPYINGMODEL "Copie..."
#define TR_MOVINGMODEL "Déplacement..."
@@ -1263,7 +1265,6 @@
#define TR_USER_INTERFACE "Interface utilisateur"
#define TR_THEME "Thème"
#define TR_SETUP "Configuration"
#define TR_MAINVIEWX "Vue principale X"
#define TR_LAYOUT "Disposition"
#define TR_ADD_MAIN_VIEW "Ajouter vue principale"
#define TR_BACKGROUND_COLOR "Couleur de fond"
+2 -1
View File
@@ -451,6 +451,8 @@
#define TR_MENUWHENDONE CENTER "\007" TR_ENTER " Conferma"
#define TR_FREE "Disp."
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "CANCELLA" BREAKSPACE "MODELLO"
#define TR_COPYINGMODEL "Copia in corso.."
#define TR_MOVINGMODEL "Spostamento..."
@@ -1252,7 +1254,6 @@
#define TR_USER_INTERFACE "Interfaccia utente"
#define TR_THEME "Tema"
#define TR_SETUP "Imposta"
#define TR_MAINVIEWX "Vista princ. X"
#define TR_LAYOUT "Layout"
#define TR_ADD_MAIN_VIEW "Aggiungi vista princ."
#define TR_BACKGROUND_COLOR "Colore background"
+2 -1
View File
@@ -427,6 +427,8 @@
#endif
#define TR_FREE "vrij"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "WIS" BREAKSPACE "MODEL"
#define TR_COPYINGMODEL "Kopieer Model"
#define TR_MOVINGMODEL "Verplaats Model"
@@ -1238,7 +1240,6 @@
#define TR_USER_INTERFACE "User interface"
#define TR_THEME "Theme"
#define TR_SETUP "Setup"
#define TR_MAINVIEWX "Main view X"
#define TR_LAYOUT "Layout"
#define TR_ADD_MAIN_VIEW "Add main view"
#define TR_BACKGROUND_COLOR "Background color"
+2 -1
View File
@@ -447,6 +447,8 @@
#define TR_MENUWHENDONE CENTER "\006" TR_ENTER " > DALEJ"
#define TR_FREE "woln"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "SKASUJ MODEL"
#define TR_COPYINGMODEL "Kopiuj model.."
#define TR_MOVINGMODEL "Przenieś model."
@@ -1248,7 +1250,6 @@
#define TR_USER_INTERFACE "User interface"
#define TR_THEME "Theme"
#define TR_SETUP "Setup"
#define TR_MAINVIEWX "Main view X"
#define TR_LAYOUT "Layout"
#define TR_ADD_MAIN_VIEW "Add main view"
#define TR_BACKGROUND_COLOR "Background color"
+2 -1
View File
@@ -440,6 +440,8 @@
#define TR_MENUWHENDONE CENTER"\006" TR_ENTER "QDO PRONTO"
#define TR_FREE "Livre"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "EXCLUI MODELO"
#define TR_COPYINGMODEL "Copiando modelo"
#define TR_MOVINGMODEL "Movendo modelo"
@@ -1248,7 +1250,6 @@
#define TR_USER_INTERFACE "User interface"
#define TR_THEME "Theme"
#define TR_SETUP "Setup"
#define TR_MAINVIEWX "Main view X"
#define TR_LAYOUT "Layout"
#define TR_ADD_MAIN_VIEW "Add main view"
#define TR_BACKGROUND_COLOR "Background color"
+2 -1
View File
@@ -445,6 +445,8 @@
#define TR_MENUWHENDONE CENTER "\011" TR_ENTER " Avslutar "
#define TR_FREE "kvar"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "Radera Modell"
#define TR_COPYINGMODEL "Kopierar Modell "
#define TR_MOVINGMODEL "Flyttar Modell "
@@ -1251,7 +1253,6 @@
#define TR_USER_INTERFACE "User interface"
#define TR_THEME "Theme"
#define TR_SETUP "Setup"
#define TR_MAINVIEWX "Main view X"
#define TR_LAYOUT "Layout"
#define TR_ADD_MAIN_VIEW "Add main view"
#define TR_BACKGROUND_COLOR "Background color"
+2 -1
View File
@@ -348,6 +348,8 @@
#define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define TR_FREE "空閒"
#define TR_YES "Yes"
#define TR_NO "No"
#define TR_DELETEMODEL "刪除" BREAKSPACE "模型"
#define TR_COPYINGMODEL "複製模型..."
#define TR_MOVINGMODEL "移動模型..."
@@ -1132,7 +1134,6 @@
#define TR_USER_INTERFACE "用戶界面"
#define TR_THEME "主題"
#define TR_SETUP "設置"
#define TR_MAINVIEWX "Main view X"
#define TR_LAYOUT "佈局"
#define TR_ADD_MAIN_VIEW "添加主視圖"
#define TR_BACKGROUND_COLOR "背景顏色"