fix(color): Button matrix styling (#4318)

This commit is contained in:
philmoz
2023-11-17 10:50:56 +10:00
committed by GitHub
parent b0e43e09ea
commit 2ff6f75a26
5 changed files with 518 additions and 454 deletions
+12 -13
View File
@@ -20,32 +20,31 @@
*/
#include "fm_matrix.h"
#include "opentx.h"
template<class T>
template <class T>
FMMatrix<T>::FMMatrix(Window* parent, const rect_t& r, T* input) :
ButtonMatrix(parent, r), input(input)
{
#if LCD_W > LCD_H
initBtnMap(5, MAX_FLIGHT_MODES + 1);
initBtnMap(5, MAX_FLIGHT_MODES);
#else
initBtnMap(3, MAX_FLIGHT_MODES);
#endif
update();
for (int i = 0; i < MAX_FLIGHT_MODES; i++) {
setTextAndState(i);
}
update();
#if LCD_W > LCD_H
// hide last element
lv_btnmatrix_set_btn_ctrl(lvobj, MAX_FLIGHT_MODES, LV_BTNMATRIX_CTRL_HIDDEN);
lv_obj_set_width(lvobj, LV_DPI_DEF * 2);
lv_obj_set_height(lvobj, LV_DPI_DEF / 2);
lv_obj_set_width(lvobj, 258);
lv_obj_set_height(lvobj, 73);
#else
lv_obj_set_width(lvobj, LV_DPI_DEF);
lv_obj_set_height(lvobj, LV_DPI_DEF);
lv_obj_set_width(lvobj, 156);
lv_obj_set_height(lvobj, 108);
#endif
lv_obj_set_style_pad_all(lvobj, lv_dpx(4), LV_PART_MAIN);
@@ -53,14 +52,14 @@ FMMatrix<T>::FMMatrix(Window* parent, const rect_t& r, T* input) :
lv_obj_set_style_pad_column(lvobj, lv_dpx(4), LV_PART_MAIN);
}
template<class T>
template <class T>
void FMMatrix<T>::setTextAndState(uint8_t btn_id)
{
setText(btn_id, std::to_string(btn_id).c_str());
setChecked(btn_id);
}
template<class T>
template <class T>
void FMMatrix<T>::onPress(uint8_t btn_id)
{
if (btn_id >= MAX_FLIGHT_MODES) return;
@@ -69,7 +68,7 @@ void FMMatrix<T>::onPress(uint8_t btn_id)
storageDirty(EE_MODEL);
}
template<class T>
template <class T>
bool FMMatrix<T>::isActive(uint8_t btn_id)
{
if (btn_id >= MAX_FLIGHT_MODES) return false;
+404 -368
View File
@@ -20,19 +20,19 @@
*/
#include "model_usbjoystick.h"
#include "usb_joystick.h"
#include "channel_bar.h"
#include "button_matrix.h"
#include "button_matrix.h"
#include "channel_bar.h"
#include "opentx.h"
#include "usb_joystick.h"
#define SET_DIRTY() storageDirty(EE_MODEL)
#if LCD_W > LCD_H // Landscape
#if LCD_W > LCD_H // Landscape
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};
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
@@ -40,23 +40,25 @@ static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
#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};
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 PAGE_LINE_HEIGHT + 14
#define USBCH_LINE_HEIGHT PAGE_LINE_HEIGHT + 12
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), LV_GRID_TEMPLATE_LAST};
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),
LV_GRID_TEMPLATE_LAST};
static const lv_coord_t b_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
#else // Portrait
#else // Portrait
static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
LV_GRID_TEMPLATE_LAST};
LV_GRID_TEMPLATE_LAST};
#define USBCH_EDIT_STATUS_BAR_WIDTH 160
#define USBCH_EDIT_STATUS_BAR_MARGIN 0
@@ -64,18 +66,19 @@ static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
#define USBCH_COLS 2
static const lv_coord_t ch_col_dsc[] = {LV_GRID_FR(2), LV_GRID_FR(3),
LV_GRID_TEMPLATE_LAST};
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 2 * PAGE_LINE_HEIGHT + 10
#define USBCH_LINE_HEIGHT 2 * PAGE_LINE_HEIGHT + 8
static const lv_coord_t b_col_dsc[] = {LV_GRID_FR(1), 20, LV_GRID_FR(1), LV_GRID_FR(1),
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};
static const lv_coord_t b_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};
static const lv_coord_t b_row_dsc[] = {LV_GRID_CONTENT, LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
#endif
#define USBCH_BTNMX_COL 8
@@ -84,111 +87,114 @@ static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_TEMPLATE_LAST};
class USBChannelEditStatusBar : public Window
{
public:
USBChannelEditStatusBar(Window *parent, const rect_t &rect, int8_t channel) :
Window(parent, rect), _channel(channel)
{
channelBar = new ComboChannelBar(this, {USBCH_EDIT_STATUS_BAR_MARGIN, 0, rect.w - (USBCH_EDIT_STATUS_BAR_MARGIN * 2), rect.h}, channel);
channelBar->setLeftMargin(15);
channelBar->setTextColor(COLOR_THEME_PRIMARY2);
channelBar->setOutputChannelBarLimitColor(COLOR_THEME_EDIT);
}
public:
USBChannelEditStatusBar(Window* parent, const rect_t& rect, int8_t channel) :
Window(parent, rect), _channel(channel)
{
channelBar = new ComboChannelBar(
this,
{USBCH_EDIT_STATUS_BAR_MARGIN, 0,
rect.w - (USBCH_EDIT_STATUS_BAR_MARGIN * 2), rect.h},
channel);
channelBar->setLeftMargin(15);
channelBar->setTextColor(COLOR_THEME_PRIMARY2);
channelBar->setOutputChannelBarLimitColor(COLOR_THEME_EDIT);
}
protected:
ComboChannelBar *channelBar;
int8_t _channel;
protected:
ComboChannelBar* channelBar;
int8_t _channel;
};
static void btnsel_event_cb(lv_event_t* e);
class USBChannelButtonSel : public ButtonMatrix
{
public:
USBChannelButtonSel(Window* parent, const rect_t& rect, uint8_t channel,
std::function<void(int)> _setValue) :
public:
USBChannelButtonSel(Window* parent, const rect_t& rect, uint8_t channel,
std::function<void(int)> _setValue) :
ButtonMatrix(parent, rect),
m_channel(channel),
m_setValue(std::move(_setValue))
{
bg_color[0] = makeLvColor(COLOR_THEME_PRIMARY2); // Unused
fg_color[0] = makeLvColor(COLOR_THEME_SECONDARY1);
bg_color[1] = makeLvColor(COLOR_THEME_DISABLED); // Used by other channel_bar
fg_color[1] = makeLvColor(COLOR_THEME_PRIMARY1);
bg_color[2] = makeLvColor(COLOR_THEME_ACTIVE); // Used by this channel
fg_color[2] = makeLvColor(COLOR_THEME_PRIMARY1);
bg_color[3] = makeLvColor(COLOR_THEME_WARNING); // Collision
fg_color[3] = makeLvColor(COLOR_THEME_PRIMARY2);
{
bg_color[0] = makeLvColor(COLOR_THEME_PRIMARY2); // Unused
fg_color[0] = makeLvColor(COLOR_THEME_SECONDARY1);
bg_color[1] =
makeLvColor(COLOR_THEME_DISABLED); // Used by other channel_bar
fg_color[1] = makeLvColor(COLOR_THEME_PRIMARY1);
bg_color[2] = makeLvColor(COLOR_THEME_ACTIVE); // Used by this channel
fg_color[2] = makeLvColor(COLOR_THEME_PRIMARY1);
bg_color[3] = makeLvColor(COLOR_THEME_WARNING); // Collision
fg_color[3] = makeLvColor(COLOR_THEME_PRIMARY2);
initBtnMap(USBCH_BTNMX_COL, USBJ_BUTTON_SIZE);
char snum[5];
for (uint8_t btn = 0; btn < USBJ_BUTTON_SIZE; btn++) {
snprintf(snum, 5, "%u", btn);
setText(btn, snum);
}
update();
initBtnMap(USBCH_BTNMX_COL, USBJ_BUTTON_SIZE);
char snum[5];
for (uint8_t btn = 0; btn < USBJ_BUTTON_SIZE; btn++) {
snprintf(snum, 5, "%u", btn);
setText(btn, snum);
}
update();
lv_obj_set_style_radius(lvobj, LV_RADIUS_CIRCLE, LV_PART_ITEMS);
lv_obj_set_style_radius(lvobj, LV_RADIUS_CIRCLE, LV_PART_ITEMS);
lv_obj_add_event_cb(lvobj, btnsel_event_cb, LV_EVENT_DRAW_PART_BEGIN, this);
lv_obj_add_event_cb(lvobj, btnsel_event_cb, LV_EVENT_DRAW_PART_BEGIN, this);
memset(m_btns, 0, USBJ_BUTTON_SIZE);
for (uint8_t ch = 0; ch < USBJ_MAX_JOYSTICK_CHANNELS; ch++) {
if (ch != m_channel) {
USBJoystickChData * cch = usbJChAddress(ch);
memset(m_btns, 0, USBJ_BUTTON_SIZE);
for (uint8_t ch = 0; ch < USBJ_MAX_JOYSTICK_CHANNELS; ch++) {
if (ch != m_channel) {
USBJoystickChData* cch = usbJChAddress(ch);
if (cch->mode == USBJOYS_CH_BUTTON) {
uint8_t last = cch->lastBtnNum();
for(uint8_t b = cch->btn_num; b <= last; b++) {
m_btns[b] = 1;
}
if (cch->mode == USBJOYS_CH_BUTTON) {
uint8_t last = cch->lastBtnNum();
for (uint8_t b = cch->btn_num; b <= last; b++) {
m_btns[b] = 1;
}
}
}
updateState();
}
updateState();
}
void onPress(uint8_t btn_id) override
{
if (m_setValue) {
m_setValue(btn_id);
}
updateState();
void onPress(uint8_t btn_id) override
{
if (m_setValue) {
m_setValue(btn_id);
}
updateState();
}
bool isActive(uint8_t btn_id) override { return false; }
bool isActive(uint8_t btn_id) override { return false; }
uint8_t getBtnState(uint8_t id)
{
if (id < USBJ_BUTTON_SIZE) return m_btns[id];
return 0;
}
uint8_t getBtnState(uint8_t id)
{
if (id < USBJ_BUTTON_SIZE) return m_btns[id];
return 0;
}
void updateState()
{
USBJoystickChData * cch = usbJChAddress(m_channel);
uint8_t last = cch->lastBtnNum();
uint8_t i;
void updateState()
{
USBJoystickChData* cch = usbJChAddress(m_channel);
uint8_t last = cch->lastBtnNum();
uint8_t i;
for (i = 0; i < USBJ_BUTTON_SIZE; i++)
m_btns[i] &= 1;
for (i = 0; i < USBJ_BUTTON_SIZE; i++) m_btns[i] &= 1;
for(i = cch->btn_num; i <= last; i++)
m_btns[i] |= 2;
}
for (i = cch->btn_num; i <= last; i++) m_btns[i] |= 2;
}
void setColor(lv_obj_draw_part_dsc_t* dsc)
{
uint8_t state = getBtnState((uint8_t)dsc->id);
dsc->rect_dsc->bg_color = bg_color[state];
dsc->label_dsc->color = fg_color[state];
}
void setColor(lv_obj_draw_part_dsc_t* dsc)
{
uint8_t state = getBtnState((uint8_t)dsc->id);
dsc->rect_dsc->bg_color = bg_color[state];
dsc->label_dsc->color = fg_color[state];
}
protected:
uint8_t m_channel = 0;
std::function<void(int)> m_setValue;
uint8_t m_btns[USBJ_BUTTON_SIZE];
lv_color_t bg_color[4];
lv_color_t fg_color[4];
protected:
uint8_t m_channel = 0;
std::function<void(int)> m_setValue;
uint8_t m_btns[USBJ_BUTTON_SIZE];
lv_color_t bg_color[4];
lv_color_t fg_color[4];
};
static void btnsel_event_cb(lv_event_t* e)
@@ -198,7 +204,8 @@ static void btnsel_event_cb(lv_event_t* e)
if (code == LV_EVENT_DRAW_PART_BEGIN) {
lv_obj_draw_part_dsc_t* dsc = lv_event_get_draw_part_dsc(e);
if(dsc->class_p == &lv_btnmatrix_class && dsc->type == LV_BTNMATRIX_DRAW_PART_BTN) {
if (dsc->class_p == &lv_btnmatrix_class &&
dsc->type == LV_BTNMATRIX_DRAW_PART_BTN) {
auto btsel = (USBChannelButtonSel*)lv_event_get_user_data(e);
btsel->setColor(dsc);
}
@@ -206,310 +213,332 @@ static void btnsel_event_cb(lv_event_t* e)
}
#define USBCH_LINES 3
#define SET_VALUE_WUPDATE(value) [=](int32_t newValue) { value = newValue; SET_DIRTY(); this->update(); }
#define SET_VALUE_WUPDATE(value) \
[=](int32_t newValue) { \
value = newValue; \
SET_DIRTY(); \
this->update(); \
}
class USBChannelEditWindow : public Page
{
public:
USBChannelEditWindow(uint8_t channel) :
Page(ICON_MODEL_USB), channel(channel)
{
auto form = new FormWindow(&body, rect_t{});
form->padAll(2);
form->padLeft(8);
form->padRight(8);
public:
USBChannelEditWindow(uint8_t channel) : Page(ICON_MODEL_USB), channel(channel)
{
auto form = new FormWindow(&body, rect_t{});
form->padAll(2);
form->padLeft(8);
form->padRight(8);
buildHeader(&header);
buildBody(form);
}
buildHeader(&header);
buildBody(form);
}
protected:
uint8_t channel;
USBChannelEditStatusBar* statusBar = nullptr;
FormWindow* m_btnModeFrame = nullptr;
Window* m_axisModeLine = nullptr;
Window* m_simModeLine = nullptr;
USBChannelButtonSel* _BtnNumSel = nullptr;
StaticText* collisionText = nullptr;
Choice* m_btnPosChoice = nullptr;
protected:
uint8_t channel;
USBChannelEditStatusBar* statusBar = nullptr;
FormWindow* m_btnModeFrame = nullptr;
Window* m_axisModeLine = nullptr;
Window* m_simModeLine = nullptr;
USBChannelButtonSel* _BtnNumSel = nullptr;
StaticText* collisionText = nullptr;
Choice* m_btnPosChoice = nullptr;
protected:
void update()
{
USBJoystickChData * cch = usbJChAddress(channel);
protected:
void update()
{
USBJoystickChData* cch = usbJChAddress(channel);
lv_obj_add_flag(m_btnModeFrame->getLvObj(), LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(m_axisModeLine->getLvObj(), LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(m_simModeLine->getLvObj(), LV_OBJ_FLAG_HIDDEN);
if (cch->mode == USBJOYS_CH_BUTTON)
lv_obj_clear_flag(m_btnModeFrame->getLvObj(), LV_OBJ_FLAG_HIDDEN);
else if (cch->mode == USBJOYS_CH_AXIS)
lv_obj_clear_flag(m_axisModeLine->getLvObj(), LV_OBJ_FLAG_HIDDEN);
else if (cch->mode == USBJOYS_CH_SIM)
lv_obj_clear_flag(m_simModeLine->getLvObj(), LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(m_btnModeFrame->getLvObj(), LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(m_axisModeLine->getLvObj(), LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(m_simModeLine->getLvObj(), LV_OBJ_FLAG_HIDDEN);
if (cch->mode == USBJOYS_CH_BUTTON)
lv_obj_clear_flag(m_btnModeFrame->getLvObj(), LV_OBJ_FLAG_HIDDEN);
else if (cch->mode == USBJOYS_CH_AXIS)
lv_obj_clear_flag(m_axisModeLine->getLvObj(), LV_OBJ_FLAG_HIDDEN);
else if (cch->mode == USBJOYS_CH_SIM)
lv_obj_clear_flag(m_simModeLine->getLvObj(), LV_OBJ_FLAG_HIDDEN);
if(m_btnPosChoice)
m_btnPosChoice->enable((cch->param != USBJOYS_BTN_MODE_SW_EMU) && (cch->param != USBJOYS_BTN_MODE_DELTA));
if (m_btnPosChoice)
m_btnPosChoice->enable((cch->param != USBJOYS_BTN_MODE_SW_EMU) &&
(cch->param != USBJOYS_BTN_MODE_DELTA));
if(collisionText) {
collisionText->setText("");
lv_obj_add_flag(collisionText->getLvObj(), LV_OBJ_FLAG_HIDDEN);
if (cch->mode == USBJOYS_CH_BUTTON) {
if (isUSBBtnNumCollision(channel)) {
collisionText->setText(STR_USBJOYSTICK_BTN_COLLISION);
lv_obj_clear_flag(collisionText->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
if (collisionText) {
collisionText->setText("");
lv_obj_add_flag(collisionText->getLvObj(), LV_OBJ_FLAG_HIDDEN);
if (cch->mode == USBJOYS_CH_BUTTON) {
if (isUSBBtnNumCollision(channel)) {
collisionText->setText(STR_USBJOYSTICK_BTN_COLLISION);
lv_obj_clear_flag(collisionText->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else if (cch->mode == USBJOYS_CH_AXIS) {
if (isUSBAxisCollision(channel)) {
collisionText->setText(STR_USBJOYSTICK_AXIS_COLLISION);
lv_obj_clear_flag(collisionText->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
} else if (cch->mode == USBJOYS_CH_AXIS) {
if (isUSBAxisCollision(channel)) {
collisionText->setText(STR_USBJOYSTICK_AXIS_COLLISION);
lv_obj_clear_flag(collisionText->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
else if (cch->mode == USBJOYS_CH_SIM) {
if (isUSBSimCollision(channel)) {
collisionText->setText(STR_USBJOYSTICK_AXIS_COLLISION);
lv_obj_clear_flag(collisionText->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
} else if (cch->mode == USBJOYS_CH_SIM) {
if (isUSBSimCollision(channel)) {
collisionText->setText(STR_USBJOYSTICK_AXIS_COLLISION);
lv_obj_clear_flag(collisionText->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
}
_BtnNumSel->updateState();
}
void buildHeader(Window *window)
{
header.setTitle(STR_USBJOYSTICK_LABEL);
header.setTitle2(getSourceString(MIXSRC_FIRST_CH + channel));
_BtnNumSel->updateState();
}
statusBar = new USBChannelEditStatusBar(
window,
{window->getRect().w - USBCH_EDIT_STATUS_BAR_WIDTH - USBCH_EDIT_RIGHT_MARGIN,
0, USBCH_EDIT_STATUS_BAR_WIDTH, MENU_HEADER_HEIGHT},
channel);
}
void buildHeader(Window* window)
{
header.setTitle(STR_USBJOYSTICK_LABEL);
header.setTitle2(getSourceString(MIXSRC_FIRST_CH + channel));
void buildBody(FormWindow* form)
{
FlexGridLayout grid(ch_col_dsc, row_dsc, 2);
form->setFlexLayout();
statusBar = new USBChannelEditStatusBar(
window,
{window->getRect().w - USBCH_EDIT_STATUS_BAR_WIDTH -
USBCH_EDIT_RIGHT_MARGIN,
0, USBCH_EDIT_STATUS_BAR_WIDTH, MENU_HEADER_HEIGHT},
channel);
}
USBJoystickChData * cch = usbJChAddress(channel);
void buildBody(FormWindow* form)
{
FlexGridLayout grid(ch_col_dsc, row_dsc, 2);
form->setFlexLayout();
auto line = form->newLine(&grid);
USBJoystickChData* cch = usbJChAddress(channel);
new StaticText(line, rect_t{}, STR_USBJOYSTICK_CH_MODE, 0, COLOR_THEME_PRIMARY1);
new Choice(line, rect_t{}, STR_VUSBJOYSTICK_CH_MODE, 0, USBJOYS_CH_LAST,
GET_DEFAULT(cch->mode), SET_VALUE_WUPDATE(cch->mode));
auto line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_USBJOYSTICK_CH_MODE, 0,
COLOR_THEME_PRIMARY1);
new Choice(line, rect_t{}, STR_VUSBJOYSTICK_CH_MODE, 0, USBJOYS_CH_LAST,
GET_DEFAULT(cch->mode), SET_VALUE_WUPDATE(cch->mode));
#if LCD_H > LCD_W
line = form->newLine(&grid);
line = form->newLine(&grid);
#endif
new StaticText(line, rect_t{}, STR_USBJOYSTICK_CH_INVERSION, 0, COLOR_THEME_PRIMARY1);
new ToggleSwitch(line, rect_t{}, GET_SET_DEFAULT(cch->inversion));
new StaticText(line, rect_t{}, STR_USBJOYSTICK_CH_INVERSION, 0,
COLOR_THEME_PRIMARY1);
new ToggleSwitch(line, rect_t{}, GET_SET_DEFAULT(cch->inversion));
line = form->newLine(&grid);
m_btnModeFrame = new FormWindow(line, rect_t{});
m_btnModeFrame->setFlexLayout();
line = form->newLine(&grid);
m_btnModeFrame = new FormWindow(line, rect_t{});
m_btnModeFrame->setFlexLayout();
line = m_btnModeFrame->newLine(&grid);
new StaticText(line, rect_t{}, STR_USBJOYSTICK_CH_BTNMODE, 0, COLOR_THEME_PRIMARY1);
new Choice(line, rect_t{}, STR_VUSBJOYSTICK_CH_BTNMODE, 0, USBJOYS_BTN_MODE_LAST,
GET_DEFAULT(cch->param),
[=](int32_t newValue)
{
cch->param = newValue;
if(cch->param == USBJOYS_BTN_MODE_SW_EMU) m_btnPosChoice->setValue(0);
else if(cch->param == USBJOYS_BTN_MODE_DELTA) m_btnPosChoice->setValue(1);
SET_DIRTY();
this->update();
});
line = m_btnModeFrame->newLine(&grid);
new StaticText(line, rect_t{}, STR_USBJOYSTICK_CH_BTNMODE, 0,
COLOR_THEME_PRIMARY1);
new Choice(line, rect_t{}, STR_VUSBJOYSTICK_CH_BTNMODE, 0,
USBJOYS_BTN_MODE_LAST, GET_DEFAULT(cch->param),
[=](int32_t newValue) {
cch->param = newValue;
if (cch->param == USBJOYS_BTN_MODE_SW_EMU)
m_btnPosChoice->setValue(0);
else if (cch->param == USBJOYS_BTN_MODE_DELTA)
m_btnPosChoice->setValue(1);
SET_DIRTY();
this->update();
});
#if LCD_H > LCD_W
line = m_btnModeFrame->newLine(&grid);
line = m_btnModeFrame->newLine(&grid);
#endif
new StaticText(line, rect_t{}, STR_USBJOYSTICK_CH_SWPOS, 0, COLOR_THEME_PRIMARY1);
m_btnPosChoice = new Choice(line, rect_t{}, STR_VUSBJOYSTICK_CH_SWPOS, 0, 7,
GET_DEFAULT(cch->switch_npos), SET_VALUE_WUPDATE(cch->switch_npos));
new StaticText(line, rect_t{}, STR_USBJOYSTICK_CH_SWPOS, 0,
COLOR_THEME_PRIMARY1);
m_btnPosChoice = new Choice(line, rect_t{}, STR_VUSBJOYSTICK_CH_SWPOS, 0, 7,
GET_DEFAULT(cch->switch_npos),
SET_VALUE_WUPDATE(cch->switch_npos));
line = m_btnModeFrame->newLine(&grid);
new StaticText(line, rect_t{}, STR_USBJOYSTICK_CH_BTNNUM, 0, COLOR_THEME_PRIMARY1);
line = m_btnModeFrame->newLine(&grid);
new StaticText(line, rect_t{}, STR_USBJOYSTICK_CH_BTNNUM, 0,
COLOR_THEME_PRIMARY1);
#if LCD_H > LCD_W
line = m_btnModeFrame->newLine(&grid);
line = m_btnModeFrame->newLine(&grid);
#endif
_BtnNumSel = new USBChannelButtonSel(line, rect_t{},
channel, SET_VALUE_WUPDATE(cch->btn_num));
_BtnNumSel = new USBChannelButtonSel(line, rect_t{}, channel,
SET_VALUE_WUPDATE(cch->btn_num));
m_axisModeLine = form->newLine(&grid);
new StaticText(m_axisModeLine, rect_t{}, STR_USBJOYSTICK_CH_AXIS, 0, COLOR_THEME_PRIMARY1);
new Choice(m_axisModeLine, rect_t{}, STR_VUSBJOYSTICK_CH_AXIS, 0, USBJOYS_AXIS_LAST,
GET_DEFAULT(cch->param), SET_VALUE_WUPDATE(cch->param));
m_axisModeLine = form->newLine(&grid);
new StaticText(m_axisModeLine, rect_t{}, STR_USBJOYSTICK_CH_AXIS, 0,
COLOR_THEME_PRIMARY1);
new Choice(m_axisModeLine, rect_t{}, STR_VUSBJOYSTICK_CH_AXIS, 0,
USBJOYS_AXIS_LAST, GET_DEFAULT(cch->param),
SET_VALUE_WUPDATE(cch->param));
m_simModeLine = form->newLine(&grid);
new StaticText(m_simModeLine, rect_t{}, STR_USBJOYSTICK_CH_SIM, 0, COLOR_THEME_PRIMARY1);
new Choice(m_simModeLine, rect_t{}, STR_VUSBJOYSTICK_CH_SIM, 0, USBJOYS_SIM_LAST,
GET_DEFAULT(cch->param), SET_VALUE_WUPDATE(cch->param));
m_simModeLine = form->newLine(&grid);
new StaticText(m_simModeLine, rect_t{}, STR_USBJOYSTICK_CH_SIM, 0,
COLOR_THEME_PRIMARY1);
new Choice(m_simModeLine, rect_t{}, STR_VUSBJOYSTICK_CH_SIM, 0,
USBJOYS_SIM_LAST, GET_DEFAULT(cch->param),
SET_VALUE_WUPDATE(cch->param));
line = form->newLine(&grid);
line->padTop(0);
line->padBottom(0);
collisionText = new StaticText(line, rect_t{}, "", OPAQUE, FONT(BOLD) | COLOR_THEME_PRIMARY2 | CENTERED);
collisionText->setBackgroundColor(COLOR_THEME_WARNING);
lv_obj_set_grid_cell(collisionText->getLvObj(), LV_GRID_ALIGN_STRETCH, 0, USBCH_COLS, LV_GRID_ALIGN_CENTER, 0, 1);
line = form->newLine(&grid);
line->padTop(0);
line->padBottom(0);
collisionText =
new StaticText(line, rect_t{}, "", OPAQUE,
FONT(BOLD) | COLOR_THEME_PRIMARY2 | CENTERED);
collisionText->setBackgroundColor(COLOR_THEME_WARNING);
lv_obj_set_grid_cell(collisionText->getLvObj(), LV_GRID_ALIGN_STRETCH, 0,
USBCH_COLS, LV_GRID_ALIGN_CENTER, 0, 1);
update();
}
update();
}
};
class USBChannelLineButton : public Button
{
public:
USBChannelLineButton(Window* parent, uint8_t index) :
Button(parent, rect_t{}, nullptr, 0, 0, input_mix_line_create), index(index)
{
setHeight(USBCH_LINE_HEIGHT);
public:
USBChannelLineButton(Window* parent, uint8_t index) :
Button(parent, rect_t{}, nullptr, 0, 0, input_mix_line_create),
index(index)
{
setHeight(USBCH_LINE_HEIGHT);
#if LCD_W > LCD_H
padTop(4);
#endif
lv_obj_set_layout(lvobj, LV_LAYOUT_GRID);
lv_obj_set_grid_dsc_array(lvobj, b_col_dsc, b_row_dsc);
lv_obj_set_style_pad_row(lvobj, 0, 0);
lv_obj_set_style_pad_column(lvobj, 4, 0);
lv_obj_set_layout(lvobj, LV_LAYOUT_GRID);
lv_obj_set_grid_dsc_array(lvobj, b_col_dsc, b_row_dsc);
lv_obj_set_style_pad_row(lvobj, 0, 0);
lv_obj_set_style_pad_column(lvobj, 4, 0);
lv_obj_add_event_cb(lvobj, USBChannelLineButton::on_draw,
LV_EVENT_DRAW_MAIN_BEGIN, nullptr);
lv_obj_add_event_cb(lvobj, USBChannelLineButton::on_draw,
LV_EVENT_DRAW_MAIN_BEGIN, nullptr);
}
static void on_draw(lv_event_t* e)
{
lv_obj_t* target = lv_event_get_target(e);
auto line = (USBChannelLineButton*)lv_obj_get_user_data(target);
if (line) {
if (!line->init)
line->delayed_init(e);
else
line->refresh();
}
}
static void on_draw(lv_event_t* e)
{
lv_obj_t* target = lv_event_get_target(e);
auto line = (USBChannelLineButton*)lv_obj_get_user_data(target);
if (line) {
if (!line->init)
line->delayed_init(e);
else
line->refresh();
void delayed_init(lv_event_t* e)
{
m_chn = lv_label_create(lvobj);
lv_obj_set_grid_cell(m_chn, LV_GRID_ALIGN_START, 0, 1, LV_GRID_ALIGN_CENTER,
0, USBCH_CHN_ROWS);
m_inverse =
new StaticBitmap(this, rect_t{0, 0, 11, 16}, chanMonInvertedBitmap,
COLOR_THEME_SECONDARY1, false);
lv_obj_set_grid_cell(m_inverse->getLvObj(), LV_GRID_ALIGN_START, 1, 1,
LV_GRID_ALIGN_CENTER, 0, 1);
m_mode = lv_label_create(lvobj);
lv_obj_set_grid_cell(m_mode, LV_GRID_ALIGN_START, 2, 1,
LV_GRID_ALIGN_CENTER, 0, 1);
m_param = lv_label_create(lvobj);
lv_obj_set_grid_cell(m_param, LV_GRID_ALIGN_START, 3, 1,
LV_GRID_ALIGN_CENTER, 0, 1);
m_btn_mode = lv_label_create(lvobj);
lv_obj_set_grid_cell(m_btn_mode, LV_GRID_ALIGN_START, USBCH_BTN_MODE_COL, 1,
LV_GRID_ALIGN_CENTER, USBCH_BTN_MODE_ROW, 1);
m_btns = lv_label_create(lvobj);
lv_obj_set_grid_cell(m_btns, LV_GRID_ALIGN_START, USBCH_BTN_MODE_COL + 1, 1,
LV_GRID_ALIGN_CENTER, USBCH_BTN_MODE_ROW, 1);
lv_label_set_text(m_chn, getSourceString(MIXSRC_FIRST_CH + index));
lv_label_set_text(m_mode, "");
lv_label_set_text(m_param, "");
lv_label_set_text(m_btn_mode, "");
lv_label_set_text(m_btns, "");
init = true;
refresh();
lv_obj_update_layout(lvobj);
if (e) {
auto param = lv_event_get_param(e);
lv_event_send(lvobj, LV_EVENT_DRAW_MAIN, param);
}
}
void refresh()
{
if (!init) return;
USBJoystickChData* cch = usbJChAddress(index);
lv_label_set_text(m_mode, STR_VUSBJOYSTICK_CH_MODE[cch->mode]);
if (cch->inversion)
lv_obj_clear_flag(m_inverse->getLvObj(), LV_OBJ_FLAG_HIDDEN);
else
lv_obj_add_flag(m_inverse->getLvObj(), LV_OBJ_FLAG_HIDDEN);
LcdFlags warn = COLOR_THEME_SECONDARY1;
LcdFlags font = FONT(STD);
const char* param = "";
if (cch->mode == USBJOYS_CH_BUTTON) {
param = STR_VUSBJOYSTICK_CH_BTNMODE[cch->param];
} else if (cch->mode == USBJOYS_CH_AXIS) {
param = STR_VUSBJOYSTICK_CH_AXIS[cch->param];
if (isUSBAxisCollision(index)) {
warn = COLOR_THEME_WARNING;
font = FONT(BOLD);
}
} else if (cch->mode == USBJOYS_CH_SIM) {
param = STR_VUSBJOYSTICK_CH_SIM[cch->param];
if (isUSBSimCollision(index)) {
warn = COLOR_THEME_WARNING;
font = FONT(BOLD);
}
}
void delayed_init(lv_event_t* e)
{
m_chn = lv_label_create(lvobj);
lv_obj_set_grid_cell(m_chn, LV_GRID_ALIGN_START, 0, 1,
LV_GRID_ALIGN_CENTER, 0, USBCH_CHN_ROWS);
lv_label_set_text(m_param, param);
lv_obj_set_style_text_color(m_param, makeLvColor(warn), 0);
lv_obj_set_style_text_font(m_param, getFont(font), 0);
m_inverse = new StaticBitmap(this, rect_t{0, 0, 11, 16}, chanMonInvertedBitmap, COLOR_THEME_SECONDARY1, false);
lv_obj_set_grid_cell(m_inverse->getLvObj(), LV_GRID_ALIGN_START, 1, 1,
LV_GRID_ALIGN_CENTER, 0, 1);
if (cch->mode == USBJOYS_CH_BUTTON) {
lv_label_set_text(m_btn_mode,
STR_VUSBJOYSTICK_CH_SWPOS[cch->switch_npos]);
m_mode = lv_label_create(lvobj);
lv_obj_set_grid_cell(m_mode, LV_GRID_ALIGN_START, 2, 1,
LV_GRID_ALIGN_CENTER, 0, 1);
char str[20];
m_param = lv_label_create(lvobj);
lv_obj_set_grid_cell(m_param, LV_GRID_ALIGN_START, 3, 1,
LV_GRID_ALIGN_CENTER, 0, 1);
m_btn_mode = lv_label_create(lvobj);
lv_obj_set_grid_cell(m_btn_mode, LV_GRID_ALIGN_START, USBCH_BTN_MODE_COL, 1,
LV_GRID_ALIGN_CENTER, USBCH_BTN_MODE_ROW, 1);
m_btns = lv_label_create(lvobj);
lv_obj_set_grid_cell(m_btns, LV_GRID_ALIGN_START, USBCH_BTN_MODE_COL+1, 1,
LV_GRID_ALIGN_CENTER, USBCH_BTN_MODE_ROW, 1);
lv_label_set_text(m_chn, getSourceString(MIXSRC_FIRST_CH + index));
lv_label_set_text(m_mode, "");
lv_label_set_text(m_param, "");
uint8_t last = cch->lastBtnNum();
if (last > cch->btn_num)
snprintf(str, 20, "%u..%u", cch->btn_num, last);
else
snprintf(str, 20, "%u", cch->btn_num);
lv_label_set_text(m_btns, str);
if (isUSBBtnNumCollision(index)) {
warn = COLOR_THEME_WARNING;
font = FONT(BOLD);
}
lv_obj_set_style_text_color(m_btns, makeLvColor(warn), 0);
lv_obj_set_style_text_font(m_btns, getFont(font), 0);
} else {
lv_label_set_text(m_btn_mode, "");
lv_label_set_text(m_btns, "");
init = true;
refresh();
lv_obj_update_layout(lvobj);
if (e) {
auto param = lv_event_get_param(e);
lv_event_send(lvobj, LV_EVENT_DRAW_MAIN, param);
}
}
}
void refresh()
{
if (!init) return;
protected:
bool init = false;
uint8_t index;
USBJoystickChData * cch = usbJChAddress(index);
lv_label_set_text(m_mode, STR_VUSBJOYSTICK_CH_MODE[cch->mode]);
if (cch->inversion)
lv_obj_clear_flag(m_inverse->getLvObj(), LV_OBJ_FLAG_HIDDEN);
else
lv_obj_add_flag(m_inverse->getLvObj(), LV_OBJ_FLAG_HIDDEN);
LcdFlags warn = COLOR_THEME_SECONDARY1;
LcdFlags font = FONT(STD);
const char* param = "";
if (cch->mode == USBJOYS_CH_BUTTON) {
param = STR_VUSBJOYSTICK_CH_BTNMODE[cch->param];
}
else if (cch->mode == USBJOYS_CH_AXIS) {
param = STR_VUSBJOYSTICK_CH_AXIS[cch->param];
if (isUSBAxisCollision(index)) {
warn = COLOR_THEME_WARNING;
font = FONT(BOLD);
}
}
else if (cch->mode == USBJOYS_CH_SIM) {
param = STR_VUSBJOYSTICK_CH_SIM[cch->param];
if (isUSBSimCollision(index)) {
warn = COLOR_THEME_WARNING;
font = FONT(BOLD);
}
}
lv_label_set_text(m_param, param);
lv_obj_set_style_text_color(m_param, makeLvColor(warn), 0);
lv_obj_set_style_text_font(m_param, getFont(font), 0);
if (cch->mode == USBJOYS_CH_BUTTON) {
lv_label_set_text(m_btn_mode, STR_VUSBJOYSTICK_CH_SWPOS[cch->switch_npos]);
char str[20];
uint8_t last = cch->lastBtnNum();
if (last > cch->btn_num)
snprintf(str, 20, "%u..%u", cch->btn_num, last);
else
snprintf(str, 20, "%u", cch->btn_num);
lv_label_set_text(m_btns, str);
if (isUSBBtnNumCollision(index)) {
warn = COLOR_THEME_WARNING;
font = FONT(BOLD);
}
lv_obj_set_style_text_color(m_btns, makeLvColor(warn), 0);
lv_obj_set_style_text_font(m_btns, getFont(font), 0);
} else {
lv_label_set_text(m_btn_mode, "");
lv_label_set_text(m_btns, "");
}
}
protected:
bool init = false;
uint8_t index;
lv_obj_t* m_chn;
lv_obj_t* m_mode;
lv_obj_t* m_param;
lv_obj_t* m_btn_mode;
lv_obj_t* m_btns;
StaticBitmap* m_inverse;
lv_obj_t* m_chn;
lv_obj_t* m_mode;
lv_obj_t* m_param;
lv_obj_t* m_btn_mode;
lv_obj_t* m_btns;
StaticBitmap* m_inverse;
};
ModelUSBJoystickPage::ModelUSBJoystickPage() :
Page(ICON_MODEL_USB)
ModelUSBJoystickPage::ModelUSBJoystickPage() : Page(ICON_MODEL_USB)
{
header.setTitle(STR_MENU_MODEL_SETUP);
header.setTitle2(STR_USBJOYSTICK_LABEL);
@@ -521,50 +550,57 @@ ModelUSBJoystickPage::ModelUSBJoystickPage() :
// Extended mode
auto line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_USBJOYSTICK_EXTMODE, 0, COLOR_THEME_PRIMARY1);
new StaticText(line, rect_t{}, STR_USBJOYSTICK_EXTMODE, 0,
COLOR_THEME_PRIMARY1);
new Choice(line, rect_t{}, STR_VUSBJOYSTICK_EXTMODE, 0, 1,
GET_DEFAULT(g_model.usbJoystickExtMode), SET_VALUE_WUPDATE(g_model.usbJoystickExtMode));
GET_DEFAULT(g_model.usbJoystickExtMode),
SET_VALUE_WUPDATE(g_model.usbJoystickExtMode));
#if LCD_H > LCD_W
line = form->newLine(&grid);
#endif
_IfModeLabel = new StaticText(line, rect_t{}, STR_USBJOYSTICK_IF_MODE, 0, COLOR_THEME_PRIMARY1);
_IfMode = new Choice(line, rect_t{}, STR_VUSBJOYSTICK_IF_MODE, 0, USBJOYS_LAST,
GET_DEFAULT(g_model.usbJoystickIfMode), SET_VALUE_WUPDATE(g_model.usbJoystickIfMode));
_IfModeLabel = new StaticText(line, rect_t{}, STR_USBJOYSTICK_IF_MODE, 0,
COLOR_THEME_PRIMARY1);
_IfMode = new Choice(line, rect_t{}, STR_VUSBJOYSTICK_IF_MODE, 0,
USBJOYS_LAST, GET_DEFAULT(g_model.usbJoystickIfMode),
SET_VALUE_WUPDATE(g_model.usbJoystickIfMode));
line = form->newLine(&grid);
_CircCoutoutLabel = new StaticText(line, rect_t{}, STR_USBJOYSTICK_CIRC_COUTOUT, 0, COLOR_THEME_PRIMARY1);
_CircCoutout = new Choice(line, rect_t{}, STR_VUSBJOYSTICK_CIRC_COUTOUT, 0, USBJOYS_LAST,
GET_DEFAULT(g_model.usbJoystickCircularCut), SET_VALUE_WUPDATE(g_model.usbJoystickCircularCut));
_CircCoutoutLabel = new StaticText(
line, rect_t{}, STR_USBJOYSTICK_CIRC_COUTOUT, 0, COLOR_THEME_PRIMARY1);
_CircCoutout =
new Choice(line, rect_t{}, STR_VUSBJOYSTICK_CIRC_COUTOUT, 0, USBJOYS_LAST,
GET_DEFAULT(g_model.usbJoystickCircularCut),
SET_VALUE_WUPDATE(g_model.usbJoystickCircularCut));
#if LCD_H > LCD_W
line = form->newLine(&grid);
#endif
_ApplyBtn = new TextButton(line, rect_t{}, STR_USBJOYSTICK_APPLY_CHANGES,
[=]() { onUSBJoystickModelChanged(); this->update(); return 0; });
_ApplyBtn =
new TextButton(line, rect_t{}, STR_USBJOYSTICK_APPLY_CHANGES, [=]() {
onUSBJoystickModelChanged();
this->update();
return 0;
});
auto btngrp = new FormWindow(form, rect_t{});
_ChannelsGroup = btngrp;
btngrp->setFlexLayout();
btngrp->padRow(lv_dpx(4));
for (uint8_t ch = 0; ch < USBJ_MAX_JOYSTICK_CHANNELS; ch++) {
// Channel settings
auto btn = new USBChannelLineButton(btngrp, ch);
USBJoystickChData * cch = usbJChAddress(ch);
USBJoystickChData* cch = usbJChAddress(ch);
btn->setPressHandler([=]() -> uint8_t {
if (cch->mode == USBJOYS_CH_NONE) {
editChannel(ch, btn);
}
else {
Menu *menu = new Menu(parent);
menu->addLine(STR_EDIT, [=]() {
editChannel(ch, btn);
});
} else {
Menu* menu = new Menu(parent);
menu->addLine(STR_EDIT, [=]() { editChannel(ch, btn); });
menu->addLine(STR_CLEAR, [=]() {
memset(cch, 0, sizeof(USBJoystickChData));
SET_DIRTY();
@@ -581,22 +617,22 @@ ModelUSBJoystickPage::ModelUSBJoystickPage() :
void ModelUSBJoystickPage::update()
{
const uint8_t usbj_ctrls = 6;
Window* ctrls[usbj_ctrls] = { _IfModeLabel, _IfMode, _CircCoutoutLabel, _CircCoutout, _ApplyBtn, _ChannelsGroup };
Window* ctrls[usbj_ctrls] = {_IfModeLabel, _IfMode, _CircCoutoutLabel,
_CircCoutout, _ApplyBtn, _ChannelsGroup};
for(uint8_t i = 0; i < usbj_ctrls; i++) {
if(usbJoystickExtMode()) {
for (uint8_t i = 0; i < usbj_ctrls; i++) {
if (usbJoystickExtMode()) {
lv_obj_clear_flag(ctrls[i]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
_ApplyBtn->enable(usbJoystickSettingsChanged());
}
else {
} else {
lv_obj_add_flag(ctrls[i]->getLvObj(), LV_OBJ_FLAG_HIDDEN);
}
}
}
void ModelUSBJoystickPage::editChannel(uint8_t channel, USBChannelLineButton* btn)
void ModelUSBJoystickPage::editChannel(uint8_t channel,
USBChannelLineButton* btn)
{
auto chedit = new USBChannelEditWindow(channel);
chedit->setCloseHandler(
[=]() { this->update(); });
chedit->setCloseHandler([=]() { this->update(); });
}
+77 -49
View File
@@ -20,14 +20,14 @@
*/
#include "preflight_checks.h"
#include "button_matrix.h"
#include "opentx.h"
#include "button_matrix.h"
#include "hal/adc_driver.h"
#include "hal/switch_driver.h"
#include "opentx.h"
#include "strhelpers.h"
#define SET_DIRTY() storageDirty(EE_MODEL)
#define SET_DIRTY() storageDirty(EE_MODEL)
static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
LV_GRID_TEMPLATE_LAST};
@@ -49,7 +49,9 @@ static void cb_changed(lv_event_t* e)
static void make_conditional(Window* w, ToggleSwitch* cb)
{
lv_obj_t* w_obj = w->getLvObj();
if (!cb->getValue()) { lv_obj_add_flag(w_obj, LV_OBJ_FLAG_HIDDEN); }
if (!cb->getValue()) {
lv_obj_add_flag(w_obj, LV_OBJ_FLAG_HIDDEN);
}
lv_obj_t* cb_obj = cb->getLvObj();
lv_obj_add_event_cb(cb_obj, cb_changed, LV_EVENT_VALUE_CHANGED, w_obj);
@@ -71,10 +73,13 @@ static void choice_changed(lv_event_t* e)
static void make_conditional(Window* w, Choice* choice)
{
lv_obj_t* w_obj = w->getLvObj();
if (choice->getIntValue() == 0) { lv_obj_add_flag(w_obj, LV_OBJ_FLAG_HIDDEN); }
if (choice->getIntValue() == 0) {
lv_obj_add_flag(w_obj, LV_OBJ_FLAG_HIDDEN);
}
lv_obj_t* choice_obj = choice->getLvObj();
lv_obj_add_event_cb(choice_obj, choice_changed, LV_EVENT_VALUE_CHANGED, w_obj);
lv_obj_add_event_cb(choice_obj, choice_changed, LV_EVENT_VALUE_CHANGED,
w_obj);
}
struct SwitchWarnMatrix : public ButtonMatrix {
@@ -82,7 +87,8 @@ struct SwitchWarnMatrix : public ButtonMatrix {
void onPress(uint8_t btn_id);
bool isActive(uint8_t btn_id);
void setTextAndState(uint8_t btn_id);
private:
private:
uint8_t sw_idx[MAX_SWITCHES];
};
@@ -91,7 +97,8 @@ struct PotWarnMatrix : public ButtonMatrix {
void onPress(uint8_t btn_id);
bool isActive(uint8_t btn_id);
void setTextAndState(uint8_t btn_id);
private:
private:
uint8_t pot_idx[MAX_POTS];
};
@@ -100,7 +107,8 @@ struct CenterBeepsMatrix : public ButtonMatrix {
void onPress(uint8_t btn_id);
bool isActive(uint8_t btn_id);
void setTextAndState(uint8_t btn_id);
private:
private:
uint8_t max_analogs;
uint8_t ana_idx[MAX_ANALOG_INPUTS];
};
@@ -118,32 +126,38 @@ PreflightChecks::PreflightChecks() : Page(ICON_MODEL_SETUP)
// Display checklist
auto line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_CHECKLIST, 0, COLOR_THEME_PRIMARY1);
auto chkList = new ToggleSwitch(line, rect_t{}, GET_SET_DEFAULT(g_model.displayChecklist));
auto chkList = new ToggleSwitch(line, rect_t{},
GET_SET_DEFAULT(g_model.displayChecklist));
// Interactive checklist
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_CHECKLIST_INTERACTIVE, 0, COLOR_THEME_PRIMARY1);
auto interactiveChkList = new ToggleSwitch(line, rect_t{}, GET_SET_DEFAULT(g_model.checklistInteractive));
if(!chkList->getValue())
interactiveChkList->disable();
new StaticText(line, rect_t{}, STR_CHECKLIST_INTERACTIVE, 0,
COLOR_THEME_PRIMARY1);
auto interactiveChkList = new ToggleSwitch(
line, rect_t{}, GET_SET_DEFAULT(g_model.checklistInteractive));
if (!chkList->getValue()) interactiveChkList->disable();
chkList->setSetValueHandler([=](int32_t newValue) {
g_model.displayChecklist = newValue; SET_DIRTY();
(g_model.displayChecklist)?interactiveChkList->enable():interactiveChkList->disable();
g_model.displayChecklist = newValue;
SET_DIRTY();
(g_model.displayChecklist) ? interactiveChkList->enable()
: interactiveChkList->disable();
});
// Throttle warning
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_THROTTLE_WARNING, 0, COLOR_THEME_PRIMARY1);
auto tw = new ToggleSwitch(line, rect_t{}, GET_SET_INVERTED(g_model.disableThrottleWarning));
auto tw = new ToggleSwitch(line, rect_t{},
GET_SET_INVERTED(g_model.disableThrottleWarning));
// Custom Throttle warning (conditional on previous field)
line = form->newLine(&grid);
make_conditional(line, tw);
new StaticText(line, rect_t{}, STR_CUSTOM_THROTTLE_WARNING, 0, COLOR_THEME_PRIMARY1);
new StaticText(line, rect_t{}, STR_CUSTOM_THROTTLE_WARNING, 0,
COLOR_THEME_PRIMARY1);
auto box = new FormWindow::Line(line, window_create(line->getLvObj()));
lv_obj_set_layout(box->getLvObj(), LV_LAYOUT_FLEX);
box->setWidth(LCD_W /2 - 15);
box->setWidth(LCD_W / 2 - 15);
auto cst_tw = new ToggleSwitch(
box, rect_t{}, GET_SET_DEFAULT(g_model.enableCustomThrottleWarning));
@@ -164,17 +178,26 @@ PreflightChecks::PreflightChecks() : Page(ICON_MODEL_SETUP)
// Pots and sliders warning
if (adcGetMaxInputs(ADC_INPUT_FLEX) > 0) {
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_POTWARNINGSTATE, 0, COLOR_THEME_PRIMARY1);
auto pots_wm = new Choice(line, rect_t{}, STR_PREFLIGHT_POTSLIDER_CHECK, 0, 2,
GET_SET_DEFAULT(g_model.potsWarnMode));
uint8_t pot_cnt = 0;
for (uint8_t i = 0; i < MAX_POTS; i++) {
if (IS_POT_AVAILABLE(i)) {
pot_cnt++;
}
}
if (pot_cnt > 0) {
line = form->newLine(&grid);
new StaticText(line, rect_t{}, STR_POTWARNINGSTATE, 0,
COLOR_THEME_PRIMARY1);
auto pots_wm = new Choice(line, rect_t{}, STR_PREFLIGHT_POTSLIDER_CHECK,
0, 2, GET_SET_DEFAULT(g_model.potsWarnMode));
// Pot warnings
line = form->newLine(&grid);
line->padTop(0);
line->padLeft(4);
auto pwm = new PotWarnMatrix(line, rect_t{});
make_conditional(pwm, pots_wm);
// Pot warnings
line = form->newLine(&grid);
line->padTop(0);
line->padLeft(4);
auto pwm = new PotWarnMatrix(line, rect_t{});
make_conditional(pwm, pots_wm);
}
}
// Center beeps
@@ -195,10 +218,11 @@ static std::string switchWarninglabel(swsrc_t index)
#if LCD_W > LCD_H
#define SW_BTNS 8
#define SW_BTN_W 56
#else
#define SW_BTNS 4
#define SW_BTN_W 72
#endif
#define SW_BTN_W ((LCD_W-24)/SW_BTNS)
SwitchWarnMatrix::SwitchWarnMatrix(Window* parent, const rect_t& r) :
ButtonMatrix(parent, r)
@@ -212,8 +236,7 @@ SwitchWarnMatrix::SwitchWarnMatrix(Window* parent, const rect_t& r) :
}
}
initBtnMap(SW_BTNS, btn_cnt);
update();
initBtnMap(min((int)btn_cnt, SW_BTNS), btn_cnt);
uint8_t btn_id = 0;
for (uint8_t i = 0; i < MAX_SWITCHES; i++) {
@@ -223,10 +246,12 @@ SwitchWarnMatrix::SwitchWarnMatrix(Window* parent, const rect_t& r) :
}
}
lv_obj_set_width(lvobj, min((int)btn_cnt, SW_BTNS) * SW_BTN_W);
update();
lv_obj_set_width(lvobj, min((int)btn_cnt, SW_BTNS) * SW_BTN_W + 4);
uint8_t rows = ((btn_cnt - 1) / SW_BTNS) + 1;
lv_obj_set_height(lvobj, (rows * LV_DPI_DEF) / 3);
lv_obj_set_height(lvobj, (rows * 36) + 4);
lv_obj_set_style_pad_all(lvobj, 4, LV_PART_MAIN);
@@ -266,7 +291,7 @@ bool SwitchWarnMatrix::isActive(uint8_t btn_id)
}
PotWarnMatrix::PotWarnMatrix(Window* parent, const rect_t& r) :
ButtonMatrix(parent, r)
ButtonMatrix(parent, r)
{
// Setup button layout & texts
uint8_t btn_cnt = 0;
@@ -277,8 +302,7 @@ PotWarnMatrix::PotWarnMatrix(Window* parent, const rect_t& r) :
}
}
initBtnMap(SW_BTNS, btn_cnt);
update();
initBtnMap(min((int)btn_cnt, SW_BTNS), btn_cnt);
uint8_t btn_id = 0;
for (uint16_t i = 0; i < MAX_POTS; i++) {
@@ -288,10 +312,12 @@ PotWarnMatrix::PotWarnMatrix(Window* parent, const rect_t& r) :
}
}
lv_obj_set_width(lvobj, min((int)btn_cnt, SW_BTNS) * SW_BTN_W);
update();
lv_obj_set_width(lvobj, min((int)btn_cnt, SW_BTNS) * SW_BTN_W + 4);
uint8_t rows = ((btn_cnt - 1) / SW_BTNS) + 1;
lv_obj_set_height(lvobj, (rows * LV_DPI_DEF) / 3);
lv_obj_set_height(lvobj, (rows * 36) + 4);
lv_obj_set_style_pad_all(lvobj, 4, LV_PART_MAIN);
@@ -309,7 +335,7 @@ void PotWarnMatrix::onPress(uint8_t btn_id)
{
if (btn_id >= MAX_POTS) return;
auto pot = pot_idx[btn_id];
g_model.potsWarnEnabled ^= (1 << pot);
if ((g_model.potsWarnMode == POTS_WARN_MANUAL) &&
(g_model.potsWarnEnabled & (1 << pot))) {
@@ -326,7 +352,7 @@ bool PotWarnMatrix::isActive(uint8_t btn_id)
}
CenterBeepsMatrix::CenterBeepsMatrix(Window* parent, const rect_t& r) :
ButtonMatrix(parent, r)
ButtonMatrix(parent, r)
{
// Setup button layout & texts
uint8_t btn_cnt = 0;
@@ -344,8 +370,7 @@ CenterBeepsMatrix::CenterBeepsMatrix(Window* parent, const rect_t& r) :
}
}
initBtnMap(SW_BTNS, btn_cnt);
update();
initBtnMap(min((int)btn_cnt, SW_BTNS), btn_cnt);
uint8_t btn_id = 0;
for (uint8_t i = 0; i < max_analogs; i++) {
@@ -356,10 +381,12 @@ CenterBeepsMatrix::CenterBeepsMatrix(Window* parent, const rect_t& r) :
}
}
lv_obj_set_width(lvobj, min((int)btn_cnt, SW_BTNS) * SW_BTN_W);
update();
lv_obj_set_width(lvobj, min((int)btn_cnt, SW_BTNS) * SW_BTN_W + 4);
uint8_t rows = ((btn_cnt - 1) / SW_BTNS) + 1;
lv_obj_set_height(lvobj, (rows * LV_DPI_DEF) / 3);
lv_obj_set_height(lvobj, (rows * 36) + 4);
lv_obj_set_style_pad_all(lvobj, 4, LV_PART_MAIN);
@@ -373,7 +400,8 @@ void CenterBeepsMatrix::setTextAndState(uint8_t btn_id)
if (ana_idx[btn_id] < max_sticks)
setText(btn_id, getAnalogShortLabel(ana_idx[btn_id]));
else
setText(btn_id, getAnalogLabel(ADC_INPUT_FLEX, ana_idx[btn_id] - max_sticks));
setText(btn_id,
getAnalogLabel(ADC_INPUT_FLEX, ana_idx[btn_id] - max_sticks));
setChecked(btn_id);
}
@@ -383,7 +411,7 @@ void CenterBeepsMatrix::onPress(uint8_t btn_id)
uint8_t i = ana_idx[btn_id];
BFBIT_FLIP(g_model.beepANACenter, bfBit<BeepANACenter>(i));
setTextAndState(btn_id);
SET_DIRTY();
SET_DIRTY();
}
bool CenterBeepsMatrix::isActive(uint8_t btn_id)
@@ -595,7 +595,7 @@ void etx_slider_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj)
void etx_btnmatrix_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj)
{
lv_obj_add_style(obj, (lv_style_t*)&rounded, LV_PART_MAIN);
lv_obj_add_style(obj, (lv_style_t*)&bg_opacity_20, LV_PART_MAIN);
lv_obj_add_style(obj, (lv_style_t*)&bg_opacity_20, LV_PART_MAIN | LV_STATE_FOCUSED);
lv_obj_add_style(obj, &styles->bg_color[COLOR_THEME_FOCUS_INDEX],
LV_PART_MAIN | LV_STATE_FOCUSED);
+24 -23
View File
@@ -25,17 +25,18 @@ static const char _filler[] = "0";
static const char _newline[] = "\n";
static const char _map_end[] = "";
static void btn_matrix_event(lv_event_t *e)
static void btn_matrix_event(lv_event_t* e)
{
lv_event_code_t code = lv_event_get_code(e);
if (code == LV_EVENT_VALUE_CHANGED) {
lv_obj_t* obj = lv_event_get_target(e);
auto btn_id = *((uint8_t *)lv_event_get_param(e));
auto btn_id = *((uint8_t*)lv_event_get_param(e));
auto btnm = (ButtonMatrix*)lv_event_get_user_data(e);
bool edited = lv_obj_has_state(obj, LV_STATE_EDITED);
bool is_pointer = lv_indev_get_type(lv_indev_get_act()) == LV_INDEV_TYPE_POINTER;
bool is_pointer =
lv_indev_get_type(lv_indev_get_act()) == LV_INDEV_TYPE_POINTER;
if (edited || is_pointer) {
btnm->onPress(btn_id);
}
@@ -43,7 +44,7 @@ static void btn_matrix_event(lv_event_t *e)
}
ButtonMatrix::ButtonMatrix(Window* parent, const rect_t& r) :
FormField(parent, r, 0, 0, etx_btnmatrix_create)
FormField(parent, r, 0, 0, etx_btnmatrix_create)
{
lv_obj_add_flag(lvobj, LV_OBJ_FLAG_SCROLL_ON_FOCUS);
lv_obj_clear_flag(lvobj, LV_OBJ_FLAG_CLICK_FOCUSABLE);
@@ -51,10 +52,7 @@ ButtonMatrix::ButtonMatrix(Window* parent, const rect_t& r) :
lv_obj_add_event_cb(lvobj, btn_matrix_event, LV_EVENT_ALL, this);
}
ButtonMatrix::~ButtonMatrix()
{
deallocate();
}
ButtonMatrix::~ButtonMatrix() { deallocate(); }
void ButtonMatrix::deallocate()
{
@@ -77,47 +75,50 @@ void ButtonMatrix::initBtnMap(uint8_t cols, uint8_t btns)
deallocate();
uint8_t rows = ((btns - 1) / cols) + 1;
txt_cnt = btns + rows;
if (rows == 1) cols = btns;
txt_cnt = (cols + 1) * rows;
btn_cnt = btns;
lv_btnm_map = (char**)malloc(sizeof(char*) * txt_cnt);
txt_index = (uint8_t*)malloc(sizeof(uint8_t) * btns);
txt_index = (uint8_t*)malloc(sizeof(uint8_t) * cols * rows);
uint8_t col = 0;
uint8_t btn = 0;
uint8_t txt_i = 0;
while (btn < btns) {
while (btn < cols * rows) {
if (col == cols) {
lv_btnm_map[txt_i++] = (char*)_newline;
col = 0;
}
txt_index[btn] = txt_i;
lv_btnm_map[txt_i++] = (char*)_filler;
btn++;
col++;
}
lv_btnm_map[txt_i++] = (char*)_map_end;
lv_btnm_map[txt_i] = (char*)_map_end;
update();
}
void ButtonMatrix::setText(uint8_t btn_id, const char* txt)
{
if (btn_id >= btn_cnt) return;
uint8_t txt_i = txt_index[btn_id];
lv_btnm_map[txt_i] = strdup(txt);
if (btn_id < btn_cnt) lv_btnm_map[txt_index[btn_id]] = strdup(txt);
}
void ButtonMatrix::update()
{
lv_btnmatrix_set_map(lvobj, (const char**)lv_btnm_map);
lv_btnmatrix_ctrl_t ctrl = LV_BTNMATRIX_CTRL_CLICK_TRIG |
LV_BTNMATRIX_CTRL_NO_REPEAT;
lv_btnmatrix_set_btn_ctrl_all(lvobj, ctrl);
lv_btnmatrix_set_btn_ctrl_all(
lvobj, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT);
int btn = 0;
for (int i = 0; lv_btnm_map[i] != _map_end; i += 1) {
if (lv_btnm_map[i] == _filler)
lv_btnmatrix_set_btn_ctrl(lvobj, btn, LV_BTNMATRIX_CTRL_HIDDEN);
else
lv_btnmatrix_clear_btn_ctrl(lvobj, btn, LV_BTNMATRIX_CTRL_HIDDEN);
if (lv_btnm_map[i] != _newline) btn += 1;
}
}
void ButtonMatrix::onClicked()