Input & Mixer edit pages: flex layout rework
This commit is contained in:
committed by
Raphael Coeffic
parent
c418758863
commit
e31a1cc1fc
@@ -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)
|
||||
|
||||
@@ -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<int(int)> function;
|
||||
std::function<int()> position;
|
||||
std::list<CurvePoint> points;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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<class T>
|
||||
FMMatrix<T>::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<class T>
|
||||
void FMMatrix<T>::onPress(uint8_t btn_id)
|
||||
{
|
||||
if (btn_id >= MAX_FLIGHT_MODES) return;
|
||||
BFBIT_FLIP(input->flightModes, bfBit<uint32_t>(btn_id));
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool FMMatrix<T>::isActive(uint8_t btn_id)
|
||||
{
|
||||
if (btn_id >= MAX_FLIGHT_MODES) return false;
|
||||
return !bfSingleBitGet(input->flightModes, btn_id);
|
||||
}
|
||||
|
||||
// explicit instantiation
|
||||
template struct FMMatrix<ExpoData>;
|
||||
template struct FMMatrix<MixData>;
|
||||
@@ -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<class T>
|
||||
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<ExpoData>;
|
||||
extern template struct FMMatrix<MixData>;
|
||||
@@ -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<int32_t()> getValue,
|
||||
std::function<void(int32_t)> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<int32_t()> getValue,
|
||||
GVarNumberEdit(Window* parent, const rect_t& rect, int32_t vmin, int32_t vmax,
|
||||
std::function<int32_t()> getValue,
|
||||
std::function<void(int32_t)> 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<int32_t()> getValue;
|
||||
std::function<void(int32_t)> 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_
|
||||
|
||||
@@ -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<uint32_t>(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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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<ExpoData>(line, rect_t{}, input);
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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<uint32_t>(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));
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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<MixData>(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");
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Vendored
+1
-1
Submodule radio/src/thirdparty/libopenui updated: 67df92ec6d...29dd3f3ec1
Reference in New Issue
Block a user