diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index 5a2050217..8fbd82e6a 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -52,7 +52,6 @@ set(GUI_SRC switchchoice.cpp tabsgroup.cpp theme_manager.cpp - theme.cpp topbar.cpp view_about.cpp view_channels.cpp diff --git a/radio/src/gui/colorlcd/channel_bar.h b/radio/src/gui/colorlcd/channel_bar.h index c1b6adc40..36681deab 100644 --- a/radio/src/gui/colorlcd/channel_bar.h +++ b/radio/src/gui/colorlcd/channel_bar.h @@ -31,7 +31,7 @@ class ChannelBar : public Window LcdColorIndex textColorIndex = COLOR_THEME_SECONDARY1_INDEX); static LAYOUT_VAL(BAR_HEIGHT, 13, 13) - static LAYOUT_VAL(LMARGIN, 15, 15) + static LAYOUT_VAL(LMARGIN, 2, 2) static LAYOUT_VAL(TMARGIN, 2, 2) static LAYOUT_VAL(VAL_W, 45, 45) diff --git a/radio/src/gui/colorlcd/color_picker.cpp b/radio/src/gui/colorlcd/color_picker.cpp index 97e27c946..7f1ac80c6 100644 --- a/radio/src/gui/colorlcd/color_picker.cpp +++ b/radio/src/gui/colorlcd/color_picker.cpp @@ -158,7 +158,7 @@ class ColorEditorPopup : public BaseDialog ColorPicker::ColorPicker(Window* parent, const rect_t& rect, std::function getValue, std::function setValue) : - Button(parent, {0, 0, ColorEditorPopup::COLOR_PAD_WIDTH, ColorEditorPopup::COLOR_PAD_HEIGHT}), + Button(parent, {rect.x, rect.y, ColorEditorPopup::COLOR_PAD_WIDTH, ColorEditorPopup::COLOR_PAD_HEIGHT}), setValue(std::move(setValue)) { updateColor(getValue()); diff --git a/radio/src/gui/colorlcd/curveedit.cpp b/radio/src/gui/colorlcd/curveedit.cpp index 7fad54c25..cad77b8b9 100644 --- a/radio/src/gui/colorlcd/curveedit.cpp +++ b/radio/src/gui/colorlcd/curveedit.cpp @@ -165,7 +165,7 @@ void CurveDataEdit::update() auto form = new Window(this, rect_t{}); form->padAll(PAD_ZERO); - form->padBottom(4); + form->padBottom(PAD_SMALL); form->setFlexLayout(); FlexGridLayout grid(default_col_dsc, default_row_dsc); diff --git a/radio/src/gui/colorlcd/file_carosell.cpp b/radio/src/gui/colorlcd/file_carosell.cpp index a99badfa5..285096493 100644 --- a/radio/src/gui/colorlcd/file_carosell.cpp +++ b/radio/src/gui/colorlcd/file_carosell.cpp @@ -59,12 +59,9 @@ void FileCarosell::setSelected(int n) fp->setFile(""); } - if (selected == -1) { - lv_obj_clear_flag(message->getLvObj(), LV_OBJ_FLAG_HIDDEN); + message->show(selected == -1); + if (selected == -1) message->setText(_fileNames.size() > 0 ? STR_LOADING : STR_NO_THEME_IMAGE); - } else { - lv_obj_add_flag(message->getLvObj(), LV_OBJ_FLAG_HIDDEN); - } } void FileCarosell::checkEvents() diff --git a/radio/src/gui/colorlcd/fm_matrix.cpp b/radio/src/gui/colorlcd/fm_matrix.cpp index bcd712a50..385d48f28 100644 --- a/radio/src/gui/colorlcd/fm_matrix.cpp +++ b/radio/src/gui/colorlcd/fm_matrix.cpp @@ -24,14 +24,6 @@ #include "opentx.h" #include "themes/etx_lv_theme.h" -#if PORTRAIT_LCD -#define FM_COLS 3 -#define FM_ROWS 3 -#else -#define FM_COLS 5 -#define FM_ROWS 2 -#endif - template FMMatrix::FMMatrix(Window* parent, const rect_t& r, T* input) : ButtonMatrix(parent, r), input(input) diff --git a/radio/src/gui/colorlcd/fm_matrix.h b/radio/src/gui/colorlcd/fm_matrix.h index df4172734..08c70321d 100644 --- a/radio/src/gui/colorlcd/fm_matrix.h +++ b/radio/src/gui/colorlcd/fm_matrix.h @@ -35,6 +35,8 @@ struct FMMatrix : public ButtonMatrix { void setTextAndState(uint8_t btn_id); static LAYOUT_VAL(FM_BTN_W, 48, 48) + static LAYOUT_VAL(FM_COLS, 5, 3) + static LAYOUT_VAL(FM_ROWS, 2, 3) }; extern template struct FMMatrix; diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.cpp b/radio/src/gui/colorlcd/fullscreen_dialog.cpp index a29823ed4..608f36c34 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.cpp +++ b/radio/src/gui/colorlcd/fullscreen_dialog.cpp @@ -25,31 +25,10 @@ #include "libopenui.h" #include "mainwindow.h" #include "opentx.h" -#include "theme.h" #include "themes/etx_lv_theme.h" #include "view_main.h" #include "hal/watchdog_driver.h" -#if !PORTRAIT_LCD -constexpr uint32_t ALERT_FRAME_TOP = 50; -constexpr uint32_t ALERT_FRAME_HEIGHT = (LCD_H - 120); -constexpr uint32_t ALERT_BITMAP_TOP = ALERT_FRAME_TOP + 25; -constexpr uint32_t ALERT_BITMAP_LEFT = 20; -constexpr uint32_t ALERT_TITLE_TOP = ALERT_FRAME_TOP + 5; -constexpr uint32_t ALERT_TITLE_LEFT = 146; -constexpr uint32_t ALERT_MESSAGE_TOP = ALERT_TITLE_TOP + 85; -constexpr uint32_t ALERT_MESSAGE_LEFT = ALERT_TITLE_LEFT; -#else -constexpr uint32_t ALERT_FRAME_TOP = 70; -constexpr uint32_t ALERT_FRAME_HEIGHT = (LCD_H - 2 * ALERT_FRAME_TOP); -constexpr uint32_t ALERT_BITMAP_TOP = ALERT_FRAME_TOP + 15; -constexpr uint32_t ALERT_BITMAP_LEFT = 15; -constexpr uint32_t ALERT_TITLE_TOP = ALERT_FRAME_TOP + 10; -constexpr uint32_t ALERT_TITLE_LEFT = 140; -constexpr uint32_t ALERT_MESSAGE_TOP = ALERT_TITLE_TOP + 130; -constexpr uint32_t ALERT_MESSAGE_LEFT = 15; -#endif - FullScreenDialog::FullScreenDialog( uint8_t type, std::string title, std::string message, std::string action, const std::function& confirmHandler) : diff --git a/radio/src/gui/colorlcd/fullscreen_dialog.h b/radio/src/gui/colorlcd/fullscreen_dialog.h index c5c1d9ba2..bc0962d95 100644 --- a/radio/src/gui/colorlcd/fullscreen_dialog.h +++ b/radio/src/gui/colorlcd/fullscreen_dialog.h @@ -58,6 +58,15 @@ class FullScreenDialog : public Window void closeDialog(); + static LAYOUT_VAL(ALERT_FRAME_TOP, 50, 70) + static LAYOUT_VAL(ALERT_FRAME_HEIGHT, LCD_H - 120, LCD_H - 2 * ALERT_FRAME_TOP) + static LAYOUT_VAL(ALERT_BITMAP_TOP, ALERT_FRAME_TOP + 25, ALERT_FRAME_TOP + 15) + static LAYOUT_VAL(ALERT_BITMAP_LEFT, 20, 15) + static LAYOUT_VAL(ALERT_TITLE_TOP, ALERT_FRAME_TOP + 5, ALERT_FRAME_TOP + 10) + static LAYOUT_VAL(ALERT_TITLE_LEFT, 146, 140) + static LAYOUT_VAL(ALERT_MESSAGE_TOP, ALERT_TITLE_TOP + 85, ALERT_TITLE_TOP + 130) + static LAYOUT_VAL(ALERT_MESSAGE_LEFT, ALERT_TITLE_LEFT, 15) + protected: uint8_t type; std::string title; diff --git a/radio/src/gui/colorlcd/function_switches.cpp b/radio/src/gui/colorlcd/function_switches.cpp index 79c5e91f6..54c2a2fe8 100644 --- a/radio/src/gui/colorlcd/function_switches.cpp +++ b/radio/src/gui/colorlcd/function_switches.cpp @@ -49,21 +49,21 @@ class FunctionSwitch : public Window { public: FunctionSwitch(Window* parent, uint8_t sw) : - Window(parent, {0, 0, LCD_W - PAD_SMALL * 2, 36}), switchIndex(sw) + Window(parent, {0, 0, LCD_W - PAD_SMALL * 2, EdgeTxStyles::UI_ELEMENT_HEIGHT + PAD_TINY_GAP * 2}), switchIndex(sw) { - padAll(PAD_TINY); + padAll(PAD_TINY_GAP); std::string s(STR_CHAR_SWITCH); s += switchGetName(switchIndex + switchGetMaxSwitches()); - new StaticText(this, {8, 6, SW_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, s, + new StaticText(this, {PAD_LARGE, PAD_MEDIUM, SW_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, s, COLOR_THEME_PRIMARY1); - new ModelTextEdit(this, {NM_X, 0, NM_W, 32}, + new ModelTextEdit(this, {NM_X, 0, NM_W, 0}, g_model.switchNames[switchIndex], LEN_SWITCH_NAME); typeChoice = new Choice( - this, {TP_X, 0, TP_W, 32}, STR_SWTYPES, SWITCH_NONE, SWITCH_2POS, + this, {TP_X, 0, TP_W, 0}, STR_SWTYPES, SWITCH_NONE, SWITCH_2POS, [=]() { return FSWITCH_CONFIG(switchIndex); }, [=](int val) { FSWITCH_SET_CONFIG(switchIndex, val); @@ -81,7 +81,7 @@ class FunctionSwitch : public Window }); groupChoice = new Choice( - this, {GR_X, 0, GR_W, 32}, STR_FUNCTION_SWITCH_GROUPS, 0, 3, + this, {GR_X, 0, GR_W, 0}, STR_FUNCTION_SWITCH_GROUPS, 0, 3, [=]() { return FSWITCH_GROUP(switchIndex); }, [=](int group) { int oldGroup = FSWITCH_GROUP(switchIndex); @@ -109,7 +109,7 @@ class FunctionSwitch : public Window }); startChoice = new Choice( - this, {ST_X, 0, ST_W, 32}, _fct_sw_start, 0, 2, + this, {ST_X, 0, ST_W, 0}, _fct_sw_start, 0, 2, [=]() { return FSWITCH_STARTUP(switchIndex); }, [=](int val) { FSWITCH_SET_STARTUP(switchIndex, val); @@ -157,16 +157,16 @@ class SwitchGroup : public Window { public: SwitchGroup(Window* parent, uint8_t group) : - Window(parent, {0, 0, LCD_W - PAD_SMALL * 2, 36}), groupIndex(group) + Window(parent, {0, 0, LCD_W - PAD_SMALL * 2, EdgeTxStyles::UI_ELEMENT_HEIGHT + PAD_TINY_GAP * 2}), groupIndex(group) { - padAll(PAD_TINY); + padAll(PAD_TINY_GAP); - new StaticText(this, {0, 6, NM_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, + new StaticText(this, {0, PAD_MEDIUM, NM_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, STR_FUNCTION_SWITCH_GROUPS[groupIndex], COLOR_THEME_PRIMARY1); auto btn = new TextButton( - this, {AO_X, 0, AO_W, 32}, STR_GROUP_ALWAYS_ON, [=]() -> int8_t { + this, {AO_X, 0, AO_W, 0}, STR_GROUP_ALWAYS_ON, [=]() -> int8_t { int groupAlwaysOn = IS_FSWITCH_GROUP_ON(groupIndex); groupAlwaysOn ^= 1; SET_FSWITCH_GROUP_ON(groupIndex, groupAlwaysOn); @@ -177,11 +177,11 @@ class SwitchGroup : public Window }); btn->check(IS_FSWITCH_GROUP_ON(groupIndex)); - new StaticText(this, {SL_X, 6, SL_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, STR_SWITCH_STARTUP, + new StaticText(this, {SL_X, PAD_MEDIUM, SL_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, STR_SWITCH_STARTUP, COLOR_THEME_PRIMARY1); startChoice = new Choice( - this, {ST_X, 0, ST_W, 32}, STR_FSSWITCHES, 0, + this, {ST_X, 0, ST_W, 0}, STR_FSSWITCHES, 0, NUM_FUNCTIONS_SWITCHES + 1, [=]() { return groupDefaultSwitch(groupIndex) + 1; }, [=](int sw) { @@ -256,7 +256,7 @@ ModelFunctionSwitches::ModelFunctionSwitches() : Page(ICON_MODEL_SETUP) new StaticText(line, rect_t{}, STR_MORE_INFO, COLOR_THEME_PRIMARY1); line = body->newLine(grid1); - line->padBottom(10); + line->padBottom(PAD_LARGE); line->padLeft((width() - 150) / 2); auto qr = lv_qrcode_create(line->getLvObj(), 150, diff --git a/radio/src/gui/colorlcd/hw_inputs.cpp b/radio/src/gui/colorlcd/hw_inputs.cpp index acd0bcbeb..ca2cf37d6 100644 --- a/radio/src/gui/colorlcd/hw_inputs.cpp +++ b/radio/src/gui/colorlcd/hw_inputs.cpp @@ -108,14 +108,14 @@ HWPots::HWPots(Window* parent) : // if (!globalData.flyskygimbals && (i >= (NUM_POTS - 2))) continue; // #endif new StaticText(this, - rect_t{P_LBL_X, P_Y(i) + yo + PAD_MEDIUM, P_LBL_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, + rect_t{P_LBL_X, P_Y(i) + yo + PAD_MEDIUM, P_LBL_W, 0}, adcGetInputLabel(ADC_INPUT_FLEX, i)); new HWInputEdit(this, (char*)analogGetCustomLabel(ADC_INPUT_FLEX, i), LEN_ANA_NAME, P_NM_X, P_Y(i) + yo); auto pot = new Choice( - this, rect_t{P_TYP_X, P_Y(i) + P_OFST_Y + yo, P_TYP_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, + this, rect_t{P_TYP_X, P_Y(i) + P_OFST_Y + yo, P_TYP_W, 0}, STR_POTTYPES, FLEX_NONE, FLEX_SWITCH, [=]() -> int { return getPotType(i); }, [=](int newValue) { @@ -132,7 +132,7 @@ HWPots::HWPots(Window* parent) : pot->setAvailableHandler([=](int val) { return isPotTypeAvailable(val); }); auto tgl = new ToggleSwitch( - this, rect_t{P_INV_X, P_Y(i) + P_OFST_Y + yo, P_INV_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, + this, rect_t{P_INV_X, P_Y(i) + P_OFST_Y + yo, P_INV_W, 0}, [=]() -> uint8_t { return (uint8_t)getPotInversion(i); }, [=](int8_t newValue) { setPotInversion(i, newValue); @@ -151,7 +151,7 @@ class SwitchDynamicLabel : public StaticText { public: SwitchDynamicLabel(Window* parent, uint8_t index, coord_t x, coord_t y) : - StaticText(parent, rect_t{x, y, HWSwitches::SW_CTRL_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, ""), + StaticText(parent, rect_t{x, y, HWSwitches::SW_CTRL_W, 0}, ""), index(index) { checkEvents(); @@ -217,7 +217,7 @@ HWSwitches::HWSwitches(Window* parent) : Choice* channel = nullptr; if (switchIsFlex(i)) { channel = new Choice( - this, rect_t{x, i * SW_CTRL_H + PAD_TINY, SW_CTRL_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, -1, + this, rect_t{x, i * SW_CTRL_H + PAD_TINY, SW_CTRL_W, 0}, -1, adcGetMaxInputs(ADC_INPUT_FLEX) - 1, [=]() -> int { return switchGetFlexConfig(i); }, [=](int newValue) { switchConfigFlex(i, newValue); }); @@ -232,7 +232,7 @@ HWSwitches::HWSwitches(Window* parent) : } auto sw_cfg = new Choice( - this, rect_t{x, i * SW_CTRL_H + PAD_TINY, SW_CTRL_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, + this, rect_t{x, i * SW_CTRL_H + PAD_TINY, SW_CTRL_W, 0}, STR_SWTYPES, SWITCH_NONE, switchGetMaxType(i), [=]() -> int { return SWITCH_CONFIG(i); }, [=](int newValue) { diff --git a/radio/src/gui/colorlcd/layout.cpp b/radio/src/gui/colorlcd/layout.cpp index be5d16c84..60a4900ac 100644 --- a/radio/src/gui/colorlcd/layout.cpp +++ b/radio/src/gui/colorlcd/layout.cpp @@ -20,7 +20,6 @@ */ #include "opentx.h" -#include "theme.h" #include "topbar_impl.h" #include "view_main.h" diff --git a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp index 46afc2a5c..4fd599e9a 100644 --- a/radio/src/gui/colorlcd/layouts/topbar_impl.cpp +++ b/radio/src/gui/colorlcd/layouts/topbar_impl.cpp @@ -21,7 +21,7 @@ #include "topbar_impl.h" #include "opentx.h" -#include "theme.h" +#include "theme_manager.h" #include "view_main.h" constexpr uint32_t TOPBAR_REFRESH = 1000 / 10; // 10 Hz diff --git a/radio/src/gui/colorlcd/menu_model.cpp b/radio/src/gui/colorlcd/menu_model.cpp index 67f32fa22..bd2a14827 100644 --- a/radio/src/gui/colorlcd/menu_model.cpp +++ b/radio/src/gui/colorlcd/menu_model.cpp @@ -66,7 +66,13 @@ void ModelMenu::build() addTab(new ModelTelemetryPage()); #if defined(PCBNV14) || defined(PCBPL18) - addGoToMonitorsButton(); + new TextButton( + this, + {LCD_W / 2 + 6, MENU_TITLE_TOP, LCD_W / 2 - 8, MENU_TITLE_HEIGHT}, + STR_OPEN_CHANNEL_MONITORS, [=]() { + new ChannelsViewMenu(this); + return 0; + }); #endif } diff --git a/radio/src/gui/colorlcd/model_curves.cpp b/radio/src/gui/colorlcd/model_curves.cpp index 37936638d..1391b6c8b 100644 --- a/radio/src/gui/colorlcd/model_curves.cpp +++ b/radio/src/gui/colorlcd/model_curves.cpp @@ -27,12 +27,6 @@ #define SET_DIRTY() storageDirty(EE_MODEL) -#if PORTRAIT_LCD -#define PER_ROW 2 -#else -#define PER_ROW 3 -#endif - class CurveButton : public Button { public: diff --git a/radio/src/gui/colorlcd/model_curves.h b/radio/src/gui/colorlcd/model_curves.h index 2a7ac6f65..55371a089 100644 --- a/radio/src/gui/colorlcd/model_curves.h +++ b/radio/src/gui/colorlcd/model_curves.h @@ -34,6 +34,8 @@ class ModelCurvesPage : public PageTab virtual void build(Window* window) override; + static LAYOUT_VAL(PER_ROW, 3, 2) + protected: uint8_t focusIndex = -1; ButtonBase* addButton = nullptr; diff --git a/radio/src/gui/colorlcd/model_flightmodes.cpp b/radio/src/gui/colorlcd/model_flightmodes.cpp index 76c1df4f0..707e65887 100644 --- a/radio/src/gui/colorlcd/model_flightmodes.cpp +++ b/radio/src/gui/colorlcd/model_flightmodes.cpp @@ -50,11 +50,9 @@ static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; #if !PORTRAIT_LCD -#define TRIMS_PER_LINE 2 static const lv_coord_t trims_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; #else -#define TRIMS_PER_LINE 1 static const lv_coord_t trims_col_dsc[] = {LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; #endif @@ -196,6 +194,8 @@ class FlightModeEdit : public Page } } + static LAYOUT_VAL(TRIMS_PER_LINE, 2, 1) + protected: uint8_t index; }; diff --git a/radio/src/gui/colorlcd/model_heli.cpp b/radio/src/gui/colorlcd/model_heli.cpp index 8346d0034..024cdf139 100644 --- a/radio/src/gui/colorlcd/model_heli.cpp +++ b/radio/src/gui/colorlcd/model_heli.cpp @@ -66,9 +66,8 @@ void ModelHeliPage::build(Window* form) GET_SET_DEFAULT(g_model.swashR.elevatorSource)); // Elevator weight - auto w = new StaticText(line, rect_t{}, STR_WEIGHT); - lv_obj_set_style_grid_cell_x_align(w->getLvObj(), LV_GRID_ALIGN_END, 0); - lv_obj_set_style_pad_right(w->getLvObj(), lv_dpx(8), 0); + auto w = new StaticText(line, rect_t{}, STR_WEIGHT, COLOR_THEME_PRIMARY1 | RIGHT); + w->padRight(PAD_LARGE); new NumberEdit(line, rect_t{}, -100, 100, GET_SET_DEFAULT(g_model.swashR.elevatorWeight)); @@ -79,9 +78,8 @@ void ModelHeliPage::build(Window* form) GET_SET_DEFAULT(g_model.swashR.aileronSource)); // Aileron weight - w = new StaticText(line, rect_t{}, STR_WEIGHT); - lv_obj_set_style_grid_cell_x_align(w->getLvObj(), LV_GRID_ALIGN_END, 0); - lv_obj_set_style_pad_right(w->getLvObj(), lv_dpx(8), 0); + w = new StaticText(line, rect_t{}, STR_WEIGHT, COLOR_THEME_PRIMARY1 | RIGHT); + w->padRight(PAD_LARGE); new NumberEdit(line, rect_t{}, -100, 100, GET_SET_DEFAULT(g_model.swashR.aileronWeight)); @@ -92,9 +90,8 @@ void ModelHeliPage::build(Window* form) GET_SET_DEFAULT(g_model.swashR.collectiveSource)); // Collective weight - w = new StaticText(line, rect_t{}, STR_WEIGHT); - lv_obj_set_style_grid_cell_x_align(w->getLvObj(), LV_GRID_ALIGN_END, 0); - lv_obj_set_style_pad_right(w->getLvObj(), lv_dpx(8), 0); + w = new StaticText(line, rect_t{}, STR_WEIGHT, COLOR_THEME_PRIMARY1 | RIGHT); + w->padRight(PAD_LARGE); new NumberEdit(line, rect_t{}, -100, 100, GET_SET_DEFAULT(g_model.swashR.collectiveWeight)); diff --git a/radio/src/gui/colorlcd/model_logical_switches.cpp b/radio/src/gui/colorlcd/model_logical_switches.cpp index 6e38c7298..a5c590bc9 100644 --- a/radio/src/gui/colorlcd/model_logical_switches.cpp +++ b/radio/src/gui/colorlcd/model_logical_switches.cpp @@ -257,8 +257,8 @@ class LogicalSwitchEditPage : public Page void buildBody(Window* window) { window->setFlexLayout(); - window->padLeft(4); - window->padRight(4); + window->padLeft(PAD_SMALL); + window->padRight(PAD_SMALL); FlexGridLayout grid(col_dsc, row_dsc, PAD_TINY); diff --git a/radio/src/gui/colorlcd/model_mixer_scripts.cpp b/radio/src/gui/colorlcd/model_mixer_scripts.cpp index ad641d258..82e82ea0b 100644 --- a/radio/src/gui/colorlcd/model_mixer_scripts.cpp +++ b/radio/src/gui/colorlcd/model_mixer_scripts.cpp @@ -127,7 +127,7 @@ class ScriptEditWindow : public Page ScriptInput& si = sio->inputs[i]; auto lbl = new StaticText(line, rect_t{}, si.name); - lbl->padLeft(10); + lbl->padLeft(PAD_LARGE); if (si.type == INPUT_TYPE_VALUE) { (new NumberEdit(line, rect_t{}, si.min, si.max, GET_SET_WITH_OFFSET(sd->inputs[i].value, si.def))) @@ -155,7 +155,7 @@ class ScriptEditWindow : public Page return std::string(s, sizeof(s) - 1); }, COLOR_THEME_PRIMARY1); - lbl->padLeft(10); + lbl->padLeft(PAD_LARGE); new DynamicNumber( line, rect_t{}, [=]() { return calcRESXto1000(so->value); }); } @@ -182,10 +182,10 @@ class ScriptLineButton : public ListLineButton runtimeData(runtimeData) { #if PORTRAIT_LCD - padTop(5); + padTop(PAD_SMALL); #endif - padLeft(3); - padRight(3); + padLeft(PAD_TINY); + padRight(PAD_TINY); lv_obj_set_layout(lvobj, LV_LAYOUT_GRID); lv_obj_set_grid_dsc_array(lvobj, b_col_dsc, row_dsc); lv_obj_set_style_pad_row(lvobj, 0, 0); diff --git a/radio/src/gui/colorlcd/model_mixes.cpp b/radio/src/gui/colorlcd/model_mixes.cpp index f7f46e7c2..9b901df73 100644 --- a/radio/src/gui/colorlcd/model_mixes.cpp +++ b/radio/src/gui/colorlcd/model_mixes.cpp @@ -444,7 +444,7 @@ void ModelMixesPage::build(Window * window) auto box = new Window(window, rect_t{}); box->padAll(PAD_TINY); box->setFlexLayout(LV_FLEX_FLOW_ROW, PAD_SMALL); - box->padLeft(lv_dpx(8)); + box->padLeft(PAD_MEDIUM); auto box_obj = box->getLvObj(); lv_obj_set_style_flex_cross_place(box_obj, LV_FLEX_ALIGN_CENTER, 0); diff --git a/radio/src/gui/colorlcd/model_telemetry.cpp b/radio/src/gui/colorlcd/model_telemetry.cpp index 9a1b3df4c..9f988b58e 100644 --- a/radio/src/gui/colorlcd/model_telemetry.cpp +++ b/radio/src/gui/colorlcd/model_telemetry.cpp @@ -56,12 +56,6 @@ static const lv_coord_t col_dsc5[] = {LV_GRID_FR(5), LV_GRID_FR(4), LV_GRID_FR(4), LV_GRID_FR(4), LV_GRID_TEMPLATE_LAST}; -// Edit grid variants -static const lv_coord_t e_col_dsc[] = {LV_GRID_FR(2), LV_GRID_FR(3), - LV_GRID_TEMPLATE_LAST}; -static const lv_coord_t e_col_dsc2[] = {LV_GRID_FR(4), LV_GRID_FR(3), - LV_GRID_FR(3), LV_GRID_TEMPLATE_LAST}; - static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; class TSStyle @@ -401,59 +395,11 @@ class SensorSourceChoice : public SourceChoice } }; -class SensorRatioEdit : Window -{ - public: - SensorRatioEdit(Window* parent, const rect_t& rect, int vmin, int vmax, - std::function _getValue, - std::function _setValue) : - Window(parent, rect), - m_getValue(std::move(_getValue)), - m_setValue(std::move(_setValue)) - { - setFlexLayout(LV_FLEX_FLOW_ROW, 75); - lv_obj_set_flex_align(lvobj, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, - LV_FLEX_ALIGN_SPACE_AROUND); - - editRatio = new NumberEdit( - this, rect_t{}, vmin, vmax, m_getValue, - [=](int32_t newValue) { - m_setValue(newValue); - setPercent(); - }, - PREC1); - editRatio->setZeroText("-"); - - percentText = new StaticText(this, rect_t{}, ""); - setPercent(); - } - - protected: - int32_t ratioPercent; - NumberEdit* editRatio; - StaticText* percentText; - std::function m_getValue; - std::function m_setValue; - - private: - void setPercent() - { - int32_t value = m_getValue(); - if (value == 0) { - percentText->setText(""); - } else { - std::string str = - formatNumberAsString((value * 1000) / 255, PREC1, 0, "", "%"); - percentText->setText(str); - } - } -}; - -class SensorEditWindow : public Page +class SensorEditWindow : public SubPage { public: explicit SensorEditWindow(uint8_t index) : - Page(ICON_MODEL_TELEMETRY, PAD_SMALL), index(index) + SubPage(ICON_MODEL_TELEMETRY, STR_MENUTELEMETRY, "", true), index(index) { buildHeader(header); buildBody(body); @@ -490,13 +436,12 @@ class SensorEditWindow : public Page P_COUNT, }; - FormLine* paramLines[P_COUNT] = {}; + Window* paramLines[P_COUNT] = {}; void buildHeader(Window* window) { std::string title2 = STR_SENSOR + std::to_string(index + 1) + " = " + STR_NA; - header->setTitle(STR_MENUTELEMETRY); headerValue = header->setTitle2(title2); @@ -627,218 +572,222 @@ class SensorEditWindow : public Page { window->setFlexLayout(); - FlexGridLayout grid(e_col_dsc, row_dsc, PAD_TINY); - FlexGridLayout grid2(e_col_dsc2, row_dsc, PAD_TINY); - TelemetrySensor* sensor = &g_model.telemetrySensors[index]; // Sensor name - auto line = window->newLine(grid); - new StaticText(line, rect_t{}, STR_NAME); - new ModelTextEdit(line, rect_t{}, sensor->label, sizeof(sensor->label)); + setupLine(STR_NAME, [=](Window* parent, coord_t x, coord_t y) { + new ModelTextEdit(parent, {x, y, 0, 0}, sensor->label, sizeof(sensor->label)); + }); // Type - line = window->newLine(grid); - new StaticText(line, rect_t{}, STR_TYPE); - new Choice(line, rect_t{}, STR_VSENSORTYPES, 0, 1, - GET_DEFAULT(sensor->type), [=](uint8_t newValue) { - sensor->type = newValue; - sensor->instance = 0; - if (sensor->type == TELEM_TYPE_CALCULATED) { - sensor->param = 0; - sensor->filter = 0; - sensor->autoOffset = 0; - } - SET_DIRTY(); - updateSensorParameters(); - }); + setupLine(STR_TYPE, [=](Window* parent, coord_t x, coord_t y) { + new Choice(parent, {x, y, 0, 0}, STR_VSENSORTYPES, 0, 1, + GET_DEFAULT(sensor->type), [=](uint8_t newValue) { + sensor->type = newValue; + sensor->instance = 0; + if (sensor->type == TELEM_TYPE_CALCULATED) { + sensor->param = 0; + sensor->filter = 0; + sensor->autoOffset = 0; + } + SET_DIRTY(); + updateSensorParameters(); + }); + }); // Parameters - paramLines[P_FORMULA] = window->newLine(grid); - new StaticText(paramLines[P_FORMULA], rect_t{}, STR_FORMULA); - new Choice(paramLines[P_FORMULA], rect_t{}, STR_VFORMULAS, 0, - TELEM_FORMULA_LAST, GET_DEFAULT(sensor->formula), - [=](uint8_t newValue) { - sensor->formula = newValue; - sensor->param = 0; - if (sensor->formula == TELEM_FORMULA_CELL) { - sensor->unit = UNIT_VOLTS; - sensor->prec = 2; - } else if (sensor->formula == TELEM_FORMULA_DIST) { - sensor->unit = UNIT_DIST; - sensor->prec = 0; - } else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) { - sensor->unit = UNIT_MAH; - sensor->prec = 0; - } - SET_DIRTY(); - telemetryItems[index].clear(); - updateSensorParameters(); - }); + paramLines[P_FORMULA] = setupLine(STR_FORMULA, [=](Window* parent, coord_t x, coord_t y) { + new Choice(parent, {x, y, 0, 0}, STR_VFORMULAS, 0, + TELEM_FORMULA_LAST, GET_DEFAULT(sensor->formula), + [=](uint8_t newValue) { + sensor->formula = newValue; + sensor->param = 0; + if (sensor->formula == TELEM_FORMULA_CELL) { + sensor->unit = UNIT_VOLTS; + sensor->prec = 2; + } else if (sensor->formula == TELEM_FORMULA_DIST) { + sensor->unit = UNIT_DIST; + sensor->prec = 0; + } else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) { + sensor->unit = UNIT_MAH; + sensor->prec = 0; + } + SET_DIRTY(); + telemetryItems[index].clear(); + updateSensorParameters(); + }); + }); - paramLines[P_ID] = window->newLine(grid2); - new StaticText(paramLines[P_ID], rect_t{}, STR_ID); - auto num = new NumberEdit(paramLines[P_ID], rect_t{}, 0, 0xFFFF, - GET_SET_DEFAULT(sensor->id)); -#if PORTRAIT_LCD - // Portrait layout - need to limit width of edit box - num->setWidth((lv_pct(28))); -#endif - num->setDisplayHandler([](int32_t value) { - char buf[4]; - buf[0] = hex2char((value & 0xf000) >> 12); - buf[1] = hex2char((value & 0x0f00) >> 8); - buf[2] = hex2char((value & 0x00f0) >> 4); - buf[3] = hex2char((value & 0x000f) >> 0); - return std::string(buf, sizeof(buf)); - }); - num = new NumberEdit(paramLines[P_ID], rect_t{}, 0, 0xff, - GET_SET_DEFAULT(sensor->instance)); -#if PORTRAIT_LCD - // Portrait layout - need to limit width of edit box - num->setWidth(lv_pct(28)); -#endif + paramLines[P_ID] = setupLine(STR_ID, [=](Window* parent, coord_t x, coord_t y) { + auto num = new NumberEdit(parent, {x, y, NUM_EDIT_W, 0}, 0, 0xFFFF, + GET_SET_DEFAULT(sensor->id)); + num->setDisplayHandler([](int32_t value) { + char buf[4]; + buf[0] = hex2char((value & 0xf000) >> 12); + buf[1] = hex2char((value & 0x0f00) >> 8); + buf[2] = hex2char((value & 0x00f0) >> 4); + buf[3] = hex2char((value & 0x000f) >> 0); + return std::string(buf, sizeof(buf)); + }); + num = new NumberEdit(paramLines[P_ID], {x, y, NUM_EDIT_W, 0}, 0, 0xff, + GET_SET_DEFAULT(sensor->instance)); + }); - paramLines[P_UNIT] = window->newLine(grid); - new StaticText(paramLines[P_UNIT], rect_t{}, STR_UNIT); - new Choice(paramLines[P_UNIT], rect_t{}, STR_VTELEMUNIT, 0, UNIT_MAX, - GET_DEFAULT(sensor->unit), [=](uint8_t newValue) { - sensor->unit = newValue; - if (sensor->unit == UNIT_FAHRENHEIT) { - sensor->prec = 0; - } - SET_DIRTY(); - telemetryItems[index].clear(); - updateSensorParameters(); - }); + paramLines[P_UNIT] = setupLine(STR_UNIT, [=](Window* parent, coord_t x, coord_t y) { + new Choice(parent, {x, y, 0, 0}, STR_VTELEMUNIT, 0, UNIT_MAX, + GET_DEFAULT(sensor->unit), [=](uint8_t newValue) { + sensor->unit = newValue; + if (sensor->unit == UNIT_FAHRENHEIT) { + sensor->prec = 0; + } + SET_DIRTY(); + telemetryItems[index].clear(); + updateSensorParameters(); + }); + }); - paramLines[P_PREC] = window->newLine(grid); - new StaticText(paramLines[P_PREC], rect_t{}, STR_PRECISION); - new Choice(paramLines[P_PREC], rect_t{}, STR_VPREC, 0, 2, - GET_DEFAULT(sensor->prec), [=](uint8_t newValue) { - sensor->prec = newValue; - SET_DIRTY(); - telemetryItems[index].clear(); - updateSensorParameters(); - }); + paramLines[P_PREC] = setupLine(STR_PRECISION, [=](Window* parent, coord_t x, coord_t y) { + new Choice(parent, {x, y, 0, 0}, STR_VPREC, 0, 2, + GET_DEFAULT(sensor->prec), [=](uint8_t newValue) { + sensor->prec = newValue; + SET_DIRTY(); + telemetryItems[index].clear(); + updateSensorParameters(); + }); + }); - paramLines[P_CELLSENSOR] = window->newLine(grid); - new StaticText(paramLines[P_CELLSENSOR], rect_t{}, STR_CELLSENSOR); - new SensorSourceChoice(paramLines[P_CELLSENSOR], rect_t{}, - &sensor->cell.source, isCellsSensor); + paramLines[P_CELLSENSOR] = setupLine(STR_CELLSENSOR, [=](Window* parent, coord_t x, coord_t y) { + new SensorSourceChoice(parent, {x, y, 0, 0}, + &sensor->cell.source, isCellsSensor); + }); - paramLines[P_GPSSENSOR] = window->newLine(grid); - new StaticText(paramLines[P_GPSSENSOR], rect_t{}, STR_GPSSENSOR); - new SensorSourceChoice(paramLines[P_GPSSENSOR], rect_t{}, &sensor->dist.gps, - isGPSSensor); + paramLines[P_GPSSENSOR] = setupLine(STR_GPSSENSOR, [=](Window* parent, coord_t x, coord_t y) { + new SensorSourceChoice(parent, {x, y, 0, 0}, &sensor->dist.gps, + isGPSSensor); + }); - paramLines[P_CURRENTSENSOR] = window->newLine(grid); - new StaticText(paramLines[P_CURRENTSENSOR], rect_t{}, STR_CURRENTSENSOR); - new SensorSourceChoice(paramLines[P_CURRENTSENSOR], rect_t{}, - &sensor->consumption.source, isSensorAvailable); + paramLines[P_CURRENTSENSOR] = setupLine(STR_CURRENTSENSOR, [=](Window* parent, coord_t x, coord_t y) { + new SensorSourceChoice(parent, {x, y, 0, 0}, + &sensor->consumption.source, isSensorAvailable); + }); - paramLines[P_CONSUMPTIONSOURCE] = window->newLine(grid); - new StaticText(paramLines[P_CONSUMPTIONSOURCE], rect_t{}, STR_SOURCE); - new SensorSourceChoice(paramLines[P_CONSUMPTIONSOURCE], rect_t{}, - &sensor->consumption.source, isSensorAvailable); + paramLines[P_CONSUMPTIONSOURCE] = setupLine(STR_SOURCE, [=](Window* parent, coord_t x, coord_t y) { + new SensorSourceChoice(parent, {x, y, 0, 0}, + &sensor->consumption.source, isSensorAvailable); + }); - paramLines[P_CALC0] = window->newLine(grid); - new StaticText(paramLines[P_CALC0], rect_t{}, - STR_SOURCE + std::to_string(1)); - new SensorSourceChoice(paramLines[P_CALC0], rect_t{}, - (uint8_t*)&sensor->calc.sources[0], - isSensorAvailable); + std::string s(STR_SOURCE); - paramLines[P_BLADES] = window->newLine(grid); - new StaticText(paramLines[P_BLADES], rect_t{}, STR_BLADES); - new NumberEdit(paramLines[P_BLADES], rect_t{}, 1, 30000, - GET_SET_DEFAULT(sensor->custom.ratio)); + paramLines[P_CALC0] = setupLine((s + std::to_string(1)).c_str(), [=](Window* parent, coord_t x, coord_t y) { + new SensorSourceChoice(parent, {x, y, 0, 0}, + (uint8_t*)&sensor->calc.sources[0], + isSensorAvailable); + }); - paramLines[P_RATIO] = window->newLine(grid); - new StaticText(paramLines[P_RATIO], rect_t{}, STR_RATIO); - new SensorRatioEdit(paramLines[P_RATIO], rect_t{}, 0, 30000, + paramLines[P_BLADES] = setupLine(STR_BLADES, [=](Window* parent, coord_t x, coord_t y) { + new NumberEdit(parent, {x, y, NUM_EDIT_W, 0}, 1, 30000, GET_SET_DEFAULT(sensor->custom.ratio)); + }); - paramLines[P_CELLINDEX] = window->newLine(grid); - new StaticText(paramLines[P_CELLINDEX], rect_t{}, STR_CELLINDEX); - new Choice(paramLines[P_CELLINDEX], rect_t{}, STR_VCELLINDEX, - TELEM_CELL_INDEX_LOWEST, TELEM_CELL_INDEX_LAST, - GET_SET_DEFAULT(sensor->cell.index)); + paramLines[P_RATIO] = setupLine(STR_RATIO, [=](Window* parent, coord_t x, coord_t y) { + auto pct = new StaticText(parent, {x + NUM_EDIT_W + PAD_MEDIUM, y + PAD_MEDIUM, 0, 0}, ""); + auto num = new NumberEdit( + parent, {x, y, NUM_EDIT_W, 0}, 0, 30000, + GET_DEFAULT(sensor->custom.ratio), + [=](int32_t value) { + sensor->custom.ratio = value; + std::string s(""); + if (sensor->custom.ratio != 0) + s = formatNumberAsString((sensor->custom.ratio * 1000) / 255, PREC1, 0, "", "%"); + pct->setText(s); + }, + PREC1); + num->setZeroText("-"); + std::string s(""); + if (sensor->custom.ratio != 0) + s = formatNumberAsString((sensor->custom.ratio * 1000) / 255, PREC1, 0, "", "%"); + pct->setText(s); + }); - paramLines[P_ALTSENSOR] = window->newLine(grid); - new StaticText(paramLines[P_ALTSENSOR], rect_t{}, STR_ALTSENSOR); - new SensorSourceChoice(paramLines[P_ALTSENSOR], rect_t{}, &sensor->dist.alt, - isAltSensor); + paramLines[P_CELLINDEX] = setupLine(STR_CELLINDEX, [=](Window* parent, coord_t x, coord_t y) { + new Choice(parent, {x, y, 0, 0}, STR_VCELLINDEX, + TELEM_CELL_INDEX_LOWEST, TELEM_CELL_INDEX_LAST, + GET_SET_DEFAULT(sensor->cell.index)); + }); - paramLines[P_CALC1] = window->newLine(grid); - new StaticText(paramLines[P_CALC1], rect_t{}, - STR_SOURCE + std::to_string(2)); - new SensorSourceChoice(paramLines[P_CALC1], rect_t{}, - (uint8_t*)&sensor->calc.sources[1], - isSensorAvailable); + paramLines[P_ALTSENSOR] = setupLine(STR_ALTSENSOR, [=](Window* parent, coord_t x, coord_t y) { + new SensorSourceChoice(parent, {x, y, 0, 0}, &sensor->dist.alt, + isAltSensor); + }); - paramLines[P_MULT] = window->newLine(grid); - new StaticText(paramLines[P_MULT], rect_t{}, STR_MULTIPLIER); - new NumberEdit(paramLines[P_MULT], rect_t{}, 1, 30000, - GET_SET_DEFAULT(sensor->custom.offset)); + paramLines[P_CALC1] = setupLine((s + std::to_string(2)).c_str(), [=](Window* parent, coord_t x, coord_t y) { + new SensorSourceChoice(parent, {x, y, 0, 0}, + (uint8_t*)&sensor->calc.sources[1], + isSensorAvailable); + }); - paramLines[P_OFFSET] = window->newLine(grid); - new StaticText(paramLines[P_OFFSET], rect_t{}, STR_OFFSET); - new NumberEdit( - paramLines[P_OFFSET], rect_t{}, -30000, 30000, - GET_SET_DEFAULT(sensor->custom.offset), - (sensor->prec > 0) ? (sensor->prec == 2 ? PREC2 : PREC1) : 0); + paramLines[P_MULT] = setupLine(STR_MULTIPLIER, [=](Window* parent, coord_t x, coord_t y) { + new NumberEdit(parent, {x, y, NUM_EDIT_W, 0}, 1, 30000, + GET_SET_DEFAULT(sensor->custom.offset)); + }); - paramLines[P_CALC2] = window->newLine(grid); - new StaticText(paramLines[P_CALC2], rect_t{}, - STR_SOURCE + std::to_string(3)); - new SensorSourceChoice(paramLines[P_CALC2], rect_t{}, - (uint8_t*)&sensor->calc.sources[2], - isSensorAvailable); + paramLines[P_OFFSET] = setupLine(STR_OFFSET, [=](Window* parent, coord_t x, coord_t y) { + new NumberEdit( + parent, {x, y, NUM_EDIT_W, 0}, -30000, 30000, + GET_SET_DEFAULT(sensor->custom.offset), + (sensor->prec > 0) ? (sensor->prec == 2 ? PREC2 : PREC1) : 0); + }); - paramLines[P_CALC3] = window->newLine(grid); - new StaticText(paramLines[P_CALC3], rect_t{}, - STR_SOURCE + std::to_string(4)); - new SensorSourceChoice(paramLines[P_CALC3], rect_t{}, - (uint8_t*)&sensor->calc.sources[3], - isSensorAvailable); + paramLines[P_CALC2] = setupLine((s + std::to_string(3)).c_str(), [=](Window* parent, coord_t x, coord_t y) { + new SensorSourceChoice(parent, {x, y, 0, 0}, + (uint8_t*)&sensor->calc.sources[2], + isSensorAvailable); + }); - paramLines[P_AUTOOFFSET] = window->newLine(grid); - new StaticText(paramLines[P_AUTOOFFSET], rect_t{}, STR_AUTOOFFSET); - new ToggleSwitch(paramLines[P_AUTOOFFSET], rect_t{}, - GET_SET_DEFAULT(sensor->autoOffset)); + paramLines[P_CALC3] = setupLine((s + std::to_string(4)).c_str(), [=](Window* parent, coord_t x, coord_t y) { + new SensorSourceChoice(parent, {x, y, 0, 0}, + (uint8_t*)&sensor->calc.sources[3], + isSensorAvailable); + }); - paramLines[P_ONLYPOS] = window->newLine(grid); - new StaticText(paramLines[P_ONLYPOS], rect_t{}, STR_ONLYPOSITIVE); - new ToggleSwitch(paramLines[P_ONLYPOS], rect_t{}, - GET_SET_DEFAULT(sensor->onlyPositive)); + paramLines[P_AUTOOFFSET] = setupLine(STR_AUTOOFFSET, [=](Window* parent, coord_t x, coord_t y) { + new ToggleSwitch(parent, {x, y, 0, 0}, + GET_SET_DEFAULT(sensor->autoOffset)); + }); - paramLines[P_FILTER] = window->newLine(grid); - new StaticText(paramLines[P_FILTER], rect_t{}, STR_FILTER); - new ToggleSwitch(paramLines[P_FILTER], rect_t{}, - GET_SET_DEFAULT(sensor->filter)); + paramLines[P_ONLYPOS] = setupLine(STR_ONLYPOSITIVE, [=](Window* parent, coord_t x, coord_t y) { + new ToggleSwitch(parent, {x, y, 0, 0}, + GET_SET_DEFAULT(sensor->onlyPositive)); + }); - paramLines[P_PERSISTENT] = window->newLine(grid); - new StaticText(paramLines[P_PERSISTENT], rect_t{}, STR_PERSISTENT); - new ToggleSwitch(paramLines[P_PERSISTENT], rect_t{}, - GET_DEFAULT(sensor->persistent), [=](int32_t newValue) { - sensor->persistent = newValue; - if (!sensor->persistent) sensor->persistentValue = 0; - SET_DIRTY(); - }); + paramLines[P_FILTER] = setupLine(STR_FILTER, [=](Window* parent, coord_t x, coord_t y) { + new ToggleSwitch(parent, {x, y, 0, 0}, + GET_SET_DEFAULT(sensor->filter)); + }); + + paramLines[P_PERSISTENT] = setupLine(STR_PERSISTENT, [=](Window* parent, coord_t x, coord_t y) { + new ToggleSwitch(parent, {x, y, 0, 0}, + GET_DEFAULT(sensor->persistent), [=](int32_t newValue) { + sensor->persistent = newValue; + if (!sensor->persistent) sensor->persistentValue = 0; + SET_DIRTY(); + }); + }); // Logs - line = window->newLine(grid); - new StaticText(line, rect_t{}, STR_LOGS); - new ToggleSwitch(line, rect_t{}, GET_DEFAULT(sensor->logs), - [=](int32_t newValue) { - sensor->logs = newValue; - logsClose(); - SET_DIRTY(); - }); + setupLine(STR_LOGS, [=](Window* parent, coord_t x, coord_t y) { + new ToggleSwitch(parent, {x, y, 0, 0}, GET_DEFAULT(sensor->logs), + [=](int32_t newValue) { + sensor->logs = newValue; + logsClose(); + SET_DIRTY(); + }); + }); updateSensorParameters(); } + + static LAYOUT_VAL(NUM_EDIT_W, 100, 80) }; ModelTelemetryPage::ModelTelemetryPage() : @@ -942,7 +891,7 @@ void ModelTelemetryPage::buildSensorList(int8_t focusSensorIndex) void ModelTelemetryPage::build(Window* window) { window->padAll(PAD_TINY); - window->padBottom(16); + window->padBottom(PAD_LARGE); window->setFlexLayout(LV_FLEX_FLOW_COLUMN, PAD_ZERO); this->window = window; @@ -1015,13 +964,13 @@ void ModelTelemetryPage::build(Window* window) // Show instance IDs button line = window->newLine(grid); - line->padLeft(10); + line->padLeft(PAD_LARGE); new StaticText(line, rect_t{}, STR_SHOW_INSTANCE_ID); new ToggleSwitch(line, rect_t{}, GET_SET_DEFAULT(g_model.showInstanceIds)); // Ignore instance button line = window->newLine(grid); - line->padLeft(10); + line->padLeft(PAD_LARGE); new StaticText(line, rect_t{}, STR_IGNORE_INSTANCE); new ToggleSwitch(line, rect_t{}, GET_SET_DEFAULT(g_model.ignoreSensorIds)); @@ -1029,19 +978,19 @@ void ModelTelemetryPage::build(Window* window) new Subtitle(window, getRxStatLabels()->label); line = window->newLine(grid); - line->padLeft(10); + line->padLeft(PAD_LARGE); new StaticText(line, rect_t{}, STR_LOWALARM); - new NumberEdit(line, rect_t{0, 0, NUM_EDIT_W, 0}, 0, 100, + new NumberEdit(line, {0, 0, NUM_EDIT_W, 0}, 0, 100, GET_SET_DEFAULT(g_model.rfAlarms.warning)); line = window->newLine(grid); - line->padLeft(10); + line->padLeft(PAD_LARGE); new StaticText(line, rect_t{}, STR_CRITICALALARM); - new NumberEdit(line, rect_t{0, 0, NUM_EDIT_W, 0}, 0, 100, + new NumberEdit(line, {0, 0, NUM_EDIT_W, 0}, 0, 100, GET_SET_DEFAULT(g_model.rfAlarms.critical)); line = window->newLine(grid); - line->padLeft(10); + line->padLeft(PAD_LARGE); new StaticText(line, rect_t{}, STR_DISABLE_ALARM); new ToggleSwitch(line, rect_t{}, GET_SET_DEFAULT(g_model.disableTelemetryWarning)); @@ -1052,7 +1001,7 @@ void ModelTelemetryPage::build(Window* window) FlexGridLayout grid5(col_dsc5, row_dsc); line = window->newLine(grid5); - line->padLeft(10); + line->padLeft(PAD_LARGE); new StaticText(line, rect_t{}, STR_SOURCE); auto choice = new SourceChoice( line, rect_t{}, MIXSRC_NONE, MIXSRC_LAST_TELEM, @@ -1071,21 +1020,21 @@ void ModelTelemetryPage::build(Window* window) }); line = window->newLine(grid5); - line->padLeft(10); + line->padLeft(PAD_LARGE); new StaticText(line, rect_t{}, STR_RANGE); - auto vMin = new NumberEdit(line, rect_t{0, 0, NUM_EDIT_W, 0}, -17, 17, + auto vMin = new NumberEdit(line, {0, 0, NUM_EDIT_W, 0}, -17, 17, GET_SET_WITH_OFFSET(g_model.varioData.min, -10)); vMin->setAvailableHandler( [](int val) { return val < g_model.varioData.max + 10; }); - auto vMax = new NumberEdit(line, rect_t{0, 0, NUM_EDIT_W, 0}, -17, 17, + auto vMax = new NumberEdit(line, {0, 0, NUM_EDIT_W, 0}, -17, 17, GET_SET_WITH_OFFSET(g_model.varioData.max, 10)); vMax->setAvailableHandler( [](int val) { return g_model.varioData.min - 10 < val; }); line = window->newLine(grid5); - line->padLeft(10); + line->padLeft(PAD_LARGE); new StaticText(line, rect_t{}, STR_CENTER); auto cMin = new NumberEdit( diff --git a/radio/src/gui/colorlcd/model_usbjoystick.cpp b/radio/src/gui/colorlcd/model_usbjoystick.cpp index dbbb67821..03607b153 100644 --- a/radio/src/gui/colorlcd/model_usbjoystick.cpp +++ b/radio/src/gui/colorlcd/model_usbjoystick.cpp @@ -38,20 +38,10 @@ static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; -#define USBCH_EDIT_STATUS_BAR_WIDTH 250 -#define USBCH_EDIT_STATUS_BAR_MARGIN 3 -#define USBCH_EDIT_RIGHT_MARGIN 0 -#define USBCH_COLS 4 - static const lv_coord_t ch_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2), LV_GRID_FR(1), LV_GRID_FR(2), LV_GRID_TEMPLATE_LAST}; -#define USBCH_CHN_ROWS 1 -#define USBCH_BTN_MODE_COL 4 -#define USBCH_BTN_MODE_ROW 0 -#define USBCH_LINE_HEIGHT 32 - static const lv_coord_t b_col_dsc[] = {LV_GRID_FR(10), 20, LV_GRID_FR(10), LV_GRID_FR(12), LV_GRID_FR(9), LV_GRID_FR(9), @@ -64,19 +54,9 @@ static const lv_coord_t b_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; -#define USBCH_EDIT_STATUS_BAR_WIDTH 160 -#define USBCH_EDIT_STATUS_BAR_MARGIN 0 -#define USBCH_EDIT_RIGHT_MARGIN 3 -#define USBCH_COLS 2 - static const lv_coord_t ch_col_dsc[] = {LV_GRID_FR(2), LV_GRID_FR(3), LV_GRID_TEMPLATE_LAST}; -#define USBCH_CHN_ROWS 2 -#define USBCH_BTN_MODE_COL 2 -#define USBCH_BTN_MODE_ROW 1 -#define USBCH_LINE_HEIGHT 48 - static const lv_coord_t b_col_dsc[] = {LV_GRID_FR(1), 20, LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; @@ -102,6 +82,8 @@ class USBChannelEditStatusBar : public Window channel, true); } + static LAYOUT_VAL(USBCH_EDIT_STATUS_BAR_MARGIN, 3, 0) + protected: ComboChannelBar* channelBar; int8_t _channel; @@ -226,13 +208,17 @@ class USBChannelEditWindow : public Page public: USBChannelEditWindow(uint8_t channel) : Page(ICON_MODEL_USB, PAD_TINY), channel(channel) { - body->padLeft(8); - body->padRight(8); + body->padLeft(PAD_MEDIUM); + body->padRight(PAD_MEDIUM); buildHeader(header); buildBody(body); } + static LAYOUT_VAL(USBCH_EDIT_STATUS_BAR_WIDTH, 250, 160) + static LAYOUT_VAL(USBCH_EDIT_RIGHT_MARGIN, 0, 3) + static LAYOUT_VAL(USBCH_COLS, 4, 2) + protected: uint8_t channel; USBChannelEditStatusBar* statusBar = nullptr; @@ -243,7 +229,6 @@ class USBChannelEditWindow : public Page StaticText* collisionText = nullptr; Choice* m_btnPosChoice = nullptr; - protected: void update() { USBJoystickChData* cch = usbJChAddress(channel); @@ -361,8 +346,8 @@ class USBChannelEditWindow : public Page SET_VALUE_WUPDATE(cch->param)); line = form->newLine(grid); - line->padTop(0); - line->padBottom(0); + line->padTop(PAD_ZERO); + line->padBottom(PAD_ZERO); collisionText = new StaticText(line, rect_t{}, "", FONT(BOLD) | COLOR_THEME_PRIMARY2 | CENTERED); @@ -382,7 +367,7 @@ class USBChannelLineButton : public ListLineButton { setHeight(USBCH_LINE_HEIGHT); #if !PORTRAIT_LCD - padTop(4); + padTop(PAD_SMALL); #endif lv_obj_set_layout(lvobj, LV_LAYOUT_GRID); @@ -503,6 +488,11 @@ class USBChannelLineButton : public ListLineButton bool isActive() const override { return false; } + static LAYOUT_VAL(USBCH_LINE_HEIGHT, 32, 48) + static LAYOUT_VAL(USBCH_CHN_ROWS, 1, 2) + static LAYOUT_VAL(USBCH_BTN_MODE_COL, 4, 2) + static LAYOUT_VAL(USBCH_BTN_MODE_ROW, 0, 1) + protected: bool init = false; diff --git a/radio/src/gui/colorlcd/mpm_settings.cpp b/radio/src/gui/colorlcd/mpm_settings.cpp index 36e77aaf6..59b9b321f 100644 --- a/radio/src/gui/colorlcd/mpm_settings.cpp +++ b/radio/src/gui/colorlcd/mpm_settings.cpp @@ -54,7 +54,7 @@ class MPMProtoOption : public FormLine { rssi = new DynamicNumber( box, rect_t{}, [] { return (uint16_t)TELEMETRY_RSSI(); }, 0, getRxStatLabels()->label, getRxStatLabels()->unit); - rssi->padTop(5); + rssi->padTop(PAD_SMALL); } void update(const MultiRfProtocols::RfProto* rfProto, ModuleData* md, diff --git a/radio/src/gui/colorlcd/page.cpp b/radio/src/gui/colorlcd/page.cpp index e8537b7e6..5c552f058 100644 --- a/radio/src/gui/colorlcd/page.cpp +++ b/radio/src/gui/colorlcd/page.cpp @@ -21,7 +21,7 @@ #include "page.h" -#include "theme.h" +#include "theme_manager.h" #include "themes/etx_lv_theme.h" #include "view_main.h" diff --git a/radio/src/gui/colorlcd/preview_window.cpp b/radio/src/gui/colorlcd/preview_window.cpp index 3566c9757..1c1ffc09d 100644 --- a/radio/src/gui/colorlcd/preview_window.cpp +++ b/radio/src/gui/colorlcd/preview_window.cpp @@ -24,7 +24,6 @@ #include "libopenui.h" #include "opentx.h" #include "sliders.h" -#include "theme.h" #include "themes/etx_lv_theme.h" #include "trims.h" #include "topbar_impl.h" @@ -159,11 +158,11 @@ PreviewWindow::PreviewWindow(Window *window, rect_t rect, COLOR_THEME_PRIMARY2); new StaticText(this, {ICON_X1, CBT_Y, CBT_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, STR_THEME_CHECKBOX); - new ThemedCheckBox(this, {CB1_X, CB_Y, CB_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, true); - new ThemedCheckBox(this, {CB2_X, CB_Y, CB_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, false); - (new ThemedButton(this, {BTN_X, BTN1_Y, BTN_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, STR_THEME_ACTIVE, true)) + new ThemedCheckBox(this, {CB1_X, CB_Y, CB_W, 0}, true); + new ThemedCheckBox(this, {CB2_X, CB_Y, CB_W, 0}, false); + (new ThemedButton(this, {BTN_X, BTN1_Y, BTN_W, 0}, STR_THEME_ACTIVE, true)) ->check(true); - new ThemedButton(this, {BTN_X, BTN2_Y, BTN_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, STR_THEME_REGULAR, false); + new ThemedButton(this, {BTN_X, BTN2_Y, BTN_W, 0}, STR_THEME_REGULAR, false); new MainViewTrim(this, {ICON_X1, TRIM_Y, MainViewSlider::HORIZONTAL_SLIDERS_WIDTH, TRIM_H}, 0, false); new MainViewSlider(this, {ICON_X1, SLIDER_Y, MainViewSlider::HORIZONTAL_SLIDERS_WIDTH, TRIM_H}, 0, false); new StaticText(this, {ICON_X1, TXT1_Y, TXT_W, EdgeTxStyles::PAGE_LINE_HEIGHT}, STR_THEME_WARNING, @@ -175,7 +174,7 @@ PreviewWindow::PreviewWindow(Window *window, rect_t rect, new ThemedTextEdit(this, {EDT2_X, EDT_Y, TXT_W, 0}, STR_THEME_FOCUS, false); ticks = 0; - dateTime = new HeaderDateTime(this->getLvObj(), width() - DATE_XO, PAD_SMALL); + new HeaderDateTime(this, width() - DATE_XO, PAD_SMALL); lv_group_set_default(def_group); @@ -191,5 +190,3 @@ void PreviewWindow::setColorList(std::vector colorList) // Update preview colors invalidate(); } - -void PreviewWindow::checkEvents() { dateTime->update(); } diff --git a/radio/src/gui/colorlcd/preview_window.h b/radio/src/gui/colorlcd/preview_window.h index 2cdb39b24..a50357428 100644 --- a/radio/src/gui/colorlcd/preview_window.h +++ b/radio/src/gui/colorlcd/preview_window.h @@ -60,7 +60,4 @@ class PreviewWindow : public Window protected: tmr10ms_t ticks; - HeaderDateTime *dateTime; - - void checkEvents() override; }; diff --git a/radio/src/gui/colorlcd/radio_diaganas.cpp b/radio/src/gui/colorlcd/radio_diaganas.cpp index 2e4f6c9c3..117a54792 100644 --- a/radio/src/gui/colorlcd/radio_diaganas.cpp +++ b/radio/src/gui/colorlcd/radio_diaganas.cpp @@ -34,9 +34,6 @@ #if !PORTRAIT_LCD -#define GRIDCOLS 10 -#define TSI2CEventsCol 5 - static const lv_coord_t col_dsc[] = { LV_GRID_FR(30), LV_GRID_FR(30), LV_GRID_FR(40), LV_GRID_FR(40), LV_GRID_FR(40), LV_GRID_FR(30), LV_GRID_FR(30), LV_GRID_FR(40), @@ -44,9 +41,6 @@ static const lv_coord_t col_dsc[] = { #else -#define GRIDCOLS 5 -#define TSI2CEventsCol 0 - static const lv_coord_t col_dsc[] = {LV_GRID_FR(30), LV_GRID_FR(30), LV_GRID_FR(40), LV_GRID_FR(40), LV_GRID_FR(40), LV_GRID_TEMPLATE_LAST}; @@ -64,8 +58,8 @@ class AnaViewWindow : public Window { parent->padAll(PAD_ZERO); padAll(PAD_SMALL); - padLeft(10); - padRight(10); + padLeft(PAD_LARGE); + padRight(PAD_LARGE); setFlexLayout(); line = newLine(grid); @@ -175,7 +169,7 @@ class AnaCalibratedViewWindow : public AnaViewWindow #if PORTRAIT_LCD line->padTop(20); #else - line->padTop(2); + line->padTop(PAD_TINY); #endif auto lbl = new DynamicText( @@ -248,6 +242,8 @@ class AnaCalibratedViewWindow : public AnaViewWindow } #endif + static LAYOUT_VAL(TSI2CEventsCol, 5, 0) + protected: #if defined(HARDWARE_TOUCH) lv_point_t touchPts[4]; @@ -451,6 +447,8 @@ class AnaMinMaxViewWindow : public AnaViewWindow } AnaViewWindow::checkEvents(); } + + static LAYOUT_VAL(GRIDCOLS, 10, 5) }; class AnaCalibratedViewPage : public PageTab diff --git a/radio/src/gui/colorlcd/radio_ghost_module_config.cpp b/radio/src/gui/colorlcd/radio_ghost_module_config.cpp index 4ceb3c1ea..805893849 100644 --- a/radio/src/gui/colorlcd/radio_ghost_module_config.cpp +++ b/radio/src/gui/colorlcd/radio_ghost_module_config.cpp @@ -32,13 +32,6 @@ class GhostModuleConfigWindow : public Window GhostModuleConfigWindow(Window* parent, const rect_t& rect) : Window(parent, rect) { -#if PORTRAIT_LCD - constexpr coord_t xOffset = 20; - constexpr coord_t xOffset2 = 140; -#else - constexpr coord_t xOffset = 140; - constexpr coord_t xOffset2 = 260; -#endif constexpr coord_t yOffset = 20; constexpr coord_t lineSpacing = 25; coord_t h = getFontHeight(FONT(L)); @@ -66,6 +59,9 @@ class GhostModuleConfigWindow : public Window } } + static LAYOUT_VAL(xOffset, 140, 20) + static LAYOUT_VAL(xOffset2, 260, 140) + protected: StaticText* menuLines[GHST_MENU_LINES][2]; diff --git a/radio/src/gui/colorlcd/radio_sdmanager.cpp b/radio/src/gui/colorlcd/radio_sdmanager.cpp index c9f631f4b..943353765 100644 --- a/radio/src/gui/colorlcd/radio_sdmanager.cpp +++ b/radio/src/gui/colorlcd/radio_sdmanager.cpp @@ -239,11 +239,7 @@ void RadioSdManagerPage::build(Window * window) // Adjust file browser width browser->adjustWidth(); -#if !PORTRAIT_LCD - preview = new FilePreview(form, rect_t{0, 0, LCD_W * 2 / 5 - 8, LCD_H - 68}); -#else - preview = new FilePreview(form, rect_t{0, 0, LCD_W - 12, (LCD_H - 68) / 3 }); -#endif + preview = new FilePreview(form, rect_t{0, 0, PREVIEW_W, PREVIEW_H}); preview->padAll(PAD_SMALL); grid.add(preview); grid.nextCell(); diff --git a/radio/src/gui/colorlcd/radio_sdmanager.h b/radio/src/gui/colorlcd/radio_sdmanager.h index ebda836a6..db4c54d97 100644 --- a/radio/src/gui/colorlcd/radio_sdmanager.h +++ b/radio/src/gui/colorlcd/radio_sdmanager.h @@ -38,6 +38,9 @@ class RadioSdManagerPage : public PageTab RadioSdManagerPage(); void build(Window* window) override; + static LAYOUT_VAL(PREVIEW_W, LCD_W * 2 / 5 - PAD_SMALL * 2, LCD_W - PAD_MEDIUM * 2) + static LAYOUT_VAL(PREVIEW_H, LCD_H - 68, (LCD_H - 68) / 3) + protected: void fileAction(const char* path, const char* name, const char* fullpath); diff --git a/radio/src/gui/colorlcd/radio_setup.cpp b/radio/src/gui/colorlcd/radio_setup.cpp index 3acc68122..c2f291b04 100644 --- a/radio/src/gui/colorlcd/radio_setup.cpp +++ b/radio/src/gui/colorlcd/radio_setup.cpp @@ -123,7 +123,7 @@ class DateTimeWindow : public Window // Date new StaticText(this, rect_t{PAD_TINY, DT_Y1 + PAD_MEDIUM, SubPage::EDT_X - PAD_TINY - PAD_SMALL, EdgeTxStyles::PAGE_LINE_HEIGHT}, STR_DATE); year = new NumberEdit( - this, rect_t{SubPage::EDT_X, DT_Y1, DT_EDT_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, 2023, 2037, + this, rect_t{SubPage::EDT_X, DT_Y1, DT_EDT_W, 0}, 2023, 2037, [=]() -> int32_t { return TM_YEAR_BASE + m_tm.tm_year; }, [=](int32_t newValue) { m_last_tm.tm_year = m_tm.tm_year = newValue - TM_YEAR_BASE; @@ -132,7 +132,7 @@ class DateTimeWindow : public Window }); month = new NumberEdit( - this, rect_t{SubPage::EDT_X + DT_EDT_W + PAD_TINY, DT_Y1, DT_EDT_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, 1, 12, + this, rect_t{SubPage::EDT_X + DT_EDT_W + PAD_TINY, DT_Y1, DT_EDT_W, 0}, 1, 12, [=]() -> int32_t { return 1 + m_tm.tm_mon; }, [=](int32_t newValue) { m_last_tm.tm_mon = m_tm.tm_mon = newValue - 1; @@ -143,7 +143,7 @@ class DateTimeWindow : public Window [](int32_t value) { return formatNumberAsString(value, LEADING0); }); day = new NumberEdit( - this, rect_t{SubPage::EDT_X + 2 * DT_EDT_W + PAD_SMALL, DT_Y1, DT_EDT_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, 1, + this, rect_t{SubPage::EDT_X + 2 * DT_EDT_W + PAD_SMALL, DT_Y1, DT_EDT_W, 0}, 1, daysInMonth(), [=]() -> int32_t { return m_tm.tm_mday; }, [=](int32_t newValue) { m_last_tm.tm_mday = m_tm.tm_mday = newValue; @@ -155,7 +155,7 @@ class DateTimeWindow : public Window // Time new StaticText(this, rect_t{PAD_TINY, DT_Y2 + PAD_MEDIUM, SubPage::EDT_X - PAD_TINY - PAD_SMALL, EdgeTxStyles::PAGE_LINE_HEIGHT}, STR_TIME); hour = new NumberEdit( - this, rect_t{SubPage::EDT_X, DT_Y2, DT_EDT_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, 0, 23, + this, rect_t{SubPage::EDT_X, DT_Y2, DT_EDT_W, 0}, 0, 23, [=]() -> int32_t { return m_tm.tm_hour; }, [=](int32_t newValue) { m_last_tm.tm_hour = m_tm.tm_hour = newValue; @@ -165,7 +165,7 @@ class DateTimeWindow : public Window [](int32_t value) { return formatNumberAsString(value, LEADING0, 2); }); minutes = new NumberEdit( - this, rect_t{SubPage::EDT_X + DT_EDT_W + PAD_TINY, DT_Y2, DT_EDT_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, 0, 59, + this, rect_t{SubPage::EDT_X + DT_EDT_W + PAD_TINY, DT_Y2, DT_EDT_W, 0}, 0, 59, [=]() -> int32_t { return m_tm.tm_min; }, [=](int32_t newValue) { m_last_tm.tm_min = m_tm.tm_min = newValue; @@ -175,7 +175,7 @@ class DateTimeWindow : public Window [](int32_t value) { return formatNumberAsString(value, LEADING0, 2); }); seconds = new NumberEdit( - this, rect_t{SubPage::EDT_X + DT_EDT_W * 2 + PAD_SMALL, DT_Y2, DT_EDT_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, 0, 59, + this, rect_t{SubPage::EDT_X + DT_EDT_W * 2 + PAD_SMALL, DT_Y2, DT_EDT_W, 0}, 0, 59, [=]() -> int32_t { return m_tm.tm_sec; }, [=](int32_t newValue) { m_last_tm.tm_sec = m_tm.tm_sec = newValue; @@ -739,7 +739,7 @@ static SetupLineDef setupLines[] = { STR_SPLASHSCREEN, [](Window* parent, coord_t x, coord_t y) { new Choice( - parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, STR_SPLASHSCREEN_DELAYS, 0, 7, + parent, {x, y, 0, 0}, STR_SPLASHSCREEN_DELAYS, 0, 7, [=]() -> int32_t { return 3 - g_eeGeneral.splashMode; }, [=](int32_t newValue) { g_eeGeneral.splashMode = 3 - newValue; @@ -751,7 +751,7 @@ static SetupLineDef setupLines[] = { // Play startup sound STR_PLAY_HELLO, [](Window* parent, coord_t x, coord_t y) { - new ToggleSwitch(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, GET_SET_INVERTED(g_eeGeneral.dontPlayHello)); + new ToggleSwitch(parent, {x, y, 0, 0}, GET_SET_INVERTED(g_eeGeneral.dontPlayHello)); } }, #if defined(PWR_BUTTON_PRESS) @@ -760,7 +760,7 @@ static SetupLineDef setupLines[] = { STR_PWR_OFF_DELAY, [](Window* parent, coord_t x, coord_t y) { new Choice( - parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, STR_PWR_OFF_DELAYS, 0, 4, + parent, {x, y, 0, 0}, STR_PWR_OFF_DELAYS, 0, 4, [=]() -> int32_t { return pwrDelayFromYaml(g_eeGeneral.pwrOffSpeed); }, [=](int32_t newValue) { g_eeGeneral.pwrOffSpeed = pwrDelayToYaml(newValue); @@ -774,7 +774,7 @@ static SetupLineDef setupLines[] = { // Power on/off haptic alarm STR_PWR_ON_OFF_HAPTIC, [](Window* parent, coord_t x, coord_t y) { - new ToggleSwitch(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, GET_SET_INVERTED(g_eeGeneral.disablePwrOnOffHaptic)); + new ToggleSwitch(parent, {x, y, 0, 0}, GET_SET_INVERTED(g_eeGeneral.disablePwrOnOffHaptic)); } }, #endif @@ -783,7 +783,7 @@ static SetupLineDef setupLines[] = { // Owner ID STR_OWNER_ID, [](Window* parent, coord_t x, coord_t y) { - new RadioTextEdit(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, g_eeGeneral.ownerRegistrationID, + new RadioTextEdit(parent, {x, y, 0, 0}, g_eeGeneral.ownerRegistrationID, PXX2_LEN_REGISTRATION_ID); } }, @@ -792,7 +792,7 @@ static SetupLineDef setupLines[] = { // Country code STR_COUNTRY_CODE, [](Window* parent, coord_t x, coord_t y) { - new Choice(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, STR_COUNTRY_CODES, 0, 2, + new Choice(parent, {x, y, 0, 0}, STR_COUNTRY_CODES, 0, 2, GET_SET_DEFAULT(g_eeGeneral.countryCode)); } }, @@ -801,7 +801,7 @@ static SetupLineDef setupLines[] = { STR_VOICE_LANGUAGE, [](Window* parent, coord_t x, coord_t y) { auto choice = - new Choice(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, 0, DIM(languagePacks) - 2, + new Choice(parent, {x, y, 0, 0}, 0, DIM(languagePacks) - 2, GET_VALUE(currentLanguagePackIdx), [](uint8_t newValue) { currentLanguagePackIdx = newValue; currentLanguagePack = languagePacks[currentLanguagePackIdx]; @@ -816,7 +816,7 @@ static SetupLineDef setupLines[] = { // Imperial units STR_UNITS_SYSTEM, [](Window* parent, coord_t x, coord_t y) { - new Choice(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, STR_VUNITSSYSTEM, 0, 1, + new Choice(parent, {x, y, 0, 0}, STR_VUNITSSYSTEM, 0, 1, GET_SET_DEFAULT(g_eeGeneral.imperial)); } }, @@ -824,7 +824,7 @@ static SetupLineDef setupLines[] = { // PPM units STR_UNITS_PPM, [](Window* parent, coord_t x, coord_t y) { - new Choice(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, STR_PPMUNIT, PPM_PERCENT_PREC0, PPM_US, + new Choice(parent, {x, y, 0, 0}, STR_PPMUNIT, PPM_PERCENT_PREC0, PPM_US, GET_SET_DEFAULT(g_eeGeneral.ppmunit)); } }, @@ -833,7 +833,7 @@ static SetupLineDef setupLines[] = { STR_SWITCHES_DELAY, [](Window* parent, coord_t x, coord_t y) { auto edit = - new NumberEdit(parent, {x, y, RadioSetupPage::NUM_W, EdgeTxStyles::UI_ELEMENT_HEIGHT}, 0, 100, + new NumberEdit(parent, {x, y, RadioSetupPage::NUM_W, 0}, 0, 100, GET_SET_VALUE_WITH_OFFSET(g_eeGeneral.switchesDelay, 15)); edit->setDisplayHandler([](int32_t value) { return formatNumberAsString(value * 10, 0, 0, nullptr, STR_MS); @@ -844,7 +844,7 @@ static SetupLineDef setupLines[] = { // USB mode STR_USBMODE, [](Window* parent, coord_t x, coord_t y) { - new Choice(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, STR_USBMODES, USB_UNSELECTED_MODE, USB_MAX_MODE, + new Choice(parent, {x, y, 0, 0}, STR_USBMODES, USB_UNSELECTED_MODE, USB_MAX_MODE, GET_SET_DEFAULT(g_eeGeneral.USBMode)); } }, @@ -852,7 +852,7 @@ static SetupLineDef setupLines[] = { { STR_ROTARY_ENC_MODE, [](Window* parent, coord_t x, coord_t y) { - new Choice(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, STR_ROTARY_ENC_OPT, ROTARY_ENCODER_MODE_NORMAL, + new Choice(parent, {x, y, 0, 0}, STR_ROTARY_ENC_OPT, ROTARY_ENCODER_MODE_NORMAL, ROTARY_ENCODER_MODE_INVERT_BOTH, GET_SET_DEFAULT(g_eeGeneral.rotEncMode)); } @@ -862,9 +862,9 @@ static SetupLineDef setupLines[] = { { STR_HATSMODE, [](Window* parent, coord_t x, coord_t y) { - new Choice(parent, {x, y, 120, EdgeTxStyles::UI_ELEMENT_HEIGHT}, STR_HATSOPT, HATSMODE_TRIMS_ONLY, + new Choice(parent, {x, y, 120, 0}, STR_HATSOPT, HATSMODE_TRIMS_ONLY, HATSMODE_SWITCHABLE, GET_SET_DEFAULT(g_eeGeneral.hatsMode)); - new TextButton(parent, {x + 120 + PAD_MEDIUM, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, "?", [=]() { + new TextButton(parent, {x + 120 + PAD_MEDIUM, y, 0, 0}, "?", [=]() { new MessageDialog(parent, STR_HATSMODE_KEYS, STR_HATSMODE_KEYS_HELP, "", LEFT); return 0; @@ -878,7 +878,7 @@ static SetupLineDef setupLines[] = { [](Window* parent, coord_t x, coord_t y) { uint8_t mains = adcGetMaxInputs(ADC_INPUT_MAIN); auto max_order = inputMappingGetMaxChannelOrder() - 1; - auto choice = new Choice(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, 0, max_order, + auto choice = new Choice(parent, {x, y, 0, 0}, 0, max_order, GET_SET_DEFAULT(g_eeGeneral.templateSetup)); choice->setTextHandler([=](uint8_t value) { @@ -894,7 +894,7 @@ static SetupLineDef setupLines[] = { // Stick mode STR_MODE, [](Window* parent, coord_t x, coord_t y) { - auto choice = new Choice(parent, {x, y, 0, EdgeTxStyles::UI_ELEMENT_HEIGHT}, 0, 3, GET_DEFAULT(g_eeGeneral.stickMode), + auto choice = new Choice(parent, {x, y, 0, 0}, 0, 3, GET_DEFAULT(g_eeGeneral.stickMode), [=](uint8_t newValue) { mixerTaskStop(); g_eeGeneral.stickMode = newValue; diff --git a/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp b/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp index 7f05c3828..1d271689d 100644 --- a/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp +++ b/radio/src/gui/colorlcd/radio_spectrum_analyser.cpp @@ -51,8 +51,8 @@ class SpectrumFooterWindow : public Window { setFlexLayout(); padAll(PAD_ZERO); - padLeft(4); - padRight(4); + padLeft(PAD_SMALL); + padRight(PAD_SMALL); FlexGridLayout grid(col_dsc, row_dsc); diff --git a/radio/src/gui/colorlcd/radio_theme.cpp b/radio/src/gui/colorlcd/radio_theme.cpp index 3bf6b7e66..e91d53624 100644 --- a/radio/src/gui/colorlcd/radio_theme.cpp +++ b/radio/src/gui/colorlcd/radio_theme.cpp @@ -108,21 +108,23 @@ class ThemeDetailsDialog : public BaseDialog { FlexGridLayout grid(d_col_dsc, row_dsc, PAD_TINY); + strAppend(name, this->theme.getName().c_str(), SELECTED_THEME_NAME_LEN); + strAppend(author, this->theme.getAuthor().c_str(), ThemeFile::AUTHOR_LENGTH); + strAppend(info, this->theme.getInfo().c_str(), ThemeFile::INFO_LENGTH); + auto line = form->newLine(grid); line->padAll(PAD_TINY); new StaticText(line, rect_t{}, STR_NAME); - auto te = new TextEdit(line, rect_t{}, this->theme.getName(), - SELECTED_THEME_NAME_LEN); + auto te = new TextEdit(line, rect_t{}, name, SELECTED_THEME_NAME_LEN); lv_obj_set_grid_cell(te->getLvObj(), LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 0, 1); line = form->newLine(grid); line->padAll(PAD_TINY); - line->padTop(2); new StaticText(line, rect_t{}, STR_AUTHOR); - te = new TextEdit(line, rect_t{}, this->theme.getAuthor(), AUTHOR_LENGTH); + te = new TextEdit(line, rect_t{}, author, ThemeFile::AUTHOR_LENGTH); lv_obj_set_grid_cell(te->getLvObj(), LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 0, 1); @@ -134,7 +136,7 @@ class ThemeDetailsDialog : public BaseDialog new StaticText(line, rect_t{}, STR_DESCRIPTION); line = form->newLine(grid2); line->padAll(PAD_TINY); - te = new TextEdit(line, rect_t{}, this->theme.getInfo(), INFO_LENGTH); + te = new TextEdit(line, rect_t{}, info, ThemeFile::INFO_LENGTH); lv_obj_set_grid_cell(te->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, 2, LV_GRID_ALIGN_CENTER, 0, 1); @@ -152,9 +154,13 @@ class ThemeDetailsDialog : public BaseDialog button = new TextButton(line, rect_t{0, 0, lv_pct(30), 0}, STR_SAVE, [=]() { - if (saveHandler != nullptr) + if (saveHandler != nullptr) { + this->theme.setName(name); + this->theme.setAuthor(author); + this->theme.setInfo(info); if (!saveHandler(this->theme)) return 0; + } deleteLater(); return 0; }); @@ -164,6 +170,9 @@ class ThemeDetailsDialog : public BaseDialog protected: ThemeFile theme; + char name[SELECTED_THEME_NAME_LEN + 1]; + char author[ThemeFile::AUTHOR_LENGTH + 1]; + char info[ThemeFile::INFO_LENGTH + 1]; std::function saveHandler = nullptr; }; @@ -302,7 +311,7 @@ class ColorEditPage : public Page #endif // page tabs - rect_t r = {LCD_W - 2 * (BUTTON_WIDTH + 5), PAD_MEDIUM, BUTTON_WIDTH, EdgeTxStyles::UI_ELEMENT_HEIGHT}; + rect_t r = {LCD_W - 2 * (BUTTON_WIDTH + 5), PAD_MEDIUM, BUTTON_WIDTH, 0}; _tabs.emplace_back(new TextButton(window, r, "RGB", [=]() { setActiveColorBar(0); return 1; @@ -335,7 +344,7 @@ class ThemeEditPage : public Page { if (_dirty) { new ConfirmDialog( - this, STR_SAVE_THEME, _theme.getName(), + this, STR_SAVE_THEME, _theme.getName().c_str(), [=]() { if (saveHandler != nullptr) { saveHandler(_theme); @@ -377,7 +386,7 @@ class ThemeEditPage : public Page #endif // save and cancel - rect_t r = {LCD_W - (ColorEditPage::BUTTON_WIDTH + 5), PAD_MEDIUM, ColorEditPage::BUTTON_WIDTH, EdgeTxStyles::UI_ELEMENT_HEIGHT}; + rect_t r = {LCD_W - (ColorEditPage::BUTTON_WIDTH + 5), PAD_MEDIUM, ColorEditPage::BUTTON_WIDTH, 0}; new TextButton(window, r, STR_DETAILS, [=]() { new ThemeDetailsDialog(page, _theme, [=](ThemeFile t) { _theme.setAuthor(t.getAuthor()); @@ -435,7 +444,7 @@ ThemeSetupPage::ThemeSetupPage(TabsGroup *tabsGroup) : void ThemeSetupPage::setAuthor(ThemeFile *theme) { std::string s(""); - if (theme && (strlen(theme->getAuthor()) > 0)) { + if (theme && !theme->getAuthor().empty()) { s = s + "By: " + theme->getAuthor(); } authorText->setText(s); @@ -443,7 +452,7 @@ void ThemeSetupPage::setAuthor(ThemeFile *theme) void ThemeSetupPage::setName(ThemeFile *theme) { - if (theme && (strlen(theme->getName()) > 0)) { + if (theme && !theme->getName().empty()) { nameText->setText(theme->getName()); } else { nameText->setText(""); @@ -466,16 +475,6 @@ void ThemeSetupPage::checkEvents() if (fileCarosell) fileCarosell->pause(!isTopWindow(pageWindow)); } -static void removeAllWhiteSpace(char *str) -{ - int len = strlen(str); - int origLen = len; - while (len) { - if (isspace(str[len])) memmove(str + len, str + len + 1, origLen - len); - len--; - } -} - void ThemeSetupPage::displayThemeMenu(Window *window, ThemePersistance *tp) { auto menu = new Menu(listBox, false); @@ -528,10 +527,16 @@ void ThemeSetupPage::displayThemeMenu(Window *window, ThemePersistance *tp) ThemeFile newTheme; new ThemeDetailsDialog(window, newTheme, [=](ThemeFile theme) { - if (strlen(theme.getName()) != 0) { - char name[SELECTED_THEME_NAME_LEN + 20]; - strncpy(name, theme.getName(), SELECTED_THEME_NAME_LEN + 19); - removeAllWhiteSpace(name); + if (!theme.getName().empty()) { + char name[SELECTED_THEME_NAME_LEN + 1]; + int n = 0; + for (size_t i = 0; i < theme.getName().size(); i += 1) { + if (!isspace(theme.getName()[i])) { + name[n] = theme.getName()[i]; + n += 1; + } + } + name[n] = 0; // use the selected themes color list to make the new theme auto themeIdx = listBox->getSelected(); @@ -559,7 +564,7 @@ void ThemeSetupPage::displayThemeMenu(Window *window, ThemePersistance *tp) menu->addLine(STR_DELETE, [=]() { new ConfirmDialog( window, STR_DELETE_THEME, - tp->getThemeByIndex(listBox->getSelected())->getName(), [=] { + tp->getThemeByIndex(listBox->getSelected())->getName().c_str(), [=] { tp->deleteThemeByIndex(listBox->getSelected()); listBox->setNames(tp->getNames()); currentTheme = min(currentTheme, tp->getNames().size() - 1); diff --git a/radio/src/gui/colorlcd/radio_tools.cpp b/radio/src/gui/colorlcd/radio_tools.cpp index aee9ffad5..8d0ded996 100644 --- a/radio/src/gui/colorlcd/radio_tools.cpp +++ b/radio/src/gui/colorlcd/radio_tools.cpp @@ -178,11 +178,7 @@ struct ToolButton : public TextButton { return 0; }) { -#if !PORTRAIT_LCD - setWidth((LCD_W - 24) / 3); // 3 columns on landscape -#else - setWidth((LCD_W - 18) / 2); // 2 columns on portrait -#endif + setWidth(TOOLS_BTN_W); setHeight(TOOLS_BTN_H); lv_obj_set_width(label, lv_pct(100)); @@ -190,6 +186,7 @@ struct ToolButton : public TextButton { lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); } + static LAYOUT_VAL(TOOLS_BTN_W, (LCD_W - 24) / 3, (LCD_W - 18) / 2) static LAYOUT_VAL(TOOLS_BTN_H, 48, 48) }; diff --git a/radio/src/gui/colorlcd/radio_trainer.cpp b/radio/src/gui/colorlcd/radio_trainer.cpp index 9971f7790..bdecfe2df 100644 --- a/radio/src/gui/colorlcd/radio_trainer.cpp +++ b/radio/src/gui/colorlcd/radio_trainer.cpp @@ -75,7 +75,7 @@ void RadioTrainerPage::build(Window* form) #if PORTRAIT_LCD line = form->newLine(grid); line->padLeft(30); - line->padBottom(8); + line->padBottom(PAD_LARGE); #endif LcdFlags flags = LEFT | COLOR_THEME_PRIMARY1; @@ -93,12 +93,12 @@ void RadioTrainerPage::build(Window* form) #if PORTRAIT_LCD line->padTop(10); #else - line->padTop(6); + line->padTop(PAD_MEDIUM); #endif // Trainer multiplier auto lbl = new StaticText(line, rect_t{}, STR_MULTIPLIER); - lbl->padRight(4); + lbl->padRight(PAD_SMALL); lv_obj_set_grid_cell(lbl->getLvObj(), LV_GRID_ALIGN_END, 0, 2, LV_GRID_ALIGN_CENTER, 0, 1); diff --git a/radio/src/gui/colorlcd/sourcechoice.cpp b/radio/src/gui/colorlcd/sourcechoice.cpp index 6caa5207e..bb90710fd 100644 --- a/radio/src/gui/colorlcd/sourcechoice.cpp +++ b/radio/src/gui/colorlcd/sourcechoice.cpp @@ -29,12 +29,6 @@ #include "strhelpers.h" #include "switches.h" -#if !PORTRAIT_LCD -#define FILTER_COLUMNS 3 -#else -#define FILTER_COLUMNS 2 -#endif - class SourceChoiceMenuToolbar : public MenuToolbar { public: @@ -148,6 +142,8 @@ class SourceChoiceMenuToolbar : public MenuToolbar } } + static LAYOUT_VAL(FILTER_COLUMNS, 3, 2) + protected: #if defined(HARDWARE_TOUCH) MenuToolbarButton* invertBtn = nullptr; diff --git a/radio/src/gui/colorlcd/special_functions.cpp b/radio/src/gui/colorlcd/special_functions.cpp index 9a3b885b6..0255d7673 100644 --- a/radio/src/gui/colorlcd/special_functions.cpp +++ b/radio/src/gui/colorlcd/special_functions.cpp @@ -742,17 +742,7 @@ void FunctionsPage::plusPopup(Window *window) void FunctionsPage::build(Window *window) { -#if !PORTRAIT_LCD -#define PER_ROW 6 - static const lv_coord_t l_col_dsc[] = { - LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), - LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; -#else -#define PER_ROW 4 - static const lv_coord_t l_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), - LV_GRID_FR(1), LV_GRID_FR(1), - LV_GRID_TEMPLATE_LAST}; -#endif + static const lv_coord_t l_col_dsc[] = {LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; window->padAll(PAD_SMALL); window->setFlexLayout(LV_FLEX_FLOW_COLUMN, PAD_ZERO); @@ -776,7 +766,7 @@ void FunctionsPage::build(Window *window) auto button = functionButton( line, rect_t{0, 0, window->width() - 12, SF_BUTTON_H}, i); - lv_obj_set_grid_cell(button->getLvObj(), LV_GRID_ALIGN_CENTER, 0, PER_ROW, + lv_obj_set_grid_cell(button->getLvObj(), LV_GRID_ALIGN_CENTER, 0, 1, LV_GRID_ALIGN_CENTER, 0, 1); if (focusIndex == i) { diff --git a/radio/src/gui/colorlcd/startup_shutdown.cpp b/radio/src/gui/colorlcd/startup_shutdown.cpp index da41e515f..efeb377da 100644 --- a/radio/src/gui/colorlcd/startup_shutdown.cpp +++ b/radio/src/gui/colorlcd/startup_shutdown.cpp @@ -23,7 +23,6 @@ #include "inactivity_timer.h" #include "opentx.h" #include "stamp.h" -#include "theme.h" #include "theme_manager.h" extern void checkSpeakerVolume(); diff --git a/radio/src/gui/colorlcd/tabsgroup.cpp b/radio/src/gui/colorlcd/tabsgroup.cpp index a0e0e44a1..8a47062ab 100644 --- a/radio/src/gui/colorlcd/tabsgroup.cpp +++ b/radio/src/gui/colorlcd/tabsgroup.cpp @@ -21,7 +21,7 @@ #include "tabsgroup.h" -#include "theme.h" +#include "theme_manager.h" #include "themes/etx_lv_theme.h" #include "view_main.h" #include "topbar_impl.h" @@ -30,173 +30,6 @@ #include "keyboard_base.h" #endif -class SelectedTabIcon : public StaticIcon -{ - public: - SelectedTabIcon(Window* parent) : - StaticIcon(parent, 0, 0, ICON_CURRENTMENU_SHADOW, COLOR_THEME_PRIMARY1) - { - new StaticIcon(this, 0, 0, ICON_CURRENTMENU_BG, COLOR_THEME_FOCUS); - new StaticIcon(this, SEL_DOT_X, SEL_DOT_Y, ICON_CURRENTMENU_DOT, COLOR_THEME_PRIMARY2); - } - -#if defined(DEBUG_WINDOWS) - std::string getName() const override { return "SelectedTabIcon"; } -#endif - - static LAYOUT_VAL(SEL_DOT_X, 10, 10) - static LAYOUT_VAL(SEL_DOT_Y, 39, 39) -}; - -class TabCarouselButton : public ButtonBase -{ - public: - TabCarouselButton(Window* parent, const rect_t& rect, PageTab* page) : - ButtonBase(parent, rect, nullptr, window_create), pageTab(page) - { - selected = new SelectedTabIcon(this); - selected->hide(); - - lastIcon = getIcon(); - icon = new StaticIcon(this, 2, ICON_Y, lastIcon, COLOR_THEME_PRIMARY2); - - show(isVisible()); - } - - ~TabCarouselButton() - { - delete pageTab; - } - -#if defined(DEBUG_WINDOWS) - std::string getName() const override - { - return "TabCarouselButton(" + std::to_string(getIcon()) + ")"; - } -#endif - - bool isVisible() const { return pageTab->isVisible(); } - - EdgeTxIcon getIcon() const { return pageTab->getIcon(); } - PageTab* page() const { return pageTab; } - - static LAYOUT_VAL(ICON_Y, 7, 7) - - protected: - PageTab* pageTab; - EdgeTxIcon lastIcon; - SelectedTabIcon* selected = nullptr; - StaticIcon* icon = nullptr; - - void checkEvents() override - { - selected->show(checked()); - show(isVisible()); - if (lastIcon != getIcon()) { - lastIcon = getIcon(); - icon->setIcon(lastIcon); - } - ButtonBase::checkEvents(); - } -}; - -class TabsCarousel : public Window -{ - public: - TabsCarousel(Window* parent, TabsGroup* menu) : - Window(parent, - {TopBar::MENU_HEADER_BUTTONS_LEFT, 0, - LCD_W - HDR_DATE_FULL_WIDTH - TopBar::MENU_HEADER_BUTTONS_LEFT, EdgeTxStyles::MENU_HEADER_HEIGHT + 10}), - menu(menu) - { - setWindowFlag(NO_FOCUS); - - lv_obj_set_style_max_width(lvobj, LCD_W - HDR_DATE_FULL_WIDTH - TopBar::MENU_HEADER_BUTTONS_LEFT, - LV_PART_MAIN); - - padAll(PAD_ZERO); - setFlexLayout(LV_FLEX_FLOW_ROW, PAD_ZERO); - lv_obj_set_flex_align(lvobj, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, - LV_FLEX_ALIGN_CENTER); - - setCurrentIndex(0); - } - -#if defined(DEBUG_WINDOWS) - std::string getName() const override { return "TabsCarousel"; } -#endif - - void setCurrentIndex(uint8_t index) - { - if (index < buttons.size()) { - buttons[currentIndex]->check(false); - currentIndex = index; - buttons[currentIndex]->check(true); - } - } - - void nextTab() - { - uint8_t idx = currentIndex; - do { - idx += 1; - if (idx >= buttons.size()) idx = 0; - } while (!buttons[idx]->isVisible()); - menu->setCurrentTab(idx); - } - - void prevTab() - { - uint8_t idx = currentIndex; - do { - if (idx == 0) idx = buttons.size(); - idx -= 1; - } while (!buttons[idx]->isVisible()); - menu->setCurrentTab(idx); - } - - void addTab(PageTab* page) - { - TabCarouselButton* btn = new TabCarouselButton( - this, {0, 0, MENU_HEADER_BUTTON_WIDTH + 3, TabsGroup::MENU_TITLE_TOP + 5}, page); - btn->setPressHandler([=]() { - menu->setCurrentTab(getIndex(btn->getIcon())); - return true; - }); - btn->show(btn->isVisible()); - buttons.emplace_back(btn); - } - - void removeTab(unsigned index) - { - auto btn = buttons[index]; - buttons.erase(buttons.begin() + index); - btn->deleteLater(); - for (uint8_t i = 0; i < buttons.size(); i += 1) - buttons[i]->page()->update(i); - } - - PageTab* pageTab(uint8_t idx) const { return buttons[idx]->page(); } - bool isCurrent(uint8_t idx) const { return currentIndex == idx; } - uint8_t tabCount() const { return buttons.size(); } - - protected: - std::vector buttons; - TabsGroup* menu; - uint8_t currentIndex = 0; - - uint8_t getIndex(EdgeTxIcon icon) - { - for (uint8_t i = 0; i < buttons.size(); i += 1) { - if (buttons[i]->getIcon() == icon) return i; - } - return -1; - } - - static LAYOUT_VAL(MENU_HEADER_BUTTON_WIDTH, 33, 33) - static LAYOUT_VAL(HDR_DATE_FULL_WIDTH, 51, 51) -}; - #if defined(DEBUG) static uint32_t dsms, dems, end_ms, start_ms; static bool timepg = false; @@ -216,20 +49,89 @@ static void on_draw_end(lv_event_t* e) } #endif +class SelectedTabIcon : public StaticIcon +{ + public: + SelectedTabIcon(Window* parent) : + StaticIcon(parent, 0, 0, ICON_CURRENTMENU_SHADOW, COLOR_THEME_PRIMARY1) + { + new StaticIcon(this, 0, 0, ICON_CURRENTMENU_BG, COLOR_THEME_FOCUS); + new StaticIcon(this, SEL_DOT_X, SEL_DOT_Y, ICON_CURRENTMENU_DOT, COLOR_THEME_PRIMARY2); + } + +#if defined(DEBUG_WINDOWS) + std::string getName() const override { return "SelectedTabIcon"; } +#endif + + static LAYOUT_VAL(SEL_DOT_X, 10, 10) + static LAYOUT_VAL(SEL_DOT_Y, 39, 39) +}; + +class TabsGroupButton : public ButtonBase +{ + public: + TabsGroupButton(Window* parent, const rect_t& rect, PageTab* page, int idx) : + ButtonBase(parent, rect, nullptr, window_create), pageTab(page), index(idx) + { + lastIcon = pageTab->getIcon(); + icon = new StaticIcon(this, 2, ICON_Y, lastIcon, COLOR_THEME_PRIMARY2); + + show(isVisible()); + } + + ~TabsGroupButton() + { + delete pageTab; + } + +#if defined(DEBUG_WINDOWS) + std::string getName() const override + { + return "TabsGroupButton(" + std::to_string(lastIcon) + ")"; + } +#endif + + bool isVisible() const { return pageTab->isVisible(); } + + PageTab* page() const { return pageTab; } + int getIndex() const { return index; } + void setIndex(int idx) + { + index = idx; + pageTab->update(index); + } + + static LAYOUT_VAL(ICON_Y, 7, 7) + + protected: + PageTab* pageTab; + EdgeTxIcon lastIcon; + StaticIcon* icon = nullptr; + int index; + + void checkEvents() override + { + show(isVisible()); + if (lastIcon != pageTab->getIcon()) { + lastIcon = pageTab->getIcon(); + icon->setIcon(lastIcon); + } + ButtonBase::checkEvents(); + } +}; + class TabsGroupHeader : public Window { - friend class TabsGroup; - public: TabsGroupHeader(TabsGroup* menu, EdgeTxIcon icon) : Window(menu, {0, 0, LCD_W, TabsGroup::MENU_BODY_TOP}), - icon(icon) + menu(menu) { setWindowFlag(NO_FOCUS | OPAQUE); etx_solid_bg(lvobj, COLOR_THEME_SECONDARY1_INDEX); - headerIcon = new HeaderIcon(this, icon); + new HeaderIcon(this, icon); auto sep = lv_obj_create(lvobj); etx_solid_bg(sep); @@ -244,9 +146,15 @@ class TabsGroupHeader : public Window lv_obj_set_size(titleLabel, LCD_W, TabsGroup::MENU_TITLE_HEIGHT); setTitle(""); - carousel = new TabsCarousel(this, menu); + carousel = new Window(this, + {TopBar::MENU_HEADER_BUTTONS_LEFT, 0, + LCD_W - HDR_DATE_FULL_WIDTH - TopBar::MENU_HEADER_BUTTONS_LEFT, EdgeTxStyles::MENU_HEADER_HEIGHT + 10}); + carousel->padAll(PAD_ZERO); + carousel->setWindowFlag(NO_FOCUS); - dateTime = new HeaderDateTime(lvobj, LCD_W - DATE_XO, DATE_Y); + selectedIcon = new SelectedTabIcon(carousel); + + new HeaderDateTime(this, LCD_W - DATE_XO, DATE_Y); } void setTitle(const char* title) { lv_label_set_text(titleLabel, title); } @@ -255,34 +163,101 @@ class TabsGroupHeader : public Window std::string getName() const override { return "TabsGroupHeader"; } #endif + void setCurrentIndex(uint8_t index) + { + if (index < buttons.size()) { + buttons[currentIndex]->check(false); + currentIndex = index; + buttons[currentIndex]->check(true); + selectedIcon->setPos(getX(currentIndex), 0); + } + } + + void chgTab(int dir) + { + int idx = currentIndex; + do { + idx += dir; + if (idx < 0) idx = buttons.size() - 1; + if (idx >= (int)buttons.size()) idx = 0; + } while (!buttons[idx]->isVisible()); + menu->setCurrentTab(idx); + } + + void nextTab() { chgTab(1); } + void prevTab() { chgTab(-1); } + + void addTab(PageTab* page) + { + uint8_t idx = buttons.size(); + TabsGroupButton* btn = new TabsGroupButton( + carousel, {getX(idx), 0, MENU_HEADER_BUTTON_WIDTH + 3, TabsGroup::MENU_TITLE_TOP + 5}, page, idx); + btn->setPressHandler([=]() { + menu->setCurrentTab(btn->getIndex()); + return true; + }); + btn->show(btn->isVisible()); + buttons.emplace_back(btn); + } + + void removeTab(unsigned index) + { + auto btn = buttons[index]; + buttons.erase(buttons.begin() + index); + btn->deleteLater(); + updateLayout(); + } + + void updateLayout() + { + for (uint8_t i = 0; i < buttons.size(); i += 1) { + buttons[i]->setIndex(i); + buttons[i]->setPos(getX(i), 0); + } + } + + PageTab* pageTab(uint8_t idx) const { return buttons[idx]->page(); } + bool isCurrent(uint8_t idx) const { return currentIndex == idx; } + uint8_t tabCount() const { return buttons.size(); } + static LAYOUT_VAL(DATE_XO, 48, 48) static LAYOUT_VAL(DATE_Y, 6, 6) + static LAYOUT_VAL(MENU_HEADER_BUTTON_WIDTH, 33, 33) + static LAYOUT_VAL(HDR_DATE_FULL_WIDTH, 51, 51) protected: - EdgeTxIcon icon; - TabsCarousel* carousel = nullptr; + uint8_t currentIndex = 0; + TabsGroup* menu; lv_obj_t* titleLabel = nullptr; - HeaderDateTime* dateTime = nullptr; - HeaderIcon* headerIcon = nullptr; + SelectedTabIcon* selectedIcon = nullptr; + Window* carousel = nullptr; + std::vector buttons; + + coord_t getX(uint8_t idx) + { + coord_t x = 0; + for (uint8_t i = 0; i < idx; i += 1) + if (buttons[i]->isVisible()) + x += MENU_HEADER_BUTTON_WIDTH; + return x; + } void checkEvents() override { - dateTime->update(); + updateLayout(); Window::checkEvents(); } - - void updateDateTime(); }; TabsGroup::TabsGroup(EdgeTxIcon icon) : NavWindow(MainWindow::instance(), {0, 0, LCD_W, LCD_H}) { - header = new TabsGroupHeader(this, icon); - body = - new Window(this, {0, MENU_BODY_TOP, LCD_W, MENU_BODY_HEIGHT}); - body->setWindowFlag(NO_FOCUS); - etx_solid_bg(lvobj); + + header = new TabsGroupHeader(this, icon); + + body = new Window(this, {0, MENU_BODY_TOP, LCD_W, MENU_BODY_HEIGHT}); + body->setWindowFlag(NO_FOCUS); lv_obj_set_style_max_height(body->getLvObj(), MENU_BODY_HEIGHT, LV_PART_MAIN); etx_scrollbar(body->getLvObj()); @@ -299,43 +274,16 @@ TabsGroup::TabsGroup(EdgeTxIcon icon) : #endif } -uint8_t TabsGroup::tabCount() const { return header->carousel->tabCount(); } +uint8_t TabsGroup::tabCount() const { return header->tabCount(); } void TabsGroup::setCurrentTab(unsigned index) { - header->carousel->setCurrentIndex(index); - setVisibleTab(header->carousel->pageTab(index)); -} + header->setCurrentIndex(index); -void TabsGroup::deleteLater(bool detach, bool trash) -{ - if (_deleted) return; + PageTab* tab = header->pageTab(index); - Layer::pop(this); - Layer::back()->show(); - - Window::deleteLater(detach, trash); -} - -void TabsGroup::addTab(PageTab* page) -{ - header->carousel->addTab(page); - if (!currentTab) { - setCurrentTab(0); - } -} - -void TabsGroup::removeTab(unsigned index) -{ - if (header->carousel->isCurrent(index)) - setCurrentTab(max(0, index - 1)); - header->carousel->removeTab(index); -} - -void TabsGroup::setVisibleTab(PageTab* tab) -{ if (tab != currentTab && !deleted()) { - header->setTitle(tab->title.c_str()); + header->setTitle(tab->getTitle().c_str()); lv_obj_enable_style_refresh(false); @@ -357,7 +305,7 @@ void TabsGroup::setVisibleTab(PageTab* tab) lv_obj_remove_local_style_prop(body->getLvObj(), remStyles[i], LV_PART_MAIN); - body->padAll(tab->padding); + body->padAll(tab->getPadding()); tab->build(body); @@ -370,6 +318,31 @@ void TabsGroup::setVisibleTab(PageTab* tab) } } +void TabsGroup::deleteLater(bool detach, bool trash) +{ + if (_deleted) return; + + Layer::pop(this); + Layer::back()->show(); + + Window::deleteLater(detach, trash); +} + +void TabsGroup::addTab(PageTab* page) +{ + header->addTab(page); + if (!currentTab) { + setCurrentTab(0); + } +} + +void TabsGroup::removeTab(unsigned index) +{ + if (header->isCurrent(index)) + setCurrentTab(max(0, index - 1)); + header->removeTab(index); +} + void TabsGroup::checkEvents() { Window::checkEvents(); @@ -380,23 +353,10 @@ void TabsGroup::checkEvents() } #if defined(HARDWARE_KEYS) -void TabsGroup::onPressPGUP() { header->carousel->prevTab(); } -void TabsGroup::onPressPGDN() { header->carousel->nextTab(); } +void TabsGroup::onPressPGUP() { header->prevTab(); } +void TabsGroup::onPressPGDN() { header->nextTab(); } #endif void TabsGroup::onClicked() { Keyboard::hide(false); } void TabsGroup::onCancel() { deleteLater(); } - -#if defined(PCBNV14) || defined(PCBPL18) -void TabsGroup::addGoToMonitorsButton() -{ - new TextButton( - header, - {LCD_W / 2 + 6, MENU_TITLE_TOP + 1, LCD_W / 2 - 8, MENU_TITLE_HEIGHT - 2}, - STR_OPEN_CHANNEL_MONITORS, [=]() { - pushEvent(EVT_KEY_FIRST(KEY_MODEL)); - return 0; - }); -} -#endif diff --git a/radio/src/gui/colorlcd/tabsgroup.h b/radio/src/gui/colorlcd/tabsgroup.h index 3f4e5c498..a6f702402 100644 --- a/radio/src/gui/colorlcd/tabsgroup.h +++ b/radio/src/gui/colorlcd/tabsgroup.h @@ -24,13 +24,9 @@ class TabsGroup; class TabsGroupHeader; -class TabsCarousel; class PageTab { - friend class TabsCarousel; - friend class TabsGroup; - public: PageTab(PaddingSize padding = PAD_MEDIUM) : padding(padding) {} @@ -49,10 +45,13 @@ class PageTab virtual void checkEvents() {} void setTitle(std::string value) { title = std::move(value); } + std::string getTitle() const { return title; } void setIcon(EdgeTxIcon icon) { this->icon = icon; } EdgeTxIcon getIcon() const { return icon; } + PaddingSize getPadding() const { return padding; } + virtual void update(uint8_t index) {} virtual void cleanup() {} @@ -64,8 +63,6 @@ class PageTab class TabsGroup : public NavWindow { - friend class TabsCarousel; - public: explicit TabsGroup(EdgeTxIcon icon); @@ -98,14 +95,8 @@ class TabsGroup : public NavWindow Window* body = nullptr; PageTab* currentTab = nullptr; - void setVisibleTab(PageTab* tab); - #if defined(HARDWARE_KEYS) void onPressPGUP() override; void onPressPGDN() override; #endif - -#if defined(PCBNV14) || defined(PCBPL18) - void addGoToMonitorsButton(void); -#endif }; diff --git a/radio/src/gui/colorlcd/theme.cpp b/radio/src/gui/colorlcd/theme.cpp deleted file mode 100644 index e5316d828..000000000 --- a/radio/src/gui/colorlcd/theme.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) EdgeTX - * - * Based on code named - * opentx - https://github.com/opentx/opentx - * 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 "theme.h" - -#include "libopenui.h" -#include "theme_manager.h" -#include "topbar_impl.h" - -EdgeTxTheme* EdgeTxTheme::_instance = nullptr; - -EdgeTxTheme* EdgeTxTheme::instance() -{ - if (!_instance) _instance = new EdgeTxTheme(); - return _instance; -} - -EdgeTxTheme::EdgeTxTheme() {} - -void EdgeTxTheme::load() -{ - initLvglTheme(); - ThemePersistance::instance()->loadDefaultTheme(); -} - -void EdgeTxTheme::update() -{ - styles->applyColors(); - if (!backgroundBitmap) { - backgroundBitmap = BitmapBuffer::loadBitmap( - THEMES_PATH "/EdgeTX/background.png", BMP_RGB565); - } - if (backgroundBitmap) MainWindow::instance()->setBackground(backgroundBitmap); -} - -void EdgeTxTheme::setBackgroundImageFileName(const char* fileName) -{ - // ensure you delete old bitmap - if (backgroundBitmap != nullptr) delete backgroundBitmap; - - strncpy(backgroundImageFileName, fileName, FF_MAX_LFN); - backgroundImageFileName[FF_MAX_LFN] = '\0'; // ensure string termination - - // Try to load bitmap. If this fails backgroundBitmap will be NULL and default - // will be loaded in update() method - backgroundBitmap = - BitmapBuffer::loadBitmap(backgroundImageFileName, BMP_RGB565); -} - -HeaderDateTime::HeaderDateTime(lv_obj_t* parent, coord_t x, coord_t y) -{ - date = lv_label_create(parent); - lv_obj_set_pos(date, x, y); - lv_obj_set_size(date, HDR_DATE_WIDTH, HDR_DATE_HEIGHT); - lv_obj_set_style_text_align(date, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN); - etx_txt_color(date, COLOR_THEME_PRIMARY2_INDEX); - etx_font(date, FONT_XS_INDEX); - - time = lv_label_create(parent); - lv_obj_set_pos(time, x, y + HDR_DATE_LINE2); - lv_obj_set_size(time, HDR_DATE_WIDTH, HDR_DATE_HEIGHT); - lv_obj_set_style_text_align(time, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN); - etx_txt_color(time, COLOR_THEME_PRIMARY2_INDEX); - etx_font(time, FONT_XS_INDEX); - - update(); -} - -void HeaderDateTime::update() -{ - const TimerOptions timerOptions = {.options = SHOW_TIME}; - struct gtm t; - gettime(&t); - - if (t.tm_min != lastMinute) { - char str[10]; -#if defined(TRANSLATIONS_CN) || defined(TRANSLATIONS_TW) - sprintf(str, "%02d-%02d", t.tm_mon + 1, t.tm_mday); -#else - sprintf(str, "%d %s", t.tm_mday, STR_MONTHS[t.tm_mon]); -#endif - lv_label_set_text(date, str); - - getTimerString(str, getValue(MIXSRC_TX_TIME), timerOptions); - lv_label_set_text(time, str); - - lastMinute = t.tm_min; - } -} - -void HeaderDateTime::setColor(uint32_t color) -{ - lv_obj_set_style_text_color(date, makeLvColor(color), LV_PART_MAIN); - lv_obj_set_style_text_color(time, makeLvColor(color), LV_PART_MAIN); -} - -HeaderIcon::HeaderIcon(Window* parent, EdgeTxIcon icon) : - StaticIcon(parent, 0, 0, ICON_TOPLEFT_BG, COLOR_THEME_FOCUS) -{ - (new StaticIcon(this, 0, 0, icon, COLOR_THEME_PRIMARY2))->center(width(), height()); -} - -UsbSDConnected::UsbSDConnected() : - Window(MainWindow::instance(), {0, 0, LCD_W, LCD_H}) -{ - setWindowFlag(OPAQUE); - - etx_solid_bg(lvobj, COLOR_THEME_PRIMARY1_INDEX); - dateTime = new HeaderDateTime(lvobj, LCD_W - TopBar::HDR_DATE_XO, HDR_DATE_Y); - - auto icon = new StaticIcon(this, 0, 0, ICON_USB_PLUGGED, COLOR_THEME_PRIMARY2); - lv_obj_center(icon->getLvObj()); -} - -void UsbSDConnected::checkEvents() -{ - dateTime->update(); -} diff --git a/radio/src/gui/colorlcd/theme.h b/radio/src/gui/colorlcd/theme.h deleted file mode 100644 index 415ba6d7f..000000000 --- a/radio/src/gui/colorlcd/theme.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) EdgeTX - * - * Based on code named - * opentx - https://github.com/opentx/opentx - * 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 "opentx.h" -#include "bitmaps.h" -#include "static.h" - -class BitmapBuffer; - -class EdgeTxTheme -{ - public: - EdgeTxTheme(); - - static EdgeTxTheme *instance(); - - virtual void load(); - void update(); - - void setBackgroundImageFileName(const char *fileName); - - protected: - static EdgeTxTheme *_instance; - - char backgroundImageFileName[FF_MAX_LFN + 1]; - - const BitmapBuffer *backgroundBitmap = nullptr; -}; - -class HeaderDateTime -{ - public: - HeaderDateTime(lv_obj_t *parent, int x, int y); - void update(); - void setColor(uint32_t color); - - static LAYOUT_VAL(HDR_DATE_WIDTH, 45, 45) - static LAYOUT_VAL(HDR_DATE_HEIGHT, 12, 12) - static LAYOUT_VAL(HDR_DATE_LINE2, 15, 15) - - protected: - lv_obj_t *date = nullptr; - lv_obj_t *time = nullptr; - int8_t lastMinute = -1; -}; - -class HeaderIcon : public StaticIcon -{ - public: - HeaderIcon(Window *parent, EdgeTxIcon icon); -}; - -class UsbSDConnected : public Window -{ - public: - UsbSDConnected(); - - void checkEvents() override; - - static LAYOUT_VAL(HDR_DATE_Y, 6, 6) - - protected: - HeaderDateTime* dateTime = nullptr; -}; diff --git a/radio/src/gui/colorlcd/theme_manager.cpp b/radio/src/gui/colorlcd/theme_manager.cpp index 563ff7907..f17af54e8 100644 --- a/radio/src/gui/colorlcd/theme_manager.cpp +++ b/radio/src/gui/colorlcd/theme_manager.cpp @@ -24,8 +24,8 @@ #include "../../storage/sdcard_common.h" #include "../../storage/yaml/yaml_bits.h" #include "../../storage/yaml/yaml_tree_walker.h" -#include "theme.h" #include "themes/etx_lv_theme.h" +#include "topbar_impl.h" #include "view_main.h" #define SET_DIRTY() storageDirty(EE_GENERAL) @@ -34,7 +34,7 @@ constexpr const char* RGBSTRING = "RGB("; -ThemePersistance themePersistance; +ThemePersistance ThemePersistance::themePersistance; // prototype for SD card function to read a YAML file // TODO: should this be in sdcard header file? @@ -76,8 +76,8 @@ static bool w_color(const YamlNode* node, uint32_t val, yaml_writer_func wf, PACK(struct YAMLThemeSummary { char name[SELECTED_THEME_NAME_LEN + 1]; - char author[AUTHOR_LENGTH + 1]; - char info[INFO_LENGTH + 1]; + char author[ThemeFile::AUTHOR_LENGTH + 1]; + char info[ThemeFile::INFO_LENGTH + 1]; }); PACK(struct YAMLThemeColors { @@ -93,8 +93,8 @@ PACK(struct YAMLTheme { static const struct YamlNode struct_YAMLThemeSummary[] = { YAML_STRING("name", (SELECTED_THEME_NAME_LEN + 1)), - YAML_STRING("author", (AUTHOR_LENGTH + 1)), - YAML_STRING("info", (INFO_LENGTH + 1)), YAML_END}; + YAML_STRING("author", (ThemeFile::AUTHOR_LENGTH + 1)), + YAML_STRING("info", (ThemeFile::INFO_LENGTH + 1)), YAML_END}; static const struct YamlNode struct_YAMLThemeColors[] = { YAML_UNSIGNED_CUST("PRIMARY1", 32, r_color, w_color), @@ -116,14 +116,14 @@ static const struct YamlNode struct_YAMLThemeColors[] = { // TODO: Remove this sometime in the future static const struct YamlNode w_struct_YAMLTheme[] = { YAML_STRUCT("---\r\nsummary", - (SELECTED_THEME_NAME_LEN + AUTHOR_LENGTH + INFO_LENGTH + 3) * 8, + (SELECTED_THEME_NAME_LEN + ThemeFile::AUTHOR_LENGTH + ThemeFile::INFO_LENGTH + 3) * 8, struct_YAMLThemeSummary, NULL), YAML_STRUCT("colors", (LCD_COLOR_COUNT - 1) * 32, struct_YAMLThemeColors, NULL), YAML_END}; static const struct YamlNode r_struct_YAMLTheme[] = { YAML_STRUCT("summary", - (SELECTED_THEME_NAME_LEN + AUTHOR_LENGTH + INFO_LENGTH + 3) * 8, + (SELECTED_THEME_NAME_LEN + ThemeFile::AUTHOR_LENGTH + ThemeFile::INFO_LENGTH + 3) * 8, struct_YAMLThemeSummary, NULL), YAML_STRUCT("colors", (LCD_COLOR_COUNT - 1) * 32, struct_YAMLThemeColors, NULL), @@ -167,9 +167,9 @@ ThemeFile& ThemeFile::operator=(const ThemeFile& theme) if (this == &theme) return *this; path = theme.path; - strAppend(name, theme.name, SELECTED_THEME_NAME_LEN); - strAppend(author, theme.author, AUTHOR_LENGTH); - strAppend(info, theme.info, INFO_LENGTH); + name = theme.name; + author = theme.author; + info = theme.info; colorList.assign(theme.colorList.begin(), theme.colorList.end()); _imageFileNames.assign(theme._imageFileNames.begin(), theme._imageFileNames.end()); @@ -187,9 +187,9 @@ void ThemeFile::serialize() struct YAMLTheme yt; struct YamlNode themeRootNode = YAML_ROOT(w_struct_YAMLTheme); - strAppend(yt.summary.name, name, SELECTED_THEME_NAME_LEN); - strAppend(yt.summary.author, author, AUTHOR_LENGTH); - strAppend(yt.summary.info, info, INFO_LENGTH); + strAppend(yt.summary.name, name.c_str(), SELECTED_THEME_NAME_LEN); + strAppend(yt.summary.author, author.c_str(), ThemeFile::AUTHOR_LENGTH); + strAppend(yt.summary.info, info.c_str(), ThemeFile::INFO_LENGTH); for (auto colorEntry : colorList) { yt.colors.colors[colorEntry.colorNumber] = colorEntry.colorValue; } @@ -211,9 +211,9 @@ void ThemeFile::deSerialize() &tree, nullptr); if (err == nullptr) { - strAppend(name, yt.summary.name, SELECTED_THEME_NAME_LEN); - strAppend(author, yt.summary.author, AUTHOR_LENGTH); - strAppend(info, yt.summary.info, INFO_LENGTH); + name = yt.summary.name; + author = yt.summary.author; + info = yt.summary.info; for (int i = 0; i < LCD_COLOR_COUNT - 1; i += 1) { colorList.emplace_back( ColorEntry{(LcdColorIndex)(i), yt.colors.colors[i]}); @@ -242,7 +242,7 @@ void ThemeFile::applyColors() void ThemeFile::applyBackground() { - auto instance = EdgeTxTheme::instance(); + auto instance = MainWindow::instance(); std::string backgroundImageFileName(getPath()); auto pos = backgroundImageFileName.rfind('/'); if (pos != std::string::npos) { @@ -251,7 +251,7 @@ void ThemeFile::applyBackground() std::to_string(LCD_H) + ".png"; if (isFileAvailable(rootDir.c_str())) { - instance->setBackgroundImageFileName((char*)rootDir.c_str()); + instance->setBackgroundImage((char*)rootDir.c_str()); return; } @@ -259,21 +259,21 @@ void ThemeFile::applyBackground() rootDir = rootDir + "background.png"; if (isFileAvailable(rootDir.c_str())) { - instance->setBackgroundImageFileName((char*)rootDir.c_str()); + instance->setBackgroundImage((char*)rootDir.c_str()); return; } } // Use EdgeTxTheme default background // TODO: This needs to be made user configurable - instance->setBackgroundImageFileName(""); + instance->setBackgroundImage(""); } void ThemeFile::applyTheme() { applyColors(); applyBackground(); - EdgeTxTheme::instance()->update(); + styles->applyColors(); } // avoid leaking memory @@ -327,7 +327,7 @@ void ThemePersistance::scanForThemes() f_closedir(&dir); std::sort(themes.begin(), themes.end(), [](ThemeFile* a, ThemeFile* b) { - return strcmp(a->getName(), b->getName()) < 0; + return a->getName().compare(b->getName()) < 0; }); } } @@ -390,8 +390,7 @@ void ThemePersistance::loadDefaultTheme() } for (auto theme : themes) { - if (strncmp(theme->getName(), g_eeGeneral.selectedTheme, - SELECTED_THEME_NAME_LEN) == 0) { + if (theme->getName().compare(0, SELECTED_THEME_NAME_LEN, g_eeGeneral.selectedTheme) == 0) { found = true; break; } @@ -464,7 +463,7 @@ bool ThemePersistance::createNewTheme(std::string name, ThemeFile& theme) void ThemePersistance::setDefaultTheme(int index) { if (index >= 0 && index < (int)themes.size()) { - strAppend(g_eeGeneral.selectedTheme, themes[index]->getName(), + strAppend(g_eeGeneral.selectedTheme, themes[index]->getName().c_str(), SELECTED_THEME_NAME_LEN); SET_DIRTY(); currentTheme = index; @@ -492,3 +491,69 @@ void ThemePersistance::insertDefaultTheme() auto themeFile = new DefaultEdgeTxTheme(); themes.insert(themes.begin(), themeFile); } + +HeaderDateTime::HeaderDateTime(Window* parent, coord_t x, coord_t y) : + Window(parent, {x, y, HDR_DATE_WIDTH, HDR_DATE_LINE2 + HDR_DATE_HEIGHT + 2}) +{ + date = lv_label_create(lvobj); + lv_obj_set_pos(date, 0, 0); + lv_obj_set_size(date, HDR_DATE_WIDTH, HDR_DATE_HEIGHT); + lv_obj_set_style_text_align(date, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN); + etx_txt_color(date, COLOR_THEME_PRIMARY2_INDEX); + etx_font(date, FONT_XS_INDEX); + + time = lv_label_create(lvobj); + lv_obj_set_pos(time, 0, HDR_DATE_LINE2); + lv_obj_set_size(time, HDR_DATE_WIDTH, HDR_DATE_HEIGHT); + lv_obj_set_style_text_align(time, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN); + etx_txt_color(time, COLOR_THEME_PRIMARY2_INDEX); + etx_font(time, FONT_XS_INDEX); + + checkEvents(); +} + +void HeaderDateTime::checkEvents() +{ + const TimerOptions timerOptions = {.options = SHOW_TIME}; + struct gtm t; + gettime(&t); + + if (t.tm_min != lastMinute) { + char str[10]; +#if defined(TRANSLATIONS_CN) || defined(TRANSLATIONS_TW) + sprintf(str, "%02d-%02d", t.tm_mon + 1, t.tm_mday); +#else + sprintf(str, "%d %s", t.tm_mday, STR_MONTHS[t.tm_mon]); +#endif + lv_label_set_text(date, str); + + getTimerString(str, getValue(MIXSRC_TX_TIME), timerOptions); + lv_label_set_text(time, str); + + lastMinute = t.tm_min; + } +} + +void HeaderDateTime::setColor(uint32_t color) +{ + lv_obj_set_style_text_color(date, makeLvColor(color), LV_PART_MAIN); + lv_obj_set_style_text_color(time, makeLvColor(color), LV_PART_MAIN); +} + +HeaderIcon::HeaderIcon(Window* parent, EdgeTxIcon icon) : + StaticIcon(parent, 0, 0, ICON_TOPLEFT_BG, COLOR_THEME_FOCUS) +{ + (new StaticIcon(this, 0, 0, icon, COLOR_THEME_PRIMARY2))->center(width(), height()); +} + +UsbSDConnected::UsbSDConnected() : + Window(MainWindow::instance(), {0, 0, LCD_W, LCD_H}) +{ + setWindowFlag(OPAQUE); + + etx_solid_bg(lvobj, COLOR_THEME_PRIMARY1_INDEX); + dateTime = new HeaderDateTime(this, LCD_W - TopBar::HDR_DATE_XO, HDR_DATE_Y); + + auto icon = new StaticIcon(this, 0, 0, ICON_USB_PLUGGED, COLOR_THEME_PRIMARY2); + lv_obj_center(icon->getLvObj()); +} diff --git a/radio/src/gui/colorlcd/theme_manager.h b/radio/src/gui/colorlcd/theme_manager.h index 8e4cd5230..2b7eb9b73 100644 --- a/radio/src/gui/colorlcd/theme_manager.h +++ b/radio/src/gui/colorlcd/theme_manager.h @@ -28,12 +28,6 @@ #include "opentx.h" #include "sdcard.h" -#define AUTHOR_LENGTH 50 -#define INFO_LENGTH 255 - -class ThemePersistance; -extern ThemePersistance themePersistance; - struct ColorEntry { LcdColorIndex colorNumber; @@ -45,12 +39,7 @@ struct ColorEntry class ThemeFile { public: - ThemeFile() { - name[0] = '\0'; - author[0] = '\0'; - info[0] = '\0'; - } - + ThemeFile() {} ThemeFile(std::string themePath, bool loadYAML = true); virtual ~ThemeFile() {} @@ -60,9 +49,9 @@ class ThemeFile void serialize(); std::string getPath() { return path; } - char *getName() { return name; } - char *getAuthor() { return author; } - char *getInfo() { return info; } + std::string getName() { return name; } + std::string getAuthor() { return author; } + std::string getInfo() { return info; } ColorEntry *getColorEntryByIndex(LcdColorIndex colorNumber) { int n = 0; @@ -75,9 +64,9 @@ class ThemeFile return nullptr; } - void setName(std::string name) { strAppend(this->name, name.c_str(), SELECTED_THEME_NAME_LEN); } - void setAuthor(std::string author) { strAppend(this->author, author.c_str(), AUTHOR_LENGTH); } - void setInfo(std::string info) { strAppend(this->info, info.c_str(), INFO_LENGTH); } + void setName(std::string name) { this->name = name; } + void setAuthor(std::string author) { this->author = author; } + void setInfo(std::string info) { this->info = info; } void setPath(std::string path) { this->path = path; } std::vector& getColorList() { return colorList; } @@ -86,20 +75,23 @@ class ThemeFile virtual std::vector getThemeImageFileNames(); void applyTheme(); + static constexpr int AUTHOR_LENGTH = 50; + static constexpr int INFO_LENGTH = 255; + protected: std::string path; - char name[SELECTED_THEME_NAME_LEN + 1]; - char author[AUTHOR_LENGTH + 1]; - char info[INFO_LENGTH + 1]; + std::string name; + std::string author; + std::string info; std::vector colorList; std::vector _imageFileNames; + void applyColors(); - virtual void applyBackground(); + void applyBackground(); void deSerialize(); }; - class ThemePersistance { public: @@ -108,7 +100,7 @@ class ThemePersistance } static ThemePersistance *instance() { - return &themePersistance; + return &themePersistance; } void loadDefaultTheme(); @@ -162,4 +154,42 @@ class ThemePersistance void insertDefaultTheme(); void clearThemes(); void scanThemeFolder(char *fullPath); + + static ThemePersistance themePersistance; +}; + +class HeaderDateTime : public Window +{ + public: + HeaderDateTime(Window* parent, int x, int y); + + void setColor(uint32_t color); + + static LAYOUT_VAL(HDR_DATE_WIDTH, 45, 45) + static LAYOUT_VAL(HDR_DATE_HEIGHT, 12, 12) + static LAYOUT_VAL(HDR_DATE_LINE2, 15, 15) + + protected: + lv_obj_t *date = nullptr; + lv_obj_t *time = nullptr; + int8_t lastMinute = -1; + + void checkEvents() override; +}; + +class HeaderIcon : public StaticIcon +{ + public: + HeaderIcon(Window *parent, EdgeTxIcon icon); +}; + +class UsbSDConnected : public Window +{ + public: + UsbSDConnected(); + + static LAYOUT_VAL(HDR_DATE_Y, 6, 6) + + protected: + HeaderDateTime* dateTime = nullptr; }; diff --git a/radio/src/gui/colorlcd/view_channels.cpp b/radio/src/gui/colorlcd/view_channels.cpp index 6f8692b74..d8c59741b 100644 --- a/radio/src/gui/colorlcd/view_channels.cpp +++ b/radio/src/gui/colorlcd/view_channels.cpp @@ -30,41 +30,42 @@ #include "opentx.h" #include "view_logical_switches.h" -constexpr coord_t LEG_COLORBOX = 14; - //----------------------------------------------------------------------------- class ChannelsViewFooter : public Window { public: explicit ChannelsViewFooter(Window* parent) : - Window(parent, {0, parent->height() - LEG_COLORBOX - 10, LCD_W, - LEG_COLORBOX + 10}) + Window(parent, {0, parent->height() - LEG_COLORBOX - PAD_SMALL * 2 - 2, LCD_W, + LEG_COLORBOX + PAD_SMALL * 2 + 2}) { etx_solid_bg(lvobj, COLOR_THEME_SECONDARY1_INDEX); auto w = - new Window(this, {6, 4, LEG_COLORBOX + 2, LEG_COLORBOX + 2}); + new Window(this, {PAD_MEDIUM, PAD_SMALL, LEG_COLORBOX + PAD_TINY, LEG_COLORBOX + PAD_TINY}); w->setWindowFlag(NO_FOCUS); etx_solid_bg(w->getLvObj(), COLOR_THEME_SECONDARY3_INDEX); w = new Window(w, {1, 1, LEG_COLORBOX, LEG_COLORBOX}); w->setWindowFlag(NO_FOCUS); etx_solid_bg(w->getLvObj(), COLOR_THEME_ACTIVE_INDEX); - new StaticText(this, {24, 2, LV_SIZE_CONTENT, 16}, STR_MONITOR_OUTPUT_DESC, COLOR_THEME_PRIMARY2 | LEFT); + new StaticText(this, {LEG_COLORBOX + PAD_MEDIUM + PAD_SMALL, PAD_TINY, LV_SIZE_CONTENT, TXT_H}, STR_MONITOR_OUTPUT_DESC, COLOR_THEME_PRIMARY2 | LEFT); - int x = getTextWidth(STR_MONITOR_OUTPUT_DESC) + 32; + int x = getTextWidth(STR_MONITOR_OUTPUT_DESC) + LEG_COLORBOX + PAD_MEDIUM * 2; - w = new Window(this, {x + 6, 4, LEG_COLORBOX + 2, LEG_COLORBOX + 2}); + w = new Window(this, {x + PAD_MEDIUM, PAD_SMALL, LEG_COLORBOX + PAD_TINY, LEG_COLORBOX + PAD_TINY}); w->setWindowFlag(NO_FOCUS); etx_solid_bg(w->getLvObj(), COLOR_THEME_SECONDARY3_INDEX); w = new Window(w, {1, 1, LEG_COLORBOX, LEG_COLORBOX}); w->setWindowFlag(NO_FOCUS); etx_solid_bg(w->getLvObj(), COLOR_THEME_FOCUS_INDEX); - new StaticText(this, {x + 24, 2, LV_SIZE_CONTENT, 16}, + new StaticText(this, {x + LEG_COLORBOX + PAD_MEDIUM + PAD_SMALL, PAD_TINY, LV_SIZE_CONTENT, TXT_H}, STR_MONITOR_MIXER_DESC, COLOR_THEME_PRIMARY2); } + + static LAYOUT_VAL(LEG_COLORBOX, 14, 14) + static LAYOUT_VAL(TXT_H, 18, 18) }; //----------------------------------------------------------------------------- @@ -84,7 +85,7 @@ class ChannelsViewPage : public PageTab void build(Window* window) override { - constexpr coord_t hmargin = 5; + constexpr coord_t hmargin = PAD_SMALL; window->padAll(PAD_ZERO); // Channels bars diff --git a/radio/src/gui/colorlcd/view_logical_switches.cpp b/radio/src/gui/colorlcd/view_logical_switches.cpp index a0e311380..395db838f 100644 --- a/radio/src/gui/colorlcd/view_logical_switches.cpp +++ b/radio/src/gui/colorlcd/view_logical_switches.cpp @@ -27,10 +27,6 @@ #if PORTRAIT_LCD -static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), - LV_GRID_FR(1), LV_GRID_FR(1), - LV_GRID_TEMPLATE_LAST}; - // Footer grid static const lv_coord_t f_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), @@ -38,12 +34,6 @@ static const lv_coord_t f_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), #else // Landscape -// Switch grid -static const lv_coord_t col_dsc[] = { - LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), - LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), - LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST}; - // Footer grid static const lv_coord_t f_col_dsc[] = { 60, LV_GRID_FR(1), 112, LV_GRID_FR(1), 50, 50, LV_GRID_TEMPLATE_LAST}; @@ -248,13 +238,8 @@ void LogicalSwitchesViewPage::build(Window* window) { window->padAll(PAD_ZERO); - auto form = new Window(window, rect_t{}); - form->setFlexLayout(LV_FLEX_FLOW_COLUMN, PAD_ZERO); - form->padAll(PAD_ZERO); - form->padTop(3); - - FlexGridLayout grid(col_dsc, row_dsc, PAD_TINY); - FormLine* line = nullptr; + coord_t xo = (LCD_W - (BTN_MATRIX_COL * (BTN_WIDTH + PAD_TINY) - PAD_TINY)) / 2; + coord_t yo = PAD_TINY; // Footer footer = new LogicalSwitchDisplayFooter( @@ -264,12 +249,8 @@ void LogicalSwitchesViewPage::build(Window* window) // LSW table std::string lsString("L64"); for (uint8_t i = 0; i < MAX_LOGICAL_SWITCHES; i++) { - if ((i % BTN_MATRIX_COL) == 0) { - line = form->newLine(grid); - lv_obj_set_style_pad_all(line->getLvObj(), BTN_PAD, LV_PART_MAIN); - line->padLeft(PAD_SMALL); - line->padRight(PAD_SMALL); - } + coord_t x = (i % BTN_MATRIX_COL) * (BTN_WIDTH + PAD_TINY) + xo; + coord_t y = (i / BTN_MATRIX_COL) * (BTN_HEIGHT + PAD_TINY) + yo; LogicalSwitchData* ls = lswAddress(i); bool isActive = (ls->func != LS_FUNC_NONE); @@ -278,9 +259,7 @@ void LogicalSwitchesViewPage::build(Window* window) if (isActive) { auto button = new LogicalSwitchDisplayButton( - line, rect_t{0, 0, 0, BTN_HEIGHT}, lsString, i); - lv_obj_set_grid_cell(button->getLvObj(), LV_GRID_ALIGN_STRETCH, - i % BTN_MATRIX_COL, 1, LV_GRID_ALIGN_CENTER, 0, 1); + window, {x, y, BTN_WIDTH, BTN_HEIGHT}, lsString, i); button->setFocusHandler([=](bool focus) { if (focus) { @@ -289,12 +268,11 @@ void LogicalSwitchesViewPage::build(Window* window) return 0; }); } else { - auto lbl = lv_label_create(line->getLvObj()); - lv_obj_set_height(lbl, BTN_HEIGHT); + auto lbl = lv_label_create(window->getLvObj()); + lv_obj_set_size(lbl, BTN_WIDTH, BTN_HEIGHT); + lv_obj_set_pos(lbl, x, y); etx_obj_add_style(lbl, styles->text_align_center, LV_PART_MAIN); etx_txt_color(lbl, COLOR_THEME_DISABLED_INDEX); - lv_obj_set_grid_cell(lbl, LV_GRID_ALIGN_STRETCH, i % BTN_MATRIX_COL, 1, - LV_GRID_ALIGN_CENTER, 0, 1); lv_label_set_text(lbl, lsString.c_str()); } } diff --git a/radio/src/gui/colorlcd/view_logical_switches.h b/radio/src/gui/colorlcd/view_logical_switches.h index f63c39a7b..f156c2037 100644 --- a/radio/src/gui/colorlcd/view_logical_switches.h +++ b/radio/src/gui/colorlcd/view_logical_switches.h @@ -31,8 +31,8 @@ class LogicalSwitchesViewPage : public PageTab LogicalSwitchesViewPage(); static LAYOUT_VAL(FOOTER_HEIGHT, 20, 40) + static LAYOUT_VAL(BTN_WIDTH, 57, 76) static LAYOUT_VAL(BTN_HEIGHT, 20, 21) - static LAYOUT_VAL(BTN_PAD, 1, 2) static LAYOUT_VAL(BTN_MATRIX_COL, 8, 4) protected: diff --git a/radio/src/gui/colorlcd/view_main.cpp b/radio/src/gui/colorlcd/view_main.cpp index 7d8ce8145..3ff1c8c77 100644 --- a/radio/src/gui/colorlcd/view_main.cpp +++ b/radio/src/gui/colorlcd/view_main.cpp @@ -26,7 +26,6 @@ #include "menu_screen.h" #include "model_select.h" #include "opentx.h" -#include "theme.h" #include "topbar_impl.h" #include "view_channels.h" #include "view_main_menu.h" diff --git a/radio/src/gui/colorlcd/view_main_menu.cpp b/radio/src/gui/colorlcd/view_main_menu.cpp index a17490c43..28b1bf532 100644 --- a/radio/src/gui/colorlcd/view_main_menu.cpp +++ b/radio/src/gui/colorlcd/view_main_menu.cpp @@ -58,14 +58,6 @@ static lv_obj_t* etx_modal_dialog_create(lv_obj_t* parent) return etx_create(&etx_modal_dialog_class, parent); } -#if !PORTRAIT_LCD -#define VM_W (SelectFabCarousel::FAB_BUTTON_WIDTH * 4 + PAD_LARGE * 2) -#define VM_H (SelectFabCarousel::FAB_BUTTON_HEIGHT * 2 + PAD_LARGE * 2) -#else -#define VM_W (SelectFabCarousel::FAB_BUTTON_WIDTH * 3 + PAD_LARGE * 2) -#define VM_H (SelectFabCarousel::FAB_BUTTON_HEIGHT * 3 + PAD_LARGE * 2) -#endif - ViewMainMenu::ViewMainMenu(Window* parent, std::function closeHandler) : Window(parent->getFullScreenWindow(), {0, 0, LCD_W, LCD_H}), closeHandler(std::move(closeHandler)) @@ -73,16 +65,18 @@ ViewMainMenu::ViewMainMenu(Window* parent, std::function closeHandler) : // Save focus Layer::push(this); - coord_t width = VM_W; + coord_t w = SelectFabCarousel::FAB_BUTTON_WIDTH * QM_COLS + PAD_LARGE * 2; + coord_t h = SelectFabCarousel::FAB_BUTTON_HEIGHT * QM_ROWS + PAD_LARGE * 2; + bool hasNotes = modelHasNotes(); #if !PORTRAIT_LCD if (hasNotes) - width += SelectFabCarousel::FAB_BUTTON_WIDTH; + w += SelectFabCarousel::FAB_BUTTON_WIDTH; #endif auto box = - new Window(this, {(LCD_W - width) / 2, (LCD_H - VM_H) / 2, width, VM_H}, + new Window(this, {(LCD_W - w) / 2, (LCD_H - h) / 2, w, h}, etx_modal_dialog_create); box->padAll(PAD_LARGE); diff --git a/radio/src/gui/colorlcd/view_main_menu.h b/radio/src/gui/colorlcd/view_main_menu.h index 9332d1ee5..057a14ca0 100644 --- a/radio/src/gui/colorlcd/view_main_menu.h +++ b/radio/src/gui/colorlcd/view_main_menu.h @@ -32,6 +32,9 @@ class ViewMainMenu : public Window void onClicked() override; void deleteLater(bool detach = true, bool trash = true) override; + static LAYOUT_VAL(QM_COLS, 4, 3) + static LAYOUT_VAL(QM_ROWS, 2, 3) + protected: std::function closeHandler = nullptr; }; diff --git a/radio/src/gui/colorlcd/view_statistics.cpp b/radio/src/gui/colorlcd/view_statistics.cpp index 03429395e..ee0b8db4c 100644 --- a/radio/src/gui/colorlcd/view_statistics.cpp +++ b/radio/src/gui/colorlcd/view_statistics.cpp @@ -168,8 +168,8 @@ class ThrottleCurveWindow : public Window void StatisticsViewPage::build(Window* window) { window->setFlexLayout(LV_FLEX_FLOW_COLUMN, PAD_ZERO); - window->padLeft(4); - window->padRight(4); + window->padLeft(PAD_SMALL); + window->padRight(PAD_SMALL); FlexGridLayout grid(col_dsc, row_dsc, PAD_ZERO); diff --git a/radio/src/gui/colorlcd/widget.cpp b/radio/src/gui/colorlcd/widget.cpp index a82aa7e7e..d4df1d609 100644 --- a/radio/src/gui/colorlcd/widget.cpp +++ b/radio/src/gui/colorlcd/widget.cpp @@ -21,7 +21,7 @@ #include "widget.h" -#include "theme.h" +#include "opentx.h" #include "themes/etx_lv_theme.h" #include "view_main.h" #include "widget_settings.h" diff --git a/radio/src/gui/colorlcd/widgets/radio_info.cpp b/radio/src/gui/colorlcd/widgets/radio_info.cpp index 2be88d1e4..e80bdc7dc 100644 --- a/radio/src/gui/colorlcd/widgets/radio_info.cpp +++ b/radio/src/gui/colorlcd/widgets/radio_info.cpp @@ -21,7 +21,7 @@ #include "hal/usb_driver.h" #include "opentx.h" -#include "theme.h" +#include "theme_manager.h" #include "widget.h" #include "widgets_container_impl.h" @@ -245,23 +245,10 @@ class DateTimeWidget : public TopBarWidget const rect_t& rect, Widget::PersistentData* persistentData) : TopBarWidget(factory, parent, rect, persistentData) { - dateTime = new HeaderDateTime(lvobj, DT_X, DT_Y); + dateTime = new HeaderDateTime(this, DT_X, DT_Y); update(); } - void checkEvents() override - { - TopBarWidget::checkEvents(); - - // Only update if minute value has changed - struct gtm t; - gettime(&t); - if (t.tm_min != lastMinute) { - lastMinute = t.tm_min; - dateTime->update(); - } - } - void update() override { // get color from options diff --git a/radio/src/lua/api_colorlcd.cpp b/radio/src/lua/api_colorlcd.cpp index f40d137b8..3978450a1 100644 --- a/radio/src/lua/api_colorlcd.cpp +++ b/radio/src/lua/api_colorlcd.cpp @@ -27,7 +27,6 @@ #include "opentx.h" #include "libopenui.h" #include "widget.h" -#include "theme.h" #include "lua_api.h" #include "lua_widget.h" @@ -972,8 +971,7 @@ static int luaLcdSetColor(lua_State *L) if (index < LCD_COLOR_COUNT && lcdColorTable[index] != color) { lcdColorTable[index] = color; - if (index != CUSTOM_COLOR_INDEX) - EdgeTxTheme::instance()->update(); + styles->applyColors(); } return 0; } diff --git a/radio/src/lua/lua_lvgl_widget.cpp b/radio/src/lua/lua_lvgl_widget.cpp index ede3bc096..86aecaf92 100644 --- a/radio/src/lua/lua_lvgl_widget.cpp +++ b/radio/src/lua/lua_lvgl_widget.cpp @@ -570,7 +570,7 @@ class LvglWidgetScaleIndicator : public LvglWidgetObjectBase public: LvglWidgetScaleIndicator() {} - virtual void build(lv_obj_t *parent, lv_meter_scale_t *scale) = 0; + virtual void buildIndicator(lv_obj_t *parent, lv_meter_scale_t *scale) = 0; protected: lv_obj_t *meter = nullptr; @@ -601,7 +601,7 @@ class LvglWidgetScaleArc : public LvglWidgetScaleIndicator clearRef(L, getEndPosFunction); } - void build(lv_obj_t *parent, lv_meter_scale_t *scale) override + void buildIndicator(lv_obj_t *parent, lv_meter_scale_t *scale) override { meter = parent; @@ -671,7 +671,7 @@ class LvglWidgetScaleLines : public LvglWidgetScaleIndicator clearRef(L, getEndPosFunction); } - void build(lv_obj_t *parent, lv_meter_scale_t *scale) override + void buildIndicator(lv_obj_t *parent, lv_meter_scale_t *scale) override { meter = parent; @@ -736,7 +736,7 @@ class LvglWidgetScaleNeedle : public LvglWidgetScaleIndicator void clearRefs(lua_State *L) override { clearRef(L, getPosFunction); } - void build(lv_obj_t *parent, lv_meter_scale_t *scale) override + void buildIndicator(lv_obj_t *parent, lv_meter_scale_t *scale) override { meter = parent; @@ -811,7 +811,7 @@ class LvglWidgetMeterScale : public LvglWidgetObjectBase } for (auto it = indicators.cbegin(); it != indicators.cend(); ++it) { - (*it)->build(meter, scale); + (*it)->buildIndicator(meter, scale); } } diff --git a/radio/src/main.cpp b/radio/src/main.cpp index cea043867..7b73cb157 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -30,7 +30,7 @@ #include "gui/colorlcd/LvglWrapper.h" #include "gui/colorlcd/view_main.h" #include "startup_shutdown.h" -#include "theme.h" +#include "theme_manager.h" #include "themes/etx_lv_theme.h" #endif diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index e1c1d9f7d..c689d635c 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -53,7 +53,7 @@ #include "radio_calibration.h" #include "view_main.h" #include "view_text.h" - #include "theme.h" + #include "theme_manager.h" #include "switch_warn_dialog.h" #include "startup_shutdown.h" @@ -1114,7 +1114,7 @@ void edgeTxResume() #if defined(COLORLCD) //TODO: needs to go into storageReadAll() TRACE("reloading theme"); - EdgeTxTheme::instance()->load(); + ThemePersistance::instance()->loadDefaultTheme(); #endif referenceSystemAudioFiles(); @@ -1339,6 +1339,7 @@ void edgeTxInit() #endif #if defined(LIBOPENUI) + initLvglTheme(); // create ViewMain ViewMain::instance(); #elif defined(GUI) @@ -1473,7 +1474,7 @@ void edgeTxInit() BACKLIGHT_ENABLE(); #if defined(COLORLCD) - EdgeTxTheme::instance()->load(); + ThemePersistance::instance()->loadDefaultTheme(); if (g_eeGeneral.backlightMode == e_backlight_mode_off) { // no backlight mode off on color lcd radios g_eeGeneral.backlightMode = e_backlight_mode_keys; diff --git a/radio/src/storage/sdcard_common.cpp b/radio/src/storage/sdcard_common.cpp index 4f7aacb5c..59b64743b 100644 --- a/radio/src/storage/sdcard_common.cpp +++ b/radio/src/storage/sdcard_common.cpp @@ -28,7 +28,7 @@ #include "hal/abnormal_reboot.h" #if defined(COLORLCD) - #include "theme.h" + #include "theme_manager.h" #endif void getModelPath(char * path, const char * filename, const char* pathName) @@ -45,7 +45,7 @@ void storageEraseAll(bool warn) #if defined(COLORLCD) // the theme has not been loaded before - EdgeTxTheme::instance()->load(); + ThemePersistance::instance()->loadDefaultTheme(); #endif // Init backlight mode before entering alert screens diff --git a/radio/src/thirdparty/libopenui/src/button.cpp b/radio/src/thirdparty/libopenui/src/button.cpp index 65d106c03..48fa22391 100644 --- a/radio/src/thirdparty/libopenui/src/button.cpp +++ b/radio/src/thirdparty/libopenui/src/button.cpp @@ -18,7 +18,7 @@ #include "button.h" -#include "theme.h" +#include "static.h" #include "themes/etx_lv_theme.h" static void button_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) diff --git a/radio/src/thirdparty/libopenui/src/choice.cpp b/radio/src/thirdparty/libopenui/src/choice.cpp index 6593f1491..e26c68011 100644 --- a/radio/src/thirdparty/libopenui/src/choice.cpp +++ b/radio/src/thirdparty/libopenui/src/choice.cpp @@ -19,7 +19,6 @@ #include "choice.h" #include "menu.h" -#include "theme.h" #include "themes/etx_lv_theme.h" // Choice diff --git a/radio/src/thirdparty/libopenui/src/dialog.cpp b/radio/src/thirdparty/libopenui/src/dialog.cpp index dab721b37..3298509e6 100644 --- a/radio/src/thirdparty/libopenui/src/dialog.cpp +++ b/radio/src/thirdparty/libopenui/src/dialog.cpp @@ -18,9 +18,9 @@ #include "dialog.h" +#include "opentx.h" #include "mainwindow.h" #include "progress.h" -#include "theme.h" #include "themes/etx_lv_theme.h" //----------------------------------------------------------------------------- diff --git a/radio/src/thirdparty/libopenui/src/filechoice.cpp b/radio/src/thirdparty/libopenui/src/filechoice.cpp index e0d3439cf..bbeac9640 100644 --- a/radio/src/thirdparty/libopenui/src/filechoice.cpp +++ b/radio/src/thirdparty/libopenui/src/filechoice.cpp @@ -20,10 +20,10 @@ #include +#include "opentx.h" #include "libopenui_file.h" #include "menu.h" #include "menutoolbar.h" -#include "theme.h" class FileChoiceMenuToolbar : public MenuToolbar { diff --git a/radio/src/thirdparty/libopenui/src/mainwindow.cpp b/radio/src/thirdparty/libopenui/src/mainwindow.cpp index af9c7e9bd..770eaea8c 100644 --- a/radio/src/thirdparty/libopenui/src/mainwindow.cpp +++ b/radio/src/thirdparty/libopenui/src/mainwindow.cpp @@ -22,6 +22,7 @@ #include "keyboard_base.h" #include "layout.h" #include "themes/etx_lv_theme.h" +#include "sdcard.h" // timers_driver.h uint32_t timersGetMsTick(); @@ -76,12 +77,6 @@ void MainWindow::run(bool trash) } } -void MainWindow::setBackground(const BitmapBuffer* bitmap) -{ - lv_canvas_set_buffer(background, bitmap->getData(), bitmap->width(), - bitmap->height(), LV_IMG_CF_TRUE_COLOR); -} - void MainWindow::shutdown() { // Called when USB is connected in SD card mode @@ -100,3 +95,28 @@ void MainWindow::shutdown() background = lv_canvas_create(lvobj); lv_obj_center(background); } + +void MainWindow::setBackgroundImage(const char* fileName) +{ + // ensure you delete old bitmap + if (backgroundBitmap != nullptr) delete backgroundBitmap; + + if (fileName == nullptr) fileName = ""; + + backgroundImageFileName = fileName; + + // Try to load bitmap. If this fails backgroundBitmap will be NULL and default + // will be loaded in update() method + backgroundBitmap = + BitmapBuffer::loadBitmap(backgroundImageFileName.c_str(), BMP_RGB565); + + if (!backgroundBitmap) { + backgroundBitmap = BitmapBuffer::loadBitmap( + THEMES_PATH "/EdgeTX/background.png", BMP_RGB565); + } + + if (backgroundBitmap) { + lv_canvas_set_buffer(background, backgroundBitmap->getData(), backgroundBitmap->width(), + backgroundBitmap->height(), LV_IMG_CF_TRUE_COLOR); + } +} diff --git a/radio/src/thirdparty/libopenui/src/mainwindow.h b/radio/src/thirdparty/libopenui/src/mainwindow.h index ec0ef703e..b475af07f 100644 --- a/radio/src/thirdparty/libopenui/src/mainwindow.h +++ b/radio/src/thirdparty/libopenui/src/mainwindow.h @@ -23,40 +23,42 @@ class MainWindow: public Window { - protected: - // singleton - MainWindow(); + protected: + // singleton + MainWindow(); - public: - static MainWindow * instance(); + public: + static MainWindow * instance(); #if defined(TESTS) - static void create() - { - _instance = new MainWindow(); - } + static void create() + { + _instance = new MainWindow(); + } #endif #if defined(DEBUG_WINDOWS) - std::string getName() const override - { - return "MainWindow"; - } + std::string getName() const override + { + return "MainWindow"; + } #endif - void setActiveScreen() { - lv_scr_load(lvobj); - } + void setActiveScreen() { + lv_scr_load(lvobj); + } - void run(bool trash=true); + void run(bool trash=true); - void setBackground(const BitmapBuffer* bitmap); + void setBackgroundImage(const char* fileName); - void shutdown(); + void shutdown(); - protected: - lv_obj_t* background = nullptr; + protected: + lv_obj_t* background = nullptr; + std::string backgroundImageFileName; + const BitmapBuffer *backgroundBitmap = nullptr; - static MainWindow * _instance; - static void emptyTrash(); + static MainWindow * _instance; + static void emptyTrash(); }; diff --git a/radio/src/thirdparty/libopenui/src/menu.cpp b/radio/src/thirdparty/libopenui/src/menu.cpp index 33ae20a6e..2c2a5d493 100644 --- a/radio/src/thirdparty/libopenui/src/menu.cpp +++ b/radio/src/thirdparty/libopenui/src/menu.cpp @@ -21,8 +21,8 @@ #include #include "menutoolbar.h" +#include "opentx.h" #include "table.h" -#include "theme.h" #include "themes/etx_lv_theme.h" #include diff --git a/radio/src/thirdparty/libopenui/src/slider.cpp b/radio/src/thirdparty/libopenui/src/slider.cpp index 6b148323f..1c8cdf201 100644 --- a/radio/src/thirdparty/libopenui/src/slider.cpp +++ b/radio/src/thirdparty/libopenui/src/slider.cpp @@ -18,7 +18,7 @@ #include "slider.h" -#include "theme.h" +#include "form.h" #include "themes/etx_lv_theme.h" // Slider diff --git a/radio/src/thirdparty/libopenui/src/toggleswitch.cpp b/radio/src/thirdparty/libopenui/src/toggleswitch.cpp index 3a046e942..a90c9773e 100644 --- a/radio/src/thirdparty/libopenui/src/toggleswitch.cpp +++ b/radio/src/thirdparty/libopenui/src/toggleswitch.cpp @@ -18,7 +18,6 @@ #include "toggleswitch.h" -#include "theme.h" #include "themes/etx_lv_theme.h" // Animation diff --git a/radio/src/thirdparty/libopenui/src/window.cpp b/radio/src/thirdparty/libopenui/src/window.cpp index 5ba196d0b..66007a885 100644 --- a/radio/src/thirdparty/libopenui/src/window.cpp +++ b/radio/src/thirdparty/libopenui/src/window.cpp @@ -509,7 +509,7 @@ SetupLine::SetupLine(Window* parent, coord_t y, coord_t col2, PaddingSize paddin Window(parent, {0, y, LCD_W - padding * 2, 0}) { padAll(PAD_ZERO); - coord_t titleY = PAD_MEDIUM + 1 + lblYOffset; + coord_t titleY = PAD_LARGE + lblYOffset; coord_t titleH = EdgeTxStyles::PAGE_LINE_HEIGHT; coord_t h = EdgeTxStyles::UI_ELEMENT_HEIGHT + PAD_TINY * 2 + lblYOffset * 2; if (createEdit) { @@ -519,7 +519,7 @@ SetupLine::SetupLine(Window* parent, coord_t y, coord_t col2, PaddingSize paddin if (getTextWidth(title) >= lblWidth) { h += PAD_MEDIUM; titleY = 0; - titleH = EdgeTxStyles::UI_ELEMENT_HEIGHT + PAD_TINY + 1; + titleH = EdgeTxStyles::UI_ELEMENT_HEIGHT + PAD_TINY + PAD_LARGE; editY = PAD_SMALL + 1; } new StaticText(this, {PAD_TINY, titleY, lblWidth, titleH}, title);