chore(color): more layout cleanup and minor bug fixes (#5171)

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