Skip to content

Commit

Permalink
Convert the logical switch view in the channel monitor to LVGL flex.
Browse files Browse the repository at this point in the history
  • Loading branch information
Phil Mitchell committed Jan 25, 2023
1 parent 7e27ffd commit 48f7500
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 109 deletions.
7 changes: 0 additions & 7 deletions radio/src/gui/colorlcd/model_logical_switches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,13 +268,6 @@ void getsEdgeDelayParam(char* s, LogicalSwitchData * ls)
);
}

void putsEdgeDelayParam(BitmapBuffer * dc, coord_t x, coord_t y, LogicalSwitchData * ls, LcdFlags flags = 0)
{
char s[20];
getsEdgeDelayParam(s, ls);
dc->drawText(x, y, s, flags);
}

#if LCD_W > LCD_H // Landscape

#define TXT_ALIGN LV_GRID_ALIGN_CENTER
Expand Down
230 changes: 204 additions & 26 deletions radio/src/gui/colorlcd/view_logical_switches.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,180 @@

#include "opentx.h"
#include "view_logical_switches.h"
#include "gridlayout.h"

#include <utility>

#if LCD_W > LCD_H // Landscape
#define BTN_MATRIX_COL 8

#define BTN_MATRIX_COL 8
#define BTN_HEIGHT 20
#define FOOTER_HEIGHT 20
#define DURSW_ROW 0
#define DURSW_COL 3

// 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), LV_GRID_FR(1), LV_GRID_FR(1), 50, 50,
LV_GRID_TEMPLATE_LAST};

#else // Portrait
#define BTN_MATRIX_COL 4

#define BTN_MATRIX_COL 4
#define BTN_HEIGHT 21
#define FOOTER_HEIGHT 40
#define DURSW_ROW 1
#define DURSW_COL 2

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),
LV_GRID_TEMPLATE_LAST};

#endif

static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT, LV_GRID_CONTENT,
LV_GRID_TEMPLATE_LAST};

void getsEdgeDelayParam(char* s, LogicalSwitchData * ls);

class LogicalSwitchDisplayFooter : public Window
{
public:
explicit LogicalSwitchDisplayFooter(Window* parent, rect_t rect) :
Window(parent, rect, OPAQUE)
{
padAll(0);
padLeft(4);
padRight(4);
lv_obj_set_style_bg_color(lvobj, makeLvColor(COLOR_THEME_SECONDARY1), 0);

lv_obj_set_layout(lvobj, LV_LAYOUT_GRID);
lv_obj_set_grid_dsc_array(lvobj, f_col_dsc, row_dsc);
lv_obj_set_style_pad_row(lvobj, 0, 0);
lv_obj_set_style_pad_column(lvobj, 2, 0);

lsFunc = lv_label_create(lvobj);
lv_obj_set_style_text_align(lsFunc, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lsFunc, LV_GRID_ALIGN_STRETCH, 0, 1, LV_GRID_ALIGN_CENTER, 0, 1);
lv_obj_set_style_text_color(lsFunc, makeLvColor(COLOR_THEME_PRIMARY2), 0);

lsV1 = lv_label_create(lvobj);
lv_obj_set_style_text_align(lsV1, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lsV1, LV_GRID_ALIGN_STRETCH, 1, 1, LV_GRID_ALIGN_CENTER, 0, 1);
lv_obj_set_style_text_color(lsV1, makeLvColor(COLOR_THEME_PRIMARY2), 0);

lsV2 = lv_label_create(lvobj);
lv_obj_set_style_text_align(lsV2, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lsV2, LV_GRID_ALIGN_STRETCH, 2, 1, LV_GRID_ALIGN_CENTER, 0, 1);
lv_obj_set_style_text_color(lsV2, makeLvColor(COLOR_THEME_PRIMARY2), 0);

lsAnd = lv_label_create(lvobj);
lv_obj_set_style_text_align(lsAnd, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lsAnd, LV_GRID_ALIGN_STRETCH, 3, 1, LV_GRID_ALIGN_CENTER, 0, 1);
lv_obj_set_style_text_color(lsAnd, makeLvColor(COLOR_THEME_PRIMARY2), 0);

lsDuration = lv_label_create(lvobj);
lv_obj_set_style_text_align(lsDuration, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lsDuration, LV_GRID_ALIGN_STRETCH, DURSW_COL, 1, LV_GRID_ALIGN_CENTER, DURSW_ROW, 1);
lv_obj_set_style_text_color(lsDuration, makeLvColor(COLOR_THEME_PRIMARY2), 0);

lsDelay = lv_label_create(lvobj);
lv_obj_set_style_text_align(lsDelay, LV_TEXT_ALIGN_LEFT, 0);
lv_obj_set_grid_cell(lsDelay, LV_GRID_ALIGN_STRETCH, DURSW_COL+1, 1, LV_GRID_ALIGN_CENTER, DURSW_ROW, 1);
lv_obj_set_style_text_color(lsDelay, makeLvColor(COLOR_THEME_PRIMARY2), 0);

lv_obj_update_layout(parent->getLvObj());

refresh();
}

void refresh()
{
LogicalSwitchData* ls = lswAddress(lsIndex);
uint8_t lsFamily = lswFamily(ls->func);

char s[20];

lv_label_set_text(lsFunc, STR_VCSWFUNC[ls->func]);

// CSW params - V1
switch (lsFamily) {
case LS_FAMILY_BOOL:
case LS_FAMILY_STICKY:
case LS_FAMILY_EDGE:
lv_label_set_text(lsV1, getSwitchPositionName(ls->v1));
break;
case LS_FAMILY_TIMER:
lv_label_set_text(lsV1, formatNumberAsString(lswTimerValue(ls->v1), PREC1, 0, nullptr, "s").c_str());
break;
default:
lv_label_set_text(lsV1, getSourceString(ls->v1));
break;
}

// CSW params - V2
strcat(s, " ");
switch (lsFamily) {
case LS_FAMILY_BOOL:
case LS_FAMILY_STICKY:
lv_label_set_text(lsV2, getSwitchPositionName(ls->v2));
break;
case LS_FAMILY_EDGE:
getsEdgeDelayParam(s, ls);
lv_label_set_text(lsV2, s);
break;
case LS_FAMILY_TIMER:
lv_label_set_text(lsV2, formatNumberAsString(lswTimerValue(ls->v2), PREC1, 0, nullptr, "s").c_str());
break;
case LS_FAMILY_COMP:
lv_label_set_text(lsV2, getSourceString(ls->v2));
break;
default:
lv_label_set_text(lsV2, getSourceCustomValueString(ls->v1, (ls->v1 <= MIXSRC_LAST_CH ? calc100toRESX(ls->v2) : ls->v2), 0));
break;
}

// AND switch
lv_label_set_text(lsAnd, getSwitchPositionName(ls->andsw));

// CSW duration
if (ls->duration > 0) {
lv_label_set_text(lsDuration, formatNumberAsString(ls->duration, PREC1, 0, nullptr, "s").c_str());
} else {
lv_label_set_text(lsDuration, "");
}

// CSW delay
if (lsFamily != LS_FAMILY_EDGE && ls->delay > 0) {
lv_label_set_text(lsDelay, formatNumberAsString(ls->delay, PREC1, 0, nullptr, "s").c_str());
} else {
lv_label_set_text(lsDelay, "");
}
}

void setIndex(unsigned value)
{
lsIndex = value;
refresh();
}

protected:
unsigned lsIndex = 0;
lv_obj_t* lsFunc = nullptr;
lv_obj_t* lsV1 = nullptr;
lv_obj_t* lsV2 = nullptr;
lv_obj_t* lsAnd = nullptr;
lv_obj_t* lsDuration = nullptr;
lv_obj_t* lsDelay = nullptr;
};

class LogicalSwitchDisplayButton : public TextButton
{
public:
LogicalSwitchDisplayButton(FormGroup* parent, const rect_t& rect,
LogicalSwitchDisplayButton(Window* parent, const rect_t& rect,
std::string text, unsigned index) :
TextButton(parent, rect, std::move(text), nullptr, OPAQUE), index(index)
{
Expand Down Expand Up @@ -62,34 +222,52 @@ class LogicalSwitchDisplayButton : public TextButton

void LogicalSwitchesViewPage::build(FormWindow * window)
{
constexpr coord_t LSW_VIEW_FOOTER_HEIGHT = 20;
FormGridLayout grid;
grid.spacer(PAGE_PADDING);
grid.setLabelWidth(BTN_MATRIX_COL);
window->padAll(0);

auto form = new FormWindow(window, rect_t{});
form->setFlexLayout();
form->padAll(0);
form->padTop(3);

FlexGridLayout grid(col_dsc, row_dsc, 2);
FormWindow::Line* line;

// Footer
footer = new LogicalSwitchDisplayFooter(
window, {0, window->height() - LSW_VIEW_FOOTER_HEIGHT, window->width(),
LSW_VIEW_FOOTER_HEIGHT});
footer = new LogicalSwitchDisplayFooter(window, {0, window->height() - FOOTER_HEIGHT, window->width(), FOOTER_HEIGHT});

// LSW table
std::string lsString("LS64");
lcdColorTable[CUSTOM_COLOR_INDEX] = RGB(160, 160, 160);
std::string lsString("L64");
for (uint8_t i = 0; i < MAX_LOGICAL_SWITCHES; i++) {
if ((i % BTN_MATRIX_COL) == 0) {
line = form->newLine(&grid);
line->padAll(1);
line->padLeft(4);
line->padRight(4);
}

LogicalSwitchData* ls = lswAddress(i);
bool isActive = (ls->func != LS_FUNC_NONE);

strAppendSigned(&lsString[1], i + 1, 2);

auto button = new LogicalSwitchDisplayButton(
window, grid.getFieldSlot(BTN_MATRIX_COL, i % BTN_MATRIX_COL), lsString, i);

button->setFocusHandler([=](bool focus) {
if (focus) {
footer->setIndex(i);
footer->invalidate();
}
return 0;
});
if ((i + 1) % BTN_MATRIX_COL == 0) grid.nextLine();
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);

button->setFocusHandler([=](bool focus) {
if (focus) {
footer->setIndex(i);
footer->invalidate();
}
return 0;
});
} else {
auto lbl = lv_label_create(line->getLvObj());
lv_obj_set_height(lbl, BTN_HEIGHT);
lv_obj_set_style_text_color(lbl, makeLvColor(COLOR_THEME_DISABLED), 0);
lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_CENTER, 0);
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());
}
}
}
77 changes: 1 addition & 76 deletions radio/src/gui/colorlcd/view_logical_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,82 +25,7 @@
#include "tabsgroup.h"
#include "switches.h"

constexpr coord_t CSW_1ST_COLUMN = 50;
constexpr coord_t CSW_2ND_COLUMN = 120;
constexpr coord_t CSW_3RD_COLUMN = 200;
constexpr coord_t CSW_4TH_COLUMN = 280;
constexpr coord_t CSW_5TH_COLUMN = 340;
constexpr coord_t CSW_6TH_COLUMN = 390;

void putsEdgeDelayParam(BitmapBuffer* dc, coord_t x, coord_t y,
LogicalSwitchData* ls, LcdFlags flags);

class LogicalSwitchDisplayFooter : public Window
{
public:
explicit LogicalSwitchDisplayFooter(Window* parent, rect_t rect) :
Window(parent, rect, OPAQUE), rect(rect)
{
}

void setIndex(unsigned value) { index = value; }

void paint(BitmapBuffer* dc) override
{
dc->clear(COLOR_THEME_SECONDARY1);
LogicalSwitchData* cs = lswAddress(index);

LcdFlags textColor = COLOR_THEME_PRIMARY2;
dc->drawTextAtIndex(10, 1, STR_VCSWFUNC, cs->func, textColor);
// CSW params
unsigned int cstate = lswFamily(cs->func);

if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
drawSwitch(dc, CSW_2ND_COLUMN, 1, cs->v1, textColor);
drawSwitch(dc, CSW_3RD_COLUMN, 1, cs->v2, textColor);
} else if (cstate == LS_FAMILY_EDGE) {
drawSwitch(dc, CSW_2ND_COLUMN, 1, cs->v1, textColor);
putsEdgeDelayParam(dc, CSW_3RD_COLUMN, 1, cs, textColor);
} else if (cstate == LS_FAMILY_COMP) {
drawSource(dc, CSW_2ND_COLUMN, 1, cs->v1, textColor);
drawSource(dc, CSW_3RD_COLUMN, 1, cs->v2, textColor);
} else if (cstate == LS_FAMILY_TIMER) {
dc->drawNumber(CSW_2ND_COLUMN, 1, lswTimerValue(cs->v1),
LEFT | PREC1 | textColor);
dc->drawNumber(CSW_3RD_COLUMN, 1, lswTimerValue(cs->v2),
LEFT | PREC1 | textColor);
} else {
drawSource(dc, CSW_2ND_COLUMN, 1, cs->v1, textColor);
drawSourceCustomValue(
dc, CSW_3RD_COLUMN, 1, cs->v1,
cs->v1 <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2,
LEFT | textColor);
}

// CSW AND switch
drawSwitch(dc, CSW_4TH_COLUMN, 1, cs->andsw, textColor);

// CSW duration
if (cs->duration > 0)
dc->drawNumber(CSW_5TH_COLUMN, 1, cs->duration,
PREC1 | LEFT | textColor);
else
dc->drawTextAtIndex(CSW_5TH_COLUMN, 1, STR_MMMINV, 0, textColor);

// CSW delay
if (cstate == LS_FAMILY_EDGE) {
dc->drawText(CSW_6TH_COLUMN, 1, STR_NA, textColor);
} else if (cs->delay > 0) {
dc->drawNumber(CSW_6TH_COLUMN, 1, cs->delay, PREC1 | LEFT | textColor);
} else {
dc->drawTextAtIndex(CSW_6TH_COLUMN, 1, STR_MMMINV, 0, textColor);
}
}

protected:
rect_t rect;
unsigned index = 0;
};
class LogicalSwitchDisplayFooter;

class LogicalSwitchesViewPage : public PageTab
{
Expand Down

0 comments on commit 48f7500

Please sign in to comment.