From e31a1cc1fc2d0f18dc1b9cc8a72e179447985614 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 6 Jun 2022 09:14:55 +0200 Subject: [PATCH] Input & Mixer edit pages: flex layout rework --- radio/src/gui/colorlcd/CMakeLists.txt | 6 + radio/src/gui/colorlcd/curve.h | 7 +- radio/src/gui/colorlcd/curve_param.cpp | 123 +++++++ radio/src/gui/colorlcd/curve_param.h | 49 +++ radio/src/gui/colorlcd/fm_matrix.cpp | 67 ++++ radio/src/gui/colorlcd/fm_matrix.h | 38 +++ radio/src/gui/colorlcd/gvar_numberedit.cpp | 146 +++++++++ radio/src/gui/colorlcd/gvar_numberedit.h | 112 +------ radio/src/gui/colorlcd/input_edit.cpp | 357 ++++++--------------- radio/src/gui/colorlcd/input_edit.h | 7 +- radio/src/gui/colorlcd/input_edit_adv.cpp | 74 +++++ radio/src/gui/colorlcd/input_edit_adv.h | 33 ++ radio/src/gui/colorlcd/input_source.cpp | 160 +++++++++ radio/src/gui/colorlcd/input_source.h | 39 +++ radio/src/gui/colorlcd/mixer_edit.cpp | 255 ++++----------- radio/src/gui/colorlcd/mixer_edit.h | 11 +- radio/src/gui/colorlcd/mixer_edit_adv.cpp | 107 ++++++ radio/src/gui/colorlcd/mixer_edit_adv.h | 41 +++ radio/src/gui/colorlcd/model_inputs.cpp | 2 +- radio/src/gui/colorlcd/output_edit.cpp | 6 +- radio/src/gui/colorlcd/page.cpp | 17 +- radio/src/gui/colorlcd/page.h | 20 +- radio/src/opentx.cpp | 2 + radio/src/targets/horus/libopenui_config.h | 2 +- radio/src/targets/nv14/libopenui_config.h | 8 +- radio/src/thirdparty/libopenui | 2 +- 26 files changed, 1093 insertions(+), 598 deletions(-) create mode 100644 radio/src/gui/colorlcd/curve_param.cpp create mode 100644 radio/src/gui/colorlcd/curve_param.h create mode 100644 radio/src/gui/colorlcd/fm_matrix.cpp create mode 100644 radio/src/gui/colorlcd/fm_matrix.h create mode 100644 radio/src/gui/colorlcd/gvar_numberedit.cpp create mode 100644 radio/src/gui/colorlcd/input_edit_adv.cpp create mode 100644 radio/src/gui/colorlcd/input_edit_adv.h create mode 100644 radio/src/gui/colorlcd/input_source.cpp create mode 100644 radio/src/gui/colorlcd/input_source.h create mode 100644 radio/src/gui/colorlcd/mixer_edit_adv.cpp create mode 100644 radio/src/gui/colorlcd/mixer_edit_adv.h diff --git a/radio/src/gui/colorlcd/CMakeLists.txt b/radio/src/gui/colorlcd/CMakeLists.txt index 80d8dcb53..3515a5a00 100644 --- a/radio/src/gui/colorlcd/CMakeLists.txt +++ b/radio/src/gui/colorlcd/CMakeLists.txt @@ -167,8 +167,14 @@ add_gui_src(curve.cpp) add_gui_src(sourcechoice.cpp) add_gui_src(switchchoice.cpp) add_gui_src(curveedit.cpp) +add_gui_src(gvar_numberedit.cpp) +add_gui_src(curve_param.cpp) +add_gui_src(fm_matrix.cpp) +add_gui_src(input_source.cpp) add_gui_src(input_edit.cpp) +add_gui_src(input_edit_adv.cpp) add_gui_src(mixer_edit.cpp) +add_gui_src(mixer_edit_adv.cpp) add_gui_src(output_edit.cpp) add_gui_src(input_mix_group.cpp) add_gui_src(input_mix_button.cpp) diff --git a/radio/src/gui/colorlcd/curve.h b/radio/src/gui/colorlcd/curve.h index 44854944a..e63588e76 100644 --- a/radio/src/gui/colorlcd/curve.h +++ b/radio/src/gui/colorlcd/curve.h @@ -51,7 +51,11 @@ class Curve: public Window { // will always force a full window refresh if (position) { - invalidate(); + // int pos = position(); + // if (pos != lastPos) { + // lastPos = pos; + invalidate(); + // } } Window::checkEvents(); @@ -64,6 +68,7 @@ class Curve: public Window void paint(BitmapBuffer * dc) override; protected: + // int lastPos = 0; std::function function; std::function position; std::list points; diff --git a/radio/src/gui/colorlcd/curve_param.cpp b/radio/src/gui/colorlcd/curve_param.cpp new file mode 100644 index 000000000..34d983c9a --- /dev/null +++ b/radio/src/gui/colorlcd/curve_param.cpp @@ -0,0 +1,123 @@ +/* + * 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 "curve_param.h" +#include "gvar_numberedit.h" +#include "model_curves.h" + +#include "opentx.h" + +#define SET_DIRTY() storageDirty(EE_MODEL) + +static const char *_curve_type[] = {"Diff", "Expo", "Func", "Cstm"}; + +void CurveParam::value_changed(lv_event_t* e) +{ + auto obj = lv_event_get_target(e); + auto param = (CurveParam*)lv_obj_get_user_data(obj); + if (!param) return; + + param->update(); +} + +CurveParam::CurveParam(Window* parent, const rect_t& rect, CurveRef* ref) : + Window(parent, rect), + ref(ref) +{ + lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_ROW_WRAP); + lv_obj_set_style_pad_column(lvobj, lv_dpx(4), 0); + lv_obj_set_style_flex_cross_place(lvobj, LV_FLEX_ALIGN_CENTER, 0); + lv_obj_set_size(lvobj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + + new Choice(this, rect_t{}, _curve_type, 0, + CURVE_REF_CUSTOM, GET_DEFAULT(ref->type), + [=](int32_t newValue) { + ref->type = newValue; + ref->value = 0; + SET_DIRTY(); + lv_event_send(lvobj, LV_EVENT_VALUE_CHANGED, nullptr); + }); + lv_obj_add_event_cb(lvobj, CurveParam::value_changed, LV_EVENT_VALUE_CHANGED, + nullptr); + + // CURVE_REF_DIFF + // CURVE_REF_EXPO + value_edit = new GVarNumberEdit(this, rect_t{}, -100, 100, + GET_SET_DEFAULT(ref->value)); + value_edit->setSuffix("%"); + + // CURVE_REF_FUNC + func_choice = new Choice(this, rect_t{}, STR_VCURVEFUNC, 0, CURVE_BASE - 1, + GET_SET_DEFAULT(ref->value)); + + + // CURVE_REF_CUSTOM + cust_choice = new ChoiceEx(this, rect_t{}, -MAX_CURVES, MAX_CURVES, + GET_SET_DEFAULT(ref->value)); + cust_choice->setTextHandler([](int value) { return getCurveString(value); }); + cust_choice->setLongPressHandler([ref](event_t event) { + // if no curve is specified then dont link to curve page + if (ref->value != 0) ModelCurvesPage::pushEditCurve(abs(ref->value) - 1); + }); + + update(); +} + +void CurveParam::update() +{ + bool has_focus = act_field && act_field->hasFocus(); + + auto value_obj = value_edit->getLvObj(); + auto func_obj = func_choice->getLvObj(); + auto cust_obj = cust_choice->getLvObj(); + + lv_obj_add_flag(value_obj, LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(func_obj, LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(cust_obj, LV_OBJ_FLAG_HIDDEN); + + switch(ref->type) { + case CURVE_REF_DIFF: + case CURVE_REF_EXPO: + lv_obj_clear_flag(value_obj, LV_OBJ_FLAG_HIDDEN); + act_field = value_edit; + break; + + case CURVE_REF_FUNC: + lv_obj_clear_flag(func_obj, LV_OBJ_FLAG_HIDDEN); + act_field = func_choice; + break; + + case CURVE_REF_CUSTOM: + lv_obj_clear_flag(cust_obj, LV_OBJ_FLAG_HIDDEN); + act_field = cust_choice; + break; + + default: + return; + } + + auto act_obj = act_field->getLvObj(); + if (has_focus) { + lv_group_focus_obj(act_obj); + } + lv_event_send(act_obj, LV_EVENT_VALUE_CHANGED, nullptr); +} + diff --git a/radio/src/gui/colorlcd/curve_param.h b/radio/src/gui/colorlcd/curve_param.h new file mode 100644 index 000000000..c6d8e7ace --- /dev/null +++ b/radio/src/gui/colorlcd/curve_param.h @@ -0,0 +1,49 @@ +/* + * 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 "window.h" + +struct CurveRef; + +class GVarNumberEdit; +class Choice; +class ChoiceEx; + +class CurveParam : public Window +{ + // Curve + CurveRef* ref; + + // Controls + GVarNumberEdit* value_edit; + Choice* func_choice; + ChoiceEx* cust_choice; + + Window* act_field = nullptr; + + void update(); + static void value_changed(lv_event_t* e); + +public: + CurveParam(Window* parent, const rect_t& rect, CurveRef* ref); +}; diff --git a/radio/src/gui/colorlcd/fm_matrix.cpp b/radio/src/gui/colorlcd/fm_matrix.cpp new file mode 100644 index 000000000..a952a285e --- /dev/null +++ b/radio/src/gui/colorlcd/fm_matrix.cpp @@ -0,0 +1,67 @@ +/* + * 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 "fm_matrix.h" +#include "opentx.h" + +template +FMMatrix::FMMatrix(Window* parent, const rect_t& r, T* input) : + ButtonMatrix(parent, r), input(input) +{ + initBtnMap(3, MAX_FLIGHT_MODES); + for (int i = 0; i < MAX_FLIGHT_MODES; i++) { + setText(i, std::to_string(i).c_str()); + } + update(); + + lv_obj_set_width(lvobj, LV_DPI_DEF * 2); + lv_obj_set_width(lvobj, LV_DPI_DEF); + + lv_obj_set_style_bg_opa(lvobj, LV_OPA_0, LV_PART_MAIN); + + lv_obj_set_style_pad_all(lvobj, 4, LV_PART_MAIN); + // lv_obj_set_style_pad_left(lvobj, LV_DPI_DEF / 10, LV_PART_MAIN); + + lv_obj_set_style_pad_row(lvobj, 4, LV_PART_MAIN); + lv_obj_set_style_pad_column(lvobj, 4, LV_PART_MAIN); + + lv_obj_remove_style(lvobj, nullptr, LV_PART_MAIN | LV_STATE_FOCUSED); + lv_obj_remove_style(lvobj, nullptr, LV_PART_MAIN | LV_STATE_EDITED); +} + +template +void FMMatrix::onPress(uint8_t btn_id) +{ + if (btn_id >= MAX_FLIGHT_MODES) return; + BFBIT_FLIP(input->flightModes, bfBit(btn_id)); + storageDirty(EE_MODEL); +} + +template +bool FMMatrix::isActive(uint8_t btn_id) +{ + if (btn_id >= MAX_FLIGHT_MODES) return false; + return !bfSingleBitGet(input->flightModes, btn_id); +} + +// explicit instantiation +template struct FMMatrix; +template struct FMMatrix; diff --git a/radio/src/gui/colorlcd/fm_matrix.h b/radio/src/gui/colorlcd/fm_matrix.h new file mode 100644 index 000000000..e987600a3 --- /dev/null +++ b/radio/src/gui/colorlcd/fm_matrix.h @@ -0,0 +1,38 @@ +/* + * 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 "button_matrix.h" + +struct ExpoData; +struct MixData; + +template +struct FMMatrix : public ButtonMatrix { + T* input; + FMMatrix(Window* parent, const rect_t& rect, T* input); + void onPress(uint8_t btn_id); + bool isActive(uint8_t btn_id); +}; + +extern template struct FMMatrix; +extern template struct FMMatrix; diff --git a/radio/src/gui/colorlcd/gvar_numberedit.cpp b/radio/src/gui/colorlcd/gvar_numberedit.cpp new file mode 100644 index 000000000..ddbce1335 --- /dev/null +++ b/radio/src/gui/colorlcd/gvar_numberedit.cpp @@ -0,0 +1,146 @@ +/* + * 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 "gvar_numberedit.h" +#include "opentx.h" + +void GVarNumberEdit::value_changed(lv_event_t* e) +{ + auto obj = lv_event_get_target(e); + auto edit = (GVarNumberEdit*)lv_obj_get_user_data(obj); + if (!edit) return; + + edit->update(); +} + +GVarNumberEdit::GVarNumberEdit(Window* parent, const rect_t& rect, int32_t vmin, + int32_t vmax, std::function getValue, + std::function setValue, + LcdFlags textFlags, int32_t voffset) : + Window(parent, rect), + vmin(vmin), + vmax(vmax), + getValue(getValue), + setValue(setValue), + textFlags(textFlags), + voffset(voffset) +{ + lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_ROW_WRAP); + lv_obj_set_style_pad_column(lvobj, lv_dpx(4), 0); + lv_obj_set_style_flex_cross_place(lvobj, LV_FLEX_ALIGN_CENTER, 0); + lv_obj_set_size(lvobj, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + + // GVAR field + gvar_field = new Choice( + this, rect_t{}, -MAX_GVARS, MAX_GVARS - 1, + [=]() { + uint16_t gvar1 = GV_GET_GV1_VALUE(vmin, vmax); + return GV_INDEX_CALC_DELTA(getValue(), gvar1); + }, + [=](int idx) { + uint16_t gvar1 = GV_GET_GV1_VALUE(vmin, vmax); + if (idx < 0) + setValue(GV_CALC_VALUE_IDX_NEG(idx, gvar1)); + else + setValue(GV_CALC_VALUE_IDX_POS(idx, gvar1)); + }); + gvar_field->setTextHandler( + [=](int32_t value) { return getGVarString(value); }); + + num_field = new NumberEdit( + this, rect_t{}, vmin, vmax, [=]() { return getValue() + voffset; }, + [=](int32_t newValue) { return setValue(newValue - voffset); }, + windowFlags, textFlags); + +#if defined(GVARS) + // The GVAR button + auto btn = new TextButton(this, rect_t{}, STR_GV, [=]() { + switchGVarMode(); + return 0; + }); + lv_obj_set_height(btn->getLvObj(), lv_obj_get_height(gvar_field->getLvObj())); +#endif + + lv_obj_add_event_cb(lvobj, GVarNumberEdit::value_changed, + LV_EVENT_VALUE_CHANGED, nullptr); + + // update field type based on value + update(); +} + +void GVarNumberEdit::switchGVarMode() +{ + int32_t value = getValue(); + setValue( + GV_IS_GV_VALUE(value, vmin, vmax) + ? ((textFlags & PREC1) + ? GET_GVAR_PREC1(value, vmin, vmax, mixerCurrentFlightMode) + : GET_GVAR(value, vmin, vmax, mixerCurrentFlightMode)) + : GV_GET_GV1_VALUE(vmin, vmax)); + + // update field type based on value + update(); +} + +void GVarNumberEdit::setSuffix(std::string value) +{ + num_field->setSuffix(value); +} + +void GVarNumberEdit::onEvent(event_t event) +{ + if (event == EVT_KEY_LONG(KEY_ENTER)) { + // TODO: check this... + // killEvents(event); + switchGVarMode(); + } else { + Window::onEvent(event); + } +} + +void GVarNumberEdit::update() +{ + bool has_focus = act_field && act_field->hasFocus(); + + auto gvar_obj = gvar_field->getLvObj(); + auto num_obj = num_field->getLvObj(); + + lv_obj_add_flag(gvar_obj, LV_OBJ_FLAG_HIDDEN); + lv_obj_add_flag(num_obj, LV_OBJ_FLAG_HIDDEN); + + int32_t value = getValue(); + if (GV_IS_GV_VALUE(value, vmin, vmax)) { + // GVAR mode + act_field = gvar_field; + lv_obj_clear_flag(gvar_obj, LV_OBJ_FLAG_HIDDEN); + lv_event_send(gvar_obj, LV_EVENT_VALUE_CHANGED, nullptr); + } else { + // number edit mode + act_field = num_field; + lv_obj_clear_flag(num_obj, LV_OBJ_FLAG_HIDDEN); + num_field->setValue(value); + } + + if (has_focus) { + auto act_obj = act_field->getLvObj(); + lv_group_focus_obj(act_obj); + } +} diff --git a/radio/src/gui/colorlcd/gvar_numberedit.h b/radio/src/gui/colorlcd/gvar_numberedit.h index 1182a9891..b0bbf5130 100644 --- a/radio/src/gui/colorlcd/gvar_numberedit.h +++ b/radio/src/gui/colorlcd/gvar_numberedit.h @@ -29,117 +29,33 @@ constexpr coord_t GVAR_BUTTON_WIDTH = 30; - -class GVarNumberEdit : public FormGroup +class GVarNumberEdit : public Window { public: - GVarNumberEdit(FormGroup* parent, const rect_t& rect, int32_t vmin, - int32_t vmax, std::function getValue, + GVarNumberEdit(Window* parent, const rect_t& rect, int32_t vmin, int32_t vmax, + std::function getValue, std::function setValue, - WindowFlags windowFlags = 0, LcdFlags textFlags = 0, - int32_t voffset = 0) : - FormGroup(parent, rect, FORWARD_SCROLL /*| FORM_FORWARD_FOCUS*/), - vmin(vmin), - vmax(vmax), - voffset(voffset), - getValue(getValue), - setValue(setValue), - windowFlags(windowFlags), - textFlags(textFlags) - { - update(); - } + LcdFlags textFlags = 0, int32_t voffset = 0); - void switchGVarMode() - { - int32_t value = getValue(); - setValue( - GV_IS_GV_VALUE(value, vmin, vmax) - ? ((textFlags & PREC1) - ? GET_GVAR_PREC1(value, vmin, vmax, mixerCurrentFlightMode) - : GET_GVAR(value, vmin, vmax, mixerCurrentFlightMode)) - : GV_GET_GV1_VALUE(vmin, vmax)); - - update(); - } - - void setSuffix(std::string value) - { - suffix = std::move(value); - update(); - } - -#if defined(HARDWARE_KEYS) - void onEvent(event_t event) override - { - if (event == EVT_KEY_LONG(KEY_ENTER)) { - // TODO: check this... - // killEvents(event); - switchGVarMode(); - // field->setFocus(SET_FOCUS_DEFAULT); - } else { - FormGroup::onEvent(event); - } - } -#endif + void switchGVarMode(); + void setSuffix(std::string value); protected: - FormField* field = nullptr; + Choice* gvar_field = nullptr; + NumberEdit* num_field = nullptr; + FormField* act_field = nullptr; + int32_t vmin; int32_t vmax; - int32_t voffset; std::function getValue; std::function setValue; - WindowFlags windowFlags; LcdFlags textFlags; - std::string suffix; + int32_t voffset; - void update() - { - clear(); + void onEvent(event_t event) override; + void update(); - // The main field - int32_t value = getValue(); - if (GV_IS_GV_VALUE(value, vmin, vmax)) { - auto result = new Choice( - this, {0, 0, width() - GVAR_BUTTON_WIDTH, height()}, -MAX_GVARS, - MAX_GVARS - 1, - [=]() { - uint16_t gvar1 = GV_GET_GV1_VALUE(vmin, vmax); - return GV_INDEX_CALC_DELTA(getValue(), gvar1); - }, - [=](int idx) { - uint16_t gvar1 = GV_GET_GV1_VALUE(vmin, vmax); - if (idx < 0) - setValue(GV_CALC_VALUE_IDX_NEG(idx, gvar1)); - else - setValue(GV_CALC_VALUE_IDX_POS(idx, gvar1)); - }); - result->setTextHandler( - [=](int32_t value) { return getGVarString(value); }); - field = result; - } else { - auto result = new NumberEdit( - this, {0, 0, width() - GVAR_BUTTON_WIDTH, height()}, vmin, vmax, - [=]() { return getValue() + voffset; }, - [=](int32_t newValue) { return setValue(newValue - voffset); }, - windowFlags, textFlags); - result->setSuffix(suffix); - field = result; - } -#if defined(GVARS) - // The GVAR button - new TextButton( - this, {width() - GVAR_BUTTON_WIDTH, 0, GVAR_BUTTON_WIDTH, height()}, - STR_GV, - [=]() { - switchGVarMode(); - return 0; - }, - BUTTON_BACKGROUND | OPAQUE | FORM_DETACHED); -#endif - } + static void value_changed(lv_event_t* e); }; - #endif // _GVAR_NUMBEREDIT_H_ diff --git a/radio/src/gui/colorlcd/input_edit.cpp b/radio/src/gui/colorlcd/input_edit.cpp index 821df32b6..ff9fb6894 100644 --- a/radio/src/gui/colorlcd/input_edit.cpp +++ b/radio/src/gui/colorlcd/input_edit.cpp @@ -20,296 +20,125 @@ */ #include "input_edit.h" -#include "model_curves.h" +#include "input_edit_adv.h" + +#include "curve_param.h" +#include "gvar_numberedit.h" +#include "input_source.h" #include "opentx.h" -#include "gvar_numberedit.h" #define SET_DIRTY() storageDirty(EE_MODEL) -class SensorValue : Window -{ - public: - SensorValue(Window *parent, const rect_t &rect, ExpoData *expoData) : - Window(parent, rect), expoData(expoData) - { - } - void paint(BitmapBuffer *dc) override - { - if (isTelemetryValue()) { - uint8_t sensorIndex = (expoData->srcRaw - MIXSRC_FIRST_TELEM) / 3; -#if defined(SIMU) - if (true) { -#else - TelemetryItem &telemetryItem = telemetryItems[sensorIndex]; - if (telemetryItem.isAvailable()) { -#endif - LcdFlags flags = LEFT | COLOR_THEME_PRIMARY1; - drawSensorCustomValue(dc, 3, 2, sensorIndex, lastSensorVal, flags); - } else { - dc->drawText(3, 2, "---", COLOR_THEME_PRIMARY1); - } - } - } - bool isTelemetryValue() - { - return expoData->srcRaw >= MIXSRC_FIRST_TELEM && - expoData->srcRaw <= MIXSRC_LAST_TELEM; - } - void checkEvents() override - { - getvalue_t sensorVal = -1; - if (isTelemetryValue()) { - sensorVal = getValue(expoData->srcRaw); - } - if (lastSensorVal != sensorVal) { - lastSensorVal = sensorVal; - invalidate(); - } - } - - LcdFlags getSensorPrec() - { - LcdFlags prec = 0; - if (isTelemetryValue()) { - uint8_t sensorIndex = (expoData->srcRaw - MIXSRC_FIRST_TELEM) / 3; - TelemetrySensor sensor = g_model.telemetrySensors[sensorIndex]; - if (sensor.prec > 0) { - prec |= (sensor.prec == 1 ? PREC1 : PREC2); - } - } - return prec; - } - - protected: - getvalue_t lastSensorVal; - ExpoData *expoData; -}; - InputEditWindow::InputEditWindow(int8_t input, uint8_t index) : Page(ICON_MODEL_INPUTS), input(input), - index(index), - preview( - this, - {INPUT_EDIT_CURVE_LEFT, INPUT_EDIT_CURVE_TOP, INPUT_EDIT_CURVE_WIDTH, - INPUT_EDIT_CURVE_HEIGHT}, - [=](int x) -> int { - ExpoData *line = expoAddress(index); - int16_t anas[MAX_INPUTS] = {0}; - applyExpos(anas, e_perout_mode_inactive_flight_mode, line->srcRaw, x); - return anas[line->chn]; - }, - [=]() -> int { return getValue(expoAddress(index)->srcRaw); }) + index(index) { -#if LCD_W > LCD_H - auto BODY_WIDTH = LCD_W - preview.width() - PAGE_PADDING; - body.setWidth(BODY_WIDTH); - body.setLeft(preview.width() + PAGE_PADDING); -#else - body.setRect({0, INPUT_EDIT_CURVE_TOP + INPUT_EDIT_CURVE_HEIGHT, LCD_W, - LCD_H - INPUT_EDIT_CURVE_TOP - INPUT_EDIT_CURVE_HEIGHT}); + std::string title(STR_MENUINPUTS); + title += "\n"; + title += getSourceString(MIXSRC_FIRST_INPUT + input); + header.setTitle(title); + + auto body_obj = body.getLvObj(); +#if LCD_H > LCD_W // portrait + lv_obj_set_flex_flow(body_obj, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_pad_row(body_obj, lv_dpx(8), 0); +#else // landscape + lv_obj_set_flex_flow(body_obj, LV_FLEX_FLOW_ROW); + lv_obj_set_style_pad_column(body_obj, lv_dpx(8), 0); #endif - buildBody(&body); - buildHeader(&header); -} + lv_obj_set_style_flex_cross_place(body_obj, LV_FLEX_ALIGN_CENTER, 0); + + // TODO: would be better to set the padding on the preview window... + // ...but it doesn't support it yet. + lv_obj_set_style_pad_all(body_obj, lv_dpx(8), 0); -void InputEditWindow::deleteLater(bool detach, bool trash) -{ - if (_deleted) return; + auto box = new Window(&body, rect_t{}); + auto box_obj = box->getLvObj(); + lv_obj_set_flex_grow(box_obj, 2); - preview.deleteLater(true, false); - - Page::deleteLater(detach, trash); -} - -void InputEditWindow::buildHeader(Window *window) -{ - new StaticText(window, - {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, - PAGE_LINE_HEIGHT}, - STR_MENUINPUTS, 0, COLOR_THEME_PRIMARY2); - new StaticText(window, - {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, - LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, - getSourceString(MIXSRC_FIRST_INPUT + input), 0, - COLOR_THEME_PRIMARY2); -} - -// TODO share this code with MIXER -void InputEditWindow::updateCurveParamField(ExpoData *line) -{ - curveParamField->clear(); - - const rect_t rect = {0, 0, curveParamField->width(), - curveParamField->height()}; - - switch (line->curve.type) { - case CURVE_REF_DIFF: - case CURVE_REF_EXPO: { - GVarNumberEdit *edit = new GVarNumberEdit( - curveParamField, rect, -100, 100, GET_SET_DEFAULT(line->curve.value)); - edit->setSuffix("%"); - break; - } - - case CURVE_REF_FUNC: - new Choice(curveParamField, rect, STR_VCURVEFUNC, 0, CURVE_BASE - 1, - GET_SET_DEFAULT(line->curve.value)); - break; - - case CURVE_REF_CUSTOM: { - auto choice = new ChoiceEx(curveParamField, rect, -MAX_CURVES, MAX_CURVES, - GET_SET_DEFAULT(line->curve.value)); - choice->setTextHandler([](int value) { return getCurveString(value); }); - choice->setLongPressHandler([this](event_t event) { - ExpoData *line = expoAddress(index); - - // if no curve is specified then dont link to curve page - if (line->curve.value != 0) - ModelCurvesPage::pushEditCurve(abs(line->curve.value) - 1); - }); - break; - } - } -} - -void InputEditWindow::buildBody(FormWindow *window) -{ - FormGridLayout grid; - grid.setLabelWidth(INPUT_EDIT_LABELS_WIDTH); - grid.spacer(PAGE_PADDING); - - ExpoData *line = expoAddress(index); - -#if LCD_W > LCD_H - grid.setMarginRight(180); +#if LCD_H > LCD_W // portrait + box->setWidth(body.width() - 2*lv_dpx(8)); +#else // landscape + box->setHeight(body.height() - 2*lv_dpx(8)); #endif + auto form = new FormWindow(box, rect_t{}); + auto form_obj = form->getLvObj(); + lv_obj_set_style_pad_all(form_obj, lv_dpx(8), 0); + buildBody(form); + + preview = new Curve(&body, rect_t{}, + [=](int x) -> int { + ExpoData* line = expoAddress(index); + int16_t anas[MAX_INPUTS] = {0}; + applyExpos(anas, e_perout_mode_inactive_flight_mode, line->srcRaw, x); + return anas[line->chn]; + }, + [=]() -> int { return getValue(expoAddress(index)->srcRaw); }); + + preview->setWidth(INPUT_EDIT_CURVE_WIDTH); + preview->setHeight(INPUT_EDIT_CURVE_HEIGHT); +} + +static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2), + LV_GRID_TEMPLATE_LAST}; +static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; + +void InputEditWindow::buildBody(FormWindow* form) +{ + FlexGridLayout grid(col_dsc, row_dsc, 2); + form->setFlexLayout(); + + ExpoData* input = expoAddress(index); + // Input Name - new StaticText(window, grid.getLabelSlot(), STR_INPUTNAME, 0, - COLOR_THEME_PRIMARY1); - new ModelTextEdit(window, grid.getFieldSlot(), g_model.inputNames[line->chn], - sizeof(g_model.inputNames[line->chn])); - grid.nextLine(); + auto line = form->newLine(&grid); + auto inputName = g_model.inputNames[input->chn]; + new StaticText(line, rect_t{}, STR_INPUTNAME, 0, COLOR_THEME_PRIMARY1); + new ModelTextEdit(line, rect_t{}, inputName, sizeof(inputName)); - // Switch - new StaticText(window, grid.getLabelSlot(), STR_SWITCH, 0, - COLOR_THEME_PRIMARY1); - new SwitchChoice(window, grid.getFieldSlot(), SWSRC_FIRST_IN_MIXES, - SWSRC_LAST_IN_MIXES, GET_SET_DEFAULT(line->swtch)); - grid.nextLine(); - - // Side - new StaticText(window, grid.getLabelSlot(), STR_SIDE, 0, - COLOR_THEME_PRIMARY1); - new Choice( - window, grid.getFieldSlot(), STR_VCURVEFUNC, 1, 3, - [=]() -> int16_t { return 4 - line->mode; }, - [=](int16_t newValue) { - line->mode = 4 - newValue; - SET_DIRTY(); - }); - grid.nextLine(); - - // Name - new StaticText(window, grid.getLabelSlot(), STR_EXPONAME, 0, - COLOR_THEME_PRIMARY1); - new ModelTextEdit(window, grid.getFieldSlot(), line->name, - sizeof(line->name)); - grid.nextLine(); + // Line Name + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_EXPONAME, 0, COLOR_THEME_PRIMARY1); + new ModelTextEdit(line, rect_t{}, input->name, sizeof(input->name)); // Source - new StaticText(window, grid.getLabelSlot(), STR_SOURCE, 0, - COLOR_THEME_PRIMARY1); - new SourceChoice( - window, grid.getFieldSlot(2, 0), INPUTSRC_FIRST, INPUTSRC_LAST, - GET_DEFAULT(line->srcRaw), [=](int32_t newValue) { - line->srcRaw = newValue; - if (line->srcRaw > MIXSRC_Ail && line->carryTrim == TRIM_ON) { - line->carryTrim = TRIM_OFF; - trimChoice->invalidate(); - } - window->clear(); - buildBody(window); - SET_DIRTY(); - }); - - SensorValue *sensor = nullptr; - if (line->srcRaw >= MIXSRC_FIRST_TELEM) { - sensor = new SensorValue(window, grid.getFieldSlot(2, 1), line); - - grid.nextLine(); - // Scale - new StaticText(window, grid.getLabelSlot(), STR_SCALE, 0, - COLOR_THEME_PRIMARY1); - new NumberEdit(window, grid.getFieldSlot(), 0, - maxTelemValue(line->srcRaw - MIXSRC_FIRST_TELEM + 1), - GET_SET_DEFAULT(line->scale), 0, sensor->getSensorPrec()); - adjustHeight(); - } - grid.nextLine(); + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_SOURCE, 0, COLOR_THEME_PRIMARY1); + auto src = new InputSource(line, input); + lv_obj_set_style_grid_cell_x_align(src->getLvObj(), LV_GRID_ALIGN_STRETCH, 0); // Weight - new StaticText(window, grid.getLabelSlot(), STR_WEIGHT, 0, - COLOR_THEME_PRIMARY1); - auto gvar = new GVarNumberEdit(window, grid.getFieldSlot(), -100, 100, - GET_SET_DEFAULT(line->weight)); + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_WEIGHT, 0, COLOR_THEME_PRIMARY1); + auto gvar = new GVarNumberEdit(line, rect_t{}, -100, 100, GET_SET_DEFAULT(input->weight)); gvar->setSuffix("%"); - grid.nextLine(); // Offset - new StaticText(window, grid.getLabelSlot(), STR_OFFSET, 0, - COLOR_THEME_PRIMARY1); - gvar = new GVarNumberEdit(window, grid.getFieldSlot(), -100, 100, - GET_SET_DEFAULT(line->offset)); + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_OFFSET, 0, COLOR_THEME_PRIMARY1); + gvar = new GVarNumberEdit(line, rect_t{}, -100, 100, GET_SET_DEFAULT(input->offset)); gvar->setSuffix("%"); - grid.nextLine(); - // Trim - new StaticText(window, grid.getLabelSlot(), STR_TRIM, 0, - COLOR_THEME_PRIMARY1); - trimChoice = new Choice(window, grid.getFieldSlot(), STR_VMIXTRIMS, -TRIM_OFF, - -TRIM_LAST, GET_VALUE(-line->carryTrim), - SET_VALUE(line->carryTrim, -newValue)); - trimChoice->setAvailableHandler([=](int value) { - return value != TRIM_ON || line->srcRaw <= MIXSRC_Ail; - }); - grid.nextLine(); + // Switch + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_SWITCH, 0, COLOR_THEME_PRIMARY1); + new SwitchChoice(line, rect_t{}, SWSRC_FIRST_IN_MIXES, + SWSRC_LAST_IN_MIXES, GET_SET_DEFAULT(input->swtch)); // Curve - new StaticText(&body, grid.getLabelSlot(), STR_CURVE, 0, - COLOR_THEME_PRIMARY1); - new Choice(&body, grid.getFieldSlot(2, 0), "\004DiffExpoFuncCstm", 0, - CURVE_REF_CUSTOM, GET_DEFAULT(line->curve.type), - [=](int32_t newValue) { - line->curve.type = newValue; - line->curve.value = 0; - SET_DIRTY(); - updateCurveParamField(line); - }); - curveParamField = new FormGroup(&body, grid.getFieldSlot(2, 1) - // , FORM_FORWARD_FOCUS - ); - updateCurveParamField(line); - grid.nextLine(); + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_CURVE, 0, COLOR_THEME_PRIMARY1); + auto param = new CurveParam(line, rect_t{}, &input->curve); + lv_obj_set_style_grid_cell_x_align(param->getLvObj(), LV_GRID_ALIGN_STRETCH, 0); -#if defined(FLIGHT_MODES) - // Flight modes - new StaticText(window, grid.getLabelSlot(), STR_FLMODE, 0, - COLOR_THEME_PRIMARY1); - for (uint32_t i = 0; i < MAX_FLIGHT_MODES; i++) { - char fm[2] = {char('0' + i), '\0'}; - if (i > 0 && (i % 4) == 0) grid.nextLine(); - new TextButton( - window, grid.getFieldSlot(4, i % 4), fm, - [=]() -> uint32_t { - BFBIT_FLIP(line->flightModes, bfBit(i)); - SET_DIRTY(); - return !(bfSingleBitGet(line->flightModes, i)); - }, - OPAQUE | (bfSingleBitGet(line->flightModes, i) ? 0 : BUTTON_CHECKED)); - } - grid.nextLine(); -#endif + line = form->newLine(); + lv_obj_set_style_pad_all(line->getLvObj(), lv_dpx(8), 0); + auto btn = new TextButton(line, rect_t{}, LV_SYMBOL_SETTINGS, [=]() -> uint8_t { + new InputEditAdvanced(this->input, index); + return 0; + }); + lv_obj_set_width(btn->getLvObj(), lv_pct(100)); } diff --git a/radio/src/gui/colorlcd/input_edit.h b/radio/src/gui/colorlcd/input_edit.h index 854c02d22..338a6e0f0 100644 --- a/radio/src/gui/colorlcd/input_edit.h +++ b/radio/src/gui/colorlcd/input_edit.h @@ -31,16 +31,11 @@ class InputEditWindow : public Page { public: InputEditWindow(int8_t input, uint8_t index); - void deleteLater(bool detach = true, bool trash = true) override; protected: uint8_t input; uint8_t index; - Curve preview; - Choice *trimChoice = nullptr; - FormGroup *curveParamField = nullptr; + Curve* preview; - void buildHeader(Window *window); - void updateCurveParamField(ExpoData *line); void buildBody(FormWindow *window); }; diff --git a/radio/src/gui/colorlcd/input_edit_adv.cpp b/radio/src/gui/colorlcd/input_edit_adv.cpp new file mode 100644 index 000000000..93ffb2319 --- /dev/null +++ b/radio/src/gui/colorlcd/input_edit_adv.cpp @@ -0,0 +1,74 @@ +/* + * 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 "input_edit_adv.h" +#include "fm_matrix.h" + +#include "opentx.h" + +#define SET_DIRTY() storageDirty(EE_MODEL) + +static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), + LV_GRID_TEMPLATE_LAST}; +static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; + +InputEditAdvanced::InputEditAdvanced(uint8_t input_n, uint8_t index) : + Page(ICON_MODEL_INPUTS) +{ + std::string title(STR_MENUINPUTS); + title += "\n"; + title += getSourceString(MIXSRC_FIRST_INPUT + input_n); + header.setTitle(title); + + rect_t r = rect_t{0, 0, body.width(), body.height()}; + auto form = new FormWindow(&body, r); + + FlexGridLayout grid(col_dsc, row_dsc, 2); + form->setFlexLayout(); + + ExpoData* input = expoAddress(index); + + // Side + auto line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_SIDE, 0, COLOR_THEME_PRIMARY1); + new Choice( + line, rect_t{}, STR_VCURVEFUNC, 1, 3, + [=]() -> int16_t { return 4 - input->mode; }, + [=](int16_t newValue) { + input->mode = 4 - newValue; + SET_DIRTY(); + }); + + // Trim + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_TRIM, 0, COLOR_THEME_PRIMARY1); + auto c = new Choice(line, rect_t{}, STR_VMIXTRIMS, -TRIM_OFF, + -TRIM_LAST, GET_VALUE(-input->carryTrim), + SET_VALUE(input->carryTrim, -newValue)); + c->setAvailableHandler([=](int value) { + return value != TRIM_ON || input->srcRaw <= MIXSRC_Ail; + }); + + // Flight modes + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_FLMODE, 0, COLOR_THEME_PRIMARY1); + new FMMatrix(line, rect_t{}, input); +} diff --git a/radio/src/gui/colorlcd/input_edit_adv.h b/radio/src/gui/colorlcd/input_edit_adv.h new file mode 100644 index 000000000..11d11e760 --- /dev/null +++ b/radio/src/gui/colorlcd/input_edit_adv.h @@ -0,0 +1,33 @@ +/* + * 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 "page.h" +#include "button_matrix.h" + +struct ExpoData; + +class InputEditAdvanced : public Page +{ + public: + InputEditAdvanced(uint8_t input_n, uint8_t index); +}; diff --git a/radio/src/gui/colorlcd/input_source.cpp b/radio/src/gui/colorlcd/input_source.cpp new file mode 100644 index 000000000..f077530f5 --- /dev/null +++ b/radio/src/gui/colorlcd/input_source.cpp @@ -0,0 +1,160 @@ +/* + * 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 "input_source.h" +#include "opentx.h" + +#define SET_DIRTY() storageDirty(EE_MODEL) + +class SensorValue : public StaticText +{ + public: + SensorValue(Window *parent, const rect_t &rect, ExpoData *input) : + StaticText(parent, rect), input(input) + { + } + +// void paint(BitmapBuffer *dc) override +// { +// if (isTelemetryValue()) { +// uint8_t sensorIndex = (input->srcRaw - MIXSRC_FIRST_TELEM) / 3; +// #if defined(SIMU) +// if (true) { +// #else +// TelemetryItem &telemetryItem = telemetryItems[sensorIndex]; +// if (telemetryItem.isAvailable()) { +// #endif +// LcdFlags flags = LEFT | COLOR_THEME_PRIMARY1; +// drawSensorCustomValue(dc, 3, 2, sensorIndex, lastSensorVal, flags); +// } else { +// dc->drawText(3, 2, "---", COLOR_THEME_PRIMARY1); +// } +// } +// } + + bool isTelemetryValue() + { + return input->srcRaw >= MIXSRC_FIRST_TELEM && + input->srcRaw <= MIXSRC_LAST_TELEM; + } + + void checkEvents() override + { + if (lv_obj_has_flag(lvobj, LV_OBJ_FLAG_HIDDEN)) + return; + + // TODO: check for telemetry available + if (isTelemetryValue()) { + getvalue_t sensorVal = getValue(input->srcRaw); + if (lastSensorVal != sensorVal) { + lastSensorVal = sensorVal; + setText(std::to_string(lastSensorVal)); + } + } else { + setText("---"); + } + } + + LcdFlags getSensorPrec() + { + LcdFlags prec = 0; + if (isTelemetryValue()) { + uint8_t sensorIndex = (input->srcRaw - MIXSRC_FIRST_TELEM) / 3; + TelemetrySensor sensor = g_model.telemetrySensors[sensorIndex]; + if (sensor.prec > 0) { + prec |= (sensor.prec == 1 ? PREC1 : PREC2); + } + } + return prec; + } + + protected: + getvalue_t lastSensorVal; + ExpoData *input; +}; + +void InputSource::value_changed(lv_event_t *e) +{ + auto obj = lv_event_get_target(e); + auto src = (InputSource*)lv_obj_get_user_data(obj); + if (!src) return; + + src->update(); +} + +static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), + LV_GRID_TEMPLATE_LAST}; +static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; + +InputSource::InputSource(Window* parent, ExpoData* input) : + Window(parent, rect_t{}), input(input) +{ + lv_obj_set_flex_flow(lvobj, LV_FLEX_FLOW_COLUMN); + lv_obj_set_style_pad_row(lvobj, lv_dpx(4), 0); + lv_obj_set_size(lvobj, lv_pct(100), LV_SIZE_CONTENT); + + new SourceChoice( + this, rect_t{}, INPUTSRC_FIRST, INPUTSRC_LAST, GET_DEFAULT(input->srcRaw), + [=](int32_t newValue) { + input->srcRaw = newValue; + lv_event_send(lvobj, LV_EVENT_VALUE_CHANGED, nullptr); + SET_DIRTY(); + }); + lv_obj_add_event_cb(lvobj, InputSource::value_changed, LV_EVENT_VALUE_CHANGED, nullptr); + + sensor_form = new FormGroup(this, rect_t{}); + sensor_form->setFlexLayout(); + auto sensor_form_obj = sensor_form->getLvObj(); + + FlexGridLayout grid(col_dsc, row_dsc); + auto line = sensor_form->newLine(&grid); + + // Value + Window* w = new StaticText(line, rect_t{}, STR_VALUE, 0, COLOR_THEME_PRIMARY1); + auto sensor = new SensorValue(line, rect_t{}, input); + + + // Scale + line = sensor_form->newLine(&grid); + w = new StaticText(line, rect_t{}, STR_SCALE, 0, COLOR_THEME_PRIMARY1); + w = new NumberEdit(line, rect_t{}, 0, + maxTelemValue(input->srcRaw - MIXSRC_FIRST_TELEM + 1), + GET_SET_DEFAULT(input->scale), 0, sensor->getSensorPrec()); + + update(); +} + +void InputSource::update() +{ + if (input->srcRaw > MIXSRC_Ail && input->carryTrim == TRIM_ON) { + input->carryTrim = TRIM_OFF; + } + + if (!sensor_form) return; + auto sensor_form_obj = sensor_form->getLvObj(); + + if (input->srcRaw >= MIXSRC_FIRST_TELEM && + input->srcRaw <= MIXSRC_LAST_TELEM) { + lv_obj_clear_flag(sensor_form_obj, LV_OBJ_FLAG_HIDDEN); + } else { + lv_obj_add_flag(sensor_form_obj, LV_OBJ_FLAG_HIDDEN); + } +} diff --git a/radio/src/gui/colorlcd/input_source.h b/radio/src/gui/colorlcd/input_source.h new file mode 100644 index 000000000..81670a999 --- /dev/null +++ b/radio/src/gui/colorlcd/input_source.h @@ -0,0 +1,39 @@ +/* + * 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 "window.h" + +struct ExpoData; +class FormGroup; + +class InputSource : public Window +{ + ExpoData* input; + FormGroup* sensor_form; + + void update(); + static void value_changed(lv_event_t* e); + + public: + InputSource(Window* parent, ExpoData* input); +}; diff --git a/radio/src/gui/colorlcd/mixer_edit.cpp b/radio/src/gui/colorlcd/mixer_edit.cpp index 2e99dee35..2104afdaf 100644 --- a/radio/src/gui/colorlcd/mixer_edit.cpp +++ b/radio/src/gui/colorlcd/mixer_edit.cpp @@ -20,9 +20,10 @@ */ #include "mixer_edit.h" +#include "mixer_edit_adv.h" #include "channel_bar.h" #include "gvar_numberedit.h" -#include "model_curves.h" +#include "curve_param.h" #include "opentx.h" @@ -40,223 +41,101 @@ class MixerEditStatusBar : public Window { - public: - MixerEditStatusBar(Window *parent, const rect_t &rect, int8_t channel) : - Window(parent, rect), - _channel(channel) - { - channelBar = new ComboChannelBar(this, {MIX_STATUS_BAR_MARGIN, 0, rect.w - (MIX_STATUS_BAR_MARGIN * 2), rect.h}, channel); - channelBar->setLeftMargin(0); - channelBar->setTextColor(COLOR_THEME_PRIMARY2); - channelBar->setOutputChannelBarLimitColor(COLOR_THEME_EDIT); - } + public: + MixerEditStatusBar(Window *parent, const rect_t &rect, int8_t channel) : + Window(parent, rect), _channel(channel) + { + channelBar = + new ComboChannelBar(this, + {MIX_STATUS_BAR_MARGIN, 0, + rect.w - (MIX_STATUS_BAR_MARGIN * 2), rect.h}, + channel); + channelBar->setLeftMargin(0); + channelBar->setTextColor(COLOR_THEME_PRIMARY2); + channelBar->setOutputChannelBarLimitColor(COLOR_THEME_EDIT); + } - void paint(BitmapBuffer *dc) override - { - // dc->clear(COLOR_THEME_SECONDARY2); - } - - protected: - ComboChannelBar *channelBar; - int8_t _channel; + protected: + ComboChannelBar *channelBar; + int8_t _channel; }; -MixEditWindow::MixEditWindow(int8_t channel, uint8_t mixIndex) : - Page(ICON_MODEL_MIXER), channel(channel), mixIndex(mixIndex) +MixEditWindow::MixEditWindow(int8_t channel, uint8_t index) : + Page(ICON_MODEL_MIXER), channel(channel), index(index) { - buildBody(&body); + auto form = new FormWindow(&body, rect_t{}); + lv_obj_set_style_pad_all(form->getLvObj(), lv_dpx(8), 0); + + buildBody(form); buildHeader(&header); } void MixEditWindow::buildHeader(Window *window) { - new StaticText(window, - {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, - PAGE_LINE_HEIGHT}, - STR_MIXES, 0, COLOR_THEME_PRIMARY2); - new StaticText(window, - {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, - LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, - getSourceString(MIXSRC_CH1 + channel), 0, - COLOR_THEME_PRIMARY2); + std::string title(STR_MIXES); + title += "\n"; + title += getSourceString(MIXSRC_CH1 + channel); + header.setTitle(title); - statusBar = new MixerEditStatusBar( + new MixerEditStatusBar( window, {window->getRect().w - MIX_STATUS_BAR_WIDTH - MIX_RIGHT_MARGIN, 0, MIX_STATUS_BAR_WIDTH, MENU_HEADER_HEIGHT + 3}, channel); } -void MixEditWindow::buildBody(FormWindow *window) -{ - FormGridLayout grid; - grid.spacer(8); +static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2), + LV_GRID_TEMPLATE_LAST}; +static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; - MixData *mix = mixAddress(mixIndex); +void MixEditWindow::buildBody(FormWindow* form) +{ + FlexGridLayout grid(col_dsc, row_dsc, 2); + form->setFlexLayout(); + + MixData *mix = mixAddress(index); // Mix name - new StaticText(window, grid.getLabelSlot(), STR_MIXNAME, 0, - COLOR_THEME_PRIMARY1); - new ModelTextEdit(window, grid.getFieldSlot(), mix->name, sizeof(mix->name)); - grid.nextLine(); + auto line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_MIXNAME, 0, COLOR_THEME_PRIMARY1); + new ModelTextEdit(line, rect_t{}, mix->name, sizeof(mix->name)); // Source - new StaticText(window, grid.getLabelSlot(), STR_SOURCE, 0, - COLOR_THEME_PRIMARY1); - new SourceChoice(window, grid.getFieldSlot(), 0, MIXSRC_LAST, + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_SOURCE, 0, COLOR_THEME_PRIMARY1); + new SourceChoice(line, rect_t{}, 0, MIXSRC_LAST, GET_SET_DEFAULT(mix->srcRaw)); - grid.nextLine(); // Weight - new StaticText(window, grid.getLabelSlot(), STR_WEIGHT, 0, - COLOR_THEME_PRIMARY1); - auto gvar = new GVarNumberEdit(window, grid.getFieldSlot(), MIX_WEIGHT_MIN, - MIX_WEIGHT_MAX, GET_SET_DEFAULT(mix->weight)); + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_WEIGHT, 0, COLOR_THEME_PRIMARY1); + auto gvar = new GVarNumberEdit(line, rect_t{}, MIX_WEIGHT_MIN, MIX_WEIGHT_MAX, + GET_SET_DEFAULT(mix->weight)); gvar->setSuffix("%"); - grid.nextLine(); // Offset - new StaticText(window, grid.getLabelSlot(), STR_OFFSET, 0, - COLOR_THEME_PRIMARY1); - gvar = new GVarNumberEdit(window, grid.getFieldSlot(), MIX_OFFSET_MIN, - MIX_OFFSET_MAX, GET_SET_DEFAULT(mix->offset)); + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_OFFSET, 0, COLOR_THEME_PRIMARY1); + gvar = new GVarNumberEdit(line, rect_t{}, MIX_OFFSET_MIN, MIX_OFFSET_MAX, + GET_SET_DEFAULT(mix->offset)); gvar->setSuffix("%"); - grid.nextLine(); - - // Trim - new StaticText(window, grid.getLabelSlot(), STR_TRIM, 0, - COLOR_THEME_PRIMARY1); - new CheckBox(window, grid.getFieldSlot(), GET_SET_INVERTED(mix->carryTrim)); - grid.nextLine(); - - // Curve - new StaticText(&body, grid.getLabelSlot(), STR_CURVE, 0, - COLOR_THEME_PRIMARY1); - new Choice(&body, grid.getFieldSlot(2, 0), "\004DiffExpoFuncCstm", 0, - CURVE_REF_CUSTOM, GET_DEFAULT(mix->curve.type), - [=](int32_t newValue) { - mix->curve.type = newValue; - mix->curve.value = 0; - SET_DIRTY(); - updateCurveParamField(mix); - }); - curveParamField = - new FormGroup(&body, grid.getFieldSlot(2, 1) // , FORM_FORWARD_FOCUS - ); - updateCurveParamField(mix); - grid.nextLine(); - -#if defined(FLIGHT_MODES) - // Flight modes - new StaticText(window, grid.getLabelSlot(), STR_FLMODE, 0, - COLOR_THEME_PRIMARY1); - for (uint32_t i = 0; i < MAX_FLIGHT_MODES; i++) { - char fm[2] = {char('0' + i), '\0'}; - if (i > 0 && (i % 4) == 0) grid.nextLine(); - new TextButton( - window, grid.getFieldSlot(4, i % 4), fm, - [=]() -> uint32_t { - BFBIT_FLIP(mix->flightModes, bfBit(i)); - SET_DIRTY(); - return !(bfSingleBitGet(mix->flightModes, i)); - }, - OPAQUE | (bfSingleBitGet(mix->flightModes, i) ? 0 : BUTTON_CHECKED)); - } - grid.nextLine(); -#endif // Switch - new StaticText(window, grid.getLabelSlot(), STR_SWITCH, 0, - COLOR_THEME_PRIMARY1); - new SwitchChoice(window, grid.getFieldSlot(), SWSRC_FIRST_IN_MIXES, - SWSRC_LAST_IN_MIXES, GET_SET_DEFAULT(mix->swtch)); - grid.nextLine(); + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_SWITCH, 0, COLOR_THEME_PRIMARY1); + new SwitchChoice(line, rect_t{}, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, + GET_SET_DEFAULT(mix->swtch)); - // Warning - new StaticText(window, grid.getLabelSlot(), STR_MIXWARNING, 0, - COLOR_THEME_PRIMARY1); - auto edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, 3, - GET_SET_DEFAULT(mix->mixWarn)); - edit->setZeroText(STR_OFF); - grid.nextLine(); + // Curve + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_CURVE, 0, COLOR_THEME_PRIMARY1); + new CurveParam(line, rect_t{}, &mix->curve); - // Multiplex - new StaticText(window, grid.getLabelSlot(), STR_MULTPX, 0, - COLOR_THEME_PRIMARY1); - new Choice(window, grid.getFieldSlot(), STR_VMLTPX, 0, 2, - GET_SET_DEFAULT(mix->mltpx)); - grid.nextLine(); - - // Delay up - new StaticText(window, grid.getLabelSlot(), STR_DELAYUP, 0, - COLOR_THEME_PRIMARY1); - edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX, - GET_DEFAULT(mix->delayUp), - SET_VALUE(mix->delayUp, newValue), 0, PREC1); - edit->setSuffix("s"); - grid.nextLine(); - - // Delay down - new StaticText(window, grid.getLabelSlot(), STR_DELAYDOWN, 0, - COLOR_THEME_PRIMARY1); - edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX, - GET_DEFAULT(mix->delayDown), - SET_VALUE(mix->delayDown, newValue), 0, PREC1); - edit->setSuffix("s"); - grid.nextLine(); - - // Slow up - new StaticText(window, grid.getLabelSlot(), STR_SLOWUP, 0, - COLOR_THEME_PRIMARY1); - edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX, - GET_DEFAULT(mix->speedUp), - SET_VALUE(mix->speedUp, newValue), 0, PREC1); - edit->setSuffix("s"); - grid.nextLine(); - - // Slow down - new StaticText(window, grid.getLabelSlot(), STR_SLOWDOWN, 0, - COLOR_THEME_PRIMARY1); - edit = new NumberEdit(window, grid.getFieldSlot(2, 0), 0, DELAY_MAX, - GET_DEFAULT(mix->speedDown), - SET_VALUE(mix->speedDown, newValue), 0, PREC1); - edit->setSuffix("s"); - grid.nextLine(); -} - -// TODO share this code with INPUT -void MixEditWindow::updateCurveParamField(MixData *line) -{ - curveParamField->clear(); - - const rect_t rect = {0, 0, curveParamField->width(), - curveParamField->height()}; - - switch (line->curve.type) { - case CURVE_REF_DIFF: - case CURVE_REF_EXPO: { - GVarNumberEdit *edit = new GVarNumberEdit( - curveParamField, rect, -100, 100, GET_SET_DEFAULT(line->curve.value)); - edit->setSuffix("%"); - break; - } - - case CURVE_REF_FUNC: - new Choice(curveParamField, rect, STR_VCURVEFUNC, 0, CURVE_BASE - 1, - GET_SET_DEFAULT(line->curve.value)); - break; - - case CURVE_REF_CUSTOM: { - auto choice = new ChoiceEx(curveParamField, rect, -MAX_CURVES, MAX_CURVES, - GET_SET_DEFAULT(line->curve.value)); - choice->setTextHandler([](int value) { return getCurveString(value); }); - choice->setLongPressHandler([this](event_t event) { - MixData *mix = mixAddress(mixIndex); - // if no curve is specified then dont link to curve page - if (mix->curve.value != 0) - ModelCurvesPage::pushEditCurve(abs(mix->curve.value) - 1); - }); - break; - } - } + line = form->newLine(); + lv_obj_set_style_pad_all(line->getLvObj(), lv_dpx(8), 0); + auto btn = new TextButton(line, rect_t{}, LV_SYMBOL_SETTINGS, [=]() -> uint8_t { + new MixEditAdvanced(channel, index); + return 0; + }); + lv_obj_set_width(btn->getLvObj(), lv_pct(100)); } diff --git a/radio/src/gui/colorlcd/mixer_edit.h b/radio/src/gui/colorlcd/mixer_edit.h index 12e981151..76ec6e222 100644 --- a/radio/src/gui/colorlcd/mixer_edit.h +++ b/radio/src/gui/colorlcd/mixer_edit.h @@ -25,24 +25,17 @@ #include "form.h" #include "curve.h" -struct MixData; class FormGroup; -class MixerEditStatusBar; class MixEditWindow : public Page { public: - MixEditWindow(int8_t channel, uint8_t mixIndex); + MixEditWindow(int8_t channel, uint8_t index); protected: uint8_t channel; - uint8_t mixIndex; - FormGroup *curveParamField = nullptr; - MixerEditStatusBar *statusBar = nullptr; + uint8_t index; void buildHeader(Window *window); void buildBody(FormWindow *window); - - // TODO share this code with INPUT - void updateCurveParamField(MixData *line); }; diff --git a/radio/src/gui/colorlcd/mixer_edit_adv.cpp b/radio/src/gui/colorlcd/mixer_edit_adv.cpp new file mode 100644 index 000000000..02c2b3cef --- /dev/null +++ b/radio/src/gui/colorlcd/mixer_edit_adv.cpp @@ -0,0 +1,107 @@ +/* + * 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 "mixer_edit_adv.h" +#include "numberedit.h" +#include "fm_matrix.h" + +#include "opentx.h" + +#define SET_DIRTY() storageDirty(EE_MODEL) + +MixEditAdvanced::MixEditAdvanced(int8_t channel, uint8_t index) : + Page(ICON_MODEL_MIXER), channel(channel), index(index) +{ + std::string title(STR_MIXES); + title += "\n"; + title += getSourceString(MIXSRC_CH1 + channel); + header.setTitle(title); + + auto form = new FormWindow(&body, rect_t{}); + lv_obj_set_style_pad_all(form->getLvObj(), lv_dpx(8), 0); + + buildBody(form); +} + +static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2), + LV_GRID_TEMPLATE_LAST}; +static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST}; + +void MixEditAdvanced::buildBody(FormWindow* form) +{ + FlexGridLayout grid(col_dsc, row_dsc, 2); + form->setFlexLayout(); + + MixData *mix = mixAddress(index); + + // Advanced... + + // Multiplex + auto line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_MULTPX, 0, COLOR_THEME_PRIMARY1); + new Choice(line, rect_t{}, STR_VMLTPX, 0, 2, GET_SET_DEFAULT(mix->mltpx)); + + // Flight modes + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_FLMODE, 0, COLOR_THEME_PRIMARY1); + new FMMatrix(line, rect_t{}, mix); + + // Trim + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_TRIM, 0, COLOR_THEME_PRIMARY1); + new CheckBox(line, rect_t{}, GET_SET_INVERTED(mix->carryTrim)); + + // Warning + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_MIXWARNING, 0, COLOR_THEME_PRIMARY1); + auto edit = new NumberEdit(line, rect_t{}, 0, 3, GET_SET_DEFAULT(mix->mixWarn)); + edit->setZeroText(STR_OFF); + + // Delay up + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_DELAYUP, 0, COLOR_THEME_PRIMARY1); + edit = new NumberEdit(line, rect_t{}, 0, DELAY_MAX, GET_DEFAULT(mix->delayUp), + SET_VALUE(mix->delayUp, newValue), 0, PREC1); + edit->setSuffix("s"); + + // Delay down + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_DELAYDOWN, 0, COLOR_THEME_PRIMARY1); + edit = + new NumberEdit(line, rect_t{}, 0, DELAY_MAX, GET_DEFAULT(mix->delayDown), + SET_VALUE(mix->delayDown, newValue), 0, PREC1); + edit->setSuffix("s"); + + // Slow up + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_SLOWUP, 0, COLOR_THEME_PRIMARY1); + edit = new NumberEdit(line, rect_t{}, 0, DELAY_MAX, GET_DEFAULT(mix->speedUp), + SET_VALUE(mix->speedUp, newValue), 0, PREC1); + edit->setSuffix("s"); + + // Slow down + line = form->newLine(&grid); + new StaticText(line, rect_t{}, STR_SLOWDOWN, 0, COLOR_THEME_PRIMARY1); + edit = + new NumberEdit(line, rect_t{}, 0, DELAY_MAX, GET_DEFAULT(mix->speedDown), + SET_VALUE(mix->speedDown, newValue), 0, PREC1); + edit->setSuffix("s"); +} diff --git a/radio/src/gui/colorlcd/mixer_edit_adv.h b/radio/src/gui/colorlcd/mixer_edit_adv.h new file mode 100644 index 000000000..0f2996386 --- /dev/null +++ b/radio/src/gui/colorlcd/mixer_edit_adv.h @@ -0,0 +1,41 @@ +/* + * 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 "page.h" +#include "form.h" +#include "curve.h" + +class FormGroup; + +class MixEditAdvanced : public Page +{ + public: + MixEditAdvanced(int8_t channel, uint8_t index); + + protected: + uint8_t channel; + uint8_t index; + + void buildHeader(Window *window); + void buildBody(FormWindow *window); +}; diff --git a/radio/src/gui/colorlcd/model_inputs.cpp b/radio/src/gui/colorlcd/model_inputs.cpp index deb05f539..deadd7ea8 100644 --- a/radio/src/gui/colorlcd/model_inputs.cpp +++ b/radio/src/gui/colorlcd/model_inputs.cpp @@ -158,8 +158,8 @@ class InputLineButton : public InputMixButton } // second line ... + y += line_h; if (line.swtch || line.curve.value) { - y += line_h; if (line.swtch) { dc->drawMask(x, y, mixerSetupSwitchIcon, textColor); drawSwitch(dc, x + 21, y, line.swtch, textColor); diff --git a/radio/src/gui/colorlcd/output_edit.cpp b/radio/src/gui/colorlcd/output_edit.cpp index ef5b07ef3..e2a67d9e1 100644 --- a/radio/src/gui/colorlcd/output_edit.cpp +++ b/radio/src/gui/colorlcd/output_edit.cpp @@ -124,7 +124,7 @@ void OutputEditWindow::buildBody(FormWindow *window) new StaticText(window, grid.getLabelSlot(), TR_LIMITS_HEADERS_SUBTRIM, 0, COLOR_THEME_PRIMARY1); new GVarNumberEdit(window, grid.getFieldSlot(), -LIMIT_STD_MAX, - +LIMIT_STD_MAX, GET_SET_DEFAULT(output->offset), 0, PREC1); + +LIMIT_STD_MAX, GET_SET_DEFAULT(output->offset), PREC1); grid.nextLine(); // TRACE("ch=%d cV=%d zero=%d", channel, chanVal, chanZero); @@ -133,14 +133,14 @@ void OutputEditWindow::buildBody(FormWindow *window) minText = new StaticText(window, grid.getLabelSlot(), TR_MIN, 0, COLOR_THEME_PRIMARY1); new GVarNumberEdit(window, grid.getFieldSlot(), -limit, 0, - GET_SET_DEFAULT(output->min), 0, PREC1, -LIMIT_STD_MAX); + GET_SET_DEFAULT(output->min), PREC1, -LIMIT_STD_MAX); grid.nextLine(); // Max maxText = new StaticText(window, grid.getLabelSlot(), TR_MAX, 0, COLOR_THEME_PRIMARY1); new GVarNumberEdit(window, grid.getFieldSlot(), 0, +limit, - GET_SET_DEFAULT(output->max), 0, PREC1, +LIMIT_STD_MAX); + GET_SET_DEFAULT(output->max), PREC1, +LIMIT_STD_MAX); grid.nextLine(); // Direction diff --git a/radio/src/gui/colorlcd/page.cpp b/radio/src/gui/colorlcd/page.cpp index 796023970..9793b3e0c 100644 --- a/radio/src/gui/colorlcd/page.cpp +++ b/radio/src/gui/colorlcd/page.cpp @@ -27,14 +27,17 @@ PageHeader::PageHeader(Page * parent, uint8_t icon): FormGroup(parent, { 0, 0, LCD_W, MENU_HEADER_HEIGHT }, OPAQUE), icon(icon) -#if defined(HARDWARE_TOUCH) - , back(this, { 0, 0, MENU_HEADER_BACK_BUTTON_WIDTH, MENU_HEADER_BACK_BUTTON_HEIGHT }, - [=]() -> uint8_t { - parent->deleteLater(); - return 0; - }, NO_FOCUS | FORM_NO_BORDER) -#endif { +#if defined(HARDWARE_TOUCH) + new Button(this, { 0, 0, MENU_HEADER_BACK_BUTTON_WIDTH, MENU_HEADER_BACK_BUTTON_HEIGHT }, + [=]() -> uint8_t { + parent->deleteLater(); + return 0; + }, NO_FOCUS | FORM_NO_BORDER); +#endif + title = new StaticText(this, rect_t{}, "", 0, COLOR_THEME_PRIMARY2); + title->setTop(PAGE_TITLE_TOP); + title->setLeft(PAGE_TITLE_LEFT); } void PageHeader::paint(BitmapBuffer * dc) diff --git a/radio/src/gui/colorlcd/page.h b/radio/src/gui/colorlcd/page.h index 2f2a443b0..8a4084625 100644 --- a/radio/src/gui/colorlcd/page.h +++ b/radio/src/gui/colorlcd/page.h @@ -24,6 +24,7 @@ #include "window.h" #include "button.h" +#include "static.h" class Page; @@ -32,24 +33,14 @@ class PageHeader : public FormGroup public: PageHeader(Page* parent, uint8_t icon); -#if defined(HARDWARE_TOUCH) - void deleteLater(bool detach = true, bool trash = true) override - { - if (_deleted) return; - - back.deleteLater(true, false); - FormGroup::deleteLater(detach, trash); - } -#endif + uint8_t getIcon() const { return icon; } + void setTitle(std::string txt) { title->setText(std::move(txt)); } void paint(BitmapBuffer* dc) override; - uint8_t getIcon() const { return icon; } protected: uint8_t icon; -#if defined(HARDWARE_TOUCH) - Button back; -#endif + StaticText* title; }; class Page : public Window @@ -57,8 +48,6 @@ class Page : public Window public: explicit Page(unsigned icon); - void deleteLater(bool detach = true, bool trash = true) override; - #if defined(DEBUG_WINDOWS) std::string getName() const override { return "Page"; } #endif @@ -67,6 +56,7 @@ class Page : public Window void onClicked() override; void paint(BitmapBuffer* dc) override; + void deleteLater(bool detach = true, bool trash = true) override; protected: PageHeader header; diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index d37e86b44..4460a7319 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1404,6 +1404,8 @@ void opentxClose(uint8_t shutdown) RTOS_WAIT_MS(100); #if defined(COLORLCD) + // clear layer stack first + for (Window* w = Layer::back(); w; w = Layer::back()) w->deleteLater(); MainWindow::instance()->clear(); // this is necessary as the custom screens are not deleted // by using deleteCustomScreens(), but here through it's parent window diff --git a/radio/src/targets/horus/libopenui_config.h b/radio/src/targets/horus/libopenui_config.h index 2e3c013ac..31a2cac30 100644 --- a/radio/src/targets/horus/libopenui_config.h +++ b/radio/src/targets/horus/libopenui_config.h @@ -117,7 +117,7 @@ constexpr uint32_t PAGE_TITLE_LEFT = 50; constexpr uint32_t INPUT_EDIT_LABELS_WIDTH = 120; -constexpr coord_t INPUT_EDIT_CURVE_WIDTH = 158; +constexpr coord_t INPUT_EDIT_CURVE_WIDTH = 132; constexpr coord_t INPUT_EDIT_CURVE_HEIGHT = INPUT_EDIT_CURVE_WIDTH; constexpr coord_t INPUT_EDIT_CURVE_LEFT = PAGE_PADDING; constexpr coord_t INPUT_EDIT_CURVE_TOP = MENU_HEADER_HEIGHT + PAGE_PADDING; diff --git a/radio/src/targets/nv14/libopenui_config.h b/radio/src/targets/nv14/libopenui_config.h index 4240af8a8..ca6ea9d87 100644 --- a/radio/src/targets/nv14/libopenui_config.h +++ b/radio/src/targets/nv14/libopenui_config.h @@ -114,10 +114,10 @@ constexpr uint32_t PAGE_TITLE_TOP = 2; constexpr uint32_t PAGE_TITLE_LEFT = 50; constexpr uint32_t INPUT_EDIT_LABELS_WIDTH = 80; -constexpr coord_t INPUT_EDIT_CURVE_WIDTH = LCD_W; -constexpr coord_t INPUT_EDIT_CURVE_HEIGHT = 158; -constexpr coord_t INPUT_EDIT_CURVE_LEFT = 0; -constexpr coord_t INPUT_EDIT_CURVE_TOP = MENU_HEADER_HEIGHT; +constexpr coord_t INPUT_EDIT_CURVE_WIDTH = 176; +constexpr coord_t INPUT_EDIT_CURVE_HEIGHT = 132; +constexpr coord_t INPUT_EDIT_CURVE_LEFT = PAGE_PADDING; +constexpr coord_t INPUT_EDIT_CURVE_TOP = MENU_HEADER_HEIGHT + PAGE_PADDING; constexpr coord_t MENUS_LINE_HEIGHT = 40; constexpr coord_t MENUS_WIDTH = 200; constexpr coord_t POPUP_HEADER_HEIGHT = 30; diff --git a/radio/src/thirdparty/libopenui b/radio/src/thirdparty/libopenui index 67df92ec6..29dd3f3ec 160000 --- a/radio/src/thirdparty/libopenui +++ b/radio/src/thirdparty/libopenui @@ -1 +1 @@ -Subproject commit 67df92ec6da99315ad8f6b824f427381fb14cd8c +Subproject commit 29dd3f3ec154dccbe507001424a86fa70e9835f6