Model setup: use single buttons instead of button matrix for sub-screens

This commit is contained in:
Raphael Coeffic
2022-06-11 15:38:08 +02:00
committed by Raphael Coeffic
parent e31a1cc1fc
commit b1cbbc4fc6
+176 -61
View File
@@ -84,12 +84,140 @@ struct ModelBitmapEdit : public FileChoice {
}
};
struct SubScreenButtonMatrix : public ButtonMatrix {
SubScreenButtonMatrix(Window* parent, const rect_t& rect);
struct TimerBtnMatrix : public ButtonMatrix {
TimerBtnMatrix(Window* parent, const rect_t& rect);
void onPress(uint8_t btn_id) override;
bool isActive(uint8_t btn_id) override;
};
class SubScreenButton : public Button
{
std::string text;
public:
SubScreenButton(Window* parent, const char* text,
std::function<void(void)> pressHandler);
protected:
virtual bool isActive() { return false; }
static void event_cb(lv_event_t* e);
};
SubScreenButton::SubScreenButton(Window* parent, const char* text,
std::function<void(void)> pressHandler) :
Button(parent, rect_t{}, [=]() -> uint8_t {
pressHandler();
return 0;
}, 0, 0, lv_btn_create),
text(text)
{
lv_obj_add_event_cb(lvobj, SubScreenButton::event_cb, LV_EVENT_ALL, nullptr);
}
// TODO: move code to TextButton with BEGIN/END in main and using events
// to grab lv_draw_label_dsc_t (see lv_btnmatrix.c)
//
void SubScreenButton::event_cb(lv_event_t* e)
{
auto obj = lv_event_get_target(e);
auto btn = (SubScreenButton*)lv_obj_get_user_data(obj);
if (!btn) return;
lv_event_code_t code = lv_event_get_code(e);
if (code == LV_EVENT_DRAW_PART_BEGIN) {
lv_obj_draw_part_dsc_t* dsc = lv_event_get_draw_part_dsc(e);
if (dsc->part != LV_PART_MAIN) return;
if (btn->isActive()) {
dsc->rect_dsc->bg_color = makeLvColor(COLOR_THEME_ACTIVE);
} else {
dsc->rect_dsc->bg_color = makeLvColor(COLOR_THEME_PRIMARY2);
}
} else if (code == LV_EVENT_DRAW_PART_END) {
if (btn->text.empty()) return;
lv_obj_draw_part_dsc_t* dsc = lv_event_get_draw_part_dsc(e);
if (dsc->part != LV_PART_MAIN) return;
lv_area_t txt_coords;
lv_obj_get_content_coords(obj, &txt_coords);
lv_draw_label_dsc_t label_draw_dsc;
lv_draw_label_dsc_init(&label_draw_dsc);
lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_draw_dsc);
label_draw_dsc.align = LV_TEXT_ALIGN_CENTER;
if (btn->isActive()) {
label_draw_dsc.color = makeLvColor(COLOR_THEME_PRIMARY2);
} else {
label_draw_dsc.color = makeLvColor(COLOR_THEME_SECONDARY1);
}
lv_area_t txt_clip;
bool is_common = _lv_area_intersect(&txt_clip, &txt_coords, dsc->draw_ctx->clip_area);
if (!is_common) return;
lv_draw_label(dsc->draw_ctx, &label_draw_dsc, &txt_coords, btn->text.c_str(), nullptr);
} else if (code == LV_EVENT_GET_SELF_SIZE) {
// from lv_label_t with some simplifications
lv_point_t size;
const lv_font_t* font = lv_obj_get_style_text_font(obj, LV_PART_MAIN);
lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN);
lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN);
lv_text_flag_t flag = LV_TEXT_FLAG_NONE;
lv_coord_t w = lv_obj_get_content_width(obj);
if (lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT && !obj->w_layout)
w = LV_COORD_MAX;
else
w = lv_obj_get_content_width(obj);
lv_txt_get_size(&size, btn->text.c_str(), font, letter_space, line_space, w, flag);
lv_point_t* self_size = (lv_point_t*)lv_event_get_param(e);
self_size->x = LV_MAX(self_size->x, size.x);
self_size->y = LV_MAX(self_size->y, size.y);
}
}
struct IntmoduleButton : public SubScreenButton {
IntmoduleButton(Window* parent) :
SubScreenButton(parent, STR_INTERNALRF,
[]() { new ModulePage(INTERNAL_MODULE); })
{
}
bool isActive() override
{
return g_model.moduleData[INTERNAL_MODULE].type > 0;
}
};
struct ExtmoduleButton : public SubScreenButton {
ExtmoduleButton(Window* parent) :
SubScreenButton(parent, STR_EXTERNALRF,
[]() { new ModulePage(EXTERNAL_MODULE); })
{
}
bool isActive() override
{
return g_model.moduleData[EXTERNAL_MODULE].type > 0;
}
};
struct TrainerModuleButton : public SubScreenButton {
TrainerModuleButton(Window* parent) :
SubScreenButton(parent, STR_TRAINER, []() { new TrainerPage(); })
{
}
bool isActive() override { return g_model.trainerData.mode > 0; }
};
static const lv_coord_t line_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1),
LV_GRID_TEMPLATE_LAST};
static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT,
@@ -98,6 +226,7 @@ static const lv_coord_t line_row_dsc[] = {LV_GRID_CONTENT,
void ModelSetupPage::build(FormWindow * window)
{
window->setFlexLayout();
FlexGridLayout grid(line_col_dsc, line_row_dsc, 2);
// Model name
@@ -128,82 +257,68 @@ void ModelSetupPage::build(FormWindow * window)
new Choice(line, rect_t{}, STR_ADCFILTERVALUES, 0, 2,
GET_SET_DEFAULT(g_model.jitterFilter));
// Sub-screens
new SubScreenButtonMatrix(window, rect_t{});
// Modules
auto form = new FormGroup(window, rect_t{});
form->setFlexLayout(LV_FLEX_FLOW_ROW_WRAP, lv_dpx(8));
lv_obj_set_style_pad_all(form->getLvObj(), lv_dpx(8), 0);
new IntmoduleButton(form);
new ExtmoduleButton(form);
new TrainerModuleButton(form);
// Timer buttons
form = new FormGroup(window, rect_t{});
form->setFlexLayout(LV_FLEX_FLOW_ROW_WRAP, lv_dpx(8));
lv_obj_set_style_pad_all(form->getLvObj(), lv_dpx(8), 0);
new SubScreenButton(form, TR_TIMER "1",
[]() { new TimerWindow(0); });
new SubScreenButton(form, TR_TIMER "2",
[]() { new TimerWindow(1); });
new SubScreenButton(form, TR_TIMER "3",
[]() { new TimerWindow(2); });
form = new FormGroup(window, rect_t{});
form->setFlexLayout(LV_FLEX_FLOW_ROW_WRAP, lv_dpx(8));
lv_obj_set_style_pad_all(form->getLvObj(), lv_dpx(8), 0);
new SubScreenButton(form, STR_PREFLIGHT,
[]() { new ModulePage(EXTERNAL_MODULE); });
new SubScreenButton(form, STR_TRIMS,
[]() { new ModulePage(EXTERNAL_MODULE); });
new SubScreenButton(form, STR_THROTTLE_LABEL,
[]() { new ModulePage(EXTERNAL_MODULE); });
}
#define MAX_SUBSCREEN_BTNS 9
SubScreenButtonMatrix::SubScreenButtonMatrix(Window* parent, const rect_t& r) :
TimerBtnMatrix::TimerBtnMatrix(Window* parent, const rect_t& r) :
ButtonMatrix(parent, r)
{
initBtnMap(3, MAX_SUBSCREEN_BTNS);
setText(0, STR_INTERNALRF);
setText(1, STR_EXTERNALRF);
setText(2, STR_TRAINER);
setText(3, STR_PREFLIGHT);
setText(4, STR_TRIMS);
setText(5, STR_THROTTLE_LABEL);
setText(6, TR_TIMER "1");
setText(7, TR_TIMER "2");
setText(8, TR_TIMER "3");
initBtnMap(3, MAX_TIMERS);
setText(0, TR_TIMER "1");
setText(1, TR_TIMER "2");
setText(2, TR_TIMER "3");
update();
lv_btnmatrix_set_btn_width(lvobj, 3, 2);
lv_obj_set_width(lvobj, lv_pct(100));
lv_obj_set_height(lvobj, (4 * LV_DPI_DEF) / 3);
lv_obj_set_height(lvobj, LV_DPI_DEF / 2);
lv_obj_set_style_bg_opa(lvobj, LV_OPA_0, LV_PART_MAIN);
lv_obj_set_style_pad_all(lvobj, LV_DPI_DEF / 10, LV_PART_MAIN);
lv_obj_set_style_bg_opa(lvobj, LV_OPA_0, 0);
lv_obj_set_style_pad_all(lvobj, lv_dpx(8), 0);
lv_obj_set_style_pad_row(lvobj, 8, LV_PART_MAIN);
lv_obj_set_style_pad_column(lvobj, 8, LV_PART_MAIN);
lv_obj_set_style_pad_row(lvobj, lv_dpx(8), 0);
lv_obj_set_style_pad_column(lvobj, lv_dpx(8), 0);
}
void SubScreenButtonMatrix::onPress(uint8_t btn_id)
void TimerBtnMatrix::onPress(uint8_t btn_id)
{
if (btn_id >= MAX_SUBSCREEN_BTNS) return;
Window* w = nullptr;
switch (btn_id) {
case 0:
w = new ModulePage(INTERNAL_MODULE);
break;
case 1:
w = new ModulePage(EXTERNAL_MODULE);
break;
case 2:
w = new TrainerPage();
break;
case 3:
w = new PreflightChecks();
break;
case 4:
w = new TrimsSetup();
break;
case 5:
w = new ThrottleParams();
break;
default:
w = new TimerWindow((uint8_t)(btn_id - 6));
break;
}
// if (w) w->setFocus();
if (btn_id >= MAX_TIMERS) return;
new TimerWindow((uint8_t)(btn_id));
}
bool SubScreenButtonMatrix::isActive(uint8_t btn_id)
bool TimerBtnMatrix::isActive(uint8_t btn_id)
{
if (btn_id == 0)
return g_model.moduleData[INTERNAL_MODULE].type > 0;
if (btn_id == 1)
return g_model.moduleData[EXTERNAL_MODULE].type > 0;
if (btn_id == 2)
return g_model.trainerData.mode > 0;
return false;
}